51 void appendLayerProjectSettings( QDomDocument &doc, QDomElement &layerElem,
QgsMapLayer *currentLayer );
53 void appendDrawingOrder( QDomDocument &doc, QDomElement &parentElem,
QgsServerInterface *serverIface,
56 void combineExtentAndCrsOfGroupChildren( QDomDocument &doc, QDomElement &groupElem,
const QgsProject *project,
57 bool considerMapExtent =
false );
59 bool crsSetFromLayerElement(
const QDomElement &layerElement, QSet<QString> &crsSet );
61 QgsRectangle layerBoundingBoxInProjectCrs(
const QDomDocument &doc,
const QDomElement &layerElem,
64 void appendLayerBoundingBox( QDomDocument &doc, QDomElement &layerElem,
const QgsRectangle &layerExtent,
68 void appendLayerBoundingBoxes( QDomDocument &doc, QDomElement &layerElem,
const QgsRectangle &lExtent,
70 const QStringList &constrainedCrsList,
const QgsProject *project );
72 void appendCrsElementToLayer( QDomDocument &doc, QDomElement &layerElement,
const QDomElement &precedingElement,
73 const QString &crsText );
75 void appendCrsElementsToLayer( QDomDocument &doc, QDomElement &layerElement,
76 const QStringList &crsList,
const QStringList &constrainedCrsList );
78 void appendLayerStyles( QDomDocument &doc, QDomElement &layerElem,
QgsMapLayer *currentLayer,
81 void appendLayersFromTreeGroup( QDomDocument &doc,
82 QDomElement &parentLayer,
85 const QString &version,
88 bool projectSettings );
90 void addKeywordListElement(
const QgsProject *project, QDomDocument &doc, QDomElement &parent );
97 #ifdef HAVE_SERVER_PYTHON_PLUGINS
102 const QDomDocument *capabilitiesDocument =
nullptr;
107 QStringList cacheKeyList;
108 cacheKeyList << ( projectSettings ? QStringLiteral(
"projectSettings" ) : version );
109 cacheKeyList << request.
url().host();
112 #ifdef HAVE_SERVER_PYTHON_PLUGINS
116 QString cacheKey = cacheKeyList.join(
'-' );
118 #ifdef HAVE_SERVER_PYTHON_PLUGINS
120 if ( cacheManager && cacheManager->
getCachedDocument( &doc, project, request, accessControl ) )
122 capabilitiesDocument = &doc;
125 if ( !capabilitiesDocument && cache )
130 if ( !capabilitiesDocument )
132 QgsMessageLog::logMessage( QStringLiteral(
"WMS capabilities document not found in cache" ), QStringLiteral(
"Server" ) );
134 doc =
getCapabilities( serverIface, project, version, request, projectSettings );
136 #ifdef HAVE_SERVER_PYTHON_PLUGINS
140 capabilitiesDocument = &doc;
145 if ( !capabilitiesDocument )
150 if ( !capabilitiesDocument )
152 capabilitiesDocument = &doc;
164 response.
setHeader( QStringLiteral(
"Content-Type" ), QStringLiteral(
"text/xml; charset=utf-8" ) );
165 response.
write( capabilitiesDocument->toByteArray() );
170 bool projectSettings )
173 QDomElement wmsCapabilitiesElement;
179 QString hrefString = href.toString();
180 hrefString.append( href.hasQuery() ?
"&" :
"?" );
183 QDomProcessingInstruction xmlDeclaration = doc.createProcessingInstruction( QStringLiteral(
"xml" ),
184 QStringLiteral(
"version=\"1.0\" encoding=\"utf-8\"" ) );
187 std::function < void ( QDomElement &,
const QString & ) > appendFormat = [&doc]( QDomElement & elem,
const QString & format )
189 QDomElement formatElem = doc.createElement( QStringLiteral(
"Format" ) );
190 formatElem.appendChild( doc.createTextNode( format ) );
191 elem.appendChild( formatElem );
194 if ( version == QLatin1String(
"1.1.1" ) )
196 doc = QDomDocument( QStringLiteral(
"WMT_MS_Capabilities SYSTEM 'http://schemas.opengis.net/wms/1.1.1/WMS_MS_Capabilities.dtd'" ) );
197 doc.appendChild( xmlDeclaration );
198 wmsCapabilitiesElement = doc.createElement( QStringLiteral(
"WMT_MS_Capabilities" ) );
202 doc.appendChild( xmlDeclaration );
203 wmsCapabilitiesElement = doc.createElement( QStringLiteral(
"WMS_Capabilities" ) );
204 wmsCapabilitiesElement.setAttribute( QStringLiteral(
"xmlns" ), QStringLiteral(
"http://www.opengis.net/wms" ) );
205 wmsCapabilitiesElement.setAttribute( QStringLiteral(
"xmlns:sld" ), QStringLiteral(
"http://www.opengis.net/sld" ) );
206 wmsCapabilitiesElement.setAttribute( QStringLiteral(
"xmlns:qgs" ), QStringLiteral(
"http://www.qgis.org/wms" ) );
207 wmsCapabilitiesElement.setAttribute( QStringLiteral(
"xmlns:xsi" ), QStringLiteral(
"http://www.w3.org/2001/XMLSchema-instance" ) );
208 QString schemaLocation = QStringLiteral(
"http://www.opengis.net/wms" );
209 schemaLocation += QLatin1String(
" http://schemas.opengis.net/wms/1.3.0/capabilities_1_3_0.xsd" );
210 schemaLocation += QLatin1String(
" http://www.opengis.net/sld" );
211 schemaLocation += QLatin1String(
" http://schemas.opengis.net/sld/1.1.0/sld_capabilities.xsd" );
215 wmsCapabilitiesElement.setAttribute( QStringLiteral(
"xmlns:inspire_common" ), QStringLiteral(
"http://inspire.ec.europa.eu/schemas/common/1.0" ) );
216 wmsCapabilitiesElement.setAttribute( QStringLiteral(
"xmlns:inspire_vs" ), QStringLiteral(
"http://inspire.ec.europa.eu/schemas/inspire_vs/1.0" ) );
217 schemaLocation += QLatin1String(
" http://inspire.ec.europa.eu/schemas/inspire_vs/1.0" );
218 schemaLocation += QLatin1String(
" http://inspire.ec.europa.eu/schemas/inspire_vs/1.0/inspire_vs.xsd" );
221 schemaLocation += QLatin1String(
" http://www.qgis.org/wms" );
222 schemaLocation +=
" " + hrefString +
"SERVICE=WMS&REQUEST=GetSchemaExtension";
224 wmsCapabilitiesElement.setAttribute( QStringLiteral(
"xsi:schemaLocation" ), schemaLocation );
226 wmsCapabilitiesElement.setAttribute( QStringLiteral(
"version" ), version );
227 doc.appendChild( wmsCapabilitiesElement );
230 wmsCapabilitiesElement.appendChild(
getServiceElement( doc, project, version, request ) );
233 QDomElement capabilityElement =
getCapabilityElement( doc, project, version, request, projectSettings, serverIface );
234 wmsCapabilitiesElement.appendChild( capabilityElement );
236 if ( projectSettings )
245 capabilityElement.appendChild(
249 if ( projectSettings )
251 appendDrawingOrder( doc, capabilityElement, serverIface, project );
261 QDomElement serviceElem = doc.createElement( QStringLiteral(
"Service" ) );
264 QDomElement nameElem = doc.createElement( QStringLiteral(
"Name" ) );
265 QDomText nameText = doc.createTextNode( QStringLiteral(
"WMS" ) );
266 nameElem.appendChild( nameText );
267 serviceElem.appendChild( nameElem );
271 QDomElement titleElem = doc.createElement( QStringLiteral(
"Title" ) );
272 if ( !title.isEmpty() )
274 titleText = doc.createTextNode( title );
278 if ( !project->
title().isEmpty() )
280 titleText = doc.createTextNode( project->
title() );
284 titleText = doc.createTextNode( QStringLiteral(
"untitled" ) );
287 titleElem.appendChild( titleText );
288 serviceElem.appendChild( titleElem );
291 if ( !
abstract.isEmpty() )
293 QDomElement abstractElem = doc.createElement( QStringLiteral(
"Abstract" ) );
294 QDomText abstractText = doc.createCDATASection(
abstract );
295 abstractElem.appendChild( abstractText );
296 serviceElem.appendChild( abstractElem );
299 addKeywordListElement( project, doc, serviceElem );
302 if ( onlineResource.isEmpty() )
304 onlineResource =
serviceUrl( request, project ).toString();
306 QDomElement onlineResourceElem = doc.createElement( QStringLiteral(
"OnlineResource" ) );
307 onlineResourceElem.setAttribute( QStringLiteral(
"xmlns:xlink" ), QStringLiteral(
"http://www.w3.org/1999/xlink" ) );
308 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
309 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:href" ), onlineResource );
310 serviceElem.appendChild( onlineResourceElem );
317 if ( !contactPerson.isEmpty() ||
318 !contactOrganization.isEmpty() ||
319 !contactPosition.isEmpty() ||
320 !contactMail.isEmpty() ||
321 !contactPhone.isEmpty() )
324 QDomElement contactInfoElem = doc.createElement( QStringLiteral(
"ContactInformation" ) );
327 if ( !contactPerson.isEmpty() ||
328 !contactOrganization.isEmpty() )
330 QDomElement contactPersonPrimaryElem = doc.createElement( QStringLiteral(
"ContactPersonPrimary" ) );
332 QDomText contactPersonText;
333 if ( !contactPerson.isEmpty() )
335 contactPersonText = doc.createTextNode( contactPerson );
339 contactPersonText = doc.createTextNode( QStringLiteral(
"unknown" ) );
341 QDomElement contactPersonElem = doc.createElement( QStringLiteral(
"ContactPerson" ) );
342 contactPersonElem.appendChild( contactPersonText );
343 contactPersonPrimaryElem.appendChild( contactPersonElem );
345 QDomText contactOrganizationText;
346 if ( !contactOrganization.isEmpty() )
348 contactOrganizationText = doc.createTextNode( contactOrganization );
352 contactOrganizationText = doc.createTextNode( QStringLiteral(
"unknown" ) );
354 QDomElement contactOrganizationElem = doc.createElement( QStringLiteral(
"ContactOrganization" ) );
355 contactOrganizationElem.appendChild( contactOrganizationText );
356 contactPersonPrimaryElem.appendChild( contactOrganizationElem );
358 contactInfoElem.appendChild( contactPersonPrimaryElem );
361 if ( !contactPosition.isEmpty() )
363 QDomElement contactPositionElem = doc.createElement( QStringLiteral(
"ContactPosition" ) );
364 QDomText contactPositionText = doc.createTextNode( contactPosition );
365 contactPositionElem.appendChild( contactPositionText );
366 contactInfoElem.appendChild( contactPositionElem );
369 if ( !contactPhone.isEmpty() )
371 QDomElement phoneElem = doc.createElement( QStringLiteral(
"ContactVoiceTelephone" ) );
372 QDomText phoneText = doc.createTextNode( contactPhone );
373 phoneElem.appendChild( phoneText );
374 contactInfoElem.appendChild( phoneElem );
377 if ( !contactMail.isEmpty() )
379 QDomElement mailElem = doc.createElement( QStringLiteral(
"ContactElectronicMailAddress" ) );
380 QDomText mailText = doc.createTextNode( contactMail );
381 mailElem.appendChild( mailText );
382 contactInfoElem.appendChild( mailElem );
385 serviceElem.appendChild( contactInfoElem );
388 QDomElement feesElem = doc.createElement( QStringLiteral(
"Fees" ) );
389 QDomText feesText = doc.createTextNode( QStringLiteral(
"None" ) );
391 if ( !fees.isEmpty() )
393 feesText = doc.createTextNode( fees );
395 feesElem.appendChild( feesText );
396 serviceElem.appendChild( feesElem );
398 QDomElement accessConstraintsElem = doc.createElement( QStringLiteral(
"AccessConstraints" ) );
399 QDomText accessConstraintsText = doc.createTextNode( QStringLiteral(
"None" ) );
401 if ( !accessConstraints.isEmpty() )
403 accessConstraintsText = doc.createTextNode( accessConstraints );
405 accessConstraintsElem.appendChild( accessConstraintsText );
406 serviceElem.appendChild( accessConstraintsElem );
408 if ( version == QLatin1String(
"1.3.0" ) )
413 QDomElement maxWidthElem = doc.createElement( QStringLiteral(
"MaxWidth" ) );
414 QDomText maxWidthText = doc.createTextNode( QString::number( maxWidth ) );
415 maxWidthElem.appendChild( maxWidthText );
416 serviceElem.appendChild( maxWidthElem );
422 QDomElement maxHeightElem = doc.createElement( QStringLiteral(
"MaxHeight" ) );
423 QDomText maxHeightText = doc.createTextNode( QString::number( maxHeight ) );
424 maxHeightElem.appendChild( maxHeightText );
425 serviceElem.appendChild( maxHeightElem );
442 QString hrefString = href.toString();
443 hrefString.append( href.hasQuery() ?
"&" :
"?" );
445 QDomElement capabilityElem = doc.createElement( QStringLiteral(
"Capability" ) );
448 QDomElement requestElem = doc.createElement( QStringLiteral(
"Request" ) );
449 capabilityElem.appendChild( requestElem );
451 QDomElement dcpTypeElem = doc.createElement( QStringLiteral(
"DCPType" ) );
452 QDomElement httpElem = doc.createElement( QStringLiteral(
"HTTP" ) );
453 dcpTypeElem.appendChild( httpElem );
456 std::function < void ( QDomElement &,
const QString & ) > appendFormat = [&doc]( QDomElement & elem,
const QString & format )
458 QDomElement formatElem = doc.createElement( QStringLiteral(
"Format" ) );
459 formatElem.appendChild( doc.createTextNode( format ) );
460 elem.appendChild( formatElem );
466 elem = doc.createElement( QStringLiteral(
"GetCapabilities" ) );
467 appendFormat( elem, ( version == QLatin1String(
"1.1.1" ) ?
"application/vnd.ogc.wms_xml" :
"text/xml" ) );
468 elem.appendChild( dcpTypeElem );
469 requestElem.appendChild( elem );
474 if ( parameters.value( QStringLiteral(
"SERVICE" ) ).compare( QLatin1String(
"WMS" ), Qt::CaseInsensitive ) != 0 )
476 QDomElement soapElem = doc.createElement( QStringLiteral(
"SOAP" ) );
477 httpElem.appendChild( soapElem );
478 QDomElement soapResourceElem = doc.createElement( QStringLiteral(
"OnlineResource" ) );
479 soapResourceElem.setAttribute( QStringLiteral(
"xmlns:xlink" ), QStringLiteral(
"http://www.w3.org/1999/xlink" ) );
480 soapResourceElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
481 soapResourceElem.setAttribute( QStringLiteral(
"xlink:href" ), hrefString );
482 soapElem.appendChild( soapResourceElem );
486 QDomElement getElem = doc.createElement( QStringLiteral(
"Get" ) );
487 httpElem.appendChild( getElem );
488 QDomElement olResourceElem = doc.createElement( QStringLiteral(
"OnlineResource" ) );
489 olResourceElem.setAttribute( QStringLiteral(
"xmlns:xlink" ), QStringLiteral(
"http://www.w3.org/1999/xlink" ) );
490 olResourceElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
491 olResourceElem.setAttribute( QStringLiteral(
"xlink:href" ), hrefString );
492 getElem.appendChild( olResourceElem );
495 elem = doc.createElement( QStringLiteral(
"GetMap" ) );
496 appendFormat( elem, QStringLiteral(
"image/jpeg" ) );
497 appendFormat( elem, QStringLiteral(
"image/png" ) );
498 appendFormat( elem, QStringLiteral(
"image/png; mode=16bit" ) );
499 appendFormat( elem, QStringLiteral(
"image/png; mode=8bit" ) );
500 appendFormat( elem, QStringLiteral(
"image/png; mode=1bit" ) );
501 appendFormat( elem, QStringLiteral(
"application/dxf" ) );
502 elem.appendChild( dcpTypeElem.cloneNode().toElement() );
503 requestElem.appendChild( elem );
506 elem = doc.createElement( QStringLiteral(
"GetFeatureInfo" ) );
507 appendFormat( elem, QStringLiteral(
"text/plain" ) );
508 appendFormat( elem, QStringLiteral(
"text/html" ) );
509 appendFormat( elem, QStringLiteral(
"text/xml" ) );
510 appendFormat( elem, QStringLiteral(
"application/vnd.ogc.gml" ) );
511 appendFormat( elem, QStringLiteral(
"application/vnd.ogc.gml/3.1.1" ) );
512 appendFormat( elem, QStringLiteral(
"application/json" ) );
513 appendFormat( elem, QStringLiteral(
"application/geo+json" ) );
514 elem.appendChild( dcpTypeElem.cloneNode().toElement() );
515 requestElem.appendChild( elem );
518 elem = doc.createElement( ( version == QLatin1String(
"1.1.1" ) ?
"GetLegendGraphic" :
"sld:GetLegendGraphic" ) );
519 appendFormat( elem, QStringLiteral(
"image/jpeg" ) );
520 appendFormat( elem, QStringLiteral(
"image/png" ) );
521 appendFormat( elem, QStringLiteral(
"application/json" ) );
522 elem.appendChild( dcpTypeElem.cloneNode().toElement() );
523 requestElem.appendChild( elem );
526 elem = doc.createElement( ( version == QLatin1String(
"1.1.1" ) ?
"DescribeLayer" :
"sld:DescribeLayer" ) );
527 appendFormat( elem, QStringLiteral(
"text/xml" ) );
528 elem.appendChild( dcpTypeElem.cloneNode().toElement() );
529 requestElem.appendChild( elem );
532 elem = doc.createElement( ( version == QLatin1String(
"1.1.1" ) ?
"GetStyles" :
"qgs:GetStyles" ) );
533 appendFormat( elem, QStringLiteral(
"text/xml" ) );
534 elem.appendChild( dcpTypeElem.cloneNode().toElement() );
535 requestElem.appendChild( elem );
541 elem = doc.createElement( QStringLiteral(
"GetPrint" ) );
542 appendFormat( elem, QStringLiteral(
"svg" ) );
543 appendFormat( elem, QStringLiteral(
"png" ) );
544 appendFormat( elem, QStringLiteral(
"pdf" ) );
545 elem.appendChild( dcpTypeElem.cloneNode().toElement() );
546 requestElem.appendChild( elem );
550 elem = doc.createElement( QStringLiteral(
"Exception" ) );
551 appendFormat( elem, ( version == QLatin1String(
"1.1.1" ) ?
"application/vnd.ogc.se_xml" :
"XML" ) );
552 capabilityElem.appendChild( elem );
555 if ( version == QLatin1String(
"1.3.0" ) )
557 elem = doc.createElement( QStringLiteral(
"sld:UserDefinedSymbolization" ) );
558 elem.setAttribute( QStringLiteral(
"SupportSLD" ), QStringLiteral(
"1" ) );
559 elem.setAttribute( QStringLiteral(
"UserLayer" ), QStringLiteral(
"0" ) );
560 elem.setAttribute( QStringLiteral(
"UserStyle" ), QStringLiteral(
"1" ) );
561 elem.setAttribute( QStringLiteral(
"RemoteWFS" ), QStringLiteral(
"0" ) );
562 elem.setAttribute( QStringLiteral(
"InlineFeature" ), QStringLiteral(
"0" ) );
563 elem.setAttribute( QStringLiteral(
"RemoteWCS" ), QStringLiteral(
"0" ) );
564 capabilityElem.appendChild( elem );
572 return capabilityElem;
577 QDomElement inspireCapabilitiesElem;
580 return inspireCapabilitiesElem;
582 inspireCapabilitiesElem = doc.createElement( QStringLiteral(
"inspire_vs:ExtendedCapabilities" ) );
586 if ( !inspireMetadataUrl.isEmpty() )
588 QDomElement inspireCommonMetadataUrlElem = doc.createElement( QStringLiteral(
"inspire_common:MetadataUrl" ) );
589 inspireCommonMetadataUrlElem.setAttribute( QStringLiteral(
"xsi:type" ), QStringLiteral(
"inspire_common:resourceLocatorType" ) );
591 QDomElement inspireCommonMetadataUrlUrlElem = doc.createElement( QStringLiteral(
"inspire_common:URL" ) );
592 inspireCommonMetadataUrlUrlElem.appendChild( doc.createTextNode( inspireMetadataUrl ) );
593 inspireCommonMetadataUrlElem.appendChild( inspireCommonMetadataUrlUrlElem );
596 if ( !inspireMetadataUrlType.isNull() )
598 QDomElement inspireCommonMetadataUrlMediaTypeElem = doc.createElement( QStringLiteral(
"inspire_common:MediaType" ) );
599 inspireCommonMetadataUrlMediaTypeElem.appendChild( doc.createTextNode( inspireMetadataUrlType ) );
600 inspireCommonMetadataUrlElem.appendChild( inspireCommonMetadataUrlMediaTypeElem );
603 inspireCapabilitiesElem.appendChild( inspireCommonMetadataUrlElem );
607 QDomElement inspireCommonResourceTypeElem = doc.createElement( QStringLiteral(
"inspire_common:ResourceType" ) );
608 inspireCommonResourceTypeElem.appendChild( doc.createTextNode( QStringLiteral(
"service" ) ) );
609 inspireCapabilitiesElem.appendChild( inspireCommonResourceTypeElem );
611 QDomElement inspireCommonSpatialDataServiceTypeElem = doc.createElement( QStringLiteral(
"inspire_common:SpatialDataServiceType" ) );
612 inspireCommonSpatialDataServiceTypeElem.appendChild( doc.createTextNode( QStringLiteral(
"view" ) ) );
613 inspireCapabilitiesElem.appendChild( inspireCommonSpatialDataServiceTypeElem );
616 if ( !inspireTemporalReference.isNull() )
618 QDomElement inspireCommonTemporalReferenceElem = doc.createElement( QStringLiteral(
"inspire_common:TemporalReference" ) );
619 QDomElement inspireCommonDateOfLastRevisionElem = doc.createElement( QStringLiteral(
"inspire_common:DateOfLastRevision" ) );
620 inspireCommonDateOfLastRevisionElem.appendChild( doc.createTextNode( inspireTemporalReference ) );
621 inspireCommonTemporalReferenceElem.appendChild( inspireCommonDateOfLastRevisionElem );
622 inspireCapabilitiesElem.appendChild( inspireCommonTemporalReferenceElem );
625 QDomElement inspireCommonMetadataPointOfContactElem = doc.createElement( QStringLiteral(
"inspire_common:MetadataPointOfContact" ) );
628 QDomElement inspireCommonOrganisationNameElem = doc.createElement( QStringLiteral(
"inspire_common:OrganisationName" ) );
629 if ( !contactOrganization.isNull() )
631 inspireCommonOrganisationNameElem.appendChild( doc.createTextNode( contactOrganization ) );
633 inspireCommonMetadataPointOfContactElem.appendChild( inspireCommonOrganisationNameElem );
636 QDomElement inspireCommonEmailAddressElem = doc.createElement( QStringLiteral(
"inspire_common:EmailAddress" ) );
637 if ( !contactMail.isNull() )
639 inspireCommonEmailAddressElem.appendChild( doc.createTextNode( contactMail ) );
641 inspireCommonMetadataPointOfContactElem.appendChild( inspireCommonEmailAddressElem );
643 inspireCapabilitiesElem.appendChild( inspireCommonMetadataPointOfContactElem );
646 if ( !inspireMetadataDate.isNull() )
648 QDomElement inspireCommonMetadataDateElem = doc.createElement( QStringLiteral(
"inspire_common:MetadataDate" ) );
649 inspireCommonMetadataDateElem.appendChild( doc.createTextNode( inspireMetadataDate ) );
650 inspireCapabilitiesElem.appendChild( inspireCommonMetadataDateElem );
655 QDomElement inspireCommonSupportedLanguagesElem = doc.createElement( QStringLiteral(
"inspire_common:SupportedLanguages" ) );
656 inspireCommonSupportedLanguagesElem.setAttribute( QStringLiteral(
"xsi:type" ), QStringLiteral(
"inspire_common:supportedLanguagesType" ) );
658 QDomElement inspireCommonLanguageElem = doc.createElement( QStringLiteral(
"inspire_common:Language" ) );
661 QDomElement inspireCommonDefaultLanguageElem = doc.createElement( QStringLiteral(
"inspire_common:DefaultLanguage" ) );
662 inspireCommonDefaultLanguageElem.appendChild( inspireCommonLanguageElem );
663 inspireCommonSupportedLanguagesElem.appendChild( inspireCommonDefaultLanguageElem );
667 QDomElement inspireCommonSupportedLanguageElem = doc.createElement(
"inspire_common:SupportedLanguage" );
668 inspireCommonSupportedLanguageElem.appendChild( inspireCommonLanguageElem.cloneNode().toElement() );
669 inspireCommonSupportedLanguagesElem.appendChild( inspireCommonSupportedLanguageElem );
672 inspireCapabilitiesElem.appendChild( inspireCommonSupportedLanguagesElem );
674 QDomElement inspireCommonResponseLanguageElem = doc.createElement( QStringLiteral(
"inspire_common:ResponseLanguage" ) );
675 inspireCommonResponseLanguageElem.appendChild( inspireCommonLanguageElem.cloneNode().toElement() );
676 inspireCapabilitiesElem.appendChild( inspireCommonResponseLanguageElem );
678 return inspireCapabilitiesElem;
684 if ( projectComposers.size() == 0 )
685 return QDomElement();
689 QDomElement composerTemplatesElem = doc.createElement( QStringLiteral(
"ComposerTemplates" ) );
690 QList<QgsPrintLayout *>::const_iterator cIt = projectComposers.constBegin();
691 for ( ; cIt != projectComposers.constEnd(); ++cIt )
694 if ( restrictedComposers.contains( layout->
name() ) )
706 QDomElement composerTemplateElem = doc.createElement( QStringLiteral(
"ComposerTemplate" ) );
707 composerTemplateElem.setAttribute( QStringLiteral(
"name" ), layout->
name() );
710 composerTemplateElem.setAttribute( QStringLiteral(
"width" ), width.
length() );
711 composerTemplateElem.setAttribute( QStringLiteral(
"height" ), height.
length() );
715 if ( atlas && atlas->
enabled() )
717 composerTemplateElem.setAttribute( QStringLiteral(
"atlasEnabled" ), QStringLiteral(
"1" ) );
724 layerName = cLayer->
id();
726 else if ( layerName.isEmpty() )
728 layerName = cLayer->
name();
730 composerTemplateElem.setAttribute( QStringLiteral(
"atlasCoverageLayer" ), layerName );
735 QList<QgsLayoutItemMap *> layoutMapList;
737 QList<QgsLayoutItemMap *>::const_iterator cmIt = layoutMapList.constBegin();
740 for ( ; cmIt != layoutMapList.constEnd(); ++cmIt )
744 QDomElement composerMapElem = doc.createElement( QStringLiteral(
"ComposerMap" ) );
745 composerMapElem.setAttribute( QStringLiteral(
"name" ), QStringLiteral(
"map%1" ).arg( mapId ) );
747 composerMapElem.setAttribute( QStringLiteral(
"width" ), composerMap->rect().width() );
748 composerMapElem.setAttribute( QStringLiteral(
"height" ), composerMap->rect().height() );
749 composerTemplateElem.appendChild( composerMapElem );
753 QList<QgsLayoutItemLabel *> composerLabelList;
755 QList<QgsLayoutItemLabel *>::const_iterator clIt = composerLabelList.constBegin();
756 for ( ; clIt != composerLabelList.constEnd(); ++clIt )
759 QString
id = composerLabel->
id();
763 QDomElement composerLabelElem = doc.createElement( QStringLiteral(
"ComposerLabel" ) );
764 composerLabelElem.setAttribute( QStringLiteral(
"name" ), id );
765 composerTemplateElem.appendChild( composerLabelElem );
769 QList<QgsLayoutItemHtml *> composerHtmlList;
771 QList<QgsLayoutItemHtml *>::const_iterator chIt = composerHtmlList.constBegin();
772 for ( ; chIt != composerHtmlList.constEnd(); ++chIt )
778 QString
id = composerHtml->
frame( 0 )->
id();
782 QDomElement composerHtmlElem = doc.createElement( QStringLiteral(
"ComposerHtml" ) );
783 composerHtmlElem.setAttribute( QStringLiteral(
"name" ), id );
784 composerTemplateElem.appendChild( composerHtmlElem );
787 composerTemplatesElem.appendChild( composerTemplateElem );
790 if ( composerTemplatesElem.childNodes().size() == 0 )
791 return QDomElement();
793 return composerTemplatesElem;
800 return QDomElement();
802 QDomElement wfsLayersElem = doc.createElement( QStringLiteral(
"WFSLayers" ) );
811 QDomElement wfsLayerElem = doc.createElement( QStringLiteral(
"WFSLayer" ) );
814 wfsLayerElem.setAttribute( QStringLiteral(
"name" ), layer->
id() );
818 wfsLayerElem.setAttribute( QStringLiteral(
"name" ), layer->
name() );
820 wfsLayersElem.appendChild( wfsLayerElem );
823 return wfsLayersElem;
827 const QgsProject *project,
const QString &version,
832 QDomElement layerParentElem = doc.createElement( QStringLiteral(
"Layer" ) );
836 if ( rootLayerName.isEmpty() && !project->
title().isEmpty() )
838 rootLayerName = project->
title();
841 if ( !rootLayerName.isEmpty() )
843 QDomElement layerParentNameElem = doc.createElement( QStringLiteral(
"Name" ) );
844 QDomText layerParentNameText = doc.createTextNode( rootLayerName );
845 layerParentNameElem.appendChild( layerParentNameText );
846 layerParentElem.appendChild( layerParentNameElem );
849 if ( !project->
title().isEmpty() )
852 QDomElement layerParentTitleElem = doc.createElement( QStringLiteral(
"Title" ) );
853 QDomText layerParentTitleText = doc.createTextNode( project->
title() );
854 layerParentTitleElem.appendChild( layerParentTitleText );
855 layerParentElem.appendChild( layerParentTitleElem );
858 QDomElement layerParentAbstElem = doc.createElement( QStringLiteral(
"Abstract" ) );
859 QDomText layerParentAbstText = doc.createTextNode( project->
title() );
860 layerParentAbstElem.appendChild( layerParentAbstText );
861 layerParentElem.appendChild( layerParentAbstElem );
865 addKeywordListElement( project, doc, layerParentElem );
868 if ( projectSettings )
870 QDomElement treeNameElem = doc.createElement( QStringLiteral(
"TreeName" ) );
871 QDomText treeNameText = doc.createTextNode( project->
title() );
872 treeNameElem.appendChild( treeNameText );
873 layerParentElem.appendChild( treeNameElem );
878 layerParentElem.setAttribute( QStringLiteral(
"queryable" ), QStringLiteral(
"1" ) );
882 layerParentElem.setAttribute( QStringLiteral(
"queryable" ), QStringLiteral(
"0" ) );
885 appendLayersFromTreeGroup( doc, layerParentElem, serverIface, project, version, request, projectLayerTreeRoot, projectSettings );
887 combineExtentAndCrsOfGroupChildren( doc, layerParentElem, project,
true );
889 return layerParentElem;
895 void appendLayersFromTreeGroup( QDomDocument &doc,
896 QDomElement &parentLayer,
899 const QString &version,
902 bool projectSettings )
908 QList< QgsLayerTreeNode * > layerTreeGroupChildren = layerTreeGroup->
children();
909 for (
int i = 0; i < layerTreeGroupChildren.size(); ++i )
912 QDomElement layerElem = doc.createElement( QStringLiteral(
"Layer" ) );
914 if ( projectSettings )
916 layerElem.setAttribute( QStringLiteral(
"visible" ), treeNode->
isVisible() );
918 layerElem.setAttribute( QStringLiteral(
"expanded" ), treeNode->
isExpanded() );
925 QString name = treeGroupChild->
name();
926 if ( restrictedLayers.contains( name ) )
931 if ( projectSettings )
933 layerElem.setAttribute( QStringLiteral(
"mutuallyExclusive" ), treeGroupChild->
isMutuallyExclusive() );
936 QString shortName = treeGroupChild->
customProperty( QStringLiteral(
"wmsShortName" ) ).toString();
937 QString title = treeGroupChild->
customProperty( QStringLiteral(
"wmsTitle" ) ).toString();
939 QDomElement nameElem = doc.createElement( QStringLiteral(
"Name" ) );
941 if ( !shortName.isEmpty() )
942 nameText = doc.createTextNode( shortName );
944 nameText = doc.createTextNode( name );
945 nameElem.appendChild( nameText );
946 layerElem.appendChild( nameElem );
948 QDomElement titleElem = doc.createElement( QStringLiteral(
"Title" ) );
950 if ( !title.isEmpty() )
951 titleText = doc.createTextNode( title );
953 titleText = doc.createTextNode( name );
954 titleElem.appendChild( titleText );
955 layerElem.appendChild( titleElem );
957 QString
abstract = treeGroupChild->
customProperty( QStringLiteral(
"wmsAbstract" ) ).toString();
958 if ( !
abstract.isEmpty() )
960 QDomElement abstractElem = doc.createElement( QStringLiteral(
"Abstract" ) );
961 QDomText abstractText = doc.createTextNode(
abstract );
962 abstractElem.appendChild( abstractText );
963 layerElem.appendChild( abstractElem );
967 if ( projectSettings )
969 QDomElement treeNameElem = doc.createElement( QStringLiteral(
"TreeName" ) );
970 QDomText treeNameText = doc.createTextNode( name );
971 treeNameElem.appendChild( treeNameText );
972 layerElem.appendChild( treeNameElem );
978 layerElem.setAttribute( QStringLiteral(
"queryable" ), QStringLiteral(
"1" ) );
982 layerElem.setAttribute( QStringLiteral(
"queryable" ), QStringLiteral(
"0" ) );
985 appendLayersFromTreeGroup( doc, layerElem, serverIface, project, version, request, treeGroupChild, projectSettings );
987 combineExtentAndCrsOfGroupChildren( doc, layerElem, project );
993 if ( !l || restrictedLayers.contains( l->
name() ) )
998 #ifdef HAVE_SERVER_PYTHON_PLUGINS
1005 QString wmsName = l->
name();
1018 layerElem.setAttribute( QStringLiteral(
"queryable" ), QStringLiteral(
"0" ) );
1022 layerElem.setAttribute( QStringLiteral(
"queryable" ), QStringLiteral(
"1" ) );
1025 QDomElement nameElem = doc.createElement( QStringLiteral(
"Name" ) );
1026 QDomText nameText = doc.createTextNode( wmsName );
1027 nameElem.appendChild( nameText );
1028 layerElem.appendChild( nameElem );
1030 QDomElement titleElem = doc.createElement( QStringLiteral(
"Title" ) );
1031 QString title = l->
title();
1032 if ( title.isEmpty() )
1036 QDomText titleText = doc.createTextNode( title );
1037 titleElem.appendChild( titleText );
1038 layerElem.appendChild( titleElem );
1041 if ( !
abstract.isEmpty() )
1043 QDomElement abstractElem = doc.createElement( QStringLiteral(
"Abstract" ) );
1044 QDomText abstractText = doc.createTextNode(
abstract );
1045 abstractElem.appendChild( abstractText );
1046 layerElem.appendChild( abstractElem );
1052 QStringList keywordStringList = l->
keywordList().split(
',' );
1054 QDomElement keywordListElem = doc.createElement( QStringLiteral(
"KeywordList" ) );
1055 for (
int i = 0; i < keywordStringList.size(); ++i )
1057 QDomElement keywordElem = doc.createElement( QStringLiteral(
"Keyword" ) );
1058 QDomText keywordText = doc.createTextNode( keywordStringList.at( i ).trimmed() );
1059 keywordElem.appendChild( keywordText );
1062 keywordElem.setAttribute( QStringLiteral(
"vocabulary" ), QStringLiteral(
"SIA_Geo405" ) );
1064 keywordListElem.appendChild( keywordElem );
1066 layerElem.appendChild( keywordListElem );
1070 bool geometryLayer =
true;
1078 geometryLayer =
false;
1084 if ( geometryLayer )
1086 QStringList crsList;
1089 appendCrsElementsToLayer( doc, layerElem, crsList, outputCrsList );
1107 else if ( vl->
crs() != project->
crs() )
1112 extent = ct.transform( extent );
1116 QgsMessageLog::logMessage( QStringLiteral(
"Error transforming extent for layer %1: %2" ).arg( vl->
name() ).arg( cse.
what() ), QStringLiteral(
"Server" ), Qgis::MessageLevel::Warning );
1123 appendLayerBoundingBoxes( doc, layerElem, extent, l->
crs(), crsList, outputCrsList, project );
1127 appendLayerStyles( doc, layerElem, l, project, version, request );
1132 if ( version == QLatin1String(
"1.1.1" ) )
1135 double SCALE_TO_SCALEHINT =
OGC_PX_M * M_SQRT2;
1137 QDomElement scaleHintElem = doc.createElement( QStringLiteral(
"ScaleHint" ) );
1138 scaleHintElem.setAttribute( QStringLiteral(
"min" ), QString::number( l->
maximumScale() * SCALE_TO_SCALEHINT ) );
1139 scaleHintElem.setAttribute( QStringLiteral(
"max" ), QString::number( l->
minimumScale() * SCALE_TO_SCALEHINT ) );
1140 layerElem.appendChild( scaleHintElem );
1144 QString minScaleString = QString::number( l->
maximumScale() );
1145 QDomElement minScaleElem = doc.createElement( QStringLiteral(
"MinScaleDenominator" ) );
1146 QDomText minScaleText = doc.createTextNode( minScaleString );
1147 minScaleElem.appendChild( minScaleText );
1148 layerElem.appendChild( minScaleElem );
1150 QString maxScaleString = QString::number( l->
minimumScale() );
1151 QDomElement maxScaleElem = doc.createElement( QStringLiteral(
"MaxScaleDenominator" ) );
1152 QDomText maxScaleText = doc.createTextNode( maxScaleString );
1153 maxScaleElem.appendChild( maxScaleText );
1154 layerElem.appendChild( maxScaleElem );
1159 QString dataUrl = l->
dataUrl();
1160 if ( !dataUrl.isEmpty() )
1162 QDomElement dataUrlElem = doc.createElement( QStringLiteral(
"DataURL" ) );
1163 QDomElement dataUrlFormatElem = doc.createElement( QStringLiteral(
"Format" ) );
1165 QDomText dataUrlFormatText = doc.createTextNode( dataUrlFormat );
1166 dataUrlFormatElem.appendChild( dataUrlFormatText );
1167 dataUrlElem.appendChild( dataUrlFormatElem );
1168 QDomElement dataORElem = doc.createElement( QStringLiteral(
"OnlineResource" ) );
1169 dataORElem.setAttribute( QStringLiteral(
"xmlns:xlink" ), QStringLiteral(
"http://www.w3.org/1999/xlink" ) );
1170 dataORElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
1171 dataORElem.setAttribute( QStringLiteral(
"xlink:href" ), dataUrl );
1172 dataUrlElem.appendChild( dataORElem );
1173 layerElem.appendChild( dataUrlElem );
1178 if ( !attribution.isEmpty() )
1180 QDomElement attribElem = doc.createElement( QStringLiteral(
"Attribution" ) );
1181 QDomElement attribTitleElem = doc.createElement( QStringLiteral(
"Title" ) );
1182 QDomText attribText = doc.createTextNode( attribution );
1183 attribTitleElem.appendChild( attribText );
1184 attribElem.appendChild( attribTitleElem );
1186 if ( !attributionUrl.isEmpty() )
1188 QDomElement attribORElem = doc.createElement( QStringLiteral(
"OnlineResource" ) );
1189 attribORElem.setAttribute( QStringLiteral(
"xmlns:xlink" ), QStringLiteral(
"http://www.w3.org/1999/xlink" ) );
1190 attribORElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
1191 attribORElem.setAttribute( QStringLiteral(
"xlink:href" ), attributionUrl );
1192 attribElem.appendChild( attribORElem );
1194 layerElem.appendChild( attribElem );
1199 if ( !metadataUrl.isEmpty() )
1201 QDomElement metaUrlElem = doc.createElement( QStringLiteral(
"MetadataURL" ) );
1203 if ( version == QLatin1String(
"1.1.1" ) )
1205 metaUrlElem.setAttribute( QStringLiteral(
"type" ), metadataUrlType );
1207 else if ( metadataUrlType == QLatin1String(
"FGDC" ) )
1209 metaUrlElem.setAttribute( QStringLiteral(
"type" ), QStringLiteral(
"FGDC:1998" ) );
1211 else if ( metadataUrlType == QLatin1String(
"TC211" ) )
1213 metaUrlElem.setAttribute( QStringLiteral(
"type" ), QStringLiteral(
"ISO19115:2003" ) );
1217 metaUrlElem.setAttribute( QStringLiteral(
"type" ), metadataUrlType );
1220 if ( !metadataUrlFormat.isEmpty() )
1222 QDomElement metaUrlFormatElem = doc.createElement( QStringLiteral(
"Format" ) );
1223 QDomText metaUrlFormatText = doc.createTextNode( metadataUrlFormat );
1224 metaUrlFormatElem.appendChild( metaUrlFormatText );
1225 metaUrlElem.appendChild( metaUrlFormatElem );
1227 QDomElement metaUrlORElem = doc.createElement( QStringLiteral(
"OnlineResource" ) );
1228 metaUrlORElem.setAttribute( QStringLiteral(
"xmlns:xlink" ), QStringLiteral(
"http://www.w3.org/1999/xlink" ) );
1229 metaUrlORElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
1230 metaUrlORElem.setAttribute( QStringLiteral(
"xlink:href" ), metadataUrl );
1231 metaUrlElem.appendChild( metaUrlORElem );
1232 layerElem.appendChild( metaUrlElem );
1244 if ( fieldIndex == -1 )
1249 QSet<QVariant> uniqueValues = vl->
uniqueValues( fieldIndex );
1252 if ( !dim.endFieldName.isEmpty() )
1254 int endFieldIndex = vl->
fields().
indexOf( dim.endFieldName );
1256 if ( endFieldIndex == -1 )
1260 uniqueValues.unite( vl->
uniqueValues( endFieldIndex ) );
1263 QList<QVariant> values = qgis::setToList( uniqueValues );
1264 std::sort( values.begin(), values.end() );
1266 QDomElement dimElem = doc.createElement( QStringLiteral(
"Dimension" ) );
1267 dimElem.setAttribute( QStringLiteral(
"name" ), dim.name );
1268 if ( !dim.units.isEmpty() )
1270 dimElem.setAttribute( QStringLiteral(
"units" ), dim.units );
1272 if ( !dim.unitSymbol.isEmpty() )
1274 dimElem.setAttribute( QStringLiteral(
"unitSymbol" ), dim.unitSymbol );
1278 dimElem.setAttribute( QStringLiteral(
"default" ), values.first().toString() );
1282 dimElem.setAttribute( QStringLiteral(
"default" ), values.last().toString() );
1286 dimElem.setAttribute( QStringLiteral(
"default" ), dim.referenceValue.toString() );
1288 dimElem.setAttribute( QStringLiteral(
"multipleValue" ),
'1' );
1289 dimElem.setAttribute( QStringLiteral(
"nearestValue" ),
'0' );
1291 QStringList strValues;
1292 for (
const QVariant &v : values )
1294 strValues << v.toString();
1296 QDomText dimValuesText = doc.createTextNode( strValues.join( QLatin1String(
", " ) ) );
1297 dimElem.appendChild( dimValuesText );
1298 layerElem.appendChild( dimElem );
1302 if ( projectSettings )
1304 appendLayerProjectSettings( doc, layerElem, l );
1308 parentLayer.appendChild( layerElem );
1312 void appendLayerStyles( QDomDocument &doc, QDomElement &layerElem,
QgsMapLayer *currentLayer,
1319 QString hrefString = href.toString();
1320 hrefString.append( href.hasQuery() ?
"&" :
"?" );
1323 QDomElement styleElem = doc.createElement( QStringLiteral(
"Style" ) );
1324 QDomElement styleNameElem = doc.createElement( QStringLiteral(
"Name" ) );
1325 QDomText styleNameText = doc.createTextNode( styleName );
1326 styleNameElem.appendChild( styleNameText );
1327 QDomElement styleTitleElem = doc.createElement( QStringLiteral(
"Title" ) );
1328 QDomText styleTitleText = doc.createTextNode( styleName );
1329 styleTitleElem.appendChild( styleTitleText );
1330 styleElem.appendChild( styleNameElem );
1331 styleElem.appendChild( styleTitleElem );
1334 QDomElement getLayerLegendGraphicElem = doc.createElement( QStringLiteral(
"LegendURL" ) );
1336 QString customHrefString = currentLayer->
legendUrl();
1338 QStringList getLayerLegendGraphicFormats;
1339 if ( !customHrefString.isEmpty() )
1345 getLayerLegendGraphicFormats << QStringLiteral(
"image/png" );
1348 for (
int i = 0; i < getLayerLegendGraphicFormats.size(); ++i )
1350 QDomElement getLayerLegendGraphicFormatElem = doc.createElement( QStringLiteral(
"Format" ) );
1351 QString getLayerLegendGraphicFormat = getLayerLegendGraphicFormats[i];
1352 QDomText getLayerLegendGraphicFormatText = doc.createTextNode( getLayerLegendGraphicFormat );
1353 getLayerLegendGraphicFormatElem.appendChild( getLayerLegendGraphicFormatText );
1354 getLayerLegendGraphicElem.appendChild( getLayerLegendGraphicFormatElem );
1358 if ( customHrefString.isEmpty() )
1360 QString layerName = currentLayer->
name();
1362 layerName = currentLayer->
id();
1363 else if ( !currentLayer->
shortName().isEmpty() )
1365 QUrlQuery mapUrl( hrefString );
1366 mapUrl.addQueryItem( QStringLiteral(
"SERVICE" ), QStringLiteral(
"WMS" ) );
1367 mapUrl.addQueryItem( QStringLiteral(
"VERSION" ), version );
1368 mapUrl.addQueryItem( QStringLiteral(
"REQUEST" ), QStringLiteral(
"GetLegendGraphic" ) );
1369 mapUrl.addQueryItem( QStringLiteral(
"LAYER" ), layerName );
1370 mapUrl.addQueryItem( QStringLiteral(
"FORMAT" ), QStringLiteral(
"image/png" ) );
1371 mapUrl.addQueryItem( QStringLiteral(
"STYLE" ), styleNameText.data() );
1372 if ( version == QLatin1String(
"1.3.0" ) )
1374 mapUrl.addQueryItem( QStringLiteral(
"SLD_VERSION" ), QStringLiteral(
"1.1.0" ) );
1376 customHrefString = mapUrl.toString();
1379 QDomElement getLayerLegendGraphicORElem = doc.createElement( QStringLiteral(
"OnlineResource" ) );
1380 getLayerLegendGraphicORElem.setAttribute( QStringLiteral(
"xmlns:xlink" ), QStringLiteral(
"http://www.w3.org/1999/xlink" ) );
1381 getLayerLegendGraphicORElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
1382 getLayerLegendGraphicORElem.setAttribute( QStringLiteral(
"xlink:href" ), customHrefString );
1383 getLayerLegendGraphicElem.appendChild( getLayerLegendGraphicORElem );
1384 styleElem.appendChild( getLayerLegendGraphicElem );
1386 layerElem.appendChild( styleElem );
1390 void appendCrsElementsToLayer( QDomDocument &doc, QDomElement &layerElement,
1391 const QStringList &crsList,
const QStringList &constrainedCrsList )
1393 if ( layerElement.isNull() )
1399 QDomElement titleElement = layerElement.firstChildElement( QStringLiteral(
"Title" ) );
1400 QDomElement abstractElement = layerElement.firstChildElement( QStringLiteral(
"Abstract" ) );
1401 QDomElement keywordListElement = layerElement.firstChildElement( QStringLiteral(
"KeywordList" ) );
1402 QDomElement CRSPrecedingElement = !keywordListElement.isNull() ? keywordListElement : !abstractElement.isNull() ? abstractElement : titleElement;
1404 if ( CRSPrecedingElement.isNull() )
1407 const QDomElement keyElement = layerElement.firstChildElement( QStringLiteral(
"KeywordList" ) );
1408 CRSPrecedingElement = keyElement;
1412 if ( !constrainedCrsList.isEmpty() )
1414 for (
int i = constrainedCrsList.size() - 1; i >= 0; --i )
1416 appendCrsElementToLayer( doc, layerElement, CRSPrecedingElement, constrainedCrsList.at( i ) );
1421 for (
const QString &
crs : crsList )
1423 appendCrsElementToLayer( doc, layerElement, CRSPrecedingElement,
crs );
1428 appendCrsElementToLayer( doc, layerElement, CRSPrecedingElement, QString(
"CRS:84" ) );
1431 void appendCrsElementToLayer( QDomDocument &doc, QDomElement &layerElement,
const QDomElement &precedingElement,
1432 const QString &crsText )
1434 if ( crsText.isEmpty() )
1436 QString version = doc.documentElement().attribute( QStringLiteral(
"version" ) );
1437 QDomElement crsElement = doc.createElement( version == QLatin1String(
"1.1.1" ) ?
"SRS" :
"CRS" );
1438 QDomText crsTextNode = doc.createTextNode( crsText );
1439 crsElement.appendChild( crsTextNode );
1440 layerElement.insertAfter( crsElement, precedingElement );
1443 void appendLayerBoundingBoxes( QDomDocument &doc, QDomElement &layerElem,
const QgsRectangle &lExtent,
1445 const QStringList &constrainedCrsList,
const QgsProject *project )
1447 if ( layerElem.isNull() )
1456 layerExtent.
grow( 0.000001 );
1460 int wgs84precision = 6;
1462 QString version = doc.documentElement().attribute( QStringLiteral(
"version" ) );
1465 QDomElement ExGeoBBoxElement;
1468 if ( !layerExtent.
isNull() )
1473 wgs84BoundingRect = exGeoTransform.transformBoundingBox( layerExtent );
1477 QgsMessageLog::logMessage( QStringLiteral(
"Error transforming extent: %1" ).arg( cse.
what() ), QStringLiteral(
"Server" ), Qgis::MessageLevel::Warning );
1482 if ( version == QLatin1String(
"1.1.1" ) )
1484 ExGeoBBoxElement = doc.createElement( QStringLiteral(
"LatLonBoundingBox" ) );
1492 ExGeoBBoxElement = doc.createElement( QStringLiteral(
"EX_GeographicBoundingBox" ) );
1493 QDomElement wBoundLongitudeElement = doc.createElement( QStringLiteral(
"westBoundLongitude" ) );
1495 wBoundLongitudeElement.appendChild( wBoundLongitudeText );
1496 ExGeoBBoxElement.appendChild( wBoundLongitudeElement );
1497 QDomElement eBoundLongitudeElement = doc.createElement( QStringLiteral(
"eastBoundLongitude" ) );
1499 eBoundLongitudeElement.appendChild( eBoundLongitudeText );
1500 ExGeoBBoxElement.appendChild( eBoundLongitudeElement );
1501 QDomElement sBoundLatitudeElement = doc.createElement( QStringLiteral(
"southBoundLatitude" ) );
1503 sBoundLatitudeElement.appendChild( sBoundLatitudeText );
1504 ExGeoBBoxElement.appendChild( sBoundLatitudeElement );
1505 QDomElement nBoundLatitudeElement = doc.createElement( QStringLiteral(
"northBoundLatitude" ) );
1507 nBoundLatitudeElement.appendChild( nBoundLatitudeText );
1508 ExGeoBBoxElement.appendChild( nBoundLatitudeElement );
1511 if ( !wgs84BoundingRect.
isNull() )
1513 QDomElement lastCRSElem = layerElem.lastChildElement( version == QLatin1String(
"1.1.1" ) ?
"SRS" :
"CRS" );
1514 if ( !lastCRSElem.isNull() )
1516 layerElem.insertAfter( ExGeoBBoxElement, lastCRSElem );
1520 layerElem.appendChild( ExGeoBBoxElement );
1525 if ( !constrainedCrsList.isEmpty() )
1527 for (
int i = constrainedCrsList.size() - 1; i >= 0; --i )
1529 appendLayerBoundingBox( doc, layerElem, layerExtent, layerCRS, constrainedCrsList.at( i ), project );
1534 for (
const QString &
crs : crsList )
1536 appendLayerBoundingBox( doc, layerElem, layerExtent, layerCRS,
crs, project );
1542 void appendLayerBoundingBox( QDomDocument &doc, QDomElement &layerElem,
const QgsRectangle &layerExtent,
1546 if ( layerElem.isNull() )
1551 if ( crsText.isEmpty() )
1556 QString version = doc.documentElement().attribute( QStringLiteral(
"version" ) );
1562 if ( !layerExtent.
isNull() )
1567 crsExtent = crsTransform.transformBoundingBox( layerExtent );
1571 QgsMessageLog::logMessage( QStringLiteral(
"Error transforming extent: %1" ).arg( cse.
what() ), QStringLiteral(
"Server" ), Qgis::MessageLevel::Warning );
1576 if ( crsExtent.
isNull() )
1588 QDomElement bBoxElement = doc.createElement( QStringLiteral(
"BoundingBox" ) );
1591 bBoxElement.setAttribute( version == QLatin1String(
"1.1.1" ) ?
"SRS" :
"CRS",
crs.
authid() );
1604 QDomElement lastBBoxElem = layerElem.lastChildElement( QStringLiteral(
"BoundingBox" ) );
1605 if ( !lastBBoxElem.isNull() )
1607 layerElem.insertAfter( bBoxElement, lastBBoxElem );
1611 lastBBoxElem = layerElem.lastChildElement( version == QLatin1String(
"1.1.1" ) ?
"LatLonBoundingBox" :
"EX_GeographicBoundingBox" );
1612 if ( !lastBBoxElem.isNull() )
1614 layerElem.insertAfter( bBoxElement, lastBBoxElem );
1618 layerElem.appendChild( bBoxElement );
1623 QgsRectangle layerBoundingBoxInProjectCrs(
const QDomDocument &doc,
const QDomElement &layerElem,
1627 if ( layerElem.isNull() )
1633 QDomElement boundingBoxElem = layerElem.firstChildElement( QStringLiteral(
"BoundingBox" ) );
1634 if ( boundingBoxElem.isNull() )
1639 double minx, miny, maxx, maxy;
1641 minx = boundingBoxElem.attribute( QStringLiteral(
"minx" ) ).toDouble( &conversionOk );
1642 if ( !conversionOk )
1646 miny = boundingBoxElem.attribute( QStringLiteral(
"miny" ) ).toDouble( &conversionOk );
1647 if ( !conversionOk )
1651 maxx = boundingBoxElem.attribute( QStringLiteral(
"maxx" ) ).toDouble( &conversionOk );
1652 if ( !conversionOk )
1656 maxy = boundingBoxElem.attribute( QStringLiteral(
"maxy" ) ).toDouble( &conversionOk );
1657 if ( !conversionOk )
1663 QString version = doc.documentElement().attribute( QStringLiteral(
"version" ) );
1677 if ( version != QLatin1String(
"1.1.1" ) && layerCrs.
hasAxisInverted() )
1688 BBox = t.transformBoundingBox( BBox );
1692 QgsMessageLog::logMessage( QStringLiteral(
"Error transforming extent: %1" ).arg( cse.
what() ), QStringLiteral(
"Server" ), Qgis::MessageLevel::Warning );
1699 bool crsSetFromLayerElement(
const QDomElement &layerElement, QSet<QString> &crsSet )
1701 if ( layerElement.isNull() )
1708 QDomNodeList crsNodeList;
1709 crsNodeList = layerElement.elementsByTagName( QStringLiteral(
"CRS" ) );
1710 for (
int i = 0; i < crsNodeList.size(); ++i )
1712 crsSet.insert( crsNodeList.at( i ).toElement().text() );
1715 crsNodeList = layerElement.elementsByTagName( QStringLiteral(
"SRS" ) );
1716 for (
int i = 0; i < crsNodeList.size(); ++i )
1718 crsSet.insert( crsNodeList.at( i ).toElement().text() );
1724 void combineExtentAndCrsOfGroupChildren( QDomDocument &doc, QDomElement &groupElem,
const QgsProject *project,
1725 bool considerMapExtent )
1728 QSet<QString> combinedCRSSet;
1729 bool firstBBox =
true;
1730 bool firstCRSSet =
true;
1732 QDomNodeList layerChildren = groupElem.childNodes();
1733 for (
int j = 0; j < layerChildren.size(); ++j )
1735 QDomElement childElem = layerChildren.at( j ).toElement();
1737 if ( childElem.tagName() != QLatin1String(
"Layer" ) )
1740 QgsRectangle bbox = layerBoundingBoxInProjectCrs( doc, childElem, project );
1750 combinedBBox = bbox;
1760 QSet<QString> crsSet;
1761 if ( crsSetFromLayerElement( childElem, crsSet ) )
1765 combinedCRSSet = crsSet;
1766 firstCRSSet =
false;
1770 combinedCRSSet.intersect( crsSet );
1776 appendCrsElementsToLayer( doc, groupElem, qgis::setToList( combinedCRSSet ), outputCrsList );
1779 if ( considerMapExtent )
1784 combinedBBox = mapRect;
1787 appendLayerBoundingBoxes( doc, groupElem, combinedBBox, groupCRS, qgis::setToList( combinedCRSSet ), outputCrsList, project );
1791 void appendDrawingOrder( QDomDocument &doc, QDomElement &parentElem,
QgsServerInterface *serverIface,
1794 #ifdef HAVE_SERVER_PYTHON_PLUGINS
1797 ( void )serverIface;
1802 QStringList layerList;
1805 QList< QgsMapLayer * > projectLayerOrder = projectLayerTreeRoot->
layerOrder();
1806 for (
int i = 0; i < projectLayerOrder.size(); ++i )
1810 if ( restrictedLayers.contains( l->
name() ) )
1814 #ifdef HAVE_SERVER_PYTHON_PLUGINS
1820 QString wmsName = l->
name();
1830 layerList << wmsName;
1833 if ( !layerList.isEmpty() )
1835 QStringList reversedList;
1836 reversedList.reserve( layerList.size() );
1837 for (
int i = layerList.size() - 1; i >= 0; --i )
1838 reversedList << layerList[ i ];
1840 QDomElement layerDrawingOrderElem = doc.createElement( QStringLiteral(
"LayerDrawingOrder" ) );
1841 QDomText drawingOrderText = doc.createTextNode( reversedList.join(
',' ) );
1842 layerDrawingOrderElem.appendChild( drawingOrderText );
1843 parentElem.appendChild( layerDrawingOrderElem );
1847 void appendLayerProjectSettings( QDomDocument &doc, QDomElement &layerElem,
QgsMapLayer *currentLayer )
1849 if ( !currentLayer )
1855 QDomElement treeNameElem = doc.createElement( QStringLiteral(
"TreeName" ) );
1856 QDomText treeNameText = doc.createTextNode( currentLayer->
name() );
1857 treeNameElem.appendChild( treeNameText );
1858 layerElem.appendChild( treeNameElem );
1860 switch ( currentLayer->
type() )
1866 int displayFieldIdx = -1;
1867 QString displayField = QStringLiteral(
"maptip" );
1869 if ( exp.isField() )
1876 QDomElement attributesElem = doc.createElement( QStringLiteral(
"Attributes" ) );
1878 for (
int idx = 0; idx < layerFields.
count(); ++idx )
1886 if ( idx == displayFieldIdx )
1890 QDomElement attributeElem = doc.createElement( QStringLiteral(
"Attribute" ) );
1891 attributeElem.setAttribute( QStringLiteral(
"name" ),
field.
name() );
1892 attributeElem.setAttribute( QStringLiteral(
"type" ), QVariant::typeToName(
field.
type() ) );
1893 attributeElem.setAttribute( QStringLiteral(
"typeName" ),
field.
typeName() );
1895 if ( !alias.isEmpty() )
1897 attributeElem.setAttribute( QStringLiteral(
"alias" ), alias );
1901 attributeElem.setAttribute( QStringLiteral(
"editType" ), vLayer->
editorWidgetSetup( idx ).
type() );
1902 attributeElem.setAttribute( QStringLiteral(
"comment" ),
field.
comment() );
1903 attributeElem.setAttribute( QStringLiteral(
"length" ),
field.
length() );
1904 attributeElem.setAttribute( QStringLiteral(
"precision" ),
field.
precision() );
1905 attributesElem.appendChild( attributeElem );
1909 layerElem.setAttribute( QStringLiteral(
"displayField" ), displayField );
1913 if ( pkAttributes.size() > 0 )
1915 QDomElement pkElem = doc.createElement( QStringLiteral(
"PrimaryKey" ) );
1916 QgsAttributeList::const_iterator pkIt = pkAttributes.constBegin();
1917 for ( ; pkIt != pkAttributes.constEnd(); ++pkIt )
1919 QDomElement pkAttributeElem = doc.createElement( QStringLiteral(
"PrimaryKeyAttribute" ) );
1920 QDomText pkAttName = doc.createTextNode( layerFields.
at( *pkIt ).
name() );
1921 pkAttributeElem.appendChild( pkAttName );
1922 pkElem.appendChild( pkAttributeElem );
1924 layerElem.appendChild( pkElem );
1931 layerElem.setAttribute( QStringLiteral(
"opacity" ), QString::number( vLayer->
opacity() ) );
1933 layerElem.appendChild( attributesElem );
1940 if ( provider && provider->
name() ==
"wms" )
1943 QVariant wmsBackgroundLayer = currentLayer->
customProperty( QStringLiteral(
"WMSBackgroundLayer" ), false );
1944 QDomElement wmsBackgroundLayerElem = doc.createElement(
"WMSBackgroundLayer" );
1945 QDomText wmsBackgroundLayerText = doc.createTextNode( wmsBackgroundLayer.toBool() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1946 wmsBackgroundLayerElem.appendChild( wmsBackgroundLayerText );
1947 layerElem.appendChild( wmsBackgroundLayerElem );
1950 QVariant wmsPublishDataSourceUrl = currentLayer->
customProperty( QStringLiteral(
"WMSPublishDataSourceUrl" ),
false );
1951 if ( wmsPublishDataSourceUrl.toBool() )
1953 bool tiled = qobject_cast< const QgsRasterDataProvider * >( provider )
1954 ? !qobject_cast< const QgsRasterDataProvider * >( provider )->nativeResolutions().isEmpty()
1957 QDomElement dataSourceElem = doc.createElement( tiled ? QStringLiteral(
"WMTSDataSource" ) : QStringLiteral(
"WMSDataSource" ) );
1958 QDomText dataSourceUri = doc.createTextNode( provider->
dataSourceUri() );
1959 dataSourceElem.appendChild( dataSourceUri );
1960 layerElem.appendChild( dataSourceElem );
1964 QVariant wmsPrintLayer = currentLayer->
customProperty( QStringLiteral(
"WMSPrintLayer" ) );
1965 if ( wmsPrintLayer.isValid() )
1967 QDomElement wmsPrintLayerElem = doc.createElement(
"WMSPrintLayer" );
1968 QDomText wmsPrintLayerText = doc.createTextNode( wmsPrintLayer.toString() );
1969 wmsPrintLayerElem.appendChild( wmsPrintLayerText );
1970 layerElem.appendChild( wmsPrintLayerElem );
1976 if ( rasterRenderer )
1978 layerElem.setAttribute( QStringLiteral(
"opacity" ), QString::number( rasterRenderer->
opacity() ) );
1991 void addKeywordListElement(
const QgsProject *project, QDomDocument &doc, QDomElement &parent )
1995 QDomElement keywordsElem = doc.createElement( QStringLiteral(
"KeywordList" ) );
1997 QDomElement keywordElem = doc.createElement( QStringLiteral(
"Keyword" ) );
1998 keywordElem.setAttribute( QStringLiteral(
"vocabulary" ), QStringLiteral(
"ISO" ) );
1999 QDomText keywordText = doc.createTextNode( QStringLiteral(
"infoMapAccessService" ) );
2000 keywordElem.appendChild( keywordText );
2001 keywordsElem.appendChild( keywordElem );
2002 parent.appendChild( keywordsElem );
2004 for (
const QString &keyword : qgis::as_const( keywords ) )
2006 if ( !keyword.isEmpty() )
2008 keywordElem = doc.createElement( QStringLiteral(
"Keyword" ) );
2009 keywordText = doc.createTextNode( keyword );
2010 keywordElem.appendChild( keywordText );
2013 keywordElem.setAttribute( QStringLiteral(
"vocabulary" ), QStringLiteral(
"SIA_Geo405" ) );
2015 keywordsElem.appendChild( keywordElem );
2018 parent.appendChild( keywordsElem );
2026 for (
int j = 0; j < childNode->
children().size(); ++j )
2036 const auto l { treeLayer->
layer() };