Source code for silx.gui.widgets.IntEdit
import numpy
from silx.gui import qt
[docs]
class IntEdit(qt.QLineEdit):
"""QLineEdit for integers with a default value and update on validation.
:param QWidget parent:
"""
sigValueChanged = qt.Signal(int)
"""Signal emitted when the value has changed (on editing finished)"""
def __init__(self, parent=None):
super().__init__(parent)
self.__value = None
self.setAlignment(qt.Qt.AlignRight)
validator = qt.QIntValidator()
self.setValidator(validator)
validator.bottomChanged.connect(self.__updateSize)
validator.topChanged.connect(self.__updateSize)
self.__updateSize()
self.textEdited.connect(self.__textEdited)
def __updateSize(self, *args):
"""Update widget's maximum size according to bounds"""
bottom, top = self.getRange()
nbchar = max(len(str(bottom)), len(str(top)))
font = self.font()
font.setStyle(qt.QFont.StyleItalic)
fontMetrics = qt.QFontMetrics(font)
self.setMaximumWidth(fontMetrics.boundingRect("0" * (nbchar + 1)).width())
self.setMaxLength(nbchar)
def __textEdited(self, _):
if self.font().style() != qt.QFont.StyleItalic:
font = self.font()
font.setStyle(qt.QFont.StyleItalic)
self.setFont(font)
# Use events rather than editingFinished to also trigger with empty text
def focusOutEvent(self, event):
self.__commitValue()
return super().focusOutEvent(event)
def keyPressEvent(self, event):
if event.key() in (qt.Qt.Key_Enter, qt.Qt.Key_Return):
self.__commitValue()
return super().keyPressEvent(event)
def __commitValue(self):
"""Update the value returned by :meth:`getValue`"""
value = self.getCurrentValue()
if value is None:
value = self.getDefaultValue()
if value is None:
return # No value, keep previous one
if self.font().style() != qt.QFont.StyleNormal:
font = self.font()
font.setStyle(qt.QFont.StyleNormal)
self.setFont(font)
if value != self.__value:
self.__value = value
self.sigValueChanged.emit(value)
[docs]
def getValue(self) -> int | None:
"""Return current value (None if never set)."""
return self.__value
[docs]
def setRange(self, bottom: int, top: int):
"""Set the range of valid values"""
self.validator().setRange(bottom, top)
[docs]
def getRange(self) -> tuple[int, int]:
"""Returns the current range of valid values
:returns: (bottom, top)
"""
return self.validator().bottom(), self.validator().top()
def __validate(self, value: int, extend_range: bool):
"""Ensure value is in range
:param int value:
:param bool extend_range:
True to extend range if needed.
False to clip value if needed.
"""
if extend_range:
bottom, top = self.getRange()
self.setRange(min(value, bottom), max(value, top))
return numpy.clip(value, *self.getRange())
[docs]
def setDefaultValue(self, value: int, extend_range: bool = False):
"""Set default value when QLineEdit is empty
:param int value:
:param bool extend_range:
True to extend range if needed.
False to clip value if needed
"""
self.setPlaceholderText(str(self.__validate(value, extend_range)))
if self.getCurrentValue() is None:
self.__commitValue()
[docs]
def getDefaultValue(self) -> int | None:
"""Return the default value or the bottom one if not set"""
try:
return int(self.placeholderText())
except ValueError:
return None
[docs]
def setCurrentValue(self, value: int, extend_range: bool = False):
"""Set the currently displayed value
:param int value:
:param bool extend_range:
True to extend range if needed.
False to clip value if needed
"""
self.setText(str(self.__validate(value, extend_range)))
self.__commitValue()
[docs]
def getCurrentValue(self) -> int | None:
"""Returns the displayed value or None if not correct"""
try:
return int(self.text())
except ValueError:
return None