QGIS API Documentation  2.12.0-Lyon
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 | DeferredLegendInvalidation )
39  , mAutoCollapseLegendNodesCount( -1 )
40  , mLegendFilterByScale( 0 )
41  , mLegendMapViewMupp( 0 )
42  , mLegendMapViewDpi( 0 )
43  , mLegendMapViewScale( 0 )
44 {
46 
47  mFontLayer.setBold( true );
48 
49  connect( &mDeferLegendInvalidationTimer, SIGNAL( timeout() ), this, SLOT( invalidateLegendMapBasedData() ) );
51 }
52 
54 {
55  legendCleanup();
56 }
57 
59 {
60  if ( !index.isValid() )
61  return mRootNode;
62 
63  QObject* obj = reinterpret_cast<QObject*>( index.internalPointer() );
64  return qobject_cast<QgsLayerTreeNode*>( obj );
65 }
66 
67 
68 int QgsLayerTreeModel::rowCount( const QModelIndex &parent ) const
69 {
70  if ( QgsLayerTreeModelLegendNode* nodeLegend = index2legendNode( parent ) )
71  return legendNodeRowCount( nodeLegend );
72 
73  QgsLayerTreeNode* n = index2node( parent );
74  if ( !n )
75  return 0;
76 
77  if ( QgsLayerTree::isLayer( n ) )
78  {
79  if ( !testFlag( ShowLegend ) )
80  return 0;
81 
83  }
84 
85  return n->children().count();
86 }
87 
88 int QgsLayerTreeModel::columnCount( const QModelIndex &parent ) const
89 {
90  Q_UNUSED( parent );
91  return 1;
92 }
93 
94 QModelIndex QgsLayerTreeModel::index( int row, int column, const QModelIndex &parent ) const
95 {
96  if ( column < 0 || column >= columnCount( parent ) ||
97  row < 0 || row >= rowCount( parent ) )
98  return QModelIndex();
99 
100  if ( QgsLayerTreeModelLegendNode* nodeLegend = index2legendNode( parent ) )
101  return legendNodeIndex( row, column, nodeLegend );
102 
103  QgsLayerTreeNode *n = index2node( parent );
104  if ( !n )
105  return QModelIndex(); // have no children
106 
107  if ( testFlag( ShowLegend ) && QgsLayerTree::isLayer( n ) )
108  {
109  return legendRootIndex( row, column, QgsLayerTree::toLayer( n ) );
110  }
111 
112  return createIndex( row, column, static_cast<QObject*>( n->children().at( row ) ) );
113 }
114 
115 
117 {
118  if ( !child.isValid() )
119  return QModelIndex();
120 
121  if ( QgsLayerTreeNode *n = index2node( child ) )
122  {
123  return indexOfParentLayerTreeNode( n->parent() ); // must not be null
124  }
125  else if ( QgsLayerTreeModelLegendNode* legendNode = index2legendNode( child ) )
126  {
127  return legendParent( legendNode );
128  }
129  else
130  {
131  Q_ASSERT( false ); // no other node types!
132  return QModelIndex();
133  }
134 
135 }
136 
137 
139 {
140  Q_ASSERT( parentNode );
141 
142  QgsLayerTreeNode* grandParentNode = parentNode->parent();
143  if ( !grandParentNode )
144  return QModelIndex(); // root node -> invalid index
145 
146  int row = grandParentNode->children().indexOf( parentNode );
147  Q_ASSERT( row >= 0 );
148 
149  return createIndex( row, 0, static_cast<QObject*>( parentNode ) );
150 }
151 
152 
154 {
155  if ( !index.isValid() || index.column() > 1 )
156  return QVariant();
157 
158  if ( QgsLayerTreeModelLegendNode* sym = index2legendNode( index ) )
159  return legendNodeData( sym, role );
160 
161  QgsLayerTreeNode* node = index2node( index );
162  if ( role == Qt::DisplayRole || role == Qt::EditRole )
163  {
164  if ( QgsLayerTree::isGroup( node ) )
165  return QgsLayerTree::toGroup( node )->name();
166 
167  if ( QgsLayerTree::isLayer( node ) )
168  {
169  QgsLayerTreeLayer* nodeLayer = QgsLayerTree::toLayer( node );
170  QString name = nodeLayer->layerName();
171  if ( nodeLayer->customProperty( "showFeatureCount", 0 ).toInt() && role == Qt::DisplayRole )
172  {
173  QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer*>( nodeLayer->layer() );
174  if ( vlayer && vlayer->featureCount() >= 0 )
175  name += QString( " [%1]" ).arg( vlayer->featureCount() );
176  }
177  return name;
178  }
179  }
180  else if ( role == Qt::DecorationRole && index.column() == 0 )
181  {
182  if ( QgsLayerTree::isGroup( node ) )
183  return iconGroup();
184 
185  if ( QgsLayerTree::isLayer( node ) )
186  {
187  QgsLayerTreeLayer *nodeLayer = QgsLayerTree::toLayer( node );
188 
189  QgsMapLayer *layer = nodeLayer->layer();
190  if ( !layer )
191  return QVariant();
192 
193  // icons possibly overriding default icon
194  if ( layer->type() == QgsMapLayer::RasterLayer )
195  {
197  {
198  QgsRasterLayer* rlayer = qobject_cast<QgsRasterLayer *>( layer );
199  return QIcon( QPixmap::fromImage( rlayer->previewAsImage( QSize( 32, 32 ) ) ) );
200  }
201  else
202  {
203  return QgsLayerItem::iconRaster();
204  }
205  }
206 
207  QgsVectorLayer *vlayer = dynamic_cast<QgsVectorLayer*>( layer );
208  QIcon icon;
209 
210  // if there's just on legend entry that should be embedded in layer - do that!
211  if ( testFlag( ShowLegend ) && legendEmbeddedInParent( nodeLayer ) )
212  {
213  icon = legendIconEmbeddedInParent( nodeLayer );
214  }
215  else if ( vlayer && layer->type() == QgsMapLayer::VectorLayer )
216  {
217  if ( vlayer->geometryType() == QGis::Point )
218  icon = QgsLayerItem::iconPoint();
219  else if ( vlayer->geometryType() == QGis::Line )
220  icon = QgsLayerItem::iconLine();
221  else if ( vlayer->geometryType() == QGis::Polygon )
222  icon = QgsLayerItem::iconPolygon();
223  else if ( vlayer->geometryType() == QGis::NoGeometry )
224  icon = QgsLayerItem::iconTable();
225  else
226  icon = QgsLayerItem::iconDefault();
227  }
228 
229  if ( vlayer && vlayer->isEditable() )
230  {
231  QPixmap pixmap( icon.pixmap( 16, 16 ) );
232 
233  QPainter painter( &pixmap );
234  painter.drawPixmap( 0, 0, 16, 16, QgsApplication::getThemePixmap( vlayer->isModified() ? "/mIconEditableEdits.png" : "/mIconEditable.png" ) );
235  painter.end();
236 
237  icon = QIcon( pixmap );
238  }
239 
240  return icon;
241  }
242  }
243  else if ( role == Qt::CheckStateRole )
244  {
246  return QVariant();
247 
248  if ( QgsLayerTree::isLayer( node ) )
249  {
250  QgsLayerTreeLayer* nodeLayer = QgsLayerTree::toLayer( node );
251  if ( nodeLayer->layer() && nodeLayer->layer()->type() == QgsMapLayer::VectorLayer )
252  {
253  if ( qobject_cast<QgsVectorLayer*>( nodeLayer->layer() )->geometryType() == QGis::NoGeometry )
254  return QVariant(); // do not show checkbox for non-spatial tables
255  }
256  return nodeLayer->isVisible();
257  }
258  else if ( QgsLayerTree::isGroup( node ) )
259  {
260  QgsLayerTreeGroup* nodeGroup = QgsLayerTree::toGroup( node );
261  return nodeGroup->isVisible();
262  }
263  }
264  else if ( role == Qt::FontRole )
265  {
266  QFont f( QgsLayerTree::isLayer( node ) ? mFontLayer : ( QgsLayerTree::isGroup( node ) ? mFontGroup : QFont() ) );
267  if ( node->customProperty( "embedded" ).toInt() )
268  f.setItalic( true );
269  if ( index == mCurrentIndex )
270  f.setUnderline( true );
271  return f;
272  }
273  else if ( role == Qt::ToolTipRole )
274  {
275  if ( QgsLayerTree::isLayer( node ) )
276  {
277  if ( QgsMapLayer* layer = QgsLayerTree::toLayer( node )->layer() )
278  return layer->publicSource();
279  }
280  }
281 
282  return QVariant();
283 }
284 
285 
287 {
288  if ( !index.isValid() )
289  {
290  Qt::ItemFlags rootFlags = 0;
291  if ( testFlag( AllowNodeReorder ) )
292  rootFlags |= Qt::ItemIsDropEnabled;
293  return rootFlags;
294  }
295 
296  if ( QgsLayerTreeModelLegendNode* symn = index2legendNode( index ) )
297  return legendNodeFlags( symn );
298 
299  Qt::ItemFlags f = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
300 
301  if ( testFlag( AllowNodeRename ) )
302  f |= Qt::ItemIsEditable;
303 
304  QgsLayerTreeNode* node = index2node( index );
305  bool isEmbedded = node->customProperty( "embedded" ).toInt();
306 
307  if ( testFlag( AllowNodeReorder ) )
308  {
309  // only root embedded nodes can be reordered
310  if ( !isEmbedded || ( isEmbedded && node->parent() && !node->parent()->customProperty( "embedded" ).toInt() ) )
311  f |= Qt::ItemIsDragEnabled;
312  }
313 
315  f |= Qt::ItemIsUserCheckable;
316 
317  if ( testFlag( AllowNodeReorder ) && QgsLayerTree::isGroup( node ) && !isEmbedded )
318  f |= Qt::ItemIsDropEnabled;
319 
320  return f;
321 }
322 
323 bool QgsLayerTreeModel::setData( const QModelIndex& index, const QVariant& value, int role )
324 {
326  if ( sym )
327  {
328  if ( role == Qt::CheckStateRole && !testFlag( AllowLegendChangeState ) )
329  return false;
330  bool res = sym->setData( value, role );
331  if ( res )
332  emit dataChanged( index, index );
333  return res;
334  }
335 
336  QgsLayerTreeNode* node = index2node( index );
337  if ( !node )
338  return QgsLayerTreeModel::setData( index, value, role );
339 
340  if ( role == Qt::CheckStateRole )
341  {
343  return false;
344 
345  if ( QgsLayerTree::isLayer( node ) )
346  {
347  QgsLayerTreeLayer* layer = QgsLayerTree::toLayer( node );
348  layer->setVisible(( Qt::CheckState )value.toInt() );
349  return true;
350  }
351 
352  if ( QgsLayerTree::isGroup( node ) )
353  {
354  QgsLayerTreeGroup* group = QgsLayerTree::toGroup( node );
355  group->setVisible(( Qt::CheckState )value.toInt() );
356  return true;
357  }
358 
359  return true;
360  }
361  else if ( role == Qt::EditRole )
362  {
363  if ( !testFlag( AllowNodeRename ) )
364  return false;
365 
366  if ( QgsLayerTree::isLayer( node ) )
367  {
368  QgsLayerTreeLayer* layer = QgsLayerTree::toLayer( node );
369  layer->setLayerName( value.toString() );
370  emit dataChanged( index, index );
371  }
372  else if ( QgsLayerTree::isGroup( node ) )
373  {
374  QgsLayerTree::toGroup( node )->setName( value.toString() );
375  emit dataChanged( index, index );
376  }
377  }
378 
379  return QAbstractItemModel::setData( index, value, role );
380 }
381 
383 {
384  if ( !node->parent() )
385  return QModelIndex(); // this is the only root item -> invalid index
386 
387  QModelIndex parentIndex = node2index( node->parent() );
388 
389  int row = node->parent()->children().indexOf( node );
390  Q_ASSERT( row >= 0 );
391  return index( row, 0, parentIndex );
392 }
393 
394 
396 {
397  if ( !child->parent() )
398  return false;
399 
400  if ( child->parent() == node )
401  return true;
402 
403  return _isChildOfNode( child->parent(), node );
404 }
405 
406 static bool _isChildOfNodes( QgsLayerTreeNode* child, const QList<QgsLayerTreeNode*>& nodes )
407 {
408  Q_FOREACH ( QgsLayerTreeNode* n, nodes )
409  {
410  if ( _isChildOfNode( child, n ) )
411  return true;
412  }
413 
414  return false;
415 }
416 
417 
418 QList<QgsLayerTreeNode*> QgsLayerTreeModel::indexes2nodes( const QModelIndexList& list, bool skipInternal ) const
419 {
421  Q_FOREACH ( const QModelIndex& index, list )
422  {
423  QgsLayerTreeNode* node = index2node( index );
424  if ( !node )
425  continue;
426 
427  nodes << node;
428  }
429 
430  if ( !skipInternal )
431  return nodes;
432 
433  // remove any children of nodes if both parent node and children are selected
434  QList<QgsLayerTreeNode*> nodesFinal;
435  Q_FOREACH ( QgsLayerTreeNode* node, nodes )
436  {
437  if ( !_isChildOfNodes( node, nodes ) )
438  nodesFinal << node;
439  }
440 
441  return nodesFinal;
442 }
443 
445 {
446  return index2legendNode( index ) != 0;
447 }
448 
450 {
451  QgsLayerTreeModelLegendNode* symNode = index2legendNode( index );
452  return symNode ? symNode->layerNode() : 0;
453 }
454 
456 {
457  return mRootNode;
458 }
459 
461 {
462  beginResetModel();
463 
465 
466  Q_ASSERT( mLegend.isEmpty() );
467 
468  mRootNode = newRootGroup;
469 
470  endResetModel();
471 
473 }
474 
476 {
477  // update title
478  QModelIndex idx = node2index( nodeLayer );
479  emit dataChanged( idx, idx );
480 
481  // update children
482  int oldNodeCount = rowCount( idx );
483  beginRemoveRows( idx, 0, oldNodeCount - 1 );
484  removeLegendFromLayer( nodeLayer );
485  endRemoveRows();
486 
487  addLegendToLayer( nodeLayer );
488  int newNodeCount = rowCount( idx );
489 
490  // automatic collapse of legend nodes - useful if a layer has many legend nodes
491  if ( mAutoCollapseLegendNodesCount != -1 && oldNodeCount != newNodeCount && newNodeCount >= mAutoCollapseLegendNodesCount )
492  nodeLayer->setExpanded( false );
493 }
494 
496 {
497  return mCurrentIndex;
498 }
499 
501 {
502  QModelIndex oldIndex = mCurrentIndex;
504 
505  if ( oldIndex.isValid() )
506  emit dataChanged( oldIndex, oldIndex );
507  if ( currentIndex.isValid() )
508  emit dataChanged( currentIndex, currentIndex );
509 }
510 
511 
512 void QgsLayerTreeModel::setLayerTreeNodeFont( int nodeType, const QFont& font )
513 {
514  if ( nodeType == QgsLayerTreeNode::NodeGroup )
515  {
516  if ( mFontGroup != font )
517  {
518  mFontGroup = font;
520  }
521  }
522  else if ( nodeType == QgsLayerTreeNode::NodeLayer )
523  {
524  if ( mFontLayer != font )
525  {
526  mFontLayer = font;
528  }
529  }
530  else
531  {
532  QgsDebugMsg( "invalid node type" );
533  }
534 }
535 
536 
538 {
539  if ( nodeType == QgsLayerTreeNode::NodeGroup )
540  return mFontGroup;
541  else if ( nodeType == QgsLayerTreeNode::NodeLayer )
542  return mFontLayer;
543  else
544  {
545  QgsDebugMsg( "invalid node type" );
546  return QFont();
547  }
548 }
549 
550 void QgsLayerTreeModel::setLegendFilterByScale( double scaleDenominator )
551 {
552  mLegendFilterByScale = scaleDenominator;
553 
554  // this could be later done in more efficient way
555  // by just updating active legend nodes, without refreshing original legend nodes
556  Q_FOREACH ( QgsLayerTreeLayer* nodeLayer, mRootNode->findLayers() )
557  refreshLayerLegend( nodeLayer );
558 }
559 
561 {
562  if ( settings && settings->hasValidSettings() )
563  {
564  mLegendFilterByMapSettings.reset( new QgsMapSettings( *settings ) );
565  mLegendFilterByMapSettings->setLayerStyleOverrides( mLayerStyleOverrides );
568  }
569  else
570  {
572  return; // no change
573 
576  }
577 
578  // temporarily disable autocollapse so that legend nodes stay visible
579  int bkAutoCollapse = autoCollapseLegendNodes();
581 
582  // this could be later done in more efficient way
583  // by just updating active legend nodes, without refreshing original legend nodes
584  Q_FOREACH ( QgsLayerTreeLayer* nodeLayer, mRootNode->findLayers() )
585  refreshLayerLegend( nodeLayer );
586 
587  setAutoCollapseLegendNodes( bkAutoCollapse );
588 }
589 
590 void QgsLayerTreeModel::setLegendMapViewData( double mapUnitsPerPixel, int dpi, double scale )
591 {
592  if ( mLegendMapViewDpi == dpi && mLegendMapViewMupp == mapUnitsPerPixel && mLegendMapViewScale == scale )
593  return;
594 
595  mLegendMapViewMupp = mapUnitsPerPixel;
596  mLegendMapViewDpi = dpi;
597  mLegendMapViewScale = scale;
598 
599  // now invalidate legend nodes!
601 }
602 
603 void QgsLayerTreeModel::legendMapViewData( double* mapUnitsPerPixel, int* dpi, double* scale )
604 {
605  if ( mapUnitsPerPixel ) *mapUnitsPerPixel = mLegendMapViewMupp;
606  if ( dpi ) *dpi = mLegendMapViewDpi;
607  if ( scale ) *scale = mLegendMapViewScale;
608 }
609 
611 {
612  return mLayerStyleOverrides;
613 }
614 
616 {
617  mLayerStyleOverrides = overrides;
618 }
619 
620 void QgsLayerTreeModel::nodeWillAddChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo )
621 {
622  Q_ASSERT( node );
623  beginInsertRows( node2index( node ), indexFrom, indexTo );
624 }
625 
626 static QList<QgsLayerTreeLayer*> _layerNodesInSubtree( QgsLayerTreeNode* node, int indexFrom, int indexTo )
627 {
628  QList<QgsLayerTreeNode*> children = node->children();
629  QList<QgsLayerTreeLayer*> newLayerNodes;
630  for ( int i = indexFrom; i <= indexTo; ++i )
631  {
632  QgsLayerTreeNode* child = children.at( i );
633  if ( QgsLayerTree::isLayer( child ) )
634  newLayerNodes << QgsLayerTree::toLayer( child );
635  else if ( QgsLayerTree::isGroup( child ) )
636  newLayerNodes << QgsLayerTree::toGroup( child )->findLayers();
637  }
638  return newLayerNodes;
639 }
640 
641 void QgsLayerTreeModel::nodeAddedChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo )
642 {
643  Q_ASSERT( node );
644 
645  endInsertRows();
646 
647  Q_FOREACH ( QgsLayerTreeLayer* newLayerNode, _layerNodesInSubtree( node, indexFrom, indexTo ) )
648  connectToLayer( newLayerNode );
649 }
650 
651 void QgsLayerTreeModel::nodeWillRemoveChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo )
652 {
653  Q_ASSERT( node );
654 
655  beginRemoveRows( node2index( node ), indexFrom, indexTo );
656 
657  // disconnect from layers and remove their legend
658  Q_FOREACH ( QgsLayerTreeLayer* nodeLayer, _layerNodesInSubtree( node, indexFrom, indexTo ) )
659  disconnectFromLayer( nodeLayer );
660 }
661 
663 {
664  endRemoveRows();
665 }
666 
668 {
669  Q_ASSERT( node );
670 
671  QModelIndex index = node2index( node );
672  emit dataChanged( index, index );
673 }
674 
675 
677 {
678  if ( QgsLayerTree::isLayer( node ) && key == "showFeatureCount" )
680 }
681 
682 
684 {
685  QgsLayerTreeLayer* nodeLayer = qobject_cast<QgsLayerTreeLayer*>( sender() );
686  if ( !nodeLayer )
687  return;
688 
689  // deferred connection to the layer
690  connectToLayer( nodeLayer );
691 }
692 
694 {
695  QgsLayerTreeLayer* nodeLayer = qobject_cast<QgsLayerTreeLayer*>( sender() );
696  if ( !nodeLayer )
697  return;
698 
699  disconnectFromLayer( nodeLayer );
700 
701  // wait for the layer to appear again
702  connect( nodeLayer, SIGNAL( layerLoaded() ), this, SLOT( nodeLayerLoaded() ) );
703 }
704 
706 {
707  if ( !testFlag( ShowLegend ) )
708  return;
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  refreshLayerLegend( nodeLayer );
719 }
720 
722 {
723  QgsMapLayer* layer = qobject_cast<QgsMapLayer*>( sender() );
724  if ( !layer )
725  return;
726 
727  QgsLayerTreeLayer* nodeLayer = mRootNode->findLayer( layer->id() );
728  if ( !nodeLayer )
729  return;
730 
731  QModelIndex index = node2index( nodeLayer );
732  emit dataChanged( index, index );
733 
734  if ( nodeLayer->customProperty( "showFeatureCount" ).toInt() )
735  refreshLayerLegend( nodeLayer );
736 }
737 
738 
740 {
741  QgsLayerTreeModelLegendNode* legendNode = qobject_cast<QgsLayerTreeModelLegendNode*>( sender() );
742  if ( !legendNode )
743  return;
744 
745  QModelIndex index = legendNode2index( legendNode );
746  if ( index.isValid() )
747  emit dataChanged( index, index );
748 }
749 
750 
752 {
753  if ( !nodeLayer->layer() )
754  {
755  // in order to connect to layer, we need to have it loaded.
756  // keep an eye on the layer ID: once loaded, we will use it
757  connect( nodeLayer, SIGNAL( layerLoaded() ), this, SLOT( nodeLayerLoaded() ) );
758  return;
759  }
760 
761  // watch if the layer is getting removed
762  connect( nodeLayer, SIGNAL( layerWillBeUnloaded() ), this, SLOT( nodeLayerWillBeUnloaded() ) );
763 
764  if ( testFlag( ShowLegend ) )
765  {
766  addLegendToLayer( nodeLayer );
767 
768  // automatic collapse of legend nodes - useful if a layer has many legend nodes
769  if ( !mRootNode->customProperty( "loading" ).toBool() )
770  {
772  nodeLayer->setExpanded( false );
773  }
774  }
775 
776  QgsMapLayer* layer = nodeLayer->layer();
777  connect( layer, SIGNAL( legendChanged() ), this, SLOT( layerLegendChanged() ), Qt::UniqueConnection );
778 
779  if ( layer->type() == QgsMapLayer::VectorLayer )
780  {
781  // using unique connection because there may be temporarily more nodes for a layer than just one
782  // which would create multiple connections, however disconnect() would disconnect all multiple connections
783  // even if we wanted to disconnect just one connection in each call.
784  connect( layer, SIGNAL( editingStarted() ), this, SLOT( layerNeedsUpdate() ), Qt::UniqueConnection );
785  connect( layer, SIGNAL( editingStopped() ), this, SLOT( layerNeedsUpdate() ), Qt::UniqueConnection );
786  connect( layer, SIGNAL( layerModified() ), this, SLOT( layerNeedsUpdate() ), Qt::UniqueConnection );
787  connect( layer, SIGNAL( layerNameChanged() ), this, SLOT( layerNeedsUpdate() ), Qt::UniqueConnection );
788  }
789 }
790 
791 // try to find out if the layer ID is present in the tree multiple times
792 static int _numLayerCount( QgsLayerTreeGroup* group, const QString& layerId )
793 {
794  int count = 0;
795  Q_FOREACH ( QgsLayerTreeNode* child, group->children() )
796  {
797  if ( QgsLayerTree::isLayer( child ) )
798  {
799  if ( QgsLayerTree::toLayer( child )->layerId() == layerId )
800  count++;
801  }
802  else if ( QgsLayerTree::isGroup( child ) )
803  {
804  count += _numLayerCount( QgsLayerTree::toGroup( child ), layerId );
805  }
806  }
807  return count;
808 }
809 
811 {
812  disconnect( nodeLayer, 0, this, 0 ); // disconnect from delayed load of layer
813 
814  if ( !nodeLayer->layer() )
815  return; // we were never connected
816 
817  if ( testFlag( ShowLegend ) )
818  {
819  removeLegendFromLayer( nodeLayer );
820  }
821 
822  if ( _numLayerCount( mRootNode, nodeLayer->layerId() ) == 1 )
823  {
824  // last instance of the layer in the tree: disconnect from all signals from layer!
825  disconnect( nodeLayer->layer(), 0, this, 0 );
826  }
827 }
828 
830 {
831  Q_FOREACH ( QgsLayerTreeNode* node, parentGroup->children() )
832  {
833  if ( QgsLayerTree::isGroup( node ) )
835  else if ( QgsLayerTree::isLayer( node ) )
837  }
838 }
839 
841 {
842  Q_FOREACH ( QgsLayerTreeNode* node, parentGroup->children() )
843  {
844  if ( QgsLayerTree::isGroup( node ) )
846  else if ( QgsLayerTree::isLayer( node ) )
848  }
849 }
850 
852 {
853  Q_ASSERT( mRootNode );
854 
855  connect( mRootNode, SIGNAL( willAddChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeWillAddChildren( QgsLayerTreeNode*, int, int ) ) );
856  connect( mRootNode, SIGNAL( addedChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeAddedChildren( QgsLayerTreeNode*, int, int ) ) );
857  connect( mRootNode, SIGNAL( willRemoveChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeWillRemoveChildren( QgsLayerTreeNode*, int, int ) ) );
858  connect( mRootNode, SIGNAL( removedChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeRemovedChildren() ) );
859  connect( mRootNode, SIGNAL( visibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ), this, SLOT( nodeVisibilityChanged( QgsLayerTreeNode* ) ) );
860 
861  connect( mRootNode, SIGNAL( customPropertyChanged( QgsLayerTreeNode*, QString ) ), this, SLOT( nodeCustomPropertyChanged( QgsLayerTreeNode*, QString ) ) );
862 
864 }
865 
867 {
868  disconnect( mRootNode, 0, this, 0 );
869 
871 }
872 
874 {
875  QgsLayerTreeNode* node = index2node( idx );
876  if ( !node )
877  return;
878 
879  int count = node->children().count();
880  if ( count == 0 )
881  return;
882  emit dataChanged( index( 0, 0, idx ), index( count - 1, 0, idx ) );
883  for ( int i = 0; i < count; ++i )
884  recursivelyEmitDataChanged( index( i, 0, idx ) );
885 }
886 
887 
889 {
890  return Qt::MoveAction;
891 }
892 
894 {
895  QStringList types;
896  types << "application/qgis.layertreemodeldata";
897  return types;
898 }
899 
900 
901 QMimeData* QgsLayerTreeModel::mimeData( const QModelIndexList& indexes ) const
902 {
903  QList<QgsLayerTreeNode*> nodesFinal = indexes2nodes( indexes, true );
904 
905  if ( nodesFinal.count() == 0 )
906  return 0;
907 
908  QMimeData *mimeData = new QMimeData();
909 
910  QDomDocument doc;
911  QDomElement rootElem = doc.createElement( "layer_tree_model_data" );
912  Q_FOREACH ( QgsLayerTreeNode* node, nodesFinal )
913  node->writeXML( rootElem );
914  doc.appendChild( rootElem );
915  QString txt = doc.toString();
916 
917  mimeData->setData( "application/qgis.layertreemodeldata", txt.toUtf8() );
918  return mimeData;
919 }
920 
921 bool QgsLayerTreeModel::dropMimeData( const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent )
922 {
923  if ( action == Qt::IgnoreAction )
924  return true;
925 
926  if ( !data->hasFormat( "application/qgis.layertreemodeldata" ) )
927  return false;
928 
929  if ( column >= columnCount( parent ) )
930  return false;
931 
932  QgsLayerTreeNode* nodeParent = index2node( parent );
933  if ( !QgsLayerTree::isGroup( nodeParent ) )
934  return false;
935 
936  QByteArray encodedData = data->data( "application/qgis.layertreemodeldata" );
937 
938  QDomDocument doc;
939  if ( !doc.setContent( QString::fromUtf8( encodedData ) ) )
940  return false;
941 
942  QDomElement rootElem = doc.documentElement();
943  if ( rootElem.tagName() != "layer_tree_model_data" )
944  return false;
945 
947 
948  QDomElement elem = rootElem.firstChildElement();
949  while ( !elem.isNull() )
950  {
952  if ( node )
953  nodes << node;
954 
955  elem = elem.nextSiblingElement();
956  }
957 
958  if ( nodes.count() == 0 )
959  return false;
960 
961  if ( parent.isValid() && row == -1 )
962  row = 0; // if dropped directly onto group item, insert at first position
963 
964  QgsLayerTree::toGroup( nodeParent )->insertChildNodes( row, nodes );
965 
966  return true;
967 }
968 
969 bool QgsLayerTreeModel::removeRows( int row, int count, const QModelIndex& parent )
970 {
971  QgsLayerTreeNode* parentNode = index2node( parent );
972  if ( QgsLayerTree::isGroup( parentNode ) )
973  {
974  QgsLayerTree::toGroup( parentNode )->removeChildren( row, count );
975  return true;
976  }
977  return false;
978 }
979 
980 void QgsLayerTreeModel::setFlags( const QgsLayerTreeModel::Flags& f )
981 {
982  mFlags = f;
983 }
984 
986 {
987  if ( on )
988  mFlags |= f;
989  else
990  mFlags &= ~f;
991 }
992 
993 QgsLayerTreeModel::Flags QgsLayerTreeModel::flags() const
994 {
995  return mFlags;
996 }
997 
999 {
1000  return mFlags.testFlag( f );
1001 }
1002 
1004 {
1005  static QIcon icon;
1006 
1007  if ( icon.isNull() )
1008  icon = QgsApplication::getThemeIcon( "/mActionFolder.png" );
1009 
1010  return icon;
1011 }
1012 
1014 {
1016 
1017  if ( mLegendFilterByScale > 0 )
1018  {
1019  Q_FOREACH ( QgsLayerTreeModelLegendNode* node, nodes )
1020  {
1021  if ( node->isScaleOK( mLegendFilterByScale ) )
1022  filtered << node;
1023  }
1024  }
1025  else if ( mLegendFilterByMapSettings )
1026  {
1027  Q_FOREACH ( QgsLayerTreeModelLegendNode* node, nodes )
1028  {
1030  if ( ruleKey )
1031  {
1032  if ( QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( node->layerNode()->layer() ) )
1033  {
1034  if ( mLegendFilterByMapHitTest->symbolVisible( ruleKey, vl ) )
1035  filtered << node;
1036  }
1037  }
1038  else // unknown node type
1039  filtered << node;
1040  }
1041  }
1042  else
1043  {
1044  return nodes;
1045  }
1046 
1047  return filtered;
1048 }
1049 
1050 
1051 
1053 // Legend nodes routines - start
1054 
1056 {
1057  Q_FOREACH ( const LayerLegendData& data, mLegend )
1058  {
1059  qDeleteAll( data.originalNodes );
1060  delete data.tree;
1061  }
1062  mLegend.clear();
1063 }
1064 
1065 
1067 {
1068  if ( mLegend.contains( nodeLayer ) )
1069  {
1070  qDeleteAll( mLegend[nodeLayer].originalNodes );
1071  delete mLegend[nodeLayer].tree;
1072  mLegend.remove( nodeLayer );
1073  }
1074 }
1075 
1076 
1078 {
1079  if ( !nodeL->layer() )
1080  return;
1081 
1082  QgsMapLayer* ml = nodeL->layer();
1083  QgsMapLayerLegend* layerLegend = ml->legend();
1084  if ( !layerLegend )
1085  return;
1086 
1087  bool hasStyleOverride = mLayerStyleOverrides.contains( ml->id() );
1088  if ( hasStyleOverride )
1090 
1092 
1093  // apply filtering defined in layer node's custom properties (reordering, filtering, custom labels)
1095 
1096  QList<QgsLayerTreeModelLegendNode*> filteredLstNew = filterLegendNodes( lstNew );
1097 
1098  bool isEmbedded = filteredLstNew.count() == 1 && filteredLstNew[0]->isEmbeddedInParent();
1099 
1100  Q_FOREACH ( QgsLayerTreeModelLegendNode* n, lstNew )
1101  {
1102  n->setParent( this );
1103  connect( n, SIGNAL( dataChanged() ), this, SLOT( legendNodeDataChanged() ) );
1104  }
1105 
1107  data.originalNodes = lstNew;
1108  data.activeNodes = filteredLstNew;
1109  data.tree = 0;
1110 
1111  // maybe the legend nodes form a tree - try to create a tree structure from the list
1112  if ( testFlag( ShowLegendAsTree ) )
1113  tryBuildLegendTree( data );
1114 
1115  int count = data.tree ? data.tree->children[0].count() : filteredLstNew.count();
1116 
1117  if ( ! isEmbedded ) beginInsertRows( node2index( nodeL ), 0, count - 1 );
1118 
1119  mLegend[nodeL] = data;
1120 
1121  if ( ! isEmbedded ) endInsertRows();
1122 
1123  if ( hasStyleOverride )
1125 
1126  // invalidate map based data even if the data is not map-based to make sure
1127  // the symbol sizes are computed at least once
1129 }
1130 
1131 
1133 {
1134  // first check whether there are any legend nodes that are not top-level
1135  bool hasParentKeys = false;
1136  Q_FOREACH ( QgsLayerTreeModelLegendNode* n, data.activeNodes )
1137  {
1139  {
1140  hasParentKeys = true;
1141  break;
1142  }
1143  }
1144  if ( !hasParentKeys )
1145  return; // all legend nodes are top-level => stick with list representation
1146 
1147  // make mapping from rules to nodes and do some sanity checks
1149  rule2node[QString()] = 0;
1150  Q_FOREACH ( QgsLayerTreeModelLegendNode* n, data.activeNodes )
1151  {
1153  if ( ruleKey.isEmpty() ) // in tree all nodes must have key
1154  return;
1155  if ( rule2node.contains( ruleKey ) ) // and they must be unique
1156  return;
1157  rule2node[ruleKey] = n;
1158  }
1159 
1160  // create the tree structure
1161  data.tree = new LayerLegendTree;
1162  Q_FOREACH ( QgsLayerTreeModelLegendNode* n, data.activeNodes )
1163  {
1165  QgsLayerTreeModelLegendNode* parent = rule2node.value( parentRuleKey, 0 );
1166  data.tree->parents[n] = parent;
1167  data.tree->children[parent] << n;
1168  }
1169 }
1170 
1171 
1173 {
1174  return qobject_cast<QgsLayerTreeModelLegendNode*>( reinterpret_cast<QObject*>( index.internalPointer() ) );
1175 }
1176 
1177 
1179 {
1180  const LayerLegendData& data = mLegend[legendNode->layerNode()];
1181  if ( data.tree )
1182  {
1183  if ( QgsLayerTreeModelLegendNode* parentLegendNode = data.tree->parents[legendNode] )
1184  {
1185  QModelIndex parentIndex = legendNode2index( parentLegendNode );
1186  int row = data.tree->children[parentLegendNode].indexOf( legendNode );
1187  return index( row, 0, parentIndex );
1188  }
1189  else
1190  {
1191  QModelIndex parentIndex = node2index( legendNode->layerNode() );
1192  int row = data.tree->children[0].indexOf( legendNode );
1193  return index( row, 0, parentIndex );
1194  }
1195  }
1196 
1197  QModelIndex parentIndex = node2index( legendNode->layerNode() );
1198  Q_ASSERT( parentIndex.isValid() );
1199  int row = data.activeNodes.indexOf( legendNode );
1200  if ( row < 0 ) // legend node may be filtered (exists within the list of original nodes, but not in active nodes)
1201  return QModelIndex();
1202  return index( row, 0, parentIndex );
1203 }
1204 
1205 
1207 {
1208  const LayerLegendData& data = mLegend[node->layerNode()];
1209  if ( data.tree )
1210  return data.tree->children[node].count();
1211 
1212  return 0; // they are leaves
1213 }
1214 
1215 
1217 {
1218  if ( legendEmbeddedInParent( nL ) )
1219  return 0;
1220 
1221  if ( !mLegend.contains( nL ) )
1222  return 0;
1223 
1224  const LayerLegendData& data = mLegend[nL];
1225  if ( data.tree )
1226  return data.tree->children[0].count();
1227 
1228  return data.activeNodes.count();
1229 }
1230 
1231 
1233 {
1234  Q_ASSERT( mLegend.contains( nL ) );
1235  const LayerLegendData& data = mLegend[nL];
1236  if ( data.tree )
1237  return createIndex( row, column, static_cast<QObject*>( data.tree->children[0].at( row ) ) );
1238 
1239  return createIndex( row, column, static_cast<QObject*>( data.activeNodes.at( row ) ) );
1240 }
1241 
1242 
1244 {
1245  const LayerLegendData& data = mLegend[node->layerNode()];
1246  if ( data.tree )
1247  return createIndex( row, column, static_cast<QObject*>( data.tree->children[node].at( row ) ) );
1248 
1249  return QModelIndex(); // have no children
1250 }
1251 
1252 
1254 {
1255  QgsLayerTreeLayer* layerNode = legendNode->layerNode();
1256  const LayerLegendData& data = mLegend[layerNode];
1257  if ( data.tree )
1258  {
1259  if ( QgsLayerTreeModelLegendNode* parentNode = data.tree->parents[legendNode] )
1260  {
1261  QgsLayerTreeModelLegendNode* grandParentNode = data.tree->parents[parentNode]; // may be null (not a problem)
1262  int row = data.tree->children[grandParentNode].indexOf( parentNode );
1263  return createIndex( row, 0, static_cast<QObject*>( parentNode ) );
1264  }
1265  else
1266  return indexOfParentLayerTreeNode( layerNode );
1267  }
1268 
1269  return indexOfParentLayerTreeNode( layerNode );
1270 }
1271 
1272 
1274 {
1275  if ( role == Qt::CheckStateRole && !testFlag( AllowLegendChangeState ) )
1276  return QVariant();
1277  return node->data( role );
1278 }
1279 
1280 
1282 {
1283  Qt::ItemFlags f = node->flags();
1284  if ( !testFlag( AllowLegendChangeState ) )
1285  f &= ~Qt::ItemIsUserCheckable;
1286  return f;
1287 }
1288 
1289 
1291 {
1292  const LayerLegendData& data = mLegend[nodeLayer];
1293  return data.activeNodes.count() == 1 && data.activeNodes[0]->isEmbeddedInParent();
1294 }
1295 
1296 
1298 {
1299  return QIcon( qvariant_cast<QPixmap>( mLegend[nodeLayer].activeNodes[0]->data( Qt::DecorationRole ) ) );
1300 }
1301 
1302 
1304 {
1305  return mLegend.value( nodeLayer ).activeNodes;
1306 }
1307 
1309 {
1312  else
1314 }
1315 
1317 {
1318  QgsDebugCall;
1319 
1320  // we have varying icon sizes, and we want icon to be centered and
1321  // text to be left aligned, so we have to compute the max width of icons
1322  //
1323  // we do that for nodes who share a common parent
1324  //
1325  // we do that here because for symbols with size defined in map units
1326  // the symbol sizes changes depends on the zoom level
1327 
1328  Q_FOREACH ( const LayerLegendData& data, mLegend )
1329  {
1330  QList<QgsSymbolV2LegendNode*> symbolNodes;
1331  QMap<QString, int> widthMax;
1332  Q_FOREACH ( QgsLayerTreeModelLegendNode* legendNode, data.originalNodes )
1333  {
1334  QgsSymbolV2LegendNode* n = dynamic_cast<QgsSymbolV2LegendNode*>( legendNode );
1335  if ( n )
1336  {
1337  const QSize sz( n->minimumIconSize() );
1339  widthMax[parentKey] = qMax( sz.width(), widthMax.contains( parentKey ) ? widthMax[parentKey] : 0 );
1340  n->setIconSize( sz );
1341  symbolNodes.append( n );
1342  }
1343  }
1344  Q_FOREACH ( QgsSymbolV2LegendNode* n, symbolNodes )
1345  {
1347  Q_ASSERT( widthMax[parentKey] > 0 );
1348  const int twiceMarginWidth = 2; // a one pixel margin avoids hugly rendering of icon
1349  n->setIconSize( QSize( widthMax[parentKey] + twiceMarginWidth, n->iconSize().rheight() + twiceMarginWidth ) );
1350  }
1351  Q_FOREACH ( QgsLayerTreeModelLegendNode* legendNode, data.originalNodes )
1352  legendNode->invalidateMapBasedData();
1353  }
1354 
1355 }
1356 
1357 // 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:94
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()
QImage previewAsImage(const QSize &size, const QColor &bgColor=Qt::white, QImage::Format format=QImage::Format_ARGB32_Premultiplied)
Draws a preview of the rasterlayer into a QImage.
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.
QSize minimumIconSize() const
Get the minimum icon size to prevent cropping.
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
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)
int & rheight()
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)
long featureCount(QgsSymbolV2 *symbol)
Number of features rendered with specified symbol.
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
void append(const T &value)
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...
QTimer mDeferLegendInvalidationTimer
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
virtual QVariant data(int role) const override
Return data associated with the item.
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.
QgsLayerTreeLayer * layerNode() const
Return pointer to the parent layer node.
The QgsMapLayerLegend class is abstract interface for implementations of legends for one map layer...
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.
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.
void insertChildNodes(int index, const 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.
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.
#define QgsDebugCall
Definition: qgslogger.h:32
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
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.
void start(int msec)
Implementation of legend node interface for displaying preview of vector symbols and their labels and...
QFont layerTreeNodeFont(int nodeType) const
Get font for a particular type of layer tree node. nodeType should come from QgsLayerTreeNode::NodeTy...
static bool _isChildOfNodes(QgsLayerTreeNode *child, const QList< QgsLayerTreeNode * > &nodes)
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)
void setIconSize(const QSize &sz)
Set the icon size.
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.
void setFlags(const QgsLayerTreeModel::Flags &f)
Set OR-ed combination of model flags.
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 setSingleShot(bool singleShot)
void nodeVisibilityChanged(QgsLayerTreeNode *node)
Structure that stores all data associated with one map layer.
typedef ItemFlags
QByteArray toUtf8() const