diff --git a/src/mcp_feedback_enhanced/gui/tabs/settings_tab.py b/src/mcp_feedback_enhanced/gui/tabs/settings_tab.py index 6edaed4..45e3f5c 100644 --- a/src/mcp_feedback_enhanced/gui/tabs/settings_tab.py +++ b/src/mcp_feedback_enhanced/gui/tabs/settings_tab.py @@ -9,7 +9,8 @@ from PySide6.QtWidgets import ( QWidget, QVBoxLayout, QHBoxLayout, QLabel, - QGroupBox, QComboBox, QRadioButton, QButtonGroup, QMessageBox + QGroupBox, QComboBox, QRadioButton, QButtonGroup, QMessageBox, + QCheckBox ) from PySide6.QtCore import Signal @@ -21,9 +22,10 @@ class SettingsTab(QWidget): language_changed = Signal() layout_mode_change_requested = Signal(bool) # 佈局模式變更請求信號 - def __init__(self, combined_mode: bool, parent=None): + def __init__(self, combined_mode: bool, config_manager, parent=None): super().__init__(parent) self.combined_mode = combined_mode + self.config_manager = config_manager self.i18n = get_i18n_manager() self._setup_ui() @@ -136,6 +138,27 @@ class SettingsTab(QWidget): self.layout_button_group.buttonToggled.connect(self._on_layout_mode_changed) layout.addWidget(self.layout_group) + + # === 視窗定位設置區域 === + self.window_group = QGroupBox(t('settings.window.title')) + self.window_group.setObjectName('window_group') + window_layout = QVBoxLayout(self.window_group) + window_layout.setSpacing(12) + window_layout.setContentsMargins(16, 16, 16, 16) + + # 總是在主螢幕中心顯示視窗選項 + self.always_center_checkbox = QCheckBox(t('settings.window.alwaysCenter')) + self.always_center_checkbox.setChecked(self.config_manager.get_always_center_window()) + self.always_center_checkbox.setStyleSheet("font-size: 14px; font-weight: bold; color: #e0e0e0;") + self.always_center_checkbox.stateChanged.connect(self._on_always_center_changed) + window_layout.addWidget(self.always_center_checkbox) + + self.center_desc_label = QLabel(t('settings.window.alwaysCenterDescription')) + self.center_desc_label.setStyleSheet("color: #9e9e9e; font-size: 12px; margin-left: 20px; margin-bottom: 8px;") + self.center_desc_label.setWordWrap(True) + window_layout.addWidget(self.center_desc_label) + + layout.addWidget(self.window_group) layout.addStretch() def _populate_language_selector(self) -> None: @@ -200,11 +223,17 @@ class SettingsTab(QWidget): else: self.separate_mode_radio.setChecked(True) + def _on_always_center_changed(self, state: int) -> None: + """處理視窗定位設置變更""" + always_center = state == 2 # Qt.Checked = 2 + self.config_manager.set_always_center_window(always_center) + def update_texts(self) -> None: """更新界面文字(用於語言切換)""" # 更新GroupBox標題 self.language_group.setTitle(t('settings.language.title')) self.layout_group.setTitle(t('settings.layout.title')) + self.window_group.setTitle(t('settings.window.title')) # 更新標籤文字 self.language_label.setText(t('settings.language.selector')) @@ -218,8 +247,15 @@ class SettingsTab(QWidget): self.separate_desc_label.setText(t('settings.layout.separateModeDescription')) self.combined_desc_label.setText(t('settings.layout.combinedModeDescription')) + # 更新視窗設置文字 + self.always_center_checkbox.setText(t('settings.window.alwaysCenter')) + self.center_desc_label.setText(t('settings.window.alwaysCenterDescription')) + # 重新填充語言選擇器 self._populate_language_selector() + + # 重新設置勾選狀態,確保設置被正確保持 + self.always_center_checkbox.setChecked(self.config_manager.get_always_center_window()) def set_layout_mode(self, combined_mode: bool) -> None: """設置佈局模式""" diff --git a/src/mcp_feedback_enhanced/gui/window/config_manager.py b/src/mcp_feedback_enhanced/gui/window/config_manager.py index 772ebf6..5e2af4d 100644 --- a/src/mcp_feedback_enhanced/gui/window/config_manager.py +++ b/src/mcp_feedback_enhanced/gui/window/config_manager.py @@ -100,4 +100,13 @@ class ConfigManager: def set_window_geometry(self, geometry: dict) -> None: """設置窗口幾何信息""" self.set('window_geometry', geometry) - debug_log(f"保存窗口幾何信息: {geometry}") \ No newline at end of file + debug_log(f"保存窗口幾何信息: {geometry}") + + def get_always_center_window(self) -> bool: + """獲取總是在主螢幕中心顯示視窗的設置""" + return self.get('always_center_window', False) + + def set_always_center_window(self, always_center: bool) -> None: + """設置總是在主螢幕中心顯示視窗""" + self.set('always_center_window', always_center) + debug_log(f"視窗定位設置: {'總是中心顯示' if always_center else '智能定位'}") \ No newline at end of file diff --git a/src/mcp_feedback_enhanced/gui/window/feedback_window.py b/src/mcp_feedback_enhanced/gui/window/feedback_window.py index 00bd4ca..a427602 100644 --- a/src/mcp_feedback_enhanced/gui/window/feedback_window.py +++ b/src/mcp_feedback_enhanced/gui/window/feedback_window.py @@ -49,6 +49,9 @@ class FeedbackWindow(QMainWindow): self.setMinimumSize(1000, 800) self.resize(1200, 900) + # 智能視窗定位 + self._apply_window_positioning() + # 中央元件 central_widget = QWidget() self.setCentralWidget(central_widget) @@ -359,8 +362,80 @@ class FeedbackWindow(QMainWindow): # 更新分頁文字 self.tab_manager.update_tab_texts() + def _apply_window_positioning(self) -> None: + """根據用戶設置應用視窗定位策略""" + always_center = self.config_manager.get_always_center_window() + + if always_center: + # 強制在主螢幕中心顯示 + self._move_to_primary_screen_center() + else: + # 先嘗試恢復上次位置 + if self._restore_last_position(): + # 檢查恢復的位置是否可見 + if not self._is_window_visible(): + self._move_to_primary_screen_center() + else: + # 沒有保存的位置,移到中心 + self._move_to_primary_screen_center() + + def _is_window_visible(self) -> bool: + """檢查視窗是否在任何螢幕的可見範圍內""" + from PySide6.QtWidgets import QApplication + + window_rect = self.frameGeometry() + + for screen in QApplication.screens(): + if screen.availableGeometry().intersects(window_rect): + return True + return False + + def _move_to_primary_screen_center(self) -> None: + """將視窗移到主螢幕中心""" + from PySide6.QtWidgets import QApplication + + screen = QApplication.primaryScreen() + if screen: + screen_geometry = screen.availableGeometry() + window_geometry = self.frameGeometry() + center_point = screen_geometry.center() + window_geometry.moveCenter(center_point) + self.move(window_geometry.topLeft()) + debug_log("視窗已移到主螢幕中心") + + def _restore_last_position(self) -> bool: + """嘗試恢復上次保存的視窗位置""" + try: + geometry = self.config_manager.get_window_geometry() + if geometry and 'x' in geometry and 'y' in geometry and 'width' in geometry and 'height' in geometry: + self.move(geometry['x'], geometry['y']) + self.resize(geometry['width'], geometry['height']) + debug_log(f"已恢復視窗位置: ({geometry['x']}, {geometry['y']}) 大小: {geometry['width']}x{geometry['height']}") + return True + except Exception as e: + debug_log(f"恢復視窗位置失敗: {e}") + return False + + def _save_window_position(self) -> None: + """保存當前視窗位置""" + try: + geometry = { + 'x': self.x(), + 'y': self.y(), + 'width': self.width(), + 'height': self.height() + } + self.config_manager.set_window_geometry(geometry) + debug_log(f"已保存視窗位置: ({geometry['x']}, {geometry['y']}) 大小: {geometry['width']}x{geometry['height']}") + except Exception as e: + debug_log(f"保存視窗位置失敗: {e}") + def closeEvent(self, event) -> None: """窗口關閉事件""" + # 保存視窗位置(除非設置為總是中心顯示) + if not self.config_manager.get_always_center_window(): + self._save_window_position() + # 清理分頁管理器 self.tab_manager.cleanup() event.accept() diff --git a/src/mcp_feedback_enhanced/gui/window/tab_manager.py b/src/mcp_feedback_enhanced/gui/window/tab_manager.py index 3870b0e..be08893 100644 --- a/src/mcp_feedback_enhanced/gui/window/tab_manager.py +++ b/src/mcp_feedback_enhanced/gui/window/tab_manager.py @@ -60,7 +60,7 @@ class TabManager: self.tab_widget.addTab(self.command_tab, t('tabs.command')) # 設置分頁 - self.settings_tab = SettingsTab(self.combined_mode) + self.settings_tab = SettingsTab(self.combined_mode, self.config_manager) self.tab_widget.addTab(self.settings_tab, t('tabs.language')) # 關於分頁 diff --git a/src/mcp_feedback_enhanced/locales/en/translations.json b/src/mcp_feedback_enhanced/locales/en/translations.json index 82574e4..e52ec3b 100644 --- a/src/mcp_feedback_enhanced/locales/en/translations.json +++ b/src/mcp_feedback_enhanced/locales/en/translations.json @@ -91,6 +91,11 @@ "combinedModeDescription": "Display AI summary and feedback on the same page for easy comparison", "separateMode": "Separate Mode", "separateModeDescription": "AI summary and feedback are in separate tabs" + }, + "window": { + "title": "Window Positioning", + "alwaysCenter": "Always show window at primary screen center", + "alwaysCenterDescription": "Recommended for multi-monitor setups or when experiencing window positioning issues" } }, "buttons": { diff --git a/src/mcp_feedback_enhanced/locales/zh-CN/translations.json b/src/mcp_feedback_enhanced/locales/zh-CN/translations.json index 9eec5f7..76cfcf8 100644 --- a/src/mcp_feedback_enhanced/locales/zh-CN/translations.json +++ b/src/mcp_feedback_enhanced/locales/zh-CN/translations.json @@ -71,6 +71,11 @@ "combinedModeDescription": "将 AI 摘要和反馈放在同一页面,便于对照阅读", "separateMode": "分离模式", "separateModeDescription": "AI 摘要和反馈分别在不同页签" + }, + "window": { + "title": "窗口定位", + "alwaysCenter": "总是在主屏幕中心显示窗口", + "alwaysCenterDescription": "建议在多屏幕环境或遇到窗口定位问题时开启此选项" } }, "buttons": { diff --git a/src/mcp_feedback_enhanced/locales/zh-TW/translations.json b/src/mcp_feedback_enhanced/locales/zh-TW/translations.json index 4451f70..b296773 100644 --- a/src/mcp_feedback_enhanced/locales/zh-TW/translations.json +++ b/src/mcp_feedback_enhanced/locales/zh-TW/translations.json @@ -92,6 +92,11 @@ "combinedModeDescription": "將 AI 摘要和回饋放在同一頁面,便於對照閱讀", "separateMode": "分離模式", "separateModeDescription": "AI 摘要和回饋分別在不同頁籤" + }, + "window": { + "title": "視窗定位", + "alwaysCenter": "總是在主螢幕中心顯示視窗", + "alwaysCenterDescription": "建議在多螢幕環境或遇到視窗定位問題時開啟此選項" } }, "buttons": {