Propagate WMS identify GML schema error and show it in results, fixes part of #8724

This commit is contained in:
Radim Blazek 2013-10-17 13:56:31 +02:00
parent 491231e600
commit d5f167f1db
5 changed files with 144 additions and 91 deletions

View File

@ -57,7 +57,6 @@ QString QgsError::message( QgsErrorMessage::Format theFormat ) const
// and there are no local not commited changes
QString hash = QString( QGis::QGIS_DEV_VERSION );
QString remote = QString( QGS_GIT_REMOTE_URL );
QgsDebugMsg( "remote = " + remote );
if ( !hash.isEmpty() && !remote.isEmpty() && remote.contains( "github.com" ) )
{
QString path = remote.remove( QRegExp( ".*github.com[:/]" ) ).remove( ".git" );
@ -79,9 +78,29 @@ QString QgsError::message( QgsErrorMessage::Format theFormat ) const
if ( theFormat == QgsErrorMessage::Text )
{
str += m.tag() + " " + m.message();
if ( !str.isEmpty() )
{
str += "\n"; // new message
}
if ( !m.tag().isEmpty() )
{
str += m.tag() + " ";
}
str += m.message();
#ifdef QGISDEBUG
str += QString( "\nat %1 : %2 : %3" ).arg( file ).arg( m.line() ).arg( m.function() );
QString where;
if ( !file.isEmpty() )
{
where += QString( "file: %1 row: %2" ).arg( file ).arg( m.line() );
}
if ( !m.function().isEmpty() )
{
where += QString( "function %1:" ).arg( m.function() );
}
if ( !where.isEmpty() )
{
str += QString( " (%1)" ).arg( where );
}
#endif
}
else // QgsErrorMessage::Html

View File

@ -15,6 +15,7 @@
#include "qgsgmlschema.h"
#include "qgsrectangle.h"
#include "qgscoordinatereferencesystem.h"
#include "qgserror.h"
#include "qgsgeometry.h"
#include "qgslogger.h"
#include "qgsnetworkaccessmanager.h"
@ -337,8 +338,17 @@ bool QgsGmlSchema::guessSchema( const QByteArray &data )
XML_SetElementHandler( p, QgsGmlSchema::start, QgsGmlSchema::end );
XML_SetCharacterDataHandler( p, QgsGmlSchema::chars );
int atEnd = 1;
XML_Parse( p, data.constData(), data.size(), atEnd );
return 0;
int res = XML_Parse( p, data.constData(), data.size(), atEnd );
if ( res == 0 )
{
QString err = QString( XML_ErrorString( XML_GetErrorCode( p ) ) );
QgsDebugMsg( QString( "XML_Parse returned %1 error %2" ).arg( res ).arg( err ) );
mError = QgsError( err, "GML schema" );
mError.append( tr( "Cannot guess schema" ) );
}
return res != 0;
}
void QgsGmlSchema::startElement( const XML_Char* el, const XML_Char** attr )

View File

@ -19,6 +19,7 @@
#include "qgis.h"
#include "qgsapplication.h"
#include "qgsdataprovider.h"
#include "qgserror.h"
#include "qgsfeature.h"
#include "qgsfield.h"
#include "qgslogger.h"
@ -97,6 +98,9 @@ class CORE_EXPORT QgsGmlSchema: public QObject
/** Get list of geometry attributes for type/class name */
QStringList geometryAttributes( const QString & typeName );
/** Get error if parseXSD() or guessSchema() failed */
QgsError error() const { return mError; }
private:
enum ParseMode
@ -199,6 +203,9 @@ class CORE_EXPORT QgsGmlSchema: public QObject
/* Feature classes map with element paths as keys */
QMap<QString, QgsGmlFeatureClass> mFeatureClassMap;
/* Error set if something failed */
QgsError mError;
};
#endif

View File

@ -376,8 +376,6 @@ bool QgsMapToolIdentify::identifyRasterLayer( QList<IdentifyResult> *results, Qg
QMap< QString, QString > attributes, derivedAttributes;
QMap<int, QVariant> values;
QgsRaster::IdentifyFormat format = QgsRasterDataProvider::identifyFormatFromName( layer->customProperty( "identify/format" ).toString() );
// check if the format is really supported otherwise use first supported format
@ -390,12 +388,13 @@ bool QgsMapToolIdentify::identifyRasterLayer( QList<IdentifyResult> *results, Qg
else return false;
}
QgsRasterIdentifyResult identifyResult;
// We can only use context (extent, width, height) if layer is not reprojected,
// otherwise we don't know source resolution (size).
if ( mCanvas->hasCrsTransformEnabled() && dprovider->crs() != mCanvas->mapRenderer()->destinationCrs() )
{
viewExtent = toLayerCoordinates( layer, viewExtent );
values = dprovider->identify( point, format ).results();
identifyResult = dprovider->identify( point, format );
}
else
{
@ -418,106 +417,117 @@ bool QgsMapToolIdentify::identifyRasterLayer( QList<IdentifyResult> *results, Qg
QgsDebugMsg( QString( "width = %1 height = %2" ).arg( width ).arg( height ) );
QgsDebugMsg( QString( "xRes = %1 yRes = %2 mapUnitsPerPixel = %3" ).arg( viewExtent.width() / width ).arg( viewExtent.height() / height ).arg( mapUnitsPerPixel ) );
values = dprovider->identify( point, format, viewExtent, width, height ).results();
identifyResult = dprovider->identify( point, format, viewExtent, width, height );
}
derivedAttributes.insert( tr( "(clicked coordinate)" ), point.toString() );
//QString type = tr( "Raster" );
QgsGeometry geometry;
if ( format == QgsRaster::IdentifyFormatValue )
if ( identifyResult.isValid() )
{
foreach ( int bandNo, values.keys() )
QMap<int, QVariant> values = identifyResult.results();
QgsGeometry geometry;
if ( format == QgsRaster::IdentifyFormatValue )
{
QString valueString;
if ( values.value( bandNo ).isNull() )
foreach ( int bandNo, values.keys() )
{
valueString = tr( "no data" );
}
else
{
double value = values.value( bandNo ).toDouble();
valueString = QgsRasterBlock::printValue( value );
}
attributes.insert( dprovider->generateBandName( bandNo ), valueString );
}
QString label = layer->name();
results->append( IdentifyResult( qobject_cast<QgsMapLayer *>( layer ), label, attributes, derivedAttributes ) );
}
else if ( format == QgsRaster::IdentifyFormatFeature )
{
foreach ( int i, values.keys() )
{
QVariant value = values.value( i );
if ( value.type() == QVariant::Bool && !value.toBool() )
{
// sublayer not visible or not queryable
continue;
}
if ( value.type() == QVariant::String )
{
// error
// TODO: better error reporting
QString label = layer->subLayers().value( i );
attributes.clear();
attributes.insert( tr( "Error" ), value.toString() );
results->append( IdentifyResult( qobject_cast<QgsMapLayer *>( layer ), label, attributes, derivedAttributes ) );
continue;
}
// list of feature stores for a single sublayer
QgsFeatureStoreList featureStoreList = values.value( i ).value<QgsFeatureStoreList>();
foreach ( QgsFeatureStore featureStore, featureStoreList )
{
foreach ( QgsFeature feature, featureStore.features() )
QString valueString;
if ( values.value( bandNo ).isNull() )
{
valueString = tr( "no data" );
}
else
{
double value = values.value( bandNo ).toDouble();
valueString = QgsRasterBlock::printValue( value );
}
attributes.insert( dprovider->generateBandName( bandNo ), valueString );
}
QString label = layer->name();
results->append( IdentifyResult( qobject_cast<QgsMapLayer *>( layer ), label, attributes, derivedAttributes ) );
}
else if ( format == QgsRaster::IdentifyFormatFeature )
{
foreach ( int i, values.keys() )
{
QVariant value = values.value( i );
if ( value.type() == QVariant::Bool && !value.toBool() )
{
// sublayer not visible or not queryable
continue;
}
if ( value.type() == QVariant::String )
{
// error
// TODO: better error reporting
QString label = layer->subLayers().value( i );
attributes.clear();
// WMS sublayer and feature type, a sublayer may contain multiple feature types.
// Sublayer name may be the same as layer name and feature type name
// may be the same as sublayer. We try to avoid duplicities in label.
QString sublayer = featureStore.params().value( "sublayer" ).toString();
QString featureType = featureStore.params().value( "featureType" ).toString();
// Strip UMN MapServer '_feature'
featureType.remove( "_feature" );
QStringList labels;
if ( sublayer.compare( layer->name(), Qt::CaseInsensitive ) != 0 )
attributes.insert( tr( "Error" ), value.toString() );
results->append( IdentifyResult( qobject_cast<QgsMapLayer *>( layer ), label, attributes, derivedAttributes ) );
continue;
}
// list of feature stores for a single sublayer
QgsFeatureStoreList featureStoreList = values.value( i ).value<QgsFeatureStoreList>();
foreach ( QgsFeatureStore featureStore, featureStoreList )
{
foreach ( QgsFeature feature, featureStore.features() )
{
labels << sublayer;
attributes.clear();
// WMS sublayer and feature type, a sublayer may contain multiple feature types.
// Sublayer name may be the same as layer name and feature type name
// may be the same as sublayer. We try to avoid duplicities in label.
QString sublayer = featureStore.params().value( "sublayer" ).toString();
QString featureType = featureStore.params().value( "featureType" ).toString();
// Strip UMN MapServer '_feature'
featureType.remove( "_feature" );
QStringList labels;
if ( sublayer.compare( layer->name(), Qt::CaseInsensitive ) != 0 )
{
labels << sublayer;
}
if ( featureType.compare( sublayer, Qt::CaseInsensitive ) != 0 || labels.isEmpty() )
{
labels << featureType;
}
QMap< QString, QString > derAttributes = derivedAttributes;
derAttributes.unite( featureDerivedAttributes( &feature, layer ) );
IdentifyResult identifyResult( qobject_cast<QgsMapLayer *>( layer ), labels.join( " / " ), featureStore.fields(), feature, derAttributes );
identifyResult.mParams.insert( "getFeatureInfoUrl", featureStore.params().value( "getFeatureInfoUrl" ) );
results->append( identifyResult );
}
if ( featureType.compare( sublayer, Qt::CaseInsensitive ) != 0 || labels.isEmpty() )
{
labels << featureType;
}
QMap< QString, QString > derAttributes = derivedAttributes;
derAttributes.unite( featureDerivedAttributes( &feature, layer ) );
IdentifyResult identifyResult( qobject_cast<QgsMapLayer *>( layer ), labels.join( " / " ), featureStore.fields(), feature, derAttributes );
identifyResult.mParams.insert( "getFeatureInfoUrl", featureStore.params().value( "getFeatureInfoUrl" ) );
results->append( identifyResult );
}
}
}
}
else // text or html
{
QgsDebugMsg( QString( "%1 html or text values" ).arg( values.size() ) );
foreach ( int bandNo, values.keys() )
else // text or html
{
QString value = values.value( bandNo ).toString();
attributes.clear();
attributes.insert( "", value );
QgsDebugMsg( QString( "%1 html or text values" ).arg( values.size() ) );
foreach ( int bandNo, values.keys() )
{
QString value = values.value( bandNo ).toString();
attributes.clear();
attributes.insert( "", value );
QString label = layer->subLayers().value( bandNo );
results->append( IdentifyResult( qobject_cast<QgsMapLayer *>( layer ), label, attributes, derivedAttributes ) );
QString label = layer->subLayers().value( bandNo );
results->append( IdentifyResult( qobject_cast<QgsMapLayer *>( layer ), label, attributes, derivedAttributes ) );
}
}
}
else
{
attributes.clear();
QString value = identifyResult.error().message( QgsErrorMessage::Text );
attributes.insert( tr( "Error" ), value );
QString label = tr( "Identify error" );
results->append( IdentifyResult( qobject_cast<QgsMapLayer *>( layer ), label, attributes, derivedAttributes ) );
}
return true;
}

View File

@ -4315,7 +4315,14 @@ QgsRasterIdentifyResult QgsWmsProvider::identify( const QgsPoint & thePoint, Qgs
else
{
// guess from GML
gmlSchema.guessSchema( mIdentifyResultBodies.value( gmlPart ) );
bool ok = gmlSchema.guessSchema( mIdentifyResultBodies.value( gmlPart ) );
if ( ! ok )
{
QgsError err = gmlSchema.error();
err.append( tr( "Cannot identify" ) );
QgsDebugMsg( "guess schema error: " + err.message() );
return QgsRasterIdentifyResult( err );
}
}
QStringList featureTypeNames = gmlSchema.typeNames();