QGIS API Documentation  3.0.2-Girona (307d082)
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  setLocale( QLocale( QgsApplication::locale( ) ) );
36  setLineEdit( mLineEdit );
37 
38  QSize msz = minimumSizeHint();
39  setMinimumSize( msz.width() + CLEAR_ICON_SIZE + 9 + frameWidth() * 2 + 2,
40  std::max( msz.height(), CLEAR_ICON_SIZE + frameWidth() * 2 + 2 ) );
41 
42  connect( mLineEdit, &QgsFilterLineEdit::cleared, this, &QgsDoubleSpinBox::clear );
43  connect( this, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsDoubleSpinBox::changed );
44 }
45 
47 {
48  mShowClearButton = showClearButton;
49  mLineEdit->setShowClearButton( showClearButton );
50 }
51 
52 void QgsDoubleSpinBox::setExpressionsEnabled( const bool enabled )
53 {
54  mExpressionsEnabled = enabled;
55 }
56 
57 void QgsDoubleSpinBox::changeEvent( QEvent *event )
58 {
59  QDoubleSpinBox::changeEvent( event );
60  mLineEdit->setShowClearButton( shouldShowClearForValue( value() ) );
61 }
62 
63 void QgsDoubleSpinBox::wheelEvent( QWheelEvent *event )
64 {
65  double step = singleStep();
66  if ( event->modifiers() & Qt::ControlModifier )
67  {
68  // ctrl modifier results in finer increments - 10% of usual step
69  double newStep = step / 10;
70  // but don't ever use an increment smaller than would be visible in the widget
71  // i.e. if showing 2 decimals, smallest increment will be 0.01
72  newStep = std::max( newStep, std::pow( 10.0, 0.0 - decimals() ) );
73 
74  setSingleStep( newStep );
75 
76  // clear control modifier before handing off event - Qt uses it for unwanted purposes
77  // (*increasing* step size, whereas QGIS UX convention is that control modifier
78  // results in finer changes!)
79  event->setModifiers( event->modifiers() & ~Qt::ControlModifier );
80  }
81  QDoubleSpinBox::wheelEvent( event );
82  setSingleStep( step );
83 }
84 
85 void QgsDoubleSpinBox::paintEvent( QPaintEvent *event )
86 {
87  mLineEdit->setShowClearButton( shouldShowClearForValue( value() ) );
88  QDoubleSpinBox::paintEvent( event );
89 }
90 
91 void QgsDoubleSpinBox::changed( double value )
92 {
93  mLineEdit->setShowClearButton( shouldShowClearForValue( value ) );
94 }
95 
97 {
98  setValue( clearValue() );
99 }
100 
101 void QgsDoubleSpinBox::setClearValue( double customValue, const QString &specialValueText )
102 {
103  mClearValueMode = CustomValue;
104  mCustomClearValue = customValue;
105 
106  if ( !specialValueText.isEmpty() )
107  {
108  double v = value();
109  clear();
110  setSpecialValueText( specialValueText );
111  setValue( v );
112  }
113 }
114 
116 {
117  mClearValueMode = mode;
118  mCustomClearValue = 0;
119 
120  if ( !clearValueText.isEmpty() )
121  {
122  double v = value();
123  clear();
124  setSpecialValueText( clearValueText );
125  setValue( v );
126  }
127 }
128 
129 double QgsDoubleSpinBox::clearValue() const
130 {
131  if ( mClearValueMode == MinimumValue )
132  return minimum();
133  else if ( mClearValueMode == MaximumValue )
134  return maximum();
135  else
136  return mCustomClearValue;
137 }
138 
139 void QgsDoubleSpinBox::setLineEditAlignment( Qt::Alignment alignment )
140 {
141  mLineEdit->setAlignment( alignment );
142 }
143 
144 QString QgsDoubleSpinBox::stripped( const QString &originalText ) const
145 {
146  //adapted from QAbstractSpinBoxPrivate::stripped
147  //trims whitespace, prefix and suffix from spin box text
148  QString text = originalText;
149  if ( specialValueText().isEmpty() || text != specialValueText() )
150  {
151  int from = 0;
152  int size = text.size();
153  bool changed = false;
154  if ( !prefix().isEmpty() && text.startsWith( prefix() ) )
155  {
156  from += prefix().size();
157  size -= from;
158  changed = true;
159  }
160  if ( !suffix().isEmpty() && text.endsWith( suffix() ) )
161  {
162  size -= suffix().size();
163  changed = true;
164  }
165  if ( changed )
166  text = text.mid( from, size );
167  }
168 
169  text = text.trimmed();
170 
171  return text;
172 }
173 
174 double QgsDoubleSpinBox::valueFromText( const QString &text ) const
175 {
176  if ( !mExpressionsEnabled )
177  {
178  return QDoubleSpinBox::valueFromText( text );
179  }
180 
181  QString trimmedText = stripped( text );
182  if ( trimmedText.isEmpty() )
183  {
184  return mShowClearButton ? clearValue() : value();
185  }
186 
187  return QgsExpression::evaluateToDouble( trimmedText, value() );
188 }
189 
190 QValidator::State QgsDoubleSpinBox::validate( QString &input, int &pos ) const
191 {
192  if ( !mExpressionsEnabled )
193  {
194  QValidator::State r = QDoubleSpinBox::validate( input, pos );
195  return r;
196  }
197 
198  return QValidator::Acceptable;
199 }
200 
201 int QgsDoubleSpinBox::frameWidth() const
202 {
203  return style()->pixelMetric( QStyle::PM_DefaultFrameWidth );
204 }
205 
206 bool QgsDoubleSpinBox::shouldShowClearForValue( const double value ) const
207 {
208  if ( !mShowClearButton || !isEnabled() )
209  {
210  return false;
211  }
212  return value != clearValue();
213 }
void wheelEvent(QWheelEvent *event) override
static QString locale()
Returns the QGIS locale.
void paintEvent(QPaintEvent *e) override
QValidator::State validate(QString &input, int &pos) const override
Reset value to custom value (see setClearValue() )
Reset value to maximum()
QgsDoubleSpinBox(QWidget *parent=nullptr)
Constructor for QgsDoubleSpinBox.
ClearValueMode
Behavior when widget is cleared.
#define CLEAR_ICON_SIZE
void clear() override
Set the current value to the value defined by the clear value.
void setShowClearButton(const bool showClearButton)
Sets whether the widget will show a clear button.
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()
void setExpressionsEnabled(const bool enabled)
Sets if the widget will allow entry of simple expressions, which are evaluated and then discarded...