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 );
1102 QVariantMap parameterValues;
1103 for (
const auto &ppww : std::as_const( mParameterWidgetWrappers ) )
1105 mClassificationMethod->setParameterValues( parameterValues );
1108 mRenderer->setClassificationMethod( mClassificationMethod->clone().release() );
1111 mRenderer->setClassAttribute( attrName );
1115 if ( mRenderer->classificationMethod()->codeComplexity() > 1 &&
mLayer->featureCount() > 50000 )
1117 if ( QMessageBox::Cancel
1118 == QMessageBox::question(
1120 tr(
"Apply Classification" ),
1121 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." ),
1122 QMessageBox::Cancel,
1130 if ( methodComboBox->currentData() == ColorMode )
1132 std::unique_ptr<QgsColorRamp> ramp( btnColorRamp->colorRamp() );
1135 QMessageBox::critical(
this, tr(
"Apply Classification" ), tr(
"No color ramp defined." ) );
1138 mRenderer->setSourceColorRamp( ramp.release() );
1142 mRenderer->setSourceColorRamp(
nullptr );
1146 mRenderer->updateClasses(
mLayer, nclasses, error );
1148 if ( !error.isEmpty() )
1149 QMessageBox::critical(
this, tr(
"Apply Classification" ), error );
1151 if ( methodComboBox->currentData() == SizeMode )
1152 mRenderer->setSymbolSizes( minSizeSpinBox->value(), maxSizeSpinBox->value() );
1154 mRenderer->calculateLabelPrecision();
1162 std::unique_ptr<QgsColorRamp> ramp( btnColorRamp->colorRamp() );
1166 mRenderer->updateColorRamp( ramp.release() );
1167 mRenderer->updateSymbols( mGraduatedSymbol.get() );
1173 mRenderer->setSymbolSizes( minSizeSpinBox->value(), maxSizeSpinBox->value() );
1174 mRenderer->updateSymbols( mGraduatedSymbol.get() );
1179int QgsRendererPropertiesDialog::currentRangeRow()
1181 QModelIndex idx = viewGraduated->selectionModel()->currentIndex();
1182 if ( !idx.isValid() )
1191 QModelIndexList selectedRows = viewGraduated->selectionModel()->selectedRows();
1193 const auto constSelectedRows = selectedRows;
1194 for (
const QModelIndex &r : constSelectedRows )
1198 rows.append( r.row() );
1207 QModelIndexList selectedRows = viewGraduated->selectionModel()->selectedRows();
1208 QModelIndexList::const_iterator sIt = selectedRows.constBegin();
1210 for ( ; sIt != selectedRows.constEnd(); ++sIt )
1219 if ( idx.isValid() && idx.column() == 0 )
1221 if ( idx.isValid() && idx.column() == 1 )
1227 if ( !idx.isValid() )
1230 mRowSelected = idx.row();
1239 std::unique_ptr<QgsSymbol> newSymbol( range.
symbol()->
clone() );
1253 if ( !dlg.exec() || !newSymbol )
1258 mGraduatedSymbol = std::move( newSymbol );
1259 whileBlocking( btnChangeGraduatedSymbol )->setSymbol( mGraduatedSymbol->clone() );
1271 int decimalPlaces = mRenderer->classificationMethod()->labelPrecision() + 2;
1272 if ( decimalPlaces < 0 )
1277 if ( dialog.exec() == QDialog::Accepted )
1283 if ( cbxLinkBoundaries->isChecked() )
1287 mRenderer->updateRangeUpperValue( rangeIdx - 1, dialog.
lowerValueDouble() );
1290 if ( rangeIdx < mRenderer->ranges().size() - 1 )
1292 mRenderer->updateRangeLowerValue( rangeIdx + 1, dialog.
upperValueDouble() );
1296 mHistogramWidget->refresh();
1302 mModel->addClass( mGraduatedSymbol.get() );
1303 mHistogramWidget->refresh();
1310 mModel->deleteRows( classIndexes );
1311 mHistogramWidget->refresh();
1317 mModel->removeAllRows();
1318 mHistogramWidget->refresh();
1325 bool ordered =
true;
1326 for (
int i = 1; i < ranges.size(); ++i )
1328 if ( ranges[i] < ranges[i - 1] )
1345 int result = QMessageBox::warning(
this, tr(
"Link Class Boundaries" ), tr(
"Rows will be reordered before linking boundaries. Continue?" ), QMessageBox::Ok | QMessageBox::Cancel );
1346 if ( result != QMessageBox::Ok )
1348 cbxLinkBoundaries->setChecked(
false );
1351 mRenderer->sortByValue();
1355 for (
int i = 1; i < mRenderer->ranges().size(); ++i )
1357 mRenderer->updateRangeLowerValue( i, mRenderer->ranges()[i - 1].upperValue() );
1365 if ( item->column() == 2 )
1367 QString label = item->text();
1368 int idx = item->row();
1369 mRenderer->updateRangeLabel( idx, label );
1375 mRenderer->classificationMethod()->setLabelFormat( txtLegendFormat->text() );
1376 mRenderer->classificationMethod()->setLabelPrecision( spinPrecision->value() );
1377 mRenderer->classificationMethod()->setLabelTrimTrailingZeroes( cbxTrimTrailingZeroes->isChecked() );
1378 mRenderer->updateRangeLabels();
1379 mModel->updateLabels();
1387 QItemSelectionModel *m = viewGraduated->selectionModel();
1388 QModelIndexList selectedIndexes = m->selectedRows( 1 );
1389 if ( !selectedIndexes.isEmpty() )
1392 QModelIndexList::const_iterator indexIt = selectedIndexes.constBegin();
1393 for ( ; indexIt != selectedIndexes.constEnd(); ++indexIt )
1395 QStringList list = m->model()->data( *indexIt ).toString().split(
' ' );
1396 if ( list.size() < 3 )
1421 int decimalPlaces = mRenderer->classificationMethod()->labelPrecision() + 2;
1422 if ( decimalPlaces < 0 )
1424 double precision = 1.0 / std::pow( 10, decimalPlaces );
1426 for ( QgsRangeList::const_iterator it = ranges.begin(); it != ranges.end(); ++it )
1430 return it->symbol();
1440 mModel->updateSymbology();
1442 mHistogramWidget->refresh();
1453 viewGraduated->selectionModel()->clear();
1456 cbxLinkBoundaries->setChecked(
false );
1473 if ( event->key() == Qt::Key_C && event->modifiers() == Qt::ControlModifier )
1475 mCopyBuffer.clear();
1478 else if ( event->key() == Qt::Key_V && event->modifiers() == Qt::ControlModifier )
1480 QgsRangeList::iterator rIt = mCopyBuffer.begin();
1481 for ( ; rIt != mCopyBuffer.end(); ++rIt )
1483 rIt->mUuid = QUuid::createUuid().toString();
1484 mModel->addClass( *rIt );
1490void QgsGraduatedSymbolRendererWidget::selectionChanged(
const QItemSelection &,
const QItemSelection & )
1493 if ( !ranges.isEmpty() )
1495 whileBlocking( btnChangeGraduatedSymbol )->setSymbol( ranges.at( 0 ).symbol()->clone() );
1497 else if ( mRenderer->sourceSymbol() )
1499 whileBlocking( btnChangeGraduatedSymbol )->setSymbol( mRenderer->sourceSymbol()->clone() );
1501 btnChangeGraduatedSymbol->setDialogTitle( ranges.size() == 1 ? ranges.at( 0 ).label() : tr(
"Symbol Settings" ) );
1504void QgsGraduatedSymbolRendererWidget::dataDefinedSizeLegend()
1506 QgsMarkerSymbol *s =
static_cast<QgsMarkerSymbol *
>( mGraduatedSymbol.get() );
1518void QgsGraduatedSymbolRendererWidget::changeGraduatedSymbol()
1520 mGraduatedSymbol.reset( btnChangeGraduatedSymbol->symbol()->clone() );
1530 const QModelIndexList selectedRows = viewGraduated->selectionModel()->selectedRows();
1531 for (
const QModelIndex &index : selectedRows )
1533 if ( !index.isValid() )
1536 const int row = index.row();
1537 if ( !mRenderer || mRenderer->ranges().size() <= row )
1540 if ( mRenderer->ranges().at( row ).symbol()->type() != tempSymbol->type() )
1543 std::unique_ptr<QgsSymbol> newCatSymbol( tempSymbol->clone() );
1544 if ( selectedRows.count() > 1 )
1547 newCatSymbol->setColor( mRenderer->ranges().at( row ).symbol()->color() );
1550 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