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