QGIS API Documentation  2.7.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  }
198 
199  QgsVectorLayer *vlayer = dynamic_cast<QgsVectorLayer*>( layer );
200 
201  if ( layer->type() == QgsMapLayer::RasterLayer )
202  {
203  return QgsLayerItem::iconRaster();
204  }
205 
206  QIcon icon;
207 
208  // if there's just on legend entry that should be embedded in layer - do that!
209  if ( testFlag( ShowLegend ) && legendEmbeddedInParent( nodeLayer ) )
210  {
211  icon = legendIconEmbeddedInParent( nodeLayer );
212  }
213  else if ( layer->type() == QgsMapLayer::VectorLayer )
214  {
215  if ( vlayer->geometryType() == QGis::Point )
216  icon = QgsLayerItem::iconPoint();
217  else if ( vlayer->geometryType() == QGis::Line )
218  icon = QgsLayerItem::iconLine();
219  else if ( vlayer->geometryType() == QGis::Polygon )
220  icon = QgsLayerItem::iconPolygon();
221  else if ( vlayer->geometryType() == QGis::NoGeometry )
222  icon = QgsLayerItem::iconTable();
223  else
224  icon = QgsLayerItem::iconDefault();
225  }
226 
227  if ( vlayer && vlayer->isEditable() )
228  {
229  QPixmap pixmap( icon.pixmap( 16, 16 ) );
230 
231  QPainter painter( &pixmap );
232  painter.drawPixmap( 0, 0, 16, 16, QgsApplication::getThemePixmap( vlayer->isModified() ? "/mIconEditableEdits.png" : "/mIconEditable.png" ) );
233  painter.end();
234 
235  icon = QIcon( pixmap );
236  }
237 
238  return icon;
239  }
240  }
241  else if ( role == Qt::CheckStateRole )
242  {
244  return QVariant();
245 
246  if ( QgsLayerTree::isLayer( node ) )
247  {
248  QgsLayerTreeLayer* nodeLayer = QgsLayerTree::toLayer( node );
249  if ( nodeLayer->layer() && nodeLayer->layer()->type() == QgsMapLayer::VectorLayer )
250  {
251  if ( qobject_cast<QgsVectorLayer*>( nodeLayer->layer() )->geometryType() == QGis::NoGeometry )
252  return QVariant(); // do not show checkbox for non-spatial tables
253  }
254  return nodeLayer->isVisible();
255  }
256  else if ( QgsLayerTree::isGroup( node ) )
257  {
258  QgsLayerTreeGroup* nodeGroup = QgsLayerTree::toGroup( node );
259  return nodeGroup->isVisible();
260  }
261  }
262  else if ( role == Qt::FontRole )
263  {
264  QFont f( QgsLayerTree::isLayer( node ) ? mFontLayer : ( QgsLayerTree::isGroup( node ) ? mFontGroup : QFont() ) );
265  if ( node->customProperty( "embedded" ).toInt() )
266  f.setItalic( true );
267  if ( index == mCurrentIndex )
268  f.setUnderline( true );
269  return f;
270  }
271  else if ( role == Qt::ToolTipRole )
272  {
273  if ( QgsLayerTree::isLayer( node ) )
274  {
275  if ( QgsMapLayer* layer = QgsLayerTree::toLayer( node )->layer() )
276  return layer->publicSource();
277  }
278  }
279 
280  return QVariant();
281 }
282 
283 
284 Qt::ItemFlags QgsLayerTreeModel::flags( const QModelIndex& index ) const
285 {
286  if ( !index.isValid() )
287  {
288  Qt::ItemFlags rootFlags = 0;
289  if ( testFlag( AllowNodeReorder ) )
290  rootFlags |= Qt::ItemIsDropEnabled;
291  return rootFlags;
292  }
293 
294  if ( QgsLayerTreeModelLegendNode* symn = index2legendNode( index ) )
295  return legendNodeFlags( symn );
296 
297  Qt::ItemFlags f = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
298 
299  if ( testFlag( AllowNodeRename ) )
300  f |= Qt::ItemIsEditable;
301 
302  QgsLayerTreeNode* node = index2node( index );
303  bool isEmbedded = node->customProperty( "embedded" ).toInt();
304 
305  if ( testFlag( AllowNodeReorder ) )
306  {
307  // only root embedded nodes can be reordered
308  if ( !isEmbedded || ( isEmbedded && node->parent() && !node->parent()->customProperty( "embedded" ).toInt() ) )
309  f |= Qt::ItemIsDragEnabled;
310  }
311 
313  f |= Qt::ItemIsUserCheckable;
314 
315  if ( testFlag( AllowNodeReorder ) && QgsLayerTree::isGroup( node ) && !isEmbedded )
316  f |= Qt::ItemIsDropEnabled;
317 
318  return f;
319 }
320 
321 bool QgsLayerTreeModel::setData( const QModelIndex& index, const QVariant& value, int role )
322 {
324  if ( sym )
325  {
326  if ( role == Qt::CheckStateRole && !testFlag( AllowLegendChangeState ) )
327  return false;
328  bool res = sym->setData( value, role );
329  if ( res )
330  emit dataChanged( index, index );
331  return res;
332  }
333 
334  QgsLayerTreeNode* node = index2node( index );
335  if ( !node )
336  return QgsLayerTreeModel::setData( index, value, role );
337 
338  if ( role == Qt::CheckStateRole )
339  {
341  return false;
342 
343  if ( QgsLayerTree::isLayer( node ) )
344  {
345  QgsLayerTreeLayer* layer = QgsLayerTree::toLayer( node );
346  layer->setVisible(( Qt::CheckState )value.toInt() );
347  return true;
348  }
349 
350  if ( QgsLayerTree::isGroup( node ) )
351  {
352  QgsLayerTreeGroup* group = QgsLayerTree::toGroup( node );
353  group->setVisible(( Qt::CheckState )value.toInt() );
354  return true;
355  }
356 
357  return true;
358  }
359  else if ( role == Qt::EditRole )
360  {
361  if ( !testFlag( AllowNodeRename ) )
362  return false;
363 
364  if ( QgsLayerTree::isLayer( node ) )
365  {
366  QgsLayerTreeLayer* layer = QgsLayerTree::toLayer( node );
367  layer->setLayerName( value.toString() );
368  emit dataChanged( index, index );
369  }
370  else if ( QgsLayerTree::isGroup( node ) )
371  {
372  QgsLayerTree::toGroup( node )->setName( value.toString() );
373  emit dataChanged( index, index );
374  }
375  }
376 
377  return QAbstractItemModel::setData( index, value, role );
378 }
379 
381 {
382  if ( !node->parent() )
383  return QModelIndex(); // this is the only root item -> invalid index
384 
385  QModelIndex parentIndex = node2index( node->parent() );
386 
387  int row = node->parent()->children().indexOf( node );
388  Q_ASSERT( row >= 0 );
389  return index( row, 0, parentIndex );
390 }
391 
392 
394 {
395  if ( !child->parent() )
396  return false;
397 
398  if ( child->parent() == node )
399  return true;
400 
401  return _isChildOfNode( child->parent(), node );
402 }
403 
404 static bool _isChildOfNodes( QgsLayerTreeNode* child, QList<QgsLayerTreeNode*> nodes )
405 {
406  foreach ( QgsLayerTreeNode* n, nodes )
407  {
408  if ( _isChildOfNode( child, n ) )
409  return true;
410  }
411 
412  return false;
413 }
414 
415 
416 QList<QgsLayerTreeNode*> QgsLayerTreeModel::indexes2nodes( const QModelIndexList& list, bool skipInternal ) const
417 {
418  QList<QgsLayerTreeNode*> nodes;
419  foreach ( QModelIndex index, list )
420  {
421  QgsLayerTreeNode* node = index2node( index );
422  if ( !node )
423  continue;
424 
425  nodes << node;
426  }
427 
428  if ( !skipInternal )
429  return nodes;
430 
431  // remove any children of nodes if both parent node and children are selected
432  QList<QgsLayerTreeNode*> nodesFinal;
433  foreach ( QgsLayerTreeNode* node, nodes )
434  {
435  if ( !_isChildOfNodes( node, nodes ) )
436  nodesFinal << node;
437  }
438 
439  return nodesFinal;
440 }
441 
442 bool QgsLayerTreeModel::isIndexSymbologyNode( const QModelIndex& index ) const
443 {
444  return index2legendNode( index ) != 0;
445 }
446 
448 {
449  QgsLayerTreeModelLegendNode* symNode = index2legendNode( index );
450  return symNode ? symNode->layerNode() : 0;
451 }
452 
454 {
455  return mRootNode;
456 }
457 
459 {
460  beginResetModel();
461 
463 
464  Q_ASSERT( mLegend.isEmpty() );
465 
466  mRootNode = newRootGroup;
467 
468  endResetModel();
469 
471 }
472 
474 {
475  // update title
476  QModelIndex idx = node2index( nodeLayer );
477  emit dataChanged( idx, idx );
478 
479  // update children
480  int oldNodeCount = rowCount( idx );
481  beginRemoveRows( idx, 0, oldNodeCount - 1 );
482  removeLegendFromLayer( nodeLayer );
483  endRemoveRows();
484 
485  addLegendToLayer( nodeLayer );
486  int newNodeCount = rowCount( idx );
487 
488  // automatic collapse of legend nodes - useful if a layer has many legend nodes
489  if ( mAutoCollapseLegendNodesCount != -1 && oldNodeCount != newNodeCount && newNodeCount >= mAutoCollapseLegendNodesCount )
490  nodeLayer->setExpanded( false );
491 }
492 
494 {
495  return mCurrentIndex;
496 }
497 
498 void QgsLayerTreeModel::setCurrentIndex( const QModelIndex& currentIndex )
499 {
500  QModelIndex oldIndex = mCurrentIndex;
502 
503  if ( oldIndex.isValid() )
504  emit dataChanged( oldIndex, oldIndex );
505  if ( currentIndex.isValid() )
506  emit dataChanged( currentIndex, currentIndex );
507 }
508 
509 
510 void QgsLayerTreeModel::setLayerTreeNodeFont( int nodeType, const QFont& font )
511 {
512  if ( nodeType == QgsLayerTreeNode::NodeGroup )
513  {
514  if ( mFontGroup != font )
515  {
516  mFontGroup = font;
518  }
519  }
520  else if ( nodeType == QgsLayerTreeNode::NodeLayer )
521  {
522  if ( mFontLayer != font )
523  {
524  mFontLayer = font;
526  }
527  }
528  else
529  {
530  QgsDebugMsg( "invalid node type" );
531  }
532 }
533 
534 
535 QFont QgsLayerTreeModel::layerTreeNodeFont( int nodeType ) const
536 {
537  if ( nodeType == QgsLayerTreeNode::NodeGroup )
538  return mFontGroup;
539  else if ( nodeType == QgsLayerTreeNode::NodeLayer )
540  return mFontLayer;
541  else
542  {
543  QgsDebugMsg( "invalid node type" );
544  return QFont();
545  }
546 }
547 
548 void QgsLayerTreeModel::setLegendFilterByScale( double scaleDenominator )
549 {
550  mLegendFilterByScale = scaleDenominator;
551 
552  // this could be later done in more efficient way
553  // by just updating active legend nodes, without refreshing original legend nodes
554  foreach ( QgsLayerTreeLayer* nodeLayer, mRootNode->findLayers() )
555  refreshLayerLegend( nodeLayer );
556 }
557 
559 {
560  if ( settings && settings->hasValidSettings() )
561  {
562  mLegendFilterByMapSettings.reset( new QgsMapSettings( *settings ) );
565  }
566  else
567  {
569  return; // no change
570 
573  }
574 
575  // temporarily disable autocollapse so that legend nodes stay visible
576  int bkAutoCollapse = autoCollapseLegendNodes();
578 
579  // this could be later done in more efficient way
580  // by just updating active legend nodes, without refreshing original legend nodes
581  foreach ( QgsLayerTreeLayer* nodeLayer, mRootNode->findLayers() )
582  refreshLayerLegend( nodeLayer );
583 
584  setAutoCollapseLegendNodes( bkAutoCollapse );
585 }
586 
587 void QgsLayerTreeModel::setLegendMapViewData( double mapUnitsPerPixel, int dpi, double scale )
588 {
589  if ( mLegendMapViewDpi == dpi && mLegendMapViewMupp == mapUnitsPerPixel && mLegendMapViewScale == scale )
590  return;
591 
592  mLegendMapViewMupp = mapUnitsPerPixel;
593  mLegendMapViewDpi = dpi;
594  mLegendMapViewScale = scale;
595 
596  // now invalidate legend nodes!
598 }
599 
600 void QgsLayerTreeModel::legendMapViewData( double* mapUnitsPerPixel, int* dpi, double* scale )
601 {
602  if ( mapUnitsPerPixel ) *mapUnitsPerPixel = mLegendMapViewMupp;
603  if ( dpi ) *dpi = mLegendMapViewDpi;
604  if ( scale ) *scale = mLegendMapViewScale;
605 }
606 
607 void QgsLayerTreeModel::nodeWillAddChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo )
608 {
609  Q_ASSERT( node );
610  beginInsertRows( node2index( node ), indexFrom, indexTo );
611 }
612 
613 static QList<QgsLayerTreeLayer*> _layerNodesInSubtree( QgsLayerTreeNode* node, int indexFrom, int indexTo )
614 {
615  QList<QgsLayerTreeNode*> children = node->children();
616  QList<QgsLayerTreeLayer*> newLayerNodes;
617  for ( int i = indexFrom; i <= indexTo; ++i )
618  {
619  QgsLayerTreeNode* child = children.at( i );
620  if ( QgsLayerTree::isLayer( child ) )
621  newLayerNodes << QgsLayerTree::toLayer( child );
622  else if ( QgsLayerTree::isGroup( child ) )
623  newLayerNodes << QgsLayerTree::toGroup( child )->findLayers();
624  }
625  return newLayerNodes;
626 }
627 
628 void QgsLayerTreeModel::nodeAddedChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo )
629 {
630  Q_ASSERT( node );
631 
632  endInsertRows();
633 
634  foreach ( QgsLayerTreeLayer* newLayerNode, _layerNodesInSubtree( node, indexFrom, indexTo ) )
635  connectToLayer( newLayerNode );
636 }
637 
638 void QgsLayerTreeModel::nodeWillRemoveChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo )
639 {
640  Q_ASSERT( node );
641 
642  beginRemoveRows( node2index( node ), indexFrom, indexTo );
643 
644  // disconnect from layers and remove their legend
645  foreach ( QgsLayerTreeLayer* nodeLayer, _layerNodesInSubtree( node, indexFrom, indexTo ) )
646  disconnectFromLayer( nodeLayer );
647 }
648 
650 {
651  endRemoveRows();
652 }
653 
655 {
656  Q_ASSERT( node );
657 
658  QModelIndex index = node2index( node );
659  emit dataChanged( index, index );
660 }
661 
662 
664 {
665  if ( QgsLayerTree::isLayer( node ) && key == "showFeatureCount" )
667 }
668 
669 
671 {
672  QgsLayerTreeLayer* nodeLayer = qobject_cast<QgsLayerTreeLayer*>( sender() );
673  if ( !nodeLayer )
674  return;
675 
676  // deffered connection to the layer
677  connectToLayer( nodeLayer );
678 }
679 
681 {
682  QgsLayerTreeLayer* nodeLayer = qobject_cast<QgsLayerTreeLayer*>( sender() );
683  if ( !nodeLayer )
684  return;
685 
686  disconnectFromLayer( nodeLayer );
687 
688  // wait for the layer to appear again
689  connect( nodeLayer, SIGNAL( layerLoaded() ), this, SLOT( nodeLayerLoaded() ) );
690 }
691 
693 {
694  if ( !testFlag( ShowLegend ) )
695  return;
696 
697  QgsMapLayer* layer = qobject_cast<QgsMapLayer*>( sender() );
698  if ( !layer )
699  return;
700 
701  QgsLayerTreeLayer* nodeLayer = mRootNode->findLayer( layer->id() );
702  if ( !nodeLayer )
703  return;
704 
705  refreshLayerLegend( nodeLayer );
706 }
707 
709 {
710  QgsMapLayer* layer = qobject_cast<QgsMapLayer*>( sender() );
711  if ( !layer )
712  return;
713 
714  QgsLayerTreeLayer* nodeLayer = mRootNode->findLayer( layer->id() );
715  if ( !nodeLayer )
716  return;
717 
718  QModelIndex index = node2index( nodeLayer );
719  emit dataChanged( index, index );
720 
721  if ( nodeLayer->customProperty( "showFeatureCount" ).toInt() )
722  refreshLayerLegend( nodeLayer );
723 }
724 
725 
727 {
728  QgsLayerTreeModelLegendNode* legendNode = qobject_cast<QgsLayerTreeModelLegendNode*>( sender() );
729  if ( !legendNode )
730  return;
731 
732  QModelIndex index = legendNode2index( legendNode );
733  if ( index.isValid() )
734  emit dataChanged( index, index );
735 }
736 
737 
739 {
740  if ( !nodeLayer->layer() )
741  {
742  // in order to connect to layer, we need to have it loaded.
743  // keep an eye on the layer ID: once loaded, we will use it
744  connect( nodeLayer, SIGNAL( layerLoaded() ), this, SLOT( nodeLayerLoaded() ) );
745  return;
746  }
747 
748  // watch if the layer is getting removed
749  connect( nodeLayer, SIGNAL( layerWillBeUnloaded() ), this, SLOT( nodeLayerWillBeUnloaded() ) );
750 
751  if ( testFlag( ShowLegend ) )
752  {
753  addLegendToLayer( nodeLayer );
754 
755  // automatic collapse of legend nodes - useful if a layer has many legend nodes
756  if ( !mRootNode->customProperty( "loading" ).toBool() )
757  {
759  nodeLayer->setExpanded( false );
760  }
761  }
762 
763  QgsMapLayer* layer = nodeLayer->layer();
764  connect( layer, SIGNAL( legendChanged() ), this, SLOT( layerLegendChanged() ), Qt::UniqueConnection );
765 
766  if ( layer->type() == QgsMapLayer::VectorLayer )
767  {
768  // using unique connection because there may be temporarily more nodes for a layer than just one
769  // which would create multiple connections, however disconnect() would disconnect all multiple connections
770  // even if we wanted to disconnect just one connection in each call.
771  connect( layer, SIGNAL( editingStarted() ), this, SLOT( layerNeedsUpdate() ), Qt::UniqueConnection );
772  connect( layer, SIGNAL( editingStopped() ), this, SLOT( layerNeedsUpdate() ), Qt::UniqueConnection );
773  connect( layer, SIGNAL( layerModified() ), this, SLOT( layerNeedsUpdate() ), Qt::UniqueConnection );
774  connect( layer, SIGNAL( layerNameChanged() ), this, SLOT( layerNeedsUpdate() ), Qt::UniqueConnection );
775  }
776 }
777 
778 // try to find out if the layer ID is present in the tree multiple times
779 static int _numLayerCount( QgsLayerTreeGroup* group, const QString& layerId )
780 {
781  int count = 0;
782  foreach ( QgsLayerTreeNode* child, group->children() )
783  {
784  if ( QgsLayerTree::isLayer( child ) )
785  {
786  if ( QgsLayerTree::toLayer( child )->layerId() == layerId )
787  count++;
788  }
789  else if ( QgsLayerTree::isGroup( child ) )
790  {
791  count += _numLayerCount( QgsLayerTree::toGroup( child ), layerId );
792  }
793  }
794  return count;
795 }
796 
798 {
799  disconnect( nodeLayer, 0, this, 0 ); // disconnect from delayed load of layer
800 
801  if ( !nodeLayer->layer() )
802  return; // we were never connected
803 
804  if ( testFlag( ShowLegend ) )
805  {
806  removeLegendFromLayer( nodeLayer );
807  }
808 
809  if ( _numLayerCount( mRootNode, nodeLayer->layerId() ) == 1 )
810  {
811  // last instance of the layer in the tree: disconnect from all signals from layer!
812  disconnect( nodeLayer->layer(), 0, this, 0 );
813  }
814 }
815 
817 {
818  foreach ( QgsLayerTreeNode* node, parentGroup->children() )
819  {
820  if ( QgsLayerTree::isGroup( node ) )
822  else if ( QgsLayerTree::isLayer( node ) )
824  }
825 }
826 
828 {
829  foreach ( QgsLayerTreeNode* node, parentGroup->children() )
830  {
831  if ( QgsLayerTree::isGroup( node ) )
833  else if ( QgsLayerTree::isLayer( node ) )
835  }
836 }
837 
839 {
840  Q_ASSERT( mRootNode );
841 
842  connect( mRootNode, SIGNAL( willAddChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeWillAddChildren( QgsLayerTreeNode*, int, int ) ) );
843  connect( mRootNode, SIGNAL( addedChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeAddedChildren( QgsLayerTreeNode*, int, int ) ) );
844  connect( mRootNode, SIGNAL( willRemoveChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeWillRemoveChildren( QgsLayerTreeNode*, int, int ) ) );
845  connect( mRootNode, SIGNAL( removedChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeRemovedChildren() ) );
846  connect( mRootNode, SIGNAL( visibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ), this, SLOT( nodeVisibilityChanged( QgsLayerTreeNode* ) ) );
847 
848  connect( mRootNode, SIGNAL( customPropertyChanged( QgsLayerTreeNode*, QString ) ), this, SLOT( nodeCustomPropertyChanged( QgsLayerTreeNode*, QString ) ) );
849 
851 }
852 
854 {
855  disconnect( mRootNode, 0, this, 0 );
856 
858 }
859 
860 void QgsLayerTreeModel::recursivelyEmitDataChanged( const QModelIndex& idx )
861 {
862  QgsLayerTreeNode* node = index2node( idx );
863  if ( !node )
864  return;
865 
866  int count = node->children().count();
867  if ( count == 0 )
868  return;
869  emit dataChanged( index( 0, 0, idx ), index( count - 1, 0, idx ) );
870  for ( int i = 0; i < count; ++i )
871  recursivelyEmitDataChanged( index( i, 0, idx ) );
872 }
873 
874 
876 {
877  return Qt::MoveAction;
878 }
879 
880 QStringList QgsLayerTreeModel::mimeTypes() const
881 {
882  QStringList types;
883  types << "application/qgis.layertreemodeldata";
884  return types;
885 }
886 
887 
888 QMimeData* QgsLayerTreeModel::mimeData( const QModelIndexList& indexes ) const
889 {
890  QList<QgsLayerTreeNode*> nodesFinal = indexes2nodes( indexes, true );
891 
892  if ( nodesFinal.count() == 0 )
893  return 0;
894 
895  QMimeData *mimeData = new QMimeData();
896 
897  QDomDocument doc;
898  QDomElement rootElem = doc.createElement( "layer_tree_model_data" );
899  foreach ( QgsLayerTreeNode* node, nodesFinal )
900  node->writeXML( rootElem );
901  doc.appendChild( rootElem );
902  QString txt = doc.toString();
903 
904  mimeData->setData( "application/qgis.layertreemodeldata", txt.toUtf8() );
905  return mimeData;
906 }
907 
908 bool QgsLayerTreeModel::dropMimeData( const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent )
909 {
910  if ( action == Qt::IgnoreAction )
911  return true;
912 
913  if ( !data->hasFormat( "application/qgis.layertreemodeldata" ) )
914  return false;
915 
916  if ( column >= columnCount( parent ) )
917  return false;
918 
919  QgsLayerTreeNode* nodeParent = index2node( parent );
920  if ( !QgsLayerTree::isGroup( nodeParent ) )
921  return false;
922 
923  QByteArray encodedData = data->data( "application/qgis.layertreemodeldata" );
924 
925  QDomDocument doc;
926  if ( !doc.setContent( QString::fromUtf8( encodedData ) ) )
927  return false;
928 
929  QDomElement rootElem = doc.documentElement();
930  if ( rootElem.tagName() != "layer_tree_model_data" )
931  return false;
932 
933  QList<QgsLayerTreeNode*> nodes;
934 
935  QDomElement elem = rootElem.firstChildElement();
936  while ( !elem.isNull() )
937  {
939  if ( node )
940  nodes << node;
941 
942  elem = elem.nextSiblingElement();
943  }
944 
945  if ( nodes.count() == 0 )
946  return false;
947 
948  if ( parent.isValid() && row == -1 )
949  row = 0; // if dropped directly onto group item, insert at first position
950 
951  QgsLayerTree::toGroup( nodeParent )->insertChildNodes( row, nodes );
952 
953  return true;
954 }
955 
956 bool QgsLayerTreeModel::removeRows( int row, int count, const QModelIndex& parent )
957 {
958  QgsLayerTreeNode* parentNode = index2node( parent );
959  if ( QgsLayerTree::isGroup( parentNode ) )
960  {
961  QgsLayerTree::toGroup( parentNode )->removeChildren( row, count );
962  return true;
963  }
964  return false;
965 }
966 
967 void QgsLayerTreeModel::setFlags( QgsLayerTreeModel::Flags f )
968 {
969  mFlags = f;
970 }
971 
973 {
974  if ( on )
975  mFlags |= f;
976  else
977  mFlags &= ~f;
978 }
979 
980 QgsLayerTreeModel::Flags QgsLayerTreeModel::flags() const
981 {
982  return mFlags;
983 }
984 
986 {
987  return mFlags.testFlag( f );
988 }
989 
991 {
992  static QIcon icon;
993 
994  if ( icon.isNull() )
995  icon = QgsApplication::getThemeIcon( "/mActionFolder.png" );
996 
997  return icon;
998 }
999 
1000 QList<QgsLayerTreeModelLegendNode*> QgsLayerTreeModel::filterLegendNodes( const QList<QgsLayerTreeModelLegendNode*>& nodes )
1001 {
1002  QList<QgsLayerTreeModelLegendNode*> filtered;
1003 
1004  if ( mLegendFilterByScale > 0 )
1005  {
1006  foreach ( QgsLayerTreeModelLegendNode* node, nodes )
1007  {
1008  if ( node->isScaleOK( mLegendFilterByScale ) )
1009  filtered << node;
1010  }
1011  }
1012  else if ( mLegendFilterByMapSettings )
1013  {
1014  foreach ( QgsLayerTreeModelLegendNode* node, nodes )
1015  {
1016  QgsSymbolV2* ruleKey = ( QgsSymbolV2* ) node->data( QgsSymbolV2LegendNode::SymbolV2LegacyRuleKeyRole ).value<void*>();
1017  if ( ruleKey )
1018  {
1019  if ( QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( node->layerNode()->layer() ) )
1020  {
1021  if ( mLegendFilterByMapHitTest->symbolsForLayer( vl ).contains( ruleKey ) )
1022  filtered << node;
1023  }
1024  }
1025  else // unknown node type
1026  filtered << node;
1027  }
1028  }
1029  else
1030  {
1031  return nodes;
1032  }
1033 
1034  return filtered;
1035 }
1036 
1037 
1038 
1040 // Legend nodes routines - start
1041 
1043 {
1044  foreach ( const LayerLegendData& data, mLegend )
1045  {
1046  qDeleteAll( data.originalNodes );
1047  delete data.tree;
1048  }
1049  mLegend.clear();
1050 }
1051 
1052 
1054 {
1055  if ( mLegend.contains( nodeLayer ) )
1056  {
1057  qDeleteAll( mLegend[nodeLayer].originalNodes );
1058  delete mLegend[nodeLayer].tree;
1059  mLegend.remove( nodeLayer );
1060  }
1061 }
1062 
1063 
1065 {
1066  if ( !nodeL->layer() )
1067  return;
1068 
1069  QgsMapLayerLegend* layerLegend = nodeL->layer()->legend();
1070  if ( !layerLegend )
1071  return;
1072 
1073  QList<QgsLayerTreeModelLegendNode*> lstNew = layerLegend->createLayerTreeModelLegendNodes( nodeL );
1074 
1075  // apply filtering defined in layer node's custom properties (reordering, filtering, custom labels)
1077 
1078  QList<QgsLayerTreeModelLegendNode*> filteredLstNew = filterLegendNodes( lstNew );
1079 
1080  bool isEmbedded = filteredLstNew.count() == 1 && filteredLstNew[0]->isEmbeddedInParent();
1081 
1082  foreach ( QgsLayerTreeModelLegendNode* n, lstNew )
1083  {
1084  n->setParent( this );
1085  connect( n, SIGNAL( dataChanged() ), this, SLOT( legendNodeDataChanged() ) );
1086  }
1087 
1089  data.originalNodes = lstNew;
1090  data.activeNodes = filteredLstNew;
1091  data.tree = 0;
1092 
1093  // maybe the legend nodes form a tree - try to create a tree structure from the list
1094  if ( testFlag( ShowLegendAsTree ) )
1095  tryBuildLegendTree( data );
1096 
1097  int count = data.tree ? data.tree->children[0].count() : filteredLstNew.count();
1098 
1099  if ( ! isEmbedded ) beginInsertRows( node2index( nodeL ), 0, count - 1 );
1100 
1101  mLegend[nodeL] = data;
1102 
1103  if ( ! isEmbedded ) endInsertRows();
1104 }
1105 
1106 
1108 {
1109  // first check whether there are any legend nodes that are not top-level
1110  bool hasParentKeys = false;
1111  foreach ( QgsLayerTreeModelLegendNode* n, data.activeNodes )
1112  {
1113  if ( !n->data( QgsLayerTreeModelLegendNode::ParentRuleKeyRole ).toString().isEmpty() )
1114  {
1115  hasParentKeys = true;
1116  break;
1117  }
1118  }
1119  if ( !hasParentKeys )
1120  return; // all legend nodes are top-level => stick with list representation
1121 
1122  // make mapping from rules to nodes and do some sanity checks
1123  QHash<QString, QgsLayerTreeModelLegendNode*> rule2node;
1124  rule2node[QString()] = 0;
1125  foreach ( QgsLayerTreeModelLegendNode* n, data.activeNodes )
1126  {
1127  QString ruleKey = n->data( QgsLayerTreeModelLegendNode::RuleKeyRole ).toString();
1128  if ( ruleKey.isEmpty() ) // in tree all nodes must have key
1129  return;
1130  if ( rule2node.contains( ruleKey ) ) // and they must be unique
1131  return;
1132  rule2node[ruleKey] = n;
1133  }
1134 
1135  // create the tree structure
1136  data.tree = new LayerLegendTree;
1137  foreach ( QgsLayerTreeModelLegendNode* n, data.activeNodes )
1138  {
1139  QString parentRuleKey = n->data( QgsLayerTreeModelLegendNode::ParentRuleKeyRole ).toString();
1140  QgsLayerTreeModelLegendNode* parent = rule2node.value( parentRuleKey, 0 );
1141  data.tree->parents[n] = parent;
1142  data.tree->children[parent] << n;
1143  }
1144 }
1145 
1146 
1148 {
1149  return qobject_cast<QgsLayerTreeModelLegendNode*>( reinterpret_cast<QObject*>( index.internalPointer() ) );
1150 }
1151 
1152 
1154 {
1155  const LayerLegendData& data = mLegend[legendNode->layerNode()];
1156  if ( data.tree )
1157  {
1158  if ( QgsLayerTreeModelLegendNode* parentLegendNode = data.tree->parents[legendNode] )
1159  {
1160  QModelIndex parentIndex = legendNode2index( parentLegendNode );
1161  int row = data.tree->children[parentLegendNode].indexOf( legendNode );
1162  return index( row, 0, parentIndex );
1163  }
1164  else
1165  {
1166  QModelIndex parentIndex = node2index( legendNode->layerNode() );
1167  int row = data.tree->children[0].indexOf( legendNode );
1168  return index( row, 0, parentIndex );
1169  }
1170  }
1171 
1172  QModelIndex parentIndex = node2index( legendNode->layerNode() );
1173  Q_ASSERT( parentIndex.isValid() );
1174  int row = data.activeNodes.indexOf( legendNode );
1175  if ( row < 0 ) // legend node may be filtered (exists within the list of original nodes, but not in active nodes)
1176  return QModelIndex();
1177  return index( row, 0, parentIndex );
1178 }
1179 
1180 
1182 {
1183  const LayerLegendData& data = mLegend[node->layerNode()];
1184  if ( data.tree )
1185  return data.tree->children[node].count();
1186 
1187  return 0; // they are leaves
1188 }
1189 
1190 
1192 {
1193  if ( legendEmbeddedInParent( nL ) )
1194  return 0;
1195 
1196  if ( !mLegend.contains( nL ) )
1197  return 0;
1198 
1199  const LayerLegendData& data = mLegend[nL];
1200  if ( data.tree )
1201  return data.tree->children[0].count();
1202 
1203  return data.activeNodes.count();
1204 }
1205 
1206 
1207 QModelIndex QgsLayerTreeModel::legendRootIndex( int row, int column, QgsLayerTreeLayer* nL ) const
1208 {
1209  Q_ASSERT( mLegend.contains( nL ) );
1210  const LayerLegendData& data = mLegend[nL];
1211  if ( data.tree )
1212  return createIndex( row, column, static_cast<QObject*>( data.tree->children[0].at( row ) ) );
1213 
1214  return createIndex( row, column, static_cast<QObject*>( data.activeNodes.at( row ) ) );
1215 }
1216 
1217 
1218 QModelIndex QgsLayerTreeModel::legendNodeIndex( int row, int column, QgsLayerTreeModelLegendNode* node ) const
1219 {
1220  const LayerLegendData& data = mLegend[node->layerNode()];
1221  if ( data.tree )
1222  return createIndex( row, column, static_cast<QObject*>( data.tree->children[node].at( row ) ) );
1223 
1224  return QModelIndex(); // have no children
1225 }
1226 
1227 
1229 {
1230  QgsLayerTreeLayer* layerNode = legendNode->layerNode();
1231  const LayerLegendData& data = mLegend[layerNode];
1232  if ( data.tree )
1233  {
1234  if ( QgsLayerTreeModelLegendNode* parentNode = data.tree->parents[legendNode] )
1235  {
1236  QgsLayerTreeModelLegendNode* grandParentNode = data.tree->parents[parentNode]; // may be null (not a problem)
1237  int row = data.tree->children[grandParentNode].indexOf( parentNode );
1238  return createIndex( row, 0, static_cast<QObject*>( parentNode ) );
1239  }
1240  else
1241  return indexOfParentLayerTreeNode( layerNode );
1242  }
1243 
1244  return indexOfParentLayerTreeNode( layerNode );
1245 }
1246 
1247 
1249 {
1250  if ( role == Qt::CheckStateRole && !testFlag( AllowLegendChangeState ) )
1251  return QVariant();
1252  return node->data( role );
1253 }
1254 
1255 
1257 {
1258  Qt::ItemFlags f = node->flags();
1259  if ( !testFlag( AllowLegendChangeState ) )
1260  f &= ~Qt::ItemIsUserCheckable;
1261  return f;
1262 }
1263 
1264 
1266 {
1267  const LayerLegendData& data = mLegend[nodeLayer];
1268  return data.activeNodes.count() == 1 && data.activeNodes[0]->isEmbeddedInParent();
1269 }
1270 
1271 
1273 {
1274  return QIcon( qvariant_cast<QPixmap>( mLegend[nodeLayer].activeNodes[0]->data( Qt::DecorationRole ) ) );
1275 }
1276 
1277 
1278 QList<QgsLayerTreeModelLegendNode*> QgsLayerTreeModel::layerLegendNodes( QgsLayerTreeLayer* nodeLayer )
1279 {
1280  return mLegend.value( nodeLayer ).activeNodes;
1281 }
1282 
1284 {
1285  foreach ( const LayerLegendData& data, mLegend )
1286  {
1287  foreach ( QgsLayerTreeModelLegendNode* legendNode, data.originalNodes )
1288  legendNode->invalidateMapBasedData();
1289  }
1290 }
1291 
1292 // 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.