aboutsummaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorIvan Solovev <ivan.solovev@qt.io>2023-06-15 15:49:29 +0200
committerIvan Solovev <ivan.solovev@qt.io>2023-06-21 19:24:42 +0200
commit6036fd0982122dce9f471877417bab6a7c8833dc (patch)
treea4d58deb708a81f87e0106cb7cf03c8eb0fb3f7b /examples
parentc291841ff1886c081503112cb26d462f820abced (diff)
CoAP Multicast Discovery example: update the documentation
* Do not use the "Example" word in the title * Set the proper example category * Add a note about running the example from QtCreator * Add a note on how to terminate docker containers after usage * Update the screenshot to reflect the changes in the UI, switch to webp format * Update the documentation about exposing C++ types to QML. Describe the modern way of doing it. * Introduce a section about changes to build files. Task-number: QTBUG-113858 Pick-to: 6.6 6.5 Change-Id: I1ff3cdc4be673affa791a28d5f4641351060b13b Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'examples')
-rw-r--r--examples/coap/doc/images/quickmulticastclient.pngbin17289 -> 0 bytes
-rw-r--r--examples/coap/doc/images/quickmulticastclient.webpbin0 -> 16396 bytes
-rw-r--r--examples/coap/doc/quickmulticastclient.qdoc166
-rw-r--r--examples/coap/quickmulticastclient/Main.qml6
-rw-r--r--examples/coap/quickmulticastclient/qmlcoapmulticastclient.cpp10
-rw-r--r--examples/coap/quickmulticastclient/qmlcoapmulticastclient.h6
6 files changed, 122 insertions, 66 deletions
diff --git a/examples/coap/doc/images/quickmulticastclient.png b/examples/coap/doc/images/quickmulticastclient.png
deleted file mode 100644
index 3339db1..0000000
--- a/examples/coap/doc/images/quickmulticastclient.png
+++ /dev/null
Binary files differ
diff --git a/examples/coap/doc/images/quickmulticastclient.webp b/examples/coap/doc/images/quickmulticastclient.webp
new file mode 100644
index 0000000..f7eb6b4
--- /dev/null
+++ b/examples/coap/doc/images/quickmulticastclient.webp
Binary files differ
diff --git a/examples/coap/doc/quickmulticastclient.qdoc b/examples/coap/doc/quickmulticastclient.qdoc
index e1382b6..dbf8063 100644
--- a/examples/coap/doc/quickmulticastclient.qdoc
+++ b/examples/coap/doc/quickmulticastclient.qdoc
@@ -1,23 +1,26 @@
-// Copyright (C) 2019 The Qt Company Ltd.
+// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\example quickmulticastclient
- \title Quick CoAP Multicast Discovery Example
+ \title Quick CoAP Multicast Discovery
+ \examplecategory {Connectivity}
\ingroup qtcoap-examples
\brief Using the CoAP client for a multicast resource discovery with a Qt Quick
user interface.
- \image quickmulticastclient.png
+ \image quickmulticastclient.webp
- The \e {Quick CoAP Multicast Discovery Example} demonstrates how to register
+ The \e {Quick CoAP Multicast Discovery} example demonstrates how to register
QCoapClient as a QML type and use it in a Qt Quick application for CoAP multicast
resource discovery.
\note Qt CoAP does not provide a QML API in its current version. However, you can
make the C++ classes of the module available to QML as shown in this example.
- \section1 Running the Example
+ \include examples-run.qdocinc
+
+ \section1 Setting Up a CoAP Server
To run the example application, you first need to set up and start at least one CoAP
server supporting multicast resource discovery. You have the following options:
@@ -46,92 +49,123 @@
\note You can run more than one multicast CoAP servers (on the same host or other
hosts in the network) by passing a different \c{--name} to the command above.
- \section1 Creating a Client and Using It with QML
+ To terminate the docker container after usage, first obtain the container's
+ ID by executing the \c {docker ps} command. The output will look like this:
- We create the \c QmlCoapMulticastClient class with the QCoapClient class as a
- base class:
+ \badcode
+ $ docker ps
+ CONTAINER ID IMAGE
+ ccaaeae059f1 sokurazy/coap-multicast-test-server:californium.2.0.x
+ \endcode
- \quotefromfile quickmulticastclient/qmlcoapmulticastclient.h
- \skipto QmlCoapMulticastClient
- \printuntil };
+ After that, use this ID to stop the container:
- In the main.cpp file, we register the \c QmlCoapMulticastClient class as a QML
- type:
+ \badcode
+ docker stop <container_id>
+ \endcode
- \quotefromfile quickmulticastclient/main.cpp
- \skipto qmlRegisterType
- \printline qmlRegisterType
+ \section1 Exposign C++ Classes to QML
- We also register the QtCoap namespace, to be able to use it in QML code:
+ In this example, you need to expose the \l QCoapResource and \l QCoapClient
+ classes, as well as the \l {QtCoap Namespace}{QtCoap} namespace, to QML.
+ To achieve this, create custom wrapper classes and use the special
+ \l {Defining QML Types from C++}{registration macros}.
- \skipto qmlRegisterUncreatableMetaObject
- \printto const QUrl
+ Create the \c QmlCoapResource class as a wrapper around \l QCoapResource.
+ Use the \l Q_PROPERTY macro to make several properties accessible from
+ QML. The class does not need to be directly instantiable from QML, so use
+ the \l QML_ANONYMOUS macro to register it.
- Now in the QML code, we can import and use these types:
+ \snippet quickmulticastclient/qmlcoapmulticastclient.h coap_resource
- \quotefromfile quickmulticastclient/main.qml
- \dots
- \skipto CoapMulticastClient
- \printuntil qtcoap.example.namespace
- \dots
- \skipto CoapMulticastClient
- \printto GridLayout
- \dots
+ After that, create the \c QmlCoapMulticastClient class with the
+ \l QCoapClient class as a base class. Use the \l Q_PROPERTY macro to
+ expose a custom property, and also create several \l Q_INVOKABLE methods.
+ Both the property and the invokable methods can be accessed from QML.
+ Unlike \c QmlCoapResource, you want to be able to create this class from
+ QML, so use the \l QML_NAMED_ELEMENT macro to register the class in QML.
- The \c {QCoapClient::error()} signal triggers the \c onError signal handler of
- \c CoapMulticastClient, and the \c {QmlCoapMulticastClient::finished()} signal
- triggers the \c onFinished signal handler, to show the request's status in the UI.
- Note that we are not using the \c {QCoapClient::finished()} signal directly,
- because it takes a \c {QCoapReply} as a parameter (which is not a QML type), and
- we are interested only in the error code.
+ \snippet quickmulticastclient/qmlcoapmulticastclient.h coap_client
- In the \c QmlCoapMulticastClient's constructor, we arrange for the
- \c {QCoapClient::finished()} signal to be forwarded to the
- \c {QmlCoapMulticastClient::finished()} signal:
+ Finally, register the \l {QtCoap Namespace}{QtCoap} namespace, so that you
+ can use the enums provided there:
- \quotefromfile quickmulticastclient/qmlcoapmulticastclient.cpp
- \skipto QmlCoapMulticastClient::QmlCoapMulticastClient
- \printto QmlCoapMulticastClient::discover
+ \snippet quickmulticastclient/qmlcoapmulticastclient.h coap_namespace
- When the \uicontrol Discover button is pressed, we invoke one of the overloaded
- \c {discover()} methods, based on the selected multicast group:
+ \section1 Adjusting Build Files
- \quotefromfile quickmulticastclient/main.qml
- \skipto Button {
- \dots
- \printto ListModel {
+ To make the custom types available from QML, update the build system files
+ accordingly.
+
+ \section2 CMake Build
+
+ For a CMake-based build, add the following to the \c {CMakeLists.txt}:
+
+ \quotefromfile quickmulticastclient/CMakeLists.txt
+ \skipto qt_add_qml_module
+ \printuntil )
+
+ \section2 qmake Build
+
+ For a qmake build, modify the \c {quickmulticastclient.pro} file in the
+ following way:
+
+ \quotefromfile quickmulticastclient/quickmulticastclient.pro
+ \skipto CONFIG
+ \printuntil QML_IMPORT_MAJOR_VERSION
\dots
+ \skipto qml_resources.files
+ \printuntil RESOURCES
+
+ \section1 Using New QML Types
+
+ Now, when the C++ classes are properly exposed to QML, you can use the new
+ types:
+
+ \snippet quickmulticastclient/Main.qml client
+
+ The \c {QmlCoapMulticastClient::finished()} signal triggers the
+ \c onFinished signal handler, to show the request's status in the UI.
+ Note that the example does not use \l {QCoapClient}'s signals directly,
+ because both \l {QCoapClient::}{error()} and \l {QCoapClient::}{finished()}
+ signals take a \l {QCoapReply} as a parameter (which is not exposed to QML),
+ and the example only requires the error code.
+
+ The \c {QmlCoapMulticastClient}'s constructor forwards the
+ \l {QCoapClient}'s signals to \c {QmlCoapMulticastClient::finished()}
+ signal:
+
+ \snippet quickmulticastclient/qmlcoapmulticastclient.cpp ctor
+
+ When the \uicontrol Discover button is pressed, one of the overloaded
+ \c {discover()} methods is invoked, based on the selected multicast group:
+
+ \snippet quickmulticastclient/Main.qml discover_button
This overload is called when a custom multicast group or a host address is selected:
- \quotefromfile quickmulticastclient/qmlcoapmulticastclient.cpp
- \skipto QmlCoapMulticastClient::discover
- \printto QmlCoapMulticastClient::discover(QtCoap::MulticastGroup
+ \snippet quickmulticastclient/qmlcoapmulticastclient.cpp discover_custom
And this overload is called when one of the suggested multicast groups is selected
in the UI:
- \printto void QmlCoapMulticastClient::onDiscovered
+ \snippet quickmulticastclient/qmlcoapmulticastclient.cpp discover_group
- The \c {QCoapClient::discovered()} signal delivers a list of \c {QCoapResources},
- which is not a QML type. To make the resources available in QML, we forward each
- resource in the list to the \c {QmlCoapMulticastClient::discovered()} signal, which
- takes a \c QmlCoapResource instead:
+ The \l {QCoapResourceDiscoveryReply::discovered()} signal delivers a list
+ of \l {QCoapResource}s, which is not a QML type. To make the resources
+ available in QML, forward each resource in the list to the
+ \c {QmlCoapMulticastClient::discovered()} signal, which takes a
+ \c QmlCoapResource instead:
- \printuntil
+ \snippet quickmulticastclient/qmlcoapmulticastclient.cpp on_discovered
- \c QmlCoapResource is a wrapper around QCoapResource, to make some of its
- properties available in QML:
+ The discovered resources are added to the \c resourceModel of the list view in the UI:
- \quotefromfile quickmulticastclient/qmlcoapmulticastclient.h
- \skipto class QmlCoapResource
- \printuntil };
+ \snippet quickmulticastclient/Main.qml add_resources
- The discovered resources are added to the \c resourceModel of the list view in the UI:
+ While the discovery is in progress, press the \uicontrol {Stop Discovery}
+ button to stop the discovery. Internally it is done by aborting the current
+ request:
- \quotefromfile quickmulticastclient/main.qml
- \skipto addResource
- \dots
- \printto CoapMulticastClient {
- \dots
+ \snippet quickmulticastclient/qmlcoapmulticastclient.cpp stop_discovery
*/
diff --git a/examples/coap/quickmulticastclient/Main.qml b/examples/coap/quickmulticastclient/Main.qml
index 08047b1..5be06f2 100644
--- a/examples/coap/quickmulticastclient/Main.qml
+++ b/examples/coap/quickmulticastclient/Main.qml
@@ -16,12 +16,15 @@ Window {
height: 480
title: qsTr("Qt Quick CoAP Multicast Discovery")
+ //! [add_resources]
function addResource(resource) {
resourceModel.insert(0, {"host" : resource.host,
"path" : resource.path,
"title" : resource.title})
}
+ //! [add_resources]
+ //! [client]
CoapMulticastClient {
id: client
onDiscovered: (resource) => { root.addResource(resource) }
@@ -32,6 +35,7 @@ Window {
: qsTr("Resource discovery failed with error code: %1").arg(error)
}
}
+ //! [client]
GridLayout {
anchors.fill: parent
@@ -121,6 +125,7 @@ Window {
Layout.fillWidth: true
}
+ //! [discover_button]
Button {
id: discoverButton
text: client.isDiscovering ? qsTr("Stop Discovery") : qsTr("Discover")
@@ -146,6 +151,7 @@ Window {
}
}
}
+ //! [discover_button]
Button {
id: clearButton
diff --git a/examples/coap/quickmulticastclient/qmlcoapmulticastclient.cpp b/examples/coap/quickmulticastclient/qmlcoapmulticastclient.cpp
index 5669fb4..9d12c4c 100644
--- a/examples/coap/quickmulticastclient/qmlcoapmulticastclient.cpp
+++ b/examples/coap/quickmulticastclient/qmlcoapmulticastclient.cpp
@@ -8,6 +8,7 @@
Q_LOGGING_CATEGORY(lcCoapClient, "qt.coap.client")
+//! [ctor]
QmlCoapMulticastClient::QmlCoapMulticastClient(QObject *parent)
: QCoapClient(QtCoap::SecurityMode::NoSecurity, parent)
{
@@ -30,7 +31,9 @@ QmlCoapMulticastClient::QmlCoapMulticastClient(QObject *parent)
emit finished(static_cast<int>(err));
});
}
+//! [ctor]
+//! [discover_custom]
void QmlCoapMulticastClient::discover(const QString &host, int port, const QString &discoveryPath)
{
QUrl url;
@@ -46,7 +49,9 @@ void QmlCoapMulticastClient::discover(const QString &host, int port, const QStri
qCWarning(lcCoapClient, "Discovery request failed.");
}
}
+//! [discover_custom]
+//! [discover_group]
void QmlCoapMulticastClient::discover(QtCoap::MulticastGroup group, int port,
const QString &discoveryPath)
{
@@ -59,18 +64,22 @@ void QmlCoapMulticastClient::discover(QtCoap::MulticastGroup group, int port,
qCWarning(lcCoapClient, "Discovery request failed.");
}
}
+//! [discover_group]
+//! [stop_discovery]
void QmlCoapMulticastClient::stopDiscovery()
{
if (m_reply)
m_reply->abortRequest();
}
+//! [stop_discovery]
bool QmlCoapMulticastClient::isDiscovering() const
{
return m_reply && !m_reply->isFinished();
}
+//! [on_discovered]
void QmlCoapMulticastClient::onDiscovered(QCoapResourceDiscoveryReply *reply,
const QList<QCoapResource> &resources)
{
@@ -78,5 +87,6 @@ void QmlCoapMulticastClient::onDiscovered(QCoapResourceDiscoveryReply *reply,
for (const auto &resource : resources)
emit discovered(resource);
}
+//! [on_discovered]
#include "moc_qmlcoapmulticastclient.cpp"
diff --git a/examples/coap/quickmulticastclient/qmlcoapmulticastclient.h b/examples/coap/quickmulticastclient/qmlcoapmulticastclient.h
index 79c33ee..2001d03 100644
--- a/examples/coap/quickmulticastclient/qmlcoapmulticastclient.h
+++ b/examples/coap/quickmulticastclient/qmlcoapmulticastclient.h
@@ -14,6 +14,7 @@ QT_BEGIN_NAMESPACE
class QCoapResourceDiscoveryReply;
QT_END_NAMESPACE
+//! [coap_resource]
class QmlCoapResource : public QCoapResource
{
Q_GADGET
@@ -29,8 +30,10 @@ public:
QString hostStr() const { return host().toString(); }
};
+//! [coap_resource]
Q_DECLARE_METATYPE(QmlCoapResource)
+//! [coap_client]
class QmlCoapMulticastClient : public QCoapClient
{
Q_OBJECT
@@ -60,12 +63,15 @@ public slots:
private:
QCoapResourceDiscoveryReply *m_reply = nullptr;
};
+//! [coap_client]
+//! [coap_namespace]
namespace QCoapForeignNamespace
{
Q_NAMESPACE
QML_FOREIGN_NAMESPACE(QtCoap)
QML_NAMED_ELEMENT(QtCoap)
}
+//! [coap_namespace]
#endif // QMLCOAPMULTICASTCLIENT_H