QGIS API Documentation  2.14.0-Essen
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 }
61 
63 {
64  if ( !mPresets.contains( name ) )
65  return;
66 
67  mPresets[name] = state;
68 
70 }
71 
73 {
74  if ( !mPresets.contains( name ) )
75  return;
76 
77  mPresets.remove( name );
78 
80 }
81 
83 {
84  mPresets.clear();
85 
87 }
88 
90 {
91  return mPresets.keys();
92 }
93 
95 {
96  return mPresets.value( name ).mVisibleLayerIDs;
97 }
98 
99 
101 {
102  if ( !mPresets.contains( name ) )
103  return;
104 
105  QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( layerID );
106  if ( !layer )
107  return;
108 
109  const PresetRecord& rec = mPresets[name];
110 
111  QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer*>( layer );
112  if ( !vlayer || !vlayer->rendererV2() )
113  return;
114 
115  if ( !vlayer->rendererV2()->legendSymbolItemsCheckable() )
116  return; // no need to do anything
117 
118  bool someNodesUnchecked = rec.mPerLayerCheckedLegendSymbols.contains( layerID );
119 
120  Q_FOREACH ( const QgsLegendSymbolItemV2& item, vlayer->rendererV2()->legendSymbolItemsV2() )
121  {
122  bool checked = vlayer->rendererV2()->legendSymbolItemChecked( item.ruleKey() );
123  bool shouldBeChecked = someNodesUnchecked ? rec.mPerLayerCheckedLegendSymbols[layerID].contains( item.ruleKey() ) : true;
124  if ( checked != shouldBeChecked )
125  vlayer->rendererV2()->checkLegendSymbolItem( item.ruleKey(), shouldBeChecked );
126  }
127 }
128 
129 
131 {
132  QMap<QString, QString> styleOverrides;
133  if ( !mPresets.contains( presetName ) )
134  return styleOverrides;
135 
136  QStringList lst = presetVisibleLayers( presetName );
137  const QgsVisibilityPresetCollection::PresetRecord& rec = mPresets[presetName];
138  Q_FOREACH ( const QString& layerID, lst )
139  {
140  QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( layerID );
141  if ( !layer )
142  continue;
143 
144  // use either the stored style name or the current one if none has been stored
145  QString overrideStyleName = rec.mPerLayerCurrentStyle.value( layerID, layer->styleManager()->currentStyle() );
146 
147  // store original style and temporarily apply a style
148  layer->styleManager()->setOverrideStyle( overrideStyleName );
149 
150  // set the checked legend nodes
151  applyPresetCheckedLegendNodesToLayer( presetName, layerID );
152 
153  // save to overrides
154  QgsMapLayerStyle layerStyle;
155  layerStyle.readFromLayer( layer );
156  styleOverrides[layerID] = layerStyle.xmlData();
157 
159  }
160  return styleOverrides;
161 }
162 
164 {
165  // disconnect( 0, 0, this, SLOT( layerStyleRenamed( QString, QString ) ) );
166 
167  QSet<QString> layerIDs;
168  PresetRecordMap::const_iterator it = mPresets.constBegin();
169  for ( ; it != mPresets.constEnd(); ++it )
170  {
171  const PresetRecord& rec = it.value();
173  for ( ; layerIt != rec.mPerLayerCurrentStyle.constEnd(); ++layerIt )
174  layerIDs << layerIt.key();
175  }
176 
177  Q_FOREACH ( const QString& layerID, layerIDs )
178  {
179  if ( QgsMapLayer* ml = QgsMapLayerRegistry::instance()->mapLayer( layerID ) )
180  connect( ml->styleManager(), SIGNAL( styleRenamed( QString, QString ) ), this, SLOT( layerStyleRenamed( QString, QString ) ) );
181  }
182 }
183 
185 {
186  clear();
187 
188  QDomElement visPresetsElem = doc.firstChildElement( "qgis" ).firstChildElement( "visibility-presets" );
189  if ( visPresetsElem.isNull() )
190  return;
191 
192  QDomElement visPresetElem = visPresetsElem.firstChildElement( "visibility-preset" );
193  while ( !visPresetElem.isNull() )
194  {
195  QString presetName = visPresetElem.attribute( "name" );
196  PresetRecord rec;
197  QDomElement visPresetLayerElem = visPresetElem.firstChildElement( "layer" );
198  while ( !visPresetLayerElem.isNull() )
199  {
200  QString layerID = visPresetLayerElem.attribute( "id" );
201  if ( QgsMapLayerRegistry::instance()->mapLayer( layerID ) )
202  {
203  rec.mVisibleLayerIDs << layerID; // only use valid layer IDs
204  if ( visPresetLayerElem.hasAttribute( "style" ) )
205  rec.mPerLayerCurrentStyle[layerID] = visPresetLayerElem.attribute( "style" );
206  }
207  visPresetLayerElem = visPresetLayerElem.nextSiblingElement( "layer" );
208  }
209 
210  QDomElement checkedLegendNodesElem = visPresetElem.firstChildElement( "checked-legend-nodes" );
211  while ( !checkedLegendNodesElem.isNull() )
212  {
213  QSet<QString> checkedLegendNodes;
214 
215  QDomElement checkedLegendNodeElem = checkedLegendNodesElem.firstChildElement( "checked-legend-node" );
216  while ( !checkedLegendNodeElem.isNull() )
217  {
218  checkedLegendNodes << checkedLegendNodeElem.attribute( "id" );
219  checkedLegendNodeElem = checkedLegendNodeElem.nextSiblingElement( "checked-legend-node" );
220  }
221 
222  QString layerID = checkedLegendNodesElem.attribute( "id" );
223  if ( QgsMapLayerRegistry::instance()->mapLayer( layerID ) ) // only use valid IDs
224  rec.mPerLayerCheckedLegendSymbols.insert( layerID, checkedLegendNodes );
225  checkedLegendNodesElem = checkedLegendNodesElem.nextSiblingElement( "checked-legend-nodes" );
226  }
227 
228  mPresets.insert( presetName, rec );
229 
230  visPresetElem = visPresetElem.nextSiblingElement( "visibility-preset" );
231  }
232 
234 }
235 
237 {
238  QDomElement visPresetsElem = doc.createElement( "visibility-presets" );
239  PresetRecordMap::const_iterator it = mPresets.constBegin();
240  for ( ; it != mPresets.constEnd(); ++ it )
241  {
242  QString grpName = it.key();
243  const PresetRecord& rec = it.value();
244  QDomElement visPresetElem = doc.createElement( "visibility-preset" );
245  visPresetElem.setAttribute( "name", grpName );
246  Q_FOREACH ( const QString& layerID, rec.mVisibleLayerIDs )
247  {
248  QDomElement layerElem = doc.createElement( "layer" );
249  layerElem.setAttribute( "id", layerID );
250  if ( rec.mPerLayerCurrentStyle.contains( layerID ) )
251  layerElem.setAttribute( "style", rec.mPerLayerCurrentStyle[layerID] );
252  visPresetElem.appendChild( layerElem );
253  }
254 
255  QMap<QString, QSet<QString> >::const_iterator layerIt = rec.mPerLayerCheckedLegendSymbols.constBegin();
256  for ( ; layerIt != rec.mPerLayerCheckedLegendSymbols.constEnd(); ++layerIt )
257  {
258  QString layerID = layerIt.key();
259  QDomElement checkedLegendNodesElem = doc.createElement( "checked-legend-nodes" );
260  checkedLegendNodesElem.setAttribute( "id", layerID );
261  Q_FOREACH ( const QString& checkedLegendNode, layerIt.value() )
262  {
263  QDomElement checkedLegendNodeElem = doc.createElement( "checked-legend-node" );
264  checkedLegendNodeElem.setAttribute( "id", checkedLegendNode );
265  checkedLegendNodesElem.appendChild( checkedLegendNodeElem );
266  }
267  visPresetElem.appendChild( checkedLegendNodesElem );
268  }
269 
270  visPresetsElem.appendChild( visPresetElem );
271  }
272 
273  doc.firstChildElement( "qgis" ).appendChild( visPresetsElem );
274 }
275 
277 {
278  Q_FOREACH ( const QString& layerID, layerIDs )
279  {
280  PresetRecordMap::iterator it = mPresets.begin();
281  for ( ; it != mPresets.end(); ++it )
282  {
283  PresetRecord& rec = it.value();
284  rec.mVisibleLayerIDs.removeAll( layerID );
285  rec.mPerLayerCheckedLegendSymbols.remove( layerID );
286  rec.mPerLayerCurrentStyle.remove( layerID );
287  }
288  }
289 }
290 
292 {
293  QgsMapLayerStyleManager* styleMgr = qobject_cast<QgsMapLayerStyleManager*>( sender() );
294  if ( !styleMgr )
295  return;
296 
297  QString layerID = styleMgr->layer()->id();
298 
299  PresetRecordMap::iterator it = mPresets.begin();
300  for ( ; it != mPresets.end(); ++it )
301  {
302  PresetRecord& rec = it.value();
303 
304  if ( rec.mPerLayerCurrentStyle.contains( layerID ) )
305  {
306  QString styleName = rec.mPerLayerCurrentStyle[layerID];
307  if ( styleName == oldName )
308  rec.mPerLayerCurrentStyle[layerID] = newName;
309  }
310  }
311 }
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 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 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
QgsMapLayerStyleManager * styleManager() const
Get access to the layer&#39;s style manager.
const_iterator constBegin() 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.
QString ruleKey() const
Return unique identifier of the rule for identification of the item within renderer.
void clear()
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
QStringList presets() const
Returns a list of existing preset names.
QgsMapLayer * mapLayer(const QString &theLayerId)
Retrieve a pointer to a loaded layer by id.
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.
QStringList presetVisibleLayers(const QString &name) const
Returns the list of layer IDs that should be visible for the specified preset.
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.
Qt::CheckState isVisible() const
QgsFeatureRendererV2 * rendererV2()
Return renderer V2.
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.
QString currentStyle() const
Return name of the current style.
QStringList mVisibleLayerIDs
Ordered list of layers that are visible.
This class is a base class for nodes in a layer tree.
QString id() const
Get this layer&#39;s unique ID, this ID is used to access this layer from map layer registry.
QString layerId() const
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
QgsMapLayer * layer() const
Get pointer to the associated map layer.
iterator begin()
static void addVisibleLayersToPreset(QgsLayerTreeGroup *parent, PresetRecord &rec)
Static method for adding visible layers from a layer tree group to a preset record.
QString xmlData() const
Return XML content of the style.
bool isNull() const
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
virtual QgsLegendSymbolListV2 legendSymbolItemsV2() const
Return a list of symbology items for the legend.
virtual bool legendSymbolItemsCheckable() const
items of symbology items in legend should be checkable
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)
bool setOverrideStyle(const QString &styleDef)
Temporarily apply a different style to the layer.
bool hasPreset(const QString &name) const
Returns whether a preset with a matching name exists.
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 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
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)