QGIS API Documentation 4.1.0-Master (5bf3c20f3c9)
Loading...
Searching...
No Matches
qgsmasksourceselectionwidget.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmasksourceselectionwidget.cpp
3 ---------------------
4 begin : September 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
17
18#include "qgsguiutils.h"
19#include "qgslayertree.h"
20#include "qgslayertreelayer.h"
21#include "qgsnewnamedialog.h"
22#include "qgsproject.h"
23#include "qgsrenderer.h"
29#include "qgssymbollayerutils.h"
30#include "qgsvectorlayer.h"
32
33#include <QAction>
34#include <QComboBox>
35#include <QInputDialog>
36#include <QLabel>
37#include <QMenu>
38#include <QMessageBox>
39#include <QPointer>
40#include <QScreen>
41#include <QString>
42#include <QToolButton>
43#include <QTreeWidget>
44#include <QVBoxLayout>
45
46#include "moc_qgsmasksourceselectionwidget.cpp"
47
48using namespace Qt::StringLiterals;
49
50static void expandAll( QTreeWidgetItem *item )
51{
52 for ( int i = 0; i < item->childCount(); i++ )
53 expandAll( item->child( i ) );
54 item->setExpanded( true );
55}
56
58{
59 std::cout << ref.layerId().toLocal8Bit().constData() << "/" << ref.symbolLayerIdV2().toLocal8Bit().constData();
60}
61
63 : QWidget( parent )
64{
65 QVBoxLayout *vbox = new QVBoxLayout();
66 vbox->setContentsMargins( 0, 0, 0, 0 );
67
68 QHBoxLayout *hLayout = new QHBoxLayout();
69
70 mSetComboBox = new QComboBox();
71 mManagerModel = new QgsSelectiveMaskingSourceSetManagerModel( QgsProject::instance()->selectiveMaskingSourceSetManager(), this );
72 mManagerModel->setAllowEmptyObject( true );
73 mManagerProxyModel = new QgsSelectiveMaskingSourceSetManagerProxyModel( this );
74 mManagerProxyModel->setSourceModel( mManagerModel );
75 mSetComboBox->setModel( mManagerProxyModel );
76 connect( mSetComboBox, qOverload< int >( &QComboBox::currentIndexChanged ), this, &QgsMaskSourceSelectionWidget::selectedSetChanged );
77
78 mSetsToolButton = new QToolButton();
79 mSetsToolButton->setText( u"…"_s );
80 mSetsToolButton->setPopupMode( QToolButton::InstantPopup );
81
82 QMenu *toolMenu = new QMenu( mSetsToolButton );
83 connect( toolMenu, &QMenu::aboutToShow, this, [this] {
84 const bool isCustomSelected = isCustomSet();
85 mRemoveAction->setEnabled( !isCustomSelected );
86 mRenameAction->setEnabled( !isCustomSelected );
87 } );
88 QAction *addAction = new QAction( tr( "New Selective Masking Set…" ), toolMenu );
89 connect( addAction, &QAction::triggered, this, &QgsMaskSourceSelectionWidget::newSet );
90 toolMenu->addAction( addAction );
91 mRemoveAction = new QAction( tr( "Remove Set…" ), toolMenu );
92 connect( mRemoveAction, &QAction::triggered, this, &QgsMaskSourceSelectionWidget::removeSet );
93 toolMenu->addAction( mRemoveAction );
94 mRenameAction = new QAction( tr( "Rename Set…" ), toolMenu );
95 connect( mRenameAction, &QAction::triggered, this, &QgsMaskSourceSelectionWidget::renameSet );
96 toolMenu->addAction( mRenameAction );
97 mSetsToolButton->setMenu( toolMenu );
98
99 hLayout->addWidget( new QLabel( tr( "Preset" ) ) );
100 hLayout->addWidget( mSetComboBox, 1 );
101 hLayout->addWidget( mSetsToolButton, 1 );
102 vbox->addLayout( hLayout );
103
104 mTree = new QTreeWidget( this );
105 mTree->setHeaderHidden( true );
106
107 connect( mTree, &QTreeWidget::itemChanged, this, &QgsMaskSourceSelectionWidget::onItemChanged );
108
109 vbox->addWidget( mTree, 1 );
110
111 setLayout( vbox );
112}
113
115{
116 mBlockChangedSignals++;
117 mTree->clear();
118 mItems.clear();
119
120 class SymbolLayerFillVisitor : public QgsStyleEntityVisitorInterface
121 {
122 public:
123 SymbolLayerFillVisitor( QTreeWidgetItem *layerItem, const QgsVectorLayer *layer, QHash<QgsSymbolLayerReference, QTreeWidgetItem *> &items, QScreen *screen )
124 : mLayerItem( layerItem )
125 , mLayer( layer )
126 , mItems( items )
127 , mScreen( screen )
128 {}
129
130 bool visitEnter( const QgsStyleEntityVisitorInterface::Node &node ) override
131 {
133 return false;
134
135 mCurrentDescription = node.description;
136
137 return true;
138 }
139
140 struct TreeNode
141 {
142 TreeNode( const QgsSymbol *_symbol, const QgsSymbolLayer *_sl = nullptr )
143 : sl( _sl )
144 , symbol( _symbol ) {};
145
146 const QgsSymbolLayer *sl = nullptr;
147 const QgsSymbol *symbol = nullptr;
148 QList<TreeNode> children;
149 };
150
151
152 bool visitSymbol( TreeNode &parent, const QString &identifier, const QgsSymbol *symbol, QVector<int> rootPath )
153 {
154 bool ret = false;
155 for ( int idx = 0; idx < symbol->symbolLayerCount(); idx++ )
156 {
157 QgsSymbolLayer *sl = const_cast<QgsSymbol *>( symbol )->symbolLayer( idx );
158 QgsSymbol *subSymbol = sl->subSymbol();
159
160 QVector<int> indexPath = rootPath;
161 indexPath.append( idx );
162
163 TreeNode node( symbol, sl );
164 if ( ( sl->layerType() == "MaskMarker" ) || ( subSymbol && visitSymbol( node, identifier, subSymbol, indexPath ) ) )
165 {
166 ret = true;
167 parent.children << node;
168 }
169 }
170 return ret;
171 }
172
173 bool visit( const QgsStyleEntityVisitorInterface::StyleLeaf &leaf ) override
174 {
175 if ( !leaf.entity || leaf.entity->type() != QgsStyle::SymbolEntity )
176 return true;
177
178 const auto symbolEntity = static_cast<const QgsStyleSymbolEntity *>( leaf.entity );
179 const QgsSymbol *symbol = symbolEntity->symbol();
180 if ( !symbol )
181 return true;
182
183 TreeNode node( symbol );
184 if ( visitSymbol( node, leaf.identifier, symbol, {} ) )
185 createItems( leaf.description, mLayerItem, node );
186
187 return true;
188 }
189
190 void createItems( const QString &leafDescription, QTreeWidgetItem *rootItem, const TreeNode &node )
191 {
192 QTreeWidgetItem *item = nullptr;
193 // root symbol node
194 if ( !node.sl )
195 {
196 item = new QTreeWidgetItem( rootItem, QStringList() << ( mCurrentDescription + leafDescription ) );
197 const QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( node.symbol, QSize( iconSize, iconSize ), 0, nullptr, QgsScreenProperties( mScreen.data() ) );
198 item->setIcon( 0, icon );
199 }
200 // symbol layer node
201 else
202 {
203 item = new QTreeWidgetItem( rootItem );
204 const QIcon slIcon = QgsSymbolLayerUtils::
205 symbolLayerPreviewIcon( node.sl, Qgis::RenderUnit::Millimeters, QSize( iconSize, iconSize ), QgsMapUnitScale(), node.symbol->type(), nullptr, QgsScreenProperties( mScreen.data() ) );
206 item->setIcon( 0, slIcon );
207 if ( node.sl->layerType() == "MaskMarker" )
208 {
209 item->setText( 0, QObject::tr( "Mask symbol layer" ) );
210 item->setFlags( item->flags() | Qt::ItemIsUserCheckable );
211 item->setCheckState( 0, Qt::Unchecked );
212
213 const QgsSymbolLayerReference ref( mLayer->id(), node.sl->id() );
214 mItems[ref] = item;
215 }
216 }
217
218 rootItem->addChild( item );
219
220 for ( TreeNode child : node.children )
221 createItems( leafDescription, item, child );
222 };
223
224 const int iconSize = QgsGuiUtils::scaleIconSize( 16 );
225 QString mCurrentDescription;
226 QTreeWidgetItem *mLayerItem;
227 const QgsVectorLayer *mLayer;
228 QHash<QgsSymbolLayerReference, QTreeWidgetItem *> &mItems;
229 QPointer<QScreen> mScreen;
230 };
231
232 class LabelMasksVisitor : public QgsStyleEntityVisitorInterface
233 {
234 public:
235 LabelMasksVisitor( QTreeWidgetItem *layerItem, const QgsVectorLayer *layer, QHash<QgsSymbolLayerReference, QTreeWidgetItem *> &items )
236 : mLayerItem( layerItem )
237 , mLayer( layer )
238 , mItems( items )
239 {}
240 bool visitEnter( const QgsStyleEntityVisitorInterface::Node &node ) override
241 {
243 {
244 currentRule = node.identifier;
245 currentDescription = node.description;
246 return true;
247 }
248 return false;
249 }
250 bool visit( const QgsStyleEntityVisitorInterface::StyleLeaf &leaf ) override
251 {
252 if ( leaf.entity && leaf.entity->type() == QgsStyle::LabelSettingsEntity )
253 {
254 auto labelSettingsEntity = static_cast<const QgsStyleLabelSettingsEntity *>( leaf.entity );
255 if ( labelSettingsEntity->settings().format().mask().enabled() )
256 {
257 const QString maskTitle = currentRule.isEmpty() ? QObject::tr( "Label mask" ) : QObject::tr( "Label mask for '%1' rule" ).arg( currentDescription );
258 QTreeWidgetItem *slItem = new QTreeWidgetItem( mLayerItem, QStringList() << maskTitle );
259 slItem->setFlags( slItem->flags() | Qt::ItemIsUserCheckable );
260 slItem->setCheckState( 0, Qt::Unchecked );
261 mLayerItem->addChild( slItem );
262 mItems[QgsSymbolLayerReference( "__labels__" + mLayer->id(), currentRule )] = slItem;
263 }
264 }
265 return true;
266 }
267
268 QHash<QString, QHash<QString, QSet<QgsSymbolLayerId>>> masks;
269 // Current label rule, empty string for a simple labeling
270 QString currentRule;
271 QString currentDescription;
272 QTreeWidgetItem *mLayerItem;
273 const QgsVectorLayer *mLayer;
274 QHash<QgsSymbolLayerReference, QTreeWidgetItem *> &mItems;
275 };
276
277 // populate the tree
278 const auto layers = QgsProject::instance()->layerTreeRoot()->findLayers();
279 for ( const QgsLayerTreeLayer *layerTreeLayer : layers )
280 {
281 QgsMapLayer *layer = layerTreeLayer->layer();
282 QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer );
283 if ( !vl )
284 continue;
285 if ( !vl->renderer() )
286 continue;
287
288 auto layerItem = std::make_unique<QTreeWidgetItem>( mTree, QStringList() << layer->name() );
289 layerItem->setData( 0, Qt::UserRole, QVariant::fromValue( vl ) );
290
291 if ( vl->labeling() )
292 {
293 LabelMasksVisitor lblVisitor( layerItem.get(), vl, mItems );
294 vl->labeling()->accept( &lblVisitor );
295 }
296
297 SymbolLayerFillVisitor slVisitor( layerItem.get(), vl, mItems, screen() );
298 vl->renderer()->accept( &slVisitor );
299
300 if ( layerItem->childCount() > 0 )
301 mTree->addTopLevelItem( layerItem.release() );
302 }
303
304 expandAll( mTree->invisibleRootItem() );
305 mBlockChangedSignals--;
306}
307
309{
311
312 const QModelIndex selectedIndex = mManagerProxyModel->mapToSource( mManagerProxyModel->index( mSetComboBox->currentIndex(), 0 ) );
313 const bool isCustomSet = mManagerModel->data( selectedIndex, static_cast< int >( QgsSelectiveMaskingSourceSetManagerModel::CustomRole::IsEmptyObject ) ).toBool();
314 if ( !isCustomSet )
315 {
316 set.setName( mManagerModel->data( selectedIndex, Qt::DisplayRole ).toString() );
317 set.setId( mManagerModel->data( selectedIndex, static_cast< int >( QgsSelectiveMaskingSourceSetManagerModel::CustomRole::SetId ) ).toString() );
318 }
319
320 for ( auto it = mItems.begin(); it != mItems.end(); it++ )
321 {
322 if ( it.value()->checkState( 0 ) == Qt::Checked )
323 {
324 const QgsSymbolLayerReference &ref = it.key();
326 const bool isLabeling = ref.layerId().startsWith( "__labels__" );
327 if ( isLabeling )
328 {
330 source.setLayerId( ref.layerId().mid( 10 ) );
331 }
332 else
333 {
335 source.setLayerId( ref.layerId() );
336 }
337 source.setSourceId( ref.symbolLayerIdV2() );
338 set.append( source );
339 }
340 }
341 return set;
342}
343
345{
346 // Clear current selection
347 mBlockChangedSignals++;
348 for ( auto it = mItems.begin(); it != mItems.end(); it++ )
349 {
350 it.value()->setCheckState( 0, Qt::Unchecked );
351 }
352
353 const QVector< QgsSelectiveMaskSource > sources = set.sources();
354 for ( const QgsSelectiveMaskSource &source : sources )
355 {
356 QString layerId;
357 switch ( source.sourceType() )
358 {
360 layerId = source.layerId();
361 break;
363 layerId = u"__labels__%1"_s.arg( source.layerId() );
364 break;
365 }
366 const auto it = mItems.find( QgsSymbolLayerReference( layerId, source.sourceId() ) );
367 if ( it != mItems.end() )
368 {
369 it.value()->setCheckState( 0, Qt::Checked );
370 }
371 }
372 if ( !set.isValid() )
373 {
374 mSetComboBox->setCurrentIndex( 0 );
375 }
376 else
377 {
378 mSetComboBox->setCurrentIndex( mSetComboBox->findText( set.name() ) );
379 }
380 mBlockChangedSignals--;
381}
382
383void QgsMaskSourceSelectionWidget::selectedSetChanged()
384{
385 mBlockChangedSignals++;
386 if ( !isCustomSet() )
387 {
388 const QModelIndex selectedIndex = mManagerProxyModel->mapToSource( mManagerProxyModel->index( mSetComboBox->currentIndex(), 0 ) );
389 const QString selectedSetId = mManagerModel->data( selectedIndex, static_cast< int >( QgsSelectiveMaskingSourceSetManagerModel::CustomRole::SetId ) ).toString();
391 setSourceSet( set );
392 }
393 mBlockChangedSignals--;
394
395 emitChanged();
396}
397
398void QgsMaskSourceSelectionWidget::emitChanged()
399{
400 if ( !mBlockChangedSignals )
401 {
402 emit changed();
403 }
404}
405
406void QgsMaskSourceSelectionWidget::onItemChanged()
407{
408 if ( mBlockChangedSignals )
409 return;
410
411 if ( !isCustomSet() )
412 {
413 const QgsSelectiveMaskingSourceSet set = sourceSet();
415 }
416 emitChanged();
417}
418
419void QgsMaskSourceSelectionWidget::newSet()
420{
422
423 QStringList existingNames;
424 const QVector<QgsSelectiveMaskingSourceSet> sets = QgsProject::instance()->selectiveMaskingSourceSetManager()->sets();
425 existingNames.reserve( sets.size() );
426 for ( const QgsSelectiveMaskingSourceSet &set : sets )
427 {
428 existingNames << set.name();
429 }
430
431 QgsNewNameDialog dlg( tr( "selective masking set" ), newTitle, QStringList(), existingNames, Qt::CaseSensitive, this );
432 dlg.setWindowTitle( tr( "Create Selective Masking Set" ) );
433 dlg.setHintString( tr( "Enter a unique selective masking set name" ) );
434 dlg.setOverwriteEnabled( false );
435 dlg.setAllowEmptyName( false );
436 dlg.setConflictingNameWarning( tr( "A masking set with this name already exists." ) );
437
438 if ( dlg.exec() != QDialog::Accepted )
439 {
440 return;
441 }
442
443 QgsSelectiveMaskingSourceSet newSet;
444 newSet.setName( dlg.name() );
446 mSetComboBox->setCurrentIndex( mSetComboBox->findText( newSet.name() ) );
447}
448
449void QgsMaskSourceSelectionWidget::removeSet()
450{
451 if ( isCustomSet() )
452 return;
453
454 const QString setName = mSetComboBox->currentText();
455 if ( QMessageBox::warning( this, tr( "Remove Selective Masking Set" ), tr( "Do you really want to remove the selective masking set “%1”?" ).arg( setName ), QMessageBox::Ok | QMessageBox::Cancel )
456 != QMessageBox::Ok )
457 {
458 return;
459 }
460
461 mSetComboBox->setCurrentIndex( 0 );
463}
464
465void QgsMaskSourceSelectionWidget::renameSet()
466{
467 if ( isCustomSet() )
468 return;
469
470 const QString setName = mSetComboBox->currentText();
471
472 QStringList existingNames;
473 const QVector<QgsSelectiveMaskingSourceSet> sets = QgsProject::instance()->selectiveMaskingSourceSetManager()->sets();
474 existingNames.reserve( sets.size() );
475 for ( const QgsSelectiveMaskingSourceSet &set : sets )
476 {
477 if ( set.name() != setName )
478 existingNames << set.name();
479 }
480
481 QgsNewNameDialog dlg( tr( "selective masking set" ), setName, QStringList(), existingNames, Qt::CaseSensitive, this );
482 dlg.setWindowTitle( tr( "Rename Selective Masking Set" ) );
483 dlg.setHintString( tr( "Enter a unique selective masking set name" ) );
484 dlg.setOverwriteEnabled( false );
485 dlg.setAllowEmptyName( false );
486 dlg.setConflictingNameWarning( tr( "A masking set with this name already exists." ) );
487
488 if ( dlg.exec() != QDialog::Accepted )
489 {
490 return;
491 }
492
494}
495
496bool QgsMaskSourceSelectionWidget::isCustomSet() const
497{
498 const QModelIndex selectedIndex = mManagerProxyModel->mapToSource( mManagerProxyModel->index( mSetComboBox->currentIndex(), 0 ) );
499 return mManagerModel->data( selectedIndex, static_cast< int >( QgsSelectiveMaskingSourceSetManagerModel::CustomRole::IsEmptyObject ) ).toBool();
500}
@ Label
A mask generated from a labeling provider.
Definition qgis.h:3170
@ SymbolLayer
A mask generated from a symbol layer.
Definition qgis.h:3169
@ Millimeters
Millimeters.
Definition qgis.h:5341
virtual bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified symbology visitor, causing it to visit all symbols associated with the labeling...
virtual bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified symbology visitor, causing it to visit all symbols associated with the renderer...
QList< QgsLayerTreeLayer * > findLayers() const
Find all layer nodes.
Layer tree node points to a map layer.
Base class for all map layer types.
Definition qgsmaplayer.h:83
QString name
Definition qgsmaplayer.h:87
Struct for storing maximum and minimum scales for measurements in map units.
void changed()
Emitted when an item was changed.
QgsSelectiveMaskingSourceSet sourceSet() const
Returns the current masking source set.
void update()
Updates the possible sources, from the project layers.
QgsMaskSourceSelectionWidget(QWidget *parent=nullptr)
constructor
void setSourceSet(const QgsSelectiveMaskingSourceSet &set)
Sets the current masking source set.
static QgsProject * instance()
Returns the QgsProject singleton instance.
QgsLayerTree * layerTreeRoot() const
Returns pointer to the root (invisible) node of the project's layer tree.
const QgsSelectiveMaskingSourceSetManager * selectiveMaskingSourceSetManager() const
Returns the project's selective masking set manager, which manages storage of a set of selective mask...
Stores properties relating to a screen.
Encapsulates a single source for selective masking (e.g.
void setSourceId(const QString &id)
Sets the symbol layer or label rule id.
void setLayerId(const QString &id)
Sets the source layer id.
void setSourceType(Qgis::SelectiveMaskSourceType type)
Sets the source type.
List model representing the selective masking source sets available in a selective masking source set...
QVariant data(const QModelIndex &index, int role) const override
QSortFilterProxyModel subclass for QgsSelectiveMaskingSourceSetManagerModel.
bool renameSet(const QString &oldName, const QString &newName)
Renames a set in the manager from oldName to newName.
QVector< QgsSelectiveMaskingSourceSet > sets() const
Returns a list of all sets contained in the manager.
QgsSelectiveMaskingSourceSet setById(const QString &id) const
Returns the set with a matching id, or an invalid set if no matching sets were found.
bool addSet(const QgsSelectiveMaskingSourceSet &set)
Adds a set to the manager.
QString generateUniqueTitle() const
Generates a unique title for a new set, which does not clash with any already contained by the manage...
bool removeSet(const QString &name)
Removes the set with matching name from the manager.
bool updateSet(const QgsSelectiveMaskingSourceSet &set)
Updates the definition of a set already in the manager.
Represents a named set of selective masking sources (QgsSelectiveMaskSource).
void setName(const QString &name)
Sets the set's unique name.
void setId(const QString &id)
Sets the unique identifier for the set.
QVector< QgsSelectiveMaskSource > sources() const
Returns the list of selective mask sources configured in this set.
void append(const QgsSelectiveMaskSource &source)
Appends a source to the set.
QString name() const
Returns the set's unique name.
bool isValid() const
Returns true if the source set is valid, or false if it is invalid (default constructed).
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 label settings entity for QgsStyle databases.
Definition qgsstyle.h:1478
A symbol entity for QgsStyle databases.
Definition qgsstyle.h:1393
@ LabelSettingsEntity
Label settings.
Definition qgsstyle.h:210
@ SymbolEntity
Symbols.
Definition qgsstyle.h:205
Type used to refer to a specific symbol layer in a symbol of a layer.
QString symbolLayerIdV2() const
The symbol layer's id.
QString layerId() const
The referenced vector layer / feature renderer.
static QIcon symbolLayerPreviewIcon(const QgsSymbolLayer *layer, Qgis::RenderUnit u, QSize size, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::SymbolType parentSymbolType=Qgis::SymbolType::Hybrid, QgsMapLayer *mapLayer=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Draws a symbol layer preview to an icon.
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.
Abstract base class for symbol layers.
virtual QString layerType() const =0
Returns a string that represents this layer type.
virtual QgsSymbol * subSymbol()
Returns the symbol's sub symbol, if present.
Abstract base class for all rendered symbols.
Definition qgssymbol.h:227
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
Definition qgssymbol.h:357
Represents a vector layer which manages a vector based dataset.
const QgsAbstractVectorLayerLabeling * labeling() const
Access to const labeling configuration.
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,...
void printSymbolLayerRef(const QgsSymbolLayerReference &ref)
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.