QGIS API Documentation  3.6.0-Noosa (5873452)
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  Q_FOREACH ( QgsSymbolLegendNode *node, nodes )
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  layout()->setMargin( 0 );
339 
340  if ( definition.standardTemplate() == QgsPropertyDefinition::Size )
341  {
342  scaleMethodComboBox->addItem( tr( "Flannery" ), QgsSizeScaleTransformer::Flannery );
343  scaleMethodComboBox->addItem( tr( "Surface" ), QgsSizeScaleTransformer::Area );
344  scaleMethodComboBox->addItem( tr( "Radius" ), QgsSizeScaleTransformer::Linear );
345  scaleMethodComboBox->addItem( tr( "Exponential" ), QgsSizeScaleTransformer::Exponential );
346  }
347  else if ( definition.standardTemplate() == QgsPropertyDefinition::StrokeWidth )
348  {
349  scaleMethodComboBox->addItem( tr( "Exponential" ), QgsSizeScaleTransformer::Exponential );
350  scaleMethodComboBox->addItem( tr( "Linear" ), QgsSizeScaleTransformer::Linear );
351  }
352 
353  minSizeSpinBox->setShowClearButton( false );
354  maxSizeSpinBox->setShowClearButton( false );
355  nullSizeSpinBox->setShowClearButton( false );
356 
357  if ( const QgsSizeScaleTransformer *sizeTransform = dynamic_cast< const QgsSizeScaleTransformer * >( initialState.transformer() ) )
358  {
359  minSizeSpinBox->setValue( sizeTransform->minSize() );
360  maxSizeSpinBox->setValue( sizeTransform->maxSize() );
361  nullSizeSpinBox->setValue( sizeTransform->nullSize() );
362  exponentSpinBox->setValue( sizeTransform->exponent() );
363  scaleMethodComboBox->setCurrentIndex( scaleMethodComboBox->findData( sizeTransform->type() ) );
364  }
365 
366  exponentSpinBox->setEnabled( scaleMethodComboBox->currentData().toInt() == QgsSizeScaleTransformer::Exponential );
367 
368  connect( minSizeSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
369  connect( maxSizeSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
370  connect( nullSizeSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
371  connect( exponentSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
372  connect( scaleMethodComboBox, static_cast < void ( QComboBox::* )( int ) > ( &QComboBox::currentIndexChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
373  connect( scaleMethodComboBox, static_cast < void ( QComboBox::* )( int ) > ( &QComboBox::currentIndexChanged ), this,
374  [ = ]
375  {
376  exponentSpinBox->setEnabled( scaleMethodComboBox->currentData().toInt() == QgsSizeScaleTransformer::Exponential );
377  }
378  );
379 }
380 
381 QgsSizeScaleTransformer *QgsPropertySizeAssistantWidget::createTransformer( double minValue, double maxValue ) const
382 {
384  static_cast< QgsSizeScaleTransformer::ScaleType >( scaleMethodComboBox->currentData().toInt() ),
385  minValue,
386  maxValue,
387  minSizeSpinBox->value(),
388  maxSizeSpinBox->value(),
389  nullSizeSpinBox->value(),
390  exponentSpinBox->value() );
391  return transformer;
392 }
393 
394 QList< QgsSymbolLegendNode * > QgsPropertySizeAssistantWidget::generatePreviews( const QList<double> &breaks, QgsLayerTreeLayer *parent, const QgsSymbol *symbol, double minValue, double maxValue, QgsCurveTransform *curve ) const
395 {
396  QList< QgsSymbolLegendNode * > nodes;
397 
398  const QgsSymbol *legendSymbol = symbol;
399  std::unique_ptr< QgsSymbol > tempSymbol;
400 
401  if ( !legendSymbol )
402  {
403  if ( mDefinition.standardTemplate() == QgsPropertyDefinition::Size )
404  {
405  tempSymbol.reset( QgsMarkerSymbol::createSimple( QgsStringMap() ) );
406  }
407  else if ( mDefinition.standardTemplate() == QgsPropertyDefinition::StrokeWidth )
408  {
409  tempSymbol.reset( QgsLineSymbol::createSimple( QgsStringMap() ) );
410  }
411  legendSymbol = tempSymbol.get();
412  }
413  if ( !legendSymbol )
414  return nodes;
415 
416  std::unique_ptr< QgsSizeScaleTransformer > t( createTransformer( minValue, maxValue ) );
417  if ( curve )
418  t->setCurveTransform( new QgsCurveTransform( *curve ) );
419 
420  for ( int i = 0; i < breaks.length(); i++ )
421  {
422  std::unique_ptr< QgsSymbolLegendNode > node;
423  if ( dynamic_cast<const QgsMarkerSymbol *>( legendSymbol ) )
424  {
425  std::unique_ptr< QgsMarkerSymbol > symbolClone( static_cast<QgsMarkerSymbol *>( legendSymbol->clone() ) );
426  symbolClone->setDataDefinedSize( QgsProperty() );
427  symbolClone->setDataDefinedAngle( QgsProperty() ); // to avoid symbol not being drawn
428  symbolClone->setSize( t->size( breaks[i] ) );
429  node.reset( new QgsSymbolLegendNode( parent, QgsLegendSymbolItem( symbolClone.get(), QString::number( i ), QString() ) ) );
430  }
431  else if ( dynamic_cast<const QgsLineSymbol *>( legendSymbol ) )
432  {
433  std::unique_ptr< QgsLineSymbol > symbolClone( static_cast<QgsLineSymbol *>( legendSymbol->clone() ) );
434  symbolClone->setDataDefinedWidth( QgsProperty() );
435  symbolClone->setWidth( t->size( breaks[i] ) );
436  node.reset( new QgsSymbolLegendNode( parent, QgsLegendSymbolItem( symbolClone.get(), QString::number( i ), QString() ) ) );
437  }
438  if ( node )
439  nodes << node.release();
440  }
441  return nodes;
442 }
443 
444 QList<QgsSymbolLegendNode *> QgsPropertyAbstractTransformerWidget::generatePreviews( const QList<double> &, QgsLayerTreeLayer *, const QgsSymbol *, double, double, QgsCurveTransform * ) const
445 {
446  return QList< QgsSymbolLegendNode * >();
447 }
448 
449 QgsPropertyColorAssistantWidget::QgsPropertyColorAssistantWidget( QWidget *parent, const QgsPropertyDefinition &definition, const QgsProperty &initialState )
450  : QgsPropertyAbstractTransformerWidget( parent, definition )
451 {
452  setupUi( this );
453 
454  layout()->setContentsMargins( 0, 0, 0, 0 );
455  layout()->setMargin( 0 );
456 
457  bool supportsAlpha = definition.standardTemplate() == QgsPropertyDefinition::ColorWithAlpha;
458  mNullColorButton->setAllowOpacity( supportsAlpha );
459  mNullColorButton->setShowNoColor( true );
460  mNullColorButton->setColorDialogTitle( tr( "Color For Null Values" ) );
461  mNullColorButton->setContext( QStringLiteral( "symbology" ) );
462  mNullColorButton->setNoColorString( tr( "Transparent" ) );
463 
464  if ( const QgsColorRampTransformer *colorTransform = dynamic_cast< const QgsColorRampTransformer * >( initialState.transformer() ) )
465  {
466  mNullColorButton->setColor( colorTransform->nullColor() );
467  if ( colorTransform->colorRamp() )
468  mColorRampButton->setColorRamp( colorTransform->colorRamp() );
469  }
470 
471  connect( mNullColorButton, &QgsColorButton::colorChanged, this, &QgsPropertyColorAssistantWidget::widgetChanged );
472  connect( mColorRampButton, &QgsColorRampButton::colorRampChanged, this, &QgsPropertyColorAssistantWidget::widgetChanged );
473 
474  if ( !mColorRampButton->colorRamp() )
475  {
476  // set a default ramp
477  QString defaultRampName = QgsProject::instance()->readEntry( QStringLiteral( "DefaultStyles" ), QStringLiteral( "/ColorRamp" ), QString() );
478  std::unique_ptr< QgsColorRamp > defaultRamp( QgsStyle::defaultStyle()->colorRamp( !defaultRampName.isEmpty() ? defaultRampName : QStringLiteral( "Blues" ) ) );
479  if ( defaultRamp )
480  mColorRampButton->setColorRamp( defaultRamp.get() );
481  }
482 }
483 
484 QgsColorRampTransformer *QgsPropertyColorAssistantWidget::createTransformer( double minValue, double maxValue ) const
485 {
487  minValue,
488  maxValue,
489  mColorRampButton->colorRamp(),
490  mNullColorButton->color() );
491  return transformer;
492 }
493 
494 QList<QgsSymbolLegendNode *> QgsPropertyColorAssistantWidget::generatePreviews( const QList<double> &breaks, QgsLayerTreeLayer *parent, const QgsSymbol *symbol, double minValue, double maxValue, QgsCurveTransform *curve ) const
495 {
496  QList< QgsSymbolLegendNode * > nodes;
497 
498  const QgsMarkerSymbol *legendSymbol = dynamic_cast<const QgsMarkerSymbol *>( symbol );
499  std::unique_ptr< QgsMarkerSymbol > tempSymbol;
500 
501  if ( !legendSymbol )
502  {
503  tempSymbol.reset( QgsMarkerSymbol::createSimple( QgsStringMap() ) );
504  legendSymbol = tempSymbol.get();
505  }
506  if ( !legendSymbol )
507  return nodes;
508 
509  std::unique_ptr< QgsColorRampTransformer > t( createTransformer( minValue, maxValue ) );
510  if ( curve )
511  t->setCurveTransform( new QgsCurveTransform( *curve ) );
512 
513  for ( int i = 0; i < breaks.length(); i++ )
514  {
515  std::unique_ptr< QgsSymbolLegendNode > node;
516  std::unique_ptr< QgsMarkerSymbol > symbolClone( static_cast<QgsMarkerSymbol *>( legendSymbol->clone() ) );
517  symbolClone->setColor( t->color( breaks[i] ) );
518  node.reset( new QgsSymbolLegendNode( parent, QgsLegendSymbolItem( symbolClone.get(), QString::number( i ), QString() ) ) );
519  if ( node )
520  nodes << node.release();
521  }
522  return nodes;
523 }
524 
525 QgsPropertyGenericNumericAssistantWidget::QgsPropertyGenericNumericAssistantWidget( QWidget *parent, const QgsPropertyDefinition &definition, const QgsProperty &initialState )
526  : QgsPropertyAbstractTransformerWidget( parent, definition )
527 {
528  setupUi( this );
529 
530  layout()->setContentsMargins( 0, 0, 0, 0 );
531  layout()->setMargin( 0 );
532 
533  nullOutputSpinBox->setShowClearButton( false );
534 
536  {
537  // tweak dialog for rotation
538  minOutputSpinBox->setMaximum( 360.0 );
539  minOutputSpinBox->setValue( 0.0 );
540  minOutputSpinBox->setShowClearButton( true );
541  minOutputSpinBox->setClearValue( 0.0 );
542  minOutputSpinBox->setSuffix( tr( " °" ) );
543  maxOutputSpinBox->setMaximum( 360.0 );
544  maxOutputSpinBox->setValue( 360.0 );
545  maxOutputSpinBox->setShowClearButton( true );
546  maxOutputSpinBox->setClearValue( 360.0 );
547  maxOutputSpinBox->setSuffix( tr( " °" ) );
548  exponentSpinBox->hide();
549  mExponentLabel->hide();
550  mLabelMinOutput->setText( tr( "Angle from" ) );
551  mLabelNullOutput->setText( tr( "Angle when NULL" ) );
552  }
553  else
554  {
555  minOutputSpinBox->setShowClearButton( false );
556  maxOutputSpinBox->setShowClearButton( false );
557  }
558 
559  if ( const QgsGenericNumericTransformer *transform = dynamic_cast< const QgsGenericNumericTransformer * >( initialState.transformer() ) )
560  {
561  minOutputSpinBox->setValue( transform->minOutputValue() );
562  maxOutputSpinBox->setValue( transform->maxOutputValue() );
563  nullOutputSpinBox->setValue( transform->nullOutputValue() );
564  exponentSpinBox->setValue( transform->exponent() );
565  }
566 
567  connect( minOutputSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
568  connect( maxOutputSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
569  connect( nullOutputSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
570  connect( exponentSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
571 }
572 
573 QgsGenericNumericTransformer *QgsPropertyGenericNumericAssistantWidget::createTransformer( double minValue, double maxValue ) const
574 {
576  minValue,
577  maxValue,
578  minOutputSpinBox->value(),
579  maxOutputSpinBox->value(),
580  nullOutputSpinBox->value(),
581  exponentSpinBox->value() );
582  return transformer;
583 }
584 
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
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:1137
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
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: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:732
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
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)
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.
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:430
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
Query 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:1126
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:1585
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.