#!/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 set of basic Taurus widgets based on QLabel"""
__all__ = ["TaurusLabel"]
__docformat__ = 'restructuredtext'
import operator
import re
# shame of me for importing PyTango!
import PyTango
from taurus.core.taurusbasetypes import TaurusElementType, TaurusEventType
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
_QT_PLUGIN_INFO = {
'module': 'taurus.qt.qtgui.display',
'group': 'Taurus Display',
'icon': "designer:label.png",
}
TaurusModelType = TaurusElementType
EventType = TaurusEventType
class TaurusLabelController(TaurusBaseController):
StyleSheetTemplate = "border-style: outset; border-width: 2px; border-color: {0}; {1}"
def __init__(self, label):
self._text = ''
self._trimmedText = False
self._trimPattern = re.compile('<[^<]*>')
TaurusBaseController.__init__(self, label)
def _setStyle(self):
TaurusBaseController._setStyle(self)
label = self.label()
# if update as palette
if self.usePalette():
label.setFrameShape(Qt.QFrame.Box)
label.setFrameShadow(Qt.QFrame.Raised)
label.setLineWidth(1)
def label(self):
return self.widget()
def showValueDialog(self, label):
Qt.QMessageBox.about(label, "Full text", self._text)
def _needsStateConnection(self):
label = self.label()
ret = 'state' in (label.fgRole, label.bgRole)
return ret
def _updateForeground(self, label):
fgRole, value = label.fgRole, ''
# handle special cases (that are not covered with fragment)
if fgRole.lower() == 'state':
value = self.state().name
elif fgRole.lower() in ('', 'none'):
pass
else:
value = label.getDisplayValue(fragmentName=fgRole)
self._text = text = label.prefixText + value + label.suffixText
# Checks that the display fits in the widget and sets it to "..." if
# it does not fit the widget
self._trimmedText = self._shouldTrim(label, text)
if self._trimmedText:
text = "<a href='...'>...</a>"
label.setText(text)
def _shouldTrim(self, label, text):
if not label.autoTrim:
return False
text = re.sub(self._trimPattern, '', text)
font_metrics = Qt.QFontMetrics(label.font())
size, textSize = label.size().width(), font_metrics.width(text)
return textSize > size
def _updateToolTip(self, label):
if not label.getAutoTooltip():
return
toolTip = label.getFormatedToolTip()
if self._trimmedText:
toolTip = u"<p><b>Value:</b> %s</p><hr>%s" %\
(unicode(self._text, errors='replace'),
unicode(str(toolTip), errors='replace'))
label.setToolTip(toolTip)
_updateBackground = updateLabelBackground
class TaurusLabelControllerAttribute(TaurusScalarAttributeControllerHelper, TaurusLabelController):
def __init__(self, label):
TaurusScalarAttributeControllerHelper.__init__(self)
TaurusLabelController.__init__(self, label)
def _setStyle(self):
TaurusLabelController._setStyle(self)
label = self.label()
label.setDynamicTextInteractionFlags(
Qt.Qt.TextSelectableByMouse | Qt.Qt.LinksAccessibleByMouse)
class TaurusLabelControllerConfiguration(TaurusConfigurationControllerHelper, TaurusLabelController):
def __init__(self, label):
TaurusConfigurationControllerHelper.__init__(self)
TaurusLabelController.__init__(self, label)
def _setStyle(self):
TaurusLabelController._setStyle(self)
label = self.label()
label.setDynamicTextInteractionFlags(Qt.Qt.NoTextInteraction)
#-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
# Design time controllers for label
#-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
class TaurusLabelControllerDesignMode(object):
def _updateLength(self, lcd):
lcd.setNumDigits(6)
def getDisplayValue(self, write=False):
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 PyTango.AttrQuality.ATTR_VALID
def state(self):
return PyTango.DevState.ON
def _updateToolTip(self, lcd):
lcd.setToolTip("Some random value for design purposes only")
class TaurusLabelControllerAttributeDesignMode(TaurusLabelControllerDesignMode, TaurusLabelControllerAttribute):
def __init__(self, label):
TaurusLabelControllerDesignMode.__init__(self)
TaurusLabelControllerAttribute.__init__(self, label)
class TaurusLabelControllerConfigurationDesignMode(TaurusLabelControllerDesignMode, TaurusLabelControllerConfiguration):
def __init__(self, label):
TaurusLabelControllerDesignMode.__init__(self)
TaurusLabelControllerConfiguration.__init__(self, label)
def getDisplayValue(self, write=False):
return "%6.2f" % -99.99
def _updateToolTip(self, lcd):
lcd.setToolTip(
"Some random configuration value for design purposes only")
_CONTROLLER_MAP = {
None: None,
TaurusModelType.Unknown: None,
TaurusModelType.Attribute: TaurusLabelControllerAttribute,
TaurusModelType.Configuration: TaurusLabelControllerConfiguration,
}
_DESIGNER_CONTROLLER_MAP = {
None: TaurusLabelControllerAttributeDesignMode,
TaurusModelType.Unknown: TaurusLabelControllerAttributeDesignMode,
TaurusModelType.Attribute: TaurusLabelControllerAttributeDesignMode,
TaurusModelType.Configuration: TaurusLabelControllerConfigurationDesignMode,
}
[docs]class TaurusLabel(Qt.QLabel, TaurusBaseWidget):
DefaultPrefix = ''
DefaultSuffix = ''
DefaultBgRole = 'quality'
DefaultFgRole = 'rvalue'
DefaultShowText = True
DefaultModelIndex = None
DefaultAutoTrim = True
DefaultAlignment = Qt.Qt.AlignRight | Qt.Qt.AlignVCenter
_deprecatedRoles = dict(value='rvalue', w_value='wvalue')
def __init__(self, parent=None, designMode=False):
self._prefix = self.DefaultPrefix
self._suffix = self.DefaultSuffix
self._bgRole = self.DefaultBgRole
self._fgRole = self.DefaultFgRole
self._modelIndex = self.DefaultModelIndex
self._autoTrim = self.DefaultAutoTrim
self._modelIndexStr = ''
self._controller = None
self._dynamicTextInteractionFlags = True
name = self.__class__.__name__
self.call__init__wo_kw(Qt.QLabel, parent)
self.call__init__(TaurusBaseWidget, name, designMode=designMode)
self.setAlignment(self.DefaultAlignment)
self.linkActivated.connect(self.showValueDialog)
# if we are in design mode there will be no events so we force the
# creation of a controller object
if self._designMode:
self.controllerUpdate()
def _calculate_controller_class(self):
ctrl_map = _CONTROLLER_MAP
if self._designMode:
ctrl_map = _DESIGNER_CONTROLLER_MAP
model_type = self.getModelType()
# ugly workaround to adapt TaurusLabel to tep14 without refactoring
# TODO: proper refactoring of TaurusValue to supress the Conf API
if model_type == TaurusModelType.Attribute and self.modelFragmentName:
model_type = TaurusModelType.Configuration
ctrl_klass = ctrl_map.get(model_type, TaurusLabelController)
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__ == TaurusLabelController:
return ctrl
# if there is a controller object and it is still the same class...
ctrl_klass = self._calculate_controller_class()
if ctrl_klass is None:
return None
elif ctrl.__class__ == ctrl_klass:
return ctrl
self._controller = ctrl = ctrl_klass(self)
return ctrl
[docs] def controllerUpdate(self):
ctrl = self.controller()
if ctrl is not None:
ctrl.update()
[docs] def showValueDialog(self, *args):
ctrl = self.controller()
if ctrl is not None:
ctrl.showValueDialog(self)
[docs] def resizeEvent(self, event):
# # recheck the display every time we resize to make sure the text should
# # become trimmed or not
if not getattr(self, '_inResize', False):
self._inResize = True
self.controllerUpdate()
self._inResize = False
Qt.QLabel.resizeEvent(self, event)
#-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
# TaurusBaseWidget overwriting
#-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
[docs] def handleEvent(self, evt_src, evt_type, evt_value):
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):
# force to build another controller
self._controller = None
TaurusBaseWidget.setModel(self, m)
if self.modelFragmentName:
self.setFgRole(self.modelFragmentName)
#-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
# 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:
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.controllerUpdate()
[docs] def getModelMimeData(self):
mimeData = TaurusBaseWidget.getModelMimeData(self)
mimeData.setText(self.text())
return mimeData
[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.controllerUpdate()
[docs] def resetBgRole(self):
self.setBgRole(self.DefaultBgRole)
[docs] def getFgRole(self):
return self._fgRole
[docs] def setFgRole(self, fgRole):
# warn about deprecated roles
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.controllerUpdate()
[docs] def resetFgRole(self):
self.setFgRole(self.DefaultFgRole)
[docs] def getPrefixText(self):
return self._prefix
[docs] def setPrefixText(self, prefix):
self._prefix = str(prefix)
self.controllerUpdate()
[docs] def resetPrefixText(self):
self.setPrefixText(self.DefaultPrefix)
[docs] def getSuffixText(self):
return self._suffix
[docs] def setSuffixText(self, suffix):
self._suffix = str(suffix)
self.controllerUpdate()
[docs] def resetSuffixText(self):
self.setSuffixText(self.DefaultSuffix)
[docs] def setAutoTrim(self, trim):
self._autoTrim = trim
self.controllerUpdate()
[docs] def setDynamicTextInteractionFlags(self, flags):
if self.hasDynamicTextInteractionFlags():
Qt.QLabel.setTextInteractionFlags(self, flags)
[docs] def hasDynamicTextInteractionFlags(self):
return self._dynamicTextInteractionFlags
[docs] def setTextInteractionFlags(self, flags):
Qt.QLabel.setTextInteractionFlags(self, flags)
self._dynamicTextInteractionFlags = False
[docs] def resetTextInteractionFlags(self):
Qt.QLabel.resetTextInteractionFlags(self)
self.dynamicTextInteractionFlags = True
[docs] def getAutoTrim(self):
return self._autoTrim
[docs] def resetAutoTrim(self):
self.setAutoTrim(self.DefaultAutoTrim)
@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:`TaurusLabel.getModelIndex`
#: * :meth:`TaurusLabel.setModelIndex`
#: * :meth:`TaurusLabel.resetModelIndex`
#:
#: .. seealso:: :ref:`model-concept`
modelIndex = Qt.pyqtProperty(
"QString", getModelIndex, setModelIndex, resetModelIndex)
#: This property holds a prefix text
#:
#: **Access functions:**
#:
#: * :meth:`TaurusLabel.getPrefixText`
#: * :meth:`TaurusLabel.setPrefixText`
#: * :meth:`TaurusLabel.resetPrefixText`
prefixText = Qt.pyqtProperty("QString", getPrefixText, setPrefixText,
resetPrefixText, doc="prefix text")
#: This property holds a suffix text
#:
#: **Access functions:**
#:
#: * :meth:`TaurusLabel.getSuffixText`
#: * :meth:`TaurusLabel.setSuffixText`
#: * :meth:`TaurusLabel.resetSuffixText`
suffixText = Qt.pyqtProperty("QString", getSuffixText, setSuffixText,
resetSuffixText, doc="suffix text")
#: This property holds the foreground role (the text).
#: Valid values are:
#:
#: #. ''/'None' - no value is displayed
#: #. 'value' - the value is displayed
#: #. 'w_value' - the write value is displayed
#: #. 'quality' - the quality is displayed
#: #. 'state' - the device state is displayed
#:
#: **Access functions:**
#:
#: * :meth:`TaurusLabel.getFgRole`
#: * :meth:`TaurusLabel.setFgRole`
#: * :meth:`TaurusLabel.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:`TaurusLabel.getBgRole`
#: * :meth:`TaurusLabel.setBgRole`
#: * :meth:`TaurusLabel.resetBgRole`
bgRole = Qt.pyqtProperty("QString", getBgRole, setBgRole,
resetBgRole, doc="background role")
#: This property holds the
#:
#: **Access functions:**
#:
#: * :meth:`TaurusLabel.getAutoTrim`
#: * :meth:`TaurusLabel.setAutoTrim`
#: * :meth:`TaurusLabel.resetAutoTrim`
autoTrim = Qt.pyqtProperty("bool", getAutoTrim, setAutoTrim,
resetAutoTrim, doc="auto trim text")
#: This property holds the
#:
#: **Access functions:**
#:
#: * :meth:`TaurusLabel.isDragEnabled`
#: * :meth:`TaurusLabel.setDragEnabled`
#: * :meth:`TaurusLabel.resetDragEnabled`
dragEnabled = Qt.pyqtProperty("bool", TaurusBaseWidget.isDragEnabled,
TaurusBaseWidget.setDragEnabled,
TaurusBaseWidget.resetDragEnabled,
doc="enable dragging")
#: Specifies how the label should interact with user input if it displays
#: text.
#:
#: **Access functions:**
#:
#: * :meth:`TaurusLabel.textInteractionFlags`
#: * :meth:`TaurusLabel.setTextInteractionFlags`
#: * :meth:`TaurusLabel.resetTextInteractionFlags
try:
textInteractionFlags = Qt.pyqtProperty(Qt.Qt.TextInteractionFlag,
Qt.QLabel.textInteractionFlags,
setTextInteractionFlags,
resetTextInteractionFlags,
doc="Specifies how the label should interact with user input if it displays text.")
except TypeError: # Old PyQt4 version only accept strings for the type arg
textInteractionFlags = Qt.pyqtProperty("int",
Qt.QLabel.textInteractionFlags,
setTextInteractionFlags,
resetTextInteractionFlags,
doc="Specifies how the label should interact with user input if it displays text.")
def demo():
"Label"
import demo.tauruslabeldemo
return demo.tauruslabeldemo.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 label 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 = TaurusLabel()
label.model = model
layout.addWidget(label)
w.show()
if owns_app:
sys.exit(app.exec_())
else:
return w
if __name__ == '__main__':
main()