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