46 #include <QMessageBox>
47 #include <QStandardItemModel>
48 #include <QStandardItem>
51 #include <QFileDialog>
56 QgsCategorizedSymbolRendererModel::QgsCategorizedSymbolRendererModel( QObject *parent ) : QAbstractItemModel( parent )
57 , mMimeFormat( QStringLiteral(
"application/x-qgscategorizedsymbolrendererv2model" ) )
65 beginRemoveRows( QModelIndex(), 0, std::max( mRenderer->categories().size() - 1, 0 ) );
74 beginInsertRows( QModelIndex(), 0, renderer->
categories().size() - 1 );
82 if ( !mRenderer )
return;
83 int idx = mRenderer->categories().size();
84 beginInsertRows( QModelIndex(), idx, idx );
85 mRenderer->addCategory( cat );
96 int row = index.row();
97 if ( row >= catList.size() )
101 return catList.at( row );
105 Qt::ItemFlags QgsCategorizedSymbolRendererModel::flags(
const QModelIndex &index )
const
107 if ( !index.isValid() || !mRenderer )
109 return Qt::ItemIsDropEnabled;
112 Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsUserCheckable;
113 if ( index.column() == 1 )
116 if ( category.
value().type() != QVariant::List )
118 flags |= Qt::ItemIsEditable;
121 else if ( index.column() == 2 )
123 flags |= Qt::ItemIsEditable;
128 Qt::DropActions QgsCategorizedSymbolRendererModel::supportedDropActions()
const
130 return Qt::MoveAction;
133 QVariant QgsCategorizedSymbolRendererModel::data(
const QModelIndex &index,
int role )
const
135 if ( !index.isValid() || !mRenderer )
142 case Qt::CheckStateRole:
144 if ( index.column() == 0 )
146 return category.
renderState() ? Qt::Checked : Qt::Unchecked;
151 case Qt::DisplayRole:
152 case Qt::ToolTipRole:
154 switch ( index.column() )
158 if ( category.
value().type() == QVariant::List )
161 const QVariantList list = category.
value().toList();
162 res.reserve( list.size() );
163 for (
const QVariant &v : list )
166 if ( role == Qt::DisplayRole )
167 return res.join(
';' );
169 return res.join(
'\n' );
171 else if ( !category.
value().isValid() || category.
value().isNull() || category.
value().toString().isEmpty() )
173 return tr(
"all other values" );
177 return category.
value().toString();
181 return category.
label();
188 if ( index.column() == 1 && category.
value().type() != QVariant::List && ( !category.
value().isValid() || category.
value().isNull() || category.
value().toString().isEmpty() ) )
191 italicFont.setItalic(
true );
197 case Qt::DecorationRole:
199 if ( index.column() == 0 && category.
symbol() )
207 case Qt::ForegroundRole:
209 QBrush brush( qApp->palette().color( QPalette::Text ), Qt::SolidPattern );
210 if ( index.column() == 1 && ( category.
value().type() == QVariant::List
211 || !category.
value().isValid() || category.
value().isNull() || category.
value().toString().isEmpty() ) )
213 QColor fadedTextColor = brush.color();
214 fadedTextColor.setAlpha( 128 );
215 brush.setColor( fadedTextColor );
220 case Qt::TextAlignmentRole:
222 return ( index.column() == 0 ) ? Qt::AlignHCenter : Qt::AlignLeft;
227 switch ( index.column() )
231 if ( category.
value().type() == QVariant::List )
234 const QVariantList list = category.
value().toList();
235 res.reserve( list.size() );
236 for (
const QVariant &v : list )
239 return res.join(
';' );
243 return category.
value();
248 return category.
label();
257 bool QgsCategorizedSymbolRendererModel::setData(
const QModelIndex &index,
const QVariant &value,
int role )
259 if ( !index.isValid() )
262 if ( index.column() == 0 && role == Qt::CheckStateRole )
264 mRenderer->updateCategoryRenderState( index.row(), value == Qt::Checked );
265 emit dataChanged( index, index );
269 if ( role != Qt::EditRole )
272 switch ( index.column() )
278 switch ( mRenderer->categories().value( index.row() ).value().type() )
283 case QVariant::Double:
284 val = value.toDouble();
288 const QStringList parts = value.toString().split(
';' );
290 list.reserve( parts.count() );
291 for (
const QString &p : parts )
294 if ( list.count() == 1 )
301 val = value.toString();
304 mRenderer->updateCategoryValue( index.row(), val );
308 mRenderer->updateCategoryLabel( index.row(), value.toString() );
314 emit dataChanged( index, index );
318 QVariant QgsCategorizedSymbolRendererModel::headerData(
int section, Qt::Orientation orientation,
int role )
const
320 if ( orientation == Qt::Horizontal && role == Qt::DisplayRole && section >= 0 && section < 3 )
323 lst << tr(
"Symbol" ) << tr(
"Value" ) << tr(
"Legend" );
324 return lst.value( section );
329 int QgsCategorizedSymbolRendererModel::rowCount(
const QModelIndex &parent )
const
331 if ( parent.isValid() || !mRenderer )
335 return mRenderer->categories().size();
338 int QgsCategorizedSymbolRendererModel::columnCount(
const QModelIndex &index )
const
344 QModelIndex QgsCategorizedSymbolRendererModel::index(
int row,
int column,
const QModelIndex &parent )
const
346 if ( hasIndex( row, column, parent ) )
348 return createIndex( row, column );
350 return QModelIndex();
353 QModelIndex QgsCategorizedSymbolRendererModel::parent(
const QModelIndex &index )
const
356 return QModelIndex();
359 QStringList QgsCategorizedSymbolRendererModel::mimeTypes()
const
362 types << mMimeFormat;
366 QMimeData *QgsCategorizedSymbolRendererModel::mimeData(
const QModelIndexList &indexes )
const
368 QMimeData *mimeData =
new QMimeData();
369 QByteArray encodedData;
371 QDataStream stream( &encodedData, QIODevice::WriteOnly );
374 const auto constIndexes = indexes;
375 for (
const QModelIndex &index : constIndexes )
377 if ( !index.isValid() || index.column() != 0 )
380 stream << index.row();
382 mimeData->setData( mMimeFormat, encodedData );
386 bool QgsCategorizedSymbolRendererModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
int row,
int column,
const QModelIndex &parent )
390 if ( action != Qt::MoveAction )
return true;
392 if ( !data->hasFormat( mMimeFormat ) )
return false;
394 QByteArray encodedData = data->data( mMimeFormat );
395 QDataStream stream( &encodedData, QIODevice::ReadOnly );
398 while ( !stream.atEnd() )
405 int to = parent.row();
408 if ( to == -1 ) to = mRenderer->categories().size();
409 for (
int i = rows.size() - 1; i >= 0; i-- )
411 QgsDebugMsg( QStringLiteral(
"move %1 to %2" ).arg( rows[i] ).arg( to ) );
414 if ( rows[i] < t ) t--;
415 mRenderer->moveCategory( rows[i], t );
417 for (
int j = 0; j < i; j++ )
419 if ( to < rows[j] && rows[i] > rows[j] ) rows[j] += 1;
422 if ( rows[i] < to ) to--;
424 emit dataChanged( createIndex( 0, 0 ), createIndex( mRenderer->categories().size(), 0 ) );
429 void QgsCategorizedSymbolRendererModel::deleteRows( QList<int> rows )
431 std::sort( rows.begin(), rows.end() );
432 for (
int i = rows.size() - 1; i >= 0; i-- )
434 beginRemoveRows( QModelIndex(), rows[i], rows[i] );
435 mRenderer->deleteCategory( rows[i] );
440 void QgsCategorizedSymbolRendererModel::removeAllRows()
442 beginRemoveRows( QModelIndex(), 0, mRenderer->categories().size() - 1 );
443 mRenderer->deleteAllCategories();
447 void QgsCategorizedSymbolRendererModel::sort(
int column, Qt::SortOrder order )
455 mRenderer->sortByValue( order );
457 else if ( column == 2 )
459 mRenderer->sortByLabel( order );
461 emit dataChanged( createIndex( 0, 0 ), createIndex( mRenderer->categories().size(), 0 ) );
464 void QgsCategorizedSymbolRendererModel::updateSymbology()
466 emit dataChanged( createIndex( 0, 0 ), createIndex( mRenderer->categories().size(), 0 ) );
470 QgsCategorizedSymbolRendererViewStyle::QgsCategorizedSymbolRendererViewStyle( QWidget *parent )
474 void QgsCategorizedSymbolRendererViewStyle::drawPrimitive( PrimitiveElement element,
const QStyleOption *option, QPainter *painter,
const QWidget *widget )
const
476 if ( element == QStyle::PE_IndicatorItemViewItemDrop && !option->rect.isNull() )
478 QStyleOption opt( *option );
479 opt.rect.setLeft( 0 );
481 opt.rect.setHeight( 0 );
482 if ( widget ) opt.rect.setRight( widget->width() );
483 QProxyStyle::drawPrimitive( element, &opt, painter, widget );
486 QProxyStyle::drawPrimitive( element, option, painter, widget );
494 return new QgsCategorizedSymbolRendererWidget( layer, style, renderer );
499 , mContextMenu( new QMenu( this ) )
513 QString attrName =
mRenderer->classAttribute();
514 mOldClassificationAttribute = attrName;
518 layout()->setContentsMargins( 0, 0, 0, 0 );
520 mExpressionWidget->setLayer(
mLayer );
521 btnChangeCategorizedSymbol->setLayer(
mLayer );
522 btnChangeCategorizedSymbol->registerExpressionContextGenerator(
this );
525 btnColorRamp->setShowRandomColorRamp(
true );
528 QString defaultColorRamp =
QgsProject::instance()->
readEntry( QStringLiteral(
"DefaultStyles" ), QStringLiteral(
"/ColorRamp" ), QString() );
529 if ( !defaultColorRamp.isEmpty() )
531 btnColorRamp->setColorRampFromName( defaultColorRamp );
535 btnColorRamp->setRandomColorRamp();
545 mModel =
new QgsCategorizedSymbolRendererModel(
this );
551 viewCategories->setModel(
mModel );
552 viewCategories->resizeColumnToContents( 0 );
553 viewCategories->resizeColumnToContents( 1 );
554 viewCategories->resizeColumnToContents( 2 );
556 viewCategories->setStyle(
new QgsCategorizedSymbolRendererViewStyle( viewCategories ) );
557 connect( viewCategories->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsCategorizedSymbolRendererWidget::selectionChanged );
565 connect( viewCategories, &QTreeView::customContextMenuRequested,
this, &QgsCategorizedSymbolRendererWidget::showContextMenu );
567 connect( btnChangeCategorizedSymbol, &
QgsSymbolButton::changed,
this, &QgsCategorizedSymbolRendererWidget::updateSymbolsFromButton );
577 QMenu *advMenu =
new QMenu;
581 advMenu->addAction( tr(
"Symbol Levels…" ),
this, SLOT(
showSymbolLevels() ) );
584 QAction *actionDdsLegend = advMenu->addAction( tr(
"Data-defined Size Legend…" ) );
586 connect( actionDdsLegend, &QAction::triggered,
this, &QgsCategorizedSymbolRendererWidget::dataDefinedSizeLegend );
589 btnAdvanced->setMenu( advMenu );
591 mExpressionWidget->registerExpressionContextGenerator(
this );
593 mMergeCategoriesAction =
new QAction( tr(
"Merge Categories" ),
this );
594 connect( mMergeCategoriesAction, &QAction::triggered,
this, &QgsCategorizedSymbolRendererWidget::mergeSelectedCategories );
595 mUnmergeCategoriesAction =
new QAction( tr(
"Unmerge Categories" ),
this );
596 connect( mUnmergeCategoriesAction, &QAction::triggered,
this, &QgsCategorizedSymbolRendererWidget::unmergeSelectedCategories );
598 connect( mContextMenu, &QMenu::aboutToShow,
this, [ = ]
619 QString attrName = mRenderer->classAttribute();
620 mExpressionWidget->setField( attrName );
623 if ( mRenderer->sourceSymbol() )
625 mCategorizedSymbol.reset( mRenderer->sourceSymbol()->clone() );
626 whileBlocking( btnChangeCategorizedSymbol )->setSymbol( mCategorizedSymbol->clone() );
630 if ( mRenderer->sourceColorRamp() )
632 btnColorRamp->setColorRamp( mRenderer->sourceColorRamp() );
638 return mRenderer.get();
644 btnChangeCategorizedSymbol->setMapCanvas( context.
mapCanvas() );
645 btnChangeCategorizedSymbol->setMessageBar( context.
messageBar() );
650 QList<int> selectedCats = selectedCategories();
652 if ( !selectedCats.isEmpty() )
663 const auto constSelectedCats = selectedCats;
664 for (
int idx : constSelectedCats )
669 newCatSymbol->
setColor( mRenderer->categories()[idx].symbol()->color() );
670 mRenderer->updateCategorySymbol( idx, newCatSymbol );
678 std::unique_ptr<QgsSymbol> newSymbol( mCategorizedSymbol->clone() );
693 if ( !dlg.exec() || !newSymbol )
698 mCategorizedSymbol = std::move( newSymbol );
699 applyChangeToSymbol();
710 mRenderer->setClassAttribute(
field );
711 emit widgetChanged();
716 if ( idx.isValid() && idx.column() == 0 )
717 changeCategorySymbol();
724 std::unique_ptr< QgsSymbol > symbol;
726 if (
auto *lSymbol = category.
symbol() )
728 symbol.reset( lSymbol->clone() );
749 if ( !dlg.exec() || !symbol )
754 mCategorizedSymbol = std::move( symbol );
755 applyChangeToSymbol();
762 QString attrName = mExpressionWidget->currentField();
763 int idx = mLayer->fields().lookupField( attrName );
764 QList<QVariant> uniqueValues;
775 expression->
prepare( &context );
781 QVariant value = expression->
evaluate( &context );
782 if ( uniqueValues.contains( value ) )
784 uniqueValues << value;
789 uniqueValues = qgis::setToList( mLayer->uniqueValues( idx ) );
793 if ( uniqueValues.size() >= 1000 )
795 int res = QMessageBox::warning(
nullptr, tr(
"Classify Categories" ),
796 tr(
"High number of classes. Classification would yield %1 entries which might not be expected. Continue?" ).arg( uniqueValues.size() ),
797 QMessageBox::Ok | QMessageBox::Cancel,
798 QMessageBox::Cancel );
799 if ( res == QMessageBox::Cancel )
806 DlgAddCategories dlg( mStyle, createDefaultSymbol(), unique_vals,
this );
812 bool deleteExisting =
false;
814 if ( !mOldClassificationAttribute.isEmpty() &&
815 attrName != mOldClassificationAttribute &&
816 !mRenderer->categories().isEmpty() )
818 int res = QMessageBox::question(
this,
819 tr(
"Delete Classification" ),
820 tr(
"The classification field was changed from '%1' to '%2'.\n"
821 "Should the existing classes be deleted before classification?" )
822 .arg( mOldClassificationAttribute, attrName ),
823 QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel );
824 if ( res == QMessageBox::Cancel )
829 deleteExisting = ( res == QMessageBox::Yes );
833 bool keepExistingColors =
false;
834 if ( !deleteExisting )
837 keepExistingColors = !prevCats.isEmpty();
839 if ( keepExistingColors && btnColorRamp->isRandomColorRamp() )
841 for (
int i = 0; i < cats.size(); ++i )
843 bool contains =
false;
844 QVariant value = cats.at( i ).value();
845 for (
int j = 0; j < prevCats.size() && !contains; ++j )
847 const QVariant prevCatValue = prevCats.at( j ).value();
848 if ( prevCatValue.type() == QVariant::List )
850 const QVariantList list = prevCatValue.toList();
851 for (
const QVariant &v : list )
862 if ( prevCats.at( j ).value() == value )
873 if ( keepExistingColors && btnColorRamp->isRandomColorRamp() )
876 cats.at( i ).symbol()->setColor( randomColors.
color( i ) );
878 prevCats.append( cats.at( i ) );
884 mOldClassificationAttribute = attrName;
901 std::unique_ptr< QgsCategorizedSymbolRenderer > r = qgis::make_unique< QgsCategorizedSymbolRenderer >( attrName, cats );
902 r->setSourceSymbol( mCategorizedSymbol->clone() );
903 std::unique_ptr< QgsColorRamp > ramp( btnColorRamp->colorRamp() );
905 r->setSourceColorRamp( ramp->clone() );
909 mModel->setRenderer( r.get() );
911 mRenderer = std::move( r );
912 if ( ! keepExistingColors && ramp )
914 emit widgetChanged();
919 if ( !btnColorRamp->isNull() )
921 mRenderer->updateColorRamp( btnColorRamp->colorRamp() );
923 mModel->updateSymbology();
928 QModelIndex idx = viewCategories->selectionModel()->currentIndex();
929 if ( !idx.isValid() )
937 QModelIndexList selectedRows = viewCategories->selectionModel()->selectedRows();
939 const auto constSelectedRows = selectedRows;
940 for (
const QModelIndex &r : constSelectedRows )
944 rows.append( r.row() );
952 QList<int> categoryIndexes = selectedCategories();
953 mModel->deleteRows( categoryIndexes );
954 emit widgetChanged();
959 mModel->removeAllRows();
960 emit widgetChanged();
965 if ( !mModel )
return;
968 mModel->addCategory( cat );
969 emit widgetChanged();
974 QList<QgsSymbol *> selectedSymbols;
976 QItemSelectionModel *m = viewCategories->selectionModel();
977 QModelIndexList selectedIndexes = m->selectedRows( 1 );
979 if ( !selectedIndexes.isEmpty() )
982 QModelIndexList::const_iterator indexIt = selectedIndexes.constBegin();
983 for ( ; indexIt != selectedIndexes.constEnd(); ++indexIt )
985 int row = ( *indexIt ).row();
989 selectedSymbols.append( s );
993 return selectedSymbols;
1000 QItemSelectionModel *m = viewCategories->selectionModel();
1001 QModelIndexList selectedIndexes = m->selectedRows( 1 );
1003 if ( !selectedIndexes.isEmpty() )
1005 QModelIndexList::const_iterator indexIt = selectedIndexes.constBegin();
1006 for ( ; indexIt != selectedIndexes.constEnd(); ++indexIt )
1008 cl.append( mModel->category( *indexIt ) );
1016 populateCategories();
1017 emit widgetChanged();
1022 showSymbolLevelsDialog( mRenderer.get() );
1027 viewCategories->selectionModel()->clear();
1035 QMessageBox::information(
this, tr(
"Matched Symbols" ),
1036 tr(
"Matched %1 categories to symbols." ).arg( matched ) );
1040 QMessageBox::warning(
this, tr(
"Matched Symbols" ),
1041 tr(
"No categories could be matched to symbols in library." ) );
1047 if ( !mLayer || !style )
1054 QVariantList unmatchedCategories;
1055 QStringList unmatchedSymbols;
1056 const int matched = mRenderer->matchToSymbols( style, type, unmatchedCategories, unmatchedSymbols );
1058 mModel->updateSymbology();
1065 QString openFileDir = settings.
value( QStringLiteral(
"UI/lastMatchToSymbolsDir" ), QDir::homePath() ).toString();
1067 QString fileName = QFileDialog::getOpenFileName(
this, tr(
"Match to Symbols from File" ), openFileDir,
1068 tr(
"XML files (*.xml *.XML)" ) );
1069 if ( fileName.isEmpty() )
1074 QFileInfo openFileInfo( fileName );
1075 settings.
setValue( QStringLiteral(
"UI/lastMatchToSymbolsDir" ), openFileInfo.absolutePath() );
1078 if ( !importedStyle.
importXml( fileName ) )
1080 QMessageBox::warning(
this, tr(
"Match to Symbols from File" ),
1081 tr(
"An error occurred while reading file:\n%1" ).arg( importedStyle.
errorString() ) );
1085 int matched = matchToSymbols( &importedStyle );
1088 QMessageBox::information(
this, tr(
"Match to Symbols from File" ),
1089 tr(
"Matched %1 categories to symbols from file." ).arg( matched ) );
1093 QMessageBox::warning(
this, tr(
"Match to Symbols from File" ),
1094 tr(
"No categories could be matched to symbols in file." ) );
1104 const QList<int> selectedCats = selectedCategories();
1105 if ( !selectedCats.isEmpty() )
1107 for (
int idx : selectedCats )
1109 if ( mRenderer->categories().at( idx ).symbol()->type() != tempSymbol->type() )
1112 std::unique_ptr< QgsSymbol > newCatSymbol( tempSymbol->clone() );
1113 if ( selectedCats.count() > 1 )
1116 newCatSymbol->setColor( mRenderer->categories().at( idx ).symbol()->color() );
1118 mRenderer->updateCategorySymbol( idx, newCatSymbol.release() );
1120 emit widgetChanged();
1124 void QgsCategorizedSymbolRendererWidget::cleanUpSymbolSelector(
QgsPanelWidget *container )
1133 void QgsCategorizedSymbolRendererWidget::updateSymbolsFromWidget()
1136 mCategorizedSymbol.reset( dlg->
symbol()->
clone() );
1138 applyChangeToSymbol();
1141 void QgsCategorizedSymbolRendererWidget::updateSymbolsFromButton()
1143 mCategorizedSymbol.reset( btnChangeCategorizedSymbol->symbol()->clone() );
1145 applyChangeToSymbol();
1151 QItemSelectionModel *m = viewCategories->selectionModel();
1152 QModelIndexList i = m->selectedRows();
1156 QList<int> selectedCats = selectedCategories();
1158 if ( !selectedCats.isEmpty() )
1160 const auto constSelectedCats = selectedCats;
1161 for (
int idx : constSelectedCats )
1164 if ( selectedCats.count() > 1 )
1167 newCatSymbol->
setColor( mRenderer->categories().at( idx ).symbol()->color() );
1169 mRenderer->updateCategorySymbol( idx, newCatSymbol );
1175 mRenderer->updateSymbols( mCategorizedSymbol.get() );
1178 mModel->updateSymbology();
1179 emit widgetChanged();
1189 if ( event->key() == Qt::Key_C && event->modifiers() == Qt::ControlModifier )
1191 mCopyBuffer.clear();
1192 mCopyBuffer = selectedCategoryList();
1194 else if ( event->key() == Qt::Key_V && event->modifiers() == Qt::ControlModifier )
1196 QgsCategoryList::const_iterator rIt = mCopyBuffer.constBegin();
1197 for ( ; rIt != mCopyBuffer.constEnd(); ++rIt )
1199 mModel->addCategory( *rIt );
1211 if (
auto *lMapCanvas = mContext.mapCanvas() )
1217 expContext << generator->createExpressionContextScope();
1225 if (
auto *lVectorLayer = vectorLayer() )
1229 const auto constAdditionalExpressionContextScopes = mContext.additionalExpressionContextScopes();
1238 void QgsCategorizedSymbolRendererWidget::dataDefinedSizeLegend()
1241 QgsDataDefinedSizeLegendWidget *panel = createDataDefinedSizeLegendWidget( s, mRenderer->dataDefinedSizeLegend() );
1246 mRenderer->setDataDefinedSizeLegend( panel->dataDefinedSizeLegend() );
1247 emit widgetChanged();
1253 void QgsCategorizedSymbolRendererWidget::mergeSelectedCategories()
1257 QList<int> selectedCategoryIndexes = selectedCategories();
1258 QList< int > categoryIndexes;
1261 for (
int i : selectedCategoryIndexes )
1263 QVariant v = categories.at( i ).value();
1265 if ( !v.isValid() || v ==
"" )
1270 categoryIndexes.append( i );
1273 if ( categoryIndexes.count() < 2 )
1277 QVariantList values;
1278 values.reserve( categoryIndexes.count() );
1279 labels.reserve( categoryIndexes.count() );
1280 for (
int i : categoryIndexes )
1282 QVariant v = categories.at( i ).value();
1284 if ( v.type() == QVariant::List )
1286 values.append( v.toList() );
1291 labels << categories.at( i ).label();
1295 mRenderer->updateCategoryLabel( categoryIndexes.at( 0 ), labels.join(
',' ) );
1296 mRenderer->updateCategoryValue( categoryIndexes.at( 0 ), values );
1298 categoryIndexes.pop_front();
1299 mModel->deleteRows( categoryIndexes );
1301 emit widgetChanged();
1304 void QgsCategorizedSymbolRendererWidget::unmergeSelectedCategories()
1306 const QList<int> categoryIndexes = selectedCategories();
1307 if ( categoryIndexes.isEmpty() )
1311 for (
int i : categoryIndexes )
1313 const QVariant v = categories.at( i ).value();
1314 if ( v.type() != QVariant::List )
1317 const QVariantList list = v.toList();
1318 for (
int j = 1; j < list.count(); ++j )
1320 mModel->addCategory(
QgsRendererCategory( list.at( j ), categories.at( i ).symbol()->clone(), list.at( j ).toString(), categories.at( i ).renderState() ) );
1322 mRenderer->updateCategoryValue( i, list.at( 0 ) );
1323 mRenderer->updateCategoryLabel( i, list.at( 0 ).toString() );
1326 emit widgetChanged();
1329 void QgsCategorizedSymbolRendererWidget::showContextMenu( QPoint )
1331 mContextMenu->clear();
1332 const QList< QAction * > actions = contextMenu->actions();
1333 for ( QAction *act : actions )
1335 mContextMenu->addAction( act );
1338 mContextMenu->addSeparator();
1340 if ( viewCategories->selectionModel()->selectedRows().count() > 1 )
1342 mContextMenu->addAction( mMergeCategoriesAction );
1344 if ( viewCategories->selectionModel()->selectedRows().count() == 1 )
1346 const QList<int> categoryIndexes = selectedCategories();
1348 const QVariant v = categories.at( categoryIndexes.at( 0 ) ).value();
1349 if ( v.type() == QVariant::List )
1350 mContextMenu->addAction( mUnmergeCategoriesAction );
1352 else if ( viewCategories->selectionModel()->selectedRows().count() > 1 )
1354 mContextMenu->addAction( mUnmergeCategoriesAction );
1357 mContextMenu->exec( QCursor::pos() );
1360 void QgsCategorizedSymbolRendererWidget::selectionChanged(
const QItemSelection &,
const QItemSelection & )
1362 QList<int> selectedCats = selectedCategories();
1363 if ( !selectedCats.isEmpty() )
1365 whileBlocking( btnChangeCategorizedSymbol )->setSymbol( mRenderer->categories().at( selectedCats.at( 0 ) ).symbol()->clone() );
1367 else if ( mRenderer->sourceSymbol() )
1369 whileBlocking( btnChangeCategorizedSymbol )->setSymbol( mRenderer->sourceSymbol()->clone() );
1371 btnChangeCategorizedSymbol->setDialogTitle( selectedCats.size() == 1 ? mRenderer->categories().at( selectedCats.at( 0 ) ).label() : tr(
"Symbol Settings" ) );