QGIS API Documentation  2.99.0-Master (9fdd060)
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  break;
51  }
52  case QVariant::Int:
53  case QVariant::LongLong:
54  default:
55  editor = new QgsSpinBox( parent );
56  break;
57  }
58  }
59 
60  return editor;
61 }
62 
63 template<class T>
64 static void setupIntEditor( const QVariant &min, const QVariant &max, const QVariant &step, T *slider, QgsRangeWidgetWrapper *wrapper )
65 {
66  // must use a template function because those methods are overloaded and not inherited by some classes
67  slider->setMinimum( min.isValid() ? min.toInt() : std::numeric_limits<int>::min() );
68  slider->setMaximum( max.isValid() ? max.toInt() : std::numeric_limits<int>::max() );
69  slider->setSingleStep( step.isValid() ? step.toInt() : 1 );
70  QObject::connect( slider, SIGNAL( valueChanged( int ) ), wrapper, SLOT( valueChanged( int ) ) );
71 }
72 
73 void QgsRangeWidgetWrapper::initWidget( QWidget *editor )
74 {
75  mDoubleSpinBox = qobject_cast<QDoubleSpinBox *>( editor );
76  mIntSpinBox = qobject_cast<QSpinBox *>( editor );
77 
78  mDial = qobject_cast<QDial *>( editor );
79  mSlider = qobject_cast<QSlider *>( editor );
80  mQgsDial = qobject_cast<QgsDial *>( editor );
81  mQgsSlider = qobject_cast<QgsSlider *>( editor );
82 
83  bool allowNull = config( QStringLiteral( "AllowNull" ), true ).toBool();
84 
85  QVariant min( config( QStringLiteral( "Min" ) ) );
86  QVariant max( config( QStringLiteral( "Max" ) ) );
87  QVariant step( config( QStringLiteral( "Step" ) ) );
88 
89  if ( mDoubleSpinBox )
90  {
91  // set the precision if field is integer
92  int precision = layer()->fields().at( fieldIdx() ).precision();
93  if ( precision > 0 )
94  {
95  mDoubleSpinBox->setDecimals( layer()->fields().at( fieldIdx() ).precision() );
96  }
97 
98  double minval = min.toDouble();
99  double stepval = step.toDouble();
100  QgsDoubleSpinBox *qgsWidget = dynamic_cast<QgsDoubleSpinBox *>( mDoubleSpinBox );
101  if ( qgsWidget )
102  qgsWidget->setShowClearButton( allowNull );
103  if ( allowNull )
104  {
105  if ( precision > 0 )
106  {
107  minval -= 10 ^ -precision;
108  }
109  else
110  {
111  minval -= stepval;
112  }
113  mDoubleSpinBox->setValue( minval );
114  mDoubleSpinBox->setSpecialValueText( QgsApplication::nullRepresentation() );
115  }
116  mDoubleSpinBox->setMinimum( min.isValid() ? min.toDouble() : std::numeric_limits<double>::min() );
117  mDoubleSpinBox->setMaximum( max.isValid() ? max.toDouble() : std::numeric_limits<double>::max() );
118  mDoubleSpinBox->setSingleStep( step.isValid() ? step.toDouble() : 1.0 );
119  if ( config( QStringLiteral( "Suffix" ) ).isValid() )
120  mDoubleSpinBox->setSuffix( config( QStringLiteral( "Suffix" ) ).toString() );
121 
122  connect( mDoubleSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ),
123  this, static_cast < void ( QgsEditorWidgetWrapper::* )( double ) > ( &QgsEditorWidgetWrapper::valueChanged ) );
124  }
125  else if ( mIntSpinBox )
126  {
127  QgsSpinBox *qgsWidget = dynamic_cast<QgsSpinBox *>( mIntSpinBox );
128  if ( qgsWidget )
129  qgsWidget->setShowClearButton( allowNull );
130  if ( allowNull )
131  {
132  int minval = min.toInt();
133  int stepval = step.toInt();
134  minval -= stepval;
135  mIntSpinBox->setValue( minval );
136  mIntSpinBox->setSpecialValueText( QgsApplication::nullRepresentation() );
137  }
138  setupIntEditor( min, max, step, mIntSpinBox, this );
139  if ( config( QStringLiteral( "Suffix" ) ).isValid() )
140  mIntSpinBox->setSuffix( config( QStringLiteral( "Suffix" ) ).toString() );
141  }
142  else
143  {
144  field().convertCompatible( min );
145  field().convertCompatible( max );
146  field().convertCompatible( step );
147  if ( mQgsDial ) setupIntEditor( min, max, step, mQgsDial, this );
148  else if ( mQgsSlider ) setupIntEditor( min, max, step, mQgsSlider, this );
149  else if ( mDial ) setupIntEditor( min, max, step, mDial, this );
150  else if ( mSlider ) setupIntEditor( min, max, step, mSlider, this );
151  }
152 }
153 
155 {
156  return mSlider || mDial || mQgsDial || mQgsSlider || mIntSpinBox || mDoubleSpinBox;
157 }
158 
159 void QgsRangeWidgetWrapper::valueChangedVariant( const QVariant &v )
160 {
161  if ( v.type() == QVariant::Int )
162  valueChanged( v.toInt() );
163  if ( v.type() == QVariant::Double )
164  valueChanged( v.toDouble() );
165 }
166 
168 {
169  QVariant value;
170 
171  if ( mDoubleSpinBox )
172  {
173  value = mDoubleSpinBox->value();
174  if ( value == mDoubleSpinBox->minimum() && config( QStringLiteral( "AllowNull" ), true ).toBool() )
175  {
176  value = QVariant( field().type() );
177  }
178  }
179  else if ( mIntSpinBox )
180  {
181  value = mIntSpinBox->value();
182  if ( value == mIntSpinBox->minimum() && config( QStringLiteral( "AllowNull" ), true ).toBool() )
183  {
184  value = QVariant( field().type() );
185  }
186  }
187  else if ( mQgsDial )
188  {
189  value = mQgsDial->variantValue();
190  }
191  else if ( mQgsSlider )
192  {
193  value = mQgsSlider->variantValue();
194  }
195  else if ( mDial )
196  {
197  value = mDial->value();
198  }
199  else if ( mSlider )
200  {
201  value = mSlider->value();
202  }
203 
204  return value;
205 }
206 
207 void QgsRangeWidgetWrapper::setValue( const QVariant &value )
208 {
209  if ( mDoubleSpinBox )
210  {
211  if ( value.isNull() && config( QStringLiteral( "AllowNull" ), true ).toBool() )
212  {
213  mDoubleSpinBox->setValue( mDoubleSpinBox->minimum() );
214  }
215  else
216  {
217  mDoubleSpinBox->setValue( value.toDouble() );
218  }
219  }
220 
221  if ( mIntSpinBox )
222  {
223  if ( value.isNull() && config( QStringLiteral( "AllowNull" ), true ).toBool() )
224  {
225  mIntSpinBox->setValue( mIntSpinBox->minimum() );
226  }
227  else
228  {
229  mIntSpinBox->setValue( value.toInt() );
230  }
231  }
232 
233  if ( mQgsDial )
234  {
235  mQgsDial->setValue( value );
236  }
237  else if ( mQgsSlider )
238  {
239  mQgsSlider->setValue( value );
240  }
241  else if ( mDial )
242  {
243  mDial->setValue( value.toInt() );
244  }
245  else if ( mSlider )
246  {
247  mSlider->setValue( value.toInt() );
248  }
249 }
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.
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:54
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:224
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:44
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
virtual void setValue(const QVariant &value) override
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.
virtual QVariant value() const override
Will be used to access the widget&#39;s value.
QVariant variantValue() const
Definition: qgsslider.cpp:110