QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgsrangewidgetwrapper.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrangewidgetwrapper.cpp
3  --------------------------------------
4  Date : 5.1.2014
5  Copyright : (C) 2014 Matthias Kuhn
6  Email : matthias at opengis dot ch
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 <QSettings>
17 
18 #include "qgsrangewidgetwrapper.h"
19 #include "qgsspinbox.h"
20 #include "qgsdoublespinbox.h"
21 #include "qgsvectorlayer.h"
22 #include "qgsdial.h"
23 #include "qgsslider.h"
24 #include "qgsapplication.h"
25 
26 
27 
28 QgsRangeWidgetWrapper::QgsRangeWidgetWrapper( QgsVectorLayer *layer, int fieldIdx, QWidget *editor, QWidget *parent )
29  : QgsEditorWidgetWrapper( layer, fieldIdx, editor, parent )
30 
31 {
32 }
33 
34 QWidget *QgsRangeWidgetWrapper::createWidget( QWidget *parent )
35 {
36  QWidget *editor = nullptr;
37 
38  if ( config( QStringLiteral( "Style" ) ).toString() == QLatin1String( "Dial" ) )
39  {
40  editor = new QgsDial( parent );
41  }
42  else if ( config( QStringLiteral( "Style" ) ).toString() == QLatin1String( "Slider" ) )
43  {
44  editor = new QgsSlider( Qt::Horizontal, parent );
45  }
46  else
47  {
48  switch ( layer()->fields().at( fieldIdx() ).type() )
49  {
50  case QVariant::Double:
51  {
52  editor = new QgsDoubleSpinBox( parent );
53  static_cast<QgsDoubleSpinBox *>( editor )->setLineEditAlignment( Qt::AlignRight );
54  break;
55  }
56  case QVariant::Int:
57  case QVariant::LongLong:
58  default:
59  editor = new QgsSpinBox( parent );
60  static_cast<QgsSpinBox *>( editor )->setLineEditAlignment( Qt::AlignRight );
61  break;
62  }
63  }
64 
65  return editor;
66 }
67 
68 template<class T>
69 static void setupIntEditor( const QVariant &min, const QVariant &max, const QVariant &step, T *slider, QgsRangeWidgetWrapper *wrapper )
70 {
71  // must use a template function because those methods are overloaded and not inherited by some classes
72  slider->setMinimum( min.isValid() ? min.toInt() : std::numeric_limits<int>::lowest() );
73  slider->setMaximum( max.isValid() ? max.toInt() : std::numeric_limits<int>::max() );
74  slider->setSingleStep( step.isValid() ? step.toInt() : 1 );
75  QObject::connect( slider, SIGNAL( valueChanged( int ) ), wrapper, SLOT( emitValueChanged() ) );
76 }
77 
78 void QgsRangeWidgetWrapper::initWidget( QWidget *editor )
79 {
80  mDoubleSpinBox = qobject_cast<QDoubleSpinBox *>( editor );
81  mIntSpinBox = qobject_cast<QSpinBox *>( editor );
82 
83  mDial = qobject_cast<QDial *>( editor );
84  mSlider = qobject_cast<QSlider *>( editor );
85  mQgsDial = qobject_cast<QgsDial *>( editor );
86  mQgsSlider = qobject_cast<QgsSlider *>( editor );
87 
88  bool allowNull = config( QStringLiteral( "AllowNull" ), true ).toBool();
89 
90  QVariant min( config( QStringLiteral( "Min" ) ) );
91  QVariant max( config( QStringLiteral( "Max" ) ) );
92  QVariant step( config( QStringLiteral( "Step" ) ) );
93  QVariant precision( config( QStringLiteral( "Precision" ) ) );
94 
95  if ( mDoubleSpinBox )
96  {
97  double stepval = step.isValid() ? step.toDouble() : 1.0;
98  double minval = min.isValid() ? min.toDouble() : std::numeric_limits<double>::lowest();
99  double maxval = max.isValid() ? max.toDouble() : std::numeric_limits<double>::max();
100  int precisionval = precision.isValid() ? precision.toInt() : layer()->fields().at( fieldIdx() ).precision();
101 
102  mDoubleSpinBox->setDecimals( precisionval );
103 
104  QgsDoubleSpinBox *qgsWidget = qobject_cast<QgsDoubleSpinBox *>( mDoubleSpinBox );
105 
106 
107  if ( qgsWidget )
108  qgsWidget->setShowClearButton( allowNull );
109  // Make room for null value: lower the minimum to allow for NULL special values
110  if ( allowNull )
111  {
112  double decr;
113  if ( precisionval > 0 )
114  {
115  decr = std::pow( 10, -precisionval );
116  }
117  else
118  {
119  decr = stepval;
120  }
121  minval -= decr;
122  // Note: call setMinimum here or setValue won't work
123  mDoubleSpinBox->setMinimum( minval );
124  mDoubleSpinBox->setValue( minval );
125  QgsDoubleSpinBox *doubleSpinBox( qobject_cast<QgsDoubleSpinBox *>( mDoubleSpinBox ) );
126  if ( doubleSpinBox )
128  else
129  mDoubleSpinBox->setSpecialValueText( QgsApplication::nullRepresentation() );
130  }
131  mDoubleSpinBox->setMinimum( minval );
132  mDoubleSpinBox->setMaximum( maxval );
133  mDoubleSpinBox->setSingleStep( stepval );
134  if ( config( QStringLiteral( "Suffix" ) ).isValid() )
135  mDoubleSpinBox->setSuffix( config( QStringLiteral( "Suffix" ) ).toString() );
136 
137  connect( mDoubleSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ),
138  this, [ = ]( double ) { emitValueChanged(); } );
139  }
140  else if ( mIntSpinBox )
141  {
142  QgsSpinBox *qgsWidget = qobject_cast<QgsSpinBox *>( mIntSpinBox );
143  if ( qgsWidget )
144  qgsWidget->setShowClearButton( allowNull );
145  int minval = min.isValid() ? min.toInt() : std::numeric_limits<int>::lowest();
146  int maxval = max.isValid() ? max.toInt() : std::numeric_limits<int>::max();
147  uint stepval = step.isValid() ? step.toUInt() : 1;
148  if ( allowNull )
149  {
150  // make sure there is room for a new value (i.e. signed integer does not overflow)
151  int minvalOverflow = uint( minval ) - stepval;
152  if ( minvalOverflow < minval )
153  {
154  minval = minvalOverflow;
155  }
156  mIntSpinBox->setValue( minval );
157  QgsSpinBox *intSpinBox( qobject_cast<QgsSpinBox *>( mIntSpinBox ) );
158  if ( intSpinBox )
160  else
161  mIntSpinBox->setSpecialValueText( QgsApplication::nullRepresentation() );
162  }
163  setupIntEditor( minval, maxval, stepval, mIntSpinBox, this );
164  if ( config( QStringLiteral( "Suffix" ) ).isValid() )
165  mIntSpinBox->setSuffix( config( QStringLiteral( "Suffix" ) ).toString() );
166  }
167  else
168  {
169  ( void )field().convertCompatible( min );
170  ( void )field().convertCompatible( max );
171  ( void )field().convertCompatible( step );
172  if ( mQgsDial )
173  setupIntEditor( min, max, step, mQgsDial, this );
174  else if ( mQgsSlider )
175  setupIntEditor( min, max, step, mQgsSlider, this );
176  else if ( mDial )
177  setupIntEditor( min, max, step, mDial, this );
178  else if ( mSlider )
179  setupIntEditor( min, max, step, mSlider, this );
180  }
181 }
182 
184 {
185  return mSlider || mDial || mQgsDial || mQgsSlider || mIntSpinBox || mDoubleSpinBox;
186 }
187 
188 void QgsRangeWidgetWrapper::valueChangedVariant( const QVariant &v )
189 {
190  if ( v.type() == QVariant::Int )
191  {
193  emit valueChanged( v.toInt() );
195  emit valuesChanged( v.toInt() );
196  }
197  if ( v.type() == QVariant::Double )
198  {
200  emit valueChanged( v.toDouble() );
202  emit valuesChanged( v.toDouble() );
203  }
204 }
205 
207 {
208  QVariant value;
209 
210  if ( mDoubleSpinBox )
211  {
212  value = mDoubleSpinBox->value();
213  if ( value == mDoubleSpinBox->minimum() && config( QStringLiteral( "AllowNull" ), true ).toBool() )
214  {
215  value = QVariant( field().type() );
216  }
217  }
218  else if ( mIntSpinBox )
219  {
220  value = mIntSpinBox->value();
221  if ( value == mIntSpinBox->minimum() && config( QStringLiteral( "AllowNull" ), true ).toBool() )
222  {
223  value = QVariant( field().type() );
224  }
225  }
226  else if ( mQgsDial )
227  {
228  value = mQgsDial->variantValue();
229  }
230  else if ( mQgsSlider )
231  {
232  value = mQgsSlider->variantValue();
233  }
234  else if ( mDial )
235  {
236  value = mDial->value();
237  }
238  else if ( mSlider )
239  {
240  value = mSlider->value();
241  }
242 
243  return value;
244 }
245 
246 void QgsRangeWidgetWrapper::updateValues( const QVariant &value, const QVariantList & )
247 {
248  if ( mDoubleSpinBox )
249  {
250  if ( value.isNull() && config( QStringLiteral( "AllowNull" ), true ).toBool() )
251  {
252  mDoubleSpinBox->setValue( mDoubleSpinBox->minimum() );
253  }
254  else
255  {
256  mDoubleSpinBox->setValue( value.toDouble() );
257  }
258  }
259 
260  if ( mIntSpinBox )
261  {
262  if ( value.isNull() && config( QStringLiteral( "AllowNull" ), true ).toBool() )
263  {
264  mIntSpinBox->setValue( mIntSpinBox->minimum() );
265  }
266  else
267  {
268  mIntSpinBox->setValue( value.toInt() );
269  }
270  }
271 
272  if ( mQgsDial )
273  {
274  mQgsDial->setValue( value );
275  }
276  else if ( mQgsSlider )
277  {
278  mQgsSlider->setValue( value );
279  }
280  else if ( mDial )
281  {
282  mDial->setValue( value.toInt() );
283  }
284  else if ( mSlider )
285  {
286  mSlider->setValue( value.toInt() );
287  }
288 }
QgsRangeWidgetWrapper::value
QVariant value() const override
Will be used to access the widget's value.
Definition: qgsrangewidgetwrapper.cpp:206
QgsSpinBox::setShowClearButton
void setShowClearButton(bool showClearButton)
Sets whether the widget will show a clear button.
Definition: qgsspinbox.cpp:52
qgsdoublespinbox.h
QgsRangeWidgetWrapper::valid
bool valid() const override
Returns true if the widget has been properly initialized.
Definition: qgsrangewidgetwrapper.cpp:183
qgsrangewidgetwrapper.h
QgsRangeWidgetWrapper::createWidget
QWidget * createWidget(QWidget *parent) override
This method should create a new widget with the provided parent.
Definition: qgsrangewidgetwrapper.cpp:34
QgsDial::variantValue
QVariant variantValue() const
Definition: qgsdial.cpp:106
QgsSlider::variantValue
QVariant variantValue() const
Definition: qgsslider.cpp:111
QgsEditorWidgetWrapper
Manages an editor widget Widget and wrapper share the same parent.
Definition: qgseditorwidgetwrapper.h:48
QgsRangeWidgetWrapper::initWidget
void initWidget(QWidget *editor) override
This method should initialize the editor widget with runtime data.
Definition: qgsrangewidgetwrapper.cpp:78
QgsEditorWidgetWrapper::fieldIdx
int fieldIdx() const
Access the field index.
Definition: qgseditorwidgetwrapper.cpp:34
qgsapplication.h
QgsEditorWidgetWrapper::valueChanged
Q_DECL_DEPRECATED void valueChanged(const QVariant &value)
Emit this signal, whenever the value changed.
QgsVectorLayer::fields
QgsFields fields() const FINAL
Returns the list of fields of this layer.
Definition: qgsvectorlayer.cpp:3283
Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:797
QgsField::precision
int precision
Definition: qgsfield.h:56
precision
int precision
Definition: qgswfsgetfeature.cpp:49
QgsSlider
Definition: qgsslider.h:30
QgsSpinBox::setSpecialValueText
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...
Definition: qgsspinbox.cpp:168
QgsRangeWidgetWrapper
Wraps a range widget.
Definition: qgsrangewidgetwrapper.h:49
QgsWidgetWrapper::layer
QgsVectorLayer * layer() const
Returns the vector layer associated with the widget.
Definition: qgswidgetwrapper.cpp:91
QgsApplication::nullRepresentation
static QString nullRepresentation()
This string is used to represent the value NULL throughout QGIS.
Definition: qgsapplication.cpp:1851
qgsspinbox.h
QgsEditorWidgetWrapper::field
QgsField field() const
Access the field.
Definition: qgseditorwidgetwrapper.cpp:39
QgsEditorWidgetWrapper::emitValueChanged
void emitValueChanged()
Will call the value() method to determine the emitted value.
Definition: qgseditorwidgetwrapper.cpp:91
QgsDoubleSpinBox::setShowClearButton
void setShowClearButton(bool showClearButton)
Sets whether the widget will show a clear button.
Definition: qgsdoublespinbox.cpp:55
QgsSpinBox
The QgsSpinBox is a spin box with a clear button that will set the value to the defined clear value.
Definition: qgsspinbox.h:43
QgsRangeWidgetWrapper::QgsRangeWidgetWrapper
QgsRangeWidgetWrapper(QgsVectorLayer *layer, int fieldIdx, QWidget *editor, QWidget *parent=nullptr)
Constructor for QgsRangeWidgetWrapper.
Definition: qgsrangewidgetwrapper.cpp:28
qgsvectorlayer.h
QgsDoubleSpinBox::setSpecialValueText
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...
Definition: qgsdoublespinbox.cpp:172
QgsDial::setValue
void setValue(const QVariant &value)
Definition: qgsdial.cpp:60
QgsEditorWidgetWrapper::valuesChanged
void valuesChanged(const QVariant &value, const QVariantList &additionalFieldValues=QVariantList())
Emit this signal, whenever the value changed.
QgsSlider::setValue
void setValue(const QVariant &value)
Definition: qgsslider.cpp:65
QgsWidgetWrapper::config
QVariantMap config() const
Returns the whole config.
Definition: qgswidgetwrapper.cpp:81
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:387
QgsDoubleSpinBox
The QgsSpinBox is a spin box with a clear button that will set the value to the defined clear value.
Definition: qgsdoublespinbox.h:43
qgsdial.h
QgsFields::at
QgsField at(int i) const
Gets field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:163
Q_NOWARN_DEPRECATED_PUSH
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:796
QgsDial
Definition: qgsdial.h:30
QgsField::convertCompatible
bool convertCompatible(QVariant &v, QString *errorMessage=nullptr) const
Converts the provided variant to a compatible format.
Definition: qgsfield.cpp:371
qgsslider.h