QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
qgsvisibilitypresetcollection.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsvisibilitypresetcollection.cpp
3  --------------------------------------
4  Date : September 2014
5  Copyright : (C) 2014 by Martin Dobias
6  Email : wonder dot sk at gmail 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 "qgslayertree.h"
19 #include "qgslayertreemodel.h"
21 #include "qgsmaplayerregistry.h"
23 #include "qgsproject.h"
24 #include "qgsrendererv2.h"
25 #include "qgsvectorlayer.h"
26 
27 #include <QInputDialog>
28 
30 {
31  connect( QgsMapLayerRegistry::instance(), SIGNAL( layersRemoved( QStringList ) ),
32  this, SLOT( registryLayersRemoved( QStringList ) ) );
33 }
34 
36 {
37  Q_FOREACH ( QgsLayerTreeNode* node, parent->children() )
38  {
39  if ( QgsLayerTree::isGroup( node ) )
41  else if ( QgsLayerTree::isLayer( node ) )
42  {
43  QgsLayerTreeLayer* nodeLayer = QgsLayerTree::toLayer( node );
44  if ( nodeLayer->isVisible() )
45  rec.mVisibleLayerIDs << nodeLayer->layerId();
46  }
47  }
48 }
49 
51 {
52  return mPresets.contains( name );
53 }
54 
56 {
57  mPresets.insert( name, state );
58 
60  emit presetsChanged();
61 }
62 
64 {
65  if ( !mPresets.contains( name ) )
66  return;
67 
68  mPresets[name] = state;
69 
71  emit presetsChanged();
72 }
73 
75 {
76  if ( !mPresets.contains( name ) )
77  return;
78 
79  mPresets.remove( name );
80 
82  emit presetsChanged();
83 }
84 
86 {
87  mPresets.clear();
88 
90  emit presetsChanged();
91 }
92 
94 {
95  return mPresets.keys();
96 }
97 
99 {
100  return mPresets.value( name ).mVisibleLayerIDs;
101 }
102 
103 
105 {
106  if ( !mPresets.contains( name ) )
107  return;
108 
109  QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( layerID );
110  if ( !layer )
111  return;
112 
113  const PresetRecord& rec = mPresets[name];
114 
115  QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer*>( layer );
116  if ( !vlayer || !vlayer->rendererV2() )
117  return;
118 
119  if ( !vlayer->rendererV2()->legendSymbolItemsCheckable() )
120  return; // no need to do anything
121 
122  bool someNodesUnchecked = rec.mPerLayerCheckedLegendSymbols.contains( layerID );
123 
124  Q_FOREACH ( const QgsLegendSymbolItemV2& item, vlayer->rendererV2()->legendSymbolItemsV2() )
125  {
126  bool checked = vlayer->rendererV2()->legendSymbolItemChecked( item.ruleKey() );
127  bool shouldBeChecked = someNodesUnchecked ? rec.mPerLayerCheckedLegendSymbols[layerID].contains( item.ruleKey() ) : true;
128  if ( checked != shouldBeChecked )
129  vlayer->rendererV2()->checkLegendSymbolItem( item.ruleKey(), shouldBeChecked );
130  }
131 }
132 
133 
135 {
136  QMap<QString, QString> styleOverrides;
137  if ( !mPresets.contains( presetName ) )
138  return styleOverrides;
139 
140  QStringList lst = presetVisibleLayers( presetName );
141  const QgsVisibilityPresetCollection::PresetRecord& rec = mPresets[presetName];
142  Q_FOREACH ( const QString& layerID, lst )
143  {
144  QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( layerID );
145  if ( !layer )
146  continue;
147 
148  // use either the stored style name or the current one if none has been stored
149  QString overrideStyleName = rec.mPerLayerCurrentStyle.value( layerID, layer->styleManager()->currentStyle() );
150 
151  // store original style and temporarily apply a style
152  layer->styleManager()->setOverrideStyle( overrideStyleName );
153 
154  // set the checked legend nodes
155  applyPresetCheckedLegendNodesToLayer( presetName, layerID );
156 
157  // save to overrides
158  QgsMapLayerStyle layerStyle;
159  layerStyle.readFromLayer( layer );
160  styleOverrides[layerID] = layerStyle.xmlData();
161 
163  }
164  return styleOverrides;
165 }
166 
168 {
169  // disconnect( 0, 0, this, SLOT( layerStyleRenamed( QString, QString ) ) );
170 
171  QSet<QString> layerIDs;
172  PresetRecordMap::const_iterator it = mPresets.constBegin();
173  for ( ; it != mPresets.constEnd(); ++it )
174  {
175  const PresetRecord& rec = it.value();
177  for ( ; layerIt != rec.mPerLayerCurrentStyle.constEnd(); ++layerIt )
178  layerIDs << layerIt.key();
179  }
180 
181  Q_FOREACH ( const QString& layerID, layerIDs )
182  {
183  if ( QgsMapLayer* ml = QgsMapLayerRegistry::instance()->mapLayer( layerID ) )
184  connect( ml->styleManager(), SIGNAL( styleRenamed( QString, QString ) ), this, SLOT( layerStyleRenamed( QString, QString ) ) );
185  }
186 }
187 
189 {
190  clear();
191 
192  QDomElement visPresetsElem = doc.firstChildElement( "qgis" ).firstChildElement( "visibility-presets" );
193  if ( visPresetsElem.isNull() )
194  return;
195 
196  QDomElement visPresetElem = visPresetsElem.firstChildElement( "visibility-preset" );
197  while ( !visPresetElem.isNull() )
198  {
199  QString presetName = visPresetElem.attribute( "name" );
200  PresetRecord rec;
201  QDomElement visPresetLayerElem = visPresetElem.firstChildElement( "layer" );
202  while ( !visPresetLayerElem.isNull() )
203  {
204  QString layerID = visPresetLayerElem.attribute( "id" );
205  if ( QgsMapLayerRegistry::instance()->mapLayer( layerID ) )
206  {
207  rec.mVisibleLayerIDs << layerID; // only use valid layer IDs
208  if ( visPresetLayerElem.hasAttribute( "style" ) )
209  rec.mPerLayerCurrentStyle[layerID] = visPresetLayerElem.attribute( "style" );
210  }
211  visPresetLayerElem = visPresetLayerElem.nextSiblingElement( "layer" );
212  }
213 
214  QDomElement checkedLegendNodesElem = visPresetElem.firstChildElement( "checked-legend-nodes" );
215  while ( !checkedLegendNodesElem.isNull() )
216  {
217  QSet<QString> checkedLegendNodes;
218 
219  QDomElement checkedLegendNodeElem = checkedLegendNodesElem.firstChildElement( "checked-legend-node" );
220  while ( !checkedLegendNodeElem.isNull() )
221  {
222  checkedLegendNodes << checkedLegendNodeElem.attribute( "id" );
223  checkedLegendNodeElem = checkedLegendNodeElem.nextSiblingElement( "checked-legend-node" );
224  }
225 
226  QString layerID = checkedLegendNodesElem.attribute( "id" );
227  if ( QgsMapLayerRegistry::instance()->mapLayer( layerID ) ) // only use valid IDs
228  rec.mPerLayerCheckedLegendSymbols.insert( layerID, checkedLegendNodes );
229  checkedLegendNodesElem = checkedLegendNodesElem.nextSiblingElement( "checked-legend-nodes" );
230  }
231 
232  mPresets.insert( presetName, rec );
233 
234  visPresetElem = visPresetElem.nextSiblingElement( "visibility-preset" );
235  }
236 
238  emit presetsChanged();
239 }
240 
242 {
243  QDomElement visPresetsElem = doc.createElement( "visibility-presets" );
244  PresetRecordMap::const_iterator it = mPresets.constBegin();
245  for ( ; it != mPresets.constEnd(); ++ it )
246  {
247  QString grpName = it.key();
248  const PresetRecord& rec = it.value();
249  QDomElement visPresetElem = doc.createElement( "visibility-preset" );
250  visPresetElem.setAttribute( "name", grpName );
251  Q_FOREACH ( const QString& layerID, rec.mVisibleLayerIDs )
252  {
253  QDomElement layerElem = doc.createElement( "layer" );
254  layerElem.setAttribute( "id", layerID );
255  if ( rec.mPerLayerCurrentStyle.contains( layerID ) )
256  layerElem.setAttribute( "style", rec.mPerLayerCurrentStyle[layerID] );
257  visPresetElem.appendChild( layerElem );
258  }
259 
260  QMap<QString, QSet<QString> >::const_iterator layerIt = rec.mPerLayerCheckedLegendSymbols.constBegin();
261  for ( ; layerIt != rec.mPerLayerCheckedLegendSymbols.constEnd(); ++layerIt )
262  {
263  QString layerID = layerIt.key();
264  QDomElement checkedLegendNodesElem = doc.createElement( "checked-legend-nodes" );
265  checkedLegendNodesElem.setAttribute( "id", layerID );
266  Q_FOREACH ( const QString& checkedLegendNode, layerIt.value() )
267  {
268  QDomElement checkedLegendNodeElem = doc.createElement( "checked-legend-node" );
269  checkedLegendNodeElem.setAttribute( "id", checkedLegendNode );
270  checkedLegendNodesElem.appendChild( checkedLegendNodeElem );
271  }
272  visPresetElem.appendChild( checkedLegendNodesElem );
273  }
274 
275  visPresetsElem.appendChild( visPresetElem );
276  }
277 
278  doc.firstChildElement( "qgis" ).appendChild( visPresetsElem );
279 }
280 
282 {
283  Q_FOREACH ( const QString& layerID, layerIDs )
284  {
285  PresetRecordMap::iterator it = mPresets.begin();
286  for ( ; it != mPresets.end(); ++it )
287  {
288  PresetRecord& rec = it.value();
289  rec.mVisibleLayerIDs.removeAll( layerID );
290  rec.mPerLayerCheckedLegendSymbols.remove( layerID );
291  rec.mPerLayerCurrentStyle.remove( layerID );
292  }
293  }
294  emit presetsChanged();
295 }
296 
298 {
299  QgsMapLayerStyleManager* styleMgr = qobject_cast<QgsMapLayerStyleManager*>( sender() );
300  if ( !styleMgr )
301  return;
302 
303  QString layerID = styleMgr->layer()->id();
304 
305  PresetRecordMap::iterator it = mPresets.begin();
306  for ( ; it != mPresets.end(); ++it )
307  {
308  PresetRecord& rec = it.value();
309 
310  if ( rec.mPerLayerCurrentStyle.contains( layerID ) )
311  {
312  QString styleName = rec.mPerLayerCurrentStyle[layerID];
313  if ( styleName == oldName )
314  rec.mPerLayerCurrentStyle[layerID] = newName;
315  }
316  }
317  emit presetsChanged();
318 }
bool restoreOverrideStyle()
Restore the original store after a call to setOverrideStyle()
Layer tree group node serves as a container for layers and further groups.
void clear()
Remove all presets from the collection.
Base class for all map layer types.
Definition: qgsmaplayer.h:49
void presetsChanged()
Emitted when presets within the collection are changed.
void layerStyleRenamed(const QString &oldName, const QString &newName)
Update style name if a stored style gets renamed.
bool contains(const Key &key) const
void readXML(const QDomDocument &doc)
Reads the preset collection state from XML.
QDomNode appendChild(const QDomNode &newChild)
QString xmlData() const
Return XML content of the style.
QString attribute(const QString &name, const QString &defValue) const
QMap< QString, QString > presetStyleOverrides(const QString &name)
Get layer style overrides (for QgsMapSettings) of the visible layers for given preset.
QObject * sender() const
QgsMapLayer * mapLayer(const QString &theLayerId) const
Retrieve a pointer to a registered layer by layer ID.
QString ruleKey() const
Return unique identifier of the rule for identification of the item within renderer.
const_iterator constBegin() const
Qt::CheckState isVisible() const
void writeXML(QDomDocument &doc)
Writes the preset collection state to XML.
QDomElement nextSiblingElement(const QString &tagName) const
void applyPresetCheckedLegendNodesToLayer(const QString &name, const QString &layerID)
Apply check states of legend nodes of a given layer as defined in the preset.
virtual QgsLegendSymbolListV2 legendSymbolItemsV2() const
Return a list of symbology items for the legend.
void clear()
QString layerId() const
virtual bool legendSymbolItemChecked(const QString &key)
items of symbology items in legend is checked
virtual void checkLegendSymbolItem(const QString &key, bool state=true)
item in symbology was checked
QgsLayerTreeGroup * toGroup(QgsLayerTreeNode *node)
Cast node to a group. No type checking is done - use isGroup() to find out whether this operation is ...
Definition: qgslayertree.h:46
QgsMapLayerStyleManager * styleManager() const
Get access to the layer&#39;s style manager.
void readFromLayer(QgsMapLayer *layer)
Store layer&#39;s active style information in the instance.
QList< Key > keys() const
void update(const QString &name, const PresetRecord &state)
Updates a preset within the collection.
Stores style information (renderer, transparency, labeling, diagrams etc.) applicable to a map layer...
const char * name() const
void reconnectToLayersStyleManager()
Reconnects all preset layers to handle style renames.
QgsFeatureRendererV2 * rendererV2()
Return renderer V2.
QString id() const
Get this layer&#39;s unique ID, this ID is used to access this layer from map layer registry.
void insert(const QString &name, const PresetRecord &state)
Inserts a new preset to the collection.
bool hasAttribute(const QString &name) const
QMap< QString, QString > mPerLayerCurrentStyle
For layers that use multiple styles - which one is currently selected.
void setAttribute(const QString &name, const QString &value)
int removeAll(const T &value)
const_iterator constEnd() const
void removePreset(const QString &name)
Remove existing preset from collection.
QStringList mVisibleLayerIDs
Ordered list of layers that are visible.
This class is a base class for nodes in a layer tree.
iterator end()
QList< QgsLayerTreeNode * > children()
Get list of children of the node. Children are owned by the parent.
bool isLayer(QgsLayerTreeNode *node)
Check whether the node is a valid layer node.
Definition: qgslayertree.h:40
iterator begin()
static void addVisibleLayersToPreset(QgsLayerTreeGroup *parent, PresetRecord &rec)
Static method for adding visible layers from a layer tree group to a preset record.
QgsMapLayer * layer() const
Get pointer to the associated map layer.
bool isNull() const
QString currentStyle() const
Return name of the current style.
const Key key(const T &value) const
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
Individual preset record of visible layers and styles.
QgsLayerTreeLayer * toLayer(QgsLayerTreeNode *node)
Cast node to a layer. No type checking is done - use isLayer() to find out whether this operation is ...
Definition: qgslayertree.h:52
QDomElement firstChildElement(const QString &tagName) const
void registryLayersRemoved(const QStringList &layerIDs)
Handles updates of the preset collection when layers are removed from the registry.
iterator insert(const Key &key, const T &value)
QStringList presetVisibleLayers(const QString &name) const
Returns the list of layer IDs that should be visible for the specified preset.
bool setOverrideStyle(const QString &styleDef)
Temporarily apply a different style to the layer.
virtual bool legendSymbolItemsCheckable() const
items of symbology items in legend should be checkable
QDomElement createElement(const QString &tagName)
QMap< QString, QSet< QString > > mPerLayerCheckedLegendSymbols
For layers that have checkable legend symbols and not all symbols are checked - list which ones are...
bool hasPreset(const QString &name) const
Returns whether a preset with a matching name exists.
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
Management of styles for use with one map layer.
QObject * parent() const
QStringList presets() const
Returns a list of existing preset names.
Represents a vector layer which manages a vector based data sets.
bool isGroup(QgsLayerTreeNode *node)
Check whether the node is a valid group node.
Definition: qgslayertree.h:34
The class stores information about one class/rule of a vector layer renderer in a unified way that ca...
Layer tree node points to a map layer.
const T value(const Key &key) const
int remove(const Key &key)