QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
qgssymbollayerselectionwidget.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgssymbollayerselectionwidget.h
3 ---------------------
4 begin : July 2019
5 copyright : (C) 2019 by Hugo Mercier
6 email : hugo dot mercier at oslandia dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16#include <QTreeWidget>
17#include <QVBoxLayout>
18
20#include "qgsproject.h"
21#include "qgsvectorlayer.h"
22#include "qgslegendsymbolitem.h"
26#include "qgsguiutils.h"
27#include "qgslayertree.h"
28#include "qgslayertreelayer.h"
29
31 : QWidget( parent )
32{
33 mTree = new QTreeWidget( this );
34 mTree->setHeaderHidden( true );
35
36 connect( mTree, &QTreeWidget::itemChanged, this, [&]( QTreeWidgetItem *, int ) { emit this->changed(); } );
37
38 // place the tree in a layout
39 QVBoxLayout *vbox = new QVBoxLayout();
40 vbox->setContentsMargins( 0, 0, 0, 0 );
41 vbox->addWidget( mTree );
42
43 setLayout( vbox );
44}
45
47{
48 mLayer = layer;
49 mItems.clear();
50 mTree->clear();
51
52 class TreeFillVisitor : public QgsStyleEntityVisitorInterface
53 {
54 public:
55 TreeFillVisitor( QTreeWidgetItem *layerItem, const QgsVectorLayer *layer, QHash<QgsSymbolLayerId, QTreeWidgetItem *> &items ):
56 mLayerItem( layerItem ), mLayer( layer ), mItems( items )
57 {}
58
59 bool visitEnter( const QgsStyleEntityVisitorInterface::Node &node ) override
60 {
62 return false;
63
64 mCurrentIdentifier = node.identifier;
65 mCurrentDescription = node.description;
66
67 return true;
68 }
69
70 void visitSymbol( QTreeWidgetItem *rootItem, const QString &identifier, const QgsSymbol *symbol, QVector<int> rootPath )
71 {
72 for ( int idx = 0; idx < symbol->symbolLayerCount(); idx++ )
73 {
74 const QgsSymbolLayer *sl = symbol->symbolLayer( idx );
75 // Skip mask symbol layers. It makes no sense to take them as mask targets.
76 if ( sl->layerType() == "MaskMarker" )
77 continue;
78
79 const QgsSymbol *subSymbol = const_cast<QgsSymbolLayer *>( sl )->subSymbol();
80
81 QVector<int> indexPath = rootPath;
82 indexPath.append( idx );
83
84 QTreeWidgetItem *slItem = new QTreeWidgetItem();
86 slItem->setData( 0, Qt::UserRole, idx );
87 slItem->setIcon( 0, slIcon );
88 auto flags = slItem->flags();
89 if ( ! subSymbol || subSymbol->symbolLayerCount() == 0 )
90 {
91 flags.setFlag( Qt::ItemIsUserCheckable, true );
92 slItem->setCheckState( 0, Qt::Unchecked );
93 }
94 else
95 {
96 flags.setFlag( Qt::ItemIsUserCheckable, false );
97 }
98 slItem->setFlags( flags );
99 rootItem->addChild( slItem );
100 slItem->setExpanded( true );
101
102 mItems[QgsSymbolLayerId( mCurrentIdentifier + identifier, indexPath )] = slItem;
103
104 if ( subSymbol )
105 {
106 visitSymbol( slItem, identifier, subSymbol, indexPath );
107 }
108 }
109 }
110
111 bool visit( const QgsStyleEntityVisitorInterface::StyleLeaf &leaf ) override
112 {
113 if ( ! leaf.entity || leaf.entity->type() != QgsStyle::SymbolEntity )
114 return true;
115
116 const auto symbolEntity = static_cast<const QgsStyleSymbolEntity *>( leaf.entity );
117 const QgsSymbol *symbol = symbolEntity->symbol();
118 if ( ! symbol )
119 return true;
120
121 // either leaf.description or mCurrentDescription is defined
122 QTreeWidgetItem *symbolItem = new QTreeWidgetItem( QStringList() << ( mCurrentDescription + leaf.description ) );
123 const QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( symbol, QSize( iconSize, iconSize ) );
124 symbolItem->setData( 0, Qt::UserRole, mCurrentIdentifier );
125 symbolItem->setIcon( 0, icon );
126 mLayerItem->addChild( symbolItem );
127 symbolItem->setExpanded( true );
128
129 visitSymbol( symbolItem, leaf.identifier, symbol, {} );
130
131 return true;
132 }
133
134 const int iconSize = QgsGuiUtils::scaleIconSize( 16 );
135 QString mCurrentDescription;
136 QString mCurrentIdentifier;
137 QTreeWidgetItem *mLayerItem;
138 const QgsVectorLayer *mLayer;
139 QHash<QgsSymbolLayerId, QTreeWidgetItem *> &mItems;
140 };
141
142 // populate the tree
143 if ( ! mLayer )
144 return;
145 if ( ! mLayer->renderer() )
146 return;
147
148 TreeFillVisitor visitor( mTree->invisibleRootItem(), mLayer, mItems );
149 mLayer->renderer()->accept( &visitor );
150}
151
152QSet<QgsSymbolLayerId> QgsSymbolLayerSelectionWidget::selection() const
153{
154 QSet<QgsSymbolLayerId> sel;
155 for ( auto it = mItems.begin(); it != mItems.end(); it++ )
156 {
157 if ( it.value()->checkState( 0 ) == Qt::Checked )
158 sel.insert( it.key() );
159 }
160 return sel;
161}
162
163void QgsSymbolLayerSelectionWidget::setSelection( const QSet<QgsSymbolLayerId> &sel )
164{
165 // clear selection
166 for ( auto it = mItems.begin(); it != mItems.end(); it++ )
167 {
168 if ( it.value()->flags() & Qt::ItemIsUserCheckable )
169 it.value()->setCheckState( 0, Qt::Unchecked );
170 }
171
172 // apply selection passed in parameter
173 for ( const QgsSymbolLayerId &lid : sel )
174 {
175 const auto it = mItems.find( lid );
176 if ( it != mItems.end() )
177 ( *it )->setCheckState( 0, Qt::Checked );
178 }
179}
virtual bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified symbology visitor, causing it to visit all symbols associated with the renderer...
Struct for storing maximum and minimum scales for measurements in map units.
virtual QgsStyle::StyleEntity type() const =0
Returns the type of style entity.
An interface for classes which can visit style entity (e.g.
@ SymbolRule
Rule based symbology or label child rule.
A symbol entity for QgsStyle databases.
Definition: qgsstyle.h:1342
@ SymbolEntity
Symbols.
Definition: qgsstyle.h:180
We may need stable references to symbol layers, when pointers to symbol layers is not usable (when a ...
QgsSymbolLayerSelectionWidget(QWidget *parent=nullptr)
Default constructor.
QSet< QgsSymbolLayerId > selection() const
Returns current symbol layer selection.
void changed()
Signal emitted when something the configuration is changed.
void setLayer(const QgsVectorLayer *layer)
Populate the tree with selectable symbol layers from a given layer.
void setSelection(const QSet< QgsSymbolLayerId > &sel)
Sets the symbol layer selection.
static QIcon symbolLayerPreviewIcon(const QgsSymbolLayer *layer, QgsUnitTypes::RenderUnit u, QSize size, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::SymbolType parentSymbolType=Qgis::SymbolType::Hybrid, QgsMapLayer *mapLayer=nullptr)
Draws a symbol layer preview to an icon.
static QIcon symbolPreviewIcon(const QgsSymbol *symbol, QSize size, int padding=0, QgsLegendPatchShape *shape=nullptr)
Returns an icon preview for a color ramp.
virtual QString layerType() const =0
Returns a string that represents this layer type.
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:93
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
Definition: qgssymbol.cpp:756
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
Definition: qgssymbol.h:215
Qgis::SymbolType type() const
Returns the symbol's type.
Definition: qgssymbol.h:152
@ RenderMillimeters
Millimeters.
Definition: qgsunittypes.h:169
Represents a vector layer which manages a vector based data sets.
QgsFeatureRenderer * renderer()
Returns the feature renderer used for rendering the features in the layer in 2D map views.
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,...
Contains information relating to a node (i.e.
QString identifier
A string identifying the node.
QString description
A string describing the node.
QgsStyleEntityVisitorInterface::NodeType type
Node type.
Contains information relating to the style entity currently being visited.
QString description
A string describing the style entity.
const QgsStyleEntityInterface * entity
Reference to style entity being visited.
QString identifier
A string identifying the style entity.