#!/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
# Shame on me!!!!
import PyTango
State = PyTango.DevState
DataFormat = PyTango.AttrDataFormat
Quality = PyTango.AttrQuality
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 = {
Quality.ATTR_ALARM : ( True, "orange", False),
Quality.ATTR_CHANGING : ( True, "blue", False),
Quality.ATTR_INVALID : ( True, "red", False),
Quality.ATTR_VALID : ( True, "green", False),
Quality.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 valueObj(self):
modelObj = self.modelObj()
if modelObj is None: return None
return modelObj.getValueObj()
def value(self):
widget, obj = self.widget(), self.valueObj()
fgRole = widget.fgRole
value = None
if fgRole == 'value':
value = obj.value
elif fgRole == 'w_value':
value = obj.w_value
elif fgRole == 'quality':
return obj.quality
# handle 1D and 2D values
if obj.data_format == DataFormat.SCALAR: 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 = { State.ON : ( True, "green", False),
State.OFF : ( False, "black", False),
State.CLOSE : ( True, "white", False),
State.OPEN : ( True, "green", False),
State.INSERT : ( True, "green", False),
State.EXTRACT : ( True, "green", False),
State.MOVING : ( True, "blue", False),
State.STANDBY : ( True, "yellow", False),
State.FAULT : ( True, "red", False),
State.INIT : ( True, "yellow", False),
State.RUNNING : ( True, "blue", False),
State.ALARM : ( True, "orange", False),
State.DISABLE : ( True, "magenta", False),
State.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 = 'value'
DefaultOnColor = "green"
DefaultOffColor = "black"
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.isState():
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):
self._fgRole = str(fgRole).lower()
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) or full configuration_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()