52 void appendLayerProjectSettings( QDomDocument &doc, QDomElement &layerElem,
QgsMapLayer *currentLayer );
54 void appendDrawingOrder( QDomDocument &doc, QDomElement &parentElem,
QgsServerInterface *serverIface,
57 void combineExtentAndCrsOfGroupChildren( QDomDocument &doc, QDomElement &groupElem,
const QgsProject *project,
58 bool considerMapExtent =
false );
60 bool crsSetFromLayerElement(
const QDomElement &layerElement, QSet<QString> &crsSet );
62 QgsRectangle layerBoundingBoxInProjectCrs(
const QDomDocument &doc,
const QDomElement &layerElem,
65 void appendLayerBoundingBox( QDomDocument &doc, QDomElement &layerElem,
const QgsRectangle &layerExtent,
69 void appendLayerBoundingBoxes( QDomDocument &doc, QDomElement &layerElem,
const QgsRectangle &lExtent,
71 const QStringList &constrainedCrsList,
const QgsProject *project,
74 void appendCrsElementToLayer( QDomDocument &doc, QDomElement &layerElement,
const QDomElement &precedingElement,
75 const QString &crsText );
77 void appendCrsElementsToLayer( QDomDocument &doc, QDomElement &layerElement,
78 const QStringList &crsList,
const QStringList &constrainedCrsList );
80 void appendLayerStyles( QDomDocument &doc, QDomElement &layerElem,
QgsMapLayer *currentLayer,
83 void appendLayersFromTreeGroup( QDomDocument &doc,
84 QDomElement &parentLayer,
87 const QgsWmsRequest &request,
89 bool projectSettings );
91 void addKeywordListElement(
const QgsProject *project, QDomDocument &doc, QDomElement &parent );
96 const QgsWmsRequest &request,
98 bool projectSettings )
100 #ifdef HAVE_SERVER_PYTHON_PLUGINS
105 const QDomDocument *capabilitiesDocument =
nullptr;
110 QStringList cacheKeyList;
111 cacheKeyList << ( projectSettings ? QStringLiteral(
"projectSettings" ) : request.wmsParameters().version() );
115 #ifdef HAVE_SERVER_PYTHON_PLUGINS
119 QString cacheKey = cacheKeyList.join(
'-' );
121 #ifdef HAVE_SERVER_PYTHON_PLUGINS
123 if ( cacheManager && cacheManager->
getCachedDocument( &doc, project, request, accessControl ) )
125 capabilitiesDocument = &doc;
128 if ( !capabilitiesDocument && cache )
133 if ( !capabilitiesDocument )
135 QgsMessageLog::logMessage( QStringLiteral(
"WMS capabilities document not found in cache" ), QStringLiteral(
"Server" ) );
137 doc =
getCapabilities( serverIface, project, request, projectSettings );
139 #ifdef HAVE_SERVER_PYTHON_PLUGINS
143 capabilitiesDocument = &doc;
148 if ( !capabilitiesDocument )
153 if ( !capabilitiesDocument )
155 capabilitiesDocument = &doc;
167 response.
setHeader( QStringLiteral(
"Content-Type" ), QStringLiteral(
"text/xml; charset=utf-8" ) );
168 response.
write( capabilitiesDocument->toByteArray() );
172 const QgsWmsRequest &request,
173 bool projectSettings )
176 QDomElement wmsCapabilitiesElement;
182 QString hrefString = href.toString();
183 hrefString.append( href.hasQuery() ?
"&" :
"?" );
186 QDomProcessingInstruction xmlDeclaration = doc.createProcessingInstruction( QStringLiteral(
"xml" ),
187 QStringLiteral(
"version=\"1.0\" encoding=\"utf-8\"" ) );
190 std::function < void ( QDomElement &,
const QString & ) > appendFormat = [&doc]( QDomElement & elem,
const QString & format )
192 QDomElement formatElem = doc.createElement( QStringLiteral(
"Format" ) );
193 formatElem.appendChild( doc.createTextNode( format ) );
194 elem.appendChild( formatElem );
197 if ( request.wmsParameters().version() == QLatin1String(
"1.1.1" ) )
199 doc = QDomDocument( QStringLiteral(
"WMT_MS_Capabilities SYSTEM 'http://schemas.opengis.net/wms/1.1.1/WMS_MS_Capabilities.dtd'" ) );
200 doc.appendChild( xmlDeclaration );
201 wmsCapabilitiesElement = doc.createElement( QStringLiteral(
"WMT_MS_Capabilities" ) );
205 doc.appendChild( xmlDeclaration );
206 wmsCapabilitiesElement = doc.createElement( QStringLiteral(
"WMS_Capabilities" ) );
207 wmsCapabilitiesElement.setAttribute( QStringLiteral(
"xmlns" ), QStringLiteral(
"http://www.opengis.net/wms" ) );
208 wmsCapabilitiesElement.setAttribute( QStringLiteral(
"xmlns:sld" ), QStringLiteral(
"http://www.opengis.net/sld" ) );
209 wmsCapabilitiesElement.setAttribute( QStringLiteral(
"xmlns:qgs" ), QStringLiteral(
"http://www.qgis.org/wms" ) );
210 wmsCapabilitiesElement.setAttribute( QStringLiteral(
"xmlns:xsi" ), QStringLiteral(
"http://www.w3.org/2001/XMLSchema-instance" ) );
211 QString schemaLocation = QStringLiteral(
"http://www.opengis.net/wms" );
212 schemaLocation += QLatin1String(
" http://schemas.opengis.net/wms/1.3.0/capabilities_1_3_0.xsd" );
213 schemaLocation += QLatin1String(
" http://www.opengis.net/sld" );
214 schemaLocation += QLatin1String(
" http://schemas.opengis.net/sld/1.1.0/sld_capabilities.xsd" );
218 wmsCapabilitiesElement.setAttribute( QStringLiteral(
"xmlns:inspire_common" ), QStringLiteral(
"http://inspire.ec.europa.eu/schemas/common/1.0" ) );
219 wmsCapabilitiesElement.setAttribute( QStringLiteral(
"xmlns:inspire_vs" ), QStringLiteral(
"http://inspire.ec.europa.eu/schemas/inspire_vs/1.0" ) );
220 schemaLocation += QLatin1String(
" http://inspire.ec.europa.eu/schemas/inspire_vs/1.0" );
221 schemaLocation += QLatin1String(
" http://inspire.ec.europa.eu/schemas/inspire_vs/1.0/inspire_vs.xsd" );
224 schemaLocation += QLatin1String(
" http://www.qgis.org/wms" );
225 schemaLocation +=
" " + hrefString +
"SERVICE=WMS&REQUEST=GetSchemaExtension";
227 wmsCapabilitiesElement.setAttribute( QStringLiteral(
"xsi:schemaLocation" ), schemaLocation );
229 wmsCapabilitiesElement.setAttribute( QStringLiteral(
"version" ), request.wmsParameters().version() );
230 doc.appendChild( wmsCapabilitiesElement );
236 QDomElement capabilityElement =
getCapabilityElement( doc, project, request, projectSettings, serverIface );
237 wmsCapabilitiesElement.appendChild( capabilityElement );
239 if ( projectSettings )
248 capabilityElement.appendChild(
252 if ( projectSettings )
254 appendDrawingOrder( doc, capabilityElement, serverIface, project );
264 QDomElement serviceElem = doc.createElement( QStringLiteral(
"Service" ) );
267 QDomElement nameElem = doc.createElement( QStringLiteral(
"Name" ) );
268 QDomText nameText = doc.createTextNode( QStringLiteral(
"WMS" ) );
269 nameElem.appendChild( nameText );
270 serviceElem.appendChild( nameElem );
273 QDomElement titleElem = doc.createElement( QStringLiteral(
"Title" ) );
275 titleElem.appendChild( titleText );
276 serviceElem.appendChild( titleElem );
279 if ( !
abstract.isEmpty() )
281 QDomElement abstractElem = doc.createElement( QStringLiteral(
"Abstract" ) );
282 QDomText abstractText = doc.createCDATASection(
abstract );
283 abstractElem.appendChild( abstractText );
284 serviceElem.appendChild( abstractElem );
287 addKeywordListElement( project, doc, serviceElem );
290 if ( onlineResource.isEmpty() )
292 onlineResource =
serviceUrl( request, project, *serverSettings ).toString();
294 QDomElement onlineResourceElem = doc.createElement( QStringLiteral(
"OnlineResource" ) );
295 onlineResourceElem.setAttribute( QStringLiteral(
"xmlns:xlink" ), QStringLiteral(
"http://www.w3.org/1999/xlink" ) );
296 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
297 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:href" ), onlineResource );
298 serviceElem.appendChild( onlineResourceElem );
305 if ( !contactPerson.isEmpty() ||
306 !contactOrganization.isEmpty() ||
307 !contactPosition.isEmpty() ||
308 !contactMail.isEmpty() ||
309 !contactPhone.isEmpty() )
312 QDomElement contactInfoElem = doc.createElement( QStringLiteral(
"ContactInformation" ) );
315 if ( !contactPerson.isEmpty() ||
316 !contactOrganization.isEmpty() )
318 QDomElement contactPersonPrimaryElem = doc.createElement( QStringLiteral(
"ContactPersonPrimary" ) );
320 QDomText contactPersonText;
321 if ( !contactPerson.isEmpty() )
323 contactPersonText = doc.createTextNode( contactPerson );
327 contactPersonText = doc.createTextNode( QStringLiteral(
"unknown" ) );
329 QDomElement contactPersonElem = doc.createElement( QStringLiteral(
"ContactPerson" ) );
330 contactPersonElem.appendChild( contactPersonText );
331 contactPersonPrimaryElem.appendChild( contactPersonElem );
333 QDomText contactOrganizationText;
334 if ( !contactOrganization.isEmpty() )
336 contactOrganizationText = doc.createTextNode( contactOrganization );
340 contactOrganizationText = doc.createTextNode( QStringLiteral(
"unknown" ) );
342 QDomElement contactOrganizationElem = doc.createElement( QStringLiteral(
"ContactOrganization" ) );
343 contactOrganizationElem.appendChild( contactOrganizationText );
344 contactPersonPrimaryElem.appendChild( contactOrganizationElem );
346 contactInfoElem.appendChild( contactPersonPrimaryElem );
349 if ( !contactPosition.isEmpty() )
351 QDomElement contactPositionElem = doc.createElement( QStringLiteral(
"ContactPosition" ) );
352 QDomText contactPositionText = doc.createTextNode( contactPosition );
353 contactPositionElem.appendChild( contactPositionText );
354 contactInfoElem.appendChild( contactPositionElem );
357 if ( !contactPhone.isEmpty() )
359 QDomElement phoneElem = doc.createElement( QStringLiteral(
"ContactVoiceTelephone" ) );
360 QDomText phoneText = doc.createTextNode( contactPhone );
361 phoneElem.appendChild( phoneText );
362 contactInfoElem.appendChild( phoneElem );
365 if ( !contactMail.isEmpty() )
367 QDomElement mailElem = doc.createElement( QStringLiteral(
"ContactElectronicMailAddress" ) );
368 QDomText mailText = doc.createTextNode( contactMail );
369 mailElem.appendChild( mailText );
370 contactInfoElem.appendChild( mailElem );
373 serviceElem.appendChild( contactInfoElem );
376 QDomElement feesElem = doc.createElement( QStringLiteral(
"Fees" ) );
377 QDomText feesText = doc.createTextNode( QStringLiteral(
"None" ) );
379 if ( !fees.isEmpty() )
381 feesText = doc.createTextNode( fees );
383 feesElem.appendChild( feesText );
384 serviceElem.appendChild( feesElem );
386 QDomElement accessConstraintsElem = doc.createElement( QStringLiteral(
"AccessConstraints" ) );
387 QDomText accessConstraintsText = doc.createTextNode( QStringLiteral(
"None" ) );
389 if ( !accessConstraints.isEmpty() )
391 accessConstraintsText = doc.createTextNode( accessConstraints );
393 accessConstraintsElem.appendChild( accessConstraintsText );
394 serviceElem.appendChild( accessConstraintsElem );
396 if ( request.wmsParameters().version() == QLatin1String(
"1.3.0" ) )
401 QDomElement maxWidthElem = doc.createElement( QStringLiteral(
"MaxWidth" ) );
402 QDomText maxWidthText = doc.createTextNode( QString::number( maxWidth ) );
403 maxWidthElem.appendChild( maxWidthText );
404 serviceElem.appendChild( maxWidthElem );
410 QDomElement maxHeightElem = doc.createElement( QStringLiteral(
"MaxHeight" ) );
411 QDomText maxHeightText = doc.createTextNode( QString::number( maxHeight ) );
412 maxHeightElem.appendChild( maxHeightText );
413 serviceElem.appendChild( maxHeightElem );
421 const QgsWmsRequest &request,
424 const QString version = request.wmsParameters().version();
430 QString hrefString = href.toString();
431 hrefString.append( href.hasQuery() ?
"&" :
"?" );
433 QDomElement capabilityElem = doc.createElement( QStringLiteral(
"Capability" ) );
436 QDomElement requestElem = doc.createElement( QStringLiteral(
"Request" ) );
437 capabilityElem.appendChild( requestElem );
439 QDomElement dcpTypeElem = doc.createElement( QStringLiteral(
"DCPType" ) );
440 QDomElement httpElem = doc.createElement( QStringLiteral(
"HTTP" ) );
441 dcpTypeElem.appendChild( httpElem );
444 std::function < void ( QDomElement &,
const QString & ) > appendFormat = [&doc]( QDomElement & elem,
const QString & format )
446 QDomElement formatElem = doc.createElement( QStringLiteral(
"Format" ) );
447 formatElem.appendChild( doc.createTextNode( format ) );
448 elem.appendChild( formatElem );
454 elem = doc.createElement( QStringLiteral(
"GetCapabilities" ) );
455 appendFormat( elem, ( version == QLatin1String(
"1.1.1" ) ?
"application/vnd.ogc.wms_xml" :
"text/xml" ) );
456 elem.appendChild( dcpTypeElem );
457 requestElem.appendChild( elem );
460 QDomElement getElem = doc.createElement( QStringLiteral(
"Get" ) );
461 httpElem.appendChild( getElem );
462 QDomElement olResourceElem = doc.createElement( QStringLiteral(
"OnlineResource" ) );
463 olResourceElem.setAttribute( QStringLiteral(
"xmlns:xlink" ), QStringLiteral(
"http://www.w3.org/1999/xlink" ) );
464 olResourceElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
465 olResourceElem.setAttribute( QStringLiteral(
"xlink:href" ), hrefString );
466 getElem.appendChild( olResourceElem );
469 elem = doc.createElement( QStringLiteral(
"GetMap" ) );
470 appendFormat( elem, QStringLiteral(
"image/jpeg" ) );
471 appendFormat( elem, QStringLiteral(
"image/png" ) );
472 appendFormat( elem, QStringLiteral(
"image/png; mode=16bit" ) );
473 appendFormat( elem, QStringLiteral(
"image/png; mode=8bit" ) );
474 appendFormat( elem, QStringLiteral(
"image/png; mode=1bit" ) );
475 appendFormat( elem, QStringLiteral(
"application/dxf" ) );
476 elem.appendChild( dcpTypeElem.cloneNode().toElement() );
477 requestElem.appendChild( elem );
480 elem = doc.createElement( QStringLiteral(
"GetFeatureInfo" ) );
481 appendFormat( elem, QStringLiteral(
"text/plain" ) );
482 appendFormat( elem, QStringLiteral(
"text/html" ) );
483 appendFormat( elem, QStringLiteral(
"text/xml" ) );
484 appendFormat( elem, QStringLiteral(
"application/vnd.ogc.gml" ) );
485 appendFormat( elem, QStringLiteral(
"application/vnd.ogc.gml/3.1.1" ) );
486 appendFormat( elem, QStringLiteral(
"application/json" ) );
487 appendFormat( elem, QStringLiteral(
"application/geo+json" ) );
488 elem.appendChild( dcpTypeElem.cloneNode().toElement() );
489 requestElem.appendChild( elem );
492 elem = doc.createElement( ( version == QLatin1String(
"1.1.1" ) ?
"GetLegendGraphic" :
"sld:GetLegendGraphic" ) );
493 appendFormat( elem, QStringLiteral(
"image/jpeg" ) );
494 appendFormat( elem, QStringLiteral(
"image/png" ) );
495 appendFormat( elem, QStringLiteral(
"application/json" ) );
496 elem.appendChild( dcpTypeElem.cloneNode().toElement() );
497 requestElem.appendChild( elem );
500 elem = doc.createElement( ( version == QLatin1String(
"1.1.1" ) ?
"DescribeLayer" :
"sld:DescribeLayer" ) );
501 appendFormat( elem, QStringLiteral(
"text/xml" ) );
502 elem.appendChild( dcpTypeElem.cloneNode().toElement() );
503 requestElem.appendChild( elem );
506 elem = doc.createElement( ( version == QLatin1String(
"1.1.1" ) ?
"GetStyles" :
"qgs:GetStyles" ) );
507 appendFormat( elem, QStringLiteral(
"text/xml" ) );
508 elem.appendChild( dcpTypeElem.cloneNode().toElement() );
509 requestElem.appendChild( elem );
515 elem = doc.createElement( QStringLiteral(
"GetPrint" ) );
516 appendFormat( elem, QStringLiteral(
"svg" ) );
517 appendFormat( elem, QStringLiteral(
"png" ) );
518 appendFormat( elem, QStringLiteral(
"pdf" ) );
519 elem.appendChild( dcpTypeElem.cloneNode().toElement() );
520 requestElem.appendChild( elem );
524 elem = doc.createElement( QStringLiteral(
"Exception" ) );
525 appendFormat( elem, ( version == QLatin1String(
"1.1.1" ) ?
"application/vnd.ogc.se_xml" :
"XML" ) );
526 capabilityElem.appendChild( elem );
529 if ( version == QLatin1String(
"1.3.0" ) )
531 elem = doc.createElement( QStringLiteral(
"sld:UserDefinedSymbolization" ) );
532 elem.setAttribute( QStringLiteral(
"SupportSLD" ), QStringLiteral(
"1" ) );
533 elem.setAttribute( QStringLiteral(
"UserLayer" ), QStringLiteral(
"0" ) );
534 elem.setAttribute( QStringLiteral(
"UserStyle" ), QStringLiteral(
"1" ) );
535 elem.setAttribute( QStringLiteral(
"RemoteWFS" ), QStringLiteral(
"0" ) );
536 elem.setAttribute( QStringLiteral(
"InlineFeature" ), QStringLiteral(
"0" ) );
537 elem.setAttribute( QStringLiteral(
"RemoteWCS" ), QStringLiteral(
"0" ) );
538 capabilityElem.appendChild( elem );
546 return capabilityElem;
551 QDomElement inspireCapabilitiesElem;
554 return inspireCapabilitiesElem;
556 inspireCapabilitiesElem = doc.createElement( QStringLiteral(
"inspire_vs:ExtendedCapabilities" ) );
560 if ( !inspireMetadataUrl.isEmpty() )
562 QDomElement inspireCommonMetadataUrlElem = doc.createElement( QStringLiteral(
"inspire_common:MetadataUrl" ) );
563 inspireCommonMetadataUrlElem.setAttribute( QStringLiteral(
"xsi:type" ), QStringLiteral(
"inspire_common:resourceLocatorType" ) );
565 QDomElement inspireCommonMetadataUrlUrlElem = doc.createElement( QStringLiteral(
"inspire_common:URL" ) );
566 inspireCommonMetadataUrlUrlElem.appendChild( doc.createTextNode( inspireMetadataUrl ) );
567 inspireCommonMetadataUrlElem.appendChild( inspireCommonMetadataUrlUrlElem );
570 if ( !inspireMetadataUrlType.isNull() )
572 QDomElement inspireCommonMetadataUrlMediaTypeElem = doc.createElement( QStringLiteral(
"inspire_common:MediaType" ) );
573 inspireCommonMetadataUrlMediaTypeElem.appendChild( doc.createTextNode( inspireMetadataUrlType ) );
574 inspireCommonMetadataUrlElem.appendChild( inspireCommonMetadataUrlMediaTypeElem );
577 inspireCapabilitiesElem.appendChild( inspireCommonMetadataUrlElem );
581 QDomElement inspireCommonResourceTypeElem = doc.createElement( QStringLiteral(
"inspire_common:ResourceType" ) );
582 inspireCommonResourceTypeElem.appendChild( doc.createTextNode( QStringLiteral(
"service" ) ) );
583 inspireCapabilitiesElem.appendChild( inspireCommonResourceTypeElem );
585 QDomElement inspireCommonSpatialDataServiceTypeElem = doc.createElement( QStringLiteral(
"inspire_common:SpatialDataServiceType" ) );
586 inspireCommonSpatialDataServiceTypeElem.appendChild( doc.createTextNode( QStringLiteral(
"view" ) ) );
587 inspireCapabilitiesElem.appendChild( inspireCommonSpatialDataServiceTypeElem );
590 if ( !inspireTemporalReference.isNull() )
592 QDomElement inspireCommonTemporalReferenceElem = doc.createElement( QStringLiteral(
"inspire_common:TemporalReference" ) );
593 QDomElement inspireCommonDateOfLastRevisionElem = doc.createElement( QStringLiteral(
"inspire_common:DateOfLastRevision" ) );
594 inspireCommonDateOfLastRevisionElem.appendChild( doc.createTextNode( inspireTemporalReference ) );
595 inspireCommonTemporalReferenceElem.appendChild( inspireCommonDateOfLastRevisionElem );
596 inspireCapabilitiesElem.appendChild( inspireCommonTemporalReferenceElem );
599 QDomElement inspireCommonMetadataPointOfContactElem = doc.createElement( QStringLiteral(
"inspire_common:MetadataPointOfContact" ) );
602 QDomElement inspireCommonOrganisationNameElem = doc.createElement( QStringLiteral(
"inspire_common:OrganisationName" ) );
603 if ( !contactOrganization.isNull() )
605 inspireCommonOrganisationNameElem.appendChild( doc.createTextNode( contactOrganization ) );
607 inspireCommonMetadataPointOfContactElem.appendChild( inspireCommonOrganisationNameElem );
610 QDomElement inspireCommonEmailAddressElem = doc.createElement( QStringLiteral(
"inspire_common:EmailAddress" ) );
611 if ( !contactMail.isNull() )
613 inspireCommonEmailAddressElem.appendChild( doc.createTextNode( contactMail ) );
615 inspireCommonMetadataPointOfContactElem.appendChild( inspireCommonEmailAddressElem );
617 inspireCapabilitiesElem.appendChild( inspireCommonMetadataPointOfContactElem );
620 if ( !inspireMetadataDate.isNull() )
622 QDomElement inspireCommonMetadataDateElem = doc.createElement( QStringLiteral(
"inspire_common:MetadataDate" ) );
623 inspireCommonMetadataDateElem.appendChild( doc.createTextNode( inspireMetadataDate ) );
624 inspireCapabilitiesElem.appendChild( inspireCommonMetadataDateElem );
629 QDomElement inspireCommonSupportedLanguagesElem = doc.createElement( QStringLiteral(
"inspire_common:SupportedLanguages" ) );
630 inspireCommonSupportedLanguagesElem.setAttribute( QStringLiteral(
"xsi:type" ), QStringLiteral(
"inspire_common:supportedLanguagesType" ) );
632 QDomElement inspireCommonLanguageElem = doc.createElement( QStringLiteral(
"inspire_common:Language" ) );
635 QDomElement inspireCommonDefaultLanguageElem = doc.createElement( QStringLiteral(
"inspire_common:DefaultLanguage" ) );
636 inspireCommonDefaultLanguageElem.appendChild( inspireCommonLanguageElem );
637 inspireCommonSupportedLanguagesElem.appendChild( inspireCommonDefaultLanguageElem );
641 QDomElement inspireCommonSupportedLanguageElem = doc.createElement(
"inspire_common:SupportedLanguage" );
642 inspireCommonSupportedLanguageElem.appendChild( inspireCommonLanguageElem.cloneNode().toElement() );
643 inspireCommonSupportedLanguagesElem.appendChild( inspireCommonSupportedLanguageElem );
646 inspireCapabilitiesElem.appendChild( inspireCommonSupportedLanguagesElem );
648 QDomElement inspireCommonResponseLanguageElem = doc.createElement( QStringLiteral(
"inspire_common:ResponseLanguage" ) );
649 inspireCommonResponseLanguageElem.appendChild( inspireCommonLanguageElem.cloneNode().toElement() );
650 inspireCapabilitiesElem.appendChild( inspireCommonResponseLanguageElem );
652 return inspireCapabilitiesElem;
658 if ( projectComposers.size() == 0 )
659 return QDomElement();
663 QDomElement composerTemplatesElem = doc.createElement( QStringLiteral(
"ComposerTemplates" ) );
664 QList<QgsPrintLayout *>::const_iterator cIt = projectComposers.constBegin();
665 for ( ; cIt != projectComposers.constEnd(); ++cIt )
668 if ( restrictedComposers.contains( layout->
name() ) )
680 QDomElement composerTemplateElem = doc.createElement( QStringLiteral(
"ComposerTemplate" ) );
681 composerTemplateElem.setAttribute( QStringLiteral(
"name" ), layout->
name() );
684 composerTemplateElem.setAttribute( QStringLiteral(
"width" ), width.length() );
685 composerTemplateElem.setAttribute( QStringLiteral(
"height" ), height.length() );
689 if ( atlas && atlas->
enabled() )
691 composerTemplateElem.setAttribute( QStringLiteral(
"atlasEnabled" ), QStringLiteral(
"1" ) );
698 layerName = cLayer->
id();
700 else if ( layerName.isEmpty() )
702 layerName = cLayer->
name();
704 composerTemplateElem.setAttribute( QStringLiteral(
"atlasCoverageLayer" ), layerName );
709 QList<QgsLayoutItemMap *> layoutMapList;
711 QList<QgsLayoutItemMap *>::const_iterator cmIt = layoutMapList.constBegin();
714 for ( ; cmIt != layoutMapList.constEnd(); ++cmIt )
718 QDomElement composerMapElem = doc.createElement( QStringLiteral(
"ComposerMap" ) );
719 composerMapElem.setAttribute( QStringLiteral(
"name" ), QStringLiteral(
"map%1" ).arg( mapId ) );
720 composerMapElem.setAttribute( QStringLiteral(
"itemName" ), composerMap->
displayName() );
722 composerMapElem.setAttribute( QStringLiteral(
"width" ), composerMap->rect().width() );
723 composerMapElem.setAttribute( QStringLiteral(
"height" ), composerMap->rect().height() );
724 composerTemplateElem.appendChild( composerMapElem );
728 QList<QgsLayoutItemLabel *> composerLabelList;
730 QList<QgsLayoutItemLabel *>::const_iterator clIt = composerLabelList.constBegin();
731 for ( ; clIt != composerLabelList.constEnd(); ++clIt )
734 QString
id = composerLabel->
id();
738 QDomElement composerLabelElem = doc.createElement( QStringLiteral(
"ComposerLabel" ) );
739 composerLabelElem.setAttribute( QStringLiteral(
"name" ), id );
740 composerTemplateElem.appendChild( composerLabelElem );
744 QList<QgsLayoutItemHtml *> composerHtmlList;
746 QList<QgsLayoutItemHtml *>::const_iterator chIt = composerHtmlList.constBegin();
747 for ( ; chIt != composerHtmlList.constEnd(); ++chIt )
753 QString
id = composerHtml->
frame( 0 )->
id();
757 QDomElement composerHtmlElem = doc.createElement( QStringLiteral(
"ComposerHtml" ) );
758 composerHtmlElem.setAttribute( QStringLiteral(
"name" ), id );
759 composerTemplateElem.appendChild( composerHtmlElem );
762 composerTemplatesElem.appendChild( composerTemplateElem );
765 if ( composerTemplatesElem.childNodes().size() == 0 )
766 return QDomElement();
768 return composerTemplatesElem;
775 return QDomElement();
777 QDomElement wfsLayersElem = doc.createElement( QStringLiteral(
"WFSLayers" ) );
786 QDomElement wfsLayerElem = doc.createElement( QStringLiteral(
"WFSLayer" ) );
789 wfsLayerElem.setAttribute( QStringLiteral(
"name" ), layer->
id() );
793 wfsLayerElem.setAttribute( QStringLiteral(
"name" ), layer->
name() );
795 wfsLayersElem.appendChild( wfsLayerElem );
798 return wfsLayersElem;
803 const QgsWmsRequest &request,
bool projectSettings )
807 QDomElement layerParentElem = doc.createElement( QStringLiteral(
"Layer" ) );
811 if ( rootLayerName.isEmpty() && !project->
title().isEmpty() )
813 rootLayerName = project->
title();
816 if ( !rootLayerName.isEmpty() )
818 QDomElement layerParentNameElem = doc.createElement( QStringLiteral(
"Name" ) );
819 QDomText layerParentNameText = doc.createTextNode( rootLayerName );
820 layerParentNameElem.appendChild( layerParentNameText );
821 layerParentElem.appendChild( layerParentNameElem );
825 QDomElement layerParentTitleElem = doc.createElement( QStringLiteral(
"Title" ) );
827 layerParentTitleElem.appendChild( layerParentTitleText );
828 layerParentElem.appendChild( layerParentTitleElem );
832 if ( !rootLayerAbstract.isEmpty() )
834 QDomElement layerParentAbstElem = doc.createElement( QStringLiteral(
"Abstract" ) );
835 QDomText layerParentAbstText = doc.createCDATASection( rootLayerAbstract );
836 layerParentAbstElem.appendChild( layerParentAbstText );
837 layerParentElem.appendChild( layerParentAbstElem );
841 addKeywordListElement( project, doc, layerParentElem );
844 if ( projectSettings )
846 QDomElement treeNameElem = doc.createElement( QStringLiteral(
"TreeName" ) );
847 QDomText treeNameText = doc.createTextNode( project->
title() );
848 treeNameElem.appendChild( treeNameText );
849 layerParentElem.appendChild( treeNameElem );
854 layerParentElem.setAttribute( QStringLiteral(
"queryable" ), QStringLiteral(
"1" ) );
858 layerParentElem.setAttribute( QStringLiteral(
"queryable" ), QStringLiteral(
"0" ) );
861 appendLayersFromTreeGroup( doc, layerParentElem, serverIface, project, request, projectLayerTreeRoot, projectSettings );
863 combineExtentAndCrsOfGroupChildren( doc, layerParentElem, project,
true );
865 return layerParentElem;
871 void appendLayersFromTreeGroup( QDomDocument &doc,
872 QDomElement &parentLayer,
875 const QgsWmsRequest &request,
877 bool projectSettings )
879 const QString version = request.wmsParameters().version();
885 QList< QgsLayerTreeNode * > layerTreeGroupChildren = layerTreeGroup->
children();
886 for (
int i = 0; i < layerTreeGroupChildren.size(); ++i )
889 QDomElement layerElem = doc.createElement( QStringLiteral(
"Layer" ) );
891 if ( projectSettings )
893 layerElem.setAttribute( QStringLiteral(
"visible" ), treeNode->
isVisible() );
895 layerElem.setAttribute( QStringLiteral(
"expanded" ), treeNode->
isExpanded() );
902 QString name = treeGroupChild->
name();
903 if ( restrictedLayers.contains( name ) )
908 if ( projectSettings )
910 layerElem.setAttribute( QStringLiteral(
"mutuallyExclusive" ), treeGroupChild->
isMutuallyExclusive() );
913 QString shortName = treeGroupChild->
customProperty( QStringLiteral(
"wmsShortName" ) ).toString();
914 QString title = treeGroupChild->
customProperty( QStringLiteral(
"wmsTitle" ) ).toString();
916 QDomElement nameElem = doc.createElement( QStringLiteral(
"Name" ) );
918 if ( !shortName.isEmpty() )
919 nameText = doc.createTextNode( shortName );
921 nameText = doc.createTextNode( name );
922 nameElem.appendChild( nameText );
923 layerElem.appendChild( nameElem );
925 QDomElement titleElem = doc.createElement( QStringLiteral(
"Title" ) );
927 if ( !title.isEmpty() )
928 titleText = doc.createTextNode( title );
930 titleText = doc.createTextNode( name );
931 titleElem.appendChild( titleText );
932 layerElem.appendChild( titleElem );
934 QString
abstract = treeGroupChild->
customProperty( QStringLiteral(
"wmsAbstract" ) ).toString();
935 if ( !
abstract.isEmpty() )
937 QDomElement abstractElem = doc.createElement( QStringLiteral(
"Abstract" ) );
938 QDomText abstractText = doc.createTextNode(
abstract );
939 abstractElem.appendChild( abstractText );
940 layerElem.appendChild( abstractElem );
944 if ( projectSettings )
946 QDomElement treeNameElem = doc.createElement( QStringLiteral(
"TreeName" ) );
947 QDomText treeNameText = doc.createTextNode( name );
948 treeNameElem.appendChild( treeNameText );
949 layerElem.appendChild( treeNameElem );
955 layerElem.setAttribute( QStringLiteral(
"queryable" ), QStringLiteral(
"1" ) );
959 layerElem.setAttribute( QStringLiteral(
"queryable" ), QStringLiteral(
"0" ) );
962 appendLayersFromTreeGroup( doc, layerElem, serverIface, project, request, treeGroupChild, projectSettings );
964 combineExtentAndCrsOfGroupChildren( doc, layerElem, project );
970 if ( !l || restrictedLayers.contains( l->
name() ) )
975 #ifdef HAVE_SERVER_PYTHON_PLUGINS
982 QString wmsName = l->
name();
995 layerElem.setAttribute( QStringLiteral(
"queryable" ), QStringLiteral(
"0" ) );
999 layerElem.setAttribute( QStringLiteral(
"queryable" ), QStringLiteral(
"1" ) );
1002 QDomElement nameElem = doc.createElement( QStringLiteral(
"Name" ) );
1003 QDomText nameText = doc.createTextNode( wmsName );
1004 nameElem.appendChild( nameText );
1005 layerElem.appendChild( nameElem );
1007 QDomElement titleElem = doc.createElement( QStringLiteral(
"Title" ) );
1008 QString title = l->
title();
1009 if ( title.isEmpty() )
1013 QDomText titleText = doc.createTextNode( title );
1014 titleElem.appendChild( titleText );
1015 layerElem.appendChild( titleElem );
1018 if ( !
abstract.isEmpty() )
1020 QDomElement abstractElem = doc.createElement( QStringLiteral(
"Abstract" ) );
1021 QDomText abstractText = doc.createTextNode(
abstract );
1022 abstractElem.appendChild( abstractText );
1023 layerElem.appendChild( abstractElem );
1029 QStringList keywordStringList = l->
keywordList().split(
',' );
1031 QDomElement keywordListElem = doc.createElement( QStringLiteral(
"KeywordList" ) );
1032 for (
int i = 0; i < keywordStringList.size(); ++i )
1034 QDomElement keywordElem = doc.createElement( QStringLiteral(
"Keyword" ) );
1035 QDomText keywordText = doc.createTextNode( keywordStringList.at( i ).trimmed() );
1036 keywordElem.appendChild( keywordText );
1039 keywordElem.setAttribute( QStringLiteral(
"vocabulary" ), QStringLiteral(
"SIA_Geo405" ) );
1041 keywordListElem.appendChild( keywordElem );
1043 layerElem.appendChild( keywordListElem );
1047 bool geometryLayer =
true;
1055 geometryLayer =
false;
1061 if ( geometryLayer )
1063 QStringList crsList;
1066 appendCrsElementsToLayer( doc, layerElem, crsList, outputCrsList );
1081 else if ( l->
crs() != project->
crs() )
1087 extent = ct.transform( extent );
1091 QgsMessageLog::logMessage( QStringLiteral(
"Error transforming extent for layer %1: %2" ).arg( l->
name() ).arg( cse.
what() ), QStringLiteral(
"Server" ), Qgis::MessageLevel::Warning );
1102 appendLayerBoundingBoxes( doc, layerElem, extent, l->
crs(), crsList, outputCrsList, project, wgs84Extent );
1106 appendLayerStyles( doc, layerElem, l, project, request, serverIface->
serverSettings() );
1111 if ( version == QLatin1String(
"1.1.1" ) )
1114 double SCALE_TO_SCALEHINT =
OGC_PX_M * M_SQRT2;
1116 QDomElement scaleHintElem = doc.createElement( QStringLiteral(
"ScaleHint" ) );
1117 scaleHintElem.setAttribute( QStringLiteral(
"min" ), QString::number( l->
maximumScale() * SCALE_TO_SCALEHINT ) );
1118 scaleHintElem.setAttribute( QStringLiteral(
"max" ), QString::number( l->
minimumScale() * SCALE_TO_SCALEHINT ) );
1119 layerElem.appendChild( scaleHintElem );
1123 QString minScaleString = QString::number( l->
maximumScale() );
1124 QDomElement minScaleElem = doc.createElement( QStringLiteral(
"MinScaleDenominator" ) );
1125 QDomText minScaleText = doc.createTextNode( minScaleString );
1126 minScaleElem.appendChild( minScaleText );
1127 layerElem.appendChild( minScaleElem );
1129 QString maxScaleString = QString::number( l->
minimumScale() );
1130 QDomElement maxScaleElem = doc.createElement( QStringLiteral(
"MaxScaleDenominator" ) );
1131 QDomText maxScaleText = doc.createTextNode( maxScaleString );
1132 maxScaleElem.appendChild( maxScaleText );
1133 layerElem.appendChild( maxScaleElem );
1138 QString dataUrl = l->
dataUrl();
1139 if ( !dataUrl.isEmpty() )
1141 QDomElement dataUrlElem = doc.createElement( QStringLiteral(
"DataURL" ) );
1142 QDomElement dataUrlFormatElem = doc.createElement( QStringLiteral(
"Format" ) );
1144 QDomText dataUrlFormatText = doc.createTextNode( dataUrlFormat );
1145 dataUrlFormatElem.appendChild( dataUrlFormatText );
1146 dataUrlElem.appendChild( dataUrlFormatElem );
1147 QDomElement dataORElem = doc.createElement( QStringLiteral(
"OnlineResource" ) );
1148 dataORElem.setAttribute( QStringLiteral(
"xmlns:xlink" ), QStringLiteral(
"http://www.w3.org/1999/xlink" ) );
1149 dataORElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
1150 dataORElem.setAttribute( QStringLiteral(
"xlink:href" ), dataUrl );
1151 dataUrlElem.appendChild( dataORElem );
1152 layerElem.appendChild( dataUrlElem );
1157 if ( !attribution.isEmpty() )
1159 QDomElement attribElem = doc.createElement( QStringLiteral(
"Attribution" ) );
1160 QDomElement attribTitleElem = doc.createElement( QStringLiteral(
"Title" ) );
1161 QDomText attribText = doc.createTextNode( attribution );
1162 attribTitleElem.appendChild( attribText );
1163 attribElem.appendChild( attribTitleElem );
1165 if ( !attributionUrl.isEmpty() )
1167 QDomElement attribORElem = doc.createElement( QStringLiteral(
"OnlineResource" ) );
1168 attribORElem.setAttribute( QStringLiteral(
"xmlns:xlink" ), QStringLiteral(
"http://www.w3.org/1999/xlink" ) );
1169 attribORElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
1170 attribORElem.setAttribute( QStringLiteral(
"xlink:href" ), attributionUrl );
1171 attribElem.appendChild( attribORElem );
1173 layerElem.appendChild( attribElem );
1180 QDomElement metaUrlElem = doc.createElement( QStringLiteral(
"MetadataURL" ) );
1181 QString metadataUrlType = url.type;
1182 if ( version == QLatin1String(
"1.1.1" ) )
1184 metaUrlElem.setAttribute( QStringLiteral(
"type" ), metadataUrlType );
1186 else if ( metadataUrlType == QLatin1String(
"FGDC" ) )
1188 metaUrlElem.setAttribute( QStringLiteral(
"type" ), QStringLiteral(
"FGDC:1998" ) );
1190 else if ( metadataUrlType == QLatin1String(
"TC211" ) )
1192 metaUrlElem.setAttribute( QStringLiteral(
"type" ), QStringLiteral(
"ISO19115:2003" ) );
1196 metaUrlElem.setAttribute( QStringLiteral(
"type" ), metadataUrlType );
1198 QString metadataUrlFormat = url.format;
1199 if ( !metadataUrlFormat.isEmpty() )
1201 QDomElement metaUrlFormatElem = doc.createElement( QStringLiteral(
"Format" ) );
1202 QDomText metaUrlFormatText = doc.createTextNode( metadataUrlFormat );
1203 metaUrlFormatElem.appendChild( metaUrlFormatText );
1204 metaUrlElem.appendChild( metaUrlFormatElem );
1206 QDomElement metaUrlORElem = doc.createElement( QStringLiteral(
"OnlineResource" ) );
1207 metaUrlORElem.setAttribute( QStringLiteral(
"xmlns:xlink" ), QStringLiteral(
"http://www.w3.org/1999/xlink" ) );
1208 metaUrlORElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
1209 metaUrlORElem.setAttribute( QStringLiteral(
"xlink:href" ), url.url );
1210 metaUrlElem.appendChild( metaUrlORElem );
1211 layerElem.appendChild( metaUrlElem );
1214 bool timeDimensionAdded {
false };
1221 const QList<QgsMapLayerServerProperties::WmsDimensionInfo> wmsDims = serverProperties->
wmsDimensions();
1227 if ( fieldIndex == -1 )
1232 QSet<QVariant> uniqueValues = vl->
uniqueValues( fieldIndex );
1235 if ( !dim.endFieldName.isEmpty() )
1237 int endFieldIndex = vl->
fields().
indexOf( dim.endFieldName );
1239 if ( endFieldIndex == -1 )
1243 uniqueValues.unite( vl->
uniqueValues( endFieldIndex ) );
1246 QList<QVariant> values = qgis::setToList( uniqueValues );
1247 std::sort( values.begin(), values.end() );
1249 QDomElement dimElem = doc.createElement( QStringLiteral(
"Dimension" ) );
1250 dimElem.setAttribute( QStringLiteral(
"name" ), dim.name );
1252 if ( dim.name.toUpper() == QLatin1String(
"TIME" ) )
1254 timeDimensionAdded =
true;
1257 if ( !dim.units.isEmpty() )
1259 dimElem.setAttribute( QStringLiteral(
"units" ), dim.units );
1261 if ( !dim.unitSymbol.isEmpty() )
1263 dimElem.setAttribute( QStringLiteral(
"unitSymbol" ), dim.unitSymbol );
1267 dimElem.setAttribute( QStringLiteral(
"default" ), values.first().toString() );
1271 dimElem.setAttribute( QStringLiteral(
"default" ), values.last().toString() );
1275 dimElem.setAttribute( QStringLiteral(
"default" ), dim.referenceValue.toString() );
1277 dimElem.setAttribute( QStringLiteral(
"multipleValues" ), QStringLiteral(
"1" ) );
1278 dimElem.setAttribute( QStringLiteral(
"nearestValue" ), QStringLiteral(
"0" ) );
1279 if ( projectSettings )
1281 dimElem.setAttribute( QStringLiteral(
"fieldName" ), dim.fieldName );
1282 dimElem.setAttribute( QStringLiteral(
"endFieldName" ), dim.endFieldName );
1285 QStringList strValues;
1286 for (
const QVariant &v : values )
1288 strValues << v.toString();
1290 QDomText dimValuesText = doc.createTextNode( strValues.join( QLatin1String(
", " ) ) );
1291 dimElem.appendChild( dimValuesText );
1292 layerElem.appendChild( dimElem );
1297 if ( ! timeDimensionAdded
1302 QDomElement dimElem = doc.createElement( QStringLiteral(
"Dimension" ) );
1303 dimElem.setAttribute( QStringLiteral(
"name" ), QStringLiteral(
"TIME" ) );
1304 dimElem.setAttribute( QStringLiteral(
"units" ), QStringLiteral(
"ISO8601" ) );
1314 bool isDateList {
true };
1315 bool isInstantList {
true };
1317 QList<QDateTime> values;
1318 for (
const auto &r : std::as_const( allRanges ) )
1320 if ( r.isInstant() )
1322 if ( r.begin().time() != QTime( 0, 0, 0, 0 ) )
1326 values.append( r.begin() );
1330 isInstantList =
false;
1337 if ( isInstantList )
1340 QStringList strValues;
1341 for (
const auto &v : values )
1345 strValues << v.date().toString( Qt::DateFormat::ISODate );
1349 strValues << v.toString( Qt::DateFormat::ISODate );
1352 QDomText dimValuesText = doc.createTextNode( strValues.join( QChar(
',' ) ) );
1353 dimElem.appendChild( dimValuesText );
1356 layerElem.appendChild( dimElem );
1358 QDomElement timeExtentElem = doc.createElement( QStringLiteral(
"Extent" ) );
1359 timeExtentElem.setAttribute( QStringLiteral(
"name" ), QStringLiteral(
"TIME" ) );
1365 extent = QStringLiteral(
"%1/%2" ).arg( timeExtent.begin().date().toString( Qt::DateFormat::ISODate ), timeExtent.end().date().toString( Qt::DateFormat::ISODate ) );
1369 extent = QStringLiteral(
"%1/%2" ).arg( timeExtent.begin().toString( Qt::DateFormat::ISODate ), timeExtent.end().toString( Qt::DateFormat::ISODate ) );
1371 QDomText extentValueText = doc.createTextNode( extent );
1372 timeExtentElem.appendChild( extentValueText );
1373 layerElem.appendChild( timeExtentElem );
1377 if ( projectSettings )
1379 appendLayerProjectSettings( doc, layerElem, l );
1383 parentLayer.appendChild( layerElem );
1387 void appendLayerStyles( QDomDocument &doc, QDomElement &layerElem,
QgsMapLayer *currentLayer,
1391 QUrl href =
serviceUrl( request, project, *settings );
1394 QString hrefString = href.toString();
1395 hrefString.append( href.hasQuery() ?
"&" :
"?" );
1398 QDomElement styleElem = doc.createElement( QStringLiteral(
"Style" ) );
1399 QDomElement styleNameElem = doc.createElement( QStringLiteral(
"Name" ) );
1400 QDomText styleNameText = doc.createTextNode( styleName );
1401 styleNameElem.appendChild( styleNameText );
1402 QDomElement styleTitleElem = doc.createElement( QStringLiteral(
"Title" ) );
1403 QDomText styleTitleText = doc.createTextNode( styleName );
1404 styleTitleElem.appendChild( styleTitleText );
1405 styleElem.appendChild( styleNameElem );
1406 styleElem.appendChild( styleTitleElem );
1409 QDomElement getLayerLegendGraphicElem = doc.createElement( QStringLiteral(
"LegendURL" ) );
1411 QString customHrefString = currentLayer->
legendUrl();
1413 QStringList getLayerLegendGraphicFormats;
1414 if ( !customHrefString.isEmpty() )
1420 getLayerLegendGraphicFormats << QStringLiteral(
"image/png" );
1423 for (
int i = 0; i < getLayerLegendGraphicFormats.size(); ++i )
1425 QDomElement getLayerLegendGraphicFormatElem = doc.createElement( QStringLiteral(
"Format" ) );
1426 QString getLayerLegendGraphicFormat = getLayerLegendGraphicFormats[i];
1427 QDomText getLayerLegendGraphicFormatText = doc.createTextNode( getLayerLegendGraphicFormat );
1428 getLayerLegendGraphicFormatElem.appendChild( getLayerLegendGraphicFormatText );
1429 getLayerLegendGraphicElem.appendChild( getLayerLegendGraphicFormatElem );
1433 if ( customHrefString.isEmpty() )
1435 QString layerName = currentLayer->
name();
1437 layerName = currentLayer->
id();
1438 else if ( !currentLayer->
shortName().isEmpty() )
1440 QUrl mapUrl( hrefString );
1441 QUrlQuery mapUrlQuery( mapUrl.query() );
1442 mapUrlQuery.addQueryItem( QStringLiteral(
"SERVICE" ), QStringLiteral(
"WMS" ) );
1443 mapUrlQuery.addQueryItem( QStringLiteral(
"VERSION" ), request.wmsParameters().version() );
1444 mapUrlQuery.addQueryItem( QStringLiteral(
"REQUEST" ), QStringLiteral(
"GetLegendGraphic" ) );
1445 mapUrlQuery.addQueryItem( QStringLiteral(
"LAYER" ), layerName );
1446 mapUrlQuery.addQueryItem( QStringLiteral(
"FORMAT" ), QStringLiteral(
"image/png" ) );
1447 mapUrlQuery.addQueryItem( QStringLiteral(
"STYLE" ), styleNameText.data() );
1448 if ( request.wmsParameters().version() == QLatin1String(
"1.3.0" ) )
1450 mapUrlQuery.addQueryItem( QStringLiteral(
"SLD_VERSION" ), QStringLiteral(
"1.1.0" ) );
1452 mapUrl.setQuery( mapUrlQuery );
1453 customHrefString = mapUrl.toString();
1456 QDomElement getLayerLegendGraphicORElem = doc.createElement( QStringLiteral(
"OnlineResource" ) );
1457 getLayerLegendGraphicORElem.setAttribute( QStringLiteral(
"xmlns:xlink" ), QStringLiteral(
"http://www.w3.org/1999/xlink" ) );
1458 getLayerLegendGraphicORElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
1459 getLayerLegendGraphicORElem.setAttribute( QStringLiteral(
"xlink:href" ), customHrefString );
1460 getLayerLegendGraphicElem.appendChild( getLayerLegendGraphicORElem );
1461 styleElem.appendChild( getLayerLegendGraphicElem );
1463 layerElem.appendChild( styleElem );
1467 void appendCrsElementsToLayer( QDomDocument &doc, QDomElement &layerElement,
1468 const QStringList &crsList,
const QStringList &constrainedCrsList )
1470 if ( layerElement.isNull() )
1475 const QString version = doc.documentElement().attribute( QStringLiteral(
"version" ) );
1478 QDomElement titleElement = layerElement.firstChildElement( QStringLiteral(
"Title" ) );
1479 QDomElement abstractElement = layerElement.firstChildElement( QStringLiteral(
"Abstract" ) );
1480 QDomElement keywordListElement = layerElement.firstChildElement( QStringLiteral(
"KeywordList" ) );
1481 QDomElement CRSPrecedingElement = !keywordListElement.isNull() ? keywordListElement : !abstractElement.isNull() ? abstractElement : titleElement;
1483 if ( CRSPrecedingElement.isNull() )
1486 const QDomElement keyElement = layerElement.firstChildElement( QStringLiteral(
"KeywordList" ) );
1487 CRSPrecedingElement = keyElement;
1491 if ( !constrainedCrsList.isEmpty() )
1493 for (
int i = constrainedCrsList.size() - 1; i >= 0; --i )
1495 appendCrsElementToLayer( doc, layerElement, CRSPrecedingElement, constrainedCrsList.at( i ) );
1500 for (
const QString &
crs : crsList )
1502 appendCrsElementToLayer( doc, layerElement, CRSPrecedingElement,
crs );
1508 if ( version == QLatin1String(
"1.3.0" ) )
1510 appendCrsElementToLayer( doc, layerElement, CRSPrecedingElement, QString(
"CRS:84" ) );
1514 void appendCrsElementToLayer( QDomDocument &doc, QDomElement &layerElement,
const QDomElement &precedingElement,
1515 const QString &crsText )
1517 if ( crsText.isEmpty() )
1519 const QString version = doc.documentElement().attribute( QStringLiteral(
"version" ) );
1520 QDomElement crsElement = doc.createElement( version == QLatin1String(
"1.1.1" ) ?
"SRS" :
"CRS" );
1521 QDomText crsTextNode = doc.createTextNode( crsText );
1522 crsElement.appendChild( crsTextNode );
1523 layerElement.insertAfter( crsElement, precedingElement );
1526 void appendLayerBoundingBoxes( QDomDocument &doc, QDomElement &layerElem,
const QgsRectangle &lExtent,
1528 const QStringList &constrainedCrsList,
const QgsProject *project,
1531 if ( layerElem.isNull() )
1540 layerExtent.
grow( 0.000001 );
1544 if ( wgs84BoundingRect.
isNull() )
1549 if ( !layerExtent.
isNull() )
1554 wgs84BoundingRect = exGeoTransform.transformBoundingBox( layerExtent );
1558 QgsMessageLog::logMessage( QStringLiteral(
"Error transforming extent: %1" ).arg( cse.
what() ), QStringLiteral(
"Server" ), Qgis::MessageLevel::Warning );
1567 wgs84BoundingRect.
grow( 0.000001 );
1571 QDomElement ExGeoBBoxElement;
1572 const int wgs84precision = 6;
1573 const QString version = doc.documentElement().attribute( QStringLiteral(
"version" ) );
1574 if ( version == QLatin1String(
"1.1.1" ) )
1576 ExGeoBBoxElement = doc.createElement( QStringLiteral(
"LatLonBoundingBox" ) );
1584 ExGeoBBoxElement = doc.createElement( QStringLiteral(
"EX_GeographicBoundingBox" ) );
1585 QDomElement wBoundLongitudeElement = doc.createElement( QStringLiteral(
"westBoundLongitude" ) );
1587 wBoundLongitudeElement.appendChild( wBoundLongitudeText );
1588 ExGeoBBoxElement.appendChild( wBoundLongitudeElement );
1589 QDomElement eBoundLongitudeElement = doc.createElement( QStringLiteral(
"eastBoundLongitude" ) );
1591 eBoundLongitudeElement.appendChild( eBoundLongitudeText );
1592 ExGeoBBoxElement.appendChild( eBoundLongitudeElement );
1593 QDomElement sBoundLatitudeElement = doc.createElement( QStringLiteral(
"southBoundLatitude" ) );
1595 sBoundLatitudeElement.appendChild( sBoundLatitudeText );
1596 ExGeoBBoxElement.appendChild( sBoundLatitudeElement );
1597 QDomElement nBoundLatitudeElement = doc.createElement( QStringLiteral(
"northBoundLatitude" ) );
1599 nBoundLatitudeElement.appendChild( nBoundLatitudeText );
1600 ExGeoBBoxElement.appendChild( nBoundLatitudeElement );
1603 if ( !wgs84BoundingRect.
isNull() )
1605 QDomElement lastCRSElem = layerElem.lastChildElement( version == QLatin1String(
"1.1.1" ) ?
"SRS" :
"CRS" );
1606 if ( !lastCRSElem.isNull() )
1608 layerElem.insertAfter( ExGeoBBoxElement, lastCRSElem );
1612 layerElem.appendChild( ExGeoBBoxElement );
1617 if ( !constrainedCrsList.isEmpty() )
1619 for (
int i = constrainedCrsList.size() - 1; i >= 0; --i )
1621 appendLayerBoundingBox( doc, layerElem, layerExtent, layerCRS, constrainedCrsList.at( i ), project );
1626 for (
const QString &
crs : crsList )
1628 appendLayerBoundingBox( doc, layerElem, layerExtent, layerCRS,
crs, project );
1634 void appendLayerBoundingBox( QDomDocument &doc, QDomElement &layerElem,
const QgsRectangle &layerExtent,
1638 if ( layerElem.isNull() )
1643 if ( crsText.isEmpty() )
1648 const QString version = doc.documentElement().attribute( QStringLiteral(
"version" ) );
1654 if ( !layerExtent.
isNull() )
1659 crsExtent = crsTransform.transformBoundingBox( layerExtent );
1663 QgsMessageLog::logMessage( QStringLiteral(
"Error transforming extent: %1" ).arg( cse.
what() ), QStringLiteral(
"Server" ), Qgis::MessageLevel::Warning );
1668 if ( crsExtent.
isNull() )
1680 QDomElement bBoxElement = doc.createElement( QStringLiteral(
"BoundingBox" ) );
1683 bBoxElement.setAttribute( version == QLatin1String(
"1.1.1" ) ?
"SRS" :
"CRS",
crs.
authid() );
1696 QDomElement lastBBoxElem = layerElem.lastChildElement( QStringLiteral(
"BoundingBox" ) );
1697 if ( !lastBBoxElem.isNull() )
1699 layerElem.insertAfter( bBoxElement, lastBBoxElem );
1703 lastBBoxElem = layerElem.lastChildElement( version == QLatin1String(
"1.1.1" ) ?
"LatLonBoundingBox" :
"EX_GeographicBoundingBox" );
1704 if ( !lastBBoxElem.isNull() )
1706 layerElem.insertAfter( bBoxElement, lastBBoxElem );
1710 layerElem.appendChild( bBoxElement );
1715 QgsRectangle layerBoundingBoxInProjectCrs(
const QDomDocument &doc,
const QDomElement &layerElem,
1719 if ( layerElem.isNull() )
1725 QDomElement boundingBoxElem = layerElem.firstChildElement( QStringLiteral(
"BoundingBox" ) );
1726 if ( boundingBoxElem.isNull() )
1731 double minx, miny, maxx, maxy;
1733 minx = boundingBoxElem.attribute( QStringLiteral(
"minx" ) ).toDouble( &conversionOk );
1734 if ( !conversionOk )
1738 miny = boundingBoxElem.attribute( QStringLiteral(
"miny" ) ).toDouble( &conversionOk );
1739 if ( !conversionOk )
1743 maxx = boundingBoxElem.attribute( QStringLiteral(
"maxx" ) ).toDouble( &conversionOk );
1744 if ( !conversionOk )
1748 maxy = boundingBoxElem.attribute( QStringLiteral(
"maxy" ) ).toDouble( &conversionOk );
1749 if ( !conversionOk )
1755 const QString version = doc.documentElement().attribute( QStringLiteral(
"version" ) );
1769 if ( version != QLatin1String(
"1.1.1" ) && layerCrs.
hasAxisInverted() )
1780 BBox = t.transformBoundingBox( BBox );
1784 QgsMessageLog::logMessage( QStringLiteral(
"Error transforming extent: %1" ).arg( cse.
what() ), QStringLiteral(
"Server" ), Qgis::MessageLevel::Warning );
1791 bool crsSetFromLayerElement(
const QDomElement &layerElement, QSet<QString> &crsSet )
1793 if ( layerElement.isNull() )
1800 QDomNodeList crsNodeList;
1801 crsNodeList = layerElement.elementsByTagName( QStringLiteral(
"CRS" ) );
1802 for (
int i = 0; i < crsNodeList.size(); ++i )
1804 crsSet.insert( crsNodeList.at( i ).toElement().text() );
1807 crsNodeList = layerElement.elementsByTagName( QStringLiteral(
"SRS" ) );
1808 for (
int i = 0; i < crsNodeList.size(); ++i )
1810 crsSet.insert( crsNodeList.at( i ).toElement().text() );
1816 void combineExtentAndCrsOfGroupChildren( QDomDocument &doc, QDomElement &groupElem,
const QgsProject *project,
1817 bool considerMapExtent )
1820 QSet<QString> combinedCRSSet;
1821 bool firstBBox =
true;
1822 bool firstCRSSet =
true;
1824 QDomNodeList layerChildren = groupElem.childNodes();
1825 for (
int j = 0; j < layerChildren.size(); ++j )
1827 QDomElement childElem = layerChildren.at( j ).toElement();
1829 if ( childElem.tagName() != QLatin1String(
"Layer" ) )
1832 QgsRectangle bbox = layerBoundingBoxInProjectCrs( doc, childElem, project );
1842 combinedBBox = bbox;
1852 QSet<QString> crsSet;
1853 if ( crsSetFromLayerElement( childElem, crsSet ) )
1857 combinedCRSSet = crsSet;
1858 firstCRSSet =
false;
1862 combinedCRSSet.intersect( crsSet );
1868 appendCrsElementsToLayer( doc, groupElem, qgis::setToList( combinedCRSSet ), outputCrsList );
1871 if ( considerMapExtent )
1876 combinedBBox = mapRect;
1879 appendLayerBoundingBoxes( doc, groupElem, combinedBBox, groupCRS, qgis::setToList( combinedCRSSet ), outputCrsList, project );
1883 void appendDrawingOrder( QDomDocument &doc, QDomElement &parentElem,
QgsServerInterface *serverIface,
1886 #ifdef HAVE_SERVER_PYTHON_PLUGINS
1889 ( void )serverIface;
1894 QStringList layerList;
1897 QList< QgsMapLayer * > projectLayerOrder = projectLayerTreeRoot->
layerOrder();
1898 for (
int i = 0; i < projectLayerOrder.size(); ++i )
1902 if ( restrictedLayers.contains( l->
name() ) )
1906 #ifdef HAVE_SERVER_PYTHON_PLUGINS
1912 QString wmsName = l->
name();
1922 layerList << wmsName;
1925 if ( !layerList.isEmpty() )
1927 QStringList reversedList;
1928 reversedList.reserve( layerList.size() );
1929 for (
int i = layerList.size() - 1; i >= 0; --i )
1930 reversedList << layerList[ i ];
1932 QDomElement layerDrawingOrderElem = doc.createElement( QStringLiteral(
"LayerDrawingOrder" ) );
1933 QDomText drawingOrderText = doc.createTextNode( reversedList.join(
',' ) );
1934 layerDrawingOrderElem.appendChild( drawingOrderText );
1935 parentElem.appendChild( layerDrawingOrderElem );
1939 void appendLayerProjectSettings( QDomDocument &doc, QDomElement &layerElem,
QgsMapLayer *currentLayer )
1941 if ( !currentLayer )
1947 QDomElement treeNameElem = doc.createElement( QStringLiteral(
"TreeName" ) );
1948 QDomText treeNameText = doc.createTextNode( currentLayer->
name() );
1949 treeNameElem.appendChild( treeNameText );
1950 layerElem.appendChild( treeNameElem );
1952 switch ( currentLayer->
type() )
1958 int displayFieldIdx = -1;
1959 QString displayField = QStringLiteral(
"maptip" );
1961 if ( exp.isField() )
1968 QDomElement attributesElem = doc.createElement( QStringLiteral(
"Attributes" ) );
1970 for (
int idx = 0; idx < layerFields.
count(); ++idx )
1978 if ( idx == displayFieldIdx )
1982 QDomElement attributeElem = doc.createElement( QStringLiteral(
"Attribute" ) );
1983 attributeElem.setAttribute( QStringLiteral(
"name" ),
field.
name() );
1984 attributeElem.setAttribute( QStringLiteral(
"type" ), QVariant::typeToName(
field.
type() ) );
1985 attributeElem.setAttribute( QStringLiteral(
"typeName" ),
field.
typeName() );
1987 if ( !alias.isEmpty() )
1989 attributeElem.setAttribute( QStringLiteral(
"alias" ), alias );
1993 attributeElem.setAttribute( QStringLiteral(
"editType" ), vLayer->
editorWidgetSetup( idx ).
type() );
1994 attributeElem.setAttribute( QStringLiteral(
"comment" ),
field.
comment() );
1995 attributeElem.setAttribute( QStringLiteral(
"length" ),
field.
length() );
1996 attributeElem.setAttribute( QStringLiteral(
"precision" ),
field.
precision() );
1997 attributesElem.appendChild( attributeElem );
2001 layerElem.setAttribute( QStringLiteral(
"displayField" ), displayField );
2005 if ( pkAttributes.size() > 0 )
2007 QDomElement pkElem = doc.createElement( QStringLiteral(
"PrimaryKey" ) );
2008 QgsAttributeList::const_iterator pkIt = pkAttributes.constBegin();
2009 for ( ; pkIt != pkAttributes.constEnd(); ++pkIt )
2011 QDomElement pkAttributeElem = doc.createElement( QStringLiteral(
"PrimaryKeyAttribute" ) );
2012 QDomText pkAttName = doc.createTextNode( layerFields.
at( *pkIt ).
name() );
2013 pkAttributeElem.appendChild( pkAttName );
2014 pkElem.appendChild( pkAttributeElem );
2016 layerElem.appendChild( pkElem );
2023 layerElem.setAttribute( QStringLiteral(
"opacity" ), QString::number( vLayer->
opacity() ) );
2025 layerElem.appendChild( attributesElem );
2032 if ( provider && provider->
name() ==
"wms" )
2035 QVariant wmsBackgroundLayer = currentLayer->
customProperty( QStringLiteral(
"WMSBackgroundLayer" ), false );
2036 QDomElement wmsBackgroundLayerElem = doc.createElement(
"WMSBackgroundLayer" );
2037 QDomText wmsBackgroundLayerText = doc.createTextNode( wmsBackgroundLayer.toBool() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
2038 wmsBackgroundLayerElem.appendChild( wmsBackgroundLayerText );
2039 layerElem.appendChild( wmsBackgroundLayerElem );
2042 QVariant wmsPublishDataSourceUrl = currentLayer->
customProperty( QStringLiteral(
"WMSPublishDataSourceUrl" ),
false );
2043 if ( wmsPublishDataSourceUrl.toBool() )
2045 bool tiled = qobject_cast< const QgsRasterDataProvider * >( provider )
2046 ? !qobject_cast< const QgsRasterDataProvider * >( provider )->nativeResolutions().isEmpty()
2049 QDomElement dataSourceElem = doc.createElement( tiled ? QStringLiteral(
"WMTSDataSource" ) : QStringLiteral(
"WMSDataSource" ) );
2050 QDomText dataSourceUri = doc.createTextNode( provider->
dataSourceUri() );
2051 dataSourceElem.appendChild( dataSourceUri );
2052 layerElem.appendChild( dataSourceElem );
2056 QVariant wmsPrintLayer = currentLayer->
customProperty( QStringLiteral(
"WMSPrintLayer" ) );
2057 if ( wmsPrintLayer.isValid() )
2059 QDomElement wmsPrintLayerElem = doc.createElement(
"WMSPrintLayer" );
2060 QDomText wmsPrintLayerText = doc.createTextNode( wmsPrintLayer.toString() );
2061 wmsPrintLayerElem.appendChild( wmsPrintLayerText );
2062 layerElem.appendChild( wmsPrintLayerElem );
2068 if ( rasterRenderer )
2070 layerElem.setAttribute( QStringLiteral(
"opacity" ), QString::number( rasterRenderer->
opacity() ) );
2085 void addKeywordListElement(
const QgsProject *project, QDomDocument &doc, QDomElement &parent )
2089 QDomElement keywordsElem = doc.createElement( QStringLiteral(
"KeywordList" ) );
2091 QDomElement keywordElem = doc.createElement( QStringLiteral(
"Keyword" ) );
2092 keywordElem.setAttribute( QStringLiteral(
"vocabulary" ), QStringLiteral(
"ISO" ) );
2093 QDomText keywordText = doc.createTextNode( QStringLiteral(
"infoMapAccessService" ) );
2094 keywordElem.appendChild( keywordText );
2095 keywordsElem.appendChild( keywordElem );
2096 parent.appendChild( keywordsElem );
2098 for (
const QString &keyword : std::as_const( keywords ) )
2100 if ( !keyword.isEmpty() )
2102 keywordElem = doc.createElement( QStringLiteral(
"Keyword" ) );
2103 keywordText = doc.createTextNode( keyword );
2104 keywordElem.appendChild( keywordText );
2107 keywordElem.setAttribute( QStringLiteral(
"vocabulary" ), QStringLiteral(
"SIA_Geo405" ) );
2109 keywordsElem.appendChild( keywordElem );
2112 parent.appendChild( keywordsElem );
2120 for (
int j = 0; j < childNode->
children().size(); ++j )
2130 const auto l { treeLayer->
layer() };
2137 QgsMessageLog::logMessage( QStringLiteral(
"Broken/corrupted layer tree, layer '%1' does not exist: check your project!" ).arg( treeLayer->
name() ), QStringLiteral(
"Server" ), Qgis::MessageLevel::Warning );