48    void appendLayerProjectSettings( QDomDocument &doc, QDomElement &layerElem, 
QgsMapLayer *currentLayer );
 
   52    void appendLayerWgs84BoundingRect( QDomDocument &doc, QDomElement &layerElement, 
const QgsRectangle &wgs84BoundingRect );
 
   54    void appendLayerCrsExtents( QDomDocument &doc, QDomElement &layerElement, 
const QMap<QString, QgsRectangle> &crsExtents );
 
   56    void appendCrsElementToLayer( QDomDocument &doc, QDomElement &layerElement, 
const QDomElement &precedingElement, 
const QString &crsText );
 
   58    void appendCrsElementsToLayer( QDomDocument &doc, QDomElement &layerElement, 
const QStringList &crsList, 
const QStringList &constrainedCrsList );
 
   62    void appendLayersFromTreeGroup( QDomDocument &doc, QDomElement &parentLayer, 
QgsServerInterface *serverIface, 
const QgsProject *project, 
const QgsWmsRequest &request, 
const QgsLayerTreeGroup *layerTreeGroup, 
const QMap<QString, QgsWmsLayerInfos> &wmsLayerInfos, 
bool projectSettings, QList<QgsDateTimeRange> &parentDateRanges );
 
   64    void addKeywordListElement( 
const QgsProject *project, QDomDocument &doc, QDomElement &parent );
 
   69#ifdef HAVE_SERVER_PYTHON_PLUGINS 
   74    const QDomDocument *capabilitiesDocument = 
nullptr;
 
   79    QStringList cacheKeyList;
 
   80    cacheKeyList << ( projectSettings ? QStringLiteral( 
"projectSettings" ) : request.
wmsParameters().
version() );
 
   84#ifdef HAVE_SERVER_PYTHON_PLUGINS 
   88    QString cacheKey = cacheKeyList.join( 
'-' );
 
   90#ifdef HAVE_SERVER_PYTHON_PLUGINS 
   92    if ( cacheManager && cacheManager->
getCachedDocument( &doc, project, request, accessControl ) )
 
   94      capabilitiesDocument = &doc;
 
   97    if ( !capabilitiesDocument && cache ) 
 
  102    if ( !capabilitiesDocument ) 
 
  104      QgsMessageLog::logMessage( QStringLiteral( 
"WMS capabilities document not found in cache" ), QStringLiteral( 
"Server" ) );
 
  106      doc = 
getCapabilities( serverIface, project, request, projectSettings );
 
  108#ifdef HAVE_SERVER_PYTHON_PLUGINS 
  109      if ( cacheManager && cacheManager->
setCachedDocument( &doc, project, request, accessControl ) )
 
  111        capabilitiesDocument = &doc;
 
  116      if ( !capabilitiesDocument )
 
  121      if ( !capabilitiesDocument )
 
  123        capabilitiesDocument = &doc;
 
  135    response.
setHeader( QStringLiteral( 
"Content-Type" ), QStringLiteral( 
"text/xml; charset=utf-8" ) );
 
  136    response.
write( capabilitiesDocument->toByteArray() );
 
 
  142    QDomElement wmsCapabilitiesElement;
 
  148    QString hrefString = href.toString();
 
  149    hrefString.append( href.hasQuery() ? 
"&" : 
"?" );
 
  152    QDomProcessingInstruction xmlDeclaration = doc.createProcessingInstruction( QStringLiteral( 
"xml" ), QStringLiteral( 
"version=\"1.0\" encoding=\"utf-8\"" ) );
 
  155    std::function<void( QDomElement &, 
const QString & )> appendFormat = [&doc]( QDomElement &elem, 
const QString &format ) {
 
  156      QDomElement formatElem = doc.createElement( QStringLiteral( 
"Format" )  );
 
  157      formatElem.appendChild( doc.createTextNode( format ) );
 
  158      elem.appendChild( formatElem );
 
  163      doc = QDomDocument( QStringLiteral( 
"WMT_MS_Capabilities SYSTEM 'http://schemas.opengis.net/wms/1.1.1/WMS_MS_Capabilities.dtd'" ) ); 
 
  164      doc.appendChild( xmlDeclaration );
 
  165      wmsCapabilitiesElement = doc.createElement( QStringLiteral( 
"WMT_MS_Capabilities" )  );
 
  169      doc.appendChild( xmlDeclaration );
 
  170      wmsCapabilitiesElement = doc.createElement( QStringLiteral( 
"WMS_Capabilities" )  );
 
  171      wmsCapabilitiesElement.setAttribute( QStringLiteral( 
"xmlns" ), QStringLiteral( 
"http://www.opengis.net/wms" ) );
 
  172      wmsCapabilitiesElement.setAttribute( QStringLiteral( 
"xmlns:sld" ), QStringLiteral( 
"http://www.opengis.net/sld" ) );
 
  173      wmsCapabilitiesElement.setAttribute( QStringLiteral( 
"xmlns:qgs" ), QStringLiteral( 
"http://www.qgis.org/wms" ) );
 
  174      wmsCapabilitiesElement.setAttribute( QStringLiteral( 
"xmlns:xsi" ), QStringLiteral( 
"http://www.w3.org/2001/XMLSchema-instance" ) );
 
  175      QString schemaLocation = QStringLiteral( 
"http://www.opengis.net/wms" );
 
  176      schemaLocation += QLatin1String( 
" http://schemas.opengis.net/wms/1.3.0/capabilities_1_3_0.xsd" );
 
  177      schemaLocation += QLatin1String( 
" http://www.opengis.net/sld" );
 
  178      schemaLocation += QLatin1String( 
" http://schemas.opengis.net/sld/1.1.0/sld_capabilities.xsd" );
 
  182        wmsCapabilitiesElement.setAttribute( QStringLiteral( 
"xmlns:inspire_common" ), QStringLiteral( 
"http://inspire.ec.europa.eu/schemas/common/1.0" ) );
 
  183        wmsCapabilitiesElement.setAttribute( QStringLiteral( 
"xmlns:inspire_vs" ), QStringLiteral( 
"http://inspire.ec.europa.eu/schemas/inspire_vs/1.0" ) );
 
  184        schemaLocation += QLatin1String( 
" http://inspire.ec.europa.eu/schemas/inspire_vs/1.0" );
 
  185        schemaLocation += QLatin1String( 
" http://inspire.ec.europa.eu/schemas/inspire_vs/1.0/inspire_vs.xsd" );
 
  188      schemaLocation += QLatin1String( 
" http://www.qgis.org/wms" );
 
  189      schemaLocation += 
" " + hrefString + 
"SERVICE=WMS&REQUEST=GetSchemaExtension";
 
  191      wmsCapabilitiesElement.setAttribute( QStringLiteral( 
"xsi:schemaLocation" ), schemaLocation );
 
  193    wmsCapabilitiesElement.setAttribute( QStringLiteral( 
"version" ), request.
wmsParameters().
version() );
 
  194    doc.appendChild( wmsCapabilitiesElement );
 
  200    QDomElement capabilityElement = 
getCapabilityElement( doc, project, request, projectSettings, serverIface );
 
  201    wmsCapabilitiesElement.appendChild( capabilityElement );
 
  203    if ( projectSettings )
 
  212    capabilityElement.appendChild(
 
  216    if ( projectSettings )
 
  218      appendDrawingOrder( doc, capabilityElement, serverIface, project );
 
 
  227    QDomElement serviceElem = doc.createElement( QStringLiteral( 
"Service" ) );
 
  230    QDomElement nameElem = doc.createElement( QStringLiteral( 
"Name" ) );
 
  231    QDomText nameText = doc.createTextNode( QStringLiteral( 
"WMS" ) );
 
  232    nameElem.appendChild( nameText );
 
  233    serviceElem.appendChild( nameElem );
 
  236    QDomElement titleElem = doc.createElement( QStringLiteral( 
"Title" ) );
 
  238    titleElem.appendChild( titleText );
 
  239    serviceElem.appendChild( titleElem );
 
  242    if ( !abstract.isEmpty() )
 
  244      QDomElement abstractElem = doc.createElement( QStringLiteral( 
"Abstract" ) );
 
  245      QDomText abstractText = doc.createCDATASection( abstract );
 
  246      abstractElem.appendChild( abstractText );
 
  247      serviceElem.appendChild( abstractElem );
 
  250    addKeywordListElement( project, doc, serviceElem );
 
  253    if ( onlineResource.isEmpty() )
 
  255      onlineResource = 
serviceUrl( request, project, *serverSettings ).toString();
 
  257    QDomElement onlineResourceElem = doc.createElement( QStringLiteral( 
"OnlineResource" ) );
 
  258    onlineResourceElem.setAttribute( QStringLiteral( 
"xmlns:xlink" ), QStringLiteral( 
"http://www.w3.org/1999/xlink" ) );
 
  259    onlineResourceElem.setAttribute( QStringLiteral( 
"xlink:type" ), QStringLiteral( 
"simple" ) );
 
  260    onlineResourceElem.setAttribute( QStringLiteral( 
"xlink:href" ), onlineResource );
 
  261    serviceElem.appendChild( onlineResourceElem );
 
  268    if ( !contactPerson.isEmpty() || !contactOrganization.isEmpty() || !contactPosition.isEmpty() || !contactMail.isEmpty() || !contactPhone.isEmpty() )
 
  271      QDomElement contactInfoElem = doc.createElement( QStringLiteral( 
"ContactInformation" ) );
 
  274      if ( !contactPerson.isEmpty() || !contactOrganization.isEmpty() )
 
  276        QDomElement contactPersonPrimaryElem = doc.createElement( QStringLiteral( 
"ContactPersonPrimary" ) );
 
  278        QDomText contactPersonText;
 
  279        if ( !contactPerson.isEmpty() )
 
  281          contactPersonText = doc.createTextNode( contactPerson );
 
  285          contactPersonText = doc.createTextNode( QStringLiteral( 
"unknown" ) );
 
  287        QDomElement contactPersonElem = doc.createElement( QStringLiteral( 
"ContactPerson" ) );
 
  288        contactPersonElem.appendChild( contactPersonText );
 
  289        contactPersonPrimaryElem.appendChild( contactPersonElem );
 
  291        QDomText contactOrganizationText;
 
  292        if ( !contactOrganization.isEmpty() )
 
  294          contactOrganizationText = doc.createTextNode( contactOrganization );
 
  298          contactOrganizationText = doc.createTextNode( QStringLiteral( 
"unknown" ) );
 
  300        QDomElement contactOrganizationElem = doc.createElement( QStringLiteral( 
"ContactOrganization" ) );
 
  301        contactOrganizationElem.appendChild( contactOrganizationText );
 
  302        contactPersonPrimaryElem.appendChild( contactOrganizationElem );
 
  304        contactInfoElem.appendChild( contactPersonPrimaryElem );
 
  307      if ( !contactPosition.isEmpty() )
 
  309        QDomElement contactPositionElem = doc.createElement( QStringLiteral( 
"ContactPosition" ) );
 
  310        QDomText contactPositionText = doc.createTextNode( contactPosition );
 
  311        contactPositionElem.appendChild( contactPositionText );
 
  312        contactInfoElem.appendChild( contactPositionElem );
 
  315      if ( !contactPhone.isEmpty() )
 
  317        QDomElement phoneElem = doc.createElement( QStringLiteral( 
"ContactVoiceTelephone" ) );
 
  318        QDomText phoneText = doc.createTextNode( contactPhone );
 
  319        phoneElem.appendChild( phoneText );
 
  320        contactInfoElem.appendChild( phoneElem );
 
  323      if ( !contactMail.isEmpty() )
 
  325        QDomElement mailElem = doc.createElement( QStringLiteral( 
"ContactElectronicMailAddress" ) );
 
  326        QDomText mailText = doc.createTextNode( contactMail );
 
  327        mailElem.appendChild( mailText );
 
  328        contactInfoElem.appendChild( mailElem );
 
  331      serviceElem.appendChild( contactInfoElem );
 
  334    QDomElement feesElem = doc.createElement( QStringLiteral( 
"Fees" ) );
 
  335    QDomText feesText = doc.createTextNode( QStringLiteral( 
"None" ) ); 
 
  337    if ( !fees.isEmpty() )
 
  339      feesText = doc.createTextNode( fees );
 
  341    feesElem.appendChild( feesText );
 
  342    serviceElem.appendChild( feesElem );
 
  344    QDomElement accessConstraintsElem = doc.createElement( QStringLiteral( 
"AccessConstraints" ) );
 
  345    QDomText accessConstraintsText = doc.createTextNode( QStringLiteral( 
"None" ) ); 
 
  347    if ( !accessConstraints.isEmpty() )
 
  349      accessConstraintsText = doc.createTextNode( accessConstraints );
 
  351    accessConstraintsElem.appendChild( accessConstraintsText );
 
  352    serviceElem.appendChild( accessConstraintsElem );
 
  359        QDomElement maxWidthElem = doc.createElement( QStringLiteral( 
"MaxWidth" ) );
 
  360        QDomText maxWidthText = doc.createTextNode( QString::number( maxWidth ) );
 
  361        maxWidthElem.appendChild( maxWidthText );
 
  362        serviceElem.appendChild( maxWidthElem );
 
  368        QDomElement maxHeightElem = doc.createElement( QStringLiteral( 
"MaxHeight" ) );
 
  369        QDomText maxHeightText = doc.createTextNode( QString::number( maxHeight ) );
 
  370        maxHeightElem.appendChild( maxHeightText );
 
  371        serviceElem.appendChild( maxHeightElem );
 
 
  386    QString hrefString = href.toString();
 
  387    hrefString.append( href.hasQuery() ? 
"&" : 
"?" );
 
  389    QDomElement capabilityElem = doc.createElement( QStringLiteral( 
"Capability" )  );
 
  392    QDomElement requestElem = doc.createElement( QStringLiteral( 
"Request" )  );
 
  393    capabilityElem.appendChild( requestElem );
 
  395    QDomElement dcpTypeElem = doc.createElement( QStringLiteral( 
"DCPType" )  );
 
  396    QDomElement httpElem = doc.createElement( QStringLiteral( 
"HTTP" )  );
 
  397    dcpTypeElem.appendChild( httpElem );
 
  400    std::function<void( QDomElement &, 
const QString & )> appendFormat = [&doc]( QDomElement &elem, 
const QString &format ) {
 
  401      QDomElement formatElem = doc.createElement( QStringLiteral( 
"Format" )  );
 
  402      formatElem.appendChild( doc.createTextNode( format ) );
 
  403      elem.appendChild( formatElem );
 
  409    elem = doc.createElement( QStringLiteral( 
"GetCapabilities" )  );
 
  410    appendFormat( elem, ( version == QLatin1String( 
"1.1.1" ) ? 
"application/vnd.ogc.wms_xml" : 
"text/xml" ) );
 
  411    elem.appendChild( dcpTypeElem );
 
  412    requestElem.appendChild( elem );
 
  415    QDomElement getElem = doc.createElement( QStringLiteral( 
"Get" )  );
 
  416    httpElem.appendChild( getElem );
 
  417    QDomElement olResourceElem = doc.createElement( QStringLiteral( 
"OnlineResource" )  );
 
  418    olResourceElem.setAttribute( QStringLiteral( 
"xmlns:xlink" ), QStringLiteral( 
"http://www.w3.org/1999/xlink" ) );
 
  419    olResourceElem.setAttribute( QStringLiteral( 
"xlink:type" ), QStringLiteral( 
"simple" ) );
 
  420    olResourceElem.setAttribute( QStringLiteral( 
"xlink:href" ), hrefString );
 
  421    getElem.appendChild( olResourceElem );
 
  424    elem = doc.createElement( QStringLiteral( 
"GetMap" )  );
 
  425    appendFormat( elem, QStringLiteral( 
"image/jpeg" ) );
 
  426    appendFormat( elem, QStringLiteral( 
"image/png" ) );
 
  427    appendFormat( elem, QStringLiteral( 
"image/png; mode=16bit" ) );
 
  428    appendFormat( elem, QStringLiteral( 
"image/png; mode=8bit" ) );
 
  429    appendFormat( elem, QStringLiteral( 
"image/png; mode=1bit" ) );
 
  430    appendFormat( elem, QStringLiteral( 
"application/dxf" ) );
 
  431    appendFormat( elem, QStringLiteral( 
"application/pdf" ) );
 
  432    elem.appendChild( dcpTypeElem.cloneNode().toElement() ); 
 
  433    requestElem.appendChild( elem );
 
  436    elem = doc.createElement( QStringLiteral( 
"GetFeatureInfo" ) );
 
  437    appendFormat( elem, QStringLiteral( 
"text/plain" ) );
 
  438    appendFormat( elem, QStringLiteral( 
"text/html" ) );
 
  439    appendFormat( elem, QStringLiteral( 
"text/xml" ) );
 
  440    appendFormat( elem, QStringLiteral( 
"application/vnd.ogc.gml" ) );
 
  441    appendFormat( elem, QStringLiteral( 
"application/vnd.ogc.gml/3.1.1" ) );
 
  442    appendFormat( elem, QStringLiteral( 
"application/json" ) );
 
  443    appendFormat( elem, QStringLiteral( 
"application/geo+json" ) );
 
  444    elem.appendChild( dcpTypeElem.cloneNode().toElement() ); 
 
  445    requestElem.appendChild( elem );
 
  448    elem = doc.createElement( ( version == QLatin1String( 
"1.1.1" ) ? 
"GetLegendGraphic" : 
"sld:GetLegendGraphic" )  );
 
  449    appendFormat( elem, QStringLiteral( 
"image/jpeg" ) );
 
  450    appendFormat( elem, QStringLiteral( 
"image/png" ) );
 
  451    appendFormat( elem, QStringLiteral( 
"application/json" ) );
 
  452    elem.appendChild( dcpTypeElem.cloneNode().toElement() ); 
 
  453    requestElem.appendChild( elem );
 
  456    elem = doc.createElement( ( version == QLatin1String( 
"1.1.1" ) ? 
"DescribeLayer" : 
"sld:DescribeLayer" )  );
 
  457    appendFormat( elem, QStringLiteral( 
"text/xml" ) );
 
  458    elem.appendChild( dcpTypeElem.cloneNode().toElement() ); 
 
  459    requestElem.appendChild( elem );
 
  462    elem = doc.createElement( ( version == QLatin1String( 
"1.1.1" ) ? 
"GetStyles" : 
"qgs:GetStyles" )  );
 
  463    appendFormat( elem, QStringLiteral( 
"text/xml" ) );
 
  464    elem.appendChild( dcpTypeElem.cloneNode().toElement() ); 
 
  465    requestElem.appendChild( elem );
 
  470      elem = doc.createElement( QStringLiteral( 
"GetPrint" )  );
 
  471      appendFormat( elem, QStringLiteral( 
"svg" ) );
 
  472      appendFormat( elem, QStringLiteral( 
"png" ) );
 
  473      appendFormat( elem, QStringLiteral( 
"pdf" ) );
 
  474      elem.appendChild( dcpTypeElem.cloneNode().toElement() ); 
 
  475      requestElem.appendChild( elem );
 
  479    elem = doc.createElement( QStringLiteral( 
"Exception" ) );
 
  480    appendFormat( elem, ( version == QLatin1String( 
"1.1.1" ) ? 
"application/vnd.ogc.se_xml" : 
"XML" ) );
 
  481    capabilityElem.appendChild( elem );
 
  484    if ( version == QLatin1String( 
"1.3.0" ) )
 
  486      elem = doc.createElement( QStringLiteral( 
"sld:UserDefinedSymbolization" ) );
 
  487      elem.setAttribute( QStringLiteral( 
"SupportSLD" ), QStringLiteral( 
"1" ) );
 
  488      elem.setAttribute( QStringLiteral( 
"UserLayer" ), QStringLiteral( 
"0" ) );
 
  489      elem.setAttribute( QStringLiteral( 
"UserStyle" ), QStringLiteral( 
"1" ) );
 
  490      elem.setAttribute( QStringLiteral( 
"RemoteWFS" ), QStringLiteral( 
"0" ) );
 
  491      elem.setAttribute( QStringLiteral( 
"InlineFeature" ), QStringLiteral( 
"0" ) );
 
  492      elem.setAttribute( QStringLiteral( 
"RemoteWCS" ), QStringLiteral( 
"0" ) );
 
  493      capabilityElem.appendChild( elem );
 
  501    return capabilityElem;
 
 
  506    QDomElement inspireCapabilitiesElem;
 
  509      return inspireCapabilitiesElem;
 
  511    inspireCapabilitiesElem = doc.createElement( QStringLiteral( 
"inspire_vs:ExtendedCapabilities" ) );
 
  515    if ( !inspireMetadataUrl.isEmpty() )
 
  517      QDomElement inspireCommonMetadataUrlElem = doc.createElement( QStringLiteral( 
"inspire_common:MetadataUrl" ) );
 
  518      inspireCommonMetadataUrlElem.setAttribute( QStringLiteral( 
"xsi:type" ), QStringLiteral( 
"inspire_common:resourceLocatorType" ) );
 
  520      QDomElement inspireCommonMetadataUrlUrlElem = doc.createElement( QStringLiteral( 
"inspire_common:URL" ) );
 
  521      inspireCommonMetadataUrlUrlElem.appendChild( doc.createTextNode( inspireMetadataUrl ) );
 
  522      inspireCommonMetadataUrlElem.appendChild( inspireCommonMetadataUrlUrlElem );
 
  525      if ( !inspireMetadataUrlType.isNull() )
 
  527        QDomElement inspireCommonMetadataUrlMediaTypeElem = doc.createElement( QStringLiteral( 
"inspire_common:MediaType" ) );
 
  528        inspireCommonMetadataUrlMediaTypeElem.appendChild( doc.createTextNode( inspireMetadataUrlType ) );
 
  529        inspireCommonMetadataUrlElem.appendChild( inspireCommonMetadataUrlMediaTypeElem );
 
  532      inspireCapabilitiesElem.appendChild( inspireCommonMetadataUrlElem );
 
  536      QDomElement inspireCommonResourceTypeElem = doc.createElement( QStringLiteral( 
"inspire_common:ResourceType" ) );
 
  537      inspireCommonResourceTypeElem.appendChild( doc.createTextNode( QStringLiteral( 
"service" ) ) );
 
  538      inspireCapabilitiesElem.appendChild( inspireCommonResourceTypeElem );
 
  540      QDomElement inspireCommonSpatialDataServiceTypeElem = doc.createElement( QStringLiteral( 
"inspire_common:SpatialDataServiceType" ) );
 
  541      inspireCommonSpatialDataServiceTypeElem.appendChild( doc.createTextNode( QStringLiteral( 
"view" ) ) );
 
  542      inspireCapabilitiesElem.appendChild( inspireCommonSpatialDataServiceTypeElem );
 
  545      if ( !inspireTemporalReference.isNull() )
 
  547        QDomElement inspireCommonTemporalReferenceElem = doc.createElement( QStringLiteral( 
"inspire_common:TemporalReference" ) );
 
  548        QDomElement inspireCommonDateOfLastRevisionElem = doc.createElement( QStringLiteral( 
"inspire_common:DateOfLastRevision" ) );
 
  549        inspireCommonDateOfLastRevisionElem.appendChild( doc.createTextNode( inspireTemporalReference ) );
 
  550        inspireCommonTemporalReferenceElem.appendChild( inspireCommonDateOfLastRevisionElem );
 
  551        inspireCapabilitiesElem.appendChild( inspireCommonTemporalReferenceElem );
 
  554      QDomElement inspireCommonMetadataPointOfContactElem = doc.createElement( QStringLiteral( 
"inspire_common:MetadataPointOfContact" ) );
 
  557      QDomElement inspireCommonOrganisationNameElem = doc.createElement( QStringLiteral( 
"inspire_common:OrganisationName" ) );
 
  558      if ( !contactOrganization.isNull() )
 
  560        inspireCommonOrganisationNameElem.appendChild( doc.createTextNode( contactOrganization ) );
 
  562      inspireCommonMetadataPointOfContactElem.appendChild( inspireCommonOrganisationNameElem );
 
  565      QDomElement inspireCommonEmailAddressElem = doc.createElement( QStringLiteral( 
"inspire_common:EmailAddress" ) );
 
  566      if ( !contactMail.isNull() )
 
  568        inspireCommonEmailAddressElem.appendChild( doc.createTextNode( contactMail ) );
 
  570      inspireCommonMetadataPointOfContactElem.appendChild( inspireCommonEmailAddressElem );
 
  572      inspireCapabilitiesElem.appendChild( inspireCommonMetadataPointOfContactElem );
 
  575      if ( !inspireMetadataDate.isNull() )
 
  577        QDomElement inspireCommonMetadataDateElem = doc.createElement( QStringLiteral( 
"inspire_common:MetadataDate" ) );
 
  578        inspireCommonMetadataDateElem.appendChild( doc.createTextNode( inspireMetadataDate ) );
 
  579        inspireCapabilitiesElem.appendChild( inspireCommonMetadataDateElem );
 
  584    QDomElement inspireCommonSupportedLanguagesElem = doc.createElement( QStringLiteral( 
"inspire_common:SupportedLanguages" ) );
 
  585    inspireCommonSupportedLanguagesElem.setAttribute( QStringLiteral( 
"xsi:type" ), QStringLiteral( 
"inspire_common:supportedLanguagesType" ) );
 
  587    QDomElement inspireCommonLanguageElem = doc.createElement( QStringLiteral( 
"inspire_common:Language" ) );
 
  590    QDomElement inspireCommonDefaultLanguageElem = doc.createElement( QStringLiteral( 
"inspire_common:DefaultLanguage" ) );
 
  591    inspireCommonDefaultLanguageElem.appendChild( inspireCommonLanguageElem );
 
  592    inspireCommonSupportedLanguagesElem.appendChild( inspireCommonDefaultLanguageElem );
 
  596    QDomElement inspireCommonSupportedLanguageElem = doc.createElement( 
"inspire_common:SupportedLanguage" );
 
  597    inspireCommonSupportedLanguageElem.appendChild( inspireCommonLanguageElem.cloneNode().toElement() );
 
  598    inspireCommonSupportedLanguagesElem.appendChild( inspireCommonSupportedLanguageElem );
 
  601    inspireCapabilitiesElem.appendChild( inspireCommonSupportedLanguagesElem );
 
  603    QDomElement inspireCommonResponseLanguageElem = doc.createElement( QStringLiteral( 
"inspire_common:ResponseLanguage" ) );
 
  604    inspireCommonResponseLanguageElem.appendChild( inspireCommonLanguageElem.cloneNode().toElement() );
 
  605    inspireCapabilitiesElem.appendChild( inspireCommonResponseLanguageElem );
 
  607    return inspireCapabilitiesElem;
 
 
  613    if ( projectComposers.size() == 0 )
 
  614      return QDomElement();
 
  618    QDomElement composerTemplatesElem = doc.createElement( QStringLiteral( 
"ComposerTemplates" ) );
 
  619    QList<QgsPrintLayout *>::const_iterator cIt = projectComposers.constBegin();
 
  620    for ( ; cIt != projectComposers.constEnd(); ++cIt )
 
  623      if ( restrictedComposers.contains( layout->
name() ) )
 
  635      QDomElement composerTemplateElem = doc.createElement( QStringLiteral( 
"ComposerTemplate" ) );
 
  636      composerTemplateElem.setAttribute( QStringLiteral( 
"name" ), layout->
name() );
 
  639      composerTemplateElem.setAttribute( QStringLiteral( 
"width" ), width.
length() );
 
  640      composerTemplateElem.setAttribute( QStringLiteral( 
"height" ), height.
length() );
 
  644      if ( atlas && atlas->
enabled() )
 
  646        composerTemplateElem.setAttribute( QStringLiteral( 
"atlasEnabled" ), QStringLiteral( 
"1" ) );
 
  653            layerName = cLayer->
id();
 
  655          else if ( layerName.isEmpty() )
 
  657            layerName = cLayer->
name();
 
  659          composerTemplateElem.setAttribute( QStringLiteral( 
"atlasCoverageLayer" ), layerName );
 
  664      QList<QgsLayoutItemMap *> layoutMapList;
 
  666      QList<QgsLayoutItemMap *>::const_iterator cmIt = layoutMapList.constBegin();
 
  669      for ( ; cmIt != layoutMapList.constEnd(); ++cmIt )
 
  673        QDomElement composerMapElem = doc.createElement( QStringLiteral( 
"ComposerMap" ) );
 
  674        composerMapElem.setAttribute( QStringLiteral( 
"name" ), QStringLiteral( 
"map%1" ).arg( mapId ) );
 
  675        composerMapElem.setAttribute( QStringLiteral( 
"itemName" ), composerMap->
displayName() );
 
  677        composerMapElem.setAttribute( QStringLiteral( 
"width" ), composerMap->rect().width() );
 
  678        composerMapElem.setAttribute( QStringLiteral( 
"height" ), composerMap->rect().height() );
 
  679        composerTemplateElem.appendChild( composerMapElem );
 
  683      QList<QgsLayoutItemLabel *> composerLabelList;
 
  685      QList<QgsLayoutItemLabel *>::const_iterator clIt = composerLabelList.constBegin();
 
  686      for ( ; clIt != composerLabelList.constEnd(); ++clIt )
 
  689        QString 
id = composerLabel->
id();
 
  693        QDomElement composerLabelElem = doc.createElement( QStringLiteral( 
"ComposerLabel" ) );
 
  694        composerLabelElem.setAttribute( QStringLiteral( 
"name" ), id );
 
  695        composerTemplateElem.appendChild( composerLabelElem );
 
  699      QList<QgsLayoutItemHtml *> composerHtmlList;
 
  701      QList<QgsLayoutItemHtml *>::const_iterator chIt = composerHtmlList.constBegin();
 
  702      for ( ; chIt != composerHtmlList.constEnd(); ++chIt )
 
  708        QString 
id = composerHtml->
frame( 0 )->
id();
 
  712        QDomElement composerHtmlElem = doc.createElement( QStringLiteral( 
"ComposerHtml" ) );
 
  713        composerHtmlElem.setAttribute( QStringLiteral( 
"name" ), id );
 
  714        composerTemplateElem.appendChild( composerHtmlElem );
 
  717      composerTemplatesElem.appendChild( composerTemplateElem );
 
  720    if ( composerTemplatesElem.childNodes().size() == 0 )
 
  721      return QDomElement();
 
  723    return composerTemplatesElem;
 
 
  729    if ( wfsLayerIds.size() == 0 )
 
  730      return QDomElement();
 
  732    QDomElement wfsLayersElem = doc.createElement( QStringLiteral( 
"WFSLayers" ) );
 
  733    for ( 
int i = 0; i < wfsLayerIds.size(); ++i )
 
  741      QDomElement wfsLayerElem = doc.createElement( QStringLiteral( 
"WFSLayer" ) );
 
  744        wfsLayerElem.setAttribute( QStringLiteral( 
"name" ), layer->
id() );
 
  748        wfsLayerElem.setAttribute( QStringLiteral( 
"name" ), layer->
name() );
 
  750      wfsLayersElem.appendChild( wfsLayerElem );
 
  753    return wfsLayersElem;
 
 
  760    parentLayer.setAttribute(
 
  761      QStringLiteral( 
"queryable" ),
 
  762      hasQueryableLayers( layerIds, wmsLayerInfos ) ? QStringLiteral( 
"1" ) : QStringLiteral( 
"0" )
 
  766    QMap<QString, QgsRectangle> crsExtents = 
combineCrsExtents( layerIds, wmsLayerInfos );
 
  768    appendCrsElementsToLayer( doc, parentLayer, crsExtents.keys(), QStringList() );
 
  769    appendLayerWgs84BoundingRect( doc, parentLayer, wgs84BoundingRect );
 
  770    appendLayerCrsExtents( doc, parentLayer, crsExtents );
 
  772    appendLayersFromTreeGroup( doc, parentLayer, serverIface, project, request, layerTreeGroup, wmsLayerInfos, projectSettings, parentDateRanges );
 
 
  779    QDomElement layerParentElem = doc.createElement( QStringLiteral( 
"Layer" ) );
 
  783    if ( rootLayerName.isEmpty() && !project->
title().isEmpty() )
 
  785      rootLayerName = project->
title();
 
  788    if ( !rootLayerName.isEmpty() )
 
  790      QDomElement layerParentNameElem = doc.createElement( QStringLiteral( 
"Name" ) );
 
  791      QDomText layerParentNameText = doc.createTextNode( rootLayerName );
 
  792      layerParentNameElem.appendChild( layerParentNameText );
 
  793      layerParentElem.appendChild( layerParentNameElem );
 
  797    QDomElement layerParentTitleElem = doc.createElement( QStringLiteral( 
"Title" ) );
 
  799    layerParentTitleElem.appendChild( layerParentTitleText );
 
  800    layerParentElem.appendChild( layerParentTitleElem );
 
  804    if ( !rootLayerAbstract.isEmpty() )
 
  806      QDomElement layerParentAbstElem = doc.createElement( QStringLiteral( 
"Abstract" ) );
 
  807      QDomText layerParentAbstText = doc.createCDATASection( rootLayerAbstract );
 
  808      layerParentAbstElem.appendChild( layerParentAbstText );
 
  809      layerParentElem.appendChild( layerParentAbstElem );
 
  813    addKeywordListElement( project, doc, layerParentElem );
 
  816    if ( projectSettings )
 
  818      QDomElement treeNameElem = doc.createElement( QStringLiteral( 
"TreeName" ) );
 
  819      QDomText treeNameText = doc.createTextNode( project->
title() );
 
  820      treeNameElem.appendChild( treeNameText );
 
  821      layerParentElem.appendChild( treeNameElem );
 
  827    auto outputCrsList = QList<QgsCoordinateReferenceSystem>();
 
  833        outputCrsList.append( 
crs );
 
  857          QStringLiteral( 
"Error transforming extent: %1" ).arg( cse.
what() ),
 
  858          QStringLiteral( 
"Server" ),
 
  864      QMap<QString, QgsRectangle> wmsCrsExtents;
 
  876      layerParentElem.setAttribute(
 
  877        QStringLiteral( 
"queryable" ),
 
  881      appendCrsElementsToLayer( doc, layerParentElem, wmsCrsExtents.keys(), QStringList() );
 
  882      appendLayerWgs84BoundingRect( doc, layerParentElem, wmsWgs84BoundingRect );
 
  883      appendLayerCrsExtents( doc, layerParentElem, wmsCrsExtents );
 
  885      QList<QgsDateTimeRange> parentDateRanges;
 
  886      appendLayersFromTreeGroup( doc, layerParentElem, serverIface, project, request, projectLayerTreeRoot, wmsLayerInfos, projectSettings, parentDateRanges );
 
  890      QList<QgsDateTimeRange> parentDateRanges;
 
  891      handleLayersFromTreeGroup( doc, layerParentElem, serverIface, project, request, projectLayerTreeRoot, wmsLayerInfos, projectSettings, parentDateRanges );
 
  894    return layerParentElem;
 
 
  902    void writeServerProperties( QDomDocument &doc, QDomElement &layerElem, 
const QgsProject *project, 
const QgsMapLayerServerProperties *serverProperties, 
const QString &name, 
const QString &version )
 
  904      const QString title = serverProperties->
title();
 
  905      QDomElement titleElem = doc.createElement( QStringLiteral( 
"Title" ) );
 
  906      QDomText titleText = doc.createTextNode( !title.isEmpty() ? title : name );
 
  907      titleElem.appendChild( titleText );
 
  908      layerElem.appendChild( titleElem );
 
  910      const QString abstract = serverProperties->
abstract();
 
  911      if ( !abstract.isEmpty() )
 
  913        QDomElement abstractElem = doc.createElement( QStringLiteral( 
"Abstract" ) );
 
  914        QDomText abstractText = doc.createTextNode( abstract );
 
  915        abstractElem.appendChild( abstractText );
 
  916        layerElem.appendChild( abstractElem );
 
  921      const QStringList keywords = !serverProperties->
keywordList().isEmpty() ? serverProperties->
keywordList().split( 
',' ) : QStringList();
 
  922      if ( !keywords.isEmpty() )
 
  924        QDomElement keywordListElem = doc.createElement( QStringLiteral( 
"KeywordList" ) );
 
  925        for ( 
const QString &keyword : std::as_const( keywords ) )
 
  927          QDomElement keywordElem = doc.createElement( QStringLiteral( 
"Keyword" ) );
 
  928          QDomText keywordText = doc.createTextNode( keyword.trimmed() );
 
  929          keywordElem.appendChild( keywordText );
 
  932            keywordElem.setAttribute( QStringLiteral( 
"vocabulary" ), QStringLiteral( 
"SIA_Geo405" ) );
 
  934          keywordListElem.appendChild( keywordElem );
 
  936        layerElem.appendChild( keywordListElem );
 
  940      const QString dataUrl = serverProperties->
dataUrl();
 
  941      if ( !dataUrl.isEmpty() )
 
  943        QDomElement dataUrlElem = doc.createElement( QStringLiteral( 
"DataURL" ) );
 
  944        QDomElement dataUrlFormatElem = doc.createElement( QStringLiteral( 
"Format" ) );
 
  945        const QString dataUrlFormat = serverProperties->
dataUrlFormat();
 
  946        QDomText dataUrlFormatText = doc.createTextNode( dataUrlFormat );
 
  947        dataUrlFormatElem.appendChild( dataUrlFormatText );
 
  948        dataUrlElem.appendChild( dataUrlFormatElem );
 
  949        QDomElement dataORElem = doc.createElement( QStringLiteral( 
"OnlineResource" ) );
 
  950        dataORElem.setAttribute( QStringLiteral( 
"xmlns:xlink" ), QStringLiteral( 
"http://www.w3.org/1999/xlink" ) );
 
  951        dataORElem.setAttribute( QStringLiteral( 
"xlink:type" ), QStringLiteral( 
"simple" ) );
 
  952        dataORElem.setAttribute( QStringLiteral( 
"xlink:href" ), dataUrl );
 
  953        dataUrlElem.appendChild( dataORElem );
 
  954        layerElem.appendChild( dataUrlElem );
 
  958      const QString attribution = serverProperties->
attribution();
 
  959      if ( !attribution.isEmpty() )
 
  961        QDomElement attribElem = doc.createElement( QStringLiteral( 
"Attribution" ) );
 
  962        QDomElement attribTitleElem = doc.createElement( QStringLiteral( 
"Title" ) );
 
  963        QDomText attribText = doc.createTextNode( attribution );
 
  964        attribTitleElem.appendChild( attribText );
 
  965        attribElem.appendChild( attribTitleElem );
 
  966        const QString attributionUrl = serverProperties->
attributionUrl();
 
  967        if ( !attributionUrl.isEmpty() )
 
  969          QDomElement attribORElem = doc.createElement( QStringLiteral( 
"OnlineResource" ) );
 
  970          attribORElem.setAttribute( QStringLiteral( 
"xmlns:xlink" ), QStringLiteral( 
"http://www.w3.org/1999/xlink" ) );
 
  971          attribORElem.setAttribute( QStringLiteral( 
"xlink:type" ), QStringLiteral( 
"simple" ) );
 
  972          attribORElem.setAttribute( QStringLiteral( 
"xlink:href" ), attributionUrl );
 
  973          attribElem.appendChild( attribORElem );
 
  975        layerElem.appendChild( attribElem );
 
  979      const QList<QgsServerMetadataUrlProperties::MetadataUrl> metadataUrls = serverProperties->
metadataUrls();
 
  982        QDomElement metaUrlElem = doc.createElement( QStringLiteral( 
"MetadataURL" ) );
 
  983        const QString metadataUrlType = metadataUrl.type;
 
  984        if ( version == QLatin1String( 
"1.1.1" ) )
 
  986          metaUrlElem.setAttribute( QStringLiteral( 
"type" ), metadataUrlType );
 
  988        else if ( metadataUrlType == QLatin1String( 
"FGDC" ) )
 
  990          metaUrlElem.setAttribute( QStringLiteral( 
"type" ), QStringLiteral( 
"FGDC:1998" ) );
 
  992        else if ( metadataUrlType == QLatin1String( 
"TC211" ) )
 
  994          metaUrlElem.setAttribute( QStringLiteral( 
"type" ), QStringLiteral( 
"ISO19115:2003" ) );
 
  998          metaUrlElem.setAttribute( QStringLiteral( 
"type" ), metadataUrlType );
 
 1000        const QString metadataUrlFormat = metadataUrl.format;
 
 1001        if ( !metadataUrlFormat.isEmpty() )
 
 1003          QDomElement metaUrlFormatElem = doc.createElement( QStringLiteral( 
"Format" ) );
 
 1004          QDomText metaUrlFormatText = doc.createTextNode( metadataUrlFormat );
 
 1005          metaUrlFormatElem.appendChild( metaUrlFormatText );
 
 1006          metaUrlElem.appendChild( metaUrlFormatElem );
 
 1008        QDomElement metaUrlORElem = doc.createElement( QStringLiteral( 
"OnlineResource" ) );
 
 1009        metaUrlORElem.setAttribute( QStringLiteral( 
"xmlns:xlink" ), QStringLiteral( 
"http://www.w3.org/1999/xlink" ) );
 
 1010        metaUrlORElem.setAttribute( QStringLiteral( 
"xlink:type" ), QStringLiteral( 
"simple" ) );
 
 1011        metaUrlORElem.setAttribute( QStringLiteral( 
"xlink:href" ), metadataUrl.url );
 
 1012        metaUrlElem.appendChild( metaUrlORElem );
 
 1013        layerElem.appendChild( metaUrlElem );
 
 1017    void writeLegendUrl( QDomDocument &doc, QDomElement &styleElem, 
const QString &legendUrl, 
const QString &legendUrlFormat, 
const QString &name, 
const QString &styleName, 
const QgsProject *project, 
const QgsWmsRequest &request, 
const QgsServerSettings *settings )
 
 1020      QDomElement getLayerLegendGraphicElem = doc.createElement( QStringLiteral( 
"LegendURL" ) );
 
 1022      QString customHrefString = legendUrl;
 
 1024      QStringList getLayerLegendGraphicFormats;
 
 1025      if ( !customHrefString.isEmpty() )
 
 1027        getLayerLegendGraphicFormats << legendUrlFormat;
 
 1031        getLayerLegendGraphicFormats << QStringLiteral( 
"image/png" ); 
 
 1034      for ( 
const QString &getLayerLegendGraphicFormat : std::as_const( getLayerLegendGraphicFormats ) )
 
 1036        QDomElement getLayerLegendGraphicFormatElem = doc.createElement( QStringLiteral( 
"Format" ) );
 
 1037        QDomText getLayerLegendGraphicFormatText = doc.createTextNode( getLayerLegendGraphicFormat );
 
 1038        getLayerLegendGraphicFormatElem.appendChild( getLayerLegendGraphicFormatText );
 
 1039        getLayerLegendGraphicElem.appendChild( getLayerLegendGraphicFormatElem );
 
 1043      if ( customHrefString.isEmpty() )
 
 1046        QUrl href = 
serviceUrl( request, project, *settings );
 
 1047        const QString hrefString = href.toString() + ( href.hasQuery() ? 
"&" : 
"?" );
 
 1049        QUrl mapUrl( hrefString );
 
 1050        QUrlQuery mapUrlQuery( mapUrl.query() );
 
 1051        mapUrlQuery.addQueryItem( QStringLiteral( 
"SERVICE" ), QStringLiteral( 
"WMS" ) );
 
 1052        mapUrlQuery.addQueryItem( QStringLiteral( 
"VERSION" ), request.wmsParameters().version() );
 
 1053        mapUrlQuery.addQueryItem( QStringLiteral( 
"REQUEST" ), QStringLiteral( 
"GetLegendGraphic" ) );
 
 1054        mapUrlQuery.addQueryItem( QStringLiteral( 
"LAYER" ), name );
 
 1055        mapUrlQuery.addQueryItem( QStringLiteral( 
"FORMAT" ), QStringLiteral( 
"image/png" ) );
 
 1056        mapUrlQuery.addQueryItem( QStringLiteral( 
"STYLE" ), styleName );
 
 1057        if ( request.wmsParameters().version() == QLatin1String( 
"1.3.0" ) )
 
 1059          mapUrlQuery.addQueryItem( QStringLiteral( 
"SLD_VERSION" ), QStringLiteral( 
"1.1.0" ) );
 
 1061        mapUrl.setQuery( mapUrlQuery );
 
 1062        customHrefString = mapUrl.toString();
 
 1065      QDomElement getLayerLegendGraphicORElem = doc.createElement( QStringLiteral( 
"OnlineResource" ) );
 
 1066      getLayerLegendGraphicORElem.setAttribute( QStringLiteral( 
"xmlns:xlink" ), QStringLiteral( 
"http://www.w3.org/1999/xlink" ) );
 
 1067      getLayerLegendGraphicORElem.setAttribute( QStringLiteral( 
"xlink:type" ), QStringLiteral( 
"simple" ) );
 
 1068      getLayerLegendGraphicORElem.setAttribute( QStringLiteral( 
"xlink:href" ), customHrefString );
 
 1069      getLayerLegendGraphicElem.appendChild( getLayerLegendGraphicORElem );
 
 1070      styleElem.appendChild( getLayerLegendGraphicElem );
 
 1073    QDomElement createStyleElement( QDomDocument &doc, 
const QString &styleName )
 
 1075      QDomElement styleElem = doc.createElement( QStringLiteral( 
"Style" ) );
 
 1076      QDomElement styleNameElem = doc.createElement( QStringLiteral( 
"Name" ) );
 
 1077      QDomText styleNameText = doc.createTextNode( styleName );
 
 1078      styleNameElem.appendChild( styleNameText );
 
 1079      QDomElement styleTitleElem = doc.createElement( QStringLiteral( 
"Title" ) );
 
 1080      QDomText styleTitleText = doc.createTextNode( styleName );
 
 1081      styleTitleElem.appendChild( styleTitleText );
 
 1082      styleElem.appendChild( styleNameElem );
 
 1083      styleElem.appendChild( styleTitleElem );
 
 1089    bool writeTimeDimensionNode( QDomDocument &doc, QDomElement &layerElem, 
const QList<QgsDateTimeRange> &dateRanges )
 
 1097      const bool hasDateTime = std::any_of( dateRanges.constBegin(), dateRanges.constEnd(), []( 
const QgsDateTimeRange &r ) { return r.begin().time() != QTime( 0, 0 )
 
 1098                                                                                                                                     || ( !r.isInstant() && r.end().time() != QTime( 0, 0 ) ); } );
 
 1100      const QString dateFormat = hasDateTime ? QStringLiteral( 
"yyyy-MM-ddTHH:mm:ss" ) : QStringLiteral( 
"yyyy-MM-dd" );
 
 1102      QStringList strValues;
 
 1106        if ( range.begin().isValid() && range.end().isValid() )
 
 1108          strValues << ( range.isInstant() ? range.begin().toString( dateFormat ) : QStringLiteral( 
"%1/%2" ).arg( range.begin().toString( dateFormat ) ).arg( range.end().toString( dateFormat ) ) );
 
 1112      QDomElement dimElem = doc.createElement( QStringLiteral( 
"Dimension" ) );
 
 1113      dimElem.setAttribute( QStringLiteral( 
"name" ), QStringLiteral( 
"TIME" ) );
 
 1114      dimElem.setAttribute( QStringLiteral( 
"units" ), QStringLiteral( 
"ISO8601" ) );
 
 1115      QDomText dimValuesText = doc.createTextNode( strValues.join( QChar( 
',' ) ) );
 
 1116      dimElem.appendChild( dimValuesText );
 
 1118      layerElem.appendChild( dimElem );
 
 1120      return !hasDateTime;
 
 1123    void appendLayersFromTreeGroup( QDomDocument &doc, QDomElement &parentLayer, 
QgsServerInterface *serverIface, 
const QgsProject *project, 
const QgsWmsRequest &request, 
const QgsLayerTreeGroup *layerTreeGroup, 
const QMap<QString, QgsWmsLayerInfos> &wmsLayerInfos, 
bool projectSettings, QList<QgsDateTimeRange> &parentDateRanges )
 
 1125      const QString version = request.wmsParameters().version();
 
 1130      QList<QgsLayerTreeNode *> layerTreeGroupChildren = layerTreeGroup->
children();
 
 1131      for ( 
int i = 0; i < layerTreeGroupChildren.size(); ++i )
 
 1134        QDomElement layerElem = doc.createElement( QStringLiteral( 
"Layer" ) );
 
 1136        if ( projectSettings )
 
 1138          layerElem.setAttribute( QStringLiteral( 
"visible" ), treeNode->
isVisible() );
 
 1140          layerElem.setAttribute( QStringLiteral( 
"expanded" ), treeNode->
isExpanded() );
 
 1147          QString name = treeGroupChild->
name();
 
 1148          if ( restrictedLayers.contains( name ) ) 
 
 1153          if ( projectSettings )
 
 1155            layerElem.setAttribute( QStringLiteral( 
"mutuallyExclusive" ), treeGroupChild->
isMutuallyExclusive() );
 
 1160          if ( !skipNameForGroup )
 
 1162            QDomElement nameElem = doc.createElement( QStringLiteral( 
"Name" ) );
 
 1164            if ( !shortName.isEmpty() )
 
 1165              nameText = doc.createTextNode( shortName );
 
 1167              nameText = doc.createTextNode( name );
 
 1168            nameElem.appendChild( nameText );
 
 1169            layerElem.appendChild( nameElem );
 
 1172          writeServerProperties( doc, layerElem, project, treeGroupChild->
serverProperties(), name, version );
 
 1175          const QString styleName = QStringLiteral( 
"default" );
 
 1176          QDomElement styleElem = createStyleElement( doc, styleName );
 
 1179          layerElem.appendChild( styleElem );
 
 1182          if ( projectSettings )
 
 1184            QDomElement treeNameElem = doc.createElement( QStringLiteral( 
"TreeName" ) );
 
 1185            QDomText treeNameText = doc.createTextNode( name );
 
 1186            treeNameElem.appendChild( treeNameText );
 
 1187            layerElem.appendChild( treeNameElem );
 
 1190          QList<QgsDateTimeRange> childrenDateRanges;
 
 1191          handleLayersFromTreeGroup( doc, layerElem, serverIface, project, request, treeGroupChild, wmsLayerInfos, projectSettings, childrenDateRanges );
 
 1195            writeTimeDimensionNode( doc, layerElem, childrenDateRanges );
 
 1196            parentDateRanges.append( childrenDateRanges );
 
 1200          if ( layerElem.elementsByTagName( QStringLiteral( 
"Layer" ) ).length() == 0 )
 
 1209          if ( !wmsLayerInfos.contains( treeLayer->
layerId() ) ) 
 
 1216          layerElem.setAttribute(
 
 1217            QStringLiteral( 
"queryable" ),
 
 1218            layerInfos.
queryable ? QStringLiteral( 
"1" ) : QStringLiteral( 
"0" )
 
 1221          QDomElement nameElem = doc.createElement( QStringLiteral( 
"Name" ) );
 
 1222          QDomText nameText = doc.createTextNode( layerInfos.
name );
 
 1223          nameElem.appendChild( nameText );
 
 1224          layerElem.appendChild( nameElem );
 
 1231            appendCrsElementsToLayer( doc, layerElem, layerInfos.
crsExtents.keys(), QStringList() );
 
 1235            appendLayerCrsExtents( doc, layerElem, layerInfos.
crsExtents );
 
 1239          appendLayerStyles( doc, layerElem, layerInfos, project, request, serverIface->
serverSettings() );
 
 1245            auto formatScale = []( 
double value ) {
 
 1246              const thread_local QRegularExpression trailingZeroRegEx = QRegularExpression( QStringLiteral( 
"0+$" ) );
 
 1247              const thread_local QRegularExpression trailingPointRegEx = QRegularExpression( QStringLiteral( 
"[.]+$" ) );
 
 1248              return QString::number( value, 
'f' ).remove( trailingZeroRegEx ).remove( trailingPointRegEx );
 
 1251            if ( version == QLatin1String( 
"1.1.1" ) )
 
 1254              double SCALE_TO_SCALEHINT = 
OGC_PX_M * M_SQRT2;
 
 1256              QDomElement scaleHintElem = doc.createElement( QStringLiteral( 
"ScaleHint" ) );
 
 1257              scaleHintElem.setAttribute( QStringLiteral( 
"min" ), formatScale( layerInfos.
maxScale * SCALE_TO_SCALEHINT ) );
 
 1258              scaleHintElem.setAttribute( QStringLiteral( 
"max" ), formatScale( layerInfos.
minScale * SCALE_TO_SCALEHINT ) );
 
 1259              layerElem.appendChild( scaleHintElem );
 
 1263              QDomElement minScaleElem = doc.createElement( QStringLiteral( 
"MinScaleDenominator" ) );
 
 1264              QDomText minScaleText = doc.createTextNode( formatScale( layerInfos.
maxScale ) );
 
 1265              minScaleElem.appendChild( minScaleText );
 
 1266              layerElem.appendChild( minScaleElem );
 
 1268              QDomElement maxScaleElem = doc.createElement( QStringLiteral( 
"MaxScaleDenominator" ) );
 
 1269              QDomText maxScaleText = doc.createTextNode( formatScale( layerInfos.
minScale ) );
 
 1270              maxScaleElem.appendChild( maxScaleText );
 
 1271              layerElem.appendChild( maxScaleElem );
 
 1275          bool timeDimensionAdded { 
false };
 
 1282            const QList<QgsMapLayerServerProperties::WmsDimensionInfo> wmsDims = serverProperties->
wmsDimensions();
 
 1287              if ( fieldIndex == -1 )
 
 1292              QSet<QVariant> uniqueValues = vl->
uniqueValues( fieldIndex );
 
 1295              if ( !dim.endFieldName.isEmpty() )
 
 1297                int endFieldIndex = vl->
fields().
indexOf( dim.endFieldName );
 
 1299                if ( endFieldIndex == -1 )
 
 1303                uniqueValues.unite( vl->
uniqueValues( endFieldIndex ) );
 
 1306              QList<QVariant> values = qgis::setToList( uniqueValues );
 
 1307              std::sort( values.begin(), values.end() );
 
 1309              QDomElement dimElem = doc.createElement( QStringLiteral( 
"Dimension" ) );
 
 1310              dimElem.setAttribute( QStringLiteral( 
"name" ), dim.name );
 
 1312              if ( dim.name.toUpper() == QLatin1String( 
"TIME" ) )
 
 1314                timeDimensionAdded = 
true;
 
 1317              if ( !dim.units.isEmpty() )
 
 1319                dimElem.setAttribute( QStringLiteral( 
"units" ), dim.units );
 
 1321              if ( !dim.unitSymbol.isEmpty() )
 
 1323                dimElem.setAttribute( QStringLiteral( 
"unitSymbol" ), dim.unitSymbol );
 
 1325              if ( !values.isEmpty() && dim.defaultDisplayType == QgsMapLayerServerProperties::WmsDimensionInfo::MinValue )
 
 1327                dimElem.setAttribute( QStringLiteral( 
"default" ), values.first().toString() );
 
 1329              else if ( !values.isEmpty() && dim.defaultDisplayType == QgsMapLayerServerProperties::WmsDimensionInfo::MaxValue )
 
 1331                dimElem.setAttribute( QStringLiteral( 
"default" ), values.last().toString() );
 
 1333              else if ( dim.defaultDisplayType == QgsMapLayerServerProperties::WmsDimensionInfo::ReferenceValue )
 
 1335                dimElem.setAttribute( QStringLiteral( 
"default" ), dim.referenceValue.toString() );
 
 1337              dimElem.setAttribute( QStringLiteral( 
"multipleValues" ), QStringLiteral( 
"1" ) );
 
 1338              dimElem.setAttribute( QStringLiteral( 
"nearestValue" ), QStringLiteral( 
"0" ) );
 
 1339              if ( projectSettings )
 
 1341                dimElem.setAttribute( QStringLiteral( 
"fieldName" ), dim.fieldName );
 
 1342                dimElem.setAttribute( QStringLiteral( 
"endFieldName" ), dim.endFieldName );
 
 1345              QStringList strValues;
 
 1346              for ( 
const QVariant &v : values )
 
 1348                strValues << v.toString();
 
 1350              QDomText dimValuesText = doc.createTextNode( strValues.join( QLatin1String( 
", " ) ) );
 
 1351              dimElem.appendChild( dimValuesText );
 
 1352              layerElem.appendChild( dimElem );
 
 1357          if ( !timeDimensionAdded
 
 1365            const bool isDateList = writeTimeDimensionNode( doc, layerElem, allRanges );
 
 1367            parentDateRanges.append( allRanges );
 
 1369            QDomElement timeExtentElem = doc.createElement( QStringLiteral( 
"Extent" ) );
 
 1370            timeExtentElem.setAttribute( QStringLiteral( 
"name" ), QStringLiteral( 
"TIME" ) );
 
 1376              extent = QStringLiteral( 
"%1/%2" ).arg( timeExtent.begin().date().toString( Qt::DateFormat::ISODate ), timeExtent.end().date().toString( Qt::DateFormat::ISODate ) );
 
 1380              extent = QStringLiteral( 
"%1/%2" ).arg( timeExtent.begin().toString( Qt::DateFormat::ISODate ), timeExtent.end().toString( Qt::DateFormat::ISODate ) );
 
 1382            QDomText extentValueText = doc.createTextNode( extent );
 
 1383            timeExtentElem.appendChild( extentValueText );
 
 1384            layerElem.appendChild( timeExtentElem );
 
 1387          if ( projectSettings )
 
 1389            appendLayerProjectSettings( doc, layerElem, l );
 
 1393        parentLayer.appendChild( layerElem );
 
 1399      for ( 
const QString &styleName : std::as_const( layerInfos.styles ) )
 
 1401        QDomElement styleElem = createStyleElement( doc, styleName );
 
 1403        writeLegendUrl( doc, styleElem, layerInfos.
legendUrl, layerInfos.
legendUrlFormat, layerInfos.
name, styleName, project, request, settings );
 
 1405        layerElem.appendChild( styleElem );
 
 1409    void appendCrsElementsToLayer( QDomDocument &doc, QDomElement &layerElement, 
const QStringList &crsList, 
const QStringList &constrainedCrsList )
 
 1411      if ( layerElement.isNull() )
 
 1416      const QString version = doc.documentElement().attribute( QStringLiteral( 
"version" ) );
 
 1419      QDomElement titleElement = layerElement.firstChildElement( QStringLiteral( 
"Title" ) );
 
 1420      QDomElement abstractElement = layerElement.firstChildElement( QStringLiteral( 
"Abstract" ) );
 
 1421      QDomElement keywordListElement = layerElement.firstChildElement( QStringLiteral( 
"KeywordList" ) );
 
 1422      QDomElement CRSPrecedingElement = !keywordListElement.isNull() ? keywordListElement : !abstractElement.isNull() ? abstractElement
 
 1425      if ( CRSPrecedingElement.isNull() )
 
 1428        const QDomElement keyElement = layerElement.firstChildElement( QStringLiteral( 
"KeywordList" ) );
 
 1429        CRSPrecedingElement = keyElement;
 
 1433      if ( !constrainedCrsList.isEmpty() )
 
 1435        for ( 
int i = constrainedCrsList.size() - 1; i >= 0; --i )
 
 1437          appendCrsElementToLayer( doc, layerElement, CRSPrecedingElement, constrainedCrsList.at( i ) );
 
 1442        for ( 
const QString &
crs : crsList )
 
 1444          appendCrsElementToLayer( doc, layerElement, CRSPrecedingElement, 
crs );
 
 1450      if ( version == QLatin1String( 
"1.3.0" ) )
 
 1452        appendCrsElementToLayer( doc, layerElement, CRSPrecedingElement, QString( 
"CRS:84" ) );
 
 1456    void appendCrsElementToLayer( QDomDocument &doc, QDomElement &layerElement, 
const QDomElement &precedingElement, 
const QString &crsText )
 
 1458      if ( crsText.isEmpty() )
 
 1460      const QString version = doc.documentElement().attribute( QStringLiteral( 
"version" ) );
 
 1461      QDomElement crsElement = doc.createElement( version == QLatin1String( 
"1.1.1" ) ? 
"SRS" : 
"CRS" );
 
 1462      QDomText crsTextNode = doc.createTextNode( crsText );
 
 1463      crsElement.appendChild( crsTextNode );
 
 1464      layerElement.insertAfter( crsElement, precedingElement );
 
 1467    void appendLayerWgs84BoundingRect( QDomDocument &doc, QDomElement &layerElem, 
const QgsRectangle &wgs84BoundingRect )
 
 1470      if ( wgs84BoundingRect.
isNull() )
 
 1476      QDomElement ExGeoBBoxElement;
 
 1477      const int wgs84precision = 6;
 
 1478      const QString version = doc.documentElement().attribute( QStringLiteral( 
"version" ) );
 
 1479      if ( version == QLatin1String( 
"1.1.1" ) ) 
 
 1481        ExGeoBBoxElement = doc.createElement( QStringLiteral( 
"LatLonBoundingBox" ) );
 
 1489        ExGeoBBoxElement = doc.createElement( QStringLiteral( 
"EX_GeographicBoundingBox" ) );
 
 1490        QDomElement wBoundLongitudeElement = doc.createElement( QStringLiteral( 
"westBoundLongitude" ) );
 
 1492        wBoundLongitudeElement.appendChild( wBoundLongitudeText );
 
 1493        ExGeoBBoxElement.appendChild( wBoundLongitudeElement );
 
 1494        QDomElement eBoundLongitudeElement = doc.createElement( QStringLiteral( 
"eastBoundLongitude" ) );
 
 1496        eBoundLongitudeElement.appendChild( eBoundLongitudeText );
 
 1497        ExGeoBBoxElement.appendChild( eBoundLongitudeElement );
 
 1498        QDomElement sBoundLatitudeElement = doc.createElement( QStringLiteral( 
"southBoundLatitude" ) );
 
 1500        sBoundLatitudeElement.appendChild( sBoundLatitudeText );
 
 1501        ExGeoBBoxElement.appendChild( sBoundLatitudeElement );
 
 1502        QDomElement nBoundLatitudeElement = doc.createElement( QStringLiteral( 
"northBoundLatitude" ) );
 
 1504        nBoundLatitudeElement.appendChild( nBoundLatitudeText );
 
 1505        ExGeoBBoxElement.appendChild( nBoundLatitudeElement );
 
 1508      const QDomElement lastCRSElem = layerElem.lastChildElement( version == QLatin1String( 
"1.1.1" ) ? 
"SRS" : 
"CRS" );
 
 1509      if ( !lastCRSElem.isNull() )
 
 1511        layerElem.insertAfter( ExGeoBBoxElement, lastCRSElem );
 
 1515        layerElem.appendChild( ExGeoBBoxElement );
 
 1519    void appendLayerCrsExtents( QDomDocument &doc, QDomElement &layerElem, 
const QMap<QString, QgsRectangle> &crsExtents )
 
 1521      const QString version = doc.documentElement().attribute( QStringLiteral( 
"version" ) );
 
 1523      const auto &keys = crsExtents.keys();
 
 1524      for ( 
const QString &crsText : std::as_const( keys ) )
 
 1529        if ( crsExtent.isNull() )
 
 1541        QDomElement bBoxElement = doc.createElement( QStringLiteral( 
"BoundingBox" ) );
 
 1544          bBoxElement.setAttribute( version == QLatin1String( 
"1.1.1" ) ? 
"SRS" : 
"CRS", 
crs.authid() );
 
 1557        QDomElement lastBBoxElem = layerElem.lastChildElement( QStringLiteral( 
"BoundingBox" ) );
 
 1558        if ( !lastBBoxElem.isNull() )
 
 1560          layerElem.insertAfter( bBoxElement, lastBBoxElem );
 
 1564          lastBBoxElem = layerElem.lastChildElement( version == QLatin1String( 
"1.1.1" ) ? 
"LatLonBoundingBox" : 
"EX_GeographicBoundingBox" );
 
 1565          if ( !lastBBoxElem.isNull() )
 
 1567            layerElem.insertAfter( bBoxElement, lastBBoxElem );
 
 1571            layerElem.appendChild( bBoxElement );
 
 1579#ifdef HAVE_SERVER_PYTHON_PLUGINS 
 1582      ( void ) serverIface;
 
 1587      QStringList layerList;
 
 1590      QList<QgsMapLayer *> projectLayerOrder = projectLayerTreeRoot->
layerOrder();
 
 1591      for ( 
int i = 0; i < projectLayerOrder.size(); ++i )
 
 1595        if ( restrictedLayers.contains( l->
name() ) ) 
 
 1599#ifdef HAVE_SERVER_PYTHON_PLUGINS 
 1605        QString wmsName = l->
name();
 
 1615        layerList << wmsName;
 
 1618      if ( !layerList.isEmpty() )
 
 1620        QStringList reversedList;
 
 1621        reversedList.reserve( layerList.size() );
 
 1622        for ( 
int i = layerList.size() - 1; i >= 0; --i )
 
 1623          reversedList << layerList[i];
 
 1625        QDomElement layerDrawingOrderElem = doc.createElement( QStringLiteral( 
"LayerDrawingOrder" ) );
 
 1626        QDomText drawingOrderText = doc.createTextNode( reversedList.join( 
',' ) );
 
 1627        layerDrawingOrderElem.appendChild( drawingOrderText );
 
 1628        parentElem.appendChild( layerDrawingOrderElem );
 
 1632    void appendLayerProjectSettings( QDomDocument &doc, QDomElement &layerElem, 
QgsMapLayer *currentLayer )
 
 1634      if ( !currentLayer )
 
 1640      QDomElement treeNameElem = doc.createElement( QStringLiteral( 
"TreeName" ) );
 
 1641      QDomText treeNameText = doc.createTextNode( currentLayer->
name() );
 
 1642      treeNameElem.appendChild( treeNameText );
 
 1643      layerElem.appendChild( treeNameElem );
 
 1645      switch ( currentLayer->
type() )
 
 1651          int displayFieldIdx = -1;
 
 1652          QString displayField = QStringLiteral( 
"maptip" );
 
 1654          if ( exp.isField() )
 
 1661          QDomElement attributesElem = doc.createElement( QStringLiteral( 
"Attributes" ) );
 
 1663          for ( 
int idx = 0; idx < layerFields.
count(); ++idx )
 
 1671            if ( idx == displayFieldIdx )
 
 1675            QDomElement attributeElem = doc.createElement( QStringLiteral( 
"Attribute" ) );
 
 1676            attributeElem.setAttribute( QStringLiteral( 
"name" ), field.
name() );
 
 1677            attributeElem.setAttribute( QStringLiteral( 
"type" ), QVariant::typeToName( field.
type() ) );
 
 1678            attributeElem.setAttribute( QStringLiteral( 
"typeName" ), field.
typeName() );
 
 1679            QString alias = field.
alias();
 
 1680            if ( !alias.isEmpty() )
 
 1682              attributeElem.setAttribute( QStringLiteral( 
"alias" ), alias );
 
 1686            attributeElem.setAttribute( QStringLiteral( 
"editType" ), vLayer->
editorWidgetSetup( idx ).
type() );
 
 1687            attributeElem.setAttribute( QStringLiteral( 
"comment" ), field.
comment() );
 
 1688            attributeElem.setAttribute( QStringLiteral( 
"length" ), field.
length() );
 
 1689            attributeElem.setAttribute( QStringLiteral( 
"precision" ), field.
precision() );
 
 1690            attributesElem.appendChild( attributeElem );
 
 1694          layerElem.setAttribute( QStringLiteral( 
"displayField" ), displayField );
 
 1698          if ( pkAttributes.size() > 0 )
 
 1700            QDomElement pkElem = doc.createElement( QStringLiteral( 
"PrimaryKey" ) );
 
 1701            QgsAttributeList::const_iterator pkIt = pkAttributes.constBegin();
 
 1702            for ( ; pkIt != pkAttributes.constEnd(); ++pkIt )
 
 1704              QDomElement pkAttributeElem = doc.createElement( QStringLiteral( 
"PrimaryKeyAttribute" ) );
 
 1705              QDomText pkAttName = doc.createTextNode( layerFields.
at( *pkIt ).
name() );
 
 1706              pkAttributeElem.appendChild( pkAttName );
 
 1707              pkElem.appendChild( pkAttributeElem );
 
 1709            layerElem.appendChild( pkElem );
 
 1716          layerElem.setAttribute( QStringLiteral( 
"opacity" ), QString::number( vLayer->
opacity() ) );
 
 1718          layerElem.appendChild( attributesElem );
 
 1725          if ( provider && provider->
name() == 
"wms" )
 
 1728            QVariant wmsBackgroundLayer = currentLayer->
customProperty( QStringLiteral( 
"WMSBackgroundLayer" ), false );
 
 1729            QDomElement wmsBackgroundLayerElem = doc.createElement( 
"WMSBackgroundLayer" );
 
 1730            QDomText wmsBackgroundLayerText = doc.createTextNode( wmsBackgroundLayer.toBool() ? QStringLiteral( 
"1" ) : QStringLiteral( 
"0" ) );
 
 1731            wmsBackgroundLayerElem.appendChild( wmsBackgroundLayerText );
 
 1732            layerElem.appendChild( wmsBackgroundLayerElem );
 
 1735            QVariant wmsPublishDataSourceUrl = currentLayer->
customProperty( QStringLiteral( 
"WMSPublishDataSourceUrl" ), 
false );
 
 1736            if ( wmsPublishDataSourceUrl.toBool() )
 
 1738              bool tiled = qobject_cast<const QgsRasterDataProvider *>( provider )
 
 1739                             ? !qobject_cast<const QgsRasterDataProvider *>( provider )->nativeResolutions().isEmpty()
 
 1742              QDomElement dataSourceElem = doc.createElement( tiled ? QStringLiteral( 
"WMTSDataSource" ) : QStringLiteral( 
"WMSDataSource" ) );
 
 1743              QDomText dataSourceUri = doc.createTextNode( provider->
dataSourceUri() );
 
 1744              dataSourceElem.appendChild( dataSourceUri );
 
 1745              layerElem.appendChild( dataSourceElem );
 
 1749          QVariant wmsPrintLayer = currentLayer->
customProperty( QStringLiteral( 
"WMSPrintLayer" ) );
 
 1750          if ( wmsPrintLayer.isValid() )
 
 1752            QDomElement wmsPrintLayerElem = doc.createElement( 
"WMSPrintLayer" );
 
 1753            QDomText wmsPrintLayerText = doc.createTextNode( wmsPrintLayer.toString() );
 
 1754            wmsPrintLayerElem.appendChild( wmsPrintLayerText );
 
 1755            layerElem.appendChild( wmsPrintLayerElem );
 
 1761          if ( rasterRenderer )
 
 1763            layerElem.setAttribute( QStringLiteral( 
"opacity" ), QString::number( rasterRenderer->
opacity() ) );
 
 1779    void addKeywordListElement( 
const QgsProject *project, QDomDocument &doc, QDomElement &parent )
 
 1783      QDomElement keywordsElem = doc.createElement( QStringLiteral( 
"KeywordList" ) );
 
 1785      QDomElement keywordElem = doc.createElement( QStringLiteral( 
"Keyword" ) );
 
 1786      keywordElem.setAttribute( QStringLiteral( 
"vocabulary" ), QStringLiteral( 
"ISO" ) );
 
 1787      QDomText keywordText = doc.createTextNode( QStringLiteral( 
"infoMapAccessService" ) );
 
 1788      keywordElem.appendChild( keywordText );
 
 1789      keywordsElem.appendChild( keywordElem );
 
 1790      parent.appendChild( keywordsElem );
 
 1792      for ( 
const QString &keyword : std::as_const( keywords ) )
 
 1794        if ( !keyword.isEmpty() )
 
 1796          keywordElem = doc.createElement( QStringLiteral( 
"Keyword" ) );
 
 1797          keywordText = doc.createTextNode( keyword );
 
 1798          keywordElem.appendChild( keywordText );
 
 1801            keywordElem.setAttribute( QStringLiteral( 
"vocabulary" ), QStringLiteral( 
"SIA_Geo405" ) );
 
 1803          keywordsElem.appendChild( keywordElem );
 
 1806      parent.appendChild( keywordsElem );
 
 1810  bool hasQueryableLayers( 
const QStringList &layerIds, 
const QMap<QString, QgsWmsLayerInfos> &wmsLayerInfos )
 
 1812    for ( 
const QString &
id : std::as_const( layerIds ) )
 
 1814      if ( !wmsLayerInfos.contains( 
id ) )
 
 1818      if ( wmsLayerInfos[
id].queryable )
 
 
 1831    for ( 
const QString &
id : std::as_const( layerIds ) )
 
 1833      if ( !wmsLayerInfos.contains( 
id ) )
 
 1838      QgsRectangle rect = wmsLayerInfos[id].wgs84BoundingRect;
 
 
 1863  QMap<QString, QgsRectangle> 
combineCrsExtents( 
const QStringList &layerIds, 
const QMap<QString, QgsWmsLayerInfos> &wmsLayerInfos )
 
 1865    QMap<QString, QgsRectangle> combined;
 
 1867    for ( 
const QString &
id : std::as_const( layerIds ) )
 
 1869      if ( !wmsLayerInfos.contains( 
id ) )
 
 1875      const auto keys = layerInfos.
crsExtents.keys();
 
 1876      for ( 
const QString &
crs : std::as_const( keys ) )
 
 1889        if ( !combined.contains( 
crs ) )
 
 1891          combined[
crs] = rect;
 
 
@ Millimeters
Millimeters.
 
@ Warning
Warning message.
 
@ Group
Composite group layer. Added in QGIS 3.24.
 
@ Plugin
Plugin based layer.
 
@ TiledScene
Tiled scene layer. Added in QGIS 3.34.
 
@ Annotation
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
 
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
 
@ Mesh
Mesh layer. Added in QGIS 3.2.
 
@ PointCloud
Point cloud layer. Added in QGIS 3.18.
 
static QString geographicCrsAuthId()
Geographic coordinate system auth:id string for a default geographic CRS (EPSG:4326).
 
@ HideFromWms
Field is not available if layer is served as WMS from QGIS server.
 
A helper class that centralizes restrictions given by all the access control filter plugins.
 
bool layerReadPermission(const QgsMapLayer *layer) const
Returns the layer read right.
 
bool fillCacheKey(QStringList &cacheKey) const
Fill the capabilities caching key.
 
A cache for capabilities xml documents (by configuration file path).
 
const QDomDocument * searchCapabilitiesDocument(const QString &configFilePath, const QString &key)
Returns cached capabilities document (or 0 if document for configuration file not in cache)
 
void insertCapabilitiesDocument(const QString &configFilePath, const QString &key, const QDomDocument *doc)
Inserts new capabilities document (creates a copy of the document, does not take ownership)
 
Represents a coordinate reference system (CRS).
 
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
 
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
 
bool hasAxisInverted() const
Returns whether the axis order is inverted for the CRS compared to the order east/north (longitude/la...
 
Custom exception class for Coordinate Reference System related exceptions.
 
Abstract base class for spatial data provider implementations.
 
virtual QString name() const =0
Returns a provider name.
 
virtual QString dataSourceUri(bool expandAuthConfig=false) const
Gets the data source specification.
 
An expression node which takes its value from a feature's field.
 
Handles parsing and evaluation of expressions (formerly called "search strings").
 
Encapsulate a field in an attribute table or data source.
 
QString typeName() const
Gets the field type.
 
Qgis::FieldConfigurationFlags configurationFlags
 
Container of fields for a vector layer.
 
Q_INVOKABLE int indexOf(const QString &fieldName) const
Gets the field index from the field name.
 
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
 
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
 
Layer tree group node serves as a container for layers and further groups.
 
QString name() const override
Returns the group's name.
 
QStringList findLayerIds() const
Find layer IDs used in all layer nodes.
 
QgsMapLayerServerProperties * serverProperties()
Returns QGIS Server Properties for the layer tree group.
 
bool isMutuallyExclusive() const
Returns whether the group is mutually exclusive (only one child can be checked at a time)
 
bool hasWmsTimeDimension() const
Returns whether the WMS time dimension should be computed for this group or not.
 
Layer tree node points to a map layer.
 
QString layerId() const
Returns the ID for the map layer associated with this node.
 
QgsMapLayer * layer() const
Returns the map layer associated with this node.
 
Base class for nodes in a layer tree.
 
@ NodeGroup
Container of other groups and layers.
 
bool isVisible() const
Returns whether a node is really visible (ie checked and all its ancestors checked as well)
 
QList< QgsLayerTreeNode * > children()
Gets list of children of the node. Children are owned by the parent.
 
NodeType nodeType() const
Find out about type of the node. It is usually shorter to use convenience functions from QgsLayerTree...
 
bool isExpanded() const
Returns whether the node should be shown as expanded or collapsed in GUI.
 
bool itemVisibilityChecked() const
Returns whether a node is checked (independently of its ancestors or children)
 
Namespace with helper functions for layer tree operations.
 
QList< QgsMapLayer * > layerOrder() const
The order in which layers will be rendered on the canvas.
 
Used to render QgsLayout as an atlas, by iterating over the features from an associated vector layer.
 
bool enabled() const
Returns whether the atlas generation is enabled.
 
QgsVectorLayer * coverageLayer() const
Returns the coverage layer used for the atlas features.
 
A layout multiframe subclass for HTML content.
 
A layout item subclass for text labels.
 
Layout graphical items for displaying a map.
 
QString displayName() const override
Gets item display name.
 
QgsLayoutSize sizeWithUnits() const
Returns the item's current size, including units.
 
QString id() const
Returns the item's ID name.
 
QList< QgsPrintLayout * > printLayouts() const
Returns a list of all print layouts contained in the manager.
 
Provides a method of storing measurements for use in QGIS layouts using a variety of different measur...
 
double length() const
Returns the length of the measurement.
 
int frameCount() const
Returns the number of frames associated with this multiframe.
 
QgsLayoutFrame * frame(int index) const
Returns the child frame at a specified index from the multiframe.
 
int pageCount() const
Returns the number of pages in the collection.
 
QgsLayoutItemPage * page(int pageNumber)
Returns a specific page (by pageNumber) from the collection.
 
Provides a method of storing sizes, consisting of a width and height, for use in QGIS layouts.
 
double height() const
Returns the height of the size.
 
double width() const
Returns the width of the size.
 
QgsLayoutPageCollection * pageCollection()
Returns a pointer to the layout's page collection, which stores and manages page items in the layout.
 
void layoutItems(QList< T * > &itemList) const
Returns a list of layout items of a specific type.
 
void layoutObjects(QList< T * > &objectList) const
Returns a list of layout objects (items and multiframes) of a specific type.
 
QgsLayoutMeasurement convertFromLayoutUnits(double length, Qgis::LayoutUnit unit) const
Converts a length measurement from the layout's native units to a specified target unit.
 
Manages QGIS Server properties for a map layer.
 
QString attribution() const
Returns the attribution of the layer used by QGIS Server in GetCapabilities request.
 
QString dataUrlFormat() const
Returns the DataUrl format of the layer used by QGIS Server in GetCapabilities request.
 
QString title() const
Returns the title of the layer used by QGIS Server in GetCapabilities request.
 
QString legendUrlFormat() const
Returns the format for a URL based layer legend.
 
QString dataUrl() const
Returns the DataUrl of the layer used by QGIS Server in GetCapabilities request.
 
QString keywordList() const
Returns the keyword list of the layerused by QGIS Server in GetCapabilities request.
 
QString shortName() const
Returns the short name of the layer used by QGIS Server to identify the layer.
 
QString attributionUrl() const
Returns the attribution URL of the layer used by QGIS Server in GetCapabilities request.
 
QString legendUrl() const
Returns the URL for the layer's legend.
 
QString abstract() const
Returns the abstract of the layerused by QGIS Server in GetCapabilities request.
 
virtual QgsDateTimeRange calculateTemporalExtent(QgsMapLayer *layer) const
Attempts to calculate the overall temporal extent for the specified layer, using the settings defined...
 
virtual QList< QgsDateTimeRange > allTemporalRanges(QgsMapLayer *layer) const
Attempts to calculate the overall list of all temporal extents which are contained in the specified l...
 
Base class for all map layer types.
 
Q_INVOKABLE QVariant customProperty(const QString &value, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer.
 
QgsMapLayerServerProperties * serverProperties()
Returns QGIS Server Properties for the map layer.
 
virtual QgsMapLayerTemporalProperties * temporalProperties()
Returns the layer's temporal properties.
 
virtual Q_INVOKABLE QgsDataProvider * dataProvider()
Returns the layer's data provider, it may be nullptr.
 
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
Adds a message to the log instance (and creates it if necessary).
 
Print layout, a QgsLayout subclass for static or atlas-based layouts.
 
QgsLayoutAtlas * atlas()
Returns the print layout's atlas.
 
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
 
QString title() const
Returns the project's title.
 
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
 
QgsCoordinateTransformContext transformContext
 
QgsLayerTree * layerTreeRoot() const
Returns pointer to the root (invisible) node of the project's layer tree.
 
const QgsLayoutManager * layoutManager() const
Returns the project's layout manager, which manages print layouts, atlases and reports within the pro...
 
QgsCoordinateReferenceSystem crs
 
Represents a raster layer.
 
QgsRasterRenderer * renderer() const
Returns the raster's renderer.
 
Raster renderer pipe that applies colors to a raster.
 
double opacity() const
Returns the opacity for the renderer, where opacity is a value between 0 (totally transparent) and 1....
 
A rectangle specified with double values.
 
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle.
 
A helper class that centralizes caches accesses given by all the server cache filter plugins.
 
bool setCachedDocument(const QDomDocument *doc, const QgsProject *project, const QgsServerRequest &request, QgsAccessControl *accessControl) const
Updates or inserts the document in cache like capabilities.
 
bool getCachedDocument(QDomDocument *doc, const QgsProject *project, const QgsServerRequest &request, QgsAccessControl *accessControl) const
Returns cached document (or 0 if document not in cache) like capabilities.
 
Defines interfaces exposed by QGIS Server and made available to plugins.
 
virtual QgsServerCacheManager * cacheManager() const =0
Gets the registered server cache filters.
 
virtual QString configFilePath()=0
Returns the configuration file path.
 
virtual QgsAccessControl * accessControls() const =0
Gets the registered access control filters.
 
virtual QgsServerSettings * serverSettings()=0
Returns the server settings.
 
virtual QgsCapabilitiesCache * capabilitiesCache()=0
Gets pointer to the capabiblities cache.
 
QString service() const
Returns SERVICE parameter as a string or an empty string if not defined.
 
static QString wmsRootName(const QgsProject &project)
Returns the WMS root layer name defined in a QGIS project.
 
static bool wmsInfoFormatSia2045(const QgsProject &project)
Returns if the info format is SIA20145.
 
static bool wmsSkipNameForGroup(const QgsProject &project)
Returns if name attribute should be skipped for groups in WMS capabilities document.
 
static QString wmsInspireMetadataUrl(const QgsProject &project)
Returns the Inspire metadata URL.
 
static double ceilWithPrecision(double number, int places)
Returns a double greater than number to the specified number of places.
 
static QStringList wmsRestrictedComposers(const QgsProject &project)
Returns the restricted composer list.
 
static QgsRectangle wmsExtent(const QgsProject &project)
Returns the WMS Extent restriction.
 
static bool wmsUseLayerIds(const QgsProject &project)
Returns if layer ids are used as name in WMS.
 
static QString owsServiceAccessConstraints(const QgsProject &project)
Returns the owsService access constraints defined in project.
 
static QStringList wfsLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published in WFS.
 
static QString owsServiceOnlineResource(const QgsProject &project)
Returns the owsService online resource defined in project.
 
static QString owsServiceFees(const QgsProject &project)
Returns the owsService fees defined in project.
 
static QStringList owsServiceKeywords(const QgsProject &project)
Returns the owsService keywords defined in project.
 
static QString owsServiceContactPosition(const QgsProject &project)
Returns the owsService contact position defined in project.
 
static QString serviceUrl(const QString &service, const QgsServerRequest &request, const QgsServerSettings &settings)
Returns the service url defined in the environment variable or with HTTP header.
 
static QString wmsInspireTemporalReference(const QgsProject &project)
Returns the Inspire temporal reference.
 
static QStringList wmsOutputCrsList(const QgsProject &project)
Returns the WMS output CRS list.
 
static QString wmsInspireMetadataDate(const QgsProject &project)
Returns the Inspire metadata date.
 
static QString owsServiceContactOrganization(const QgsProject &project)
Returns the owsService contact organization defined in project.
 
static QStringList wmsRestrictedLayers(const QgsProject &project)
Returns the restricted layer name list.
 
static QString wmsInspireLanguage(const QgsProject &project)
Returns the Inspire language.
 
static QString wmsInspireMetadataUrlType(const QgsProject &project)
Returns the Inspire metadata URL type.
 
static bool wmsInspireActivate(const QgsProject &project)
Returns if Inspire is activated.
 
static int wmsMaxWidth(const QgsProject &project)
Returns the maximum width for WMS images defined in a QGIS project.
 
static QString owsServiceTitle(const QgsProject &project)
Returns the owsService title defined in project.
 
static QString owsServiceContactMail(const QgsProject &project)
Returns the owsService contact mail defined in project.
 
static QString owsServiceAbstract(const QgsProject &project)
Returns the owsService abstract defined in project.
 
static double floorWithPrecision(double number, int places)
Returns a double less than number to the specified number of places.
 
static int wmsMaxHeight(const QgsProject &project)
Returns the maximum height for WMS images defined in a QGIS project.
 
static QString owsServiceContactPhone(const QgsProject &project)
Returns the owsService contact phone defined in project.
 
static QString owsServiceContactPerson(const QgsProject &project)
Returns the owsService contact person defined in project.
 
QgsServerParameters serverParameters() const
Returns parameters.
 
Defines the response interface passed to QgsService.
 
virtual void write(const QString &data)
Write string This is a convenient method that will write directly to the underlying I/O device.
 
virtual void setHeader(const QString &key, const QString &value)=0
Set Header entry Add Header entry to the response Note that it is usually an error to set Header afte...
 
Provides a way to retrieve settings by prioritizing according to environment variables,...
 
bool getPrintDisabled() const
Returns true if WMS GetPrint request is disabled and the project's reading flag QgsProject::ReadFlag:...
 
const QList< QgsServerWmsDimensionProperties::WmsDimensionInfo > wmsDimensions() const
Returns the QGIS Server WMS Dimension list.
 
bool isActive() const
Returns true if the temporal property is active.
 
Represents a vector layer which manages a vector based dataset.
 
QString attributeDisplayName(int index) const
Convenience function that returns the attribute alias if defined or the field name else.
 
Q_INVOKABLE Qgis::WkbType wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
 
QString displayExpression
 
QgsEditorWidgetSetup editorWidgetSetup(int index) const
Returns the editor widget setup for the field at the specified index.
 
QgsAttributeList primaryKeyAttributes() const
Returns the list of attributes which make up the layer's primary keys.
 
QSet< QVariant > uniqueValues(int fieldIndex, int limit=-1) const FINAL
Calculates a list of unique values contained within an attribute in the layer.
 
static Q_INVOKABLE QString displayString(Qgis::WkbType type)
Returns a non-translated display string type for a WKB type, e.g., the geometry name used in WKT geom...
 
QString legendUrlFormat
WMS layer legend URL format.
 
QString legendUrl
WMS layer legend URL.
 
static QgsRectangle transformExtent(const QgsRectangle &extent, const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination, const QgsCoordinateTransformContext &context, const bool &ballparkTransformsAreAppropriate=false)
Returns a transformed extent.
 
double maxScale
WMS layer maximum scale (if negative, no maximum scale is defined)
 
QMap< QString, QgsRectangle > crsExtents
WMS layer CRS extents (can be empty)
 
static QMap< QString, QgsRectangle > transformExtentToCrsList(const QgsRectangle &extent, const QgsCoordinateReferenceSystem &source, const QList< QgsCoordinateReferenceSystem > &destinations, const QgsCoordinateTransformContext &context)
Returns a map with CRS authid as key and the transformed extent as value.
 
QString name
WMS layer name.
 
static QMap< QString, QgsWmsLayerInfos > buildWmsLayerInfos(QgsServerInterface *serverIface, const QgsProject *project, const QList< QgsCoordinateReferenceSystem > &outputCrsList)
Returns the WMS layers definition to build WMS capabilities.
 
bool hasScaleBasedVisibility
WMS layer has scale based visibility.
 
double minScale
WMS layer minimum scale (if negative, no maximum scale is defined)
 
bool queryable
WMS layer is queryable.
 
QgsRectangle wgs84BoundingRect
WMS layer WGS84 bounding rectangle (can be empty)
 
QString version() const override
Returns VERSION parameter as a string or an empty string if not defined.
 
Defines request interfaces passed to WMS service.
 
const QgsWmsParameters & wmsParameters() const
Returns the parameters interpreted for the WMS service.
 
Median cut implementation.
 
QDomElement getWFSLayersElement(QDomDocument &doc, const QgsProject *project)
Create WFSLayers element for get capabilities document.
 
void writeGetCapabilities(QgsServerInterface *serverIface, const QgsProject *project, const QgsWmsRequest &request, QgsServerResponse &response, bool projectSettings)
Output GetCapabilities response.
 
QDomElement getLayersAndStylesCapabilitiesElement(QDomDocument &doc, QgsServerInterface *serverIface, const QgsProject *project, const QgsWmsRequest &request, bool projectSettings)
Create element for get capabilities document.
 
QDomElement getInspireCapabilitiesElement(QDomDocument &doc, const QgsProject *project)
Create InspireCapabilities element for get capabilities document.
 
void handleLayersFromTreeGroup(QDomDocument &doc, QDomElement &parentLayer, QgsServerInterface *serverIface, const QgsProject *project, const QgsWmsRequest &request, const QgsLayerTreeGroup *layerTreeGroup, const QMap< QString, QgsWmsLayerInfos > &wmsLayerInfos, bool projectSettings, QList< QgsDateTimeRange > &parentDateRanges)
 
QDomElement getComposerTemplatesElement(QDomDocument &doc, const QgsProject *project)
Create ComposerTemplates element for get capabilities document.
 
QDomElement getServiceElement(QDomDocument &doc, const QgsProject *project, const QgsWmsRequest &request, const QgsServerSettings *serverSettings)
Create Service element for get capabilities document.
 
QDomElement getCapabilityElement(QDomDocument &doc, const QgsProject *project, const QgsWmsRequest &request, bool projectSettings, QgsServerInterface *serverIface)
Create Capability element for get capabilities document.
 
QDomDocument getCapabilities(QgsServerInterface *serverIface, const QgsProject *project, const QgsWmsRequest &request, bool projectSettings)
Creates the WMS GetCapabilities XML document.
 
bool hasQueryableLayers(const QStringList &layerIds, const QMap< QString, QgsWmsLayerInfos > &wmsLayerInfos)
Returns true if at least one layer from the layers ids is queryable.
 
QgsRectangle combineWgs84BoundingRect(const QStringList &layerIds, const QMap< QString, QgsWmsLayerInfos > &wmsLayerInfos)
Returns the combination of the WGS84 bounding rectangle of the layers from the list of layers ids.
 
QMap< QString, QgsRectangle > combineCrsExtents(const QStringList &layerIds, const QMap< QString, QgsWmsLayerInfos > &wmsLayerInfos)
Returns the combinations of the extent CRSes of the layers from the list of layers ids.
 
QUrl serviceUrl(const QgsServerRequest &request, const QgsProject *project, const QgsServerSettings &settings)
Returns WMS service URL.
 
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
 
QList< int > QgsAttributeList
 
const QgsCoordinateReferenceSystem & crs
 
Setting to define QGIS Server WMS Dimension.