WebView.qml 8.65 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: ""
36
37
    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"
    property string desktopUserAgent: profile.httpUserAgent
38
39
40
41

    width: pageWidth
    height: pageHeight

42
    profile {
43
44
45
46
47
48
49
        httpUserAgent: {
            if (Kirigami.Settings.isMobile)
                return mobileUserAgent
            else
                return desktopUserAgent
        }

50
51
        offTheRecord: rootPage.privateMode

52
        onDownloadRequested: {
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
            // 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()
            downloadQuestion.download = download
            downloadQuestion.visible = true
        }

        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")
            }
73
74
        }
    }
75

76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
    settings {
        errorPageEnabled: false
    }

    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")
            onTriggered:  webEngineView.triggerWebAction(WebEngineView.CopyLinkToClipboard)
        }
        Controls.MenuItem {
            text: i18n("View source")
106
            onTriggered: newTab("view-source:" + webEngineView.url)
107
108
109
110
111
112
113
114
115
116
117
        }
        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)
        }
    }
118

119
120
121
122
123
124
125
126
127
128
129
130
    Kirigami.OverlaySheet {
        id: authSheet
        property var request

        Kirigami.FormLayout {
            Layout.fillWidth: true

            Kirigami.Heading {
                elide: Text.ElideRight
                wrapMode: Text.WordWrap
                Layout.fillWidth: true

Yuri Chornoivan's avatar
Yuri Chornoivan committed
131
                text: i18n("Authentication required")
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
            }

            Controls.TextField {
                id: usernameField

                Kirigami.FormData.label: i18n("Username")
                Layout.fillWidth: true
            }
            Controls.TextField {
                id: passwordField
                echoMode: TextInput.Password

                Kirigami.FormData.label: i18n("Password")
                Layout.fillWidth: true
            }

            RowLayout {
                Layout.fillWidth: true

                Controls.Button {
                    Layout.fillWidth: true
                    text: i18n("Accept")

                    onClicked: {
                        authSheet.request.dialogAccept(usernameField.text, passwordField.text)
                        authSheet.close()
                    }
                }
                Controls.Button {
                    Layout.fillWidth: true
                    text: i18n("Cancel")

                    onClicked: {
                        authSheet.request.dialogReject()
                        authSheet.close()
                    }
                }
            }
        }
    }

173
174
    //Rectangle { color: "yellow"; opacity: 0.3; anchors.fill: parent }
    focus: true
175
    onLoadingChanged: {
176
177
178
179
180
181
182
183
184
185
186
187
188
        //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 = "";
189
        if (loadRequest.status === WebEngineView.LoadSucceededStatus) {
190
            if (!rootPage.privateMode) {
Jonah Brüchert's avatar
Jonah Brüchert committed
191
                addHistoryEntry();
192
            }
193
        }
194
        if (loadRequest.status === WebEngineView.LoadFailedStatus) {
195
196
197
198
199
200
201
202
203
204
            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
205
        var settings = webEngineView.settings;
206
207
        print("Settings: " + settings);
    }
208
209
210
211
212

    onIconChanged: {
        if (icon)
            browserManager.history.updateIcon(url, icon)
    }
213
214

    onNewViewRequested: {
215
216
        if (request.userInitiated) {
            newTab(request.requestedUrl.toString())
Pino Toscano's avatar
Pino Toscano committed
217
            showPassiveNotification(i18n("Website was opened in a new tab"))
218
219
220
221
        } else {
            newTabQuestion.url = request.requestedUrl
            newTabQuestion.visible = true
        }
222
223
    }

Jonah Brüchert's avatar
Jonah Brüchert committed
224
225
226
227
228
229
230
231
    onFullScreenRequested: {
        request.accept()
        if (webBrowser.visibility !== Window.FullScreen)
            webBrowser.showFullScreen()
        else
            webBrowser.showNormal()
    }

232
    onContextMenuRequested: {
Jonah Brüchert's avatar
Jonah Brüchert committed
233
        request.accepted = true // Make sure QtWebEngine doesn't show its own context menu.
234
235
236
237
238
        contextMenu.request = request
        contextMenu.x = request.x
        contextMenu.y = request.y
        contextMenu.open()
    }
239
240
241
242
243
244

    onAuthenticationDialogRequested: {
        request.accepted = true
        authSheet.request = request
        authSheet.open()
    }
245
246
247
248
249
250

    onFeaturePermissionRequested: {
        permissionQuestion.permission = feature
        permissionQuestion.origin = securityOrigin
        permissionQuestion.visible = true
    }
251
}