mirror of
https://github.com/LorenEteval/Furious.git
synced 2026-10-12 09:18:26 +03:00
Make combo boxes fit translated content
Signed-off-by: Loren Eteval <loren.eteval@proton.me>
This commit is contained in:
@@ -295,6 +295,7 @@ class NetworkStateBadge(Mixins.QTranslatable, Mixins.ThemeAware, QFrame):
|
||||
"""Publish size constraints for the current responsive presentation."""
|
||||
if self._profileDetailsVisible:
|
||||
requiredWidth = self.widthWithProfile()
|
||||
|
||||
self.setMinimumWidth(requiredWidth)
|
||||
self.setMaximumWidth(requiredWidth)
|
||||
else:
|
||||
@@ -751,8 +752,8 @@ class HomePage(Mixins.QTranslatable, QMainWindow):
|
||||
|
||||
self.searchButton = SearchButton()
|
||||
self.subscriptionFilterComboBox = AppQComboBox()
|
||||
self.subscriptionFilterComboBox.setContentWidthAdjustable()
|
||||
self.subscriptionFilterComboBox.setMinimumWidth(190)
|
||||
self.subscriptionFilterComboBox.setMaximumWidth(300)
|
||||
self.subscriptionFilterComboBox.setSizePolicy(
|
||||
QSizePolicy.Policy.Preferred,
|
||||
QSizePolicy.Policy.Fixed,
|
||||
|
||||
@@ -156,6 +156,7 @@ class LogPage(Mixins.QTranslatable, QMainWindow):
|
||||
# metadata, so LogPage rebuilds this application-styled selector with
|
||||
# the correct per-category translation policy.
|
||||
self.filterComboBox = AppQComboBox(translatable=False)
|
||||
self.filterComboBox.setContentWidthAdjustable()
|
||||
self.filterComboBox.setMinimumWidth(180)
|
||||
|
||||
self.textBrowser = DraculaTextBrowser(
|
||||
|
||||
@@ -94,12 +94,12 @@ class _TrafficMetricsCard(QFrame):
|
||||
AppQLabel(_('Granularity'), parent=self),
|
||||
)
|
||||
|
||||
self.timeRangeComboBox, self.granularityComboBox = (
|
||||
AppQComboBox(parent=self),
|
||||
AppQComboBox(parent=self),
|
||||
)
|
||||
|
||||
self.timeRangeComboBox = AppQComboBox(parent=self)
|
||||
self.timeRangeComboBox.setContentWidthAdjustable()
|
||||
self.timeRangeComboBox.setMinimumWidth(160)
|
||||
|
||||
self.granularityComboBox = AppQComboBox(parent=self)
|
||||
self.granularityComboBox.setContentWidthAdjustable()
|
||||
self.granularityComboBox.setMinimumWidth(130)
|
||||
|
||||
self.downloadTitleLabel, self.uploadTitleLabel = (
|
||||
|
||||
@@ -469,6 +469,7 @@ class _ApplicationThemeSettingsCard(_SettingsCard):
|
||||
"""Initialize the translated application-theme selector."""
|
||||
self.comboBox = AppQComboBox()
|
||||
self.comboBox.setObjectName('SettingsComboBox')
|
||||
self.comboBox.setContentWidthAdjustable()
|
||||
self.comboBox.setMinimumWidth(260)
|
||||
|
||||
for label, preference in self.Options:
|
||||
@@ -522,6 +523,7 @@ class _SystemProxySettingsCard(_SettingsCard):
|
||||
"""Initialize the translated system-proxy mode selector."""
|
||||
self.comboBox = AppQComboBox()
|
||||
self.comboBox.setObjectName('SettingsComboBox')
|
||||
self.comboBox.setContentWidthAdjustable()
|
||||
self.comboBox.setMinimumWidth(260)
|
||||
|
||||
for label, mode in self.Options:
|
||||
|
||||
@@ -84,22 +84,32 @@ class _SubscriptionEditorDialog(AppQTransientDialog):
|
||||
|
||||
subscription = dict(subscription or {})
|
||||
|
||||
self.remarkEdit = AppQLineEdit(subscription.get('remark', ''))
|
||||
self.urlEdit = AppQLineEdit(subscription.get('webURL', ''))
|
||||
self.enabledSwitch = AppQSwitch()
|
||||
self.enabledSwitch.syncChecked(subscription.get('enabled', True))
|
||||
self.autoUpdateComboBox = AppQComboBox()
|
||||
self.proxyComboBox = AppQComboBox()
|
||||
self.userAgentEdit = AppQLineEdit(subscription.get('userAgent', ''))
|
||||
self.filterEdit = AppQLineEdit(subscription.get('filter', ''))
|
||||
(
|
||||
self.remarkEdit,
|
||||
self.urlEdit,
|
||||
self.enabledSwitch,
|
||||
self.autoUpdateComboBox,
|
||||
self.proxyComboBox,
|
||||
self.userAgentEdit,
|
||||
self.filterEdit,
|
||||
) = (
|
||||
AppQLineEdit(subscription.get('remark', '')),
|
||||
AppQLineEdit(subscription.get('webURL', '')),
|
||||
AppQSwitch(),
|
||||
AppQComboBox(),
|
||||
AppQComboBox(),
|
||||
AppQLineEdit(subscription.get('userAgent', '')),
|
||||
AppQLineEdit(subscription.get('filter', '')),
|
||||
)
|
||||
|
||||
self.remarkEdit.setMinimumWidth(240)
|
||||
self.remarkEdit.setMaximumWidth(360)
|
||||
self.urlEdit.setMinimumWidth(420)
|
||||
self.enabledSwitch.syncChecked(subscription.get('enabled', True))
|
||||
self.autoUpdateComboBox.setMinimumWidth(220)
|
||||
self.autoUpdateComboBox.setMaximumWidth(320)
|
||||
self.autoUpdateComboBox.setContentWidthAdjustable()
|
||||
self.proxyComboBox.setMinimumWidth(220)
|
||||
self.proxyComboBox.setMaximumWidth(320)
|
||||
self.proxyComboBox.setContentWidthAdjustable()
|
||||
self.userAgentEdit.setMinimumWidth(260)
|
||||
self.filterEdit.setMinimumWidth(260)
|
||||
|
||||
@@ -109,8 +119,10 @@ class _SubscriptionEditorDialog(AppQTransientDialog):
|
||||
for value in SubscriptionTableView.ProxyOptions:
|
||||
self.proxyComboBox.addItem(_(value), value)
|
||||
|
||||
autoIndex = self.autoUpdateComboBox.findData(subscription.get('autoupdate', ''))
|
||||
proxyIndex = self.proxyComboBox.findData(subscription.get('proxy', ''))
|
||||
autoIndex, proxyIndex = (
|
||||
self.autoUpdateComboBox.findData(subscription.get('autoupdate', '')),
|
||||
self.proxyComboBox.findData(subscription.get('proxy', '')),
|
||||
)
|
||||
|
||||
self.autoUpdateComboBox.setCurrentIndex(max(autoIndex, 0))
|
||||
self.proxyComboBox.setCurrentIndex(max(proxyIndex, 0))
|
||||
@@ -236,20 +248,35 @@ class SubscriptionPage(Mixins.QTranslatable, Mixins.ThemeAware, QMainWindow):
|
||||
super().__init__(parent)
|
||||
|
||||
self.setObjectName('SubscriptionPage')
|
||||
|
||||
self.serverTable = serverTable
|
||||
|
||||
self.pageTitleLabel = AppQLabel(_('Subscriptions'))
|
||||
self.pageTitleLabel.setObjectName('SubscriptionPageTitle')
|
||||
|
||||
self.proxyLabel = AppQLabel(_('Update Using'))
|
||||
|
||||
self.proxyComboBox = AppQComboBox()
|
||||
self.proxyComboBox.setContentWidthAdjustable()
|
||||
self.proxyComboBox.setMinimumWidth(160)
|
||||
|
||||
self.addButton = AppQPushButton(_('Add'))
|
||||
self.editButton = AppQPushButton(_('Edit'))
|
||||
self.deleteButton = AppQPushButton(_('Delete'))
|
||||
self.copyURLButton = AppQPushButton(_('Copy URL'))
|
||||
self.viewProfilesButton = AppQPushButton(_('View Profiles'))
|
||||
self.updateSelectedButton = AppQPushButton(_('Update Selected'))
|
||||
self.updateAllButton = AppQPushButton(_('Update All'))
|
||||
(
|
||||
self.addButton,
|
||||
self.editButton,
|
||||
self.deleteButton,
|
||||
self.copyURLButton,
|
||||
self.viewProfilesButton,
|
||||
self.updateSelectedButton,
|
||||
self.updateAllButton,
|
||||
) = (
|
||||
AppQPushButton(_('Add')),
|
||||
AppQPushButton(_('Edit')),
|
||||
AppQPushButton(_('Delete')),
|
||||
AppQPushButton(_('Copy URL')),
|
||||
AppQPushButton(_('View Profiles')),
|
||||
AppQPushButton(_('Update Selected')),
|
||||
AppQPushButton(_('Update All')),
|
||||
)
|
||||
|
||||
self.table = SubscriptionTableView(
|
||||
deleteUniqueCallback=self._deleteProfilesForSubscription,
|
||||
|
||||
@@ -55,10 +55,17 @@ from Furious.Controllers.ConnectionController import (
|
||||
ConnectionState,
|
||||
)
|
||||
from Furious.Controllers.SettingsController import (
|
||||
APPLICATION_THEME_SETTING,
|
||||
LOG_AUTO_CLEAR_SETTING,
|
||||
LOG_AUTO_SCROLL_DOWN_SETTING,
|
||||
)
|
||||
from Furious.Frozenlib import APPLICATION_NAME, AppSettings, Mixins
|
||||
from Furious.Frozenlib import (
|
||||
APPLICATION_NAME,
|
||||
AppBuiltinProxyMode,
|
||||
ApplicationTheme,
|
||||
AppSettings,
|
||||
Mixins,
|
||||
)
|
||||
from Furious.Models import ProfileMetadata, Protocol, ServerProfile
|
||||
from Furious.Plugins.API import RoutingOption
|
||||
from Furious.Qt import (
|
||||
@@ -76,13 +83,23 @@ from Furious.Service import (
|
||||
LogManager,
|
||||
)
|
||||
from Furious.Window.LogPage import LogPage
|
||||
from Furious.Window.SettingsPage import (
|
||||
_ApplicationThemeSettingsCard,
|
||||
_SystemProxySettingsCard,
|
||||
)
|
||||
from Furious.Window.SubscriptionPage import _SubscriptionEditorDialog
|
||||
from Furious.Widget.ConnectionButton import ConnectionButton
|
||||
from Furious.Widget.RoutingSelector import RoutingSelector
|
||||
|
||||
from PySide6 import QtCore
|
||||
from PySide6.QtTest import QTest
|
||||
from PySide6.QtWidgets import QHBoxLayout, QWidget
|
||||
from PySide6.QtWidgets import (
|
||||
QComboBox,
|
||||
QHBoxLayout,
|
||||
QStyle,
|
||||
QStyleOptionComboBox,
|
||||
QWidget,
|
||||
)
|
||||
|
||||
from tests.support import (
|
||||
application,
|
||||
@@ -144,6 +161,22 @@ class ComboTranslationLayoutTest(unittest.TestCase):
|
||||
"""Finish deferred widget deletion between tests."""
|
||||
collectAtBoundary()
|
||||
|
||||
def assertCurrentComboTextFits(self, comboBox):
|
||||
"""Assert the styled combo edit field can display its current text."""
|
||||
option = QStyleOptionComboBox()
|
||||
comboBox.initStyleOption(option)
|
||||
textRect = comboBox.style().subControlRect(
|
||||
QStyle.ComplexControl.CC_ComboBox,
|
||||
option,
|
||||
QStyle.SubControl.SC_ComboBoxEditField,
|
||||
comboBox,
|
||||
)
|
||||
|
||||
self.assertGreaterEqual(
|
||||
textRect.width(),
|
||||
comboBox.fontMetrics().horizontalAdvance(comboBox.currentText()),
|
||||
)
|
||||
|
||||
def testContentAwareComboRefreshesHintWithoutChangingSemanticData(self):
|
||||
"""Grow for longer translated text while retaining item identity."""
|
||||
parent = QWidget()
|
||||
@@ -223,6 +256,64 @@ class ComboTranslationLayoutTest(unittest.TestCase):
|
||||
parent.close()
|
||||
parent.deleteLater()
|
||||
|
||||
def testTranslatedSettingsChoicesResizeWithoutChangingSemanticValues(self):
|
||||
"""Resize translated Settings choices without applying fake changes."""
|
||||
cases = (
|
||||
(
|
||||
_ApplicationThemeSettingsCard,
|
||||
APPLICATION_THEME_SETTING,
|
||||
ApplicationTheme.System.value,
|
||||
'Follow System Appearance',
|
||||
'setApplicationTheme',
|
||||
),
|
||||
(
|
||||
_SystemProxySettingsCard,
|
||||
'SystemProxyMode',
|
||||
AppBuiltinProxyMode.Auto.value,
|
||||
'Automatically Configure System Proxy',
|
||||
'setSystemProxyMode',
|
||||
),
|
||||
)
|
||||
|
||||
with isolatedSettings(), mock.patch(
|
||||
'Furious.Window.SettingsPage.AppSettingsController'
|
||||
) as controllerFactory:
|
||||
for cardType, settingName, semanticValue, sourceText, callbackName in cases:
|
||||
AppSettings.set('Language', 'EN')
|
||||
AppSettings.set(settingName, semanticValue)
|
||||
parent = QWidget()
|
||||
layout = QHBoxLayout(parent)
|
||||
card = cardType(parent=parent)
|
||||
layout.addWidget(card)
|
||||
parent.resize(1800, 120)
|
||||
parent.show()
|
||||
processQtEvents()
|
||||
|
||||
comboBox = card.comboBox
|
||||
callback = getattr(controllerFactory.return_value, callbackName)
|
||||
indexChanges = []
|
||||
comboBox.currentIndexChanged.connect(indexChanges.append)
|
||||
|
||||
self.assertEqual(
|
||||
comboBox.sizeAdjustPolicy(),
|
||||
QComboBox.SizeAdjustPolicy.AdjustToContents,
|
||||
)
|
||||
|
||||
for language in ('EN', 'ZH', 'RU'):
|
||||
AppSettings.set('Language', language)
|
||||
comboBox.retranslate()
|
||||
processQtEvents()
|
||||
|
||||
self.assertEqual(comboBox.currentData(), semanticValue)
|
||||
self.assertEqual(comboBox.currentText(), _(sourceText, language))
|
||||
self.assertCurrentComboTextFits(comboBox)
|
||||
|
||||
callback.assert_not_called()
|
||||
self.assertEqual(indexChanges, [])
|
||||
|
||||
parent.close()
|
||||
parent.deleteLater()
|
||||
|
||||
|
||||
class EditorMappingTest(unittest.TestCase):
|
||||
"""Verify editor fields preserve structured configuration semantics."""
|
||||
|
||||
Reference in New Issue
Block a user