QGIS API Documentation 3.28.14-Firenze (exported)
Loading...
Searching...
No Matches
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();
85 const QIcon slIcon = QgsSymbolLayerUtils::symbolLayerPreviewIcon( sl, QgsUnitTypes::RenderMillimeters, QSize( iconSize, iconSize ), QgsMapUnitScale(), symbol->type() );
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.
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.
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.
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.