QGIS API Documentation  3.2.0-Bonn (bc43194)
qgsdoublespinbox.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsdoublespinbox.cpp
3  --------------------------------------
4  Date : 09.2014
5  Copyright : (C) 2014 Denis Rouzaud
6  Email : [email protected]
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include <QLineEdit>
17 #include <QMouseEvent>
18 #include <QSettings>
19 #include <QStyle>
20 
21 #include "qgsdoublespinbox.h"
22 #include "qgsexpression.h"
23 #include "qgsapplication.h"
24 #include "qgslogger.h"
25 #include "qgsfilterlineedit.h"
26 
27 #define CLEAR_ICON_SIZE 16
28 
30  : QDoubleSpinBox( parent )
31 {
32  mLineEdit = new QgsSpinBoxLineEdit();
33 
34  // By default, group separator is off
35  setLineEdit( mLineEdit );
36 
37  QSize msz = minimumSizeHint();
38  setMinimumSize( msz.width() + CLEAR_ICON_SIZE + 9 + frameWidth() * 2 + 2,
39  std::max( msz.height(), CLEAR_ICON_SIZE + frameWidth() * 2 + 2 ) );
40 
41  connect( mLineEdit, &QgsFilterLineEdit::cleared, this, &QgsDoubleSpinBox::clear );
42  connect( this, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsDoubleSpinBox::changed );
43 }
44 
46 {
47  mShowClearButton = showClearButton;
48  mLineEdit->setShowClearButton( showClearButton );
49 }
50 
51 void QgsDoubleSpinBox::setExpressionsEnabled( const bool enabled )
52 {
53  mExpressionsEnabled = enabled;
54 }
55 
56 void QgsDoubleSpinBox::changeEvent( QEvent *event )
57 {
58  QDoubleSpinBox::changeEvent( event );
59  mLineEdit->setShowClearButton( shouldShowClearForValue( value() ) );
60 }
61 
62 void QgsDoubleSpinBox::wheelEvent( QWheelEvent *event )
63 {
64  double step = singleStep();
65  if ( event->modifiers() & Qt::ControlModifier )
66  {
67  // ctrl modifier results in finer increments - 10% of usual step
68  double newStep = step / 10;
69  // but don't ever use an increment smaller than would be visible in the widget
70  // i.e. if showing 2 decimals, smallest increment will be 0.01
71  newStep = std::max( newStep, std::pow( 10.0, 0.0 - decimals() ) );
72 
73  setSingleStep( newStep );
74 
75  // clear control modifier before handing off event - Qt uses it for unwanted purposes
76  // (*increasing* step size, whereas QGIS UX convention is that control modifier
77  // results in finer changes!)
78  event->setModifiers( event->modifiers() & ~Qt::ControlModifier );
79  }
80  QDoubleSpinBox::wheelEvent( event );
81  setSingleStep( step );
82 }
83 
84 void QgsDoubleSpinBox::paintEvent( QPaintEvent *event )
85 {
86  mLineEdit->setShowClearButton( shouldShowClearForValue( value() ) );
87  QDoubleSpinBox::paintEvent( event );
88 }
89 
90 void QgsDoubleSpinBox::changed( double value )
91 {
92  mLineEdit->setShowClearButton( shouldShowClearForValue( value ) );
93 }
94 
96 {
97  setValue( clearValue() );
98 }
99 
100 void QgsDoubleSpinBox::setClearValue( double customValue, const QString &specialValueText )
101 {
102  mClearValueMode = CustomValue;
103  mCustomClearValue = customValue;
104 
105  if ( !specialValueText.isEmpty() )
106  {
107  double v = value();
108  clear();
109  setSpecialValueText( specialValueText );
110  setValue( v );
111  }
112 }
113 
115 {
116  mClearValueMode = mode;
117  mCustomClearValue = 0;
118 
119  if ( !clearValueText.isEmpty() )
120  {
121  double v = value();
122  clear();
123  setSpecialValueText( clearValueText );
124  setValue( v );
125  }
126 }
127 
128 double QgsDoubleSpinBox::clearValue() const
129 {
130  if ( mClearValueMode == MinimumValue )
131  return minimum();
132  else if ( mClearValueMode == MaximumValue )
133  return maximum();
134  else
135  return mCustomClearValue;
136 }
137 
138 void QgsDoubleSpinBox::setLineEditAlignment( Qt::Alignment alignment )
139 {
140  mLineEdit->setAlignment( alignment );
141 }
142 
143 QString QgsDoubleSpinBox::stripped( const QString &originalText ) const
144 {
145  //adapted from QAbstractSpinBoxPrivate::stripped
146  //trims whitespace, prefix and suffix from spin box text
147  QString text = originalText;
148  if ( specialValueText().isEmpty() || text != specialValueText() )
149  {
150  int from = 0;
151  int size = text.size();
152  bool changed = false;
153  if ( !prefix().isEmpty() && text.startsWith( prefix() ) )
154  {
155  from += prefix().size();
156  size -= from;
157  changed = true;
158  }
159  if ( !suffix().isEmpty() && text.endsWith( suffix() ) )
160  {
161  size -= suffix().size();
162  changed = true;
163  }
164  if ( changed )
165  text = text.mid( from, size );
166  }
167 
168  text = text.trimmed();
169 
170  return text;
171 }
172 
173 double QgsDoubleSpinBox::valueFromText( const QString &text ) const
174 {
175  if ( !mExpressionsEnabled )
176  {
177  return QDoubleSpinBox::valueFromText( text );
178  }
179 
180  QString trimmedText = stripped( text );
181  if ( trimmedText.isEmpty() )
182  {
183  return mShowClearButton ? clearValue() : value();
184  }
185 
186  return QgsExpression::evaluateToDouble( trimmedText, value() );
187 }
188 
189 QValidator::State QgsDoubleSpinBox::validate( QString &input, int &pos ) const
190 {
191  if ( !mExpressionsEnabled )
192  {
193  QValidator::State r = QDoubleSpinBox::validate( input, pos );
194  return r;
195  }
196 
197  return QValidator::Acceptable;
198 }
199 
200 int QgsDoubleSpinBox::frameWidth() const
201 {
202  return style()->pixelMetric( QStyle::PM_DefaultFrameWidth );
203 }
204 
205 bool QgsDoubleSpinBox::shouldShowClearForValue( const double value ) const
206 {
207  if ( !mShowClearButton || !isEnabled() )
208  {
209  return false;
210  }
211  return value != clearValue();
212 }
void wheelEvent(QWheelEvent *event) override
void paintEvent(QPaintEvent *e) override
void setExpressionsEnabled(bool enabled)
Sets if the widget will allow entry of simple expressions, which are evaluated and then discarded...
QValidator::State validate(QString &input, int &pos) const override
void setShowClearButton(bool showClearButton)
Sets whether the widget will show a clear button.
Reset value to custom value (see setClearValue() )
static double evaluateToDouble(const QString &text, double fallbackValue)
Attempts to evaluate a text string as an expression to a resultant double value.
Reset value to maximum()
QgsDoubleSpinBox(QWidget *parent=nullptr)
Constructor for QgsDoubleSpinBox.
ClearValueMode
Behavior when widget is cleared.
#define CLEAR_ICON_SIZE
void clear() override
Sets the current value to the value defined by the clear value.
bool showClearButton() const
Returns whether the widget is showing a clear button.
double valueFromText(const QString &text) const override
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...
double clearValue() const
Returns the value used when clear() is called.
void changeEvent(QEvent *event) override
void setLineEditAlignment(Qt::Alignment alignment)
Set alignment in the embedded line edit widget.
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...
void cleared()
Emitted when the widget is cleared.
Reset value to minimum()