27 #include <QInputDialog>
37 MapThemeLayerRecord layerRec( nodeLayer->
layer() );
38 layerRec.isVisible = nodeLayer->
isVisible();
39 layerRec.usingCurrentStyle =
true;
41 layerRec.expandedLayerNode = nodeLayer->
isExpanded();
42 layerRec.expandedLegendItems = qgis::listToSet( nodeLayer->
customProperty( QStringLiteral(
"expandedLegendNodes" ) ).toStringList() );
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 )
127 MapThemeLayerRecord layerRec;
128 const bool recordExists = findRecordForLayer( nodeLayer->
layer(), rec, layerRec );
144 if ( layerRec.usingCurrentStyle )
150 if ( layerRec.usingLegendItems )
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 );
178 nodeLayer->
setExpanded( layerRec.expandedLayerNode );
179 nodeLayer->
setCustomProperty( QStringLiteral(
"expandedLegendNodes" ), QStringList( qgis::setToList( layerRec.expandedLegendItems ) ) );
186 const QList<QgsLayerTreeNode *> constChildren = parent->
children();
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 ) || mMapThemes.contains( newName ) )
291 insert( newName, newState );
299 if ( !mMapThemes.contains( name ) )
302 mMapThemes.remove( name );
304 reconnectToLayersStyleManager();
312 reconnectToLayersStyleManager();
318 return mMapThemes.keys();
323 QStringList layerIds;
325 for (
QgsMapLayer *layer : constMapThemeVisibleLayers )
327 layerIds << layer->
id();
334 QList<QgsMapLayer *> layers;
335 const QList<MapThemeLayerRecord> recs = mMapThemes.value( name ).mLayerRecords;
337 if ( layerOrder.isEmpty() )
340 const QList<MapThemeLayerRecord> records { mMapThemes.value( name ).mLayerRecords };
343 if ( layerRec.isVisible && layerRec.layer() )
344 layers << layerRec.layer();
353 if ( layerRec.isVisible && layerRec.layer() == layer )
354 layers << layerRec.layer();
363 void QgsMapThemeCollection::applyMapThemeCheckedLegendNodesToLayer(
const MapThemeLayerRecord &layerRec,
QgsMapLayer *layer )
366 if ( !vlayer || !vlayer->
renderer() )
373 bool someNodesUnchecked = layerRec.usingLegendItems;
379 bool shouldBeChecked = someNodesUnchecked ? layerRec.checkedLegendItems.contains( item.ruleKey() ) :
true;
380 if ( checked != shouldBeChecked )
388 QMap<QString, QString> styleOverrides;
389 if ( !mMapThemes.contains( presetName ) )
390 return styleOverrides;
392 const QList<MapThemeLayerRecord> records {mMapThemes.value( presetName ).mLayerRecords};
395 if ( !layerRec.layer() )
398 if ( layerRec.usingCurrentStyle )
405 applyMapThemeCheckedLegendNodesToLayer( layerRec, layer );
410 styleOverrides[layer->
id()] = layerStyle.
xmlData();
413 return styleOverrides;
416 void QgsMapThemeCollection::reconnectToLayersStyleManager()
420 QSet<QgsMapLayer *> layers;
421 for (
const MapThemeRecord &rec : qgis::as_const( mMapThemes ) )
423 for (
const MapThemeLayerRecord &layerRec : qgis::as_const( rec.mLayerRecords ) )
425 if ( layerRec.layer() )
426 layers << layerRec.layer();
430 const QSet<QgsMapLayer *> constLayers = layers;
441 QDomElement visPresetsElem = doc.firstChildElement( QStringLiteral(
"qgis" ) ).firstChildElement( QStringLiteral(
"visibility-presets" ) );
442 if ( visPresetsElem.isNull() )
445 QDomElement visPresetElem = visPresetsElem.firstChildElement( QStringLiteral(
"visibility-preset" ) );
446 while ( !visPresetElem.isNull() )
448 QHash<QString, MapThemeLayerRecord> layerRecords;
450 bool expandedStateInfo =
false;
451 if ( visPresetElem.hasAttribute( QStringLiteral(
"has-expanded-info" ) ) )
452 expandedStateInfo = visPresetElem.attribute( QStringLiteral(
"has-expanded-info" ) ).toInt();
454 bool checkedStateInfo =
false;
455 if ( visPresetElem.hasAttribute( QStringLiteral(
"has-checked-group-info" ) ) )
456 checkedStateInfo = visPresetElem.attribute( QStringLiteral(
"has-checked-group-info" ) ).toInt();
458 QString presetName = visPresetElem.attribute( QStringLiteral(
"name" ) );
459 QDomElement visPresetLayerElem = visPresetElem.firstChildElement( QStringLiteral(
"layer" ) );
460 while ( !visPresetLayerElem.isNull() )
462 QString layerID = visPresetLayerElem.attribute( QStringLiteral(
"id" ) );
466 layerRecords[layerID].isVisible = visPresetLayerElem.attribute( QStringLiteral(
"visible" ), QStringLiteral(
"1" ) ).toInt();
468 if ( visPresetLayerElem.hasAttribute( QStringLiteral(
"style" ) ) )
470 layerRecords[layerID].usingCurrentStyle =
true;
471 layerRecords[layerID].currentStyle = visPresetLayerElem.attribute( QStringLiteral(
"style" ) );
474 if ( visPresetLayerElem.hasAttribute( QStringLiteral(
"expanded" ) ) )
475 layerRecords[layerID].expandedLayerNode = visPresetLayerElem.attribute( QStringLiteral(
"expanded" ) ).toInt();
477 visPresetLayerElem = visPresetLayerElem.nextSiblingElement( QStringLiteral(
"layer" ) );
480 QDomElement checkedLegendNodesElem = visPresetElem.firstChildElement( QStringLiteral(
"checked-legend-nodes" ) );
481 while ( !checkedLegendNodesElem.isNull() )
483 QSet<QString> checkedLegendNodes;
485 QDomElement checkedLegendNodeElem = checkedLegendNodesElem.firstChildElement( QStringLiteral(
"checked-legend-node" ) );
486 while ( !checkedLegendNodeElem.isNull() )
488 checkedLegendNodes << checkedLegendNodeElem.attribute( QStringLiteral(
"id" ) );
489 checkedLegendNodeElem = checkedLegendNodeElem.nextSiblingElement( QStringLiteral(
"checked-legend-node" ) );
492 QString layerID = checkedLegendNodesElem.attribute( QStringLiteral(
"id" ) );
493 if ( mProject->
mapLayer( layerID ) )
495 layerRecords[layerID].usingLegendItems =
true;
496 layerRecords[layerID].checkedLegendItems = checkedLegendNodes;
498 checkedLegendNodesElem = checkedLegendNodesElem.nextSiblingElement( QStringLiteral(
"checked-legend-nodes" ) );
501 QSet<QString> expandedGroupNodes;
502 if ( expandedStateInfo )
505 QDomElement expandedLegendNodesElem = visPresetElem.firstChildElement( QStringLiteral(
"expanded-legend-nodes" ) );
506 while ( !expandedLegendNodesElem.isNull() )
508 QSet<QString> expandedLegendNodes;
510 QDomElement expandedLegendNodeElem = expandedLegendNodesElem.firstChildElement( QStringLiteral(
"expanded-legend-node" ) );
511 while ( !expandedLegendNodeElem.isNull() )
513 expandedLegendNodes << expandedLegendNodeElem.attribute( QStringLiteral(
"id" ) );
514 expandedLegendNodeElem = expandedLegendNodeElem.nextSiblingElement( QStringLiteral(
"expanded-legend-node" ) );
517 QString layerID = expandedLegendNodesElem.attribute( QStringLiteral(
"id" ) );
518 if ( mProject->
mapLayer( layerID ) )
520 layerRecords[layerID].expandedLegendItems = expandedLegendNodes;
522 expandedLegendNodesElem = expandedLegendNodesElem.nextSiblingElement( QStringLiteral(
"expanded-legend-nodes" ) );
526 QDomElement expandedGroupNodesElem = visPresetElem.firstChildElement( QStringLiteral(
"expanded-group-nodes" ) );
527 if ( !expandedGroupNodesElem.isNull() )
529 QDomElement expandedGroupNodeElem = expandedGroupNodesElem.firstChildElement( QStringLiteral(
"expanded-group-node" ) );
530 while ( !expandedGroupNodeElem.isNull() )
532 expandedGroupNodes << expandedGroupNodeElem.attribute( QStringLiteral(
"id" ) );
533 expandedGroupNodeElem = expandedGroupNodeElem.nextSiblingElement( QStringLiteral(
"expanded-group-node" ) );
538 QSet<QString> checkedGroupNodes;
539 if ( checkedStateInfo )
542 QDomElement checkedGroupNodesElem = visPresetElem.firstChildElement( QStringLiteral(
"checked-group-nodes" ) );
543 if ( !checkedGroupNodesElem.isNull() )
545 QDomElement checkedGroupNodeElem = checkedGroupNodesElem.firstChildElement( QStringLiteral(
"checked-group-node" ) );
546 while ( !checkedGroupNodeElem.isNull() )
548 checkedGroupNodes << checkedGroupNodeElem.attribute( QStringLiteral(
"id" ) );
549 checkedGroupNodeElem = checkedGroupNodeElem.nextSiblingElement( QStringLiteral(
"checked-group-node" ) );
560 mMapThemes.insert( presetName, rec );
563 visPresetElem = visPresetElem.nextSiblingElement( QStringLiteral(
"visibility-preset" ) );
566 reconnectToLayersStyleManager();
572 QDomElement visPresetsElem = doc.createElement( QStringLiteral(
"visibility-presets" ) );
574 QList< QString > keys = mMapThemes.keys();
576 std::sort( keys.begin(), keys.end() );
578 for (
const QString &grpName : qgis::as_const( keys ) )
581 QDomElement visPresetElem = doc.createElement( QStringLiteral(
"visibility-preset" ) );
582 visPresetElem.setAttribute( QStringLiteral(
"name" ), grpName );
584 visPresetElem.setAttribute( QStringLiteral(
"has-expanded-info" ), QStringLiteral(
"1" ) );
586 visPresetElem.setAttribute( QStringLiteral(
"has-checked-group-info" ), QStringLiteral(
"1" ) );
589 if ( !layerRec.layer() )
591 QString layerID = layerRec.layer()->id();
592 QDomElement layerElem = doc.createElement( QStringLiteral(
"layer" ) );
593 layerElem.setAttribute( QStringLiteral(
"id" ), layerID );
594 layerElem.setAttribute( QStringLiteral(
"visible" ), layerRec.isVisible ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
595 if ( layerRec.usingCurrentStyle )
596 layerElem.setAttribute( QStringLiteral(
"style" ), layerRec.currentStyle );
597 visPresetElem.appendChild( layerElem );
599 if ( layerRec.usingLegendItems )
601 QDomElement checkedLegendNodesElem = doc.createElement( QStringLiteral(
"checked-legend-nodes" ) );
602 checkedLegendNodesElem.setAttribute( QStringLiteral(
"id" ), layerID );
603 for (
const QString &checkedLegendNode : qgis::as_const( layerRec.checkedLegendItems ) )
605 QDomElement checkedLegendNodeElem = doc.createElement( QStringLiteral(
"checked-legend-node" ) );
606 checkedLegendNodeElem.setAttribute( QStringLiteral(
"id" ), checkedLegendNode );
607 checkedLegendNodesElem.appendChild( checkedLegendNodeElem );
609 visPresetElem.appendChild( checkedLegendNodesElem );
614 layerElem.setAttribute( QStringLiteral(
"expanded" ), layerRec.expandedLayerNode ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
616 QDomElement expandedLegendNodesElem = doc.createElement( QStringLiteral(
"expanded-legend-nodes" ) );
617 expandedLegendNodesElem.setAttribute( QStringLiteral(
"id" ), layerID );
618 for (
const QString &expandedLegendNode : qgis::as_const( layerRec.expandedLegendItems ) )
620 QDomElement expandedLegendNodeElem = doc.createElement( QStringLiteral(
"expanded-legend-node" ) );
621 expandedLegendNodeElem.setAttribute( QStringLiteral(
"id" ), expandedLegendNode );
622 expandedLegendNodesElem.appendChild( expandedLegendNodeElem );
624 visPresetElem.appendChild( expandedLegendNodesElem );
630 QDomElement checkedGroupElems = doc.createElement( QStringLiteral(
"checked-group-nodes" ) );
632 for (
const QString &groupId : checkedGroupNodes )
634 QDomElement checkedGroupElem = doc.createElement( QStringLiteral(
"checked-group-node" ) );
635 checkedGroupElem.setAttribute( QStringLiteral(
"id" ), groupId );
636 checkedGroupElems.appendChild( checkedGroupElem );
638 visPresetElem.appendChild( checkedGroupElems );
643 QDomElement expandedGroupElems = doc.createElement( QStringLiteral(
"expanded-group-nodes" ) );
645 for (
const QString &groupId : expandedGroupNodes )
647 QDomElement expandedGroupElem = doc.createElement( QStringLiteral(
"expanded-group-node" ) );
648 expandedGroupElem.setAttribute( QStringLiteral(
"id" ), groupId );
649 expandedGroupElems.appendChild( expandedGroupElem );
651 visPresetElem.appendChild( expandedGroupElems );
654 visPresetsElem.appendChild( visPresetElem );
657 doc.firstChildElement( QStringLiteral(
"qgis" ) ).appendChild( visPresetsElem );
660 void QgsMapThemeCollection::registryLayersRemoved(
const QStringList &layerIDs )
664 QSet< QString > changedThemes;
665 MapThemeRecordMap::iterator it = mMapThemes.begin();
666 for ( ; it != mMapThemes.end(); ++it )
668 MapThemeRecord &rec = it.value();
669 for (
int i = 0; i < rec.mLayerRecords.count(); ++i )
671 MapThemeLayerRecord &layerRec = rec.mLayerRecords[i];
672 if ( layerRec.layer() && layerIDs.contains( layerRec.layer()->id() ) )
674 rec.mLayerRecords.removeAt( i-- );
675 changedThemes << it.key();
680 for (
const QString &theme : qgis::as_const( changedThemes ) )
687 void QgsMapThemeCollection::layerStyleRenamed(
const QString &oldName,
const QString &newName )
693 QSet< QString > changedThemes;
695 MapThemeRecordMap::iterator it = mMapThemes.begin();
696 for ( ; it != mMapThemes.end(); ++it )
698 MapThemeRecord &rec = it.value();
699 for (
int i = 0; i < rec.mLayerRecords.count(); ++i )
701 MapThemeLayerRecord &layerRec = rec.mLayerRecords[i];
702 if ( layerRec.layer() == styleMgr->
layer() )
704 if ( layerRec.currentStyle == oldName )
706 layerRec.currentStyle = newName;
707 changedThemes << it.key();
713 for (
const QString &theme : qgis::as_const( changedThemes ) )
722 for (
int i = 0; i < mLayerRecords.length(); ++i )
724 if ( mLayerRecords.at( i ).layer() == layer )
725 mLayerRecords.removeAt( i );
731 mLayerRecords.append( record );
736 QHash<QgsMapLayer *, MapThemeLayerRecord> validSet;
739 if ( layerRec.layer() )
740 validSet.insert( layerRec.layer(), layerRec );