#!/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 the set of base class taurus controllers.
"""
import weakref
from taurus.external.qt import Qt
from taurus.core.taurusbasetypes import DataFormat, TaurusEventType
from taurus.qt.qtgui.util import QT_ATTRIBUTE_QUALITY_PALETTE
from taurus.qt.qtgui.util import QT_DEVICE_STATE_PALETTE
__docformat__ = "restructuredtext"
[docs]
class TaurusBaseController(object):
"""Base class for all taurus controllers"""
def __init__(self, widget, updateAsPalette=True):
self._widget = weakref.ref(widget)
self._updateAsPalette = updateAsPalette
self._stateObj = None
self._last_value = None
self._last_config_value = None
self._last_error_value = None
self._setStyle()
def _setStyle(self):
pass
[docs]
def usePalette(self):
return self._updateAsPalette
[docs]
def modelObj(self):
return self.widget().getModelObj()
attrObj = configObj = deviceObj = modelObj
[docs]
def valueObj(self):
value = self._last_value
if value is None:
modelObj = self.modelObj()
if modelObj is None:
return None
value = modelObj.getValueObj()
return value
[docs]
def value(self):
valueObj = self.valueObj()
return getattr(valueObj, "value", None)
[docs]
def w_value(self): # TODO: adapt to tep14
valueObj = self.valueObj()
return getattr(valueObj, "w_value", None)
[docs]
def quality(self):
valueObj = self.valueObj()
return getattr(valueObj, "quality", None)
[docs]
def state(self):
return self._stateObj.state
[docs]
def getDisplayValue(self, write=False, **kwargs):
return self.widget().getDisplayValue(**kwargs)
[docs]
def handleEvent(self, evt_src, evt_type, evt_value):
# update the "_last" values only if the event source is the model
# (it could be the background...)
if evt_src == self.modelObj():
if evt_type in (TaurusEventType.Change, TaurusEventType.Periodic):
if self._last_value is None:
# reset the format so that it gets updated by displayValue
self.widget().resetFormat()
self._last_value = evt_value
elif evt_type == TaurusEventType.Config: # TODO: adapt to tep14
self._last_config_value = evt_value
self.widget().resetFormat()
else:
self._last_error_value = evt_value
# In case of error, modify the last_value as well
try:
self._last_value = self.modelObj().getValueObj()
except Exception:
self._last_value = None
self.update()
[docs]
def eventReceived(self, evt_src, evt_type, evt_value):
# should handle the state event here. Because this is invoked by a
# random thread, we pass it to the widget, which will forward to the
# proper thread
# @todo: sometimes we get this method called but self.widget() is None.
# Check why. For the moment I just protect it by substituting
# the following line by the ones after it
# self.widget().eventReceived(evt_src, evt_type, evt_value)
w = self.widget()
if w is not None:
w.eventReceived(evt_src, evt_type, evt_value)
[docs]
def update(self):
widget = self.widget()
self._updateConnections(widget)
self._updateForeground(widget)
self._updateBackground(widget)
self._updateToolTip(widget)
def _needsStateConnection(self):
return False
def _updateConnections(self, widget):
stateObj, newStateObj = self._stateObj, None
if self._needsStateConnection():
newStateObj = self.deviceObj()
if stateObj != newStateObj:
if stateObj is not None:
stateObj.removeListener(self)
if newStateObj is not None:
newStateObj.addListener(self)
else:
if stateObj is not None:
stateObj.removeListener(self)
self._stateObj = newStateObj
def _updateForeground(self, widget):
pass
def _updateBackground(self, widget):
pass
def _updateToolTip(self, widget):
if widget.getAutoTooltip():
widget.setToolTip(widget.getFormatedToolTip())
[docs]
class TaurusAttributeControllerHelper(object):
[docs]
def configObj(self):
return self.attrObj() # they are the same object since tep14
# attrObj = self.attrObj()
# if attrObj is None: return None
# return attrObj.getConfig()
[docs]
def deviceObj(self):
attrObj = self.attrObj()
if attrObj is None:
return None
return attrObj.getParentObj()
[docs]
class TaurusScalarAttributeControllerHelper(TaurusAttributeControllerHelper):
[docs]
def getDisplayValue(self, write=False, **kwargs):
valueObj = self.valueObj()
widget = self.widget()
if valueObj is None or valueObj.rvalue is None:
return widget.getDisplayValue(**kwargs)
format = self.attrObj().data_format
if format == DataFormat._0D:
return self._getDisplayValue(widget, valueObj, None, write)
idx = widget.getModelIndexValue()
return self._getDisplayValue(widget, valueObj, idx, write)
def _getDisplayValue(self, widget, valueObj, idx, write):
try:
if write:
value = valueObj.wvalue
else:
value = valueObj.rvalue
if idx is not None and len(idx):
for i in idx:
value = value[i]
return widget.displayValue(value)
except Exception:
return widget.getNoneValue()
[docs]
def displayValue(self, value):
if value is None:
return None
ret = None
try:
if self.isScalar():
format = self.getFormat()
if self.isNumeric() and format is not None:
format = self.getFormat()
ret = self.getFormat() % value
else:
ret = str(value)
elif self.isSpectrum():
ret = str(value)
else:
ret = str(value)
except Exception:
# if cannot calculate value based on the format just return the
# value
raise
ret = str(value)
return ret
[docs]
class TaurusConfigurationControllerHelper(object):
# TODO: Check if this is used. If so, rename to avoid "Configuration"
def __init__(self):
self._configParam = None
[docs]
def attrObj(self):
return self.configObj() # they are the same object since tep14
[docs]
def deviceObj(self):
attrObj = self.attrObj()
if attrObj is None:
return None
return attrObj.getParentObj()
@property
def configParam(self):
if self._configParam is None:
self._configParam = self.widget().modelFragmentName or ""
return self._configParam
[docs]
def getDisplayValue(self, write=False, **kwargs):
widget = self.widget()
model = self.getModelObj(**kwargs)
if model is None:
return widget.getNoneValue()
param = self.configParam
try:
val = widget.getModelFragmentObj(**kwargs)
try:
no_val = getattr(model, "no_" + param) # TODO: Tango-centric
if val.lower() == no_val.lower():
val = widget.getNoneValue()
except Exception:
pass
except AttributeError:
if param:
val = str(param)
attr = self.attrObj()
if attr is not None:
val = val.replace("<label>", attr.label or "---")
val = val.replace("<attr_name>", attr.name or "---")
val = val.replace(
"<attr_fullname>", attr.getFullName() or "---"
)
dev = self.deviceObj()
if dev is not None:
val = val.replace(
"<dev_fullname>", dev.getFullName() or "---"
)
val = val.replace(
"<dev_alias>", dev.getSimpleName() or "---"
)
val = val.replace(
"<dev_name>", dev.getNormalName() or "---"
)
else:
val = widget.getNoneValue()
except Exception:
widget.debug("Invalid configuration parameter '%s'" % param)
val = widget.getNoneValue()
if val is None:
val = widget.getNoneValue()
return val
StyleSheetTemplate = """border-style: outset; border-width: 2px; border-color: {0}; {1}
"""
def _updatePaletteColors(widget, bgBrush, fgBrush, frameBrush):
qt_palette = widget.palette()
qt_palette.setBrush(Qt.QPalette.Window, bgBrush)
qt_palette.setBrush(Qt.QPalette.Base, bgBrush)
qt_palette.setBrush(Qt.QPalette.WindowText, fgBrush)
qt_palette.setBrush(Qt.QPalette.Light, frameBrush)
qt_palette.setBrush(Qt.QPalette.Dark, frameBrush)
widget.setPalette(qt_palette)
[docs]
def updateLabelBackground(ctrl, widget):
"""Helper method to setup background of taurus labels and lcds"""
bgRole = widget.bgRole
if ctrl.usePalette():
widget.setAutoFillBackground(True)
if bgRole in ("", "none", "None"):
transparentBrush = Qt.QBrush(Qt.Qt.transparent)
frameBrush = transparentBrush
bgBrush, fgBrush = transparentBrush, Qt.QBrush(Qt.Qt.black)
else:
frameBrush = Qt.QBrush(Qt.QColor(255, 255, 255, 128))
bgItem, palette = None, QT_DEVICE_STATE_PALETTE
if bgRole == "quality":
palette = QT_ATTRIBUTE_QUALITY_PALETTE
bgItem = ctrl.quality()
elif bgRole == "state":
try:
bgItem = ctrl.state()
except AttributeError:
pass # protect against calls with state not instantiated
elif bgRole == "value":
bgItem = ctrl.value()
else:
# TODO: this is an *experimental* extension of the bgRole API
# added in v 4.1.2-alpha. It may change in future versions
modelObj = widget.getModelObj()
try:
bgItem = modelObj.getFragmentObj(bgRole)
except Exception:
widget.warning('Invalid bgRole "%s"', bgRole)
bgBrush, fgBrush = palette.qbrush(bgItem)
_updatePaletteColors(widget, bgBrush, fgBrush, frameBrush)
else:
if bgRole in ("", "none", "None"):
ss = StyleSheetTemplate.format("rgba(0,0,0,0)", "")
else:
bgItem, palette = None, QT_DEVICE_STATE_PALETTE
if bgRole == "quality":
palette = QT_ATTRIBUTE_QUALITY_PALETTE
bgItem = ctrl.quality()
elif bgRole == "state":
bgItem = ctrl.state()
elif bgRole == "value":
bgItem = ctrl.value()
else:
# TODO: this is an *experimental* extension of the bgRole API
# added in v 4.1.2-alpha. It may change in future versions
modelObj = widget.getModelObj()
try:
bgItem = modelObj.getFragmentObj(bgRole)
except Exception:
widget.warning('Invalid bgRole "%s"', bgRole)
color_ss = palette.qtStyleSheet(bgItem)
ss = StyleSheetTemplate.format("rgba(255,255,255,128)", color_ss)
widget.setStyleSheet(ss)
widget.update() # necessary in pyqt <= 4.4