diff options
166 files changed, 1713 insertions, 142 deletions
diff --git a/dependencies.yaml b/dependencies.yaml index 3e8f3df9f5..2dce6be48a 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,16 +1,16 @@ dependencies: ../qtbase: - ref: 51c7503568174669b48a8f8ddbe49eebb127a128 + ref: ccce91461a39adebde7ec7803b4cc0b97093f77f required: true ../qtimageformats: - ref: 9617a44154fe7b04e70996dc130755b0b05c7813 + ref: fa96798b387a6adbe4838eec05165645ccd8853d required: false ../qtlanguageserver: - ref: 4e403965939ec6f67e46e071dbf8e8e63fb54c8e + ref: b5d17027959532cbb0a78a9ebb1af1c566d451d9 required: false ../qtshadertools: - ref: 0656117b95a35ec98ccce4ba9dbcf9b1f8a81698 + ref: 0c841bbdbfd00edfecfd5c3d8294ee3b2aef9f83 required: false ../qtsvg: - ref: 44a3e8f5e3a26b2d303874affda50d9b2cc4db42 + ref: 45d219f1f83b3a832d4f2829821144ea74a852f7 required: false diff --git a/examples/quick/models/CMakeLists.txt b/examples/quick/models/CMakeLists.txt index ca1ffc26a1..c874f21180 100644 --- a/examples/quick/models/CMakeLists.txt +++ b/examples/quick/models/CMakeLists.txt @@ -5,3 +5,4 @@ qt_internal_add_example(abstractitemmodel) qt_internal_add_example(objectlistmodel) qt_internal_add_example(stringlistmodel) qt_internal_add_example(threadedfetchmore) +qt_internal_add_example(threadedsonglist) diff --git a/examples/quick/models/models.pro b/examples/quick/models/models.pro index 7e86f14847..7675c4588f 100644 --- a/examples/quick/models/models.pro +++ b/examples/quick/models/models.pro @@ -3,4 +3,5 @@ SUBDIRS = \ abstractitemmodel \ objectlistmodel \ stringlistmodel \ - threadedfetchmore + threadedfetchmore \ + threadedsonglist diff --git a/examples/quick/models/threadedsonglist/CMakeLists.txt b/examples/quick/models/threadedsonglist/CMakeLists.txt new file mode 100644 index 0000000000..1da9d32deb --- /dev/null +++ b/examples/quick/models/threadedsonglist/CMakeLists.txt @@ -0,0 +1,80 @@ +# Copyright (C) 2025 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) + +project(threadedsonglist VERSION 0.1 LANGUAGES CXX) + +find_package(Qt6 REQUIRED COMPONENTS Quick) + +qt_standard_project_setup(REQUIRES 6.8) + +qt_add_executable(appthreadedsonglist WIN32 MACOSX_BUNDLE + main.cpp +) + +qt_add_qml_module(appthreadedsonglist + URI threadedsonglist + QML_FILES + SongListDelegate.qml + ThreadedSongList.qml + SOURCES + datastorage.h + datastorage.cpp + mediaelement.h + mediaelement.cpp + queueworker.h + queueworker.cpp + remotemedia.h + remotemedia.cpp + songdatagenerator.h + songdatagenerator.cpp + threadedlistmodel.h + threadedlistmodel.cpp + RESOURCES + images/album_covers/classical1.jpeg + images/album_covers/classical2.jpeg + images/album_covers/classical3.jpeg + images/album_covers/classical4.jpeg + images/album_covers/classical5.jpeg + images/album_covers/classical6.jpeg + images/album_covers/metal1.jpeg + images/album_covers/metal2.jpeg + images/album_covers/metal3.jpeg + images/album_covers/metal4.jpeg + images/album_covers/metal5.jpeg + images/album_covers/metal6.jpeg + images/album_covers/pop1.jpeg + images/album_covers/pop2.jpeg + images/album_covers/pop3.jpeg + images/album_covers/pop4.jpeg + images/album_covers/pop5.jpeg + images/album_covers/pop6.jpeg + images/album_covers/rock1.jpeg + images/album_covers/rock2.jpeg + images/album_covers/rock3.jpeg + images/album_covers/rock4.jpeg + images/album_covers/rock5.jpeg + images/album_covers/rock6.jpeg + images/device/remote.jpeg +) + +target_link_libraries(appthreadedsonglist + PRIVATE Qt6::Quick +) + +include(GNUInstallDirs) +install(TARGETS appthreadedsonglist + BUNDLE DESTINATION . + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} +) + +qt_generate_deploy_qml_app_script( + TARGET appthreadedsonglist + OUTPUT_SCRIPT deploy_script + MACOS_BUNDLE_POST_BUILD + NO_UNSUPPORTED_PLATFORM_ERROR + DEPLOY_USER_QML_MODULES_ON_UNSUPPORTED_PLATFORM +) +install(SCRIPT ${deploy_script}) diff --git a/examples/quick/models/threadedsonglist/SongListDelegate.qml b/examples/quick/models/threadedsonglist/SongListDelegate.qml new file mode 100644 index 0000000000..ba96d3c3d5 --- /dev/null +++ b/examples/quick/models/threadedsonglist/SongListDelegate.qml @@ -0,0 +1,93 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Controls.Universal + +MouseArea { + id: delegateRoot + signal songSelected(albumName: string, albumArt: string, artistName: string, songTitle: string) + + implicitHeight: 60 + enabled: model.albumArt !== "" + onClicked: songSelected(model.album, model.albumArt, model.artist, model.song) + BusyIndicator { + id: loadingIndicator + anchors.verticalCenter: parent.verticalCenter + anchors.right: loadingText.left + anchors.rightMargin: 5 + height: loadingText.implicitHeight + width: height + running: model.loadingText === "" && model.isLoadingElement + } + Text { + id: loadingText + anchors.centerIn: parent + font.pixelSize: delegateRoot.implicitHeight / 4 + text: model.loadingText === "" ? qsTr("Loading...") : model.loadingText + visible: model.isLoadingElement + } + Item { + anchors.fill: parent + visible: !loadingIndicator.running + Image { + id: albumArtImage + anchors.left: parent.left + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.leftMargin: 1 + anchors.topMargin: 1 + anchors.bottomMargin: 1 + source: model.albumArt + width: height + fillMode: Image.PreserveAspectCrop + } + Text { + id: artistName + anchors.left: albumArtImage.right + anchors.right: parent.right + anchors.top: parent.top + anchors.topMargin: 1 + anchors.leftMargin: 1 + anchors.rightMargin: 1 + font.pixelSize: delegateRoot.implicitHeight / 5 + text: model.artist + } + Text { + id: songName + anchors.left: albumArtImage.right + anchors.right: parent.right + anchors.top: artistName.bottom + anchors.topMargin: 1 + anchors.leftMargin: 1 + anchors.rightMargin: 1 + font.pixelSize: delegateRoot.implicitHeight / 4 + text: model.song + } + Text { + id: albumName + anchors.left: albumArtImage.right + anchors.right: parent.right + anchors.top: songName.bottom + anchors.topMargin: 1 + anchors.leftMargin: 1 + anchors.rightMargin: 1 + font.pixelSize: delegateRoot.implicitHeight / 5 + text: model.album + } + } + Rectangle { + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + implicitHeight: 1 + color: "lightgray" + } + Text { + anchors.right: parent.right + anchors.rightMargin: delegateRoot.implicitHeight / 2 + anchors.verticalCenter: parent.verticalCenter + font.pixelSize: delegateRoot.implicitHeight / 4 + text: "#"+(index+1) + } +} diff --git a/examples/quick/models/threadedsonglist/ThreadedSongList.qml b/examples/quick/models/threadedsonglist/ThreadedSongList.qml new file mode 100644 index 0000000000..9563b64639 --- /dev/null +++ b/examples/quick/models/threadedsonglist/ThreadedSongList.qml @@ -0,0 +1,151 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +pragma ComponentBehavior: Bound + +//! [Fixed Controls style] +import QtQuick +import QtQuick.Controls.Universal +//! [Fixed Controls style] + +Window { + id: mainWindow + minimumWidth: 800 + minimumHeight: 480 + width: minimumWidth + height: minimumHeight + visible: true + title: qsTr("Threaded Song List") + + property string currentAlbumName: "" + property string currentAlbumArt: "" + property string currentArtistName: "" + property string currentSongTitle: "" + ListView { + id: songListView + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.left: parent.left + width: 2 * parent.width / 5 + model: ThreadedListModel{} + readonly property int delegateHeight: (songListView.height / 8) - songListView.spacing + cacheBuffer: delegateHeight * 2 + delegate: SongListDelegate{ + required property int index + required property var model + implicitHeight: songListView.delegateHeight + width: songListView.width + onSongSelected: (albumName, albumArt, artistName, songTitle) => { + mainWindow.currentAlbumName = albumName + mainWindow.currentAlbumArt = albumArt + mainWindow.currentArtistName = artistName + mainWindow.currentSongTitle = songTitle + } + } + ScrollBar.vertical: ScrollBar { + policy: ScrollBar.AlwaysOn + implicitWidth: songListView.height / 20 + } + BusyIndicator { + anchors.centerIn: parent + width: parent.width / 3 + height: width + running: songListView.count === 0 + } + } + Rectangle { + color: "white" + anchors.left: songListView.right + anchors.right: parent.right + anchors.top: parent.top + anchors.bottom: parent.bottom + Label { + id: statusLabel + anchors.top: parent.top + anchors.right: parent.right + anchors.left: parent.left + anchors.leftMargin: 10 + anchors.topMargin: 5 + textFormat: Text.RichText + text: qsTr("🔗 Connected, %1 songs available").arg(songListView.count) + font.pixelSize: Math.min(parent.height, parent.width) / 32 + horizontalAlignment: Text.AlignHCenter + } + Item { + id: deviceImage + anchors.right: parent.right + anchors.top: statusLabel.bottom + anchors.left: parent.left + anchors.leftMargin: 10 + height: (3 * parent.height / 4) - statusLabel.height + Image { + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + width: Math.min(parent.width, parent.height) + height: width + source: "qrc:/qt/qml/threadedsonglist/images/device/remote.jpeg" + fillMode: Image.PreserveAspectFit + } + } + Rectangle { + visible: mainWindow.currentSongTitle !== "" + color: "black" + anchors.top: deviceImage.bottom + anchors.right: parent.right + anchors.left: parent.left + anchors.bottom: parent.bottom + Rectangle { + id: nowPlayingBox + anchors.top: parent.top + anchors.right: parent.right + anchors.left: parent.left + height: nowPlayingTitle.implicitHeight + color: "#555555" + Label { + id: nowPlayingTitle + anchors.centerIn: parent + color: "white" + text: qsTr("Now playing:") + font.pixelSize: 16 + horizontalAlignment: Text.AlignHCenter + } + } + Image { + id: albumArtImage + anchors.top: nowPlayingBox.bottom + anchors.left: parent.left + anchors.bottom: parent.bottom + anchors.topMargin: 5 + source: mainWindow.currentAlbumArt + fillMode: Image.PreserveAspectFit + } + Column { + anchors.top: nowPlayingBox.bottom + anchors.right: parent.right + anchors.left: albumArtImage.right + anchors.bottom: parent.bottom + anchors.topMargin: 5 + anchors.leftMargin: 5 + spacing: 5 + Label { + color: "white" + text: "♫: " + mainWindow.currentSongTitle + textFormat: Text.RichText + font.pixelSize: (parent.height - 20) / 4 + } + Label { + color: "white" + text: "👤: " + mainWindow.currentArtistName + textFormat: Text.RichText + font.pixelSize: (parent.height - 20) / 4 + } + Label { + color: "white" + text: "💿: " + mainWindow.currentAlbumName + textFormat: Text.RichText + font.pixelSize: (parent.height - 20) / 4 + } + } + } + } +} diff --git a/examples/quick/models/threadedsonglist/datastorage.cpp b/examples/quick/models/threadedsonglist/datastorage.cpp new file mode 100644 index 0000000000..c38458960d --- /dev/null +++ b/examples/quick/models/threadedsonglist/datastorage.cpp @@ -0,0 +1,84 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "datastorage.h" +#include "queueworker.h" + +DataStorage::DataStorage() : QObject{ nullptr } +{ + /* Generate a list of IDs to use locally. + * DataStorage will use indexes for accessing the remote data. + */ + m_idList.reserve(RemoteMedia::count()); + for (int id = 1; id <= RemoteMedia::count(); ++id) { + m_idList.append(id); + } + m_worker = new QueueWorker; + connect(&m_workerThread, &QThread::finished, m_worker, &QObject::deleteLater); + m_worker->moveToThread(&m_workerThread); + connect(m_worker, &QueueWorker::dataFetched, this, &DataStorage::dataReceived); + connect(m_worker, &QueueWorker::processing, this, &DataStorage::fetchStarted); + connect(m_worker, &QueueWorker::dropped, this, &DataStorage::fetchAborted); + connect(this, &DataStorage::dataFetchNeeded, m_worker, &QueueWorker::fetchData); + m_workerThread.start(); +} + +DataStorage::~DataStorage() +{ + /* Clean the worker object by stopping it and then ending the thread */ + m_worker->abort(); + m_worker = nullptr; + m_workerThread.quit(); + m_workerThread.wait(); +} + +QList<int> DataStorage::idList() +{ + return m_idList; +} + +MediaElement DataStorage::item(int id) const +{ + if (id < 1) + return MediaElement{}; + //! [Send signal if no data] + if (!m_items.contains(id)) { + m_items.insert(id, MediaElement{}); + emit dataFetchNeeded(m_idList.indexOf(id)); + } + return m_items.value(id); + //! [Send signal if no data] +} + +std::optional<int> DataStorage::currentlyFetchedId() const +{ + return m_currentlyFetchedId; +} + +void DataStorage::fetchStarted(int index) +{ + const auto idBeingFetched = m_idList.at(index); + m_currentlyFetchedId = idBeingFetched; + emit dataUpdated(idBeingFetched); +} + +void DataStorage::fetchAborted(int index) +{ + /* The data will never be fetched. Remove the empty item (so storge will send a signal to thread + * if needed). Then send dataUpdated signal. If the item is still visible, view will re-request + * its data and item will be requeued to thread. If item is no longer in visible area, view will + * ignore the dataChanged signal and storage will not receive any calls. + */ + const auto idAborted = m_idList.at(index); + m_items.remove(idAborted); + if (m_currentlyFetchedId == idAborted) + m_currentlyFetchedId = std::nullopt; + emit dataUpdated(idAborted); +} + +void DataStorage::dataReceived(int index, MediaElement element) +{ + const auto idUpdated = m_idList.at(index); + m_items.insert(idUpdated, element); + emit dataUpdated(idUpdated); +} diff --git a/examples/quick/models/threadedsonglist/datastorage.h b/examples/quick/models/threadedsonglist/datastorage.h new file mode 100644 index 0000000000..d8cd4b9f2a --- /dev/null +++ b/examples/quick/models/threadedsonglist/datastorage.h @@ -0,0 +1,49 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef DATASTORAGE_H +#define DATASTORAGE_H + +#include "mediaelement.h" + +#include <QHash> +#include <QThread> + +class QueueWorker; + +class DataStorage : public QObject +{ + Q_OBJECT +public: + explicit DataStorage(); + ~DataStorage(); + + //! [Interface towards the model] + QList<int> idList(); + MediaElement item(int id) const; + std::optional<int> currentlyFetchedId() const; + //! [Interface towards the model] + +signals: + // Towards client + void dataUpdated(int id); + // Towards worker + void dataFetchNeeded(int index) const; + +private slots: + // From worker + void fetchStarted(int index); + void fetchAborted(int index); + void dataReceived(int index, MediaElement element); + +private: + QueueWorker *m_worker; + QList<int> m_idList; + QThread m_workerThread; + std::optional<int> m_currentlyFetchedId; + /* The item list is mutable as DataStorage needs to mark already signaled items to it in + * const data() call of model */ + mutable QHash<int, MediaElement> m_items; +}; + +#endif // DATASTORAGE_H diff --git a/examples/quick/models/threadedsonglist/doc/images/qml-threadedsonglist-example.webp b/examples/quick/models/threadedsonglist/doc/images/qml-threadedsonglist-example.webp Binary files differnew file mode 100644 index 0000000000..b0cd68b44c --- /dev/null +++ b/examples/quick/models/threadedsonglist/doc/images/qml-threadedsonglist-example.webp diff --git a/examples/quick/models/threadedsonglist/doc/src/threadedsonglist-example.qdoc b/examples/quick/models/threadedsonglist/doc/src/threadedsonglist-example.qdoc new file mode 100644 index 0000000000..b3c23602e7 --- /dev/null +++ b/examples/quick/models/threadedsonglist/doc/src/threadedsonglist-example.qdoc @@ -0,0 +1,96 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \example models/threadedsonglist + \title Models and Views: List Model using a worker thread for data fetching + \brief Demonstrates how to implement a list model with a responsive UI + using a worker thread to fetch data. + \examplecategory {User Interface Components} + \examplecategory {Data Processing & I/O} + \meta {tag} {quick,threads} + \image qml-threadedsonglist-example.webp {Screenshot of the application + where a songlist with album arts, song names, artist names and album names + are visible} + + This example introduces a custom item model, inheriting QAbstractListModel. + The model gets its data from a worker object that is in separate QThread, + fetching data from a slow data source. + + \section1 Overview of the Threaded Song List example + + The data source simulates a slow data source by adding a delay of 100 + milliseconds per song fetched from it. This means that loading of the + entire list of 3600 songs would take 6 minutes, making the opening of the + application impractical. This delay is mitigated by fetching the data only + for the visible area of the view, using a QObject placed into a worker + thread. + + The worker object has a limit for the number of fetch requests it holds in + queue. This ensures that only the elements of the currently visible part of + the song list are fetched, removing the need to wait for the non-visible + part of the list to load, when user has already scrolled past some part of + the list. + + Focus of this example is in the source model of the view. The view itself + is an unmodified QML ListView with a simple delegate. The use of thread is + hidden behind the implementation of model data handling and the ListView + does not need to have any customization to be able to adapt to the + thread-based model. + + Also since the focus is in the model, the Qt Quick Controls is set to use + Universal style on all platforms to ensure identical UI behavior. + + \snippet models/threadedsonglist/ThreadedSongList.qml Fixed Controls style + + \section1 How it works + + The business logic of providing the song list data is separated into + \c DataStorage class that provides a simple ID-based interface for the model. + + \snippet models/threadedsonglist/datastorage.h Interface towards the model + + When model requests data from the DataStorage, the storage will first check + if it has the data already available. If it does, data is returned + instantly, as would be the case in a non-threaded model. In case the data + is not found, DataStorage will emit a \c dataFetchNeeded() signal to the + worker object and add an empty item to the list of already existing data. + Adding the empty item ensures that no further signals are sent to the + worker for the same list item. + + \snippet models/threadedsonglist/datastorage.cpp Send signal if no data + + \c QueueWorker - the worker thread object - processes the dataFetchNeeded() + signals it has received by sending a signal to itself, which makes it + possible to receive all signals already in QEventQueue before starting the + slow data read operation. + + \section1 Applying the approach to dynamic models + + If one wishes to expand the solution towards a case where items may be + added, moved or removed from the data source (in this case RemoteMedia), + DataStorage needs to be updated with signals to match + QAbstractItemModel::rowsMoved(), QAbstractItemModel::rowsInserted() and + two signals to trigger the QAbstractItemModel::beginRemoveRows() and + QAbstractItemModel::endRemoveRows() inside ThreadedListModel. + + For the insertion and move the ThreadedListModel can just call + QAbstractItemModel::beginInsertRows(), then add new IDs to its ID list and + call QAbstractItemModel::endInsertRows(). As ThreadedListModel holds a copy + of the ID list and accesses storage by ID, there is no need to signal the + begin and end from storage. Equally ThreadedListModel can call + QAbstractItemModel::beginMoveRows(), move IDs in its ID list and then call + QAbstractItemModel::endMoveRows(). + + Removal is a slightly more complex case. The view needs to have a + possibility to request the data that is going to be removed before it is + actually removed. So DataStorage needs to signal a warning of the removal, + causing the Model to call QAbstractItemModel::beginRemoveRows(). At this + stage ThreadedListModel may get one or more \c data() calls. Once the call + to direct connected signal returns at DataStorage, it is OK for DataStorage + to remove the item and then signal the model again with another signal that + triggers the model to call QAbstractItemModel::endRemoveRows(). + + \include examples-run.qdocinc + +*/ diff --git a/examples/quick/models/threadedsonglist/images/album_covers/classical1.jpeg b/examples/quick/models/threadedsonglist/images/album_covers/classical1.jpeg Binary files differnew file mode 100644 index 0000000000..b7af47e53b --- /dev/null +++ b/examples/quick/models/threadedsonglist/images/album_covers/classical1.jpeg diff --git a/examples/quick/models/threadedsonglist/images/album_covers/classical2.jpeg b/examples/quick/models/threadedsonglist/images/album_covers/classical2.jpeg Binary files differnew file mode 100644 index 0000000000..d06411375e --- /dev/null +++ b/examples/quick/models/threadedsonglist/images/album_covers/classical2.jpeg diff --git a/examples/quick/models/threadedsonglist/images/album_covers/classical3.jpeg b/examples/quick/models/threadedsonglist/images/album_covers/classical3.jpeg Binary files differnew file mode 100644 index 0000000000..6e16f84ba9 --- /dev/null +++ b/examples/quick/models/threadedsonglist/images/album_covers/classical3.jpeg diff --git a/examples/quick/models/threadedsonglist/images/album_covers/classical4.jpeg b/examples/quick/models/threadedsonglist/images/album_covers/classical4.jpeg Binary files differnew file mode 100644 index 0000000000..07e6d72c02 --- /dev/null +++ b/examples/quick/models/threadedsonglist/images/album_covers/classical4.jpeg diff --git a/examples/quick/models/threadedsonglist/images/album_covers/classical5.jpeg b/examples/quick/models/threadedsonglist/images/album_covers/classical5.jpeg Binary files differnew file mode 100644 index 0000000000..a7e7dce536 --- /dev/null +++ b/examples/quick/models/threadedsonglist/images/album_covers/classical5.jpeg diff --git a/examples/quick/models/threadedsonglist/images/album_covers/classical6.jpeg b/examples/quick/models/threadedsonglist/images/album_covers/classical6.jpeg Binary files differnew file mode 100644 index 0000000000..9b6c146d98 --- /dev/null +++ b/examples/quick/models/threadedsonglist/images/album_covers/classical6.jpeg diff --git a/examples/quick/models/threadedsonglist/images/album_covers/metal1.jpeg b/examples/quick/models/threadedsonglist/images/album_covers/metal1.jpeg Binary files differnew file mode 100644 index 0000000000..edea49d108 --- /dev/null +++ b/examples/quick/models/threadedsonglist/images/album_covers/metal1.jpeg diff --git a/examples/quick/models/threadedsonglist/images/album_covers/metal2.jpeg b/examples/quick/models/threadedsonglist/images/album_covers/metal2.jpeg Binary files differnew file mode 100644 index 0000000000..dac8e02ece --- /dev/null +++ b/examples/quick/models/threadedsonglist/images/album_covers/metal2.jpeg diff --git a/examples/quick/models/threadedsonglist/images/album_covers/metal3.jpeg b/examples/quick/models/threadedsonglist/images/album_covers/metal3.jpeg Binary files differnew file mode 100644 index 0000000000..c3044af90a --- /dev/null +++ b/examples/quick/models/threadedsonglist/images/album_covers/metal3.jpeg diff --git a/examples/quick/models/threadedsonglist/images/album_covers/metal4.jpeg b/examples/quick/models/threadedsonglist/images/album_covers/metal4.jpeg Binary files differnew file mode 100644 index 0000000000..bda98ee77e --- /dev/null +++ b/examples/quick/models/threadedsonglist/images/album_covers/metal4.jpeg diff --git a/examples/quick/models/threadedsonglist/images/album_covers/metal5.jpeg b/examples/quick/models/threadedsonglist/images/album_covers/metal5.jpeg Binary files differnew file mode 100644 index 0000000000..c467f53a19 --- /dev/null +++ b/examples/quick/models/threadedsonglist/images/album_covers/metal5.jpeg diff --git a/examples/quick/models/threadedsonglist/images/album_covers/metal6.jpeg b/examples/quick/models/threadedsonglist/images/album_covers/metal6.jpeg Binary files differnew file mode 100644 index 0000000000..0b90d744d2 --- /dev/null +++ b/examples/quick/models/threadedsonglist/images/album_covers/metal6.jpeg diff --git a/examples/quick/models/threadedsonglist/images/album_covers/pop1.jpeg b/examples/quick/models/threadedsonglist/images/album_covers/pop1.jpeg Binary files differnew file mode 100644 index 0000000000..65c09a576c --- /dev/null +++ b/examples/quick/models/threadedsonglist/images/album_covers/pop1.jpeg diff --git a/examples/quick/models/threadedsonglist/images/album_covers/pop2.jpeg b/examples/quick/models/threadedsonglist/images/album_covers/pop2.jpeg Binary files differnew file mode 100644 index 0000000000..0bd2b28ca9 --- /dev/null +++ b/examples/quick/models/threadedsonglist/images/album_covers/pop2.jpeg diff --git a/examples/quick/models/threadedsonglist/images/album_covers/pop3.jpeg b/examples/quick/models/threadedsonglist/images/album_covers/pop3.jpeg Binary files differnew file mode 100644 index 0000000000..683dc2931b --- /dev/null +++ b/examples/quick/models/threadedsonglist/images/album_covers/pop3.jpeg diff --git a/examples/quick/models/threadedsonglist/images/album_covers/pop4.jpeg b/examples/quick/models/threadedsonglist/images/album_covers/pop4.jpeg Binary files differnew file mode 100644 index 0000000000..72ca07f3d3 --- /dev/null +++ b/examples/quick/models/threadedsonglist/images/album_covers/pop4.jpeg diff --git a/examples/quick/models/threadedsonglist/images/album_covers/pop5.jpeg b/examples/quick/models/threadedsonglist/images/album_covers/pop5.jpeg Binary files differnew file mode 100644 index 0000000000..d7abcb0cac --- /dev/null +++ b/examples/quick/models/threadedsonglist/images/album_covers/pop5.jpeg diff --git a/examples/quick/models/threadedsonglist/images/album_covers/pop6.jpeg b/examples/quick/models/threadedsonglist/images/album_covers/pop6.jpeg Binary files differnew file mode 100644 index 0000000000..217816a694 --- /dev/null +++ b/examples/quick/models/threadedsonglist/images/album_covers/pop6.jpeg diff --git a/examples/quick/models/threadedsonglist/images/album_covers/rock1.jpeg b/examples/quick/models/threadedsonglist/images/album_covers/rock1.jpeg Binary files differnew file mode 100644 index 0000000000..728353ce83 --- /dev/null +++ b/examples/quick/models/threadedsonglist/images/album_covers/rock1.jpeg diff --git a/examples/quick/models/threadedsonglist/images/album_covers/rock2.jpeg b/examples/quick/models/threadedsonglist/images/album_covers/rock2.jpeg Binary files differnew file mode 100644 index 0000000000..0fc626173d --- /dev/null +++ b/examples/quick/models/threadedsonglist/images/album_covers/rock2.jpeg diff --git a/examples/quick/models/threadedsonglist/images/album_covers/rock3.jpeg b/examples/quick/models/threadedsonglist/images/album_covers/rock3.jpeg Binary files differnew file mode 100644 index 0000000000..96f3c342e7 --- /dev/null +++ b/examples/quick/models/threadedsonglist/images/album_covers/rock3.jpeg diff --git a/examples/quick/models/threadedsonglist/images/album_covers/rock4.jpeg b/examples/quick/models/threadedsonglist/images/album_covers/rock4.jpeg Binary files differnew file mode 100644 index 0000000000..4e35aa6124 --- /dev/null +++ b/examples/quick/models/threadedsonglist/images/album_covers/rock4.jpeg diff --git a/examples/quick/models/threadedsonglist/images/album_covers/rock5.jpeg b/examples/quick/models/threadedsonglist/images/album_covers/rock5.jpeg Binary files differnew file mode 100644 index 0000000000..7d3456419a --- /dev/null +++ b/examples/quick/models/threadedsonglist/images/album_covers/rock5.jpeg diff --git a/examples/quick/models/threadedsonglist/images/album_covers/rock6.jpeg b/examples/quick/models/threadedsonglist/images/album_covers/rock6.jpeg Binary files differnew file mode 100644 index 0000000000..fb71999e14 --- /dev/null +++ b/examples/quick/models/threadedsonglist/images/album_covers/rock6.jpeg diff --git a/examples/quick/models/threadedsonglist/images/device/remote.jpeg b/examples/quick/models/threadedsonglist/images/device/remote.jpeg Binary files differnew file mode 100644 index 0000000000..9751188536 --- /dev/null +++ b/examples/quick/models/threadedsonglist/images/device/remote.jpeg diff --git a/examples/quick/models/threadedsonglist/main.cpp b/examples/quick/models/threadedsonglist/main.cpp new file mode 100644 index 0000000000..60c12ad601 --- /dev/null +++ b/examples/quick/models/threadedsonglist/main.cpp @@ -0,0 +1,21 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include <QGuiApplication> +#include <QQmlApplicationEngine> + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + + QQmlApplicationEngine engine; + QObject::connect( + &engine, + &QQmlApplicationEngine::objectCreationFailed, + &app, + []() { QCoreApplication::exit(-1); }, + Qt::QueuedConnection); + engine.loadFromModule("threadedsonglist", "ThreadedSongList"); + + return app.exec(); +} diff --git a/examples/quick/models/threadedsonglist/mediaelement.cpp b/examples/quick/models/threadedsonglist/mediaelement.cpp new file mode 100644 index 0000000000..6d93cd55ea --- /dev/null +++ b/examples/quick/models/threadedsonglist/mediaelement.cpp @@ -0,0 +1,42 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "mediaelement.h" + +MediaElement::MediaElement() {} + +MediaElement::MediaElement(QStringView songName, + QStringView artistName, + QStringView albumName, + const QUrl& albumArt) + : m_isValid{true} + , m_song{songName} + , m_artist{artistName} + , m_album{albumName} + , m_albumArtUrl{albumArt} +{} + +bool MediaElement::isValid() const +{ + return m_isValid; +} + +QUrl MediaElement::albumArtFile() const +{ + return m_albumArtUrl; +} + +QString MediaElement::song() const +{ + return m_song; +} + +QString MediaElement::artist() const +{ + return m_artist; +} + +QString MediaElement::album() const +{ + return m_album; +} diff --git a/examples/quick/models/threadedsonglist/mediaelement.h b/examples/quick/models/threadedsonglist/mediaelement.h new file mode 100644 index 0000000000..d93942f65d --- /dev/null +++ b/examples/quick/models/threadedsonglist/mediaelement.h @@ -0,0 +1,31 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef MEDIAELEMENT_H +#define MEDIAELEMENT_H + +#include <QUrl> + +class MediaElement +{ +public: + explicit MediaElement(); + MediaElement(QStringView songName, + QStringView artistName, + QStringView albumName, + const QUrl &albumArt); + bool isValid() const; + QUrl albumArtFile() const; + QString song() const; + QString artist() const; + QString album() const; + +private: + bool m_isValid{false}; + QString m_song; + QString m_artist; + QString m_album; + QUrl m_albumArtUrl; +}; + +#endif // MEDIAELEMENT_H diff --git a/examples/quick/models/threadedsonglist/queueworker.cpp b/examples/quick/models/threadedsonglist/queueworker.cpp new file mode 100644 index 0000000000..0b41a0e395 --- /dev/null +++ b/examples/quick/models/threadedsonglist/queueworker.cpp @@ -0,0 +1,68 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "queueworker.h" + +/* view needs 8 items and cacheBuffer of 2 items above and below to show visible area, so limit queue max length to that. */ +static constexpr int s_queueMaxLength{12}; + +QueueWorker::QueueWorker() + : QObject{nullptr} +{ + connect(this, + &QueueWorker::triggerQueueProcessing, + this, + &QueueWorker::processQueue, + Qt::QueuedConnection); +} + +void QueueWorker::abort() +{ + m_killSignalReceived = true; +} + +void QueueWorker::fetchData(int id) +{ + if (m_indicesAlreadyFetched.contains(id) || m_indicesToFetch.contains(id) + || m_killSignalReceived) + return; + + /* This is signal from UI thread. It is likely that there are more than one in queue. + * Add our own triggerQueueProcessing() signal to the end of event queue and add id to queue of IDs. + * Then let all queued signals to be processed until QueueWorker receives its own signal. + */ + sendTriggerQueueProcessingSignal(id); +} + +void QueueWorker::processQueue() +{ + /* This slot receives QueueWorker's own signal after all signals from UI thread have been processed. */ + m_queueProcessingSignalSent = false; + const auto index = m_indicesToFetch.dequeue(); + emit processing(index); + const auto data = m_remoteMedia.getElements(1, index); + m_indicesAlreadyFetched.insert(index); + emit dataFetched(index, data.front()); + if (!m_indicesToFetch.empty() && !m_killSignalReceived) { + /* Queueworker should process more indices, but the UI thread may have sent more signals during previous processing. + * Add our own signal to end of event queue and let all preceding signals to be processed before continuing. + */ + emit triggerQueueProcessing(QPrivateSignal{}); + m_queueProcessingSignalSent = true; + } + /* Else all fetches have been processed so far. */ +} + +void QueueWorker::sendTriggerQueueProcessingSignal(int id) +{ + /* Make sure excess IDs are removed. */ + while (m_indicesToFetch.size() >= s_queueMaxLength) { + emit dropped(m_indicesToFetch.dequeue()); + } + /* Before calling this function QueueWorker has ensured that m_indicesToFetch doesn't contain id yet, so just add id. */ + m_indicesToFetch.enqueue(id); + if (!m_queueProcessingSignalSent) { + emit triggerQueueProcessing(QPrivateSignal{}); + m_queueProcessingSignalSent = true; + } +} diff --git a/examples/quick/models/threadedsonglist/queueworker.h b/examples/quick/models/threadedsonglist/queueworker.h new file mode 100644 index 0000000000..6a30639d64 --- /dev/null +++ b/examples/quick/models/threadedsonglist/queueworker.h @@ -0,0 +1,41 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef QUEUEWORKER_H +#define QUEUEWORKER_H + +#include "remotemedia.h" + +#include <QObject> +#include <QQueue> +#include <QSet> + +class QueueWorker : public QObject +{ + Q_OBJECT +public: + explicit QueueWorker(); + void abort(); + +signals: + void processing(int index); + void dropped(int index); + void dataFetched(int index, MediaElement element); + void triggerQueueProcessing(QPrivateSignal); // signal to self, see implementation of fetchData() + +public slots: + void fetchData(int index); + +private slots: + void processQueue(); + +private: + void sendTriggerQueueProcessingSignal(int index); + RemoteMedia m_remoteMedia; + QSet<int> m_indicesAlreadyFetched; + QQueue<int> m_indicesToFetch; + std::atomic<bool> m_killSignalReceived{false}; + bool m_queueProcessingSignalSent{false}; +}; + +#endif // QUEUEWORKER_H diff --git a/examples/quick/models/threadedsonglist/remotemedia.cpp b/examples/quick/models/threadedsonglist/remotemedia.cpp new file mode 100644 index 0000000000..0556458035 --- /dev/null +++ b/examples/quick/models/threadedsonglist/remotemedia.cpp @@ -0,0 +1,29 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "remotemedia.h" +#include "songdatagenerator.h" + +#include <QThread> + +static constexpr int s_fetchMilliSecondsPerSong{100}; + +RemoteMedia::RemoteMedia() +{ + SongDataGenerator dataGenerator; + m_items = dataGenerator.createSongList(); +} + +int RemoteMedia::count() +{ + return SongDataGenerator::elementMaxCount(); +} + +QList<MediaElement> RemoteMedia::getElements(int amount, int offset) const +{ + if (amount < 1) + return {}; + QList<MediaElement> returnValue{m_items.cbegin() + offset, m_items.cbegin() + offset + amount}; + QThread::sleep(std::chrono::milliseconds{s_fetchMilliSecondsPerSong * amount}); + return returnValue; +} diff --git a/examples/quick/models/threadedsonglist/remotemedia.h b/examples/quick/models/threadedsonglist/remotemedia.h new file mode 100644 index 0000000000..64c081deac --- /dev/null +++ b/examples/quick/models/threadedsonglist/remotemedia.h @@ -0,0 +1,25 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef REMOTEMEDIA_H +#define REMOTEMEDIA_H +#include "mediaelement.h" + +#include <QList> + +class RemoteMedia +{ +public: + explicit RemoteMedia(); + + /* Fast access to total count of items (so UI knows the total item list size). */ + static int count(); + + /* Getter (100 milliseconds per item, function call is blocking the thread) */ + QList<MediaElement> getElements(int amount, int offset) const; + +private: + QList<MediaElement> m_items; +}; + +#endif // REMOTEMEDIA_H diff --git a/examples/quick/models/threadedsonglist/songdatagenerator.cpp b/examples/quick/models/threadedsonglist/songdatagenerator.cpp new file mode 100644 index 0000000000..42bf9cfe33 --- /dev/null +++ b/examples/quick/models/threadedsonglist/songdatagenerator.cpp @@ -0,0 +1,182 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "songdatagenerator.h" + +#include <QStringLiteral> + +static constexpr int s_albumCount{6}; +static constexpr int s_bandNamePrefixSuffixCount{5}; +static constexpr int s_songNamePrefixSuffixCount{6}; +static constexpr int s_genreCount{4}; + +SongDataGenerator::SongDataGenerator() +{ + //classical music + m_bandPrefixes << QStringList{QStringLiteral("Qtie's"), + QStringLiteral("Kjuutburg"), + QStringLiteral("Qtional"), + QStringLiteral("Kjuutinese"), + QStringLiteral("Qtian's")}; + m_bandSuffixes << QStringList{QStringLiteral("Philharmonic QOrchestra"), + QStringLiteral("Theatre QOrchestra"), + QStringLiteral("Opera QOrchestra"), + QStringLiteral("City QChoir"), + QStringLiteral("University QOrchestra")}; + // metal music + m_bandPrefixes << QStringList{QStringLiteral("QtBlack"), + QStringLiteral("QtDark"), + QStringLiteral("QtHard"), + QStringLiteral("QTest"), + QStringLiteral("QtPale")}; + m_bandSuffixes << QStringList{QStringLiteral("Death"), + QStringLiteral("Creature"), + QStringLiteral("Devil"), + QStringLiteral("Souls"), + QStringLiteral("Being")}; + // pop music + m_bandPrefixes << QStringList{QStringLiteral("Happy"), + QStringLiteral("Joyful"), + QStringLiteral("Pretty"), + QStringLiteral("Crazy"), + QStringLiteral("Wild")}; + m_bandSuffixes << QStringList{QStringLiteral("QPink"), + QStringLiteral("QLife"), + QStringLiteral("QGirls"), + QStringLiteral("QBoys"), + QStringLiteral("QMood")}; + // rock music + m_bandPrefixes << QStringList{QStringLiteral("Grateful"), + QStringLiteral("Hard"), + QStringLiteral("Rolling"), + QStringLiteral("Clashing"), + QStringLiteral("Breaking")}; + m_bandSuffixes << QStringList{QStringLiteral("QML Thunder"), + QStringLiteral("QML Slam"), + QStringLiteral("QML Rocks"), + QStringLiteral("QML Rally"), + QStringLiteral("QML Tune")}; + + // classical music + m_songPrefixes << QStringList{"QWaltz", "QPrelude", "QDance", "QSonata", "QSymphony", "QPiano"}; + m_songSuffixes << QStringList{"in D Minor", + "of the Pixies", + "by Night", + "on Violin", + "no. 5", + "in tune"}; + // metal music + m_songPrefixes << QStringList{"QHunger", "QScreaming", "QPain", "QIllusion", "QBeauty", "QDream"}; + m_songSuffixes << QStringList{"That Never Ends", + "Rising", + "in My Soul", + "from The Dark", + "on the Night", + "from Beyond"}; + // pop music + m_songPrefixes << QStringList{"Jumping", "Running", "Playing", "Laughing", "Singing", "Joking"}; + m_songSuffixes << QStringList{"Qt Alone", + "of Qt Life", + "for Qt Fun", + "Q-Day", + "with Qties", + "All the QTime"}; + // rock music + m_songPrefixes << QStringList{"Full Steam", "Going", "Looking", "Always", "Crazy", "Drive Me"}; + m_songSuffixes << QStringList{"QWild", + "Qt-wards", + "to the QEnd", + "for you, Qtie", + "QTonight", + "QHome"}; + Q_ASSERT(m_bandPrefixes.size() == s_genreCount); + Q_ASSERT(m_bandSuffixes.size() == s_genreCount); + Q_ASSERT(m_songPrefixes.size() == s_genreCount); + Q_ASSERT(m_songSuffixes.size() == s_genreCount); + for (const auto &prefixList : std::as_const(m_bandPrefixes)) { + Q_ASSERT(prefixList.size() == s_bandNamePrefixSuffixCount); + } + for (const auto &suffixList : std::as_const(m_bandSuffixes)) { + Q_ASSERT(suffixList.size() == s_bandNamePrefixSuffixCount); + } + for (const auto &prefixList : std::as_const(m_songPrefixes)) { + Q_ASSERT(prefixList.size() == s_songNamePrefixSuffixCount); + } + for (const auto &suffixList : std::as_const(m_songSuffixes)) { + Q_ASSERT(suffixList.size() == s_songNamePrefixSuffixCount); + } +} + +int SongDataGenerator::elementMaxCount() +{ + return s_bandNamePrefixSuffixCount * s_songNamePrefixSuffixCount * s_bandNamePrefixSuffixCount + * s_songNamePrefixSuffixCount * s_genreCount; +} + +QList<MediaElement> SongDataGenerator::createSongList() const +{ + QList<MediaElement> returnList; + returnList.reserve(elementMaxCount()); + for (int bandSuffix = 0; bandSuffix < s_bandNamePrefixSuffixCount; ++bandSuffix) { + for (int songSuffix = 0; songSuffix < s_songNamePrefixSuffixCount; ++songSuffix) { + for (int bandPrefix = 0; bandPrefix < s_bandNamePrefixSuffixCount; ++bandPrefix) { + for (int songPrefix = 0; songPrefix < s_songNamePrefixSuffixCount; ++songPrefix) { + for (int genre = 0; genre < s_genreCount; ++genre) { + returnList.append( + MediaElement{songName(songPrefix, songSuffix, genre), + bandName(bandPrefix, bandSuffix, genre), + SongDataGenerator::albumName(bandPrefix, songPrefix, genre), + SongDataGenerator::albumArt(bandPrefix, songPrefix, genre)}); + } + } + } + } + } + Q_ASSERT(returnList.size() == elementMaxCount()); + return returnList; +} + +QString SongDataGenerator::bandName(int bandNamePrefixIndex, + int bandNameSuffixIndex, + int genreIndex) const +{ + return QStringLiteral("%1 %2").arg(m_bandPrefixes.at(genreIndex).at(bandNamePrefixIndex), + m_bandSuffixes.at(genreIndex).at(bandNameSuffixIndex)); +} + +QString SongDataGenerator::songName(int songNamePrefixIndex, + int songNameSuffixIndex, + int genreIndex) const +{ + return QStringLiteral("%1 %2").arg(m_songPrefixes.at(genreIndex).at(songNamePrefixIndex), + m_songSuffixes.at(genreIndex).at(songNameSuffixIndex)); +} + +QString SongDataGenerator::albumName(int bandNamePrefixIndex, + int songNamePrefixIndex, + int genreIndex) +{ + static const QStringList albums{"First QAlbum", + "The QBest Of", + "World QtTour", + "Live at Qt Arena", + "QEnchanted", + "QFarewell"}; + Q_ASSERT(albums.size() == s_albumCount); + return albums.at(albumIndex(bandNamePrefixIndex, songNamePrefixIndex, genreIndex)); +} + +QUrl SongDataGenerator::albumArt(int bandNamePrefixIndex, int songNamePrefixIndex, int genreIndex) +{ + static const QStringList genres{"classical", "metal", "pop", "rock"}; + return QUrl{QStringLiteral("qrc:/qt/qml/threadedsonglist/images/album_covers/%1%2.jpeg") + .arg(genres.at(genreIndex)) + .arg(albumIndex(bandNamePrefixIndex, songNamePrefixIndex, genreIndex) + 1)}; +} + +int SongDataGenerator::albumIndex(int bandNamePrefixIndex, int songNamePrefixIndex, int genreIndex) +{ + return ((bandNamePrefixIndex * s_songNamePrefixSuffixCount) + songNamePrefixIndex + + (genreIndex % s_genreCount)) + % s_albumCount; +} diff --git a/examples/quick/models/threadedsonglist/songdatagenerator.h b/examples/quick/models/threadedsonglist/songdatagenerator.h new file mode 100644 index 0000000000..9227a5badb --- /dev/null +++ b/examples/quick/models/threadedsonglist/songdatagenerator.h @@ -0,0 +1,30 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef SONGDATAGENERATOR_H +#define SONGDATAGENERATOR_H +#include "mediaelement.h" + +#include <QPair> +#include <QStringList> + +class SongDataGenerator +{ +public: + explicit SongDataGenerator(); + static int elementMaxCount(); + QList<MediaElement> createSongList() const; + +private: + QString bandName(int bandNamePrefixIndex, int bandNameSuffixIndex, int genreIndex) const; + QString songName(int songNamePrefixIndex, int songNameSuffixIndex, int genreIndex) const; + static QString albumName(int bandNamePrefixIndex, int songNamePrefixIndex, int genreIndex); + static QUrl albumArt(int bandNamePrefixIndex, int songNamePrefixIndex, int genreIndex); + static int albumIndex(int bandNamePrefixIndex, int songNamePrefixIndex, int genreIndex); + QList<QStringList> m_bandPrefixes; + QList<QStringList> m_bandSuffixes; + QList<QStringList> m_songPrefixes; + QList<QStringList> m_songSuffixes; +}; + +#endif // SONGDATAGENERATOR_H diff --git a/examples/quick/models/threadedsonglist/threadedlistmodel.cpp b/examples/quick/models/threadedsonglist/threadedlistmodel.cpp new file mode 100644 index 0000000000..b509d88ead --- /dev/null +++ b/examples/quick/models/threadedsonglist/threadedlistmodel.cpp @@ -0,0 +1,75 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "threadedlistmodel.h" + +ThreadedListModel::ThreadedListModel() +{ + m_idList = m_storage.idList(); + connect(&m_storage, &DataStorage::dataUpdated, this, &ThreadedListModel::dataUpdated); +} + +int ThreadedListModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) + return 0; + return m_idList.size(); +} + +QVariant ThreadedListModel::data(const QModelIndex &index, int role) const +{ + const auto id = m_idList.at(index.row()); + const auto &item = m_storage.item(id); + if (item.isValid()) { + switch (static_cast<Role>(role)) { + case Role::Album: + return item.album(); + case Role::AlbumArt: + return item.albumArtFile(); + case Role::Artist: + return item.artist(); + case Role::Song: + return item.song(); + case Role::LoadingElement: + return false; + case Role::LoadingText: + return QString(); + default: + break; + } + } else { + /* Item not fetched yet, pass "loading" item. */ + switch (static_cast<Role>(role)) { + case Role::Album: + case Role::AlbumArt: + case Role::Artist: + case Role::Song: + return QString{}; + case Role::LoadingElement: + return true; + case Role::LoadingText: + return m_storage.currentlyFetchedId() == id ? QString{} : tr("Waiting..."); + default: + break; + } + } + return QVariant{}; +} + +void ThreadedListModel::dataUpdated(int id) +{ + const QModelIndex changedIndex = index(m_idList.indexOf(id)); + emit dataChanged(changedIndex, changedIndex); +} + +QHash<int, QByteArray> ThreadedListModel::roleNames() const +{ + static const QHash<int, QByteArray> roles{{static_cast<int>(Role::Song), "song"}, + {static_cast<int>(Role::Artist), "artist"}, + {static_cast<int>(Role::Album), "album"}, + {static_cast<int>(Role::AlbumArt), "albumArt"}, + {static_cast<int>(Role::LoadingText), "loadingText"}, + {static_cast<int>(Role::LoadingElement), + "isLoadingElement"}}; + return roles; +} diff --git a/examples/quick/models/threadedsonglist/threadedlistmodel.h b/examples/quick/models/threadedsonglist/threadedlistmodel.h new file mode 100644 index 0000000000..b9d4056b15 --- /dev/null +++ b/examples/quick/models/threadedsonglist/threadedlistmodel.h @@ -0,0 +1,41 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef THREADEDLISTMODEL_H +#define THREADEDLISTMODEL_H + +#include "datastorage.h" + +#include <QAbstractListModel> +#include <QQmlEngine> + +class ThreadedListModel : public QAbstractListModel +{ + Q_OBJECT + QML_ELEMENT +public: + explicit ThreadedListModel(); + Q_INVOKABLE int rowCount(const QModelIndex &parent = QModelIndex()) const override; + Q_INVOKABLE QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + QHash<int, QByteArray> roleNames() const override; + +protected: + enum class Role { + Song = Qt::ItemDataRole::UserRole, + Artist, + Album, + AlbumArt, + LoadingElement, + LoadingText + }; + +private slots: + void dataUpdated(int id); + +private: + DataStorage m_storage; + QList<int> m_idList; + int m_currentSongId{-1}; +}; + +#endif // THREADEDLISTMODEL_H diff --git a/examples/quick/models/threadedsonglist/threadedsonglist.pro b/examples/quick/models/threadedsonglist/threadedsonglist.pro new file mode 100644 index 0000000000..bc83d7c89f --- /dev/null +++ b/examples/quick/models/threadedsonglist/threadedsonglist.pro @@ -0,0 +1,20 @@ +TARGET = threadedsonglist +QT += qml quick + +HEADERS = datastorage.h \ + mediaelement.h \ + queueworker.h \ + remotemedia.h \ + songdatagenerator.h \ + threadedlistmodel.h +SOURCES = main.cpp \ + datastorage.cpp \ + mediaelement.cpp \ + queueworker.cpp \ + remotemedia.cpp \ + songdatagenerator.cpp \ + threadedlistmodel.cpp +RESOURCES += threadedsonglist.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/quick/models/threadedsonglist +INSTALLS += target diff --git a/examples/quick/models/threadedsonglist/threadedsonglist.qrc b/examples/quick/models/threadedsonglist/threadedsonglist.qrc new file mode 100644 index 0000000000..ac4cd3c049 --- /dev/null +++ b/examples/quick/models/threadedsonglist/threadedsonglist.qrc @@ -0,0 +1,32 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/"> + <file>SongListDelegate.qml</file> + <file>ThreadedSongList.qml</file> + <file>images/album_covers/classical1.jpeg</file> + <file>images/album_covers/classical2.jpeg</file> + <file>images/album_covers/classical3.jpeg</file> + <file>images/album_covers/classical4.jpeg</file> + <file>images/album_covers/classical5.jpeg</file> + <file>images/album_covers/classical6.jpeg</file> + <file>images/album_covers/metal1.jpeg</file> + <file>images/album_covers/metal2.jpeg</file> + <file>images/album_covers/metal3.jpeg</file> + <file>images/album_covers/metal4.jpeg</file> + <file>images/album_covers/metal5.jpeg</file> + <file>images/album_covers/metal6.jpeg</file> + <file>images/album_covers/pop1.jpeg</file> + <file>images/album_covers/pop2.jpeg</file> + <file>images/album_covers/pop3.jpeg</file> + <file>images/album_covers/pop4.jpeg</file> + <file>images/album_covers/pop5.jpeg</file> + <file>images/album_covers/pop6.jpeg</file> + <file>images/album_covers/rock1.jpeg</file> + <file>images/album_covers/rock2.jpeg</file> + <file>images/album_covers/rock3.jpeg</file> + <file>images/album_covers/rock4.jpeg</file> + <file>images/album_covers/rock5.jpeg</file> + <file>images/album_covers/rock6.jpeg</file> + <file>images/device/remote.jpeg</file> +</qresource> +</RCC> + diff --git a/src/qml/Qt6QmlMacros.cmake b/src/qml/Qt6QmlMacros.cmake index 6122394e09..c9aebff06d 100644 --- a/src/qml/Qt6QmlMacros.cmake +++ b/src/qml/Qt6QmlMacros.cmake @@ -2946,6 +2946,7 @@ function(qt6_target_qml_sources target) set(actual_${file_set} "") set(actual_${file_set}_absolute "") set(duplicate_in_${file_set} "") + set(duplicate_input_in_${file_set} "") get_target_property(current_${file_set} ${target} QT_QML_MODULE_${file_set}) foreach(file_src IN LISTS arg_${file_set}) # TODO: For now we check against absolute path to avoid surprises with other @@ -2953,7 +2954,7 @@ function(qt6_target_qml_sources target) get_filename_component(file_absolute ${file_src} ABSOLUTE) # Check for duplicates in the current list if(file_absolute IN_LIST actual_${file_set}_absolute) - # We can silently ignore these because they have the same function parameters + list(APPEND duplicate_input_in_${file_set}) continue() endif() # Check for duplicates in the target property added so far @@ -2984,8 +2985,26 @@ function(qt6_target_qml_sources target) endforeach() # Display warnings for all invalid files - # Warn about duplicated files - if(duplicate_in_${file_set}) + # Warn about duplicated files in input + if(NOT QT_QML_IGNORE_DUPLICATE_FILES AND duplicate_input_in_${file_set}) + # We trigger a warning here because it was added before with potentially different + # parameters, properties + set(warning_message + "The following files are passed more than once ${file_set}:" + ) + list(JOIN duplicate_input_in_${file_set} + "\n${warning_message_file_prefix}" + warning_file_set + ) + string(APPEND warning_message + "\n${warning_message_file_prefix}" + "${warning_file_set}\n" + "(this message can be suppressed by setting QT_QML_IGNORE_DUPLICATE_FILES=ON)" + ) + message(WARNING "${warning_message}") + endif() + # Warn about duplicated files overall + if(NOT QT_QML_IGNORE_DUPLICATE_FILES AND duplicate_in_${file_set}) # We trigger a warning here because it was added before with potentially different # parameters, properties set(warning_message @@ -2997,7 +3016,8 @@ function(qt6_target_qml_sources target) ) string(APPEND warning_message "\n${warning_message_file_prefix}" - "${warning_file_set}" + "${warning_file_set}\n" + "(this message can be suppressed by setting QT_QML_IGNORE_DUPLICATE_FILES=ON)" ) message(WARNING "${warning_message}") endif() @@ -3617,24 +3637,26 @@ function(qt6_target_qml_sources target) endif() set(qml_resource_name ${target}_raw_qml_${counter}) - set(qml_resource_targets) - set(qml_resource_options) - if(discard_qml_contents) - list(APPEND qml_resource_options DISCARD_FILE_CONTENTS) - endif() - qt6_add_resources(${target} ${qml_resource_name} - PREFIX ${arg_PREFIX} - FILES ${actual_QML_FILES} - OUTPUT_TARGETS qml_resource_targets - ${qml_resource_options} - ) - list(APPEND output_targets ${qml_resource_targets}) - # Save the resource name in a property so we can reference it later in a qml plugin - # constructor, to avoid discarding the resource if it's in a static library. - __qt_internal_sanitize_resource_name( - sanitized_qml_resource_name "${qml_resource_name}") - set_property(TARGET ${target} APPEND PROPERTY - _qt_qml_module_sanitized_resource_names "${sanitized_qml_resource_name}") + if(actual_QML_FILES) + set(qml_resource_targets "") + set(qml_resource_options "") + if(discard_qml_contents) + list(APPEND qml_resource_options DISCARD_FILE_CONTENTS) + endif() + qt6_add_resources(${target} ${qml_resource_name} + PREFIX ${arg_PREFIX} + FILES ${actual_QML_FILES} + OUTPUT_TARGETS qml_resource_targets + ${qml_resource_options} + ) + list(APPEND output_targets ${qml_resource_targets}) + # Save the resource name in a property so we can reference it later in a qml plugin + # constructor, to avoid discarding the resource if it's in a static library. + __qt_internal_sanitize_resource_name( + sanitized_qml_resource_name "${qml_resource_name}") + set_property(TARGET ${target} APPEND PROPERTY + _qt_qml_module_sanitized_resource_names "${sanitized_qml_resource_name}") + endif() if(actual_RESOURCES) set(resources_resource_name ${target}_raw_res_${counter}) diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index c4e0ea1b2b..803521fa63 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -1140,13 +1140,19 @@ QObject *QQmlComponentPrivate::beginCreate(QQmlRefPointer<QQmlContextData> conte m_state.ensureRequiredPropertyStorage(rv); } - for (int i = 0, propertyCount = propertyCache->propertyCount(); i < propertyCount; ++i) { - if (const QQmlPropertyData *propertyData = propertyCache->property(i); propertyData->isRequired()) { - m_state.ensureRequiredPropertyStorage(rv); - RequiredPropertyInfo info; - info.propertyName = propertyData->name(rv); - m_state.addPendingRequiredProperty(rv, propertyData, info); + if (propertyCache) { + for (int i = 0, propertyCount = propertyCache->propertyCount(); i < propertyCount; ++i) { + if (const QQmlPropertyData *propertyData = propertyCache->property(i); propertyData->isRequired()) { + m_state.ensureRequiredPropertyStorage(rv); + RequiredPropertyInfo info; + info.propertyName = propertyData->name(rv); + m_state.addPendingRequiredProperty(rv, propertyData, info); + } } + } else { + // we couldn't get a propertyCache from ensurePropertyCache + // it is unclear what we can do in that case + // ### TOOD: QTBUG-136560 } } diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index e267392a59..3bf22d77a4 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -311,6 +311,11 @@ void QQmlMetaType::clearTypeRegistrations() data->undeletableTypes.clear(); data->propertyCaches.clear(); + qDeleteAll(data->metaTypeToValueType); + data->metaTypeToValueType.clear(); + + data->moduleImports.clear(); + // Avoid deletion recursion (via QQmlTypePrivate dtor) by moving them out of the way first. QQmlMetaTypeData::CompositeTypes emptyComposites; emptyComposites.swap(data->compositeTypes); @@ -1862,6 +1867,9 @@ static bool isInternalType(int idx) bool QQmlMetaType::isValueType(QMetaType type) { + if (type.flags().testFlag(QMetaType::PointerToQObject)) + return false; + if (!type.isValid() || isInternalType(type.id())) return false; diff --git a/src/qmlcompiler/qqmljstypepropagator.cpp b/src/qmlcompiler/qqmljstypepropagator.cpp index c6fec6643c..88e16d8076 100644 --- a/src/qmlcompiler/qqmljstypepropagator.cpp +++ b/src/qmlcompiler/qqmljstypepropagator.cpp @@ -3092,6 +3092,16 @@ QQmlJSRegisterContent QQmlJSTypePropagator::propagateBinaryOperation(QSOperator: return type; } +static bool deepCompare(const QQmlJSRegisterContent &a, const QQmlJSRegisterContent &b) +{ + if (!a.isValid() && !b.isValid()) + return true; + + return a.containedType() == b.containedType() + && a.variant() == b.variant() + && deepCompare(a.scope(), b.scope()); +} + void QQmlJSTypePropagator::saveRegisterStateForJump(int offset) { auto jumpToOffset = offset + nextInstructionOffset(); @@ -3105,10 +3115,27 @@ void QQmlJSTypePropagator::saveRegisterStateForJump(int offset) const auto registerStates = m_jumpOriginRegisterStateByTargetInstructionOffset.equal_range(jumpToOffset); for (auto it = registerStates.first; it != registerStates.second; ++it) { - if (it->registers.keys() == state.registers.keys() - && it->registers.values() == state.registers.values()) { - return; // We've seen the same register state before. No need for merging. + if (it->registers.keys() != state.registers.keys()) + continue; + + const auto valuesIt = it->registers.values(); + const auto valuesState = state.registers.values(); + + bool different = false; + for (qsizetype i = 0, end = valuesIt.size(); i != end; ++i) { + const auto &valueIt = valuesIt[i]; + const auto &valueState = valuesState[i]; + if (valueIt.affectedBySideEffects != valueState.affectedBySideEffects + || valueIt.canMove != valueState.canMove + || valueIt.isShadowable != valueState.isShadowable + || !deepCompare(valueIt.content, valueState.content)) { + different = true; + break; + } } + + if (!different) + return; // We've seen the same register state before. No need for merging. } // The register state at the target offset needs to be resolved in a further pass. diff --git a/src/quick/doc/src/examples.qdoc b/src/quick/doc/src/examples.qdoc index da49c6e22e..aa6bbc5fe8 100644 --- a/src/quick/doc/src/examples.qdoc +++ b/src/quick/doc/src/examples.qdoc @@ -110,6 +110,7 @@ Creator. \li \l{Qt Quick Examples - Positioners}{Positioners} \li \l{Qt Quick Examples - Views}{Views} \li \l{Qt Quick Examples - Window and Screen}{Windows and Screen} + \li \l{Models and Views: List Model using a worker thread for data fetching}{Threaded List Model Example} \endlist \enddiv \div {class="doc-column"} diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp index e6ca6be9cb..9417bb9b3f 100644 --- a/src/quick/items/qquicktextedit.cpp +++ b/src/quick/items/qquicktextedit.cpp @@ -3316,6 +3316,18 @@ void QQuickTextEdit::focusOutEvent(QFocusEvent *event) QQuickImplicitSizeItem::focusOutEvent(event); } +#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) +bool QQuickTextEditPrivate::handleContextMenuEvent(QContextMenuEvent *event) +#else +bool QQuickTextEdit::contextMenuEvent(QContextMenuEvent *event) +#endif +{ + Q_Q(QQuickTextEdit); + QContextMenuEvent mapped(event->reason(), q->cursorRectangle().center().toPoint(), + event->globalPos(), event->modifiers()); + return QQuickItemPrivate::handleContextMenuEvent(&mapped); +} + void QQuickTextEditPrivate::handleFocusEvent(QFocusEvent *event) { Q_Q(QQuickTextEdit); diff --git a/src/quick/items/qquicktextedit_p.h b/src/quick/items/qquicktextedit_p.h index f44b373b5c..b3ea8ea183 100644 --- a/src/quick/items/qquicktextedit_p.h +++ b/src/quick/items/qquicktextedit_p.h @@ -406,6 +406,9 @@ protected: void mouseReleaseEvent(QMouseEvent *event) override; void mouseDoubleClickEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent *event) override; +#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) + bool contextMenuEvent(QContextMenuEvent *event) override; +#endif #if QT_CONFIG(im) void inputMethodEvent(QInputMethodEvent *e) override; #endif diff --git a/src/quick/items/qquicktextedit_p_p.h b/src/quick/items/qquicktextedit_p_p.h index 0a30117ea2..86a72ab0c4 100644 --- a/src/quick/items/qquicktextedit_p_p.h +++ b/src/quick/items/qquicktextedit_p_p.h @@ -129,6 +129,9 @@ public: #endif void setNativeCursorEnabled(bool) {} +#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) + bool handleContextMenuEvent(QContextMenuEvent *event) override; +#endif void handleFocusEvent(QFocusEvent *event); void addCurrentTextNodeToRoot(QQuickTextNodeEngine *, QSGTransformNode *, QSGInternalTextNode *, TextNodeIterator&, int startPos); QSGInternalTextNode* createTextNode(); diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index 1df9df6df5..1b8a8d3612 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -1718,6 +1718,18 @@ void QQuickTextInput::mouseReleaseEvent(QMouseEvent *event) QQuickImplicitSizeItem::mouseReleaseEvent(event); } +#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) +bool QQuickTextInputPrivate::handleContextMenuEvent(QContextMenuEvent *event) +#else +bool QQuickTextInput::contextMenuEvent(QContextMenuEvent *event) +#endif +{ + Q_Q(QQuickTextInput); + QContextMenuEvent mapped(event->reason(), q->cursorRectangle().center().toPoint(), + event->globalPos(), event->modifiers()); + return QQuickItemPrivate::handleContextMenuEvent(&mapped); +} + bool QQuickTextInputPrivate::sendMouseEventToInputContext(QMouseEvent *event) { #if QT_CONFIG(im) diff --git a/src/quick/items/qquicktextinput_p.h b/src/quick/items/qquicktextinput_p.h index 9eab7d1b80..35f505cbde 100644 --- a/src/quick/items/qquicktextinput_p.h +++ b/src/quick/items/qquicktextinput_p.h @@ -359,6 +359,9 @@ protected: void mouseReleaseEvent(QMouseEvent *event) override; void mouseDoubleClickEvent(QMouseEvent *event) override; void keyPressEvent(QKeyEvent* ev) override; +#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) + bool contextMenuEvent(QContextMenuEvent *event) override; +#endif #if QT_CONFIG(im) void inputMethodEvent(QInputMethodEvent *) override; #endif diff --git a/src/quick/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h index 63a8901547..028712abd1 100644 --- a/src/quick/items/qquicktextinput_p_p.h +++ b/src/quick/items/qquicktextinput_p_p.h @@ -150,6 +150,9 @@ public: bool determineHorizontalAlignment(); bool setHAlign(QQuickTextInput::HAlignment, bool forceAlign = false); void mirrorChange() override; +#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) + bool handleContextMenuEvent(QContextMenuEvent *event) override; +#endif bool sendMouseEventToInputContext(QMouseEvent *event); #if QT_CONFIG(im) Qt::InputMethodHints effectiveInputMethodHints() const; diff --git a/src/quick/scenegraph/qsgdefaultrendercontext.cpp b/src/quick/scenegraph/qsgdefaultrendercontext.cpp index 1b0753e9ae..6b0a8d6556 100644 --- a/src/quick/scenegraph/qsgdefaultrendercontext.cpp +++ b/src/quick/scenegraph/qsgdefaultrendercontext.cpp @@ -101,6 +101,14 @@ void QSGDefaultRenderContext::invalidate() qDeleteAll(m_textures); m_textures.clear(); + for (auto it = m_depthStencilBuffers.cbegin(), end = m_depthStencilBuffers.cend(); it != end; ++it) { + QSharedPointer<QSGDepthStencilBuffer> buf = it.value().toStrongRef(); + delete buf->ds; + buf->ds = nullptr; + buf->rc = nullptr; + } + m_depthStencilBuffers.clear(); + /* The cleanup of the atlas textures is a bit intriguing. As part of the cleanup in the threaded render loop, we do: @@ -296,6 +304,44 @@ void QSGDefaultRenderContext::resetGlyphCacheResources() m_pendingGlyphCacheTextures.clear(); } +QSGDepthStencilBuffer::~QSGDepthStencilBuffer() +{ + if (rc && ds) { + const auto key = std::pair(ds->pixelSize(), ds->sampleCount()); + rc->m_depthStencilBuffers.remove(key); + } + delete ds; +} + +QSharedPointer<QSGDepthStencilBuffer> QSGDefaultRenderContext::getDepthStencilBuffer(const QSize &size, int sampleCount) +{ + const auto key = std::pair(size, sampleCount); + auto it = m_depthStencilBuffers.constFind(key); + if (it != m_depthStencilBuffers.cend()) { + if (it.value()) + return it.value().toStrongRef(); + } + + QRhiRenderBuffer *ds = m_rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, size, sampleCount); + if (!ds->create()) { + qWarning("Failed to build depth-stencil buffer for layer"); + delete ds; + return {}; + } + QSharedPointer<QSGDepthStencilBuffer> buf(new QSGDepthStencilBuffer(ds)); + addDepthStencilBuffer(buf); + return buf; +} + +void QSGDefaultRenderContext::addDepthStencilBuffer(const QSharedPointer<QSGDepthStencilBuffer> &ds) +{ + if (ds) { + const auto key = std::pair(ds->ds->pixelSize(), ds->ds->sampleCount()); + ds->rc = this; + m_depthStencilBuffers.insert(key, ds.toWeakRef()); + } +} + QT_END_NAMESPACE #include "moc_qsgdefaultrendercontext_p.cpp" diff --git a/src/quick/scenegraph/qsgdefaultrendercontext_p.h b/src/quick/scenegraph/qsgdefaultrendercontext_p.h index c3352aa89f..be3d1c1312 100644 --- a/src/quick/scenegraph/qsgdefaultrendercontext_p.h +++ b/src/quick/scenegraph/qsgdefaultrendercontext_p.h @@ -25,13 +25,25 @@ class QRhiCommandBuffer; class QRhiRenderPassDescriptor; class QRhiResourceUpdateBatch; class QRhiTexture; +class QRhiRenderBuffer; class QSGMaterialShader; class QSurface; +class QSGDefaultRenderContext; namespace QSGRhiAtlasTexture { class Manager; } +class QSGDepthStencilBuffer +{ +public: + QSGDepthStencilBuffer() { } + QSGDepthStencilBuffer(QRhiRenderBuffer *ds) : ds(ds) { } + ~QSGDepthStencilBuffer(); + QRhiRenderBuffer *ds = nullptr; + QSGDefaultRenderContext *rc = nullptr; +}; + class Q_QUICK_EXPORT QSGDefaultRenderContext : public QSGRenderContext { Q_OBJECT @@ -107,6 +119,9 @@ public: void deferredReleaseGlyphCacheTexture(QRhiTexture *texture); void resetGlyphCacheResources(); + QSharedPointer<QSGDepthStencilBuffer> getDepthStencilBuffer(const QSize &size, int sampleCount); + void addDepthStencilBuffer(const QSharedPointer<QSGDepthStencilBuffer> &ds); + protected: InitParams m_initParams; QRhi *m_rhi; @@ -119,6 +134,9 @@ protected: QRhiResourceUpdateBatch *m_glyphCacheResourceUpdates; QSet<QRhiTexture *> m_pendingGlyphCacheTextures; QHash<FontKey, QSGCurveGlyphAtlas *> m_curveGlyphAtlases; + QHash<std::pair<QSize, int>, QWeakPointer<QSGDepthStencilBuffer>> m_depthStencilBuffers; + + friend class QSGDepthStencilBuffer; }; QT_END_NAMESPACE diff --git a/src/quick/scenegraph/qsgrhilayer.cpp b/src/quick/scenegraph/qsgrhilayer.cpp index 3ce7e5e81a..e802805d0d 100644 --- a/src/quick/scenegraph/qsgrhilayer.cpp +++ b/src/quick/scenegraph/qsgrhilayer.cpp @@ -5,7 +5,6 @@ #include <private/qqmlglobal_p.h> #include <private/qsgrenderer_p.h> -#include <private/qsgdefaultrendercontext_p.h> QSGRhiLayer::QSGRhiLayer(QSGRenderContext *context) : QSGLayer(*(new QSGTexturePrivate(this))) @@ -210,8 +209,7 @@ void QSGRhiLayer::releaseResources() delete m_rtRp; m_rtRp = nullptr; - delete m_ds; - m_ds = nullptr; + m_ds.clear(); delete m_msaaColorBuffer; m_msaaColorBuffer = nullptr; @@ -278,9 +276,8 @@ void QSGRhiLayer::grab() return; } if (depthBufferEnabled) { - m_ds = m_rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, m_pixelSize, effectiveSamples); - if (!m_ds->create()) { - qWarning("Failed to build depth-stencil buffer for layer"); + m_ds = m_context->getDepthStencilBuffer(m_pixelSize, effectiveSamples); + if (!m_ds) { releaseResources(); return; } @@ -290,7 +287,7 @@ void QSGRhiLayer::grab() color0.setResolveTexture(m_texture); desc.setColorAttachments({ color0 }); if (depthBufferEnabled) - desc.setDepthStencilBuffer(m_ds); + desc.setDepthStencilBuffer(m_ds->ds); m_rt = m_rhi->newTextureRenderTarget(desc); m_rtRp = m_rt->newCompatibleRenderPassDescriptor(); if (!m_rtRp) { @@ -313,9 +310,8 @@ void QSGRhiLayer::grab() return; } if (depthBufferEnabled) { - m_ds = m_rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, m_pixelSize); - if (!m_ds->create()) { - qWarning("Failed to build depth-stencil buffer for layer"); + m_ds = m_context->getDepthStencilBuffer(m_pixelSize, 1); + if (!m_ds) { releaseResources(); return; } @@ -332,10 +328,10 @@ void QSGRhiLayer::grab() } color0.setTexture(m_secondaryTexture); } + QRhiTextureRenderTargetDescription desc({ color0 }); if (depthBufferEnabled) - m_rt = m_rhi->newTextureRenderTarget({ color0, m_ds }); - else - m_rt = m_rhi->newTextureRenderTarget({ color0 }); + desc.setDepthStencilBuffer(m_ds->ds); + m_rt = m_rhi->newTextureRenderTarget(desc); m_rtRp = m_rt->newCompatibleRenderPassDescriptor(); if (!m_rtRp) { qWarning("Failed to build render pass descriptor for layer"); diff --git a/src/quick/scenegraph/qsgrhilayer_p.h b/src/quick/scenegraph/qsgrhilayer_p.h index 922192ec5e..d6d9165123 100644 --- a/src/quick/scenegraph/qsgrhilayer_p.h +++ b/src/quick/scenegraph/qsgrhilayer_p.h @@ -17,6 +17,7 @@ #include <private/qsgadaptationlayer_p.h> #include <private/qsgcontext_p.h> #include <private/qsgtexture_p.h> +#include <private/qsgdefaultrendercontext_p.h> #include <rhi/qrhi.h> QT_BEGIN_NAMESPACE @@ -73,7 +74,7 @@ private: QSGRenderer *m_renderer = nullptr; QRhiTexture *m_texture = nullptr; - QRhiRenderBuffer *m_ds = nullptr; + QSharedPointer<QSGDepthStencilBuffer> m_ds; QRhiRenderBuffer *m_msaaColorBuffer = nullptr; QRhiTexture *m_secondaryTexture = nullptr; QRhiTextureRenderTarget *m_rt = nullptr; diff --git a/src/quick/util/qquickdeliveryagent.cpp b/src/quick/util/qquickdeliveryagent.cpp index 1d6924f198..9301f64204 100644 --- a/src/quick/util/qquickdeliveryagent.cpp +++ b/src/quick/util/qquickdeliveryagent.cpp @@ -2943,7 +2943,10 @@ QVector<QQuickItem *> QQuickDeliveryAgentPrivate::contextMenuTargets(QQuickItem return std::nullopt; }; - return eventTargets(item, event, event->pos(), predicate); + const auto pos = event->pos().isNull() ? activeFocusItem->mapToScene({}).toPoint() : event->pos(); + if (event->pos().isNull()) + qCDebug(lcContextMenu) << "for QContextMenuEvent, active focus item is" << activeFocusItem << "@" << pos; + return eventTargets(item, event, pos, predicate); } /*! diff --git a/tests/auto/cmake/CMakeLists.txt b/tests/auto/cmake/CMakeLists.txt index 4d5ab1c2a7..a36bd5afc8 100644 --- a/tests/auto/cmake/CMakeLists.txt +++ b/tests/auto/cmake/CMakeLists.txt @@ -147,6 +147,8 @@ if(TARGET Qt::Qml) BUILD_OPTIONS -Drun=case_resources ${test_duplicate_files_extra_args} ) + + _qt_internal_test_expect_pass(test_separate_qml_and_resources) endif() if(TARGET Qt::Quick) diff --git a/tests/auto/cmake/test_separate_qml_and_resources/CMakeLists.txt b/tests/auto/cmake/test_separate_qml_and_resources/CMakeLists.txt new file mode 100644 index 0000000000..2c7a4f2dca --- /dev/null +++ b/tests/auto/cmake/test_separate_qml_and_resources/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.16) +project(test_separate_qml_and_resources LANGUAGES CXX) + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml Test) +qt_standard_project_setup(REQUIRES 6.10) + +qt_add_qml_module(MyQmlModule + STATIC + URI org.qt-project.test_separate_qml_and_resources + VERSION 1.0 +) + +qt_target_qml_sources(MyQmlModule + QML_FILES + Main.qml +) + +qt_target_qml_sources(MyQmlModule + RESOURCES + file.txt +) + +add_executable(app + main.cpp +) + +target_link_libraries(app PRIVATE MyQmlModule MyQmlModuleplugin) diff --git a/tests/auto/cmake/test_separate_qml_and_resources/Main.qml b/tests/auto/cmake/test_separate_qml_and_resources/Main.qml new file mode 100644 index 0000000000..c3bb793936 --- /dev/null +++ b/tests/auto/cmake/test_separate_qml_and_resources/Main.qml @@ -0,0 +1,7 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick + +Item { +} diff --git a/tests/auto/cmake/test_separate_qml_and_resources/file.txt b/tests/auto/cmake/test_separate_qml_and_resources/file.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/auto/cmake/test_separate_qml_and_resources/file.txt diff --git a/tests/auto/cmake/test_separate_qml_and_resources/main.cpp b/tests/auto/cmake/test_separate_qml_and_resources/main.cpp new file mode 100644 index 0000000000..ae0c99bb7d --- /dev/null +++ b/tests/auto/cmake/test_separate_qml_and_resources/main.cpp @@ -0,0 +1,4 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +int main() {} diff --git a/tests/auto/core/qqmlsettings/CMakeLists.txt b/tests/auto/core/qqmlsettings/CMakeLists.txt index 2a61b758dd..d1b76d8ea9 100644 --- a/tests/auto/core/qqmlsettings/CMakeLists.txt +++ b/tests/auto/core/qqmlsettings/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qqmlsettings LANGUAGES C CXX ASM) + project(tst_qqmlsettings LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/core/qqmlstandardpaths/CMakeLists.txt b/tests/auto/core/qqmlstandardpaths/CMakeLists.txt index 38aef62d82..12c0e28880 100644 --- a/tests/auto/core/qqmlstandardpaths/CMakeLists.txt +++ b/tests/auto/core/qqmlstandardpaths/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qqmlstandardpaths LANGUAGES C CXX ASM) + project(tst_qqmlstandardpaths LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/core/qqmlsysteminformation/CMakeLists.txt b/tests/auto/core/qqmlsysteminformation/CMakeLists.txt index 9d6e0d342b..5c2c72dec7 100644 --- a/tests/auto/core/qqmlsysteminformation/CMakeLists.txt +++ b/tests/auto/core/qqmlsysteminformation/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qqmlsysteminformation LANGUAGES C CXX ASM) + project(tst_qqmlsysteminformation LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt index f09a3af62f..bd00605eb2 100644 --- a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt +++ b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt @@ -56,6 +56,7 @@ set(qml_files Cycle2.qml Cycle3.qml CppMethodListReturnType.qml + DeduplicateConversionOrigins.qml Dummy.qml Dummy2.qml EditConstraint.qml diff --git a/tests/auto/qml/qmlcppcodegen/data/DeduplicateConversionOrigins.qml b/tests/auto/qml/qmlcppcodegen/data/DeduplicateConversionOrigins.qml new file mode 100644 index 0000000000..ba1ddb156b --- /dev/null +++ b/tests/auto/qml/qmlcppcodegen/data/DeduplicateConversionOrigins.qml @@ -0,0 +1,9 @@ +import QtQml + +QtObject { + function yep() { + try { } + catch (e) { replace(/()/, ""); } + for (let i = 0; i < 1; ++i) { } + } +} diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp index 81c68057ee..6f2a8f4b51 100644 --- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp +++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp @@ -93,6 +93,7 @@ private slots: void dateConstruction(); void dateConversions(); void deadShoeSize(); + void deduplicateConversionOrigins(); void destroyAndToString(); void detachOnAssignment(); void dialogButtonBox(); @@ -1618,6 +1619,15 @@ void tst_QmlCppCodegen::deadShoeSize() QCOMPARE(o->property("shoeSize").toInt(), 0); } +void tst_QmlCppCodegen::deduplicateConversionOrigins() +{ + QQmlEngine engine; + QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/DeduplicateConversionOrigins.qml"_s)); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer<QObject> o(c.create()); + QVERIFY(o); +} + void tst_QmlCppCodegen::destroyAndToString() { QQmlEngine engine; diff --git a/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt b/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt index 3eab68a7e7..3bb8133e9b 100644 --- a/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt +++ b/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt @@ -33,9 +33,7 @@ set(qml_sources simpleQtQuickTypes.qml typeWithEnums.qml methods.qml - properties.qml ObjectWithId.qml - documentWithIds.qml importNamespace.qml gradients.qml qjsvalueAssignments.qml @@ -161,6 +159,13 @@ set(common_libraries Qt::Gui # QColor, QMatrix4x4, ... ) +if(QT_FEATURE_quick_tableview) + list(APPEND qml_sources properties.qml) + if(QT_FEATURE_quick_gridview) + list(APPEND qml_sources documentWithIds.qml) + endif() +endif() + if (QT_FEATURE_qml_table_model) list(APPEND qml_sources QmlTableModel.qml) list(APPEND common_libraries Qt::LabsQmlModelsPrivate) diff --git a/tests/auto/qml/qmltc/tst_qmltc.cpp b/tests/auto/qml/qmltc/tst_qmltc.cpp index 73ef03eaaf..d2fcab4658 100644 --- a/tests/auto/qml/qmltc/tst_qmltc.cpp +++ b/tests/auto/qml/qmltc/tst_qmltc.cpp @@ -9,9 +9,13 @@ #include "simpleqtquicktypes.h" #include "typewithenums.h" #include "methods.h" +#if QT_CONFIG(quick_tableview) #include "properties.h" +#endif #include "objectwithid.h" +#if QT_CONFIG(quick_gridview) #include "documentwithids.h" +#endif #include "importnamespace.h" #include "deferredproperties.h" #include "deferredproperties_group.h" @@ -87,7 +91,9 @@ #include "mysignals.h" #include "namespacedtypes.h" #include "type.h" +#if QT_CONFIG(qml_table_model) #include "qmltablemodel.h" +#endif #include "stringtourl.h" #include "signalconnections.h" #include "requiredproperties.h" @@ -334,6 +340,7 @@ void tst_qmltc::methods() QCOMPARE(metaTypedMethod.parameterNames(), QList<QByteArray>({ "a", "b" })); } +#if QT_CONFIG(quick_tableview) void tst_qmltc::properties() { QQmlEngine e; @@ -478,7 +485,9 @@ void tst_qmltc::properties() QVERIFY(sentinelForComponent); QCOMPARE(sentinelForComponent->property("text").toString(), u"should be correctly created"_s); } +#endif // QT_CONFIG(quick_tableview) +#if QT_CONFIG(quick_tableview) && QT_CONFIG(quick_gridview) void tst_qmltc::ids() { { @@ -575,6 +584,7 @@ void tst_qmltc::ids() verifyComponent(afterChild, QString(), u"afterDelegateDefaultPropertyText"_s); } } +#endif // QT_CONFIG(quick_tableview) && QT_CONFIG(quick_gridview) void tst_qmltc::importNamespace() { diff --git a/tests/auto/qml/qmltc/tst_qmltc.h b/tests/auto/qml/qmltc/tst_qmltc.h index 99abb60dc5..17a464bdb2 100644 --- a/tests/auto/qml/qmltc/tst_qmltc.h +++ b/tests/auto/qml/qmltc/tst_qmltc.h @@ -3,6 +3,7 @@ #include <qtest.h> #include <private/qtqmlmodelsglobal_p.h> +#include <private/qtquick-config_p.h> // For feature definitions using namespace Qt::StringLiterals; @@ -27,8 +28,12 @@ private slots: void qtQuickIncludes(); void enumerations(); void methods(); +#if QT_CONFIG(quick_tableview) void properties(); +#if QT_CONFIG(quick_gridview) void ids(); +#endif +#endif void importNamespace(); void deferredProperties(); void gradients(); // QTBUG-102560 diff --git a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp index f6869ab300..d14e0b76a4 100644 --- a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp +++ b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp @@ -1563,11 +1563,53 @@ struct SingleRequiredProperty : QObject int i = 42; }; + +struct SingleRequiredPropertyDynamic : QObject +{ + Q_OBJECT + Q_PROPERTY(int i MEMBER i REQUIRED) + + int i = 42; + + class QObjectDynamicMetaObject : public QDynamicMetaObjectData + { + public: + #if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) + const QMetaObject *toDynamicMetaObject(QObject *) const final + { + return &SingleRequiredPropertyDynamic::staticMetaObject; + } + #else + QMetaObject *toDynamicMetaObject(QObject *) final + { + return const_cast<QMetaObject *>(&SingleRequiredPropertyDynamic::staticMetaObject); + } + #endif + int metaCall(QObject *o, QMetaObject::Call c, int id, void **argv) final + { + return o->qt_metacall(c, id, argv); + } + }; + +public: + SingleRequiredPropertyDynamic() { + auto priv = QObjectPrivate::get(this); + priv->metaObject = new QObjectDynamicMetaObject; + } + + ~SingleRequiredPropertyDynamic() { + auto priv = QObjectPrivate::get(this); + delete priv->metaObject; + priv->metaObject = nullptr ; + } +}; + void tst_qqmlcomponent::loadFromModuleRequired() { QQmlEngine engine; qmlRegisterType<SingleRequiredProperty>("qqmlcomponenttest", 1, 0, "SingleRequiredProperty"); + qmlRegisterType<SingleRequiredPropertyDynamic>("qqmlcomponenttest", 1, 0, "SingleRequiredPropertyDynamic"); const QString error = QStringLiteral("Required property i was not initialized"); { QQmlComponent component(&engine, "qqmlcomponenttest", "SingleRequiredProperty"); @@ -1591,6 +1633,13 @@ void tst_qqmlcomponent::loadFromModuleRequired() QVERIFY(component.isError()); QCOMPARE(component.errorString(), qPrintable(":-1 " + error + "\n")); } + { + QQmlComponent component(&engine, "qqmlcomponenttest", "SingleRequiredPropertyDynamic"); + QVERIFY2(!component.isError(), qPrintable(component.errorString())); + QScopedPointer<QObject> root(component.create()); + QEXPECT_FAIL("", "Can't check required properties when there's a dynamic metaobject", Continue); + QVERIFY(!root); + } } void tst_qqmlcomponent::loadUrlRequired() diff --git a/tests/auto/qmlnetwork/qqmlnetworkinformation/CMakeLists.txt b/tests/auto/qmlnetwork/qqmlnetworkinformation/CMakeLists.txt index 576a434773..1d729468af 100644 --- a/tests/auto/qmlnetwork/qqmlnetworkinformation/CMakeLists.txt +++ b/tests/auto/qmlnetwork/qqmlnetworkinformation/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qqmlnetworkinformation LANGUAGES C CXX ASM) + project(tst_qqmlnetworkinformation LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/accessibility/CMakeLists.txt b/tests/auto/quickcontrols/accessibility/CMakeLists.txt index 2ae2aec45b..0aa8911f4a 100644 --- a/tests/auto/quickcontrols/accessibility/CMakeLists.txt +++ b/tests/auto/quickcontrols/accessibility/CMakeLists.txt @@ -5,7 +5,7 @@ if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_accessibility LANGUAGES C CXX ASM) + project(tst_accessibility LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/controls/basic/CMakeLists.txt b/tests/auto/quickcontrols/controls/basic/CMakeLists.txt index daafef324f..3ff5924047 100644 --- a/tests/auto/quickcontrols/controls/basic/CMakeLists.txt +++ b/tests/auto/quickcontrols/controls/basic/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_basic LANGUAGES C CXX ASM) + project(tst_basic LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/controls/fluentwinui3/CMakeLists.txt b/tests/auto/quickcontrols/controls/fluentwinui3/CMakeLists.txt index e77bd78674..32cd4902c2 100644 --- a/tests/auto/quickcontrols/controls/fluentwinui3/CMakeLists.txt +++ b/tests/auto/quickcontrols/controls/fluentwinui3/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_fluentwinui3 LANGUAGES C CXX ASM) + project(tst_fluentwinui3 LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/controls/fusion/CMakeLists.txt b/tests/auto/quickcontrols/controls/fusion/CMakeLists.txt index 2e077988b7..a4b797c77c 100644 --- a/tests/auto/quickcontrols/controls/fusion/CMakeLists.txt +++ b/tests/auto/quickcontrols/controls/fusion/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_fusion LANGUAGES C CXX ASM) + project(tst_fusion LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/controls/imagine/CMakeLists.txt b/tests/auto/quickcontrols/controls/imagine/CMakeLists.txt index f11edec156..f1d0187d10 100644 --- a/tests/auto/quickcontrols/controls/imagine/CMakeLists.txt +++ b/tests/auto/quickcontrols/controls/imagine/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_imagine LANGUAGES C CXX ASM) + project(tst_imagine LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/controls/ios/CMakeLists.txt b/tests/auto/quickcontrols/controls/ios/CMakeLists.txt index 566ad33678..eab16c1b44 100644 --- a/tests/auto/quickcontrols/controls/ios/CMakeLists.txt +++ b/tests/auto/quickcontrols/controls/ios/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_ios LANGUAGES C CXX ASM) + project(tst_ios LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/controls/macos/CMakeLists.txt b/tests/auto/quickcontrols/controls/macos/CMakeLists.txt index 94557222e1..ef04f1cba0 100644 --- a/tests/auto/quickcontrols/controls/macos/CMakeLists.txt +++ b/tests/auto/quickcontrols/controls/macos/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_macos LANGUAGES C CXX ASM) + project(tst_macos LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/controls/material/CMakeLists.txt b/tests/auto/quickcontrols/controls/material/CMakeLists.txt index 912c49566a..63aa92e378 100644 --- a/tests/auto/quickcontrols/controls/material/CMakeLists.txt +++ b/tests/auto/quickcontrols/controls/material/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_material LANGUAGES C CXX ASM) + project(tst_material LANGUAGES C CXX) find_package(Qt6 REQUIRED COMPONENTS ShaderTools) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/controls/universal/CMakeLists.txt b/tests/auto/quickcontrols/controls/universal/CMakeLists.txt index 218302da2d..8519c6f2c4 100644 --- a/tests/auto/quickcontrols/controls/universal/CMakeLists.txt +++ b/tests/auto/quickcontrols/controls/universal/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_universal LANGUAGES C CXX ASM) + project(tst_universal LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/controls/windows/CMakeLists.txt b/tests/auto/quickcontrols/controls/windows/CMakeLists.txt index 447b89df1a..d57fb0a699 100644 --- a/tests/auto/quickcontrols/controls/windows/CMakeLists.txt +++ b/tests/auto/quickcontrols/controls/windows/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_windows LANGUAGES C CXX ASM) + project(tst_windows LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/cursor/CMakeLists.txt b/tests/auto/quickcontrols/cursor/CMakeLists.txt index 8247ef1f44..46cb2d5743 100644 --- a/tests/auto/quickcontrols/cursor/CMakeLists.txt +++ b/tests/auto/quickcontrols/cursor/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_cursor LANGUAGES C CXX ASM) + project(tst_cursor LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/customization/CMakeLists.txt b/tests/auto/quickcontrols/customization/CMakeLists.txt index 9dff827989..6b45d891d0 100644 --- a/tests/auto/quickcontrols/customization/CMakeLists.txt +++ b/tests/auto/quickcontrols/customization/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_customization LANGUAGES C CXX ASM) + project(tst_customization LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/designer/CMakeLists.txt b/tests/auto/quickcontrols/designer/CMakeLists.txt index 5157ad562a..8c26be8ae8 100644 --- a/tests/auto/quickcontrols/designer/CMakeLists.txt +++ b/tests/auto/quickcontrols/designer/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_designer LANGUAGES C CXX ASM) + project(tst_designer LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/focus/CMakeLists.txt b/tests/auto/quickcontrols/focus/CMakeLists.txt index 25948ffa9f..f83397c4f6 100644 --- a/tests/auto/quickcontrols/focus/CMakeLists.txt +++ b/tests/auto/quickcontrols/focus/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_focus LANGUAGES C CXX ASM) + project(tst_focus LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/font/CMakeLists.txt b/tests/auto/quickcontrols/font/CMakeLists.txt index cc8aff01b2..5dc79e8869 100644 --- a/tests/auto/quickcontrols/font/CMakeLists.txt +++ b/tests/auto/quickcontrols/font/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_font LANGUAGES C CXX ASM) + project(tst_font LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/palette/CMakeLists.txt b/tests/auto/quickcontrols/palette/CMakeLists.txt index a89c35638d..639beebbbd 100644 --- a/tests/auto/quickcontrols/palette/CMakeLists.txt +++ b/tests/auto/quickcontrols/palette/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_palette LANGUAGES C CXX ASM) + project(tst_palette LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/platform/CMakeLists.txt b/tests/auto/quickcontrols/platform/CMakeLists.txt index 5669052475..7bbe41ac44 100644 --- a/tests/auto/quickcontrols/platform/CMakeLists.txt +++ b/tests/auto/quickcontrols/platform/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_platform LANGUAGES C CXX ASM) + project(tst_platform LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/pointerhandlers/CMakeLists.txt b/tests/auto/quickcontrols/pointerhandlers/CMakeLists.txt index 7839d1644e..076e4273df 100644 --- a/tests/auto/quickcontrols/pointerhandlers/CMakeLists.txt +++ b/tests/auto/quickcontrols/pointerhandlers/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_pointerhandlers LANGUAGES C CXX ASM) + project(tst_pointerhandlers LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/pressandhold/CMakeLists.txt b/tests/auto/quickcontrols/pressandhold/CMakeLists.txt index 88213edbf3..fdbfd43d7d 100644 --- a/tests/auto/quickcontrols/pressandhold/CMakeLists.txt +++ b/tests/auto/quickcontrols/pressandhold/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_pressandhold LANGUAGES C CXX ASM) + project(tst_pressandhold LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickapplicationwindow/CMakeLists.txt b/tests/auto/quickcontrols/qquickapplicationwindow/CMakeLists.txt index cdabbed6c0..1b5a5bcda7 100644 --- a/tests/auto/quickcontrols/qquickapplicationwindow/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickapplicationwindow/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickapplicationwindow LANGUAGES C CXX ASM) + project(tst_qquickapplicationwindow LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickcolor/CMakeLists.txt b/tests/auto/quickcontrols/qquickcolor/CMakeLists.txt index 9cf98b4c84..b76d3ed030 100644 --- a/tests/auto/quickcontrols/qquickcolor/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickcolor/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickcolor LANGUAGES C CXX ASM) + project(tst_qquickcolor LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickcontainer/CMakeLists.txt b/tests/auto/quickcontrols/qquickcontainer/CMakeLists.txt index c79e508cd1..c04b31a415 100644 --- a/tests/auto/quickcontrols/qquickcontainer/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickcontainer/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickcontainer LANGUAGES C CXX ASM) + project(tst_qquickcontainer LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickcontextmenu/CMakeLists.txt b/tests/auto/quickcontrols/qquickcontextmenu/CMakeLists.txt index b6969a1bbf..693e69ba03 100644 --- a/tests/auto/quickcontrols/qquickcontextmenu/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickcontextmenu/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickcontextmenu LANGUAGES C CXX ASM) + project(tst_qquickcontextmenu LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickcontextmenu/data/textControlsAndParentMenus.qml b/tests/auto/quickcontrols/qquickcontextmenu/data/textControlsAndParentMenus.qml new file mode 100644 index 0000000000..a22d026e0b --- /dev/null +++ b/tests/auto/quickcontrols/qquickcontextmenu/data/textControlsAndParentMenus.qml @@ -0,0 +1,38 @@ +import QtQuick +import QtQuick.Controls + +ApplicationWindow { + id: window + width: 600 + height: 400 + + TextArea { + id: textArea + objectName: "textArea" + text: qsTr("Some, well, text here (surprise!)") + width: parent.width + height: parent.height / 3 + } + + TextField { + objectName: "textField" + text: qsTr("A not-so-vast partially-open field") + width: parent.width + y: parent.height * 2 / 3 + } + + contentItem.ContextMenu.menu: Menu { + id: windowMenu + objectName: "windowMenu" + + MenuItem { + text: qsTr("Open window") + } + MenuItem { + text: qsTr("Wash window") + } + MenuItem { + text: qsTr("Admire the view") + } + } +} diff --git a/tests/auto/quickcontrols/qquickcontextmenu/tst_qquickcontextmenu.cpp b/tests/auto/quickcontrols/qquickcontextmenu/tst_qquickcontextmenu.cpp index 40a33b3a35..5b40fc56d6 100644 --- a/tests/auto/quickcontrols/qquickcontextmenu/tst_qquickcontextmenu.cpp +++ b/tests/auto/quickcontrols/qquickcontextmenu/tst_qquickcontextmenu.cpp @@ -37,6 +37,7 @@ private slots: void drawerShouldntPreventOpening(); void explicitMenuPreventsBuiltInMenu(); void menuItemShouldntTriggerOnRelease(); + void textControlsMenuKey(); private: bool contextMenuTriggeredOnRelease = false; @@ -350,6 +351,53 @@ void tst_QQuickContextMenu::menuItemShouldntTriggerOnRelease() // QTBUG-133302 QCOMPARE(triggeredSpy.size(), 0); } +void tst_QQuickContextMenu::textControlsMenuKey() +{ + QQuickApplicationHelper helper(this, "textControlsAndParentMenus.qml"); + QVERIFY2(helper.ready, helper.failureMessage()); + QQuickWindow *window = helper.window; + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + auto *textArea = window->findChild<QQuickItem *>("textArea"); + QVERIFY(textArea); + auto *textField = window->findChild<QQuickItem *>("textField"); + QVERIFY(textField); + auto *windowMenu = window->findChild<QQuickMenu *>("windowMenu"); + QVERIFY(windowMenu); + const QPoint &windowCenter = mapCenterToWindow(window->contentItem()); + + // give position in the middle of the window: expect the window menu + { + QContextMenuEvent cme(QContextMenuEvent::Keyboard, windowCenter, window->mapToGlobal(windowCenter)); + QGuiApplication::sendEvent(window, &cme); + auto *openMenu = window->findChild<QQuickMenu *>(); + QVERIFY(openMenu); + QCOMPARE(openMenu->objectName(), "windowMenu"); + openMenu->close(); + } + + // focus the TextArea and give position 0, 0: expect the TextArea's menu + { + textArea->forceActiveFocus(); + QContextMenuEvent cme(QContextMenuEvent::Keyboard, {}, window->mapToGlobal(QPoint())); + QGuiApplication::sendEvent(window, &cme); + auto *openMenu = textArea->findChild<QQuickMenu *>(); + QVERIFY(openMenu); + openMenu->close(); + } + + // focus the TextField and give position 0, 0: expect the TextField's menu + { + textField->forceActiveFocus(); + QContextMenuEvent cme(QContextMenuEvent::Keyboard, {}, window->mapToGlobal(QPoint())); + QGuiApplication::sendEvent(window, &cme); + auto *openMenu = textField->findChild<QQuickMenu *>(); + QVERIFY(openMenu); + openMenu->close(); + } +} + QTEST_QUICKCONTROLS_MAIN(tst_QQuickContextMenu) #include "tst_qquickcontextmenu.moc" diff --git a/tests/auto/quickcontrols/qquickcontrol/CMakeLists.txt b/tests/auto/quickcontrols/qquickcontrol/CMakeLists.txt index e3ddf163bd..139f78379d 100644 --- a/tests/auto/quickcontrols/qquickcontrol/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickcontrol/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickcontrol LANGUAGES C CXX ASM) + project(tst_qquickcontrol LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickdrawer/CMakeLists.txt b/tests/auto/quickcontrols/qquickdrawer/CMakeLists.txt index 107d9b63fb..77ac0e23c5 100644 --- a/tests/auto/quickcontrols/qquickdrawer/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickdrawer/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickdrawer LANGUAGES C CXX ASM) + project(tst_qquickdrawer LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickheaderview/CMakeLists.txt b/tests/auto/quickcontrols/qquickheaderview/CMakeLists.txt index 6c01ba6e25..a1b143b11f 100644 --- a/tests/auto/quickcontrols/qquickheaderview/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickheaderview/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickheaderview LANGUAGES C CXX ASM) + project(tst_qquickheaderview LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickheaderviewdelegate/CMakeLists.txt b/tests/auto/quickcontrols/qquickheaderviewdelegate/CMakeLists.txt index 4a302dc8b7..730f7b6516 100644 --- a/tests/auto/quickcontrols/qquickheaderviewdelegate/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickheaderviewdelegate/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickheaderviewdelegate LANGUAGES C CXX ASM) + project(tst_qquickheaderviewdelegate LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickiconimage/CMakeLists.txt b/tests/auto/quickcontrols/qquickiconimage/CMakeLists.txt index 369570e3d0..0cd49b93f5 100644 --- a/tests/auto/quickcontrols/qquickiconimage/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickiconimage/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickiconimage LANGUAGES C CXX ASM) + project(tst_qquickiconimage LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickiconlabel/CMakeLists.txt b/tests/auto/quickcontrols/qquickiconlabel/CMakeLists.txt index 66add1069d..4ed2f63d90 100644 --- a/tests/auto/quickcontrols/qquickiconlabel/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickiconlabel/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickiconlabel LANGUAGES C CXX ASM) + project(tst_qquickiconlabel LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickimaginestyle/CMakeLists.txt b/tests/auto/quickcontrols/qquickimaginestyle/CMakeLists.txt index 91df77c5c9..d33f0cff3a 100644 --- a/tests/auto/quickcontrols/qquickimaginestyle/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickimaginestyle/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickimaginestyle LANGUAGES C CXX ASM) + project(tst_qquickimaginestyle LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickmaterialstyle/CMakeLists.txt b/tests/auto/quickcontrols/qquickmaterialstyle/CMakeLists.txt index 452311019f..75b11b340a 100644 --- a/tests/auto/quickcontrols/qquickmaterialstyle/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickmaterialstyle/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickmaterialstyle LANGUAGES C CXX ASM) + project(tst_qquickmaterialstyle LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickmaterialstyleconf/CMakeLists.txt b/tests/auto/quickcontrols/qquickmaterialstyleconf/CMakeLists.txt index 575d7f6990..ea62f25e09 100644 --- a/tests/auto/quickcontrols/qquickmaterialstyleconf/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickmaterialstyleconf/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickmaterialstyleconf LANGUAGES C CXX ASM) + project(tst_qquickmaterialstyleconf LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickmenu/CMakeLists.txt b/tests/auto/quickcontrols/qquickmenu/CMakeLists.txt index 5fec9625e6..8014429ae4 100644 --- a/tests/auto/quickcontrols/qquickmenu/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickmenu/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickmenu LANGUAGES C CXX ASM) + project(tst_qquickmenu LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickmenubar/CMakeLists.txt b/tests/auto/quickcontrols/qquickmenubar/CMakeLists.txt index df6d3f1be6..a1e70b82be 100644 --- a/tests/auto/quickcontrols/qquickmenubar/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickmenubar/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickmenubar LANGUAGES C CXX ASM) + project(tst_qquickmenubar LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickninepatchimage/CMakeLists.txt b/tests/auto/quickcontrols/qquickninepatchimage/CMakeLists.txt index 003bdd7725..45579ddde5 100644 --- a/tests/auto/quickcontrols/qquickninepatchimage/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickninepatchimage/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickninepatchimage LANGUAGES C CXX ASM) + project(tst_qquickninepatchimage LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickoverlay/CMakeLists.txt b/tests/auto/quickcontrols/qquickoverlay/CMakeLists.txt index dca782642e..cf48739acb 100644 --- a/tests/auto/quickcontrols/qquickoverlay/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickoverlay/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickpopup LANGUAGES C CXX ASM) + project(tst_qquickpopup LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickpopup/CMakeLists.txt b/tests/auto/quickcontrols/qquickpopup/CMakeLists.txt index e9a39e137c..49a1580d81 100644 --- a/tests/auto/quickcontrols/qquickpopup/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickpopup/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickpopup LANGUAGES C CXX ASM) + project(tst_qquickpopup LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickstyle/CMakeLists.txt b/tests/auto/quickcontrols/qquickstyle/CMakeLists.txt index e75ae59ecc..2c8e59b274 100644 --- a/tests/auto/quickcontrols/qquickstyle/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickstyle/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickstyle LANGUAGES C CXX ASM) + project(tst_qquickstyle LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquicktableviewdelegate/CMakeLists.txt b/tests/auto/quickcontrols/qquicktableviewdelegate/CMakeLists.txt index 9f045719ac..e044aba3a8 100644 --- a/tests/auto/quickcontrols/qquicktableviewdelegate/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquicktableviewdelegate/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquicktableviewdelegate LANGUAGES C CXX ASM) + project(tst_qquicktableviewdelegate LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquicktextarea/CMakeLists.txt b/tests/auto/quickcontrols/qquicktextarea/CMakeLists.txt index b9db57d51e..5aa934becc 100644 --- a/tests/auto/quickcontrols/qquicktextarea/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquicktextarea/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquicktextarea LANGUAGES C CXX ASM) + project(tst_qquicktextarea LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquicktextfield/CMakeLists.txt b/tests/auto/quickcontrols/qquicktextfield/CMakeLists.txt index 1cad180ef5..5eb3dbec83 100644 --- a/tests/auto/quickcontrols/qquicktextfield/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquicktextfield/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquicktextfield LANGUAGES C CXX ASM) + project(tst_qquicktextfield LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquicktreeviewdelegate/CMakeLists.txt b/tests/auto/quickcontrols/qquicktreeviewdelegate/CMakeLists.txt index 1bfe33f2cb..8f96364489 100644 --- a/tests/auto/quickcontrols/qquicktreeviewdelegate/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquicktreeviewdelegate/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquicktreeviewdelegate LANGUAGES C CXX ASM) + project(tst_qquicktreeviewdelegate LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickuniversalstyle/CMakeLists.txt b/tests/auto/quickcontrols/qquickuniversalstyle/CMakeLists.txt index 2d5426402c..6a281b5e4c 100644 --- a/tests/auto/quickcontrols/qquickuniversalstyle/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickuniversalstyle/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickuniversalstyle LANGUAGES C CXX ASM) + project(tst_qquickuniversalstyle LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickuniversalstyleconf/CMakeLists.txt b/tests/auto/quickcontrols/qquickuniversalstyleconf/CMakeLists.txt index 6a2c41ebb5..348a9ecefc 100644 --- a/tests/auto/quickcontrols/qquickuniversalstyleconf/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickuniversalstyleconf/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickuniversalstyleconf LANGUAGES C CXX ASM) + project(tst_qquickuniversalstyleconf LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/revisions/CMakeLists.txt b/tests/auto/quickcontrols/revisions/CMakeLists.txt index 2dc13eb887..6be38988a0 100644 --- a/tests/auto/quickcontrols/revisions/CMakeLists.txt +++ b/tests/auto/quickcontrols/revisions/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_revisions LANGUAGES C CXX ASM) + project(tst_revisions LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/sanity/CMakeLists.txt b/tests/auto/quickcontrols/sanity/CMakeLists.txt index bf9a061be7..2b50a02df4 100644 --- a/tests/auto/quickcontrols/sanity/CMakeLists.txt +++ b/tests/auto/quickcontrols/sanity/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_sanity LANGUAGES C CXX ASM) + project(tst_sanity LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/snippets/CMakeLists.txt b/tests/auto/quickcontrols/snippets/CMakeLists.txt index 37a4b67e49..40732eb84f 100644 --- a/tests/auto/quickcontrols/snippets/CMakeLists.txt +++ b/tests/auto/quickcontrols/snippets/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_snippets LANGUAGES C CXX ASM) + project(tst_snippets LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/styleimports/CMakeLists.txt b/tests/auto/quickcontrols/styleimports/CMakeLists.txt index b70031c3c3..9b8b05970d 100644 --- a/tests/auto/quickcontrols/styleimports/CMakeLists.txt +++ b/tests/auto/quickcontrols/styleimports/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_styleimports LANGUAGES C CXX ASM) + project(tst_styleimports LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/styleimportscompiletimematerial/CMakeLists.txt b/tests/auto/quickcontrols/styleimportscompiletimematerial/CMakeLists.txt index 69238c2bbd..d4fdcffe1a 100644 --- a/tests/auto/quickcontrols/styleimportscompiletimematerial/CMakeLists.txt +++ b/tests/auto/quickcontrols/styleimportscompiletimematerial/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_styleimportscompiletimematerial LANGUAGES C CXX ASM) + project(tst_styleimportscompiletimematerial LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/styleimportscompiletimeqmlonly/CMakeLists.txt b/tests/auto/quickcontrols/styleimportscompiletimeqmlonly/CMakeLists.txt index 11b4de75a7..3940aee987 100644 --- a/tests/auto/quickcontrols/styleimportscompiletimeqmlonly/CMakeLists.txt +++ b/tests/auto/quickcontrols/styleimportscompiletimeqmlonly/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_styleimportscompiletimeqmlonly LANGUAGES C CXX ASM) + project(tst_styleimportscompiletimeqmlonly LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/translation/CMakeLists.txt b/tests/auto/quickcontrols/translation/CMakeLists.txt index e56f3decb3..c4984e41f4 100644 --- a/tests/auto/quickcontrols/translation/CMakeLists.txt +++ b/tests/auto/quickcontrols/translation/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_translation LANGUAGES C CXX ASM) + project(tst_translation LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/benchmarks/quickcontrols/creationtime/CMakeLists.txt b/tests/benchmarks/quickcontrols/creationtime/CMakeLists.txt index b719e8148f..f877fedb1f 100644 --- a/tests/benchmarks/quickcontrols/creationtime/CMakeLists.txt +++ b/tests/benchmarks/quickcontrols/creationtime/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_creationtime LANGUAGES C CXX ASM) + project(tst_creationtime LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/benchmarks/quickcontrols/objectcount/CMakeLists.txt b/tests/benchmarks/quickcontrols/objectcount/CMakeLists.txt index 65fdf74a2c..251b60059f 100644 --- a/tests/benchmarks/quickcontrols/objectcount/CMakeLists.txt +++ b/tests/benchmarks/quickcontrols/objectcount/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_objectcount LANGUAGES C CXX ASM) + project(tst_objectcount LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/fontfeatures/CMakeLists.txt b/tests/manual/fontfeatures/CMakeLists.txt index 7938d64803..9f829e9a0c 100644 --- a/tests/manual/fontfeatures/CMakeLists.txt +++ b/tests/manual/fontfeatures/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(fontfeatures LANGUAGES C CXX ASM) + project(fontfeatures LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/listview/reuseItems/CMakeLists.txt b/tests/manual/listview/reuseItems/CMakeLists.txt index 81becfb9df..5362612ec4 100644 --- a/tests/manual/listview/reuseItems/CMakeLists.txt +++ b/tests/manual/listview/reuseItems/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(listview LANGUAGES C CXX ASM) + project(listview LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/painterpathquickshape/CMakeLists.txt b/tests/manual/painterpathquickshape/CMakeLists.txt index 4677fad26c..beb26a7569 100644 --- a/tests/manual/painterpathquickshape/CMakeLists.txt +++ b/tests/manual/painterpathquickshape/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.16) if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) - project(painterPathQuickShape LANGUAGES C CXX ASM) + project(painterPathQuickShape LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/quickcontrols/buttons/CMakeLists.txt b/tests/manual/quickcontrols/buttons/CMakeLists.txt index 048645b43f..31d01abc7c 100644 --- a/tests/manual/quickcontrols/buttons/CMakeLists.txt +++ b/tests/manual/quickcontrols/buttons/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(buttons LANGUAGES C CXX ASM) + project(buttons LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/quickcontrols/fonts/CMakeLists.txt b/tests/manual/quickcontrols/fonts/CMakeLists.txt index 476b7f1a7a..4ef977e518 100644 --- a/tests/manual/quickcontrols/fonts/CMakeLists.txt +++ b/tests/manual/quickcontrols/fonts/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(fonts LANGUAGES C CXX ASM) + project(fonts LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/quickcontrols/gifs/CMakeLists.txt b/tests/manual/quickcontrols/gifs/CMakeLists.txt index 674806e145..deb982dc18 100644 --- a/tests/manual/quickcontrols/gifs/CMakeLists.txt +++ b/tests/manual/quickcontrols/gifs/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_gifs LANGUAGES C CXX ASM) + project(tst_gifs LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/quickcontrols/headerview/CMakeLists.txt b/tests/manual/quickcontrols/headerview/CMakeLists.txt index fd00f693c8..1973f1a2fd 100644 --- a/tests/manual/quickcontrols/headerview/CMakeLists.txt +++ b/tests/manual/quickcontrols/headerview/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(headerview LANGUAGES C CXX ASM) + project(headerview LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/quickcontrols/material/CMakeLists.txt b/tests/manual/quickcontrols/material/CMakeLists.txt index 8c18341bbe..232771b88e 100644 --- a/tests/manual/quickcontrols/material/CMakeLists.txt +++ b/tests/manual/quickcontrols/material/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(material LANGUAGES C CXX ASM) + project(material LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/quickcontrols/qquickdialog/CMakeLists.txt b/tests/manual/quickcontrols/qquickdialog/CMakeLists.txt index 232dae7ffa..d2322ed934 100644 --- a/tests/manual/quickcontrols/qquickdialog/CMakeLists.txt +++ b/tests/manual/quickcontrols/qquickdialog/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(qquickdialog LANGUAGES C CXX ASM) + project(qquickdialog LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/quickcontrols/screenshots/CMakeLists.txt b/tests/manual/quickcontrols/screenshots/CMakeLists.txt index 32d465b9d4..ece360c1c0 100644 --- a/tests/manual/quickcontrols/screenshots/CMakeLists.txt +++ b/tests/manual/quickcontrols/screenshots/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(screenshots LANGUAGES C CXX ASM) + project(screenshots LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/quickcontrols/styles-cover-flow/CMakeLists.txt b/tests/manual/quickcontrols/styles-cover-flow/CMakeLists.txt index b2fa66bf44..8412eeab4d 100644 --- a/tests/manual/quickcontrols/styles-cover-flow/CMakeLists.txt +++ b/tests/manual/quickcontrols/styles-cover-flow/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(styles-cover-flow LANGUAGES C CXX ASM) + project(styles-cover-flow LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/quickcontrols/styles/CMakeLists.txt b/tests/manual/quickcontrols/styles/CMakeLists.txt index 479fcfdc22..05aebfe89f 100644 --- a/tests/manual/quickcontrols/styles/CMakeLists.txt +++ b/tests/manual/quickcontrols/styles/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(styles LANGUAGES C CXX ASM) + project(styles LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/quickcontrols/systemtrayicon/CMakeLists.txt b/tests/manual/quickcontrols/systemtrayicon/CMakeLists.txt index b8913ec986..4a415c767a 100644 --- a/tests/manual/quickcontrols/systemtrayicon/CMakeLists.txt +++ b/tests/manual/quickcontrols/systemtrayicon/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(systemtrayicon LANGUAGES C CXX ASM) + project(systemtrayicon LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/quickcontrols/testbench/CMakeLists.txt b/tests/manual/quickcontrols/testbench/CMakeLists.txt index 64d8aa734d..98fc538e79 100644 --- a/tests/manual/quickcontrols/testbench/CMakeLists.txt +++ b/tests/manual/quickcontrols/testbench/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(testbench LANGUAGES C CXX ASM) + project(testbench LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/quickcontrols/viewinqwidget/CMakeLists.txt b/tests/manual/quickcontrols/viewinqwidget/CMakeLists.txt index 7deba0df55..848d2171a0 100644 --- a/tests/manual/quickcontrols/viewinqwidget/CMakeLists.txt +++ b/tests/manual/quickcontrols/viewinqwidget/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(viewinqwidget LANGUAGES C CXX ASM) + project(viewinqwidget LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/quickdialogs/dialogs/CMakeLists.txt b/tests/manual/quickdialogs/dialogs/CMakeLists.txt index 65d641f333..d2a20d96e9 100644 --- a/tests/manual/quickdialogs/dialogs/CMakeLists.txt +++ b/tests/manual/quickdialogs/dialogs/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(dialogs LANGUAGES C CXX ASM) + project(dialogs LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/quicklayouts/sizepolicies/CMakeLists.txt b/tests/manual/quicklayouts/sizepolicies/CMakeLists.txt index ad0056cf46..f1f5560c69 100644 --- a/tests/manual/quicklayouts/sizepolicies/CMakeLists.txt +++ b/tests/manual/quicklayouts/sizepolicies/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(sizepolicies LANGUAGES C CXX ASM) + project(sizepolicies LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/quickvectorimage/vectorimage/CMakeLists.txt b/tests/manual/quickvectorimage/vectorimage/CMakeLists.txt index 631009594f..1ade1d3eb3 100644 --- a/tests/manual/quickvectorimage/vectorimage/CMakeLists.txt +++ b/tests/manual/quickvectorimage/vectorimage/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(svgitem LANGUAGES C CXX ASM) + project(svgitem LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/righttoleft/layoutdirection/CMakeLists.txt b/tests/manual/righttoleft/layoutdirection/CMakeLists.txt index 7c1e38e79a..f442f17012 100644 --- a/tests/manual/righttoleft/layoutdirection/CMakeLists.txt +++ b/tests/manual/righttoleft/layoutdirection/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(layoutdirection LANGUAGES C CXX ASM) + project(layoutdirection LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/righttoleft/layoutmirroring/CMakeLists.txt b/tests/manual/righttoleft/layoutmirroring/CMakeLists.txt index 69fb0a05a8..cc8a04693a 100644 --- a/tests/manual/righttoleft/layoutmirroring/CMakeLists.txt +++ b/tests/manual/righttoleft/layoutmirroring/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(layoutmirroring LANGUAGES C CXX ASM) + project(layoutmirroring LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/righttoleft/textalignment/CMakeLists.txt b/tests/manual/righttoleft/textalignment/CMakeLists.txt index fa0c90f79c..f04cb76184 100644 --- a/tests/manual/righttoleft/textalignment/CMakeLists.txt +++ b/tests/manual/righttoleft/textalignment/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(textalignment LANGUAGES C CXX ASM) + project(textalignment LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/tableview/abstracttablemodel/CMakeLists.txt b/tests/manual/tableview/abstracttablemodel/CMakeLists.txt index 7f49c14567..7c6c62d61c 100644 --- a/tests/manual/tableview/abstracttablemodel/CMakeLists.txt +++ b/tests/manual/tableview/abstracttablemodel/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tableview_abstracttablemodel LANGUAGES C CXX ASM) + project(tableview_abstracttablemodel LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/tableview/listmodel/CMakeLists.txt b/tests/manual/tableview/listmodel/CMakeLists.txt index 0f5c27ca87..ffadc2ea47 100644 --- a/tests/manual/tableview/listmodel/CMakeLists.txt +++ b/tests/manual/tableview/listmodel/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tableview_listmodel LANGUAGES C CXX ASM) + project(tableview_listmodel LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/tableview/storagemodel/CMakeLists.txt b/tests/manual/tableview/storagemodel/CMakeLists.txt index 11ca5971ba..589cf7f3bc 100644 --- a/tests/manual/tableview/storagemodel/CMakeLists.txt +++ b/tests/manual/tableview/storagemodel/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tableview_storage LANGUAGES C CXX ASM) + project(tableview_storage LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/tableview/tablemodel/form/CMakeLists.txt b/tests/manual/tableview/tablemodel/form/CMakeLists.txt index 1943079f9f..f355677a44 100644 --- a/tests/manual/tableview/tablemodel/form/CMakeLists.txt +++ b/tests/manual/tableview/tablemodel/form/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(form LANGUAGES C CXX ASM) + project(form LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/tableview/tablemodel/json/CMakeLists.txt b/tests/manual/tableview/tablemodel/json/CMakeLists.txt index 279fae77b6..aeb6253447 100644 --- a/tests/manual/tableview/tablemodel/json/CMakeLists.txt +++ b/tests/manual/tableview/tablemodel/json/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(json LANGUAGES C CXX ASM) + project(json LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/textrendering/CMakeLists.txt b/tests/manual/textrendering/CMakeLists.txt index 9987010192..2f43b05084 100644 --- a/tests/manual/textrendering/CMakeLists.txt +++ b/tests/manual/textrendering/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.16) if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) - project(textrendering LANGUAGES C CXX ASM) + project(textrendering LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/threading/threadedlistmodel/CMakeLists.txt b/tests/manual/threading/threadedlistmodel/CMakeLists.txt index 68fb5c511c..e479ca921c 100644 --- a/tests/manual/threading/threadedlistmodel/CMakeLists.txt +++ b/tests/manual/threading/threadedlistmodel/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(threadedlistmodel LANGUAGES C CXX ASM) + project(threadedlistmodel LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/threading/workerscript/CMakeLists.txt b/tests/manual/threading/workerscript/CMakeLists.txt index 3f73985b33..74fd1ea861 100644 --- a/tests/manual/threading/workerscript/CMakeLists.txt +++ b/tests/manual/threading/workerscript/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(workerscript LANGUAGES C CXX ASM) + project(workerscript LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/treeview/sidebyside/CMakeLists.txt b/tests/manual/treeview/sidebyside/CMakeLists.txt index 046ab4e3bd..91e6c3d016 100644 --- a/tests/manual/treeview/sidebyside/CMakeLists.txt +++ b/tests/manual/treeview/sidebyside/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(treeview_sidebyside LANGUAGES C CXX ASM) + project(treeview_sidebyside LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/wasm/a11y/qml_basic_item/CMakeLists.txt b/tests/manual/wasm/a11y/qml_basic_item/CMakeLists.txt index 2214747fe5..0e87ef1aa5 100644 --- a/tests/manual/wasm/a11y/qml_basic_item/CMakeLists.txt +++ b/tests/manual/wasm/a11y/qml_basic_item/CMakeLists.txt @@ -4,7 +4,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(textManual LANGUAGES C CXX ASM) + project(textManual LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() |