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