""" MainView 클래스는 PyQt5를 사용하여 DBC 파일을 C 파일로 변환하는 GUI 애플리케이션을 구현합니다. 메서드: __init__(self): MainView 클래스의 초기화 메서드입니다. UI 설정 및 초기값을 설정합니다. loadSettings(self): 설정 파일을 로드하고, 기본 저장 경로 및 마지막 열린 디렉토리를 설정합니다. saveSettings(self): 현재 설정을 설정 파일에 저장합니다. setupUI(self): UI를 설정하고 메뉴, 툴바, 상태바, 파일 리스트 및 기타 위젯을 추가합니다. selectSavePath(self): 저장 경로를 선택하는 파일 다이얼로그를 엽니다. openSavePath(self): 현재 설정된 저장 경로를 엽니다. openCalculator(self): 계산기를 엽니다. centerWindow(self): 창을 화면 중앙에 위치시킵니다. centerDialog(self, dialog): 다이얼로그를 부모 창의 중앙에 위치시킵니다. FilesOpen(self): 파일 열기 다이얼로그를 열고 선택된 파일을 파일 리스트에 추가합니다. deleteSelectedFiles(self): 선택된 파일을 파일 리스트에서 삭제합니다. deleteAllFiles(self): 파일 리스트의 모든 파일을 삭제합니다. removeChannelInfo(self, file_path): 설정 파일에서 특정 파일의 채널 정보를 제거합니다. clearAlerts(self): 알림창의 내용을 지웁니다. showWarning(self, title, message): 경고 메시지 박스를 표시합니다. showDuplicateFilesWarning(self, duplicate_files, new_files, new_files_names): 중복 파일 경고 메시지 박스를 표시합니다. sortTreeView(self, col, reverse): 파일 리스트를 특정 열을 기준으로 정렬합니다. selectAllFiles(self): 파일 리스트의 모든 파일을 선택합니다. invertSelection(self): 파일 리스트의 선택을 반전시킵니다. setWindowSize(self, size): 창의 크기를 설정합니다. openSettings(self): 설정 다이얼로그를 엽니다. openAbout(self): 프로그램 정보 다이얼로그를 엽니다. populateTreeView(self, file_paths): 파일 리스트에 파일을 추가하고 채널 정보를 업데이트합니다. updateAlertText(self, message, file_list): 알림창에 메시지를 추가합니다. convertFiles(self): 파일을 변환하고 변환 상태를 업데이트합니다. onHeaderClicked(self, logicalIndex): 파일 리스트의 헤더를 클릭했을 때 정렬을 수행합니다. onItemDoubleClicked(self, item, column): 파일 리스트의 항목을 더블클릭했을 때 파일을 열거나 경로를 엽니다. openChannelDialog(self, item): 채널 선택 다이얼로그를 엽니다. applyChannelSelection(self, item, combo, dialog): 선택된 채널을 파일 리스트에 적용하고 다이얼로그를 닫습니다. updateChannelInfo(self, directory, filename, channel): 설정 파일에 채널 정보를 업데이트합니다. setupCloseEvent(self): 프로그램 종료 이벤트를 설정합니다. onClose(self, event): 프로그램 종료 시 설정을 초기화하고 저장합니다. """ import os import sys from PyQt5 import QtWidgets, QtGui, QtCore from datetime import datetime import json import subprocess import shutil # 파일 복사를 위해 shutil 모듈 추가 class MainView(QtWidgets.QMainWindow): def __init__(self): super().__init__() if hasattr(sys, '_MEIPASS'): base_path = sys._MEIPASS # 실행 파일 내에서 파일 경로 설정 else: base_path = os.path.abspath(".") # 실행 파일이 아닌 경우 현재 디렉토리로 설정 icon_path = os.path.join(base_path, "icon/icon.png") # 아이콘 경로 설정 self.setWindowIcon(QtGui.QIcon(icon_path)) # 프로그램 아이콘 설정 self.version = "1.0.0" # 프로그램 버전 설정 self.default_save_path = os.path.join(os.path.expanduser("~"), "Desktop") # 바탕화면 경로 설정 self.file_paths = [] # 파일 경로 저장 리스트 self.channel_info = {} # 채널 정보 초기화 self.loadSettings() # 설정 로드 self.setupUI(base_path) # UI 설정 self.centerWindow() # 창을 화면 중앙에 위치 self.sortTreeView(0, True) # 기본 파일명 오름차순 정렬 self.channel_options = ["CH0", "CH1", "CH2", "CH3", "CH4", "CH5"] # 채널 옵션 설정 self.setupCloseEvent() # 프로그램 종료 이벤트 설정 def loadSettings(self): self.settings_file = "settings.json" if os.path.exists(self.settings_file): with open(self.settings_file, "r", encoding="utf-8") as file: self.settings = json.load(file) # 설정 파일 로드 self.default_save_path = self.settings.get("default_save_path", os.path.join(os.path.expanduser("~"), "Desktop")) self.last_opened_dir = self.settings.get("last_opened_dir", os.path.expanduser("~")) # JSON 파일 내의 file_paths와 channel_info 정보 지우기 self.settings["file_paths"] = [] self.settings["channel_info"] = {} self.saveSettings() else: self.settings = {"theme": "light"} # 기본 설정 self.default_save_path = os.path.join(os.path.expanduser("~"), "Desktop") # 바탕화면 경로 설정 self.last_opened_dir = os.path.expanduser("~") def saveSettings(self): self.settings["default_save_path"] = self.default_save_path self.settings["file_paths"] = self.file_paths self.settings["last_opened_dir"] = self.last_opened_dir with open(self.settings_file, "w", encoding="utf-8") as file: json.dump(self.settings, file, ensure_ascii=False, indent=4) # 설정 파일 저장 def setupUI(self, base_path): self.setWindowTitle("DBC Converter") self.setGeometry(100, 100, 1250, 600) # 창 크기 조정 # 메뉴바 추가 self.menu_bar = self.menuBar() file_menu = self.menu_bar.addMenu("파일") edit_menu = self.menu_bar.addMenu("편집") view_menu = self.menu_bar.addMenu("보기") tools_menu = self.menu_bar.addMenu("도구") # 파일 메뉴 항목 추가 add_file_action = QtWidgets.QAction("파일 추가", self) add_file_action.setShortcut('Ctrl+O') add_file_action.triggered.connect(self.FilesOpen) file_menu.addAction(add_file_action) delete_selected_action = QtWidgets.QAction("선택 파일 삭제", self) delete_selected_action.setShortcut('Delete') delete_selected_action.triggered.connect(self.deleteSelectedFiles) file_menu.addAction(delete_selected_action) delete_all_action = QtWidgets.QAction("모든 파일 삭제", self) delete_all_action.setShortcut('Ctrl+Shift+Delete') delete_all_action.triggered.connect(self.deleteAllFiles) file_menu.addAction(delete_all_action) # 편집 메뉴 항목 추가 select_all_action = QtWidgets.QAction("모두 선택", self) select_all_action.setShortcut('Ctrl+A') select_all_action.triggered.connect(self.selectAllFiles) edit_menu.addAction(select_all_action) invert_selection_action = QtWidgets.QAction("선택 반전", self) invert_selection_action.setShortcut('Ctrl+I') invert_selection_action.triggered.connect(self.invertSelection) edit_menu.addAction(invert_selection_action) # 보기 메뉴 항목 추가 size_menu = view_menu.addMenu("창크기") size_menu.addAction("기본", lambda: self.setWindowSize("default")).setShortcut('Ctrl+0') size_menu.addAction("작게", lambda: self.setWindowSize("small")).setShortcut('Ctrl+1') size_menu.addAction("보통", lambda: self.setWindowSize("medium")).setShortcut('Ctrl+2') size_menu.addAction("크게", lambda: self.setWindowSize("large")).setShortcut('Ctrl+3') size_menu.addAction("자동", lambda: self.setWindowSize("auto")).setShortcut('Ctrl+4') sort_menu = view_menu.addMenu("정렬") sort_menu.addAction("파일명 오름차순", lambda: self.sortTreeView(0, False)).setShortcut('Ctrl+Shift+N') sort_menu.addAction("파일명 내림차순", lambda: self.sortTreeView(0, True)).setShortcut('Ctrl+Shift+M') sort_menu.addAction("파일경로 오름차순", lambda: self.sortTreeView(1, False)).setShortcut('Ctrl+Shift+P') sort_menu.addAction("파일경로 내림차순", lambda: self.sortTreeView(1, True)).setShortcut('Ctrl+Shift+Q') sort_menu.addAction("파일크기 오름차순", lambda: self.sortTreeView(3, False)).setShortcut('Ctrl+Shift+S') sort_menu.addAction("파일크기 내림차순", lambda: self.sortTreeView(3, True)).setShortcut('Ctrl+Shift+T') # 도구 메뉴 항목 추가 settings_action = QtWidgets.QAction("설정", self) settings_action.setShortcut('Ctrl+P') settings_action.triggered.connect(self.openSettings) tools_menu.addAction(settings_action) about_action = QtWidgets.QAction("프로그램 정보", self) about_action.setShortcut('Ctrl+I') about_action.triggered.connect(self.openAbout) tools_menu.addAction(about_action) tools_menu.addSeparator() # 구분선 추가 calculator_action = QtWidgets.QAction("계산기", self) calculator_action.setShortcut('Ctrl+Shift+C') calculator_action.triggered.connect(self.openCalculator) tools_menu.addAction(calculator_action) # 툴바 추가 self.toolbar = self.addToolBar("Main Toolbar") add_file_action_img_path = os.path.join(base_path, "img/add_file.png") # 파일 추가 아이콘 경로 설정 add_file_action = QtWidgets.QAction(QtGui.QIcon(add_file_action_img_path), "파일 추가\n(Ctrl+O)", self) add_file_action.triggered.connect(self.FilesOpen) self.toolbar.addAction(add_file_action) delete_file_action_img_path = os.path.join(base_path, "img/delete_file.png") # 파일 삭제 아이콘 경로 설정 delete_file_action = QtWidgets.QAction(QtGui.QIcon(delete_file_action_img_path), "선택 파일 삭제\n(Delete)", self) delete_file_action.triggered.connect(self.deleteSelectedFiles) self.toolbar.addAction(delete_file_action) delete_all_action_img_path = os.path.join(base_path, "img/delete_all.png") # 모든 파일 삭제 아이콘 경로 설정 delete_all_action = QtWidgets.QAction(QtGui.QIcon(delete_all_action_img_path), "모든 파일 삭제\n(Ctrl+Shift+Delete)", self) delete_all_action.triggered.connect(self.deleteAllFiles) self.toolbar.addAction(delete_all_action) delete_description_action_img_path = os.path.join(base_path, "img/delete_description.png") # 메시지 창 내용 삭제 아이콘 경로 설정 delete_description_action = QtWidgets.QAction(QtGui.QIcon(delete_description_action_img_path), "메시지 창 내용 삭제\n(Ctrl+Shift+D)", self) delete_description_action.triggered.connect(self.clearAlerts) self.toolbar.addAction(delete_description_action) convert_action_img_path = os.path.join(base_path, "img/convert.png") # 변환 아이콘 경로 설정 convert_action = QtWidgets.QAction(QtGui.QIcon(convert_action_img_path), "변환\n(Ctrl+R)", self) convert_action.triggered.connect(self.convertFiles) self.toolbar.addAction(convert_action) # 상태바 추가 self.status_bar = self.statusBar() self.status_bar.showMessage("준비 완료") self.progress_bar = QtWidgets.QProgressBar() self.progress_bar.setMaximumWidth(200) self.status_bar.addPermanentWidget(self.progress_bar) self.progress_bar.setVisible(False) # 메인 위젯 설정 main_widget = QtWidgets.QWidget() self.setCentralWidget(main_widget) main_layout = QtWidgets.QHBoxLayout(main_widget) # 파일 리스트 설정 file_list_widget = QtWidgets.QWidget() file_list_layout = QtWidgets.QVBoxLayout(file_list_widget) self.tree = QtWidgets.QTreeWidget() self.tree.setColumnCount(4) self.tree.setHeaderLabels(['파일명', '파일경로', '채널', '파일크기']) self.tree.setColumnWidth(0, 400) # 파일명 너비 설정 self.tree.setColumnWidth(1, 450) # 파일경로 너비 설정 self.tree.setColumnWidth(2, 50) # 채널 너비 설정 self.tree.setColumnWidth(3, 50) # 파일크기 너비 설정 self.tree.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) self.tree.header().sectionClicked.connect(self.onHeaderClicked) self.tree.itemDoubleClicked.connect(self.onItemDoubleClicked) # 헤더 라벨 가운데 정렬 header = self.tree.header() for i in range(self.tree.columnCount()): header.setDefaultAlignment(QtCore.Qt.AlignCenter) file_list_layout.addWidget(self.tree) # 저장 경로 설정 위젯 추가 path_layout = QtWidgets.QHBoxLayout() self.path_label = QtWidgets.QLabel("저장 경로:") self.path_edit = QtWidgets.QLineEdit(self.default_save_path) self.path_edit.setReadOnly(True) # 읽기 전용으로 설정 self.path_button = QtWidgets.QPushButton("경로 선택") self.path_button.clicked.connect(self.selectSavePath) self.open_path_button = QtWidgets.QPushButton("경로 열기") self.open_path_button.clicked.connect(self.openSavePath) path_layout.addWidget(self.path_label) path_layout.addWidget(self.path_edit) path_layout.addWidget(self.path_button) path_layout.addWidget(self.open_path_button) file_list_layout.addLayout(path_layout) # 알림창 설정 self.alert_text = QtWidgets.QTextEdit() self.alert_text.setReadOnly(True) self.alert_text.setAcceptRichText(True) file_list_layout.addWidget(self.alert_text) main_layout.addWidget(file_list_widget) # 설정 창 추가 self.settings_panel = self.createSettingsPanel() self.settings_panel.setFixedWidth(200) # 너비를 200으로 설정 main_layout.addWidget(self.settings_panel, 0) def createSettingsPanel(self): settings_panel = QtWidgets.QWidget() settings_layout = QtWidgets.QVBoxLayout(settings_panel) settings_label = QtWidgets.QLabel("설정") settings_label.setAlignment(QtCore.Qt.AlignCenter) settings_layout.addWidget(settings_label) return settings_panel def selectSavePath(self): selected_path = QtWidgets.QFileDialog.getExistingDirectory(self, "저장 경로 선택", self.default_save_path) if selected_path: self.default_save_path = selected_path self.path_edit.setText(selected_path) def openSavePath(self): if os.path.exists(self.default_save_path): os.startfile(self.default_save_path) else: self.showWarning("경고", "경로가 존재하지 않습니다") def openCalculator(self): subprocess.Popen('calc.exe') def centerWindow(self): frame_geometry = self.frameGeometry() screen_center = QtWidgets.QDesktopWidget().availableGeometry().center() frame_geometry.moveCenter(screen_center) self.move(frame_geometry.topLeft()) def centerDialog(self, dialog): dialog_geometry = dialog.frameGeometry() dialog_geometry.moveCenter(self.frameGeometry().center()) dialog.move(dialog_geometry.topLeft()) def FilesOpen(self): file_paths, _ = QtWidgets.QFileDialog.getOpenFileNames( self, "파일 열기", self.last_opened_dir, "DBC 파일 (*.dbc);;모든 파일 (*.*)" ) if file_paths: self.last_opened_dir = os.path.dirname(file_paths[0]) self.file_paths = file_paths # 새로운 경로로 덮어쓰기 existing_files = [self.tree.topLevelItem(i).text(0) for i in range(self.tree.topLevelItemCount())] duplicate_files = [os.path.split(file_path)[1] for file_path in file_paths if os.path.split(file_path)[1] in existing_files] new_files = [file_path for file_path in file_paths if os.path.split(file_path)[1] not in existing_files] if duplicate_files: self.showDuplicateFilesWarning(duplicate_files, new_files, [os.path.split(file_path)[1] for file_path in new_files]) self.updateAlertText(f"중복 파일 경고", duplicate_files) if new_files: self.populateTreeView(new_files) self.updateAlertText(f"파일 추가 완료", [os.path.split(file_path)[1] for file_path in new_files]) self.saveSettings() def deleteSelectedFiles(self): selected_items = self.tree.selectedItems() if not selected_items: self.showWarning("경고", "선택된 파일이 없습니다") self.updateAlertText("파일 삭제 실패", ["선택된 파일이 없습니다"]) return deleted_files = [item.text(0) for item in selected_items] for item in selected_items: index = self.tree.indexOfTopLevelItem(item) file_path = os.path.join(item.text(1), item.text(0)) self.removeChannelInfo(file_path) # 채널 정보 제거 self.tree.takeTopLevelItem(index) self.file_paths = [self.tree.topLevelItem(i).text(1) + '/' + self.tree.topLevelItem(i).text(0) for i in range(self.tree.topLevelItemCount())] self.updateAlertText(f"파일 삭제 완료", deleted_files) self.saveSettings() def deleteAllFiles(self): if self.tree.topLevelItemCount() == 0: self.showWarning("경고", "삭제할 파일이 없습니다") self.updateAlertText("모든 파일 삭제 실패", ["삭제할 파일이 없습니다"]) return deleted_files = [self.tree.topLevelItem(i).text(0) for i in range(self.tree.topLevelItemCount())] for i in range(self.tree.topLevelItemCount()): item = self.tree.topLevelItem(i) file_path = os.path.join(item.text(1), item.text(0)) self.removeChannelInfo(file_path) # 채널 정보 제거 self.tree.clear() self.file_paths = [] self.updateAlertText(f"모든 파일 삭제 완료", deleted_files) self.saveSettings() def removeChannelInfo(self, file_path): if "channel_info" in self.settings and file_path in self.settings["channel_info"]: del self.settings["channel_info"][file_path] self.saveSettings() print(f"[INFO] Removed channel info for {file_path}") def clearAlerts(self): self.alert_text.clear() def showWarning(self, title, message): warning_box = QtWidgets.QMessageBox(self) warning_box.setIcon(QtWidgets.QMessageBox.Warning) warning_box.setWindowTitle(title) warning_box.setText(message) warning_box.exec_() def showDuplicateFilesWarning(self, duplicate_files, new_files, new_files_names): duplicate_files_str = "\n".join(duplicate_files) new_files_str = "\n".join(new_files_names) if new_files: self.showWarning("중복 파일 경고", f"**중복 파일이 존재합니다**\n\n{duplicate_files_str}\n\n\n**중복 파일을 제외한 신규 파일을 추가합니다**\n\n{new_files_str}") else: self.showWarning("중복 파일 경고", f"**중복 파일이 존재합니다**\n\n{duplicate_files_str}") def sortTreeView(self, col, reverse): items = [] for i in range(self.tree.topLevelItemCount()): item = self.tree.takeTopLevelItem(0) items.append(item) if col == 3: # 파일크기 정렬 items.sort(key=lambda x: float(x.text(col).replace(" KB", "")), reverse=reverse) else: items.sort(key=lambda x: x.text(col), reverse=reverse) for item in items: self.tree.addTopLevelItem(item) def selectAllFiles(self): for i in range(self.tree.topLevelItemCount()): self.tree.topLevelItem(i).setSelected(True) def invertSelection(self): for i in range(self.tree.topLevelItemCount()): item = self.tree.topLevelItem(i) item.setSelected(not item.isSelected()) def setWindowSize(self, size): if size == "small": self.resize(600, 400) elif size == "medium": self.resize(800, 600) elif size == "large": self.resize(1200, 1000) elif size == "default": self.resize(1250, 600) elif size == "auto": self.adjustSize() def openSettings(self): settings_window = QtWidgets.QDialog(self) settings_window.setWindowTitle("설정") settings_window.setGeometry(100, 100, 400, 300) layout = QtWidgets.QVBoxLayout(settings_window) label = QtWidgets.QLabel("설정 창입니다.") label.setAlignment(QtCore.Qt.AlignCenter) layout.addWidget(label) self.centerDialog(settings_window) settings_window.exec_() def openAbout(self): about_window = QtWidgets.QDialog(self) about_window.setWindowTitle("프로그램 정보") about_window.setGeometry(100, 100, 400, 300) layout = QtWidgets.QVBoxLayout(about_window) label1 = QtWidgets.QLabel("이 프로그램은 DBC 파일을 C 파일로 변환합니다.") label1.setAlignment(QtCore.Qt.AlignCenter) label3 = QtWidgets.QLabel(f"버전: {self.version}") label3.setAlignment(QtCore.Qt.AlignCenter) layout.addWidget(label1) layout.addWidget(label3) self.centerDialog(about_window) about_window.exec_() def populateTreeView(self, file_paths): def format_file_size(size_in_bytes): size_in_kb = size_in_bytes / 1024 return f"{size_in_kb:.2f} KB" for file_path in file_paths: directory, file = os.path.split(file_path) fsize = format_file_size(os.path.getsize(file_path)) item = QtWidgets.QTreeWidgetItem([file, directory, self.channel_options[0], fsize]) self.tree.addTopLevelItem(item) self.updateChannelInfo(directory, file, self.channel_options[0]) # 기본 채널을 0으로 설정 self.file_paths = [self.tree.topLevelItem(i).text(1) + '/' + self.tree.topLevelItem(i).text(0) for i in range(self.tree.topLevelItemCount())] self.saveSettings() def updateAlertText(self, message, file_list): current_time = QtCore.QDateTime.currentDateTime().toString("yy-MM-dd-ddd HH:mm:ss") self.alert_text.append(f"[{current_time}] {message}") for file in file_list: self.alert_text.append(f" - {file}") self.alert_text.append("") # 한 줄 띄우기 def convertFiles(self): if not self.file_paths: self.showWarning("경고", "변환할 파일이 없습니다") self.updateAlertText("변환 실패", ["변환할 파일이 없습니다"]) return self.status_bar.showMessage("변환 중...") self.progress_bar.setVisible(True) self.progress_bar.setValue(0) total_files = len(self.file_paths) timestamp = datetime.now().strftime("%y-%m-%d-%a-%H-%M-%S") # 날짜 및 시간 형식 변경 base_output_dir = os.path.join(self.default_save_path, "DBC 변환", timestamp) for index, file_path in enumerate(self.file_paths): file_name = os.path.splitext(os.path.basename(file_path))[0] rx_output_dir = os.path.join(base_output_dir, file_name, "RX") tx_output_dir = os.path.join(base_output_dir, file_name, "TX") common_output_dir = os.path.join(base_output_dir, file_name, "Common") dbc_output_dir = os.path.join(base_output_dir, "#DBC") # DBC 파일 저장 경로 설정 os.makedirs(rx_output_dir, exist_ok=True) os.makedirs(tx_output_dir, exist_ok=True) os.makedirs(common_output_dir, exist_ok=True) os.makedirs(dbc_output_dir, exist_ok=True) # DBC 파일 저장 경로 생성 channel_info = self.settings.get("channel_info", {}).get(os.path.basename(file_path), "CH0") try: shutil.copy(file_path, dbc_output_dir) # DBC 파일 복사 subprocess.run(["python", "DBC_Converter_RX.py", file_path, rx_output_dir, json.dumps({os.path.basename(file_path): channel_info})], check=True) subprocess.run(["python", "DBC_Converter_TX.py", file_path, tx_output_dir, json.dumps({os.path.basename(file_path): channel_info})], check=True) subprocess.run(["python", "DBC_Converter_Common.py", file_path, common_output_dir, json.dumps({os.path.basename(file_path): channel_info})], check=True) self.updateAlertText(f"변환 성공", [file_path]) except subprocess.CalledProcessError as e: self.updateAlertText(f"변환 실패: {e}", [file_path]) self.progress_bar.setValue(int((index + 1) / total_files * 100)) self.status_bar.showMessage("변환 완료") self.progress_bar.setVisible(False) def onHeaderClicked(self, logicalIndex): header = self.tree.headerItem() if header.text(logicalIndex).endswith("▲"): self.sortTreeView(logicalIndex, True) header.setText(logicalIndex, header.text(logicalIndex).replace("▲", "▼")) else: self.sortTreeView(logicalIndex, False) header.setText(logicalIndex, header.text(logicalIndex).replace("▼", "▲")) def onItemDoubleClicked(self, item, column): if column == 0: # 파일명을 더블클릭한 경우 file_path = os.path.join(item.text(1), item.text(0)) os.startfile(file_path) elif column == 1: # 경로를 더블클릭한 경우 os.startfile(item.text(1)) elif column == 2: # 채널을 더블클릭한 경우 self.openChannelDialog(item) def openChannelDialog(self, item): channel_dialog = QtWidgets.QDialog(self) channel_dialog.setWindowTitle("채널 선택") channel_dialog.setGeometry(100, 100, 200, 100) layout = QtWidgets.QVBoxLayout(channel_dialog) channel_combo = QtWidgets.QComboBox() channel_combo.addItems(self.channel_options) current_channel = item.text(2) channel_combo.setCurrentText(current_channel) # 현재 채널을 콤보박스에 설정 layout.addWidget(channel_combo) button_layout = QtWidgets.QHBoxLayout() apply_button = QtWidgets.QPushButton("확인") apply_button.clicked.connect(lambda: self.applyChannelSelection(item, channel_combo, channel_dialog)) button_layout.addWidget(apply_button) cancel_button = QtWidgets.QPushButton("취소") cancel_button.clicked.connect(channel_dialog.close) button_layout.addWidget(cancel_button) layout.addLayout(button_layout) self.centerDialog(channel_dialog) channel_dialog.exec_() def applyChannelSelection(self, item, combo, dialog): item.setText(2, combo.currentText()) self.updateChannelInfo(item.text(1), item.text(0), combo.currentText()) # 채널 정보 업데이트 dialog.close() def updateChannelInfo(self, directory, filename, channel): file_path = os.path.join(directory, filename) file_name = os.path.basename(file_path) if "channel_info" not in self.settings: self.settings["channel_info"] = {} self.settings["channel_info"][file_name] = channel self.saveSettings() print(f"[INFO] Updated channel info for {file_name} to {channel}") def setupCloseEvent(self): self.closeEvent = self.onClose # 종료 이벤트 핸들러 설정 def onClose(self, event): self.file_paths = [] # 파일 경로 초기화 self.settings["file_paths"] = [] # 설정 파일 경로 초기화 self.settings["channel_info"] = {} # 채널 정보 초기화 self.saveSettings() # 설정 저장 event.accept() # 종료 이벤트 수락 if __name__ == '__main__': app = QtWidgets.QApplication(sys.argv) main_view = MainView() main_view.show() sys.exit(app.exec_())