class ResetMode(enum.Enum):
    All = "all"
    Ranges = "ranges" class MainGroupCti(GroupCti):
    """ Read only config Tree Item that only stores None.
        To be used as a high level group (e.g. the inspector group)
        Is the same as a groupCti but drawn as light text on a dark grey back ground
    """
    _backgroundBrush = QtGui.QBrush(QtGui.QColor("#606060")) # create only once
    _foregroundBrush = QtGui.QBrush(QtGui.QColor(Qt.white)) # create only once
    _font = QtGui.QFont()
    _font.setWeight(QtGui.QFont.Bold)

    def __init__(self, nodeName, defaultData=None):
        """ Constructor. For the parameters see the AbstractCti constructor documentation.
        """
        super(MainGroupCti, self).__init__(nodeName, defaultData, expanded=True) # always expand


    @property
    def font(self):
        """ Returns a font for displaying this item's text in the tree.
        """
        return self._font


    @property
    def backgroundBrush(self):
        """ Returns a (dark gray) brush for drawing the background role in the tree.
        """
        return self._backgroundBrush


    @property
    def foregroundBrush(self):
        """ Returns a (white) brush for drawing the foreground role in the tree.
        """
        return self._foregroundBrush


    def resetRangesToDefault(self):
        """ Resets range settings to the default data.

            The base implementation does nothing. Descendants should override
        """
        pass DEBUGGING = ('-d' in sys.argv or '--debug' in sys.argv) API_PYSIDE2 = 'pyside2'
API_PYQT5 = 'pyqt5'
ALL_API = [API_PYQT5, API_PYSIDE2]
QT_API_NAME = os.environ.get('QT_API')
    QT_API_NAME = None
        QT_API_NAME = API_PYQT5
        QT_API_NAME = API_PYSIDE2
        QT_API_NAME = API_PYQT5
        QT_API_NAME = API_PYSIDE2 def type_name(var):
    """ Returns the name of the type of var"""
    return type(var).__name__ def check_class(obj, target_class, allow_none = False):
    """ Checks that the  obj is a (sub)type of target_class.
        Raises a TypeError if this is not the case.

        :param obj: object whos type is to be checked
        :type obj: any type
        :param target_class: target type/class
        :type target_class: any class or type
        :param allow_none: if true obj may be None
        :type allow_none: boolean
    """
    if not isinstance(obj, target_class):
        if not (allow_none and obj is None):
            raise TypeError("obj must be a of type {}, got: {}"
                            .format(target_class, type(obj))) DOCK_SPACING = 0 DOCK_MARGIN  = 0 class MessageDisplay(BasePanel):
    """ Widget that shows a label and title.
        Consists of a title label and a larger message label for details.
    """
    def __init__(self, parent=None, msg="", title="Error"):
        super(MessageDisplay, self).__init__(parent=parent)

        self.layout = QtWidgets.QVBoxLayout()
        self.setLayout(self.layout)

        self.titleLabel = QtWidgets.QLabel(title)
        self.titleLabel.setTextFormat(Qt.PlainText)
        self.titleLabel.setTextInteractionFlags(Qt.TextSelectableByMouse)
        self.titleLabel.setAlignment(Qt.AlignHCenter)
        self.layout.addWidget(self.titleLabel, stretch=0)

        font = QtGui.QFont()
        font.setFamily(MONO_FONT)
        font.setFixedPitch(True)
        font.setPointSize(FONT_SIZE)

        self.messageLabel = QtWidgets.QLabel(msg)
        self.messageLabel.setFont(font)
        self.messageLabel.setTextFormat(Qt.PlainText)
        self.messageLabel.setTextInteractionFlags(Qt.TextSelectableByMouse)
        self.messageLabel.setWordWrap(True)
        self.messageLabel.setAlignment(Qt.AlignTop)
        self.messageLabel.setFrameStyle(QtWidgets.QFrame.Panel | QtWidgets.QFrame.Plain)
        self.layout.addWidget(self.messageLabel, stretch=1)


    def setError(self, msg=None, title=None):
        """ Shows and error message
        """
        if msg is not None:
            self.messageLabel.setText(msg)

        if title is not None:
            self.titleLabel.setText(title) class BasePanel(QtWidgets.QFrame):
    """ Base panel from which others are derived.

        Define shape
    """
    def __init__(self, **kwargs):
        super(BasePanel, self).__init__(**kwargs)
        #self.setFrameShape(QtWidgets.QFrame.StyledPanel)
        #self.setFrameShadow(QtWidgets.QFrame.Sunken)
import logging
from argos.config.abstractcti import ResetMode
from argos.config.groupcti import MainGroupCti
from argos.info import DEBUGGING
from argos.qt import QtWidgets, QtSignal
from argos.utils.cls import type_name, check_class
from argos.widgets.constants import DOCK_SPACING, DOCK_MARGIN
from argos.widgets.display import MessageDisplay
from argos.widgets.misc import BasePanel
# -*- coding: utf-8 -*-

# This file is part of Argos.
#
# Argos is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Argos is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Argos. If not, see <http://www.gnu.org/licenses/>.

""" Base class for inspectors
"""


logger = logging.getLogger(__name__)

class InvalidDataError(Exception):
    """ Exception that should be raised if the inspector cannot handle this type of data.
        Can be used to distuingish the situation from other exceptions an then, for example,
        draw an empty plot instead of the error message pane.
    """
    pass


class UpdateReason(object):
    """ Enumeration class that contains the reason for updating the inspector contents.
    """
    NEW_MAIN_WINDOW     = "new main window"
    INSPECTOR_CHANGED   = "inspector changed"
    RTI_CHANGED         = "repo tree item changed"
    COLLECTOR_COMBO_BOX = "collector combobox changed"
    COLLECTOR_SPIN_BOX  = "collector spinbox changed"
    CONFIG_CHANGED      = "config changed"

    __VALID_REASONS = (NEW_MAIN_WINDOW, INSPECTOR_CHANGED, RTI_CHANGED,
                       COLLECTOR_COMBO_BOX, COLLECTOR_SPIN_BOX, CONFIG_CHANGED)


    @classmethod
    def validReasons(cls):
        """ Returns a tuple with all valid reasond
        """
        return cls.__VALID_REASONS


    @classmethod
    def checkValid(cls, reason):
        """ Raises ValueError if the reason is not one of the valid enumerations
        """
        if reason not in cls.__VALID_REASONS:
            raise ValueError("reason must be one of {}, got {}".format(cls.__VALID_REASONS, reason))



class AbstractInspector(QtWidgets.QStackedWidget):
    """ Abstract base class for inspectors.
        An inspector is a stacked widget; it has a contents page and and error page.
    """
    _fullName = "base" # see the fullName() class method for explanation
    ERROR_PAGE_IDX = 0
    CONTENTS_PAGE_IDX = 1

    sigShowMessage = QtSignal(str)
    sigUpdateFailed = QtSignal()  # Emitted when updateContents fails and displays the error tab

    def __init__(self, collector, parent=None):
        """ Constructor.

            When subclassing the AbstractInspector try to minimize the work done in the constructor.
            Place all functionality that may raise an exception in updateContents or clearContents,
            these functions will show an error page and prevent the application from aborting. If
            an exception occurs in the constructor it is not caught!

            :param collector: the data collector from where this inspector gets its data
            :param parent: parent widget.
        """

        super(AbstractInspector, self).__init__(parent)

        self.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)

        self._config = MainGroupCti(nodeName='inspector') # Is typically redefined.
        self._collector = collector

        self.errorWidget = MessageDisplay()
        self.addWidget(self.errorWidget)

        self.contentsWidget = BasePanel()
        self.addWidget(self.contentsWidget)

        self.contentsLayout = QtWidgets.QBoxLayout(QtWidgets.QBoxLayout.TopToBottom)
        self.contentsLayout.setSpacing(DOCK_SPACING)

        self.contentsLayout.setContentsMargins(DOCK_MARGIN, DOCK_MARGIN, DOCK_MARGIN, DOCK_MARGIN)