27 #include <QInputDialog> 40 layerRec.expandedLayerNode = nodeLayer->
isExpanded();
41 layerRec.expandedLegendItems = nodeLayer->
customProperty( QStringLiteral(
"expandedLegendNodes" ) ).toStringList().toSet();
44 bool hasCheckableItems =
false;
45 bool someItemsUnchecked =
false;
46 QSet<QString> checkedItems;
47 const auto constLayerLegendNodes = model->
layerLegendNodes( nodeLayer,
true );
52 hasCheckableItems =
true;
54 if (
legendNode->
data( Qt::CheckStateRole ).toInt() == Qt::Checked )
57 someItemsUnchecked =
true;
61 if ( hasCheckableItems && someItemsUnchecked )
63 layerRec.usingLegendItems =
true;
64 layerRec.checkedLegendItems = checkedItems;
74 lst.prepend( node->
name() );
77 return lst.join(
'/' );
82 const auto constChildren = parent->
children();
89 rec.mExpandedGroupNodes.insert( _groupId( node ) );
95 rec.mLayerRecords << createThemeLayerRecord( nodeLayer, model );
112 if ( lr.layer() == layer )
124 bool isVisible = findRecordForLayer( nodeLayer->
layer(), rec, layerRec );
144 const auto constLayerLegendNodes = model->
layerLegendNodes( nodeLayer,
true );
148 Qt::CheckState shouldHaveState = layerRec.
checkedLegendItems.contains( ruleKey ) ? Qt::Checked : Qt::Unchecked;
150 legendNode->
data( Qt::CheckStateRole ).toInt() != shouldHaveState )
157 const auto constLayerLegendNodes = model->
layerLegendNodes( nodeLayer,
true );
177 const auto constChildren = parent->
children();
207 if ( project == mProject )
219 return QList< QgsMapLayer * >();
229 if ( allLayers.isEmpty() )
232 return visibleLayers;
236 QList< QgsMapLayer * > orderedVisibleLayers;
237 const auto constAllLayers = allLayers;
240 if ( visibleLayers.contains( layer ) )
241 orderedVisibleLayers << layer;
243 return orderedVisibleLayers;
250 return mMapThemes.contains( name );
255 mMapThemes.insert( name, state );
257 reconnectToLayersStyleManager();
264 if ( !mMapThemes.contains( name ) )
267 mMapThemes[name] = state;
269 reconnectToLayersStyleManager();
276 if ( !mMapThemes.contains( name ) )
279 mMapThemes.remove( name );
281 reconnectToLayersStyleManager();
289 reconnectToLayersStyleManager();
295 return mMapThemes.keys();
300 QStringList layerIds;
302 for (
QgsMapLayer *layer : constMapThemeVisibleLayers )
304 layerIds << layer->
id();
311 QList<QgsMapLayer *> layers;
312 const QList<MapThemeLayerRecord> &recs = mMapThemes.value( name ).mLayerRecords;
314 if ( layerOrder.isEmpty() )
317 const auto records {mMapThemes.value( name ).mLayerRecords};
320 if ( layerRec.
layer() )
321 layers << layerRec.
layer();
326 const auto constLayerOrder = layerOrder;
329 const auto constRecs = recs;
332 if ( layerRec.
layer() == layer )
333 layers << layerRec.
layer();
345 if ( !vlayer || !vlayer->
renderer() )
358 bool shouldBeChecked = someNodesUnchecked ? layerRec.
checkedLegendItems.contains( item.ruleKey() ) :
true;
359 if ( checked != shouldBeChecked )
367 QMap<QString, QString> styleOverrides;
368 if ( !mMapThemes.contains( presetName ) )
369 return styleOverrides;
371 const auto records {mMapThemes.value( presetName ).mLayerRecords};
374 if ( !layerRec.
layer() )
384 applyMapThemeCheckedLegendNodesToLayer( layerRec, layer );
389 styleOverrides[layer->
id()] = layerStyle.
xmlData();
392 return styleOverrides;
395 void QgsMapThemeCollection::reconnectToLayersStyleManager()
399 QSet<QgsMapLayer *> layers;
400 const auto constMMapThemes = mMapThemes;
405 if ( layerRec.
layer() )
406 layers << layerRec.
layer();
410 const auto constLayers = layers;
421 QDomElement visPresetsElem = doc.firstChildElement( QStringLiteral(
"qgis" ) ).firstChildElement( QStringLiteral(
"visibility-presets" ) );
422 if ( visPresetsElem.isNull() )
425 QDomElement visPresetElem = visPresetsElem.firstChildElement( QStringLiteral(
"visibility-preset" ) );
426 while ( !visPresetElem.isNull() )
428 QHash<QString, MapThemeLayerRecord> layerRecords;
430 bool expandedStateInfo =
false;
431 if ( visPresetElem.hasAttribute( QStringLiteral(
"has-expanded-info" ) ) )
432 expandedStateInfo = visPresetElem.attribute( QStringLiteral(
"has-expanded-info" ) ).toInt();
434 QString presetName = visPresetElem.attribute( QStringLiteral(
"name" ) );
435 QDomElement visPresetLayerElem = visPresetElem.firstChildElement( QStringLiteral(
"layer" ) );
436 while ( !visPresetLayerElem.isNull() )
438 QString layerID = visPresetLayerElem.attribute( QStringLiteral(
"id" ) );
443 if ( visPresetLayerElem.hasAttribute( QStringLiteral(
"style" ) ) )
445 layerRecords[layerID].usingCurrentStyle =
true;
446 layerRecords[layerID].currentStyle = visPresetLayerElem.attribute( QStringLiteral(
"style" ) );
449 if ( visPresetLayerElem.hasAttribute( QStringLiteral(
"expanded" ) ) )
450 layerRecords[layerID].expandedLayerNode = visPresetLayerElem.attribute( QStringLiteral(
"expanded" ) ).toInt();
452 visPresetLayerElem = visPresetLayerElem.nextSiblingElement( QStringLiteral(
"layer" ) );
455 QDomElement checkedLegendNodesElem = visPresetElem.firstChildElement( QStringLiteral(
"checked-legend-nodes" ) );
456 while ( !checkedLegendNodesElem.isNull() )
458 QSet<QString> checkedLegendNodes;
460 QDomElement checkedLegendNodeElem = checkedLegendNodesElem.firstChildElement( QStringLiteral(
"checked-legend-node" ) );
461 while ( !checkedLegendNodeElem.isNull() )
463 checkedLegendNodes << checkedLegendNodeElem.attribute( QStringLiteral(
"id" ) );
464 checkedLegendNodeElem = checkedLegendNodeElem.nextSiblingElement( QStringLiteral(
"checked-legend-node" ) );
467 QString layerID = checkedLegendNodesElem.attribute( QStringLiteral(
"id" ) );
468 if ( mProject->
mapLayer( layerID ) )
470 layerRecords[layerID].usingLegendItems =
true;
471 layerRecords[layerID].checkedLegendItems = checkedLegendNodes;
473 checkedLegendNodesElem = checkedLegendNodesElem.nextSiblingElement( QStringLiteral(
"checked-legend-nodes" ) );
476 QSet<QString> expandedGroupNodes;
477 if ( expandedStateInfo )
480 QDomElement expandedLegendNodesElem = visPresetElem.firstChildElement( QStringLiteral(
"expanded-legend-nodes" ) );
481 while ( !expandedLegendNodesElem.isNull() )
483 QSet<QString> expandedLegendNodes;
485 QDomElement expandedLegendNodeElem = expandedLegendNodesElem.firstChildElement( QStringLiteral(
"expanded-legend-node" ) );
486 while ( !expandedLegendNodeElem.isNull() )
488 expandedLegendNodes << expandedLegendNodeElem.attribute( QStringLiteral(
"id" ) );
489 expandedLegendNodeElem = expandedLegendNodeElem.nextSiblingElement( QStringLiteral(
"expanded-legend-node" ) );
492 QString layerID = expandedLegendNodesElem.attribute( QStringLiteral(
"id" ) );
493 if ( mProject->
mapLayer( layerID ) )
495 layerRecords[layerID].expandedLegendItems = expandedLegendNodes;
497 expandedLegendNodesElem = expandedLegendNodesElem.nextSiblingElement( QStringLiteral(
"expanded-legend-nodes" ) );
501 QDomElement expandedGroupNodesElem = visPresetElem.firstChildElement( QStringLiteral(
"expanded-group-nodes" ) );
502 if ( !expandedGroupNodesElem.isNull() )
504 QDomElement expandedGroupNodeElem = expandedGroupNodesElem.firstChildElement( QStringLiteral(
"expanded-group-node" ) );
505 while ( !expandedGroupNodeElem.isNull() )
507 expandedGroupNodes << expandedGroupNodeElem.attribute( QStringLiteral(
"id" ) );
508 expandedGroupNodeElem = expandedGroupNodeElem.nextSiblingElement( QStringLiteral(
"expanded-group-node" ) );
517 mMapThemes.insert( presetName, rec );
520 visPresetElem = visPresetElem.nextSiblingElement( QStringLiteral(
"visibility-preset" ) );
523 reconnectToLayersStyleManager();
529 QDomElement visPresetsElem = doc.createElement( QStringLiteral(
"visibility-presets" ) );
531 auto keys = mMapThemes.keys();
533 std::sort( keys.begin(), keys.end() );
535 for (
const QString &grpName : qgis::as_const( keys ) )
538 QDomElement visPresetElem = doc.createElement( QStringLiteral(
"visibility-preset" ) );
539 visPresetElem.setAttribute( QStringLiteral(
"name" ), grpName );
541 visPresetElem.setAttribute( QStringLiteral(
"has-expanded-info" ), QStringLiteral(
"1" ) );
544 if ( !layerRec.
layer() )
546 QString layerID = layerRec.
layer()->
id();
547 QDomElement layerElem = doc.createElement( QStringLiteral(
"layer" ) );
548 layerElem.setAttribute( QStringLiteral(
"id" ), layerID );
550 layerElem.setAttribute( QStringLiteral(
"style" ), layerRec.
currentStyle );
551 visPresetElem.appendChild( layerElem );
555 QDomElement checkedLegendNodesElem = doc.createElement( QStringLiteral(
"checked-legend-nodes" ) );
556 checkedLegendNodesElem.setAttribute( QStringLiteral(
"id" ), layerID );
557 for (
const QString &checkedLegendNode : qgis::as_const( layerRec.
checkedLegendItems ) )
559 QDomElement checkedLegendNodeElem = doc.createElement( QStringLiteral(
"checked-legend-node" ) );
560 checkedLegendNodeElem.setAttribute( QStringLiteral(
"id" ), checkedLegendNode );
561 checkedLegendNodesElem.appendChild( checkedLegendNodeElem );
563 visPresetElem.appendChild( checkedLegendNodesElem );
568 layerElem.setAttribute( QStringLiteral(
"expanded" ), layerRec.
expandedLayerNode ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
570 QDomElement expandedLegendNodesElem = doc.createElement( QStringLiteral(
"expanded-legend-nodes" ) );
571 expandedLegendNodesElem.setAttribute( QStringLiteral(
"id" ), layerID );
574 QDomElement expandedLegendNodeElem = doc.createElement( QStringLiteral(
"expanded-legend-node" ) );
575 expandedLegendNodeElem.setAttribute( QStringLiteral(
"id" ), expandedLegendNode );
576 expandedLegendNodesElem.appendChild( expandedLegendNodeElem );
578 visPresetElem.appendChild( expandedLegendNodesElem );
584 QDomElement expandedGroupElems = doc.createElement( QStringLiteral(
"expanded-group-nodes" ) );
586 for (
const QString &groupId : expandedGroupNodes )
588 QDomElement expandedGroupElem = doc.createElement( QStringLiteral(
"expanded-group-node" ) );
589 expandedGroupElem.setAttribute( QStringLiteral(
"id" ), groupId );
590 expandedGroupElems.appendChild( expandedGroupElem );
592 visPresetElem.appendChild( expandedGroupElems );
595 visPresetsElem.appendChild( visPresetElem );
598 doc.firstChildElement( QStringLiteral(
"qgis" ) ).appendChild( visPresetsElem );
601 void QgsMapThemeCollection::registryLayersRemoved(
const QStringList &layerIDs )
605 QSet< QString > changedThemes;
606 MapThemeRecordMap::iterator it = mMapThemes.begin();
607 for ( ; it != mMapThemes.end(); ++it )
610 for (
int i = 0; i < rec.mLayerRecords.count(); ++i )
613 if ( layerRec.
layer() && layerIDs.contains( layerRec.
layer()->
id() ) )
615 rec.mLayerRecords.removeAt( i-- );
616 changedThemes << it.key();
621 const auto constChangedThemes = changedThemes;
622 for (
const QString &theme : constChangedThemes )
629 void QgsMapThemeCollection::layerStyleRenamed(
const QString &oldName,
const QString &newName )
635 QSet< QString > changedThemes;
637 MapThemeRecordMap::iterator it = mMapThemes.begin();
638 for ( ; it != mMapThemes.end(); ++it )
641 for (
int i = 0; i < rec.mLayerRecords.count(); ++i )
649 changedThemes << it.key();
654 const auto constChangedThemes = changedThemes;
655 for (
const QString &theme : constChangedThemes )
664 for (
int i = 0; i < mLayerRecords.length(); ++i )
666 if ( mLayerRecords.at( i ).layer() == layer )
667 mLayerRecords.removeAt( i );
673 mLayerRecords.append( record );
678 QHash<QgsMapLayer *, MapThemeLayerRecord> validSet;
679 const auto constMLayerRecords = mLayerRecords;
682 if ( layerRec.
layer() )
683 validSet.insert( layerRec.
layer(), layerRec );
Layer tree group node serves as a container for layers and further groups.
virtual QgsLegendSymbolList legendSymbolItems() const
Returns a list of symbology items for the legend.
static QgsLayerTreeLayer * toLayer(QgsLayerTreeNode *node)
Cast node to a layer.
QgsMapLayer * layer() const
Returns map layer or nullptr if the layer does not exist anymore.
Base class for all map layer types.
void setLayer(QgsMapLayer *layer)
Sets the map layer for this record.
void setProject(QgsProject *project)
The QgsProject on which this map theme collection works.
virtual QString name() const =0
Returns name of the node.
virtual Qt::ItemFlags flags() const
Returns item flags associated with the item. Default implementation returns Qt::ItemIsEnabled.
bool hasMapTheme(const QString &name) const
Returns whether a map theme with a matching name exists.
static bool isGroup(QgsLayerTreeNode *node)
Check whether the node is a valid group node.
void styleRenamed(const QString &oldName, const QString &newName)
Emitted when a style has been renamed.
QList< QgsMapLayer * > mapThemeVisibleLayers(const QString &name) const
Returns the list of layers that are visible for the specified map theme.
QMap< QString, QString > mapThemeStyleOverrides(const QString &name)
Gets layer style overrides (for QgsMapSettings) of the visible layers for given map theme...
QString xmlData() const
Returns XML content of the style.
Restore overridden layer style on destruction.
QHash< QgsMapLayer *, QgsMapThemeCollection::MapThemeLayerRecord > validLayerRecords() const
Returns set with only records for valid layers.
virtual bool setData(const QVariant &value, int role)
Sets some data associated with the item. Default implementation does nothing and returns false...
QgsMapThemeCollection::MapThemeRecord mapThemeState(const QString &name) const
Returns the recorded state of a map theme.
static QgsLayerTreeGroup * toGroup(QgsLayerTreeNode *node)
Cast node to a group.
Individual map theme record of visible layers and styles.
void update(const QString &name, const QgsMapThemeCollection::MapThemeRecord &state)
Updates a map theme within the collection.
bool isVisible() const
Returns whether a node is really visible (ie checked and all its ancestors checked as well) ...
void clear()
Remove all map themes from the collection.
void setExpandedGroupNodes(const QSet< QString > &expandedGroupNodes)
Sets a set of group identifiers for group nodes that should have expanded state.
Individual record of a visible layer in a map theme record.
bool isExpanded() const
Returns whether the node should be shown as expanded or collapsed in GUI.
void mapThemesChanged()
Emitted when map themes within the collection are changed.
void setHasExpandedStateInfo(bool hasInfo)
Sets whether the map theme contains valid expanded/collapsed state of nodes.
QList< QgsMapLayer *> checkedLayers() const
Returns a list of any checked layers which belong to this node or its children.
void removeLayerRecord(QgsMapLayer *layer)
Removes a record for layer if present.
QStringList mapThemeVisibleLayerIds(const QString &name) const
Returns the list of layer IDs that are visible for the specified map theme.
void readXml(const QDomDocument &doc)
Reads the map theme collection state from XML.
QgsMapLayerStyleManager * styleManager() const
Gets access to the layer's style manager.
void projectChanged()
Emitted when the project changes.
void readFromLayer(QgsMapLayer *layer)
Store layer's active style information in the instance.
The QgsLayerTreeModel class is model implementation for Qt item views framework.
Stores style information (renderer, opacity, labeling, diagrams etc.) applicable to a map layer...
QList< QgsMapLayer *> masterVisibleLayers() const
Returns the master list of visible layers.
void mapThemeChanged(const QString &theme)
Emitted when a map theme changes definition.
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
QList< QgsLayerTreeNode * > children()
Gets list of children of the node. Children are owned by the parent.
QgsMapThemeCollection(QgsProject *project=nullptr)
Create map theme collection that handles themes of the given project.
Rule key of the node (QString)
QList< QgsMapLayer *> masterLayerOrder() const
Returns the master layer order (this will always match the project's QgsProject::layerOrder() )...
void removeMapTheme(const QString &name)
Remove an existing map theme from collection.
QgsLayerTreeNode * parent()
Gets pointer to the parent. If parent is nullptr, the node is a root node.
void setLayerRecords(const QList< QgsMapThemeCollection::MapThemeLayerRecord > &records)
Sets layer records for the theme.
QVariant customProperty(const QString &key, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer. Properties are stored in a map and saved in project file...
QSet< QString > checkedLegendItems
Rule keys of check legend items in layer tree model.
QStringList mapThemes() const
Returns a list of existing map theme names.
static bool isLayer(const QgsLayerTreeNode *node)
Check whether the node is a valid layer node.
This class is a base class for nodes in a layer tree.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts, annotations, canvases, etc.
virtual bool legendSymbolItemChecked(const QString &key)
items of symbology items in legend is checked
QgsFeatureRenderer * renderer()
Returns renderer.
QgsLayerTreeModelLegendNode * legendNode(const QString &rule, QgsLayerTreeModel &model)
void applyTheme(const QString &name, QgsLayerTreeGroup *root, QgsLayerTreeModel *model)
Apply theme given by its name and modify layer tree, current style of layers and checked legend items...
virtual void checkLegendSymbolItem(const QString &key, bool state=true)
item in symbology was checked
bool hasExpandedStateInfo() const
Returns whether information about expanded/collapsed state of nodes has been recorded and thus whethe...
void setExpanded(bool expanded)
Sets whether the node should be shown as expanded or collapsed in GUI.
void insert(const QString &name, const QgsMapThemeCollection::MapThemeRecord &state)
Inserts a new map theme to the collection.
void setItemVisibilityCheckedParentRecursive(bool checked)
Check or uncheck a node and all its parents.
QgsLayerTree * layerTreeRoot() const
Returns pointer to the root (invisible) node of the project's layer tree.
QgsMapLayer * layer() const
Gets pointer to the associated map layer.
QgsMapLayer * layer() const
Returns the map layer associated with this node.
QString currentStyle() const
Returns name of the current style.
QList< QgsMapLayer * > layerOrder() const
The order in which layers will be rendered on the canvas.
The class stores information about one class/rule of a vector layer renderer in a unified way that ca...
void layersWillBeRemoved(const QStringList &layerIds)
Emitted when one or more layers are about to be removed from the registry.
QgsProject * project()
The QgsProject on which this map theme collection works.
QSet< QString > expandedLegendItems
Rule keys of expanded legend items in layer tree view.
QSet< QString > expandedGroupNodes() const
Returns a set of group identifiers for group nodes that should have expanded state (other group nodes...
virtual QVariant data(int role) const =0
Returns data associated with the item. Must be implemented in derived class.
The QgsLegendRendererItem class is abstract interface for legend items returned from QgsMapLayerLegen...
QList< QgsLayerTreeModelLegendNode * > layerLegendNodes(QgsLayerTreeLayer *nodeLayer, bool skipNodeEmbeddedInParent=false)
Returns filtered list of active legend nodes attached to a particular layer node (by default it retur...
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
void setItemVisibilityChecked(bool checked)
Check or uncheck a node (independently of its ancestors or children)
bool expandedLayerNode
Whether the layer's tree node is expanded (only to be applied if the parent MapThemeRecord has the in...
virtual bool legendSymbolItemsCheckable() const
items of symbology items in legend should be checkable
void setOverrideStyle(const QString &style)
Temporarily apply a different style to the layer.
static QgsMapThemeCollection::MapThemeRecord createThemeFromCurrentState(QgsLayerTreeGroup *root, QgsLayerTreeModel *model)
Static method to create theme from the current state of layer visibilities in layer tree...
Management of styles for use with one map layer.
Represents a vector layer which manages a vector based data sets.
QString currentStyle
Name of the current style of the layer.
bool usingCurrentStyle
Whether current style is valid and should be applied.
void writeXml(QDomDocument &doc)
Writes the map theme collection state to XML.
void addLayerRecord(const QgsMapThemeCollection::MapThemeLayerRecord &record)
Add a new record for a layer.
bool setCurrentStyle(const QString &name)
Set a different style as the current style - will apply it to the layer.
bool usingLegendItems
Whether checkedLegendItems should be applied.
void setCustomProperty(const QString &key, const QVariant &value)
Sets a custom property for the node. Properties are stored in a map and saved in project file...
Layer tree node points to a map layer.