summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSami Nurmenniemi <sami.nurmenniemi@qt.io>2019-01-24 14:45:19 +0200
committerSami Nurmenniemi <sami.nurmenniemi@qt.io>2019-02-04 11:39:20 +0000
commit32bd51b0ee16696488f1476c004e944b44f76eb6 (patch)
tree13b90fd9411dc22de79706c2b916111db8d53ffb
parent64f65e26feb4f6b0b3ac31cfc4e22c5971c1c41d (diff)
Enable boot2qt launcher automatic demo mode
Task-number: QTBUG-72852 Change-Id: I8e2ab58a2a0b13f5a1ce67a24c5c75b809683324 Reviewed-by: Tuomas Heimonen <tuomas.heimonen@qt.io>
-rw-r--r--qml.qrc4
-rw-r--r--qml/DemoHeader.qml1
-rw-r--r--qml/DemoMode.qml395
-rw-r--r--qml/DetailView.qml2
-rw-r--r--qml/GlobalIndicator.qml (renamed from qml/FpsIndicator.qml)12
-rw-r--r--qml/Header.qml1
-rw-r--r--qml/LaunchScreen.qml1
-rw-r--r--qml/LauncherCheckBox.qml74
-rw-r--r--qml/LayoutSettings.qml56
-rw-r--r--qml/MainWindow.qml40
-rw-r--r--src/automationhelper.cpp91
-rw-r--r--src/automationhelper.h47
-rw-r--r--src/main.cpp2
-rw-r--r--src/settingsmanager.cpp13
-rw-r--r--src/settingsmanager.h6
-rw-r--r--startup.pro6
16 files changed, 701 insertions, 50 deletions
diff --git a/qml.qrc b/qml.qrc
index 615bfc0..102bd9d 100644
--- a/qml.qrc
+++ b/qml.qrc
@@ -22,6 +22,8 @@
<file>qml/BusyIndicator.qml</file>
<file>qml/MainWindow.qml</file>
<file>qml/FlickSlider.qml</file>
- <file>qml/FpsIndicator.qml</file>
+ <file>qml/LauncherCheckBox.qml</file>
+ <file>qml/DemoMode.qml</file>
+ <file>qml/GlobalIndicator.qml</file>
</qresource>
</RCC>
diff --git a/qml/DemoHeader.qml b/qml/DemoHeader.qml
index 18c4016..555fff2 100644
--- a/qml/DemoHeader.qml
+++ b/qml/DemoHeader.qml
@@ -91,6 +91,7 @@ Rectangle {
Image {
id: applicationCloseButton
+ objectName: "applicationCloseButton"
height: parent.height
width: height
source: "icons/close_icon.svg"
diff --git a/qml/DemoMode.qml b/qml/DemoMode.qml
new file mode 100644
index 0000000..f5b8dcd
--- /dev/null
+++ b/qml/DemoMode.qml
@@ -0,0 +1,395 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Device Creation.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** 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 or (at your option) 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.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-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+import QtQuick 2.0
+import AutomationHelper 1.0
+
+Item {
+ property var visibleItem
+ property var demoHeader
+ property var launcherHeader
+ property var visibleItemName: visibleItem ? visibleItem.objectName : 0
+ property bool demoModeSeleted: globalSettings.demoModeSelected
+ property bool demoIsRunning: false
+
+ property int demoInitialStartTime: 2000 // How fast demo starts after turning the demo on
+ property int demoIdleStartTime: 2 * 60 * 1000 // How fast demo starts after idle
+ property int demoStepDuration: 2000
+ property int applicationWaitDuration: 1000
+ property int verticalFlickVelocity: 1000
+ property int horizontalFlickVelocity: 1000
+
+ onDemoModeSeletedChanged: {
+ if (demoModeSeleted) {
+ demoStartCounter.interval = demoInitialStartTime
+ demoStartCounter.start()
+ } else {
+ demoStartCounter.stop()
+ stopDemos()
+ }
+ }
+
+ /*
+ Start the demo sequence. First demo to start depends on the current screen.
+ */
+ function startDemos() {
+ console.log("Start automatic demo mode")
+ if (visibleItemName === "settingsView") {
+ settingsDemoAnimation.start()
+ } else if ((visibleItemName === "launchScreen") || (visibleItemName === "detailView")) {
+ switchToSettingScreenAnimation.start()
+ } else {
+ exitFromRunningDemoAnimation.start()
+ }
+
+ demoIsRunning = true
+ }
+
+ /*
+ Stop all currently running demos
+ */
+ function stopDemos() {
+ console.log("Stop automatic demo mode")
+ switchToSettingScreenAnimation.stop()
+ settingsDemoAnimation.stop()
+ gridViewDemoAnimation.stop()
+ graphicsEffectsDemoAnimation.stop()
+ qtChartsDemoAnimation.stop()
+ switchToDetailViewAnimation.stop()
+ detailViewDemoAnimation.stop()
+ eBikeViewDemoAnimation.stop()
+ demoIsRunning = false
+
+ // Restart demo after idle time
+ if (demoModeSeleted) {
+ demoStartCounter.interval = demoIdleStartTime
+ demoStartCounter.restart()
+ }
+ }
+
+ Timer {
+ id: demoStartCounter
+ repeat: false
+ onTriggered: startDemos()
+ }
+
+ /*
+ Cet index of with \a title from the \a applicationList
+ */
+ function applicationIndex(applicationList, title) {
+ var i
+ var applicationListModel = applicationList.model
+
+ // count and get() do not work on QAbstractItemModel, rowCount and query must be used
+ for (i=0; i<applicationListModel.rowCount(); i++) {
+ if (applicationListModel.query(i, "name") === title) {
+ return i
+ }
+ }
+ return -1
+ }
+
+ /*
+ Click application with \a title from the launcher with \a launcherName
+
+ Returns \c true if application launcher was clicked
+ */
+ function clickApplicationLauncher(launcherName, title) {
+ var applicationList = automationHelper.findChildObject(visibleItem, launcherName)
+ var index = applicationIndex(applicationList, title)
+
+ if (index !== -1) {
+ applicationList.currentIndex = index;
+ automationHelper.click(applicationList.currentItem)
+ return true
+ }
+ return false
+ }
+
+ /*
+ Flick flickable with objectName \a objName with \a amountHorizontal and \a amountVertical
+ */
+ function flickUpDown(objName, amountHorizontal, amountVertical) {
+ var gridView = automationHelper.findChildObject(visibleItem, objName)
+ if (gridView)
+ gridView.flick(amountHorizontal, amountVertical)
+ else
+ console.log("no child " + objName)
+ }
+
+ AutomationHelper {
+ id: automationHelper
+ }
+
+ // Exit from already running demo
+ SequentialAnimation {
+ id: exitFromRunningDemoAnimation
+ ScriptAction { script: console.log("Exit from running demo") }
+ PauseAnimation { duration: demoStepDuration }
+ ScriptAction { script: automationHelper.clickChildObject(demoHeader, "applicationCloseButton") }
+ PauseAnimation { duration: applicationWaitDuration }
+
+ // Start next demo
+ ScriptAction { script: switchToSettingScreenAnimation.start() }
+ }
+
+ // Switch to settings screen
+ SequentialAnimation {
+ id: switchToSettingScreenAnimation
+ ScriptAction { script: console.log("Switch to settings screen") }
+ PauseAnimation { duration: demoStepDuration }
+ ScriptAction { script: automationHelper.clickChildObject(launcherHeader, "settingsMenuIcon") }
+ PauseAnimation { duration: applicationWaitDuration }
+
+ // Start next demo
+ ScriptAction { script: settingsDemoAnimation.start() }
+ }
+
+ // Settings screen
+ SequentialAnimation {
+ id: settingsDemoAnimation
+
+ function clickSettingsItem(title) {
+ var i
+ var settingsList = automationHelper.findChildObject(visibleItem, "settingsList")
+ var settingsModel = settingsList.model
+
+ // count + get() can be used on ListModel
+ for (i=0; i<settingsModel.count; i++) {
+ if (settingsModel.get(i).title === title) {
+ settingsList.currentIndex = i
+ automationHelper.click(settingsList.currentItem)
+ }
+ }
+ }
+
+ ScriptAction { script: console.log("Settings demo") }
+ PauseAnimation { duration: applicationWaitDuration }
+
+ // Make sure the grid layout is on
+ ScriptAction { script: automationHelper.clickChildObject(visibleItem, "gridLayoutButton") }
+ PauseAnimation { duration: demoStepDuration }
+
+ // Show some settings pages
+ ScriptAction { script: settingsDemoAnimation.clickSettingsItem("Network") }
+ PauseAnimation { duration: demoStepDuration }
+ ScriptAction { script: settingsDemoAnimation.clickSettingsItem("Date & Time") }
+ PauseAnimation { duration: demoStepDuration }
+ ScriptAction { script: settingsDemoAnimation.clickSettingsItem("About Qt") }
+ PauseAnimation { duration: demoStepDuration }
+
+ // Go back to launcher screen and start next demo
+ ScriptAction { script: automationHelper.clickChildObject(visibleItem, "settingsBackButton") }
+ ScriptAction { script: gridViewDemoAnimation.start() }
+ }
+
+ // Grid view demo
+ SequentialAnimation {
+ id: gridViewDemoAnimation
+
+ // Flick the grid up and down
+ ScriptAction { script: console.log("Grid view demo") }
+ PauseAnimation { duration: applicationWaitDuration }
+ ScriptAction { script: flickUpDown("launcherGridView", 0, -verticalFlickVelocity) }
+ PauseAnimation { duration: demoStepDuration }
+ ScriptAction { script: flickUpDown("launcherGridView", 0, verticalFlickVelocity) }
+
+ // Start next demo
+ ScriptAction { script: graphicsEffectsDemoAnimation.start() }
+ }
+
+ // Graphics effects demo
+ SequentialAnimation {
+ id: graphicsEffectsDemoAnimation
+
+ function clickGraphicsEffectItem(title) {
+ var i
+ var effectList = automationHelper.findChildObject(visibleItem, "graphicsEffectsList")
+ var effectListModel = effectList.model
+
+ // count + get() can be used on ListModel
+ for (i=0; i<effectListModel.count; i++) {
+ if (effectListModel.get(i).name === title) {
+ effectList.currentIndex = i
+ automationHelper.click(effectList.currentItem)
+ }
+ }
+ }
+
+ // Start the demo application
+ ScriptAction { script: console.log("Graphics effects demo") }
+ PauseAnimation { duration: demoStepDuration }
+ ScriptAction {
+ script: {
+ // If the application does not exist, move on to next demo
+ if (!clickApplicationLauncher("launcherGridView", "Graphical Effects")) {
+ qtChartsDemoAnimation.start()
+ graphicsEffectsDemoAnimation.stop()
+ }
+ }
+ }
+ PauseAnimation { duration: applicationWaitDuration }
+
+ // Show few graphics effects
+ ScriptAction { script: graphicsEffectsDemoAnimation.clickGraphicsEffectItem("Colorize") }
+ PauseAnimation { duration: demoStepDuration }
+ ScriptAction { script: graphicsEffectsDemoAnimation.clickGraphicsEffectItem("Gaussian Blur") }
+ PauseAnimation { duration: demoStepDuration }
+ ScriptAction { script: graphicsEffectsDemoAnimation.clickGraphicsEffectItem("Wave (custom)") }
+ PauseAnimation { duration: demoStepDuration }
+ ScriptAction { script: automationHelper.clickChildObject(demoHeader, "applicationCloseButton") }
+
+ // Start next demo
+ ScriptAction { script: qtChartsDemoAnimation.start() }
+ }
+
+ // Qt charts demo
+ SequentialAnimation {
+ id: qtChartsDemoAnimation
+ property var chartsList
+
+ // Start the demo application and get the chart list
+ ScriptAction { script: console.log("Qt charts demo") }
+ PauseAnimation { duration: demoStepDuration }
+ ScriptAction { script: flickUpDown("launcherGridView", 0, -1.5 * verticalFlickVelocity) }
+ PauseAnimation { duration: demoStepDuration }
+ ScriptAction {
+ script: {
+ // If the application does not exist, move on to next demo
+ if (!clickApplicationLauncher("launcherGridView", "Qt Charts - Gallery")) {
+ switchToDetailViewAnimation.start()
+ qtChartsDemoAnimation.stop()
+ }
+ }
+ }
+ PauseAnimation { duration: applicationWaitDuration }
+ ScriptAction { script: qtChartsDemoAnimation.chartsList = automationHelper.findChildObject(visibleItem, "chartsListView") }
+
+ // Flick through some of the charts
+ ScriptAction { script: qtChartsDemoAnimation.chartsList.currentIndex = 1 }
+ PauseAnimation { duration: demoStepDuration }
+ ScriptAction { script: qtChartsDemoAnimation.chartsList.currentIndex = 2 }
+ PauseAnimation { duration: demoStepDuration }
+ ScriptAction { script: qtChartsDemoAnimation.chartsList.currentIndex = 3 }
+ PauseAnimation { duration: demoStepDuration }
+ ScriptAction { script: qtChartsDemoAnimation.chartsList.currentIndex = 4 }
+ PauseAnimation { duration: demoStepDuration }
+ ScriptAction { script: qtChartsDemoAnimation.chartsList.currentIndex = 5 }
+ PauseAnimation { duration: demoStepDuration }
+ ScriptAction { script: qtChartsDemoAnimation.chartsList.currentIndex = 6 }
+ PauseAnimation { duration: demoStepDuration }
+ ScriptAction { script: qtChartsDemoAnimation.chartsList.currentIndex = 7 }
+ PauseAnimation { duration: demoStepDuration }
+ ScriptAction { script: qtChartsDemoAnimation.chartsList.currentIndex = 8 }
+ PauseAnimation { duration: demoStepDuration }
+ ScriptAction { script: qtChartsDemoAnimation.chartsList.currentIndex = 9 }
+ PauseAnimation { duration: demoStepDuration }
+ ScriptAction { script: automationHelper.clickChildObject(demoHeader, "applicationCloseButton") }
+
+ // Start next demo
+ ScriptAction { script: switchToDetailViewAnimation.start() }
+ }
+
+ // Switch to detail view demo
+ SequentialAnimation {
+ id: switchToDetailViewAnimation
+ ScriptAction { script: console.log("Switch to detail view demo") }
+ PauseAnimation { duration: demoStepDuration }
+ ScriptAction { script: automationHelper.clickChildObject(launcherHeader, "settingsMenuIcon") }
+ PauseAnimation { duration: applicationWaitDuration }
+ ScriptAction { script: automationHelper.clickChildObject(visibleItem, "detailLayoutButton") }
+ PauseAnimation { duration: demoStepDuration }
+ ScriptAction { script: automationHelper.clickChildObject(visibleItem, "settingsBackButton") }
+
+ // Start next demo
+ ScriptAction { script: detailViewDemoAnimation.start() }
+ }
+
+ // Detail view demo
+ SequentialAnimation {
+ id: detailViewDemoAnimation
+
+ // Flick the list left and right
+ ScriptAction { script: console.log("Detail view demo") }
+ PauseAnimation { duration: applicationWaitDuration }
+ ScriptAction { script: flickUpDown("detailListView", -horizontalFlickVelocity, 0) }
+ PauseAnimation { duration: demoStepDuration }
+ ScriptAction { script: flickUpDown("detailListView", horizontalFlickVelocity, 0) }
+ PauseAnimation { duration: demoStepDuration }
+ ScriptAction { script: clickApplicationLauncher("detailListView", "Media Player") }
+ PauseAnimation { duration: demoStepDuration }
+ ScriptAction { script: clickApplicationLauncher("detailListView", "Quick Controls 2") }
+
+ // Start next demo
+ ScriptAction { script: eBikeViewDemoAnimation.start() }
+ }
+
+ // E-Bike view demo
+ SequentialAnimation {
+ id: eBikeViewDemoAnimation
+
+ // Start the demo application
+ ScriptAction { script: console.log("E-Bike demo") }
+ PauseAnimation { duration: demoStepDuration }
+ ScriptAction {
+ script: {
+ // If the application does not exist, move on to next demo
+ if (!clickApplicationLauncher("detailListView", "E-Bike")) {
+ startDemos()
+ eBikeViewDemoAnimation.stop()
+ }
+ }
+ }
+ PauseAnimation { duration: demoStepDuration }
+ ScriptAction { script: automationHelper.clickChildObject(visibleItem, "detailStartButton") }
+ PauseAnimation { duration: applicationWaitDuration }
+
+ // Turn on lights
+ ScriptAction { script: automationHelper.clickChildObject(visibleItem, "ebikeLightsButton") }
+ PauseAnimation { duration: demoStepDuration }
+
+ // Go to navigation view and come back
+ ScriptAction { script: automationHelper.clickChildObject(visibleItem, "ebikeNaviButton") }
+ PauseAnimation { duration: demoStepDuration }
+ ScriptAction { script: automationHelper.clickChildObject(visibleItem, "ebikeSpeedView") }
+ PauseAnimation { duration: demoStepDuration }
+
+ // Go to stats view and come back
+ ScriptAction { script: automationHelper.clickChildObject(visibleItem, "ebikeStatsButton") }
+ PauseAnimation { duration: demoStepDuration }
+ ScriptAction { script: automationHelper.clickChildObject(visibleItem, "ebikeSpeedView") }
+ PauseAnimation { duration: 5*demoStepDuration }
+
+ // Go back to main view
+ ScriptAction { script: automationHelper.clickChildObject(demoHeader, "applicationCloseButton") }
+
+ // Start demos again
+ PauseAnimation { duration: 2 * demoStepDuration }
+ ScriptAction { script: startDemos() }
+ }
+}
diff --git a/qml/DetailView.qml b/qml/DetailView.qml
index 899ae7f..cd39e9d 100644
--- a/qml/DetailView.qml
+++ b/qml/DetailView.qml
@@ -105,6 +105,7 @@ Item {
QtButton {
id: startButton
+ objectName: "detailStartButton"
height: detailInformation.height * 0.14
width: height * 3
anchors.left: parent.left
@@ -129,6 +130,7 @@ Item {
ListView {
id: thumbList
+ objectName: "detailListView"
anchors.fill: parent
anchors.margins: viewSettings.pageMargin * 0.5
orientation: ListView.Horizontal
diff --git a/qml/FpsIndicator.qml b/qml/GlobalIndicator.qml
index b83cb27..f68cbbd 100644
--- a/qml/FpsIndicator.qml
+++ b/qml/GlobalIndicator.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt for Device Creation.
@@ -31,25 +31,25 @@ import QtQuick 2.4
Item {
id: fps
property bool enabled
+ property alias text: globalIndicatorLabel.text
opacity: enabled ? 1 : 0
Behavior on opacity { NumberAnimation { duration: 500 } }
anchors.bottom: parent.bottom;
anchors.left: parent.left;
- width: fpsLabel.width
- height: fpsLabel.height
+ width: globalIndicatorLabel.width
+ height: globalIndicatorLabel.height
Rectangle {
color: "black"
opacity: 0.5
- anchors.fill: fpsLabel
+ anchors.fill: globalIndicatorLabel
}
Text {
- id: fpsLabel;
+ id: globalIndicatorLabel;
color: "white"
- text: "FPS: " + engine.fps
font.pixelSize: engine.sensibleButtonSize() * 0.2
}
}
diff --git a/qml/Header.qml b/qml/Header.qml
index 8283de6..f9cf920 100644
--- a/qml/Header.qml
+++ b/qml/Header.qml
@@ -38,6 +38,7 @@ Item {
signal menuClicked()
Image {
+ objectName: "settingsMenuIcon"
anchors.left: parent.left
anchors.top: parent.top
source: "icons/settingsmenu_launcher_icon.svg"
diff --git a/qml/LaunchScreen.qml b/qml/LaunchScreen.qml
index 7d369b7..70e9c71 100644
--- a/qml/LaunchScreen.qml
+++ b/qml/LaunchScreen.qml
@@ -35,6 +35,7 @@ Item {
GridView {
id: grid
+ objectName: "launcherGridView"
anchors.fill: parent
anchors.margins: viewSettings.pageMargin * 0.5
anchors.topMargin: viewSettings.pageMargin
diff --git a/qml/LauncherCheckBox.qml b/qml/LauncherCheckBox.qml
new file mode 100644
index 0000000..bf81b80
--- /dev/null
+++ b/qml/LauncherCheckBox.qml
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Device Creation.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** 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 or (at your option) 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.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-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+
+CheckBox {
+ id: checkBox
+ text: qsTr("Flip screen")
+
+ indicator: Rectangle {
+ implicitHeight: 26
+ implicitWidth: 26
+ height: pluginMain.buttonHeight
+ width: height
+ x: checkBox.leftPadding
+ y: parent.height / 2 - height / 2
+ color: "transparent"
+ border.color: "#9d9faa"
+ border.width: 2
+ radius: 4
+
+ Image {
+ anchors.centerIn: parent
+ sourceSize.width: parent.width
+ sourceSize.height: parent.height
+ width: parent.width * 0.9
+ height: width
+ source: "icons/checkmark.svg"
+ visible: checkBox.checked
+ antialiasing: true
+ smooth: true
+ fillMode: Image.PreserveAspectFit
+ }
+ }
+
+ contentItem: Text {
+ text: checkBox.text
+ font.family: appFont
+ font.pixelSize: pluginMain.subTitleFontSize
+ opacity: enabled ? 1.0 : 0.3
+ color: checkBox.down ? "#17a81a" : "#41cd52"
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ leftPadding: checkBox.indicator.width + checkBox.spacing
+ height: pluginMain.fieldTextHeight
+ font.styleName: checkBox.checked ? "Bold" : "Regular"
+ }
+}
diff --git a/qml/LayoutSettings.qml b/qml/LayoutSettings.qml
index 8518030..4e4d08b 100644
--- a/qml/LayoutSettings.qml
+++ b/qml/LayoutSettings.qml
@@ -67,6 +67,7 @@ Item {
spacing: root.margin
ImageTextDelegate {
+ objectName: "gridLayoutButton"
height: root.buttonSize
width: height
onClicked: root.gridSelected = true
@@ -77,6 +78,7 @@ Item {
}
ImageTextDelegate {
+ objectName: "detailLayoutButton"
height: root.buttonSize
width: height
onClicked: root.gridSelected = false
@@ -124,54 +126,30 @@ Item {
}
}
}
- CheckBox {
- id: checkBox
+
+ LauncherCheckBox {
+ id: flipScreenCheckBox
text: qsTr("Flip screen")
checked: globalSettings.rotationSelected
anchors.top: column.bottom
anchors.left: parent.left
anchors.topMargin: root.margin
- indicator: Rectangle {
- implicitHeight: 26
- implicitWidth: 26
- height: pluginMain.buttonHeight
- width: height
- x: checkBox.leftPadding
- y: parent.height / 2 - height / 2
- color: "transparent"
- border.color: "#9d9faa"
- border.width: 2
- radius: 4
-
- Image {
- anchors.centerIn: parent
- sourceSize.width: parent.width
- sourceSize.height: parent.height
- width: parent.width * 0.9
- height: width
- source: "icons/checkmark.svg"
- visible: checkBox.checked
- antialiasing: true
- smooth: true
- fillMode: Image.PreserveAspectFit
- }
+ onCheckedChanged: {
+ globalSettings.rotationSelected = checked
}
+ }
+
+ LauncherCheckBox {
+ id: demoModeCheckBox
+ text: qsTr("Demo mode")
+ checked: globalSettings.demoModeSelected
+ anchors.top: column.bottom
+ anchors.left: flipScreenCheckBox.right
+ anchors.topMargin: root.margin
- contentItem: Text {
- text: checkBox.text
- font.family: appFont
- font.pixelSize: pluginMain.subTitleFontSize
- opacity: enabled ? 1.0 : 0.3
- color: checkBox.down ? "#17a81a" : "#41cd52"
- horizontalAlignment: Text.AlignHCenter
- verticalAlignment: Text.AlignVCenter
- leftPadding: checkBox.indicator.width + checkBox.spacing
- height: pluginMain.fieldTextHeight
- font.styleName: checkBox.checked ? "Bold" : "Regular"
- }
onCheckedChanged: {
- globalSettings.rotationSelected = checked
+ globalSettings.demoModeSelected = checked
}
}
}
diff --git a/qml/MainWindow.qml b/qml/MainWindow.qml
index 0249773..95c005d 100644
--- a/qml/MainWindow.qml
+++ b/qml/MainWindow.qml
@@ -45,6 +45,7 @@ Item {
Component {
id: gridComponent
LaunchScreen {
+ objectName: "launchScreen"
id: launchScreen
}
}
@@ -52,6 +53,7 @@ Item {
Component {
id: detailComponent
DetailView {
+ objectName: "detailView"
id: detailView
}
}
@@ -319,8 +321,44 @@ Item {
}
}
- FpsIndicator {
+ GlobalIndicator {
+ id: fps
enabled: engine.fpsEnabled
+ text: "FPS: " + engine.fps
}
+
+ GlobalIndicator {
+ id: demoModeIndicator
+ enabled: demoMode.demoIsRunning
+ text: qsTr("DEMO MODE - Tap screen to use")
+ anchors.bottom: fps.enabled ? fps.top : parent.bottom
+ }
+ }
+
+ DemoMode {
+ id: demoMode
+ demoHeader: demoHeader
+ launcherHeader: header
+ visibleItem: (applicationLoader.item && (applicationLoader.item.objectName !== "empty")) ?
+ applicationLoader.item : contentLoader.item
+ }
+
+ // MouseArea for capturing mouse clicks/presses
+ MouseArea {
+ anchors.fill: parent
+ propagateComposedEvents: true
+ enabled: demoMode.demoIsRunning
+
+ // Press or click
+ function pressedOrClicked(mouse) {
+ mouse.accepted = false
+ if (mouse.source === Qt.MouseEventSynthesizedByApplication)
+ return
+ demoMode.stopDemos()
+ mouse.accepted = true
+ }
+
+ onClicked: pressedOrClicked(mouse)
+ onPressed: pressedOrClicked(mouse)
}
}
diff --git a/src/automationhelper.cpp b/src/automationhelper.cpp
new file mode 100644
index 0000000..b4c6a99
--- /dev/null
+++ b/src/automationhelper.cpp
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Device Creation.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** 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 or (at your option) 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.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-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "automationhelper.h"
+#include <QCoreApplication>
+#include <QApplication>
+#include <QQuickWindow>
+
+AutomationHelper::AutomationHelper(QObject* parent) :
+ QObject(parent)
+{
+}
+
+/*!
+ * \brief Click center of given QQuickItem
+ * \param item Item to click
+ */
+void AutomationHelper::click(QQuickItem* item)
+{
+ QQuickWindow* window = item->window();
+ if (!window) {
+ qWarning()<<"No window for item "<<item;
+ return;
+ }
+
+ int centerX = static_cast<int>(item->width()/2);
+ int centerY = static_cast<int>(item->height()/2);
+ QPointF globalCoordinates = item->mapToGlobal(QPoint(centerX, centerY));
+ QPointF windowCoordinates = window->mapFromGlobal(globalCoordinates.toPoint());
+
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, windowCoordinates, windowCoordinates, windowCoordinates,
+ Qt::MouseButton::LeftButton, Qt::NoButton, Qt::NoModifier, Qt::MouseEventSynthesizedByApplication);
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, windowCoordinates, windowCoordinates, windowCoordinates,
+ Qt::MouseButton::LeftButton, Qt::NoButton, Qt::NoModifier, Qt::MouseEventSynthesizedByApplication);
+ QApplication::instance()->sendEvent(window, &pressEvent);
+ QApplication::instance()->sendEvent(window, &releaseEvent);
+}
+
+/*!
+ * \brief Click center of child item of given QQuickItem
+ * \param item Item which child to click
+ * \param childObjectName Object name of the child to click
+ */
+void AutomationHelper::clickChildObject(QQuickItem* item, QString childObjectName)
+{
+ QQuickItem* obj = findChildObject(item, childObjectName);
+ if (!obj) {
+ qWarning()<<"No such child "<<childObjectName<<" for "<<item;
+ return;
+ }
+
+ click(obj);
+}
+
+/*!
+ * \brief Find child item of given QQuickItem
+ *
+ * This function is needed for exposing findChildObject to QML
+ * \param item Item which child to find
+ * \param childObjectName Object name of the child to find
+ * \return found child
+ */
+QQuickItem* AutomationHelper::findChildObject(QQuickItem* item, QString childObjectName)
+{
+ return item->findChild<QQuickItem*>(childObjectName);
+}
diff --git a/src/automationhelper.h b/src/automationhelper.h
new file mode 100644
index 0000000..8ed5000
--- /dev/null
+++ b/src/automationhelper.h
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Device Creation.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** 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 or (at your option) 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.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-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef AUTOMATIONHELPER_H
+#define AUTOMATIONHELPER_H
+
+#include <QObject>
+#include <QQuickItem>
+
+class AutomationHelper : public QObject
+{
+ Q_OBJECT
+public:
+ AutomationHelper(QObject *parent = 0);
+
+public slots:
+ void click(QQuickItem* item);
+ void clickChildObject(QQuickItem* item, QString childObjectName);
+ QQuickItem* findChildObject(QQuickItem* item, QString childObjectName);
+};
+
+#endif // AUTOMATIONHELPER_H
diff --git a/src/main.cpp b/src/main.cpp
index 4c41ca6..792351f 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -51,6 +51,7 @@
#include "settingsmanager.h"
#include "imageproviders.h"
#include "circularindicator.h"
+#include "automationhelper.h"
void displayHelp(const char *appName)
{
@@ -121,6 +122,7 @@ int main(int argc, char **argv)
qmlRegisterType<ApplicationsModel>("com.qtcompany.B2QtLauncher", 1, 0, "LauncherApplicationsModel");
qmlRegisterType<Engine>("com.qtcompany.B2QtLauncher", 1, 0, "LauncherEngine");
qmlRegisterType<CircularIndicator>("Circle", 1, 0, "CircularIndicator");
+ qmlRegisterType<AutomationHelper>("AutomationHelper", 1, 0, "AutomationHelper");
QQmlApplicationEngine engine;
SettingsManager settings;
diff --git a/src/settingsmanager.cpp b/src/settingsmanager.cpp
index 55e5def..e8dfc77 100644
--- a/src/settingsmanager.cpp
+++ b/src/settingsmanager.cpp
@@ -91,3 +91,16 @@ void SettingsManager::setRotationSelected(bool enabled)
setValue("rotationSelected", enabled);
emit rotationSelectedChanged(enabled);
}
+
+bool SettingsManager::demoModeSelected()
+{
+ return getValue("demoModeSelected", false).toBool();
+}
+
+void SettingsManager::setDemoModeSelected(bool enabled)
+{
+ if (demoModeSelected() == enabled)
+ return;
+ setValue("demoModeSelected", enabled);
+ emit demoModeSelectedChanged(enabled);
+}
diff --git a/src/settingsmanager.h b/src/settingsmanager.h
index cc41a0a..50a8900 100644
--- a/src/settingsmanager.h
+++ b/src/settingsmanager.h
@@ -36,7 +36,7 @@ class SettingsManager : public QObject
{
Q_OBJECT
public:
- explicit SettingsManager(QObject *parent = 0);
+ explicit SettingsManager(QObject *parent = nullptr);
~SettingsManager();
Q_INVOKABLE QVariant getValue(const QString& key, const QVariant &defaultValue);
@@ -53,14 +53,18 @@ public:
void setMouseSelected(bool enabled);
Q_PROPERTY (bool rotationSelected READ rotationSelected WRITE setRotationSelected NOTIFY rotationSelectedChanged)
+ Q_PROPERTY (bool demoModeSelected READ demoModeSelected WRITE setDemoModeSelected NOTIFY demoModeSelectedChanged)
bool rotationSelected();
void setRotationSelected(bool enabled);
+ bool demoModeSelected();
+ void setDemoModeSelected(bool enabled);
signals:
void gridSelectedChanged(bool enabled);
void mouseSelectedChanged(bool enabled);
void rotationSelectedChanged(bool enabled);
+ void demoModeSelectedChanged(bool enabled);
private:
QSettings m_settings;
diff --git a/startup.pro b/startup.pro
index 495271c..2aa5599 100644
--- a/startup.pro
+++ b/startup.pro
@@ -15,7 +15,8 @@ HEADERS += \
src/applicationsettings.h \
src/settingsmanager.h \
src/imageproviders.h \
- src/circularindicator.h
+ src/circularindicator.h \
+ src/automationhelper.h
SOURCES += src/main.cpp \
src/engine.cpp \
@@ -24,7 +25,8 @@ SOURCES += src/main.cpp \
src/applicationsettings.cpp \
src/settingsmanager.cpp \
src/imageproviders.cpp \
- src/circularindicator.cpp
+ src/circularindicator.cpp \
+ src/automationhelper.cpp
target.path = $$[INSTALL_ROOT]/usr/bin