QGIS API Documentation 3.41.0-Master (3440c17df1d)
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#include "moc_qgslayertreemapcanvasbridge.cpp"
18
19#include "qgslayertree.h"
20#include "qgslayertreeutils.h"
21#include "qgsmaplayer.h"
22#include "qgsvectorlayer.h"
23#include "qgsmapcanvas.h"
25#include "qgsproject.h"
26#include "qgssettings.h"
27#include "qgsgui.h"
28
30 : QObject( parent )
31 , mRoot( root )
32 , mCanvas( canvas )
33 , mPendingCanvasUpdate( false )
34 , mAutoSetupOnFirstLayer( true )
35 , mHasLayersLoaded( !root->findLayers().isEmpty() )
36{
37 connect( root, &QgsLayerTreeGroup::customPropertyChanged, this, &QgsLayerTreeMapCanvasBridge::nodeCustomPropertyChanged );
38 connect( root, &QgsLayerTreeNode::visibilityChanged, this, &QgsLayerTreeMapCanvasBridge::nodeVisibilityChanged );
39 connect( root, &QgsLayerTree::layerOrderChanged, this, &QgsLayerTreeMapCanvasBridge::deferredSetCanvasLayers );
40
41 connect( QgsProject::instance(), &QgsProject::layersAdded, this, &QgsLayerTreeMapCanvasBridge::layersAdded );
42
44}
45
47{
48 QList<QgsMapLayer *> canvasLayers, overviewLayers, allLayerOrder;
49
50 if ( mRoot->hasCustomLayerOrder() )
51 {
52 const QList<QgsMapLayer *> customOrderLayers = mRoot->customLayerOrder();
53 for ( const QgsMapLayer *layer : customOrderLayers )
54 {
55 QgsLayerTreeLayer *nodeLayer = mRoot->findLayer( layer->id() );
56 if ( nodeLayer )
57 {
58 if ( !nodeLayer->layer()->isSpatial() )
59 continue;
60
61 allLayerOrder << nodeLayer->layer();
62 if ( nodeLayer->isVisible() )
63 canvasLayers << nodeLayer->layer();
64 if ( nodeLayer->customProperty( QStringLiteral( "overview" ), 0 ).toInt() )
65 overviewLayers << nodeLayer->layer();
66 }
67 }
68 }
69 else
70 {
71 setCanvasLayers( mRoot, canvasLayers, overviewLayers, allLayerOrder );
72 }
73
74 const QList<QgsLayerTreeLayer *> layerNodes = mRoot->findLayers();
75 int currentSpatialLayerCount = 0;
76 int currentValidSpatialLayerCount = 0;
77 for ( QgsLayerTreeLayer *layerNode : layerNodes )
78 {
79 if ( layerNode->layer() && layerNode->layer()->isSpatial() )
80 {
81 currentSpatialLayerCount++;
82 if ( layerNode->layer()->isValid() )
83 currentValidSpatialLayerCount++;
84 }
85 }
86
87 const bool firstLayers = mAutoSetupOnFirstLayer && !mHasLayersLoaded && currentSpatialLayerCount != 0;
88 const bool firstValidLayers = mAutoSetupOnFirstLayer && !mHasValidLayersLoaded && currentValidSpatialLayerCount != 0;
89
90 mCanvas->setLayers( canvasLayers );
91 if ( mOverviewCanvas )
92 mOverviewCanvas->setLayers( overviewLayers );
93
94 if ( firstValidLayers )
95 {
96 // if we are moving from zero to non-zero layers, let's zoom to those data (only consider valid layers here!)
97 mCanvas->zoomToProjectExtent();
98 }
99
100 if ( !mFirstCRS.isValid() )
101 {
102 // find out what is the first used CRS in case we may need to turn on OTF projections later
103 for ( const QgsLayerTreeLayer *layerNode : layerNodes )
104 {
105 if ( layerNode->layer() && layerNode->layer()->crs().isValid() )
106 {
107 mFirstCRS = layerNode->layer()->crs();
108 break;
109 }
110 }
111 }
112
113 if ( mFirstCRS.isValid() && firstLayers )
114 {
115 const QgsGui::ProjectCrsBehavior projectCrsBehavior = QgsSettings().enumValue( QStringLiteral( "/projections/newProjectCrsBehavior" ), QgsGui::UseCrsOfFirstLayerAdded, QgsSettings::App );
116 switch ( projectCrsBehavior )
117 {
119 {
120 const bool planimetric = QgsSettings().value( QStringLiteral( "measure/planimetric" ), true, QgsSettings::Core ).toBool();
121 // Only adjust ellipsoid to CRS if it's not set to planimetric
122 QgsProject::instance()->setCrs( mFirstCRS, !planimetric );
123 break;
124 }
125
127 break;
128 }
129 }
130
131 mHasLayersLoaded = currentSpatialLayerCount;
132 mHasValidLayersLoaded = currentValidSpatialLayerCount;
133 if ( currentSpatialLayerCount == 0 )
134 mFirstCRS = QgsCoordinateReferenceSystem();
135
136 mPendingCanvasUpdate = false;
137
138 emit canvasLayersChanged( canvasLayers );
139}
140
141void QgsLayerTreeMapCanvasBridge::setCanvasLayers( QgsLayerTreeNode *node, QList<QgsMapLayer *> &canvasLayers, QList<QgsMapLayer *> &overviewLayers, QList<QgsMapLayer *> &allLayers )
142{
143 if ( QgsLayerTree::isLayer( node ) )
144 {
145 QgsLayerTreeLayer *nodeLayer = QgsLayerTree::toLayer( node );
146 if ( nodeLayer->layer() && nodeLayer->layer()->isSpatial() )
147 {
148 allLayers << nodeLayer->layer();
149 if ( nodeLayer->isVisible() )
150 canvasLayers << nodeLayer->layer();
151 if ( nodeLayer->customProperty( QStringLiteral( "overview" ), 0 ).toInt() )
152 overviewLayers << nodeLayer->layer();
153 }
154 }
155
156 const QList<QgsLayerTreeNode *> children = node->children();
157 for ( QgsLayerTreeNode *child : children )
158 {
159 if ( QgsLayerTree::isGroup( child ) )
160 {
161 if ( QgsGroupLayer *groupLayer = QgsLayerTree::toGroup( child )->groupLayer() )
162 {
163 if ( child->isVisible() )
164 canvasLayers << groupLayer;
165 continue;
166 }
167 }
168 setCanvasLayers( child, canvasLayers, overviewLayers, allLayers );
169 }
170}
171
172void QgsLayerTreeMapCanvasBridge::deferredSetCanvasLayers()
173{
174 if ( mPendingCanvasUpdate )
175 return;
176
177 mPendingCanvasUpdate = true;
178 QMetaObject::invokeMethod( this, "setCanvasLayers", Qt::QueuedConnection );
179}
180
181void QgsLayerTreeMapCanvasBridge::nodeVisibilityChanged()
182{
183 deferredSetCanvasLayers();
184}
185
186void QgsLayerTreeMapCanvasBridge::nodeCustomPropertyChanged( QgsLayerTreeNode *node, const QString &key )
187{
188 Q_UNUSED( node )
189 if ( key == QLatin1String( "overview" ) )
190 deferredSetCanvasLayers();
191}
192
193void QgsLayerTreeMapCanvasBridge::layersAdded( const QList<QgsMapLayer *> &layers )
194{
195 for ( QgsMapLayer *l : layers )
196 {
197 if ( l )
198 {
199 connect( l, &QgsMapLayer::dataSourceChanged, this, [ this, l ]
200 {
201 if ( l->isValid() && l->isSpatial() && mAutoSetupOnFirstLayer && !mHasValidLayersLoaded )
202 {
203 mHasValidLayersLoaded = true;
204 // if we are moving from zero valid layers to non-zero VALID layers, let's zoom to those data
205 mCanvas->zoomToProjectExtent();
206 }
207 } );
208 }
209 }
210}
This class represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
A map layer which consists of a set of child layers, where all component layers are rendered as a sin...
ProjectCrsBehavior
Defines the behavior to use when setting the CRS for a newly created project.
Definition qgsgui.h:75
@ UseCrsOfFirstLayerAdded
Set the project CRS to the CRS of the first layer added to a new project.
Definition qgsgui.h:76
@ UsePresetCrs
Always set new projects to use a preset default CRS.
Definition qgsgui.h:77
QList< QgsLayerTreeLayer * > findLayers() const
Find all layer nodes.
QgsLayerTreeLayer * findLayer(QgsMapLayer *layer) const
Find layer node representing the map layer.
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.
This class is a 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.
bool hasCustomLayerOrder() const
Determines if the layer order should be derived from the layer tree or if a custom override order sha...
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.
QList< QgsMapLayer * > customLayerOrder() const
The order in which layers will be rendered on the canvas.
Map canvas is a class for displaying all GIS data types on a canvas.
void zoomToProjectExtent()
Zoom to the full extent the project associated with this canvas.
void setLayers(const QList< QgsMapLayer * > &layers)
Sets the list of layers that should be shown in the canvas.
Base class for all map layer types.
Definition qgsmaplayer.h:76
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 setLayers(const QList< QgsMapLayer * > &layers)
updates layer set for overview
void setCrs(const QgsCoordinateReferenceSystem &crs, bool adjustEllipsoid=false)
Sets the project's native coordinate reference system.
static QgsProject * instance()
Returns the QgsProject singleton instance.
void layersAdded(const QList< QgsMapLayer * > &layers)
Emitted when one or more layers were added to the registry.
This class is a composition of two QSettings instances:
Definition qgssettings.h:64
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
T enumValue(const QString &key, const T &defaultValue, const Section section=NoSection)
Returns the setting value for a setting based on an enum.