29#include "moc_qgsspinbox.cpp"
31#define CLEAR_ICON_SIZE 16
37static QChar SPECIAL_TEXT_WHEN_EMPTY = QChar( 0x2063 );
39static constexpr QChar SPECIAL_TEXT_WHEN_EMPTY = QChar( 0x2063 );
45 mLineEdit =
new QgsSpinBoxLineEdit();
48 setLineEdit( mLineEdit );
50 const QSize msz = minimumSizeHint();
54 connect(
this,
static_cast<void ( QSpinBox::* )(
int )
>( &QSpinBox::valueChanged ),
this, &QgsSpinBox::changed );
56 mLastEditTimer =
new QTimer(
this );
57 mLastEditTimer->setSingleShot(
true );
58 mLastEditTimer->setInterval( 1000 );
59 connect( mLastEditTimer, &QTimer::timeout,
this, &QgsSpinBox::onLastEditTimeout );
70 mExpressionsEnabled = enabled;
75 QSpinBox::changeEvent( event );
77 if ( event->type() == QEvent::FontChange )
79 lineEdit()->setFont( font() );
82 mLineEdit->setShowClearButton( shouldShowClearForValue( value() ) );
87 mLineEdit->setShowClearButton( shouldShowClearForValue( value() ) );
88 QSpinBox::paintEvent( event );
93 const int step = singleStep();
94 if ( event->modifiers() & Qt::ControlModifier )
97 int newStep = step / 10;
99 newStep = std::max( newStep, 1 );
101 setSingleStep( newStep );
106 event->setModifiers( event->modifiers() & ~Qt::ControlModifier );
108 QSpinBox::wheelEvent( event );
109 setSingleStep( step );
118 qApp->processEvents();
119 if ( QApplication::mouseButtons() & Qt::LeftButton )
120 QSpinBox::timerEvent( event );
125 QSpinBox::focusOutEvent( event );
129void QgsSpinBox::changed(
int value )
131 mLineEdit->setShowClearButton( shouldShowClearForValue( value ) );
132 mLastEditTimer->start();
135void QgsSpinBox::onLastEditTimeout()
137 mLastEditTimer->stop();
138 const int currentValue = value();
139 if ( !mHasEmittedEditTimeout || mLastEditTimeoutValue != currentValue )
141 mHasEmittedEditTimeout =
true;
142 mLastEditTimeoutValue = currentValue;
150 if ( mLineEdit->isNull() )
156 if ( mClearValueMode ==
CustomValue && mCustomClearValue == customValue && QAbstractSpinBox::specialValueText() == specialValueText )
162 mCustomClearValue = customValue;
164 if ( !specialValueText.isEmpty() )
166 const int v = value();
175 if ( mClearValueMode == mode && mCustomClearValue == 0 && QAbstractSpinBox::specialValueText() == specialValueText )
180 mClearValueMode = mode;
181 mCustomClearValue = 0;
183 if ( !specialValueText.isEmpty() )
185 const int v = value();
199 return mCustomClearValue;
204 mLineEdit->setAlignment( alignment );
211 QSpinBox::setSpecialValueText( SPECIAL_TEXT_WHEN_EMPTY );
212 mLineEdit->setNullValue( SPECIAL_TEXT_WHEN_EMPTY );
216 QSpinBox::setSpecialValueText( txt );
217 mLineEdit->setNullValue( txt );
223 if ( !mExpressionsEnabled )
225 return QSpinBox::valueFromText( text );
228 const QString trimmedText = stripped( text );
229 if ( trimmedText.isEmpty() )
231 return mShowClearButton ?
clearValue() : value();
239 if ( !mExpressionsEnabled )
241 const QValidator::State r = QSpinBox::validate( input, pos );
245 return QValidator::Acceptable;
250 const bool wasNull = mShowClearButton && value() ==
clearValue();
251 if ( wasNull && minimum() < 0 && maximum() > 0 && !( specialValueText().isEmpty() || specialValueText() == SPECIAL_TEXT_WHEN_EMPTY ) )
259 QSpinBox::stepBy( steps );
264 return mLastEditTimer->interval();
269 mLastEditTimer->setInterval( timeout );
272int QgsSpinBox::frameWidth()
const
274 return style()->pixelMetric( QStyle::PM_DefaultFrameWidth );
277bool QgsSpinBox::shouldShowClearForValue(
const int value )
const
279 if ( !mShowClearButton || !isEnabled() )
286QString QgsSpinBox::stripped(
const QString &originalText )
const
290 QString text = originalText;
291 if ( specialValueText().isEmpty() || text != specialValueText() )
294 if ( text.contains( SPECIAL_TEXT_WHEN_EMPTY ) )
295 text = text.replace( SPECIAL_TEXT_WHEN_EMPTY, QString() );
297 int size = text.size();
298 bool changed =
false;
299 if ( !prefix().isEmpty() && text.startsWith( prefix() ) )
301 from += prefix().size();
305 if ( !suffix().isEmpty() && text.endsWith( suffix() ) )
307 size -= suffix().size();
311 text = text.mid( from, size );
314 text = text.trimmed();
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.
void setLineEditAlignment(Qt::Alignment alignment)
Set alignment in the embedded line edit widget.
void returnPressed()
Emitted when the Return or Enter key is used in the line edit.
ClearValueMode
Behavior when widget is cleared.
@ MaximumValue
Reset value to maximum().
@ MinimumValue
Reset value to minimum().
@ CustomValue
Reset value to custom value (see setClearValue() ).
void wheelEvent(QWheelEvent *event) override
void editingTimeout(int value)
Emitted when either:
void setShowClearButton(bool showClearButton)
Sets whether the widget will show a clear button.
void focusOutEvent(QFocusEvent *event) override
QgsSpinBox(QWidget *parent=nullptr)
Constructor for QgsSpinBox.
QValidator::State validate(QString &input, int &pos) const override
void stepBy(int steps) override
void textEdited(const QString &text)
Emitted when the the value has been manually edited via line edit.
void paintEvent(QPaintEvent *event) override
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.
int valueFromText(const QString &text) const override
void setEditingTimeoutInterval(int timeout)
Sets the timeout (in milliseconds) threshold for the editingTimeout() signal to be emitted after an e...
int editingTimeoutInterval() const
Returns the timeout (in milliseconds) threshold for the editingTimeout() signal to be emitted after a...
void timerEvent(QTimerEvent *event) override
void setClearValue(int customValue, const QString &clearValueText=QString())
Defines the clear value as a custom value and will automatically set the clear value mode to CustomVa...
void setExpressionsEnabled(bool enabled)
Sets if the widget will allow entry of simple expressions, which are evaluated and then discarded.
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 changeEvent(QEvent *event) override
void clear() override
Sets the current value to the value defined by the clear value.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.