QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgswmsrenderer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgswmsrenderer.cpp
3  -------------------
4  begin : May 14, 2006
5  copyright : (C) 2006 by Marco Hugentobler
6  (C) 2017 by David Marteau
7  email : marco dot hugentobler at karto dot baug dot ethz dot ch
8  david dot marteau at 3liz dot com
9  ***************************************************************************/
10 
11 /***************************************************************************
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * *
18  ***************************************************************************/
19 
20 #include "qgswmsutils.h"
21 #include "qgsjsonutils.h"
22 #include "qgswmsrenderer.h"
23 #include "qgsfilterrestorer.h"
24 #include "qgsexception.h"
25 #include "qgsfields.h"
26 #include "qgsfieldformatter.h"
28 #include "qgsfeatureiterator.h"
29 #include "qgsgeometry.h"
30 #include "qgsmapserviceexception.h"
31 #include "qgslayertree.h"
32 #include "qgslayertreemodel.h"
33 #include "qgslegendrenderer.h"
34 #include "qgsmaplayer.h"
35 #include "qgsmaplayerlegend.h"
36 #include "qgsmapthemecollection.h"
37 #include "qgsmaptopixel.h"
38 #include "qgsproject.h"
40 #include "qgsrasterlayer.h"
41 #include "qgsrasterrenderer.h"
42 #include "qgsscalecalculator.h"
45 #include "qgsvectordataprovider.h"
46 #include "qgsvectorlayer.h"
47 #include "qgsmessagelog.h"
48 #include "qgsrenderer.h"
49 #include "qgsfeature.h"
50 #include "qgsaccesscontrol.h"
51 #include "qgsfeaturerequest.h"
52 #include "qgsmaprendererjobproxy.h"
53 #include "qgswmsserviceexception.h"
54 #include "qgsserverprojectutils.h"
55 #include "qgsserverfeatureid.h"
57 #include "qgswkbtypes.h"
58 #include "qgsannotationmanager.h"
59 #include "qgsannotation.h"
60 #include "qgsvectorlayerlabeling.h"
62 #include "qgspallabeling.h"
63 #include "qgswmsrestorer.h"
64 #include "qgsdxfexport.h"
65 #include "qgssymbollayerutils.h"
66 #include "qgsserverexception.h"
67 #include "qgsserverapiutils.h"
69 #include "qgsfeaturestore.h"
73 #include "qgsdimensionfilter.h"
74 
75 #include <QImage>
76 #include <QPainter>
77 #include <QStringList>
78 #include <QTemporaryFile>
79 #include <QDir>
80 #include <QUrl>
81 #include <nlohmann/json.hpp>
82 
83 //for printing
84 #include "qgslayoutatlas.h"
85 #include "qgslayoutmanager.h"
86 #include "qgslayoutexporter.h"
87 #include "qgslayoutsize.h"
88 #include "qgslayoutrendercontext.h"
89 #include "qgslayoutmeasurement.h"
90 #include "qgsprintlayout.h"
92 #include "qgslayoutitempage.h"
93 #include "qgslayoutitemlabel.h"
94 #include "qgslayoutitemlegend.h"
95 #include "qgslayoutitemmap.h"
96 #include "qgslayoutitemmapgrid.h"
97 #include "qgslayoutframe.h"
98 #include "qgslayoutitemhtml.h"
100 #include "qgsogcutils.h"
101 #include "qgsunittypes.h"
102 
103 namespace QgsWms
104 {
105  QgsRenderer::QgsRenderer( const QgsWmsRenderContext &context )
106  : mContext( context )
107  {
108  mProject = mContext.project();
109 
110  mWmsParameters = mContext.parameters();
111  mWmsParameters.dump();
112  }
113 
115  {
116  removeTemporaryLayers();
117  }
118 
120  {
121  // get layers
122  std::unique_ptr<QgsWmsRestorer> restorer;
123  restorer.reset( new QgsWmsRestorer( mContext ) );
124 
125  // configure layers
126  QList<QgsMapLayer *> layers = mContext.layersToRender();
127  configureLayers( layers );
128 
129  // init renderer
130  QgsLegendSettings settings = legendSettings();
131  QgsLegendRenderer renderer( &model, settings );
132 
133  // create image
134  std::unique_ptr<QImage> image;
135  const qreal dpmm = mContext.dotsPerMm();
136  const QSizeF minSize = renderer.minimumSize();
137  const QSize size( static_cast<int>( minSize.width() * dpmm ), static_cast<int>( minSize.height() * dpmm ) );
138  if ( !mContext.isValidWidthHeight( size.width(), size.height() ) )
139  {
140  throw QgsServerException( QStringLiteral( "Legend image is too large" ) );
141  }
142  image.reset( createImage( size ) );
143 
144  // configure painter
145  QPainter painter( image.get() );
146  QgsRenderContext context = QgsRenderContext::fromQPainter( &painter );
148  QgsScopedRenderContextScaleToMm scaleContext( context );
149  // QGIS 4.0 -- take from real render context instead
151  context.setRendererScale( settings.mapScale() );
152  context.setMapToPixel( QgsMapToPixel( 1 / ( settings.mmPerMapUnit() * context.scaleFactor() ) ) );
154 
155  // rendering
156  renderer.drawLegend( context );
157  painter.end();
158 
159  return image.release();
160  }
161 
163  {
164  // get layers
165  std::unique_ptr<QgsWmsRestorer> restorer;
166  restorer.reset( new QgsWmsRestorer( mContext ) );
167 
168  // configure layers
169  QList<QgsMapLayer *> layers = mContext.layersToRender();
170  configureLayers( layers );
171 
172  // create image
173  const QSize size( mWmsParameters.widthAsInt(), mWmsParameters.heightAsInt() );
174  //test if legend image is larger than max width/height
175  if ( !mContext.isValidWidthHeight( size.width(), size.height() ) )
176  {
177  throw QgsServerException( QStringLiteral( "Legend image is too large" ) );
178  }
179  std::unique_ptr<QImage> image( createImage( size ) );
180 
181  // configure painter
182  const qreal dpmm = mContext.dotsPerMm();
183  std::unique_ptr<QPainter> painter;
184  painter.reset( new QPainter( image.get() ) );
185  painter->setRenderHint( QPainter::Antialiasing, true );
186  painter->scale( dpmm, dpmm );
187 
188  // rendering
189  QgsLegendSettings settings = legendSettings();
191  ctx.painter = painter.get();
192  nodeModel.drawSymbol( settings, &ctx, size.height() / dpmm );
193  painter->end();
194 
195  return image.release();
196  }
197 
199  {
200  // get layers
201  std::unique_ptr<QgsWmsRestorer> restorer;
202  restorer.reset( new QgsWmsRestorer( mContext ) );
203 
204  // configure layers
205  QList<QgsMapLayer *> layers = mContext.layersToRender();
206  configureLayers( layers );
207 
208  // init renderer
209  QgsLegendSettings settings = legendSettings();
210  QgsLegendRenderer renderer( &model, settings );
211 
212  // rendering
213  QgsRenderContext renderContext;
214  return renderer.exportLegendToJson( renderContext );
215  }
216 
217  void QgsRenderer::runHitTest( const QgsMapSettings &mapSettings, HitTest &hitTest ) const
218  {
219  QgsRenderContext context = QgsRenderContext::fromMapSettings( mapSettings );
220 
221  for ( const QString &id : mapSettings.layerIds() )
222  {
223  QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( mProject->mapLayer( id ) );
224  if ( !vl || !vl->renderer() )
225  continue;
226 
227  if ( vl->hasScaleBasedVisibility() && vl->isInScaleRange( mapSettings.scale() ) )
228  {
229  hitTest[vl] = SymbolSet(); // no symbols -> will not be shown
230  continue;
231  }
232 
233  QgsCoordinateTransform tr = mapSettings.layerTransform( vl );
234  context.setCoordinateTransform( tr );
235  context.setExtent( tr.transformBoundingBox( mapSettings.extent(), Qgis::TransformDirection::Reverse ) );
236 
237  SymbolSet &usedSymbols = hitTest[vl];
238  runHitTestLayer( vl, usedSymbols, context );
239  }
240  }
241 
242  void QgsRenderer::runHitTestLayer( QgsVectorLayer *vl, SymbolSet &usedSymbols, QgsRenderContext &context ) const
243  {
244  std::unique_ptr< QgsFeatureRenderer > r( vl->renderer()->clone() );
245  bool moreSymbolsPerFeature = r->capabilities() & QgsFeatureRenderer::MoreSymbolsPerFeature;
246  r->startRender( context, vl->fields() );
247  QgsFeature f;
248  QgsFeatureRequest request( context.extent() );
249  request.setFlags( QgsFeatureRequest::ExactIntersect );
250  QgsFeatureIterator fi = vl->getFeatures( request );
251  while ( fi.nextFeature( f ) )
252  {
253  context.expressionContext().setFeature( f );
254  if ( moreSymbolsPerFeature )
255  {
256  for ( QgsSymbol *s : r->originalSymbolsForFeature( f, context ) )
257  usedSymbols.insert( QgsSymbolLayerUtils::symbolProperties( s ) );
258  }
259  else
260  usedSymbols.insert( QgsSymbolLayerUtils::symbolProperties( r->originalSymbolForFeature( f, context ) ) );
261  }
262  r->stopRender( context );
263  }
264 
266  {
267  // check size
268  if ( ! mContext.isValidWidthHeight() )
269  {
271  QStringLiteral( "The requested map size is too large" ) );
272  }
273 
274  // init layer restorer before doing anything
275  std::unique_ptr<QgsWmsRestorer> restorer;
276  restorer.reset( new QgsWmsRestorer( mContext ) );
277 
278  // configure layers
279  QgsMapSettings mapSettings;
281  QList<QgsMapLayer *> layers = mContext.layersToRender();
282  configureLayers( layers, &mapSettings );
283 
284  // create the output image and the painter
285  std::unique_ptr<QPainter> painter;
286  std::unique_ptr<QImage> image( createImage( mContext.mapSize() ) );
287 
288  // configure map settings (background, DPI, ...)
289  configureMapSettings( image.get(), mapSettings );
290 
291  // add layers to map settings
292  mapSettings.setLayers( layers );
293 
294  // run hit tests
296  runHitTest( mapSettings, symbols );
297 
298  return symbols;
299  }
300 
301  QByteArray QgsRenderer::getPrint()
302  {
303  // init layer restorer before doing anything
304  std::unique_ptr<QgsWmsRestorer> restorer;
305  restorer.reset( new QgsWmsRestorer( mContext ) );
306 
307  // GetPrint request needs a template parameter
308  const QString templateName = mWmsParameters.composerTemplate();
309  if ( templateName.isEmpty() )
310  {
313  }
314  else if ( QgsServerProjectUtils::wmsRestrictedComposers( *mProject ).contains( templateName ) )
315  {
317  mWmsParameters[QgsWmsParameter::TEMPLATE ] );
318  }
319 
320  // check template
321  const QgsLayoutManager *lManager = mProject->layoutManager();
322  QgsPrintLayout *sourceLayout( dynamic_cast<QgsPrintLayout *>( lManager->layoutByName( templateName ) ) );
323  if ( !sourceLayout )
324  {
326  mWmsParameters[QgsWmsParameter::TEMPLATE ] );
327  }
328 
329  // Check that layout has at least one page
330  if ( sourceLayout->pageCollection()->pageCount() < 1 )
331  {
333  QStringLiteral( "The template has no pages" ) );
334  }
335 
336  std::unique_ptr<QgsPrintLayout> layout( sourceLayout->clone() );
337 
338  //atlas print?
339  QgsLayoutAtlas *atlas = nullptr;
340  QStringList atlasPk = mWmsParameters.atlasPk();
341  if ( !atlasPk.isEmpty() ) //atlas print requested?
342  {
343  atlas = layout->atlas();
344  if ( !atlas || !atlas->enabled() )
345  {
346  //error
348  QStringLiteral( "The template has no atlas enabled" ) );
349  }
350 
351  QgsVectorLayer *cLayer = atlas->coverageLayer();
352  if ( !cLayer )
353  {
355  QStringLiteral( "The atlas has no coverage layer" ) );
356  }
357 
358  int maxAtlasFeatures = QgsServerProjectUtils::wmsMaxAtlasFeatures( *mProject );
359  if ( atlasPk.size() == 1 && atlasPk.at( 0 ) == QLatin1String( "*" ) )
360  {
361  atlas->setFilterFeatures( false );
362  atlas->updateFeatures();
363  if ( atlas->count() > maxAtlasFeatures )
364  {
366  QString( "The project configuration allows printing maximum %1 atlas features at a time" ).arg( maxAtlasFeatures ) );
367  }
368  }
369  else
370  {
371  const QgsAttributeList pkIndexes = cLayer->primaryKeyAttributes();
372  if ( pkIndexes.size() == 0 )
373  {
374  QgsDebugMsgLevel( QStringLiteral( "Atlas print: layer %1 has no primary key attributes" ).arg( cLayer->name() ), 2 );
375  }
376 
377  // Handles the pk-less case
378  const int pkIndexesSize {std::max( pkIndexes.size(), 1 )};
379 
380  QStringList pkAttributeNames;
381  for ( int pkIndex : std::as_const( pkIndexes ) )
382  {
383  pkAttributeNames.append( cLayer->fields().at( pkIndex ).name() );
384  }
385 
386  const int nAtlasFeatures = atlasPk.size() / pkIndexesSize;
387  if ( nAtlasFeatures * pkIndexesSize != atlasPk.size() ) //Test if atlasPk.size() is a multiple of pkIndexesSize. Bail out if not
388  {
390  QStringLiteral( "Wrong number of ATLAS_PK parameters" ) );
391  }
392 
393  //number of atlas features might be restricted
394  if ( nAtlasFeatures > maxAtlasFeatures )
395  {
397  QString( "%1 atlas features have been requested, but the project configuration only allows printing %2 atlas features at a time" )
398  .arg( nAtlasFeatures ).arg( maxAtlasFeatures ) );
399  }
400 
401  QString filterString;
402  int currentAtlasPk = 0;
403 
404  for ( int i = 0; i < nAtlasFeatures; ++i )
405  {
406  if ( i > 0 )
407  {
408  filterString.append( " OR " );
409  }
410 
411  filterString.append( "( " );
412 
413  // If the layer has no PK attributes, assume FID
414  if ( pkAttributeNames.isEmpty() )
415  {
416  filterString.append( QStringLiteral( "$id = %1" ).arg( atlasPk.at( currentAtlasPk ) ) );
417  ++currentAtlasPk;
418  }
419  else
420  {
421  for ( int j = 0; j < pkIndexes.size(); ++j )
422  {
423  if ( j > 0 )
424  {
425  filterString.append( " AND " );
426  }
427  filterString.append( QgsExpression::createFieldEqualityExpression( pkAttributeNames.at( j ), atlasPk.at( currentAtlasPk ) ) );
428  ++currentAtlasPk;
429  }
430  }
431 
432  filterString.append( " )" );
433  }
434 
435  atlas->setFilterFeatures( true );
436  QString errorString;
437  atlas->setFilterExpression( filterString, errorString );
438  if ( !errorString.isEmpty() )
439  {
440  throw QgsException( QStringLiteral( "An error occurred during the Atlas print: %1" ).arg( errorString ) );
441  }
442  }
443  }
444 
445  // configure layers
446  QgsMapSettings mapSettings;
448  QList<QgsMapLayer *> layers = mContext.layersToRender();
449  configureLayers( layers, &mapSettings );
450 
451  // configure map settings (background, DPI, ...)
452  std::unique_ptr<QImage> image( new QImage() );
453  configureMapSettings( image.get(), mapSettings );
454 
455  // add layers to map settings
456  mapSettings.setLayers( layers );
457 
458  // configure layout
459  configurePrintLayout( layout.get(), mapSettings, atlas );
460 
461  QgsLayoutRenderContext &layoutRendererContext = layout->renderContext();
463  const QList<QgsMapLayer *> lyrs = mapSettings.layers();
464 
465 #ifdef HAVE_SERVER_PYTHON_PLUGINS
466  mContext.accessControl()->resolveFilterFeatures( lyrs );
467  filters.addProvider( mContext.accessControl() );
468 #endif
469 
470  QHash<const QgsVectorLayer *, QStringList> fltrs;
471  for ( QgsMapLayer *l : lyrs )
472  {
473  if ( QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( l ) )
474  {
475  fltrs.insert( vl, dimensionFilter( vl ) );
476  }
477  }
478 
479  QgsDimensionFilter dimFilter( fltrs );
480  filters.addProvider( &dimFilter );
481  layoutRendererContext.setFeatureFilterProvider( &filters );
482 
483  // Get the temporary output file
484  const QgsWmsParameters::Format format = mWmsParameters.format();
485  const QString extension = QgsWmsParameters::formatAsString( format ).toLower();
486 
487  QTemporaryFile tempOutputFile( QDir::tempPath() + '/' + QStringLiteral( "XXXXXX.%1" ).arg( extension ) );
488  if ( !tempOutputFile.open() )
489  {
490  throw QgsException( QStringLiteral( "Could not open temporary file for the GetPrint request." ) );
491 
492  }
493 
494  QString exportError;
495  if ( format == QgsWmsParameters::SVG )
496  {
497  // Settings for the layout exporter
499  if ( !mWmsParameters.dpi().isEmpty() )
500  {
501  bool ok;
502  double dpi( mWmsParameters.dpi().toDouble( &ok ) );
503  if ( ok )
504  exportSettings.dpi = dpi;
505  }
506  // Draw selections
508  if ( atlas )
509  {
510  //export first page of atlas
511  atlas->beginRender();
512  if ( atlas->next() )
513  {
514  QgsLayoutExporter atlasSvgExport( atlas->layout() );
515  atlasSvgExport.exportToSvg( tempOutputFile.fileName(), exportSettings );
516  }
517  }
518  else
519  {
520  QgsLayoutExporter exporter( layout.get() );
521  exporter.exportToSvg( tempOutputFile.fileName(), exportSettings );
522  }
523  }
524  else if ( format == QgsWmsParameters::PNG || format == QgsWmsParameters::JPG )
525  {
526  // Settings for the layout exporter
528 
529  // Get the dpi from input or use the default
530  double dpi( layout->renderContext().dpi( ) );
531  if ( !mWmsParameters.dpi().isEmpty() )
532  {
533  bool ok;
534  double _dpi = mWmsParameters.dpi().toDouble( &ok );
535  if ( ok )
536  dpi = _dpi;
537  }
538  exportSettings.dpi = dpi;
539  // Draw selections
541  // Destination image size in px
542  QgsLayoutSize layoutSize( layout->pageCollection()->page( 0 )->sizeWithUnits() );
543 
544  QgsLayoutMeasurement width( layout->convertFromLayoutUnits( layoutSize.width(), QgsUnitTypes::LayoutUnit::LayoutMillimeters ) );
545  QgsLayoutMeasurement height( layout->convertFromLayoutUnits( layoutSize.height(), QgsUnitTypes::LayoutUnit::LayoutMillimeters ) );
546 
547  const QSize imageSize = QSize( static_cast<int>( width.length() * dpi / 25.4 ), static_cast<int>( height.length() * dpi / 25.4 ) );
548 
549  const QString paramWidth = mWmsParameters.width();
550  const QString paramHeight = mWmsParameters.height();
551 
552  // Prefer width and height from the http request
553  // Fallback to predefined values from layout
554  // Preserve aspect ratio if only one value is specified
555  if ( !paramWidth.isEmpty() && !paramHeight.isEmpty() )
556  {
557  exportSettings.imageSize = QSize( paramWidth.toInt(), paramHeight.toInt() );
558  }
559  else if ( !paramWidth.isEmpty() && paramHeight.isEmpty() )
560  {
561  exportSettings.imageSize = QSize( paramWidth.toInt(), static_cast<double>( paramWidth.toInt() ) / imageSize.width() * imageSize.height() );
562  }
563  else if ( paramWidth.isEmpty() && !paramHeight.isEmpty() )
564  {
565  exportSettings.imageSize = QSize( static_cast<double>( paramHeight.toInt() ) / imageSize.height() * imageSize.width(), paramHeight.toInt() );
566  }
567  else
568  {
569  exportSettings.imageSize = imageSize;
570  }
571 
572  // Export first page only (unless it's a pdf, see below)
573  exportSettings.pages.append( 0 );
574  if ( atlas )
575  {
576  //only can give back one page in server rendering
577  atlas->beginRender();
578  if ( atlas->next() )
579  {
580  QgsLayoutExporter atlasPngExport( atlas->layout() );
581  atlasPngExport.exportToImage( tempOutputFile.fileName(), exportSettings );
582  }
583  else
584  {
585  throw QgsServiceException( QStringLiteral( "Bad request" ), QStringLiteral( "Atlas error: empty atlas." ), QString(), 400 );
586  }
587  }
588  else
589  {
590  QgsLayoutExporter exporter( layout.get() );
591  exporter.exportToImage( tempOutputFile.fileName(), exportSettings );
592  }
593  }
594  else if ( format == QgsWmsParameters::PDF )
595  {
596  // Settings for the layout exporter
598  // TODO: handle size from input ?
599  if ( !mWmsParameters.dpi().isEmpty() )
600  {
601  bool ok;
602  double dpi( mWmsParameters.dpi().toDouble( &ok ) );
603  if ( ok )
604  exportSettings.dpi = dpi;
605  }
606  // Draw selections
608  // Print as raster
609  exportSettings.rasterizeWholeImage = layout->customProperty( QStringLiteral( "rasterize" ), false ).toBool();
610 
611  // Export all pages
612  if ( atlas )
613  {
614  QgsLayoutExporter::exportToPdf( atlas, tempOutputFile.fileName(), exportSettings, exportError );
615  }
616  else
617  {
618  QgsLayoutExporter exporter( layout.get() );
619  exporter.exportToPdf( tempOutputFile.fileName(), exportSettings );
620  }
621  }
622  else //unknown format
623  {
625  mWmsParameters[QgsWmsParameter::FORMAT] );
626  }
627 
628  if ( atlas )
629  {
630  handlePrintErrors( atlas->layout() );
631  }
632  else
633  {
634  handlePrintErrors( layout.get() );
635  }
636 
637  return tempOutputFile.readAll();
638  }
639 
640  bool QgsRenderer::configurePrintLayout( QgsPrintLayout *c, const QgsMapSettings &mapSettings, bool atlasPrint )
641  {
642 
643  c->renderContext().setSelectionColor( mapSettings.selectionColor() );
644  // Maps are configured first
645  QList<QgsLayoutItemMap *> maps;
646  c->layoutItems<QgsLayoutItemMap>( maps );
647  // Layout maps now use a string UUID as "id", let's assume that the first map
648  // has id 0 and so on ...
649  int mapId = 0;
650 
651  for ( const auto &map : std::as_const( maps ) )
652  {
653  QgsWmsParametersComposerMap cMapParams = mWmsParameters.composerMapParameters( mapId );
654  mapId++;
655 
656  // If there are no configured layers, we take layers from unprefixed LAYER(S) if any
657  if ( cMapParams.mLayers.isEmpty() )
658  {
659  cMapParams.mLayers = mWmsParameters.composerMapParameters( -1 ).mLayers;
660  }
661 
662  if ( !atlasPrint || !map->atlasDriven() ) //No need to extent, scal, rotation set with atlas feature
663  {
664  //map extent is mandatory
665  if ( !cMapParams.mHasExtent )
666  {
667  //remove map from composition if not referenced by the request
668  c->removeLayoutItem( map );
669  continue;
670  }
671  // Change CRS of map set to "project CRS" to match requested CRS
672  // (if map has a valid preset crs then we keep this crs and don't use the
673  // requested crs for this map item)
674  if ( mapSettings.destinationCrs().isValid() && !map->presetCrs().isValid() )
675  map->setCrs( mapSettings.destinationCrs() );
676 
677  QgsRectangle r( cMapParams.mExtent );
678  if ( mWmsParameters.versionAsNumber() >= QgsProjectVersion( 1, 3, 0 ) &&
679  mapSettings.destinationCrs().hasAxisInverted() )
680  {
681  r.invert();
682  }
683  map->setExtent( r );
684 
685  // scale
686  if ( cMapParams.mScale > 0 )
687  {
688  map->setScale( static_cast<double>( cMapParams.mScale ) );
689  }
690 
691  // rotation
692  if ( cMapParams.mRotation )
693  {
694  map->setMapRotation( cMapParams.mRotation );
695  }
696  }
697 
698  if ( !map->keepLayerSet() )
699  {
700  QList<QgsMapLayer *> layerSet;
701 
702  for ( const auto &layer : std::as_const( cMapParams.mLayers ) )
703  {
704  if ( mContext.isValidGroup( layer.mNickname ) )
705  {
706  QList<QgsMapLayer *> layersFromGroup;
707 
708  const QList<QgsMapLayer *> cLayersFromGroup = mContext.layersFromGroup( layer.mNickname );
709  for ( QgsMapLayer *layerFromGroup : cLayersFromGroup )
710  {
711 
712  if ( ! layerFromGroup )
713  {
714  continue;
715  }
716 
717  layersFromGroup.push_front( layerFromGroup );
718  }
719 
720  if ( !layersFromGroup.isEmpty() )
721  {
722  layerSet.append( layersFromGroup );
723  }
724  }
725  else
726  {
727  QgsMapLayer *mlayer = mContext.layer( layer.mNickname );
728 
729  if ( ! mlayer )
730  {
731  continue;
732  }
733 
734  setLayerStyle( mlayer, layer.mStyle );
735  layerSet << mlayer;
736  }
737  }
738 
739  std::reverse( layerSet.begin(), layerSet.end() );
740 
741  // If the map is set to follow preset we need to disable follow preset and manually
742  // configure the layers here or the map item internal logic will override and get
743  // the layers from the map theme.
744  QMap<QString, QString> layersStyle;
745  if ( map->followVisibilityPreset() )
746  {
747  const QString presetName = map->followVisibilityPresetName();
748  if ( layerSet.isEmpty() )
749  {
750  // Get the layers from the theme
751  const QgsExpressionContext ex { map->createExpressionContext() };
752  layerSet = map->layersToRender( &ex );
753  }
754  // Disable the theme
755  map->setFollowVisibilityPreset( false );
756 
757  // Collect the style of each layer in the theme that has been disabled
758  const QList<QgsMapThemeCollection::MapThemeLayerRecord> mapThemeRecords = QgsProject::instance()->mapThemeCollection()->mapThemeState( presetName ).layerRecords();
759  for ( const auto &layerMapThemeRecord : std::as_const( mapThemeRecords ) )
760  {
761  if ( layerSet.contains( layerMapThemeRecord.layer() ) )
762  {
763  layersStyle.insert( layerMapThemeRecord.layer()->id(),
764  layerMapThemeRecord.layer()->styleManager()->style( layerMapThemeRecord.currentStyle ).xmlData() );
765  }
766  }
767  }
768 
769  // Handle highlight layers
770  const QList< QgsMapLayer *> highlights = highlightLayers( cMapParams.mHighlightLayers );
771  for ( const auto &hl : std::as_const( highlights ) )
772  {
773  layerSet.prepend( hl );
774  }
775 
776  map->setLayers( layerSet );
777  map->setKeepLayerSet( true );
778 
779  // Set style override if a particular style should be used due to a map theme.
780  // It will actualize linked legend symbols too.
781  if ( !layersStyle.isEmpty() )
782  {
783  map->setLayerStyleOverrides( layersStyle );
784  map->setKeepLayerStyles( true );
785  }
786  }
787 
788  //grid space x / y
789  if ( cMapParams.mGridX > 0 && cMapParams.mGridY > 0 )
790  {
791  map->grid()->setIntervalX( static_cast<double>( cMapParams.mGridX ) );
792  map->grid()->setIntervalY( static_cast<double>( cMapParams.mGridY ) );
793  }
794  }
795 
796  // Labels
797  QList<QgsLayoutItemLabel *> labels;
798  c->layoutItems<QgsLayoutItemLabel>( labels );
799  for ( const auto &label : std::as_const( labels ) )
800  {
801  bool ok = false;
802  const QString labelId = label->id();
803  const QString labelParam = mWmsParameters.layoutParameter( labelId, ok );
804 
805  if ( !ok )
806  continue;
807 
808  if ( labelParam.isEmpty() )
809  {
810  //remove exported labels referenced in the request
811  //but with empty string
812  c->removeItem( label );
813  delete label;
814  continue;
815  }
816 
817  label->setText( labelParam );
818  }
819 
820  // HTMLs
821  QList<QgsLayoutItemHtml *> htmls;
822  c->layoutObjects<QgsLayoutItemHtml>( htmls );
823  for ( const auto &html : std::as_const( htmls ) )
824  {
825  if ( html->frameCount() == 0 )
826  continue;
827 
828  QgsLayoutFrame *htmlFrame = html->frame( 0 );
829  bool ok = false;
830  const QString htmlId = htmlFrame->id();
831  const QString url = mWmsParameters.layoutParameter( htmlId, ok );
832 
833  if ( !ok )
834  {
835  html->update();
836  continue;
837  }
838 
839  //remove exported Htmls referenced in the request
840  //but with empty string
841  if ( url.isEmpty() )
842  {
843  c->removeMultiFrame( html );
844  delete html;
845  continue;
846  }
847 
848  QUrl newUrl( url );
849  html->setUrl( newUrl );
850  html->update();
851  }
852 
853 
854  // legends
855  QList<QgsLayoutItemLegend *> legends;
856  c->layoutItems<QgsLayoutItemLegend>( legends );
857  for ( const auto &legend : std::as_const( legends ) )
858  {
859  if ( legend->autoUpdateModel() )
860  {
861  // the legend has an auto-update model
862  // we will update it with map's layers
863  const QgsLayoutItemMap *map = legend->linkedMap();
864  if ( !map )
865  {
866  continue;
867  }
868 
869  legend->setAutoUpdateModel( false );
870 
871  // get model and layer tree root of the legend
872  QgsLegendModel *model = legend->model();
873  QStringList layerSet;
874  QList<QgsMapLayer *> mapLayers;
875  if ( map->layers().isEmpty() )
876  {
877  // in QGIS desktop, each layer has its legend, including invisible layers
878  // and using maptheme, legend items are automatically filtered
879  mapLayers = mProject->mapLayers( true ).values();
880  }
881  else
882  {
883  mapLayers = map->layers();
884  }
885  const QList<QgsMapLayer *> layerList = mapLayers;
886  for ( const auto &layer : layerList )
887  layerSet << layer->id();
888 
889  //setLayerIdsToLegendModel( model, layerSet, map->scale() );
890 
891  // get model and layer tree root of the legend
892  QgsLayerTree *root = model->rootGroup();
893 
894  // get layerIds find in the layer tree root
895  const QStringList layerIds = root->findLayerIds();
896 
897  // find the layer in the layer tree
898  // remove it if the layer id is not in map layerIds
899  for ( const auto &layerId : layerIds )
900  {
901  QgsLayerTreeLayer *nodeLayer = root->findLayer( layerId );
902  if ( !nodeLayer )
903  {
904  continue;
905  }
906  if ( !layerSet.contains( layerId ) )
907  {
908  qobject_cast<QgsLayerTreeGroup *>( nodeLayer->parent() )->removeChildNode( nodeLayer );
909  }
910  else
911  {
912  QgsMapLayer *layer = nodeLayer->layer();
913  if ( !layer->isInScaleRange( map->scale() ) )
914  {
915  qobject_cast<QgsLayerTreeGroup *>( nodeLayer->parent() )->removeChildNode( nodeLayer );
916  }
917  }
918  }
920  }
921  }
922  return true;
923  }
924 
925  QImage *QgsRenderer::getMap()
926  {
927  // check size
928  if ( ! mContext.isValidWidthHeight() )
929  {
931  QStringLiteral( "The requested map size is too large" ) );
932  }
933 
934  // init layer restorer before doing anything
935  std::unique_ptr<QgsWmsRestorer> restorer;
936  restorer.reset( new QgsWmsRestorer( mContext ) );
937 
938  // configure layers
939  QList<QgsMapLayer *> layers = mContext.layersToRender();
940 
941  QgsMapSettings mapSettings;
943  configureLayers( layers, &mapSettings );
944 
945  // create the output image and the painter
946  std::unique_ptr<QPainter> painter;
947  std::unique_ptr<QImage> image( createImage( mContext.mapSize() ) );
948 
949  // configure map settings (background, DPI, ...)
950  configureMapSettings( image.get(), mapSettings );
951 
952  // add layers to map settings
953  mapSettings.setLayers( layers );
954 
955  // rendering step for layers
956  painter.reset( layersRendering( mapSettings, *image ) );
957 
958  // rendering step for annotations
959  annotationsRendering( painter.get(), mapSettings );
960 
961  // painting is terminated
962  painter->end();
963 
964  // scale output image if necessary (required by WMS spec)
965  QImage *scaledImage = scaleImage( image.get() );
966  if ( scaledImage )
967  image.reset( scaledImage );
968 
969  // return
970  return image.release();
971  }
972 
973  std::unique_ptr<QgsDxfExport> QgsRenderer::getDxf()
974  {
975  // init layer restorer before doing anything
976  std::unique_ptr<QgsWmsRestorer> restorer;
977  restorer.reset( new QgsWmsRestorer( mContext ) );
978 
979  // configure layers
980  QList<QgsMapLayer *> layers = mContext.layersToRender();
981  configureLayers( layers );
982 
983  // get dxf layers
984  const QStringList attributes = mWmsParameters.dxfLayerAttributes();
985  QList< QgsDxfExport::DxfLayer > dxfLayers;
986  int layerIdx = -1;
987  for ( QgsMapLayer *layer : layers )
988  {
989  layerIdx++;
990  if ( layer->type() != QgsMapLayerType::VectorLayer )
991  continue;
992 
993  // cast for dxf layers
994  QgsVectorLayer *vlayer = static_cast<QgsVectorLayer *>( layer );
995 
996  // get the layer attribute used in dxf
997  int layerAttribute = -1;
998  if ( attributes.size() > layerIdx )
999  {
1000  layerAttribute = vlayer->fields().indexFromName( attributes[ layerIdx ] );
1001  }
1002 
1003  dxfLayers.append( QgsDxfExport::DxfLayer( vlayer, layerAttribute ) );
1004  }
1005 
1006  //map extent
1007  QgsRectangle mapExtent = mWmsParameters.bboxAsRectangle();
1008 
1009  QString crs = mWmsParameters.crs();
1010  if ( crs.compare( QStringLiteral( "CRS:84" ), Qt::CaseInsensitive ) == 0 )
1011  {
1012  crs = QStringLiteral( "EPSG:4326" );
1013  mapExtent.invert();
1014  }
1015  else if ( crs.isEmpty() )
1016  {
1017  crs = QStringLiteral( "EPSG:4326" );
1018  }
1019 
1021 
1022  if ( !outputCRS.isValid() )
1023  {
1025  QgsWmsParameter parameter;
1026 
1027  if ( mWmsParameters.versionAsNumber() >= QgsProjectVersion( 1, 3, 0 ) )
1028  {
1030  parameter = mWmsParameters[ QgsWmsParameter::CRS ];
1031  }
1032  else
1033  {
1035  parameter = mWmsParameters[ QgsWmsParameter::SRS ];
1036  }
1037 
1038  throw QgsBadRequestException( code, parameter );
1039  }
1040 
1041  //then set destinationCrs
1042 
1043  // Change x- and y- of BBOX for WMS 1.3.0 if axis inverted
1044  if ( mWmsParameters.versionAsNumber() >= QgsProjectVersion( 1, 3, 0 ) && outputCRS.hasAxisInverted() )
1045  {
1046  mapExtent.invert();
1047  }
1048 
1049 
1050  // add layers to dxf
1051  std::unique_ptr<QgsDxfExport> dxf = std::make_unique<QgsDxfExport>();
1052  dxf->setExtent( mapExtent );
1053  dxf->setDestinationCrs( outputCRS );
1054  dxf->addLayers( dxfLayers );
1055  dxf->setLayerTitleAsName( mWmsParameters.dxfUseLayerTitleAsName() );
1056  dxf->setSymbologyExport( mWmsParameters.dxfMode() );
1057  if ( mWmsParameters.dxfFormatOptions().contains( QgsWmsParameters::DxfFormatOption::SCALE ) )
1058  {
1059  dxf->setSymbologyScale( mWmsParameters.dxfScale() );
1060  }
1061 
1062  dxf->setForce2d( mWmsParameters.isForce2D() );
1063  QgsDxfExport::Flags flags;
1064  if ( mWmsParameters.noMText() )
1065  flags.setFlag( QgsDxfExport::Flag::FlagNoMText );
1066 
1067  dxf->setFlags( flags );
1068 
1069  return dxf;
1070  }
1071 
1072  static void infoPointToMapCoordinates( int i, int j, QgsPointXY *infoPoint, const QgsMapSettings &mapSettings )
1073  {
1074  //check if i, j are in the pixel range of the image
1075  if ( i < 0 || i > mapSettings.outputSize().width() )
1076  {
1077  QgsWmsParameter param( QgsWmsParameter::I );
1078  param.mValue = i;
1080  param );
1081  }
1082 
1083  if ( j < 0 || j > mapSettings.outputSize().height() )
1084  {
1085  QgsWmsParameter param( QgsWmsParameter::J );
1086  param.mValue = j;
1088  param );
1089  }
1090 
1091  double xRes = mapSettings.extent().width() / mapSettings.outputSize().width();
1092  double yRes = mapSettings.extent().height() / mapSettings.outputSize().height();
1093  infoPoint->setX( mapSettings.extent().xMinimum() + i * xRes + xRes / 2.0 );
1094  infoPoint->setY( mapSettings.extent().yMaximum() - j * yRes - yRes / 2.0 );
1095  }
1096 
1097  QByteArray QgsRenderer::getFeatureInfo( const QString &version )
1098  {
1099  // Verifying Mandatory parameters
1100  // The QUERY_LAYERS parameter is Mandatory
1101  if ( mWmsParameters.queryLayersNickname().isEmpty() )
1102  {
1104  mWmsParameters[QgsWmsParameter::QUERY_LAYERS] );
1105  }
1106 
1107  // The I/J parameters are Mandatory if they are not replaced by X/Y or FILTER or FILTER_GEOM
1108  const bool ijDefined = !mWmsParameters.i().isEmpty() && !mWmsParameters.j().isEmpty();
1109  const bool xyDefined = !mWmsParameters.x().isEmpty() && !mWmsParameters.y().isEmpty();
1110  const bool filtersDefined = !mWmsParameters.filters().isEmpty();
1111  const bool filterGeomDefined = !mWmsParameters.filterGeom().isEmpty();
1113  if ( !ijDefined && !xyDefined && !filtersDefined && !filterGeomDefined )
1114  {
1115  QgsWmsParameter parameter = mWmsParameters[QgsWmsParameter::I];
1116 
1117  if ( mWmsParameters.j().isEmpty() )
1118  parameter = mWmsParameters[QgsWmsParameter::J];
1119 
1121  }
1122 
1123  const QgsWmsParameters::Format infoFormat = mWmsParameters.infoFormat();
1124  if ( infoFormat == QgsWmsParameters::Format::NONE )
1125  {
1127  mWmsParameters[QgsWmsParameter::INFO_FORMAT] );
1128  }
1129 
1130  // create the mapSettings and the output image
1131  std::unique_ptr<QImage> outputImage( createImage( mContext.mapSize() ) );
1132 
1133  // init layer restorer before doing anything
1134  std::unique_ptr<QgsWmsRestorer> restorer;
1135  restorer.reset( new QgsWmsRestorer( mContext ) );
1136 
1137  // The CRS parameter is considered as mandatory in configureMapSettings
1138  // but in the case of filter parameter, CRS parameter has not to be mandatory
1139  bool mandatoryCrsParam = true;
1140  if ( filtersDefined && !ijDefined && !xyDefined && mWmsParameters.crs().isEmpty() )
1141  {
1142  mandatoryCrsParam = false;
1143  }
1144 
1145  // configure map settings (background, DPI, ...)
1146  QgsMapSettings mapSettings;
1148  configureMapSettings( outputImage.get(), mapSettings, mandatoryCrsParam );
1149 
1150  // compute scale denominator
1151  QgsScaleCalculator scaleCalc( ( outputImage->logicalDpiX() + outputImage->logicalDpiY() ) / 2, mapSettings.destinationCrs().mapUnits() );
1152  const double scaleDenominator = scaleCalc.calculate( mWmsParameters.bboxAsRectangle(), outputImage->width() );
1153 
1154  // configure layers
1155  QgsWmsRenderContext context = mContext;
1156  context.setScaleDenominator( scaleDenominator );
1157 
1158  QList<QgsMapLayer *> layers = context.layersToRender();
1159  configureLayers( layers, &mapSettings );
1160 
1161  // add layers to map settings
1162  mapSettings.setLayers( layers );
1163 
1164 #ifdef HAVE_SERVER_PYTHON_PLUGINS
1165  mContext.accessControl()->resolveFilterFeatures( mapSettings.layers() );
1166 #endif
1167 
1168  QDomDocument result = featureInfoDocument( layers, mapSettings, outputImage.get(), version );
1169 
1170  QByteArray ba;
1171 
1172  if ( infoFormat == QgsWmsParameters::Format::TEXT )
1173  ba = convertFeatureInfoToText( result );
1174  else if ( infoFormat == QgsWmsParameters::Format::HTML )
1175  ba = convertFeatureInfoToHtml( result );
1176  else if ( infoFormat == QgsWmsParameters::Format::JSON )
1177  ba = convertFeatureInfoToJson( layers, result );
1178  else
1179  ba = result.toByteArray();
1180 
1181  return ba;
1182  }
1183 
1184  QImage *QgsRenderer::createImage( const QSize &size ) const
1185  {
1186  std::unique_ptr<QImage> image;
1187 
1188  // use alpha channel only if necessary because it slows down performance
1189  QgsWmsParameters::Format format = mWmsParameters.format();
1190  bool transparent = mWmsParameters.transparentAsBool();
1191 
1192  if ( transparent && format != QgsWmsParameters::JPG )
1193  {
1194  image = std::make_unique<QImage>( size, QImage::Format_ARGB32_Premultiplied );
1195  image->fill( 0 );
1196  }
1197  else
1198  {
1199  image = std::make_unique<QImage>( size, QImage::Format_RGB32 );
1200  image->fill( mWmsParameters.backgroundColorAsColor() );
1201  }
1202 
1203  // Check that image was correctly created
1204  if ( image->isNull() )
1205  {
1206  throw QgsException( QStringLiteral( "createImage: image could not be created, check for out of memory conditions" ) );
1207  }
1208 
1209  const int dpm = static_cast<int>( mContext.dotsPerMm() * 1000.0 );
1210  image->setDotsPerMeterX( dpm );
1211  image->setDotsPerMeterY( dpm );
1212 
1213  return image.release();
1214  }
1215 
1216  void QgsRenderer::configureMapSettings( const QPaintDevice *paintDevice, QgsMapSettings &mapSettings, bool mandatoryCrsParam )
1217  {
1218  if ( !paintDevice )
1219  {
1220  throw QgsException( QStringLiteral( "configureMapSettings: no paint device" ) );
1221  }
1222 
1223  mapSettings.setOutputSize( QSize( paintDevice->width(), paintDevice->height() ) );
1224  // Recalculate from input DPI: do not take the (integer) value from paint device
1225  // because it loose precision!
1226  mapSettings.setOutputDpi( mContext.dotsPerMm() * 25.4 );
1227 
1228  //map extent
1229  QgsRectangle mapExtent = mWmsParameters.bboxAsRectangle();
1230  if ( !mWmsParameters.bbox().isEmpty() && mapExtent.isEmpty() )
1231  {
1233  mWmsParameters[QgsWmsParameter::BBOX] );
1234  }
1235 
1236  QString crs = mWmsParameters.crs();
1237  if ( crs.compare( "CRS:84", Qt::CaseInsensitive ) == 0 )
1238  {
1239  crs = QString( "EPSG:4326" );
1240  mapExtent.invert();
1241  }
1242  else if ( crs.isEmpty() && !mandatoryCrsParam )
1243  {
1244  crs = QString( "EPSG:4326" );
1245  }
1246 
1247  QgsCoordinateReferenceSystem outputCRS;
1248 
1249  //wms spec says that CRS parameter is mandatory.
1251  if ( !outputCRS.isValid() )
1252  {
1254  QgsWmsParameter parameter;
1255 
1256  if ( mWmsParameters.versionAsNumber() >= QgsProjectVersion( 1, 3, 0 ) )
1257  {
1259  parameter = mWmsParameters[ QgsWmsParameter::CRS ];
1260  }
1261  else
1262  {
1264  parameter = mWmsParameters[ QgsWmsParameter::SRS ];
1265  }
1266 
1267  throw QgsBadRequestException( code, parameter );
1268  }
1269 
1270  //then set destinationCrs
1271  mapSettings.setDestinationCrs( outputCRS );
1272 
1273  // Change x- and y- of BBOX for WMS 1.3.0 if axis inverted
1274  if ( mWmsParameters.versionAsNumber() >= QgsProjectVersion( 1, 3, 0 ) && outputCRS.hasAxisInverted() )
1275  {
1276  mapExtent.invert();
1277  }
1278 
1279  mapSettings.setExtent( mapExtent );
1280 
1281  // set the extent buffer
1282  mapSettings.setExtentBuffer( mContext.mapTileBuffer( paintDevice->width() ) );
1283 
1284  /* Define the background color
1285  * Transparent or colored
1286  */
1287  QgsWmsParameters::Format format = mWmsParameters.format();
1288  bool transparent = mWmsParameters.transparentAsBool();
1289  QColor backgroundColor = mWmsParameters.backgroundColorAsColor();
1290 
1291  //set background color
1292  if ( transparent && format != QgsWmsParameters::JPG )
1293  {
1294  mapSettings.setBackgroundColor( QColor( 0, 0, 0, 0 ) );
1295  }
1296  else if ( backgroundColor.isValid() )
1297  {
1298  mapSettings.setBackgroundColor( backgroundColor );
1299  }
1300 
1301  // add context from project (global variables, ...)
1302  QgsExpressionContext context = mProject->createExpressionContext();
1303  context << QgsExpressionContextUtils::mapSettingsScope( mapSettings );
1304  mapSettings.setExpressionContext( context );
1305 
1306  // add labeling engine settings
1307  mapSettings.setLabelingEngineSettings( mProject->labelingEngineSettings() );
1308 
1309  // enable rendering optimization
1311 
1312  mapSettings.setFlag( Qgis::MapSettingsFlag::RenderMapTile, mContext.renderMapTiles() );
1313 
1314  // set selection color
1315  mapSettings.setSelectionColor( mProject->selectionColor() );
1316 
1317  // Set WMS temporal properties
1318  // Note that this cannot parse multiple time instants while the vector dimensions implementation can
1319  const QString timeString { mWmsParameters.dimensionValues().value( QStringLiteral( "TIME" ), QString() ) };
1320  if ( ! timeString.isEmpty() )
1321  {
1322  bool isValidTemporalRange { true };
1323  QgsDateTimeRange range;
1324  // First try with a simple date/datetime instant
1325  const QDateTime dt { QDateTime::fromString( timeString, Qt::DateFormat::ISODateWithMs ) };
1326  if ( dt.isValid() )
1327  {
1328  range = QgsDateTimeRange( dt, dt );
1329  }
1330  else // parse as an interval
1331  {
1332  try
1333  {
1335  }
1336  catch ( const QgsServerApiBadRequestException &ex )
1337  {
1338  isValidTemporalRange = false;
1339  QgsMessageLog::logMessage( QStringLiteral( "Could not parse TIME parameter into a temporal range" ), "Server", Qgis::MessageLevel::Warning );
1340  }
1341  }
1342 
1343  if ( isValidTemporalRange )
1344  {
1345  mIsTemporal = true;
1346  mapSettings.setIsTemporal( true );
1347  mapSettings.setTemporalRange( range );
1348  }
1349 
1350  }
1351  }
1352 
1353  QDomDocument QgsRenderer::featureInfoDocument( QList<QgsMapLayer *> &layers, const QgsMapSettings &mapSettings,
1354  const QImage *outputImage, const QString &version ) const
1355  {
1356  const QStringList queryLayers = mContext.flattenedQueryLayers( mContext.parameters().queryLayersNickname() );
1357 
1358  bool ijDefined = ( !mWmsParameters.i().isEmpty() && !mWmsParameters.j().isEmpty() );
1359 
1360  bool xyDefined = ( !mWmsParameters.x().isEmpty() && !mWmsParameters.y().isEmpty() );
1361 
1362  bool filtersDefined = !mWmsParameters.filters().isEmpty();
1363 
1364  bool filterGeomDefined = !mWmsParameters.filterGeom().isEmpty();
1365 
1366  int featureCount = mWmsParameters.featureCountAsInt();
1367  if ( featureCount < 1 )
1368  {
1369  featureCount = 1;
1370  }
1371 
1372  int i = mWmsParameters.iAsInt();
1373  int j = mWmsParameters.jAsInt();
1374  if ( xyDefined && !ijDefined )
1375  {
1376  i = mWmsParameters.xAsInt();
1377  j = mWmsParameters.yAsInt();
1378  }
1379  int width = mWmsParameters.widthAsInt();
1380  int height = mWmsParameters.heightAsInt();
1381  if ( ( i != -1 && j != -1 && width != 0 && height != 0 ) && ( width != outputImage->width() || height != outputImage->height() ) )
1382  {
1383  i *= ( outputImage->width() / static_cast<double>( width ) );
1384  j *= ( outputImage->height() / static_cast<double>( height ) );
1385  }
1386 
1387  // init search variables
1388  std::unique_ptr<QgsRectangle> featuresRect;
1389  std::unique_ptr<QgsGeometry> filterGeom;
1390  std::unique_ptr<QgsPointXY> infoPoint;
1391 
1392  if ( i != -1 && j != -1 )
1393  {
1394  infoPoint.reset( new QgsPointXY() );
1395  infoPointToMapCoordinates( i, j, infoPoint.get(), mapSettings );
1396  }
1397  else if ( filtersDefined )
1398  {
1399  featuresRect.reset( new QgsRectangle() );
1400  }
1401  else if ( filterGeomDefined )
1402  {
1403  filterGeom.reset( new QgsGeometry( QgsGeometry::fromWkt( mWmsParameters.filterGeom() ) ) );
1404  }
1405 
1406  QDomDocument result;
1407 
1408  QDomElement getFeatureInfoElement;
1409  QgsWmsParameters::Format infoFormat = mWmsParameters.infoFormat();
1410  if ( infoFormat == QgsWmsParameters::Format::GML )
1411  {
1412  getFeatureInfoElement = result.createElement( QStringLiteral( "wfs:FeatureCollection" ) );
1413  getFeatureInfoElement.setAttribute( QStringLiteral( "xmlns:wfs" ), QStringLiteral( "http://www.opengis.net/wfs" ) );
1414  getFeatureInfoElement.setAttribute( QStringLiteral( "xmlns:ogc" ), QStringLiteral( "http://www.opengis.net/ogc" ) );
1415  getFeatureInfoElement.setAttribute( QStringLiteral( "xmlns:gml" ), QStringLiteral( "http://www.opengis.net/gml" ) );
1416  getFeatureInfoElement.setAttribute( QStringLiteral( "xmlns:ows" ), QStringLiteral( "http://www.opengis.net/ows" ) );
1417  getFeatureInfoElement.setAttribute( QStringLiteral( "xmlns:xlink" ), QStringLiteral( "http://www.w3.org/1999/xlink" ) );
1418  getFeatureInfoElement.setAttribute( QStringLiteral( "xmlns:qgs" ), QStringLiteral( "http://qgis.org/gml" ) );
1419  getFeatureInfoElement.setAttribute( QStringLiteral( "xmlns:xsi" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema-instance" ) );
1420  getFeatureInfoElement.setAttribute( QStringLiteral( "xsi:schemaLocation" ), QStringLiteral( "http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd http://qgis.org/gml" ) );
1421  }
1422  else
1423  {
1424  QString featureInfoElemName = QgsServerProjectUtils::wmsFeatureInfoDocumentElement( *mProject );
1425  if ( featureInfoElemName.isEmpty() )
1426  {
1427  featureInfoElemName = QStringLiteral( "GetFeatureInfoResponse" );
1428  }
1429  QString featureInfoElemNs = QgsServerProjectUtils::wmsFeatureInfoDocumentElementNs( *mProject );
1430  if ( featureInfoElemNs.isEmpty() )
1431  {
1432  getFeatureInfoElement = result.createElement( featureInfoElemName );
1433  }
1434  else
1435  {
1436  getFeatureInfoElement = result.createElementNS( featureInfoElemNs, featureInfoElemName );
1437  }
1438  //feature info schema
1439  QString featureInfoSchema = QgsServerProjectUtils::wmsFeatureInfoSchema( *mProject );
1440  if ( !featureInfoSchema.isEmpty() )
1441  {
1442  getFeatureInfoElement.setAttribute( QStringLiteral( "xmlns:xsi" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema-instance" ) );
1443  getFeatureInfoElement.setAttribute( QStringLiteral( "xsi:schemaLocation" ), featureInfoSchema );
1444  }
1445  }
1446  result.appendChild( getFeatureInfoElement );
1447 
1448  //Render context is needed to determine feature visibility for vector layers
1449  QgsRenderContext renderContext = QgsRenderContext::fromMapSettings( mapSettings );
1450 
1451  bool sia2045 = QgsServerProjectUtils::wmsInfoFormatSia2045( *mProject );
1452 
1453  //layers can have assigned a different name for GetCapabilities
1454  QHash<QString, QString> layerAliasMap = QgsServerProjectUtils::wmsFeatureInfoLayerAliasMap( *mProject );
1455 
1456  for ( const QString &queryLayer : queryLayers )
1457  {
1458  bool validLayer = false;
1459  bool queryableLayer = true;
1460  for ( QgsMapLayer *layer : std::as_const( layers ) )
1461  {
1462  if ( queryLayer == mContext.layerNickname( *layer ) )
1463  {
1464  validLayer = true;
1465  queryableLayer = layer->flags().testFlag( QgsMapLayer::Identifiable );
1466  if ( !queryableLayer )
1467  {
1468  break;
1469  }
1470 
1471  QDomElement layerElement;
1472  if ( infoFormat == QgsWmsParameters::Format::GML )
1473  {
1474  layerElement = getFeatureInfoElement;
1475  }
1476  else
1477  {
1478  layerElement = result.createElement( QStringLiteral( "Layer" ) );
1479  QString layerName = queryLayer;
1480 
1481  //check if the layer is given a different name for GetFeatureInfo output
1482  QHash<QString, QString>::const_iterator layerAliasIt = layerAliasMap.constFind( layerName );
1483  if ( layerAliasIt != layerAliasMap.constEnd() )
1484  {
1485  layerName = layerAliasIt.value();
1486  }
1487 
1488  layerElement.setAttribute( QStringLiteral( "name" ), layerName );
1489  getFeatureInfoElement.appendChild( layerElement );
1490  if ( sia2045 ) //the name might not be unique after alias replacement
1491  {
1492  layerElement.setAttribute( QStringLiteral( "id" ), layer->id() );
1493  }
1494  }
1495 
1496  if ( layer->type() == QgsMapLayerType::VectorLayer )
1497  {
1498  QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layer );
1499  if ( vectorLayer )
1500  {
1501  ( void )featureInfoFromVectorLayer( vectorLayer, infoPoint.get(), featureCount, result, layerElement, mapSettings, renderContext, version, featuresRect.get(), filterGeom.get() );
1502  break;
1503  }
1504  }
1505  else
1506  {
1507  QgsRasterLayer *rasterLayer = qobject_cast<QgsRasterLayer *>( layer );
1508  if ( !rasterLayer )
1509  {
1510  break;
1511  }
1512  if ( !infoPoint )
1513  {
1514  break;
1515  }
1516  QgsPointXY layerInfoPoint = mapSettings.mapToLayerCoordinates( layer, *( infoPoint.get() ) );
1517  if ( !rasterLayer->extent().contains( layerInfoPoint ) )
1518  {
1519  break;
1520  }
1521  if ( infoFormat == QgsWmsParameters::Format::GML )
1522  {
1523  layerElement = result.createElement( QStringLiteral( "gml:featureMember" )/*wfs:FeatureMember*/ );
1524  getFeatureInfoElement.appendChild( layerElement );
1525  }
1526 
1527  ( void )featureInfoFromRasterLayer( rasterLayer, mapSettings, &layerInfoPoint, result, layerElement, version );
1528  }
1529  break;
1530  }
1531  }
1532  if ( !validLayer && !mContext.isValidLayer( queryLayer ) && !mContext.isValidGroup( queryLayer ) )
1533  {
1534  QgsWmsParameter param( QgsWmsParameter::LAYER );
1535  param.mValue = queryLayer;
1537  param );
1538  }
1539  else if ( ( validLayer && !queryableLayer ) || ( !validLayer && mContext.isValidGroup( queryLayer ) ) )
1540  {
1541  QgsWmsParameter param( QgsWmsParameter::LAYER );
1542  param.mValue = queryLayer;
1543  // Check if this layer belongs to a group and the group has any queryable layers
1544  bool hasGroupAndQueryable { false };
1545  if ( ! mContext.parameters().queryLayersNickname().contains( queryLayer ) )
1546  {
1547  // Find which group this layer belongs to
1548  const QStringList constNicks { mContext.parameters().queryLayersNickname() };
1549  for ( const QString &ql : constNicks )
1550  {
1551  if ( mContext.layerGroups().contains( ql ) )
1552  {
1553  const QList<QgsMapLayer *> constLayers { mContext.layerGroups()[ql] };
1554  for ( const QgsMapLayer *ml : constLayers )
1555  {
1556  if ( ( ! ml->shortName().isEmpty() && ml->shortName() == queryLayer ) || ( ml->name() == queryLayer ) )
1557  {
1558  param.mValue = ql;
1559  }
1560  if ( ml->flags().testFlag( QgsMapLayer::Identifiable ) )
1561  {
1562  hasGroupAndQueryable = true;
1563  break;
1564  }
1565  }
1566  break;
1567  }
1568  }
1569  }
1570  // Only throw if it's not a group or the group has no queryable children
1571  if ( ! hasGroupAndQueryable )
1572  {
1574  param );
1575  }
1576  }
1577  }
1578 
1579  if ( featuresRect )
1580  {
1581  if ( infoFormat == QgsWmsParameters::Format::GML )
1582  {
1583  QDomElement bBoxElem = result.createElement( QStringLiteral( "gml:boundedBy" ) );
1584  QDomElement boxElem;
1585  int gmlVersion = mWmsParameters.infoFormatVersion();
1586  if ( gmlVersion < 3 )
1587  {
1588  boxElem = QgsOgcUtils::rectangleToGMLBox( featuresRect.get(), result, 8 );
1589  }
1590  else
1591  {
1592  boxElem = QgsOgcUtils::rectangleToGMLEnvelope( featuresRect.get(), result, 8 );
1593  }
1594 
1595  QgsCoordinateReferenceSystem crs = mapSettings.destinationCrs();
1596  if ( crs.isValid() )
1597  {
1598  boxElem.setAttribute( QStringLiteral( "srsName" ), crs.authid() );
1599  }
1600  bBoxElem.appendChild( boxElem );
1601  getFeatureInfoElement.insertBefore( bBoxElem, QDomNode() ); //insert as first child
1602  }
1603  else
1604  {
1605  QDomElement bBoxElem = result.createElement( QStringLiteral( "BoundingBox" ) );
1606  bBoxElem.setAttribute( QStringLiteral( "CRS" ), mapSettings.destinationCrs().authid() );
1607  bBoxElem.setAttribute( QStringLiteral( "minx" ), qgsDoubleToString( featuresRect->xMinimum(), 8 ) );
1608  bBoxElem.setAttribute( QStringLiteral( "maxx" ), qgsDoubleToString( featuresRect->xMaximum(), 8 ) );
1609  bBoxElem.setAttribute( QStringLiteral( "miny" ), qgsDoubleToString( featuresRect->yMinimum(), 8 ) );
1610  bBoxElem.setAttribute( QStringLiteral( "maxy" ), qgsDoubleToString( featuresRect->yMaximum(), 8 ) );
1611  getFeatureInfoElement.insertBefore( bBoxElem, QDomNode() ); //insert as first child
1612  }
1613  }
1614 
1615  if ( sia2045 && infoFormat == QgsWmsParameters::Format::XML )
1616  {
1617  convertFeatureInfoToSia2045( result );
1618  }
1619 
1620  return result;
1621  }
1622 
1623  bool QgsRenderer::featureInfoFromVectorLayer( QgsVectorLayer *layer,
1624  const QgsPointXY *infoPoint,
1625  int nFeatures,
1626  QDomDocument &infoDocument,
1627  QDomElement &layerElement,
1628  const QgsMapSettings &mapSettings,
1629  QgsRenderContext &renderContext,
1630  const QString &version,
1631  QgsRectangle *featureBBox,
1632  QgsGeometry *filterGeom ) const
1633  {
1634  if ( !layer )
1635  {
1636  return false;
1637  }
1638 
1639  QgsFeatureRequest fReq;
1640 
1641  // Transform filter geometry to layer CRS
1642  std::unique_ptr<QgsGeometry> layerFilterGeom;
1643  if ( filterGeom )
1644  {
1645  layerFilterGeom.reset( new QgsGeometry( *filterGeom ) );
1646  layerFilterGeom->transform( QgsCoordinateTransform( mapSettings.destinationCrs(), layer->crs(), fReq.transformContext() ) );
1647  }
1648 
1649  //we need a selection rect (0.01 of map width)
1650  QgsRectangle mapRect = mapSettings.extent();
1651  QgsRectangle layerRect = mapSettings.mapToLayerCoordinates( layer, mapRect );
1652 
1653 
1654  QgsRectangle searchRect;
1655 
1656  //info point could be 0 in case there is only an attribute filter
1657  if ( infoPoint )
1658  {
1659  searchRect = featureInfoSearchRect( layer, mapSettings, renderContext, *infoPoint );
1660  }
1661  else if ( layerFilterGeom )
1662  {
1663  searchRect = layerFilterGeom->boundingBox();
1664  }
1665  else if ( !mWmsParameters.bbox().isEmpty() )
1666  {
1667  searchRect = layerRect;
1668  }
1669 
1670  //do a select with searchRect and go through all the features
1671 
1672  QgsFeature feature;
1673  QgsAttributes featureAttributes;
1674  int featureCounter = 0;
1675  layer->updateFields();
1676  const QgsFields fields = layer->fields();
1677  bool addWktGeometry = ( QgsServerProjectUtils::wmsFeatureInfoAddWktGeometry( *mProject ) && mWmsParameters.withGeometry() );
1678  bool segmentizeWktGeometry = QgsServerProjectUtils::wmsFeatureInfoSegmentizeWktGeometry( *mProject );
1679 
1680  bool hasGeometry = QgsServerProjectUtils::wmsFeatureInfoAddWktGeometry( *mProject ) || addWktGeometry || featureBBox || layerFilterGeom;
1682 
1683  if ( ! searchRect.isEmpty() )
1684  {
1685  fReq.setFilterRect( searchRect );
1686  }
1687  else
1688  {
1690  }
1691 
1692 
1693  if ( layerFilterGeom )
1694  {
1695  fReq.setFilterExpression( QString( "intersects( $geometry, geom_from_wkt('%1') )" ).arg( layerFilterGeom->asWkt() ) );
1696  }
1697 
1698  mFeatureFilter.filterFeatures( layer, fReq );
1699 
1700 #ifdef HAVE_SERVER_PYTHON_PLUGINS
1701  mContext.accessControl()->filterFeatures( layer, fReq );
1702 
1703  QStringList attributes;
1704  for ( const QgsField &field : fields )
1705  {
1706  attributes.append( field.name() );
1707  }
1708  attributes = mContext.accessControl()->layerAttributes( layer, attributes );
1709  fReq.setSubsetOfAttributes( attributes, layer->fields() );
1710 #endif
1711 
1712  QgsFeatureIterator fit = layer->getFeatures( fReq );
1713  std::unique_ptr< QgsFeatureRenderer > r2( layer->renderer() ? layer->renderer()->clone() : nullptr );
1714  if ( r2 )
1715  {
1716  r2->startRender( renderContext, layer->fields() );
1717  }
1718 
1719  bool featureBBoxInitialized = false;
1720  while ( fit.nextFeature( feature ) )
1721  {
1722  if ( layer->wkbType() == QgsWkbTypes::NoGeometry && ! searchRect.isEmpty() )
1723  {
1724  break;
1725  }
1726 
1727  ++featureCounter;
1728  if ( featureCounter > nFeatures )
1729  {
1730  break;
1731  }
1732 
1733  renderContext.expressionContext().setFeature( feature );
1734 
1735  if ( layer->wkbType() != QgsWkbTypes::NoGeometry && ! searchRect.isEmpty() )
1736  {
1737  if ( !r2 )
1738  {
1739  continue;
1740  }
1741 
1742  //check if feature is rendered at all
1743  bool render = r2->willRenderFeature( feature, renderContext );
1744  if ( !render )
1745  {
1746  continue;
1747  }
1748  }
1749 
1750  QgsRectangle box;
1751  if ( layer->wkbType() != QgsWkbTypes::NoGeometry && hasGeometry )
1752  {
1753  box = mapSettings.layerExtentToOutputExtent( layer, feature.geometry().boundingBox() );
1754  if ( featureBBox ) //extend feature info bounding box if requested
1755  {
1756  if ( !featureBBoxInitialized && featureBBox->isEmpty() )
1757  {
1758  *featureBBox = box;
1759  featureBBoxInitialized = true;
1760  }
1761  else
1762  {
1763  featureBBox->combineExtentWith( box );
1764  }
1765  }
1766  }
1767 
1769  if ( layer->crs() != mapSettings.destinationCrs() )
1770  {
1771  outputCrs = mapSettings.destinationCrs();
1772  }
1773 
1774  if ( mWmsParameters.infoFormat() == QgsWmsParameters::Format::GML )
1775  {
1776  bool withGeom = layer->wkbType() != QgsWkbTypes::NoGeometry && addWktGeometry;
1777  int gmlVersion = mWmsParameters.infoFormatVersion();
1778  QString typeName = mContext.layerNickname( *layer );
1779  QDomElement elem = createFeatureGML(
1780  &feature, layer, infoDocument, outputCrs, mapSettings, typeName, withGeom, gmlVersion
1781 #ifdef HAVE_SERVER_PYTHON_PLUGINS
1782  , &attributes
1783 #endif
1784  );
1785  QDomElement featureMemberElem = infoDocument.createElement( QStringLiteral( "gml:featureMember" )/*wfs:FeatureMember*/ );
1786  featureMemberElem.appendChild( elem );
1787  layerElement.appendChild( featureMemberElem );
1788  continue;
1789  }
1790  else
1791  {
1792  QDomElement featureElement = infoDocument.createElement( QStringLiteral( "Feature" ) );
1793  featureElement.setAttribute( QStringLiteral( "id" ), QgsServerFeatureId::getServerFid( feature, layer->dataProvider()->pkAttributeIndexes() ) );
1794  layerElement.appendChild( featureElement );
1795 
1796  featureAttributes = feature.attributes();
1797  QgsEditFormConfig editConfig = layer->editFormConfig();
1799  {
1800  writeAttributesTabLayout( editConfig, layer, fields, featureAttributes, infoDocument, featureElement, renderContext
1801 #ifdef HAVE_SERVER_PYTHON_PLUGINS
1802  , &attributes
1803 #endif
1804  );
1805  }
1806  else
1807  {
1808  for ( int i = 0; i < featureAttributes.count(); ++i )
1809  {
1810  writeVectorLayerAttribute( i, layer, fields, featureAttributes, infoDocument, featureElement, renderContext
1811 #ifdef HAVE_SERVER_PYTHON_PLUGINS
1812  , &attributes
1813 #endif
1814  );
1815  }
1816  }
1817 
1818  //add maptip attribute based on html/expression (in case there is no maptip attribute)
1819  QString mapTip = layer->mapTipTemplate();
1820  if ( !mapTip.isEmpty() && mWmsParameters.withMapTip() )
1821  {
1822  QDomElement maptipElem = infoDocument.createElement( QStringLiteral( "Attribute" ) );
1823  maptipElem.setAttribute( QStringLiteral( "name" ), QStringLiteral( "maptip" ) );
1824  maptipElem.setAttribute( QStringLiteral( "value" ), QgsExpression::replaceExpressionText( mapTip, &renderContext.expressionContext() ) );
1825  featureElement.appendChild( maptipElem );
1826  }
1827 
1828  //append feature bounding box to feature info xml
1830  layer->wkbType() != QgsWkbTypes::NoGeometry && hasGeometry )
1831  {
1832  QDomElement bBoxElem = infoDocument.createElement( QStringLiteral( "BoundingBox" ) );
1833  bBoxElem.setAttribute( version == QLatin1String( "1.1.1" ) ? "SRS" : "CRS", outputCrs.authid() );
1834  bBoxElem.setAttribute( QStringLiteral( "minx" ), qgsDoubleToString( box.xMinimum(), mContext.precision() ) );
1835  bBoxElem.setAttribute( QStringLiteral( "maxx" ), qgsDoubleToString( box.xMaximum(), mContext.precision() ) );
1836  bBoxElem.setAttribute( QStringLiteral( "miny" ), qgsDoubleToString( box.yMinimum(), mContext.precision() ) );
1837  bBoxElem.setAttribute( QStringLiteral( "maxy" ), qgsDoubleToString( box.yMaximum(), mContext.precision() ) );
1838  featureElement.appendChild( bBoxElem );
1839  }
1840 
1841  //also append the wkt geometry as an attribute
1842  if ( layer->wkbType() != QgsWkbTypes::NoGeometry && addWktGeometry && hasGeometry )
1843  {
1844  QgsGeometry geom = feature.geometry();
1845  if ( !geom.isNull() )
1846  {
1847  if ( layer->crs() != outputCrs )
1848  {
1849  QgsCoordinateTransform transform = mapSettings.layerTransform( layer );
1850  if ( transform.isValid() )
1851  geom.transform( transform );
1852  }
1853 
1854  if ( segmentizeWktGeometry )
1855  {
1856  const QgsAbstractGeometry *abstractGeom = geom.constGet();
1857  if ( abstractGeom )
1858  {
1859  if ( QgsWkbTypes::isCurvedType( abstractGeom->wkbType() ) )
1860  {
1861  QgsAbstractGeometry *segmentizedGeom = abstractGeom->segmentize();
1862  geom.set( segmentizedGeom );
1863  }
1864  }
1865  }
1866  QDomElement geometryElement = infoDocument.createElement( QStringLiteral( "Attribute" ) );
1867  geometryElement.setAttribute( QStringLiteral( "name" ), QStringLiteral( "geometry" ) );
1868  geometryElement.setAttribute( QStringLiteral( "value" ), geom.asWkt( mContext.precision() ) );
1869  geometryElement.setAttribute( QStringLiteral( "type" ), QStringLiteral( "derived" ) );
1870  featureElement.appendChild( geometryElement );
1871  }
1872  }
1873  }
1874  }
1875  if ( r2 )
1876  {
1877  r2->stopRender( renderContext );
1878  }
1879 
1880  return true;
1881  }
1882 
1883  void QgsRenderer::writeAttributesTabGroup( const QgsAttributeEditorElement *group, QgsVectorLayer *layer, const QgsFields &fields, QgsAttributes &featureAttributes, QDomDocument &doc, QDomElement &parentElem, QgsRenderContext &renderContext, QStringList *attributes ) const
1884  {
1885  const QgsAttributeEditorContainer *container = dynamic_cast<const QgsAttributeEditorContainer *>( group );
1886  if ( container )
1887  {
1888  QString groupName = container->name();
1889  QDomElement nameElem;
1890 
1891  if ( !groupName.isEmpty() )
1892  {
1893  nameElem = doc.createElement( groupName );
1894  parentElem.appendChild( nameElem );
1895  }
1896 
1897  const QList<QgsAttributeEditorElement *> children = container->children();
1898  for ( const QgsAttributeEditorElement *child : children )
1899  {
1900  if ( child->type() == QgsAttributeEditorElement::AeTypeContainer )
1901  {
1902  writeAttributesTabGroup( child, layer, fields, featureAttributes, doc, nameElem.isNull() ? parentElem : nameElem, renderContext );
1903  }
1904  else if ( child->type() == QgsAttributeEditorElement::AeTypeField )
1905  {
1906  const QgsAttributeEditorField *editorField = dynamic_cast<const QgsAttributeEditorField *>( child );
1907  if ( editorField )
1908  {
1909  const int idx { fields.indexFromName( editorField->name() ) };
1910  if ( idx >= 0 )
1911  {
1912  writeVectorLayerAttribute( idx, layer, fields, featureAttributes, doc, nameElem.isNull() ? parentElem : nameElem, renderContext, attributes );
1913  }
1914  }
1915  }
1916  }
1917  }
1918  }
1919 
1920  void QgsRenderer::writeAttributesTabLayout( QgsEditFormConfig &config, QgsVectorLayer *layer, const QgsFields &fields, QgsAttributes &featureAttributes, QDomDocument &doc, QDomElement &featureElem, QgsRenderContext &renderContext, QStringList *attributes ) const
1921  {
1922  QgsAttributeEditorContainer *editorContainer = config.invisibleRootContainer();
1923  if ( !editorContainer )
1924  {
1925  return;
1926  }
1927 
1928  writeAttributesTabGroup( editorContainer, layer, fields, featureAttributes, doc, featureElem, renderContext, attributes );
1929  }
1930 
1931  void QgsRenderer::writeVectorLayerAttribute( int attributeIndex, QgsVectorLayer *layer, const QgsFields &fields, QgsAttributes &featureAttributes, QDomDocument &doc, QDomElement &featureElem, QgsRenderContext &renderContext, QStringList *attributes ) const
1932  {
1933 #ifndef HAVE_SERVER_PYTHON_PLUGINS
1934  Q_UNUSED( attributes );
1935 #endif
1936 
1937  if ( !layer )
1938  {
1939  return;
1940  }
1941 
1942  //skip attribute if it is explicitly excluded from WMS publication
1943  if ( fields.at( attributeIndex ).configurationFlags().testFlag( QgsField::ConfigurationFlag::HideFromWms ) )
1944  {
1945  return;
1946  }
1947 #ifdef HAVE_SERVER_PYTHON_PLUGINS
1948  //skip attribute if it is excluded by access control
1949  if ( attributes && !attributes->contains( fields.at( attributeIndex ).name() ) )
1950  {
1951  return;
1952  }
1953 #endif
1954 
1955  QString attributeName = layer->attributeDisplayName( attributeIndex );
1956  QDomElement attributeElement = doc.createElement( QStringLiteral( "Attribute" ) );
1957  attributeElement.setAttribute( QStringLiteral( "name" ), attributeName );
1958  const QgsEditorWidgetSetup setup = layer->editorWidgetSetup( attributeIndex );
1959  attributeElement.setAttribute( QStringLiteral( "value" ),
1961  replaceValueMapAndRelation(
1962  layer, attributeIndex,
1963  featureAttributes[attributeIndex] ),
1964  &renderContext.expressionContext() )
1965  );
1966  featureElem.appendChild( attributeElement );
1967  }
1968 
1969  bool QgsRenderer::featureInfoFromRasterLayer( QgsRasterLayer *layer,
1970  const QgsMapSettings &mapSettings,
1971  const QgsPointXY *infoPoint,
1972  QDomDocument &infoDocument,
1973  QDomElement &layerElement,
1974  const QString &version ) const
1975  {
1976  Q_UNUSED( version )
1977 
1978  if ( !infoPoint || !layer || !layer->dataProvider() )
1979  {
1980  return false;
1981  }
1982 
1983  QgsMessageLog::logMessage( QStringLiteral( "infoPoint: %1 %2" ).arg( infoPoint->x() ).arg( infoPoint->y() ) );
1984 
1987  {
1988  return false;
1989  }
1990 
1991  const QgsRaster::IdentifyFormat identifyFormat(
1992  static_cast<bool>( layer->dataProvider()->capabilities() & QgsRasterDataProvider::IdentifyFeature )
1993  ? QgsRaster::IdentifyFormat::IdentifyFormatFeature
1994  : QgsRaster::IdentifyFormat::IdentifyFormatValue );
1995 
1996  QgsRasterIdentifyResult identifyResult;
1997  if ( layer->crs() != mapSettings.destinationCrs() )
1998  {
1999  const QgsRectangle extent { mapSettings.extent() };
2000  const QgsCoordinateTransform transform { mapSettings.destinationCrs(), layer->crs(), mapSettings.transformContext() };
2001  if ( ! transform.isValid() )
2002  {
2003  throw QgsBadRequestException( QgsServiceException::OGC_InvalidCRS, QStringLiteral( "CRS transform error from %1 to %2 in layer %3" )
2004  .arg( mapSettings.destinationCrs().authid() )
2005  .arg( layer->crs().authid() )
2006  .arg( layer->name() ) );
2007  }
2008  identifyResult = layer->dataProvider()->identify( *infoPoint, identifyFormat, transform.transform( extent ), mapSettings.outputSize().width(), mapSettings.outputSize().height() );
2009  }
2010  else
2011  {
2012  identifyResult = layer->dataProvider()->identify( *infoPoint, identifyFormat, mapSettings.extent(), mapSettings.outputSize().width(), mapSettings.outputSize().height() );
2013  }
2014 
2015  if ( !identifyResult.isValid() )
2016  return false;
2017 
2018  QMap<int, QVariant> attributes = identifyResult.results();
2019 
2020  if ( mWmsParameters.infoFormat() == QgsWmsParameters::Format::GML )
2021  {
2022  QgsFeature feature;
2023  QgsFields fields;
2024  QgsCoordinateReferenceSystem layerCrs = layer->crs();
2025  int gmlVersion = mWmsParameters.infoFormatVersion();
2026  QString typeName = mContext.layerNickname( *layer );
2027 
2028  if ( identifyFormat == QgsRaster::IdentifyFormatValue )
2029  {
2030  feature.initAttributes( attributes.count() );
2031  int index = 0;
2032  for ( auto it = attributes.constBegin(); it != attributes.constEnd(); ++it )
2033  {
2034  fields.append( QgsField( layer->bandName( it.key() ), QVariant::Double ) );
2035  feature.setAttribute( index++, QString::number( it.value().toDouble() ) );
2036  }
2037  feature.setFields( fields );
2038  QDomElement elem = createFeatureGML(
2039  &feature, nullptr, infoDocument, layerCrs, mapSettings, typeName, false, gmlVersion, nullptr );
2040  layerElement.appendChild( elem );
2041  }
2042  else
2043  {
2044  const auto values = identifyResult.results();
2045  for ( auto it = values.constBegin(); it != values.constEnd(); ++it )
2046  {
2047  QVariant value = it.value();
2048  if ( value.type() == QVariant::Bool && !value.toBool() )
2049  {
2050  // sublayer not visible or not queryable
2051  continue;
2052  }
2053 
2054  if ( value.type() == QVariant::String )
2055  {
2056  continue;
2057  }
2058 
2059  // list of feature stores for a single sublayer
2060  const QgsFeatureStoreList featureStoreList = it.value().value<QgsFeatureStoreList>();
2061 
2062  for ( const QgsFeatureStore &featureStore : featureStoreList )
2063  {
2064  const QgsFeatureList storeFeatures = featureStore.features();
2065  for ( const QgsFeature &feature : storeFeatures )
2066  {
2067  QDomElement elem = createFeatureGML(
2068  &feature, nullptr, infoDocument, layerCrs, mapSettings, typeName, false, gmlVersion, nullptr );
2069  layerElement.appendChild( elem );
2070  }
2071  }
2072  }
2073  }
2074  }
2075  else
2076  {
2077  if ( identifyFormat == QgsRaster::IdentifyFormatValue )
2078  {
2079  for ( auto it = attributes.constBegin(); it != attributes.constEnd(); ++it )
2080  {
2081  QDomElement attributeElement = infoDocument.createElement( QStringLiteral( "Attribute" ) );
2082  attributeElement.setAttribute( QStringLiteral( "name" ), layer->bandName( it.key() ) );
2083 
2084  QString value;
2085  if ( ! it.value().isNull() )
2086  {
2087  value = QString::number( it.value().toDouble() );
2088  }
2089 
2090  attributeElement.setAttribute( QStringLiteral( "value" ), value );
2091  layerElement.appendChild( attributeElement );
2092  }
2093  }
2094  else // feature
2095  {
2096  const auto values = identifyResult.results();
2097  for ( auto it = values.constBegin(); it != values.constEnd(); ++it )
2098  {
2099  QVariant value = it.value();
2100  if ( value.type() == QVariant::Bool && !value.toBool() )
2101  {
2102  // sublayer not visible or not queryable
2103  continue;
2104  }
2105 
2106  if ( value.type() == QVariant::String )
2107  {
2108  continue;
2109  }
2110 
2111  // list of feature stores for a single sublayer
2112  const QgsFeatureStoreList featureStoreList = it.value().value<QgsFeatureStoreList>();
2113  for ( const QgsFeatureStore &featureStore : featureStoreList )
2114  {
2115  const QgsFeatureList storeFeatures = featureStore.features();
2116  for ( const QgsFeature &feature : storeFeatures )
2117  {
2118  for ( const auto &fld : feature.fields() )
2119  {
2120  const auto val { feature.attribute( fld.name() )};
2121  if ( val.isValid() )
2122  {
2123  QDomElement attributeElement = infoDocument.createElement( QStringLiteral( "Attribute" ) );
2124  attributeElement.setAttribute( QStringLiteral( "name" ), fld.name() );
2125  attributeElement.setAttribute( QStringLiteral( "value" ), val.toString() );
2126  layerElement.appendChild( attributeElement );
2127  }
2128  }
2129  }
2130  }
2131  }
2132  }
2133  }
2134  return true;
2135  }
2136 
2137  bool QgsRenderer::testFilterStringSafety( const QString &filter ) const
2138  {
2139  //; too dangerous for sql injections
2140  if ( filter.contains( QLatin1String( ";" ) ) )
2141  {
2142  return false;
2143  }
2144 
2145 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
2146  QStringList tokens = filter.split( ' ', QString::SkipEmptyParts );
2147 #else
2148  QStringList tokens = filter.split( ' ', Qt::SkipEmptyParts );
2149 #endif
2150  groupStringList( tokens, QStringLiteral( "'" ) );
2151  groupStringList( tokens, QStringLiteral( "\"" ) );
2152 
2153  for ( auto tokenIt = tokens.constBegin() ; tokenIt != tokens.constEnd(); ++tokenIt )
2154  {
2155  //allowlist of allowed characters and keywords
2156  if ( tokenIt->compare( QLatin1String( "," ) ) == 0
2157  || tokenIt->compare( QLatin1String( "(" ) ) == 0
2158  || tokenIt->compare( QLatin1String( ")" ) ) == 0
2159  || tokenIt->compare( QLatin1String( "=" ) ) == 0
2160  || tokenIt->compare( QLatin1String( "!=" ) ) == 0
2161  || tokenIt->compare( QLatin1String( "<" ) ) == 0
2162  || tokenIt->compare( QLatin1String( "<=" ) ) == 0
2163  || tokenIt->compare( QLatin1String( ">" ) ) == 0
2164  || tokenIt->compare( QLatin1String( ">=" ) ) == 0
2165  || tokenIt->compare( QLatin1String( "%" ) ) == 0
2166  || tokenIt->compare( QLatin1String( "IS" ), Qt::CaseInsensitive ) == 0
2167  || tokenIt->compare( QLatin1String( "NOT" ), Qt::CaseInsensitive ) == 0
2168  || tokenIt->compare( QLatin1String( "NULL" ), Qt::CaseInsensitive ) == 0
2169  || tokenIt->compare( QLatin1String( "AND" ), Qt::CaseInsensitive ) == 0
2170  || tokenIt->compare( QLatin1String( "OR" ), Qt::CaseInsensitive ) == 0
2171  || tokenIt->compare( QLatin1String( "IN" ), Qt::CaseInsensitive ) == 0
2172  || tokenIt->compare( QLatin1String( "LIKE" ), Qt::CaseInsensitive ) == 0
2173  || tokenIt->compare( QLatin1String( "ILIKE" ), Qt::CaseInsensitive ) == 0
2174  || tokenIt->compare( QLatin1String( "DMETAPHONE" ), Qt::CaseInsensitive ) == 0
2175  || tokenIt->compare( QLatin1String( "SOUNDEX" ), Qt::CaseInsensitive ) == 0 )
2176  {
2177  continue;
2178  }
2179 
2180  //numbers are OK
2181  bool isNumeric;
2182  tokenIt->toDouble( &isNumeric );
2183  if ( isNumeric )
2184  {
2185  continue;
2186  }
2187 
2188  //numeric strings need to be quoted once either with single or with double quotes
2189 
2190  //empty strings are OK
2191  if ( *tokenIt == QLatin1String( "''" ) )
2192  {
2193  continue;
2194  }
2195 
2196  //single quote
2197  if ( tokenIt->size() > 2
2198  && ( *tokenIt )[0] == QChar( '\'' )
2199  && ( *tokenIt )[tokenIt->size() - 1] == QChar( '\'' )
2200  && ( *tokenIt )[1] != QChar( '\'' )
2201  && ( *tokenIt )[tokenIt->size() - 2] != QChar( '\'' ) )
2202  {
2203  continue;
2204  }
2205 
2206  //double quote
2207  if ( tokenIt->size() > 2
2208  && ( *tokenIt )[0] == QChar( '"' )
2209  && ( *tokenIt )[tokenIt->size() - 1] == QChar( '"' )
2210  && ( *tokenIt )[1] != QChar( '"' )
2211  && ( *tokenIt )[tokenIt->size() - 2] != QChar( '"' ) )
2212  {
2213  continue;
2214  }
2215 
2216  return false;
2217  }
2218 
2219  return true;
2220  }
2221 
2222  void QgsRenderer::groupStringList( QStringList &list, const QString &groupString )
2223  {
2224  //group contents within single quotes together
2225  bool groupActive = false;
2226  int startGroup = -1;
2227  QString concatString;
2228 
2229  for ( int i = 0; i < list.size(); ++i )
2230  {
2231  QString &str = list[i];
2232  if ( str.startsWith( groupString ) )
2233  {
2234  startGroup = i;
2235  groupActive = true;
2236  concatString.clear();
2237  }
2238 
2239  if ( groupActive )
2240  {
2241  if ( i != startGroup )
2242  {
2243  concatString.append( " " );
2244  }
2245  concatString.append( str );
2246  }
2247 
2248  if ( str.endsWith( groupString ) )
2249  {
2250  int endGroup = i;
2251  groupActive = false;
2252 
2253  if ( startGroup != -1 )
2254  {
2255  list[startGroup] = concatString;
2256  for ( int j = startGroup + 1; j <= endGroup; ++j )
2257  {
2258  list.removeAt( startGroup + 1 );
2259  --i;
2260  }
2261  }
2262 
2263  concatString.clear();
2264  startGroup = -1;
2265  }
2266  }
2267  }
2268 
2269  void QgsRenderer::convertFeatureInfoToSia2045( QDomDocument &doc ) const
2270  {
2271  QDomDocument SIAInfoDoc;
2272  QDomElement infoDocElement = doc.documentElement();
2273  QDomElement SIAInfoDocElement = SIAInfoDoc.importNode( infoDocElement, false ).toElement();
2274  SIAInfoDoc.appendChild( SIAInfoDocElement );
2275 
2276  QString currentAttributeName;
2277  QString currentAttributeValue;
2278  QDomElement currentAttributeElem;
2279  QString currentLayerName;
2280  QDomElement currentLayerElem;
2281  QDomNodeList layerNodeList = infoDocElement.elementsByTagName( QStringLiteral( "Layer" ) );
2282  for ( int i = 0; i < layerNodeList.size(); ++i )
2283  {
2284  currentLayerElem = layerNodeList.at( i ).toElement();
2285  currentLayerName = currentLayerElem.attribute( QStringLiteral( "name" ) );
2286 
2287  QDomElement currentFeatureElem;
2288 
2289  QDomNodeList featureList = currentLayerElem.elementsByTagName( QStringLiteral( "Feature" ) );
2290  if ( featureList.isEmpty() )
2291  {
2292  //raster?
2293  QDomNodeList attributeList = currentLayerElem.elementsByTagName( QStringLiteral( "Attribute" ) );
2294  QDomElement rasterLayerElem;
2295  if ( !attributeList.isEmpty() )
2296  {
2297  rasterLayerElem = SIAInfoDoc.createElement( currentLayerName );
2298  }
2299  for ( int j = 0; j < attributeList.size(); ++j )
2300  {
2301  currentAttributeElem = attributeList.at( j ).toElement();
2302  currentAttributeName = currentAttributeElem.attribute( QStringLiteral( "name" ) );
2303  currentAttributeValue = currentAttributeElem.attribute( QStringLiteral( "value" ) );
2304  QDomElement outAttributeElem = SIAInfoDoc.createElement( currentAttributeName );
2305  QDomText outAttributeText = SIAInfoDoc.createTextNode( currentAttributeValue );
2306  outAttributeElem.appendChild( outAttributeText );
2307  rasterLayerElem.appendChild( outAttributeElem );
2308  }
2309  if ( !attributeList.isEmpty() )
2310  {
2311  SIAInfoDocElement.appendChild( rasterLayerElem );
2312  }
2313  }
2314  else //vector
2315  {
2316  //property attributes
2317  QSet<QString> layerPropertyAttributes;
2318  QString currentLayerId = currentLayerElem.attribute( QStringLiteral( "id" ) );
2319  if ( !currentLayerId.isEmpty() )
2320  {
2321  QgsMapLayer *currentLayer = mProject->mapLayer( currentLayerId );
2322  if ( currentLayer )
2323  {
2324  QString WMSPropertyAttributesString = currentLayer->customProperty( QStringLiteral( "WMSPropertyAttributes" ) ).toString();
2325  if ( !WMSPropertyAttributesString.isEmpty() )
2326  {
2327  QStringList propertyList = WMSPropertyAttributesString.split( QStringLiteral( "//" ) );
2328  for ( auto propertyIt = propertyList.constBegin() ; propertyIt != propertyList.constEnd(); ++propertyIt )
2329  {
2330  layerPropertyAttributes.insert( *propertyIt );
2331  }
2332  }
2333  }
2334  }
2335 
2336  QDomElement propertyRefChild; //child to insert the next property after (or
2337  for ( int j = 0; j < featureList.size(); ++j )
2338  {
2339  QDomElement SIAFeatureElem = SIAInfoDoc.createElement( currentLayerName );
2340  currentFeatureElem = featureList.at( j ).toElement();
2341  QDomNodeList attributeList = currentFeatureElem.elementsByTagName( QStringLiteral( "Attribute" ) );
2342 
2343  for ( int k = 0; k < attributeList.size(); ++k )
2344  {
2345  currentAttributeElem = attributeList.at( k ).toElement();
2346  currentAttributeName = currentAttributeElem.attribute( QStringLiteral( "name" ) );
2347  currentAttributeValue = currentAttributeElem.attribute( QStringLiteral( "value" ) );
2348  if ( layerPropertyAttributes.contains( currentAttributeName ) )
2349  {
2350  QDomElement propertyElem = SIAInfoDoc.createElement( QStringLiteral( "property" ) );
2351  QDomElement identifierElem = SIAInfoDoc.createElement( QStringLiteral( "identifier" ) );
2352  QDomText identifierText = SIAInfoDoc.createTextNode( currentAttributeName );
2353  identifierElem.appendChild( identifierText );
2354  QDomElement valueElem = SIAInfoDoc.createElement( QStringLiteral( "value" ) );
2355  QDomText valueText = SIAInfoDoc.createTextNode( currentAttributeValue );
2356  valueElem.appendChild( valueText );
2357  propertyElem.appendChild( identifierElem );
2358  propertyElem.appendChild( valueElem );
2359  if ( propertyRefChild.isNull() )
2360  {
2361  SIAFeatureElem.insertBefore( propertyElem, QDomNode() );
2362  propertyRefChild = propertyElem;
2363  }
2364  else
2365  {
2366  SIAFeatureElem.insertAfter( propertyElem, propertyRefChild );
2367  }
2368  }
2369  else
2370  {
2371  QDomElement SIAAttributeElem = SIAInfoDoc.createElement( currentAttributeName );
2372  QDomText SIAAttributeText = SIAInfoDoc.createTextNode( currentAttributeValue );
2373  SIAAttributeElem.appendChild( SIAAttributeText );
2374  SIAFeatureElem.appendChild( SIAAttributeElem );
2375  }
2376  }
2377  SIAInfoDocElement.appendChild( SIAFeatureElem );
2378  }
2379  }
2380  }
2381  doc = SIAInfoDoc;
2382  }
2383 
2384  QByteArray QgsRenderer::convertFeatureInfoToHtml( const QDomDocument &doc ) const
2385  {
2386  QString featureInfoString;
2387 
2388  //the HTML head
2389  featureInfoString.append( "<HEAD>\n" );
2390  featureInfoString.append( "<TITLE> GetFeatureInfo results </TITLE>\n" );
2391  featureInfoString.append( "<META http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\"/>\n" );
2392  featureInfoString.append( "</HEAD>\n" );
2393 
2394  //start the html body
2395  featureInfoString.append( "<BODY>\n" );
2396 
2397  QDomNodeList layerList = doc.elementsByTagName( QStringLiteral( "Layer" ) );
2398 
2399  //layer loop
2400  for ( int i = 0; i < layerList.size(); ++i )
2401  {
2402  QDomElement layerElem = layerList.at( i ).toElement();
2403 
2404  featureInfoString.append( "<TABLE border=1 width=100%>\n" );
2405  featureInfoString.append( "<TR><TH width=25%>Layer</TH><TD>" + layerElem.attribute( QStringLiteral( "name" ) ) + "</TD></TR>\n" );
2406  featureInfoString.append( "</BR>" );
2407 
2408  //feature loop (for vector layers)
2409  QDomNodeList featureNodeList = layerElem.elementsByTagName( QStringLiteral( "Feature" ) );
2410  QDomElement currentFeatureElement;
2411 
2412  if ( !featureNodeList.isEmpty() ) //vector layer
2413  {
2414  for ( int j = 0; j < featureNodeList.size(); ++j )
2415  {
2416  QDomElement featureElement = featureNodeList.at( j ).toElement();
2417  featureInfoString.append( "<TABLE border=1 width=100%>\n" );
2418  featureInfoString.append( "<TR><TH>Feature</TH><TD>" + featureElement.attribute( QStringLiteral( "id" ) ) +
2419  "</TD></TR>\n" );
2420 
2421  //attribute loop
2422  QDomNodeList attributeNodeList = featureElement.elementsByTagName( QStringLiteral( "Attribute" ) );
2423  for ( int k = 0; k < attributeNodeList.size(); ++k )
2424  {
2425  QDomElement attributeElement = attributeNodeList.at( k ).toElement();
2426  featureInfoString.append( "<TR><TH>" + attributeElement.attribute( QStringLiteral( "name" ) ) +
2427  "</TH><TD>" + attributeElement.attribute( QStringLiteral( "value" ) ) + "</TD></TR>\n" );
2428  }
2429 
2430  featureInfoString.append( "</TABLE>\n</BR>\n" );
2431  }
2432  }
2433  else //raster layer
2434  {
2435  QDomNodeList attributeNodeList = layerElem.elementsByTagName( QStringLiteral( "Attribute" ) );
2436  for ( int j = 0; j < attributeNodeList.size(); ++j )
2437  {
2438  QDomElement attributeElement = attributeNodeList.at( j ).toElement();
2439  QString value = attributeElement.attribute( QStringLiteral( "value" ) );
2440  if ( value.isEmpty() )
2441  {
2442  value = QStringLiteral( "no data" );
2443  }
2444  featureInfoString.append( "<TR><TH>" + attributeElement.attribute( QStringLiteral( "name" ) ) +
2445  "</TH><TD>" + value + "</TD></TR>\n" );
2446  }
2447  }
2448 
2449  featureInfoString.append( "</TABLE>\n<BR></BR>\n" );
2450  }
2451 
2452  //start the html body
2453  featureInfoString.append( "</BODY>\n" );
2454 
2455  return featureInfoString.toUtf8();
2456  }
2457 
2458  QByteArray QgsRenderer::convertFeatureInfoToText( const QDomDocument &doc ) const
2459  {
2460  QString featureInfoString;
2461 
2462  //the Text head
2463  featureInfoString.append( "GetFeatureInfo results\n" );
2464  featureInfoString.append( "\n" );
2465 
2466  QDomNodeList layerList = doc.elementsByTagName( QStringLiteral( "Layer" ) );
2467 
2468  //layer loop
2469  for ( int i = 0; i < layerList.size(); ++i )
2470  {
2471  QDomElement layerElem = layerList.at( i ).toElement();
2472 
2473  featureInfoString.append( "Layer '" + layerElem.attribute( QStringLiteral( "name" ) ) + "'\n" );
2474 
2475  //feature loop (for vector layers)
2476  QDomNodeList featureNodeList = layerElem.elementsByTagName( QStringLiteral( "Feature" ) );
2477  QDomElement currentFeatureElement;
2478 
2479  if ( !featureNodeList.isEmpty() ) //vector layer
2480  {
2481  for ( int j = 0; j < featureNodeList.size(); ++j )
2482  {
2483  QDomElement featureElement = featureNodeList.at( j ).toElement();
2484  featureInfoString.append( "Feature " + featureElement.attribute( QStringLiteral( "id" ) ) + "\n" );
2485 
2486  //attribute loop
2487  QDomNodeList attributeNodeList = featureElement.elementsByTagName( QStringLiteral( "Attribute" ) );
2488  for ( int k = 0; k < attributeNodeList.size(); ++k )
2489  {
2490  QDomElement attributeElement = attributeNodeList.at( k ).toElement();
2491  featureInfoString.append( attributeElement.attribute( QStringLiteral( "name" ) ) + " = '" +
2492  attributeElement.attribute( QStringLiteral( "value" ) ) + "'\n" );
2493  }
2494  }
2495  }
2496  else //raster layer
2497  {
2498  QDomNodeList attributeNodeList = layerElem.elementsByTagName( QStringLiteral( "Attribute" ) );
2499  for ( int j = 0; j < attributeNodeList.size(); ++j )
2500  {
2501  QDomElement attributeElement = attributeNodeList.at( j ).toElement();
2502  QString value = attributeElement.attribute( QStringLiteral( "value" ) );
2503  if ( value.isEmpty() )
2504  {
2505  value = QStringLiteral( "no data" );
2506  }
2507  featureInfoString.append( attributeElement.attribute( QStringLiteral( "name" ) ) + " = '" +
2508  value + "'\n" );
2509  }
2510  }
2511 
2512  featureInfoString.append( "\n" );
2513  }
2514 
2515  return featureInfoString.toUtf8();
2516  }
2517 
2518  QByteArray QgsRenderer::convertFeatureInfoToJson( const QList<QgsMapLayer *> &layers, const QDomDocument &doc ) const
2519  {
2520  json json
2521  {
2522  { "type", "FeatureCollection" },
2523  { "features", json::array() },
2524  };
2525  const bool withGeometry = ( QgsServerProjectUtils::wmsFeatureInfoAddWktGeometry( *mProject ) && mWmsParameters.withGeometry() );
2526 
2527  const QDomNodeList layerList = doc.elementsByTagName( QStringLiteral( "Layer" ) );
2528  for ( int i = 0; i < layerList.size(); ++i )
2529  {
2530  const QDomElement layerElem = layerList.at( i ).toElement();
2531  const QString layerName = layerElem.attribute( QStringLiteral( "name" ) );
2532 
2533  QgsMapLayer *layer = nullptr;
2534  for ( QgsMapLayer *l : layers )
2535  {
2536  if ( mContext.layerNickname( *l ).compare( layerName ) == 0 )
2537  {
2538  layer = l;
2539  }
2540  }
2541 
2542  if ( !layer )
2543  continue;
2544 
2545  if ( layer->type() == QgsMapLayerType::VectorLayer )
2546  {
2547  QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer );
2548 
2549  // search features to export
2550  QgsFeatureList features;
2551  QgsAttributeList attributes;
2552  const QDomNodeList featuresNode = layerElem.elementsByTagName( QStringLiteral( "Feature" ) );
2553  if ( featuresNode.isEmpty() )
2554  continue;
2555 
2556  QMap<QgsFeatureId, QString> fidMap;
2557 
2558  for ( int j = 0; j < featuresNode.size(); ++j )
2559  {
2560  const QDomElement featureNode = featuresNode.at( j ).toElement();
2561  const QString fid = featureNode.attribute( QStringLiteral( "id" ) );
2562  QgsFeature feature;
2563  const QString expression { QgsServerFeatureId::getExpressionFromServerFid( fid, static_cast<QgsVectorDataProvider *>( layer->dataProvider() ) ) };
2564  if ( expression.isEmpty() )
2565  {
2566  feature = vl->getFeature( fid.toLongLong() );
2567  }
2568  else
2569  {
2570  QgsFeatureRequest request { QgsExpression( expression )};
2571  request.setFlags( QgsFeatureRequest::Flag::NoGeometry );
2572  vl->getFeatures( request ).nextFeature( feature );
2573  }
2574 
2575  fidMap.insert( feature.id(), fid );
2576 
2577  QString wkt;
2578  if ( withGeometry )
2579  {
2580  const QDomNodeList attrs = featureNode.elementsByTagName( "Attribute" );
2581  for ( int k = 0; k < attrs.count(); k++ )
2582  {
2583  const QDomElement elm = attrs.at( k ).toElement();
2584  if ( elm.attribute( QStringLiteral( "name" ) ).compare( "geometry" ) == 0 )
2585  {
2586  wkt = elm.attribute( "value" );
2587  break;
2588  }
2589  }
2590 
2591  if ( ! wkt.isEmpty() )
2592  {
2593  // CRS in WMS parameters may be different from the layer
2594  feature.setGeometry( QgsGeometry::fromWkt( wkt ) );
2595  }
2596  }
2597  features << feature;
2598 
2599  // search attributes to export (one time only)
2600  if ( !attributes.isEmpty() )
2601  continue;
2602 
2603  const QDomNodeList attributesNode = featureNode.elementsByTagName( QStringLiteral( "Attribute" ) );
2604  for ( int k = 0; k < attributesNode.size(); ++k )
2605  {
2606  const QDomElement attributeElement = attributesNode.at( k ).toElement();
2607  const QString fieldName = attributeElement.attribute( QStringLiteral( "name" ) );
2608 
2609  attributes << feature.fieldNameIndex( fieldName );
2610  }
2611  }
2612 
2613  // export
2614  QgsJsonExporter exporter( vl );
2615  exporter.setAttributeDisplayName( true );
2616  exporter.setAttributes( attributes );
2617  exporter.setIncludeGeometry( withGeometry );
2618  exporter.setTransformGeometries( false );
2619 
2620  for ( const auto &feature : std::as_const( features ) )
2621  {
2622  const QString id = QStringLiteral( "%1.%2" ).arg( layerName ).arg( fidMap.value( feature.id() ) );
2623  json["features"].push_back( exporter.exportFeatureToJsonObject( feature, QVariantMap(), id ) );
2624  }
2625  }
2626  else // raster layer
2627  {
2628  auto properties = json::object();
2629  const QDomNodeList attributesNode = layerElem.elementsByTagName( QStringLiteral( "Attribute" ) );
2630  for ( int j = 0; j < attributesNode.size(); ++j )
2631  {
2632  const QDomElement attrElmt = attributesNode.at( j ).toElement();
2633  const QString name = attrElmt.attribute( QStringLiteral( "name" ) );
2634 
2635  QString value = attrElmt.attribute( QStringLiteral( "value" ) );
2636  if ( value.isEmpty() )
2637  {
2638  value = QStringLiteral( "null" );
2639  }
2640 
2641  properties[name.toStdString()] = value.toStdString();
2642  }
2643 
2644  json["features"].push_back(
2645  {
2646  {"type", "Feature" },
2647  {"id", layerName.toStdString() },
2648  {"properties", properties }
2649  } );
2650  }
2651  }
2652 #ifdef QGISDEBUG
2653  // This is only useful to generate human readable reference files for tests
2654  return QByteArray::fromStdString( json.dump( 2 ) );
2655 #else
2656  return QByteArray::fromStdString( json.dump() );
2657 #endif
2658  }
2659 
2660  QDomElement QgsRenderer::createFeatureGML(
2661  const QgsFeature *feat,
2662  QgsVectorLayer *layer,
2663  QDomDocument &doc,
2665  const QgsMapSettings &mapSettings,
2666  const QString &typeName,
2667  bool withGeom,
2668  int version,
2669  QStringList *attributes ) const
2670  {
2671  //qgs:%TYPENAME%
2672  QDomElement typeNameElement = doc.createElement( "qgs:" + typeName /*qgs:%TYPENAME%*/ );
2673  QString fid;
2674  if ( layer && layer->dataProvider() )
2676  else
2677  fid = FID_TO_STRING( feat->id() );
2678 
2679  typeNameElement.setAttribute( QStringLiteral( "fid" ), QStringLiteral( "%1.%2" ).arg( typeName, fid ) );
2680 
2681  QgsCoordinateTransform transform;
2682  if ( layer && layer->crs() != crs )
2683  {
2684  transform = mapSettings.layerTransform( layer );
2685  }
2686 
2687  QgsGeometry geom = feat->geometry();
2688 
2689  QgsExpressionContext expressionContext;
2690  expressionContext << QgsExpressionContextUtils::globalScope()
2692  if ( layer )
2693  expressionContext << QgsExpressionContextUtils::layerScope( layer );
2694  expressionContext.setFeature( *feat );
2695 
2696  // always add bounding box info if feature contains geometry and has been
2697  // explicitly configured in the project
2699  !geom.isNull() && geom.type() != QgsWkbTypes::UnknownGeometry &&
2700  geom.type() != QgsWkbTypes::NullGeometry )
2701  {
2702  QgsRectangle box = feat->geometry().boundingBox();
2703  if ( transform.isValid() )
2704  {
2705  try
2706  {
2707  box = transform.transformBoundingBox( box );
2708  }
2709  catch ( QgsCsException &e )
2710  {
2711  QgsMessageLog::logMessage( QStringLiteral( "Transform error caught: %1" ).arg( e.what() ) );
2712  }
2713  }
2714 
2715  QDomElement bbElem = doc.createElement( QStringLiteral( "gml:boundedBy" ) );
2716  QDomElement boxElem;
2717  if ( version < 3 )
2718  {
2719  boxElem = QgsOgcUtils::rectangleToGMLBox( &box, doc, mContext.precision() );
2720  }
2721  else
2722  {
2723  boxElem = QgsOgcUtils::rectangleToGMLEnvelope( &box, doc, mContext.precision() );
2724  }
2725 
2726  if ( crs.isValid() )
2727  {
2728  boxElem.setAttribute( QStringLiteral( "srsName" ), crs.authid() );
2729  }
2730  bbElem.appendChild( boxElem );
2731  typeNameElement.appendChild( bbElem );
2732  }
2733 
2734  if ( withGeom && !geom.isNull() )
2735  {
2736  //add geometry column (as gml)
2737 
2738  if ( transform.isValid() )
2739  {
2740  geom.transform( transform );
2741  }
2742 
2743  QDomElement geomElem = doc.createElement( QStringLiteral( "qgs:geometry" ) );
2744  QDomElement gmlElem;
2745  if ( version < 3 )
2746  {
2747  gmlElem = QgsOgcUtils::geometryToGML( geom, doc, mContext.precision() );
2748  }
2749  else
2750  {
2751  gmlElem = QgsOgcUtils::geometryToGML( geom, doc, QStringLiteral( "GML3" ), mContext.precision() );
2752  }
2753 
2754  if ( !gmlElem.isNull() )
2755  {
2756  if ( crs.isValid() )
2757  {
2758  gmlElem.setAttribute( QStringLiteral( "srsName" ), crs.authid() );
2759  }
2760  geomElem.appendChild( gmlElem );
2761  typeNameElement.appendChild( geomElem );
2762  }
2763  }
2764 
2765  //read all allowed attribute values from the feature
2766  QgsAttributes featureAttributes = feat->attributes();
2767  QgsFields fields = feat->fields();
2768  for ( int i = 0; i < fields.count(); ++i )
2769  {
2770  QString attributeName = fields.at( i ).name();
2771  //skip attribute if it is explicitly excluded from WMS publication
2772  if ( fields.at( i ).configurationFlags().testFlag( QgsField::ConfigurationFlag::HideFromWms ) )
2773  {
2774  continue;
2775  }
2776  //skip attribute if it is excluded by access control
2777  if ( attributes && !attributes->contains( attributeName ) )
2778  {
2779  continue;
2780  }
2781 
2782  QDomElement fieldElem = doc.createElement( "qgs:" + attributeName.replace( ' ', '_' ) );
2783  QString fieldTextString = featureAttributes.at( i ).toString();
2784  if ( layer )
2785  {
2786  fieldTextString = QgsExpression::replaceExpressionText( replaceValueMapAndRelation( layer, i, fieldTextString ), &expressionContext );
2787  }
2788  QDomText fieldText = doc.createTextNode( fieldTextString );
2789  fieldElem.appendChild( fieldText );
2790  typeNameElement.appendChild( fieldElem );
2791  }
2792 
2793  //add maptip attribute based on html/expression (in case there is no maptip attribute)
2794  if ( layer )
2795  {
2796  QString mapTip = layer->mapTipTemplate();
2797 
2798  if ( !mapTip.isEmpty() && mWmsParameters.withMapTip() )
2799  {
2800  QString fieldTextString = QgsExpression::replaceExpressionText( mapTip, &expressionContext );
2801  QDomElement fieldElem = doc.createElement( QStringLiteral( "qgs:maptip" ) );
2802  QDomText maptipText = doc.createTextNode( fieldTextString );
2803  fieldElem.appendChild( maptipText );
2804  typeNameElement.appendChild( fieldElem );
2805  }
2806  }
2807 
2808  return typeNameElement;
2809  }
2810 
2811  QString QgsRenderer::replaceValueMapAndRelation( QgsVectorLayer *vl, int idx, const QVariant &attributeVal )
2812  {
2813  const QgsEditorWidgetSetup setup = vl->editorWidgetSetup( idx );
2815  QString value( fieldFormatter->representValue( vl, idx, setup.config(), QVariant(), attributeVal ) );
2816 
2817  if ( setup.config().value( QStringLiteral( "AllowMulti" ) ).toBool() && value.startsWith( QLatin1Char( '{' ) ) && value.endsWith( QLatin1Char( '}' ) ) )
2818  {
2819  value = value.mid( 1, value.size() - 2 );
2820  }
2821  return value;
2822  }
2823 
2824  QgsRectangle QgsRenderer::featureInfoSearchRect( QgsVectorLayer *ml, const QgsMapSettings &mapSettings, const QgsRenderContext &rct, const QgsPointXY &infoPoint ) const
2825  {
2826  if ( !ml )
2827  {
2828  return QgsRectangle();
2829  }
2830 
2831  double mapUnitTolerance = 0.0;
2833  {
2834  if ( ! mWmsParameters.polygonTolerance().isEmpty()
2835  && mWmsParameters.polygonToleranceAsInt() > 0 )
2836  {
2837  mapUnitTolerance = mWmsParameters.polygonToleranceAsInt() * rct.mapToPixel().mapUnitsPerPixel();
2838  }
2839  else
2840  {
2841  mapUnitTolerance = mapSettings.extent().width() / 400.0;
2842  }
2843  }
2844  else if ( ml->geometryType() == QgsWkbTypes::LineGeometry )
2845  {
2846  if ( ! mWmsParameters.lineTolerance().isEmpty()
2847  && mWmsParameters.lineToleranceAsInt() > 0 )
2848  {
2849  mapUnitTolerance = mWmsParameters.lineToleranceAsInt() * rct.mapToPixel().mapUnitsPerPixel();
2850  }
2851  else
2852  {
2853  mapUnitTolerance = mapSettings.extent().width() / 200.0;
2854  }
2855  }
2856  else //points
2857  {
2858  if ( ! mWmsParameters.pointTolerance().isEmpty()
2859  && mWmsParameters.pointToleranceAsInt() > 0 )
2860  {
2861  mapUnitTolerance = mWmsParameters.pointToleranceAsInt() * rct.mapToPixel().mapUnitsPerPixel();
2862  }
2863  else
2864  {
2865  mapUnitTolerance = mapSettings.extent().width() / 100.0;
2866  }
2867  }
2868 
2869  QgsRectangle mapRectangle( infoPoint.x() - mapUnitTolerance, infoPoint.y() - mapUnitTolerance,
2870  infoPoint.x() + mapUnitTolerance, infoPoint.y() + mapUnitTolerance );
2871  return ( mapSettings.mapToLayerCoordinates( ml, mapRectangle ) );
2872  }
2873 
2874  QList<QgsMapLayer *> QgsRenderer::highlightLayers( QList<QgsWmsParametersHighlightLayer> params )
2875  {
2876  QList<QgsMapLayer *> highlightLayers;
2877 
2878  // try to create highlight layer for each geometry
2879  QString crs = mWmsParameters.crs();
2880  for ( const QgsWmsParametersHighlightLayer &param : params )
2881  {
2882  // create sld document from symbology
2883  QDomDocument sldDoc;
2884  QString errorMsg;
2885  int errorLine;
2886  int errorColumn;
2887  if ( !sldDoc.setContent( param.mSld, true, &errorMsg, &errorLine, &errorColumn ) )
2888  {
2889  QgsMessageLog::logMessage( QStringLiteral( "Error parsing SLD for layer %1 at line %2, column %3:\n%4" )
2890  .arg( param.mName )
2891  .arg( errorLine )
2892  .arg( errorColumn )
2893  .arg( errorMsg ),
2894  QStringLiteral( "Server" ), Qgis::MessageLevel::Warning );
2895  continue;
2896  }
2897 
2898  // create renderer from sld document
2899  std::unique_ptr<QgsFeatureRenderer> renderer;
2900  QDomElement el = sldDoc.documentElement();
2901  renderer.reset( QgsFeatureRenderer::loadSld( el, param.mGeom.type(), errorMsg ) );
2902  if ( !renderer )
2903  {
2904  QgsMessageLog::logMessage( errorMsg, "Server", Qgis::MessageLevel::Info );
2905  continue;
2906  }
2907 
2908  // build url for vector layer
2909  const QString typeName = QgsWkbTypes::displayString( param.mGeom.wkbType() );
2910  QString url = typeName + "?crs=" + crs;
2911  if ( ! param.mLabel.isEmpty() )
2912  {
2913  url += "&field=label:string";
2914  }
2915 
2916  // create vector layer
2918  std::unique_ptr<QgsVectorLayer> layer = std::make_unique<QgsVectorLayer>( url, param.mName, QLatin1String( "memory" ), options );
2919  if ( !layer->isValid() )
2920  {
2921  continue;
2922  }
2923 
2924  // create feature with label if necessary
2925  QgsFeature fet( layer->fields() );
2926  if ( ! param.mLabel.isEmpty() )
2927  {
2928  fet.setAttribute( 0, param.mLabel );
2929 
2930  // init labeling engine
2931  QgsPalLayerSettings palSettings;
2932  palSettings.fieldName = "label"; // defined in url
2933  palSettings.priority = 10; // always drawn
2935  palSettings.placementSettings().setAllowDegradedPlacement( true );
2936  palSettings.dist = param.mLabelDistance;
2937 
2938  if ( !qgsDoubleNear( param.mLabelRotation, 0 ) )
2939  {
2941  palSettings.dataDefinedProperties().setProperty( pR, param.mLabelRotation );
2942  }
2943 
2945  switch ( param.mGeom.type() )
2946  {
2948  {
2949  if ( param.mHali.isEmpty() || param.mVali.isEmpty() || QgsWkbTypes::flatType( param.mGeom.wkbType() ) != QgsWkbTypes::Point )
2950  {
2952  palSettings.lineSettings().setPlacementFlags( QgsLabeling::LinePlacementFlags() );
2953  }
2954  else //set label directly on point if there is hali/vali
2955  {
2956  QgsPointXY pt = param.mGeom.asPoint();
2958  QVariant x( pt.x() );
2959  palSettings.dataDefinedProperties().setProperty( pX, x );
2961  QVariant y( pt.y() );
2962  palSettings.dataDefinedProperties().setProperty( pY, y );
2964  palSettings.dataDefinedProperties().setProperty( pHali, param.mHali );
2966  palSettings.dataDefinedProperties().setProperty( pVali, param.mVali );
2967  }
2968 
2969  break;
2970  }
2972  {
2973  QgsGeometry point = param.mGeom.pointOnSurface();
2974  QgsPointXY pt = point.asPoint();
2976 
2978  QVariant x( pt.x() );
2979  palSettings.dataDefinedProperties().setProperty( pX, x );
2980 
2982  QVariant y( pt.y() );
2983  palSettings.dataDefinedProperties().setProperty( pY, y );
2984 
2986  QVariant hali( "Center" );
2987  palSettings.dataDefinedProperties().setProperty( pHali, hali );
2988 
2990  QVariant vali( "Half" );
2991  palSettings.dataDefinedProperties().setProperty( pVali, vali );
2992  break;
2993  }
2994  default:
2995  {
2996  placement = Qgis::LabelPlacement::Line;
2997  palSettings.lineSettings().setPlacementFlags( QgsLabeling::LinePlacementFlag::AboveLine | QgsLabeling::LinePlacementFlag::MapOrientation );
2998  break;
2999  }
3000  }
3001  palSettings.placement = placement;
3002  QgsTextFormat textFormat;
3003  QgsTextBufferSettings bufferSettings;
3004 
3005  if ( param.mColor.isValid() )
3006  {
3007  textFormat.setColor( param.mColor );
3008  }
3009 
3010  if ( param.mSize > 0 )
3011  {
3012  textFormat.setSize( param.mSize );
3013  }
3014 
3015  // no weight property in PAL settings or QgsTextFormat
3016  /* if ( param.fontWeight > 0 )
3017  {
3018  } */
3019 
3020  if ( ! param.mFont.isEmpty() )
3021  {
3022  textFormat.setFont( param.mFont );
3023  }
3024 
3025  if ( param.mBufferColor.isValid() )
3026  {
3027  bufferSettings.setColor( param.mBufferColor );
3028  }
3029 
3030  if ( param.mBufferSize > 0 )
3031  {
3032  bufferSettings.setEnabled( true );
3033  bufferSettings.setSize( static_cast<double>( param.mBufferSize ) );
3034  }
3035 
3036  textFormat.setBuffer( bufferSettings );
3037  palSettings.setFormat( textFormat );
3038 
3039  QgsVectorLayerSimpleLabeling *simpleLabeling = new QgsVectorLayerSimpleLabeling( palSettings );
3040  layer->setLabeling( simpleLabeling );
3041  layer->setLabelsEnabled( true );
3042  }
3043  fet.setGeometry( param.mGeom );
3044 
3045  // add feature to layer and set the SLD renderer
3046  layer->dataProvider()->addFeatures( QgsFeatureList() << fet );
3047  layer->setRenderer( renderer.release() );
3048 
3049  // keep the vector as an highlight layer
3050  if ( layer->isValid() )
3051  {
3052  highlightLayers.append( layer.release() );
3053  }
3054  }
3055 
3056  mTemporaryLayers.append( highlightLayers );
3057  return highlightLayers;
3058  }
3059 
3060  void QgsRenderer::removeTemporaryLayers()
3061  {
3062  qDeleteAll( mTemporaryLayers );
3063  mTemporaryLayers.clear();
3064  }
3065 
3066  QPainter *QgsRenderer::layersRendering( const QgsMapSettings &mapSettings, QImage &image ) const
3067  {
3068  QPainter *painter = nullptr;
3069 
3071  filters.addProvider( &mFeatureFilter );
3072 #ifdef HAVE_SERVER_PYTHON_PLUGINS
3073  mContext.accessControl()->resolveFilterFeatures( mapSettings.layers() );
3074  filters.addProvider( mContext.accessControl() );
3075 #endif
3076  QgsMapRendererJobProxy renderJob( mContext.settings().parallelRendering(), mContext.settings().maxThreads(), &filters );
3077  renderJob.render( mapSettings, &image );
3078  painter = renderJob.takePainter();
3079 
3080  if ( !renderJob.errors().isEmpty() )
3081  {
3082  QString layerWMSName;
3083  QString firstErrorLayerId = renderJob.errors().at( 0 ).layerID;
3084  QgsMapLayer *errorLayer = mProject->mapLayer( firstErrorLayerId );
3085  if ( errorLayer )
3086  {
3087  layerWMSName = mContext.layerNickname( *errorLayer );
3088  }
3089 
3090  throw QgsException( QStringLiteral( "Map rendering error in layer '%1'" ).arg( layerWMSName ) );
3091  }
3092 
3093  return painter;
3094  }
3095 
3096  void QgsRenderer::setLayerOpacity( QgsMapLayer *layer, int opacity ) const
3097  {
3098  if ( opacity >= 0 && opacity <= 255 )
3099  {
3100  switch ( layer->type() )
3101  {
3103  {
3104  QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer );
3105  vl->setOpacity( opacity / 255. );
3106  break;
3107  }
3108 
3110  {
3111  QgsRasterLayer *rl = qobject_cast<QgsRasterLayer *>( layer );
3112  QgsRasterRenderer *rasterRenderer = rl->renderer();
3113  rasterRenderer->setOpacity( opacity / 255. );
3114  break;
3115  }
3116 
3123  break;
3124  }
3125  }
3126  }
3127 
3128  void QgsRenderer::setLayerFilter( QgsMapLayer *layer, const QList<QgsWmsParametersFilter> &filters )
3129  {
3130  if ( layer->type() == QgsMapLayerType::VectorLayer )
3131  {
3132  QgsVectorLayer *filteredLayer = qobject_cast<QgsVectorLayer *>( layer );
3133  QStringList expList;
3134  for ( const QgsWmsParametersFilter &filter : filters )
3135  {
3136  if ( filter.mType == QgsWmsParametersFilter::OGC_FE )
3137  {
3138  // OGC filter
3139  QDomDocument filterXml;
3140  QString errorMsg;
3141  if ( !filterXml.setContent( filter.mFilter, true, &errorMsg ) )
3142  {
3144  QStringLiteral( "Filter string rejected. Error message: %1. The XML string was: %2" ).arg( errorMsg, filter.mFilter ) );
3145  }
3146  QDomElement filterElem = filterXml.firstChildElement();
3147  std::unique_ptr<QgsExpression> filterExp( QgsOgcUtils::expressionFromOgcFilter( filterElem, filter.mVersion, filteredLayer ) );
3148 
3149  if ( filterExp )
3150  {
3151  expList << filterExp->dump();
3152  }
3153  }
3154  else if ( filter.mType == QgsWmsParametersFilter::SQL )
3155  {
3156  // QGIS (SQL) filter
3157  if ( !testFilterStringSafety( filter.mFilter ) )
3158  {
3159  throw QgsSecurityException( QStringLiteral( "The filter string %1"
3160  " has been rejected because of security reasons."
3161  " Note: Text strings have to be enclosed in single or double quotes."
3162  " A space between each word / special character is mandatory."
3163  " Allowed Keywords and special characters are "
3164  " IS,NOT,NULL,AND,OR,IN,=,<,>=,>,>=,!=,',',(,),DMETAPHONE,SOUNDEX."
3165  " Not allowed are semicolons in the filter expression." ).arg(
3166  filter.mFilter ) );
3167  }
3168 
3169  QString newSubsetString = filter.mFilter;
3170  if ( !filteredLayer->subsetString().isEmpty() )
3171  {
3172  newSubsetString.prepend( ") AND (" );
3173  newSubsetString.append( ")" );
3174  newSubsetString.prepend( filteredLayer->subsetString() );
3175  newSubsetString.prepend( "(" );
3176  }
3177  if ( ! filteredLayer->setSubsetString( newSubsetString ) )
3178  {
3179  QgsMessageLog::logMessage( QStringLiteral( "Error setting subset string from filter for layer %1, filter: %2" ).arg( layer->name(), newSubsetString ),
3180  QStringLiteral( "Server" ),
3181  Qgis::MessageLevel::Warning );
3183  QStringLiteral( "Filter not valid for layer %1: check the filter syntax and the field names." ).arg( layer->name() ) );
3184 
3185  }
3186  }
3187  }
3188 
3189  expList.append( dimensionFilter( filteredLayer ) );
3190 
3191  // Join and apply expressions provided by OGC filter and Dimensions
3192  QString exp;
3193  if ( expList.size() == 1 )
3194  {
3195  exp = expList[0];
3196  }
3197  else if ( expList.size() > 1 )
3198  {
3199  exp = QStringLiteral( "( %1 )" ).arg( expList.join( QLatin1String( " ) AND ( " ) ) );
3200  }
3201  if ( !exp.isEmpty() )
3202  {
3203  std::unique_ptr<QgsExpression> expression( new QgsExpression( exp ) );
3204  if ( expression )
3205  {
3206  mFeatureFilter.setFilter( filteredLayer, *expression );
3207  }
3208  }
3209  }
3210  }
3211 
3212  QStringList QgsRenderer::dimensionFilter( QgsVectorLayer *layer ) const
3213  {
3214  QStringList expList;
3215  // WMS Dimension filters
3216  QgsMapLayerServerProperties *serverProperties = static_cast<QgsMapLayerServerProperties *>( layer->serverProperties() );
3217  const QList<QgsMapLayerServerProperties::WmsDimensionInfo> wmsDims = serverProperties->wmsDimensions();
3218  if ( wmsDims.isEmpty() )
3219  {
3220  return expList;
3221  }
3222 
3223  QMap<QString, QString> dimParamValues = mContext.parameters().dimensionValues();
3224  for ( const QgsMapLayerServerProperties::WmsDimensionInfo &dim : wmsDims )
3225  {
3226  // Skip temporal properties for this layer, give precedence to the dimensions implementation
3227  if ( mIsTemporal && dim.name.toUpper() == QLatin1String( "TIME" ) && layer->temporalProperties()->isActive() )
3228  {
3229  layer->temporalProperties()->setIsActive( false );
3230  }
3231  // Check field index
3232  int fieldIndex = layer->fields().indexOf( dim.fieldName );
3233  if ( fieldIndex == -1 )
3234  {
3235  continue;
3236  }
3237  // Check end field index
3238  int endFieldIndex = -1;
3239  if ( !dim.endFieldName.isEmpty() )
3240  {
3241  endFieldIndex = layer->fields().indexOf( dim.endFieldName );
3242  if ( endFieldIndex == -1 )
3243  {
3244  continue;
3245  }
3246  }
3247  // Apply dimension filtering
3248  if ( !dimParamValues.contains( dim.name.toUpper() ) )
3249  {
3250  // Default value based on type configured by user
3251  QVariant defValue;
3252  if ( dim.defaultDisplayType == QgsMapLayerServerProperties::WmsDimensionInfo::AllValues )
3253  {
3254  continue; // no filter by default for this dimension
3255  }
3256  else if ( dim.defaultDisplayType == QgsMapLayerServerProperties::WmsDimensionInfo::ReferenceValue )
3257  {
3258  defValue = dim.referenceValue;
3259  }
3260  else
3261  {
3262  // get unique values
3263  QSet<QVariant> uniqueValues = layer->uniqueValues( fieldIndex );
3264  if ( endFieldIndex != -1 )
3265  {
3266  uniqueValues.unite( layer->uniqueValues( endFieldIndex ) );
3267  }
3268  // sort unique values
3269  QList<QVariant> values = qgis::setToList( uniqueValues );
3270  std::sort( values.begin(), values.end() );
3271  if ( dim.defaultDisplayType == QgsMapLayerServerProperties::WmsDimensionInfo::MinValue )
3272  {
3273  defValue = values.first();
3274  }
3275  else if ( dim.defaultDisplayType == QgsMapLayerServerProperties::WmsDimensionInfo::MaxValue )
3276  {
3277  defValue = values.last();
3278  }
3279  }
3280  // build expression
3281  if ( endFieldIndex == -1 )
3282  {
3283  expList << QgsExpression::createFieldEqualityExpression( dim.fieldName, defValue );
3284  }
3285  else
3286  {
3287  QStringList expElems;
3288  expElems << QgsExpression::quotedColumnRef( dim.fieldName )
3289  << QStringLiteral( "<=" ) << QgsExpression::quotedValue( defValue )
3290  << QStringLiteral( "AND" ) << QgsExpression::quotedColumnRef( dim.endFieldName )
3291  << QStringLiteral( ">=" ) << QgsExpression::quotedValue( defValue );
3292  expList << expElems.join( ' ' );
3293  }
3294  }
3295  else
3296  {
3297  // Get field to convert value provided in parameters
3298  QgsField dimField = layer->fields().at( fieldIndex );
3299  // Value provided in parameters
3300  QString dimParamValue = dimParamValues[dim.name.toUpper()];
3301  // The expression list for this dimension
3302  QStringList dimExplist;
3303  // Multiple values are separated by ,
3304  QStringList dimValues = dimParamValue.split( ',' );
3305  for ( int i = 0; i < dimValues.size(); ++i )
3306  {
3307  QString dimValue = dimValues[i];
3308  // Trim value if necessary
3309  if ( dimValue.size() > 1 )
3310  {
3311  dimValue = dimValue.trimmed();
3312  }
3313  // Range value is separated by / for example 0/1
3314  if ( dimValue.contains( '/' ) )
3315  {
3316  QStringList rangeValues = dimValue.split( '/' );
3317  // Check range value size
3318  if ( rangeValues.size() != 2 )
3319  {
3320  continue; // throw an error
3321  }
3322  // Get range values
3323  QVariant rangeMin = QVariant( rangeValues[0] );
3324  QVariant rangeMax = QVariant( rangeValues[1] );
3325  // Convert and check range values
3326  if ( !dimField.convertCompatible( rangeMin ) )
3327  {
3328  continue; // throw an error
3329  }
3330  if ( !dimField.convertCompatible( rangeMax ) )
3331  {
3332  continue; // throw an error
3333  }
3334  // Build expression for this range
3335  QStringList expElems;
3336  if ( endFieldIndex == -1 )
3337  {
3338  // The field values are between min and max range
3339  expElems << QgsExpression::quotedColumnRef( dim.fieldName )
3340  << QStringLiteral( ">=" ) << QgsExpression::quotedValue( rangeMin )
3341  << QStringLiteral( "AND" ) << QgsExpression::quotedColumnRef( dim.fieldName )
3342  << QStringLiteral( "<=" ) << QgsExpression::quotedValue( rangeMax );
3343  }
3344  else
3345  {
3346  // The start field or the end field are lesser than min range
3347  // or the start field or the end field are greater than min range
3348  expElems << QStringLiteral( "(" ) << QgsExpression::quotedColumnRef( dim.fieldName )
3349  << QStringLiteral( ">=" ) << QgsExpression::quotedValue( rangeMin )
3350  << QStringLiteral( "OR" ) << QgsExpression::quotedColumnRef( dim.endFieldName )
3351  << QStringLiteral( ">=" ) << QgsExpression::quotedValue( rangeMin )
3352  << QStringLiteral( ") AND (" ) << QgsExpression::quotedColumnRef( dim.fieldName )
3353  << QStringLiteral( "<=" ) << QgsExpression::quotedValue( rangeMax )
3354  << QStringLiteral( "OR" ) << QgsExpression::quotedColumnRef( dim.endFieldName )
3355  << QStringLiteral( "<=" ) << QgsExpression::quotedValue( rangeMax )
3356  << QStringLiteral( ")" );
3357  }
3358  dimExplist << expElems.join( ' ' );
3359  }
3360  else
3361  {
3362  QVariant dimVariant = QVariant( dimValue );
3363  if ( !dimField.convertCompatible( dimVariant ) )
3364  {
3365  continue; // throw an error
3366  }
3367  // Build expression for this value
3368  if ( endFieldIndex == -1 )
3369  {
3370  // Field is equal to
3371  dimExplist << QgsExpression::createFieldEqualityExpression( dim.fieldName, dimVariant );
3372  }
3373  else
3374  {
3375  // The start field is lesser or equal to
3376  // and the end field is greater or equal to
3377  QStringList expElems;
3378  expElems << QgsExpression::quotedColumnRef( dim.fieldName )
3379  << QStringLiteral( "<=" ) << QgsExpression::quotedValue( dimVariant )
3380  << QStringLiteral( "AND" ) << QgsExpression::quotedColumnRef( dim.endFieldName )
3381  << QStringLiteral( ">=" ) << QgsExpression::quotedValue( dimVariant );
3382  dimExplist << expElems.join( ' ' );
3383  }
3384  }
3385  }
3386  // Build the expression for this dimension
3387  if ( dimExplist.size() == 1 )
3388  {
3389  expList << dimExplist;
3390  }
3391  else if ( dimExplist.size() > 1 )
3392  {
3393  expList << QStringLiteral( "( %1 )" ).arg( dimExplist.join( QLatin1String( " ) OR ( " ) ) );
3394  }
3395  }
3396  }
3397  return expList;
3398  }
3399 
3400  void QgsRenderer::setLayerSelection( QgsMapLayer *layer, const QStringList &fids ) const
3401  {
3402  if ( !fids.empty() && layer->type() == QgsMapLayerType::VectorLayer )
3403  {
3404  QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer );
3405 
3406  QgsFeatureRequest request;
3408  const QgsFeatureIds selectedIds = request.filterFids();
3409 
3410  if ( selectedIds.empty() )
3411  {
3412  vl->selectByExpression( request.filterExpression()->expression() );
3413  }
3414  else
3415  {
3416  vl->selectByIds( selectedIds );
3417  }
3418  }
3419  }
3420 
3421  void QgsRenderer::setLayerAccessControlFilter( QgsMapLayer *layer ) const
3422  {
3423 #ifdef HAVE_SERVER_PYTHON_PLUGINS
3424  QgsOWSServerFilterRestorer::applyAccessControlLayerFilters( mContext.accessControl(), layer );
3425 #else
3426  Q_UNUSED( layer )
3427 #endif
3428  }
3429 
3430  void QgsRenderer::updateExtent( const QgsMapLayer *layer, QgsMapSettings &mapSettings ) const
3431  {
3432  QgsRectangle layerExtent = mapSettings.layerToMapCoordinates( layer, layer->extent() );
3433  QgsRectangle mapExtent = mapSettings.extent();
3434  if ( !layerExtent.isEmpty() )
3435  {
3436  mapExtent.combineExtentWith( layerExtent );
3437  mapSettings.setExtent( mapExtent );
3438  }
3439  }
3440 
3441  void QgsRenderer::annotationsRendering( QPainter *painter, const QgsMapSettings &mapSettings ) const
3442  {
3443  const QgsAnnotationManager *annotationManager = mProject->annotationManager();
3444  const QList< QgsAnnotation * > annotations = annotationManager->annotations();
3445 
3446  QgsRenderContext renderContext = QgsRenderContext::fromQPainter( painter );
3448  for ( QgsAnnotation *annotation : annotations )
3449  {
3450  if ( !annotation || !annotation->isVisible() )
3451  continue;
3452 
3453  //consider item position
3454  double offsetX = 0;
3455  double offsetY = 0;
3456  if ( annotation->hasFixedMapPosition() )
3457  {
3458  QgsPointXY mapPos = annotation->mapPosition();
3459  if ( mapSettings.destinationCrs() != annotation->mapPositionCrs() )
3460  {
3461  QgsCoordinateTransform coordTransform( annotation->mapPositionCrs(), mapSettings.destinationCrs(), mapSettings.transformContext() );
3462  try
3463  {
3464  mapPos = coordTransform.transform( mapPos );
3465  }
3466  catch ( const QgsCsException &e )
3467  {
3468  QgsMessageLog::logMessage( QStringLiteral( "Error transforming coordinates of annotation item: %1" ).arg( e.what() ) );
3469  }
3470  }
3471  const QgsPointXY devicePos = mapSettings.mapToPixel().transform( mapPos );
3472  offsetX = devicePos.x();
3473  offsetY = devicePos.y();
3474  }
3475  else
3476  {
3477  const QPointF relativePos = annotation->relativePosition();
3478  offsetX = mapSettings.outputSize().width() * relativePos.x();
3479  offsetY = mapSettings.outputSize().height() * relativePos.y();
3480  }
3481 
3482  painter->save();
3483  painter->translate( offsetX, offsetY );
3484  annotation->render( renderContext );
3485  painter->restore();
3486  }
3487  }
3488 
3489  QImage *QgsRenderer::scaleImage( const QImage *image ) const
3490  {
3491  // Test if width / height ratio of image is the same as the ratio of
3492  // WIDTH / HEIGHT parameters. If not, the image has to be scaled (required
3493  // by WMS spec)
3494  QImage *scaledImage = nullptr;
3495  const int width = mWmsParameters.widthAsInt();
3496  const int height = mWmsParameters.heightAsInt();
3497  if ( width != image->width() || height != image->height() )
3498  {
3499  scaledImage = new QImage( image->scaled( width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ) );
3500  }
3501 
3502  return scaledImage;
3503  }
3504 
3505  void QgsRenderer::handlePrintErrors( const QgsLayout *layout ) const
3506  {
3507  if ( !layout )
3508  {
3509  return;
3510  }
3511  QList< QgsLayoutItemMap * > mapList;
3512  layout->layoutItems( mapList );
3513 
3514  QList< QgsLayoutItemMap * >::const_iterator mapIt = mapList.constBegin();
3515  for ( ; mapIt != mapList.constEnd(); ++mapIt )
3516  {
3517  if ( !( *mapIt )->renderingErrors().isEmpty() )
3518  {
3519  const QgsMapRendererJob::Error e = ( *mapIt )->renderingErrors().at( 0 );
3520  throw QgsException( QStringLiteral( "Rendering error : '%1' in layer %2" ).arg( e.message, e.layerID ) );
3521  }
3522  }
3523  }
3524 
3525  void QgsRenderer::configureLayers( QList<QgsMapLayer *> &layers, QgsMapSettings *settings )
3526  {
3527  const bool useSld = !mContext.parameters().sldBody().isEmpty();
3528 
3529  for ( auto layer : layers )
3530  {
3531  const QgsWmsParametersLayer param = mContext.parameters( *layer );
3532 
3533  if ( ! mContext.layersToRender().contains( layer ) )
3534  {
3535  continue;
3536  }
3537 
3538  if ( mContext.isExternalLayer( param.mNickname ) )
3539  {
3541  {
3542  setLayerOpacity( layer, param.mOpacity );
3543  }
3544  continue;
3545  }
3546 
3547  if ( useSld )
3548  {
3549  setLayerSld( layer, mContext.sld( *layer ) );
3550  }
3551  else
3552  {
3553  setLayerStyle( layer, mContext.style( *layer ) );
3554  }
3555 
3556  if ( mContext.testFlag( QgsWmsRenderContext::UseOpacity ) )
3557  {
3558  setLayerOpacity( layer, param.mOpacity );
3559  }
3560 
3561  if ( mContext.testFlag( QgsWmsRenderContext::UseFilter ) )
3562  {
3563  setLayerFilter( layer, param.mFilter );
3564  }
3565 
3567  {
3568  setLayerAccessControlFilter( layer );
3569  }
3570 
3571  if ( mContext.testFlag( QgsWmsRenderContext::UseSelection ) )
3572  {
3573  setLayerSelection( layer, param.mSelection );
3574  }
3575 
3576  if ( settings && mContext.updateExtent() )
3577  {
3578  updateExtent( layer, *settings );
3579  }
3580  }
3581 
3583  {
3584  layers = highlightLayers( mWmsParameters.highlightLayersParameters() ) << layers;
3585  }
3586  }
3587 
3588  void QgsRenderer::setLayerStyle( QgsMapLayer *layer, const QString &style ) const
3589  {
3590  if ( style.isEmpty() )
3591  {
3592  return;
3593  }
3594 
3595  bool rc = layer->styleManager()->setCurrentStyle( style );
3596  if ( ! rc )
3597  {
3599  QStringLiteral( "Style '%1' does not exist for layer '%2'" ).arg( style, layer->name() ) );
3600  }
3601  }
3602 
3603  void QgsRenderer::setLayerSld( QgsMapLayer *layer, const QDomElement &sld ) const
3604  {
3605  QString err;
3606  // Defined sld style name
3607  const QStringList styles = layer->styleManager()->styles();
3608  QString sldStyleName = "__sld_style";
3609  while ( styles.contains( sldStyleName ) )
3610  {
3611  sldStyleName.append( '@' );
3612  }
3613  layer->styleManager()->addStyleFromLayer( sldStyleName );
3614  layer->styleManager()->setCurrentStyle( sldStyleName );
3615  layer->readSld( sld, err );
3616  layer->setCustomProperty( "sldStyleName", sldStyleName );
3617  }
3618 
3619  QgsLegendSettings QgsRenderer::legendSettings()
3620  {
3621  // getting scale from bbox or default size
3622  QgsLegendSettings settings = mWmsParameters.legendSettings();
3623 
3624  if ( !mWmsParameters.bbox().isEmpty() )
3625  {
3626  QgsMapSettings mapSettings;
3628  std::unique_ptr<QImage> tmp( createImage( mContext.mapSize( false ) ) );
3629  configureMapSettings( tmp.get(), mapSettings );
3630  // QGIS 4.0 - require correct use of QgsRenderContext instead of these
3632  settings.setMapScale( mapSettings.scale() );
3633  settings.setMapUnitsPerPixel( mapSettings.mapUnitsPerPixel() );
3635  }
3636  else
3637  {
3638  // QGIS 4.0 - require correct use of QgsRenderContext instead of these
3640  const double defaultMapUnitsPerPixel = QgsServerProjectUtils::wmsDefaultMapUnitsPerMm( *mContext.project() ) / mContext.dotsPerMm();
3641  settings.setMapUnitsPerPixel( defaultMapUnitsPerPixel );
3643  }
3644 
3645  return settings;
3646  }
3647 } // namespace QgsWms
QgsAttributeEditorElement
This is an abstract base class for any elements of a drag and drop form.
Definition: qgsattributeeditorelement.h:37
QgsFeatureRequest::NoGeometry
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Definition: qgsfeaturerequest.h:115
QgsMapLayerStyleManager::styles
QStringList styles() const
Returns list of all defined style names.
Definition: qgsmaplayerstylemanager.cpp:86
QgsVectorLayer::getFeatures
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
Definition: qgsvectorlayer.cpp:1052
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:406
QgsServerFeatureId::getExpressionFromServerFid
SERVER_EXPORT QString getExpressionFromServerFid(const QString &serverFid, const QgsVectorDataProvider *provider)
Returns the expression feature id based on primary keys.
Definition: qgsserverfeatureid.cpp:83
QgsWms::QgsServiceException::QGIS_InvalidParameterValue
@ QGIS_InvalidParameterValue
Definition: qgswmsserviceexception.h:75
QgsMapLayer::crs
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:79
QgsLayoutItem::id
QString id() const
Returns the item's ID name.
Definition: qgslayoutitem.h:359
qgswmsrenderer.h
QgsMapSettings::setDestinationCrs
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
Sets the destination crs (coordinate reference system) for the map render.
Definition: qgsmapsettings.cpp:350
qgsfields.h
QgsLayerTreeGroup::findLayer
QgsLayerTreeLayer * findLayer(QgsMapLayer *layer) const
Find layer node representing the map layer.
Definition: qgslayertreegroup.cpp:221
qgsexpressioncontextutils.h
QgsPalLayerSettings::placement
Qgis::LabelPlacement placement
Label placement mode.
Definition: qgspallabeling.h:434
qgsserverfeatureid.h
QgsRectangle::height
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
Definition: qgsrectangle.h:230
QgsVectorLayer::selectByIds
Q_INVOKABLE void selectByIds(const QgsFeatureIds &ids, Qgis::SelectBehavior behavior=Qgis::SelectBehavior::SetSelection)
Selects matching features using a list of feature IDs.
Definition: qgsvectorlayer.cpp:572
QgsServerProjectUtils::wmsMaxAtlasFeatures
SERVER_EXPORT int wmsMaxAtlasFeatures(const QgsProject &project)
Returns the maximum number of atlas features which can be printed in a request.
Definition: qgsserverprojectutils.cpp:150
qgslayoutitemmapgrid.h
QgsProject::annotationManager
QgsAnnotationManager * annotationManager()
Returns pointer to the project's annotation manager.
Definition: qgsproject.cpp:3551
QgsWms::QgsWmsRenderContext::layersFromGroup
QList< QgsMapLayer * > layersFromGroup(const QString &nickname) const
Returns the group's layers list corresponding to the nickname, or an empty list if not found.
Definition: qgswmsrendercontext.cpp:310
QgsPalLayerSettings::Hali
@ Hali
Horizontal alignment for data defined label position (Left, Center, Right)
Definition: qgspallabeling.h:246
QgsWms::QgsWmsParameter::QUERY_LAYERS
@ QUERY_LAYERS
Definition: qgswmsparameters.h:147
QgsPointXY::y
double y
Definition: qgspointxy.h:63
QgsMapRendererJob::Error
Definition: qgsmaprendererjob.h:354
qgspallabeling.h
QgsException
Defines a QGIS exception class.
Definition: qgsexception.h:34
QgsOgcUtils::expressionFromOgcFilter
static QgsExpression * expressionFromOgcFilter(const QDomElement &element, QgsVectorLayer *layer=nullptr)
Parse XML with OGC filter into QGIS expression.
Definition: qgsogcutils.cpp:1670
QgsProject::selectionColor
QColor selectionColor
Definition: qgsproject.h:119
QgsServerWmsDimensionProperties::WmsDimensionInfo::ReferenceValue
@ ReferenceValue
Remove from current selection.
Definition: qgsmaplayerserverproperties.h:168
QgsWms::QgsServiceException::OGC_LayerNotQueryable
@ OGC_LayerNotQueryable
Definition: qgswmsserviceexception.h:66
outputCrs
const QgsCoordinateReferenceSystem & outputCrs
Definition: qgswfsgetfeature.cpp:115
qgsmaplayerstylemanager.h
QgsLayoutExporter::PdfExportSettings::rasterizeWholeImage
bool rasterizeWholeImage
Set to true to force whole layout to be rasterized while exporting.
Definition: qgslayoutexporter.h:268
QgsLayoutManager
Manages storage of a set of layouts.
Definition: qgslayoutmanager.h:44
Qgis::MapSettingsFlag::UseRenderingOptimization
@ UseRenderingOptimization
Enable vector simplification and other rendering optimizations.
QgsRenderContext::mapToPixel
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
Definition: qgsrendercontext.h:258
QgsVectorLayer::wkbType
Q_INVOKABLE QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
Definition: qgsvectorlayer.cpp:725
QgsMapSettings::mapToLayerCoordinates
QgsPointXY mapToLayerCoordinates(const QgsMapLayer *layer, QgsPointXY point) const
transform point coordinates from output CRS to layer's CRS
Definition: qgsmapsettings.cpp:633
qgsrasterlayer.h
QgsWkbTypes::displayString
static QString displayString(Type type) SIP_HOLDGIL
Returns a non-translated display string type for a WKB type, e.g., the geometry name used in WKT geom...
Definition: qgswkbtypes.cpp:145
QgsWms::QgsRenderer::HitTest
QHash< QgsVectorLayer *, SymbolSet > HitTest
Definition: qgswmsrenderer.h:110
qgsfeaturerequest.h
QgsTextFormat::setFont
void setFont(const QFont &font)
Sets the font used for rendering text.
Definition: qgstextformat.cpp:207
QgsVectorDataProvider::pkAttributeIndexes
virtual QgsAttributeList pkAttributeIndexes() const
Returns list of indexes of fields that make up the primary key.
Definition: qgsvectordataprovider.cpp:366
QgsWkbTypes::Point
@ Point
Definition: qgswkbtypes.h:72
qgsscalecalculator.h
QgsFeatureRequest::filterFids
const QgsFeatureIds & filterFids() const
Returns the feature IDs that should be fetched.
Definition: qgsfeaturerequest.h:492
QgsServerProjectUtils::wmsFeatureInfoDocumentElementNs
SERVER_EXPORT QString wmsFeatureInfoDocumentElementNs(const QgsProject &project)
Returns the document element namespace for XML GetFeatureInfo request.
Definition: qgsserverprojectutils.cpp:201
QgsVectorLayer::dataProvider
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
Definition: qgsvectorlayer.cpp:676
QgsRenderContext::expressionContext
QgsExpressionContext & expressionContext()
Gets the expression context.
Definition: qgsrendercontext.h:625
QgsMapToPixel::mapUnitsPerPixel
double mapUnitsPerPixel() const
Returns the current map units per pixel.
Definition: qgsmaptopixel.h:229
QgsLegendSettings::mmPerMapUnit
Q_DECL_DEPRECATED double mmPerMapUnit() const
Definition: qgslegendsettings.cpp:43
QgsRectangle::combineExtentWith
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle.
Definition: qgsrectangle.h:391
QgsMapLayerType::MeshLayer
@ MeshLayer
Mesh layer. Added in QGIS 3.2.
QgsVectorLayer::updateFields
void updateFields()
Will regenerate the fields property of this layer by obtaining all fields from the dataProvider,...
Definition: qgsvectorlayer.cpp:3963
QgsFeatureRequest::transformContext
QgsCoordinateTransformContext transformContext() const
Returns the transform context, for use when a destinationCrs() has been set and reprojection is requi...
Definition: qgsfeaturerequest.cpp:296
QgsExpressionContextUtils::globalScope
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
Definition: qgsexpressioncontextutils.cpp:40
qgsattributeeditorcontainer.h
QgsFeatureRequest::ExactIntersect
@ ExactIntersect
Use exact geometry intersection (slower) instead of bounding boxes.
Definition: qgsfeaturerequest.h:117
QgsServerProjectUtils::wmsFeatureInfoSegmentizeWktGeometry
SERVER_EXPORT bool wmsFeatureInfoSegmentizeWktGeometry(const QgsProject &project)
Returns if the geometry has to be segmentize in GetFeatureInfo request.
Definition: qgsserverprojectutils.cpp:183
QgsMapSettings::outputSize
QSize outputSize() const
Returns the size of the resulting map image, in pixels.
Definition: qgsmapsettings.cpp:239
QgsMapSettings::setFlag
void setFlag(Qgis::MapSettingsFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
Definition: qgsmapsettings.cpp:382
QgsMapSettings::layerTransform
QgsCoordinateTransform layerTransform(const QgsMapLayer *layer) const
Returns the coordinate transform from layer's CRS to destination CRS.
Definition: qgsmapsettings.cpp:481
QgsServerWmsDimensionProperties::WmsDimensionInfo
Setting to define QGIS Server WMS Dimension.
Definition: qgsmaplayerserverproperties.h:156
QgsWms::QgsWmsParameters::isForce2D
bool isForce2D() const
Definition: qgswmsparameters.cpp:1547
QgsEditorWidgetSetup
Holder for the widget type and its configuration for a field.
Definition: qgseditorwidgetsetup.h:28
QgsWkbTypes::NullGeometry
@ NullGeometry
Definition: qgswkbtypes.h:146
QgsRenderContext::fromMapSettings
static QgsRenderContext fromMapSettings(const QgsMapSettings &mapSettings)
create initialized QgsRenderContext instance from given QgsMapSettings
Definition: qgsrendercontext.cpp:234
QgsWms::QgsWmsRenderContext::isExternalLayer
bool isExternalLayer(const QString &name) const
Returns true if the layer is an external layer, false otherwise.
Definition: qgswmsrendercontext.cpp:826
QgsMapLayerType::VectorLayer
@ VectorLayer
Vector layer.
qgswmsutils.h
qgsmapthemecollection.h
QgsFeature::initAttributes
void initAttributes(int fieldCount)
Initialize this feature with the given number of fields.
Definition: qgsfeature.cpp:235
QgsWms::QgsWmsParameters::heightAsInt
int heightAsInt() const
Returns HEIGHT parameter as an int or its default value if not defined.
Definition: qgswmsparameters.cpp:732
qgsannotation.h
QgsWms::QgsWmsParametersFilter::OGC_FE
@ OGC_FE
Definition: qgswmsparameters.h:80
QgsServerFeatureId::getServerFid
SERVER_EXPORT QString getServerFid(const QgsFeature &feature, const QgsAttributeList &pkAttributes)
Returns the feature id based on primary keys.
Definition: qgsserverfeatureid.cpp:24
QgsLayout::layoutItems
void layoutItems(QList< T * > &itemList) const
Returns a list of layout items of a specific type.
Definition: qgslayout.h:122
QgsWms::QgsWmsRenderContext::style
QString style(const QgsMapLayer &layer) const
Returns a style's name for a specific layer.
Definition: qgswmsrendercontext.cpp:100
QgsWms::QgsWmsParameters::infoFormatVersion
int infoFormatVersion() const
Returns the infoFormat version for GML.
Definition: qgswmsparameters.cpp:913
QgsAttributeEditorField
This element will load a field's widget onto the form.
Definition: qgsattributeeditorfield.h:27
QgsDebugMsgLevel
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QgsGeometry::transform
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
Definition: qgsgeometry.cpp:3128
QgsPalLayerSettings
Contains settings for how a map layer will be labeled.
Definition: qgspallabeling.h:86
qgsrasteridentifyresult.h
QgsProject::mapLayers
QMap< QString, QgsMapLayer * > mapLayers(const bool validOnly=false) const
Returns a map of all registered layers by layer ID.
Definition: qgsproject.cpp:3955
QgsRectangle::invert
void invert()
Swap x/y coordinates in the rectangle.
Definition: qgsrectangle.h:575
qgsmaptopixel.h
QgsPalLayerSettings::PositionY
@ PositionY
Y-coordinate data defined label position.
Definition: qgspallabeling.h:244
QgsMapLayer::setCustomProperty
Q_INVOKABLE void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for layer.
Definition: qgsmaplayer.cpp:1976
QgsTextBufferSettings::setEnabled
void setEnabled(bool enabled)
Sets whether the text buffer will be drawn.
Definition: qgstextbuffersettings.cpp:77
QgsWms::QgsWmsParametersComposerMap::mLayers
QList< QgsWmsParametersLayer > mLayers
Definition: qgswmsparameters.h:105
QgsLayoutAtlas::count
int count() const override
Returns the number of features to iterate over.
Definition: qgslayoutatlas.cpp:401
crs
const QgsCoordinateReferenceSystem & crs
Definition: qgswfsgetfeature.cpp:105
QgsWms::QgsWmsRenderContext::UseFilter
@ UseFilter
Definition: qgswmsrendercontext.h:55
QgsCoordinateReferenceSystem::fromOgcWmsCrs
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
Definition: qgscoordinatereferencesystem.cpp:195
QgsLayoutExporter::ImageExportSettings::flags
QgsLayoutRenderContext::Flags flags
Layout context flags, which control how the export will be created.
Definition: qgslayoutexporter.h:213
QgsWms::QgsServiceException::OGC_InvalidCRS
@ OGC_InvalidCRS
Definition: qgswmsserviceexception.h:72
QgsWkbTypes::flatType
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:732
QgsWms::QgsWmsParameters::crs
QString crs() const
Returns CRS or an empty string if none is defined.
Definition: qgswmsparameters.cpp:689
QgsWms::QgsWmsParameters::Format
Format
Output format for the response.
Definition: qgswmsparameters.h:353
QgsTemporalRangeObject::setIsTemporal
void setIsTemporal(bool enabled)
Sets whether the temporal range is enabled (i.e.
Definition: qgstemporalrangeobject.cpp:25
QgsMapLayerType::AnnotationLayer
@ AnnotationLayer
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
qgssymbollayerutils.h
qgsfeatureiterator.h
QgsWms::QgsWmsParameters::legendSettings
QgsLegendSettings legendSettings() const
Returns legend settings.
Definition: qgswmsparameters.cpp:1273
QgsFields::count
int count() const
Returns number of items.
Definition: qgsfields.cpp:133
QgsFields
Container of fields for a vector layer.
Definition: qgsfields.h:44
QgsRectangle::yMinimum
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:198
QgsFeatureStore
A container for features with the same fields and crs.
Definition: qgsfeaturestore.h:32
QgsGeometry::fromWkt
static QgsGeometry fromWkt(const QString &wkt)
Creates a new geometry from a WKT string.
QgsEditorWidgetSetup::config
QVariantMap config() const
Definition: qgseditorwidgetsetup.h:64
QgsCoordinateTransform::transformBoundingBox
QgsRectangle transformBoundingBox(const QgsRectangle &rectangle, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool handle180Crossover=false) const SIP_THROW(QgsCsException)
Transforms a rectangle from the source CRS to the destination CRS.
Definition: qgscoordinatetransform.cpp:560
QgsWms::QgsWmsParameters::bbox
QString bbox() const
Returns BBOX if defined or an empty string.
Definition: qgswmsparameters.cpp:712
QgsExpressionContextUtils::layerScope
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
Definition: qgsexpressioncontextutils.cpp:334
qgsserverprojectutils.h
QgsWms::QgsWmsRenderContext::updateExtent
bool updateExtent() const
Returns true if the extent has to be updated before the rendering, false otherwise.
Definition: qgswmsrendercontext.cpp:256
QgsWms::QgsWmsParameters::featureCountAsInt
int featureCountAsInt() const
Returns FEATURE_COUNT as an integer.
Definition: qgswmsparameters.cpp:1035
qgslayoutmanager.h
qgsfeature.h
QgsMapLayer::styleManager
QgsMapLayerStyleManager * styleManager() const
Gets access to the layer's style manager.
Definition: qgsmaplayer.cpp:2092
QgsLegendSettings::setMapUnitsPerPixel
Q_DECL_DEPRECATED void setMapUnitsPerPixel(double mapUnitsPerPixel)
Sets the mmPerMapUnit calculated by mapUnitsPerPixel mostly taken from the map settings.
Definition: qgslegendsettings.cpp:78
QgsWms::QgsWmsRenderContext::layerGroups
QMap< QString, QList< QgsMapLayer * > > layerGroups() const
Returns a map having layer group names as keys and a list of layers as values.
Definition: qgswmsrendercontext.cpp:601
QgsPointXY::setY
void setY(double y) SIP_HOLDGIL
Sets the y value of the point.
Definition: qgspointxy.h:132
QgsFeature::geometry
QgsGeometry geometry
Definition: qgsfeature.h:71
QgsLayoutItemHtml
A layout multiframe subclass for HTML content.
Definition: qgslayoutitemhtml.h:36
qgsfieldformatterregistry.h
QgsProject::transformContext
QgsCoordinateTransformContext transformContext
Definition: qgsproject.h:110
QgsWms::QgsWmsParameters::i
QString i() const
Returns I parameter or an empty string if not defined.
Definition: qgswmsparameters.cpp:925
QgsMapSettings::mapUnitsPerPixel
double mapUnitsPerPixel() const
Returns the distance in geographical coordinates that equals to one pixel in the map.
Definition: qgsmapsettings.cpp:453
QgsLayoutAtlas::updateFeatures
int updateFeatures()
Requeries the current atlas coverage layer and applies filtering and sorting.
Definition: qgslayoutatlas.cpp:262
QgsServerProjectUtils::wmsFeatureInfoLayerAliasMap
SERVER_EXPORT QHash< QString, QString > wmsFeatureInfoLayerAliasMap(const QgsProject &project)
Returns the mapping between layer name and wms layer name for GetFeatureInfo request.
Definition: qgsserverprojectutils.cpp:211
QgsLegendSettings::mapScale
Q_DECL_DEPRECATED double mapScale() const
Returns the legend map scale.
Definition: qgslegendsettings.cpp:63
QgsExpressionContextUtils::mapSettingsScope
static QgsExpressionContextScope * mapSettingsScope(const QgsMapSettings &mapSettings)
Creates a new scope which contains variables and functions relating to a QgsMapSettings object.
Definition: qgsexpressioncontextutils.cpp:427
QgsRenderContext
Contains information about the context of a rendering operation.
Definition: qgsrendercontext.h:59
QgsLabelPlacementSettings::setAllowDegradedPlacement
void setAllowDegradedPlacement(bool allow)
Sets whether labels can be placed in inferior fallback positions if they cannot otherwise be placed.
Definition: qgslabelplacementsettings.h:70
QgsProject::instance
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:480
QgsMapSettings::layerExtentToOutputExtent
QgsRectangle layerExtentToOutputExtent(const QgsMapLayer *layer, QgsRectangle extent) const
transform bounding box from layer's CRS to output CRS
Definition: qgsmapsettings.cpp:528
QgsLayoutRenderContext
Stores information relating to the current rendering settings for a layout.
Definition: qgslayoutrendercontext.h:36
QgsMapThemeCollection::MapThemeRecord::layerRecords
QList< QgsMapThemeCollection::MapThemeLayerRecord > layerRecords() const
Returns a list of records for all visible layer belonging to the theme.
Definition: qgsmapthemecollection.h:137
qgsunittypes.h
QgsWms::QgsWmsRenderContext::AddHighlightLayers
@ AddHighlightLayers
Definition: qgswmsrendercontext.h:57
qgsmapserviceexception.h
qgsrasterrenderer.h
QgsFeatureFilterProviderGroup
A filter filter provider grouping several filter providers.
Definition: qgsfeaturefilterprovidergroup.h:32
QgsWms::QgsWmsRenderContext::isValidWidthHeight
bool isValidWidthHeight() const
Returns true if width and height are valid according to the maximum values defined within the project...
Definition: qgswmsrendercontext.cpp:632
QgsCoordinateReferenceSystem::hasAxisInverted
bool hasAxisInverted() const
Returns whether axis is inverted (e.g., for WMS 1.3) for the CRS.
Definition: qgscoordinatereferencesystem.cpp:793
QgsPalLayerSettings::Vali
@ Vali
Vertical alignment for data defined label position (Bottom, Base, Half, Cap, Top)
Definition: qgspallabeling.h:247
QgsRasterInterface::IdentifyFeature
@ IdentifyFeature
WMS GML -> feature.
Definition: qgsrasterinterface.h:213
QgsWms::QgsWmsParameters::transparentAsBool
bool transparentAsBool() const
Returns TRANSPARENT parameter as a bool or its default value if not defined.
Definition: qgswmsparameters.cpp:985
qgsmaprendererjobproxy.h
QgsLayoutExporter::ImageExportSettings::pages
QList< int > pages
List of specific pages to export, or an empty list to export all pages.
Definition: qgslayoutexporter.h:193
qgslayoutitemlabel.h
QgsRasterIdentifyResult::isValid
bool isValid() const
Returns true if valid.
Definition: qgsrasteridentifyresult.h:68
QgsWms::QgsRenderer::getPrint
QByteArray getPrint()
Returns printed page as binary.
Definition: qgswmsrenderer.cpp:316
QgsFeatureRequest::setSubsetOfAttributes
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
Definition: qgsfeaturerequest.cpp:228
QgsLayerTreeModel
The QgsLayerTreeModel class is model implementation for Qt item views framework.
Definition: qgslayertreemodel.h:55
QgsWms::QgsServiceException::OGC_InvalidFormat
@ OGC_InvalidFormat
Definition: qgswmsserviceexception.h:62
QgsMapSettings::setOutputDpi
void setOutputDpi(double dpi)
Sets the dpi (dots per inch) used for conversion between real world units (e.g.
Definition: qgsmapsettings.cpp:272
QgsSymbol
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:92
field
const QgsField & field
Definition: qgsfield.h:463
QgsWms::QgsWmsParameters::dpi
QString dpi() const
Returns DPI parameter or an empty string if not defined.
Definition: qgswmsparameters.cpp:762
QgsFields::append
bool append(const QgsField &field, FieldOrigin origin=OriginProvider, int originIndex=-1)
Appends a field. The field must have unique name, otherwise it is rejected (returns false)
Definition: qgsfields.cpp:59
QgsWms::QgsWmsParameter::INFO_FORMAT
@ INFO_FORMAT
Definition: qgswmsparameters.h:164
QgsRenderContext::scaleFactor
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
Definition: qgsrendercontext.h:266
qgsvectorlayerfeaturecounter.h
QgsProject::mapLayer
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
Definition: qgsproject.cpp:3680
QgsAttributeEditorContainer::children
QList< QgsAttributeEditorElement * > children() const
Gets a list of the children elements of this container.
Definition: qgsattributeeditorcontainer.h:107
FID_TO_STRING
#define FID_TO_STRING(fid)
Definition: qgsfeatureid.h:33
QgsCoordinateTransform::isValid
bool isValid() const
Returns true if the coordinate transform is valid, ie both the source and destination CRS have been s...
Definition: qgscoordinatetransform.cpp:900
QgsRenderContext::extent
const QgsRectangle & extent() const
When rendering a map layer, calling this method returns the "clipping" extent for the layer (in the l...
Definition: qgsrendercontext.h:239
QgsServerProjectUtils::wmsFeatureInfoUseAttributeFormSettings
SERVER_EXPORT bool wmsFeatureInfoUseAttributeFormSettings(const QgsProject &project)
Returns if feature form settings should be considered for the format of the feature info response.
Definition: qgsserverprojectutils.cpp:176
QgsFeatureFilter::filterFeatures
void filterFeatures(const QgsVectorLayer *layer, QgsFeatureRequest &filterFeatures) const override
Filter the features of the layer.
Definition: qgsfeaturefilter.cpp:23
QgsAttributeList
QList< int > QgsAttributeList
Definition: qgsfield.h:26
Qgis::LabelOverlapHandling::AllowOverlapIfRequired
@ AllowOverlapIfRequired
Avoids overlapping labels when possible, but permit overlaps if labels for features cannot otherwise ...
QgsPointXY::setX
void setX(double x) SIP_HOLDGIL
Sets the x value of the point.
Definition: qgspointxy.h:122
QgsLayoutExporter::SvgExportSettings::flags
QgsLayoutRenderContext::Flags flags
Layout context flags, which control how the export will be created.
Definition: qgslayoutexporter.h:542
QgsField::name
QString name
Definition: qgsfield.h:60
QgsFeatureFilter::setFilter
void setFilter(const QgsVectorLayer *layer, const QgsExpression &expression)
Set a filter for the given layer.
Definition: qgsfeaturefilter.cpp:45
QgsLayoutAtlas::layout
QgsLayout * layout() override
Returns the layout associated with the iterator.
Definition: qgslayoutatlas.cpp:47
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:41
QgsPalLayerSettings::dist
double dist
Distance from feature to the label.
Definition: qgspallabeling.h:483
QgsWkbTypes::PolygonGeometry
@ PolygonGeometry
Definition: qgswkbtypes.h:144
qgsogcutils.h
QgsRasterLayer::bandName
QString bandName(int bandNoInt) const
Returns the name of a band given its number.
Definition: qgsrasterlayer.cpp:246
QgsServerWmsDimensionProperties::WmsDimensionInfo::MaxValue
@ MaxValue
Modify current selection to include only select features which match.
Definition: qgsmaplayerserverproperties.h:167
qgsDoubleToString
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:2204
QgsWms::QgsRenderer::getFeatureInfo
QByteArray getFeatureInfo(const QString &version="1.3.0")
Creates an xml document that describes the result of the getFeatureInfo request.
Definition: qgswmsrenderer.cpp:1112
QgsWms::QgsWmsParameters::PNG
@ PNG
Definition: qgswmsparameters.h:357
QgsProject::layoutManager
const QgsLayoutManager * layoutManager() const
Returns the project's layout manager, which manages print layouts, atlases and reports within the pro...
Definition: qgsproject.cpp:3461
QgsWms::QgsWmsParameter::I
@ I
Definition: qgswmsparameters.h:165
QgsFeatureRequest::flags
Flags flags() const
Returns the flags which affect how features are fetched.
Definition: qgsfeaturerequest.h:673
QgsField::configurationFlags
ConfigurationFlags configurationFlags
Definition: qgsfield.h:64
qgslayoutsize.h
QgsPalLayerSettings::placementSettings
const QgsLabelPlacementSettings & placementSettings() const
Returns the label placement settings.
Definition: qgspallabeling.h:949
qgsserverapiutils.h
QgsMapSettings::extent
QgsRectangle extent() const
Returns geographical coordinates of the rectangle that should be rendered.
Definition: qgsmapsettings.cpp:75
QgsEditFormConfig::invisibleRootContainer
QgsAttributeEditorContainer * invisibleRootContainer()
Gets the invisible root container for the drag and drop designer form (EditorLayout::TabLayout).
Definition: qgseditformconfig.cpp:191
QgsFeatureRequest::setFilterExpression
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
Definition: qgsfeaturerequest.cpp:167
QgsSymbolLayerUtils::symbolProperties
static QString symbolProperties(QgsSymbol *symbol)
Returns a string representing the symbol.
Definition: qgssymbollayerutils.cpp:1454
qgsfeaturefilterprovidergroup.h
QgsWms::QgsWmsParameters::withMapTip
bool withMapTip() const
withMapTip
Definition: qgswmsparameters.cpp:2060
QgsWms::QgsWmsParameter::SRS
@ SRS
Definition: qgswmsparameters.h:126
qgslayoutframe.h
QgsLayoutItemLegend
A layout item subclass for map legends.
Definition: qgslayoutitemlegend.h:113
QgsProject::labelingEngineSettings
const QgsLabelingEngineSettings & labelingEngineSettings() const
Returns project's global labeling engine settings.
Definition: qgsproject.cpp:2175
qgswmsrestorer.h
QgsDimensionFilter
A server filter to apply a dimension filter to a request.
Definition: qgsdimensionfilter.h:32
QgsExpression::quotedValue
static QString quotedValue(const QVariant &value)
Returns a string representation of a literal value, including appropriate quotations where required.
Definition: qgsexpression.cpp:82
QgsRasterLayer::renderer
QgsRasterRenderer * renderer() const
Returns the raster's renderer.
Definition: qgsrasterlayer.cpp:1758
QgsFeatureRequest::setFilterRect
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
Definition: qgsfeaturerequest.cpp:101
qgslayoutexporter.h
QgsServerProjectUtils::wmsFeatureInfoDocumentElement
SERVER_EXPORT QString wmsFeatureInfoDocumentElement(const QgsProject &project)
Returns the document element name for XML GetFeatureInfo request.
Definition: qgsserverprojectutils.cpp:196
QgsVectorLayer::editorWidgetSetup
QgsEditorWidgetSetup editorWidgetSetup(int index) const
The editor widget setup defines which QgsFieldFormatter and editor widget will be used for the field ...
Definition: qgsvectorlayer.cpp:5779
qgsfilterrestorer.h
QgsWms::QgsWmsParameter::LAYER
@ LAYER
Definition: qgswmsparameters.h:137
QgsVectorLayer::fields
QgsFields fields() const FINAL
Returns the list of fields of this layer.
Definition: qgsvectorlayer.cpp:3436
QgsWms::QgsWmsParameters::height
QString height() const
Returns HEIGHT parameter or an empty string if not defined.
Definition: qgswmsparameters.cpp:722
Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:2820
QgsRectangle::xMaximum
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:183
QgsFeature::id
QgsFeatureId id
Definition: qgsfeature.h:68
QgsEditorWidgetSetup::type
QString type() const
Definition: qgseditorwidgetsetup.h:59
QgsWms::QgsWmsParameters::queryLayersNickname
QStringList queryLayersNickname() const
Returns nickname of layers found in QUERY_LAYERS parameter.
Definition: qgswmsparameters.cpp:1480
QgsTextFormat
Container for all settings relating to text rendering.
Definition: qgstextformat.h:40
QgsTextFormat::setColor
void setColor(const QColor &color)
Sets the color that text will be rendered in.
Definition: qgstextformat.cpp:302
QgsMapLayer::isInScaleRange
bool isInScaleRange(double scale) const
Tests whether the layer should be visible at the specified scale.
Definition: qgsmaplayer.cpp:832
QgsWms::QgsWmsParameters::sldBody
QString sldBody() const
Returns SLD_body if defined or an empty string.
Definition: qgswmsparameters.cpp:1412
QgsFeatureRequest
This class wraps a request for features to a vector layer (or directly its vector data provider).
Definition: qgsfeaturerequest.h:83
qgsmaplayertemporalproperties.h
QgsExpressionContextUtils::projectScope
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
Definition: qgsexpressioncontextutils.cpp:291
QgsWms::QgsWmsParameters::widthAsInt
int widthAsInt() const
Returns WIDTH parameter as an int or its default value if not defined.
Definition: qgswmsparameters.cpp:737
QgsAttributeEditorElement::AeTypeContainer
@ AeTypeContainer
A container.
Definition: qgsattributeeditorelement.h:119
QgsFeatureRequest::NoFlags
@ NoFlags
Definition: qgsfeaturerequest.h:114
QgsOgcUtils::rectangleToGMLBox
static QDomElement rectangleToGMLBox(QgsRectangle *box, QDomDocument &doc, int precision=17)
Exports the rectangle to GML2 Box.
Definition: qgsogcutils.cpp:1111
QgsCsException
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:65
QgsWms::QgsServiceException::OGC_LayerNotDefined
@ OGC_LayerNotDefined
Definition: qgswmsserviceexception.h:64
QgsLayerTree
Namespace with helper functions for layer tree operations.
Definition: qgslayertree.h:32
QgsAnnotation
Abstract base class for annotation items which are drawn over a map.
Definition: qgsannotation.h:53
QgsPrintLayout
Print layout, a QgsLayout subclass for static or atlas-based layouts.
Definition: qgsprintlayout.h:30
QgsMapSettings::setBackgroundColor
void setBackgroundColor(const QColor &color)
Sets the background color of the map.
Definition: qgsmapsettings.h:381
QgsWms::QgsRenderer::QgsRenderer
QgsRenderer(const QgsWmsRenderContext &context)
Constructor for QgsRenderer.
Definition: qgswmsrenderer.cpp:120
QgsWms::QgsRenderer::~QgsRenderer
~QgsRenderer()
Destructor for QgsRenderer.
Definition: qgswmsrenderer.cpp:129
QgsLayoutExporter::SvgExportSettings::dpi
double dpi
Resolution to export layout at. If dpi <= 0 the default layout dpi will be used.
Definition: qgslayoutexporter.h:491
QgsMapLayer::dataProvider
virtual Q_INVOKABLE QgsDataProvider * dataProvider()
Returns the layer's data provider, it may be nullptr.
Definition: qgsmaplayer.cpp:190
QgsRaster::IdentifyFormatValue
@ IdentifyFormatValue
Definition: qgsraster.h:73
QgsScaleCalculator
Calculates scale for a given combination of canvas size, map extent, and monitor dpi.
Definition: qgsscalecalculator.h:34
QgsAbstractGeometry::wkbType
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns the WKB type of the geometry.
Definition: qgsabstractgeometry.h:206
QgsMapSettings::transformContext
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context, which stores various information regarding which datum tran...
Definition: qgsmapsettings.cpp:463
QgsRasterInterface::IdentifyValue
@ IdentifyValue
Numerical values.
Definition: qgsrasterinterface.h:210
QgsVectorLayer::temporalProperties
QgsMapLayerTemporalProperties * temporalProperties() override
Returns the layer's temporal properties.
Definition: qgsvectorlayer.cpp:686
QgsLayoutItemMap::layers
QList< QgsMapLayer * > layers() const
Returns the stored layer set.
Definition: qgslayoutitemmap.cpp:326
QgsMapSettings::layerIds
QStringList layerIds(bool expandGroupLayers=false) const
Returns the list of layer IDs which will be rendered in the map.
Definition: qgsmapsettings.cpp:289
QgsMapLayer::readSld
virtual bool readSld(const QDomNode &node, QString &errorMessage)
Definition: qgsmaplayer.h:1160
QgsFeature::setGeometry
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:170
QgsTemporalProperty::isActive
bool isActive() const
Returns true if the temporal property is active.
Definition: qgstemporalproperty.cpp:36
QgsLayoutAtlas::enabled
bool enabled() const
Returns whether the atlas generation is enabled.
Definition: qgslayoutatlas.h:67
QgsWms::QgsWmsParameters::polygonToleranceAsInt
int polygonToleranceAsInt() const
Returns FI_POLYGON_TOLERANCE parameter as an integer.
Definition: qgswmsparameters.cpp:1150
QgsLayoutFrame
Base class for frame items, which form a layout multiframe item.
Definition: qgslayoutframe.h:31
QgsRasterIdentifyResult::results
QMap< int, QVariant > results() const
Returns the identify results.
Definition: qgsrasteridentifyresult.h:80
QgsWms::QgsWmsRenderContext::mapSize
QSize mapSize(bool aspectRatio=true) const
Returns the size (in pixels) of the map to render, according to width and height WMS parameters as we...
Definition: qgswmsrendercontext.cpp:731
QgsWms::QgsWmsParameters::x
QString x() const
Returns X parameter or an empty string if not defined.
Definition: qgswmsparameters.cpp:945
QgsWms::QgsWmsParameters::versionAsNumber
QgsProjectVersion versionAsNumber() const
Returns VERSION parameter if defined or its default value.
Definition: qgswmsparameters.cpp:822
QgsMapLayerType::GroupLayer
@ GroupLayer
Composite group layer. Added in QGIS 3.24.
QgsRasterRenderer
Raster renderer pipe that applies colors to a raster.
Definition: qgsrasterrenderer.h:40
QgsFeature::setFields
void setFields(const QgsFields &fields, bool initAttributes=false)
Assigns a field map with the feature to allow attribute access by attribute name.
Definition: qgsfeature.cpp:195
QgsRasterIdentifyResult
Raster identify results container.
Definition: qgsrasteridentifyresult.h:30
qgsDoubleNear
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:2265
QgsWms::QgsWmsParameters::lineTolerance
QString lineTolerance() const
Returns FI_LINE_TOLERANCE parameter or an empty string if not defined.
Definition: qgswmsparameters.cpp:1140
QgsWms::QgsWmsRenderContext::setScaleDenominator
void setScaleDenominator(double scaleDenominator)
Sets a custom scale denominator.
Definition: qgswmsrendercontext.cpp:250
QgsWms::QgsWmsParameters::yAsInt
int yAsInt() const
Returns Y parameter as an int or its default value if not defined.
Definition: qgswmsparameters.cpp:960
QgsServerSettings::parallelRendering
bool parallelRendering() const
Returns parallel rendering setting.
Definition: qgsserversettings.cpp:509
QgsRenderContext::setExtent
void setExtent(const QgsRectangle &extent)
When rendering a map layer, calling this method sets the "clipping" extent for the layer (in the laye...
Definition: qgsrendercontext.h:426
QgsRenderContext::setFlag
void setFlag(Qgis::RenderContextFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
Definition: qgsrendercontext.cpp:216
QgsWms::QgsWmsParametersFilter::SQL
@ SQL
Definition: qgswmsparameters.h:79
QgsWms::QgsRenderer::getMap
QImage * getMap()
Returns the map as an image (or nullptr in case of error).
Definition: qgswmsrenderer.cpp:940
QgsFeatureRenderer::clone
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
QgsRenderContext::setCoordinateTransform
void setCoordinateTransform(const QgsCoordinateTransform &t)
Sets the current coordinate transform for the context.
Definition: qgsrendercontext.cpp:320
QgsMapLayer::extent
virtual QgsRectangle extent() const
Returns the extent of the layer.
Definition: qgsmaplayer.cpp:305
QgsException::what
QString what() const
Definition: qgsexception.h:48
QgsLayerTreeLayer
Layer tree node points to a map layer.
Definition: qgslayertreelayer.h:43
qgsmaplayer.h
QgsLayoutAtlas::coverageLayer
QgsVectorLayer * coverageLayer() const
Returns the coverage layer used for the atlas features.
Definition: qgslayoutatlas.h:116
QgsMapLayerType::RasterLayer
@ RasterLayer
Raster layer.
QgsFeatureRequest::filterExpression
QgsExpression * filterExpression() const
Returns the filter expression (if set).
Definition: qgsfeaturerequest.h:562
QgsRectangle::contains
bool contains(const QgsRectangle &rect) const SIP_HOLDGIL
Returns true when rectangle contains other rectangle.
Definition: qgsrectangle.h:363
QgsLayoutAtlas::beginRender
bool beginRender() override
Called when rendering begins, before iteration commences.
Definition: qgslayoutatlas.cpp:376
QgsWms::QgsServiceException::OGC_InvalidPoint
@ OGC_InvalidPoint
Definition: qgswmsserviceexception.h:71
QgsVectorLayer::uniqueValues
QSet< QVariant > uniqueValues(int fieldIndex, int limit=-1) const FINAL
Calculates a list of unique values contained within an attribute in the layer.
Definition: qgsvectorlayer.cpp:4161
QgsMapLayer::setOpacity
virtual void setOpacity(double opacity)
Sets the opacity for the layer, where opacity is a value between 0 (totally transparent) and 1....
Definition: qgsmaplayer.cpp:325
QgsPalLayerSettings::setFormat
void setFormat(const QgsTextFormat &format)
Sets the label text formatting settings, e.g., font settings, buffer settings, etc.
Definition: qgspallabeling.h:849
QgsWms::QgsWmsParameters::lineToleranceAsInt
int lineToleranceAsInt() const
Returns FI_LINE_TOLERANCE parameter as an integer.
Definition: qgswmsparameters.cpp:1155
qgsdimensionfilter.h
QgsLayoutExporter::ImageExportSettings::imageSize
QSize imageSize
Manual size in pixels for output image.
Definition: qgslayoutexporter.h:172
QgsWms::QgsWmsRenderContext::SetAccessControl
@ SetAccessControl
Definition: qgswmsrendercontext.h:59
QgsPalLayerSettings::LabelRotation
@ LabelRotation
Label rotation.
Definition: qgspallabeling.h:249
qgsvectordataprovider.h
QgsFeatureList
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:882
QgsRasterDataProvider::identify
virtual QgsRasterIdentifyResult identify(const QgsPointXY &point, QgsRaster::IdentifyFormat format, const QgsRectangle &boundingBox=QgsRectangle(), int width=0, int height=0, int dpi=96)
Identify raster value(s) found on the point position.
Definition: qgsrasterdataprovider.cpp:269
QgsWms::QgsWmsParameters::xAsInt
int xAsInt() const
Returns X parameter as an int or its default value if not defined.
Definition: qgswmsparameters.cpp:955
QgsRenderContext::setMapToPixel
void setMapToPixel(const QgsMapToPixel &mtp)
Sets the context's map to pixel transform, which transforms between map coordinates and device coordi...
Definition: qgsrendercontext.h:412
QgsMapSettings::setSelectionColor
void setSelectionColor(const QColor &color)
Sets the color that is used for drawing of selected vector features.
Definition: qgsmapsettings.h:395
QgsFeatureRenderer::MoreSymbolsPerFeature
@ MoreSymbolsPerFeature
May use more than one symbol to render a feature: symbolsForFeature() will return them.
Definition: qgsrenderer.h:264
QgsLegendSettings
The QgsLegendSettings class stores the appearance and layout settings for legend drawing with QgsLege...
Definition: qgslegendsettings.h:38
QgsMessageLog::logMessage
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Definition: qgsmessagelog.cpp:27
QgsWms::QgsWmsParameters::SVG
@ SVG
Definition: qgswmsparameters.h:358
QgsCoordinateReferenceSystem::isValid
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
Definition: qgscoordinatereferencesystem.cpp:977
QgsAnnotationManager
Manages storage of a set of QgsAnnotation annotation objects.
Definition: qgsannotationmanager.h:44
QgsMapLayerServerProperties
Manages QGIS Server properties for a map layer.
Definition: qgsmaplayerserverproperties.h:272
QgsServerProjectUtils::wmsFeatureInfoAddWktGeometry
SERVER_EXPORT bool wmsFeatureInfoAddWktGeometry(const QgsProject &project)
Returns if the geometry is displayed as Well Known Text in GetFeatureInfo request.
Definition: qgsserverprojectutils.cpp:168
QgsWms::QgsWmsRenderContext::settings
const QgsServerSettings & settings() const
Returns settings of the server.
Definition: qgswmsrendercontext.cpp:77
QgsWms::QgsWmsRenderContext::isValidLayer
bool isValidLayer(const QString &nickname) const
Returns true if the layer has to be rendered, false otherwise.
Definition: qgswmsrendercontext.cpp:305
QgsPalLayerSettings::lineSettings
const QgsLabelLineSettings & lineSettings() const
Returns the label line settings, which contain settings related to how the label engine places and fo...
Definition: qgspallabeling.h:879
QgsFeature::attribute
QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Definition: qgsfeature.cpp:327
QgsWms::QgsServiceException::QGIS_MissingParameterValue
@ QGIS_MissingParameterValue
Definition: qgswmsserviceexception.h:74
QgsWms::QgsServiceException::OGC_StyleNotDefined
@ OGC_StyleNotDefined
Definition: qgswmsserviceexception.h:65
QgsLayoutExporter
Handles rendering and exports of layouts to various formats.
Definition: qgslayoutexporter.h:46
QgsGeometry::isNull
bool isNull
Definition: qgsgeometry.h:127
qgsannotationmanager.h
QgsMapSettings::scale
double scale() const
Returns the calculated map scale.
Definition: qgsmapsettings.cpp:458
QgsWms::QgsWmsRenderContext::precision
int precision() const
Returns the precision to use according to the current configuration.
Definition: qgswmsrendercontext.cpp:160
QgsLayoutExporter::PdfExportSettings::flags
QgsLayoutRenderContext::Flags flags
Layout context flags, which control how the export will be created.
Definition: qgslayoutexporter.h:297
QgsFeatureStoreList
QVector< QgsFeatureStore > QgsFeatureStoreList
Definition: qgsfeaturestore.h:119
QgsVectorLayer::primaryKeyAttributes
QgsAttributeList primaryKeyAttributes() const
Returns the list of attributes which make up the layer's primary keys.
Definition: qgsvectorlayer.cpp:3441
typeName
const QString & typeName
Definition: qgswfsgetfeature.cpp:109
QgsProject::mapThemeCollection
QgsMapThemeCollection mapThemeCollection
Definition: qgsproject.h:112
QgsOWSServerFilterRestorer::applyAccessControlLayerFilters
static void applyAccessControlLayerFilters(const QgsAccessControl *accessControl, QgsMapLayer *mapLayer, QHash< QgsMapLayer *, QString > &originalLayerFilters)
Apply filter from AccessControl.
QgsLayerTreeModelLegendNode::ItemContext
Definition: qgslayertreemodellegendnode.h:168
QgsEditFormConfig::TabLayout
@ TabLayout
Use a layout with tabs and group boxes. Needs to be configured.
Definition: qgseditformconfig.h:50
QgsMapLayer::hasScaleBasedVisibility
bool hasScaleBasedVisibility() const
Returns whether scale based visibility is enabled for the layer.
Definition: qgsmaplayer.cpp:839
QgsRectangle::xMinimum
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:188
QgsWms::QgsWmsParameters::bboxAsRectangle
QgsRectangle bboxAsRectangle() const
Returns BBOX as a rectangle if defined and valid.
Definition: qgswmsparameters.cpp:717
QgsWms::QgsWmsParameters::j
QString j() const
Returns J parameter or an empty string if not defined.
Definition: qgswmsparameters.cpp:930
qgsrenderer.h
QgsWms::QgsWmsRenderContext::sld
QDomElement sld(const QgsMapLayer &layer) const
Returns a SLD document for a specific layer.
Definition: qgswmsrendercontext.cpp:87
QgsWms::QgsWmsParameters::pointToleranceAsInt
int pointToleranceAsInt() const
Returns FI_POINT_TOLERANCE parameter as an integer.
Definition: qgswmsparameters.cpp:1160
QgsRasterLayer
Represents a raster layer.
Definition: qgsrasterlayer.h:76
QgsWms::QgsWmsParameters::filterGeom
QString filterGeom() const
Returns the filter geometry found in FILTER_GEOM parameter.
Definition: qgswmsparameters.cpp:1425
qgslayoutmeasurement.h
QgsExpression::createFieldEqualityExpression
static QString createFieldEqualityExpression(const QString &fieldName, const QVariant &value, QVariant::Type fieldType=QVariant::Type::Invalid)
Create an expression allowing to evaluate if a field is equal to a value.
Definition: qgsexpression.cpp:1126
QgsTextBufferSettings
Container for settings relating to a text buffer.
Definition: qgstextbuffersettings.h:42
QgsLayerTreeLayer::layer
QgsMapLayer * layer() const
Returns the map layer associated with this node.
Definition: qgslayertreelayer.h:82
qgslayertree.h
QgsWms::QgsWmsParameter::TEMPLATE
@ TEMPLATE
Definition: qgswmsparameters.h:190
QgsGeometry::pointOnSurface
QgsGeometry pointOnSurface() const
Returns a point guaranteed to lie on the surface of a geometry.
Definition: qgsgeometry.cpp:2308
QgsTemporalProperty::setIsActive
void setIsActive(bool active)
Sets whether the temporal property is active.
Definition: qgstemporalproperty.cpp:27
QgsWms::QgsRenderer::SymbolSet
QSet< QString > SymbolSet
Definition: qgswmsrenderer.h:109
QgsWms::QgsWmsRenderContext::layerNickname
QString layerNickname(const QgsMapLayer &layer) const
Returns the nickname (short name, id or name) of the layer according to the current configuration.
Definition: qgswmsrendercontext.cpp:268
QgsGeometry::constGet
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
Definition: qgsgeometry.cpp:136
QgsFeatureIds
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:37
QgsLayoutManager::layoutByName
QgsMasterLayoutInterface * layoutByName(const QString &name) const
Returns the layout with a matching name, or nullptr if no matching layouts were found.
Definition: qgslayoutmanager.cpp:124
QgsScopedRenderContextScaleToMm
Scoped object for temporary scaling of a QgsRenderContext for millimeter based rendering.
Definition: qgsrendercontext.h:1248
QgsWms::QgsServiceException::ExceptionCode
ExceptionCode
Exception codes as defined in OGC scpecifications for WMS 1.1.1 and WMS 1.3.0.
Definition: qgswmsserviceexception.h:60
QgsWms::QgsWmsParameter::BBOX
@ BBOX
Definition: qgswmsparameters.h:129
QgsEditFormConfig
Contains configuration settings for an editor form.
Definition: qgseditformconfig.h:39
QgsWms::QgsWmsParameters::format
Format format() const
Returns format.
Definition: qgswmsparameters.cpp:843
QgsFeature::attributes
QgsAttributes attributes
Definition: qgsfeature.h:69
QgsMapRendererJob::Error::message
QString message
Definition: qgsmaprendererjob.h:362
QgsCoordinateReferenceSystem
This class represents a coordinate reference system (CRS).
Definition: qgscoordinatereferencesystem.h:211
Qgis::MapSettingsFlag::RenderBlocking
@ RenderBlocking
Render and load remote sources in the same thread to ensure rendering remote sources (svg and images)...
QgsMapToPixel::transform
QgsPointXY transform(const QgsPointXY &p) const
Transforms a point p from map (world) coordinates to device coordinates.
Definition: qgsmaptopixel.h:90
QgsAbstractGeometry
Abstract base class for all geometries.
Definition: qgsabstractgeometry.h:79
QgsMapSettings::selectionColor
QColor selectionColor() const
Returns the color that is used for drawing of selected vector features.
Definition: qgsmapsettings.h:402
QgsWms::QgsServiceException::OGC_InvalidSRS
@ OGC_InvalidSRS
Definition: qgswmsserviceexception.h:63
QgsMapSettings::setLabelingEngineSettings
void setLabelingEngineSettings(const QgsLabelingEngineSettings &settings)
Sets the global configuration of the labeling engine.
Definition: qgsmapsettings.h:654
QgsLegendSettings::setMapScale
Q_DECL_DEPRECATED void setMapScale(double scale)
Sets the legend map scale.
Definition: qgslegendsettings.cpp:68
QgsLayerTreeModel::rootGroup
QgsLayerTree * rootGroup() const
Returns pointer to the root node of the layer tree. Always a non nullptr value.
Definition: qgslayertreemodel.cpp:492
QgsApplication::fieldFormatterRegistry
static QgsFieldFormatterRegistry * fieldFormatterRegistry()
Gets the registry of available field formatters.
Definition: qgsapplication.cpp:2480
QgsMapSettings::setLayers
void setLayers(const QList< QgsMapLayer * > &layers)
Sets the list of layers to render in the map.
Definition: qgsmapsettings.cpp:327
QgsAbstractGeometry::segmentize
virtual QgsAbstractGeometry * segmentize(double tolerance=M_PI/180., SegmentationToleranceType toleranceType=MaximumAngle) const
Returns a version of the geometry without curves.
Definition: qgsabstractgeometry.cpp:395
QgsWms::QgsWmsRenderContext::renderMapTiles
bool renderMapTiles() const
Returns true if WMS requests should use the QgsMapSettings::RenderMapTile flag, so that no visible ar...
Definition: qgswmsrendercontext.cpp:155
QgsWms::QgsRenderer::getDxf
std::unique_ptr< QgsDxfExport > getDxf()
Returns the map as DXF data.
Definition: qgswmsrenderer.cpp:988
QgsWms::QgsWmsParameters::PDF
@ PDF
Definition: qgswmsparameters.h:359
QgsRenderContext::setRendererScale
void setRendererScale(double scale)
Sets the renderer map scale.
Definition: qgsrendercontext.h:487
withGeom
bool withGeom
Definition: qgswfsgetfeature.cpp:111
QgsWms::QgsWmsParameters::composerMapParameters
QgsWmsParametersComposerMap composerMapParameters(int mapId) const
Returns the requested parameters for a composer map parameter.
Definition: qgswmsparameters.cpp:1747
QgsWms::QgsWmsParameters::dxfFormatOptions
QMap< DxfFormatOption, QString > dxfFormatOptions() const
Returns a map of DXF options defined within FORMAT_OPTIONS parameter.
Definition: qgswmsparameters.cpp:2186
qgsvectorlayer.h
QgsPointXY
A class to represent a 2D point.
Definition: qgspointxy.h:58
QgsWms::QgsWmsParameters::composerTemplate
QString composerTemplate() const
Returns TEMPLATE parameter or an empty string if not defined.
Definition: qgswmsparameters.cpp:1742
QgsMapSettings::destinationCrs
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination coordinate reference system for the map render.
Definition: qgsmapsettings.cpp:358
qgslayoutitemlegend.h
QgsLayoutItemMap
Layout graphical items for displaying a map.
Definition: qgslayoutitemmap.h:317
QgsGeometry::asPoint
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
Definition: qgsgeometry.cpp:1662
QgsJsonExporter
Handles exporting QgsFeature features to GeoJSON features.
Definition: qgsjsonutils.h:40
QgsPalLayerSettings::PositionX
@ PositionX
X-coordinate data defined label position.
Definition: qgspallabeling.h:243
QgsServerProjectUtils::wmsFeatureInfoSchema
SERVER_EXPORT QString wmsFeatureInfoSchema(const QgsProject &project)
Returns the schema URL for XML GetFeatureInfo request.
Definition: qgsserverprojectutils.cpp:206
QgsWms
Median cut implementation.
Definition: qgsdxfwriter.cpp:22
QgsFieldFormatter::representValue
virtual QString representValue(QgsVectorLayer *layer, int fieldIndex, const QVariantMap &config, const QVariant &cache, const QVariant &value) const
Create a pretty String representation of the value.
Definition: qgsfieldformatter.cpp:24
QgsVectorLayer::LayerOptions
Setting options for loading vector layers.
Definition: qgsvectorlayer.h:408
QgsLayoutExporter::PdfExportSettings::dpi
double dpi
Resolution to export layout at. If dpi <= 0 the default layout dpi will be used.
Definition: qgslayoutexporter.h:261
QgsWms::QgsWmsRenderContext::isValidGroup
bool isValidGroup(const QString &name) const
Returns true if name is a group.
Definition: qgswmsrendercontext.cpp:315
QgsFeature::setAttribute
bool setAttribute(int field, const QVariant &attr)
Sets an attribute's value by field index.
Definition: qgsfeature.cpp:262
QgsMapSettings::setExpressionContext
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
Definition: qgsmapsettings.h:479
QgsLayoutExporter::ImageExportSettings
Contains settings relating to exporting layouts to raster images.
Definition: qgslayoutexporter.h:150
qgslayoutitempage.h
QgsWkbTypes::isCurvedType
static bool isCurvedType(Type type) SIP_HOLDGIL
Returns true if the WKB type is a curved type or can contain curved geometries.
Definition: qgswkbtypes.h:911
QgsMapLayer::Identifiable
@ Identifiable
If the layer is identifiable using the identify map tool and as a WMS layer.
Definition: qgsmaplayer.h:145
Qgis::RenderContextFlag::Antialiasing
@ Antialiasing
Use antialiasing while drawing.
QgsPalLayerSettings::priority
int priority
Label priority.
Definition: qgspallabeling.h:596
QgsWkbTypes::LineGeometry
@ LineGeometry
Definition: qgswkbtypes.h:143
Qgis::RenderContextFlag::RenderBlocking
@ RenderBlocking
Render and load remote sources in the same thread to ensure rendering remote sources (svg and images)...
QgsWms::QgsWmsParameters::backgroundColorAsColor
QColor backgroundColorAsColor() const
Returns BGCOLOR parameter as a QColor or its default value if not defined.
Definition: qgswmsparameters.cpp:1737
QgsGeometry::asWkt
QString asWkt(int precision=17) const
Exports the geometry to WKT.
Definition: qgsgeometry.cpp:1407
QgsWkbTypes::PointGeometry
@ PointGeometry
Definition: qgswkbtypes.h:142
qgslayoutrendercontext.h
QgsTextFormat::setBuffer
void setBuffer(const QgsTextBufferSettings &bufferSettings)
Sets the text's buffer settings.
Definition: qgstextformat.cpp:118
QgsPalLayerSettings::fieldName
QString fieldName
Name of field (or an expression) to use for label text.
Definition: qgspallabeling.h:354
QgsLayerTreeGroup::findLayerIds
QStringList findLayerIds() const
Find layer IDs used in all layer nodes.
Definition: qgslayertreegroup.cpp:498
QgsWms::QgsWmsParameter::J
@ J
Definition: qgswmsparameters.h:166
QgsCoordinateReferenceSystem::mapUnits
QgsUnitTypes::DistanceUnit mapUnits
Definition: qgscoordinatereferencesystem.h:215
QgsRectangle::yMaximum
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:193
QgsVectorLayer::mapTipTemplate
QString mapTipTemplate
Definition: qgsvectorlayer.h:397
QgsWkbTypes::NoGeometry
@ NoGeometry
Definition: qgswkbtypes.h:85
QgsMapLayer::customProperty
Q_INVOKABLE QVariant customProperty(const QString &value, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer.
Definition: qgsmaplayer.cpp:1999
qgsgeometry.h
qgsaccesscontrol.h
QgsVectorLayerSimpleLabeling
Basic implementation of the labeling interface.
Definition: qgsvectorlayerlabeling.h:163
QgsServerFeatureId::updateFeatureRequestFromServerFids
SERVER_EXPORT QgsFeatureRequest updateFeatureRequestFromServerFids(QgsFeatureRequest &featureRequest, const QStringList &serverFids, const QgsVectorDataProvider *provider)
Returns the feature request based on feature ids build with primary keys.
Definition: qgsserverfeatureid.cpp:39
QgsWms::QgsWmsRenderContext::layer
QgsMapLayer * layer(const QString &nickname) const
Returns the layer corresponding to the nickname, or a nullptr if not found or if the layer do not nee...
Definition: qgswmsrendercontext.cpp:289
QgsLayoutRenderContext::setFeatureFilterProvider
void setFeatureFilterProvider(QgsFeatureFilterProvider *featureFilterProvider)
Sets feature filter provider to featureFilterProvider.
Definition: qgslayoutrendercontext.cpp:145
QgsWms::QgsBadRequestException
Exception thrown in case of malformed request.
Definition: qgswmsserviceexception.h:226
QgsWms::QgsWmsParameters::layoutParameter
QString layoutParameter(const QString &id, bool &ok) const
Returns a layout parameter thanks to its id.
Definition: qgswmsparameters.cpp:1303
QgsDxfExport::DxfLayer
Layers and optional attribute index to split into multiple layers using attribute value as layer name...
Definition: qgsdxfexport.h:73
QgsFeatureIterator::nextFeature
bool nextFeature(QgsFeature &f)
Definition: qgsfeatureiterator.h:399
QgsVectorLayer::attributeDisplayName
QString attributeDisplayName(int index) const
Convenience function that returns the attribute alias if defined or the field name else.
Definition: qgsvectorlayer.cpp:3245
c
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
Definition: porting_processing.dox:1
QgsGeometry
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
QgsMapToPixel
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:38
QgsWms::QgsWmsParameters::atlasPk
QStringList atlasPk() const
Returns the ATLAS_PK parameter.
Definition: qgswmsparameters.cpp:1317
QgsLayout
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Definition: qgslayout.h:50
QgsServerException
Exception base class for server exceptions.
Definition: qgsserverexception.h:42
str
#define str(x)
Definition: qgis.cpp:37
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:391
QgsRectangle::width
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
Definition: qgsrectangle.h:223
QgsOgcUtils::geometryToGML
static QDomElement geometryToGML(const QgsGeometry &geometry, QDomDocument &doc, QgsOgcUtils::GMLVersion gmlVersion, const QString &srsName, bool invertAxisOrientation, const QString &gmlIdBase, int precision=17)
Exports the geometry to GML.
Definition: qgsogcutils.cpp:1197
QgsServerProjectUtils::wmsDefaultMapUnitsPerMm
SERVER_EXPORT double wmsDefaultMapUnitsPerMm(const QgsProject &project)
Returns the default number of map units per millimeters in case of the scale is not given.
Definition: qgsserverprojectutils.cpp:155
QgsVectorLayer::editFormConfig
QgsEditFormConfig editFormConfig
Definition: qgsvectorlayer.h:398
QgsWms::QgsWmsRenderContext::testFlag
bool testFlag(Flag flag) const
Returns the status of a rendering flag.
Definition: qgswmsrendercontext.cpp:67
QgsMapLayer
Base class for all map layer types. This is the base class for all map layer types (vector,...
Definition: qgsmaplayer.h:72
QgsServerSettings::maxThreads
int maxThreads() const
Returns the maximum number of threads to use.
Definition: qgsserversettings.cpp:514
QgsRenderContext::fromQPainter
static QgsRenderContext fromQPainter(QPainter *painter)
Creates a default render context given a pixel based QPainter destination.
Definition: qgsrendercontext.cpp:143
QgsAttributeEditorContainer
This is a container for attribute editors, used to group them visually in the attribute form if it is...
Definition: qgsattributeeditorcontainer.h:27
QgsEditFormConfig::layout
EditorLayout layout() const
Gets the active layout style for the attribute editor for this layer.
Definition: qgseditformconfig.cpp:196
QgsAnnotationManager::annotations
QList< QgsAnnotation * > annotations() const
Returns a list of all annotations contained in the manager.
Definition: qgsannotationmanager.cpp:73
QgsPointXY::x
double x
Definition: qgspointxy.h:62
QgsMapLayerStyleManager::addStyleFromLayer
bool addStyleFromLayer(const QString &name)
Add style by cloning the current one.
Definition: qgsmaplayerstylemanager.cpp:121
QgsWms::QgsWmsParameters::polygonTolerance
QString polygonTolerance() const
Returns FI_POLYGON_TOLERANCE parameter or an empty string if not defined.
Definition: qgswmsparameters.cpp:1135
QgsFieldFormatterRegistry::fieldFormatter
QgsFieldFormatter * fieldFormatter(const QString &id) const
Gets a field formatter by its id.
Definition: qgsfieldformatterregistry.cpp:76
qgsprintlayout.h
QgsWms::QgsWmsRenderContext::project
const QgsProject * project() const
Returns the project.
Definition: qgswmsrendercontext.cpp:82
QgsTextBufferSettings::setSize
void setSize(double size)
Sets the size of the buffer.
Definition: qgstextbuffersettings.cpp:87
QgsMapLayerType::VectorTileLayer
@ VectorTileLayer
Vector tile layer. Added in QGIS 3.14.
QgsLayoutItemMap::scale
double scale() const
Returns the map scale.
Definition: qgslayoutitemmap.cpp:172
QgsWms::QgsWmsRenderContext::mapTileBuffer
double mapTileBuffer(int mapWidth) const
Returns the tile buffer in geographical units for the given map width in pixels.
Definition: qgswmsrendercontext.cpp:711
QgsLayoutExporter::SvgExportSettings
Contains settings relating to exporting layouts to SVG.
Definition: qgslayoutexporter.h:483
QgsWms::QgsWmsParameters::withGeometry
bool withGeometry() const
Returns if the client wants the feature info response with geometry information.
Definition: qgswmsparameters.cpp:2055
QgsWms::QgsWmsParameters::jAsInt
int jAsInt() const
Returns J parameter as an int or its default value if not defined.
Definition: qgswmsparameters.cpp:940
QgsWms::QgsWmsParameters::JPG
@ JPG
Definition: qgswmsparameters.h:356
QgsMapLayer::name
QString name
Definition: qgsmaplayer.h:76
QgsWms::QgsWmsParameter::FORMAT
@ FORMAT
Definition: qgswmsparameters.h:163
QgsLayoutRenderContext::FlagDrawSelection
@ FlagDrawSelection
Draw selection.
Definition: qgslayoutrendercontext.h:52
QgsWkbTypes::UnknownGeometry
@ UnknownGeometry
Definition: qgswkbtypes.h:145
QgsExpression::quotedColumnRef
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
Definition: qgsexpression.cpp:68
QgsWms::QgsWmsParameters::dxfLayerAttributes
QStringList dxfLayerAttributes() const
Returns the DXF LAYERATTRIBUTES parameter.
Definition: qgswmsparameters.cpp:2111
qgsmaplayerlegend.h
QgsTextBufferSettings::setColor
void setColor(const QColor &color)
Sets the color for the buffer.
Definition: qgstextbuffersettings.cpp:117
QgsWms::QgsWmsParameters::dxfMode
QgsDxfExport::SymbologyExport dxfMode() const
Returns the DXF MODE parameter.
Definition: qgswmsparameters.cpp:2150
QgsWms::QgsWmsParameters::y
QString y() const
Returns Y parameter or an empty string if not defined.
Definition: qgswmsparameters.cpp:950
QgsMapLayerStyleManager::setCurrentStyle
bool setCurrentStyle(const QString &name)
Set a different style as the current style - will apply it to the layer.
Definition: qgsmaplayerstylemanager.cpp:169
QgsCoordinateReferenceSystem::authid
QString authid
Definition: qgscoordinatereferencesystem.h:217
qgslayoutpagecollection.h
QgsWms::QgsWmsParameter
WMS parameter received from the client.
Definition: qgswmsparameters.h:115
QgsLayoutAtlas::next
bool next() override
Definition: qgslayoutatlas.cpp:417
QgsLayoutSize
This class provides a method of storing sizes, consisting of a width and height, for use in QGIS layo...
Definition: qgslayoutsize.h:40
QgsTemporalRangeObject::setTemporalRange
void setTemporalRange(const QgsDateTimeRange &range)
Sets the temporal range for the object.
Definition: qgstemporalrangeobject.cpp:35
QgsVectorLayer::subsetString
QString subsetString
Definition: qgsvectorlayer.h:395
QgsGeometry::boundingBox
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
Definition: qgsgeometry.cpp:1080
qgslayertreemodel.h
QgsLayerTreeModelLegendNode::ItemContext::painter
QPainter * painter
Painter.
Definition: qgslayertreemodellegendnode.h:177
qgsdxfexport.h
QgsAttributes
A vector of attributes. Mostly equal to QVector<QVariant>.
Definition: qgsattributes.h:57
QgsProject::createExpressionContext
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
Definition: qgsproject.cpp:2214
QgsVectorDataProvider
This is the base class for vector data providers.
Definition: qgsvectordataprovider.h:58
QgsFeature::fields
QgsFields fields
Definition: qgsfeature.h:70
qgsexception.h
QgsMapLayer::serverProperties
QgsMapLayerServerProperties * serverProperties()
Returns QGIS Server Properties for the map layer.
Definition: qgsmaplayer.h:426
QgsServerWmsDimensionProperties::WmsDimensionInfo::AllValues
@ AllValues
Display all values of the dimension.
Definition: qgsmaplayerserverproperties.h:165
QgsLayerTreeNode::parent
QgsLayerTreeNode * parent()
Gets pointer to the parent. If parent is nullptr, the node is a root node.
Definition: qgslayertreenode.h:119
QgsLegendRenderer
The QgsLegendRenderer class handles automatic layout and rendering of legend. The content is given by...
Definition: qgslegendrenderer.h:46
QgsFeature
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:55
QgsPropertyCollection::setProperty
void setProperty(int key, const QgsProperty &property)
Adds a property to the collection and takes ownership of it.
Definition: qgspropertycollection.cpp:187
QgsLayoutExporter::PdfExportSettings
Contains settings relating to exporting layouts to PDF.
Definition: qgslayoutexporter.h:253
QgsServerApiUtils::parseTemporalDateTimeInterval
static QgsDateTimeRange parseTemporalDateTimeInterval(const QString &interval) SIP_THROW(QgsServerApiBadRequestException)
Parses a datetime interval and returns a QgsDateTimeRange.
Definition: qgsserverapiutils.cpp:142
QgsWms::QgsWmsParameters::formatAsString
QString formatAsString() const
Returns FORMAT parameter as a string.
Definition: qgswmsparameters.cpp:832
qgsvectorlayerlabeling.h
QgsAttributeEditorElement::name
QString name() const
Returns the name of this element.
Definition: qgsattributeeditorelement.h:156
qgswmsserviceexception.h
QgsWms::QgsWmsParameters::iAsInt
int iAsInt() const
Returns I parameter as an int or its default value if not defined.
Definition: qgswmsparameters.cpp:935
QgsLayoutAtlas::setFilterExpression
bool setFilterExpression(const QString &expression, QString &errorString)
Sets the expression used for filtering features in the coverage layer.
Definition: qgslayoutatlas.cpp:221
QgsServerProjectUtils::wmsRestrictedComposers
SERVER_EXPORT QStringList wmsRestrictedComposers(const QgsProject &project)
Returns the restricted composer list.
Definition: qgsserverprojectutils.cpp:268
QgsServerProjectUtils::wmsInfoFormatSia2045
SERVER_EXPORT bool wmsInfoFormatSia2045(const QgsProject &project)
Returns if the info format is SIA20145.
Definition: qgsserverprojectutils.cpp:160
QgsWms::QgsRenderer::getLegendGraphics
QImage * getLegendGraphics(QgsLayerTreeModel &model)
Returns the map legend as an image (or nullptr in case of error).
Definition: qgswmsrenderer.cpp:134
QgsWms::QgsWmsParameters::infoFormat
Format infoFormat() const
Returns infoFormat.
Definition: qgswmsparameters.cpp:888
QgsPalLayerSettings::Property
Property
Data definable properties.
Definition: qgspallabeling.h:144
QgsVectorLayer::getFeature
QgsFeature getFeature(QgsFeatureId fid) const
Queries the layer for the feature with the given id.
Definition: qgsvectorlayer.h:1187
QgsWms::QgsWmsRenderContext::flattenedQueryLayers
QStringList flattenedQueryLayers(const QStringList &layerNames) const
Returns a list of query layer names where group names are replaced by the names of their layer compon...
Definition: qgswmsrendercontext.cpp:187
QgsWms::QgsWmsRenderContext::UseSelection
@ UseSelection
Definition: qgswmsrendercontext.h:56
QgsLayoutItemLabel
A layout item subclass for text labels.
Definition: qgslayoutitemlabel.h:36
QgsMapSettings::setOutputSize
void setOutputSize(QSize size)
Sets the size of the resulting map image, in pixels.
Definition: qgsmapsettings.cpp:244
QgsLayerTreeModelLegendNode::drawSymbol
virtual QSizeF drawSymbol(const QgsLegendSettings &settings, ItemContext *ctx, double itemHeight) const
Draws symbol on the left side of the item.
Definition: qgslayertreemodellegendnode.cpp:110
QgsWms::QgsWmsParameters::filters
QStringList filters() const
Returns the list of filters found in FILTER parameter.
Definition: qgswmsparameters.cpp:1417
qgsjsonutils.h
QgsWms::QgsWmsRenderContext::dotsPerMm
qreal dotsPerMm() const
Returns default dots per mm according to the current configuration.
Definition: qgswmsrendercontext.cpp:172
QgsWms::QgsWmsParameters::dxfUseLayerTitleAsName
bool dxfUseLayerTitleAsName() const
Returns the DXF USE_TITLE_AS_LAYERNAME parameter.
Definition: qgswmsparameters.cpp:2124
QgsCoordinateTransform::transform
QgsPointXY transform(const QgsPointXY &point, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward) const SIP_THROW(QgsCsException)
Transform the point from the source CRS to the destination CRS.
Definition: qgscoordinatetransform.cpp:272
QgsTextFormat::setSize
void setSize(double size)
Sets the size for rendered text.
Definition: qgstextformat.cpp:291
QgsWms::QgsWmsParameters::pointTolerance
QString pointTolerance() const
Returns FI_POINT_TOLERANCE parameter or an empty string if not defined.
Definition: qgswmsparameters.cpp:1145
QgsWms::QgsRenderer::configureLayers
void configureLayers(QList< QgsMapLayer * > &layers, QgsMapSettings *settings=nullptr)
Configures layers for rendering optionally considering the map settings.
Definition: qgswmsrenderer.cpp:3540
Qgis::LabelPlacement::Line
@ Line
Arranges candidates parallel to a generalised line representing the feature or parallel to a polygon'...
qgsfeaturestore.h
QgsFields::at
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Definition: qgsfields.cpp:163
QgsLegendModel
Item model implementation based on layer tree model for layout legend.
Definition: qgslayoutitemlegend.h:43
QgsExpression
Class for parsing and evaluation of expressions (formerly called "search strings")....
Definition: qgsexpression.h:102
QgsMapSettings
The QgsMapSettings class contains configuration for rendering of the map. The rendering itself is don...
Definition: qgsmapsettings.h:88
QgsPalLayerSettings::dataDefinedProperties
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the label's property collection, used for data defined overrides.
Definition: qgspallabeling.h:816
QgsBadRequestException
Exception thrown in case of malformed request.
Definition: qgsserverexception.h:121
QgsCoordinateTransform
Class for doing transforms between two map coordinate systems.
Definition: qgscoordinatetransform.h:57
QgsWms::QgsWmsRenderContext::layersToRender
QList< QgsMapLayer * > layersToRender() const
Returns a list of all layers to actually render according to the current configuration.
Definition: qgswmsrendercontext.cpp:224
QgsRasterRenderer::setOpacity
void setOpacity(double opacity)
Sets the opacity for the renderer, where opacity is a value between 0 (totally transparent) and 1....
Definition: qgsrasterrenderer.h:83
QgsLayoutAtlas::setFilterFeatures
void setFilterFeatures(bool filtered)
Sets whether features should be filtered in the coverage layer.
Definition: qgslayoutatlas.cpp:212
QgsGeometry::type
QgsWkbTypes::GeometryType type
Definition: qgsgeometry.h:128
QgsLayoutExporter::exportToPdf
ExportResult exportToPdf(const QString &filePath, const QgsLayoutExporter::PdfExportSettings &settings)
Exports the layout as a PDF to the filePath, using the specified export settings.
Definition: qgslayoutexporter.cpp:528
qgsattributeeditorelement.h
QgsWms::QgsWmsParameter::CRS
@ CRS
Definition: qgswmsparameters.h:125
QgsFeatureIterator
Wrapper for iterator of features from vector data provider or vector layer.
Definition: qgsfeatureiterator.h:289
QgsMapSettings::layerToMapCoordinates
QgsPointXY layerToMapCoordinates(const QgsMapLayer *layer, QgsPointXY point) const
transform point coordinates from layer's CRS to output CRS
Definition: qgsmapsettings.cpp:578
QgsFeatureRenderer::loadSld
static QgsFeatureRenderer * loadSld(const QDomNode &node, QgsWkbTypes::GeometryType geomType, QString &errorMessage)
Create a new renderer according to the information contained in the UserStyle element of a SLD style ...
Definition: qgsrenderer.cpp:222
QgsVectorLayer::geometryType
Q_INVOKABLE QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
Definition: qgsvectorlayer.cpp:720
Q_NOWARN_DEPRECATED_PUSH
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:2819
QgsMapLayerType::PointCloudLayer
@ PointCloudLayer
Point cloud layer. Added in QGIS 3.18.
QgsMapSettings::setExtent
void setExtent(const QgsRectangle &rect, bool magnified=true)
Sets the coordinates of the rectangle which should be rendered.
Definition: qgsmapsettings.cpp:80
QgsRectangle::isEmpty
bool isEmpty() const
Returns true if the rectangle is empty.
Definition: qgsrectangle.h:469
qgswkbtypes.h
qgsattributeeditorfield.h
QgsRaster::IdentifyFormat
IdentifyFormat
Definition: qgsraster.h:70
QgsExpression::replaceExpressionText
static QString replaceExpressionText(const QString &action, const QgsExpressionContext *context, const QgsDistanceArea *distanceArea=nullptr)
This function replaces each expression between [% and %] in the string with the result of its evaluat...
Definition: qgsexpression.cpp:434
qgslegendrenderer.h
qgscoordinatereferencesystem.h
QgsLayoutAtlas
Class used to render QgsLayout as an atlas, by iterating over the features from an associated vector ...
Definition: qgslayoutatlas.h:41
QgsFieldFormatter
A field formatter helps to handle and display values for a field.
Definition: qgsfieldformatter.h:72
QgsRasterInterface::capabilities
virtual int capabilities() const
Returns a bitmask containing the supported capabilities.
Definition: qgsrasterinterface.h:225
QgsFeatureRequest::setFlags
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.
Definition: qgsfeaturerequest.cpp:222
QgsLabelPlacementSettings::setOverlapHandling
void setOverlapHandling(Qgis::LabelOverlapHandling handling)
Sets the technique used to handle overlapping labels.
Definition: qgslabelplacementsettings.h:48
QgsWms::QgsWmsParameters::highlightLayersParameters
QList< QgsWmsParametersHighlightLayer > highlightLayersParameters() const
Returns parameters for each highlight layer.
Definition: qgswmsparameters.cpp:1649
QgsLabelLineSettings::setPlacementFlags
void setPlacementFlags(QgsLabeling::LinePlacementFlags flags)
Returns the line placement flags, which dictate how line labels can be placed above or below the line...
Definition: qgslabellinesettings.h:106
QgsExpression::expression
QString expression() const
Returns the original, unmodified expression string.
Definition: qgsexpression.cpp:60
QgsServerApiBadRequestException
Bad request error API exception.
Definition: qgsserverexception.h:244
qgsserverexception.h
QgsMapSettings::mapToPixel
const QgsMapToPixel & mapToPixel() const
Definition: qgsmapsettings.h:527
QgsServerWmsDimensionProperties::wmsDimensions
const QList< QgsServerWmsDimensionProperties::WmsDimensionInfo > wmsDimensions() const
Returns the QGIS Server WMS Dimension list.
Definition: qgsmaplayerserverproperties.cpp:126
QgsVectorLayer::selectByExpression
Q_INVOKABLE void selectByExpression(const QString &expression, Qgis::SelectBehavior behavior=Qgis::SelectBehavior::SetSelection, QgsExpressionContext *context=nullptr)
Selects matching features using an expression.
Definition: qgsvectorlayer.cpp:507
QgsMapThemeCollection::mapThemeState
QgsMapThemeCollection::MapThemeRecord mapThemeState(const QString &name) const
Returns the recorded state of a map theme.
Definition: qgsmapthemecollection.h:286
QgsWms::QgsWmsRestorer
RAII class to restore the rendering context configuration on destruction.
Definition: qgswmsrestorer.h:75
QgsWms::QgsRenderer::getLegendGraphicsAsJson
QJsonObject getLegendGraphicsAsJson(QgsLayerTreeModel &model)
Returns the map legend as a JSON object.
Definition: qgswmsrenderer.cpp:213
QgsLayoutExporter::ImageExportSettings::dpi
double dpi
Resolution to export layout at. If dpi <= 0 the default layout dpi will be used.
Definition: qgslayoutexporter.h:158
QgsGeometry::set
void set(QgsAbstractGeometry *geometry)
Sets the underlying geometry store.
Definition: qgsgeometry.cpp:147
qgsproject.h
QgsField::convertCompatible
bool convertCompatible(QVariant &v, QString *errorMessage=nullptr) const
Converts the provided variant to a compatible format.
Definition: qgsfield.cpp:402
QgsWms::QgsWmsParameters::dimensionValues
QMap< QString, QString > dimensionValues() const
Returns the dimensions parameter.
Definition: qgswmsparameters.cpp:2209
QgsField::ConfigurationFlag::HideFromWms
@ HideFromWms
Field is not available if layer is served as WMS from QGIS server.
QgsServerWmsDimensionProperties::WmsDimensionInfo::MinValue
@ MinValue
Add selection to current selection.
Definition: qgsmaplayerserverproperties.h:166
QgsFields::indexFromName
int indexFromName(const QString &fieldName) const
Gets the field index from the field name.
Definition: qgsfields.cpp:202
QgsWms::QgsWmsParameters::width
QString width() const
Returns WIDTH parameter or an empty string if not defined.
Definition: qgswmsparameters.cpp:727
QgsMapLayerType::PluginLayer
@ PluginLayer
Plugin based layer.
Qgis::LabelPlacement::AroundPoint
@ AroundPoint
Arranges candidates in a circle around a point (or centroid of a polygon). Applies to point or polygo...
QgsLayoutMeasurement
This class provides a method of storing measurements for use in QGIS layouts using a variety of diffe...
Definition: qgslayoutmeasurement.h:33
QgsProjectVersion
A class to describe the version of a project.
Definition: qgsprojectversion.h:32
QgsMapRendererJob::Error::layerID
QString layerID
Definition: qgsmaprendererjob.h:361
QgsMapSettings::layers
QList< QgsMapLayer * > layers(bool expandGroupLayers=false) const
Returns the list of layers which will be rendered in the map.
Definition: qgsmapsettings.cpp:299
QgsRasterLayer::dataProvider
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
Definition: qgsrasterlayer.cpp:257
QgsAttributeEditorElement::AeTypeField
@ AeTypeField
A field.
Definition: qgsattributeeditorelement.h:120
QgsOgcUtils::rectangleToGMLEnvelope
static QDomElement rectangleToGMLEnvelope(QgsRectangle *env, QDomDocument &doc, int precision=17)
Exports the rectangle to GML3 Envelope.
Definition: qgsogcutils.cpp:1151
QgsWms::QgsWmsRenderContext::parameters
QgsWmsParameters parameters() const
Returns WMS parameters.
Definition: qgswmsrendercontext.cpp:72
qgslayoutitemhtml.h
qgsfieldformatter.h
QgsFields::indexOf
int indexOf(const QString &fieldName) const
Gets the field index from the field name.
Definition: qgsfields.cpp:207
QgsVectorLayer::setSubsetString
virtual bool setSubsetString(const QString &subset)
Sets the string (typically sql) used to define a subset of the layer.
Definition: qgsvectorlayer.cpp:1002
QgsMapSettings::setExtentBuffer
void setExtentBuffer(double buffer)
Sets the buffer in map units to use around the visible extent for rendering symbols whose correspondi...
Definition: qgsmapsettings.cpp:97
qgslayoutitemmap.h
QgsWms::QgsRenderer::symbols
HitTest symbols()
Returns the hit test according to the current context.
Definition: qgswmsrenderer.cpp:280
Qgis::LabelPlacement
LabelPlacement
Placement modes which determine how label candidates are generated for a feature.
Definition: qgis.h:560
QgsWms::QgsWmsParameters::dxfScale
double dxfScale() const
Returns the DXF SCALE parameter.
Definition: qgswmsparameters.cpp:2137
Qgis::MapSettingsFlag::RenderMapTile
@ RenderMapTile
Draw map such that there are no problems between adjacent tiles.
qgsmessagelog.h
QgsExpressionContext::setFeature
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Definition: qgsexpressioncontext.cpp:525
QgsVectorLayer::renderer
QgsFeatureRenderer * renderer()
Returns the feature renderer used for rendering the features in the layer in 2D map views.
Definition: qgsvectorlayer.h:903
QgsFeatureFilterProviderGroup::addProvider
QgsFeatureFilterProviderGroup & addProvider(const QgsFeatureFilterProvider *provider)
Add another filter provider to the group.
Definition: qgsfeaturefilterprovidergroup.cpp:52
QgsLayerTreeGroup::removeChildrenGroupWithoutLayers
void removeChildrenGroupWithoutLayers()
Remove all child group nodes without layers.
Definition: qgslayertreegroup.cpp:197
qgslayoutatlas.h
QgsField
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:50
QgsWms::QgsWmsParameters::noMText
bool noMText() const
Definition: qgswmsparameters.cpp:1560
QgsWms::QgsWmsRenderContext::UseOpacity
@ UseOpacity
Definition: qgswmsrendercontext.h:54
QgsMapLayer::type
QgsMapLayerType type
Definition: qgsmaplayer.h:80
QgsLayerTreeModelLegendNode
The QgsLegendRendererItem class is abstract interface for legend items returned from QgsMapLayerLegen...
Definition: qgslayertreemodellegendnode.h:49