From 810f9938306117431f369be3df5c53cd5338269a Mon Sep 17 00:00:00 2001 From: Joppe Blondel Date: Sun, 26 Jul 2026 14:39:27 +0200 Subject: [PATCH] Panel and Toolbar enable/disable items in View menu --- src/bedit_gui/application.py | 3 ++ .../controllers/view_menu_controller.py | 49 +++++++++++++++++++ tests/unit/test_view_menu_controller.py | 38 ++++++++++++++ 3 files changed, 90 insertions(+) create mode 100644 src/bedit_gui/controllers/view_menu_controller.py create mode 100644 tests/unit/test_view_menu_controller.py diff --git a/src/bedit_gui/application.py b/src/bedit_gui/application.py index ed36c68..588b270 100644 --- a/src/bedit_gui/application.py +++ b/src/bedit_gui/application.py @@ -1,10 +1,12 @@ from __future__ import annotations + import sys from PySide6.QtWidgets import QApplication from bedit_gui.controllers.document_controller import DocumentController from bedit_gui.controllers.undo_controller import UndoController +from bedit_gui.controllers.view_menu_controller import ViewMenuController from bedit_gui.controllers.window_state_controller import WindowStateController from bedit_gui.documents import Document from bedit_gui.views.main_window import MainWindow @@ -20,6 +22,7 @@ def main() -> int: window = MainWindow() DocumentController(document, window) UndoController(document, window) + ViewMenuController(window) window_state_controller = WindowStateController(app, window) window_state_controller.restore() window.showMaximized() diff --git a/src/bedit_gui/controllers/view_menu_controller.py b/src/bedit_gui/controllers/view_menu_controller.py new file mode 100644 index 0000000..7589438 --- /dev/null +++ b/src/bedit_gui/controllers/view_menu_controller.py @@ -0,0 +1,49 @@ +from __future__ import annotations + +import re + +from PySide6.QtCore import QObject +from PySide6.QtWidgets import QDockWidget, QMenu, QToolBar + +from bedit_gui.views.main_window import MainWindow + + +class ViewMenuController(QObject): + """Populate View submenus with synchronized visibility actions.""" + + def __init__(self, window: MainWindow) -> None: + super().__init__(window) + + self.panels_menu = QMenu("Panels", window.ui.menuView) + self.toolbars_menu = QMenu("Toolbars", window.ui.menuView) + + window.ui.actionPanels.setMenu(self.panels_menu) + window.ui.actionToolbars.setMenu(self.toolbars_menu) + + self._populate( + self.panels_menu, + window.findChildren(QDockWidget), + ) + self._populate( + self.toolbars_menu, + window.findChildren(QToolBar), + ) + + def _populate( + self, + menu: QMenu, + widgets: list[QDockWidget] | list[QToolBar], + ) -> None: + for widget in sorted(widgets, key=self._label): + action = widget.toggleViewAction() + action.setText(self._label(widget)) + menu.addAction(action) + + @staticmethod + def _label(widget: QDockWidget | QToolBar) -> str: + title = widget.windowTitle().strip() + if title and title.lower() != "toolbar": + return title + + name = re.sub(r"(DockWidget|Widget|ToolBar)$", "", widget.objectName()) + return re.sub(r"(? QApplication: + return QApplication.instance() or QApplication([]) + + +@pytest.mark.unit +def test_view_submenus_contain_visibility_actions( + qt_app: QApplication, +) -> None: + window = MainWindow() + controller = ViewMenuController(window) + + assert window.ui.actionPanels.menu() is controller.panels_menu + assert window.ui.actionToolbars.menu() is controller.toolbars_menu + assert [action.text() for action in controller.panels_menu.actions()] == [ + "Document Tree", + "Log", + ] + assert [action.text() for action in controller.toolbars_menu.actions()] == [ + "File", + "Undo", + ] + assert all( + action.isCheckable() + for action in ( + controller.panels_menu.actions() + + controller.toolbars_menu.actions() + ) + )