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