# -*- coding: utf-8 -*- # pylint: disable=too-few-public-methods """Common widgets and their bases.""" __all__ = ['IconButton'] import typing from qtpy import QtWidgets, QtCore from anaconda_navigator.static import images from anaconda_navigator import widgets if typing.TYPE_CHECKING: import typing_extensions class IconButton(QtWidgets.QPushButton): """Common control for icon-only buttons.""" class WarningIcon(QtWidgets.QLabel): """ Icon with exclamation sign. Used by :class:`~WarningLabel` and its derivatives. """ class ErrorIcon(QtWidgets.QLabel): """ Icon with exclamation sign in circle. """ class InfoIcon(QtWidgets.QLabel): """ Icon with exclamation sign in circle. """ class LabelWithIcon(QtWidgets.QFrame): """ Combined label with icon at the beginning. Icon is shown only when the main text is not empty. """ sig_button_clicked = QtCore.Signal() def __init__( # pylint: disable=too-many-arguments self, icon: typing.Optional[widgets.QLabel] = None, text: str = '', tooltip: str = '', button: str = '', alignment: typing.Any = QtCore.Qt.AlignTop, ) -> None: """Initialize new :class:`~WarningLabel` instance.""" super().__init__() self.__icon: 'typing_extensions.Final[widgets.QLabel]' = icon self.__icon.setVisible(bool(text)) self.__content: 'typing_extensions.Final[widgets.LabelBase]' = widgets.LabelBase() self.__content.setText(text) self.__content.setToolTip(tooltip) self.__content.setWordWrap(True) self.__button: 'typing_extensions.Final[widgets.LabelBase]' = widgets.LabelBase() self.__button.setText(button) self.__button.sig_clicked.connect(self.sig_button_clicked) self.__layout: 'typing_extensions.Final[QtWidgets.QHBoxLayout]' = QtWidgets.QHBoxLayout() self.__layout.addWidget(self.__icon, 0, alignment) self.__layout.addWidget(self.__content, 1, alignment) if button: self.__layout.addWidget(self.__button, 0, alignment) self.__layout.setContentsMargins(0, 0, 0, 0) self.__layout.setSpacing(4) self.setLayout(self.__layout) @property def text(self) -> str: # noqa: D401 """Content of the main label.""" return self.__content.text() @text.setter def text(self, value: str) -> None: """Update `text` value.""" self.__content.setText(value) self.__icon.setVisible(bool(value)) class WarningLabel(LabelWithIcon): """ Combined label with warning icon at the beginning. Icon is shown only when the main text is not empty. """ def __init__( self, text: str = '', tooltip: str = '', button: str = '', alignment: typing.Any = QtCore.Qt.AlignTop, ) -> None: """Initialize new :class:`~WarningLabel` instance.""" super().__init__(icon=WarningIcon(), text=text, tooltip=tooltip, button=button, alignment=alignment) class WarningBlock(WarningLabel): """Same as :class:`~WarningLabel`, but with colored background.""" def __init__( self, text: str = '', tooltip: str = '', button: str = '', alignment: typing.Any = QtCore.Qt.AlignTop, ) -> None: """Initialize new :class:`~WarningBlock` instance.""" super().__init__(text=text, tooltip=tooltip, button=button, alignment=alignment) class ErrorLabel(LabelWithIcon): """ Combined label with error icon at the beginning. Icon is shown only when the main text is not empty. """ def __init__( self, text: str = '', tooltip: str = '', button: str = '', alignment: typing.Any = QtCore.Qt.AlignTop, ) -> None: """Initialize new :class:`~ErrorLabel` instance.""" super().__init__(icon=ErrorIcon(), text=text, tooltip=tooltip, button=button, alignment=alignment) class ErrorBlock(ErrorLabel): """Same as :class:`~ErrorLabel`, but with colored background.""" def __init__( self, text: str = '', tooltip: str = '', button: str = '', alignment: typing.Any = QtCore.Qt.AlignTop, ) -> None: """Initialize new :class:`~ErrorBlock` instance.""" super().__init__(text=text, tooltip=tooltip, button=button, alignment=alignment) class InfoLabel(LabelWithIcon): """ Combined label with info icon at the beginning. Icon is shown only when the main text is not empty. """ def __init__( self, text: str = '', tooltip: str = '', button: str = '', alignment: typing.Any = QtCore.Qt.AlignTop, ) -> None: """Initialize new :class:`~InfoLabel` instance.""" super().__init__(icon=InfoIcon(), text=text, tooltip=tooltip, button=button, alignment=alignment) class InfoBlock(InfoLabel): """Same as :class:`~InfoLabel`, but with colored background.""" def __init__( self, text: str = '', tooltip: str = '', button: str = '', alignment: typing.Any = QtCore.Qt.AlignTop, ) -> None: """Initialize new :class:`~InfoBlock` instance.""" super().__init__(text=text, tooltip=tooltip, button=button, alignment=alignment) class TeamEditionServerAlert(QtWidgets.QWidget): """Show combined labels with icon about connectivity problems to TE Server.""" def __init__(self) -> None: super().__init__() self.error_label: 'typing_extensions.Final[ErrorBlock]' = ErrorBlock( text=( 'Anaconda Anaconda Server server cannot be reached. ' 'Some actions may not work as expected until connection is restored.' ), alignment=QtCore.Qt.AlignVCenter, ) self.info_label: 'typing_extensions.Final[InfoBlock]' = InfoBlock( text='Connection to Anaconda Anaconda Server server restored.', button=f'', alignment=QtCore.Qt.AlignVCenter, ) self.__timer: 'typing_extensions.Final[QtCore.QTimer]' = QtCore.QTimer() layout: 'typing_extensions.Final[QtWidgets.QVBoxLayout]' = QtWidgets.QVBoxLayout() layout.addWidget(self.error_label) layout.addWidget(self.info_label) self.info_label.sig_button_clicked.connect(self.hide_all) self.setLayout(layout) self.hide_all() def show_info(self, limit: typing.Optional[int] = 5000) -> None: """Show info label for `limit` seconds""" if not self.error_label.isVisible(): self.error_label.hide() return self.show() self.error_label.hide() self.info_label.show() if limit: self.__timer.singleShot(limit, self.hide_all) def show_error(self) -> None: """Show error label""" self.show() self.error_label.show() self.info_label.hide() def hide_all(self) -> None: """Hide all labels.""" self.hide() self.error_label.hide() self.info_label.hide()