QGIS API Documentation  2.5.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgslayertreegroup.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslayertreegroup.cpp
3  --------------------------------------
4  Date : May 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 
16 #include "qgslayertreegroup.h"
17 
18 #include "qgslayertree.h"
19 #include "qgslayertreeutils.h"
20 
21 #include <QDomElement>
22 #include <QStringList>
23 
24 
25 QgsLayerTreeGroup::QgsLayerTreeGroup( const QString& name, Qt::CheckState checked )
26  : QgsLayerTreeNode( NodeGroup )
27  , mName( name )
28  , mChecked( checked )
29  , mChangingChildVisibility( false )
30 {
31  connect( this, SIGNAL( visibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ), this, SLOT( nodeVisibilityChanged( QgsLayerTreeNode* ) ) );
32 }
33 
35  : QgsLayerTreeNode( other )
36  , mName( other.mName )
37  , mChecked( other.mChecked )
38  , mChangingChildVisibility( false )
39 {
40  connect( this, SIGNAL( visibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ), this, SLOT( nodeVisibilityChanged( QgsLayerTreeNode* ) ) );
41 }
42 
43 
45 {
46  QgsLayerTreeGroup* grp = new QgsLayerTreeGroup( name );
47  insertChildNode( index, grp );
48  return grp;
49 }
50 
52 {
53  QgsLayerTreeGroup* grp = new QgsLayerTreeGroup( name );
54  addChildNode( grp );
55  return grp;
56 }
57 
59 {
60  QgsLayerTreeLayer* ll = new QgsLayerTreeLayer( layer );
61  insertChildNode( index, ll );
62  return ll;
63 }
64 
66 {
67  QgsLayerTreeLayer* ll = new QgsLayerTreeLayer( layer );
68  addChildNode( ll );
69  return ll;
70 }
71 
73 {
74  QList<QgsLayerTreeNode*> nodes;
75  nodes << node;
76  insertChildNodes( index, nodes );
77 }
78 
79 void QgsLayerTreeGroup::insertChildNodes( int index, QList<QgsLayerTreeNode*> nodes )
80 {
81  // low-level insert
82  insertChildrenPrivate( index, nodes );
83 
85 }
86 
88 {
89  insertChildNode( -1, node );
90 }
91 
93 {
94  int i = mChildren.indexOf( node );
95  if ( i >= 0 )
96  removeChildren( i, 1 );
97 }
98 
100 {
101  foreach ( QgsLayerTreeNode* child, mChildren )
102  {
103  if ( QgsLayerTree::isLayer( child ) )
104  {
105  QgsLayerTreeLayer* childLayer = QgsLayerTree::toLayer( child );
106  if ( childLayer->layer() == layer )
107  {
108  removeChildren( mChildren.indexOf( child ), 1 );
109  break;
110  }
111  }
112  }
113 }
114 
115 void QgsLayerTreeGroup::removeChildren( int from, int count )
116 {
117  removeChildrenPrivate( from, count );
118 
120 }
121 
123 {
124  removeChildren( 0, mChildren.count() );
125 }
126 
128 {
129  foreach ( QgsLayerTreeNode* child, mChildren )
130  {
131  if ( QgsLayerTree::isLayer( child ) )
132  {
133  QgsLayerTreeLayer* childLayer = QgsLayerTree::toLayer( child );
134  if ( childLayer->layerId() == layerId )
135  return childLayer;
136  }
137  else if ( QgsLayerTree::isGroup( child ) )
138  {
139  QgsLayerTreeLayer* res = QgsLayerTree::toGroup( child )->findLayer( layerId );
140  if ( res )
141  return res;
142  }
143  }
144  return 0;
145 }
146 
147 QList<QgsLayerTreeLayer*> QgsLayerTreeGroup::findLayers() const
148 {
149  QList<QgsLayerTreeLayer*> list;
150  foreach ( QgsLayerTreeNode* child, mChildren )
151  {
152  if ( QgsLayerTree::isLayer( child ) )
153  list << QgsLayerTree::toLayer( child );
154  else if ( QgsLayerTree::isGroup( child ) )
155  list << QgsLayerTree::toGroup( child )->findLayers();
156  }
157  return list;
158 }
159 
161 {
162  foreach ( QgsLayerTreeNode* child, mChildren )
163  {
164  if ( QgsLayerTree::isGroup( child ) )
165  {
166  QgsLayerTreeGroup* childGroup = QgsLayerTree::toGroup( child );
167  if ( childGroup->name() == name )
168  return childGroup;
169  else
170  {
171  QgsLayerTreeGroup* grp = childGroup->findGroup( name );
172  if ( grp )
173  return grp;
174  }
175  }
176  }
177  return 0;
178 }
179 
181 {
182  if ( element.tagName() != "layer-tree-group" )
183  return 0;
184 
185  QString name = element.attribute( "name" );
186  bool isExpanded = ( element.attribute( "expanded", "1" ) == "1" );
187  Qt::CheckState checked = QgsLayerTreeUtils::checkStateFromXml( element.attribute( "checked" ) );
188 
189  QgsLayerTreeGroup* groupNode = new QgsLayerTreeGroup( name, checked );
190  groupNode->setExpanded( isExpanded );
191 
192  groupNode->readCommonXML( element );
193 
194  groupNode->readChildrenFromXML( element );
195 
196  return groupNode;
197 }
198 
199 void QgsLayerTreeGroup::writeXML( QDomElement& parentElement )
200 {
201  QDomDocument doc = parentElement.ownerDocument();
202  QDomElement elem = doc.createElement( "layer-tree-group" );
203  elem.setAttribute( "name", mName );
204  elem.setAttribute( "expanded", mExpanded ? "1" : "0" );
205  elem.setAttribute( "checked", QgsLayerTreeUtils::checkStateToXml( mChecked ) );
206 
207  writeCommonXML( elem );
208 
209  foreach ( QgsLayerTreeNode* node, mChildren )
210  node->writeXML( elem );
211 
212  parentElement.appendChild( elem );
213 }
214 
215 void QgsLayerTreeGroup::readChildrenFromXML( QDomElement& element )
216 {
217  QList<QgsLayerTreeNode*> nodes;
218  QDomElement childElem = element.firstChildElement();
219  while ( !childElem.isNull() )
220  {
221  QgsLayerTreeNode* newNode = QgsLayerTreeNode::readXML( childElem );
222  if ( newNode )
223  nodes << newNode;
224 
225  childElem = childElem.nextSiblingElement();
226  }
227 
228  insertChildNodes( -1, nodes );
229 }
230 
231 QString QgsLayerTreeGroup::dump() const
232 {
233  QString header = QString( "GROUP: %1 visible=%2 expanded=%3\n" ).arg( name() ).arg( mChecked ).arg( mExpanded );
234  QStringList childrenDump;
235  foreach ( QgsLayerTreeNode* node, mChildren )
236  childrenDump << node->dump().split( "\n" );
237  for ( int i = 0; i < childrenDump.count(); ++i )
238  childrenDump[i].prepend( " " );
239  return header + childrenDump.join( "\n" );
240 }
241 
243 {
244  return new QgsLayerTreeGroup( *this );
245 }
246 
247 void QgsLayerTreeGroup::setVisible( Qt::CheckState state )
248 {
249  if ( mChecked == state )
250  return;
251 
252  mChecked = state;
253  emit visibilityChanged( this, state );
254 
255  if ( mChecked == Qt::Unchecked || mChecked == Qt::Checked )
256  {
257  mChangingChildVisibility = true; // guard against running again setVisible() triggered from children
258 
259  // update children to have the correct visibility
260  foreach ( QgsLayerTreeNode* child, mChildren )
261  {
262  if ( QgsLayerTree::isGroup( child ) )
264  else if ( QgsLayerTree::isLayer( child ) )
266  }
267 
268  mChangingChildVisibility = false;
269  }
270 }
271 
273 {
274  QStringList lst;
275  foreach ( QgsLayerTreeNode* child, mChildren )
276  {
277  if ( QgsLayerTree::isGroup( child ) )
278  lst << QgsLayerTree::toGroup( child )->findLayerIds();
279  else if ( QgsLayerTree::isLayer( child ) )
280  lst << QgsLayerTree::toLayer( child )->layerId();
281  }
282  return lst;
283 }
284 
285 
287 {
288  //QgsMapLayer* layer = static_cast<QgsMapLayer*>( sender() );
289  //removeLayer( layer );
290 }
291 
293 {
294  if ( mChildren.indexOf( node ) != -1 )
296 }
297 
299 {
301  return;
302 
303  if ( mChildren.count() == 0 )
304  return;
305 
306  bool hasVisible = false, hasHidden = false;
307 
308  foreach ( QgsLayerTreeNode* child, mChildren )
309  {
310  if ( QgsLayerTree::isLayer( child ) )
311  {
312  bool layerVisible = QgsLayerTree::toLayer( child )->isVisible() == Qt::Checked;
313  if ( layerVisible ) hasVisible = true;
314  if ( !layerVisible ) hasHidden = true;
315  }
316  else if ( QgsLayerTree::isGroup( child ) )
317  {
318  Qt::CheckState state = QgsLayerTree::toGroup( child )->isVisible();
319  if ( state == Qt::Checked || state == Qt::PartiallyChecked ) hasVisible = true;
320  if ( state == Qt::Unchecked || state == Qt::PartiallyChecked ) hasHidden = true;
321  }
322  }
323 
324  Qt::CheckState newState;
325  if ( hasVisible && !hasHidden )
326  newState = Qt::Checked;
327  else if ( hasHidden && !hasVisible )
328  newState = Qt::Unchecked;
329  else
330  newState = Qt::PartiallyChecked;
331 
332  setVisible( newState );
333 }
334 
void nodeVisibilityChanged(QgsLayerTreeNode *node)
Layer tree group node serves as a container for layers and further groups.
void removeChildren(int from, int count)
Remove child nodes from index "from". The nodes will be deleted.
static unsigned index
Base class for all map layer types.
Definition: qgsmaplayer.h:48
static Qt::CheckState checkStateFromXml(QString txt)
Convert QString to Qt::CheckState.
QgsLayerTreeGroup * addGroup(const QString &name)
Append a new group node with given name. Newly created node is owned by this group.
void readChildrenFromXML(QDomElement &element)
Read children from XML and append them to the group.
static QString checkStateToXml(Qt::CheckState state)
Convert Qt::CheckState to QString.
virtual QString dump() const
Return text representation of the tree. For debugging purposes only.
static QgsLayerTreeGroup * readXML(QDomElement &element)
Read group (tree) from XML element and return the newly created group (or null on ...
QgsMapLayer * layer() const
void removeAllChildren()
Remove all child nodes. The nodes will be deleted.
bool mExpanded
whether the node should be shown in GUI as expanded
virtual QString dump() const =0
Return string with layer tree structure. For debug purposes only.
QgsLayerTreeLayer * findLayer(const QString &layerId)
Find layer node representing the map layer specified by its ID. Searches recursively the whole sub-tr...
void removeChildNode(QgsLayerTreeNode *node)
Remove a child node from this group. The node will be deleted.
void insertChildNodes(int index, QList< QgsLayerTreeNode * > nodes)
Insert existing nodes at specified position. The nodes must not have a parent yet. The nodes will be owned by this group.
virtual void writeXML(QDomElement &parentElement)=0
Write layer tree to XML.
void removeLayer(QgsMapLayer *layer)
Remove map layer's node from this group. The node will be deleted.
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
QgsLayerTreeLayer * addLayer(QgsMapLayer *layer)
Append a new layer node for given map layer. Newly created node is owned by this group.
void removeChildrenPrivate(int from, int count)
Low-level removal of children from the node.
Qt::CheckState isVisible() const
void visibilityChanged(QgsLayerTreeNode *node, Qt::CheckState state)
Emitted when check state of a node within the tree has been changed.
QgsLayerTreeLayer * insertLayer(int index, QgsMapLayer *layer)
Insert a new layer node for given map layer at specified position. Newly created node is owned by thi...
void insertChildrenPrivate(int index, QList< QgsLayerTreeNode * > nodes)
Low-level insertion of children to the node. The children must not have any parent yet! ...
QList< QgsLayerTreeLayer * > findLayers() const
Find all layer nodes. Searches recursively the whole sub-tree.
This class is a base class for nodes in a layer tree.
QString layerId() const
void setVisible(Qt::CheckState visible)
static QgsLayerTreeNode * readXML(QDomElement &element)
Read layer tree from XML. Returns new instance.
bool isExpanded() const
Return whether the node should be shown as expanded or collapsed in GUI.
QString name() const
Get group's name.
QList< QgsLayerTreeNode * > mChildren
list of children - node is responsible for their deletion
bool isLayer(QgsLayerTreeNode *node)
Check whether the node is a valid layer node.
Definition: qgslayertree.h:40
Qt::CheckState isVisible() const
Return the check state of the group node.
Qt::CheckState mChecked
virtual void writeXML(QDomElement &parentElement)
Write group (tree) as XML element and add it to the given parent element...
virtual QgsLayerTreeNode * clone() const
Return a clone of the group. The children are cloned too.
void writeCommonXML(QDomElement &element)
void insertChildNode(int index, QgsLayerTreeNode *node)
Insert existing node at specified position. The node must not have a parent yet. The node will be own...
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
QStringList findLayerIds() const
Find layer IDs used in all layer nodes. Searches recursively the whole sub-tree.
QgsLayerTreeGroup * findGroup(const QString &name)
Find group node with specified name. Searches recursively the whole sub-tree.
void addChildNode(QgsLayerTreeNode *node)
Append an existing node. The node must not have a parent yet. The node will be owned by this group...
void setVisible(Qt::CheckState state)
Set check state of the group node - will also update children.
bool isGroup(QgsLayerTreeNode *node)
Check whether the node is a valid group node.
Definition: qgslayertree.h:34
QgsLayerTreeGroup * insertGroup(int index, const QString &name)
Insert a new group node with given name at specified position. Newly created node is owned by this gr...
Layer tree node points to a map layer.
QgsLayerTreeGroup(const QString &name=QString(), Qt::CheckState checked=Qt::Checked)