From c6a8c27488553db7edee2e4179c9257c989bc8b7 Mon Sep 17 00:00:00 2001 From: wakonig_k Date: Sun, 5 Jul 2026 19:49:33 +0200 Subject: [PATCH] feat: replace app id with account is status label --- .../containers/main_window/main_window.py | 60 +++++++++++++++---- tests/unit_tests/test_main_widnow.py | 43 +++++++++++-- 2 files changed, 89 insertions(+), 14 deletions(-) diff --git a/bec_widgets/widgets/containers/main_window/main_window.py b/bec_widgets/widgets/containers/main_window/main_window.py index 72468fe1..0e44bfbe 100644 --- a/bec_widgets/widgets/containers/main_window/main_window.py +++ b/bec_widgets/widgets/containers/main_window/main_window.py @@ -78,6 +78,9 @@ class BECMainWindow(BECWidget, QMainWindow): self.bec_dispatcher.connect_slot( self.display_client_message, MessageEndpoints.client_info() ) + self.bec_dispatcher.connect_slot( + self.on_active_account_update, MessageEndpoints.account(), newest_only=True + ) def setCentralWidget(self, widget: QWidget, qt_default: bool = False): # type: ignore[override] """ @@ -121,20 +124,22 @@ class BECMainWindow(BECWidget, QMainWindow): # BEC Specific UI self.display_app_id() + self.display_active_account() def _init_status_bar_widgets(self): """ Prepare the BEC specific widgets in the status bar. """ - # Left: App‑ID label - self._app_id_label = QLabel() - self._app_id_label.setAlignment( + # Left: active-account label + self._account_label = QLabel() + self._account_label.setToolTip("Currently active account") + self._account_label.setAlignment( Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter ) - self.status_bar.addWidget(self._app_id_label) + self.status_bar.addWidget(self._account_label) - # Add a separator after the app ID label + # Add a separator after the account label self._add_separator() # Centre: Client‑info label (stretch=1 so it expands) @@ -379,21 +384,56 @@ class BECMainWindow(BECWidget, QMainWindow): help_menu.addAction(bec_docs) help_menu.addAction(bug_report) + help_menu.addSeparator() + + self._app_id_action = QAction(self) + self._app_id_action.triggered.connect(self._copy_app_id_to_clipboard) + help_menu.addAction(self._app_id_action) + + def _copy_app_id_to_clipboard(self): + """ + Copy the app ID to the clipboard. + """ + cli_server = getattr(self.bec_dispatcher, "cli_server", None) + if cli_server is None: + return + + clipboard = QApplication.clipboard() + clipboard.setText(cli_server.gui_id) ################################################################################ # Status Bar Addons ################################################################################ + def display_active_account(self, account: str | None = None): + """ + Display the active account in the status bar. + """ + if account is None: + account = self.client.active_account + + if not isinstance(account, str) or not account: + account = "-" + + self._account_label.setText(account) + def display_app_id(self): """ - Display the app ID in the status bar. + Display the app ID in the Help menu. """ if self.bec_dispatcher.cli_server is None: - status_message = "Not connected" + action_message = "App ID: Not connected" else: - # Get the server ID from the dispatcher server_id = self.bec_dispatcher.cli_server.gui_id - status_message = f"App ID: {server_id}" - self._app_id_label.setText(status_message) + action_message = f"App ID: {server_id}" + + self._app_id_action.setText(action_message) + + @SafeSlot(dict, dict) + def on_active_account_update(self, msg: dict, meta: dict): + """ + Update the active account label from Redis account messages. + """ + self.display_active_account(msg.get("value")) @SafeSlot(dict, dict) def display_client_message(self, msg: dict, meta: dict): diff --git a/tests/unit_tests/test_main_widnow.py b/tests/unit_tests/test_main_widnow.py index 3382dfc1..491e41d8 100644 --- a/tests/unit_tests/test_main_widnow.py +++ b/tests/unit_tests/test_main_widnow.py @@ -1,7 +1,7 @@ import os import webbrowser from types import SimpleNamespace -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock, PropertyMock, patch import pytest from qtpy.QtCore import QEvent, QPoint, QPointF, QSettings @@ -39,7 +39,7 @@ def test_bec_main_window_initialization(bec_main_window): assert bec_main_window.windowTitle() == "BEC" assert bec_main_window.app is not None assert bec_main_window.statusBar() is not None - assert bec_main_window._app_id_label is not None + assert bec_main_window._account_label is not None def test_bec_main_window_display_client_message(qtbot, bec_main_window): @@ -59,16 +59,51 @@ def test_status_bar_has_separator(bec_main_window): assert separators, "Expected at least one QFrame separator in the status bar." +def test_display_active_account_empty(bec_main_window): + with patch.object( + type(bec_main_window.client), "active_account", new_callable=PropertyMock + ) as mock_account: + mock_account.return_value = "" + bec_main_window.display_active_account() + assert bec_main_window._account_label.text() == "-" + + +def test_display_active_account_connected(bec_main_window): + with patch.object( + type(bec_main_window.client), "active_account", new_callable=PropertyMock + ) as mock_account: + mock_account.return_value = "e12345" + bec_main_window.display_active_account() + assert bec_main_window._account_label.text() == "e12345" + + +def test_on_active_account_update(bec_main_window): + bec_main_window.on_active_account_update({"value": "p12345"}, {}) + assert bec_main_window._account_label.text() == "p12345" + + def test_display_app_id_not_connected(bec_main_window): with patch.object(bec_main_window.bec_dispatcher, "cli_server", None): bec_main_window.display_app_id() - assert bec_main_window._app_id_label.text() == "Not connected" + assert bec_main_window._app_id_action.text() == "App ID: Not connected" def test_display_app_id_connected(bec_main_window): with patch.object(bec_main_window.bec_dispatcher, "cli_server", MagicMock(gui_id="gui_123")): bec_main_window.display_app_id() - assert bec_main_window._app_id_label.text() == "App ID: gui_123" + assert bec_main_window._app_id_action.text() == "App ID: gui_123" + + +def test_copy_app_id_to_clipboard(bec_main_window): + clipboard = MagicMock() + + with ( + patch.object(bec_main_window.bec_dispatcher, "cli_server", MagicMock(gui_id="gui_123")), + patch.object(QApplication, "clipboard", return_value=clipboard), + ): + bec_main_window._copy_app_id_to_clipboard() + + clipboard.setText.assert_called_once_with("gui_123") def test_get_launcher_from_qapp_returns_none_when_absent(bec_main_window):