File: C:/Users/fred/anaconda3/Lib/site-packages/spyder/api/widgets/status.py
# -*- coding: utf-8 -*-
#
# Copyright © Spyder Project Contributors
#
# Licensed under the terms of the MIT License
# (see spyder/__init__.py for details)
"""Status bar widgets."""
# Third party imports
from qtpy import PYQT5
from qtpy.QtCore import Qt, QSize, QTimer, Signal
from qtpy.QtGui import QFont, QIcon
from qtpy.QtWidgets import QHBoxLayout, QLabel, QWidget
# Local imports
from spyder.api.exceptions import SpyderAPIError
from spyder.api.widgets.mixins import SpyderWidgetMixin
from spyder.utils.palette import QStylePalette
from spyder.utils.qthelpers import create_waitspinner
class StatusBarWidget(QWidget, SpyderWidgetMixin):
"""
Base class for status bar widgets.
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
"""
Unique string widget identifier.
"""
CUSTOM_WIDGET_CLASS = None
"""
Custom widget class to add to the default layout.
"""
sig_clicked = Signal()
"""
This signal is emmitted when the widget is clicked.
"""
def __init__(self, parent=None, show_icon=True, show_label=True,
show_spinner=False):
"""
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
* Spinner
Parameters
----------
show_icon: bool
Show an icon in the widget.
show_label: bool
Show a label in the widget.
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``.
"""
if PYQT5:
super().__init__(parent, class_parent=parent)
else:
QWidget.__init__(self, parent)
SpyderWidgetMixin.__init__(self, class_parent=parent)
self._parent = parent
self.show_icon = show_icon
self.show_label = show_label
self.show_spinner = show_spinner
self.value = None
self.label_icon = None
self.label_value = None
self.spinner = None
self.custom_widget = None
self.set_layout()
self.setStyleSheet(self._stylesheet())
def set_layout(self):
"""Set layout for default widgets."""
# Icon
if self.show_icon:
self._icon = self.get_icon()
self._pixmap = None
self._icon_size = QSize(16, 16) # Should this be adjustable?
self.label_icon = QLabel(self)
self.set_icon()
# Label
if self.show_label:
self.label_value = QLabel(self)
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
if self.show_icon:
layout.addWidget(self.label_icon)
if self.show_label:
layout.addWidget(self.label_value)
if self.custom_widget:
layout.addWidget(self.custom_widget)
if self.show_spinner:
layout.addWidget(self.spinner)
layout.addSpacing(0)
layout.setContentsMargins(0, 0, 0, 0)
layout.setAlignment(Qt.AlignVCenter)
# Setup
self.update_tooltip()
# ---- Status bar widget API
def set_icon(self):
"""Set the icon for the status bar widget."""
if self.label_icon:
icon = self._icon
self.label_icon.setVisible(icon is not None)
if icon is not None and isinstance(icon, QIcon):
self._pixmap = icon.pixmap(self._icon_size)
self.label_icon.setPixmap(self._pixmap)
def set_value(self, value):
"""Set formatted text value."""
if self.label_value:
self.value = value
self.label_value.setText(value)
def update_tooltip(self):
"""Update tooltip for widget."""
tooltip = self.get_tooltip()
if tooltip:
if self.label_value:
self.label_value.setToolTip(tooltip)
if self.label_icon:
self.label_icon.setToolTip(tooltip)
self.setToolTip(tooltip)
def mouseReleaseEvent(self, event):
"""Override Qt method to allow for click signal."""
super(StatusBarWidget, self).mousePressEvent(event)
self.sig_clicked.emit()
# ---- API to be defined by user
def get_tooltip(self):
"""Return the widget tooltip text."""
return ''
def get_icon(self):
"""Return the widget tooltip text."""
return None
def _stylesheet(self):
stylesheet = ("QToolTip {{background-color: {background_color};"
"color: {color};"
"border: none}}").format(
background_color=QStylePalette.COLOR_ACCENT_2,
color=QStylePalette.COLOR_TEXT_1
)
return stylesheet
class BaseTimerStatus(StatusBarWidget):
"""
Base class for status bar widgets that update based on timers.
"""
def __init__(self, parent=None):
"""Base class for status bar widgets that update based on timers."""
self.timer = None # Needs to come before parent call
super().__init__(parent)
self._interval = 2000
# Widget setup
fm = self.label_value.fontMetrics()
self.label_value.setMinimumWidth(fm.width('000%'))
# Setup
self.timer = QTimer(self)
self.timer.timeout.connect(self.update_status)
self.timer.start(self._interval)
def closeEvent(self, event):
self.timer.stop()
super().closeEvent(event)
# ---- Qt API
def setVisible(self, value):
"""Override Qt method to stops timers if widget is not visible."""
if self.timer is not None:
if value:
self.timer.start(self._interval)
else:
self.timer.stop()
super(BaseTimerStatus, self).setVisible(value)
# ---- BaseTimerStatus widget API
def update_status(self):
"""Update status label widget, if widget is visible."""
if self.isVisible():
self.label_value.setText(self.get_value())
def set_interval(self, interval):
"""Set timer interval (ms)."""
self._interval = interval
if self.timer is not None:
self.timer.setInterval(interval)
# ---- API to be defined by user
def get_value(self):
"""Return formatted text value."""
raise NotImplementedError