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