QGIS API Documentation  2.8.2-Wien
 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 #include "qgsmaplayer.h"
21 #include "qgsmaplayerregistry.h"
22 
23 #include <QDomElement>
24 #include <QStringList>
25 
26 
27 QgsLayerTreeGroup::QgsLayerTreeGroup( const QString& name, Qt::CheckState checked )
28  : QgsLayerTreeNode( NodeGroup )
29  , mName( name )
30  , mChecked( checked )
31  , mChangingChildVisibility( false )
32 {
33  connect( this, SIGNAL( visibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ), this, SLOT( nodeVisibilityChanged( QgsLayerTreeNode* ) ) );
34 }
35 
37  : QgsLayerTreeNode( other )
38  , mName( other.mName )
39  , mChecked( other.mChecked )
40  , mChangingChildVisibility( false )
41 {
42  connect( this, SIGNAL( visibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ), this, SLOT( nodeVisibilityChanged( QgsLayerTreeNode* ) ) );
43 }
44 
45 
47 {
48  QgsLayerTreeGroup* grp = new QgsLayerTreeGroup( name );
49  insertChildNode( index, grp );
50  return grp;
51 }
52 
54 {
55  QgsLayerTreeGroup* grp = new QgsLayerTreeGroup( name );
56  addChildNode( grp );
57  return grp;
58 }
59 
61 {
62  if ( !layer || QgsMapLayerRegistry::instance()->mapLayer( layer->id() ) != layer )
63  return 0;
64 
65  QgsLayerTreeLayer* ll = new QgsLayerTreeLayer( layer );
66  insertChildNode( index, ll );
67  return ll;
68 }
69 
71 {
72  if ( !layer || QgsMapLayerRegistry::instance()->mapLayer( layer->id() ) != layer )
73  return 0;
74 
75  QgsLayerTreeLayer* ll = new QgsLayerTreeLayer( layer );
76  addChildNode( ll );
77  return ll;
78 }
79 
81 {
82  QList<QgsLayerTreeNode*> nodes;
83  nodes << node;
84  insertChildNodes( index, nodes );
85 }
86 
87 void QgsLayerTreeGroup::insertChildNodes( int index, QList<QgsLayerTreeNode*> nodes )
88 {
89  // low-level insert
90  insertChildrenPrivate( index, nodes );
91 
93 }
94 
96 {
97  insertChildNode( -1, node );
98 }
99 
101 {
102  int i = mChildren.indexOf( node );
103  if ( i >= 0 )
104  removeChildren( i, 1 );
105 }
106 
108 {
109  foreach ( QgsLayerTreeNode* child, mChildren )
110  {
111  if ( QgsLayerTree::isLayer( child ) )
112  {
113  QgsLayerTreeLayer* childLayer = QgsLayerTree::toLayer( child );
114  if ( childLayer->layer() == layer )
115  {
116  removeChildren( mChildren.indexOf( child ), 1 );
117  break;
118  }
119  }
120  }
121 }
122 
123 void QgsLayerTreeGroup::removeChildren( int from, int count )
124 {
125  removeChildrenPrivate( from, count );
126 
128 }
129 
131 {
132  // clean the layer tree by removing empty group
133  foreach ( QgsLayerTreeNode* treeNode, children() )
134  {
135  if ( treeNode->nodeType() == QgsLayerTreeNode::NodeGroup )
136  {
137  QgsLayerTreeGroup* treeGroup = qobject_cast<QgsLayerTreeGroup*>( treeNode );
138  if ( treeGroup->findLayerIds().count() == 0 )
139  removeChildNode( treeNode );
140  else
142  }
143  }
144 }
145 
147 {
148  removeChildren( 0, mChildren.count() );
149 }
150 
151 QgsLayerTreeLayer *QgsLayerTreeGroup::findLayer( const QString& layerId ) const
152 {
153  foreach ( QgsLayerTreeNode* child, mChildren )
154  {
155  if ( QgsLayerTree::isLayer( child ) )
156  {
157  QgsLayerTreeLayer* childLayer = QgsLayerTree::toLayer( child );
158  if ( childLayer->layerId() == layerId )
159  return childLayer;
160  }
161  else if ( QgsLayerTree::isGroup( child ) )
162  {
163  QgsLayerTreeLayer* res = QgsLayerTree::toGroup( child )->findLayer( layerId );
164  if ( res )
165  return res;
166  }
167  }
168  return 0;
169 }
170 
171 QList<QgsLayerTreeLayer*> QgsLayerTreeGroup::findLayers() const
172 {
173  QList<QgsLayerTreeLayer*> list;
174  foreach ( QgsLayerTreeNode* child, mChildren )
175  {
176  if ( QgsLayerTree::isLayer( child ) )
177  list << QgsLayerTree::toLayer( child );
178  else if ( QgsLayerTree::isGroup( child ) )
179  list << QgsLayerTree::toGroup( child )->findLayers();
180  }
181  return list;
182 }
183 
185 {
186  foreach ( QgsLayerTreeNode* child, mChildren )
187  {
188  if ( QgsLayerTree::isGroup( child ) )
189  {
190  QgsLayerTreeGroup* childGroup = QgsLayerTree::toGroup( child );
191  if ( childGroup->name() == name )
192  return childGroup;
193  else
194  {
195  QgsLayerTreeGroup* grp = childGroup->findGroup( name );
196  if ( grp )
197  return grp;
198  }
199  }
200  }
201  return 0;
202 }
203 
205 {
206  if ( element.tagName() != "layer-tree-group" )
207  return 0;
208 
209  QString name = element.attribute( "name" );
210  bool isExpanded = ( element.attribute( "expanded", "1" ) == "1" );
211  Qt::CheckState checked = QgsLayerTreeUtils::checkStateFromXml( element.attribute( "checked" ) );
212 
213  QgsLayerTreeGroup* groupNode = new QgsLayerTreeGroup( name, checked );
214  groupNode->setExpanded( isExpanded );
215 
216  groupNode->readCommonXML( element );
217 
218  groupNode->readChildrenFromXML( element );
219 
220  return groupNode;
221 }
222 
223 void QgsLayerTreeGroup::writeXML( QDomElement& parentElement )
224 {
225  QDomDocument doc = parentElement.ownerDocument();
226  QDomElement elem = doc.createElement( "layer-tree-group" );
227  elem.setAttribute( "name", mName );
228  elem.setAttribute( "expanded", mExpanded ? "1" : "0" );
229  elem.setAttribute( "checked", QgsLayerTreeUtils::checkStateToXml( mChecked ) );
230 
231  writeCommonXML( elem );
232 
233  foreach ( QgsLayerTreeNode* node, mChildren )
234  node->writeXML( elem );
235 
236  parentElement.appendChild( elem );
237 }
238 
239 void QgsLayerTreeGroup::readChildrenFromXML( QDomElement& element )
240 {
241  QList<QgsLayerTreeNode*> nodes;
242  QDomElement childElem = element.firstChildElement();
243  while ( !childElem.isNull() )
244  {
245  QgsLayerTreeNode* newNode = QgsLayerTreeNode::readXML( childElem );
246  if ( newNode )
247  nodes << newNode;
248 
249  childElem = childElem.nextSiblingElement();
250  }
251 
252  insertChildNodes( -1, nodes );
253 }
254 
255 QString QgsLayerTreeGroup::dump() const
256 {
257  QString header = QString( "GROUP: %1 visible=%2 expanded=%3\n" ).arg( name() ).arg( mChecked ).arg( mExpanded );
258  QStringList childrenDump;
259  foreach ( QgsLayerTreeNode* node, mChildren )
260  childrenDump << node->dump().split( "\n" );
261  for ( int i = 0; i < childrenDump.count(); ++i )
262  childrenDump[i].prepend( " " );
263  return header + childrenDump.join( "\n" );
264 }
265 
267 {
268  return new QgsLayerTreeGroup( *this );
269 }
270 
271 void QgsLayerTreeGroup::setVisible( Qt::CheckState state )
272 {
273  if ( mChecked == state )
274  return;
275 
276  mChecked = state;
277  emit visibilityChanged( this, state );
278 
279  if ( mChecked == Qt::Unchecked || mChecked == Qt::Checked )
280  {
281  mChangingChildVisibility = true; // guard against running again setVisible() triggered from children
282 
283  // update children to have the correct visibility
284  foreach ( QgsLayerTreeNode* child, mChildren )
285  {
286  if ( QgsLayerTree::isGroup( child ) )
288  else if ( QgsLayerTree::isLayer( child ) )
290  }
291 
292  mChangingChildVisibility = false;
293  }
294 }
295 
297 {
298  QStringList lst;
299  foreach ( QgsLayerTreeNode* child, mChildren )
300  {
301  if ( QgsLayerTree::isGroup( child ) )
302  lst << QgsLayerTree::toGroup( child )->findLayerIds();
303  else if ( QgsLayerTree::isLayer( child ) )
304  lst << QgsLayerTree::toLayer( child )->layerId();
305  }
306  return lst;
307 }
308 
309 
311 {
312  //QgsMapLayer* layer = static_cast<QgsMapLayer*>( sender() );
313  //removeLayer( layer );
314 }
315 
317 {
318  if ( mChildren.indexOf( node ) != -1 )
320 }
321 
323 {
325  return;
326 
327  if ( mChildren.count() == 0 )
328  return;
329 
330  bool hasVisible = false, hasHidden = false;
331 
332  foreach ( QgsLayerTreeNode* child, mChildren )
333  {
334  if ( QgsLayerTree::isLayer( child ) )
335  {
336  bool layerVisible = QgsLayerTree::toLayer( child )->isVisible() == Qt::Checked;
337  if ( layerVisible ) hasVisible = true;
338  if ( !layerVisible ) hasHidden = true;
339  }
340  else if ( QgsLayerTree::isGroup( child ) )
341  {
342  Qt::CheckState state = QgsLayerTree::toGroup( child )->isVisible();
343  if ( state == Qt::Checked || state == Qt::PartiallyChecked ) hasVisible = true;
344  if ( state == Qt::Unchecked || state == Qt::PartiallyChecked ) hasHidden = true;
345  }
346  }
347 
348  Qt::CheckState newState;
349  if ( hasVisible && !hasHidden )
350  newState = Qt::Checked;
351  else if ( hasHidden && !hasVisible )
352  newState = Qt::Unchecked;
353  else
354  newState = Qt::PartiallyChecked;
355 
356  setVisible( newState );
357 }
358