diff options
author | Daniel d'Andrada <daniel.dandrada@luxoft.com> | 2017-10-19 14:15:17 +0200 |
---|---|---|
committer | Daniel d'Andrada <daniel.dandrada@luxoft.com> | 2018-02-28 15:57:56 +0100 |
commit | 266467aa8474530f9e5682c221a0625cf252a84e (patch) | |
tree | 9b16cef183d252155646a19020a1ebaeaed36cb7 /tests | |
parent | 54a77753da3765b4e1cc6508b900560ee6093c2b (diff) |
Testing infrastructure
Change-Id: I3efc62ee86d345ca16dc6eb334eea4c8c99240b4
Diffstat (limited to 'tests')
18 files changed, 1331 insertions, 0 deletions
diff --git a/tests/README b/tests/README new file mode 100644 index 00000000..9ebc7f85 --- /dev/null +++ b/tests/README @@ -0,0 +1,11 @@ +There are two ways to run qml tests: + +1-Execute the automated tests defined inside TestCase{} throughout tst_*.qml files + (using a qmltestrunner): + build_dir$ make check + +2-Try out a test in a window for manual interaction (manual testing). + Say you have a component called WidgetDrawer. If it has a test it will + be called tst_WidgetDrawer.qml. To show it using triton-qmlscene you run: + + build_dir/tests/qmltests$ make tryWidgetDrawer diff --git a/tests/dummyimports/QtApplicationManager/ApplicationIPCInterface.qml b/tests/dummyimports/QtApplicationManager/ApplicationIPCInterface.qml new file mode 100644 index 00000000..c5aa25d6 --- /dev/null +++ b/tests/dummyimports/QtApplicationManager/ApplicationIPCInterface.qml @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Pelagicore AG +** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Pelagicore Application Manager. +** +** $QT_BEGIN_LICENSE:LGPL-QTAS$ +** Commercial License Usage +** Licensees holding valid commercial Qt Automotive Suite licenses may use +** this file in accordance with the commercial license agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and The Qt Company. For +** licensing terms and conditions see https://www.qt.io/terms-conditions. +** For further information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +** SPDX-License-Identifier: LGPL-3.0 +** +****************************************************************************/ + +import QtQml 2.0 + +QtObject { +} diff --git a/tests/dummyimports/QtApplicationManager/ApplicationInstaller.js b/tests/dummyimports/QtApplicationManager/ApplicationInstaller.js new file mode 100644 index 00000000..4494e49a --- /dev/null +++ b/tests/dummyimports/QtApplicationManager/ApplicationInstaller.js @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Pelagicore AG +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Pelagicore Application Manager. +** +** $QT_BEGIN_LICENSE:LGPL-QTAS$ +** Commercial License Usage +** Licensees holding valid commercial Qt Automotive Suite licenses may use +** this file in accordance with the commercial license agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and The Qt Company. For +** licensing terms and conditions see https://www.qt.io/terms-conditions. +** For further information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +** SPDX-License-Identifier: LGPL-3.0 +** +****************************************************************************/ + +function removePackage(id) { + print("Dummy implementation of removePackage was called for ", id) + return "" +} diff --git a/tests/dummyimports/QtApplicationManager/ApplicationManager.qml b/tests/dummyimports/QtApplicationManager/ApplicationManager.qml new file mode 100644 index 00000000..c16db806 --- /dev/null +++ b/tests/dummyimports/QtApplicationManager/ApplicationManager.qml @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Pelagicore AG +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Pelagicore Application Manager. +** +** $QT_BEGIN_LICENSE:LGPL-QTAS$ +** Commercial License Usage +** Licensees holding valid commercial Qt Automotive Suite licenses may use +** this file in accordance with the commercial license agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and The Qt Company. For +** licensing terms and conditions see https://www.qt.io/terms-conditions. +** For further information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +** SPDX-License-Identifier: LGPL-3.0 +** +****************************************************************************/ + +pragma Singleton +import QtQuick 2.2 + +ListModel { + id: root + + property int count: 3 + property bool dummy: true + + property var applibrary : [ + ["com.pelagicore.browser","icon.png", "Browser", "browser", "Browser.qml"], + ["com.pelagicore.movies","icon.png", "Movies", "media", "Movies.qml"], + ["com.pelagicore.music","icon.png", "Music", "media", "Music.qml"], + ] + + signal emitSurface(int index, Item item) + + + + function setApplicationAudioFocus(appId, appFocus) + { + print("setApplicationAudioFocus(" + appId + ", " + appFocus + ")") + } + + function qmltypeof(obj, className) { // QtObject, string -> bool + // className plus "(" is the class instance without modification + // className plus "_QML" is the class instance with user-defined properties + var str = obj.toString(); + return str.indexOf(className + "(") == 0 || str.indexOf(className + "_QML") == 0; + } + + function startApplication(id) { + print("Starting the application. ") + var component + var item + for (var i = 0; i < root.count; i++) { + var entry + print("ApplicationManager: " + createAppEntry(i).applicationId + " given app id to open: " + id) + if (root.get(i).applicationId === id) { + component = Qt.createComponent("../../../../apps/" + createAppEntry(i).applicationId + "/" + createAppEntry(i).qml); + if (component.status === Component.Ready) { + item = component.createObject() + if (!item) + console.log("Failed to create an Object.") + else { + print("Starting the application. Sending a signal", i, item, item.children.length) + root.setProperty(i, "surfaceItem", item) + root.emitSurface(i, item) + } + } + else + console.log("Component creation failed " + createAppEntry(i).qml + " Error: " + component.errorString()) + } + } + } + + + + function createAppEntry(i) { + + var entry = { + applicationId: applibrary[i][0], + icon: "../../apps/" + applibrary[i][0] + "/" + applibrary[i][1], + name: applibrary[i][2], + isRunning: false, + isStarting: false, + isActive: false, + isBlocked: false, + isUpdating: false, + isRemovable: false, + updateProgress: 0, + codeFilePath: "", + categories: applibrary[i][3], + qml: applibrary[i][4], + surfaceItem: null + } + return entry + } + Component.onCompleted: { + clear() + for (var i = 0; i < root.count; i++) { + append(createAppEntry(i)) + } + } + +} diff --git a/tests/dummyimports/QtApplicationManager/ApplicationManagerWindow.qml b/tests/dummyimports/QtApplicationManager/ApplicationManagerWindow.qml new file mode 100644 index 00000000..15a39a9d --- /dev/null +++ b/tests/dummyimports/QtApplicationManager/ApplicationManagerWindow.qml @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Pelagicore AG +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Pelagicore Application Manager. +** +** $QT_BEGIN_LICENSE:LGPL-QTAS$ +** Commercial License Usage +** Licensees holding valid commercial Qt Automotive Suite licenses may use +** this file in accordance with the commercial license agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and The Qt Company. For +** licensing terms and conditions see https://www.qt.io/terms-conditions. +** For further information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +** SPDX-License-Identifier: LGPL-3.0 +** +****************************************************************************/ + +import QtQuick 2.0 +import QtApplicationManager 1.0 + +Item { + id: root + width: 768 + height: 860 + property color color + + signal windowPropertyChanged(string name, var value) + signal close() + //function showFullScreen() {} + function showMaximized() {} + function showNormal() {} + function setWindowProperty(status, value) { + WindowManager.surfaceWindowPropertyChanged(root, status, value) + windowPropertyChanged(status, value) + } +} diff --git a/tests/dummyimports/QtApplicationManager/Notification.qml b/tests/dummyimports/QtApplicationManager/Notification.qml new file mode 100644 index 00000000..50a84774 --- /dev/null +++ b/tests/dummyimports/QtApplicationManager/Notification.qml @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Pelagicore AG +** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Pelagicore Application Manager. +** +** $QT_BEGIN_LICENSE:LGPL-QTAS$ +** Commercial License Usage +** Licensees holding valid commercial Qt Automotive Suite licenses may use +** this file in accordance with the commercial license agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and The Qt Company. For +** licensing terms and conditions see https://www.qt.io/terms-conditions. +** For further information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +** SPDX-License-Identifier: LGPL-3.0 +** +****************************************************************************/ + +import QtQml 2.0 + +QtObject { + property string summary + property int timeout + property variant actions +} diff --git a/tests/dummyimports/QtApplicationManager/SystemMonitor.qml b/tests/dummyimports/QtApplicationManager/SystemMonitor.qml new file mode 100644 index 00000000..4a2d0467 --- /dev/null +++ b/tests/dummyimports/QtApplicationManager/SystemMonitor.qml @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Pelagicore AG +** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Pelagicore Application Manager. +** +** $QT_BEGIN_LICENSE:LGPL-QTAS$ +** Commercial License Usage +** Licensees holding valid commercial Qt Automotive Suite licenses may use +** this file in accordance with the commercial license agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and The Qt Company. For +** licensing terms and conditions see https://www.qt.io/terms-conditions. +** For further information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +** SPDX-License-Identifier: LGPL-3.0 +** +****************************************************************************/ + +pragma Singleton + +import QtQml 2.0 + +QtObject { + property int reportingInterval + property int reportingRange + property bool cpuLoadReportingEnabled + property bool fpsReportingEnabled + signal fpsReportingChanged(real average, real minimum, real maximum, real jitter) +} diff --git a/tests/dummyimports/QtApplicationManager/WindowManager.qml b/tests/dummyimports/QtApplicationManager/WindowManager.qml new file mode 100644 index 00000000..276fa02f --- /dev/null +++ b/tests/dummyimports/QtApplicationManager/WindowManager.qml @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Pelagicore AG +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Pelagicore Application Manager. +** +** $QT_BEGIN_LICENSE:LGPL-QTAS$ +** Commercial License Usage +** Licensees holding valid commercial Qt Automotive Suite licenses may use +** this file in accordance with the commercial license agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and The Qt Company. For +** licensing terms and conditions see https://www.qt.io/terms-conditions. +** For further information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +** SPDX-License-Identifier: LGPL-3.0 +** +****************************************************************************/ + +pragma Singleton +import QtQuick 2.2 +import QtApplicationManager 1.0 + +QtObject { + id: root + property int count: ApplicationManager.count + property var surfaceItems: [] + property Connections conn: Connections { + target: ApplicationManager + onEmitSurface: { + surfaceItems[index] = item + root.surfaceItemReady(index, item) + } + } + + signal surfaceItemReady(int index, Item item) + signal surfaceItemClosing() + signal surfaceItemLost() + signal raiseApplicationWindow() + signal surfaceWindowPropertyChanged(Item surfaceItem, string name, var value) + + function setSurfaceWindowProperty(appItem, type, status) { + appItem.windowPropertyChanged(type, status) + } + + function surfaceWindowProperty(item, type) { + return false + } + + function get(index) { + var entry = ApplicationManager.get(index) + entry.surfaceItem = surfaceItems[index] + return entry + } + + Component.onCompleted: { + for (var i = 0; i < root.count; i++) { + surfaceItems.push(null) + } + } + +} diff --git a/tests/dummyimports/QtApplicationManager/qmldir b/tests/dummyimports/QtApplicationManager/qmldir new file mode 100644 index 00000000..6af7b9d7 --- /dev/null +++ b/tests/dummyimports/QtApplicationManager/qmldir @@ -0,0 +1,7 @@ +singleton ApplicationManager 1.0 ApplicationManager.qml +ApplicationManagerWindow 1.0 ApplicationManagerWindow.qml +ApplicationInstaller 1.0 ApplicationInstaller.js +ApplicationIPCInterface 1.0 ApplicationIPCInterface.qml +Notification 1.0 Notification.qml +singleton WindowManager 1.0 WindowManager.qml +singleton SystemMonitor 1.0 SystemMonitor.qml diff --git a/tests/dummyimports/dummyimports.pro b/tests/dummyimports/dummyimports.pro new file mode 100644 index 00000000..338e3e60 --- /dev/null +++ b/tests/dummyimports/dummyimports.pro @@ -0,0 +1,6 @@ +TEMPLATE = aux + +OTHER_FILES += \ + QtApplicationManager/*.js \ + QtApplicationManager/*.qml \ + QtApplicationManager/qmldir \ diff --git a/tests/qmltests/qmltests.pro b/tests/qmltests/qmltests.pro new file mode 100644 index 00000000..721414cf --- /dev/null +++ b/tests/qmltests/qmltests.pro @@ -0,0 +1,20 @@ +TEMPLATE=app +TARGET=triton-qmltestsrunner +SOURCES += testrunner.cpp + +CONFIG += qmltestcase + +IMPORTPATH = $$BUILD_DIR/imports/shared/ $$SOURCE_DIR/sysui $$SOURCE_DIR/tests/dummyimports + +COMPONENT_NAMES = ApplicationWidget +COMPONENT_NAMES += WidgetDrawer + +for(COMPONENT_NAME, COMPONENT_NAMES) { + targetName = try$$COMPONENT_NAME + QMAKE_EXTRA_TARGETS += $${targetName} + $${targetName}.commands = $$OUT_PWD/../triton-qmlscene/triton-qmlscene + !isEmpty(IMPORTPATH) { + for(import, IMPORTPATH): $${targetName}.commands += -I \"$$import\" + } + $${targetName}.commands += $$PWD/tst_$${COMPONENT_NAME}.qml +} diff --git a/tests/qmltests/testrunner.cpp b/tests/qmltests/testrunner.cpp new file mode 100644 index 00000000..663febe9 --- /dev/null +++ b/tests/qmltests/testrunner.cpp @@ -0,0 +1,2 @@ +#include <QtQuickTest/quicktest.h> +QUICK_TEST_MAIN(neptune-qmltests) diff --git a/tests/qmltests/tst_ApplicationWidget.qml b/tests/qmltests/tst_ApplicationWidget.qml new file mode 100644 index 00000000..3f11f193 --- /dev/null +++ b/tests/qmltests/tst_ApplicationWidget.qml @@ -0,0 +1,28 @@ +import QtQuick 2.6 +import QtTest 1.1 + +// sysui, for getting ApplicationWidget +import display 1.0 + +Item { + width: 600 + height: 600 + + ApplicationWidget { + y: 200 + width: 600 + height: 200 + + Rectangle { color: "green"; anchors.fill: parent } + } + + TestCase { + name: "ApplicationWidget" + when: windowShown + + function test_pass() { + compare(2 + 2, 4, "2 + 2") + } + } +} + diff --git a/tests/qmltests/tst_WidgetDrawer.qml b/tests/qmltests/tst_WidgetDrawer.qml new file mode 100644 index 00000000..9d282c4d --- /dev/null +++ b/tests/qmltests/tst_WidgetDrawer.qml @@ -0,0 +1,27 @@ +import QtQuick 2.6 +import QtTest 1.1 + +// sysui, for getting WidgetDrawer +import display 1.0 + +Item { + width: 600 + height: 600 + + WidgetDrawer { + y: 200 + width: 600 + height: 200 + + Rectangle { color: "green"; anchors.fill: parent } + } + + TestCase { + name: "WidgetDrawer" + when: windowShown + + function test_pass() { + compare(2 + 2, 4, "2 + 2") + } + } +} diff --git a/tests/tests.pro b/tests/tests.pro index 96710850..1148860a 100644 --- a/tests/tests.pro +++ b/tests/tests.pro @@ -1 +1,2 @@ TEMPLATE = subdirs +SUBDIRS += qmltests triton-qmlscene diff --git a/tests/triton-qmlscene/README b/tests/triton-qmlscene/README new file mode 100644 index 00000000..80101478 --- /dev/null +++ b/tests/triton-qmlscene/README @@ -0,0 +1,6 @@ +triton-qmlscene is useful when you want to manually interact with a qml file that has a TestCase in it. + +It's just qmlscene from qtdeclarative with minor modifications. Namely: + - Made it register a dummy QTestRootObject singleton type under a Qt.test.qtestroot so that qml files + that have a TestCase (ie, that import QtTest) can be loaded and displayed. + - Added a MouseTouchAdaptor for emulating touch interaction with a mouse device diff --git a/tests/triton-qmlscene/triton-qmlscene.cpp b/tests/triton-qmlscene/triton-qmlscene.cpp new file mode 100644 index 00000000..33a10a8c --- /dev/null +++ b/tests/triton-qmlscene/triton-qmlscene.cpp @@ -0,0 +1,743 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/qabstractanimation.h> +#include <QtCore/qdir.h> +#include <QtCore/qmath.h> +#include <QtCore/qdatetime.h> +#include <QtCore/qpointer.h> +#include <QtCore/qscopedpointer.h> +#include <QtCore/qtextstream.h> +#include <QtCore/qregularexpression.h> + +#include <QtGui/QGuiApplication> +#include <QtGui/QOpenGLFunctions> + +#include <QtQml/qqml.h> +#include <QtQml/qqmlengine.h> +#include <QtQml/qqmlcomponent.h> +#include <QtQml/qqmlcontext.h> + +#include <QtQuick/qquickitem.h> +#include <QtQuick/qquickview.h> + +#include <private/qabstractanimation_p.h> +#include <private/qopenglcontext_p.h> + +#ifdef QT_WIDGETS_LIB +#include <QtWidgets/QApplication> +#include <QtWidgets/QFileDialog> +#endif + +#include <QtCore/QTranslator> +#include <QtCore/QLibraryInfo> + +#ifdef TRITON_ENABLE_TOUCH_EMULATION +# include <MouseTouchAdaptor.h> +#endif + +#ifdef QML_RUNTIME_TESTING +class RenderStatistics +{ +public: + static void updateStats(); + static void printTotalStats(); +private: + static QVector<qreal> timePerFrame; + static QVector<int> timesPerFrames; +}; + +QVector<qreal> RenderStatistics::timePerFrame; +QVector<int> RenderStatistics::timesPerFrames; + +void RenderStatistics::updateStats() +{ + static QTime time; + static int frames; + static int lastTime; + + if (frames == 0) { + time.start(); + } else { + int elapsed = time.elapsed(); + timesPerFrames.append(elapsed - lastTime); + lastTime = elapsed; + + if (elapsed > 5000) { + qreal avgtime = elapsed / (qreal) frames; + qreal var = 0; + for (int i = 0; i < timesPerFrames.size(); ++i) { + qreal diff = timesPerFrames.at(i) - avgtime; + var += diff * diff; + } + var /= timesPerFrames.size(); + + printf("Average time per frame: %f ms (%i fps), std.dev: %f ms\n", avgtime, qRound(1000. / avgtime), qSqrt(var)); + + timePerFrame.append(avgtime); + timesPerFrames.clear(); + time.start(); + lastTime = 0; + frames = 0; + } + } + ++frames; +} + +void RenderStatistics::printTotalStats() +{ + int count = timePerFrame.count(); + if (count == 0) + return; + + qreal minTime = 0; + qreal maxTime = 0; + qreal avg = 0; + for (int i = 0; i < count; ++i) { + minTime = minTime == 0 ? timePerFrame.at(i) : qMin(minTime, timePerFrame.at(i)); + maxTime = qMax(maxTime, timePerFrame.at(i)); + avg += timePerFrame.at(i); + } + avg /= count; + + puts(" "); + puts("----- Statistics -----"); + printf("Average time per frame: %f ms (%i fps)\n", avg, qRound(1000. / avg)); + printf("Best time per frame: %f ms (%i fps)\n", minTime, int(1000 / minTime)); + printf("Worst time per frame: %f ms (%i fps)\n", maxTime, int(1000 / maxTime)); + puts("----------------------"); + puts(" "); +} +#endif + +struct Options +{ + enum QmlApplicationType + { + QmlApplicationTypeGui, + QmlApplicationTypeWidget, +#ifdef QT_WIDGETS_LIB + DefaultQmlApplicationType = QmlApplicationTypeWidget +#else + DefaultQmlApplicationType = QmlApplicationTypeGui +#endif + }; + + Options() + : originalQml(false) + , originalQmlRaster(false) + , maximized(false) + , fullscreen(false) + , transparent(false) + , clip(false) + , versionDetection(true) + , slowAnimations(false) + , quitImmediately(false) + , resizeViewToRootItem(false) + , multisample(false) + , coreProfile(false) + , verbose(false) + , applicationType(DefaultQmlApplicationType) + , textRenderType(QQuickWindow::textRenderType()) + { + // QtWebEngine needs a shared context in order for the GPU thread to + // upload textures. + applicationAttributes.append(Qt::AA_ShareOpenGLContexts); + } + + QUrl url; + bool originalQml; + bool originalQmlRaster; + bool maximized; + bool fullscreen; + bool transparent; + bool clip; + bool versionDetection; + bool slowAnimations; + bool quitImmediately; + bool resizeViewToRootItem; + bool multisample; + bool coreProfile; + bool verbose; + QVector<Qt::ApplicationAttribute> applicationAttributes; + QString translationFile; + QmlApplicationType applicationType; + QQuickWindow::TextRenderType textRenderType; +}; + +#if defined(QMLSCENE_BUNDLE) +QFileInfoList findQmlFiles(const QString &dirName) +{ + QDir dir(dirName); + + QFileInfoList ret; + if (dir.exists()) { + const QFileInfoList fileInfos = dir.entryInfoList(QStringList() << "*.qml", + QDir::Files | QDir::AllDirs | QDir::NoDotAndDotDot); + + for (const QFileInfo &fileInfo : fileInfos) { + if (fileInfo.isDir()) + ret += findQmlFiles(fileInfo.filePath()); + else if (fileInfo.fileName().length() > 0 && fileInfo.fileName().at(0).isLower()) + ret.append(fileInfo); + } + } + + return ret; +} + +static int displayOptionsDialog(Options *options) +{ + QDialog dialog; + + QFormLayout *layout = new QFormLayout(&dialog); + + QComboBox *qmlFileComboBox = new QComboBox(&dialog); + const QFileInfoList fileInfos = findQmlFiles(":/bundle") + findQmlFiles("./qmlscene-resources"); + + for (const QFileInfo &fileInfo : fileInfos) + qmlFileComboBox->addItem(fileInfo.dir().dirName() + QLatin1Char('/') + fileInfo.fileName(), QVariant::fromValue(fileInfo)); + + QCheckBox *originalCheckBox = new QCheckBox(&dialog); + originalCheckBox->setText("Use original QML viewer"); + originalCheckBox->setChecked(options->originalQml); + + QCheckBox *fullscreenCheckBox = new QCheckBox(&dialog); + fullscreenCheckBox->setText("Start fullscreen"); + fullscreenCheckBox->setChecked(options->fullscreen); + + QCheckBox *maximizedCheckBox = new QCheckBox(&dialog); + maximizedCheckBox->setText("Start maximized"); + maximizedCheckBox->setChecked(options->maximized); + + QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, + Qt::Horizontal, + &dialog); + QObject::connect(buttonBox, SIGNAL(accepted()), &dialog, SLOT(accept())); + QObject::connect(buttonBox, SIGNAL(rejected()), &dialog, SLOT(reject())); + + layout->addRow("Qml file:", qmlFileComboBox); + layout->addWidget(originalCheckBox); + layout->addWidget(maximizedCheckBox); + layout->addWidget(fullscreenCheckBox); + layout->addWidget(buttonBox); + + int result = dialog.exec(); + if (result == QDialog::Accepted) { + QVariant variant = qmlFileComboBox->itemData(qmlFileComboBox->currentIndex()); + QFileInfo fileInfo = variant.value<QFileInfo>(); + + if (fileInfo.canonicalFilePath().startsWith(QLatin1Char(':'))) + options->file = QUrl("qrc" + fileInfo.canonicalFilePath()); + else + options->file = QUrl::fromLocalFile(fileInfo.canonicalFilePath()); + options->originalQml = originalCheckBox->isChecked(); + options->maximized = maximizedCheckBox->isChecked(); + options->fullscreen = fullscreenCheckBox->isChecked(); + } + return result; +} +#endif + +static bool checkVersion(const QUrl &url) +{ + if (!qgetenv("QMLSCENE_IMPORT_NAME").isEmpty()) + fprintf(stderr, "QMLSCENE_IMPORT_NAME is no longer supported.\n"); + + if (!url.isLocalFile()) + return true; + + const QString fileName = url.toLocalFile(); + QFile f(fileName); + if (!f.open(QFile::ReadOnly | QFile::Text)) { + fprintf(stderr, "qmlscene: failed to check version of file '%s', could not open...\n", + qPrintable(fileName)); + return false; + } + + QRegularExpression quick1("^\\s*import +QtQuick +1\\.\\w*"); + QRegularExpression qt47("^\\s*import +Qt +4\\.7"); + + QTextStream stream(&f); + bool codeFound= false; + while (!codeFound) { + QString line = stream.readLine(); + if (line.contains(QLatin1Char('{'))) { + codeFound = true; + } else { + QString import; + QRegularExpressionMatch match = quick1.match(line); + if (match.hasMatch()) + import = match.captured(0).trimmed(); + else if ((match = qt47.match(line)).hasMatch()) + import = match.captured(0).trimmed(); + + if (!import.isNull()) { + fprintf(stderr, "qmlscene: '%s' is no longer supported.\n" + "Use qmlviewer to load file '%s'.\n", + qPrintable(import), + qPrintable(fileName)); + return false; + } + } + } + + return true; +} + +static void displayFileDialog(Options *options) +{ +#if defined(QT_WIDGETS_LIB) && QT_CONFIG(filedialog) + if (options->applicationType == Options::QmlApplicationTypeWidget) { + QString fileName = QFileDialog::getOpenFileName(0, "Open QML file", QString(), "QML Files (*.qml)"); + if (!fileName.isEmpty()) { + QFileInfo fi(fileName); + options->url = QUrl::fromLocalFile(fi.canonicalFilePath()); + } + return; + } +#endif // QT_WIDGETS_LIB && QT_CONFIG(filedialog) + Q_UNUSED(options); + puts("No filename specified..."); +} + +#if QT_CONFIG(translation) +static void loadTranslationFile(QTranslator &translator, const QString& directory) +{ + translator.load(QLatin1String("qml_" )+QLocale::system().name(), directory + QLatin1String("/i18n")); + QCoreApplication::installTranslator(&translator); +} +#endif + +static void loadDummyDataFiles(QQmlEngine &engine, const QString& directory) +{ + QDir dir(directory+"/dummydata", "*.qml"); + QStringList list = dir.entryList(); + for (int i = 0; i < list.size(); ++i) { + QString qml = list.at(i); + QQmlComponent comp(&engine, dir.filePath(qml)); + QObject *dummyData = comp.create(); + + if (comp.isError()) { + const QList<QQmlError> errors = comp.errors(); + for (const QQmlError &error : errors) + fprintf(stderr, "%s\n", qPrintable(error.toString())); + } + + if (dummyData) { + fprintf(stderr, "Loaded dummy data: %s\n", qPrintable(dir.filePath(qml))); + qml.truncate(qml.length()-4); + engine.rootContext()->setContextProperty(qml, dummyData); + dummyData->setParent(&engine); + } + } +} + +static void usage() +{ + puts("Usage: qmlscene [options] <filename>"); + puts(" "); + puts(" Options:"); + puts(" --maximized ...................... Run maximized"); + puts(" --fullscreen ..................... Run fullscreen"); + puts(" --transparent .................... Make the window transparent"); + puts(" --multisample .................... Enable multisampling (OpenGL anti-aliasing)"); + puts(" --core-profile ................... Request a core profile OpenGL context"); + puts(" --no-version-detection ........... Do not try to detect the version of the .qml file"); + puts(" --slow-animations ................ Run all animations in slow motion"); + puts(" --resize-to-root ................. Resize the window to the size of the root item"); + puts(" --quit ........................... Quit immediately after starting"); + puts(" --disable-context-sharing ........ Disable the use of a shared GL context for QtQuick Windows\n" + " .........(remove AA_ShareOpenGLContexts)"); + puts(" --desktop..........................Force use of desktop GL (AA_UseDesktopOpenGL)"); + puts(" --gles.............................Force use of GLES (AA_UseOpenGLES)"); + puts(" --software.........................Force use of software rendering (AA_UseOpenGLES)"); + puts(" --scaling..........................Enable High DPI scaling (AA_EnableHighDpiScaling)"); + puts(" --no-scaling.......................Disable High DPI scaling (AA_DisableHighDpiScaling)"); + puts(" --verbose..........................Print version and graphical diagnostics for the run-time"); +#ifdef QT_WIDGETS_LIB + puts(" --apptype [gui|widgets] ...........Select which application class to use. Default is widgets."); +#endif + puts(" --textrendertype [qt|native].......Select the default render type for text-like elements."); + puts(" -I <path> ........................ Add <path> to the list of import paths"); + puts(" -P <path> ........................ Add <path> to the list of plugin paths"); + puts(" -translation <translationfile> ... Set the language to run in"); + + puts(" "); + exit(1); +} +#if QT_CONFIG(opengl) +// Listen on GL context creation of the QQuickWindow in order to print diagnostic output. +class DiagnosticGlContextCreationListener : public QObject { + Q_OBJECT +public: + explicit DiagnosticGlContextCreationListener(QQuickWindow *window) : QObject(window) + { + connect(window, &QQuickWindow::openglContextCreated, + this, &DiagnosticGlContextCreationListener::onOpenGlContextCreated); + } + +private slots: + void onOpenGlContextCreated(QOpenGLContext *context) + { + context->makeCurrent(qobject_cast<QQuickWindow *>(parent())); + QOpenGLFunctions functions(context); + QByteArray output = "Vendor : "; + output += reinterpret_cast<const char *>(functions.glGetString(GL_VENDOR)); + output += "\nRenderer: "; + output += reinterpret_cast<const char *>(functions.glGetString(GL_RENDERER)); + output += "\nVersion : "; + output += reinterpret_cast<const char *>(functions.glGetString(GL_VERSION)); + output += "\nLanguage: "; + output += reinterpret_cast<const char *>(functions.glGetString(GL_SHADING_LANGUAGE_VERSION)); + puts(output.constData()); + context->doneCurrent(); + deleteLater(); + } + +}; +#endif + +static void setWindowTitle(bool verbose, const QObject *topLevel, QWindow *window) +{ + const QString oldTitle = window->title(); + QString newTitle = oldTitle; + if (newTitle.isEmpty()) { + newTitle = QLatin1String("qmlscene"); + if (!qobject_cast<const QWindow *>(topLevel) && !topLevel->objectName().isEmpty()) + newTitle += QLatin1String(": ") + topLevel->objectName(); + } + if (verbose) { + newTitle += QLatin1String(" [Qt ") + QLatin1String(QT_VERSION_STR) + QLatin1Char(' ') + + QGuiApplication::platformName() + QLatin1Char(' '); +#if QT_CONFIG(opengl) + newTitle += QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL + ? QLatin1String("GL") : QLatin1String("GLES"); +#endif + newTitle += QLatin1Char(']'); + } + if (oldTitle != newTitle) + window->setTitle(newTitle); +} + +static QUrl parseUrlArgument(const QString &arg) +{ + const QUrl url = QUrl::fromUserInput(arg, QDir::currentPath(), QUrl::AssumeLocalFile); + if (!url.isValid()) { + fprintf(stderr, "Invalid URL: \"%s\"\n", qPrintable(arg)); + return QUrl(); + } + if (url.isLocalFile()) { + const QFileInfo fi(url.toLocalFile()); + if (!fi.exists()) { + fprintf(stderr, "\"%s\" does not exist.\n", + qPrintable(QDir::toNativeSeparators(fi.absoluteFilePath()))); + return QUrl(); + } + } + return url; +} + +static QQuickWindow::TextRenderType parseTextRenderType(const QString &renderType) +{ + if (renderType == QLatin1String("qt")) + return QQuickWindow::QtTextRendering; + else if (renderType == QLatin1String("native")) + return QQuickWindow::NativeTextRendering; + + usage(); + + Q_UNREACHABLE(); + return QQuickWindow::QtTextRendering; +} + +class DummyTestRootObject : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool windowShown READ windowShown NOTIFY windowShownChanged) + +public: + DummyTestRootObject(QObject *o) : QObject(o) {} + + bool windowShown() const { return false; } + +Q_SIGNALS: + void windowShownChanged(); +}; + +static QObject *s_testRootObject = nullptr; +static QObject *testRootObject(QQmlEngine *engine, QJSEngine *jsEngine) +{ + Q_UNUSED(jsEngine); + if (!s_testRootObject) { + s_testRootObject = new DummyTestRootObject(engine); + } + return s_testRootObject; +} + +int main(int argc, char ** argv) +{ + Options options; + + QStringList imports; + QStringList pluginPaths; + + // Parse arguments for application attributes to be applied before Q[Gui]Application creation. + for (int i = 1; i < argc; ++i) { + const char *arg = argv[i]; + if (!qstrcmp(arg, "--disable-context-sharing")) { + options.applicationAttributes.removeAll(Qt::AA_ShareOpenGLContexts); + } else if (!qstrcmp(arg, "--gles")) { + options.applicationAttributes.append(Qt::AA_UseOpenGLES); + } else if (!qstrcmp(arg, "--software")) { + options.applicationAttributes.append(Qt::AA_UseSoftwareOpenGL); + } else if (!qstrcmp(arg, "--desktop")) { + options.applicationAttributes.append(Qt::AA_UseDesktopOpenGL); + } else if (!qstrcmp(arg, "--scaling")) { + options.applicationAttributes.append(Qt::AA_EnableHighDpiScaling); + } else if (!qstrcmp(arg, "--no-scaling")) { + options.applicationAttributes.append(Qt::AA_DisableHighDpiScaling); + } else if (!qstrcmp(arg, "--apptype")) { + if (++i >= argc) + usage(); + if (!qstrcmp(argv[i], "gui")) + options.applicationType = Options::QmlApplicationTypeGui; + } + } + + for (Qt::ApplicationAttribute a : qAsConst(options.applicationAttributes)) + QCoreApplication::setAttribute(a); + QScopedPointer<QGuiApplication> app; +#ifdef QT_WIDGETS_LIB + if (options.applicationType == Options::QmlApplicationTypeWidget) + app.reset(new QApplication(argc, argv)); +#endif + if (app.isNull()) + app.reset(new QGuiApplication(argc, argv)); + QCoreApplication::setApplicationName(QStringLiteral("Viewer for Triton qml tests")); + QCoreApplication::setOrganizationName(QStringLiteral("QtProject")); + QCoreApplication::setOrganizationDomain(QStringLiteral("qt-project.org")); + QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR)); + + const QStringList arguments = QCoreApplication::arguments(); + for (int i = 1, size = arguments.size(); i < size; ++i) { + if (!arguments.at(i).startsWith(QLatin1Char('-'))) { + options.url = parseUrlArgument(arguments.at(i)); + } else { + const QString lowerArgument = arguments.at(i).toLower(); + if (lowerArgument == QLatin1String("--maximized")) + options.maximized = true; + else if (lowerArgument == QLatin1String("--fullscreen")) + options.fullscreen = true; + else if (lowerArgument == QLatin1String("--transparent")) + options.transparent = true; + else if (lowerArgument == QLatin1String("--clip")) + options.clip = true; + else if (lowerArgument == QLatin1String("--no-version-detection")) + options.versionDetection = false; + else if (lowerArgument == QLatin1String("--slow-animations")) + options.slowAnimations = true; + else if (lowerArgument == QLatin1String("--quit")) + options.quitImmediately = true; + else if (lowerArgument == QLatin1String("-translation")) + options.translationFile = QLatin1String(argv[++i]); + else if (lowerArgument == QLatin1String("--resize-to-root")) + options.resizeViewToRootItem = true; + else if (lowerArgument == QLatin1String("--multisample")) + options.multisample = true; + else if (lowerArgument == QLatin1String("--core-profile")) + options.coreProfile = true; + else if (lowerArgument == QLatin1String("--verbose")) + options.verbose = true; + else if (lowerArgument == QLatin1String("-i") && i + 1 < size) + imports.append(arguments.at(++i)); + else if (lowerArgument == QLatin1String("-p") && i + 1 < size) + pluginPaths.append(arguments.at(++i)); + else if (lowerArgument == QLatin1String("--apptype")) + ++i; // Consume previously parsed argument + else if (lowerArgument == QLatin1String("--textrendertype") && i + 1 < size) + options.textRenderType = parseTextRenderType(arguments.at(++i)); + else if (lowerArgument == QLatin1String("--help") + || lowerArgument == QLatin1String("-help") + || lowerArgument == QLatin1String("--h") + || lowerArgument == QLatin1String("-h")) + usage(); + } + } + +#if QT_CONFIG(translation) + QTranslator translator; + QTranslator qtTranslator; + QString sysLocale = QLocale::system().name(); + if (qtTranslator.load(QLatin1String("qt_") + sysLocale, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) + app->installTranslator(&qtTranslator); + if (translator.load(QLatin1String("qmlscene_") + sysLocale, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) + app->installTranslator(&translator); + + QTranslator qmlTranslator; + if (!options.translationFile.isEmpty()) { + if (qmlTranslator.load(options.translationFile)) { + app->installTranslator(&qmlTranslator); + } else { + fprintf(stderr, "Could not load the translation file \"%s\"\n", + qPrintable(options.translationFile)); + } + } +#endif + + QQuickWindow::setTextRenderType(options.textRenderType); + + QUnifiedTimer::instance()->setSlowModeEnabled(options.slowAnimations); + + if (options.url.isEmpty()) +#if defined(QMLSCENE_BUNDLE) + displayOptionsDialog(&options); +#else + displayFileDialog(&options); +#endif + + int exitCode = 0; + + if (options.verbose) + puts(QLibraryInfo::build()); + + if (!options.url.isEmpty()) { + if (!options.versionDetection || checkVersion(options.url)) { +#if QT_CONFIG(translation) + QTranslator translator; +#endif + + // TODO: as soon as the engine construction completes, the debug service is + // listening for connections. But actually we aren't ready to debug anything. + QQmlEngine engine; + QPointer<QQmlComponent> component = new QQmlComponent(&engine); + for (int i = 0; i < imports.size(); ++i) + engine.addImportPath(imports.at(i)); + for (int i = 0; i < pluginPaths.size(); ++i) + engine.addPluginPath(pluginPaths.at(i)); + if (options.url.isLocalFile()) { + QFileInfo fi(options.url.toLocalFile()); +#if QT_CONFIG(translation) + loadTranslationFile(translator, fi.path()); +#endif + loadDummyDataFiles(engine, fi.path()); + } + + qmlRegisterSingletonType<QObject>("Qt.test.qtestroot", 1, 0, "QTestRootObject", testRootObject); + + QObject::connect(&engine, SIGNAL(quit()), QCoreApplication::instance(), SLOT(quit())); + QObject::connect(&engine, &QQmlEngine::exit, QCoreApplication::instance(), &QCoreApplication::exit); + component->loadUrl(options.url); + while (component->isLoading()) + QCoreApplication::processEvents(); + if ( !component->isReady() ) { + fprintf(stderr, "%s\n", qPrintable(component->errorString())); + return -1; + } + + QObject *topLevel = component->create(); + if (!topLevel && component->isError()) { + fprintf(stderr, "%s\n", qPrintable(component->errorString())); + return -1; + } + QScopedPointer<QQuickWindow> window(qobject_cast<QQuickWindow *>(topLevel)); + if (window) { + engine.setIncubationController(window->incubationController()); + } else { + QQuickItem *contentItem = qobject_cast<QQuickItem *>(topLevel); + if (contentItem) { + QQuickView* qxView = new QQuickView(&engine, NULL); + window.reset(qxView); + // Set window default properties; the qml can still override them + if (options.resizeViewToRootItem) + qxView->setResizeMode(QQuickView::SizeViewToRootObject); + else + qxView->setResizeMode(QQuickView::SizeRootObjectToView); + qxView->setContent(options.url, component, contentItem); + } + } + +#ifdef TRITON_ENABLE_TOUCH_EMULATION + QScopedPointer<MouseTouchAdaptor> mouseTouchAdaptor; + if (QTouchDevice::devices().isEmpty()) + mouseTouchAdaptor.reset(MouseTouchAdaptor::instance()); +#endif + + if (window) { + setWindowTitle(options.verbose, topLevel, window.data()); +#if QT_CONFIG(opengl) + if (options.verbose) + new DiagnosticGlContextCreationListener(window.data()); +#endif + QSurfaceFormat surfaceFormat = window->requestedFormat(); + if (options.multisample) + surfaceFormat.setSamples(16); + if (options.transparent) { + surfaceFormat.setAlphaBufferSize(8); + window->setClearBeforeRendering(true); + window->setColor(QColor(Qt::transparent)); + window->setFlags(Qt::FramelessWindowHint); + } + if (options.coreProfile) { + surfaceFormat.setVersion(4, 1); + surfaceFormat.setProfile(QSurfaceFormat::CoreProfile); + } + window->setFormat(surfaceFormat); + + if (window->flags() == Qt::Window) // Fix window flags unless set by QML. + window->setFlags(Qt::Window | Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::WindowFullscreenButtonHint); + + if (options.fullscreen) + window->showFullScreen(); + else if (options.maximized) + window->showMaximized(); + else if (!window->isVisible()) + window->show(); + } + + if (options.quitImmediately) + QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection); + + // Now would be a good time to inform the debug service to start listening. + + exitCode = app->exec(); + +#ifdef QML_RUNTIME_TESTING + RenderStatistics::printTotalStats(); +#endif + // Ready to exit. Notice that the component might be owned by + // QQuickView if one was created. That case is tracked by + // QPointer, so it is safe to delete the component here. + delete component; + } + } + + return exitCode; +} + +#include "triton-qmlscene.moc" diff --git a/tests/triton-qmlscene/triton-qmlscene.pro b/tests/triton-qmlscene/triton-qmlscene.pro new file mode 100644 index 00000000..e0fa24ee --- /dev/null +++ b/tests/triton-qmlscene/triton-qmlscene.pro @@ -0,0 +1,16 @@ +TEMPLATE = app +TARGET = triton-qmlscene + +QT += qml quick quick-private gui-private core-private + +SOURCES = triton-qmlscene.cpp + +unix:!macos: { + CONFIG += link_pkgconfig + PKGCONFIG += xcb x11 xi + SOURCES += ../../src/MouseTouchAdaptor.cpp + HEADERS += ../../src/MouseTouchAdaptor.h + DEFINES += TRITON_ENABLE_TOUCH_EMULATION + INCLUDEPATH += $$SOURCE_DIR/src + QT += testlib +} |