31#include "moc_qgsdoublespinbox.cpp"
33#define CLEAR_ICON_SIZE 16
39static QChar SPECIAL_TEXT_WHEN_EMPTY = QChar( 0x2063 );
41static constexpr QChar SPECIAL_TEXT_WHEN_EMPTY = QChar( 0x2063 );
46 : QDoubleSpinBox( parent )
48 mLineEdit =
new QgsSpinBoxLineEdit();
52 setLineEdit( mLineEdit );
54 const QSize msz = minimumSizeHint();
58 connect(
this,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsDoubleSpinBox::changed );
60 mLastEditTimer =
new QTimer(
this );
61 mLastEditTimer->setSingleShot(
true );
62 mLastEditTimer->setInterval( 1000 );
63 connect( mLastEditTimer, &QTimer::timeout,
this, &QgsDoubleSpinBox::onLastEditTimeout );
74 mExpressionsEnabled = enabled;
79 QDoubleSpinBox::changeEvent( event );
81 if ( event->type() == QEvent::FontChange )
83 lineEdit()->setFont( font() );
86 mLineEdit->setShowClearButton( shouldShowClearForValue( value() ) );
91 const double step = singleStep();
92 if ( event->modifiers() & Qt::ControlModifier )
95 double newStep = step / 10;
98 newStep = std::max( newStep, std::pow( 10.0, 0.0 - decimals() ) );
100 setSingleStep( newStep );
105 event->setModifiers( event->modifiers() & ~Qt::ControlModifier );
107 QDoubleSpinBox::wheelEvent( event );
108 setSingleStep( step );
113 QDoubleSpinBox::focusOutEvent( event );
123 qApp->processEvents();
124 if ( QApplication::mouseButtons() & Qt::LeftButton )
125 QDoubleSpinBox::timerEvent( event );
130 mLineEdit->setShowClearButton( shouldShowClearForValue( value() ) );
131 QDoubleSpinBox::paintEvent( event );
136 const bool wasNull = mShowClearButton && value() ==
clearValue();
137 if ( wasNull && minimum() < 0 && maximum() > 0 && !( specialValueText().isEmpty() || specialValueText() == SPECIAL_TEXT_WHEN_EMPTY ) )
145 QDoubleSpinBox::stepBy( steps );
150 return mLastEditTimer->interval();
155 mLastEditTimer->setInterval( timeout );
158void QgsDoubleSpinBox::changed(
double value )
160 mLineEdit->setShowClearButton( shouldShowClearForValue( value ) );
161 mLastEditTimer->start();
164void QgsDoubleSpinBox::onLastEditTimeout()
166 mLastEditTimer->stop();
167 const double currentValue = value();
168 if ( std::isnan( mLastEditTimeoutValue ) || mLastEditTimeoutValue != currentValue )
170 mLastEditTimeoutValue = currentValue;
178 if ( mLineEdit->isNull() )
184 if ( mClearValueMode ==
CustomValue && mCustomClearValue == customValue && QAbstractSpinBox::specialValueText() == specialValueText )
190 mCustomClearValue = customValue;
192 if ( !specialValueText.isEmpty() )
194 const double v = value();
203 if ( mClearValueMode == mode && mCustomClearValue == 0 && QAbstractSpinBox::specialValueText() == clearValueText )
208 mClearValueMode = mode;
209 mCustomClearValue = 0;
211 if ( !clearValueText.isEmpty() )
213 const double v = value();
227 return mCustomClearValue;
232 mLineEdit->setAlignment( alignment );
239 QDoubleSpinBox::setSpecialValueText( SPECIAL_TEXT_WHEN_EMPTY );
240 mLineEdit->setNullValue( SPECIAL_TEXT_WHEN_EMPTY );
244 QDoubleSpinBox::setSpecialValueText( txt );
245 mLineEdit->setNullValue( txt );
249QString QgsDoubleSpinBox::stripped(
const QString &originalText )
const
253 QString text = originalText;
254 if ( specialValueText().isEmpty() || text != specialValueText() )
257 if ( text.contains( SPECIAL_TEXT_WHEN_EMPTY ) )
258 text = text.replace( SPECIAL_TEXT_WHEN_EMPTY, QString() );
260 int size = text.size();
261 bool changed =
false;
262 if ( !prefix().isEmpty() && text.startsWith( prefix() ) )
264 from += prefix().size();
268 if ( !suffix().isEmpty() && text.endsWith( suffix() ) )
270 size -= suffix().size();
274 text = text.mid( from, size );
277 text = text.trimmed();
284 if ( !mExpressionsEnabled )
286 return QDoubleSpinBox::valueFromText( text );
289 const QString trimmedText = stripped( text );
290 if ( trimmedText.isEmpty() )
292 return mShowClearButton ?
clearValue() : value();
303 if ( !mExpressionsEnabled )
305 const QValidator::State r = QDoubleSpinBox::validate( input, pos );
309 return QValidator::Acceptable;
312int QgsDoubleSpinBox::frameWidth()
const
314 return style()->pixelMetric( QStyle::PM_DefaultFrameWidth );
317bool QgsDoubleSpinBox::shouldShowClearForValue(
const double value )
const
319 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 std::unique_ptr< QgsExpressionContextScope > globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
static std::unique_ptr< QgsExpressionContextScope > projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
static Q_DECL_DEPRECATED 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.
static QgsProject * instance()
Returns the QgsProject singleton instance.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.