QGIS API Documentation 3.41.0-Master (181b2f43d8e)
Loading...
Searching...
No Matches
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
19#include "moc_qgsrangewidgetwrapper.cpp"
20#include "qgsspinbox.h"
21#include "qgsdoublespinbox.h"
22#include "qgsvectorlayer.h"
23#include "qgsdial.h"
24#include "qgsslider.h"
25#include "qgsapplication.h"
26
27
28
29QgsRangeWidgetWrapper::QgsRangeWidgetWrapper( QgsVectorLayer *layer, int fieldIdx, QWidget *editor, QWidget *parent )
30 : QgsEditorWidgetWrapper( layer, fieldIdx, editor, parent )
31
32{
33}
34
35QWidget *QgsRangeWidgetWrapper::createWidget( QWidget *parent )
36{
37 QWidget *editor = nullptr;
38
39 if ( config( QStringLiteral( "Style" ) ).toString() == QLatin1String( "Dial" ) )
40 {
41 editor = new QgsDial( parent );
42 }
43 else if ( config( QStringLiteral( "Style" ) ).toString() == QLatin1String( "Slider" ) )
44 {
45 editor = new QgsSlider( Qt::Horizontal, parent );
46 }
47 else
48 {
49 switch ( layer()->fields().at( fieldIdx() ).type() )
50 {
51 case QMetaType::Type::Double:
52 // for long long field types we have to use a double spin box with 0 decimal places,
53 // as the min/max value supported by QSpinBox is not large enough
54 case QMetaType::Type::LongLong:
55 {
56
57 editor = new QgsDoubleSpinBox( parent );
58 static_cast<QgsDoubleSpinBox *>( editor )->setLineEditAlignment( Qt::AlignRight );
59 break;
60 }
61
62 case QMetaType::Type::Int:
63 default:
64 editor = new QgsSpinBox( parent );
65 static_cast<QgsSpinBox *>( editor )->setLineEditAlignment( Qt::AlignRight );
66 break;
67 }
68 }
69
70 return editor;
71}
72
73template<class T>
74static void setupIntEditor( const QVariant &min, const QVariant &max, const QVariant &step, T *slider, QgsRangeWidgetWrapper *wrapper )
75{
76 // must use a template function because those methods are overloaded and not inherited by some classes
77 slider->setMinimum( min.isValid() ? min.toInt() : std::numeric_limits<int>::lowest() );
78 slider->setMaximum( max.isValid() ? max.toInt() : std::numeric_limits<int>::max() );
79 slider->setSingleStep( step.isValid() ? step.toInt() : 1 );
80 QObject::connect( slider, SIGNAL( valueChanged( int ) ), wrapper, SLOT( emitValueChanged() ) );
81}
82
83void QgsRangeWidgetWrapper::initWidget( QWidget *editor )
84{
85 mDoubleSpinBox = qobject_cast<QDoubleSpinBox *>( editor );
86 mIntSpinBox = qobject_cast<QSpinBox *>( editor );
87
88 mDial = qobject_cast<QDial *>( editor );
89 mSlider = qobject_cast<QSlider *>( editor );
90 mQgsDial = qobject_cast<QgsDial *>( editor );
91 mQgsSlider = qobject_cast<QgsSlider *>( editor );
92
93 const bool allowNull = config( QStringLiteral( "AllowNull" ), true ).toBool();
94
95 QVariant min( config( QStringLiteral( "Min" ) ) );
96 QVariant max( config( QStringLiteral( "Max" ) ) );
97 QVariant step( config( QStringLiteral( "Step" ) ) );
98 const QVariant precision( config( QStringLiteral( "Precision" ) ) );
99
100 if ( mDoubleSpinBox )
101 {
102 const double stepval = step.isValid() ? step.toDouble() : 1.0;
103 double minval = min.isValid() ? min.toDouble() : std::numeric_limits<double>::lowest();
104 const double maxval = max.isValid() ? max.toDouble() : std::numeric_limits<double>::max();
105
106 const QgsField field = layer()->fields().at( fieldIdx() );
107 // we use the double spin box for long long fields in order to get sufficient range of min/max values
108 const int precisionval = field.type() == QMetaType::Type::LongLong ? 0 : ( precision.isValid() ? precision.toInt() : field.precision() );
109
110 mDoubleSpinBox->setDecimals( precisionval );
111
112 QgsDoubleSpinBox *qgsWidget = qobject_cast<QgsDoubleSpinBox *>( mDoubleSpinBox );
113
114
115 if ( qgsWidget )
116 qgsWidget->setShowClearButton( allowNull );
117 // Make room for null value: lower the minimum to allow for NULL special values
118 if ( allowNull )
119 {
120 double decr;
121 if ( precisionval > 0 )
122 {
123 decr = std::pow( 10, -precisionval );
124 }
125 else
126 {
127 decr = stepval;
128 }
129 minval -= decr;
130 // Note: call setMinimum here or setValue won't work
131 mDoubleSpinBox->setMinimum( minval );
132 mDoubleSpinBox->setValue( minval );
133 QgsDoubleSpinBox *doubleSpinBox( qobject_cast<QgsDoubleSpinBox *>( mDoubleSpinBox ) );
134 if ( doubleSpinBox )
136 else
137 mDoubleSpinBox->setSpecialValueText( QgsApplication::nullRepresentation() );
138 }
139 mDoubleSpinBox->setMinimum( minval );
140 mDoubleSpinBox->setMaximum( maxval );
141 mDoubleSpinBox->setSingleStep( stepval );
142 if ( config( QStringLiteral( "Suffix" ) ).isValid() )
143 mDoubleSpinBox->setSuffix( config( QStringLiteral( "Suffix" ) ).toString() );
144
145 connect( mDoubleSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ),
146 this, [ = ]( double ) { emitValueChanged(); } );
147 }
148 else if ( mIntSpinBox )
149 {
150 QgsSpinBox *qgsWidget = qobject_cast<QgsSpinBox *>( mIntSpinBox );
151 if ( qgsWidget )
152 qgsWidget->setShowClearButton( allowNull );
153 int minval = min.isValid() ? min.toInt() : std::numeric_limits<int>::lowest();
154 const int maxval = max.isValid() ? max.toInt() : std::numeric_limits<int>::max();
155 const uint stepval = step.isValid() ? step.toUInt() : 1;
156 if ( allowNull )
157 {
158 // make sure there is room for a new value (i.e. signed integer does not overflow)
159 const int minvalOverflow = uint( minval ) - stepval;
160 if ( minvalOverflow < minval )
161 {
162 minval = minvalOverflow;
163 }
164 mIntSpinBox->setValue( minval );
165 QgsSpinBox *intSpinBox( qobject_cast<QgsSpinBox *>( mIntSpinBox ) );
166 if ( intSpinBox )
168 else
169 mIntSpinBox->setSpecialValueText( QgsApplication::nullRepresentation() );
170 }
171 setupIntEditor( minval, maxval, stepval, mIntSpinBox, this );
172 if ( config( QStringLiteral( "Suffix" ) ).isValid() )
173 mIntSpinBox->setSuffix( config( QStringLiteral( "Suffix" ) ).toString() );
174 }
175 else
176 {
177 ( void )field().convertCompatible( min );
178 ( void )field().convertCompatible( max );
179 ( void )field().convertCompatible( step );
180 if ( mQgsDial )
181 setupIntEditor( min, max, step, mQgsDial, this );
182 else if ( mQgsSlider )
183 setupIntEditor( min, max, step, mQgsSlider, this );
184 else if ( mDial )
185 setupIntEditor( min, max, step, mDial, this );
186 else if ( mSlider )
187 setupIntEditor( min, max, step, mSlider, this );
188 }
189}
190
192{
193 return mSlider || mDial || mQgsDial || mQgsSlider || mIntSpinBox || mDoubleSpinBox;
194}
195
196void QgsRangeWidgetWrapper::valueChangedVariant( const QVariant &v )
197{
198 if ( v.userType() == QMetaType::Type::Int )
199 {
201 emit valueChanged( v.toInt() );
203 emit valuesChanged( v.toInt() );
204 }
205 else if ( v.userType() == QMetaType::Type::LongLong )
206 {
208 emit valueChanged( v.toLongLong() );
210 emit valuesChanged( v.toLongLong() );
211 }
212 else if ( v.userType() == QMetaType::Type::Double )
213 {
215 emit valueChanged( v.toDouble() );
217 emit valuesChanged( v.toDouble() );
218 }
219}
220
222{
223 QVariant value;
224
225 if ( mDoubleSpinBox )
226 {
227 const QMetaType::Type fieldType = field().type();
228 switch ( fieldType )
229 {
230 case QMetaType::Type::Double:
231 value = mDoubleSpinBox->value();
232 break;
233
234 case QMetaType::Type::LongLong:
235 value = static_cast< long long >( mDoubleSpinBox->value() );
236 break;
237
238 default:
239 break;
240 }
241
242 if ( value == mDoubleSpinBox->minimum() && config( QStringLiteral( "AllowNull" ), true ).toBool() )
243 {
245 }
246 }
247 else if ( mIntSpinBox )
248 {
249 value = mIntSpinBox->value();
250 if ( value == mIntSpinBox->minimum() && config( QStringLiteral( "AllowNull" ), true ).toBool() )
251 {
253 }
254 }
255 else if ( mQgsDial )
256 {
257 value = mQgsDial->variantValue();
258 }
259 else if ( mQgsSlider )
260 {
261 value = mQgsSlider->variantValue();
262 }
263 else if ( mDial )
264 {
265 value = mDial->value();
266 }
267 else if ( mSlider )
268 {
269 value = mSlider->value();
270 }
271
272 return value;
273}
274
275void QgsRangeWidgetWrapper::updateValues( const QVariant &value, const QVariantList & )
276{
277 if ( mDoubleSpinBox )
278 {
279 if ( QgsVariantUtils::isNull( value ) && config( QStringLiteral( "AllowNull" ), true ).toBool() )
280 {
281 mDoubleSpinBox->setValue( mDoubleSpinBox->minimum() );
282 }
283 else
284 {
285 mDoubleSpinBox->setValue( value.toDouble() );
286 }
287 }
288
289 if ( mIntSpinBox )
290 {
291 if ( QgsVariantUtils::isNull( value ) && config( QStringLiteral( "AllowNull" ), true ).toBool() )
292 {
293 mIntSpinBox->setValue( mIntSpinBox->minimum() );
294 }
295 else
296 {
297 mIntSpinBox->setValue( value.toInt() );
298 }
299 }
300
301 if ( mQgsDial )
302 {
303 mQgsDial->setValue( value );
304 }
305 else if ( mQgsSlider )
306 {
307 mQgsSlider->setValue( value );
308 }
309 else if ( mDial )
310 {
311 mDial->setValue( value.toInt() );
312 }
313 else if ( mSlider )
314 {
315 mSlider->setValue( value.toInt() );
316 }
317}
318
320{
321 if ( mDoubleSpinBox )
322 {
323 mDoubleSpinBox->setReadOnly( !enabled );
324 mDoubleSpinBox->setFrame( enabled );
325 }
326 else if ( mIntSpinBox )
327 {
328 mIntSpinBox->setReadOnly( !enabled );
329 mIntSpinBox->setFrame( enabled );
330 }
331 else
332 {
334 }
335}
336
static QString nullRepresentation()
Returns the string used to represent the value NULL throughout QGIS.
void setValue(const QVariant &value)
Definition qgsdial.cpp:62
QVariant variantValue() const
Definition qgsdial.cpp:108
The QgsSpinBox is a spin box with a clear button that will set the value to the defined clear value.
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...
void setShowClearButton(bool showClearButton)
Sets whether the widget will show a clear button.
Manages an editor widget Widget and wrapper share the same parent.
Q_DECL_DEPRECATED void valueChanged(const QVariant &value)
Emit this signal, whenever the value changed.
int fieldIdx() const
Access the field index.
void setEnabled(bool enabled) override
Is used to enable or disable the edit functionality of the managed widget.
void valuesChanged(const QVariant &value, const QVariantList &additionalFieldValues=QVariantList())
Emit this signal, whenever the value changed.
void emitValueChanged()
Will call the value() method to determine the emitted value.
QgsField field() const
Access the field.
Encapsulate a field in an attribute table or data source.
Definition qgsfield.h:53
QMetaType::Type type
Definition qgsfield.h:60
int precision
Definition qgsfield.h:59
bool convertCompatible(QVariant &v, QString *errorMessage=nullptr) const
Converts the provided variant to a compatible format.
Definition qgsfield.cpp:473
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Wraps a range widget.
QWidget * createWidget(QWidget *parent) override
This method should create a new widget with the provided parent.
bool valid() const override
Returns true if the widget has been properly initialized.
QgsRangeWidgetWrapper(QgsVectorLayer *layer, int fieldIdx, QWidget *editor, QWidget *parent=nullptr)
Constructor for QgsRangeWidgetWrapper.
QVariant value() const override
Will be used to access the widget's value.
void initWidget(QWidget *editor) override
This method should initialize the editor widget with runtime data.
void setEnabled(bool enabled) override
void setValue(const QVariant &value)
Definition qgsslider.cpp:67
QVariant variantValue() const
The QgsSpinBox is a spin box with a clear button that will set the value to the defined clear value.
Definition qgsspinbox.h:43
void setShowClearButton(bool showClearButton)
Sets whether the widget will show a clear button.
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...
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
static QVariant createNullVariant(QMetaType::Type metaType)
Helper method to properly create a null QVariant from a metaType Returns the created QVariant.
Represents a vector layer which manages a vector based data sets.
QgsVectorLayer * layer() const
Returns the vector layer associated with the widget.
QVariantMap config() const
Returns the whole config.
#define Q_NOWARN_DEPRECATED_POP
Definition qgis.h:6601
#define Q_NOWARN_DEPRECATED_PUSH
Definition qgis.h:6600
int precision