QGIS API Documentation  3.18.1-Zürich (202f1bf7e5)
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 #include "qgsproject.h"
21 #include "qgsmapsettings.h"
22 #include "qgsvectorlayer.h"
23 #include "qgslayertreelayer.h"
24 #include "qgssymbollayerutils.h"
26 #include "qgsstyle.h"
27 
29  const QgsPropertyDefinition &definition, const QgsProperty &initialState,
30  const QgsVectorLayer *layer )
31  : QgsPanelWidget( parent )
32  , mDefinition( definition )
33  , mLayer( layer )
34 {
35  setupUi( this );
36 
37  layout()->setContentsMargins( 0, 0, 0, 0 );
38 
39  setPanelTitle( mDefinition.description() );
40 
41  mLegendPreview->hide();
42 
43  minValueSpinBox->setShowClearButton( false );
44  maxValueSpinBox->setShowClearButton( false );
45 
46  // TODO expression widget shouldn't require a non-const layer
47  mExpressionWidget->setLayer( const_cast< QgsVectorLayer * >( mLayer ) );
48  mExpressionWidget->setFilters( QgsFieldProxyModel::Numeric );
49  mExpressionWidget->setField( initialState.propertyType() == QgsProperty::ExpressionBasedProperty ? initialState.expressionString() : initialState.field() );
50 
51  if ( auto *lTransformer = initialState.transformer() )
52  {
53  minValueSpinBox->setValue( lTransformer->minValue() );
54  maxValueSpinBox->setValue( lTransformer->maxValue() );
55 
56  if ( lTransformer->curveTransform() )
57  {
58  mTransformCurveCheckBox->setChecked( true );
59  mTransformCurveCheckBox->setCollapsed( false );
60  mCurveEditor->setCurve( *lTransformer->curveTransform() );
61  }
62  }
63 
64  connect( computeValuesButton, &QPushButton::clicked, this, &QgsPropertyAssistantWidget::computeValuesFromLayer );
65 
66  if ( mLayer )
67  {
68  mLayerTreeLayer = new QgsLayerTreeLayer( const_cast< QgsVectorLayer * >( mLayer ) );
69  mRoot.addChildNode( mLayerTreeLayer ); // takes ownership
70  }
71  mLegendPreview->setModel( &mPreviewList );
72  mLegendPreview->setItemDelegate( new QgsAssistantPreviewItemDelegate( &mPreviewList ) );
73  mLegendPreview->setHeaderHidden( true );
74  mLegendPreview->expandAll();
75  mLegendVerticalFrame->setLayout( new QVBoxLayout() );
76  mLegendVerticalFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
77  mLegendVerticalFrame->hide();
78 
79  switch ( definition.standardTemplate() )
80  {
83  {
84  mTransformerWidget = new QgsPropertySizeAssistantWidget( this, mDefinition, initialState );
85  mLegendPreview->show();
86  break;
87  }
88 
91  {
92  mTransformerWidget = new QgsPropertyColorAssistantWidget( this, mDefinition, initialState );
93  mLegendPreview->show();
94  break;
95  }
96 
98  {
99  mTransformerWidget = new QgsPropertyGenericNumericAssistantWidget( this, mDefinition, initialState );
100  break;
101  }
102 
103  default:
104  {
105  if ( mDefinition.dataType() == QgsPropertyDefinition::DataTypeNumeric )
106  {
107  mTransformerWidget = new QgsPropertyGenericNumericAssistantWidget( this, mDefinition, initialState );
108  }
109  break;
110  }
111  }
112 
113  if ( mTransformerWidget )
114  {
115  mOutputWidget->layout()->addWidget( mTransformerWidget );
116  connect( mTransformerWidget, &QgsPropertyAbstractTransformerWidget::widgetChanged, this, &QgsPropertyAssistantWidget::widgetChanged );
117 
118  mCurveEditor->setMinHistogramValueRange( minValueSpinBox->value() );
119  mCurveEditor->setMaxHistogramValueRange( maxValueSpinBox->value() );
120 
121  mCurveEditor->setHistogramSource( mLayer, mExpressionWidget->currentField() );
122  connect( mExpressionWidget, static_cast < void ( QgsFieldExpressionWidget::* )( const QString & ) > ( &QgsFieldExpressionWidget::fieldChanged ), this, [ = ]( const QString & expression )
123  {
124  mCurveEditor->setHistogramSource( mLayer, expression );
125  }
126  );
127  connect( minValueSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), mCurveEditor, &QgsCurveEditorWidget::setMinHistogramValueRange );
128  connect( maxValueSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), mCurveEditor, &QgsCurveEditorWidget::setMaxHistogramValueRange );
129  }
130  mTransformCurveCheckBox->setVisible( mTransformerWidget );
131 
132  connect( minValueSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertyAssistantWidget::widgetChanged );
133  connect( maxValueSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertyAssistantWidget::widgetChanged );
134  connect( mExpressionWidget, static_cast < void ( QgsFieldExpressionWidget::* )( const QString & ) > ( &QgsFieldExpressionWidget::fieldChanged ), this, &QgsPropertyAssistantWidget::widgetChanged );
136  connect( this, &QgsPropertyAssistantWidget::widgetChanged, this, &QgsPropertyAssistantWidget::updatePreview );
137  updatePreview();
138 }
139 
141 {
142  mExpressionContextGenerator = generator;
143  mExpressionWidget->registerExpressionContextGenerator( generator );
144 }
145 
147 {
148  property.setActive( !mExpressionWidget->currentText().isEmpty() );
149  if ( mExpressionWidget->isExpression() )
150  property.setExpressionString( mExpressionWidget->currentField() );
151  else
152  property.setField( mExpressionWidget->currentField() );
153 
154  if ( mTransformerWidget )
155  {
156  std::unique_ptr< QgsPropertyTransformer> t( mTransformerWidget->createTransformer( minValueSpinBox->value(), maxValueSpinBox->value() ) );
157  if ( mTransformCurveCheckBox->isChecked() )
158  {
159  t->setCurveTransform( new QgsCurveTransform( mCurveEditor->curve() ) );
160  }
161  else
162  {
163  t->setCurveTransform( nullptr );
164  }
165  property.setTransformer( t.release() );
166  }
167 }
168 
170 {
172 
173  if ( dockMode && mLegendVerticalFrame->isHidden() )
174  {
175  mLegendVerticalFrame->layout()->addWidget( mLegendPreview );
176  mLegendVerticalFrame->show();
177  }
178 }
179 
180 void QgsPropertyAssistantWidget::computeValuesFromLayer()
181 {
182  if ( !mLayer )
183  return;
184 
185  double minValue = 0.0;
186  double maxValue = 0.0;
187 
188  if ( mExpressionWidget->isExpression() )
189  {
190  if ( !computeValuesFromExpression( mExpressionWidget->currentField(), minValue, maxValue ) )
191  return;
192  }
193  else
194  {
195  if ( !computeValuesFromField( mExpressionWidget->currentField(), minValue, maxValue ) )
196  return;
197  }
198 
199  whileBlocking( minValueSpinBox )->setValue( minValue );
200  whileBlocking( maxValueSpinBox )->setValue( maxValue );
201 
202  mCurveEditor->setMinHistogramValueRange( minValueSpinBox->value() );
203  mCurveEditor->setMaxHistogramValueRange( maxValueSpinBox->value() );
204 
205  emit widgetChanged();
206 }
207 
208 void QgsPropertyAssistantWidget::updatePreview()
209 {
210  if ( mLegendPreview->isHidden() || !mTransformerWidget || !mLayer ) // TODO - make this work OK without a layer
211  return;
212 
213  mLegendPreview->setIconSize( QSize( 512, 512 ) );
214  mPreviewList.clear();
215 
216  QList<double> breaks = QgsSymbolLayerUtils::prettyBreaks( minValueSpinBox->value(),
217  maxValueSpinBox->value(), 8 );
218 
219  QgsCurveTransform curve = mCurveEditor->curve();
220  QList< QgsSymbolLegendNode * > nodes = mTransformerWidget->generatePreviews( breaks, mLayerTreeLayer, mSymbol.get(), minValueSpinBox->value(),
221  maxValueSpinBox->value(), mTransformCurveCheckBox->isChecked() ? &curve : nullptr );
222 
223  int widthMax = 0;
224  int i = 0;
225  const auto constNodes = nodes;
226  for ( QgsSymbolLegendNode *node : constNodes )
227  {
228  const QSize minSize( node->minimumIconSize() );
229  node->setIconSize( minSize );
230  widthMax = std::max( minSize.width(), widthMax );
231  QStandardItem *item = new QStandardItem( node->data( Qt::DecorationRole ).value<QPixmap>(), QString::number( breaks[i] ) );
232  item->setEditable( false );
233  mPreviewList.appendRow( item );
234  delete node;
235  i++;
236  }
237  // center icon and align text left by giving icons the same width
238  // TODO maybe add some space so that icons don't touch
239  for ( int i = 0; i < breaks.length(); i++ )
240  {
241  QPixmap img( mPreviewList.item( i )->icon().pixmap( mPreviewList.item( i )->icon().actualSize( QSize( 512, 512 ) ) ) );
242  QPixmap enlarged( widthMax, img.height() );
243  // fill transparent and add original image
244  enlarged.fill( Qt::transparent );
245  QPainter p( &enlarged );
246  p.drawPixmap( QPoint( ( widthMax - img.width() ) / 2, 0 ), img );
247  p.end();
248  mPreviewList.item( i )->setIcon( enlarged );
249  }
250 }
251 
252 bool QgsPropertyAssistantWidget::computeValuesFromExpression( const QString &expression, double &minValue, double &maxValue ) const
253 {
254  QgsExpression e( expression );
255 
256  QgsExpressionContext context;
257  if ( mExpressionContextGenerator )
258  {
259  context = mExpressionContextGenerator->createExpressionContext();
260  }
261  else
262  {
266  }
267 
268  if ( !e.prepare( &context ) )
269  return false;
270 
271  QSet<QString> referencedCols( e.referencedColumns() );
272 
273  QgsFeatureIterator fit = mLayer->getFeatures(
274  QgsFeatureRequest().setFlags( e.needsGeometry()
277  .setSubsetOfAttributes( referencedCols, mLayer->fields() ) );
278 
279  // create list of non-null attribute values
280  double min = std::numeric_limits<double>::max();
281  double max = std::numeric_limits<double>::lowest();
282  QgsFeature f;
283  bool found = false;
284  while ( fit.nextFeature( f ) )
285  {
286  bool ok;
287  context.setFeature( f );
288  const double value = e.evaluate( &context ).toDouble( &ok );
289  if ( ok )
290  {
291  max = std::max( max, value );
292  min = std::min( min, value );
293  found = true;
294  }
295  }
296  if ( found )
297  {
298  minValue = min;
299  maxValue = max;
300  }
301  return found;
302 }
303 
304 bool QgsPropertyAssistantWidget::computeValuesFromField( const QString &fieldName, double &minValue, double &maxValue ) const
305 {
306  int fieldIndex = mLayer->fields().lookupField( fieldName );
307  if ( fieldIndex < 0 )
308  {
309  return false;
310  }
311 
312  bool ok = false;
313  double minDouble = mLayer->minimumValue( fieldIndex ).toDouble( &ok );
314  if ( !ok )
315  return false;
316 
317  double maxDouble = mLayer->maximumValue( fieldIndex ).toDouble( &ok );
318  if ( !ok )
319  return false;
320 
321  minValue = minDouble;
322  maxValue = maxDouble;
323  return true;
324 }
325 
327 
328 //
329 // QgsPropertySizeAssistantWidget
330 //
331 
332 QgsPropertySizeAssistantWidget::QgsPropertySizeAssistantWidget( QWidget *parent, const QgsPropertyDefinition &definition, const QgsProperty &initialState )
333  : QgsPropertyAbstractTransformerWidget( parent, definition )
334 {
335  setupUi( this );
336 
337  layout()->setContentsMargins( 0, 0, 0, 0 );
338 
339  if ( definition.standardTemplate() == QgsPropertyDefinition::Size )
340  {
341  scaleMethodComboBox->addItem( tr( "Flannery" ), QgsSizeScaleTransformer::Flannery );
342  scaleMethodComboBox->addItem( tr( "Surface" ), QgsSizeScaleTransformer::Area );
343  scaleMethodComboBox->addItem( tr( "Radius" ), QgsSizeScaleTransformer::Linear );
344  scaleMethodComboBox->addItem( tr( "Exponential" ), QgsSizeScaleTransformer::Exponential );
345  }
346  else if ( definition.standardTemplate() == QgsPropertyDefinition::StrokeWidth )
347  {
348  scaleMethodComboBox->addItem( tr( "Exponential" ), QgsSizeScaleTransformer::Exponential );
349  scaleMethodComboBox->addItem( tr( "Linear" ), QgsSizeScaleTransformer::Linear );
350  }
351 
352  minSizeSpinBox->setShowClearButton( false );
353  maxSizeSpinBox->setShowClearButton( false );
354  nullSizeSpinBox->setShowClearButton( false );
355 
356  if ( const QgsSizeScaleTransformer *sizeTransform = dynamic_cast< const QgsSizeScaleTransformer * >( initialState.transformer() ) )
357  {
358  minSizeSpinBox->setValue( sizeTransform->minSize() );
359  maxSizeSpinBox->setValue( sizeTransform->maxSize() );
360  nullSizeSpinBox->setValue( sizeTransform->nullSize() );
361  exponentSpinBox->setValue( sizeTransform->exponent() );
362  scaleMethodComboBox->setCurrentIndex( scaleMethodComboBox->findData( sizeTransform->type() ) );
363  }
364 
365  exponentSpinBox->setEnabled( scaleMethodComboBox->currentData().toInt() == QgsSizeScaleTransformer::Exponential );
366 
367  connect( minSizeSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
368  connect( maxSizeSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
369  connect( nullSizeSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
370  connect( exponentSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
371  connect( scaleMethodComboBox, static_cast < void ( QComboBox::* )( int ) > ( &QComboBox::currentIndexChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
372  connect( scaleMethodComboBox, static_cast < void ( QComboBox::* )( int ) > ( &QComboBox::currentIndexChanged ), this,
373  [ = ]
374  {
375  exponentSpinBox->setEnabled( scaleMethodComboBox->currentData().toInt() == QgsSizeScaleTransformer::Exponential );
376  }
377  );
378 }
379 
380 QgsSizeScaleTransformer *QgsPropertySizeAssistantWidget::createTransformer( double minValue, double maxValue ) const
381 {
383  static_cast< QgsSizeScaleTransformer::ScaleType >( scaleMethodComboBox->currentData().toInt() ),
384  minValue,
385  maxValue,
386  minSizeSpinBox->value(),
387  maxSizeSpinBox->value(),
388  nullSizeSpinBox->value(),
389  exponentSpinBox->value() );
390  return transformer;
391 }
392 
393 QList< QgsSymbolLegendNode * > QgsPropertySizeAssistantWidget::generatePreviews( const QList<double> &breaks, QgsLayerTreeLayer *parent, const QgsSymbol *symbol, double minValue, double maxValue, QgsCurveTransform *curve ) const
394 {
395  QList< QgsSymbolLegendNode * > nodes;
396 
397  const QgsSymbol *legendSymbol = symbol;
398  std::unique_ptr< QgsSymbol > tempSymbol;
399 
400  if ( !legendSymbol )
401  {
402  if ( mDefinition.standardTemplate() == QgsPropertyDefinition::Size )
403  {
404  tempSymbol.reset( QgsMarkerSymbol::createSimple( QVariantMap() ) );
405  }
406  else if ( mDefinition.standardTemplate() == QgsPropertyDefinition::StrokeWidth )
407  {
408  tempSymbol.reset( QgsLineSymbol::createSimple( QVariantMap() ) );
409  }
410  legendSymbol = tempSymbol.get();
411  }
412  if ( !legendSymbol )
413  return nodes;
414 
415  std::unique_ptr< QgsSizeScaleTransformer > t( createTransformer( minValue, maxValue ) );
416  if ( curve )
417  t->setCurveTransform( new QgsCurveTransform( *curve ) );
418 
419  for ( int i = 0; i < breaks.length(); i++ )
420  {
421  std::unique_ptr< QgsSymbolLegendNode > node;
422  if ( dynamic_cast<const QgsMarkerSymbol *>( legendSymbol ) )
423  {
424  std::unique_ptr< QgsMarkerSymbol > symbolClone( static_cast<QgsMarkerSymbol *>( legendSymbol->clone() ) );
425  symbolClone->setDataDefinedSize( QgsProperty() );
426  symbolClone->setDataDefinedAngle( QgsProperty() ); // to avoid symbol not being drawn
427  symbolClone->setSize( t->size( breaks[i] ) );
428  node.reset( new QgsSymbolLegendNode( parent, QgsLegendSymbolItem( symbolClone.get(), QString::number( i ), QString() ) ) );
429  }
430  else if ( dynamic_cast<const QgsLineSymbol *>( legendSymbol ) )
431  {
432  std::unique_ptr< QgsLineSymbol > symbolClone( static_cast<QgsLineSymbol *>( legendSymbol->clone() ) );
433  symbolClone->setDataDefinedWidth( QgsProperty() );
434  symbolClone->setWidth( t->size( breaks[i] ) );
435  node.reset( new QgsSymbolLegendNode( parent, QgsLegendSymbolItem( symbolClone.get(), QString::number( i ), QString() ) ) );
436  }
437  if ( node )
438  nodes << node.release();
439  }
440  return nodes;
441 }
442 
443 QList<QgsSymbolLegendNode *> QgsPropertyAbstractTransformerWidget::generatePreviews( const QList<double> &, QgsLayerTreeLayer *, const QgsSymbol *, double, double, QgsCurveTransform * ) const
444 {
445  return QList< QgsSymbolLegendNode * >();
446 }
447 
448 QgsPropertyColorAssistantWidget::QgsPropertyColorAssistantWidget( QWidget *parent, const QgsPropertyDefinition &definition, const QgsProperty &initialState )
449  : QgsPropertyAbstractTransformerWidget( parent, definition )
450 {
451  setupUi( this );
452 
453  layout()->setContentsMargins( 0, 0, 0, 0 );
454 
455  bool supportsAlpha = definition.standardTemplate() == QgsPropertyDefinition::ColorWithAlpha;
456  mNullColorButton->setAllowOpacity( supportsAlpha );
457  mNullColorButton->setShowNoColor( true );
458  mNullColorButton->setColorDialogTitle( tr( "Color For Null Values" ) );
459  mNullColorButton->setContext( QStringLiteral( "symbology" ) );
460  mNullColorButton->setNoColorString( tr( "Transparent" ) );
461 
462  if ( const QgsColorRampTransformer *colorTransform = dynamic_cast< const QgsColorRampTransformer * >( initialState.transformer() ) )
463  {
464  mNullColorButton->setColor( colorTransform->nullColor() );
465  if ( colorTransform->colorRamp() )
466  mColorRampButton->setColorRamp( colorTransform->colorRamp() );
467  }
468 
469  connect( mNullColorButton, &QgsColorButton::colorChanged, this, &QgsPropertyColorAssistantWidget::widgetChanged );
470  connect( mColorRampButton, &QgsColorRampButton::colorRampChanged, this, &QgsPropertyColorAssistantWidget::widgetChanged );
471 
472  if ( !mColorRampButton->colorRamp() )
473  {
474  // set a default ramp
475  QString defaultRampName = QgsProject::instance()->readEntry( QStringLiteral( "DefaultStyles" ), QStringLiteral( "/ColorRamp" ), QString() );
476  std::unique_ptr< QgsColorRamp > defaultRamp( QgsStyle::defaultStyle()->colorRamp( !defaultRampName.isEmpty() ? defaultRampName : QStringLiteral( "Blues" ) ) );
477  if ( defaultRamp )
478  mColorRampButton->setColorRamp( defaultRamp.get() );
479  }
480 }
481 
482 QgsColorRampTransformer *QgsPropertyColorAssistantWidget::createTransformer( double minValue, double maxValue ) const
483 {
485  minValue,
486  maxValue,
487  mColorRampButton->colorRamp(),
488  mNullColorButton->color() );
489  return transformer;
490 }
491 
492 QList<QgsSymbolLegendNode *> QgsPropertyColorAssistantWidget::generatePreviews( const QList<double> &breaks, QgsLayerTreeLayer *parent, const QgsSymbol *symbol, double minValue, double maxValue, QgsCurveTransform *curve ) const
493 {
494  QList< QgsSymbolLegendNode * > nodes;
495 
496  const QgsMarkerSymbol *legendSymbol = dynamic_cast<const QgsMarkerSymbol *>( symbol );
497  std::unique_ptr< QgsMarkerSymbol > tempSymbol;
498 
499  if ( !legendSymbol )
500  {
501  tempSymbol.reset( QgsMarkerSymbol::createSimple( QVariantMap() ) );
502  legendSymbol = tempSymbol.get();
503  }
504  if ( !legendSymbol )
505  return nodes;
506 
507  std::unique_ptr< QgsColorRampTransformer > t( createTransformer( minValue, maxValue ) );
508  if ( curve )
509  t->setCurveTransform( new QgsCurveTransform( *curve ) );
510 
511  for ( int i = 0; i < breaks.length(); i++ )
512  {
513  std::unique_ptr< QgsSymbolLegendNode > node;
514  std::unique_ptr< QgsMarkerSymbol > symbolClone( static_cast<QgsMarkerSymbol *>( legendSymbol->clone() ) );
515  symbolClone->setColor( t->color( breaks[i] ) );
516  node.reset( new QgsSymbolLegendNode( parent, QgsLegendSymbolItem( symbolClone.get(), QString::number( i ), QString() ) ) );
517  if ( node )
518  nodes << node.release();
519  }
520  return nodes;
521 }
522 
523 QgsPropertyGenericNumericAssistantWidget::QgsPropertyGenericNumericAssistantWidget( QWidget *parent, const QgsPropertyDefinition &definition, const QgsProperty &initialState )
524  : QgsPropertyAbstractTransformerWidget( parent, definition )
525 {
526  setupUi( this );
527 
528  layout()->setContentsMargins( 0, 0, 0, 0 );
529 
530  nullOutputSpinBox->setShowClearButton( false );
531 
532  switch ( definition.standardTemplate() )
533  {
535  {
536  // tweak dialog for rotation
537  minOutputSpinBox->setMaximum( 360.0 );
538  minOutputSpinBox->setValue( 0.0 );
539  minOutputSpinBox->setShowClearButton( true );
540  minOutputSpinBox->setClearValue( 0.0 );
541  minOutputSpinBox->setSuffix( tr( " °" ) );
542  maxOutputSpinBox->setMaximum( 360.0 );
543  maxOutputSpinBox->setValue( 360.0 );
544  maxOutputSpinBox->setShowClearButton( true );
545  maxOutputSpinBox->setClearValue( 360.0 );
546  maxOutputSpinBox->setSuffix( tr( " °" ) );
547  exponentSpinBox->hide();
548  mExponentLabel->hide();
549  mLabelMinOutput->setText( tr( "Angle from" ) );
550  mLabelNullOutput->setText( tr( "Angle when NULL" ) );
551  break;
552  }
553 
555  {
556  // tweak dialog for opacity
557  minOutputSpinBox->setMaximum( 100.0 );
558  minOutputSpinBox->setValue( 0.0 );
559  minOutputSpinBox->setShowClearButton( true );
560  minOutputSpinBox->setClearValue( 0.0 );
561  minOutputSpinBox->setSuffix( tr( " %" ) );
562  maxOutputSpinBox->setMaximum( 100.0 );
563  maxOutputSpinBox->setValue( 100.0 );
564  maxOutputSpinBox->setShowClearButton( true );
565  maxOutputSpinBox->setClearValue( 100.0 );
566  maxOutputSpinBox->setSuffix( tr( " %" ) );
567  mLabelMinOutput->setText( tr( "Opacity from" ) );
568  mLabelNullOutput->setText( tr( "Opacity when NULL" ) );
569  break;
570  }
571 
572  default:
573  {
574  minOutputSpinBox->setShowClearButton( false );
575  maxOutputSpinBox->setShowClearButton( false );
576  break;
577  }
578  }
579 
580  if ( const QgsGenericNumericTransformer *transform = dynamic_cast< const QgsGenericNumericTransformer * >( initialState.transformer() ) )
581  {
582  minOutputSpinBox->setValue( transform->minOutputValue() );
583  maxOutputSpinBox->setValue( transform->maxOutputValue() );
584  nullOutputSpinBox->setValue( transform->nullOutputValue() );
585  exponentSpinBox->setValue( transform->exponent() );
586  }
587 
588  connect( minOutputSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
589  connect( maxOutputSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
590  connect( nullOutputSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
591  connect( exponentSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
592 }
593 
594 QgsGenericNumericTransformer *QgsPropertyGenericNumericAssistantWidget::createTransformer( double minValue, double maxValue ) const
595 {
597  minValue,
598  maxValue,
599  minOutputSpinBox->value(),
600  maxOutputSpinBox->value(),
601  nullOutputSpinBox->value(),
602  exponentSpinBox->value() );
603  return transformer;
604 }
605 
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.
virtual QgsExpressionContext createExpressionContext() const =0
This method needs to be reimplemented in all classes which implement this interface and return an exp...
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.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Class for parsing and evaluation of expressions (formerly called "search strings").
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:56
The QgsFieldExpressionWidget class reates a widget to choose fields and edit expressions It contains ...
void fieldChanged(const QString &fieldName)
Emitted when the currently selected field changes.
@ Numeric
All numeric fields.
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Definition: qgsfields.cpp:344
QgsPropertyTransformer subclass for scaling an input numeric value into an output numeric value.
void addChildNode(QgsLayerTreeNode *node)
Append an existing node.
Layer tree node points to a map layer.
The class stores information about one class/rule of a vector layer renderer in a unified way that ca...
A line symbol type, for rendering LineString and MultiLineString geometries.
Definition: qgssymbol.h:1204
static QgsLineSymbol * createSimple(const QVariantMap &properties)
Create a line symbol with one symbol layer: SimpleLine with specified properties.
Definition: qgssymbol.cpp:1567
A marker symbol type, for rendering Point and MultiPoint geometries.
Definition: qgssymbol.h:1004
static QgsMarkerSymbol * createSimple(const QVariantMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
Definition: qgssymbol.cpp:1556
QgsMarkerSymbol * clone() const override
Returns a deep copy of this symbol.
Definition: qgssymbol.cpp:2036
Base class for any widget that can be shown as a 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.
bool dockMode()
Returns the dock mode state.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:501
QString readEntry(const QString &scope, const QString &key, const QString &def=QString(), bool *ok=nullptr) const
Reads a string from the specified scope and key.
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:48
StandardPropertyTemplate standardTemplate() const
Returns the property's standard template, if applicable.
Definition: qgsproperty.h:195
DataType dataType() const
Returns the allowable field/value data type for the property.
Definition: qgsproperty.h:189
QString description() const
Descriptive name of the property.
Definition: qgsproperty.h:164
@ StrokeWidth
Line stroke width.
Definition: qgsproperty.h:73
@ Opacity
Opacity (0-100)
Definition: qgsproperty.h:63
@ ColorNoAlpha
Color with no alpha channel.
Definition: qgsproperty.h:66
@ Rotation
Rotation (value between 0-360 degrees)
Definition: qgsproperty.h:61
@ Size
1D size (eg marker radius, or square marker height/width)
Definition: qgsproperty.h:70
@ ColorWithAlpha
Color with alpha channel.
Definition: qgsproperty.h:65
@ DataTypeNumeric
Property requires a numeric value.
Definition: qgsproperty.h:100
A store for object properties.
Definition: qgsproperty.h:232
@ ExpressionBasedProperty
Expression based property (QgsExpressionBasedProperty)
Definition: qgsproperty.h:241
QString expressionString() const
Returns the expression used for the property value.
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,...
Type propertyType() const
Returns the property type.
QgsPropertyTransformer subclass for scaling a value into a size according to various scaling methods.
ScaleType
Size scaling methods.
@ Exponential
Scale using set exponent.
@ Flannery
Flannery scaling method.
static QgsStyle * defaultStyle()
Returns default application-wide style.
Definition: qgsstyle.cpp:128
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...
Implementation of legend node interface for displaying preview of vector symbols and their labels and...
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:65
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
Represents a vector layer which manages a vector based data sets.
QVariant maximumValue(int index) const FINAL
Returns the maximum value for an attribute column or an invalid variant in case of error.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
QVariant minimumValue(int index) const FINAL
Returns the minimum value for an attribute column or an invalid variant in case of error.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:263