41 #include "qgssettings.h" 
   47 #include <QMessageBox> 
   48 #include <QStandardItemModel> 
   49 #include <QStandardItem> 
   52 #include <QFileDialog> 
   57 QgsCategorizedSymbolRendererModel::QgsCategorizedSymbolRendererModel( QObject *parent ) : QAbstractItemModel( parent )
 
   58   , mMimeFormat( QStringLiteral( 
"application/x-qgscategorizedsymbolrendererv2model" ) )
 
   66     beginRemoveRows( QModelIndex(), 0, std::max( mRenderer->categories().size() - 1, 0 ) );
 
   75       beginInsertRows( QModelIndex(), 0, renderer->
categories().size() - 1 );
 
   83   if ( !mRenderer ) 
return;
 
   84   int idx = mRenderer->categories().size();
 
   85   beginInsertRows( QModelIndex(), idx, idx );
 
   86   mRenderer->addCategory( cat );
 
   97   int row = index.row();
 
   98   if ( row >= catList.size() )
 
  102   return catList.at( row );
 
  106 Qt::ItemFlags QgsCategorizedSymbolRendererModel::flags( 
const QModelIndex &index )
 const 
  108   if ( !index.isValid() || !mRenderer )
 
  110     return Qt::ItemIsDropEnabled;
 
  113   Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsUserCheckable;
 
  114   if ( index.column() == 1 )
 
  117     if ( category.
value().type() != QVariant::List )
 
  119       flags |= Qt::ItemIsEditable;
 
  122   else if ( index.column() == 2 )
 
  124     flags |= Qt::ItemIsEditable;
 
  129 Qt::DropActions QgsCategorizedSymbolRendererModel::supportedDropActions()
 const 
  131   return Qt::MoveAction;
 
  134 QVariant QgsCategorizedSymbolRendererModel::data( 
const QModelIndex &index, 
int role )
 const 
  136   if ( !index.isValid() || !mRenderer )
 
  143     case Qt::CheckStateRole:
 
  145       if ( index.column() == 0 )
 
  147         return category.
renderState() ? Qt::Checked : Qt::Unchecked;
 
  152     case Qt::DisplayRole:
 
  153     case Qt::ToolTipRole:
 
  155       switch ( index.column() )
 
  159           if ( category.
value().type() == QVariant::List )
 
  162             const QVariantList list = category.
value().toList();
 
  163             res.reserve( list.size() );
 
  164             for ( 
const QVariant &v : list )
 
  167             if ( role == Qt::DisplayRole )
 
  168               return res.join( 
';' );
 
  170               return res.join( 
'\n' );
 
  172           else if ( !category.
value().isValid() || category.
value().isNull() || category.
value().toString().isEmpty() )
 
  174             return tr( 
"all other values" );
 
  178             return category.
value().toString();
 
  182           return category.
label();
 
  189       if ( index.column() == 1 && category.
value().type() != QVariant::List && ( !category.
value().isValid() || category.
value().isNull() || category.
value().toString().isEmpty() ) )
 
  192         italicFont.setItalic( 
true );
 
  198     case Qt::DecorationRole:
 
  200       if ( index.column() == 0 && category.
symbol() )
 
  208     case Qt::ForegroundRole:
 
  210       QBrush brush( qApp->palette().color( QPalette::Text ), Qt::SolidPattern );
 
  211       if ( index.column() == 1 && ( category.
value().type() == QVariant::List
 
  212                                     || !category.
value().isValid() || category.
value().isNull() || category.
value().toString().isEmpty() ) )
 
  214         QColor fadedTextColor = brush.color();
 
  215         fadedTextColor.setAlpha( 128 );
 
  216         brush.setColor( fadedTextColor );
 
  221     case Qt::TextAlignmentRole:
 
  223       return ( index.column() == 0 ) ? Qt::AlignHCenter : Qt::AlignLeft;
 
  228       switch ( index.column() )
 
  232           if ( category.
value().type() == QVariant::List )
 
  235             const QVariantList list = category.
value().toList();
 
  236             res.reserve( list.size() );
 
  237             for ( 
const QVariant &v : list )
 
  240             return res.join( 
';' );
 
  244             return category.
value();
 
  249           return category.
label();
 
  258 bool QgsCategorizedSymbolRendererModel::setData( 
const QModelIndex &index, 
const QVariant &value, 
int role )
 
  260   if ( !index.isValid() )
 
  263   if ( index.column() == 0 && role == Qt::CheckStateRole )
 
  265     mRenderer->updateCategoryRenderState( index.row(), value == Qt::Checked );
 
  266     emit dataChanged( index, index );
 
  270   if ( role != Qt::EditRole )
 
  273   switch ( index.column() )
 
  279       switch ( mRenderer->categories().value( index.row() ).value().type() )
 
  284         case QVariant::Double:
 
  285           val = value.toDouble();
 
  289           const QStringList parts = value.toString().split( 
';' );
 
  291           list.reserve( parts.count() );
 
  292           for ( 
const QString &p : parts )
 
  295           if ( list.count() == 1 )
 
  302           val = value.toString();
 
  305       mRenderer->updateCategoryValue( index.row(), val );
 
  309       mRenderer->updateCategoryLabel( index.row(), value.toString() );
 
  315   emit dataChanged( index, index );
 
  319 QVariant QgsCategorizedSymbolRendererModel::headerData( 
int section, Qt::Orientation orientation, 
int role )
 const 
  321   if ( orientation == Qt::Horizontal && role == Qt::DisplayRole && section >= 0 && section < 3 )
 
  324     lst << tr( 
"Symbol" ) << tr( 
"Value" ) << tr( 
"Legend" );
 
  325     return lst.value( section );
 
  330 int QgsCategorizedSymbolRendererModel::rowCount( 
const QModelIndex &parent )
 const 
  332   if ( parent.isValid() || !mRenderer )
 
  336   return mRenderer->categories().size();
 
  339 int QgsCategorizedSymbolRendererModel::columnCount( 
const QModelIndex &index )
 const 
  345 QModelIndex QgsCategorizedSymbolRendererModel::index( 
int row, 
int column, 
const QModelIndex &parent )
 const 
  347   if ( hasIndex( row, column, parent ) )
 
  349     return createIndex( row, column );
 
  351   return QModelIndex();
 
  354 QModelIndex QgsCategorizedSymbolRendererModel::parent( 
const QModelIndex &index )
 const 
  357   return QModelIndex();
 
  360 QStringList QgsCategorizedSymbolRendererModel::mimeTypes()
 const 
  363   types << mMimeFormat;
 
  367 QMimeData *QgsCategorizedSymbolRendererModel::mimeData( 
const QModelIndexList &indexes )
 const 
  369   QMimeData *mimeData = 
new QMimeData();
 
  370   QByteArray encodedData;
 
  372   QDataStream stream( &encodedData, QIODevice::WriteOnly );
 
  375   const auto constIndexes = indexes;
 
  376   for ( 
const QModelIndex &index : constIndexes )
 
  378     if ( !index.isValid() || index.column() != 0 )
 
  381     stream << index.row();
 
  383   mimeData->setData( mMimeFormat, encodedData );
 
  387 bool QgsCategorizedSymbolRendererModel::dropMimeData( 
const QMimeData *data, Qt::DropAction action, 
int row, 
int column, 
const QModelIndex &parent )
 
  391   if ( action != Qt::MoveAction ) 
return true;
 
  393   if ( !data->hasFormat( mMimeFormat ) ) 
return false;
 
  395   QByteArray encodedData = data->data( mMimeFormat );
 
  396   QDataStream stream( &encodedData, QIODevice::ReadOnly );
 
  399   while ( !stream.atEnd() )
 
  406   int to = parent.row();
 
  409   if ( to == -1 ) to = mRenderer->categories().size(); 
 
  410   for ( 
int i = rows.size() - 1; i >= 0; i-- )
 
  412     QgsDebugMsg( QStringLiteral( 
"move %1 to %2" ).arg( rows[i] ).arg( to ) );
 
  415     if ( rows[i] < t ) t--;
 
  416     mRenderer->moveCategory( rows[i], t );
 
  418     for ( 
int j = 0; j < i; j++ )
 
  420       if ( to < rows[j] && rows[i] > rows[j] ) rows[j] += 1;
 
  423     if ( rows[i] < to ) to--;
 
  425   emit dataChanged( createIndex( 0, 0 ), createIndex( mRenderer->categories().size(), 0 ) );
 
  430 void QgsCategorizedSymbolRendererModel::deleteRows( QList<int> rows )
 
  432   std::sort( rows.begin(), rows.end() ); 
 
  433   for ( 
int i = rows.size() - 1; i >= 0; i-- )
 
  435     beginRemoveRows( QModelIndex(), rows[i], rows[i] );
 
  436     mRenderer->deleteCategory( rows[i] );
 
  441 void QgsCategorizedSymbolRendererModel::removeAllRows()
 
  443   beginRemoveRows( QModelIndex(), 0, mRenderer->categories().size() - 1 );
 
  444   mRenderer->deleteAllCategories();
 
  448 void QgsCategorizedSymbolRendererModel::sort( 
int column, Qt::SortOrder order )
 
  456     mRenderer->sortByValue( order );
 
  458   else if ( column == 2 )
 
  460     mRenderer->sortByLabel( order );
 
  462   emit dataChanged( createIndex( 0, 0 ), createIndex( mRenderer->categories().size(), 0 ) );
 
  465 void QgsCategorizedSymbolRendererModel::updateSymbology()
 
  467   emit dataChanged( createIndex( 0, 0 ), createIndex( mRenderer->categories().size(), 0 ) );
 
  471 QgsCategorizedSymbolRendererViewStyle::QgsCategorizedSymbolRendererViewStyle( QWidget *parent )
 
  475 void QgsCategorizedSymbolRendererViewStyle::drawPrimitive( PrimitiveElement element, 
const QStyleOption *option, QPainter *painter, 
const QWidget *widget )
 const 
  477   if ( element == QStyle::PE_IndicatorItemViewItemDrop && !option->rect.isNull() )
 
  479     QStyleOption opt( *option );
 
  480     opt.rect.setLeft( 0 );
 
  482     opt.rect.setHeight( 0 );
 
  483     if ( widget ) opt.rect.setRight( widget->width() );
 
  484     QProxyStyle::drawPrimitive( element, &opt, painter, widget );
 
  487   QProxyStyle::drawPrimitive( element, option, painter, widget );
 
  500   , mContextMenu( new QMenu( this ) )
 
  514   QString attrName = 
mRenderer->classAttribute();
 
  515   mOldClassificationAttribute = attrName;
 
  519   layout()->setContentsMargins( 0, 0, 0, 0 );
 
  521   mExpressionWidget->setLayer( 
mLayer );
 
  522   btnChangeCategorizedSymbol->setLayer( 
mLayer );
 
  523   btnChangeCategorizedSymbol->registerExpressionContextGenerator( 
this );
 
  526   btnColorRamp->setShowRandomColorRamp( 
true );
 
  529   QString defaultColorRamp = 
QgsProject::instance()->
readEntry( QStringLiteral( 
"DefaultStyles" ), QStringLiteral( 
"/ColorRamp" ), QString() );
 
  530   if ( !defaultColorRamp.isEmpty() )
 
  532     btnColorRamp->setColorRampFromName( defaultColorRamp );
 
  536     btnColorRamp->setRandomColorRamp();
 
  546   mModel = 
new QgsCategorizedSymbolRendererModel( 
this );
 
  552   viewCategories->setModel( 
mModel );
 
  553   viewCategories->resizeColumnToContents( 0 );
 
  554   viewCategories->resizeColumnToContents( 1 );
 
  555   viewCategories->resizeColumnToContents( 2 );
 
  557   viewCategories->setStyle( 
new QgsCategorizedSymbolRendererViewStyle( viewCategories ) );
 
  558   connect( viewCategories->selectionModel(), &QItemSelectionModel::selectionChanged, 
this, &QgsCategorizedSymbolRendererWidget::selectionChanged );
 
  566   connect( viewCategories, &QTreeView::customContextMenuRequested, 
this, &QgsCategorizedSymbolRendererWidget::showContextMenu );
 
  568   connect( btnChangeCategorizedSymbol, &
QgsSymbolButton::changed, 
this, &QgsCategorizedSymbolRendererWidget::updateSymbolsFromButton );
 
  578   QMenu *advMenu = 
new QMenu;
 
  585     QAction *actionDdsLegend = advMenu->addAction( tr( 
"Data-defined Size Legend…" ) );
 
  587     connect( actionDdsLegend, &QAction::triggered, 
this, &QgsCategorizedSymbolRendererWidget::dataDefinedSizeLegend );
 
  590   btnAdvanced->setMenu( advMenu );
 
  592   mExpressionWidget->registerExpressionContextGenerator( 
this );
 
  594   mMergeCategoriesAction = 
new QAction( tr( 
"Merge Categories" ), 
this );
 
  595   connect( mMergeCategoriesAction, &QAction::triggered, 
this, &QgsCategorizedSymbolRendererWidget::mergeSelectedCategories );
 
  596   mUnmergeCategoriesAction = 
new QAction( tr( 
"Unmerge Categories" ), 
this );
 
  597   connect( mUnmergeCategoriesAction, &QAction::triggered, 
this, &QgsCategorizedSymbolRendererWidget::unmergeSelectedCategories );
 
  599   connect( mContextMenu, &QMenu::aboutToShow, 
this, [ = ]
 
  620   QString attrName = 
mRenderer->classAttribute();
 
  621   mExpressionWidget->setField( attrName );
 
  633     btnColorRamp->setColorRamp( 
mRenderer->sourceColorRamp() );
 
  651   delete mActionLevels;
 
  652   mActionLevels = 
nullptr;
 
  659   if ( !selectedCats.isEmpty() )
 
  670     const auto constSelectedCats = selectedCats;
 
  671     for ( 
int idx : constSelectedCats )
 
  677       mRenderer->updateCategorySymbol( idx, newCatSymbol );
 
  700     if ( !dlg.exec() || !newSymbol )
 
  723   if ( idx.isValid() && idx.column() == 0 )
 
  731   std::unique_ptr< QgsSymbol > symbol;
 
  733   if ( 
auto *lSymbol = category.
symbol() )
 
  735     symbol.reset( lSymbol->clone() );
 
  756     if ( !dlg.exec() || !symbol )
 
  769   QString attrName = mExpressionWidget->currentField();
 
  771   QList<QVariant> uniqueValues;
 
  789       if ( uniqueValues.contains( value ) )
 
  791       uniqueValues << value;
 
  800   if ( uniqueValues.size() >= 1000 )
 
  802     int res = QMessageBox::warning( 
nullptr, tr( 
"Classify Categories" ),
 
  803                                     tr( 
"High number of classes. Classification would yield %1 entries which might not be expected. Continue?" ).arg( uniqueValues.size() ),
 
  804                                     QMessageBox::Ok | QMessageBox::Cancel,
 
  805                                     QMessageBox::Cancel );
 
  806     if ( res == QMessageBox::Cancel )
 
  813   DlgAddCategories dlg( 
mStyle, createDefaultSymbol(), unique_vals, 
this );
 
  819   bool deleteExisting = 
false;
 
  821   if ( !mOldClassificationAttribute.isEmpty() &&
 
  822        attrName != mOldClassificationAttribute &&
 
  825     int res = QMessageBox::question( 
this,
 
  826                                      tr( 
"Delete Classification" ),
 
  827                                      tr( 
"The classification field was changed from '%1' to '%2'.\n" 
  828                                          "Should the existing classes be deleted before classification?" )
 
  829                                      .arg( mOldClassificationAttribute, attrName ),
 
  830                                      QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel );
 
  831     if ( res == QMessageBox::Cancel )
 
  836     deleteExisting = ( res == QMessageBox::Yes );
 
  840   bool keepExistingColors = 
false;
 
  841   if ( !deleteExisting )
 
  844     keepExistingColors = !prevCats.isEmpty();
 
  846     if ( keepExistingColors && btnColorRamp->isRandomColorRamp() )
 
  848     for ( 
int i = 0; i < cats.size(); ++i )
 
  850       bool contains = 
false;
 
  851       QVariant value = cats.at( i ).value();
 
  852       for ( 
int j = 0; j < prevCats.size() && !contains; ++j )
 
  854         const QVariant prevCatValue = prevCats.at( j ).value();
 
  855         if ( prevCatValue.type() == QVariant::List )
 
  857           const QVariantList list = prevCatValue.toList();
 
  858           for ( 
const QVariant &v : list )
 
  869           if ( prevCats.at( j ).value() == value )
 
  880         if ( keepExistingColors && btnColorRamp->isRandomColorRamp() )
 
  883           cats.at( i ).symbol()->setColor( randomColors.
color( i ) );
 
  885         prevCats.append( cats.at( i ) );
 
  891   mOldClassificationAttribute = attrName;
 
  908   std::unique_ptr< QgsCategorizedSymbolRenderer > r = std::make_unique< QgsCategorizedSymbolRenderer >( attrName, cats );
 
  910   std::unique_ptr< QgsColorRamp > ramp( btnColorRamp->colorRamp() );
 
  912     r->setSourceColorRamp( ramp->clone() );
 
  916     mModel->setRenderer( r.get() );
 
  919   if ( ! keepExistingColors && ramp )
 
  926   if ( !btnColorRamp->isNull() )
 
  928     mRenderer->updateColorRamp( btnColorRamp->colorRamp() );
 
  930   mModel->updateSymbology();
 
  935   QModelIndex idx = viewCategories->selectionModel()->currentIndex();
 
  936   if ( !idx.isValid() )
 
  944   QModelIndexList selectedRows = viewCategories->selectionModel()->selectedRows();
 
  946   const auto constSelectedRows = selectedRows;
 
  947   for ( 
const QModelIndex &r : constSelectedRows )
 
  951       rows.append( r.row() );
 
  960   mModel->deleteRows( categoryIndexes );
 
  975   mModel->addCategory( cat );
 
  983   QItemSelectionModel *m = viewCategories->selectionModel();
 
  984   QModelIndexList selectedIndexes = m->selectedRows( 1 );
 
  986   if ( !selectedIndexes.isEmpty() )
 
  989     QModelIndexList::const_iterator indexIt = selectedIndexes.constBegin();
 
  990     for ( ; indexIt != selectedIndexes.constEnd(); ++indexIt )
 
  992       int row = ( *indexIt ).row();
 
 1007   QItemSelectionModel *m = viewCategories->selectionModel();
 
 1008   QModelIndexList selectedIndexes = m->selectedRows( 1 );
 
 1010   if ( !selectedIndexes.isEmpty() )
 
 1012     QModelIndexList::const_iterator indexIt = selectedIndexes.constBegin();
 
 1013     for ( ; indexIt != selectedIndexes.constEnd(); ++indexIt )
 
 1015       cl.append( 
mModel->category( *indexIt ) );
 
 1034   viewCategories->selectionModel()->clear();
 
 1042     QMessageBox::information( 
this, tr( 
"Matched Symbols" ),
 
 1043                               tr( 
"Matched %1 categories to symbols." ).arg( matched ) );
 
 1047     QMessageBox::warning( 
this, tr( 
"Matched Symbols" ),
 
 1048                           tr( 
"No categories could be matched to symbols in library." ) );
 
 1061   QVariantList unmatchedCategories;
 
 1062   QStringList unmatchedSymbols;
 
 1063   const int matched = 
mRenderer->matchToSymbols( style, type, unmatchedCategories, unmatchedSymbols );
 
 1065   mModel->updateSymbology();
 
 1071   QgsSettings settings;
 
 1072   QString openFileDir = settings.value( QStringLiteral( 
"UI/lastMatchToSymbolsDir" ), QDir::homePath() ).toString();
 
 1074   QString fileName = QFileDialog::getOpenFileName( 
this, tr( 
"Match to Symbols from File" ), openFileDir,
 
 1075                      tr( 
"XML files (*.xml *.XML)" ) );
 
 1076   if ( fileName.isEmpty() )
 
 1081   QFileInfo openFileInfo( fileName );
 
 1082   settings.setValue( QStringLiteral( 
"UI/lastMatchToSymbolsDir" ), openFileInfo.absolutePath() );
 
 1085   if ( !importedStyle.
importXml( fileName ) )
 
 1087     QMessageBox::warning( 
this, tr( 
"Match to Symbols from File" ),
 
 1088                           tr( 
"An error occurred while reading file:\n%1" ).arg( importedStyle.
errorString() ) );
 
 1095     QMessageBox::information( 
this, tr( 
"Match to Symbols from File" ),
 
 1096                               tr( 
"Matched %1 categories to symbols from file." ).arg( matched ) );
 
 1100     QMessageBox::warning( 
this, tr( 
"Match to Symbols from File" ),
 
 1101                           tr( 
"No categories could be matched to symbols in file." ) );
 
 1112       mRenderer->setLegendSymbolItem( legendSymbol.ruleKey(), sym->
clone() );
 
 1115   mRenderer->setUsingSymbolLevels( enabled );
 
 1116   mModel->updateSymbology();
 
 1127   if ( !selectedCats.isEmpty() )
 
 1129     for ( 
int idx : selectedCats )
 
 1131       if ( 
mRenderer->categories().at( idx ).symbol()->type() != tempSymbol->type() )
 
 1134       std::unique_ptr< QgsSymbol > newCatSymbol( tempSymbol->clone() );
 
 1135       if ( selectedCats.count() > 1 )
 
 1138         newCatSymbol->setColor( 
mRenderer->categories().at( idx ).symbol()->color() );
 
 1140       mRenderer->updateCategorySymbol( idx, newCatSymbol.release() );
 
 1146 void QgsCategorizedSymbolRendererWidget::cleanUpSymbolSelector( 
QgsPanelWidget *container )
 
 1155 void QgsCategorizedSymbolRendererWidget::updateSymbolsFromWidget()
 
 1163 void QgsCategorizedSymbolRendererWidget::updateSymbolsFromButton()
 
 1173   QItemSelectionModel *m = viewCategories->selectionModel();
 
 1174   QModelIndexList i = m->selectedRows();
 
 1180     if ( !selectedCats.isEmpty() )
 
 1182       const auto constSelectedCats = selectedCats;
 
 1183       for ( 
int idx : constSelectedCats )
 
 1186         if ( selectedCats.count() > 1 )
 
 1191         mRenderer->updateCategorySymbol( idx, newCatSymbol );
 
 1200   mModel->updateSymbology();
 
 1211   if ( event->key() == Qt::Key_C && event->modifiers() == Qt::ControlModifier )
 
 1213     mCopyBuffer.clear();
 
 1216   else if ( event->key() == Qt::Key_V && event->modifiers() == Qt::ControlModifier )
 
 1218     QgsCategoryList::const_iterator rIt = mCopyBuffer.constBegin();
 
 1219     for ( ; rIt != mCopyBuffer.constEnd(); ++rIt )
 
 1221       mModel->addCategory( *rIt );
 
 1239       expContext << generator->createExpressionContextScope();
 
 1260 void QgsCategorizedSymbolRendererWidget::dataDefinedSizeLegend()
 
 1275 void QgsCategorizedSymbolRendererWidget::mergeSelectedCategories()
 
 1280   QList< int > categoryIndexes;
 
 1283   for ( 
int i : selectedCategoryIndexes )
 
 1285     QVariant v = categories.at( i ).value();
 
 1287     if ( !v.isValid() || v == 
"" )
 
 1292     categoryIndexes.append( i );
 
 1295   if ( categoryIndexes.count() < 2 )
 
 1299   QVariantList values;
 
 1300   values.reserve( categoryIndexes.count() );
 
 1301   labels.reserve( categoryIndexes.count() );
 
 1302   for ( 
int i : categoryIndexes )
 
 1304     QVariant v = categories.at( i ).value();
 
 1306     if ( v.type() == QVariant::List )
 
 1308       values.append( v.toList() );
 
 1313     labels << categories.at( i ).label();
 
 1317   mRenderer->updateCategoryLabel( categoryIndexes.at( 0 ), labels.join( 
',' ) );
 
 1318   mRenderer->updateCategoryValue( categoryIndexes.at( 0 ), values );
 
 1320   categoryIndexes.pop_front();
 
 1321   mModel->deleteRows( categoryIndexes );
 
 1326 void QgsCategorizedSymbolRendererWidget::unmergeSelectedCategories()
 
 1329   if ( categoryIndexes.isEmpty() )
 
 1333   for ( 
int i : categoryIndexes )
 
 1335     const QVariant v = categories.at( i ).value();
 
 1336     if ( v.type() != QVariant::List )
 
 1339     const QVariantList list = v.toList();
 
 1340     for ( 
int j = 1; j < list.count(); ++j )
 
 1342       mModel->addCategory( 
QgsRendererCategory( list.at( j ), categories.at( i ).symbol()->clone(), list.at( j ).toString(), categories.at( i ).renderState() ) );
 
 1344     mRenderer->updateCategoryValue( i, list.at( 0 ) );
 
 1345     mRenderer->updateCategoryLabel( i, list.at( 0 ).toString() );
 
 1351 void QgsCategorizedSymbolRendererWidget::showContextMenu( QPoint )
 
 1353   mContextMenu->clear();
 
 1354   const QList< QAction * > actions = 
contextMenu->actions();
 
 1355   for ( QAction *act : actions )
 
 1357     mContextMenu->addAction( act );
 
 1360   mContextMenu->addSeparator();
 
 1362   if ( viewCategories->selectionModel()->selectedRows().count() > 1 )
 
 1364     mContextMenu->addAction( mMergeCategoriesAction );
 
 1366   if ( viewCategories->selectionModel()->selectedRows().count() == 1 )
 
 1370     const QVariant v = categories.at( categoryIndexes.at( 0 ) ).value();
 
 1371     if ( v.type() == QVariant::List )
 
 1372       mContextMenu->addAction( mUnmergeCategoriesAction );
 
 1374   else if ( viewCategories->selectionModel()->selectedRows().count() > 1 )
 
 1376     mContextMenu->addAction( mUnmergeCategoriesAction );
 
 1379   mContextMenu->exec( QCursor::pos() );
 
 1382 void QgsCategorizedSymbolRendererWidget::selectionChanged( 
const QItemSelection &, 
const QItemSelection & )
 
 1385   if ( !selectedCats.isEmpty() )
 
 1387     whileBlocking( btnChangeCategorizedSymbol )->setSymbol( 
mRenderer->categories().at( selectedCats.at( 0 ) ).symbol()->clone() );
 
 1393   btnChangeCategorizedSymbol->setDialogTitle( selectedCats.size() == 1 ? 
mRenderer->categories().at( selectedCats.at( 0 ) ).label() : tr( 
"Symbol Settings" ) );
 
const QgsCategoryList & categories() const
Returns a list of all categories recognized by the renderer.
static QgsCategorizedSymbolRenderer * convertFromRenderer(const QgsFeatureRenderer *renderer, QgsVectorLayer *layer=nullptr)
Creates a new QgsCategorizedSymbolRenderer from an existing renderer.
static QgsCategoryList createCategories(const QVariantList &values, const QgsSymbol *symbol, QgsVectorLayer *layer=nullptr, const QString &fieldName=QString())
Create categories for a list of values.
Abstract interface for generating an expression context scope.
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.
Class for parsing and evaluation of expressions (formerly called "search strings").
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
QVariant evaluate()
Evaluate the feature and return the result.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
The class stores information about one class/rule of a vector layer renderer in a unified way that ca...
The QgsMapSettings class contains configuration for rendering of the map.
A marker symbol type, for rendering Point and MultiPoint geometries.
static QgsProject * instance()
Returns the QgsProject singleton instance.
QString readEntry(const QString &scope, const QString &key, const QString &def=QString(), bool *ok=nullptr) const
Reads a string from the specified scope and key.
A QProxyStyle subclass which correctly sets the base style to match the QGIS application style,...
Totally random color ramp.
virtual void setTotalColorCount(int colorCount)
Sets the desired total number of unique colors for the resultant ramp.
QColor color(double value) const override
Returns the color corresponding to a specified value.
Represents an individual category (class) from a QgsCategorizedSymbolRenderer.
QgsSymbol * symbol() const
Returns the symbol which will be used to render this category.
bool renderState() const
Returns true if the category is currently enabled and should be rendered.
QVariant value() const
Returns the value corresponding to this category.
QString label() const
Returns the label for this category, which is used to represent the category within legends and the l...
QString errorString()
Returns last error from load/save operation.
static QgsStyle * defaultStyle()
Returns default application-wide style.
bool importXml(const QString &filename)
Imports the symbols and colorramps into the default style database from the given XML file.
static 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)
Returns an icon preview for a color ramp.
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.
static QgsSymbol * defaultSymbol(QgsWkbTypes::GeometryType geomType)
Returns a new default symbol for the specified geometry type.
void setColor(const QColor &color)
Sets the color for the symbol.
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
Represents a vector layer which manages a vector based data sets.
Q_INVOKABLE QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
QSet< QVariant > uniqueValues(int fieldIndex, int limit=-1) const FINAL
Calculates a list of unique values contained within an attribute in the layer.
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,...
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
QList< QgsRendererCategory > QgsCategoryList
QList< QgsLegendSymbolItem > QgsLegendSymbolList