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

#!/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, ""
        if fgRole == 'value':
            value += self.getDisplayValue()
        elif fgRole == 'w_value':
            value += self.getDisplayValue(True)
        elif fgRole == 'state':
            stateObj = self.stateObj()
            value += stateObj and stateObj.getDisplayValue() or label.getNoneValue()
        elif fgRole == 'quality':
            quality = self.quality()
            if quality is None:
                value += label.getNoneValue()
            else:
                value += str(quality)
        elif fgRole in ('', 'none'):
            pass
        else:
            label.setText("undef")
            return
        
        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(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 = 'value' DefaultShowText = True DefaultModelIndex = None DefaultAutoTrim = True DefaultAlignment = Qt.Qt.AlignRight | Qt.Qt.AlignVCenter 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.connect(self, Qt.SIGNAL("linkActivated (const QString &)"), 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() 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)
#-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~- # 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): self._fgRole = str(fgRole).lower() 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) or full configuration_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()