An error occurred while loading the file. Please try again.
-
Szabolcs David authored
When the user does a middle click on a link which originally opens a new tab (target="_blank"), the newly created RenderView is hidden, so the new tab has no visible content. We need to unhide it explicitly. This also adds background tab support for the Quick example browsers and fixes the profile mismatching warning in the case when we adopt a new tab without WebContents. Change-Id: Ia3c2e752a4784d32133cee0ff278c2849b151582 Reviewed-by:
Allan Sandfeld Jensen <allan.jensen@theqtcompany.com>
6cbeac50
/****************************************************************************
**
** 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.1
import QtWebEngine 1.1
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 QtQuick.Dialogs 1.2
import Qt.labs.settings 1.0
ApplicationWindow {
id: browserWindow
property QtObject applicationRoot
property Item currentWebView: tabs.currentIndex < tabs.count ? tabs.getTab(tabs.currentIndex).item : 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()
}
}
width: 1300
height: 900
visible: true
title: currentWebView && currentWebView.title
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
// 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"
Settings {
id : appSettings
property alias autoLoadImages: loadImages.checked;
property alias javaScriptEnabled: javaScriptEnabled.checked;
property alias errorPageEnabled: errorPageEnabled.checked;
}
WebEngineProfile {
id: defaultProfile
storageName: "Default"
httpCacheType: httpDiskCacheEnabled.checked ? WebEngineProfile.DiskHttpCache : WebEngineProfile.MemoryHttpCache;
onDownloadRequested: {
downloadView.visible = true
downloadView.append(download)
download.accept()
}
}
WebEngineProfile {
id: otrProfile
offTheRecord: true
}
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()
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)
}
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
}
Action {
shortcut: "Escape"
onTriggered: {
if (browserWindow.isFullScreen)
browserWindow.visibility = browserWindow.previousVisibility
}
}
Action {
shortcut: "Ctrl+0"
onTriggered: currentWebView.zoomFactor = 1.0;
}
Action {
shortcut: "Ctrl+-"
onTriggered: currentWebView.zoomFactor -= 0.1;
}
Action {
shortcut: "Ctrl+="
onTriggered: currentWebView.zoomFactor += 0.1;
}
toolBar: ToolBar {
id: navigationBar
RowLayout {
anchors.fill: parent;
ToolButton {
enabled: currentWebView && (currentWebView.canGoBack || currentWebView.canGoForward)
menu:Menu {
id: historyMenu
Instantiator {
model: currentWebView && currentWebView.navigationHistory.items
MenuItem {
text: model.title
onTriggered: currentWebView.goBackOrForward(model.offset)
checkable: !enabled
checked: !enabled
enabled: model.offset
}
onObjectAdded: historyMenu.insertItem(index, object)
onObjectRemoved: historyMenu.removeItem(object)
}
}
}
ToolButton {
id: backButton
iconSource: "icons/go-previous.png"
onClicked: currentWebView.goBack()
enabled: currentWebView && currentWebView.canGoBack
activeFocusOnTab: !browserWindow.platformIsMac
}
ToolButton {
id: forwardButton
iconSource: "icons/go-next.png"
onClicked: currentWebView.goForward()
enabled: currentWebView && currentWebView.canGoForward
activeFocusOnTab: !browserWindow.platformIsMac
}
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;
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
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: WebEngine.settings.autoLoadImages
}
MenuItem {
id: javaScriptEnabled
text: "JavaScript On"
checkable: true
checked: WebEngine.settings.javascriptEnabled
}
MenuItem {
id: errorPageEnabled
text: "ErrorPage On"
checkable: true
checked: WebEngine.settings.errorPageEnabled
}
MenuItem {
id: offTheRecordEnabled
text: "Off The Record"
checkable: true
checked: false
}
MenuItem {
id: httpDiskCacheEnabled
text: "HTTP Disk Cache"
checkable: true
checked: (defaultProfile.httpCacheType == WebEngineProfile.DiskHttpCache)
}
}
}
}
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
}
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
}
TabView {
id: tabs
function createEmptyTab() {
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 })
return tab
}
anchors.fill: parent
Component.onCompleted: createEmptyTab()
Component {
id: tabComponent
WebEngineView {
id: webEngineView
focus: true
profile: offTheRecordEnabled.checked ? otrProfile : defaultProfile
onLinkHovered: {
if (hoveredUrl == "")
resetStatusText.start()
else {
resetStatusText.stop()
statusText.text = hoveredUrl
}
}
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
onCertificateError: {
error.defer()
sslDialog.enqueue(error)
}
onNewViewRequested: {
if (!request.userInitiated)
print("Warning: Blocked a popup window.")
else if (request.destination == WebEngineView.NewViewInTab) {
var tab = tabs.createEmptyTab()
tabs.currentIndex = tabs.count - 1
request.openIn(tab.item)
} else if (request.destination == WebEngineView.NewViewInBackgroundTab) {
var tab = tabs.createEmptyTab()
request.openIn(tab.item)
} else if (request.destination == WebEngineView.NewViewInDialog) {
var dialog = applicationRoot.createDialog()
request.openIn(dialog.currentWebView)
} else {
var window = applicationRoot.createWindow()
request.openIn(window.currentWebView)
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
}
}
onFullScreenRequested: {
if (request.toggleOn) {
webEngineView.state = "FullScreen"
browserWindow.previousVisibility = browserWindow.visibility
browserWindow.showFullScreen()
} else {
webEngineView.state = ""
browserWindow.visibility = browserWindow.previousVisibility
}
request.accept()
}
}
}
}
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: {
certErrors.shift().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
}
}
DownloadView {
id: downloadView
visible: false
anchors.fill: parent
}
Rectangle {
id: statusBubble
color: "oldlace"
property int padding: 8
anchors.left: parent.left
anchors.bottom: parent.bottom
width: statusText.paintedWidth + padding
height: statusText.paintedHeight + padding
Text {
id: statusText
anchors.centerIn: statusBubble
elide: Qt.ElideMiddle
Timer {
id: resetStatusText
421422423424425426427
interval: 750
onTriggered: statusText.text = ""
}
}
}
}