diff --git a/src/jabs/ui/settings_dialog/collapsible_section.py b/src/jabs/ui/settings_dialog/collapsible_section.py index cf5101e0..a1b3b36c 100644 --- a/src/jabs/ui/settings_dialog/collapsible_section.py +++ b/src/jabs/ui/settings_dialog/collapsible_section.py @@ -1,6 +1,9 @@ -from PySide6.QtCore import Signal -from PySide6.QtGui import Qt +from PySide6.QtCore import QSize, Qt, Signal from PySide6.QtWidgets import QFrame, QSizePolicy, QToolButton, QVBoxLayout, QWidget +from qt_material_icons import MaterialIcon + +# Pixel size of the disclosure triangle. +_INDICATOR_SIZE = 18 class CollapsibleSection(QWidget): @@ -16,10 +19,20 @@ class CollapsibleSection(QWidget): def __init__(self, title: str, content: QWidget, parent: QWidget | None = None) -> None: super().__init__(parent) self._content = content + + # Disclosure indicator: a small Material triangle that points to the side when + # collapsed and down when expanded. qt_material_icons renders in the palette + # text color, so it follows the application theme. + self._collapsed_icon = MaterialIcon("arrow_right") + self._expanded_icon = MaterialIcon("arrow_drop_down") + self._toggle_btn = QToolButton(self) self._toggle_btn.setStyleSheet("QToolButton { border: none; }") self._toggle_btn.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon) - self._toggle_btn.setArrowType(Qt.ArrowType.RightArrow) + # Only the Material disclosure icon is shown; never the style's native arrow. + self._toggle_btn.setArrowType(Qt.ArrowType.NoArrow) + self._toggle_btn.setIconSize(QSize(_INDICATOR_SIZE, _INDICATOR_SIZE)) + self._toggle_btn.setIcon(self._collapsed_icon) self._toggle_btn.setText(title) self._toggle_btn.setCheckable(True) self._toggle_btn.setChecked(False) @@ -43,9 +56,7 @@ def __init__(self, title: str, content: QWidget, parent: QWidget | None = None) def _on_toggled(self, checked: bool) -> None: """Handle toggling the collapsible section.""" - self._toggle_btn.setArrowType( - Qt.ArrowType.DownArrow if checked else Qt.ArrowType.RightArrow - ) + self._toggle_btn.setIcon(self._expanded_icon if checked else self._collapsed_icon) self._content.setVisible(checked) self._content.updateGeometry() diff --git a/tests/ui/test_settings_dialog.py b/tests/ui/test_settings_dialog.py index 381885fa..10522638 100644 --- a/tests/ui/test_settings_dialog.py +++ b/tests/ui/test_settings_dialog.py @@ -7,11 +7,13 @@ from jabs.core.enums import ClassifierMode try: - from PySide6.QtWidgets import QApplication + from PySide6.QtCore import Qt + from PySide6.QtWidgets import QApplication, QLabel from jabs.ui.settings_dialog.classifier_mode_settings_group import ( ClassifierModeSettingsGroup, ) + from jabs.ui.settings_dialog.collapsible_section import CollapsibleSection from jabs.ui.settings_dialog.settings_dialog import _OverlapCheckThread SKIP_UI_TESTS = False @@ -81,3 +83,19 @@ def test_classifier_mode_group_roundtrips_enum_not_label() -> None: group.set_values({CLASSIFIER_MODE_KEY: ClassifierMode.BINARY.value}) assert group.get_values() == {CLASSIFIER_MODE_KEY: ClassifierMode.BINARY} + + +def test_collapsible_section_toggles_disclosure_icon() -> None: + """The disclosure indicator swaps between the collapsed and expanded icons.""" + section = CollapsibleSection("More info", QLabel("content")) + + # No native arrow is drawn; only the Material disclosure icon is shown. + assert section._toggle_btn.arrowType() == Qt.ArrowType.NoArrow + collapsed_key = section._toggle_btn.icon().cacheKey() + + section.set_expanded(True) + expanded_key = section._toggle_btn.icon().cacheKey() + assert expanded_key != collapsed_key + + section.set_expanded(False) + assert section._toggle_btn.icon().cacheKey() == collapsed_key