19#include <QStandardItemModel>
20#include <QStandardItem>
30#include "moc_qgsgraduatedsymbolrendererwidget.cpp"
67QgsGraduatedSymbolRendererModel::QgsGraduatedSymbolRendererModel( QObject *parent, QScreen *screen )
68 : QAbstractItemModel( parent )
69 , mMimeFormat( QStringLiteral(
"application/x-qgsgraduatedsymbolrendererv2model" ) )
78 if ( !mRenderer->ranges().isEmpty() )
80 beginRemoveRows( QModelIndex(), 0, mRenderer->ranges().size() - 1 );
91 if ( !renderer->
ranges().isEmpty() )
93 beginInsertRows( QModelIndex(), 0, renderer->
ranges().size() - 1 );
104void QgsGraduatedSymbolRendererModel::addClass(
QgsSymbol *symbol )
108 int idx = mRenderer->
ranges().size();
109 beginInsertRows( QModelIndex(), idx, idx );
110 mRenderer->addClass( symbol );
114void QgsGraduatedSymbolRendererModel::addClass(
const QgsRendererRange &range )
120 int idx = mRenderer->ranges().size();
121 beginInsertRows( QModelIndex(), idx, idx );
122 mRenderer->addClass( range );
126QgsRendererRange QgsGraduatedSymbolRendererModel::rendererRange(
const QModelIndex &index )
128 if ( !index.isValid() || !mRenderer || mRenderer->ranges().size() <= index.row() )
133 return mRenderer->ranges().value( index.row() );
136Qt::ItemFlags QgsGraduatedSymbolRendererModel::flags(
const QModelIndex &index )
const
139 if ( !index.isValid() )
141 return Qt::ItemIsDropEnabled;
144 Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsUserCheckable;
146 if ( index.column() == 2 )
148 flags |= Qt::ItemIsEditable;
154Qt::DropActions QgsGraduatedSymbolRendererModel::supportedDropActions()
const
156 return Qt::MoveAction;
159QVariant QgsGraduatedSymbolRendererModel::data(
const QModelIndex &index,
int role )
const
161 if ( !index.isValid() || !mRenderer )
166 if ( role == Qt::CheckStateRole && index.column() == 0 )
168 return range.
renderState() ? Qt::Checked : Qt::Unchecked;
170 else if ( role == Qt::DisplayRole || role == Qt::ToolTipRole )
172 switch ( index.column() )
176 int decimalPlaces = mRenderer->classificationMethod()->labelPrecision() + 2;
177 if ( decimalPlaces < 0 )
179 return QString( QLocale().toString( range.
lowerValue(),
'f', decimalPlaces ) +
" - " + QLocale().toString( range.
upperValue(),
'f', decimalPlaces ) );
182 return range.
label();
187 else if ( role == Qt::DecorationRole && index.column() == 0 && range.
symbol() )
192 else if ( role == Qt::TextAlignmentRole )
194 return ( index.column() == 0 ) ?
static_cast<Qt::Alignment::Int
>( Qt::AlignHCenter ) : static_cast<Qt::Alignment::Int>( Qt::AlignLeft );
196 else if ( role == Qt::EditRole )
198 switch ( index.column() )
202 return range.
label();
211bool QgsGraduatedSymbolRendererModel::setData(
const QModelIndex &index,
const QVariant &value,
int role )
213 if ( !index.isValid() )
216 if ( index.column() == 0 && role == Qt::CheckStateRole )
218 mRenderer->updateRangeRenderState( index.row(), value == Qt::Checked );
219 emit dataChanged( index, index );
223 if ( role != Qt::EditRole )
226 switch ( index.column() )
231 mRenderer->updateRangeLabel( index.row(), value.toString() );
237 emit dataChanged( index, index );
241QVariant QgsGraduatedSymbolRendererModel::headerData(
int section, Qt::Orientation orientation,
int role )
const
243 if ( orientation == Qt::Horizontal && role == Qt::DisplayRole && section >= 0 && section < 3 )
246 lst << tr(
"Symbol" ) << tr(
"Values" ) << tr(
"Legend" );
247 return lst.value( section );
252int QgsGraduatedSymbolRendererModel::rowCount(
const QModelIndex &parent )
const
254 if ( parent.isValid() || !mRenderer )
258 return mRenderer->ranges().size();
261int QgsGraduatedSymbolRendererModel::columnCount(
const QModelIndex &index )
const
267QModelIndex QgsGraduatedSymbolRendererModel::index(
int row,
int column,
const QModelIndex &parent )
const
269 if ( hasIndex( row, column, parent ) )
271 return createIndex( row, column );
273 return QModelIndex();
276QModelIndex QgsGraduatedSymbolRendererModel::parent(
const QModelIndex &index )
const
279 return QModelIndex();
282QStringList QgsGraduatedSymbolRendererModel::mimeTypes()
const
285 types << mMimeFormat;
289QMimeData *QgsGraduatedSymbolRendererModel::mimeData(
const QModelIndexList &indexes )
const
291 QMimeData *mimeData =
new QMimeData();
292 QByteArray encodedData;
294 QDataStream stream( &encodedData, QIODevice::WriteOnly );
297 const auto constIndexes = indexes;
298 for (
const QModelIndex &index : constIndexes )
300 if ( !index.isValid() || index.column() != 0 )
303 stream << index.row();
305 mimeData->setData( mMimeFormat, encodedData );
309bool QgsGraduatedSymbolRendererModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
int row,
int column,
const QModelIndex &parent )
313 if ( action != Qt::MoveAction )
316 if ( !data->hasFormat( mMimeFormat ) )
319 QByteArray encodedData = data->data( mMimeFormat );
320 QDataStream stream( &encodedData, QIODevice::ReadOnly );
323 while ( !stream.atEnd() )
331 std::sort( rows.begin(), rows.end() );
338 to = mRenderer->ranges().size();
339 for (
int i = rows.size() - 1; i >= 0; i-- )
341 QgsDebugMsgLevel( QStringLiteral(
"move %1 to %2" ).arg( rows[i] ).arg( to ), 2 );
346 mRenderer->moveClass( rows[i], t );
348 for (
int j = 0; j < i; j++ )
350 if ( to < rows[j] && rows[i] > rows[j] )
357 emit dataChanged( createIndex( 0, 0 ), createIndex( mRenderer->ranges().size(), 0 ) );
362void QgsGraduatedSymbolRendererModel::deleteRows( QList<int> rows )
364 for (
int i = rows.size() - 1; i >= 0; i-- )
366 beginRemoveRows( QModelIndex(), rows[i], rows[i] );
367 mRenderer->deleteClass( rows[i] );
372void QgsGraduatedSymbolRendererModel::removeAllRows()
374 beginRemoveRows( QModelIndex(), 0, mRenderer->ranges().size() - 1 );
375 mRenderer->deleteAllClasses();
379void QgsGraduatedSymbolRendererModel::sort(
int column, Qt::SortOrder order )
387 mRenderer->sortByValue( order );
389 else if ( column == 2 )
391 mRenderer->sortByLabel( order );
394 emit dataChanged( createIndex( 0, 0 ), createIndex( mRenderer->ranges().size(), 0 ) );
397void QgsGraduatedSymbolRendererModel::updateSymbology()
399 emit dataChanged( createIndex( 0, 0 ), createIndex( mRenderer->ranges().size(), 0 ) );
402void QgsGraduatedSymbolRendererModel::updateLabels()
404 emit dataChanged( createIndex( 0, 2 ), createIndex( mRenderer->ranges().size(), 2 ) );
408QgsGraduatedSymbolRendererViewStyle::QgsGraduatedSymbolRendererViewStyle( QWidget *parent )
412void QgsGraduatedSymbolRendererViewStyle::drawPrimitive( PrimitiveElement element,
const QStyleOption *option, QPainter *painter,
const QWidget *widget )
const
414 if ( element == QStyle::PE_IndicatorItemViewItemDrop && !option->rect.isNull() )
416 QStyleOption opt( *option );
417 opt.rect.setLeft( 0 );
419 opt.rect.setHeight( 0 );
421 opt.rect.setRight( widget->width() );
422 QProxyStyle::drawPrimitive( element, &opt, painter, widget );
425 QProxyStyle::drawPrimitive( element, option, painter, widget );
443 expContext = lMapCanvas->createExpressionContext();
477 mRenderer = std::make_unique<QgsGraduatedSymbolRenderer>( QString(),
QgsRangeList() );
486 cboSymmetryPoint->setEditable(
true );
487 cboSymmetryPoint->setValidator( mSymmetryPointValidator );
490 for ( QMap<QString, QString>::const_iterator it = methods.constBegin(); it != methods.constEnd(); ++it )
493 cboGraduatedMode->addItem( icon, it.key(), it.value() );
496 connect( methodComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, &QgsGraduatedSymbolRendererWidget::methodComboBox_currentIndexChanged );
497 this->layout()->setContentsMargins( 0, 0, 0, 0 );
499 mModel =
new QgsGraduatedSymbolRendererModel(
this, screen() );
502 mExpressionWidget->setLayer(
mLayer );
504 btnChangeGraduatedSymbol->setLayer(
mLayer );
505 btnChangeGraduatedSymbol->registerExpressionContextGenerator(
this );
507 mSizeUnitWidget->setUnits(
518 spinPrecision->setClearValue( 4 );
520 spinGraduatedClasses->setShowClearButton(
false );
522 btnColorRamp->setShowRandomColorRamp(
true );
525 std::unique_ptr<QgsColorRamp> colorRamp(
QgsProject::instance()->styleSettings()->defaultColorRamp() );
528 btnColorRamp->setColorRamp( colorRamp.get() );
533 btnColorRamp->setColorRamp( ramp );
538 viewGraduated->setStyle(
new QgsGraduatedSymbolRendererViewStyle( viewGraduated ) );
541 if ( mGraduatedSymbol )
543 btnChangeGraduatedSymbol->setSymbolType( mGraduatedSymbol->type() );
544 btnChangeGraduatedSymbol->setSymbol( mGraduatedSymbol->clone() );
546 methodComboBox->blockSignals(
true );
547 methodComboBox->addItem( tr(
"Color" ), ColorMode );
548 switch ( mGraduatedSymbol->type() )
552 methodComboBox->addItem( tr(
"Size" ), SizeMode );
553 minSizeSpinBox->setValue( 1 );
554 maxSizeSpinBox->setValue( 8 );
559 methodComboBox->addItem( tr(
"Size" ), SizeMode );
560 minSizeSpinBox->setValue( .1 );
561 maxSizeSpinBox->setValue( 2 );
567 methodComboBox->hide();
574 methodComboBox->blockSignals(
false );
583 connect( btnChangeGraduatedSymbol, &
QgsSymbolButton::changed,
this, &QgsGraduatedSymbolRendererWidget::changeGraduatedSymbol );
590 connect( cboGraduatedMode, qOverload<int>( &QComboBox::currentIndexChanged ),
this, &QgsGraduatedSymbolRendererWidget::updateMethodParameters );
593 updateMethodParameters();
601 mGroupBoxSymmetric->setCollapsed(
true );
604 QMenu *advMenu =
new QMenu(
this );
609 QAction *actionDdsLegend = advMenu->addAction( tr(
"Data-defined Size Legend…" ) );
611 connect( actionDdsLegend, &QAction::triggered,
this, &QgsGraduatedSymbolRendererWidget::dataDefinedSizeLegend );
614 btnAdvanced->setMenu( advMenu );
616 mHistogramWidget->setLayer(
mLayer );
617 mHistogramWidget->setRenderer( mRenderer.get() );
621 mExpressionWidget->registerExpressionContextGenerator(
this );
623 mUpdateTimer.setSingleShot(
true );
624 mUpdateTimer.connect( &mUpdateTimer, &QTimer::timeout,
this, &QgsGraduatedSymbolRendererWidget::classifyGraduatedImpl );
627void QgsGraduatedSymbolRendererWidget::mSizeUnitWidget_changed()
629 if ( !mGraduatedSymbol )
631 mGraduatedSymbol->setOutputUnit( mSizeUnitWidget->unit() );
632 mGraduatedSymbol->setMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
633 mRenderer->updateSymbols( mGraduatedSymbol.get() );
640 mParameterWidgetWrappers.clear();
645 return mRenderer.get();
657 delete mActionLevels;
658 mActionLevels =
nullptr;
679 connect( cboSymmetryPoint->lineEdit(), &QLineEdit::editingFinished,
this, &QgsGraduatedSymbolRendererWidget::symmetryPointEditingFinished );
681 for (
const auto &ppww : std::as_const( mParameterWidgetWrappers ) )
705 disconnect( cboSymmetryPoint->lineEdit(), &QLineEdit::editingFinished,
this, &QgsGraduatedSymbolRendererWidget::symmetryPointEditingFinished );
707 for (
const auto &ppww : std::as_const( mParameterWidgetWrappers ) )
723 int precision = spinPrecision->value() + 2;
724 while ( cboSymmetryPoint->count() )
725 cboSymmetryPoint->removeItem( 0 );
726 for (
int i = 0; i < ranges.count() - 1; i++ )
727 cboSymmetryPoint->addItem( QLocale().toString( ranges.at( i ).upperValue(),
'f',
precision ), ranges.at( i ).upperValue() );
731 int idx = cboGraduatedMode->findData( method->
id() );
733 cboGraduatedMode->setCurrentIndex( idx );
739 cboSymmetryPoint->setItemText( cboSymmetryPoint->currentIndex(), QLocale().toString( method->
symmetryPoint(),
'f', method->
labelPrecision() + 2 ) );
746 for (
const auto &ppww : std::as_const( mParameterWidgetWrappers ) )
750 ppww->setParameterValue( value,
context );
755 int nclasses = ranges.count();
758 spinGraduatedClasses->setValue( ranges.count() );
766 spinGraduatedClasses->setEnabled(
true );
770 QString attrName = mRenderer->classAttribute();
771 mExpressionWidget->setField( attrName );
772 mHistogramWidget->setSourceFieldExp( attrName );
775 if ( mRenderer->sourceSymbol() )
777 mGraduatedSymbol.reset( mRenderer->sourceSymbol()->clone() );
778 whileBlocking( btnChangeGraduatedSymbol )->setSymbol( mGraduatedSymbol->clone() );
781 mModel->setRenderer( mRenderer.get() );
782 viewGraduated->setModel( mModel );
784 connect( viewGraduated->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsGraduatedSymbolRendererWidget::selectionChanged );
786 if ( mGraduatedSymbol )
788 mSizeUnitWidget->blockSignals(
true );
789 mSizeUnitWidget->setUnit( mGraduatedSymbol->outputUnit() );
790 mSizeUnitWidget->setMapUnitScale( mGraduatedSymbol->mapUnitScale() );
791 mSizeUnitWidget->blockSignals(
false );
795 methodComboBox->blockSignals(
true );
796 switch ( mRenderer->graduatedMethod() )
800 methodComboBox->setCurrentIndex( methodComboBox->findData( ColorMode ) );
801 if ( mRenderer->sourceColorRamp() )
803 btnColorRamp->setColorRamp( mRenderer->sourceColorRamp() );
809 methodComboBox->setCurrentIndex( methodComboBox->findData( SizeMode ) );
810 if ( !mRenderer->ranges().isEmpty() )
812 minSizeSpinBox->setValue( mRenderer->minSymbolSize() );
813 maxSizeSpinBox->setValue( mRenderer->maxSymbolSize() );
818 toggleMethodWidgets(
static_cast<MethodMode
>( methodComboBox->currentData().toInt() ) );
819 methodComboBox->blockSignals(
false );
821 viewGraduated->resizeColumnToContents( 0 );
822 viewGraduated->resizeColumnToContents( 1 );
823 viewGraduated->resizeColumnToContents( 2 );
825 mHistogramWidget->refresh();
835 mRenderer->setClassAttribute( field );
838void QgsGraduatedSymbolRendererWidget::methodComboBox_currentIndexChanged(
int )
840 const MethodMode newMethod =
static_cast<MethodMode
>( methodComboBox->currentData().toInt() );
841 toggleMethodWidgets( newMethod );
851 QMessageBox::critical(
this, tr(
"Select Method" ), tr(
"No color ramp defined." ) );
854 mRenderer->setSourceColorRamp( ramp );
861 lblColorRamp->setVisible(
false );
862 btnColorRamp->setVisible(
false );
863 lblSize->setVisible(
true );
864 minSizeSpinBox->setVisible(
true );
865 lblSize->setVisible(
true );
866 maxSizeSpinBox->setVisible(
true );
867 mSizeUnitWidget->setVisible(
true );
876void QgsGraduatedSymbolRendererWidget::updateMethodParameters()
878 clearParameterWidgets();
880 const QString methodId = cboGraduatedMode->currentData().toString();
882 Q_ASSERT( mClassificationMethod.get() );
892 QVariant value = mClassificationMethod->parameterValues().value( def->name(), def->defaultValueForGui() );
897 mParameterWidgetWrappers.push_back( std::unique_ptr<QgsAbstractProcessingParameterWidgetWrapper>( ppww ) );
903void QgsGraduatedSymbolRendererWidget::toggleMethodWidgets( MethodMode mode )
909 lblColorRamp->setVisible(
true );
910 btnColorRamp->setVisible(
true );
911 lblSize->setVisible(
false );
912 minSizeSpinBox->setVisible(
false );
913 lblSizeTo->setVisible(
false );
914 maxSizeSpinBox->setVisible(
false );
915 mSizeUnitWidget->setVisible(
false );
921 lblColorRamp->setVisible(
false );
922 btnColorRamp->setVisible(
false );
923 lblSize->setVisible(
true );
924 minSizeSpinBox->setVisible(
true );
925 lblSizeTo->setVisible(
true );
926 maxSizeSpinBox->setVisible(
true );
927 mSizeUnitWidget->setVisible(
true );
933void QgsGraduatedSymbolRendererWidget::clearParameterWidgets()
935 while ( mParametersLayout->rowCount() )
937 QFormLayout::TakeRowResult row = mParametersLayout->takeRow( 0 );
938 for ( QLayoutItem *item : { row.labelItem, row.fieldItem } )
941 QWidget *widget = item->widget();
947 mParameterWidgetWrappers.clear();
955 mModel->updateSymbology();
958 spinGraduatedClasses->setValue( mRenderer->ranges().count() );
971 mRenderer->setLegendSymbolItem( legendSymbol.ruleKey(), sym->
clone() );
974 mRenderer->setUsingSymbolLevels( enabled );
975 mModel->updateSymbology();
981 mGraduatedSymbol.reset( widget->
symbol()->
clone() );
988 mSizeUnitWidget->blockSignals(
true );
989 mSizeUnitWidget->setUnit( mGraduatedSymbol->outputUnit() );
990 mSizeUnitWidget->setMapUnitScale( mGraduatedSymbol->mapUnitScale() );
991 mSizeUnitWidget->blockSignals(
false );
993 QItemSelectionModel *m = viewGraduated->selectionModel();
994 QModelIndexList selectedIndexes = m->selectedRows( 1 );
995 if ( !selectedIndexes.isEmpty() )
997 const auto constSelectedIndexes = selectedIndexes;
998 for (
const QModelIndex &idx : constSelectedIndexes )
1000 if ( idx.isValid() )
1002 int rangeIdx = idx.row();
1003 QgsSymbol *newRangeSymbol = mGraduatedSymbol->clone();
1004 if ( selectedIndexes.count() > 1 )
1007 newRangeSymbol->
setColor( mRenderer->ranges().at( rangeIdx ).symbol()->color() );
1009 mRenderer->updateRangeSymbol( rangeIdx, newRangeSymbol );
1015 mRenderer->updateSymbols( mGraduatedSymbol.get() );
1022void QgsGraduatedSymbolRendererWidget::symmetryPointEditingFinished()
1024 const QString text = cboSymmetryPoint->lineEdit()->text();
1025 int index = cboSymmetryPoint->findText( text );
1028 cboSymmetryPoint->setCurrentIndex( index );
1032 cboSymmetryPoint->setItemText( cboSymmetryPoint->currentIndex(), text );
1040 mUpdateTimer.start( 500 );
1043void QgsGraduatedSymbolRendererWidget::classifyGraduatedImpl()
1045 if ( mBlockUpdates || !mClassificationMethod )
1049 QString attrName = mExpressionWidget->currentField();
1050 int nclasses = spinGraduatedClasses->value();
1058 double minimum = minVal.toDouble();
1059 double maximum = maxVal.toDouble();
1060 mSymmetryPointValidator->
setBottom( minimum );
1061 mSymmetryPointValidator->
setTop( maximum );
1062 mSymmetryPointValidator->
setMaxDecimals( spinPrecision->value() );
1069 if ( currentValue < ( minimum + ( maximum - minimum ) / 100. ) || currentValue > ( maximum - ( maximum - minimum ) / 100. ) )
1070 cboSymmetryPoint->setItemText( cboSymmetryPoint->currentIndex(), QLocale().toString( minimum + ( maximum - minimum ) / 2.,
'f', mClassificationMethod->labelPrecision() + 2 ) );
1073 if ( mGroupBoxSymmetric->isChecked() )
1076 bool astride = cbxAstride->isChecked();
1077 mClassificationMethod->setSymmetricMode(
true, symmetryPoint, astride );
1080 QVariantMap parameterValues;
1081 for (
const auto &ppww : std::as_const( mParameterWidgetWrappers ) )
1082 parameterValues.insert( ppww->parameterDefinition()->name(), ppww->parameterValue() );
1083 mClassificationMethod->setParameterValues( parameterValues );
1086 mRenderer->setClassificationMethod( mClassificationMethod->clone().release() );
1089 mRenderer->setClassAttribute( attrName );
1093 if ( mRenderer->classificationMethod()->codeComplexity() > 1 &&
mLayer->
featureCount() > 50000 )
1095 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 ) )
1101 if ( methodComboBox->currentData() == ColorMode )
1103 std::unique_ptr<QgsColorRamp> ramp( btnColorRamp->colorRamp() );
1106 QMessageBox::critical(
this, tr(
"Apply Classification" ), tr(
"No color ramp defined." ) );
1109 mRenderer->setSourceColorRamp( ramp.release() );
1113 mRenderer->setSourceColorRamp(
nullptr );
1117 mRenderer->updateClasses(
mLayer, nclasses, error );
1119 if ( !error.isEmpty() )
1120 QMessageBox::critical(
this, tr(
"Apply Classification" ), error );
1122 if ( methodComboBox->currentData() == SizeMode )
1123 mRenderer->setSymbolSizes( minSizeSpinBox->value(), maxSizeSpinBox->value() );
1125 mRenderer->calculateLabelPrecision();
1133 std::unique_ptr<QgsColorRamp> ramp( btnColorRamp->colorRamp() );
1137 mRenderer->updateColorRamp( ramp.release() );
1138 mRenderer->updateSymbols( mGraduatedSymbol.get() );
1144 mRenderer->setSymbolSizes( minSizeSpinBox->value(), maxSizeSpinBox->value() );
1145 mRenderer->updateSymbols( mGraduatedSymbol.get() );
1150int QgsRendererPropertiesDialog::currentRangeRow()
1152 QModelIndex idx = viewGraduated->selectionModel()->currentIndex();
1153 if ( !idx.isValid() )
1162 QModelIndexList selectedRows = viewGraduated->selectionModel()->selectedRows();
1164 const auto constSelectedRows = selectedRows;
1165 for (
const QModelIndex &r : constSelectedRows )
1169 rows.append( r.row() );
1178 QModelIndexList selectedRows = viewGraduated->selectionModel()->selectedRows();
1179 QModelIndexList::const_iterator sIt = selectedRows.constBegin();
1181 for ( ; sIt != selectedRows.constEnd(); ++sIt )
1190 if ( idx.isValid() && idx.column() == 0 )
1192 if ( idx.isValid() && idx.column() == 1 )
1198 if ( !idx.isValid() )
1201 mRowSelected = idx.row();
1211 std::unique_ptr<QgsSymbol> newSymbol( range.
symbol()->
clone() );
1225 if ( !dlg.exec() || !newSymbol )
1230 mGraduatedSymbol = std::move( newSymbol );
1231 whileBlocking( btnChangeGraduatedSymbol )->setSymbol( mGraduatedSymbol->clone() );
1243 int decimalPlaces = mRenderer->classificationMethod()->labelPrecision() + 2;
1244 if ( decimalPlaces < 0 )
1249 if ( dialog.exec() == QDialog::Accepted )
1255 if ( cbxLinkBoundaries->isChecked() )
1259 mRenderer->updateRangeUpperValue( rangeIdx - 1, dialog.
lowerValueDouble() );
1262 if ( rangeIdx < mRenderer->ranges().size() - 1 )
1264 mRenderer->updateRangeLowerValue( rangeIdx + 1, dialog.
upperValueDouble() );
1268 mHistogramWidget->refresh();
1274 mModel->addClass( mGraduatedSymbol.get() );
1275 mHistogramWidget->refresh();
1282 mModel->deleteRows( classIndexes );
1283 mHistogramWidget->refresh();
1289 mModel->removeAllRows();
1290 mHistogramWidget->refresh();
1297 bool ordered =
true;
1298 for (
int i = 1; i < ranges.size(); ++i )
1300 if ( ranges[i] < ranges[i - 1] )
1317 int result = QMessageBox::warning(
1319 tr(
"Link Class Boundaries" ),
1320 tr(
"Rows will be reordered before linking boundaries. Continue?" ),
1321 QMessageBox::Ok | QMessageBox::Cancel
1323 if ( result != QMessageBox::Ok )
1325 cbxLinkBoundaries->setChecked(
false );
1328 mRenderer->sortByValue();
1332 for (
int i = 1; i < mRenderer->ranges().size(); ++i )
1334 mRenderer->updateRangeLowerValue( i, mRenderer->ranges()[i - 1].upperValue() );
1342 if ( item->column() == 2 )
1344 QString label = item->text();
1345 int idx = item->row();
1346 mRenderer->updateRangeLabel( idx, label );
1352 mRenderer->classificationMethod()->setLabelFormat( txtLegendFormat->text() );
1353 mRenderer->classificationMethod()->setLabelPrecision( spinPrecision->value() );
1354 mRenderer->classificationMethod()->setLabelTrimTrailingZeroes( cbxTrimTrailingZeroes->isChecked() );
1355 mRenderer->updateRangeLabels();
1356 mModel->updateLabels();
1364 QItemSelectionModel *m = viewGraduated->selectionModel();
1365 QModelIndexList selectedIndexes = m->selectedRows( 1 );
1366 if ( !selectedIndexes.isEmpty() )
1369 QModelIndexList::const_iterator indexIt = selectedIndexes.constBegin();
1370 for ( ; indexIt != selectedIndexes.constEnd(); ++indexIt )
1372 QStringList list = m->model()->data( *indexIt ).toString().split(
' ' );
1373 if ( list.size() < 3 )
1398 int decimalPlaces = mRenderer->classificationMethod()->labelPrecision() + 2;
1399 if ( decimalPlaces < 0 )
1401 double precision = 1.0 / std::pow( 10, decimalPlaces );
1403 for ( QgsRangeList::const_iterator it = ranges.begin(); it != ranges.end(); ++it )
1407 return it->symbol();
1417 mModel->updateSymbology();
1419 mHistogramWidget->refresh();
1430 viewGraduated->selectionModel()->clear();
1433 cbxLinkBoundaries->setChecked(
false );
1450 if ( event->key() == Qt::Key_C && event->modifiers() == Qt::ControlModifier )
1452 mCopyBuffer.clear();
1455 else if ( event->key() == Qt::Key_V && event->modifiers() == Qt::ControlModifier )
1457 QgsRangeList::iterator rIt = mCopyBuffer.begin();
1458 for ( ; rIt != mCopyBuffer.end(); ++rIt )
1460 rIt->mUuid = QUuid::createUuid().toString();
1461 mModel->addClass( *rIt );
1467void QgsGraduatedSymbolRendererWidget::selectionChanged(
const QItemSelection &,
const QItemSelection & )
1470 if ( !ranges.isEmpty() )
1472 whileBlocking( btnChangeGraduatedSymbol )->setSymbol( ranges.at( 0 ).symbol()->clone() );
1474 else if ( mRenderer->sourceSymbol() )
1476 whileBlocking( btnChangeGraduatedSymbol )->setSymbol( mRenderer->sourceSymbol()->clone() );
1478 btnChangeGraduatedSymbol->setDialogTitle( ranges.size() == 1 ? ranges.at( 0 ).label() : tr(
"Symbol Settings" ) );
1481void QgsGraduatedSymbolRendererWidget::dataDefinedSizeLegend()
1495void QgsGraduatedSymbolRendererWidget::changeGraduatedSymbol()
1497 mGraduatedSymbol.reset( btnChangeGraduatedSymbol->symbol()->clone() );
1507 const QModelIndexList selectedRows = viewGraduated->selectionModel()->selectedRows();
1508 for (
const QModelIndex &index : selectedRows )
1510 if ( !index.isValid() )
1513 const int row = index.row();
1514 if ( !mRenderer || mRenderer->ranges().size() <= row )
1517 if ( mRenderer->ranges().at( row ).symbol()->type() != tempSymbol->type() )
1520 std::unique_ptr<QgsSymbol> newCatSymbol( tempSymbol->clone() );
1521 if ( selectedRows.count() > 1 )
1524 newCatSymbol->setColor( mRenderer->ranges().at( row ).symbol()->color() );
1527 mRenderer->updateRangeSymbol( row, newCatSymbol.release() );
@ 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.
void copyRendererData(QgsFeatureRenderer *destRenderer) const
Clones generic renderer data to another renderer.
@ Date
Date or datetime fields.
@ 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.
A marker symbol type, for rendering Point and MultiPoint geometries.
Contains information about the context in which a processing algorithm is executed.
QgsAbstractProcessingParameterWidgetWrapper * createParameterWidgetWrapper(const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type)
Creates a new parameter widget wrapper for the given parameter.
@ Standard
Standard algorithm dialog.
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,...
QList< QgsExpressionContextScope > additionalExpressionContextScopes() const
Returns the list of additional expression context scopes to show as available within the layer.
QgsMapCanvas * mapCanvas() const
Returns the map canvas associated with the widget.
QgsMessageBar * messageBar() const
Returns the message bar associated with the widget.
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.
long long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
void minimumAndMaximumValue(int index, QVariant &minimum, QVariant &maximum) const
Calculates both the minimum and maximum value for an attribute column.
Q_INVOKABLE Qgis::GeometryType geometryType() const
Returns point, line or polygon.
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