Merge lp:~artmello/webbrowser-app/webbrowser-app-multi_window into lp:webbrowser-app
- webbrowser-app-multi_window
- Merge into trunk
Status: | Rejected |
---|---|
Rejected by: | Olivier Tilloy |
Proposed branch: | lp:~artmello/webbrowser-app/webbrowser-app-multi_window |
Merge into: | lp:webbrowser-app |
Diff against target: |
772 lines (+440/-91) 13 files modified
src/app/BrowserView.qml (+4/-0) src/app/actions/NewPrivateWindow.qml (+28/-0) src/app/actions/NewWindow.qml (+28/-0) src/app/actions/OpenLinkInNewPrivateWindow.qml (+23/-0) src/app/actions/OpenLinkInNewWindow.qml (+23/-0) src/app/webbrowser/BookmarksModel.qml (+0/-24) src/app/webbrowser/Browser.qml (+118/-33) src/app/webbrowser/CMakeLists.txt (+1/-0) src/app/webbrowser/HistoryModel.qml (+0/-24) src/app/webbrowser/webbrowser-app.cpp (+40/-9) src/app/webbrowser/webbrowser-app.qml (+9/-1) src/app/webbrowser/windows-model.cpp (+106/-0) src/app/webbrowser/windows-model.h (+60/-0) |
To merge this branch: | bzr merge lp:~artmello/webbrowser-app/webbrowser-app-multi_window |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Olivier Tilloy | Disapprove | ||
system-apps-ci-bot | continuous-integration | Needs Fixing | |
PS Jenkins bot | continuous-integration | Needs Fixing | |
Review via email: mp+272681@code.launchpad.net |
Commit message
Description of the change
*DO NOT MERGE/REVIEW*
Initial prototype of Multi Window using QML approach
PS Jenkins bot (ps-jenkins) wrote : | # |
- 1207. By Arthur Mello
-
Undo changes on the models
- 1208. By Arthur Mello
-
Make HistoryModel and BookmarksModel to be singletons
- 1209. By Arthur Mello
-
Open new window with startuo url wn nothing is set
- 1210. By Arthur Mello
-
Add support to open new windows in private mode
- 1211. By Arthur Mello
-
Add initial support to storing all opened windows
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1211
http://
Executed test runs:
UNSTABLE: http://
FAILURE: http://
SUCCESS: http://
deb: http://
FAILURE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 1212. By Arthur Mello
-
Expand session storage support
- 1213. By Arthur Mello
-
Merge with trunk
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1213
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
FAILURE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 1214. By Arthur Mello
-
Make sure that only a single instance of webbrowser is running
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1214
http://
Executed test runs:
UNSTABLE: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
system-apps-ci-bot (system-apps-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:1214
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https:/
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Unmerged revisions
- 1214. By Arthur Mello
-
Make sure that only a single instance of webbrowser is running
- 1213. By Arthur Mello
-
Merge with trunk
- 1212. By Arthur Mello
-
Expand session storage support
- 1211. By Arthur Mello
-
Add initial support to storing all opened windows
- 1210. By Arthur Mello
-
Add support to open new windows in private mode
- 1209. By Arthur Mello
-
Open new window with startuo url wn nothing is set
- 1208. By Arthur Mello
-
Make HistoryModel and BookmarksModel to be singletons
- 1207. By Arthur Mello
-
Undo changes on the models
- 1206. By Arthur Mello
-
Initial prototype of Multi Window using QML approach
Preview Diff
1 | === modified file 'src/app/BrowserView.qml' | |||
2 | --- src/app/BrowserView.qml 2015-08-10 15:22:00 +0000 | |||
3 | +++ src/app/BrowserView.qml 2015-10-07 00:51:42 +0000 | |||
4 | @@ -37,11 +37,15 @@ | |||
5 | 37 | 37 | ||
6 | 38 | focus: true | 38 | focus: true |
7 | 39 | 39 | ||
8 | 40 | /* FIXME: Error when opening new windows | ||
9 | 41 | * Reason: An object is already exported for the interface org.gtk.Actions at /com/canonical/unity/actions | ||
10 | 42 | |||
11 | 40 | property QtObject actionManager: UnityActions.ActionManager { | 43 | property QtObject actionManager: UnityActions.ActionManager { |
12 | 41 | id: unityActionManager | 44 | id: unityActionManager |
13 | 42 | onQuit: Qt.quit() | 45 | onQuit: Qt.quit() |
14 | 43 | } | 46 | } |
15 | 44 | property alias actions: unityActionManager.actions | 47 | property alias actions: unityActionManager.actions |
16 | 48 | */ | ||
17 | 45 | 49 | ||
18 | 46 | default property alias contents: contentsItem.data | 50 | default property alias contents: contentsItem.data |
19 | 47 | property alias automaticOrientation: contentsItem.automaticOrientation | 51 | property alias automaticOrientation: contentsItem.automaticOrientation |
20 | 48 | 52 | ||
21 | === added file 'src/app/actions/NewPrivateWindow.qml' | |||
22 | --- src/app/actions/NewPrivateWindow.qml 1970-01-01 00:00:00 +0000 | |||
23 | +++ src/app/actions/NewPrivateWindow.qml 2015-10-07 00:51:42 +0000 | |||
24 | @@ -0,0 +1,28 @@ | |||
25 | 1 | /* | ||
26 | 2 | * Copyright 2015 Canonical Ltd. | ||
27 | 3 | * | ||
28 | 4 | * This file is part of webbrowser-app. | ||
29 | 5 | * | ||
30 | 6 | * webbrowser-app is free software; you can redistribute it and/or modify | ||
31 | 7 | * it under the terms of the GNU General Public License as published by | ||
32 | 8 | * the Free Software Foundation; version 3. | ||
33 | 9 | * | ||
34 | 10 | * webbrowser-app is distributed in the hope that it will be useful, | ||
35 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
36 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
37 | 13 | * GNU General Public License for more details. | ||
38 | 14 | * | ||
39 | 15 | * You should have received a copy of the GNU General Public License | ||
40 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
41 | 17 | */ | ||
42 | 18 | |||
43 | 19 | import Ubuntu.Components 1.3 | ||
44 | 20 | import Ubuntu.Unity.Action 1.1 as UnityActions | ||
45 | 21 | |||
46 | 22 | UnityActions.Action { | ||
47 | 23 | text: i18n.tr("New Private Window") | ||
48 | 24 | // TRANSLATORS: This is a free-form list of keywords associated to the 'New Private Window' action. | ||
49 | 25 | // Keywords may actually be sentences, and must be separated by semi-colons. | ||
50 | 26 | keywords: i18n.tr("Open a New Private Window") | ||
51 | 27 | } | ||
52 | 28 | |||
53 | 0 | 29 | ||
54 | === added file 'src/app/actions/NewWindow.qml' | |||
55 | --- src/app/actions/NewWindow.qml 1970-01-01 00:00:00 +0000 | |||
56 | +++ src/app/actions/NewWindow.qml 2015-10-07 00:51:42 +0000 | |||
57 | @@ -0,0 +1,28 @@ | |||
58 | 1 | /* | ||
59 | 2 | * Copyright 2015 Canonical Ltd. | ||
60 | 3 | * | ||
61 | 4 | * This file is part of webbrowser-app. | ||
62 | 5 | * | ||
63 | 6 | * webbrowser-app is free software; you can redistribute it and/or modify | ||
64 | 7 | * it under the terms of the GNU General Public License as published by | ||
65 | 8 | * the Free Software Foundation; version 3. | ||
66 | 9 | * | ||
67 | 10 | * webbrowser-app is distributed in the hope that it will be useful, | ||
68 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
69 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
70 | 13 | * GNU General Public License for more details. | ||
71 | 14 | * | ||
72 | 15 | * You should have received a copy of the GNU General Public License | ||
73 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
74 | 17 | */ | ||
75 | 18 | |||
76 | 19 | import Ubuntu.Components 1.3 | ||
77 | 20 | import Ubuntu.Unity.Action 1.1 as UnityActions | ||
78 | 21 | |||
79 | 22 | UnityActions.Action { | ||
80 | 23 | text: i18n.tr("New Window") | ||
81 | 24 | // TRANSLATORS: This is a free-form list of keywords associated to the 'New Window' action. | ||
82 | 25 | // Keywords may actually be sentences, and must be separated by semi-colons. | ||
83 | 26 | keywords: i18n.tr("Open a New Window") | ||
84 | 27 | } | ||
85 | 28 | |||
86 | 0 | 29 | ||
87 | === added file 'src/app/actions/OpenLinkInNewPrivateWindow.qml' | |||
88 | --- src/app/actions/OpenLinkInNewPrivateWindow.qml 1970-01-01 00:00:00 +0000 | |||
89 | +++ src/app/actions/OpenLinkInNewPrivateWindow.qml 2015-10-07 00:51:42 +0000 | |||
90 | @@ -0,0 +1,23 @@ | |||
91 | 1 | /* | ||
92 | 2 | * Copyright 2015 Canonical Ltd. | ||
93 | 3 | * | ||
94 | 4 | * This file is part of webbrowser-app. | ||
95 | 5 | * | ||
96 | 6 | * webbrowser-app is free software; you can redistribute it and/or modify | ||
97 | 7 | * it under the terms of the GNU General Public License as published by | ||
98 | 8 | * the Free Software Foundation; version 3. | ||
99 | 9 | * | ||
100 | 10 | * webbrowser-app is distributed in the hope that it will be useful, | ||
101 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
102 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
103 | 13 | * GNU General Public License for more details. | ||
104 | 14 | * | ||
105 | 15 | * You should have received a copy of the GNU General Public License | ||
106 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
107 | 17 | */ | ||
108 | 18 | |||
109 | 19 | import Ubuntu.Components 1.3 | ||
110 | 20 | |||
111 | 21 | Action { | ||
112 | 22 | text: i18n.tr("Open link in new private window") | ||
113 | 23 | } | ||
114 | 0 | 24 | ||
115 | === added file 'src/app/actions/OpenLinkInNewWindow.qml' | |||
116 | --- src/app/actions/OpenLinkInNewWindow.qml 1970-01-01 00:00:00 +0000 | |||
117 | +++ src/app/actions/OpenLinkInNewWindow.qml 2015-10-07 00:51:42 +0000 | |||
118 | @@ -0,0 +1,23 @@ | |||
119 | 1 | /* | ||
120 | 2 | * Copyright 2015 Canonical Ltd. | ||
121 | 3 | * | ||
122 | 4 | * This file is part of webbrowser-app. | ||
123 | 5 | * | ||
124 | 6 | * webbrowser-app is free software; you can redistribute it and/or modify | ||
125 | 7 | * it under the terms of the GNU General Public License as published by | ||
126 | 8 | * the Free Software Foundation; version 3. | ||
127 | 9 | * | ||
128 | 10 | * webbrowser-app is distributed in the hope that it will be useful, | ||
129 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
130 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
131 | 13 | * GNU General Public License for more details. | ||
132 | 14 | * | ||
133 | 15 | * You should have received a copy of the GNU General Public License | ||
134 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
135 | 17 | */ | ||
136 | 18 | |||
137 | 19 | import Ubuntu.Components 1.3 | ||
138 | 20 | |||
139 | 21 | Action { | ||
140 | 22 | text: i18n.tr("Open link in new window") | ||
141 | 23 | } | ||
142 | 0 | 24 | ||
143 | === removed file 'src/app/webbrowser/BookmarksModel.qml' | |||
144 | --- src/app/webbrowser/BookmarksModel.qml 2015-08-10 15:22:00 +0000 | |||
145 | +++ src/app/webbrowser/BookmarksModel.qml 1970-01-01 00:00:00 +0000 | |||
146 | @@ -1,24 +0,0 @@ | |||
147 | 1 | /* | ||
148 | 2 | * Copyright 2014-2015 Canonical Ltd. | ||
149 | 3 | * | ||
150 | 4 | * This file is part of webbrowser-app. | ||
151 | 5 | * | ||
152 | 6 | * webbrowser-app is free software; you can redistribute it and/or modify | ||
153 | 7 | * it under the terms of the GNU General Public License as published by | ||
154 | 8 | * the Free Software Foundation; version 3. | ||
155 | 9 | * | ||
156 | 10 | * webbrowser-app is distributed in the hope that it will be useful, | ||
157 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
158 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
159 | 13 | * GNU General Public License for more details. | ||
160 | 14 | * | ||
161 | 15 | * You should have received a copy of the GNU General Public License | ||
162 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
163 | 17 | */ | ||
164 | 18 | |||
165 | 19 | import QtQuick 2.4 | ||
166 | 20 | import webbrowserapp.private 0.1 | ||
167 | 21 | |||
168 | 22 | BookmarksModel { | ||
169 | 23 | databasePath: dataLocation + "/bookmarks.sqlite" | ||
170 | 24 | } | ||
171 | 25 | 0 | ||
172 | === modified file 'src/app/webbrowser/Browser.qml' | |||
173 | --- src/app/webbrowser/Browser.qml 2015-09-28 08:15:10 +0000 | |||
174 | +++ src/app/webbrowser/Browser.qml 2015-10-07 00:51:42 +0000 | |||
175 | @@ -31,13 +31,15 @@ | |||
176 | 31 | BrowserView { | 31 | BrowserView { |
177 | 32 | id: browser | 32 | id: browser |
178 | 33 | 33 | ||
179 | 34 | signal closingWindow() | ||
180 | 35 | |||
181 | 34 | // Should be true when the containing window is fullscreen. | 36 | // Should be true when the containing window is fullscreen. |
182 | 35 | property bool fullscreen: false | 37 | property bool fullscreen: false |
183 | 36 | 38 | ||
184 | 37 | currentWebview: tabsModel && tabsModel.currentTab ? tabsModel.currentTab.webview : null | 39 | currentWebview: tabsModel && tabsModel.currentTab ? tabsModel.currentTab.webview : null |
185 | 38 | 40 | ||
188 | 39 | property var historyModel: (historyModelLoader.status == Loader.Ready) ? historyModelLoader.item : null | 41 | property var historyModel: HistoryModel |
189 | 40 | property var bookmarksModel: (bookmarksModelLoader.status == Loader.Ready) ? bookmarksModelLoader.item : null | 42 | property var bookmarksModel: BookmarksModel |
190 | 41 | 43 | ||
191 | 42 | property bool newSession: false | 44 | property bool newSession: false |
192 | 43 | 45 | ||
193 | @@ -54,6 +56,21 @@ | |||
194 | 54 | // tab objects (see http://pad.lv/1376433). | 56 | // tab objects (see http://pad.lv/1376433). |
195 | 55 | readonly property int maxTabsToRestore: 10 | 57 | readonly property int maxTabsToRestore: 10 |
196 | 56 | 58 | ||
197 | 59 | property alias tabContainer: tabContainer | ||
198 | 60 | property alias currentTabIndex: publicTabsModel.currentIndex | ||
199 | 61 | |||
200 | 62 | Component.onCompleted: { | ||
201 | 63 | WindowsModel.add(browser) | ||
202 | 64 | HistoryModel.databasePath = dataLocation + "/history.sqlite" | ||
203 | 65 | BookmarksModel.databasePath = dataLocation + "/bookmarks.sqlite" | ||
204 | 66 | } | ||
205 | 67 | |||
206 | 68 | Component.onDestruction: closingWindow() | ||
207 | 69 | |||
208 | 70 | onClosingWindow: { | ||
209 | 71 | WindowsModel.remove(browser) | ||
210 | 72 | } | ||
211 | 73 | |||
212 | 57 | onTabsModelChanged: { | 74 | onTabsModelChanged: { |
213 | 58 | if (incognito && privateTabsModelLoader.item) { | 75 | if (incognito && privateTabsModelLoader.item) { |
214 | 59 | browser.openUrlInNewTab("", true) | 76 | browser.openUrlInNewTab("", true) |
215 | @@ -75,6 +92,7 @@ | |||
216 | 75 | } | 92 | } |
217 | 76 | } | 93 | } |
218 | 77 | 94 | ||
219 | 95 | /* | ||
220 | 78 | actions: [ | 96 | actions: [ |
221 | 79 | Actions.GoTo { | 97 | Actions.GoTo { |
222 | 80 | onTriggered: currentWebview.url = value | 98 | onTriggered: currentWebview.url = value |
223 | @@ -98,6 +116,12 @@ | |||
224 | 98 | Actions.NewTab { | 116 | Actions.NewTab { |
225 | 99 | onTriggered: browser.openUrlInNewTab("", true) | 117 | onTriggered: browser.openUrlInNewTab("", true) |
226 | 100 | }, | 118 | }, |
227 | 119 | Actions.NewWindow { | ||
228 | 120 | onTriggered: browser.openUrlInNewWindow("") | ||
229 | 121 | }, | ||
230 | 122 | Actions.NewPrivateWindow { | ||
231 | 123 | onTriggered: browser.openUrlInNewWindow("", true) | ||
232 | 124 | }, | ||
233 | 101 | Actions.ClearHistory { | 125 | Actions.ClearHistory { |
234 | 102 | enabled: browser.historyModel | 126 | enabled: browser.historyModel |
235 | 103 | onTriggered: browser.historyModel.clearAll() | 127 | onTriggered: browser.historyModel.clearAll() |
236 | @@ -110,6 +134,7 @@ | |||
237 | 110 | } | 134 | } |
238 | 111 | } | 135 | } |
239 | 112 | ] | 136 | ] |
240 | 137 | */ | ||
241 | 113 | 138 | ||
242 | 114 | Settings { | 139 | Settings { |
243 | 115 | id: settings | 140 | id: settings |
244 | @@ -335,7 +360,7 @@ | |||
245 | 335 | y: webview ? webview.locationBarController.offset : 0 | 360 | y: webview ? webview.locationBarController.offset : 0 |
246 | 336 | 361 | ||
247 | 337 | function isCurrentUrlBookmarked() { | 362 | function isCurrentUrlBookmarked() { |
249 | 338 | return ((webview && browser.bookmarksModel) ? browser.bookmarksModel.contains(webview.url) : false) | 363 | return ((webview && BookmarksModel) ? BookmarksModel.contains(webview.url) : false) |
250 | 339 | } | 364 | } |
251 | 340 | bookmarked: isCurrentUrlBookmarked() | 365 | bookmarked: isCurrentUrlBookmarked() |
252 | 341 | onToggleBookmark: { | 366 | onToggleBookmark: { |
253 | @@ -348,7 +373,7 @@ | |||
254 | 348 | onUrlChanged: chrome.bookmarked = chrome.isCurrentUrlBookmarked() | 373 | onUrlChanged: chrome.bookmarked = chrome.isCurrentUrlBookmarked() |
255 | 349 | } | 374 | } |
256 | 350 | Connections { | 375 | Connections { |
258 | 351 | target: browser.bookmarksModel | 376 | target: BookmarksModel |
259 | 352 | onAdded: if (!chrome.bookmarked && (url === chrome.webview.url)) chrome.bookmarked = true | 377 | onAdded: if (!chrome.bookmarked && (url === chrome.webview.url)) chrome.bookmarked = true |
260 | 353 | onRemoved: if (chrome.bookmarked && (url === chrome.webview.url)) chrome.bookmarked = false | 378 | onRemoved: if (chrome.bookmarked && (url === chrome.webview.url)) chrome.bookmarked = false |
261 | 354 | } | 379 | } |
262 | @@ -395,6 +420,20 @@ | |||
263 | 395 | onTriggered: browser.openUrlInNewTab("", true) | 420 | onTriggered: browser.openUrlInNewTab("", true) |
264 | 396 | }, | 421 | }, |
265 | 397 | Action { | 422 | Action { |
266 | 423 | objectName: "newwindow" | ||
267 | 424 | text: i18n.tr("New window") | ||
268 | 425 | iconName: "note-new" | ||
269 | 426 | visible: (formFactor === "desktop") | ||
270 | 427 | onTriggered: browser.openUrlInNewWindow("") | ||
271 | 428 | }, | ||
272 | 429 | Action { | ||
273 | 430 | objectName: "newprivatewindow" | ||
274 | 431 | text: i18n.tr("New private window") | ||
275 | 432 | iconName: "note-new" | ||
276 | 433 | visible: (formFactor === "desktop") | ||
277 | 434 | onTriggered: browser.openUrlInNewWindow("", true) | ||
278 | 435 | }, | ||
279 | 436 | Action { | ||
280 | 398 | objectName: "findinpage" | 437 | objectName: "findinpage" |
281 | 399 | text: i18n.tr("Find in page") | 438 | text: i18n.tr("Find in page") |
282 | 400 | iconName: "search" | 439 | iconName: "search" |
283 | @@ -899,19 +938,7 @@ | |||
284 | 899 | } | 938 | } |
285 | 900 | } | 939 | } |
286 | 901 | } | 940 | } |
300 | 902 | 941 | ||
288 | 903 | Loader { | ||
289 | 904 | id: historyModelLoader | ||
290 | 905 | source: "HistoryModel.qml" | ||
291 | 906 | asynchronous: true | ||
292 | 907 | } | ||
293 | 908 | |||
294 | 909 | Loader { | ||
295 | 910 | id: bookmarksModelLoader | ||
296 | 911 | source: "BookmarksModel.qml" | ||
297 | 912 | asynchronous: true | ||
298 | 913 | } | ||
299 | 914 | |||
301 | 915 | Component { | 942 | Component { |
302 | 916 | id: tabComponent | 943 | id: tabComponent |
303 | 917 | 944 | ||
304 | @@ -961,6 +988,16 @@ | |||
305 | 961 | (formFactor === "desktop"))) | 988 | (formFactor === "desktop"))) |
306 | 962 | onTriggered: browser.openUrlInNewTab(contextModel.linkUrl, false) | 989 | onTriggered: browser.openUrlInNewTab(contextModel.linkUrl, false) |
307 | 963 | } | 990 | } |
308 | 991 | Actions.OpenLinkInNewWindow { | ||
309 | 992 | objectName: "openLinkInNewWindowContextualAction" | ||
310 | 993 | enabled: contextModel && contextModel.linkUrl.toString() && formFactor === "desktop" | ||
311 | 994 | onTriggered: browser.openUrlInNewWindow(contextModel.linkUrl) | ||
312 | 995 | } | ||
313 | 996 | Actions.OpenLinkInNewPrivateWindow { | ||
314 | 997 | objectName: "OpenLinkInNewPrivateWindowContextualAction" | ||
315 | 998 | enabled: contextModel && contextModel.linkUrl.toString() && formFactor === "desktop" | ||
316 | 999 | onTriggered: browser.openUrlInNewWindow(contextModel.linkUrl, true) | ||
317 | 1000 | } | ||
318 | 964 | Actions.BookmarkLink { | 1001 | Actions.BookmarkLink { |
319 | 965 | objectName: "BookmarkLinkContextualAction" | 1002 | objectName: "BookmarkLinkContextualAction" |
320 | 966 | enabled: contextModel && contextModel.linkUrl.toString() && | 1003 | enabled: contextModel && contextModel.linkUrl.toString() && |
321 | @@ -1364,6 +1401,27 @@ | |||
322 | 1364 | } | 1401 | } |
323 | 1365 | } | 1402 | } |
324 | 1366 | 1403 | ||
325 | 1404 | function openUrlInNewWindow(url, incognito) { | ||
326 | 1405 | incognito = typeof incognito !== 'undefined' ? incognito : false | ||
327 | 1406 | |||
328 | 1407 | var component = Qt.createComponent("./webbrowser-app.qml") | ||
329 | 1408 | if (component.status == Component.Ready) { | ||
330 | 1409 | var newWindow = component.createObject() | ||
331 | 1410 | |||
332 | 1411 | newWindow.incognito = incognito | ||
333 | 1412 | |||
334 | 1413 | if (url.toString()) { | ||
335 | 1414 | newWindow.urls = [url] | ||
336 | 1415 | } | ||
337 | 1416 | newWindow.show() | ||
338 | 1417 | return newWindow | ||
339 | 1418 | } | ||
340 | 1419 | } | ||
341 | 1420 | |||
342 | 1421 | function restoreTab(tab, setCurrent) { | ||
343 | 1422 | internal.addTab(tab, setCurrent) | ||
344 | 1423 | } | ||
345 | 1424 | |||
346 | 1367 | SessionStorage { | 1425 | SessionStorage { |
347 | 1368 | id: session | 1426 | id: session |
348 | 1369 | 1427 | ||
349 | @@ -1373,12 +1431,27 @@ | |||
350 | 1373 | if (!locked) { | 1431 | if (!locked) { |
351 | 1374 | return | 1432 | return |
352 | 1375 | } | 1433 | } |
359 | 1376 | var tabs = [] | 1434 | |
360 | 1377 | for (var i = 0; i < publicTabsModel.count; ++i) { | 1435 | var session = { |
361 | 1378 | var tab = publicTabsModel.get(i) | 1436 | 'windows': [] |
362 | 1379 | tabs.push(serializeTabState(tab)) | 1437 | } |
363 | 1380 | } | 1438 | |
364 | 1381 | store(JSON.stringify({tabs: tabs, currentIndex: publicTabsModel.currentIndex})) | 1439 | for (var i = 0; i < WindowsModel.count; ++i) { |
365 | 1440 | var window = WindowsModel.get(i) | ||
366 | 1441 | var tabs = window.tabsModel | ||
367 | 1442 | var sessionWindow = { | ||
368 | 1443 | 'tabs': [], | ||
369 | 1444 | 'currentIndex': tabsModel.currentIndex | ||
370 | 1445 | } | ||
371 | 1446 | |||
372 | 1447 | for (var j = 0; j < tabsModel.count; ++j) { | ||
373 | 1448 | var tab = tabs.get(j) | ||
374 | 1449 | sessionWindow.tabs.push(serializeTabState(tab)) | ||
375 | 1450 | } | ||
376 | 1451 | |||
377 | 1452 | session.windows.push(sessionWindow) | ||
378 | 1453 | } | ||
379 | 1454 | store(JSON.stringify(session)) | ||
380 | 1382 | } | 1455 | } |
381 | 1383 | 1456 | ||
382 | 1384 | function restore() { | 1457 | function restore() { |
383 | @@ -1392,16 +1465,28 @@ | |||
384 | 1392 | return | 1465 | return |
385 | 1393 | } | 1466 | } |
386 | 1394 | if (state) { | 1467 | if (state) { |
392 | 1395 | var tabs = state.tabs | 1468 | var windows = state.windows |
393 | 1396 | if (tabs) { | 1469 | if (windows) { |
394 | 1397 | for (var i = 0; i < Math.min(tabs.length, browser.maxTabsToRestore); ++i) { | 1470 | for (var w = 0; w < windows.length; ++w) { |
395 | 1398 | var tab = createTabFromState(tabs[i]) | 1471 | var windowBrowser = browser |
396 | 1399 | internal.addTab(tab, i == 0) | 1472 | if (w > 0) { |
397 | 1473 | var newWindow = browser.openUrlInNewWindow("") | ||
398 | 1474 | windowBrowser = newWindow.browser | ||
399 | 1475 | } | ||
400 | 1476 | |||
401 | 1477 | var tabs = windows[w].tabs | ||
402 | 1478 | if (tabs) { | ||
403 | 1479 | for (var t = 0; t < Math.min(tabs.length, windowBrowser.maxTabsToRestore); ++t) { | ||
404 | 1480 | var tab = createTabFromState(tabs[t], windowBrowser.tabContainer) | ||
405 | 1481 | windowBrowser.restoreTab(tab, t == 0) | ||
406 | 1482 | } | ||
407 | 1483 | } | ||
408 | 1484 | |||
409 | 1485 | if ('currentIndex' in windows[w]) { | ||
410 | 1486 | windowBrowser.currentTabIndex = windows[w].currentIndex | ||
411 | 1487 | } | ||
412 | 1400 | } | 1488 | } |
413 | 1401 | } | 1489 | } |
414 | 1402 | if ('currentIndex' in state) { | ||
415 | 1403 | publicTabsModel.currentIndex = state.currentIndex | ||
416 | 1404 | } | ||
417 | 1405 | } | 1490 | } |
418 | 1406 | } | 1491 | } |
419 | 1407 | 1492 | ||
420 | @@ -1417,7 +1502,7 @@ | |||
421 | 1417 | return state | 1502 | return state |
422 | 1418 | } | 1503 | } |
423 | 1419 | 1504 | ||
425 | 1420 | function createTabFromState(state) { | 1505 | function createTabFromState(state, container) { |
426 | 1421 | var properties = {'initialUrl': state.url, 'initialTitle': state.title} | 1506 | var properties = {'initialUrl': state.url, 'initialTitle': state.title} |
427 | 1422 | if ('uniqueId' in state) { | 1507 | if ('uniqueId' in state) { |
428 | 1423 | properties["uniqueId"] = state.uniqueId | 1508 | properties["uniqueId"] = state.uniqueId |
429 | @@ -1432,7 +1517,7 @@ | |||
430 | 1432 | properties['restoreState'] = state.savedState | 1517 | properties['restoreState'] = state.savedState |
431 | 1433 | properties['restoreType'] = Oxide.WebView.RestoreLastSessionExitedCleanly | 1518 | properties['restoreType'] = Oxide.WebView.RestoreLastSessionExitedCleanly |
432 | 1434 | } | 1519 | } |
434 | 1435 | return tabComponent.createObject(tabContainer, properties) | 1520 | return tabComponent.createObject(container, properties) |
435 | 1436 | } | 1521 | } |
436 | 1437 | } | 1522 | } |
437 | 1438 | Timer { | 1523 | Timer { |
438 | 1439 | 1524 | ||
439 | === modified file 'src/app/webbrowser/CMakeLists.txt' | |||
440 | --- src/app/webbrowser/CMakeLists.txt 2015-09-22 01:27:19 +0000 | |||
441 | +++ src/app/webbrowser/CMakeLists.txt 2015-10-07 00:51:42 +0000 | |||
442 | @@ -24,6 +24,7 @@ | |||
443 | 24 | tabs-model.cpp | 24 | tabs-model.cpp |
444 | 25 | text-search-filter-model.cpp | 25 | text-search-filter-model.cpp |
445 | 26 | top-sites-model.cpp | 26 | top-sites-model.cpp |
446 | 27 | windows-model.cpp | ||
447 | 27 | ) | 28 | ) |
448 | 28 | 29 | ||
449 | 29 | set(WEBBROWSER_APP_MODELS webbrowser-app-models) | 30 | set(WEBBROWSER_APP_MODELS webbrowser-app-models) |
450 | 30 | 31 | ||
451 | === removed file 'src/app/webbrowser/HistoryModel.qml' | |||
452 | --- src/app/webbrowser/HistoryModel.qml 2015-08-10 15:22:00 +0000 | |||
453 | +++ src/app/webbrowser/HistoryModel.qml 1970-01-01 00:00:00 +0000 | |||
454 | @@ -1,24 +0,0 @@ | |||
455 | 1 | /* | ||
456 | 2 | * Copyright 2014-2015 Canonical Ltd. | ||
457 | 3 | * | ||
458 | 4 | * This file is part of webbrowser-app. | ||
459 | 5 | * | ||
460 | 6 | * webbrowser-app is free software; you can redistribute it and/or modify | ||
461 | 7 | * it under the terms of the GNU General Public License as published by | ||
462 | 8 | * the Free Software Foundation; version 3. | ||
463 | 9 | * | ||
464 | 10 | * webbrowser-app is distributed in the hope that it will be useful, | ||
465 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
466 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
467 | 13 | * GNU General Public License for more details. | ||
468 | 14 | * | ||
469 | 15 | * You should have received a copy of the GNU General Public License | ||
470 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
471 | 17 | */ | ||
472 | 18 | |||
473 | 19 | import QtQuick 2.4 | ||
474 | 20 | import webbrowserapp.private 0.1 | ||
475 | 21 | |||
476 | 22 | HistoryModel { | ||
477 | 23 | databasePath: dataLocation + "/history.sqlite" | ||
478 | 24 | } | ||
479 | 25 | 0 | ||
480 | === modified file 'src/app/webbrowser/webbrowser-app.cpp' | |||
481 | --- src/app/webbrowser/webbrowser-app.cpp 2015-08-19 13:16:06 +0000 | |||
482 | +++ src/app/webbrowser/webbrowser-app.cpp 2015-10-07 00:51:42 +0000 | |||
483 | @@ -32,6 +32,7 @@ | |||
484 | 32 | #include "text-search-filter-model.h" | 32 | #include "text-search-filter-model.h" |
485 | 33 | #include "tabs-model.h" | 33 | #include "tabs-model.h" |
486 | 34 | #include "top-sites-model.h" | 34 | #include "top-sites-model.h" |
487 | 35 | #include "windows-model.h" | ||
488 | 35 | #include "webbrowser-app.h" | 36 | #include "webbrowser-app.h" |
489 | 36 | 37 | ||
490 | 37 | // Qt | 38 | // Qt |
491 | @@ -64,24 +65,46 @@ | |||
492 | 64 | return new CacheDeleter(); | 65 | return new CacheDeleter(); |
493 | 65 | } | 66 | } |
494 | 66 | 67 | ||
495 | 68 | static QObject* HistoryModel_singleton_factory(QQmlEngine* engine, QJSEngine* scriptEngine) | ||
496 | 69 | { | ||
497 | 70 | Q_UNUSED(engine); | ||
498 | 71 | Q_UNUSED(scriptEngine); | ||
499 | 72 | return new HistoryModel(); | ||
500 | 73 | } | ||
501 | 74 | |||
502 | 75 | static QObject* BookmarksModel_singleton_factory(QQmlEngine* engine, QJSEngine* scriptEngine) | ||
503 | 76 | { | ||
504 | 77 | Q_UNUSED(engine); | ||
505 | 78 | Q_UNUSED(scriptEngine); | ||
506 | 79 | return new BookmarksModel(); | ||
507 | 80 | } | ||
508 | 81 | |||
509 | 82 | static QObject* WindowsModel_singleton_factory(QQmlEngine* engine, QJSEngine* scriptEngine) | ||
510 | 83 | { | ||
511 | 84 | Q_UNUSED(engine); | ||
512 | 85 | Q_UNUSED(scriptEngine); | ||
513 | 86 | return new WindowsModel(); | ||
514 | 87 | } | ||
515 | 88 | |||
516 | 67 | bool WebbrowserApp::initialize() | 89 | bool WebbrowserApp::initialize() |
517 | 68 | { | 90 | { |
518 | 69 | const char* uri = "webbrowserapp.private"; | 91 | const char* uri = "webbrowserapp.private"; |
522 | 70 | qmlRegisterType<HistoryModel>(uri, 0, 1, "HistoryModel"); | 92 | qmlRegisterSingletonType<BookmarksModel>(uri, 0, 1, "BookmarksModel", BookmarksModel_singleton_factory); |
523 | 71 | qmlRegisterType<HistoryTimeframeModel>(uri, 0, 1, "HistoryTimeframeModel"); | 93 | qmlRegisterSingletonType<CacheDeleter>(uri, 0, 1, "CacheDeleter", CacheDeleter_singleton_factory); |
524 | 72 | qmlRegisterType<TopSitesModel>(uri, 0 , 1, "TopSitesModel"); | 94 | qmlRegisterSingletonType<FileOperations>(uri, 0, 1, "FileOperations", FileOperations_singleton_factory); |
525 | 95 | qmlRegisterSingletonType<HistoryModel>(uri, 0, 1, "HistoryModel", HistoryModel_singleton_factory); | ||
526 | 96 | qmlRegisterSingletonType<WindowsModel>(uri, 0, 1, "WindowsModel", WindowsModel_singleton_factory); | ||
527 | 97 | qmlRegisterType<BookmarksFolderListModel>(uri, 0, 1, "BookmarksFolderListModel"); | ||
528 | 98 | qmlRegisterType<HistoryDomainListChronologicalModel>(uri, 0, 1, "HistoryDomainListChronologicalModel"); | ||
529 | 73 | qmlRegisterType<HistoryDomainListModel>(uri, 0, 1, "HistoryDomainListModel"); | 99 | qmlRegisterType<HistoryDomainListModel>(uri, 0, 1, "HistoryDomainListModel"); |
530 | 74 | qmlRegisterType<HistoryDomainListChronologicalModel>(uri, 0, 1, "HistoryDomainListChronologicalModel"); | ||
531 | 75 | qmlRegisterType<HistoryLastVisitDateListModel>(uri, 0, 1, "HistoryLastVisitDateListModel"); | 100 | qmlRegisterType<HistoryLastVisitDateListModel>(uri, 0, 1, "HistoryLastVisitDateListModel"); |
532 | 76 | qmlRegisterType<HistoryLastVisitDateModel>(uri, 0, 1, "HistoryLastVisitDateModel"); | 101 | qmlRegisterType<HistoryLastVisitDateModel>(uri, 0, 1, "HistoryLastVisitDateModel"); |
533 | 102 | qmlRegisterType<HistoryTimeframeModel>(uri, 0, 1, "HistoryTimeframeModel"); | ||
534 | 77 | qmlRegisterType<LimitProxyModel>(uri, 0 , 1, "LimitProxyModel"); | 103 | qmlRegisterType<LimitProxyModel>(uri, 0 , 1, "LimitProxyModel"); |
535 | 104 | qmlRegisterType<SearchEngine>(uri, 0, 1, "SearchEngine"); | ||
536 | 78 | qmlRegisterType<TabsModel>(uri, 0, 1, "TabsModel"); | 105 | qmlRegisterType<TabsModel>(uri, 0, 1, "TabsModel"); |
537 | 79 | qmlRegisterType<BookmarksModel>(uri, 0, 1, "BookmarksModel"); | ||
538 | 80 | qmlRegisterType<BookmarksFolderListModel>(uri, 0, 1, "BookmarksFolderListModel"); | ||
539 | 81 | qmlRegisterSingletonType<FileOperations>(uri, 0, 1, "FileOperations", FileOperations_singleton_factory); | ||
540 | 82 | qmlRegisterType<SearchEngine>(uri, 0, 1, "SearchEngine"); | ||
541 | 83 | qmlRegisterSingletonType<CacheDeleter>(uri, 0, 1, "CacheDeleter", CacheDeleter_singleton_factory); | ||
542 | 84 | qmlRegisterType<TextSearchFilterModel>(uri, 0, 1, "TextSearchFilterModel"); | 106 | qmlRegisterType<TextSearchFilterModel>(uri, 0, 1, "TextSearchFilterModel"); |
543 | 107 | qmlRegisterType<TopSitesModel>(uri, 0 , 1, "TopSitesModel"); | ||
544 | 85 | 108 | ||
545 | 86 | if (BrowserApplication::initialize("webbrowser/webbrowser-app.qml")) { | 109 | if (BrowserApplication::initialize("webbrowser/webbrowser-app.qml")) { |
546 | 87 | QStringList searchEnginesSearchPaths; | 110 | QStringList searchEnginesSearchPaths; |
547 | @@ -122,6 +145,14 @@ | |||
548 | 122 | int main(int argc, char** argv) | 145 | int main(int argc, char** argv) |
549 | 123 | { | 146 | { |
550 | 124 | QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts); | 147 | QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts); |
551 | 148 | |||
552 | 149 | // Make sure that only a single instance of webbrowser is running | ||
553 | 150 | const char *sharedMemKey = "webbrowser-app"; | ||
554 | 151 | QSharedMemory sharedMem(sharedMemKey); | ||
555 | 152 | if (!sharedMem.create(1, QSharedMemory::ReadOnly)) { | ||
556 | 153 | return 0; | ||
557 | 154 | } | ||
558 | 155 | |||
559 | 125 | WebbrowserApp app(argc, argv); | 156 | WebbrowserApp app(argc, argv); |
560 | 126 | if (app.initialize()) { | 157 | if (app.initialize()) { |
561 | 127 | return app.run(); | 158 | return app.run(); |
562 | 128 | 159 | ||
563 | === modified file 'src/app/webbrowser/webbrowser-app.qml' | |||
564 | --- src/app/webbrowser/webbrowser-app.qml 2015-08-10 15:33:43 +0000 | |||
565 | +++ src/app/webbrowser/webbrowser-app.qml 2015-10-07 00:51:42 +0000 | |||
566 | @@ -24,11 +24,15 @@ | |||
567 | 24 | BrowserWindow { | 24 | BrowserWindow { |
568 | 25 | id: window | 25 | id: window |
569 | 26 | 26 | ||
570 | 27 | property bool incognito: false | ||
571 | 27 | property alias urls: browser.initialUrls | 28 | property alias urls: browser.initialUrls |
572 | 28 | property alias newSession: browser.newSession | 29 | property alias newSession: browser.newSession |
573 | 30 | property alias browser: browser | ||
574 | 29 | 31 | ||
575 | 30 | currentWebview: browser.currentWebview | 32 | currentWebview: browser.currentWebview |
576 | 31 | 33 | ||
577 | 34 | onClosing: browser.closingWindow() | ||
578 | 35 | |||
579 | 32 | title: { | 36 | title: { |
580 | 33 | if (browser.title) { | 37 | if (browser.title) { |
581 | 34 | // TRANSLATORS: %1 refers to the current page’s title | 38 | // TRANSLATORS: %1 refers to the current page’s title |
582 | @@ -44,9 +48,13 @@ | |||
583 | 44 | webbrowserWindow: webbrowserWindowProxy | 48 | webbrowserWindow: webbrowserWindowProxy |
584 | 45 | developerExtrasEnabled: window.developerExtrasEnabled | 49 | developerExtrasEnabled: window.developerExtrasEnabled |
585 | 46 | 50 | ||
586 | 51 | incognito: window.incognito | ||
587 | 52 | |||
588 | 47 | fullscreen: window.visibility === Window.FullScreen | 53 | fullscreen: window.visibility === Window.FullScreen |
589 | 48 | 54 | ||
591 | 49 | Component.onCompleted: i18n.domain = "webbrowser-app" | 55 | Component.onCompleted: { |
592 | 56 | i18n.domain = "webbrowser-app" | ||
593 | 57 | } | ||
594 | 50 | 58 | ||
595 | 51 | Keys.onPressed: { | 59 | Keys.onPressed: { |
596 | 52 | if ((event.key === Qt.Key_F11) && (event.modifiers === Qt.NoModifier)) { | 60 | if ((event.key === Qt.Key_F11) && (event.modifiers === Qt.NoModifier)) { |
597 | 53 | 61 | ||
598 | === added file 'src/app/webbrowser/windows-model.cpp' | |||
599 | --- src/app/webbrowser/windows-model.cpp 1970-01-01 00:00:00 +0000 | |||
600 | +++ src/app/webbrowser/windows-model.cpp 2015-10-07 00:51:42 +0000 | |||
601 | @@ -0,0 +1,106 @@ | |||
602 | 1 | /* | ||
603 | 2 | * Copyright 2015 Canonical Ltd. | ||
604 | 3 | * | ||
605 | 4 | * This file is part of webbrowser-app. | ||
606 | 5 | * | ||
607 | 6 | * webbrowser-app is free software; you can redistribute it and/or modify | ||
608 | 7 | * it under the terms of the GNU General Public License as published by | ||
609 | 8 | * the Free Software Foundation; version 3. | ||
610 | 9 | * | ||
611 | 10 | * webbrowser-app is distributed in the hope that it will be useful, | ||
612 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
613 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
614 | 13 | * GNU General Public License for more details. | ||
615 | 14 | * | ||
616 | 15 | * You should have received a copy of the GNU General Public License | ||
617 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
618 | 17 | */ | ||
619 | 18 | |||
620 | 19 | #include "windows-model.h" | ||
621 | 20 | |||
622 | 21 | // Qt | ||
623 | 22 | #include <QtCore/QDebug> | ||
624 | 23 | #include <QtCore/QObject> | ||
625 | 24 | |||
626 | 25 | /*! | ||
627 | 26 | \class WindowsModel | ||
628 | 27 | \brief List model that stores the list of currently open windows. | ||
629 | 28 | |||
630 | 29 | WindowsModel is a list model that stores the list of currently open windowss. | ||
631 | 30 | Each window holds a pointer to a Window and associated metadata (id). | ||
632 | 31 | |||
633 | 32 | The model doesn’t own the Window, so it is the responsibility of whoever | ||
634 | 33 | adds a window to instantiate the corresponding Window, and to destroy it after | ||
635 | 34 | it’s removed from the model. | ||
636 | 35 | */ | ||
637 | 36 | WindowsModel::WindowsModel(QObject* parent) | ||
638 | 37 | : QAbstractListModel(parent) | ||
639 | 38 | { | ||
640 | 39 | } | ||
641 | 40 | |||
642 | 41 | WindowsModel::~WindowsModel() | ||
643 | 42 | { | ||
644 | 43 | } | ||
645 | 44 | |||
646 | 45 | QHash<int, QByteArray> WindowsModel::roleNames() const | ||
647 | 46 | { | ||
648 | 47 | static QHash<int, QByteArray> roles; | ||
649 | 48 | if (roles.isEmpty()) { | ||
650 | 49 | roles[TabsModel] = "tabsModel"; | ||
651 | 50 | } | ||
652 | 51 | return roles; | ||
653 | 52 | } | ||
654 | 53 | |||
655 | 54 | int WindowsModel::rowCount(const QModelIndex& parent) const | ||
656 | 55 | { | ||
657 | 56 | Q_UNUSED(parent); | ||
658 | 57 | return m_windows.count(); | ||
659 | 58 | } | ||
660 | 59 | |||
661 | 60 | QVariant WindowsModel::data(const QModelIndex& index, int role) const | ||
662 | 61 | { | ||
663 | 62 | if (!index.isValid()) { | ||
664 | 63 | return QVariant(); | ||
665 | 64 | } | ||
666 | 65 | QObject* window = m_windows.at(index.row()); | ||
667 | 66 | switch (role) { | ||
668 | 67 | case TabsModel: | ||
669 | 68 | return window->property("urls"); | ||
670 | 69 | default: | ||
671 | 70 | return QVariant(); | ||
672 | 71 | } | ||
673 | 72 | } | ||
674 | 73 | |||
675 | 74 | void WindowsModel::add(QObject* window) | ||
676 | 75 | { | ||
677 | 76 | if (window == nullptr) { | ||
678 | 77 | qWarning() << "Invalid Window"; | ||
679 | 78 | return; | ||
680 | 79 | } | ||
681 | 80 | int index = m_windows.count(); | ||
682 | 81 | beginInsertRows(QModelIndex(), index, index); | ||
683 | 82 | m_windows.append(window); | ||
684 | 83 | endInsertRows(); | ||
685 | 84 | Q_EMIT countChanged(); | ||
686 | 85 | } | ||
687 | 86 | |||
688 | 87 | void WindowsModel::remove(QObject* window) | ||
689 | 88 | { | ||
690 | 89 | int index = m_windows.indexOf(window); | ||
691 | 90 | if (index < 0) { | ||
692 | 91 | return; | ||
693 | 92 | } | ||
694 | 93 | beginRemoveRows(QModelIndex(), index, index); | ||
695 | 94 | m_windows.removeAt(index); | ||
696 | 95 | endRemoveRows(); | ||
697 | 96 | Q_EMIT countChanged(); | ||
698 | 97 | } | ||
699 | 98 | |||
700 | 99 | QObject* WindowsModel::get(int index) const | ||
701 | 100 | { | ||
702 | 101 | if ((index < 0) || (index >= m_windows.count())) { | ||
703 | 102 | qWarning() << "Invalid window index:" << index; | ||
704 | 103 | return nullptr; | ||
705 | 104 | } | ||
706 | 105 | return m_windows.at(index); | ||
707 | 106 | } | ||
708 | 0 | 107 | ||
709 | === added file 'src/app/webbrowser/windows-model.h' | |||
710 | --- src/app/webbrowser/windows-model.h 1970-01-01 00:00:00 +0000 | |||
711 | +++ src/app/webbrowser/windows-model.h 2015-10-07 00:51:42 +0000 | |||
712 | @@ -0,0 +1,60 @@ | |||
713 | 1 | /* | ||
714 | 2 | * Copyright 2015 Canonical Ltd. | ||
715 | 3 | * | ||
716 | 4 | * This file is part of webbrowser-app. | ||
717 | 5 | * | ||
718 | 6 | * webbrowser-app is free software; you can redistribute it and/or modify | ||
719 | 7 | * it under the terms of the GNU General Public License as published by | ||
720 | 8 | * the Free Software Foundation; version 3. | ||
721 | 9 | * | ||
722 | 10 | * webbrowser-app is distributed in the hope that it will be useful, | ||
723 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
724 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
725 | 13 | * GNU General Public License for more details. | ||
726 | 14 | * | ||
727 | 15 | * You should have received a copy of the GNU General Public License | ||
728 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
729 | 17 | */ | ||
730 | 18 | |||
731 | 19 | #ifndef __WINDOWS_MODEL_H__ | ||
732 | 20 | #define __WINDOWS_MODEL_H__ | ||
733 | 21 | |||
734 | 22 | // Qt | ||
735 | 23 | #include <QtCore/QAbstractListModel> | ||
736 | 24 | #include <QtCore/QList> | ||
737 | 25 | |||
738 | 26 | class QObject; | ||
739 | 27 | |||
740 | 28 | class WindowsModel : public QAbstractListModel | ||
741 | 29 | { | ||
742 | 30 | Q_OBJECT | ||
743 | 31 | |||
744 | 32 | Q_ENUMS(Roles) | ||
745 | 33 | |||
746 | 34 | Q_PROPERTY(int count READ rowCount NOTIFY countChanged) | ||
747 | 35 | |||
748 | 36 | public: | ||
749 | 37 | WindowsModel(QObject* parent=0); | ||
750 | 38 | ~WindowsModel(); | ||
751 | 39 | |||
752 | 40 | enum Roles { | ||
753 | 41 | TabsModel = Qt::UserRole + 1, | ||
754 | 42 | }; | ||
755 | 43 | |||
756 | 44 | // reimplemented from QAbstractListModel | ||
757 | 45 | QHash<int, QByteArray> roleNames() const; | ||
758 | 46 | int rowCount(const QModelIndex& parent=QModelIndex()) const; | ||
759 | 47 | QVariant data(const QModelIndex& index, int role) const; | ||
760 | 48 | |||
761 | 49 | Q_INVOKABLE void add(QObject* window); | ||
762 | 50 | Q_INVOKABLE void remove(QObject* window); | ||
763 | 51 | Q_INVOKABLE QObject* get(int index) const; | ||
764 | 52 | |||
765 | 53 | Q_SIGNALS: | ||
766 | 54 | void countChanged() const; | ||
767 | 55 | |||
768 | 56 | private: | ||
769 | 57 | QList<QObject*> m_windows; | ||
770 | 58 | }; | ||
771 | 59 | |||
772 | 60 | #endif // __WINDOWS_MODEL_H__ |
FAILED: Continuous integration, rev:1206 jenkins. qa.ubuntu. com/job/ webbrowser- app-ci/ 2292/ jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- vivid-touch/ 4392 jenkins. qa.ubuntu. com/job/ webbrowser- app-vivid- amd64-ci/ 1046 jenkins. qa.ubuntu. com/job/ webbrowser- app-vivid- armhf-ci/ 1046 jenkins. qa.ubuntu. com/job/ webbrowser- app-vivid- armhf-ci/ 1046/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ webbrowser- app-vivid- i386-ci/ 1046/console jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- runner- vivid-mako/ 3575 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- vivid-armhf/ 4389 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- vivid-armhf/ 4389/artifact/ work/output/ *zip*/output. zip s-jenkins. ubuntu- ci:8080/ job/touch- flash-device/ 23730
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
FAILURE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/webbrowser- app-ci/ 2292/rebuild
http://