23#include "moc_qgsspinbox.cpp"
29#define CLEAR_ICON_SIZE 16
35static QChar SPECIAL_TEXT_WHEN_EMPTY = QChar( 0x2063 );
37static constexpr QChar SPECIAL_TEXT_WHEN_EMPTY = QChar( 0x2063 );
43 mLineEdit =
new QgsSpinBoxLineEdit();
46 setLineEdit( mLineEdit );
48 const QSize msz = minimumSizeHint();
52 connect(
this,
static_cast<void ( QSpinBox::* )(
int )
>( &QSpinBox::valueChanged ),
this, &QgsSpinBox::changed );
54 mLastEditTimer =
new QTimer(
this );
55 mLastEditTimer->setSingleShot(
true );
56 mLastEditTimer->setInterval( 1000 );
57 connect( mLastEditTimer, &QTimer::timeout,
this, &QgsSpinBox::onLastEditTimeout );
68 mExpressionsEnabled = enabled;
73 QSpinBox::changeEvent( event );
75 if ( event->type() == QEvent::FontChange )
77 lineEdit()->setFont( font() );
80 mLineEdit->setShowClearButton( shouldShowClearForValue( value() ) );
85 mLineEdit->setShowClearButton( shouldShowClearForValue( value() ) );
86 QSpinBox::paintEvent( event );
91 const int step = singleStep();
92 if ( event->modifiers() & Qt::ControlModifier )
95 int newStep = step / 10;
97 newStep = std::max( newStep, 1 );
99 setSingleStep( newStep );
104 event->setModifiers( event->modifiers() & ~Qt::ControlModifier );
106 QSpinBox::wheelEvent( event );
107 setSingleStep( step );
116 qApp->processEvents();
117 if ( QApplication::mouseButtons() & Qt::LeftButton )
118 QSpinBox::timerEvent( event );
123 QSpinBox::focusOutEvent( event );
127void QgsSpinBox::changed(
int value )
129 mLineEdit->setShowClearButton( shouldShowClearForValue( value ) );
130 mLastEditTimer->start();
133void QgsSpinBox::onLastEditTimeout()
135 mLastEditTimer->stop();
136 const int currentValue = value();
137 if ( !mHasEmittedEditTimeout || mLastEditTimeoutValue != currentValue )
139 mHasEmittedEditTimeout =
true;
140 mLastEditTimeoutValue = currentValue;
148 if ( mLineEdit->isNull() )
154 if ( mClearValueMode ==
CustomValue && mCustomClearValue == customValue && QAbstractSpinBox::specialValueText() == specialValueText )
160 mCustomClearValue = customValue;
162 if ( !specialValueText.isEmpty() )
164 const int v = value();
173 if ( mClearValueMode == mode && mCustomClearValue == 0 && QAbstractSpinBox::specialValueText() == specialValueText )
178 mClearValueMode = mode;
179 mCustomClearValue = 0;
181 if ( !specialValueText.isEmpty() )
183 const int v = value();
197 return mCustomClearValue;
202 mLineEdit->setAlignment( alignment );
209 QSpinBox::setSpecialValueText( SPECIAL_TEXT_WHEN_EMPTY );
210 mLineEdit->setNullValue( SPECIAL_TEXT_WHEN_EMPTY );
214 QSpinBox::setSpecialValueText( txt );
215 mLineEdit->setNullValue( txt );
221 if ( !mExpressionsEnabled )
223 return QSpinBox::valueFromText( text );
226 const QString trimmedText = stripped( text );
227 if ( trimmedText.isEmpty() )
229 return mShowClearButton ?
clearValue() : value();
237 if ( !mExpressionsEnabled )
239 const QValidator::State r = QSpinBox::validate( input, pos );
243 return QValidator::Acceptable;
248 const bool wasNull = mShowClearButton && value() ==
clearValue();
249 if ( wasNull && minimum() < 0 && maximum() > 0 && !( specialValueText().isEmpty() || specialValueText() == SPECIAL_TEXT_WHEN_EMPTY ) )
257 QSpinBox::stepBy( steps );
262 return mLastEditTimer->interval();
267 mLastEditTimer->setInterval( timeout );
270int QgsSpinBox::frameWidth()
const
272 return style()->pixelMetric( QStyle::PM_DefaultFrameWidth );
275bool QgsSpinBox::shouldShowClearForValue(
const int value )
const
277 if ( !mShowClearButton || !isEnabled() )
284QString QgsSpinBox::stripped(
const QString &originalText )
const
288 QString text = originalText;
289 if ( specialValueText().isEmpty() || text != specialValueText() )
292 if ( text.contains( SPECIAL_TEXT_WHEN_EMPTY ) )
293 text = text.replace( SPECIAL_TEXT_WHEN_EMPTY, QString() );
295 int size = text.size();
296 bool changed =
false;
297 if ( !prefix().isEmpty() && text.startsWith( prefix() ) )
299 from += prefix().size();
303 if ( !suffix().isEmpty() && text.endsWith( suffix() ) )
305 size -= suffix().size();
309 text = text.mid( from, size );
312 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.