QGIS API Documentation  2.9.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgslayertreeview.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslayertreeview.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 "qgslayertreeview.h"
17 
18 #include "qgslayertree.h"
19 #include "qgslayertreemodel.h"
22 #include "qgsmaplayer.h"
23 
24 #include <QMenu>
25 #include <QContextMenuEvent>
26 
28  : QTreeView( parent )
29  , mDefaultActions( 0 )
30  , mMenuProvider( 0 )
31 {
32  setHeaderHidden( true );
33 
34  setDragEnabled( true );
35  setAcceptDrops( true );
36  setDropIndicatorShown( true );
37  setEditTriggers( EditKeyPressed );
38  setExpandsOnDoubleClick( false ); // normally used for other actions
39 
40  setSelectionMode( ExtendedSelection );
41 
42  connect( this, SIGNAL( collapsed( QModelIndex ) ), this, SLOT( updateExpandedStateToNode( QModelIndex ) ) );
43  connect( this, SIGNAL( expanded( QModelIndex ) ), this, SLOT( updateExpandedStateToNode( QModelIndex ) ) );
44 }
45 
47 {
48  delete mMenuProvider;
49 }
50 
51 void QgsLayerTreeView::setModel( QAbstractItemModel* model )
52 {
53  if ( !qobject_cast<QgsLayerTreeModel*>( model ) )
54  return;
55 
56  connect( model, SIGNAL( rowsInserted( QModelIndex, int, int ) ), this, SLOT( modelRowsInserted( QModelIndex, int, int ) ) );
57  connect( model, SIGNAL( rowsRemoved( QModelIndex, int, int ) ), this, SLOT( modelRowsRemoved() ) );
58 
59  QTreeView::setModel( model );
60 
61  connect( layerTreeModel()->rootGroup(), SIGNAL( expandedChanged( QgsLayerTreeNode*, bool ) ), this, SLOT( onExpandedChanged( QgsLayerTreeNode*, bool ) ) );
62 
63  connect( selectionModel(), SIGNAL( currentChanged( QModelIndex, QModelIndex ) ), this, SLOT( onCurrentChanged() ) );
64 
65  connect( layerTreeModel(), SIGNAL( modelReset() ), this, SLOT( onModelReset() ) );
66 
68 }
69 
71 {
72  return qobject_cast<QgsLayerTreeModel*>( model() );
73 }
74 
76 {
77  if ( !mDefaultActions )
79  return mDefaultActions;
80 }
81 
83 {
84  delete mMenuProvider;
86 }
87 
89 {
90  return layerForIndex( currentIndex() );
91 }
92 
94 {
95  if ( !layer )
96  {
97  setCurrentIndex( QModelIndex() );
98  return;
99  }
100 
101  QgsLayerTreeLayer* nodeLayer = layerTreeModel()->rootGroup()->findLayer( layer->id() );
102  if ( !nodeLayer )
103  return;
104 
105  setCurrentIndex( layerTreeModel()->node2index( nodeLayer ) );
106 }
107 
108 
109 void QgsLayerTreeView::contextMenuEvent( QContextMenuEvent *event )
110 {
111  if ( !mMenuProvider )
112  return;
113 
114  QModelIndex idx = indexAt( event->pos() );
115  if ( !idx.isValid() )
116  setCurrentIndex( QModelIndex() );
117 
118  QMenu* menu = mMenuProvider->createContextMenu();
119  if ( menu && menu->actions().count() != 0 )
120  menu->exec( mapToGlobal( event->pos() ) );
121  delete menu;
122 }
123 
124 
125 void QgsLayerTreeView::modelRowsInserted( QModelIndex index, int start, int end )
126 {
127  QgsLayerTreeNode* parentNode = layerTreeModel()->index2node( index );
128  if ( !parentNode )
129  return;
130 
131  if ( QgsLayerTree::isLayer( parentNode ) )
132  {
133  // if ShowLegendAsTree flag is enabled in model, we may need to expand some legend nodes
134  QStringList expandedNodeKeys = parentNode->customProperty( "expandedLegendNodes" ).toStringList();
135  if ( expandedNodeKeys.isEmpty() )
136  return;
137 
138  foreach ( QgsLayerTreeModelLegendNode* legendNode, layerTreeModel()->layerLegendNodes( QgsLayerTree::toLayer( parentNode ) ) )
139  {
140  QString ruleKey = legendNode->data( QgsLayerTreeModelLegendNode::RuleKeyRole ).toString();
141  if ( expandedNodeKeys.contains( ruleKey ) )
142  setExpanded( layerTreeModel()->legendNode2index( legendNode ), true );
143  }
144  return;
145  }
146 
147  QList<QgsLayerTreeNode*> children = parentNode->children();
148  for ( int i = start; i <= end; ++i )
149  {
150  updateExpandedStateFromNode( children[i] );
151  }
152 
153  // make sure we still have correct current layer
155 }
156 
158 {
159  // make sure we still have correct current layer
161 }
162 
164 {
165  if ( QgsLayerTreeNode* node = layerTreeModel()->index2node( index ) )
166  {
167  node->setExpanded( isExpanded( index ) );
168  }
169  else if ( QgsLayerTreeModelLegendNode* node = layerTreeModel()->index2legendNode( index ) )
170  {
171  QString ruleKey = node->data( QgsLayerTreeModelLegendNode::RuleKeyRole ).toString();
172  QStringList lst = node->layerNode()->customProperty( "expandedLegendNodes" ).toStringList();
173  bool expanded = isExpanded( index );
174  bool isInList = lst.contains( ruleKey );
175  if ( expanded && !isInList )
176  {
177  lst.append( ruleKey );
178  node->layerNode()->setCustomProperty( "expandedLegendNodes", lst );
179  }
180  else if ( !expanded && isInList )
181  {
182  lst.removeAll( ruleKey );
183  node->layerNode()->setCustomProperty( "expandedLegendNodes", lst );
184  }
185  }
186 }
187 
189 {
190  QgsMapLayer* layerCurrent = layerForIndex( currentIndex() );
191  QString layerCurrentID = layerCurrent ? layerCurrent->id() : QString();
192  if ( mCurrentLayerID == layerCurrentID )
193  return;
194 
195  // update the current index in model (the item will be underlined)
196  QModelIndex nodeLayerIndex;
197  if ( layerCurrent )
198  {
199  QgsLayerTreeLayer* nodeLayer = layerTreeModel()->rootGroup()->findLayer( layerCurrentID );
200  if ( nodeLayer )
201  nodeLayerIndex = layerTreeModel()->node2index( nodeLayer );
202  }
203  layerTreeModel()->setCurrentIndex( nodeLayerIndex );
204 
205  mCurrentLayerID = layerCurrentID;
206  emit currentLayerChanged( layerCurrent );
207 }
208 
210 {
211  QModelIndex idx = layerTreeModel()->node2index( node );
212  if ( isExpanded( idx ) != expanded )
213  setExpanded( idx, expanded );
214 }
215 
217 {
219 }
220 
222 {
223  QModelIndex idx = layerTreeModel()->node2index( node );
224  setExpanded( idx, node->isExpanded() );
225 
226  foreach ( QgsLayerTreeNode* child, node->children() )
228 }
229 
231 {
232  QgsLayerTreeNode* node = layerTreeModel()->index2node( index );
233  if ( node )
234  {
235  if ( QgsLayerTree::isLayer( node ) )
236  return QgsLayerTree::toLayer( node )->layer();
237  }
238  else
239  {
240  // possibly a legend node
242  if ( legendNode )
243  return legendNode->layerNode()->layer();
244  }
245 
246  return 0;
247 }
248 
250 {
251  return layerTreeModel()->index2node( selectionModel()->currentIndex() );
252 }
253 
255 {
256  QgsLayerTreeNode* node = currentNode();
257  if ( QgsLayerTree::isGroup( node ) )
258  return QgsLayerTree::toGroup( node );
259  else if ( QgsLayerTree::isLayer( node ) )
260  {
261  QgsLayerTreeNode* parent = node->parent();
262  if ( QgsLayerTree::isGroup( parent ) )
263  return QgsLayerTree::toGroup( parent );
264  }
265 
266  if ( QgsLayerTreeModelLegendNode* legendNode = layerTreeModel()->index2legendNode( selectionModel()->currentIndex() ) )
267  {
268  QgsLayerTreeLayer* parent = legendNode->layerNode();
269  if ( QgsLayerTree::isGroup( parent->parent() ) )
270  return QgsLayerTree::toGroup( parent->parent() );
271  }
272 
273  return 0;
274 }
275 
276 QList<QgsLayerTreeNode*> QgsLayerTreeView::selectedNodes( bool skipInternal ) const
277 {
278  return layerTreeModel()->indexes2nodes( selectionModel()->selectedIndexes(), skipInternal );
279 }
280 
281 QList<QgsLayerTreeLayer*> QgsLayerTreeView::selectedLayerNodes() const
282 {
283  QList<QgsLayerTreeLayer*> layerNodes;
284  foreach ( QgsLayerTreeNode* node, selectedNodes() )
285  {
286  if ( QgsLayerTree::isLayer( node ) )
287  layerNodes << QgsLayerTree::toLayer( node );
288  }
289  return layerNodes;
290 }
291 
292 QList<QgsMapLayer*> QgsLayerTreeView::selectedLayers() const
293 {
294  QList<QgsMapLayer*> list;
295  foreach ( QgsLayerTreeLayer* node, selectedLayerNodes() )
296  {
297  if ( node->layer() )
298  list << node->layer();
299  }
300  return list;
301 }
302 
303 
304 void QgsLayerTreeView::refreshLayerSymbology( const QString& layerId )
305 {
306  QgsLayerTreeLayer* nodeLayer = layerTreeModel()->rootGroup()->findLayer( layerId );
307  if ( nodeLayer )
308  layerTreeModel()->refreshLayerLegend( nodeLayer );
309 }