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