29#include "moc_qgsdoublespinbox.cpp"
31#define CLEAR_ICON_SIZE 16
37static QChar SPECIAL_TEXT_WHEN_EMPTY = QChar( 0x2063 );
39static constexpr QChar SPECIAL_TEXT_WHEN_EMPTY = QChar( 0x2063 );
44 : QDoubleSpinBox( parent )
46 mLineEdit =
new QgsSpinBoxLineEdit();
50 setLineEdit( mLineEdit );
52 const QSize msz = minimumSizeHint();
56 connect(
this,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsDoubleSpinBox::changed );
58 mLastEditTimer =
new QTimer(
this );
59 mLastEditTimer->setSingleShot(
true );
60 mLastEditTimer->setInterval( 1000 );
61 connect( mLastEditTimer, &QTimer::timeout,
this, &QgsDoubleSpinBox::onLastEditTimeout );
72 mExpressionsEnabled = enabled;
77 QDoubleSpinBox::changeEvent( event );
79 if ( event->type() == QEvent::FontChange )
81 lineEdit()->setFont( font() );
84 mLineEdit->setShowClearButton( shouldShowClearForValue( value() ) );
89 const double step = singleStep();
90 if ( event->modifiers() & Qt::ControlModifier )
93 double newStep = step / 10;
96 newStep = std::max( newStep, std::pow( 10.0, 0.0 - decimals() ) );
98 setSingleStep( newStep );
103 event->setModifiers( event->modifiers() & ~Qt::ControlModifier );
105 QDoubleSpinBox::wheelEvent( event );
106 setSingleStep( step );
111 QDoubleSpinBox::focusOutEvent( event );
121 qApp->processEvents();
122 if ( QApplication::mouseButtons() & Qt::LeftButton )
123 QDoubleSpinBox::timerEvent( event );
128 mLineEdit->setShowClearButton( shouldShowClearForValue( value() ) );
129 QDoubleSpinBox::paintEvent( event );
134 const bool wasNull = mShowClearButton && value() ==
clearValue();
135 if ( wasNull && minimum() < 0 && maximum() > 0 && !( specialValueText().isEmpty() || specialValueText() == SPECIAL_TEXT_WHEN_EMPTY ) )
143 QDoubleSpinBox::stepBy( steps );
148 return mLastEditTimer->interval();
153 mLastEditTimer->setInterval( timeout );
156void QgsDoubleSpinBox::changed(
double value )
158 mLineEdit->setShowClearButton( shouldShowClearForValue( value ) );
159 mLastEditTimer->start();
162void QgsDoubleSpinBox::onLastEditTimeout()
164 mLastEditTimer->stop();
165 const double currentValue = value();
166 if ( std::isnan( mLastEditTimeoutValue ) || mLastEditTimeoutValue != currentValue )
168 mLastEditTimeoutValue = currentValue;
176 if ( mLineEdit->isNull() )
182 if ( mClearValueMode ==
CustomValue && mCustomClearValue == customValue && QAbstractSpinBox::specialValueText() == specialValueText )
188 mCustomClearValue = customValue;
190 if ( !specialValueText.isEmpty() )
192 const double v = value();
201 if ( mClearValueMode == mode && mCustomClearValue == 0 && QAbstractSpinBox::specialValueText() == clearValueText )
206 mClearValueMode = mode;
207 mCustomClearValue = 0;
209 if ( !clearValueText.isEmpty() )
211 const double v = value();
225 return mCustomClearValue;
230 mLineEdit->setAlignment( alignment );
237 QDoubleSpinBox::setSpecialValueText( SPECIAL_TEXT_WHEN_EMPTY );
238 mLineEdit->setNullValue( SPECIAL_TEXT_WHEN_EMPTY );
242 QDoubleSpinBox::setSpecialValueText( txt );
243 mLineEdit->setNullValue( txt );
247QString QgsDoubleSpinBox::stripped(
const QString &originalText )
const
251 QString text = originalText;
252 if ( specialValueText().isEmpty() || text != specialValueText() )
255 if ( text.contains( SPECIAL_TEXT_WHEN_EMPTY ) )
256 text = text.replace( SPECIAL_TEXT_WHEN_EMPTY, QString() );
258 int size = text.size();
259 bool changed =
false;
260 if ( !prefix().isEmpty() && text.startsWith( prefix() ) )
262 from += prefix().size();
266 if ( !suffix().isEmpty() && text.endsWith( suffix() ) )
268 size -= suffix().size();
272 text = text.mid( from, size );
275 text = text.trimmed();
282 if ( !mExpressionsEnabled )
284 return QDoubleSpinBox::valueFromText( text );
287 const QString trimmedText = stripped( text );
288 if ( trimmedText.isEmpty() )
290 return mShowClearButton ?
clearValue() : value();
298 if ( !mExpressionsEnabled )
300 const QValidator::State r = QDoubleSpinBox::validate( input, pos );
304 return QValidator::Acceptable;
307int QgsDoubleSpinBox::frameWidth()
const
309 return style()->pixelMetric( QStyle::PM_DefaultFrameWidth );
312bool QgsDoubleSpinBox::shouldShowClearForValue(
const double value )
const
314 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.
bool isCleared() const
Returns true if the value is equal to the clear 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.