QGIS API Documentation 4.1.0-Master (5bf3c20f3c9)
Loading...
Searching...
No Matches
qgspropertyassistantwidget.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgspropertyassistantwidget.cpp
3 ------------------------------
4 begin : February, 2017
5 copyright : (C) 2017 Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7
8 ***************************************************************************/
9
10/***************************************************************************
11 * *
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
16 * *
17 ***************************************************************************/
18
20
21#include <memory>
22
24#include "qgsgui.h"
25#include "qgslayertreelayer.h"
26#include "qgslinesymbol.h"
27#include "qgsmapsettings.h"
28#include "qgsmarkersymbol.h"
29#include "qgsproject.h"
31#include "qgsstringutils.h"
32#include "qgsstyle.h"
33#include "qgssymbollayerutils.h"
34#include "qgsvectorlayer.h"
35
36#include <QString>
37
38#include "moc_qgspropertyassistantwidget.cpp"
39
40using namespace Qt::StringLiterals;
41
42QgsPropertyAssistantWidget::QgsPropertyAssistantWidget( QWidget *parent, const QgsPropertyDefinition &definition, const QgsProperty &initialState, const QgsVectorLayer *layer )
43 : QgsPanelWidget( parent )
44 , mDefinition( definition )
45 , mLayer( layer )
46{
47 setupUi( this );
48
49 layout()->setContentsMargins( 0, 0, 0, 0 );
50
51 setPanelTitle( ( QgsGui::higFlags() & QgsGui::HigDialogTitleIsTitleCase ) ? QgsStringUtils::capitalize( mDefinition.description(), Qgis::Capitalization::TitleCase ) : mDefinition.description() );
52
53 mLegendPreview->hide();
54
55 minValueSpinBox->setShowClearButton( false );
56 maxValueSpinBox->setShowClearButton( false );
57
58 // TODO expression widget shouldn't require a non-const layer
59 mExpressionWidget->setLayer( const_cast<QgsVectorLayer *>( mLayer ) );
60 mExpressionWidget->setFilters( QgsFieldProxyModel::Numeric );
61 mExpressionWidget->setField( initialState.propertyType() == Qgis::PropertyType::Expression ? initialState.expressionString() : initialState.field() );
62
63 if ( auto *lTransformer = initialState.transformer() )
64 {
65 minValueSpinBox->setValue( lTransformer->minValue() );
66 maxValueSpinBox->setValue( lTransformer->maxValue() );
67
68 if ( lTransformer->curveTransform() )
69 {
70 mTransformCurveCheckBox->setChecked( true );
71 mTransformCurveCheckBox->setCollapsed( false );
72 mCurveEditor->setCurve( *lTransformer->curveTransform() );
73 }
74 }
75
76 connect( computeValuesButton, &QPushButton::clicked, this, &QgsPropertyAssistantWidget::computeValuesFromLayer );
77
78 if ( mLayer )
79 {
80 mLayerTreeLayer = new QgsLayerTreeLayer( const_cast<QgsVectorLayer *>( mLayer ) );
81 mRoot.addChildNode( mLayerTreeLayer ); // takes ownership
82 }
83 mLegendPreview->setModel( &mPreviewList );
84 mLegendPreview->setItemDelegate( new QgsAssistantPreviewItemDelegate( &mPreviewList ) );
85 mLegendPreview->setHeaderHidden( true );
86 mLegendPreview->expandAll();
87 mLegendVerticalFrame->setLayout( new QVBoxLayout() );
88 mLegendVerticalFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
89 mLegendVerticalFrame->hide();
90
91 switch ( definition.standardTemplate() )
92 {
95 {
96 mTransformerWidget = new QgsPropertySizeAssistantWidget( this, mDefinition, initialState );
97 mLegendPreview->show();
98 break;
99 }
100
103 {
104 mTransformerWidget = new QgsPropertyColorAssistantWidget( this, mDefinition, initialState );
105 mLegendPreview->show();
106 break;
107 }
108
110 {
111 mTransformerWidget = new QgsPropertyGenericNumericAssistantWidget( this, mDefinition, initialState );
112 break;
113 }
114
115 default:
116 {
117 if ( mDefinition.dataType() == QgsPropertyDefinition::DataTypeNumeric )
118 {
119 mTransformerWidget = new QgsPropertyGenericNumericAssistantWidget( this, mDefinition, initialState );
120 }
121 break;
122 }
123 }
124
125 if ( mTransformerWidget )
126 {
127 mOutputWidget->layout()->addWidget( mTransformerWidget );
128 connect( mTransformerWidget, &QgsPropertyAbstractTransformerWidget::widgetChanged, this, &QgsPropertyAssistantWidget::widgetChanged );
129
130 mCurveEditor->setMinHistogramValueRange( minValueSpinBox->value() );
131 mCurveEditor->setMaxHistogramValueRange( maxValueSpinBox->value() );
132
133 mCurveEditor->setHistogramSource( mLayer, mExpressionWidget->currentField() );
134 connect( mExpressionWidget, static_cast<void ( QgsFieldExpressionWidget::* )( const QString & )>( &QgsFieldExpressionWidget::fieldChanged ), this, [this]( const QString &expression ) {
135 mCurveEditor->setHistogramSource( mLayer, expression );
136 } );
137 connect( minValueSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), mCurveEditor, &QgsCurveEditorWidget::setMinHistogramValueRange );
138 connect( maxValueSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), mCurveEditor, &QgsCurveEditorWidget::setMaxHistogramValueRange );
139 }
140 mTransformCurveCheckBox->setVisible( mTransformerWidget );
141
142 connect( minValueSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertyAssistantWidget::widgetChanged );
143 connect( maxValueSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertyAssistantWidget::widgetChanged );
144 connect( mExpressionWidget, static_cast<void ( QgsFieldExpressionWidget::* )( const QString & )>( &QgsFieldExpressionWidget::fieldChanged ), this, &QgsPropertyAssistantWidget::widgetChanged );
145 connect( mTransformCurveCheckBox, &QgsCollapsibleGroupBox::toggled, this, &QgsPropertyAssistantWidget::widgetChanged );
147 connect( this, &QgsPropertyAssistantWidget::widgetChanged, this, &QgsPropertyAssistantWidget::updatePreview );
148 updatePreview();
149}
150
152{
153 mExpressionContextGenerator = generator;
154 mExpressionWidget->registerExpressionContextGenerator( generator );
155}
156
158{
159 property.setActive( !mExpressionWidget->currentText().isEmpty() );
160 if ( mExpressionWidget->isExpression() )
161 property.setExpressionString( mExpressionWidget->currentField() );
162 else
163 property.setField( mExpressionWidget->currentField() );
164
165 if ( mTransformerWidget )
166 {
167 std::unique_ptr<QgsPropertyTransformer> t( mTransformerWidget->createTransformer( minValueSpinBox->value(), maxValueSpinBox->value() ) );
168 if ( mTransformCurveCheckBox->isChecked() )
169 {
170 t->setCurveTransform( new QgsCurveTransform( mCurveEditor->curve() ) );
171 }
172 else
173 {
174 t->setCurveTransform( nullptr );
175 }
176 property.setTransformer( t.release() );
177 }
178}
179
181{
183
184 if ( dockMode && mLegendVerticalFrame->isHidden() )
185 {
186 mLegendVerticalFrame->layout()->addWidget( mLegendPreview );
187 mLegendVerticalFrame->show();
188 }
189}
190
191void QgsPropertyAssistantWidget::computeValuesFromLayer()
192{
193 if ( !mLayer )
194 return;
195
196 double minValue = 0.0;
197 double maxValue = 0.0;
198
199 if ( mExpressionWidget->isExpression() )
200 {
201 if ( !computeValuesFromExpression( mExpressionWidget->currentField(), minValue, maxValue ) )
202 return;
203 }
204 else
205 {
206 if ( !computeValuesFromField( mExpressionWidget->currentField(), minValue, maxValue ) )
207 return;
208 }
209
210 whileBlocking( minValueSpinBox )->setValue( minValue );
211 whileBlocking( maxValueSpinBox )->setValue( maxValue );
212
213 mCurveEditor->setMinHistogramValueRange( minValueSpinBox->value() );
214 mCurveEditor->setMaxHistogramValueRange( maxValueSpinBox->value() );
215
216 emit widgetChanged();
217}
218
219void QgsPropertyAssistantWidget::updatePreview()
220{
221 if ( mLegendPreview->isHidden() || !mTransformerWidget || !mLayer ) // TODO - make this work OK without a layer
222 return;
223
224 mLegendPreview->setIconSize( QSize( 512, 512 ) );
225 mPreviewList.clear();
226
227 QList<double> breaks = QgsSymbolLayerUtils::prettyBreaks( minValueSpinBox->value(), maxValueSpinBox->value(), 8 );
228
229 QgsCurveTransform curve = mCurveEditor->curve();
230 const QList<QgsSymbolLegendNode *> nodes
231 = mTransformerWidget->generatePreviews( breaks, mLayerTreeLayer, mSymbol.get(), minValueSpinBox->value(), maxValueSpinBox->value(), mTransformCurveCheckBox->isChecked() ? &curve : nullptr );
232
233 int widthMax = 0;
234 int i = 0;
235 const auto constNodes = nodes;
236 for ( QgsSymbolLegendNode *node : constNodes )
237 {
238 const QSize minSize( node->minimumIconSize() );
239 node->setIconSize( minSize );
240 widthMax = std::max( minSize.width(), widthMax );
241 QStandardItem *item = new QStandardItem( node->data( Qt::DecorationRole ).value<QPixmap>(), QLocale().toString( breaks[i] ) );
242 item->setEditable( false );
243 mPreviewList.appendRow( item );
244 delete node;
245 i++;
246 }
247 // center icon and align text left by giving icons the same width
248 // TODO maybe add some space so that icons don't touch
249 for ( int i = 0; i < breaks.length(); i++ )
250 {
251 const QPixmap img( mPreviewList.item( i )->icon().pixmap( mPreviewList.item( i )->icon().actualSize( QSize( 512, 512 ) ) ) );
252 QPixmap enlarged( widthMax, img.height() );
253 // fill transparent and add original image
254 enlarged.fill( Qt::transparent );
255 QPainter p( &enlarged );
256 p.drawPixmap( QPoint( ( widthMax - img.width() ) / 2, 0 ), img );
257 p.end();
258 mPreviewList.item( i )->setIcon( enlarged );
259 }
260}
261
262bool QgsPropertyAssistantWidget::computeValuesFromExpression( const QString &expression, double &minValue, double &maxValue ) const
263{
264 QgsExpression e( expression );
265
266 QgsExpressionContext context;
267 if ( mExpressionContextGenerator )
268 {
269 context = mExpressionContextGenerator->createExpressionContext();
270 }
271 else
272 {
274 }
275
276 if ( !e.prepare( &context ) )
277 return false;
278
279 const QSet<QString> referencedCols( e.referencedColumns() );
280
281 QgsFeatureIterator fit = mLayer->getFeatures(
282 QgsFeatureRequest().setFlags( e.needsGeometry() ? Qgis::FeatureRequestFlag::NoFlags : Qgis::FeatureRequestFlag::NoGeometry ).setSubsetOfAttributes( referencedCols, mLayer->fields() )
283 );
284
285 // create list of non-null attribute values
286 double min = std::numeric_limits<double>::max();
287 double max = std::numeric_limits<double>::lowest();
288 QgsFeature f;
289 bool found = false;
290 while ( fit.nextFeature( f ) )
291 {
292 bool ok;
293 context.setFeature( f );
294 const double value = e.evaluate( &context ).toDouble( &ok );
295 if ( ok )
296 {
297 max = std::max( max, value );
298 min = std::min( min, value );
299 found = true;
300 }
301 }
302 if ( found )
303 {
304 minValue = min;
305 maxValue = max;
306 }
307 return found;
308}
309
310bool QgsPropertyAssistantWidget::computeValuesFromField( const QString &fieldName, double &minValue, double &maxValue ) const
311{
312 const int fieldIndex = mLayer->fields().lookupField( fieldName );
313 if ( fieldIndex < 0 )
314 {
315 return false;
316 }
317
318 QVariant min;
319 QVariant max;
320 mLayer->minimumAndMaximumValue( fieldIndex, min, max );
321
322 bool ok = false;
323 const double minDouble = min.toDouble( &ok );
324 if ( !ok )
325 return false;
326
327 const double maxDouble = max.toDouble( &ok );
328 if ( !ok )
329 return false;
330
331 minValue = minDouble;
332 maxValue = maxDouble;
333 return true;
334}
335
337
338//
339// QgsPropertySizeAssistantWidget
340//
341
342QgsPropertySizeAssistantWidget::QgsPropertySizeAssistantWidget( QWidget *parent, const QgsPropertyDefinition &definition, const QgsProperty &initialState )
343 : QgsPropertyAbstractTransformerWidget( parent, definition )
344{
345 setupUi( this );
346
347 layout()->setContentsMargins( 0, 0, 0, 0 );
348
349 if ( definition.standardTemplate() == QgsPropertyDefinition::Size )
350 {
351 scaleMethodComboBox->addItem( tr( "Flannery" ), QgsSizeScaleTransformer::Flannery );
352 scaleMethodComboBox->addItem( tr( "Surface" ), QgsSizeScaleTransformer::Area );
353 scaleMethodComboBox->addItem( tr( "Radius" ), QgsSizeScaleTransformer::Linear );
354 scaleMethodComboBox->addItem( tr( "Exponential" ), QgsSizeScaleTransformer::Exponential );
355 }
356 else if ( definition.standardTemplate() == QgsPropertyDefinition::StrokeWidth )
357 {
358 scaleMethodComboBox->addItem( tr( "Exponential" ), QgsSizeScaleTransformer::Exponential );
359 scaleMethodComboBox->addItem( tr( "Linear" ), QgsSizeScaleTransformer::Linear );
360 }
361
362 minSizeSpinBox->setShowClearButton( false );
363 maxSizeSpinBox->setShowClearButton( false );
364 nullSizeSpinBox->setShowClearButton( false );
365
366 if ( const QgsSizeScaleTransformer *sizeTransform = dynamic_cast<const QgsSizeScaleTransformer *>( initialState.transformer() ) )
367 {
368 minSizeSpinBox->setValue( sizeTransform->minSize() );
369 maxSizeSpinBox->setValue( sizeTransform->maxSize() );
370 nullSizeSpinBox->setValue( sizeTransform->nullSize() );
371 exponentSpinBox->setValue( sizeTransform->exponent() );
372 scaleMethodComboBox->setCurrentIndex( scaleMethodComboBox->findData( sizeTransform->type() ) );
373 }
374
375 exponentSpinBox->setEnabled( scaleMethodComboBox->currentData().toInt() == QgsSizeScaleTransformer::Exponential );
376
377 connect( minSizeSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
378 connect( maxSizeSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
379 connect( nullSizeSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
380 connect( exponentSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
381 connect( scaleMethodComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
382 connect( scaleMethodComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, [this] {
383 exponentSpinBox->setEnabled( scaleMethodComboBox->currentData().toInt() == QgsSizeScaleTransformer::Exponential );
384 } );
385}
386
387QgsSizeScaleTransformer *QgsPropertySizeAssistantWidget::createTransformer( double minValue, double maxValue ) const
388{
390 static_cast<QgsSizeScaleTransformer::ScaleType>( scaleMethodComboBox->currentData().toInt() ),
391 minValue,
392 maxValue,
393 minSizeSpinBox->value(),
394 maxSizeSpinBox->value(),
395 nullSizeSpinBox->value(),
396 exponentSpinBox->value()
397 );
398 return transformer;
399}
400
401QList<QgsSymbolLegendNode *> QgsPropertySizeAssistantWidget::generatePreviews(
402 const QList<double> &breaks, QgsLayerTreeLayer *parent, const QgsSymbol *symbol, double minValue, double maxValue, QgsCurveTransform *curve
403) const
404{
405 QList<QgsSymbolLegendNode *> nodes;
406
407 const QgsSymbol *legendSymbol = symbol;
408 std::unique_ptr<QgsSymbol> tempSymbol;
409
410 if ( !legendSymbol )
411 {
412 if ( mDefinition.standardTemplate() == QgsPropertyDefinition::Size )
413 {
414 tempSymbol = QgsMarkerSymbol::createSimple( QVariantMap() );
415 }
416 else if ( mDefinition.standardTemplate() == QgsPropertyDefinition::StrokeWidth )
417 {
418 tempSymbol = QgsLineSymbol::createSimple( QVariantMap() );
419 }
420 legendSymbol = tempSymbol.get();
421 }
422 if ( !legendSymbol )
423 return nodes;
424
425 std::unique_ptr<QgsSizeScaleTransformer> t( createTransformer( minValue, maxValue ) );
426 if ( curve )
427 t->setCurveTransform( new QgsCurveTransform( *curve ) );
428
429 for ( int i = 0; i < breaks.length(); i++ )
430 {
431 std::unique_ptr<QgsSymbolLegendNode> node;
432 if ( dynamic_cast<const QgsMarkerSymbol *>( legendSymbol ) )
433 {
434 std::unique_ptr<QgsMarkerSymbol> symbolClone( static_cast<QgsMarkerSymbol *>( legendSymbol->clone() ) );
435 symbolClone->setDataDefinedSize( QgsProperty() );
436 symbolClone->setDataDefinedAngle( QgsProperty() ); // to avoid symbol not being drawn
437 symbolClone->setSize( t->size( breaks[i] ) );
438 node = std::make_unique<QgsSymbolLegendNode>( parent, QgsLegendSymbolItem( symbolClone.get(), QString::number( i ), QString() ) );
439 }
440 else if ( dynamic_cast<const QgsLineSymbol *>( legendSymbol ) )
441 {
442 std::unique_ptr<QgsLineSymbol> symbolClone( static_cast<QgsLineSymbol *>( legendSymbol->clone() ) );
443 symbolClone->setDataDefinedWidth( QgsProperty() );
444 symbolClone->setWidth( t->size( breaks[i] ) );
445 node = std::make_unique<QgsSymbolLegendNode>( parent, QgsLegendSymbolItem( symbolClone.get(), QString::number( i ), QString() ) );
446 }
447 if ( node )
448 nodes << node.release();
449 }
450 return nodes;
451}
452
453QList<QgsSymbolLegendNode *> QgsPropertyAbstractTransformerWidget::generatePreviews( const QList<double> &, QgsLayerTreeLayer *, const QgsSymbol *, double, double, QgsCurveTransform * ) const
454{
455 return QList<QgsSymbolLegendNode *>();
456}
457
458QgsPropertyColorAssistantWidget::QgsPropertyColorAssistantWidget( QWidget *parent, const QgsPropertyDefinition &definition, const QgsProperty &initialState )
459 : QgsPropertyAbstractTransformerWidget( parent, definition )
460{
461 setupUi( this );
462
463 layout()->setContentsMargins( 0, 0, 0, 0 );
464
465 const bool supportsAlpha = definition.standardTemplate() == QgsPropertyDefinition::ColorWithAlpha;
466 mNullColorButton->setAllowOpacity( supportsAlpha );
467 mNullColorButton->setShowNoColor( true );
468 mNullColorButton->setColorDialogTitle( tr( "Color For Null Values" ) );
469 mNullColorButton->setContext( u"symbology"_s );
470 mNullColorButton->setNoColorString( tr( "Transparent" ) );
471
472 if ( const QgsColorRampTransformer *colorTransform = dynamic_cast<const QgsColorRampTransformer *>( initialState.transformer() ) )
473 {
474 mNullColorButton->setColor( colorTransform->nullColor() );
475 if ( colorTransform->colorRamp() )
476 mColorRampButton->setColorRamp( colorTransform->colorRamp() );
477 }
478
479 connect( mNullColorButton, &QgsColorButton::colorChanged, this, &QgsPropertyColorAssistantWidget::widgetChanged );
480 connect( mColorRampButton, &QgsColorRampButton::colorRampChanged, this, &QgsPropertyColorAssistantWidget::widgetChanged );
481
482 if ( !mColorRampButton->colorRamp() )
483 {
484 // set a default ramp
485 std::unique_ptr<QgsColorRamp> colorRamp( QgsProject::instance()->styleSettings()->defaultColorRamp() );
486 if ( !colorRamp )
487 {
488 colorRamp.reset( QgsStyle::defaultStyle()->colorRamp( u"Blues"_s ) );
489 }
490 if ( colorRamp )
491 mColorRampButton->setColorRamp( colorRamp.get() );
492 }
493}
494
495QgsColorRampTransformer *QgsPropertyColorAssistantWidget::createTransformer( double minValue, double maxValue ) const
496{
497 QgsColorRampTransformer *transformer = new QgsColorRampTransformer( minValue, maxValue, mColorRampButton->colorRamp(), mNullColorButton->color(), mColorRampButton->colorRampName() );
498 return transformer;
499}
500
501QList<QgsSymbolLegendNode *> QgsPropertyColorAssistantWidget::generatePreviews(
502 const QList<double> &breaks, QgsLayerTreeLayer *parent, const QgsSymbol *symbol, double minValue, double maxValue, QgsCurveTransform *curve
503) const
504{
505 QList<QgsSymbolLegendNode *> nodes;
506
507 const QgsMarkerSymbol *legendSymbol = dynamic_cast<const QgsMarkerSymbol *>( symbol );
508 std::unique_ptr<QgsMarkerSymbol> tempSymbol;
509
510 if ( !legendSymbol )
511 {
512 tempSymbol = QgsMarkerSymbol::createSimple( QVariantMap() );
513 legendSymbol = tempSymbol.get();
514 }
515 if ( !legendSymbol )
516 return nodes;
517
518 std::unique_ptr<QgsColorRampTransformer> t( createTransformer( minValue, maxValue ) );
519 if ( curve )
520 t->setCurveTransform( new QgsCurveTransform( *curve ) );
521
522 for ( int i = 0; i < breaks.length(); i++ )
523 {
524 std::unique_ptr<QgsSymbolLegendNode> node;
525 std::unique_ptr<QgsMarkerSymbol> symbolClone( static_cast<QgsMarkerSymbol *>( legendSymbol->clone() ) );
526 symbolClone->setColor( t->color( breaks[i] ) );
527 node = std::make_unique<QgsSymbolLegendNode>( parent, QgsLegendSymbolItem( symbolClone.get(), QString::number( i ), QString() ) );
528 if ( node )
529 nodes << node.release();
530 }
531 return nodes;
532}
533
534QgsPropertyGenericNumericAssistantWidget::QgsPropertyGenericNumericAssistantWidget( QWidget *parent, const QgsPropertyDefinition &definition, const QgsProperty &initialState )
535 : QgsPropertyAbstractTransformerWidget( parent, definition )
536{
537 setupUi( this );
538
539 layout()->setContentsMargins( 0, 0, 0, 0 );
540
541 nullOutputSpinBox->setShowClearButton( false );
542
543 switch ( definition.standardTemplate() )
544 {
546 {
547 // tweak dialog for rotation
548 minOutputSpinBox->setMaximum( 360.0 );
549 minOutputSpinBox->setValue( 0.0 );
550 minOutputSpinBox->setShowClearButton( true );
551 minOutputSpinBox->setClearValue( 0.0 );
552 minOutputSpinBox->setSuffix( tr( " °" ) );
553 maxOutputSpinBox->setMaximum( 360.0 );
554 maxOutputSpinBox->setValue( 360.0 );
555 maxOutputSpinBox->setShowClearButton( true );
556 maxOutputSpinBox->setClearValue( 360.0 );
557 maxOutputSpinBox->setSuffix( tr( " °" ) );
558 exponentSpinBox->hide();
559 mExponentLabel->hide();
560 mLabelMinOutput->setText( tr( "Angle from" ) );
561 mLabelNullOutput->setText( tr( "Angle when NULL" ) );
562 break;
563 }
564
566 {
567 // tweak dialog for opacity
568 minOutputSpinBox->setMaximum( 100.0 );
569 minOutputSpinBox->setValue( 0.0 );
570 minOutputSpinBox->setShowClearButton( true );
571 minOutputSpinBox->setClearValue( 0.0 );
572 minOutputSpinBox->setSuffix( tr( " %" ) );
573 maxOutputSpinBox->setMaximum( 100.0 );
574 maxOutputSpinBox->setValue( 100.0 );
575 maxOutputSpinBox->setShowClearButton( true );
576 maxOutputSpinBox->setClearValue( 100.0 );
577 maxOutputSpinBox->setSuffix( tr( " %" ) );
578 mLabelMinOutput->setText( tr( "Opacity from" ) );
579 mLabelNullOutput->setText( tr( "Opacity when NULL" ) );
580 break;
581 }
582
585 minOutputSpinBox->setMinimum( 0 );
586 maxOutputSpinBox->setMinimum( 0 );
587 minOutputSpinBox->setShowClearButton( false );
588 maxOutputSpinBox->setShowClearButton( false );
589 break;
590
592 minOutputSpinBox->setMinimum( 1 );
593 maxOutputSpinBox->setMinimum( 1 );
594 minOutputSpinBox->setShowClearButton( false );
595 maxOutputSpinBox->setShowClearButton( false );
596 break;
597
599 minOutputSpinBox->setMinimum( 0 );
600 maxOutputSpinBox->setMinimum( 0 );
601 minOutputSpinBox->setMaximum( 1 );
602 maxOutputSpinBox->setMaximum( 1 );
603 minOutputSpinBox->setShowClearButton( false );
604 maxOutputSpinBox->setShowClearButton( false );
605 break;
606
608 minOutputSpinBox->setMinimum( -99999999.000000 );
609 maxOutputSpinBox->setMinimum( -99999999.000000 );
610 minOutputSpinBox->setMaximum( 99999999.000000 );
611 maxOutputSpinBox->setMaximum( 99999999.000000 );
612 minOutputSpinBox->setShowClearButton( false );
613 maxOutputSpinBox->setShowClearButton( false );
614 break;
615
616 default:
617 {
618 minOutputSpinBox->setShowClearButton( false );
619 maxOutputSpinBox->setShowClearButton( false );
620 break;
621 }
622 }
623
624 if ( const QgsGenericNumericTransformer *transform = dynamic_cast<const QgsGenericNumericTransformer *>( initialState.transformer() ) )
625 {
626 minOutputSpinBox->setValue( transform->minOutputValue() );
627 maxOutputSpinBox->setValue( transform->maxOutputValue() );
628 nullOutputSpinBox->setValue( transform->nullOutputValue() );
629 exponentSpinBox->setValue( transform->exponent() );
630 }
631
632 connect( minOutputSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
633 connect( maxOutputSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
634 connect( nullOutputSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
635 connect( exponentSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
636}
637
638QgsGenericNumericTransformer *QgsPropertyGenericNumericAssistantWidget::createTransformer( double minValue, double maxValue ) const
639{
641 = new QgsGenericNumericTransformer( minValue, maxValue, minOutputSpinBox->value(), maxOutputSpinBox->value(), nullOutputSpinBox->value(), exponentSpinBox->value() );
642 return transformer;
643}
644
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Definition qgis.h:2276
@ NoFlags
No flags are set.
Definition qgis.h:2275
@ Expression
Expression based property.
Definition qgis.h:712
@ TitleCase
Simple title case conversion - does not fully grammatically parse the text and uses simple rules only...
Definition qgis.h:3509
void colorChanged(const QColor &color)
Emitted whenever a new color is set for the button.
void colorRampChanged()
Emitted whenever a new color ramp is set for the button.
QgsPropertyTransformer subclass for transforming a numeric value into a color from a color ramp.
void setMaxHistogramValueRange(double maxValueRange)
Sets the maximum expected value for the range of values shown in the histogram.
void changed()
Emitted when the widget curve changes.
void setMinHistogramValueRange(double minValueRange)
Sets the minimum expected value for the range of values shown in the histogram.
Handles scaling of input values to output values by using a curve created from smoothly joining a num...
The QgsSpinBox is a spin box with a clear button that will set the value to the defined clear value.
Abstract interface for generating an expression context.
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
A widget for selection of layer fields or expression creation.
void fieldChanged(const QString &fieldName)
Emitted when the currently selected field changes.
@ Numeric
All numeric fields.
QgsPropertyTransformer subclass for scaling an input numeric value into an output numeric value.
@ HigDialogTitleIsTitleCase
Dialog titles should be title case.
Definition qgsgui.h:284
static QgsGui::HigFlags higFlags()
Returns the platform's HIG flags.
Definition qgsgui.cpp:253
Layer tree node points to a map layer.
Stores information about one class/rule of a vector layer renderer in a unified way that can be used ...
A line symbol type, for rendering LineString and MultiLineString geometries.
static std::unique_ptr< QgsLineSymbol > createSimple(const QVariantMap &properties)
Create a line symbol with one symbol layer: SimpleLine with specified properties.
A marker symbol type, for rendering Point and MultiPoint geometries.
static std::unique_ptr< QgsMarkerSymbol > createSimple(const QVariantMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
QgsMarkerSymbol * clone() const override
Returns a deep copy of this symbol.
bool dockMode() const
Returns the dock mode state.
QgsPanelWidget(QWidget *parent=nullptr)
Base class for any widget that can be shown as an inline panel.
void widgetChanged()
Emitted when the widget state changes.
void setPanelTitle(const QString &panelTitle)
Set the title of the panel when shown in the interface.
virtual void setDockMode(bool dockMode)
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs.
static QgsProject * instance()
Returns the QgsProject singleton instance.
void registerExpressionContextGenerator(QgsExpressionContextGenerator *generator)
Register an expression context generator class that will be used to retrieve an expression context fo...
void setDockMode(bool dockMode) override
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs.
QgsPropertyAssistantWidget(QWidget *parent=nullptr, const QgsPropertyDefinition &definition=QgsPropertyDefinition(), const QgsProperty &initialState=QgsProperty(), const QgsVectorLayer *layer=nullptr)
Constructor for QgsPropertyAssistantWidget.
void updateProperty(QgsProperty &property)
Updates a property in place to corresponding to the current settings shown in the widget.
Definition for a property.
Definition qgsproperty.h:47
StandardPropertyTemplate standardTemplate() const
Returns the property's standard template, if applicable.
@ Double
Double value (including negative values).
Definition qgsproperty.h:56
@ Double0To1
Double value between 0-1 (inclusive).
Definition qgsproperty.h:58
@ StrokeWidth
Line stroke width.
Definition qgsproperty.h:71
@ IntegerPositiveGreaterZero
Non-zero positive integer values.
Definition qgsproperty.h:55
@ IntegerPositive
Positive integer values (including 0).
Definition qgsproperty.h:54
@ Opacity
Opacity (0-100).
Definition qgsproperty.h:61
@ ColorNoAlpha
Color with no alpha channel.
Definition qgsproperty.h:64
@ Rotation
Rotation (value between 0-360 degrees).
Definition qgsproperty.h:59
@ Size
1D size (eg marker radius, or square marker height/width)
Definition qgsproperty.h:68
@ ColorWithAlpha
Color with alpha channel.
Definition qgsproperty.h:63
@ DoublePositive
Positive double value (including 0).
Definition qgsproperty.h:57
@ DataTypeNumeric
Property requires a numeric value.
Definition qgsproperty.h:98
A store for object properties.
QString expressionString() const
Returns the expression used for the property value.
Qgis::PropertyType propertyType() const
Returns the property type.
QString field() const
Returns the current field name the property references.
const QgsPropertyTransformer * transformer() const
Returns the existing transformer used for manipulating the calculated values for the property,...
QgsPropertyTransformer subclass for scaling a value into a size according to various scaling methods.
@ Exponential
Scale using set exponent.
@ Flannery
Flannery scaling method.
static QString capitalize(const QString &string, Qgis::Capitalization capitalization)
Converts a string by applying capitalization rules to the string.
static QgsStyle * defaultStyle(bool initialize=true)
Returns the default application-wide style.
Definition qgsstyle.cpp:148
static QList< double > prettyBreaks(double minimum, double maximum, int classes)
Computes a sequence of about 'classes' equally spaced round values which cover the range of values fr...
Abstract base class for all rendered symbols.
Definition qgssymbol.h:227
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
Represents a vector layer which manages a vector based dataset.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition qgis.h:6880