Une application minimaliste de liste RSS
Une démonstration de la manière de récupérer et d'afficher une ressource réseau.
Cet exemple montre comment récupérer une ressource demandée par l'utilisateur et afficher les données contenues dans la réponse, à l'aide d'une application de liste RSS. (RDF Site Summary, ou Really Simple Syndication, est un format standard permettant de communiquer les mises à jour des sites web. Voir https://www.rssboard.org/rss-specification pour plus de détails.) L'interface utilisateur présentée dans l'illustration est simple, car cet exemple se concentre sur l'utilisation du réseau, mais il va de soi qu'une interface plus sophistiquée serait souhaitable pour un lecteur RSS digne de ce nom.
L’exemple montre également comment effectuer une analyse asynchrone des données au fur et à mesure de leur réception, en conservant l’état dans des variables membres afin qu’un analyseur incrémental puisse traiter des blocs de données à mesure qu’ils arrivent sur le réseau. Les éléments constitutifs du contenu analysé peuvent commencer dans un bloc de données mais ne pas être complétés avant un bloc ultérieur, ce qui oblige l’analyseur à conserver l’état entre les appels.

Le programme principal est assez minimaliste. Il se contente d’instancier un objet ` QApplication ` et le widget ` RSSListing `, d’afficher ce dernier, puis de céder le contrôle au premier. À titre d’illustration, il attribue au widget l’URL du blog Qt comme valeur par défaut pour la ressource à surveiller.
int main(int argc, char **argv)
{
QApplication app(argc, argv);
RSSListing rsslisting(u"https://www.qt.io/blog/rss.xml"_s);
rsslisting.show();
return app.exec();
}La classe RSSListing
class RSSListing : public QWidget
{
Q_OBJECT
public:
explicit RSSListing(const QString &url = QString(), QWidget *widget = nullptr);
public slots:
void fetch();
void finished(QNetworkReply *reply);
void consumeData();
void error(QNetworkReply::NetworkError);
private:
void parseXml();
void get(const QUrl &url);
// Parser state:
QXmlStreamReader xml;
QString currentTag;
QString linkString;
QString titleString;
// Network state:
QNetworkAccessManager manager;
QNetworkReply *currentReply;
// UI elements:
QLineEdit *lineEdit;
QTreeWidget *treeWidget;
QPushButton *fetchButton;
};Le widget lui-même offre une interface utilisateur simple permettant de spécifier l'URL à récupérer et, une fois les mises à jour disponibles affichées, de contrôler le téléchargement des éléments mis à jour. Une QLineEdit permet de saisir l'URL, et une QTreeWidget affiche les résultats une fois ceux-ci récupérés.
Le widget télécharge et analyse le flux RSS (une forme de XML) de manière asynchrone, en transmettant les données à un lecteur XML au fur et à mesure de leur arrivée. Cela permet la lecture de sources de données très volumineuses. Les données étant transmises en continu depuis le réseau via le lecteur XML, il n’est pas nécessaire de conserver l’intégralité du texte XML en mémoire. Dans un autre contexte, une approche similaire peut permettre à l’utilisateur d’interrompre ce chargement incrémental.
Construction
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);
}Le constructeur configure les différents composants du widget et relie leurs divers signaux aux slots qui serviront à les gérer.
L'interface utilisateur se compose d'un champ de saisie, d'un bouton et d'un widget de liste. Le champ de saisie sert à saisir l'URL à récupérer ; le bouton lance le processus de récupération des mises à jour. Le champ de saisie est vide par défaut, mais l'appelant du constructeur peut redéfinir cette valeur, comme l'a fait notre exemple « main() ». Dans tous les cas, l’utilisateur peut remplacer l’URL par défaut par celle d’un autre flux RSS.
La vue de liste affiche les éléments mis à jour signalés dans le flux RSS. Un double-clic sur l’un d’entre eux envoie son URL au navigateur de l’utilisateur ou à un autre agent utilisateur à l’aide de la méthode ` QDesktopServices::openUrl()`.
Les 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);
}Tous les slots restent simples grâce à la délégation des tâches complexes à des méthodes privées.
Lorsque l’utilisateur a terminé de saisir une URL, soit en cliquant sur le bouton « Fetch », soit en appuyant sur la touche Entrée dans le champ de saisie, le slot fetch() désactive le bouton « Fetch » et empêche toute modification ultérieure du champ de saisie. Il efface l’affichage des mises à jour disponibles et délègue à get() le lancement d’une requête HTTP GET.
Lorsque les données sont reçues, la réponse réseau déclenche son signal « readyRead() », que « get() » relie au slot « consumeData() ». Celui-ci vérifie si la réponse comporte un code d’état de réussite et, si c’est le cas, appelle « parseXml() » pour traiter les données.
Si la réponse réseau génère une erreur, celle-ci est transmise au slot error(), qui signale l’erreur, efface le lecteur de flux XML, puis se déconnecte de la réponse et la supprime.
Une fois la réponse réseau terminée (qu’elle ait abouti ou non), le slot « finished() » rétablit l’interface utilisateur afin qu’elle soit prête à accepter une nouvelle URL à récupérer, en réactivant le champ de saisie et le bouton « Récupérer ».
La méthode 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.
}La méthode privée ` get() ` est utilisée par le slot ` fetch() ` pour lancer une requête HTTP GET. Elle efface d’abord le lecteur de flux XML et, si une réponse est en cours, se déconnecte et la supprime. Si l’URL qui lui a été transmise est valide, elle demande au gestionnaire d’accès réseau d’effectuer une requête GET. Elle connecte ses slots pertinents aux signaux de la réponse obtenue (le cas échéant) et configure son lecteur de flux XML pour lire les données de la réponse — un objet de réponse réseau est également une instance de ` QIODevice`, à partir de laquelle des données peuvent être lues.
La méthode parseXml()
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();
}Lorsque des données sont reçues et donc mises à la disposition du lecteur de flux XML, la fonction parseXml() lit le flux XML, recherche les éléments item et, à l’intérieur de ceux-ci, les éléments title et link. Il utilise l’attribut « rss:about » d’un élément « item » comme URL dans la colonne « Link » de l’arborescence ; à défaut, il utilise le contenu de son élément « link » ; et il utilise le contenu de l’élément « title » dans la colonne « Title » de l’arborescence. À la fermeture de chaque élément ` item `, ses détails sont convertis en une nouvelle ligne dans le widget arborescent, avec le titre et l’URL extraits respectivement dans les colonnes « Titre » et « Lien ».
Les variables qui suivent l’état de l’analyse — linkString, titleString et currentTag — sont des variables membres de la classe RSSListing, même si elles ne sont accessibles qu’à partir de cette méthode, car celle-ci peut être appelée à plusieurs reprises à mesure que de nouvelles données arrivent, et un bloc de données reçu peut marquer le début d’un élément qui ne sera complété qu’à l’arrivée d’un bloc ultérieur. Cela permet à l’analyseur de fonctionner de manière asynchrone au fur et à mesure de l’arrivée des données, au lieu de devoir attendre que toutes les données soient reçues.
Voir également QNetworkReply et QXmlStreamReader.
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.