27 #include <QInputDialog> 39 layerRec.usingCurrentStyle =
true;
41 layerRec.expandedLayerNode = nodeLayer->
isExpanded();
42 layerRec.expandedLegendItems = nodeLayer->
customProperty( QStringLiteral(
"expandedLegendNodes" ) ).toStringList().toSet();
45 bool hasCheckableItems =
false;
46 bool someItemsUnchecked =
false;
47 QSet<QString> checkedItems;
48 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = model->
layerLegendNodes( nodeLayer,
true );
53 hasCheckableItems =
true;
55 if (
legendNode->
data( Qt::CheckStateRole ).toInt() == Qt::Checked )
58 someItemsUnchecked =
true;
62 if ( hasCheckableItems && someItemsUnchecked )
64 layerRec.usingLegendItems =
true;
65 layerRec.checkedLegendItems = checkedItems;
75 lst.prepend( node->
name() );
78 return lst.join(
'/' );
83 const QList<QgsLayerTreeNode *> constChildren = parent->
children();
90 rec.mExpandedGroupNodes.insert( _groupId( node ) );
92 rec.mCheckedGroupNodes.insert( _groupId( node ) );
98 rec.mLayerRecords << createThemeLayerRecord( nodeLayer, model );
116 if ( lr.layer() == layer )
128 const bool recordExists = findRecordForLayer( nodeLayer->
layer(), rec, layerRec );
153 const QList<QgsLayerTreeModelLegendNode *> constLayerLegendNodes = model->
layerLegendNodes( nodeLayer,
true );
157 Qt::CheckState shouldHaveState = layerRec.
checkedLegendItems.contains( ruleKey ) ? Qt::Checked : Qt::Unchecked;
159 legendNode->
data( Qt::CheckStateRole ).toInt() != shouldHaveState )
166 const QList<QgsLayerTreeModelLegendNode *> constLayerLegendNodes = model->
layerLegendNodes( nodeLayer,
true );
186 const QList<QgsLayerTreeNode *> constChildren = parent->
children();
218 if ( project == mProject )
230 return QList< QgsMapLayer * >();
240 if ( allLayers.isEmpty() )
243 return visibleLayers;
247 QList< QgsMapLayer * > orderedVisibleLayers;
250 if ( visibleLayers.contains( layer ) )
251 orderedVisibleLayers << layer;
253 return orderedVisibleLayers;
260 return mMapThemes.contains( name );
265 mMapThemes.insert( name, state );
267 reconnectToLayersStyleManager();
274 if ( !mMapThemes.contains( name ) )
277 mMapThemes[name] = state;
279 reconnectToLayersStyleManager();
286 if ( !mMapThemes.contains( name ) )
289 mMapThemes.remove( name );
291 reconnectToLayersStyleManager();
299 reconnectToLayersStyleManager();
305 return mMapThemes.keys();
310 QStringList layerIds;
312 for (
QgsMapLayer *layer : constMapThemeVisibleLayers )
314 layerIds << layer->
id();
321 QList<QgsMapLayer *> layers;
322 const QList<MapThemeLayerRecord> recs = mMapThemes.value( name ).mLayerRecords;
324 if ( layerOrder.isEmpty() )
327 const QList<MapThemeLayerRecord> records { mMapThemes.value( name ).mLayerRecords };
331 layers << layerRec.
layer();
341 layers << layerRec.
layer();
353 if ( !vlayer || !vlayer->
renderer() )
366 bool shouldBeChecked = someNodesUnchecked ? layerRec.
checkedLegendItems.contains( item.ruleKey() ) :
true;
367 if ( checked != shouldBeChecked )
375 QMap<QString, QString> styleOverrides;
376 if ( !mMapThemes.contains( presetName ) )
377 return styleOverrides;
379 const QList<MapThemeLayerRecord> records {mMapThemes.value( presetName ).mLayerRecords};
382 if ( !layerRec.
layer() )
392 applyMapThemeCheckedLegendNodesToLayer( layerRec, layer );
397 styleOverrides[layer->
id()] = layerStyle.
xmlData();
400 return styleOverrides;
403 void QgsMapThemeCollection::reconnectToLayersStyleManager()
407 QSet<QgsMapLayer *> layers;
412 if ( layerRec.
layer() )
413 layers << layerRec.
layer();
417 const QSet<QgsMapLayer *> constLayers = layers;
428 QDomElement visPresetsElem = doc.firstChildElement( QStringLiteral(
"qgis" ) ).firstChildElement( QStringLiteral(
"visibility-presets" ) );
429 if ( visPresetsElem.isNull() )
432 QDomElement visPresetElem = visPresetsElem.firstChildElement( QStringLiteral(
"visibility-preset" ) );
433 while ( !visPresetElem.isNull() )
435 QHash<QString, MapThemeLayerRecord> layerRecords;
437 bool expandedStateInfo =
false;
438 if ( visPresetElem.hasAttribute( QStringLiteral(
"has-expanded-info" ) ) )
439 expandedStateInfo = visPresetElem.attribute( QStringLiteral(
"has-expanded-info" ) ).toInt();
441 bool checkedStateInfo =
false;
442 if ( visPresetElem.hasAttribute( QStringLiteral(
"has-checked-group-info" ) ) )
443 checkedStateInfo = visPresetElem.attribute( QStringLiteral(
"has-checked-group-info" ) ).toInt();
445 QString presetName = visPresetElem.attribute( QStringLiteral(
"name" ) );
446 QDomElement visPresetLayerElem = visPresetElem.firstChildElement( QStringLiteral(
"layer" ) );
447 while ( !visPresetLayerElem.isNull() )
449 QString layerID = visPresetLayerElem.attribute( QStringLiteral(
"id" ) );
453 layerRecords[layerID].isVisible = visPresetLayerElem.attribute( QStringLiteral(
"visible" ), QStringLiteral(
"1" ) ).toInt();
455 if ( visPresetLayerElem.hasAttribute( QStringLiteral(
"style" ) ) )
457 layerRecords[layerID].usingCurrentStyle =
true;
458 layerRecords[layerID].currentStyle = visPresetLayerElem.attribute( QStringLiteral(
"style" ) );
461 if ( visPresetLayerElem.hasAttribute( QStringLiteral(
"expanded" ) ) )
462 layerRecords[layerID].expandedLayerNode = visPresetLayerElem.attribute( QStringLiteral(
"expanded" ) ).toInt();
464 visPresetLayerElem = visPresetLayerElem.nextSiblingElement( QStringLiteral(
"layer" ) );
467 QDomElement checkedLegendNodesElem = visPresetElem.firstChildElement( QStringLiteral(
"checked-legend-nodes" ) );
468 while ( !checkedLegendNodesElem.isNull() )
470 QSet<QString> checkedLegendNodes;
472 QDomElement checkedLegendNodeElem = checkedLegendNodesElem.firstChildElement( QStringLiteral(
"checked-legend-node" ) );
473 while ( !checkedLegendNodeElem.isNull() )
475 checkedLegendNodes << checkedLegendNodeElem.attribute( QStringLiteral(
"id" ) );
476 checkedLegendNodeElem = checkedLegendNodeElem.nextSiblingElement( QStringLiteral(
"checked-legend-node" ) );
479 QString layerID = checkedLegendNodesElem.attribute( QStringLiteral(
"id" ) );
480 if ( mProject->
mapLayer( layerID ) )
482 layerRecords[layerID].usingLegendItems =
true;
483 layerRecords[layerID].checkedLegendItems = checkedLegendNodes;
485 checkedLegendNodesElem = checkedLegendNodesElem.nextSiblingElement( QStringLiteral(
"checked-legend-nodes" ) );
488 QSet<QString> expandedGroupNodes;
489 if ( expandedStateInfo )
492 QDomElement expandedLegendNodesElem = visPresetElem.firstChildElement( QStringLiteral(
"expanded-legend-nodes" ) );
493 while ( !expandedLegendNodesElem.isNull() )
495 QSet<QString> expandedLegendNodes;
497 QDomElement expandedLegendNodeElem = expandedLegendNodesElem.firstChildElement( QStringLiteral(
"expanded-legend-node" ) );
498 while ( !expandedLegendNodeElem.isNull() )
500 expandedLegendNodes << expandedLegendNodeElem.attribute( QStringLiteral(
"id" ) );
501 expandedLegendNodeElem = expandedLegendNodeElem.nextSiblingElement( QStringLiteral(
"expanded-legend-node" ) );
504 QString layerID = expandedLegendNodesElem.attribute( QStringLiteral(
"id" ) );
505 if ( mProject->
mapLayer( layerID ) )
507 layerRecords[layerID].expandedLegendItems = expandedLegendNodes;
509 expandedLegendNodesElem = expandedLegendNodesElem.nextSiblingElement( QStringLiteral(
"expanded-legend-nodes" ) );
513 QDomElement expandedGroupNodesElem = visPresetElem.firstChildElement( QStringLiteral(
"expanded-group-nodes" ) );
514 if ( !expandedGroupNodesElem.isNull() )
516 QDomElement expandedGroupNodeElem = expandedGroupNodesElem.firstChildElement( QStringLiteral(
"expanded-group-node" ) );
517 while ( !expandedGroupNodeElem.isNull() )
519 expandedGroupNodes << expandedGroupNodeElem.attribute( QStringLiteral(
"id" ) );
520 expandedGroupNodeElem = expandedGroupNodeElem.nextSiblingElement( QStringLiteral(
"expanded-group-node" ) );
525 QSet<QString> checkedGroupNodes;
526 if ( checkedStateInfo )
529 QDomElement checkedGroupNodesElem = visPresetElem.firstChildElement( QStringLiteral(
"checked-group-nodes" ) );
530 if ( !checkedGroupNodesElem.isNull() )
532 QDomElement checkedGroupNodeElem = checkedGroupNodesElem.firstChildElement( QStringLiteral(
"checked-group-node" ) );
533 while ( !checkedGroupNodeElem.isNull() )
535 checkedGroupNodes << checkedGroupNodeElem.attribute( QStringLiteral(
"id" ) );
536 checkedGroupNodeElem = checkedGroupNodeElem.nextSiblingElement( QStringLiteral(
"checked-group-node" ) );
547 mMapThemes.insert( presetName, rec );
550 visPresetElem = visPresetElem.nextSiblingElement( QStringLiteral(
"visibility-preset" ) );
553 reconnectToLayersStyleManager();
559 QDomElement visPresetsElem = doc.createElement( QStringLiteral(
"visibility-presets" ) );
561 QList< QString > keys = mMapThemes.keys();
563 std::sort( keys.begin(), keys.end() );
565 for (
const QString &grpName : qgis::as_const( keys ) )
568 QDomElement visPresetElem = doc.createElement( QStringLiteral(
"visibility-preset" ) );
569 visPresetElem.setAttribute( QStringLiteral(
"name" ), grpName );
571 visPresetElem.setAttribute( QStringLiteral(
"has-expanded-info" ), QStringLiteral(
"1" ) );
573 visPresetElem.setAttribute( QStringLiteral(
"has-checked-group-info" ), QStringLiteral(
"1" ) );
576 if ( !layerRec.
layer() )
578 QString layerID = layerRec.
layer()->
id();
579 QDomElement layerElem = doc.createElement( QStringLiteral(
"layer" ) );
580 layerElem.setAttribute( QStringLiteral(
"id" ), layerID );
581 layerElem.setAttribute( QStringLiteral(
"visible" ), layerRec.
isVisible ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
583 layerElem.setAttribute( QStringLiteral(
"style" ), layerRec.
currentStyle );
584 visPresetElem.appendChild( layerElem );
588 QDomElement checkedLegendNodesElem = doc.createElement( QStringLiteral(
"checked-legend-nodes" ) );
589 checkedLegendNodesElem.setAttribute( QStringLiteral(
"id" ), layerID );
590 for (
const QString &checkedLegendNode : qgis::as_const( layerRec.
checkedLegendItems ) )
592 QDomElement checkedLegendNodeElem = doc.createElement( QStringLiteral(
"checked-legend-node" ) );
593 checkedLegendNodeElem.setAttribute( QStringLiteral(
"id" ), checkedLegendNode );
594 checkedLegendNodesElem.appendChild( checkedLegendNodeElem );
596 visPresetElem.appendChild( checkedLegendNodesElem );
601 layerElem.setAttribute( QStringLiteral(
"expanded" ), layerRec.
expandedLayerNode ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
603 QDomElement expandedLegendNodesElem = doc.createElement( QStringLiteral(
"expanded-legend-nodes" ) );
604 expandedLegendNodesElem.setAttribute( QStringLiteral(
"id" ), layerID );
607 QDomElement expandedLegendNodeElem = doc.createElement( QStringLiteral(
"expanded-legend-node" ) );
608 expandedLegendNodeElem.setAttribute( QStringLiteral(
"id" ), expandedLegendNode );
609 expandedLegendNodesElem.appendChild( expandedLegendNodeElem );
611 visPresetElem.appendChild( expandedLegendNodesElem );
617 QDomElement checkedGroupElems = doc.createElement( QStringLiteral(
"checked-group-nodes" ) );
619 for (
const QString &groupId : checkedGroupNodes )
621 QDomElement checkedGroupElem = doc.createElement( QStringLiteral(
"checked-group-node" ) );
622 checkedGroupElem.setAttribute( QStringLiteral(
"id" ), groupId );
623 checkedGroupElems.appendChild( checkedGroupElem );
625 visPresetElem.appendChild( checkedGroupElems );
630 QDomElement expandedGroupElems = doc.createElement( QStringLiteral(
"expanded-group-nodes" ) );
632 for (
const QString &groupId : expandedGroupNodes )
634 QDomElement expandedGroupElem = doc.createElement( QStringLiteral(
"expanded-group-node" ) );
635 expandedGroupElem.setAttribute( QStringLiteral(
"id" ), groupId );
636 expandedGroupElems.appendChild( expandedGroupElem );
638 visPresetElem.appendChild( expandedGroupElems );
641 visPresetsElem.appendChild( visPresetElem );
644 doc.firstChildElement( QStringLiteral(
"qgis" ) ).appendChild( visPresetsElem );
647 void QgsMapThemeCollection::registryLayersRemoved(
const QStringList &layerIDs )
651 QSet< QString > changedThemes;
652 MapThemeRecordMap::iterator it = mMapThemes.begin();
653 for ( ; it != mMapThemes.end(); ++it )
656 for (
int i = 0; i < rec.mLayerRecords.count(); ++i )
659 if ( layerRec.
layer() && layerIDs.contains( layerRec.
layer()->
id() ) )
661 rec.mLayerRecords.removeAt( i-- );
662 changedThemes << it.key();
667 for (
const QString &theme : qgis::as_const( changedThemes ) )
674 void QgsMapThemeCollection::layerStyleRenamed(
const QString &oldName,
const QString &newName )
680 QSet< QString > changedThemes;
682 MapThemeRecordMap::iterator it = mMapThemes.begin();
683 for ( ; it != mMapThemes.end(); ++it )
686 for (
int i = 0; i < rec.mLayerRecords.count(); ++i )
694 changedThemes << it.key();
700 for (
const QString &theme : qgis::as_const( changedThemes ) )
709 for (
int i = 0; i < mLayerRecords.length(); ++i )
711 if ( mLayerRecords.at( i ).layer() == layer )
712 mLayerRecords.removeAt( i );
718 mLayerRecords.append( record );
723 QHash<QgsMapLayer *, MapThemeLayerRecord> validSet;
726 if ( layerRec.
layer() )
727 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.
QSet< QString > checkedGroupNodes() const
Returns a set of group identifiers for group nodes that should have checked state (other group nodes ...
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.
bool itemVisibilityChecked() const
Returns whether a node is checked (independently of its ancestors or children)
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.
void setHasCheckedStateInfo(bool hasInfo)
Sets whether the map theme contains valid checked/unchecked state of group nodes. ...
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.
bool hasCheckedStateInfo() const
Returns whether information about checked/unchecked state of groups has been recorded and thus whethe...
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.
bool isVisible
true if the layer is visible in the associated theme.
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.
void setCheckedGroupNodes(const QSet< QString > &checkedGroupNodes)
Sets a set of group identifiers for group nodes that should have checked state.
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.