1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
|
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "rsslisting.h"
#include <QtCore>
#include <QtWidgets>
#include <QtNetwork>
//! [setup]
RSSListing::RSSListing(const QString &url, QWidget *parent)
: QWidget(parent), currentReply(0)
{
connect(&manager, &QNetworkAccessManager::finished, this, &RSSListing::finished);
lineEdit = new QLineEdit(this);
lineEdit->setText(url);
connect(lineEdit, &QLineEdit::returnPressed, this, &RSSListing::fetch);
fetchButton = new QPushButton(tr("Fetch"), this);
connect(fetchButton, &QPushButton::clicked, this, &RSSListing::fetch);
treeWidget = new QTreeWidget(this);
connect(treeWidget, &QTreeWidget::itemActivated,
// Open the link in the browser:
this, [](QTreeWidgetItem *item) { QDesktopServices::openUrl(QUrl(item->text(1))); });
treeWidget->setHeaderLabels(QStringList { tr("Title"), tr("Link") });
treeWidget->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
QHBoxLayout *hboxLayout = new QHBoxLayout;
hboxLayout->addWidget(lineEdit);
hboxLayout->addWidget(fetchButton);
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addLayout(hboxLayout);
layout->addWidget(treeWidget);
setWindowTitle(tr("RSS listing example"));
resize(640, 480);
}
//! [setup]
//! [slots]
void RSSListing::fetch()
{
lineEdit->setReadOnly(true);
fetchButton->setEnabled(false);
treeWidget->clear();
get(QUrl(lineEdit->text()));
}
void RSSListing::consumeData()
{
int statusCode = currentReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (statusCode >= 200 && statusCode < 300)
parseXml();
}
void RSSListing::error(QNetworkReply::NetworkError)
{
qWarning("error retrieving RSS feed");
xml.clear();
currentReply->disconnect(this);
currentReply->deleteLater();
currentReply = nullptr;
}
void RSSListing::finished(QNetworkReply *reply)
{
Q_UNUSED(reply);
lineEdit->setReadOnly(false);
fetchButton->setEnabled(true);
}
//! [slots]
// Private methods
//! [get]
void RSSListing::get(const QUrl &url)
{
if (currentReply) {
currentReply->disconnect(this);
currentReply->deleteLater();
}
currentReply = url.isValid() ? manager.get(QNetworkRequest(url)) : nullptr;
if (currentReply) {
connect(currentReply, &QNetworkReply::readyRead, this, &RSSListing::consumeData);
connect(currentReply, &QNetworkReply::errorOccurred, this, &RSSListing::error);
}
xml.setDevice(currentReply); // Equivalent to clear() if currentReply is null.
}
//! [get]
// TODO: this is a candidate for showing how to use coroutines, once available.
//! [parse]
void RSSListing::parseXml()
{
while (!xml.atEnd()) {
xml.readNext();
if (xml.isStartElement()) {
if (xml.name() == u"item") {
linkString = xml.attributes().value("rss:about").toString();
titleString.clear();
}
currentTag = xml.name().toString();
} else if (xml.isEndElement()) {
if (xml.name() == u"item") {
QTreeWidgetItem *item = new QTreeWidgetItem;
item->setText(0, titleString);
item->setText(1, linkString);
treeWidget->addTopLevelItem(item);
}
} else if (xml.isCharacters() && !xml.isWhitespace()) {
if (currentTag == "title")
titleString += xml.text();
else if (currentTag == "link")
linkString += xml.text();
}
}
if (xml.error() && xml.error() != QXmlStreamReader::PrematureEndOfDocumentError)
qWarning() << "XML ERROR:" << xml.lineNumber() << ": " << xml.errorString();
}
//! [parse]
|