mirror of
https://github.com/HChaZZY/Any2MIF.git
synced 2025-12-06 10:33:49 +08:00
256 lines
9.8 KiB
Python
256 lines
9.8 KiB
Python
#!/usr/bin/env python
|
||
# -*- coding: utf-8 -*-
|
||
# Copyright (c) 2025 Any2MIF Project
|
||
# All rights reserved.
|
||
|
||
"""
|
||
Any2MIF - 主窗口类
|
||
包含应用程序的主界面和核心功能组织
|
||
"""
|
||
|
||
import os
|
||
import sys
|
||
from PyQt6.QtWidgets import (
|
||
QMainWindow, QVBoxLayout, QHBoxLayout, QWidget,
|
||
QSplitter, QStatusBar, QToolBar, QMessageBox,
|
||
QFileDialog, QGroupBox, QLabel
|
||
)
|
||
from PyQt6.QtCore import Qt, QSettings, QSize, QTimer
|
||
from PyQt6.QtGui import QIcon, QAction
|
||
|
||
from ui.file_selector import FileSelector
|
||
from ui.param_panel import ParamPanel
|
||
from ui.image_toolbar import ImageToolbar
|
||
from ui.theme_controller import ThemeController
|
||
from core.converter import MifConverter
|
||
from core.batch_manager import BatchManager
|
||
from core.image_processor import ImageProcessor
|
||
|
||
class MainWindow(QMainWindow):
|
||
"""主窗口类"""
|
||
|
||
def __init__(self, settings: QSettings, parent=None):
|
||
"""初始化主窗口"""
|
||
super().__init__(parent)
|
||
self.settings = settings
|
||
self.converter = MifConverter()
|
||
self.batch_manager = BatchManager(self.converter)
|
||
self.image_processor = ImageProcessor()
|
||
|
||
self._init_ui()
|
||
self._load_settings()
|
||
self._connect_signals()
|
||
|
||
def _init_ui(self):
|
||
"""初始化UI"""
|
||
# 设置窗口属性
|
||
self.setWindowTitle("Any2MIF - 文件转换器")
|
||
self.setMinimumSize(900, 600)
|
||
|
||
# 创建中央部件
|
||
central_widget = QWidget()
|
||
self.setCentralWidget(central_widget)
|
||
|
||
# 创建主布局
|
||
main_layout = QVBoxLayout(central_widget)
|
||
main_layout.setContentsMargins(10, 10, 10, 10)
|
||
main_layout.setSpacing(10)
|
||
|
||
# 创建左侧面板
|
||
left_panel = QWidget()
|
||
left_layout = QVBoxLayout(left_panel)
|
||
left_layout.setContentsMargins(0, 0, 0, 0)
|
||
left_layout.setSpacing(10)
|
||
|
||
# 创建文件选择器
|
||
self.file_selector = FileSelector(self.settings)
|
||
left_layout.addWidget(self.file_selector)
|
||
|
||
# 创建图像预览标签
|
||
preview_group = QGroupBox("图像预览")
|
||
preview_layout = QVBoxLayout(preview_group)
|
||
self.preview_label = QLabel()
|
||
self.preview_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||
# 设置固定高度而不是最小高度,确保在整个应用程序运行期间保持一致
|
||
self.preview_label.setFixedHeight(200)
|
||
self.preview_label.setStyleSheet("background-color: #333333; border: 1px solid #5d5d5d;")
|
||
preview_layout.addWidget(self.preview_label)
|
||
left_layout.addWidget(preview_group)
|
||
|
||
# 创建右侧面板
|
||
right_panel = QWidget()
|
||
right_layout = QVBoxLayout(right_panel)
|
||
right_layout.setContentsMargins(0, 0, 0, 0)
|
||
right_layout.setSpacing(10)
|
||
|
||
# 创建参数配置面板
|
||
self.param_panel = ParamPanel(self.settings)
|
||
right_layout.addWidget(self.param_panel)
|
||
|
||
# 创建图像处理工具栏
|
||
self.image_toolbar = ImageToolbar(self.image_processor, self.settings, self.preview_label)
|
||
right_layout.addWidget(self.image_toolbar)
|
||
|
||
# 创建分割器
|
||
splitter = QSplitter(Qt.Orientation.Horizontal)
|
||
splitter.addWidget(left_panel)
|
||
splitter.addWidget(right_panel)
|
||
main_layout.addWidget(splitter)
|
||
|
||
# 设置分割器比例
|
||
splitter.setSizes([int(self.width() * 0.4), int(self.width() * 0.6)])
|
||
|
||
# 创建状态栏
|
||
self.status_bar = QStatusBar()
|
||
self.setStatusBar(self.status_bar)
|
||
self.status_bar.showMessage("就绪")
|
||
|
||
# 创建主题控制器(不显示在界面上)
|
||
self.theme_controller = ThemeController(self.settings)
|
||
|
||
def _load_settings(self):
|
||
"""加载设置"""
|
||
# 恢复窗口几何形状
|
||
geometry = self.settings.value("geometry")
|
||
if geometry:
|
||
self.restoreGeometry(geometry)
|
||
|
||
# 应用主题(锁定为深色模式)
|
||
self.theme_controller.apply_theme("dark")
|
||
|
||
def _connect_signals(self):
|
||
"""连接信号和槽"""
|
||
# 文件选择器信号
|
||
self.file_selector.file_selected.connect(self.on_file_selected)
|
||
self.file_selector.convert_clicked.connect(self.convert_files)
|
||
self.file_selector.batch_convert_clicked.connect(self.batch_convert)
|
||
|
||
# 主题控制器信号
|
||
self.theme_controller.theme_changed.connect(self.on_theme_changed)
|
||
|
||
# 批量管理器信号
|
||
self.batch_manager.progress_updated.connect(self.update_progress)
|
||
self.batch_manager.conversion_completed.connect(self.on_conversion_completed)
|
||
|
||
def on_file_selected(self, file_path):
|
||
"""处理文件选择事件"""
|
||
self.status_bar.showMessage(f"已选择文件: {os.path.basename(file_path)}")
|
||
|
||
# 如果是图像文件,启用图像处理工具栏
|
||
if self.image_processor.is_image_file(file_path):
|
||
self.image_toolbar.setEnabled(True)
|
||
self.image_toolbar.load_image(file_path)
|
||
# 确保预览标签显示图像
|
||
self.preview_label.setVisible(True)
|
||
else:
|
||
self.image_toolbar.setEnabled(False)
|
||
# 隐藏预览标签
|
||
self.preview_label.setVisible(False)
|
||
|
||
def on_theme_changed(self, theme):
|
||
"""处理主题变更事件"""
|
||
self.settings.setValue("theme", theme)
|
||
|
||
def update_progress(self, current, total, file_name):
|
||
"""更新进度信息"""
|
||
self.status_bar.showMessage(f"正在转换 {file_name}... ({current}/{total})")
|
||
|
||
def on_conversion_completed(self, success_count, fail_count):
|
||
"""处理转换完成事件"""
|
||
self.status_bar.showMessage(f"转换完成。成功: {success_count}, 失败: {fail_count}")
|
||
|
||
if success_count > 0:
|
||
QMessageBox.information(
|
||
self,
|
||
"转换完成",
|
||
f"已成功转换 {success_count} 个文件" +
|
||
(f",{fail_count} 个文件失败" if fail_count > 0 else "")
|
||
)
|
||
elif fail_count > 0:
|
||
QMessageBox.warning(
|
||
self,
|
||
"转换失败",
|
||
f"所有 {fail_count} 个文件转换失败"
|
||
)
|
||
|
||
def convert_files(self):
|
||
"""转换选定的文件"""
|
||
files = self.file_selector.get_selected_files()
|
||
if not files:
|
||
QMessageBox.warning(self, "警告", "请先选择要转换的文件")
|
||
return
|
||
|
||
# 获取输出目录
|
||
output_dir = QFileDialog.getExistingDirectory(
|
||
self, "选择输出目录", os.path.expanduser("~")
|
||
)
|
||
if not output_dir:
|
||
return
|
||
|
||
# 获取转换参数
|
||
params = self.param_panel.get_params()
|
||
|
||
# 执行转换
|
||
for file_path in files:
|
||
try:
|
||
# 如果是图像文件且图像处理工具栏已启用,先处理图像
|
||
if self.image_processor.is_image_file(file_path) and self.image_toolbar.isEnabled():
|
||
processed_image = self.image_toolbar.get_processed_image()
|
||
if processed_image:
|
||
# 直接使用处理后的图像进行转换,而不是保存为临时文件
|
||
output_file = os.path.join(
|
||
output_dir,
|
||
f"{os.path.splitext(os.path.basename(file_path))[0]}.mif"
|
||
)
|
||
self.converter.convert_from_image(processed_image, output_file, params)
|
||
else:
|
||
# 如果没有处理后的图像,使用原始文件
|
||
output_file = os.path.join(
|
||
output_dir,
|
||
f"{os.path.splitext(os.path.basename(file_path))[0]}.mif"
|
||
)
|
||
self.converter.convert(file_path, output_file, params)
|
||
else:
|
||
# 非图像文件或图像处理工具栏未启用,直接转换
|
||
output_file = os.path.join(
|
||
output_dir,
|
||
f"{os.path.splitext(os.path.basename(file_path))[0]}.mif"
|
||
)
|
||
self.converter.convert(file_path, output_file, params)
|
||
|
||
self.status_bar.showMessage(f"已转换: {os.path.basename(file_path)}")
|
||
except Exception as e:
|
||
QMessageBox.critical(self, "转换错误", f"转换文件 {os.path.basename(file_path)} 时出错: {str(e)}")
|
||
|
||
QMessageBox.information(self, "转换完成", "文件转换完成")
|
||
|
||
def batch_convert(self):
|
||
"""批量转换文件"""
|
||
files = self.file_selector.get_selected_files()
|
||
if not files:
|
||
QMessageBox.warning(self, "警告", "请先选择要转换的文件")
|
||
return
|
||
|
||
# 获取输出目录
|
||
output_dir = QFileDialog.getExistingDirectory(
|
||
self, "选择输出目录", os.path.expanduser("~")
|
||
)
|
||
if not output_dir:
|
||
return
|
||
|
||
# 获取转换参数
|
||
params = self.param_panel.get_params()
|
||
|
||
# 检查是否有需要预处理的图像
|
||
processed_image = None
|
||
if self.image_toolbar.isEnabled():
|
||
processed_image = self.image_toolbar.get_processed_image()
|
||
|
||
# 启动批量转换,传递处理后的图像
|
||
self.batch_manager.start_batch(files, output_dir, params, processed_image)
|
||
|
||
def closeEvent(self, event):
|
||
"""处理窗口关闭事件"""
|
||
# 保存窗口几何形状
|
||
self.settings.setValue("geometry", self.saveGeometry())
|
||
super().closeEvent(event) |