diff --git a/src/gui.py b/src/gui.py
index c3778e6..06c4427 100644
--- a/src/gui.py
+++ b/src/gui.py
@@ -10,6 +10,7 @@ import os
import threading
import logging
import configparser
+import yaml
from pathlib import Path
# 设置环境
@@ -63,16 +64,150 @@ class GUI(QMainWindow):
self.signaller = Signaller()
self.worker_thread = None
- self._setup_ui()
+ self.pipeline = None # 当前 Pipeline 实例
+ self.project_config = None # 当前项目配置
# 连接信号
self.signaller.log_signal.connect(self._append_log)
self.signaller.finished_signal.connect(self._on_finished)
- def _setup_ui(self):
+ # 显示启动页
+ self._setup_start_page()
+
+ def _clear_ui(self):
+ """清空当前 UI"""
+ central = self.centralWidget()
+ if central:
+ central.deleteLater()
+
+ def _setup_start_page(self):
+ """启动页:新建项目 / 打开已有项目"""
self.setWindowTitle("Piano Highlight Generator - GUI")
+ self.setGeometry(100, 100, 500, 300)
+
+ self._clear_ui()
+ central = QWidget()
+ self.setCentralWidget(central)
+ layout = QVBoxLayout(central)
+ layout.setAlignment(Qt.AlignCenter)
+
+ # 标题
+ title = QLabel("Piano Highlight Generator")
+ title.setStyleSheet("font-size: 24px; font-weight: bold;")
+ title.setAlignment(Qt.AlignCenter)
+ layout.addWidget(title)
+
+ layout.addSpacing(40)
+
+ # 按钮
+ self.new_project_btn = QPushButton("新建项目")
+ self.new_project_btn.setMinimumHeight(50)
+ self.new_project_btn.clicked.connect(self._on_new_project)
+ layout.addWidget(self.new_project_btn)
+
+ self.open_project_btn = QPushButton("打开已有项目")
+ self.open_project_btn.setMinimumHeight(50)
+ self.open_project_btn.clicked.connect(self._on_open_project)
+ layout.addWidget(self.open_project_btn)
+
+ layout.addStretch()
+
+ def _on_new_project(self):
+ """新建项目:切换到文件选择界面"""
+ self._setup_new_project_ui()
+
+ def _on_open_project(self):
+ """打开已有项目"""
+ dir_path = QFileDialog.getExistingDirectory(self, "选择项目目录")
+ if not dir_path:
+ return
+ self.load_project(dir_path)
+
+ def load_project(self, output_dir):
+ """
+ 加载已有项目,加载 generated_config.yaml,显示 clip 列表
+ """
+ config_path = os.path.join(output_dir, 'generated_config.yaml')
+ if not os.path.exists(config_path):
+ QMessageBox.critical(self, "错误", f"不是有效的项目目录:\n{config_path}")
+ return
+
+ with open(config_path, 'r', encoding='utf-8') as f:
+ self.project_config = yaml.safe_load(f)
+
+ self.project_config['output_dir'] = output_dir
+
+ # 初始化 Pipeline
+ self.pipeline = Pipeline(self.project_config)
+
+ # 显示项目信息(Task 9 完成后替换为完整编辑界面)
+ self._show_project_info()
+
+ def _show_project_info(self):
+ """显示项目基本信息(临时,过渡用)"""
+ self.setWindowTitle("项目信息 - Piano Highlight Generator")
+ self.setGeometry(100, 100, 600, 400)
+
+ self._clear_ui()
+ central = QWidget()
+ self.setCentralWidget(central)
+ layout = QVBoxLayout(central)
+
+ # 项目路径
+ layout.addWidget(QLabel(f"项目目录: {self.project_config.get('output_dir', 'N/A')}"))
+
+ # 视频源
+ video_src = self.project_config.get('video_src', 'N/A')
+ layout.addWidget(QLabel(f"视频: {video_src}"))
+
+ # PPT 源
+ ppt_src = self.project_config.get('ppt_src', 'N/A')
+ layout.addWidget(QLabel(f"PPT: {ppt_src}"))
+
+ # Clips 数量
+ clips = self.project_config.get('clips', [])
+ layout.addWidget(QLabel(f"Clips 数量: {len(clips)}"))
+
+ # Clips 列表
+ if clips:
+ list_label = QLabel("Clips 列表:")
+ layout.addWidget(list_label)
+ for i, clip in enumerate(clips[:10]): # 只显示前10个
+ title = clip.get('title', clip.get('content', 'N/A'))[:50]
+ start = clip.get('start_time', 'N/A')
+ end = clip.get('end_time', 'N/A')
+ layout.addWidget(QLabel(f" {i+1}. [{start}-{end}] {title}"))
+ if len(clips) > 10:
+ layout.addWidget(QLabel(f" ... 还有 {len(clips) - 10} 个"))
+
+ layout.addStretch()
+
+ # 按钮区
+ btn_layout = QHBoxLayout()
+ self.edit_btn = QPushButton("进入编辑模式")
+ self.edit_btn.clicked.connect(self._setup_edit_ui) # Task 9 实现
+ back_btn = QPushButton("返回")
+ back_btn.clicked.connect(self._setup_start_page)
+ btn_layout.addWidget(self.edit_btn)
+ btn_layout.addWidget(back_btn)
+ layout.addLayout(btn_layout)
+
+ def _setup_edit_ui(self):
+ """
+ 编辑界面(Task 9 实现)
+ 目前显示 TODO 提示
+ """
+ QMessageBox.information(
+ self, "提示",
+ "编辑模式将在 Task 9 中实现\n目前可以手动编辑 generated_config.yaml 后重新运行"
+ )
+
+ def _setup_new_project_ui(self):
+ """新建项目的文件选择界面"""
+ self.setWindowTitle("新建项目 - Piano Highlight Generator")
self.setGeometry(100, 100, 700, 500)
+ self._clear_ui()
central = QWidget()
self.setCentralWidget(central)
layout = QVBoxLayout(central)
@@ -124,12 +259,11 @@ class GUI(QMainWindow):
# === 按钮区 ===
btn_layout = QHBoxLayout()
self.start_btn = QPushButton("开始处理")
- self.start_btn.clicked.connect(self._on_start)
- self.clear_btn = QPushButton("清空日志")
- self.clear_btn.clicked.connect(lambda: self.log_area.clear())
+ self.start_btn.clicked.connect(self._on_start_new)
+ self.back_btn = QPushButton("返回")
+ self.back_btn.clicked.connect(self._setup_start_page)
btn_layout.addWidget(self.start_btn)
- btn_layout.addWidget(self.clear_btn)
- btn_layout.addStretch()
+ btn_layout.addWidget(self.back_btn)
layout.addLayout(btn_layout)
def _select_file(self, edit, filter_str):
@@ -156,8 +290,8 @@ class GUI(QMainWindow):
else:
QMessageBox.critical(self, "错误", message)
- def _on_start(self):
- # 收集参数
+ def _on_start_new(self):
+ """开始新建项目流程"""
video_path = self.video_edit.text().strip()
ppt_path = self.ppt_edit.text().strip()
output_dir = self.output_edit.text().strip()
@@ -182,12 +316,13 @@ class GUI(QMainWindow):
# 后台线程执行
self.worker_thread = threading.Thread(
- target=self._worker,
+ target=self._worker_new,
args=(video_path, ppt_path, output_dir, api_key, api_host)
)
self.worker_thread.start()
- def _worker(self, video_path, ppt_path, output_dir, api_key, api_host):
+ def _worker_new(self, video_path, ppt_path, output_dir, api_key, api_host):
+ """新建项目的工作线程"""
try:
os.makedirs(output_dir, exist_ok=True)
@@ -217,7 +352,6 @@ class GUI(QMainWindow):
# 保存配置
config_path = os.path.join(output_dir, 'generated_config.yaml')
- import yaml
with open(config_path, 'w', encoding='utf-8') as f:
yaml.dump(config, f, allow_unicode=True, default_flow_style=False)
self.signaller.log_signal.emit(f"配置已保存: {config_path}")