examples/xml/rsslisting/rsslisting.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/xml/rsslisting/rsslisting.cpp	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,239 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+rsslisting.cpp
+
+Provides a widget for displaying news items from RDF news sources.
+RDF is an XML-based format for storing items of information (see
+http://www.w3.org/RDF/ for details).
+
+The widget itself provides a simple user interface for specifying
+the URL of a news source, and controlling the downloading of news.
+
+The widget downloads and parses the XML asynchronously, feeding the
+data to an XML reader in pieces. This allows the user to interrupt
+its operation, and also allows very large data sources to be read.
+*/
+
+
+#include <QtCore>
+#include <QtGui>
+#include <QtNetwork>
+
+#include "rsslisting.h"
+
+
+/*
+    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
+    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
+    news.
+*/
+
+RSSListing::RSSListing(QWidget *parent)
+    : QWidget(parent)
+{
+    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)),
+            this, SLOT(itemActivated(QTreeWidgetItem*)));
+    QStringList headerLabels;
+    headerLabels << tr("Title") << tr("Link");
+    treeWidget->setHeaderLabels(headerLabels);
+    treeWidget->header()->setResizeMode(QHeaderView::ResizeToContents);
+
+    connect(&http, SIGNAL(readyRead(const QHttpResponseHeader &)),
+             this, SLOT(readData(const QHttpResponseHeader &)));
+
+    connect(&http, SIGNAL(requestFinished(int, bool)),
+             this, SLOT(finished(int, bool)));
+
+    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);
+
+    QHBoxLayout *hboxLayout = new QHBoxLayout;
+
+    hboxLayout->addWidget(lineEdit);
+    hboxLayout->addWidget(fetchButton);
+    hboxLayout->addWidget(abortButton);
+
+    layout->addLayout(hboxLayout);
+    layout->addWidget(treeWidget);
+
+    setWindowTitle(tr("RSS listing example"));
+    resize(640,480);
+}
+
+/*
+    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
+    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.
+*/
+
+void RSSListing::fetch()
+{
+    lineEdit->setReadOnly(true);
+    fetchButton->setEnabled(false);
+    abortButton->setEnabled(true);
+    treeWidget->clear();
+
+    xml.clear();
+
+    QUrl url(lineEdit->text());
+
+    http.setHost(url.host());
+    connectionId = http.get(url.path());
+}
+
+/*
+    Reads data received from the RDF source.
+
+    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)
+{
+    if (resp.statusCode() != 200)
+        http.abort();
+    else {
+        xml.addData(http.readAll());
+        parseXml();
+    }
+}
+
+/*
+    Finishes processing an HTTP request.
+
+    The default behavior is to keep the text edit read only.
+
+    If an error has occurred, the user interface is made available
+    to the user for further input, allowing a new fetch to be
+    started.
+
+    If the HTTP get request has finished, we make the
+    user interface available to the user for further input.
+*/
+
+void RSSListing::finished(int id, bool error)
+{
+    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);
+    }
+}
+
+
+/*
+    Parses the XML data and creates treeWidget items accordingly.
+*/
+void RSSListing::parseXml()
+{
+    while (!xml.atEnd()) {
+        xml.readNext();
+        if (xml.isStartElement()) {
+            if (xml.name() == "item")
+                linkString = xml.attributes().value("rss:about").toString();
+            currentTag = xml.name().toString();
+        } else if (xml.isEndElement()) {
+            if (xml.name() == "item") {
+
+                QTreeWidgetItem *item = new QTreeWidgetItem;
+                item->setText(0, titleString);
+                item->setText(1, linkString);
+                treeWidget->addTopLevelItem(item);
+
+                titleString.clear();
+                linkString.clear();
+            }
+
+        } else if (xml.isCharacters() && !xml.isWhitespace()) {
+            if (currentTag == "title")
+                titleString += xml.text().toString();
+            else if (currentTag == "link")
+                linkString += xml.text().toString();
+        }
+    }
+    if (xml.error() && xml.error() != QXmlStreamReader::PrematureEndOfDocumentError) {
+        qWarning() << "XML ERROR:" << xml.lineNumber() << ": " << xml.errorString();
+        http.abort();
+    }
+}
+
+/*
+    Open the link in the browser
+*/
+void RSSListing::itemActivated(QTreeWidgetItem * item)
+{
+    QDesktopServices::openUrl(QUrl(item->text(1)));
+}