Skip to content

Commit 07d23be

Browse files
author
morb_au
committedMar 19, 2006
More WMS improvements:
* The "Identify" map tool now works on queryable map layers. * The raster Properties/Metadata tab now shows if layers are queryable or not. Errors fixed: * Raster Properties/Metadata no longer repeats the details per layer. Errors known: * Layers that are non-queryable are not tested for when the Identify tool is invoked - the WMS server has to report the error instead. * The pixel identified is not highlighted. * Errors are not handled correctly; the window appears but no useful information is shown. git-svn-id: http://svn.osgeo.org/qgis/trunk@5066 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent 5373fae commit 07d23be

File tree

7 files changed

+449
-133
lines changed

7 files changed

+449
-133
lines changed
 

‎src/core/qgsrasterdataprovider.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,21 @@ class QgsRasterDataProvider : public QgsDataProvider
9393
*/
9494
virtual QString getMetadata() = 0;
9595

96+
/**
97+
* \brief Identify details from a server (e.g. WMS) from the last screen update
98+
*
99+
* \param point[in] The pixel coordinate (as it was displayed locally on screen)
100+
*
101+
* \retval An HTML document containing the return from the WMS server
102+
*
103+
* \note WMS Servers prefer to receive coordinates in image space, therefore
104+
* this function expects coordinates in that format.
105+
*
106+
* \note The arbitraryness of the returned document is enforced by WMS standards
107+
* up to at least v1.3.0
108+
*/
109+
virtual QString identifyAsHtml(const QgsPoint& point) = 0;
110+
96111
/**
97112
* \brief Returns the caption error text for the last error in this provider
98113
*

‎src/gui/qgsmaptoolidentify.cpp

Lines changed: 90 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
***************************************************************************/
1515
/* $Id$ */
1616

17+
#include "qgsmessageviewer.h"
1718
#include "qgsmaptoolidentify.h"
1819
#include "qgsmapcanvas.h"
1920
#include "qgsvectordataprovider.h"
@@ -30,10 +31,13 @@
3031
#include <QMessageBox>
3132
#include <QCursor>
3233
#include <QPixmap>
34+
#include <QObject>
3335

3436

3537
QgsMapToolIdentify::QgsMapToolIdentify(QgsMapCanvas* canvas)
36-
: QgsMapTool(canvas), mResults(NULL)
38+
: QgsMapTool(canvas),
39+
mResults(0),
40+
mViewer(0)
3741
{
3842
// set cursor
3943
QPixmap myIdentifyQPixmap = QPixmap((const char **) identify_cursor);
@@ -42,7 +46,15 @@ QgsMapToolIdentify::QgsMapToolIdentify(QgsMapCanvas* canvas)
4246

4347
QgsMapToolIdentify::~QgsMapToolIdentify()
4448
{
45-
delete mResults;
49+
if (mResults)
50+
{
51+
delete mResults;
52+
}
53+
54+
if (mViewer)
55+
{
56+
delete mViewer;
57+
}
4658
}
4759

4860
void QgsMapToolIdentify::canvasMoveEvent(QMouseEvent * e)
@@ -61,24 +73,38 @@ void QgsMapToolIdentify::canvasReleaseEvent(QMouseEvent * e)
6173

6274
if (layer)
6375
{
64-
// convert screen coordinates to map coordinates
65-
QgsPoint idPoint = mCanvas->getCoordinateTransform()->toMapCoordinates(e->x(), e->y());
66-
67-
if (layer->type() == QgsMapLayer::VECTOR)
76+
// In the special case of the WMS provider,
77+
// coordinates are sent back to the server as pixel coordinates
78+
// not the layer's native CRS. So identify on screen coordinates!
79+
if (
80+
(layer->type() == QgsMapLayer::RASTER)
81+
&&
82+
(dynamic_cast<QgsRasterLayer*>(layer)->providerKey() == "wms")
83+
)
6884
{
69-
identifyVectorLayer(dynamic_cast<QgsVectorLayer*>(layer), idPoint);
70-
}
71-
else if (layer->type() == QgsMapLayer::RASTER)
72-
{
73-
identifyRasterLayer(dynamic_cast<QgsRasterLayer*>(layer), idPoint);
85+
identifyRasterWmsLayer(dynamic_cast<QgsRasterLayer*>(layer), QgsPoint(e->x(), e->y()) );
7486
}
7587
else
7688
{
89+
// convert screen coordinates to map coordinates
90+
QgsPoint idPoint = mCanvas->getCoordinateTransform()->toMapCoordinates(e->x(), e->y());
91+
92+
if (layer->type() == QgsMapLayer::VECTOR)
93+
{
94+
identifyVectorLayer(dynamic_cast<QgsVectorLayer*>(layer), idPoint);
95+
}
96+
else if (layer->type() == QgsMapLayer::RASTER)
97+
{
98+
identifyRasterLayer(dynamic_cast<QgsRasterLayer*>(layer), idPoint);
99+
}
100+
else
101+
{
77102
#ifdef QGISDEBUG
78-
std::cout << "identify: unknown layer type!" << std::endl;
103+
std::cout << "QgsMapToolIdentify::canvasReleaseEvent: unknown layer type!" << std::endl;
79104
#endif
105+
}
80106
}
81-
107+
82108
}
83109
else
84110
{
@@ -124,6 +150,34 @@ void QgsMapToolIdentify::identifyRasterLayer(QgsRasterLayer* layer, const QgsPoi
124150
}
125151

126152

153+
void QgsMapToolIdentify::identifyRasterWmsLayer(QgsRasterLayer* layer, const QgsPoint& point)
154+
{
155+
if (!layer)
156+
{
157+
return;
158+
}
159+
160+
QString html = layer->identifyAsHtml(point);
161+
162+
if (html.isEmpty())
163+
{
164+
showError(layer);
165+
return;
166+
}
167+
168+
if (!mViewer)
169+
{
170+
mViewer = new QgsMessageViewer();
171+
}
172+
173+
mViewer->setCaption( layer->name() );
174+
mViewer->setMessageAsPlainText( html );
175+
// mViewer->setMessageAsHtml( html );
176+
177+
// mViewer->exec();
178+
mViewer->show();
179+
}
180+
127181

128182
void QgsMapToolIdentify::identifyVectorLayer(QgsVectorLayer* layer, const QgsPoint& point)
129183
{
@@ -313,3 +367,26 @@ void QgsMapToolIdentify::identifyVectorLayer(QgsVectorLayer* layer, const QgsPoi
313367
}
314368
dataProvider->reset();
315369
}
370+
371+
372+
void QgsMapToolIdentify::showError(QgsMapLayer * mapLayer)
373+
{
374+
// QMessageBox::warning(
375+
// this,
376+
// mapLayer->errorCaptionString(),
377+
// tr("Could not draw") + " " + mapLayer->name() + " " + tr("because") + ":\n" +
378+
// mapLayer->errorString()
379+
// );
380+
381+
QgsMessageViewer * mv = new QgsMessageViewer();
382+
mv->setCaption( mapLayer->errorCaptionString() );
383+
mv->setMessageAsPlainText(
384+
QObject::tr("Could not identify objects on") + " " + mapLayer->name() + " " + QObject::tr("because") + ":\n" +
385+
mapLayer->errorString()
386+
);
387+
mv->exec();
388+
delete mv;
389+
390+
}
391+
392+
// ENDS

‎src/gui/qgsmaptoolidentify.h

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,14 @@
2323
#define MapTool_Identify "identify"
2424

2525
class QgsIdentifyResults;
26+
class QgsMessageViewer;
27+
class QgsMapLayer;
2628
class QgsRasterLayer;
2729
class QgsVectorLayer;
2830

2931
/**
3032
\brief Map tool for identifying features in current layer
31-
33+
3234
after selecting a point shows dialog with identification results
3335
- for raster layers shows value of underlying pixel
3436
- for vector layers shows feature attributes within search radius
@@ -38,31 +40,56 @@ class QgsMapToolIdentify : public QgsMapTool
3840
{
3941
public:
4042
QgsMapToolIdentify(QgsMapCanvas* canvas);
41-
43+
4244
~QgsMapToolIdentify();
43-
45+
4446
//! Overridden mouse move event
4547
virtual void canvasMoveEvent(QMouseEvent * e);
46-
48+
4749
//! Overridden mouse press event
4850
virtual void canvasPressEvent(QMouseEvent * e);
49-
51+
5052
//! Overridden mouse release event
5153
virtual void canvasReleaseEvent(QMouseEvent * e);
52-
54+
5355
virtual QString toolName() { return MapTool_Identify; }
54-
56+
5557
private:
56-
57-
//! function for identifying raster layer
58+
59+
/**
60+
* \brief function for identifying pixel values at a coordinate in a non-OGC-WMS raster layer
61+
*
62+
* \param point[in] The coordinate (as the CRS of the raster layer)
63+
*/
5864
void identifyRasterLayer(QgsRasterLayer* layer, const QgsPoint& point);
59-
60-
//! function for identifying vector layer
65+
66+
/**
67+
* \brief function for identifying a pixel in a OGC WMS raster layer
68+
*
69+
* \param point[in] The pixel coordinate (as it was displayed locally on screen)
70+
*
71+
* \note WMS Servers prefer to receive coordinates in image space not CRS space, therefore
72+
* this special variant of identifyRasterLayer.
73+
*/
74+
void identifyRasterWmsLayer(QgsRasterLayer* layer, const QgsPoint& point);
75+
76+
/**
77+
* \brief function for identifying features at a coordinate in a vector layer
78+
*
79+
* \param point[in] The coordinate (as the CRS of the vector layer)
80+
*/
6181
void identifyVectorLayer(QgsVectorLayer* layer, const QgsPoint& point);
6282

63-
//! Pointer to the identify results dialog
83+
//! show whatever error is exposed by the QgsMapLayer.
84+
void showError(QgsMapLayer * mapLayer);
85+
86+
87+
//! Pointer to the identify results dialog for name/value pairs
6488
QgsIdentifyResults *mResults;
65-
89+
90+
//! Pointer to the identify results dialog for WMS XML files
91+
QgsMessageViewer * mViewer;
92+
6693
};
6794

6895
#endif

‎src/providers/wms/qgswmsprovider.cpp

Lines changed: 208 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,17 @@ static QString DEFAULT_LATLON_CRS = "CRS:84";
5757
QgsWmsProvider::QgsWmsProvider(QString const & uri)
5858
: QgsRasterDataProvider(uri),
5959
httpuri(uri),
60-
httpproxyhost(0),
61-
httpproxyport(80),
60+
mHttpproxyhost(0),
61+
mHttpproxyport(80),
6262
httpcapabilitiesresponse(0),
6363
cachedImage(0),
6464
cachedViewExtent(0),
6565
cachedPixelWidth(0),
6666
cachedPixelHeight(0),
6767
mCoordinateTransform(0),
6868
extentDirty(TRUE),
69-
imageCrs(DEFAULT_LATLON_CRS)
69+
imageCrs(DEFAULT_LATLON_CRS),
70+
mGetFeatureInfoUrlBase(0)
7071
{
7172
#ifdef QGISDEBUG
7273
std::cout << "QgsWmsProvider: constructing with uri '" << uri.toLocal8Bit().data() << "'." << std::endl;
@@ -89,23 +90,23 @@ QgsWmsProvider::QgsWmsProvider(QString const & uri)
8990

9091
if (drawuriparts.count())
9192
{
92-
httpproxyhost = drawuriparts.front();
93+
mHttpproxyhost = drawuriparts.front();
9394
drawuriparts.pop_front();
9495

9596
if (drawuriparts.count())
9697
{
9798
bool ushortConversionOK;
98-
httpproxyport = drawuriparts.front().toUShort(&ushortConversionOK);
99+
mHttpproxyport = drawuriparts.front().toUShort(&ushortConversionOK);
99100
drawuriparts.pop_front();
100101

101102
if (!ushortConversionOK)
102103
{
103-
httpproxyport = 80; // standard HTTP port
104+
mHttpproxyport = 80; // standard HTTP port
104105
}
105106
}
106107
else
107108
{
108-
httpproxyport = 80; // standard HTTP port
109+
mHttpproxyport = 80; // standard HTTP port
109110
}
110111
}
111112

@@ -445,22 +446,48 @@ QImage* QgsWmsProvider::draw(QgsRect const & viewExtent, int pixelWidth, int pi
445446
url += "&";
446447
url += "TRANSPARENT=TRUE";
447448

448-
#ifdef QGISDEBUG
449-
std::cout << "QgsWmsProvider::draw: emitting setStatus(Test from QgsWmsProvider)." << std::endl;
450-
#endif
451-
emit setStatus( QString("Test from QgsWmsProvider") );
449+
// cache some details for if the user wants to do an identifyAsHtml() later
450+
mGetFeatureInfoUrlBase = baseUrl;
451+
mGetFeatureInfoUrlBase += "SERVICE=WMS";
452+
mGetFeatureInfoUrlBase += "&";
453+
mGetFeatureInfoUrlBase += "VERSION=1.1.0";
454+
mGetFeatureInfoUrlBase += "&";
455+
mGetFeatureInfoUrlBase += "REQUEST=GetFeatureInfo";
456+
mGetFeatureInfoUrlBase += "&";
457+
mGetFeatureInfoUrlBase += "BBOX=" + bbox;
458+
mGetFeatureInfoUrlBase += "&";
459+
mGetFeatureInfoUrlBase += "SRS=" + imageCrs;
460+
mGetFeatureInfoUrlBase += "&";
461+
mGetFeatureInfoUrlBase += "WIDTH=" + width;
462+
mGetFeatureInfoUrlBase += "&";
463+
mGetFeatureInfoUrlBase += "HEIGHT=" + height;
464+
mGetFeatureInfoUrlBase += "&";
465+
mGetFeatureInfoUrlBase += "LAYERS=" + layers;
466+
mGetFeatureInfoUrlBase += "&";
467+
mGetFeatureInfoUrlBase += "STYLES=" + styles;
468+
mGetFeatureInfoUrlBase += "&";
469+
mGetFeatureInfoUrlBase += "FORMAT=" + imageMimeType;
470+
mGetFeatureInfoUrlBase += "&";
471+
mGetFeatureInfoUrlBase += "TRANSPARENT=TRUE";
452472

453-
473+
474+
QByteArray imagesource;
475+
imagesource = retrieveUrl(url);
476+
477+
if (imagesource.isEmpty())
478+
{
479+
return 0;
480+
}
481+
482+
/*
454483
QgsHttpTransaction http(url, httpproxyhost, httpproxyport);
455-
456-
484+
457485
// Do a passthrough for the status bar text
458486
connect(
459487
&http, SIGNAL(setStatus (QString)),
460488
this, SLOT(showStatusMessage(QString))
461489
);
462490
463-
QByteArray imagesource;
464491
bool httpOk;
465492
466493
httpOk = http.getSynchronously(imagesource);
@@ -499,7 +526,7 @@ QImage* QgsWmsProvider::draw(QgsRect const & viewExtent, int pixelWidth, int pi
499526
500527
return 0;
501528
}
502-
529+
*/
503530

504531
#ifdef QGISDEBUG
505532
std::cout << "QgsWmsProvider::draw: Response received." << std::endl;
@@ -580,6 +607,13 @@ bool QgsWmsProvider::retrieveServerCapabilities(bool forceRefresh)
580607

581608
QString url = baseUrl + "SERVICE=WMS&REQUEST=GetCapabilities";
582609

610+
httpcapabilitiesresponse = retrieveUrl(url);
611+
612+
if (httpcapabilitiesresponse.isEmpty())
613+
{
614+
return FALSE;
615+
}
616+
/*
583617
QgsHttpTransaction http(url, httpproxyhost, httpproxyport);
584618
585619
// Do a passthrough for the status bar text
@@ -607,8 +641,7 @@ bool QgsWmsProvider::retrieveServerCapabilities(bool forceRefresh)
607641
608642
return FALSE;
609643
}
610-
http.getSynchronously(httpcapabilitiesresponse);
611-
644+
*/
612645

613646
#ifdef QGISDEBUG
614647
std::cout << "QgsWmsProvider::getServerCapabilities: Converting to DOM." << std::endl;
@@ -640,6 +673,61 @@ bool QgsWmsProvider::retrieveServerCapabilities(bool forceRefresh)
640673

641674
}
642675

676+
677+
QByteArray QgsWmsProvider::retrieveUrl(QString url)
678+
{
679+
QgsHttpTransaction http(url, mHttpproxyhost, mHttpproxyport);
680+
681+
// Do a passthrough for the status bar text
682+
connect(
683+
&http, SIGNAL(setStatus (QString)),
684+
this, SLOT(showStatusMessage(QString))
685+
);
686+
687+
QByteArray httpResponse;
688+
bool httpOk;
689+
690+
httpOk = http.getSynchronously(httpResponse);
691+
692+
if (!httpOk)
693+
{
694+
// We had an HTTP exception
695+
696+
mErrorCaption = tr("HTTP Exception");
697+
mError = http.errorString();
698+
699+
mError += "\n" + tr("Tried URL: ") + url;
700+
701+
return 0;
702+
}
703+
704+
if (http.responseContentType() == "application/vnd.ogc.se_xml")
705+
{
706+
// We had a Service Exception from the WMS
707+
708+
#ifdef QGISDEBUG
709+
std::cout << "QgsWmsProvider::retrieveUrl: got Service Exception as:\n"
710+
<< QString(httpResponse).toLocal8Bit().data() << std::endl;
711+
#endif
712+
713+
mErrorCaption = tr("WMS Service Exception");
714+
715+
// set mError with the following:
716+
parseServiceExceptionReportDOM(httpResponse);
717+
718+
mError += "\n" + tr("Tried URL: ") + url;
719+
720+
#ifdef QGISDEBUG
721+
std::cout << "QgsWmsProvider::retrieveUrl: composed error message '"
722+
<< mError.toLocal8Bit().data() << "'." << std::endl;
723+
#endif
724+
725+
return 0;
726+
}
727+
728+
return httpResponse;
729+
}
730+
643731
// deprecated
644732
/*
645733
bool QgsWmsProvider::downloadCapabilitiesURI(QString const & uri)
@@ -1906,6 +1994,14 @@ QString QgsWmsProvider::getMetadata()
19061994
myMetadataQString += capabilities.capability.request.getMap.format.join("<br />");
19071995
myMetadataQString += "</td></tr>";
19081996

1997+
// GetFeatureInfo Request Formats
1998+
myMetadataQString += "<tr><td bgcolor=\"gray\">";
1999+
myMetadataQString += tr("Identify Formats");
2000+
myMetadataQString += "</td>";
2001+
myMetadataQString += "<td bgcolor=\"gray\">";
2002+
myMetadataQString += capabilities.capability.request.getFeatureInfo.format.join("<br />");
2003+
myMetadataQString += "</td></tr>";
2004+
19092005
// Layer Count (as managed by this provider)
19102006
myMetadataQString += "<tr><td bgcolor=\"gray\">";
19112007
myMetadataQString += tr("Layer Count");
@@ -1982,78 +2078,53 @@ QString QgsWmsProvider::getMetadata()
19822078
myMetadataQString += layersSupported[i].abstract;
19832079
myMetadataQString += "</td></tr>";
19842080

2081+
// Layer Queryability
2082+
myMetadataQString += "<tr><td bgcolor=\"gray\">";
2083+
myMetadataQString += tr("Can Identify");
2084+
myMetadataQString += "</td>";
2085+
myMetadataQString += "<td bgcolor=\"gray\">";
2086+
myMetadataQString += ((layersSupported[i].queryable) ? tr("Yes") : tr("No"));
2087+
myMetadataQString += "</td></tr>";
19852088

1986-
1987-
// Layer Coordinate Reference Systems
1988-
for ( int j = 0; j < layersSupported[i].crs.size(); j++ )
1989-
{
1990-
myMetadataQString += "<tr><td bgcolor=\"gray\">";
1991-
myMetadataQString += tr("Available in CRS");
1992-
myMetadataQString += "</td>";
1993-
myMetadataQString += "<td bgcolor=\"gray\">";
1994-
myMetadataQString += layersSupported[i].crs[j];
1995-
myMetadataQString += "</td></tr>";
1996-
}
1997-
1998-
// Layer Styles
1999-
for (int j = 0; j < layersSupported[i].style.size(); j++)
2000-
{
2001-
myMetadataQString += "<tr><td bgcolor=\"gray\">";
2002-
myMetadataQString += tr("Available in style");
2003-
myMetadataQString += "</td>";
2004-
myMetadataQString += "<td bgcolor=\"gray\">";
2005-
myMetadataQString += layersSupported[i].style[j].name;
2006-
myMetadataQString += "</td></tr>";
2007-
2008-
myMetadataQString += "<table width=\"100%\">";
2009-
2010-
// Table header
2011-
myMetadataQString += "<tr><th bgcolor=\"black\">";
2012-
myMetadataQString += "<font color=\"white\">" + tr("Property") + "</font>";
2013-
myMetadataQString += "</th>";
2014-
myMetadataQString += "<th bgcolor=\"black\">";
2015-
myMetadataQString += "<font color=\"white\">" + tr("Value") + "</font>";
2016-
myMetadataQString += "</th><tr>";
2017-
2018-
// Layer Selectivity (as managed by this provider)
2089+
// Layer Opacity
20192090
myMetadataQString += "<tr><td bgcolor=\"gray\">";
2020-
myMetadataQString += tr("Selected");
2091+
myMetadataQString += tr("Can be Transparent");
20212092
myMetadataQString += "</td>";
20222093
myMetadataQString += "<td bgcolor=\"gray\">";
2023-
myMetadataQString += (activeSubLayers.findIndex(layerName) >= 0) ?
2024-
tr("Yes") : tr("No");
2094+
myMetadataQString += ((layersSupported[i].opaque) ? tr("No") : tr("Yes"));
20252095
myMetadataQString += "</td></tr>";
2026-
2027-
// Layer Visibility (as managed by this provider)
2096+
2097+
// Layer Subsetability
20282098
myMetadataQString += "<tr><td bgcolor=\"gray\">";
2029-
myMetadataQString += tr("Visibility");
2099+
myMetadataQString += tr("Can Zoom In");
20302100
myMetadataQString += "</td>";
20312101
myMetadataQString += "<td bgcolor=\"gray\">";
2032-
myMetadataQString += (activeSubLayers.findIndex(layerName) >= 0) ?
2033-
(
2034-
(activeSubLayerVisibility.find(layerName)->second) ?
2035-
tr("Visible") : tr("Hidden")
2036-
) :
2037-
tr("n/a");
2102+
myMetadataQString += ((layersSupported[i].noSubsets) ? tr("No") : tr("Yes"));
20382103
myMetadataQString += "</td></tr>";
2039-
2040-
// Layer Title
2104+
2105+
// Layer Server Cascade Count
20412106
myMetadataQString += "<tr><td bgcolor=\"gray\">";
2042-
myMetadataQString += tr("Title");
2107+
myMetadataQString += tr("Cascade Count");
20432108
myMetadataQString += "</td>";
20442109
myMetadataQString += "<td bgcolor=\"gray\">";
2045-
myMetadataQString += layersSupported[i].title;
2110+
myMetadataQString += layersSupported[i].cascaded;
20462111
myMetadataQString += "</td></tr>";
2047-
2048-
// Layer Abstract
2112+
2113+
// Layer Fixed Width
20492114
myMetadataQString += "<tr><td bgcolor=\"gray\">";
2050-
myMetadataQString += tr("Abstract");
2115+
myMetadataQString += tr("Fixed Width");
20512116
myMetadataQString += "</td>";
20522117
myMetadataQString += "<td bgcolor=\"gray\">";
2053-
myMetadataQString += layersSupported[i].abstract;
2118+
myMetadataQString += layersSupported[i].fixedWidth;
20542119
myMetadataQString += "</td></tr>";
2055-
20562120

2121+
// Layer Fixed Height
2122+
myMetadataQString += "<tr><td bgcolor=\"gray\">";
2123+
myMetadataQString += tr("Fixed Height");
2124+
myMetadataQString += "</td>";
2125+
myMetadataQString += "<td bgcolor=\"gray\">";
2126+
myMetadataQString += layersSupported[i].fixedHeight;
2127+
myMetadataQString += "</td></tr>";
20572128

20582129
// Layer Coordinate Reference Systems
20592130
for ( int j = 0; j < layersSupported[i].crs.size(); j++ )
@@ -2109,13 +2180,8 @@ QString QgsWmsProvider::getMetadata()
21092180
// Close the nested table
21102181
myMetadataQString += "</table>";
21112182
myMetadataQString += "</td></tr>";
2112-
}
2113-
2114-
// Close the nested table
2115-
myMetadataQString += "</table>";
2116-
myMetadataQString += "</td></tr>";
21172183

2118-
}
2184+
} // for each layer
21192185

21202186
#ifdef QGISDEBUG
21212187
std::cout << "QgsWmsProvider::getMetadata: exiting with '" << myMetadataQString.toLocal8Bit().data() << "'." << std::endl;
@@ -2125,6 +2191,70 @@ QString QgsWmsProvider::getMetadata()
21252191
}
21262192

21272193

2194+
QString QgsWmsProvider::identifyAsHtml(const QgsPoint& point)
2195+
{
2196+
#ifdef QGISDEBUG
2197+
std::cout << "QgsWmsProvider::identifyAsHtml: entering." << std::endl;
2198+
#endif
2199+
2200+
// Collect which layers to query on
2201+
2202+
QStringList visibleLayers = QStringList();
2203+
2204+
for ( QStringList::Iterator it = activeSubLayers.begin();
2205+
it != activeSubLayers.end();
2206+
++it )
2207+
{
2208+
if (TRUE == activeSubLayerVisibility.find( *it )->second)
2209+
{
2210+
visibleLayers += *it;
2211+
}
2212+
}
2213+
2214+
QString layers = visibleLayers.join(",");
2215+
Q3Url::encode( layers );
2216+
2217+
// Compose request to WMS server
2218+
2219+
QString requestUrl = mGetFeatureInfoUrlBase;
2220+
2221+
requestUrl += "&";
2222+
requestUrl += "QUERY_LAYERS=" + layers;
2223+
requestUrl += "&";
2224+
//! \todo Need to tie this into the options provided by GetCapabilities
2225+
requestUrl += "INFO_FORMAT=text/plain";
2226+
2227+
// X,Y in WMS 1.1.1; I,J in WMS 1.3.0
2228+
2229+
// requestUrl += "&";
2230+
// requestUrl += QString( "I=%1" )
2231+
// .arg( point.x() );
2232+
// requestUrl += "&";
2233+
// requestUrl += QString( "J=%1" )
2234+
// .arg( point.y() );
2235+
2236+
requestUrl += "&";
2237+
requestUrl += QString( "X=%1" )
2238+
.arg( point.x() );
2239+
requestUrl += "&";
2240+
requestUrl += QString( "Y=%1" )
2241+
.arg( point.y() );
2242+
2243+
QString html = retrieveUrl(requestUrl);
2244+
2245+
if (html.isEmpty())
2246+
{
2247+
return QString();
2248+
}
2249+
2250+
#ifdef QGISDEBUG
2251+
std::cout << "QgsWmsProvider::identifyAsHtml: exiting with '"
2252+
<< html.toLocal8Bit().data() << "'." << std::endl;
2253+
#endif
2254+
return html;
2255+
}
2256+
2257+
21282258
QString QgsWmsProvider::errorCaptionString()
21292259
{
21302260
return mErrorCaption;

‎src/providers/wms/qgswmsprovider.h

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,21 @@ class QgsWmsProvider : public QgsRasterDataProvider
495495
*/
496496
QString getMetadata();
497497

498+
/**
499+
* \brief Identify details from a WMS Server from the last screen update
500+
*
501+
* \param point[in] The pixel coordinate (as it was displayed locally on screen)
502+
*
503+
* \retval An HTML document containing the return from the WMS server
504+
*
505+
* \note WMS Servers prefer to receive coordinates in image space, therefore
506+
* this function expects coordinates in that format.
507+
*
508+
* \note The arbitraryness of the returned document is enforced by WMS standards
509+
* up to at least v1.3.0
510+
*/
511+
QString identifyAsHtml(const QgsPoint& point);
512+
498513
/**
499514
* \brief Returns the caption error text for the last error in this provider
500515
*
@@ -564,7 +579,8 @@ public slots:
564579
private:
565580

566581
/**
567-
* Retrieve and parse the (cached) Capabilities document from the server
582+
* \brief Retrieve and parse the (cached) Capabilities document from the server
583+
*
568584
* \param forceRefresh if true, ignores any previous response cached in memory
569585
* and always contact the server for a new copy.
570586
* \retval FALSE if the capabilities document could not be retreived or parsed -
@@ -576,6 +592,14 @@ public slots:
576592
*/
577593
bool retrieveServerCapabilities(bool forceRefresh = FALSE);
578594

595+
/**
596+
* \brief Common URL retreival code for the differing WMS request types
597+
*
598+
* \retval 0 if an error occured - use errorString() and errorCaptionString() for details
599+
*
600+
*/
601+
QByteArray retrieveUrl(QString url);
602+
579603
/*
580604
//! Test function: see if we can download a WMS' capabilites
581605
//! \retval FALSE if the download failed in some way
@@ -664,10 +688,10 @@ public slots:
664688
QString baseUrl;
665689

666690
//! HTTP proxy host name for the WMS for this layer
667-
QString httpproxyhost;
691+
QString mHttpproxyhost;
668692

669693
//! HTTP proxy port number for the WMS for this layer
670-
Q_UINT16 httpproxyport;
694+
Q_UINT16 mHttpproxyport;
671695

672696
/**
673697
* Flag indicating if the layer data source is a valid WMS layer
@@ -780,6 +804,8 @@ public slots:
780804
//! See if calculateExtents() needs to be called before extent() returns useful data
781805
bool extentDirty;
782806

807+
//! Base URL for WMS GetFeatureInfo requests
808+
QString mGetFeatureInfoUrlBase;
783809
};
784810

785811
#endif

‎src/raster/qgsrasterlayer.cpp

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ wish to see edbug messages printed to stdout.
131131
/*
132132
* END
133133
*/
134-
134+
135+
#include "../providers/wms/qgswmsprovider.h"
135136

136137
#include <gdal_priv.h>
137138

@@ -496,7 +497,7 @@ QgsRasterLayer::QgsRasterLayer(QString const & path, QString const & baseName)
496497
QgsRasterLayer::~QgsRasterLayer()
497498
{
498499

499-
if (providerKey.isEmpty())
500+
if (mProviderKey.isEmpty())
500501
{
501502
GDALClose(gdalDataset);
502503
}
@@ -978,7 +979,7 @@ void QgsRasterLayer::drawThumbnail(QPixmap * theQPixmap)
978979
theQPixmap->fill(); //defaults to white
979980

980981
// Raster providers are disabled (for the moment)
981-
if (providerKey.isEmpty())
982+
if (mProviderKey.isEmpty())
982983
{
983984
QgsRasterViewPort *myRasterViewPort = new QgsRasterViewPort();
984985
myRasterViewPort->rectXOffsetInt = 0;
@@ -1014,7 +1015,7 @@ QPixmap QgsRasterLayer::getPaletteAsPixmap()
10141015
// Only do this for the non-provider (hard-coded GDAL) scenario...
10151016
// Maybe WMS can do this differently using QImage::numColors and QImage::color()
10161017
if (
1017-
(providerKey.isEmpty()) &&
1018+
(mProviderKey.isEmpty()) &&
10181019
(hasBand("Palette") ) //dont tr() this its a gdal word!
10191020
)
10201021
{
@@ -1097,11 +1098,11 @@ bool QgsRasterLayer::draw(QPainter * theQPainter,
10971098

10981099
/* TODO: Re-enable this for providers
10991100
// Check timestamp
1100-
if ( !providerKey )
1101+
if ( !mProviderKey )
11011102
{
11021103
11031104
#ifdef QGISDEBUG
1104-
std::cout << "QgsRasterLayer::draw(4 arguments): checking timestamp with no providerKey." << std::endl;
1105+
std::cout << "QgsRasterLayer::draw(4 arguments): checking timestamp with no mProviderKey." << std::endl;
11051106
#endif
11061107
11071108
if ( !update() )
@@ -1342,13 +1343,13 @@ static_cast<int>(myRasterViewPort->topLeftPoint .x() + 0.5);
13421343
std::cout << "QgsRasterLayer::draw: Checking for provider key." << std::endl;
13431344
#endif
13441345

1345-
if (!providerKey.isEmpty())
1346+
if (!mProviderKey.isEmpty())
13461347
{
13471348
#ifdef QGISDEBUG
1348-
std::cout << "QgsRasterLayer::draw: Wanting a '" << providerKey.toLocal8Bit().data() << "' provider to draw this." << std::endl;
1349+
std::cout << "QgsRasterLayer::draw: Wanting a '" << mProviderKey.toLocal8Bit().data() << "' provider to draw this." << std::endl;
13491350
#endif
13501351

1351-
emit setStatus(QString("Retrieving using ")+providerKey);
1352+
emit setStatus(QString("Retrieving using ")+mProviderKey);
13521353

13531354
QImage* image =
13541355
dataProvider->draw(
@@ -3225,10 +3226,10 @@ QPixmap QgsRasterLayer::getLegendQPixmap(bool theWithNameFlag)
32253226
QPainter myQPainter;
32263227

32273228

3228-
if (!providerKey.isEmpty())
3229+
if (!mProviderKey.isEmpty())
32293230
{
32303231
#ifdef QGISDEBUG
3231-
std::cout << "QgsRasterLayer::getLegendQPixmap called with provider Key (" << providerKey.toLocal8Bit().data() << ")" << std::endl;
3232+
std::cout << "QgsRasterLayer::getLegendQPixmap called with provider Key (" << mProviderKey.toLocal8Bit().data() << ")" << std::endl;
32323233
#endif
32333234

32343235
myLegendQPixmap = QPixmap(3, 1);
@@ -3906,7 +3907,7 @@ QString QgsRasterLayer::getMetadata()
39063907
myMetadataQString += tr("Driver:");
39073908
myMetadataQString += "</td></tr>";
39083909
myMetadataQString += "<tr><td bgcolor=\"white\">";
3909-
if (providerKey.isEmpty())
3910+
if (mProviderKey.isEmpty())
39103911
{
39113912
myMetadataQString += QString(gdalDataset->GetDriver()->GetDescription());
39123913
myMetadataQString += "<br>";
@@ -3918,7 +3919,7 @@ QString QgsRasterLayer::getMetadata()
39183919
}
39193920
myMetadataQString += "</td></tr>";
39203921

3921-
if (!providerKey.isEmpty())
3922+
if (!mProviderKey.isEmpty())
39223923
{
39233924
// Insert provider-specific (e.g. WMS-specific) metadata
39243925
myMetadataQString += dataProvider->getMetadata();
@@ -4060,7 +4061,7 @@ QString QgsRasterLayer::getMetadata()
40604061
}
40614062
}
40624063
myMetadataQString += "</td></tr>";
4063-
} // if (providerKey.isEmpty())
4064+
} // if (mProviderKey.isEmpty())
40644065

40654066

40664067
myMetadataQString += "<tr><td bgcolor=\"gray\">";
@@ -4078,7 +4079,7 @@ QString QgsRasterLayer::getMetadata()
40784079
myMetadataQString += mCoordinateTransform->destSRS().proj4String();
40794080
myMetadataQString += "</td></tr>";
40804081

4081-
if (providerKey.isEmpty())
4082+
if (mProviderKey.isEmpty())
40824083
{
40834084
if (gdalDataset->GetGeoTransform(adfGeoTransform) != CE_None)
40844085
{
@@ -4233,7 +4234,7 @@ QString QgsRasterLayer::getMetadata()
42334234
}
42344235
myMetadataQString += "</table>"; //end of nested table
42354236
myMetadataQString += "</td></tr>"; //end of stats container table row
4236-
} // if (providerKey.isEmpty())
4237+
} // if (mProviderKey.isEmpty())
42374238

42384239
//
42394240
// Close the table
@@ -4867,6 +4868,17 @@ void QgsRasterLayer::identify(const QgsPoint& point, std::map<QString,QString>&
48674868
} // void QgsRasterLayer::identify
48684869

48694870

4871+
QString QgsRasterLayer::identifyAsHtml(const QgsPoint& point)
4872+
{
4873+
if (mProviderKey != "wms")
4874+
{
4875+
// Currently no meaning for anything other than OGC WMS layers
4876+
return QString();
4877+
}
4878+
4879+
return (dataProvider->identifyAsHtml(point));
4880+
}
4881+
48704882
void QgsRasterLayer::populateHistogram(int theBandNoInt, int theBinCountInt,bool theIgnoreOutOfRangeFlag,bool theHistogramEstimatedFlag)
48714883
{
48724884

@@ -4942,7 +4954,7 @@ QgsRasterLayer::QgsRasterLayer(int dummy,
49424954
stdDevsToPlotDouble(0),
49434955
mTransparencySlider(0x0),
49444956
mLayerProperties(0x0),
4945-
providerKey(providerKey),
4957+
mProviderKey(providerKey),
49464958
dataProvider(0),
49474959
mEditable(false),
49484960
mModified(false)
@@ -5018,7 +5030,7 @@ void QgsRasterLayer::setDataProvider( QString const & provider,
50185030
// XXX should I check for and possibly delete any pre-existing providers?
50195031
// XXX How often will that scenario occur?
50205032

5021-
providerKey = provider; // XXX is this necessary? Usually already set
5033+
mProviderKey = provider; // XXX is this necessary? Usually already set
50225034
// XXX when execution gets here.
50235035

50245036
// load the plugin
@@ -5164,7 +5176,7 @@ void QgsRasterLayer::setDataProvider( QString const & provider,
51645176

51655177
bool QgsRasterLayer::usesProvider()
51665178
{
5167-
if (providerKey.isEmpty())
5179+
if (mProviderKey.isEmpty())
51685180
{
51695181
return FALSE;
51705182
}
@@ -5175,6 +5187,19 @@ bool QgsRasterLayer::usesProvider()
51755187
}
51765188

51775189

5190+
QString QgsRasterLayer::providerKey()
5191+
{
5192+
if (mProviderKey.isEmpty())
5193+
{
5194+
return QString();
5195+
}
5196+
else
5197+
{
5198+
return mProviderKey;
5199+
}
5200+
}
5201+
5202+
51785203
void QgsRasterLayer::showStatusMessage(QString const & theMessage)
51795204
{
51805205
#ifdef QGISDEBUG

‎src/raster/qgsrasterlayer.h

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -294,9 +294,23 @@ class QgsRasterLayer : public QgsMapLayer
294294
// const char *theMessageCharArray,
295295
// void *theData);
296296

297-
/** \brief Identify raster value(s) found on the point position */
297+
/** \brief Identify raster value(s) found on the point position
298+
*
299+
* \param point[in] a coordinate in the CRS of this layer.
300+
*/
298301
void identify(const QgsPoint& point, std::map<QString,QString>& results);
299302

303+
/** \brief Identify arbitrary details from the WMS server found on the point position
304+
*
305+
* \param point[in] an image pixel coordinate in the last requested extent of layer.
306+
*
307+
* \retval An HTML document containing the return from the WMS server
308+
*
309+
* \note The arbitraryness of the returned document is enforced by WMS standards
310+
* up to at least v1.3.0
311+
*/
312+
QString identifyAsHtml(const QgsPoint& point);
313+
300314
/** \brief Query gdal to find out the WKT projection string for this layer. This implements the virtual method of the same name defined in QgsMapLayer*/
301315
QString getProjectionWKT();
302316

@@ -1045,17 +1059,19 @@ public slots:
10451059

10461060
//! Does this layer use a provider for setting/retrieving data?
10471061
bool usesProvider();
1048-
1049-
1062+
1063+
//! Which provider is being used for this Raster Layer?
1064+
QString providerKey();
1065+
10501066
public slots:
1051-
1067+
10521068
void showStatusMessage(QString const & theMessage);
1053-
1054-
1069+
1070+
10551071
private:
10561072

10571073
//! Data provider key
1058-
QString providerKey;
1074+
QString mProviderKey;
10591075

10601076
//! pointer for loading the provider library
10611077
QLibrary *myLib;

0 commit comments

Comments
 (0)
Please sign in to comment.