36 MapThemeLayerRecord layerRec( nodeLayer->
layer() );
37 layerRec.isVisible = nodeLayer->
isVisible();
38 layerRec.usingCurrentStyle =
true;
40 layerRec.expandedLayerNode = nodeLayer->
isExpanded();
41 layerRec.expandedLegendItems = qgis::listToSet( nodeLayer->
customProperty( QStringLiteral(
"expandedLegendNodes" ) ).toStringList() );
44 bool hasCheckableItems =
false;
45 bool someItemsUnchecked =
false;
46 QSet<QString> checkedItems;
47 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = 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 QList<QgsLayerTreeNode *> constChildren = parent->
children();
89 rec.mExpandedGroupNodes.insert( _groupId( node ) );
91 rec.mCheckedGroupNodes.insert( _groupId( node ) );
97 rec.mLayerRecords << createThemeLayerRecord( nodeLayer, model );
115 if ( lr.layer() == layer )
126 MapThemeLayerRecord layerRec;
127 const bool recordExists = findRecordForLayer( nodeLayer->
layer(), rec, layerRec );
143 if ( layerRec.usingCurrentStyle )
149 if ( layerRec.usingLegendItems )
152 const QList<QgsLayerTreeModelLegendNode *> constLayerLegendNodes = model->
layerLegendNodes( nodeLayer,
true );
156 Qt::CheckState shouldHaveState = layerRec.checkedLegendItems.contains( ruleKey ) ? Qt::Checked : Qt::Unchecked;
158 legendNode->
data( Qt::CheckStateRole ).toInt() != shouldHaveState )
165 const QList<QgsLayerTreeModelLegendNode *> constLayerLegendNodes = model->
layerLegendNodes( nodeLayer,
true );
177 nodeLayer->
setExpanded( layerRec.expandedLayerNode );
178 nodeLayer->
setCustomProperty( QStringLiteral(
"expandedLegendNodes" ), QStringList( qgis::setToList( layerRec.expandedLegendItems ) ) );
185 const QList<QgsLayerTreeNode *> constChildren = parent->
children();
229 return QList< QgsMapLayer * >();
239 if ( allLayers.isEmpty() )
242 return visibleLayers;
246 QList< QgsMapLayer * > orderedVisibleLayers;
249 if ( visibleLayers.contains( layer ) )
250 orderedVisibleLayers << layer;
252 return orderedVisibleLayers;
259 return mMapThemes.contains( name );
264 mMapThemes.insert( name, state );
266 reconnectToLayersStyleManager();
273 if ( !mMapThemes.contains( name ) )
276 mMapThemes[name] = state;
278 reconnectToLayersStyleManager();
285 if ( !mMapThemes.contains( name ) || mMapThemes.contains( newName ) )
290 insert( newName, newState );
298 if ( !mMapThemes.contains( name ) )
301 mMapThemes.remove( name );
303 reconnectToLayersStyleManager();
311 reconnectToLayersStyleManager();
317 return mMapThemes.keys();
322 QStringList layerIds;
324 for (
QgsMapLayer *layer : constMapThemeVisibleLayers )
326 layerIds << layer->
id();
333 QList<QgsMapLayer *> layers;
334 const QList<MapThemeLayerRecord> recs = mMapThemes.value( name ).mLayerRecords;
336 if ( layerOrder.isEmpty() )
339 const QList<MapThemeLayerRecord> records { mMapThemes.value( name ).mLayerRecords };
342 if ( layerRec.isVisible && layerRec.layer() )
343 layers << layerRec.layer();
352 if ( layerRec.isVisible && layerRec.layer() == layer )
353 layers << layerRec.layer();
362 void QgsMapThemeCollection::applyMapThemeCheckedLegendNodesToLayer(
const MapThemeLayerRecord &layerRec,
QgsMapLayer *layer )
365 if ( !vlayer || !vlayer->
renderer() )
372 bool someNodesUnchecked = layerRec.usingLegendItems;
378 bool shouldBeChecked = someNodesUnchecked ? layerRec.checkedLegendItems.contains( item.ruleKey() ) :
true;
379 if ( checked != shouldBeChecked )
387 QMap<QString, QString> styleOverrides;
388 if ( !mMapThemes.contains( presetName ) )
389 return styleOverrides;
391 const QList<MapThemeLayerRecord> records {mMapThemes.value( presetName ).mLayerRecords};
394 if ( !layerRec.layer() )
397 if ( layerRec.usingCurrentStyle )
404 applyMapThemeCheckedLegendNodesToLayer( layerRec, layer );
409 styleOverrides[layer->
id()] = layerStyle.
xmlData();
412 return styleOverrides;
415 void QgsMapThemeCollection::reconnectToLayersStyleManager()
419 QSet<QgsMapLayer *> layers;
420 for (
const MapThemeRecord &rec : std::as_const( mMapThemes ) )
422 for (
const MapThemeLayerRecord &layerRec : std::as_const( rec.mLayerRecords ) )
424 if (
auto *lLayer = layerRec.layer() )
429 const QSet<QgsMapLayer *> constLayers = layers;
440 QDomElement visPresetsElem = doc.firstChildElement( QStringLiteral(
"qgis" ) ).firstChildElement( QStringLiteral(
"visibility-presets" ) );
441 if ( visPresetsElem.isNull() )
444 QDomElement visPresetElem = visPresetsElem.firstChildElement( QStringLiteral(
"visibility-preset" ) );
445 while ( !visPresetElem.isNull() )
447 QHash<QString, MapThemeLayerRecord> layerRecords;
449 bool expandedStateInfo =
false;
450 if ( visPresetElem.hasAttribute( QStringLiteral(
"has-expanded-info" ) ) )
451 expandedStateInfo = visPresetElem.attribute( QStringLiteral(
"has-expanded-info" ) ).toInt();
453 bool checkedStateInfo =
false;
454 if ( visPresetElem.hasAttribute( QStringLiteral(
"has-checked-group-info" ) ) )
455 checkedStateInfo = visPresetElem.attribute( QStringLiteral(
"has-checked-group-info" ) ).toInt();
457 QString presetName = visPresetElem.attribute( QStringLiteral(
"name" ) );
458 QDomElement visPresetLayerElem = visPresetElem.firstChildElement( QStringLiteral(
"layer" ) );
459 while ( !visPresetLayerElem.isNull() )
461 QString layerID = visPresetLayerElem.attribute( QStringLiteral(
"id" ) );
465 layerRecords[layerID].isVisible = visPresetLayerElem.attribute( QStringLiteral(
"visible" ), QStringLiteral(
"1" ) ).toInt();
467 if ( visPresetLayerElem.hasAttribute( QStringLiteral(
"style" ) ) )
469 layerRecords[layerID].usingCurrentStyle =
true;
470 layerRecords[layerID].currentStyle = visPresetLayerElem.attribute( QStringLiteral(
"style" ) );
473 if ( visPresetLayerElem.hasAttribute( QStringLiteral(
"expanded" ) ) )
474 layerRecords[layerID].expandedLayerNode = visPresetLayerElem.attribute( QStringLiteral(
"expanded" ) ).toInt();
476 visPresetLayerElem = visPresetLayerElem.nextSiblingElement( QStringLiteral(
"layer" ) );
479 QDomElement checkedLegendNodesElem = visPresetElem.firstChildElement( QStringLiteral(
"checked-legend-nodes" ) );
480 while ( !checkedLegendNodesElem.isNull() )
482 QSet<QString> checkedLegendNodes;
484 QDomElement checkedLegendNodeElem = checkedLegendNodesElem.firstChildElement( QStringLiteral(
"checked-legend-node" ) );
485 while ( !checkedLegendNodeElem.isNull() )
487 checkedLegendNodes << checkedLegendNodeElem.attribute( QStringLiteral(
"id" ) );
488 checkedLegendNodeElem = checkedLegendNodeElem.nextSiblingElement( QStringLiteral(
"checked-legend-node" ) );
491 QString layerID = checkedLegendNodesElem.attribute( QStringLiteral(
"id" ) );
492 if ( mProject->
mapLayer( layerID ) )
494 layerRecords[layerID].usingLegendItems =
true;
495 layerRecords[layerID].checkedLegendItems = checkedLegendNodes;
497 checkedLegendNodesElem = checkedLegendNodesElem.nextSiblingElement( QStringLiteral(
"checked-legend-nodes" ) );
500 QSet<QString> expandedGroupNodes;
501 if ( expandedStateInfo )
504 QDomElement expandedLegendNodesElem = visPresetElem.firstChildElement( QStringLiteral(
"expanded-legend-nodes" ) );
505 while ( !expandedLegendNodesElem.isNull() )
507 QSet<QString> expandedLegendNodes;
509 QDomElement expandedLegendNodeElem = expandedLegendNodesElem.firstChildElement( QStringLiteral(
"expanded-legend-node" ) );
510 while ( !expandedLegendNodeElem.isNull() )
512 expandedLegendNodes << expandedLegendNodeElem.attribute( QStringLiteral(
"id" ) );
513 expandedLegendNodeElem = expandedLegendNodeElem.nextSiblingElement( QStringLiteral(
"expanded-legend-node" ) );
516 QString layerID = expandedLegendNodesElem.attribute( QStringLiteral(
"id" ) );
517 if ( mProject->
mapLayer( layerID ) )
519 layerRecords[layerID].expandedLegendItems = expandedLegendNodes;
521 expandedLegendNodesElem = expandedLegendNodesElem.nextSiblingElement( QStringLiteral(
"expanded-legend-nodes" ) );
525 QDomElement expandedGroupNodesElem = visPresetElem.firstChildElement( QStringLiteral(
"expanded-group-nodes" ) );
526 if ( !expandedGroupNodesElem.isNull() )
528 QDomElement expandedGroupNodeElem = expandedGroupNodesElem.firstChildElement( QStringLiteral(
"expanded-group-node" ) );
529 while ( !expandedGroupNodeElem.isNull() )
531 expandedGroupNodes << expandedGroupNodeElem.attribute( QStringLiteral(
"id" ) );
532 expandedGroupNodeElem = expandedGroupNodeElem.nextSiblingElement( QStringLiteral(
"expanded-group-node" ) );
537 QSet<QString> checkedGroupNodes;
538 if ( checkedStateInfo )
541 QDomElement checkedGroupNodesElem = visPresetElem.firstChildElement( QStringLiteral(
"checked-group-nodes" ) );
542 if ( !checkedGroupNodesElem.isNull() )
544 QDomElement checkedGroupNodeElem = checkedGroupNodesElem.firstChildElement( QStringLiteral(
"checked-group-node" ) );
545 while ( !checkedGroupNodeElem.isNull() )
547 checkedGroupNodes << checkedGroupNodeElem.attribute( QStringLiteral(
"id" ) );
548 checkedGroupNodeElem = checkedGroupNodeElem.nextSiblingElement( QStringLiteral(
"checked-group-node" ) );
559 mMapThemes.insert( presetName, rec );
562 visPresetElem = visPresetElem.nextSiblingElement( QStringLiteral(
"visibility-preset" ) );
565 reconnectToLayersStyleManager();
571 QDomElement visPresetsElem = doc.createElement( QStringLiteral(
"visibility-presets" ) );
573 QList< QString > keys = mMapThemes.keys();
575 std::sort( keys.begin(), keys.end() );
577 for (
const QString &grpName : std::as_const( keys ) )
580 QDomElement visPresetElem = doc.createElement( QStringLiteral(
"visibility-preset" ) );
581 visPresetElem.setAttribute( QStringLiteral(
"name" ), grpName );
583 visPresetElem.setAttribute( QStringLiteral(
"has-expanded-info" ), QStringLiteral(
"1" ) );
585 visPresetElem.setAttribute( QStringLiteral(
"has-checked-group-info" ), QStringLiteral(
"1" ) );
588 if ( !layerRec.layer() )
590 QString layerID = layerRec.layer()->id();
591 QDomElement layerElem = doc.createElement( QStringLiteral(
"layer" ) );
592 layerElem.setAttribute( QStringLiteral(
"id" ), layerID );
593 layerElem.setAttribute( QStringLiteral(
"visible" ), layerRec.isVisible ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
594 if ( layerRec.usingCurrentStyle )
595 layerElem.setAttribute( QStringLiteral(
"style" ), layerRec.currentStyle );
596 visPresetElem.appendChild( layerElem );
598 if ( layerRec.usingLegendItems )
600 QDomElement checkedLegendNodesElem = doc.createElement( QStringLiteral(
"checked-legend-nodes" ) );
601 checkedLegendNodesElem.setAttribute( QStringLiteral(
"id" ), layerID );
602 for (
const QString &checkedLegendNode : std::as_const( layerRec.checkedLegendItems ) )
604 QDomElement checkedLegendNodeElem = doc.createElement( QStringLiteral(
"checked-legend-node" ) );
605 checkedLegendNodeElem.setAttribute( QStringLiteral(
"id" ), checkedLegendNode );
606 checkedLegendNodesElem.appendChild( checkedLegendNodeElem );
608 visPresetElem.appendChild( checkedLegendNodesElem );
613 layerElem.setAttribute( QStringLiteral(
"expanded" ), layerRec.expandedLayerNode ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
615 QDomElement expandedLegendNodesElem = doc.createElement( QStringLiteral(
"expanded-legend-nodes" ) );
616 expandedLegendNodesElem.setAttribute( QStringLiteral(
"id" ), layerID );
617 for (
const QString &expandedLegendNode : std::as_const( layerRec.expandedLegendItems ) )
619 QDomElement expandedLegendNodeElem = doc.createElement( QStringLiteral(
"expanded-legend-node" ) );
620 expandedLegendNodeElem.setAttribute( QStringLiteral(
"id" ), expandedLegendNode );
621 expandedLegendNodesElem.appendChild( expandedLegendNodeElem );
623 visPresetElem.appendChild( expandedLegendNodesElem );
629 QDomElement checkedGroupElems = doc.createElement( QStringLiteral(
"checked-group-nodes" ) );
631 for (
const QString &groupId : checkedGroupNodes )
633 QDomElement checkedGroupElem = doc.createElement( QStringLiteral(
"checked-group-node" ) );
634 checkedGroupElem.setAttribute( QStringLiteral(
"id" ), groupId );
635 checkedGroupElems.appendChild( checkedGroupElem );
637 visPresetElem.appendChild( checkedGroupElems );
642 QDomElement expandedGroupElems = doc.createElement( QStringLiteral(
"expanded-group-nodes" ) );
644 for (
const QString &groupId : expandedGroupNodes )
646 QDomElement expandedGroupElem = doc.createElement( QStringLiteral(
"expanded-group-node" ) );
647 expandedGroupElem.setAttribute( QStringLiteral(
"id" ), groupId );
648 expandedGroupElems.appendChild( expandedGroupElem );
650 visPresetElem.appendChild( expandedGroupElems );
653 visPresetsElem.appendChild( visPresetElem );
656 doc.firstChildElement( QStringLiteral(
"qgis" ) ).appendChild( visPresetsElem );
659 void QgsMapThemeCollection::registryLayersRemoved(
const QStringList &layerIDs )
663 QSet< QString > changedThemes;
664 MapThemeRecordMap::iterator it = mMapThemes.begin();
665 for ( ; it != mMapThemes.end(); ++it )
667 MapThemeRecord &rec = it.value();
668 for (
int i = 0; i < rec.mLayerRecords.count(); ++i )
670 MapThemeLayerRecord &layerRec = rec.mLayerRecords[i];
671 if ( layerRec.layer() && layerIDs.contains( layerRec.layer()->id() ) )
673 rec.mLayerRecords.removeAt( i-- );
674 changedThemes << it.key();
679 for (
const QString &theme : std::as_const( changedThemes ) )
686 void QgsMapThemeCollection::layerStyleRenamed(
const QString &oldName,
const QString &newName )
692 QSet< QString > changedThemes;
694 MapThemeRecordMap::iterator it = mMapThemes.begin();
695 for ( ; it != mMapThemes.end(); ++it )
697 MapThemeRecord &rec = it.value();
698 for (
int i = 0; i < rec.mLayerRecords.count(); ++i )
700 MapThemeLayerRecord &layerRec = rec.mLayerRecords[i];
701 if ( layerRec.layer() == styleMgr->
layer() )
703 if ( layerRec.currentStyle == oldName )
705 layerRec.currentStyle = newName;
706 changedThemes << it.key();
712 for (
const QString &theme : std::as_const( changedThemes ) )
721 for (
int i = 0; i < mLayerRecords.length(); ++i )
723 if ( mLayerRecords.at( i ).layer() == layer )
724 mLayerRecords.removeAt( i );
730 mLayerRecords.append( record );
735 QHash<QgsMapLayer *, MapThemeLayerRecord> validSet;
738 if (
auto *lLayer = layerRec.layer() )
739 validSet.insert( lLayer, layerRec );