source: trunk/examples/xml/rsslisting/rsslisting.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 7.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the examples of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:BSD$
10** You may use this file under the terms of the BSD license as follows:
11**
12** "Redistribution and use in source and binary forms, with or without
13** modification, are permitted provided that the following conditions are
14** met:
15** * Redistributions of source code must retain the above copyright
16** notice, this list of conditions and the following disclaimer.
17** * Redistributions in binary form must reproduce the above copyright
18** notice, this list of conditions and the following disclaimer in
19** the documentation and/or other materials provided with the
20** distribution.
21** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
22** the names of its contributors may be used to endorse or promote
23** products derived from this software without specific prior written
24** permission.
25**
26** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
37** $QT_END_LICENSE$
38**
39****************************************************************************/
40
41/*
42rsslisting.cpp
43
44Provides a widget for displaying news items from RDF news sources.
45RDF is an XML-based format for storing items of information (see
46http://www.w3.org/RDF/ for details).
47
48The widget itself provides a simple user interface for specifying
49the URL of a news source, and controlling the downloading of news.
50
51The widget downloads and parses the XML asynchronously, feeding the
52data to an XML reader in pieces. This allows the user to interrupt
53its operation, and also allows very large data sources to be read.
54*/
55
56
57#include <QtCore>
58#include <QtGui>
59#include <QtNetwork>
60
61#include "rsslisting.h"
62
63
64/*
65 Constructs an RSSListing widget with a simple user interface, and sets
66 up the XML reader to use a custom handler class.
67
68 The user interface consists of a line edit, a push button, and a
69 list view widget. The line edit is used for entering the URLs of news
70 sources; the push button starts the process of reading the
71 news.
72*/
73
74RSSListing::RSSListing(QWidget *parent)
75 : QWidget(parent), currentReply(0)
76{
77 lineEdit = new QLineEdit(this);
78 lineEdit->setText("http://labs.qt.nokia.com/blogs/feed");
79
80 fetchButton = new QPushButton(tr("Fetch"), this);
81
82 treeWidget = new QTreeWidget(this);
83 connect(treeWidget, SIGNAL(itemActivated(QTreeWidgetItem*,int)),
84 this, SLOT(itemActivated(QTreeWidgetItem*)));
85 QStringList headerLabels;
86 headerLabels << tr("Title") << tr("Link");
87 treeWidget->setHeaderLabels(headerLabels);
88 treeWidget->header()->setResizeMode(QHeaderView::ResizeToContents);
89
90 connect(&manager, SIGNAL(finished(QNetworkReply*)),
91 this, SLOT(finished(QNetworkReply*)));
92
93 connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(fetch()));
94 connect(fetchButton, SIGNAL(clicked()), this, SLOT(fetch()));
95
96 QVBoxLayout *layout = new QVBoxLayout(this);
97
98 QHBoxLayout *hboxLayout = new QHBoxLayout;
99
100 hboxLayout->addWidget(lineEdit);
101 hboxLayout->addWidget(fetchButton);
102
103 layout->addLayout(hboxLayout);
104 layout->addWidget(treeWidget);
105
106 setWindowTitle(tr("RSS listing example"));
107 resize(640,480);
108}
109
110/*
111 Starts the network request and connects the needed signals
112*/
113void RSSListing::get(const QUrl &url)
114{
115 QNetworkRequest request(url);
116 if (currentReply) {
117 currentReply->disconnect(this);
118 currentReply->deleteLater();
119 }
120 currentReply = manager.get(request);
121 connect(currentReply, SIGNAL(readyRead()), this, SLOT(readyRead()));
122 connect(currentReply, SIGNAL(metaDataChanged()), this, SLOT(metaDataChanged()));
123 connect(currentReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(error(QNetworkReply::NetworkError)));
124}
125
126/*
127 Starts fetching data from a news source specified in the line
128 edit widget.
129
130 The line edit is made read only to prevent the user from modifying its
131 contents during the fetch; this is only for cosmetic purposes.
132 The fetch button is disabled, the list view is cleared, and we
133 define the last list view item to be 0, meaning that there are no
134 existing items in the list.
135
136 A URL is created with the raw contents of the line edit and
137 a get is initiated.
138*/
139
140void RSSListing::fetch()
141{
142 lineEdit->setReadOnly(true);
143 fetchButton->setEnabled(false);
144 treeWidget->clear();
145
146 xml.clear();
147
148 QUrl url(lineEdit->text());
149 get(url);
150}
151
152void RSSListing::metaDataChanged()
153{
154 QUrl redirectionTarget = currentReply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
155 if (redirectionTarget.isValid()) {
156 get(redirectionTarget);
157 }
158}
159
160/*
161 Reads data received from the RDF source.
162
163 We read all the available data, and pass it to the XML
164 stream reader. Then we call the XML parsing function.
165*/
166
167void RSSListing::readyRead()
168{
169 int statusCode = currentReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
170 if (statusCode >= 200 && statusCode < 300) {
171 QByteArray data = currentReply->readAll();
172 xml.addData(data);
173 parseXml();
174 }
175}
176
177/*
178 Finishes processing an HTTP request.
179
180 The default behavior is to keep the text edit read only.
181
182 If an error has occurred, the user interface is made available
183 to the user for further input, allowing a new fetch to be
184 started.
185
186 If the HTTP get request has finished, we make the
187 user interface available to the user for further input.
188*/
189
190void RSSListing::finished(QNetworkReply *reply)
191{
192 Q_UNUSED(reply);
193 lineEdit->setReadOnly(false);
194 fetchButton->setEnabled(true);
195}
196
197
198/*
199 Parses the XML data and creates treeWidget items accordingly.
200*/
201void RSSListing::parseXml()
202{
203 while (!xml.atEnd()) {
204 xml.readNext();
205 if (xml.isStartElement()) {
206 if (xml.name() == "item")
207 linkString = xml.attributes().value("rss:about").toString();
208 currentTag = xml.name().toString();
209 } else if (xml.isEndElement()) {
210 if (xml.name() == "item") {
211
212 QTreeWidgetItem *item = new QTreeWidgetItem;
213 item->setText(0, titleString);
214 item->setText(1, linkString);
215 treeWidget->addTopLevelItem(item);
216
217 titleString.clear();
218 linkString.clear();
219 }
220
221 } else if (xml.isCharacters() && !xml.isWhitespace()) {
222 if (currentTag == "title")
223 titleString += xml.text().toString();
224 else if (currentTag == "link")
225 linkString += xml.text().toString();
226 }
227 }
228 if (xml.error() && xml.error() != QXmlStreamReader::PrematureEndOfDocumentError) {
229 qWarning() << "XML ERROR:" << xml.lineNumber() << ": " << xml.errorString();
230 }
231}
232
233/*
234 Open the link in the browser
235*/
236void RSSListing::itemActivated(QTreeWidgetItem * item)
237{
238 QDesktopServices::openUrl(QUrl(item->text(1)));
239}
240
241void RSSListing::error(QNetworkReply::NetworkError)
242{
243 qWarning("error retrieving RSS feed");
244 currentReply->disconnect(this);
245 currentReply->deleteLater();
246 currentReply = 0;
247}
Note: See TracBrowser for help on using the repository browser.