6.5.3 clean

This commit is contained in:
kleuter
2023-11-01 18:02:52 +01:00
parent bbe896803b
commit 7018d9e6c8
2170 changed files with 57471 additions and 43550 deletions

View File

@ -4,7 +4,7 @@
if(NOT TARGET Qt6::Network)
return()
endif()
if(NOT INTEGRITY)
if(NOT INTEGRITY AND NOT ANDROID)
qt_internal_add_example(dnslookup)
endif()
if(TARGET Qt6::Widgets)
@ -18,6 +18,7 @@ if(TARGET Qt6::Widgets)
qt_internal_add_example(multicastsender)
qt_internal_add_example(fortuneclient)
qt_internal_add_example(fortuneserver)
qt_internal_add_example(rsslisting)
endif()
if(QT_FEATURE_processenvironment AND TARGET Qt6::Widgets)
qt_internal_add_example(network-chat)

View File

@ -4,6 +4,10 @@
cmake_minimum_required(VERSION 3.16)
project(dnslookup LANGUAGES CXX)
if (ANDROID)
message(FATAL_ERROR "This project cannot be built on Android.")
endif()
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()

View File

@ -79,7 +79,7 @@ CommandLineParseResult parseCommandLine(QCommandLineParser &parser, DnsQuery *qu
if (query->nameServer.isNull()
|| query->nameServer.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol) {
return { Status::Error,
u"Bad nameserver address: %1"_qs.arg(nameserver) };
u"Bad nameserver address: %1"_s.arg(nameserver) };
}
}
@ -88,14 +88,14 @@ CommandLineParseResult parseCommandLine(QCommandLineParser &parser, DnsQuery *qu
if (std::optional<QDnsLookup::Type> type = typeFromParameter(typeParameter))
query->type = *type;
else
return { Status::Error, u"Bad record type: %1"_qs.arg(typeParameter) };
return { Status::Error, u"Bad record type: %1"_s.arg(typeParameter) };
}
const QStringList positionalArguments = parser.positionalArguments();
if (positionalArguments.isEmpty())
return { Status::Error, u"Argument 'name' missing."_qs };
return { Status::Error, u"Argument 'name' missing."_s };
if (positionalArguments.size() > 1)
return { Status::Error, u"Several 'name' arguments specified."_qs };
return { Status::Error, u"Several 'name' arguments specified."_s };
query->name = positionalArguments.first();
return { Status::Ok };
@ -202,7 +202,7 @@ int main(int argc, char *argv[])
case Status::Ok:
break;
case Status::Error:
std::fputs(qPrintable(parseResult.errorString.value_or(u"Unknown error occurred"_qs)),
std::fputs(qPrintable(parseResult.errorString.value_or(u"Unknown error occurred"_s)),
stderr);
std::fputs("\n\n", stderr);
std::fputs(qPrintable(parser.helpText()), stderr);

View File

@ -4,6 +4,7 @@
/*!
\example secureudpclient
\title DTLS client
\examplecategory {Networking}
\ingroup examples-network
\brief This example demonstrates how to implement client-side DTLS connections.

View File

@ -4,6 +4,7 @@
/*!
\example secureudpserver
\title DTLS server
\examplecategory {Networking}
\ingroup examples-network
\brief This examples demonstrates how to implement a simple DTLS server.

View File

@ -4,6 +4,7 @@
/*!
\example torrent
\title Torrent Example
\examplecategory {Networking}
\ingroup examples-network
\brief Demonstrates complex TCP/IP operations.

View File

@ -8,18 +8,16 @@ qtHaveModule(widgets) {
blockingfortuneclient \
broadcastreceiver \
broadcastsender \
fortuneclient \
fortuneserver \
http \
threadedfortuneserver \
torrent \
multicastreceiver \
multicastsender
multicastsender \
rsslisting \
threadedfortuneserver \
torrent
qtConfig(processenvironment): SUBDIRS += network-chat
SUBDIRS += \
fortuneclient \
fortuneserver
qtConfig(ssl): SUBDIRS += securesocketclient
qtConfig(dtls): SUBDIRS += secureudpserver secureudpclient
qtConfig(sctp): SUBDIRS += multistreamserver multistreamclient

View File

@ -0,0 +1,38 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(rsslisting LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/network/rsslisting")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Network Widgets)
qt_standard_project_setup()
qt_add_executable(rsslisting
main.cpp
rsslisting.cpp rsslisting.h
)
set_target_properties(rsslisting PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(rsslisting PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Network
Qt6::Widgets
)
install(TARGETS rsslisting
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -0,0 +1,129 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\example rsslisting
\examplecategory {Networking}
\meta tag {serialization}
\title A minimal RSS listing application
\brief A demonstration of how to fetch and display a network resource.
This example shows how to fetch a resource the user has requested and
display data contained in the response, illustrated by an RSS listing
application. (RDF Site Summary, or Really Simple Syndication, is a standard
format for communicating updates to web sites. See
https://www.rssboard.org/rss-specification for details.) The user inferface
in the illustration is simple, as the focus of this example is on how to use
networking, but naturally a more sophisticated interface would be wanted for
a serious RSS reader.
The example also illustrates how to do asynchronous parsing of data as it is
received, preserving state in member variables so that an incremental parser
can consume chunks of data as they arrive over the network. Constituents of
the parsed content may start in one chunk of data but not be completed until
a later chunk, requiring the parser to retain state between calls.
\image rsslisting.png
The main program is fairly minimal. It simply instantiates a \l QApplication
and the \c RSSListing widget, shows the latter and hands over control to the
former. For the sake of illustration, it gives the widget the Qt blog's URL
as default value for the resource to check.
\snippet rsslisting/main.cpp 0
\section1 The RSSListing class
\snippet rsslisting/rsslisting.h 0
The widget itself provides a simple user interface for specifying the URL to
fetch and, once available updates are displayed, controlling the downloading
of updated items. A \l QLineEdit provides for input of the URL, and a
\l QTreeWidget for display of the results once fetched.
The widget downloads and parses the RSS (a form of XML) asynchronously,
feeding the data to an XML reader as it arrives. This supports reading of
very large data sources. Because the data is streamed from the network
through the XML reader, there is no need to retain the full text of the XML
in memory. In other context, a similar approach can allow the user to
interrupt such incremental loading.
\section2 Construction
\snippet rsslisting/rsslisting.cpp setup
The constructor sets up the assorted components of the widget and connects
their various signals to the slots it shall use to handle them.
The user interface consists of a line edit, a push button, and a list view
widget. The line edit is used for entering the URL to fetch; the push button
starts the process of fetching updates. The line edit is empty by default,
but the constructor's caller can override that, as our \c main() has done.
In any case, the user can replace the default with the URL of another RSS
feed.
The list view shows the updated items reported in the RSS feed.
Double-clicking on one of these sends its URL to the user's browser or other
user agent using \l QDesktopServices::openUrl().
\section2 The slots
\snippet rsslisting/rsslisting.cpp slots
All slots are kept simple by delegating any hard work to private methods.
When the user completes input of a URL, either by clicking the "Fetch"
button or by pressing the return key in the line edit, the \c fetch() slot
disables the "Fetch" button and disables further editing of the line edit.
It clears the display of available updates and delegates to \c get() the
initiating of an HTTP GET request.
When data is received, the network reply triggers its \l {QNetworkReply::}
{readyRead()} signal, which \c get() connects to the \c consumeData()
slot. This checks the response got a successful status code and, if it did,
calls \c parseXml() to consume the data.
If the network reply gets an error, this is delivered to the \c error()
slot, which reports the error, clears the XML stream reader then disconnects
from the reply and deletes it.
On completion (whether successful or otherwise) of a network reply, the \c
finished() slot restores the UI to be ready to accept a new URL to fetch by
re-enabling the line edit and "Fetch" button.
\section2 The get() method
\snippet rsslisting/rsslisting.cpp get
The private \c get() method is used by the \c fetch() slot to initiate an
HTTP GET request. It first clears the XML stream reader and, if a reply is
currently active, disconnects and deletes it. If the URL it has been passed
is valid, it asks the network access manager to GET it. It connects its
relevant slots to signals of the resulting reply (if any) and sets up its
XML stream reader to read data from the reply - a network reply object is
also a \c QIODevice, from which data can be read.
\section2 The parseXml() method
\snippet rsslisting/rsslisting.cpp parse
When data is received, and thus made available to the XML stream reader, \c
parseXml() reads from the XML stream, checking for \c item elements and,
within them, \c title and \c link elements. It will use the \c{rss:about}
attribute of an \c item as URL in the Link column of the tree-view, failing
that the content of its \c link element; and it uses the content of the \c
title element in the Title column of the tree-view. As each \c item element
closes, its details are turned into a new row in the tree widget, with the
extracted title and URL in the Title and Link columns.
The variables that keep track of the parsing state - \c linkString, \c
titleString and \c currentTag - are member variables of the \c RSSListing
class, even though they are only accessed from this method, because this
method may be called repeatedly, as new data arrives, and one chunk of
received data may start an element that isn't completed until a later chunk
arrives. This enables the parser to operate asynchronously as the data
arrives, instead of having to wait until all the data has arrived.
\sa QNetworkReply, QXmlStreamReader
*/

View File

@ -0,0 +1,16 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "rsslisting.h"
#include <QtWidgets>
using namespace Qt::StringLiterals;
//! [0]
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();
}
//! [0]

View File

@ -0,0 +1,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]

View File

@ -0,0 +1,54 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef RSSLISTING_H
#define RSSLISTING_H
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QWidget>
#include <QXmlStreamReader>
QT_BEGIN_NAMESPACE
class QLineEdit;
class QPushButton;
class QTreeWidget;
class QTreeWidgetItem;
class QUrl;
QT_END_NAMESPACE
//! [0]
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;
};
//! [0]
#endif

View File

@ -0,0 +1,8 @@
HEADERS += rsslisting.h
SOURCES += main.cpp rsslisting.cpp
QT += network widgets
requires(qtConfig(treewidget))
# install
target.path = $$[QT_INSTALL_EXAMPLES]/network/rsslisting
INSTALLS += target

View File

@ -11,8 +11,6 @@ QT_REQUIRE_CONFIG(ssl);
int main(int argc, char **argv)
{
Q_INIT_RESOURCE(securesocketclient);
QApplication app(argc, argv);
if (!QSslSocket::supportsSsl()) {

View File

@ -9,8 +9,6 @@ int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Q_INIT_RESOURCE(icons);
MainWindow window;
window.show();