QGIS API Documentation  2.99.0-Master (6a61179)
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  , mIntSpinBox( nullptr )
28  , mDoubleSpinBox( nullptr )
29  , mSlider( nullptr )
30  , mDial( nullptr )
31  , mQgsSlider( nullptr )
32  , mQgsDial( nullptr )
33 {
34 }
35 
36 QWidget* QgsRangeWidgetWrapper::createWidget( QWidget* parent )
37 {
38  QWidget* editor = nullptr;
39 
40  if ( config( QStringLiteral( "Style" ) ).toString() == QLatin1String( "Dial" ) )
41  {
42  editor = new QgsDial( parent );
43  }
44  else if ( config( QStringLiteral( "Style" ) ).toString() == QLatin1String( "Slider" ) )
45  {
46  editor = new QgsSlider( Qt::Horizontal, parent );
47  }
48  else
49  {
50  switch ( layer()->fields().at( fieldIdx() ).type() )
51  {
52  case QVariant::Double:
53  {
54  editor = new QgsDoubleSpinBox( parent );
55  break;
56  }
57  case QVariant::Int:
58  case QVariant::LongLong:
59  default:
60  editor = new QgsSpinBox( parent );
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>::min() );
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( valueChanged( int ) ) );
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 
94  if ( mDoubleSpinBox )
95  {
96  // set the precision if field is integer
97  int precision = layer()->fields().at( fieldIdx() ).precision();
98  if ( precision > 0 )
99  {
100  mDoubleSpinBox->setDecimals( layer()->fields().at( fieldIdx() ).precision() );
101  }
102 
103  double minval = min.toDouble();
104  double stepval = step.toDouble();
105  QgsDoubleSpinBox* qgsWidget = dynamic_cast<QgsDoubleSpinBox*>( mDoubleSpinBox );
106  if ( qgsWidget )
107  qgsWidget->setShowClearButton( allowNull );
108  if ( allowNull )
109  {
110  if ( precision > 0 )
111  {
112  minval -= 10 ^ -precision;
113  }
114  else
115  {
116  minval -= stepval;
117  }
118  mDoubleSpinBox->setValue( minval );
119  mDoubleSpinBox->setSpecialValueText( QSettings().value( QStringLiteral( "qgis/nullValue" ), "NULL" ).toString() );
120  }
121  mDoubleSpinBox->setMinimum( min.isValid() ? min.toDouble() : std::numeric_limits<double>::min() );
122  mDoubleSpinBox->setMaximum( max.isValid() ? max.toDouble() : std::numeric_limits<double>::max() );
123  mDoubleSpinBox->setSingleStep( step.isValid() ? step.toDouble() : 1.0 );
124  if ( config( QStringLiteral( "Suffix" ) ).isValid() )
125  mDoubleSpinBox->setSuffix( config( QStringLiteral( "Suffix" ) ).toString() );
126 
127  connect( mDoubleSpinBox, SIGNAL( valueChanged( double ) ), this, SLOT( valueChanged( double ) ) );
128  }
129  else if ( mIntSpinBox )
130  {
131  QgsSpinBox* qgsWidget = dynamic_cast<QgsSpinBox*>( mIntSpinBox );
132  if ( qgsWidget )
133  qgsWidget->setShowClearButton( allowNull );
134  if ( allowNull )
135  {
136  int minval = min.toInt();
137  int stepval = step.toInt();
138  minval -= stepval;
139  mIntSpinBox->setValue( minval );
140  mIntSpinBox->setSpecialValueText( QSettings().value( QStringLiteral( "qgis/nullValue" ), "NULL" ).toString() );
141  }
142  setupIntEditor( min, max, step, mIntSpinBox, this );
143  if ( config( QStringLiteral( "Suffix" ) ).isValid() )
144  mIntSpinBox->setSuffix( config( QStringLiteral( "Suffix" ) ).toString() );
145  }
146  else
147  {
148  field().convertCompatible( min );
149  field().convertCompatible( max );
150  field().convertCompatible( step );
151  if ( mQgsDial ) setupIntEditor( min, max, step, mQgsDial, this );
152  else if ( mQgsSlider ) setupIntEditor( min, max, step, mQgsSlider, this );
153  else if ( mDial ) setupIntEditor( min, max, step, mDial, this );
154  else if ( mSlider ) setupIntEditor( min, max, step, mSlider, this );
155  }
156 }
157 
159 {
160  return mSlider || mDial || mQgsDial || mQgsSlider || mIntSpinBox || mDoubleSpinBox;
161 }
162 
163 void QgsRangeWidgetWrapper::valueChangedVariant( const QVariant& v )
164 {
165  if ( v.type() == QVariant::Int )
166  valueChanged( v.toInt() );
167  if ( v.type() == QVariant::Double )
168  valueChanged( v.toDouble() );
169 }
170 
172 {
173  QVariant value;
174 
175  if ( mDoubleSpinBox )
176  {
177  value = mDoubleSpinBox->value();
178  if ( value == mDoubleSpinBox->minimum() && config( QStringLiteral( "AllowNull" ), true ).toBool() )
179  {
180  value = QVariant( field().type() );
181  }
182  }
183  else if ( mIntSpinBox )
184  {
185  value = mIntSpinBox->value();
186  if ( value == mIntSpinBox->minimum() && config( QStringLiteral( "AllowNull" ), true ).toBool() )
187  {
188  value = QVariant( field().type() );
189  }
190  }
191  else if ( mQgsDial )
192  {
193  value = mQgsDial->variantValue();
194  }
195  else if ( mQgsSlider )
196  {
197  value = mQgsSlider->variantValue();
198  }
199  else if ( mDial )
200  {
201  value = mDial->value();
202  }
203  else if ( mSlider )
204  {
205  value = mSlider->value();
206  }
207 
208  return value;
209 }
210 
211 void QgsRangeWidgetWrapper::setValue( const QVariant& value )
212 {
213  if ( mDoubleSpinBox )
214  {
215  if ( value.isNull() && config( QStringLiteral( "AllowNull" ), true ).toBool() )
216  {
217  mDoubleSpinBox->setValue( mDoubleSpinBox->minimum() );
218  }
219  else
220  {
221  mDoubleSpinBox->setValue( value.toDouble() );
222  }
223  }
224 
225  if ( mIntSpinBox )
226  {
227  if ( value.isNull() && config( QStringLiteral( "AllowNull" ), true ).toBool() )
228  {
229  mIntSpinBox->setValue( mIntSpinBox->minimum() );
230  }
231  else
232  {
233  mIntSpinBox->setValue( value.toInt() );
234  }
235  }
236 
237  if ( mQgsDial )
238  {
239  mQgsDial->setValue( value );
240  }
241  else if ( mQgsSlider )
242  {
243  mQgsSlider->setValue( value );
244  }
245  else if ( mDial )
246  {
247  mDial->setValue( value.toInt() );
248  }
249  else if ( mSlider )
250  {
251  mSlider->setValue( value.toInt() );
252  }
253 }
void setValue(const QVariant &value)
Definition: qgsslider.cpp:65
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.
virtual QWidget * createWidget(QWidget *parent) override
This method should create a new widget with the provided parent.
virtual void initWidget(QWidget *editor) override
This method should initialize the editor widget with runtime data.
int precision
Definition: qgsfield.h:53
void valueChanged()
Will call the value() method to determine the emitted value.
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:229
The QgsSpinBox is a spin box with a clear button that will set the value to the defined clear value...
Definition: qgsspinbox.h:28
void setShowClearButton(const bool showClearButton)
Sets whether the widget will show a clear button.
QgsFields fields() const
Returns the list of fields of this layer.
QgsField at(int i) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:137
void setShowClearButton(const bool showClearButton)
Sets whether the widget will show a clear button.
Definition: qgsspinbox.cpp:48
Wraps a range widget.
double ANALYSIS_EXPORT min(double x, double y)
Returns the minimum of two doubles or the first argument if both are equal.
Definition: MathUtils.cc:452
double ANALYSIS_EXPORT max(double x, double y)
Returns the maximum of two doubles or the first argument if both are equal.
Definition: MathUtils.cc:437
void setValue(const QVariant &value)
Definition: qgsdial.cpp:60
virtual void setValue(const QVariant &value) override
QgsRangeWidgetWrapper(QgsVectorLayer *vl, int fieldIdx, QWidget *editor, QWidget *parent=nullptr)
QVariant variantValue() const
Definition: qgsdial.cpp:106
QgsEditorWidgetConfig config() const
Returns the whole config.
int fieldIdx() const
Access the field index.
static void setupIntEditor(const QVariant &min, const QVariant &max, const QVariant &step, T *slider, QgsRangeWidgetWrapper *wrapper)
QgsVectorLayer * layer() const
Access the QgsVectorLayer, you are working on.
Represents a vector layer which manages a vector based data sets.
virtual QVariant value() const override
Will be used to access the widget&#39;s value.
QVariant variantValue() const
Definition: qgsslider.cpp:111