[FEATURE] (re-?)add identifyAsHtml to raster layer and use it in identify

git-svn-id: http://svn.osgeo.org/qgis/trunk@13467 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
jef 2010-05-11 21:08:45 +00:00
parent 0bb64e5172
commit 3e6fb20ff5
11 changed files with 216 additions and 54 deletions

View File

@ -98,6 +98,23 @@ public:
*/
virtual QString identifyAsText(const QgsPoint& point) = 0;
/**
* \brief Identify details from a server (e.g. WMS) from the last screen update
*
* \param point[in] The pixel coordinate (as it was displayed locally on screen)
*
* \return A text document containing the return from the WMS server
*
* \note WMS Servers prefer to receive coordinates in image space, therefore
* this function expects coordinates in that format.
*
* \note The arbitraryness of the returned document is enforced by WMS standards
* up to at least v1.3.0
*
* \note added in 1.5
*/
virtual QString identifyAsHtml(const QgsPoint& point) = 0;
/**
* \brief Returns the caption error text for the last error in this provider
*

View File

@ -322,6 +322,11 @@ public:
/** \brief Identify arbitrary details from the WMS server found on the point position */
QString identifyAsText( const QgsPoint & point );
/** \brief Identify arbitrary details from the WMS server found on the point position
* @added in 1.5
*/
QString identifyAsHtml( const QgsPoint & point );
/** \brief Currently returns always false */
bool isEditable() const;

View File

@ -22,6 +22,7 @@
#include "qgisapp.h"
#include "qgsmaplayer.h"
#include "qgsvectorlayer.h"
#include "qgsrasterlayer.h"
#include "qgsrubberband.h"
#include "qgsgeometry.h"
#include "qgsattributedialog.h"
@ -39,6 +40,7 @@
#include <QDockWidget>
#include <QMenuBar>
#include <QPushButton>
#include <QTextBrowser>
#include "qgslogger.h"
@ -154,6 +156,7 @@ void QgsIdentifyResults::addFeature( QgsMapLayer *layer, int fid,
{
QTreeWidgetItem *layItem = layerItem( layer );
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
QgsRasterLayer *rlayer = qobject_cast<QgsRasterLayer *>( layer );
if ( layItem == 0 )
{
@ -179,15 +182,28 @@ void QgsIdentifyResults::addFeature( QgsMapLayer *layer, int fid,
QTreeWidgetItem *featItem = new QTreeWidgetItem( QStringList() << displayField << displayValue );
featItem->setData( 0, Qt::UserRole, fid );
layItem->addChild( featItem );
for ( QMap<QString, QString>::const_iterator it = attributes.begin(); it != attributes.end(); it++ )
if ( !rlayer || rlayer->providerKey() != "wms" )
{
QTreeWidgetItem *attrItem = new QTreeWidgetItem( QStringList() << it.key() << it.value() );
if ( vlayer )
for ( QMap<QString, QString>::const_iterator it = attributes.begin(); it != attributes.end(); it++ )
{
attrItem->setData( 0, Qt::UserRole, vlayer->fieldNameIndex( it.key() ) );
QTreeWidgetItem *attrItem = new QTreeWidgetItem( QStringList() << it.key() << it.value() );
if ( vlayer )
{
attrItem->setData( 0, Qt::UserRole, vlayer->fieldNameIndex( it.key() ) );
}
featItem->addChild( attrItem );
}
}
else
{
QTreeWidgetItem *attrItem = new QTreeWidgetItem( QStringList() << attributes.begin().key() << "" );
featItem->addChild( attrItem );
QTextBrowser *tb = new QTextBrowser( attrItem->treeWidget() );
tb->setHtml( attributes.begin().value() );
attrItem->treeWidget()->setItemWidget( attrItem, 1, tb );
}
if ( derivedAttributes.size() >= 0 )
@ -228,8 +244,6 @@ void QgsIdentifyResults::addFeature( QgsMapLayer *layer, int fid,
}
}
layItem->addChild( featItem );
highlightFeature( featItem );
}

View File

@ -373,7 +373,7 @@ bool QgsMapToolIdentify::identifyRasterLayer( QgsRasterLayer *layer, int x, int
yMaxView > yMaxLayer ? floor( y - ( yMaxView - yMaxLayer ) / mapUnitsPerPixel ) : y
);
attributes.insert( tr( "Feature info" ), layer->identifyAsText( idPoint ) );
attributes.insert( tr( "Feature info" ), layer->identifyAsHtml( idPoint ) );
}
else
{

View File

@ -133,6 +133,23 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider
*/
virtual QString identifyAsText( const QgsPoint& point ) = 0;
/**
* \brief Identify details from a server (e.g. WMS) from the last screen update
*
* \param point[in] The pixel coordinate (as it was displayed locally on screen)
*
* \return A html document containing the return from the WMS server
*
* \note WMS Servers prefer to receive coordinates in image space, therefore
* this function expects coordinates in that format.
*
* \note The arbitraryness of the returned document is enforced by WMS standards
* up to at least v1.3.0
*
* \note added in 1.5
*/
virtual QString identifyAsHtml( const QgsPoint& point ) = 0;
/**
* \brief Returns the caption error text for the last error in this provider
*

View File

@ -1969,7 +1969,24 @@ QString QgsRasterLayer::identifyAsText( const QgsPoint& thePoint )
return QString();
}
return ( mDataProvider->identifyAsText( thePoint ) );
return mDataProvider->identifyAsText( thePoint );
}
/**
* @note The arbitraryness of the returned document is enforced by WMS standards up to at least v1.3.0
*
* @param thePoint an image pixel coordinate in the last requested extent of layer.
* @return A html document containing the return from the WMS server
*/
QString QgsRasterLayer::identifyAsHtml( const QgsPoint& thePoint )
{
if ( mProviderKey != "wms" )
{
// Currently no meaning for anything other than OGC WMS layers
return QString();
}
return mDataProvider->identifyAsHtml( thePoint );
}
/**

View File

@ -488,6 +488,11 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
/** \brief Identify arbitrary details from the WMS server found on the point position */
QString identifyAsText( const QgsPoint & point );
/** \brief Identify arbitrary details from the WMS server found on the point position
* @added in 1.5
*/
QString identifyAsHtml( const QgsPoint & point );
/** \brief Currently returns always false */
bool isEditable() const;

View File

@ -42,21 +42,21 @@ static QString PROVIDER_KEY = "grassraster";
static QString PROVIDER_DESCRIPTION = "GRASS raster provider";
QgsGrassRasterProvider::QgsGrassRasterProvider( QString const & uri )
: QgsRasterDataProvider( uri ), mValid(true)
: QgsRasterDataProvider( uri ), mValid( true )
{
QgsDebugMsg( "QgsGrassRasterProvider: constructing with uri '" + uri + "'." );
// Parse URI, it is the same like using GDAL, i.e. path to raster cellhd, i.e.
// /path/to/gisdbase/location/mapset/cellhd/map
QFileInfo fileInfo ( uri );
QFileInfo fileInfo( uri );
mValid = fileInfo.exists(); // then we keep it valid forever
mMapName = fileInfo.fileName();
QDir dir = fileInfo.dir();
QString element = dir.dirName();
if ( element != "cellhd" )
if ( element != "cellhd" )
{
QMessageBox::warning( 0, QObject::tr( "Warning" ),
QObject::tr( "Groups not yet supported" ) + " (GRASS " + uri + ")" );
QMessageBox::warning( 0, QObject::tr( "Warning" ),
QObject::tr( "Groups not yet supported" ) + " (GRASS " + uri + ")" );
mValid = false;
return;
@ -72,8 +72,8 @@ QgsGrassRasterProvider::QgsGrassRasterProvider( QString const & uri )
QgsDebugMsg( QString( "location: %1" ).arg( mLocation ) );
QgsDebugMsg( QString( "mapset: %1" ).arg( mMapset ) );
QgsDebugMsg( QString( "mapName: %1" ).arg( mMapName ) );
mCrs = QgsGrass::crs ( mGisdbase, mLocation );
mCrs = QgsGrass::crs( mGisdbase, mLocation );
}
QgsGrassRasterProvider::~QgsGrassRasterProvider()
@ -88,37 +88,37 @@ QImage* QgsGrassRasterProvider::draw( QgsRectangle const & viewExtent, int pixe
QgsDebugMsg( "viewExtent: " + viewExtent.toString() );
QImage *image = new QImage( pixelWidth, pixelHeight, QImage::Format_ARGB32 );
image->fill ( QColor(Qt::gray).rgb() );
image->fill( QColor( Qt::gray ).rgb() );
QStringList arguments;
arguments.append( "map=" + mMapName + "@" + mMapset );
arguments.append( (QString("window=%1,%2,%3,%4,%5,%6")
.arg(viewExtent.xMinimum()).arg(viewExtent.yMinimum())
.arg(viewExtent.xMaximum()).arg(viewExtent.yMaximum())
.arg(pixelWidth).arg(pixelHeight)) );
arguments.append(( QString( "window=%1,%2,%3,%4,%5,%6" )
.arg( viewExtent.xMinimum() ).arg( viewExtent.yMinimum() )
.arg( viewExtent.xMaximum() ).arg( viewExtent.yMaximum() )
.arg( pixelWidth ).arg( pixelHeight ) ) );
QProcess process( this );
QString cmd = QgsApplication::pkgDataPath() + "/grass/modules/qgis.d.rast";
QByteArray data;
try
try
{
data = QgsGrass::runModule ( mGisdbase, mLocation, cmd, arguments );
data = QgsGrass::runModule( mGisdbase, mLocation, cmd, arguments );
}
catch ( QgsGrass::Exception &e )
{
QMessageBox::warning( 0, QObject::tr( "Warning" ), QObject::tr( "Cannot draw raster" ) + "\n"
+ e.what() );
+ e.what() );
// We don't set mValid to false, because the raster can be recreated and work next time
return image;
}
QgsDebugMsg( QString("%1 bytes read from modules stdout").arg(data.size()) );
QgsDebugMsg( QString( "%1 bytes read from modules stdout" ).arg( data.size() ) );
uchar * ptr = image->bits( ) ;
// byteCount() in Qt >= 4.6
//int size = image->byteCount() < data.size() ? image->byteCount() : data.size();
int size = pixelWidth*pixelHeight*4 < data.size() ? pixelWidth*pixelHeight*4 : data.size();
memcpy ( ptr, data.data(), size );
int size = pixelWidth * pixelHeight * 4 < data.size() ? pixelWidth * pixelHeight * 4 : data.size();
memcpy( ptr, data.data(), size );
return image;
}
@ -134,7 +134,7 @@ QgsRectangle QgsGrassRasterProvider::extent()
// we should save mExtent and mLastModified and check if the map was modified
QgsRectangle rect;
rect = QgsGrass::extent ( mGisdbase, mLocation, mMapset, mMapName, QgsGrass::Raster );
rect = QgsGrass::extent( mGisdbase, mLocation, mMapset, mMapName, QgsGrass::Raster );
return rect;
}
@ -142,7 +142,7 @@ bool QgsGrassRasterProvider::identify( const QgsPoint& thePoint, QMap<QString, Q
{
QgsDebugMsg( "Entered" );
//theResults["Error"] = tr( "Out of extent" );
theResults = QgsGrass::query ( mGisdbase, mLocation, mMapset, mMapName, QgsGrass::Raster, thePoint.x(), thePoint.y() );
theResults = QgsGrass::query( mGisdbase, mLocation, mMapset, mMapName, QgsGrass::Raster, thePoint.x(), thePoint.y() );
return true;
}
@ -159,23 +159,28 @@ bool QgsGrassRasterProvider::isValid()
QString QgsGrassRasterProvider::identifyAsText( const QgsPoint& point )
{
return QString ("Not implemented");
return QString( "Not implemented" );
}
QString QgsGrassRasterProvider::identifyAsHtml( const QgsPoint& point )
{
return QString( "Not implemented" );
}
QString QgsGrassRasterProvider::lastErrorTitle()
{
return QString ("Not implemented");
return QString( "Not implemented" );
}
QString QgsGrassRasterProvider::lastError()
{
return QString ("Not implemented");
return QString( "Not implemented" );
}
QString QgsGrassRasterProvider::name() const
{
return PROVIDER_KEY;
}
}
QString QgsGrassRasterProvider::description() const
{

View File

@ -126,6 +126,23 @@ class QgsGrassRasterProvider : public QgsRasterDataProvider
*/
QString identifyAsText( const QgsPoint& point );
/**
* \brief Identify details from a WMS Server from the last screen update
*
* \param point[in] The pixel coordinate (as it was displayed locally on screen)
*
* \return A text document containing the return from the WMS server
*
* \note WMS Servers prefer to receive coordinates in image space, therefore
* this function expects coordinates in that format.
*
* \note The arbitraryness of the returned document is enforced by WMS standards
* up to at least v1.3.0
*
* \note added in 1.5
*/
QString identifyAsHtml( const QgsPoint& point );
/**
* \brief Returns the caption error text for the last error in this provider
*
@ -160,12 +177,12 @@ class QgsGrassRasterProvider : public QgsRasterDataProvider
*/
QString metadata() { return QString(); }
// Following methods specific for WMS are not used at all in this provider and should be removed IMO from qgsdataprovider.h
// Following methods specific for WMS are not used at all in this provider and should be removed IMO from qgsdataprovider.h
void addLayers( QStringList const & layers, QStringList const & styles = QStringList() ) {}
QStringList supportedImageEncodings() { return QStringList();}
QStringList supportedImageEncodings() { return QStringList();}
QString imageEncoding() const { return QString(); }
void setImageEncoding( QString const & mimeType ) {}
void setImageCrs( QString const & crs ) {}
void setImageCrs( QString const & crs ) {}
private:
@ -177,8 +194,8 @@ class QgsGrassRasterProvider : public QgsRasterDataProvider
QString mGisdbase; // map gisdabase
QString mLocation; // map location name (not path!)
QString mMapset; // map mapset
QString mMapName; // map name
QString mMapName; // map name
QgsCoordinateReferenceSystem mCrs;
};

View File

@ -101,6 +101,8 @@ QgsWmsProvider::QgsWmsProvider( QString const &uri )
mBaseUrl = prepareUri( httpuri );
mSupportedGetFeatureFormats = QStringList() << "text/html" << "text/plain" << "text/xml";
QgsDebugMsg( "mBaseUrl = " + mBaseUrl );
QgsDebugMsg( "exiting constructor." );
@ -2098,10 +2100,17 @@ int QgsWmsProvider::capabilities() const
}
}
// Collect all the test results into one bitmask
if ( canIdentify )
{
capability = ( capability | QgsRasterDataProvider::Identify );
foreach( QString f, mCapabilities.capability.request.getFeatureInfo.format )
{
if ( mSupportedGetFeatureFormats.contains( f ) )
{
// Collect all the test results into one bitmask
capability |= QgsRasterDataProvider::Identify;
break;
}
}
}
QgsDebugMsg( "exiting with '" + QString( capability ) + "'." );
@ -2599,10 +2608,10 @@ QString QgsWmsProvider::metadata()
return myMetadataQString;
}
QString QgsWmsProvider::identifyAsText( const QgsPoint& point )
QStringList QgsWmsProvider::identifyAs( const QgsPoint& point, QString format )
{
QgsDebugMsg( "Entering." );
QStringList results;
// Collect which layers to query on
@ -2628,8 +2637,8 @@ QString QgsWmsProvider::identifyAsText( const QgsPoint& point )
//! \todo Need to tie this into the options provided by GetCapabilities
requestUrl += QString( "&QUERY_LAYERS=%1" ).arg( layer );
requestUrl += QString( "&INFO_FORMAT=text/plain&X=%1&Y=%2" )
.arg( point.x() ).arg( point.y() );
requestUrl += QString( "&INFO_FORMAT=%1&X=%2&Y=%3" )
.arg( format ).arg( point.x() ).arg( point.y() );
// X,Y in WMS 1.1.1; I,J in WMS 1.3.0
// requestUrl += QString( "&I=%1&J=%2" ).arg( point.x() ).arg( point.y() );
@ -2643,22 +2652,58 @@ QString QgsWmsProvider::identifyAsText( const QgsPoint& point )
QCoreApplication::processEvents( QEventLoop::ExcludeUserInputEvents );
}
text += "---------------\n" + mIdentifyResult;
results << mIdentifyResult;
}
}
}
if ( text.isEmpty() )
{
// No layers were queryably. This can happen if identify tool was
// active when this non-queriable layer was selected.
// Return a descriptive text.
QgsDebugMsg( "Exiting with: " + results.join( "\n------\n" ) );
return results;
}
text = tr( "Layer cannot be queried." );
QString QgsWmsProvider::identifyAsText( const QgsPoint &point )
{
if ( !mCapabilities.capability.request.getFeatureInfo.format.contains( "text/plain" ) )
return tr( "Layer cannot be queried in plain text." );
QStringList list = identifyAs( point, "text/plain" );
if ( list.isEmpty() )
{
return tr( "Layer cannot be queried." );
}
else
{
return list.join( "\n-------------\n" );
}
}
QString QgsWmsProvider::identifyAsHtml( const QgsPoint &point )
{
QString format;
foreach( QString f, mSupportedGetFeatureFormats )
{
if ( mCapabilities.capability.request.getFeatureInfo.format.contains( f ) )
{
format = f;
break;
}
}
QgsDebugMsg( "Exiting with: " + text );
return text;
Q_ASSERT( !format.isEmpty() );
QStringList results = identifyAs( point, format );
if ( format == "text/html" )
{
return "<table>\n<tr><td>" + results.join( "</td></tr>\n<tr><td>" ) + "</td></tr>\n</table>";
}
else
{
// TODO format text/xml
return "<table>\n<tr><td><pre>\n" + results.join( "\n</pre></td></tr>\n<tr><td><pre>\n" ) + "\n</pre></td></tr>\n</table>";
}
}
void QgsWmsProvider::identifyReplyFinished()

View File

@ -531,6 +531,21 @@ class QgsWmsProvider : public QgsRasterDataProvider
QString metadata();
/**
* \brief Identify details from a WMS Server from the last screen update
*
* \param point[in] The pixel coordinate (as it was displayed locally on screen)
*
* \return A html document containing the return from the WMS server
*
* \note WMS Servers prefer to receive coordinates in image space, therefore
* this function expects coordinates in that format.
*
* \note The arbitraryness of the returned document is enforced by WMS standards
* up to at least v1.3.0
*/
QString identifyAsHtml( const QgsPoint& point );
/**
* \brief Identify details from a WMS Server from the last screen update
*
@ -724,6 +739,8 @@ class QgsWmsProvider : public QgsRasterDataProvider
*/
QString prepareUri( QString uri ) const;
QStringList identifyAs( const QgsPoint &point, QString format );
QString layerMetadata( QgsWmsLayerProperty &layer );
//! Data source URI of the WMS for this layer
@ -906,6 +923,9 @@ class QgsWmsProvider : public QgsRasterDataProvider
// the given base urls for GetMap and GetFeatureInfo
bool mIgnoreGetMapUrl;
bool mIgnoreGetFeatureInfoUrl;
//! supported formats for GetFeatureInfo in order of preference
QStringList mSupportedGetFeatureFormats;
};
#endif