QGIS API Documentation 3.99.0-Master (d270888f95f)
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 = mTransformerWidget->generatePreviews( breaks, mLayerTreeLayer, mSymbol.get(), minValueSpinBox->value(), maxValueSpinBox->value(), mTransformCurveCheckBox->isChecked() ? &curve : nullptr );
231
232 int widthMax = 0;
233 int i = 0;
234 const auto constNodes = nodes;
235 for ( QgsSymbolLegendNode *node : constNodes )
236 {
237 const QSize minSize( node->minimumIconSize() );
238 node->setIconSize( minSize );
239 widthMax = std::max( minSize.width(), widthMax );
240 QStandardItem *item = new QStandardItem( node->data( Qt::DecorationRole ).value<QPixmap>(), QLocale().toString( breaks[i] ) );
241 item->setEditable( false );
242 mPreviewList.appendRow( item );
243 delete node;
244 i++;
245 }
246 // center icon and align text left by giving icons the same width
247 // TODO maybe add some space so that icons don't touch
248 for ( int i = 0; i < breaks.length(); i++ )
249 {
250 const QPixmap img( mPreviewList.item( i )->icon().pixmap( mPreviewList.item( i )->icon().actualSize( QSize( 512, 512 ) ) ) );
251 QPixmap enlarged( widthMax, img.height() );
252 // fill transparent and add original image
253 enlarged.fill( Qt::transparent );
254 QPainter p( &enlarged );
255 p.drawPixmap( QPoint( ( widthMax - img.width() ) / 2, 0 ), img );
256 p.end();
257 mPreviewList.item( i )->setIcon( enlarged );
258 }
259}
260
261bool QgsPropertyAssistantWidget::computeValuesFromExpression( const QString &expression, double &minValue, double &maxValue ) const
262{
263 QgsExpression e( expression );
264
265 QgsExpressionContext context;
266 if ( mExpressionContextGenerator )
267 {
268 context = mExpressionContextGenerator->createExpressionContext();
269 }
270 else
271 {
275 }
276
277 if ( !e.prepare( &context ) )
278 return false;
279
280 const QSet<QString> referencedCols( e.referencedColumns() );
281
282 QgsFeatureIterator fit = mLayer->getFeatures(
283 QgsFeatureRequest().setFlags( e.needsGeometry() ? Qgis::FeatureRequestFlag::NoFlags : Qgis::FeatureRequestFlag::NoGeometry ).setSubsetOfAttributes( referencedCols, mLayer->fields() )
284 );
285
286 // create list of non-null attribute values
287 double min = std::numeric_limits<double>::max();
288 double max = std::numeric_limits<double>::lowest();
289 QgsFeature f;
290 bool found = false;
291 while ( fit.nextFeature( f ) )
292 {
293 bool ok;
294 context.setFeature( f );
295 const double value = e.evaluate( &context ).toDouble( &ok );
296 if ( ok )
297 {
298 max = std::max( max, value );
299 min = std::min( min, value );
300 found = true;
301 }
302 }
303 if ( found )
304 {
305 minValue = min;
306 maxValue = max;
307 }
308 return found;
309}
310
311bool QgsPropertyAssistantWidget::computeValuesFromField( const QString &fieldName, double &minValue, double &maxValue ) const
312{
313 const int fieldIndex = mLayer->fields().lookupField( fieldName );
314 if ( fieldIndex < 0 )
315 {
316 return false;
317 }
318
319 QVariant min;
320 QVariant max;
321 mLayer->minimumAndMaximumValue( fieldIndex, min, max );
322
323 bool ok = false;
324 const double minDouble = min.toDouble( &ok );
325 if ( !ok )
326 return false;
327
328 const double maxDouble = max.toDouble( &ok );
329 if ( !ok )
330 return false;
331
332 minValue = minDouble;
333 maxValue = maxDouble;
334 return true;
335}
336
338
339//
340// QgsPropertySizeAssistantWidget
341//
342
343QgsPropertySizeAssistantWidget::QgsPropertySizeAssistantWidget( QWidget *parent, const QgsPropertyDefinition &definition, const QgsProperty &initialState )
344 : QgsPropertyAbstractTransformerWidget( parent, definition )
345{
346 setupUi( this );
347
348 layout()->setContentsMargins( 0, 0, 0, 0 );
349
350 if ( definition.standardTemplate() == QgsPropertyDefinition::Size )
351 {
352 scaleMethodComboBox->addItem( tr( "Flannery" ), QgsSizeScaleTransformer::Flannery );
353 scaleMethodComboBox->addItem( tr( "Surface" ), QgsSizeScaleTransformer::Area );
354 scaleMethodComboBox->addItem( tr( "Radius" ), QgsSizeScaleTransformer::Linear );
355 scaleMethodComboBox->addItem( tr( "Exponential" ), QgsSizeScaleTransformer::Exponential );
356 }
357 else if ( definition.standardTemplate() == QgsPropertyDefinition::StrokeWidth )
358 {
359 scaleMethodComboBox->addItem( tr( "Exponential" ), QgsSizeScaleTransformer::Exponential );
360 scaleMethodComboBox->addItem( tr( "Linear" ), QgsSizeScaleTransformer::Linear );
361 }
362
363 minSizeSpinBox->setShowClearButton( false );
364 maxSizeSpinBox->setShowClearButton( false );
365 nullSizeSpinBox->setShowClearButton( false );
366
367 if ( const QgsSizeScaleTransformer *sizeTransform = dynamic_cast<const QgsSizeScaleTransformer *>( initialState.transformer() ) )
368 {
369 minSizeSpinBox->setValue( sizeTransform->minSize() );
370 maxSizeSpinBox->setValue( sizeTransform->maxSize() );
371 nullSizeSpinBox->setValue( sizeTransform->nullSize() );
372 exponentSpinBox->setValue( sizeTransform->exponent() );
373 scaleMethodComboBox->setCurrentIndex( scaleMethodComboBox->findData( sizeTransform->type() ) );
374 }
375
376 exponentSpinBox->setEnabled( scaleMethodComboBox->currentData().toInt() == QgsSizeScaleTransformer::Exponential );
377
378 connect( minSizeSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
379 connect( maxSizeSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
380 connect( nullSizeSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
381 connect( exponentSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
382 connect( scaleMethodComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
383 connect( scaleMethodComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, [this] {
384 exponentSpinBox->setEnabled( scaleMethodComboBox->currentData().toInt() == QgsSizeScaleTransformer::Exponential );
385 } );
386}
387
388QgsSizeScaleTransformer *QgsPropertySizeAssistantWidget::createTransformer( double minValue, double maxValue ) const
389{
391 static_cast<QgsSizeScaleTransformer::ScaleType>( scaleMethodComboBox->currentData().toInt() ),
392 minValue,
393 maxValue,
394 minSizeSpinBox->value(),
395 maxSizeSpinBox->value(),
396 nullSizeSpinBox->value(),
397 exponentSpinBox->value()
398 );
399 return transformer;
400}
401
402QList<QgsSymbolLegendNode *> QgsPropertySizeAssistantWidget::generatePreviews( const QList<double> &breaks, QgsLayerTreeLayer *parent, const QgsSymbol *symbol, double minValue, double maxValue, QgsCurveTransform *curve ) const
403{
404 QList<QgsSymbolLegendNode *> nodes;
405
406 const QgsSymbol *legendSymbol = symbol;
407 std::unique_ptr<QgsSymbol> tempSymbol;
408
409 if ( !legendSymbol )
410 {
411 if ( mDefinition.standardTemplate() == QgsPropertyDefinition::Size )
412 {
413 tempSymbol = QgsMarkerSymbol::createSimple( QVariantMap() );
414 }
415 else if ( mDefinition.standardTemplate() == QgsPropertyDefinition::StrokeWidth )
416 {
417 tempSymbol = QgsLineSymbol::createSimple( QVariantMap() );
418 }
419 legendSymbol = tempSymbol.get();
420 }
421 if ( !legendSymbol )
422 return nodes;
423
424 std::unique_ptr<QgsSizeScaleTransformer> t( createTransformer( minValue, maxValue ) );
425 if ( curve )
426 t->setCurveTransform( new QgsCurveTransform( *curve ) );
427
428 for ( int i = 0; i < breaks.length(); i++ )
429 {
430 std::unique_ptr<QgsSymbolLegendNode> node;
431 if ( dynamic_cast<const QgsMarkerSymbol *>( legendSymbol ) )
432 {
433 std::unique_ptr<QgsMarkerSymbol> symbolClone( static_cast<QgsMarkerSymbol *>( legendSymbol->clone() ) );
434 symbolClone->setDataDefinedSize( QgsProperty() );
435 symbolClone->setDataDefinedAngle( QgsProperty() ); // to avoid symbol not being drawn
436 symbolClone->setSize( t->size( breaks[i] ) );
437 node = std::make_unique<QgsSymbolLegendNode>( parent, QgsLegendSymbolItem( symbolClone.get(), QString::number( i ), QString() ) );
438 }
439 else if ( dynamic_cast<const QgsLineSymbol *>( legendSymbol ) )
440 {
441 std::unique_ptr<QgsLineSymbol> symbolClone( static_cast<QgsLineSymbol *>( legendSymbol->clone() ) );
442 symbolClone->setDataDefinedWidth( QgsProperty() );
443 symbolClone->setWidth( t->size( breaks[i] ) );
444 node = std::make_unique<QgsSymbolLegendNode>( parent, QgsLegendSymbolItem( symbolClone.get(), QString::number( i ), QString() ) );
445 }
446 if ( node )
447 nodes << node.release();
448 }
449 return nodes;
450}
451
452QList<QgsSymbolLegendNode *> QgsPropertyAbstractTransformerWidget::generatePreviews( const QList<double> &, QgsLayerTreeLayer *, const QgsSymbol *, double, double, QgsCurveTransform * ) const
453{
454 return QList<QgsSymbolLegendNode *>();
455}
456
457QgsPropertyColorAssistantWidget::QgsPropertyColorAssistantWidget( QWidget *parent, const QgsPropertyDefinition &definition, const QgsProperty &initialState )
458 : QgsPropertyAbstractTransformerWidget( parent, definition )
459{
460 setupUi( this );
461
462 layout()->setContentsMargins( 0, 0, 0, 0 );
463
464 const bool supportsAlpha = definition.standardTemplate() == QgsPropertyDefinition::ColorWithAlpha;
465 mNullColorButton->setAllowOpacity( supportsAlpha );
466 mNullColorButton->setShowNoColor( true );
467 mNullColorButton->setColorDialogTitle( tr( "Color For Null Values" ) );
468 mNullColorButton->setContext( u"symbology"_s );
469 mNullColorButton->setNoColorString( tr( "Transparent" ) );
470
471 if ( const QgsColorRampTransformer *colorTransform = dynamic_cast<const QgsColorRampTransformer *>( initialState.transformer() ) )
472 {
473 mNullColorButton->setColor( colorTransform->nullColor() );
474 if ( colorTransform->colorRamp() )
475 mColorRampButton->setColorRamp( colorTransform->colorRamp() );
476 }
477
478 connect( mNullColorButton, &QgsColorButton::colorChanged, this, &QgsPropertyColorAssistantWidget::widgetChanged );
479 connect( mColorRampButton, &QgsColorRampButton::colorRampChanged, this, &QgsPropertyColorAssistantWidget::widgetChanged );
480
481 if ( !mColorRampButton->colorRamp() )
482 {
483 // set a default ramp
484 std::unique_ptr<QgsColorRamp> colorRamp( QgsProject::instance()->styleSettings()->defaultColorRamp() );
485 if ( !colorRamp )
486 {
487 colorRamp.reset( QgsStyle::defaultStyle()->colorRamp( u"Blues"_s ) );
488 }
489 if ( colorRamp )
490 mColorRampButton->setColorRamp( colorRamp.get() );
491 }
492}
493
494QgsColorRampTransformer *QgsPropertyColorAssistantWidget::createTransformer( double minValue, double maxValue ) const
495{
497 minValue,
498 maxValue,
499 mColorRampButton->colorRamp(),
500 mNullColorButton->color(),
501 mColorRampButton->colorRampName()
502 );
503 return transformer;
504}
505
506QList<QgsSymbolLegendNode *> QgsPropertyColorAssistantWidget::generatePreviews( const QList<double> &breaks, QgsLayerTreeLayer *parent, const QgsSymbol *symbol, double minValue, double maxValue, QgsCurveTransform *curve ) const
507{
508 QList<QgsSymbolLegendNode *> nodes;
509
510 const QgsMarkerSymbol *legendSymbol = dynamic_cast<const QgsMarkerSymbol *>( symbol );
511 std::unique_ptr<QgsMarkerSymbol> tempSymbol;
512
513 if ( !legendSymbol )
514 {
515 tempSymbol = QgsMarkerSymbol::createSimple( QVariantMap() );
516 legendSymbol = tempSymbol.get();
517 }
518 if ( !legendSymbol )
519 return nodes;
520
521 std::unique_ptr<QgsColorRampTransformer> t( createTransformer( minValue, maxValue ) );
522 if ( curve )
523 t->setCurveTransform( new QgsCurveTransform( *curve ) );
524
525 for ( int i = 0; i < breaks.length(); i++ )
526 {
527 std::unique_ptr<QgsSymbolLegendNode> node;
528 std::unique_ptr<QgsMarkerSymbol> symbolClone( static_cast<QgsMarkerSymbol *>( legendSymbol->clone() ) );
529 symbolClone->setColor( t->color( breaks[i] ) );
530 node = std::make_unique<QgsSymbolLegendNode>( parent, QgsLegendSymbolItem( symbolClone.get(), QString::number( i ), QString() ) );
531 if ( node )
532 nodes << node.release();
533 }
534 return nodes;
535}
536
537QgsPropertyGenericNumericAssistantWidget::QgsPropertyGenericNumericAssistantWidget( QWidget *parent, const QgsPropertyDefinition &definition, const QgsProperty &initialState )
538 : QgsPropertyAbstractTransformerWidget( parent, definition )
539{
540 setupUi( this );
541
542 layout()->setContentsMargins( 0, 0, 0, 0 );
543
544 nullOutputSpinBox->setShowClearButton( false );
545
546 switch ( definition.standardTemplate() )
547 {
549 {
550 // tweak dialog for rotation
551 minOutputSpinBox->setMaximum( 360.0 );
552 minOutputSpinBox->setValue( 0.0 );
553 minOutputSpinBox->setShowClearButton( true );
554 minOutputSpinBox->setClearValue( 0.0 );
555 minOutputSpinBox->setSuffix( tr( " °" ) );
556 maxOutputSpinBox->setMaximum( 360.0 );
557 maxOutputSpinBox->setValue( 360.0 );
558 maxOutputSpinBox->setShowClearButton( true );
559 maxOutputSpinBox->setClearValue( 360.0 );
560 maxOutputSpinBox->setSuffix( tr( " °" ) );
561 exponentSpinBox->hide();
562 mExponentLabel->hide();
563 mLabelMinOutput->setText( tr( "Angle from" ) );
564 mLabelNullOutput->setText( tr( "Angle when NULL" ) );
565 break;
566 }
567
569 {
570 // tweak dialog for opacity
571 minOutputSpinBox->setMaximum( 100.0 );
572 minOutputSpinBox->setValue( 0.0 );
573 minOutputSpinBox->setShowClearButton( true );
574 minOutputSpinBox->setClearValue( 0.0 );
575 minOutputSpinBox->setSuffix( tr( " %" ) );
576 maxOutputSpinBox->setMaximum( 100.0 );
577 maxOutputSpinBox->setValue( 100.0 );
578 maxOutputSpinBox->setShowClearButton( true );
579 maxOutputSpinBox->setClearValue( 100.0 );
580 maxOutputSpinBox->setSuffix( tr( " %" ) );
581 mLabelMinOutput->setText( tr( "Opacity from" ) );
582 mLabelNullOutput->setText( tr( "Opacity when NULL" ) );
583 break;
584 }
585
588 minOutputSpinBox->setMinimum( 0 );
589 maxOutputSpinBox->setMinimum( 0 );
590 minOutputSpinBox->setShowClearButton( false );
591 maxOutputSpinBox->setShowClearButton( false );
592 break;
593
595 minOutputSpinBox->setMinimum( 1 );
596 maxOutputSpinBox->setMinimum( 1 );
597 minOutputSpinBox->setShowClearButton( false );
598 maxOutputSpinBox->setShowClearButton( false );
599 break;
600
602 minOutputSpinBox->setMinimum( 0 );
603 maxOutputSpinBox->setMinimum( 0 );
604 minOutputSpinBox->setMaximum( 1 );
605 maxOutputSpinBox->setMaximum( 1 );
606 minOutputSpinBox->setShowClearButton( false );
607 maxOutputSpinBox->setShowClearButton( false );
608 break;
609
611 minOutputSpinBox->setMinimum( -99999999.000000 );
612 maxOutputSpinBox->setMinimum( -99999999.000000 );
613 minOutputSpinBox->setMaximum( 99999999.000000 );
614 maxOutputSpinBox->setMaximum( 99999999.000000 );
615 minOutputSpinBox->setShowClearButton( false );
616 maxOutputSpinBox->setShowClearButton( false );
617 break;
618
619 default:
620 {
621 minOutputSpinBox->setShowClearButton( false );
622 maxOutputSpinBox->setShowClearButton( false );
623 break;
624 }
625 }
626
627 if ( const QgsGenericNumericTransformer *transform = dynamic_cast<const QgsGenericNumericTransformer *>( initialState.transformer() ) )
628 {
629 minOutputSpinBox->setValue( transform->minOutputValue() );
630 maxOutputSpinBox->setValue( transform->maxOutputValue() );
631 nullOutputSpinBox->setValue( transform->nullOutputValue() );
632 exponentSpinBox->setValue( transform->exponent() );
633 }
634
635 connect( minOutputSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
636 connect( maxOutputSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
637 connect( nullOutputSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
638 connect( exponentSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
639}
640
641QgsGenericNumericTransformer *QgsPropertyGenericNumericAssistantWidget::createTransformer( double minValue, double maxValue ) const
642{
644 minValue,
645 maxValue,
646 minOutputSpinBox->value(),
647 maxOutputSpinBox->value(),
648 nullOutputSpinBox->value(),
649 exponentSpinBox->value()
650 );
651 return transformer;
652}
653
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Definition qgis.h:2254
@ NoFlags
No flags are set.
Definition qgis.h:2253
@ Expression
Expression based property.
Definition qgis.h:705
@ TitleCase
Simple title case conversion - does not fully grammatically parse the text and uses simple rules only...
Definition qgis.h:3454
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:57
@ Double0To1
Double value between 0-1 (inclusive).
Definition qgsproperty.h:59
@ StrokeWidth
Line stroke width.
Definition qgsproperty.h:72
@ IntegerPositiveGreaterZero
Non-zero positive integer values.
Definition qgsproperty.h:56
@ IntegerPositive
Positive integer values (including 0).
Definition qgsproperty.h:55
@ Opacity
Opacity (0-100).
Definition qgsproperty.h:62
@ ColorNoAlpha
Color with no alpha channel.
Definition qgsproperty.h:65
@ Rotation
Rotation (value between 0-360 degrees).
Definition qgsproperty.h:60
@ Size
1D size (eg marker radius, or square marker height/width)
Definition qgsproperty.h:69
@ ColorWithAlpha
Color with alpha channel.
Definition qgsproperty.h:64
@ DoublePositive
Positive double value (including 0).
Definition qgsproperty.h:58
@ DataTypeNumeric
Property requires a numeric value.
Definition qgsproperty.h:99
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:150
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:231
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:6804