diff options
author | Olivier De Cannière <olivier.decanniere@qt.io> | 2023-03-17 15:42:47 +0100 |
---|---|---|
committer | Olivier De Cannière <olivier.decanniere@qt.io> | 2023-03-30 18:02:16 +0200 |
commit | 405bd4299819e39397cea0090a9442fd4b6ce911 (patch) | |
tree | c1254e18a8ab47cc6bde048eb52ad0d89c2492c8 /examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project | |
parent | 03ff348b4942ae29dd5bc2bd563998d7ba82ecd7 (diff) | |
download | qtdeclarative-405bd4299819e39397cea0090a9442fd4b6ce911.tar.gz |
Doc: Revamp "Extending QML" examples into a tutorial
The examples in the "Extending QML" series were often redundant with the
information of the "Writing QML Extensions with C++" tutorial, had
outdated code and sometimes had no documentation. The examples that
covered topics not mentioned in the first tutorial were revamped into a
second "advanced" tutorial extending the first one. The others were
removed. The remaining examples were largely based on the same example
code of a birthday party. This code was slightly adapted and separated
into 7 states, each building upon the previous, with the code change
illustrating the associated feature. A tutorial page, in the style of
the first one, was added documenting the different QML features and
the required code changes in the example project.
Links in the documentation from and to the affected pages were update
as best as possible.
Pick-to: 6.5
Fixes: QTBUG-111033
Change-Id: I9d97e8b32b128c1624d67525996fa14d493909d3
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project')
10 files changed, 325 insertions, 0 deletions
diff --git a/examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/CMakeLists.txt b/examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/CMakeLists.txt new file mode 100644 index 0000000000..a8064b77ef --- /dev/null +++ b/examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/CMakeLists.txt @@ -0,0 +1,43 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(baseproject LANGUAGES CXX) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/qml/tutorials/extending-qml-advanced/advanced1-Basic-project") + +find_package(Qt6 REQUIRED COMPONENTS Core Qml) +qt_standard_project_setup() + +qt_policy(SET QTP0001 NEW) + +qt_add_executable(baseproject + birthdayparty.cpp birthdayparty.h + main.cpp + person.cpp person.h +) + +set_target_properties(baseproject PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(baseproject PUBLIC + Qt::Core + Qt::Qml +) + +qt_add_qml_module(baseproject + URI People + QML_FILES Main.qml +) + +install(TARGETS baseproject + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/Main.qml b/examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/Main.qml new file mode 100644 index 0000000000..c917d5b1f1 --- /dev/null +++ b/examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/Main.qml @@ -0,0 +1,16 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import People + +BirthdayParty { + host: Person { + name: "Bob Jones" + shoeSize: 12 + } + guests: [ + Person { name: "Leo Hodges" }, + Person { name: "Jack Smith" }, + Person { name: "Anne Brown" } + ] +} diff --git a/examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/baseproject.pro b/examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/baseproject.pro new file mode 100644 index 0000000000..26c865fbba --- /dev/null +++ b/examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/baseproject.pro @@ -0,0 +1,13 @@ +QT = core qml + +CONFIG += qmltypes +QML_IMPORT_NAME = People +QML_IMPORT_MAJOR_VERSION = 1 + +SOURCES += main.cpp \ + person.cpp \ + birthdayparty.cpp +HEADERS += person.h \ + birthdayparty.h + +RESOURCES += baseproject.qrc diff --git a/examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/baseproject.qrc b/examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/baseproject.qrc new file mode 100644 index 0000000000..b1eeb489e2 --- /dev/null +++ b/examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/baseproject.qrc @@ -0,0 +1,6 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/qt/qml/People/"> + <file>Main.qml</file> + <file alias="qmldir">qmldir.in</file> +</qresource> +</RCC> diff --git a/examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/birthdayparty.cpp b/examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/birthdayparty.cpp new file mode 100644 index 0000000000..ad38f284e7 --- /dev/null +++ b/examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/birthdayparty.cpp @@ -0,0 +1,99 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "birthdayparty.h" + +Person *BirthdayParty::host() const +{ + return m_host; +} + +void BirthdayParty::setHost(Person *host) +{ + if (m_host != host) { + m_host = host; + emit hostChanged(); + } +} + +QQmlListProperty<Person> BirthdayParty::guests() +{ + return { this, + this, + &BirthdayParty::appendGuest, + &BirthdayParty::guestCount, + &BirthdayParty::guest, + &BirthdayParty::clearGuests, + &BirthdayParty::replaceGuest, + &BirthdayParty::removeLastGuest }; +} + +void BirthdayParty::appendGuest(Person *guest) +{ + m_guests.append(guest); + emit guestsChanged(); +} + +qsizetype BirthdayParty::guestCount() const +{ + return m_guests.count(); +} + +Person *BirthdayParty::guest(qsizetype index) const +{ + return m_guests.at(index); +} + +void BirthdayParty::clearGuests() +{ + if (!m_guests.empty()) { + m_guests.clear(); + emit guestsChanged(); + } +} + +void BirthdayParty::replaceGuest(qsizetype index, Person *guest) +{ + if (m_guests.size() > index) { + m_guests[index] = guest; + emit guestsChanged(); + } +} + +void BirthdayParty::removeLastGuest() +{ + if (!m_guests.empty()) { + m_guests.removeLast(); + emit guestsChanged(); + } +} + +void BirthdayParty::appendGuest(QQmlListProperty<Person> *list, Person *guest) +{ + static_cast<BirthdayParty *>(list->data)->appendGuest(guest); +} + +void BirthdayParty::clearGuests(QQmlListProperty<Person> *list) +{ + static_cast<BirthdayParty *>(list->data)->clearGuests(); +} + +void BirthdayParty::replaceGuest(QQmlListProperty<Person> *list, qsizetype index, Person *guest) +{ + static_cast<BirthdayParty *>(list->data)->replaceGuest(index, guest); +} + +void BirthdayParty::removeLastGuest(QQmlListProperty<Person> *list) +{ + static_cast<BirthdayParty *>(list->data)->removeLastGuest(); +} + +Person *BirthdayParty::guest(QQmlListProperty<Person> *list, qsizetype index) +{ + return static_cast<BirthdayParty *>(list->data)->guest(index); +} + +qsizetype BirthdayParty::guestCount(QQmlListProperty<Person> *list) +{ + return static_cast<BirthdayParty *>(list->data)->guestCount(); +} diff --git a/examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/birthdayparty.h b/examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/birthdayparty.h new file mode 100644 index 0000000000..1a28ef2632 --- /dev/null +++ b/examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/birthdayparty.h @@ -0,0 +1,48 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef BIRTHDAYPARTY_H +#define BIRTHDAYPARTY_H + +#include "person.h" + +#include <QObject> +#include <QQmlListProperty> + +class BirthdayParty : public QObject +{ + Q_OBJECT + Q_PROPERTY(Person *host READ host WRITE setHost NOTIFY hostChanged FINAL) + Q_PROPERTY(QQmlListProperty<Person> guests READ guests NOTIFY guestsChanged FINAL) + QML_ELEMENT +public: + using QObject::QObject; + + Person *host() const; + void setHost(Person *); + + QQmlListProperty<Person> guests(); + void appendGuest(Person *); + qsizetype guestCount() const; + Person *guest(qsizetype) const; + void clearGuests(); + void replaceGuest(qsizetype, Person *); + void removeLastGuest(); + +signals: + void hostChanged(); + void guestsChanged(); + +private: + static void appendGuest(QQmlListProperty<Person> *, Person *); + static qsizetype guestCount(QQmlListProperty<Person> *); + static Person *guest(QQmlListProperty<Person> *, qsizetype); + static void clearGuests(QQmlListProperty<Person> *); + static void replaceGuest(QQmlListProperty<Person> *, qsizetype, Person *); + static void removeLastGuest(QQmlListProperty<Person> *); + + Person *m_host = nullptr; + QList<Person *> m_guests; +}; + +#endif // BIRTHDAYPARTY_H diff --git a/examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/main.cpp b/examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/main.cpp new file mode 100644 index 0000000000..eac94016d2 --- /dev/null +++ b/examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/main.cpp @@ -0,0 +1,32 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "birthdayparty.h" +#include "person.h" + +#include <QCoreApplication> +#include <QDebug> +#include <QQmlComponent> +#include <QQmlEngine> + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + + QQmlEngine engine; + QQmlComponent component(&engine); + component.loadFromModule("People", "Main"); + std::unique_ptr<BirthdayParty> party{ qobject_cast<BirthdayParty *>(component.create()) }; + + if (party && party->host()) { + qInfo() << party->host()->name() + << "is having a birthday!\n" + "They are inviting:"; + for (qsizetype ii = 0; ii < party->guestCount(); ++ii) + qInfo() << " " << party->guest(ii)->name(); + return EXIT_SUCCESS; + } + + qWarning() << component.errors(); + return EXIT_FAILURE; +} diff --git a/examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/person.cpp b/examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/person.cpp new file mode 100644 index 0000000000..f8f4b1d2f4 --- /dev/null +++ b/examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/person.cpp @@ -0,0 +1,30 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "person.h" + +QString Person::name() const +{ + return m_name; +} + +void Person::setName(const QString &name) +{ + if (m_name != name) { + m_name = name; + emit nameChanged(); + } +} + +int Person::shoeSize() const +{ + return m_shoeSize; +} + +void Person::setShoeSize(int shoeSize) +{ + if (m_shoeSize != shoeSize) { + m_shoeSize = shoeSize; + emit shoeSizeChanged(); + } +} diff --git a/examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/person.h b/examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/person.h new file mode 100644 index 0000000000..ded272626a --- /dev/null +++ b/examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/person.h @@ -0,0 +1,34 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef PERSON_H +#define PERSON_H + +#include <QtQml/qqml.h> +#include <QObject> + +class Person : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged FINAL) + Q_PROPERTY(int shoeSize READ shoeSize WRITE setShoeSize NOTIFY shoeSizeChanged FINAL) + QML_ELEMENT +public: + using QObject::QObject; + + QString name() const; + void setName(const QString &); + + int shoeSize() const; + void setShoeSize(int); + +signals: + void nameChanged(); + void shoeSizeChanged(); + +private: + QString m_name; + int m_shoeSize = 0; +}; + +#endif // PERSON_H diff --git a/examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/qmldir.in b/examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/qmldir.in new file mode 100644 index 0000000000..70cde3c958 --- /dev/null +++ b/examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/qmldir.in @@ -0,0 +1,4 @@ +module People +typeinfo birthdayparty.qmltypes +prefer :/qt/qml/People/ +Main 254.0 Main.qml |