feat: 메인 UI 윈도우를 도입하고 애플리케이션 시작 로직을 초기화했습니다.

This commit is contained in:
9700X_PC 2026-01-18 12:18:34 +09:00
parent ef3d9212b5
commit 4dc2322fed
7 changed files with 76 additions and 31 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
venv/ venv/
build/ build/
dist/ dist/
__pycache__

View File

@ -2,6 +2,10 @@ import os
import numpy as np import numpy as np
import os import os
import numpy as np import numpy as np
import os
import numpy as np
import os
import numpy as np
import polars as pl import polars as pl
from typing import Optional from typing import Optional
@ -9,10 +13,9 @@ class FastLogParser:
CHUNK_SIZE = 84 CHUNK_SIZE = 84
@staticmethod @staticmethod
def parse_to_parquet(input_path: str, output_path: str = None) -> Optional[str]: def parse(input_path: str) -> Optional[pl.DataFrame]:
""" """
Numpy 벡터 연산을 사용하여 MMI 바이너리 로그를 초고속으로 파싱 Parquet 저장. Numpy 벡터 연산을 사용하여 MMI 바이너리 로그를 초고속으로 파싱 DataFrame 반환.
(VDI/VDO 포함 모든 필드 완벽 구현)
""" """
if not os.path.exists(input_path): if not os.path.exists(input_path):
return None return None
@ -241,6 +244,24 @@ class FastLogParser:
# [Optional] 여기서 역 이름 매핑이나 코드 변환을 수행할 수 있음 # [Optional] 여기서 역 이름 매핑이나 코드 변환을 수행할 수 있음
# (이전 대화의 Processor 로직을 여기에 통합해도 됨) # (이전 대화의 Processor 로직을 여기에 통합해도 됨)
return df
except Exception as e:
print(f"[FastParser] Error: {e}")
import traceback
traceback.print_exc()
return None
@staticmethod
def parse_to_parquet(input_path: str, output_path: str = None) -> Optional[str]:
"""
MMI 바이너리 로그를 파싱하여 Parquet로 저장 (Wrapper)
"""
df = FastLogParser.parse(input_path)
if df is None:
return None
try:
if output_path is None: if output_path is None:
output_path = input_path.replace(".dat", ".parquet") output_path = input_path.replace(".dat", ".parquet")

View File

@ -18,51 +18,74 @@ from app.core.settings import get_settings_manager
from app.ui.widgets.ai_floating_chat import AIFloatingButton, AIChatDialog, animate_open, animate_close from app.ui.widgets.ai_floating_chat import AIFloatingButton, AIChatDialog, animate_open, animate_close
from PySide6.QtCore import Qt, QRect, QTimer
class MainWindow(QMainWindow): class MainWindow(QMainWindow):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.setWindowTitle("SL200 AI Smart Analyzer") self.setWindowTitle("SL200 AI Smart Analyzer")
self.resize(1800, 1000) self.resize(1800, 1000)
self.setup_ui() # 1. 기본 UI 골격만 즉시 생성 (매우 빠름)
self.setup_ui_skeleton()
self.setup_menubar() self.setup_menubar()
self.setup_toolbar() self.setup_toolbar()
# 패널 데이터 로드 시 날짜 비교를 위한 시그널 연결 # 2. 무거운 컴포넌트(패널, AI)는 윈도우가 뜬 직후 지연 로딩
self.left_panel.data_loaded.connect(self.check_sync_availability) # 0ms: 이벤트 루프가 돌기 시작한 직후 실행 (윈도우 표시 후)
self.right_panel.data_loaded.connect(self.check_sync_availability) QTimer.singleShot(10, self._init_panels)
# AI 클라이언트 초기화 # 500ms: 패널 로딩 후 실행
self._init_ai_client() QTimer.singleShot(500, self._init_ai_client)
def setup_ui(self): def setup_ui_skeleton(self):
"""기본 UI 골격 생성 (빈 패널)"""
central = QWidget() central = QWidget()
self.setCentralWidget(central) self.setCentralWidget(central)
layout = QVBoxLayout(central) self.main_layout = QVBoxLayout(central)
# 좌우 분할 # 좌우 분할 (빈 상태로 생성)
splitter = QSplitter(Qt.Orientation.Horizontal) self.splitter = QSplitter(Qt.Orientation.Horizontal)
self.main_layout.addWidget(self.splitter)
# 왼쪽/오른쪽 패널 생성 (ID 부여)
self.left_panel = AnalysisPanel("left")
self.right_panel = AnalysisPanel("right")
splitter.addWidget(self.left_panel)
splitter.addWidget(self.right_panel)
splitter.setSizes([900, 900]) # 1:1 비율
layout.addWidget(splitter)
self.status_bar = QStatusBar() self.status_bar = QStatusBar()
self.setStatusBar(self.status_bar) self.setStatusBar(self.status_bar)
self.status_bar.showMessage("초기화 중...")
# 플로팅 AI 버튼 # 플로팅 AI 버튼 (미리 생성하되 기능은 나중에 연결)
self._ai_button = AIFloatingButton(central) self._ai_button = AIFloatingButton(central)
self._ai_button.clicked.connect(self._open_ai_chat)
self._ai_button.show() self._ai_button.show()
self._ai_chat: AIChatDialog | None = None self._ai_chat: AIChatDialog | None = None
self._ai_button.move_to_bottom_right() self._ai_button.move_to_bottom_right()
def _init_panels(self):
"""패널 지연 생성"""
try:
# 왼쪽/오른쪽 패널 생성 (ID 부여)
# 여기가 가장 시간이 많이 걸리는 부분 (약 0.5~1초)
self.left_panel = AnalysisPanel("left")
self.right_panel = AnalysisPanel("right")
self.splitter.addWidget(self.left_panel)
self.splitter.addWidget(self.right_panel)
self.splitter.setSizes([900, 900]) # 1:1 비율
# 패널 데이터 로드 시 날짜 비교를 위한 시그널 연결
self.left_panel.data_loaded.connect(self.check_sync_availability)
self.right_panel.data_loaded.connect(self.check_sync_availability)
# AI 버튼 클릭 연결
self._ai_button.clicked.connect(self._open_ai_chat)
self.status_bar.showMessage("준비 완료", 3000)
print("[MainWindow] Panels initialized lazily.")
except Exception as e:
print(f"[MainWindow] Panel initialization failed: {e}")
self.status_bar.showMessage(f"초기화 오류: {e}")
# setup_ui 메서드는 제거 (setup_ui_skeleton으로 대체됨)
def resizeEvent(self, event): def resizeEvent(self, event):
super().resizeEvent(event) super().resizeEvent(event)
try: try:

View File

@ -4,6 +4,7 @@ from PySide6.QtWidgets import QApplication
from app.ui.main_window import MainWindow from app.ui.main_window import MainWindow
def main(): def main():
# 시작 시간 측정
start_time = time.time() start_time = time.time()
print(f"[STARTUP] Application starting at {time.strftime('%H:%M:%S')}") print(f"[STARTUP] Application starting at {time.strftime('%H:%M:%S')}")
@ -12,20 +13,19 @@ def main():
app = QApplication(sys.argv) app = QApplication(sys.argv)
print(f"[STARTUP] QApplication created in {time.time() - t0:.3f}s") print(f"[STARTUP] QApplication created in {time.time() - t0:.3f}s")
# 다크 테마나 스타일시트 적용 가능 # 스타일 설정
print("[STARTUP] Setting style...") print("[STARTUP] Setting style...")
t0 = time.time() t0 = time.time()
app.setStyle("Fusion") app.setStyle("Fusion")
print(f"[STARTUP] Style set in {time.time() - t0:.3f}s") print(f"[STARTUP] Style set in {time.time() - t0:.3f}s")
# 역 정보는 파일 로드 시점에 자동으로 로드됨 (지연 로딩) # 메인 윈도우 생성 (지연 로딩 적용됨)
# TrackInfo.load_info() 호출 제거 - 불필요한 초기 로딩 방지
print("[STARTUP] Creating MainWindow...") print("[STARTUP] Creating MainWindow...")
t0 = time.time() t0 = time.time()
window = MainWindow() window = MainWindow()
print(f"[STARTUP] MainWindow created in {time.time() - t0:.3f}s") print(f"[STARTUP] MainWindow created in {time.time() - t0:.3f}s")
# 윈도우 표시
print("[STARTUP] Showing window...") print("[STARTUP] Showing window...")
t0 = time.time() t0 = time.time()
window.show() window.show()