feat: 메인 UI 윈도우를 도입하고 애플리케이션 시작 로직을 초기화했습니다.
This commit is contained in:
parent
ef3d9212b5
commit
4dc2322fed
|
|
@ -1,3 +1,4 @@
|
|||
venv/
|
||||
build/
|
||||
dist/
|
||||
__pycache__
|
||||
|
|
@ -2,6 +2,10 @@ import os
|
|||
import numpy as np
|
||||
import os
|
||||
import numpy as np
|
||||
import os
|
||||
import numpy as np
|
||||
import os
|
||||
import numpy as np
|
||||
import polars as pl
|
||||
from typing import Optional
|
||||
|
||||
|
|
@ -9,10 +13,9 @@ class FastLogParser:
|
|||
CHUNK_SIZE = 84
|
||||
|
||||
@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 저장.
|
||||
(VDI/VDO 포함 모든 필드 완벽 구현)
|
||||
Numpy 벡터 연산을 사용하여 MMI 바이너리 로그를 초고속으로 파싱 후 DataFrame 반환.
|
||||
"""
|
||||
if not os.path.exists(input_path):
|
||||
return None
|
||||
|
|
@ -241,6 +244,24 @@ class FastLogParser:
|
|||
# [Optional] 여기서 역 이름 매핑이나 코드 변환을 수행할 수 있음
|
||||
# (이전 대화의 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:
|
||||
output_path = input_path.replace(".dat", ".parquet")
|
||||
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
|
|
@ -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 PySide6.QtCore import Qt, QRect, QTimer
|
||||
|
||||
class MainWindow(QMainWindow):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setWindowTitle("SL200 AI Smart Analyzer")
|
||||
self.resize(1800, 1000)
|
||||
|
||||
self.setup_ui()
|
||||
# 1. 기본 UI 골격만 즉시 생성 (매우 빠름)
|
||||
self.setup_ui_skeleton()
|
||||
self.setup_menubar()
|
||||
self.setup_toolbar()
|
||||
|
||||
# 패널 데이터 로드 시 날짜 비교를 위한 시그널 연결
|
||||
self.left_panel.data_loaded.connect(self.check_sync_availability)
|
||||
self.right_panel.data_loaded.connect(self.check_sync_availability)
|
||||
# 2. 무거운 컴포넌트(패널, AI)는 윈도우가 뜬 직후 지연 로딩
|
||||
# 0ms: 이벤트 루프가 돌기 시작한 직후 실행 (윈도우 표시 후)
|
||||
QTimer.singleShot(10, self._init_panels)
|
||||
|
||||
# AI 클라이언트 초기화
|
||||
self._init_ai_client()
|
||||
# 500ms: 패널 로딩 후 실행
|
||||
QTimer.singleShot(500, self._init_ai_client)
|
||||
|
||||
def setup_ui(self):
|
||||
def setup_ui_skeleton(self):
|
||||
"""기본 UI 골격 생성 (빈 패널)"""
|
||||
central = QWidget()
|
||||
self.setCentralWidget(central)
|
||||
layout = QVBoxLayout(central)
|
||||
self.main_layout = QVBoxLayout(central)
|
||||
|
||||
# 좌우 분할
|
||||
splitter = QSplitter(Qt.Orientation.Horizontal)
|
||||
|
||||
# 왼쪽/오른쪽 패널 생성 (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.splitter = QSplitter(Qt.Orientation.Horizontal)
|
||||
self.main_layout.addWidget(self.splitter)
|
||||
|
||||
self.status_bar = QStatusBar()
|
||||
self.setStatusBar(self.status_bar)
|
||||
self.status_bar.showMessage("초기화 중...")
|
||||
|
||||
# 플로팅 AI 버튼
|
||||
# 플로팅 AI 버튼 (미리 생성하되 기능은 나중에 연결)
|
||||
self._ai_button = AIFloatingButton(central)
|
||||
self._ai_button.clicked.connect(self._open_ai_chat)
|
||||
self._ai_button.show()
|
||||
self._ai_chat: AIChatDialog | None = None
|
||||
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):
|
||||
super().resizeEvent(event)
|
||||
try:
|
||||
|
|
|
|||
Binary file not shown.
8
main.py
8
main.py
|
|
@ -4,6 +4,7 @@ from PySide6.QtWidgets import QApplication
|
|||
from app.ui.main_window import MainWindow
|
||||
|
||||
def main():
|
||||
# 시작 시간 측정
|
||||
start_time = time.time()
|
||||
print(f"[STARTUP] Application starting at {time.strftime('%H:%M:%S')}")
|
||||
|
||||
|
|
@ -12,20 +13,19 @@ def main():
|
|||
app = QApplication(sys.argv)
|
||||
print(f"[STARTUP] QApplication created in {time.time() - t0:.3f}s")
|
||||
|
||||
# 다크 테마나 스타일시트 적용 가능
|
||||
# 스타일 설정
|
||||
print("[STARTUP] Setting style...")
|
||||
t0 = time.time()
|
||||
app.setStyle("Fusion")
|
||||
print(f"[STARTUP] Style set in {time.time() - t0:.3f}s")
|
||||
|
||||
# 역 정보는 파일 로드 시점에 자동으로 로드됨 (지연 로딩)
|
||||
# TrackInfo.load_info() 호출 제거 - 불필요한 초기 로딩 방지
|
||||
|
||||
# 메인 윈도우 생성 (지연 로딩 적용됨)
|
||||
print("[STARTUP] Creating MainWindow...")
|
||||
t0 = time.time()
|
||||
window = MainWindow()
|
||||
print(f"[STARTUP] MainWindow created in {time.time() - t0:.3f}s")
|
||||
|
||||
# 윈도우 표시
|
||||
print("[STARTUP] Showing window...")
|
||||
t0 = time.time()
|
||||
window.show()
|
||||
|
|
|
|||
Loading…
Reference in New Issue