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.
 
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.