QGIS API Documentation  2.12.0-Lyon
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 0;
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 0;
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 0;
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 
156  node->setCustomProperty( "overview", node->customProperty( "overview", 0 ).toInt() ? 0 : 1 );
157 }
158 
160 {
162  if ( !QgsLayerTree::isLayer( node ) )
163  return;
164 
165 
166  node->setCustomProperty( "showFeatureCount", node->customProperty( "showFeatureCount", 0 ).toInt() ? 0 : 1 );
167 }
168 
169 
171 {
172  QgsMapLayer* layer = mView->currentLayer();
173  if ( !layer )
174  return;
175 
176  QList<QgsMapLayer*> layers;
177  layers << layer;
178  zoomToLayers( canvas, layers );
179 }
180 
182 {
183  QgsLayerTreeGroup* groupNode = mView->currentGroupNode();
184  if ( !groupNode )
185  return;
186 
187  QList<QgsMapLayer*> layers;
188  Q_FOREACH ( const QString& layerId, groupNode->findLayerIds() )
189  layers << QgsMapLayerRegistry::instance()->mapLayer( layerId );
190 
191  zoomToLayers( canvas, layers );
192 }
193 
195 {
196  QAction* s = qobject_cast<QAction*>( sender() );
197  QgsMapCanvas* canvas = reinterpret_cast<QgsMapCanvas*>( s->data().value<void*>() );
198  zoomToLayer( canvas );
199 }
200 
202 {
203  QAction* s = qobject_cast<QAction*>( sender() );
204  QgsMapCanvas* canvas = reinterpret_cast<QgsMapCanvas*>( s->data().value<void*>() );
205  zoomToGroup( canvas );
206 }
207 
208 
210 {
211  QgsRectangle extent;
212  extent.setMinimal();
213 
214  for ( int i = 0; i < layers.size(); ++i )
215  {
216  QgsMapLayer* layer = layers.at( i );
217  QgsRectangle layerExtent = layer->extent();
218 
219  QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer*>( layer );
220  if ( vLayer )
221  {
222  if ( vLayer->geometryType() == QGis::NoGeometry )
223  continue;
224 
225  if ( layerExtent.isEmpty() )
226  {
227  vLayer->updateExtents();
228  layerExtent = vLayer->extent();
229  }
230  }
231 
232  if ( layerExtent.isNull() )
233  continue;
234 
235  //transform extent if otf-projection is on
236  if ( canvas->hasCrsTransformEnabled() )
237  layerExtent = canvas->mapSettings().layerExtentToOutputExtent( layer, layerExtent );
238 
239  extent.combineExtentWith( &layerExtent );
240  }
241 
242  if ( extent.isNull() )
243  return;
244 
245  // Increase bounding box with 5%, so that layer is a bit inside the borders
246  extent.scale( 1.05 );
247 
248  //zoom to bounding box
249  canvas->setExtent( extent );
250  canvas->refresh();
251 }
252 
253 
255 {
256  QString prefix = parentGroup == mView->layerTreeModel()->rootGroup() ? "group" : "sub-group";
257  QString newName = prefix + "1";
258  for ( int i = 2; parentGroup->findGroup( newName ); ++i )
259  newName = prefix + QString::number( i );
260  return newName;
261 }
262 
263 
265 {
267  if ( !node )
268  return;
269 
270  QgsLayerTreeGroup* rootGroup = mView->layerTreeModel()->rootGroup();
271  QgsLayerTreeGroup* parentGroup = qobject_cast<QgsLayerTreeGroup*>( node->parent() );
272  if ( !parentGroup || parentGroup == rootGroup )
273  return;
274 
275  QgsLayerTreeNode* clonedNode = node->clone();
276  rootGroup->addChildNode( clonedNode );
277  parentGroup->removeChildNode( node );
278 }
279 
280 
282 {
284  if ( nodes.count() < 2 || ! QgsLayerTree::isGroup( nodes[0]->parent() ) )
285  return;
286 
287  QgsLayerTreeGroup* parentGroup = QgsLayerTree::toGroup( nodes[0]->parent() );
288  int insertIdx = parentGroup->children().indexOf( nodes[0] );
289 
290  QgsLayerTreeGroup* newGroup = new QgsLayerTreeGroup( uniqueGroupName( parentGroup ) );
291  Q_FOREACH ( QgsLayerTreeNode* node, nodes )
292  newGroup->addChildNode( node->clone() );
293 
294  parentGroup->insertChildNode( insertIdx, newGroup );
295 
296  Q_FOREACH ( QgsLayerTreeNode* node, nodes )
297  {
298  QgsLayerTreeGroup* group = qobject_cast<QgsLayerTreeGroup*>( node->parent() );
299  if ( group )
300  group->removeChildNode( node );
301  }
302 
304 }
305 
307 {
309  if ( !node || !QgsLayerTree::isGroup( node ) )
310  return;
311 
312  QgsLayerTree::toGroup( node )->setIsMutuallyExclusive( !QgsLayerTree::toGroup( node )->isMutuallyExclusive() );
313 }
Layer tree group node serves as a container for layers and further groups.
QgsLayerTreeModel * layerTreeModel() const
Get access to the model casted to QgsLayerTreeModel.
A rectangle specified with double values.
Definition: qgsrectangle.h:35
Base class for all map layer types.
Definition: qgsmaplayer.h:49
The QgsLayerTreeView class extends QTreeView and provides some additional functionality when working ...
bool isEmpty() const
test if rectangle is empty.
QgsLayerTreeGroup * addGroup(const QString &name)
Append a new group node with given name. Newly created node is owned by this group.
QgsMapLayer * currentLayer() const
Get currently selected layer. May be null.
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)
QgsLayerTreeGroup * rootGroup() const
Return pointer to the root node of the layer tree. Always a non-null pointer.
QVariant customProperty(const QString &key, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer.
virtual QgsLayerTreeNode * clone() const =0
Create a copy of the node. Returns new instance.
QObject * sender() const
void setChecked(bool)
QAction * actionShowFeatureCount(QObject *parent=0)
QgsLayerTreeViewDefaultActions(QgsLayerTreeView *view)
QVariant data() const
static QIcon getThemeIcon(const QString &theName)
Helper to get a theme icon.
void setExtent(const QgsRectangle &r)
Set the extent of the map canvas.
const T & at(int i) const
bool isNull() const
test if the rectangle is null (all coordinates zero or after call to setMinimal()).
bool hasCrsTransformEnabled()
A simple helper method to find out if on the fly projections are enabled or not.
QgsLayerTreeNode * currentNode() const
Get current node. May be null.
T value() const
const QgsMapSettings & mapSettings() const
Get access to properties used for map rendering.
QgsRectangle layerExtentToOutputExtent(QgsMapLayer *theLayer, QgsRectangle extent) const
transform bounding box from layer's CRS to output CRS
void refresh()
Repaints the canvas map.
void removeChildNode(QgsLayerTreeNode *node)
Remove a child node from this group. The node will be deleted.
QString tr(const char *sourceText, const char *disambiguation, int n)
QList< QgsLayerTreeNode * > selectedNodes(bool skipInternal=false) const
Return list of selected nodes.
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:107
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
QgsMapLayer * mapLayer(const QString &theLayerId)
Retrieve a pointer to a loaded layer by id.
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
void combineExtentWith(QgsRectangle *rect)
expand the rectangle so that covers both the original rectangle and the given rectangle ...
QgsRectangle extent() override
Return the extent of the layer.
int toInt(bool *ok) const
QAction * actionGroupSelected(QObject *parent=0)
void mutuallyExclusiveGroup()
Slot to enable/disable mutually exclusive group flag.
QgsLayerTreeGroup * currentGroupNode() const
Get current group node. If a layer is current node, the function will return parent group...
QgsLayerTreeNode * parent()
Get pointer to the parent. If parent is a null pointer, the node is a root node.
QAction * actionShowInOverview(QObject *parent=0)
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)
QVariant fromValue(const T &value)
void setCheckable(bool)
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...
QAction * actionRemoveGroupOrLayer(QObject *parent=0)
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
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...
QAction * actionZoomToGroup(QgsMapCanvas *canvas, QObject *parent=0)
QStringList findLayerIds() const
Find layer IDs used in all layer nodes. Searches recursively the whole sub-tree.
QgsLayerTreeGroup * findGroup(const QString &name)
Find group node with specified name. Searches recursively the whole sub-tree.
QString uniqueGroupName(QgsLayerTreeGroup *parentGroup)
void zoomToLayers(QgsMapCanvas *canvas, const QList< QgsMapLayer * > &layers)
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 edit(const QModelIndex &index)
QAction * actionRenameGroupOrLayer(QObject *parent=0)
QAction * actionMutuallyExclusiveGroup(QObject *parent=0)
Action to enable/disable mutually exclusive flag of a group (only one child node may be checked) ...
QModelIndex currentIndex() const
QAction * actionMakeTopLevel(QObject *parent=0)
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QAction * actionZoomToLayer(QgsMapCanvas *canvas, QObject *parent=0)
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
void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for the node.
void scale(double scaleFactor, const QgsPoint *c=0)
Scale the rectangle around its center point.