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