QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
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  ***************************************************************************/
15 
16 #include <QKeyEvent>
17 #include <QMenu>
18 #include <QMessageBox>
19 #include <QStandardItemModel>
20 #include <QStandardItem>
21 #include <QPen>
22 #include <QPainter>
23 #include <QClipboard>
24 #include <QCompleter>
25 
27 #include "qgspanelwidget.h"
28 
31 #include "qgssymbol.h"
32 #include "qgssymbollayerutils.h"
33 #include "qgscolorramp.h"
34 #include "qgscolorrampbutton.h"
35 #include "qgsstyle.h"
37 #include "qgsvectorlayer.h"
40 #include "qgslogger.h"
41 #include "qgsludialog.h"
42 #include "qgsproject.h"
43 #include "qgsmapcanvas.h"
45 #include "qgsapplication.h"
49 #include "qgsgui.h"
50 #include "qgsprocessinggui.h"
52 #include "qgsprocessingcontext.h"
54 #include "qgstemporalcontroller.h"
55 
56 
57 
58 // ------------------------------ Model ------------------------------------
59 
61 
62 QgsGraduatedSymbolRendererModel::QgsGraduatedSymbolRendererModel( QObject *parent ) : QAbstractItemModel( parent )
63  , mMimeFormat( QStringLiteral( "application/x-qgsgraduatedsymbolrendererv2model" ) )
64 {
65 }
66 
67 void QgsGraduatedSymbolRendererModel::setRenderer( QgsGraduatedSymbolRenderer *renderer )
68 {
69  if ( mRenderer )
70  {
71  if ( !mRenderer->ranges().isEmpty() )
72  {
73  beginRemoveRows( QModelIndex(), 0, mRenderer->ranges().size() - 1 );
74  mRenderer = nullptr;
75  endRemoveRows();
76  }
77  else
78  {
79  mRenderer = nullptr;
80  }
81  }
82  if ( renderer )
83  {
84  if ( !renderer->ranges().isEmpty() )
85  {
86  beginInsertRows( QModelIndex(), 0, renderer->ranges().size() - 1 );
87  mRenderer = renderer;
88  endInsertRows();
89  }
90  else
91  {
92  mRenderer = renderer;
93  }
94  }
95 }
96 
97 void QgsGraduatedSymbolRendererModel::addClass( QgsSymbol *symbol )
98 {
99  if ( !mRenderer ) return;
100  int idx = mRenderer->ranges().size();
101  beginInsertRows( QModelIndex(), idx, idx );
102  mRenderer->addClass( symbol );
103  endInsertRows();
104 }
105 
106 void QgsGraduatedSymbolRendererModel::addClass( const QgsRendererRange &range )
107 {
108  if ( !mRenderer )
109  {
110  return;
111  }
112  int idx = mRenderer->ranges().size();
113  beginInsertRows( QModelIndex(), idx, idx );
114  mRenderer->addClass( range );
115  endInsertRows();
116 }
117 
118 QgsRendererRange QgsGraduatedSymbolRendererModel::rendererRange( const QModelIndex &index )
119 {
120  if ( !index.isValid() || !mRenderer || mRenderer->ranges().size() <= index.row() )
121  {
122  return QgsRendererRange();
123  }
124 
125  return mRenderer->ranges().value( index.row() );
126 }
127 
128 Qt::ItemFlags QgsGraduatedSymbolRendererModel::flags( const QModelIndex &index ) const
129 {
130  if ( !index.isValid() )
131  {
132  return Qt::ItemIsDropEnabled;
133  }
134 
135  Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsUserCheckable;
136 
137  if ( index.column() == 2 )
138  {
139  flags |= Qt::ItemIsEditable;
140  }
141 
142  return flags;
143 }
144 
145 Qt::DropActions QgsGraduatedSymbolRendererModel::supportedDropActions() const
146 {
147  return Qt::MoveAction;
148 }
149 
150 QVariant QgsGraduatedSymbolRendererModel::data( const QModelIndex &index, int role ) const
151 {
152  if ( !index.isValid() || !mRenderer ) return QVariant();
153 
154  const QgsRendererRange range = mRenderer->ranges().value( index.row() );
155 
156  if ( role == Qt::CheckStateRole && index.column() == 0 )
157  {
158  return range.renderState() ? Qt::Checked : Qt::Unchecked;
159  }
160  else if ( role == Qt::DisplayRole || role == Qt::ToolTipRole )
161  {
162  switch ( index.column() )
163  {
164  case 1:
165  {
166  int decimalPlaces = mRenderer->classificationMethod()->labelPrecision() + 2;
167  if ( decimalPlaces < 0 ) decimalPlaces = 0;
168  return QString( QLocale().toString( range.lowerValue(), 'f', decimalPlaces ) + " - " + QLocale().toString( range.upperValue(), 'f', decimalPlaces ) );
169  }
170  case 2:
171  return range.label();
172  default:
173  return QVariant();
174  }
175  }
176  else if ( role == Qt::DecorationRole && index.column() == 0 && range.symbol() )
177  {
178  const int iconSize = QgsGuiUtils::scaleIconSize( 16 );
179  return QgsSymbolLayerUtils::symbolPreviewIcon( range.symbol(), QSize( iconSize, iconSize ) );
180  }
181  else if ( role == Qt::TextAlignmentRole )
182  {
183  return ( index.column() == 0 ) ? Qt::AlignHCenter : Qt::AlignLeft;
184  }
185  else if ( role == Qt::EditRole )
186  {
187  switch ( index.column() )
188  {
189  // case 1: return rangeStr;
190  case 2:
191  return range.label();
192  default:
193  return QVariant();
194  }
195  }
196 
197  return QVariant();
198 }
199 
200 bool QgsGraduatedSymbolRendererModel::setData( const QModelIndex &index, const QVariant &value, int role )
201 {
202  if ( !index.isValid() )
203  return false;
204 
205  if ( index.column() == 0 && role == Qt::CheckStateRole )
206  {
207  mRenderer->updateRangeRenderState( index.row(), value == Qt::Checked );
208  emit dataChanged( index, index );
209  return true;
210  }
211 
212  if ( role != Qt::EditRole )
213  return false;
214 
215  switch ( index.column() )
216  {
217  case 1: // range
218  return false; // range is edited in popup dialog
219  case 2: // label
220  mRenderer->updateRangeLabel( index.row(), value.toString() );
221  break;
222  default:
223  return false;
224  }
225 
226  emit dataChanged( index, index );
227  return true;
228 }
229 
230 QVariant QgsGraduatedSymbolRendererModel::headerData( int section, Qt::Orientation orientation, int role ) const
231 {
232  if ( orientation == Qt::Horizontal && role == Qt::DisplayRole && section >= 0 && section < 3 )
233  {
234  QStringList lst;
235  lst << tr( "Symbol" ) << tr( "Values" ) << tr( "Legend" );
236  return lst.value( section );
237  }
238  return QVariant();
239 }
240 
241 int QgsGraduatedSymbolRendererModel::rowCount( const QModelIndex &parent ) const
242 {
243  if ( parent.isValid() || !mRenderer )
244  {
245  return 0;
246  }
247  return mRenderer->ranges().size();
248 }
249 
250 int QgsGraduatedSymbolRendererModel::columnCount( const QModelIndex &index ) const
251 {
252  Q_UNUSED( index )
253  return 3;
254 }
255 
256 QModelIndex QgsGraduatedSymbolRendererModel::index( int row, int column, const QModelIndex &parent ) const
257 {
258  if ( hasIndex( row, column, parent ) )
259  {
260  return createIndex( row, column );
261  }
262  return QModelIndex();
263 }
264 
265 QModelIndex QgsGraduatedSymbolRendererModel::parent( const QModelIndex &index ) const
266 {
267  Q_UNUSED( index )
268  return QModelIndex();
269 }
270 
271 QStringList QgsGraduatedSymbolRendererModel::mimeTypes() const
272 {
273  QStringList types;
274  types << mMimeFormat;
275  return types;
276 }
277 
278 QMimeData *QgsGraduatedSymbolRendererModel::mimeData( const QModelIndexList &indexes ) const
279 {
280  QMimeData *mimeData = new QMimeData();
281  QByteArray encodedData;
282 
283  QDataStream stream( &encodedData, QIODevice::WriteOnly );
284 
285  // Create list of rows
286  const auto constIndexes = indexes;
287  for ( const QModelIndex &index : constIndexes )
288  {
289  if ( !index.isValid() || index.column() != 0 )
290  continue;
291 
292  stream << index.row();
293  }
294  mimeData->setData( mMimeFormat, encodedData );
295  return mimeData;
296 }
297 
298 bool QgsGraduatedSymbolRendererModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent )
299 {
300  Q_UNUSED( row )
301  Q_UNUSED( column )
302  if ( action != Qt::MoveAction ) return true;
303 
304  if ( !data->hasFormat( mMimeFormat ) ) return false;
305 
306  QByteArray encodedData = data->data( mMimeFormat );
307  QDataStream stream( &encodedData, QIODevice::ReadOnly );
308 
309  QVector<int> rows;
310  while ( !stream.atEnd() )
311  {
312  int r;
313  stream >> r;
314  rows.append( r );
315  }
316 
317  int to = parent.row();
318  // to is -1 if dragged outside items, i.e. below any item,
319  // then move to the last position
320  if ( to == -1 ) to = mRenderer->ranges().size(); // out of rang ok, will be decreased
321  for ( int i = rows.size() - 1; i >= 0; i-- )
322  {
323  QgsDebugMsg( QStringLiteral( "move %1 to %2" ).arg( rows[i] ).arg( to ) );
324  int t = to;
325  // moveCategory first removes and then inserts
326  if ( rows[i] < t ) t--;
327  mRenderer->moveClass( rows[i], t );
328  // current moved under another, shift its index up
329  for ( int j = 0; j < i; j++ )
330  {
331  if ( to < rows[j] && rows[i] > rows[j] ) rows[j] += 1;
332  }
333  // removed under 'to' so the target shifted down
334  if ( rows[i] < to ) to--;
335  }
336  emit dataChanged( createIndex( 0, 0 ), createIndex( mRenderer->ranges().size(), 0 ) );
337  emit rowsMoved();
338  return false;
339 }
340 
341 void QgsGraduatedSymbolRendererModel::deleteRows( QList<int> rows )
342 {
343  for ( int i = rows.size() - 1; i >= 0; i-- )
344  {
345  beginRemoveRows( QModelIndex(), rows[i], rows[i] );
346  mRenderer->deleteClass( rows[i] );
347  endRemoveRows();
348  }
349 }
350 
351 void QgsGraduatedSymbolRendererModel::removeAllRows()
352 {
353  beginRemoveRows( QModelIndex(), 0, mRenderer->ranges().size() - 1 );
354  mRenderer->deleteAllClasses();
355  endRemoveRows();
356 }
357 
358 void QgsGraduatedSymbolRendererModel::sort( int column, Qt::SortOrder order )
359 {
360  if ( column == 0 )
361  {
362  return;
363  }
364  if ( column == 1 )
365  {
366  mRenderer->sortByValue( order );
367  }
368  else if ( column == 2 )
369  {
370  mRenderer->sortByLabel( order );
371  }
372  emit rowsMoved();
373  emit dataChanged( createIndex( 0, 0 ), createIndex( mRenderer->ranges().size(), 0 ) );
374 }
375 
376 void QgsGraduatedSymbolRendererModel::updateSymbology()
377 {
378  emit dataChanged( createIndex( 0, 0 ), createIndex( mRenderer->ranges().size(), 0 ) );
379 }
380 
381 void QgsGraduatedSymbolRendererModel::updateLabels()
382 {
383  emit dataChanged( createIndex( 0, 2 ), createIndex( mRenderer->ranges().size(), 2 ) );
384 }
385 
386 // ------------------------------ View style --------------------------------
387 QgsGraduatedSymbolRendererViewStyle::QgsGraduatedSymbolRendererViewStyle( QWidget *parent )
388  : QgsProxyStyle( parent )
389 {}
390 
391 void QgsGraduatedSymbolRendererViewStyle::drawPrimitive( PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget ) const
392 {
393  if ( element == QStyle::PE_IndicatorItemViewItemDrop && !option->rect.isNull() )
394  {
395  QStyleOption opt( *option );
396  opt.rect.setLeft( 0 );
397  // draw always as line above, because we move item to that index
398  opt.rect.setHeight( 0 );
399  if ( widget ) opt.rect.setRight( widget->width() );
400  QProxyStyle::drawPrimitive( element, &opt, painter, widget );
401  return;
402  }
403  QProxyStyle::drawPrimitive( element, option, painter, widget );
404 }
405 
407 
408 // ------------------------------ Widget ------------------------------------
409 
411 {
412  return new QgsGraduatedSymbolRendererWidget( layer, style, renderer );
413 }
414 
415 QgsExpressionContext QgsGraduatedSymbolRendererWidget::createExpressionContext() const
416 {
417  QgsExpressionContext expContext;
421 
422  if ( auto *lMapCanvas = mContext.mapCanvas() )
423  {
424  expContext << QgsExpressionContextUtils::mapSettingsScope( lMapCanvas->mapSettings() )
425  << new QgsExpressionContextScope( lMapCanvas->expressionContextScope() );
426  if ( const QgsExpressionContextScopeGenerator *generator = dynamic_cast< const QgsExpressionContextScopeGenerator * >( lMapCanvas->temporalController() ) )
427  {
428  expContext << generator->createExpressionContextScope();
429  }
430  }
431  else
432  {
434  }
435 
436  if ( auto *lVectorLayer = vectorLayer() )
437  expContext << QgsExpressionContextUtils::layerScope( lVectorLayer );
438 
439  // additional scopes
440  const auto constAdditionalExpressionContextScopes = mContext.additionalExpressionContextScopes();
441  for ( const QgsExpressionContextScope &scope : constAdditionalExpressionContextScopes )
442  {
443  expContext.appendScope( new QgsExpressionContextScope( scope ) );
444  }
445 
446  return expContext;
447 }
448 
450  : QgsRendererWidget( layer, style )
451 {
452  // try to recognize the previous renderer
453  // (null renderer means "no previous renderer")
454  if ( renderer )
455  {
457  }
458  if ( !mRenderer )
459  {
460  mRenderer = qgis::make_unique< QgsGraduatedSymbolRenderer >( QString(), QgsRangeList() );
461  }
462 
463  // setup user interface
464  setupUi( this );
465 
466  mSymmetryPointValidator = new QDoubleValidator();
467  cboSymmetryPoint->setEditable( true );
468  cboSymmetryPoint->setValidator( mSymmetryPointValidator );
469 
470  const QMap<QString, QString> methods = QgsApplication::classificationMethodRegistry()->methodNames();
471  for ( QMap<QString, QString>::const_iterator it = methods.constBegin(); it != methods.constEnd(); ++it )
472  {
473  QIcon icon = QgsApplication::classificationMethodRegistry()->icon( it.value() );
474  cboGraduatedMode->addItem( icon, it.key(), it.value() );
475  }
476 
477  connect( methodComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsGraduatedSymbolRendererWidget::methodComboBox_currentIndexChanged );
478  this->layout()->setContentsMargins( 0, 0, 0, 0 );
479 
480  mModel = new QgsGraduatedSymbolRendererModel( this );
481 
482  mExpressionWidget->setFilters( QgsFieldProxyModel::Numeric | QgsFieldProxyModel::Date );
483  mExpressionWidget->setLayer( mLayer );
484 
485  btnChangeGraduatedSymbol->setLayer( mLayer );
486  btnChangeGraduatedSymbol->registerExpressionContextGenerator( this );
487 
490 
491  spinPrecision->setMinimum( QgsClassificationMethod::MIN_PRECISION );
492  spinPrecision->setMaximum( QgsClassificationMethod::MAX_PRECISION );
493  spinPrecision->setClearValue( 4 );
494 
495  spinGraduatedClasses->setShowClearButton( false );
496 
497  btnColorRamp->setShowRandomColorRamp( true );
498 
499  // set project default color ramp
500  QString defaultColorRamp = QgsProject::instance()->readEntry( QStringLiteral( "DefaultStyles" ), QStringLiteral( "/ColorRamp" ), QString() );
501  if ( !defaultColorRamp.isEmpty() )
502  {
503  btnColorRamp->setColorRampFromName( defaultColorRamp );
504  }
505  else
506  {
507  QgsColorRamp *ramp = new QgsGradientColorRamp( QColor( 255, 255, 255 ), QColor( 255, 0, 0 ) );
508  btnColorRamp->setColorRamp( ramp );
509  delete ramp;
510  }
511 
512 
513  viewGraduated->setStyle( new QgsGraduatedSymbolRendererViewStyle( viewGraduated ) );
514 
515  mGraduatedSymbol.reset( QgsSymbol::defaultSymbol( mLayer->geometryType() ) );
516  if ( mGraduatedSymbol )
517  {
518  btnChangeGraduatedSymbol->setSymbolType( mGraduatedSymbol->type() );
519  btnChangeGraduatedSymbol->setSymbol( mGraduatedSymbol->clone() );
520 
521  methodComboBox->blockSignals( true );
522  methodComboBox->addItem( tr( "Color" ), ColorMode );
523  switch ( mGraduatedSymbol->type() )
524  {
525  case QgsSymbol::Marker:
526  {
527  methodComboBox->addItem( tr( "Size" ), SizeMode );
528  minSizeSpinBox->setValue( 1 );
529  maxSizeSpinBox->setValue( 8 );
530  break;
531  }
532  case QgsSymbol::Line:
533  {
534  methodComboBox->addItem( tr( "Size" ), SizeMode );
535  minSizeSpinBox->setValue( .1 );
536  maxSizeSpinBox->setValue( 2 );
537  break;
538  }
539  case QgsSymbol::Fill:
540  {
541  //set button and label invisible to avoid display of a single item combobox
542  methodComboBox->hide();
543  labelMethod->hide();
544  break;
545  }
546  case QgsSymbol::Hybrid:
547  break;
548  }
549  methodComboBox->blockSignals( false );
550  }
551 
552  connect( mExpressionWidget, static_cast < void ( QgsFieldExpressionWidget::* )( const QString & ) >( &QgsFieldExpressionWidget::fieldChanged ), this, &QgsGraduatedSymbolRendererWidget::graduatedColumnChanged );
553  connect( viewGraduated, &QAbstractItemView::doubleClicked, this, &QgsGraduatedSymbolRendererWidget::rangesDoubleClicked );
554  connect( viewGraduated, &QAbstractItemView::clicked, this, &QgsGraduatedSymbolRendererWidget::rangesClicked );
555  connect( viewGraduated, &QTreeView::customContextMenuRequested, this, &QgsGraduatedSymbolRendererWidget::contextMenuViewCategories );
556 
557  connect( btnGraduatedClassify, &QAbstractButton::clicked, this, &QgsGraduatedSymbolRendererWidget::classifyGraduated );
558  connect( btnChangeGraduatedSymbol, &QgsSymbolButton::changed, this, &QgsGraduatedSymbolRendererWidget::changeGraduatedSymbol );
559  connect( btnGraduatedDelete, &QAbstractButton::clicked, this, &QgsGraduatedSymbolRendererWidget::deleteClasses );
560  connect( btnDeleteAllClasses, &QAbstractButton::clicked, this, &QgsGraduatedSymbolRendererWidget::deleteAllClasses );
561  connect( btnGraduatedAdd, &QAbstractButton::clicked, this, &QgsGraduatedSymbolRendererWidget::addClass );
562  connect( cbxLinkBoundaries, &QAbstractButton::toggled, this, &QgsGraduatedSymbolRendererWidget::toggleBoundariesLink );
563  connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsGraduatedSymbolRendererWidget::mSizeUnitWidget_changed );
564 
565  connect( cboGraduatedMode, qgis::overload<int>::of( &QComboBox::currentIndexChanged ), this, &QgsGraduatedSymbolRendererWidget::updateMethodParameters );
566 
568 
569  // initialize from previously set renderer
571 
572  // default to collapsed symmetric group for ui simplicity
573  mGroupBoxSymmetric->setCollapsed( true ); //
574 
575  // menus for data-defined rotation/size
576  QMenu *advMenu = new QMenu( this );
577 
578  advMenu->addAction( tr( "Symbol Levels…" ), this, SLOT( showSymbolLevels() ) );
579  if ( mGraduatedSymbol && mGraduatedSymbol->type() == QgsSymbol::Marker )
580  {
581  QAction *actionDdsLegend = advMenu->addAction( tr( "Data-defined Size Legend…" ) );
582  // only from Qt 5.6 there is convenience addAction() with new style connection
583  connect( actionDdsLegend, &QAction::triggered, this, &QgsGraduatedSymbolRendererWidget::dataDefinedSizeLegend );
584  }
585 
586  btnAdvanced->setMenu( advMenu );
587 
588  mHistogramWidget->setLayer( mLayer );
589  mHistogramWidget->setRenderer( mRenderer.get() );
591  connect( mExpressionWidget, static_cast < void ( QgsFieldExpressionWidget::* )( const QString & ) >( &QgsFieldExpressionWidget::fieldChanged ), mHistogramWidget, &QgsHistogramWidget::setSourceFieldExp );
592 
593  mExpressionWidget->registerExpressionContextGenerator( this );
594 }
595 
596 void QgsGraduatedSymbolRendererWidget::mSizeUnitWidget_changed()
597 {
598  if ( !mGraduatedSymbol )
599  return;
600  mGraduatedSymbol->setOutputUnit( mSizeUnitWidget->unit() );
601  mGraduatedSymbol->setMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
602  mRenderer->updateSymbols( mGraduatedSymbol.get() );
603  refreshSymbolView();
604 }
605 
607 {
608  delete mModel;
609  mParameterWidgetWrappers.clear();
610 }
611 
613 {
614  return mRenderer.get();
615 }
616 
618 {
620  btnChangeGraduatedSymbol->setMapCanvas( context.mapCanvas() );
621  btnChangeGraduatedSymbol->setMessageBar( context.messageBar() );
622 }
623 
624 // Connect/disconnect event handlers which trigger updating renderer
626 {
627  connect( spinGraduatedClasses, qgis::overload<int>::of( &QSpinBox::valueChanged ), this, &QgsGraduatedSymbolRendererWidget::classifyGraduated );
628  connect( cboGraduatedMode, qgis::overload<int>::of( &QComboBox::currentIndexChanged ), this, &QgsGraduatedSymbolRendererWidget::classifyGraduated );
630  connect( spinPrecision, qgis::overload<int>::of( &QSpinBox::valueChanged ), this, &QgsGraduatedSymbolRendererWidget::labelFormatChanged );
631  connect( cbxTrimTrailingZeroes, &QAbstractButton::toggled, this, &QgsGraduatedSymbolRendererWidget::labelFormatChanged );
632  connect( txtLegendFormat, &QLineEdit::textChanged, this, &QgsGraduatedSymbolRendererWidget::labelFormatChanged );
633  connect( minSizeSpinBox, qgis::overload<double>::of( &QDoubleSpinBox::valueChanged ), this, &QgsGraduatedSymbolRendererWidget::reapplySizes );
634  connect( maxSizeSpinBox, qgis::overload<double>::of( &QDoubleSpinBox::valueChanged ), this, &QgsGraduatedSymbolRendererWidget::reapplySizes );
635 
636  connect( mModel, &QgsGraduatedSymbolRendererModel::rowsMoved, this, &QgsGraduatedSymbolRendererWidget::rowsMoved );
637  connect( mModel, &QAbstractItemModel::dataChanged, this, &QgsGraduatedSymbolRendererWidget::modelDataChanged );
638 
639  connect( mGroupBoxSymmetric, &QGroupBox::toggled, this, &QgsGraduatedSymbolRendererWidget::classifyGraduated );
640  connect( cbxAstride, &QAbstractButton::toggled, this, &QgsGraduatedSymbolRendererWidget::classifyGraduated );
641  connect( cboSymmetryPoint, qgis::overload<int>::of( &QComboBox::currentIndexChanged ), this, &QgsGraduatedSymbolRendererWidget::classifyGraduated );
642  connect( cboSymmetryPoint->lineEdit(), &QLineEdit::editingFinished, this, &QgsGraduatedSymbolRendererWidget::symmetryPointEditingFinished );
643 
644  for ( const auto &ppww : qgis::as_const( mParameterWidgetWrappers ) )
645  {
647  }
648 }
649 
650 // Connect/disconnect event handlers which trigger updating renderer
652 {
653  disconnect( spinGraduatedClasses, qgis::overload<int>::of( &QSpinBox::valueChanged ), this, &QgsGraduatedSymbolRendererWidget::classifyGraduated );
654  disconnect( cboGraduatedMode, qgis::overload<int>::of( &QComboBox::currentIndexChanged ), this, &QgsGraduatedSymbolRendererWidget::classifyGraduated );
656  disconnect( spinPrecision, qgis::overload<int>::of( &QSpinBox::valueChanged ), this, &QgsGraduatedSymbolRendererWidget::labelFormatChanged );
657  disconnect( cbxTrimTrailingZeroes, &QAbstractButton::toggled, this, &QgsGraduatedSymbolRendererWidget::labelFormatChanged );
658  disconnect( txtLegendFormat, &QLineEdit::textChanged, this, &QgsGraduatedSymbolRendererWidget::labelFormatChanged );
659  disconnect( minSizeSpinBox, qgis::overload<double>::of( &QDoubleSpinBox::valueChanged ), this, &QgsGraduatedSymbolRendererWidget::reapplySizes );
660  disconnect( maxSizeSpinBox, qgis::overload<double>::of( &QDoubleSpinBox::valueChanged ), this, &QgsGraduatedSymbolRendererWidget::reapplySizes );
661 
662  disconnect( mModel, &QgsGraduatedSymbolRendererModel::rowsMoved, this, &QgsGraduatedSymbolRendererWidget::rowsMoved );
663  disconnect( mModel, &QAbstractItemModel::dataChanged, this, &QgsGraduatedSymbolRendererWidget::modelDataChanged );
664 
665  disconnect( mGroupBoxSymmetric, &QGroupBox::toggled, this, &QgsGraduatedSymbolRendererWidget::classifyGraduated );
666  disconnect( cbxAstride, &QAbstractButton::toggled, this, &QgsGraduatedSymbolRendererWidget::classifyGraduated );
667  disconnect( cboSymmetryPoint, qgis::overload<int>::of( &QComboBox::currentIndexChanged ), this, &QgsGraduatedSymbolRendererWidget::classifyGraduated );
668  disconnect( cboSymmetryPoint->lineEdit(), &QLineEdit::editingFinished, this, &QgsGraduatedSymbolRendererWidget::symmetryPointEditingFinished );
669 
670  for ( const auto &ppww : qgis::as_const( mParameterWidgetWrappers ) )
671  {
673  }
674 }
675 
677 {
678  disconnectUpdateHandlers();
679 
680  const QgsClassificationMethod *method = mRenderer->classificationMethod();
681 
682  const QgsRangeList ranges = mRenderer->ranges();
683 
684  // use the breaks for symmetry point
685  int precision = spinPrecision->value() + 2;
686  while ( cboSymmetryPoint->count() )
687  cboSymmetryPoint->removeItem( 0 );
688  for ( int i = 0; i < ranges.count() - 1; i++ )
689  cboSymmetryPoint->addItem( QString::number( ranges.at( i ).upperValue(), 'f', precision ), ranges.at( i ).upperValue() );
690 
691  if ( method )
692  {
693  int idx = cboGraduatedMode->findData( method->id() );
694  if ( idx >= 0 )
695  cboGraduatedMode->setCurrentIndex( idx );
696 
697  mGroupBoxSymmetric->setVisible( method->symmetricModeAvailable() );
698  mGroupBoxSymmetric->setChecked( method->symmetricModeEnabled() );
699  cbxAstride->setChecked( method->symmetryAstride() );
700  if ( method->symmetricModeEnabled() )
701  cboSymmetryPoint->setItemText( cboSymmetryPoint->currentIndex(), QString::number( method->symmetryPoint(), 'f', method->labelPrecision() + 2 ) );
702 
703  txtLegendFormat->setText( method->labelFormat() );
704  spinPrecision->setValue( method->labelPrecision() );
705  cbxTrimTrailingZeroes->setChecked( method->labelTrimTrailingZeroes() );
706 
707  QgsProcessingContext context;
708  for ( const auto &ppww : qgis::as_const( mParameterWidgetWrappers ) )
709  {
710  const QgsProcessingParameterDefinition *def = ppww->parameterDefinition();
711  QVariant value = method->parameterValues().value( def->name(), def->defaultValue() );
712  ppww->setParameterValue( value, context );
713  }
714  }
715 
716  // Only update class count if different - otherwise typing value gets very messy
717  int nclasses = ranges.count();
718  if ( nclasses && updateCount )
719  {
720  spinGraduatedClasses->setValue( ranges.count() );
721  }
722 
723  // set column
724  QString attrName = mRenderer->classAttribute();
725  mExpressionWidget->setField( attrName );
726  mHistogramWidget->setSourceFieldExp( attrName );
727 
728  // set source symbol
729  if ( mRenderer->sourceSymbol() )
730  {
731  mGraduatedSymbol.reset( mRenderer->sourceSymbol()->clone() );
732  whileBlocking( btnChangeGraduatedSymbol )->setSymbol( mGraduatedSymbol->clone() );
733  }
734 
735  mModel->setRenderer( mRenderer.get() );
736  viewGraduated->setModel( mModel );
737 
738  connect( viewGraduated->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsGraduatedSymbolRendererWidget::selectionChanged );
739 
740  if ( mGraduatedSymbol )
741  {
742  mSizeUnitWidget->blockSignals( true );
743  mSizeUnitWidget->setUnit( mGraduatedSymbol->outputUnit() );
744  mSizeUnitWidget->setMapUnitScale( mGraduatedSymbol->mapUnitScale() );
745  mSizeUnitWidget->blockSignals( false );
746  }
747 
748  // set source color ramp
749  methodComboBox->blockSignals( true );
750  switch ( mRenderer->graduatedMethod() )
751  {
753  {
754  methodComboBox->setCurrentIndex( methodComboBox->findData( ColorMode ) );
755  if ( mRenderer->sourceColorRamp() )
756  {
757  btnColorRamp->setColorRamp( mRenderer->sourceColorRamp() );
758  }
759  break;
760  }
762  {
763  methodComboBox->setCurrentIndex( methodComboBox->findData( SizeMode ) );
764  if ( !mRenderer->ranges().isEmpty() ) // avoid overriding default size with zeros
765  {
766  minSizeSpinBox->setValue( mRenderer->minSymbolSize() );
767  maxSizeSpinBox->setValue( mRenderer->maxSymbolSize() );
768  }
769  break;
770  }
771  }
772  toggleMethodWidgets( static_cast< MethodMode>( methodComboBox->currentData().toInt() ) );
773  methodComboBox->blockSignals( false );
774 
775  viewGraduated->resizeColumnToContents( 0 );
776  viewGraduated->resizeColumnToContents( 1 );
777  viewGraduated->resizeColumnToContents( 2 );
778 
779  mHistogramWidget->refresh();
780 
781  connectUpdateHandlers();
782  emit widgetChanged();
783 }
784 
786 {
787  mRenderer->setClassAttribute( field );
788 }
789 
790 void QgsGraduatedSymbolRendererWidget::methodComboBox_currentIndexChanged( int )
791 {
792  const MethodMode newMethod = static_cast< MethodMode >( methodComboBox->currentData().toInt() );
793  toggleMethodWidgets( newMethod );
794  switch ( newMethod )
795  {
796  case ColorMode:
797  {
798  mRenderer->setGraduatedMethod( QgsGraduatedSymbolRenderer::GraduatedColor );
799  QgsColorRamp *ramp = btnColorRamp->colorRamp();
800 
801  if ( !ramp )
802  {
803  QMessageBox::critical( this, tr( "Select Method" ), tr( "No color ramp defined." ) );
804  return;
805  }
806  mRenderer->setSourceColorRamp( ramp );
807  reapplyColorRamp();
808  break;
809  }
810 
811  case SizeMode:
812  {
813  lblColorRamp->setVisible( false );
814  btnColorRamp->setVisible( false );
815  lblSize->setVisible( true );
816  minSizeSpinBox->setVisible( true );
817  lblSize->setVisible( true );
818  maxSizeSpinBox->setVisible( true );
819  mSizeUnitWidget->setVisible( true );
820 
821  mRenderer->setGraduatedMethod( QgsGraduatedSymbolRenderer::GraduatedSize );
822  reapplySizes();
823  break;
824  }
825  }
826 }
827 
828 void QgsGraduatedSymbolRendererWidget::updateMethodParameters()
829 {
830  clearParameterWidgets();
831 
832  const QString methodId = cboGraduatedMode->currentData().toString();
834  Q_ASSERT( method );
835 
836  // need more context?
837  QgsProcessingContext context;
838 
839  for ( const QgsProcessingParameterDefinition *def : method->parameterDefinitions() )
840  {
842  mParametersLayout->addRow( ppww->createWrappedLabel(), ppww->createWrappedWidget( context ) );
843 
844  QVariant value = method->parameterValues().value( def->name(), def->defaultValue() );
845  ppww->setParameterValue( value, context );
846 
848 
849  mParameterWidgetWrappers.push_back( std::unique_ptr<QgsAbstractProcessingParameterWidgetWrapper>( ppww ) );
850  }
851 }
852 
853 void QgsGraduatedSymbolRendererWidget::toggleMethodWidgets( MethodMode mode )
854 {
855  switch ( mode )
856  {
857  case ColorMode:
858  {
859  lblColorRamp->setVisible( true );
860  btnColorRamp->setVisible( true );
861  lblSize->setVisible( false );
862  minSizeSpinBox->setVisible( false );
863  lblSizeTo->setVisible( false );
864  maxSizeSpinBox->setVisible( false );
865  mSizeUnitWidget->setVisible( false );
866  break;
867  }
868 
869  case SizeMode:
870  {
871  lblColorRamp->setVisible( false );
872  btnColorRamp->setVisible( false );
873  lblSize->setVisible( true );
874  minSizeSpinBox->setVisible( true );
875  lblSizeTo->setVisible( true );
876  maxSizeSpinBox->setVisible( true );
877  mSizeUnitWidget->setVisible( true );
878  break;
879  }
880  }
881 }
882 
883 void QgsGraduatedSymbolRendererWidget::clearParameterWidgets()
884 {
885  while ( mParametersLayout->rowCount() )
886  {
887  QFormLayout::TakeRowResult row = mParametersLayout->takeRow( 0 );
888  for ( QLayoutItem *item : QList<QLayoutItem *>( {row.labelItem, row.fieldItem} ) )
889  if ( item )
890  {
891  if ( item->widget() )
892  item->widget()->deleteLater();
893  delete item;
894  }
895  }
896  mParameterWidgetWrappers.clear();
897 }
898 
900 {
901  if ( !mModel )
902  return;
903 
904  mModel->updateSymbology();
905 
906  disconnectUpdateHandlers();
907  spinGraduatedClasses->setValue( mRenderer->ranges().count() );
908  connectUpdateHandlers();
909 
910  emit widgetChanged();
911 }
912 
913 void QgsGraduatedSymbolRendererWidget::cleanUpSymbolSelector( QgsPanelWidget *container )
914 {
915  QgsSymbolSelectorWidget *dlg = qobject_cast<QgsSymbolSelectorWidget *>( container );
916  if ( !dlg )
917  return;
918 
919  delete dlg->symbol();
920 }
921 
922 void QgsGraduatedSymbolRendererWidget::updateSymbolsFromWidget()
923 {
924  QgsSymbolSelectorWidget *dlg = qobject_cast<QgsSymbolSelectorWidget *>( sender() );
925  mGraduatedSymbol.reset( dlg->symbol()->clone() );
926 
927  applyChangeToSymbol();
928 }
929 
931 {
932  mSizeUnitWidget->blockSignals( true );
933  mSizeUnitWidget->setUnit( mGraduatedSymbol->outputUnit() );
934  mSizeUnitWidget->setMapUnitScale( mGraduatedSymbol->mapUnitScale() );
935  mSizeUnitWidget->blockSignals( false );
936 
937  QItemSelectionModel *m = viewGraduated->selectionModel();
938  QModelIndexList selectedIndexes = m->selectedRows( 1 );
939  if ( !selectedIndexes.isEmpty() )
940  {
941  const auto constSelectedIndexes = selectedIndexes;
942  for ( const QModelIndex &idx : constSelectedIndexes )
943  {
944  if ( idx.isValid() )
945  {
946  int rangeIdx = idx.row();
947  QgsSymbol *newRangeSymbol = mGraduatedSymbol->clone();
948  if ( selectedIndexes.count() > 1 )
949  {
950  //if updating multiple ranges, retain the existing range colors
951  newRangeSymbol->setColor( mRenderer->ranges().at( rangeIdx ).symbol()->color() );
952  }
953  mRenderer->updateRangeSymbol( rangeIdx, newRangeSymbol );
954  }
955  }
956  }
957  else
958  {
959  mRenderer->updateSymbols( mGraduatedSymbol.get() );
960  }
961 
962  refreshSymbolView();
963  emit widgetChanged();
964 }
965 
966 void QgsGraduatedSymbolRendererWidget::symmetryPointEditingFinished( )
967 {
968  const QString text = cboSymmetryPoint->lineEdit()->text();
969  int index = cboSymmetryPoint->findText( text );
970  if ( index != -1 )
971  {
972  cboSymmetryPoint->setCurrentIndex( index );
973  }
974  else
975  {
976  cboSymmetryPoint->setItemText( cboSymmetryPoint->currentIndex(), text );
977  classifyGraduated();
978  }
979 }
980 
981 
983 {
984 
985  QgsTemporaryCursorOverride override( Qt::WaitCursor );
986  QString attrName = mExpressionWidget->currentField();
987  int nclasses = spinGraduatedClasses->value();
988 
989  const QString methodId = cboGraduatedMode->currentData().toString();
991  Q_ASSERT( method );
992 
993  int attrNum = mLayer->fields().lookupField( attrName );
994  double minimum = mLayer->minimumValue( attrNum ).toDouble();
995  double maximum = mLayer->maximumValue( attrNum ).toDouble();
996  mSymmetryPointValidator->setBottom( minimum );
997  mSymmetryPointValidator->setTop( maximum );
998  mSymmetryPointValidator->setDecimals( spinPrecision->value() );
999 
1000  if ( method->id() == QgsClassificationEqualInterval::METHOD_ID ||
1002  {
1003  // knowing that spinSymmetryPointForOtherMethods->value() is automatically put at minimum when out of min-max
1004  // using "(maximum-minimum)/100)" to avoid direct comparison of doubles
1005  double currentValue = cboSymmetryPoint->currentText().toDouble();
1006  if ( currentValue < ( minimum + ( maximum - minimum ) / 100. ) || currentValue > ( maximum - ( maximum - minimum ) / 100. ) )
1007  cboSymmetryPoint->setItemText( cboSymmetryPoint->currentIndex(), QString::number( minimum + ( maximum - minimum ) / 2., 'f', method->labelPrecision() + 2 ) );
1008  }
1009 
1010  if ( mGroupBoxSymmetric->isChecked() )
1011  {
1012  double symmetryPoint = cboSymmetryPoint->currentText().toDouble();
1013  bool astride = cbxAstride->isChecked();
1014  method->setSymmetricMode( true, symmetryPoint, astride );
1015  }
1016 
1017  QVariantMap parameterValues;
1018  for ( const auto &ppww : qgis::as_const( mParameterWidgetWrappers ) )
1019  parameterValues.insert( ppww->parameterDefinition()->name(), ppww->parameterValue() );
1020  method->setParameterValues( parameterValues );
1021 
1022  // set method to renderer
1023  mRenderer->setClassificationMethod( method );
1024 
1025  // create and set new renderer
1026  mRenderer->setClassAttribute( attrName );
1027 
1028  // If complexity >= oN^2, warn for big dataset (more than 50k records)
1029  // and give the user the chance to cancel
1030  if ( method->codeComplexity() > 1 && mLayer->featureCount() > 50000 )
1031  {
1032  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 ) )
1033  {
1034  return;
1035  }
1036  }
1037 
1038  if ( methodComboBox->currentData() == ColorMode )
1039  {
1040  std::unique_ptr<QgsColorRamp> ramp( btnColorRamp->colorRamp() );
1041  if ( !ramp )
1042  {
1043  QMessageBox::critical( this, tr( "Apply Classification" ), tr( "No color ramp defined." ) );
1044  return;
1045  }
1046  mRenderer->setSourceColorRamp( ramp.release() );
1047  }
1048  else
1049  {
1050  mRenderer->setSourceColorRamp( nullptr );
1051  }
1052 
1053  mRenderer->updateClasses( mLayer, nclasses );
1054 
1055  if ( methodComboBox->currentData() == SizeMode )
1056  mRenderer->setSymbolSizes( minSizeSpinBox->value(), maxSizeSpinBox->value() );
1057 
1058  mRenderer->calculateLabelPrecision();
1059  // PrettyBreaks and StdDev calculation don't generate exact
1060  // number of classes - leave user interface unchanged for these
1061  updateUiFromRenderer( false );
1062 }
1063 
1065 {
1066  std::unique_ptr< QgsColorRamp > ramp( btnColorRamp->colorRamp() );
1067  if ( !ramp )
1068  return;
1069 
1070  mRenderer->updateColorRamp( ramp.release() );
1071  mRenderer->updateSymbols( mGraduatedSymbol.get() );
1072  refreshSymbolView();
1073 }
1074 
1076 {
1077  mRenderer->setSymbolSizes( minSizeSpinBox->value(), maxSizeSpinBox->value() );
1078  mRenderer->updateSymbols( mGraduatedSymbol.get() );
1079  refreshSymbolView();
1080 }
1081 
1082 #if 0
1083 int QgsRendererPropertiesDialog::currentRangeRow()
1084 {
1085  QModelIndex idx = viewGraduated->selectionModel()->currentIndex();
1086  if ( !idx.isValid() )
1087  return -1;
1088  return idx.row();
1089 }
1090 #endif
1091 
1093 {
1094  QList<int> rows;
1095  QModelIndexList selectedRows = viewGraduated->selectionModel()->selectedRows();
1096 
1097  const auto constSelectedRows = selectedRows;
1098  for ( const QModelIndex &r : constSelectedRows )
1099  {
1100  if ( r.isValid() )
1101  {
1102  rows.append( r.row() );
1103  }
1104  }
1105  return rows;
1106 }
1107 
1109 {
1110  QgsRangeList selectedRanges;
1111  QModelIndexList selectedRows = viewGraduated->selectionModel()->selectedRows();
1112  QModelIndexList::const_iterator sIt = selectedRows.constBegin();
1113 
1114  for ( ; sIt != selectedRows.constEnd(); ++sIt )
1115  {
1116  selectedRanges.append( mModel->rendererRange( *sIt ) );
1117  }
1118  return selectedRanges;
1119 }
1120 
1122 {
1123  if ( idx.isValid() && idx.column() == 0 )
1124  changeRangeSymbol( idx.row() );
1125  if ( idx.isValid() && idx.column() == 1 )
1126  changeRange( idx.row() );
1127 }
1128 
1130 {
1131  if ( !idx.isValid() )
1132  mRowSelected = -1;
1133  else
1134  mRowSelected = idx.row();
1135 }
1136 
1138 {
1139 }
1140 
1142 {
1143  const QgsRendererRange &range = mRenderer->ranges()[rangeIdx];
1144  std::unique_ptr< QgsSymbol > newSymbol( range.symbol()->clone() );
1146  if ( panel && panel->dockMode() )
1147  {
1148  // bit tricky here - the widget doesn't take ownership of the symbol. So we need it to last for the duration of the
1149  // panel's existence. Accordingly, just kinda give it ownership here, and clean up in cleanUpSymbolSelector
1150  QgsSymbolSelectorWidget *dlg = new QgsSymbolSelectorWidget( newSymbol.release(), mStyle, mLayer, panel );
1151  dlg->setContext( mContext );
1152  dlg->setPanelTitle( range.label() );
1153  connect( dlg, &QgsPanelWidget::widgetChanged, this, &QgsGraduatedSymbolRendererWidget::updateSymbolsFromWidget );
1154  connect( dlg, &QgsPanelWidget::panelAccepted, this, &QgsGraduatedSymbolRendererWidget::cleanUpSymbolSelector );
1155  openPanel( dlg );
1156  }
1157  else
1158  {
1159  QgsSymbolSelectorDialog dlg( newSymbol.get(), mStyle, mLayer, panel );
1160  dlg.setContext( mContext );
1161  if ( !dlg.exec() || !newSymbol )
1162  {
1163  return;
1164  }
1165 
1166  mGraduatedSymbol = std::move( newSymbol );
1167  whileBlocking( btnChangeGraduatedSymbol )->setSymbol( mGraduatedSymbol->clone() );
1168  applyChangeToSymbol();
1169  }
1170 }
1171 
1173 {
1174  QgsLUDialog dialog( this );
1175 
1176  const QgsRendererRange &range = mRenderer->ranges()[rangeIdx];
1177  // Add arbitrary 2 to number of decimal places to retain a bit extra.
1178  // Ensures users can see if legend is not completely honest!
1179  int decimalPlaces = mRenderer->classificationMethod()->labelPrecision() + 2;
1180  if ( decimalPlaces < 0 ) decimalPlaces = 0;
1181  dialog.setLowerValue( QLocale().toString( range.lowerValue(), 'f', decimalPlaces ) );
1182  dialog.setUpperValue( QLocale().toString( range.upperValue(), 'f', decimalPlaces ) );
1183 
1184  if ( dialog.exec() == QDialog::Accepted )
1185  {
1186  bool ok = false;
1187  double lowerValue = qgsPermissiveToDouble( dialog.lowerValue(), ok );
1188  if ( ! ok )
1189  lowerValue = 0.0;
1190  double upperValue = qgsPermissiveToDouble( dialog.upperValue(), ok );
1191  if ( ! ok )
1192  upperValue = 0.0;
1193  mRenderer->updateRangeUpperValue( rangeIdx, upperValue );
1194  mRenderer->updateRangeLowerValue( rangeIdx, lowerValue );
1195 
1196  //If the boundaries have to stay linked, we update the ranges above and below, as well as their label if needed
1197  if ( cbxLinkBoundaries->isChecked() )
1198  {
1199  if ( rangeIdx > 0 )
1200  {
1201  mRenderer->updateRangeUpperValue( rangeIdx - 1, lowerValue );
1202  }
1203 
1204  if ( rangeIdx < mRenderer->ranges().size() - 1 )
1205  {
1206  mRenderer->updateRangeLowerValue( rangeIdx + 1, upperValue );
1207  }
1208  }
1209  }
1210  mHistogramWidget->refresh();
1211  emit widgetChanged();
1212 }
1213 
1215 {
1216  mModel->addClass( mGraduatedSymbol.get() );
1217  mHistogramWidget->refresh();
1218  emit widgetChanged();
1219 
1220 }
1221 
1223 {
1224  QList<int> classIndexes = selectedClasses();
1225  mModel->deleteRows( classIndexes );
1226  mHistogramWidget->refresh();
1227  emit widgetChanged();
1228 }
1229 
1231 {
1232  mModel->removeAllRows();
1233  mHistogramWidget->refresh();
1234  emit widgetChanged();
1235 }
1236 
1238 {
1239  const QgsRangeList &ranges = mRenderer->ranges();
1240  bool ordered = true;
1241  for ( int i = 1; i < ranges.size(); ++i )
1242  {
1243  if ( ranges[i] < ranges[i - 1] )
1244  {
1245  ordered = false;
1246  break;
1247  }
1248  }
1249  return ordered;
1250 }
1251 
1253 {
1254  //If the checkbox controlling the link between boundaries was unchecked and we check it, we have to link the boundaries
1255  //This is done by updating all lower ranges to the upper value of the range above
1256  if ( linked )
1257  {
1258  if ( ! rowsOrdered() )
1259  {
1260  int result = QMessageBox::warning(
1261  this,
1262  tr( "Link Class Boundaries" ),
1263  tr( "Rows will be reordered before linking boundaries. Continue?" ),
1264  QMessageBox::Ok | QMessageBox::Cancel );
1265  if ( result != QMessageBox::Ok )
1266  {
1267  cbxLinkBoundaries->setChecked( false );
1268  return;
1269  }
1270  mRenderer->sortByValue();
1271  }
1272 
1273  // Ok to proceed
1274  for ( int i = 1; i < mRenderer->ranges().size(); ++i )
1275  {
1276  mRenderer->updateRangeLowerValue( i, mRenderer->ranges()[i - 1].upperValue() );
1277  }
1278  refreshSymbolView();
1279  }
1280 }
1281 
1283 {
1284  if ( item->column() == 2 )
1285  {
1286  QString label = item->text();
1287  int idx = item->row();
1288  mRenderer->updateRangeLabel( idx, label );
1289  }
1290 }
1291 
1293 {
1294  mRenderer->classificationMethod()->setLabelFormat( txtLegendFormat->text() );
1295  mRenderer->classificationMethod()->setLabelPrecision( spinPrecision->value() );
1296  mRenderer->classificationMethod()->setLabelTrimTrailingZeroes( cbxTrimTrailingZeroes->isChecked() );
1297  mRenderer->updateRangeLabels();
1298  mModel->updateLabels();
1299 }
1300 
1301 
1303 {
1304  QList<QgsSymbol *> selectedSymbols;
1305 
1306  QItemSelectionModel *m = viewGraduated->selectionModel();
1307  QModelIndexList selectedIndexes = m->selectedRows( 1 );
1308  if ( !selectedIndexes.isEmpty() )
1309  {
1310  const QgsRangeList &ranges = mRenderer->ranges();
1311  QModelIndexList::const_iterator indexIt = selectedIndexes.constBegin();
1312  for ( ; indexIt != selectedIndexes.constEnd(); ++indexIt )
1313  {
1314  QStringList list = m->model()->data( *indexIt ).toString().split( ' ' );
1315  if ( list.size() < 3 )
1316  {
1317  continue;
1318  }
1319  // Not strictly necessary because the range should have been sanitized already
1320  // after user input, but being permissive never hurts
1321  bool ok = false;
1322  double lowerBound = qgsPermissiveToDouble( list.at( 0 ), ok );
1323  if ( ! ok )
1324  lowerBound = 0.0;
1325  double upperBound = qgsPermissiveToDouble( list.at( 2 ), ok );
1326  if ( ! ok )
1327  upperBound = 0.0;
1328  QgsSymbol *s = findSymbolForRange( lowerBound, upperBound, ranges );
1329  if ( s )
1330  {
1331  selectedSymbols.append( s );
1332  }
1333  }
1334  }
1335  return selectedSymbols;
1336 }
1337 
1338 QgsSymbol *QgsGraduatedSymbolRendererWidget::findSymbolForRange( double lowerBound, double upperBound, const QgsRangeList &ranges ) const
1339 {
1340  int decimalPlaces = mRenderer->classificationMethod()->labelPrecision() + 2;
1341  if ( decimalPlaces < 0 )
1342  decimalPlaces = 0;
1343  double precision = 1.0 / std::pow( 10, decimalPlaces );
1344 
1345  for ( QgsRangeList::const_iterator it = ranges.begin(); it != ranges.end(); ++it )
1346  {
1347  if ( qgsDoubleNear( lowerBound, it->lowerValue(), precision ) && qgsDoubleNear( upperBound, it->upperValue(), precision ) )
1348  {
1349  return it->symbol();
1350  }
1351  }
1352  return nullptr;
1353 }
1354 
1356 {
1357  if ( mModel )
1358  {
1359  mModel->updateSymbology();
1360  }
1361  mHistogramWidget->refresh();
1362  emit widgetChanged();
1363 }
1364 
1366 {
1367  showSymbolLevelsDialog( mRenderer.get() );
1368 }
1369 
1371 {
1372  viewGraduated->selectionModel()->clear();
1373  if ( ! rowsOrdered() )
1374  {
1375  cbxLinkBoundaries->setChecked( false );
1376  }
1377  emit widgetChanged();
1378 }
1379 
1381 {
1382  emit widgetChanged();
1383 }
1384 
1386 {
1387  if ( !event )
1388  {
1389  return;
1390  }
1391 
1392  if ( event->key() == Qt::Key_C && event->modifiers() == Qt::ControlModifier )
1393  {
1394  mCopyBuffer.clear();
1395  mCopyBuffer = selectedRanges();
1396  }
1397  else if ( event->key() == Qt::Key_V && event->modifiers() == Qt::ControlModifier )
1398  {
1399  QgsRangeList::const_iterator rIt = mCopyBuffer.constBegin();
1400  for ( ; rIt != mCopyBuffer.constEnd(); ++rIt )
1401  {
1402  mModel->addClass( *rIt );
1403  }
1404  emit widgetChanged();
1405  }
1406 }
1407 
1408 void QgsGraduatedSymbolRendererWidget::selectionChanged( const QItemSelection &, const QItemSelection & )
1409 {
1410  const QgsRangeList ranges = selectedRanges();
1411  if ( !ranges.isEmpty() )
1412  {
1413  whileBlocking( btnChangeGraduatedSymbol )->setSymbol( ranges.at( 0 ).symbol()->clone() );
1414  }
1415  else if ( mRenderer->sourceSymbol() )
1416  {
1417  whileBlocking( btnChangeGraduatedSymbol )->setSymbol( mRenderer->sourceSymbol()->clone() );
1418  }
1419  btnChangeGraduatedSymbol->setDialogTitle( ranges.size() == 1 ? ranges.at( 0 ).label() : tr( "Symbol Settings" ) );
1420 }
1421 
1422 void QgsGraduatedSymbolRendererWidget::dataDefinedSizeLegend()
1423 {
1424  QgsMarkerSymbol *s = static_cast<QgsMarkerSymbol *>( mGraduatedSymbol.get() ); // this should be only enabled for marker symbols
1425  QgsDataDefinedSizeLegendWidget *panel = createDataDefinedSizeLegendWidget( s, mRenderer->dataDefinedSizeLegend() );
1426  if ( panel )
1427  {
1428  connect( panel, &QgsPanelWidget::widgetChanged, this, [ = ]
1429  {
1430  mRenderer->setDataDefinedSizeLegend( panel->dataDefinedSizeLegend() );
1431  emit widgetChanged();
1432  } );
1433  openPanel( panel ); // takes ownership of the panel
1434  }
1435 }
1436 
1437 void QgsGraduatedSymbolRendererWidget::changeGraduatedSymbol()
1438 {
1439  mGraduatedSymbol.reset( btnChangeGraduatedSymbol->symbol()->clone() );
1440  applyChangeToSymbol();
1441 }
1442 
1444 {
1445  std::unique_ptr< QgsSymbol > tempSymbol( QgsSymbolLayerUtils::symbolFromMimeData( QApplication::clipboard()->mimeData() ) );
1446  if ( !tempSymbol )
1447  return;
1448 
1449  const QModelIndexList selectedRows = viewGraduated->selectionModel()->selectedRows();
1450  for ( const QModelIndex &index : selectedRows )
1451  {
1452  if ( !index.isValid() )
1453  continue;
1454 
1455  const int row = index.row();
1456  if ( !mRenderer || mRenderer->ranges().size() <= row )
1457  continue;
1458 
1459  if ( mRenderer->ranges().at( row ).symbol()->type() != tempSymbol->type() )
1460  continue;
1461 
1462  std::unique_ptr< QgsSymbol > newCatSymbol( tempSymbol->clone() );
1463  if ( selectedRows.count() > 1 )
1464  {
1465  //if updating multiple ranges, retain the existing category colors
1466  newCatSymbol->setColor( mRenderer->ranges().at( row ).symbol()->color() );
1467  }
1468 
1469  mRenderer->updateRangeSymbol( row, newCatSymbol.release() );
1470  }
1471  emit widgetChanged();
1472 }
QgsSymbolSelectorDialog
Definition: qgssymbolselectordialog.h:264
QgsFieldProxyModel::Numeric
@ Numeric
All numeric fields.
Definition: qgsfieldproxymodel.h:45
QgsGraduatedSymbolRendererWidget::rangesDoubleClicked
void rangesDoubleClicked(const QModelIndex &idx)
Definition: qgsgraduatedsymbolrendererwidget.cpp:1121
qgsPermissiveToDouble
double qgsPermissiveToDouble(QString string, bool &ok)
Converts a string to a double in a permissive way, e.g., allowing for incorrect numbers of digits bet...
Definition: qgis.cpp:65
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:370
QgsGraduatedSymbolRendererWidget::refreshSymbolView
void refreshSymbolView() override
Definition: qgsgraduatedsymbolrendererwidget.cpp:1355
QgsColorRamp
Abstract base class for color ramps.
Definition: qgscolorramp.h:32
qgsexpressioncontextutils.h
QgsSymbolWidgetContext::mapCanvas
QgsMapCanvas * mapCanvas() const
Returns the map canvas associated with the widget.
Definition: qgssymbolwidgetcontext.cpp:54
QgsUnitTypes::RenderInches
@ RenderInches
Inches.
Definition: qgsunittypes.h:173
QgsGraduatedSymbolRendererWidget::selectedSymbols
QList< QgsSymbol * > selectedSymbols() override
Subclasses may provide the capability of changing multiple symbols at once by implementing the follow...
Definition: qgsgraduatedsymbolrendererwidget.cpp:1302
QgsClassificationMethod
QgsClassificationMethod is an abstract class for implementations of classification methods.
Definition: qgsclassificationmethod.h:88
QgsGraduatedSymbolRendererWidget::changeCurrentValue
void changeCurrentValue(QStandardItem *item)
Definition: qgsgraduatedsymbolrendererwidget.cpp:1282
QgsSymbolButton::changed
void changed()
Emitted when the symbol's settings are changed.
QgsLUDialog
Definition: qgsludialog.h:31
QgsGraduatedSymbolRendererWidget::applyChangeToSymbol
void applyChangeToSymbol()
Applies current symbol to selected ranges, or to all ranges if none is selected.
Definition: qgsgraduatedsymbolrendererwidget.cpp:930
QgsGradientColorRamp
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
Definition: qgscolorramp.h:151
qgsludialog.h
qgsclassificationstandarddeviation.h
QgsGraduatedHistogramWidget::rangesModified
void rangesModified(bool rangesAdded)
Emitted when the user modifies the graduated ranges using the histogram widget.
QgsGraduatedSymbolRendererWidget::connectUpdateHandlers
void connectUpdateHandlers()
Definition: qgsgraduatedsymbolrendererwidget.cpp:625
QgsRendererRange::label
QString label() const
Definition: qgsrendererrange.cpp:83
QgsExpressionContextUtils::globalScope
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
Definition: qgsexpressioncontextutils.cpp:34
QgsSymbol::defaultSymbol
static QgsSymbol * defaultSymbol(QgsWkbTypes::GeometryType geomType)
Returns a new default symbol for the specified geometry type.
Definition: qgssymbol.cpp:320
qgsmapcanvas.h
QgsFieldProxyModel::Date
@ Date
Date or datetime fields.
Definition: qgsfieldproxymodel.h:46
QgsGraduatedSymbolRendererWidget::rowsOrdered
bool rowsOrdered()
Definition: qgsgraduatedsymbolrendererwidget.cpp:1237
QgsPanelWidget::findParentPanel
static QgsPanelWidget * findParentPanel(QWidget *widget)
Traces through the parents of a widget to find if it is contained within a QgsPanelWidget widget.
Definition: qgspanelwidget.cpp:49
QgsRendererWidget::mLayer
QgsVectorLayer * mLayer
Definition: qgsrendererwidget.h:99
QgsGraduatedSymbolRendererWidget::selectedClasses
QList< int > selectedClasses()
Returns a list of indexes for the classes under selection.
Definition: qgsgraduatedsymbolrendererwidget.cpp:1092
QgsSymbolLayerUtils::symbolFromMimeData
static QgsSymbol * symbolFromMimeData(const QMimeData *data)
Attempts to parse mime data as a symbol.
Definition: qgssymbollayerutils.cpp:3062
QgsGraduatedSymbolRendererWidget::QgsGraduatedSymbolRendererWidget
QgsGraduatedSymbolRendererWidget(QgsVectorLayer *layer, QgsStyle *style, QgsFeatureRenderer *renderer)
Definition: qgsgraduatedsymbolrendererwidget.cpp:449
qgsgui.h
QgsClassificationMethod::symmetryAstride
bool symmetryAstride() const
Returns if the symmetric mode is astride if true, it will remove the symmetry point break so that the...
Definition: qgsclassificationmethod.h:194
QgsAbstractProcessingParameterWidgetWrapper::createWrappedWidget
QWidget * createWrappedWidget(QgsProcessingContext &context)
Creates and return a new wrapped widget which allows customization of the parameter's value.
Definition: qgsprocessingwidgetwrapper.cpp:131
QgsGraduatedSymbolRendererWidget::rowsMoved
void rowsMoved()
Definition: qgsgraduatedsymbolrendererwidget.cpp:1370
QgsSymbolSelectorWidget::symbol
QgsSymbol * symbol()
Returns the symbol that is currently active in the widget.
Definition: qgssymbolselectordialog.h:129
QgsGraduatedSymbolRendererWidget::deleteAllClasses
void deleteAllClasses()
Removes all classes from the classification.
Definition: qgsgraduatedsymbolrendererwidget.cpp:1230
QgsUnitTypes::RenderPoints
@ RenderPoints
Points (e.g., for font sizes)
Definition: qgsunittypes.h:172
qgssymbollayerutils.h
QgsProcessingGuiRegistry::createParameterWidgetWrapper
QgsAbstractProcessingParameterWidgetWrapper * createParameterWidgetWrapper(const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type)
Creates a new parameter widget wrapper for the given parameter.
Definition: qgsprocessingguiregistry.cpp:139
QgsClassificationMethodRegistry::method
QgsClassificationMethod * method(const QString &id)
Returns a new instance of the method for the given id.
Definition: qgsclassificationmethodregistry.cpp:53
QgsExpressionContextUtils::layerScope
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
Definition: qgsexpressioncontextutils.cpp:265
QgsSymbolWidgetContext
Contains settings which reflect the context in which a symbol (or renderer) widget is shown,...
Definition: qgssymbolwidgetcontext.h:36
QgsRendererRange::symbol
QgsSymbol * symbol() const
Definition: qgsrendererrange.cpp:78
QgsRendererRange
Definition: qgsrendererrange.h:37
QgsGraduatedSymbolRendererWidget::changeRange
void changeRange(int rangeIdx)
Definition: qgsgraduatedsymbolrendererwidget.cpp:1172
QgsExpressionContextUtils::mapSettingsScope
static QgsExpressionContextScope * mapSettingsScope(const QgsMapSettings &mapSettings)
Creates a new scope which contains variables and functions relating to a QgsMapSettings object.
Definition: qgsexpressioncontextutils.cpp:357
QgsProject::instance
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:468
QgsClassificationStandardDeviation::METHOD_ID
static const QString METHOD_ID
Definition: qgsclassificationstandarddeviation.h:41
QgsProcessingParameterDefinition
Base class for the definition of processing parameters.
Definition: qgsprocessingparameters.h:331
QgsUnitTypes::RenderMillimeters
@ RenderMillimeters
Millimeters.
Definition: qgsunittypes.h:168
QgsLUDialog::setLowerValue
void setLowerValue(const QString &val)
Definition: qgsludialog.cpp:37
qgsdatadefinedsizelegendwidget.h
QgsExpressionContextScopeGenerator
Abstract interface for generating an expression context scope.
Definition: qgsexpressioncontextscopegenerator.h:29
QgsRendererRange::lowerValue
double lowerValue() const
Definition: qgsrendererrange.cpp:68
QgsSymbolSelectorWidget
Symbol selector widget that can be used to select and build a symbol.
Definition: qgssymbolselectordialog.h:88
QgsProject::readEntry
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.
Definition: qgsproject.cpp:2526
QgsSymbol
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:64
field
const QgsField & field
Definition: qgsfield.h:456
QgsClassificationMethod::codeComplexity
int codeComplexity() const
Code complexity as the exponent in Big O notation.
Definition: qgsclassificationmethod.h:173
QgsDebugMsg
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QgsGraduatedSymbolRenderer::GraduatedColor
@ GraduatedColor
Definition: qgsgraduatedsymbolrenderer.h:377
QgsGraduatedSymbolRendererWidget::changeRangeSymbol
void changeRangeSymbol(int rangeIdx)
Definition: qgsgraduatedsymbolrendererwidget.cpp:1141
QgsSymbolSelectorWidget::setContext
void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the symbol widget is shown, e.g., the associated map canvas and expression ...
Definition: qgssymbolselectordialog.cpp:355
QgsAbstractProcessingParameterWidgetWrapper
A widget wrapper for Processing parameter value widgets.
Definition: qgsprocessingwidgetwrapper.h:267
QgsGraduatedSymbolRendererWidget::rangesClicked
void rangesClicked(const QModelIndex &idx)
Definition: qgsgraduatedsymbolrendererwidget.cpp:1129
QgsPanelWidget::dockMode
bool dockMode()
Returns the dock mode state.
Definition: qgspanelwidget.h:83
QgsGraduatedSymbolRendererWidget::renderer
QgsFeatureRenderer * renderer() override
Returns pointer to the renderer (no transfer of ownership)
Definition: qgsgraduatedsymbolrendererwidget.cpp:612
QgsClassificationMethodRegistry::methodNames
QMap< QString, QString > methodNames() const
Returns a map <name, id> of all registered methods.
Definition: qgsclassificationmethodregistry.cpp:59
QgsGraduatedSymbolRendererWidget::reapplyColorRamp
void reapplyColorRamp()
Definition: qgsgraduatedsymbolrendererwidget.cpp:1064
QgsGuiUtils::iconSize
QSize iconSize(bool dockableToolbar)
Returns the user-preferred size of a window's toolbar icons.
Definition: qgsguiutils.cpp:250
QgsProcessingGui::Standard
@ Standard
Standard algorithm dialog.
Definition: qgsprocessinggui.h:40
QgsClassificationMethod::parameterDefinitions
QgsProcessingParameterDefinitions parameterDefinitions() const
Returns the list of parameters.
Definition: qgsclassificationmethod.h:284
QgsAbstractProcessingParameterWidgetWrapper::createWrappedLabel
QLabel * createWrappedLabel()
Creates and returns a new label to accompany widgets created by the wrapper.
Definition: qgsprocessingwidgetwrapper.cpp:162
QgsGraduatedSymbolRendererWidget::selectedRanges
QgsRangeList selectedRanges()
Definition: qgsgraduatedsymbolrendererwidget.cpp:1108
QgsGraduatedSymbolRendererWidget::classifyGraduated
void classifyGraduated()
Definition: qgsgraduatedsymbolrendererwidget.cpp:982
qgsapplication.h
QgsClassificationMethod::symmetryPoint
double symmetryPoint() const
Returns the symmetry point for symmetric mode.
Definition: qgsclassificationmethod.h:188
QgsSymbolLayerUtils::symbolPreviewIcon
static QIcon symbolPreviewIcon(const QgsSymbol *symbol, QSize size, int padding=0, QgsLegendPatchShape *shape=nullptr)
Returns an icon preview for a color ramp.
Definition: qgssymbollayerutils.cpp:762
qgstemporalcontroller.h
QgsClassificationMethod::labelPrecision
int labelPrecision() const
Returns the precision for the formatting of the labels.
Definition: qgsclassificationmethod.h:211
QgsGraduatedSymbolRendererWidget::updateUiFromRenderer
void updateUiFromRenderer(bool updateCount=true)
Definition: qgsgraduatedsymbolrendererwidget.cpp:676
precision
int precision
Definition: qgswfsgetfeature.cpp:49
QgsExpressionContextUtils::projectScope
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
Definition: qgsexpressioncontextutils.cpp:222
QgsClassificationMethod::id
virtual QString id() const =0
The id of the method as saved in the project, must be unique in registry.
qgsgraduatedsymbolrendererwidget.h
QgsPanelWidget
Base class for any widget that can be shown as a inline panel.
Definition: qgspanelwidget.h:30
QgsRangeList
QList< QgsRendererRange > QgsRangeList
Definition: qgsrendererrange.h:98
whileBlocking
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:262
QgsClassificationMethod::setSymmetricMode
void setSymmetricMode(bool enabled, double symmetryPoint=0, bool symmetryAstride=false)
Defines if the symmetric mode is enables and configures its parameters.
Definition: qgsclassificationmethod.cpp:135
QgsClassificationMethod::MIN_PRECISION
static const int MIN_PRECISION
Definition: qgsclassificationmethod.h:300
QgsClassificationMethod::symmetricModeEnabled
bool symmetricModeEnabled() const
Returns if the symmetric mode is enabled.
Definition: qgsclassificationmethod.h:183
QgsProcessingContext
Contains information about the context in which a processing algorithm is executed.
Definition: qgsprocessingcontext.h:44
qgscolorramp.h
QgsMarkerSymbol
A marker symbol type, for rendering Point and MultiPoint geometries.
Definition: qgssymbol.h:931
qgsDoubleNear
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:315
QgsClassificationMethodRegistry::icon
QIcon icon(const QString &id) const
Returns the icon for a given method id.
Definition: qgsclassificationmethodregistry.cpp:67
QgsPanelWidget::panelAccepted
void panelAccepted(QgsPanelWidget *panel)
Emitted when the panel is accepted by the user.
QgsGraduatedSymbolRendererWidget::toggleBoundariesLink
void toggleBoundariesLink(bool linked)
Toggle the link between classes boundaries.
Definition: qgsgraduatedsymbolrendererwidget.cpp:1252
QgsGraduatedSymbolRenderer::GraduatedSize
@ GraduatedSize
Definition: qgsgraduatedsymbolrenderer.h:378
QgsProcessingParameterDefinition::name
QString name() const
Returns the name of the parameter.
Definition: qgsprocessingparameters.h:460
qgsprocessinggui.h
QgsClassificationMethod::MAX_PRECISION
static const int MAX_PRECISION
Definition: qgsclassificationmethod.h:299
QgsFieldExpressionWidget::fieldChanged
void fieldChanged(const QString &fieldName)
Emitted when the currently selected field changes.
QgsGraduatedSymbolRenderer
Definition: qgsgraduatedsymbolrenderer.h:36
QgsGraduatedSymbolRendererWidget::showSymbolLevels
void showSymbolLevels()
Definition: qgsgraduatedsymbolrendererwidget.cpp:1365
QgsGraduatedSymbolRendererWidget::keyPressEvent
void keyPressEvent(QKeyEvent *event) override
Definition: qgsgraduatedsymbolrendererwidget.cpp:1385
QgsGui::processingGuiRegistry
static QgsProcessingGuiRegistry * processingGuiRegistry()
Returns the global processing gui registry, used for registering the GUI behavior of processing algor...
Definition: qgsgui.cpp:104
qgsprocessingwidgetwrapper.h
QgsPanelWidget::widgetChanged
void widgetChanged()
Emitted when the widget state changes.
QgsClassificationMethod::labelTrimTrailingZeroes
bool labelTrimTrailingZeroes() const
Returns if the trailing 0 are trimmed in the label.
Definition: qgsclassificationmethod.h:215
QgsSymbolSelectorDialog::setContext
void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the symbol widget is shown, e.g., the associated map canvas and expression ...
Definition: qgssymbolselectordialog.cpp:810
QgsGraduatedSymbolRendererWidget::findSymbolForRange
QgsSymbol * findSymbolForRange(double lowerBound, double upperBound, const QgsRangeList &ranges) const
Definition: qgsgraduatedsymbolrendererwidget.cpp:1338
QgsRendererRange::upperValue
double upperValue() const
Definition: qgsrendererrange.cpp:73
QgsUnitSelectionWidget::changed
void changed()
QgsAbstractProcessingParameterWidgetWrapper::widgetValueHasChanged
void widgetValueHasChanged(QgsAbstractProcessingParameterWidgetWrapper *wrapper)
Emitted whenever the parameter value (as defined by the wrapped widget) is changed.
qgsclassificationequalinterval.h
QgsSymbol::Fill
@ Fill
Fill symbol.
Definition: qgssymbol.h:89
QgsApplication::classificationMethodRegistry
static QgsClassificationMethodRegistry * classificationMethodRegistry()
Returns the application's classification methods registry, used in graduated renderer.
Definition: qgsapplication.cpp:2233
QgsPanelWidget::setPanelTitle
void setPanelTitle(const QString &panelTitle)
Set the title of the panel when shown in the interface.
Definition: qgspanelwidget.h:44
QgsRendererRange::renderState
bool renderState() const
Definition: qgsrendererrange.cpp:108
QgsExpressionContextScope
Single scope for storing variables and functions for use within a QgsExpressionContext.
Definition: qgsexpressioncontext.h:112
QgsClassificationEqualInterval::METHOD_ID
static const QString METHOD_ID
Definition: qgsclassificationequalinterval.h:40
qgssymbolselectordialog.h
qgsstyle.h
QgsUnitTypes::RenderPixels
@ RenderPixels
Pixels.
Definition: qgsunittypes.h:170
QgsRendererWidget
Base class for renderer settings widgets.
Definition: qgsrendererwidget.h:45
QgsExpressionContext::appendScope
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
Definition: qgsexpressioncontext.cpp:490
qgsclassificationmethod.h
qgsvectorlayer.h
QgsAbstractProcessingParameterWidgetWrapper::setParameterValue
void setParameterValue(const QVariant &value, QgsProcessingContext &context)
Sets the current value for the parameter.
Definition: qgsprocessingwidgetwrapper.cpp:186
QgsGraduatedSymbolRendererWidget::modelDataChanged
void modelDataChanged()
Definition: qgsgraduatedsymbolrendererwidget.cpp:1380
QgsGraduatedSymbolRendererWidget::changeSelectedSymbols
void changeSelectedSymbols()
Definition: qgsgraduatedsymbolrendererwidget.cpp:1137
QgsSymbol::clone
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
QgsLUDialog::lowerValue
QString lowerValue() const
Definition: qgsludialog.cpp:27
QgsGraduatedSymbolRenderer::ranges
const QgsRangeList & ranges() const
Definition: qgsgraduatedsymbolrenderer.h:59
QgsClassificationMethod::labelFormat
QString labelFormat() const
Returns the format of the label for the classes.
Definition: qgsclassificationmethod.h:207
QgsClassificationMethod::setParameterValues
void setParameterValues(const QVariantMap &values)
Defines the values of the additional parameters.
Definition: qgsclassificationmethod.cpp:197
QgsFeatureRenderer
Definition: qgsrenderer.h:103
QgsGraduatedSymbolRendererWidget::labelFormatChanged
void labelFormatChanged()
Definition: qgsgraduatedsymbolrendererwidget.cpp:1292
QgsGraduatedSymbolRendererWidget::setContext
void setContext(const QgsSymbolWidgetContext &context) override
Sets the context in which the renderer widget is shown, e.g., the associated map canvas and expressio...
Definition: qgsgraduatedsymbolrendererwidget.cpp:617
QgsRendererWidget::contextMenuViewCategories
void contextMenuViewCategories(QPoint p)
Definition: qgsrendererwidget.cpp:78
QgsSymbol::setColor
void setColor(const QColor &color)
Sets the color for the symbol.
Definition: qgssymbol.cpp:504
QgsStyle
Definition: qgsstyle.h:160
QgsLUDialog::setUpperValue
void setUpperValue(const QString &val)
Definition: qgsludialog.cpp:42
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:387
QgsGraduatedSymbolRendererWidget::~QgsGraduatedSymbolRendererWidget
~QgsGraduatedSymbolRendererWidget() override
Definition: qgsgraduatedsymbolrendererwidget.cpp:606
QgsAbstractProcessingParameterWidgetWrapper::parameterValue
QVariant parameterValue() const
Returns the current value of the parameter.
Definition: qgsprocessingwidgetwrapper.cpp:201
QgsSymbol::Line
@ Line
Line symbol.
Definition: qgssymbol.h:88
QgsSymbol::Marker
@ Marker
Marker symbol.
Definition: qgssymbol.h:87
QgsGraduatedSymbolRendererWidget::refreshRanges
void refreshRanges(bool reset)
Refreshes the ranges for the renderer.
Definition: qgsgraduatedsymbolrendererwidget.cpp:899
QgsExpressionContextUtils::atlasScope
static QgsExpressionContextScope * atlasScope(const QgsLayoutAtlas *atlas)
Creates a new scope which contains variables and functions relating to a QgsLayoutAtlas.
Definition: qgsexpressioncontextutils.cpp:580
qgsprocessingcontext.h
QgsGraduatedSymbolRenderer::convertFromRenderer
static QgsGraduatedSymbolRenderer * convertFromRenderer(const QgsFeatureRenderer *renderer)
creates a QgsGraduatedSymbolRenderer from an existing renderer.
Definition: qgsgraduatedsymbolrenderer.cpp:1240
QgsGraduatedSymbolRendererWidget::create
static QgsRendererWidget * create(QgsVectorLayer *layer, QgsStyle *style, QgsFeatureRenderer *renderer)
Definition: qgsgraduatedsymbolrendererwidget.cpp:410
QgsLUDialog::upperValue
QString upperValue() const
Definition: qgsludialog.cpp:32
QgsGraduatedSymbolRendererWidget::addClass
void addClass()
Adds a class manually to the classification.
Definition: qgsgraduatedsymbolrendererwidget.cpp:1214
QgsSymbolWidgetContext::messageBar
QgsMessageBar * messageBar() const
Returns the message bar associated with the widget.
Definition: qgssymbolwidgetcontext.cpp:64
QgsGraduatedSymbolRendererWidget::disconnectUpdateHandlers
void disconnectUpdateHandlers()
Definition: qgsgraduatedsymbolrendererwidget.cpp:651
QgsGraduatedSymbolRendererWidget::reapplySizes
void reapplySizes()
Definition: qgsgraduatedsymbolrendererwidget.cpp:1075
qgsdatadefinedsizelegend.h
qgscolorrampbutton.h
QgsSymbol::Hybrid
@ Hybrid
Hybrid symbol.
Definition: qgssymbol.h:90
qgslogger.h
QgsUnitTypes::RenderUnitList
QList< QgsUnitTypes::RenderUnit > RenderUnitList
List of render units.
Definition: qgsunittypes.h:239
qgsprocessingguiregistry.h
QgsGraduatedSymbolRendererWidget::graduatedColumnChanged
void graduatedColumnChanged(const QString &field)
Definition: qgsgraduatedsymbolrendererwidget.cpp:785
QgsGuiUtils::scaleIconSize
int scaleIconSize(int standardSize)
Scales an icon size to compensate for display pixel density, making the icon size hi-dpi friendly,...
Definition: qgsguiutils.cpp:245
qgspanelwidget.h
QgsProcessingParameterDefinition::defaultValue
QVariant defaultValue() const
Returns the default value for the parameter.
Definition: qgsprocessingparameters.h:509
QgsMapSettings
The QgsMapSettings class contains configuration for rendering of the map.
Definition: qgsmapsettings.h:88
QgsAbstractProcessingParameterWidgetWrapper::parameterDefinition
const QgsProcessingParameterDefinition * parameterDefinition() const
Returns the parameter definition associated with this wrapper.
Definition: qgsprocessingwidgetwrapper.cpp:181
QgsVectorLayer::geometryType
Q_INVOKABLE QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
Definition: qgsvectorlayer.cpp:659
qgsclassificationmethodregistry.h
QgsFieldExpressionWidget
The QgsFieldExpressionWidget class reates a widget to choose fields and edit expressions It contains ...
Definition: qgsfieldexpressionwidget.h:47
QgsRendererWidget::setContext
virtual void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the renderer widget is shown, e.g., the associated map canvas and expressio...
Definition: qgsrendererwidget.cpp:337
qgssymbol.h
QgsClassificationMethod::parameterValues
QVariantMap parameterValues() const
Returns the values of the processing parameters.
Definition: qgsclassificationmethod.h:297
QgsUnitTypes::RenderMapUnits
@ RenderMapUnits
Map units.
Definition: qgsunittypes.h:169
QgsHistogramWidget::setSourceFieldExp
void setSourceFieldExp(const QString &fieldOrExp)
Sets the source field or expression to use for values in the histogram.
Definition: qgshistogramwidget.cpp:162
qgsproject.h
QgsTemporaryCursorOverride
Temporarily sets a cursor override for the QApplication for the lifetime of the object.
Definition: qgsguiutils.h:222
QgsClassificationMethod::symmetricModeAvailable
bool symmetricModeAvailable() const
Returns if the method supports symmetric calculation.
Definition: qgsclassificationmethod.h:178
QgsProxyStyle
A QProxyStyle subclass which correctly sets the base style to match the QGIS application style,...
Definition: qgsproxystyle.h:31
QgsGraduatedSymbolRendererWidget::pasteSymbolToSelection
void pasteSymbolToSelection() override
Definition: qgsgraduatedsymbolrendererwidget.cpp:1443
QgsColorRampButton::colorRampChanged
void colorRampChanged()
Emitted whenever a new color ramp is set for the button.
qgsexpressionbuilderdialog.h
QgsGraduatedSymbolRendererWidget::deleteClasses
void deleteClasses()
Removes currently selected classes.
Definition: qgsgraduatedsymbolrendererwidget.cpp:1222