QGIS API Documentation 3.99.0-Master (7d2ca374f2d)
Loading...
Searching...
No Matches
qgsmaplayerutils.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmaplayerutils.cpp
3 -------------------
4 begin : May 2021
5 copyright : (C) 2021 Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18#include "qgsmaplayerutils.h"
19
24#include "qgslogger.h"
25#include "qgsmaplayer.h"
26#include "qgsprovidermetadata.h"
27#include "qgsproviderregistry.h"
28#include "qgsrectangle.h"
29
30#include <QRegularExpression>
31#include <QString>
32
33using namespace Qt::StringLiterals;
34
35QgsRectangle QgsMapLayerUtils::combinedExtent( const QList<QgsMapLayer *> &layers, const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &transformContext )
36{
37 // We can't use a constructor since QgsRectangle normalizes the rectangle upon construction
38 QgsRectangle fullExtent;
39 fullExtent.setNull();
40
41 // iterate through the map layers and test each layers extent
42 // against the current min and max values
43 QgsDebugMsgLevel( u"Layer count: %1"_s.arg( layers.count() ), 5 );
44 for ( const QgsMapLayer *layer : layers )
45 {
46 QgsDebugMsgLevel( "Updating extent using " + layer->name(), 5 );
47 QgsDebugMsgLevel( "Input extent: " + layer->extent().toString(), 5 );
48
49 if ( layer->extent().isNull() )
50 continue;
51
52 // Layer extents are stored in the coordinate system (CS) of the
53 // layer. The extent must be projected to the canvas CS
54 QgsCoordinateTransform ct( layer->crs(), crs, transformContext );
56 try
57 {
58 const QgsRectangle extent = ct.transformBoundingBox( layer->extent() );
59
60 QgsDebugMsgLevel( "Output extent: " + extent.toString(), 5 );
61 fullExtent.combineExtentWith( extent );
62 }
63 catch ( QgsCsException & )
64 {
65 QgsDebugError( u"Could not reproject layer extent"_s );
66 }
67 }
68
69 if ( fullExtent.width() == 0.0 || fullExtent.height() == 0.0 )
70 {
71 // If all of the features are at the one point, buffer the
72 // rectangle a bit. If they are all at zero, do something a bit
73 // more crude.
74
75 if ( fullExtent.xMinimum() == 0.0 && fullExtent.xMaximum() == 0.0 &&
76 fullExtent.yMinimum() == 0.0 && fullExtent.yMaximum() == 0.0 )
77 {
78 fullExtent.set( -1.0, -1.0, 1.0, 1.0 );
79 }
80 else
81 {
82 const double padFactor = 1e-8;
83 const double widthPad = fullExtent.xMinimum() * padFactor;
84 const double heightPad = fullExtent.yMinimum() * padFactor;
85 const double xmin = fullExtent.xMinimum() - widthPad;
86 const double xmax = fullExtent.xMaximum() + widthPad;
87 const double ymin = fullExtent.yMinimum() - heightPad;
88 const double ymax = fullExtent.yMaximum() + heightPad;
89 fullExtent.set( xmin, ymin, xmax, ymax );
90 }
91 }
92
93 QgsDebugMsgLevel( "Full extent: " + fullExtent.toString(), 5 );
94 return fullExtent;
95}
96
98{
99 if ( !layer )
100 {
101 return nullptr;
102 }
103
104 try
105 {
107 if ( ! providerMetadata )
108 {
109 return nullptr;
110 }
111
112 std::unique_ptr< QgsAbstractDatabaseProviderConnection > conn { static_cast<QgsAbstractDatabaseProviderConnection *>( providerMetadata->createConnection( layer->source(), {} ) ) };
113 return conn.release();
114 }
115 catch ( const QgsProviderConnectionException &ex )
116 {
117 if ( !ex.what().contains( "createConnection"_L1 ) )
118 {
119 QgsDebugError( u"Error retrieving database connection for layer %1: %2"_s.arg( layer->name(), ex.what() ) );
120 }
121 return nullptr;
122 }
123}
124
125bool QgsMapLayerUtils::layerSourceMatchesPath( const QgsMapLayer *layer, const QString &path )
126{
127 if ( !layer || path.isEmpty() )
128 return false;
129
130 const QVariantMap parts = QgsProviderRegistry::instance()->decodeUri( layer->providerType(), layer->source() );
131 return parts.value( u"path"_s ).toString() == path;
132}
133
134bool QgsMapLayerUtils::layerRefersToUri( const QgsMapLayer *layer, const QString &uri, Qgis::SourceHierarchyLevel level )
135{
136 if ( !layer )
137 return false;
138
140 if ( !metadata )
141 {
142 throw QgsNotSupportedException( u"Could not retrieve metadata for %1 provider"_s.arg( layer->providerType() ) );
143 }
144
146 {
147 throw QgsNotSupportedException( u"%1 provider does not support UrisReferToSame capability"_s.arg( layer->providerType() ) );
148 }
149
150 return metadata->urisReferToSame( layer->source(), uri, level );
151}
152
153bool QgsMapLayerUtils::updateLayerSourcePath( QgsMapLayer *layer, const QString &newPath )
154{
155 if ( !layer || newPath.isEmpty() )
156 return false;
157
158 QVariantMap parts = QgsProviderRegistry::instance()->decodeUri( layer->providerType(), layer->source() );
159 if ( !parts.contains( u"path"_s ) )
160 return false;
161
162 parts.insert( u"path"_s, newPath );
163 const QString newUri = QgsProviderRegistry::instance()->encodeUri( layer->providerType(), parts );
164 layer->setDataSource( newUri, layer->name(), layer->providerType() );
165 return true;
166}
167
168QList<QgsMapLayer *> QgsMapLayerUtils::sortLayersByType( const QList<QgsMapLayer *> &layers, const QList<Qgis::LayerType> &order )
169{
170 QList< QgsMapLayer * > res = layers;
171 std::sort( res.begin(), res.end(), [&order]( const QgsMapLayer * a, const QgsMapLayer * b ) -> bool
172 {
173 for ( Qgis::LayerType type : order )
174 {
175 if ( a->type() == type && b->type() != type )
176 return true;
177 else if ( b->type() == type )
178 return false;
179 }
180 return false;
181 } );
182 return res;
183}
184
185QString QgsMapLayerUtils::launderLayerName( const QString &name )
186{
187 QString laundered = name.toLower();
188 const thread_local QRegularExpression sRxSwapChars( u"\\s"_s );
189 laundered.replace( sRxSwapChars, u"_"_s );
190
191 const thread_local QRegularExpression sRxRemoveChars( u"[^a-zA-Z0-9_]"_s );
192 laundered.replace( sRxRemoveChars, QString() );
193
194 return laundered;
195}
196
198{
199 if ( layer->providerType() == "wms"_L1 )
200 {
201 if ( const QgsProviderMetadata *metadata = layer->providerMetadata() )
202 {
203 QVariantMap details = metadata->decodeUri( layer->source() );
204 QUrl url( details.value( u"url"_s ).toString() );
205 if ( url.host().endsWith( ".openstreetmap.org"_L1 ) || url.host().endsWith( ".osm.org"_L1 ) )
206 {
207 return true;
208 }
209 }
210 }
211 return false;
212}
213
215{
216 switch ( type )
217 {
219 return QObject::tr( "Vector" );
221 return QObject::tr( "Raster" );
223 return QObject::tr( "Mesh" );
225 return QObject::tr( "Point Cloud" );
227 return QObject::tr( "Annotation" );
229 return QObject::tr( "Vector Tile" );
231 return QObject::tr( "Plugin" );
233 return QObject::tr( "Group" );
235 return QObject::tr( "Tiled Scene" );
236 }
237 Q_ASSERT( false );
238 return QString();
239}
LayerType
Types of layers that can be added to a map.
Definition qgis.h:204
@ Group
Composite group layer. Added in QGIS 3.24.
Definition qgis.h:212
@ Plugin
Plugin based layer.
Definition qgis.h:207
@ TiledScene
Tiled scene layer. Added in QGIS 3.34.
Definition qgis.h:213
@ Annotation
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
Definition qgis.h:210
@ Vector
Vector layer.
Definition qgis.h:205
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
Definition qgis.h:209
@ Mesh
Mesh layer. Added in QGIS 3.2.
Definition qgis.h:208
@ Raster
Raster layer.
Definition qgis.h:206
@ PointCloud
Point cloud layer. Added in QGIS 3.18.
Definition qgis.h:211
SourceHierarchyLevel
Defines the structural levels within a data source hierarchy.
Definition qgis.h:1451
Provides common functionality for database based connections.
Represents a coordinate reference system (CRS).
Contains information about the context in which a coordinate transform is executed.
Handles coordinate transforms between two coordinate systems.
void setBallparkTransformsAreAppropriate(bool appropriate)
Sets whether approximate "ballpark" results are appropriate for this coordinate transform.
QgsRectangle transformBoundingBox(const QgsRectangle &rectangle, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool handle180Crossover=false) const
Transforms a rectangle from the source CRS to the destination CRS.
Custom exception class for Coordinate Reference System related exceptions.
QString what() const
static bool updateLayerSourcePath(QgsMapLayer *layer, const QString &newPath)
Updates a layer's data source, replacing its data source with a path referring to newPath.
static bool layerRefersToUri(const QgsMapLayer *layer, const QString &uri, Qgis::SourceHierarchyLevel level=Qgis::SourceHierarchyLevel::Object)
Returns true if a layer and uri point to the same resource at the specified hierarchy level.
static QgsRectangle combinedExtent(const QList< QgsMapLayer * > &layers, const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &transformContext)
Returns the combined extent of a list of layers.
static QgsAbstractDatabaseProviderConnection * databaseConnection(const QgsMapLayer *layer)
Creates and returns the (possibly nullptr) database connection for a layer.
static QString layerTypeToString(Qgis::LayerType type)
Returns the translated name of the type for a given layer type.
static QList< QgsMapLayer * > sortLayersByType(const QList< QgsMapLayer * > &layers, const QList< Qgis::LayerType > &order)
Sorts a list of map layers by their layer type, respecting the order of types specified.
static QString launderLayerName(const QString &name)
Launders a layer's name, converting it into a format which is general suitable for file names or data...
static bool isOpenStreetMapLayer(QgsMapLayer *layer)
Returns true if the layer is served by OpenStreetMap server.
static bool layerSourceMatchesPath(const QgsMapLayer *layer, const QString &path)
Returns true if the source of the specified layer matches the given path.
Base class for all map layer types.
Definition qgsmaplayer.h:83
QString name
Definition qgsmaplayer.h:87
QString source() const
Returns the source for the layer.
QString providerType() const
Returns the provider type (provider key) for this layer.
void setDataSource(const QString &dataSource, const QString &baseName=QString(), const QString &provider=QString(), bool loadDefaultStyleFlag=false)
Updates the data source of the layer.
QgsProviderMetadata * providerMetadata() const
Returns the layer data provider's metadata, it may be nullptr.
Custom exception class which is raised when an operation is not supported.
Custom exception class for provider connection related exceptions.
Holds data provider key, description, and associated shared library file or function pointer informat...
virtual bool urisReferToSame(const QString &uri1, const QString &uri2, Qgis::SourceHierarchyLevel level=Qgis::SourceHierarchyLevel::Object) const
Returns true if the URI uri1 and uri2 point to the same resource at the specified hierarchy level.
virtual QgsAbstractProviderConnection * createConnection(const QString &uri, const QVariantMap &configuration)
Creates a new connection from uri and configuration, the newly created connection is not automaticall...
@ UrisReferToSame
Indicates that the metadata can check whether layer URIs refer to the same object.
virtual QgsProviderMetadata::ProviderMetadataCapabilities capabilities() const
Returns the provider metadata capabilities.
QVariantMap decodeUri(const QString &providerKey, const QString &uri)
Breaks a provider data source URI into its component paths (e.g.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
QString encodeUri(const QString &providerKey, const QVariantMap &parts)
Reassembles a provider data source URI from its component paths (e.g.
QgsProviderMetadata * providerMetadata(const QString &providerKey) const
Returns metadata of the provider or nullptr if not found.
A rectangle specified with double values.
Q_INVOKABLE QString toString(int precision=16) const
Returns a string representation of form xmin,ymin : xmax,ymax Coordinates will be rounded to the spec...
double xMinimum
double yMinimum
double xMaximum
void set(const QgsPointXY &p1, const QgsPointXY &p2, bool normalize=true)
Sets the rectangle from two QgsPoints.
double yMaximum
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle.
void setNull()
Mark a rectangle as being null (holding no spatial information).
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:63
#define QgsDebugError(str)
Definition qgslogger.h:59