mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-17 00:04:02 -04:00
Merge pull request #4846 from rldhont/server-wms-configparser-getfeatureinfo
[Server] WMS GetFeatureInfo refactoring
This commit is contained in:
commit
08c06def1b
@ -145,6 +145,62 @@ namespace QgsServerProjectUtils
|
|||||||
:rtype: bool
|
:rtype: bool
|
||||||
%End
|
%End
|
||||||
|
|
||||||
|
bool wmsFeatureInfoAddWktGeometry( const QgsProject &project );
|
||||||
|
%Docstring
|
||||||
|
Returns if the geometry is displayed as Well Known Text in GetFeatureInfo request.
|
||||||
|
\param project the QGIS project
|
||||||
|
:return: if the geometry is displayed as Well Known Text in GetFeatureInfo request.
|
||||||
|
:rtype: bool
|
||||||
|
%End
|
||||||
|
|
||||||
|
bool wmsFeatureInfoSegmentizeWktGeometry( const QgsProject &project );
|
||||||
|
%Docstring
|
||||||
|
Returns if the geometry has to be segmentize in GetFeatureInfo request.
|
||||||
|
\param project the QGIS project
|
||||||
|
:return: if the geometry has to be segmentize in GetFeatureInfo request.
|
||||||
|
:rtype: bool
|
||||||
|
%End
|
||||||
|
|
||||||
|
int wmsFeatureInfoPrecision( const QgsProject &project );
|
||||||
|
%Docstring
|
||||||
|
Returns the geometry precision for GetFeatureInfo request.
|
||||||
|
\param project the QGIS project
|
||||||
|
:return: the geometry precision for GetFeatureInfo request.
|
||||||
|
:rtype: int
|
||||||
|
%End
|
||||||
|
|
||||||
|
QString wmsFeatureInfoDocumentElement( const QgsProject &project );
|
||||||
|
%Docstring
|
||||||
|
Returns the document element name for XML GetFeatureInfo request.
|
||||||
|
\param project the QGIS project
|
||||||
|
:return: the document element name for XML GetFeatureInfo request.
|
||||||
|
:rtype: str
|
||||||
|
%End
|
||||||
|
|
||||||
|
QString wmsFeatureInfoDocumentElementNs( const QgsProject &project );
|
||||||
|
%Docstring
|
||||||
|
Returns the document element namespace for XML GetFeatureInfo request.
|
||||||
|
\param project the QGIS project
|
||||||
|
:return: the document element namespace for XML GetFeatureInfo request.
|
||||||
|
:rtype: str
|
||||||
|
%End
|
||||||
|
|
||||||
|
QString wmsFeatureInfoSchema( const QgsProject &project );
|
||||||
|
%Docstring
|
||||||
|
Returns the schema URL for XML GetFeatureInfo request.
|
||||||
|
\param project the QGIS project
|
||||||
|
:return: the schema URL for XML GetFeatureInfo request.
|
||||||
|
:rtype: str
|
||||||
|
%End
|
||||||
|
|
||||||
|
QHash<QString, QString> wmsFeatureInfoLayerAliasMap( const QgsProject &project );
|
||||||
|
%Docstring
|
||||||
|
Returns the mapping between layer name and wms layer name for GetFeatureInfo request.
|
||||||
|
\param project the QGIS project
|
||||||
|
:return: the mapping between layer name and wms layer name for GetFeatureInfo request.
|
||||||
|
:rtype: QHash<str, QString>
|
||||||
|
%End
|
||||||
|
|
||||||
bool wmsInspireActivate( const QgsProject &project );
|
bool wmsInspireActivate( const QgsProject &project );
|
||||||
%Docstring
|
%Docstring
|
||||||
Returns if Inspire is activated.
|
Returns if Inspire is activated.
|
||||||
|
@ -117,6 +117,77 @@ bool QgsServerProjectUtils::wmsInfoFormatSia2045( const QgsProject &project )
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool QgsServerProjectUtils::wmsFeatureInfoAddWktGeometry( const QgsProject &project )
|
||||||
|
{
|
||||||
|
QString wktGeom = project.readEntry( QStringLiteral( "WMSAddWktGeometry" ), QStringLiteral( "/" ), "" );
|
||||||
|
|
||||||
|
if ( wktGeom.compare( QLatin1String( "enabled" ), Qt::CaseInsensitive ) == 0
|
||||||
|
|| wktGeom.compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0 )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QgsServerProjectUtils::wmsFeatureInfoSegmentizeWktGeometry( const QgsProject &project )
|
||||||
|
{
|
||||||
|
QString segmGeom = project.readEntry( QStringLiteral( "WMSSegmentizeFeatureInfoGeometry" ), QStringLiteral( "/" ), "" );
|
||||||
|
|
||||||
|
if ( segmGeom.compare( QLatin1String( "enabled" ), Qt::CaseInsensitive ) == 0
|
||||||
|
|| segmGeom.compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0 )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int QgsServerProjectUtils::wmsFeatureInfoPrecision( const QgsProject &project )
|
||||||
|
{
|
||||||
|
return project.readNumEntry( QStringLiteral( "WMSPrecision" ), QStringLiteral( "/" ), 6 );
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QgsServerProjectUtils::wmsFeatureInfoDocumentElement( const QgsProject &project )
|
||||||
|
{
|
||||||
|
return project.readEntry( QStringLiteral( "WMSFeatureInfoDocumentElement" ), QStringLiteral( "/" ), "" );
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QgsServerProjectUtils::wmsFeatureInfoDocumentElementNs( const QgsProject &project )
|
||||||
|
{
|
||||||
|
return project.readEntry( QStringLiteral( "WMSFeatureInfoDocumentElementNS" ), QStringLiteral( "/" ), "" );
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QgsServerProjectUtils::wmsFeatureInfoSchema( const QgsProject &project )
|
||||||
|
{
|
||||||
|
return project.readEntry( QStringLiteral( "WMSFeatureInfoSchema" ), QStringLiteral( "/" ), "" );
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<QString, QString> QgsServerProjectUtils::wmsFeatureInfoLayerAliasMap( const QgsProject &project )
|
||||||
|
{
|
||||||
|
QHash<QString, QString> aliasMap;
|
||||||
|
|
||||||
|
//WMSFeatureInfoAliasLayers
|
||||||
|
QStringList aliasLayerStringList = project.readListEntry( QStringLiteral( "WMSFeatureInfoAliasLayers" ), QStringLiteral( "/value" ), QStringList() );
|
||||||
|
if ( aliasLayerStringList.isEmpty() )
|
||||||
|
{
|
||||||
|
return aliasMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
//WMSFeatureInfoLayerAliases
|
||||||
|
QStringList layerAliasStringList = project.readListEntry( QStringLiteral( "WMSFeatureInfoLayerAliases" ), QStringLiteral( "/value" ), QStringList() );
|
||||||
|
if ( layerAliasStringList.isEmpty() )
|
||||||
|
{
|
||||||
|
return aliasMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nMapEntries = qMin( aliasLayerStringList.size(), layerAliasStringList.size() );
|
||||||
|
for ( int i = 0; i < nMapEntries; ++i )
|
||||||
|
{
|
||||||
|
aliasMap.insert( aliasLayerStringList.at( i ), layerAliasStringList.at( i ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return aliasMap;
|
||||||
|
}
|
||||||
|
|
||||||
bool QgsServerProjectUtils::wmsInspireActivate( const QgsProject &project )
|
bool QgsServerProjectUtils::wmsInspireActivate( const QgsProject &project )
|
||||||
{
|
{
|
||||||
return project.readBoolEntry( QStringLiteral( "WMSInspire" ), QStringLiteral( "/activated" ) );
|
return project.readBoolEntry( QStringLiteral( "WMSInspire" ), QStringLiteral( "/activated" ) );
|
||||||
|
@ -132,6 +132,48 @@ namespace QgsServerProjectUtils
|
|||||||
*/
|
*/
|
||||||
SERVER_EXPORT bool wmsInfoFormatSia2045( const QgsProject &project );
|
SERVER_EXPORT bool wmsInfoFormatSia2045( const QgsProject &project );
|
||||||
|
|
||||||
|
/** Returns if the geometry is displayed as Well Known Text in GetFeatureInfo request.
|
||||||
|
* \param project the QGIS project
|
||||||
|
* \returns if the geometry is displayed as Well Known Text in GetFeatureInfo request.
|
||||||
|
*/
|
||||||
|
SERVER_EXPORT bool wmsFeatureInfoAddWktGeometry( const QgsProject &project );
|
||||||
|
|
||||||
|
/** Returns if the geometry has to be segmentize in GetFeatureInfo request.
|
||||||
|
* \param project the QGIS project
|
||||||
|
* \returns if the geometry has to be segmentize in GetFeatureInfo request.
|
||||||
|
*/
|
||||||
|
SERVER_EXPORT bool wmsFeatureInfoSegmentizeWktGeometry( const QgsProject &project );
|
||||||
|
|
||||||
|
/** Returns the geometry precision for GetFeatureInfo request.
|
||||||
|
* \param project the QGIS project
|
||||||
|
* \returns the geometry precision for GetFeatureInfo request.
|
||||||
|
*/
|
||||||
|
SERVER_EXPORT int wmsFeatureInfoPrecision( const QgsProject &project );
|
||||||
|
|
||||||
|
/** Returns the document element name for XML GetFeatureInfo request.
|
||||||
|
* \param project the QGIS project
|
||||||
|
* \returns the document element name for XML GetFeatureInfo request.
|
||||||
|
*/
|
||||||
|
SERVER_EXPORT QString wmsFeatureInfoDocumentElement( const QgsProject &project );
|
||||||
|
|
||||||
|
/** Returns the document element namespace for XML GetFeatureInfo request.
|
||||||
|
* \param project the QGIS project
|
||||||
|
* \returns the document element namespace for XML GetFeatureInfo request.
|
||||||
|
*/
|
||||||
|
SERVER_EXPORT QString wmsFeatureInfoDocumentElementNs( const QgsProject &project );
|
||||||
|
|
||||||
|
/** Returns the schema URL for XML GetFeatureInfo request.
|
||||||
|
* \param project the QGIS project
|
||||||
|
* \returns the schema URL for XML GetFeatureInfo request.
|
||||||
|
*/
|
||||||
|
SERVER_EXPORT QString wmsFeatureInfoSchema( const QgsProject &project );
|
||||||
|
|
||||||
|
/** Returns the mapping between layer name and wms layer name for GetFeatureInfo request.
|
||||||
|
* \param project the QGIS project
|
||||||
|
* \returns the mapping between layer name and wms layer name for GetFeatureInfo request.
|
||||||
|
*/
|
||||||
|
SERVER_EXPORT QHash<QString, QString> wmsFeatureInfoLayerAliasMap( const QgsProject &project );
|
||||||
|
|
||||||
/** Returns if Inspire is activated.
|
/** Returns if Inspire is activated.
|
||||||
* \param project the QGIS project
|
* \param project the QGIS project
|
||||||
* \returns if Inspire is activated.
|
* \returns if Inspire is activated.
|
||||||
|
@ -25,136 +25,6 @@
|
|||||||
namespace QgsWms
|
namespace QgsWms
|
||||||
{
|
{
|
||||||
|
|
||||||
void writeInfoResponse( QDomDocument &infoDoc, QgsServerResponse &response, const QString &infoFormat )
|
|
||||||
{
|
|
||||||
QByteArray ba;
|
|
||||||
QgsMessageLog::logMessage( "Info format is:" + infoFormat );
|
|
||||||
|
|
||||||
if ( infoFormat == QLatin1String( "text/xml" ) || infoFormat.startsWith( QLatin1String( "application/vnd.ogc.gml" ) ) )
|
|
||||||
{
|
|
||||||
ba = infoDoc.toByteArray();
|
|
||||||
}
|
|
||||||
else if ( infoFormat == QLatin1String( "text/plain" ) || infoFormat == QLatin1String( "text/html" ) )
|
|
||||||
{
|
|
||||||
//create string
|
|
||||||
QString featureInfoString;
|
|
||||||
|
|
||||||
if ( infoFormat == QLatin1String( "text/plain" ) )
|
|
||||||
{
|
|
||||||
featureInfoString.append( "GetFeatureInfo results\n" );
|
|
||||||
featureInfoString.append( "\n" );
|
|
||||||
}
|
|
||||||
else if ( infoFormat == QLatin1String( "text/html" ) )
|
|
||||||
{
|
|
||||||
featureInfoString.append( "<HEAD>\n" );
|
|
||||||
featureInfoString.append( "<TITLE> GetFeatureInfo results </TITLE>\n" );
|
|
||||||
featureInfoString.append( "<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\">\n" );
|
|
||||||
featureInfoString.append( "</HEAD>\n" );
|
|
||||||
featureInfoString.append( "<BODY>\n" );
|
|
||||||
}
|
|
||||||
|
|
||||||
QDomNodeList layerList = infoDoc.elementsByTagName( QStringLiteral( "Layer" ) );
|
|
||||||
|
|
||||||
//layer loop
|
|
||||||
for ( int i = 0; i < layerList.size(); ++i )
|
|
||||||
{
|
|
||||||
QDomElement layerElem = layerList.at( i ).toElement();
|
|
||||||
if ( infoFormat == QLatin1String( "text/plain" ) )
|
|
||||||
{
|
|
||||||
featureInfoString.append( "Layer '" + layerElem.attribute( QStringLiteral( "name" ) ) + "'\n" );
|
|
||||||
}
|
|
||||||
else if ( infoFormat == QLatin1String( "text/html" ) )
|
|
||||||
{
|
|
||||||
featureInfoString.append( "<TABLE border=1 width=100%>\n" );
|
|
||||||
featureInfoString.append( "<TR><TH width=25%>Layer</TH><TD>" + layerElem.attribute( QStringLiteral( "name" ) ) + "</TD></TR>\n" );
|
|
||||||
featureInfoString.append( "</BR>" );
|
|
||||||
}
|
|
||||||
|
|
||||||
//feature loop (for vector layers)
|
|
||||||
QDomNodeList featureNodeList = layerElem.elementsByTagName( QStringLiteral( "Feature" ) );
|
|
||||||
QDomElement currentFeatureElement;
|
|
||||||
|
|
||||||
if ( featureNodeList.isEmpty() ) //raster layer?
|
|
||||||
{
|
|
||||||
QDomNodeList attributeNodeList = layerElem.elementsByTagName( QStringLiteral( "Attribute" ) );
|
|
||||||
for ( int j = 0; j < attributeNodeList.size(); ++j )
|
|
||||||
{
|
|
||||||
QDomElement attributeElement = attributeNodeList.at( j ).toElement();
|
|
||||||
if ( infoFormat == QLatin1String( "text/plain" ) )
|
|
||||||
{
|
|
||||||
featureInfoString.append( attributeElement.attribute( QStringLiteral( "name" ) ) + " = '" +
|
|
||||||
attributeElement.attribute( QStringLiteral( "value" ) ) + "'\n" );
|
|
||||||
}
|
|
||||||
else if ( infoFormat == QLatin1String( "text/html" ) )
|
|
||||||
{
|
|
||||||
featureInfoString.append( "<TR><TH>" + attributeElement.attribute( QStringLiteral( "name" ) ) + "</TH><TD>" +
|
|
||||||
attributeElement.attribute( QStringLiteral( "value" ) ) + "</TD></TR>\n" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else //vector layer
|
|
||||||
{
|
|
||||||
for ( int j = 0; j < featureNodeList.size(); ++j )
|
|
||||||
{
|
|
||||||
QDomElement featureElement = featureNodeList.at( j ).toElement();
|
|
||||||
if ( infoFormat == QLatin1String( "text/plain" ) )
|
|
||||||
{
|
|
||||||
featureInfoString.append( "Feature " + featureElement.attribute( QStringLiteral( "id" ) ) + "\n" );
|
|
||||||
}
|
|
||||||
else if ( infoFormat == QLatin1String( "text/html" ) )
|
|
||||||
{
|
|
||||||
featureInfoString.append( "<TABLE border=1 width=100%>\n" );
|
|
||||||
featureInfoString.append( "<TR><TH>Feature</TH><TD>" + featureElement.attribute( QStringLiteral( "id" ) ) + "</TD></TR>\n" );
|
|
||||||
}
|
|
||||||
//attribute loop
|
|
||||||
QDomNodeList attributeNodeList = featureElement.elementsByTagName( QStringLiteral( "Attribute" ) );
|
|
||||||
for ( int k = 0; k < attributeNodeList.size(); ++k )
|
|
||||||
{
|
|
||||||
QDomElement attributeElement = attributeNodeList.at( k ).toElement();
|
|
||||||
if ( infoFormat == QLatin1String( "text/plain" ) )
|
|
||||||
{
|
|
||||||
featureInfoString.append( attributeElement.attribute( QStringLiteral( "name" ) ) + " = '" +
|
|
||||||
attributeElement.attribute( QStringLiteral( "value" ) ) + "'\n" );
|
|
||||||
}
|
|
||||||
else if ( infoFormat == QLatin1String( "text/html" ) )
|
|
||||||
{
|
|
||||||
featureInfoString.append( "<TR><TH>" + attributeElement.attribute( QStringLiteral( "name" ) ) + "</TH><TD>" + attributeElement.attribute( QStringLiteral( "value" ) ) + "</TD></TR>\n" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( infoFormat == QLatin1String( "text/html" ) )
|
|
||||||
{
|
|
||||||
featureInfoString.append( "</TABLE>\n</BR>\n" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( infoFormat == QLatin1String( "text/plain" ) )
|
|
||||||
{
|
|
||||||
featureInfoString.append( "\n" );
|
|
||||||
}
|
|
||||||
else if ( infoFormat == QLatin1String( "text/html" ) )
|
|
||||||
{
|
|
||||||
featureInfoString.append( "</TABLE>\n<BR></BR>\n" );
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( infoFormat == QLatin1String( "text/html" ) )
|
|
||||||
{
|
|
||||||
featureInfoString.append( "</BODY>\n" );
|
|
||||||
}
|
|
||||||
ba = featureInfoString.toUtf8();
|
|
||||||
}
|
|
||||||
else //unsupported format, set exception
|
|
||||||
{
|
|
||||||
throw QgsServiceException( QStringLiteral( "InvalidFormat" ),
|
|
||||||
QString( "Feature info format '%1' is not supported. Possibilities are 'text/plain', 'text/html' or 'text/xml'." ).arg( infoFormat ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
response.setHeader( QStringLiteral( "Content-Type" ), infoFormat + QStringLiteral( "; charset=utf-8" ) );
|
|
||||||
response.write( ba );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void writeGetFeatureInfo( QgsServerInterface *serverIface, const QgsProject *project,
|
void writeGetFeatureInfo( QgsServerInterface *serverIface, const QgsProject *project,
|
||||||
const QString &version, const QgsServerRequest &request,
|
const QString &version, const QgsServerRequest &request,
|
||||||
QgsServerResponse &response )
|
QgsServerResponse &response )
|
||||||
@ -163,9 +33,11 @@ namespace QgsWms
|
|||||||
QgsServerRequest::Parameters params = request.parameters();
|
QgsServerRequest::Parameters params = request.parameters();
|
||||||
QgsRenderer renderer( serverIface, project, params, getConfigParser( serverIface ) );
|
QgsRenderer renderer( serverIface, project, params, getConfigParser( serverIface ) );
|
||||||
|
|
||||||
QDomDocument doc = renderer.getFeatureInfo( version );
|
std::unique_ptr<QByteArray> result( renderer.getFeatureInfo( version ) );
|
||||||
QString outputFormat = params.value( QStringLiteral( "INFO_FORMAT" ), QStringLiteral( "text/plain" ) );
|
QString infoFormat = params.value( QStringLiteral( "INFO_FORMAT" ), QStringLiteral( "text/plain" ) );
|
||||||
writeInfoResponse( doc, response, outputFormat );
|
|
||||||
|
response.setHeader( QStringLiteral( "Content-Type" ), infoFormat + QStringLiteral( "; charset=utf-8" ) );
|
||||||
|
response.write( *result );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -191,6 +191,41 @@ namespace QgsWms
|
|||||||
};
|
};
|
||||||
save( pFormat );
|
save( pFormat );
|
||||||
|
|
||||||
|
const Parameter pInfoFormat = { ParameterName::INFO_FORMAT,
|
||||||
|
QVariant::String,
|
||||||
|
QVariant( "" ),
|
||||||
|
QVariant()
|
||||||
|
};
|
||||||
|
save( pInfoFormat );
|
||||||
|
|
||||||
|
const Parameter pI = { ParameterName::I,
|
||||||
|
QVariant::Int,
|
||||||
|
QVariant( -1 ),
|
||||||
|
QVariant()
|
||||||
|
};
|
||||||
|
save( pI );
|
||||||
|
|
||||||
|
const Parameter pJ = { ParameterName::J,
|
||||||
|
QVariant::Int,
|
||||||
|
QVariant( -1 ),
|
||||||
|
QVariant()
|
||||||
|
};
|
||||||
|
save( pJ );
|
||||||
|
|
||||||
|
const Parameter pX = { ParameterName::X,
|
||||||
|
QVariant::Int,
|
||||||
|
QVariant( -1 ),
|
||||||
|
QVariant()
|
||||||
|
};
|
||||||
|
save( pX );
|
||||||
|
|
||||||
|
const Parameter pY = { ParameterName::Y,
|
||||||
|
QVariant::Int,
|
||||||
|
QVariant( -1 ),
|
||||||
|
QVariant()
|
||||||
|
};
|
||||||
|
save( pY );
|
||||||
|
|
||||||
const Parameter pRule = { ParameterName::RULE,
|
const Parameter pRule = { ParameterName::RULE,
|
||||||
QVariant::String,
|
QVariant::String,
|
||||||
QVariant( "" ),
|
QVariant( "" ),
|
||||||
@ -254,6 +289,20 @@ namespace QgsWms
|
|||||||
};
|
};
|
||||||
save( pLayers );
|
save( pLayers );
|
||||||
|
|
||||||
|
const Parameter pQueryLayers = { ParameterName::QUERY_LAYERS,
|
||||||
|
QVariant::String,
|
||||||
|
QVariant( "" ),
|
||||||
|
QVariant()
|
||||||
|
};
|
||||||
|
save( pQueryLayers );
|
||||||
|
|
||||||
|
const Parameter pFeatureCount = { ParameterName::FEATURE_COUNT,
|
||||||
|
QVariant::Int,
|
||||||
|
QVariant( 1 ),
|
||||||
|
QVariant()
|
||||||
|
};
|
||||||
|
save( pFeatureCount );
|
||||||
|
|
||||||
const Parameter pLayerTitle = { ParameterName::LAYERTITLE,
|
const Parameter pLayerTitle = { ParameterName::LAYERTITLE,
|
||||||
QVariant::Bool,
|
QVariant::Bool,
|
||||||
QVariant( true ),
|
QVariant( true ),
|
||||||
@ -324,12 +373,26 @@ namespace QgsWms
|
|||||||
};
|
};
|
||||||
save( pFilter );
|
save( pFilter );
|
||||||
|
|
||||||
|
const Parameter pFilterGeom = { ParameterName::FILTER_GEOM,
|
||||||
|
QVariant::String,
|
||||||
|
QVariant( "" ),
|
||||||
|
QVariant()
|
||||||
|
};
|
||||||
|
save( pFilterGeom );
|
||||||
|
|
||||||
const Parameter pSelection = { ParameterName::SELECTION,
|
const Parameter pSelection = { ParameterName::SELECTION,
|
||||||
QVariant::String,
|
QVariant::String,
|
||||||
QVariant( "" ),
|
QVariant( "" ),
|
||||||
QVariant()
|
QVariant()
|
||||||
};
|
};
|
||||||
save( pSelection );
|
save( pSelection );
|
||||||
|
|
||||||
|
const Parameter pWmsPrecision = { ParameterName::WMS_PRECISION,
|
||||||
|
QVariant::Int,
|
||||||
|
QVariant( -1 ),
|
||||||
|
QVariant()
|
||||||
|
};
|
||||||
|
save( pWmsPrecision );
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsWmsParameters::QgsWmsParameters( const QgsServerRequest::Parameters ¶meters )
|
QgsWmsParameters::QgsWmsParameters( const QgsServerRequest::Parameters ¶meters )
|
||||||
@ -628,9 +691,12 @@ namespace QgsWms
|
|||||||
|
|
||||||
QgsWmsParameters::Format QgsWmsParameters::format() const
|
QgsWmsParameters::Format QgsWmsParameters::format() const
|
||||||
{
|
{
|
||||||
Format f = Format::PNG;
|
|
||||||
QString fStr = formatAsString();
|
QString fStr = formatAsString();
|
||||||
|
|
||||||
|
if ( fStr.isEmpty() )
|
||||||
|
return Format::NONE;
|
||||||
|
|
||||||
|
Format f = Format::PNG;
|
||||||
if ( fStr.compare( QLatin1String( "jpg" ), Qt::CaseInsensitive ) == 0
|
if ( fStr.compare( QLatin1String( "jpg" ), Qt::CaseInsensitive ) == 0
|
||||||
|| fStr.compare( QLatin1String( "jpeg" ), Qt::CaseInsensitive ) == 0
|
|| fStr.compare( QLatin1String( "jpeg" ), Qt::CaseInsensitive ) == 0
|
||||||
|| fStr.compare( QLatin1String( "image/jpeg" ), Qt::CaseInsensitive ) == 0 )
|
|| fStr.compare( QLatin1String( "image/jpeg" ), Qt::CaseInsensitive ) == 0 )
|
||||||
@ -639,6 +705,81 @@ namespace QgsWms
|
|||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString QgsWmsParameters::infoFormatAsString() const
|
||||||
|
{
|
||||||
|
return value( ParameterName::INFO_FORMAT ).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsWmsParameters::Format QgsWmsParameters::infoFormat() const
|
||||||
|
{
|
||||||
|
QString fStr = infoFormatAsString();
|
||||||
|
|
||||||
|
Format f = Format::TEXT;
|
||||||
|
if ( fStr.isEmpty() )
|
||||||
|
return f;
|
||||||
|
|
||||||
|
if ( fStr.startsWith( QLatin1String( "text/xml" ), Qt::CaseInsensitive ) )
|
||||||
|
f = Format::XML;
|
||||||
|
else if ( fStr.startsWith( QLatin1String( "text/html" ), Qt::CaseInsensitive ) )
|
||||||
|
f = Format::HTML;
|
||||||
|
else if ( fStr.startsWith( QLatin1String( "application/vnd.ogc.gml" ), Qt::CaseInsensitive ) )
|
||||||
|
f = Format::GML;
|
||||||
|
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
int QgsWmsParameters::infoFormatVersion() const
|
||||||
|
{
|
||||||
|
if ( infoFormat() != Format::GML )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
QString fStr = infoFormatAsString();
|
||||||
|
if ( fStr.startsWith( QLatin1String( "application/vnd.ogc.gml/3" ), Qt::CaseInsensitive ) )
|
||||||
|
return 3;
|
||||||
|
else
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QgsWmsParameters::i() const
|
||||||
|
{
|
||||||
|
return value( ParameterName::I ).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QgsWmsParameters::j() const
|
||||||
|
{
|
||||||
|
return value( ParameterName::J ).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
int QgsWmsParameters::iAsInt() const
|
||||||
|
{
|
||||||
|
return toInt( ParameterName::I );
|
||||||
|
}
|
||||||
|
|
||||||
|
int QgsWmsParameters::jAsInt() const
|
||||||
|
{
|
||||||
|
return toInt( ParameterName::J );
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QgsWmsParameters::x() const
|
||||||
|
{
|
||||||
|
return value( ParameterName::X ).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QgsWmsParameters::y() const
|
||||||
|
{
|
||||||
|
return value( ParameterName::Y ).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
int QgsWmsParameters::xAsInt() const
|
||||||
|
{
|
||||||
|
return toInt( ParameterName::X );
|
||||||
|
}
|
||||||
|
|
||||||
|
int QgsWmsParameters::yAsInt() const
|
||||||
|
{
|
||||||
|
return toInt( ParameterName::Y );
|
||||||
|
}
|
||||||
|
|
||||||
QString QgsWmsParameters::rule() const
|
QString QgsWmsParameters::rule() const
|
||||||
{
|
{
|
||||||
return value( ParameterName::RULE ).toString();
|
return value( ParameterName::RULE ).toString();
|
||||||
@ -674,6 +815,16 @@ namespace QgsWms
|
|||||||
return toBool( ParameterName::SHOWFEATURECOUNT );
|
return toBool( ParameterName::SHOWFEATURECOUNT );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString QgsWmsParameters::featureCount() const
|
||||||
|
{
|
||||||
|
return value( ParameterName::FEATURE_COUNT ).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
int QgsWmsParameters::featureCountAsInt() const
|
||||||
|
{
|
||||||
|
return toInt( ParameterName::FEATURE_COUNT );
|
||||||
|
}
|
||||||
|
|
||||||
QString QgsWmsParameters::boxSpace() const
|
QString QgsWmsParameters::boxSpace() const
|
||||||
{
|
{
|
||||||
return value( ParameterName::BOXSPACE ).toString();
|
return value( ParameterName::BOXSPACE ).toString();
|
||||||
@ -960,6 +1111,16 @@ namespace QgsWms
|
|||||||
return toFloatList( highlightLabelBufferSize(), ParameterName::HIGHLIGHT_LABELBUFFERSIZE );
|
return toFloatList( highlightLabelBufferSize(), ParameterName::HIGHLIGHT_LABELBUFFERSIZE );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString QgsWmsParameters::wmsPrecision() const
|
||||||
|
{
|
||||||
|
return value( ParameterName::WMS_PRECISION ).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
int QgsWmsParameters::wmsPrecisionAsInt() const
|
||||||
|
{
|
||||||
|
return toInt( ParameterName::WMS_PRECISION );
|
||||||
|
}
|
||||||
|
|
||||||
QString QgsWmsParameters::sld() const
|
QString QgsWmsParameters::sld() const
|
||||||
{
|
{
|
||||||
return value( ParameterName::SLD ).toString();
|
return value( ParameterName::SLD ).toString();
|
||||||
@ -970,6 +1131,11 @@ namespace QgsWms
|
|||||||
return toStringList( ParameterName::FILTER, ';' );
|
return toStringList( ParameterName::FILTER, ';' );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString QgsWmsParameters::filterGeom() const
|
||||||
|
{
|
||||||
|
return value( ParameterName::FILTER_GEOM ).toString();
|
||||||
|
}
|
||||||
|
|
||||||
QStringList QgsWmsParameters::selections() const
|
QStringList QgsWmsParameters::selections() const
|
||||||
{
|
{
|
||||||
return toStringList( ParameterName::SELECTION );
|
return toStringList( ParameterName::SELECTION );
|
||||||
@ -992,6 +1158,11 @@ namespace QgsWms
|
|||||||
return layer << layers;
|
return layer << layers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList QgsWmsParameters::queryLayersNickname() const
|
||||||
|
{
|
||||||
|
return toStringList( ParameterName::QUERY_LAYERS );
|
||||||
|
}
|
||||||
|
|
||||||
QStringList QgsWmsParameters::allStyles() const
|
QStringList QgsWmsParameters::allStyles() const
|
||||||
{
|
{
|
||||||
QStringList style = value( ParameterName::STYLE ).toString().split( ",", QString::SkipEmptyParts );
|
QStringList style = value( ParameterName::STYLE ).toString().split( ",", QString::SkipEmptyParts );
|
||||||
|
@ -86,6 +86,8 @@ namespace QgsWms
|
|||||||
LAYERS,
|
LAYERS,
|
||||||
LAYERSPACE,
|
LAYERSPACE,
|
||||||
LAYERTITLESPACE,
|
LAYERTITLESPACE,
|
||||||
|
QUERY_LAYERS,
|
||||||
|
FEATURE_COUNT,
|
||||||
SHOWFEATURECOUNT,
|
SHOWFEATURECOUNT,
|
||||||
STYLE,
|
STYLE,
|
||||||
STYLES,
|
STYLES,
|
||||||
@ -95,7 +97,13 @@ namespace QgsWms
|
|||||||
OPACITIES,
|
OPACITIES,
|
||||||
SLD,
|
SLD,
|
||||||
FILTER,
|
FILTER,
|
||||||
|
FILTER_GEOM,
|
||||||
FORMAT,
|
FORMAT,
|
||||||
|
INFO_FORMAT,
|
||||||
|
I,
|
||||||
|
J,
|
||||||
|
X,
|
||||||
|
Y,
|
||||||
RULE,
|
RULE,
|
||||||
RULELABEL,
|
RULELABEL,
|
||||||
SCALE,
|
SCALE,
|
||||||
@ -108,7 +116,8 @@ namespace QgsWms
|
|||||||
HIGHLIGHT_LABELWEIGHT,
|
HIGHLIGHT_LABELWEIGHT,
|
||||||
HIGHLIGHT_LABELCOLOR,
|
HIGHLIGHT_LABELCOLOR,
|
||||||
HIGHLIGHT_LABELBUFFERCOLOR,
|
HIGHLIGHT_LABELBUFFERCOLOR,
|
||||||
HIGHLIGHT_LABELBUFFERSIZE
|
HIGHLIGHT_LABELBUFFERSIZE,
|
||||||
|
WMS_PRECISION
|
||||||
};
|
};
|
||||||
Q_ENUM( ParameterName )
|
Q_ENUM( ParameterName )
|
||||||
|
|
||||||
@ -116,7 +125,11 @@ namespace QgsWms
|
|||||||
{
|
{
|
||||||
NONE,
|
NONE,
|
||||||
JPG,
|
JPG,
|
||||||
PNG
|
PNG,
|
||||||
|
TEXT,
|
||||||
|
XML,
|
||||||
|
HTML,
|
||||||
|
GML
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Parameter
|
struct Parameter
|
||||||
@ -203,6 +216,11 @@ namespace QgsWms
|
|||||||
*/
|
*/
|
||||||
QStringList filters() const;
|
QStringList filters() const;
|
||||||
|
|
||||||
|
/** Returns the filter geometry found in FILTER_GEOM parameter.
|
||||||
|
* \returns the filter geometry as Well Known Text.
|
||||||
|
*/
|
||||||
|
QString filterGeom() const;
|
||||||
|
|
||||||
/** Returns the list of opacities found in OPACITIES parameter.
|
/** Returns the list of opacities found in OPACITIES parameter.
|
||||||
* \returns the list of opacities in string
|
* \returns the list of opacities in string
|
||||||
*/
|
*/
|
||||||
@ -221,6 +239,11 @@ namespace QgsWms
|
|||||||
*/
|
*/
|
||||||
QStringList allLayersNickname() const;
|
QStringList allLayersNickname() const;
|
||||||
|
|
||||||
|
/** Returns nickname of layers found in QUERY_LAYERS parameter.
|
||||||
|
* \returns nickname of layers
|
||||||
|
*/
|
||||||
|
QStringList queryLayersNickname() const;
|
||||||
|
|
||||||
/** Returns styles found in STYLE and STYLES parameters.
|
/** Returns styles found in STYLE and STYLES parameters.
|
||||||
* \returns name of styles
|
* \returns name of styles
|
||||||
*/
|
*/
|
||||||
@ -242,6 +265,75 @@ namespace QgsWms
|
|||||||
*/
|
*/
|
||||||
Format format() const;
|
Format format() const;
|
||||||
|
|
||||||
|
/** Returns INFO_FORMAT parameter as a string.
|
||||||
|
* \returns INFO_FORMAT parameter as string
|
||||||
|
*/
|
||||||
|
QString infoFormatAsString() const;
|
||||||
|
|
||||||
|
/** Returns infoFormat. If the INFO_FORMAT parameter is not used, then the
|
||||||
|
* default value is text/plain.
|
||||||
|
* \returns infoFormat
|
||||||
|
*/
|
||||||
|
Format infoFormat() const;
|
||||||
|
|
||||||
|
/** Returns the infoFormat version for GML. If the INFO_FORMAT is not GML,
|
||||||
|
* then the default value is -1.
|
||||||
|
* \returns infoFormat version
|
||||||
|
*/
|
||||||
|
int infoFormatVersion() const;
|
||||||
|
|
||||||
|
/** Returns I parameter or an empty string if not defined.
|
||||||
|
* \returns i parameter
|
||||||
|
*/
|
||||||
|
QString i() const;
|
||||||
|
|
||||||
|
/** Returns I parameter as an int or its default value if not
|
||||||
|
* defined. An exception is raised if I is defined and cannot be
|
||||||
|
* converted.
|
||||||
|
* \returns i parameter
|
||||||
|
* \throws QgsBadRequestException
|
||||||
|
*/
|
||||||
|
int iAsInt() const;
|
||||||
|
|
||||||
|
/** Returns J parameter or an empty string if not defined.
|
||||||
|
* \returns j parameter
|
||||||
|
*/
|
||||||
|
QString j() const;
|
||||||
|
|
||||||
|
/** Returns J parameter as an int or its default value if not
|
||||||
|
* defined. An exception is raised if J is defined and cannot be
|
||||||
|
* converted.
|
||||||
|
* \returns j parameter
|
||||||
|
* \throws QgsBadRequestException
|
||||||
|
*/
|
||||||
|
int jAsInt() const;
|
||||||
|
|
||||||
|
/** Returns X parameter or an empty string if not defined.
|
||||||
|
* \returns x parameter
|
||||||
|
*/
|
||||||
|
QString x() const;
|
||||||
|
|
||||||
|
/** Returns X parameter as an int or its default value if not
|
||||||
|
* defined. An exception is raised if X is defined and cannot be
|
||||||
|
* converted.
|
||||||
|
* \returns x parameter
|
||||||
|
* \throws QgsBadRequestException
|
||||||
|
*/
|
||||||
|
int xAsInt() const;
|
||||||
|
|
||||||
|
/** Returns Y parameter or an empty string if not defined.
|
||||||
|
* \returns y parameter
|
||||||
|
*/
|
||||||
|
QString y() const;
|
||||||
|
|
||||||
|
/** Returns Y parameter as an int or its default value if not
|
||||||
|
* defined. An exception is raised if Y is defined and cannot be
|
||||||
|
* converted.
|
||||||
|
* \returns j parameter
|
||||||
|
* \throws QgsBadRequestException
|
||||||
|
*/
|
||||||
|
int yAsInt() const;
|
||||||
|
|
||||||
/** Returns RULE parameter or an empty string if none is defined
|
/** Returns RULE parameter or an empty string if none is defined
|
||||||
* \returns RULE parameter or an empty string if none is defined
|
* \returns RULE parameter or an empty string if none is defined
|
||||||
*/
|
*/
|
||||||
@ -271,6 +363,18 @@ namespace QgsWms
|
|||||||
*/
|
*/
|
||||||
bool showFeatureCountAsBool() const;
|
bool showFeatureCountAsBool() const;
|
||||||
|
|
||||||
|
/** Returns FEATURE_COUNT parameter or an empty string if none is defined
|
||||||
|
* \returns FEATURE_COUNT parameter or an empty string if none is defined
|
||||||
|
*/
|
||||||
|
QString featureCount() const;
|
||||||
|
|
||||||
|
/** Returns FEATURE_COUNT as an integer. An exception is raised if an invalid
|
||||||
|
* parameter is found.
|
||||||
|
* \returns FeatureCount
|
||||||
|
* \throws QgsBadRequestException
|
||||||
|
*/
|
||||||
|
int featureCountAsInt() const;
|
||||||
|
|
||||||
/** Returns SCALE parameter or an empty string if none is defined
|
/** Returns SCALE parameter or an empty string if none is defined
|
||||||
* \returns SCALE parameter or an empty string if none is defined
|
* \returns SCALE parameter or an empty string if none is defined
|
||||||
*/
|
*/
|
||||||
@ -595,6 +699,19 @@ namespace QgsWms
|
|||||||
*/
|
*/
|
||||||
QList<QColor> highlightLabelBufferColorAsColor() const;
|
QList<QColor> highlightLabelBufferColorAsColor() const;
|
||||||
|
|
||||||
|
/** Returns WMS_PRECISION parameter or an empty string if not defined.
|
||||||
|
* \returns wms precision parameter
|
||||||
|
*/
|
||||||
|
QString wmsPrecision() const;
|
||||||
|
|
||||||
|
/** Returns WMS_PRECISION parameter as an int or its default value if not
|
||||||
|
* defined. An exception is raised if WMS_PRECISION is defined and cannot be
|
||||||
|
* converted.
|
||||||
|
* \returns wms precision parameter
|
||||||
|
* \throws QgsBadRequestException
|
||||||
|
*/
|
||||||
|
int wmsPrecisionAsInt() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString name( ParameterName name ) const;
|
QString name( ParameterName name ) const;
|
||||||
void raiseError( ParameterName name ) const;
|
void raiseError( ParameterName name ) const;
|
||||||
|
@ -642,322 +642,111 @@ namespace QgsWms
|
|||||||
infoPoint->setY( mapSettings.extent().yMaximum() - j * yRes - yRes / 2.0 );
|
infoPoint->setY( mapSettings.extent().yMaximum() - j * yRes - yRes / 2.0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
QDomDocument QgsRenderer::getFeatureInfo( const QString &version )
|
QByteArray *QgsRenderer::getFeatureInfo( const QString &version )
|
||||||
{
|
{
|
||||||
if ( !mConfigParser )
|
// Verifying Mandatory parameters
|
||||||
|
// The QUERY_LAYERS parameter is Mandatory
|
||||||
|
QStringList queryLayers = mWmsParameters.queryLayersNickname();
|
||||||
|
if ( queryLayers.isEmpty() )
|
||||||
{
|
{
|
||||||
throw QgsException( QStringLiteral( "No config parser" ) );
|
throw QgsBadRequestException( QStringLiteral( "ParameterMissing" ),
|
||||||
|
QStringLiteral( "QUERY_LAYERS parameter is required for GetFeatureInfo" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
QDomDocument result;
|
// The I/J parameters are Mandatory if they are not replaced by X/Y or FILTER or FILTER_GEOM
|
||||||
QStringList layersList, stylesList;
|
bool ijDefined = false;
|
||||||
bool conversionSuccess;
|
if ( !mWmsParameters.i().isEmpty() && !mWmsParameters.j().isEmpty() )
|
||||||
|
ijDefined = true;
|
||||||
|
|
||||||
for ( auto it = mParameters.constBegin(); it != mParameters.constEnd(); ++it )
|
bool xyDefined = false;
|
||||||
{
|
if ( !mWmsParameters.x().isEmpty() && !mWmsParameters.y().isEmpty() )
|
||||||
QgsMessageLog::logMessage( QStringLiteral( "%1 // %2" ).arg( it.key(), it.value() ) );
|
xyDefined = true;
|
||||||
}
|
|
||||||
|
|
||||||
readLayersAndStyles( mParameters, layersList, stylesList );
|
bool filtersDefined = false;
|
||||||
initializeSLDParser( layersList, stylesList );
|
if ( !mWmsParameters.filters().isEmpty() )
|
||||||
|
filtersDefined = true;
|
||||||
|
|
||||||
QgsMapSettings mapSettings;
|
bool filterGeomDefined = false;
|
||||||
std::unique_ptr<QImage> outputImage( createImage() );
|
if ( !mWmsParameters.filterGeom().isEmpty() )
|
||||||
|
filterGeomDefined = true;
|
||||||
|
|
||||||
configureMapSettings( outputImage.get(), mapSettings );
|
if ( !ijDefined && !xyDefined && !filtersDefined && !filterGeomDefined )
|
||||||
|
|
||||||
QgsMessageLog::logMessage( "mapSettings.extent(): " + mapSettings.extent().toString() );
|
|
||||||
QgsMessageLog::logMessage( QStringLiteral( "mapSettings width = %1 height = %2" ).arg( mapSettings.outputSize().width() ).arg( mapSettings.outputSize().height() ) );
|
|
||||||
QgsMessageLog::logMessage( QStringLiteral( "mapSettings.mapUnitsPerPixel() = %1" ).arg( mapSettings.mapUnitsPerPixel() ) );
|
|
||||||
|
|
||||||
//find out the current scale denominator and set it to the SLD parser
|
|
||||||
QgsScaleCalculator scaleCalc( ( outputImage->logicalDpiX() + outputImage->logicalDpiY() ) / 2, mapSettings.destinationCrs().mapUnits() );
|
|
||||||
QgsRectangle mapExtent = mapSettings.extent();
|
|
||||||
double scaleDenominator = scaleCalc.calculate( mapExtent, outputImage->width() );
|
|
||||||
mConfigParser->setScaleDenominator( scaleDenominator );
|
|
||||||
|
|
||||||
//read FEATURE_COUNT
|
|
||||||
int featureCount = 1;
|
|
||||||
if ( mParameters.contains( QStringLiteral( "FEATURE_COUNT" ) ) )
|
|
||||||
{
|
|
||||||
featureCount = mParameters[ QStringLiteral( "FEATURE_COUNT" )].toInt( &conversionSuccess );
|
|
||||||
if ( !conversionSuccess )
|
|
||||||
{
|
|
||||||
featureCount = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//read QUERY_LAYERS
|
|
||||||
if ( !mParameters.contains( QStringLiteral( "QUERY_LAYERS" ) ) )
|
|
||||||
{
|
|
||||||
throw QgsBadRequestException( QStringLiteral( "ParameterMissing" ), QStringLiteral( "No QUERY_LAYERS" ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList queryLayerList = mParameters[ QStringLiteral( "QUERY_LAYERS" )].split( ',', QString::SkipEmptyParts );
|
|
||||||
if ( queryLayerList.isEmpty() )
|
|
||||||
{
|
|
||||||
throw QgsBadRequestException( QStringLiteral( "InvalidParameterValue" ), QStringLiteral( "Malformed QUERY_LAYERS" ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
//read I,J resp. X,Y
|
|
||||||
QString iString = mParameters.value( QStringLiteral( "I" ), mParameters.value( QStringLiteral( "X" ) ) );
|
|
||||||
int i = iString.toInt( &conversionSuccess );
|
|
||||||
if ( !conversionSuccess )
|
|
||||||
{
|
|
||||||
i = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString jString = mParameters.value( QStringLiteral( "J" ), mParameters.value( QStringLiteral( "Y" ) ) );
|
|
||||||
int j = jString.toInt( &conversionSuccess );
|
|
||||||
if ( !conversionSuccess )
|
|
||||||
{
|
|
||||||
j = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//read FILTER_GEOM
|
|
||||||
std::unique_ptr<QgsGeometry> filterGeom;
|
|
||||||
if ( mParameters.contains( QStringLiteral( "FILTER_GEOM" ) ) )
|
|
||||||
{
|
|
||||||
filterGeom.reset( new QgsGeometry( QgsGeometry::fromWkt( mParameters.value( QStringLiteral( "FILTER_GEOM" ) ) ) ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
//In case the output image is distorted (WIDTH/HEIGHT ratio not equal to BBOX width/height), I and J need to be adapted as well
|
|
||||||
int widthParam = mParameters.value( "WIDTH", "-1" ).toInt();
|
|
||||||
int heightParam = mParameters.value( "HEIGHT", "-1" ).toInt();
|
|
||||||
if ( ( i != -1 && j != -1 && widthParam != -1 && heightParam != -1 ) && ( widthParam != outputImage->width() || heightParam != outputImage->height() ) )
|
|
||||||
{
|
|
||||||
i *= ( outputImage->width() / ( double )widthParam );
|
|
||||||
j *= ( outputImage->height() / ( double )heightParam );
|
|
||||||
}
|
|
||||||
|
|
||||||
//Normally, I/J or X/Y are mandatory parameters.
|
|
||||||
//However, in order to make attribute only queries via the FILTER parameter, it is allowed to skip them if the FILTER parameter is there
|
|
||||||
|
|
||||||
std::unique_ptr<QgsRectangle> featuresRect;
|
|
||||||
std::unique_ptr<QgsPointXY> infoPoint;
|
|
||||||
|
|
||||||
if ( i == -1 || j == -1 )
|
|
||||||
{
|
|
||||||
if ( mParameters.contains( QStringLiteral( "FILTER" ) ) )
|
|
||||||
{
|
|
||||||
featuresRect.reset( new QgsRectangle() );
|
|
||||||
}
|
|
||||||
else if ( !filterGeom.get() )
|
|
||||||
{
|
{
|
||||||
throw QgsBadRequestException( QStringLiteral( "ParameterMissing" ),
|
throw QgsBadRequestException( QStringLiteral( "ParameterMissing" ),
|
||||||
QStringLiteral( "I/J parameters are required for GetFeatureInfo" ) );
|
QStringLiteral( "I/J parameters are required for GetFeatureInfo" ) );
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// get layers parameters
|
||||||
|
QList<QgsMapLayer *> layers;
|
||||||
|
QList<QgsWmsParametersLayer> params = mWmsParameters.layersParameters();
|
||||||
|
|
||||||
|
// init layer restorer before doing anything
|
||||||
|
std::unique_ptr<QgsLayerRestorer> restorer;
|
||||||
|
restorer.reset( new QgsLayerRestorer( mNicknameLayers.values() ) );
|
||||||
|
|
||||||
|
// init stylized layers according to LAYERS/STYLES or SLD
|
||||||
|
QString sld = mWmsParameters.sld();
|
||||||
|
if ( !sld.isEmpty() )
|
||||||
|
layers = sldStylizedLayers( sld );
|
||||||
else
|
else
|
||||||
|
layers = stylizedLayers( params );
|
||||||
|
|
||||||
|
// create the mapSettings and the output image
|
||||||
|
QgsMapSettings mapSettings;
|
||||||
|
std::unique_ptr<QImage> outputImage( createImage() );
|
||||||
|
|
||||||
|
// configure map settings (background, DPI, ...)
|
||||||
|
configureMapSettings( outputImage.get(), mapSettings );
|
||||||
|
|
||||||
|
QgsMessageLog::logMessage( "mapSettings.destinationCrs(): " + mapSettings.destinationCrs().authid() );
|
||||||
|
QgsMessageLog::logMessage( "mapSettings.extent(): " + mapSettings.extent().toString() );
|
||||||
|
QgsMessageLog::logMessage( QStringLiteral( "mapSettings width = %1 height = %2" ).arg( mapSettings.outputSize().width() ).arg( mapSettings.outputSize().height() ) );
|
||||||
|
QgsMessageLog::logMessage( QStringLiteral( "mapSettings.mapUnitsPerPixel() = %1" ).arg( mapSettings.mapUnitsPerPixel() ) );
|
||||||
|
|
||||||
|
QgsScaleCalculator scaleCalc( ( outputImage->logicalDpiX() + outputImage->logicalDpiY() ) / 2, mapSettings.destinationCrs().mapUnits() );
|
||||||
|
QgsRectangle mapExtent = mapSettings.extent();
|
||||||
|
double scaleDenominator = scaleCalc.calculate( mapExtent, outputImage->width() );
|
||||||
|
|
||||||
|
// remove unwanted layers (restricted layers, ...)
|
||||||
|
removeUnwantedLayers( layers, scaleDenominator );
|
||||||
|
// remove non identifiable layers
|
||||||
|
removeNonIdentifiableLayers( layers );
|
||||||
|
|
||||||
|
Q_FOREACH ( QgsMapLayer *layer, layers )
|
||||||
{
|
{
|
||||||
infoPoint.reset( new QgsPointXY() );
|
Q_FOREACH ( QgsWmsParametersLayer param, params )
|
||||||
infoPointToMapCoordinates( i, j, infoPoint.get(), mapSettings );
|
{
|
||||||
|
if ( param.mNickname == layerNickname( *layer ) )
|
||||||
|
{
|
||||||
|
checkLayerReadPermissions( layer );
|
||||||
|
|
||||||
|
setLayerFilter( layer, param.mFilter );
|
||||||
|
|
||||||
|
setLayerAccessControlFilter( layer );
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//get the layer registered in QgsMapLayerRegistry and apply possible filters
|
// add layers to map settings (revert order for the rendering)
|
||||||
( void )layerSet( layersList, stylesList, mapSettings.destinationCrs() );
|
std::reverse( layers.begin(), layers.end() );
|
||||||
|
mapSettings.setLayers( layers );
|
||||||
|
|
||||||
//scoped pointer to restore all original layer filters (subsetStrings) when pointer goes out of scope
|
QDomDocument result = featureInfoDocument( layers, mapSettings, outputImage.get(), version );
|
||||||
//there's LOTS of potential exit paths here, so we avoid having to restore the filters manually
|
|
||||||
std::unique_ptr< QgsOWSServerFilterRestorer > filterRestorer( new QgsOWSServerFilterRestorer( mAccessControl ) );
|
|
||||||
applyRequestedLayerFilters( layersList, mapSettings, filterRestorer->originalFilters() );
|
|
||||||
|
|
||||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
QByteArray *ba = nullptr;
|
||||||
applyAccessControlLayersFilters( layersList, filterRestorer->originalFilters() );
|
ba = new QByteArray();
|
||||||
#endif
|
|
||||||
|
|
||||||
QDomElement getFeatureInfoElement;
|
QgsWmsParameters::Format infoFormat = mWmsParameters.infoFormat();
|
||||||
QString infoFormat = mParameters.value( QStringLiteral( "INFO_FORMAT" ) );
|
if ( infoFormat == QgsWmsParameters::Format::TEXT )
|
||||||
if ( infoFormat.startsWith( QLatin1String( "application/vnd.ogc.gml" ) ) )
|
*ba = convertFeatureInfoToText( result );
|
||||||
{
|
else if ( infoFormat == QgsWmsParameters::Format::HTML )
|
||||||
getFeatureInfoElement = result.createElement( QStringLiteral( "wfs:FeatureCollection" ) );
|
*ba = convertFeatureInfoToHtml( result );
|
||||||
getFeatureInfoElement.setAttribute( QStringLiteral( "xmlns:wfs" ), QStringLiteral( "http://www.opengis.net/wfs" ) );
|
|
||||||
getFeatureInfoElement.setAttribute( QStringLiteral( "xmlns:ogc" ), QStringLiteral( "http://www.opengis.net/ogc" ) );
|
|
||||||
getFeatureInfoElement.setAttribute( QStringLiteral( "xmlns:gml" ), QStringLiteral( "http://www.opengis.net/gml" ) );
|
|
||||||
getFeatureInfoElement.setAttribute( QStringLiteral( "xmlns:ows" ), QStringLiteral( "http://www.opengis.net/ows" ) );
|
|
||||||
getFeatureInfoElement.setAttribute( QStringLiteral( "xmlns:xlink" ), QStringLiteral( "http://www.w3.org/1999/xlink" ) );
|
|
||||||
getFeatureInfoElement.setAttribute( QStringLiteral( "xmlns:qgs" ), QStringLiteral( "http://qgis.org/gml" ) );
|
|
||||||
getFeatureInfoElement.setAttribute( QStringLiteral( "xmlns:xsi" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema-instance" ) );
|
|
||||||
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" ) );
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
*ba = result.toByteArray();
|
||||||
QString featureInfoElemName = mConfigParser->featureInfoDocumentElement( QStringLiteral( "GetFeatureInfoResponse" ) );
|
|
||||||
QString featureInfoElemNS = mConfigParser->featureInfoDocumentElementNS();
|
|
||||||
if ( featureInfoElemNS.isEmpty() )
|
|
||||||
{
|
|
||||||
getFeatureInfoElement = result.createElement( featureInfoElemName );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
getFeatureInfoElement = result.createElementNS( featureInfoElemNS, featureInfoElemName );
|
|
||||||
}
|
|
||||||
//feature info schema
|
|
||||||
QString featureInfoSchema = mConfigParser->featureInfoSchema();
|
|
||||||
if ( !featureInfoSchema.isEmpty() )
|
|
||||||
{
|
|
||||||
getFeatureInfoElement.setAttribute( QStringLiteral( "xmlns:xsi" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema-instance" ) );
|
|
||||||
getFeatureInfoElement.setAttribute( QStringLiteral( "xsi:schemaLocation" ), featureInfoSchema );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result.appendChild( getFeatureInfoElement );
|
|
||||||
|
|
||||||
QStringList nonIdentifiableLayers = mConfigParser->identifyDisabledLayers();
|
return ba;
|
||||||
|
|
||||||
//Render context is needed to determine feature visibility for vector layers
|
|
||||||
QgsRenderContext renderContext = QgsRenderContext::fromMapSettings( mapSettings );
|
|
||||||
|
|
||||||
bool sia2045 = mConfigParser->featureInfoFormatSIA2045();
|
|
||||||
|
|
||||||
//layers can have assigned a different name for GetCapabilities
|
|
||||||
QHash<QString, QString> layerAliasMap = mConfigParser->featureInfoLayerAliasMap();
|
|
||||||
|
|
||||||
QList<QgsMapLayer *> layerList;
|
|
||||||
QgsMapLayer *currentLayer = nullptr;
|
|
||||||
for ( auto layerIt = queryLayerList.constBegin(); layerIt != queryLayerList.constEnd(); ++layerIt )
|
|
||||||
{
|
|
||||||
//create maplayers from sld parser (several layers are possible in case of feature info on a group)
|
|
||||||
layerList = mConfigParser->mapLayerFromStyle( *layerIt, QLatin1String( "" ) );
|
|
||||||
for ( auto layerListIt = layerList.begin() ; layerListIt != layerList.end(); ++layerListIt )
|
|
||||||
{
|
|
||||||
currentLayer = *layerListIt;
|
|
||||||
if ( !currentLayer || nonIdentifiableLayers.contains( currentLayer->id() ) )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
QgsMapLayer *registeredMapLayer = QgsProject::instance()->mapLayer( currentLayer->id() );
|
|
||||||
if ( registeredMapLayer )
|
|
||||||
{
|
|
||||||
currentLayer = registeredMapLayer;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
|
||||||
if ( !mAccessControl->layerReadPermission( currentLayer ) )
|
|
||||||
{
|
|
||||||
throw QgsSecurityException( QStringLiteral( "You are not allowed to access to the layer: %1" ).arg( currentLayer->name() ) );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//skip layer if not visible at current map scale
|
|
||||||
if ( scaleDenominator > 0 && !currentLayer->isInScaleRange( scaleDenominator ) )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//switch depending on vector or raster
|
|
||||||
QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( currentLayer );
|
|
||||||
|
|
||||||
QDomElement layerElement;
|
|
||||||
if ( infoFormat.startsWith( QLatin1String( "application/vnd.ogc.gml" ) ) )
|
|
||||||
{
|
|
||||||
layerElement = getFeatureInfoElement;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
layerElement = result.createElement( QStringLiteral( "Layer" ) );
|
|
||||||
QString layerName = currentLayer->name();
|
|
||||||
if ( mConfigParser->useLayerIds() )
|
|
||||||
layerName = currentLayer->id();
|
|
||||||
else if ( !currentLayer->shortName().isEmpty() )
|
|
||||||
layerName = currentLayer->shortName();
|
|
||||||
|
|
||||||
//check if the layer is given a different name for GetFeatureInfo output
|
|
||||||
QHash<QString, QString>::const_iterator layerAliasIt = layerAliasMap.find( layerName );
|
|
||||||
if ( layerAliasIt != layerAliasMap.constEnd() )
|
|
||||||
{
|
|
||||||
layerName = layerAliasIt.value();
|
|
||||||
}
|
|
||||||
layerElement.setAttribute( QStringLiteral( "name" ), layerName );
|
|
||||||
getFeatureInfoElement.appendChild( layerElement );
|
|
||||||
if ( sia2045 ) //the name might not be unique after alias replacement
|
|
||||||
{
|
|
||||||
layerElement.setAttribute( QStringLiteral( "id" ), currentLayer->id() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( vectorLayer )
|
|
||||||
{
|
|
||||||
if ( !featureInfoFromVectorLayer( vectorLayer, infoPoint.get(), featureCount, result, layerElement, mapSettings, renderContext, version, infoFormat, featuresRect.get(), filterGeom.get() ) )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else //raster layer
|
|
||||||
{
|
|
||||||
if ( infoFormat.startsWith( QLatin1String( "application/vnd.ogc.gml" ) ) )
|
|
||||||
{
|
|
||||||
layerElement = result.createElement( QStringLiteral( "gml:featureMember" )/*wfs:FeatureMember*/ );
|
|
||||||
getFeatureInfoElement.appendChild( layerElement );
|
|
||||||
}
|
|
||||||
|
|
||||||
QgsRasterLayer *rasterLayer = qobject_cast<QgsRasterLayer *>( currentLayer );
|
|
||||||
if ( rasterLayer )
|
|
||||||
{
|
|
||||||
if ( !infoPoint )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
QgsPointXY layerInfoPoint = mapSettings.mapToLayerCoordinates( currentLayer, *( infoPoint.get() ) );
|
|
||||||
if ( !featureInfoFromRasterLayer( rasterLayer, mapSettings, &layerInfoPoint, result, layerElement, version, infoFormat ) )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( featuresRect )
|
|
||||||
{
|
|
||||||
if ( infoFormat.startsWith( QLatin1String( "application/vnd.ogc.gml" ) ) )
|
|
||||||
{
|
|
||||||
QDomElement bBoxElem = result.createElement( QStringLiteral( "gml:boundedBy" ) );
|
|
||||||
QDomElement boxElem;
|
|
||||||
int gmlVersion = infoFormat.startsWith( QLatin1String( "application/vnd.ogc.gml/3" ) ) ? 3 : 2;
|
|
||||||
if ( gmlVersion < 3 )
|
|
||||||
{
|
|
||||||
boxElem = QgsOgcUtils::rectangleToGMLBox( featuresRect.get(), result, 8 );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
boxElem = QgsOgcUtils::rectangleToGMLEnvelope( featuresRect.get(), result, 8 );
|
|
||||||
}
|
|
||||||
|
|
||||||
QgsCoordinateReferenceSystem crs = mapSettings.destinationCrs();
|
|
||||||
if ( crs.isValid() )
|
|
||||||
{
|
|
||||||
boxElem.setAttribute( QStringLiteral( "srsName" ), crs.authid() );
|
|
||||||
}
|
|
||||||
bBoxElem.appendChild( boxElem );
|
|
||||||
getFeatureInfoElement.insertBefore( bBoxElem, QDomNode() ); //insert as first child
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QDomElement bBoxElem = result.createElement( QStringLiteral( "BoundingBox" ) );
|
|
||||||
bBoxElem.setAttribute( QStringLiteral( "CRS" ), mapSettings.destinationCrs().authid() );
|
|
||||||
bBoxElem.setAttribute( QStringLiteral( "minx" ), qgsDoubleToString( featuresRect->xMinimum(), 8 ) );
|
|
||||||
bBoxElem.setAttribute( QStringLiteral( "maxx" ), qgsDoubleToString( featuresRect->xMaximum(), 8 ) );
|
|
||||||
bBoxElem.setAttribute( QStringLiteral( "miny" ), qgsDoubleToString( featuresRect->yMinimum(), 8 ) );
|
|
||||||
bBoxElem.setAttribute( QStringLiteral( "maxy" ), qgsDoubleToString( featuresRect->yMaximum(), 8 ) );
|
|
||||||
getFeatureInfoElement.insertBefore( bBoxElem, QDomNode() ); //insert as first child
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( sia2045 && infoFormat.compare( QLatin1String( "text/xml" ), Qt::CaseInsensitive ) == 0 )
|
|
||||||
{
|
|
||||||
convertFeatureInfoToSIA2045( result );
|
|
||||||
}
|
|
||||||
|
|
||||||
//force restoration of original filters
|
|
||||||
filterRestorer.reset();
|
|
||||||
|
|
||||||
QgsProject::instance()->removeAllMapLayers();
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QImage *QgsRenderer::initializeRendering( QStringList &layersList, QStringList &stylesList, QStringList &layerIdList, QgsMapSettings &mapSettings )
|
QImage *QgsRenderer::initializeRendering( QStringList &layersList, QStringList &stylesList, QStringList &layerIdList, QgsMapSettings &mapSettings )
|
||||||
@ -1243,6 +1032,224 @@ namespace QgsWms
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDomDocument QgsRenderer::featureInfoDocument( QList<QgsMapLayer *> &layers, const QgsMapSettings &mapSettings,
|
||||||
|
const QImage *outputImage, const QString &version ) const
|
||||||
|
{
|
||||||
|
QStringList queryLayers = mWmsParameters.queryLayersNickname();
|
||||||
|
|
||||||
|
bool ijDefined = ( !mWmsParameters.i().isEmpty() && !mWmsParameters.j().isEmpty() );
|
||||||
|
|
||||||
|
bool xyDefined = ( !mWmsParameters.x().isEmpty() && !mWmsParameters.y().isEmpty() );
|
||||||
|
|
||||||
|
bool filtersDefined = !mWmsParameters.filters().isEmpty();
|
||||||
|
|
||||||
|
bool filterGeomDefined = !mWmsParameters.filterGeom().isEmpty();
|
||||||
|
|
||||||
|
int featureCount = mWmsParameters.featureCountAsInt();
|
||||||
|
if ( featureCount < 1 )
|
||||||
|
{
|
||||||
|
featureCount = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = mWmsParameters.iAsInt();
|
||||||
|
int j = mWmsParameters.jAsInt();
|
||||||
|
if ( xyDefined && !ijDefined )
|
||||||
|
{
|
||||||
|
i = mWmsParameters.xAsInt();
|
||||||
|
j = mWmsParameters.yAsInt();
|
||||||
|
}
|
||||||
|
int width = mWmsParameters.widthAsInt();
|
||||||
|
int height = mWmsParameters.heightAsInt();
|
||||||
|
if ( ( i != -1 && j != -1 && width != 0 && height != 0 ) && ( width != outputImage->width() || height != outputImage->height() ) )
|
||||||
|
{
|
||||||
|
i *= ( outputImage->width() / ( double )width );
|
||||||
|
j *= ( outputImage->height() / ( double )height );
|
||||||
|
}
|
||||||
|
|
||||||
|
// init search variables
|
||||||
|
std::unique_ptr<QgsRectangle> featuresRect;
|
||||||
|
std::unique_ptr<QgsGeometry> filterGeom;
|
||||||
|
std::unique_ptr<QgsPointXY> infoPoint;
|
||||||
|
|
||||||
|
if ( i != -1 && j != -1 )
|
||||||
|
{
|
||||||
|
infoPoint.reset( new QgsPointXY() );
|
||||||
|
infoPointToMapCoordinates( i, j, infoPoint.get(), mapSettings );
|
||||||
|
}
|
||||||
|
else if ( filtersDefined )
|
||||||
|
{
|
||||||
|
featuresRect.reset( new QgsRectangle() );
|
||||||
|
}
|
||||||
|
else if ( filterGeomDefined )
|
||||||
|
{
|
||||||
|
filterGeom.reset( new QgsGeometry( QgsGeometry::fromWkt( mWmsParameters.filterGeom() ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
QDomDocument result;
|
||||||
|
|
||||||
|
QDomElement getFeatureInfoElement;
|
||||||
|
QgsWmsParameters::Format infoFormat = mWmsParameters.infoFormat();
|
||||||
|
if ( infoFormat == QgsWmsParameters::Format::GML )
|
||||||
|
{
|
||||||
|
getFeatureInfoElement = result.createElement( QStringLiteral( "wfs:FeatureCollection" ) );
|
||||||
|
getFeatureInfoElement.setAttribute( QStringLiteral( "xmlns:wfs" ), QStringLiteral( "http://www.opengis.net/wfs" ) );
|
||||||
|
getFeatureInfoElement.setAttribute( QStringLiteral( "xmlns:ogc" ), QStringLiteral( "http://www.opengis.net/ogc" ) );
|
||||||
|
getFeatureInfoElement.setAttribute( QStringLiteral( "xmlns:gml" ), QStringLiteral( "http://www.opengis.net/gml" ) );
|
||||||
|
getFeatureInfoElement.setAttribute( QStringLiteral( "xmlns:ows" ), QStringLiteral( "http://www.opengis.net/ows" ) );
|
||||||
|
getFeatureInfoElement.setAttribute( QStringLiteral( "xmlns:xlink" ), QStringLiteral( "http://www.w3.org/1999/xlink" ) );
|
||||||
|
getFeatureInfoElement.setAttribute( QStringLiteral( "xmlns:qgs" ), QStringLiteral( "http://qgis.org/gml" ) );
|
||||||
|
getFeatureInfoElement.setAttribute( QStringLiteral( "xmlns:xsi" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema-instance" ) );
|
||||||
|
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" ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QString featureInfoElemName = QgsServerProjectUtils::wmsFeatureInfoDocumentElement( *mProject );
|
||||||
|
if ( featureInfoElemName.isEmpty() )
|
||||||
|
{
|
||||||
|
featureInfoElemName = QStringLiteral( "GetFeatureInfoResponse" );
|
||||||
|
}
|
||||||
|
QString featureInfoElemNs = QgsServerProjectUtils::wmsFeatureInfoDocumentElementNs( *mProject );
|
||||||
|
if ( featureInfoElemNs.isEmpty() )
|
||||||
|
{
|
||||||
|
getFeatureInfoElement = result.createElement( featureInfoElemName );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
getFeatureInfoElement = result.createElementNS( featureInfoElemNs, featureInfoElemName );
|
||||||
|
}
|
||||||
|
//feature info schema
|
||||||
|
QString featureInfoSchema = QgsServerProjectUtils::wmsFeatureInfoSchema( *mProject );
|
||||||
|
if ( !featureInfoSchema.isEmpty() )
|
||||||
|
{
|
||||||
|
getFeatureInfoElement.setAttribute( QStringLiteral( "xmlns:xsi" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema-instance" ) );
|
||||||
|
getFeatureInfoElement.setAttribute( QStringLiteral( "xsi:schemaLocation" ), featureInfoSchema );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.appendChild( getFeatureInfoElement );
|
||||||
|
|
||||||
|
//Render context is needed to determine feature visibility for vector layers
|
||||||
|
QgsRenderContext renderContext = QgsRenderContext::fromMapSettings( mapSettings );
|
||||||
|
|
||||||
|
bool sia2045 = QgsServerProjectUtils::wmsInfoFormatSia2045( *mProject );
|
||||||
|
|
||||||
|
//layers can have assigned a different name for GetCapabilities
|
||||||
|
QHash<QString, QString> layerAliasMap = QgsServerProjectUtils::wmsFeatureInfoLayerAliasMap( *mProject );
|
||||||
|
|
||||||
|
Q_FOREACH ( QString queryLayer, queryLayers )
|
||||||
|
{
|
||||||
|
Q_FOREACH ( QgsMapLayer *layer, layers )
|
||||||
|
{
|
||||||
|
if ( queryLayer == layerNickname( *layer ) )
|
||||||
|
{
|
||||||
|
QDomElement layerElement;
|
||||||
|
if ( infoFormat == QgsWmsParameters::Format::GML )
|
||||||
|
{
|
||||||
|
layerElement = getFeatureInfoElement;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
layerElement = result.createElement( QStringLiteral( "Layer" ) );
|
||||||
|
QString layerName = queryLayer;
|
||||||
|
|
||||||
|
//check if the layer is given a different name for GetFeatureInfo output
|
||||||
|
QHash<QString, QString>::const_iterator layerAliasIt = layerAliasMap.find( layerName );
|
||||||
|
if ( layerAliasIt != layerAliasMap.constEnd() )
|
||||||
|
{
|
||||||
|
layerName = layerAliasIt.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
layerElement.setAttribute( QStringLiteral( "name" ), layerName );
|
||||||
|
getFeatureInfoElement.appendChild( layerElement );
|
||||||
|
if ( sia2045 ) //the name might not be unique after alias replacement
|
||||||
|
{
|
||||||
|
layerElement.setAttribute( QStringLiteral( "id" ), layer->id() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( layer->type() == QgsMapLayer::VectorLayer )
|
||||||
|
{
|
||||||
|
QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layer );
|
||||||
|
if ( vectorLayer )
|
||||||
|
{
|
||||||
|
if ( !featureInfoFromVectorLayer( vectorLayer, infoPoint.get(), featureCount, result, layerElement, mapSettings, renderContext, version, featuresRect.get(), filterGeom.get() ) )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( infoFormat == QgsWmsParameters::Format::GML )
|
||||||
|
{
|
||||||
|
layerElement = result.createElement( QStringLiteral( "gml:featureMember" )/*wfs:FeatureMember*/ );
|
||||||
|
getFeatureInfoElement.appendChild( layerElement );
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsRasterLayer *rasterLayer = qobject_cast<QgsRasterLayer *>( layer );
|
||||||
|
if ( rasterLayer )
|
||||||
|
{
|
||||||
|
if ( !infoPoint )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
QgsPointXY layerInfoPoint = mapSettings.mapToLayerCoordinates( layer, *( infoPoint.get() ) );
|
||||||
|
if ( !featureInfoFromRasterLayer( rasterLayer, mapSettings, &layerInfoPoint, result, layerElement, version ) )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( featuresRect )
|
||||||
|
{
|
||||||
|
if ( infoFormat == QgsWmsParameters::Format::GML )
|
||||||
|
{
|
||||||
|
QDomElement bBoxElem = result.createElement( QStringLiteral( "gml:boundedBy" ) );
|
||||||
|
QDomElement boxElem;
|
||||||
|
int gmlVersion = mWmsParameters.infoFormatVersion();
|
||||||
|
if ( gmlVersion < 3 )
|
||||||
|
{
|
||||||
|
boxElem = QgsOgcUtils::rectangleToGMLBox( featuresRect.get(), result, 8 );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
boxElem = QgsOgcUtils::rectangleToGMLEnvelope( featuresRect.get(), result, 8 );
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsCoordinateReferenceSystem crs = mapSettings.destinationCrs();
|
||||||
|
if ( crs.isValid() )
|
||||||
|
{
|
||||||
|
boxElem.setAttribute( QStringLiteral( "srsName" ), crs.authid() );
|
||||||
|
}
|
||||||
|
bBoxElem.appendChild( boxElem );
|
||||||
|
getFeatureInfoElement.insertBefore( bBoxElem, QDomNode() ); //insert as first child
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QDomElement bBoxElem = result.createElement( QStringLiteral( "BoundingBox" ) );
|
||||||
|
bBoxElem.setAttribute( QStringLiteral( "CRS" ), mapSettings.destinationCrs().authid() );
|
||||||
|
bBoxElem.setAttribute( QStringLiteral( "minx" ), qgsDoubleToString( featuresRect->xMinimum(), 8 ) );
|
||||||
|
bBoxElem.setAttribute( QStringLiteral( "maxx" ), qgsDoubleToString( featuresRect->xMaximum(), 8 ) );
|
||||||
|
bBoxElem.setAttribute( QStringLiteral( "miny" ), qgsDoubleToString( featuresRect->yMinimum(), 8 ) );
|
||||||
|
bBoxElem.setAttribute( QStringLiteral( "maxy" ), qgsDoubleToString( featuresRect->yMaximum(), 8 ) );
|
||||||
|
getFeatureInfoElement.insertBefore( bBoxElem, QDomNode() ); //insert as first child
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( sia2045 && infoFormat == QgsWmsParameters::Format::XML )
|
||||||
|
{
|
||||||
|
convertFeatureInfoToSia2045( result );
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
bool QgsRenderer::featureInfoFromVectorLayer( QgsVectorLayer *layer,
|
bool QgsRenderer::featureInfoFromVectorLayer( QgsVectorLayer *layer,
|
||||||
const QgsPointXY *infoPoint,
|
const QgsPointXY *infoPoint,
|
||||||
int nFeatures,
|
int nFeatures,
|
||||||
@ -1251,7 +1258,6 @@ namespace QgsWms
|
|||||||
const QgsMapSettings &mapSettings,
|
const QgsMapSettings &mapSettings,
|
||||||
QgsRenderContext &renderContext,
|
QgsRenderContext &renderContext,
|
||||||
const QString &version,
|
const QString &version,
|
||||||
const QString &infoFormat,
|
|
||||||
QgsRectangle *featureBBox,
|
QgsRectangle *featureBBox,
|
||||||
QgsGeometry *filterGeom ) const
|
QgsGeometry *filterGeom ) const
|
||||||
{
|
{
|
||||||
@ -1288,8 +1294,8 @@ namespace QgsWms
|
|||||||
int featureCounter = 0;
|
int featureCounter = 0;
|
||||||
layer->updateFields();
|
layer->updateFields();
|
||||||
const QgsFields &fields = layer->pendingFields();
|
const QgsFields &fields = layer->pendingFields();
|
||||||
bool addWktGeometry = mConfigParser && mConfigParser->featureInfoWithWktGeometry();
|
bool addWktGeometry = QgsServerProjectUtils::wmsFeatureInfoAddWktGeometry( *mProject );
|
||||||
bool segmentizeWktGeometry = mConfigParser && mConfigParser->segmentizeFeatureInfoWktGeometry();
|
bool segmentizeWktGeometry = QgsServerProjectUtils::wmsFeatureInfoSegmentizeWktGeometry( *mProject );
|
||||||
const QSet<QString> &excludedAttributes = layer->excludeAttributesWms();
|
const QSet<QString> &excludedAttributes = layer->excludeAttributesWms();
|
||||||
|
|
||||||
QgsFeatureRequest fReq;
|
QgsFeatureRequest fReq;
|
||||||
@ -1385,17 +1391,13 @@ namespace QgsWms
|
|||||||
outputCrs = mapSettings.destinationCrs();
|
outputCrs = mapSettings.destinationCrs();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( infoFormat == QLatin1String( "application/vnd.ogc.gml" ) )
|
if ( mWmsParameters.infoFormat() == QgsWmsParameters::Format::GML )
|
||||||
{
|
{
|
||||||
bool withGeom = layer->wkbType() != QgsWkbTypes::NoGeometry && addWktGeometry;
|
bool withGeom = layer->wkbType() != QgsWkbTypes::NoGeometry && addWktGeometry;
|
||||||
int version = infoFormat.startsWith( QLatin1String( "application/vnd.ogc.gml/3" ) ) ? 3 : 2;
|
int gmlVersion = mWmsParameters.infoFormatVersion();
|
||||||
QString typeName = layer->name();
|
QString typeName = layerNickname( *layer );
|
||||||
if ( mConfigParser && mConfigParser->useLayerIds() )
|
|
||||||
typeName = layer->id();
|
|
||||||
else if ( !layer->shortName().isEmpty() )
|
|
||||||
typeName = layer->shortName();
|
|
||||||
QDomElement elem = createFeatureGML(
|
QDomElement elem = createFeatureGML(
|
||||||
&feature, layer, infoDocument, outputCrs, mapSettings, typeName, withGeom, version
|
&feature, layer, infoDocument, outputCrs, mapSettings, typeName, withGeom, gmlVersion
|
||||||
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
#ifdef HAVE_SERVER_PYTHON_PLUGINS
|
||||||
, &attributes
|
, &attributes
|
||||||
#endif
|
#endif
|
||||||
@ -1453,14 +1455,14 @@ namespace QgsWms
|
|||||||
}
|
}
|
||||||
|
|
||||||
//append feature bounding box to feature info xml
|
//append feature bounding box to feature info xml
|
||||||
if ( layer->wkbType() != QgsWkbTypes::NoGeometry && hasGeometry && mConfigParser )
|
if ( layer->wkbType() != QgsWkbTypes::NoGeometry && hasGeometry )
|
||||||
{
|
{
|
||||||
QDomElement bBoxElem = infoDocument.createElement( QStringLiteral( "BoundingBox" ) );
|
QDomElement bBoxElem = infoDocument.createElement( QStringLiteral( "BoundingBox" ) );
|
||||||
bBoxElem.setAttribute( version == QLatin1String( "1.1.1" ) ? "SRS" : "CRS", outputCrs.authid() );
|
bBoxElem.setAttribute( version == QLatin1String( "1.1.1" ) ? "SRS" : "CRS", outputCrs.authid() );
|
||||||
bBoxElem.setAttribute( QStringLiteral( "minx" ), qgsDoubleToString( box.xMinimum(), getWMSPrecision( 8 ) ) );
|
bBoxElem.setAttribute( QStringLiteral( "minx" ), qgsDoubleToString( box.xMinimum(), getWMSPrecision() ) );
|
||||||
bBoxElem.setAttribute( QStringLiteral( "maxx" ), qgsDoubleToString( box.xMaximum(), getWMSPrecision( 8 ) ) );
|
bBoxElem.setAttribute( QStringLiteral( "maxx" ), qgsDoubleToString( box.xMaximum(), getWMSPrecision() ) );
|
||||||
bBoxElem.setAttribute( QStringLiteral( "miny" ), qgsDoubleToString( box.yMinimum(), getWMSPrecision( 8 ) ) );
|
bBoxElem.setAttribute( QStringLiteral( "miny" ), qgsDoubleToString( box.yMinimum(), getWMSPrecision() ) );
|
||||||
bBoxElem.setAttribute( QStringLiteral( "maxy" ), qgsDoubleToString( box.yMaximum(), getWMSPrecision( 8 ) ) );
|
bBoxElem.setAttribute( QStringLiteral( "maxy" ), qgsDoubleToString( box.yMaximum(), getWMSPrecision() ) );
|
||||||
featureElement.appendChild( bBoxElem );
|
featureElement.appendChild( bBoxElem );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1484,14 +1486,14 @@ namespace QgsWms
|
|||||||
{
|
{
|
||||||
if ( QgsWkbTypes::isCurvedType( abstractGeom->wkbType() ) )
|
if ( QgsWkbTypes::isCurvedType( abstractGeom->wkbType() ) )
|
||||||
{
|
{
|
||||||
QgsAbstractGeometry *segmentizedGeom = abstractGeom-> segmentize();
|
QgsAbstractGeometry *segmentizedGeom = abstractGeom->segmentize();
|
||||||
geom.setGeometry( segmentizedGeom );
|
geom.setGeometry( segmentizedGeom );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QDomElement geometryElement = infoDocument.createElement( QStringLiteral( "Attribute" ) );
|
QDomElement geometryElement = infoDocument.createElement( QStringLiteral( "Attribute" ) );
|
||||||
geometryElement.setAttribute( QStringLiteral( "name" ), QStringLiteral( "geometry" ) );
|
geometryElement.setAttribute( QStringLiteral( "name" ), QStringLiteral( "geometry" ) );
|
||||||
geometryElement.setAttribute( QStringLiteral( "value" ), geom.exportToWkt( getWMSPrecision( 8 ) ) );
|
geometryElement.setAttribute( QStringLiteral( "value" ), geom.exportToWkt( getWMSPrecision() ) );
|
||||||
geometryElement.setAttribute( QStringLiteral( "type" ), QStringLiteral( "derived" ) );
|
geometryElement.setAttribute( QStringLiteral( "type" ), QStringLiteral( "derived" ) );
|
||||||
featureElement.appendChild( geometryElement );
|
featureElement.appendChild( geometryElement );
|
||||||
}
|
}
|
||||||
@ -1511,8 +1513,7 @@ namespace QgsWms
|
|||||||
const QgsPointXY *infoPoint,
|
const QgsPointXY *infoPoint,
|
||||||
QDomDocument &infoDocument,
|
QDomDocument &infoDocument,
|
||||||
QDomElement &layerElement,
|
QDomElement &layerElement,
|
||||||
const QString &version,
|
const QString &version ) const
|
||||||
const QString &infoFormat ) const
|
|
||||||
{
|
{
|
||||||
Q_UNUSED( version );
|
Q_UNUSED( version );
|
||||||
|
|
||||||
@ -1540,7 +1541,7 @@ namespace QgsWms
|
|||||||
attributes = layer->dataProvider()->identify( *infoPoint, QgsRaster::IdentifyFormatValue, mapSettings.extent(), mapSettings.outputSize().width(), mapSettings.outputSize().height() ).results();
|
attributes = layer->dataProvider()->identify( *infoPoint, QgsRaster::IdentifyFormatValue, mapSettings.extent(), mapSettings.outputSize().width(), mapSettings.outputSize().height() ).results();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( infoFormat == QLatin1String( "application/vnd.ogc.gml" ) )
|
if ( mWmsParameters.infoFormat() == QgsWmsParameters::Format::GML )
|
||||||
{
|
{
|
||||||
QgsFeature feature;
|
QgsFeature feature;
|
||||||
QgsFields fields;
|
QgsFields fields;
|
||||||
@ -1554,14 +1555,10 @@ namespace QgsWms
|
|||||||
feature.setFields( fields );
|
feature.setFields( fields );
|
||||||
|
|
||||||
QgsCoordinateReferenceSystem layerCrs = layer->crs();
|
QgsCoordinateReferenceSystem layerCrs = layer->crs();
|
||||||
int version = infoFormat.startsWith( QLatin1String( "application/vnd.ogc.gml/3" ) ) ? 3 : 2;
|
int gmlVersion = mWmsParameters.infoFormatVersion();
|
||||||
QString typeName = layer->name();
|
QString typeName = layerNickname( *layer );
|
||||||
if ( mConfigParser && mConfigParser->useLayerIds() )
|
|
||||||
typeName = layer->id();
|
|
||||||
else if ( !layer->shortName().isEmpty() )
|
|
||||||
typeName = layer->shortName();
|
|
||||||
QDomElement elem = createFeatureGML(
|
QDomElement elem = createFeatureGML(
|
||||||
&feature, nullptr, infoDocument, layerCrs, mapSettings, typeName, false, version, nullptr );
|
&feature, nullptr, infoDocument, layerCrs, mapSettings, typeName, false, gmlVersion, nullptr );
|
||||||
layerElement.appendChild( elem );
|
layerElement.appendChild( elem );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -2097,7 +2094,7 @@ namespace QgsWms
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsRenderer::convertFeatureInfoToSIA2045( QDomDocument &doc )
|
void QgsRenderer::convertFeatureInfoToSia2045( QDomDocument &doc ) const
|
||||||
{
|
{
|
||||||
QDomDocument SIAInfoDoc;
|
QDomDocument SIAInfoDoc;
|
||||||
QDomElement infoDocElement = doc.documentElement();
|
QDomElement infoDocElement = doc.documentElement();
|
||||||
@ -2212,6 +2209,130 @@ namespace QgsWms
|
|||||||
doc = SIAInfoDoc;
|
doc = SIAInfoDoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QByteArray QgsRenderer::convertFeatureInfoToHtml( const QDomDocument &doc ) const
|
||||||
|
{
|
||||||
|
QString featureInfoString;
|
||||||
|
|
||||||
|
//the HTML head
|
||||||
|
featureInfoString.append( "<HEAD>\n" );
|
||||||
|
featureInfoString.append( "<TITLE> GetFeatureInfo results </TITLE>\n" );
|
||||||
|
featureInfoString.append( "<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\">\n" );
|
||||||
|
featureInfoString.append( "</HEAD>\n" );
|
||||||
|
|
||||||
|
//start the html body
|
||||||
|
featureInfoString.append( "<BODY>\n" );
|
||||||
|
|
||||||
|
QDomNodeList layerList = doc.elementsByTagName( QStringLiteral( "Layer" ) );
|
||||||
|
|
||||||
|
//layer loop
|
||||||
|
for ( int i = 0; i < layerList.size(); ++i )
|
||||||
|
{
|
||||||
|
QDomElement layerElem = layerList.at( i ).toElement();
|
||||||
|
|
||||||
|
featureInfoString.append( "<TABLE border=1 width=100%>\n" );
|
||||||
|
featureInfoString.append( "<TR><TH width=25%>Layer</TH><TD>" + layerElem.attribute( QStringLiteral( "name" ) ) + "</TD></TR>\n" );
|
||||||
|
featureInfoString.append( "</BR>" );
|
||||||
|
|
||||||
|
//feature loop (for vector layers)
|
||||||
|
QDomNodeList featureNodeList = layerElem.elementsByTagName( QStringLiteral( "Feature" ) );
|
||||||
|
QDomElement currentFeatureElement;
|
||||||
|
|
||||||
|
if ( !featureNodeList.isEmpty() ) //vector layer
|
||||||
|
{
|
||||||
|
for ( int j = 0; j < featureNodeList.size(); ++j )
|
||||||
|
{
|
||||||
|
QDomElement featureElement = featureNodeList.at( j ).toElement();
|
||||||
|
featureInfoString.append( "<TABLE border=1 width=100%>\n" );
|
||||||
|
featureInfoString.append( "<TR><TH>Feature</TH><TD>" + featureElement.attribute( QStringLiteral( "id" ) ) +
|
||||||
|
"</TD></TR>\n" );
|
||||||
|
|
||||||
|
//attribute loop
|
||||||
|
QDomNodeList attributeNodeList = featureElement.elementsByTagName( QStringLiteral( "Attribute" ) );
|
||||||
|
for ( int k = 0; k < attributeNodeList.size(); ++k )
|
||||||
|
{
|
||||||
|
QDomElement attributeElement = attributeNodeList.at( k ).toElement();
|
||||||
|
featureInfoString.append( "<TR><TH>" + attributeElement.attribute( QStringLiteral( "name" ) ) +
|
||||||
|
"</TH><TD>" + attributeElement.attribute( QStringLiteral( "value" ) ) + "</TD></TR>\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
featureInfoString.append( "</TABLE>\n</BR>\n" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else //raster layer
|
||||||
|
{
|
||||||
|
QDomNodeList attributeNodeList = layerElem.elementsByTagName( QStringLiteral( "Attribute" ) );
|
||||||
|
for ( int j = 0; j < attributeNodeList.size(); ++j )
|
||||||
|
{
|
||||||
|
QDomElement attributeElement = attributeNodeList.at( j ).toElement();
|
||||||
|
featureInfoString.append( "<TR><TH>" + attributeElement.attribute( QStringLiteral( "name" ) ) +
|
||||||
|
"</TH><TD>" + attributeElement.attribute( QStringLiteral( "value" ) ) + "</TD></TR>\n" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
featureInfoString.append( "</TABLE>\n<BR></BR>\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
//start the html body
|
||||||
|
featureInfoString.append( "</BODY>\n" );
|
||||||
|
|
||||||
|
return featureInfoString.toUtf8();
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray QgsRenderer::convertFeatureInfoToText( const QDomDocument &doc ) const
|
||||||
|
{
|
||||||
|
QString featureInfoString;
|
||||||
|
|
||||||
|
//the Text head
|
||||||
|
featureInfoString.append( "GetFeatureInfo results\n" );
|
||||||
|
featureInfoString.append( "\n" );
|
||||||
|
|
||||||
|
QDomNodeList layerList = doc.elementsByTagName( QStringLiteral( "Layer" ) );
|
||||||
|
|
||||||
|
//layer loop
|
||||||
|
for ( int i = 0; i < layerList.size(); ++i )
|
||||||
|
{
|
||||||
|
QDomElement layerElem = layerList.at( i ).toElement();
|
||||||
|
|
||||||
|
featureInfoString.append( "Layer '" + layerElem.attribute( QStringLiteral( "name" ) ) + "'\n" );
|
||||||
|
|
||||||
|
//feature loop (for vector layers)
|
||||||
|
QDomNodeList featureNodeList = layerElem.elementsByTagName( QStringLiteral( "Feature" ) );
|
||||||
|
QDomElement currentFeatureElement;
|
||||||
|
|
||||||
|
if ( !featureNodeList.isEmpty() ) //vector layer
|
||||||
|
{
|
||||||
|
for ( int j = 0; j < featureNodeList.size(); ++j )
|
||||||
|
{
|
||||||
|
QDomElement featureElement = featureNodeList.at( j ).toElement();
|
||||||
|
featureInfoString.append( "Feature " + featureElement.attribute( QStringLiteral( "id" ) ) + "\n" );
|
||||||
|
|
||||||
|
//attribute loop
|
||||||
|
QDomNodeList attributeNodeList = featureElement.elementsByTagName( QStringLiteral( "Attribute" ) );
|
||||||
|
for ( int k = 0; k < attributeNodeList.size(); ++k )
|
||||||
|
{
|
||||||
|
QDomElement attributeElement = attributeNodeList.at( k ).toElement();
|
||||||
|
featureInfoString.append( attributeElement.attribute( QStringLiteral( "name" ) ) + " = '" +
|
||||||
|
attributeElement.attribute( QStringLiteral( "value" ) ) + "'\n" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else //raster layer
|
||||||
|
{
|
||||||
|
QDomNodeList attributeNodeList = layerElem.elementsByTagName( QStringLiteral( "Attribute" ) );
|
||||||
|
for ( int j = 0; j < attributeNodeList.size(); ++j )
|
||||||
|
{
|
||||||
|
QDomElement attributeElement = attributeNodeList.at( j ).toElement();
|
||||||
|
featureInfoString.append( attributeElement.attribute( QStringLiteral( "name" ) ) + " = '" +
|
||||||
|
attributeElement.attribute( QStringLiteral( "value" ) ) + "'\n" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
featureInfoString.append( "\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
return featureInfoString.toUtf8();
|
||||||
|
}
|
||||||
|
|
||||||
QDomElement QgsRenderer::createFeatureGML(
|
QDomElement QgsRenderer::createFeatureGML(
|
||||||
QgsFeature *feat,
|
QgsFeature *feat,
|
||||||
QgsVectorLayer *layer,
|
QgsVectorLayer *layer,
|
||||||
@ -2263,11 +2384,11 @@ namespace QgsWms
|
|||||||
QDomElement boxElem;
|
QDomElement boxElem;
|
||||||
if ( version < 3 )
|
if ( version < 3 )
|
||||||
{
|
{
|
||||||
boxElem = QgsOgcUtils::rectangleToGMLBox( &box, doc, 8 );
|
boxElem = QgsOgcUtils::rectangleToGMLBox( &box, doc, getWMSPrecision() );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
boxElem = QgsOgcUtils::rectangleToGMLEnvelope( &box, doc, 8 );
|
boxElem = QgsOgcUtils::rectangleToGMLEnvelope( &box, doc, getWMSPrecision() );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( crs.isValid() )
|
if ( crs.isValid() )
|
||||||
@ -2291,11 +2412,11 @@ namespace QgsWms
|
|||||||
QDomElement gmlElem;
|
QDomElement gmlElem;
|
||||||
if ( version < 3 )
|
if ( version < 3 )
|
||||||
{
|
{
|
||||||
gmlElem = QgsOgcUtils::geometryToGML( geom, doc, 8 );
|
gmlElem = QgsOgcUtils::geometryToGML( geom, doc, getWMSPrecision() );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gmlElem = QgsOgcUtils::geometryToGML( geom, doc, QStringLiteral( "GML3" ), 8 );
|
gmlElem = QgsOgcUtils::geometryToGML( geom, doc, QStringLiteral( "GML3" ), getWMSPrecision() );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !gmlElem.isNull() )
|
if ( !gmlElem.isNull() )
|
||||||
@ -2388,26 +2509,17 @@ namespace QgsWms
|
|||||||
return imageQuality;
|
return imageQuality;
|
||||||
}
|
}
|
||||||
|
|
||||||
int QgsRenderer::getWMSPrecision( int defaultValue = 8 ) const
|
int QgsRenderer::getWMSPrecision() const
|
||||||
{
|
{
|
||||||
// First taken from QGIS project
|
// First taken from QGIS project and the default value is 6
|
||||||
int WMSPrecision = mConfigParser->wmsPrecision();
|
int WMSPrecision = QgsServerProjectUtils::wmsFeatureInfoPrecision( *mProject );
|
||||||
|
|
||||||
// Then checks if a parameter is given, if so use it instead
|
// Then checks if a parameter is given, if so use it instead
|
||||||
if ( mParameters.contains( QStringLiteral( "WMS_PRECISION" ) ) )
|
int WMSPrecisionParameter = mWmsParameters.wmsPrecisionAsInt();
|
||||||
{
|
|
||||||
bool conversionSuccess;
|
if ( WMSPrecisionParameter > -1 )
|
||||||
int WMSPrecisionParameter;
|
return WMSPrecisionParameter;
|
||||||
WMSPrecisionParameter = mParameters[ QStringLiteral( "WMS_PRECISION" )].toInt( &conversionSuccess );
|
else
|
||||||
if ( conversionSuccess )
|
|
||||||
{
|
|
||||||
WMSPrecision = WMSPrecisionParameter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( WMSPrecision == -1 )
|
|
||||||
{
|
|
||||||
WMSPrecision = defaultValue;
|
|
||||||
}
|
|
||||||
return WMSPrecision;
|
return WMSPrecision;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2929,6 +3041,25 @@ namespace QgsWms
|
|||||||
layers = wantedLayers;
|
layers = wantedLayers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QgsRenderer::removeNonIdentifiableLayers( QList<QgsMapLayer *> &layers ) const
|
||||||
|
{
|
||||||
|
QStringList nonIdentifiableLayers = mProject->nonIdentifiableLayers();
|
||||||
|
if ( !nonIdentifiableLayers.isEmpty() )
|
||||||
|
{
|
||||||
|
QList<QgsMapLayer *> wantedLayers;
|
||||||
|
|
||||||
|
Q_FOREACH ( QgsMapLayer *layer, layers )
|
||||||
|
{
|
||||||
|
if ( nonIdentifiableLayers.contains( layer->id() ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
wantedLayers.append( layer );
|
||||||
|
}
|
||||||
|
|
||||||
|
layers = wantedLayers;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QgsLayerTreeModel *QgsRenderer::buildLegendTreeModel( const QList<QgsMapLayer *> &layers, double scaleDenominator, QgsLayerTree &rootGroup )
|
QgsLayerTreeModel *QgsRenderer::buildLegendTreeModel( const QList<QgsMapLayer *> &layers, double scaleDenominator, QgsLayerTree &rootGroup )
|
||||||
{
|
{
|
||||||
// get params
|
// get params
|
||||||
|
@ -116,7 +116,7 @@ namespace QgsWms
|
|||||||
/** Creates an xml document that describes the result of the getFeatureInfo request.
|
/** Creates an xml document that describes the result of the getFeatureInfo request.
|
||||||
* May throw an exception
|
* May throw an exception
|
||||||
*/
|
*/
|
||||||
QDomDocument getFeatureInfo( const QString &version = "1.3.0" );
|
QByteArray *getFeatureInfo( const QString &version = "1.3.0" );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -140,6 +140,9 @@ namespace QgsWms
|
|||||||
// Remove unwanted layers (restricted, not visible, etc)
|
// Remove unwanted layers (restricted, not visible, etc)
|
||||||
void removeUnwantedLayers( QList<QgsMapLayer *> &layers, double scaleDenominator = -1 ) const;
|
void removeUnwantedLayers( QList<QgsMapLayer *> &layers, double scaleDenominator = -1 ) const;
|
||||||
|
|
||||||
|
// Remove non identifiable layers (restricted, not visible, etc)
|
||||||
|
void removeNonIdentifiableLayers( QList<QgsMapLayer *> &layers ) const;
|
||||||
|
|
||||||
// Rendering step for layers
|
// Rendering step for layers
|
||||||
QPainter *layersRendering( const QgsMapSettings &mapSettings, QImage &image, HitTest *hitTest = nullptr ) const;
|
QPainter *layersRendering( const QgsMapSettings &mapSettings, QImage &image, HitTest *hitTest = nullptr ) const;
|
||||||
|
|
||||||
@ -211,6 +214,9 @@ namespace QgsWms
|
|||||||
*/
|
*/
|
||||||
void initializeSLDParser( QStringList &layersList, QStringList &stylesList );
|
void initializeSLDParser( QStringList &layersList, QStringList &stylesList );
|
||||||
|
|
||||||
|
QDomDocument featureInfoDocument( QList<QgsMapLayer *> &layers, const QgsMapSettings &mapSettings,
|
||||||
|
const QImage *outputImage, const QString &version ) const;
|
||||||
|
|
||||||
/** Appends feature info xml for the layer to the layer element of the feature info dom document
|
/** Appends feature info xml for the layer to the layer element of the feature info dom document
|
||||||
\param featureBBox the bounding box of the selected features in output CRS
|
\param featureBBox the bounding box of the selected features in output CRS
|
||||||
\returns true in case of success*/
|
\returns true in case of success*/
|
||||||
@ -222,7 +228,6 @@ namespace QgsWms
|
|||||||
const QgsMapSettings &mapSettings,
|
const QgsMapSettings &mapSettings,
|
||||||
QgsRenderContext &renderContext,
|
QgsRenderContext &renderContext,
|
||||||
const QString &version,
|
const QString &version,
|
||||||
const QString &infoFormat,
|
|
||||||
QgsRectangle *featureBBox = nullptr,
|
QgsRectangle *featureBBox = nullptr,
|
||||||
QgsGeometry *filterGeom = nullptr ) const;
|
QgsGeometry *filterGeom = nullptr ) const;
|
||||||
//! Appends feature info xml for the layer to the layer element of the dom document
|
//! Appends feature info xml for the layer to the layer element of the dom document
|
||||||
@ -231,8 +236,7 @@ namespace QgsWms
|
|||||||
const QgsPointXY *infoPoint,
|
const QgsPointXY *infoPoint,
|
||||||
QDomDocument &infoDocument,
|
QDomDocument &infoDocument,
|
||||||
QDomElement &layerElement,
|
QDomElement &layerElement,
|
||||||
const QString &version,
|
const QString &version ) const;
|
||||||
const QString &infoFormat ) const;
|
|
||||||
|
|
||||||
/** Creates a layer set and returns a stringlist with layer ids that can be passed to a renderer. Usually used in conjunction with readLayersAndStyles
|
/** Creates a layer set and returns a stringlist with layer ids that can be passed to a renderer. Usually used in conjunction with readLayersAndStyles
|
||||||
\param scaleDenominator Filter out layer if scale based visibility does not match (or use -1 if no scale restriction)*/
|
\param scaleDenominator Filter out layer if scale based visibility does not match (or use -1 if no scale restriction)*/
|
||||||
@ -291,7 +295,13 @@ namespace QgsWms
|
|||||||
bool checkMaximumWidthHeight() const;
|
bool checkMaximumWidthHeight() const;
|
||||||
|
|
||||||
//! Converts a feature info xml document to SIA2045 norm
|
//! Converts a feature info xml document to SIA2045 norm
|
||||||
void convertFeatureInfoToSIA2045( QDomDocument &doc );
|
void convertFeatureInfoToSia2045( QDomDocument &doc ) const;
|
||||||
|
|
||||||
|
//! Converts a feature info xml document to HTML
|
||||||
|
QByteArray convertFeatureInfoToHtml( const QDomDocument &doc ) const;
|
||||||
|
|
||||||
|
//! Converts a feature info xml document to Text
|
||||||
|
QByteArray convertFeatureInfoToText( const QDomDocument &doc ) const;
|
||||||
|
|
||||||
QDomElement createFeatureGML(
|
QDomElement createFeatureGML(
|
||||||
QgsFeature *feat,
|
QgsFeature *feat,
|
||||||
@ -334,7 +344,7 @@ namespace QgsWms
|
|||||||
int getImageQuality() const;
|
int getImageQuality() const;
|
||||||
|
|
||||||
//! Return precision to use for GetFeatureInfo request
|
//! Return precision to use for GetFeatureInfo request
|
||||||
int getWMSPrecision( int defaultValue ) const;
|
int getWMSPrecision() const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -453,6 +453,33 @@ class TestQgsServerAccessControl(unittest.TestCase):
|
|||||||
str(response).find("<qgs:color>red</qgs:color>") != -1, # spellok
|
str(response).find("<qgs:color>red</qgs:color>") != -1, # spellok
|
||||||
"No color in result of GetFeatureInfo\n%s" % response)
|
"No color in result of GetFeatureInfo\n%s" % response)
|
||||||
|
|
||||||
|
response, headers = self._get_restricted(query_string)
|
||||||
|
self.assertEqual(
|
||||||
|
headers.get("Content-Type"), "text/xml; charset=utf-8",
|
||||||
|
"Content type for GetFeatureInfo is wrong: %s" % headers.get("Content-Type"))
|
||||||
|
self.assertTrue(
|
||||||
|
str(response).find('<ServiceException code="Security">') != -1,
|
||||||
|
"Not allowed do a GetFeatureInfo on Country"
|
||||||
|
)
|
||||||
|
|
||||||
|
query_string = "&".join(["%s=%s" % i for i in list({
|
||||||
|
"MAP": urllib.parse.quote(self.projectPath),
|
||||||
|
"SERVICE": "WMS",
|
||||||
|
"VERSION": "1.1.1",
|
||||||
|
"REQUEST": "GetFeatureInfo",
|
||||||
|
"LAYERS": "Hello",
|
||||||
|
"QUERY_LAYERS": "Hello",
|
||||||
|
"STYLES": "",
|
||||||
|
"FORMAT": "image/png",
|
||||||
|
"BBOX": "-16817707,-6318936.5,5696513,16195283.5",
|
||||||
|
"HEIGHT": "500",
|
||||||
|
"WIDTH": "500",
|
||||||
|
"SRS": "EPSG:3857",
|
||||||
|
"FEATURE_COUNT": "10",
|
||||||
|
"INFO_FORMAT": "application/vnd.ogc.gml",
|
||||||
|
"X": "56",
|
||||||
|
"Y": "144"
|
||||||
|
}.items())])
|
||||||
response, headers = self._get_restricted(query_string)
|
response, headers = self._get_restricted(query_string)
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
|
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
|
||||||
@ -1053,6 +1080,33 @@ class TestQgsServerAccessControl(unittest.TestCase):
|
|||||||
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
|
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
|
||||||
"No good result in GetFeatureInfo Hello/1\n%s" % response)
|
"No good result in GetFeatureInfo Hello/1\n%s" % response)
|
||||||
|
|
||||||
|
response, headers = self._get_restricted(query_string)
|
||||||
|
self.assertEqual(
|
||||||
|
headers.get("Content-Type"), "text/xml; charset=utf-8",
|
||||||
|
"Content type for GetFeatureInfo is wrong: %s" % headers.get("Content-Type"))
|
||||||
|
self.assertTrue(
|
||||||
|
str(response).find('<ServiceException code="Security">') != -1,
|
||||||
|
"Not allowed do a GetFeatureInfo on Country"
|
||||||
|
)
|
||||||
|
|
||||||
|
query_string = "&".join(["%s=%s" % i for i in list({
|
||||||
|
"SERVICE": "WMS",
|
||||||
|
"VERSION": "1.1.1",
|
||||||
|
"REQUEST": "GetFeatureInfo",
|
||||||
|
"LAYERS": "Hello_SubsetString",
|
||||||
|
"QUERY_LAYERS": "Hello_SubsetString",
|
||||||
|
"STYLES": "",
|
||||||
|
"FORMAT": "image/png",
|
||||||
|
"BBOX": "-16817707,-6318936.5,5696513,16195283.5",
|
||||||
|
"HEIGHT": "500",
|
||||||
|
"WIDTH": "500",
|
||||||
|
"SRS": "EPSG:3857",
|
||||||
|
"FEATURE_COUNT": "10",
|
||||||
|
"INFO_FORMAT": "application/vnd.ogc.gml",
|
||||||
|
"X": "56",
|
||||||
|
"Y": "144",
|
||||||
|
"MAP": urllib.parse.quote(self.projectPath)
|
||||||
|
}.items())])
|
||||||
response, headers = self._get_restricted(query_string)
|
response, headers = self._get_restricted(query_string)
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
str(response).find("<qgs:pk>") != -1,
|
str(response).find("<qgs:pk>") != -1,
|
||||||
|
@ -69,7 +69,16 @@ class TestQgsServerWMS(QgsServerTestBase):
|
|||||||
for request in ('GetCapabilities', 'GetProjectSettings', 'GetContext'):
|
for request in ('GetCapabilities', 'GetProjectSettings', 'GetContext'):
|
||||||
self.wms_request_compare(request)
|
self.wms_request_compare(request)
|
||||||
|
|
||||||
# Test getfeatureinfo response
|
# Test getfeatureinfo response xml
|
||||||
|
self.wms_request_compare('GetFeatureInfo',
|
||||||
|
'&layers=testlayer%20%C3%A8%C3%A9&styles=&' +
|
||||||
|
'info_format=text%2Fxml&transparent=true&' +
|
||||||
|
'width=600&height=400&srs=EPSG%3A3857&bbox=913190.6389747962%2C' +
|
||||||
|
'5606005.488876367%2C913235.426296057%2C5606035.347090538&' +
|
||||||
|
'query_layers=testlayer%20%C3%A8%C3%A9&X=190&Y=320',
|
||||||
|
'wms_getfeatureinfo-text-xml')
|
||||||
|
|
||||||
|
# Test getfeatureinfo response html
|
||||||
self.wms_request_compare('GetFeatureInfo',
|
self.wms_request_compare('GetFeatureInfo',
|
||||||
'&layers=testlayer%20%C3%A8%C3%A9&styles=&' +
|
'&layers=testlayer%20%C3%A8%C3%A9&styles=&' +
|
||||||
'info_format=text%2Fhtml&transparent=true&' +
|
'info_format=text%2Fhtml&transparent=true&' +
|
||||||
|
14
tests/testdata/qgis_server/wms_getfeatureinfo-text-xml.txt
vendored
Normal file
14
tests/testdata/qgis_server/wms_getfeatureinfo-text-xml.txt
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
*****
|
||||||
|
Content-Type: text/xml; charset=utf-8
|
||||||
|
|
||||||
|
<GetFeatureInfoResponse>
|
||||||
|
<Layer name="testlayer èé">
|
||||||
|
<Feature id="2">
|
||||||
|
<Attribute value="3" name="id"/>
|
||||||
|
<Attribute value="three" name="name"/>
|
||||||
|
<Attribute value="three èé↓" name="utf8nameè"/>
|
||||||
|
<BoundingBox maxy="5606011.4565" maxx="913204.9128" miny="5606011.4565" CRS="EPSG:3857" minx="913204.9128"/>
|
||||||
|
<Attribute type="derived" value="Point (913204.9128 5606011.4565)" name="geometry"/>
|
||||||
|
</Feature>
|
||||||
|
</Layer>
|
||||||
|
</GetFeatureInfoResponse>
|
Loading…
x
Reference in New Issue
Block a user