57#include <QStandardItem>
58#include <QStandardItemModel>
62#include "moc_qgsgraduatedsymbolrendererwidget.cpp"
64using namespace Qt::StringLiterals;
70QgsGraduatedSymbolRendererModel::QgsGraduatedSymbolRendererModel( QObject *parent, QScreen *screen )
71 : QAbstractItemModel( parent )
72 , mMimeFormat( u
"application/x-qgsgraduatedsymbolrendererv2model"_s )
81 if ( !mRenderer->ranges().isEmpty() )
83 beginRemoveRows( QModelIndex(), 0, mRenderer->ranges().size() - 1 );
94 if ( !renderer->
ranges().isEmpty() )
96 beginInsertRows( QModelIndex(), 0, renderer->
ranges().size() - 1 );
102 mRenderer = renderer;
107void QgsGraduatedSymbolRendererModel::addClass(
QgsSymbol *symbol )
111 int idx = mRenderer->ranges().size();
112 beginInsertRows( QModelIndex(), idx, idx );
113 mRenderer->addClass( symbol );
117void QgsGraduatedSymbolRendererModel::addClass(
const QgsRendererRange &range )
123 int idx = mRenderer->ranges().size();
124 beginInsertRows( QModelIndex(), idx, idx );
125 mRenderer->addClass( range );
129QgsRendererRange QgsGraduatedSymbolRendererModel::rendererRange(
const QModelIndex &index )
131 if ( !index.isValid() || !mRenderer || mRenderer->ranges().size() <= index.row() )
136 return mRenderer->ranges().value( index.row() );
139Qt::ItemFlags QgsGraduatedSymbolRendererModel::flags(
const QModelIndex &index )
const
142 if ( !index.isValid() )
144 return Qt::ItemIsDropEnabled;
147 Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsUserCheckable;
149 if ( index.column() == 2 )
151 flags |= Qt::ItemIsEditable;
157Qt::DropActions QgsGraduatedSymbolRendererModel::supportedDropActions()
const
159 return Qt::MoveAction;
162QVariant QgsGraduatedSymbolRendererModel::data(
const QModelIndex &index,
int role )
const
164 if ( !index.isValid() || !mRenderer )
169 if ( role == Qt::CheckStateRole && index.column() == 0 )
171 return range.
renderState() ? Qt::Checked : Qt::Unchecked;
173 else if ( role == Qt::DisplayRole || role == Qt::ToolTipRole )
175 switch ( index.column() )
179 int decimalPlaces = mRenderer->classificationMethod()->labelPrecision() + 2;
180 if ( decimalPlaces < 0 )
182 return QString( QLocale().toString( range.
lowerValue(),
'f', decimalPlaces ) +
" - " + QLocale().toString( range.
upperValue(),
'f', decimalPlaces ) );
185 return range.
label();
190 else if ( role == Qt::DecorationRole && index.column() == 0 && range.
symbol() )
195 else if ( role == Qt::TextAlignmentRole )
197 return ( index.column() == 0 ) ?
static_cast<Qt::Alignment::Int
>( Qt::AlignHCenter ) : static_cast<Qt::Alignment::Int>( Qt::AlignLeft );
199 else if ( role == Qt::EditRole )
201 switch ( index.column() )
205 return range.
label();
214bool QgsGraduatedSymbolRendererModel::setData(
const QModelIndex &index,
const QVariant &value,
int role )
216 if ( !index.isValid() )
219 if ( index.column() == 0 && role == Qt::CheckStateRole )
221 mRenderer->updateRangeRenderState( index.row(), value == Qt::Checked );
222 emit dataChanged( index, index );
226 if ( role != Qt::EditRole )
229 switch ( index.column() )
234 mRenderer->updateRangeLabel( index.row(), value.toString() );
240 emit dataChanged( index, index );
244QVariant QgsGraduatedSymbolRendererModel::headerData(
int section, Qt::Orientation orientation,
int role )
const
246 if ( orientation == Qt::Horizontal && role == Qt::DisplayRole && section >= 0 && section < 3 )
249 lst << tr(
"Symbol" ) << tr(
"Values" ) << tr(
"Legend" );
250 return lst.value( section );
255int QgsGraduatedSymbolRendererModel::rowCount(
const QModelIndex &parent )
const
257 if ( parent.isValid() || !mRenderer )
261 return mRenderer->ranges().size();
264int QgsGraduatedSymbolRendererModel::columnCount(
const QModelIndex &index )
const
270QModelIndex QgsGraduatedSymbolRendererModel::index(
int row,
int column,
const QModelIndex &parent )
const
272 if ( hasIndex( row, column, parent ) )
274 return createIndex( row, column );
276 return QModelIndex();
279QModelIndex QgsGraduatedSymbolRendererModel::parent(
const QModelIndex &index )
const
282 return QModelIndex();
285QStringList QgsGraduatedSymbolRendererModel::mimeTypes()
const
288 types << mMimeFormat;
292QMimeData *QgsGraduatedSymbolRendererModel::mimeData(
const QModelIndexList &indexes )
const
294 QMimeData *mimeData =
new QMimeData();
295 QByteArray encodedData;
297 QDataStream stream( &encodedData, QIODevice::WriteOnly );
300 const auto constIndexes = indexes;
301 for (
const QModelIndex &index : constIndexes )
303 if ( !index.isValid() || index.column() != 0 )
306 stream << index.row();
308 mimeData->setData( mMimeFormat, encodedData );
312bool QgsGraduatedSymbolRendererModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
int row,
int column,
const QModelIndex &parent )
316 if ( action != Qt::MoveAction )
319 if ( !data->hasFormat( mMimeFormat ) )
322 QByteArray encodedData = data->data( mMimeFormat );
323 QDataStream stream( &encodedData, QIODevice::ReadOnly );
326 while ( !stream.atEnd() )
334 std::sort( rows.begin(), rows.end() );
341 to = mRenderer->ranges().size();
342 for (
int i = rows.size() - 1; i >= 0; i-- )
349 mRenderer->moveClass( rows[i], t );
351 for (
int j = 0; j < i; j++ )
353 if ( to < rows[j] && rows[i] > rows[j] )
360 emit dataChanged( createIndex( 0, 0 ), createIndex( mRenderer->ranges().size(), 0 ) );
365void QgsGraduatedSymbolRendererModel::deleteRows( QList<int> rows )
367 for (
int i = rows.size() - 1; i >= 0; i-- )
369 beginRemoveRows( QModelIndex(), rows[i], rows[i] );
370 mRenderer->deleteClass( rows[i] );
375void QgsGraduatedSymbolRendererModel::removeAllRows()
377 beginRemoveRows( QModelIndex(), 0, mRenderer->ranges().size() - 1 );
378 mRenderer->deleteAllClasses();
382void QgsGraduatedSymbolRendererModel::sort(
int column, Qt::SortOrder order )
390 mRenderer->sortByValue( order );
392 else if ( column == 2 )
394 mRenderer->sortByLabel( order );
397 emit dataChanged( createIndex( 0, 0 ), createIndex( mRenderer->ranges().size(), 0 ) );
400void QgsGraduatedSymbolRendererModel::updateSymbology()
402 emit dataChanged( createIndex( 0, 0 ), createIndex( mRenderer->ranges().size(), 0 ) );
405void QgsGraduatedSymbolRendererModel::updateLabels()
407 emit dataChanged( createIndex( 0, 2 ), createIndex( mRenderer->ranges().size(), 2 ) );
411QgsGraduatedSymbolRendererViewStyle::QgsGraduatedSymbolRendererViewStyle( QWidget *parent )
415void QgsGraduatedSymbolRendererViewStyle::drawPrimitive( PrimitiveElement element,
const QStyleOption *option, QPainter *painter,
const QWidget *widget )
const
417 if ( element == QStyle::PE_IndicatorItemViewItemDrop && !option->rect.isNull() )
419 QStyleOption opt( *option );
420 opt.rect.setLeft( 0 );
422 opt.rect.setHeight( 0 );
424 opt.rect.setRight( widget->width() );
425 QProxyStyle::drawPrimitive( element, &opt, painter, widget );
428 QProxyStyle::drawPrimitive( element, option, painter, widget );
444 if (
auto *lMapCanvas =
mContext.mapCanvas() )
446 expContext = lMapCanvas->createExpressionContext();
460 const auto constAdditionalExpressionContextScopes =
mContext.additionalExpressionContextScopes();
480 mRenderer = std::make_unique<QgsGraduatedSymbolRenderer>( QString(),
QgsRangeList() );
482 renderer->copyRendererData( mRenderer.get() );
489 cboSymmetryPoint->setEditable(
true );
490 cboSymmetryPoint->setValidator( mSymmetryPointValidator );
493 for ( QMap<QString, QString>::const_iterator it = methods.constBegin(); it != methods.constEnd(); ++it )
496 cboGraduatedMode->addItem( icon, it.key(), it.value() );
499 connect( methodComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, &QgsGraduatedSymbolRendererWidget::methodComboBox_currentIndexChanged );
500 this->layout()->setContentsMargins( 0, 0, 0, 0 );
502 mModel =
new QgsGraduatedSymbolRendererModel(
this, screen() );
505 mExpressionWidget->setLayer(
mLayer );
507 btnChangeGraduatedSymbol->setLayer(
mLayer );
508 btnChangeGraduatedSymbol->registerExpressionContextGenerator(
this );
510 mSizeUnitWidget->setUnits(
521 spinPrecision->setClearValue( 4 );
523 spinGraduatedClasses->setShowClearButton(
false );
525 btnColorRamp->setShowRandomColorRamp(
true );
528 std::unique_ptr<QgsColorRamp> colorRamp(
QgsProject::instance()->styleSettings()->defaultColorRamp() );
531 btnColorRamp->setColorRamp( colorRamp.get() );
536 btnColorRamp->setColorRamp( ramp );
541 viewGraduated->setStyle(
new QgsGraduatedSymbolRendererViewStyle( viewGraduated ) );
544 if ( mGraduatedSymbol )
546 btnChangeGraduatedSymbol->setSymbolType( mGraduatedSymbol->type() );
547 btnChangeGraduatedSymbol->setSymbol( mGraduatedSymbol->clone() );
549 methodComboBox->blockSignals(
true );
550 methodComboBox->addItem( tr(
"Color" ), ColorMode );
551 switch ( mGraduatedSymbol->type() )
555 methodComboBox->addItem( tr(
"Size" ), SizeMode );
556 minSizeSpinBox->setValue( 1 );
557 maxSizeSpinBox->setValue( 8 );
562 methodComboBox->addItem( tr(
"Size" ), SizeMode );
563 minSizeSpinBox->setValue( .1 );
564 maxSizeSpinBox->setValue( 2 );
570 methodComboBox->hide();
577 methodComboBox->blockSignals(
false );
586 connect( btnChangeGraduatedSymbol, &
QgsSymbolButton::changed,
this, &QgsGraduatedSymbolRendererWidget::changeGraduatedSymbol );
593 connect( cboGraduatedMode, qOverload<int>( &QComboBox::currentIndexChanged ),
this, &QgsGraduatedSymbolRendererWidget::updateMethodParameters );
596 updateMethodParameters();
604 mGroupBoxSymmetric->setCollapsed(
true );
607 QMenu *advMenu =
new QMenu(
this );
612 QAction *actionDdsLegend = advMenu->addAction( tr(
"Data-defined Size Legend…" ) );
614 connect( actionDdsLegend, &QAction::triggered,
this, &QgsGraduatedSymbolRendererWidget::dataDefinedSizeLegend );
617 btnAdvanced->setMenu( advMenu );
619 mHistogramWidget->setLayer(
mLayer );
620 mHistogramWidget->setRenderer( mRenderer.get() );
624 mExpressionWidget->registerExpressionContextGenerator(
this );
626 mUpdateTimer.setSingleShot(
true );
627 mUpdateTimer.connect( &mUpdateTimer, &QTimer::timeout,
this, &QgsGraduatedSymbolRendererWidget::classifyGraduatedImpl );
630void QgsGraduatedSymbolRendererWidget::mSizeUnitWidget_changed()
632 if ( !mGraduatedSymbol )
634 mGraduatedSymbol->setOutputUnit( mSizeUnitWidget->unit() );
635 mGraduatedSymbol->setMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
636 mRenderer->updateSymbols( mGraduatedSymbol.get() );
643 mParameterWidgetWrappers.clear();
648 return mRenderer.get();
654 btnChangeGraduatedSymbol->setMapCanvas(
context.mapCanvas() );
655 btnChangeGraduatedSymbol->setMessageBar(
context.messageBar() );
660 delete mActionLevels;
661 mActionLevels =
nullptr;
682 connect( cboSymmetryPoint->lineEdit(), &QLineEdit::editingFinished,
this, &QgsGraduatedSymbolRendererWidget::symmetryPointEditingFinished );
684 for (
const auto &ppww : std::as_const( mParameterWidgetWrappers ) )
708 disconnect( cboSymmetryPoint->lineEdit(), &QLineEdit::editingFinished,
this, &QgsGraduatedSymbolRendererWidget::symmetryPointEditingFinished );
710 for (
const auto &ppww : std::as_const( mParameterWidgetWrappers ) )
726 int precision = spinPrecision->value() + 2;
727 while ( cboSymmetryPoint->count() )
728 cboSymmetryPoint->removeItem( 0 );
729 for (
int i = 0; i < ranges.count() - 1; i++ )
730 cboSymmetryPoint->addItem( QLocale().toString( ranges.at( i ).upperValue(),
'f', precision ), ranges.at( i ).upperValue() );
734 int idx = cboGraduatedMode->findData( method->
id() );
736 cboGraduatedMode->setCurrentIndex( idx );
742 cboSymmetryPoint->setItemText( cboSymmetryPoint->currentIndex(), QLocale().toString( method->
symmetryPoint(),
'f', method->
labelPrecision() + 2 ) );
749 for (
const auto &ppww : std::as_const( mParameterWidgetWrappers ) )
753 ppww->setParameterValue( value,
context );
758 int nclasses = ranges.count();
761 spinGraduatedClasses->setValue( ranges.count() );
769 spinGraduatedClasses->setEnabled(
true );
773 QString attrName = mRenderer->classAttribute();
774 mExpressionWidget->setField( attrName );
775 mHistogramWidget->setSourceFieldExp( attrName );
778 if ( mRenderer->sourceSymbol() )
780 mGraduatedSymbol.reset( mRenderer->sourceSymbol()->clone() );
781 whileBlocking( btnChangeGraduatedSymbol )->setSymbol( mGraduatedSymbol->clone() );
784 mModel->setRenderer( mRenderer.get() );
785 viewGraduated->setModel( mModel );
787 connect( viewGraduated->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsGraduatedSymbolRendererWidget::selectionChanged );
789 if ( mGraduatedSymbol )
791 mSizeUnitWidget->blockSignals(
true );
792 mSizeUnitWidget->setUnit( mGraduatedSymbol->outputUnit() );
793 mSizeUnitWidget->setMapUnitScale( mGraduatedSymbol->mapUnitScale() );
794 mSizeUnitWidget->blockSignals(
false );
798 methodComboBox->blockSignals(
true );
799 switch ( mRenderer->graduatedMethod() )
803 methodComboBox->setCurrentIndex( methodComboBox->findData( ColorMode ) );
804 if ( mRenderer->sourceColorRamp() )
806 btnColorRamp->setColorRamp( mRenderer->sourceColorRamp() );
812 methodComboBox->setCurrentIndex( methodComboBox->findData( SizeMode ) );
813 if ( !mRenderer->ranges().isEmpty() )
815 minSizeSpinBox->setValue( mRenderer->minSymbolSize() );
816 maxSizeSpinBox->setValue( mRenderer->maxSymbolSize() );
821 toggleMethodWidgets(
static_cast<MethodMode
>( methodComboBox->currentData().toInt() ) );
822 methodComboBox->blockSignals(
false );
824 viewGraduated->resizeColumnToContents( 0 );
825 viewGraduated->resizeColumnToContents( 1 );
826 viewGraduated->resizeColumnToContents( 2 );
828 mHistogramWidget->refresh();
838 mRenderer->setClassAttribute( field );
842void QgsGraduatedSymbolRendererWidget::methodComboBox_currentIndexChanged(
int )
844 const MethodMode newMethod =
static_cast<MethodMode
>( methodComboBox->currentData().toInt() );
845 toggleMethodWidgets( newMethod );
855 QMessageBox::critical(
this, tr(
"Select Method" ), tr(
"No color ramp defined." ) );
858 mRenderer->setSourceColorRamp( ramp );
865 lblColorRamp->setVisible(
false );
866 btnColorRamp->setVisible(
false );
867 lblSize->setVisible(
true );
868 minSizeSpinBox->setVisible(
true );
869 lblSize->setVisible(
true );
870 maxSizeSpinBox->setVisible(
true );
871 mSizeUnitWidget->setVisible(
true );
880void QgsGraduatedSymbolRendererWidget::updateMethodParameters()
882 clearParameterWidgets();
884 const QString methodId = cboGraduatedMode->currentData().toString();
886 Q_ASSERT( mClassificationMethod.get() );
891 for (
const QgsProcessingParameterDefinition *def : mClassificationMethod->parameterDefinitions() )
896 QVariant value = mClassificationMethod->parameterValues().value( def->name(), def->defaultValueForGui() );
901 mParameterWidgetWrappers.push_back( std::unique_ptr<QgsAbstractProcessingParameterWidgetWrapper>( ppww ) );
907void QgsGraduatedSymbolRendererWidget::toggleMethodWidgets( MethodMode mode )
913 lblColorRamp->setVisible(
true );
914 btnColorRamp->setVisible(
true );
915 lblSize->setVisible(
false );
916 minSizeSpinBox->setVisible(
false );
917 lblSizeTo->setVisible(
false );
918 maxSizeSpinBox->setVisible(
false );
919 mSizeUnitWidget->setVisible(
false );
925 lblColorRamp->setVisible(
false );
926 btnColorRamp->setVisible(
false );
927 lblSize->setVisible(
true );
928 minSizeSpinBox->setVisible(
true );
929 lblSizeTo->setVisible(
true );
930 maxSizeSpinBox->setVisible(
true );
931 mSizeUnitWidget->setVisible(
true );
937void QgsGraduatedSymbolRendererWidget::clearParameterWidgets()
939 while ( mParametersLayout->rowCount() )
941 QFormLayout::TakeRowResult row = mParametersLayout->takeRow( 0 );
942 for ( QLayoutItem *item : { row.labelItem, row.fieldItem } )
945 QWidget *widget = item->widget();
951 mParameterWidgetWrappers.clear();
959 mModel->updateSymbology();
962 spinGraduatedClasses->setValue( mRenderer->ranges().count() );
975 mRenderer->setLegendSymbolItem( legendSymbol.ruleKey(), sym->
clone() );
978 mRenderer->setUsingSymbolLevels( enabled );
979 mModel->updateSymbology();
985 mGraduatedSymbol.reset( widget->
symbol()->
clone() );
992 mSizeUnitWidget->blockSignals(
true );
993 mSizeUnitWidget->setUnit( mGraduatedSymbol->outputUnit() );
994 mSizeUnitWidget->setMapUnitScale( mGraduatedSymbol->mapUnitScale() );
995 mSizeUnitWidget->blockSignals(
false );
997 QItemSelectionModel *m = viewGraduated->selectionModel();
998 QModelIndexList selectedIndexes = m->selectedRows( 1 );
999 if ( !selectedIndexes.isEmpty() )
1001 const auto constSelectedIndexes = selectedIndexes;
1002 for (
const QModelIndex &idx : constSelectedIndexes )
1004 if ( idx.isValid() )
1006 int rangeIdx = idx.row();
1008 if ( selectedIndexes.count() > 1 )
1011 newRangeSymbol->
setColor( mRenderer->ranges().at( rangeIdx ).symbol()->color() );
1013 mRenderer->updateRangeSymbol( rangeIdx, newRangeSymbol );
1019 mRenderer->updateSymbols( mGraduatedSymbol.get() );
1026void QgsGraduatedSymbolRendererWidget::symmetryPointEditingFinished()
1028 const QString text = cboSymmetryPoint->lineEdit()->text();
1029 int index = cboSymmetryPoint->findText( text );
1032 cboSymmetryPoint->setCurrentIndex( index );
1036 cboSymmetryPoint->setItemText( cboSymmetryPoint->currentIndex(), text );
1044 mUpdateTimer.start( 500 );
1047void QgsGraduatedSymbolRendererWidget::classifyGraduatedImpl()
1049 if ( mBlockUpdates || !mClassificationMethod )
1053 QString attrName = mExpressionWidget->currentField();
1054 int nclasses = spinGraduatedClasses->value();
1062 double minimum = minVal.toDouble();
1063 double maximum = maxVal.toDouble();
1064 mSymmetryPointValidator->
setBottom( minimum );
1065 mSymmetryPointValidator->
setTop( maximum );
1066 mSymmetryPointValidator->
setMaxDecimals( spinPrecision->value() );
1073 if ( currentValue < ( minimum + ( maximum - minimum ) / 100. ) || currentValue > ( maximum - ( maximum - minimum ) / 100. ) )
1074 cboSymmetryPoint->setItemText( cboSymmetryPoint->currentIndex(), QLocale().toString( minimum + ( maximum - minimum ) / 2.,
'f', mClassificationMethod->labelPrecision() + 2 ) );
1077 if ( mGroupBoxSymmetric->isChecked() )
1080 bool astride = cbxAstride->isChecked();
1081 mClassificationMethod->setSymmetricMode(
true, symmetryPoint, astride );
1084 QVariantMap parameterValues;
1085 for (
const auto &ppww : std::as_const( mParameterWidgetWrappers ) )
1087 mClassificationMethod->setParameterValues( parameterValues );
1090 mRenderer->setClassificationMethod( mClassificationMethod->clone().release() );
1093 mRenderer->setClassAttribute( attrName );
1097 if ( mRenderer->classificationMethod()->codeComplexity() > 1 &&
mLayer->featureCount() > 50000 )
1099 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 ) )
1105 if ( methodComboBox->currentData() == ColorMode )
1107 std::unique_ptr<QgsColorRamp> ramp( btnColorRamp->colorRamp() );
1110 QMessageBox::critical(
this, tr(
"Apply Classification" ), tr(
"No color ramp defined." ) );
1113 mRenderer->setSourceColorRamp( ramp.release() );
1117 mRenderer->setSourceColorRamp(
nullptr );
1121 mRenderer->updateClasses(
mLayer, nclasses, error );
1123 if ( !error.isEmpty() )
1124 QMessageBox::critical(
this, tr(
"Apply Classification" ), error );
1126 if ( methodComboBox->currentData() == SizeMode )
1127 mRenderer->setSymbolSizes( minSizeSpinBox->value(), maxSizeSpinBox->value() );
1129 mRenderer->calculateLabelPrecision();
1137 std::unique_ptr<QgsColorRamp> ramp( btnColorRamp->colorRamp() );
1141 mRenderer->updateColorRamp( ramp.release() );
1142 mRenderer->updateSymbols( mGraduatedSymbol.get() );
1148 mRenderer->setSymbolSizes( minSizeSpinBox->value(), maxSizeSpinBox->value() );
1149 mRenderer->updateSymbols( mGraduatedSymbol.get() );
1154int QgsRendererPropertiesDialog::currentRangeRow()
1156 QModelIndex idx = viewGraduated->selectionModel()->currentIndex();
1157 if ( !idx.isValid() )
1166 QModelIndexList selectedRows = viewGraduated->selectionModel()->selectedRows();
1168 const auto constSelectedRows = selectedRows;
1169 for (
const QModelIndex &r : constSelectedRows )
1173 rows.append( r.row() );
1182 QModelIndexList selectedRows = viewGraduated->selectionModel()->selectedRows();
1183 QModelIndexList::const_iterator sIt = selectedRows.constBegin();
1185 for ( ; sIt != selectedRows.constEnd(); ++sIt )
1194 if ( idx.isValid() && idx.column() == 0 )
1196 if ( idx.isValid() && idx.column() == 1 )
1202 if ( !idx.isValid() )
1205 mRowSelected = idx.row();
1215 std::unique_ptr<QgsSymbol> newSymbol( range.
symbol()->
clone() );
1229 if ( !dlg.exec() || !newSymbol )
1234 mGraduatedSymbol = std::move( newSymbol );
1235 whileBlocking( btnChangeGraduatedSymbol )->setSymbol( mGraduatedSymbol->clone() );
1247 int decimalPlaces = mRenderer->classificationMethod()->labelPrecision() + 2;
1248 if ( decimalPlaces < 0 )
1253 if ( dialog.exec() == QDialog::Accepted )
1259 if ( cbxLinkBoundaries->isChecked() )
1263 mRenderer->updateRangeUpperValue( rangeIdx - 1, dialog.
lowerValueDouble() );
1266 if ( rangeIdx < mRenderer->ranges().size() - 1 )
1268 mRenderer->updateRangeLowerValue( rangeIdx + 1, dialog.
upperValueDouble() );
1272 mHistogramWidget->refresh();
1278 mModel->addClass( mGraduatedSymbol.get() );
1279 mHistogramWidget->refresh();
1286 mModel->deleteRows( classIndexes );
1287 mHistogramWidget->refresh();
1293 mModel->removeAllRows();
1294 mHistogramWidget->refresh();
1301 bool ordered =
true;
1302 for (
int i = 1; i < ranges.size(); ++i )
1304 if ( ranges[i] < ranges[i - 1] )
1321 int result = QMessageBox::warning(
1323 tr(
"Link Class Boundaries" ),
1324 tr(
"Rows will be reordered before linking boundaries. Continue?" ),
1325 QMessageBox::Ok | QMessageBox::Cancel
1327 if ( result != QMessageBox::Ok )
1329 cbxLinkBoundaries->setChecked(
false );
1332 mRenderer->sortByValue();
1336 for (
int i = 1; i < mRenderer->ranges().size(); ++i )
1338 mRenderer->updateRangeLowerValue( i, mRenderer->ranges()[i - 1].upperValue() );
1346 if ( item->column() == 2 )
1348 QString label = item->text();
1349 int idx = item->row();
1350 mRenderer->updateRangeLabel( idx, label );
1356 mRenderer->classificationMethod()->setLabelFormat( txtLegendFormat->text() );
1357 mRenderer->classificationMethod()->setLabelPrecision( spinPrecision->value() );
1358 mRenderer->classificationMethod()->setLabelTrimTrailingZeroes( cbxTrimTrailingZeroes->isChecked() );
1359 mRenderer->updateRangeLabels();
1360 mModel->updateLabels();
1368 QItemSelectionModel *m = viewGraduated->selectionModel();
1369 QModelIndexList selectedIndexes = m->selectedRows( 1 );
1370 if ( !selectedIndexes.isEmpty() )
1373 QModelIndexList::const_iterator indexIt = selectedIndexes.constBegin();
1374 for ( ; indexIt != selectedIndexes.constEnd(); ++indexIt )
1376 QStringList list = m->model()->data( *indexIt ).toString().split(
' ' );
1377 if ( list.size() < 3 )
1402 int decimalPlaces = mRenderer->classificationMethod()->labelPrecision() + 2;
1403 if ( decimalPlaces < 0 )
1405 double precision = 1.0 / std::pow( 10, decimalPlaces );
1407 for ( QgsRangeList::const_iterator it = ranges.begin(); it != ranges.end(); ++it )
1411 return it->symbol();
1421 mModel->updateSymbology();
1423 mHistogramWidget->refresh();
1434 viewGraduated->selectionModel()->clear();
1437 cbxLinkBoundaries->setChecked(
false );
1454 if ( event->key() == Qt::Key_C && event->modifiers() == Qt::ControlModifier )
1456 mCopyBuffer.clear();
1459 else if ( event->key() == Qt::Key_V && event->modifiers() == Qt::ControlModifier )
1461 QgsRangeList::iterator rIt = mCopyBuffer.begin();
1462 for ( ; rIt != mCopyBuffer.end(); ++rIt )
1464 rIt->mUuid = QUuid::createUuid().toString();
1465 mModel->addClass( *rIt );
1471void QgsGraduatedSymbolRendererWidget::selectionChanged(
const QItemSelection &,
const QItemSelection & )
1474 if ( !ranges.isEmpty() )
1476 whileBlocking( btnChangeGraduatedSymbol )->setSymbol( ranges.at( 0 ).symbol()->clone() );
1478 else if ( mRenderer->sourceSymbol() )
1480 whileBlocking( btnChangeGraduatedSymbol )->setSymbol( mRenderer->sourceSymbol()->clone() );
1482 btnChangeGraduatedSymbol->setDialogTitle( ranges.size() == 1 ? ranges.at( 0 ).label() : tr(
"Symbol Settings" ) );
1485void QgsGraduatedSymbolRendererWidget::dataDefinedSizeLegend()
1487 QgsMarkerSymbol *s =
static_cast<QgsMarkerSymbol *
>( mGraduatedSymbol.get() );
1499void QgsGraduatedSymbolRendererWidget::changeGraduatedSymbol()
1501 mGraduatedSymbol.reset( btnChangeGraduatedSymbol->symbol()->clone() );
1511 const QModelIndexList selectedRows = viewGraduated->selectionModel()->selectedRows();
1512 for (
const QModelIndex &index : selectedRows )
1514 if ( !index.isValid() )
1517 const int row = index.row();
1518 if ( !mRenderer || mRenderer->ranges().size() <= row )
1521 if ( mRenderer->ranges().at( row ).symbol()->type() != tempSymbol->type() )
1524 std::unique_ptr<QgsSymbol> newCatSymbol( tempSymbol->clone() );
1525 if ( selectedRows.count() > 1 )
1528 newCatSymbol->setColor( mRenderer->ranges().at( row ).symbol()->color() );
1531 mRenderer->updateRangeSymbol( row, newCatSymbol.release() );
@ Standard
Standard (single-run) algorithm mode.
@ Size
Alter size of symbols.
@ Color
Alter color of symbols.
@ Millimeters
Millimeters.
@ Points
Points (e.g., for font sizes).
static QgsClassificationMethodRegistry * classificationMethodRegistry()
Returns the application's classification methods registry, used in graduated renderer.
static const QString METHOD_ID
std::unique_ptr< QgsClassificationMethod > method(const QString &id)
Returns a new instance of the method for the given id.
QIcon icon(const QString &id) const
Returns the icon for a given method id.
QMap< QString, QString > methodNames() const
Returns a map <name, id> of all registered methods.
An abstract class for implementations of classification methods.
double symmetryPoint() const
Returns the symmetry point for symmetric mode.
bool symmetricModeEnabled() const
Returns if the symmetric mode is enabled.
int labelPrecision() const
Returns the precision for the formatting of the labels.
virtual QString id() const =0
The id of the method as saved in the project, must be unique in registry.
QVariantMap parameterValues() const
Returns the values of the processing parameters.
bool symmetryAstride() const
Returns if the symmetric mode is astride if true, it will remove the symmetry point break so that the...
static const int MIN_PRECISION
QString labelFormat() const
Returns the format of the label for the classes.
static const int MAX_PRECISION
bool labelTrimTrailingZeroes() const
Returns if the trailing 0 are trimmed in the label.
@ IgnoresClassCount
The classification method does not compute classes based on a class count.
bool symmetricModeAvailable() const
Returns if the method supports symmetric calculation.
QgsClassificationMethod::MethodProperties flags() const
Returns the classification flags.
static const QString METHOD_ID
Abstract base class for color ramps.
A custom validator which allows entry of doubles in a locale-tolerant way.
static double toDouble(const QString &input, bool *ok)
Converts input string to double value.
void setTop(double top)
Set top range limit.
void setMaxDecimals(int maxDecimals)
Sets the number of decimals accepted by the validator to maxDecimals.
void setBottom(double bottom)
Set top range limit.
Single scope for storing variables and functions for use within a QgsExpressionContext.
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
static QgsExpressionContextScope * atlasScope(const QgsLayoutAtlas *atlas)
Creates a new scope which contains variables and functions relating to a QgsLayoutAtlas.
static QgsExpressionContextScope * mapSettingsScope(const QgsMapSettings &mapSettings)
Creates a new scope which contains variables and functions relating to a QgsMapSettings object.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
Abstract base class for all 2D vector feature renderers.
@ Numeric
All numeric fields.
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
A vector feature renderer which uses numeric attributes to classify features into different ranges.
static QgsGraduatedSymbolRenderer * convertFromRenderer(const QgsFeatureRenderer *renderer)
creates a QgsGraduatedSymbolRenderer from an existing renderer.
const QgsRangeList & ranges() const
Returns a list of all ranges used in the classification.
static QgsProcessingGuiRegistry * processingGuiRegistry()
Returns the global processing gui registry, used for registering the GUI behavior of processing algor...
A dialog for setting a lower and upper range value.
double upperValueDouble() const
Returns the upper value.
double lowerValueDouble() const
Returns the lower value.
void setLowerValue(const QString &val)
void setUpperValue(const QString &val)
Stores information about one class/rule of a vector layer renderer in a unified way that can be used ...
Contains configuration for rendering maps.
Contains information about the context in which a processing algorithm is executed.
QgsAbstractProcessingParameterWidgetWrapper * createParameterWidgetWrapper(const QgsProcessingParameterDefinition *parameter, Qgis::ProcessingMode type)
Creates a new parameter widget wrapper for the given parameter.
Base class for the definition of processing parameters.
QVariant defaultValueForGui() const
Returns the default value to use for the parameter in a GUI.
QString name() const
Returns the name of the parameter.
static QgsProject * instance()
Returns the QgsProject singleton instance.
A QProxyStyle subclass which correctly sets the base style to match the QGIS application style,...
Represents a value range for a QgsGraduatedSymbolRenderer.
QString label() const
Returns the label used for the range.
QgsSymbol * symbol() const
Returns the symbol used for the range.
bool renderState() const
Returns true if the range should be rendered.
double upperValue() const
Returns the upper bound of the range.
double lowerValue() const
Returns the lower bound of the range.
Stores properties relating to a screen.
A database of saved style entities, including symbols, color ramps, text formats and others.
static std::unique_ptr< QgsSymbol > symbolFromMimeData(const QMimeData *data)
Attempts to parse mime data as a symbol.
static QIcon symbolPreviewIcon(const QgsSymbol *symbol, QSize size, int padding=0, QgsLegendPatchShape *shape=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Returns an icon preview for a color ramp.
A dialog that can be used to select and build a symbol.
void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the symbol widget is shown, e.g., the associated map canvas and expression ...
Contains settings which reflect the context in which a symbol (or renderer) widget is shown,...
Abstract base class for all rendered symbols.
void setColor(const QColor &color) const
Sets the color for the symbol.
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
static QgsSymbol * defaultSymbol(Qgis::GeometryType geomType)
Returns a new default symbol for the specified geometry type.
Temporarily sets a cursor override for the QApplication for the lifetime of the object.
Represents a vector layer which manages a vector based dataset.
void minimumAndMaximumValue(int index, QVariant &minimum, QVariant &maximum) const
Calculates both the minimum and maximum value for an attribute column.
QSize iconSize(bool dockableToolbar)
Returns the user-preferred size of a window's toolbar icons.
int scaleIconSize(int standardSize)
Scales an icon size to compensate for display pixel density, making the icon size hi-dpi friendly,...
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...
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
QList< QgsLegendSymbolItem > QgsLegendSymbolList
#define QgsDebugMsgLevel(str, level)
QList< QgsRendererRange > QgsRangeList