QGIS API Documentation  2.9.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
qgslayertreemodel.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslayertreemodel.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 "qgslayertreemodel.h"
17 
18 #include "qgslayertree.h"
20 
21 #include <QMimeData>
22 #include <QTextStream>
23 
24 #include "qgsdataitem.h"
25 #include "qgsmaphittest.h"
26 #include "qgsmaplayerlegend.h"
27 #include "qgspluginlayer.h"
28 #include "qgsrasterlayer.h"
29 #include "qgsrendererv2.h"
30 #include "qgssymbollayerv2utils.h"
31 #include "qgsvectorlayer.h"
32 
33 
35  : QAbstractItemModel( parent )
36  , mRootNode( rootNode )
37  , mFlags( ShowLegend | AllowLegendChangeState )
38  , mAutoCollapseLegendNodesCount( -1 )
39  , mLegendFilterByScale( 0 )
40  , mLegendMapViewMupp( 0 )
41  , mLegendMapViewDpi( 0 )
42  , mLegendMapViewScale( 0 )
43 {
45 
46  mFontLayer.setBold( true );
47 }
48 
50 {
51  legendCleanup();
52 }
53 
55 {
56  if ( !index.isValid() )
57  return mRootNode;
58 
59  QObject* obj = reinterpret_cast<QObject*>( index.internalPointer() );
60  return qobject_cast<QgsLayerTreeNode*>( obj );
61 }
62 
63 
64 int QgsLayerTreeModel::rowCount( const QModelIndex &parent ) const
65 {
66  if ( QgsLayerTreeModelLegendNode* nodeLegend = index2legendNode( parent ) )
67  return legendNodeRowCount( nodeLegend );
68 
69  QgsLayerTreeNode* n = index2node( parent );
70  if ( !n )
71  return 0;
72 
73  if ( QgsLayerTree::isLayer( n ) )
74  {
75  if ( !testFlag( ShowLegend ) )
76  return 0;
77 
79  }
80 
81  return n->children().count();
82 }
83 
84 int QgsLayerTreeModel::columnCount( const QModelIndex &parent ) const
85 {
86  Q_UNUSED( parent );
87  return 1;
88 }
89 
90 QModelIndex QgsLayerTreeModel::index( int row, int column, const QModelIndex &parent ) const
91 {
92  if ( column < 0 || column >= columnCount( parent ) ||
93  row < 0 || row >= rowCount( parent ) )
94  return QModelIndex();
95 
96  if ( QgsLayerTreeModelLegendNode* nodeLegend = index2legendNode( parent ) )
97  return legendNodeIndex( row, column, nodeLegend );
98 
99  QgsLayerTreeNode *n = index2node( parent );
100  if ( !n )
101  return QModelIndex(); // have no children
102 
103  if ( testFlag( ShowLegend ) && QgsLayerTree::isLayer( n ) )
104  {
105  return legendRootIndex( row, column, QgsLayerTree::toLayer( n ) );
106  }
107 
108  return createIndex( row, column, static_cast<QObject*>( n->children().at( row ) ) );
109 }
110 
111 
112 QModelIndex QgsLayerTreeModel::parent( const QModelIndex &child ) const
113 {
114  if ( !child.isValid() )
115  return QModelIndex();
116 
117  if ( QgsLayerTreeNode *n = index2node( child ) )
118  {
119  return indexOfParentLayerTreeNode( n->parent() ); // must not be null
120  }
121  else if ( QgsLayerTreeModelLegendNode* legendNode = index2legendNode( child ) )
122  {
123  return legendParent( legendNode );
124  }
125  else
126  {
127  Q_ASSERT( false ); // no other node types!
128  return QModelIndex();
129  }
130 
131 }
132 
133 
135 {
136  Q_ASSERT( parentNode );
137 
138  QgsLayerTreeNode* grandParentNode = parentNode->parent();
139  if ( !grandParentNode )
140  return QModelIndex(); // root node -> invalid index
141 
142  int row = grandParentNode->children().indexOf( parentNode );
143  Q_ASSERT( row >= 0 );
144 
145  return createIndex( row, 0, static_cast<QObject*>( parentNode ) );
146 }
147 
148 
149 QVariant QgsLayerTreeModel::data( const QModelIndex &index, int role ) const
150 {
151  if ( !index.isValid() || index.column() > 1 )
152  return QVariant();
153 
154  if ( QgsLayerTreeModelLegendNode* sym = index2legendNode( index ) )
155  return legendNodeData( sym, role );
156 
157  QgsLayerTreeNode* node = index2node( index );
158  if ( role == Qt::DisplayRole || role == Qt::EditRole )
159  {
160  if ( QgsLayerTree::isGroup( node ) )
161  return QgsLayerTree::toGroup( node )->name();
162 
163  if ( QgsLayerTree::isLayer( node ) )
164  {
165  QgsLayerTreeLayer* nodeLayer = QgsLayerTree::toLayer( node );
166  QString name = nodeLayer->layerName();
167  if ( nodeLayer->customProperty( "showFeatureCount", 0 ).toInt() && role == Qt::DisplayRole )
168  {
169  QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer*>( nodeLayer->layer() );
170  if ( vlayer && vlayer->pendingFeatureCount() >= 0 )
171  name += QString( " [%1]" ).arg( vlayer->pendingFeatureCount() );
172  }
173  return name;
174  }
175  }
176  else if ( role == Qt::DecorationRole && index.column() == 0 )
177  {
178  if ( QgsLayerTree::isGroup( node ) )
179  return iconGroup();
180 
181  if ( QgsLayerTree::isLayer( node ) )
182  {
183  QgsLayerTreeLayer *nodeLayer = QgsLayerTree::toLayer( node );
184 
185  QgsMapLayer *layer = nodeLayer->layer();
186  if ( !layer )
187  return QVariant();
188 
189  // icons possibly overriding default icon
190  if ( layer->type() == QgsMapLayer::RasterLayer )
191  {
193  {
194  QgsRasterLayer* rlayer = qobject_cast<QgsRasterLayer *>( layer );
195  return QIcon( rlayer->previewAsPixmap( QSize( 32, 32 ) ) );
196  }
197  else
198  {
199  return QgsLayerItem::iconRaster();
200  }
201  }
202 
203  QgsVectorLayer *vlayer = dynamic_cast<QgsVectorLayer*>( layer );
204  QIcon icon;
205 
206  // if there's just on legend entry that should be embedded in layer - do that!
207  if ( testFlag( ShowLegend ) && legendEmbeddedInParent( nodeLayer ) )
208  {
209  icon = legendIconEmbeddedInParent( nodeLayer );
210  }
211  else if ( vlayer && layer->type() == QgsMapLayer::VectorLayer )
212  {
213  if ( vlayer->geometryType() == QGis::Point )
214  icon = QgsLayerItem::iconPoint();
215  else if ( vlayer->geometryType() == QGis::Line )
216  icon = QgsLayerItem::iconLine();
217  else if ( vlayer->geometryType() == QGis::Polygon )
218  icon = QgsLayerItem::iconPolygon();
219  else if ( vlayer->geometryType() == QGis::NoGeometry )
220  icon = QgsLayerItem::iconTable();
221  else
222  icon = QgsLayerItem::iconDefault();
223  }
224 
225  if ( vlayer && vlayer->isEditable() )
226  {
227  QPixmap pixmap( icon.pixmap( 16, 16 ) );
228 
229  QPainter painter( &pixmap );
230  painter.drawPixmap( 0, 0, 16, 16, QgsApplication::getThemePixmap( vlayer->isModified() ? "/mIconEditableEdits.png" : "/mIconEditable.png" ) );
231  painter.end();
232 
233  icon = QIcon( pixmap );
234  }
235 
236  return icon;
237  }
238  }
239  else if ( role == Qt::CheckStateRole )
240  {
242  return QVariant();
243 
244  if ( QgsLayerTree::isLayer( node ) )
245  {
246  QgsLayerTreeLayer* nodeLayer = QgsLayerTree::toLayer( node );
247  if ( nodeLayer->layer() && nodeLayer->layer()->type() == QgsMapLayer::VectorLayer )
248  {
249  if ( qobject_cast<QgsVectorLayer*>( nodeLayer->layer() )->geometryType() == QGis::NoGeometry )
250  return QVariant(); // do not show checkbox for non-spatial tables
251  }
252  return nodeLayer->isVisible();
253  }
254  else if ( QgsLayerTree::isGroup( node ) )
255  {
256  QgsLayerTreeGroup* nodeGroup = QgsLayerTree::toGroup( node );
257  return nodeGroup->isVisible();
258  }
259  }
260  else if ( role == Qt::FontRole )
261  {
262  QFont f( QgsLayerTree::isLayer( node ) ? mFontLayer : ( QgsLayerTree::isGroup( node ) ? mFontGroup : QFont() ) );
263  if ( node->customProperty( "embedded" ).toInt() )
264  f.setItalic( true );
265  if ( index == mCurrentIndex )
266  f.setUnderline( true );
267  return f;
268  }
269  else if ( role == Qt::ToolTipRole )
270  {
271  if ( QgsLayerTree::isLayer( node ) )
272  {
273  if ( QgsMapLayer* layer = QgsLayerTree::toLayer( node )->layer() )
274  return layer->publicSource();
275  }
276  }
277 
278  return QVariant();
279 }
280 
281 
282 Qt::ItemFlags QgsLayerTreeModel::flags( const QModelIndex& index ) const
283 {
284  if ( !index.isValid() )
285  {
286  Qt::ItemFlags rootFlags = 0;
287  if ( testFlag( AllowNodeReorder ) )
288  rootFlags |= Qt::ItemIsDropEnabled;
289  return rootFlags;
290  }
291 
292  if ( QgsLayerTreeModelLegendNode* symn = index2legendNode( index ) )
293  return legendNodeFlags( symn );
294 
295  Qt::ItemFlags f = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
296 
297  if ( testFlag( AllowNodeRename ) )
298  f |= Qt::ItemIsEditable;
299 
300  QgsLayerTreeNode* node = index2node( index );
301  bool isEmbedded = node->customProperty( "embedded" ).toInt();
302 
303  if ( testFlag( AllowNodeReorder ) )
304  {
305  // only root embedded nodes can be reordered
306  if ( !isEmbedded || ( isEmbedded && node->parent() && !node->parent()->customProperty( "embedded" ).toInt() ) )
307  f |= Qt::ItemIsDragEnabled;
308  }
309 
311  f |= Qt::ItemIsUserCheckable;
312 
313  if ( testFlag( AllowNodeReorder ) && QgsLayerTree::isGroup( node ) && !isEmbedded )
314  f |= Qt::ItemIsDropEnabled;
315 
316  return f;
317 }
318 
319 bool QgsLayerTreeModel::setData( const QModelIndex& index, const QVariant& value, int role )
320 {
322  if ( sym )
323  {
324  if ( role == Qt::CheckStateRole && !testFlag( AllowLegendChangeState ) )
325  return false;
326  bool res = sym->setData( value, role );
327  if ( res )
328  emit dataChanged( index, index );
329  return res;
330  }
331 
332  QgsLayerTreeNode* node = index2node( index );
333  if ( !node )
334  return QgsLayerTreeModel::setData( index, value, role );
335 
336  if ( role == Qt::CheckStateRole )
337  {
339  return false;
340 
341  if ( QgsLayerTree::isLayer( node ) )
342  {
343  QgsLayerTreeLayer* layer = QgsLayerTree::toLayer( node );
344  layer->setVisible(( Qt::CheckState )value.toInt() );
345  return true;
346  }
347 
348  if ( QgsLayerTree::isGroup( node ) )
349  {
350  QgsLayerTreeGroup* group = QgsLayerTree::toGroup( node );
351  group->setVisible(( Qt::CheckState )value.toInt() );
352  return true;
353  }
354 
355  return true;
356  }
357  else if ( role == Qt::EditRole )
358  {
359  if ( !testFlag( AllowNodeRename ) )
360  return false;
361 
362  if ( QgsLayerTree::isLayer( node ) )
363  {
364  QgsLayerTreeLayer* layer = QgsLayerTree::toLayer( node );
365  layer->setLayerName( value.toString() );
366  emit dataChanged( index, index );
367  }
368  else if ( QgsLayerTree::isGroup( node ) )
369  {
370  QgsLayerTree::toGroup( node )->setName( value.toString() );
371  emit dataChanged( index, index );
372  }
373  }
374 
375  return QAbstractItemModel::setData( index, value, role );
376 }
377 
379 {
380  if ( !node->parent() )
381  return QModelIndex(); // this is the only root item -> invalid index
382 
383  QModelIndex parentIndex = node2index( node->parent() );
384 
385  int row = node->parent()->children().indexOf( node );
386  Q_ASSERT( row >= 0 );
387  return index( row, 0, parentIndex );
388 }
389 
390 
392 {
393  if ( !child->parent() )
394  return false;
395 
396  if ( child->parent() == node )
397  return true;
398 
399  return _isChildOfNode( child->parent(), node );
400 }
401 
402 static bool _isChildOfNodes( QgsLayerTreeNode* child, QList<QgsLayerTreeNode*> nodes )
403 {
404  foreach ( QgsLayerTreeNode* n, nodes )
405  {
406  if ( _isChildOfNode( child, n ) )
407  return true;
408  }
409 
410  return false;
411 }
412 
413 
414 QList<QgsLayerTreeNode*> QgsLayerTreeModel::indexes2nodes( const QModelIndexList& list, bool skipInternal ) const
415 {
416  QList<QgsLayerTreeNode*> nodes;
417  foreach ( QModelIndex index, list )
418  {
419  QgsLayerTreeNode* node = index2node( index );
420  if ( !node )
421  continue;
422 
423  nodes << node;
424  }
425 
426  if ( !skipInternal )
427  return nodes;
428 
429  // remove any children of nodes if both parent node and children are selected
430  QList<QgsLayerTreeNode*> nodesFinal;
431  foreach ( QgsLayerTreeNode* node, nodes )
432  {
433  if ( !_isChildOfNodes( node, nodes ) )
434  nodesFinal << node;
435  }
436 
437  return nodesFinal;
438 }
439 
440 bool QgsLayerTreeModel::isIndexSymbologyNode( const QModelIndex& index ) const
441 {
442  return index2legendNode( index ) != 0;
443 }
444 
446 {
447  QgsLayerTreeModelLegendNode* symNode = index2legendNode( index );
448  return symNode ? symNode->layerNode() : 0;
449 }
450 
452 {
453  return mRootNode;
454 }
455 
457 {
458  beginResetModel();
459 
461 
462  Q_ASSERT( mLegend.isEmpty() );
463 
464  mRootNode = newRootGroup;
465 
466  endResetModel();
467 
469 }
470 
472 {
473  // update title
474  QModelIndex idx = node2index( nodeLayer );
475  emit dataChanged( idx, idx );
476 
477  // update children
478  int oldNodeCount = rowCount( idx );
479  beginRemoveRows( idx, 0, oldNodeCount - 1 );
480  removeLegendFromLayer( nodeLayer );
481  endRemoveRows();
482 
483  addLegendToLayer( nodeLayer );
484  int newNodeCount = rowCount( idx );
485 
486  // automatic collapse of legend nodes - useful if a layer has many legend nodes
487  if ( mAutoCollapseLegendNodesCount != -1 && oldNodeCount != newNodeCount && newNodeCount >= mAutoCollapseLegendNodesCount )
488  nodeLayer->setExpanded( false );
489 }
490 
492 {
493  return mCurrentIndex;
494 }
495 
496 void QgsLayerTreeModel::setCurrentIndex( const QModelIndex& currentIndex )
497 {
498  QModelIndex oldIndex = mCurrentIndex;
500 
501  if ( oldIndex.isValid() )
502  emit dataChanged( oldIndex, oldIndex );
503  if ( currentIndex.isValid() )
504  emit dataChanged( currentIndex, currentIndex );
505 }
506 
507 
508 void QgsLayerTreeModel::setLayerTreeNodeFont( int nodeType, const QFont& font )
509 {
510  if ( nodeType == QgsLayerTreeNode::NodeGroup )
511  {
512  if ( mFontGroup != font )
513  {
514  mFontGroup = font;
516  }
517  }
518  else if ( nodeType == QgsLayerTreeNode::NodeLayer )
519  {
520  if ( mFontLayer != font )
521  {
522  mFontLayer = font;
524  }
525  }
526  else
527  {
528  QgsDebugMsg( "invalid node type" );
529  }
530 }
531 
532 
533 QFont QgsLayerTreeModel::layerTreeNodeFont( int nodeType ) const
534 {
535  if ( nodeType == QgsLayerTreeNode::NodeGroup )
536  return mFontGroup;
537  else if ( nodeType == QgsLayerTreeNode::NodeLayer )
538  return mFontLayer;
539  else
540  {
541  QgsDebugMsg( "invalid node type" );
542  return QFont();
543  }
544 }
545 
546 void QgsLayerTreeModel::setLegendFilterByScale( double scaleDenominator )
547 {
548  mLegendFilterByScale = scaleDenominator;
549 
550  // this could be later done in more efficient way
551  // by just updating active legend nodes, without refreshing original legend nodes
552  foreach ( QgsLayerTreeLayer* nodeLayer, mRootNode->findLayers() )
553  refreshLayerLegend( nodeLayer );
554 }
555 
557 {
558  if ( settings && settings->hasValidSettings() )
559  {
560  mLegendFilterByMapSettings.reset( new QgsMapSettings( *settings ) );
563  }
564  else
565  {
567  return; // no change
568 
571  }
572 
573  // temporarily disable autocollapse so that legend nodes stay visible
574  int bkAutoCollapse = autoCollapseLegendNodes();
576 
577  // this could be later done in more efficient way
578  // by just updating active legend nodes, without refreshing original legend nodes
579  foreach ( QgsLayerTreeLayer* nodeLayer, mRootNode->findLayers() )
580  refreshLayerLegend( nodeLayer );
581 
582  setAutoCollapseLegendNodes( bkAutoCollapse );
583 }
584 
585 void QgsLayerTreeModel::setLegendMapViewData( double mapUnitsPerPixel, int dpi, double scale )
586 {
587  if ( mLegendMapViewDpi == dpi && mLegendMapViewMupp == mapUnitsPerPixel && mLegendMapViewScale == scale )
588  return;
589 
590  mLegendMapViewMupp = mapUnitsPerPixel;
591  mLegendMapViewDpi = dpi;
592  mLegendMapViewScale = scale;
593 
594  // now invalidate legend nodes!
596 }
597 
598 void QgsLayerTreeModel::legendMapViewData( double* mapUnitsPerPixel, int* dpi, double* scale )
599 {
600  if ( mapUnitsPerPixel ) *mapUnitsPerPixel = mLegendMapViewMupp;
601  if ( dpi ) *dpi = mLegendMapViewDpi;
602  if ( scale ) *scale = mLegendMapViewScale;
603 }
604 
605 void QgsLayerTreeModel::nodeWillAddChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo )
606 {
607  Q_ASSERT( node );
608  beginInsertRows( node2index( node ), indexFrom, indexTo );
609 }
610 
611 static QList<QgsLayerTreeLayer*> _layerNodesInSubtree( QgsLayerTreeNode* node, int indexFrom, int indexTo )
612 {
613  QList<QgsLayerTreeNode*> children = node->children();
614  QList<QgsLayerTreeLayer*> newLayerNodes;
615  for ( int i = indexFrom; i <= indexTo; ++i )
616  {
617  QgsLayerTreeNode* child = children.at( i );
618  if ( QgsLayerTree::isLayer( child ) )
619  newLayerNodes << QgsLayerTree::toLayer( child );
620  else if ( QgsLayerTree::isGroup( child ) )
621  newLayerNodes << QgsLayerTree::toGroup( child )->findLayers();
622  }
623  return newLayerNodes;
624 }
625 
626 void QgsLayerTreeModel::nodeAddedChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo )
627 {
628  Q_ASSERT( node );
629 
630  endInsertRows();
631 
632  foreach ( QgsLayerTreeLayer* newLayerNode, _layerNodesInSubtree( node, indexFrom, indexTo ) )
633  connectToLayer( newLayerNode );
634 }
635 
636 void QgsLayerTreeModel::nodeWillRemoveChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo )
637 {
638  Q_ASSERT( node );
639 
640  beginRemoveRows( node2index( node ), indexFrom, indexTo );
641 
642  // disconnect from layers and remove their legend
643  foreach ( QgsLayerTreeLayer* nodeLayer, _layerNodesInSubtree( node, indexFrom, indexTo ) )
644  disconnectFromLayer( nodeLayer );
645 }
646 
648 {
649  endRemoveRows();
650 }
651 
653 {
654  Q_ASSERT( node );
655 
656  QModelIndex index = node2index( node );
657  emit dataChanged( index, index );
658 }
659 
660 
662 {
663  if ( QgsLayerTree::isLayer( node ) && key == "showFeatureCount" )
665 }
666 
667 
669 {
670  QgsLayerTreeLayer* nodeLayer = qobject_cast<QgsLayerTreeLayer*>( sender() );
671  if ( !nodeLayer )
672  return;
673 
674  // deffered connection to the layer
675  connectToLayer( nodeLayer );
676 }
677 
679 {
680  QgsLayerTreeLayer* nodeLayer = qobject_cast<QgsLayerTreeLayer*>( sender() );
681  if ( !nodeLayer )
682  return;
683 
684  disconnectFromLayer( nodeLayer );
685 
686  // wait for the layer to appear again
687  connect( nodeLayer, SIGNAL( layerLoaded() ), this, SLOT( nodeLayerLoaded() ) );
688 }
689 
691 {
692  if ( !testFlag( ShowLegend ) )
693  return;
694 
695  QgsMapLayer* layer = qobject_cast<QgsMapLayer*>( sender() );
696  if ( !layer )
697  return;
698 
699  QgsLayerTreeLayer* nodeLayer = mRootNode->findLayer( layer->id() );
700  if ( !nodeLayer )
701  return;
702 
703  refreshLayerLegend( nodeLayer );
704 }
705 
707 {
708  QgsMapLayer* layer = qobject_cast<QgsMapLayer*>( sender() );
709  if ( !layer )
710  return;
711 
712  QgsLayerTreeLayer* nodeLayer = mRootNode->findLayer( layer->id() );
713  if ( !nodeLayer )
714  return;
715 
716  QModelIndex index = node2index( nodeLayer );
717  emit dataChanged( index, index );
718 
719  if ( nodeLayer->customProperty( "showFeatureCount" ).toInt() )
720  refreshLayerLegend( nodeLayer );
721 }
722 
723 
725 {
726  QgsLayerTreeModelLegendNode* legendNode = qobject_cast<QgsLayerTreeModelLegendNode*>( sender() );
727  if ( !legendNode )
728  return;
729 
730  QModelIndex index = legendNode2index( legendNode );
731  if ( index.isValid() )
732  emit dataChanged( index, index );
733 }
734 
735 
737 {
738  if ( !nodeLayer->layer() )
739  {
740  // in order to connect to layer, we need to have it loaded.
741  // keep an eye on the layer ID: once loaded, we will use it
742  connect( nodeLayer, SIGNAL( layerLoaded() ), this, SLOT( nodeLayerLoaded() ) );
743  return;
744  }
745 
746  // watch if the layer is getting removed
747  connect( nodeLayer, SIGNAL( layerWillBeUnloaded() ), this, SLOT( nodeLayerWillBeUnloaded() ) );
748 
749  if ( testFlag( ShowLegend ) )
750  {
751  addLegendToLayer( nodeLayer );
752 
753  // automatic collapse of legend nodes - useful if a layer has many legend nodes
754  if ( !mRootNode->customProperty( "loading" ).toBool() )
755  {
757  nodeLayer->setExpanded( false );
758  }
759  }
760 
761  QgsMapLayer* layer = nodeLayer->layer();
762  connect( layer, SIGNAL( legendChanged() ), this, SLOT( layerLegendChanged() ), Qt::UniqueConnection );
763 
764  if ( layer->type() == QgsMapLayer::VectorLayer )
765  {
766  // using unique connection because there may be temporarily more nodes for a layer than just one
767  // which would create multiple connections, however disconnect() would disconnect all multiple connections
768  // even if we wanted to disconnect just one connection in each call.
769  connect( layer, SIGNAL( editingStarted() ), this, SLOT( layerNeedsUpdate() ), Qt::UniqueConnection );
770  connect( layer, SIGNAL( editingStopped() ), this, SLOT( layerNeedsUpdate() ), Qt::UniqueConnection );
771  connect( layer, SIGNAL( layerModified() ), this, SLOT( layerNeedsUpdate() ), Qt::UniqueConnection );
772  connect( layer, SIGNAL( layerNameChanged() ), this, SLOT( layerNeedsUpdate() ), Qt::UniqueConnection );
773  }
774 }
775 
776 // try to find out if the layer ID is present in the tree multiple times
777 static int _numLayerCount( QgsLayerTreeGroup* group, const QString& layerId )
778 {
779  int count = 0;
780  foreach ( QgsLayerTreeNode* child, group->children() )
781  {
782  if ( QgsLayerTree::isLayer( child ) )
783  {
784  if ( QgsLayerTree::toLayer( child )->layerId() == layerId )
785  count++;
786  }
787  else if ( QgsLayerTree::isGroup( child ) )
788  {
789  count += _numLayerCount( QgsLayerTree::toGroup( child ), layerId );
790  }
791  }
792  return count;
793 }
794 
796 {
797  disconnect( nodeLayer, 0, this, 0 ); // disconnect from delayed load of layer
798 
799  if ( !nodeLayer->layer() )
800  return; // we were never connected
801 
802  if ( testFlag( ShowLegend ) )
803  {
804  removeLegendFromLayer( nodeLayer );
805  }
806 
807  if ( _numLayerCount( mRootNode, nodeLayer->layerId() ) == 1 )
808  {
809  // last instance of the layer in the tree: disconnect from all signals from layer!
810  disconnect( nodeLayer->layer(), 0, this, 0 );
811  }
812 }
813 
815 {
816  foreach ( QgsLayerTreeNode* node, parentGroup->children() )
817  {
818  if ( QgsLayerTree::isGroup( node ) )
820  else if ( QgsLayerTree::isLayer( node ) )
822  }
823 }
824 
826 {
827  foreach ( QgsLayerTreeNode* node, parentGroup->children() )
828  {
829  if ( QgsLayerTree::isGroup( node ) )
831  else if ( QgsLayerTree::isLayer( node ) )
833  }
834 }
835 
837 {
838  Q_ASSERT( mRootNode );
839 
840  connect( mRootNode, SIGNAL( willAddChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeWillAddChildren( QgsLayerTreeNode*, int, int ) ) );
841  connect( mRootNode, SIGNAL( addedChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeAddedChildren( QgsLayerTreeNode*, int, int ) ) );
842  connect( mRootNode, SIGNAL( willRemoveChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeWillRemoveChildren( QgsLayerTreeNode*, int, int ) ) );
843  connect( mRootNode, SIGNAL( removedChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeRemovedChildren() ) );
844  connect( mRootNode, SIGNAL( visibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ), this, SLOT( nodeVisibilityChanged( QgsLayerTreeNode* ) ) );
845 
846  connect( mRootNode, SIGNAL( customPropertyChanged( QgsLayerTreeNode*, QString ) ), this, SLOT( nodeCustomPropertyChanged( QgsLayerTreeNode*, QString ) ) );
847 
849 }
850 
852 {
853  disconnect( mRootNode, 0, this, 0 );
854 
856 }
857 
858 void QgsLayerTreeModel::recursivelyEmitDataChanged( const QModelIndex& idx )
859 {
860  QgsLayerTreeNode* node = index2node( idx );
861  if ( !node )
862  return;
863 
864  int count = node->children().count();
865  if ( count == 0 )
866  return;
867  emit dataChanged( index( 0, 0, idx ), index( count - 1, 0, idx ) );
868  for ( int i = 0; i < count; ++i )
869  recursivelyEmitDataChanged( index( i, 0, idx ) );
870 }
871 
872 
874 {
875  return Qt::MoveAction;
876 }
877 
878 QStringList QgsLayerTreeModel::mimeTypes() const
879 {
880  QStringList types;
881  types << "application/qgis.layertreemodeldata";
882  return types;
883 }
884 
885 
886 QMimeData* QgsLayerTreeModel::mimeData( const QModelIndexList& indexes ) const
887 {
888  QList<QgsLayerTreeNode*> nodesFinal = indexes2nodes( indexes, true );
889 
890  if ( nodesFinal.count() == 0 )
891  return 0;
892 
893  QMimeData *mimeData = new QMimeData();
894 
895  QDomDocument doc;
896  QDomElement rootElem = doc.createElement( "layer_tree_model_data" );
897  foreach ( QgsLayerTreeNode* node, nodesFinal )
898  node->writeXML( rootElem );
899  doc.appendChild( rootElem );
900  QString txt = doc.toString();
901 
902  mimeData->setData( "application/qgis.layertreemodeldata", txt.toUtf8() );
903  return mimeData;
904 }
905 
906 bool QgsLayerTreeModel::dropMimeData( const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent )
907 {
908  if ( action == Qt::IgnoreAction )
909  return true;
910 
911  if ( !data->hasFormat( "application/qgis.layertreemodeldata" ) )
912  return false;
913 
914  if ( column >= columnCount( parent ) )
915  return false;
916 
917  QgsLayerTreeNode* nodeParent = index2node( parent );
918  if ( !QgsLayerTree::isGroup( nodeParent ) )
919  return false;
920 
921  QByteArray encodedData = data->data( "application/qgis.layertreemodeldata" );
922 
923  QDomDocument doc;
924  if ( !doc.setContent( QString::fromUtf8( encodedData ) ) )
925  return false;
926 
927  QDomElement rootElem = doc.documentElement();
928  if ( rootElem.tagName() != "layer_tree_model_data" )
929  return false;
930 
931  QList<QgsLayerTreeNode*> nodes;
932 
933  QDomElement elem = rootElem.firstChildElement();
934  while ( !elem.isNull() )
935  {
937  if ( node )
938  nodes << node;
939 
940  elem = elem.nextSiblingElement();
941  }
942 
943  if ( nodes.count() == 0 )
944  return false;
945 
946  if ( parent.isValid() && row == -1 )
947  row = 0; // if dropped directly onto group item, insert at first position
948 
949  QgsLayerTree::toGroup( nodeParent )->insertChildNodes( row, nodes );
950 
951  return true;
952 }
953 
954 bool QgsLayerTreeModel::removeRows( int row, int count, const QModelIndex& parent )
955 {
956  QgsLayerTreeNode* parentNode = index2node( parent );
957  if ( QgsLayerTree::isGroup( parentNode ) )
958  {
959  QgsLayerTree::toGroup( parentNode )->removeChildren( row, count );
960  return true;
961  }
962  return false;
963 }
964 
965 void QgsLayerTreeModel::setFlags( QgsLayerTreeModel::Flags f )
966 {
967  mFlags = f;
968 }
969 
971 {
972  if ( on )
973  mFlags |= f;
974  else
975  mFlags &= ~f;
976 }
977 
978 QgsLayerTreeModel::Flags QgsLayerTreeModel::flags() const
979 {
980  return mFlags;
981 }
982 
984 {
985  return mFlags.testFlag( f );
986 }
987 
989 {
990  static QIcon icon;
991 
992  if ( icon.isNull() )
993  icon = QgsApplication::getThemeIcon( "/mActionFolder.png" );
994 
995  return icon;
996 }
997 
998 QList<QgsLayerTreeModelLegendNode*> QgsLayerTreeModel::filterLegendNodes( const QList<QgsLayerTreeModelLegendNode*>& nodes )
999 {
1000  QList<QgsLayerTreeModelLegendNode*> filtered;
1001 
1002  if ( mLegendFilterByScale > 0 )
1003  {
1004  foreach ( QgsLayerTreeModelLegendNode* node, nodes )
1005  {
1006  if ( node->isScaleOK( mLegendFilterByScale ) )
1007  filtered << node;
1008  }
1009  }
1010  else if ( mLegendFilterByMapSettings )
1011  {
1012  foreach ( QgsLayerTreeModelLegendNode* node, nodes )
1013  {
1014  QgsSymbolV2* ruleKey = ( QgsSymbolV2* ) node->data( QgsSymbolV2LegendNode::SymbolV2LegacyRuleKeyRole ).value<void*>();
1015  if ( ruleKey )
1016  {
1017  if ( QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( node->layerNode()->layer() ) )
1018  {
1019  if ( mLegendFilterByMapHitTest->symbolsForLayer( vl ).contains( ruleKey ) )
1020  filtered << node;
1021  }
1022  }
1023  else // unknown node type
1024  filtered << node;
1025  }
1026  }
1027  else
1028  {
1029  return nodes;
1030  }
1031 
1032  return filtered;
1033 }
1034 
1035 
1036 
1038 // Legend nodes routines - start
1039 
1041 {
1042  foreach ( const LayerLegendData& data, mLegend )
1043  {
1044  qDeleteAll( data.originalNodes );
1045  delete data.tree;
1046  }
1047  mLegend.clear();
1048 }
1049 
1050 
1052 {
1053  if ( mLegend.contains( nodeLayer ) )
1054  {
1055  qDeleteAll( mLegend[nodeLayer].originalNodes );
1056  delete mLegend[nodeLayer].tree;
1057  mLegend.remove( nodeLayer );
1058  }
1059 }
1060 
1061 
1063 {
1064  if ( !nodeL->layer() )
1065  return;
1066 
1067  QgsMapLayerLegend* layerLegend = nodeL->layer()->legend();
1068  if ( !layerLegend )
1069  return;
1070 
1071  QList<QgsLayerTreeModelLegendNode*> lstNew = layerLegend->createLayerTreeModelLegendNodes( nodeL );
1072 
1073  // apply filtering defined in layer node's custom properties (reordering, filtering, custom labels)
1075 
1076  QList<QgsLayerTreeModelLegendNode*> filteredLstNew = filterLegendNodes( lstNew );
1077 
1078  bool isEmbedded = filteredLstNew.count() == 1 && filteredLstNew[0]->isEmbeddedInParent();
1079 
1080  foreach ( QgsLayerTreeModelLegendNode* n, lstNew )
1081  {
1082  n->setParent( this );
1083  connect( n, SIGNAL( dataChanged() ), this, SLOT( legendNodeDataChanged() ) );
1084  }
1085 
1087  data.originalNodes = lstNew;
1088  data.activeNodes = filteredLstNew;
1089  data.tree = 0;
1090 
1091  // maybe the legend nodes form a tree - try to create a tree structure from the list
1092  if ( testFlag( ShowLegendAsTree ) )
1093  tryBuildLegendTree( data );
1094 
1095  int count = data.tree ? data.tree->children[0].count() : filteredLstNew.count();
1096 
1097  if ( ! isEmbedded ) beginInsertRows( node2index( nodeL ), 0, count - 1 );
1098 
1099  mLegend[nodeL] = data;
1100 
1101  if ( ! isEmbedded ) endInsertRows();
1102 }
1103 
1104 
1106 {
1107  // first check whether there are any legend nodes that are not top-level
1108  bool hasParentKeys = false;
1109  foreach ( QgsLayerTreeModelLegendNode* n, data.activeNodes )
1110  {
1111  if ( !n->data( QgsLayerTreeModelLegendNode::ParentRuleKeyRole ).toString().isEmpty() )
1112  {
1113  hasParentKeys = true;
1114  break;
1115  }
1116  }
1117  if ( !hasParentKeys )
1118  return; // all legend nodes are top-level => stick with list representation
1119 
1120  // make mapping from rules to nodes and do some sanity checks
1121  QHash<QString, QgsLayerTreeModelLegendNode*> rule2node;
1122  rule2node[QString()] = 0;
1123  foreach ( QgsLayerTreeModelLegendNode* n, data.activeNodes )
1124  {
1125  QString ruleKey = n->data( QgsLayerTreeModelLegendNode::RuleKeyRole ).toString();
1126  if ( ruleKey.isEmpty() ) // in tree all nodes must have key
1127  return;
1128  if ( rule2node.contains( ruleKey ) ) // and they must be unique
1129  return;
1130  rule2node[ruleKey] = n;
1131  }
1132 
1133  // create the tree structure
1134  data.tree = new LayerLegendTree;
1135  foreach ( QgsLayerTreeModelLegendNode* n, data.activeNodes )
1136  {
1137  QString parentRuleKey = n->data( QgsLayerTreeModelLegendNode::ParentRuleKeyRole ).toString();
1138  QgsLayerTreeModelLegendNode* parent = rule2node.value( parentRuleKey, 0 );
1139  data.tree->parents[n] = parent;
1140  data.tree->children[parent] << n;
1141  }
1142 }
1143 
1144 
1146 {
1147  return qobject_cast<QgsLayerTreeModelLegendNode*>( reinterpret_cast<QObject*>( index.internalPointer() ) );
1148 }
1149 
1150 
1152 {
1153  const LayerLegendData& data = mLegend[legendNode->layerNode()];
1154  if ( data.tree )
1155  {
1156  if ( QgsLayerTreeModelLegendNode* parentLegendNode = data.tree->parents[legendNode] )
1157  {
1158  QModelIndex parentIndex = legendNode2index( parentLegendNode );
1159  int row = data.tree->children[parentLegendNode].indexOf( legendNode );
1160  return index( row, 0, parentIndex );
1161  }
1162  else
1163  {
1164  QModelIndex parentIndex = node2index( legendNode->layerNode() );
1165  int row = data.tree->children[0].indexOf( legendNode );
1166  return index( row, 0, parentIndex );
1167  }
1168  }
1169 
1170  QModelIndex parentIndex = node2index( legendNode->layerNode() );
1171  Q_ASSERT( parentIndex.isValid() );
1172  int row = data.activeNodes.indexOf( legendNode );
1173  if ( row < 0 ) // legend node may be filtered (exists within the list of original nodes, but not in active nodes)
1174  return QModelIndex();
1175  return index( row, 0, parentIndex );
1176 }
1177 
1178 
1180 {
1181  const LayerLegendData& data = mLegend[node->layerNode()];
1182  if ( data.tree )
1183  return data.tree->children[node].count();
1184 
1185  return 0; // they are leaves
1186 }
1187 
1188 
1190 {
1191  if ( legendEmbeddedInParent( nL ) )
1192  return 0;
1193 
1194  if ( !mLegend.contains( nL ) )
1195  return 0;
1196 
1197  const LayerLegendData& data = mLegend[nL];
1198  if ( data.tree )
1199  return data.tree->children[0].count();
1200 
1201  return data.activeNodes.count();
1202 }
1203 
1204 
1205 QModelIndex QgsLayerTreeModel::legendRootIndex( int row, int column, QgsLayerTreeLayer* nL ) const
1206 {
1207  Q_ASSERT( mLegend.contains( nL ) );
1208  const LayerLegendData& data = mLegend[nL];
1209  if ( data.tree )
1210  return createIndex( row, column, static_cast<QObject*>( data.tree->children[0].at( row ) ) );
1211 
1212  return createIndex( row, column, static_cast<QObject*>( data.activeNodes.at( row ) ) );
1213 }
1214 
1215 
1216 QModelIndex QgsLayerTreeModel::legendNodeIndex( int row, int column, QgsLayerTreeModelLegendNode* node ) const
1217 {
1218  const LayerLegendData& data = mLegend[node->layerNode()];
1219  if ( data.tree )
1220  return createIndex( row, column, static_cast<QObject*>( data.tree->children[node].at( row ) ) );
1221 
1222  return QModelIndex(); // have no children
1223 }
1224 
1225 
1227 {
1228  QgsLayerTreeLayer* layerNode = legendNode->layerNode();
1229  const LayerLegendData& data = mLegend[layerNode];
1230  if ( data.tree )
1231  {
1232  if ( QgsLayerTreeModelLegendNode* parentNode = data.tree->parents[legendNode] )
1233  {
1234  QgsLayerTreeModelLegendNode* grandParentNode = data.tree->parents[parentNode]; // may be null (not a problem)
1235  int row = data.tree->children[grandParentNode].indexOf( parentNode );
1236  return createIndex( row, 0, static_cast<QObject*>( parentNode ) );
1237  }
1238  else
1239  return indexOfParentLayerTreeNode( layerNode );
1240  }
1241 
1242  return indexOfParentLayerTreeNode( layerNode );
1243 }
1244 
1245 
1247 {
1248  if ( role == Qt::CheckStateRole && !testFlag( AllowLegendChangeState ) )
1249  return QVariant();
1250  return node->data( role );
1251 }
1252 
1253 
1255 {
1256  Qt::ItemFlags f = node->flags();
1257  if ( !testFlag( AllowLegendChangeState ) )
1258  f &= ~Qt::ItemIsUserCheckable;
1259  return f;
1260 }
1261 
1262 
1264 {
1265  const LayerLegendData& data = mLegend[nodeLayer];
1266  return data.activeNodes.count() == 1 && data.activeNodes[0]->isEmbeddedInParent();
1267 }
1268 
1269 
1271 {
1272  return QIcon( qvariant_cast<QPixmap>( mLegend[nodeLayer].activeNodes[0]->data( Qt::DecorationRole ) ) );
1273 }
1274 
1275 
1276 QList<QgsLayerTreeModelLegendNode*> QgsLayerTreeModel::layerLegendNodes( QgsLayerTreeLayer* nodeLayer )
1277 {
1278  return mLegend.value( nodeLayer ).activeNodes;
1279 }
1280 
1282 {
1283  foreach ( const LayerLegendData& data, mLegend )
1284  {
1285  foreach ( QgsLayerTreeModelLegendNode* legendNode, data.originalNodes )
1286  legendNode->invalidateMapBasedData();
1287  }
1288 }
1289 
1290 // Legend nodes routines - end
int legendNodeRowCount(QgsLayerTreeModelLegendNode *node) const
Layer tree group node serves as a container for layers and further groups.
static const QIcon & iconGroup()
void removeChildren(int from, int count)
Remove child nodes from index "from". The nodes will be deleted.
QModelIndex parent(const QModelIndex &child) const override
static unsigned index
QList< QgsLayerTreeModelLegendNode * > originalNodes
Data structure for storage of legend nodes.
QModelIndex legendParent(QgsLayerTreeModelLegendNode *legendNode) const
Base class for all map layer types.
Definition: qgsmaplayer.h:49
void setLayerName(const QString &n)
QModelIndex currentIndex() const
Get index of the item marked as current. Item marked as current is underlined.
QMimeData * mimeData(const QModelIndexList &indexes) const override
QList< QgsLayerTreeModelLegendNode * > layerLegendNodes(QgsLayerTreeLayer *nodeLayer)
Return list of legend nodes attached to a particular layer node.
QIcon legendIconEmbeddedInParent(QgsLayerTreeLayer *nodeLayer) const
Q_DECL_DEPRECATED bool isIndexSymbologyNode(const QModelIndex &index) const
Return true if index represents a legend node (instead of layer node)
QgsMapLayer::LayerType type() const
Get the type of the layer.
Definition: qgsmaplayer.cpp:92
void removeLegendFromLayer(QgsLayerTreeLayer *nodeLayer)
void connectToLayer(QgsLayerTreeLayer *nodeLayer)
void setCurrentIndex(const QModelIndex &currentIndex)
Set index of the current item. May be used by view. Item marked as current is underlined.
QList< QgsLayerTreeNode * > indexes2nodes(const QModelIndexList &list, bool skipInternal=false) const
Convert a list of indexes to a list of layer tree nodes.
LayerLegendTree * tree
Optional pointer to a tree structure - see LayerLegendTree for details.
QgsLayerTreeGroup * rootGroup() const
Return pointer to the root node of the layer tree. Always a non-null pointer.
static const QIcon & iconDefault()
Definition: qgsdataitem.cpp:95
void nodeCustomPropertyChanged(QgsLayerTreeNode *node, const QString &key)
void addLegendToLayer(QgsLayerTreeLayer *nodeL)
static const QIcon & iconPoint()
Definition: qgsdataitem.cpp:45
QVariant customProperty(const QString &key, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer.
QgsMapLayer * layer() const
Qt::ItemFlags legendNodeFlags(QgsLayerTreeModelLegendNode *node) const
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
virtual bool setData(const QVariant &value, int role)
Set some data associated with the item.
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
static QIcon getThemeIcon(const QString &theName)
Helper to get a theme icon.
static int _numLayerCount(QgsLayerTreeGroup *group, const QString &layerId)
bool legendEmbeddedInParent(QgsLayerTreeLayer *nodeLayer) const
Structure that stores tree representation of map layer's legend.
Flags flags() const
Return OR-ed combination of model flags.
QList< QgsLayerTreeModelLegendNode * > filterLegendNodes(const QList< QgsLayerTreeModelLegendNode * > &nodes)
Filter nodes from QgsMapLayerLegend according to the current filtering rules.
void recursivelyEmitDataChanged(const QModelIndex &index=QModelIndex())
emit dataChanged() for layer tree node items
static bool _isChildOfNode(QgsLayerTreeNode *child, QgsLayerTreeNode *node)
virtual Qt::ItemFlags flags() const
Return item flags associated with the item.
static const QIcon & iconPolygon()
Definition: qgsdataitem.cpp:65
QScopedPointer< QgsMapSettings > mLegendFilterByMapSettings
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.
QScopedPointer< QgsMapHitTest > mLegendFilterByMapHitTest
QVariant legendNodeData(QgsLayerTreeModelLegendNode *node, int role) const
Flags mFlags
Set of flags for the model.
virtual bool isEditable() const override
Returns true if the provider is in editing mode.
void tryBuildLegendTree(LayerLegendData &data)
static QPixmap getThemePixmap(const QString &theName)
Helper to get a theme icon as a pixmap.
virtual void writeXML(QDomElement &parentElement)=0
Write layer tree to XML.
void nodeAddedChildren(QgsLayerTreeNode *node, int indexFrom, int indexTo)
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
void nodeWillAddChildren(QgsLayerTreeNode *node, int indexFrom, int indexTo)
Allow check boxes for legend nodes (if supported by layer's legend)
void connectToLayers(QgsLayerTreeGroup *parentGroup)
The QgsMapSettings class contains configuration for rendering of the map.
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Allow renaming of groups and layers.
rule key of the parent legend node - for legends with tree hierarchy (QString). Added in 2...
Qt::CheckState isVisible() const
void disconnectFromLayer(QgsLayerTreeLayer *nodeLayer)
QMap< QgsLayerTreeModelLegendNode *, QgsLayerTreeModelLegendNode * > parents
Pointer to parent for each active node. Top-level nodes have null parent. Pointers are not owned...
QModelIndex legendNode2index(QgsLayerTreeModelLegendNode *legendNode)
Return index for a given legend node.
static const QIcon & iconRaster()
Definition: qgsdataitem.cpp:85
void disconnectFromLayers(QgsLayerTreeGroup *parentGroup)
bool hasValidSettings() const
Check whether the map settings are valid and can be used for rendering.
void setLegendFilterByMap(const QgsMapSettings *settings)
Force only display of legend nodes which are valid for given map settings.
int legendRootRowCount(QgsLayerTreeLayer *nL) const
static QgsLayerTreeModelLegendNode * index2legendNode(const QModelIndex &index)
Return legend node for given index.
Qt::DropActions supportedDropActions() const override
QList< QgsLayerTreeLayer * > findLayers() const
Find all layer nodes. Searches recursively the whole sub-tree.
QgsLayerTreeNode * parent()
Get pointer to the parent. If parent is a null pointer, the node is a root node.
bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override
int autoCollapseLegendNodes() const
Return at what number of legend nodes the layer node should be collapsed. -1 means no auto-collapse (...
void legendMapViewData(double *mapUnitsPerPixel, int *dpi, double *scale)
Get hints about map view - to be used in legend nodes.
void setName(const QString &n)
Set group's name.
void setFlags(Flags f)
Set OR-ed combination of model flags.
QgsLayerTreeLayer * layerNode() const
Return pointer to the parent layer node.
The QgsMapLayerLegend class is abstract interface for implementations of legends for one map layer...
int pendingFeatureCount()
returns feature count after commit
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.
Definition: qgsmaplayer.cpp:98
QgsLayerTreeGroup * mRootNode
Pointer to the root node of the layer tree. Not owned by the model.
QString layerId() const
void setVisible(Qt::CheckState visible)
virtual bool isModified() const
Returns true if the provider has been modified since the last commit.
QGis::GeometryType geometryType() const
Returns point, line or polygon.
QMap< QgsLayerTreeModelLegendNode *, QList< QgsLayerTreeModelLegendNode * > > children
List of children for each active node. Top-level nodes are under null pointer key. Pointers are not owned.
static QgsLayerTreeNode * readXML(QDomElement &element)
Read layer tree from XML. Returns new instance.
QString name() const
Get group's name.
Class that runs a hit test with given map settings.
Definition: qgsmaphittest.h:18
void setLegendFilterByScale(double scaleDenominator)
Force only display of legend nodes which are valid for given scale denominator.
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
void setLayerTreeNodeFont(int nodeType, const QFont &font)
Set font for a particular type of layer tree node. nodeType should come from QgsLayerTreeNode::NodeTy...
Qt::CheckState isVisible() const
Return the check state of the group node.
void setFlag(Flag f, bool on=true)
Enable or disable a model flag.
static void applyLayerNodeProperties(QgsLayerTreeLayer *nodeLayer, QList< QgsLayerTreeModelLegendNode * > &nodes)
update according to layer node's custom properties (order of items, user labels for items) ...
QPersistentModelIndex mCurrentIndex
Current index - will be underlined.
Q_DECL_DEPRECATED QPixmap previewAsPixmap(QSize size, QColor bgColor=Qt::white)
Draws a preview of the rasterlayer into a pixmap.
void setRootGroup(QgsLayerTreeGroup *newRootGroup)
Reset the model and use a new root group node.
bool testFlag(Flag f) const
Check whether a flag is enabled.
double mLegendFilterByScale
scale denominator for filtering of legend nodes (<= 0 means no filtering)
void refreshLayerLegend(QgsLayerTreeLayer *nodeLayer)
Force a refresh of legend nodes of a layer node.
void setExpanded(bool expanded)
Set whether the node should be shown as expanded or collapsed in GUI.
void setLegendMapViewData(double mapUnitsPerPixel, int dpi, double scale)
Give the layer tree model hints about the currently associated map view so that legend nodes that use...
QgsMapLayerLegend * legend() const
Can be null.
static const QIcon & iconTable()
Definition: qgsdataitem.cpp:75
QModelIndex node2index(QgsLayerTreeNode *node) const
Return index for a given node. If the node does not belong to the layer tree, the result is undefined...
void setAutoCollapseLegendNodes(int nodeCount)
Set at what number of legend nodes the layer node should be collapsed. Setting -1 disables the auto-c...
leaf node pointing to a layer
static bool _isChildOfNodes(QgsLayerTreeNode *child, QList< QgsLayerTreeNode * > nodes)
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
int mAutoCollapseLegendNodesCount
Minimal number of nodes when legend should be automatically collapsed. -1 = disabled.
QModelIndex indexOfParentLayerTreeNode(QgsLayerTreeNode *parentNode) const
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 bool isScaleOK(double scale) const
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
QStringList mimeTypes() const override
virtual QVariant data(int role) const =0
Return data associated with the item.
static const QIcon & iconLine()
Definition: qgsdataitem.cpp:55
The QgsLegendRendererItem class is abstract interface for legend items returned from QgsMapLayerLegen...
QgsLayerTreeModel(QgsLayerTreeGroup *rootNode, QObject *parent=0)
Construct a new tree model with given layer tree (root node must not be null pointer).
QgsLayerTreeLayer * findLayer(const QString &layerId) const
Find layer node representing the map layer specified by its ID. Searches recursively the whole sub-tr...
for QgsSymbolV2LegendNode only - legacy rule key (void ptr, to be cast to QgsSymbolV2 ptr) ...
Allow user to set node visibility with a check box.
QFont layerTreeNodeFont(int nodeType) const
Get font for a particular type of layer tree node. nodeType should come from QgsLayerTreeNode::NodeTy...
QgsLayerTreeNode * index2node(const QModelIndex &index) const
Return layer tree node for given index.
container of other groups and layers
int columnCount(const QModelIndex &parent=QModelIndex()) const override
QList< QgsLayerTreeModelLegendNode * > activeNodes
Active legend nodes.
For legends that support it, will show them in a tree instead of a list (needs also ShowLegend)...
QString layerName() const
Q_DECL_DEPRECATED QgsLayerTreeLayer * layerNodeForSymbologyNode(const QModelIndex &index) const
Return layer node to which a legend node belongs to.
Represents a vector layer which manages a vector based data sets.
Will use real preview of raster layer as icon (may be slow)
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
QModelIndex legendRootIndex(int row, int column, QgsLayerTreeLayer *nL) const
static QList< QgsLayerTreeLayer * > _layerNodesInSubtree(QgsLayerTreeNode *node, int indexFrom, int indexTo)
Allow reordering with drag'n'drop.
Add legend nodes for layer nodes.
virtual void invalidateMapBasedData()
Notification from model that information from associated map view has changed.
void nodeWillRemoveChildren(QgsLayerTreeNode *node, int indexFrom, int indexTo)
virtual QList< QgsLayerTreeModelLegendNode * > createLayerTreeModelLegendNodes(QgsLayerTreeLayer *nodeLayer)=0
Return list of legend nodes to be used for a particular layer tree layer node.
QMap< QgsLayerTreeLayer *, LayerLegendData > mLegend
Per layer data about layer's legend nodes.
QModelIndex legendNodeIndex(int row, int column, QgsLayerTreeModelLegendNode *node) const
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Layer tree node points to a map layer.
void nodeVisibilityChanged(QgsLayerTreeNode *node)
Structure that stores all data associated with one map layer.