diff options
Diffstat (limited to 'src/silx/gui/widgets/FloatEdit.py')
-rw-r--r-- | src/silx/gui/widgets/FloatEdit.py | 102 |
1 files changed, 94 insertions, 8 deletions
diff --git a/src/silx/gui/widgets/FloatEdit.py b/src/silx/gui/widgets/FloatEdit.py index 61f518f..f9d7331 100644 --- a/src/silx/gui/widgets/FloatEdit.py +++ b/src/silx/gui/widgets/FloatEdit.py @@ -1,6 +1,6 @@ # /*########################################################################## # -# Copyright (c) 2004-2021 European Synchrotron Radiation Facility +# Copyright (c) 2004-2023 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -23,6 +23,8 @@ # ###########################################################################*/ """Module contains a float editor """ +from __future__ import annotations + __authors__ = ["V.A. Sole", "T. Vincent"] __license__ = "MIT" @@ -34,18 +36,33 @@ from .. import qt class FloatEdit(qt.QLineEdit): """Field to edit a float value. - :param parent: See :class:`QLineEdit` - :param float value: The value to set the QLineEdit to. + The value can be modified with :meth:`value` and :meth:`setValue`. + + The property :meth:`widgetResizable` allow to change the default + behaviour in order to automatically resize the widget to the displayed value. + Use :meth:`setMinimumWidth` to enforce the minimum width. + + :param parent: Parent of the widget + :param value: The value to set the QLineEdit to. """ - def __init__(self, parent=None, value=None): + + _QLineEditPrivateHorizontalMargin = 2 + """Constant from Qt source code""" + + def __init__(self, parent: qt.QWidget | None = None, value: float | None = None): qt.QLineEdit.__init__(self, parent) validator = qt.QDoubleValidator(self) + self.__widgetResizable: bool = False + self.__minimumWidth = 30 + """Store the minimum width requested by the user, the real one is + dynamic""" self.setValidator(validator) self.setAlignment(qt.Qt.AlignRight) + self.textChanged.connect(self.__textChanged) if value is not None: self.setValue(value) - def value(self): + def value(self) -> float: """Return the QLineEdit current value as a float.""" text = self.text() value, validated = self.validator().locale().toDouble(text) @@ -53,16 +70,85 @@ class FloatEdit(qt.QLineEdit): self.setValue(value) return value - def setValue(self, value): + def setValue(self, value: float): """Set the current value of the LineEdit - :param float value: The value to set the QLineEdit to. + :param value: The value to set the QLineEdit to. """ locale = self.validator().locale() if qt.BINDING == "PySide6": # Fix for PySide6 not selecting the right method - text = locale.toString(float(value), 'g') + text = locale.toString(float(value), "g") else: text = locale.toString(float(value)) self.setText(text) + if self.__widgetResizable: + self.__forceMinimumWidthFromContent() + + def __textChanged(self, text: str): + if self.__widgetResizable: + self.__forceMinimumWidthFromContent() + + def widgetResizable(self) -> bool: + """ + Returns whether or not the widget auto resizes itself based on it's content + """ + return self.__widgetResizable + + def setWidgetResizable(self, resizable: bool): + """ + If true, the widget will automatically resize itself to its displayed content. + + This avoids to have to scroll to see the widget's content, and allow to take + advantage of extra space. + """ + if self.__widgetResizable == resizable: + return + self.__widgetResizable = resizable + self.updateGeometry() + if resizable: + self.__forceMinimumWidthFromContent() + else: + qt.QLineEdit.setMinimumWidth(self, self.__minimumWidth) + + def __minimumWidthFromContent(self) -> int: + """Minimum size for the widget to properly read the actual number""" + text = self.text() + font = self.font() + metrics = qt.QFontMetrics(font) + margins = self.textMargins() + width = ( + metrics.horizontalAdvance(text) + + self._QLineEditPrivateHorizontalMargin * 2 + + margins.left() + + margins.right() + ) + width = max(self.__minimumWidth, width) + opt = qt.QStyleOptionFrame() + self.initStyleOption(opt) + s = self.style().sizeFromContents( + qt.QStyle.CT_LineEdit, opt, qt.QSize(width, self.height()) + ) + return s.width() + + def sizeHint(self) -> qt.QSize: + sizeHint = qt.QLineEdit.sizeHint(self) + if not self.__widgetResizable: + return sizeHint + width = self.__minimumWidthFromContent() + return qt.QSize(width, sizeHint.height()) + + def __forceMinimumWidthFromContent(self): + width = self.__minimumWidthFromContent() + qt.QLineEdit.setMinimumWidth(self, width) + self.updateGeometry() + + def setMinimumWidth(self, width: int): + self.__minimumWidth = width + qt.QLineEdit.setMinimumWidth(self, width) + self.updateGeometry() + + def minimumWidth(self) -> int: + """Returns the user defined minimum width.""" + return self.__minimumWidth |