182 lines
6.0 KiB
Python
182 lines
6.0 KiB
Python
import os
|
|
|
|
# 프로젝트 기본 코드 (뼈대)
|
|
CODE_MAIN = """import sys
|
|
from PySide6.QtWidgets import QApplication
|
|
from app.ui.main_window import MainWindow
|
|
|
|
def main():
|
|
app = QApplication(sys.argv)
|
|
app.setStyle("Fusion")
|
|
window = MainWindow()
|
|
window.show()
|
|
sys.exit(app.exec())
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
|
"""
|
|
|
|
CODE_SYNC = """from PySide6.QtCore import QObject, Signal
|
|
|
|
class SyncController(QObject):
|
|
# 시점 변경 시그널 (현재 인덱스, 현재 데이터 행)
|
|
time_changed = Signal(int, object)
|
|
file_loaded = Signal(int)
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._current_index = 0
|
|
self._total_records = 0
|
|
self._current_data = None
|
|
|
|
def set_index(self, index, data_row=None):
|
|
if 0 <= index < self._total_records:
|
|
self._current_index = index
|
|
self._current_data = data_row
|
|
self.time_changed.emit(index, data_row)
|
|
|
|
def set_total_records(self, count):
|
|
self._total_records = count
|
|
self.file_loaded.emit(count)
|
|
|
|
sync_manager = SyncController()
|
|
"""
|
|
|
|
CODE_MAIN_WINDOW = """from PySide6.QtWidgets import (QMainWindow, QWidget, QVBoxLayout,
|
|
QSplitter, QTabWidget, QFileDialog, QStatusBar)
|
|
from PySide6.QtCore import Qt
|
|
from app.core.sync_controller import sync_manager
|
|
from app.data.log_parser import LogLoader
|
|
|
|
class MainWindow(QMainWindow):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.setWindowTitle("SL200 AI Smart Analyzer")
|
|
self.resize(1600, 900)
|
|
|
|
self.log_loader = LogLoader()
|
|
self.raw_data = []
|
|
|
|
self.setup_ui()
|
|
self.setup_menu()
|
|
|
|
sync_manager.time_changed.connect(self.on_time_changed)
|
|
|
|
def setup_ui(self):
|
|
central_widget = QWidget()
|
|
self.setCentralWidget(central_widget)
|
|
main_layout = QVBoxLayout(central_widget)
|
|
|
|
self.splitter = QSplitter(Qt.Orientation.Horizontal)
|
|
|
|
# [왼쪽 패널]
|
|
self.left_panel = QTabWidget()
|
|
self.left_panel.addTab(QWidget(), "Dashboard (Legacy)")
|
|
self.left_panel.addTab(QWidget(), "Signal List")
|
|
|
|
# [오른쪽 패널]
|
|
self.right_panel = QTabWidget()
|
|
self.right_panel.addTab(QWidget(), "Analysis Graph")
|
|
self.right_panel.addTab(QWidget(), "AI Diagnosis")
|
|
|
|
self.splitter.addWidget(self.left_panel)
|
|
self.splitter.addWidget(self.right_panel)
|
|
self.splitter.setSizes([600, 1000])
|
|
|
|
main_layout.addWidget(self.splitter, stretch=1)
|
|
|
|
self.status_bar = QStatusBar()
|
|
self.setStatusBar(self.status_bar)
|
|
self.status_bar.showMessage("Ready")
|
|
|
|
def setup_menu(self):
|
|
menu_bar = self.menuBar()
|
|
file_menu = menu_bar.addMenu("File")
|
|
open_action = file_menu.addAction("Open Log File")
|
|
open_action.triggered.connect(self.open_file_dialog)
|
|
|
|
def open_file_dialog(self):
|
|
file_name, _ = QFileDialog.getOpenFileName(self, "Open Log", "", "Log Files (*.dat);;All Files (*)")
|
|
if file_name:
|
|
self.load_data(file_name)
|
|
|
|
def load_data(self, file_path):
|
|
self.status_bar.showMessage(f"Loading... {file_path}")
|
|
self.raw_data = self.log_loader.load(file_path)
|
|
if self.raw_data:
|
|
total = len(self.raw_data)
|
|
sync_manager.set_total_records(total)
|
|
sync_manager.set_index(0, self.raw_data[0])
|
|
self.status_bar.showMessage(f"Loaded {total} records.")
|
|
|
|
def on_time_changed(self, index, data_row):
|
|
if data_row:
|
|
self.status_bar.showMessage(f"Time: {data_row.time} | Speed: {data_row.trainspeed} km/h")
|
|
"""
|
|
|
|
# 프로젝트 구조 정의
|
|
structure = {
|
|
"app": {
|
|
"__init__.py": "",
|
|
"core": {
|
|
"__init__.py": "",
|
|
"sync_controller.py": CODE_SYNC,
|
|
"settings.py": "# Settings management\n"
|
|
},
|
|
"data": {
|
|
"__init__.py": "",
|
|
"log_parser.py": "# [TODO] Paste the LogParser code here!\n",
|
|
"log_manager.py": "# Data caching and management\n",
|
|
"db_handler.py": "# SQLite/JSON handler\n"
|
|
},
|
|
"ui": {
|
|
"__init__.py": "",
|
|
"main_window.py": CODE_MAIN_WINDOW,
|
|
"components": {
|
|
"__init__.py": "",
|
|
"speedometer.py": "# Custom Speedometer Widget\n",
|
|
"status_lamp.py": "# Custom LED Lamp Widget\n",
|
|
"time_slider.py": "# Timeline Slider\n"
|
|
},
|
|
"views": {
|
|
"__init__.py": "",
|
|
"dashboard_view.py": "# Legacy Dashboard UI\n",
|
|
"graph_view.py": "# PyQtGraph Implementation\n",
|
|
"log_list_view.py": "# Data Grid View\n",
|
|
"ai_view.py": "# AI Analysis Result View\n"
|
|
}
|
|
},
|
|
"analysis": {
|
|
"__init__.py": "",
|
|
"pattern_match.py": "# Pattern Matching Logic\n",
|
|
"correlation.py": "# Signal Correlation Logic\n"
|
|
},
|
|
"ai": {
|
|
"__init__.py": "",
|
|
"llm_engine.py": "# LangChain / Ollama Integration\n"
|
|
}
|
|
},
|
|
"resources": {},
|
|
"main.py": CODE_MAIN,
|
|
"requirements.txt": "PySide6\npyqtgraph\npandas\nnumpy\n"
|
|
}
|
|
|
|
def create_structure(base_path, structure):
|
|
for name, content in structure.items():
|
|
path = os.path.join(base_path, name)
|
|
if isinstance(content, dict):
|
|
os.makedirs(path, exist_ok=True)
|
|
create_structure(path, content)
|
|
else:
|
|
# 파일이 없을 때만 생성 (덮어쓰기 방지)
|
|
if not os.path.exists(path):
|
|
with open(path, 'w', encoding='utf-8') as f:
|
|
f.write(content)
|
|
print(f"Created: {path}")
|
|
else:
|
|
print(f"Skipped (Exists): {path}")
|
|
|
|
if __name__ == "__main__":
|
|
create_structure(".", structure)
|
|
print("\n[Success] Project structure created successfully!")
|
|
print("Next Step: Copy your 'log_parser.py' code into 'app/data/log_parser.py'.") |