Spaces:
Running
Running
antigravity
sync all fixes: prompt leakage, cross-lang, ref_cache update, and file wait logic
c441d2c | import sys | |
| import os | |
| import datetime | |
| from PySide6.QtWidgets import ( | |
| QApplication, QWidget, QVBoxLayout, QPushButton, QTextEdit, QFileDialog, | |
| QListView, QTreeView, QAbstractItemView | |
| ) | |
| from PySide6.QtCore import Signal, QObject, QSettings, QThread | |
| from ..Converter.Converter import convert | |
| from ..Converter.v2.Converter import find_ckpt_and_pth | |
| def get_timestamp_msg(message: str, level: str = "INFO") -> str: | |
| """辅助函数:生成类似 Logging 格式的带时间戳字符串""" | |
| now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') | |
| return f"{now} - {level} - {message}" | |
| class Worker(QObject): | |
| finished = Signal() | |
| log_signal = Signal(str) | |
| def __init__(self, folders): | |
| super().__init__() | |
| self.folders = folders | |
| def log(self, message: str, level: str = "INFO"): | |
| """内部辅助方法,用于格式化并发送日志""" | |
| formatted_msg = get_timestamp_msg(message, level) | |
| self.log_signal.emit(formatted_msg) | |
| def run(self): | |
| """执行转换任务""" | |
| try: | |
| root_output_dir = os.path.abspath("./Output") | |
| for folder in self.folders: | |
| character_name: str = os.path.basename(folder) | |
| output_dir: str = os.path.join(root_output_dir, character_name) | |
| if os.path.exists(output_dir): | |
| self.log(f'输出文件夹 {output_dir} 已存在,将覆盖内容。', "WARNING") | |
| torch_ckpt_path, torch_pth_path = find_ckpt_and_pth(folder) | |
| if not torch_ckpt_path or not torch_pth_path: | |
| self.log(f'无法处理文件夹 {folder} 。请保证文件夹内有 GPT—SOVITS V2 导出的 .pth 和 .ckpt 模型。', | |
| "ERROR") | |
| continue | |
| self.log(f'正在处理 {folder} 。') | |
| # 调用转换逻辑 | |
| convert(torch_ckpt_path, torch_pth_path, output_dir) | |
| self.log(f'{folder} 处理完成。') # 可选:提示完成 | |
| os.startfile(root_output_dir) | |
| except Exception as e: | |
| self.log(f"任务执行过程中发生未捕获异常: {str(e)}", "ERROR") | |
| finally: | |
| self.finished.emit() | |
| class ConverterWidget(QWidget): | |
| def __init__(self): | |
| super().__init__() | |
| self.setWindowTitle('GENIE Converter (PySide6 Version)') | |
| self.resize(1280, 720) | |
| self.settings = QSettings("MyCompany", "GENIE Converter") | |
| main_layout = QVBoxLayout(self) | |
| main_layout.setContentsMargins(20, 20, 20, 20) | |
| main_layout.setSpacing(15) | |
| self.folder_button = QPushButton('📂 选择一个或多个文件夹') | |
| self.folder_button.setFixedHeight(40) | |
| self.folder_button.clicked.connect(self.open_folder_dialog) | |
| self.log_display = QTextEdit() | |
| self.log_display.setReadOnly(True) | |
| main_layout.addWidget(self.folder_button) | |
| main_layout.addWidget(self.log_display) | |
| self.apply_stylesheet() | |
| self.thread = None | |
| self.worker = None | |
| self.append_formatted_log("欢迎使用 GENIE Converter!") | |
| self.append_formatted_log("支持将 GPT—SOVITS V2/V2ProPlus 模型导出为 GENIE 引擎所需的格式。") | |
| self.append_formatted_log("请选择一个或多个文件夹,每个文件夹中包含一对 .pth 和 .ckpt 文件。") | |
| self.append_formatted_log("您可以使用 Ctrl 或 Shift 键来进行多选。\n") | |
| def apply_stylesheet(self): | |
| self.setStyleSheet(""" | |
| QWidget { | |
| background-color: #2b2b2b; | |
| color: #f0f0f0; | |
| font-family: 'Segoe UI', 'Microsoft YaHei', 'Arial'; | |
| font-size: 14px; | |
| } | |
| QPushButton { | |
| background-color: #007bff; | |
| color: white; | |
| border: none; | |
| padding: 10px; | |
| border-radius: 5px; | |
| font-weight: bold; | |
| } | |
| QPushButton:hover { background-color: #0056b3; } | |
| QPushButton:pressed { background-color: #004494; } | |
| QPushButton:disabled { | |
| background-color: #555; | |
| color: #aaa; | |
| } | |
| QTextEdit { | |
| background-color: #1e1e1e; | |
| border: 1px solid #444; | |
| border-radius: 5px; | |
| padding: 8px; | |
| font-family: 'Consolas', 'Courier New', monospace; | |
| } | |
| QScrollBar:vertical { | |
| border: none; background: #2b2b2b; width: 12px; margin: 0; | |
| } | |
| QScrollBar::handle:vertical { | |
| background: #555; min-height: 20px; border-radius: 6px; | |
| } | |
| QScrollBar::handle:vertical:hover { background: #007bff; } | |
| QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical { height: 0px; } | |
| """) | |
| def append_log(self, text: str): | |
| """直接给主线程调用的日志打印方法""" | |
| self.log_display.append(text) | |
| self.scroll_to_bottom() | |
| def append_formatted_log(self, text: str, level="INFO"): | |
| """给主线程调用的带格式日志方法""" | |
| msg = get_timestamp_msg(text, level) | |
| self.append_log(msg) | |
| def scroll_to_bottom(self): | |
| self.log_display.verticalScrollBar().setValue( | |
| self.log_display.verticalScrollBar().maximum() | |
| ) | |
| def open_folder_dialog(self): | |
| last_dir = self.settings.value("last_dir", "") | |
| dialog = QFileDialog(self, '请选择文件夹', str(last_dir)) | |
| dialog.setFileMode(QFileDialog.FileMode.Directory) | |
| dialog.setOption(QFileDialog.Option.DontUseNativeDialog, True) | |
| list_view = dialog.findChild(QListView, 'listView') | |
| if list_view: | |
| list_view.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection) | |
| tree_view = dialog.findChild(QTreeView) | |
| if tree_view: | |
| tree_view.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection) | |
| if dialog.exec(): | |
| selected_folders = dialog.selectedFiles() | |
| if selected_folders: | |
| self.run_conversion_task(selected_folders) | |
| self.settings.setValue("last_dir", os.path.dirname(selected_folders[0])) | |
| def run_conversion_task(self, folders): | |
| self.folder_button.setEnabled(False) | |
| self.folder_button.setText("🔄 转换中,请稍候...") | |
| self.thread = QThread() | |
| self.worker = Worker(folders) | |
| self.worker.moveToThread(self.thread) | |
| # 连接线程控制信号 | |
| self.thread.started.connect(self.worker.run) | |
| self.worker.finished.connect(self.on_conversion_finished) | |
| self.worker.log_signal.connect(self.append_log) | |
| self.thread.start() | |
| def on_conversion_finished(self): | |
| self.thread.quit() | |
| self.thread.wait() | |
| self.worker.deleteLater() | |
| self.thread.deleteLater() | |
| self.thread = None | |
| self.worker = None | |
| self.folder_button.setEnabled(True) | |
| self.folder_button.setText("📂 选择一个或多个文件夹") | |
| self.append_formatted_log("所有任务已完成。", "INFO") | |
| def closeEvent(self, event): | |
| if self.thread is not None and self.thread.isRunning(): | |
| self.thread.quit() | |
| self.thread.wait() | |
| super().closeEvent(event) | |
| def start_gui() -> None: | |
| app = QApplication(sys.argv) | |
| window = ConverterWidget() | |
| window.show() | |
| sys.exit(app.exec()) | |