QGIS API Documentation 3.32.0-Lima (311a8cb8a6)
qgswmslayerinfos.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgswmslayerinfos.cpp
3
4 Layer's information
5 ------------------------------------
6 begin : September 26 , 2022
7 copyright : (C) 2022 by René-Luc D'Hont and David Marteau
8 email : rldhont at 3liz doc com
9 dmarteau at 3liz dot com
10 ***************************************************************************/
11
12/***************************************************************************
13 * *
14 * This program is free software; you can redistribute it and/or modify *
15 * it under the terms of the GNU General Public License as published by *
16 * the Free Software Foundation; either version 2 of the License, or *
17 * (at your option) any later version. *
18 * *
19 ***************************************************************************/
20
23#include "qgsproject.h"
24#include "qgsvectorlayer.h"
25#include "qgswmslayerinfos.h"
26#include "qgsmessagelog.h"
27#include "qgsserverinterface.h"
29
30#include <algorithm>
31
33 const QgsRectangle &extent,
34 const QgsCoordinateReferenceSystem &source,
35 const QgsCoordinateReferenceSystem &destination,
36 const QgsCoordinateTransformContext &context,
37 const bool &ballparkTransformsAreAppropriate )
38{
39 QgsCoordinateTransform transformer { source, destination, context };
40 transformer.setBallparkTransformsAreAppropriate( ballparkTransformsAreAppropriate );
41 // Transform extent and do not catch exception
42 return transformer.transformBoundingBox( extent );
43}
44
45QMap< QString, QgsRectangle > QgsWmsLayerInfos::transformExtentToCrsList(
46 const QgsRectangle &extent,
47 const QgsCoordinateReferenceSystem &source,
48 const QList<QgsCoordinateReferenceSystem> &destinations,
49 const QgsCoordinateTransformContext &context )
50{
51 QMap< QString, QgsRectangle > crsExtents;
52 if ( extent.isEmpty() )
53 {
54 return crsExtents;
55 }
56 for ( const QgsCoordinateReferenceSystem &destination : std::as_const( destinations ) )
57 {
58 // Transform extent and do not catch exception
59 QgsCoordinateTransform crsTransform { source, destination, context };
60 crsExtents[ destination.authid() ] = crsTransform.transformBoundingBox( extent );
61 }
62 return crsExtents;
63}
64
65
67 const QgsProject *project,
68 QgsWmsLayerInfos &pLayer,
69 QgsMapLayer *ml,
72 const QList<QgsCoordinateReferenceSystem> &outputCrsList )
73{
74 QgsRectangle layerExtent = ml->extent();
75 if ( layerExtent.isEmpty() )
76 {
77 // if the extent is empty (not only Null), use the wms extent
78 // defined in the project...
79 if ( wmsExtent.isNull() )
80 {
81 // or the CRS extent otherwise
82 layerExtent = ml->crs().bounds();
83 }
84 else
85 {
86 layerExtent = QgsRectangle( wmsExtent );
87 if ( ml->crs() != project->crs() )
88 {
89 // If CRS is different transform it to layer's CRS
90 try
91 {
92 layerExtent = QgsWmsLayerInfos::transformExtent( wmsExtent, project->crs(), ml->crs(), project->transformContext() );
93 }
94 catch ( QgsCsException &cse )
95 {
96 QgsMessageLog::logMessage( QStringLiteral( "Error transforming extent for layer %1: %2" ).arg( ml->name() ).arg( cse.what() ), QStringLiteral( "Server" ), Qgis::MessageLevel::Warning );
97 return false;
98 }
99 }
100 }
101
102 // Now we have a layer Extent we need the WGS84 bounding rectangle
103 try
104 {
105 pLayer.wgs84BoundingRect = QgsWmsLayerInfos::transformExtent( layerExtent, ml->crs(), wgs84, project->transformContext(), true );
106 }
107 catch ( const QgsCsException &cse )
108 {
109 QgsMessageLog::logMessage( QStringLiteral( "Error transforming extent for layer %1: %2" ).arg( ml->name() ).arg( cse.what() ), QStringLiteral( "Server" ), Qgis::MessageLevel::Warning );
110 return false;
111 }
112 }
113 else
114 {
115 pLayer.wgs84BoundingRect = ml->wgs84Extent();
116 }
117
118 try
119 {
121 layerExtent, ml->crs(), outputCrsList, project->transformContext()
122 );
123 }
124 catch ( QgsCsException &cse )
125 {
126 QgsMessageLog::logMessage( QStringLiteral( "Error transforming extent for layer %1: %2" ).arg( ml->name() ).arg( cse.what() ), QStringLiteral( "Server" ), Qgis::MessageLevel::Warning );
127 return false;
128 }
129
130 return true;
131}
132
133// ===================================
134// Get wms layer infos
135// ===================================
136QMap< QString, QgsWmsLayerInfos > QgsWmsLayerInfos::buildWmsLayerInfos(
137 QgsServerInterface *serverIface,
138 const QgsProject *project,
139 const QList<QgsCoordinateReferenceSystem> &outputCrsList )
140{
141 QMap< QString, QgsWmsLayerInfos > wmsLayers;
142#ifdef HAVE_SERVER_PYTHON_PLUGINS
143 QgsAccessControl *accessControl = serverIface->accessControls();
144#else
145 ( void )serverIface;
146#endif
147
148 bool useLayerIds = QgsServerProjectUtils::wmsUseLayerIds( *project );
149 const QStringList restrictedLayers = QgsServerProjectUtils::wmsRestrictedLayers( *project );
152
153 for ( QgsMapLayer *ml : project->mapLayers() )
154 {
155 if ( !ml || restrictedLayers.contains( ml->name() ) ) //unpublished layer
156 {
157 continue;
158 }
159
160#ifdef HAVE_SERVER_PYTHON_PLUGINS
161 if ( accessControl && !accessControl->layerReadPermission( ml ) )
162 {
163 continue;
164 }
165#endif
166
167 QgsWmsLayerInfos pLayer;
168 pLayer.id = ml->id();
169
170 // Calculate layer extents for the WMS output CRSes list
171 // First define if the layer has an extent
172 // Vector layer with No Geometry has no extent the other has one
173 bool hasExtent = true;
174 if ( ml->type() == Qgis::LayerType::Vector )
175 {
176 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( ml );
177 if ( !vLayer || vLayer->wkbType() == Qgis::WkbType::NoGeometry )
178 {
179 hasExtent = false;
180 }
181 }
182
183 // If the layer has an extent and we cannot get CRS bounding boxes, do not keep the layer
184 if ( hasExtent && !setBoundingRect( project, pLayer, ml, wmsExtent, wgs84, outputCrsList ) )
185 continue;
186
187 // layer type
188 pLayer.type = ml->type();
189 // layer wms name
190 pLayer.name = ml->name();
191 if ( useLayerIds )
192 {
193 pLayer.name = ml->id();
194 }
195 else if ( !ml->shortName().isEmpty() )
196 {
197 pLayer.name = ml->shortName();
198 }
199 // layer title
200 pLayer.title = ml->title();
201 if ( pLayer.title.isEmpty() )
202 {
203 pLayer.title = ml->name();
204 }
205 // layer abstract
206 pLayer.abstract = ml->abstract();
207 // layer is queryable
208 pLayer.queryable = ml->flags().testFlag( QgsMapLayer::Identifiable );
209 // layer keywords
210 if ( !ml->keywordList().isEmpty() )
211 {
212 pLayer.keywords = ml->keywordList().split( ',' );
213 }
214 // layer styles
215 pLayer.styles = ml->styleManager()->styles();
216 // layer legend URL
217 pLayer.legendUrl = ml->legendUrl();
218 // layer legend URL format
219 pLayer.legendUrlFormat = ml->legendUrlFormat();
220 // layer min/max scales
221 if ( ml->hasScaleBasedVisibility() )
222 {
223 pLayer.hasScaleBasedVisibility = ml->hasScaleBasedVisibility();
224 pLayer.maxScale = ml->maximumScale();
225 pLayer.minScale = ml->minimumScale();
226 }
227 // layer data URL
228 pLayer.dataUrl = ml->dataUrl();
229 // layer attribution
230 pLayer.attribution = ml->attribution();
231 pLayer.attributionUrl = ml->attributionUrl();
232 // layer metadata URLs
233 pLayer.metadataUrls = ml->serverProperties()->metadataUrls();
234
235 wmsLayers[pLayer.id] = pLayer;
236 }
237
238 return wmsLayers;
239}
240
@ NoGeometry
No geometry.
A helper class that centralizes restrictions given by all the access control filter plugins.
bool layerReadPermission(const QgsMapLayer *layer) const
Returns the layer read right.
This class represents a coordinate reference system (CRS).
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
QgsRectangle bounds() const
Returns the approximate bounds for the region the CRS is usable within.
Contains information about the context in which a coordinate transform is executed.
Class for doing transforms between two map coordinate systems.
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:67
QString what() const
Definition: qgsexception.h:49
Base class for all map layer types.
Definition: qgsmaplayer.h:73
QString name
Definition: qgsmaplayer.h:76
QgsRectangle wgs84Extent(bool forceRecalculate=false) const
Returns the WGS84 extent (EPSG:4326) of the layer according to ReadFlag::FlagTrustLayerMetadata.
virtual QgsRectangle extent() const
Returns the extent of the layer.
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:79
@ Identifiable
If the layer is identifiable using the identify map tool and as a WMS layer.
Definition: qgsmaplayer.h:147
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition: qgsproject.h:107
QgsCoordinateTransformContext transformContext
Definition: qgsproject.h:113
QgsCoordinateReferenceSystem crs
Definition: qgsproject.h:112
QMap< QString, QgsMapLayer * > mapLayers(const bool validOnly=false) const
Returns a map of all registered layers by layer ID.
A rectangle specified with double values.
Definition: qgsrectangle.h:42
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
Definition: qgsrectangle.h:479
bool isEmpty() const
Returns true if the rectangle is empty.
Definition: qgsrectangle.h:469
QgsServerInterface Class defining interfaces exposed by QGIS Server and made available to plugins.
virtual QgsAccessControl * accessControls() const =0
Gets the registered access control filters.
Represents a vector layer which manages a vector based data sets.
Q_INVOKABLE Qgis::WkbType wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
WMS Layer infos.
QString legendUrlFormat
WMS layer legend URL format.
QString title
WMS layer title.
QStringList styles
WMS layer styles.
QStringList keywords
WMS layer keywords.
QString legendUrl
WMS layer legend URL.
QString id
QGIS layer id.
QString abstract
WMS layer abstract.
static QgsRectangle transformExtent(const QgsRectangle &extent, const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination, const QgsCoordinateTransformContext &context, const bool &ballparkTransformsAreAppropriate=false)
Returns a transformed extent.
QString attribution
WMS layer attribution.
QString dataUrl
WMS layer dataUrl.
double maxScale
WMS layer maximum scale (if negative, no maximum scale is defined)
QMap< QString, QgsRectangle > crsExtents
WMS layer CRS extents (can be empty)
QString attributionUrl
WMS layer attribution URL.
static QMap< QString, QgsRectangle > transformExtentToCrsList(const QgsRectangle &extent, const QgsCoordinateReferenceSystem &source, const QList< QgsCoordinateReferenceSystem > &destinations, const QgsCoordinateTransformContext &context)
Returns a map with CRS authid as key and the transformed extent as value.
Qgis::LayerType type
QGIS layer type.
QString name
WMS layer name.
static QMap< QString, QgsWmsLayerInfos > buildWmsLayerInfos(QgsServerInterface *serverIface, const QgsProject *project, const QList< QgsCoordinateReferenceSystem > &outputCrsList)
Returns the WMS layers definition to build WMS capabilities.
QList< QgsMapLayerServerProperties::MetadataUrl > metadataUrls
WMS layer metadata URLs.
bool hasScaleBasedVisibility
WMS layer has scale based visibility.
double minScale
WMS layer minimum scale (if negative, no maximum scale is defined)
bool queryable
WMS layer is queryable.
QgsRectangle wgs84BoundingRect
WMS layer WGS84 bounding rectangle (can be empty)
SERVER_EXPORT QgsRectangle wmsExtent(const QgsProject &project)
Returns the WMS Extent restriction.
SERVER_EXPORT bool wmsUseLayerIds(const QgsProject &project)
Returns if layer ids are used as name in WMS.
SERVER_EXPORT QStringList wmsRestrictedLayers(const QgsProject &project)
Returns the restricted layer name list.
CONSTLATIN1STRING geoEpsgCrsAuthId()
Geographic coord sys from EPSG authority.
Definition: qgis.h:4484
bool setBoundingRect(const QgsProject *project, QgsWmsLayerInfos &pLayer, QgsMapLayer *ml, const QgsRectangle &wmsExtent, const QgsCoordinateReferenceSystem &wgs84, const QList< QgsCoordinateReferenceSystem > &outputCrsList)