summaryrefslogtreecommitdiffstats
path: root/examples/webenginequick/quicknanobrowser
diff options
context:
space:
mode:
authorBalazs Egedi <egedib@inf.u-szeged.hu>2021-08-17 12:59:28 +0200
committerBalazs Egedi <egedib@inf.u-szeged.hu>2021-09-13 10:25:48 +0200
commita32ef7057c01fbcadcf451e7f2b785f7b3dd3942 (patch)
tree15258c16f6369ad9f3318101102d7da1b3002927 /examples/webenginequick/quicknanobrowser
parent498c4ac362cb6cbee8a30c8cc46fa4253bf93ee0 (diff)
Rename Quick examples' folder from webengine to webenginequick
Fix webengine directory path in project files and comments Pick-to: 6.2 6.2.0 Change-Id: I06ed9ee41111e7135fa9feb152ad2a5eb2262b76 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'examples/webenginequick/quicknanobrowser')
-rw-r--r--examples/webenginequick/quicknanobrowser/ApplicationRoot.qml87
-rw-r--r--examples/webenginequick/quicknanobrowser/BrowserDialog.qml74
-rw-r--r--examples/webenginequick/quicknanobrowser/BrowserWindow.qml801
-rw-r--r--examples/webenginequick/quicknanobrowser/CMakeLists.txt81
-rw-r--r--examples/webenginequick/quicknanobrowser/DownloadView.qml174
-rw-r--r--examples/webenginequick/quicknanobrowser/FindBar.qml142
-rw-r--r--examples/webenginequick/quicknanobrowser/FullScreenNotification.qml109
-rw-r--r--examples/webenginequick/quicknanobrowser/doc/images/quicknanobrowser-demo.jpgbin0 -> 30156 bytes
-rw-r--r--examples/webenginequick/quicknanobrowser/doc/src/quicknanobrowser.qdoc153
-rw-r--r--examples/webenginequick/quicknanobrowser/icons/3rdparty/COPYING1
-rw-r--r--examples/webenginequick/quicknanobrowser/icons/3rdparty/go-next.pngbin0 -> 930 bytes
-rw-r--r--examples/webenginequick/quicknanobrowser/icons/3rdparty/go-previous.pngbin0 -> 955 bytes
-rw-r--r--examples/webenginequick/quicknanobrowser/icons/3rdparty/process-stop.pngbin0 -> 1272 bytes
-rw-r--r--examples/webenginequick/quicknanobrowser/icons/3rdparty/qt_attribution.json24
-rw-r--r--examples/webenginequick/quicknanobrowser/icons/3rdparty/view-refresh.pngbin0 -> 1364 bytes
-rw-r--r--examples/webenginequick/quicknanobrowser/main.cpp96
-rw-r--r--examples/webenginequick/quicknanobrowser/quicknanobrowser.pro25
-rw-r--r--examples/webenginequick/quicknanobrowser/resources.qrc16
-rw-r--r--examples/webenginequick/quicknanobrowser/utils.h70
19 files changed, 1853 insertions, 0 deletions
diff --git a/examples/webenginequick/quicknanobrowser/ApplicationRoot.qml b/examples/webenginequick/quicknanobrowser/ApplicationRoot.qml
new file mode 100644
index 000000000..cd40a7fdb
--- /dev/null
+++ b/examples/webenginequick/quicknanobrowser/ApplicationRoot.qml
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** 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: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
+import QtWebEngine
+
+QtObject {
+ id: root
+
+ property QtObject defaultProfile: WebEngineProfile {
+ storageName: "Profile"
+ offTheRecord: false
+ }
+
+ property QtObject otrProfile: WebEngineProfile {
+ offTheRecord: true
+ }
+
+ property Component browserWindowComponent: BrowserWindow {
+ applicationRoot: root
+ }
+ property Component browserDialogComponent: BrowserDialog {
+ onClosing: destroy()
+ }
+ function createWindow(profile) {
+ var newWindow = browserWindowComponent.createObject(root);
+ newWindow.currentWebView.profile = profile;
+ profile.downloadRequested.connect(newWindow.onDownloadRequested);
+ return newWindow;
+ }
+ function createDialog(profile) {
+ var newDialog = browserDialogComponent.createObject(root);
+ newDialog.currentWebView.profile = profile;
+ return newDialog;
+ }
+ function load(url) {
+ var browserWindow = createWindow(defaultProfile);
+ browserWindow.currentWebView.url = url;
+ }
+}
diff --git a/examples/webenginequick/quicknanobrowser/BrowserDialog.qml b/examples/webenginequick/quicknanobrowser/BrowserDialog.qml
new file mode 100644
index 000000000..281f44904
--- /dev/null
+++ b/examples/webenginequick/quicknanobrowser/BrowserDialog.qml
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** 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: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
+import QtQuick.Window
+import QtWebEngine
+
+Window {
+ id: window
+ property alias currentWebView: webView
+ flags: Qt.Dialog | Qt.WindowStaysOnTopHint
+ width: 800
+ height: 600
+ visible: true
+ onClosing: destroy()
+ WebEngineView {
+ id: webView
+ anchors.fill: parent
+
+ onGeometryChangeRequested: function(geometry) {
+ window.x = geometry.x
+ window.y = geometry.y
+ window.width = geometry.width
+ window.height = geometry.height
+ }
+ }
+}
diff --git a/examples/webenginequick/quicknanobrowser/BrowserWindow.qml b/examples/webenginequick/quicknanobrowser/BrowserWindow.qml
new file mode 100644
index 000000000..0da1bc043
--- /dev/null
+++ b/examples/webenginequick/quicknanobrowser/BrowserWindow.qml
@@ -0,0 +1,801 @@
+/****************************************************************************
+**
+** 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: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 Qt.labs.settings
+import QtQml
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import QtQuick.Window
+import QtWebEngine
+
+ApplicationWindow {
+ id: browserWindow
+ property QtObject applicationRoot
+ property Item currentWebView: tabBar.currentIndex < tabBar.count ? tabLayout.children[tabBar.currentIndex] : null
+ property int previousVisibility: Window.Windowed
+ property int createdTabs: 0
+
+ width: 1300
+ height: 900
+ visible: true
+ title: currentWebView && currentWebView.title
+
+ // Make sure the Qt.WindowFullscreenButtonHint is set on OS X.
+ Component.onCompleted: flags = flags | Qt.WindowFullscreenButtonHint
+
+ onCurrentWebViewChanged: {
+ findBar.reset();
+ }
+
+ // When using style "mac", ToolButtons are not supposed to accept focus.
+ property bool platformIsMac: Qt.platform.os == "osx"
+
+ Settings {
+ id : appSettings
+ property alias autoLoadImages: loadImages.checked
+ property alias javaScriptEnabled: javaScriptEnabled.checked
+ property alias errorPageEnabled: errorPageEnabled.checked
+ property alias pluginsEnabled: pluginsEnabled.checked
+ property alias fullScreenSupportEnabled: fullScreenSupportEnabled.checked
+ property alias autoLoadIconsForPage: autoLoadIconsForPage.checked
+ property alias touchIconsEnabled: touchIconsEnabled.checked
+ property alias webRTCPublicInterfacesOnly : webRTCPublicInterfacesOnly.checked
+ property alias devToolsEnabled: devToolsEnabled.checked
+ property alias pdfViewerEnabled: pdfViewerEnabled.checked
+ }
+
+ Action {
+ shortcut: "Ctrl+D"
+ onTriggered: {
+ downloadView.visible = !downloadView.visible;
+ }
+ }
+ Action {
+ id: focus
+ shortcut: "Ctrl+L"
+ onTriggered: {
+ addressBar.forceActiveFocus();
+ addressBar.selectAll();
+ }
+ }
+ Action {
+ shortcut: StandardKey.Refresh
+ onTriggered: {
+ if (currentWebView)
+ currentWebView.reload();
+ }
+ }
+ Action {
+ shortcut: StandardKey.AddTab
+ onTriggered: {
+ tabBar.createTab(tabBar.count != 0 ? currentWebView.profile : defaultProfile);
+ addressBar.forceActiveFocus();
+ addressBar.selectAll();
+ }
+ }
+ Action {
+ shortcut: StandardKey.Close
+ onTriggered: {
+ currentWebView.triggerWebAction(WebEngineView.RequestClose);
+ }
+ }
+ Action {
+ shortcut: StandardKey.Quit
+ onTriggered: browserWindow.close()
+ }
+ Action {
+ shortcut: "Escape"
+ onTriggered: {
+ if (currentWebView.state == "FullScreen") {
+ browserWindow.visibility = browserWindow.previousVisibility;
+ fullScreenNotification.hide();
+ currentWebView.triggerWebAction(WebEngineView.ExitFullScreen);
+ }
+
+ if (findBar.visible)
+ findBar.visible = false;
+ }
+ }
+ Action {
+ shortcut: "Ctrl+0"
+ onTriggered: currentWebView.zoomFactor = 1.0
+ }
+ Action {
+ shortcut: StandardKey.ZoomOut
+ onTriggered: currentWebView.zoomFactor -= 0.1
+ }
+ Action {
+ shortcut: StandardKey.ZoomIn
+ onTriggered: currentWebView.zoomFactor += 0.1
+ }
+
+ Action {
+ shortcut: StandardKey.Copy
+ onTriggered: currentWebView.triggerWebAction(WebEngineView.Copy)
+ }
+ Action {
+ shortcut: StandardKey.Cut
+ onTriggered: currentWebView.triggerWebAction(WebEngineView.Cut)
+ }
+ Action {
+ shortcut: StandardKey.Paste
+ onTriggered: currentWebView.triggerWebAction(WebEngineView.Paste)
+ }
+ Action {
+ shortcut: "Shift+"+StandardKey.Paste
+ onTriggered: currentWebView.triggerWebAction(WebEngineView.PasteAndMatchStyle)
+ }
+ Action {
+ shortcut: StandardKey.SelectAll
+ onTriggered: currentWebView.triggerWebAction(WebEngineView.SelectAll)
+ }
+ Action {
+ shortcut: StandardKey.Undo
+ onTriggered: currentWebView.triggerWebAction(WebEngineView.Undo)
+ }
+ Action {
+ shortcut: StandardKey.Redo
+ onTriggered: currentWebView.triggerWebAction(WebEngineView.Redo)
+ }
+ Action {
+ shortcut: StandardKey.Back
+ onTriggered: currentWebView.triggerWebAction(WebEngineView.Back)
+ }
+ Action {
+ shortcut: StandardKey.Forward
+ onTriggered: currentWebView.triggerWebAction(WebEngineView.Forward)
+ }
+ Action {
+ shortcut: StandardKey.Find
+ onTriggered: {
+ if (!findBar.visible)
+ findBar.visible = true;
+ }
+ }
+ Action {
+ shortcut: StandardKey.FindNext
+ onTriggered: findBar.findNext()
+ }
+ Action {
+ shortcut: StandardKey.FindPrevious
+ onTriggered: findBar.findPrevious()
+ }
+
+ menuBar: ToolBar {
+ id: navigationBar
+ RowLayout {
+ anchors.fill: parent
+ ToolButton {
+ enabled: currentWebView && (currentWebView.canGoBack || currentWebView.canGoForward)
+ onClicked: historyMenu.open()
+ text: qsTr("▼")
+ Menu {
+ id: historyMenu
+ Instantiator {
+ model: currentWebView && currentWebView.history.items
+ MenuItem {
+ text: model.title
+ onTriggered: currentWebView.goBackOrForward(model.offset)
+ checkable: !enabled
+ checked: !enabled
+ enabled: model.offset
+ }
+
+ onObjectAdded: function(index, object) {
+ historyMenu.insertItem(index, object)
+ }
+ onObjectRemoved: function(index, object) {
+ historyMenu.removeItem(object)
+ }
+ }
+ }
+ }
+
+ ToolButton {
+ id: backButton
+ icon.source: "qrc:/icons/go-previous.png"
+ onClicked: currentWebView.goBack()
+ enabled: currentWebView && currentWebView.canGoBack
+ activeFocusOnTab: !browserWindow.platformIsMac
+ }
+ ToolButton {
+ id: forwardButton
+ icon.source: "qrc:/icons/go-next.png"
+ onClicked: currentWebView.goForward()
+ enabled: currentWebView && currentWebView.canGoForward
+ activeFocusOnTab: !browserWindow.platformIsMac
+ }
+ ToolButton {
+ id: reloadButton
+ icon.source: currentWebView && currentWebView.loading ? "qrc:/icons/process-stop.png" : "qrc:/icons/view-refresh.png"
+ onClicked: currentWebView && currentWebView.loading ? currentWebView.stop() : currentWebView.reload()
+ activeFocusOnTab: !browserWindow.platformIsMac
+ }
+ TextField {
+ id: addressBar
+ Image {
+ anchors.verticalCenter: addressBar.verticalCenter;
+ x: 5
+ z: 2
+ id: faviconImage
+ width: 16; height: 16
+ sourceSize: Qt.size(width, height)
+ source: currentWebView && currentWebView.icon ? currentWebView.icon : ''
+ }
+ MouseArea {
+ id: textFieldMouseArea
+ acceptedButtons: Qt.RightButton
+ anchors.fill: parent
+ onClicked: {
+ var textSelectionStartPos = addressBar.selectionStart;
+ var textSelectionEndPos = addressBar.selectionEnd;
+ textFieldContextMenu.open();
+ addressBar.select(textSelectionStartPos, textSelectionEndPos);
+ }
+ Menu {
+ id: textFieldContextMenu
+ x: textFieldMouseArea.mouseX
+ y: textFieldMouseArea.mouseY
+ MenuItem {
+ text: qsTr("Cut")
+ onTriggered: addressBar.cut()
+ enabled: addressBar.selectedText.length > 0
+ }
+ MenuItem {
+ text: qsTr("Copy")
+ onTriggered: addressBar.copy()
+ enabled: addressBar.selectedText.length > 0
+ }
+ MenuItem {
+ text: qsTr("Paste")
+ onTriggered: addressBar.paste()
+ enabled: addressBar.canPaste
+ }
+ MenuItem {
+ text: qsTr("Delete")
+ onTriggered: addressBar.text = qsTr("")
+ enabled: addressBar.selectedText.length > 0
+ }
+ MenuSeparator {}
+ MenuItem {
+ text: qsTr("Select All")
+ onTriggered: addressBar.selectAll()
+ enabled: addressBar.text.length > 0
+ }
+ }
+ }
+ leftPadding: 26
+ focus: true
+ Layout.fillWidth: true
+ Binding on text {
+ when: currentWebView
+ value: currentWebView.url
+ }
+ onAccepted: currentWebView.url = utils.fromUserInput(text)
+ selectByMouse: true
+ }
+ ToolButton {
+ id: settingsMenuButton
+ text: qsTr("⋮")
+ onClicked: settingsMenu.open()
+ Menu {
+ id: settingsMenu
+ y: settingsMenuButton.height
+ MenuItem {
+ id: loadImages
+ text: "Autoload images"
+ checkable: true
+ checked: WebEngine.settings.autoLoadImages
+ }
+ MenuItem {
+ id: javaScriptEnabled
+ text: "JavaScript On"
+ checkable: true
+ checked: WebEngine.settings.javascriptEnabled
+ }
+ MenuItem {
+ id: errorPageEnabled
+ text: "ErrorPage On"
+ checkable: true
+ checked: WebEngine.settings.errorPageEnabled
+ }
+ MenuItem {
+ id: pluginsEnabled
+ text: "Plugins On"
+ checkable: true
+ checked: true
+ }
+ MenuItem {
+ id: fullScreenSupportEnabled
+ text: "FullScreen On"
+ checkable: true
+ checked: WebEngine.settings.fullScreenSupportEnabled
+ }
+ MenuItem {
+ id: offTheRecordEnabled
+ text: "Off The Record"
+ checkable: true
+ checked: currentWebView && currentWebView.profile === otrProfile
+ onToggled: function(checked) {
+ if (currentWebView) {
+ currentWebView.profile = checked ? otrProfile : defaultProfile;
+ }
+ }
+ }
+ MenuItem {
+ id: httpDiskCacheEnabled
+ text: "HTTP Disk Cache"
+ checkable: currentWebView && !currentWebView.profile.offTheRecord
+ checked: currentWebView && (currentWebView.profile.httpCacheType === WebEngineProfile.DiskHttpCache)
+ onToggled: function(checked) {
+ if (currentWebView) {
+ currentWebView.profile.httpCacheType = checked ? WebEngineProfile.DiskHttpCache : WebEngineProfile.MemoryHttpCache;
+ }
+ }
+ }
+ MenuItem {
+ id: autoLoadIconsForPage
+ text: "Icons On"
+ checkable: true
+ checked: WebEngine.settings.autoLoadIconsForPage
+ }
+ MenuItem {
+ id: touchIconsEnabled
+ text: "Touch Icons On"
+ checkable: true
+ checked: WebEngine.settings.touchIconsEnabled
+ enabled: autoLoadIconsForPage.checked
+ }
+ MenuItem {
+ id: webRTCPublicInterfacesOnly
+ text: "WebRTC Public Interfaces Only"
+ checkable: true
+ checked: WebEngine.settings.webRTCPublicInterfacesOnly
+ }
+ MenuItem {
+ id: devToolsEnabled
+ text: "Open DevTools"
+ checkable: true
+ checked: false
+ }
+ MenuItem {
+ id: pdfViewerEnabled
+ text: "PDF viewer enabled"
+ checkable: true
+ checked: WebEngine.settings.pdfViewerEnabled
+ }
+ }
+ }
+ }
+ ProgressBar {
+ id: progressBar
+ height: 3
+ anchors {
+ left: parent.left
+ top: parent.bottom
+ right: parent.right
+ leftMargin: parent.leftMargin
+ rightMargin: parent.rightMargin
+ }
+ background: Item {}
+ z: -2
+ from: 0
+ to: 100
+ value: (currentWebView && currentWebView.loadProgress < 100) ? currentWebView.loadProgress : 0
+ }
+ }
+
+ StackLayout {
+ id: tabLayout
+ currentIndex: tabBar.currentIndex
+
+ anchors.top: tabBar.bottom
+ anchors.bottom: devToolsView.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ }
+
+ Component {
+ id: tabButtonComponent
+
+ TabButton {
+ property color frameColor: "#999"
+ property color fillColor: "#eee"
+ property color nonSelectedColor: "#ddd"
+ property string tabTitle: "New Tab"
+
+ id: tabButton
+ contentItem: Rectangle {
+ id: tabRectangle
+ color: tabButton.down ? fillColor : nonSelectedColor
+ border.width: 1
+ border.color: frameColor
+ implicitWidth: Math.max(text.width + 30, 80)
+ implicitHeight: Math.max(text.height + 10, 20)
+ Rectangle { height: 1 ; width: parent.width ; color: frameColor}
+ Rectangle { height: parent.height ; width: 1; color: frameColor}
+ Rectangle { x: parent.width - 2; height: parent.height ; width: 1; color: frameColor}
+ Text {
+ id: text
+ anchors.left: parent.left
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.leftMargin: 6
+ text: tabButton.tabTitle
+ elide: Text.ElideRight
+ color: tabButton.down ? "black" : frameColor
+ width: parent.width - button.background.width
+ }
+ Button {
+ id: button
+ anchors.right: parent.right
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.rightMargin: 4
+ height: 12
+ background: Rectangle {
+ implicitWidth: 12
+ implicitHeight: 12
+ color: button.hovered ? "#ccc" : tabRectangle.color
+ Text {text: "x"; anchors.centerIn: parent; color: "gray"}
+ }
+ onClicked: tabButton.closeTab()
+ }
+ }
+
+ onClicked: addressBar.text = tabLayout.itemAt(TabBar.index).url;
+ function closeTab() {
+ tabBar.removeView(TabBar.index);
+ }
+ }
+ }
+
+ TabBar {
+ id: tabBar
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ Component.onCompleted: createTab(defaultProfile)
+
+ function createTab(profile, focusOnNewTab = true, url = undefined) {
+ var webview = tabComponent.createObject(tabLayout, {profile: profile});
+ var newTabButton = tabButtonComponent.createObject(tabBar, {tabTitle: Qt.binding(function () { return webview.title; })});
+ tabBar.addItem(newTabButton);
+ if (focusOnNewTab) {
+ tabBar.setCurrentIndex(tabBar.count - 1);
+ }
+ if (url !== undefined) {
+ webview.url = url;
+ }
+ return webview;
+ }
+
+ function removeView(index) {
+ tabBar.removeItem(index);
+ if (tabBar.count > 1) {
+ tabBar.removeItem(tabBar.itemAt(index));
+ tabLayout.children[index].destroy();
+ } else {
+ browserWindow.close();
+ }
+ }
+
+ Component {
+ id: tabComponent
+ WebEngineView {
+ id: webEngineView
+ focus: true
+
+ onLinkHovered: function(hoveredUrl) {
+ if (hoveredUrl == "")
+ hideStatusText.start();
+ else {
+ statusText.text = hoveredUrl;
+ statusBubble.visible = true;
+ hideStatusText.stop();
+ }
+ }
+
+ states: [
+ State {
+ name: "FullScreen"
+ PropertyChanges {
+ target: tabBar
+ visible: false
+ height: 0
+ }
+ PropertyChanges {
+ target: navigationBar
+ visible: false
+ }
+ }
+ ]
+ settings.autoLoadImages: appSettings.autoLoadImages
+ settings.javascriptEnabled: appSettings.javaScriptEnabled
+ settings.errorPageEnabled: appSettings.errorPageEnabled
+ settings.pluginsEnabled: appSettings.pluginsEnabled
+ settings.fullScreenSupportEnabled: appSettings.fullScreenSupportEnabled
+ settings.autoLoadIconsForPage: appSettings.autoLoadIconsForPage
+ settings.touchIconsEnabled: appSettings.touchIconsEnabled
+ settings.webRTCPublicInterfacesOnly: appSettings.webRTCPublicInterfacesOnly
+ settings.pdfViewerEnabled: appSettings.pdfViewerEnabled
+
+ onCertificateError: function(error) {
+ error.defer();
+ sslDialog.enqueue(error);
+ }
+
+ onNewWindowRequested: function(request) {
+ if (!request.userInitiated)
+ console.warn("Blocked a popup window.");
+ else if (request.destination === WebEngineNewWindowRequest.InNewTab) {
+ var tab = tabBar.createTab(currentWebView.profile, true, request.requestedUrl);
+ tab.acceptAsNewWindow(request);
+ } else if (request.destination === WebEngineNewWindowRequest.InNewBackgroundTab) {
+ var backgroundTab = tabBar.createTab(currentWebView.profile, false);
+ backgroundTab.acceptAsNewWindow(request);
+ } else if (request.destination === WebEngineNewWindowRequest.InNewDialog) {
+ var dialog = applicationRoot.createDialog(currentWebView.profile);
+ dialog.currentWebView.acceptAsNewWindow(request);
+ } else {
+ var window = applicationRoot.createWindow(currentWebView.profile);
+ window.currentWebView.acceptAsNewWindow(request);
+ }
+ }
+
+ onFullScreenRequested: function(request) {
+ if (request.toggleOn) {
+ webEngineView.state = "FullScreen";
+ browserWindow.previousVisibility = browserWindow.visibility;
+ browserWindow.showFullScreen();
+ fullScreenNotification.show();
+ } else {
+ webEngineView.state = "";
+ browserWindow.visibility = browserWindow.previousVisibility;
+ fullScreenNotification.hide();
+ }
+ request.accept();
+ }
+
+ onQuotaRequested: function(request) {
+ if (request.requestedSize <= 5 * 1024 * 1024)
+ request.accept();
+ else
+ request.reject();
+ }
+
+ onRegisterProtocolHandlerRequested: function(request) {
+ console.log("accepting registerProtocolHandler request for "
+ + request.scheme + " from " + request.origin);
+ request.accept();
+ }
+
+ onRenderProcessTerminated: function(terminationStatus, exitCode) {
+ var status = "";
+ switch (terminationStatus) {
+ case WebEngineView.NormalTerminationStatus:
+ status = "(normal exit)";
+ break;
+ case WebEngineView.AbnormalTerminationStatus:
+ status = "(abnormal exit)";
+ break;
+ case WebEngineView.CrashedTerminationStatus:
+ status = "(crashed)";
+ break;
+ case WebEngineView.KilledTerminationStatus:
+ status = "(killed)";
+ break;
+ }
+
+ print("Render process exited with code " + exitCode + " " + status);
+ reloadTimer.running = true;
+ }
+
+ onSelectClientCertificate: function(selection) {
+ selection.certificates[0].select();
+ }
+
+ onFindTextFinished: function(result) {
+ if (!findBar.visible)
+ findBar.visible = true;
+
+ findBar.numberOfMatches = result.numberOfMatches;
+ findBar.activeMatch = result.activeMatch;
+ }
+
+ onLoadingChanged: function(loadRequest) {
+ if (loadRequest.status == WebEngineView.LoadStartedStatus)
+ findBar.reset();
+ }
+
+ Timer {
+ id: reloadTimer
+ interval: 0
+ running: false
+ repeat: false
+ onTriggered: currentWebView.reload()
+ }
+ }
+ }
+ }
+ WebEngineView {
+ id: devToolsView
+ visible: devToolsEnabled.checked
+ height: visible ? 400 : 0
+ inspectedView: visible && tabBar.currentIndex < tabBar.count ? tabLayout.children[tabBar.currentIndex] : null
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ onNewWindowRequested: function(request) {
+ var tab = tabBar.createTab(currentWebView.profile);
+ request.openIn(tab);
+ }
+
+ Timer {
+ id: hideTimer
+ interval: 0
+ running: false
+ repeat: false
+ onTriggered: devToolsEnabled.checked = false
+ }
+ onWindowCloseRequested: function(request) {
+ // Delay hiding for keep the inspectedView set to receive the ACK message of close.
+ hideTimer.running = true;
+ }
+ }
+ Dialog {
+ id: sslDialog
+ anchors.centerIn: parent
+ contentWidth: Math.max(mainText.width, detailedText.width)
+ contentHeight: mainText.height + detailedText.height
+ property var certErrors: []
+ // fixme: icon!
+ // icon: StandardIcon.Warning
+ standardButtons: Dialog.No | Dialog.Yes
+ title: "Server's certificate not trusted"
+ contentItem: Item {
+ id: textContentItem
+ Label {
+ id: mainText
+ text: "Do you wish to continue?"
+ }
+ Text {
+ id: detailedText
+ anchors.top: mainText.bottom
+ text: "If you wish so, you may continue with an unverified certificate.\n" +
+ "Accepting an unverified certificate means\n" +
+ "you may not be connected with the host you tried to connect to.\n" +
+ "Do you wish to override the security check and continue?"
+ }
+ }
+
+ onAccepted: {
+ certErrors.shift().acceptCertificate();
+ presentError();
+ }
+ onRejected: reject()
+
+ function reject(){
+ certErrors.shift().rejectCertificate();
+ presentError();
+ }
+ function enqueue(error){
+ certErrors.push(error);
+ presentError();
+ }
+ function presentError(){
+ visible = certErrors.length > 0
+ }
+ }
+
+ FullScreenNotification {
+ id: fullScreenNotification
+ }
+
+ DownloadView {
+ id: downloadView
+ visible: false
+ anchors.fill: parent
+ }
+
+ function onDownloadRequested(download) {
+ downloadView.visible = true;
+ downloadView.append(download);
+ download.accept();
+ }
+
+ FindBar {
+ id: findBar
+ visible: false
+ anchors.right: parent.right
+ anchors.rightMargin: 10
+ anchors.top: parent.top
+
+ onFindNext: {
+ if (text)
+ currentWebView && currentWebView.findText(text);
+ else if (!visible)
+ visible = true;
+ }
+ onFindPrevious: {
+ if (text)
+ currentWebView && currentWebView.findText(text, WebEngineView.FindBackward);
+ else if (!visible)
+ visible = true;
+ }
+ }
+
+
+ Rectangle {
+ id: statusBubble
+ color: "oldlace"
+ property int padding: 8
+ visible: false
+
+ anchors.left: parent.left
+ anchors.bottom: parent.bottom
+ width: statusText.paintedWidth + padding
+ height: statusText.paintedHeight + padding
+
+ Text {
+ id: statusText
+ anchors.centerIn: statusBubble
+ elide: Qt.ElideMiddle
+
+ Timer {
+ id: hideStatusText
+ interval: 750
+ onTriggered: {
+ statusText.text = "";
+ statusBubble.visible = false;
+ }
+ }
+ }
+ }
+}
diff --git a/examples/webenginequick/quicknanobrowser/CMakeLists.txt b/examples/webenginequick/quicknanobrowser/CMakeLists.txt
new file mode 100644
index 000000000..a9e8bb4ae
--- /dev/null
+++ b/examples/webenginequick/quicknanobrowser/CMakeLists.txt
@@ -0,0 +1,81 @@
+cmake_minimum_required(VERSION 3.16)
+project(quicknanobrowser LANGUAGES CXX)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTORCC ON)
+set(CMAKE_AUTOUIC ON)
+
+if(NOT DEFINED INSTALL_EXAMPLESDIR)
+ set(INSTALL_EXAMPLESDIR "examples")
+endif()
+
+set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/webenginequick/quicknanobrowser")
+
+find_package(Qt6 COMPONENTS Core)
+find_package(Qt6 COMPONENTS Gui)
+find_package(Qt6 COMPONENTS Qml)
+find_package(Qt6 COMPONENTS Quick)
+find_package(Qt6 COMPONENTS WebEngineQuick)
+
+qt_add_executable(quicknanobrowser
+ main.cpp
+ utils.h
+)
+set_target_properties(quicknanobrowser PROPERTIES
+ WIN32_EXECUTABLE TRUE
+ MACOSX_BUNDLE TRUE
+)
+target_link_libraries(quicknanobrowser PUBLIC
+ Qt::Core
+ Qt::Gui
+ Qt::Qml
+ Qt::Quick
+ Qt::WebEngineQuick
+)
+
+
+# Resources:
+set(resources_resource_files
+ "ApplicationRoot.qml"
+ "BrowserDialog.qml"
+ "BrowserWindow.qml"
+ "DownloadView.qml"
+ "FindBar.qml"
+ "FullScreenNotification.qml"
+)
+
+qt6_add_resources(quicknanobrowser "resources"
+ PREFIX
+ "/"
+ FILES
+ ${resources_resource_files}
+)
+set(resources1_resource_files
+ "icons/3rdparty/go-next.png"
+ "icons/3rdparty/go-previous.png"
+ "icons/3rdparty/process-stop.png"
+ "icons/3rdparty/view-refresh.png"
+)
+
+qt6_add_resources(quicknanobrowser "resources1"
+ PREFIX
+ "/icons"
+ BASE
+ "icons/3rdparty"
+ FILES
+ ${resources1_resource_files}
+)
+
+if(TARGET Qt::Widgets)
+ target_link_libraries(quicknanobrowser PUBLIC
+ Qt::Widgets
+ )
+endif()
+
+install(TARGETS quicknanobrowser
+ RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
+ BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
+ LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
+)
diff --git a/examples/webenginequick/quicknanobrowser/DownloadView.qml b/examples/webenginequick/quicknanobrowser/DownloadView.qml
new file mode 100644
index 000000000..ea7e0b53d
--- /dev/null
+++ b/examples/webenginequick/quicknanobrowser/DownloadView.qml
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** 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: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
+import QtQuick.Controls
+import QtWebEngine
+import QtQuick.Layouts
+
+Rectangle {
+ id: downloadView
+ color: "lightgray"
+
+ ListModel {
+ id: downloadModel
+ property var downloads: []
+ }
+
+ function append(download) {
+ downloadModel.append(download);
+ downloadModel.downloads.push(download);
+ }
+
+ Component {
+ id: downloadItemDelegate
+
+ Rectangle {
+ width: listView.width
+ height: childrenRect.height
+ anchors.margins: 10
+ radius: 3
+ color: "transparent"
+ border.color: "black"
+ Rectangle {
+ id: progressBar
+
+ property real progress: downloadModel.downloads[index]
+ ? downloadModel.downloads[index].receivedBytes / downloadModel.downloads[index].totalBytes : 0
+
+ radius: 3
+ color: width == listView.width ? "green" : "#2b74c7"
+ width: listView.width * progress
+ height: cancelButton.height
+
+ Behavior on width {
+ SmoothedAnimation { duration: 100 }
+ }
+ }
+ Rectangle {
+ anchors {
+ left: parent.left
+ right: parent.right
+ leftMargin: 20
+ }
+ Label {
+ id: label
+ text: downloadModel.downloads[index] ? downloadModel.downloads[index].downloadDirectory + "/" + downloadModel.downloads[index].downloadFileName : qsTr("")
+ anchors {
+ verticalCenter: cancelButton.verticalCenter
+ left: parent.left
+ right: cancelButton.left
+ }
+ }
+ Button {
+ id: cancelButton
+ anchors.right: parent.right
+ icon.source: "qrc:/icons/process-stop.png"
+ onClicked: {
+ var download = downloadModel.downloads[index];
+
+ download.cancel();
+
+ downloadModel.downloads = downloadModel.downloads.filter(function (el) {
+ return el.id !== download.id;
+ });
+ downloadModel.remove(index);
+ }
+ }
+ }
+ }
+
+ }
+ ListView {
+ id: listView
+ anchors {
+ topMargin: 10
+ top: parent.top
+ bottom: parent.bottom
+ horizontalCenter: parent.horizontalCenter
+ }
+ width: parent.width - 20
+ spacing: 5
+
+ model: downloadModel
+ delegate: downloadItemDelegate
+
+ Text {
+ visible: !listView.count
+ horizontalAlignment: Text.AlignHCenter
+ height: 30
+ anchors {
+ top: parent.top
+ left: parent.left
+ right: parent.right
+ }
+ font.pixelSize: 20
+ text: "No active downloads."
+ }
+
+ Rectangle {
+ color: "gray"
+ anchors {
+ bottom: parent.bottom
+ left: parent.left
+ right: parent.right
+ }
+ height: 30
+ Button {
+ id: okButton
+ text: "OK"
+ anchors.centerIn: parent
+ onClicked: {
+ downloadView.visible = false;
+ }
+ }
+ }
+ }
+}
diff --git a/examples/webenginequick/quicknanobrowser/FindBar.qml b/examples/webenginequick/quicknanobrowser/FindBar.qml
new file mode 100644
index 000000000..738a38c84
--- /dev/null
+++ b/examples/webenginequick/quicknanobrowser/FindBar.qml
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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: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
+import QtQuick.Controls
+import QtQuick.Layouts
+
+Rectangle {
+ id: root
+
+ property int numberOfMatches: 0
+ property int activeMatch: 0
+ property alias text: findTextField.text
+
+ function reset() {
+ numberOfMatches = 0;
+ activeMatch = 0;
+ visible = false;
+ }
+
+ signal findNext()
+ signal findPrevious()
+
+ width: 250
+ height: 35
+ radius: 2
+
+ border.width: 1
+ border.color: "black"
+ color: "white"
+
+ onVisibleChanged: {
+ if (visible)
+ findTextField.forceActiveFocus();
+ }
+
+
+ RowLayout {
+ anchors.fill: parent
+ anchors.topMargin: 5
+ anchors.bottomMargin: 5
+ anchors.leftMargin: 10
+ anchors.rightMargin: 10
+
+ spacing: 5
+
+ Rectangle {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+
+ TextField {
+ id: findTextField
+ anchors.fill: parent
+ background: Rectangle {
+ color: "transparent"
+ }
+
+ onAccepted: root.findNext()
+ onTextChanged: root.findNext()
+ onActiveFocusChanged: activeFocus ? selectAll() : deselect()
+ }
+ }
+
+ Label {
+ text: activeMatch + "/" + numberOfMatches
+ visible: findTextField.text != ""
+ }
+
+ Rectangle {
+ border.width: 1
+ border.color: "#ddd"
+ width: 2
+ height: parent.height
+ anchors.topMargin: 5
+ anchors.bottomMargin: 5
+ }
+
+ ToolButton {
+ text: "<"
+ enabled: numberOfMatches > 0
+ onClicked: root.findPrevious()
+ }
+
+ ToolButton {
+ text: ">"
+ enabled: numberOfMatches > 0
+ onClicked: root.findNext()
+ }
+
+ ToolButton {
+ text: "x"
+ onClicked: root.visible = false
+ }
+ }
+}
diff --git a/examples/webenginequick/quicknanobrowser/FullScreenNotification.qml b/examples/webenginequick/quicknanobrowser/FullScreenNotification.qml
new file mode 100644
index 000000000..c5f891db6
--- /dev/null
+++ b/examples/webenginequick/quicknanobrowser/FullScreenNotification.qml
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 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
+
+Rectangle {
+ id: fullScreenNotification
+ width: 500
+ height: 40
+ color: "white"
+ radius: 7
+
+ visible: false
+ opacity: 0
+
+ function show() {
+ visible = true;
+ opacity = 1;
+ reset.start();
+ }
+
+ function hide() {
+ reset.stop();
+ opacity = 0;
+ }
+
+ Behavior on opacity {
+ NumberAnimation {
+ duration: 750
+ onStopped: {
+ if (opacity == 0)
+ visible = false;
+ }
+ }
+ }
+
+ Timer {
+ id: reset
+ interval: 5000
+ onTriggered: hide()
+ }
+
+ anchors.horizontalCenter: parent.horizontalCenter
+ y: 125
+
+ Text {
+ id: message
+ width: parent.width
+
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+
+ wrapMode: Text.WordWrap
+ elide: Text.ElideNone
+ clip: true
+
+ text: qsTr("You are now in fullscreen mode. Press ESC to quit!")
+ }
+}
diff --git a/examples/webenginequick/quicknanobrowser/doc/images/quicknanobrowser-demo.jpg b/examples/webenginequick/quicknanobrowser/doc/images/quicknanobrowser-demo.jpg
new file mode 100644
index 000000000..12693bb0f
--- /dev/null
+++ b/examples/webenginequick/quicknanobrowser/doc/images/quicknanobrowser-demo.jpg
Binary files differ
diff --git a/examples/webenginequick/quicknanobrowser/doc/src/quicknanobrowser.qdoc b/examples/webenginequick/quicknanobrowser/doc/src/quicknanobrowser.qdoc
new file mode 100644
index 000000000..3b9af68b2
--- /dev/null
+++ b/examples/webenginequick/quicknanobrowser/doc/src/quicknanobrowser.qdoc
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example webenginequick/quicknanobrowser
+ \title WebEngine Quick Nano Browser
+ \ingroup webengine-examples
+ \brief A web browser implemented using the WebEngineView QML type.
+
+ \image quicknanobrowser-demo.jpg
+
+ \e {Quick Nano Browser} demonstrates how to use the \l{Qt WebEngine QML Types}
+ {Qt WebEngine QML types} to develop a small web browser application that consists of a browser
+ window with a title bar, toolbar, tab view, and status bar. The web content is loaded in a web
+ engine view within the tab view. If certificate errors occur, users are prompted for action in a
+ message dialog. The status bar pops up to display the URL of a hovered link.
+
+ A web page can issue a request for being displayed in fullscreen mode. Users can allow full
+ screen mode by using a toolbar button. They can leave fullscreen mode by using a keyboard
+ shortcut. Additional toolbar buttons enable moving backwards and forwards in the browser
+ history, reloading tab content, and opening a settings menu for enabling the following features:
+ JavaScript, plugins, fullscreen mode, off the record, HTTP disk cache, autoloading images, and
+ ignoring certificate errors.
+
+ \include examples-run.qdocinc
+
+ \section1 Creating the Main Browser Window
+
+ When the browser main window is loaded, it creates an empty tab using the default profile. Each
+ tab is a web engine view that fills the main window.
+
+ We create the main window in the \e BrowserWindow.qml file using the ApplicationWindow type:
+
+ \quotefromfile webenginequick/quicknanobrowser/BrowserWindow.qml
+ \skipto ApplicationWindow
+ \printuntil currentWebView
+ \dots
+ \skipto width
+ \printuntil title
+
+ We use the TabBar Qt Quick control to create a tab bar anchored to the top of the window, and
+ create a new, empty tab:
+
+ \skipto TabBar {
+ \printuntil return webview
+ \printuntil }
+
+ The tab contains a web engine view that loads web content:
+
+ \skipto Component {
+ \printuntil currentWebView.reload
+ \printuntil /^\ {8}\}/
+
+ We use the \l Action type to create new tabs:
+
+ \quotefromfile webenginequick/quicknanobrowser/BrowserWindow.qml
+ \skipto reload
+ \skipto Action
+ \printuntil }
+
+ We use the \l TextField Qt Quick Control within a \l ToolBar to create an address bar that
+ shows the current URL and where users can enter another URL:
+
+ \quotefromfile webenginequick/quicknanobrowser/BrowserWindow.qml
+ \skipto menuBar: ToolBar
+ \printuntil anchors.fill
+ \dots
+ \skipto TextField
+ \printuntil addressBar
+ \dots
+ \skipto focus
+ \printuntil /^\ {12}\}/
+
+ \section1 Handling Certificate Errors
+
+ If the certificate of the site being loaded triggers a certificate error, we call the
+ \l{WebEngineCertificateError::}{defer()} QML method to pause the URL request and wait for user
+ input:
+
+ \quotefromfile webenginequick/quicknanobrowser/BrowserWindow.qml
+ \skipto onCertificateError
+ \printuntil }
+
+ We use the Dialog type to prompt users to continue or cancel the loading of the web page.
+ If users select \uicontrol Yes, we call the
+ \l{WebEngineCertificateError::}{acceptCertificate()} method to continue loading content from
+ the URL. If users select \uicontrol No, we call the
+ \l{WebEngineCertificateError::}{rejectCertificate()} method to reject the request and stop
+ loading content from the URL:
+
+ \skipto Dialog {
+ \printuntil /^\ {4}\}/
+
+ \section1 Entering and Leaving Fullscreen Mode
+
+ We create a menu item for allowing fullscreen mode in a settings menu that we place on the tool
+ bar. Also, we create an action for leaving fullscreen mode by using a keyboard shortcut.
+ We call the \l{FullScreenRequest::}{accept()} method to accept the fullscreen request.
+ The methdod sets the \l{WebEngineView::}{isFullScreen} property to be equal to the
+ \l{FullScreenRequest::}{toggleOn} property.
+
+ \quotefromfile webenginequick/quicknanobrowser/BrowserWindow.qml
+ \skipto onFullScreenRequested
+ \printuntil /^\ {16}\}/
+
+ When entering fullscreen mode, we display a notification using the FullScreenNotification custom
+ type that we create in \e FullScreenNotification.qml.
+
+ We use the \l Action type in the settings menu to create a shortcut for leaving fullscreen mode
+ by pressing the escape key:
+
+ \quotefromfile webenginequick/quicknanobrowser/BrowserWindow.qml
+ \skipto Settings
+ \printuntil appSettings
+ \skipto fullScreenSupportEnabled
+ \printuntil Action
+ \skipto Escape
+ \printuntil /^\ {4}\}/
+
+ \section1 Files and Attributions
+
+ The example uses icons from the Tango Icon Library:
+
+ \table
+ \row
+ \li \l{quicknanobrowser-tango}{Tango Icon Library}
+ \li Public Domain
+ \endtable
+*/
diff --git a/examples/webenginequick/quicknanobrowser/icons/3rdparty/COPYING b/examples/webenginequick/quicknanobrowser/icons/3rdparty/COPYING
new file mode 100644
index 000000000..220881da6
--- /dev/null
+++ b/examples/webenginequick/quicknanobrowser/icons/3rdparty/COPYING
@@ -0,0 +1 @@
+The icons in this repository are herefore released into the Public Domain.
diff --git a/examples/webenginequick/quicknanobrowser/icons/3rdparty/go-next.png b/examples/webenginequick/quicknanobrowser/icons/3rdparty/go-next.png
new file mode 100644
index 000000000..6f3f65d33
--- /dev/null
+++ b/examples/webenginequick/quicknanobrowser/icons/3rdparty/go-next.png
Binary files differ
diff --git a/examples/webenginequick/quicknanobrowser/icons/3rdparty/go-previous.png b/examples/webenginequick/quicknanobrowser/icons/3rdparty/go-previous.png
new file mode 100644
index 000000000..93be3d1ee
--- /dev/null
+++ b/examples/webenginequick/quicknanobrowser/icons/3rdparty/go-previous.png
Binary files differ
diff --git a/examples/webenginequick/quicknanobrowser/icons/3rdparty/process-stop.png b/examples/webenginequick/quicknanobrowser/icons/3rdparty/process-stop.png
new file mode 100644
index 000000000..b68290bf1
--- /dev/null
+++ b/examples/webenginequick/quicknanobrowser/icons/3rdparty/process-stop.png
Binary files differ
diff --git a/examples/webenginequick/quicknanobrowser/icons/3rdparty/qt_attribution.json b/examples/webenginequick/quicknanobrowser/icons/3rdparty/qt_attribution.json
new file mode 100644
index 000000000..4e5a44448
--- /dev/null
+++ b/examples/webenginequick/quicknanobrowser/icons/3rdparty/qt_attribution.json
@@ -0,0 +1,24 @@
+{
+ "Id": "quicknanobrowser-tango",
+ "Name": "Tango Icon Library",
+ "QDocModule": "qtwebengine",
+ "QtUsage": "Used in WebEngine Quick Nano Browser example.",
+
+ "QtParts": [ "examples" ],
+ "Description": "Selected icons from the Tango Icon Library",
+ "Homepage": "http://tango.freedesktop.org/Tango_Icon_Library",
+ "Version": "0.8.90",
+ "DownloadLocation": "http://tango.freedesktop.org/releases/tango-icon-theme-0.8.90.tar.gz",
+ "LicenseId": "DocumentRef-PublicDomain",
+ "License": "Public Domain",
+ "LicenseFile": "COPYING",
+ "Copyright": "Ulisse Perusin <uli.peru@gmail.com>
+Steven Garrity <sgarrity@silverorange.com>
+Lapo Calamandrei <calamandrei@gmail.com>
+Ryan Collier <rcollier@novell.com>
+Rodney Dawes <dobey@novell.com>
+Andreas Nilsson <nisses.mail@home.se>
+Tuomas Kuosmanen <tigert@tigert.com>
+Garrett LeSage <garrett@novell.com>
+Jakub Steiner <jimmac@novell.com>"
+}
diff --git a/examples/webenginequick/quicknanobrowser/icons/3rdparty/view-refresh.png b/examples/webenginequick/quicknanobrowser/icons/3rdparty/view-refresh.png
new file mode 100644
index 000000000..cab4d02c7
--- /dev/null
+++ b/examples/webenginequick/quicknanobrowser/icons/3rdparty/view-refresh.png
Binary files differ
diff --git a/examples/webenginequick/quicknanobrowser/main.cpp b/examples/webenginequick/quicknanobrowser/main.cpp
new file mode 100644
index 000000000..859856d92
--- /dev/null
+++ b/examples/webenginequick/quicknanobrowser/main.cpp
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** 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: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$
+**
+****************************************************************************/
+
+#include "utils.h"
+
+#ifndef QT_NO_WIDGETS
+#include <QtWidgets/QApplication>
+typedef QApplication Application;
+#else
+#include <QtGui/QGuiApplication>
+typedef QGuiApplication Application;
+#endif
+#include <QtQml/QQmlApplicationEngine>
+#include <QtQml/QQmlContext>
+#include <QtWebEngineQuick/qtwebenginequickglobal.h>
+
+static QUrl startupUrl()
+{
+ QUrl ret;
+ QStringList args(qApp->arguments());
+ args.takeFirst();
+ for (const QString &arg : qAsConst(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)
+{
+ QCoreApplication::setOrganizationName("QtExamples");
+ QtWebEngineQuick::initialize();
+
+ Application app(argc, argv);
+
+ QQmlApplicationEngine appEngine;
+ Utils utils;
+ appEngine.rootContext()->setContextProperty("utils", &utils);
+ appEngine.load(QUrl("qrc:/ApplicationRoot.qml"));
+ if (!appEngine.rootObjects().isEmpty())
+ QMetaObject::invokeMethod(appEngine.rootObjects().first(), "load", Q_ARG(QVariant, startupUrl()));
+ else
+ qFatal("Failed to load sources");
+
+ return app.exec();
+}
diff --git a/examples/webenginequick/quicknanobrowser/quicknanobrowser.pro b/examples/webenginequick/quicknanobrowser/quicknanobrowser.pro
new file mode 100644
index 000000000..8208e446a
--- /dev/null
+++ b/examples/webenginequick/quicknanobrowser/quicknanobrowser.pro
@@ -0,0 +1,25 @@
+requires(qtConfig(accessibility))
+
+TEMPLATE = app
+TARGET = quicknanobrowser
+
+HEADERS = utils.h
+SOURCES = main.cpp
+
+OTHER_FILES += ApplicationRoot.qml \
+ BrowserDialog.qml \
+ BrowserWindow.qml \
+ DownloadView.qml \
+ FindBar.qml \
+ FullScreenNotification.qml
+
+RESOURCES += resources.qrc
+
+QT += qml quick webenginequick
+
+qtHaveModule(widgets) {
+ QT += widgets # QApplication is required to get native styling with QtQuickControls
+}
+
+target.path = $$[QT_INSTALL_EXAMPLES]/webenginequick/quicknanobrowser
+INSTALLS += target
diff --git a/examples/webenginequick/quicknanobrowser/resources.qrc b/examples/webenginequick/quicknanobrowser/resources.qrc
new file mode 100644
index 000000000..9d1f927d3
--- /dev/null
+++ b/examples/webenginequick/quicknanobrowser/resources.qrc
@@ -0,0 +1,16 @@
+<RCC>
+ <qresource prefix="/">
+ <file>ApplicationRoot.qml</file>
+ <file>BrowserDialog.qml</file>
+ <file>BrowserWindow.qml</file>
+ <file>DownloadView.qml</file>
+ <file>FindBar.qml</file>
+ <file>FullScreenNotification.qml</file>
+ </qresource>
+ <qresource prefix="/icons">
+ <file alias="go-next.png">icons/3rdparty/go-next.png</file>
+ <file alias="go-previous.png">icons/3rdparty/go-previous.png</file>
+ <file alias="process-stop.png">icons/3rdparty/process-stop.png</file>
+ <file alias="view-refresh.png">icons/3rdparty/view-refresh.png</file>
+ </qresource>
+</RCC>
diff --git a/examples/webenginequick/quicknanobrowser/utils.h b/examples/webenginequick/quicknanobrowser/utils.h
new file mode 100644
index 000000000..79aa38cc7
--- /dev/null
+++ b/examples/webenginequick/quicknanobrowser/utils.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** 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: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$
+**
+****************************************************************************/
+#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