summaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/examples.pro5
-rw-r--r--examples/webengine/quicknanobrowser/ApplicationRoot.qml2
-rw-r--r--examples/webengine/quicknanobrowser/BrowserDialog.qml2
-rw-r--r--examples/webengine/quicknanobrowser/BrowserWindow.qml119
-rw-r--r--examples/webengine/quicknanobrowser/DownloadView.qml2
-rw-r--r--examples/webengine/quicknanobrowser/FullScreenNotification.qml99
-rw-r--r--examples/webengine/quicknanobrowser/doc/src/quicknanobrowser.qdoc2
-rw-r--r--examples/webengine/quicknanobrowser/quicknanobrowser.pro3
-rw-r--r--examples/webengine/quicknanobrowser/resources.qrc1
-rw-r--r--examples/webenginewidgets/browser/browser.rc1
-rw-r--r--examples/webenginewidgets/browser/doc/images/browser-demo.pngbin156342 -> 0 bytes
-rw-r--r--examples/webenginewidgets/browser/networkaccessmanager.cpp160
-rw-r--r--examples/webenginewidgets/browser/networkaccessmanager.h75
-rw-r--r--examples/webenginewidgets/demobrowser/Info_mac.plist (renamed from examples/webenginewidgets/browser/Info_mac.plist)0
-rw-r--r--examples/webenginewidgets/demobrowser/addbookmarkdialog.ui (renamed from examples/webenginewidgets/browser/addbookmarkdialog.ui)0
-rw-r--r--examples/webenginewidgets/demobrowser/autosaver.cpp (renamed from examples/webenginewidgets/browser/autosaver.cpp)0
-rw-r--r--examples/webenginewidgets/demobrowser/autosaver.h (renamed from examples/webenginewidgets/browser/autosaver.h)0
-rw-r--r--examples/webenginewidgets/demobrowser/bookmarks.cpp (renamed from examples/webenginewidgets/browser/bookmarks.cpp)0
-rw-r--r--examples/webenginewidgets/demobrowser/bookmarks.h (renamed from examples/webenginewidgets/browser/bookmarks.h)0
-rw-r--r--examples/webenginewidgets/demobrowser/bookmarks.ui (renamed from examples/webenginewidgets/browser/bookmarks.ui)0
-rw-r--r--examples/webenginewidgets/demobrowser/browserapplication.cpp (renamed from examples/webenginewidgets/browser/browserapplication.cpp)110
-rw-r--r--examples/webenginewidgets/demobrowser/browserapplication.h (renamed from examples/webenginewidgets/browser/browserapplication.h)19
-rw-r--r--examples/webenginewidgets/demobrowser/browsermainwindow.cpp (renamed from examples/webenginewidgets/browser/browsermainwindow.cpp)0
-rw-r--r--examples/webenginewidgets/demobrowser/browsermainwindow.h (renamed from examples/webenginewidgets/browser/browsermainwindow.h)0
-rw-r--r--examples/webenginewidgets/demobrowser/chasewidget.cpp (renamed from examples/webenginewidgets/browser/chasewidget.cpp)0
-rw-r--r--examples/webenginewidgets/demobrowser/chasewidget.h (renamed from examples/webenginewidgets/browser/chasewidget.h)0
-rw-r--r--examples/webenginewidgets/demobrowser/cookiejar.cpp (renamed from examples/webenginewidgets/browser/cookiejar.cpp)0
-rw-r--r--examples/webenginewidgets/demobrowser/cookiejar.h (renamed from examples/webenginewidgets/browser/cookiejar.h)0
-rw-r--r--examples/webenginewidgets/demobrowser/cookies.ui (renamed from examples/webenginewidgets/browser/cookies.ui)0
-rw-r--r--examples/webenginewidgets/demobrowser/cookiesexceptions.ui (renamed from examples/webenginewidgets/browser/cookiesexceptions.ui)0
-rw-r--r--examples/webenginewidgets/demobrowser/data/addtab.png (renamed from examples/webenginewidgets/browser/data/addtab.png)bin469 -> 469 bytes
-rw-r--r--examples/webenginewidgets/demobrowser/data/closetab.png (renamed from examples/webenginewidgets/browser/data/closetab.png)bin516 -> 516 bytes
-rw-r--r--examples/webenginewidgets/demobrowser/data/data.qrc (renamed from examples/webenginewidgets/browser/data/data.qrc)2
-rw-r--r--examples/webenginewidgets/demobrowser/data/defaultbookmarks.xbel (renamed from examples/webenginewidgets/browser/data/defaultbookmarks.xbel)0
-rw-r--r--examples/webenginewidgets/demobrowser/data/defaulticon.png (renamed from examples/webenginewidgets/browser/data/defaulticon.png)bin1473 -> 1473 bytes
-rw-r--r--examples/webenginewidgets/demobrowser/data/demobrowser.svg (renamed from examples/webenginewidgets/browser/data/browser.svg)3
-rw-r--r--examples/webenginewidgets/demobrowser/data/history.png (renamed from examples/webenginewidgets/browser/data/history.png)bin1527 -> 1527 bytes
-rw-r--r--examples/webenginewidgets/demobrowser/data/loading.gif (renamed from examples/webenginewidgets/browser/data/loading.gif)bin847 -> 847 bytes
-rw-r--r--examples/webenginewidgets/demobrowser/demobrowser.icns (renamed from examples/webenginewidgets/browser/browser.icns)bin50218 -> 50218 bytes
-rw-r--r--examples/webenginewidgets/demobrowser/demobrowser.ico (renamed from examples/webenginewidgets/browser/browser.ico)bin15374 -> 15374 bytes
-rw-r--r--examples/webenginewidgets/demobrowser/demobrowser.pro (renamed from examples/webenginewidgets/browser/browser.pro)20
-rw-r--r--examples/webenginewidgets/demobrowser/demobrowser.rc1
-rw-r--r--examples/webenginewidgets/demobrowser/doc/images/browser-demo.pngbin0 -> 199354 bytes
-rw-r--r--examples/webenginewidgets/demobrowser/doc/src/demobrowser.qdoc (renamed from examples/webenginewidgets/browser/doc/src/browser.qdoc)10
-rw-r--r--examples/webenginewidgets/demobrowser/downloaditem.ui (renamed from examples/webenginewidgets/browser/downloaditem.ui)0
-rw-r--r--examples/webenginewidgets/demobrowser/downloadmanager.cpp (renamed from examples/webenginewidgets/browser/downloadmanager.cpp)1
-rw-r--r--examples/webenginewidgets/demobrowser/downloadmanager.h (renamed from examples/webenginewidgets/browser/downloadmanager.h)2
-rw-r--r--examples/webenginewidgets/demobrowser/downloads.ui (renamed from examples/webenginewidgets/browser/downloads.ui)0
-rw-r--r--examples/webenginewidgets/demobrowser/edittableview.cpp (renamed from examples/webenginewidgets/browser/edittableview.cpp)0
-rw-r--r--examples/webenginewidgets/demobrowser/edittableview.h (renamed from examples/webenginewidgets/browser/edittableview.h)0
-rw-r--r--examples/webenginewidgets/demobrowser/edittreeview.cpp (renamed from examples/webenginewidgets/browser/edittreeview.cpp)0
-rw-r--r--examples/webenginewidgets/demobrowser/edittreeview.h (renamed from examples/webenginewidgets/browser/edittreeview.h)0
-rw-r--r--examples/webenginewidgets/demobrowser/featurepermissionbar.cpp (renamed from examples/webenginewidgets/browser/featurepermissionbar.cpp)0
-rw-r--r--examples/webenginewidgets/demobrowser/featurepermissionbar.h (renamed from examples/webenginewidgets/browser/featurepermissionbar.h)0
-rw-r--r--examples/webenginewidgets/demobrowser/fullscreennotification.cpp112
-rw-r--r--examples/webenginewidgets/demobrowser/fullscreennotification.h76
-rw-r--r--examples/webenginewidgets/demobrowser/history.cpp (renamed from examples/webenginewidgets/browser/history.cpp)0
-rw-r--r--examples/webenginewidgets/demobrowser/history.h (renamed from examples/webenginewidgets/browser/history.h)0
-rw-r--r--examples/webenginewidgets/demobrowser/history.ui (renamed from examples/webenginewidgets/browser/history.ui)0
-rw-r--r--examples/webenginewidgets/demobrowser/htmls/htmls.qrc (renamed from examples/webenginewidgets/browser/htmls/htmls.qrc)0
-rw-r--r--examples/webenginewidgets/demobrowser/htmls/notfound.html (renamed from examples/webenginewidgets/browser/htmls/notfound.html)0
-rw-r--r--examples/webenginewidgets/demobrowser/main.cpp (renamed from examples/webenginewidgets/browser/main.cpp)0
-rw-r--r--examples/webenginewidgets/demobrowser/modelmenu.cpp (renamed from examples/webenginewidgets/browser/modelmenu.cpp)0
-rw-r--r--examples/webenginewidgets/demobrowser/modelmenu.h (renamed from examples/webenginewidgets/browser/modelmenu.h)0
-rw-r--r--examples/webenginewidgets/demobrowser/passworddialog.ui (renamed from examples/webenginewidgets/browser/passworddialog.ui)0
-rw-r--r--examples/webenginewidgets/demobrowser/proxy.ui (renamed from examples/webenginewidgets/browser/proxy.ui)0
-rw-r--r--examples/webenginewidgets/demobrowser/searchlineedit.cpp (renamed from examples/webenginewidgets/browser/searchlineedit.cpp)0
-rw-r--r--examples/webenginewidgets/demobrowser/searchlineedit.h (renamed from examples/webenginewidgets/browser/searchlineedit.h)0
-rw-r--r--examples/webenginewidgets/demobrowser/settings.cpp (renamed from examples/webenginewidgets/browser/settings.cpp)33
-rw-r--r--examples/webenginewidgets/demobrowser/settings.h (renamed from examples/webenginewidgets/browser/settings.h)3
-rw-r--r--examples/webenginewidgets/demobrowser/settings.ui (renamed from examples/webenginewidgets/browser/settings.ui)27
-rw-r--r--examples/webenginewidgets/demobrowser/squeezelabel.cpp (renamed from examples/webenginewidgets/browser/squeezelabel.cpp)0
-rw-r--r--examples/webenginewidgets/demobrowser/squeezelabel.h (renamed from examples/webenginewidgets/browser/squeezelabel.h)0
-rw-r--r--examples/webenginewidgets/demobrowser/tabwidget.cpp (renamed from examples/webenginewidgets/browser/tabwidget.cpp)89
-rw-r--r--examples/webenginewidgets/demobrowser/tabwidget.h (renamed from examples/webenginewidgets/browser/tabwidget.h)11
-rw-r--r--examples/webenginewidgets/demobrowser/toolbarsearch.cpp (renamed from examples/webenginewidgets/browser/toolbarsearch.cpp)0
-rw-r--r--examples/webenginewidgets/demobrowser/toolbarsearch.h (renamed from examples/webenginewidgets/browser/toolbarsearch.h)0
-rw-r--r--examples/webenginewidgets/demobrowser/urllineedit.cpp (renamed from examples/webenginewidgets/browser/urllineedit.cpp)0
-rw-r--r--examples/webenginewidgets/demobrowser/urllineedit.h (renamed from examples/webenginewidgets/browser/urllineedit.h)0
-rw-r--r--examples/webenginewidgets/demobrowser/webview.cpp (renamed from examples/webenginewidgets/browser/webview.cpp)74
-rw-r--r--examples/webenginewidgets/demobrowser/webview.h (renamed from examples/webenginewidgets/browser/webview.h)5
-rw-r--r--examples/webenginewidgets/demobrowser/xbel.cpp (renamed from examples/webenginewidgets/browser/xbel.cpp)0
-rw-r--r--examples/webenginewidgets/demobrowser/xbel.h (renamed from examples/webenginewidgets/browser/xbel.h)0
-rw-r--r--examples/webenginewidgets/fancybrowser/doc/src/fancybrowser.qdoc22
-rw-r--r--examples/webenginewidgets/markdowneditor/3RDPARTY.md23
-rw-r--r--examples/webenginewidgets/markdowneditor/doc/images/markdowneditor-example.pngbin0 -> 41883 bytes
-rw-r--r--examples/webenginewidgets/markdowneditor/doc/src/markdowneditor.qdoc164
-rw-r--r--examples/webenginewidgets/markdowneditor/document.cpp50
-rw-r--r--examples/webenginewidgets/markdowneditor/document.h64
-rw-r--r--examples/webenginewidgets/markdowneditor/main.cpp56
-rw-r--r--examples/webenginewidgets/markdowneditor/mainwindow.cpp172
-rw-r--r--examples/webenginewidgets/markdowneditor/mainwindow.h77
-rw-r--r--examples/webenginewidgets/markdowneditor/mainwindow.ui115
-rw-r--r--examples/webenginewidgets/markdowneditor/markdowneditor.pro28
-rw-r--r--examples/webenginewidgets/markdowneditor/previewpage.cpp55
-rw-r--r--examples/webenginewidgets/markdowneditor/previewpage.h57
-rw-r--r--examples/webenginewidgets/markdowneditor/resources/default.md12
-rw-r--r--examples/webenginewidgets/markdowneditor/resources/index.html32
-rw-r--r--examples/webenginewidgets/markdowneditor/resources/markdown.css260
-rw-r--r--examples/webenginewidgets/markdowneditor/resources/markdowneditor.qrc9
-rw-r--r--examples/webenginewidgets/markdowneditor/resources/marked.min.js6
-rw-r--r--examples/webenginewidgets/markdowneditor/resources/qwebchannel.js413
102 files changed, 2310 insertions, 374 deletions
diff --git a/examples/examples.pro b/examples/examples.pro
index 3d6872d55..b1e1ade46 100644
--- a/examples/examples.pro
+++ b/examples/examples.pro
@@ -6,6 +6,7 @@ qtHaveModule(webengine) {
qtHaveModule(webenginewidgets) {
SUBDIRS += \
- webenginewidgets/browser \
- webenginewidgets/fancybrowser
+ webenginewidgets/demobrowser \
+ webenginewidgets/fancybrowser \
+ webenginewidgets/markdowneditor
}
diff --git a/examples/webengine/quicknanobrowser/ApplicationRoot.qml b/examples/webengine/quicknanobrowser/ApplicationRoot.qml
index b409696be..91d1551a7 100644
--- a/examples/webengine/quicknanobrowser/ApplicationRoot.qml
+++ b/examples/webengine/quicknanobrowser/ApplicationRoot.qml
@@ -39,7 +39,7 @@
****************************************************************************/
import QtQuick 2.1
-import QtWebEngine 1.1
+import QtWebEngine 1.2
QtObject {
id: root
diff --git a/examples/webengine/quicknanobrowser/BrowserDialog.qml b/examples/webengine/quicknanobrowser/BrowserDialog.qml
index 6202d02f7..0577bf642 100644
--- a/examples/webengine/quicknanobrowser/BrowserDialog.qml
+++ b/examples/webengine/quicknanobrowser/BrowserDialog.qml
@@ -40,7 +40,7 @@
import QtQuick 2.1
import QtQuick.Window 2.2
-import QtWebEngine 1.1
+import QtWebEngine 1.2
Window {
property alias currentWebView: webView
diff --git a/examples/webengine/quicknanobrowser/BrowserWindow.qml b/examples/webengine/quicknanobrowser/BrowserWindow.qml
index c4c0270a4..e8a9cb9ce 100644
--- a/examples/webengine/quicknanobrowser/BrowserWindow.qml
+++ b/examples/webengine/quicknanobrowser/BrowserWindow.qml
@@ -38,8 +38,8 @@
**
****************************************************************************/
-import QtQuick 2.1
-import QtWebEngine 1.1
+import QtQuick 2.2
+import QtWebEngine 1.2
import QtQuick.Controls 1.0
import QtQuick.Controls.Styles 1.0
import QtQuick.Layouts 1.0
@@ -59,8 +59,10 @@ ApplicationWindow {
// This is for the case where the system forces us to leave fullscreen.
if (currentWebView && !isFullScreen) {
currentWebView.state = ""
- if (currentWebView.isFullScreen)
+ if (currentWebView.isFullScreen) {
currentWebView.fullScreenCancelled()
+ fullScreenNotification.hide()
+ }
}
}
@@ -82,6 +84,8 @@ ApplicationWindow {
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;
}
Action {
@@ -99,14 +103,14 @@ ApplicationWindow {
}
}
Action {
- shortcut: "Ctrl+R"
+ shortcut: StandardKey.Refresh
onTriggered: {
if (currentWebView)
currentWebView.reload()
}
}
Action {
- shortcut: "Ctrl+T"
+ shortcut: StandardKey.AddTab
onTriggered: {
tabs.createEmptyTab(currentWebView.profile)
tabs.currentIndex = tabs.count - 1
@@ -115,12 +119,9 @@ ApplicationWindow {
}
}
Action {
- shortcut: "Ctrl+W"
+ shortcut: StandardKey.Close
onTriggered: {
- if (tabs.count == 1)
- browserWindow.close()
- else
- tabs.removeTab(tabs.currentIndex)
+ currentWebView.triggerWebAction(WebEngineView.RequestClose);
}
}
Action {
@@ -135,14 +136,51 @@ ApplicationWindow {
onTriggered: currentWebView.zoomFactor = 1.0;
}
Action {
- shortcut: "Ctrl+-"
+ shortcut: StandardKey.ZoomOut
onTriggered: currentWebView.zoomFactor -= 0.1;
}
Action {
- shortcut: "Ctrl+="
+ 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)
+ }
+
toolBar: ToolBar {
id: navigationBar
RowLayout {
@@ -230,6 +268,18 @@ ApplicationWindow {
checked: WebEngine.settings.errorPageEnabled
}
MenuItem {
+ id: pluginsEnabled
+ text: "Plugins On"
+ checkable: true
+ checked: WebEngine.settings.pluginsEnabled
+ }
+ MenuItem {
+ id: fullScreenSupportEnabled
+ text: "FullScreen On"
+ checkable: true
+ checked: WebEngine.settings.fullScreenSupportEnabled
+ }
+ MenuItem {
id: offTheRecordEnabled
text: "Off The Record"
checkable: true
@@ -312,6 +362,8 @@ ApplicationWindow {
settings.autoLoadImages: appSettings.autoLoadImages
settings.javascriptEnabled: appSettings.javaScriptEnabled
settings.errorPageEnabled: appSettings.errorPageEnabled
+ settings.pluginsEnabled: appSettings.pluginsEnabled
+ settings.fullScreenSupportEnabled: appSettings.fullScreenSupportEnabled
onCertificateError: {
error.defer()
@@ -342,12 +394,50 @@ ApplicationWindow {
webEngineView.state = "FullScreen"
browserWindow.previousVisibility = browserWindow.visibility
browserWindow.showFullScreen()
+ fullScreenNotification.show()
} else {
webEngineView.state = ""
browserWindow.visibility = browserWindow.previousVisibility
+ fullScreenNotification.hide()
}
request.accept()
}
+
+ onRenderProcessTerminated: {
+ 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
+ }
+
+ onWindowCloseRequested: {
+ if (tabs.count == 1)
+ browserWindow.close()
+ else
+ tabs.removeTab(tabs.currentIndex)
+ }
+
+ Timer {
+ id: reloadTimer
+ interval: 0
+ running: false
+ repeat: false
+ onTriggered: currentWebView.reload()
+ }
}
}
}
@@ -382,6 +472,11 @@ ApplicationWindow {
visible = certErrors.length > 0
}
}
+
+ FullScreenNotification {
+ id: fullScreenNotification
+ }
+
DownloadView {
id: downloadView
visible: false
diff --git a/examples/webengine/quicknanobrowser/DownloadView.qml b/examples/webengine/quicknanobrowser/DownloadView.qml
index 9a5cdd28f..c17a8bd60 100644
--- a/examples/webengine/quicknanobrowser/DownloadView.qml
+++ b/examples/webengine/quicknanobrowser/DownloadView.qml
@@ -41,7 +41,7 @@
import QtQuick 2.1
import QtQuick.Controls 1.0
import QtQuick.Controls.Styles 1.0
-import QtWebEngine 1.0
+import QtWebEngine 1.2
import QtQuick.Layouts 1.0
Rectangle {
diff --git a/examples/webengine/quicknanobrowser/FullScreenNotification.qml b/examples/webengine/quicknanobrowser/FullScreenNotification.qml
new file mode 100644
index 000000000..80a63d479
--- /dev/null
+++ b/examples/webengine/quicknanobrowser/FullScreenNotification.qml
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.5
+
+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/webengine/quicknanobrowser/doc/src/quicknanobrowser.qdoc b/examples/webengine/quicknanobrowser/doc/src/quicknanobrowser.qdoc
index 4fac9fe09..211951929 100644
--- a/examples/webengine/quicknanobrowser/doc/src/quicknanobrowser.qdoc
+++ b/examples/webengine/quicknanobrowser/doc/src/quicknanobrowser.qdoc
@@ -26,7 +26,7 @@
****************************************************************************/
/*!
- \example quicknanobrowser
+ \example webengine/quicknanobrowser
\title WebEngine Quick Nano Browser
\ingroup webengine-examples
\brief A web browser implemented using the WebEngineView QML type.
diff --git a/examples/webengine/quicknanobrowser/quicknanobrowser.pro b/examples/webengine/quicknanobrowser/quicknanobrowser.pro
index 1447af927..6cf556984 100644
--- a/examples/webengine/quicknanobrowser/quicknanobrowser.pro
+++ b/examples/webengine/quicknanobrowser/quicknanobrowser.pro
@@ -9,7 +9,8 @@ SOURCES = main.cpp
OTHER_FILES += ApplicationRoot.qml \
BrowserDialog.qml \
BrowserWindow.qml \
- DownloadView.qml
+ DownloadView.qml \
+ FullScreenNotification.qml
RESOURCES += resources.qrc
diff --git a/examples/webengine/quicknanobrowser/resources.qrc b/examples/webengine/quicknanobrowser/resources.qrc
index 28fd7b7dc..694f8d19b 100644
--- a/examples/webengine/quicknanobrowser/resources.qrc
+++ b/examples/webengine/quicknanobrowser/resources.qrc
@@ -4,6 +4,7 @@
<file>BrowserDialog.qml</file>
<file>BrowserWindow.qml</file>
<file>DownloadView.qml</file>
+ <file>FullScreenNotification.qml</file>
</qresource>
<qresource prefix="icons">
<file alias="go-next.png">icons/go-next.png</file>
diff --git a/examples/webenginewidgets/browser/browser.rc b/examples/webenginewidgets/browser/browser.rc
deleted file mode 100644
index 39e17e973..000000000
--- a/examples/webenginewidgets/browser/browser.rc
+++ /dev/null
@@ -1 +0,0 @@
-IDI_ICON1 ICON DISCARDABLE "browser.ico"
diff --git a/examples/webenginewidgets/browser/doc/images/browser-demo.png b/examples/webenginewidgets/browser/doc/images/browser-demo.png
deleted file mode 100644
index 09d065095..000000000
--- a/examples/webenginewidgets/browser/doc/images/browser-demo.png
+++ /dev/null
Binary files differ
diff --git a/examples/webenginewidgets/browser/networkaccessmanager.cpp b/examples/webenginewidgets/browser/networkaccessmanager.cpp
deleted file mode 100644
index d2b4f827f..000000000
--- a/examples/webenginewidgets/browser/networkaccessmanager.cpp
+++ /dev/null
@@ -1,160 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the demonstration applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "networkaccessmanager.h"
-
-#include "browserapplication.h"
-#include "browsermainwindow.h"
-
-#include <QtCore/QSettings>
-
-#include <QtGui/QDesktopServices>
-#include <QtWidgets/QDialog>
-#include <QtWidgets/QMessageBox>
-#include <QtWidgets/QStyle>
-#include <QtGui/QTextDocument>
-
-#include <QtNetwork/QAuthenticator>
-#include <QtNetwork/QNetworkDiskCache>
-#include <QtNetwork/QNetworkProxy>
-#include <QtNetwork/QNetworkRequest>
-#include <QtNetwork/QNetworkReply>
-#include <QtNetwork/QSslError>
-
-NetworkAccessManager::NetworkAccessManager(QObject *parent)
- : QNetworkAccessManager(parent),
- requestFinishedCount(0), requestFinishedFromCacheCount(0), requestFinishedPipelinedCount(0),
- requestFinishedSecureCount(0), requestFinishedDownloadBufferCount(0)
-{
- connect(this, SIGNAL(finished(QNetworkReply*)),
- SLOT(requestFinished(QNetworkReply*)));
-#ifndef QT_NO_OPENSSL
- connect(this, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)),
- SLOT(sslErrors(QNetworkReply*,QList<QSslError>)));
-#endif
- loadSettings();
-
- QNetworkDiskCache *diskCache = new QNetworkDiskCache(this);
- QString location = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
- diskCache->setCacheDirectory(location);
- setCache(diskCache);
-}
-
-QNetworkReply* NetworkAccessManager::createRequest(Operation op, const QNetworkRequest & req, QIODevice * outgoingData)
-{
- QNetworkRequest request = req; // copy so we can modify
- // this is a temporary hack until we properly use the pipelining flags from QtWebkit
- // pipeline everything! :)
- request.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
- return QNetworkAccessManager::createRequest(op, request, outgoingData);
-}
-
-void NetworkAccessManager::requestFinished(QNetworkReply *reply)
-{
- requestFinishedCount++;
-
- if (reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool() == true)
- requestFinishedFromCacheCount++;
-
- if (reply->attribute(QNetworkRequest::HttpPipeliningWasUsedAttribute).toBool() == true)
- requestFinishedPipelinedCount++;
-
- if (reply->attribute(QNetworkRequest::ConnectionEncryptedAttribute).toBool() == true)
- requestFinishedSecureCount++;
-
- if (reply->attribute(QNetworkRequest::DownloadBufferAttribute).isValid() == true)
- requestFinishedDownloadBufferCount++;
-
- if (requestFinishedCount % 10)
- return;
-
-#ifdef QT_DEBUG
- double pctCached = (double(requestFinishedFromCacheCount) * 100.0/ double(requestFinishedCount));
- double pctPipelined = (double(requestFinishedPipelinedCount) * 100.0/ double(requestFinishedCount));
- double pctSecure = (double(requestFinishedSecureCount) * 100.0/ double(requestFinishedCount));
- double pctDownloadBuffer = (double(requestFinishedDownloadBufferCount) * 100.0/ double(requestFinishedCount));
-
- qDebug("STATS [%lli requests total] [%3.2f%% from cache] [%3.2f%% pipelined] [%3.2f%% SSL/TLS] [%3.2f%% Zerocopy]", requestFinishedCount, pctCached, pctPipelined, pctSecure, pctDownloadBuffer);
-#endif
-}
-
-void NetworkAccessManager::loadSettings()
-{
- QSettings settings;
- settings.beginGroup(QLatin1String("proxy"));
- QNetworkProxy proxy;
- if (settings.value(QLatin1String("enabled"), false).toBool()) {
- if (settings.value(QLatin1String("type"), 0).toInt() == 0)
- proxy = QNetworkProxy::Socks5Proxy;
- else
- proxy = QNetworkProxy::HttpProxy;
- proxy.setHostName(settings.value(QLatin1String("hostName")).toString());
- proxy.setPort(settings.value(QLatin1String("port"), 1080).toInt());
- proxy.setUser(settings.value(QLatin1String("userName")).toString());
- proxy.setPassword(settings.value(QLatin1String("password")).toString());
- }
- setProxy(proxy);
-}
-
-#ifndef QT_NO_OPENSSL
-void NetworkAccessManager::sslErrors(QNetworkReply *reply, const QList<QSslError> &error)
-{
- // check if SSL certificate has been trusted already
- QString replyHost = reply->url().host() + QString(":%1").arg(reply->url().port());
- if (! sslTrustedHostList.contains(replyHost)) {
- BrowserMainWindow *mainWindow = BrowserApplication::instance()->mainWindow();
-
- QStringList errorStrings;
- for (int i = 0; i < error.count(); ++i)
- errorStrings += error.at(i).errorString();
- QString errors = errorStrings.join(QLatin1String("\n"));
- int ret = QMessageBox::warning(mainWindow, QCoreApplication::applicationName(),
- tr("SSL Errors:\n\n%1\n\n%2\n\n"
- "Do you want to ignore these errors for this host?").arg(reply->url().toString()).arg(errors),
- QMessageBox::Yes | QMessageBox::No,
- QMessageBox::No);
- if (ret == QMessageBox::Yes) {
- reply->ignoreSslErrors();
- sslTrustedHostList.append(replyHost);
- }
- }
-}
-#endif
diff --git a/examples/webenginewidgets/browser/networkaccessmanager.h b/examples/webenginewidgets/browser/networkaccessmanager.h
deleted file mode 100644
index f3ee2d338..000000000
--- a/examples/webenginewidgets/browser/networkaccessmanager.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the demonstration applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef NETWORKACCESSMANAGER_H
-#define NETWORKACCESSMANAGER_H
-
-#include <QtNetwork/QNetworkAccessManager>
-#include <QtNetwork/QNetworkRequest>
-
-class NetworkAccessManager : public QNetworkAccessManager
-{
- Q_OBJECT
-
-public:
- NetworkAccessManager(QObject *parent = 0);
-
- virtual QNetworkReply* createRequest ( Operation op, const QNetworkRequest & req, QIODevice * outgoingData = 0 );
-
-private:
- QList<QString> sslTrustedHostList;
- qint64 requestFinishedCount;
- qint64 requestFinishedFromCacheCount;
- qint64 requestFinishedPipelinedCount;
- qint64 requestFinishedSecureCount;
- qint64 requestFinishedDownloadBufferCount;
-
-public slots:
- void loadSettings();
- void requestFinished(QNetworkReply *reply);
-
-private slots:
-#ifndef QT_NO_OPENSSL
- void sslErrors(QNetworkReply *reply, const QList<QSslError> &error);
-#endif
-};
-
-#endif // NETWORKACCESSMANAGER_H
diff --git a/examples/webenginewidgets/browser/Info_mac.plist b/examples/webenginewidgets/demobrowser/Info_mac.plist
index ccd4b3f28..ccd4b3f28 100644
--- a/examples/webenginewidgets/browser/Info_mac.plist
+++ b/examples/webenginewidgets/demobrowser/Info_mac.plist
diff --git a/examples/webenginewidgets/browser/addbookmarkdialog.ui b/examples/webenginewidgets/demobrowser/addbookmarkdialog.ui
index 3460d7bb8..3460d7bb8 100644
--- a/examples/webenginewidgets/browser/addbookmarkdialog.ui
+++ b/examples/webenginewidgets/demobrowser/addbookmarkdialog.ui
diff --git a/examples/webenginewidgets/browser/autosaver.cpp b/examples/webenginewidgets/demobrowser/autosaver.cpp
index dc72090dd..dc72090dd 100644
--- a/examples/webenginewidgets/browser/autosaver.cpp
+++ b/examples/webenginewidgets/demobrowser/autosaver.cpp
diff --git a/examples/webenginewidgets/browser/autosaver.h b/examples/webenginewidgets/demobrowser/autosaver.h
index b0c73846f..b0c73846f 100644
--- a/examples/webenginewidgets/browser/autosaver.h
+++ b/examples/webenginewidgets/demobrowser/autosaver.h
diff --git a/examples/webenginewidgets/browser/bookmarks.cpp b/examples/webenginewidgets/demobrowser/bookmarks.cpp
index 15078caa3..15078caa3 100644
--- a/examples/webenginewidgets/browser/bookmarks.cpp
+++ b/examples/webenginewidgets/demobrowser/bookmarks.cpp
diff --git a/examples/webenginewidgets/browser/bookmarks.h b/examples/webenginewidgets/demobrowser/bookmarks.h
index 244f003c6..244f003c6 100644
--- a/examples/webenginewidgets/browser/bookmarks.h
+++ b/examples/webenginewidgets/demobrowser/bookmarks.h
diff --git a/examples/webenginewidgets/browser/bookmarks.ui b/examples/webenginewidgets/demobrowser/bookmarks.ui
index c893e941d..c893e941d 100644
--- a/examples/webenginewidgets/browser/bookmarks.ui
+++ b/examples/webenginewidgets/demobrowser/bookmarks.ui
diff --git a/examples/webenginewidgets/browser/browserapplication.cpp b/examples/webenginewidgets/demobrowser/browserapplication.cpp
index ca28b2d0b..a85bce2c3 100644
--- a/examples/webenginewidgets/browser/browserapplication.cpp
+++ b/examples/webenginewidgets/demobrowser/browserapplication.cpp
@@ -46,7 +46,6 @@
#include "cookiejar.h"
#include "downloadmanager.h"
#include "history.h"
-#include "networkaccessmanager.h"
#include "tabwidget.h"
#include "webview.h"
@@ -64,6 +63,7 @@
#include <QtNetwork/QLocalServer>
#include <QtNetwork/QLocalSocket>
#include <QtNetwork/QNetworkProxy>
+#include <QtNetwork/QNetworkReply>
#include <QtNetwork/QSslSocket>
#include <QWebEngineProfile>
@@ -191,25 +191,24 @@ BrowserApplication::~BrowserApplication()
delete s_bookmarksManager;
}
-#if defined(Q_OS_OSX)
void BrowserApplication::lastWindowClosed()
{
+#if defined(Q_OS_OSX)
clean();
BrowserMainWindow *mw = new BrowserMainWindow;
mw->slotHome();
m_mainWindows.prepend(mw);
-}
#endif
+}
BrowserApplication *BrowserApplication::instance()
{
return (static_cast<BrowserApplication *>(QCoreApplication::instance()));
}
-#if defined(Q_OS_OSX)
-#include <QtWidgets/QMessageBox>
void BrowserApplication::quitBrowser()
{
+#if defined(Q_OS_OSX)
clean();
int tabCount = 0;
for (int i = 0; i < m_mainWindows.count(); ++i) {
@@ -227,8 +226,8 @@ void BrowserApplication::quitBrowser()
}
exit(0);
-}
#endif
+}
/*!
Any actions that can be delayed until the window is visible
@@ -243,7 +242,7 @@ void BrowserApplication::postLaunch()
QWebEngineSettings::setOfflineStoragePath(directory);
#endif
- setWindowIcon(QIcon(QLatin1String(":browser.svg")));
+ setWindowIcon(QIcon(QLatin1String(":demobrowser.svg")));
loadSettings();
@@ -283,14 +282,15 @@ void BrowserApplication::loadSettings()
defaultSettings->setAttribute(QWebEngineSettings::JavascriptEnabled, settings.value(QLatin1String("enableJavascript"), true).toBool());
defaultSettings->setAttribute(QWebEngineSettings::ScrollAnimatorEnabled, settings.value(QLatin1String("enableScrollAnimator"), true).toBool());
-#if defined(QTWEBENGINE_PLUGINS)
defaultSettings->setAttribute(QWebEngineSettings::PluginsEnabled, settings.value(QLatin1String("enablePlugins"), true).toBool());
-#endif
+
+ defaultSettings->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true);
QString css = settings.value(QLatin1String("userStyleSheet")).toString();
setUserStyleSheet(defaultProfile, css, mainWindow());
defaultProfile->setHttpUserAgent(settings.value(QLatin1String("httpUserAgent")).toString());
+ defaultProfile->setHttpAcceptLanguage(settings.value(QLatin1String("httpAcceptLanguage")).toString());
settings.endGroup();
settings.beginGroup(QLatin1String("cookies"));
@@ -300,6 +300,21 @@ void BrowserApplication::loadSettings()
defaultProfile->setPersistentStoragePath(pdataPath);
settings.endGroup();
+
+ settings.beginGroup(QLatin1String("proxy"));
+ QNetworkProxy proxy;
+ if (settings.value(QLatin1String("enabled"), false).toBool()) {
+ if (settings.value(QLatin1String("type"), 0).toInt() == 0)
+ proxy = QNetworkProxy::Socks5Proxy;
+ else
+ proxy = QNetworkProxy::HttpProxy;
+ proxy.setHostName(settings.value(QLatin1String("hostName")).toString());
+ proxy.setPort(settings.value(QLatin1String("port"), 1080).toInt());
+ proxy.setUser(settings.value(QLatin1String("userName")).toString());
+ proxy.setPassword(settings.value(QLatin1String("password")).toString());
+ }
+ QNetworkProxy::setApplicationProxy(proxy);
+ settings.endGroup();
}
QList<BrowserMainWindow*> BrowserApplication::mainWindows()
@@ -475,18 +490,14 @@ DownloadManager *BrowserApplication::downloadManager()
QNetworkAccessManager *BrowserApplication::networkAccessManager()
{
-#if defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER)
- if (!s_networkAccessManager) {
- s_networkAccessManager = new NetworkAccessManager();
- s_networkAccessManager->setCookieJar(new CookieJar);
- }
- return s_networkAccessManager;
-#else
if (!s_networkAccessManager) {
s_networkAccessManager = new QNetworkAccessManager();
+ connect(s_networkAccessManager, &QNetworkAccessManager::authenticationRequired,
+ BrowserApplication::instance(), &BrowserApplication::authenticationRequired);
+ connect(s_networkAccessManager, &QNetworkAccessManager::proxyAuthenticationRequired,
+ BrowserApplication::instance(), &BrowserApplication::proxyAuthenticationRequired);
}
return s_networkAccessManager;
-#endif
}
HistoryManager *BrowserApplication::historyManager()
@@ -543,3 +554,68 @@ void BrowserApplication::setPrivateBrowsing(bool privateBrowsing)
}
emit privateBrowsingChanged(privateBrowsing);
}
+
+void BrowserApplication::setLastAuthenticator(QAuthenticator *authenticator)
+{
+ m_lastAuthenticator = QAuthenticator(*authenticator);
+}
+
+void BrowserApplication::setLastProxyAuthenticator(QAuthenticator *authenticator)
+{
+ m_lastProxyAuthenticator = QAuthenticator(*authenticator);
+}
+
+void BrowserApplication::authenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator)
+{
+ if (m_lastAuthenticator.isNull())
+ return;
+
+
+ Q_ASSERT(m_lastAuthenticator.option("key").isValid());
+ QByteArray lastKey = m_lastAuthenticator.option("key").toByteArray();
+ QByteArray key = BrowserApplication::authenticationKey(reply->url(), authenticator->realm());
+
+ if (lastKey == key)
+ *authenticator = m_lastAuthenticator;
+}
+
+void BrowserApplication::proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator)
+{
+ if (m_lastProxyAuthenticator.isNull())
+ return;
+
+ QNetworkProxy::ProxyType proxyType = proxy.type();
+ if (proxyType != QNetworkProxy::HttpProxy || proxyType != QNetworkProxy::HttpCachingProxy)
+ return;
+
+ Q_ASSERT(m_lastProxyAuthenticator.option("host").isValid());
+ QByteArray lastKey = m_lastProxyAuthenticator.option("key").toByteArray();
+ QByteArray key = BrowserApplication::proxyAuthenticationKey(proxy, authenticator->realm());
+
+ if (lastKey == key)
+ *authenticator = m_lastAuthenticator;
+}
+
+// TODO: Remove these functions (QTBUG-47967)
+QByteArray BrowserApplication::authenticationKey(const QUrl &url, const QString &realm)
+{
+ QUrl copy = url;
+ copy.setFragment(realm);
+ return "auth:" + copy.toEncoded(QUrl::RemovePassword | QUrl::RemovePath | QUrl::RemoveQuery);
+}
+
+QByteArray BrowserApplication::proxyAuthenticationKey(const QNetworkProxy &proxy, const QString &realm)
+{
+ QString host = QString("%1:%2").arg(proxy.hostName()).arg(proxy.port());
+ return BrowserApplication::proxyAuthenticationKey(proxy.user(), host, realm);
+}
+
+QByteArray BrowserApplication::proxyAuthenticationKey(const QString &user, const QString &host, const QString &realm)
+{
+ QUrl key;
+ key.setScheme(QLatin1String("proxy-http"));
+ key.setUserName(user);
+ key.setHost(host);
+ key.setFragment(realm);
+ return "auth:" + key.toEncoded();
+}
diff --git a/examples/webenginewidgets/browser/browserapplication.h b/examples/webenginewidgets/demobrowser/browserapplication.h
index 26557b8f9..75ae57c64 100644
--- a/examples/webenginewidgets/browser/browserapplication.h
+++ b/examples/webenginewidgets/demobrowser/browserapplication.h
@@ -49,9 +49,13 @@
#include <QtGui/QIcon>
+#include <QtNetwork/QAuthenticator>
+
QT_BEGIN_NAMESPACE
class QLocalServer;
class QNetworkAccessManager;
+class QNetworkProxy;
+class QNetworkReply;
class QWebEngineProfile;
QT_END_NAMESPACE
@@ -80,6 +84,14 @@ public:
bool canRestoreSession() const;
bool privateBrowsing() const { return m_privateBrowsing; }
+ void setLastAuthenticator(QAuthenticator *);
+ void setLastProxyAuthenticator(QAuthenticator *);
+
+ // TODO: Remove these functions (QTBUG-47967)
+ static QByteArray authenticationKey(const QUrl &, const QString &);
+ static QByteArray proxyAuthenticationKey(const QNetworkProxy &, const QString &);
+ static QByteArray proxyAuthenticationKey(const QString &, const QString &, const QString &);
+
static HistoryManager *historyManager();
static CookieJar *cookieJar();
static DownloadManager *downloadManager();
@@ -93,11 +105,11 @@ public:
public slots:
BrowserMainWindow *newMainWindow();
void restoreLastSession();
-#if defined(Q_OS_OSX)
void lastWindowClosed();
void quitBrowser();
-#endif
void setPrivateBrowsing(bool);
+ void authenticationRequired(QNetworkReply *, QAuthenticator *);
+ void proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *);
signals:
void privateBrowsingChanged(bool);
@@ -122,6 +134,9 @@ private:
QWebEngineProfile *m_privateProfile;
bool m_privateBrowsing;
mutable QIcon m_defaultIcon;
+
+ QAuthenticator m_lastAuthenticator;
+ QAuthenticator m_lastProxyAuthenticator;
};
#endif // BROWSERAPPLICATION_H
diff --git a/examples/webenginewidgets/browser/browsermainwindow.cpp b/examples/webenginewidgets/demobrowser/browsermainwindow.cpp
index 9595ca7ba..9595ca7ba 100644
--- a/examples/webenginewidgets/browser/browsermainwindow.cpp
+++ b/examples/webenginewidgets/demobrowser/browsermainwindow.cpp
diff --git a/examples/webenginewidgets/browser/browsermainwindow.h b/examples/webenginewidgets/demobrowser/browsermainwindow.h
index a2bbc443f..a2bbc443f 100644
--- a/examples/webenginewidgets/browser/browsermainwindow.h
+++ b/examples/webenginewidgets/demobrowser/browsermainwindow.h
diff --git a/examples/webenginewidgets/browser/chasewidget.cpp b/examples/webenginewidgets/demobrowser/chasewidget.cpp
index fb0e9ce76..fb0e9ce76 100644
--- a/examples/webenginewidgets/browser/chasewidget.cpp
+++ b/examples/webenginewidgets/demobrowser/chasewidget.cpp
diff --git a/examples/webenginewidgets/browser/chasewidget.h b/examples/webenginewidgets/demobrowser/chasewidget.h
index a90389034..a90389034 100644
--- a/examples/webenginewidgets/browser/chasewidget.h
+++ b/examples/webenginewidgets/demobrowser/chasewidget.h
diff --git a/examples/webenginewidgets/browser/cookiejar.cpp b/examples/webenginewidgets/demobrowser/cookiejar.cpp
index d9a7465ca..d9a7465ca 100644
--- a/examples/webenginewidgets/browser/cookiejar.cpp
+++ b/examples/webenginewidgets/demobrowser/cookiejar.cpp
diff --git a/examples/webenginewidgets/browser/cookiejar.h b/examples/webenginewidgets/demobrowser/cookiejar.h
index 374156e89..374156e89 100644
--- a/examples/webenginewidgets/browser/cookiejar.h
+++ b/examples/webenginewidgets/demobrowser/cookiejar.h
diff --git a/examples/webenginewidgets/browser/cookies.ui b/examples/webenginewidgets/demobrowser/cookies.ui
index c4bccc548..c4bccc548 100644
--- a/examples/webenginewidgets/browser/cookies.ui
+++ b/examples/webenginewidgets/demobrowser/cookies.ui
diff --git a/examples/webenginewidgets/browser/cookiesexceptions.ui b/examples/webenginewidgets/demobrowser/cookiesexceptions.ui
index 3d9ef6241..3d9ef6241 100644
--- a/examples/webenginewidgets/browser/cookiesexceptions.ui
+++ b/examples/webenginewidgets/demobrowser/cookiesexceptions.ui
diff --git a/examples/webenginewidgets/browser/data/addtab.png b/examples/webenginewidgets/demobrowser/data/addtab.png
index 20928fb40..20928fb40 100644
--- a/examples/webenginewidgets/browser/data/addtab.png
+++ b/examples/webenginewidgets/demobrowser/data/addtab.png
Binary files differ
diff --git a/examples/webenginewidgets/browser/data/closetab.png b/examples/webenginewidgets/demobrowser/data/closetab.png
index ab9d669ee..ab9d669ee 100644
--- a/examples/webenginewidgets/browser/data/closetab.png
+++ b/examples/webenginewidgets/demobrowser/data/closetab.png
Binary files differ
diff --git a/examples/webenginewidgets/browser/data/data.qrc b/examples/webenginewidgets/demobrowser/data/data.qrc
index c7d0294c1..5cb8a97c0 100644
--- a/examples/webenginewidgets/browser/data/data.qrc
+++ b/examples/webenginewidgets/demobrowser/data/data.qrc
@@ -3,7 +3,7 @@
<file>addtab.png</file>
<file>closetab.png</file>
<file>history.png</file>
- <file>browser.svg</file>
+ <file>demobrowser.svg</file>
<file>defaultbookmarks.xbel</file>
<file>loading.gif</file>
<file>defaulticon.png</file>
diff --git a/examples/webenginewidgets/browser/data/defaultbookmarks.xbel b/examples/webenginewidgets/demobrowser/data/defaultbookmarks.xbel
index fef7f5514..fef7f5514 100644
--- a/examples/webenginewidgets/browser/data/defaultbookmarks.xbel
+++ b/examples/webenginewidgets/demobrowser/data/defaultbookmarks.xbel
diff --git a/examples/webenginewidgets/browser/data/defaulticon.png b/examples/webenginewidgets/demobrowser/data/defaulticon.png
index 01a0920c9..01a0920c9 100644
--- a/examples/webenginewidgets/browser/data/defaulticon.png
+++ b/examples/webenginewidgets/demobrowser/data/defaulticon.png
Binary files differ
diff --git a/examples/webenginewidgets/browser/data/browser.svg b/examples/webenginewidgets/demobrowser/data/demobrowser.svg
index 2127a0a6e..f61a54c67 100644
--- a/examples/webenginewidgets/browser/data/browser.svg
+++ b/examples/webenginewidgets/demobrowser/data/demobrowser.svg
@@ -14,11 +14,10 @@
id="svg2160"
sodipodi:version="0.32"
inkscape:version="0.46"
- inkscape:export-filename="c:\icons\qtbrowser48.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
sodipodi:docbase="C:\icons"
- sodipodi:docname="browser.svg"
+ sodipodi:docname="demobrowser.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<defs
id="defs2162"><linearGradient
diff --git a/examples/webenginewidgets/browser/data/history.png b/examples/webenginewidgets/demobrowser/data/history.png
index 552a1cbd8..552a1cbd8 100644
--- a/examples/webenginewidgets/browser/data/history.png
+++ b/examples/webenginewidgets/demobrowser/data/history.png
Binary files differ
diff --git a/examples/webenginewidgets/browser/data/loading.gif b/examples/webenginewidgets/demobrowser/data/loading.gif
index c1545eb0e..c1545eb0e 100644
--- a/examples/webenginewidgets/browser/data/loading.gif
+++ b/examples/webenginewidgets/demobrowser/data/loading.gif
Binary files differ
diff --git a/examples/webenginewidgets/browser/browser.icns b/examples/webenginewidgets/demobrowser/demobrowser.icns
index f591ae48a..f591ae48a 100644
--- a/examples/webenginewidgets/browser/browser.icns
+++ b/examples/webenginewidgets/demobrowser/demobrowser.icns
Binary files differ
diff --git a/examples/webenginewidgets/browser/browser.ico b/examples/webenginewidgets/demobrowser/demobrowser.ico
index 7f9be934d..7f9be934d 100644
--- a/examples/webenginewidgets/browser/browser.ico
+++ b/examples/webenginewidgets/demobrowser/demobrowser.ico
Binary files differ
diff --git a/examples/webenginewidgets/browser/browser.pro b/examples/webenginewidgets/demobrowser/demobrowser.pro
index f54186856..113eeb40e 100644
--- a/examples/webenginewidgets/browser/browser.pro
+++ b/examples/webenginewidgets/demobrowser/demobrowser.pro
@@ -1,6 +1,7 @@
TEMPLATE = app
-TARGET = browser
+TARGET = demobrowser
QT += webenginewidgets network widgets printsupport
+CONFIG += c++11
qtHaveModule(uitools):!embedded: QT += uitools
else: DEFINES += QT_NO_UITOOLS
@@ -27,6 +28,7 @@ HEADERS += \
edittableview.h \
edittreeview.h \
featurepermissionbar.h\
+ fullscreennotification.h \
history.h \
modelmenu.h \
searchlineedit.h \
@@ -48,6 +50,7 @@ SOURCES += \
edittableview.cpp \
edittreeview.cpp \
featurepermissionbar.cpp\
+ fullscreennotification.cpp \
history.cpp \
modelmenu.cpp \
searchlineedit.cpp \
@@ -62,28 +65,23 @@ SOURCES += \
RESOURCES += data/data.qrc htmls/htmls.qrc
-contains(DEFINES, QWEBENGINEPAGE_SETNETWORKACCESSMANAGER) {
- HEADERS += cookiejar.h networkaccessmanager.h
- SOURCES += cookiejar.cpp networkaccessmanager.cpp
-}
-
build_all:!build_pass {
CONFIG -= build_all
CONFIG += release
}
win32 {
- RC_FILE = browser.rc
+ RC_FILE = demobrowser.rc
}
mac {
- ICON = browser.icns
+ ICON = demobrowser.icns
QMAKE_INFO_PLIST = Info_mac.plist
- TARGET = Browser
+ TARGET = Demobrowser
}
-EXAMPLE_FILES = Info_mac.plist browser.icns browser.ico browser.rc
+EXAMPLE_FILES = Info_mac.plist demobrowser.icns demobrowser.ico demobrowser.rc
# install
-target.path = $$[QT_INSTALL_EXAMPLES]/webenginewidgets/browser
+target.path = $$[QT_INSTALL_EXAMPLES]/webenginewidgets/demobrowser
INSTALLS += target
diff --git a/examples/webenginewidgets/demobrowser/demobrowser.rc b/examples/webenginewidgets/demobrowser/demobrowser.rc
new file mode 100644
index 000000000..70cd8bb1c
--- /dev/null
+++ b/examples/webenginewidgets/demobrowser/demobrowser.rc
@@ -0,0 +1 @@
+IDI_ICON1 ICON DISCARDABLE "demobrowser.ico"
diff --git a/examples/webenginewidgets/demobrowser/doc/images/browser-demo.png b/examples/webenginewidgets/demobrowser/doc/images/browser-demo.png
new file mode 100644
index 000000000..e8695dbca
--- /dev/null
+++ b/examples/webenginewidgets/demobrowser/doc/images/browser-demo.png
Binary files differ
diff --git a/examples/webenginewidgets/browser/doc/src/browser.qdoc b/examples/webenginewidgets/demobrowser/doc/src/demobrowser.qdoc
index 99581d8a9..ba61dd79d 100644
--- a/examples/webenginewidgets/browser/doc/src/browser.qdoc
+++ b/examples/webenginewidgets/demobrowser/doc/src/demobrowser.qdoc
@@ -26,13 +26,13 @@
****************************************************************************/
/*!
- \example browser
- \title WebEngine Tab Browser Example
+ \example webenginewidgets/demobrowser
+ \title WebEngine Demo Browser Example
\ingroup webengine-widgetexamples
- \brief The QtWebKit browser example ported to use QtWebEngine
+ \brief A demo browser based on Qt WebEngine Widgets
- The Tab Browser example shows the \l{Qt WebEngine Widgets} module in action,
- providing a little Web browser application with support for tabs.
+ \e {Demo Browser} demonstrates how to use the \l{Qt WebEngine Widgets C++ Classes}
+ {Qt WebEngine C++ classes} to develop a small Web browser application with support for tabs.
\image browser-demo.png
diff --git a/examples/webenginewidgets/browser/downloaditem.ui b/examples/webenginewidgets/demobrowser/downloaditem.ui
index b7f7deb72..b7f7deb72 100644
--- a/examples/webenginewidgets/browser/downloaditem.ui
+++ b/examples/webenginewidgets/demobrowser/downloaditem.ui
diff --git a/examples/webenginewidgets/browser/downloadmanager.cpp b/examples/webenginewidgets/demobrowser/downloadmanager.cpp
index aa83d7145..1c33f12c7 100644
--- a/examples/webenginewidgets/browser/downloadmanager.cpp
+++ b/examples/webenginewidgets/demobrowser/downloadmanager.cpp
@@ -43,7 +43,6 @@
#include "autosaver.h"
#include "browserapplication.h"
-#include "networkaccessmanager.h"
#include <math.h>
diff --git a/examples/webenginewidgets/browser/downloadmanager.h b/examples/webenginewidgets/demobrowser/downloadmanager.h
index 877682d77..cd96f35a5 100644
--- a/examples/webenginewidgets/browser/downloadmanager.h
+++ b/examples/webenginewidgets/demobrowser/downloadmanager.h
@@ -98,7 +98,6 @@ class DownloadManager : public QDialog, public Ui_DownloadDialog
{
Q_OBJECT
Q_PROPERTY(RemovePolicy removePolicy READ removePolicy WRITE setRemovePolicy)
- Q_ENUMS(RemovePolicy)
public:
enum RemovePolicy {
@@ -106,6 +105,7 @@ public:
Exit,
SuccessFullDownload
};
+ Q_ENUM(RemovePolicy)
DownloadManager(QWidget *parent = 0);
~DownloadManager();
diff --git a/examples/webenginewidgets/browser/downloads.ui b/examples/webenginewidgets/demobrowser/downloads.ui
index a2e256935..a2e256935 100644
--- a/examples/webenginewidgets/browser/downloads.ui
+++ b/examples/webenginewidgets/demobrowser/downloads.ui
diff --git a/examples/webenginewidgets/browser/edittableview.cpp b/examples/webenginewidgets/demobrowser/edittableview.cpp
index 866ee6f1f..866ee6f1f 100644
--- a/examples/webenginewidgets/browser/edittableview.cpp
+++ b/examples/webenginewidgets/demobrowser/edittableview.cpp
diff --git a/examples/webenginewidgets/browser/edittableview.h b/examples/webenginewidgets/demobrowser/edittableview.h
index 315427eac..315427eac 100644
--- a/examples/webenginewidgets/browser/edittableview.h
+++ b/examples/webenginewidgets/demobrowser/edittableview.h
diff --git a/examples/webenginewidgets/browser/edittreeview.cpp b/examples/webenginewidgets/demobrowser/edittreeview.cpp
index d515ea058..d515ea058 100644
--- a/examples/webenginewidgets/browser/edittreeview.cpp
+++ b/examples/webenginewidgets/demobrowser/edittreeview.cpp
diff --git a/examples/webenginewidgets/browser/edittreeview.h b/examples/webenginewidgets/demobrowser/edittreeview.h
index 1cf87d54f..1cf87d54f 100644
--- a/examples/webenginewidgets/browser/edittreeview.h
+++ b/examples/webenginewidgets/demobrowser/edittreeview.h
diff --git a/examples/webenginewidgets/browser/featurepermissionbar.cpp b/examples/webenginewidgets/demobrowser/featurepermissionbar.cpp
index b7275dfc2..b7275dfc2 100644
--- a/examples/webenginewidgets/browser/featurepermissionbar.cpp
+++ b/examples/webenginewidgets/demobrowser/featurepermissionbar.cpp
diff --git a/examples/webenginewidgets/browser/featurepermissionbar.h b/examples/webenginewidgets/demobrowser/featurepermissionbar.h
index 1bfe1b483..1bfe1b483 100644
--- a/examples/webenginewidgets/browser/featurepermissionbar.h
+++ b/examples/webenginewidgets/demobrowser/featurepermissionbar.h
diff --git a/examples/webenginewidgets/demobrowser/fullscreennotification.cpp b/examples/webenginewidgets/demobrowser/fullscreennotification.cpp
new file mode 100644
index 000000000..8ee968bec
--- /dev/null
+++ b/examples/webenginewidgets/demobrowser/fullscreennotification.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the demonstration applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "fullscreennotification.h"
+
+#include <QApplication>
+#include <QDesktopWidget>
+#include <QGridLayout>
+#include <QLabel>
+#include <QPropertyAnimation>
+#include <QTimer>
+
+FullScreenNotification::FullScreenNotification(QWidget *parent)
+ : QWidget(parent)
+ , width(400)
+ , height(80)
+ , x((parent->geometry().width() - width) / 2)
+ , y(80)
+{
+ setVisible(false);
+ setWindowFlags(Qt::ToolTip | Qt::WindowDoesNotAcceptFocus);
+
+ QGridLayout *layout = new QGridLayout(this);
+
+ m_label = new QLabel(tr("You are now in fullscreen mode. Press ESC to quit!"), this);
+ layout->addWidget(m_label, 0, 0, 0, 0, Qt::AlignHCenter | Qt::AlignVCenter);
+
+ setGeometry(x, y, width, height);
+
+ setStyleSheet("background-color: white;\
+ color: black;");
+
+ m_animation = new QPropertyAnimation(this, "windowOpacity");
+ connect(m_animation, SIGNAL(finished()), this, SLOT(fadeOutFinished()));
+}
+
+FullScreenNotification::~FullScreenNotification()
+{
+}
+
+void FullScreenNotification::show()
+{
+ setWindowOpacity(1.0);
+ QTimer::singleShot(300, [&] {
+ QWidget *parent = parentWidget();
+ x = (parent->geometry().width() - width) / 2;
+ QPoint topLeft = parent->mapToGlobal(QPoint(x, y));
+ QWidget::move(topLeft.x(), topLeft.y());
+ QWidget::show();
+ QWidget::raise();
+ });
+ QTimer::singleShot(5000, this, SLOT(fadeOut()));
+}
+
+void FullScreenNotification::hide()
+{
+ QWidget::hide();
+ m_animation->stop();
+}
+
+void FullScreenNotification::fadeOut()
+{
+ m_animation->setDuration(800);
+ m_animation->setStartValue(1.0);
+ m_animation->setEndValue(0.0);
+ m_animation->setEasingCurve(QEasingCurve::OutQuad);
+ m_animation->start();
+}
+
+void FullScreenNotification::fadeOutFinished()
+{
+ hide();
+ setWindowOpacity(1.0);
+}
diff --git a/examples/webenginewidgets/demobrowser/fullscreennotification.h b/examples/webenginewidgets/demobrowser/fullscreennotification.h
new file mode 100644
index 000000000..051075ab3
--- /dev/null
+++ b/examples/webenginewidgets/demobrowser/fullscreennotification.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the demonstration applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FULLSCREENNOTIFICATION_H
+#define FULLSCREENNOTIFICATION_H
+
+#include <QWidget>
+
+class QLabel;
+class QGridLayout;
+class QPropertyAnimation;
+
+class FullScreenNotification : public QWidget
+{
+ Q_OBJECT
+public:
+ FullScreenNotification(QWidget *parent = 0);
+ ~FullScreenNotification();
+
+ void show();
+ void hide();
+
+public slots:
+ void fadeOut();
+ void fadeOutFinished();
+
+private:
+ QLabel *m_label;
+ QGridLayout *m_layout;
+ QPropertyAnimation *m_animation;
+ int width;
+ int height;
+ int x;
+ int y;
+};
+
+
+#endif // FULLSCREENNOTIFICATION_H
diff --git a/examples/webenginewidgets/browser/history.cpp b/examples/webenginewidgets/demobrowser/history.cpp
index ce104e982..ce104e982 100644
--- a/examples/webenginewidgets/browser/history.cpp
+++ b/examples/webenginewidgets/demobrowser/history.cpp
diff --git a/examples/webenginewidgets/browser/history.h b/examples/webenginewidgets/demobrowser/history.h
index bcb9c9b28..bcb9c9b28 100644
--- a/examples/webenginewidgets/browser/history.h
+++ b/examples/webenginewidgets/demobrowser/history.h
diff --git a/examples/webenginewidgets/browser/history.ui b/examples/webenginewidgets/demobrowser/history.ui
index 0944940e7..0944940e7 100644
--- a/examples/webenginewidgets/browser/history.ui
+++ b/examples/webenginewidgets/demobrowser/history.ui
diff --git a/examples/webenginewidgets/browser/htmls/htmls.qrc b/examples/webenginewidgets/demobrowser/htmls/htmls.qrc
index 03b256ccb..03b256ccb 100644
--- a/examples/webenginewidgets/browser/htmls/htmls.qrc
+++ b/examples/webenginewidgets/demobrowser/htmls/htmls.qrc
diff --git a/examples/webenginewidgets/browser/htmls/notfound.html b/examples/webenginewidgets/demobrowser/htmls/notfound.html
index e89845aa6..e89845aa6 100644
--- a/examples/webenginewidgets/browser/htmls/notfound.html
+++ b/examples/webenginewidgets/demobrowser/htmls/notfound.html
diff --git a/examples/webenginewidgets/browser/main.cpp b/examples/webenginewidgets/demobrowser/main.cpp
index 86859f741..86859f741 100644
--- a/examples/webenginewidgets/browser/main.cpp
+++ b/examples/webenginewidgets/demobrowser/main.cpp
diff --git a/examples/webenginewidgets/browser/modelmenu.cpp b/examples/webenginewidgets/demobrowser/modelmenu.cpp
index ec0eaffab..ec0eaffab 100644
--- a/examples/webenginewidgets/browser/modelmenu.cpp
+++ b/examples/webenginewidgets/demobrowser/modelmenu.cpp
diff --git a/examples/webenginewidgets/browser/modelmenu.h b/examples/webenginewidgets/demobrowser/modelmenu.h
index c0a7d56b8..c0a7d56b8 100644
--- a/examples/webenginewidgets/browser/modelmenu.h
+++ b/examples/webenginewidgets/demobrowser/modelmenu.h
diff --git a/examples/webenginewidgets/browser/passworddialog.ui b/examples/webenginewidgets/demobrowser/passworddialog.ui
index 7c1665867..7c1665867 100644
--- a/examples/webenginewidgets/browser/passworddialog.ui
+++ b/examples/webenginewidgets/demobrowser/passworddialog.ui
diff --git a/examples/webenginewidgets/browser/proxy.ui b/examples/webenginewidgets/demobrowser/proxy.ui
index 62a8be627..62a8be627 100644
--- a/examples/webenginewidgets/browser/proxy.ui
+++ b/examples/webenginewidgets/demobrowser/proxy.ui
diff --git a/examples/webenginewidgets/browser/searchlineedit.cpp b/examples/webenginewidgets/demobrowser/searchlineedit.cpp
index 5152ac1c0..5152ac1c0 100644
--- a/examples/webenginewidgets/browser/searchlineedit.cpp
+++ b/examples/webenginewidgets/demobrowser/searchlineedit.cpp
diff --git a/examples/webenginewidgets/browser/searchlineedit.h b/examples/webenginewidgets/demobrowser/searchlineedit.h
index b8b8337fd..b8b8337fd 100644
--- a/examples/webenginewidgets/browser/searchlineedit.h
+++ b/examples/webenginewidgets/demobrowser/searchlineedit.h
diff --git a/examples/webenginewidgets/browser/settings.cpp b/examples/webenginewidgets/demobrowser/settings.cpp
index 7ed5f707b..35e5e26c9 100644
--- a/examples/webenginewidgets/browser/settings.cpp
+++ b/examples/webenginewidgets/demobrowser/settings.cpp
@@ -47,9 +47,9 @@
#include "cookiejar.h"
#endif
#include "history.h"
-#include "networkaccessmanager.h"
#include "webview.h"
+#include <QtCore/QLocale>
#include <QtCore/QSettings>
#include <QtWidgets/QtWidgets>
#include <QtWebEngineWidgets/QtWebEngineWidgets>
@@ -66,6 +66,21 @@ SettingsDialog::SettingsDialog(QWidget *parent)
loadFromSettings();
}
+static QString defaultAcceptLanguage()
+{
+ const QStringList langs = QLocale().uiLanguages();
+ if (langs.isEmpty())
+ return QString();
+ QString str = langs.first();
+ const float qstep = 1.0f / float(langs.count());
+ float q = 1.0f - qstep;
+ for (int i = 1; i < langs.count(); ++i) {
+ str += QStringLiteral(", ") + langs.at(i) + QStringLiteral(";q=") + QString::number(q, 'f', 2);
+ q -= qstep;
+ }
+ return str;
+}
+
void SettingsDialog::loadDefaults()
{
QWebEngineSettings *defaultSettings = QWebEngineSettings::globalSettings();
@@ -82,15 +97,14 @@ void SettingsDialog::loadDefaults()
downloadsLocation->setText(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation));
enableJavascript->setChecked(defaultSettings->testAttribute(QWebEngineSettings::JavascriptEnabled));
-#if defined(QTWEBENGINE_PLUGINS)
enablePlugins->setChecked(defaultSettings->testAttribute(QWebEngineSettings::PluginsEnabled));
-#endif
enableScrollAnimator->setChecked(defaultSettings->testAttribute(QWebEngineSettings::ScrollAnimatorEnabled));
persistentDataPath->setText(QWebEngineProfile::defaultProfile()->persistentStoragePath());
sessionCookiesCombo->setCurrentIndex(QWebEngineProfile::defaultProfile()->persistentCookiesPolicy());
httpUserAgent->setText(QWebEngineProfile::defaultProfile()->httpUserAgent());
+ httpAcceptLanguage->setText(defaultAcceptLanguage());
}
void SettingsDialog::loadFromSettings()
@@ -140,6 +154,7 @@ void SettingsDialog::loadFromSettings()
userStyleSheet->setPlainText(settings.value(QLatin1String("userStyleSheet")).toString());
enableScrollAnimator->setChecked(settings.value(QLatin1String("enableScrollAnimator"), enableScrollAnimator->isChecked()).toBool());
httpUserAgent->setText(settings.value(QLatin1String("httpUserAgent"), httpUserAgent->text()).toString());
+ httpAcceptLanguage->setText(settings.value(QLatin1String("httpAcceptLanguage"), httpAcceptLanguage->text()).toString());
settings.endGroup();
// Privacy
@@ -198,6 +213,7 @@ void SettingsDialog::saveToSettings()
settings.setValue(QLatin1String("enableScrollAnimator"), enableScrollAnimator->isChecked());
settings.setValue(QLatin1String("userStyleSheet"), userStyleSheet->toPlainText());
settings.setValue(QLatin1String("httpUserAgent"), httpUserAgent->text());
+ settings.setValue(QLatin1String("httpAcceptLanguage"), httpAcceptLanguage->text());
settings.endGroup();
//Privacy
@@ -223,7 +239,6 @@ void SettingsDialog::saveToSettings()
BrowserApplication::instance()->loadSettings();
#if defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER)
- BrowserApplication::networkAccessManager()->loadSettings();
BrowserApplication::cookieJar()->loadSettings();
#endif
BrowserApplication::historyManager()->loadSettings();
@@ -271,6 +286,16 @@ void SettingsDialog::chooseFixedFont()
}
}
+void SettingsDialog::on_httpUserAgent_editingFinished()
+{
+ QWebEngineProfile::defaultProfile()->setHttpUserAgent(httpUserAgent->text());
+}
+
+void SettingsDialog::on_httpAcceptLanguage_editingFinished()
+{
+ QWebEngineProfile::defaultProfile()->setHttpAcceptLanguage(httpAcceptLanguage->text());
+}
+
void SettingsDialog::setHomeToCurrentPage()
{
BrowserMainWindow *mw = static_cast<BrowserMainWindow*>(parent());
diff --git a/examples/webenginewidgets/browser/settings.h b/examples/webenginewidgets/demobrowser/settings.h
index 6def66928..3a50dd29f 100644
--- a/examples/webenginewidgets/browser/settings.h
+++ b/examples/webenginewidgets/demobrowser/settings.h
@@ -65,6 +65,9 @@ private slots:
void chooseFont();
void chooseFixedFont();
+ void on_httpUserAgent_editingFinished();
+ void on_httpAcceptLanguage_editingFinished();
+
private:
QFont standardFont;
QFont fixedFont;
diff --git a/examples/webenginewidgets/browser/settings.ui b/examples/webenginewidgets/demobrowser/settings.ui
index 11bdee4d3..38a7af344 100644
--- a/examples/webenginewidgets/browser/settings.ui
+++ b/examples/webenginewidgets/demobrowser/settings.ui
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>657</width>
- <height>322</height>
+ <height>336</height>
</rect>
</property>
<property name="windowTitle">
@@ -499,19 +499,29 @@
<string>Advanced</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_2">
- <item row="2" column="1">
- <widget class="QTextEdit" name="userStyleSheet"/>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_15">
+ <property name="text">
+ <string>HTTP User-Agent:</string>
+ </property>
+ </widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="httpUserAgent"/>
</item>
- <item row="0" column="0">
- <widget class="QLabel" name="label_15">
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_16">
<property name="text">
- <string>HTTP User-Agent:</string>
+ <string>HTTP Accept-&amp;Language:</string>
+ </property>
+ <property name="buddy">
+ <cstring>httpAcceptLanguage</cstring>
</property>
</widget>
</item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="httpAcceptLanguage"/>
+ </item>
<item row="2" column="0">
<widget class="QLabel" name="label_14">
<property name="text">
@@ -519,7 +529,10 @@
</property>
</widget>
</item>
- <item row="4" column="1">
+ <item row="2" column="1">
+ <widget class="QTextEdit" name="userStyleSheet"/>
+ </item>
+ <item row="3" column="1">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
diff --git a/examples/webenginewidgets/browser/squeezelabel.cpp b/examples/webenginewidgets/demobrowser/squeezelabel.cpp
index 78198c3f0..78198c3f0 100644
--- a/examples/webenginewidgets/browser/squeezelabel.cpp
+++ b/examples/webenginewidgets/demobrowser/squeezelabel.cpp
diff --git a/examples/webenginewidgets/browser/squeezelabel.h b/examples/webenginewidgets/demobrowser/squeezelabel.h
index 628b7350a..628b7350a 100644
--- a/examples/webenginewidgets/browser/squeezelabel.h
+++ b/examples/webenginewidgets/demobrowser/squeezelabel.h
diff --git a/examples/webenginewidgets/browser/tabwidget.cpp b/examples/webenginewidgets/demobrowser/tabwidget.cpp
index c093b804a..95b79aaac 100644
--- a/examples/webenginewidgets/browser/tabwidget.cpp
+++ b/examples/webenginewidgets/demobrowser/tabwidget.cpp
@@ -44,14 +44,16 @@
#include "browserapplication.h"
#include "browsermainwindow.h"
#include "downloadmanager.h"
+#include "fullscreennotification.h"
#include "history.h"
#include "urllineedit.h"
#include "webview.h"
+#include <QWebEngineDownloadItem>
+#include <QWebEngineProfile>
+#include <QWebEngineFullScreenRequest>
#include <QtCore/QMimeData>
#include <QtGui/QClipboard>
-#include <QtWebEngineWidgets/QWebEngineDownloadItem>
-#include <QtWebEngineWidgets/QWebEngineProfile>
#include <QtWidgets/QCompleter>
#include <QtWidgets/QListView>
#include <QtWidgets/QMenu>
@@ -85,6 +87,12 @@ TabBar::TabBar(QWidget *parent)
setMovable(true);
}
+TabWidget::~TabWidget()
+{
+ delete m_fullScreenNotification;
+ delete m_fullScreenView;
+}
+
void TabBar::selectTabAction()
{
if (QShortcut *shortCut = qobject_cast<QShortcut*>(sender())) {
@@ -213,11 +221,13 @@ TabWidget::TabWidget(QWidget *parent)
, m_lineEdits(0)
, m_tabBar(new TabBar(this))
, m_profile(QWebEngineProfile::defaultProfile())
+ , m_fullScreenView(0)
+ , m_fullScreenNotification(0)
{
setElideMode(Qt::ElideRight);
connect(m_tabBar, SIGNAL(newTab()), this, SLOT(newTab()));
- connect(m_tabBar, SIGNAL(closeTab(int)), this, SLOT(closeTab(int)));
+ connect(m_tabBar, SIGNAL(closeTab(int)), this, SLOT(requestCloseTab(int)));
connect(m_tabBar, SIGNAL(cloneTab(int)), this, SLOT(cloneTab(int)));
connect(m_tabBar, SIGNAL(closeOtherTabs(int)), this, SLOT(closeOtherTabs(int)));
connect(m_tabBar, SIGNAL(reloadTab(int)), this, SLOT(reloadTab(int)));
@@ -235,7 +245,7 @@ TabWidget::TabWidget(QWidget *parent)
m_closeTabAction = new QAction(QIcon(QLatin1String(":closetab.png")), tr("&Close Tab"), this);
m_closeTabAction->setShortcuts(QKeySequence::Close);
m_closeTabAction->setIconVisibleInMenu(false);
- connect(m_closeTabAction, SIGNAL(triggered()), this, SLOT(closeTab()));
+ connect(m_closeTabAction, SIGNAL(triggered()), this, SLOT(requestCloseTab()));
m_nextTabAction = new QAction(tr("Show Next Tab"), this);
QList<QKeySequence> shortcuts;
@@ -315,6 +325,8 @@ void TabWidget::currentChanged(int index)
this, SIGNAL(loadProgress(int)));
disconnect(oldWebView->page()->profile(), SIGNAL(downloadRequested(QWebEngineDownloadItem*)),
this, SLOT(downloadRequested(QWebEngineDownloadItem*)));
+ disconnect(oldWebView->page(), SIGNAL(fullScreenRequested(QWebEngineFullScreenRequest)),
+ this, SLOT(fullScreenRequested(QWebEngineFullScreenRequest)));
}
#if defined(QWEBENGINEVIEW_STATUSBARMESSAGE)
@@ -327,6 +339,8 @@ void TabWidget::currentChanged(int index)
this, SIGNAL(loadProgress(int)));
connect(webView->page()->profile(), SIGNAL(downloadRequested(QWebEngineDownloadItem*)),
this, SLOT(downloadRequested(QWebEngineDownloadItem*)));
+ connect(webView->page(), SIGNAL(fullScreenRequested(QWebEngineFullScreenRequest)),
+ this, SLOT(fullScreenRequested(QWebEngineFullScreenRequest)));
for (int i = 0; i < m_actions.count(); ++i) {
WebActionMapper *mapper = m_actions[i];
@@ -342,6 +356,38 @@ void TabWidget::currentChanged(int index)
webView->setFocus();
}
+void TabWidget::fullScreenRequested(QWebEngineFullScreenRequest request)
+{
+ WebPage *webPage = qobject_cast<WebPage*>(sender());
+ if (request.toggleOn()) {
+ if (!m_fullScreenView) {
+ m_fullScreenView = new QWebEngineView();
+ m_fullScreenNotification = new FullScreenNotification(m_fullScreenView);
+
+ QAction *exitFullScreenAction = new QAction(m_fullScreenView);
+ exitFullScreenAction->setShortcut(Qt::Key_Escape);
+ connect(exitFullScreenAction, &QAction::triggered, [webPage] {
+ webPage->triggerAction(QWebEnginePage::ExitFullScreen);
+ });
+ m_fullScreenView->addAction(exitFullScreenAction);
+ }
+ webPage->setView(m_fullScreenView);
+ request.accept();
+ m_fullScreenView->showFullScreen();
+ m_fullScreenView->raise();
+ m_fullScreenNotification->show();
+ } else {
+ if (!m_fullScreenView)
+ return;
+ WebView *oldWebView = this->webView(m_lineEdits->currentIndex());
+ webPage->setView(oldWebView);
+ request.accept();
+ raise();
+ m_fullScreenView->hide();
+ m_fullScreenNotification->hide();
+ }
+}
+
QAction *TabWidget::newTabAction() const
{
return m_newTabAction;
@@ -522,12 +568,8 @@ void TabWidget::windowCloseRequested()
WebPage *webPage = qobject_cast<WebPage*>(sender());
WebView *webView = qobject_cast<WebView*>(webPage->view());
int index = webViewIndex(webView);
- if (index >= 0) {
- if (count() == 1)
- webView->webPage()->mainWindow()->close();
- else
- closeTab(index);
- }
+ if (index >= 0)
+ closeTab(index);
}
void TabWidget::closeOtherTabs(int index)
@@ -552,30 +594,25 @@ void TabWidget::cloneTab(int index)
}
// When index is -1 index chooses the current tab
-void TabWidget::closeTab(int index)
+void TabWidget::requestCloseTab(int index)
{
if (index < 0)
index = currentIndex();
if (index < 0 || index >= count())
return;
+ WebView *tab = webView(index);
+ if (!tab)
+ return;
+ tab->page()->triggerAction(QWebEnginePage::RequestClose);
+}
+
+void TabWidget::closeTab(int index)
+{
+ if (index < 0 || index >= count())
+ return;
bool hasFocus = false;
if (WebView *tab = webView(index)) {
-#if defined(QWEBENGINEPAGE_ISMODIFIED)
- if (tab->isModified()) {
- QMessageBox closeConfirmation(tab);
- closeConfirmation.setWindowFlags(Qt::Sheet);
- closeConfirmation.setWindowTitle(tr("Do you really want to close this page?"));
- closeConfirmation.setInformativeText(tr("You have modified this page and when closing it you would lose the modification.\n"
- "Do you really want to close this page?\n"));
- closeConfirmation.setIcon(QMessageBox::Question);
- closeConfirmation.addButton(QMessageBox::Yes);
- closeConfirmation.addButton(QMessageBox::No);
- closeConfirmation.setEscapeButton(QMessageBox::No);
- if (closeConfirmation.exec() == QMessageBox::No)
- return;
- }
-#endif
hasFocus = tab->hasFocus();
if (m_profile == QWebEngineProfile::defaultProfile()) {
diff --git a/examples/webenginewidgets/browser/tabwidget.h b/examples/webenginewidgets/demobrowser/tabwidget.h
index 5d7f1e2c5..b00131130 100644
--- a/examples/webenginewidgets/browser/tabwidget.h
+++ b/examples/webenginewidgets/demobrowser/tabwidget.h
@@ -42,13 +42,14 @@
#ifndef TABWIDGET_H
#define TABWIDGET_H
+#include <QtWebEngineWidgets/QWebEngineFullScreenRequest>
#include <QtWidgets/QTabBar>
-
#include <QtWidgets/QShortcut>
QT_BEGIN_NAMESPACE
class QWebEngineDownloadItem;
class QWebEngineProfile;
+class QWebEngineView;
QT_END_NAMESPACE
/*
@@ -128,6 +129,7 @@ private:
#include <QtCore/QUrl>
#include <QtWidgets/QTabWidget>
QT_BEGIN_NAMESPACE
+class FullScreenNotification;
class QCompleter;
class QLineEdit;
class QMenu;
@@ -164,6 +166,7 @@ signals:
public:
TabWidget(QWidget *parent = 0);
+ ~TabWidget();
void clear();
void addWebAction(QAction *action, QWebEnginePage::WebAction webAction);
@@ -194,7 +197,8 @@ public slots:
void loadUrlInCurrentTab(const QUrl &url);
WebView *newTab(bool makeCurrent = true);
void cloneTab(int index = -1);
- void closeTab(int index = -1);
+ void requestCloseTab(int index = -1);
+ void closeTab(int index);
void closeOtherTabs(int index);
void reloadTab(int index = -1);
void reloadAllTabs();
@@ -213,6 +217,7 @@ private slots:
void lineEditReturnPressed();
void windowCloseRequested();
void moveTab(int fromIndex, int toIndex);
+ void fullScreenRequested(QWebEngineFullScreenRequest request);
private:
QAction *m_recentlyClosedTabsAction;
@@ -230,6 +235,8 @@ private:
QStackedWidget *m_lineEdits;
TabBar *m_tabBar;
QWebEngineProfile *m_profile;
+ QWebEngineView *m_fullScreenView;
+ FullScreenNotification *m_fullScreenNotification;
};
#endif // TABWIDGET_H
diff --git a/examples/webenginewidgets/browser/toolbarsearch.cpp b/examples/webenginewidgets/demobrowser/toolbarsearch.cpp
index 42cdaec18..42cdaec18 100644
--- a/examples/webenginewidgets/browser/toolbarsearch.cpp
+++ b/examples/webenginewidgets/demobrowser/toolbarsearch.cpp
diff --git a/examples/webenginewidgets/browser/toolbarsearch.h b/examples/webenginewidgets/demobrowser/toolbarsearch.h
index cbe00366c..cbe00366c 100644
--- a/examples/webenginewidgets/browser/toolbarsearch.h
+++ b/examples/webenginewidgets/demobrowser/toolbarsearch.h
diff --git a/examples/webenginewidgets/browser/urllineedit.cpp b/examples/webenginewidgets/demobrowser/urllineedit.cpp
index 685277d9c..685277d9c 100644
--- a/examples/webenginewidgets/browser/urllineedit.cpp
+++ b/examples/webenginewidgets/demobrowser/urllineedit.cpp
diff --git a/examples/webenginewidgets/browser/urllineedit.h b/examples/webenginewidgets/demobrowser/urllineedit.h
index 775aa7d18..775aa7d18 100644
--- a/examples/webenginewidgets/browser/urllineedit.h
+++ b/examples/webenginewidgets/demobrowser/urllineedit.h
diff --git a/examples/webenginewidgets/browser/webview.cpp b/examples/webenginewidgets/demobrowser/webview.cpp
index 99986642e..79a6cf344 100644
--- a/examples/webenginewidgets/browser/webview.cpp
+++ b/examples/webenginewidgets/demobrowser/webview.cpp
@@ -44,7 +44,6 @@
#include "cookiejar.h"
#include "downloadmanager.h"
#include "featurepermissionbar.h"
-#include "networkaccessmanager.h"
#include "ui_passworddialog.h"
#include "ui_proxy.h"
#include "tabwidget.h"
@@ -67,12 +66,12 @@
#include <QtCore/QDebug>
#include <QtCore/QBuffer>
+#include <QtCore/QTimer>
WebPage::WebPage(QWebEngineProfile *profile, QObject *parent)
: QWebEnginePage(profile, parent)
, m_keyboardModifiers(Qt::NoModifier)
, m_pressedButtons(Qt::NoButton)
- , m_openInNewTab(false)
{
#if defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER)
setNetworkAccessManager(BrowserApplication::networkAccessManager());
@@ -175,8 +174,7 @@ private:
QWebEnginePage *WebPage::createWindow(QWebEnginePage::WebWindowType type)
{
- if (m_openInNewTab || type == QWebEnginePage::WebBrowserTab) {
- m_openInNewTab = false;
+ if (type == QWebEnginePage::WebBrowserTab) {
return mainWindow()->tabWidget()->newTab()->page();
} else if (type == QWebEnginePage::WebBrowserWindow) {
BrowserApplication::instance()->newMainWindow();
@@ -274,8 +272,14 @@ void WebPage::authenticationRequired(const QUrl &requestUrl, QAuthenticator *aut
passwordDialog.introLabel->setWordWrap(true);
if (dialog.exec() == QDialog::Accepted) {
+ QByteArray key = BrowserApplication::authenticationKey(requestUrl, auth->realm());
auth->setUser(passwordDialog.userNameLineEdit->text());
auth->setPassword(passwordDialog.passwordLineEdit->text());
+ auth->setOption("key", key);
+ BrowserApplication::instance()->setLastAuthenticator(auth);
+ } else {
+ // Set authenticator null if dialog is cancelled
+ *auth = QAuthenticator();
}
}
@@ -299,8 +303,15 @@ void WebPage::proxyAuthenticationRequired(const QUrl &requestUrl, QAuthenticator
proxyDialog.introLabel->setWordWrap(true);
if (dialog.exec() == QDialog::Accepted) {
- auth->setUser(proxyDialog.userNameLineEdit->text());
+ QString user = proxyDialog.userNameLineEdit->text();
+ QByteArray key = BrowserApplication::proxyAuthenticationKey(user, proxyHost, auth->realm());
+ auth->setUser(user);
auth->setPassword(proxyDialog.passwordLineEdit->text());
+ auth->setOption("key", key);
+ BrowserApplication::instance()->setLastProxyAuthenticator(auth);
+ } else {
+ // Set authenticator null if dialog is cancelled
+ *auth = QAuthenticator();
}
}
@@ -314,6 +325,27 @@ WebView::WebView(QWidget* parent)
this, SLOT(setProgress(int)));
connect(this, SIGNAL(loadFinished(bool)),
this, SLOT(loadFinished(bool)));
+ connect(this, &QWebEngineView::renderProcessTerminated,
+ [=](QWebEnginePage::RenderProcessTerminationStatus termStatus, int statusCode) {
+ const char *status = "";
+ switch (termStatus) {
+ case QWebEnginePage::NormalTerminationStatus:
+ status = "(normal exit)";
+ break;
+ case QWebEnginePage::AbnormalTerminationStatus:
+ status = "(abnormal exit)";
+ break;
+ case QWebEnginePage::CrashedTerminationStatus:
+ status = "(crashed)";
+ break;
+ case QWebEnginePage::KilledTerminationStatus:
+ status = "(killed)";
+ break;
+ }
+
+ qInfo() << "Render process exited with code" << statusCode << status;
+ QTimer::singleShot(0, [this] { reload(); });
+ });
}
void WebView::setPage(WebPage *_page)
@@ -338,24 +370,17 @@ void WebView::setPage(WebPage *_page)
void WebView::contextMenuEvent(QContextMenuEvent *event)
{
-#if defined(QWEBENGINEPAGE_HITTESTCONTENT)
- QWebEngineHitTestResult r = page()->hitTestContent(event->pos());
- if (!r.linkUrl().isEmpty()) {
- QMenu menu(this);
- menu.addAction(pageAction(QWebEnginePage::OpenLinkInNewWindow));
- menu.addAction(tr("Open in New Tab"), this, SLOT(openLinkInNewTab()));
- menu.addSeparator();
- menu.addAction(pageAction(QWebEnginePage::DownloadLinkToDisk));
- // Add link to bookmarks...
- menu.addSeparator();
- menu.addAction(pageAction(QWebEnginePage::CopyLinkToClipboard));
- if (page()->settings()->testAttribute(QWebEngineSettings::DeveloperExtrasEnabled))
- menu.addAction(pageAction(QWebEnginePage::InspectElement));
- menu.exec(mapToGlobal(event->pos()));
- return;
+ QMenu *menu = page()->createStandardContextMenu();
+ const QList<QAction*> actions = menu->actions();
+ QList<QAction*>::const_iterator it = qFind(actions.cbegin(), actions.cend(), page()->action(QWebEnginePage::OpenLinkInThisWindow));
+ if (it != actions.cend()) {
+ (*it)->setText(tr("Open Link in This Window"));
+ ++it;
+ menu->insertAction(*it, page()->action(QWebEnginePage::OpenLinkInNewWindow));
+ menu->insertAction(*it, page()->action(QWebEnginePage::OpenLinkInNewTab));
}
-#endif
- QWebEngineView::contextMenuEvent(event);
+
+ menu->popup(event->globalPos());
}
void WebView::wheelEvent(QWheelEvent *event)
@@ -374,10 +399,7 @@ void WebView::wheelEvent(QWheelEvent *event)
void WebView::openLinkInNewTab()
{
-#if defined(QWEBENGINEPAGE_WEBACTION_OPENLINKINNEWWINDOW)
- m_page->m_openInNewTab = true;
- pageAction(QWebEnginePage::OpenLinkInNewWindow)->trigger();
-#endif
+ pageAction(QWebEnginePage::OpenLinkInNewTab)->trigger();
}
void WebView::onFeaturePermissionRequested(const QUrl &securityOrigin, QWebEnginePage::Feature feature)
diff --git a/examples/webenginewidgets/browser/webview.h b/examples/webenginewidgets/demobrowser/webview.h
index a147d780a..34188a259 100644
--- a/examples/webenginewidgets/browser/webview.h
+++ b/examples/webenginewidgets/demobrowser/webview.h
@@ -65,8 +65,8 @@ public:
BrowserMainWindow *mainWindow();
protected:
- bool acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame);
- QWebEnginePage *createWindow(QWebEnginePage::WebWindowType type);
+ bool acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame) Q_DECL_OVERRIDE;
+ QWebEnginePage *createWindow(QWebEnginePage::WebWindowType type) Q_DECL_OVERRIDE;
#if !defined(QT_NO_UITOOLS)
QObject *createPlugin(const QString &classId, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues);
#endif
@@ -85,7 +85,6 @@ private:
// set the webview mousepressedevent
Qt::KeyboardModifiers m_keyboardModifiers;
Qt::MouseButtons m_pressedButtons;
- bool m_openInNewTab;
QUrl m_loadingUrl;
};
diff --git a/examples/webenginewidgets/browser/xbel.cpp b/examples/webenginewidgets/demobrowser/xbel.cpp
index 6b4f53d2e..6b4f53d2e 100644
--- a/examples/webenginewidgets/browser/xbel.cpp
+++ b/examples/webenginewidgets/demobrowser/xbel.cpp
diff --git a/examples/webenginewidgets/browser/xbel.h b/examples/webenginewidgets/demobrowser/xbel.h
index d95549dd8..d95549dd8 100644
--- a/examples/webenginewidgets/browser/xbel.h
+++ b/examples/webenginewidgets/demobrowser/xbel.h
diff --git a/examples/webenginewidgets/fancybrowser/doc/src/fancybrowser.qdoc b/examples/webenginewidgets/fancybrowser/doc/src/fancybrowser.qdoc
index e6c6ada34..b798e4832 100644
--- a/examples/webenginewidgets/fancybrowser/doc/src/fancybrowser.qdoc
+++ b/examples/webenginewidgets/fancybrowser/doc/src/fancybrowser.qdoc
@@ -26,7 +26,7 @@
****************************************************************************/
/*!
- \example fancybrowser
+ \example webenginewidgets/fancybrowser
\title WebEngine Fancy Browser Example
\ingroup webengine-widgetexamples
\brief Demonstrates how to use browse web and manipulate content
@@ -48,7 +48,7 @@
The \c MainWindow class inherits QMainWindow. It implements a number of
slots to perform actions on both the application and on the web content.
- \snippet fancybrowser/mainwindow.h 1
+ \snippet webenginewidgets/fancybrowser/mainwindow.h 1
We also declare a QString that contains the jQuery, a QWebView
that displays the web content, and a QLineEdit that acts as the
@@ -58,7 +58,7 @@
We start by implementing the constructor.
- \snippet fancybrowser/mainwindow.cpp 1
+ \snippet webenginewidgets/fancybrowser/mainwindow.cpp 1
The first part of the constructor sets the value of \c progress to
0. This value will be used later in the code to visualize the
@@ -68,7 +68,7 @@
content. The jQuery library is a JavaScript library that provides different
functions for manipulating HTML.
- \snippet fancybrowser/mainwindow.cpp 2
+ \snippet webenginewidgets/fancybrowser/mainwindow.cpp 2
The second part of the constructor creates a QWebView and connects
slots to the views signals. Furthermore, we create a QLineEdit as
@@ -77,13 +77,13 @@
QLineEdit to a QToolbar together with a set of navigation actions
from QWebView::pageAction.
- \snippet fancybrowser/mainwindow.cpp 3
+ \snippet webenginewidgets/fancybrowser/mainwindow.cpp 3
The third and last part of the constructor implements two QMenus and assigns
a set of actions to them. The last line sets the QWebView as the central
widget in the QMainWindow.
- \snippet fancybrowser/mainwindow.cpp 4
+ \snippet webenginewidgets/fancybrowser/mainwindow.cpp 4
When the page is loaded, \c adjustLocation() updates the address
bar; \c adjustLocation() is triggered by the \c loadFinished()
@@ -92,13 +92,13 @@
the new web page has finished loading, \c adjustLocation() will be
run once more to update the address bar.
- \snippet fancybrowser/mainwindow.cpp 5
+ \snippet webenginewidgets/fancybrowser/mainwindow.cpp 5
\c adjustTitle() sets the window title and displays the loading
progress. This slot is triggered by the \c titleChanged() signal
in QWebView.
- \snippet fancybrowser/mainwindow.cpp 6
+ \snippet webenginewidgets/fancybrowser/mainwindow.cpp 6
When a web page has loaded, \c finishLoading() is triggered by the
\c loadFinished() signal in QWebView. \c finishLoading() then updates the
@@ -113,7 +113,7 @@
that the images of the newly loaded page respect the state of the toggle
action.
- \snippet fancybrowser/mainwindow.cpp 7
+ \snippet webenginewidgets/fancybrowser/mainwindow.cpp 7
The first jQuery-based function, \c highlightAllLinks(), is designed to
highlight all links in the current webpage. The JavaScript code looks
@@ -121,14 +121,14 @@
For each such element, the background color is set to be yellow by
using CSS.
- \snippet fancybrowser/mainwindow.cpp 8
+ \snippet webenginewidgets/fancybrowser/mainwindow.cpp 8
The \c rotateImages() function rotates the images on the current
web page. This JavaScript code relies on CSS transforms and
looks up all \e {img} elements and rotates the images 180 degrees
and then back again.
- \snippet fancybrowser/mainwindow.cpp 9
+ \snippet webenginewidgets/fancybrowser/mainwindow.cpp 9
The remaining four methods remove different elements from the current web
page. \c removeGifImages() removes all GIF images on the page by looking up
diff --git a/examples/webenginewidgets/markdowneditor/3RDPARTY.md b/examples/webenginewidgets/markdowneditor/3RDPARTY.md
new file mode 100644
index 000000000..9e91ab302
--- /dev/null
+++ b/examples/webenginewidgets/markdowneditor/3RDPARTY.md
@@ -0,0 +1,23 @@
+## markd license
+
+```
+Copyright (c) 2011-2014, Christopher Jeffrey (https://github.com/chjj/)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+```
diff --git a/examples/webenginewidgets/markdowneditor/doc/images/markdowneditor-example.png b/examples/webenginewidgets/markdowneditor/doc/images/markdowneditor-example.png
new file mode 100644
index 000000000..9f456c4db
--- /dev/null
+++ b/examples/webenginewidgets/markdowneditor/doc/images/markdowneditor-example.png
Binary files differ
diff --git a/examples/webenginewidgets/markdowneditor/doc/src/markdowneditor.qdoc b/examples/webenginewidgets/markdowneditor/doc/src/markdowneditor.qdoc
new file mode 100644
index 000000000..44b1246b3
--- /dev/null
+++ b/examples/webenginewidgets/markdowneditor/doc/src/markdowneditor.qdoc
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example webenginewidgets/markdowneditor
+ \title Markdown Editor Example
+ \ingroup webengine-widgetexamples
+ \brief Demonstrates how to integrate a web engine in a hybrid desktop
+ application.
+
+ \image markdowneditor-example.png
+
+ \e {Markdown Editor} demonstrates how to use QWebChannel and JavaScript
+ libraries to provide a rich text preview tool for a custom markup language.
+
+ \l{http://daringfireball.net/projects/markdown/}{Markdown} is a lightweight
+ markup language with a plain text formatting syntax.
+ Some services, such as \l{http://github.com}{github}, acknowledge the
+ format, and render the content as rich text when viewed in a browser.
+
+ The Markdown Editor main window is split into an editor and a preview area.
+ The editor supports the Markdown syntax and is implemented by using
+ QPlainTextEdit. The document is rendered as rich text in the preview area,
+ which is implemented by using QWebEngineView. To render the text, the
+ Markdown text is converted to HTML format with the help of a JavaScript
+ library inside the web engine. The preview is updated from the editor
+ through QWebChannel.
+
+ \include examples-run.qdocinc
+
+ \section1 Exposing Document Text
+
+ Because we expose the current Markdown text to be rendered to the web engine
+ through QWebChannel, we need to somehow make the current text available
+ through the Qt metatype system. This is done by using a dedicated
+ \c Document class that exposes the document text as a \c{Q_PROPERTY}:
+
+ \quotefromfile webenginewidgets/markdowneditor/document.h
+ \skipto class Document
+ \printto #endif
+
+ The \c Document class wraps a QString to be set on the C++ side with
+ the \c setText() method and exposes it at runtime as a \c text property
+ with a \c textChanged signal.
+
+ We define the \c setText method as follows:
+
+ \quotefromfile webenginewidgets/markdowneditor/document.cpp
+ \skipto Document::setText
+ \printuntil
+
+ \section1 Previewing Text
+
+ We implement our own \c PreviewPage class that publicly inherits from
+ \c QWebEnginePage:
+
+ \quotefromfile webenginewidgets/markdowneditor/previewpage.h
+ \skipto class PreviewPage
+ \printto #endif
+
+ We reimplement the virtual \c acceptNavigationRequest method to
+ stop the page from navigating away from the current document. Instead,
+ we redirect external links to the system browser:
+
+ \quotefromfile webenginewidgets/markdowneditor/previewpage.cpp
+ \skipto acceptNavigationRequest
+ \printuntil
+
+ \section1 Creating the Main Window
+
+ The \c MainWindow class inherits the QMainWindow class:
+
+ \quotefromfile webenginewidgets/markdowneditor/mainwindow.h
+ \skipto class MainWindow :
+ \printto endif
+
+ The class declares private slots that match the actions in the menu,
+ as well as the \c isModified() helper method.
+
+ The actual layout of the main window is specified in a \c .ui file.
+ The widgets and actions are available at runtime in the \c ui member
+ variable.
+
+ \c m_filePath holds the file path to the currently loaded document.
+ \c m_content is an instance of the \c Document class.
+
+ The actual setup of the different objects is done in the \c MainWindow
+ constructor:
+
+ \quotefromfile webenginewidgets/markdowneditor/mainwindow.cpp
+ \skipto MainWindow::MainWindow
+ \printto connect
+
+ The constructor first calls \c setupUi to construct the widgets and menu
+ actions according to the UI file. It then makes sure our custom
+ \c PreviewPage is used by the QWebEngineView instance in \c{ui->preview}.
+
+ \printto ui->preview
+
+ Here the \c textChanged signal of the editor is connected to a lambda that
+ updates the text in \c m_content. This object is then exposed to the JS side
+ by \c QWebChannel under the name \c{content}.
+
+ \printto connect
+
+ Now we can actually load the \e index.html file from the
+ resources. For more information about the file, see
+ \l{Creating an Index File}.
+
+ \printto defaultTextFile
+
+ The menu items are connected to the mapping member slots. The
+ \uicontrol Save item is activated or deactivated depending on whether
+ the user has edited the content.
+
+ \printuntil }
+
+ Finally, we load a default document \e default.md from the resources.
+
+ \section1 Creating an Index File
+
+ \quotefile webenginewidgets/markdowneditor/resources/index.html
+
+ In the \e index.html, we load a custom stylesheet and two JavaScript
+ libraries. \l{http://kevinburke.bitbucket.org/markdowncss/}{markdown.css} is
+ a markdown-friendly stylesheet created by Kevin Burke.
+ \l{https://github.com/chjj/marked}{marked.min.js} is a markdown parser and
+ compiler designed for speed written by Christopher Jeffrey and
+ \e qwebchannel.js is part of the \l{QWebChannel} module.
+
+ In the \c <body> element we first define a \c placeholder element, and
+ make it available as a JavaScript variable. We then define the \c updateText
+ helper method that updates the content of \c placeholder with the HTML
+ that the JavaScript method \c marked() returns.
+
+ Finally, we set up the web channel to access the \c content proxy object
+ and make sure that \c updateText() is called whenever \c content.text
+ changes.
+*/
+
diff --git a/examples/webenginewidgets/markdowneditor/document.cpp b/examples/webenginewidgets/markdowneditor/document.cpp
new file mode 100644
index 000000000..98665680c
--- /dev/null
+++ b/examples/webenginewidgets/markdowneditor/document.cpp
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the demonstration applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "document.h"
+
+void Document::setText(const QString &text)
+{
+ if (text == m_text)
+ return;
+ m_text = text;
+ emit textChanged(m_text);
+}
diff --git a/examples/webenginewidgets/markdowneditor/document.h b/examples/webenginewidgets/markdowneditor/document.h
new file mode 100644
index 000000000..d2f33ec81
--- /dev/null
+++ b/examples/webenginewidgets/markdowneditor/document.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the demonstration applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DOCUMENT_H
+#define DOCUMENT_H
+
+#include <QObject>
+#include <QString>
+
+class Document : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString text MEMBER m_text NOTIFY textChanged)
+public:
+ explicit Document(QObject *parent = nullptr) : QObject(parent) {}
+
+ void setText(const QString &text);
+
+signals:
+ void textChanged(const QString &text);
+
+private:
+ QString m_text;
+};
+
+#endif // DOCUMENT_H
diff --git a/examples/webenginewidgets/markdowneditor/main.cpp b/examples/webenginewidgets/markdowneditor/main.cpp
new file mode 100644
index 000000000..2cf4e1f60
--- /dev/null
+++ b/examples/webenginewidgets/markdowneditor/main.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the demonstration applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "document.h"
+#include "mainwindow.h"
+
+#include <QApplication>
+#include <QFile>
+
+int main(int argc, char *argv[])
+{
+ QApplication a(argc, argv);
+
+ MainWindow window;
+ window.show();
+
+ return a.exec();
+}
diff --git a/examples/webenginewidgets/markdowneditor/mainwindow.cpp b/examples/webenginewidgets/markdowneditor/mainwindow.cpp
new file mode 100644
index 000000000..fec7c661e
--- /dev/null
+++ b/examples/webenginewidgets/markdowneditor/mainwindow.cpp
@@ -0,0 +1,172 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the demonstration applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mainwindow.h"
+#include "previewpage.h"
+#include "ui_mainwindow.h"
+
+#include <QFile>
+#include <QFileDialog>
+#include <QMessageBox>
+#include <QTextStream>
+#include <QWebChannel>
+
+MainWindow::MainWindow(QWidget *parent) :
+ QMainWindow(parent),
+ ui(new Ui::MainWindow)
+{
+ ui->setupUi(this);
+
+ PreviewPage *page = new PreviewPage(this);
+ ui->preview->setPage(page);
+
+ connect(ui->editor, &QPlainTextEdit::textChanged,
+ [this]() { m_content.setText(ui->editor->toPlainText()); });
+
+ QWebChannel *channel = new QWebChannel(this);
+ channel->registerObject(QStringLiteral("content"), &m_content);
+ page->setWebChannel(channel);
+
+ ui->preview->setUrl(QUrl("qrc:/index.html"));
+
+ connect(ui->actionNew, &QAction::triggered, this, &MainWindow::onFileNew);
+ connect(ui->actionOpen, &QAction::triggered, this, &MainWindow::onFileOpen);
+ connect(ui->actionSave, &QAction::triggered, this, &MainWindow::onFileSave);
+ connect(ui->actionSaveAs, &QAction::triggered, this, &MainWindow::onFileSaveAs);
+ connect(ui->actionExit, &QAction::triggered, this, &MainWindow::onExit);
+
+ connect(ui->editor->document(), &QTextDocument::modificationChanged,
+ ui->actionSave, &QAction::setEnabled);
+
+ QFile defaultTextFile(":/default.md");
+ defaultTextFile.open(QIODevice::ReadOnly);
+ ui->editor->setPlainText(defaultTextFile.readAll());
+}
+
+MainWindow::~MainWindow()
+{
+ delete ui;
+}
+
+bool MainWindow::isModified() const
+{
+ return ui->editor->document()->isModified();
+}
+
+void MainWindow::onFileNew()
+{
+ if (isModified()) {
+ QMessageBox::StandardButton button = QMessageBox::question(this, windowTitle(),
+ tr("You have unsaved changes. Do you want to create a new document anyway?"));
+ if (button != QMessageBox::Yes)
+ return;
+ }
+
+ m_filePath.clear();
+ ui->editor->setPlainText(tr("## New document"));
+ ui->editor->document()->setModified(false);
+}
+
+void MainWindow::onFileOpen()
+{
+ if (isModified()) {
+ QMessageBox::StandardButton button = QMessageBox::question(this, windowTitle(),
+ tr("You have unsaved changes. Do you want to open a new document anyway?"));
+ if (button != QMessageBox::Yes)
+ return;
+ }
+
+ QString path = QFileDialog::getOpenFileName(this,
+ tr("Open MarkDown File"), "", tr("MarkDown File (*.md)"));
+ if (path.isEmpty())
+ return;
+
+ QFile f(path);
+ if (!f.open(QIODevice::ReadOnly)) {
+ QMessageBox::warning(this, windowTitle(),
+ tr("Could not open file %1: %2").arg(
+ QDir::toNativeSeparators(path), f.errorString()));
+ return;
+ }
+ m_filePath = path;
+ ui->editor->setPlainText(f.readAll());
+}
+
+void MainWindow::onFileSave()
+{
+ if (m_filePath.isEmpty()) {
+ onFileSaveAs();
+ return;
+ }
+
+ QFile f(m_filePath);
+ if (!f.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ QMessageBox::warning(this, windowTitle(),
+ tr("Could not write to file %1: %2").arg(
+ QDir::toNativeSeparators(m_filePath), f.errorString()));
+ return;
+ }
+ QTextStream str(&f);
+ str << ui->editor->toPlainText();
+
+ ui->editor->document()->setModified(false);
+}
+
+void MainWindow::onFileSaveAs()
+{
+ QString path = QFileDialog::getSaveFileName(this,
+ tr("Save MarkDown File"), "", tr("MarkDown File (*.md, *.markdown)"));
+ if (path.isEmpty())
+ return;
+ m_filePath = path;
+ onFileSave();
+}
+
+void MainWindow::onExit()
+{
+ if (isModified()) {
+ QMessageBox::StandardButton button = QMessageBox::question(this, windowTitle(),
+ tr("You have unsaved changes. Do you want to exit anyway?"));
+ if (button != QMessageBox::Yes)
+ return;
+ }
+ close();
+}
diff --git a/examples/webenginewidgets/markdowneditor/mainwindow.h b/examples/webenginewidgets/markdowneditor/mainwindow.h
new file mode 100644
index 000000000..6099f1f79
--- /dev/null
+++ b/examples/webenginewidgets/markdowneditor/mainwindow.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the demonstration applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include "document.h"
+
+#include <QMainWindow>
+#include <QString>
+
+namespace Ui {
+class MainWindow;
+}
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ explicit MainWindow(QWidget *parent = 0);
+ ~MainWindow();
+
+private slots:
+ void onFileNew();
+ void onFileOpen();
+ void onFileSave();
+ void onFileSaveAs();
+ void onExit();
+
+private:
+ bool isModified() const;
+
+ Ui::MainWindow *ui;
+ QString m_filePath;
+ Document m_content;
+};
+
+#endif // MAINWINDOW_H
diff --git a/examples/webenginewidgets/markdowneditor/mainwindow.ui b/examples/webenginewidgets/markdowneditor/mainwindow.ui
new file mode 100644
index 000000000..36ab352b7
--- /dev/null
+++ b/examples/webenginewidgets/markdowneditor/mainwindow.ui
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>800</width>
+ <height>600</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>MarkDown Editor</string>
+ </property>
+ <widget class="QWidget" name="centralwidget">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QSplitter" name="splitter">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <widget class="QPlainTextEdit" name="editor"/>
+ <widget class="QWebEngineView" name="preview" native="true"/>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QMenuBar" name="menubar">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>800</width>
+ <height>26</height>
+ </rect>
+ </property>
+ <widget class="QMenu" name="menu_File">
+ <property name="title">
+ <string>&amp;File</string>
+ </property>
+ <addaction name="actionNew"/>
+ <addaction name="actionOpen"/>
+ <addaction name="actionSave"/>
+ <addaction name="actionSaveAs"/>
+ <addaction name="separator"/>
+ <addaction name="actionExit"/>
+ </widget>
+ <addaction name="menu_File"/>
+ </widget>
+ <widget class="QStatusBar" name="statusbar"/>
+ <action name="actionOpen">
+ <property name="text">
+ <string>&amp;Open...</string>
+ </property>
+ <property name="toolTip">
+ <string>Open document</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+O</string>
+ </property>
+ </action>
+ <action name="actionSave">
+ <property name="text">
+ <string>&amp;Save</string>
+ </property>
+ <property name="toolTip">
+ <string>Save current document</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+S</string>
+ </property>
+ </action>
+ <action name="actionExit">
+ <property name="text">
+ <string>E&amp;xit</string>
+ </property>
+ <property name="toolTip">
+ <string>Exit editor</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+Q</string>
+ </property>
+ </action>
+ <action name="actionSaveAs">
+ <property name="text">
+ <string>Save &amp;As...</string>
+ </property>
+ <property name="toolTip">
+ <string>Save document under different name</string>
+ </property>
+ </action>
+ <action name="actionNew">
+ <property name="text">
+ <string>&amp;New</string>
+ </property>
+ <property name="toolTip">
+ <string>Create new document</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+N</string>
+ </property>
+ </action>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>QWebEngineView</class>
+ <extends>QWidget</extends>
+ <header>qwebengineview.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/examples/webenginewidgets/markdowneditor/markdowneditor.pro b/examples/webenginewidgets/markdowneditor/markdowneditor.pro
new file mode 100644
index 000000000..bfd16698a
--- /dev/null
+++ b/examples/webenginewidgets/markdowneditor/markdowneditor.pro
@@ -0,0 +1,28 @@
+TEMPLATE = app
+
+QT += webenginewidgets webchannel
+CONFIG += c++11
+
+HEADERS += \
+ mainwindow.h \
+ previewpage.h \
+ document.h
+
+SOURCES = \
+ main.cpp \
+ mainwindow.cpp \
+ previewpage.cpp \
+ document.cpp
+
+RESOURCES = \
+ resources/markdowneditor.qrc
+
+FORMS += \
+ mainwindow.ui
+
+DISTFILES += \
+ 3RDPARTY.md
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/webenginewidgets/markdowneditor
+INSTALLS += target
diff --git a/examples/webenginewidgets/markdowneditor/previewpage.cpp b/examples/webenginewidgets/markdowneditor/previewpage.cpp
new file mode 100644
index 000000000..2d4322664
--- /dev/null
+++ b/examples/webenginewidgets/markdowneditor/previewpage.cpp
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the demonstration applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "previewpage.h"
+
+#include <QDesktopServices>
+
+bool PreviewPage::acceptNavigationRequest(const QUrl &url,
+ QWebEnginePage::NavigationType /*type*/,
+ bool /*isMainFrame*/)
+{
+ // Only allow qrc:/index.html.
+ if (url.scheme() == QString("qrc"))
+ return true;
+ QDesktopServices::openUrl(url);
+ return false;
+}
diff --git a/examples/webenginewidgets/markdowneditor/previewpage.h b/examples/webenginewidgets/markdowneditor/previewpage.h
new file mode 100644
index 000000000..53b0e23e6
--- /dev/null
+++ b/examples/webenginewidgets/markdowneditor/previewpage.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the demonstration applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PREVIEWPAGE_H
+#define PREVIEWPAGE_H
+
+#include <QWebEnginePage>
+
+class PreviewPage : public QWebEnginePage
+{
+ Q_OBJECT
+public:
+ explicit PreviewPage(QObject *parent = nullptr) : QWebEnginePage(parent) {}
+
+protected:
+ bool acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame);
+};
+
+#endif // PREVIEWPAGE_H
diff --git a/examples/webenginewidgets/markdowneditor/resources/default.md b/examples/webenginewidgets/markdowneditor/resources/default.md
new file mode 100644
index 000000000..e5905b101
--- /dev/null
+++ b/examples/webenginewidgets/markdowneditor/resources/default.md
@@ -0,0 +1,12 @@
+## Markdown Editor Example
+
+This example uses [QWebEngineView](http://doc.qt.io/qt-5/qwebengineview.html)
+to preview text written using the [Markdown](https://en.wikipedia.org/wiki/Markdown)
+syntax.
+
+### Acknowledgments
+
+The conversion from Markdown to HTML is done with the help of the
+[marked JavaScript library](https://github.com/chjj/marked) by _Christopher Jeffrey_.
+The [style sheet](http://kevinburke.bitbucket.org/markdowncss/markdown.css)
+was created by _Kevin Burke_.
diff --git a/examples/webenginewidgets/markdowneditor/resources/index.html b/examples/webenginewidgets/markdowneditor/resources/index.html
new file mode 100644
index 000000000..2f45479ed
--- /dev/null
+++ b/examples/webenginewidgets/markdowneditor/resources/index.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<html lang="en">
+<meta charset="utf-8">
+<head>
+ <link rel="stylesheet" type="text/css" href="markdown.css">
+ <script src="marked.min.js"></script>
+ <script src="qwebchannel.js"></script>
+</head>
+<body>
+ <div id="placeholder"></div>
+ <script>
+ 'use strict';
+
+ var placeholder = document.getElementById('placeholder');
+
+ var updateText = function(text) {
+ placeholder.innerHTML = marked(text);
+ }
+
+ new QWebChannel(qt.webChannelTransport,
+ function(channel) {
+ var content = channel.objects.content;
+ updateText(content.text);
+ content.textChanged.connect(updateText);
+ }
+ );
+ </script>
+</body>
+</html>
+
+
+
diff --git a/examples/webenginewidgets/markdowneditor/resources/markdown.css b/examples/webenginewidgets/markdowneditor/resources/markdown.css
new file mode 100644
index 000000000..24fc2ffe2
--- /dev/null
+++ b/examples/webenginewidgets/markdowneditor/resources/markdown.css
@@ -0,0 +1,260 @@
+body{
+ margin: 0 auto;
+ font-family: Georgia, Palatino, serif;
+ color: #444444;
+ line-height: 1;
+ max-width: 960px;
+ padding: 30px;
+}
+h1, h2, h3, h4 {
+ color: #111111;
+ font-weight: 400;
+}
+h1, h2, h3, h4, h5, p {
+ margin-bottom: 24px;
+ padding: 0;
+}
+h1 {
+ font-size: 48px;
+}
+h2 {
+ font-size: 36px;
+ /* The bottom margin is small. It's designed to be used with gray meta text
+ * below a post title. */
+ margin: 24px 0 6px;
+}
+h3 {
+ font-size: 24px;
+}
+h4 {
+ font-size: 21px;
+}
+h5 {
+ font-size: 18px;
+}
+a {
+ color: #0099ff;
+ margin: 0;
+ padding: 0;
+ vertical-align: baseline;
+}
+a:hover {
+ text-decoration: none;
+ color: #ff6600;
+}
+a:visited {
+ color: purple;
+}
+ul, ol {
+ padding: 0;
+ margin: 0;
+}
+li {
+ line-height: 24px;
+}
+li ul, li ul {
+ margin-left: 24px;
+}
+p, ul, ol {
+ font-size: 16px;
+ line-height: 24px;
+ max-width: 540px;
+}
+pre {
+ padding: 0px 24px;
+ max-width: 800px;
+ white-space: pre-wrap;
+}
+code {
+ font-family: Consolas, Monaco, Andale Mono, monospace;
+ line-height: 1.5;
+ font-size: 13px;
+}
+aside {
+ display: block;
+ float: right;
+ width: 390px;
+}
+blockquote {
+ border-left:.5em solid #eee;
+ padding: 0 2em;
+ margin-left:0;
+ max-width: 476px;
+}
+blockquote cite {
+ font-size:14px;
+ line-height:20px;
+ color:#bfbfbf;
+}
+blockquote cite:before {
+ content: '\2014 \00A0';
+}
+
+blockquote p {
+ color: #666;
+ max-width: 460px;
+}
+hr {
+ width: 540px;
+ text-align: left;
+ margin: 0 auto 0 0;
+ color: #999;
+}
+
+/* Code below this line is copyright Twitter Inc. */
+
+button,
+input,
+select,
+textarea {
+ font-size: 100%;
+ margin: 0;
+ vertical-align: baseline;
+ *vertical-align: middle;
+}
+button, input {
+ line-height: normal;
+ *overflow: visible;
+}
+button::-moz-focus-inner, input::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+button,
+input[type="button"],
+input[type="reset"],
+input[type="submit"] {
+ cursor: pointer;
+ -webkit-appearance: button;
+}
+input[type=checkbox], input[type=radio] {
+ cursor: pointer;
+}
+/* override default chrome & firefox settings */
+input:not([type="image"]), textarea {
+ -webkit-box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+}
+
+input[type="search"] {
+ -webkit-appearance: textfield;
+ -webkit-box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+}
+input[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+label,
+input,
+select,
+textarea {
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 13px;
+ font-weight: normal;
+ line-height: normal;
+ margin-bottom: 18px;
+}
+input[type=checkbox], input[type=radio] {
+ cursor: pointer;
+ margin-bottom: 0;
+}
+input[type=text],
+input[type=password],
+textarea,
+select {
+ display: inline-block;
+ width: 210px;
+ padding: 4px;
+ font-size: 13px;
+ font-weight: normal;
+ line-height: 18px;
+ height: 18px;
+ color: #808080;
+ border: 1px solid #ccc;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
+}
+select, input[type=file] {
+ height: 27px;
+ line-height: 27px;
+}
+textarea {
+ height: auto;
+}
+
+/* grey out placeholders */
+:-moz-placeholder {
+ color: #bfbfbf;
+}
+::-webkit-input-placeholder {
+ color: #bfbfbf;
+}
+
+input[type=text],
+input[type=password],
+select,
+textarea {
+ -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;
+ -moz-transition: border linear 0.2s, box-shadow linear 0.2s;
+ transition: border linear 0.2s, box-shadow linear 0.2s;
+ -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
+ -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
+ box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
+}
+input[type=text]:focus, input[type=password]:focus, textarea:focus {
+ outline: none;
+ border-color: rgba(82, 168, 236, 0.8);
+ -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6);
+ -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6);
+ box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6);
+}
+
+/* buttons */
+button {
+ display: inline-block;
+ padding: 4px 14px;
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 13px;
+ line-height: 18px;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+ -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+ background-color: #0064cd;
+ background-repeat: repeat-x;
+ background-image: -khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd));
+ background-image: -moz-linear-gradient(top, #049cdb, #0064cd);
+ background-image: -ms-linear-gradient(top, #049cdb, #0064cd);
+ background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd));
+ background-image: -webkit-linear-gradient(top, #049cdb, #0064cd);
+ background-image: -o-linear-gradient(top, #049cdb, #0064cd);
+ background-image: linear-gradient(top, #049cdb, #0064cd);
+ color: #fff;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+ border: 1px solid #004b9a;
+ border-bottom-color: #003f81;
+ -webkit-transition: 0.1s linear all;
+ -moz-transition: 0.1s linear all;
+ transition: 0.1s linear all;
+ border-color: #0064cd #0064cd #003f81;
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+}
+button:hover {
+ color: #fff;
+ background-position: 0 -15px;
+ text-decoration: none;
+}
+button:active {
+ -webkit-box-shadow: inset 0 3px 7px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+ -moz-box-shadow: inset 0 3px 7px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+ box-shadow: inset 0 3px 7px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+}
+button::-moz-focus-inner {
+ padding: 0;
+ border: 0;
+}
diff --git a/examples/webenginewidgets/markdowneditor/resources/markdowneditor.qrc b/examples/webenginewidgets/markdowneditor/resources/markdowneditor.qrc
new file mode 100644
index 000000000..8b7471a9c
--- /dev/null
+++ b/examples/webenginewidgets/markdowneditor/resources/markdowneditor.qrc
@@ -0,0 +1,9 @@
+<RCC>
+ <qresource prefix="/">
+ <file>index.html</file>
+ <file>qwebchannel.js</file>
+ <file>marked.min.js</file>
+ <file>default.md</file>
+ <file>markdown.css</file>
+ </qresource>
+</RCC>
diff --git a/examples/webenginewidgets/markdowneditor/resources/marked.min.js b/examples/webenginewidgets/markdowneditor/resources/marked.min.js
new file mode 100644
index 000000000..f3542fff0
--- /dev/null
+++ b/examples/webenginewidgets/markdowneditor/resources/marked.min.js
@@ -0,0 +1,6 @@
+/**
+ * marked - a markdown parser
+ * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
+ * https://github.com/chjj/marked
+ */
+(function(){var block={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:noop,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,nptable:noop,lheading:/^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,blockquote:/^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,def:/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:noop,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,text:/^[^\n]+/};block.bullet=/(?:[*+-]|\d+\.)/;block.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;block.item=replace(block.item,"gm")(/bull/g,block.bullet)();block.list=replace(block.list)(/bull/g,block.bullet)("hr","\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))")("def","\\n+(?="+block.def.source+")")();block.blockquote=replace(block.blockquote)("def",block.def)();block._tag="(?!(?:"+"a|em|strong|small|s|cite|q|dfn|abbr|data|time|code"+"|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo"+"|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b";block.html=replace(block.html)("comment",/<!--[\s\S]*?-->/)("closed",/<(tag)[\s\S]+?<\/\1>/)("closing",/<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)(/tag/g,block._tag)();block.paragraph=replace(block.paragraph)("hr",block.hr)("heading",block.heading)("lheading",block.lheading)("blockquote",block.blockquote)("tag","<"+block._tag)("def",block.def)();block.normal=merge({},block);block.gfm=merge({},block.normal,{fences:/^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,paragraph:/^/,heading:/^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/});block.gfm.paragraph=replace(block.paragraph)("(?!","(?!"+block.gfm.fences.source.replace("\\1","\\2")+"|"+block.list.source.replace("\\1","\\3")+"|")();block.tables=merge({},block.gfm,{nptable:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/});function Lexer(options){this.tokens=[];this.tokens.links={};this.options=options||marked.defaults;this.rules=block.normal;if(this.options.gfm){if(this.options.tables){this.rules=block.tables}else{this.rules=block.gfm}}}Lexer.rules=block;Lexer.lex=function(src,options){var lexer=new Lexer(options);return lexer.lex(src)};Lexer.prototype.lex=function(src){src=src.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n");return this.token(src,true)};Lexer.prototype.token=function(src,top,bq){var src=src.replace(/^ +$/gm,""),next,loose,cap,bull,b,item,space,i,l;while(src){if(cap=this.rules.newline.exec(src)){src=src.substring(cap[0].length);if(cap[0].length>1){this.tokens.push({type:"space"})}}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);cap=cap[0].replace(/^ {4}/gm,"");this.tokens.push({type:"code",text:!this.options.pedantic?cap.replace(/\n+$/,""):cap});continue}if(cap=this.rules.fences.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"code",lang:cap[2],text:cap[3]||""});continue}if(cap=this.rules.heading.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"heading",depth:cap[1].length,text:cap[2]});continue}if(top&&(cap=this.rules.nptable.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/\n$/,"").split("\n")};for(i=0;i<item.align.length;i++){if(/^ *-+: *$/.test(item.align[i])){item.align[i]="right"}else if(/^ *:-+: *$/.test(item.align[i])){item.align[i]="center"}else if(/^ *:-+ *$/.test(item.align[i])){item.align[i]="left"}else{item.align[i]=null}}for(i=0;i<item.cells.length;i++){item.cells[i]=item.cells[i].split(/ *\| */)}this.tokens.push(item);continue}if(cap=this.rules.lheading.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"heading",depth:cap[2]==="="?1:2,text:cap[1]});continue}if(cap=this.rules.hr.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"hr"});continue}if(cap=this.rules.blockquote.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"blockquote_start"});cap=cap[0].replace(/^ *> ?/gm,"");this.token(cap,top,true);this.tokens.push({type:"blockquote_end"});continue}if(cap=this.rules.list.exec(src)){src=src.substring(cap[0].length);bull=cap[2];this.tokens.push({type:"list_start",ordered:bull.length>1});cap=cap[0].match(this.rules.item);next=false;l=cap.length;i=0;for(;i<l;i++){item=cap[i];space=item.length;item=item.replace(/^ *([*+-]|\d+\.) +/,"");if(~item.indexOf("\n ")){space-=item.length;item=!this.options.pedantic?item.replace(new RegExp("^ {1,"+space+"}","gm"),""):item.replace(/^ {1,4}/gm,"")}if(this.options.smartLists&&i!==l-1){b=block.bullet.exec(cap[i+1])[0];if(bull!==b&&!(bull.length>1&&b.length>1)){src=cap.slice(i+1).join("\n")+src;i=l-1}}loose=next||/\n\n(?!\s*$)/.test(item);if(i!==l-1){next=item.charAt(item.length-1)==="\n";if(!loose)loose=next}this.tokens.push({type:loose?"loose_item_start":"list_item_start"});this.token(item,false,bq);this.tokens.push({type:"list_item_end"})}this.tokens.push({type:"list_end"});continue}if(cap=this.rules.html.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:this.options.sanitize?"paragraph":"html",pre:!this.options.sanitizer&&(cap[1]==="pre"||cap[1]==="script"||cap[1]==="style"),text:cap[0]});continue}if(!bq&&top&&(cap=this.rules.def.exec(src))){src=src.substring(cap[0].length);this.tokens.links[cap[1].toLowerCase()]={href:cap[2],title:cap[3]};continue}if(top&&(cap=this.rules.table.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/(?: *\| *)?\n$/,"").split("\n")};for(i=0;i<item.align.length;i++){if(/^ *-+: *$/.test(item.align[i])){item.align[i]="right"}else if(/^ *:-+: *$/.test(item.align[i])){item.align[i]="center"}else if(/^ *:-+ *$/.test(item.align[i])){item.align[i]="left"}else{item.align[i]=null}}for(i=0;i<item.cells.length;i++){item.cells[i]=item.cells[i].replace(/^ *\| *| *\| *$/g,"").split(/ *\| */)}this.tokens.push(item);continue}if(top&&(cap=this.rules.paragraph.exec(src))){src=src.substring(cap[0].length);this.tokens.push({type:"paragraph",text:cap[1].charAt(cap[1].length-1)==="\n"?cap[1].slice(0,-1):cap[1]});continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"text",text:cap[0]});continue}if(src){throw new Error("Infinite loop on byte: "+src.charCodeAt(0))}}return this.tokens};var inline={escape:/^\\([\\`*{}\[\]()#+\-.!_>])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:noop,tag:/^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:noop,text:/^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/};inline._inside=/(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;inline._href=/\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;inline.link=replace(inline.link)("inside",inline._inside)("href",inline._href)();inline.reflink=replace(inline.reflink)("inside",inline._inside)();inline.normal=merge({},inline);inline.pedantic=merge({},inline.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/});inline.gfm=merge({},inline.normal,{escape:replace(inline.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:replace(inline.text)("]|","~]|")("|","|https?://|")()});inline.breaks=merge({},inline.gfm,{br:replace(inline.br)("{2,}","*")(),text:replace(inline.gfm.text)("{2,}","*")()});function InlineLexer(links,options){this.options=options||marked.defaults;this.links=links;this.rules=inline.normal;this.renderer=this.options.renderer||new Renderer;this.renderer.options=this.options;if(!this.links){throw new Error("Tokens array requires a `links` property.")}if(this.options.gfm){if(this.options.breaks){this.rules=inline.breaks}else{this.rules=inline.gfm}}else if(this.options.pedantic){this.rules=inline.pedantic}}InlineLexer.rules=inline;InlineLexer.output=function(src,links,options){var inline=new InlineLexer(links,options);return inline.output(src)};InlineLexer.prototype.output=function(src){var out="",link,text,href,cap;while(src){if(cap=this.rules.escape.exec(src)){src=src.substring(cap[0].length);out+=cap[1];continue}if(cap=this.rules.autolink.exec(src)){src=src.substring(cap[0].length);if(cap[2]==="@"){text=cap[1].charAt(6)===":"?this.mangle(cap[1].substring(7)):this.mangle(cap[1]);href=this.mangle("mailto:")+text}else{text=escape(cap[1]);href=text}out+=this.renderer.link(href,null,text);continue}if(!this.inLink&&(cap=this.rules.url.exec(src))){src=src.substring(cap[0].length);text=escape(cap[1]);href=text;out+=this.renderer.link(href,null,text);continue}if(cap=this.rules.tag.exec(src)){if(!this.inLink&&/^<a /i.test(cap[0])){this.inLink=true}else if(this.inLink&&/^<\/a>/i.test(cap[0])){this.inLink=false}src=src.substring(cap[0].length);out+=this.options.sanitize?this.options.sanitizer?this.options.sanitizer(cap[0]):escape(cap[0]):cap[0];continue}if(cap=this.rules.link.exec(src)){src=src.substring(cap[0].length);this.inLink=true;out+=this.outputLink(cap,{href:cap[2],title:cap[3]});this.inLink=false;continue}if((cap=this.rules.reflink.exec(src))||(cap=this.rules.nolink.exec(src))){src=src.substring(cap[0].length);link=(cap[2]||cap[1]).replace(/\s+/g," ");link=this.links[link.toLowerCase()];if(!link||!link.href){out+=cap[0].charAt(0);src=cap[0].substring(1)+src;continue}this.inLink=true;out+=this.outputLink(cap,link);this.inLink=false;continue}if(cap=this.rules.strong.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.strong(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.em.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.em(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.codespan(escape(cap[2],true));continue}if(cap=this.rules.br.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.br();continue}if(cap=this.rules.del.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.del(this.output(cap[1]));continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.text(escape(this.smartypants(cap[0])));continue}if(src){throw new Error("Infinite loop on byte: "+src.charCodeAt(0))}}return out};InlineLexer.prototype.outputLink=function(cap,link){var href=escape(link.href),title=link.title?escape(link.title):null;return cap[0].charAt(0)!=="!"?this.renderer.link(href,title,this.output(cap[1])):this.renderer.image(href,title,escape(cap[1]))};InlineLexer.prototype.smartypants=function(text){if(!this.options.smartypants)return text;return text.replace(/---/g,"—").replace(/--/g,"–").replace(/(^|[-\u2014/(\[{"\s])'/g,"$1‘").replace(/'/g,"’").replace(/(^|[-\u2014/(\[{\u2018\s])"/g,"$1“").replace(/"/g,"”").replace(/\.{3}/g,"…")};InlineLexer.prototype.mangle=function(text){if(!this.options.mangle)return text;var out="",l=text.length,i=0,ch;for(;i<l;i++){ch=text.charCodeAt(i);if(Math.random()>.5){ch="x"+ch.toString(16)}out+="&#"+ch+";"}return out};function Renderer(options){this.options=options||{}}Renderer.prototype.code=function(code,lang,escaped){if(this.options.highlight){var out=this.options.highlight(code,lang);if(out!=null&&out!==code){escaped=true;code=out}}if(!lang){return"<pre><code>"+(escaped?code:escape(code,true))+"\n</code></pre>"}return'<pre><code class="'+this.options.langPrefix+escape(lang,true)+'">'+(escaped?code:escape(code,true))+"\n</code></pre>\n"};Renderer.prototype.blockquote=function(quote){return"<blockquote>\n"+quote+"</blockquote>\n"};Renderer.prototype.html=function(html){return html};Renderer.prototype.heading=function(text,level,raw){return"<h"+level+' id="'+this.options.headerPrefix+raw.toLowerCase().replace(/[^\w]+/g,"-")+'">'+text+"</h"+level+">\n"};Renderer.prototype.hr=function(){return this.options.xhtml?"<hr/>\n":"<hr>\n"};Renderer.prototype.list=function(body,ordered){var type=ordered?"ol":"ul";return"<"+type+">\n"+body+"</"+type+">\n"};Renderer.prototype.listitem=function(text){return"<li>"+text+"</li>\n"};Renderer.prototype.paragraph=function(text){return"<p>"+text+"</p>\n"};Renderer.prototype.table=function(header,body){return"<table>\n"+"<thead>\n"+header+"</thead>\n"+"<tbody>\n"+body+"</tbody>\n"+"</table>\n"};Renderer.prototype.tablerow=function(content){return"<tr>\n"+content+"</tr>\n"};Renderer.prototype.tablecell=function(content,flags){var type=flags.header?"th":"td";var tag=flags.align?"<"+type+' style="text-align:'+flags.align+'">':"<"+type+">";return tag+content+"</"+type+">\n"};Renderer.prototype.strong=function(text){return"<strong>"+text+"</strong>"};Renderer.prototype.em=function(text){return"<em>"+text+"</em>"};Renderer.prototype.codespan=function(text){return"<code>"+text+"</code>"};Renderer.prototype.br=function(){return this.options.xhtml?"<br/>":"<br>"};Renderer.prototype.del=function(text){return"<del>"+text+"</del>"};Renderer.prototype.link=function(href,title,text){if(this.options.sanitize){try{var prot=decodeURIComponent(unescape(href)).replace(/[^\w:]/g,"").toLowerCase()}catch(e){return""}if(prot.indexOf("javascript:")===0||prot.indexOf("vbscript:")===0){return""}}var out='<a href="'+href+'"';if(title){out+=' title="'+title+'"'}out+=">"+text+"</a>";return out};Renderer.prototype.image=function(href,title,text){var out='<img src="'+href+'" alt="'+text+'"';if(title){out+=' title="'+title+'"'}out+=this.options.xhtml?"/>":">";return out};Renderer.prototype.text=function(text){return text};function Parser(options){this.tokens=[];this.token=null;this.options=options||marked.defaults;this.options.renderer=this.options.renderer||new Renderer;this.renderer=this.options.renderer;this.renderer.options=this.options}Parser.parse=function(src,options,renderer){var parser=new Parser(options,renderer);return parser.parse(src)};Parser.prototype.parse=function(src){this.inline=new InlineLexer(src.links,this.options,this.renderer);this.tokens=src.reverse();var out="";while(this.next()){out+=this.tok()}return out};Parser.prototype.next=function(){return this.token=this.tokens.pop()};Parser.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0};Parser.prototype.parseText=function(){var body=this.token.text;while(this.peek().type==="text"){body+="\n"+this.next().text}return this.inline.output(body)};Parser.prototype.tok=function(){switch(this.token.type){case"space":{return""}case"hr":{return this.renderer.hr()}case"heading":{return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,this.token.text)}case"code":{return this.renderer.code(this.token.text,this.token.lang,this.token.escaped)}case"table":{var header="",body="",i,row,cell,flags,j;cell="";for(i=0;i<this.token.header.length;i++){flags={header:true,align:this.token.align[i]};cell+=this.renderer.tablecell(this.inline.output(this.token.header[i]),{header:true,align:this.token.align[i]})}header+=this.renderer.tablerow(cell);for(i=0;i<this.token.cells.length;i++){row=this.token.cells[i];cell="";for(j=0;j<row.length;j++){cell+=this.renderer.tablecell(this.inline.output(row[j]),{header:false,align:this.token.align[j]})}body+=this.renderer.tablerow(cell)}return this.renderer.table(header,body)}case"blockquote_start":{var body="";while(this.next().type!=="blockquote_end"){body+=this.tok()}return this.renderer.blockquote(body)}case"list_start":{var body="",ordered=this.token.ordered;while(this.next().type!=="list_end"){body+=this.tok()}return this.renderer.list(body,ordered)}case"list_item_start":{var body="";while(this.next().type!=="list_item_end"){body+=this.token.type==="text"?this.parseText():this.tok()}return this.renderer.listitem(body)}case"loose_item_start":{var body="";while(this.next().type!=="list_item_end"){body+=this.tok()}return this.renderer.listitem(body)}case"html":{var html=!this.token.pre&&!this.options.pedantic?this.inline.output(this.token.text):this.token.text;return this.renderer.html(html)}case"paragraph":{return this.renderer.paragraph(this.inline.output(this.token.text))}case"text":{return this.renderer.paragraph(this.parseText())}}};function escape(html,encode){return html.replace(!encode?/&(?!#?\w+;)/g:/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function unescape(html){return html.replace(/&([#\w]+);/g,function(_,n){n=n.toLowerCase();if(n==="colon")return":";if(n.charAt(0)==="#"){return n.charAt(1)==="x"?String.fromCharCode(parseInt(n.substring(2),16)):String.fromCharCode(+n.substring(1))}return""})}function replace(regex,opt){regex=regex.source;opt=opt||"";return function self(name,val){if(!name)return new RegExp(regex,opt);val=val.source||val;val=val.replace(/(^|[^\[])\^/g,"$1");regex=regex.replace(name,val);return self}}function noop(){}noop.exec=noop;function merge(obj){var i=1,target,key;for(;i<arguments.length;i++){target=arguments[i];for(key in target){if(Object.prototype.hasOwnProperty.call(target,key)){obj[key]=target[key]}}}return obj}function marked(src,opt,callback){if(callback||typeof opt==="function"){if(!callback){callback=opt;opt=null}opt=merge({},marked.defaults,opt||{});var highlight=opt.highlight,tokens,pending,i=0;try{tokens=Lexer.lex(src,opt)}catch(e){return callback(e)}pending=tokens.length;var done=function(err){if(err){opt.highlight=highlight;return callback(err)}var out;try{out=Parser.parse(tokens,opt)}catch(e){err=e}opt.highlight=highlight;return err?callback(err):callback(null,out)};if(!highlight||highlight.length<3){return done()}delete opt.highlight;if(!pending)return done();for(;i<tokens.length;i++){(function(token){if(token.type!=="code"){return--pending||done()}return highlight(token.text,token.lang,function(err,code){if(err)return done(err);if(code==null||code===token.text){return--pending||done()}token.text=code;token.escaped=true;--pending||done()})})(tokens[i])}return}try{if(opt)opt=merge({},marked.defaults,opt);return Parser.parse(Lexer.lex(src,opt),opt)}catch(e){e.message+="\nPlease report this to https://github.com/chjj/marked.";if((opt||marked.defaults).silent){return"<p>An error occurred:</p><pre>"+escape(e.message+"",true)+"</pre>"}throw e}}marked.options=marked.setOptions=function(opt){merge(marked.defaults,opt);return marked};marked.defaults={gfm:true,tables:true,breaks:false,pedantic:false,sanitize:false,sanitizer:null,mangle:true,smartLists:false,silent:false,highlight:null,langPrefix:"lang-",smartypants:false,headerPrefix:"",renderer:new Renderer,xhtml:false};marked.Parser=Parser;marked.parser=Parser.parse;marked.Renderer=Renderer;marked.Lexer=Lexer;marked.lexer=Lexer.lex;marked.InlineLexer=InlineLexer;marked.inlineLexer=InlineLexer.output;marked.parse=marked;if(typeof module!=="undefined"&&typeof exports==="object"){module.exports=marked}else if(typeof define==="function"&&define.amd){define(function(){return marked})}else{this.marked=marked}}).call(function(){return this||(typeof window!=="undefined"?window:global)}()); \ No newline at end of file
diff --git a/examples/webenginewidgets/markdowneditor/resources/qwebchannel.js b/examples/webenginewidgets/markdowneditor/resources/qwebchannel.js
new file mode 100644
index 000000000..d8c28bc66
--- /dev/null
+++ b/examples/webenginewidgets/markdowneditor/resources/qwebchannel.js
@@ -0,0 +1,413 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWebChannel module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+"use strict";
+
+var QWebChannelMessageTypes = {
+ signal: 1,
+ propertyUpdate: 2,
+ init: 3,
+ idle: 4,
+ debug: 5,
+ invokeMethod: 6,
+ connectToSignal: 7,
+ disconnectFromSignal: 8,
+ setProperty: 9,
+ response: 10,
+};
+
+var QWebChannel = function(transport, initCallback)
+{
+ if (typeof transport !== "object" || typeof transport.send !== "function") {
+ console.error("The QWebChannel expects a transport object with a send function and onmessage callback property." +
+ " Given is: transport: " + typeof(transport) + ", transport.send: " + typeof(transport.send));
+ return;
+ }
+
+ var channel = this;
+ this.transport = transport;
+
+ this.send = function(data)
+ {
+ if (typeof(data) !== "string") {
+ data = JSON.stringify(data);
+ }
+ channel.transport.send(data);
+ }
+
+ this.transport.onmessage = function(message)
+ {
+ var data = message.data;
+ if (typeof data === "string") {
+ data = JSON.parse(data);
+ }
+ switch (data.type) {
+ case QWebChannelMessageTypes.signal:
+ channel.handleSignal(data);
+ break;
+ case QWebChannelMessageTypes.response:
+ channel.handleResponse(data);
+ break;
+ case QWebChannelMessageTypes.propertyUpdate:
+ channel.handlePropertyUpdate(data);
+ break;
+ default:
+ console.error("invalid message received:", message.data);
+ break;
+ }
+ }
+
+ this.execCallbacks = {};
+ this.execId = 0;
+ this.exec = function(data, callback)
+ {
+ if (!callback) {
+ // if no callback is given, send directly
+ channel.send(data);
+ return;
+ }
+ if (channel.execId === Number.MAX_VALUE) {
+ // wrap
+ channel.execId = Number.MIN_VALUE;
+ }
+ if (data.hasOwnProperty("id")) {
+ console.error("Cannot exec message with property id: " + JSON.stringify(data));
+ return;
+ }
+ data.id = channel.execId++;
+ channel.execCallbacks[data.id] = callback;
+ channel.send(data);
+ };
+
+ this.objects = {};
+
+ this.handleSignal = function(message)
+ {
+ var object = channel.objects[message.object];
+ if (object) {
+ object.signalEmitted(message.signal, message.args);
+ } else {
+ console.warn("Unhandled signal: " + message.object + "::" + message.signal);
+ }
+ }
+
+ this.handleResponse = function(message)
+ {
+ if (!message.hasOwnProperty("id")) {
+ console.error("Invalid response message received: ", JSON.stringify(message));
+ return;
+ }
+ channel.execCallbacks[message.id](message.data);
+ delete channel.execCallbacks[message.id];
+ }
+
+ this.handlePropertyUpdate = function(message)
+ {
+ for (var i in message.data) {
+ var data = message.data[i];
+ var object = channel.objects[data.object];
+ if (object) {
+ object.propertyUpdate(data.signals, data.properties);
+ } else {
+ console.warn("Unhandled property update: " + data.object + "::" + data.signal);
+ }
+ }
+ channel.exec({type: QWebChannelMessageTypes.idle});
+ }
+
+ this.debug = function(message)
+ {
+ channel.send({type: QWebChannelMessageTypes.debug, data: message});
+ };
+
+ channel.exec({type: QWebChannelMessageTypes.init}, function(data) {
+ for (var objectName in data) {
+ var object = new QObject(objectName, data[objectName], channel);
+ }
+ // now unwrap properties, which might reference other registered objects
+ for (var objectName in channel.objects) {
+ channel.objects[objectName].unwrapProperties();
+ }
+ if (initCallback) {
+ initCallback(channel);
+ }
+ channel.exec({type: QWebChannelMessageTypes.idle});
+ });
+};
+
+function QObject(name, data, webChannel)
+{
+ this.__id__ = name;
+ webChannel.objects[name] = this;
+
+ // List of callbacks that get invoked upon signal emission
+ this.__objectSignals__ = {};
+
+ // Cache of all properties, updated when a notify signal is emitted
+ this.__propertyCache__ = {};
+
+ var object = this;
+
+ // ----------------------------------------------------------------------
+
+ this.unwrapQObject = function(response)
+ {
+ if (response instanceof Array) {
+ // support list of objects
+ var ret = new Array(response.length);
+ for (var i = 0; i < response.length; ++i) {
+ ret[i] = object.unwrapQObject(response[i]);
+ }
+ return ret;
+ }
+ if (!response
+ || !response["__QObject*__"]
+ || response.id === undefined) {
+ return response;
+ }
+
+ var objectId = response.id;
+ if (webChannel.objects[objectId])
+ return webChannel.objects[objectId];
+
+ if (!response.data) {
+ console.error("Cannot unwrap unknown QObject " + objectId + " without data.");
+ return;
+ }
+
+ var qObject = new QObject( objectId, response.data, webChannel );
+ qObject.destroyed.connect(function() {
+ if (webChannel.objects[objectId] === qObject) {
+ delete webChannel.objects[objectId];
+ // reset the now deleted QObject to an empty {} object
+ // just assigning {} though would not have the desired effect, but the
+ // below also ensures all external references will see the empty map
+ // NOTE: this detour is necessary to workaround QTBUG-40021
+ var propertyNames = [];
+ for (var propertyName in qObject) {
+ propertyNames.push(propertyName);
+ }
+ for (var idx in propertyNames) {
+ delete qObject[propertyNames[idx]];
+ }
+ }
+ });
+ // here we are already initialized, and thus must directly unwrap the properties
+ qObject.unwrapProperties();
+ return qObject;
+ }
+
+ this.unwrapProperties = function()
+ {
+ for (var propertyIdx in object.__propertyCache__) {
+ object.__propertyCache__[propertyIdx] = object.unwrapQObject(object.__propertyCache__[propertyIdx]);
+ }
+ }
+
+ function addSignal(signalData, isPropertyNotifySignal)
+ {
+ var signalName = signalData[0];
+ var signalIndex = signalData[1];
+ object[signalName] = {
+ connect: function(callback) {
+ if (typeof(callback) !== "function") {
+ console.error("Bad callback given to connect to signal " + signalName);
+ return;
+ }
+
+ object.__objectSignals__[signalIndex] = object.__objectSignals__[signalIndex] || [];
+ object.__objectSignals__[signalIndex].push(callback);
+
+ if (!isPropertyNotifySignal && signalName !== "destroyed") {
+ // only required for "pure" signals, handled separately for properties in propertyUpdate
+ // also note that we always get notified about the destroyed signal
+ webChannel.exec({
+ type: QWebChannelMessageTypes.connectToSignal,
+ object: object.__id__,
+ signal: signalIndex
+ });
+ }
+ },
+ disconnect: function(callback) {
+ if (typeof(callback) !== "function") {
+ console.error("Bad callback given to disconnect from signal " + signalName);
+ return;
+ }
+ object.__objectSignals__[signalIndex] = object.__objectSignals__[signalIndex] || [];
+ var idx = object.__objectSignals__[signalIndex].indexOf(callback);
+ if (idx === -1) {
+ console.error("Cannot find connection of signal " + signalName + " to " + callback.name);
+ return;
+ }
+ object.__objectSignals__[signalIndex].splice(idx, 1);
+ if (!isPropertyNotifySignal && object.__objectSignals__[signalIndex].length === 0) {
+ // only required for "pure" signals, handled separately for properties in propertyUpdate
+ webChannel.exec({
+ type: QWebChannelMessageTypes.disconnectFromSignal,
+ object: object.__id__,
+ signal: signalIndex
+ });
+ }
+ }
+ };
+ }
+
+ /**
+ * Invokes all callbacks for the given signalname. Also works for property notify callbacks.
+ */
+ function invokeSignalCallbacks(signalName, signalArgs)
+ {
+ var connections = object.__objectSignals__[signalName];
+ if (connections) {
+ connections.forEach(function(callback) {
+ callback.apply(callback, signalArgs);
+ });
+ }
+ }
+
+ this.propertyUpdate = function(signals, propertyMap)
+ {
+ // update property cache
+ for (var propertyIndex in propertyMap) {
+ var propertyValue = propertyMap[propertyIndex];
+ object.__propertyCache__[propertyIndex] = propertyValue;
+ }
+
+ for (var signalName in signals) {
+ // Invoke all callbacks, as signalEmitted() does not. This ensures the
+ // property cache is updated before the callbacks are invoked.
+ invokeSignalCallbacks(signalName, signals[signalName]);
+ }
+ }
+
+ this.signalEmitted = function(signalName, signalArgs)
+ {
+ invokeSignalCallbacks(signalName, signalArgs);
+ }
+
+ function addMethod(methodData)
+ {
+ var methodName = methodData[0];
+ var methodIdx = methodData[1];
+ object[methodName] = function() {
+ var args = [];
+ var callback;
+ for (var i = 0; i < arguments.length; ++i) {
+ if (typeof arguments[i] === "function")
+ callback = arguments[i];
+ else
+ args.push(arguments[i]);
+ }
+
+ webChannel.exec({
+ "type": QWebChannelMessageTypes.invokeMethod,
+ "object": object.__id__,
+ "method": methodIdx,
+ "args": args
+ }, function(response) {
+ if (response !== undefined) {
+ var result = object.unwrapQObject(response);
+ if (callback) {
+ (callback)(result);
+ }
+ }
+ });
+ };
+ }
+
+ function bindGetterSetter(propertyInfo)
+ {
+ var propertyIndex = propertyInfo[0];
+ var propertyName = propertyInfo[1];
+ var notifySignalData = propertyInfo[2];
+ // initialize property cache with current value
+ // NOTE: if this is an object, it is not directly unwrapped as it might
+ // reference other QObject that we do not know yet
+ object.__propertyCache__[propertyIndex] = propertyInfo[3];
+
+ if (notifySignalData) {
+ if (notifySignalData[0] === 1) {
+ // signal name is optimized away, reconstruct the actual name
+ notifySignalData[0] = propertyName + "Changed";
+ }
+ addSignal(notifySignalData, true);
+ }
+
+ Object.defineProperty(object, propertyName, {
+ configurable: true,
+ get: function () {
+ var propertyValue = object.__propertyCache__[propertyIndex];
+ if (propertyValue === undefined) {
+ // This shouldn't happen
+ console.warn("Undefined value in property cache for property \"" + propertyName + "\" in object " + object.__id__);
+ }
+
+ return propertyValue;
+ },
+ set: function(value) {
+ if (value === undefined) {
+ console.warn("Property setter for " + propertyName + " called with undefined value!");
+ return;
+ }
+ object.__propertyCache__[propertyIndex] = value;
+ webChannel.exec({
+ "type": QWebChannelMessageTypes.setProperty,
+ "object": object.__id__,
+ "property": propertyIndex,
+ "value": value
+ });
+ }
+ });
+
+ }
+
+ // ----------------------------------------------------------------------
+
+ data.methods.forEach(addMethod);
+
+ data.properties.forEach(bindGetterSetter);
+
+ data.signals.forEach(function(signal) { addSignal(signal, false); });
+
+ for (var name in data.enums) {
+ object[name] = data.enums[name];
+ }
+}
+
+//required for use with nodejs
+if (typeof module === 'object') {
+ module.exports = {
+ QWebChannel: QWebChannel
+ };
+}