convert threading example to manual tests

The threading example used a LauncherList to combine
two different but related examples into one.

I've now separated both into a shared directory called
'threading'

Pick-to: 6.6
Change-Id: Iee8898e61adcf69dc67157a1eff5f6ac019a39ca
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
This commit is contained in:
Oliver Eftevaag 2023-06-23 16:11:31 +02:00
parent add2620e2e
commit 38373b81f3
35 changed files with 195 additions and 223 deletions

View File

@ -19,7 +19,6 @@ qt_internal_add_example(positioners)
add_subdirectory(scenegraph)
qt_internal_add_example(shadereffects)
qt_internal_add_example(text)
qt_internal_add_example(threading)
add_subdirectory(tutorials)
add_subdirectory(customitems)
qt_internal_add_example(imageprovider)
@ -48,7 +47,6 @@ set(reused_dir_targets
views_shared
positioners_shared
text_shared
threading_shared
window_shared
shapes_shared
imageelements_shared

View File

@ -18,7 +18,6 @@ SUBDIRS = quick-accessibility \
scenegraph \
shadereffects \
text \
threading \
tutorials \
customitems \
imageprovider \

View File

@ -1,51 +0,0 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(threading LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/quick/threading")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml Quick)
qt_standard_project_setup(REQUIRES 6.5)
add_subdirectory("../shared" "shared")
qt_add_executable(threadingexample
WIN32
MACOSX_BUNDLE
main.cpp
)
target_link_libraries(threadingexample PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Qml
Qt6::Quick
)
add_dependencies(threadingexample threading_shared)
qt_add_qml_module(threadingexample
URI threading
QML_FILES
"threadedlistmodel/dataloader.mjs"
"threadedlistmodel/timedisplay.qml"
"threading.qml"
"workerscript/Spinner.qml"
"workerscript/workerscript.mjs"
"workerscript/workerscript.qml"
)
install(TARGETS threadingexample
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)
bundle_shared(threadingexample)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

View File

@ -1,44 +0,0 @@
// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\title Qt Quick Examples - Threading
\example threading
\brief This is a collection of QML multithreading examples.
\image qml-threading-example.png
\ingroup qtquickexamples
\e Threading is a collection of QML multithreading examples.
\include examples-run.qdocinc
\section1 Threaded ListModel
\e{Threaded ListModel} contains a \l ListView and a \l ListModel.
The ListModel object is updated asynchronously in another thread, and the
results propagate back to the main thread. A timer requests updates from the
worker thread periodically:
\snippet threading/threadedlistmodel/timedisplay.qml 0
Inside the worker thread, the ListModel is synchronized once the data is
finished loading:
\snippet threading/threadedlistmodel/dataloader.mjs 0
\section1 WorkerScript
\e WorkerScript contains an example of using a \l WorkerScript to offload
expensive calculations into another thread. This keeps the UI from being
blocked. This example calculates numbers in Pascal's Triangle, and not in a
very optimal way, so it will often take several seconds to complete the
calculation. By doing this in a WorkerScript in another thread, the UI is
not blocked during this time.
When the UI needs another value, a request is sent to the WorkerScript:
\snippet threading/workerscript/workerscript.qml 0
The workerscript then is free to take a really long time to calculate it:
\snippet threading/workerscript/workerscript.mjs 0
When it's done, the result returns to the main scene via the WorkerScript
type:
\snippet threading/workerscript/workerscript.qml 1
*/

View File

@ -1,4 +0,0 @@
// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "../shared/shared.h"
DECLARATIVE_EXAMPLE_MAIN(threading/threading)

View File

@ -1,13 +0,0 @@
// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\title Threaded ListModel Example
\example threading/threadedlistmodel
\brief The Threaded ListModel example shows how to use a ListModel from multiple
threads using WorkerScript.
This example shows how to use a ListModel from multiple threads using
WorkerScript.
*/

View File

@ -1,19 +0,0 @@
// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QmlProject 1.1
Project {
mainFile: "timedisplay.qml"
/* Include .qml, .js, and image files from current directory and subdirectories */
QmlFiles {
directory: "."
}
JavaScriptFiles {
directory: "."
}
ImageFiles {
directory: "."
}
}

View File

@ -1,10 +0,0 @@
TEMPLATE = app
QT += quick qml
SOURCES += main.cpp
RESOURCES += \
threading.qrc \
../shared/shared.qrc
target.path = $$[QT_INSTALL_EXAMPLES]/quick/threading
INSTALLS += target

View File

@ -1,18 +0,0 @@
// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
import shared as Examples
Item {
height: 480
width: 320
Examples.LauncherList {
id: ll
anchors.fill: parent
Component.onCompleted: {
addExample("Threaded ListModel", "Updates a ListModel in another thread", Qt.resolvedUrl("threadedlistmodel/timedisplay.qml"));
addExample("WorkerScript", "Performs calculations in another thread", Qt.resolvedUrl("workerscript/workerscript.qml"));
}
}
}

View File

@ -1,17 +0,0 @@
import QmlProject 1.1
Project {
mainFile: "threading.qml"
importPaths: ["../"]
/* Include .qml, .js, and image files from current directory and subdirectories */
QmlFiles {
directory: "."
}
JavaScriptFiles {
directory: "."
}
ImageFiles {
directory: "."
}
}

View File

@ -1,10 +0,0 @@
<RCC>
<qresource prefix="/qt/qml/threading">
<file>threading.qml</file>
<file>threadedlistmodel/timedisplay.qml</file>
<file>threadedlistmodel/dataloader.mjs</file>
<file>workerscript/Spinner.qml</file>
<file>workerscript/workerscript.mjs</file>
<file>workerscript/workerscript.qml</file>
</qresource>
</RCC>

View File

@ -1,19 +0,0 @@
// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QmlProject 1.1
Project {
mainFile: "workerscript.qml"
/* Include .qml, .js, and image files from current directory and subdirectories */
QmlFiles {
directory: "."
}
JavaScriptFiles {
directory: "."
}
ImageFiles {
directory: "."
}
}

View File

@ -0,0 +1,43 @@
// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
Rectangle {
color: "white"
width: 200
height: 300
ListView {
anchors.fill: parent
model: listModel
delegate: Component {
Text {
required property string time
text: time
}
}
ListModel { id: listModel }
WorkerScript {
id: worker
source: "dataloader.mjs"
}
// ![0]
Timer {
id: timer
interval: 2000; repeat: true
running: true
triggeredOnStart: true
onTriggered: {
var msg = {'action': 'appendCurrentTime', 'model': listModel};
worker.sendMessage(msg);
}
}
// ![0]
}
}

View File

@ -0,0 +1,13 @@
// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
// ![0]
WorkerScript.onMessage = function(msg) {
if (msg.action == 'appendCurrentTime') {
var data = {'time': new Date().toTimeString()};
msg.model.append(data);
msg.model.sync(); // updates the changes to the list
}
}
// ![0]

View File

@ -1981,7 +1981,7 @@ void DynamicRoleModelNodeMetaObject::propertyWritten(int index)
\section1 Using Threaded List Models with WorkerScript
ListModel can be used together with WorkerScript access a list model
ListModel can be used together with WorkerScript to access a list model
from multiple threads. This is useful if list modifications are
synchronous and take some time: the list operations can be moved to a
different thread to avoid blocking of the main GUI thread.
@ -1989,11 +1989,11 @@ void DynamicRoleModelNodeMetaObject::propertyWritten(int index)
Here is an example that uses WorkerScript to periodically append the
current time to a list model:
\snippet ../../examples/quick/threading/threadedlistmodel/timedisplay.qml 0
\snippet qml/listmodel/WorkerScript.qml 0
The included file, \tt dataloader.mjs, looks like this:
\snippet ../../examples/quick/threading/threadedlistmodel/dataloader.mjs 0
\snippet qml/listmodel/dataloader.mjs 0
The timer in the main example sends messages to the worker script by calling
\l WorkerScript::sendMessage(). When this message is received,
@ -2004,7 +2004,7 @@ void DynamicRoleModelNodeMetaObject::propertyWritten(int index)
You must call sync() or else the changes made to the list from that
thread will not be reflected in the list model in the main thread.
\sa {qml-data-models}{Data Models}, {Qt Quick Examples - Threading}, {Qt QML}
\sa {qml-data-models}{Data Models}, {Qt QML}
*/
QQmlListModel::QQmlListModel(QObject *parent)

View File

@ -508,9 +508,6 @@ void QQuickWorkerScriptEngine::run()
Worker scripts that are plain JavaScript sources can not use \l {qtqml-javascript-imports.html}{.import} syntax.
Scripts that are ECMAScript modules can freely use import and export statements.
\sa {Qt Quick Examples - Threading},
{Threaded ListModel Example}
*/
QQuickWorkerScript::QQuickWorkerScript(QObject *parent)
: QObject(parent), m_engine(nullptr), m_scriptId(-1), m_componentComplete(true)

View File

@ -92,8 +92,7 @@ imagedirs += images
excludefiles += ../util/qquickpropertychanges_p.h
examples.fileextensions += "*.qm"
manifestmeta.thumbnail.names += "QtQuick/Threaded ListModel Example" \
"QtQuick/QML Dynamic View Ordering Tutorial*"
manifestmeta.thumbnail.names += "QtQuick/QML Dynamic View Ordering Tutorial*"
manifestmeta.highlighted.names = "QtQuick/Qt Quick Demo - Same Game"

View File

@ -138,7 +138,6 @@ Creator.
\div {class="doc-column"}
\b{System and Events}
\list
\li \l{Qt Quick Examples - Threading}{Threading}
\li \l{Qt Quick Examples - Accessibility}{Accessibility}
\li \l{Qt Quick Examples - externaldraganddrop}{External Drag and Drop}
\li \l{Qt Quick Examples - Drag and Drop}{Drag and Drop}

View File

@ -5,7 +5,6 @@
"quick/externaldraganddrop Example", "examples/quick/externaldraganddrop", "externaldraganddrop", 0, -1
"quick/customitems/maskedmousearea Example", "examples/quick/customitems/maskedmousearea", "maskedmousearea", 0, -1
"quick/imageelements Example", "examples/quick/imageelements", "imageelements", 0, -1
"quick/threading Example", "examples/quick/threading", "threading", 0, -1
"quick/scenegraph/openglunderqml Example", "examples/quick/scenegraph/openglunderqml", "openglunderqml", 0, -1
"quick/scenegraph/threadedanimation Example", "examples/quick/scenegraph/threadedanimation", "threadedanimation", 0, -1
"quick/scenegraph/twotextureproviders Example", "examples/quick/scenegraph/twotextureproviders", "twotextureproviders", 0, -1

View File

@ -14,6 +14,7 @@ add_subdirectory(shapestest)
add_subdirectory(tableview)
add_subdirectory(text)
add_subdirectory(touch)
add_subdirectory(threading)
# add_subdirectory(v4) # TODO: port if needed
add_subdirectory(quickcontrols)
add_subdirectory(quickdialogs)

View File

@ -0,0 +1,2 @@
add_subdirectory(threading)
add_subdirectory(workerscript)

View File

@ -0,0 +1,33 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(threadedlistmodel LANGUAGES C CXX ASM)
find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
endif()
qt_internal_add_manual_test(tst_manual_threadedlistmodel
GUI
SOURCES
threadedlistmodel.cpp
DEFINES
QT_DEPRECATED_WARNINGS
LIBRARIES
Qt::Gui
Qt::Qml
Qt::Quick
)
# Resources:
set(qmake_immediate_resource_files
timedisplay.qml
dataloader.mjs
)
qt_internal_add_resource(tst_manual_threadedlistmodel "qmake_immediate"
PREFIX
"/qt/qml/threadedlistmodel"
FILES
${qmake_immediate_resource_files}
)

View File

@ -0,0 +1,19 @@
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtGui/qguiapplication.h>
#include <QtQuick/QQuickView>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QCoreApplication::setApplicationName("threadedlistmodel-manual-test");
QCoreApplication::setOrganizationName("QtProject");
QQuickView view;
view.setSource(QUrl(QStringLiteral("qrc:/qt/qml/threadedlistmodel/timedisplay.qml")));
view.show();
return app.exec();
}

View File

@ -0,0 +1,6 @@
TEMPLATE = app
TARGET = threadedlistmodel
QT += qml quick
SOURCES += threadedlistmodel.cpp
RESOURCES += threadedlistmodel.qrc

View File

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/qt/qml/threadedlistmodel">
<file>timedisplay.qml</file>
</qresource>
</RCC>

View File

@ -0,0 +1,34 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(workerscript LANGUAGES C CXX ASM)
find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
endif()
qt_internal_add_manual_test(tst_manual_workerscript
GUI
SOURCES
workerscript.cpp
DEFINES
QT_DEPRECATED_WARNINGS
LIBRARIES
Qt::Gui
Qt::Qml
Qt::Quick
)
# Resources:
set(qmake_immediate_resource_files
"Spinner.qml"
"workerscript.qml"
"workerscript.mjs"
)
qt_internal_add_resource(tst_manual_workerscript "qmake_immediate"
PREFIX
"/qt/qml/workerscript"
FILES
${qmake_immediate_resource_files}
)

View File

@ -0,0 +1,19 @@
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtGui/qguiapplication.h>
#include <QtQuick/QQuickView>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QCoreApplication::setApplicationName("workerscript-manual-test");
QCoreApplication::setOrganizationName("QtProject");
QQuickView view;
view.setSource(QUrl(QStringLiteral("qrc:/qt/qml/workerscript/workerscript.qml")));
view.show();
return app.exec();
}

View File

@ -0,0 +1,6 @@
TEMPLATE = app
TARGET = workerscript
QT += qml quick
SOURCES += workerscript.cpp
RESOURCES += workerscript.qrc

View File

@ -6,7 +6,6 @@ import QtQuick
Rectangle {
width: 320; height: 480
//! [1]
WorkerScript {
id: myWorker
source: "workerscript.mjs"
@ -20,12 +19,12 @@ Rectangle {
}
}
}
//! [1]
Row {
y: 24
spacing: 24
anchors.horizontalCenter: parent.horizontalCenter
//! [0]
Spinner {
id: rowSpinner
label: "Row"
@ -34,7 +33,6 @@ Rectangle {
myWorker.sendMessage( { row: rowSpinner.value, column: columnSpinner.value } );
}
}
//! [0]
Spinner {
id: columnSpinner

View File

@ -0,0 +1,7 @@
<RCC>
<qresource prefix="/qt/qml/workerscript">
<file>Spinner.qml</file>
<file>workerscript.mjs</file>
<file>workerscript.qml</file>
</qresource>
</RCC>