QGIS API Documentation 3.41.0-Master (cea29feecf2)
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
28QgsRangeWidgetWrapper::QgsRangeWidgetWrapper( QgsVectorLayer *layer, int fieldIdx, QWidget *editor, QWidget *parent )
29 : QgsEditorWidgetWrapper( layer, fieldIdx, editor, parent )
30
31{
32}
33
34QWidget *QgsRangeWidgetWrapper::createWidget( QWidget *parent )
35{
36 QWidget *editor = nullptr;
37
38 if ( config( QStringLiteral( "Style" ) ).toString() == QLatin1String( "Dial" ) )
39 {
40 editor = new QgsDial( parent );
41 }
42 else if ( config( QStringLiteral( "Style" ) ).toString() == QLatin1String( "Slider" ) )
43 {
44 editor = new QgsSlider( Qt::Horizontal, parent );
45 }
46 else
47 {
48 switch ( layer()->fields().at( fieldIdx() ).type() )
49 {
50 case QMetaType::Type::Double:
51 // for long long field types we have to use a double spin box with 0 decimal places,
52 // as the min/max value supported by QSpinBox is not large enough
53 case QMetaType::Type::LongLong:
54 {
55 editor = new QgsDoubleSpinBox( parent );
56 static_cast<QgsDoubleSpinBox *>( editor )->setLineEditAlignment( Qt::AlignRight );
57 break;
58 }
59
60 case QMetaType::Type::Int:
61 default:
62 editor = new QgsSpinBox( parent );
63 static_cast<QgsSpinBox *>( editor )->setLineEditAlignment( Qt::AlignRight );
64 break;
65 }
66 }
67
68 return editor;
69}
70
71template<class T>
72static void setupIntEditor( const QVariant &min, const QVariant &max, const QVariant &step, T *slider, QgsRangeWidgetWrapper *wrapper )
73{
74 // must use a template function because those methods are overloaded and not inherited by some classes
75 slider->setMinimum( min.isValid() ? min.toInt() : std::numeric_limits<int>::lowest() );
76 slider->setMaximum( max.isValid() ? max.toInt() : std::numeric_limits<int>::max() );
77 slider->setSingleStep( step.isValid() ? step.toInt() : 1 );
78 QObject::connect( slider, SIGNAL( valueChanged( int ) ), wrapper, SLOT( emitValueChanged() ) );
79}
80
81void QgsRangeWidgetWrapper::initWidget( QWidget *editor )
82{
83 mDoubleSpinBox = qobject_cast<QDoubleSpinBox *>( editor );
84 mIntSpinBox = qobject_cast<QSpinBox *>( editor );
85
86 mDial = qobject_cast<QDial *>( editor );
87 mSlider = qobject_cast<QSlider *>( editor );
88 mQgsDial = qobject_cast<QgsDial *>( editor );
89 mQgsSlider = qobject_cast<QgsSlider *>( editor );
90
91 const bool allowNull = config( QStringLiteral( "AllowNull" ), true ).toBool();
92
93 QVariant min( config( QStringLiteral( "Min" ) ) );
94 QVariant max( config( QStringLiteral( "Max" ) ) );
95 QVariant step( config( QStringLiteral( "Step" ) ) );
96 const QVariant precision( config( QStringLiteral( "Precision" ) ) );
97
98 if ( mDoubleSpinBox )
99 {
100 const double stepval = step.isValid() ? step.toDouble() : 1.0;
101 double minval = min.isValid() ? min.toDouble() : std::numeric_limits<double>::lowest();
102 const double maxval = max.isValid() ? max.toDouble() : std::numeric_limits<double>::max();
103
104 const QgsField field = layer()->fields().at( fieldIdx() );
105 // we use the double spin box for long long fields in order to get sufficient range of min/max values
106 const int precisionval = field.type() == QMetaType::Type::LongLong ? 0 : ( precision.isValid() ? precision.toInt() : field.precision() );
107
108 mDoubleSpinBox->setDecimals( precisionval );
109
110 QgsDoubleSpinBox *qgsWidget = qobject_cast<QgsDoubleSpinBox *>( mDoubleSpinBox );
111
112
113 if ( qgsWidget )
114 qgsWidget->setShowClearButton( allowNull );
115 // Make room for null value: lower the minimum to allow for NULL special values
116 if ( allowNull )
117 {
118 double decr;
119 if ( precisionval > 0 )
120 {
121 decr = std::pow( 10, -precisionval );
122 }
123 else
124 {
125 decr = stepval;
126 }
127 minval -= decr;
128 // Note: call setMinimum here or setValue won't work
129 mDoubleSpinBox->setMinimum( minval );
130 mDoubleSpinBox->setValue( minval );
131 QgsDoubleSpinBox *doubleSpinBox( qobject_cast<QgsDoubleSpinBox *>( mDoubleSpinBox ) );
132 if ( doubleSpinBox )
134 else
135 mDoubleSpinBox->setSpecialValueText( QgsApplication::nullRepresentation() );
136 }
137 mDoubleSpinBox->setMinimum( minval );
138 mDoubleSpinBox->setMaximum( maxval );
139 mDoubleSpinBox->setSingleStep( stepval );
140 if ( config( QStringLiteral( "Suffix" ) ).isValid() )
141 mDoubleSpinBox->setSuffix( config( QStringLiteral( "Suffix" ) ).toString() );
142
143 connect( mDoubleSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, [=]( double ) { emitValueChanged(); } );
144 }
145 else if ( mIntSpinBox )
146 {
147 QgsSpinBox *qgsWidget = qobject_cast<QgsSpinBox *>( mIntSpinBox );
148 if ( qgsWidget )
149 qgsWidget->setShowClearButton( allowNull );
150 int minval = min.isValid() ? min.toInt() : std::numeric_limits<int>::lowest();
151 const int maxval = max.isValid() ? max.toInt() : std::numeric_limits<int>::max();
152 const uint stepval = step.isValid() ? step.toUInt() : 1;
153 if ( allowNull )
154 {
155 // make sure there is room for a new value (i.e. signed integer does not overflow)
156 const int minvalOverflow = uint( minval ) - stepval;
157 if ( minvalOverflow < minval )
158 {
159 minval = minvalOverflow;
160 }
161 mIntSpinBox->setValue( minval );
162 QgsSpinBox *intSpinBox( qobject_cast<QgsSpinBox *>( mIntSpinBox ) );
163 if ( intSpinBox )
165 else
166 mIntSpinBox->setSpecialValueText( QgsApplication::nullRepresentation() );
167 }
168 setupIntEditor( minval, maxval, stepval, mIntSpinBox, this );
169 if ( config( QStringLiteral( "Suffix" ) ).isValid() )
170 mIntSpinBox->setSuffix( config( QStringLiteral( "Suffix" ) ).toString() );
171 }
172 else
173 {
174 ( void ) field().convertCompatible( min );
175 ( void ) field().convertCompatible( max );
176 ( void ) field().convertCompatible( step );
177 if ( mQgsDial )
178 setupIntEditor( min, max, step, mQgsDial, this );
179 else if ( mQgsSlider )
180 setupIntEditor( min, max, step, mQgsSlider, this );
181 else if ( mDial )
182 setupIntEditor( min, max, step, mDial, this );
183 else if ( mSlider )
184 setupIntEditor( min, max, step, mSlider, this );
185 }
186}
187
189{
190 return mSlider || mDial || mQgsDial || mQgsSlider || mIntSpinBox || mDoubleSpinBox;
191}
192
193void QgsRangeWidgetWrapper::valueChangedVariant( const QVariant &v )
194{
195 if ( v.userType() == QMetaType::Type::Int )
196 {
198 emit valueChanged( v.toInt() );
200 emit valuesChanged( v.toInt() );
201 }
202 else if ( v.userType() == QMetaType::Type::LongLong )
203 {
205 emit valueChanged( v.toLongLong() );
207 emit valuesChanged( v.toLongLong() );
208 }
209 else if ( v.userType() == QMetaType::Type::Double )
210 {
212 emit valueChanged( v.toDouble() );
214 emit valuesChanged( v.toDouble() );
215 }
216}
217
219{
220 QVariant value;
221
222 if ( mDoubleSpinBox )
223 {
224 const QMetaType::Type fieldType = field().type();
225 switch ( fieldType )
226 {
227 case QMetaType::Type::Double:
228 value = mDoubleSpinBox->value();
229 break;
230
231 case QMetaType::Type::LongLong:
232 value = static_cast<long long>( mDoubleSpinBox->value() );
233 break;
234
235 default:
236 break;
237 }
238
239 if ( value == mDoubleSpinBox->minimum() && config( QStringLiteral( "AllowNull" ), true ).toBool() )
240 {
242 }
243 }
244 else if ( mIntSpinBox )
245 {
246 value = mIntSpinBox->value();
247 if ( value == mIntSpinBox->minimum() && config( QStringLiteral( "AllowNull" ), true ).toBool() )
248 {
250 }
251 }
252 else if ( mQgsDial )
253 {
254 value = mQgsDial->variantValue();
255 }
256 else if ( mQgsSlider )
257 {
258 value = mQgsSlider->variantValue();
259 }
260 else if ( mDial )
261 {
262 value = mDial->value();
263 }
264 else if ( mSlider )
265 {
266 value = mSlider->value();
267 }
268
269 return value;
270}
271
272void QgsRangeWidgetWrapper::updateValues( const QVariant &value, const QVariantList & )
273{
274 if ( mDoubleSpinBox )
275 {
276 if ( QgsVariantUtils::isNull( value ) && config( QStringLiteral( "AllowNull" ), true ).toBool() )
277 {
278 mDoubleSpinBox->setValue( mDoubleSpinBox->minimum() );
279 }
280 else
281 {
282 mDoubleSpinBox->setValue( value.toDouble() );
283 }
284 }
285
286 if ( mIntSpinBox )
287 {
288 if ( QgsVariantUtils::isNull( value ) && config( QStringLiteral( "AllowNull" ), true ).toBool() )
289 {
290 mIntSpinBox->setValue( mIntSpinBox->minimum() );
291 }
292 else
293 {
294 mIntSpinBox->setValue( value.toInt() );
295 }
296 }
297
298 if ( mQgsDial )
299 {
300 mQgsDial->setValue( value );
301 }
302 else if ( mQgsSlider )
303 {
304 mQgsSlider->setValue( value );
305 }
306 else if ( mDial )
307 {
308 mDial->setValue( value.toInt() );
309 }
310 else if ( mSlider )
311 {
312 mSlider->setValue( value.toInt() );
313 }
314}
315
317{
318 if ( mDoubleSpinBox )
319 {
320 mDoubleSpinBox->setReadOnly( !enabled );
321 mDoubleSpinBox->setFrame( enabled );
322 }
323 else if ( mIntSpinBox )
324 {
325 mIntSpinBox->setReadOnly( !enabled );
326 mIntSpinBox->setFrame( enabled );
327 }
328 else
329 {
331 }
332}
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:102
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:68
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