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