From 5b28c931d83b6acab4374f558482a0a2135d6528 Mon Sep 17 00:00:00 2001 From: claudi Date: Thu, 29 Jan 2026 08:37:53 +0100 Subject: [PATCH] feat: Add status bar with update status indicator Status bar implementation: - Status bar at bottom of main window - Update status label with emoji support - set_update_status() method for updates: - Checking for updates - Update available - Downloading update - Update failed - Clean status display Test coverage: - 8 new tests for status bar - Test creation and initialization - Test status updates with/without emoji - Test all status states (checking, available, downloading, error) - All 154 tests passing, 86% coverage Enables visual feedback during update operations --- src/webdrop_bridge/ui/main_window.py | 26 ++++++++++- tests/unit/test_main_window.py | 69 ++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 1 deletion(-) diff --git a/src/webdrop_bridge/ui/main_window.py b/src/webdrop_bridge/ui/main_window.py index cb4ff5e..2e0a913 100644 --- a/src/webdrop_bridge/ui/main_window.py +++ b/src/webdrop_bridge/ui/main_window.py @@ -4,7 +4,7 @@ from pathlib import Path from typing import Optional from PySide6.QtCore import QSize, Qt, QUrl, Signal -from PySide6.QtWidgets import QMainWindow, QToolBar, QVBoxLayout, QWidget +from PySide6.QtWidgets import QMainWindow, QToolBar, QVBoxLayout, QWidget, QLabel, QStatusBar from webdrop_bridge.config import Config from webdrop_bridge.core.drag_interceptor import DragInterceptor @@ -208,6 +208,9 @@ class MainWindow(QMainWindow): # Create menu bar self._create_menu_bar() + # Create status bar + self._create_status_bar() + # Create drag interceptor self.drag_interceptor = DragInterceptor() @@ -358,6 +361,27 @@ class MainWindow(QMainWindow): check_updates_action = help_menu.addAction("Check for Updates...") check_updates_action.triggered.connect(self._on_check_for_updates) + def _create_status_bar(self) -> None: + """Create status bar with update status indicator.""" + self.status_bar = self.statusBar() + + # Update status label + self.update_status_label = QLabel("Ready") + self.update_status_label.setStyleSheet("margin-right: 10px;") + self.status_bar.addPermanentWidget(self.update_status_label) + + def set_update_status(self, status: str, emoji: str = "") -> None: + """Update the status bar with update information. + + Args: + status: Status text to display + emoji: Optional emoji prefix (🔄, ✅, ⬇️, ⚠️) + """ + if emoji: + self.update_status_label.setText(f"{emoji} {status}") + else: + self.update_status_label.setText(status) + def _on_check_for_updates(self) -> None: """Handle check for updates menu action. diff --git a/tests/unit/test_main_window.py b/tests/unit/test_main_window.py index 187158a..48b7c97 100644 --- a/tests/unit/test_main_window.py +++ b/tests/unit/test_main_window.py @@ -355,6 +355,75 @@ class TestMainWindowMenuBar: assert callable(window._on_check_for_updates) +class TestMainWindowStatusBar: + """Test status bar and update status.""" + + def test_status_bar_created(self, qtbot, sample_config): + """Test status bar is created.""" + window = MainWindow(sample_config) + qtbot.addWidget(window) + + assert window.statusBar() is not None + assert hasattr(window, "status_bar") + + def test_update_status_label_created(self, qtbot, sample_config): + """Test update status label exists.""" + window = MainWindow(sample_config) + qtbot.addWidget(window) + + assert hasattr(window, "update_status_label") + assert window.update_status_label is not None + + def test_set_update_status_text_only(self, qtbot, sample_config): + """Test setting update status with text only.""" + window = MainWindow(sample_config) + qtbot.addWidget(window) + + window.set_update_status("Checking for updates") + assert "Checking for updates" in window.update_status_label.text() + + def test_set_update_status_with_emoji(self, qtbot, sample_config): + """Test setting update status with emoji.""" + window = MainWindow(sample_config) + qtbot.addWidget(window) + + window.set_update_status("Checking", emoji="🔄") + assert "🔄" in window.update_status_label.text() + assert "Checking" in window.update_status_label.text() + + def test_set_update_status_checking(self, qtbot, sample_config): + """Test checking for updates status.""" + window = MainWindow(sample_config) + qtbot.addWidget(window) + + window.set_update_status("Checking for updates", emoji="🔄") + assert "🔄" in window.update_status_label.text() + + def test_set_update_status_available(self, qtbot, sample_config): + """Test update available status.""" + window = MainWindow(sample_config) + qtbot.addWidget(window) + + window.set_update_status("Update available v0.0.2", emoji="✅") + assert "✅" in window.update_status_label.text() + + def test_set_update_status_downloading(self, qtbot, sample_config): + """Test downloading status.""" + window = MainWindow(sample_config) + qtbot.addWidget(window) + + window.set_update_status("Downloading update", emoji="⬇️") + assert "⬇️" in window.update_status_label.text() + + def test_set_update_status_error(self, qtbot, sample_config): + """Test error status.""" + window = MainWindow(sample_config) + qtbot.addWidget(window) + + window.set_update_status("Update check failed", emoji="⚠️") + assert "⚠️" in window.update_status_label.text() + + class TestMainWindowStylesheet: """Test stylesheet application."""