From 3f4a3acab163fa6675a1513ab1fccdbda7723dd6 Mon Sep 17 00:00:00 2001 From: Aaron McCarthy Date: Wed, 19 Feb 2014 16:38:10 +1000 Subject: Parse Nokia geocode response in helper thread. Change-Id: I151bd5988d0340a8203aa9e014371989b023228b Reviewed-by: Alex Blasche --- .../geoservices/nokia/qgeocodereply_nokia.cpp | 73 ++++++++++++---------- .../geoservices/nokia/qgeocodereply_nokia.h | 3 + .../geoservices/nokia/qgeocodexmlparser.cpp | 40 ++++++------ src/plugins/geoservices/nokia/qgeocodexmlparser.h | 26 +++++--- 4 files changed, 79 insertions(+), 63 deletions(-) diff --git a/src/plugins/geoservices/nokia/qgeocodereply_nokia.cpp b/src/plugins/geoservices/nokia/qgeocodereply_nokia.cpp index cb76fbca..8690eb65 100644 --- a/src/plugins/geoservices/nokia/qgeocodereply_nokia.cpp +++ b/src/plugins/geoservices/nokia/qgeocodereply_nokia.cpp @@ -51,22 +51,19 @@ #include +Q_DECLARE_METATYPE(QList) + QT_BEGIN_NAMESPACE QGeoCodeReplyNokia::QGeoCodeReplyNokia(QNetworkReply *reply, int limit, int offset, const QGeoShape &viewport, QObject *parent) - : QGeoCodeReply(parent), - m_reply(reply) +: QGeoCodeReply(parent), m_reply(reply), m_parsing(false) { - connect(m_reply, - SIGNAL(finished()), - this, - SLOT(networkFinished())); + qRegisterMetaType >(); - connect(m_reply, - SIGNAL(error(QNetworkReply::NetworkError)), - this, - SLOT(networkError(QNetworkReply::NetworkError))); + connect(m_reply, SIGNAL(finished()), this, SLOT(networkFinished())); + connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), + this, SLOT(networkError(QNetworkReply::NetworkError))); setLimit(limit); setOffset(offset); @@ -75,18 +72,19 @@ QGeoCodeReplyNokia::QGeoCodeReplyNokia(QNetworkReply *reply, int limit, int offs QGeoCodeReplyNokia::~QGeoCodeReplyNokia() { - //TODO: possible mem leak -> m_reply->deleteLater() ? + abort(); } void QGeoCodeReplyNokia::abort() { - if (!m_reply) + if (!m_reply && !m_parsing) return; m_reply->abort(); m_reply->deleteLater(); m_reply = 0; + m_parsing = false; } void QGeoCodeReplyNokia::networkFinished() @@ -94,29 +92,17 @@ void QGeoCodeReplyNokia::networkFinished() if (!m_reply) return; - if (m_reply->error() != QNetworkReply::NoError) { - // Removed because this is already done in networkError, which previously caused _two_ errors to be raised for every error. - //setError(QGeoCodeReply::CommunicationError, m_reply->errorString()); - //m_reply->deleteLater(); - //m_reply = 0; + if (m_reply->error() != QNetworkReply::NoError) return; - } - - QGeoCodeXmlParser parser; - if (parser.parse(m_reply)) { - QList locations = parser.results(); - QGeoShape bounds = viewport(); - if (bounds.isValid()) { - for (int i = locations.size() - 1; i >= 0; --i) { - if (!bounds.contains(locations[i].coordinate())) - locations.removeAt(i); - } - } - setLocations(locations); - setFinished(true); - } else { - setError(QGeoCodeReply::ParseError, parser.errorString()); - } + + QGeoCodeXmlParser *parser = new QGeoCodeXmlParser; + parser->setBounds(viewport()); + connect(parser, SIGNAL(results(QList)), + this, SLOT(appendResults(QList))); + connect(parser, SIGNAL(error(QString)), this, SLOT(parseError(QString))); + + m_parsing = true; + parser->parse(m_reply->readAll()); m_reply->deleteLater(); m_reply = 0; @@ -135,4 +121,23 @@ void QGeoCodeReplyNokia::networkError(QNetworkReply::NetworkError error) m_reply = 0; } +void QGeoCodeReplyNokia::appendResults(const QList &locations) +{ + if (!m_parsing) + return; + + m_parsing = false; + setLocations(locations); + setFinished(true); +} + +void QGeoCodeReplyNokia::parseError(const QString &errorString) +{ + Q_UNUSED(errorString) + + setError(QGeoCodeReply::ParseError, + tr("The response from the service was not in a recognisable format.")); + abort(); +} + QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/qgeocodereply_nokia.h b/src/plugins/geoservices/nokia/qgeocodereply_nokia.h index 6b72cd40..af3f4dec 100644 --- a/src/plugins/geoservices/nokia/qgeocodereply_nokia.h +++ b/src/plugins/geoservices/nokia/qgeocodereply_nokia.h @@ -66,9 +66,12 @@ public: private Q_SLOTS: void networkFinished(); void networkError(QNetworkReply::NetworkError error); + void appendResults(const QList &locations); + void parseError(const QString &errorString); private: QNetworkReply *m_reply; + bool m_parsing; }; QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/qgeocodexmlparser.cpp b/src/plugins/geoservices/nokia/qgeocodexmlparser.cpp index b9dbd934..d19246ff 100644 --- a/src/plugins/geoservices/nokia/qgeocodexmlparser.cpp +++ b/src/plugins/geoservices/nokia/qgeocodexmlparser.cpp @@ -48,10 +48,9 @@ #include "qgeocodexmlparser.h" -#include -#include - -#include +#include +#include +#include #include #include #include @@ -66,28 +65,28 @@ QGeoCodeXmlParser::~QGeoCodeXmlParser() { } -bool QGeoCodeXmlParser::parse(QIODevice *source) +void QGeoCodeXmlParser::setBounds(const QGeoShape &bounds) { - m_reader.reset(new QXmlStreamReader(source)); - - if (!parseRootElement()) { - m_errorString = m_reader->errorString(); - return false; - } - - m_errorString = ""; - - return true; + m_bounds = bounds; } -QList QGeoCodeXmlParser::results() const +void QGeoCodeXmlParser::parse(const QByteArray &data) { - return m_results; + m_data = data; + QThreadPool::globalInstance()->start(this); } -QString QGeoCodeXmlParser::errorString() const +void QGeoCodeXmlParser::run() { - return m_errorString; + m_reader = new QXmlStreamReader(m_data); + + if (!parseRootElement()) + emit error(m_reader->errorString()); + else + emit results(m_results); + + delete m_reader; + m_reader = 0; } bool QGeoCodeXmlParser::parseRootElement() @@ -137,7 +136,8 @@ bool QGeoCodeXmlParser::parseRootElement() if (!parsePlace(&location)) return false; - m_results.append(location); + if (!m_bounds.isValid() || m_bounds.contains(location.coordinate())) + m_results.append(location); } else { m_reader->raiseError(QString("The element \"places\" did not expect a child element named \"%1\".").arg(m_reader->name().toString())); return false; diff --git a/src/plugins/geoservices/nokia/qgeocodexmlparser.h b/src/plugins/geoservices/nokia/qgeocodexmlparser.h index 8eeb6cc3..67c9da9e 100644 --- a/src/plugins/geoservices/nokia/qgeocodexmlparser.h +++ b/src/plugins/geoservices/nokia/qgeocodexmlparser.h @@ -49,29 +49,35 @@ #ifndef QGEOCODEXMLPARSER_H #define QGEOCODEXMLPARSER_H -#include -#include -#include +#include +#include +#include +#include +#include QT_BEGIN_NAMESPACE -class QIODevice; class QGeoLocation; class QGeoAddress; class QGeoRectangle; class QGeoCoordinate; class QXmlStreamReader; -class QGeoCodeXmlParser +class QGeoCodeXmlParser : public QObject, public QRunnable { + Q_OBJECT + public: QGeoCodeXmlParser(); ~QGeoCodeXmlParser(); - bool parse(QIODevice *source); + void setBounds(const QGeoShape &bounds); + void parse(const QByteArray &data); + void run(); - QList results() const; - QString errorString() const; +signals: + void results(const QList &locations); + void error(const QString &errorString); private: bool parseRootElement(); @@ -81,7 +87,9 @@ private: bool parseBoundingBox(QGeoRectangle *bounds); bool parseCoordinate(QGeoCoordinate *coordinate, const QString &elementName); - QScopedPointer m_reader; + QGeoShape m_bounds; + QByteArray m_data; + QXmlStreamReader *m_reader; QList m_results; QString m_errorString; -- cgit v1.2.1