summaryrefslogtreecommitdiffstats
path: root/tests/manual/quick
diff options
context:
space:
mode:
Diffstat (limited to 'tests/manual/quick')
-rw-r--r--tests/manual/quick/CMakeLists.txt2
-rw-r--r--tests/manual/quick/geopermission/CMakeLists.txt63
-rw-r--r--tests/manual/quick/geopermission/Info.plist32
-rw-r--r--tests/manual/quick/geopermission/geolocation.html32
-rw-r--r--tests/manual/quick/geopermission/main.cpp39
-rw-r--r--tests/manual/quick/geopermission/tst_geopermission.qml28
-rw-r--r--tests/manual/quick/pdf/bookmarks-list.qml136
-rw-r--r--tests/manual/quick/pdf/bookmarks.qml147
-rw-r--r--tests/manual/quick/pdf/gridview.qml62
-rw-r--r--tests/manual/quick/pdf/listview.qml58
-rw-r--r--tests/manual/quick/pdf/multipleDocuments.qml182
-rw-r--r--tests/manual/quick/pdf/pdfPageView.qml316
-rw-r--r--tests/manual/quick/pdf/pessimizedListView.qml69
-rw-r--r--tests/manual/quick/pdf/simplest.qml53
-rw-r--r--tests/manual/quick/pdf/test.pdfbin80045 -> 76633 bytes
-rw-r--r--tests/manual/quick/pdf/underscoredLinks.qml146
-rw-r--r--tests/manual/quick/pdf/withdoc.qml99
-rw-r--r--tests/manual/quick/quick.pro5
-rw-r--r--tests/manual/quick/touchbrowser/AddressBar.qml55
-rw-r--r--tests/manual/quick/touchbrowser/CMakeLists.txt31
-rw-r--r--tests/manual/quick/touchbrowser/MockTouchPoint.qml26
-rw-r--r--tests/manual/quick/touchbrowser/main.cpp68
-rw-r--r--tests/manual/quick/touchbrowser/main.qml35
-rw-r--r--tests/manual/quick/touchbrowser/resources.qrc (renamed from tests/manual/quick/touchbrowser/qml.qrc)1
-rw-r--r--tests/manual/quick/touchbrowser/touchbrowser.pro22
-rw-r--r--tests/manual/quick/touchbrowser/touchmockingapplication.cpp287
-rw-r--r--tests/manual/quick/touchbrowser/touchmockingapplication.h72
-rw-r--r--tests/manual/quick/touchbrowser/utils.h49
28 files changed, 1335 insertions, 780 deletions
diff --git a/tests/manual/quick/CMakeLists.txt b/tests/manual/quick/CMakeLists.txt
new file mode 100644
index 000000000..d6c4b88a9
--- /dev/null
+++ b/tests/manual/quick/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_subdirectory(touchbrowser)
+add_subdirectory(geopermission)
diff --git a/tests/manual/quick/geopermission/CMakeLists.txt b/tests/manual/quick/geopermission/CMakeLists.txt
new file mode 100644
index 000000000..088f248e1
--- /dev/null
+++ b/tests/manual/quick/geopermission/CMakeLists.txt
@@ -0,0 +1,63 @@
+# Copyright (C) 2023 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(tst_geopermission LANGUAGES CXX)
+ find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+endif()
+
+qt_internal_add_manual_test(tst_geopermission
+ SOURCES
+ main.cpp
+ LIBRARIES
+ Qt::Core
+ Qt::Gui
+ Qt::Qml
+ Qt::Quick
+ Qt::WebEngineQuick
+)
+
+if(WIN32)
+ set_property(
+ TARGET tst_geopermission
+ APPEND PROPERTY
+ SOURCES tst_geopermission.exe.manifest)
+endif()
+
+set_target_properties(tst_geopermission PROPERTIES
+ WIN32_EXECUTABLE TRUE
+ MACOSX_BUNDLE TRUE
+ MACOSX_BUNDLE_GUI_IDENTIFIER "io.qt.dev.webenginequick.tst_geopermission"
+)
+
+# Resources:
+set(resources_resource_files
+ "tst_geopermission.qml"
+ "geolocation.html"
+)
+
+qt_add_resources(tst_geopermission "resources"
+ PREFIX
+ "/"
+ FILES
+ ${resources_resource_files}
+)
+
+foreach(permission_plugin IN LISTS QT_ALL_PLUGINS_FOUND_BY_FIND_PACKAGE_permissions)
+ set(permission_plugin "${QT_CMAKE_EXPORT_NAMESPACE}::${permission_plugin}")
+ qt6_import_plugins(tst_geopermission INCLUDE ${permission_plugin})
+endforeach()
+
+if (APPLE)
+ set_target_properties(tst_geopermission PROPERTIES
+ MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist"
+ )
+
+ if (NOT CMAKE_GENERATOR STREQUAL "Xcode")
+ # Need to sign application for location permissions to work
+ add_custom_command(TARGET tst_geopermission
+ POST_BUILD COMMAND codesign -s - tst_geopermission.app)
+ endif()
+endif()
+
diff --git a/tests/manual/quick/geopermission/Info.plist b/tests/manual/quick/geopermission/Info.plist
new file mode 100644
index 000000000..9853e1900
--- /dev/null
+++ b/tests/manual/quick/geopermission/Info.plist
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleName</key>
+ <string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
+ <key>CFBundleIdentifier</key>
+ <string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
+ <key>CFBundleExecutable</key>
+ <string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
+ <key>CFBundleVersion</key>
+ <string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
+ <key>CFBundleShortVersionString</key>
+ <string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
+ <key>LSMinimumSystemVersion</key>
+ <string>${CMAKE_OSX_DEPLOYMENT_TARGET}</string>
+ <key>NSHumanReadableCopyright</key>
+ <string>${MACOSX_BUNDLE_COPYRIGHT}</string>
+ <key>CFBundleIconFile</key>
+ <string>${MACOSX_BUNDLE_ICON_FILE}</string>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>NSSupportsAutomaticGraphicsSwitching</key>
+ <true/>
+ <key>NSLocationUsageDescription</key>
+ <string>Geolocation test would like to give web sites access to your location for demo purposes.</string>
+</dict>
+</plist>
diff --git a/tests/manual/quick/geopermission/geolocation.html b/tests/manual/quick/geopermission/geolocation.html
new file mode 100644
index 000000000..e8c54bc58
--- /dev/null
+++ b/tests/manual/quick/geopermission/geolocation.html
@@ -0,0 +1,32 @@
+<html>
+<head>
+<title>Geolocation Permission API Test</title>
+<script>
+
+var errorMessage;
+var handled = false;
+
+function successHandler(location) {
+ var message = document.getElementById("message");
+ message.innerHTML = "Latitude: " + location.coords.latitude +
+ "<br>Longitude: " + location.coords.longitude;
+
+ errorMessage = "";
+ handled = true;
+}
+
+function errorHandler(error) {
+ errorMessage = error.message;
+ handled = true;
+}
+
+<!-- One shot example -->
+navigator.geolocation.getCurrentPosition(successHandler, errorHandler);
+
+</script>
+</head>
+<body>
+<div id="message">Location unknown</div>
+</body>
+</html>
+
diff --git a/tests/manual/quick/geopermission/main.cpp b/tests/manual/quick/geopermission/main.cpp
new file mode 100644
index 000000000..e0ff6f3e7
--- /dev/null
+++ b/tests/manual/quick/geopermission/main.cpp
@@ -0,0 +1,39 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include <QtWebEngineQuick/qtwebenginequickglobal.h>
+
+#include <QtQml/QQmlApplicationEngine>
+#include <QtQml/QQmlContext>
+#include <QQuickView>
+
+#include <QtGui/QGuiApplication>
+
+#include <QtCore/QCommandLineParser>
+#include <QtCore/QCommandLineOption>
+#include <QtCore/QLoggingCategory>
+
+int main(int argc, char **argv)
+{
+ QCoreApplication::setApplicationName("Geopermission test");
+ QCoreApplication::setOrganizationName("QtProject");
+
+ QtWebEngineQuick::initialize();
+
+ QGuiApplication app(argc, argv);
+
+ QQuickView view;
+
+ view.setTitle("Touch Browser");
+ view.setFlags(Qt::Window | Qt::WindowTitleHint);
+ view.setResizeMode(QQuickView::SizeRootObjectToView);
+ view.setSource(QUrl("qrc:/tst_geopermission.qml"));
+
+ QObject::connect(view.engine(), SIGNAL(quit()), &app, SLOT(quit()));
+
+ view.show();
+ if (view.size().isEmpty())
+ view.setGeometry(0, 0, 800, 600);
+
+ return app.exec();
+}
diff --git a/tests/manual/quick/geopermission/tst_geopermission.qml b/tests/manual/quick/geopermission/tst_geopermission.qml
new file mode 100644
index 000000000..36317c176
--- /dev/null
+++ b/tests/manual/quick/geopermission/tst_geopermission.qml
@@ -0,0 +1,28 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtTest
+import QtWebEngine
+
+WebEngineView {
+ id: webEngineView
+ width: 200
+ height: 200
+ url: Qt.resolvedUrl("qrc:/geolocation.html")
+ property bool deniedGeolocation: false
+ property bool geoPermissionRequested: false
+
+ onFeaturePermissionRequested: function(securityOrigin, feature) {
+ if (feature === WebEngineView.Geolocation) {
+ geoPermissionRequested = true
+ if (deniedGeolocation) {
+ webEngineView.grantFeaturePermission(securityOrigin, feature, false)
+ }
+ else {
+ webEngineView.grantFeaturePermission(securityOrigin, feature, true)
+ }
+ }
+ }
+
+}
diff --git a/tests/manual/quick/pdf/bookmarks-list.qml b/tests/manual/quick/pdf/bookmarks-list.qml
new file mode 100644
index 000000000..2be0d6848
--- /dev/null
+++ b/tests/manual/quick/pdf/bookmarks-list.qml
@@ -0,0 +1,136 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Dialogs
+import QtQuick.Pdf
+import QtQuick.Shapes
+
+ApplicationWindow {
+ id: root
+ width: 800
+ height: 940
+ title: doc.source
+ visible: true
+
+ property PdfDocument doc: PdfDocument { source: "test.pdf" }
+
+ Component.onCompleted: {
+ if (Application.arguments.length > 2)
+ doc.source = Application.arguments[Application.arguments.length - 1]
+ }
+ FileDialog {
+ id: fileDialog
+ title: "Open a PDF file"
+ nameFilters: [ "PDF files (*.pdf)" ]
+ onAccepted: doc.source = selectedFile
+ }
+
+ SplitView {
+ anchors.fill: parent
+
+ Pane {
+ SplitView.minimumWidth: 6
+ SplitView.preferredWidth: 200
+ clip: true
+ ListView {
+ ScrollIndicator.vertical: ScrollIndicator { }
+ anchors.fill: parent
+ delegate: ItemDelegate {
+ width: parent.width
+ text: model.title
+ background: Item { }
+ onClicked: image.currentFrame = page
+ }
+ model: PdfBookmarkModel {
+ document: root.doc
+ }
+ }
+ }
+
+ Flickable {
+ contentWidth: paper.width
+ contentHeight: paper.height
+ z: -1
+ Rectangle {
+ id: paper
+ width: image.width
+ height: image.height
+ PdfPageImage {
+ id: image
+ document: doc
+
+ property real zoomFactor: Math.sqrt(2)
+
+ Shortcut {
+ sequence: StandardKey.MoveToNextPage
+ enabled: image.currentFrame < image.frameCount - 1
+ onActivated: image.currentFrame++
+ }
+ Shortcut {
+ sequence: StandardKey.MoveToPreviousPage
+ enabled: image.currentFrame > 0
+ onActivated: image.currentFrame--
+ }
+ Shortcut {
+ sequence: StandardKey.ZoomIn
+ enabled: image.sourceSize.width < 5000
+ onActivated: {
+ image.sourceSize.width = image.implicitWidth * image.zoomFactor
+ image.sourceSize.height = image.implicitHeight * image.zoomFactor
+ }
+ }
+ Shortcut {
+ sequence: StandardKey.ZoomOut
+ enabled: image.width > 50
+ onActivated: {
+ image.sourceSize.width = image.implicitWidth / image.zoomFactor
+ image.sourceSize.height = image.implicitHeight / image.zoomFactor
+ }
+ }
+ Shortcut {
+ sequence: "Ctrl+0"
+ onActivated: image.sourceSize = undefined
+ }
+ Shortcut {
+ sequence: StandardKey.Open
+ onActivated: fileDialog.open()
+ }
+ Shortcut {
+ sequence: StandardKey.Quit
+ onActivated: Qt.quit()
+ }
+ }
+
+ Repeater {
+ model: PdfLinkModel {
+ id: linkModel
+ document: doc
+ page: image.currentFrame
+ }
+ delegate: Rectangle {
+ color: "transparent"
+ border.color: "lightgrey"
+ x: rect.x
+ y: rect.y
+ width: rect.width
+ height: rect.height
+ HoverHandler { cursorShape: Qt.PointingHandCursor }
+ TapHandler {
+ onTapped: {
+ if (page >= 0)
+ image.currentFrame = page
+ else
+ Qt.openUrlExternally(url)
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ Text {
+ anchors { bottom: parent.bottom; right: parent.right; margins: 6 }
+ text: "page " + doc.pageLabel(image.currentFrame) + " of " + doc.pageCount
+ }
+}
diff --git a/tests/manual/quick/pdf/bookmarks.qml b/tests/manual/quick/pdf/bookmarks.qml
new file mode 100644
index 000000000..e12629b31
--- /dev/null
+++ b/tests/manual/quick/pdf/bookmarks.qml
@@ -0,0 +1,147 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Dialogs
+import QtQuick.Pdf
+import QtQuick.Shapes
+
+ApplicationWindow {
+ id: root
+ width: 800
+ height: 940
+ color: "darkgrey"
+ title: doc.source
+ visible: true
+
+ property PdfDocument doc: PdfDocument { source: "test.pdf" }
+
+ Component.onCompleted: {
+ if (Application.arguments.length > 2)
+ doc.source = Application.arguments[Application.arguments.length - 1]
+ }
+ FileDialog {
+ id: fileDialog
+ title: "Open a PDF file"
+ nameFilters: [ "PDF files (*.pdf)" ]
+ onAccepted: doc.source = selectedFile
+ }
+
+ SplitView {
+ anchors.fill: parent
+
+ Pane {
+ SplitView.minimumWidth: 6
+ SplitView.preferredWidth: 200
+ TreeView {
+ id: bookmarksTree
+ anchors.fill: parent
+ columnWidthProvider: function() { return width }
+ onWidthChanged: forceLayout() // workaround to avoid column width getting stuck
+ clip: true
+ delegate: TreeViewDelegate {
+ width: parent.width
+ onClicked: image.currentFrame = page
+ }
+ model: PdfBookmarkModel {
+ document: root.doc
+ }
+ ScrollIndicator.vertical: ScrollIndicator {
+ // get the ScrollIndicator out into the margin area of the Pane...
+ // no need to overlap the tree when so much space is wasted anyway
+ parent: bookmarksTree.parent
+ anchors {
+ top: bookmarksTree.top
+ left: bookmarksTree.right
+ bottom: bookmarksTree.bottom
+ }
+ }
+ }
+ }
+
+ ScrollView {
+ contentWidth: paper.width
+ contentHeight: paper.height
+
+ Rectangle {
+ id: paper
+ width: image.width
+ height: image.height
+ PdfPageImage {
+ id: image
+ document: doc
+
+ property real zoomFactor: Math.sqrt(2)
+
+ Shortcut {
+ sequence: StandardKey.MoveToNextPage
+ enabled: image.currentFrame < image.frameCount - 1
+ onActivated: image.currentFrame++
+ }
+ Shortcut {
+ sequence: StandardKey.MoveToPreviousPage
+ enabled: image.currentFrame > 0
+ onActivated: image.currentFrame--
+ }
+ Shortcut {
+ sequence: StandardKey.ZoomIn
+ enabled: image.sourceSize.width < 5000
+ onActivated: {
+ image.sourceSize.width = image.implicitWidth * image.zoomFactor
+ image.sourceSize.height = image.implicitHeight * image.zoomFactor
+ }
+ }
+ Shortcut {
+ sequence: StandardKey.ZoomOut
+ enabled: image.width > 50
+ onActivated: {
+ image.sourceSize.width = image.implicitWidth / image.zoomFactor
+ image.sourceSize.height = image.implicitHeight / image.zoomFactor
+ }
+ }
+ Shortcut {
+ sequence: "Ctrl+0"
+ onActivated: image.sourceSize = undefined
+ }
+ Shortcut {
+ sequence: StandardKey.Open
+ onActivated: fileDialog.open()
+ }
+ Shortcut {
+ sequence: StandardKey.Quit
+ onActivated: Qt.quit()
+ }
+ }
+
+ Repeater {
+ model: PdfLinkModel {
+ id: linkModel
+ document: doc
+ page: image.currentFrame
+ }
+ delegate: Rectangle {
+ color: "transparent"
+ border.color: "lightgrey"
+ x: rect.x
+ y: rect.y
+ width: rect.width
+ height: rect.height
+ HoverHandler { cursorShape: Qt.PointingHandCursor }
+ TapHandler {
+ onTapped: {
+ if (page >= 0)
+ image.currentFrame = page
+ else
+ Qt.openUrlExternally(url)
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ Label {
+ anchors { bottom: parent.bottom; right: parent.right; margins: 6 }
+ text: "page " + doc.pageLabel(image.currentFrame) + " of " + doc.pageCount
+ }
+}
diff --git a/tests/manual/quick/pdf/gridview.qml b/tests/manual/quick/pdf/gridview.qml
new file mode 100644
index 000000000..773e72388
--- /dev/null
+++ b/tests/manual/quick/pdf/gridview.qml
@@ -0,0 +1,62 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+import QtQuick
+import QtQuick.Pdf
+
+Window {
+ width: 320
+ height: 440
+ color: "lightgrey"
+ title: doc.source
+ visible: true
+
+ property real cellSize: 150
+
+ PdfDocument {
+ id: doc
+ source: "test.pdf"
+ }
+
+ GridView {
+ id: view
+ anchors.fill: parent
+ anchors.margins: 10
+ model: doc.pageModel
+ cellWidth: cellSize
+ cellHeight: cellSize
+ delegate: Item {
+ required property int index
+ required property string label
+ required property size pointSize
+ width: view.cellWidth
+ height: view.cellHeight
+ Rectangle {
+ id: paper
+ width: image.width
+ height: image.height
+ x: (parent.width - width) / 2
+ y: (parent.height - height - pageNumber.height) / 2
+ PdfPageImage {
+ id: image
+ document: doc
+ currentFrame: index
+ asynchronous: true
+ fillMode: Image.PreserveAspectFit
+ property bool landscape: pointSize.width > pointSize.height
+ width: landscape ? Math.min(view.cellWidth, pointSize.width)
+ : height * pointSize.width / pointSize.height
+ height: landscape ? width * pointSize.height / pointSize.width
+ : Math.min(view.cellHeight - pageNumber.height, pointSize.height)
+ sourceSize.width: width
+ sourceSize.height: height
+ }
+ }
+ Text {
+ id: pageNumber
+ anchors.bottom: parent.bottom
+ anchors.horizontalCenter: parent.horizontalCenter
+ text: "Page " + label
+ }
+ }
+ }
+}
diff --git a/tests/manual/quick/pdf/listview.qml b/tests/manual/quick/pdf/listview.qml
index 361ae7d89..d01be9e86 100644
--- a/tests/manual/quick/pdf/listview.qml
+++ b/tests/manual/quick/pdf/listview.qml
@@ -1,55 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** 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.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-import QtQuick 2.14
-import QtQuick.Window 2.14
-import QtQuick.Pdf 5.15
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+import QtQuick
+import QtQuick.Pdf
Window {
width: 600
@@ -82,7 +34,7 @@ Window {
}
}
Text {
- text: "Page " + (image.currentFrame + 1)
+ text: "Page " + doc.pageLabel(image.currentFrame)
}
}
}
diff --git a/tests/manual/quick/pdf/multipleDocuments.qml b/tests/manual/quick/pdf/multipleDocuments.qml
new file mode 100644
index 000000000..055808ab6
--- /dev/null
+++ b/tests/manual/quick/pdf/multipleDocuments.qml
@@ -0,0 +1,182 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Dialogs
+import QtQuick.Layouts
+import QtQuick.Pdf
+import Qt.labs.animation
+
+ApplicationWindow {
+ id: root
+ width: 1280
+ height: 1024
+ color: "transparent"
+ flags: Qt.FramelessWindowHint
+ visibility: Window.FullScreen
+ property string source // for main.cpp
+ property real scaleStep: Math.sqrt(2)
+
+ Component {
+ id: pdfWindow
+
+ PdfPageView {
+ property alias source: document.source
+
+ Rectangle {
+ visible: parent.activeFocus
+ color: "transparent"
+ border.color: "cyan"
+ border.width: 3
+ anchors.fill: parent
+ anchors.margins: -border.width
+ anchors.topMargin: -toolbar.height - border.width
+ }
+
+ ToolBar {
+ id: toolbar
+ width: parent.width
+ y: -height
+ RowLayout {
+ anchors.fill: parent
+ anchors.rightMargin: 6
+ ToolButton {
+ action: Action {
+ shortcut: StandardKey.ZoomIn
+ enabled: pageView.sourceSize.width < 10000
+ icon.source: "../../../../examples/pdf/singlepage/resources/zoom-in.svg"
+ onTriggered: pageView.renderScale *= root.scaleStep
+ }
+ }
+ ToolButton {
+ action: Action {
+ shortcut: StandardKey.ZoomOut
+ enabled: pageView.sourceSize.width > 50
+ icon.source: "../../../../examples/pdf/singlepage/resources/zoom-out.svg"
+ onTriggered: pageView.renderScale /= root.scaleStep
+ }
+ }
+ ToolButton {
+ action: Action {
+ shortcut: "Ctrl+0"
+ icon.source: "../../../../examples/pdf/singlepage/resources/zoom-original.svg"
+ onTriggered: pageView.resetScale()
+ }
+ }
+ ToolButton {
+ action: Action {
+ icon.source: "../../../../examples/pdf/singlepage/resources/go-previous-view-page.svg"
+ enabled: pageView.backEnabled
+ onTriggered: pageView.back()
+ }
+ ToolTip.visible: enabled && hovered
+ ToolTip.delay: 2000
+ ToolTip.text: "go back"
+ }
+ SpinBox {
+ id: currentPageSB
+ from: 1
+ to: document.pageCount
+ editable: true
+ value: pageView.currentPage + 1
+ onValueModified: pageView.goToPage(value - 1)
+ Layout.maximumWidth: 60
+ }
+ ToolButton {
+ action: Action {
+ icon.source: "../../../../examples/pdf/singlepage/resources/go-next-view-page.svg"
+ enabled: pageView.forwardEnabled
+ onTriggered: pageView.forward()
+ }
+ ToolTip.visible: enabled && hovered
+ ToolTip.delay: 2000
+ ToolTip.text: "go forward"
+ }
+ Text {
+ text: document.title
+ elide: Text.ElideRight
+ Layout.fillWidth: true
+ }
+ DragHandler {
+ target: pageView
+ }
+ TapHandler {
+ onTapped: pageView.z++
+ }
+ ToolButton {
+ action: Action {
+ shortcut: StandardKey.Close
+ text: "☒"
+ onTriggered: pageView.destroy()
+ }
+ }
+ }
+ }
+
+ id: pageView
+ document: PdfDocument {
+ id: document
+ source: Qt.resolvedUrl(root.source)
+ onStatusChanged: (status) => { if (status === PdfDocument.Error) errorDialog.open() }
+ }
+
+ DragHandler {
+ acceptedButtons: Qt.MiddleButton
+ }
+ DragHandler {
+ acceptedDevices: PointerDevice.TouchScreen
+ }
+ HoverHandler {
+ onHoveredChanged: if (hovered) pageView.forceActiveFocus()
+ }
+
+ Dialog {
+ id: errorDialog
+ title: "Error loading " + document.source
+ standardButtons: Dialog.Ok
+ modal: true
+ closePolicy: Popup.CloseOnEscape
+ anchors.centerIn: parent
+ width: 300
+
+ Label {
+ id: errorField
+ text: document.error
+ }
+ }
+ }
+ }
+
+ Shortcut {
+ sequence: StandardKey.MoveToPreviousPage
+ onActivated: root.activeFocusItem.goToPage(root.activeFocusItem.currentPage - 1)
+ }
+ Shortcut {
+ sequence: StandardKey.MoveToNextPage
+ onActivated: root.activeFocusItem.goToPage(root.activeFocusItem.currentPage + 1)
+ }
+ Shortcut {
+ sequence: StandardKey.Open
+ onActivated: fileDialog.open()
+ }
+ Shortcut {
+ sequence: StandardKey.Quit
+ onActivated: Qt.quit()
+ }
+
+ function open(src) {
+ var win = pdfWindow.createObject(root, { source: src, y: 50 })
+ }
+
+ Component.onCompleted: {
+ if (Application.arguments.length > 2)
+ root.open(Application.arguments[Application.arguments.length - 1])
+ }
+
+ FileDialog {
+ id: fileDialog
+ title: "Open a PDF file"
+ nameFilters: [ "PDF files (*.pdf)" ]
+ onAccepted: root.open(selectedFile)
+ }
+}
diff --git a/tests/manual/quick/pdf/pdfPageView.qml b/tests/manual/quick/pdf/pdfPageView.qml
new file mode 100644
index 000000000..22c0d5ac2
--- /dev/null
+++ b/tests/manual/quick/pdf/pdfPageView.qml
@@ -0,0 +1,316 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Dialogs
+import QtQuick.Layouts
+import QtQuick.Pdf
+import Qt.labs.animation
+
+ApplicationWindow {
+ id: root
+ width: 800
+ height: 1024
+ color: "lightgrey"
+ title: document.title
+ visible: true
+ property string source // for main.cpp
+ property real scaleStep: Math.sqrt(2)
+
+ header: ToolBar {
+ RowLayout {
+ anchors.fill: parent
+ anchors.rightMargin: 6
+ ToolButton {
+ action: Action {
+ shortcut: StandardKey.Open
+ icon.source: "../../../../examples/pdf/singlepage/resources/document-open.svg"
+ onTriggered: fileDialog.open()
+ }
+ }
+ ToolButton {
+ action: Action {
+ shortcut: StandardKey.ZoomIn
+ enabled: pageView.sourceSize.width < 10000
+ icon.source: "../../../../examples/pdf/singlepage/resources/zoom-in.svg"
+ onTriggered: pageView.renderScale *= root.scaleStep
+ }
+ }
+ ToolButton {
+ action: Action {
+ shortcut: StandardKey.ZoomOut
+ enabled: pageView.sourceSize.width > 50
+ icon.source: "../../../../examples/pdf/singlepage/resources/zoom-out.svg"
+ onTriggered: pageView.renderScale /= root.scaleStep
+ }
+ }
+ ToolButton {
+ action: Action {
+ icon.source: "../../../../examples/pdf/singlepage/resources/zoom-fit-width.svg"
+ onTriggered: pageView.scaleToWidth(root.contentItem.width, root.contentItem.height)
+ }
+ }
+ ToolButton {
+ action: Action {
+ icon.source: "../../../../examples/pdf/singlepage/resources/zoom-fit-best.svg"
+ onTriggered: pageView.scaleToPage(root.contentItem.width, root.contentItem.height)
+ }
+ }
+ ToolButton {
+ action: Action {
+ shortcut: "Ctrl+0"
+ icon.source: "../../../../examples/pdf/singlepage/resources/zoom-original.svg"
+ onTriggered: pageView.resetScale()
+ }
+ }
+ ToolButton {
+ action: Action {
+ shortcut: "Ctrl+L"
+ icon.source: "../../../../examples/pdf/singlepage/resources/rotate-left.svg"
+ onTriggered: pageView.rotation -= 90
+ }
+ }
+ ToolButton {
+ action: Action {
+ shortcut: "Ctrl+R"
+ icon.source: "../../../../examples/pdf/singlepage/resources/rotate-right.svg"
+ onTriggered: pageView.rotation += 90
+ }
+ }
+ ToolButton {
+ action: Action {
+ icon.source: "../../../../examples/pdf/singlepage/resources/go-previous-view-page.svg"
+ enabled: pageView.backEnabled
+ onTriggered: pageView.back()
+ }
+ ToolTip.visible: enabled && hovered
+ ToolTip.delay: 2000
+ ToolTip.text: "go back"
+ }
+ SpinBox {
+ id: currentPageSB
+ from: 0
+ to: document.pageCount
+ editable: true
+ value: pageView.currentPage
+ onValueModified: pageView.goToPage(value)
+
+ textFromValue: function(value) { return document.pageLabel(value) }
+ valueFromText: function(text) {
+ for (var i = 0; i < document.pageCount; ++i) {
+ if (document.pageLabel(i).toLowerCase().indexOf(text.toLowerCase()) === 0)
+ return i
+ }
+ return spinBox.value
+ }
+
+ Shortcut {
+ sequence: StandardKey.MoveToPreviousPage
+ onActivated: pageView.goToPage(currentPageSB.value - 1)
+ }
+ Shortcut {
+ sequence: StandardKey.MoveToNextPage
+ onActivated: pageView.goToPage(currentPageSB.value + 1)
+ }
+ }
+ ToolButton {
+ action: Action {
+ icon.source: "../../../../examples/pdf//resources/go-next-view-page.svg"
+ enabled: pageView.forwardEnabled
+ onTriggered: pageView.forward()
+ }
+ ToolTip.visible: enabled && hovered
+ ToolTip.delay: 2000
+ ToolTip.text: "go forward"
+ }
+ ToolButton {
+ action: Action {
+ shortcut: StandardKey.Copy
+ icon.source: "../../../../examples/pdf/singlepage/resources/edit-copy.svg"
+ enabled: pageView.selectedText !== ""
+ onTriggered: pageView.copySelectionToClipboard()
+ }
+ }
+ Shortcut {
+ sequence: StandardKey.Quit
+ onActivated: Qt.quit()
+ }
+ }
+ }
+
+ FileDialog {
+ id: fileDialog
+ title: "Open a PDF file"
+ nameFilters: [ "PDF files (*.pdf)" ]
+ onAccepted: document.source = selectedFile
+ }
+
+ Component.onCompleted: {
+ if (Application.arguments.length > 2)
+ document.source = Application.arguments[Application.arguments.length - 1]
+ }
+
+ Dialog {
+ id: errorDialog
+ title: "Error loading " + document.source
+ standardButtons: Dialog.Ok
+ modal: true
+ closePolicy: Popup.CloseOnEscape
+ anchors.centerIn: parent
+ width: 300
+
+ Label {
+ id: errorField
+ text: document.error
+ }
+ }
+
+ PdfPageView {
+ id: pageView
+ x: searchDrawer.position * searchDrawer.width // TODO binding gets broken during centering
+ document: PdfDocument {
+ id: document
+ source: Qt.resolvedUrl(root.source)
+ onStatusChanged: (status) => { if (status === PdfDocument.Error) errorDialog.open() }
+ }
+ searchString: searchField.text
+ onRenderScaleChanged: pageView.returnToBounds()
+
+ DragHandler {
+ acceptedButtons: Qt.MiddleButton
+ onActiveChanged: if (!active) pageView.returnToBounds()
+ }
+ DragHandler {
+ acceptedDevices: PointerDevice.TouchScreen
+ onActiveChanged: if (!active) pageView.returnToBounds()
+ }
+
+ BoundaryRule on x {
+ id: brx
+ minimumOvershoot: 100
+ maximumOvershoot: 100
+ minimum: Math.min(0, root.width - pageView.width)
+ maximum: 0
+ }
+
+ BoundaryRule on y {
+ id: bry
+ minimumOvershoot: 100
+ maximumOvershoot: 100
+ minimum: Math.min(0, root.height - pageView.height)
+ maximum: 0
+ }
+
+ function returnToBounds() {
+ bry.returnToBounds()
+ brx.returnToBounds()
+ }
+ }
+
+ WheelHandler {
+ target: pageView
+ property: "x"
+ orientation: Qt.Horizontal
+ acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
+ acceptedModifiers: Qt.NoModifier
+ onActiveChanged: if (!active) brx.returnToBounds()
+ }
+ WheelHandler {
+ target: pageView
+ property: "y"
+ orientation: Qt.Vertical
+ acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
+ acceptedModifiers: Qt.NoModifier
+ onActiveChanged: if (!active) bry.returnToBounds()
+ }
+
+ Drawer {
+ id: searchDrawer
+ edge: Qt.LeftEdge
+ modal: false
+ width: searchLayout.implicitWidth
+ y: root.header.height
+ height: root.contentItem.height
+ dim: false
+ Shortcut {
+ sequence: StandardKey.Find
+ onActivated: {
+ searchDrawer.open()
+ searchField.forceActiveFocus()
+ }
+ }
+ ColumnLayout {
+ id: searchLayout
+ anchors.fill: parent
+ anchors.margins: 2
+ RowLayout {
+ ToolButton {
+ action: Action {
+ icon.source: "../../../../examples/pdf/singlepage/resources/go-up-search.svg"
+ shortcut: StandardKey.FindPrevious
+ onTriggered: pageView.searchBack()
+ }
+ ToolTip.visible: enabled && hovered
+ ToolTip.delay: 2000
+ ToolTip.text: "find previous"
+ }
+ TextField {
+ id: searchField
+ placeholderText: "search"
+ Layout.minimumWidth: 200
+ Layout.fillWidth: true
+ Image {
+ visible: searchField.text !== ""
+ source: "../../../../examples/pdf/singlepage/resources/edit-clear.svg"
+ anchors {
+ right: parent.right
+ top: parent.top
+ bottom: parent.bottom
+ margins: 3
+ rightMargin: 5
+ }
+ TapHandler {
+ onTapped: searchField.clear()
+ }
+ }
+ }
+ ToolButton {
+ action: Action {
+ icon.source: "../../../../examples/pdf/singlepage/resources/go-down-search.svg"
+ shortcut: StandardKey.FindNext
+ onTriggered: pageView.searchForward()
+ }
+ ToolTip.visible: enabled && hovered
+ ToolTip.delay: 2000
+ ToolTip.text: "find next"
+ }
+ }
+ ListView {
+ id: searchResultsList
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ clip: true
+ model: pageView.searchModel
+ ScrollBar.vertical: ScrollBar { }
+ delegate: ItemDelegate {
+ width: parent ? parent.width : 0
+ text: "page " + document.pageLabel(page) + ": " + contextBefore + pageView.searchString + contextAfter
+ highlighted: ListView.isCurrentItem
+ onClicked: {
+ searchResultsList.currentIndex = index
+ pageView.goToLocation(page, location, 0)
+ pageView.searchModel.currentResult = indexOnPage
+ }
+ }
+ }
+ }
+ }
+
+ footer: Label {
+ property size implicitPointSize: document.pagePointSize(pageView.currentPage)
+ text: "page " + (pageView.currentPage + 1) + " of " + document.pageCount +
+ " scale " + pageView.renderScale.toFixed(2) +
+ " original " + implicitPointSize.width.toFixed(1) + "x" + implicitPointSize.height.toFixed(1) + "pts"
+ visible: document.status === PdfDocument.Ready
+ }
+}
diff --git a/tests/manual/quick/pdf/pessimizedListView.qml b/tests/manual/quick/pdf/pessimizedListView.qml
index 4ae0edabe..1b514668e 100644
--- a/tests/manual/quick/pdf/pessimizedListView.qml
+++ b/tests/manual/quick/pdf/pessimizedListView.qml
@@ -1,57 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** 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.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-import QtQuick 2.14
-import QtQuick.Controls 2.14
-import QtQuick.Layouts 1.14
-import QtQuick.Pdf 5.15
-import Qt.labs.platform 1.1 as P
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Dialogs
+import QtQuick.Layouts
+import QtQuick.Pdf
ApplicationWindow {
width: 900
@@ -127,11 +80,11 @@ ApplicationWindow {
source: "test.pdf"
}
- P.FileDialog {
+ FileDialog {
id: fileDialog
title: "Open a PDF file"
nameFilters: [ "PDF files (*.pdf)" ]
- onAccepted: doc.source = file
+ onAccepted: doc.source = selectedFile
}
ListView {
@@ -150,15 +103,15 @@ ApplicationWindow {
anchors.centerIn: parent
running: image.status === Image.Loading
}
- Image {
+ PdfPageImage {
id: image
+ document: doc
scale: imageScale
anchors.centerIn: parent
sourceSize.width: doc.pagePointSize(index).width * oversamplingSB.value
height: 100
fillMode: Image.PreserveAspectFit
objectName: "PDF page " + index
- source: doc.source
currentFrame: index
asynchronous: asyncCB.checked
cache: cacheCB.checked
diff --git a/tests/manual/quick/pdf/simplest.qml b/tests/manual/quick/pdf/simplest.qml
index 0571493af..3f39bb213 100644
--- a/tests/manual/quick/pdf/simplest.qml
+++ b/tests/manual/quick/pdf/simplest.qml
@@ -1,53 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** 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.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-import QtQuick 2.14
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+import QtQuick
Image {
id: image
diff --git a/tests/manual/quick/pdf/test.pdf b/tests/manual/quick/pdf/test.pdf
index a9dc1bc29..0832dfbed 100644
--- a/tests/manual/quick/pdf/test.pdf
+++ b/tests/manual/quick/pdf/test.pdf
Binary files differ
diff --git a/tests/manual/quick/pdf/underscoredLinks.qml b/tests/manual/quick/pdf/underscoredLinks.qml
new file mode 100644
index 000000000..514008ca2
--- /dev/null
+++ b/tests/manual/quick/pdf/underscoredLinks.qml
@@ -0,0 +1,146 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Dialogs
+import QtQuick.Pdf
+import QtQuick.Shapes
+
+ApplicationWindow {
+ id: root
+ width: 800
+ height: 940
+ color: "darkgrey"
+ title: doc.source
+ visible: true
+
+ property PdfDocument doc: PdfDocument { source: "test.pdf" }
+
+ Component.onCompleted: {
+ if (Application.arguments.length > 2)
+ doc.source = Application.arguments[Application.arguments.length - 1]
+ }
+ FileDialog {
+ id: fileDialog
+ title: "Open a PDF file"
+ nameFilters: [ "PDF files (*.pdf)" ]
+ onAccepted: doc.source = selectedFile
+ }
+ ScrollView {
+ anchors.fill: parent
+ contentWidth: paper.width
+ contentHeight: paper.height
+
+ Rectangle {
+ id: paper
+ width: image.width
+ height: image.height
+ PdfPageImage {
+ id: image
+ document: doc
+
+ property real zoomFactor: Math.sqrt(2)
+
+ Shortcut {
+ sequence: StandardKey.MoveToNextPage
+ enabled: image.currentFrame < image.frameCount - 1
+ onActivated: image.currentFrame++
+ }
+ Shortcut {
+ sequence: StandardKey.MoveToPreviousPage
+ enabled: image.currentFrame > 0
+ onActivated: image.currentFrame--
+ }
+ Shortcut {
+ sequence: StandardKey.ZoomIn
+ enabled: image.sourceSize.width < 5000
+ onActivated: {
+ image.sourceSize.width = image.implicitWidth * image.zoomFactor
+ image.sourceSize.height = image.implicitHeight * image.zoomFactor
+ }
+ }
+ Shortcut {
+ sequence: StandardKey.ZoomOut
+ enabled: image.width > 50
+ onActivated: {
+ image.sourceSize.width = image.implicitWidth / image.zoomFactor
+ image.sourceSize.height = image.implicitHeight / image.zoomFactor
+ }
+ }
+ Shortcut {
+ sequence: "Ctrl+0"
+ onActivated: image.sourceSize = undefined
+ }
+ Shortcut {
+ sequence: StandardKey.Open
+ onActivated: fileDialog.open()
+ }
+ Shortcut {
+ sequence: StandardKey.Quit
+ onActivated: Qt.quit()
+ }
+ }
+
+ Menu {
+ id: linkContextMenu
+ property var currentLink
+ MenuItem {
+ text: "Go"
+ onTriggered: {
+ if (linkContextMenu.currentLink.page >= 0)
+ image.currentFrame = linkContextMenu.currentLink.page
+ else
+ Qt.openUrlExternally(linkContextMenu.currentLink.url)
+ }
+ }
+ MenuItem {
+ text: "Copy"
+ onTriggered: linkContextMenu.currentLink.copyToClipboard()
+ }
+ }
+
+ Repeater {
+ model: PdfLinkModel {
+ id: linkModel
+ document: doc
+ page: image.currentFrame
+ }
+ delegate: PdfLinkDelegate {
+ x: rectangle.x
+ y: rectangle.y
+ width: rectangle.width
+ height: rectangle.height
+ onTapped:
+ (link) => {
+ if (link.page >= 0)
+ image.currentFrame = link.page
+ else
+ Qt.openUrlExternally(url)
+ }
+ onContextMenuRequested:
+ (link) => {
+ linkContextMenu.currentLink = link
+ linkContextMenu.x = x
+ linkContextMenu.y = y
+ linkContextMenu.open()
+ }
+ Shape {
+ anchors.fill: parent
+ ShapePath {
+ strokeWidth: 1
+ strokeColor: palette.link
+ strokeStyle: ShapePath.DashLine
+ dashPattern: [ 1, 4 ]
+ startX: 0; startY: height
+ PathLine { x: width; y: height }
+ }
+ }
+ }
+ }
+ }
+ }
+ Label {
+ anchors { bottom: parent.bottom; right: parent.right; margins: 6 }
+ text: "page " + (image.currentFrame + 1) + " of " + doc.pageCount
+ }
+}
diff --git a/tests/manual/quick/pdf/withdoc.qml b/tests/manual/quick/pdf/withdoc.qml
index 2d82a6abf..d4bf12e29 100644
--- a/tests/manual/quick/pdf/withdoc.qml
+++ b/tests/manual/quick/pdf/withdoc.qml
@@ -1,58 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** 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.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-import QtQuick 2.14
-import QtQuick.Controls 2.14
-import Qt.labs.platform 1.1 as Platform
-import QtQuick.Pdf 5.15
-import QtQuick.Shapes 1.14
-import QtQuick.Window 2.14
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Dialogs
+import QtQuick.Pdf
+import QtQuick.Shapes
Window {
width: 800
@@ -64,21 +16,42 @@ Window {
PdfDocument {
id: doc
source: "test.pdf"
+ onPasswordRequired: function() { passwordDialog.open() }
}
- Platform.FileDialog {
+ FileDialog {
id: fileDialog
title: "Open a PDF file"
nameFilters: [ "PDF files (*.pdf)" ]
- onAccepted: doc.source = file
+ onAccepted: doc.source = selectedFile
+ }
+
+ Dialog {
+ id: passwordDialog
+ title: "Password"
+ standardButtons: Dialog.Ok | Dialog.Cancel
+ modal: true
+ closePolicy: Popup.CloseOnEscape
+ anchors.centerIn: parent
+ width: 300
+
+ contentItem: TextField {
+ id: passwordField
+ placeholderText: qsTr("Please provide the password")
+ echoMode: TextInput.Password
+ width: parent.width
+ onAccepted: passwordDialog.accept()
+ }
+ onOpened: function() { passwordField.forceActiveFocus() }
+ onAccepted: doc.password = passwordField.text
}
PdfSelection {
id: selection
document: doc
page: image.currentFrame
- fromPoint: dragHandler.centroid.pressPosition
- toPoint: dragHandler.centroid.position
+ from: dragHandler.centroid.pressPosition
+ to: dragHandler.centroid.position
hold: !dragHandler.active
}
@@ -109,9 +82,9 @@ Window {
id: paper
width: image.width
height: image.height
- Image {
+ PdfPageImage {
id: image
- source: doc.status === PdfDocument.Ready ? doc.source : ""
+ document: doc
property real zoomFactor: Math.sqrt(2)
@@ -185,7 +158,7 @@ Window {
y: rect.y
width: rect.width
height: rect.height
-// HoverHandler { cursorShape: Qt.PointingHandCursor } // 5.15 onward (QTBUG-68073)
+ HoverHandler { cursorShape: Qt.PointingHandCursor }
TapHandler {
onTapped: {
if (page >= 0)
@@ -201,6 +174,6 @@ Window {
}
Text {
anchors.bottom: parent.bottom
- text: "page " + (image.currentFrame + 1) + " of " + doc.pageCount
+ text: "page " + (image.currentFrame + 1) + " of " + doc.pageCount + " label: " + doc.pageLabel(image.currentFrame)
}
}
diff --git a/tests/manual/quick/quick.pro b/tests/manual/quick/quick.pro
deleted file mode 100644
index 8522763f8..000000000
--- a/tests/manual/quick/quick.pro
+++ /dev/null
@@ -1,5 +0,0 @@
-TEMPLATE = subdirs
-
-SUBDIRS += \
- faviconbrowser \
- touchbrowser
diff --git a/tests/manual/quick/touchbrowser/AddressBar.qml b/tests/manual/quick/touchbrowser/AddressBar.qml
index 1daae6dbf..42188c94e 100644
--- a/tests/manual/quick/touchbrowser/AddressBar.qml
+++ b/tests/manual/quick/touchbrowser/AddressBar.qml
@@ -1,34 +1,8 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWebEngine module 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$
-**
-****************************************************************************/
-
-import QtQuick 2.5
-import QtQuick.Controls 1.4
-import QtQuick.Controls.Styles 1.4
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls
Rectangle {
id: root
@@ -59,6 +33,14 @@ Rectangle {
TextField {
id: addressField
anchors.fill: parent
+ leftPadding: 30
+
+ background: Rectangle {
+ color: "transparent"
+ border.color: "black"
+ border.width: 1
+ radius: root.radius
+ }
Image {
anchors.verticalCenter: addressField.verticalCenter
@@ -78,17 +60,6 @@ Rectangle {
visible: root.progress < 100
}
- style: TextFieldStyle {
- padding.left: 30
-
- background: Rectangle {
- color: "transparent"
- border.color: "black"
- border.width: 1
- radius: root.radius
- }
- }
-
onActiveFocusChanged: {
if (activeFocus)
selectAll();
diff --git a/tests/manual/quick/touchbrowser/CMakeLists.txt b/tests/manual/quick/touchbrowser/CMakeLists.txt
new file mode 100644
index 000000000..0d3275e58
--- /dev/null
+++ b/tests/manual/quick/touchbrowser/CMakeLists.txt
@@ -0,0 +1,31 @@
+# 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.19)
+ project(touchbrowser LANGUAGES CXX)
+ find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+endif()
+
+set(CMAKE_AUTORCC ON)
+set(TOUCHMOCKING_DIR "../../touchmocking")
+
+include_directories(${TOUCHMOCKING_DIR})
+add_definitions(-DQUICK_TOUCHBROWSER)
+
+qt_internal_add_manual_test(touchbrowser-quick
+ GUI
+ SOURCES
+ main.cpp
+ resources.qrc
+ ${TOUCHMOCKING_DIR}/touchmockingapplication.cpp
+ ${TOUCHMOCKING_DIR}/touchmockingapplication.h
+ ${TOUCHMOCKING_DIR}/utils.h
+ LIBRARIES
+ Qt::Core
+ Qt::Quick
+ Qt::WebEngineQuick
+ ENABLE_AUTOGEN_TOOLS
+ moc
+)
+
diff --git a/tests/manual/quick/touchbrowser/MockTouchPoint.qml b/tests/manual/quick/touchbrowser/MockTouchPoint.qml
new file mode 100644
index 000000000..895e12e70
--- /dev/null
+++ b/tests/manual/quick/touchbrowser/MockTouchPoint.qml
@@ -0,0 +1,26 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+import QtQuick
+
+Item {
+ id: mockTouchPoint
+
+ property bool pressed: false
+ property int pointId: 0
+
+ Image {
+ source: "qrc:/touchpoint.png"
+ x: -(width / 2)
+ y: -(height / 2)
+ opacity: mockTouchPoint.pressed ? 0.6 : 0.0
+
+ Behavior on opacity {
+ NumberAnimation { duration: 200 }
+ }
+
+ Text {
+ text: mockTouchPoint.pointId
+ anchors.centerIn: parent
+ }
+ }
+}
diff --git a/tests/manual/quick/touchbrowser/main.cpp b/tests/manual/quick/touchbrowser/main.cpp
index ffbe81179..1f4d7d869 100644
--- a/tests/manual/quick/touchbrowser/main.cpp
+++ b/tests/manual/quick/touchbrowser/main.cpp
@@ -1,48 +1,21 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWebEngine module 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$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-#if defined(DESKTOP_BUILD)
#include "touchmockingapplication.h"
-#endif
#include "utils.h"
-#include <QtGui/QGuiApplication>
-#include <QtQml/QQmlApplicationEngine>
-#include <QtQml/QQmlContext>
-#include <QtQuick/QQuickView>
-#include <QtWebEngineQuick/qtwebenginequickglobal.h>
+#include <QGuiApplication>
+#include <QQmlApplicationEngine>
+#include <QQmlContext>
+#include <QQuickView>
+#include <QtWebEngineQuick>
static QUrl startupUrl()
{
QUrl ret;
QStringList args(qApp->arguments());
args.takeFirst();
- for (const QString &arg : qAsConst(args)) {
+ for (const QString &arg : std::as_const(args)) {
if (arg.startsWith(QLatin1Char('-')))
continue;
ret = Utils::fromUserInput(arg);
@@ -54,31 +27,10 @@ static QUrl startupUrl()
int main(int argc, char **argv)
{
- QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
- QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
-
- // We use touch mocking on desktop and apply all the mobile switches.
- QByteArrayList args = QByteArrayList()
- << QByteArrayLiteral("--enable-embedded-switches")
- << QByteArrayLiteral("--log-level=0");
- const int count = args.size() + argc;
- QList<char*> qargv(count);
-
- qargv[0] = argv[0];
- for (int i = 0; i < args.size(); ++i)
- qargv[i + 1] = args[i].data();
- for (int i = args.size() + 1; i < count; ++i)
- qargv[i] = argv[i - args.size()];
-
- int qAppArgCount = qargv.size();
-
QtWebEngineQuick::initialize();
-#if defined(DESKTOP_BUILD)
- TouchMockingApplication app(qAppArgCount, qargv.data());
-#else
- QGuiApplication app(qAppArgCount, qargv.data());
-#endif
+ TouchMockingApplication app(argc, argv);
+ app.setAttribute(Qt::AA_SynthesizeTouchForUnhandledMouseEvents, true);
QQuickView view;
Utils utils;
diff --git a/tests/manual/quick/touchbrowser/main.qml b/tests/manual/quick/touchbrowser/main.qml
index 926b3a941..83ede7d75 100644
--- a/tests/manual/quick/touchbrowser/main.qml
+++ b/tests/manual/quick/touchbrowser/main.qml
@@ -1,34 +1,9 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWebEngine module 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$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-import QtQuick 2.5
-import QtQuick.Layouts 1.3
-import QtWebEngine 1.3
+import QtQuick
+import QtQuick.Layouts
+import QtWebEngine
Item {
function load(url) {
diff --git a/tests/manual/quick/touchbrowser/qml.qrc b/tests/manual/quick/touchbrowser/resources.qrc
index 45210fe36..87d655a27 100644
--- a/tests/manual/quick/touchbrowser/qml.qrc
+++ b/tests/manual/quick/touchbrowser/resources.qrc
@@ -2,5 +2,6 @@
<qresource prefix="/">
<file>main.qml</file>
<file>AddressBar.qml</file>
+ <file alias="touchpoint.png">../../touchmocking/touchpoint.png</file>
</qresource>
</RCC>
diff --git a/tests/manual/quick/touchbrowser/touchbrowser.pro b/tests/manual/quick/touchbrowser/touchbrowser.pro
index 92e4e6703..710584df8 100644
--- a/tests/manual/quick/touchbrowser/touchbrowser.pro
+++ b/tests/manual/quick/touchbrowser/touchbrowser.pro
@@ -1,19 +1,15 @@
TEMPLATE = app
-QT += quick webenginequick
-CONFIG += c++11
+DEFINES += QUICK_TOUCHBROWSER
+QT += core gui quick webenginequick
-SOURCES += \
- main.cpp
+INCLUDEPATH += ../../touchmocking
+SOURCES += \
+ main.cpp \
+ ../../touchmocking/touchmockingapplication.cpp
HEADERS += \
- utils.h
-
-RESOURCES += qml.qrc
+ ../../touchmocking/touchmockingapplication.h \
+ ../../touchmocking/utils.h
-!cross_compile {
- DEFINES += DESKTOP_BUILD
- SOURCES += touchmockingapplication.cpp
- HEADERS += touchmockingapplication.h
- QT += gui-private
-}
+RESOURCES += resources.qrc
diff --git a/tests/manual/quick/touchbrowser/touchmockingapplication.cpp b/tests/manual/quick/touchbrowser/touchmockingapplication.cpp
deleted file mode 100644
index 41b731a6a..000000000
--- a/tests/manual/quick/touchbrowser/touchmockingapplication.cpp
+++ /dev/null
@@ -1,287 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWebEngine module 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 "touchmockingapplication.h"
-
-#include <qpa/qwindowsysteminterface.h>
-#include <QtCore/QEvent>
-#include <QtGui/QMouseEvent>
-#include <QtGui/QTouchDevice>
-#include <QtGui/QTouchEvent>
-#include <QtQuick/QQuickItem>
-#include <QtQuick/QQuickView>
-
-static inline bool isTouchEvent(const QEvent* event)
-{
- switch (event->type()) {
- case QEvent::TouchBegin:
- case QEvent::TouchUpdate:
- case QEvent::TouchEnd:
- return true;
- default:
- return false;
- }
-}
-
-static inline bool isMouseEvent(const QEvent* event)
-{
- switch (event->type()) {
- case QEvent::MouseButtonPress:
- case QEvent::MouseMove:
- case QEvent::MouseButtonRelease:
- case QEvent::MouseButtonDblClick:
- return true;
- default:
- return false;
- }
-}
-
-TouchMockingApplication::TouchMockingApplication(int& argc, char** argv)
- : QGuiApplication(argc, argv)
- , m_realTouchEventReceived(false)
- , m_pendingFakeTouchEventCount(0)
- , m_holdingControl(false)
-{
-}
-
-bool TouchMockingApplication::notify(QObject* target, QEvent* event)
-{
- // We try to be smart, if we received real touch event, we are probably on a device
- // with touch screen, and we should not have touch mocking.
-
- if (!event->spontaneous() || m_realTouchEventReceived)
- return QGuiApplication::notify(target, event);
-
- if (isTouchEvent(event)) {
- if (m_pendingFakeTouchEventCount)
- --m_pendingFakeTouchEventCount;
- else
- m_realTouchEventReceived = true;
- return QGuiApplication::notify(target, event);
- }
-
- QQuickView* window = qobject_cast<QQuickView*>(target);
- if (!window)
- return QGuiApplication::notify(target, event);
-
- m_holdingControl = QGuiApplication::keyboardModifiers().testFlag(Qt::ControlModifier);
-
- if (event->type() == QEvent::KeyRelease && static_cast<QKeyEvent*>(event)->key() == Qt::Key_Control) {
- foreach (int id, m_heldTouchPoints)
- if (m_touchPoints.contains(id) && !QGuiApplication::mouseButtons().testFlag(Qt::MouseButton(id))) {
- m_touchPoints[id].setState(Qt::TouchPointReleased);
- m_heldTouchPoints.remove(id);
- } else
- m_touchPoints[id].setState(Qt::TouchPointStationary);
-
- sendTouchEvent(window, m_heldTouchPoints.isEmpty() ? QEvent::TouchEnd : QEvent::TouchUpdate, static_cast<QKeyEvent*>(event)->timestamp());
- }
-
- if (isMouseEvent(event)) {
- const QMouseEvent* const mouseEvent = static_cast<QMouseEvent*>(event);
-
- QTouchEvent::TouchPoint touchPoint;
- touchPoint.setPressure(1);
-
- QEvent::Type touchType = QEvent::None;
-
- switch (mouseEvent->type()) {
- case QEvent::MouseButtonPress:
- touchPoint.setId(mouseEvent->button());
- if (m_touchPoints.contains(touchPoint.id())) {
- touchPoint.setState(Qt::TouchPointMoved);
- touchType = QEvent::TouchUpdate;
- } else {
- touchPoint.setState(Qt::TouchPointPressed);
- // Check if more buttons are held down than just the event triggering one.
- if (mouseEvent->buttons() > mouseEvent->button())
- touchType = QEvent::TouchUpdate;
- else
- touchType = QEvent::TouchBegin;
- }
- break;
- case QEvent::MouseMove:
- if (!mouseEvent->buttons()) {
- // We have to swallow the event instead of propagating it,
- // since we avoid sending the mouse release events and if the
- // Flickable is the mouse grabber it would receive the event
- // and would move the content.
- event->accept();
- return true;
- }
- touchType = QEvent::TouchUpdate;
- touchPoint.setId(mouseEvent->buttons());
- touchPoint.setState(Qt::TouchPointMoved);
- break;
- case QEvent::MouseButtonRelease:
- // Check if any buttons are still held down after this event.
- if (mouseEvent->buttons())
- touchType = QEvent::TouchUpdate;
- else
- touchType = QEvent::TouchEnd;
- touchPoint.setId(mouseEvent->button());
- touchPoint.setState(Qt::TouchPointReleased);
- break;
- case QEvent::MouseButtonDblClick:
- // Eat double-clicks, their accompanying press event is all we need.
- event->accept();
- return true;
- default:
- Q_ASSERT_X(false, "multi-touch mocking", "unhandled event type");
- }
-
- // A move can have resulted in multiple buttons, so we need check them individually.
- if (touchPoint.id() & Qt::LeftButton)
- updateTouchPoint(mouseEvent, touchPoint, Qt::LeftButton);
- if (touchPoint.id() & Qt::MiddleButton)
- updateTouchPoint(mouseEvent, touchPoint, Qt::MiddleButton);
- if (touchPoint.id() & Qt::RightButton)
- updateTouchPoint(mouseEvent, touchPoint, Qt::RightButton);
-
- if (m_holdingControl && touchPoint.state() == Qt::TouchPointReleased) {
- // We avoid sending the release event because the Flickable is
- // listening to mouse events and would start a bounce-back
- // animation if it received a mouse release.
- event->accept();
- return true;
- }
-
- // Update states for all other touch-points
- for (QHash<int, QTouchEvent::TouchPoint>::iterator it = m_touchPoints.begin(), end = m_touchPoints.end(); it != end; ++it) {
- if (!(it.value().id() & touchPoint.id()))
- it.value().setState(Qt::TouchPointStationary);
- }
-
- Q_ASSERT(touchType != QEvent::None);
-
- if (!sendTouchEvent(window, touchType, mouseEvent->timestamp()))
- return QGuiApplication::notify(target, event);
-
- event->accept();
- return true;
- }
-
- return QGuiApplication::notify(target, event);
-}
-
-void TouchMockingApplication::updateTouchPoint(const QMouseEvent* mouseEvent, QTouchEvent::TouchPoint touchPoint, Qt::MouseButton mouseButton)
-{
- // Ignore inserting additional touch points if Ctrl isn't held because it produces
- // inconsistent touch events and results in assers in the gesture recognizers.
- if (!m_holdingControl && m_touchPoints.size() && !m_touchPoints.contains(mouseButton))
- return;
-
- if (m_holdingControl && touchPoint.state() == Qt::TouchPointReleased) {
- m_heldTouchPoints.insert(mouseButton);
- return;
- }
-
- // Gesture recognition uses the screen position for the initial threshold
- // but since the canvas translates touch events we actually need to pass
- // the screen position as the scene position to deliver the appropriate
- // coordinates to the target.
- touchPoint.setPos(mouseEvent->localPos());
- touchPoint.setScenePos(mouseEvent->screenPos());
-
- if (touchPoint.state() == Qt::TouchPointPressed)
- touchPoint.setStartScenePos(mouseEvent->screenPos());
- else {
- const QTouchEvent::TouchPoint& oldTouchPoint = m_touchPoints[mouseButton];
- touchPoint.setStartScenePos(oldTouchPoint.startScenePos());
- touchPoint.setLastPos(oldTouchPoint.pos());
- touchPoint.setLastScenePos(oldTouchPoint.scenePos());
- }
-
- // Update current touch-point.
- touchPoint.setId(mouseButton);
- m_touchPoints.insert(mouseButton, touchPoint);
-}
-
-bool TouchMockingApplication::sendTouchEvent(QQuickView* window, QEvent::Type type, ulong timestamp)
-{
- static QTouchDevice* device = 0;
- if (!device) {
- device = new QTouchDevice;
- device->setType(QTouchDevice::TouchScreen);
- QWindowSystemInterface::registerTouchDevice(device);
- }
-
- m_pendingFakeTouchEventCount++;
-
- const QList<QTouchEvent::TouchPoint>& currentTouchPoints = m_touchPoints.values();
- Qt::TouchPointStates touchPointStates = Qt::TouchPointState();
- foreach (const QTouchEvent::TouchPoint& touchPoint, currentTouchPoints)
- touchPointStates |= touchPoint.state();
-
- QTouchEvent event(type, device, Qt::NoModifier, touchPointStates, currentTouchPoints);
- event.setTimestamp(timestamp);
- event.setAccepted(false);
-
- QGuiApplication::notify(window, &event);
-
- updateVisualMockTouchPoints(window,m_holdingControl ? currentTouchPoints : QList<QTouchEvent::TouchPoint>());
-
- // Get rid of touch-points that are no longer valid
- foreach (const QTouchEvent::TouchPoint& touchPoint, currentTouchPoints) {
- if (touchPoint.state() == Qt::TouchPointReleased)
- m_touchPoints.remove(touchPoint.id());
- }
-
- return event.isAccepted();
-}
-
-void TouchMockingApplication::updateVisualMockTouchPoints(QQuickView* window,const QList<QTouchEvent::TouchPoint>& touchPoints)
-{
- if (touchPoints.isEmpty()) {
- // Hide all touch indicator items.
- foreach (QQuickItem* item, m_activeMockComponents.values())
- item->setProperty("pressed", false);
-
- return;
- }
-
- foreach (const QTouchEvent::TouchPoint& touchPoint, touchPoints) {
- QQuickItem* mockTouchPointItem = m_activeMockComponents.value(touchPoint.id());
-
- if (!mockTouchPointItem) {
- QQmlComponent touchMockPointComponent(window->engine(), QUrl("qrc:///qml/MockTouchPoint.qml"));
- mockTouchPointItem = qobject_cast<QQuickItem*>(touchMockPointComponent.create());
- Q_ASSERT(mockTouchPointItem);
- m_activeMockComponents.insert(touchPoint.id(), mockTouchPointItem);
- mockTouchPointItem->setProperty("pointId", QVariant(touchPoint.id()));
- mockTouchPointItem->setParent(window->rootObject());
- mockTouchPointItem->setParentItem(window->rootObject());
- }
-
- mockTouchPointItem->setX(touchPoint.pos().x());
- mockTouchPointItem->setY(touchPoint.pos().y());
- mockTouchPointItem->setWidth(touchPoint.ellipseDiameters().width());
- mockTouchPointItem->setHeight(touchPoint.ellipseDiameters().height());
- mockTouchPointItem->setProperty("pressed", QVariant(touchPoint.state() != Qt::TouchPointReleased));
- }
-}
diff --git a/tests/manual/quick/touchbrowser/touchmockingapplication.h b/tests/manual/quick/touchbrowser/touchmockingapplication.h
deleted file mode 100644
index cdabe871f..000000000
--- a/tests/manual/quick/touchbrowser/touchmockingapplication.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWebEngine module 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$
-**
-****************************************************************************/
-
-#ifndef TOUCHMOCKINGAPPLICATION_H
-#define TOUCHMOCKINGAPPLICATION_H
-
-#include <QtCore/QHash>
-#include <QtCore/QSet>
-#include <QtCore/QUrl>
-#include <QtGui/QGuiApplication>
-#include <QtGui/QTouchEvent>
-
-QT_BEGIN_NAMESPACE
-class QQuickView;
-class QQuickItem;
-QT_END_NAMESPACE
-
-class TouchMockingApplication : public QGuiApplication
-{
- Q_OBJECT
-
-public:
- TouchMockingApplication(int &argc, char **argv);
-
- virtual bool notify(QObject *, QEvent *) override;
-
-private:
- void updateTouchPoint(const QMouseEvent *, QTouchEvent::TouchPoint, Qt::MouseButton);
- bool sendTouchEvent(QQuickView *, QEvent::Type, ulong timestamp);
- void updateVisualMockTouchPoints(QQuickView *,const QList<QTouchEvent::TouchPoint> &touchPoints);
-
-private:
- bool m_realTouchEventReceived;
- int m_pendingFakeTouchEventCount;
-
- QPointF m_lastPos;
- QPointF m_lastScreenPos;
- QPointF m_startScreenPos;
-
- QHash<int, QTouchEvent::TouchPoint> m_touchPoints;
- QSet<int> m_heldTouchPoints;
- QHash<int, QQuickItem*> m_activeMockComponents;
-
- bool m_holdingControl;
-};
-
-#endif // TOUCHMOCKINGAPPLICATION_H
diff --git a/tests/manual/quick/touchbrowser/utils.h b/tests/manual/quick/touchbrowser/utils.h
deleted file mode 100644
index b7aeefce0..000000000
--- a/tests/manual/quick/touchbrowser/utils.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWebEngine module 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$
-**
-****************************************************************************/
-
-#ifndef UTILS_H
-#define UTILS_H
-
-#include <QtCore/QFileInfo>
-#include <QtCore/QUrl>
-
-class Utils : public QObject {
- Q_OBJECT
-public:
- Q_INVOKABLE static QUrl fromUserInput(const QString& userInput);
-};
-
-inline QUrl Utils::fromUserInput(const QString& userInput)
-{
- QFileInfo fileInfo(userInput);
- if (fileInfo.exists())
- return QUrl::fromLocalFile(fileInfo.absoluteFilePath());
- return QUrl::fromUserInput(userInput);
-}
-
-#endif // UTILS_H