Source code for taurus.qt.qtgui.display.taurusled

#!/usr/bin/env python
# -*- coding: utf-8 -*-

#############################################################################
##
# This file is part of Taurus
##
# http://taurus-scada.org
##
# Copyright 2011 CELLS / ALBA Synchrotron, Bellaterra, Spain
##
# Taurus is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
##
# Taurus 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 Lesser General Public License for more details.
##
# You should have received a copy of the GNU Lesser General Public License
# along with Taurus.  If not, see <http://www.gnu.org/licenses/>.
##
#############################################################################

"""This module provides a set of basic Taurus widgets based on QLed"""

__all__ = ["TaurusLed"]

__docformat__ = 'restructuredtext'

import weakref
import operator

from taurus.external.qt import Qt

from taurus.core import DataFormat, AttrQuality, DataType
from taurus.core.tango import DevState

from taurus.qt.qtgui.base import TaurusBaseWidget
from qled import QLed

_QT_PLUGIN_INFO = {
    'module': 'taurus.qt.qtgui.display',
    'group': 'Taurus Display',
    'icon': "designer:ledgreen.png",
}


class _TaurusLedController(object):

    #            key     status,     color, inTrouble
    LedMap = {True: (True,    "green",    False),
              False: (False,    "black",    False),
              None: (False,    "black",     True)}

    LedQualityMap = {
        AttrQuality.ATTR_ALARM: (True,   "orange",    False),
        AttrQuality.ATTR_CHANGING: (True,     "blue",    False),
        AttrQuality.ATTR_INVALID: (True,      "red",    False),
        AttrQuality.ATTR_VALID: (True,    "green",    False),
        AttrQuality.ATTR_WARNING: (True,   "orange",    False),
        None: (False,    "black",     True)}

    def __init__(self, widget):
        self._widget = weakref.ref(widget)

    def widget(self):
        return self._widget()

    def modelObj(self):
        return self.widget().getModelObj()

    def value(self):
        widget, obj = self.widget(), self.modelObj()
        fgRole = widget.fgRole
        value = None
        if fgRole == 'rvalue':
            value = obj.rvalue
        elif fgRole == 'wvalue':
            value = obj.wvalue
        elif fgRole == 'quality':
            return obj.quality

        # handle 1D and 2D values
        if obj.data_format == DataFormat._0D:
            return value

        idx = widget.getModelIndexValue()
        if idx is None or len(idx) == 0:
            return value

        for i in idx:
            value = value[i]
        return value

    def usePreferedColor(self, widget):
        return True

    def handleEvent(self, evt_src, evt_type, evt_value):
        self.update()

    def update(self):
        widget = self.widget()

        self._updateDisplay(widget)
        self._updateToolTip(widget)

    def _updateDisplay(self, widget):
        key = None
        try:
            key = self.value()
        except Exception:
            pass
        ledMap = self.LedMap
        if widget.fgRole == 'quality':
            ledMap = self.LedQualityMap
        try:
            status, color, trouble = ledMap[key]
        except:
            status, color, trouble = False, "red", True
        if self.usePreferedColor(widget):
            if status:
                color = widget.onColor
            else:
                color = widget.offColor
        widget.ledStatus = status
        widget.ledColor = color
        if trouble:
            widget.setAutoFillBackground(True)
            bg_brush = Qt.QBrush(Qt.Qt.BDiagPattern)
            palette = widget.palette()
            palette.setBrush(Qt.QPalette.Window, bg_brush)
            palette.setBrush(Qt.QPalette.Base, bg_brush)
            widget.setPalette(palette)
        else:
            widget.setAutoFillBackground(False)

    def _updateToolTip(self, widget):
        widget.setToolTip(widget.getFormatedToolTip())


class _TaurusLedControllerBool(_TaurusLedController):

    def usePreferedColor(self, widget):
        # use prefered widget color if representing the boolean read or write
        # value. If representing the quality, use the quality map
        return widget.fgRole != 'quality'


class _TaurusLedControllerState(_TaurusLedController):

    #                key      status,       color, inTrouble
    LedMap = {DevState.ON: (True,    "green",    False),
              DevState.OFF: (False,    "black",    False),
              DevState.CLOSE: (True,    "white",    False),
              DevState.OPEN: (True,    "green",    False),
              DevState.INSERT: (True,    "green",    False),
              DevState.EXTRACT: (True,    "green",    False),
              DevState.MOVING: (True,     "blue",    False),
              DevState.STANDBY: (True,   "yellow",    False),
              DevState.FAULT: (True,      "red",    False),
              DevState.INIT: (True,   "yellow",    False),
              DevState.RUNNING: (True,     "blue",    False),
              DevState.ALARM: (True,   "orange",    False),
              DevState.DISABLE: (True,  "magenta",    False),
              DevState.UNKNOWN: (False,    "black",    False),
              None: (False,    "black",     True)}

    def usePreferedColor(self, widget):
        # never use prefered widget color. Use always the map
        return False


class _TaurusLedControllerDesignMode(_TaurusLedController):

    def _updateDisplay(self, widget):
        widget.ledStatus = True
        if widget.ledStatus:
            widget.ledColor = widget.onColor
        else:
            widget.ledColor = widget.offColor
        widget.setAutoFillBackground(False)

    def _updateToolTip(self, widget):
        widget.setToolTip("Design mode TaurusLed")


[docs]class TaurusLed(QLed, TaurusBaseWidget): """A widget designed to represent with a LED image the state of a device, the value of a boolean attribute or the quality of an attribute.""" DefaultModelIndex = None DefaultFgRole = 'rvalue' DefaultOnColor = "green" DefaultOffColor = "black" _deprecatedRoles = dict(value='rvalue', w_value='wvalue') def __init__(self, parent=None, designMode=False): name = self.__class__.__name__ self._designMode = designMode self._modelIndex = self.DefaultModelIndex self._modelIndexStr = '' self._fgRole = self.DefaultFgRole self._onColor = self.DefaultOnColor self._offColor = self.DefaultOffColor self._controller = None self.call__init__wo_kw(QLed, parent) self.call__init__(TaurusBaseWidget, name, designMode=designMode) # if we are in design mode there will be no events so we force the # creation of a controller object if self._designMode: self.controller().update() def _calculate_controller_class(self): model = self.getModelObj() klass = _TaurusLedController if self._designMode: klass = _TaurusLedControllerDesignMode elif model is None: klass = _TaurusLedController elif model.isBoolean(): klass = _TaurusLedControllerBool elif model.type == DataType.DevState: klass = _TaurusLedControllerState return klass
[docs] def controller(self): ctrl = self._controller # if there is a controller object and it is not the base controller... if ctrl is not None and not ctrl.__class__ == _TaurusLedController: return ctrl # if there is a controller object and it is still the same class... ctrl_klass = self._calculate_controller_class() if ctrl is not None and ctrl.__class__ == ctrl_klass: return ctrl self._controller = ctrl = ctrl_klass(self) return ctrl
#-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~- # TaurusBaseWidget overwriting #-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
[docs] def handleEvent(self, evt_src, evt_type, evt_value): self.controller().handleEvent(evt_src, evt_type, evt_value)
[docs] def isReadOnly(self): return True
[docs] def setModel(self, m): # force to build another controller self._controller = None TaurusBaseWidget.setModel(self, m)
#-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~- # QT property definition #-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
[docs] def getFgRole(self): return self._fgRole
[docs] def setFgRole(self, fgRole): role = self._deprecatedRoles.get(fgRole, fgRole) if fgRole != role: self.deprecated(rel='4.0', dep='setFgRole(%s)' % fgRole, alt='setFgRole(%s)' % role) self._fgRole = str(role) self.controller().update()
[docs] def resetFgRole(self): self.setFgRole(self.DefaultFgRole)
[docs] def getOnColor(self): """Returns the preferred led on color :return: led on color :rtype: str""" return self._onColor
[docs] def setOnColor(self, color): """Sets the preferred led on color :param status: the new on color :type status: str""" color = str(color).lower() if not self.isLedColorValid(color): raise Exception("Invalid color '%s'" % color) self._onColor = color self.controller().update()
[docs] def resetOnColor(self): """Resets the preferred led on color""" self.setOnColor(self.DefaultOnColor)
[docs] def getOffColor(self): """Returns the preferred led off color :return: led off color :rtype: str""" return self._offColor
[docs] def setOffColor(self, color): """Sets the preferred led off color :param status: the new off color :type status: str""" color = str(color).lower() if not self.isLedColorValid(color): raise Exception("Invalid color '%s'" % color) self._offColor = color self.controller().update()
[docs] def resetOffColor(self): """Resets the preferred led color""" self.setOffColor(self.DefaultOffColor)
[docs] def getModelIndexValue(self): return self._modelIndex
[docs] def getModelIndex(self): return self._modelIndexStr
[docs] def setModelIndex(self, modelIndex): mi = str(modelIndex) if len(mi) == 0: self._modelIndex = None else: try: mi_value = eval(str(mi)) except: return if type(mi_value) == int: mi_value = mi_value, if not operator.isSequenceType(mi_value): return self._modelIndex = mi_value self._modelIndexStr = mi self.controller().update()
[docs] def resetModelIndex(self): self.setModelIndex(self.DefaultModelIndex)
@classmethod
[docs] def getQtDesignerPluginInfo(cls): d = TaurusBaseWidget.getQtDesignerPluginInfo() d.update(_QT_PLUGIN_INFO) return d
#: This property holds the unique URI string representing the model name #: with which this widget will get its data from. The convention used for #: the string can be found :ref:`here <model-concept>`. #: #: In case the property :attr:`useParentModel` is set to True, the model #: text must start with a '/' followed by the attribute name. #: #: **Access functions:** #: #: * :meth:`TaurusBaseWidget.getModel` #: * :meth:`TaurusLabel.setModel` #: * :meth:`TaurusBaseWidget.resetModel` #: #: .. seealso:: :ref:`model-concept` model = Qt.pyqtProperty("QString", TaurusBaseWidget.getModel, setModel, TaurusBaseWidget.resetModel) #: This property holds whether or not this widget should search in the #: widget hierarchy for a model prefix in a parent widget. #: #: **Access functions:** #: #: * :meth:`TaurusBaseWidget.getUseParentModel` #: * :meth:`TaurusBaseWidget.setUseParentModel` #: * :meth:`TaurusBaseWidget.resetUseParentModel` #: #: .. seealso:: :ref:`model-concept` useParentModel = Qt.pyqtProperty("bool", TaurusBaseWidget.getUseParentModel, TaurusBaseWidget.setUseParentModel, TaurusBaseWidget.resetUseParentModel) #: This property holds the index inside the model value that should be #: displayed #: #: **Access functions:** #: #: * :meth:`TaurusLed.getModelIndex` #: * :meth:`TaurusLed.setModelIndex` #: * :meth:`TaurusLed.resetModelIndex` #: #: .. seealso:: :ref:`model-concept` modelIndex = Qt.pyqtProperty("QString", getModelIndex, setModelIndex, resetModelIndex) #: This property holds the foreground role. #: Valid values are: #: #: #. 'value' - the value is used #: #. 'w_value' - the write value is used #: #. 'quality' - the quality is used #: #: **Access functions:** #: #: * :meth:`TaurusLed.getFgRole` #: * :meth:`TaurusLed.setFgRole` #: * :meth:`TaurusLed.resetFgRole` fgRole = Qt.pyqtProperty("QString", getFgRole, setFgRole, resetFgRole, doc="foreground role") #: This property holds the preferred led color #: This value is used for the cases where the model value does not contain #: enough information to distinguish between different On colors. #: For example, a bool attribute, when it is False it is displayed with the #: off led but when it is true it may be displayed On in any color. The #: prefered color would be used in this case. #: #: **Access functions:** #: #: * :meth:`TaurusLed.getOnColor` #: * :meth:`TaurusLed.setOnColor` #: * :meth:`TaurusLed.resetOnColor` onColor = Qt.pyqtProperty("QString", getOnColor, setOnColor, resetOnColor, doc="preferred led On color") #: This property holds the preferred led color #: This value is used for the cases where the model value does not contain #: enough information to distinguish between different Off colors. #: For example, a bool attribute, when it is False it is displayed with the #: off led but when it is true it may be displayed On in any color. The #: prefered color would be used in this case. #: #: **Access functions:** #: #: * :meth:`TaurusLed.getOffColor` #: * :meth:`TaurusLed.setOffColor` #: * :meth:`TaurusLed.resetOffColor` offColor = Qt.pyqtProperty("QString", getOffColor, setOffColor, resetOffColor, doc="preferred led Off color")
def demo(): "Led" import demo.taurusleddemo return demo.taurusleddemo.main() def main(): import sys import taurus.qt.qtgui.application Application = taurus.qt.qtgui.application.TaurusApplication app = Application.instance() owns_app = app is None if owns_app: import taurus.core.util.argparse parser = taurus.core.util.argparse.get_taurus_parser() parser.usage = "%prog [options] <full_attribute_name(s)>" app = Application(sys.argv, cmd_line_parser=parser, app_name="Taurus led demo", app_version="1.0", org_domain="Taurus", org_name="Tango community") args = app.get_command_line_args() if len(args) == 0: w = demo() else: models = map(str.lower, args) w = Qt.QWidget() layout = Qt.QGridLayout() w.setLayout(layout) for model in models: led = TaurusLed() led.model = model layout.addWidget(led) w.show() if owns_app: sys.exit(app.exec_()) else: return w if __name__ == '__main__': main()