QGIS API Documentation 4.1.0-Master (376402f9aeb)
Loading...
Searching...
No Matches
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 "qgsgui.h"
19#include "qgslayertree.h"
20#include "qgslayertreeutils.h"
21#include "qgsmapcanvas.h"
22#include "qgsmaplayer.h"
24#include "qgsproject.h"
25#include "qgssettings.h"
28#include "qgsvectorlayer.h"
29
30#include <QString>
31
32#include "moc_qgslayertreemapcanvasbridge.cpp"
33
34using namespace Qt::StringLiterals;
35
37 : QObject( parent )
38 , mRoot( root )
39 , mCanvas( canvas )
40 , mHasLayersLoaded( !root->findLayers().isEmpty() )
41{
42 connect( root, &QgsLayerTreeGroup::customPropertyChanged, this, &QgsLayerTreeMapCanvasBridge::nodeCustomPropertyChanged );
43 connect( root, &QgsLayerTreeNode::visibilityChanged, this, &QgsLayerTreeMapCanvasBridge::nodeVisibilityChanged );
44 connect( root, &QgsLayerTree::layerOrderChanged, this, &QgsLayerTreeMapCanvasBridge::deferredSetCanvasLayers );
45
46 connect( QgsProject::instance(), &QgsProject::layersAdded, this, &QgsLayerTreeMapCanvasBridge::layersAdded );
47
49}
50
52{
53 QList<QgsMapLayer *> canvasLayers, overviewLayers, allLayerOrder;
54
55 if ( mRoot->hasCustomLayerOrder() )
56 {
57 const QList<QgsMapLayer *> customOrderLayers = mRoot->customLayerOrder();
58 for ( const QgsMapLayer *layer : customOrderLayers )
59 {
60 QgsLayerTreeLayer *nodeLayer = mRoot->findLayer( layer->id() );
61 if ( nodeLayer )
62 {
63 if ( !nodeLayer->layer()->isSpatial() )
64 continue;
65
66 allLayerOrder << nodeLayer->layer();
67 if ( nodeLayer->isVisible() )
68 canvasLayers << nodeLayer->layer();
69 if ( nodeLayer->customProperty( u"overview"_s, 0 ).toInt() )
70 overviewLayers << nodeLayer->layer();
71 }
72 }
73 }
74 else
75 {
76 setCanvasLayers( mRoot, canvasLayers, overviewLayers, allLayerOrder );
77 }
78
79 const QList<QgsLayerTreeLayer *> layerNodes = mRoot->findLayers();
80 int currentSpatialLayerCount = 0;
81 int currentValidSpatialLayerCount = 0;
82 for ( QgsLayerTreeLayer *layerNode : layerNodes )
83 {
84 if ( layerNode->layer() && layerNode->layer()->isSpatial() )
85 {
86 currentSpatialLayerCount++;
87 if ( layerNode->layer()->isValid() )
88 currentValidSpatialLayerCount++;
89 }
90 }
91
92 const bool firstLayers = mAutoSetupOnFirstLayer && !mHasLayersLoaded && currentSpatialLayerCount != 0;
93 const bool firstValidLayers = mAutoSetupOnFirstLayer && !mHasValidLayersLoaded && currentValidSpatialLayerCount != 0;
94
95 mCanvas->setLayers( canvasLayers );
96 if ( mOverviewCanvas )
97 mOverviewCanvas->setLayers( overviewLayers );
98
99 if ( !mFirstCRS.isValid() )
100 {
101 // find out what is the first used CRS in case we may need to turn on OTF projections later
102 for ( const QgsLayerTreeLayer *layerNode : layerNodes )
103 {
104 if ( layerNode->layer() && layerNode->layer()->crs().isValid() )
105 {
106 mFirstCRS = layerNode->layer()->crs();
107 break;
108 }
109 }
110 }
111
112 if ( mFirstCRS.isValid() && firstLayers )
113 {
114 const QgsGui::ProjectCrsBehavior projectCrsBehavior = QgsSettings().enumValue( u"/projections/newProjectCrsBehavior"_s, QgsGui::UseCrsOfFirstLayerAdded, QgsSettings::App );
115 switch ( projectCrsBehavior )
116 {
118 {
119 const bool planimetric = QgsSettingsRegistryCore::settingsMeasurePlanimetric->value();
120 // Only adjust ellipsoid to CRS if it's not set to planimetric
121 QgsProject::instance()->setCrs( mFirstCRS.horizontalCrs(), !planimetric );
122 const QgsCoordinateReferenceSystem vertCrs = mFirstCRS.verticalCrs();
124 break;
125 }
126
128 break;
129 }
130 }
131
132 if ( firstValidLayers )
133 {
134 // if we are moving from zero to non-zero layers, let's zoom to those data (only consider valid layers here!)
135 mCanvas->zoomToProjectExtent();
136 }
137
138 mHasLayersLoaded = currentSpatialLayerCount;
139 mHasValidLayersLoaded = currentValidSpatialLayerCount;
140 if ( currentSpatialLayerCount == 0 )
141 mFirstCRS = QgsCoordinateReferenceSystem();
142
143 mPendingCanvasUpdate = false;
144
145 emit canvasLayersChanged( canvasLayers );
146}
147
148void QgsLayerTreeMapCanvasBridge::setCanvasLayers( QgsLayerTreeNode *node, QList<QgsMapLayer *> &canvasLayers, QList<QgsMapLayer *> &overviewLayers, QList<QgsMapLayer *> &allLayers )
149{
150 if ( QgsLayerTree::isLayer( node ) )
151 {
152 QgsLayerTreeLayer *nodeLayer = QgsLayerTree::toLayer( node );
153 if ( nodeLayer->layer() && nodeLayer->layer()->isSpatial() )
154 {
155 allLayers << nodeLayer->layer();
156 if ( nodeLayer->isVisible() )
157 canvasLayers << nodeLayer->layer();
158 if ( nodeLayer->customProperty( u"overview"_s, 0 ).toInt() )
159 overviewLayers << nodeLayer->layer();
160 }
161 }
162
163 const QList<QgsLayerTreeNode *> children = node->children();
164 for ( QgsLayerTreeNode *child : children )
165 {
166 if ( QgsLayerTree::isGroup( child ) )
167 {
168 if ( QgsGroupLayer *groupLayer = QgsLayerTree::toGroup( child )->groupLayer() )
169 {
170 if ( child->isVisible() )
171 canvasLayers << groupLayer;
172 continue;
173 }
174 }
175 setCanvasLayers( child, canvasLayers, overviewLayers, allLayers );
176 }
177}
178
179void QgsLayerTreeMapCanvasBridge::deferredSetCanvasLayers()
180{
181 if ( mPendingCanvasUpdate )
182 return;
183
184 mPendingCanvasUpdate = true;
185 QMetaObject::invokeMethod( this, "setCanvasLayers", Qt::QueuedConnection );
186}
187
188void QgsLayerTreeMapCanvasBridge::nodeVisibilityChanged()
189{
190 deferredSetCanvasLayers();
191}
192
193void QgsLayerTreeMapCanvasBridge::nodeCustomPropertyChanged( QgsLayerTreeNode *node, const QString &key )
194{
195 Q_UNUSED( node )
196 if ( key == "overview"_L1 )
197 deferredSetCanvasLayers();
198}
199
200void QgsLayerTreeMapCanvasBridge::layersAdded( const QList<QgsMapLayer *> &layers )
201{
202 for ( QgsMapLayer *l : layers )
203 {
204 if ( l )
205 {
206 connect( l, &QgsMapLayer::dataSourceChanged, this, [this, l] {
207 if ( l->isValid() && l->isSpatial() && mAutoSetupOnFirstLayer && !mHasValidLayersLoaded )
208 {
209 mHasValidLayersLoaded = true;
210 // if we are moving from zero valid layers to non-zero VALID layers, let's zoom to those data
211 mCanvas->zoomToProjectExtent();
212 }
213 deferredSetCanvasLayers();
214 } );
215 }
216 }
217}
Represents a coordinate reference system (CRS).
QgsCoordinateReferenceSystem verticalCrs() const
Returns the vertical CRS associated with this CRS object.
ProjectCrsBehavior
Defines the behavior to use when setting the CRS for a newly created project.
Definition qgsgui.h:82
@ UseCrsOfFirstLayerAdded
Set the project CRS to the CRS of the first layer added to a new project.
Definition qgsgui.h:83
@ UsePresetCrs
Always set new projects to use a preset default CRS.
Definition qgsgui.h:84
Layer tree node points to a map layer.
QgsMapLayer * layer() const
Returns the map layer associated with this node.
Q_INVOKABLE void setCanvasLayers()
force update of canvas layers from the layer tree. Normally this should not be needed to be called.
void canvasLayersChanged(const QList< QgsMapLayer * > &layers)
Emitted when the set of layers (or order of layers) visible in the canvas changes.
QgsLayerTreeMapCanvasBridge(QgsLayerTree *root, QgsMapCanvas *canvas, QObject *parent SIP_TRANSFERTHIS=nullptr)
Constructor: does not take ownership of the layer tree nor canvas.
Base class for nodes in a layer tree.
bool isVisible() const
Returns whether a node is really visible (ie checked and all its ancestors checked as well).
QList< QgsLayerTreeNode * > children()
Gets list of children of the node. Children are owned by the parent.
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 customPropertyChanged(QgsLayerTreeNode *node, const QString &key)
Emitted when a custom property of a node within the tree has been changed or removed.
void visibilityChanged(QgsLayerTreeNode *node)
Emitted when check state of a node within the tree has been changed.
Namespace with helper functions for layer tree operations.
static QgsLayerTreeLayer * toLayer(QgsLayerTreeNode *node)
Cast node to a layer.
static bool isLayer(const QgsLayerTreeNode *node)
Check whether the node is a valid layer node.
static bool isGroup(QgsLayerTreeNode *node)
Check whether the node is a valid group node.
static QgsLayerTreeGroup * toGroup(QgsLayerTreeNode *node)
Cast node to a group.
void layerOrderChanged()
Emitted when the layer order has changed.
Map canvas is a class for displaying all GIS data types on a canvas.
Base class for all map layer types.
Definition qgsmaplayer.h:83
virtual bool isSpatial() const
Returns true if the layer is considered a spatial layer, ie it has some form of geometry associated w...
void dataSourceChanged()
Emitted whenever the layer's data source has been changed.
void setCrs(const QgsCoordinateReferenceSystem &crs, bool adjustEllipsoid=false)
Sets the project's native coordinate reference system.
static QgsProject * instance()
Returns the QgsProject singleton instance.
bool setVerticalCrs(const QgsCoordinateReferenceSystem &crs, QString *errorMessage=nullptr)
Sets the project's vertical coordinate reference system.
void layersAdded(const QList< QgsMapLayer * > &layers)
Emitted when one or more layers were added to the registry.
static const QgsSettingsEntryBool * settingsMeasurePlanimetric
Settings entry for whether measurements should be planimetric (ellipsoid off) or use the ellipsoid.
Stores settings for use within QGIS.
Definition qgssettings.h:68
T enumValue(const QString &key, const T &defaultValue, const Section section=NoSection)
Returns the setting value for a setting based on an enum.