Files
Any2MIF/ui/main_window.py
2025-03-07 15:32:58 +08:00

256 lines
9.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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)