QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
qgslayertreeviewdefaultactions.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslayertreeviewdefaultactions.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 
17 #include "qgsguiutils.h"
18 #include "qgsapplication.h"
19 #include "qgslayertree.h"
20 #include "qgslayertreemodel.h"
21 #include "qgslayertreeview.h"
22 #include "qgsmapcanvas.h"
23 #include "qgsproject.h"
24 #include "qgsvectorlayer.h"
25 
26 #include <QAction>
27 
29  : QObject( view )
30  , mView( view )
31 {
32 }
33 
35 {
36  QAction *a = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddGroup.svg" ) ), tr( "&Add Group" ), parent );
37  connect( a, &QAction::triggered, this, &QgsLayerTreeViewDefaultActions::addGroup );
38  return a;
39 }
40 
42 {
43  QAction *a = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionRemoveLayer.svg" ) ), tr( "&Remove" ), parent );
44  connect( a, &QAction::triggered, this, &QgsLayerTreeViewDefaultActions::removeGroupOrLayer );
45  return a;
46 }
47 
49 {
51  if ( !node )
52  return nullptr;
53 
54  QAction *a = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionInOverview.svg" ) ), tr( "&Show in Overview" ), parent );
55  connect( a, &QAction::triggered, this, &QgsLayerTreeViewDefaultActions::showInOverview );
56  a->setCheckable( true );
57  a->setChecked( node->customProperty( QStringLiteral( "overview" ), 0 ).toInt() );
58  return a;
59 }
60 
62 {
64  if ( !node )
65  return nullptr;
66 
67  QString text;
68  if ( QgsLayerTree::isGroup( node ) )
69  text = tr( "Re&name Group" );
70  else
71  text = tr( "Re&name Layer" );
72 
73  QAction *a = new QAction( text, parent );
74  connect( a, &QAction::triggered, this, &QgsLayerTreeViewDefaultActions::renameGroupOrLayer );
75  return a;
76 }
77 
79 {
81  if ( !node )
82  return nullptr;
83 
84  QAction *a = new QAction( tr( "Show Feature Count" ), parent );
85  connect( a, &QAction::triggered, this, &QgsLayerTreeViewDefaultActions::showFeatureCount );
86  a->setCheckable( true );
87  a->setChecked( node->customProperty( QStringLiteral( "showFeatureCount" ), 0 ).toInt() );
88  return a;
89 }
90 
92 {
93  QAction *a = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionZoomToLayer.svg" ) ),
94  tr( "&Zoom to Layer" ), parent );
95  a->setData( QVariant::fromValue( reinterpret_cast<void *>( canvas ) ) );
96  connect( a, &QAction::triggered, this, static_cast<void ( QgsLayerTreeViewDefaultActions::* )()>( &QgsLayerTreeViewDefaultActions::zoomToLayer ) );
97  return a;
98 }
99 
101 {
102  QAction *a = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionZoomToSelected.svg" ) ),
103  tr( "&Zoom to Selection" ), parent );
104  a->setData( QVariant::fromValue( reinterpret_cast<void *>( canvas ) ) );
105  connect( a, &QAction::triggered, this, static_cast<void ( QgsLayerTreeViewDefaultActions::* )()>( &QgsLayerTreeViewDefaultActions::zoomToSelection ) );
106  return a;
107 }
108 
110 {
111  QAction *a = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionZoomToLayer.svg" ) ),
112  tr( "&Zoom to Group" ), parent );
113  a->setData( QVariant::fromValue( reinterpret_cast<void *>( canvas ) ) );
114  connect( a, &QAction::triggered, this, static_cast<void ( QgsLayerTreeViewDefaultActions::* )()>( &QgsLayerTreeViewDefaultActions::zoomToGroup ) );
115  return a;
116 }
117 
119 {
120  QAction *a = new QAction( tr( "&Move to Top-level" ), parent );
122  connect( a, &QAction::triggered, this, &QgsLayerTreeViewDefaultActions::makeTopLevel );
124  return a;
125 }
126 
128 {
129  QAction *a = new QAction( tr( "Move Out of &Group" ), parent );
130  connect( a, &QAction::triggered, this, &QgsLayerTreeViewDefaultActions::moveOutOfGroup );
131  return a;
132 }
133 
135 {
136  QAction *a = new QAction( tr( "Move to &Top" ), parent );
137  connect( a, &QAction::triggered, this, &QgsLayerTreeViewDefaultActions::moveToTop );
138  return a;
139 }
140 
142 {
143  QAction *a = new QAction( tr( "&Group Selected" ), parent );
144  connect( a, &QAction::triggered, this, &QgsLayerTreeViewDefaultActions::groupSelected );
145  return a;
146 }
147 
149 {
151  if ( !node || !QgsLayerTree::isGroup( node ) )
152  return nullptr;
153 
154  QAction *a = new QAction( tr( "Mutually Exclusive Group" ), parent );
155  a->setCheckable( true );
156  a->setChecked( QgsLayerTree::toGroup( node )->isMutuallyExclusive() );
157  connect( a, &QAction::triggered, this, &QgsLayerTreeViewDefaultActions::mutuallyExclusiveGroup );
158  return a;
159 }
160 
162 {
164  if ( !node || !QgsLayerTree::isGroup( node ) || node->isItemVisibilityCheckedRecursive() )
165  return nullptr;
166 #ifdef Q_OS_MACX
167  QAction *a = new QAction( tr( "Check and All its Children (⌘-click)" ), parent );
168 #else
169  QAction *a = new QAction( tr( "Check and All its Children (Ctrl-click)" ), parent );
170 #endif
171  connect( a, &QAction::triggered, this, &QgsLayerTreeViewDefaultActions::checkAndAllChildren );
172  return a;
173 }
174 
176 {
178  if ( !node || !QgsLayerTree::isGroup( node ) || node->isItemVisibilityUncheckedRecursive() )
179  return nullptr;
180 #ifdef Q_OS_MACX
181  QAction *a = new QAction( tr( "Uncheck and All its Children (⌘-click)" ), parent );
182 #else
183  QAction *a = new QAction( tr( "Uncheck and All its Children (Ctrl-click)" ), parent );
184 #endif
185  connect( a, &QAction::triggered, this, &QgsLayerTreeViewDefaultActions::uncheckAndAllChildren );
186  return a;
187 }
188 
190 {
192  if ( !node || !QgsLayerTree::isLayer( node ) || node->isVisible() )
193  return nullptr;
194  QAction *a = new QAction( tr( "Check and All its Parents" ), parent );
195  connect( a, &QAction::triggered, this, &QgsLayerTreeViewDefaultActions::checkAndAllParents );
196  return a;
197 }
198 
199 void QgsLayerTreeViewDefaultActions::checkAndAllChildren()
200 {
202  if ( !node )
203  return;
204  node->setItemVisibilityCheckedRecursive( true );
205 }
206 
207 void QgsLayerTreeViewDefaultActions::uncheckAndAllChildren()
208 {
210  if ( !node )
211  return;
212  node->setItemVisibilityCheckedRecursive( false );
213 }
214 
215 void QgsLayerTreeViewDefaultActions::checkAndAllParents()
216 {
218  if ( !node )
219  return;
221 }
222 
224 {
226  if ( !group )
227  group = mView->layerTreeModel()->rootGroup();
228 
229  QgsLayerTreeGroup *newGroup = group->addGroup( uniqueGroupName( group ) );
230  mView->edit( mView->layerTreeModel()->node2index( newGroup ) );
231 }
232 
234 {
235  const auto constSelectedNodes = mView->selectedNodes( true );
236  for ( QgsLayerTreeNode *node : constSelectedNodes )
237  {
238  // could be more efficient if working directly with ranges instead of individual nodes
239  qobject_cast<QgsLayerTreeGroup *>( node->parent() )->removeChildNode( node );
240  }
241 }
242 
244 {
245  mView->edit( mView->currentIndex() );
246 }
247 
249 {
251  if ( !node )
252  return;
253  int newValue = node->customProperty( QStringLiteral( "overview" ), 0 ).toInt();
254  const auto constSelectedLayerNodes = mView->selectedLayerNodes();
255  for ( QgsLayerTreeLayer *l : constSelectedLayerNodes )
256  l->setCustomProperty( QStringLiteral( "overview" ), newValue ? 0 : 1 );
257 }
258 
260 {
262  if ( !QgsLayerTree::isLayer( node ) )
263  return;
264 
265  int newValue = node->customProperty( QStringLiteral( "showFeatureCount" ), 0 ).toInt();
266  const auto constSelectedLayerNodes = mView->selectedLayerNodes();
267  for ( QgsLayerTreeLayer *l : constSelectedLayerNodes )
268  l->setCustomProperty( QStringLiteral( "showFeatureCount" ), newValue ? 0 : 1 );
269 }
270 
271 
273 {
274  QgsMapLayer *layer = mView->currentLayer();
275  if ( !layer )
276  return;
277 
278  QList<QgsMapLayer *> layers;
279  layers << layer;
280  zoomToLayers( canvas, layers );
281 }
282 
284 {
285  QgsVectorLayer *layer = qobject_cast<QgsVectorLayer *>( mView->currentLayer() );
286  if ( !layer )
287  return;
288 
289  canvas->zoomToSelected( layer );
290 }
291 
293 {
294  QgsLayerTreeGroup *groupNode = mView->currentGroupNode();
295  if ( !groupNode )
296  return;
297 
298  QList<QgsMapLayer *> layers;
299  const auto constFindLayerIds = groupNode->findLayerIds();
300  for ( const QString &layerId : constFindLayerIds )
301  layers << QgsProject::instance()->mapLayer( layerId );
302 
303  zoomToLayers( canvas, layers );
304 }
305 
307 {
308  QAction *s = qobject_cast<QAction *>( sender() );
309  QgsMapCanvas *canvas = reinterpret_cast<QgsMapCanvas *>( s->data().value<void *>() );
310  QApplication::setOverrideCursor( Qt::WaitCursor );
311  zoomToLayer( canvas );
312  QApplication::restoreOverrideCursor();
313 }
314 
316 {
317  QAction *s = qobject_cast<QAction *>( sender() );
318  QgsMapCanvas *canvas = reinterpret_cast<QgsMapCanvas *>( s->data().value<void *>() );
319  QgsTemporaryCursorOverride waitCursor( Qt::WaitCursor );
320  zoomToSelection( canvas );
321 }
322 
324 {
325  QAction *s = qobject_cast<QAction *>( sender() );
326  QgsMapCanvas *canvas = reinterpret_cast<QgsMapCanvas *>( s->data().value<void *>() );
327  QApplication::setOverrideCursor( Qt::WaitCursor );
328  zoomToGroup( canvas );
329  QApplication::restoreOverrideCursor();
330 }
331 
332 
333 void QgsLayerTreeViewDefaultActions::zoomToLayers( QgsMapCanvas *canvas, const QList<QgsMapLayer *> &layers )
334 {
335  QgsRectangle extent;
336  extent.setMinimal();
337 
338  for ( int i = 0; i < layers.size(); ++i )
339  {
340  QgsMapLayer *layer = layers.at( i );
341  QgsRectangle layerExtent = layer->extent();
342 
343  QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( layer );
344  if ( vLayer )
345  {
346  if ( vLayer->geometryType() == QgsWkbTypes::NullGeometry )
347  continue;
348 
349  if ( layerExtent.isEmpty() )
350  {
351  vLayer->updateExtents();
352  layerExtent = vLayer->extent();
353  }
354  }
355 
356  if ( layerExtent.isNull() )
357  continue;
358 
359  //transform extent
360  layerExtent = canvas->mapSettings().layerExtentToOutputExtent( layer, layerExtent );
361 
362  extent.combineExtentWith( layerExtent );
363  }
364 
365  if ( extent.isNull() )
366  return;
367 
368  // Increase bounding box with 5%, so that layer is a bit inside the borders
369  extent.scale( 1.05 );
370 
371  //zoom to bounding box
372  canvas->setExtent( extent );
373  canvas->refresh();
374 }
375 
376 
378 {
379  QString prefix = parentGroup == mView->layerTreeModel()->rootGroup() ? "group" : "sub-group";
380  QString newName = prefix + '1';
381  for ( int i = 2; parentGroup->findGroup( newName ); ++i )
382  newName = prefix + QString::number( i );
383  return newName;
384 }
385 
386 
388 {
389  const auto constSelectedLayerNodes = mView->selectedLayerNodes();
390  for ( QgsLayerTreeLayer *l : constSelectedLayerNodes )
391  {
392  QgsLayerTreeGroup *rootGroup = mView->layerTreeModel()->rootGroup();
393  QgsLayerTreeGroup *parentGroup = qobject_cast<QgsLayerTreeGroup *>( l->parent() );
394  if ( !parentGroup || parentGroup == rootGroup )
395  continue;
396  QgsLayerTreeLayer *clonedLayer = l->clone();
397  rootGroup->addChildNode( clonedLayer );
398  parentGroup->removeChildNode( l );
399  }
400 }
401 
402 
404 {
405  const QList< QgsLayerTreeLayer * > selectedLayerNodes = mView->selectedLayerNodes();
406  for ( QgsLayerTreeLayer *l : selectedLayerNodes )
407  {
408  QgsLayerTreeGroup *rootGroup = mView->layerTreeModel()->rootGroup();
409  QgsLayerTreeGroup *parentGroup = qobject_cast<QgsLayerTreeGroup *>( l->parent() );
410  if ( !parentGroup || parentGroup == rootGroup )
411  continue;
412  QgsLayerTreeGroup *tempGroup = parentGroup;
413  while ( tempGroup->parent() != rootGroup )
414  {
415  tempGroup = qobject_cast<QgsLayerTreeGroup *>( tempGroup->parent() );
416  }
417  QgsLayerTreeLayer *clonedLayer = l->clone();
418  int insertIdx = rootGroup->children().indexOf( tempGroup );
419  rootGroup->insertChildNode( insertIdx, clonedLayer );
420  parentGroup->removeChildNode( l );
421  }
422 }
423 
424 
426 {
427  QMap <QgsLayerTreeGroup *, int> groupInsertIdx;
428  int insertIdx;
429  const QList< QgsLayerTreeNode * > selectedNodes = mView->selectedNodes();
430  for ( QgsLayerTreeNode *n : selectedNodes )
431  {
432  QgsLayerTreeGroup *parentGroup = qobject_cast<QgsLayerTreeGroup *>( n->parent() );
433  QgsLayerTreeNode *clonedNode = n->clone();
434  if ( groupInsertIdx.contains( parentGroup ) )
435  {
436  insertIdx = groupInsertIdx.value( parentGroup );
437  }
438  else
439  {
440  insertIdx = 0;
441  }
442  parentGroup->insertChildNode( insertIdx, clonedNode );
443  parentGroup->removeChildNode( n );
444  groupInsertIdx.insert( parentGroup, insertIdx + 1 );
445  }
446 }
447 
449 {
450  const QList<QgsLayerTreeNode *> nodes = mView->selectedNodes( true );
451  if ( nodes.count() < 2 || ! QgsLayerTree::isGroup( nodes[0]->parent() ) )
452  return;
453 
454  QgsLayerTreeGroup *parentGroup = QgsLayerTree::toGroup( nodes[0]->parent() );
455  int insertIdx = parentGroup->children().indexOf( nodes[0] );
456 
457  QgsLayerTreeGroup *newGroup = new QgsLayerTreeGroup( uniqueGroupName( parentGroup ) );
458  for ( QgsLayerTreeNode *node : nodes )
459  newGroup->addChildNode( node->clone() );
460 
461  parentGroup->insertChildNode( insertIdx, newGroup );
462 
463  for ( QgsLayerTreeNode *node : nodes )
464  {
465  QgsLayerTreeGroup *group = qobject_cast<QgsLayerTreeGroup *>( node->parent() );
466  if ( group )
467  group->removeChildNode( node );
468  }
469 
470  mView->setCurrentIndex( mView->layerTreeModel()->node2index( newGroup ) );
471  mView->edit( mView->layerTreeModel()->node2index( newGroup ) );
472 }
473 
475 {
477  if ( !node || !QgsLayerTree::isGroup( node ) )
478  return;
479 
480  QgsLayerTree::toGroup( node )->setIsMutuallyExclusive( !QgsLayerTree::toGroup( node )->isMutuallyExclusive() );
481 }
Layer tree group node serves as a container for layers and further groups.
A rectangle specified with double values.
Definition: qgsrectangle.h:41
Base class for all map layer types.
Definition: qgsmaplayer.h:79
The QgsLayerTreeView class extends QTreeView and provides some additional functionality when working ...
QgsLayerTreeGroup * addGroup(const QString &name)
Append a new group node with given name.
Temporarily sets a cursor override for the QApplication for the lifetime of the object.
Definition: qgsguiutils.h:203
void zoomToSelection()
Slot to zoom to selected features of a vector layer.
void setMinimal()
Set a rectangle so that min corner is at max and max corner is at min.
Definition: qgsrectangle.h:151
static bool isGroup(QgsLayerTreeNode *node)
Check whether the node is a valid group node.
Definition: qgslayertree.h:43
bool isItemVisibilityUncheckedRecursive() const
Returns whether this node is unchecked and all its children.
void setIsMutuallyExclusive(bool enabled, int initialChildIndex=-1)
Set whether the group is mutually exclusive (only one child can be checked at a time).
void zoomToLayers(QgsMapCanvas *canvas, const QList< QgsMapLayer *> &layers)
QAction * actionZoomToGroup(QgsMapCanvas *canvas, QObject *parent=nullptr)
virtual QgsLayerTreeNode * clone() const =0
Create a copy of the node. Returns new instance.
QAction * actionMoveOutOfGroup(QObject *parent=nullptr)
static QgsLayerTreeGroup * toGroup(QgsLayerTreeNode *node)
Cast node to a group.
Definition: qgslayertree.h:64
QAction * actionCheckAndAllChildren(QObject *parent=nullptr)
Action to check a group and all its children.
QgsLayerTreeViewDefaultActions(QgsLayerTreeView *view)
QAction * actionAddGroup(QObject *parent=nullptr)
void scale(double scaleFactor, const QgsPointXY *c=nullptr)
Scale the rectangle around its center point.
Definition: qgsrectangle.h:235
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:649
QAction * actionGroupSelected(QObject *parent=nullptr)
QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
QAction * actionRemoveGroupOrLayer(QObject *parent=nullptr)
void refresh()
Repaints the canvas map.
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
void removeChildNode(QgsLayerTreeNode *node)
Remove a child node from this group.
bool isVisible() const
Returns whether a node is really visible (ie checked and all its ancestors checked as well) ...
QgsMapLayer * currentLayer() const
Returns the currently selected layer, or nullptr if no layers is selected.
QModelIndex node2index(QgsLayerTreeNode *node) const
Returns index for a given node. If the node does not belong to the layer tree, the result is undefine...
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:75
virtual QgsRectangle extent() const
Returns the extent of the layer.
QList< QgsLayerTreeLayer * > selectedLayerNodes() const
Returns list of selected nodes filtered to just layer nodes.
void moveOutOfGroup()
Moves selected layer(s) out of the group(s) and places this/these above the group(s) ...
QAction * actionZoomToSelection(QgsMapCanvas *canvas, QObject *parent=nullptr)
Action to zoom to selected features of a vector layer.
The QgsLayerTreeViewDefaultActions class serves as a factory of actions that can be used together wit...
virtual void updateExtents(bool force=false)
Update the extents for the layer.
virtual void setItemVisibilityCheckedRecursive(bool checked)
Check or uncheck a node and all its children (taking into account exclusion rules) ...
QList< QgsLayerTreeNode * > children()
Gets list of children of the node. Children are owned by the parent.
bool isEmpty() const
Returns true if the rectangle is empty.
Definition: qgsrectangle.h:426
Q_DECL_DEPRECATED QAction * actionMakeTopLevel(QObject *parent=nullptr)
void mutuallyExclusiveGroup()
Slot to enable/disable mutually exclusive group flag.
QgsLayerTreeNode * parent()
Gets pointer to the parent. If parent is nullptr, the node is a root node.
QgsLayerTreeGroup * currentGroupNode() const
Gets current group node. If a layer is current node, the function will return parent group...
QAction * actionCheckAndAllParents(QObject *parent=nullptr)
Action to check a group and all its parents.
QVariant customProperty(const QString &key, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer. Properties are stored in a map and saved in project file...
QgsRectangle layerExtentToOutputExtent(const QgsMapLayer *layer, QgsRectangle extent) const
transform bounding box from layer&#39;s CRS to output CRS
static bool isLayer(const QgsLayerTreeNode *node)
Check whether the node is a valid layer node.
Definition: qgslayertree.h:53
This class is a base class for nodes in a layer tree.
QgsRectangle extent() const FINAL
Returns the extent of the layer.
QgsLayerTreeModel * layerTreeModel() const
Gets access to the model casted to QgsLayerTreeModel.
void zoomToSelected(QgsVectorLayer *layer=nullptr)
Zoom to the extent of the selected features of provided (vector) layer.
void setItemVisibilityCheckedParentRecursive(bool checked)
Check or uncheck a node and all its parents.
bool isItemVisibilityCheckedRecursive() const
Returns whether this node is checked and all its children.
QAction * actionZoomToLayer(QgsMapCanvas *canvas, QObject *parent=nullptr)
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle...
Definition: qgsrectangle.h:359
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:650
QAction * actionMutuallyExclusiveGroup(QObject *parent=nullptr)
Action to enable/disable mutually exclusive flag of a group (only one child node may be checked) ...
QList< QgsLayerTreeNode * > selectedNodes(bool skipInternal=false) const
Returns list of selected nodes.
void insertChildNode(int index, QgsLayerTreeNode *node)
Insert existing node at specified position.
QgsLayerTree * rootGroup() const
Returns pointer to the root node of the layer tree. Always a non nullptr value.
QgsLayerTreeGroup * findGroup(const QString &name)
Find group node with specified name.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:442
QString uniqueGroupName(QgsLayerTreeGroup *parentGroup)
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
Definition: qgsrectangle.h:436
void addChildNode(QgsLayerTreeNode *node)
Append an existing node.
void setExtent(const QgsRectangle &r, bool magnified=false)
Sets the extent of the map canvas.
QAction * actionMoveToTop(QObject *parent=nullptr)
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
QStringList findLayerIds() const
Find layer IDs used in all layer nodes.
QAction * actionShowFeatureCount(QObject *parent=nullptr)
QAction * actionRenameGroupOrLayer(QObject *parent=nullptr)
Represents a vector layer which manages a vector based data sets.
QAction * actionUncheckAndAllChildren(QObject *parent=nullptr)
Action to uncheck a group and all its children.
QgsLayerTreeLayer * clone() const override
Create a copy of the node. Returns new instance.
QAction * actionShowInOverview(QObject *parent=nullptr)
Layer tree node points to a map layer.
void moveToTop()
Moves selected layer(s) and/or group(s) to the top of the layer panel or the top of the group if the ...
QgsLayerTreeNode * currentNode() const
Gets current node. May be nullptr.