From e7dc189024796ce31a3be8bdec62cd078f24eac2 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Fri, 5 Mar 2021 22:10:01 -0500 Subject: [PATCH] Statusbar: Add custom widgets to the default layout instead of replacing it That will allow developers to have an icon, label and spinner for their widgets, in case they need them. --- spyder/api/widgets/status.py | 120 +++++++++--------- .../statusbar/widgets/tests/test_status.py | 4 + 2 files changed, 63 insertions(+), 61 deletions(-) diff --git a/spyder/api/widgets/status.py b/spyder/api/widgets/status.py index 2a908a11f10..34d2fbe9be4 100644 --- a/spyder/api/widgets/status.py +++ b/spyder/api/widgets/status.py @@ -23,9 +23,12 @@ class StatusBarWidget(QWidget, SpyderWidgetMixin): """ Base class for status bar widgets. - These widgets consist of an icon, a label and (optionally) a - spinner. However, you can use any QWidget in the status bar by - passing its class to CUSTOM_WIDGET_CLASS. + These widgets consist by default of an icon, a label and a spinner, + which are organized from left to right on that order. + + You can also add any other QWidget to this layout by setting the + CUSTOM_WIDGET_CLASS class attribute. It'll be put between the label + and the spinner. """ ID = None @@ -35,9 +38,7 @@ class StatusBarWidget(QWidget, SpyderWidgetMixin): CUSTOM_WIDGET_CLASS = None """ - Custom widget class to use instead of the default widget layout. - This will completely override the widget API, which won't have - any effect. + Custom widget class to add to the default layout. """ sig_option_changed = Signal(str, object) @@ -52,36 +53,69 @@ class StatusBarWidget(QWidget, SpyderWidgetMixin): """ def __init__(self, parent=None, show_spinner=False): - """Status bar widget base.""" + """ + Base class for status bar widgets. + + These are composed of the following widgets, which are arranged + in a QHBoxLayout from left to right: + + * Icon + * Label + * Custom QWidget (optional) + * Spinner (optional) + + Parameters + ---------- + show_spinner: bool + Show a spinner. + + Notes + ----- + 1. To use an icon, you need to redefine the ``get_icon`` method. + 2. To use a label, you need to call ``set_value``. + """ super().__init__(parent) self._parent = parent self.show_spinner = show_spinner + + self.value = None + self.label_icon = None + self.label_value = None self.spinner = None + self.custom_widget = None - if self.CUSTOM_WIDGET_CLASS: - if not issubclass(self.CUSTOM_WIDGET_CLASS, QWidget): - raise SpyderAPIError( - 'Any custom status widget must subclass QWidget!' - ) - self.custom_widget = self.CUSTOM_WIDGET_CLASS(parent) - self.set_custom_layout() - else: - self.custom_widget = None - self.set_default_layout() + self.set_layout() - def set_default_layout(self): + def set_layout(self): """Set layout for default widgets.""" - # Variables - self.value = None - - # Widget + # Icon self._icon = self.get_icon() self._pixmap = None self._icon_size = QSize(16, 16) # Should this be adjustable? self.label_icon = QLabel() + self.set_icon() + + # Label self.label_value = QLabel() + self.set_value('') + + # See spyder-ide/spyder#9044. + self.text_font = QFont(QFont().defaultFamily(), weight=QFont.Normal) + self.label_value.setAlignment(Qt.AlignRight | Qt.AlignVCenter) + self.label_value.setFont(self.text_font) + + # Custom widget + if self.CUSTOM_WIDGET_CLASS: + if not issubclass(self.CUSTOM_WIDGET_CLASS, QWidget): + raise SpyderAPIError( + 'Any custom status widget must subclass QWidget!' + ) + self.custom_widget = self.CUSTOM_WIDGET_CLASS(self._parent) + + # Spinner if self.show_spinner: self.spinner = create_waitspinner(size=14, parent=self) + self.spinner.hide() # Layout setup layout = QHBoxLayout(self) @@ -89,6 +123,9 @@ def set_default_layout(self): layout.addWidget(self.label_icon) layout.addWidget(self.label_value) + if self.custom_widget: + layout.addWidget(self.custom_widget) + if self.show_spinner: layout.addWidget(self.spinner) self.spinner.hide() @@ -101,45 +138,12 @@ def set_default_layout(self): layout.setContentsMargins(0, 0, 0, 0) layout.setAlignment(Qt.AlignVCenter) - # Widget setup - self.set_icon() - - # See spyder-ide/spyder#9044. - self.text_font = QFont(QFont().defaultFamily(), weight=QFont.Normal) - self.label_value.setAlignment(Qt.AlignRight) - self.label_value.setFont(self.text_font) - # Setup - self.set_value('') self.update_tooltip() - def set_custom_layout(self): - """Set layout for custom widgets.""" - if self.show_spinner: - self.spinner = create_waitspinner(size=14, parent=self) - - layout = QHBoxLayout(self) - layout.setSpacing(0) - layout.addWidget(self.custom_widget) - - if self.show_spinner: - layout.addWidget(self.spinner) - self.spinner.hide() - - if is_dark_interface(): - layout.addSpacing(0) - else: - layout.addSpacing(10) - - layout.setContentsMargins(0, 0, 0, 0) - layout.setAlignment(Qt.AlignVCenter) - # ---- Status bar widget API def set_icon(self): """Set the icon for the status bar widget.""" - if self.custom_widget: - return - icon = self._icon self.label_icon.setVisible(icon is not None) if icon is not None and isinstance(icon, QIcon): @@ -148,17 +152,11 @@ def set_icon(self): def set_value(self, value): """Set formatted text value.""" - if self.custom_widget: - return - self.value = value self.label_value.setText(value) def update_tooltip(self): """Update tooltip for widget.""" - if self.custom_widget: - return - tooltip = self.get_tooltip() if tooltip: self.label_value.setToolTip(tooltip) diff --git a/spyder/plugins/statusbar/widgets/tests/test_status.py b/spyder/plugins/statusbar/widgets/tests/test_status.py index 01608414a1a..db3da55d88e 100644 --- a/spyder/plugins/statusbar/widgets/tests/test_status.py +++ b/spyder/plugins/statusbar/widgets/tests/test_status.py @@ -69,6 +69,9 @@ class CustomStatusBarWidget(StatusBarWidget): ID = 'custom_status' CUSTOM_WIDGET_CLASS = MyComboBox + def get_icon(self): + return self.create_icon('environment') + def test_status_bar_widget_signal(status_bar, qtbot): plugin, window = status_bar @@ -92,6 +95,7 @@ def test_custom_widget(status_bar, qtbot): # Add widget to status bar w = CustomStatusBarWidget(window) + w.set_value('Options: ') plugin.add_status_widget(w) # qtbot.stop()