]> rtime.felk.cvut.cz Git - coffee/qtwebbrowser.git/blob - src/app/qml/BrowserWindow.qml
Use qml extension plugin
[coffee/qtwebbrowser.git] / src / app / qml / BrowserWindow.qml
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtBrowser project.
7 **
8 ** $QT_BEGIN_LICENSE:GPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 2 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.GPLv2 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU General Public License version 2 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 3.0 as published by the Free Software
28 ** Foundation and appearing in the file LICENSE.GPL included in the
29 ** packaging of this file. Please review the following information to
30 ** ensure the GNU General Public License version 3.0 requirements will be
31 ** met: http://www.gnu.org/copyleft/gpl.html.
32 **
33 **
34 ** $QT_END_LICENSE$
35 **
36 ****************************************************************************/
37
38 import QtQuick 2.5
39 import QtWebEngine 1.1
40
41 import QtQuick.Controls 1.0
42 import QtQuick.Controls.Styles 1.0
43 import QtQuick.Layouts 1.0
44 import QtQuick.Window 2.1
45 import QtQuick.Controls.Private 1.0
46 import QtQuick.Dialogs 1.2
47 import QtQuick.Enterprise.VirtualKeyboard 2.0
48
49 import "assets"
50 import WebBrowser 1.0
51 import "Utils.js" as Utils
52
53 Item {
54     id: browserWindow
55
56     property Item currentWebView: {
57         return tabView.get(tabView.currentIndex) ? tabView.get(tabView.currentIndex).item.webView : null
58     }
59
60     property string googleSearchQuery: "https://www.google.com/search?sourceid=qtbrowser&ie=UTF-8&q="
61
62     property int toolBarSize: 80
63     property string uiColor: settingsView.privateBrowsingEnabled ? "#26282a" : "#46a2da"
64     property string uiSeparatorColor: settingsView.privateBrowsingEnabled ? "#717273" : "#7ebee5"
65     property string toolBarSeparatorColor: settingsView.privateBrowsingEnabled ? "#929495" : "#a3d1ed"
66     property string toolBarFillColor: settingsView.privateBrowsingEnabled ? "#46484a" : uiSeparatorColor
67     property string buttonPressedColor: settingsView.privateBrowsingEnabled ? "#3b3c3e" : "#3f91c4"
68     property string emptyBackgroundColor: "#e4e4e4"
69     property string uiHighlightColor: "#fddd5c"
70     property string inactivePagerColor: "#bcbdbe"
71     property string textFieldStrokeColor: "#3882ae"
72     property string placeholderColor: "#a0a1a2"
73     property string iconOverlayColor: "#0e202c"
74     property string iconStrokeColor: "#d6d6d6"
75     property string defaultFontFamily: "Open Sans"
76
77     property int gridViewPageItemCount: 8
78     property int gridViewMaxBookmarks: 3 * gridViewPageItemCount
79     property int tabViewMaxTabs: 10
80     property int animationDuration: 200
81     property int velocityThreshold: 400
82     property int velocityY: 0
83     property real touchY: 0
84     property real touchReference: 0
85     property bool touchGesture: false
86
87     width: 1024
88     height: 600
89     visible: true
90
91     Action {
92         shortcut: "Ctrl+D"
93         onTriggered: {
94             downloadView.visible = !downloadView.visible
95         }
96     }
97
98     Action {
99         id: focus
100         shortcut: "Ctrl+L"
101         onTriggered: {
102             navigation.addressBar.forceActiveFocus();
103             navigation.addressBar.selectAll();
104         }
105     }
106     Action {
107         shortcut: "Ctrl+R"
108         onTriggered: {
109             if (currentWebView)
110                 currentWebView.reload()
111             navigation.addressBar.forceActiveFocus()
112         }
113     }
114     Action {
115         id: newTabAction
116         shortcut: "Ctrl+T"
117         onTriggered: {
118             tabView.get(tabView.currentIndex).item.webView.takeSnapshot()
119             var tab = tabView.createEmptyTab()
120
121             if (!tab)
122                 return
123
124             navigation.addressBar.selectAll();
125             tabView.makeCurrent(tabView.count - 1)
126             navigation.addressBar.forceActiveFocus()
127         }
128     }
129     Action {
130         shortcut: "Ctrl+W"
131         onTriggered: tabView.remove(tabView.currentIndex)
132     }
133
134     UIToolBar {
135         id: tabEditToolBar
136
137         source: "icons/Btn_Add.png"
138         indicator: tabView.count
139
140         anchors {
141             left: parent.left
142             right: parent.right
143             top: navigation.top
144         }
145
146         visible: opacity != 0.0
147         opacity: tabView.viewState == "list" ? 1.0 : 0.0
148         onDoneClicked: tabView.viewState = "page"
149         onOptionClicked: newTabAction.trigger()
150     }
151
152     UIToolBar {
153         id: settingsToolBar
154         z: 5
155         title: qsTr("Settings")
156         visible: opacity != 0.0
157
158         anchors {
159             left: parent.left
160             right: parent.right
161             top: navigation.top
162         }
163
164         onDoneClicked: {
165             settingsView.save()
166             settingsView.state = "disabled"
167         }
168     }
169
170     UIToolBar {
171         id: fullScreenBar
172         z: 6
173         title: qsTr("Leave Full Screen Mode")
174         visible: opacity != 0.0
175         opacity: tabView.viewState == "fullscreen" ? 1.0 : 0.0
176         anchors {
177             left: parent.left
178             right: parent.right
179             top: navigation.top
180         }
181         onDoneClicked: {
182             navigation.webView.triggerWebAction(WebEngineView.ExitFullScreen);
183         }
184     }
185
186     NavigationBar {
187         id: navigation
188
189         anchors {
190             left: parent.left
191             right: parent.right
192         }
193     }
194
195     PageView {
196         id: tabView
197         interactive: {
198             if (sslDialog.visible || homeScreen.state != "disabled" || urlDropDown.state == "enabled" || settingsView.state == "enabled")
199                 return false
200             return true
201         }
202
203         anchors {
204             top: navigation.bottom
205             left: parent.left
206             right: parent.right
207         }
208
209         height: inputPanel.y
210
211         Component.onCompleted: {
212             var tab = createEmptyTab()
213
214             if (!tab)
215                 return
216
217             navigation.webView = tab.webView
218             navigation.load(WebEngine.initialUrl);
219         }
220         onCurrentIndexChanged: {
221             if (!tabView.get(tabView.currentIndex))
222                 return
223             navigation.webView = tabView.get(tabView.currentIndex).item.webView
224         }
225     }
226
227     QtObject{
228         id: acceptedCertificates
229
230         property var acceptedUrls : []
231
232         function shouldAutoAccept(certificateError){
233             var domain = WebEngine.domainFromString(certificateError.url)
234             return acceptedUrls.indexOf(domain) >= 0
235         }
236     }
237
238     MessageDialog {
239         id: sslDialog
240
241         property var certErrors: []
242         property var currentError: null
243         visible: certErrors.length > 0
244         icon: StandardIcon.Warning
245         standardButtons: StandardButton.No | StandardButton.Yes
246         title: "Server's certificate not trusted"
247         text: "Do you wish to continue?"
248         detailedText: "If you wish so, you may continue with an unverified certificate. " +
249                       "Accepting an unverified certificate means " +
250                       "you may not be connected with the host you tried to connect to.\n" +
251                       "Do you wish to override the security check and continue?"
252         onYes: {
253             var cert = certErrors.shift()
254             var domain = WebEngine.domainFromString(cert.url)
255             acceptedCertificates.acceptedUrls.push(domain)
256             cert.ignoreCertificateError()
257             presentError()
258         }
259         onNo: reject()
260         onRejected: reject()
261
262         function reject(){
263             certErrors.shift().rejectCertificate()
264             presentError()
265         }
266         function enqueue(error){
267             currentError = error
268             certErrors.push(error)
269             presentError()
270         }
271         function presentError(){
272             informativeText = "SSL error from URL\n\n" + currentError.url + "\n\n" + currentError.description + "\n"
273         }
274     }
275
276     Rectangle {
277         id: urlDropDown
278         color: "white"
279         visible: navigation.visible
280
281         property string searchString: navigation.addressBar.text
282
283         anchors {
284             left: parent.left
285             right: parent.right
286             top: navigation.bottom
287         }
288
289         state: "disabled"
290
291         states: [
292             State {
293                 name: "enabled"
294                 PropertyChanges {
295                     target: urlDropDown
296                     height: browserWindow.height - toolBarSize - 3
297                 }
298             },
299             State {
300                 name: "disabled"
301                 PropertyChanges {
302                     target: urlDropDown
303                     height: 0
304                 }
305             }
306         ]
307
308         Rectangle {
309             anchors.fill: parent
310             color: emptyBackgroundColor
311         }
312
313         SearchProxyModel {
314             id: proxy
315             target: navigation.webView.navigationHistory.items
316             searchString: urlDropDown.searchString
317             enabled: urlDropDown.state == "enabled"
318         }
319
320         ListView {
321             id: historyList
322             property int remainingHeight: Math.min((historyList.count + 1) * toolBarSize, inputPanel.y - toolBarSize - 3)
323             model: proxy
324             clip: true
325             boundsBehavior: Flickable.StopAtBounds
326             footerPositioning: ListView.InlineFooter
327             visible: urlDropDown.state == "enabled"
328
329             anchors {
330                 top: parent.top
331                 left: parent.left
332                 right: parent.right
333             }
334             height: remainingHeight
335             delegate: Rectangle {
336                 id: wrapper
337                 width: historyList.width
338                 height: toolBarSize
339
340                 MouseArea {
341                     anchors.fill: parent
342                     onClicked: {
343                         if (!url)
344                             return
345                         navigation.webView.url = url
346                         navigation.webView.forceActiveFocus()
347                     }
348                 }
349
350                 Column {
351                     width: parent.width - 60
352                     height: parent.height
353                     anchors {
354                         verticalCenter: parent.verticalCenter
355                         horizontalCenter: parent.horizontalCenter
356                     }
357                     Text {
358                         property string highlightTitle: title ? title : ""
359                         height: wrapper.height / 2
360                         width: parent.width
361                         elide: Text.ElideRight
362                         verticalAlignment: Text.AlignBottom
363                         anchors{
364                             leftMargin: 30
365                             rightMargin: 30
366                         }
367                         id: titleLabel
368                         font.family: defaultFontFamily
369                         font.pixelSize: 23
370                         color: "black"
371                         text: Utils.highlight(highlightTitle, urlDropDown.searchString)
372                     }
373                     Text {
374                         property string highlightUrl: url ? url : ""
375                         height: wrapper.height / 2 - 1
376                         width: parent.width
377                         elide: Text.ElideRight
378                         verticalAlignment: Text.AlignTop
379                         font.family: defaultFontFamily
380                         font.pixelSize: 23
381                         color: uiColor
382                         text: Utils.highlight(highlightUrl, urlDropDown.searchString)
383                     }
384                     Rectangle {
385                         anchors.horizontalCenter: parent.horizontalCenter
386                         width: historyList.width
387                         height: 1
388                         color: iconStrokeColor
389                     }
390                 }
391             }
392             footer: Rectangle {
393                 z: 5
394                 width: historyList.width
395                 height: toolBarSize
396                 MouseArea {
397                     anchors.fill: parent
398                     onClicked: {
399                         var string = urlDropDown.searchString
400                         var constructedUrl = ""
401                         if (WebEngine.isUrl(string)) {
402                             constructedUrl = WebEngine.fromUserInput(string)
403                         } else {
404                             constructedUrl = WebEngine.fromUserInput(googleSearchQuery + string)
405                         }
406                         navigation.webView.url = constructedUrl
407                         navigation.webView.forceActiveFocus()
408                     }
409                 }
410                 Row {
411                     height: parent.height
412                     Rectangle {
413                         id: searchIcon
414                         height: parent.height
415                         width: height
416                         color: "transparent"
417                         Image {
418                             anchors.centerIn: parent
419                             source: "assets/icons/Btn_Search.png"
420                         }
421                     }
422                     Text {
423                         id: searchText
424                         height: parent.height
425                         width: historyList.width - searchIcon.width - 30
426                         elide: Text.ElideRight
427                         text: urlDropDown.searchString
428                         verticalAlignment: Text.AlignVCenter
429                         font.family: defaultFontFamily
430                         font.pixelSize: 23
431                         color: "black"
432                     }
433                 }
434             }
435         }
436
437         transitions: Transition {
438             PropertyAnimation { property: "height"; duration: animationDuration; easing.type : Easing.InSine }
439         }
440     }
441
442     HomeScreen {
443         id: homeScreen
444         height: parent.height - toolBarSize
445         anchors {
446             top: navigation.bottom
447             left: parent.left
448             right: parent.right
449         }
450     }
451
452     SettingsView {
453         id: settingsView
454         height: parent.height - toolBarSize
455         anchors {
456             top: navigation.bottom
457             left: parent.left
458             right: parent.right
459         }
460     }
461     InputPanel {
462             id: inputPanel
463             y: browserWindow.height
464             anchors {
465                 left: browserWindow.left
466                 right: browserWindow.right
467             }
468             states: State {
469                 name: "visible"
470                 when: Qt.inputMethod.visible
471                 PropertyChanges {
472                     target: inputPanel
473                     y: browserWindow.height - inputPanel.height
474                 }
475             }
476             transitions: Transition {
477                 from: ""
478                 to: "visible"
479                 reversible: true
480                 NumberAnimation {
481                     properties: "y"
482                     duration: animationDuration
483                     easing.type: Easing.InOutQuad
484                 }
485             }
486     }
487 }