Skip to content

Commit

Permalink
Statusbar: Add custom widgets to the default layout instead of replac…
Browse files Browse the repository at this point in the history
…ing it

That will allow developers to have an icon, label and spinner for their
widgets, in case they need them.
  • Loading branch information
ccordoba12 committed Mar 6, 2021
1 parent 7c4b050 commit e7dc189
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 61 deletions.
120 changes: 59 additions & 61 deletions spyder/api/widgets/status.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -52,43 +53,79 @@ 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)
layout.setSpacing(0) # Reduce space between icon and label
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()
Expand All @@ -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):
Expand All @@ -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)
Expand Down
4 changes: 4 additions & 0 deletions spyder/plugins/statusbar/widgets/tests/test_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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()

Expand Down

0 comments on commit e7dc189

Please sign in to comment.