blob: 6c3c160ac0117439ebd21367072fa8ca8b552446 [file] [log] [blame] [edit]
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWebEngine module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.1
import QtWebEngine 1.2
import QtQuick.Controls 1.0
import QtQuick.Controls.Styles 1.0
import QtQuick.Layouts 1.0
import QtQuick.Window 2.1
import QtQuick.Controls.Private 1.0
import Qt.labs.settings 1.0
import QtQuick.Dialogs 1.2
ApplicationWindow {
id: browserWindow
property QtObject applicationRoot
property Item currentWebView: tabs.currentIndex < tabs.count ? tabs.getTab(tabs.currentIndex).item.webView : null
property int previousVisibility: Window.Windowed
property bool isFullScreen: visibility == Window.FullScreen
onIsFullScreenChanged: {
// This is for the case where the system forces us to leave fullscreen.
if (currentWebView && !isFullScreen) {
currentWebView.state = ""
if (currentWebView.isFullScreen) {
currentWebView.fullScreenCancelled()
fullScreenNotification.hide()
}
}
}
height: 600
width: 800
visible: true
title: currentWebView && currentWebView.title
Settings {
id : appSettings
property alias autoLoadImages: loadImages.checked;
property alias javaScriptEnabled: javaScriptEnabled.checked;
property alias errorPageEnabled: errorPageEnabled.checked;
property alias pluginsEnabled: pluginsEnabled.checked;
property alias thirdPartyCookiesEnabled: thirdPartyCookiesEnabled.checked;
}
// Make sure the Qt.WindowFullscreenButtonHint is set on OS X.
Component.onCompleted: flags = flags | Qt.WindowFullscreenButtonHint
// Create a styleItem to determine the platform.
// When using style "mac", ToolButtons are not supposed to accept focus.
StyleItem { id: styleItem }
property bool platformIsMac: styleItem.style == "mac"
Action {
shortcut: "Ctrl+D"
onTriggered: {
downloadView.visible = !downloadView.visible
}
}
Action {
id: focus
shortcut: "Ctrl+L"
onTriggered: {
addressBar.forceActiveFocus();
addressBar.selectAll();
}
}
Action {
shortcut: "Ctrl+R"
onTriggered: {
if (currentWebView)
currentWebView.reload()
}
}
Action {
shortcut: "Ctrl+T"
onTriggered: {
tabs.createEmptyTab(currentWebView.profile)
tabs.currentIndex = tabs.count - 1
addressBar.forceActiveFocus();
addressBar.selectAll();
}
}
Action {
shortcut: "Ctrl+W"
onTriggered: {
if (tabs.count == 1)
browserWindow.close()
else
tabs.removeTab(tabs.currentIndex)
}
}
Action {
shortcut: "Escape"
onTriggered: {
if (browserWindow.isFullScreen)
browserWindow.visibility = browserWindow.previousVisibility
}
}
Action {
shortcut: "Ctrl+0"
onTriggered: zoomController.reset()
}
Action {
shortcut: "Ctrl+-"
onTriggered: zoomController.zoomOut()
}
Action {
shortcut: "Ctrl+="
onTriggered: zoomController.zoomIn()
}
Menu {
id: backHistoryMenu
Instantiator {
model: currentWebView && currentWebView.navigationHistory.backItems
MenuItem {
text: model.title
onTriggered: currentWebView.goBackOrForward(model.offset)
}
onObjectAdded: backHistoryMenu.insertItem(index, object)
onObjectRemoved: backHistoryMenu.removeItem(object)
}
}
Menu {
id: forwardHistoryMenu
Instantiator {
model: currentWebView && currentWebView.navigationHistory.forwardItems
MenuItem {
text: model.title
onTriggered: currentWebView.goBackOrForward(model.offset)
}
onObjectAdded: forwardHistoryMenu.insertItem(index, object)
onObjectRemoved: forwardHistoryMenu.removeItem(object)
}
}
toolBar: ToolBar {
id: navigationBar
RowLayout {
anchors.fill: parent;
ButtonWithMenu {
id: backButton
iconSource: "icons/go-previous.png"
enabled: currentWebView && currentWebView.canGoBack
activeFocusOnTab: !browserWindow.platformIsMac
onClicked: currentWebView.goBack()
longPressMenu: backHistoryMenu
}
ButtonWithMenu {
id: forwardButton
iconSource: "icons/go-next.png"
enabled: currentWebView && currentWebView.canGoForward
activeFocusOnTab: !browserWindow.platformIsMac
onClicked: currentWebView.goForward()
longPressMenu: forwardHistoryMenu
}
ToolButton {
id: reloadButton
iconSource: currentWebView && currentWebView.loading ? "icons/process-stop.png" : "icons/view-refresh.png"
onClicked: currentWebView && currentWebView.loading ? currentWebView.stop() : currentWebView.reload()
activeFocusOnTab: !browserWindow.platformIsMac
}
TextField {
id: addressBar
Image {
anchors.verticalCenter: addressBar.verticalCenter;
x: 5
z: 2
id: faviconImage
width: 16; height: 16
source: currentWebView && currentWebView.icon
}
style: TextFieldStyle {
padding {
left: 26;
}
}
focus: true
Layout.fillWidth: true
text: currentWebView && currentWebView.url
onAccepted: currentWebView.url = utils.fromUserInput(text)
}
ToolButton {
id: settingsMenuButton
menu: Menu {
MenuItem {
id: loadImages
text: "Autoload images"
checkable: true
checked: true
}
MenuItem {
id: javaScriptEnabled
text: "JavaScript On"
checkable: true
checked: true
}
MenuItem {
id: errorPageEnabled
text: "ErrorPage On"
checkable: true
checked: true
}
MenuItem {
id: pluginsEnabled
text: "Plugins On"
checkable: true
checked: true
}
MenuItem {
id: thirdPartyCookiesEnabled
text: "Third party cookies enabled"
checkable: true
checked: true
onToggled: applicationRoot.thirdPartyCookiesEnabled = checked
}
MenuItem {
id: offTheRecordEnabled
text: "Off The Record"
checkable: true
checked: currentWebView.profile.offTheRecord
onToggled: currentWebView.profile = checked ? otrProfile : testProfile;
}
MenuItem {
id: httpDiskCacheEnabled
text: "HTTP Disk Cache"
checkable: !currentWebView.profile.offTheRecord
checked: (currentWebView.profile.httpCacheType == WebEngineProfile.DiskHttpCache)
onToggled: currentWebView.profile.httpCacheType = checked ? WebEngineProfile.DiskHttpCache : WebEngineProfile.MemoryHttpCache;
}
}
}
}
ProgressBar {
id: progressBar
height: 3
anchors {
left: parent.left
top: parent.bottom
right: parent.right
leftMargin: -parent.leftMargin
rightMargin: -parent.rightMargin
}
style: ProgressBarStyle {
background: Item {}
}
z: -2;
minimumValue: 0
maximumValue: 100
value: (currentWebView && currentWebView.loadProgress < 100) ? currentWebView.loadProgress : 0
}
}
TabView {
id: tabs
function createEmptyTab(profile) {
var tab = addTab("", tabComponent)
// We must do this first to make sure that tab.active gets set so that tab.item gets instantiated immediately.
tab.active = true
tab.title = Qt.binding(function() { return tab.item.title })
tab.item.webView.profile = profile
return tab
}
anchors.fill: parent
Component.onCompleted: createEmptyTab(testProfile)
Component {
id: tabComponent
Item {
property alias webView: webEngineView
property alias title: webEngineView.title
Action {
shortcut: "Ctrl+F"
onTriggered: {
findBar.visible = !findBar.visible
if (findBar.visible) {
findTextField.forceActiveFocus()
}
}
}
FeaturePermissionBar {
id: permBar
view: webEngineView
anchors {
left: parent.left
right: parent.right
top: parent.top
}
z: 3
}
WebEngineView {
id: webEngineView
anchors {
fill: parent
top: permBar.bottom
}
focus: true
states: [
State {
name: "FullScreen"
PropertyChanges {
target: tabs
frameVisible: false
tabsVisible: false
}
PropertyChanges {
target: navigationBar
visible: false
}
}
]
settings.autoLoadImages: appSettings.autoLoadImages
settings.javascriptEnabled: appSettings.javaScriptEnabled
settings.errorPageEnabled: appSettings.errorPageEnabled
settings.pluginsEnabled: appSettings.pluginsEnabled
onCertificateError: {
if (!acceptedCertificates.shouldAutoAccept(error)){
error.defer()
sslDialog.enqueue(error)
} else{
error.ignoreCertificateError()
}
}
onNewViewRequested: {
if (!request.userInitiated)
print("Warning: Blocked a popup window.")
else if (request.destination == WebEngineView.NewViewInTab) {
var tab = tabs.createEmptyTab(currentWebView.profile)
tabs.currentIndex = tabs.count - 1
request.openIn(tab.item.webView)
} else if (request.destination == WebEngineView.NewViewInBackgroundTab) {
var tab = tabs.createEmptyTab(currentWebView.profile)
request.openIn(tab.item.webView)
} else if (request.destination == WebEngineView.NewViewInDialog) {
var dialog = applicationRoot.createDialog(currentWebView.profile)
request.openIn(dialog.currentWebView)
} else {
var window = applicationRoot.createWindow(currentWebView.profile)
request.openIn(window.currentWebView)
}
}
onFullScreenRequested: {
if (request.toggleOn) {
webEngineView.state = "FullScreen"
browserWindow.previousVisibility = browserWindow.visibility
browserWindow.showFullScreen()
fullScreenNotification.show()
} else {
webEngineView.state = ""
browserWindow.visibility = browserWindow.previousVisibility
fullScreenNotification.hide()
}
request.accept()
}
onFeaturePermissionRequested: {
permBar.securityOrigin = securityOrigin;
permBar.requestedFeature = feature;
permBar.visible = true;
}
}
Rectangle {
id: findBar
anchors.top: webEngineView.top
anchors.right: webEngineView.right
width: 240
height: 35
border.color: "lightgray"
border.width: 1
radius: 5
visible: false
color: browserWindow.color
RowLayout {
anchors.centerIn: findBar
TextField {
id: findTextField
onAccepted: {
webEngineView.findText(text)
}
}
ToolButton {
id: findBackwardButton
iconSource: "icons/go-previous.png"
onClicked: webEngineView.findText(findTextField.text, WebEngineView.FindBackward)
}
ToolButton {
id: findForwardButton
iconSource: "icons/go-next.png"
onClicked: webEngineView.findText(findTextField.text)
}
ToolButton {
id: findCancelButton
iconSource: "icons/process-stop.png"
onClicked: findBar.visible = false
}
}
}
}
}
}
QtObject{
id:acceptedCertificates
property var acceptedUrls : []
function shouldAutoAccept(certificateError){
var domain = utils.domainFromString(certificateError.url)
return acceptedUrls.indexOf(domain) >= 0
}
}
MessageDialog {
id: sslDialog
property var certErrors: []
icon: StandardIcon.Warning
standardButtons: StandardButton.No | StandardButton.Yes
title: "Server's certificate not trusted"
text: "Do you wish to continue?"
detailedText: "If you wish so, you may continue with an unverified certificate. " +
"Accepting an unverified certificate means " +
"you may not be connected with the host you tried to connect to.\n" +
"Do you wish to override the security check and continue?"
onYes: {
var cert = certErrors.shift()
var domain = utils.domainFromString(cert.url)
acceptedCertificates.acceptedUrls.push(domain)
cert.ignoreCertificateError()
presentError()
}
onNo: reject()
onRejected: reject()
function reject(){
certErrors.shift().rejectCertificate()
presentError()
}
function enqueue(error){
certErrors.push(error)
presentError()
}
function presentError(){
visible = certErrors.length > 0
}
}
FullScreenNotification {
id: fullScreenNotification
}
DownloadView {
id: downloadView
visible: false
anchors.fill: parent
}
function onDownloadRequested(download) {
downloadView.visible = true
downloadView.append(download)
download.accept()
}
MessageDialog {
id: notificationDialog
width: 200
standardButtons: StandardButton.Ok
}
function onPresentNotification(notification) {
notificationDialog.title = notification.title
notificationDialog.text = notification.origin.toString() + '\n' + notification.message
notificationDialog.open()
}
ZoomController {
id: zoomController
y: parent.mapFromItem(currentWebView, 0 , 0).y - 4
anchors.right: parent.right
width: (parent.width > 800) ? parent.width * 0.25 : 220
anchors.rightMargin: (parent.width > 400) ? 100 : 0
}
Binding {
target: currentWebView
property: "zoomFactor"
value: zoomController.zoomFactor
}
}