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 )
80 if ( !mRenderer->ranges().isEmpty() )
82 beginRemoveRows( QModelIndex(), 0, mRenderer->ranges().size() - 1 );
93 if ( !renderer->
ranges().isEmpty() )
95 beginInsertRows( QModelIndex(), 0, renderer->
ranges().size() - 1 );
101 mRenderer = renderer;
106void QgsGraduatedSymbolRendererModel::addClass(
QgsSymbol *symbol )
110 int idx = mRenderer->ranges().size();
111 beginInsertRows( QModelIndex(), idx, idx );
112 mRenderer->addClass( symbol );
116void QgsGraduatedSymbolRendererModel::addClass(
const QgsRendererRange &range )
122 int idx = mRenderer->ranges().size();
123 beginInsertRows( QModelIndex(), idx, idx );
124 mRenderer->addClass( range );
128QgsRendererRange QgsGraduatedSymbolRendererModel::rendererRange(
const QModelIndex &index )
130 if ( !index.isValid() || !mRenderer || mRenderer->ranges().size() <= index.row() )
135 return mRenderer->ranges().value( index.row() );
138Qt::ItemFlags QgsGraduatedSymbolRendererModel::flags(
const QModelIndex &index )
const
141 if ( !index.isValid() )
143 return Qt::ItemIsDropEnabled;
146 Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsUserCheckable;
148 if ( index.column() == 2 )
150 flags |= Qt::ItemIsEditable;
156Qt::DropActions QgsGraduatedSymbolRendererModel::supportedDropActions()
const
158 return Qt::MoveAction;
161QString QgsGraduatedSymbolRendererModel::formatRangeValue(
double value )
const
163 int decimalPlaces = mRenderer->classificationMethod()->labelPrecision() + 2;
164 if ( decimalPlaces < 0 )
166 return QLocale().toString( value,
'f', decimalPlaces );
169QString QgsGraduatedSymbolRendererModel::tooltip(
const QModelIndex &index )
const
171 if ( !index.isValid() || !mRenderer || ( index.column() != 1 && index.column() != 2 ) )
175 const bool lowerInclusive = mRenderer->rangeLowerBoundIsInclusive( index.row() );
176 const bool upperInclusive = mRenderer->rangeUpperBoundIsInclusive( index.row() );
177 const QString lowerOperator = lowerInclusive ? u
"≤"_s : u
"<"_s;
178 const QString upperOperator = upperInclusive ? u
"≤"_s : u
"<"_s;
180 QString result = u
"%1 %2 %3 %4 %5"_s.arg( formatRangeValue( range.
lowerValue() ), lowerOperator, tr(
"Values" ), upperOperator, formatRangeValue( range.
upperValue() ) );
182 if ( mRenderer->rangeOverlapsEarlierRange( index.row() ) )
183 result += u
"\n%1"_s.arg( tr(
"This class overlaps with another class." ) );
188QVariant QgsGraduatedSymbolRendererModel::data(
const QModelIndex &index,
int role )
const
190 if ( !index.isValid() || !mRenderer )
195 if ( role == Qt::CheckStateRole && index.column() == 0 )
197 return range.
renderState() ? Qt::Checked : Qt::Unchecked;
199 else if ( role == Qt::DisplayRole )
201 switch ( index.column() )
204 return QString( formatRangeValue( range.
lowerValue() ) +
" - " + formatRangeValue( range.
upperValue() ) );
206 return range.
label();
211 else if ( role == Qt::ToolTipRole )
213 return tooltip( index );
215 else if ( role == Qt::DecorationRole && index.column() == 0 && range.
symbol() )
220 else if ( role == Qt::TextAlignmentRole )
222 return ( index.column() == 0 ) ?
static_cast<Qt::Alignment::Int
>( Qt::AlignHCenter ) : static_cast<Qt::Alignment::Int>( Qt::AlignLeft );
224 else if ( role == Qt::EditRole )
226 switch ( index.column() )
230 return range.
label();
239bool QgsGraduatedSymbolRendererModel::setData(
const QModelIndex &index,
const QVariant &value,
int role )
241 if ( !index.isValid() )
244 if ( index.column() == 0 && role == Qt::CheckStateRole )
246 mRenderer->updateRangeRenderState( index.row(), value == Qt::Checked );
247 emit dataChanged( index, index );
251 if ( role != Qt::EditRole )
254 switch ( index.column() )
259 mRenderer->updateRangeLabel( index.row(), value.toString() );
265 emit dataChanged( index, index );
269QVariant QgsGraduatedSymbolRendererModel::headerData(
int section, Qt::Orientation orientation,
int role )
const
271 if ( orientation == Qt::Horizontal && role == Qt::DisplayRole && section >= 0 && section < 3 )
274 lst << tr(
"Symbol" ) << tr(
"Values" ) << tr(
"Legend" );
275 return lst.value( section );
280int QgsGraduatedSymbolRendererModel::rowCount(
const QModelIndex &parent )
const
282 if ( parent.isValid() || !mRenderer )
286 return mRenderer->ranges().size();
289int QgsGraduatedSymbolRendererModel::columnCount(
const QModelIndex &index )
const
295QModelIndex QgsGraduatedSymbolRendererModel::index(
int row,
int column,
const QModelIndex &parent )
const
297 if ( hasIndex( row, column, parent ) )
299 return createIndex( row, column );
301 return QModelIndex();
304QModelIndex QgsGraduatedSymbolRendererModel::parent(
const QModelIndex &index )
const
307 return QModelIndex();
310QStringList QgsGraduatedSymbolRendererModel::mimeTypes()
const
313 types << mMimeFormat;
317QMimeData *QgsGraduatedSymbolRendererModel::mimeData(
const QModelIndexList &indexes )
const
319 QMimeData *mimeData =
new QMimeData();
320 QByteArray encodedData;
322 QDataStream stream( &encodedData, QIODevice::WriteOnly );
325 const auto constIndexes = indexes;
326 for (
const QModelIndex &index : constIndexes )
328 if ( !index.isValid() || index.column() != 0 )
331 stream << index.row();
333 mimeData->setData( mMimeFormat, encodedData );
337bool QgsGraduatedSymbolRendererModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
int row,
int column,
const QModelIndex &parent )
341 if ( action != Qt::MoveAction )
344 if ( !data->hasFormat( mMimeFormat ) )
347 QByteArray encodedData = data->data( mMimeFormat );
348 QDataStream stream( &encodedData, QIODevice::ReadOnly );
351 while ( !stream.atEnd() )
359 std::sort( rows.begin(), rows.end() );
366 to = mRenderer->ranges().size();
367 for (
int i = rows.size() - 1; i >= 0; i-- )
374 mRenderer->moveClass( rows[i], t );
376 for (
int j = 0; j < i; j++ )
378 if ( to < rows[j] && rows[i] > rows[j] )
385 emit dataChanged( createIndex( 0, 0 ), createIndex( mRenderer->ranges().size(), 0 ) );
390void QgsGraduatedSymbolRendererModel::deleteRows( QList<int> rows )
392 for (
int i = rows.size() - 1; i >= 0; i-- )
394 beginRemoveRows( QModelIndex(), rows[i], rows[i] );
395 mRenderer->deleteClass( rows[i] );
400void QgsGraduatedSymbolRendererModel::removeAllRows()
402 beginRemoveRows( QModelIndex(), 0, mRenderer->ranges().size() - 1 );
403 mRenderer->deleteAllClasses();
407void QgsGraduatedSymbolRendererModel::sort(
int column, Qt::SortOrder order )
415 mRenderer->sortByValue( order );
417 else if ( column == 2 )
419 mRenderer->sortByLabel( order );
422 emit dataChanged( createIndex( 0, 0 ), createIndex( mRenderer->ranges().size(), 0 ) );
425void QgsGraduatedSymbolRendererModel::updateSymbology()
427 emit dataChanged( createIndex( 0, 0 ), createIndex( mRenderer->ranges().size(), 0 ) );
430void QgsGraduatedSymbolRendererModel::updateLabels()
432 emit dataChanged( createIndex( 0, 2 ), createIndex( mRenderer->ranges().size(), 2 ) );
436QgsGraduatedSymbolRendererViewStyle::QgsGraduatedSymbolRendererViewStyle( QWidget *parent )
440void QgsGraduatedSymbolRendererViewStyle::drawPrimitive( PrimitiveElement element,
const QStyleOption *option, QPainter *painter,
const QWidget *widget )
const
442 if ( element == QStyle::PE_IndicatorItemViewItemDrop && !option->rect.isNull() )
444 QStyleOption opt( *option );
445 opt.rect.setLeft( 0 );
447 opt.rect.setHeight( 0 );
449 opt.rect.setRight( widget->width() );
450 QProxyStyle::drawPrimitive( element, &opt, painter, widget );
453 QProxyStyle::drawPrimitive( element, option, painter, widget );
469 if (
auto *lMapCanvas =
mContext.mapCanvas() )
471 expContext = lMapCanvas->createExpressionContext();
486 const auto constAdditionalExpressionContextScopes =
mContext.additionalExpressionContextScopes();
506 mRenderer = std::make_unique<QgsGraduatedSymbolRenderer>( QString(),
QgsRangeList() );
508 renderer->copyRendererData( mRenderer.get() );
515 cboSymmetryPoint->setEditable(
true );
516 cboSymmetryPoint->setValidator( mSymmetryPointValidator );
519 for ( QMap<QString, QString>::const_iterator it = methods.constBegin(); it != methods.constEnd(); ++it )
522 cboGraduatedMode->addItem( icon, it.key(), it.value() );
525 connect( methodComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, &QgsGraduatedSymbolRendererWidget::methodComboBox_currentIndexChanged );
526 this->layout()->setContentsMargins( 0, 0, 0, 0 );
528 mModel =
new QgsGraduatedSymbolRendererModel(
this, screen() );
531 mExpressionWidget->setLayer(
mLayer );
533 btnChangeGraduatedSymbol->setLayer(
mLayer );
534 btnChangeGraduatedSymbol->registerExpressionContextGenerator(
this );
540 spinPrecision->setClearValue( 4 );
542 spinGraduatedClasses->setShowClearButton(
false );
544 btnColorRamp->setShowRandomColorRamp(
true );
547 std::unique_ptr<QgsColorRamp> colorRamp(
QgsProject::instance()->styleSettings()->defaultColorRamp() );
550 btnColorRamp->setColorRamp( colorRamp.get() );
555 btnColorRamp->setColorRamp( ramp );
560 viewGraduated->setStyle(
new QgsGraduatedSymbolRendererViewStyle( viewGraduated ) );
563 if ( mGraduatedSymbol )
565 btnChangeGraduatedSymbol->setSymbolType( mGraduatedSymbol->type() );
566 btnChangeGraduatedSymbol->setSymbol( mGraduatedSymbol->clone() );
568 methodComboBox->blockSignals(
true );
569 methodComboBox->addItem( tr(
"Color" ), ColorMode );
570 switch ( mGraduatedSymbol->type() )
574 methodComboBox->addItem( tr(
"Size" ), SizeMode );
575 minSizeSpinBox->setValue( 1 );
576 maxSizeSpinBox->setValue( 8 );
581 methodComboBox->addItem( tr(
"Size" ), SizeMode );
582 minSizeSpinBox->setValue( .1 );
583 maxSizeSpinBox->setValue( 2 );
589 methodComboBox->hide();
596 methodComboBox->blockSignals(
false );
605 connect( btnChangeGraduatedSymbol, &
QgsSymbolButton::changed,
this, &QgsGraduatedSymbolRendererWidget::changeGraduatedSymbol );
612 connect( cboGraduatedMode, qOverload<int>( &QComboBox::currentIndexChanged ),
this, &QgsGraduatedSymbolRendererWidget::updateMethodParameters );
615 updateMethodParameters();
623 mGroupBoxSymmetric->setCollapsed(
true );
626 QMenu *advMenu =
new QMenu(
this );
631 QAction *actionDdsLegend = advMenu->addAction( tr(
"Data-defined Size Legend…" ) );
633 connect( actionDdsLegend, &QAction::triggered,
this, &QgsGraduatedSymbolRendererWidget::dataDefinedSizeLegend );
636 btnAdvanced->setMenu( advMenu );
638 mHistogramWidget->setLayer(
mLayer );
639 mHistogramWidget->setRenderer( mRenderer.get() );
643 mExpressionWidget->registerExpressionContextGenerator(
this );
645 mUpdateTimer.setSingleShot(
true );
646 mUpdateTimer.connect( &mUpdateTimer, &QTimer::timeout,
this, &QgsGraduatedSymbolRendererWidget::classifyGraduatedImpl );
649void QgsGraduatedSymbolRendererWidget::mSizeUnitWidget_changed()
651 if ( !mGraduatedSymbol )
653 mGraduatedSymbol->setOutputUnit( mSizeUnitWidget->unit() );
654 mGraduatedSymbol->setMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
655 mRenderer->updateSymbols( mGraduatedSymbol.get() );
661 mParameterWidgetWrappers.clear();
666 return mRenderer.get();
672 btnChangeGraduatedSymbol->setMapCanvas(
context.mapCanvas() );
673 btnChangeGraduatedSymbol->setMessageBar(
context.messageBar() );
678 delete mActionLevels;
679 mActionLevels =
nullptr;
700 connect( cboSymmetryPoint->lineEdit(), &QLineEdit::editingFinished,
this, &QgsGraduatedSymbolRendererWidget::symmetryPointEditingFinished );
702 for (
const auto &ppww : std::as_const( mParameterWidgetWrappers ) )
726 disconnect( cboSymmetryPoint->lineEdit(), &QLineEdit::editingFinished,
this, &QgsGraduatedSymbolRendererWidget::symmetryPointEditingFinished );
728 for (
const auto &ppww : std::as_const( mParameterWidgetWrappers ) )
744 int precision = spinPrecision->value() + 2;
745 while ( cboSymmetryPoint->count() )
746 cboSymmetryPoint->removeItem( 0 );
747 for (
int i = 0; i < ranges.count() - 1; i++ )
748 cboSymmetryPoint->addItem( QLocale().toString( ranges.at( i ).upperValue(),
'f', precision ), ranges.at( i ).upperValue() );
752 int idx = cboGraduatedMode->findData( method->
id() );
754 cboGraduatedMode->setCurrentIndex( idx );
760 cboSymmetryPoint->setItemText( cboSymmetryPoint->currentIndex(), QLocale().toString( method->
symmetryPoint(),
'f', method->
labelPrecision() + 2 ) );
767 for (
const auto &ppww : std::as_const( mParameterWidgetWrappers ) )
771 ppww->setParameterValue( value,
context );
776 int nclasses = ranges.count();
779 spinGraduatedClasses->setValue( ranges.count() );
787 spinGraduatedClasses->setEnabled(
true );
791 QString attrName = mRenderer->classAttribute();
792 mExpressionWidget->setField( attrName );
793 mHistogramWidget->setSourceFieldExp( attrName );
796 if ( mRenderer->sourceSymbol() )
798 mGraduatedSymbol.reset( mRenderer->sourceSymbol()->clone() );
799 whileBlocking( btnChangeGraduatedSymbol )->setSymbol( mGraduatedSymbol->clone() );
802 mModel->setRenderer( mRenderer.get() );
803 viewGraduated->setModel( mModel );
805 connect( viewGraduated->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsGraduatedSymbolRendererWidget::selectionChanged );
807 if ( mGraduatedSymbol )
809 mSizeUnitWidget->blockSignals(
true );
810 mSizeUnitWidget->setUnit( mGraduatedSymbol->outputUnit() );
811 mSizeUnitWidget->setMapUnitScale( mGraduatedSymbol->mapUnitScale() );
812 mSizeUnitWidget->blockSignals(
false );
816 methodComboBox->blockSignals(
true );
817 switch ( mRenderer->graduatedMethod() )
821 methodComboBox->setCurrentIndex( methodComboBox->findData( ColorMode ) );
822 if ( mRenderer->sourceColorRamp() )
824 btnColorRamp->setColorRamp( mRenderer->sourceColorRamp() );
830 methodComboBox->setCurrentIndex( methodComboBox->findData( SizeMode ) );
831 if ( !mRenderer->ranges().isEmpty() )
833 minSizeSpinBox->setValue( mRenderer->minSymbolSize() );
834 maxSizeSpinBox->setValue( mRenderer->maxSymbolSize() );
839 toggleMethodWidgets(
static_cast<MethodMode
>( methodComboBox->currentData().toInt() ) );
840 methodComboBox->blockSignals(
false );
842 viewGraduated->resizeColumnToContents( 0 );
843 viewGraduated->resizeColumnToContents( 1 );
844 viewGraduated->resizeColumnToContents( 2 );
846 mHistogramWidget->refresh();
856 mRenderer->setClassAttribute( field );
860void QgsGraduatedSymbolRendererWidget::methodComboBox_currentIndexChanged(
int )
862 const MethodMode newMethod =
static_cast<MethodMode
>( methodComboBox->currentData().toInt() );
863 toggleMethodWidgets( newMethod );
873 QMessageBox::critical(
this, tr(
"Select Method" ), tr(
"No color ramp defined." ) );
876 mRenderer->setSourceColorRamp( ramp );
883 lblColorRamp->setVisible(
false );
884 btnColorRamp->setVisible(
false );
885 lblSize->setVisible(
true );
886 minSizeSpinBox->setVisible(
true );
887 lblSize->setVisible(
true );
888 maxSizeSpinBox->setVisible(
true );
889 mSizeUnitWidget->setVisible(
true );
898void QgsGraduatedSymbolRendererWidget::updateMethodParameters()
900 clearParameterWidgets();
902 const QString methodId = cboGraduatedMode->currentData().toString();
904 Q_ASSERT( mClassificationMethod.get() );
909 for (
const QgsProcessingParameterDefinition *def : mClassificationMethod->parameterDefinitions() )
914 QVariant value = mClassificationMethod->parameterValues().value( def->name(), def->defaultValueForGui() );
919 mParameterWidgetWrappers.push_back( std::unique_ptr<QgsAbstractProcessingParameterWidgetWrapper>( ppww ) );
925void QgsGraduatedSymbolRendererWidget::toggleMethodWidgets( MethodMode mode )
931 lblColorRamp->setVisible(
true );
932 btnColorRamp->setVisible(
true );
933 lblSize->setVisible(
false );
934 minSizeSpinBox->setVisible(
false );
935 lblSizeTo->setVisible(
false );
936 maxSizeSpinBox->setVisible(
false );
937 mSizeUnitWidget->setVisible(
false );
943 lblColorRamp->setVisible(
false );
944 btnColorRamp->setVisible(
false );
945 lblSize->setVisible(
true );
946 minSizeSpinBox->setVisible(
true );
947 lblSizeTo->setVisible(
true );
948 maxSizeSpinBox->setVisible(
true );
949 mSizeUnitWidget->setVisible(
true );
955void QgsGraduatedSymbolRendererWidget::clearParameterWidgets()
957 while ( mParametersLayout->rowCount() )
959 QFormLayout::TakeRowResult row = mParametersLayout->takeRow( 0 );
960 for ( QLayoutItem *item : { row.labelItem, row.fieldItem } )
963 QWidget *widget = item->widget();
969 mParameterWidgetWrappers.clear();
977 mModel->updateSymbology();
980 spinGraduatedClasses->setValue( mRenderer->ranges().count() );
993 mRenderer->setLegendSymbolItem( legendSymbol.ruleKey(), sym->
clone() );
996 mRenderer->setUsingSymbolLevels( enabled );
997 mModel->updateSymbology();
1003 mGraduatedSymbol.reset( widget->
symbol()->
clone() );
1010 mSizeUnitWidget->blockSignals(
true );
1011 mSizeUnitWidget->setUnit( mGraduatedSymbol->outputUnit() );
1012 mSizeUnitWidget->setMapUnitScale( mGraduatedSymbol->mapUnitScale() );
1013 mSizeUnitWidget->blockSignals(
false );
1015 QItemSelectionModel *m = viewGraduated->selectionModel();
1016 QModelIndexList selectedIndexes = m->selectedRows( 1 );
1017 if ( !selectedIndexes.isEmpty() )
1019 const auto constSelectedIndexes = selectedIndexes;
1020 for (
const QModelIndex &idx : constSelectedIndexes )
1022 if ( idx.isValid() )
1024 int rangeIdx = idx.row();
1026 if ( selectedIndexes.count() > 1 )
1029 newRangeSymbol->
setColor( mRenderer->ranges().at( rangeIdx ).symbol()->color() );
1031 mRenderer->updateRangeSymbol( rangeIdx, newRangeSymbol );
1037 mRenderer->updateSymbols( mGraduatedSymbol.get() );
1044void QgsGraduatedSymbolRendererWidget::symmetryPointEditingFinished()
1046 const QString text = cboSymmetryPoint->lineEdit()->text();
1047 int index = cboSymmetryPoint->findText( text );
1050 cboSymmetryPoint->setCurrentIndex( index );
1054 cboSymmetryPoint->setItemText( cboSymmetryPoint->currentIndex(), text );
1062 mUpdateTimer.start( 500 );
1065void QgsGraduatedSymbolRendererWidget::classifyGraduatedImpl()
1067 if ( mBlockUpdates || !mClassificationMethod )
1071 QString attrName = mExpressionWidget->currentField();
1072 int nclasses = spinGraduatedClasses->value();
1080 double minimum = minVal.toDouble();
1081 double maximum = maxVal.toDouble();
1082 mSymmetryPointValidator->
setBottom( minimum );
1083 mSymmetryPointValidator->
setTop( maximum );
1084 mSymmetryPointValidator->
setMaxDecimals( spinPrecision->value() );
1091 if ( currentValue < ( minimum + ( maximum - minimum ) / 100. ) || currentValue > ( maximum - ( maximum - minimum ) / 100. ) )
1092 cboSymmetryPoint->setItemText( cboSymmetryPoint->currentIndex(), QLocale().toString( minimum + ( maximum - minimum ) / 2.,
'f', mClassificationMethod->labelPrecision() + 2 ) );
1095 if ( mGroupBoxSymmetric->isChecked() )
1098 bool astride = cbxAstride->isChecked();
1099 mClassificationMethod->setSymmetricMode(
true, symmetryPoint, astride );
1103 mClassificationMethod->setSymmetricMode(
false );
1106 QVariantMap parameterValues;
1107 for (
const auto &ppww : std::as_const( mParameterWidgetWrappers ) )
1109 mClassificationMethod->setParameterValues( parameterValues );
1112 mRenderer->setClassificationMethod( mClassificationMethod->clone().release() );
1115 mRenderer->setClassAttribute( attrName );
1119 if ( mRenderer->classificationMethod()->codeComplexity() > 1 &&
mLayer->featureCount() > 50000 )
1121 if ( QMessageBox::Cancel
1122 == QMessageBox::question(
1124 tr(
"Apply Classification" ),
1125 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." ),
1126 QMessageBox::Cancel,
1134 if ( methodComboBox->currentData() == ColorMode )
1136 std::unique_ptr<QgsColorRamp> ramp( btnColorRamp->colorRamp() );
1139 QMessageBox::critical(
this, tr(
"Apply Classification" ), tr(
"No color ramp defined." ) );
1142 mRenderer->setSourceColorRamp( ramp.release() );
1146 mRenderer->setSourceColorRamp(
nullptr );
1150 mRenderer->updateClasses(
mLayer, nclasses, error );
1152 if ( !error.isEmpty() )
1153 QMessageBox::critical(
this, tr(
"Apply Classification" ), error );
1155 if ( methodComboBox->currentData() == SizeMode )
1156 mRenderer->setSymbolSizes( minSizeSpinBox->value(), maxSizeSpinBox->value() );
1158 mRenderer->calculateLabelPrecision();
1166 std::unique_ptr<QgsColorRamp> ramp( btnColorRamp->colorRamp() );
1170 mRenderer->updateColorRamp( ramp.release() );
1171 mRenderer->updateSymbols( mGraduatedSymbol.get() );
1177 mRenderer->setSymbolSizes( minSizeSpinBox->value(), maxSizeSpinBox->value() );
1178 mRenderer->updateSymbols( mGraduatedSymbol.get() );
1183int QgsRendererPropertiesDialog::currentRangeRow()
1185 QModelIndex idx = viewGraduated->selectionModel()->currentIndex();
1186 if ( !idx.isValid() )
1195 QModelIndexList selectedRows = viewGraduated->selectionModel()->selectedRows();
1197 const auto constSelectedRows = selectedRows;
1198 for (
const QModelIndex &r : constSelectedRows )
1202 rows.append( r.row() );
1211 QModelIndexList selectedRows = viewGraduated->selectionModel()->selectedRows();
1212 QModelIndexList::const_iterator sIt = selectedRows.constBegin();
1214 for ( ; sIt != selectedRows.constEnd(); ++sIt )
1223 if ( idx.isValid() && idx.column() == 0 )
1225 if ( idx.isValid() && idx.column() == 1 )
1231 if ( !idx.isValid() )
1234 mRowSelected = idx.row();
1243 std::unique_ptr<QgsSymbol> newSymbol( range.
symbol()->
clone() );
1257 if ( !dlg.exec() || !newSymbol )
1262 mGraduatedSymbol = std::move( newSymbol );
1263 whileBlocking( btnChangeGraduatedSymbol )->setSymbol( mGraduatedSymbol->clone() );
1275 int decimalPlaces = mRenderer->classificationMethod()->labelPrecision() + 2;
1276 if ( decimalPlaces < 0 )
1281 if ( dialog.exec() == QDialog::Accepted )
1287 if ( cbxLinkBoundaries->isChecked() )
1291 mRenderer->updateRangeUpperValue( rangeIdx - 1, dialog.
lowerValueDouble() );
1294 if ( rangeIdx < mRenderer->ranges().size() - 1 )
1296 mRenderer->updateRangeLowerValue( rangeIdx + 1, dialog.
upperValueDouble() );
1300 mHistogramWidget->refresh();
1306 mModel->addClass( mGraduatedSymbol.get() );
1307 mHistogramWidget->refresh();
1314 mModel->deleteRows( classIndexes );
1315 mHistogramWidget->refresh();
1321 mModel->removeAllRows();
1322 mHistogramWidget->refresh();
1329 bool ordered =
true;
1330 for (
int i = 1; i < ranges.size(); ++i )
1332 if ( ranges[i] < ranges[i - 1] )
1349 int result = QMessageBox::warning(
this, tr(
"Link Class Boundaries" ), tr(
"Rows will be reordered before linking boundaries. Continue?" ), QMessageBox::Ok | QMessageBox::Cancel );
1350 if ( result != QMessageBox::Ok )
1352 cbxLinkBoundaries->setChecked(
false );
1355 mRenderer->sortByValue();
1359 for (
int i = 1; i < mRenderer->ranges().size(); ++i )
1361 mRenderer->updateRangeLowerValue( i, mRenderer->ranges()[i - 1].upperValue() );
1369 if ( item->column() == 2 )
1371 QString label = item->text();
1372 int idx = item->row();
1373 mRenderer->updateRangeLabel( idx, label );
1379 mRenderer->classificationMethod()->setLabelFormat( txtLegendFormat->text() );
1380 mRenderer->classificationMethod()->setLabelPrecision( spinPrecision->value() );
1381 mRenderer->classificationMethod()->setLabelTrimTrailingZeroes( cbxTrimTrailingZeroes->isChecked() );
1382 mRenderer->updateRangeLabels();
1383 mModel->updateLabels();
1391 QItemSelectionModel *m = viewGraduated->selectionModel();
1392 QModelIndexList selectedIndexes = m->selectedRows( 1 );
1393 if ( !selectedIndexes.isEmpty() )
1396 QModelIndexList::const_iterator indexIt = selectedIndexes.constBegin();
1397 for ( ; indexIt != selectedIndexes.constEnd(); ++indexIt )
1399 QStringList list = m->model()->data( *indexIt ).toString().split(
' ' );
1400 if ( list.size() < 3 )
1425 int decimalPlaces = mRenderer->classificationMethod()->labelPrecision() + 2;
1426 if ( decimalPlaces < 0 )
1428 double precision = 1.0 / std::pow( 10, decimalPlaces );
1430 for ( QgsRangeList::const_iterator it = ranges.begin(); it != ranges.end(); ++it )
1434 return it->symbol();
1444 mModel->updateSymbology();
1446 mHistogramWidget->refresh();
1457 viewGraduated->selectionModel()->clear();
1460 cbxLinkBoundaries->setChecked(
false );
1477 if ( event->key() == Qt::Key_C && event->modifiers() == Qt::ControlModifier )
1479 mCopyBuffer.clear();
1482 else if ( event->key() == Qt::Key_V && event->modifiers() == Qt::ControlModifier )
1484 QgsRangeList::iterator rIt = mCopyBuffer.begin();
1485 for ( ; rIt != mCopyBuffer.end(); ++rIt )
1487 rIt->mUuid = QUuid::createUuid().toString();
1488 mModel->addClass( *rIt );
1494void QgsGraduatedSymbolRendererWidget::selectionChanged(
const QItemSelection &,
const QItemSelection & )
1497 if ( !ranges.isEmpty() )
1499 whileBlocking( btnChangeGraduatedSymbol )->setSymbol( ranges.at( 0 ).symbol()->clone() );
1501 else if ( mRenderer->sourceSymbol() )
1503 whileBlocking( btnChangeGraduatedSymbol )->setSymbol( mRenderer->sourceSymbol()->clone() );
1505 btnChangeGraduatedSymbol->setDialogTitle( ranges.size() == 1 ? ranges.at( 0 ).label() : tr(
"Symbol Settings" ) );
1508void QgsGraduatedSymbolRendererWidget::dataDefinedSizeLegend()
1510 QgsMarkerSymbol *s =
static_cast<QgsMarkerSymbol *
>( mGraduatedSymbol.get() );
1522void QgsGraduatedSymbolRendererWidget::changeGraduatedSymbol()
1524 mGraduatedSymbol.reset( btnChangeGraduatedSymbol->symbol()->clone() );
1534 const QModelIndexList selectedRows = viewGraduated->selectionModel()->selectedRows();
1535 for (
const QModelIndex &index : selectedRows )
1537 if ( !index.isValid() )
1540 const int row = index.row();
1541 if ( !mRenderer || mRenderer->ranges().size() <= row )
1544 if ( mRenderer->ranges().at( row ).symbol()->type() != tempSymbol->type() )
1547 std::unique_ptr<QgsSymbol> newCatSymbol( tempSymbol->clone() );
1548 if ( selectedRows.count() > 1 )
1551 newCatSymbol->setColor( mRenderer->ranges().at( row ).symbol()->color() );
1554 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 std::unique_ptr< 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 std::unique_ptr< 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.
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