From 15ddcea2d15b7d7731e24151b0a30990e77efe74 Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Fri, 24 Sep 2010 11:47:36 +0200 Subject: fix RSS listing example ... by handling HTTP 30X responses and using QNetworkAccessManager instead of QHttp. The server now sends back a HTTP 302 instead of a 200. Reviewed-by: Markus Goetz Task-number: QTBUG-13892 --- examples/xml/rsslisting/main.cpp | 1 - examples/xml/rsslisting/rsslisting.cpp | 89 +++++++++++++++++++--------------- examples/xml/rsslisting/rsslisting.h | 16 +++--- 3 files changed, 59 insertions(+), 47 deletions(-) diff --git a/examples/xml/rsslisting/main.cpp b/examples/xml/rsslisting/main.cpp index 95c8a89..71ae0eb 100644 --- a/examples/xml/rsslisting/main.cpp +++ b/examples/xml/rsslisting/main.cpp @@ -57,7 +57,6 @@ Provides the main function for the RSS news reader example. int main(int argc, char **argv) { QApplication app(argc, argv); - qWarning("The usage of QHttp is not recommended anymore, please use QNetworkAccessManager."); RSSListing *rsslisting = new RSSListing; rsslisting->show(); return app.exec(); diff --git a/examples/xml/rsslisting/rsslisting.cpp b/examples/xml/rsslisting/rsslisting.cpp index b7c9eb0..48c3062 100644 --- a/examples/xml/rsslisting/rsslisting.cpp +++ b/examples/xml/rsslisting/rsslisting.cpp @@ -65,21 +65,19 @@ its operation, and also allows very large data sources to be read. Constructs an RSSListing widget with a simple user interface, and sets up the XML reader to use a custom handler class. - The user interface consists of a line edit, two push buttons, and a + The user interface consists of a line edit, a push button, and a list view widget. The line edit is used for entering the URLs of news - sources; the push buttons start and abort the process of reading the + sources; the push button starts the process of reading the news. */ RSSListing::RSSListing(QWidget *parent) - : QWidget(parent) + : QWidget(parent), currentReply(0) { lineEdit = new QLineEdit(this); lineEdit->setText("http://labs.qt.nokia.com/blogs/feed"); fetchButton = new QPushButton(tr("Fetch"), this); - abortButton = new QPushButton(tr("Abort"), this); - abortButton->setEnabled(false); treeWidget = new QTreeWidget(this); connect(treeWidget, SIGNAL(itemActivated(QTreeWidgetItem*,int)), @@ -89,15 +87,11 @@ RSSListing::RSSListing(QWidget *parent) treeWidget->setHeaderLabels(headerLabels); treeWidget->header()->setResizeMode(QHeaderView::ResizeToContents); - connect(&http, SIGNAL(readyRead(QHttpResponseHeader)), - this, SLOT(readData(QHttpResponseHeader))); - - connect(&http, SIGNAL(requestFinished(int,bool)), - this, SLOT(finished(int,bool))); + connect(&manager, SIGNAL(finished(QNetworkReply*)), + this, SLOT(finished(QNetworkReply*))); connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(fetch())); connect(fetchButton, SIGNAL(clicked()), this, SLOT(fetch())); - connect(abortButton, SIGNAL(clicked()), &http, SLOT(abort())); QVBoxLayout *layout = new QVBoxLayout(this); @@ -105,7 +99,6 @@ RSSListing::RSSListing(QWidget *parent) hboxLayout->addWidget(lineEdit); hboxLayout->addWidget(fetchButton); - hboxLayout->addWidget(abortButton); layout->addLayout(hboxLayout); layout->addWidget(treeWidget); @@ -115,34 +108,53 @@ RSSListing::RSSListing(QWidget *parent) } /* + Starts the network request and connects the needed signals +*/ +void RSSListing::get(const QUrl &url) +{ + QNetworkRequest request(url); + if (currentReply) { + currentReply->disconnect(this); + currentReply->deleteLater(); + } + currentReply = manager.get(request); + connect(currentReply, SIGNAL(readyRead()), this, SLOT(readyRead())); + connect(currentReply, SIGNAL(metaDataChanged()), this, SLOT(metaDataChanged())); + connect(currentReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(error(QNetworkReply::NetworkError))); +} + +/* Starts fetching data from a news source specified in the line edit widget. The line edit is made read only to prevent the user from modifying its contents during the fetch; this is only for cosmetic purposes. - The fetch button is disabled, and the abort button is enabled to allow - the user to interrupt processing. The list view is cleared, and we + The fetch button is disabled, the list view is cleared, and we define the last list view item to be 0, meaning that there are no existing items in the list. - The HTTP handler is supplied with the raw contents of the line edit and - a fetch is initiated. We keep the ID value returned by the HTTP handler - for future reference. + A URL is created with the raw contents of the line edit and + a get is initiated. */ void RSSListing::fetch() { lineEdit->setReadOnly(true); fetchButton->setEnabled(false); - abortButton->setEnabled(true); treeWidget->clear(); xml.clear(); QUrl url(lineEdit->text()); + get(url); +} - http.setHost(url.host()); - connectionId = http.get(url.path()); +void RSSListing::metaDataChanged() +{ + QUrl redirectionTarget = currentReply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); + if (redirectionTarget.isValid()) { + get(redirectionTarget); + } } /* @@ -150,16 +162,14 @@ void RSSListing::fetch() We read all the available data, and pass it to the XML stream reader. Then we call the XML parsing function. - - If parsing fails for any reason, we abort the fetch. */ -void RSSListing::readData(const QHttpResponseHeader &resp) +void RSSListing::readyRead() { - if (resp.statusCode() != 200) - http.abort(); - else { - xml.addData(http.readAll()); + int statusCode = currentReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + if (statusCode >= 200 && statusCode < 300) { + QByteArray data = currentReply->readAll(); + xml.addData(data); parseXml(); } } @@ -177,19 +187,11 @@ void RSSListing::readData(const QHttpResponseHeader &resp) user interface available to the user for further input. */ -void RSSListing::finished(int id, bool error) +void RSSListing::finished(QNetworkReply *reply) { - if (error) { - qWarning("Received error during HTTP fetch."); - lineEdit->setReadOnly(false); - abortButton->setEnabled(false); - fetchButton->setEnabled(true); - } - else if (id == connectionId) { - lineEdit->setReadOnly(false); - abortButton->setEnabled(false); - fetchButton->setEnabled(true); - } + Q_UNUSED(reply); + lineEdit->setReadOnly(false); + fetchButton->setEnabled(true); } @@ -225,7 +227,6 @@ void RSSListing::parseXml() } if (xml.error() && xml.error() != QXmlStreamReader::PrematureEndOfDocumentError) { qWarning() << "XML ERROR:" << xml.lineNumber() << ": " << xml.errorString(); - http.abort(); } } @@ -236,3 +237,11 @@ void RSSListing::itemActivated(QTreeWidgetItem * item) { QDesktopServices::openUrl(QUrl(item->text(1))); } + +void RSSListing::error(QNetworkReply::NetworkError) +{ + qWarning("error retrieving RSS feed"); + currentReply->disconnect(this); + currentReply->deleteLater(); + currentReply = 0; +} diff --git a/examples/xml/rsslisting/rsslisting.h b/examples/xml/rsslisting/rsslisting.h index 8939dfd..9387222 100644 --- a/examples/xml/rsslisting/rsslisting.h +++ b/examples/xml/rsslisting/rsslisting.h @@ -41,10 +41,12 @@ #ifndef RSSLISTING_H #define RSSLISTING_H -#include +#include +#include #include #include #include +#include QT_BEGIN_NAMESPACE class QLineEdit; @@ -61,24 +63,26 @@ public: public slots: void fetch(); - void finished(int id, bool error); - void readData(const QHttpResponseHeader &); + void finished(QNetworkReply *reply); + void readyRead(); + void metaDataChanged(); void itemActivated(QTreeWidgetItem * item); + void error(QNetworkReply::NetworkError); private: void parseXml(); + void get(const QUrl &url); QXmlStreamReader xml; QString currentTag; QString linkString; QString titleString; - QHttp http; - int connectionId; + QNetworkAccessManager manager; + QNetworkReply *currentReply; QLineEdit *lineEdit; QTreeWidget *treeWidget; - QPushButton *abortButton; QPushButton *fetchButton; }; -- cgit v0.12 From 44be0ca47c6dff6114bbda0ca7e294991f6a98f1 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Fri, 24 Sep 2010 15:29:25 +0200 Subject: Fix a compilation issue of tst_qsettings for win32-msvc. Need to include advapi32 for seperate usage of registry functions. Reviewed-by: Marius Storm-Olsen --- tests/auto/qsettings/qsettings.pro | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/auto/qsettings/qsettings.pro b/tests/auto/qsettings/qsettings.pro index 115fb13..19513b3 100644 --- a/tests/auto/qsettings/qsettings.pro +++ b/tests/auto/qsettings/qsettings.pro @@ -5,3 +5,4 @@ RESOURCES += qsettings.qrc contains(QT_CONFIG, qt3support):QT += qt3support CONFIG -= debug CONFIG += release +win32-msvc*:LIBS += advapi32.lib -- cgit v0.12 From 45c2ac4f1e1218f595b1d21691c8dec4eaa1a021 Mon Sep 17 00:00:00 2001 From: Jocelyn Turcotte Date: Sun, 26 Sep 2010 18:38:55 +0200 Subject: QHostInfo: Fix a crash when a new request is pushed while resolving. The loop looking for posponedLookup in the lookup thread wasn't locking the mutex before trying to access/modify the list. Reviewed-by: Andreas Kling --- src/network/kernel/qhostinfo.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp index 348b0d2..41a9512 100644 --- a/src/network/kernel/qhostinfo.cpp +++ b/src/network/kernel/qhostinfo.cpp @@ -468,14 +468,17 @@ void QHostInfoRunnable::run() resultEmitter.emitResultsReady(hostInfo); // now also iterate through the postponed ones - QMutableListIterator iterator(manager->postponedLookups); - while (iterator.hasNext()) { - QHostInfoRunnable* postponed = iterator.next(); - if (toBeLookedUp == postponed->toBeLookedUp) { - // we can now emit - iterator.remove(); - hostInfo.setLookupId(postponed->id); - postponed->resultEmitter.emitResultsReady(hostInfo); + { + QMutexLocker locker(&manager->mutex); + QMutableListIterator iterator(manager->postponedLookups); + while (iterator.hasNext()) { + QHostInfoRunnable* postponed = iterator.next(); + if (toBeLookedUp == postponed->toBeLookedUp) { + // we can now emit + iterator.remove(); + hostInfo.setLookupId(postponed->id); + postponed->resultEmitter.emitResultsReady(hostInfo); + } } } -- cgit v0.12