Compare commits

...

8 Commits

Author SHA1 Message Date
Björn
ba2070b3e3
Merge 24bbdda53918b2c234f01cadd1f1b3b7c61b38ff into 08dd318614d21eb557a1311775b1a1dff509d3b4 2025-06-30 20:46:46 +02:00
pathmapper
24bbdda539 Add tests for explicitly enabling and disabling maptips 2025-06-12 12:50:30 +02:00
pathmapper
c3641ecdad Fix test 2025-06-09 10:37:50 +02:00
pathmapper
a36f64edba Update option description in UI 2025-06-09 10:21:08 +02:00
pathmapper
7181b40dea Add check for empty maptips to the project validator 2025-06-09 10:15:16 +02:00
pathmapper
37b2f2257d Address code review comments 2025-06-06 14:25:00 +02:00
pathmapper
30798bb462 Better wording 2025-06-06 10:24:14 +02:00
pathmapper
52a05a08bd Add project setting to enable HTML GetFeatureInfo maptip-only mode 2025-06-06 10:10:55 +02:00
17 changed files with 5047 additions and 15 deletions

View File

@ -4,6 +4,7 @@ QgsProjectServerValidator.LayerShortName = QgsProjectServerValidator.ValidationE
QgsProjectServerValidator.LayerEncoding = QgsProjectServerValidator.ValidationError.LayerEncoding QgsProjectServerValidator.LayerEncoding = QgsProjectServerValidator.ValidationError.LayerEncoding
QgsProjectServerValidator.ProjectShortName = QgsProjectServerValidator.ValidationError.ProjectShortName QgsProjectServerValidator.ProjectShortName = QgsProjectServerValidator.ValidationError.ProjectShortName
QgsProjectServerValidator.ProjectRootNameConflict = QgsProjectServerValidator.ValidationError.ProjectRootNameConflict QgsProjectServerValidator.ProjectRootNameConflict = QgsProjectServerValidator.ValidationError.ProjectRootNameConflict
QgsProjectServerValidator.OnlyMaptipTrueButEmptyMaptip = QgsProjectServerValidator.ValidationError.OnlyMaptipTrueButEmptyMaptip
try: try:
QgsProjectServerValidator.ValidationResult.__attribute_docs__ = {'error': 'Error which occurred during the validation process.', 'identifier': 'Identifier related to the error. It can be a layer/group name.'} QgsProjectServerValidator.ValidationResult.__attribute_docs__ = {'error': 'Error which occurred during the validation process.', 'identifier': 'Identifier related to the error. It can be a layer/group name.'}
QgsProjectServerValidator.ValidationResult.__annotations__ = {'error': 'QgsProjectServerValidator.ValidationError', 'identifier': 'object'} QgsProjectServerValidator.ValidationResult.__annotations__ = {'error': 'QgsProjectServerValidator.ValidationError', 'identifier': 'object'}

View File

@ -33,6 +33,7 @@ project.
LayerEncoding, LayerEncoding,
ProjectShortName, ProjectShortName,
ProjectRootNameConflict, ProjectRootNameConflict,
OnlyMaptipTrueButEmptyMaptip,
}; };
static QString displayValidationError( QgsProjectServerValidator::ValidationError error ); static QString displayValidationError( QgsProjectServerValidator::ValidationError error );

View File

@ -23,6 +23,7 @@ try:
QgsServerProjectUtils.wmsInfoFormatSia2045 = staticmethod(QgsServerProjectUtils.wmsInfoFormatSia2045) QgsServerProjectUtils.wmsInfoFormatSia2045 = staticmethod(QgsServerProjectUtils.wmsInfoFormatSia2045)
QgsServerProjectUtils.wmsFeatureInfoAddWktGeometry = staticmethod(QgsServerProjectUtils.wmsFeatureInfoAddWktGeometry) QgsServerProjectUtils.wmsFeatureInfoAddWktGeometry = staticmethod(QgsServerProjectUtils.wmsFeatureInfoAddWktGeometry)
QgsServerProjectUtils.wmsFeatureInfoUseAttributeFormSettings = staticmethod(QgsServerProjectUtils.wmsFeatureInfoUseAttributeFormSettings) QgsServerProjectUtils.wmsFeatureInfoUseAttributeFormSettings = staticmethod(QgsServerProjectUtils.wmsFeatureInfoUseAttributeFormSettings)
QgsServerProjectUtils.wmsHTMLFeatureInfoUseOnlyMaptip = staticmethod(QgsServerProjectUtils.wmsHTMLFeatureInfoUseOnlyMaptip)
QgsServerProjectUtils.wmsFeatureInfoSegmentizeWktGeometry = staticmethod(QgsServerProjectUtils.wmsFeatureInfoSegmentizeWktGeometry) QgsServerProjectUtils.wmsFeatureInfoSegmentizeWktGeometry = staticmethod(QgsServerProjectUtils.wmsFeatureInfoSegmentizeWktGeometry)
QgsServerProjectUtils.wmsAddLegendGroupsLegendGraphic = staticmethod(QgsServerProjectUtils.wmsAddLegendGroupsLegendGraphic) QgsServerProjectUtils.wmsAddLegendGroupsLegendGraphic = staticmethod(QgsServerProjectUtils.wmsAddLegendGroupsLegendGraphic)
QgsServerProjectUtils.wmsSkipNameForGroup = staticmethod(QgsServerProjectUtils.wmsSkipNameForGroup) QgsServerProjectUtils.wmsSkipNameForGroup = staticmethod(QgsServerProjectUtils.wmsSkipNameForGroup)

View File

@ -252,6 +252,20 @@ the feature info response
feature info response feature info response
%End %End
static bool wmsHTMLFeatureInfoUseOnlyMaptip( const QgsProject &project );
%Docstring
Returns if only the maptip should be used for HTML feature info response
so that the HTML response to the feature info request only contains the
maptip. If no maptip is set, the HTML response is empty.
:param project: the QGIS project
:return: true if only the maptip should be used for the feature info
response only
.. versionadded:: 4.0
%End
static bool wmsFeatureInfoSegmentizeWktGeometry( const QgsProject &project ); static bool wmsFeatureInfoSegmentizeWktGeometry( const QgsProject &project );
%Docstring %Docstring
Returns if the geometry has to be segmentize in GetFeatureInfo request. Returns if the geometry has to be segmentize in GetFeatureInfo request.

View File

@ -33,6 +33,7 @@ project.
LayerEncoding, LayerEncoding,
ProjectShortName, ProjectShortName,
ProjectRootNameConflict, ProjectRootNameConflict,
OnlyMaptipTrueButEmptyMaptip,
}; };
static QString displayValidationError( QgsProjectServerValidator::ValidationError error ); static QString displayValidationError( QgsProjectServerValidator::ValidationError error );

View File

@ -23,6 +23,7 @@ try:
QgsServerProjectUtils.wmsInfoFormatSia2045 = staticmethod(QgsServerProjectUtils.wmsInfoFormatSia2045) QgsServerProjectUtils.wmsInfoFormatSia2045 = staticmethod(QgsServerProjectUtils.wmsInfoFormatSia2045)
QgsServerProjectUtils.wmsFeatureInfoAddWktGeometry = staticmethod(QgsServerProjectUtils.wmsFeatureInfoAddWktGeometry) QgsServerProjectUtils.wmsFeatureInfoAddWktGeometry = staticmethod(QgsServerProjectUtils.wmsFeatureInfoAddWktGeometry)
QgsServerProjectUtils.wmsFeatureInfoUseAttributeFormSettings = staticmethod(QgsServerProjectUtils.wmsFeatureInfoUseAttributeFormSettings) QgsServerProjectUtils.wmsFeatureInfoUseAttributeFormSettings = staticmethod(QgsServerProjectUtils.wmsFeatureInfoUseAttributeFormSettings)
QgsServerProjectUtils.wmsHTMLFeatureInfoUseOnlyMaptip = staticmethod(QgsServerProjectUtils.wmsHTMLFeatureInfoUseOnlyMaptip)
QgsServerProjectUtils.wmsFeatureInfoSegmentizeWktGeometry = staticmethod(QgsServerProjectUtils.wmsFeatureInfoSegmentizeWktGeometry) QgsServerProjectUtils.wmsFeatureInfoSegmentizeWktGeometry = staticmethod(QgsServerProjectUtils.wmsFeatureInfoSegmentizeWktGeometry)
QgsServerProjectUtils.wmsAddLegendGroupsLegendGraphic = staticmethod(QgsServerProjectUtils.wmsAddLegendGroupsLegendGraphic) QgsServerProjectUtils.wmsAddLegendGroupsLegendGraphic = staticmethod(QgsServerProjectUtils.wmsAddLegendGroupsLegendGraphic)
QgsServerProjectUtils.wmsSkipNameForGroup = staticmethod(QgsServerProjectUtils.wmsSkipNameForGroup) QgsServerProjectUtils.wmsSkipNameForGroup = staticmethod(QgsServerProjectUtils.wmsSkipNameForGroup)

View File

@ -252,6 +252,20 @@ the feature info response
feature info response feature info response
%End %End
static bool wmsHTMLFeatureInfoUseOnlyMaptip( const QgsProject &project );
%Docstring
Returns if only the maptip should be used for HTML feature info response
so that the HTML response to the feature info request only contains the
maptip. If no maptip is set, the HTML response is empty.
:param project: the QGIS project
:return: true if only the maptip should be used for the feature info
response only
.. versionadded:: 4.0
%End
static bool wmsFeatureInfoSegmentizeWktGeometry( const QgsProject &project ); static bool wmsFeatureInfoSegmentizeWktGeometry( const QgsProject &project );
%Docstring %Docstring
Returns if the geometry has to be segmentize in GetFeatureInfo request. Returns if the geometry has to be segmentize in GetFeatureInfo request.

View File

@ -736,6 +736,9 @@ QgsProjectProperties::QgsProjectProperties( QgsMapCanvas *mapCanvas, QWidget *pa
bool useAttributeFormSettings = QgsProject::instance()->readBoolEntry( QStringLiteral( "WMSFeatureInfoUseAttributeFormSettings" ), QStringLiteral( "/" ) ); bool useAttributeFormSettings = QgsProject::instance()->readBoolEntry( QStringLiteral( "WMSFeatureInfoUseAttributeFormSettings" ), QStringLiteral( "/" ) );
mUseAttributeFormSettingsCheckBox->setChecked( useAttributeFormSettings ); mUseAttributeFormSettingsCheckBox->setChecked( useAttributeFormSettings );
bool useOnlyMaptip = QgsProject::instance()->readBoolEntry( QStringLiteral( "WMSHTMLFeatureInfoUseOnlyMaptip" ), QStringLiteral( "/" ) );
mHTMLFiOnlyMaptip->setChecked( useOnlyMaptip );
bool addWktGeometry = QgsProject::instance()->readBoolEntry( QStringLiteral( "WMSAddWktGeometry" ), QStringLiteral( "/" ) ); bool addWktGeometry = QgsProject::instance()->readBoolEntry( QStringLiteral( "WMSAddWktGeometry" ), QStringLiteral( "/" ) );
mAddWktGeometryCheckBox->setChecked( addWktGeometry ); mAddWktGeometryCheckBox->setChecked( addWktGeometry );
@ -1566,6 +1569,7 @@ void QgsProjectProperties::apply()
} }
QgsProject::instance()->writeEntry( QStringLiteral( "WMSFeatureInfoUseAttributeFormSettings" ), QStringLiteral( "/" ), mUseAttributeFormSettingsCheckBox->isChecked() ); QgsProject::instance()->writeEntry( QStringLiteral( "WMSFeatureInfoUseAttributeFormSettings" ), QStringLiteral( "/" ), mUseAttributeFormSettingsCheckBox->isChecked() );
QgsProject::instance()->writeEntry( QStringLiteral( "WMSHTMLFeatureInfoUseOnlyMaptip" ), QStringLiteral( "/" ), mHTMLFiOnlyMaptip->isChecked() );
QgsProject::instance()->writeEntry( QStringLiteral( "WMSAddWktGeometry" ), QStringLiteral( "/" ), mAddWktGeometryCheckBox->isChecked() ); QgsProject::instance()->writeEntry( QStringLiteral( "WMSAddWktGeometry" ), QStringLiteral( "/" ), mAddWktGeometryCheckBox->isChecked() );
QgsProject::instance()->writeEntry( QStringLiteral( "WMSSegmentizeFeatureInfoGeometry" ), QStringLiteral( "/" ), mSegmentizeFeatureInfoGeometryCheckBox->isChecked() ); QgsProject::instance()->writeEntry( QStringLiteral( "WMSSegmentizeFeatureInfoGeometry" ), QStringLiteral( "/" ), mSegmentizeFeatureInfoGeometryCheckBox->isChecked() );
QgsProject::instance()->writeEntry( QStringLiteral( "WMSAddLayerGroupsLegendGraphic" ), QStringLiteral( "/" ), mAddLayerGroupsLegendGraphicCheckBox->isChecked() ); QgsProject::instance()->writeEntry( QStringLiteral( "WMSAddLayerGroupsLegendGraphic" ), QStringLiteral( "/" ), mAddLayerGroupsLegendGraphicCheckBox->isChecked() );

View File

@ -37,6 +37,8 @@ QString QgsProjectServerValidator::displayValidationError( QgsProjectServerValid
return QObject::tr( "The project root name (either the project short name or project title) is not valid. It must start with an unaccented alphabetical letter, followed by any alphanumeric letters, dot, dash or underscore" ); return QObject::tr( "The project root name (either the project short name or project title) is not valid. It must start with an unaccented alphabetical letter, followed by any alphanumeric letters, dot, dash or underscore" );
case QgsProjectServerValidator::ProjectRootNameConflict: case QgsProjectServerValidator::ProjectRootNameConflict:
return QObject::tr( "The project root name (either the project short name or project title) is already used by a layer or a group" ); return QObject::tr( "The project root name (either the project short name or project title) is already used by a layer or a group" );
case QgsProjectServerValidator::OnlyMaptipTrueButEmptyMaptip:
return QObject::tr( "Use only maptip for HTML GetFeatureInfo response is enabled but the HTML maptip is empty" );
} }
return QString(); return QString();
} }
@ -49,7 +51,7 @@ QString getShortName( T *node )
return shortName.isEmpty() ? node->name() : shortName; return shortName.isEmpty() ? node->name() : shortName;
} }
void QgsProjectServerValidator::browseLayerTree( QgsLayerTreeGroup *treeGroup, QStringList &owsNames, QStringList &encodingMessages ) void QgsProjectServerValidator::browseLayerTree( QgsLayerTreeGroup *treeGroup, QStringList &owsNames, QStringList &encodingMessages, QStringList &layerNames, QStringList &maptipTemplates )
{ {
const QList< QgsLayerTreeNode * > treeGroupChildren = treeGroup->children(); const QList< QgsLayerTreeNode * > treeGroupChildren = treeGroup->children();
for ( int i = 0; i < treeGroupChildren.size(); ++i ) for ( int i = 0; i < treeGroupChildren.size(); ++i )
@ -59,7 +61,7 @@ void QgsProjectServerValidator::browseLayerTree( QgsLayerTreeGroup *treeGroup, Q
{ {
QgsLayerTreeGroup *treeGroupChild = static_cast<QgsLayerTreeGroup *>( treeNode ); QgsLayerTreeGroup *treeGroupChild = static_cast<QgsLayerTreeGroup *>( treeNode );
owsNames << getShortName( treeGroupChild ); owsNames << getShortName( treeGroupChild );
browseLayerTree( treeGroupChild, owsNames, encodingMessages ); browseLayerTree( treeGroupChild, owsNames, encodingMessages, layerNames, maptipTemplates );
} }
else else
{ {
@ -74,11 +76,22 @@ void QgsProjectServerValidator::browseLayerTree( QgsLayerTreeGroup *treeGroup, Q
if ( vl->dataProvider() && vl->dataProvider()->encoding() == QLatin1String( "System" ) ) if ( vl->dataProvider() && vl->dataProvider()->encoding() == QLatin1String( "System" ) )
encodingMessages << layer->name(); encodingMessages << layer->name();
} }
layerNames << treeLayer->name();
maptipTemplates << layer->mapTipTemplate();
} }
} }
} }
} }
bool QgsProjectServerValidator::isOnlyMaptipEnabled( QgsProject *project )
{
return project->readBoolEntry(
QStringLiteral( "WMSHTMLFeatureInfoUseOnlyMaptip" ),
QString(),
false
);
}
bool QgsProjectServerValidator::validate( QgsProject *project, QList<QgsProjectServerValidator::ValidationResult> &results ) bool QgsProjectServerValidator::validate( QgsProject *project, QList<QgsProjectServerValidator::ValidationResult> &results )
{ {
results.clear(); results.clear();
@ -90,8 +103,8 @@ bool QgsProjectServerValidator::validate( QgsProject *project, QList<QgsProjectS
if ( !project->layerTreeRoot() ) if ( !project->layerTreeRoot() )
return false; return false;
QStringList owsNames, encodingMessages; QStringList owsNames, encodingMessages, layerNames, maptipTemplates;
browseLayerTree( project->layerTreeRoot(), owsNames, encodingMessages ); browseLayerTree( project->layerTreeRoot(), owsNames, encodingMessages, layerNames, maptipTemplates );
QStringList duplicateNames, regExpMessages; QStringList duplicateNames, regExpMessages;
const thread_local QRegularExpression snRegExp = QgsApplication::shortNameRegularExpression(); const thread_local QRegularExpression snRegExp = QgsApplication::shortNameRegularExpression();
@ -152,6 +165,24 @@ bool QgsProjectServerValidator::validate( QgsProject *project, QList<QgsProjectS
results << ValidationResult( QgsProjectServerValidator::ProjectShortName, rootLayerName ); results << ValidationResult( QgsProjectServerValidator::ProjectShortName, rootLayerName );
} }
} }
if ( isOnlyMaptipEnabled( project ) )
{
QStringList emptyLayers;
for ( int i = 0; i < maptipTemplates.size(); ++i )
{
if ( maptipTemplates[i].trimmed().isEmpty() )
emptyLayers << layerNames[i];
}
if ( !emptyLayers.isEmpty() )
{
result = false;
QString details = emptyLayers.join( QLatin1String( ", " ) ).toHtmlEscaped();
results << ValidationResult(
QgsProjectServerValidator::OnlyMaptipTrueButEmptyMaptip,
details );
}
}
return result; return result;
} }

View File

@ -47,6 +47,7 @@ class CORE_EXPORT QgsProjectServerValidator
LayerEncoding = 2, //!< Encoding is not correctly set on a vector layer. LayerEncoding = 2, //!< Encoding is not correctly set on a vector layer.
ProjectShortName = 3, //!< The project short name is not valid. ProjectShortName = 3, //!< The project short name is not valid.
ProjectRootNameConflict = 4, //!< The project root name is already used by a layer or a group. ProjectRootNameConflict = 4, //!< The project root name is already used by a layer or a group.
OnlyMaptipTrueButEmptyMaptip = 5, //!< Use only maptip for HTML GetFeatureInfo response is enabled but HTML maptip is empty
}; };
/** /**
@ -92,7 +93,8 @@ class CORE_EXPORT QgsProjectServerValidator
static bool validate( QgsProject *project, QList< QgsProjectServerValidator::ValidationResult > &results SIP_OUT ); static bool validate( QgsProject *project, QList< QgsProjectServerValidator::ValidationResult > &results SIP_OUT );
private: private:
static void browseLayerTree( QgsLayerTreeGroup *treeGroup, QStringList &owsNames, QStringList &encodingMessages ); static void browseLayerTree( QgsLayerTreeGroup *treeGroup, QStringList &owsNames, QStringList &encodingMessages, QStringList &layerNames, QStringList &maptipTemplates );
static bool isOnlyMaptipEnabled( QgsProject *project );
}; };

View File

@ -180,6 +180,12 @@ bool QgsServerProjectUtils::wmsFeatureInfoUseAttributeFormSettings( const QgsPro
|| useFormSettings.compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0; || useFormSettings.compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0;
} }
bool QgsServerProjectUtils::wmsHTMLFeatureInfoUseOnlyMaptip( const QgsProject &project )
{
const QString useFormSettings = project.readEntry( QStringLiteral( "WMSHTMLFeatureInfoUseOnlyMaptip" ), QStringLiteral( "/" ), "" );
return useFormSettings.compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0;
}
bool QgsServerProjectUtils::wmsFeatureInfoSegmentizeWktGeometry( const QgsProject &project ) bool QgsServerProjectUtils::wmsFeatureInfoSegmentizeWktGeometry( const QgsProject &project )
{ {
const QString segmGeom = project.readEntry( QStringLiteral( "WMSSegmentizeFeatureInfoGeometry" ), QStringLiteral( "/" ), "" ); const QString segmGeom = project.readEntry( QStringLiteral( "WMSSegmentizeFeatureInfoGeometry" ), QStringLiteral( "/" ), "" );

View File

@ -222,6 +222,16 @@ class SERVER_EXPORT QgsServerProjectUtils
*/ */
static bool wmsFeatureInfoUseAttributeFormSettings( const QgsProject &project ); static bool wmsFeatureInfoUseAttributeFormSettings( const QgsProject &project );
/**
* Returns if only the maptip should be used for HTML feature info response so
* that the HTML response to the feature info request only contains the maptip.
* If no maptip is set, the HTML response is empty.
* \param project the QGIS project
* \returns true if only the maptip should be used for the feature info response only
* \since QGIS 4.0
*/
static bool wmsHTMLFeatureInfoUseOnlyMaptip( const QgsProject &project );
/** /**
* Returns if the geometry has to be segmentize in GetFeatureInfo request. * Returns if the geometry has to be segmentize in GetFeatureInfo request.
* \param project the QGIS project * \param project the QGIS project

View File

@ -2009,7 +2009,7 @@ namespace QgsWms
//add maptip attribute based on html/expression (in case there is no maptip attribute) //add maptip attribute based on html/expression (in case there is no maptip attribute)
QString mapTip = layer->mapTipTemplate(); QString mapTip = layer->mapTipTemplate();
if ( !mapTip.isEmpty() && ( mWmsParameters.withMapTip() || mWmsParameters.htmlInfoOnlyMapTip() ) ) if ( !mapTip.isEmpty() && ( mWmsParameters.withMapTip() || mWmsParameters.htmlInfoOnlyMapTip() || QgsServerProjectUtils::wmsHTMLFeatureInfoUseOnlyMaptip( *mProject ) ) )
{ {
QDomElement maptipElem = infoDocument.createElement( QStringLiteral( "Attribute" ) ); QDomElement maptipElem = infoDocument.createElement( QStringLiteral( "Attribute" ) );
maptipElem.setAttribute( QStringLiteral( "name" ), QStringLiteral( "maptip" ) ); maptipElem.setAttribute( QStringLiteral( "name" ), QStringLiteral( "maptip" ) );
@ -2325,7 +2325,7 @@ namespace QgsWms
} }
//add maptip attribute based on html/expression //add maptip attribute based on html/expression
QString mapTip = layer->mapTipTemplate(); QString mapTip = layer->mapTipTemplate();
if ( !mapTip.isEmpty() && ( mWmsParameters.withMapTip() || mWmsParameters.htmlInfoOnlyMapTip() ) ) if ( !mapTip.isEmpty() && ( mWmsParameters.withMapTip() || mWmsParameters.htmlInfoOnlyMapTip() || QgsServerProjectUtils::wmsHTMLFeatureInfoUseOnlyMaptip( *mProject ) ) )
{ {
QDomElement maptipElem = infoDocument.createElement( QStringLiteral( "Attribute" ) ); QDomElement maptipElem = infoDocument.createElement( QStringLiteral( "Attribute" ) );
maptipElem.setAttribute( QStringLiteral( "name" ), QStringLiteral( "maptip" ) ); maptipElem.setAttribute( QStringLiteral( "name" ), QStringLiteral( "maptip" ) );
@ -2586,7 +2586,7 @@ namespace QgsWms
QByteArray QgsRenderer::convertFeatureInfoToHtml( const QDomDocument &doc ) const QByteArray QgsRenderer::convertFeatureInfoToHtml( const QDomDocument &doc ) const
{ {
const bool onlyMapTip = mWmsParameters.htmlInfoOnlyMapTip(); const bool onlyMapTip = mWmsParameters.htmlInfoOnlyMapTip() || QgsServerProjectUtils::wmsHTMLFeatureInfoUseOnlyMaptip( *mProject );
QString featureInfoString = QStringLiteral( " <!DOCTYPE html>" ); QString featureInfoString = QStringLiteral( " <!DOCTYPE html>" );
if ( !onlyMapTip ) if ( !onlyMapTip )
{ {
@ -3203,7 +3203,7 @@ namespace QgsWms
{ {
QString mapTip = layer->mapTipTemplate(); QString mapTip = layer->mapTipTemplate();
if ( !mapTip.isEmpty() && ( mWmsParameters.withMapTip() || mWmsParameters.htmlInfoOnlyMapTip() ) ) if ( !mapTip.isEmpty() && ( mWmsParameters.withMapTip() || mWmsParameters.htmlInfoOnlyMapTip() || QgsServerProjectUtils::wmsHTMLFeatureInfoUseOnlyMaptip( *mProject ) ) )
{ {
QString fieldTextString = QgsExpression::replaceExpressionText( mapTip, &expressionContext ); QString fieldTextString = QgsExpression::replaceExpressionText( mapTip, &expressionContext );
QDomElement fieldElem = doc.createElement( QStringLiteral( "qgs:maptip" ) ); QDomElement fieldElem = doc.createElement( QStringLiteral( "qgs:maptip" ) );

View File

@ -2730,6 +2730,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0">
<widget class="QCheckBox" name="mHTMLFiOnlyMaptip">
<property name="text">
<string>Use only maptip for HTML GetFeatureInfo (empty response when maptip template is missing)</string>
</property>
</widget>
</item>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QCheckBox" name="mWmsUseLayerIDs"> <widget class="QCheckBox" name="mWmsUseLayerIDs">
<property name="text"> <property name="text">
@ -2737,7 +2744,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0"> <item row="5" column="0">
<layout class="QHBoxLayout" name="grpWMSPrecision"> <layout class="QHBoxLayout" name="grpWMSPrecision">
<item> <item>
<widget class="QLabel" name="label_5"> <widget class="QLabel" name="label_5">
@ -2761,21 +2768,21 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="3" column="0"> <item row="4" column="0">
<widget class="QCheckBox" name="mSegmentizeFeatureInfoGeometryCheckBox"> <widget class="QCheckBox" name="mSegmentizeFeatureInfoGeometryCheckBox">
<property name="text"> <property name="text">
<string>Segmentize feature info geometry</string> <string>Segmentize feature info geometry</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0"> <item row="3" column="0">
<widget class="QCheckBox" name="mAddWktGeometryCheckBox"> <widget class="QCheckBox" name="mAddWktGeometryCheckBox">
<property name="text"> <property name="text">
<string>Add geometry to feature response</string> <string>Add geometry to feature response</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="0"> <item row="6" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2"> <layout class="QHBoxLayout" name="horizontalLayout_2">
<item> <item>
<widget class="QLabel" name="mWMSUrlLabel"> <widget class="QLabel" name="mWMSUrlLabel">
@ -3765,6 +3772,7 @@
<tabstop>mWMSInspireMetadataDate</tabstop> <tabstop>mWMSInspireMetadataDate</tabstop>
<tabstop>mWmsUseLayerIDs</tabstop> <tabstop>mWmsUseLayerIDs</tabstop>
<tabstop>mUseAttributeFormSettingsCheckBox</tabstop> <tabstop>mUseAttributeFormSettingsCheckBox</tabstop>
<tabstop>mHTMLFiOnlyMaptip</tabstop>
<tabstop>mAddWktGeometryCheckBox</tabstop> <tabstop>mAddWktGeometryCheckBox</tabstop>
<tabstop>mSegmentizeFeatureInfoGeometryCheckBox</tabstop> <tabstop>mSegmentizeFeatureInfoGeometryCheckBox</tabstop>
<tabstop>mWMSPrecisionSpinBox</tabstop> <tabstop>mWMSPrecisionSpinBox</tabstop>

View File

@ -124,6 +124,60 @@ class TestQgsprojectServerValidator(QgisTestCase):
results[0].error, results[0].error,
) )
def test_empty_maptip_enabled(self):
"""Empty maptip must fail when onlymaptip is enabled."""
project = QgsProject()
layer = QgsVectorLayer("Point?field=fldtxt:string", "testlayer", "memory")
project.addMapLayers([layer])
layer.setMapTipTemplate("")
project.writeEntry("WMSHTMLFeatureInfoUseOnlyMaptip", "", True)
valid, results = QgsProjectServerValidator.validate(project)
self.assertFalse(valid)
self.assertEqual(1, len(results))
self.assertEqual(
QgsProjectServerValidator.ValidationError.OnlyMaptipTrueButEmptyMaptip,
results[0].error,
)
# Explicitly enable MapTips — should still fail
layer.setMapTipsEnabled(True)
valid2, results2 = QgsProjectServerValidator.validate(project)
self.assertFalse(valid2)
self.assertEqual(1, len(results2))
self.assertEqual(
QgsProjectServerValidator.ValidationError.OnlyMaptipTrueButEmptyMaptip,
results2[0].error,
)
# Explicitly disable MapTips — should still fail
layer.setMapTipsEnabled(False)
valid3, results3 = QgsProjectServerValidator.validate(project)
self.assertFalse(valid3)
self.assertEqual(1, len(results3))
self.assertEqual(
QgsProjectServerValidator.ValidationError.OnlyMaptipTrueButEmptyMaptip,
results3[0].error,
)
def test_empty_maptip_disabled(self):
"""Empty maptip must pass when onlymaptip is disabled."""
project = QgsProject()
layer = QgsVectorLayer("Point?field=fldtxt:string", "testlayer", "memory")
project.addMapLayers([layer])
layer.setMapTipTemplate("")
project.writeEntry("WMSHTMLFeatureInfoUseOnlyMaptip", "", False)
valid, results = QgsProjectServerValidator.validate(project)
self.assertTrue(valid)
self.assertEqual(0, len(results))
# Explicitly enable MapTips — should still pass
layer.setMapTipsEnabled(True)
valid2, results2 = QgsProjectServerValidator.validate(project)
self.assertTrue(valid2)
self.assertEqual(0, len(results2))
# Explicitly disable MapTips — should still pass
layer.setMapTipsEnabled(False)
valid3, results3 = QgsProjectServerValidator.validate(project)
self.assertTrue(valid3)
self.assertEqual(0, len(results3))
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()

View File

@ -174,7 +174,7 @@ class TestQgsServerWMSGetFeatureInfo(TestQgsServerWMSTestBase):
"wms_getfeatureinfo-text-html-maptip", "wms_getfeatureinfo-text-html-maptip",
) )
# Test getfeatureinfo response html only with maptip for vector layer # Test getfeatureinfo response html only with maptip for vector layer (URL parameter)
self.wms_request_compare( self.wms_request_compare(
"GetFeatureInfo", "GetFeatureInfo",
"&layers=testlayer%20%C3%A8%C3%A9&styles=&" "&layers=testlayer%20%C3%A8%C3%A9&styles=&"
@ -186,6 +186,18 @@ class TestQgsServerWMSGetFeatureInfo(TestQgsServerWMSTestBase):
"wms_getfeatureinfo-html-only-with-maptip-vector", "wms_getfeatureinfo-html-only-with-maptip-vector",
) )
# Test getfeatureinfo response html only with maptip for vector layer (project settings)
self.wms_request_compare(
"GetFeatureInfo",
"&layers=testlayer%20%C3%A8%C3%A9&styles=&"
+ "info_format=text%2Fhtml&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-html-only-with-maptip-vector",
"test_project_html_gfi_maptip_only.qgs",
)
# Test getfeatureinfo response html with maptip and display name in text mode for vector layer # Test getfeatureinfo response html with maptip and display name in text mode for vector layer
self.wms_request_compare( self.wms_request_compare(
"GetFeatureInfo", "GetFeatureInfo",
@ -352,7 +364,7 @@ class TestQgsServerWMSGetFeatureInfo(TestQgsServerWMSTestBase):
"wms_getfeatureinfo-raster-text-xml-maptip", "wms_getfeatureinfo-raster-text-xml-maptip",
) )
# Test GetFeatureInfo on raster layer HTML only with maptip # Test GetFeatureInfo on raster layer HTML only with maptip (URL parameter)
self.wms_request_compare( self.wms_request_compare(
"GetFeatureInfo", "GetFeatureInfo",
"&layers=landsat&styles=&" "&layers=landsat&styles=&"
@ -364,6 +376,18 @@ class TestQgsServerWMSGetFeatureInfo(TestQgsServerWMSTestBase):
"wms_getfeatureinfo-html-only-with-maptip-raster", "wms_getfeatureinfo-html-only-with-maptip-raster",
) )
# Test GetFeatureInfo on raster layer HTML only with maptip (project settings)
self.wms_request_compare(
"GetFeatureInfo",
"&layers=landsat&styles=&"
+ "info_format=text%2Fhtml&transparent=true&"
+ "width=500&height=500&srs=EPSG%3A3857&"
+ "bbox=1989139.6,3522745.0,2015014.9,3537004.5&"
+ "query_layers=landsat&X=250&Y=250",
"wms_getfeatureinfo-html-only-with-maptip-raster",
"test_project_html_gfi_maptip_only.qgs",
)
def testGetFeatureInfoValueRelation(self): def testGetFeatureInfoValueRelation(self):
"""Test GetFeatureInfo resolves "value relation" widget values. regression 18518""" """Test GetFeatureInfo resolves "value relation" widget values. regression 18518"""
mypath = self.testdata_path + "test_project_values.qgz" mypath = self.testdata_path + "test_project_values.qgz"

File diff suppressed because it is too large Load Diff