diff options
Diffstat (limited to 'tests/manual')
114 files changed, 4367 insertions, 1148 deletions
diff --git a/tests/manual/CMakeLists.txt b/tests/manual/CMakeLists.txt new file mode 100644 index 000000000..d9f3e11ea --- /dev/null +++ b/tests/manual/CMakeLists.txt @@ -0,0 +1,7 @@ +add_subdirectory(examples) +if(TARGET Qt::WebEngineQuick) + add_subdirectory(quick) +endif() +if(TARGET Qt::WebEngineWidgets) + add_subdirectory(widgets) +endif() diff --git a/tests/manual/examples/CMakeLists.txt b/tests/manual/examples/CMakeLists.txt new file mode 100644 index 000000000..c56302f20 --- /dev/null +++ b/tests/manual/examples/CMakeLists.txt @@ -0,0 +1,6 @@ +if(TARGET Qt::WebEngineWidgets) + add_subdirectory(widgets) +endif() +if(TARGET Qt::WebEngineQuick) + add_subdirectory(quick) +endif() diff --git a/tests/manual/examples/quick/CMakeLists.txt b/tests/manual/examples/quick/CMakeLists.txt new file mode 100644 index 000000000..c461f2dbb --- /dev/null +++ b/tests/manual/examples/quick/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(minimal) +add_subdirectory(customdialogs) +add_subdirectory(customtouchhandle) +add_subdirectory(webengineaction) diff --git a/tests/manual/examples/quick/customdialogs/CMakeLists.txt b/tests/manual/examples/quick/customdialogs/CMakeLists.txt new file mode 100644 index 000000000..bfbff79eb --- /dev/null +++ b/tests/manual/examples/quick/customdialogs/CMakeLists.txt @@ -0,0 +1,56 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(customdialogs LANGUAGES CXX) + find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_manual_test(customdialogs + SOURCES main.cpp server.cpp server.h +) + +set_target_properties(customdialogs PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(customdialogs PUBLIC + Qt::Core + Qt::Gui + Qt::WebEngineQuick +) + +set(customdialogs_resource_files + "MessageRectangle.qml" + "SwitchButton.qml" + "WebView.qml" + "forms/Authentication.qml" + "forms/AuthenticationForm.ui.qml" + "forms/ColorCell.qml" + "forms/ColorPicker.qml" + "forms/ColorPickerForm.ui.qml" + "forms/CustomButton.qml" + "forms/FilePicker.qml" + "forms/FilePickerForm.ui.qml" + "forms/FileRow.qml" + "forms/JavaScript.qml" + "forms/JavaScriptForm.ui.qml" + "forms/Menu.qml" + "forms/MenuForm.ui.qml" + "forms/TouchSelectionMenu.qml" + "forms/TouchSelectionMenuForm.ui.qml" + "icon.svg" + "index.html" + "main.qml" + "style.css" +) + +qt_add_resources(customdialogs "customdialogs" + PREFIX + "/" + FILES + ${customdialogs_resource_files} +) + diff --git a/tests/manual/examples/quick/customdialogs/MessageRectangle.qml b/tests/manual/examples/quick/customdialogs/MessageRectangle.qml new file mode 100644 index 000000000..09a202cf3 --- /dev/null +++ b/tests/manual/examples/quick/customdialogs/MessageRectangle.qml @@ -0,0 +1,18 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick + +Rectangle { + property alias text: messageText.text + width: parent.width + height: 30 + visible: false + color: "#80c342" + Text { + id: messageText + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + font.pointSize: 12 + } +} diff --git a/tests/manual/examples/quick/customdialogs/SwitchButton.qml b/tests/manual/examples/quick/customdialogs/SwitchButton.qml new file mode 100644 index 000000000..69fc1427e --- /dev/null +++ b/tests/manual/examples/quick/customdialogs/SwitchButton.qml @@ -0,0 +1,23 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +Item { + width: parent.width + height: 40 + property alias checked: switcher.checked + RowLayout { + anchors.centerIn: parent + Text { + text: qsTr("Use default dialogs") + font.pointSize: 12 + } + Switch { + id: switcher + checked: true + } + } +} diff --git a/tests/manual/examples/quick/customdialogs/WebView.qml b/tests/manual/examples/quick/customdialogs/WebView.qml new file mode 100644 index 000000000..5c99ee7e7 --- /dev/null +++ b/tests/manual/examples/quick/customdialogs/WebView.qml @@ -0,0 +1,117 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtWebEngine + +WebEngineView { + id: view + url: "qrc:/index.html" + property bool useDefaultDialogs: true + signal openForm(var form) + + Rectangle { + id: tooltip + width: 200 + height: 30 + z: 50 + visible: false + color: "gray" + border.color: "black" + border.width: 2 + radius: 3 + + property string text: "" + + Text { + x: 0 + y: 0 + color: "#ffffff" + text: parent.text + font.pointSize: 12 + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + font.bold: false + } + + } + + onContextMenuRequested: function(request) { + // we only show menu for links with #openMenu + if (!request.linkUrl.toString().endsWith("#openMenu")) { + request.accepted = true; + return; + } + // return early to show default menu + if (useDefaultDialogs) + return; + + request.accepted = true; + openForm({item: Qt.resolvedUrl("forms/Menu.qml"), + properties: {"request": request}}); + } + + onTooltipRequested: function(request) { + if (useDefaultDialogs) + return; + + if (request.type == TooltipRequest.Show) { + tooltip.visible = true; + tooltip.x = request.x; + tooltip.y = request.y; + tooltip.text = request.text; + } else { + tooltip.visible = false; + } + + request.accepted = true; + } + + onAuthenticationDialogRequested: function(request) { + if (useDefaultDialogs) { + // do not show proxy error page + view.url = "qrc:/index.html" + return; + } + request.accepted = true; + openForm({item: Qt.resolvedUrl("forms/Authentication.qml"), + properties: {"request": request}}); + } + + onJavaScriptDialogRequested: function(request) { + if (useDefaultDialogs) + return; + + request.accepted = true; + openForm({item: Qt.resolvedUrl("forms/JavaScript.qml"), + properties: {"request": request}}); + } + + onColorDialogRequested: function(request) { + if (useDefaultDialogs) + return; + + request.accepted = true; + openForm({item: Qt.resolvedUrl("forms/ColorPicker.qml"), + properties: {"request": request}}); + } + + onFileDialogRequested: function(request) { + if (useDefaultDialogs) + return; + + request.accepted = true; + openForm({item: Qt.resolvedUrl("forms/FilePicker.qml"), + properties: {"request": request}}); + + } + + onTouchSelectionMenuRequested: function(request) { + if (useDefaultDialogs) + return; + + request.accepted = true; + openForm({item: Qt.resolvedUrl("forms/TouchSelectionMenu.qml"), + properties: {"request": request}}); + } +} diff --git a/tests/manual/examples/quick/customdialogs/customdialogs.pro b/tests/manual/examples/quick/customdialogs/customdialogs.pro new file mode 100644 index 000000000..1b9a6778e --- /dev/null +++ b/tests/manual/examples/quick/customdialogs/customdialogs.pro @@ -0,0 +1,18 @@ +QT += webenginequick + +HEADERS += \ + server.h + +SOURCES += \ + main.cpp \ + server.cpp + +RESOURCES += \ + customdialogs.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/webenginequick/customdialogs +INSTALLS += target + +qtHaveModule(widgets) { + QT += widgets # QApplication is required to get native styling with QtQuickControls +} diff --git a/tests/manual/examples/quick/customdialogs/customdialogs.qrc b/tests/manual/examples/quick/customdialogs/customdialogs.qrc new file mode 100644 index 000000000..bb2677198 --- /dev/null +++ b/tests/manual/examples/quick/customdialogs/customdialogs.qrc @@ -0,0 +1,24 @@ +<RCC> + <qresource prefix="/"> + <file>forms/AuthenticationForm.ui.qml</file> + <file>forms/Authentication.qml</file> + <file>forms/ColorCell.qml</file> + <file>forms/ColorPickerForm.ui.qml</file> + <file>forms/ColorPicker.qml</file> + <file>forms/CustomButton.qml</file> + <file>forms/FilePickerForm.ui.qml</file> + <file>forms/FilePicker.qml</file> + <file>forms/FileRow.qml</file> + <file>forms/JavaScriptForm.ui.qml</file> + <file>forms/JavaScript.qml</file> + <file>forms/MenuForm.ui.qml</file> + <file>forms/Menu.qml</file> + <file>icon.svg</file> + <file>index.html</file> + <file>main.qml</file> + <file>MessageRectangle.qml</file> + <file>style.css</file> + <file>SwitchButton.qml</file> + <file>WebView.qml</file> + </qresource> +</RCC> diff --git a/tests/manual/examples/quick/customdialogs/forms/Authentication.qml b/tests/manual/examples/quick/customdialogs/forms/Authentication.qml new file mode 100644 index 000000000..151a7c4aa --- /dev/null +++ b/tests/manual/examples/quick/customdialogs/forms/Authentication.qml @@ -0,0 +1,31 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtWebEngine + +AuthenticationForm { + property QtObject request + signal closeForm() + + cancelButton.onClicked: { + request.dialogReject(); + closeForm(); + } + + loginButton.onClicked: { + request.dialogReject(); + closeForm(); + } + + Component.onCompleted: { + switch (request.type) { + case AuthenticationDialogRequest.AuthenticationTypeHTTP: + console.log("HTTP Authentication Required. Host says: " + request.realm); + break; + case AuthenticationDialogRequest.AuthenticationTypeProxy: + console.log("Proxy Authentication Required for: " + request.proxyHost); + break; + } + } +} diff --git a/tests/manual/examples/quick/customdialogs/forms/AuthenticationForm.ui.qml b/tests/manual/examples/quick/customdialogs/forms/AuthenticationForm.ui.qml new file mode 100644 index 000000000..f14986b20 --- /dev/null +++ b/tests/manual/examples/quick/customdialogs/forms/AuthenticationForm.ui.qml @@ -0,0 +1,137 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls + +Item { + id: item1 + property alias cancelButton: cancelButton + property alias loginButton: loginButton + property alias userName: userName + property alias password: password + + ColumnLayout { + id: columnLayout + anchors.topMargin: 20 + anchors.top: parent.top + anchors.bottomMargin: 20 + anchors.bottom: parent.bottom + anchors.rightMargin: 20 + anchors.right: parent.right + anchors.leftMargin: 20 + anchors.left: parent.left + + Image { + id: image + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + source: "qrc:/icon.svg" + } + + Rectangle { + id: rectangle + width: parent.width + height: 30 + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + gradient: Gradient { + GradientStop { + position: 0 + color: "#25a6e2" + } + GradientStop { + color: "#188bd0" + } + } + + Text { + id: textArea + x: 54 + y: 5 + color: "#ffffff" + text: qsTr("Restricted Area") + font.pointSize: 12 + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + } + } + + Item { + width: 40 + height: 40 + } + + Text { + id: userNameText + text: qsTr("Username:") + font.pointSize: 12 + } + + TextField { + id: userName + width: 300 + height: 22 + Layout.fillWidth: true + font.pointSize: 12 + color: "black" + + background: Rectangle { + color: "white" + border.color: "black" + border.width: 1 + } + } + + Text { + id: passwordText + text: qsTr("Password:") + font.pointSize: 12 + } + + TextField { + id: password + width: 300 + height: 26 + Layout.fillWidth: true + font.pointSize: 12 + color: "black" + echoMode: TextInput.Password + + background: Rectangle { + color: "white" + border.color: "black" + border.width: 1 + } + } + + Item { + Layout.fillHeight: true + } + + RowLayout { + id: rowLayout + width: 100 + height: 100 + + Item { + Layout.fillWidth: true + } + + CustomButton { + id: cancelButton + width: 90 + height: 30 + btnText: qsTr("Cancel") + btnBlue: false + } + + CustomButton { + id: loginButton + width: 90 + height: 30 + btnText: qsTr("Login") + btnBlue: false + } + } + } +} diff --git a/tests/manual/examples/quick/customdialogs/forms/ColorCell.qml b/tests/manual/examples/quick/customdialogs/forms/ColorCell.qml new file mode 100644 index 000000000..57151780c --- /dev/null +++ b/tests/manual/examples/quick/customdialogs/forms/ColorCell.qml @@ -0,0 +1,16 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick + +Rectangle { + id: rectangle + width: 50 + height: 50 + signal clicked() + MouseArea { + id: mouseArea + anchors.fill: parent + onClicked: rectangle.clicked() + } +} diff --git a/tests/manual/examples/quick/customdialogs/forms/ColorPicker.qml b/tests/manual/examples/quick/customdialogs/forms/ColorPicker.qml new file mode 100644 index 000000000..63269ddff --- /dev/null +++ b/tests/manual/examples/quick/customdialogs/forms/ColorPicker.qml @@ -0,0 +1,31 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick + +ColorPickerForm { + property QtObject request + signal closeForm() + + okButton.onClicked: { + request.dialogAccept(colorPicker.color); + closeForm(); + } + + cancelButton.onClicked: { + request.dialogReject(); + closeForm(); + } + + function createCallback(color) { + return function() { colorPicker.color = color }; + } + + Component.onCompleted:{ + for (var i = 0; i < grid.children.length; i++) { + var cell = grid.children[i]; + cell.clicked.connect(createCallback(cell.color)); + } + colorPicker.color = request.color; + } +} diff --git a/tests/manual/examples/quick/customdialogs/forms/ColorPickerForm.ui.qml b/tests/manual/examples/quick/customdialogs/forms/ColorPickerForm.ui.qml new file mode 100644 index 000000000..060aeef7d --- /dev/null +++ b/tests/manual/examples/quick/customdialogs/forms/ColorPickerForm.ui.qml @@ -0,0 +1,186 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Layouts + +Item { + property alias cancelButton: cancelButton + property alias okButton: okButton + property string message: "Message" + property string title: "Title" + property alias blue1: blue1 + property alias grid: grid + property alias colorPicker: colorPicker + + ColumnLayout { + id: columnLayout + anchors.topMargin: 20 + anchors.top: parent.top + anchors.bottomMargin: 20 + anchors.bottom: parent.bottom + anchors.rightMargin: 20 + anchors.right: parent.right + anchors.leftMargin: 20 + anchors.left: parent.left + + Image { + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + source: "qrc:/icon.svg" + } + + Rectangle { + width: parent.width + height: 30 + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + gradient: Gradient { + GradientStop { + position: 0 + color: "#25a6e2" + } + + GradientStop { + color: "#188bd0" + } + } + + Text { + id: title + x: 54 + y: 5 + color: "#ffffff" + text: qsTr("Select Color") + font.pointSize: 12 + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + } + } + + Item { + width: 40 + height: 40 + } + + GridLayout { + id: grid + columns: 5 + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + + ColorCell { + id: blue1 + color: "#26d5f8" + } + ColorCell { + id: green1 + color: "#25f93d" + } + ColorCell { + id: red1 + color: "#f71111" + } + ColorCell { + id: yellow1 + color: "#faf23c" + } + ColorCell { + id: orange1 + color: "#ec8505" + } + ColorCell { + id: blue2 + color: "#037eaa" + } + ColorCell { + id: green2 + color: "#389a13" + } + ColorCell { + id: red2 + color: "#b2001b" + } + ColorCell { + id: yellow2 + color: "#caca03" + } + ColorCell { + id: orange2 + color: "#bb4900" + } + ColorCell { + id: blue3 + color: "#01506c" + } + ColorCell { + id: green3 + color: "#37592b" + } + ColorCell { + id: red3 + color: "#700113" + } + ColorCell { + id: yellow3 + color: "#848404" + } + + ColorCell { + id: orange3 + color: "#563100" + } + } + + Item { + width: 10 + height: 10 + } + + Rectangle { + width: 90 + height: 90 + color: "#000000" + radius: 4 + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + + Rectangle { + id: colorPicker + height: 80 + color: "#ffffff" + anchors.rightMargin: 5 + anchors.leftMargin: 5 + anchors.bottomMargin: 5 + anchors.topMargin: 5 + anchors.fill: parent + } + } + + Item { + Layout.fillHeight: true + } + + RowLayout { + id: rowLayout + width: 100 + height: 100 + + Item { + Layout.fillWidth: true + } + + CustomButton { + id: cancelButton + width: 90 + height: 30 + btnText: qsTr("Cancel") + btnBlue: false + } + + CustomButton { + id: okButton + width: 90 + height: 30 + btnText: qsTr("OK") + btnBlue: false + } + } + } +} diff --git a/tests/manual/examples/quick/customdialogs/forms/CustomButton.qml b/tests/manual/examples/quick/customdialogs/forms/CustomButton.qml new file mode 100644 index 000000000..00a06d558 --- /dev/null +++ b/tests/manual/examples/quick/customdialogs/forms/CustomButton.qml @@ -0,0 +1,61 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick + +Rectangle { + id: root + width: 200 + height: 30 + radius: 5 + property string btnText: "Name" + property bool btnEnable: true + property bool btnBlue: true + opacity: btnEnable ? 1.0 : 0.5 + signal clicked() + gradient: btnBlue ? blueButton : greenButton + Text { + id: textArea + x: 54 + y: 5 + color: "#ffffff" + text: parent.btnText + font.pointSize: 12 + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + font.bold: false + } + + MouseArea { + id: mouseArea + anchors.fill: parent + onClicked: { + if (btnEnable) + root.clicked(); + } + } + + Gradient { + id: blueButton + GradientStop { + position: 0 + color: "#25a6e2" + } + GradientStop { + position: mouseArea.pressed && root.btnEnable ? 0.7 :1 + color: "#188bd0" + } + } + + Gradient { + id: greenButton + GradientStop { + position: 0 + color: "#80c342" + } + GradientStop { + position: mouseArea.pressed && root.btnEnable ? 0.7 :1 + color: "#5fac18" + } + } +} diff --git a/tests/manual/examples/quick/customdialogs/forms/FilePicker.qml b/tests/manual/examples/quick/customdialogs/forms/FilePicker.qml new file mode 100644 index 000000000..45ffefb3a --- /dev/null +++ b/tests/manual/examples/quick/customdialogs/forms/FilePicker.qml @@ -0,0 +1,44 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick + +FilePickerForm { + property QtObject request + property string selectedFile + signal closeForm() + + cancelButton.onClicked: { + request.dialogReject(); + closeForm(); + } + + okButton.onClicked: { + request.dialogAccept('/' + selectedFile); + closeForm(); + } + + function createCallback(fileIndex) { + return function() { + for (var i = 0; i < files.children.length; i++) { + var file = files.children[i]; + if (i === fileIndex) { + selectedFile = file.text; + file.selected = true; + } else { + file.selected = false; + } + } + } + } + + Component.onCompleted: { + selectedFile = request.defaultFileName; + for (var i = 0; i < files.children.length; i++) { + var file = files.children[i]; + file.clicked.connect(createCallback(i)); + if (file.text === selectedFile) + file.selected = true; + } + } +} diff --git a/tests/manual/examples/quick/customdialogs/forms/FilePickerForm.ui.qml b/tests/manual/examples/quick/customdialogs/forms/FilePickerForm.ui.qml new file mode 100644 index 000000000..1e99b1a91 --- /dev/null +++ b/tests/manual/examples/quick/customdialogs/forms/FilePickerForm.ui.qml @@ -0,0 +1,128 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Layouts + +Item { + property alias cancelButton: cancelButton + property alias okButton: okButton + property string message: "Message" + property string title: "Title" + property alias files: files + + ColumnLayout { + id: columnLayout + anchors.topMargin: 20 + anchors.top: parent.top + anchors.bottomMargin: 20 + anchors.bottom: parent.bottom + anchors.rightMargin: 20 + anchors.right: parent.right + anchors.leftMargin: 20 + anchors.left: parent.left + + Image { + id: image + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + source: "qrc:/icon.svg" + } + + Rectangle { + id: rectangle + width: parent.width + height: 30 + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + gradient: Gradient { + GradientStop { + position: 0 + color: "#25a6e2" + } + + GradientStop { + color: "#188bd0" + } + } + + Text { + id: title + x: 54 + y: 5 + color: "#ffffff" + text: qsTr("Select File") + font.pointSize: 12 + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + } + } + + Item { + width: 40 + height: 40 + } + + ColumnLayout { + id: files + + FileRow { + id: filename1 + text: "example.qdoc" + } + + FileRow { + id: filename2 + text: "factory.cpp" + } + + FileRow { + id: filename3 + text: "index.html" + } + + FileRow { + id: filename4 + text: "main.qml" + } + + FileRow { + id: filename5 + text: "qt-logo.png" + } + + FileRow { + id: filename6 + text: "window.h" + } + } + + Item { + Layout.fillHeight: true + } + + RowLayout { + id: rowLayout + width: 20 + height: 100 + + Item { + Layout.fillWidth: true + } + + CustomButton { + id: cancelButton + width: 90 + height: 30 + btnText: qsTr("Cancel") + btnBlue: false + } + + CustomButton { + id: okButton + width: 90 + height: 30 + btnText: qsTr("OK") + btnBlue: false + } + } + } +} diff --git a/tests/manual/examples/quick/customdialogs/forms/FileRow.qml b/tests/manual/examples/quick/customdialogs/forms/FileRow.qml new file mode 100644 index 000000000..1a0cfc0a0 --- /dev/null +++ b/tests/manual/examples/quick/customdialogs/forms/FileRow.qml @@ -0,0 +1,44 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Layouts + +Item { + id: root + height: 30 + property string text: "Filename" + property bool selected: false + signal clicked() + + RowLayout { + id: fileRow + width: 100 + + Item { + id: item5 + width: 10 + height: 10 + } + + Rectangle { + id: rectangle2 + width: 10 + height: 10 + color: selected ? "#80c342" : "#25a6e2" + } + + Text { + id: filename + text: root.text + font.pointSize: 12 + } + } + + MouseArea { + id: mouseArea + width: 200 + height: 30 + onClicked: root.clicked() + } +} diff --git a/tests/manual/examples/quick/customdialogs/forms/JavaScript.qml b/tests/manual/examples/quick/customdialogs/forms/JavaScript.qml new file mode 100644 index 000000000..132c95697 --- /dev/null +++ b/tests/manual/examples/quick/customdialogs/forms/JavaScript.qml @@ -0,0 +1,44 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtWebEngine + +JavaScriptForm { + property QtObject request + signal closeForm() + + cancelButton.onClicked: { + request.dialogReject(); + closeForm(); + } + + okButton.onClicked: { + request.dialogAccept(prompt.text); + closeForm(); + } + + Component.onCompleted: { + switch (request.type) { + case JavaScriptDialogRequest.DialogTypeAlert: + cancelButton.visible = false; + title = qsTr("Alert"); + message = request.message; + prompt.text = ""; + prompt.visible = false; + break; + case JavaScriptDialogRequest.DialogTypeConfirm: + title = qsTr("Confirm"); + message = request.message; + prompt.text = ""; + prompt.visible = false; + break; + case JavaScriptDialogRequest.DialogTypePrompt: + title = qsTr("Prompt"); + message = request.message; + prompt.text = request.defaultText; + prompt.visible = true; + break; + } + } +} diff --git a/tests/manual/examples/quick/customdialogs/forms/JavaScriptForm.ui.qml b/tests/manual/examples/quick/customdialogs/forms/JavaScriptForm.ui.qml new file mode 100644 index 000000000..b535e7ef9 --- /dev/null +++ b/tests/manual/examples/quick/customdialogs/forms/JavaScriptForm.ui.qml @@ -0,0 +1,117 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls + +Item { + id: root + property alias cancelButton: cancelButton + property alias okButton: okButton + property string message: "Message" + property string title: "Title" + property alias prompt: prompt + + ColumnLayout { + id: columnLayout + anchors.topMargin: 20 + anchors.top: parent.top + anchors.bottomMargin: 20 + anchors.bottom: parent.bottom + anchors.rightMargin: 20 + anchors.right: parent.right + anchors.leftMargin: 20 + anchors.left: parent.left + + Image { + id: image + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + source: "qrc:/icon.svg" + } + + Rectangle { + id: rectangle + width: parent.width + height: 30 + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + gradient: Gradient { + GradientStop { + position: 0 + color: "#25a6e2" + } + + GradientStop { + color: "#188bd0" + } + } + + Text { + id: title + x: 54 + y: 5 + color: "#ffffff" + text: qsTr("Title") + font.pointSize: 12 + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + } + } + + Item { + width: 40 + height: 40 + } + + Text { + id: message + text: root.message + font.pointSize: 12 + } + + TextField { + id: prompt + width: 300 + height: 22 + Layout.fillWidth: true + font.pointSize: 12 + color: "black" + + background: Rectangle { + color: "white" + border.color: "black" + border.width: 1 + } + } + + Item { + Layout.fillHeight: true + } + + RowLayout { + id: rowLayout + width: 100 + height: 100 + + Item { + Layout.fillWidth: true + } + + CustomButton { + id: cancelButton + width: 90 + height: 30 + btnText: qsTr("Cancel") + btnBlue: false + } + + CustomButton { + id: okButton + width: 90 + height: 30 + btnText: qsTr("OK") + btnBlue: false + } + } + } +} diff --git a/tests/manual/examples/quick/customdialogs/forms/Menu.qml b/tests/manual/examples/quick/customdialogs/forms/Menu.qml new file mode 100644 index 000000000..b90802a0c --- /dev/null +++ b/tests/manual/examples/quick/customdialogs/forms/Menu.qml @@ -0,0 +1,22 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick + +MenuForm { + property QtObject request + signal closeForm() + + followLink.onClicked: closeForm() + back.onClicked: closeForm() + forward.onClicked: closeForm() + reload.onClicked: closeForm() + copyLinkUrl.onClicked: closeForm() + saveLink.onClicked: closeForm() + close.onClicked: closeForm() + + Component.onCompleted: { + back.btnEnable = false; + forward.btnEnable = false; + } +} diff --git a/tests/manual/examples/quick/customdialogs/forms/MenuForm.ui.qml b/tests/manual/examples/quick/customdialogs/forms/MenuForm.ui.qml new file mode 100644 index 000000000..b4c06bb7d --- /dev/null +++ b/tests/manual/examples/quick/customdialogs/forms/MenuForm.ui.qml @@ -0,0 +1,65 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Layouts + +Item { + property alias followLink: followLink + property alias back: back + property alias forward: forward + property alias reload: reload + property alias copyLinkUrl: copyLinkUrl + property alias saveLink: saveLink + property alias close: close + + ColumnLayout { + id: columnLayout + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + + Image { + id: image + width: 100 + height: 100 + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + source: "qrc:/icon.svg" + } + + CustomButton { + id: followLink + btnText: qsTr("Follow") + } + + CustomButton { + id: back + btnText: qsTr("Back") + } + + CustomButton { + id: forward + btnText: qsTr("Forward") + } + + CustomButton { + id: reload + btnText: qsTr("Reload") + } + + CustomButton { + id: copyLinkUrl + btnText: qsTr("Copy Link URL") + } + + CustomButton { + id: saveLink + btnText: qsTr("Save Link") + } + + CustomButton { + id: close + btnBlue: false + btnText: qsTr("Close") + } + } +} diff --git a/tests/manual/examples/quick/customdialogs/forms/TouchSelectionMenu.qml b/tests/manual/examples/quick/customdialogs/forms/TouchSelectionMenu.qml new file mode 100644 index 000000000..1b0c19789 --- /dev/null +++ b/tests/manual/examples/quick/customdialogs/forms/TouchSelectionMenu.qml @@ -0,0 +1,14 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick + +TouchSelectionMenuForm { + property QtObject request + signal closeForm() + + cut.onClicked: closeForm() + copy.onClicked: closeForm() + paste.onClicked: closeForm() + contextMenu.onClicked: closeForm() +} diff --git a/tests/manual/examples/quick/customdialogs/forms/TouchSelectionMenuForm.ui.qml b/tests/manual/examples/quick/customdialogs/forms/TouchSelectionMenuForm.ui.qml new file mode 100644 index 000000000..bed39566f --- /dev/null +++ b/tests/manual/examples/quick/customdialogs/forms/TouchSelectionMenuForm.ui.qml @@ -0,0 +1,39 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Layouts + +Item { + property alias cut: cut + property alias copy: copy + property alias paste: paste + property alias contextMenu: contextMenu + + ColumnLayout { + id: columnLayout + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + + CustomButton { + id: cut + btnText: qsTr("Cut") + } + + CustomButton { + id: copy + btnText: qsTr("Copy") + } + + CustomButton { + id: paste + btnText: qsTr("Paste") + } + + CustomButton { + id: contextMenu + btnText: qsTr("...") + } + + } +} diff --git a/tests/manual/examples/quick/customdialogs/forms/forms.qmlproject b/tests/manual/examples/quick/customdialogs/forms/forms.qmlproject new file mode 100644 index 000000000..b06afaaf1 --- /dev/null +++ b/tests/manual/examples/quick/customdialogs/forms/forms.qmlproject @@ -0,0 +1,45 @@ +import QmlProject + +Project { + mainFile: "MenuForm.ui.qml" + + /* Include .qml, .js, and image files from current directory and subdirectories */ + QmlFiles { + directory: "." + } + + JavaScriptFiles { + directory: "." + } + + ImageFiles { + directory: "." + } + + Files { + filter: "*.conf" + files: ["qtquickcontrols2.conf"] + } + + Files { + filter: "qmldir" + directory: "." + } + + Files { + filter: "*.ttf;*.otf" + } + + Environment { + QT_QUICK_CONTROLS_CONF: "qtquickcontrols2.conf" + QT_AUTO_SCREEN_SCALE_FACTOR: "1" + } + + qt6Project: true + + /* List of plugin directories passed to QML runtime */ + importPaths: [ ".", "imports" ] + + /* Required for deployment */ + targetDirectory: "/opt/forms" +} diff --git a/tests/manual/examples/quick/customdialogs/icon.svg b/tests/manual/examples/quick/customdialogs/icon.svg new file mode 100644 index 000000000..48271180b --- /dev/null +++ b/tests/manual/examples/quick/customdialogs/icon.svg @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + width="94px" height="94px" viewBox="0 0 94 94" enable-background="new 0 0 94 94" xml:space="preserve"> +<g> + <circle fill="none" cx="47" cy="47" r="47"/> + <g> + <path fill="#46A2DA" d="M47,92.979c-11.779,0-23.559-4.484-32.526-13.451C-3.461,61.591-3.461,32.409,14.472,14.474 + C32.41-3.463,61.592-3.461,79.526,14.473c17.935,17.936,17.935,47.119,0.002,65.054l-0.002,0.001 + C70.559,88.495,58.779,92.979,47,92.979z"/> + </g> + <path fill="#80C342" d="M93,47C93,21.595,72.405,1,47,1C34.297,1,22.797,6.149,14.473,14.473l65.054,65.054 + C87.851,71.203,93,59.703,93,47z"/> + <g> + <path fill="#46A2DA" d="M47,65c-4.808,0-9.328-1.873-12.728-5.272c-7.018-7.019-7.018-18.438,0-25.456 + C37.672,30.873,42.192,29,47,29s9.328,1.873,12.728,5.272c7.018,7.019,7.018,18.438,0,25.456C56.328,63.127,51.808,65,47,65z"/> + <path fill="#FFFFFF" d="M62.248,59.919c6.671-7.858,6.312-19.644-1.105-27.061C57.237,28.953,52.118,27,47,27 + c-5.118,0-10.237,1.953-14.142,5.858c-7.81,7.81-7.81,20.474,0,28.284C36.763,65.047,41.882,67,47,67 + c4.379,0,8.752-1.441,12.372-4.3L77.88,81.209c0.989-0.895,1.935-1.837,2.843-2.814L62.248,59.919z M35.686,58.314 + c-6.238-6.238-6.238-16.389,0-22.627C38.708,32.664,42.726,31,47,31c4.274,0,8.292,1.664,11.314,4.686 + c6.238,6.238,6.238,16.389,0,22.627C55.292,61.336,51.274,63,47,63C42.726,63,38.708,61.336,35.686,58.314z"/> + </g> +</g> +</svg> diff --git a/tests/manual/examples/quick/customdialogs/index.html b/tests/manual/examples/quick/customdialogs/index.html new file mode 100644 index 000000000..d5de2827c --- /dev/null +++ b/tests/manual/examples/quick/customdialogs/index.html @@ -0,0 +1,51 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="utf-8"> + <title>Custom UI</title> + <link rel="stylesheet" type="text/css" href="style.css"> + </head> + <body> + <table align="center"> + <tr> + <td><div class="div"><a href="#openMenu" class="link">Right click on text to see link context menu</a></div></td> + </tr> + <tr> + <td><div class="div"><p title="I am a tooltip.">Hover this text to display a tooltip</a></div></td> + </tr> + <tr> + <td><div class="div"><p>Touch devices only: long press on this text to see the touch selection menu</p></div></td> + </tr> + <tr> + <td><button class="button" onclick="window.location = 'http://localhost.:5555/OPEN_AUTH'"> + Open Authentication Dialog</button></td> + </tr> + <tr> + <td><button class="button" onclick="window.location = 'http://www.qt.io'"> + Open Proxy Dialog</button></td> + </tr> + <tr> + <td><button class="button" onclick="alert('This is the Alert Dialog !')"> + Open Alert Dialog</button></td> + </tr> + <tr> + <td><button class="button" onclick="confirm('This is the Confirm Dialog.')"> + Open Confirm Dialog</button></td> + </tr> + <tr> + <td><button class="button" onclick="prompt('Is this the Prompt Dialog ?', 'Yes')"> + Open Prompt Dialog</button></td> + </tr> + <tr> + <td><button class="button" onclick="document.getElementById('colorpicker').click()"> + Open Color Dialog</button></td> + </tr> + <tr> + <td><button class="button" onclick="document.getElementById('filepicker').click()"> + Open File Dialog</button></td> + </tr> + </table> + <input type="color" id="colorpicker" value="#ff0000" style="visibility:hidden"/> + <input type="file" id="filepicker" accept=".cpp, .html, .h, .png, .qdoc, .qml" style="visibility:hidden"/> + </body> +</html> diff --git a/tests/manual/examples/quick/customdialogs/main.cpp b/tests/manual/examples/quick/customdialogs/main.cpp new file mode 100644 index 000000000..c114ea935 --- /dev/null +++ b/tests/manual/examples/quick/customdialogs/main.cpp @@ -0,0 +1,32 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "server.h" +#include <QtWebEngineQuick/qtwebenginequickglobal.h> +#include <QNetworkProxy> +#include <QQmlApplicationEngine> +#include <QTimer> +#include <QtGui/QGuiApplication> + +int main(int argc, char *argv[]) +{ + QCoreApplication::setOrganizationName("QtExamples"); + QtWebEngineQuick::initialize(); + + QGuiApplication app(argc, argv); + + QQmlApplicationEngine engine; + Server *server = new Server(&engine); + + engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); + QTimer::singleShot(0, server, &Server::run); + + QNetworkProxy proxy; + proxy.setType(QNetworkProxy::HttpProxy); + proxy.setHostName("localhost"); + proxy.setPort(5555); + QNetworkProxy::setApplicationProxy(proxy); + + return app.exec(); +} + diff --git a/tests/manual/examples/quick/customdialogs/main.qml b/tests/manual/examples/quick/customdialogs/main.qml new file mode 100644 index 000000000..d0cb6f324 --- /dev/null +++ b/tests/manual/examples/quick/customdialogs/main.qml @@ -0,0 +1,56 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Window + +Window { + id: mainWindow + width: 800 + height: 610 + visible: true + + StackView { + id: stackView + anchors.fill: parent + focus: true + initialItem: Item { + id: main + width: mainWindow.width + height: mainWindow.height + ColumnLayout { + anchors.fill: parent + SwitchButton { + id: switcher + Layout.fillWidth: true + } + WebView { + id: webView + useDefaultDialogs: switcher.checked + Layout.fillWidth: true + Layout.fillHeight: true + } + } + } + + function closeForm() + { + pop(main); + // reset url in case of proxy error + webView.url = "qrc:/index.html" + } + + function openForm(form) + { + push(form.item, form.properties); + currentItem.closeForm.connect(closeForm); + } + + } + + Component.onCompleted: { + webView.openForm.connect(stackView.openForm); + } +} diff --git a/tests/manual/examples/quick/customdialogs/server.cpp b/tests/manual/examples/quick/customdialogs/server.cpp new file mode 100644 index 000000000..efb870618 --- /dev/null +++ b/tests/manual/examples/quick/customdialogs/server.cpp @@ -0,0 +1,47 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "server.h" +#include <QDataStream> +#include <QTcpSocket> + +Server::Server(QObject *parent) : QObject(parent) +{ + connect(&m_server, &QTcpServer::newConnection, this, &Server::handleNewConnection); +} + +void Server::run() +{ + if (!m_server.listen(QHostAddress::LocalHost, 5555)) + qWarning() << "Could not start the server -> http/proxy authentication dialog" + " will not work. Error:" << m_server.errorString(); +} + +void Server::handleNewConnection() +{ + QTcpSocket *socket = m_server.nextPendingConnection(); + connect(socket, &QAbstractSocket::disconnected, socket, &QObject::deleteLater); + connect(socket, &QAbstractSocket::readyRead, this, &Server::handleReadReady); +} + +void Server::handleReadReady() +{ + QTcpSocket *socket = qobject_cast<QTcpSocket*>(sender()); + Q_ASSERT(socket); + m_data.append(socket->readAll()); + + // simply wait for whole request + if (!m_data.endsWith("\r\n\r\n")) + return; + if (m_data.contains(QByteArrayLiteral("OPEN_AUTH"))) { + socket->write("HTTP/1.1 401 Unauthorized\nWWW-Authenticate: " + "Basic realm=\"Very Restricted Area\"\r\n\r\n"); + m_data.clear(); + return; + } + + socket->write("HTTP/1.1 407 Proxy Auth Required\nProxy-Authenticate: " + "Basic realm=\"Proxy requires authentication\"\r\n" + "content-length: 0\r\n\r\n"); + m_data.clear(); +} diff --git a/tests/manual/examples/quick/customdialogs/server.h b/tests/manual/examples/quick/customdialogs/server.h new file mode 100644 index 000000000..563465013 --- /dev/null +++ b/tests/manual/examples/quick/customdialogs/server.h @@ -0,0 +1,29 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef SERVER_H +#define SERVER_H + +#include <QObject> +#include <QTcpServer> + +class Server : public QObject +{ + Q_OBJECT + +public: + explicit Server(QObject *parent = nullptr); + +public slots: + void run(); + +private slots: + void handleNewConnection(); + void handleReadReady(); + +private: + QTcpServer m_server; + QByteArray m_data; +}; + +#endif // SERVER_H diff --git a/tests/manual/examples/quick/customdialogs/style.css b/tests/manual/examples/quick/customdialogs/style.css new file mode 100644 index 000000000..e4c25e7eb --- /dev/null +++ b/tests/manual/examples/quick/customdialogs/style.css @@ -0,0 +1,37 @@ +.div { + padding:8px 4px; + border: 5px solid #188BD0; + width: 280px; + font-family: sans-serif; + font-size:10pt; +} +.link { + text-decoration: none; + color: #888888; +} +.button { + background: -webkit-linear-gradient(top,#25A6E2 0%,#188BD0 100%); + padding:8px 13px; + color:#fff; + font-family: sans-serif; + font-size:17px; + -webkit-border-radius:5px; + border:1px solid #1A87FF; + width: 300px; +} +.button:focus { + outline: none; +} +.button:active { + background: -webkit-linear-gradient(top,#25A6E2 0%,#188BD0 70%); +} +.input { + padding:8px 4px; + border: 5px solid #188BD0; + width: 280px; + font-family: sans-serif; + font-size:10pt; +} +.input:focus { + outline: none; +} diff --git a/tests/manual/examples/quick/customtouchhandle/CMakeLists.txt b/tests/manual/examples/quick/customtouchhandle/CMakeLists.txt new file mode 100644 index 000000000..5574c28b8 --- /dev/null +++ b/tests/manual/examples/quick/customtouchhandle/CMakeLists.txt @@ -0,0 +1,36 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(customtouchhandle LANGUAGES CXX) + find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_manual_test(customtouchhandle + SOURCES main.cpp +) + +set_target_properties(customtouchhandle PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(customtouchhandle PUBLIC + Qt::Core + Qt::Gui + Qt::WebEngineQuick +) + +# Resources: +set(qml_resource_files + "main.qml" +) + +qt6_add_resources(customtouchhandle "qml" + PREFIX + "/" + FILES + ${qml_resource_files} +) + diff --git a/tests/manual/examples/quick/customtouchhandle/customtouchhandle.pro b/tests/manual/examples/quick/customtouchhandle/customtouchhandle.pro new file mode 100644 index 000000000..a74ef3146 --- /dev/null +++ b/tests/manual/examples/quick/customtouchhandle/customtouchhandle.pro @@ -0,0 +1,10 @@ +TEMPLATE = app + +QT += webenginequick + +SOURCES += main.cpp + +RESOURCES += qml.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/webenginequick/customtouchhandle +INSTALLS += target diff --git a/tests/manual/examples/quick/customtouchhandle/main.cpp b/tests/manual/examples/quick/customtouchhandle/main.cpp new file mode 100644 index 000000000..f1b70b024 --- /dev/null +++ b/tests/manual/examples/quick/customtouchhandle/main.cpp @@ -0,0 +1,19 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include <QGuiApplication> +#include <QQmlApplicationEngine> +#include <QtWebEngineQuick/qtwebenginequickglobal.h> + +int main(int argc, char *argv[]) +{ + QCoreApplication::setOrganizationName("QtExamples"); + QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts); + QtWebEngineQuick::initialize(); + QGuiApplication app(argc, argv); + + QQmlApplicationEngine engine; + engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); + + return app.exec(); +} diff --git a/tests/manual/examples/quick/customtouchhandle/main.qml b/tests/manual/examples/quick/customtouchhandle/main.qml new file mode 100644 index 000000000..c40b4c73b --- /dev/null +++ b/tests/manual/examples/quick/customtouchhandle/main.qml @@ -0,0 +1,96 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Window +import QtWebEngine +import QtQuick.Layouts +import QtQuick.Controls + +ApplicationWindow { + width: 1024 + height: 750 + visible: true + header: ToolBar { + RowLayout { + anchors.fill: parent + + ToolButton { + property int itemAction: WebEngineView.Back + text: webEngineView.action(itemAction).text + enabled: webEngineView.action(itemAction).enabled + onClicked: webEngineView.action(itemAction).trigger() + icon.name: webEngineView.action(itemAction).iconName + display: AbstractButton.TextUnderIcon + } + + ToolButton { + property int itemAction: WebEngineView.Forward + text: webEngineView.action(itemAction).text + enabled: webEngineView.action(itemAction).enabled + onClicked: webEngineView.action(itemAction).trigger() + icon.name: webEngineView.action(itemAction).iconName + display: AbstractButton.TextUnderIcon + } + + ToolButton { + property int itemAction: webEngineView.loading ? WebEngineView.Stop : WebEngineView.Reload + text: webEngineView.action(itemAction).text + enabled: webEngineView.action(itemAction).enabled + onClicked: webEngineView.action(itemAction).trigger() + icon.name: webEngineView.action(itemAction).iconName + display: AbstractButton.TextUnderIcon + } + + TextField { + Layout.fillWidth: true + text: webEngineView.url + selectByMouse: true + onEditingFinished: webEngineView.url = text + } + + Label { text: 'Handle: ' } + ComboBox { + model: [ 'Default', 'Circle', 'Square' ] + + onCurrentValueChanged: { + if (currentValue == 'Circle') + webEngineView.touchHandleDelegate = circleTouchHandle + else if (currentValue == 'Square') + webEngineView.touchHandleDelegate = rectTouchHandle + else + webEngineView.touchHandleDelegate = null + } + + Component.onCompleted: currentIndex = indexOfValue('Square') + } + } + } + + Component { + id: circleTouchHandle + Rectangle { + color: "blue" + border.color: "black" + border.width: 2 + radius: 50 + } + } + + Component { + id: rectTouchHandle + Rectangle { + border.color: "black" + border.width: 2 + radius: 2 + onVisibleChanged: if (visible) { color = 'yellow'; cAnim.restart(); } + ColorAnimation on color { id: cAnim; to: 'red'; duration: 1000 } + } + } + + WebEngineView { + anchors.fill: parent + id: webEngineView + url: "https://www.qt.io" + } +} diff --git a/tests/manual/quick/touchbrowser/qml.qrc b/tests/manual/examples/quick/customtouchhandle/qml.qrc index 45210fe36..5f6483ac3 100644 --- a/tests/manual/quick/touchbrowser/qml.qrc +++ b/tests/manual/examples/quick/customtouchhandle/qml.qrc @@ -1,6 +1,5 @@ <RCC> <qresource prefix="/"> <file>main.qml</file> - <file>AddressBar.qml</file> </qresource> </RCC> diff --git a/tests/manual/examples/quick/minimal/CMakeLists.txt b/tests/manual/examples/quick/minimal/CMakeLists.txt new file mode 100644 index 000000000..42e2078f7 --- /dev/null +++ b/tests/manual/examples/quick/minimal/CMakeLists.txt @@ -0,0 +1,36 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(minimal LANGUAGES CXX) + find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_manual_test(webengine-minimal-qml + SOURCES + main.cpp +) + +set_target_properties(webengine-minimal-qml PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(webengine-minimal-qml PUBLIC + Qt::Core + Qt::Gui + Qt::WebEngineQuick +) + +# Resources: +set(qml_resource_files + "main.qml" +) + +qt_add_resources(webengine-minimal-qml "qml" + PREFIX + "/" + FILES + ${qml_resource_files} +) diff --git a/tests/manual/examples/quick/minimal/main.cpp b/tests/manual/examples/quick/minimal/main.cpp new file mode 100644 index 000000000..16466ae06 --- /dev/null +++ b/tests/manual/examples/quick/minimal/main.cpp @@ -0,0 +1,19 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include <QGuiApplication> +#include <QQmlApplicationEngine> +#include <QtWebEngineQuick/qtwebenginequickglobal.h> + +int main(int argc, char *argv[]) +{ + QCoreApplication::setOrganizationName("QtExamples"); + QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts); + QtWebEngineQuick::initialize(); + QGuiApplication app(argc, argv); + + QQmlApplicationEngine engine; + engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); + + return app.exec(); +} diff --git a/tests/manual/examples/quick/minimal/main.qml b/tests/manual/examples/quick/minimal/main.qml new file mode 100644 index 000000000..6890b501b --- /dev/null +++ b/tests/manual/examples/quick/minimal/main.qml @@ -0,0 +1,16 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Window +import QtWebEngine + +Window { + width: 1024 + height: 750 + visible: true + WebEngineView { + anchors.fill: parent + url: "chrome://qt" + } +} diff --git a/tests/manual/examples/quick/minimal/minimal.pro b/tests/manual/examples/quick/minimal/minimal.pro new file mode 100644 index 000000000..acca6477c --- /dev/null +++ b/tests/manual/examples/quick/minimal/minimal.pro @@ -0,0 +1,10 @@ +TEMPLATE = app + +QT += webenginequick + +SOURCES += main.cpp + +RESOURCES += qml.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/webenginequick/minimal +INSTALLS += target diff --git a/tests/manual/examples/quick/minimal/qml.qrc b/tests/manual/examples/quick/minimal/qml.qrc new file mode 100644 index 000000000..0ff3892d9 --- /dev/null +++ b/tests/manual/examples/quick/minimal/qml.qrc @@ -0,0 +1,6 @@ +<RCC> + <qresource prefix="/"> + <file>main.qml</file> + </qresource> +</RCC> + diff --git a/tests/manual/examples/quick/webengineaction/CMakeLists.txt b/tests/manual/examples/quick/webengineaction/CMakeLists.txt new file mode 100644 index 000000000..e16772faf --- /dev/null +++ b/tests/manual/examples/quick/webengineaction/CMakeLists.txt @@ -0,0 +1,37 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(webengineaction LANGUAGES CXX) + find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_manual_test(webengineaction + SOURCES + main.cpp + utils.h +) + +set_target_properties(webengineaction PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(webengineaction PUBLIC + Qt::Core + Qt::Gui + Qt::WebEngineQuick +) + +# Resources: +set(qml_resource_files + "main.qml" +) + +qt_add_resources(webengineaction "qml" + PREFIX + "/" + FILES + ${qml_resource_files} +) diff --git a/tests/manual/examples/quick/webengineaction/main.cpp b/tests/manual/examples/quick/webengineaction/main.cpp new file mode 100644 index 000000000..a7bfaaf36 --- /dev/null +++ b/tests/manual/examples/quick/webengineaction/main.cpp @@ -0,0 +1,25 @@ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "utils.h" + +#include <QGuiApplication> +#include <QQmlApplicationEngine> +#include <QQmlContext> +#include <QtWebEngineQuick/qtwebenginequickglobal.h> + +int main(int argc, char *argv[]) +{ + QCoreApplication::setOrganizationName("QtExamples"); + QtWebEngineQuick::initialize(); + + QGuiApplication app(argc, argv); + + QQmlApplicationEngine engine; + Utils utils; + + engine.rootContext()->setContextProperty("utils", &utils); + engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); + + return app.exec(); +} diff --git a/tests/manual/examples/quick/webengineaction/main.qml b/tests/manual/examples/quick/webengineaction/main.qml new file mode 100644 index 000000000..a1483b126 --- /dev/null +++ b/tests/manual/examples/quick/webengineaction/main.qml @@ -0,0 +1,119 @@ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Window +import QtWebEngine +import QtQuick.Controls +import QtQuick.Layouts + +ApplicationWindow { + id: window + visible: true + width: 800 + height: 600 + title: qsTr("WebEngineAction Example") + + header: ToolBar { + RowLayout { + anchors.fill: parent + + ToolButton { + property int itemAction: WebEngineView.Back + text: webEngineView.action(itemAction).text + enabled: webEngineView.action(itemAction).enabled + onClicked: webEngineView.action(itemAction).trigger() + icon.name: webEngineView.action(itemAction).iconName + display: AbstractButton.TextUnderIcon + } + + ToolButton { + property int itemAction: WebEngineView.Forward + text: webEngineView.action(itemAction).text + enabled: webEngineView.action(itemAction).enabled + onClicked: webEngineView.action(itemAction).trigger() + icon.name: webEngineView.action(itemAction).iconName + display: AbstractButton.TextUnderIcon + } + + ToolButton { + property int itemAction: webEngineView.loading ? WebEngineView.Stop : WebEngineView.Reload + text: webEngineView.action(itemAction).text + enabled: webEngineView.action(itemAction).enabled + onClicked: webEngineView.action(itemAction).trigger() + icon.name: webEngineView.action(itemAction).iconName + display: AbstractButton.TextUnderIcon + } + + TextField { + Layout.fillWidth: true + + text: webEngineView.url + selectByMouse: true + onEditingFinished: webEngineView.url = utils.fromUserInput(text) + } + + ToolButton { + id: settingsButton + text: "Settings" + icon.name: "settings-configure" + display: AbstractButton.TextUnderIcon + onClicked: settingsMenu.open() + checked: settingsMenu.visible + + Menu { + id: settingsMenu + y: settingsButton.height + + MenuItem { + id: customContextMenuOption + checkable: true + checked: true + + text: "Custom context menu" + } + } + } + } + } + + WebEngineView { + id: webEngineView + url: "https://qt.io" + anchors.fill: parent + + Component.onCompleted: { + profile.downloadRequested.connect(function(download){ + download.accept(); + }) + } + + property Menu contextMenu: Menu { + Repeater { + model: [ + WebEngineView.Back, + WebEngineView.Forward, + WebEngineView.Reload, + WebEngineView.SavePage, + WebEngineView.Copy, + WebEngineView.Paste, + WebEngineView.Cut + ] + MenuItem { + text: webEngineView.action(modelData).text + enabled: webEngineView.action(modelData).enabled + onClicked: webEngineView.action(modelData).trigger() + icon.name: webEngineView.action(modelData).iconName + display: MenuItem.TextBesideIcon + } + } + } + + onContextMenuRequested: function(request) { + if (customContextMenuOption.checked) { + request.accepted = true; + contextMenu.popup(); + } + } + } +} diff --git a/tests/manual/examples/quick/webengineaction/qml.qrc b/tests/manual/examples/quick/webengineaction/qml.qrc new file mode 100644 index 000000000..5f6483ac3 --- /dev/null +++ b/tests/manual/examples/quick/webengineaction/qml.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>main.qml</file> + </qresource> +</RCC> diff --git a/tests/manual/examples/quick/webengineaction/utils.h b/tests/manual/examples/quick/webengineaction/utils.h new file mode 100644 index 000000000..d9a803907 --- /dev/null +++ b/tests/manual/examples/quick/webengineaction/utils.h @@ -0,0 +1,25 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#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 diff --git a/tests/manual/examples/quick/webengineaction/webengineaction.pro b/tests/manual/examples/quick/webengineaction/webengineaction.pro new file mode 100644 index 000000000..9286604a1 --- /dev/null +++ b/tests/manual/examples/quick/webengineaction/webengineaction.pro @@ -0,0 +1,8 @@ +TEMPLATE = app + +QT += webenginequick + +HEADERS += utils.h +SOURCES += main.cpp + +RESOURCES += qml.qrc diff --git a/tests/manual/examples/widgets/CMakeLists.txt b/tests/manual/examples/widgets/CMakeLists.txt new file mode 100644 index 000000000..d853ba634 --- /dev/null +++ b/tests/manual/examples/widgets/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(minimal) diff --git a/tests/manual/examples/widgets/minimal/CMakeLists.txt b/tests/manual/examples/widgets/minimal/CMakeLists.txt new file mode 100644 index 000000000..3b39683ba --- /dev/null +++ b/tests/manual/examples/widgets/minimal/CMakeLists.txt @@ -0,0 +1,24 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(minimal LANGUAGES CXX) + find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) + endif() + +qt_internal_add_manual_test(minimal-widgets + SOURCES + main.cpp +) + +set_target_properties(minimal-widgets PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(minimal-widgets PUBLIC + Qt::Core + Qt::Gui + Qt::WebEngineWidgets +) diff --git a/tests/manual/examples/widgets/minimal/main.cpp b/tests/manual/examples/widgets/minimal/main.cpp new file mode 100644 index 000000000..425973116 --- /dev/null +++ b/tests/manual/examples/widgets/minimal/main.cpp @@ -0,0 +1,28 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include <QApplication> +#include <QWebEngineView> + +QUrl commandLineUrlArgument() +{ + const QStringList args = QCoreApplication::arguments(); + for (const QString &arg : args.mid(1)) { + if (!arg.startsWith(QLatin1Char('-'))) + return QUrl::fromUserInput(arg); + } + return QUrl(QStringLiteral("chrome://qt")); +} + +int main(int argc, char *argv[]) +{ + QCoreApplication::setOrganizationName("QtExamples"); + QApplication app(argc, argv); + + QWebEngineView view; + view.setUrl(commandLineUrlArgument()); + view.resize(1024, 750); + view.show(); + + return app.exec(); +} diff --git a/tests/manual/examples/widgets/minimal/minimal.pro b/tests/manual/examples/widgets/minimal/minimal.pro new file mode 100644 index 000000000..849f4b9b6 --- /dev/null +++ b/tests/manual/examples/widgets/minimal/minimal.pro @@ -0,0 +1,8 @@ +TEMPLATE = app + +QT += webenginewidgets + +SOURCES += main.cpp + +target.path = $$[QT_INSTALL_EXAMPLES]/webenginewidgets/minimal +INSTALLS += target diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro deleted file mode 100644 index edf95846c..000000000 --- a/tests/manual/manual.pro +++ /dev/null @@ -1,7 +0,0 @@ -TEMPLATE = subdirs - -SUBDIRS += \ - widgets \ - quick - -!qtHaveModule(webenginewidgets): SUBDIRS -= widgets 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 Binary files differindex a9dc1bc29..0832dfbed 100644 --- a/tests/manual/quick/pdf/test.pdf +++ b/tests/manual/quick/pdf/test.pdf 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/resources.qrc b/tests/manual/quick/touchbrowser/resources.qrc new file mode 100644 index 000000000..87d655a27 --- /dev/null +++ b/tests/manual/quick/touchbrowser/resources.qrc @@ -0,0 +1,7 @@ +<RCC> + <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 diff --git a/tests/manual/touchmocking/touchmockingapplication.cpp b/tests/manual/touchmocking/touchmockingapplication.cpp new file mode 100644 index 000000000..feedae5cd --- /dev/null +++ b/tests/manual/touchmocking/touchmockingapplication.cpp @@ -0,0 +1,78 @@ +// 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 + +#include "touchmockingapplication.h" + +#include <QCursor> +#include <QEvent> +#include <QPixmap> + +#if defined(QUICK_TOUCHBROWSER) +# include <QQuickView> +#endif + +#if defined(WIDGET_TOUCHBROWSER) +# include <QMainWindow> +#endif + +static inline bool isMouseEvent(QEvent *event) +{ + switch (event->type()) { + case QEvent::MouseMove: + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + return true; + default: + return false; + } +} + +TouchMockingApplication::TouchMockingApplication(int &argc, char **argv) + : Application(argc, argv), m_touchPoint(new QCursor(QPixmap(":touchpoint.png"))) +{ +} + +TouchMockingApplication::~TouchMockingApplication() +{ + delete m_touchPoint; +} + +bool TouchMockingApplication::notify(QObject *target, QEvent *event) +{ + switch (event->type()) { + case QEvent::TouchBegin: + setOverrideCursor(*m_touchPoint); + break; + case QEvent::TouchEnd: + restoreCursor(); + break; + default: + break; + } + +// All mouse events that are not accepted by the application will be translated to touch events +// instead (see Qt::AA_SynthesizeTouchForUnhandledMouseEvents). +#if defined(QUICK_TOUCHBROWSER) + if (isMouseEvent(event) && qobject_cast<QQuickView *>(target)) { + event->ignore(); + return false; + } +#elif defined(WIDGET_TOUCHBROWSER) + // Popups ignore touch evenets so we send MouseEvents directly. + if (isMouseEvent(event)) { + if (activePopupWidget()) { + restoreCursor(); + } else { + event->ignore(); + return false; + } + } +#endif + return Application::notify(target, event); +} + +void TouchMockingApplication::restoreCursor() +{ + while (overrideCursor()) + restoreOverrideCursor(); +} diff --git a/tests/manual/touchmocking/touchmockingapplication.h b/tests/manual/touchmocking/touchmockingapplication.h new file mode 100644 index 000000000..4f6e744fc --- /dev/null +++ b/tests/manual/touchmocking/touchmockingapplication.h @@ -0,0 +1,35 @@ +// 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 + +#ifndef TOUCHMOCKINGAPPLICATION_H +#define TOUCHMOCKINGAPPLICATION_H + +#if defined(QUICK_TOUCHBROWSER) +# include <QGuiApplication> +using Application = QGuiApplication; +#elif defined(WIDGET_TOUCHBROWSER) +# include <QApplication> +using Application = QApplication; +#endif + +QT_BEGIN_NAMESPACE +class QCursor; +QT_END_NAMESPACE + +class TouchMockingApplication : public Application +{ + Q_OBJECT + +public: + TouchMockingApplication(int &argc, char **argv); + ~TouchMockingApplication(); + + virtual bool notify(QObject *, QEvent *) override; + +private: + void restoreCursor(); + + QCursor *m_touchPoint; +}; + +#endif // TOUCHMOCKINGAPPLICATION_H diff --git a/tests/manual/touchmocking/touchpoint.png b/tests/manual/touchmocking/touchpoint.png Binary files differnew file mode 100644 index 000000000..7649ee991 --- /dev/null +++ b/tests/manual/touchmocking/touchpoint.png diff --git a/tests/manual/touchmocking/utils.h b/tests/manual/touchmocking/utils.h new file mode 100644 index 000000000..12d493d3f --- /dev/null +++ b/tests/manual/touchmocking/utils.h @@ -0,0 +1,25 @@ +// 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 + +#ifndef UTILS_H +#define UTILS_H + +#include <QFileInfo> +#include <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 diff --git a/tests/manual/widgets/CMakeLists.txt b/tests/manual/widgets/CMakeLists.txt new file mode 100644 index 000000000..7c19f9e43 --- /dev/null +++ b/tests/manual/widgets/CMakeLists.txt @@ -0,0 +1,9 @@ +add_subdirectory(inputmethods) +add_subdirectory(geolocation) +add_subdirectory(touchbrowser) +if(QT_FEATURE_opengl) + add_subdirectory(webgl) +endif() +if(TARGET Qt6::HttpServer) + add_subdirectory(webrtc) +endif() diff --git a/tests/manual/widgets/geolocation/CMakeLists.txt b/tests/manual/widgets/geolocation/CMakeLists.txt new file mode 100644 index 000000000..2ca8c2f52 --- /dev/null +++ b/tests/manual/widgets/geolocation/CMakeLists.txt @@ -0,0 +1,55 @@ +# 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(geolocation LANGUAGES CXX) + find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_manual_test(geolocation + GUI + SOURCES + main.cpp + LIBRARIES + Qt::Core + Qt::Gui + Qt::Test + Qt::WebEngineWidgets + ENABLE_AUTOGEN_TOOLS + moc +) + +set_target_properties(geolocation PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE + MACOSX_BUNDLE_GUI_IDENTIFIER "io.qt.dev.webenginewidgets.geolocation" +) + +set(geolocation_resource_files + "geolocation.html" +) + +qt_add_resources(geolocation "geolocation" + PREFIX + "/" + FILES + ${geolocation_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(geolocation INCLUDE ${permission_plugin}) + endforeach() + +if (APPLE) + set_target_properties(geolocation 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 geolocation + POST_BUILD COMMAND codesign -s - geolocation.app) + endif() +endif() diff --git a/tests/manual/widgets/geolocation/Info.plist b/tests/manual/widgets/geolocation/Info.plist new file mode 100644 index 000000000..9853e1900 --- /dev/null +++ b/tests/manual/widgets/geolocation/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/widgets/geolocation/geolocation.html b/tests/manual/widgets/geolocation/geolocation.html new file mode 100644 index 000000000..e8c54bc58 --- /dev/null +++ b/tests/manual/widgets/geolocation/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/widgets/geolocation/main.cpp b/tests/manual/widgets/geolocation/main.cpp new file mode 100644 index 000000000..f33cf5798 --- /dev/null +++ b/tests/manual/widgets/geolocation/main.cpp @@ -0,0 +1,51 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include <QApplication> +#include <QFormLayout> +#include <QGroupBox> +#include <QHBoxLayout> +#include <QLabel> +#include <QMainWindow> +#include <QMessageBox> +#include <QVBoxLayout> +#include <QWebEnginePage> +#include <QWebEngineView> + +class GeoPermissionWebView : public QWebEngineView { + Q_OBJECT + +public slots: + void handleFeaturePermissionRequested(const QUrl &securityOrigin, + QWebEnginePage::Feature feature) + { + qWarning("Feature Permission"); + QString title = tr("Permission Request"); + QString question = QLatin1String("Allow access to geolocation?"); + if (!question.isEmpty() && QMessageBox::question(window(), title, question) == QMessageBox::Yes) + page()->setFeaturePermission(securityOrigin, feature, + QWebEnginePage::PermissionGrantedByUser); + else + page()->setFeaturePermission(securityOrigin, feature, + QWebEnginePage::PermissionDeniedByUser); + } + +}; + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + QMainWindow w; + GeoPermissionWebView webview; + QWebEnginePage page; + QObject::connect(&page, &QWebEnginePage::featurePermissionRequested, &webview, + &GeoPermissionWebView::handleFeaturePermissionRequested); + webview.setPage(&page); + page.load(QUrl("qrc:/geolocation.html")); + w.setCentralWidget(&webview); + w.show(); + + return a.exec(); +} + +#include "main.moc" diff --git a/tests/manual/widgets/inputmethods/CMakeLists.txt b/tests/manual/widgets/inputmethods/CMakeLists.txt new file mode 100644 index 000000000..acd5bca50 --- /dev/null +++ b/tests/manual/widgets/inputmethods/CMakeLists.txt @@ -0,0 +1,37 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(inputmethods LANGUAGES CXX) + find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_manual_test(inputmethods + GUI + SOURCES + colorpicker.cpp + controlview.cpp + main.cpp + referenceview.cpp + testview.cpp + webview.cpp + LIBRARIES + Qt::Core + Qt::Gui + Qt::Test + Qt::WebEngineWidgets + ENABLE_AUTOGEN_TOOLS + moc +) + +set(inputmethods_resource_files + "testdata.csv" +) + +qt_add_resources(inputmethods "inputmethods" + PREFIX + "/" + FILES + ${inputmethods_resource_files} +) diff --git a/tests/manual/widgets/inputmethods/colorpicker.cpp b/tests/manual/widgets/inputmethods/colorpicker.cpp index ee2e2e43f..cc0840bcd 100644 --- a/tests/manual/widgets/inputmethods/colorpicker.cpp +++ b/tests/manual/widgets/inputmethods/colorpicker.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "colorpicker.h" diff --git a/tests/manual/widgets/inputmethods/colorpicker.h b/tests/manual/widgets/inputmethods/colorpicker.h index f5448ad2d..0b6b3257a 100644 --- a/tests/manual/widgets/inputmethods/colorpicker.h +++ b/tests/manual/widgets/inputmethods/colorpicker.h @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #ifndef COLORPICKER_H #define COLORPICKER_H @@ -32,8 +7,10 @@ #include <QColor> #include <QWidget> +QT_BEGIN_NAMESPACE class QLineEdit; class QPushButton; +QT_END_NAMESPACE class ColorPicker : public QWidget { diff --git a/tests/manual/widgets/inputmethods/controlview.cpp b/tests/manual/widgets/inputmethods/controlview.cpp index 4538ced4b..86bf8cca9 100644 --- a/tests/manual/widgets/inputmethods/controlview.cpp +++ b/tests/manual/widgets/inputmethods/controlview.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "controlview.h" @@ -69,7 +44,7 @@ ControlView::ControlView(QWidget *parent) layout->addRow(m_sendEventButton); setLayout(layout); - connect(m_sendEventButton, &QPushButton::clicked, this, &ControlView::createAndSendInputMethodEvent); + connect(m_sendEventButton, &QPushButton::clicked, this, &ControlView::requestInputMethodEvent); } void ControlView::receiveInputMethodData(int start, @@ -87,7 +62,12 @@ void ControlView::receiveInputMethodData(int start, m_inputLine->setText(input); } -void ControlView::createAndSendInputMethodEvent() +const QString ControlView::getText() const +{ + return m_inputLine->text(); +} + +const QList<QInputMethodEvent::Attribute> ControlView::getAtrributes() const { int start = m_startSpin->value(); int length = m_lengthSpin->value(); @@ -102,7 +82,6 @@ void ControlView::createAndSendInputMethodEvent() QList<QInputMethodEvent::Attribute> attrs; attrs.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, start, length, format)); - QInputMethodEvent im(m_inputLine->text(), attrs); - emit sendInputMethodEvent(im); + return attrs; } diff --git a/tests/manual/widgets/inputmethods/controlview.h b/tests/manual/widgets/inputmethods/controlview.h index 0ef10f6a8..caa08593f 100644 --- a/tests/manual/widgets/inputmethods/controlview.h +++ b/tests/manual/widgets/inputmethods/controlview.h @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #ifndef CONTROLVIEW_H #define CONTROLVIEW_H @@ -33,12 +8,15 @@ #include <QTextCharFormat> #include <QWidget> -class ColorPicker; +QT_BEGIN_NAMESPACE class QComboBox; class QLabel; class QLineEdit; class QPushButton; class QSpinBox; +QT_END_NAMESPACE + +class ColorPicker; class ControlView : public QWidget { @@ -46,12 +24,13 @@ class ControlView : public QWidget public: explicit ControlView(QWidget *parent = 0); + const QString getText() const; + const QList<QInputMethodEvent::Attribute> getAtrributes() const; + public slots: void receiveInputMethodData(int, int, QTextCharFormat::UnderlineStyle, const QColor &, const QColor &, const QString &); - void createAndSendInputMethodEvent(); - signals: - void sendInputMethodEvent(QInputMethodEvent); + void requestInputMethodEvent(); private: QComboBox *m_underlineStyleCombo; diff --git a/tests/manual/widgets/inputmethods/main.cpp b/tests/manual/widgets/inputmethods/main.cpp index a96deb83a..2378e95ae 100644 --- a/tests/manual/widgets/inputmethods/main.cpp +++ b/tests/manual/widgets/inputmethods/main.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include <QApplication> #include <QFormLayout> @@ -49,7 +24,12 @@ class MainWindow : public QMainWindow public: explicit MainWindow(QWidget *parent = 0); +private slots: + void sendInputMethodEvents(); + private: + void closeEvent(QCloseEvent *event) override; + ControlView *m_controlView; ReferenceView *m_referenceView; WebView *m_webView; @@ -109,29 +89,44 @@ MainWindow::MainWindow(QWidget *parent) centralLayout->addLayout(leftLayout); centralLayout->addWidget(m_testView); - connect(m_testView, &TestView::sendInputMethodData, m_controlView, &ControlView::receiveInputMethodData); - connect(m_testView, &TestView::requestInputMethodEvent, m_controlView, &ControlView::createAndSendInputMethodEvent); - - connect(m_controlView, &ControlView::sendInputMethodEvent, [=](QInputMethodEvent im) { - bool processed; - QString resultText; - - processed = QApplication::sendEvent(m_referenceView->referenceInput(), &im); - resultText = processed ? QStringLiteral("<font color='green'>TRUE</font>") - : QStringLiteral("<font color='red'>FALSE</font>"); - m_referenceProcessed->setText(resultText); - - processed = QApplication::sendEvent(m_webView->focusProxy(), &im); - resultText = processed ? QStringLiteral("<font color='green'>TRUE</font>") - : QStringLiteral("<font color='red'>FALSE</font>"); - m_webProcessed->setText(resultText); - }); + connect(m_testView, &TestView::sendInputMethodData, m_controlView, + &ControlView::receiveInputMethodData); + connect(m_testView, &TestView::requestInputMethodEvent, this, + &MainWindow::sendInputMethodEvents); + connect(m_controlView, &ControlView::requestInputMethodEvent, this, + &MainWindow::sendInputMethodEvents); centralWidget->setLayout(centralLayout); setCentralWidget(centralWidget); setWindowTitle(tr("Input Methods Format Manual Test")); } +void MainWindow::sendInputMethodEvents() +{ + bool processed; + QString resultText; + + QString text = m_controlView->getText(); + QList<QInputMethodEvent::Attribute> attrs = m_controlView->getAtrributes(); + QInputMethodEvent im(text, attrs); + + processed = QApplication::sendEvent(m_referenceView->referenceInput(), &im); + resultText = processed ? QStringLiteral("<font color='green'>TRUE</font>") + : QStringLiteral("<font color='red'>FALSE</font>"); + m_referenceProcessed->setText(resultText); + + processed = QApplication::sendEvent(m_webView->focusProxy(), &im); + resultText = processed ? QStringLiteral("<font color='green'>TRUE</font>") + : QStringLiteral("<font color='red'>FALSE</font>"); + m_webProcessed->setText(resultText); +} + +void MainWindow::closeEvent(QCloseEvent *event) +{ + m_testView->cancelTest(); + QMainWindow::closeEvent(event); +} + int main(int argc, char *argv[]) { QApplication a(argc, argv); diff --git a/tests/manual/widgets/inputmethods/referenceview.cpp b/tests/manual/widgets/inputmethods/referenceview.cpp index 906a3001e..27e784fbc 100644 --- a/tests/manual/widgets/inputmethods/referenceview.cpp +++ b/tests/manual/widgets/inputmethods/referenceview.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "referenceview.h" diff --git a/tests/manual/widgets/inputmethods/referenceview.h b/tests/manual/widgets/inputmethods/referenceview.h index 4025d4886..d943a93d0 100644 --- a/tests/manual/widgets/inputmethods/referenceview.h +++ b/tests/manual/widgets/inputmethods/referenceview.h @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #ifndef REFERENCEVIEW_H #define REFERENCEVIEW_H diff --git a/tests/manual/widgets/inputmethods/testview.cpp b/tests/manual/widgets/inputmethods/testview.cpp index 14e355caf..d57b22cc5 100644 --- a/tests/manual/widgets/inputmethods/testview.cpp +++ b/tests/manual/widgets/inputmethods/testview.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "testview.h" @@ -94,11 +69,19 @@ void TestView::loadTestData(const QString &testDataPath) testDataFile.close(); } +void TestView::cancelTest() +{ + if (!m_testRunning) + return; + + m_testRunning = false; + m_testButton->setText(tr("Start Test")); +} + void TestView::startOrCancelTest() { if (m_testRunning) { - m_testRunning = false; - m_testButton->setText(tr("Start Test")); + cancelTest(); return; } @@ -120,10 +103,7 @@ void TestView::startOrCancelTest() QTest::qWait(1000); } - if (m_testRunning) { - m_testRunning = false; - m_testButton->setText(tr("Start Test")); - } + cancelTest(); } void TestView::collectAndSendData() diff --git a/tests/manual/widgets/inputmethods/testview.h b/tests/manual/widgets/inputmethods/testview.h index 4934a5f87..b99e60d75 100644 --- a/tests/manual/widgets/inputmethods/testview.h +++ b/tests/manual/widgets/inputmethods/testview.h @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #ifndef TESTVIEW_H #define TESTVIEW_H @@ -32,8 +7,10 @@ #include <QTextCharFormat> #include <QWidget> +QT_BEGIN_NAMESPACE class QPushButton; class QTableView; +QT_END_NAMESPACE class TestView : public QWidget { @@ -41,6 +18,8 @@ class TestView : public QWidget public: explicit TestView(QWidget *parent = 0); + void cancelTest(); + public slots: void loadTestData(const QString &); void startOrCancelTest(); diff --git a/tests/manual/widgets/inputmethods/webview.cpp b/tests/manual/widgets/inputmethods/webview.cpp index 62e210ecf..915d73a7f 100644 --- a/tests/manual/widgets/inputmethods/webview.cpp +++ b/tests/manual/widgets/inputmethods/webview.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "webview.h" #include <QWebEngineSettings> diff --git a/tests/manual/widgets/inputmethods/webview.h b/tests/manual/widgets/inputmethods/webview.h index be57fbf29..a46dcb2f6 100644 --- a/tests/manual/widgets/inputmethods/webview.h +++ b/tests/manual/widgets/inputmethods/webview.h @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #ifndef WEBVIEW_H #define WEBVIEW_H diff --git a/tests/manual/widgets/touchbrowser/CMakeLists.txt b/tests/manual/widgets/touchbrowser/CMakeLists.txt new file mode 100644 index 000000000..de60ad2b4 --- /dev/null +++ b/tests/manual/widgets/touchbrowser/CMakeLists.txt @@ -0,0 +1,30 @@ +# 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(-DWIDGET_TOUCHBROWSER) + +qt_internal_add_manual_test(touchbrowser-widget + GUI + SOURCES + main.cpp + resources.qrc + ${TOUCHMOCKING_DIR}/touchmockingapplication.cpp + ${TOUCHMOCKING_DIR}/touchmockingapplication.h + ${TOUCHMOCKING_DIR}/utils.h + LIBRARIES + Qt::Core + Qt::Gui + Qt::WebEngineWidgets + ENABLE_AUTOGEN_TOOLS + moc +) diff --git a/tests/manual/widgets/touchbrowser/main.cpp b/tests/manual/widgets/touchbrowser/main.cpp new file mode 100644 index 000000000..18baf79e8 --- /dev/null +++ b/tests/manual/widgets/touchbrowser/main.cpp @@ -0,0 +1,62 @@ +// 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 + +#include "touchmockingapplication.h" +#include "utils.h" + +#include <QApplication> +#include <QLineEdit> +#include <QMainWindow> +#include <QToolBar> +#include <QWebEngineView> + + +static QUrl startupUrl() +{ + QUrl ret; + QStringList args(qApp->arguments()); + args.takeFirst(); + for (const QString &arg : std::as_const(args)) { + if (arg.startsWith(QLatin1Char('-'))) + continue; + ret = Utils::fromUserInput(arg); + if (ret.isValid()) + return ret; + } + return QUrl(QStringLiteral("https://www.qt.io/")); +} + +int main(int argc, char **argv) +{ + TouchMockingApplication app(argc, argv); + app.setAttribute(Qt::AA_SynthesizeTouchForUnhandledMouseEvents, true); + + QMainWindow window; + QWebEngineView view(&window); + QToolBar addressBar("AddressBar", &window); + QLineEdit lineEdit(&addressBar); + + view.setAttribute(Qt::WA_AcceptTouchEvents, true); + view.setUrl(startupUrl()); + window.resize(1024, 750); + window.setCentralWidget(&view); + + addressBar.setAttribute(Qt::WA_AcceptTouchEvents, true); + addressBar.setMovable(false); + addressBar.toggleViewAction()->setEnabled(false); + + lineEdit.setAttribute(Qt::WA_AcceptTouchEvents, true); + lineEdit.setClearButtonEnabled(true); + + addressBar.addWidget(&lineEdit); + QObject::connect(&lineEdit, &QLineEdit::returnPressed, [&]() { + QUrl url = Utils::fromUserInput(lineEdit.text()); + lineEdit.setText(url.toDisplayString()); + view.setUrl(url); + }); + + window.addToolBar(&addressBar); + window.show(); + + return app.exec(); +} diff --git a/tests/manual/widgets/touchbrowser/resources.qrc b/tests/manual/widgets/touchbrowser/resources.qrc new file mode 100644 index 000000000..b621823ea --- /dev/null +++ b/tests/manual/widgets/touchbrowser/resources.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file alias="touchpoint.png">../../touchmocking/touchpoint.png</file> + </qresource> +</RCC> diff --git a/tests/manual/widgets/touchbrowser/touchbrowser.pro b/tests/manual/widgets/touchbrowser/touchbrowser.pro new file mode 100644 index 000000000..1587f390a --- /dev/null +++ b/tests/manual/widgets/touchbrowser/touchbrowser.pro @@ -0,0 +1,15 @@ +TEMPLATE = app + +DEFINES += WIDGET_TOUCHBROWSER +QT += core gui webenginewidgets + +INCLUDEPATH += ../../touchmocking + +SOURCES += \ + main.cpp \ + ../../touchmocking/touchmockingapplication.cpp +HEADERS += \ + ../../touchmocking/touchmockingapplication.h \ + ../../touchmocking/utils.h + +RESOURCES += resources.qrc diff --git a/tests/manual/widgets/webgl/CMakeLists.txt b/tests/manual/widgets/webgl/CMakeLists.txt new file mode 100644 index 000000000..034a06a79 --- /dev/null +++ b/tests/manual/widgets/webgl/CMakeLists.txt @@ -0,0 +1,20 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(webgl LANGUAGES CXX) + find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_manual_test(webgl + GUI + SOURCES + main.cpp + LIBRARIES + Qt::Core + Qt::Gui + Qt::WebEngineWidgets + ENABLE_AUTOGEN_TOOLS + moc +) diff --git a/tests/manual/widgets/webgl/main.cpp b/tests/manual/widgets/webgl/main.cpp index c18a15bac..7037c34db 100644 --- a/tests/manual/widgets/webgl/main.cpp +++ b/tests/manual/widgets/webgl/main.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** 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 #include <QtCore/QDebug> #include <QtCore/QLoggingCategory> diff --git a/tests/manual/widgets/webrtc/CMakeLists.txt b/tests/manual/widgets/webrtc/CMakeLists.txt new file mode 100644 index 000000000..3f98f1fd6 --- /dev/null +++ b/tests/manual/widgets/webrtc/CMakeLists.txt @@ -0,0 +1,24 @@ +# 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.19) + project(webrtc LANGUAGES CXX) + find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) +endif() + +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTORCC ON) + +qt_internal_add_manual_test(webrtc + GUI + SOURCES + main.cpp + mediaPicker.ui + qrc.qrc + LIBRARIES + Qt::Core + Qt::HttpServer + Qt::Gui + Qt::WebEngineWidgets +) diff --git a/tests/manual/widgets/webrtc/index.html b/tests/manual/widgets/webrtc/index.html new file mode 100644 index 000000000..433d643c3 --- /dev/null +++ b/tests/manual/widgets/webrtc/index.html @@ -0,0 +1,86 @@ +<!doctype html> +<html> + <head> + <style> + body { + display: flex; + justify-content: center; + align-items: center; + flex-wrap: wrap; + flex-flow: column; + } + buttons { + justify-content: space-around; + } + </style> + </head> + <body> + <div id="buttons" > + <input value ="getDisplayMedia" onclick="getDisplayMedia(true, true);" type="button"> + <input value = "chooseDesktopMedia" onclick="chooseDesktopMedia();" type="button"> + <input value ="Stop" onclick="stop();" type="button"> + </div> + <div id="content"></div> + </body> + <script> + const EXTENSION_ID = "nkeimhogjdpnpccoofpliimaahmaaome"; // hangout services extension + const content = document.getElementById("content"); + const video = document.createElement("video"); + video.setAttribute("width", 640); + video.setAttribute("height", 640); + video.setAttribute("style", "background-color: black;"); + content.appendChild(video); + + async function getDisplayMedia(v = true, a = true) { + stop(); + navigator.mediaDevices.getDisplayMedia({ video: v, audio: a }) + .then(stream => { + start(stream); + }, error => { + console.error(error); + }); + } + + function chooseDesktopMedia() { + stop(); + // Connect to the 'chooseDesktopMedia' listener within the hangout services extension. + let port = chrome.runtime.connect(EXTENSION_ID, {name: "chooseDesktopMedia"}) + + // The 'chooseDesktopMedia' api returns a streamId that + // identifies a media source in the constraints of 'getUserMedia' + // (see chromeMediaSourceId) + port.onMessage.addListener(result => { + navigator.mediaDevices.getUserMedia({ + video: { + mandatory: { + chromeMediaSource: "desktop", + chromeMediaSourceId: result.value.streamId + }, + } + }).then(stream => { + start(stream); + }, error => { + console.error(error); + }) + }) + + // Trigger the listener on the other side, + // we should see the picker dialog after this call. + port.postMessage({method: "chooseDesktopMedia"}) + } + + function stop() { + if (video.srcObject) + for (const track of video.srcObject.getTracks()) + track.stop() + video.srcObject = null; + video.setAttribute("style", "background-color: black;"); + } + + function start(stream) { + video.srcObject = stream; + video.play(); + } + + </script> +</html> diff --git a/tests/manual/widgets/webrtc/main.cpp b/tests/manual/widgets/webrtc/main.cpp new file mode 100644 index 000000000..328e4ae36 --- /dev/null +++ b/tests/manual/widgets/webrtc/main.cpp @@ -0,0 +1,112 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include <QApplication> +#include <QByteArray> +#include <QDialog> +#include <QFile> +#include <QHttpServer> +#include <QListView> +#include <QMessageBox> +#include <QWebEnginePage> +#include <QWebEngineProfile> +#include <QWebEngineSettings> +#include <QWebEngineView> + +#include "ui_mediaPicker.h" +#include <QWebEngineDesktopMediaRequest> + +// Test the screen/window selection and capturing APIs using QWebEngineDesktopMediaRequest, +// getDisplayMedia (js) and chooseDesktopMedia (hangouts) + +// Note: Wayland compositors require Pipewire support in QWE + +class Page : public QWebEnginePage +{ + Q_OBJECT + +public: + Page(QWebEngineProfile *profile, QObject *parent = nullptr); +private slots: + void handlePermissionRequest(const QUrl &origin, Feature feature); + void handleDesktopMediaRequest(const QWebEngineDesktopMediaRequest &request); +}; + +Page::Page(QWebEngineProfile *profile, QObject *parent) : QWebEnginePage(profile, parent) +{ + settings()->setAttribute(QWebEngineSettings::ScreenCaptureEnabled, true); + connect(this, &QWebEnginePage::featurePermissionRequested, this, + &Page::handlePermissionRequest); + connect(this, &QWebEnginePage::desktopMediaRequested, this, &Page::handleDesktopMediaRequest); +} + +void Page::handlePermissionRequest(const QUrl &origin, Feature feature) +{ + if (QMessageBox::question(QApplication::activeWindow(), tr("Permission request"), + tr("allow access?")) + == QMessageBox::Yes) + setFeaturePermission(origin, feature, PermissionGrantedByUser); + else + setFeaturePermission(origin, feature, PermissionDeniedByUser); +} + +void Page::handleDesktopMediaRequest(const QWebEngineDesktopMediaRequest &request) +{ + Ui::MediaPickerDialog mediaPickerDialog; + QDialog dialog; + dialog.setModal(true); + mediaPickerDialog.setupUi(&dialog); + + auto *screensView = mediaPickerDialog.screensView; + auto *windowsView = mediaPickerDialog.windowsView; + auto *screensModel = request.screensModel(); + auto *windowsModel = request.windowsModel(); + + screensView->setModel(screensModel); + windowsView->setModel(windowsModel); + + if (dialog.exec() == QDialog::Accepted) { + if (mediaPickerDialog.tabWidget->currentIndex() == 0) + request.selectWindow(windowsView->selectionModel()->selectedIndexes().first()); + else + request.selectScreen(screensView->selectionModel()->selectedIndexes().first()); + } else { + request.cancel(); + } +} + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + QHttpServer server; + + QFile file(":index.html"); + + if (!file.open(QIODeviceBase::ReadOnly)) { + qWarning("failed to open file!"); + return 0; + } + + QByteArray data = file.readAll(); + if (data.isEmpty()) { + qWarning("failed to read file!"); + return 0; + } + + server.route("/index.html", [data]() { + return data; + }); + + server.listen(QHostAddress::Any, 3000); + + QWebEngineView view; + Page *page = new Page(QWebEngineProfile::defaultProfile(), &view); + view.setPage(page); + view.resize(1024, 750); + view.setUrl(QUrl("http://localhost:3000/index.html")); + view.show(); + return app.exec(); +} + +#include "main.moc" diff --git a/tests/manual/widgets/webrtc/mediaPicker.ui b/tests/manual/widgets/webrtc/mediaPicker.ui new file mode 100644 index 000000000..8bfab3f9b --- /dev/null +++ b/tests/manual/widgets/webrtc/mediaPicker.ui @@ -0,0 +1,118 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MediaPickerDialog</class> + <widget class="QDialog" name="MediaPickerDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>500</width> + <height>400</height> + </rect> + </property> + <property name="windowTitle"> + <string>Choose what to share</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QTabWidget" name="tabWidget"> + <property name="styleSheet"> + <string notr="true"/> + </property> + <property name="currentIndex"> + <number>0</number> + </property> + <widget class="QWidget" name="windows"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="contextMenuPolicy"> + <enum>Qt::NoContextMenu</enum> + </property> + <property name="styleSheet"> + <string notr="true"/> + </property> + <attribute name="title"> + <string>Windows</string> + </attribute> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QListView" name="windowsView"/> + </item> + </layout> + </widget> + <widget class="QWidget" name="screens"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="contextMenuPolicy"> + <enum>Qt::NoContextMenu</enum> + </property> + <attribute name="title"> + <string>Screens</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <widget class="QListView" name="screensView"/> + </item> + </layout> + </widget> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>MediaPickerDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>MediaPickerDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/tests/manual/widgets/webrtc/qrc.qrc b/tests/manual/widgets/webrtc/qrc.qrc new file mode 100644 index 000000000..c3322b454 --- /dev/null +++ b/tests/manual/widgets/webrtc/qrc.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>index.html</file> + </qresource> +</RCC> diff --git a/tests/manual/widgets/widgets.pro b/tests/manual/widgets/widgets.pro deleted file mode 100644 index 34e88f0e3..000000000 --- a/tests/manual/widgets/widgets.pro +++ /dev/null @@ -1,5 +0,0 @@ -TEMPLATE= subdirs - -SUBDIRS += \ - inputmethods \ - webgl |