QGIS API Documentation  2.10.1-Pisa
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups 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"
28 #include "qgspluginlayer.h"
29 #include "qgsrasterlayer.h"
30 #include "qgsrendererv2.h"
31 #include "qgssymbollayerv2utils.h"
32 #include "qgsvectorlayer.h"
33 
34 
36  : QAbstractItemModel( parent )
37  , mRootNode( rootNode )
38  , mFlags( ShowLegend | AllowLegendChangeState )
39  , mAutoCollapseLegendNodesCount( -1 )
40  , mLegendFilterByScale( 0 )
41  , mLegendMapViewMupp( 0 )
42  , mLegendMapViewDpi( 0 )
43  , mLegendMapViewScale( 0 )
44 {
46 
47  mFontLayer.setBold( true );
48 }
49 
51 {
52  legendCleanup();
53 }
54 
56 {
57  if ( !index.isValid() )
58  return mRootNode;
59 
60  QObject* obj = reinterpret_cast<QObject*>( index.internalPointer() );
61  return qobject_cast<QgsLayerTreeNode*>( obj );
62 }
63 
64 
65 int QgsLayerTreeModel::rowCount( const QModelIndex &parent ) const
66 {
67  if ( QgsLayerTreeModelLegendNode* nodeLegend = index2legendNode( parent ) )
68  return legendNodeRowCount( nodeLegend );
69 
70  QgsLayerTreeNode* n = index2node( parent );
71  if ( !n )
72  return 0;
73 
74  if ( QgsLayerTree::isLayer( n ) )
75  {
76  if ( !testFlag( ShowLegend ) )
77  return 0;
78 
80  }
81 
82  return n->children().count();
83 }
84 
85 int QgsLayerTreeModel::columnCount( const QModelIndex &parent ) const
86 {
87  Q_UNUSED( parent );
88  return 1;
89 }
90 
91 QModelIndex QgsLayerTreeModel::index( int row, int column, const QModelIndex &parent ) const
92 {
93  if ( column < 0 || column >= columnCount( parent ) ||
94  row < 0 || row >= rowCount( parent ) )
95  return QModelIndex();
96 
97  if ( QgsLayerTreeModelLegendNode* nodeLegend = index2legendNode( parent ) )
98  return legendNodeIndex( row, column, nodeLegend );
99 
100  QgsLayerTreeNode *n = index2node( parent );
101  if ( !n )
102  return QModelIndex(); // have no children
103 
104  if ( testFlag( ShowLegend ) && QgsLayerTree::isLayer( n ) )
105  {
106  return legendRootIndex( row, column, QgsLayerTree::toLayer( n ) );
107  }
108 
109  return createIndex( row, column, static_cast<QObject*>( n->children().at( row ) ) );
110 }
111 
112 
114 {
115  if ( !child.isValid() )
116  return QModelIndex();
117 
118  if ( QgsLayerTreeNode *n = index2node( child ) )
119  {
120  return indexOfParentLayerTreeNode( n->parent() ); // must not be null
121  }
122  else if ( QgsLayerTreeModelLegendNode* legendNode = index2legendNode( child ) )
123  {
124  return legendParent( legendNode );
125  }
126  else
127  {
128  Q_ASSERT( false ); // no other node types!
129  return QModelIndex();
130  }
131 
132 }
133 
134 
136 {
137  Q_ASSERT( parentNode );
138 
139  QgsLayerTreeNode* grandParentNode = parentNode->parent();
140  if ( !grandParentNode )
141  return QModelIndex(); // root node -> invalid index
142 
143  int row = grandParentNode->children().indexOf( parentNode );
144  Q_ASSERT( row >= 0 );
145 
146  return createIndex( row, 0, static_cast<QObject*>( parentNode ) );
147 }
148 
149 
151 {
152  if ( !index.isValid() || index.column() > 1 )
153  return QVariant();
154 
155  if ( QgsLayerTreeModelLegendNode* sym = index2legendNode( index ) )
156  return legendNodeData( sym, role );
157 
158  QgsLayerTreeNode* node = index2node( index );
159  if ( role == Qt::DisplayRole || role == Qt::EditRole )
160  {
161  if ( QgsLayerTree::isGroup( node ) )
162  return QgsLayerTree::toGroup( node )->name();
163 
164  if ( QgsLayerTree::isLayer( node ) )
165  {
166  QgsLayerTreeLayer* nodeLayer = QgsLayerTree::toLayer( node );
167  QString name = nodeLayer->layerName();
168  if ( nodeLayer->customProperty( "showFeatureCount", 0 ).toInt() && role == Qt::DisplayRole )
169  {
170  QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer*>( nodeLayer->layer() );
171  if ( vlayer && vlayer->pendingFeatureCount() >= 0 )
172  name += QString( " [%1]" ).arg( vlayer->pendingFeatureCount() );
173  }
174  return name;
175  }
176  }
177  else if ( role == Qt::DecorationRole && index.column() == 0 )
178  {
179  if ( QgsLayerTree::isGroup( node ) )
180  return iconGroup();
181 
182  if ( QgsLayerTree::isLayer( node ) )
183  {
184  QgsLayerTreeLayer *nodeLayer = QgsLayerTree::toLayer( node );
185 
186  QgsMapLayer *layer = nodeLayer->layer();
187  if ( !layer )
188  return QVariant();
189 
190  // icons possibly overriding default icon
191  if ( layer->type() == QgsMapLayer::RasterLayer )
192  {
194  {
195  QgsRasterLayer* rlayer = qobject_cast<QgsRasterLayer *>( layer );
196  return QIcon( QPixmap::fromImage( rlayer->previewAsImage( QSize( 32, 32 ) ) ) );
197  }
198  else
199  {
200  return QgsLayerItem::iconRaster();
201  }
202  }
203 
204  QgsVectorLayer *vlayer = dynamic_cast<QgsVectorLayer*>( layer );
205  QIcon icon;
206 
207  // if there's just on legend entry that should be embedded in layer - do that!
208  if ( testFlag( ShowLegend ) && legendEmbeddedInParent( nodeLayer ) )
209  {
210  icon = legendIconEmbeddedInParent( nodeLayer );
211  }
212  else if ( vlayer && layer->type() == QgsMapLayer::VectorLayer )
213  {
214  if ( vlayer->geometryType() == QGis::Point )
215  icon = QgsLayerItem::iconPoint();
216  else if ( vlayer->geometryType() == QGis::Line )
217  icon = QgsLayerItem::iconLine();
218  else if ( vlayer->geometryType() == QGis::Polygon )
219  icon = QgsLayerItem::iconPolygon();
220  else if ( vlayer->geometryType() == QGis::NoGeometry )
221  icon = QgsLayerItem::iconTable();
222  else
223  icon = QgsLayerItem::iconDefault();
224  }
225 
226  if ( vlayer && vlayer->isEditable() )
227  {
228  QPixmap pixmap( icon.pixmap( 16, 16 ) );
229 
230  QPainter painter( &pixmap );
231  painter.drawPixmap( 0, 0, 16, 16, QgsApplication::getThemePixmap( vlayer->isModified() ? "/mIconEditableEdits.png" : "/mIconEditable.png" ) );
232  painter.end();
233 
234  icon = QIcon( pixmap );
235  }
236 
237  return icon;
238  }
239  }
240  else if ( role == Qt::CheckStateRole )
241  {
243  return QVariant();
244 
245  if ( QgsLayerTree::isLayer( node ) )
246  {
247  QgsLayerTreeLayer* nodeLayer = QgsLayerTree::toLayer( node );
248  if ( nodeLayer->layer() && nodeLayer->layer()->type() == QgsMapLayer::VectorLayer )
249  {
250  if ( qobject_cast<QgsVectorLayer*>( nodeLayer->layer() )->geometryType() == QGis::NoGeometry )
251  return QVariant(); // do not show checkbox for non-spatial tables
252  }
253  return nodeLayer->isVisible();
254  }
255  else if ( QgsLayerTree::isGroup( node ) )
256  {
257  QgsLayerTreeGroup* nodeGroup = QgsLayerTree::toGroup( node );
258  return nodeGroup->isVisible();
259  }
260  }
261  else if ( role == Qt::FontRole )
262  {
263  QFont f( QgsLayerTree::isLayer( node ) ? mFontLayer : ( QgsLayerTree::isGroup( node ) ? mFontGroup : QFont() ) );
264  if ( node->customProperty( "embedded" ).toInt() )
265  f.setItalic( true );
266  if ( index == mCurrentIndex )
267  f.setUnderline( true );
268  return f;
269  }
270  else if ( role == Qt::ToolTipRole )
271  {
272  if ( QgsLayerTree::isLayer( node ) )
273  {
274  if ( QgsMapLayer* layer = QgsLayerTree::toLayer( node )->layer() )
275  return layer->publicSource();
276  }
277  }
278 
279  return QVariant();
280 }
281 
282 
284 {
285  if ( !index.isValid() )
286  {
287  Qt::ItemFlags rootFlags = 0;
288  if ( testFlag( AllowNodeReorder ) )
289  rootFlags |= Qt::ItemIsDropEnabled;
290  return rootFlags;
291  }
292 
293  if ( QgsLayerTreeModelLegendNode* symn = index2legendNode( index ) )
294  return legendNodeFlags( symn );
295 
296  Qt::ItemFlags f = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
297 
298  if ( testFlag( AllowNodeRename ) )
299  f |= Qt::ItemIsEditable;
300 
301  QgsLayerTreeNode* node = index2node( index );
302  bool isEmbedded = node->customProperty( "embedded" ).toInt();
303 
304  if ( testFlag( AllowNodeReorder ) )
305  {
306  // only root embedded nodes can be reordered
307  if ( !isEmbedded || ( isEmbedded && node->parent() && !node->parent()->customProperty( "embedded" ).toInt() ) )
308  f |= Qt::ItemIsDragEnabled;
309  }
310 
312  f |= Qt::ItemIsUserCheckable;
313 
314  if ( testFlag( AllowNodeReorder ) && QgsLayerTree::isGroup( node ) && !isEmbedded )
315  f |= Qt::ItemIsDropEnabled;
316 
317  return f;
318 }
319 
320 bool QgsLayerTreeModel::setData( const QModelIndex& index, const QVariant& value, int role )
321 {
323  if ( sym )
324  {
325  if ( role == Qt::CheckStateRole && !testFlag( AllowLegendChangeState ) )
326  return false;
327  bool res = sym->setData( value, role );
328  if ( res )
329  emit dataChanged( index, index );
330  return res;
331  }
332 
333  QgsLayerTreeNode* node = index2node( index );
334  if ( !node )
335  return QgsLayerTreeModel::setData( index, value, role );
336 
337  if ( role == Qt::CheckStateRole )
338  {
340  return false;
341 
342  if ( QgsLayerTree::isLayer( node ) )
343  {
344  QgsLayerTreeLayer* layer = QgsLayerTree::toLayer( node );
345  layer->setVisible(( Qt::CheckState )value.toInt() );
346  return true;
347  }
348 
349  if ( QgsLayerTree::isGroup( node ) )
350  {
351  QgsLayerTreeGroup* group = QgsLayerTree::toGroup( node );
352  group->setVisible(( Qt::CheckState )value.toInt() );
353  return true;
354  }
355 
356  return true;
357  }
358  else if ( role == Qt::EditRole )
359  {
360  if ( !testFlag( AllowNodeRename ) )
361  return false;
362 
363  if ( QgsLayerTree::isLayer( node ) )
364  {
365  QgsLayerTreeLayer* layer = QgsLayerTree::toLayer( node );
366  layer->setLayerName( value.toString() );
367  emit dataChanged( index, index );
368  }
369  else if ( QgsLayerTree::isGroup( node ) )
370  {
371  QgsLayerTree::toGroup( node )->setName( value.toString() );
372  emit dataChanged( index, index );
373  }
374  }
375 
376  return QAbstractItemModel::setData( index, value, role );
377 }
378 
380 {
381  if ( !node->parent() )
382  return QModelIndex(); // this is the only root item -> invalid index
383 
384  QModelIndex parentIndex = node2index( node->parent() );
385 
386  int row = node->parent()->children().indexOf( node );
387  Q_ASSERT( row >= 0 );
388  return index( row, 0, parentIndex );
389 }
390 
391 
393 {
394  if ( !child->parent() )
395  return false;
396 
397  if ( child->parent() == node )
398  return true;
399 
400  return _isChildOfNode( child->parent(), node );
401 }
402 
404 {
405  foreach ( QgsLayerTreeNode* n, nodes )
406  {
407  if ( _isChildOfNode( child, n ) )
408  return true;
409  }
410 
411  return false;
412 }
413 
414 
415 QList<QgsLayerTreeNode*> QgsLayerTreeModel::indexes2nodes( const QModelIndexList& list, bool skipInternal ) const
416 {
418  foreach ( QModelIndex index, list )
419  {
420  QgsLayerTreeNode* node = index2node( index );
421  if ( !node )
422  continue;
423 
424  nodes << node;
425  }
426 
427  if ( !skipInternal )
428  return nodes;
429 
430  // remove any children of nodes if both parent node and children are selected
431  QList<QgsLayerTreeNode*> nodesFinal;
432  foreach ( QgsLayerTreeNode* node, nodes )
433  {
434  if ( !_isChildOfNodes( node, nodes ) )
435  nodesFinal << node;
436  }
437 
438  return nodesFinal;
439 }
440 
442 {
443  return index2legendNode( index ) != 0;
444 }
445 
447 {
448  QgsLayerTreeModelLegendNode* symNode = index2legendNode( index );
449  return symNode ? symNode->layerNode() : 0;
450 }
451 
453 {
454  return mRootNode;
455 }
456 
458 {
459  beginResetModel();
460 
462 
463  Q_ASSERT( mLegend.isEmpty() );
464 
465  mRootNode = newRootGroup;
466 
467  endResetModel();
468 
470 }
471 
473 {
474  // update title
475  QModelIndex idx = node2index( nodeLayer );
476  emit dataChanged( idx, idx );
477 
478  // update children
479  int oldNodeCount = rowCount( idx );
480  beginRemoveRows( idx, 0, oldNodeCount - 1 );
481  removeLegendFromLayer( nodeLayer );
482  endRemoveRows();
483 
484  addLegendToLayer( nodeLayer );
485  int newNodeCount = rowCount( idx );
486 
487  // automatic collapse of legend nodes - useful if a layer has many legend nodes
488  if ( mAutoCollapseLegendNodesCount != -1 && oldNodeCount != newNodeCount && newNodeCount >= mAutoCollapseLegendNodesCount )
489  nodeLayer->setExpanded( false );
490 }
491 
493 {
494  return mCurrentIndex;
495 }
496 
498 {
499  QModelIndex oldIndex = mCurrentIndex;
501 
502  if ( oldIndex.isValid() )
503  emit dataChanged( oldIndex, oldIndex );
504  if ( currentIndex.isValid() )
505  emit dataChanged( currentIndex, currentIndex );
506 }
507 
508 
509 void QgsLayerTreeModel::setLayerTreeNodeFont( int nodeType, const QFont& font )
510 {
511  if ( nodeType == QgsLayerTreeNode::NodeGroup )
512  {
513  if ( mFontGroup != font )
514  {
515  mFontGroup = font;
517  }
518  }
519  else if ( nodeType == QgsLayerTreeNode::NodeLayer )
520  {
521  if ( mFontLayer != font )
522  {
523  mFontLayer = font;
525  }
526  }
527  else
528  {
529  QgsDebugMsg( "invalid node type" );
530  }
531 }
532 
533 
535 {
536  if ( nodeType == QgsLayerTreeNode::NodeGroup )
537  return mFontGroup;
538  else if ( nodeType == QgsLayerTreeNode::NodeLayer )
539  return mFontLayer;
540  else
541  {
542  QgsDebugMsg( "invalid node type" );
543  return QFont();
544  }
545 }
546 
547 void QgsLayerTreeModel::setLegendFilterByScale( double scaleDenominator )
548 {
549  mLegendFilterByScale = scaleDenominator;
550 
551  // this could be later done in more efficient way
552  // by just updating active legend nodes, without refreshing original legend nodes
553  foreach ( QgsLayerTreeLayer* nodeLayer, mRootNode->findLayers() )
554  refreshLayerLegend( nodeLayer );
555 }
556 
558 {
559  if ( settings && settings->hasValidSettings() )
560  {
561  mLegendFilterByMapSettings.reset( new QgsMapSettings( *settings ) );
564  }
565  else
566  {
568  return; // no change
569 
572  }
573 
574  // temporarily disable autocollapse so that legend nodes stay visible
575  int bkAutoCollapse = autoCollapseLegendNodes();
577 
578  // this could be later done in more efficient way
579  // by just updating active legend nodes, without refreshing original legend nodes
580  foreach ( QgsLayerTreeLayer* nodeLayer, mRootNode->findLayers() )
581  refreshLayerLegend( nodeLayer );
582 
583  setAutoCollapseLegendNodes( bkAutoCollapse );
584 }
585 
586 void QgsLayerTreeModel::setLegendMapViewData( double mapUnitsPerPixel, int dpi, double scale )
587 {
588  if ( mLegendMapViewDpi == dpi && mLegendMapViewMupp == mapUnitsPerPixel && mLegendMapViewScale == scale )
589  return;
590 
591  mLegendMapViewMupp = mapUnitsPerPixel;
592  mLegendMapViewDpi = dpi;
593  mLegendMapViewScale = scale;
594 
595  // now invalidate legend nodes!
597 }
598 
599 void QgsLayerTreeModel::legendMapViewData( double* mapUnitsPerPixel, int* dpi, double* scale )
600 {
601  if ( mapUnitsPerPixel ) *mapUnitsPerPixel = mLegendMapViewMupp;
602  if ( dpi ) *dpi = mLegendMapViewDpi;
603  if ( scale ) *scale = mLegendMapViewScale;
604 }
605 
607 {
608  return mLayerStyleOverrides;
609 }
610 
612 {
613  mLayerStyleOverrides = overrides;
614 }
615 
616 void QgsLayerTreeModel::nodeWillAddChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo )
617 {
618  Q_ASSERT( node );
619  beginInsertRows( node2index( node ), indexFrom, indexTo );
620 }
621 
622 static QList<QgsLayerTreeLayer*> _layerNodesInSubtree( QgsLayerTreeNode* node, int indexFrom, int indexTo )
623 {
624  QList<QgsLayerTreeNode*> children = node->children();
625  QList<QgsLayerTreeLayer*> newLayerNodes;
626  for ( int i = indexFrom; i <= indexTo; ++i )
627  {
628  QgsLayerTreeNode* child = children.at( i );
629  if ( QgsLayerTree::isLayer( child ) )
630  newLayerNodes << QgsLayerTree::toLayer( child );
631  else if ( QgsLayerTree::isGroup( child ) )
632  newLayerNodes << QgsLayerTree::toGroup( child )->findLayers();
633  }
634  return newLayerNodes;
635 }
636 
637 void QgsLayerTreeModel::nodeAddedChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo )
638 {
639  Q_ASSERT( node );
640 
641  endInsertRows();
642 
643  foreach ( QgsLayerTreeLayer* newLayerNode, _layerNodesInSubtree( node, indexFrom, indexTo ) )
644  connectToLayer( newLayerNode );
645 }
646 
647 void QgsLayerTreeModel::nodeWillRemoveChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo )
648 {
649  Q_ASSERT( node );
650 
651  beginRemoveRows( node2index( node ), indexFrom, indexTo );
652 
653  // disconnect from layers and remove their legend
654  foreach ( QgsLayerTreeLayer* nodeLayer, _layerNodesInSubtree( node, indexFrom, indexTo ) )
655  disconnectFromLayer( nodeLayer );
656 }
657 
659 {
660  endRemoveRows();
661 }
662 
664 {
665  Q_ASSERT( node );
666 
667  QModelIndex index = node2index( node );
668  emit dataChanged( index, index );
669 }
670 
671 
673 {
674  if ( QgsLayerTree::isLayer( node ) && key == "showFeatureCount" )
676 }
677 
678 
680 {
681  QgsLayerTreeLayer* nodeLayer = qobject_cast<QgsLayerTreeLayer*>( sender() );
682  if ( !nodeLayer )
683  return;
684 
685  // deffered connection to the layer
686  connectToLayer( nodeLayer );
687 }
688 
690 {
691  QgsLayerTreeLayer* nodeLayer = qobject_cast<QgsLayerTreeLayer*>( sender() );
692  if ( !nodeLayer )
693  return;
694 
695  disconnectFromLayer( nodeLayer );
696 
697  // wait for the layer to appear again
698  connect( nodeLayer, SIGNAL( layerLoaded() ), this, SLOT( nodeLayerLoaded() ) );
699 }
700 
702 {
703  if ( !testFlag( ShowLegend ) )
704  return;
705 
706  QgsMapLayer* layer = qobject_cast<QgsMapLayer*>( sender() );
707  if ( !layer )
708  return;
709 
710  QgsLayerTreeLayer* nodeLayer = mRootNode->findLayer( layer->id() );
711  if ( !nodeLayer )
712  return;
713 
714  refreshLayerLegend( nodeLayer );
715 }
716 
718 {
719  QgsMapLayer* layer = qobject_cast<QgsMapLayer*>( sender() );
720  if ( !layer )
721  return;
722 
723  QgsLayerTreeLayer* nodeLayer = mRootNode->findLayer( layer->id() );
724  if ( !nodeLayer )
725  return;
726 
727  QModelIndex index = node2index( nodeLayer );
728  emit dataChanged( index, index );
729 
730  if ( nodeLayer->customProperty( "showFeatureCount" ).toInt() )
731  refreshLayerLegend( nodeLayer );
732 }
733 
734 
736 {
737  QgsLayerTreeModelLegendNode* legendNode = qobject_cast<QgsLayerTreeModelLegendNode*>( sender() );
738  if ( !legendNode )
739  return;
740 
741  QModelIndex index = legendNode2index( legendNode );
742  if ( index.isValid() )
743  emit dataChanged( index, index );
744 }
745 
746 
748 {
749  if ( !nodeLayer->layer() )
750  {
751  // in order to connect to layer, we need to have it loaded.
752  // keep an eye on the layer ID: once loaded, we will use it
753  connect( nodeLayer, SIGNAL( layerLoaded() ), this, SLOT( nodeLayerLoaded() ) );
754  return;
755  }
756 
757  // watch if the layer is getting removed
758  connect( nodeLayer, SIGNAL( layerWillBeUnloaded() ), this, SLOT( nodeLayerWillBeUnloaded() ) );
759 
760  if ( testFlag( ShowLegend ) )
761  {
762  addLegendToLayer( nodeLayer );
763 
764  // automatic collapse of legend nodes - useful if a layer has many legend nodes
765  if ( !mRootNode->customProperty( "loading" ).toBool() )
766  {
768  nodeLayer->setExpanded( false );
769  }
770  }
771 
772  QgsMapLayer* layer = nodeLayer->layer();
773  connect( layer, SIGNAL( legendChanged() ), this, SLOT( layerLegendChanged() ), Qt::UniqueConnection );
774 
775  if ( layer->type() == QgsMapLayer::VectorLayer )
776  {
777  // using unique connection because there may be temporarily more nodes for a layer than just one
778  // which would create multiple connections, however disconnect() would disconnect all multiple connections
779  // even if we wanted to disconnect just one connection in each call.
780  connect( layer, SIGNAL( editingStarted() ), this, SLOT( layerNeedsUpdate() ), Qt::UniqueConnection );
781  connect( layer, SIGNAL( editingStopped() ), this, SLOT( layerNeedsUpdate() ), Qt::UniqueConnection );
782  connect( layer, SIGNAL( layerModified() ), this, SLOT( layerNeedsUpdate() ), Qt::UniqueConnection );
783  connect( layer, SIGNAL( layerNameChanged() ), this, SLOT( layerNeedsUpdate() ), Qt::UniqueConnection );
784  }
785 }
786 
787 // try to find out if the layer ID is present in the tree multiple times
788 static int _numLayerCount( QgsLayerTreeGroup* group, const QString& layerId )
789 {
790  int count = 0;
791  foreach ( QgsLayerTreeNode* child, group->children() )
792  {
793  if ( QgsLayerTree::isLayer( child ) )
794  {
795  if ( QgsLayerTree::toLayer( child )->layerId() == layerId )
796  count++;
797  }
798  else if ( QgsLayerTree::isGroup( child ) )
799  {
800  count += _numLayerCount( QgsLayerTree::toGroup( child ), layerId );
801  }
802  }
803  return count;
804 }
805 
807 {
808  disconnect( nodeLayer, 0, this, 0 ); // disconnect from delayed load of layer
809 
810  if ( !nodeLayer->layer() )
811  return; // we were never connected
812 
813  if ( testFlag( ShowLegend ) )
814  {
815  removeLegendFromLayer( nodeLayer );
816  }
817 
818  if ( _numLayerCount( mRootNode, nodeLayer->layerId() ) == 1 )
819  {
820  // last instance of the layer in the tree: disconnect from all signals from layer!
821  disconnect( nodeLayer->layer(), 0, this, 0 );
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  foreach ( QgsLayerTreeNode* node, parentGroup->children() )
839  {
840  if ( QgsLayerTree::isGroup( node ) )
842  else if ( QgsLayerTree::isLayer( node ) )
844  }
845 }
846 
848 {
849  Q_ASSERT( mRootNode );
850 
851  connect( mRootNode, SIGNAL( willAddChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeWillAddChildren( QgsLayerTreeNode*, int, int ) ) );
852  connect( mRootNode, SIGNAL( addedChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeAddedChildren( QgsLayerTreeNode*, int, int ) ) );
853  connect( mRootNode, SIGNAL( willRemoveChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeWillRemoveChildren( QgsLayerTreeNode*, int, int ) ) );
854  connect( mRootNode, SIGNAL( removedChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeRemovedChildren() ) );
855  connect( mRootNode, SIGNAL( visibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ), this, SLOT( nodeVisibilityChanged( QgsLayerTreeNode* ) ) );
856 
857  connect( mRootNode, SIGNAL( customPropertyChanged( QgsLayerTreeNode*, QString ) ), this, SLOT( nodeCustomPropertyChanged( QgsLayerTreeNode*, QString ) ) );
858 
860 }
861 
863 {
864  disconnect( mRootNode, 0, this, 0 );
865 
867 }
868 
870 {
871  QgsLayerTreeNode* node = index2node( idx );
872  if ( !node )
873  return;
874 
875  int count = node->children().count();
876  if ( count == 0 )
877  return;
878  emit dataChanged( index( 0, 0, idx ), index( count - 1, 0, idx ) );
879  for ( int i = 0; i < count; ++i )
880  recursivelyEmitDataChanged( index( i, 0, idx ) );
881 }
882 
883 
885 {
886  return Qt::MoveAction;
887 }
888 
890 {
891  QStringList types;
892  types << "application/qgis.layertreemodeldata";
893  return types;
894 }
895 
896 
897 QMimeData* QgsLayerTreeModel::mimeData( const QModelIndexList& indexes ) const
898 {
899  QList<QgsLayerTreeNode*> nodesFinal = indexes2nodes( indexes, true );
900 
901  if ( nodesFinal.count() == 0 )
902  return 0;
903 
904  QMimeData *mimeData = new QMimeData();
905 
906  QDomDocument doc;
907  QDomElement rootElem = doc.createElement( "layer_tree_model_data" );
908  foreach ( QgsLayerTreeNode* node, nodesFinal )
909  node->writeXML( rootElem );
910  doc.appendChild( rootElem );
911  QString txt = doc.toString();
912 
913  mimeData->setData( "application/qgis.layertreemodeldata", txt.toUtf8() );
914  return mimeData;
915 }
916 
917 bool QgsLayerTreeModel::dropMimeData( const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent )
918 {
919  if ( action == Qt::IgnoreAction )
920  return true;
921 
922  if ( !data->hasFormat( "application/qgis.layertreemodeldata" ) )
923  return false;
924 
925  if ( column >= columnCount( parent ) )
926  return false;
927 
928  QgsLayerTreeNode* nodeParent = index2node( parent );
929  if ( !QgsLayerTree::isGroup( nodeParent ) )
930  return false;
931 
932  QByteArray encodedData = data->data( "application/qgis.layertreemodeldata" );
933 
934  QDomDocument doc;
935  if ( !doc.setContent( QString::fromUtf8( encodedData ) ) )
936  return false;
937 
938  QDomElement rootElem = doc.documentElement();
939  if ( rootElem.tagName() != "layer_tree_model_data" )
940  return false;
941 
943 
944  QDomElement elem = rootElem.firstChildElement();
945  while ( !elem.isNull() )
946  {
948  if ( node )
949  nodes << node;
950 
951  elem = elem.nextSiblingElement();
952  }
953 
954  if ( nodes.count() == 0 )
955  return false;
956 
957  if ( parent.isValid() && row == -1 )
958  row = 0; // if dropped directly onto group item, insert at first position
959 
960  QgsLayerTree::toGroup( nodeParent )->insertChildNodes( row, nodes );
961 
962  return true;
963 }
964 
965 bool QgsLayerTreeModel::removeRows( int row, int count, const QModelIndex& parent )
966 {
967  QgsLayerTreeNode* parentNode = index2node( parent );
968  if ( QgsLayerTree::isGroup( parentNode ) )
969  {
970  QgsLayerTree::toGroup( parentNode )->removeChildren( row, count );
971  return true;
972  }
973  return false;
974 }
975 
976 void QgsLayerTreeModel::setFlags( QgsLayerTreeModel::Flags f )
977 {
978  mFlags = f;
979 }
980 
982 {
983  if ( on )
984  mFlags |= f;
985  else
986  mFlags &= ~f;
987 }
988 
989 QgsLayerTreeModel::Flags QgsLayerTreeModel::flags() const
990 {
991  return mFlags;
992 }
993 
995 {
996  return mFlags.testFlag( f );
997 }
998 
1000 {
1001  static QIcon icon;
1002 
1003  if ( icon.isNull() )
1004  icon = QgsApplication::getThemeIcon( "/mActionFolder.png" );
1005 
1006  return icon;
1007 }
1008 
1010 {
1012 
1013  if ( mLegendFilterByScale > 0 )
1014  {
1015  foreach ( QgsLayerTreeModelLegendNode* node, nodes )
1016  {
1017  if ( node->isScaleOK( mLegendFilterByScale ) )
1018  filtered << node;
1019  }
1020  }
1021  else if ( mLegendFilterByMapSettings )
1022  {
1023  foreach ( QgsLayerTreeModelLegendNode* node, nodes )
1024  {
1026  if ( ruleKey )
1027  {
1028  if ( QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( node->layerNode()->layer() ) )
1029  {
1030  if ( mLegendFilterByMapHitTest->symbolsForLayer( vl ).contains( ruleKey ) )
1031  filtered << node;
1032  }
1033  }
1034  else // unknown node type
1035  filtered << node;
1036  }
1037  }
1038  else
1039  {
1040  return nodes;
1041  }
1042 
1043  return filtered;
1044 }
1045 
1046 
1047 
1049 // Legend nodes routines - start
1050 
1052 {
1053  foreach ( const LayerLegendData& data, mLegend )
1054  {
1055  qDeleteAll( data.originalNodes );
1056  delete data.tree;
1057  }
1058  mLegend.clear();
1059 }
1060 
1061 
1063 {
1064  if ( mLegend.contains( nodeLayer ) )
1065  {
1066  qDeleteAll( mLegend[nodeLayer].originalNodes );
1067  delete mLegend[nodeLayer].tree;
1068  mLegend.remove( nodeLayer );
1069  }
1070 }
1071 
1072 
1074 {
1075  if ( !nodeL->layer() )
1076  return;
1077 
1078  QgsMapLayer* ml = nodeL->layer();
1079  QgsMapLayerLegend* layerLegend = ml->legend();
1080  if ( !layerLegend )
1081  return;
1082 
1083  bool hasStyleOverride = mLayerStyleOverrides.contains( ml->id() );
1084  if ( hasStyleOverride )
1086 
1088 
1089  // apply filtering defined in layer node's custom properties (reordering, filtering, custom labels)
1091 
1092  QList<QgsLayerTreeModelLegendNode*> filteredLstNew = filterLegendNodes( lstNew );
1093 
1094  bool isEmbedded = filteredLstNew.count() == 1 && filteredLstNew[0]->isEmbeddedInParent();
1095 
1096  foreach ( QgsLayerTreeModelLegendNode* n, lstNew )
1097  {
1098  n->setParent( this );
1099  connect( n, SIGNAL( dataChanged() ), this, SLOT( legendNodeDataChanged() ) );
1100  }
1101 
1103  data.originalNodes = lstNew;
1104  data.activeNodes = filteredLstNew;
1105  data.tree = 0;
1106 
1107  // maybe the legend nodes form a tree - try to create a tree structure from the list
1108  if ( testFlag( ShowLegendAsTree ) )
1109  tryBuildLegendTree( data );
1110 
1111  int count = data.tree ? data.tree->children[0].count() : filteredLstNew.count();
1112 
1113  if ( ! isEmbedded ) beginInsertRows( node2index( nodeL ), 0, count - 1 );
1114 
1115  mLegend[nodeL] = data;
1116 
1117  if ( ! isEmbedded ) endInsertRows();
1118 
1119  if ( hasStyleOverride )
1121 }
1122 
1123 
1125 {
1126  // first check whether there are any legend nodes that are not top-level
1127  bool hasParentKeys = false;
1128  foreach ( QgsLayerTreeModelLegendNode* n, data.activeNodes )
1129  {
1131  {
1132  hasParentKeys = true;
1133  break;
1134  }
1135  }
1136  if ( !hasParentKeys )
1137  return; // all legend nodes are top-level => stick with list representation
1138 
1139  // make mapping from rules to nodes and do some sanity checks
1141  rule2node[QString()] = 0;
1142  foreach ( QgsLayerTreeModelLegendNode* n, data.activeNodes )
1143  {
1145  if ( ruleKey.isEmpty() ) // in tree all nodes must have key
1146  return;
1147  if ( rule2node.contains( ruleKey ) ) // and they must be unique
1148  return;
1149  rule2node[ruleKey] = n;
1150  }
1151 
1152  // create the tree structure
1153  data.tree = new LayerLegendTree;
1154  foreach ( QgsLayerTreeModelLegendNode* n, data.activeNodes )
1155  {
1157  QgsLayerTreeModelLegendNode* parent = rule2node.value( parentRuleKey, 0 );
1158  data.tree->parents[n] = parent;
1159  data.tree->children[parent] << n;
1160  }
1161 }
1162 
1163 
1165 {
1166  return qobject_cast<QgsLayerTreeModelLegendNode*>( reinterpret_cast<QObject*>( index.internalPointer() ) );
1167 }
1168 
1169 
1171 {
1172  const LayerLegendData& data = mLegend[legendNode->layerNode()];
1173  if ( data.tree )
1174  {
1175  if ( QgsLayerTreeModelLegendNode* parentLegendNode = data.tree->parents[legendNode] )
1176  {
1177  QModelIndex parentIndex = legendNode2index( parentLegendNode );
1178  int row = data.tree->children[parentLegendNode].indexOf( legendNode );
1179  return index( row, 0, parentIndex );
1180  }
1181  else
1182  {
1183  QModelIndex parentIndex = node2index( legendNode->layerNode() );
1184  int row = data.tree->children[0].indexOf( legendNode );
1185  return index( row, 0, parentIndex );
1186  }
1187  }
1188 
1189  QModelIndex parentIndex = node2index( legendNode->layerNode() );
1190  Q_ASSERT( parentIndex.isValid() );
1191  int row = data.activeNodes.indexOf( legendNode );
1192  if ( row < 0 ) // legend node may be filtered (exists within the list of original nodes, but not in active nodes)
1193  return QModelIndex();
1194  return index( row, 0, parentIndex );
1195 }
1196 
1197 
1199 {
1200  const LayerLegendData& data = mLegend[node->layerNode()];
1201  if ( data.tree )
1202  return data.tree->children[node].count();
1203 
1204  return 0; // they are leaves
1205 }
1206 
1207 
1209 {
1210  if ( legendEmbeddedInParent( nL ) )
1211  return 0;
1212 
1213  if ( !mLegend.contains( nL ) )
1214  return 0;
1215 
1216  const LayerLegendData& data = mLegend[nL];
1217  if ( data.tree )
1218  return data.tree->children[0].count();
1219 
1220  return data.activeNodes.count();
1221 }
1222 
1223 
1225 {
1226  Q_ASSERT( mLegend.contains( nL ) );
1227  const LayerLegendData& data = mLegend[nL];
1228  if ( data.tree )
1229  return createIndex( row, column, static_cast<QObject*>( data.tree->children[0].at( row ) ) );
1230 
1231  return createIndex( row, column, static_cast<QObject*>( data.activeNodes.at( row ) ) );
1232 }
1233 
1234 
1236 {
1237  const LayerLegendData& data = mLegend[node->layerNode()];
1238  if ( data.tree )
1239  return createIndex( row, column, static_cast<QObject*>( data.tree->children[node].at( row ) ) );
1240 
1241  return QModelIndex(); // have no children
1242 }
1243 
1244 
1246 {
1247  QgsLayerTreeLayer* layerNode = legendNode->layerNode();
1248  const LayerLegendData& data = mLegend[layerNode];
1249  if ( data.tree )
1250  {
1251  if ( QgsLayerTreeModelLegendNode* parentNode = data.tree->parents[legendNode] )
1252  {
1253  QgsLayerTreeModelLegendNode* grandParentNode = data.tree->parents[parentNode]; // may be null (not a problem)
1254  int row = data.tree->children[grandParentNode].indexOf( parentNode );
1255  return createIndex( row, 0, static_cast<QObject*>( parentNode ) );
1256  }
1257  else
1258  return indexOfParentLayerTreeNode( layerNode );
1259  }
1260 
1261  return indexOfParentLayerTreeNode( layerNode );
1262 }
1263 
1264 
1266 {
1267  if ( role == Qt::CheckStateRole && !testFlag( AllowLegendChangeState ) )
1268  return QVariant();
1269  return node->data( role );
1270 }
1271 
1272 
1274 {
1275  Qt::ItemFlags f = node->flags();
1276  if ( !testFlag( AllowLegendChangeState ) )
1277  f &= ~Qt::ItemIsUserCheckable;
1278  return f;
1279 }
1280 
1281 
1283 {
1284  const LayerLegendData& data = mLegend[nodeLayer];
1285  return data.activeNodes.count() == 1 && data.activeNodes[0]->isEmbeddedInParent();
1286 }
1287 
1288 
1290 {
1291  return QIcon( qvariant_cast<QPixmap>( mLegend[nodeLayer].activeNodes[0]->data( Qt::DecorationRole ) ) );
1292 }
1293 
1294 
1296 {
1297  return mLegend.value( nodeLayer ).activeNodes;
1298 }
1299 
1301 {
1302  foreach ( const LayerLegendData& data, mLegend )
1303  {
1304  foreach ( QgsLayerTreeModelLegendNode* legendNode, data.originalNodes )
1305  legendNode->invalidateMapBasedData();
1306  }
1307 }
1308 
1309 // Legend nodes routines - end
bool restoreOverrideStyle()
Restore the original store after a call to setOverrideStyle()
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.
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)
QByteArray data(const QString &mimeType) const
QgsMapLayer::LayerType type() const
Get the type of the layer.
Definition: qgsmaplayer.cpp:93
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.
bool contains(const Key &key) const
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.
QDomNode appendChild(const QDomNode &newChild)
static const QIcon & iconDefault()
void nodeCustomPropertyChanged(QgsLayerTreeNode *node, const QString &key)
void addLegendToLayer(QgsLayerTreeLayer *nodeL)
static const QIcon & iconPoint()
Definition: qgsdataitem.cpp:98
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.
virtual bool hasFormat(const QString &mimeType) const
QString toString(int indent) const
QObject * sender() const
QgsMapLayerStyleManager * styleManager() const
Get access to the layer's style manager.
static QIcon getThemeIcon(const QString &theName)
Helper to get a theme icon.
static int _numLayerCount(QgsLayerTreeGroup *group, const QString &layerId)
const T & at(int i) const
bool legendEmbeddedInParent(QgsLayerTreeLayer *nodeLayer) const
Structure that stores tree representation of map layer's legend.
void setUnderline(bool enable)
QDomElement nextSiblingElement(const QString &tagName) const
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.
T value() const
QPixmap fromImage(const QImage &image, QFlags< Qt::ImageConversionFlag > flags)
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.
QDomElement documentElement() const
static const QIcon & iconPolygon()
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
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
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)
QPixmap pixmap(const QSize &size, Mode mode, State state) const
void connectToLayers(QgsLayerTreeGroup *parentGroup)
void reset(T *other)
The QgsMapSettings class contains configuration for rendering of the map.
int indexOf(const T &value, int from) const
void setBold(bool enable)
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Allow renaming of groups and layers.
const char * name() const
QMap< QString, QString > layerStyleOverrides() const
Get map of map layer style overrides (key: layer ID, value: style name) where a different style shoul...
rule key of the parent legend node - for legends with tree hierarchy (QString). Added in 2...
bool isValid() const
Qt::CheckState isVisible() const
int count(const T &value) const
QString fromUtf8(const char *str, int size)
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...
int toInt(bool *ok) const
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
QModelIndex legendNode2index(QgsLayerTreeModelLegendNode *legendNode)
Return index for a given legend node.
static const QIcon & iconRaster()
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
bool isEmpty() const
void beginRemoveRows(const QModelIndex &parent, int first, int last)
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
QImage previewAsImage(QSize size, QColor bgColor=Qt::white, QImage::Format format=QImage::Format_ARGB32_Premultiplied)
Draws a preview of the rasterlayer into a QImage.
void * internalPointer() const
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:99
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) ...
QModelIndex createIndex(int row, int column, void *ptr) const
QPersistentModelIndex mCurrentIndex
Current index - will be underlined.
void setRootGroup(QgsLayerTreeGroup *newRootGroup)
Reset the model and use a new root group node.
const T value(const Key &key) const
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 setParent(QObject *parent)
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...
void setItalic(bool enable)
void beginInsertRows(const QModelIndex &parent, int first, int last)
QgsMapLayerLegend * legend() const
Can be null.
bool isNull() const
static const QIcon & iconTable()
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
typedef DropActions
bool isNull() const
QDomElement firstChildElement(const QString &tagName) const
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.
int column() const
static const QIcon & iconLine()
bool toBool() const
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...
virtual bool setData(const QModelIndex &index, const QVariant &value, int role)
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...
bool contains(const Key &key) const
QString tagName() const
bool setOverrideStyle(const QString &styleDef)
Temporarily apply a different style to the layer.
void setData(const QString &mimeType, const QByteArray &data)
void setLayerStyleOverrides(const QMap< QString, QString > &overrides)
Set map of map layer style overrides (key: layer ID, value: style name) where a different style shoul...
QDomElement createElement(const QString &tagName)
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)...
QMap< QString, QString > mLayerStyleOverrides
Overrides of map layers' styles: key = layer ID, value = style XML.
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QString layerName() const
Q_DECL_DEPRECATED QgsLayerTreeLayer * layerNodeForSymbologyNode(const QModelIndex &index) const
Return layer node to which a legend node belongs to.
QObject * parent() const
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
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QString toString() const
int count(const Key &key) const
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.
bool setContent(const QByteArray &data, bool namespaceProcessing, QString *errorMsg, int *errorLine, int *errorColumn)
const T value(const Key &key) const
void nodeVisibilityChanged(QgsLayerTreeNode *node)
Structure that stores all data associated with one map layer.
typedef ItemFlags
QByteArray toUtf8() const