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 );
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 );
434 bool projectSettings )
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 );
537 if ( projectSettings )
540 elem = doc.createElement( QStringLiteral(
"GetPrint" ) );
541 appendFormat( elem, QStringLiteral(
"svg" ) );
542 appendFormat( elem, QStringLiteral(
"png" ) );
543 appendFormat( elem, QStringLiteral(
"pdf" ) );
544 elem.appendChild( dcpTypeElem.cloneNode().toElement() );
545 requestElem.appendChild( elem );
549 elem = doc.createElement( QStringLiteral(
"Exception" ) );
550 appendFormat( elem, ( version == QLatin1String(
"1.1.1" ) ?
"application/vnd.ogc.se_xml" :
"XML" ) );
551 capabilityElem.appendChild( elem );
554 if ( version == QLatin1String(
"1.3.0" ) )
556 elem = doc.createElement( QStringLiteral(
"sld:UserDefinedSymbolization" ) );
557 elem.setAttribute( QStringLiteral(
"SupportSLD" ), QStringLiteral(
"1" ) );
558 elem.setAttribute( QStringLiteral(
"UserLayer" ), QStringLiteral(
"0" ) );
559 elem.setAttribute( QStringLiteral(
"UserStyle" ), QStringLiteral(
"1" ) );
560 elem.setAttribute( QStringLiteral(
"RemoteWFS" ), QStringLiteral(
"0" ) );
561 elem.setAttribute( QStringLiteral(
"InlineFeature" ), QStringLiteral(
"0" ) );
562 elem.setAttribute( QStringLiteral(
"RemoteWCS" ), QStringLiteral(
"0" ) );
563 capabilityElem.appendChild( elem );
571 return capabilityElem;
576 QDomElement inspireCapabilitiesElem;
579 return inspireCapabilitiesElem;
581 inspireCapabilitiesElem = doc.createElement( QStringLiteral(
"inspire_vs:ExtendedCapabilities" ) );
585 if ( !inspireMetadataUrl.isEmpty() )
587 QDomElement inspireCommonMetadataUrlElem = doc.createElement( QStringLiteral(
"inspire_common:MetadataUrl" ) );
588 inspireCommonMetadataUrlElem.setAttribute( QStringLiteral(
"xsi:type" ), QStringLiteral(
"inspire_common:resourceLocatorType" ) );
590 QDomElement inspireCommonMetadataUrlUrlElem = doc.createElement( QStringLiteral(
"inspire_common:URL" ) );
591 inspireCommonMetadataUrlUrlElem.appendChild( doc.createTextNode( inspireMetadataUrl ) );
592 inspireCommonMetadataUrlElem.appendChild( inspireCommonMetadataUrlUrlElem );
595 if ( !inspireMetadataUrlType.isNull() )
597 QDomElement inspireCommonMetadataUrlMediaTypeElem = doc.createElement( QStringLiteral(
"inspire_common:MediaType" ) );
598 inspireCommonMetadataUrlMediaTypeElem.appendChild( doc.createTextNode( inspireMetadataUrlType ) );
599 inspireCommonMetadataUrlElem.appendChild( inspireCommonMetadataUrlMediaTypeElem );
602 inspireCapabilitiesElem.appendChild( inspireCommonMetadataUrlElem );
606 QDomElement inspireCommonResourceTypeElem = doc.createElement( QStringLiteral(
"inspire_common:ResourceType" ) );
607 inspireCommonResourceTypeElem.appendChild( doc.createTextNode( QStringLiteral(
"service" ) ) );
608 inspireCapabilitiesElem.appendChild( inspireCommonResourceTypeElem );
610 QDomElement inspireCommonSpatialDataServiceTypeElem = doc.createElement( QStringLiteral(
"inspire_common:SpatialDataServiceType" ) );
611 inspireCommonSpatialDataServiceTypeElem.appendChild( doc.createTextNode( QStringLiteral(
"view" ) ) );
612 inspireCapabilitiesElem.appendChild( inspireCommonSpatialDataServiceTypeElem );
615 if ( !inspireTemporalReference.isNull() )
617 QDomElement inspireCommonTemporalReferenceElem = doc.createElement( QStringLiteral(
"inspire_common:TemporalReference" ) );
618 QDomElement inspireCommonDateOfLastRevisionElem = doc.createElement( QStringLiteral(
"inspire_common:DateOfLastRevision" ) );
619 inspireCommonDateOfLastRevisionElem.appendChild( doc.createTextNode( inspireTemporalReference ) );
620 inspireCommonTemporalReferenceElem.appendChild( inspireCommonDateOfLastRevisionElem );
621 inspireCapabilitiesElem.appendChild( inspireCommonTemporalReferenceElem );
624 QDomElement inspireCommonMetadataPointOfContactElem = doc.createElement( QStringLiteral(
"inspire_common:MetadataPointOfContact" ) );
627 QDomElement inspireCommonOrganisationNameElem = doc.createElement( QStringLiteral(
"inspire_common:OrganisationName" ) );
628 if ( !contactOrganization.isNull() )
630 inspireCommonOrganisationNameElem.appendChild( doc.createTextNode( contactOrganization ) );
632 inspireCommonMetadataPointOfContactElem.appendChild( inspireCommonOrganisationNameElem );
635 QDomElement inspireCommonEmailAddressElem = doc.createElement( QStringLiteral(
"inspire_common:EmailAddress" ) );
636 if ( !contactMail.isNull() )
638 inspireCommonEmailAddressElem.appendChild( doc.createTextNode( contactMail ) );
640 inspireCommonMetadataPointOfContactElem.appendChild( inspireCommonEmailAddressElem );
642 inspireCapabilitiesElem.appendChild( inspireCommonMetadataPointOfContactElem );
645 if ( !inspireMetadataDate.isNull() )
647 QDomElement inspireCommonMetadataDateElem = doc.createElement( QStringLiteral(
"inspire_common:MetadataDate" ) );
648 inspireCommonMetadataDateElem.appendChild( doc.createTextNode( inspireMetadataDate ) );
649 inspireCapabilitiesElem.appendChild( inspireCommonMetadataDateElem );
654 QDomElement inspireCommonSupportedLanguagesElem = doc.createElement( QStringLiteral(
"inspire_common:SupportedLanguages" ) );
655 inspireCommonSupportedLanguagesElem.setAttribute( QStringLiteral(
"xsi:type" ), QStringLiteral(
"inspire_common:supportedLanguagesType" ) );
657 QDomElement inspireCommonLanguageElem = doc.createElement( QStringLiteral(
"inspire_common:Language" ) );
660 QDomElement inspireCommonDefaultLanguageElem = doc.createElement( QStringLiteral(
"inspire_common:DefaultLanguage" ) );
661 inspireCommonDefaultLanguageElem.appendChild( inspireCommonLanguageElem );
662 inspireCommonSupportedLanguagesElem.appendChild( inspireCommonDefaultLanguageElem );
666 QDomElement inspireCommonSupportedLanguageElem = doc.createElement(
"inspire_common:SupportedLanguage" );
667 inspireCommonSupportedLanguageElem.appendChild( inspireCommonLanguageElem.cloneNode().toElement() );
668 inspireCommonSupportedLanguagesElem.appendChild( inspireCommonSupportedLanguageElem );
671 inspireCapabilitiesElem.appendChild( inspireCommonSupportedLanguagesElem );
673 QDomElement inspireCommonResponseLanguageElem = doc.createElement( QStringLiteral(
"inspire_common:ResponseLanguage" ) );
674 inspireCommonResponseLanguageElem.appendChild( inspireCommonLanguageElem.cloneNode().toElement() );
675 inspireCapabilitiesElem.appendChild( inspireCommonResponseLanguageElem );
677 return inspireCapabilitiesElem;
683 if ( projectComposers.size() == 0 )
684 return QDomElement();
688 QDomElement composerTemplatesElem = doc.createElement( QStringLiteral(
"ComposerTemplates" ) );
689 QList<QgsPrintLayout *>::const_iterator cIt = projectComposers.constBegin();
690 for ( ; cIt != projectComposers.constEnd(); ++cIt )
693 if ( restrictedComposers.contains( layout->
name() ) )
705 QDomElement composerTemplateElem = doc.createElement( QStringLiteral(
"ComposerTemplate" ) );
706 composerTemplateElem.setAttribute( QStringLiteral(
"name" ), layout->
name() );
709 composerTemplateElem.setAttribute( QStringLiteral(
"width" ), width.length() );
710 composerTemplateElem.setAttribute( QStringLiteral(
"height" ), height.length() );
714 if ( atlas && atlas->
enabled() )
716 composerTemplateElem.setAttribute( QStringLiteral(
"atlasEnabled" ), QStringLiteral(
"1" ) );
723 layerName = cLayer->
id();
725 else if ( layerName.isEmpty() )
727 layerName = cLayer->
name();
729 composerTemplateElem.setAttribute( QStringLiteral(
"atlasCoverageLayer" ), layerName );
734 QList<QgsLayoutItemMap *> layoutMapList;
736 QList<QgsLayoutItemMap *>::const_iterator cmIt = layoutMapList.constBegin();
739 for ( ; cmIt != layoutMapList.constEnd(); ++cmIt )
743 QDomElement composerMapElem = doc.createElement( QStringLiteral(
"ComposerMap" ) );
744 composerMapElem.setAttribute( QStringLiteral(
"name" ), QStringLiteral(
"map%1" ).arg( mapId ) );
746 composerMapElem.setAttribute( QStringLiteral(
"width" ), composerMap->rect().width() );
747 composerMapElem.setAttribute( QStringLiteral(
"height" ), composerMap->rect().height() );
748 composerTemplateElem.appendChild( composerMapElem );
752 QList<QgsLayoutItemLabel *> composerLabelList;
754 QList<QgsLayoutItemLabel *>::const_iterator clIt = composerLabelList.constBegin();
755 for ( ; clIt != composerLabelList.constEnd(); ++clIt )
758 QString
id = composerLabel->
id();
762 QDomElement composerLabelElem = doc.createElement( QStringLiteral(
"ComposerLabel" ) );
763 composerLabelElem.setAttribute( QStringLiteral(
"name" ), id );
764 composerTemplateElem.appendChild( composerLabelElem );
768 QList<QgsLayoutItemHtml *> composerHtmlList;
770 QList<QgsLayoutItemHtml *>::const_iterator chIt = composerHtmlList.constBegin();
771 for ( ; chIt != composerHtmlList.constEnd(); ++chIt )
777 QString
id = composerHtml->
frame( 0 )->
id();
781 QDomElement composerHtmlElem = doc.createElement( QStringLiteral(
"ComposerHtml" ) );
782 composerHtmlElem.setAttribute( QStringLiteral(
"name" ), id );
783 composerTemplateElem.appendChild( composerHtmlElem );
786 composerTemplatesElem.appendChild( composerTemplateElem );
789 if ( composerTemplatesElem.childNodes().size() == 0 )
790 return QDomElement();
792 return composerTemplatesElem;
799 return QDomElement();
801 QDomElement wfsLayersElem = doc.createElement( QStringLiteral(
"WFSLayers" ) );
810 QDomElement wfsLayerElem = doc.createElement( QStringLiteral(
"WFSLayer" ) );
813 wfsLayerElem.setAttribute( QStringLiteral(
"name" ), layer->
id() );
817 wfsLayerElem.setAttribute( QStringLiteral(
"name" ), layer->
name() );
819 wfsLayersElem.appendChild( wfsLayerElem );
822 return wfsLayersElem;
826 const QgsProject *project,
const QString &version,
831 QDomElement layerParentElem = doc.createElement( QStringLiteral(
"Layer" ) );
835 if ( rootLayerName.isEmpty() && !project->
title().isEmpty() )
837 rootLayerName = project->
title();
840 if ( !rootLayerName.isEmpty() )
842 QDomElement layerParentNameElem = doc.createElement( QStringLiteral(
"Name" ) );
843 QDomText layerParentNameText = doc.createTextNode( rootLayerName );
844 layerParentNameElem.appendChild( layerParentNameText );
845 layerParentElem.appendChild( layerParentNameElem );
848 if ( !project->
title().isEmpty() )
851 QDomElement layerParentTitleElem = doc.createElement( QStringLiteral(
"Title" ) );
852 QDomText layerParentTitleText = doc.createTextNode( project->
title() );
853 layerParentTitleElem.appendChild( layerParentTitleText );
854 layerParentElem.appendChild( layerParentTitleElem );
857 QDomElement layerParentAbstElem = doc.createElement( QStringLiteral(
"Abstract" ) );
858 QDomText layerParentAbstText = doc.createTextNode( project->
title() );
859 layerParentAbstElem.appendChild( layerParentAbstText );
860 layerParentElem.appendChild( layerParentAbstElem );
864 addKeywordListElement( project, doc, layerParentElem );
867 if ( projectSettings )
869 QDomElement treeNameElem = doc.createElement( QStringLiteral(
"TreeName" ) );
870 QDomText treeNameText = doc.createTextNode( project->
title() );
871 treeNameElem.appendChild( treeNameText );
872 layerParentElem.appendChild( treeNameElem );
877 layerParentElem.setAttribute( QStringLiteral(
"queryable" ), QStringLiteral(
"1" ) );
881 layerParentElem.setAttribute( QStringLiteral(
"queryable" ), QStringLiteral(
"0" ) );
884 appendLayersFromTreeGroup( doc, layerParentElem, serverIface, project, version, request, projectLayerTreeRoot, projectSettings );
886 combineExtentAndCrsOfGroupChildren( doc, layerParentElem, project,
true );
888 return layerParentElem;
894 void appendLayersFromTreeGroup( QDomDocument &doc,
895 QDomElement &parentLayer,
898 const QString &version,
901 bool projectSettings )
907 QList< QgsLayerTreeNode * > layerTreeGroupChildren = layerTreeGroup->
children();
908 for (
int i = 0; i < layerTreeGroupChildren.size(); ++i )
911 QDomElement layerElem = doc.createElement( QStringLiteral(
"Layer" ) );
913 if ( projectSettings )
915 layerElem.setAttribute( QStringLiteral(
"visible" ), treeNode->
isVisible() );
916 layerElem.setAttribute( QStringLiteral(
"expanded" ), treeNode->
isExpanded() );
923 QString name = treeGroupChild->
name();
924 if ( restrictedLayers.contains( name ) )
929 if ( projectSettings )
931 layerElem.setAttribute( QStringLiteral(
"mutuallyExclusive" ), treeGroupChild->
isMutuallyExclusive() );
934 QString shortName = treeGroupChild->
customProperty( QStringLiteral(
"wmsShortName" ) ).toString();
935 QString title = treeGroupChild->
customProperty( QStringLiteral(
"wmsTitle" ) ).toString();
937 QDomElement nameElem = doc.createElement( QStringLiteral(
"Name" ) );
939 if ( !shortName.isEmpty() )
940 nameText = doc.createTextNode( shortName );
942 nameText = doc.createTextNode( name );
943 nameElem.appendChild( nameText );
944 layerElem.appendChild( nameElem );
946 QDomElement titleElem = doc.createElement( QStringLiteral(
"Title" ) );
948 if ( !title.isEmpty() )
949 titleText = doc.createTextNode( title );
951 titleText = doc.createTextNode( name );
952 titleElem.appendChild( titleText );
953 layerElem.appendChild( titleElem );
955 QString
abstract = treeGroupChild->
customProperty( QStringLiteral(
"wmsAbstract" ) ).toString();
956 if ( !
abstract.isEmpty() )
958 QDomElement abstractElem = doc.createElement( QStringLiteral(
"Abstract" ) );
959 QDomText abstractText = doc.createTextNode(
abstract );
960 abstractElem.appendChild( abstractText );
961 layerElem.appendChild( abstractElem );
965 if ( projectSettings )
967 QDomElement treeNameElem = doc.createElement( QStringLiteral(
"TreeName" ) );
968 QDomText treeNameText = doc.createTextNode( name );
969 treeNameElem.appendChild( treeNameText );
970 layerElem.appendChild( treeNameElem );
976 layerElem.setAttribute( QStringLiteral(
"queryable" ), QStringLiteral(
"1" ) );
980 layerElem.setAttribute( QStringLiteral(
"queryable" ), QStringLiteral(
"0" ) );
983 appendLayersFromTreeGroup( doc, layerElem, serverIface, project, version, request, treeGroupChild, projectSettings );
985 combineExtentAndCrsOfGroupChildren( doc, layerElem, project );
991 if ( restrictedLayers.contains( l->
name() ) )
996 #ifdef HAVE_SERVER_PYTHON_PLUGINS
1003 QString wmsName = l->
name();
1016 layerElem.setAttribute( QStringLiteral(
"queryable" ), QStringLiteral(
"0" ) );
1020 layerElem.setAttribute( QStringLiteral(
"queryable" ), QStringLiteral(
"1" ) );
1023 QDomElement nameElem = doc.createElement( QStringLiteral(
"Name" ) );
1024 QDomText nameText = doc.createTextNode( wmsName );
1025 nameElem.appendChild( nameText );
1026 layerElem.appendChild( nameElem );
1028 QDomElement titleElem = doc.createElement( QStringLiteral(
"Title" ) );
1029 QString title = l->
title();
1030 if ( title.isEmpty() )
1034 QDomText titleText = doc.createTextNode( title );
1035 titleElem.appendChild( titleText );
1036 layerElem.appendChild( titleElem );
1039 if ( !
abstract.isEmpty() )
1041 QDomElement abstractElem = doc.createElement( QStringLiteral(
"Abstract" ) );
1042 QDomText abstractText = doc.createTextNode(
abstract );
1043 abstractElem.appendChild( abstractText );
1044 layerElem.appendChild( abstractElem );
1050 QStringList keywordStringList = l->
keywordList().split(
',' );
1052 QDomElement keywordListElem = doc.createElement( QStringLiteral(
"KeywordList" ) );
1053 for (
int i = 0; i < keywordStringList.size(); ++i )
1055 QDomElement keywordElem = doc.createElement( QStringLiteral(
"Keyword" ) );
1056 QDomText keywordText = doc.createTextNode( keywordStringList.at( i ).trimmed() );
1057 keywordElem.appendChild( keywordText );
1060 keywordElem.setAttribute( QStringLiteral(
"vocabulary" ), QStringLiteral(
"SIA_Geo405" ) );
1062 keywordListElem.appendChild( keywordElem );
1064 layerElem.appendChild( keywordListElem );
1068 bool geometryLayer =
true;
1076 geometryLayer =
false;
1082 if ( geometryLayer )
1084 QStringList crsList;
1087 appendCrsElementsToLayer( doc, layerElem, crsList, outputCrsList );
1105 else if ( vl->
crs() != project->
crs() )
1110 extent = ct.transform( extent );
1114 QgsMessageLog::logMessage( QStringLiteral(
"Error transforming extent for layer %1: %2" ).arg( vl->
name() ).arg( cse.
what() ), QStringLiteral(
"Server" ), Qgis::MessageLevel::Warning );
1121 appendLayerBoundingBoxes( doc, layerElem, extent, l->
crs(), crsList, outputCrsList, project );
1125 appendLayerStyles( doc, layerElem, l, project, version, request );
1130 if ( version == QLatin1String(
"1.1.1" ) )
1133 double SCALE_TO_SCALEHINT =
OGC_PX_M * M_SQRT2;
1135 QDomElement scaleHintElem = doc.createElement( QStringLiteral(
"ScaleHint" ) );
1136 scaleHintElem.setAttribute( QStringLiteral(
"min" ), QString::number( l->
maximumScale() * SCALE_TO_SCALEHINT ) );
1137 scaleHintElem.setAttribute( QStringLiteral(
"max" ), QString::number( l->
minimumScale() * SCALE_TO_SCALEHINT ) );
1138 layerElem.appendChild( scaleHintElem );
1142 QString minScaleString = QString::number( l->
maximumScale() );
1143 QDomElement minScaleElem = doc.createElement( QStringLiteral(
"MinScaleDenominator" ) );
1144 QDomText minScaleText = doc.createTextNode( minScaleString );
1145 minScaleElem.appendChild( minScaleText );
1146 layerElem.appendChild( minScaleElem );
1148 QString maxScaleString = QString::number( l->
minimumScale() );
1149 QDomElement maxScaleElem = doc.createElement( QStringLiteral(
"MaxScaleDenominator" ) );
1150 QDomText maxScaleText = doc.createTextNode( maxScaleString );
1151 maxScaleElem.appendChild( maxScaleText );
1152 layerElem.appendChild( maxScaleElem );
1157 QString dataUrl = l->
dataUrl();
1158 if ( !dataUrl.isEmpty() )
1160 QDomElement dataUrlElem = doc.createElement( QStringLiteral(
"DataURL" ) );
1161 QDomElement dataUrlFormatElem = doc.createElement( QStringLiteral(
"Format" ) );
1163 QDomText dataUrlFormatText = doc.createTextNode( dataUrlFormat );
1164 dataUrlFormatElem.appendChild( dataUrlFormatText );
1165 dataUrlElem.appendChild( dataUrlFormatElem );
1166 QDomElement dataORElem = doc.createElement( QStringLiteral(
"OnlineResource" ) );
1167 dataORElem.setAttribute( QStringLiteral(
"xmlns:xlink" ), QStringLiteral(
"http://www.w3.org/1999/xlink" ) );
1168 dataORElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
1169 dataORElem.setAttribute( QStringLiteral(
"xlink:href" ), dataUrl );
1170 dataUrlElem.appendChild( dataORElem );
1171 layerElem.appendChild( dataUrlElem );
1176 if ( !attribution.isEmpty() )
1178 QDomElement attribElem = doc.createElement( QStringLiteral(
"Attribution" ) );
1179 QDomElement attribTitleElem = doc.createElement( QStringLiteral(
"Title" ) );
1180 QDomText attribText = doc.createTextNode( attribution );
1181 attribTitleElem.appendChild( attribText );
1182 attribElem.appendChild( attribTitleElem );
1184 if ( !attributionUrl.isEmpty() )
1186 QDomElement attribORElem = doc.createElement( QStringLiteral(
"OnlineResource" ) );
1187 attribORElem.setAttribute( QStringLiteral(
"xmlns:xlink" ), QStringLiteral(
"http://www.w3.org/1999/xlink" ) );
1188 attribORElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
1189 attribORElem.setAttribute( QStringLiteral(
"xlink:href" ), attributionUrl );
1190 attribElem.appendChild( attribORElem );
1192 layerElem.appendChild( attribElem );
1197 if ( !metadataUrl.isEmpty() )
1199 QDomElement metaUrlElem = doc.createElement( QStringLiteral(
"MetadataURL" ) );
1201 if ( version == QLatin1String(
"1.1.1" ) )
1203 metaUrlElem.setAttribute( QStringLiteral(
"type" ), metadataUrlType );
1205 else if ( metadataUrlType == QLatin1String(
"FGDC" ) )
1207 metaUrlElem.setAttribute( QStringLiteral(
"type" ), QStringLiteral(
"FGDC:1998" ) );
1209 else if ( metadataUrlType == QLatin1String(
"TC211" ) )
1211 metaUrlElem.setAttribute( QStringLiteral(
"type" ), QStringLiteral(
"ISO19115:2003" ) );
1215 metaUrlElem.setAttribute( QStringLiteral(
"type" ), metadataUrlType );
1218 if ( !metadataUrlFormat.isEmpty() )
1220 QDomElement metaUrlFormatElem = doc.createElement( QStringLiteral(
"Format" ) );
1221 QDomText metaUrlFormatText = doc.createTextNode( metadataUrlFormat );
1222 metaUrlFormatElem.appendChild( metaUrlFormatText );
1223 metaUrlElem.appendChild( metaUrlFormatElem );
1225 QDomElement metaUrlORElem = doc.createElement( QStringLiteral(
"OnlineResource" ) );
1226 metaUrlORElem.setAttribute( QStringLiteral(
"xmlns:xlink" ), QStringLiteral(
"http://www.w3.org/1999/xlink" ) );
1227 metaUrlORElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
1228 metaUrlORElem.setAttribute( QStringLiteral(
"xlink:href" ), metadataUrl );
1229 metaUrlElem.appendChild( metaUrlORElem );
1230 layerElem.appendChild( metaUrlElem );
1242 if ( fieldIndex == -1 )
1247 QSet<QVariant> uniqueValues = vl->
uniqueValues( fieldIndex );
1250 if ( !dim.endFieldName.isEmpty() )
1252 int endFieldIndex = vl->
fields().
indexOf( dim.endFieldName );
1254 if ( endFieldIndex == -1 )
1258 uniqueValues.unite( vl->
uniqueValues( endFieldIndex ) );
1261 QList<QVariant> values = qgis::setToList( uniqueValues );
1262 std::sort( values.begin(), values.end() );
1264 QDomElement dimElem = doc.createElement( QStringLiteral(
"Dimension" ) );
1265 dimElem.setAttribute( QStringLiteral(
"name" ), dim.name );
1266 if ( !dim.units.isEmpty() )
1268 dimElem.setAttribute( QStringLiteral(
"units" ), dim.units );
1270 if ( !dim.unitSymbol.isEmpty() )
1272 dimElem.setAttribute( QStringLiteral(
"unitSymbol" ), dim.unitSymbol );
1276 dimElem.setAttribute( QStringLiteral(
"default" ), values.first().toString() );
1280 dimElem.setAttribute( QStringLiteral(
"default" ), values.last().toString() );
1284 dimElem.setAttribute( QStringLiteral(
"default" ), dim.referenceValue.toString() );
1286 dimElem.setAttribute( QStringLiteral(
"multipleValue" ),
'1' );
1287 dimElem.setAttribute( QStringLiteral(
"nearestValue" ),
'0' );
1289 QStringList strValues;
1290 for (
const QVariant &v : values )
1292 strValues << v.toString();
1294 QDomText dimValuesText = doc.createTextNode( strValues.join( QStringLiteral(
", " ) ) );
1295 dimElem.appendChild( dimValuesText );
1296 layerElem.appendChild( dimElem );
1300 if ( projectSettings )
1302 appendLayerProjectSettings( doc, layerElem, l );
1306 parentLayer.appendChild( layerElem );
1310 void appendLayerStyles( QDomDocument &doc, QDomElement &layerElem,
QgsMapLayer *currentLayer,
1317 QString hrefString = href.toString();
1318 hrefString.append( href.hasQuery() ?
"&" :
"?" );
1321 QDomElement styleElem = doc.createElement( QStringLiteral(
"Style" ) );
1322 QDomElement styleNameElem = doc.createElement( QStringLiteral(
"Name" ) );
1323 QDomText styleNameText = doc.createTextNode( styleName );
1324 styleNameElem.appendChild( styleNameText );
1325 QDomElement styleTitleElem = doc.createElement( QStringLiteral(
"Title" ) );
1326 QDomText styleTitleText = doc.createTextNode( styleName );
1327 styleTitleElem.appendChild( styleTitleText );
1328 styleElem.appendChild( styleNameElem );
1329 styleElem.appendChild( styleTitleElem );
1332 QDomElement getLayerLegendGraphicElem = doc.createElement( QStringLiteral(
"LegendURL" ) );
1334 QString customHrefString = currentLayer->
legendUrl();
1336 QStringList getLayerLegendGraphicFormats;
1337 if ( !customHrefString.isEmpty() )
1343 getLayerLegendGraphicFormats << QStringLiteral(
"image/png" );
1346 for (
int i = 0; i < getLayerLegendGraphicFormats.size(); ++i )
1348 QDomElement getLayerLegendGraphicFormatElem = doc.createElement( QStringLiteral(
"Format" ) );
1349 QString getLayerLegendGraphicFormat = getLayerLegendGraphicFormats[i];
1350 QDomText getLayerLegendGraphicFormatText = doc.createTextNode( getLayerLegendGraphicFormat );
1351 getLayerLegendGraphicFormatElem.appendChild( getLayerLegendGraphicFormatText );
1352 getLayerLegendGraphicElem.appendChild( getLayerLegendGraphicFormatElem );
1356 if ( customHrefString.isEmpty() )
1358 QString layerName = currentLayer->
name();
1360 layerName = currentLayer->
id();
1361 else if ( !currentLayer->
shortName().isEmpty() )
1363 QUrlQuery mapUrl( hrefString );
1364 mapUrl.addQueryItem( QStringLiteral(
"SERVICE" ), QStringLiteral(
"WMS" ) );
1365 mapUrl.addQueryItem( QStringLiteral(
"VERSION" ), version );
1366 mapUrl.addQueryItem( QStringLiteral(
"REQUEST" ), QStringLiteral(
"GetLegendGraphic" ) );
1367 mapUrl.addQueryItem( QStringLiteral(
"LAYER" ), layerName );
1368 mapUrl.addQueryItem( QStringLiteral(
"FORMAT" ), QStringLiteral(
"image/png" ) );
1369 mapUrl.addQueryItem( QStringLiteral(
"STYLE" ), styleNameText.data() );
1370 if ( version == QLatin1String(
"1.3.0" ) )
1372 mapUrl.addQueryItem( QStringLiteral(
"SLD_VERSION" ), QStringLiteral(
"1.1.0" ) );
1374 customHrefString = mapUrl.toString();
1377 QDomElement getLayerLegendGraphicORElem = doc.createElement( QStringLiteral(
"OnlineResource" ) );
1378 getLayerLegendGraphicORElem.setAttribute( QStringLiteral(
"xmlns:xlink" ), QStringLiteral(
"http://www.w3.org/1999/xlink" ) );
1379 getLayerLegendGraphicORElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
1380 getLayerLegendGraphicORElem.setAttribute( QStringLiteral(
"xlink:href" ), customHrefString );
1381 getLayerLegendGraphicElem.appendChild( getLayerLegendGraphicORElem );
1382 styleElem.appendChild( getLayerLegendGraphicElem );
1384 layerElem.appendChild( styleElem );
1388 void appendCrsElementsToLayer( QDomDocument &doc, QDomElement &layerElement,
1389 const QStringList &crsList,
const QStringList &constrainedCrsList )
1391 if ( layerElement.isNull() )
1397 QDomElement titleElement = layerElement.firstChildElement( QStringLiteral(
"Title" ) );
1398 QDomElement abstractElement = layerElement.firstChildElement( QStringLiteral(
"Abstract" ) );
1399 QDomElement keywordListElement = layerElement.firstChildElement( QStringLiteral(
"KeywordList" ) );
1400 QDomElement CRSPrecedingElement = !keywordListElement.isNull() ? keywordListElement : !abstractElement.isNull() ? abstractElement : titleElement;
1402 if ( CRSPrecedingElement.isNull() )
1405 const QDomElement keyElement = layerElement.firstChildElement( QStringLiteral(
"KeywordList" ) );
1406 CRSPrecedingElement = keyElement;
1410 if ( !constrainedCrsList.isEmpty() )
1412 for (
int i = constrainedCrsList.size() - 1; i >= 0; --i )
1414 appendCrsElementToLayer( doc, layerElement, CRSPrecedingElement, constrainedCrsList.at( i ) );
1419 for (
const QString &
crs : crsList )
1421 appendCrsElementToLayer( doc, layerElement, CRSPrecedingElement,
crs );
1426 appendCrsElementToLayer( doc, layerElement, CRSPrecedingElement, QString(
"CRS:84" ) );
1429 void appendCrsElementToLayer( QDomDocument &doc, QDomElement &layerElement,
const QDomElement &precedingElement,
1430 const QString &crsText )
1432 if ( crsText.isEmpty() )
1434 QString version = doc.documentElement().attribute( QStringLiteral(
"version" ) );
1435 QDomElement crsElement = doc.createElement( version == QLatin1String(
"1.1.1" ) ?
"SRS" :
"CRS" );
1436 QDomText crsTextNode = doc.createTextNode( crsText );
1437 crsElement.appendChild( crsTextNode );
1438 layerElement.insertAfter( crsElement, precedingElement );
1441 void appendLayerBoundingBoxes( QDomDocument &doc, QDomElement &layerElem,
const QgsRectangle &lExtent,
1443 const QStringList &constrainedCrsList,
const QgsProject *project )
1445 if ( layerElem.isNull() )
1454 layerExtent.
grow( 0.000001 );
1458 int wgs84precision = 6;
1460 QString version = doc.documentElement().attribute( QStringLiteral(
"version" ) );
1463 QDomElement ExGeoBBoxElement;
1466 if ( !layerExtent.
isNull() )
1471 wgs84BoundingRect = exGeoTransform.transformBoundingBox( layerExtent );
1475 QgsMessageLog::logMessage( QStringLiteral(
"Error transforming extent: %1" ).arg( cse.
what() ), QStringLiteral(
"Server" ), Qgis::MessageLevel::Warning );
1480 if ( version == QLatin1String(
"1.1.1" ) )
1482 ExGeoBBoxElement = doc.createElement( QStringLiteral(
"LatLonBoundingBox" ) );
1490 ExGeoBBoxElement = doc.createElement( QStringLiteral(
"EX_GeographicBoundingBox" ) );
1491 QDomElement wBoundLongitudeElement = doc.createElement( QStringLiteral(
"westBoundLongitude" ) );
1493 wBoundLongitudeElement.appendChild( wBoundLongitudeText );
1494 ExGeoBBoxElement.appendChild( wBoundLongitudeElement );
1495 QDomElement eBoundLongitudeElement = doc.createElement( QStringLiteral(
"eastBoundLongitude" ) );
1497 eBoundLongitudeElement.appendChild( eBoundLongitudeText );
1498 ExGeoBBoxElement.appendChild( eBoundLongitudeElement );
1499 QDomElement sBoundLatitudeElement = doc.createElement( QStringLiteral(
"southBoundLatitude" ) );
1501 sBoundLatitudeElement.appendChild( sBoundLatitudeText );
1502 ExGeoBBoxElement.appendChild( sBoundLatitudeElement );
1503 QDomElement nBoundLatitudeElement = doc.createElement( QStringLiteral(
"northBoundLatitude" ) );
1505 nBoundLatitudeElement.appendChild( nBoundLatitudeText );
1506 ExGeoBBoxElement.appendChild( nBoundLatitudeElement );
1509 if ( !wgs84BoundingRect.
isNull() )
1511 QDomElement lastCRSElem = layerElem.lastChildElement( version == QLatin1String(
"1.1.1" ) ?
"SRS" :
"CRS" );
1512 if ( !lastCRSElem.isNull() )
1514 layerElem.insertAfter( ExGeoBBoxElement, lastCRSElem );
1518 layerElem.appendChild( ExGeoBBoxElement );
1523 if ( !constrainedCrsList.isEmpty() )
1525 for (
int i = constrainedCrsList.size() - 1; i >= 0; --i )
1527 appendLayerBoundingBox( doc, layerElem, layerExtent, layerCRS, constrainedCrsList.at( i ), project );
1532 for (
const QString &
crs : crsList )
1534 appendLayerBoundingBox( doc, layerElem, layerExtent, layerCRS,
crs, project );
1540 void appendLayerBoundingBox( QDomDocument &doc, QDomElement &layerElem,
const QgsRectangle &layerExtent,
1544 if ( layerElem.isNull() )
1549 if ( crsText.isEmpty() )
1554 QString version = doc.documentElement().attribute( QStringLiteral(
"version" ) );
1560 if ( !layerExtent.
isNull() )
1565 crsExtent = crsTransform.transformBoundingBox( layerExtent );
1569 QgsMessageLog::logMessage( QStringLiteral(
"Error transforming extent: %1" ).arg( cse.
what() ), QStringLiteral(
"Server" ), Qgis::MessageLevel::Warning );
1574 if ( crsExtent.
isNull() )
1586 QDomElement bBoxElement = doc.createElement( QStringLiteral(
"BoundingBox" ) );
1589 bBoxElement.setAttribute( version == QLatin1String(
"1.1.1" ) ?
"SRS" :
"CRS",
crs.
authid() );
1602 QDomElement lastBBoxElem = layerElem.lastChildElement( QStringLiteral(
"BoundingBox" ) );
1603 if ( !lastBBoxElem.isNull() )
1605 layerElem.insertAfter( bBoxElement, lastBBoxElem );
1609 lastBBoxElem = layerElem.lastChildElement( version == QLatin1String(
"1.1.1" ) ?
"LatLonBoundingBox" :
"EX_GeographicBoundingBox" );
1610 if ( !lastBBoxElem.isNull() )
1612 layerElem.insertAfter( bBoxElement, lastBBoxElem );
1616 layerElem.appendChild( bBoxElement );
1621 QgsRectangle layerBoundingBoxInProjectCrs(
const QDomDocument &doc,
const QDomElement &layerElem,
1625 if ( layerElem.isNull() )
1631 QDomElement boundingBoxElem = layerElem.firstChildElement( QStringLiteral(
"BoundingBox" ) );
1632 if ( boundingBoxElem.isNull() )
1637 double minx, miny, maxx, maxy;
1639 minx = boundingBoxElem.attribute( QStringLiteral(
"minx" ) ).toDouble( &conversionOk );
1640 if ( !conversionOk )
1644 miny = boundingBoxElem.attribute( QStringLiteral(
"miny" ) ).toDouble( &conversionOk );
1645 if ( !conversionOk )
1649 maxx = boundingBoxElem.attribute( QStringLiteral(
"maxx" ) ).toDouble( &conversionOk );
1650 if ( !conversionOk )
1654 maxy = boundingBoxElem.attribute( QStringLiteral(
"maxy" ) ).toDouble( &conversionOk );
1655 if ( !conversionOk )
1661 QString version = doc.documentElement().attribute( QStringLiteral(
"version" ) );
1675 if ( version != QLatin1String(
"1.1.1" ) && layerCrs.
hasAxisInverted() )
1686 BBox = t.transformBoundingBox( BBox );
1690 QgsMessageLog::logMessage( QStringLiteral(
"Error transforming extent: %1" ).arg( cse.
what() ), QStringLiteral(
"Server" ), Qgis::MessageLevel::Warning );
1697 bool crsSetFromLayerElement(
const QDomElement &layerElement, QSet<QString> &crsSet )
1699 if ( layerElement.isNull() )
1706 QDomNodeList crsNodeList;
1707 crsNodeList = layerElement.elementsByTagName( QStringLiteral(
"CRS" ) );
1708 for (
int i = 0; i < crsNodeList.size(); ++i )
1710 crsSet.insert( crsNodeList.at( i ).toElement().text() );
1713 crsNodeList = layerElement.elementsByTagName( QStringLiteral(
"SRS" ) );
1714 for (
int i = 0; i < crsNodeList.size(); ++i )
1716 crsSet.insert( crsNodeList.at( i ).toElement().text() );
1722 void combineExtentAndCrsOfGroupChildren( QDomDocument &doc, QDomElement &groupElem,
const QgsProject *project,
1723 bool considerMapExtent )
1726 QSet<QString> combinedCRSSet;
1727 bool firstBBox =
true;
1728 bool firstCRSSet =
true;
1730 QDomNodeList layerChildren = groupElem.childNodes();
1731 for (
int j = 0; j < layerChildren.size(); ++j )
1733 QDomElement childElem = layerChildren.at( j ).toElement();
1735 if ( childElem.tagName() != QLatin1String(
"Layer" ) )
1738 QgsRectangle bbox = layerBoundingBoxInProjectCrs( doc, childElem, project );
1748 combinedBBox = bbox;
1758 QSet<QString> crsSet;
1759 if ( crsSetFromLayerElement( childElem, crsSet ) )
1763 combinedCRSSet = crsSet;
1764 firstCRSSet =
false;
1768 combinedCRSSet.intersect( crsSet );
1774 appendCrsElementsToLayer( doc, groupElem, qgis::setToList( combinedCRSSet ), outputCrsList );
1777 if ( considerMapExtent )
1782 combinedBBox = mapRect;
1785 appendLayerBoundingBoxes( doc, groupElem, combinedBBox, groupCRS, qgis::setToList( combinedCRSSet ), outputCrsList, project );
1789 void appendDrawingOrder( QDomDocument &doc, QDomElement &parentElem,
QgsServerInterface *serverIface,
1792 #ifdef HAVE_SERVER_PYTHON_PLUGINS
1795 ( void )serverIface;
1800 QStringList layerList;
1803 QList< QgsMapLayer * > projectLayerOrder = projectLayerTreeRoot->
layerOrder();
1804 for (
int i = 0; i < projectLayerOrder.size(); ++i )
1808 if ( restrictedLayers.contains( l->
name() ) )
1812 #ifdef HAVE_SERVER_PYTHON_PLUGINS
1818 QString wmsName = l->
name();
1828 layerList << wmsName;
1831 if ( !layerList.isEmpty() )
1833 QStringList reversedList;
1834 reversedList.reserve( layerList.size() );
1835 for (
int i = layerList.size() - 1; i >= 0; --i )
1836 reversedList << layerList[ i ];
1838 QDomElement layerDrawingOrderElem = doc.createElement( QStringLiteral(
"LayerDrawingOrder" ) );
1839 QDomText drawingOrderText = doc.createTextNode( reversedList.join(
',' ) );
1840 layerDrawingOrderElem.appendChild( drawingOrderText );
1841 parentElem.appendChild( layerDrawingOrderElem );
1845 void appendLayerProjectSettings( QDomDocument &doc, QDomElement &layerElem,
QgsMapLayer *currentLayer )
1847 if ( !currentLayer )
1853 QDomElement treeNameElem = doc.createElement( QStringLiteral(
"TreeName" ) );
1854 QDomText treeNameText = doc.createTextNode( currentLayer->
name() );
1855 treeNameElem.appendChild( treeNameText );
1856 layerElem.appendChild( treeNameElem );
1858 switch ( currentLayer->
type() )
1865 int displayFieldIdx = -1;
1866 QString displayField = QStringLiteral(
"maptip" );
1868 if ( exp.isField() )
1875 QDomElement attributesElem = doc.createElement( QStringLiteral(
"Attributes" ) );
1877 for (
int idx = 0; idx < layerFields.
count(); ++idx )
1880 if ( excludedAttributes.contains( field.
name() ) )
1885 if ( idx == displayFieldIdx )
1889 QDomElement attributeElem = doc.createElement( QStringLiteral(
"Attribute" ) );
1890 attributeElem.setAttribute( QStringLiteral(
"name" ), field.
name() );
1891 attributeElem.setAttribute( QStringLiteral(
"type" ), QVariant::typeToName( field.
type() ) );
1892 attributeElem.setAttribute( QStringLiteral(
"typeName" ), field.
typeName() );
1893 QString alias = field.
alias();
1894 if ( !alias.isEmpty() )
1896 attributeElem.setAttribute( QStringLiteral(
"alias" ), alias );
1900 attributeElem.setAttribute( QStringLiteral(
"editType" ), vLayer->
editorWidgetSetup( idx ).
type() );
1901 attributeElem.setAttribute( QStringLiteral(
"comment" ), field.
comment() );
1902 attributeElem.setAttribute( QStringLiteral(
"length" ), field.
length() );
1903 attributeElem.setAttribute( QStringLiteral(
"precision" ), field.
precision() );
1904 attributesElem.appendChild( attributeElem );
1908 layerElem.setAttribute( QStringLiteral(
"displayField" ), displayField );
1912 if ( pkAttributes.size() > 0 )
1914 QDomElement pkElem = doc.createElement( QStringLiteral(
"PrimaryKey" ) );
1915 QgsAttributeList::const_iterator pkIt = pkAttributes.constBegin();
1916 for ( ; pkIt != pkAttributes.constEnd(); ++pkIt )
1918 QDomElement pkAttributeElem = doc.createElement( QStringLiteral(
"PrimaryKeyAttribute" ) );
1919 QDomText pkAttName = doc.createTextNode( layerFields.
at( *pkIt ).
name() );
1920 pkAttributeElem.appendChild( pkAttName );
1921 pkElem.appendChild( pkAttributeElem );
1923 layerElem.appendChild( pkElem );
1930 layerElem.setAttribute( QStringLiteral(
"opacity" ), QString::number( vLayer->
opacity() ) );
1932 layerElem.appendChild( attributesElem );
1939 if ( provider && provider->
name() ==
"wms" )
1942 QVariant wmsBackgroundLayer = currentLayer->
customProperty( QStringLiteral(
"WMSBackgroundLayer" ), false );
1943 QDomElement wmsBackgroundLayerElem = doc.createElement(
"WMSBackgroundLayer" );
1944 QDomText wmsBackgroundLayerText = doc.createTextNode( wmsBackgroundLayer.toBool() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1945 wmsBackgroundLayerElem.appendChild( wmsBackgroundLayerText );
1946 layerElem.appendChild( wmsBackgroundLayerElem );
1949 QVariant wmsPublishDataSourceUrl = currentLayer->
customProperty( QStringLiteral(
"WMSPublishDataSourceUrl" ),
false );
1950 if ( wmsPublishDataSourceUrl.toBool() )
1952 bool tiled = qobject_cast< const QgsRasterDataProvider * >( provider )
1953 ? !qobject_cast< const QgsRasterDataProvider * >( provider )->nativeResolutions().isEmpty()
1956 QDomElement dataSourceElem = doc.createElement( tiled ? QStringLiteral(
"WMTSDataSource" ) : QStringLiteral(
"WMSDataSource" ) );
1957 QDomText dataSourceUri = doc.createTextNode( provider->
dataSourceUri() );
1958 dataSourceElem.appendChild( dataSourceUri );
1959 layerElem.appendChild( dataSourceElem );
1963 QVariant wmsPrintLayer = currentLayer->
customProperty( QStringLiteral(
"WMSPrintLayer" ) );
1964 if ( wmsPrintLayer.isValid() )
1966 QDomElement wmsPrintLayerElem = doc.createElement(
"WMSPrintLayer" );
1967 QDomText wmsPrintLayerText = doc.createTextNode( wmsPrintLayer.toString() );
1968 wmsPrintLayerElem.appendChild( wmsPrintLayerText );
1969 layerElem.appendChild( wmsPrintLayerElem );
1975 if ( rasterRenderer )
1977 layerElem.setAttribute( QStringLiteral(
"opacity" ), QString::number( rasterRenderer->
opacity() ) );
1989 void addKeywordListElement(
const QgsProject *project, QDomDocument &doc, QDomElement &parent )
1993 QDomElement keywordsElem = doc.createElement( QStringLiteral(
"KeywordList" ) );
1995 QDomElement keywordElem = doc.createElement( QStringLiteral(
"Keyword" ) );
1996 keywordElem.setAttribute( QStringLiteral(
"vocabulary" ), QStringLiteral(
"ISO" ) );
1997 QDomText keywordText = doc.createTextNode( QStringLiteral(
"infoMapAccessService" ) );
1998 keywordElem.appendChild( keywordText );
1999 keywordsElem.appendChild( keywordElem );
2000 parent.appendChild( keywordsElem );
2002 for (
const QString &keyword : qgis::as_const( keywords ) )
2004 if ( !keyword.isEmpty() )
2006 keywordElem = doc.createElement( QStringLiteral(
"Keyword" ) );
2007 keywordText = doc.createTextNode( keyword );
2008 keywordElem.appendChild( keywordText );
2011 keywordElem.setAttribute( QStringLiteral(
"vocabulary" ), QStringLiteral(
"SIA_Geo405" ) );
2013 keywordsElem.appendChild( keywordElem );
2016 parent.appendChild( keywordsElem );
2024 for (
int j = 0; j < childNode->
children().size(); ++j )
2034 const auto l { treeLayer->
layer() };