WebView.qml 7.68 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/***************************************************************************
 *                                                                         *
 *   Copyright 2014-2015 Sebastian Kügler <sebas@kde.org>                  *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .        *
 *                                                                         *
 ***************************************************************************/

import QtQuick 2.3
23
import QtQuick.Controls 2.4 as Controls
Jonah Brüchert's avatar
Jonah Brüchert committed
24
import QtQuick.Window 2.1
25
import QtQuick.Layouts 1.3
26

27
import QtWebEngine 1.7
28

29
30
import org.kde.kirigami 2.4 as Kirigami

31
32
33
34
35
WebEngineView {
    id: webEngineView

    property string errorCode: ""
    property string errorString: ""
Jonah Brüchert's avatar
Jonah Brüchert committed
36
37
38
39

    /**
      * User agent used on mobile devices
      */
40
    property string mobileUserAgent: "Mozilla/5.0 (Linux; Plasma Mobile, like Android 9.0 ) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/69.0.3497.128 Mobile Safari/537.36"
Jonah Brüchert's avatar
Jonah Brüchert committed
41
42
43
44
45

    /**
      * User agent used on desktop devices,
      * Defaults to QtWebEngine's default (it is only supported on desktop devices by Qt currently)
      */
46
    property string desktopUserAgent: profile.httpUserAgent
47
48
49
50

    width: pageWidth
    height: pageHeight

51
    profile {
52
53
54
55
56
57
58
        httpUserAgent: {
            if (Kirigami.Settings.isMobile)
                return mobileUserAgent
            else
                return desktopUserAgent
        }

59
60
        offTheRecord: rootPage.privateMode

61
        onDownloadRequested: {
62
63
64
65
66
            // if we don't accept the request right away, it will be deleted
            download.accept()
            // therefore just stop the download again as quickly as possible,
            // and ask the user for confirmation
            download.pause()
67
68
69
70

            questionLoader.setSource("DownloadQuestion.qml")
            questionLoader.item.download = download
            questionLoader.item.visible = true
71
72
73
74
75
76
77
78
79
80
81
82
83
        }

        onDownloadFinished: {
            if (download.state === WebEngineDownloadItem.DownloadCompleted) {
                showPassiveNotification(i18n("Download finished"))
            }
            else if (download.state === WebEngineDownloadItem.DownloadInterrupted) {
                showPassiveNotification(i18n("Download failed"))
                console.log("Download interrupt reason: " + download.interruptReason)
            }
            else if (download.state === WebEngineDownloadItem.DownloadCancelled) {
                console.log("Download cancelled by the user")
            }
84
85
        }
    }
86

87
    settings {
Jonah Brüchert's avatar
Jonah Brüchert committed
88
        // Disable builtin error pages in favor of our own
89
90
91
        errorPageEnabled: false
    }

Jonah Brüchert's avatar
Jonah Brüchert committed
92
    // Custom context menu
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
    Controls.Menu {
        property var request
        id: contextMenu

        Controls.MenuItem {
            text: i18n("Copy")
            enabled: (contextMenu.request.editFlags & ContextMenuRequest.CanCopy) != 0
            onTriggered: webEngineView.triggerWebAction(WebEngineView.Copy)
        }
        Controls.MenuItem {
            text: i18n("Cut")
            enabled: (contextMenu.request.editFlags & ContextMenuRequest.CanCut) != 0
            onTriggered: webEngineView.triggerWebAction(WebEngineView.Cut)
        }
        Controls.MenuItem {
            text: i18n("Paste")
            enabled: (contextMenu.request.editFlags & ContextMenuRequest.CanPaste) != 0
            onTriggered: webEngineView.triggerWebAction(WebEngineView.Paste)
        }
        Controls.MenuItem {
            enabled: contextMenu.request.linkUrl !== ""
            text: i18n("Copy Url")
115
            onTriggered: webEngineView.triggerWebAction(WebEngineView.CopyLinkToClipboard)
116
117
118
        }
        Controls.MenuItem {
            text: i18n("View source")
119
            onTriggered: newTab("view-source:" + webEngineView.url)
120
121
122
123
124
125
126
127
128
129
130
        }
        Controls.MenuItem {
            text: i18n("Download")
            onTriggered: webEngineView.triggerWebAction(WebEngineView.DownloadLinkToDisk)
        }
        Controls.MenuItem {
            enabled: contextMenu.request.linkUrl !== ""
            text: i18n("Open in new Tab")
            onTriggered: webEngineView.triggerWebAction(WebEngineView.OpenLinkInNewTab)
        }
    }
131
132

    focus: true
133
    onLoadingChanged: {
134
135
136
137
138
139
140
141
142
143
144
145
146
        //print("Loading: " + loading);
        print("    url: " + loadRequest.url)
        //print("   icon: " + webEngineView.icon)
        //print("  title: " + webEngineView.title)

        /* Handle
        *  - WebEngineView::LoadStartedStatus,
        *  - WebEngineView::LoadStoppedStatus,
        *  - WebEngineView::LoadSucceededStatus and
        *  - WebEngineView::LoadFailedStatus
        */
        var ec = "";
        var es = "";
147
        if (loadRequest.status === WebEngineView.LoadSucceededStatus) {
148
            if (!rootPage.privateMode) {
Jonah Brüchert's avatar
Jonah Brüchert committed
149
                addHistoryEntry();
150
            }
151
        }
152
        if (loadRequest.status === WebEngineView.LoadFailedStatus) {
153
154
155
156
157
158
159
160
161
162
            print("Load failed: " + loadRequest.errorCode + " " + loadRequest.errorString);
            ec = loadRequest.errorCode;
            es = loadRequest.errorString;
        }
        errorCode = ec;
        errorString = es;
    }

    Component.onCompleted: {
        print("WebView completed.");
Jonah Brüchert's avatar
Jonah Brüchert committed
163
        var settings = webEngineView.settings;
164
165
        print("Settings: " + settings);
    }
166
167
168
169
170

    onIconChanged: {
        if (icon)
            browserManager.history.updateIcon(url, icon)
    }
171
172

    onNewViewRequested: {
173
174
        if (request.userInitiated) {
            newTab(request.requestedUrl.toString())
Pino Toscano's avatar
Pino Toscano committed
175
            showPassiveNotification(i18n("Website was opened in a new tab"))
176
        } else {
177
178
179
            questionLoader.setSource("NewTabQuestion.qml")
            questionLoader.item.url = request.requestedUrl
            questionLoader.item.visible = true
180
        }
181
182
    }

Jonah Brüchert's avatar
Jonah Brüchert committed
183
184
185
186
187
188
189
190
    onFullScreenRequested: {
        request.accept()
        if (webBrowser.visibility !== Window.FullScreen)
            webBrowser.showFullScreen()
        else
            webBrowser.showNormal()
    }

191
    onContextMenuRequested: {
Jonah Brüchert's avatar
Jonah Brüchert committed
192
        request.accepted = true // Make sure QtWebEngine doesn't show its own context menu.
193
194
195
196
197
        contextMenu.request = request
        contextMenu.x = request.x
        contextMenu.y = request.y
        contextMenu.open()
    }
198
199
200

    onAuthenticationDialogRequested: {
        request.accepted = true
201
202
203
        sheetLoader.setSource("AuthSheet.qml")
        sheetLoader.item.request = request
        sheetLoader.item.open()
204
    }
205
206

    onFeaturePermissionRequested: {
207
208
209
210
        questionLoader.setSource("PermissionQuestion.qml")
        questionLoader.item.permission = feature
        questionLoader.item.origin = securityOrigin
        questionLoader.item.visible = true
211
    }
212
}