#!/usr/bin/env python
# ###########################################################################
#
# 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 Taurus widget based on QLCDNumber
"""
from collections.abc import Sequence
from taurus.core.taurusbasetypes import (
TaurusElementType,
TaurusEventType,
AttrQuality,
TaurusDevState,
)
from taurus.external.qt import Qt
from taurus.qt.qtgui.base import TaurusBaseWidget
from taurus.qt.qtgui.base import TaurusBaseController
from taurus.qt.qtgui.base import TaurusScalarAttributeControllerHelper
from taurus.qt.qtgui.base import TaurusConfigurationControllerHelper
from taurus.qt.qtgui.base import updateLabelBackground
__docformat__ = "restructuredtext"
_QT_PLUGIN_INFO = {
"module": "taurus.qt.qtgui.display",
"group": "Taurus Display",
"icon": "designer:lcdnumber.png",
}
TaurusModelType = TaurusElementType
EventType = TaurusEventType
# -~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~~-~-
# Controller classes for LCD
# -~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~~-~-
class TaurusLCDController(TaurusBaseController):
def _setStyle(self):
TaurusBaseController._setStyle(self)
lcd = self.lcd()
if self.usePalette():
lcd.setFrameShape(Qt.QFrame.Box)
lcd.setFrameShadow(Qt.QFrame.Raised)
lcd.setLineWidth(1)
def lcd(self):
"""Helper method that returns the LCDNumber widget"""
return self.widget()
def _updateForeground(self, lcd):
value = None
if lcd.fgRole == "value":
value = self.getDisplayValue()
elif lcd.fgRole == "w_value":
value = self.getDisplayValue(True)
elif lcd.fgRole in ("", "none"):
value = ""
if value is None:
value = "udef"
lcd.setNumDigits(len(value))
lcd.display(value)
def _needsStateConnection(self):
lcd = self.lcd()
return "state" in (lcd.fgRole, lcd.bgRole)
_updateBackground = updateLabelBackground
class TaurusLCDControllerAttribute(
TaurusScalarAttributeControllerHelper, TaurusLCDController
):
def __init__(self, lcd):
TaurusScalarAttributeControllerHelper.__init__(self)
TaurusLCDController.__init__(self, lcd)
def _getDisplayValue(self, widget, valueObj, idx, write):
try:
if write:
value = valueObj.wvalue.magnitude
else:
value = valueObj.rvalue.magnitude
if idx is not None and len(idx):
for i in idx:
value = value[i]
return widget.displayValue(value)
except Exception:
return widget.getNoneValue()
class TaurusLCDControllerConfiguration(
TaurusConfigurationControllerHelper, TaurusLCDController
):
def __init__(self, lcd):
TaurusConfigurationControllerHelper.__init__(self)
TaurusLCDController.__init__(self, lcd)
# -~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~~-~-
# Design time controllers for LCD
# -~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~~-~-
class TaurusLCDControllerDesignMode(object):
def _updateLength(self, lcd):
lcd.setNumDigits(6)
def getDisplayValue(self, write=False, **kwargs):
v = self.w_value()
if not write:
v = self.value()
return "%6.2f" % v
def value(self):
return 99.99
def w_value(self):
return 0.0
def quality(self):
return AttrQuality.ATTR_VALID
def state(self):
return TaurusDevState.ON
def _updateToolTip(self, lcd):
lcd.setToolTip("Some random value for design purposes only")
class TaurusLCDControllerAttributeDesignMode(
TaurusLCDControllerDesignMode, TaurusLCDControllerAttribute
):
def __init__(self, label):
TaurusLCDControllerDesignMode.__init__(self)
TaurusLCDControllerAttribute.__init__(self, label)
class TaurusLCDControllerConfigurationDesignMode(
TaurusLCDControllerDesignMode, TaurusLCDControllerConfiguration
):
def __init__(self, label):
TaurusLCDControllerDesignMode.__init__(self)
TaurusLCDControllerConfiguration.__init__(self, label)
def getDisplayValue(self, write=False, **kwargs):
return "%6.2f" % -99.99
def _updateToolTip(self, lcd):
lcd.setToolTip(
"Some random configuration value for design purposes only"
)
_CONTROLLER_MAP = {
None: TaurusLCDController,
TaurusModelType.Unknown: TaurusLCDController,
TaurusModelType.Attribute: TaurusLCDControllerAttribute,
TaurusModelType.Configuration: TaurusLCDControllerConfiguration,
}
_DESIGNER_CONTROLLER_MAP = {
None: TaurusLCDControllerAttributeDesignMode,
TaurusModelType.Unknown: TaurusLCDControllerAttributeDesignMode,
TaurusModelType.Attribute: TaurusLCDControllerAttributeDesignMode,
TaurusModelType.Configuration: TaurusLCDControllerConfigurationDesignMode,
}
def Controller(lcd):
ctrl_map = _CONTROLLER_MAP
if lcd._designMode:
ctrl_map = _DESIGNER_CONTROLLER_MAP
model_type = lcd.getModelType()
ctrl_klass = ctrl_map.get(model_type, TaurusLCDController)
return ctrl_klass(lcd)
[docs]
class TaurusLCD(Qt.QLCDNumber, TaurusBaseWidget):
"""A Taurus-enabled :class:`Qt.QLCDNumber` widget. Its text can represent
either the rvalue or wvalue *magnitude* (or nothing), and the background
can colour-code the attribute quality or the device state (or nothing)
"""
DefaultBgRole = "quality"
DefaultFgRole = "value"
DefaultShowText = True
DefaultModelIndex = None
def __init__(self, parent=None, designMode=False):
self._bgRole = self.DefaultBgRole
self._fgRole = self.DefaultFgRole
self._modelIndex = self.DefaultModelIndex
self._modelIndexStr = ""
self._controller = None
name = self.__class__.__name__
self.call__init__wo_kw(Qt.QLCDNumber, 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):
ctrl_map = _CONTROLLER_MAP
if self._designMode:
ctrl_map = _DESIGNER_CONTROLLER_MAP
model_type = self.getModelType()
ctrl_klass = ctrl_map.get(model_type, TaurusLCDController)
return ctrl_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__ == TaurusLCDController:
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):
if evt_type in (TaurusEventType.Change, TaurusEventType.Periodic):
self.emitValueChanged()
ctrl = self.controller()
if ctrl is not None:
ctrl.handleEvent(evt_src, evt_type, evt_value)
[docs]
def isReadOnly(self):
return True
[docs]
def setModel(self, m, **kwargs):
# force to build another controller
self._controller = None
TaurusBaseWidget.setModel(self, m, **kwargs)
# -~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
# QT property definition
# -~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
[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 Exception:
return
if type(mi_value) == int:
mi_value = (mi_value,)
if not isinstance(mi_value, Sequence):
return
self._modelIndex = mi_value
self._modelIndexStr = mi
self.controller().update()
[docs]
def resetModelIndex(self):
self.setModelIndex(self.DefaultModelIndex)
[docs]
def getBgRole(self):
return self._bgRole
[docs]
def setBgRole(self, bgRole):
self._bgRole = str(bgRole).lower()
self.controller().update()
[docs]
def resetBgRole(self):
self.setBgRole(self.DefaultBgRole)
[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]
@classmethod
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>`.
#:
#: **Access functions:**
#:
#: * :meth:`TaurusBaseWidget.getModel`
#: * :meth:`TaurusLCD.setModel`
#: * :meth:`TaurusBaseWidget.resetModel`
#:
#: .. seealso:: :ref:`model-concept`
model = Qt.pyqtProperty(
"QString",
TaurusBaseWidget.getModel,
setModel,
TaurusBaseWidget.resetModel,
)
#: (deprecated))
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:`TaurusLCD.getModelIndex`
#: * :meth:`TaurusLCD.setModelIndex`
#: * :meth:`TaurusLCD.resetModelIndex`
#:
#: .. seealso:: :ref:`model-concept`
modelIndex = Qt.pyqtProperty(
"QString", getModelIndex, setModelIndex, resetModelIndex
)
#: This property holds the foreground role.
#: Valid values are:
#:
#: #. ''/'None' - no value is displayed
#: #. 'value' - the value is displayed
#: #. 'w_value' - the write value is displayed
#:
#: **Access functions:**
#:
#: * :meth:`TaurusLCD.getFgRole`
#: * :meth:`TaurusLCD.setFgRole`
#: * :meth:`TaurusLCD.resetFgRole`
fgRole = Qt.pyqtProperty(
"QString", getFgRole, setFgRole, resetFgRole, doc="foreground role"
)
#: This property holds the background role.
#: Valid values are ''/'None', 'quality', 'state'
#:
#: **Access functions:**
#:
#: * :meth:`TaurusLCD.getBgRole`
#: * :meth:`TaurusLCD.setBgRole`
#: * :meth:`TaurusLCD.resetBgRole`
bgRole = Qt.pyqtProperty(
"QString", getBgRole, setBgRole, resetBgRole, doc="background role"
)
def demo():
"LCD"
from .demo import tauruslcddemo
return tauruslcddemo.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 LCD 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:
label = TaurusLCD()
label.model = model
layout.addWidget(label)
w.show()
if owns_app:
sys.exit(app.exec_())
else:
return w
if __name__ == "__main__":
main()