feat(settings): prevent spinbox wheel changes

This commit is contained in:
chengma
2026-07-21 09:40:53 +08:00
parent 9c0007ca4c
commit b324e5d332
4 changed files with 136 additions and 17 deletions
+47 -12
View File
@@ -5,7 +5,8 @@ from __future__ import annotations
from contextlib import contextmanager
import os
from PySide6.QtCore import Signal
from PySide6.QtCore import QPointF, Signal
from PySide6.QtGui import QWheelEvent
from ... import ai as ai_module
from ... import chrome
@@ -28,6 +29,39 @@ def AIModelTestWorker(*args, **kwargs):
def CMHubSettingsWorker(*args, **kwargs):
return _call_package_attr("CMHubSettingsWorker", _RealCMHubSettingsWorker, *args, **kwargs)
class SettingsSpinBox(QSpinBox):
"""Forward wheel input to the settings scroll area instead of changing a value."""
def wheelEvent(self, event):
target = self._outer_scroll_viewport()
if target is None:
event.ignore()
return
global_position = event.globalPosition()
local_position = target.mapFromGlobal(global_position.toPoint())
forwarded = QWheelEvent(
QPointF(local_position),
global_position,
event.pixelDelta(),
event.angleDelta(),
event.buttons(),
event.modifiers(),
event.phase(),
event.inverted(),
)
QApplication.sendEvent(target, forwarded)
event.accept()
def _outer_scroll_viewport(self):
parent = self.parentWidget()
while parent is not None:
if isinstance(parent, QScrollArea):
return parent.viewport()
parent = parent.parentWidget()
return None
class SettingsTab(QWidget):
"""Tab 5: AI model definitions stored in data/config/ai_models.json."""
@@ -117,7 +151,7 @@ class SettingsTab(QWidget):
self.cmhub_image_alias_combo.setObjectName("cmhubImageAliasCombo")
self.cmhub_vision_alias_combo = QComboBox()
self.cmhub_vision_alias_combo.setObjectName("cmhubVisionAliasCombo")
self.cmhub_connect_timeout_spin = QSpinBox()
self.cmhub_connect_timeout_spin = SettingsSpinBox()
self.cmhub_connect_timeout_spin.setObjectName("cmhubConnectTimeoutSpin")
self.cmhub_connect_timeout_spin.setRange(1, 3600)
self.cmhub_connect_timeout_spin.setValue(appconfig.CMHUB_CONNECT_TIMEOUT_DEFAULT)
@@ -161,7 +195,7 @@ class SettingsTab(QWidget):
self.api_key_edit = QLineEdit()
self.api_key_edit.setObjectName("modelApiKeyEdit")
self.api_key_edit.setEchoMode(QLineEdit.Password)
self.connect_timeout_spin = QSpinBox()
self.connect_timeout_spin = SettingsSpinBox()
self.connect_timeout_spin.setObjectName("connectTimeoutSpin")
self.connect_timeout_spin.setRange(1, 3600)
self.connect_timeout_spin.setValue(30)
@@ -173,19 +207,19 @@ class SettingsTab(QWidget):
self.default_text_model_combo.setObjectName("defaultTextModelCombo")
self.default_image_model_combo = QComboBox()
self.default_image_model_combo.setObjectName("defaultImageModelCombo")
self.title_concurrency_spin = QSpinBox()
self.title_concurrency_spin = SettingsSpinBox()
self.title_concurrency_spin.setObjectName("titleConcurrencySpin")
self.title_concurrency_spin.setRange(
appconfig.AI_CONCURRENCY_MIN,
appconfig.AI_CONCURRENCY_MAX,
)
self.image_concurrency_spin = QSpinBox()
self.image_concurrency_spin = SettingsSpinBox()
self.image_concurrency_spin.setObjectName("imageConcurrencySpin")
self.image_concurrency_spin.setRange(
appconfig.AI_CONCURRENCY_MIN,
appconfig.AI_CONCURRENCY_MAX,
)
self.retry_spin = QSpinBox()
self.retry_spin = SettingsSpinBox()
self.retry_spin.setObjectName("retrySpin")
self.retry_spin.setRange(appconfig.AI_RETRY_MIN, appconfig.AI_RETRY_MAX)
self.resolution_combo = QComboBox()
@@ -219,16 +253,16 @@ class SettingsTab(QWidget):
self.db_path_edit.setObjectName("dbPathEdit")
self.db_path_edit.setEnabled(False)
self.db_path_edit.setVisible(False)
self.default_debug_port_spin = QSpinBox()
self.default_debug_port_spin = SettingsSpinBox()
self.default_debug_port_spin.setObjectName("defaultDebugPortSpin")
self.default_debug_port_spin.setRange(1, 65535)
self.debug_port_start_spin = QSpinBox()
self.debug_port_start_spin = SettingsSpinBox()
self.debug_port_start_spin.setObjectName("debugPortStartSpin")
self.debug_port_start_spin.setRange(1, 65535)
self.debug_port_end_spin = QSpinBox()
self.debug_port_end_spin = SettingsSpinBox()
self.debug_port_end_spin.setObjectName("debugPortEndSpin")
self.debug_port_end_spin.setRange(1, 65535)
self.cdp_ready_timeout_spin = QSpinBox()
self.cdp_ready_timeout_spin = SettingsSpinBox()
self.cdp_ready_timeout_spin.setObjectName("cdpReadyTimeoutSpin")
self.cdp_ready_timeout_spin.setRange(1, 3600)
self.save_config_button = QPushButton("保存设置")
@@ -236,11 +270,11 @@ class SettingsTab(QWidget):
self.unsaved_changes_label.setObjectName("settingsUnsavedChangesLabel")
self.unsaved_changes_label.setStyleSheet("color: #bc4c00; font-weight: 600;")
self.unsaved_changes_label.setVisible(False)
self.max_items_per_run_spin = QSpinBox()
self.max_items_per_run_spin = SettingsSpinBox()
self.max_items_per_run_spin.setObjectName("maxItemsPerRunSpin")
self.max_items_per_run_spin.setRange(1, 9999)
self.max_items_per_run_spin.setToolTip("作为每批最大更新条数;正式更新会分批处理当前筛选全部可更新记录。")
self.max_parallel_accounts_spin = QSpinBox()
self.max_parallel_accounts_spin = SettingsSpinBox()
self.max_parallel_accounts_spin.setObjectName("maxParallelAccountsSpin")
self.max_parallel_accounts_spin.setRange(
appconfig.SHOPEE_PARALLEL_ACCOUNTS_MIN,
@@ -409,6 +443,7 @@ class SettingsTab(QWidget):
panel_layout.addStretch(1)
scroll = QScrollArea()
self.settings_scroll_area = scroll
scroll.setWidgetResizable(True)
scroll_content = QWidget()
scroll_layout = QHBoxLayout(scroll_content)