QGIS API Documentation  2.99.0-Master (b698612)
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( QgsApplication::nullRepresentation() );
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, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ),
128  this, static_cast < void ( QgsEditorWidgetWrapper::* )( double ) > ( &QgsEditorWidgetWrapper::valueChanged ) );
129  }
130  else if ( mIntSpinBox )
131  {
132  QgsSpinBox *qgsWidget = dynamic_cast<QgsSpinBox *>( mIntSpinBox );
133  if ( qgsWidget )
134  qgsWidget->setShowClearButton( allowNull );
135  if ( allowNull )
136  {
137  int minval = min.toInt();
138  int stepval = step.toInt();
139  minval -= stepval;
140  mIntSpinBox->setValue( minval );
141  mIntSpinBox->setSpecialValueText( QgsApplication::nullRepresentation() );
142  }
143  setupIntEditor( min, max, step, mIntSpinBox, this );
144  if ( config( QStringLiteral( "Suffix" ) ).isValid() )
145  mIntSpinBox->setSuffix( config( QStringLiteral( "Suffix" ) ).toString() );
146  }
147  else
148  {
149  field().convertCompatible( min );
150  field().convertCompatible( max );
151  field().convertCompatible( step );
152  if ( mQgsDial ) setupIntEditor( min, max, step, mQgsDial, this );
153  else if ( mQgsSlider ) setupIntEditor( min, max, step, mQgsSlider, this );
154  else if ( mDial ) setupIntEditor( min, max, step, mDial, this );
155  else if ( mSlider ) setupIntEditor( min, max, step, mSlider, this );
156  }
157 }
158 
160 {
161  return mSlider || mDial || mQgsDial || mQgsSlider || mIntSpinBox || mDoubleSpinBox;
162 }
163 
164 void QgsRangeWidgetWrapper::valueChangedVariant( const QVariant &v )
165 {
166  if ( v.type() == QVariant::Int )
167  valueChanged( v.toInt() );
168  if ( v.type() == QVariant::Double )
169  valueChanged( v.toDouble() );
170 }
171 
173 {
174  QVariant value;
175 
176  if ( mDoubleSpinBox )
177  {
178  value = mDoubleSpinBox->value();
179  if ( value == mDoubleSpinBox->minimum() && config( QStringLiteral( "AllowNull" ), true ).toBool() )
180  {
181  value = QVariant( field().type() );
182  }
183  }
184  else if ( mIntSpinBox )
185  {
186  value = mIntSpinBox->value();
187  if ( value == mIntSpinBox->minimum() && config( QStringLiteral( "AllowNull" ), true ).toBool() )
188  {
189  value = QVariant( field().type() );
190  }
191  }
192  else if ( mQgsDial )
193  {
194  value = mQgsDial->variantValue();
195  }
196  else if ( mQgsSlider )
197  {
198  value = mQgsSlider->variantValue();
199  }
200  else if ( mDial )
201  {
202  value = mDial->value();
203  }
204  else if ( mSlider )
205  {
206  value = mSlider->value();
207  }
208 
209  return value;
210 }
211 
212 void QgsRangeWidgetWrapper::setValue( const QVariant &value )
213 {
214  if ( mDoubleSpinBox )
215  {
216  if ( value.isNull() && config( QStringLiteral( "AllowNull" ), true ).toBool() )
217  {
218  mDoubleSpinBox->setValue( mDoubleSpinBox->minimum() );
219  }
220  else
221  {
222  mDoubleSpinBox->setValue( value.toDouble() );
223  }
224  }
225 
226  if ( mIntSpinBox )
227  {
228  if ( value.isNull() && config( QStringLiteral( "AllowNull" ), true ).toBool() )
229  {
230  mIntSpinBox->setValue( mIntSpinBox->minimum() );
231  }
232  else
233  {
234  mIntSpinBox->setValue( value.toInt() );
235  }
236  }
237 
238  if ( mQgsDial )
239  {
240  mQgsDial->setValue( value );
241  }
242  else if ( mQgsSlider )
243  {
244  mQgsSlider->setValue( value );
245  }
246  else if ( mDial )
247  {
248  mDial->setValue( value.toInt() );
249  }
250  else if ( mSlider )
251  {
252  mSlider->setValue( value.toInt() );
253  }
254 }
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:52
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:225
The QgsSpinBox is a spin box with a clear button that will set the value to the defined clear value...
Definition: qgsspinbox.h:41
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:135
void setShowClearButton(const bool showClearButton)
Sets whether the widget will show a clear button.
Definition: qgsspinbox.cpp:48
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.
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
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.
virtual QVariant value() const override
Will be used to access the widget&#39;s value.
QVariant variantValue() const
Definition: qgsslider.cpp:111