Skip to content

Commit

Permalink
WMS Improvements:
Browse files Browse the repository at this point in the history
* Errors are now reported as QgsMessageViewer instead of QMessageBox, so that users can copy out URLs - this will be useful for troubleshooting in the field.
* Network timeout error reporting now available - timeout set to 120 seconds.
* HTTP status code reporting now available - reports anything except codes 200 and 302.

WMS Provider Roadmap:
* Need to implement the identify() function.
* Need to pass the provider object from QgsServerSourceSelect so that it doesn't have to get instatiated twice (and therefore 2 downloads of the GetCapabilities document).



git-svn-id: http://svn.osgeo.org/qgis/trunk@4997 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
morb_au committed Mar 10, 2006
1 parent 66c28e4 commit dd7d0e0
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 34 deletions.
21 changes: 16 additions & 5 deletions src/gui/qgsmapcanvas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ email : sherman at mrcc.com
#include <QApplication>
#include <QCursor>
#include <QKeyEvent>
#include <QMessageBox>
//#include <QMessageBox>
#include <QMouseEvent>
#include <QPaintDevice>
#include <QPainter>
Expand All @@ -48,6 +48,8 @@ email : sherman at mrcc.com
#include "qgsproject.h"
#include "qgsrubberband.h"

#include "qgsmessageviewer.h"

#include "qgsmaptoolzoom.h"
#include "qgsmaptoolpan.h"

Expand Down Expand Up @@ -1085,12 +1087,21 @@ void QgsMapCanvas::updateMap()

void QgsMapCanvas::showError(QgsMapLayer * mapLayer)
{
QMessageBox::warning(
this,
mapLayer->errorCaptionString(),
// QMessageBox::warning(
// this,
// mapLayer->errorCaptionString(),
// tr("Could not draw") + " " + mapLayer->name() + " " + tr("because") + ":\n" +
// mapLayer->errorString()
// );

QgsMessageViewer * mv = new QgsMessageViewer(this);
mv->setCaption( mapLayer->errorCaptionString() );
mv->setMessageAsPlainText(
tr("Could not draw") + " " + mapLayer->name() + " " + tr("because") + ":\n" +
mapLayer->errorCaptionString()
mapLayer->errorString()
);
mv->exec();
delete mv;

}

Expand Down
23 changes: 17 additions & 6 deletions src/gui/qgsserversourceselect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@

#include "qgsproject.h"

#include "qgsmessageviewer.h"

#include <QMessageBox>
#include <QPicture>
#include <QSettings>
Expand Down Expand Up @@ -579,14 +581,23 @@ void QgsServerSourceSelect::showStatusMessage(QString const & theMessage)

void QgsServerSourceSelect::showError(QgsWmsProvider * wms)
{
QMessageBox::warning(
this,
wms->errorCaptionString(),
// QMessageBox::warning(
// this,
// wms->errorCaptionString(),
// tr("Could not understand the response. The") + " " + wms->name() + " " +
// tr("provider said") + ":\n" +
// wms->errorString()
// );

QgsMessageViewer * mv = new QgsMessageViewer(this);
mv->setCaption( wms->errorCaptionString() );
mv->setMessageAsPlainText(
tr("Could not understand the response. The") + " " + wms->name() + " " +
tr("provider said") + ":\n" +
wms->errorString()
tr("provider said") + ":\n" +
wms->errorString()
);

mv->exec();
delete mv;
}


Expand Down
119 changes: 99 additions & 20 deletions src/providers/wms/qgshttptransaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,16 @@
#include <qapplication.h>
#include <q3url.h>

#include <QTimer>

static int NETWORK_TIMEOUT_MSEC = (120 * 1000); // 120 seconds

QgsHttpTransaction::QgsHttpTransaction(QString uri, QString proxyHost, Q_UINT16 proxyPort)
: httpurl(uri),
httphost(proxyHost),
httpport(proxyPort),
httpresponsecontenttype(0)
httpresponsecontenttype(0),
mError(0)
{
#ifdef QGISDEBUG
std::cout << "QgsHttpTransaction: constructing." << std::endl;
Expand Down Expand Up @@ -87,40 +91,49 @@ bool QgsHttpTransaction::getSynchronously(QByteArray &respondedContent, int redi
// Proxy -> send complete URL
path = httpurl;
}
http = new Q3Http( httphost, httpport );
http = new Q3Http( httphost, httpport );
mWatchdogTimer = new QTimer( this );

#ifdef QGISDEBUG
qWarning("QgsHttpTransaction::getSynchronously: qurl.host() is '"+qurl.host()+ "'.");
qWarning("QgsHttpTransaction::getSynchronously: qurl.encodedPathAndQuery() is '"+qurl.encodedPathAndQuery()+"'.");
std::cout << "path = " << path.ascii() << std::endl;
#endif

httpresponse.truncate(0);
httpid = http->get( path );
httpactive = TRUE;

connect(http, SIGNAL( requestStarted ( int ) ),

connect(http, SIGNAL( requestStarted ( int ) ),
this, SLOT( dataStarted ( int ) ) );
connect(http, SIGNAL( responseHeaderReceived( const Q3HttpResponseHeader& ) ),

connect(http, SIGNAL( responseHeaderReceived( const Q3HttpResponseHeader& ) ),
this, SLOT( dataHeaderReceived( const Q3HttpResponseHeader& ) ) );
connect(http, SIGNAL( readyRead( const Q3HttpResponseHeader& ) ),

connect(http, SIGNAL( readyRead( const Q3HttpResponseHeader& ) ),
this, SLOT( dataReceived( const Q3HttpResponseHeader& ) ) );
connect(http, SIGNAL( dataReadProgress ( int, int ) ),

connect(http, SIGNAL( dataReadProgress ( int, int ) ),
this, SLOT( dataProgress ( int, int ) ) );

connect(http, SIGNAL( requestFinished ( int, bool ) ),
connect(http, SIGNAL( requestFinished ( int, bool ) ),
this, SLOT( dataFinished ( int, bool ) ) );

connect(http, SIGNAL( stateChanged ( int ) ),
connect(http, SIGNAL( stateChanged ( int ) ),
this, SLOT( dataStateChanged ( int ) ) );

// Set up the watchdog timer
connect(mWatchdogTimer, SIGNAL( timeout () ),
this, SLOT( networkTimedOut () ) );

mWatchdogTimer->setSingleShot(TRUE);
mWatchdogTimer->start(NETWORK_TIMEOUT_MSEC);

#ifdef QGISDEBUG
std::cout << "QgsHttpTransaction::getSynchronously: Starting get." << std::endl;
#endif

httpactive = TRUE;

// A little trick to make this function blocking
while ( httpactive )
{
Expand All @@ -132,14 +145,22 @@ bool QgsHttpTransaction::getSynchronously(QByteArray &respondedContent, int redi

#ifdef QGISDEBUG
std::cout << "QgsHttpTransaction::getSynchronously: Response received." << std::endl;

// QString httpresponsestring(httpresponse);
// std::cout << "QgsHttpTransaction::getSynchronously: Response received; being '" << httpresponsestring << "'." << std::endl;
#endif


delete http;

// Did we get an error? If so, bail early
if (!mError.isNull())
{
#ifdef QGISDEBUG
std::cout << "QgsHttpTransaction::getSynchronously: Processing an error '" << mError.toLocal8Bit().data() << "'." << std::endl;
#endif
return FALSE;
}

// Do one level of redirection
// TODO make this recursable
// TODO detect any redirection loops
Expand Down Expand Up @@ -195,15 +216,28 @@ void QgsHttpTransaction::dataHeaderReceived( const Q3HttpResponseHeader& resp )
resp.value("Content-Type").toLocal8Bit().data() << "'." << std::endl;
#endif

// We saw something come back, therefore restart the watchdog timer
mWatchdogTimer->start(NETWORK_TIMEOUT_MSEC);

if (resp.statusCode() == 302) // Redirect
{
// Grab the alternative URL
// (ref: "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html")
httpredirecturl = resp.value("Location");
}
else if (resp.statusCode() == 200) // OK
{
// NOOP
}
else
{
mError = QString( tr("WMS Server responded unexpectedly with HTTP Status Code %1 (%2)") )
.arg( resp.statusCode() )
.arg( resp.reasonPhrase() );
}

httpresponsecontenttype = resp.value("Content-Type");

}


Expand All @@ -224,7 +258,7 @@ void QgsHttpTransaction::dataReceived( const Q3HttpResponseHeader& resp )
// std::cout << "QgsHttpTransaction::dataReceived." << std::endl;
// std::cout << "QgsHttpTransaction::dataReceived: received '" << data << "'."<< std::endl;
#endif

}


Expand All @@ -235,6 +269,9 @@ void QgsHttpTransaction::dataProgress( int done, int total )
// std::cout << "QgsHttpTransaction::dataProgress: got " << done << " of " << total << std::endl;
#endif

// We saw something come back, therefore restart the watchdog timer
mWatchdogTimer->start(NETWORK_TIMEOUT_MSEC);

QString status;

if (total)
Expand All @@ -258,11 +295,30 @@ void QgsHttpTransaction::dataFinished( int id, bool error )
#ifdef QGISDEBUG
std::cout << "QgsHttpTransaction::dataFinished with ID " << id << "." << std::endl;

// The signal that this slot is connected to, Q3Http::requestFinished,
// appears to get called at the destruction of the Q3Http if it is
// still working at the time of the destruction.
//
// This situation may occur when we've detected a timeout and
// we already set httpactive = FALSE.
//
// We have to detect this special case so that the last known error string is
// not overwritten (it should rightfully refer to the timeout event).
if (!httpactive)
{
std::cout << "QgsHttpTransaction::dataFinished - http activity loop already FALSE." << std::endl;
return;
}

if (error)
{
std::cout << "QgsHttpTransaction::dataFinished - however there was an error." << std::endl;
std::cout << "QgsHttpTransaction::dataFinished - " << http->errorString().toLocal8Bit().data() << std::endl;
} else

mError = QString( tr("HTTP response completed, however there was an error: %1") )
.arg( http->errorString() );
}
else
{
std::cout << "QgsHttpTransaction::dataFinished - no error." << std::endl;
}
Expand All @@ -272,7 +328,7 @@ void QgsHttpTransaction::dataFinished( int id, bool error )
httpresponse = http->readAll();

httpactive = FALSE;

}

void QgsHttpTransaction::dataStateChanged( int state )
Expand All @@ -282,6 +338,9 @@ void QgsHttpTransaction::dataStateChanged( int state )
std::cout << "QgsHttpTransaction::dataStateChanged to " << state << "." << std::endl << " ";
#endif

// We saw something come back, therefore restart the watchdog timer
mWatchdogTimer->start(NETWORK_TIMEOUT_MSEC);

switch (state)
{
case Q3Http::Unconnected:
Expand Down Expand Up @@ -350,6 +409,26 @@ void QgsHttpTransaction::dataStateChanged( int state )
}


void QgsHttpTransaction::networkTimedOut()
{

#ifdef QGISDEBUG
std::cout << "QgsHttpTransaction::networkTimedOut: entering." << std::endl;
#endif

mError = QString(tr("Network timed out after %1 seconds of inactivity.\n"
"This may be a problem in your network connection or at the WMS server.")
).arg(NETWORK_TIMEOUT_MSEC/1000);

httpactive = FALSE;

#ifdef QGISDEBUG
std::cout << "QgsHttpTransaction::networkTimedOut: exiting." << std::endl;
#endif

}


QString QgsHttpTransaction::errorString()
{
return mError;
Expand Down
12 changes: 9 additions & 3 deletions src/providers/wms/qgshttptransaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ class QgsHttpTransaction : public QObject
public slots:

void dataStarted( int id );

void dataHeaderReceived( const Q3HttpResponseHeader& resp );

void dataReceived( const Q3HttpResponseHeader& resp );

void dataProgress( int done, int total );
Expand All @@ -89,7 +89,8 @@ public slots:

void dataStateChanged( int state );


void networkTimedOut();

signals:

/** \brief emit a signal to notify of a progress event */
Expand Down Expand Up @@ -160,6 +161,11 @@ public slots:
*/
int httpredirections;

/**
* Indicates the associated QTimer object - used to detect network timeouts
*/
QTimer * mWatchdogTimer;

/**
* The error message associated with the last HTTP error.
*/
Expand Down

0 comments on commit dd7d0e0

Please sign in to comment.