QGIS API Documentation 3.99.0-Master (2fe06baccd8)
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 "moc_qgspropertyassistantwidget.cpp"
37
38QgsPropertyAssistantWidget::QgsPropertyAssistantWidget( QWidget *parent, const QgsPropertyDefinition &definition, const QgsProperty &initialState, const QgsVectorLayer *layer )
39 : QgsPanelWidget( parent )
40 , mDefinition( definition )
41 , mLayer( layer )
42{
43 setupUi( this );
44
45 layout()->setContentsMargins( 0, 0, 0, 0 );
46
47 setPanelTitle( ( QgsGui::higFlags() & QgsGui::HigDialogTitleIsTitleCase ) ? QgsStringUtils::capitalize( mDefinition.description(), Qgis::Capitalization::TitleCase ) : mDefinition.description() );
48
49 mLegendPreview->hide();
50
51 minValueSpinBox->setShowClearButton( false );
52 maxValueSpinBox->setShowClearButton( false );
53
54 // TODO expression widget shouldn't require a non-const layer
55 mExpressionWidget->setLayer( const_cast<QgsVectorLayer *>( mLayer ) );
56 mExpressionWidget->setFilters( QgsFieldProxyModel::Numeric );
57 mExpressionWidget->setField( initialState.propertyType() == Qgis::PropertyType::Expression ? initialState.expressionString() : initialState.field() );
58
59 if ( auto *lTransformer = initialState.transformer() )
60 {
61 minValueSpinBox->setValue( lTransformer->minValue() );
62 maxValueSpinBox->setValue( lTransformer->maxValue() );
63
64 if ( lTransformer->curveTransform() )
65 {
66 mTransformCurveCheckBox->setChecked( true );
67 mTransformCurveCheckBox->setCollapsed( false );
68 mCurveEditor->setCurve( *lTransformer->curveTransform() );
69 }
70 }
71
72 connect( computeValuesButton, &QPushButton::clicked, this, &QgsPropertyAssistantWidget::computeValuesFromLayer );
73
74 if ( mLayer )
75 {
76 mLayerTreeLayer = new QgsLayerTreeLayer( const_cast<QgsVectorLayer *>( mLayer ) );
77 mRoot.addChildNode( mLayerTreeLayer ); // takes ownership
78 }
79 mLegendPreview->setModel( &mPreviewList );
80 mLegendPreview->setItemDelegate( new QgsAssistantPreviewItemDelegate( &mPreviewList ) );
81 mLegendPreview->setHeaderHidden( true );
82 mLegendPreview->expandAll();
83 mLegendVerticalFrame->setLayout( new QVBoxLayout() );
84 mLegendVerticalFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
85 mLegendVerticalFrame->hide();
86
87 switch ( definition.standardTemplate() )
88 {
91 {
92 mTransformerWidget = new QgsPropertySizeAssistantWidget( this, mDefinition, initialState );
93 mLegendPreview->show();
94 break;
95 }
96
99 {
100 mTransformerWidget = new QgsPropertyColorAssistantWidget( this, mDefinition, initialState );
101 mLegendPreview->show();
102 break;
103 }
104
106 {
107 mTransformerWidget = new QgsPropertyGenericNumericAssistantWidget( this, mDefinition, initialState );
108 break;
109 }
110
111 default:
112 {
113 if ( mDefinition.dataType() == QgsPropertyDefinition::DataTypeNumeric )
114 {
115 mTransformerWidget = new QgsPropertyGenericNumericAssistantWidget( this, mDefinition, initialState );
116 }
117 break;
118 }
119 }
120
121 if ( mTransformerWidget )
122 {
123 mOutputWidget->layout()->addWidget( mTransformerWidget );
124 connect( mTransformerWidget, &QgsPropertyAbstractTransformerWidget::widgetChanged, this, &QgsPropertyAssistantWidget::widgetChanged );
125
126 mCurveEditor->setMinHistogramValueRange( minValueSpinBox->value() );
127 mCurveEditor->setMaxHistogramValueRange( maxValueSpinBox->value() );
128
129 mCurveEditor->setHistogramSource( mLayer, mExpressionWidget->currentField() );
130 connect( mExpressionWidget, static_cast<void ( QgsFieldExpressionWidget::* )( const QString & )>( &QgsFieldExpressionWidget::fieldChanged ), this, [this]( const QString &expression ) {
131 mCurveEditor->setHistogramSource( mLayer, expression );
132 } );
133 connect( minValueSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), mCurveEditor, &QgsCurveEditorWidget::setMinHistogramValueRange );
134 connect( maxValueSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), mCurveEditor, &QgsCurveEditorWidget::setMaxHistogramValueRange );
135 }
136 mTransformCurveCheckBox->setVisible( mTransformerWidget );
137
138 connect( minValueSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertyAssistantWidget::widgetChanged );
139 connect( maxValueSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertyAssistantWidget::widgetChanged );
140 connect( mExpressionWidget, static_cast<void ( QgsFieldExpressionWidget::* )( const QString & )>( &QgsFieldExpressionWidget::fieldChanged ), this, &QgsPropertyAssistantWidget::widgetChanged );
141 connect( mTransformCurveCheckBox, &QgsCollapsibleGroupBox::toggled, this, &QgsPropertyAssistantWidget::widgetChanged );
143 connect( this, &QgsPropertyAssistantWidget::widgetChanged, this, &QgsPropertyAssistantWidget::updatePreview );
144 updatePreview();
145}
146
148{
149 mExpressionContextGenerator = generator;
150 mExpressionWidget->registerExpressionContextGenerator( generator );
151}
152
154{
155 property.setActive( !mExpressionWidget->currentText().isEmpty() );
156 if ( mExpressionWidget->isExpression() )
157 property.setExpressionString( mExpressionWidget->currentField() );
158 else
159 property.setField( mExpressionWidget->currentField() );
160
161 if ( mTransformerWidget )
162 {
163 std::unique_ptr<QgsPropertyTransformer> t( mTransformerWidget->createTransformer( minValueSpinBox->value(), maxValueSpinBox->value() ) );
164 if ( mTransformCurveCheckBox->isChecked() )
165 {
166 t->setCurveTransform( new QgsCurveTransform( mCurveEditor->curve() ) );
167 }
168 else
169 {
170 t->setCurveTransform( nullptr );
171 }
172 property.setTransformer( t.release() );
173 }
174}
175
177{
179
180 if ( dockMode && mLegendVerticalFrame->isHidden() )
181 {
182 mLegendVerticalFrame->layout()->addWidget( mLegendPreview );
183 mLegendVerticalFrame->show();
184 }
185}
186
187void QgsPropertyAssistantWidget::computeValuesFromLayer()
188{
189 if ( !mLayer )
190 return;
191
192 double minValue = 0.0;
193 double maxValue = 0.0;
194
195 if ( mExpressionWidget->isExpression() )
196 {
197 if ( !computeValuesFromExpression( mExpressionWidget->currentField(), minValue, maxValue ) )
198 return;
199 }
200 else
201 {
202 if ( !computeValuesFromField( mExpressionWidget->currentField(), minValue, maxValue ) )
203 return;
204 }
205
206 whileBlocking( minValueSpinBox )->setValue( minValue );
207 whileBlocking( maxValueSpinBox )->setValue( maxValue );
208
209 mCurveEditor->setMinHistogramValueRange( minValueSpinBox->value() );
210 mCurveEditor->setMaxHistogramValueRange( maxValueSpinBox->value() );
211
212 emit widgetChanged();
213}
214
215void QgsPropertyAssistantWidget::updatePreview()
216{
217 if ( mLegendPreview->isHidden() || !mTransformerWidget || !mLayer ) // TODO - make this work OK without a layer
218 return;
219
220 mLegendPreview->setIconSize( QSize( 512, 512 ) );
221 mPreviewList.clear();
222
223 QList<double> breaks = QgsSymbolLayerUtils::prettyBreaks( minValueSpinBox->value(), maxValueSpinBox->value(), 8 );
224
225 QgsCurveTransform curve = mCurveEditor->curve();
226 const QList<QgsSymbolLegendNode *> nodes = mTransformerWidget->generatePreviews( breaks, mLayerTreeLayer, mSymbol.get(), minValueSpinBox->value(), maxValueSpinBox->value(), mTransformCurveCheckBox->isChecked() ? &curve : nullptr );
227
228 int widthMax = 0;
229 int i = 0;
230 const auto constNodes = nodes;
231 for ( QgsSymbolLegendNode *node : constNodes )
232 {
233 const QSize minSize( node->minimumIconSize() );
234 node->setIconSize( minSize );
235 widthMax = std::max( minSize.width(), widthMax );
236 QStandardItem *item = new QStandardItem( node->data( Qt::DecorationRole ).value<QPixmap>(), QLocale().toString( breaks[i] ) );
237 item->setEditable( false );
238 mPreviewList.appendRow( item );
239 delete node;
240 i++;
241 }
242 // center icon and align text left by giving icons the same width
243 // TODO maybe add some space so that icons don't touch
244 for ( int i = 0; i < breaks.length(); i++ )
245 {
246 const QPixmap img( mPreviewList.item( i )->icon().pixmap( mPreviewList.item( i )->icon().actualSize( QSize( 512, 512 ) ) ) );
247 QPixmap enlarged( widthMax, img.height() );
248 // fill transparent and add original image
249 enlarged.fill( Qt::transparent );
250 QPainter p( &enlarged );
251 p.drawPixmap( QPoint( ( widthMax - img.width() ) / 2, 0 ), img );
252 p.end();
253 mPreviewList.item( i )->setIcon( enlarged );
254 }
255}
256
257bool QgsPropertyAssistantWidget::computeValuesFromExpression( const QString &expression, double &minValue, double &maxValue ) const
258{
259 QgsExpression e( expression );
260
261 QgsExpressionContext context;
262 if ( mExpressionContextGenerator )
263 {
264 context = mExpressionContextGenerator->createExpressionContext();
265 }
266 else
267 {
271 }
272
273 if ( !e.prepare( &context ) )
274 return false;
275
276 const QSet<QString> referencedCols( e.referencedColumns() );
277
278 QgsFeatureIterator fit = mLayer->getFeatures(
279 QgsFeatureRequest().setFlags( e.needsGeometry() ? Qgis::FeatureRequestFlag::NoFlags : Qgis::FeatureRequestFlag::NoGeometry ).setSubsetOfAttributes( referencedCols, mLayer->fields() )
280 );
281
282 // create list of non-null attribute values
283 double min = std::numeric_limits<double>::max();
284 double max = std::numeric_limits<double>::lowest();
285 QgsFeature f;
286 bool found = false;
287 while ( fit.nextFeature( f ) )
288 {
289 bool ok;
290 context.setFeature( f );
291 const double value = e.evaluate( &context ).toDouble( &ok );
292 if ( ok )
293 {
294 max = std::max( max, value );
295 min = std::min( min, value );
296 found = true;
297 }
298 }
299 if ( found )
300 {
301 minValue = min;
302 maxValue = max;
303 }
304 return found;
305}
306
307bool QgsPropertyAssistantWidget::computeValuesFromField( const QString &fieldName, double &minValue, double &maxValue ) const
308{
309 const int fieldIndex = mLayer->fields().lookupField( fieldName );
310 if ( fieldIndex < 0 )
311 {
312 return false;
313 }
314
315 QVariant min;
316 QVariant max;
317 mLayer->minimumAndMaximumValue( fieldIndex, min, max );
318
319 bool ok = false;
320 const double minDouble = min.toDouble( &ok );
321 if ( !ok )
322 return false;
323
324 const double maxDouble = max.toDouble( &ok );
325 if ( !ok )
326 return false;
327
328 minValue = minDouble;
329 maxValue = maxDouble;
330 return true;
331}
332
334
335//
336// QgsPropertySizeAssistantWidget
337//
338
339QgsPropertySizeAssistantWidget::QgsPropertySizeAssistantWidget( QWidget *parent, const QgsPropertyDefinition &definition, const QgsProperty &initialState )
340 : QgsPropertyAbstractTransformerWidget( parent, definition )
341{
342 setupUi( this );
343
344 layout()->setContentsMargins( 0, 0, 0, 0 );
345
346 if ( definition.standardTemplate() == QgsPropertyDefinition::Size )
347 {
348 scaleMethodComboBox->addItem( tr( "Flannery" ), QgsSizeScaleTransformer::Flannery );
349 scaleMethodComboBox->addItem( tr( "Surface" ), QgsSizeScaleTransformer::Area );
350 scaleMethodComboBox->addItem( tr( "Radius" ), QgsSizeScaleTransformer::Linear );
351 scaleMethodComboBox->addItem( tr( "Exponential" ), QgsSizeScaleTransformer::Exponential );
352 }
353 else if ( definition.standardTemplate() == QgsPropertyDefinition::StrokeWidth )
354 {
355 scaleMethodComboBox->addItem( tr( "Exponential" ), QgsSizeScaleTransformer::Exponential );
356 scaleMethodComboBox->addItem( tr( "Linear" ), QgsSizeScaleTransformer::Linear );
357 }
358
359 minSizeSpinBox->setShowClearButton( false );
360 maxSizeSpinBox->setShowClearButton( false );
361 nullSizeSpinBox->setShowClearButton( false );
362
363 if ( const QgsSizeScaleTransformer *sizeTransform = dynamic_cast<const QgsSizeScaleTransformer *>( initialState.transformer() ) )
364 {
365 minSizeSpinBox->setValue( sizeTransform->minSize() );
366 maxSizeSpinBox->setValue( sizeTransform->maxSize() );
367 nullSizeSpinBox->setValue( sizeTransform->nullSize() );
368 exponentSpinBox->setValue( sizeTransform->exponent() );
369 scaleMethodComboBox->setCurrentIndex( scaleMethodComboBox->findData( sizeTransform->type() ) );
370 }
371
372 exponentSpinBox->setEnabled( scaleMethodComboBox->currentData().toInt() == QgsSizeScaleTransformer::Exponential );
373
374 connect( minSizeSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
375 connect( maxSizeSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
376 connect( nullSizeSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
377 connect( exponentSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
378 connect( scaleMethodComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
379 connect( scaleMethodComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, [this] {
380 exponentSpinBox->setEnabled( scaleMethodComboBox->currentData().toInt() == QgsSizeScaleTransformer::Exponential );
381 } );
382}
383
384QgsSizeScaleTransformer *QgsPropertySizeAssistantWidget::createTransformer( double minValue, double maxValue ) const
385{
387 static_cast<QgsSizeScaleTransformer::ScaleType>( scaleMethodComboBox->currentData().toInt() ),
388 minValue,
389 maxValue,
390 minSizeSpinBox->value(),
391 maxSizeSpinBox->value(),
392 nullSizeSpinBox->value(),
393 exponentSpinBox->value()
394 );
395 return transformer;
396}
397
398QList<QgsSymbolLegendNode *> QgsPropertySizeAssistantWidget::generatePreviews( const QList<double> &breaks, QgsLayerTreeLayer *parent, const QgsSymbol *symbol, double minValue, double maxValue, QgsCurveTransform *curve ) const
399{
400 QList<QgsSymbolLegendNode *> nodes;
401
402 const QgsSymbol *legendSymbol = symbol;
403 std::unique_ptr<QgsSymbol> tempSymbol;
404
405 if ( !legendSymbol )
406 {
407 if ( mDefinition.standardTemplate() == QgsPropertyDefinition::Size )
408 {
409 tempSymbol = QgsMarkerSymbol::createSimple( QVariantMap() );
410 }
411 else if ( mDefinition.standardTemplate() == QgsPropertyDefinition::StrokeWidth )
412 {
413 tempSymbol = QgsLineSymbol::createSimple( QVariantMap() );
414 }
415 legendSymbol = tempSymbol.get();
416 }
417 if ( !legendSymbol )
418 return nodes;
419
420 std::unique_ptr<QgsSizeScaleTransformer> t( createTransformer( minValue, maxValue ) );
421 if ( curve )
422 t->setCurveTransform( new QgsCurveTransform( *curve ) );
423
424 for ( int i = 0; i < breaks.length(); i++ )
425 {
426 std::unique_ptr<QgsSymbolLegendNode> node;
427 if ( dynamic_cast<const QgsMarkerSymbol *>( legendSymbol ) )
428 {
429 std::unique_ptr<QgsMarkerSymbol> symbolClone( static_cast<QgsMarkerSymbol *>( legendSymbol->clone() ) );
430 symbolClone->setDataDefinedSize( QgsProperty() );
431 symbolClone->setDataDefinedAngle( QgsProperty() ); // to avoid symbol not being drawn
432 symbolClone->setSize( t->size( breaks[i] ) );
433 node = std::make_unique<QgsSymbolLegendNode>( parent, QgsLegendSymbolItem( symbolClone.get(), QString::number( i ), QString() ) );
434 }
435 else if ( dynamic_cast<const QgsLineSymbol *>( legendSymbol ) )
436 {
437 std::unique_ptr<QgsLineSymbol> symbolClone( static_cast<QgsLineSymbol *>( legendSymbol->clone() ) );
438 symbolClone->setDataDefinedWidth( QgsProperty() );
439 symbolClone->setWidth( t->size( breaks[i] ) );
440 node = std::make_unique<QgsSymbolLegendNode>( parent, QgsLegendSymbolItem( symbolClone.get(), QString::number( i ), QString() ) );
441 }
442 if ( node )
443 nodes << node.release();
444 }
445 return nodes;
446}
447
448QList<QgsSymbolLegendNode *> QgsPropertyAbstractTransformerWidget::generatePreviews( const QList<double> &, QgsLayerTreeLayer *, const QgsSymbol *, double, double, QgsCurveTransform * ) const
449{
450 return QList<QgsSymbolLegendNode *>();
451}
452
453QgsPropertyColorAssistantWidget::QgsPropertyColorAssistantWidget( QWidget *parent, const QgsPropertyDefinition &definition, const QgsProperty &initialState )
454 : QgsPropertyAbstractTransformerWidget( parent, definition )
455{
456 setupUi( this );
457
458 layout()->setContentsMargins( 0, 0, 0, 0 );
459
460 const bool supportsAlpha = definition.standardTemplate() == QgsPropertyDefinition::ColorWithAlpha;
461 mNullColorButton->setAllowOpacity( supportsAlpha );
462 mNullColorButton->setShowNoColor( true );
463 mNullColorButton->setColorDialogTitle( tr( "Color For Null Values" ) );
464 mNullColorButton->setContext( QStringLiteral( "symbology" ) );
465 mNullColorButton->setNoColorString( tr( "Transparent" ) );
466
467 if ( const QgsColorRampTransformer *colorTransform = dynamic_cast<const QgsColorRampTransformer *>( initialState.transformer() ) )
468 {
469 mNullColorButton->setColor( colorTransform->nullColor() );
470 if ( colorTransform->colorRamp() )
471 mColorRampButton->setColorRamp( colorTransform->colorRamp() );
472 }
473
474 connect( mNullColorButton, &QgsColorButton::colorChanged, this, &QgsPropertyColorAssistantWidget::widgetChanged );
475 connect( mColorRampButton, &QgsColorRampButton::colorRampChanged, this, &QgsPropertyColorAssistantWidget::widgetChanged );
476
477 if ( !mColorRampButton->colorRamp() )
478 {
479 // set a default ramp
480 std::unique_ptr<QgsColorRamp> colorRamp( QgsProject::instance()->styleSettings()->defaultColorRamp() );
481 if ( !colorRamp )
482 {
483 colorRamp.reset( QgsStyle::defaultStyle()->colorRamp( QStringLiteral( "Blues" ) ) );
484 }
485 if ( colorRamp )
486 mColorRampButton->setColorRamp( colorRamp.get() );
487 }
488}
489
490QgsColorRampTransformer *QgsPropertyColorAssistantWidget::createTransformer( double minValue, double maxValue ) const
491{
493 minValue,
494 maxValue,
495 mColorRampButton->colorRamp(),
496 mNullColorButton->color(),
497 mColorRampButton->colorRampName()
498 );
499 return transformer;
500}
501
502QList<QgsSymbolLegendNode *> QgsPropertyColorAssistantWidget::generatePreviews( const QList<double> &breaks, QgsLayerTreeLayer *parent, const QgsSymbol *symbol, double minValue, double maxValue, QgsCurveTransform *curve ) const
503{
504 QList<QgsSymbolLegendNode *> nodes;
505
506 const QgsMarkerSymbol *legendSymbol = dynamic_cast<const QgsMarkerSymbol *>( symbol );
507 std::unique_ptr<QgsMarkerSymbol> tempSymbol;
508
509 if ( !legendSymbol )
510 {
511 tempSymbol = QgsMarkerSymbol::createSimple( QVariantMap() );
512 legendSymbol = tempSymbol.get();
513 }
514 if ( !legendSymbol )
515 return nodes;
516
517 std::unique_ptr<QgsColorRampTransformer> t( createTransformer( minValue, maxValue ) );
518 if ( curve )
519 t->setCurveTransform( new QgsCurveTransform( *curve ) );
520
521 for ( int i = 0; i < breaks.length(); i++ )
522 {
523 std::unique_ptr<QgsSymbolLegendNode> node;
524 std::unique_ptr<QgsMarkerSymbol> symbolClone( static_cast<QgsMarkerSymbol *>( legendSymbol->clone() ) );
525 symbolClone->setColor( t->color( breaks[i] ) );
526 node = std::make_unique<QgsSymbolLegendNode>( parent, QgsLegendSymbolItem( symbolClone.get(), QString::number( i ), QString() ) );
527 if ( node )
528 nodes << node.release();
529 }
530 return nodes;
531}
532
533QgsPropertyGenericNumericAssistantWidget::QgsPropertyGenericNumericAssistantWidget( QWidget *parent, const QgsPropertyDefinition &definition, const QgsProperty &initialState )
534 : QgsPropertyAbstractTransformerWidget( parent, definition )
535{
536 setupUi( this );
537
538 layout()->setContentsMargins( 0, 0, 0, 0 );
539
540 nullOutputSpinBox->setShowClearButton( false );
541
542 switch ( definition.standardTemplate() )
543 {
545 {
546 // tweak dialog for rotation
547 minOutputSpinBox->setMaximum( 360.0 );
548 minOutputSpinBox->setValue( 0.0 );
549 minOutputSpinBox->setShowClearButton( true );
550 minOutputSpinBox->setClearValue( 0.0 );
551 minOutputSpinBox->setSuffix( tr( " °" ) );
552 maxOutputSpinBox->setMaximum( 360.0 );
553 maxOutputSpinBox->setValue( 360.0 );
554 maxOutputSpinBox->setShowClearButton( true );
555 maxOutputSpinBox->setClearValue( 360.0 );
556 maxOutputSpinBox->setSuffix( tr( " °" ) );
557 exponentSpinBox->hide();
558 mExponentLabel->hide();
559 mLabelMinOutput->setText( tr( "Angle from" ) );
560 mLabelNullOutput->setText( tr( "Angle when NULL" ) );
561 break;
562 }
563
565 {
566 // tweak dialog for opacity
567 minOutputSpinBox->setMaximum( 100.0 );
568 minOutputSpinBox->setValue( 0.0 );
569 minOutputSpinBox->setShowClearButton( true );
570 minOutputSpinBox->setClearValue( 0.0 );
571 minOutputSpinBox->setSuffix( tr( " %" ) );
572 maxOutputSpinBox->setMaximum( 100.0 );
573 maxOutputSpinBox->setValue( 100.0 );
574 maxOutputSpinBox->setShowClearButton( true );
575 maxOutputSpinBox->setClearValue( 100.0 );
576 maxOutputSpinBox->setSuffix( tr( " %" ) );
577 mLabelMinOutput->setText( tr( "Opacity from" ) );
578 mLabelNullOutput->setText( tr( "Opacity when NULL" ) );
579 break;
580 }
581
584 minOutputSpinBox->setMinimum( 0 );
585 maxOutputSpinBox->setMinimum( 0 );
586 minOutputSpinBox->setShowClearButton( false );
587 maxOutputSpinBox->setShowClearButton( false );
588 break;
589
591 minOutputSpinBox->setMinimum( 1 );
592 maxOutputSpinBox->setMinimum( 1 );
593 minOutputSpinBox->setShowClearButton( false );
594 maxOutputSpinBox->setShowClearButton( false );
595 break;
596
598 minOutputSpinBox->setMinimum( 0 );
599 maxOutputSpinBox->setMinimum( 0 );
600 minOutputSpinBox->setMaximum( 1 );
601 maxOutputSpinBox->setMaximum( 1 );
602 minOutputSpinBox->setShowClearButton( false );
603 maxOutputSpinBox->setShowClearButton( false );
604 break;
605
607 minOutputSpinBox->setMinimum( -99999999.000000 );
608 maxOutputSpinBox->setMinimum( -99999999.000000 );
609 minOutputSpinBox->setMaximum( 99999999.000000 );
610 maxOutputSpinBox->setMaximum( 99999999.000000 );
611 minOutputSpinBox->setShowClearButton( false );
612 maxOutputSpinBox->setShowClearButton( false );
613 break;
614
615 default:
616 {
617 minOutputSpinBox->setShowClearButton( false );
618 maxOutputSpinBox->setShowClearButton( false );
619 break;
620 }
621 }
622
623 if ( const QgsGenericNumericTransformer *transform = dynamic_cast<const QgsGenericNumericTransformer *>( initialState.transformer() ) )
624 {
625 minOutputSpinBox->setValue( transform->minOutputValue() );
626 maxOutputSpinBox->setValue( transform->maxOutputValue() );
627 nullOutputSpinBox->setValue( transform->nullOutputValue() );
628 exponentSpinBox->setValue( transform->exponent() );
629 }
630
631 connect( minOutputSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
632 connect( maxOutputSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
633 connect( nullOutputSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
634 connect( exponentSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
635}
636
637QgsGenericNumericTransformer *QgsPropertyGenericNumericAssistantWidget::createTransformer( double minValue, double maxValue ) const
638{
640 minValue,
641 maxValue,
642 minOutputSpinBox->value(),
643 maxOutputSpinBox->value(),
644 nullOutputSpinBox->value(),
645 exponentSpinBox->value()
646 );
647 return transformer;
648}
649
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Definition qgis.h:2196
@ NoFlags
No flags are set.
Definition qgis.h:2195
@ Expression
Expression based property.
Definition qgis.h:686
@ TitleCase
Simple title case conversion - does not fully grammatically parse the text and uses simple rules only...
Definition qgis.h:3395
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:281
static QgsGui::HigFlags higFlags()
Returns the platform's HIG flags.
Definition qgsgui.cpp:250
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:45
StandardPropertyTemplate standardTemplate() const
Returns the property's standard template, if applicable.
@ Double
Double value (including negative values).
Definition qgsproperty.h:55
@ Double0To1
Double value between 0-1 (inclusive).
Definition qgsproperty.h:57
@ StrokeWidth
Line stroke width.
Definition qgsproperty.h:70
@ IntegerPositiveGreaterZero
Non-zero positive integer values.
Definition qgsproperty.h:54
@ IntegerPositive
Positive integer values (including 0).
Definition qgsproperty.h:53
@ Opacity
Opacity (0-100).
Definition qgsproperty.h:60
@ ColorNoAlpha
Color with no alpha channel.
Definition qgsproperty.h:63
@ Rotation
Rotation (value between 0-360 degrees).
Definition qgsproperty.h:58
@ Size
1D size (eg marker radius, or square marker height/width)
Definition qgsproperty.h:67
@ ColorWithAlpha
Color with alpha channel.
Definition qgsproperty.h:62
@ DoublePositive
Positive double value (including 0).
Definition qgsproperty.h:56
@ DataTypeNumeric
Property requires a numeric value.
Definition qgsproperty.h:97
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:147
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:6511