70 #include <QStringList>
71 #include <QTemporaryFile>
74 #include <nlohmann/json.hpp>
101 mProject = mContext.project();
103 mWmsParameters = mContext.parameters();
104 mWmsParameters.dump();
109 removeTemporaryLayers();
115 std::unique_ptr<QgsWmsRestorer> restorer;
127 std::unique_ptr<QImage> image;
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 ) );
134 QPainter painter( image.get() );
145 renderer.drawLegend( context );
148 return image.release();
154 std::unique_ptr<QgsWmsRestorer> restorer;
163 std::unique_ptr<QImage> image( createImage( size ) );
167 std::unique_ptr<QPainter> painter;
168 painter.reset(
new QPainter( image.get() ) );
169 painter->setRenderHint( QPainter::Antialiasing,
true );
170 painter->scale( dpmm, dpmm );
176 nodeModel.
drawSymbol( settings, &ctx, size.height() / dpmm );
179 return image.release();
185 std::unique_ptr<QgsWmsRestorer> restorer;
198 return renderer.exportLegendToJson( renderContext );
201 void QgsRenderer::runHitTest(
const QgsMapSettings &mapSettings, HitTest &hitTest )
const
205 for (
const QString &
id : mapSettings.
layerIds() )
222 runHitTestLayer( vl, usedSymbols, context );
228 std::unique_ptr< QgsFeatureRenderer > r( vl->
renderer()->
clone() );
230 r->startRender( context, vl->
fields() );
238 if ( moreSymbolsPerFeature )
240 for (
QgsSymbol *s : r->originalSymbolsForFeature( f, context ) )
246 r->stopRender( context );
255 QStringLiteral(
"The requested map size is too large" ) );
259 std::unique_ptr<QgsWmsRestorer> restorer;
260 restorer.reset(
new QgsWmsRestorer( mContext ) );
269 std::unique_ptr<QPainter> painter;
270 std::unique_ptr<QImage> image( createImage( mContext.
mapSize() ) );
273 configureMapSettings( image.get(), mapSettings );
280 runHitTest( mapSettings,
symbols );
288 std::unique_ptr<QgsWmsRestorer> restorer;
293 if ( templateName.isEmpty() )
309 if ( sourceLayout->pageCollection()->pageCount() < 1 )
312 QStringLiteral(
"The template has no pages" ) );
315 std::unique_ptr<QgsPrintLayout> layout( sourceLayout->clone() );
319 QStringList atlasPk = mWmsParameters.
atlasPk();
320 if ( !atlasPk.isEmpty() )
322 atlas = layout->atlas();
323 if ( !atlas || !atlas->
enabled() )
327 QStringLiteral(
"The template has no atlas enabled" ) );
334 QStringLiteral(
"The atlas has no coverage layer" ) );
338 if ( atlasPk.size() == 1 && atlasPk.at( 0 ) == QStringLiteral(
"*" ) )
342 if ( atlas->
count() > maxAtlasFeatures )
345 QString(
"The project configuration allows printing maximum %1 atlas features at a time" ).arg( maxAtlasFeatures ) );
351 if ( pkIndexes.size() < 1 )
353 throw QgsException( QStringLiteral(
"An error occurred during the Atlas print" ) );
355 QStringList pkAttributeNames;
356 for (
int i = 0; i < pkIndexes.size(); ++i )
358 pkAttributeNames.append( cLayer->
fields()[pkIndexes.at( i )].name() );
361 int nAtlasFeatures = atlasPk.size() / pkIndexes.size();
362 if ( nAtlasFeatures * pkIndexes.size() != atlasPk.size() )
365 QStringLiteral(
"Wrong number of ATLAS_PK parameters" ) );
369 if ( nAtlasFeatures > maxAtlasFeatures )
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 ) );
376 QString filterString;
377 int currentAtlasPk = 0;
379 for (
int i = 0; i < nAtlasFeatures; ++i )
383 filterString.append(
" OR " );
386 filterString.append(
"( " );
388 for (
int j = 0; j < pkIndexes.size(); ++j )
392 filterString.append(
" AND " );
394 filterString.append( QString(
"\"%1\" = %2" ).arg( pkAttributeNames.at( j ) ).arg( atlasPk.at( currentAtlasPk ) ) );
398 filterString.append(
" )" );
404 if ( !errorString.isEmpty() )
406 throw QgsException( QStringLiteral(
"An error occurred during the Atlas print" ) );
418 std::unique_ptr<QImage> image(
new QImage() );
419 configureMapSettings( image.get(), mapSettings );
425 configurePrintLayout( layout.get(), mapSettings, atlas );
431 QTemporaryFile tempOutputFile( QDir::tempPath() +
'/' + QStringLiteral(
"XXXXXX.%1" ).arg( extension ) );
432 if ( !tempOutputFile.open() )
434 throw QgsException( QStringLiteral(
"Could not open temporary file for the GetPrint request." ) );
443 if ( !mWmsParameters.
dpi().isEmpty() )
446 double dpi( mWmsParameters.
dpi().toDouble( &ok ) );
448 exportSettings.
dpi = dpi;
459 atlasSvgExport.exportToSvg( tempOutputFile.fileName(), exportSettings );
465 exporter.exportToSvg( tempOutputFile.fileName(), exportSettings );
474 double dpi( layout->renderContext().dpi( ) );
475 if ( !mWmsParameters.
dpi().isEmpty() )
478 double _dpi = mWmsParameters.
dpi().toDouble( &ok );
482 exportSettings.
dpi = dpi;
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 ) );
491 exportSettings.
pages.append( 0 );
499 atlasPngExport.exportToImage( tempOutputFile.fileName(), exportSettings );
505 exporter.exportToImage( tempOutputFile.fileName(), exportSettings );
513 if ( !mWmsParameters.
dpi().isEmpty() )
516 double dpi( mWmsParameters.
dpi().toDouble( &ok ) );
518 exportSettings.
dpi = dpi;
523 exportSettings.
rasterizeWholeImage = layout->customProperty( QStringLiteral(
"rasterize" ),
false ).toBool();
529 exporter.exportToPdf( atlas, tempOutputFile.fileName(), exportSettings, exportError );
533 exporter.exportToPdf( tempOutputFile.fileName(), exportSettings );
544 handlePrintErrors( atlas->
layout() );
548 handlePrintErrors( layout.get() );
551 return tempOutputFile.readAll();
558 QList<QgsLayoutItemMap *> maps;
564 for (
const auto &map : qgis::as_const( maps ) )
569 if ( !atlasPrint || !map->atlasDriven() )
572 if ( !cMapParams.mHasExtent )
575 c->removeLayoutItem( map );
593 if ( cMapParams.mScale > 0 )
595 map->setScale(
static_cast<double>( cMapParams.mScale ) );
599 if ( cMapParams.mRotation )
601 map->setMapRotation( cMapParams.mRotation );
605 if ( !map->keepLayerSet() )
607 if ( cMapParams.mLayers.isEmpty() && cMapParams.mExternalLayers.isEmpty() )
609 map->setLayers( mapSettings.
layers() );
613 QList<QgsMapLayer *> layerSet;
614 for (
auto layer : cMapParams.mLayers )
618 QList<QgsMapLayer *> layersFromGroup;
620 const QList<QgsMapLayer *> cLayersFromGroup = mContext.
layersFromGroup( layer.mNickname );
621 for (
QgsMapLayer *layerFromGroup : cLayersFromGroup )
624 if ( ! layerFromGroup )
629 layersFromGroup.push_front( layerFromGroup );
632 if ( !layersFromGroup.isEmpty() )
634 layerSet.append( layersFromGroup );
646 setLayerStyle( mlayer, layer.mStyle );
651 layerSet << externalLayers( cMapParams.mExternalLayers );
652 layerSet << highlightLayers( cMapParams.mHighlightLayers );
653 std::reverse( layerSet.begin(), layerSet.end() );
654 map->setLayers( layerSet );
656 map->setKeepLayerSet(
true );
660 if ( cMapParams.mGridX > 0 && cMapParams.mGridY > 0 )
662 map->grid()->setIntervalX(
static_cast<double>( cMapParams.mGridX ) );
663 map->grid()->setIntervalY(
static_cast<double>( cMapParams.mGridY ) );
668 QList<QgsLayoutItemLabel *> labels;
670 for (
const auto &label : qgis::as_const( labels ) )
673 const QString labelId = label->
id();
674 const QString labelParam = mWmsParameters.
layoutParameter( labelId, ok );
679 if ( labelParam.isEmpty() )
683 c->removeItem( label );
688 label->setText( labelParam );
692 QList<QgsLayoutItemHtml *> htmls;
694 for (
const auto &html : qgis::as_const( htmls ) )
696 if ( html->frameCount() == 0 )
701 const QString htmlId = htmlFrame->
id();
714 c->removeMultiFrame( html );
720 html->setUrl( newUrl );
726 QList<QgsLayoutItemLegend *> legends;
728 for (
const auto &legend : qgis::as_const( legends ) )
730 if ( legend->autoUpdateModel() )
740 legend->setAutoUpdateModel(
false );
744 QStringList layerSet;
745 const QList<QgsMapLayer *> layerList( map->
layers() );
746 for (
const auto &layer : layerList )
747 layerSet << layer->id();
759 for (
const auto &layerId : layerIds )
766 if ( !layerSet.contains( layerId ) )
768 qobject_cast<QgsLayerTreeGroup *>( nodeLayer->
parent() )->removeChildNode( nodeLayer );
775 qobject_cast<QgsLayerTreeGroup *>( nodeLayer->
parent() )->removeChildNode( nodeLayer );
791 QStringLiteral(
"The requested map size is too large" ) );
795 std::unique_ptr<QgsWmsRestorer> restorer;
796 restorer.reset(
new QgsWmsRestorer( mContext ) );
806 std::unique_ptr<QPainter> painter;
807 std::unique_ptr<QImage> image( createImage( mContext.
mapSize() ) );
810 configureMapSettings( image.get(), mapSettings );
816 painter.reset( layersRendering( mapSettings, *image ) );
819 annotationsRendering( painter.get() );
825 QImage *scaledImage = scaleImage( image.get() );
827 image.reset( scaledImage );
830 return image.release();
836 std::unique_ptr<QgsWmsRestorer> restorer;
845 QList< QgsDxfExport::DxfLayer > dxfLayers;
857 int layerAttribute = -1;
858 if ( attributes.size() > layerIdx )
867 std::unique_ptr<QgsDxfExport> dxf = qgis::make_unique<QgsDxfExport>();
869 dxf->addLayers( dxfLayers );
871 dxf->setSymbologyExport( mWmsParameters.
dxfMode() );
872 if ( mWmsParameters.
dxfFormatOptions().contains( QgsWmsParameters::DxfFormatOption::SCALE ) )
874 dxf->setSymbologyScale( mWmsParameters.
dxfScale() );
877 dxf->setForce2d( mWmsParameters.
isForce2D() );
878 QgsDxfExport::Flags flags;
879 if ( mWmsParameters.
noMText() )
880 flags.setFlag( QgsDxfExport::Flag::FlagNoMText );
882 dxf->setFlags( flags );
890 if ( i < 0 || i > mapSettings.
outputSize().width() )
898 if ( j < 0 || j > mapSettings.
outputSize().height() )
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();
928 if ( !ijDefined && !xyDefined && !filtersDefined && !filterGeomDefined )
932 if ( mWmsParameters.
j().isEmpty() )
939 if ( infoFormat == QgsWmsParameters::Format::NONE )
946 std::unique_ptr<QImage> outputImage( createImage( mContext.
mapSize() ) );
949 std::unique_ptr<QgsWmsRestorer> restorer;
950 restorer.reset(
new QgsWmsRestorer( mContext ) );
954 bool mandatoryCrsParam =
true;
955 if ( filtersDefined && !ijDefined && !xyDefined && mWmsParameters.
crs().isEmpty() )
957 mandatoryCrsParam =
false;
963 configureMapSettings( outputImage.get(), mapSettings, mandatoryCrsParam );
967 const double scaleDenominator = scaleCalc.calculate( mWmsParameters.
bboxAsRectangle(), outputImage->
width() );
970 QgsWmsRenderContext context = mContext;
973 QList<QgsMapLayer *> layers = context.layersToRender();
979 QDomDocument result = featureInfoDocument( layers, mapSettings, outputImage.get(), version );
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 );
990 ba = result.toByteArray();
995 QImage *QgsRenderer::createImage(
const QSize &size )
const
997 std::unique_ptr<QImage> image;
1005 image = qgis::make_unique<QImage>( size, QImage::Format_ARGB32_Premultiplied );
1010 image = qgis::make_unique<QImage>( size, QImage::Format_RGB32 );
1015 if ( image->isNull() )
1017 throw QgsException( QStringLiteral(
"createImage: image could not be created, check for out of memory conditions" ) );
1020 const int dpm =
static_cast<int>( mContext.
dotsPerMm() * 1000.0 );
1021 image->setDotsPerMeterX( dpm );
1022 image->setDotsPerMeterY( dpm );
1024 return image.release();
1027 void QgsRenderer::configureMapSettings(
const QPaintDevice *paintDevice,
QgsMapSettings &mapSettings,
bool mandatoryCrsParam )
const
1031 throw QgsException( QStringLiteral(
"configureMapSettings: no paint device" ) );
1034 mapSettings.
setOutputSize( QSize( paintDevice->width(), paintDevice->height() ) );
1035 mapSettings.
setOutputDpi( paintDevice->logicalDpiX() );
1039 if ( !mWmsParameters.
bbox().isEmpty() && mapExtent.
isEmpty() )
1045 QString
crs = mWmsParameters.
crs();
1046 if (
crs.compare(
"CRS:84", Qt::CaseInsensitive ) == 0 )
1048 crs = QString(
"EPSG:4326" );
1051 else if (
crs.isEmpty() && !mandatoryCrsParam )
1053 crs = QString(
"EPSG:4326" );
1063 QgsWmsParameter parameter;
1105 else if ( backgroundColor.isValid() )
1125 QDomDocument QgsRenderer::featureInfoDocument( QList<QgsMapLayer *> &layers,
const QgsMapSettings &mapSettings,
1126 const QImage *outputImage,
const QString &version )
const
1130 bool ijDefined = ( !mWmsParameters.
i().isEmpty() && !mWmsParameters.
j().isEmpty() );
1132 bool xyDefined = ( !mWmsParameters.
x().isEmpty() && !mWmsParameters.
y().isEmpty() );
1134 bool filtersDefined = !mWmsParameters.
filters().isEmpty();
1136 bool filterGeomDefined = !mWmsParameters.
filterGeom().isEmpty();
1139 if ( featureCount < 1 )
1144 int i = mWmsParameters.
iAsInt();
1145 int j = mWmsParameters.
jAsInt();
1146 if ( xyDefined && !ijDefined )
1148 i = mWmsParameters.
xAsInt();
1149 j = mWmsParameters.
yAsInt();
1153 if ( ( i != -1 && j != -1 && width != 0 && height != 0 ) && ( width != outputImage->width() || height != outputImage->height() ) )
1155 i *= ( outputImage->width() /
static_cast<double>( width ) );
1156 j *= ( outputImage->height() /
static_cast<double>( height ) );
1160 std::unique_ptr<QgsRectangle> featuresRect;
1161 std::unique_ptr<QgsGeometry> filterGeom;
1162 std::unique_ptr<QgsPointXY> infoPoint;
1164 if ( i != -1 && j != -1 )
1167 infoPointToMapCoordinates( i, j, infoPoint.get(), mapSettings );
1169 else if ( filtersDefined )
1173 else if ( filterGeomDefined )
1178 QDomDocument result;
1180 QDomElement getFeatureInfoElement;
1182 if ( infoFormat == QgsWmsParameters::Format::GML )
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" ) );
1197 if ( featureInfoElemName.isEmpty() )
1199 featureInfoElemName = QStringLiteral(
"GetFeatureInfoResponse" );
1202 if ( featureInfoElemNs.isEmpty() )
1204 getFeatureInfoElement = result.createElement( featureInfoElemName );
1208 getFeatureInfoElement = result.createElementNS( featureInfoElemNs, featureInfoElemName );
1212 if ( !featureInfoSchema.isEmpty() )
1214 getFeatureInfoElement.setAttribute( QStringLiteral(
"xmlns:xsi" ), QStringLiteral(
"http://www.w3.org/2001/XMLSchema-instance" ) );
1215 getFeatureInfoElement.setAttribute( QStringLiteral(
"xsi:schemaLocation" ), featureInfoSchema );
1218 result.appendChild( getFeatureInfoElement );
1228 for (
const QString &queryLayer : queryLayers )
1230 bool validLayer =
false;
1231 bool queryableLayer =
true;
1232 for (
QgsMapLayer *layer : qgis::as_const( layers ) )
1238 if ( !queryableLayer )
1243 QDomElement layerElement;
1244 if ( infoFormat == QgsWmsParameters::Format::GML )
1246 layerElement = getFeatureInfoElement;
1250 layerElement = result.createElement( QStringLiteral(
"Layer" ) );
1251 QString layerName = queryLayer;
1254 QHash<QString, QString>::const_iterator layerAliasIt = layerAliasMap.constFind( layerName );
1255 if ( layerAliasIt != layerAliasMap.constEnd() )
1257 layerName = layerAliasIt.value();
1260 layerElement.setAttribute( QStringLiteral(
"name" ), layerName );
1261 getFeatureInfoElement.appendChild( layerElement );
1264 layerElement.setAttribute( QStringLiteral(
"id" ), layer->id() );
1270 QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layer );
1273 ( void )featureInfoFromVectorLayer( vectorLayer, infoPoint.get(), featureCount, result, layerElement, mapSettings, renderContext, version, featuresRect.get(), filterGeom.get() );
1279 QgsRasterLayer *rasterLayer = qobject_cast<QgsRasterLayer *>( layer );
1288 QgsPointXY layerInfoPoint = mapSettings.mapToLayerCoordinates( layer, *( infoPoint.get() ) );
1293 if ( infoFormat == QgsWmsParameters::Format::GML )
1295 layerElement = result.createElement( QStringLiteral(
"gml:featureMember" ) );
1296 getFeatureInfoElement.appendChild( layerElement );
1299 ( void )featureInfoFromRasterLayer( rasterLayer, mapSettings, &layerInfoPoint, result, layerElement, version );
1307 param.mValue = queryLayer;
1311 else if ( ( validLayer && !queryableLayer ) || ( !validLayer && mContext.
isValidGroup( queryLayer ) ) )
1314 param.mValue = queryLayer;
1316 bool hasGroupAndQueryable {
false };
1321 for (
const QString &ql : constNicks )
1325 const QList<QgsMapLayer *> constLayers { mContext.
layerGroups()[ql] };
1328 if ( ( ! ml->shortName().isEmpty() && ml->shortName() == queryLayer ) || ( ml->name() == queryLayer ) )
1334 hasGroupAndQueryable =
true;
1343 if ( ! hasGroupAndQueryable )
1353 if ( infoFormat == QgsWmsParameters::Format::GML )
1355 QDomElement bBoxElem = result.createElement( QStringLiteral(
"gml:boundedBy" ) );
1356 QDomElement boxElem;
1358 if ( gmlVersion < 3 )
1370 boxElem.setAttribute( QStringLiteral(
"srsName" ),
crs.
authid() );
1372 bBoxElem.appendChild( boxElem );
1373 getFeatureInfoElement.insertBefore( bBoxElem, QDomNode() );
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() );
1387 if ( sia2045 && infoFormat == QgsWmsParameters::Format::XML )
1389 convertFeatureInfoToSia2045( result );
1395 bool QgsRenderer::featureInfoFromVectorLayer(
QgsVectorLayer *layer,
1398 QDomDocument &infoDocument,
1399 QDomElement &layerElement,
1402 const QString &version,
1414 std::unique_ptr<QgsGeometry> layerFilterGeom;
1417 layerFilterGeom.reset(
new QgsGeometry( *filterGeom ) );
1431 searchRect = featureInfoSearchRect( layer, mapSettings, renderContext, *infoPoint );
1433 else if ( layerFilterGeom )
1435 searchRect = layerFilterGeom->boundingBox();
1437 else if ( !mWmsParameters.
bbox().isEmpty() )
1439 searchRect = layerRect;
1446 int featureCounter = 0;
1466 if ( layerFilterGeom )
1468 fReq.
setFilterExpression( QString(
"intersects( $geometry, geom_from_wkt('%1') )" ).arg( layerFilterGeom->asWkt() ) );
1471 #ifdef HAVE_SERVER_PYTHON_PLUGINS
1472 mContext.accessControl()->filterFeatures( layer, fReq );
1474 QStringList attributes;
1475 for (
const QgsField &field : fields )
1477 attributes.append( field.name() );
1479 attributes = mContext.accessControl()->layerAttributes( layer, attributes );
1484 std::unique_ptr< QgsFeatureRenderer > r2( layer->
renderer() ? layer->
renderer()->
clone() :
nullptr );
1487 r2->startRender( renderContext, layer->
fields() );
1490 bool featureBBoxInitialized =
false;
1499 if ( featureCounter > nFeatures )
1514 bool render = r2->willRenderFeature( feature, renderContext );
1527 if ( !featureBBoxInitialized && featureBBox->
isEmpty() )
1530 featureBBoxInitialized =
true;
1545 if ( mWmsParameters.
infoFormat() == QgsWmsParameters::Format::GML )
1550 QDomElement elem = createFeatureGML(
1552 #ifdef HAVE_SERVER_PYTHON_PLUGINS
1556 QDomElement featureMemberElem = infoDocument.createElement( QStringLiteral(
"gml:featureMember" ) );
1557 featureMemberElem.appendChild( elem );
1558 layerElement.appendChild( featureMemberElem );
1563 QDomElement featureElement = infoDocument.createElement( QStringLiteral(
"Feature" ) );
1565 layerElement.appendChild( featureElement );
1569 for (
int i = 0; i < featureAttributes.count(); ++i )
1572 if ( excludedAttributes.contains( fields.at( i ).name() ) )
1576 #ifdef HAVE_SERVER_PYTHON_PLUGINS
1578 if ( !attributes.contains( fields.at( i ).name() ) )
1587 QDomElement attributeElement = infoDocument.createElement( QStringLiteral(
"Attribute" ) );
1588 attributeElement.setAttribute( QStringLiteral(
"name" ), attributeName );
1590 attributeElement.setAttribute( QStringLiteral(
"value" ),
1592 replaceValueMapAndRelation(
1594 featureAttributes[i] ),
1597 featureElement.appendChild( attributeElement );
1602 if ( !mapTip.isEmpty() && mWmsParameters.
withMapTip() )
1604 QDomElement maptipElem = infoDocument.createElement( QStringLiteral(
"Attribute" ) );
1605 maptipElem.setAttribute( QStringLiteral(
"name" ), QStringLiteral(
"maptip" ) );
1607 featureElement.appendChild( maptipElem );
1614 QDomElement bBoxElem = infoDocument.createElement( QStringLiteral(
"BoundingBox" ) );
1615 bBoxElem.setAttribute( version == QLatin1String(
"1.1.1" ) ?
"SRS" :
"CRS",
outputCrs.
authid() );
1620 featureElement.appendChild( bBoxElem );
1636 if ( segmentizeWktGeometry )
1644 geom.
set( segmentizedGeom );
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 );
1659 r2->stopRender( renderContext );
1665 bool QgsRenderer::featureInfoFromRasterLayer(
QgsRasterLayer *layer,
1668 QDomDocument &infoDocument,
1669 QDomElement &layerElement,
1670 const QString &version )
const
1689 QgsRaster::IdentifyFormat::IdentifyFormatFeature :
1690 QgsRaster::IdentifyFormat::IdentifyFormatValue };
1702 .arg( layer->
name() ) );
1711 if ( !identifyResult.
isValid() )
1714 QMap<int, QVariant> attributes = identifyResult.
results();
1716 if ( mWmsParameters.
infoFormat() == QgsWmsParameters::Format::GML )
1728 for (
auto it = attributes.constBegin(); it != attributes.constEnd(); ++it )
1731 feature.
setAttribute( index++, QString::number( it.value().toDouble() ) );
1734 QDomElement elem = createFeatureGML(
1735 &feature,
nullptr, infoDocument, layerCrs, mapSettings,
typeName,
false, gmlVersion,
nullptr );
1736 layerElement.appendChild( elem );
1740 const auto values = identifyResult.
results();
1741 for (
auto it = values.constBegin(); it != values.constEnd(); ++it )
1743 QVariant value = it.value();
1744 if ( value.type() == QVariant::Bool && !value.toBool() )
1750 if ( value.type() == QVariant::String )
1761 for (
const QgsFeature &feature : storeFeatures )
1763 QDomElement elem = createFeatureGML(
1764 &feature,
nullptr, infoDocument, layerCrs, mapSettings,
typeName,
false, gmlVersion,
nullptr );
1765 layerElement.appendChild( elem );
1775 for (
auto it = attributes.constBegin(); it != attributes.constEnd(); ++it )
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 );
1785 const auto values = identifyResult.
results();
1786 for (
auto it = values.constBegin(); it != values.constEnd(); ++it )
1788 QVariant value = it.value();
1789 if ( value.type() == QVariant::Bool && !value.toBool() )
1795 if ( value.type() == QVariant::String )
1805 for (
const QgsFeature &feature : storeFeatures )
1807 for (
const auto &fld : feature.
fields() )
1809 const auto val { feature.
attribute( fld.name() )};
1810 if ( val.isValid() )
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 );
1826 bool QgsRenderer::testFilterStringSafety(
const QString &filter )
const
1829 if ( filter.contains( QLatin1String(
";" ) ) )
1834 QStringList tokens = filter.split(
' ', QString::SkipEmptyParts );
1835 groupStringList( tokens, QStringLiteral(
"'" ) );
1836 groupStringList( tokens, QStringLiteral(
"\"" ) );
1838 for (
auto tokenIt = tokens.constBegin() ; tokenIt != tokens.constEnd(); ++tokenIt )
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 )
1867 tokenIt->toDouble( &isNumeric );
1876 if ( *tokenIt == QLatin1String(
"''" ) )
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(
'\'' ) )
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(
'"' ) )
1907 void QgsRenderer::groupStringList( QStringList &list,
const QString &groupString )
1910 bool groupActive =
false;
1911 int startGroup = -1;
1912 QString concatString;
1914 for (
int i = 0; i < list.size(); ++i )
1916 QString &str = list[i];
1917 if ( str.startsWith( groupString ) )
1921 concatString.clear();
1926 if ( i != startGroup )
1928 concatString.append(
" " );
1930 concatString.append( str );
1933 if ( str.endsWith( groupString ) )
1936 groupActive =
false;
1938 if ( startGroup != -1 )
1940 list[startGroup] = concatString;
1941 for (
int j = startGroup + 1; j <= endGroup; ++j )
1943 list.removeAt( startGroup + 1 );
1948 concatString.clear();
1954 void QgsRenderer::convertFeatureInfoToSia2045( QDomDocument &doc )
const
1956 QDomDocument SIAInfoDoc;
1957 QDomElement infoDocElement = doc.documentElement();
1958 QDomElement SIAInfoDocElement = SIAInfoDoc.importNode( infoDocElement,
false ).toElement();
1959 SIAInfoDoc.appendChild( SIAInfoDocElement );
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 )
1969 currentLayerElem = layerNodeList.at( i ).toElement();
1970 currentLayerName = currentLayerElem.attribute( QStringLiteral(
"name" ) );
1972 QDomElement currentFeatureElem;
1974 QDomNodeList featureList = currentLayerElem.elementsByTagName( QStringLiteral(
"Feature" ) );
1975 if ( featureList.isEmpty() )
1978 QDomNodeList attributeList = currentLayerElem.elementsByTagName( QStringLiteral(
"Attribute" ) );
1979 QDomElement rasterLayerElem;
1980 if ( !attributeList.isEmpty() )
1982 rasterLayerElem = SIAInfoDoc.createElement( currentLayerName );
1984 for (
int j = 0; j < attributeList.size(); ++j )
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 );
1994 if ( !attributeList.isEmpty() )
1996 SIAInfoDocElement.appendChild( rasterLayerElem );
2002 QSet<QString> layerPropertyAttributes;
2003 QString currentLayerId = currentLayerElem.attribute( QStringLiteral(
"id" ) );
2004 if ( !currentLayerId.isEmpty() )
2009 QString WMSPropertyAttributesString = currentLayer->
customProperty( QStringLiteral(
"WMSPropertyAttributes" ) ).toString();
2010 if ( !WMSPropertyAttributesString.isEmpty() )
2012 QStringList propertyList = WMSPropertyAttributesString.split( QStringLiteral(
"//" ) );
2013 for (
auto propertyIt = propertyList.constBegin() ; propertyIt != propertyList.constEnd(); ++propertyIt )
2015 layerPropertyAttributes.insert( *propertyIt );
2021 QDomElement propertyRefChild;
2022 for (
int j = 0; j < featureList.size(); ++j )
2024 QDomElement SIAFeatureElem = SIAInfoDoc.createElement( currentLayerName );
2025 currentFeatureElem = featureList.at( j ).toElement();
2026 QDomNodeList attributeList = currentFeatureElem.elementsByTagName( QStringLiteral(
"Attribute" ) );
2028 for (
int k = 0; k < attributeList.size(); ++k )
2030 currentAttributeElem = attributeList.at( k ).toElement();
2031 currentAttributeName = currentAttributeElem.attribute( QStringLiteral(
"name" ) );
2032 currentAttributeValue = currentAttributeElem.attribute( QStringLiteral(
"value" ) );
2033 if ( layerPropertyAttributes.contains( currentAttributeName ) )
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() )
2046 SIAFeatureElem.insertBefore( propertyElem, QDomNode() );
2047 propertyRefChild = propertyElem;
2051 SIAFeatureElem.insertAfter( propertyElem, propertyRefChild );
2056 QDomElement SIAAttributeElem = SIAInfoDoc.createElement( currentAttributeName );
2057 QDomText SIAAttributeText = SIAInfoDoc.createTextNode( currentAttributeValue );
2058 SIAAttributeElem.appendChild( SIAAttributeText );
2059 SIAFeatureElem.appendChild( SIAAttributeElem );
2062 SIAInfoDocElement.appendChild( SIAFeatureElem );
2069 QByteArray QgsRenderer::convertFeatureInfoToHtml(
const QDomDocument &doc )
const
2071 QString featureInfoString;
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" );
2080 featureInfoString.append(
"<BODY>\n" );
2082 QDomNodeList layerList = doc.elementsByTagName( QStringLiteral(
"Layer" ) );
2085 for (
int i = 0; i < layerList.size(); ++i )
2087 QDomElement layerElem = layerList.at( i ).toElement();
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>" );
2094 QDomNodeList featureNodeList = layerElem.elementsByTagName( QStringLiteral(
"Feature" ) );
2095 QDomElement currentFeatureElement;
2097 if ( !featureNodeList.isEmpty() )
2099 for (
int j = 0; j < featureNodeList.size(); ++j )
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" ) ) +
2107 QDomNodeList attributeNodeList = featureElement.elementsByTagName( QStringLiteral(
"Attribute" ) );
2108 for (
int k = 0; k < attributeNodeList.size(); ++k )
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" );
2115 featureInfoString.append(
"</TABLE>\n</BR>\n" );
2120 QDomNodeList attributeNodeList = layerElem.elementsByTagName( QStringLiteral(
"Attribute" ) );
2121 for (
int j = 0; j < attributeNodeList.size(); ++j )
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" );
2129 featureInfoString.append(
"</TABLE>\n<BR></BR>\n" );
2133 featureInfoString.append(
"</BODY>\n" );
2135 return featureInfoString.toUtf8();
2138 QByteArray QgsRenderer::convertFeatureInfoToText(
const QDomDocument &doc )
const
2140 QString featureInfoString;
2143 featureInfoString.append(
"GetFeatureInfo results\n" );
2144 featureInfoString.append(
"\n" );
2146 QDomNodeList layerList = doc.elementsByTagName( QStringLiteral(
"Layer" ) );
2149 for (
int i = 0; i < layerList.size(); ++i )
2151 QDomElement layerElem = layerList.at( i ).toElement();
2153 featureInfoString.append(
"Layer '" + layerElem.attribute( QStringLiteral(
"name" ) ) +
"'\n" );
2156 QDomNodeList featureNodeList = layerElem.elementsByTagName( QStringLiteral(
"Feature" ) );
2157 QDomElement currentFeatureElement;
2159 if ( !featureNodeList.isEmpty() )
2161 for (
int j = 0; j < featureNodeList.size(); ++j )
2163 QDomElement featureElement = featureNodeList.at( j ).toElement();
2164 featureInfoString.append(
"Feature " + featureElement.attribute( QStringLiteral(
"id" ) ) +
"\n" );
2167 QDomNodeList attributeNodeList = featureElement.elementsByTagName( QStringLiteral(
"Attribute" ) );
2168 for (
int k = 0; k < attributeNodeList.size(); ++k )
2170 QDomElement attributeElement = attributeNodeList.at( k ).toElement();
2171 featureInfoString.append( attributeElement.attribute( QStringLiteral(
"name" ) ) +
" = '" +
2172 attributeElement.attribute( QStringLiteral(
"value" ) ) +
"'\n" );
2178 QDomNodeList attributeNodeList = layerElem.elementsByTagName( QStringLiteral(
"Attribute" ) );
2179 for (
int j = 0; j < attributeNodeList.size(); ++j )
2181 QDomElement attributeElement = attributeNodeList.at( j ).toElement();
2182 featureInfoString.append( attributeElement.attribute( QStringLiteral(
"name" ) ) +
" = '" +
2183 attributeElement.attribute( QStringLiteral(
"value" ) ) +
"'\n" );
2187 featureInfoString.append(
"\n" );
2190 return featureInfoString.toUtf8();
2193 QByteArray QgsRenderer::convertFeatureInfoToJson(
const QList<QgsMapLayer *> &layers,
const QDomDocument &doc )
const
2197 {
"type",
"FeatureCollection" },
2198 {
"features", json::array() },
2202 const QDomNodeList layerList = doc.elementsByTagName( QStringLiteral(
"Layer" ) );
2203 for (
int i = 0; i < layerList.size(); ++i )
2205 const QDomElement layerElem = layerList.at( i ).toElement();
2206 const QString layerName = layerElem.attribute( QStringLiteral(
"name" ) );
2211 if ( mContext.
layerNickname( *l ).compare( layerName ) == 0 )
2227 const QDomNodeList featuresNode = layerElem.elementsByTagName( QStringLiteral(
"Feature" ) );
2228 if ( featuresNode.isEmpty() )
2231 for (
int j = 0; j < featuresNode.size(); ++j )
2233 const QDomElement featureNode = featuresNode.at( j ).toElement();
2234 const QgsFeatureId fid = featureNode.attribute( QStringLiteral(
"id" ) ).toLongLong();
2240 const QDomNodeList attrs = featureNode.elementsByTagName(
"Attribute" );
2241 for (
int k = 0; k < attrs.count(); k++ )
2243 const QDomElement elm = attrs.at( k ).toElement();
2244 if ( elm.attribute( QStringLiteral(
"name" ) ).compare(
"geometry" ) == 0 )
2246 wkt = elm.attribute(
"value" );
2251 if ( ! wkt.isEmpty() )
2257 features << feature;
2260 if ( !attributes.isEmpty() )
2263 const QDomNodeList attributesNode = featureNode.elementsByTagName( QStringLiteral(
"Attribute" ) );
2264 for (
int k = 0; k < attributesNode.size(); ++k )
2266 const QDomElement attributeElement = attributesNode.at( k ).toElement();
2267 const QString fieldName = attributeElement.
attribute( QStringLiteral(
"name" ) );
2269 attributes << feature.fieldNameIndex( fieldName );
2275 exporter.setAttributeDisplayName(
true );
2276 exporter.setAttributes( attributes );
2277 exporter.setIncludeGeometry( withGeometry );
2278 exporter.setTransformGeometries(
false );
2280 for (
const auto &feature : qgis::as_const( features ) )
2282 const QString
id = QStringLiteral(
"%1.%2" ).arg( layerName ).arg( feature.id() );
2283 json[
"features"].push_back( exporter.exportFeatureToJsonObject( feature, QVariantMap(),
id ) );
2288 auto properties = json::object();
2289 const QDomNodeList attributesNode = layerElem.elementsByTagName( QStringLiteral(
"Attribute" ) );
2290 for (
int j = 0; j < attributesNode.size(); ++j )
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();
2298 json[
"features"].push_back(
2300 {
"type",
"Feature" },
2301 {
"id", layerName.toStdString() },
2302 {
"properties", properties }
2308 return QByteArray::fromStdString( json.dump( 2 ) );
2310 return QByteArray::fromStdString( json.dump() );
2314 QDomElement QgsRenderer::createFeatureGML(
2323 QStringList *attributes )
const
2326 QDomElement typeNameElement = doc.createElement(
"qgs:" +
typeName );
2327 typeNameElement.setAttribute( QStringLiteral(
"fid" ),
typeName +
"." + QString::number( feat->
id() ) );
2330 if ( layer && layer->
crs() !=
crs )
2356 box = transformedBox;
2364 QDomElement bbElem = doc.createElement( QStringLiteral(
"gml:boundedBy" ) );
2365 QDomElement boxElem;
2377 boxElem.setAttribute( QStringLiteral(
"srsName" ),
crs.
authid() );
2379 bbElem.appendChild( boxElem );
2380 typeNameElement.appendChild( bbElem );
2392 QDomElement geomElem = doc.createElement( QStringLiteral(
"qgs:geometry" ) );
2393 QDomElement gmlElem;
2403 if ( !gmlElem.isNull() )
2407 gmlElem.setAttribute( QStringLiteral(
"srsName" ),
crs.
authid() );
2409 geomElem.appendChild( gmlElem );
2410 typeNameElement.appendChild( geomElem );
2417 for (
int i = 0; i < fields.
count(); ++i )
2419 QString attributeName = fields.
at( i ).
name();
2426 if ( attributes && !attributes->contains( attributeName ) )
2431 QDomElement fieldElem = doc.createElement(
"qgs:" + attributeName.replace(
' ',
'_' ) );
2432 QString fieldTextString = featureAttributes.at( i ).toString();
2437 QDomText fieldText = doc.createTextNode( fieldTextString );
2438 fieldElem.appendChild( fieldText );
2439 typeNameElement.appendChild( fieldElem );
2447 if ( !mapTip.isEmpty() && mWmsParameters.
withMapTip() )
2450 QDomElement fieldElem = doc.createElement( QStringLiteral(
"qgs:maptip" ) );
2451 QDomText maptipText = doc.createTextNode( fieldTextString );
2452 fieldElem.appendChild( maptipText );
2453 typeNameElement.appendChild( fieldElem );
2457 return typeNameElement;
2460 QString QgsRenderer::replaceValueMapAndRelation(
QgsVectorLayer *vl,
int idx,
const QVariant &attributeVal )
2464 QString value( fieldFormatter->
representValue( vl, idx, setup.
config(), QVariant(), attributeVal ) );
2466 if ( setup.
config().value( QStringLiteral(
"AllowMulti" ) ).toBool() && value.startsWith( QLatin1String(
"{" ) ) && value.endsWith( QLatin1String(
"}" ) ) )
2468 value = value.mid( 1, value.size() - 2 );
2480 double mapUnitTolerance = 0.0;
2490 mapUnitTolerance = mapSettings.
extent().
width() / 400.0;
2502 mapUnitTolerance = mapSettings.
extent().
width() / 200.0;
2514 mapUnitTolerance = mapSettings.
extent().
width() / 100.0;
2518 QgsRectangle mapRectangle( infoPoint.
x() - mapUnitTolerance, infoPoint.
y() - mapUnitTolerance,
2519 infoPoint.
x() + mapUnitTolerance, infoPoint.
y() + mapUnitTolerance );
2523 QList<QgsMapLayer *> QgsRenderer::highlightLayers( QList<QgsWmsParametersHighlightLayer> params )
2525 QList<QgsMapLayer *> highlightLayers;
2528 QString
crs = mWmsParameters.
crs();
2529 for (
const QgsWmsParametersHighlightLayer ¶m : params )
2532 QDomDocument sldDoc;
2533 if ( !sldDoc.setContent( param.mSld,
true ) )
2540 std::unique_ptr<QgsFeatureRenderer> renderer;
2541 QDomElement el = sldDoc.documentElement();
2552 if ( ! param.mLabel.isEmpty() )
2554 url +=
"&field=label:string";
2559 std::unique_ptr<QgsVectorLayer> layer = qgis::make_unique<QgsVectorLayer>( url, param.mName, QLatin1String(
"memory" ), options );
2560 if ( !layer->isValid() )
2567 if ( ! param.mLabel.isEmpty() )
2569 fet.setAttribute( 0, param.mLabel );
2578 switch ( param.mGeom.type() )
2583 palSettings.
dist = 2;
2594 QVariant x( pt.
x() );
2598 QVariant y( pt.
y() );
2602 QVariant hali(
"Center" );
2606 QVariant vali(
"Half" );
2613 palSettings.
dist = 2;
2622 if ( param.mColor.isValid() )
2624 textFormat.
setColor( param.mColor );
2627 if ( param.mSize > 0 )
2629 textFormat.
setSize( param.mSize );
2637 if ( ! param.mFont.isEmpty() )
2639 textFormat.
setFont( param.mFont );
2642 if ( param.mBufferColor.isValid() )
2644 bufferSettings.
setColor( param.mBufferColor );
2647 if ( param.mBufferSize > 0 )
2650 bufferSettings.
setSize(
static_cast<double>( param.mBufferSize ) );
2657 layer->setLabeling( simpleLabeling );
2658 layer->setLabelsEnabled(
true );
2660 fet.setGeometry( param.mGeom );
2664 layer->setRenderer( renderer.release() );
2667 if ( layer->isValid() )
2669 highlightLayers.append( layer.release() );
2673 mTemporaryLayers.append( highlightLayers );
2674 return highlightLayers;
2677 QList<QgsMapLayer *> QgsRenderer::externalLayers(
const QList<QgsWmsParametersExternalLayer> ¶ms )
2679 QList<QgsMapLayer *> layers;
2681 for (
const QgsWmsParametersExternalLayer ¶m : params )
2683 std::unique_ptr<QgsMapLayer> layer = qgis::make_unique< QgsRasterLayer >( param.mUri, param.mName, QStringLiteral(
"wms" ) );
2685 if ( layer->isValid() )
2688 mTemporaryLayers.append( layer.release() );
2689 layers << mTemporaryLayers.last();
2696 void QgsRenderer::removeTemporaryLayers()
2698 qDeleteAll( mTemporaryLayers );
2699 mTemporaryLayers.clear();
2702 QPainter *QgsRenderer::layersRendering(
const QgsMapSettings &mapSettings, QImage &image )
const
2704 QPainter *painter =
nullptr;
2708 #ifdef HAVE_SERVER_PYTHON_PLUGINS
2709 mContext.accessControl()->resolveFilterFeatures( mapSettings.
layers() );
2713 renderJob.render( mapSettings, &image );
2714 painter = renderJob.takePainter();
2716 if ( !renderJob.errors().isEmpty() )
2718 QString layerWMSName;
2719 QString firstErrorLayerId = renderJob.errors().at( 0 ).layerID;
2726 throw QgsException( QStringLiteral(
"Map rendering error in layer '%1'" ).arg( layerWMSName ) );
2732 void QgsRenderer::setLayerOpacity(
QgsMapLayer *layer,
int opacity )
const
2734 if ( opacity >= 0 && opacity <= 255 )
2736 switch ( layer->
type() )
2749 rasterRenderer->
setOpacity( opacity / 255. );
2761 void QgsRenderer::setLayerFilter(
QgsMapLayer *layer,
const QList<QgsWmsParametersFilter> &filters )
2765 QgsVectorLayer *filteredLayer = qobject_cast<QgsVectorLayer *>( layer );
2766 QStringList expList;
2767 for (
const QgsWmsParametersFilter &filter : filters )
2772 QDomDocument filterXml;
2774 if ( !filterXml.setContent( filter.mFilter,
true, &errorMsg ) )
2777 QStringLiteral(
"Filter string rejected. Error message: %1. The XML string was: %2" ).arg( errorMsg, filter.mFilter ) );
2779 QDomElement filterElem = filterXml.firstChildElement();
2784 expList << filterExp->dump();
2790 if ( !testFilterStringSafety( filter.mFilter ) )
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(
2802 QString newSubsetString = filter.mFilter;
2805 newSubsetString.prepend(
") AND (" );
2806 newSubsetString.append(
")" );
2807 newSubsetString.prepend( filteredLayer->
subsetString() );
2808 newSubsetString.prepend(
"(" );
2814 expList.append( dimensionFilter( filteredLayer ) );
2818 if ( expList.size() == 1 )
2822 else if ( expList.size() > 1 )
2824 exp = QStringLiteral(
"( %1 )" ).arg( expList.join( QStringLiteral(
" ) AND ( " ) ) );
2826 if ( !exp.isEmpty() )
2828 std::unique_ptr<QgsExpression> expression(
new QgsExpression( exp ) );
2831 mFeatureFilter.
setFilter( filteredLayer, *expression );
2837 QStringList QgsRenderer::dimensionFilter(
QgsVectorLayer *layer )
const
2839 QStringList expList;
2842 if ( wmsDims.isEmpty() )
2852 if ( fieldIndex == -1 )
2857 int endFieldIndex = -1;
2858 if ( !dim.endFieldName.isEmpty() )
2860 endFieldIndex = layer->
fields().
indexOf( dim.endFieldName );
2861 if ( endFieldIndex == -1 )
2867 if ( !dimParamValues.contains( dim.name.toUpper() ) )
2877 defValue = dim.referenceValue;
2882 QSet<QVariant> uniqueValues = layer->
uniqueValues( fieldIndex );
2883 if ( endFieldIndex != -1 )
2885 uniqueValues.unite( layer->
uniqueValues( endFieldIndex ) );
2888 QList<QVariant> values = qgis::setToList( uniqueValues );
2889 std::sort( values.begin(), values.end() );
2892 defValue = values.first();
2896 defValue = values.last();
2900 if ( endFieldIndex == -1 )
2906 QStringList expElems;
2911 expList << expElems.join(
' ' );
2919 QString dimParamValue = dimParamValues[dim.name.toUpper()];
2921 QStringList dimExplist;
2923 QStringList dimValues = dimParamValue.split(
',' );
2924 for (
int i = 0; i < dimValues.size(); ++i )
2926 QString dimValue = dimValues[i];
2928 if ( dimValue.size() > 1 )
2930 dimValue = dimValue.trimmed();
2933 if ( dimValue.contains(
'/' ) )
2935 QStringList rangeValues = dimValue.split(
'/' );
2937 if ( rangeValues.size() != 2 )
2942 QVariant rangeMin = QVariant( rangeValues[0] );
2943 QVariant rangeMax = QVariant( rangeValues[1] );
2954 QStringList expElems;
2955 if ( endFieldIndex == -1 )
2975 << QStringLiteral(
")" );
2977 dimExplist << expElems.join(
' ' );
2981 QVariant dimVariant = QVariant( dimValue );
2987 if ( endFieldIndex == -1 )
2996 QStringList expElems;
3001 dimExplist << expElems.join(
' ' );
3006 if ( dimExplist.size() == 1 )
3008 expList << dimExplist;
3010 else if ( dimExplist.size() > 1 )
3012 expList << QStringLiteral(
"( %1 )" ).arg( dimExplist.join( QStringLiteral(
" ) OR ( " ) ) );
3019 void QgsRenderer::setLayerSelection(
QgsMapLayer *layer,
const QStringList &fids )
const
3025 for (
const QString &
id : fids )
3035 void QgsRenderer::setLayerAccessControlFilter(
QgsMapLayer *layer )
const
3037 #ifdef HAVE_SERVER_PYTHON_PLUGINS
3055 void QgsRenderer::annotationsRendering( QPainter *painter )
const
3058 const QList< QgsAnnotation * > annotations = annotationManager->
annotations();
3064 if ( !annotation || !annotation->isVisible() )
3067 annotation->render( renderContext );
3071 QImage *QgsRenderer::scaleImage(
const QImage *image )
const
3076 QImage *scaledImage =
nullptr;
3077 const int width = mWmsParameters.
widthAsInt();
3079 if ( width != image->width() || height != image->height() )
3081 scaledImage =
new QImage( image->scaled( width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ) );
3087 void QgsRenderer::handlePrintErrors(
const QgsLayout *layout )
const
3093 QList< QgsLayoutItemMap * > mapList;
3096 QList< QgsLayoutItemMap * >::const_iterator mapIt = mapList.constBegin();
3097 for ( ; mapIt != mapList.constEnd(); ++mapIt )
3099 if ( !( *mapIt )->renderingErrors().isEmpty() )
3111 for (
auto layer : layers )
3113 const QgsWmsParametersLayer param = mContext.
parameters( *layer );
3122 setLayerSld( layer, mContext.
sld( *layer ) );
3126 setLayerStyle( layer, mContext.
style( *layer ) );
3131 setLayerOpacity( layer, param.mOpacity );
3136 setLayerFilter( layer, param.mFilter );
3141 setLayerSelection( layer, param.mSelection );
3146 updateExtent( layer, *settings );
3151 setLayerAccessControlFilter( layer );
3166 void QgsRenderer::setLayerStyle(
QgsMapLayer *layer,
const QString &style )
const
3168 if ( style.isEmpty() )
3177 QStringLiteral(
"Style '%1' does not exist for layer '%2'" ).arg( style, layer->
name() ) );
3181 void QgsRenderer::setLayerSld(
QgsMapLayer *layer,
const QDomElement &sld )
const
3193 if ( !mWmsParameters.
bbox().isEmpty() )
3197 std::unique_ptr<QImage> tmp( createImage( mContext.
mapSize(
false ) ) );
3198 configureMapSettings( tmp.get(), mapSettings );