QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
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( "/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( "/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( "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( "showFeatureCount", 0 ).toInt() );
78  return a;
79 }
80 
82 {
83  QAction* a = new QAction( QgsApplication::getThemeIcon( "/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( "/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( "overview", 0 ).toInt();
156  Q_FOREACH ( QgsLayerTreeLayer* l, mView->selectedLayerNodes() )
157  l->setCustomProperty( "overview", newValue ? 0 : 1 );
158 }
159 
161 {
163  if ( !QgsLayerTree::isLayer( node ) )
164  return;
165 
166  int newValue = node->customProperty( "showFeatureCount", 0 ).toInt();
167  Q_FOREACH ( QgsLayerTreeLayer* l, mView->selectedLayerNodes() )
168  l->setCustomProperty( "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 );
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 );
212 }
213 
214 
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() == QGis::NoGeometry )
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 {
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 
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 setCurrentIndex(const QModelIndex &index)
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.
QObject * sender() const
QgsMapLayer * mapLayer(const QString &theLayerId) const
Retrieve a pointer to a registered layer by layer ID.
void setChecked(bool)
QgsLayerTreeViewDefaultActions(QgsLayerTreeView *view)
QVariant data() const
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.
const T & at(int i) const
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)
T value() const
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...
QString tr(const char *sourceText, const char *disambiguation, int n)
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:109
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
int size() const
QList< QgsLayerTreeLayer * > selectedLayerNodes() const
Return list of selected nodes filtered to just layer nodes.
virtual void updateExtents()
Update the extents for the layer.
int indexOf(const T &value, int from) const
QString number(int n, int base)
int count(const T &value) const
QgsRectangle extent() override
Return the extent of the layer.
int toInt(bool *ok) const
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.
void setOverrideCursor(const QCursor &cursor)
void restoreOverrideCursor()
This class is a base class for nodes in a layer tree.
QGis::GeometryType geometryType() const
Returns point, line or polygon.
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 setData(const QVariant &userData)
QgsLayerTreeModel * layerTreeModel() const
Get access to the model casted to QgsLayerTreeModel.
QVariant fromValue(const T &value)
void setCheckable(bool)
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.
void edit(const QModelIndex &index)
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)
QModelIndex currentIndex() const
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const
virtual QgsRectangle extent()
Return the extent of the layer.
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.
Layer tree node points to a map layer.
QgsLayerTreeNode * currentNode() const
Get current node. May be null.