70 #include <QStringList>
71 #include <QTemporaryFile>
74 #include <nlohmann/json.hpp>
104 mWmsParameters.
dump();
109 removeTemporaryLayers();
115 std::unique_ptr<QgsWmsRestorer> restorer;
127 std::unique_ptr<QImage> image;
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() );
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;
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;
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() )
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 ) == QLatin1String(
"*" ) )
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() )
575 c->removeLayoutItem( map );
593 if ( cMapParams.
mScale > 0 )
595 map->setScale(
static_cast<double>( cMapParams.
mScale ) );
601 map->setMapRotation( cMapParams.
mRotation );
605 if ( !map->keepLayerSet() )
607 if ( cMapParams.
mLayers.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 );
652 std::reverse( layerSet.begin(), layerSet.end() );
653 map->setLayers( layerSet );
655 map->setKeepLayerSet(
true );
661 map->grid()->setIntervalX(
static_cast<double>( cMapParams.
mGridX ) );
662 map->grid()->setIntervalY(
static_cast<double>( cMapParams.
mGridY ) );
667 QList<QgsLayoutItemLabel *> labels;
669 for (
const auto &label : qgis::as_const( labels ) )
672 const QString labelId = label->
id();
673 const QString labelParam = mWmsParameters.
layoutParameter( labelId, ok );
678 if ( labelParam.isEmpty() )
682 c->removeItem( label );
687 label->setText( labelParam );
691 QList<QgsLayoutItemHtml *> htmls;
693 for (
const auto &html : qgis::as_const( htmls ) )
695 if ( html->frameCount() == 0 )
700 const QString htmlId = htmlFrame->
id();
713 c->removeMultiFrame( html );
719 html->setUrl( newUrl );
725 QList<QgsLayoutItemLegend *> legends;
727 for (
const auto &legend : qgis::as_const( legends ) )
729 if ( legend->autoUpdateModel() )
739 legend->setAutoUpdateModel(
false );
743 QStringList layerSet;
744 const QList<QgsMapLayer *> layerList( map->
layers() );
745 for (
const auto &layer : layerList )
746 layerSet << layer->id();
758 for (
const auto &layerId : layerIds )
765 if ( !layerSet.contains( layerId ) )
767 qobject_cast<QgsLayerTreeGroup *>( nodeLayer->
parent() )->removeChildNode( nodeLayer );
774 qobject_cast<QgsLayerTreeGroup *>( nodeLayer->
parent() )->removeChildNode( nodeLayer );
790 QStringLiteral(
"The requested map size is too large" ) );
794 std::unique_ptr<QgsWmsRestorer> restorer;
805 std::unique_ptr<QPainter> painter;
806 std::unique_ptr<QImage> image( createImage( mContext.
mapSize() ) );
809 configureMapSettings( image.get(), mapSettings );
815 painter.reset( layersRendering( mapSettings, *image ) );
818 annotationsRendering( painter.get() );
824 QImage *scaledImage = scaleImage( image.get() );
826 image.reset( scaledImage );
829 return image.release();
835 std::unique_ptr<QgsWmsRestorer> restorer;
844 QList< QgsDxfExport::DxfLayer > dxfLayers;
856 int layerAttribute = -1;
857 if ( attributes.size() > layerIdx )
866 std::unique_ptr<QgsDxfExport> dxf = qgis::make_unique<QgsDxfExport>();
868 dxf->addLayers( dxfLayers );
870 dxf->setSymbologyExport( mWmsParameters.
dxfMode() );
871 if ( mWmsParameters.
dxfFormatOptions().contains( QgsWmsParameters::DxfFormatOption::SCALE ) )
873 dxf->setSymbologyScale( mWmsParameters.
dxfScale() );
876 dxf->setForce2d( mWmsParameters.
isForce2D() );
877 QgsDxfExport::Flags flags;
878 if ( mWmsParameters.
noMText() )
879 flags.setFlag( QgsDxfExport::Flag::FlagNoMText );
881 dxf->setFlags( flags );
889 if ( i < 0 || i > mapSettings.
outputSize().width() )
897 if ( j < 0 || j > mapSettings.
outputSize().height() )
922 const bool ijDefined = !mWmsParameters.
i().isEmpty() && !mWmsParameters.
j().isEmpty();
923 const bool xyDefined = !mWmsParameters.
x().isEmpty() && !mWmsParameters.
y().isEmpty();
924 const bool filtersDefined = !mWmsParameters.
filters().isEmpty();
925 const bool filterGeomDefined = !mWmsParameters.
filterGeom().isEmpty();
927 if ( !ijDefined && !xyDefined && !filtersDefined && !filterGeomDefined )
931 if ( mWmsParameters.
j().isEmpty() )
938 if ( infoFormat == QgsWmsParameters::Format::NONE )
945 std::unique_ptr<QImage> outputImage( createImage( mContext.
mapSize() ) );
948 std::unique_ptr<QgsWmsRestorer> restorer;
953 bool mandatoryCrsParam =
true;
954 if ( filtersDefined && !ijDefined && !xyDefined && mWmsParameters.
crs().isEmpty() )
956 mandatoryCrsParam =
false;
962 configureMapSettings( outputImage.get(), mapSettings, mandatoryCrsParam );
978 QDomDocument result = featureInfoDocument( layers, mapSettings, outputImage.get(), version );
982 if ( infoFormat == QgsWmsParameters::Format::TEXT )
983 ba = convertFeatureInfoToText( result );
984 else if ( infoFormat == QgsWmsParameters::Format::HTML )
985 ba = convertFeatureInfoToHtml( result );
986 else if ( infoFormat == QgsWmsParameters::Format::JSON )
987 ba = convertFeatureInfoToJson( layers, result );
989 ba = result.toByteArray();
994 QImage *QgsRenderer::createImage(
const QSize &size )
const
996 std::unique_ptr<QImage> image;
1004 image = qgis::make_unique<QImage>( size, QImage::Format_ARGB32_Premultiplied );
1009 image = qgis::make_unique<QImage>( size, QImage::Format_RGB32 );
1014 if ( image->isNull() )
1016 throw QgsException( QStringLiteral(
"createImage: image could not be created, check for out of memory conditions" ) );
1019 const int dpm =
static_cast<int>( mContext.
dotsPerMm() * 1000.0 );
1020 image->setDotsPerMeterX( dpm );
1021 image->setDotsPerMeterY( dpm );
1023 return image.release();
1026 void QgsRenderer::configureMapSettings(
const QPaintDevice *paintDevice,
QgsMapSettings &mapSettings,
bool mandatoryCrsParam )
const
1030 throw QgsException( QStringLiteral(
"configureMapSettings: no paint device" ) );
1033 mapSettings.
setOutputSize( QSize( paintDevice->width(), paintDevice->height() ) );
1034 mapSettings.
setOutputDpi( paintDevice->logicalDpiX() );
1038 if ( !mWmsParameters.
bbox().isEmpty() && mapExtent.
isEmpty() )
1044 QString
crs = mWmsParameters.
crs();
1045 if (
crs.compare(
"CRS:84", Qt::CaseInsensitive ) == 0 )
1047 crs = QString(
"EPSG:4326" );
1050 else if (
crs.isEmpty() && !mandatoryCrsParam )
1052 crs = QString(
"EPSG:4326" );
1062 QgsWmsParameter parameter;
1104 else if ( backgroundColor.isValid() )
1124 QDomDocument QgsRenderer::featureInfoDocument( QList<QgsMapLayer *> &layers,
const QgsMapSettings &mapSettings,
1125 const QImage *outputImage,
const QString &version )
const
1129 bool ijDefined = ( !mWmsParameters.
i().isEmpty() && !mWmsParameters.
j().isEmpty() );
1131 bool xyDefined = ( !mWmsParameters.
x().isEmpty() && !mWmsParameters.
y().isEmpty() );
1133 bool filtersDefined = !mWmsParameters.
filters().isEmpty();
1135 bool filterGeomDefined = !mWmsParameters.
filterGeom().isEmpty();
1138 if ( featureCount < 1 )
1143 int i = mWmsParameters.
iAsInt();
1144 int j = mWmsParameters.
jAsInt();
1145 if ( xyDefined && !ijDefined )
1147 i = mWmsParameters.
xAsInt();
1148 j = mWmsParameters.
yAsInt();
1152 if ( ( i != -1 && j != -1 && width != 0 && height != 0 ) && ( width != outputImage->width() || height != outputImage->height() ) )
1154 i *= ( outputImage->width() /
static_cast<double>( width ) );
1155 j *= ( outputImage->height() /
static_cast<double>( height ) );
1159 std::unique_ptr<QgsRectangle> featuresRect;
1160 std::unique_ptr<QgsGeometry> filterGeom;
1161 std::unique_ptr<QgsPointXY> infoPoint;
1163 if ( i != -1 && j != -1 )
1166 infoPointToMapCoordinates( i, j, infoPoint.get(), mapSettings );
1168 else if ( filtersDefined )
1172 else if ( filterGeomDefined )
1177 QDomDocument result;
1179 QDomElement getFeatureInfoElement;
1181 if ( infoFormat == QgsWmsParameters::Format::GML )
1183 getFeatureInfoElement = result.createElement( QStringLiteral(
"wfs:FeatureCollection" ) );
1184 getFeatureInfoElement.setAttribute( QStringLiteral(
"xmlns:wfs" ), QStringLiteral(
"http://www.opengis.net/wfs" ) );
1185 getFeatureInfoElement.setAttribute( QStringLiteral(
"xmlns:ogc" ), QStringLiteral(
"http://www.opengis.net/ogc" ) );
1186 getFeatureInfoElement.setAttribute( QStringLiteral(
"xmlns:gml" ), QStringLiteral(
"http://www.opengis.net/gml" ) );
1187 getFeatureInfoElement.setAttribute( QStringLiteral(
"xmlns:ows" ), QStringLiteral(
"http://www.opengis.net/ows" ) );
1188 getFeatureInfoElement.setAttribute( QStringLiteral(
"xmlns:xlink" ), QStringLiteral(
"http://www.w3.org/1999/xlink" ) );
1189 getFeatureInfoElement.setAttribute( QStringLiteral(
"xmlns:qgs" ), QStringLiteral(
"http://qgis.org/gml" ) );
1190 getFeatureInfoElement.setAttribute( QStringLiteral(
"xmlns:xsi" ), QStringLiteral(
"http://www.w3.org/2001/XMLSchema-instance" ) );
1191 getFeatureInfoElement.setAttribute( QStringLiteral(
"xsi:schemaLocation" ), QStringLiteral(
"http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd http://qgis.org/gml" ) );
1196 if ( featureInfoElemName.isEmpty() )
1198 featureInfoElemName = QStringLiteral(
"GetFeatureInfoResponse" );
1201 if ( featureInfoElemNs.isEmpty() )
1203 getFeatureInfoElement = result.createElement( featureInfoElemName );
1207 getFeatureInfoElement = result.createElementNS( featureInfoElemNs, featureInfoElemName );
1211 if ( !featureInfoSchema.isEmpty() )
1213 getFeatureInfoElement.setAttribute( QStringLiteral(
"xmlns:xsi" ), QStringLiteral(
"http://www.w3.org/2001/XMLSchema-instance" ) );
1214 getFeatureInfoElement.setAttribute( QStringLiteral(
"xsi:schemaLocation" ), featureInfoSchema );
1217 result.appendChild( getFeatureInfoElement );
1227 for (
const QString &queryLayer : queryLayers )
1229 bool validLayer =
false;
1230 bool queryableLayer =
true;
1231 for (
QgsMapLayer *layer : qgis::as_const( layers ) )
1237 if ( !queryableLayer )
1242 QDomElement layerElement;
1243 if ( infoFormat == QgsWmsParameters::Format::GML )
1245 layerElement = getFeatureInfoElement;
1249 layerElement = result.createElement( QStringLiteral(
"Layer" ) );
1250 QString layerName = queryLayer;
1253 QHash<QString, QString>::const_iterator layerAliasIt = layerAliasMap.constFind( layerName );
1254 if ( layerAliasIt != layerAliasMap.constEnd() )
1256 layerName = layerAliasIt.value();
1259 layerElement.setAttribute( QStringLiteral(
"name" ), layerName );
1260 getFeatureInfoElement.appendChild( layerElement );
1263 layerElement.setAttribute( QStringLiteral(
"id" ), layer->id() );
1269 QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layer );
1272 ( void )featureInfoFromVectorLayer( vectorLayer, infoPoint.get(), featureCount, result, layerElement, mapSettings, renderContext, version, featuresRect.get(), filterGeom.get() );
1278 QgsRasterLayer *rasterLayer = qobject_cast<QgsRasterLayer *>( layer );
1287 QgsPointXY layerInfoPoint = mapSettings.mapToLayerCoordinates( layer, *( infoPoint.get() ) );
1292 if ( infoFormat == QgsWmsParameters::Format::GML )
1294 layerElement = result.createElement( QStringLiteral(
"gml:featureMember" ) );
1295 getFeatureInfoElement.appendChild( layerElement );
1298 ( void )featureInfoFromRasterLayer( rasterLayer, mapSettings, &layerInfoPoint, result, layerElement, version );
1306 param.mValue = queryLayer;
1310 else if ( ( validLayer && !queryableLayer ) || ( !validLayer && mContext.
isValidGroup( queryLayer ) ) )
1313 param.mValue = queryLayer;
1315 bool hasGroupAndQueryable {
false };
1320 for (
const QString &ql : constNicks )
1324 const QList<QgsMapLayer *> constLayers { mContext.
layerGroups()[ql] };
1327 if ( ( ! ml->shortName().isEmpty() && ml->shortName() == queryLayer ) || ( ml->name() == queryLayer ) )
1333 hasGroupAndQueryable =
true;
1342 if ( ! hasGroupAndQueryable )
1352 if ( infoFormat == QgsWmsParameters::Format::GML )
1354 QDomElement bBoxElem = result.createElement( QStringLiteral(
"gml:boundedBy" ) );
1355 QDomElement boxElem;
1357 if ( gmlVersion < 3 )
1369 boxElem.setAttribute( QStringLiteral(
"srsName" ),
crs.
authid() );
1371 bBoxElem.appendChild( boxElem );
1372 getFeatureInfoElement.insertBefore( bBoxElem, QDomNode() );
1376 QDomElement bBoxElem = result.createElement( QStringLiteral(
"BoundingBox" ) );
1377 bBoxElem.setAttribute( QStringLiteral(
"CRS" ), mapSettings.destinationCrs().authid() );
1378 bBoxElem.setAttribute( QStringLiteral(
"minx" ),
qgsDoubleToString( featuresRect->xMinimum(), 8 ) );
1379 bBoxElem.setAttribute( QStringLiteral(
"maxx" ),
qgsDoubleToString( featuresRect->xMaximum(), 8 ) );
1380 bBoxElem.setAttribute( QStringLiteral(
"miny" ),
qgsDoubleToString( featuresRect->yMinimum(), 8 ) );
1381 bBoxElem.setAttribute( QStringLiteral(
"maxy" ),
qgsDoubleToString( featuresRect->yMaximum(), 8 ) );
1382 getFeatureInfoElement.insertBefore( bBoxElem, QDomNode() );
1386 if ( sia2045 && infoFormat == QgsWmsParameters::Format::XML )
1388 convertFeatureInfoToSia2045( result );
1394 bool QgsRenderer::featureInfoFromVectorLayer(
QgsVectorLayer *layer,
1397 QDomDocument &infoDocument,
1398 QDomElement &layerElement,
1401 const QString &version,
1413 std::unique_ptr<QgsGeometry> layerFilterGeom;
1416 layerFilterGeom.reset(
new QgsGeometry( *filterGeom ) );
1430 searchRect = featureInfoSearchRect( layer, mapSettings, renderContext, *infoPoint );
1432 else if ( layerFilterGeom )
1434 searchRect = layerFilterGeom->boundingBox();
1436 else if ( !mWmsParameters.
bbox().isEmpty() )
1438 searchRect = layerRect;
1445 int featureCounter = 0;
1464 if ( layerFilterGeom )
1466 fReq.
setFilterExpression( QString(
"intersects( $geometry, geom_from_wkt('%1') )" ).arg( layerFilterGeom->asWkt() ) );
1469 #ifdef HAVE_SERVER_PYTHON_PLUGINS
1470 mContext.accessControl()->filterFeatures( layer, fReq );
1472 QStringList attributes;
1477 attributes = mContext.accessControl()->layerAttributes( layer, attributes );
1482 std::unique_ptr< QgsFeatureRenderer > r2( layer->
renderer() ? layer->
renderer()->
clone() :
nullptr );
1485 r2->startRender( renderContext, layer->
fields() );
1488 bool featureBBoxInitialized =
false;
1497 if ( featureCounter > nFeatures )
1512 bool render = r2->willRenderFeature( feature, renderContext );
1525 if ( !featureBBoxInitialized && featureBBox->
isEmpty() )
1528 featureBBoxInitialized =
true;
1543 if ( mWmsParameters.
infoFormat() == QgsWmsParameters::Format::GML )
1548 QDomElement elem = createFeatureGML(
1550 #ifdef HAVE_SERVER_PYTHON_PLUGINS
1554 QDomElement featureMemberElem = infoDocument.createElement( QStringLiteral(
"gml:featureMember" ) );
1555 featureMemberElem.appendChild( elem );
1556 layerElement.appendChild( featureMemberElem );
1561 QDomElement featureElement = infoDocument.createElement( QStringLiteral(
"Feature" ) );
1563 layerElement.appendChild( featureElement );
1567 for (
int i = 0; i < featureAttributes.count(); ++i )
1574 #ifdef HAVE_SERVER_PYTHON_PLUGINS
1576 if ( !attributes.contains( fields.at( i ).name() ) )
1585 QDomElement attributeElement = infoDocument.createElement( QStringLiteral(
"Attribute" ) );
1586 attributeElement.setAttribute( QStringLiteral(
"name" ), attributeName );
1588 attributeElement.setAttribute( QStringLiteral(
"value" ),
1590 replaceValueMapAndRelation(
1592 featureAttributes[i] ),
1595 featureElement.appendChild( attributeElement );
1600 if ( !mapTip.isEmpty() && mWmsParameters.
withMapTip() )
1602 QDomElement maptipElem = infoDocument.createElement( QStringLiteral(
"Attribute" ) );
1603 maptipElem.setAttribute( QStringLiteral(
"name" ), QStringLiteral(
"maptip" ) );
1605 featureElement.appendChild( maptipElem );
1612 QDomElement bBoxElem = infoDocument.createElement( QStringLiteral(
"BoundingBox" ) );
1613 bBoxElem.setAttribute( version == QLatin1String(
"1.1.1" ) ?
"SRS" :
"CRS",
outputCrs.
authid() );
1618 featureElement.appendChild( bBoxElem );
1634 if ( segmentizeWktGeometry )
1642 geom.
set( segmentizedGeom );
1646 QDomElement geometryElement = infoDocument.createElement( QStringLiteral(
"Attribute" ) );
1647 geometryElement.setAttribute( QStringLiteral(
"name" ), QStringLiteral(
"geometry" ) );
1648 geometryElement.setAttribute( QStringLiteral(
"value" ), geom.
asWkt( mContext.
precision() ) );
1649 geometryElement.setAttribute( QStringLiteral(
"type" ), QStringLiteral(
"derived" ) );
1650 featureElement.appendChild( geometryElement );
1657 r2->stopRender( renderContext );
1663 bool QgsRenderer::featureInfoFromRasterLayer(
QgsRasterLayer *layer,
1666 QDomDocument &infoDocument,
1667 QDomElement &layerElement,
1668 const QString &version )
const
1687 ? QgsRaster::IdentifyFormat::IdentifyFormatFeature
1688 : QgsRaster::IdentifyFormat::IdentifyFormatValue );
1700 .arg( layer->
name() ) );
1709 if ( !identifyResult.
isValid() )
1712 QMap<int, QVariant> attributes = identifyResult.
results();
1714 if ( mWmsParameters.
infoFormat() == QgsWmsParameters::Format::GML )
1726 for (
auto it = attributes.constBegin(); it != attributes.constEnd(); ++it )
1729 feature.
setAttribute( index++, QString::number( it.value().toDouble() ) );
1732 QDomElement elem = createFeatureGML(
1733 &feature,
nullptr, infoDocument, layerCrs, mapSettings,
typeName,
false, gmlVersion,
nullptr );
1734 layerElement.appendChild( elem );
1738 const auto values = identifyResult.
results();
1739 for (
auto it = values.constBegin(); it != values.constEnd(); ++it )
1741 QVariant value = it.value();
1742 if ( value.type() == QVariant::Bool && !value.toBool() )
1748 if ( value.type() == QVariant::String )
1759 for (
const QgsFeature &feature : storeFeatures )
1761 QDomElement elem = createFeatureGML(
1762 &feature,
nullptr, infoDocument, layerCrs, mapSettings,
typeName,
false, gmlVersion,
nullptr );
1763 layerElement.appendChild( elem );
1773 for (
auto it = attributes.constBegin(); it != attributes.constEnd(); ++it )
1775 QDomElement attributeElement = infoDocument.createElement( QStringLiteral(
"Attribute" ) );
1776 attributeElement.setAttribute( QStringLiteral(
"name" ), layer->
bandName( it.key() ) );
1779 if ( ! it.value().isNull() )
1781 value = QString::number( it.value().toDouble() );
1784 attributeElement.setAttribute( QStringLiteral(
"value" ), value );
1785 layerElement.appendChild( attributeElement );
1790 const auto values = identifyResult.
results();
1791 for (
auto it = values.constBegin(); it != values.constEnd(); ++it )
1793 QVariant value = it.value();
1794 if ( value.type() == QVariant::Bool && !value.toBool() )
1800 if ( value.type() == QVariant::String )
1810 for (
const QgsFeature &feature : storeFeatures )
1812 for (
const auto &fld : feature.
fields() )
1814 const auto val { feature.
attribute( fld.name() )};
1815 if ( val.isValid() )
1817 QDomElement attributeElement = infoDocument.createElement( QStringLiteral(
"Attribute" ) );
1818 attributeElement.setAttribute( QStringLiteral(
"name" ), fld.name() );
1819 attributeElement.setAttribute( QStringLiteral(
"value" ), val.toString() );
1820 layerElement.appendChild( attributeElement );
1831 bool QgsRenderer::testFilterStringSafety(
const QString &filter )
const
1834 if ( filter.contains( QLatin1String(
";" ) ) )
1839 QStringList tokens = filter.split(
' ', QString::SkipEmptyParts );
1840 groupStringList( tokens, QStringLiteral(
"'" ) );
1841 groupStringList( tokens, QStringLiteral(
"\"" ) );
1843 for (
auto tokenIt = tokens.constBegin() ; tokenIt != tokens.constEnd(); ++tokenIt )
1846 if ( tokenIt->compare( QLatin1String(
"," ) ) == 0
1847 || tokenIt->compare( QLatin1String(
"(" ) ) == 0
1848 || tokenIt->compare( QLatin1String(
")" ) ) == 0
1849 || tokenIt->compare( QLatin1String(
"=" ) ) == 0
1850 || tokenIt->compare( QLatin1String(
"!=" ) ) == 0
1851 || tokenIt->compare( QLatin1String(
"<" ) ) == 0
1852 || tokenIt->compare( QLatin1String(
"<=" ) ) == 0
1853 || tokenIt->compare( QLatin1String(
">" ) ) == 0
1854 || tokenIt->compare( QLatin1String(
">=" ) ) == 0
1855 || tokenIt->compare( QLatin1String(
"%" ) ) == 0
1856 || tokenIt->compare( QLatin1String(
"IS" ), Qt::CaseInsensitive ) == 0
1857 || tokenIt->compare( QLatin1String(
"NOT" ), Qt::CaseInsensitive ) == 0
1858 || tokenIt->compare( QLatin1String(
"NULL" ), Qt::CaseInsensitive ) == 0
1859 || tokenIt->compare( QLatin1String(
"AND" ), Qt::CaseInsensitive ) == 0
1860 || tokenIt->compare( QLatin1String(
"OR" ), Qt::CaseInsensitive ) == 0
1861 || tokenIt->compare( QLatin1String(
"IN" ), Qt::CaseInsensitive ) == 0
1862 || tokenIt->compare( QLatin1String(
"LIKE" ), Qt::CaseInsensitive ) == 0
1863 || tokenIt->compare( QLatin1String(
"ILIKE" ), Qt::CaseInsensitive ) == 0
1864 || tokenIt->compare( QLatin1String(
"DMETAPHONE" ), Qt::CaseInsensitive ) == 0
1865 || tokenIt->compare( QLatin1String(
"SOUNDEX" ), Qt::CaseInsensitive ) == 0 )
1872 tokenIt->toDouble( &isNumeric );
1881 if ( *tokenIt == QLatin1String(
"''" ) )
1887 if ( tokenIt->size() > 2
1888 && ( *tokenIt )[0] == QChar(
'\'' )
1889 && ( *tokenIt )[tokenIt->size() - 1] == QChar(
'\'' )
1890 && ( *tokenIt )[1] != QChar(
'\'' )
1891 && ( *tokenIt )[tokenIt->size() - 2] != QChar(
'\'' ) )
1897 if ( tokenIt->size() > 2
1898 && ( *tokenIt )[0] == QChar(
'"' )
1899 && ( *tokenIt )[tokenIt->size() - 1] == QChar(
'"' )
1900 && ( *tokenIt )[1] != QChar(
'"' )
1901 && ( *tokenIt )[tokenIt->size() - 2] != QChar(
'"' ) )
1912 void QgsRenderer::groupStringList( QStringList &list,
const QString &groupString )
1915 bool groupActive =
false;
1916 int startGroup = -1;
1917 QString concatString;
1919 for (
int i = 0; i < list.size(); ++i )
1921 QString &str = list[i];
1922 if ( str.startsWith( groupString ) )
1926 concatString.clear();
1931 if ( i != startGroup )
1933 concatString.append(
" " );
1935 concatString.append( str );
1938 if ( str.endsWith( groupString ) )
1941 groupActive =
false;
1943 if ( startGroup != -1 )
1945 list[startGroup] = concatString;
1946 for (
int j = startGroup + 1; j <= endGroup; ++j )
1948 list.removeAt( startGroup + 1 );
1953 concatString.clear();
1959 void QgsRenderer::convertFeatureInfoToSia2045( QDomDocument &doc )
const
1961 QDomDocument SIAInfoDoc;
1962 QDomElement infoDocElement = doc.documentElement();
1963 QDomElement SIAInfoDocElement = SIAInfoDoc.importNode( infoDocElement,
false ).toElement();
1964 SIAInfoDoc.appendChild( SIAInfoDocElement );
1966 QString currentAttributeName;
1967 QString currentAttributeValue;
1968 QDomElement currentAttributeElem;
1969 QString currentLayerName;
1970 QDomElement currentLayerElem;
1971 QDomNodeList layerNodeList = infoDocElement.elementsByTagName( QStringLiteral(
"Layer" ) );
1972 for (
int i = 0; i < layerNodeList.size(); ++i )
1974 currentLayerElem = layerNodeList.at( i ).toElement();
1975 currentLayerName = currentLayerElem.attribute( QStringLiteral(
"name" ) );
1977 QDomElement currentFeatureElem;
1979 QDomNodeList featureList = currentLayerElem.elementsByTagName( QStringLiteral(
"Feature" ) );
1980 if ( featureList.isEmpty() )
1983 QDomNodeList attributeList = currentLayerElem.elementsByTagName( QStringLiteral(
"Attribute" ) );
1984 QDomElement rasterLayerElem;
1985 if ( !attributeList.isEmpty() )
1987 rasterLayerElem = SIAInfoDoc.createElement( currentLayerName );
1989 for (
int j = 0; j < attributeList.size(); ++j )
1991 currentAttributeElem = attributeList.at( j ).toElement();
1992 currentAttributeName = currentAttributeElem.attribute( QStringLiteral(
"name" ) );
1993 currentAttributeValue = currentAttributeElem.attribute( QStringLiteral(
"value" ) );
1994 QDomElement outAttributeElem = SIAInfoDoc.createElement( currentAttributeName );
1995 QDomText outAttributeText = SIAInfoDoc.createTextNode( currentAttributeValue );
1996 outAttributeElem.appendChild( outAttributeText );
1997 rasterLayerElem.appendChild( outAttributeElem );
1999 if ( !attributeList.isEmpty() )
2001 SIAInfoDocElement.appendChild( rasterLayerElem );
2007 QSet<QString> layerPropertyAttributes;
2008 QString currentLayerId = currentLayerElem.attribute( QStringLiteral(
"id" ) );
2009 if ( !currentLayerId.isEmpty() )
2014 QString WMSPropertyAttributesString = currentLayer->
customProperty( QStringLiteral(
"WMSPropertyAttributes" ) ).toString();
2015 if ( !WMSPropertyAttributesString.isEmpty() )
2017 QStringList propertyList = WMSPropertyAttributesString.split( QStringLiteral(
"//" ) );
2018 for (
auto propertyIt = propertyList.constBegin() ; propertyIt != propertyList.constEnd(); ++propertyIt )
2020 layerPropertyAttributes.insert( *propertyIt );
2026 QDomElement propertyRefChild;
2027 for (
int j = 0; j < featureList.size(); ++j )
2029 QDomElement SIAFeatureElem = SIAInfoDoc.createElement( currentLayerName );
2030 currentFeatureElem = featureList.at( j ).toElement();
2031 QDomNodeList attributeList = currentFeatureElem.elementsByTagName( QStringLiteral(
"Attribute" ) );
2033 for (
int k = 0; k < attributeList.size(); ++k )
2035 currentAttributeElem = attributeList.at( k ).toElement();
2036 currentAttributeName = currentAttributeElem.attribute( QStringLiteral(
"name" ) );
2037 currentAttributeValue = currentAttributeElem.attribute( QStringLiteral(
"value" ) );
2038 if ( layerPropertyAttributes.contains( currentAttributeName ) )
2040 QDomElement propertyElem = SIAInfoDoc.createElement( QStringLiteral(
"property" ) );
2041 QDomElement identifierElem = SIAInfoDoc.createElement( QStringLiteral(
"identifier" ) );
2042 QDomText identifierText = SIAInfoDoc.createTextNode( currentAttributeName );
2043 identifierElem.appendChild( identifierText );
2044 QDomElement valueElem = SIAInfoDoc.createElement( QStringLiteral(
"value" ) );
2045 QDomText valueText = SIAInfoDoc.createTextNode( currentAttributeValue );
2046 valueElem.appendChild( valueText );
2047 propertyElem.appendChild( identifierElem );
2048 propertyElem.appendChild( valueElem );
2049 if ( propertyRefChild.isNull() )
2051 SIAFeatureElem.insertBefore( propertyElem, QDomNode() );
2052 propertyRefChild = propertyElem;
2056 SIAFeatureElem.insertAfter( propertyElem, propertyRefChild );
2061 QDomElement SIAAttributeElem = SIAInfoDoc.createElement( currentAttributeName );
2062 QDomText SIAAttributeText = SIAInfoDoc.createTextNode( currentAttributeValue );
2063 SIAAttributeElem.appendChild( SIAAttributeText );
2064 SIAFeatureElem.appendChild( SIAAttributeElem );
2067 SIAInfoDocElement.appendChild( SIAFeatureElem );
2074 QByteArray QgsRenderer::convertFeatureInfoToHtml(
const QDomDocument &doc )
const
2076 QString featureInfoString;
2079 featureInfoString.append(
"<HEAD>\n" );
2080 featureInfoString.append(
"<TITLE> GetFeatureInfo results </TITLE>\n" );
2081 featureInfoString.append(
"<META http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\"/>\n" );
2082 featureInfoString.append(
"</HEAD>\n" );
2085 featureInfoString.append(
"<BODY>\n" );
2087 QDomNodeList layerList = doc.elementsByTagName( QStringLiteral(
"Layer" ) );
2090 for (
int i = 0; i < layerList.size(); ++i )
2092 QDomElement layerElem = layerList.at( i ).toElement();
2094 featureInfoString.append(
"<TABLE border=1 width=100%>\n" );
2095 featureInfoString.append(
"<TR><TH width=25%>Layer</TH><TD>" + layerElem.attribute( QStringLiteral(
"name" ) ) +
"</TD></TR>\n" );
2096 featureInfoString.append(
"</BR>" );
2099 QDomNodeList featureNodeList = layerElem.elementsByTagName( QStringLiteral(
"Feature" ) );
2100 QDomElement currentFeatureElement;
2102 if ( !featureNodeList.isEmpty() )
2104 for (
int j = 0; j < featureNodeList.size(); ++j )
2106 QDomElement featureElement = featureNodeList.at( j ).toElement();
2107 featureInfoString.append(
"<TABLE border=1 width=100%>\n" );
2108 featureInfoString.append(
"<TR><TH>Feature</TH><TD>" + featureElement.attribute( QStringLiteral(
"id" ) ) +
2112 QDomNodeList attributeNodeList = featureElement.elementsByTagName( QStringLiteral(
"Attribute" ) );
2113 for (
int k = 0; k < attributeNodeList.size(); ++k )
2115 QDomElement attributeElement = attributeNodeList.at( k ).toElement();
2116 featureInfoString.append(
"<TR><TH>" + attributeElement.attribute( QStringLiteral(
"name" ) ) +
2117 "</TH><TD>" + attributeElement.attribute( QStringLiteral(
"value" ) ) +
"</TD></TR>\n" );
2120 featureInfoString.append(
"</TABLE>\n</BR>\n" );
2125 QDomNodeList attributeNodeList = layerElem.elementsByTagName( QStringLiteral(
"Attribute" ) );
2126 for (
int j = 0; j < attributeNodeList.size(); ++j )
2128 QDomElement attributeElement = attributeNodeList.at( j ).toElement();
2129 QString value = attributeElement.attribute( QStringLiteral(
"value" ) );
2130 if ( value.isEmpty() )
2132 value = QStringLiteral(
"no data" );
2134 featureInfoString.append(
"<TR><TH>" + attributeElement.attribute( QStringLiteral(
"name" ) ) +
2135 "</TH><TD>" + value +
"</TD></TR>\n" );
2139 featureInfoString.append(
"</TABLE>\n<BR></BR>\n" );
2143 featureInfoString.append(
"</BODY>\n" );
2145 return featureInfoString.toUtf8();
2148 QByteArray QgsRenderer::convertFeatureInfoToText(
const QDomDocument &doc )
const
2150 QString featureInfoString;
2153 featureInfoString.append(
"GetFeatureInfo results\n" );
2154 featureInfoString.append(
"\n" );
2156 QDomNodeList layerList = doc.elementsByTagName( QStringLiteral(
"Layer" ) );
2159 for (
int i = 0; i < layerList.size(); ++i )
2161 QDomElement layerElem = layerList.at( i ).toElement();
2163 featureInfoString.append(
"Layer '" + layerElem.attribute( QStringLiteral(
"name" ) ) +
"'\n" );
2166 QDomNodeList featureNodeList = layerElem.elementsByTagName( QStringLiteral(
"Feature" ) );
2167 QDomElement currentFeatureElement;
2169 if ( !featureNodeList.isEmpty() )
2171 for (
int j = 0; j < featureNodeList.size(); ++j )
2173 QDomElement featureElement = featureNodeList.at( j ).toElement();
2174 featureInfoString.append(
"Feature " + featureElement.attribute( QStringLiteral(
"id" ) ) +
"\n" );
2177 QDomNodeList attributeNodeList = featureElement.elementsByTagName( QStringLiteral(
"Attribute" ) );
2178 for (
int k = 0; k < attributeNodeList.size(); ++k )
2180 QDomElement attributeElement = attributeNodeList.at( k ).toElement();
2181 featureInfoString.append( attributeElement.attribute( QStringLiteral(
"name" ) ) +
" = '" +
2182 attributeElement.attribute( QStringLiteral(
"value" ) ) +
"'\n" );
2188 QDomNodeList attributeNodeList = layerElem.elementsByTagName( QStringLiteral(
"Attribute" ) );
2189 for (
int j = 0; j < attributeNodeList.size(); ++j )
2191 QDomElement attributeElement = attributeNodeList.at( j ).toElement();
2192 QString value = attributeElement.attribute( QStringLiteral(
"value" ) );
2193 if ( value.isEmpty() )
2195 value = QStringLiteral(
"no data" );
2197 featureInfoString.append( attributeElement.attribute( QStringLiteral(
"name" ) ) +
" = '" +
2202 featureInfoString.append(
"\n" );
2205 return featureInfoString.toUtf8();
2208 QByteArray QgsRenderer::convertFeatureInfoToJson(
const QList<QgsMapLayer *> &layers,
const QDomDocument &doc )
const
2212 {
"type",
"FeatureCollection" },
2213 {
"features", json::array() },
2217 const QDomNodeList layerList = doc.elementsByTagName( QStringLiteral(
"Layer" ) );
2218 for (
int i = 0; i < layerList.size(); ++i )
2220 const QDomElement layerElem = layerList.at( i ).toElement();
2221 const QString layerName = layerElem.attribute( QStringLiteral(
"name" ) );
2226 if ( mContext.
layerNickname( *l ).compare( layerName ) == 0 )
2242 const QDomNodeList featuresNode = layerElem.elementsByTagName( QStringLiteral(
"Feature" ) );
2243 if ( featuresNode.isEmpty() )
2246 for (
int j = 0; j < featuresNode.size(); ++j )
2248 const QDomElement featureNode = featuresNode.at( j ).toElement();
2249 const QgsFeatureId fid = featureNode.attribute( QStringLiteral(
"id" ) ).toLongLong();
2255 const QDomNodeList attrs = featureNode.elementsByTagName(
"Attribute" );
2256 for (
int k = 0; k < attrs.count(); k++ )
2258 const QDomElement elm = attrs.at( k ).toElement();
2259 if ( elm.attribute( QStringLiteral(
"name" ) ).compare(
"geometry" ) == 0 )
2261 wkt = elm.attribute(
"value" );
2266 if ( ! wkt.isEmpty() )
2272 features << feature;
2275 if ( !attributes.isEmpty() )
2278 const QDomNodeList attributesNode = featureNode.elementsByTagName( QStringLiteral(
"Attribute" ) );
2279 for (
int k = 0; k < attributesNode.size(); ++k )
2281 const QDomElement attributeElement = attributesNode.at( k ).toElement();
2282 const QString fieldName = attributeElement.
attribute( QStringLiteral(
"name" ) );
2284 attributes << feature.fieldNameIndex( fieldName );
2290 exporter.setAttributeDisplayName(
true );
2291 exporter.setAttributes( attributes );
2292 exporter.setIncludeGeometry( withGeometry );
2293 exporter.setTransformGeometries(
false );
2295 for (
const auto &feature : qgis::as_const( features ) )
2297 const QString
id = QStringLiteral(
"%1.%2" ).arg( layerName ).arg( feature.id() );
2298 json[
"features"].push_back( exporter.exportFeatureToJsonObject( feature, QVariantMap(),
id ) );
2303 auto properties = json::object();
2304 const QDomNodeList attributesNode = layerElem.elementsByTagName( QStringLiteral(
"Attribute" ) );
2305 for (
int j = 0; j < attributesNode.size(); ++j )
2307 const QDomElement attrElmt = attributesNode.at( j ).toElement();
2308 const QString name = attrElmt.attribute( QStringLiteral(
"name" ) );
2310 QString value = attrElmt.attribute( QStringLiteral(
"value" ) );
2311 if ( value.isEmpty() )
2313 value = QStringLiteral(
"null" );
2316 properties[name.toStdString()] = value.toStdString();
2319 json[
"features"].push_back(
2321 {
"type",
"Feature" },
2322 {
"id", layerName.toStdString() },
2323 {
"properties", properties }
2329 return QByteArray::fromStdString( json.dump( 2 ) );
2331 return QByteArray::fromStdString( json.dump() );
2335 QDomElement QgsRenderer::createFeatureGML(
2344 QStringList *attributes )
const
2347 QDomElement typeNameElement = doc.createElement(
"qgs:" +
typeName );
2348 typeNameElement.setAttribute( QStringLiteral(
"fid" ),
typeName +
"." + QString::number( feat->
id() ) );
2351 if ( layer && layer->
crs() !=
crs )
2377 box = transformedBox;
2385 QDomElement bbElem = doc.createElement( QStringLiteral(
"gml:boundedBy" ) );
2386 QDomElement boxElem;
2398 boxElem.setAttribute( QStringLiteral(
"srsName" ),
crs.
authid() );
2400 bbElem.appendChild( boxElem );
2401 typeNameElement.appendChild( bbElem );
2413 QDomElement geomElem = doc.createElement( QStringLiteral(
"qgs:geometry" ) );
2414 QDomElement gmlElem;
2424 if ( !gmlElem.isNull() )
2428 gmlElem.setAttribute( QStringLiteral(
"srsName" ),
crs.
authid() );
2430 geomElem.appendChild( gmlElem );
2431 typeNameElement.appendChild( geomElem );
2438 for (
int i = 0; i < fields.
count(); ++i )
2440 QString attributeName = fields.
at( i ).
name();
2447 if ( attributes && !attributes->contains( attributeName ) )
2452 QDomElement fieldElem = doc.createElement(
"qgs:" + attributeName.replace(
' ',
'_' ) );
2453 QString fieldTextString = featureAttributes.at( i ).toString();
2458 QDomText fieldText = doc.createTextNode( fieldTextString );
2459 fieldElem.appendChild( fieldText );
2460 typeNameElement.appendChild( fieldElem );
2468 if ( !mapTip.isEmpty() && mWmsParameters.
withMapTip() )
2471 QDomElement fieldElem = doc.createElement( QStringLiteral(
"qgs:maptip" ) );
2472 QDomText maptipText = doc.createTextNode( fieldTextString );
2473 fieldElem.appendChild( maptipText );
2474 typeNameElement.appendChild( fieldElem );
2478 return typeNameElement;
2481 QString QgsRenderer::replaceValueMapAndRelation(
QgsVectorLayer *vl,
int idx,
const QVariant &attributeVal )
2485 QString value( fieldFormatter->
representValue( vl, idx, setup.
config(), QVariant(), attributeVal ) );
2487 if ( setup.
config().value( QStringLiteral(
"AllowMulti" ) ).toBool() && value.startsWith( QLatin1Char(
'{' ) ) && value.endsWith( QLatin1Char(
'}' ) ) )
2489 value = value.mid( 1, value.size() - 2 );
2501 double mapUnitTolerance = 0.0;
2511 mapUnitTolerance = mapSettings.
extent().
width() / 400.0;
2523 mapUnitTolerance = mapSettings.
extent().
width() / 200.0;
2535 mapUnitTolerance = mapSettings.
extent().
width() / 100.0;
2539 QgsRectangle mapRectangle( infoPoint.
x() - mapUnitTolerance, infoPoint.
y() - mapUnitTolerance,
2540 infoPoint.
x() + mapUnitTolerance, infoPoint.
y() + mapUnitTolerance );
2544 QList<QgsMapLayer *> QgsRenderer::highlightLayers( QList<QgsWmsParametersHighlightLayer> params )
2546 QList<QgsMapLayer *> highlightLayers;
2549 QString
crs = mWmsParameters.
crs();
2550 for (
const QgsWmsParametersHighlightLayer ¶m : params )
2553 QDomDocument sldDoc;
2554 if ( !sldDoc.setContent( param.mSld,
true ) )
2561 std::unique_ptr<QgsFeatureRenderer> renderer;
2562 QDomElement el = sldDoc.documentElement();
2573 if ( ! param.mLabel.isEmpty() )
2575 url +=
"&field=label:string";
2580 std::unique_ptr<QgsVectorLayer> layer = qgis::make_unique<QgsVectorLayer>( url, param.mName, QLatin1String(
"memory" ), options );
2581 if ( !layer->isValid() )
2588 if ( ! param.mLabel.isEmpty() )
2590 fet.setAttribute( 0, param.mLabel );
2599 switch ( param.mGeom.type() )
2604 palSettings.
dist = 2;
2615 QVariant x( pt.
x() );
2619 QVariant y( pt.
y() );
2623 QVariant hali(
"Center" );
2627 QVariant vali(
"Half" );
2634 palSettings.
dist = 2;
2643 if ( param.mColor.isValid() )
2645 textFormat.
setColor( param.mColor );
2648 if ( param.mSize > 0 )
2650 textFormat.
setSize( param.mSize );
2658 if ( ! param.mFont.isEmpty() )
2660 textFormat.
setFont( param.mFont );
2663 if ( param.mBufferColor.isValid() )
2665 bufferSettings.
setColor( param.mBufferColor );
2668 if ( param.mBufferSize > 0 )
2671 bufferSettings.
setSize(
static_cast<double>( param.mBufferSize ) );
2678 layer->setLabeling( simpleLabeling );
2679 layer->setLabelsEnabled(
true );
2681 fet.setGeometry( param.mGeom );
2685 layer->setRenderer( renderer.release() );
2688 if ( layer->isValid() )
2690 highlightLayers.append( layer.release() );
2694 mTemporaryLayers.append( highlightLayers );
2695 return highlightLayers;
2698 void QgsRenderer::removeTemporaryLayers()
2700 qDeleteAll( mTemporaryLayers );
2701 mTemporaryLayers.clear();
2704 QPainter *QgsRenderer::layersRendering(
const QgsMapSettings &mapSettings, QImage &image )
const
2706 QPainter *painter =
nullptr;
2710 #ifdef HAVE_SERVER_PYTHON_PLUGINS
2711 mContext.accessControl()->resolveFilterFeatures( mapSettings.
layers() );
2715 renderJob.render( mapSettings, &image );
2716 painter = renderJob.takePainter();
2718 if ( !renderJob.errors().isEmpty() )
2720 QString layerWMSName;
2721 QString firstErrorLayerId = renderJob.errors().at( 0 ).layerID;
2728 throw QgsException( QStringLiteral(
"Map rendering error in layer '%1'" ).arg( layerWMSName ) );
2734 void QgsRenderer::setLayerOpacity(
QgsMapLayer *layer,
int opacity )
const
2736 if ( opacity >= 0 && opacity <= 255 )
2738 switch ( layer->
type() )
2751 rasterRenderer->
setOpacity( opacity / 255. );
2764 void QgsRenderer::setLayerFilter(
QgsMapLayer *layer,
const QList<QgsWmsParametersFilter> &filters )
2768 QgsVectorLayer *filteredLayer = qobject_cast<QgsVectorLayer *>( layer );
2769 QStringList expList;
2770 for (
const QgsWmsParametersFilter &filter : filters )
2775 QDomDocument filterXml;
2777 if ( !filterXml.setContent( filter.mFilter,
true, &errorMsg ) )
2780 QStringLiteral(
"Filter string rejected. Error message: %1. The XML string was: %2" ).arg( errorMsg, filter.mFilter ) );
2782 QDomElement filterElem = filterXml.firstChildElement();
2787 expList << filterExp->dump();
2793 if ( !testFilterStringSafety( filter.mFilter ) )
2795 throw QgsSecurityException( QStringLiteral(
"The filter string %1"
2796 " has been rejected because of security reasons."
2797 " Note: Text strings have to be enclosed in single or double quotes."
2798 " A space between each word / special character is mandatory."
2799 " Allowed Keywords and special characters are "
2800 " IS,NOT,NULL,AND,OR,IN,=,<,>=,>,>=,!=,',',(,),DMETAPHONE,SOUNDEX."
2801 " Not allowed are semicolons in the filter expression." ).arg(
2805 QString newSubsetString = filter.mFilter;
2808 newSubsetString.prepend(
") AND (" );
2809 newSubsetString.append(
")" );
2810 newSubsetString.prepend( filteredLayer->
subsetString() );
2811 newSubsetString.prepend(
"(" );
2817 expList.append( dimensionFilter( filteredLayer ) );
2821 if ( expList.size() == 1 )
2825 else if ( expList.size() > 1 )
2827 exp = QStringLiteral(
"( %1 )" ).arg( expList.join( QLatin1String(
" ) AND ( " ) ) );
2829 if ( !exp.isEmpty() )
2831 std::unique_ptr<QgsExpression> expression(
new QgsExpression( exp ) );
2834 mFeatureFilter.
setFilter( filteredLayer, *expression );
2840 QStringList QgsRenderer::dimensionFilter(
QgsVectorLayer *layer )
const
2842 QStringList expList;
2845 if ( wmsDims.isEmpty() )
2855 if ( fieldIndex == -1 )
2860 int endFieldIndex = -1;
2861 if ( !dim.endFieldName.isEmpty() )
2863 endFieldIndex = layer->
fields().
indexOf( dim.endFieldName );
2864 if ( endFieldIndex == -1 )
2870 if ( !dimParamValues.contains( dim.name.toUpper() ) )
2880 defValue = dim.referenceValue;
2885 QSet<QVariant> uniqueValues = layer->
uniqueValues( fieldIndex );
2886 if ( endFieldIndex != -1 )
2888 uniqueValues.unite( layer->
uniqueValues( endFieldIndex ) );
2891 QList<QVariant> values = qgis::setToList( uniqueValues );
2892 std::sort( values.begin(), values.end() );
2895 defValue = values.first();
2899 defValue = values.last();
2903 if ( endFieldIndex == -1 )
2909 QStringList expElems;
2914 expList << expElems.join(
' ' );
2922 QString dimParamValue = dimParamValues[dim.name.toUpper()];
2924 QStringList dimExplist;
2926 QStringList dimValues = dimParamValue.split(
',' );
2927 for (
int i = 0; i < dimValues.size(); ++i )
2929 QString dimValue = dimValues[i];
2931 if ( dimValue.size() > 1 )
2933 dimValue = dimValue.trimmed();
2936 if ( dimValue.contains(
'/' ) )
2938 QStringList rangeValues = dimValue.split(
'/' );
2940 if ( rangeValues.size() != 2 )
2945 QVariant rangeMin = QVariant( rangeValues[0] );
2946 QVariant rangeMax = QVariant( rangeValues[1] );
2957 QStringList expElems;
2958 if ( endFieldIndex == -1 )
2978 << QStringLiteral(
")" );
2980 dimExplist << expElems.join(
' ' );
2984 QVariant dimVariant = QVariant( dimValue );
2990 if ( endFieldIndex == -1 )
2999 QStringList expElems;
3004 dimExplist << expElems.join(
' ' );
3009 if ( dimExplist.size() == 1 )
3011 expList << dimExplist;
3013 else if ( dimExplist.size() > 1 )
3015 expList << QStringLiteral(
"( %1 )" ).arg( dimExplist.join( QLatin1String(
" ) OR ( " ) ) );
3022 void QgsRenderer::setLayerSelection(
QgsMapLayer *layer,
const QStringList &fids )
const
3028 for (
const QString &
id : fids )
3038 void QgsRenderer::setLayerAccessControlFilter(
QgsMapLayer *layer )
const
3040 #ifdef HAVE_SERVER_PYTHON_PLUGINS
3058 void QgsRenderer::annotationsRendering( QPainter *painter )
const
3061 const QList< QgsAnnotation * > annotations = annotationManager->
annotations();
3067 if ( !annotation || !annotation->isVisible() )
3070 annotation->render( renderContext );
3074 QImage *QgsRenderer::scaleImage(
const QImage *image )
const
3079 QImage *scaledImage =
nullptr;
3080 const int width = mWmsParameters.
widthAsInt();
3082 if ( width != image->width() || height != image->height() )
3084 scaledImage =
new QImage( image->scaled( width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ) );
3090 void QgsRenderer::handlePrintErrors(
const QgsLayout *layout )
const
3096 QList< QgsLayoutItemMap * > mapList;
3099 QList< QgsLayoutItemMap * >::const_iterator mapIt = mapList.constBegin();
3100 for ( ; mapIt != mapList.constEnd(); ++mapIt )
3102 if ( !( *mapIt )->renderingErrors().isEmpty() )
3114 for (
auto layer : layers )
3130 setLayerSld( layer, mContext.
sld( *layer ) );
3134 setLayerStyle( layer, mContext.
style( *layer ) );
3139 setLayerOpacity( layer, param.
mOpacity );
3144 setLayerFilter( layer, param.
mFilter );
3149 setLayerSelection( layer, param.
mSelection );
3154 updateExtent( layer, *settings );
3159 setLayerAccessControlFilter( layer );
3169 void QgsRenderer::setLayerStyle(
QgsMapLayer *layer,
const QString &style )
const
3171 if ( style.isEmpty() )
3180 QStringLiteral(
"Style '%1' does not exist for layer '%2'" ).arg( style, layer->
name() ) );
3184 void QgsRenderer::setLayerSld(
QgsMapLayer *layer,
const QDomElement &sld )
const
3189 QString sldStyleName =
"__sld_style";
3190 while ( styles.contains( sldStyleName ) )
3192 sldStyleName.append(
'@' );
3205 if ( !mWmsParameters.
bbox().isEmpty() )
3209 std::unique_ptr<QImage> tmp( createImage( mContext.
mapSize(
false ) ) );
3210 configureMapSettings( tmp.get(), mapSettings );