QGIS API Documentation  2.12.0-Lyon
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  Q_FOREACH ( const QString& grpName, mPresets.keys() )
169  {
170  const PresetRecord& rec = mPresets[grpName];
171  Q_FOREACH ( const QString& layerID, rec.mPerLayerCurrentStyle.keys() )
172  layerIDs << layerID;
173  }
174 
175  Q_FOREACH ( const QString& layerID, layerIDs )
176  {
177  if ( QgsMapLayer* ml = QgsMapLayerRegistry::instance()->mapLayer( layerID ) )
178  connect( ml->styleManager(), SIGNAL( styleRenamed( QString, QString ) ), this, SLOT( layerStyleRenamed( QString, QString ) ) );
179  }
180 }
181 
183 {
184  clear();
185 
186  QDomElement visPresetsElem = doc.firstChildElement( "qgis" ).firstChildElement( "visibility-presets" );
187  if ( visPresetsElem.isNull() )
188  return;
189 
190  QDomElement visPresetElem = visPresetsElem.firstChildElement( "visibility-preset" );
191  while ( !visPresetElem.isNull() )
192  {
193  QString presetName = visPresetElem.attribute( "name" );
194  PresetRecord rec;
195  QDomElement visPresetLayerElem = visPresetElem.firstChildElement( "layer" );
196  while ( !visPresetLayerElem.isNull() )
197  {
198  QString layerID = visPresetLayerElem.attribute( "id" );
199  if ( QgsMapLayerRegistry::instance()->mapLayer( layerID ) )
200  {
201  rec.mVisibleLayerIDs << layerID; // only use valid layer IDs
202  if ( visPresetLayerElem.hasAttribute( "style" ) )
203  rec.mPerLayerCurrentStyle[layerID] = visPresetLayerElem.attribute( "style" );
204  }
205  visPresetLayerElem = visPresetLayerElem.nextSiblingElement( "layer" );
206  }
207 
208  QDomElement checkedLegendNodesElem = visPresetElem.firstChildElement( "checked-legend-nodes" );
209  while ( !checkedLegendNodesElem.isNull() )
210  {
211  QSet<QString> checkedLegendNodes;
212 
213  QDomElement checkedLegendNodeElem = checkedLegendNodesElem.firstChildElement( "checked-legend-node" );
214  while ( !checkedLegendNodeElem.isNull() )
215  {
216  checkedLegendNodes << checkedLegendNodeElem.attribute( "id" );
217  checkedLegendNodeElem = checkedLegendNodeElem.nextSiblingElement( "checked-legend-node" );
218  }
219 
220  QString layerID = checkedLegendNodesElem.attribute( "id" );
221  if ( QgsMapLayerRegistry::instance()->mapLayer( layerID ) ) // only use valid IDs
222  rec.mPerLayerCheckedLegendSymbols.insert( layerID, checkedLegendNodes );
223  checkedLegendNodesElem = checkedLegendNodesElem.nextSiblingElement( "checked-legend-nodes" );
224  }
225 
226  mPresets.insert( presetName, rec );
227 
228  visPresetElem = visPresetElem.nextSiblingElement( "visibility-preset" );
229  }
230 
232 }
233 
235 {
236  QDomElement visPresetsElem = doc.createElement( "visibility-presets" );
237  Q_FOREACH ( const QString& grpName, mPresets.keys() )
238  {
239  const PresetRecord& rec = mPresets[grpName];
240  QDomElement visPresetElem = doc.createElement( "visibility-preset" );
241  visPresetElem.setAttribute( "name", grpName );
242  Q_FOREACH ( const QString& layerID, rec.mVisibleLayerIDs )
243  {
244  QDomElement layerElem = doc.createElement( "layer" );
245  layerElem.setAttribute( "id", layerID );
246  if ( rec.mPerLayerCurrentStyle.contains( layerID ) )
247  layerElem.setAttribute( "style", rec.mPerLayerCurrentStyle[layerID] );
248  visPresetElem.appendChild( layerElem );
249  }
250 
251  Q_FOREACH ( const QString& layerID, rec.mPerLayerCheckedLegendSymbols.keys() )
252  {
253  QDomElement checkedLegendNodesElem = doc.createElement( "checked-legend-nodes" );
254  checkedLegendNodesElem.setAttribute( "id", layerID );
255  Q_FOREACH ( const QString& checkedLegendNode, rec.mPerLayerCheckedLegendSymbols[layerID] )
256  {
257  QDomElement checkedLegendNodeElem = doc.createElement( "checked-legend-node" );
258  checkedLegendNodeElem.setAttribute( "id", checkedLegendNode );
259  checkedLegendNodesElem.appendChild( checkedLegendNodeElem );
260  }
261  visPresetElem.appendChild( checkedLegendNodesElem );
262  }
263 
264  visPresetsElem.appendChild( visPresetElem );
265  }
266 
267  doc.firstChildElement( "qgis" ).appendChild( visPresetsElem );
268 }
269 
271 {
272  Q_FOREACH ( const QString& layerID, layerIDs )
273  {
274  Q_FOREACH ( const QString& presetName, mPresets.keys() )
275  {
276  PresetRecord& rec = mPresets[presetName];
277  rec.mVisibleLayerIDs.removeAll( layerID );
278  rec.mPerLayerCheckedLegendSymbols.remove( layerID );
279  rec.mPerLayerCurrentStyle.remove( layerID );
280  }
281  }
282 }
283 
285 {
286  QgsMapLayerStyleManager* styleMgr = qobject_cast<QgsMapLayerStyleManager*>( sender() );
287  if ( !styleMgr )
288  return;
289 
290  QString layerID = styleMgr->layer()->id();
291 
292  Q_FOREACH ( const QString& presetName, mPresets.keys() )
293  {
294  PresetRecord& rec = mPresets[presetName];
295 
296  if ( rec.mPerLayerCurrentStyle.contains( layerID ) )
297  {
298  QString styleName = rec.mPerLayerCurrentStyle[layerID];
299  if ( styleName == oldName )
300  rec.mPerLayerCurrentStyle[layerID] = newName;
301  }
302  }
303 }
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's style manager.
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'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)
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's unique ID, this ID is used to access this layer from map layer registry.
QString layerId() const
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.
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
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.
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)