QGIS API Documentation  3.2.0-Bonn (bc43194)
qgslayertreemapcanvasbridge.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslayertreemapcanvasbridge.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 "qgslayertree.h"
19 #include "qgslayertreeutils.h"
20 #include "qgsmaplayer.h"
21 #include "qgsvectorlayer.h"
22 #include "qgsmapcanvas.h"
23 #include "qgsmapoverviewcanvas.h"
24 #include "qgsproject.h"
25 
27  : QObject( parent )
28  , mRoot( root )
29  , mCanvas( canvas )
30  , mPendingCanvasUpdate( false )
31  , mAutoSetupOnFirstLayer( true )
32  , mLastLayerCount( !root->findLayers().isEmpty() )
33 {
34  connect( root, &QgsLayerTreeGroup::customPropertyChanged, this, &QgsLayerTreeMapCanvasBridge::nodeCustomPropertyChanged );
35  connect( root, &QgsLayerTreeNode::visibilityChanged, this, &QgsLayerTreeMapCanvasBridge::nodeVisibilityChanged );
36  connect( root, &QgsLayerTree::layerOrderChanged, this, &QgsLayerTreeMapCanvasBridge::deferredSetCanvasLayers );
37 
39 }
40 
42 {
43  QList<QgsMapLayer *> canvasLayers, overviewLayers, allLayerOrder;
44 
45  if ( mRoot->hasCustomLayerOrder() )
46  {
47  Q_FOREACH ( QgsMapLayer *layer, mRoot->customLayerOrder() )
48  {
49  QgsLayerTreeLayer *nodeLayer = mRoot->findLayer( layer->id() );
50  if ( nodeLayer )
51  {
52  if ( !nodeLayer->layer()->isSpatial() )
53  continue;
54 
55  allLayerOrder << nodeLayer->layer();
56  if ( nodeLayer->isVisible() )
57  canvasLayers << nodeLayer->layer();
58  if ( nodeLayer->customProperty( QStringLiteral( "overview" ), 0 ).toInt() )
59  overviewLayers << nodeLayer->layer();
60  }
61  }
62  }
63  else
64  setCanvasLayers( mRoot, canvasLayers, overviewLayers, allLayerOrder );
65 
66  QList<QgsLayerTreeLayer *> layerNodes = mRoot->findLayers();
67  int currentLayerCount = layerNodes.count();
68  bool firstLayers = mAutoSetupOnFirstLayer && mLastLayerCount == 0 && currentLayerCount != 0;
69 
70  mCanvas->setLayers( canvasLayers );
71  if ( mOverviewCanvas )
72  mOverviewCanvas->setLayers( overviewLayers );
73 
74  if ( firstLayers )
75  {
76  // if we are moving from zero to non-zero layers, let's zoom to those data
77  mCanvas->zoomToFullExtent();
78  }
79 
80  if ( !mFirstCRS.isValid() )
81  {
82  // find out what is the first used CRS in case we may need to turn on OTF projections later
83  Q_FOREACH ( QgsLayerTreeLayer *layerNode, layerNodes )
84  {
85  if ( layerNode->layer() && layerNode->layer()->crs().isValid() )
86  {
87  mFirstCRS = layerNode->layer()->crs();
88  break;
89  }
90  }
91  }
92 
93  if ( mFirstCRS.isValid() && firstLayers )
94  {
95  QgsProject::instance()->setCrs( mFirstCRS );
96  }
97 
98  mLastLayerCount = currentLayerCount;
99  if ( currentLayerCount == 0 )
100  mFirstCRS = QgsCoordinateReferenceSystem();
101 
102  mPendingCanvasUpdate = false;
103 
104  emit canvasLayersChanged( canvasLayers );
105 }
106 
107 void QgsLayerTreeMapCanvasBridge::setCanvasLayers( QgsLayerTreeNode *node, QList<QgsMapLayer *> &canvasLayers, QList<QgsMapLayer *> &overviewLayers, QList<QgsMapLayer *> &allLayers )
108 {
109  if ( QgsLayerTree::isLayer( node ) )
110  {
111  QgsLayerTreeLayer *nodeLayer = QgsLayerTree::toLayer( node );
112  if ( nodeLayer->layer() && nodeLayer->layer()->isSpatial() )
113  {
114  allLayers << nodeLayer->layer();
115  if ( nodeLayer->isVisible() )
116  canvasLayers << nodeLayer->layer();
117  if ( nodeLayer->customProperty( QStringLiteral( "overview" ), 0 ).toInt() )
118  overviewLayers << nodeLayer->layer();
119  }
120  }
121 
122  Q_FOREACH ( QgsLayerTreeNode *child, node->children() )
123  setCanvasLayers( child, canvasLayers, overviewLayers, allLayers );
124 }
125 
126 void QgsLayerTreeMapCanvasBridge::deferredSetCanvasLayers()
127 {
128  if ( mPendingCanvasUpdate )
129  return;
130 
131  mPendingCanvasUpdate = true;
132  QMetaObject::invokeMethod( this, "setCanvasLayers", Qt::QueuedConnection );
133 }
134 
135 void QgsLayerTreeMapCanvasBridge::nodeVisibilityChanged()
136 {
137  deferredSetCanvasLayers();
138 }
139 
140 void QgsLayerTreeMapCanvasBridge::nodeCustomPropertyChanged( QgsLayerTreeNode *node, const QString &key )
141 {
142  Q_UNUSED( node );
143  if ( key == QLatin1String( "overview" ) )
144  deferredSetCanvasLayers();
145 }
static QgsLayerTreeLayer * toLayer(QgsLayerTreeNode *node)
Cast node to a layer.
Definition: qgslayertree.h:75
Base class for all map layer types.
Definition: qgsmaplayer.h:61
void layerOrderChanged()
Emitted when the layer order has changed.
bool isVisible() const
Returns whether a node is really visible (ie checked and all its ancestors checked as well) ...
Q_INVOKABLE void setCanvasLayers()
force update of canvas layers from the layer tree. Normally this should not be needed to be called...
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:74
QList< QgsMapLayer * > customLayerOrder() const
The order in which layers will be rendered on the canvas.
QString id() const
Returns the layer&#39;s unique ID, which is used to access this layer from QgsProject.
QList< QgsLayerTreeNode * > children()
Gets list of children of the node. Children are owned by the parent.
Namespace with helper functions for layer tree operations.
Definition: qgslayertree.h:32
void setLayers(const QList< QgsMapLayer *> &layers)
updates layer set for overview
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...
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the project&#39;s native coordinate reference system.
Definition: qgsproject.cpp:520
QgsCoordinateReferenceSystem crs() const
Returns the layer&#39;s spatial reference system.
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.
bool hasCustomLayerOrder() const
Determines if the layer order should be derived from the layer tree or if a custom override order sha...
void canvasLayersChanged(const QList< QgsMapLayer * > &layers)
Emitted when the set of layers (or order of layers) visible in the canvas changes.
QgsMapLayer * layer() const
QgsLayerTreeMapCanvasBridge(QgsLayerTree *root, QgsMapCanvas *canvas, QObject *parent=nullptr)
Constructor: does not take ownership of the layer tree nor canvas.
void visibilityChanged(QgsLayerTreeNode *node)
Emitted when check state of a node within the tree has been changed.
void setLayers(const QList< QgsMapLayer *> &layers)
Sets the list of layers that should be shown in the canvas.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:391
void zoomToFullExtent()
Zoom to the full extent of all layers.
This class represents a coordinate reference system (CRS).
virtual bool isSpatial() const
Returns true if the layer is considered a spatial layer, ie it has some form of geometry associated w...
QList< QgsLayerTreeLayer * > findLayers() const
Find all layer nodes.
QgsLayerTreeLayer * findLayer(QgsMapLayer *layer) const
Find layer node representing the map layer.
void customPropertyChanged(QgsLayerTreeNode *node, const QString &key)
Emitted when a custom property of a node within the tree has been changed or removed.
Layer tree node points to a map layer.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.