QGIS API Documentation  2.99.0-Master (37c43df)
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 
18 #include "qgsapplication.h"
19 #include "qgslayertree.h"
20 #include "qgslayertreemodel.h"
21 #include "qgslayertreeview.h"
22 #include "qgsmapcanvas.h"
23 #include "qgsmaplayerregistry.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, SIGNAL( triggered() ), this, SLOT( addGroup() ) );
38  return a;
39 }
40 
42 {
43  QAction* a = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionRemoveLayer.svg" ) ), tr( "&Remove" ), parent );
44  connect( a, SIGNAL( triggered() ), this, SLOT( removeGroupOrLayer() ) );
45  return a;
46 }
47 
49 {
51  if ( !node )
52  return nullptr;
53 
54  QAction* a = new QAction( tr( "&Show in Overview" ), parent );
55  connect( a, SIGNAL( triggered() ), this, SLOT( showInOverview() ) );
56  a->setCheckable( true );
57  a->setChecked( node->customProperty( QStringLiteral( "overview" ), 0 ).toInt() );
58  return a;
59 }
60 
62 {
63  QAction* a = new QAction( tr( "Re&name" ), parent );
64  connect( a, SIGNAL( triggered() ), this, SLOT( renameGroupOrLayer() ) );
65  return a;
66 }
67 
69 {
71  if ( !node )
72  return nullptr;
73 
74  QAction* a = new QAction( tr( "Show Feature Count" ), parent );
75  connect( a, SIGNAL( triggered() ), this, SLOT( showFeatureCount() ) );
76  a->setCheckable( true );
77  a->setChecked( node->customProperty( QStringLiteral( "showFeatureCount" ), 0 ).toInt() );
78  return a;
79 }
80 
82 {
83  QAction* a = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionZoomToLayer.svg" ) ),
84  tr( "&Zoom to Layer" ), parent );
85  a->setData( QVariant::fromValue( reinterpret_cast<void*>( canvas ) ) );
86  connect( a, SIGNAL( triggered() ), this, SLOT( zoomToLayer() ) );
87  return a;
88 }
89 
91 {
92  QAction* a = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionZoomToLayer.svg" ) ),
93  tr( "&Zoom to Group" ), parent );
94  a->setData( QVariant::fromValue( reinterpret_cast<void*>( canvas ) ) );
95  connect( a, SIGNAL( triggered() ), this, SLOT( zoomToGroup() ) );
96  return a;
97 }
98 
100 {
101  QAction* a = new QAction( tr( "&Move to Top-level" ), parent );
102  connect( a, SIGNAL( triggered() ), this, SLOT( makeTopLevel() ) );
103  return a;
104 }
105 
107 {
108  QAction* a = new QAction( tr( "&Group Selected" ), parent );
109  connect( a, SIGNAL( triggered() ), this, SLOT( groupSelected() ) );
110  return a;
111 }
112 
114 {
116  if ( !node || !QgsLayerTree::isGroup( node ) )
117  return nullptr;
118 
119  QAction* a = new QAction( tr( "Mutually Exclusive Group" ), parent );
120  a->setCheckable( true );
121  a->setChecked( QgsLayerTree::toGroup( node )->isMutuallyExclusive() );
122  connect( a, SIGNAL( triggered() ), this, SLOT( mutuallyExclusiveGroup() ) );
123  return a;
124 }
125 
127 {
129  if ( !group )
130  group = mView->layerTreeModel()->rootGroup();
131 
132  QgsLayerTreeGroup* newGroup = group->addGroup( uniqueGroupName( group ) );
133  mView->edit( mView->layerTreeModel()->node2index( newGroup ) );
134 }
135 
137 {
138  Q_FOREACH ( QgsLayerTreeNode* node, mView->selectedNodes( true ) )
139  {
140  // could be more efficient if working directly with ranges instead of individual nodes
141  qobject_cast<QgsLayerTreeGroup*>( node->parent() )->removeChildNode( node );
142  }
143 }
144 
146 {
147  mView->edit( mView->currentIndex() );
148 }
149 
151 {
153  if ( !node )
154  return;
155  int newValue = node->customProperty( QStringLiteral( "overview" ), 0 ).toInt();
156  Q_FOREACH ( QgsLayerTreeLayer* l, mView->selectedLayerNodes() )
157  l->setCustomProperty( QStringLiteral( "overview" ), newValue ? 0 : 1 );
158 }
159 
161 {
163  if ( !QgsLayerTree::isLayer( node ) )
164  return;
165 
166  int newValue = node->customProperty( QStringLiteral( "showFeatureCount" ), 0 ).toInt();
167  Q_FOREACH ( QgsLayerTreeLayer* l, mView->selectedLayerNodes() )
168  l->setCustomProperty( QStringLiteral( "showFeatureCount" ), newValue ? 0 : 1 );
169 }
170 
171 
173 {
174  QgsMapLayer* layer = mView->currentLayer();
175  if ( !layer )
176  return;
177 
178  QList<QgsMapLayer*> layers;
179  layers << layer;
180  zoomToLayers( canvas, layers );
181 }
182 
184 {
185  QgsLayerTreeGroup* groupNode = mView->currentGroupNode();
186  if ( !groupNode )
187  return;
188 
189  QList<QgsMapLayer*> layers;
190  Q_FOREACH ( const QString& layerId, groupNode->findLayerIds() )
191  layers << QgsMapLayerRegistry::instance()->mapLayer( layerId );
192 
193  zoomToLayers( canvas, layers );
194 }
195 
197 {
198  QAction* s = qobject_cast<QAction*>( sender() );
199  QgsMapCanvas* canvas = reinterpret_cast<QgsMapCanvas*>( s->data().value<void*>() );
200  QApplication::setOverrideCursor( Qt::WaitCursor );
201  zoomToLayer( canvas );
202  QApplication::restoreOverrideCursor();
203 }
204 
206 {
207  QAction* s = qobject_cast<QAction*>( sender() );
208  QgsMapCanvas* canvas = reinterpret_cast<QgsMapCanvas*>( s->data().value<void*>() );
209  QApplication::setOverrideCursor( Qt::WaitCursor );
210  zoomToGroup( canvas );
211  QApplication::restoreOverrideCursor();
212 }
213 
214 
215 void QgsLayerTreeViewDefaultActions::zoomToLayers( QgsMapCanvas* canvas, const QList<QgsMapLayer*>& layers )
216 {
217  QgsRectangle extent;
218  extent.setMinimal();
219 
220  for ( int i = 0; i < layers.size(); ++i )
221  {
222  QgsMapLayer* layer = layers.at( i );
223  QgsRectangle layerExtent = layer->extent();
224 
225  QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer*>( layer );
226  if ( vLayer )
227  {
228  if ( vLayer->geometryType() == QgsWkbTypes::NullGeometry )
229  continue;
230 
231  if ( layerExtent.isEmpty() )
232  {
233  vLayer->updateExtents();
234  layerExtent = vLayer->extent();
235  }
236  }
237 
238  if ( layerExtent.isNull() )
239  continue;
240 
241  //transform extent if otf-projection is on
242  if ( canvas->hasCrsTransformEnabled() )
243  layerExtent = canvas->mapSettings().layerExtentToOutputExtent( layer, layerExtent );
244 
245  extent.combineExtentWith( layerExtent );
246  }
247 
248  if ( extent.isNull() )
249  return;
250 
251  // Increase bounding box with 5%, so that layer is a bit inside the borders
252  extent.scale( 1.05 );
253 
254  //zoom to bounding box
255  canvas->setExtent( extent );
256  canvas->refresh();
257 }
258 
259 
261 {
262  QString prefix = parentGroup == mView->layerTreeModel()->rootGroup() ? "group" : "sub-group";
263  QString newName = prefix + '1';
264  for ( int i = 2; parentGroup->findGroup( newName ); ++i )
265  newName = prefix + QString::number( i );
266  return newName;
267 }
268 
269 
271 {
272  Q_FOREACH ( QgsLayerTreeLayer* l, mView->selectedLayerNodes() )
273  {
274  QgsLayerTreeGroup* rootGroup = mView->layerTreeModel()->rootGroup();
275  QgsLayerTreeGroup* parentGroup = qobject_cast<QgsLayerTreeGroup*>( l->parent() );
276  if ( !parentGroup || parentGroup == rootGroup )
277  continue;
278  QgsLayerTreeLayer* clonedLayer = l->clone();
279  rootGroup->addChildNode( clonedLayer );
280  parentGroup->removeChildNode( l );
281  }
282 }
283 
284 
286 {
287  QList<QgsLayerTreeNode*> nodes = mView->selectedNodes( true );
288  if ( nodes.count() < 2 || ! QgsLayerTree::isGroup( nodes[0]->parent() ) )
289  return;
290 
291  QgsLayerTreeGroup* parentGroup = QgsLayerTree::toGroup( nodes[0]->parent() );
292  int insertIdx = parentGroup->children().indexOf( nodes[0] );
293 
294  QgsLayerTreeGroup* newGroup = new QgsLayerTreeGroup( uniqueGroupName( parentGroup ) );
295  Q_FOREACH ( QgsLayerTreeNode* node, nodes )
296  newGroup->addChildNode( node->clone() );
297 
298  parentGroup->insertChildNode( insertIdx, newGroup );
299 
300  Q_FOREACH ( QgsLayerTreeNode* node, nodes )
301  {
302  QgsLayerTreeGroup* group = qobject_cast<QgsLayerTreeGroup*>( node->parent() );
303  if ( group )
304  group->removeChildNode( node );
305  }
306 
307  mView->setCurrentIndex( mView->layerTreeModel()->node2index( newGroup ) );
308 }
309 
311 {
313  if ( !node || !QgsLayerTree::isGroup( node ) )
314  return;
315 
316  QgsLayerTree::toGroup( node )->setIsMutuallyExclusive( !QgsLayerTree::toGroup( node )->isMutuallyExclusive() );
317 }
Layer tree group node serves as a container for layers and further groups.
A rectangle specified with double values.
Definition: qgsrectangle.h:35
Base class for all map layer types.
Definition: qgsmaplayer.h:49
QgsLayerTreeGroup * rootGroup() const
Return pointer to the root node of the layer tree. Always a non-null pointer.
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. Newly created node is owned by this group.
void setMinimal()
Set a rectangle so that min corner is at max and max corner is at min.
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.
QgsMapLayer * mapLayer(const QString &theLayerId) const
Retrieve a pointer to a registered layer by layer ID.
QgsLayerTreeViewDefaultActions(QgsLayerTreeView *view)
QAction * actionAddGroup(QObject *parent=nullptr)
QgsRectangle layerExtentToOutputExtent(QgsMapLayer *theLayer, QgsRectangle extent) const
transform bounding box from layer&#39;s CRS to output CRS
static QIcon getThemeIcon(const QString &theName)
Helper to get a theme icon.
void scale(double scaleFactor, const QgsPoint *c=nullptr)
Scale the rectangle around its center point.
bool hasCrsTransformEnabled()
A simple helper method to find out if on the fly projections are enabled or not.
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.
void removeChildNode(QgsLayerTreeNode *node)
Remove a child node from this group. The node will be deleted.
QgsMapLayer * currentLayer() const
Get currently selected layer. May be null.
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...
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:106
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
virtual QgsRectangle extent() const
Returns the extent of the layer.
QList< QgsLayerTreeLayer * > selectedLayerNodes() const
Return list of selected nodes filtered to just layer nodes.
virtual void updateExtents()
Update the extents for the layer.
QgsRectangle extent() const override
Return the extent of the layer.
bool isEmpty() const
test if rectangle is empty.
QAction * actionMakeTopLevel(QObject *parent=nullptr)
void mutuallyExclusiveGroup()
Slot to enable/disable mutually exclusive group flag.
QgsLayerTreeNode * parent()
Get pointer to the parent. If parent is a null pointer, the node is a root node.
QgsLayerTreeGroup * currentGroupNode() const
Get current group node. If a layer is current node, the function will return parent group...
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...
This class is a base class for nodes in a layer tree.
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
QgsLayerTreeModel * layerTreeModel() const
Get access to the model casted to QgsLayerTreeModel.
QAction * actionZoomToLayer(QgsMapCanvas *canvas, QObject *parent=nullptr)
const QgsMapSettings & mapSettings() const
Get access to properties used for map rendering.
void combineExtentWith(const QgsRectangle &rect)
expand the rectangle so that covers both the original rectangle and the given rectangle ...
QAction * actionMutuallyExclusiveGroup(QObject *parent=nullptr)
Action to enable/disable mutually exclusive flag of a group (only one child node may be checked) ...
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
QList< QgsLayerTreeNode * > selectedNodes(bool skipInternal=false) const
Return list of selected nodes.
void insertChildNode(int index, QgsLayerTreeNode *node)
Insert existing node at specified position. The node must not have a parent yet. The node will be own...
QgsLayerTreeGroup * findGroup(const QString &name)
Find group node with specified name. Searches recursively the whole sub-tree.
QString uniqueGroupName(QgsLayerTreeGroup *parentGroup)
bool isNull() const
test if the rectangle is null (all coordinates zero or after call to setMinimal()).
void addChildNode(QgsLayerTreeNode *node)
Append an existing node. The node must not have a parent yet. The node will be owned by this group...
void setExtent(const QgsRectangle &r, bool magnified=false)
Set the extent of the map canvas.
QStringList findLayerIds() const
Find layer IDs used in all layer nodes. Searches recursively the whole sub-tree.
QAction * actionShowFeatureCount(QObject *parent=nullptr)
QAction * actionRenameGroupOrLayer(QObject *parent=nullptr)
Represents a vector layer which manages a vector based data sets.
bool isGroup(QgsLayerTreeNode *node)
Check whether the node is a valid group node.
Definition: qgslayertree.h:34
virtual QgsLayerTreeLayer * clone() const override
Create a copy of the node. Returns new instance.
QAction * actionShowInOverview(QObject *parent=nullptr)
void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for the node. Properties are stored in a map and saved in project file...
Layer tree node points to a map layer.
QgsLayerTreeNode * currentNode() const
Get current node. May be null.