QGIS API Documentation  3.0.2-Girona (307d082)
qgsgraduatedsymbolrendererwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsgraduatedsymbolrendererwidget.cpp
3  ---------------------
4  begin : November 2009
5  copyright : (C) 2009 by Martin Dobias
6  email : wonder dot sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
16 #include "qgspanelwidget.h"
17 
20 #include "qgssymbol.h"
21 #include "qgssymbollayerutils.h"
22 #include "qgscolorramp.h"
23 #include "qgscolorrampbutton.h"
24 #include "qgsstyle.h"
25 
26 #include "qgsvectorlayer.h"
27 
30 #include "qgslogger.h"
31 
32 #include "qgsludialog.h"
33 
34 #include "qgsproject.h"
35 #include "qgsmapcanvas.h"
36 
37 #include <QKeyEvent>
38 #include <QMenu>
39 #include <QMessageBox>
40 #include <QStandardItemModel>
41 #include <QStandardItem>
42 #include <QPen>
43 #include <QPainter>
44 
45 // ------------------------------ Model ------------------------------------
46 
48 
49 QgsGraduatedSymbolRendererModel::QgsGraduatedSymbolRendererModel( QObject *parent ) : QAbstractItemModel( parent )
50  , mMimeFormat( QStringLiteral( "application/x-qgsgraduatedsymbolrendererv2model" ) )
51 {
52 }
53 
54 void QgsGraduatedSymbolRendererModel::setRenderer( QgsGraduatedSymbolRenderer *renderer )
55 {
56  if ( mRenderer )
57  {
58  if ( mRenderer->ranges().size() )
59  {
60  beginRemoveRows( QModelIndex(), 0, mRenderer->ranges().size() - 1 );
61  mRenderer = nullptr;
62  endRemoveRows();
63  }
64  else
65  {
66  mRenderer = nullptr;
67  }
68  }
69  if ( renderer )
70  {
71  if ( renderer->ranges().size() )
72  {
73  beginInsertRows( QModelIndex(), 0, renderer->ranges().size() - 1 );
74  mRenderer = renderer;
75  endInsertRows();
76  }
77  else
78  {
79  mRenderer = renderer;
80  }
81  }
82 }
83 
84 void QgsGraduatedSymbolRendererModel::addClass( QgsSymbol *symbol )
85 {
86  if ( !mRenderer ) return;
87  int idx = mRenderer->ranges().size();
88  beginInsertRows( QModelIndex(), idx, idx );
89  mRenderer->addClass( symbol );
90  endInsertRows();
91 }
92 
93 void QgsGraduatedSymbolRendererModel::addClass( const QgsRendererRange &range )
94 {
95  if ( !mRenderer )
96  {
97  return;
98  }
99  int idx = mRenderer->ranges().size();
100  beginInsertRows( QModelIndex(), idx, idx );
101  mRenderer->addClass( range );
102  endInsertRows();
103 }
104 
105 QgsRendererRange QgsGraduatedSymbolRendererModel::rendererRange( const QModelIndex &index )
106 {
107  if ( !index.isValid() || !mRenderer || mRenderer->ranges().size() <= index.row() )
108  {
109  return QgsRendererRange();
110  }
111 
112  return mRenderer->ranges().value( index.row() );
113 }
114 
115 Qt::ItemFlags QgsGraduatedSymbolRendererModel::flags( const QModelIndex &index ) const
116 {
117  if ( !index.isValid() )
118  {
119  return Qt::ItemIsDropEnabled;
120  }
121 
122  Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsUserCheckable;
123 
124  if ( index.column() == 2 )
125  {
126  flags |= Qt::ItemIsEditable;
127  }
128 
129  return flags;
130 }
131 
132 Qt::DropActions QgsGraduatedSymbolRendererModel::supportedDropActions() const
133 {
134  return Qt::MoveAction;
135 }
136 
137 QVariant QgsGraduatedSymbolRendererModel::data( const QModelIndex &index, int role ) const
138 {
139  if ( !index.isValid() || !mRenderer ) return QVariant();
140 
141  const QgsRendererRange range = mRenderer->ranges().value( index.row() );
142 
143  if ( role == Qt::CheckStateRole && index.column() == 0 )
144  {
145  return range.renderState() ? Qt::Checked : Qt::Unchecked;
146  }
147  else if ( role == Qt::DisplayRole || role == Qt::ToolTipRole )
148  {
149  switch ( index.column() )
150  {
151  case 1:
152  {
153  int decimalPlaces = mRenderer->labelFormat().precision() + 2;
154  if ( decimalPlaces < 0 ) decimalPlaces = 0;
155  return QString::number( range.lowerValue(), 'f', decimalPlaces ) + " - " + QString::number( range.upperValue(), 'f', decimalPlaces );
156  }
157  case 2:
158  return range.label();
159  default:
160  return QVariant();
161  }
162  }
163  else if ( role == Qt::DecorationRole && index.column() == 0 && range.symbol() )
164  {
165  return QgsSymbolLayerUtils::symbolPreviewIcon( range.symbol(), QSize( 16, 16 ) );
166  }
167  else if ( role == Qt::TextAlignmentRole )
168  {
169  return ( index.column() == 0 ) ? Qt::AlignHCenter : Qt::AlignLeft;
170  }
171  else if ( role == Qt::EditRole )
172  {
173  switch ( index.column() )
174  {
175  // case 1: return rangeStr;
176  case 2:
177  return range.label();
178  default:
179  return QVariant();
180  }
181  }
182 
183  return QVariant();
184 }
185 
186 bool QgsGraduatedSymbolRendererModel::setData( const QModelIndex &index, const QVariant &value, int role )
187 {
188  if ( !index.isValid() )
189  return false;
190 
191  if ( index.column() == 0 && role == Qt::CheckStateRole )
192  {
193  mRenderer->updateRangeRenderState( index.row(), value == Qt::Checked );
194  emit dataChanged( index, index );
195  return true;
196  }
197 
198  if ( role != Qt::EditRole )
199  return false;
200 
201  switch ( index.column() )
202  {
203  case 1: // range
204  return false; // range is edited in popup dialog
205  case 2: // label
206  mRenderer->updateRangeLabel( index.row(), value.toString() );
207  break;
208  default:
209  return false;
210  }
211 
212  emit dataChanged( index, index );
213  return true;
214 }
215 
216 QVariant QgsGraduatedSymbolRendererModel::headerData( int section, Qt::Orientation orientation, int role ) const
217 {
218  if ( orientation == Qt::Horizontal && role == Qt::DisplayRole && section >= 0 && section < 3 )
219  {
220  QStringList lst;
221  lst << tr( "Symbol" ) << tr( "Values" ) << tr( "Legend" );
222  return lst.value( section );
223  }
224  return QVariant();
225 }
226 
227 int QgsGraduatedSymbolRendererModel::rowCount( const QModelIndex &parent ) const
228 {
229  if ( parent.isValid() || !mRenderer )
230  {
231  return 0;
232  }
233  return mRenderer->ranges().size();
234 }
235 
236 int QgsGraduatedSymbolRendererModel::columnCount( const QModelIndex &index ) const
237 {
238  Q_UNUSED( index );
239  return 3;
240 }
241 
242 QModelIndex QgsGraduatedSymbolRendererModel::index( int row, int column, const QModelIndex &parent ) const
243 {
244  if ( hasIndex( row, column, parent ) )
245  {
246  return createIndex( row, column );
247  }
248  return QModelIndex();
249 }
250 
251 QModelIndex QgsGraduatedSymbolRendererModel::parent( const QModelIndex &index ) const
252 {
253  Q_UNUSED( index );
254  return QModelIndex();
255 }
256 
257 QStringList QgsGraduatedSymbolRendererModel::mimeTypes() const
258 {
259  QStringList types;
260  types << mMimeFormat;
261  return types;
262 }
263 
264 QMimeData *QgsGraduatedSymbolRendererModel::mimeData( const QModelIndexList &indexes ) const
265 {
266  QMimeData *mimeData = new QMimeData();
267  QByteArray encodedData;
268 
269  QDataStream stream( &encodedData, QIODevice::WriteOnly );
270 
271  // Create list of rows
272  Q_FOREACH ( const QModelIndex &index, indexes )
273  {
274  if ( !index.isValid() || index.column() != 0 )
275  continue;
276 
277  stream << index.row();
278  }
279  mimeData->setData( mMimeFormat, encodedData );
280  return mimeData;
281 }
282 
283 bool QgsGraduatedSymbolRendererModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent )
284 {
285  Q_UNUSED( row );
286  Q_UNUSED( column );
287  if ( action != Qt::MoveAction ) return true;
288 
289  if ( !data->hasFormat( mMimeFormat ) ) return false;
290 
291  QByteArray encodedData = data->data( mMimeFormat );
292  QDataStream stream( &encodedData, QIODevice::ReadOnly );
293 
294  QVector<int> rows;
295  while ( !stream.atEnd() )
296  {
297  int r;
298  stream >> r;
299  rows.append( r );
300  }
301 
302  int to = parent.row();
303  // to is -1 if dragged outside items, i.e. below any item,
304  // then move to the last position
305  if ( to == -1 ) to = mRenderer->ranges().size(); // out of rang ok, will be decreased
306  for ( int i = rows.size() - 1; i >= 0; i-- )
307  {
308  QgsDebugMsg( QString( "move %1 to %2" ).arg( rows[i] ).arg( to ) );
309  int t = to;
310  // moveCategory first removes and then inserts
311  if ( rows[i] < t ) t--;
312  mRenderer->moveClass( rows[i], t );
313  // current moved under another, shift its index up
314  for ( int j = 0; j < i; j++ )
315  {
316  if ( to < rows[j] && rows[i] > rows[j] ) rows[j] += 1;
317  }
318  // removed under 'to' so the target shifted down
319  if ( rows[i] < to ) to--;
320  }
321  emit dataChanged( createIndex( 0, 0 ), createIndex( mRenderer->ranges().size(), 0 ) );
322  emit rowsMoved();
323  return false;
324 }
325 
326 void QgsGraduatedSymbolRendererModel::deleteRows( QList<int> rows )
327 {
328  for ( int i = rows.size() - 1; i >= 0; i-- )
329  {
330  beginRemoveRows( QModelIndex(), rows[i], rows[i] );
331  mRenderer->deleteClass( rows[i] );
332  endRemoveRows();
333  }
334 }
335 
336 void QgsGraduatedSymbolRendererModel::removeAllRows()
337 {
338  beginRemoveRows( QModelIndex(), 0, mRenderer->ranges().size() - 1 );
339  mRenderer->deleteAllClasses();
340  endRemoveRows();
341 }
342 
343 void QgsGraduatedSymbolRendererModel::sort( int column, Qt::SortOrder order )
344 {
345  if ( column == 0 )
346  {
347  return;
348  }
349  if ( column == 1 )
350  {
351  mRenderer->sortByValue( order );
352  }
353  else if ( column == 2 )
354  {
355  mRenderer->sortByLabel( order );
356  }
357  emit rowsMoved();
358  emit dataChanged( createIndex( 0, 0 ), createIndex( mRenderer->ranges().size(), 0 ) );
359  QgsDebugMsg( "Done" );
360 }
361 
362 void QgsGraduatedSymbolRendererModel::updateSymbology( bool resetModel )
363 {
364  if ( resetModel )
365  {
366  reset();
367  }
368  else
369  {
370  emit dataChanged( createIndex( 0, 0 ), createIndex( mRenderer->ranges().size(), 0 ) );
371  }
372 }
373 
374 void QgsGraduatedSymbolRendererModel::updateLabels()
375 {
376  emit dataChanged( createIndex( 0, 2 ), createIndex( mRenderer->ranges().size(), 2 ) );
377 }
378 
379 // ------------------------------ View style --------------------------------
380 QgsGraduatedSymbolRendererViewStyle::QgsGraduatedSymbolRendererViewStyle( QStyle *style )
381  : QProxyStyle( style )
382 {}
383 
384 void QgsGraduatedSymbolRendererViewStyle::drawPrimitive( PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget ) const
385 {
386  if ( element == QStyle::PE_IndicatorItemViewItemDrop && !option->rect.isNull() )
387  {
388  QStyleOption opt( *option );
389  opt.rect.setLeft( 0 );
390  // draw always as line above, because we move item to that index
391  opt.rect.setHeight( 0 );
392  if ( widget ) opt.rect.setRight( widget->width() );
393  QProxyStyle::drawPrimitive( element, &opt, painter, widget );
394  return;
395  }
396  QProxyStyle::drawPrimitive( element, option, painter, widget );
397 }
398 
400 
401 // ------------------------------ Widget ------------------------------------
402 
404 {
405  return new QgsGraduatedSymbolRendererWidget( layer, style, renderer );
406 }
407 
408 QgsExpressionContext QgsGraduatedSymbolRendererWidget::createExpressionContext() const
409 {
410  QgsExpressionContext expContext;
414 
415  if ( mContext.mapCanvas() )
416  {
417  expContext << QgsExpressionContextUtils::mapSettingsScope( mContext.mapCanvas()->mapSettings() )
418  << new QgsExpressionContextScope( mContext.mapCanvas()->expressionContextScope() );
419  }
420  else
421  {
423  }
424 
425  if ( vectorLayer() )
426  expContext << QgsExpressionContextUtils::layerScope( vectorLayer() );
427 
428  // additional scopes
429  Q_FOREACH ( const QgsExpressionContextScope &scope, mContext.additionalExpressionContextScopes() )
430  {
431  expContext.appendScope( new QgsExpressionContextScope( scope ) );
432  }
433 
434  return expContext;
435 }
436 
438  : QgsRendererWidget( layer, style )
439 
440 {
441 
442 
443  // try to recognize the previous renderer
444  // (null renderer means "no previous renderer")
445  if ( renderer )
446  {
447  mRenderer = QgsGraduatedSymbolRenderer::convertFromRenderer( renderer );
448  }
449  if ( !mRenderer )
450  {
451  mRenderer = new QgsGraduatedSymbolRenderer( QLatin1String( "" ), QgsRangeList() );
452  }
453 
454  // setup user interface
455  setupUi( this );
456  connect( methodComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsGraduatedSymbolRendererWidget::methodComboBox_currentIndexChanged );
457  this->layout()->setContentsMargins( 0, 0, 0, 0 );
458 
459  mModel = new QgsGraduatedSymbolRendererModel( this );
460 
461  mExpressionWidget->setFilters( QgsFieldProxyModel::Numeric | QgsFieldProxyModel::Date );
462  mExpressionWidget->setLayer( mLayer );
463 
466 
467  spinPrecision->setMinimum( QgsRendererRangeLabelFormat::MIN_PRECISION );
468  spinPrecision->setMaximum( QgsRendererRangeLabelFormat::MAX_PRECISION );
469 
470  btnColorRamp->setShowRandomColorRamp( true );
471 
472  // set project default color ramp
473  QString defaultColorRamp = QgsProject::instance()->readEntry( QStringLiteral( "DefaultStyles" ), QStringLiteral( "/ColorRamp" ), QLatin1String( "" ) );
474  if ( !defaultColorRamp.isEmpty() )
475  {
476  btnColorRamp->setColorRampFromName( defaultColorRamp );
477  }
478  else
479  {
480  QgsColorRamp *ramp = new QgsGradientColorRamp( QColor( 255, 255, 255 ), QColor( 255, 0, 0 ) );
481  btnColorRamp->setColorRamp( ramp );
482  delete ramp;
483  }
484 
485 
486  viewGraduated->setStyle( new QgsGraduatedSymbolRendererViewStyle( viewGraduated->style() ) );
487 
488  mGraduatedSymbol = QgsSymbol::defaultSymbol( mLayer->geometryType() );
489 
490  methodComboBox->blockSignals( true );
491  methodComboBox->addItem( QStringLiteral( "Color" ) );
492  if ( mGraduatedSymbol->type() == QgsSymbol::Marker )
493  {
494  methodComboBox->addItem( QStringLiteral( "Size" ) );
495  minSizeSpinBox->setValue( 1 );
496  maxSizeSpinBox->setValue( 8 );
497  }
498  else if ( mGraduatedSymbol->type() == QgsSymbol::Line )
499  {
500  methodComboBox->addItem( QStringLiteral( "Size" ) );
501  minSizeSpinBox->setValue( .1 );
502  maxSizeSpinBox->setValue( 2 );
503  }
504  methodComboBox->blockSignals( false );
505 
506  connect( mExpressionWidget, static_cast < void ( QgsFieldExpressionWidget::* )( const QString & ) >( &QgsFieldExpressionWidget::fieldChanged ), this, &QgsGraduatedSymbolRendererWidget::graduatedColumnChanged );
507  connect( viewGraduated, &QAbstractItemView::doubleClicked, this, &QgsGraduatedSymbolRendererWidget::rangesDoubleClicked );
508  connect( viewGraduated, &QAbstractItemView::clicked, this, &QgsGraduatedSymbolRendererWidget::rangesClicked );
509  connect( viewGraduated, &QTreeView::customContextMenuRequested, this, &QgsGraduatedSymbolRendererWidget::contextMenuViewCategories );
510 
511  connect( btnGraduatedClassify, &QAbstractButton::clicked, this, &QgsGraduatedSymbolRendererWidget::classifyGraduated );
512  connect( btnChangeGraduatedSymbol, &QAbstractButton::clicked, this, &QgsGraduatedSymbolRendererWidget::changeGraduatedSymbol );
513  connect( btnGraduatedDelete, &QAbstractButton::clicked, this, &QgsGraduatedSymbolRendererWidget::deleteClasses );
514  connect( btnDeleteAllClasses, &QAbstractButton::clicked, this, &QgsGraduatedSymbolRendererWidget::deleteAllClasses );
515  connect( btnGraduatedAdd, &QAbstractButton::clicked, this, &QgsGraduatedSymbolRendererWidget::addClass );
516  connect( cbxLinkBoundaries, &QAbstractButton::toggled, this, &QgsGraduatedSymbolRendererWidget::toggleBoundariesLink );
517 
518  connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsGraduatedSymbolRendererWidget::mSizeUnitWidget_changed );
519 
521 
522  // initialize from previously set renderer
524 
525  // menus for data-defined rotation/size
526  QMenu *advMenu = new QMenu( this );
527 
528  advMenu->addAction( tr( "Symbol levels…" ), this, SLOT( showSymbolLevels() ) );
529  if ( mGraduatedSymbol->type() == QgsSymbol::Marker )
530  {
531  QAction *actionDdsLegend = advMenu->addAction( tr( "Data-defined size legend…" ) );
532  // only from Qt 5.6 there is convenience addAction() with new style connection
533  connect( actionDdsLegend, &QAction::triggered, this, &QgsGraduatedSymbolRendererWidget::dataDefinedSizeLegend );
534  }
535 
536  btnAdvanced->setMenu( advMenu );
537 
538  mHistogramWidget->setLayer( mLayer );
539  mHistogramWidget->setRenderer( mRenderer );
541  connect( mExpressionWidget, static_cast < void ( QgsFieldExpressionWidget::* )( const QString & ) >( &QgsFieldExpressionWidget::fieldChanged ), mHistogramWidget, &QgsHistogramWidget::setSourceFieldExp );
542 
543  mExpressionWidget->registerExpressionContextGenerator( this );
544 }
545 
546 void QgsGraduatedSymbolRendererWidget::mSizeUnitWidget_changed()
547 {
548  if ( !mGraduatedSymbol ) return;
549  mGraduatedSymbol->setOutputUnit( mSizeUnitWidget->unit() );
550  mGraduatedSymbol->setMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
552  mRenderer->updateSymbols( mGraduatedSymbol );
554 }
555 
557 {
558  delete mRenderer;
559  delete mModel;
560  delete mGraduatedSymbol;
561 }
562 
564 {
565  return mRenderer;
566 }
567 
568 // Connect/disconnect event handlers which trigger updating renderer
569 
571 {
572  connect( spinGraduatedClasses, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), this, &QgsGraduatedSymbolRendererWidget::classifyGraduated );
573  connect( cboGraduatedMode, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsGraduatedSymbolRendererWidget::classifyGraduated );
575  connect( spinPrecision, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), this, &QgsGraduatedSymbolRendererWidget::labelFormatChanged );
576  connect( cbxTrimTrailingZeroes, &QAbstractButton::toggled, this, &QgsGraduatedSymbolRendererWidget::labelFormatChanged );
577  connect( txtLegendFormat, &QLineEdit::textChanged, this, &QgsGraduatedSymbolRendererWidget::labelFormatChanged );
578  connect( minSizeSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsGraduatedSymbolRendererWidget::reapplySizes );
579  connect( maxSizeSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsGraduatedSymbolRendererWidget::reapplySizes );
580 
581  connect( mModel, &QgsGraduatedSymbolRendererModel::rowsMoved, this, &QgsGraduatedSymbolRendererWidget::rowsMoved );
582  connect( mModel, &QAbstractItemModel::dataChanged, this, &QgsGraduatedSymbolRendererWidget::modelDataChanged );
583 }
584 
585 // Connect/disconnect event handlers which trigger updating renderer
586 
588 {
589  disconnect( spinGraduatedClasses, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), this, &QgsGraduatedSymbolRendererWidget::classifyGraduated );
590  disconnect( cboGraduatedMode, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsGraduatedSymbolRendererWidget::classifyGraduated );
592  disconnect( spinPrecision, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), this, &QgsGraduatedSymbolRendererWidget::labelFormatChanged );
593  disconnect( cbxTrimTrailingZeroes, &QAbstractButton::toggled, this, &QgsGraduatedSymbolRendererWidget::labelFormatChanged );
594  disconnect( txtLegendFormat, &QLineEdit::textChanged, this, &QgsGraduatedSymbolRendererWidget::labelFormatChanged );
595  disconnect( minSizeSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsGraduatedSymbolRendererWidget::reapplySizes );
596  disconnect( maxSizeSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsGraduatedSymbolRendererWidget::reapplySizes );
597 
598  disconnect( mModel, &QgsGraduatedSymbolRendererModel::rowsMoved, this, &QgsGraduatedSymbolRendererWidget::rowsMoved );
599  disconnect( mModel, &QAbstractItemModel::dataChanged, this, &QgsGraduatedSymbolRendererWidget::modelDataChanged );
600 }
601 
603 {
605 
607 
608  // update UI from the graduated renderer (update combo boxes, view)
609  if ( mRenderer->mode() < cboGraduatedMode->count() )
610  cboGraduatedMode->setCurrentIndex( mRenderer->mode() );
611 
612  // Only update class count if different - otherwise typing value gets very messy
613  int nclasses = mRenderer->ranges().count();
614  if ( nclasses && updateCount )
615  spinGraduatedClasses->setValue( mRenderer->ranges().count() );
616 
617  // set column
618  QString attrName = mRenderer->classAttribute();
619  mExpressionWidget->setField( attrName );
620  mHistogramWidget->setSourceFieldExp( attrName );
621 
622  // set source symbol
623  if ( mRenderer->sourceSymbol() )
624  {
625  delete mGraduatedSymbol;
626  mGraduatedSymbol = mRenderer->sourceSymbol()->clone();
628  }
629 
630  mModel->setRenderer( mRenderer );
631  viewGraduated->setModel( mModel );
632 
633  if ( mGraduatedSymbol )
634  {
635  mSizeUnitWidget->blockSignals( true );
636  mSizeUnitWidget->setUnit( mGraduatedSymbol->outputUnit() );
637  mSizeUnitWidget->setMapUnitScale( mGraduatedSymbol->mapUnitScale() );
638  mSizeUnitWidget->blockSignals( false );
639  }
640 
641  // set source color ramp
642  methodComboBox->blockSignals( true );
644  {
645  methodComboBox->setCurrentIndex( 0 );
646  if ( mRenderer->sourceColorRamp() )
647  {
648  btnColorRamp->setColorRamp( mRenderer->sourceColorRamp() );
649  }
650  }
651  else
652  {
653  methodComboBox->setCurrentIndex( 1 );
654  if ( !mRenderer->ranges().isEmpty() ) // avoid overriding default size with zeros
655  {
656  minSizeSpinBox->setValue( mRenderer->minSymbolSize() );
657  maxSizeSpinBox->setValue( mRenderer->maxSymbolSize() );
658  }
659  }
660  toggleMethodWidgets( methodComboBox->currentIndex() );
661  methodComboBox->blockSignals( false );
662 
663  QgsRendererRangeLabelFormat labelFormat = mRenderer->labelFormat();
664  txtLegendFormat->setText( labelFormat.format() );
665  spinPrecision->setValue( labelFormat.precision() );
666  cbxTrimTrailingZeroes->setChecked( labelFormat.trimTrailingZeroes() );
667 
668  viewGraduated->resizeColumnToContents( 0 );
669  viewGraduated->resizeColumnToContents( 1 );
670  viewGraduated->resizeColumnToContents( 2 );
671 
672  mHistogramWidget->refresh();
673 
675  emit widgetChanged();
676 }
677 
679 {
680  mRenderer->setClassAttribute( field );
681 }
682 
683 void QgsGraduatedSymbolRendererWidget::methodComboBox_currentIndexChanged( int idx )
684 {
685  toggleMethodWidgets( idx );
686  if ( idx == 0 )
687  {
689  QgsColorRamp *ramp = btnColorRamp->colorRamp();
690 
691  if ( !ramp )
692  {
693  QMessageBox::critical( this, tr( "Select Method" ), tr( "No color ramp defined." ) );
694  return;
695  }
696  mRenderer->setSourceColorRamp( ramp );
698  }
699  else
700  {
701  lblColorRamp->setVisible( false );
702  btnColorRamp->setVisible( false );
703  lblSize->setVisible( true );
704  minSizeSpinBox->setVisible( true );
705  lblSize->setVisible( true );
706  maxSizeSpinBox->setVisible( true );
707  mSizeUnitWidget->setVisible( true );
708 
710  reapplySizes();
711  }
712 }
713 
714 void QgsGraduatedSymbolRendererWidget::toggleMethodWidgets( int idx )
715 {
716  if ( idx == 0 )
717  {
718  lblColorRamp->setVisible( true );
719  btnColorRamp->setVisible( true );
720  lblSize->setVisible( false );
721  minSizeSpinBox->setVisible( false );
722  lblSizeTo->setVisible( false );
723  maxSizeSpinBox->setVisible( false );
724  mSizeUnitWidget->setVisible( false );
725  }
726  else
727  {
728  lblColorRamp->setVisible( false );
729  btnColorRamp->setVisible( false );
730  lblSize->setVisible( true );
731  minSizeSpinBox->setVisible( true );
732  lblSizeTo->setVisible( true );
733  maxSizeSpinBox->setVisible( true );
734  mSizeUnitWidget->setVisible( true );
735  }
736 }
737 
739 {
740  if ( !mModel )
741  return;
742 
743  mModel->updateSymbology( reset );
744  emit widgetChanged();
745 }
746 
747 void QgsGraduatedSymbolRendererWidget::cleanUpSymbolSelector( QgsPanelWidget *container )
748 {
749  QgsSymbolSelectorWidget *dlg = qobject_cast<QgsSymbolSelectorWidget *>( container );
750  if ( !dlg )
751  return;
752 
753  delete dlg->symbol();
754 }
755 
756 void QgsGraduatedSymbolRendererWidget::updateSymbolsFromWidget()
757 {
758  QgsSymbolSelectorWidget *dlg = qobject_cast<QgsSymbolSelectorWidget *>( sender() );
759  delete mGraduatedSymbol;
760  mGraduatedSymbol = dlg->symbol()->clone();
761 
762  mSizeUnitWidget->blockSignals( true );
763  mSizeUnitWidget->setUnit( mGraduatedSymbol->outputUnit() );
764  mSizeUnitWidget->setMapUnitScale( mGraduatedSymbol->mapUnitScale() );
765  mSizeUnitWidget->blockSignals( false );
766 
767  QItemSelectionModel *m = viewGraduated->selectionModel();
768  QModelIndexList selectedIndexes = m->selectedRows( 1 );
769  if ( m && !selectedIndexes.isEmpty() )
770  {
771  Q_FOREACH ( const QModelIndex &idx, selectedIndexes )
772  {
773  if ( idx.isValid() )
774  {
775  int rangeIdx = idx.row();
776  QgsSymbol *newRangeSymbol = mGraduatedSymbol->clone();
777  if ( selectedIndexes.count() > 1 )
778  {
779  //if updating multiple ranges, retain the existing range colors
780  newRangeSymbol->setColor( mRenderer->ranges().at( rangeIdx ).symbol()->color() );
781  }
782  mRenderer->updateRangeSymbol( rangeIdx, newRangeSymbol );
783  }
784  }
785  }
786  else
787  {
789  mRenderer->updateSymbols( mGraduatedSymbol );
790  }
791 
793  emit widgetChanged();
794 }
795 
796 
798 {
799  QString attrName = mExpressionWidget->currentField();
800 
801  int nclasses = spinGraduatedClasses->value();
802 
803  std::unique_ptr<QgsColorRamp> ramp( btnColorRamp->colorRamp() );
804  if ( !ramp )
805  {
806  QMessageBox::critical( this, tr( "Apply Classification" ), tr( "No color ramp defined." ) );
807  return;
808  }
809 
811  if ( cboGraduatedMode->currentIndex() == 0 )
813  else if ( cboGraduatedMode->currentIndex() == 2 )
815  else if ( cboGraduatedMode->currentIndex() == 3 )
817  else if ( cboGraduatedMode->currentIndex() == 4 )
819  else // default should be quantile for now
821 
822  // Jenks is n^2 complexity, warn for big dataset (more than 50k records)
823  // and give the user the chance to cancel
824  if ( QgsGraduatedSymbolRenderer::Jenks == mode && mLayer->featureCount() > 50000 )
825  {
826  if ( QMessageBox::Cancel == QMessageBox::question( this, tr( "Apply Classification" ), tr( "Natural break classification (Jenks) is O(n2) complexity, your classification may take a long time.\nPress cancel to abort breaks calculation or OK to continue." ), QMessageBox::Cancel, QMessageBox::Ok ) )
827  return;
828  }
829 
830  // create and set new renderer
831 
832  mRenderer->setClassAttribute( attrName );
833  mRenderer->setMode( mode );
834 
835  if ( methodComboBox->currentIndex() == 0 )
836  {
837  if ( !ramp )
838  {
839  QMessageBox::critical( this, tr( "Apply Classification" ), tr( "No color ramp defined." ) );
840  return;
841  }
842  mRenderer->setSourceColorRamp( ramp.release() );
843  }
844  else
845  {
846  mRenderer->setSourceColorRamp( nullptr );
847  }
848 
849  QApplication::setOverrideCursor( Qt::WaitCursor );
850  mRenderer->updateClasses( mLayer, mode, nclasses );
851 
852  if ( methodComboBox->currentIndex() == 1 )
853  mRenderer->setSymbolSizes( minSizeSpinBox->value(), maxSizeSpinBox->value() );
854 
855  mRenderer->calculateLabelPrecision();
856  QApplication::restoreOverrideCursor();
857  // PrettyBreaks and StdDev calculation don't generate exact
858  // number of classes - leave user interface unchanged for these
859  updateUiFromRenderer( false );
860 }
861 
863 {
864  std::unique_ptr< QgsColorRamp > ramp( btnColorRamp->colorRamp() );
865  if ( !ramp )
866  return;
867 
868  mRenderer->updateColorRamp( ramp.release() );
869  mRenderer->updateSymbols( mGraduatedSymbol );
871 }
872 
874 {
875  mRenderer->setSymbolSizes( minSizeSpinBox->value(), maxSizeSpinBox->value() );
876  mRenderer->updateSymbols( mGraduatedSymbol );
878 }
879 
881 {
882  QgsSymbol *newSymbol = mGraduatedSymbol->clone();
883  QgsSymbolSelectorWidget *dlg = new QgsSymbolSelectorWidget( newSymbol, mStyle, mLayer, nullptr );
884  dlg->setContext( mContext );
885 
886  connect( dlg, &QgsPanelWidget::widgetChanged, this, &QgsGraduatedSymbolRendererWidget::updateSymbolsFromWidget );
887  connect( dlg, &QgsPanelWidget::panelAccepted, this, &QgsGraduatedSymbolRendererWidget::cleanUpSymbolSelector );
888  openPanel( dlg );
889 }
890 
892 {
893  if ( !mGraduatedSymbol )
894  return;
895 
896  QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( mGraduatedSymbol, btnChangeGraduatedSymbol->iconSize() );
897  btnChangeGraduatedSymbol->setIcon( icon );
898 }
899 
900 #if 0
901 int QgsRendererPropertiesDialog::currentRangeRow()
902 {
903  QModelIndex idx = viewGraduated->selectionModel()->currentIndex();
904  if ( !idx.isValid() )
905  return -1;
906  return idx.row();
907 }
908 #endif
909 
911 {
912  QList<int> rows;
913  QModelIndexList selectedRows = viewGraduated->selectionModel()->selectedRows();
914 
915  Q_FOREACH ( const QModelIndex &r, selectedRows )
916  {
917  if ( r.isValid() )
918  {
919  rows.append( r.row() );
920  }
921  }
922  return rows;
923 }
924 
926 {
928  QModelIndexList selectedRows = viewGraduated->selectionModel()->selectedRows();
929  QModelIndexList::const_iterator sIt = selectedRows.constBegin();
930 
931  for ( ; sIt != selectedRows.constEnd(); ++sIt )
932  {
933  selectedRanges.append( mModel->rendererRange( *sIt ) );
934  }
935  return selectedRanges;
936 }
937 
939 {
940  if ( idx.isValid() && idx.column() == 0 )
941  changeRangeSymbol( idx.row() );
942  if ( idx.isValid() && idx.column() == 1 )
943  changeRange( idx.row() );
944 }
945 
947 {
948  if ( !idx.isValid() )
949  mRowSelected = -1;
950  else
951  mRowSelected = idx.row();
952 }
953 
955 {
956 }
957 
959 {
960  QgsSymbol *newSymbol = mRenderer->ranges()[rangeIdx].symbol()->clone();
961  QgsSymbolSelectorWidget *dlg = new QgsSymbolSelectorWidget( newSymbol, mStyle, mLayer, nullptr );
962  dlg->setContext( mContext );
963 
964  connect( dlg, &QgsPanelWidget::widgetChanged, this, &QgsGraduatedSymbolRendererWidget::updateSymbolsFromWidget );
965  connect( dlg, &QgsPanelWidget::panelAccepted, this, &QgsGraduatedSymbolRendererWidget::cleanUpSymbolSelector );
966  openPanel( dlg );
967 }
968 
970 {
971  QgsLUDialog dialog( this );
972 
973  const QgsRendererRange &range = mRenderer->ranges()[rangeIdx];
974  // Add arbitrary 2 to number of decimal places to retain a bit extra.
975  // Ensures users can see if legend is not completely honest!
976  int decimalPlaces = mRenderer->labelFormat().precision() + 2;
977  if ( decimalPlaces < 0 ) decimalPlaces = 0;
978  dialog.setLowerValue( QString::number( range.lowerValue(), 'f', decimalPlaces ) );
979  dialog.setUpperValue( QString::number( range.upperValue(), 'f', decimalPlaces ) );
980 
981  if ( dialog.exec() == QDialog::Accepted )
982  {
983  double lowerValue = dialog.lowerValue().toDouble();
984  double upperValue = dialog.upperValue().toDouble();
985  mRenderer->updateRangeUpperValue( rangeIdx, upperValue );
986  mRenderer->updateRangeLowerValue( rangeIdx, lowerValue );
987 
988  //If the boundaries have to stay linked, we update the ranges above and below, as well as their label if needed
989  if ( cbxLinkBoundaries->isChecked() )
990  {
991  if ( rangeIdx > 0 )
992  {
993  mRenderer->updateRangeUpperValue( rangeIdx - 1, lowerValue );
994  }
995 
996  if ( rangeIdx < mRenderer->ranges().size() - 1 )
997  {
998  mRenderer->updateRangeLowerValue( rangeIdx + 1, upperValue );
999  }
1000  }
1001  }
1002  mHistogramWidget->refresh();
1003  emit widgetChanged();
1004 }
1005 
1007 {
1008  mModel->addClass( mGraduatedSymbol );
1009  mHistogramWidget->refresh();
1010 }
1011 
1013 {
1014  QList<int> classIndexes = selectedClasses();
1015  mModel->deleteRows( classIndexes );
1016  mHistogramWidget->refresh();
1017 }
1018 
1020 {
1021  mModel->removeAllRows();
1022  mHistogramWidget->refresh();
1023 }
1024 
1026 {
1027  const QgsRangeList &ranges = mRenderer->ranges();
1028  bool ordered = true;
1029  for ( int i = 1; i < ranges.size(); ++i )
1030  {
1031  if ( ranges[i] < ranges[i - 1] )
1032  {
1033  ordered = false;
1034  break;
1035  }
1036  }
1037  return ordered;
1038 }
1039 
1041 {
1042  //If the checkbox controlling the link between boundaries was unchecked and we check it, we have to link the boundaries
1043  //This is done by updating all lower ranges to the upper value of the range above
1044  if ( linked )
1045  {
1046  if ( ! rowsOrdered() )
1047  {
1048  int result = QMessageBox::warning(
1049  this,
1050  tr( "Link Class Boundaries" ),
1051  tr( "Rows will be reordered before linking boundaries. Continue?" ),
1052  QMessageBox::Ok | QMessageBox::Cancel );
1053  if ( result != QMessageBox::Ok )
1054  {
1055  cbxLinkBoundaries->setChecked( false );
1056  return;
1057  }
1058  mRenderer->sortByValue();
1059  }
1060 
1061  // Ok to proceed
1062  for ( int i = 1; i < mRenderer->ranges().size(); ++i )
1063  {
1064  mRenderer->updateRangeLowerValue( i, mRenderer->ranges()[i - 1].upperValue() );
1065  }
1067  }
1068 }
1069 
1071 {
1072  if ( item->column() == 2 )
1073  {
1074  QString label = item->text();
1075  int idx = item->row();
1076  mRenderer->updateRangeLabel( idx, label );
1077  }
1078 }
1079 
1081 {
1083  txtLegendFormat->text(),
1084  spinPrecision->value(),
1085  cbxTrimTrailingZeroes->isChecked() );
1086  mRenderer->setLabelFormat( labelFormat, true );
1087  mModel->updateLabels();
1088 }
1089 
1090 
1092 {
1093  QList<QgsSymbol *> selectedSymbols;
1094 
1095  QItemSelectionModel *m = viewGraduated->selectionModel();
1096  QModelIndexList selectedIndexes = m->selectedRows( 1 );
1097  if ( m && !selectedIndexes.isEmpty() )
1098  {
1099  const QgsRangeList &ranges = mRenderer->ranges();
1100  QModelIndexList::const_iterator indexIt = selectedIndexes.constBegin();
1101  for ( ; indexIt != selectedIndexes.constEnd(); ++indexIt )
1102  {
1103  QStringList list = m->model()->data( *indexIt ).toString().split( ' ' );
1104  if ( list.size() < 3 )
1105  {
1106  continue;
1107  }
1108 
1109  double lowerBound = list.at( 0 ).toDouble();
1110  double upperBound = list.at( 2 ).toDouble();
1111  QgsSymbol *s = findSymbolForRange( lowerBound, upperBound, ranges );
1112  if ( s )
1113  {
1114  selectedSymbols.append( s );
1115  }
1116  }
1117  }
1118  return selectedSymbols;
1119 }
1120 
1121 QgsSymbol *QgsGraduatedSymbolRendererWidget::findSymbolForRange( double lowerBound, double upperBound, const QgsRangeList &ranges ) const
1122 {
1123  int decimalPlaces = mRenderer->labelFormat().precision() + 2;
1124  if ( decimalPlaces < 0 )
1125  decimalPlaces = 0;
1126  double precision = 1.0 / std::pow( 10, decimalPlaces );
1127 
1128  for ( QgsRangeList::const_iterator it = ranges.begin(); it != ranges.end(); ++it )
1129  {
1130  if ( qgsDoubleNear( lowerBound, it->lowerValue(), precision ) && qgsDoubleNear( upperBound, it->upperValue(), precision ) )
1131  {
1132  return it->symbol();
1133  }
1134  }
1135  return nullptr;
1136 }
1137 
1139 {
1140  if ( mModel )
1141  {
1142  mModel->updateSymbology();
1143  }
1144  mHistogramWidget->refresh();
1145  emit widgetChanged();
1146 }
1147 
1149 {
1150  showSymbolLevelsDialog( mRenderer );
1151 }
1152 
1154 {
1155  viewGraduated->selectionModel()->clear();
1156  if ( ! rowsOrdered() )
1157  {
1158  cbxLinkBoundaries->setChecked( false );
1159  }
1160  emit widgetChanged();
1161 }
1162 
1164 {
1165  emit widgetChanged();
1166 }
1167 
1169 {
1170  if ( !event )
1171  {
1172  return;
1173  }
1174 
1175  if ( event->key() == Qt::Key_C && event->modifiers() == Qt::ControlModifier )
1176  {
1177  mCopyBuffer.clear();
1178  mCopyBuffer = selectedRanges();
1179  }
1180  else if ( event->key() == Qt::Key_V && event->modifiers() == Qt::ControlModifier )
1181  {
1182  QgsRangeList::const_iterator rIt = mCopyBuffer.constBegin();
1183  for ( ; rIt != mCopyBuffer.constEnd(); ++rIt )
1184  {
1185  mModel->addClass( *rIt );
1186  }
1187  emit widgetChanged();
1188  }
1189 }
1190 
1191 void QgsGraduatedSymbolRendererWidget::dataDefinedSizeLegend()
1192 {
1193  QgsMarkerSymbol *s = static_cast<QgsMarkerSymbol *>( mGraduatedSymbol ); // this should be only enabled for marker symbols
1195  if ( panel )
1196  {
1197  connect( panel, &QgsPanelWidget::widgetChanged, this, [ = ]
1198  {
1199  mRenderer->setDataDefinedSizeLegend( panel->dataDefinedSizeLegend() );
1200  emit widgetChanged();
1201  } );
1202  openPanel( panel ); // takes ownership of the panel
1203  }
1204 }
void openPanel(QgsPanelWidget *panel)
Open a panel or dialog depending on dock mode setting If dock mode is true this method will emit the ...
const QgsRendererRangeLabelFormat & labelFormat() const
Return the label format used to generate default classification labels.
static QgsGraduatedSymbolRenderer * convertFromRenderer(const QgsFeatureRenderer *renderer)
creates a QgsGraduatedSymbolRenderer from an existing renderer.
The QgsFieldExpressionWidget class reates a widget to choose fields and edit expressions It contains ...
void setMapUnitScale(const QgsMapUnitScale &scale)
Definition: qgssymbol.cpp:258
QString readEntry(const QString &scope, const QString &key, const QString &def=QString(), bool *ok=nullptr) const
bool updateRangeUpperValue(int rangeIndex, double value)
QList< QgsRendererRange > QgsRangeList
QgsSymbol * symbol()
Return the symbol that is currently active in the widget.
void showSymbolLevelsDialog(QgsFeatureRenderer *r)
show a dialog with renderer&#39;s symbol level settings
void colorRampChanged()
Emitted whenever a new color ramp is set for the button.
Base class for renderer settings widgets.
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QgsMapUnitScale mapUnitScale() const
Definition: qgssymbol.cpp:226
Abstract base class for color ramps.
Definition: qgscolorramp.h:31
QgsVectorLayer * mLayer
void setGraduatedMethod(GraduatedMethod method)
set the method used for graduation (either size or color)
QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
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.
Line symbol.
Definition: qgssymbol.h:86
void setSymbolSizes(double minSize, double maxSize)
set varying symbol size for classes
void setLowerValue(const QString &val)
Definition: qgsludialog.cpp:37
void rangesModified(bool rangesAdded)
Emitted when the user modifies the graduated ranges using the histogram widget.
void panelAccepted(QgsPanelWidget *panel)
Emitted when the panel is accepted by the user.
QList< QgsUnitTypes::RenderUnit > RenderUnitList
List of render units.
Definition: qgsunittypes.h:173
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
Definition: qgis.h:251
static QgsRendererWidget * create(QgsVectorLayer *layer, QgsStyle *style, QgsFeatureRenderer *renderer)
void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the symbol widget is shown, e.g., the associated map canvas and expression ...
The QgsMapSettings class contains configuration for rendering of the map.
QgsUnitTypes::RenderUnit outputUnit() const
Returns the units to use for sizes and widths within the symbol.
Definition: qgssymbol.cpp:205
void setOutputUnit(QgsUnitTypes::RenderUnit unit)
Sets the units to use for sizes and widths within the symbol.
Definition: qgssymbol.cpp:250
void sortByValue(Qt::SortOrder order=Qt::AscendingOrder)
bool updateRangeSymbol(int rangeIndex, QgsSymbol *symbol)
static QgsSymbol * defaultSymbol(QgsWkbTypes::GeometryType geomType)
return new default symbol for specified geometry type
Definition: qgssymbol.cpp:266
void updateColorRamp(QgsColorRamp *ramp=nullptr)
Update the color ramp used.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
static QIcon symbolPreviewIcon(QgsSymbol *symbol, QSize size, int padding=0)
Returns an icon preview for a color ramp.
Date or datetime fields.
QgsGraduatedSymbolRendererWidget(QgsVectorLayer *layer, QgsStyle *style, QgsFeatureRenderer *renderer)
bool updateRangeLowerValue(int rangeIndex, double value)
Widget for configuration of appearance of legend for marker symbols with data-defined size...
long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
void setSourceFieldExp(const QString &fieldOrExp)
Sets the source field or expression to use for values in the histogram.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
points (e.g., for font sizes)
Definition: qgsunittypes.h:107
QgsColorRamp * sourceColorRamp()
Returns the source color ramp, from which each classes&#39; color is derived.
QList< int > selectedClasses()
return a list of indexes for the classes under selection
QgsDataDefinedSizeLegendWidget * createDataDefinedSizeLegendWidget(const QgsMarkerSymbol *symbol, const QgsDataDefinedSizeLegend *ddsLegend)
Creates widget to setup data-defined size legend.
Symbol selector widget that can be used to select and build a symbol.
QgsSymbol * symbol() const
QgsFeatureRenderer * renderer() override
return pointer to the renderer (no transfer of ownership)
Single scope for storing variables and functions for use within a QgsExpressionContext.
void addClass()
Adds a class manually to the classification.
void widgetChanged()
Emitted when the widget state changes.
QgsDataDefinedSizeLegend * dataDefinedSizeLegend() const
Returns configuration of appearance of legend when using data-defined size for marker symbols...
void moveClass(int from, int to)
Moves the category at index position from to index position to.
void fieldChanged(const QString &fieldName)
the signal is emitted when the currently selected field changes
void calculateLabelPrecision(bool updateRanges=true)
Reset the label decimal places to a numberbased on the minimum class interval.
void updateClasses(QgsVectorLayer *vlayer, Mode mode, int nclasses)
Recalculate classes for a layer.
Marker symbol.
Definition: qgssymbol.h:85
double minSymbolSize() const
return the min symbol size when graduated by size
QList< QgsSymbol * > selectedSymbols() override
Subclasses may provide the capability of changing multiple symbols at once by implementing the follow...
static QgsExpressionContextScope * atlasScope(QgsLayoutAtlas *atlas)
Creates a new scope which contains variables and functions relating to a QgsLayoutAtlas.
static QgsExpressionContextScope * mapSettingsScope(const QgsMapSettings &mapSettings)
Creates a new scope which contains variables and functions relating to a QgsMapSettings object...
QgsSymbolWidgetContext mContext
Context in which widget is shown.
void sortByLabel(Qt::SortOrder order=Qt::AscendingOrder)
SymbolType type() const
Definition: qgssymbol.h:113
GraduatedMethod graduatedMethod() const
return the method used for graduation (either size or color)
QgsDataDefinedSizeLegend * dataDefinedSizeLegend() const
Returns configuration as set up in the dialog (may be null). Ownership is passed to the caller...
double maxSymbolSize() const
return the max symbol size when graduated by size
virtual QgsSymbol * clone() const =0
Get a deep copy of this symbol.
void setDataDefinedSizeLegend(QgsDataDefinedSizeLegend *settings)
Configures appearance of legend when renderer is configured to use data-defined size for marker symbo...
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:383
void toggleBoundariesLink(bool linked)
Toggle the link between classes boundaries.
void contextMenuViewCategories(QPoint p)
void deleteAllClasses()
Removes all classes from the classification.
void setUpperValue(const QString &val)
Definition: qgsludialog.cpp:42
bool updateRangeRenderState(int rangeIndex, bool render)
QString lowerValue() const
Definition: qgsludialog.cpp:27
bool updateRangeLabel(int rangeIndex, const QString &label)
QString upperValue() const
Definition: qgsludialog.cpp:32
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
void setClassAttribute(const QString &attr)
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
Definition: qgscolorramp.h:139
Represents a vector layer which manages a vector based data sets.
const QgsRangeList & ranges() const
QgsSymbol * findSymbolForRange(double lowerBound, double upperBound, const QgsRangeList &ranges) const
void deleteClasses()
Removes currently selected classes.
void setSourceColorRamp(QgsColorRamp *ramp)
Sets the source color ramp.
void updateSymbols(QgsSymbol *sym)
Update all the symbols but leave breaks and colors.
QgsSymbol * sourceSymbol()
Returns the renderer&#39;s source symbol, which is the base symbol used for the each classes&#39; symbol befo...
QgsVectorLayer * layer()
Returns the layer currently associated with the widget.
void setLabelFormat(const QgsRendererRangeLabelFormat &labelFormat, bool updateRanges=false)
Set the label format used to generate default classification labels.
void setColor(const QColor &color)
Definition: qgssymbol.cpp:445