#!/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 an arrow based widget.
"""
import os
import math
import numpy
from taurus.external.qt import Qt, PYQT4, PYSIDE
from taurus.core.units import Q_
__docformat__ = "restructuredtext"
class _ArrowButton(Qt.QPushButton):
"""Private class to be used by QWheelEdit for an arrow button"""
ArrowPixmapName = "extra_icons:arrow01.svg"
ButtonSize = 14
IconSize = ButtonSize - 2
def __init__(self, id, parent=None):
Qt.QPushButton.__init__(self, parent)
self.setAutoDefault(False)
pixmap = self.getPixmap()
self.setIcon(Qt.QIcon(pixmap))
self.setIconSize(
Qt.QSize(_ArrowButton.IconSize, _ArrowButton.IconSize)
)
self.setFocusPolicy(Qt.Qt.ClickFocus)
self.setFlat(True)
self.setStyleSheet("_ArrowButton { border: 0px; }")
self.setMaximumSize(_ArrowButton.ButtonSize, _ArrowButton.ButtonSize)
# self.setMinimumSize(_ArrowButton.ButtonSize, _ArrowButton.ButtonSize)
self._id = id
self._inc = math.pow(10, id)
class _UpArrowButton(_ArrowButton):
"""Private class to be used by QWheelEdit for an up arrow button"""
ArrowPixmapKey = "upArrow01"
def __init__(self, id, parent=None):
_ArrowButton.__init__(self, id, parent)
def getPixmap(self):
pm = Qt.QPixmapCache.find(_UpArrowButton.ArrowPixmapKey)
if pm is None:
pm = Qt.QPixmap(self.ArrowPixmapName)
Qt.QPixmapCache.insert(_UpArrowButton.ArrowPixmapKey, pm)
return pm
class _DownArrowButton(_ArrowButton):
"""Private class to be used by QWheelEdit for a down arrow button"""
ArrowPixmapKey = "downArrow01"
def __init__(self, id, parent=None):
_ArrowButton.__init__(self, id, parent)
self._inc = -self._inc
def getPixmap(self):
pm = Qt.QPixmapCache.find(_DownArrowButton.ArrowPixmapKey)
if pm is None:
pm = Qt.QPixmap(self.ArrowPixmapName)
pm = pm.transformed(Qt.QTransform().rotate(180))
Qt.QPixmapCache.insert(_DownArrowButton.ArrowPixmapKey, pm)
return pm
class _DigitLabel(Qt.QLabel):
"""A private single digit label to be used by QWheelEdit widget"""
PixmapKeys = list(map(str, range(10))) + ["blank", "minus", "point"]
def __init__(self, lbl, parent=None):
Qt.QLabel.__init__(self, parent)
self.setAlignment(Qt.Qt.AlignCenter)
self.setFocusPolicy(Qt.Qt.StrongFocus)
self.setStyleSheet(
"QLabel:focus {background-color: rgb(180,180,255); "
+ "border-width: 1px; "
+ "border-style: solid; "
+ "border-color: rgb(200,200,255);}"
)
self.resetSkin()
self.setText(lbl)
self._upButton = None
self._downButton = None
def setButtons(self, up, down):
self._upButton = up
self._downButton = down
def keyPressEvent(self, key_event):
if key_event.key() == Qt.Qt.Key_Up:
self._upButton.click()
elif key_event.key() == Qt.Qt.Key_Down:
self._downButton.click()
elif key_event.key() == Qt.Qt.Key_Right:
self.focusNextChild()
elif key_event.key() == Qt.Qt.Key_Left:
self.focusPreviousChild()
Qt.QLabel.keyPressEvent(self, key_event)
def _update_skin_cache(self):
skin = os.path.join("digits", self.getSkin())
for i, d in enumerate(self.PixmapKeys):
full_name = os.path.join(skin, d)
pm = Qt.QPixmapCache.find(full_name)
if pm is None:
file_name = "%s.png" % full_name
pm = Qt.QPixmap(file_name)
if pm is None:
continue
if not pm.isNull():
Qt.QPixmapCache.insert(full_name, pm)
def setSkin(self, skin_name):
self._skin = skin_name
self._update_skin_cache()
self.update()
def getSkin(self):
return self._skin
def resetSkin(self):
self.setSkin("Nixie")
def setText(self, t):
k = t
if k == ".":
k = "point"
elif k == "-":
k = "minus"
elif k is None or k == "+":
k = "blank"
k = os.path.join("digits", self.getSkin(), k)
pm = Qt.QPixmapCache.find(k)
if pm is None:
Qt.QLabel.setText(self, t)
return
Qt.QLabel.setText(self, "")
self.setPixmap(pm)
skin = Qt.pyqtProperty("QString", getSkin, setSkin, resetSkin)
[docs]
class QWheelEdit(Qt.QFrame):
"""A widget designed to handle numeric scalar values. It allows interaction
based on single digit as well as normal value edition.
"""
numberChanged = Qt.pyqtSignal(float)
numberEdited = Qt.pyqtSignal(float)
returnPressed = Qt.pyqtSignal()
DefaultIntDigitCount = 6
DefaultDecDigitCount = 2
def __init__(self, parent=None):
"""__init__(self, parent = None) -> QWheelEdit
:param parent: the parent widget (optional, default is None
meaning there is no parent
"""
Qt.QFrame.__init__(self, parent)
Qt.QGridLayout(self)
self._roundFunc = None
self._previous_value = 0
self._value = 0
self._value_str = "0"
self._minValue = numpy.finfo("d").min # -inf
self._maxValue = numpy.finfo("d").max # inf
self._editor = None
self._editing = False
self._hideEditWidget = True
self._showArrowButtons = True
self._forwardReturn = False
self._wheel_delta_reminder = 0
self._validator = Qt.QDoubleValidator(self)
self._validator.setNotation(self._validator.StandardNotation)
self._setDigits(
QWheelEdit.DefaultIntDigitCount, QWheelEdit.DefaultDecDigitCount
)
self._setValue(0)
self._build()
self.setDigitCountAction = Qt.QAction("Change digits", self)
self.setDigitCountAction.triggered.connect(self._onSetDigitCount)
self.addAction(self.setDigitCountAction)
self.setContextMenuPolicy(Qt.Qt.ActionsContextMenu)
def _getMinPossibleValue(self):
"""_getMinPossibleValue(self) -> None
Determines which is the minimum possible value that can be represented
with the current total number of digits.
@return (float) the minimum possible value
"""
decmax = 0
for i in range(self.getDecDigitCount()):
decmax += 9 * math.pow(10, -(i + 1))
return -math.pow(10.0, self.getIntDigitCount()) + 1 - decmax
def _getMaxPossibleValue(self):
"""_getMaxPossibleValue(self) -> None
Determines which is the maximum possible value that can be represented
with the current total number of digits.
@return (float) the maximum possible value
"""
decmax = 0
for i in range(self.getDecDigitCount()):
decmax += 9 * math.pow(10, -(i + 1))
return math.pow(10.0, self.getIntDigitCount()) - 1 + decmax
def _build(self):
"""_build(self) -> None
Builds this widget sub-items
"""
lyt = self.layout()
lyt.setSpacing(0)
lyt.setContentsMargins(0, 0, 0, 0)
id = self.getIntDigitCount()
digits = self.getDigitCount()
self._upButtons = Qt.QButtonGroup()
self._downButtons = Qt.QButtonGroup()
self._digitLabels = []
for lyt in self._digitLabels:
lyt.setAlignment(Qt.AlignCenter)
showDot = self.getDecDigitCount() > 0
signLabel = _DigitLabel("+")
signLabel.setFocusPolicy(Qt.Qt.NoFocus)
signLabel.setAlignment(Qt.Qt.AlignRight | Qt.Qt.AlignVCenter)
self._digitLabels.append(signLabel)
lyt.addWidget(signLabel, 1, 0)
lyt.setRowMinimumHeight(1, signLabel.minimumSizeHint().height())
lyt.setColumnMinimumWidth(0, _ArrowButton.ButtonSize)
lyt.setColumnStretch(0, 1)
for i in range(id):
col = i + 1
d = _DigitLabel("0")
up = _UpArrowButton(id - i - 1)
down = _DownArrowButton(id - i - 1)
d.setButtons(up, down)
up.setFocusProxy(d)
down.setFocusProxy(d)
self._upButtons.addButton(up, col)
self._downButtons.addButton(down, col)
self._digitLabels.append(d)
if self.getShowArrowButtons():
lyt.addWidget(up, 0, col)
lyt.addWidget(down, 2, col)
lyt.addWidget(d, 1, col)
if showDot:
dotLabel = _DigitLabel(".")
dotLabel.setFocusPolicy(Qt.Qt.NoFocus)
dotLabel.setAlignment(Qt.Qt.AlignCenter)
self._digitLabels.append(dotLabel)
lyt.addWidget(dotLabel, 1, id + 1)
for i in range(id, digits):
col = i + 1
if showDot:
col += 1
d = _DigitLabel("0")
up = _UpArrowButton(id - i - 1)
down = _DownArrowButton(id - i - 1)
d.setButtons(up, down)
up.setFocusProxy(d)
down.setFocusProxy(d)
self._upButtons.addButton(up, col)
self._downButtons.addButton(down, col)
self._digitLabels.append(d)
if self.getShowArrowButtons():
lyt.addWidget(up, 0, col)
lyt.addWidget(down, 2, col)
lyt.addWidget(d, 1, col)
self._upButtons.buttonClicked.connect(self.buttonPressed)
self._downButtons.buttonClicked.connect(self.buttonPressed)
ed = Qt.QLineEdit(self)
ed.setFrame(False)
ed.returnPressed.connect(self.editingFinished)
ed.editingFinished.connect(self.hideEditWidget)
rect = Qt.QRect(
lyt.cellRect(1, 0).topLeft(),
lyt.cellRect(1, lyt.columnCount() - 1).bottomRight(),
)
ed.setGeometry(rect)
ed.setAlignment(Qt.Qt.AlignRight)
ed.setValidator(self._validator)
ed.setVisible(False)
self._editor = ed
self._updateValidator()
# set the minimum height for the widget
# (otherwise the hints seem to be ignored by the layouts)
min_height = max(
ed.minimumSizeHint().height(), signLabel.minimumSizeHint().height()
)
if self.getShowArrowButtons():
min_height += 2 * _ArrowButton.ButtonSize
self.setMinimumHeight(min_height)
self.clearWarning()
def _clear(self):
"""_clear(self) -> None
Clears this widget sub-items
"""
self._upButtons.buttonClicked.disconnect(self.buttonPressed)
self._downButtons.buttonClicked.disconnect(self.buttonPressed)
for b in self._upButtons.buttons():
self._upButtons.removeButton(b)
b.setParent(None)
b.destroy()
for b in self._downButtons.buttons():
self._downButtons.removeButton(b)
b.setParent(None)
b.destroy()
for label in self._digitLabels:
label.setParent(None)
label.destroy()
self._digitLabels = None
self._upButtons.setParent(None)
self._downButtons.setParent(None)
self._upButtons = None
self._downButtons = None
self._editor.setParent(None)
self._editor.destroy()
self._editor = None
def _setDigits(self, int_nb=None, dec_nb=None):
"""_setDigits(self, int_nb=None, dec_nb=None) -> None
Sets the number of digits that this widget shows. It will ensure that
the current value can be displayed (i.e., int_nb will be forced to be
large enough for displaying the integer representation of the value)
@param[in] int_nb (int) number of integer digits (optional, default is
None, meaning use the existing number of integer digits
@param[in] dec_nb (int) number of decimal digits (optional, default is
None, meaning use the existing number of decimal digits
"""
if int_nb is not None:
self._intDigitCount = int_nb
if dec_nb is not None:
self._decDigitCount = dec_nb
# make sure that the current value can be displayed
self._intDigitCount = max(self._intDigitCount, len("%d" % self._value))
self._digitCount = self._intDigitCount + self._decDigitCount
total_chars = self._digitCount
total_chars += 1 # for sign
if self._decDigitCount > 0:
total_chars += 1 # for dot
self._valueFormat = "%%+0%d.%df" % (total_chars, self._decDigitCount)
self._updateValidator()
# we call setValue to update the self._value_str
self._setValue(self.getValue())
def _buildValueStr(self, v):
"""_buildValueStr(self, v) -> str
Builds a string representation of the given value according to the
number of digits this widget can currently represent
@param[in] v (float) the value to be translated
@return (str) a proper string representation of the given value
"""
if v is None:
ret = (self._valueFormat % 0).replace("0", "-")
else:
ret = self._valueFormat % v
if ret.endswith("nan"):
ret = ret.replace("0", " ")
self._value_str = ret
return ret
def _updateDigits(self):
"""_updateDigits(self) -> None
Updates this widget contents (sub-widgets) according to the current
widget configuration
"""
self._clear()
self._build()
self._updateValue(False, False)
def _updateValue(self, trigValueChanged=True, trigValueEdited=True):
"""
_updateValue(self, trigValueChanged=True, trigValueEdited=True) -> None
Updates this widget displayed value and potentially send signal(s)
:param trigValueChanged: (optional, default is True) whether or
not to send signal 'valueChanged(double)'
:type trigValueChanged: bool
:param trigValueEdited: (optional, default is True) whether or
not to send signal 'valueEdit(double)'
:type trigValueEdited: bool
"""
v, v_str = self.getValue(), self.getValueStr()
if len(v_str) > len(self._digitLabels):
# do auto adjust
if "." in v_str:
dc = list(map(len, v_str.split(".")))
else:
dc = len(v_str), 0
self._setDigits(*dc)
v_str = self._buildValueStr(v)
self._clear()
self._build()
for i, c in enumerate(v_str):
self._digitLabels[i].setText(c)
if trigValueChanged:
self.numberChanged.emit(v)
if trigValueEdited:
self.numberEdited.emit(v)
[docs]
def setRoundFunc(self, roundFunc):
"""setRoundFunc(self, roundFunc) -> None
Sets the rounding function to use when calling _setValue(). This allows
you to filter invalid user input
@param[in] roundFunc (callable) the rounding function to use
"""
self._roundFunc = roundFunc
[docs]
def getPreviousValue(self):
"""getPreviousValue(self) -> float
Gives the previous value of this widget
@return (float) the previous value of this widget
"""
return self._previous_value
def _setValue(self, v):
"""_setValue(self, v) -> None
Sets value of this widget. If the given value exceeds any limit, the
value is NOT set.
"""
if v is None:
return
if self._roundFunc:
v = self._roundFunc(v)
if v > self._validator.top() or v < self._validator.bottom():
Qt.QMessageBox.warning(
self,
"Invalid Value",
"'{}' is out of the allowed range ({}, {})".format(
v,
self._validator.bottom(),
self._validator.top(),
),
)
return
self._previous_value = self._value
self._value = v
str_value = self._buildValueStr(v)
ed = self.getEditWidget()
if ed is not None:
ed.setText(str_value)
[docs]
def setWarning(self, msg):
"""setWarning(self, msg) -> None
Activates the warning style for this widget. This means a violet border
and a tooltip with the given message.
@param[in] msg (str) the message to be displayed as tooltip
"""
self.setStyleSheet(
"QWheelEdit {border: 1px solid; "
+ "border-radius: 4px; "
+ "border-color: violet}"
)
self.setToolTip(msg)
[docs]
def clearWarning(self):
"""clearWarning(self) -> None
Clears the warning style. If not in warning mode, nothing is done.
"""
self.setStyleSheet(
"QWheelEdit {border: 1px solid; "
+ "border-radius: 4px; "
+ "border-color: rgba(0,0,0,0)}"
)
self.setToolTip("")
def _onSetDigitCount(self):
text, ok = Qt.QInputDialog.getText(
self,
"Change digits",
"Enter digits as <int_nb>.<dec_nb>",
text="{:d}.{:d}".format(
self.getIntDigitCount(), self.getDecDigitCount()
),
)
if ok:
try:
dc = list(map(int, text.split(".")))
self.setDigitCount(*dc)
except Exception as e:
Qt.QMessageBox.warning(
self,
"Invalid digit count specification",
'Invalid specification: "{}"\nReason:{}'.format(text, e),
)
self._onSetDigitCount()
[docs]
def setDigitCount(self, int_nb, dec_nb):
"""setDigitCount(self, int_nb, dec_nb) -> None
Updates the displayed digits.
@param[in] int_nb(int) number of integer digits
@param[in] dec_nb(int) number of decimal digits
"""
self._setDigits(int_nb=int_nb, dec_nb=dec_nb)
self._updateDigits()
[docs]
def getDigitCount(self):
"""getDigitCount(self) -> int
Gets the total number of digits this widget displays
@return (int) the total number of digits this widget displays
"""
return self._digitCount
[docs]
def getIntDigitCount(self):
"""getIntDigitCount(self) -> int
Gets the number of integer digits this widget displays
@return (int) the number of integer digits this widget displays
"""
return self._intDigitCount
[docs]
def setIntDigitCount(self, n):
"""setIntDigitCount(self, n) -> None
Sets the number of integer digits this widget displays
@param[in] n (int) the number of integer digits to display
"""
self._setDigits(int_nb=n)
self._updateDigits()
[docs]
def resetIntDigitCount(self):
"""resetIntDigitCount(self) -> None
Resets the number of integer digits this widget displays to
DefaultIntDigitCount
"""
self.setIntDigitCount(QWheelEdit.DefaultIntDigitCount)
[docs]
def getDecDigitCount(self):
"""getDecDigitCount(self) -> int
Gets the number of decimal digits this widget displays
@return (int) the number of decimal digits this widget displays
"""
return self._decDigitCount
[docs]
def setDecDigitCount(self, n):
"""setDecDigitCount(self, n) -> None
Sets the number of decimal digits this widget displays
@param[in] n (int) the number of decimal digits to display
"""
self._setDigits(dec_nb=n)
self._updateDigits()
[docs]
def resetDecDigitCount(self):
"""resetDecDigitCount(self) -> None
Resets the number of decimal digits this widget displays to
DefaultDecDigitCount
"""
self.setDecDigitCount(QWheelEdit.DefaultDecDigitCount)
[docs]
def setValue(self, v):
"""setValue(self, v) -> None
Sets the value of this widget.
Send a 'valueChanged(double)' Qt signal
@param[in] v (float/Quantity) the value to be set
"""
if isinstance(v, Q_):
v = v.magnitude
self._setValue(v)
self._updateValue(trigValueEdited=False)
[docs]
def resetValue(self):
"""resetValue(self) -> None
Resets the value of this widget to 0.0
"""
self.setValue(0.0)
[docs]
def getValue(self):
"""getValue(self) -> float
Gets the current value of this widget
@return (float) the value currently displayed by the widget
"""
return self._value
[docs]
def getValueStr(self):
"""getValueStr(self) -> str
Gets the current value string of this widget
@return (str) the value currently displayed by the widget
"""
return self._value_str
[docs]
def getMinValue(self):
"""getMinValue(self) -> float
Gets the minimum allowed value
@return (float) the minimum allowed value
"""
return self._minValue
[docs]
def setMinValue(self, v):
"""setMinValue(self, v) -> None
Sets the minimum allowed value for the widget
@param[in] v (float) the new minimum allowed value
"""
self._minValue = v
self._updateValidator()
def _updateValidator(self):
min_ = max(self._minValue, self._getMinPossibleValue())
max_ = min(self._maxValue, self._getMaxPossibleValue())
self._validator.setRange(min_, max_, self._decDigitCount)
[docs]
def resetMinValue(self):
"""resetMinValue(self) -> None
Resets the minimum allowed value to -inf
"""
self.setMinValue(numpy.finfo("d").min)
[docs]
def getMaxValue(self):
"""getMaxValue(self) -> float
Gets the maximum allowed value
@return (float) the maximum allowed value
"""
return self._maxValue
[docs]
def setMaxValue(self, v):
"""setMaxValue(self, v) -> None
Sets the maximum allowed value for the widget
@param[in] v (float) the new maximum allowed value
"""
self._maxValue = v
self._updateValidator()
[docs]
def resetMaxValue(self):
"""resetMaxValue(self) -> None
Resets the maximum allowed value to +inf
"""
self.setMaxValue(numpy.finfo("d").max)
[docs]
def getAutoRepeat(self):
return self._upButtons.buttons()[0].autoRepeat()
[docs]
def setAutoRepeat(self, v):
for b in self._upButtons.buttons():
b.setAutoRepeat(v)
for b in self._downButtons.buttons():
b.setAutoRepeat(v)
[docs]
def resetAutoRepeat(self):
self.setAutoRepeat(False)
[docs]
def getAutoRepeatDelay(self):
return self._upButtons.buttons()[0].autoRepeatDelay()
[docs]
def setAutoRepeatDelay(self, milisecs):
for b in self._upButtons.buttons():
b.setAutoRepeatDelay(milisecs)
for b in self._downButtons.buttons():
b.setAutoRepeatDelay(milisecs)
[docs]
def getAutoRepeatInterval(self):
return self._upButtons.buttons()[0].autoRepeatInterval()
[docs]
def setAutoRepeatInterval(self, milisecs):
for b in self._upButtons.buttons():
b.setAutoRepeatInterval(milisecs)
for b in self._downButtons.buttons():
b.setAutoRepeatInterval(milisecs)
[docs]
def editingFinished(self):
"""editingFinished(self) -> None
Slot called when the user finishes editing
"""
ed = self.getEditWidget()
v = float(ed.text())
self._setValue(v)
self._updateValue()
[docs]
def wheelEvent(self, evt):
if PYQT4 or PYSIDE:
self._wheel_delta_reminder += evt.delta()
else:
self._wheel_delta_reminder += evt.angleDelta().y()
numSteps = self._wheel_delta_reminder // 120
self._wheel_delta_reminder -= numSteps * 120
w = self.focusWidget()
if not isinstance(w, _DigitLabel):
return Qt.QFrame.wheelEvent(self, evt)
self.setValue(self.getValue() + numSteps)
evt.accept()
[docs]
def mouseDoubleClickEvent(self, mouse_event):
"""mouseDoubleClickEvent(self, mouse_event)
Executed when user presses double click. This widget shows the edition
widget when this happens
"""
self.showEditWidget()
[docs]
def keyPressEvent(self, key_event):
"""keyPressEvent(self, key_event) -> None
Exectuted when the user presses a key.
F2 enters/leaves edition mode. ESC leaves edition mode
"""
k = key_event.key()
if k == Qt.Qt.Key_F2:
if self._editing:
self.hideEditWidget()
else:
self.showEditWidget()
return
elif k == Qt.Qt.Key_Escape:
if self._editing:
self.hideEditWidget()
return
elif k in (Qt.Qt.Key_Return, Qt.Qt.Key_Enter):
if self._editing:
self.hideEditWidget()
else:
self.returnPressed.emit()
# TODO Decide when to emit editingFinished for completeness
Qt.QWidget.keyPressEvent(self, key_event)
[docs]
def isReturnForwarded(self):
"""isReturnForwarded(self) -> bool
Gets the info if returnPressed is forwarded.
@return (bool)
"""
return self._forwardReturn
[docs]
def setReturnForwarded(self, forward_rtn=False):
"""setReturnForwarded(self, forward_rtn=False) -> None
Sets forwarding of returnPressed. If set to True, returnPressed from
edition widget emits returnPressed of 'QWheelEdit' widget.
@param[in] forward_rtn (bool) whether or not to forward returnPressed
signal
"""
if forward_rtn and not self._forwardReturn:
ed = self.getEditWidget()
ed.returnPressed.connect(self.returnPressed)
self._forwardReturn = True
elif not forward_rtn and self._forwardReturn:
ed = self.getEditWidget()
ed.returnPressed.disconnect(self.returnPressed)
self._forwardReturn = False
# -~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
# QT properties
# -~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
showArrowButtons = Qt.pyqtProperty(
"bool", getShowArrowButtons, setShowArrowButtons, resetShowArrowButtons
)
integerDigits = Qt.pyqtProperty(
"int", getIntDigitCount, setIntDigitCount, resetIntDigitCount
)
decimalDigits = Qt.pyqtProperty(
"int", getDecDigitCount, setDecDigitCount, resetDecDigitCount
)
value = Qt.pyqtProperty("double", getValue, setValue, resetValue)
minValue = Qt.pyqtProperty(
"double", getMinValue, setMinValue, resetMinValue
)
maxValue = Qt.pyqtProperty(
"double", getMaxValue, setMaxValue, resetMaxValue
)
autoRepeat = Qt.pyqtProperty(
"bool", getAutoRepeat, setAutoRepeat, resetAutoRepeat
)
autoRepeatDelay = Qt.pyqtProperty(
"int", getAutoRepeatDelay, setAutoRepeatDelay
)
autoRepeatInterval = Qt.pyqtProperty(
"int", getAutoRepeatInterval, setAutoRepeatInterval
)
def main():
# unused import to initialize the icons
import taurus.qt.qtgui.icon # noqa: F401
global arrowWidget
def resetAll():
arrowWidget.resetIntDigitCount()
arrowWidget.resetDecDigitCount()
arrowWidget.resetMinValue()
arrowWidget.resetMaxValue()
arrowWidget.resetValue()
def setNAN():
arrowWidget.setValue(float("nan"))
def setNone():
arrowWidget.setValue(None)
a = Qt.QApplication([])
panel = Qt.QWidget()
lyt = Qt.QFormLayout(panel)
button_layout = Qt.QVBoxLayout()
arrowWidget = QWheelEdit(panel)
isb, dsb = Qt.QSpinBox(panel), Qt.QSpinBox(panel)
minv, maxv = Qt.QDoubleSpinBox(panel), Qt.QDoubleSpinBox(panel)
resetbutton = Qt.QPushButton("Reset", panel)
resetbutton.setDefault(True)
nanbutton = Qt.QPushButton("Set NAN", panel)
nonebutton = Qt.QPushButton("Set None", panel)
hideEditCB = Qt.QCheckBox()
hideEditCB.setChecked(True)
showarrowbutton = Qt.QCheckBox("", panel)
lyt.addRow("Value", arrowWidget)
lyt.addRow("Integer digits:", isb)
lyt.addRow("Decimal digits:", dsb)
lyt.addRow("Minimum value:", minv)
lyt.addRow("Maximum value:", maxv)
lyt.addRow("Show arrows:", showarrowbutton)
lyt.addRow("hideEditCB", hideEditCB)
lyt.addRow(button_layout)
button_layout.addWidget(nanbutton)
button_layout.addWidget(nonebutton)
button_layout.addWidget(resetbutton)
isb.setValue(arrowWidget.getIntDigitCount())
dsb.setValue(arrowWidget.getDecDigitCount())
minv.setRange(numpy.finfo("d").min, numpy.finfo("d").max)
maxv.setRange(numpy.finfo("d").min, numpy.finfo("d").max)
minv.setValue(arrowWidget.getMinValue())
maxv.setValue(arrowWidget.getMaxValue())
showarrowbutton.setChecked(arrowWidget.getShowArrowButtons())
isb.valueChanged.connect(arrowWidget.setIntDigitCount)
dsb.valueChanged.connect(arrowWidget.setDecDigitCount)
minv.valueChanged.connect(arrowWidget.setMinValue)
showarrowbutton.stateChanged.connect(arrowWidget.setShowArrowButtons)
nanbutton.clicked.connect(setNAN)
nonebutton.clicked.connect(setNone)
hideEditCB.toggled.connect(arrowWidget.setHideEditWidget)
resetbutton.clicked.connect(resetAll)
panel.setVisible(True)
a.exec_()
if __name__ == "__main__":
main()