23#include "moc_qgsdoublespinbox.cpp"
29#define CLEAR_ICON_SIZE 16
35static QChar SPECIAL_TEXT_WHEN_EMPTY = QChar( 0x2063 );
37static constexpr QChar SPECIAL_TEXT_WHEN_EMPTY = QChar( 0x2063 );
42 : QDoubleSpinBox( parent )
44 mLineEdit =
new QgsSpinBoxLineEdit();
48 setLineEdit( mLineEdit );
50 const QSize msz = minimumSizeHint();
54 connect(
this,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsDoubleSpinBox::changed );
56 mLastEditTimer =
new QTimer(
this );
57 mLastEditTimer->setSingleShot(
true );
58 mLastEditTimer->setInterval( 1000 );
59 connect( mLastEditTimer, &QTimer::timeout,
this, &QgsDoubleSpinBox::onLastEditTimeout );
70 mExpressionsEnabled = enabled;
75 QDoubleSpinBox::changeEvent( event );
77 if ( event->type() == QEvent::FontChange )
79 lineEdit()->setFont( font() );
82 mLineEdit->setShowClearButton( shouldShowClearForValue( value() ) );
87 const double step = singleStep();
88 if ( event->modifiers() & Qt::ControlModifier )
91 double newStep = step / 10;
94 newStep = std::max( newStep, std::pow( 10.0, 0.0 - decimals() ) );
96 setSingleStep( newStep );
101 event->setModifiers( event->modifiers() & ~Qt::ControlModifier );
103 QDoubleSpinBox::wheelEvent( event );
104 setSingleStep( step );
109 QDoubleSpinBox::focusOutEvent( event );
119 qApp->processEvents();
120 if ( QApplication::mouseButtons() & Qt::LeftButton )
121 QDoubleSpinBox::timerEvent( event );
126 mLineEdit->setShowClearButton( shouldShowClearForValue( value() ) );
127 QDoubleSpinBox::paintEvent( event );
132 const bool wasNull = mShowClearButton && value() ==
clearValue();
133 if ( wasNull && minimum() < 0 && maximum() > 0 && !( specialValueText().isEmpty() || specialValueText() == SPECIAL_TEXT_WHEN_EMPTY ) )
141 QDoubleSpinBox::stepBy( steps );
146 return mLastEditTimer->interval();
151 mLastEditTimer->setInterval( timeout );
154void QgsDoubleSpinBox::changed(
double value )
156 mLineEdit->setShowClearButton( shouldShowClearForValue( value ) );
157 mLastEditTimer->start();
160void QgsDoubleSpinBox::onLastEditTimeout()
162 mLastEditTimer->stop();
163 const double currentValue = value();
164 if ( std::isnan( mLastEditTimeoutValue ) || mLastEditTimeoutValue != currentValue )
166 mLastEditTimeoutValue = currentValue;
174 if ( mLineEdit->isNull() )
180 if ( mClearValueMode ==
CustomValue && mCustomClearValue == customValue && QAbstractSpinBox::specialValueText() == specialValueText )
186 mCustomClearValue = customValue;
188 if ( !specialValueText.isEmpty() )
190 const double v = value();
199 if ( mClearValueMode == mode && mCustomClearValue == 0 && QAbstractSpinBox::specialValueText() == clearValueText )
204 mClearValueMode = mode;
205 mCustomClearValue = 0;
207 if ( !clearValueText.isEmpty() )
209 const double v = value();
223 return mCustomClearValue;
228 mLineEdit->setAlignment( alignment );
235 QDoubleSpinBox::setSpecialValueText( SPECIAL_TEXT_WHEN_EMPTY );
236 mLineEdit->setNullValue( SPECIAL_TEXT_WHEN_EMPTY );
240 QDoubleSpinBox::setSpecialValueText( txt );
241 mLineEdit->setNullValue( txt );
245QString QgsDoubleSpinBox::stripped(
const QString &originalText )
const
249 QString text = originalText;
250 if ( specialValueText().isEmpty() || text != specialValueText() )
253 if ( text.contains( SPECIAL_TEXT_WHEN_EMPTY ) )
254 text = text.replace( SPECIAL_TEXT_WHEN_EMPTY, QString() );
256 int size = text.size();
257 bool changed =
false;
258 if ( !prefix().isEmpty() && text.startsWith( prefix() ) )
260 from += prefix().size();
264 if ( !suffix().isEmpty() && text.endsWith( suffix() ) )
266 size -= suffix().size();
270 text = text.mid( from, size );
273 text = text.trimmed();
280 if ( !mExpressionsEnabled )
282 return QDoubleSpinBox::valueFromText( text );
285 const QString trimmedText = stripped( text );
286 if ( trimmedText.isEmpty() )
288 return mShowClearButton ?
clearValue() : value();
296 if ( !mExpressionsEnabled )
298 const QValidator::State r = QDoubleSpinBox::validate( input, pos );
302 return QValidator::Acceptable;
305int QgsDoubleSpinBox::frameWidth()
const
307 return style()->pixelMetric( QStyle::PM_DefaultFrameWidth );
310bool QgsDoubleSpinBox::shouldShowClearForValue(
const double value )
const
312 if ( !mShowClearButton || !isEnabled() )
void paintEvent(QPaintEvent *e) override
void wheelEvent(QWheelEvent *event) override
void setLineEditAlignment(Qt::Alignment alignment)
Set alignment in the embedded line edit widget.
void setEditingTimeoutInterval(int timeout)
Sets the timeout (in milliseconds) threshold for the editingTimeout() signal to be emitted after an e...
void stepBy(int steps) override
double valueFromText(const QString &text) const override
void setSpecialValueText(const QString &txt)
Set the special-value text to be txt If set, the spin box will display this text instead of a numeric...
void setClearValueMode(ClearValueMode mode, const QString &clearValueText=QString())
Defines if the clear value should be the minimum or maximum values of the widget or a custom value.
void editingTimeout(double value)
Emitted when either:
void focusOutEvent(QFocusEvent *event) override
void changeEvent(QEvent *event) override
void clear() override
Sets the current value to the value defined by the clear value.
ClearValueMode
Behavior when widget is cleared.
@ MaximumValue
Reset value to maximum()
@ CustomValue
Reset value to custom value (see setClearValue() )
@ MinimumValue
Reset value to minimum()
QValidator::State validate(QString &input, int &pos) const override
QgsDoubleSpinBox(QWidget *parent=nullptr)
Constructor for QgsDoubleSpinBox.
void setExpressionsEnabled(bool enabled)
Sets if the widget will allow entry of simple expressions, which are evaluated and then discarded.
int editingTimeoutInterval() const
Returns the timeout (in milliseconds) threshold for the editingTimeout() signal to be emitted after a...
void setClearValue(double customValue, const QString &clearValueText=QString())
Defines the clear value as a custom value and will automatically set the clear value mode to CustomVa...
void setShowClearButton(bool showClearButton)
Sets whether the widget will show a clear button.
void timerEvent(QTimerEvent *event) override
void returnPressed()
Emitted when the Return or Enter key is used in the line edit.
static double evaluateToDouble(const QString &text, double fallbackValue)
Attempts to evaluate a text string as an expression to a resultant double value.
void cleared()
Emitted when the widget is cleared.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.