QGIS API Documentation  3.2.0-Bonn (bc43194)
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"
25 
27  const QgsPropertyDefinition &definition, const QgsProperty &initialState,
28  const QgsVectorLayer *layer )
29  : QgsPanelWidget( parent )
30  , mDefinition( definition )
31  , mLayer( layer )
32 {
33  setupUi( this );
34 
35  layout()->setContentsMargins( 0, 0, 0, 0 );
36  layout()->setMargin( 0 );
37 
38  setPanelTitle( mDefinition.description() );
39 
40  mLegendPreview->hide();
41 
42  minValueSpinBox->setShowClearButton( false );
43  maxValueSpinBox->setShowClearButton( false );
44 
45  // TODO expression widget shouldn't require a non-const layer
46  mExpressionWidget->setLayer( const_cast< QgsVectorLayer * >( mLayer ) );
47  mExpressionWidget->setFilters( QgsFieldProxyModel::Numeric );
48  mExpressionWidget->setField( initialState.propertyType() == QgsProperty::ExpressionBasedProperty ? initialState.expressionString() : initialState.field() );
49 
50  if ( initialState.transformer() )
51  {
52  minValueSpinBox->setValue( initialState.transformer()->minValue() );
53  maxValueSpinBox->setValue( initialState.transformer()->maxValue() );
54 
55  if ( initialState.transformer()->curveTransform() )
56  {
57  mTransformCurveCheckBox->setChecked( true );
58  mTransformCurveCheckBox->setCollapsed( false );
59  mCurveEditor->setCurve( *initialState.transformer()->curveTransform() );
60  }
61  }
62 
63  connect( computeValuesButton, &QPushButton::clicked, this, &QgsPropertyAssistantWidget::computeValuesFromLayer );
64 
65  if ( mLayer )
66  {
67  mLayerTreeLayer = new QgsLayerTreeLayer( const_cast< QgsVectorLayer * >( mLayer ) );
68  mRoot.addChildNode( mLayerTreeLayer ); // takes ownership
69  }
70  mLegendPreview->setModel( &mPreviewList );
71  mLegendPreview->setItemDelegate( new QgsAssistantPreviewItemDelegate( &mPreviewList ) );
72  mLegendPreview->setHeaderHidden( true );
73  mLegendPreview->expandAll();
74  mLegendVerticalFrame->setLayout( new QVBoxLayout() );
75  mLegendVerticalFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
76  mLegendVerticalFrame->layout()->setMargin( 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 {
171  QgsPanelWidget::setDockMode( dockMode );
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  Q_FOREACH ( QgsSymbolLegendNode *node, nodes )
226  {
227  const QSize minSize( node->minimumIconSize() );
228  node->setIconSize( minSize );
229  widthMax = std::max( minSize.width(), widthMax );
230  QStandardItem *item = new QStandardItem( node->data( Qt::DecorationRole ).value<QPixmap>(), QString::number( breaks[i] ) );
231  item->setEditable( false );
232  mPreviewList.appendRow( item );
233  delete node;
234  i++;
235  }
236  // center icon and align text left by giving icons the same width
237  // TODO maybe add some space so that icons don't touch
238  for ( int i = 0; i < breaks.length(); i++ )
239  {
240  QPixmap img( mPreviewList.item( i )->icon().pixmap( mPreviewList.item( i )->icon().actualSize( QSize( 512, 512 ) ) ) );
241  QPixmap enlarged( widthMax, img.height() );
242  // fill transparent and add original image
243  enlarged.fill( Qt::transparent );
244  QPainter p( &enlarged );
245  p.drawPixmap( QPoint( ( widthMax - img.width() ) / 2, 0 ), img );
246  p.end();
247  mPreviewList.item( i )->setIcon( enlarged );
248  }
249 }
250 
251 bool QgsPropertyAssistantWidget::computeValuesFromExpression( const QString &expression, double &minValue, double &maxValue ) const
252 {
253  QgsExpression e( expression );
254 
255  QgsExpressionContext context;
256  if ( mExpressionContextGenerator )
257  {
258  context = mExpressionContextGenerator->createExpressionContext();
259  }
260  else
261  {
265  }
266 
267  if ( !e.prepare( &context ) )
268  return false;
269 
270  QSet<QString> referencedCols( e.referencedColumns() );
271 
272  QgsFeatureIterator fit = mLayer->getFeatures(
273  QgsFeatureRequest().setFlags( e.needsGeometry()
276  .setSubsetOfAttributes( referencedCols, mLayer->fields() ) );
277 
278  // create list of non-null attribute values
279  double min = std::numeric_limits<double>::max();
280  double max = std::numeric_limits<double>::lowest();
281  QgsFeature f;
282  bool found = false;
283  while ( fit.nextFeature( f ) )
284  {
285  bool ok;
286  context.setFeature( f );
287  const double value = e.evaluate( &context ).toDouble( &ok );
288  if ( ok )
289  {
290  max = std::max( max, value );
291  min = std::min( min, value );
292  found = true;
293  }
294  }
295  if ( found )
296  {
297  minValue = min;
298  maxValue = max;
299  }
300  return found;
301 }
302 
303 bool QgsPropertyAssistantWidget::computeValuesFromField( const QString &fieldName, double &minValue, double &maxValue ) const
304 {
305  int fieldIndex = mLayer->fields().lookupField( fieldName );
306  if ( fieldIndex < 0 )
307  {
308  return false;
309  }
310 
311  bool ok = false;
312  double minDouble = mLayer->minimumValue( fieldIndex ).toDouble( &ok );
313  if ( !ok )
314  return false;
315 
316  double maxDouble = mLayer->maximumValue( fieldIndex ).toDouble( &ok );
317  if ( !ok )
318  return false;
319 
320  minValue = minDouble;
321  maxValue = maxDouble;
322  return true;
323 }
324 
326 
327 //
328 // QgsPropertySizeAssistantWidget
329 //
330 
331 QgsPropertySizeAssistantWidget::QgsPropertySizeAssistantWidget( QWidget *parent, const QgsPropertyDefinition &definition, const QgsProperty &initialState )
332  : QgsPropertyAbstractTransformerWidget( parent, definition )
333 {
334  setupUi( this );
335 
336  layout()->setContentsMargins( 0, 0, 0, 0 );
337  layout()->setMargin( 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( QgsStringMap() ) );
405  }
406  else if ( mDefinition.standardTemplate() == QgsPropertyDefinition::StrokeWidth )
407  {
408  tempSymbol.reset( QgsLineSymbol::createSimple( QgsStringMap() ) );
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  layout()->setMargin( 0 );
455 
456  bool supportsAlpha = definition.standardTemplate() == QgsPropertyDefinition::ColorWithAlpha;
457  mNullColorButton->setAllowOpacity( supportsAlpha );
458  mNullColorButton->setShowNoColor( true );
459  mNullColorButton->setColorDialogTitle( tr( "Color For Null Values" ) );
460  mNullColorButton->setContext( QStringLiteral( "symbology" ) );
461  mNullColorButton->setNoColorString( tr( "Transparent" ) );
462 
463  if ( const QgsColorRampTransformer *colorTransform = dynamic_cast< const QgsColorRampTransformer * >( initialState.transformer() ) )
464  {
465  mNullColorButton->setColor( colorTransform->nullColor() );
466  if ( colorTransform->colorRamp() )
467  mColorRampButton->setColorRamp( colorTransform->colorRamp() );
468  }
469 
470  connect( mNullColorButton, &QgsColorButton::colorChanged, this, &QgsPropertyColorAssistantWidget::widgetChanged );
471  connect( mColorRampButton, &QgsColorRampButton::colorRampChanged, this, &QgsPropertyColorAssistantWidget::widgetChanged );
472 
473  if ( !mColorRampButton->colorRamp() )
474  {
475  // set a default ramp
476  QString defaultRampName = QgsProject::instance()->readEntry( QStringLiteral( "DefaultStyles" ), QStringLiteral( "/ColorRamp" ), QString() );
477  std::unique_ptr< QgsColorRamp > defaultRamp( QgsStyle::defaultStyle()->colorRamp( !defaultRampName.isEmpty() ? defaultRampName : QStringLiteral( "Blues" ) ) );
478  if ( defaultRamp )
479  mColorRampButton->setColorRamp( defaultRamp.get() );
480  }
481 }
482 
483 QgsColorRampTransformer *QgsPropertyColorAssistantWidget::createTransformer( double minValue, double maxValue ) const
484 {
486  minValue,
487  maxValue,
488  mColorRampButton->colorRamp(),
489  mNullColorButton->color() );
490  return transformer;
491 }
492 
493 QList<QgsSymbolLegendNode *> QgsPropertyColorAssistantWidget::generatePreviews( const QList<double> &breaks, QgsLayerTreeLayer *parent, const QgsSymbol *symbol, double minValue, double maxValue, QgsCurveTransform *curve ) const
494 {
495  QList< QgsSymbolLegendNode * > nodes;
496 
497  const QgsMarkerSymbol *legendSymbol = dynamic_cast<const QgsMarkerSymbol *>( symbol );
498  std::unique_ptr< QgsMarkerSymbol > tempSymbol;
499 
500  if ( !legendSymbol )
501  {
502  tempSymbol.reset( QgsMarkerSymbol::createSimple( QgsStringMap() ) );
503  legendSymbol = tempSymbol.get();
504  }
505  if ( !legendSymbol )
506  return nodes;
507 
508  std::unique_ptr< QgsColorRampTransformer > t( createTransformer( minValue, maxValue ) );
509  if ( curve )
510  t->setCurveTransform( new QgsCurveTransform( *curve ) );
511 
512  for ( int i = 0; i < breaks.length(); i++ )
513  {
514  std::unique_ptr< QgsSymbolLegendNode > node;
515  std::unique_ptr< QgsMarkerSymbol > symbolClone( static_cast<QgsMarkerSymbol *>( legendSymbol->clone() ) );
516  symbolClone->setColor( t->color( breaks[i] ) );
517  node.reset( new QgsSymbolLegendNode( parent, QgsLegendSymbolItem( symbolClone.get(), QString::number( i ), QString() ) ) );
518  if ( node )
519  nodes << node.release();
520  }
521  return nodes;
522 }
523 
524 QgsPropertyGenericNumericAssistantWidget::QgsPropertyGenericNumericAssistantWidget( QWidget *parent, const QgsPropertyDefinition &definition, const QgsProperty &initialState )
525  : QgsPropertyAbstractTransformerWidget( parent, definition )
526 {
527  setupUi( this );
528 
529  layout()->setContentsMargins( 0, 0, 0, 0 );
530  layout()->setMargin( 0 );
531 
532  nullOutputSpinBox->setShowClearButton( false );
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  }
552  else
553  {
554  minOutputSpinBox->setShowClearButton( false );
555  maxOutputSpinBox->setShowClearButton( false );
556  }
557 
558  if ( const QgsGenericNumericTransformer *transform = dynamic_cast< const QgsGenericNumericTransformer * >( initialState.transformer() ) )
559  {
560  minOutputSpinBox->setValue( transform->minOutputValue() );
561  maxOutputSpinBox->setValue( transform->maxOutputValue() );
562  nullOutputSpinBox->setValue( transform->nullOutputValue() );
563  exponentSpinBox->setValue( transform->exponent() );
564  }
565 
566  connect( minOutputSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
567  connect( maxOutputSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
568  connect( nullOutputSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
569  connect( exponentSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
570 }
571 
572 QgsGenericNumericTransformer *QgsPropertyGenericNumericAssistantWidget::createTransformer( double minValue, double maxValue ) const
573 {
575  minValue,
576  maxValue,
577  minOutputSpinBox->value(),
578  maxOutputSpinBox->value(),
579  nullOutputSpinBox->value(),
580  exponentSpinBox->value() );
581  return transformer;
582 }
583 
int lookupField(const QString &fieldName) const
Look up field&#39;s index from the field name.
Definition: qgsfields.cpp:299
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
QVariant data(int role) const override
Returns data associated with the item. Must be implemented in derived class.
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:1098
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
QVariant minimumValue(int index) const override
Returns the minimum value for an attribute column or an invalid variant in case of error...
void setIconSize(QSize sz)
Set the icon size.
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:62
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:501
Rotation (value between 0-360 degrees)
Definition: qgsproperty.h:60
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...
QSize minimumIconSize() const
Calculates the minimum icon size to prevent cropping.
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
Type propertyType() const
Returns the property type.
QgsFields fields() const override
Returns the list of fields of this layer.
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...
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.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const override
Query the layer for features specified in request.
void fieldChanged(const QString &fieldName)
the signal is 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)
Is emitted whenever a new color is set for the button.
QVariant maximumValue(int index) const override
Returns the maximum value for an attribute column or an invalid variant in case of error...
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:224
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
virtual QgsSymbol * clone() const =0
Gets 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:391
void addChildNode(QgsLayerTreeNode *node)
Append an existing node.
QgsPropertyTransformer subclass for scaling a value into a size according to various scaling methods...
static QgsMarkerSymbol * createSimple(const QgsStringMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
Definition: qgssymbol.cpp:1087
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.
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
Gets a deep copy of this symbol.
Definition: qgssymbol.cpp:1531
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.