from PySide6.QtWidgets import ( QDialog, QVBoxLayout, QHBoxLayout, QTabWidget, QPushButton, QLabel, QComboBox, QCheckBox, QGroupBox, QSpinBox, QRadioButton, QMessageBox, QWidget ) from PySide6.QtCore import Qt from src.core.config import Config from src.core.ocr_engine import OCREngine class SettingsDialog(QDialog): """ 设置对话框 提供应用程序各项设置的配置界面,包括常规设置、OCR设置和界面设置。 使用选项卡组织不同类别的设置,提供直观的设置界面。 设置更改后保存到配置文件中,供应用程序其他部分使用。 """ def __init__(self, parent=None): """ 初始化设置对话框 创建配置实例,设置窗口基本属性,初始化UI组件。 Args: parent: 父窗口,默认为None """ super().__init__(parent) self.setWindowTitle("设置") self.resize(500, 400) self.config = Config() self.init_ui() def init_ui(self): """ 初始化用户界面 创建选项卡式布局,包含常规、OCR和界面三个选项卡, 以及确定和取消按钮。 """ # 主布局 main_layout = QVBoxLayout(self) # 创建选项卡 tab_widget = QTabWidget() main_layout.addWidget(tab_widget) # 常规选项卡 general_tab = QWidget() tab_widget.addTab(general_tab, "常规") self.setup_general_tab(general_tab) # OCR选项卡 ocr_tab = QWidget() tab_widget.addTab(ocr_tab, "OCR") self.setup_ocr_tab(ocr_tab) # 界面选项卡 ui_tab = QWidget() tab_widget.addTab(ui_tab, "界面") self.setup_ui_tab(ui_tab) # 按钮区域 button_layout = QHBoxLayout() button_layout.addStretch() self.ok_btn = QPushButton("确定") self.ok_btn.clicked.connect(self.accept) self.cancel_btn = QPushButton("取消") self.cancel_btn.clicked.connect(self.reject) button_layout.addWidget(self.ok_btn) button_layout.addWidget(self.cancel_btn) main_layout.addLayout(button_layout) def setup_general_tab(self, tab): """ 设置常规选项卡 创建并布局常规设置选项,包括启动选项和文件历史设置。 Args: tab: 要设置的选项卡控件 """ layout = QVBoxLayout(tab) # 启动选项 startup_group = QGroupBox("启动选项") startup_layout = QVBoxLayout(startup_group) self.check_update_cb = QCheckBox("启动时检查更新") self.check_update_cb.setChecked(self.config.get('general.check_update_on_startup', False)) self.show_welcome_cb = QCheckBox("显示欢迎页面") self.show_welcome_cb.setChecked(self.config.get('general.show_welcome', True)) self.remember_window_cb = QCheckBox("记住窗口大小和位置") self.remember_window_cb.setChecked(self.config.get('general.remember_window_geometry', True)) startup_layout.addWidget(self.check_update_cb) startup_layout.addWidget(self.show_welcome_cb) startup_layout.addWidget(self.remember_window_cb) # 文件历史 history_group = QGroupBox("文件历史") history_layout = QVBoxLayout(history_group) recent_files_layout = QHBoxLayout() recent_files_layout.addWidget(QLabel("最近文件数量:")) self.recent_files_spin = QSpinBox() self.recent_files_spin.setRange(0, 30) self.recent_files_spin.setValue(self.config.get('general.max_recent_files', 10)) recent_files_layout.addWidget(self.recent_files_spin) recent_files_layout.addStretch() self.clear_history_btn = QPushButton("清除历史记录") self.clear_history_btn.clicked.connect(self.clear_history) history_layout.addLayout(recent_files_layout) history_layout.addWidget(self.clear_history_btn) layout.addWidget(startup_group) layout.addWidget(history_group) layout.addStretch() def setup_ocr_tab(self, tab): """ 设置OCR选项卡 创建并布局OCR设置选项,包括默认语言设置、处理选项和输出类型设置。 Args: tab: 要设置的选项卡控件 """ layout = QVBoxLayout(tab) # 默认语言 language_group = QGroupBox("默认OCR语言") language_layout = QVBoxLayout(language_group) self.language_combo = QComboBox() self.language_combo.setToolTip("选择默认的OCR识别语言") # 添加可用的语言 ocr_engine = OCREngine() # 常用语言列表 common_langs = ['eng', 'chi_sim', 'chi_tra', 'jpn', 'kor'] # 首先添加常用语言 if ocr_engine.available_languages: # 添加常用语言组 common_available = [lang for lang in common_langs if lang in ocr_engine.available_languages] if common_available: self.language_combo.addItem("--- 常用语言 ---", None) for lang_code in common_available: lang_name = ocr_engine.get_language_name(lang_code) self.language_combo.addItem(lang_name, lang_code) # 添加其他语言组 other_available = [lang for lang in ocr_engine.available_languages if lang not in common_langs] if other_available: self.language_combo.addItem("--- 其他语言 ---", None) # 按名称排序 other_langs_sorted = sorted( other_available, key=lambda x: ocr_engine.get_language_name(x) ) for lang_code in other_langs_sorted: lang_name = ocr_engine.get_language_name(lang_code) self.language_combo.addItem(lang_name, lang_code) else: # 如果没有常用语言,直接添加所有语言 for lang_code in ocr_engine.available_languages: lang_name = ocr_engine.get_language_name(lang_code) self.language_combo.addItem(lang_name, lang_code) # 设置当前默认语言 default_lang = self.config.get('default_options.language', 'eng') index = self.language_combo.findData(default_lang) if index >= 0: self.language_combo.setCurrentIndex(index) # 添加刷新语言列表按钮 lang_buttons_layout = QHBoxLayout() self.refresh_langs_btn = QPushButton("刷新语言列表") self.refresh_langs_btn.clicked.connect(self.refresh_languages) lang_buttons_layout.addWidget(self.refresh_langs_btn) language_layout.addWidget(self.language_combo) language_layout.addLayout(lang_buttons_layout) # 默认选项 options_group = QGroupBox("默认处理选项") options_layout = QVBoxLayout(options_group) self.deskew_cb = QCheckBox("自动校正倾斜页面") self.deskew_cb.setChecked(self.config.get('default_options.deskew', True)) self.rotate_cb = QCheckBox("自动旋转页面") self.rotate_cb.setChecked(self.config.get('default_options.rotate_pages', True)) self.clean_cb = QCheckBox("清理图像") self.clean_cb.setChecked(self.config.get('default_options.clean', False)) self.optimize_cb = QCheckBox("优化输出文件大小") self.optimize_cb.setChecked(self.config.get('default_options.optimize', True)) options_layout.addWidget(self.deskew_cb) options_layout.addWidget(self.rotate_cb) options_layout.addWidget(self.clean_cb) options_layout.addWidget(self.optimize_cb) # 输出类型 output_group = QGroupBox("默认输出类型") output_layout = QVBoxLayout(output_group) self.output_type_combo = QComboBox() self.output_type_combo.addItems(["pdf", "pdfa", "pdfa-1", "pdfa-2", "pdfa-3"]) self.output_type_combo.setCurrentText(self.config.get('default_options.output_type', 'pdfa')) output_layout.addWidget(self.output_type_combo) layout.addWidget(language_group) layout.addWidget(options_group) layout.addWidget(output_group) layout.addStretch() def setup_ui_tab(self, tab): """ 设置界面选项卡 创建并布局界面设置选项,包括主题和语言设置。 Args: tab: 要设置的选项卡控件 """ layout = QVBoxLayout(tab) # 主题设置 theme_group = QGroupBox("主题") theme_layout = QVBoxLayout(theme_group) self.theme_system_rb = QRadioButton("跟随系统") self.theme_light_rb = QRadioButton("浅色主题") self.theme_dark_rb = QRadioButton("深色主题") current_theme = self.config.get('ui.theme', 'system') if current_theme == 'light': self.theme_light_rb.setChecked(True) elif current_theme == 'dark': self.theme_dark_rb.setChecked(True) else: self.theme_system_rb.setChecked(True) theme_layout.addWidget(self.theme_system_rb) theme_layout.addWidget(self.theme_light_rb) theme_layout.addWidget(self.theme_dark_rb) # 语言设置 language_group = QGroupBox("界面语言") language_layout = QVBoxLayout(language_group) self.ui_language_combo = QComboBox() self.ui_language_combo.addItem("简体中文", "zh_CN") self.ui_language_combo.addItem("English", "en_US") current_lang = self.config.get('ui.language', 'zh_CN') index = self.ui_language_combo.findData(current_lang) if index >= 0: self.ui_language_combo.setCurrentIndex(index) language_note = QLabel("注:更改语言设置需要重启应用程序才能生效") language_note.setStyleSheet("color: gray;") language_layout.addWidget(self.ui_language_combo) language_layout.addWidget(language_note) layout.addWidget(theme_group) layout.addWidget(language_group) layout.addStretch() def clear_history(self): """ 清除历史记录 清空最近使用的文件和输出目录列表,并弹出确认提示。 """ self.config.set('recent_files', []) self.config.set('recent_output_dirs', []) QMessageBox.information(self, "已清除", "已清除所有历史记录") def accept(self): """ 确定按钮点击处理 保存所有设置到配置文件中,并关闭对话框。 """ # 保存常规设置 self.config.set('general.check_update_on_startup', self.check_update_cb.isChecked()) self.config.set('general.show_welcome', self.show_welcome_cb.isChecked()) self.config.set('general.remember_window_geometry', self.remember_window_cb.isChecked()) self.config.set('general.max_recent_files', self.recent_files_spin.value()) # 保存OCR设置 lang_index = self.language_combo.currentIndex() lang_data = self.language_combo.itemData(lang_index) # 如果选择了分隔符,尝试找到下一个有效选项 if lang_data is None: for i in range(lang_index + 1, self.language_combo.count()): next_data = self.language_combo.itemData(i) if next_data: lang_data = next_data break # 如果没有找到,使用默认语言 if lang_data is None: lang_data = 'eng' self.config.set('default_options.language', lang_data) self.config.set('default_options.deskew', self.deskew_cb.isChecked()) self.config.set('default_options.rotate_pages', self.rotate_cb.isChecked()) self.config.set('default_options.clean', self.clean_cb.isChecked()) self.config.set('default_options.optimize', self.optimize_cb.isChecked()) self.config.set('default_options.output_type', self.output_type_combo.currentText()) # 保存界面设置 if self.theme_light_rb.isChecked(): theme = 'light' elif self.theme_dark_rb.isChecked(): theme = 'dark' else: theme = 'system' self.config.set('ui.theme', theme) self.config.set('ui.language', self.ui_language_combo.currentData()) super().accept() def refresh_languages(self): """ 刷新语言列表 重新获取系统中已安装的Tesseract语言包,并更新语言下拉列表。 保存当前选择的语言,并在刷新后尝试恢复选择。 """ # 保存当前选择的语言 current_lang = self.language_combo.currentData() # 清空语言下拉列表 self.language_combo.clear() # 重新获取语言列表 ocr_engine = OCREngine() # 这会重新检测可用的语言 ocr_engine = OCREngine() # 重新填充语言下拉列表 common_langs = ['eng', 'chi_sim', 'chi_tra', 'jpn', 'kor'] if ocr_engine.available_languages: # 添加常用语言组 common_available = [lang for lang in common_langs if lang in ocr_engine.available_languages] if common_available: self.language_combo.addItem("--- 常用语言 ---", None) for lang_code in common_available: lang_name = ocr_engine.get_language_name(lang_code) self.language_combo.addItem(lang_name, lang_code) # 添加其他语言组 other_available = [lang for lang in ocr_engine.available_languages if lang not in common_langs] if other_available: self.language_combo.addItem("--- 其他语言 ---", None) # 按名称排序 other_langs_sorted = sorted( other_available, key=lambda x: ocr_engine.get_language_name(x) ) for lang_code in other_langs_sorted: lang_name = ocr_engine.get_language_name(lang_code) self.language_combo.addItem(lang_name, lang_code) else: # 如果没有常用语言,直接添加所有语言 for lang_code in ocr_engine.available_languages: lang_name = ocr_engine.get_language_name(lang_code) self.language_combo.addItem(lang_name, lang_code) # 恢复之前选择的语言 if current_lang: index = self.language_combo.findData(current_lang) if index >= 0: self.language_combo.setCurrentIndex(index) # 显示刷新结果 QMessageBox.information( self, "刷新完成", f"已刷新语言列表,找到 {len(ocr_engine.available_languages)} 种语言" ) def download_language_pack(self): """下载Tesseract语言包 - 已移除""" pass