QGIS API Documentation 3.41.0-Master (af5edcb665c)
Loading...
Searching...
No Matches
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{
40 QgsCoordinateTransform transformer { source, destination, context };
41 transformer.setBallparkTransformsAreAppropriate( ballparkTransformsAreAppropriate );
42 // Transform extent and do not catch exception
43 return transformer.transformBoundingBox( extent );
44}
45
47 const QgsRectangle &extent,
48 const QgsCoordinateReferenceSystem &source,
49 const QList<QgsCoordinateReferenceSystem> &destinations,
51)
52{
53 QMap<QString, QgsRectangle> crsExtents;
54 if ( extent.isEmpty() )
55 {
56 return crsExtents;
57 }
58 for ( const QgsCoordinateReferenceSystem &destination : std::as_const( destinations ) )
59 {
60 // Transform extent and do not catch exception
61 QgsCoordinateTransform crsTransform { source, destination, context };
62 crsExtents[destination.authid()] = crsTransform.transformBoundingBox( extent );
63 }
64 return crsExtents;
65}
66
67
69 const QgsProject *project,
70 QgsWmsLayerInfos &pLayer,
71 QgsMapLayer *ml,
72 const QgsRectangle &wmsExtent,
74 const QList<QgsCoordinateReferenceSystem> &outputCrsList
75)
76{
77 QgsRectangle layerExtent = ml->extent();
78 if ( layerExtent.isEmpty() )
79 {
80 // if the extent is empty (not only Null), use the wms extent
81 // defined in the project...
82 if ( wmsExtent.isNull() )
83 {
84 // or the CRS extent otherwise
85 layerExtent = ml->crs().bounds();
86 }
87 else
88 {
89 layerExtent = QgsRectangle( wmsExtent );
90 if ( ml->crs() != project->crs() )
91 {
92 // If CRS is different transform it to layer's CRS
93 try
94 {
95 layerExtent = QgsWmsLayerInfos::transformExtent( wmsExtent, project->crs(), ml->crs(), project->transformContext() );
96 }
97 catch ( QgsCsException &cse )
98 {
99 QgsMessageLog::logMessage( QStringLiteral( "Error transforming extent for layer %1: %2" ).arg( ml->name() ).arg( cse.what() ), QStringLiteral( "Server" ), Qgis::MessageLevel::Warning );
100 return false;
101 }
102 }
103 }
104
105 // Now we have a layer Extent we need the WGS84 bounding rectangle
106 try
107 {
108 pLayer.wgs84BoundingRect = QgsWmsLayerInfos::transformExtent( layerExtent, ml->crs(), wgs84, project->transformContext(), true );
109 }
110 catch ( const QgsCsException &cse )
111 {
112 QgsMessageLog::logMessage( QStringLiteral( "Error transforming extent for layer %1: %2" ).arg( ml->name() ).arg( cse.what() ), QStringLiteral( "Server" ), Qgis::MessageLevel::Warning );
113 return false;
114 }
115 }
116 else
117 {
118 pLayer.wgs84BoundingRect = ml->wgs84Extent();
119 }
120
121 try
122 {
124 layerExtent, ml->crs(), outputCrsList, project->transformContext()
125 );
126 }
127 catch ( QgsCsException &cse )
128 {
129 QgsMessageLog::logMessage( QStringLiteral( "Error transforming extent for layer %1: %2" ).arg( ml->name() ).arg( cse.what() ), QStringLiteral( "Server" ), Qgis::MessageLevel::Warning );
130 return false;
131 }
132
133 return true;
134}
135
136// ===================================
137// Get wms layer infos
138// ===================================
139QMap<QString, QgsWmsLayerInfos> QgsWmsLayerInfos::buildWmsLayerInfos(
140 QgsServerInterface *serverIface,
141 const QgsProject *project,
142 const QList<QgsCoordinateReferenceSystem> &outputCrsList
143)
144{
145 QMap<QString, QgsWmsLayerInfos> wmsLayers;
146#ifdef HAVE_SERVER_PYTHON_PLUGINS
147 QgsAccessControl *accessControl = serverIface->accessControls();
148#else
149 ( void ) serverIface;
150#endif
151
152 bool useLayerIds = QgsServerProjectUtils::wmsUseLayerIds( *project );
153 const QStringList restrictedLayers = QgsServerProjectUtils::wmsRestrictedLayers( *project );
154 const QgsRectangle wmsExtent = QgsServerProjectUtils::wmsExtent( *project );
156
157 for ( QgsMapLayer *ml : project->mapLayers() )
158 {
159 if ( !ml || restrictedLayers.contains( ml->name() ) ) //unpublished layer
160 {
161 continue;
162 }
163
164#ifdef HAVE_SERVER_PYTHON_PLUGINS
165 if ( accessControl && !accessControl->layerReadPermission( ml ) )
166 {
167 continue;
168 }
169#endif
170
171 QgsWmsLayerInfos pLayer;
172 pLayer.id = ml->id();
173
174 // Calculate layer extents for the WMS output CRSes list
175 // First define if the layer has an extent
176 // Vector layer with No Geometry has no extent the other has one
177 bool hasExtent = true;
178 if ( ml->type() == Qgis::LayerType::Vector )
179 {
180 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( ml );
181 if ( !vLayer || vLayer->wkbType() == Qgis::WkbType::NoGeometry )
182 {
183 hasExtent = false;
184 }
185 }
186
187 // If the layer has an extent and we cannot get CRS bounding boxes, do not keep the layer
188 if ( hasExtent && !setBoundingRect( project, pLayer, ml, wmsExtent, wgs84, outputCrsList ) )
189 continue;
190
191 // layer type
192 pLayer.type = ml->type();
193 // layer wms name
194 pLayer.name = ml->name();
195 if ( useLayerIds )
196 {
197 pLayer.name = ml->id();
198 }
199 else if ( !ml->serverProperties()->shortName().isEmpty() )
200 {
201 pLayer.name = ml->serverProperties()->shortName();
202 }
203 // layer title
204 pLayer.title = ml->serverProperties()->title();
205 if ( pLayer.title.isEmpty() )
206 {
207 pLayer.title = ml->name();
208 }
209 // layer abstract
210 pLayer.abstract = ml->serverProperties()->abstract();
211 // layer is queryable
212 pLayer.queryable = ml->flags().testFlag( QgsMapLayer::Identifiable );
213 // layer keywords
214 if ( !ml->serverProperties()->keywordList().isEmpty() )
215 {
216 pLayer.keywords = ml->serverProperties()->keywordList().split( ',' );
217 }
218 // layer styles
219 pLayer.styles = ml->styleManager()->styles();
220 // layer legend URL
221 pLayer.legendUrl = ml->legendUrl();
222 // layer legend URL format
223 pLayer.legendUrlFormat = ml->legendUrlFormat();
224 // layer min/max scales
225 if ( ml->hasScaleBasedVisibility() )
226 {
227 pLayer.hasScaleBasedVisibility = ml->hasScaleBasedVisibility();
228 pLayer.maxScale = ml->maximumScale();
229 pLayer.minScale = ml->minimumScale();
230 }
231 // layer data URL
232 pLayer.dataUrl = ml->serverProperties()->dataUrl();
233 // layer attribution
234 pLayer.attribution = ml->serverProperties()->attribution();
235 pLayer.attributionUrl = ml->serverProperties()->attributionUrl();
236 // layer metadata URLs
237 pLayer.metadataUrls = ml->serverProperties()->metadataUrls();
238
239 wmsLayers[pLayer.id] = pLayer;
240 }
241
242 return wmsLayers;
243}
@ Warning
Warning message.
Definition qgis.h:156
@ Vector
Vector layer.
@ 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.
QString what() const
Base class for all map layer types.
Definition qgsmaplayer.h:76
QString name
Definition qgsmaplayer.h:80
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:83
@ Identifiable
If the layer is identifiable using the identify map tool and as a WMS layer.
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.
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:6555
bool setBoundingRect(const QgsProject *project, QgsWmsLayerInfos &pLayer, QgsMapLayer *ml, const QgsRectangle &wmsExtent, const QgsCoordinateReferenceSystem &wgs84, const QList< QgsCoordinateReferenceSystem > &outputCrsList)