QGIS API Documentation 4.3.0-Master (45633be667c)
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::changed );
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::changed );
143 connect( maxValueSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertyAssistantWidget::changed );
144 connect( mExpressionWidget, static_cast<void ( QgsFieldExpressionWidget::* )( const QString & )>( &QgsFieldExpressionWidget::fieldChanged ), this, &QgsPropertyAssistantWidget::changed );
145 connect( mTransformCurveCheckBox, &QgsCollapsibleGroupBox::toggled, this, &QgsPropertyAssistantWidget::changed );
147 connect( this, &QgsPropertyAssistantWidget::changed, 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 changed();
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 mNullColorButton->setOpaqueColorString( tr( "Opaque" ) );
472
473 if ( const QgsColorRampTransformer *colorTransform = dynamic_cast<const QgsColorRampTransformer *>( initialState.transformer() ) )
474 {
475 mNullColorButton->setColor( colorTransform->nullColor() );
476 if ( colorTransform->colorRamp() )
477 mColorRampButton->setColorRamp( colorTransform->colorRamp() );
478 }
479
480 connect( mNullColorButton, &QgsColorButton::colorChanged, this, &QgsPropertyColorAssistantWidget::widgetChanged );
481 connect( mColorRampButton, &QgsColorRampButton::colorRampChanged, this, &QgsPropertyColorAssistantWidget::widgetChanged );
482
483 if ( !mColorRampButton->colorRamp() )
484 {
485 // set a default ramp
486 std::unique_ptr<QgsColorRamp> colorRamp( QgsProject::instance()->styleSettings()->defaultColorRamp() );
487 if ( !colorRamp )
488 {
489 colorRamp = QgsStyle::defaultStyle()->colorRamp( u"Blues"_s );
490 }
491 if ( colorRamp )
492 mColorRampButton->setColorRamp( colorRamp.get() );
493 }
494}
495
496QgsColorRampTransformer *QgsPropertyColorAssistantWidget::createTransformer( double minValue, double maxValue ) const
497{
498 QgsColorRampTransformer *transformer = new QgsColorRampTransformer( minValue, maxValue, mColorRampButton->colorRamp(), mNullColorButton->color(), mColorRampButton->colorRampName() );
499 return transformer;
500}
501
502QList<QgsSymbolLegendNode *> QgsPropertyColorAssistantWidget::generatePreviews(
503 const QList<double> &breaks, QgsLayerTreeLayer *parent, const QgsSymbol *symbol, double minValue, double maxValue, QgsCurveTransform *curve
504) const
505{
506 QList<QgsSymbolLegendNode *> nodes;
507
508 const QgsMarkerSymbol *legendSymbol = dynamic_cast<const QgsMarkerSymbol *>( symbol );
509 std::unique_ptr<QgsMarkerSymbol> tempSymbol;
510
511 if ( !legendSymbol )
512 {
513 tempSymbol = QgsMarkerSymbol::createSimple( QVariantMap() );
514 legendSymbol = tempSymbol.get();
515 }
516 if ( !legendSymbol )
517 return nodes;
518
519 std::unique_ptr<QgsColorRampTransformer> t( createTransformer( minValue, maxValue ) );
520 if ( curve )
521 t->setCurveTransform( new QgsCurveTransform( *curve ) );
522
523 for ( int i = 0; i < breaks.length(); i++ )
524 {
525 std::unique_ptr<QgsSymbolLegendNode> node;
526 std::unique_ptr<QgsMarkerSymbol> symbolClone( static_cast<QgsMarkerSymbol *>( legendSymbol->clone() ) );
527 symbolClone->setColor( t->color( breaks[i] ) );
528 node = std::make_unique<QgsSymbolLegendNode>( parent, QgsLegendSymbolItem( symbolClone.get(), QString::number( i ), QString() ) );
529 if ( node )
530 nodes << node.release();
531 }
532 return nodes;
533}
534
535QgsPropertyGenericNumericAssistantWidget::QgsPropertyGenericNumericAssistantWidget( QWidget *parent, const QgsPropertyDefinition &definition, const QgsProperty &initialState )
536 : QgsPropertyAbstractTransformerWidget( parent, definition )
537{
538 setupUi( this );
539
540 layout()->setContentsMargins( 0, 0, 0, 0 );
541
542 nullOutputSpinBox->setShowClearButton( false );
543
544 switch ( definition.standardTemplate() )
545 {
547 {
548 // tweak dialog for rotation
549 minOutputSpinBox->setMaximum( 360.0 );
550 minOutputSpinBox->setValue( 0.0 );
551 minOutputSpinBox->setShowClearButton( true );
552 minOutputSpinBox->setClearValue( 0.0 );
553 minOutputSpinBox->setSuffix( tr( " °" ) );
554 maxOutputSpinBox->setMaximum( 360.0 );
555 maxOutputSpinBox->setValue( 360.0 );
556 maxOutputSpinBox->setShowClearButton( true );
557 maxOutputSpinBox->setClearValue( 360.0 );
558 maxOutputSpinBox->setSuffix( tr( " °" ) );
559 exponentSpinBox->hide();
560 mExponentLabel->hide();
561 mLabelMinOutput->setText( tr( "Angle from" ) );
562 mLabelNullOutput->setText( tr( "Angle when NULL" ) );
563 break;
564 }
565
567 {
568 // tweak dialog for opacity
569 minOutputSpinBox->setMaximum( 100.0 );
570 minOutputSpinBox->setValue( 0.0 );
571 minOutputSpinBox->setShowClearButton( true );
572 minOutputSpinBox->setClearValue( 0.0 );
573 minOutputSpinBox->setSuffix( tr( " %" ) );
574 maxOutputSpinBox->setMaximum( 100.0 );
575 maxOutputSpinBox->setValue( 100.0 );
576 maxOutputSpinBox->setShowClearButton( true );
577 maxOutputSpinBox->setClearValue( 100.0 );
578 maxOutputSpinBox->setSuffix( tr( " %" ) );
579 mLabelMinOutput->setText( tr( "Opacity from" ) );
580 mLabelNullOutput->setText( tr( "Opacity when NULL" ) );
581 break;
582 }
583
586 minOutputSpinBox->setMinimum( 0 );
587 maxOutputSpinBox->setMinimum( 0 );
588 minOutputSpinBox->setShowClearButton( false );
589 maxOutputSpinBox->setShowClearButton( false );
590 break;
591
593 minOutputSpinBox->setMinimum( 1 );
594 maxOutputSpinBox->setMinimum( 1 );
595 minOutputSpinBox->setShowClearButton( false );
596 maxOutputSpinBox->setShowClearButton( false );
597 break;
598
600 minOutputSpinBox->setMinimum( 0 );
601 maxOutputSpinBox->setMinimum( 0 );
602 minOutputSpinBox->setMaximum( 1 );
603 maxOutputSpinBox->setMaximum( 1 );
604 minOutputSpinBox->setShowClearButton( false );
605 maxOutputSpinBox->setShowClearButton( false );
606 break;
607
609 minOutputSpinBox->setMinimum( -99999999.000000 );
610 maxOutputSpinBox->setMinimum( -99999999.000000 );
611 minOutputSpinBox->setMaximum( 99999999.000000 );
612 maxOutputSpinBox->setMaximum( 99999999.000000 );
613 minOutputSpinBox->setShowClearButton( false );
614 maxOutputSpinBox->setShowClearButton( false );
615 break;
616
617 default:
618 {
619 minOutputSpinBox->setShowClearButton( false );
620 maxOutputSpinBox->setShowClearButton( false );
621 break;
622 }
623 }
624
625 if ( const QgsGenericNumericTransformer *transform = dynamic_cast<const QgsGenericNumericTransformer *>( initialState.transformer() ) )
626 {
627 minOutputSpinBox->setValue( transform->minOutputValue() );
628 maxOutputSpinBox->setValue( transform->maxOutputValue() );
629 nullOutputSpinBox->setValue( transform->nullOutputValue() );
630 exponentSpinBox->setValue( transform->exponent() );
631 }
632
633 connect( minOutputSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
634 connect( maxOutputSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
635 connect( nullOutputSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
636 connect( exponentSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
637}
638
639QgsGenericNumericTransformer *QgsPropertyGenericNumericAssistantWidget::createTransformer( double minValue, double maxValue ) const
640{
642 = new QgsGenericNumericTransformer( minValue, maxValue, minOutputSpinBox->value(), maxOutputSpinBox->value(), nullOutputSpinBox->value(), exponentSpinBox->value() );
643 return transformer;
644}
645
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Definition qgis.h:2360
@ NoFlags
No flags are set.
Definition qgis.h:2359
@ Expression
Expression based property.
Definition qgis.h:727
@ TitleCase
Simple title case conversion - does not fully grammatically parse the text and uses simple rules only...
Definition qgis.h:3613
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:254
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.
void changed()
Emitted when the widget state changes.
QgsPanelWidget(QWidget *parent=nullptr)
Base class for any widget that can be shown as an inline panel.
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.
std::unique_ptr< QgsColorRamp > colorRamp(const QString &name) const
Returns a new copy of the specified color ramp.
Definition qgsstyle.cpp:537
static QgsStyle * defaultStyle(bool initialize=true)
Returns the default application-wide style.
Definition qgsstyle.cpp:164
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:7587