Merge lp:~osomon/webbrowser-app/keyboard-nav-narrow into lp:webbrowser-app
- keyboard-nav-narrow
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Olivier Tilloy | ||||
Approved revision: | 1363 | ||||
Merged at revision: | 1350 | ||||
Proposed branch: | lp:~osomon/webbrowser-app/keyboard-nav-narrow | ||||
Merge into: | lp:webbrowser-app | ||||
Prerequisite: | lp:~osomon/webbrowser-app/bottomedgebar-autopilot-tests | ||||
Diff against target: |
2400 lines (+1100/-505) 25 files modified
src/app/webbrowser/BookmarksFoldersView.qml (+212/-125) src/app/webbrowser/BookmarksFoldersViewWide.qml (+1/-6) src/app/webbrowser/BookmarksView.qml (+2/-3) src/app/webbrowser/Browser.qml (+33/-29) src/app/webbrowser/BrowserPageHeader.qml (+2/-1) src/app/webbrowser/DownloadDelegate.qml (+1/-0) src/app/webbrowser/DownloadsPage.qml (+21/-4) src/app/webbrowser/ExpandedHistoryView.qml (+16/-6) src/app/webbrowser/HistoryView.qml (+13/-3) src/app/webbrowser/ListViewHighlight.qml (+11/-2) src/app/webbrowser/NewTabView.qml (+245/-130) src/app/webbrowser/NewTabViewWide.qml (+1/-11) src/app/webbrowser/ToolbarAction.qml (+1/-0) src/app/webbrowser/UrlDelegate.qml (+16/-5) src/app/webbrowser/UrlPreviewDelegate.qml (+5/-1) src/app/webbrowser/UrlPreviewGrid.qml (+23/-16) src/app/webbrowser/UrlsList.qml (+0/-52) tests/autopilot/webbrowser_app/emulators/browser.py (+9/-17) tests/autopilot/webbrowser_app/tests/test_new_tab_view.py (+13/-18) tests/unittests/qml/CMakeLists.txt (+2/-0) tests/unittests/qml/tst_BookmarksView.qml (+82/-3) tests/unittests/qml/tst_HistoryView.qml (+50/-4) tests/unittests/qml/tst_NewTabView.qml (+292/-0) tests/unittests/qml/tst_NewTabViewWide.qml (+1/-10) tests/unittests/qml/tst_QmlTests.cpp (+48/-59) |
||||
To merge this branch: | bzr merge lp:~osomon/webbrowser-app/keyboard-nav-narrow | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Needs Fixing | |
Ubuntu Phablet Team | Pending | ||
Review via email:
|
Commit message
Add keyboard navigation support to narrow views (new tab view, history view, bookmarks view, downloads view).
Description of the change
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
- 1360. By Olivier Tilloy
-
Ensure the state of the NewTabView under test is reset between each test run.
- 1361. By Olivier Tilloy
-
Clip expanded history view contents so list items are not drawn over the header.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1360
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1361
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 1362. By Olivier Tilloy
-
Show the keyboard highlight only when there’s actually a physical keyboard connected.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1362
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 1363. By Olivier Tilloy
-
Fix unit tests.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1363
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file 'src/app/webbrowser/BookmarksFoldersView.qml' |
2 | --- src/app/webbrowser/BookmarksFoldersView.qml 2015-11-12 16:16:15 +0000 |
3 | +++ src/app/webbrowser/BookmarksFoldersView.qml 2016-02-11 08:27:04 +0000 |
4 | @@ -1,5 +1,5 @@ |
5 | /* |
6 | - * Copyright 2015 Canonical Ltd. |
7 | + * Copyright 2015-2016 Canonical Ltd. |
8 | * |
9 | * This file is part of webbrowser-app. |
10 | * |
11 | @@ -28,6 +28,8 @@ |
12 | property alias interactive: bookmarksFolderListView.interactive |
13 | property url homeBookmarkUrl |
14 | |
15 | + readonly property Item currentItem: bookmarksFolderListView.currentItem ? bookmarksFolderListView.currentItem.currentItem : null |
16 | + |
17 | signal bookmarkClicked(url url) |
18 | signal bookmarkRemoved(url url) |
19 | |
20 | @@ -54,10 +56,28 @@ |
21 | } |
22 | |
23 | height: active ? item.height : 0 |
24 | - active: entries.count > 0 |
25 | - |
26 | - sourceComponent: Item { |
27 | + active: (entries.count > 0) || !folder |
28 | + |
29 | + readonly property Item currentItem: active ? item.currentItem : null |
30 | + |
31 | + onActiveChanged: { |
32 | + if (!active && activeFocus) { |
33 | + bookmarksFolderListView.decrementCurrentIndex() |
34 | + } |
35 | + } |
36 | + |
37 | + sourceComponent: FocusScope { |
38 | objectName: "bookmarkFolderDelegate" |
39 | + focus: true |
40 | + |
41 | + readonly property Item currentItem: activeFocus ? (bookmarkFolderHeader.focus ? bookmarkFolderHeader : bookmarksInFolderLoader.item.currentItem) : null |
42 | + |
43 | + function focusHeader() { |
44 | + bookmarkFolderHeader.focus = true |
45 | + } |
46 | + function focusBookmarks() { |
47 | + bookmarksInFolderLoader.focus = true |
48 | + } |
49 | |
50 | property string folderName: folder |
51 | |
52 | @@ -66,127 +86,194 @@ |
53 | right: parent ? parent.right : undefined |
54 | } |
55 | |
56 | - height: delegateColumn.height |
57 | - |
58 | - Column { |
59 | - id: delegateColumn |
60 | - |
61 | - property bool expanded: folderName ? false : true |
62 | - |
63 | - anchors { |
64 | - left: parent.left |
65 | - right: parent.right |
66 | - } |
67 | - |
68 | - Item { |
69 | - objectName: "bookmarkFolderHeader" |
70 | - |
71 | - anchors { |
72 | - left: parent.left |
73 | - right: parent.right |
74 | - leftMargin: units.gu(2) |
75 | - rightMargin: units.gu(2) |
76 | - } |
77 | - |
78 | - height: units.gu(6.5) |
79 | - |
80 | - Row { |
81 | - anchors { |
82 | - left: parent.left |
83 | - leftMargin: units.gu(1.5) |
84 | - right: parent.right |
85 | - } |
86 | - |
87 | - height: units.gu(6) |
88 | - spacing: units.gu(1.5) |
89 | - |
90 | - Icon { |
91 | - id: expandedIcon |
92 | - name: delegateColumn.expanded ? "go-down" : "go-next" |
93 | - |
94 | - height: units.gu(2) |
95 | - width: height |
96 | - |
97 | - anchors { |
98 | - leftMargin: units.gu(1) |
99 | - topMargin: units.gu(2) |
100 | - top: parent.top |
101 | - } |
102 | - } |
103 | - |
104 | - Label { |
105 | - width: parent.width - expandedIcon.width - units.gu(3) |
106 | - anchors.verticalCenter: expandedIcon.verticalCenter |
107 | - |
108 | - text: folderName ? folderName : i18n.tr("All Bookmarks") |
109 | - fontSize: "small" |
110 | - } |
111 | - } |
112 | - |
113 | - ListItem.ThinDivider { |
114 | - anchors { |
115 | - left: parent.left |
116 | - right: parent.right |
117 | - bottom: parent.bottom |
118 | - bottomMargin: units.gu(1) |
119 | - } |
120 | - } |
121 | - |
122 | - MouseArea { |
123 | - anchors.fill: parent |
124 | - onClicked: delegateColumn.expanded = !delegateColumn.expanded |
125 | - } |
126 | - } |
127 | - |
128 | - Loader { |
129 | - anchors { |
130 | - left: parent.left |
131 | - right: parent.right |
132 | - } |
133 | - |
134 | - height: item ? item.contentHeight : 0 |
135 | - |
136 | - visible: status == Loader.Ready |
137 | - |
138 | - active: delegateColumn.expanded |
139 | - sourceComponent: ListView { |
140 | - readonly property bool isAllBookmarksFolder: folder === "" |
141 | - |
142 | - interactive: false |
143 | - |
144 | - model: { |
145 | - if (isAllBookmarksFolder) { |
146 | - return BookmarksModelUtils.prependHomepageToBookmarks(entries, { |
147 | - title: i18n.tr("Homepage"), |
148 | - url: bookmarksFoldersViewItem.homeBookmarkUrl |
149 | - }) |
150 | - } |
151 | - |
152 | - return entries |
153 | - } |
154 | - |
155 | - delegate: UrlDelegate{ |
156 | - id: urlDelegate |
157 | - objectName: "urlDelegate_" + index |
158 | - |
159 | - property var entry: isAllBookmarksFolder ? modelData : model |
160 | - |
161 | - width: parent.width |
162 | - height: units.gu(5) |
163 | - |
164 | - removable: !isAllBookmarksFolder || index !== 0 |
165 | - |
166 | - icon: entry.icon ? entry.icon : "" |
167 | - title: entry.title ? entry.title : entry.url |
168 | - url: entry.url |
169 | - |
170 | - onClicked: bookmarksFoldersViewItem.bookmarkClicked(url) |
171 | - onRemoved: bookmarksFoldersViewItem.bookmarkRemoved(url) |
172 | - } |
173 | - } |
174 | - } |
175 | - } |
176 | - } |
177 | + height: childrenRect.height |
178 | + |
179 | + property bool expanded: folderName ? false : true |
180 | + |
181 | + Item { |
182 | + id: bookmarkFolderHeader |
183 | + objectName: "bookmarkFolderHeader" |
184 | + |
185 | + anchors { |
186 | + top: parent.top |
187 | + left: parent.left |
188 | + right: parent.right |
189 | + } |
190 | + height: units.gu(6.5) |
191 | + focus: true |
192 | + |
193 | + Row { |
194 | + anchors { |
195 | + left: parent.left |
196 | + leftMargin: units.gu(2.5) |
197 | + right: parent.right |
198 | + } |
199 | + |
200 | + height: units.gu(6) |
201 | + spacing: units.gu(1.5) |
202 | + |
203 | + Icon { |
204 | + id: expandedIcon |
205 | + name: expanded ? "go-down" : "go-next" |
206 | + |
207 | + height: units.gu(2) |
208 | + width: height |
209 | + |
210 | + anchors { |
211 | + leftMargin: units.gu(1) |
212 | + topMargin: units.gu(2) |
213 | + top: parent.top |
214 | + } |
215 | + } |
216 | + |
217 | + Label { |
218 | + width: parent.width - expandedIcon.width - units.gu(3) |
219 | + anchors.verticalCenter: expandedIcon.verticalCenter |
220 | + |
221 | + text: folderName ? folderName : i18n.tr("All Bookmarks") |
222 | + fontSize: "small" |
223 | + } |
224 | + } |
225 | + |
226 | + ListItem.ThinDivider { |
227 | + anchors { |
228 | + left: parent.left |
229 | + right: parent.right |
230 | + bottom: parent.bottom |
231 | + bottomMargin: units.gu(1) |
232 | + } |
233 | + } |
234 | + |
235 | + ListViewHighlight { |
236 | + anchors.fill: parent |
237 | + visible: hasKeyboard && parent.activeFocus |
238 | + } |
239 | + |
240 | + MouseArea { |
241 | + anchors.fill: parent |
242 | + onClicked: expanded = !expanded |
243 | + } |
244 | + |
245 | + Keys.onEnterPressed: expanded = !expanded |
246 | + Keys.onReturnPressed: expanded = !expanded |
247 | + Keys.onSpacePressed: expanded = !expanded |
248 | + } |
249 | + |
250 | + Loader { |
251 | + id: bookmarksInFolderLoader |
252 | + anchors { |
253 | + top: bookmarkFolderHeader.bottom |
254 | + left: parent.left |
255 | + right: parent.right |
256 | + } |
257 | + |
258 | + height: item ? item.contentHeight : 0 |
259 | + |
260 | + visible: status == Loader.Ready |
261 | + |
262 | + active: expanded |
263 | + onActiveChanged: { |
264 | + if (!active && focus) { |
265 | + focusHeader() |
266 | + } |
267 | + } |
268 | + |
269 | + sourceComponent: ListView { |
270 | + readonly property bool isAllBookmarksFolder: folder === "" |
271 | + |
272 | + focus: true |
273 | + interactive: false |
274 | + currentIndex: 0 |
275 | + |
276 | + model: { |
277 | + if (isAllBookmarksFolder) { |
278 | + return BookmarksModelUtils.prependHomepageToBookmarks(entries, { |
279 | + title: i18n.tr("Homepage"), |
280 | + url: bookmarksFoldersViewItem.homeBookmarkUrl |
281 | + }) |
282 | + } |
283 | + |
284 | + return entries |
285 | + } |
286 | + |
287 | + delegate: UrlDelegate{ |
288 | + id: urlDelegate |
289 | + objectName: "urlDelegate_%1".arg(index) |
290 | + |
291 | + property var entry: isAllBookmarksFolder ? modelData : model |
292 | + |
293 | + width: parent.width |
294 | + height: units.gu(5) |
295 | + |
296 | + removable: !isAllBookmarksFolder || index !== 0 |
297 | + |
298 | + icon: entry.icon ? entry.icon : "" |
299 | + title: entry.title ? entry.title : entry.url |
300 | + url: entry.url |
301 | + |
302 | + onClicked: bookmarksFoldersViewItem.bookmarkClicked(url) |
303 | + onRemoved: bookmarksFoldersViewItem.bookmarkRemoved(url) |
304 | + } |
305 | + |
306 | + highlight: ListViewHighlight {} |
307 | + |
308 | + Keys.onUpPressed: { |
309 | + if (currentIndex > 0) { |
310 | + --currentIndex |
311 | + } else { |
312 | + focusHeader() |
313 | + } |
314 | + } |
315 | + Keys.onDownPressed: { |
316 | + if (currentIndex < (count - 1)) { |
317 | + ++currentIndex |
318 | + } else { |
319 | + event.accepted = false |
320 | + } |
321 | + } |
322 | + Keys.onEnterPressed: currentItem.clicked() |
323 | + Keys.onReturnPressed: currentItem.clicked() |
324 | + Keys.onDeletePressed: currentItem.removed() |
325 | + } |
326 | + } |
327 | + |
328 | + Keys.onDownPressed: { |
329 | + if (expanded && !bookmarksInFolderLoader.focus) { |
330 | + focusBookmarks() |
331 | + } else { |
332 | + event.accepted = false |
333 | + } |
334 | + } |
335 | + } |
336 | + } |
337 | + |
338 | + Keys.onUpPressed: { |
339 | + var current = currentIndex |
340 | + --currentIndex |
341 | + while (currentItem && !currentItem.active) { |
342 | + --currentIndex |
343 | + } |
344 | + if (!currentItem) { |
345 | + currentIndex = current |
346 | + event.accepted = false |
347 | + } |
348 | + } |
349 | + Keys.onDownPressed: { |
350 | + var current = currentIndex |
351 | + ++currentIndex |
352 | + while (currentItem && !currentItem.active) { |
353 | + ++currentIndex |
354 | + } |
355 | + if (!currentItem || !currentItem.active) { |
356 | + currentIndex = current |
357 | + } |
358 | + } |
359 | + } |
360 | + |
361 | + // Initially focus the first bookmark |
362 | + Component.onCompleted: { |
363 | + if (bookmarksFolderListView.currentItem) { |
364 | + bookmarksFolderListView.currentItem.item.focusBookmarks() |
365 | } |
366 | } |
367 | } |
368 | |
369 | === modified file 'src/app/webbrowser/BookmarksFoldersViewWide.qml' |
370 | --- src/app/webbrowser/BookmarksFoldersViewWide.qml 2016-01-28 18:35:14 +0000 |
371 | +++ src/app/webbrowser/BookmarksFoldersViewWide.qml 2016-02-11 08:27:04 +0000 |
372 | @@ -33,7 +33,7 @@ |
373 | function restoreLastFocusedColumn() { |
374 | if (internal.lastFocusedColumn && |
375 | internal.lastFocusedColumn == bookmarksList && |
376 | - model.count > 0) { |
377 | + BookmarksModel.count > 0) { |
378 | bookmarksList.forceActiveFocus() |
379 | } else { |
380 | folders.forceActiveFocus() |
381 | @@ -46,11 +46,6 @@ |
382 | } |
383 | } |
384 | |
385 | - Rectangle { |
386 | - anchors.fill: parent |
387 | - color: "#fbfbfb" |
388 | - } |
389 | - |
390 | ListView { |
391 | id: folders |
392 | objectName: "foldersList" |
393 | |
394 | === modified file 'src/app/webbrowser/BookmarksView.qml' |
395 | --- src/app/webbrowser/BookmarksView.qml 2015-12-17 20:25:21 +0000 |
396 | +++ src/app/webbrowser/BookmarksView.qml 2016-02-11 08:27:04 +0000 |
397 | @@ -1,5 +1,5 @@ |
398 | /* |
399 | - * Copyright 2015 Canonical Ltd. |
400 | + * Copyright 2015-2016 Canonical Ltd. |
401 | * |
402 | * This file is part of webbrowser-app. |
403 | * |
404 | @@ -44,7 +44,6 @@ |
405 | left: parent.left |
406 | right: parent.right |
407 | bottom: toolbar.top |
408 | - rightMargin: units.gu(2) |
409 | } |
410 | |
411 | interactive: true |
412 | @@ -109,8 +108,8 @@ |
413 | verticalCenter: parent.verticalCenter |
414 | } |
415 | |
416 | + activeFocusOnPress: false |
417 | strokeColor: UbuntuColors.darkGrey |
418 | - |
419 | text: i18n.tr("Done") |
420 | |
421 | onClicked: bookmarksView.done() |
422 | |
423 | === modified file 'src/app/webbrowser/Browser.qml' |
424 | --- src/app/webbrowser/Browser.qml 2016-02-11 08:27:04 +0000 |
425 | +++ src/app/webbrowser/Browser.qml 2016-02-11 08:27:04 +0000 |
426 | @@ -290,6 +290,7 @@ |
427 | currentWebview.url = url |
428 | tabContainer.forceActiveFocus() |
429 | } |
430 | + Keys.onUpPressed: chrome.focus = true |
431 | } |
432 | } |
433 | |
434 | @@ -311,7 +312,7 @@ |
435 | currentWebview.url = url |
436 | tabContainer.forceActiveFocus() |
437 | } |
438 | - onReleasingKeyboardFocus: chrome.focus = true |
439 | + Keys.onUpPressed: chrome.focus = true |
440 | } |
441 | } |
442 | |
443 | @@ -873,40 +874,43 @@ |
444 | Component { |
445 | id: historyViewComponent |
446 | |
447 | - HistoryView { |
448 | - anchors.fill: parent |
449 | + FocusScope { |
450 | + signal loadModel() |
451 | + onLoadModel: children[0].loadModel() |
452 | |
453 | - onSeeMoreEntriesClicked: { |
454 | - var view = expandedHistoryViewComponent.createObject(expandedHistoryViewContainer, {model: model}) |
455 | - view.onHistoryEntryClicked.connect(done) |
456 | + HistoryView { |
457 | + anchors.fill: parent |
458 | + focus: !expandedHistoryViewLoader.focus |
459 | + visible: focus |
460 | + onSeeMoreEntriesClicked: { |
461 | + expandedHistoryViewLoader.model = model |
462 | + expandedHistoryViewLoader.active = true |
463 | + } |
464 | + onNewTabRequested: browser.openUrlInNewTab("", true) |
465 | + onDone: historyViewLoader.active = false |
466 | } |
467 | - onNewTabRequested: browser.openUrlInNewTab("", true) |
468 | - onDone: historyViewLoader.active = false |
469 | - |
470 | - FocusScope { |
471 | - id: expandedHistoryViewContainer |
472 | - |
473 | - visible: children.length > 0 |
474 | + |
475 | + Loader { |
476 | + id: expandedHistoryViewLoader |
477 | + asynchronous: true |
478 | anchors.fill: parent |
479 | - |
480 | - Component { |
481 | - id: expandedHistoryViewComponent |
482 | - |
483 | - ExpandedHistoryView { |
484 | - anchors.fill: parent |
485 | - |
486 | - onHistoryEntryClicked: { |
487 | - browser.openUrlInNewTab(url, true) |
488 | + active: false |
489 | + focus: active |
490 | + property var model: null |
491 | + sourceComponent: ExpandedHistoryView { |
492 | + focus: true |
493 | + model: expandedHistoryViewLoader.model |
494 | + onHistoryEntryClicked: { |
495 | + browser.openUrlInNewTab(url, true) |
496 | + historyViewLoader.active = false |
497 | + } |
498 | + onHistoryEntryRemoved: { |
499 | + if (count == 1) { |
500 | done() |
501 | } |
502 | - onHistoryEntryRemoved: { |
503 | - if (count == 1) { |
504 | - done() |
505 | - } |
506 | - HistoryModel.removeEntryByUrl(url) |
507 | - } |
508 | - onDone: destroy() |
509 | + HistoryModel.removeEntryByUrl(url) |
510 | } |
511 | + onDone: expandedHistoryViewLoader.active = false |
512 | } |
513 | } |
514 | } |
515 | |
516 | === modified file 'src/app/webbrowser/BrowserPageHeader.qml' |
517 | --- src/app/webbrowser/BrowserPageHeader.qml 2016-01-12 17:41:47 +0000 |
518 | +++ src/app/webbrowser/BrowserPageHeader.qml 2016-02-11 08:27:04 +0000 |
519 | @@ -1,5 +1,5 @@ |
520 | /* |
521 | - * Copyright 2015 Canonical Ltd. |
522 | + * Copyright 2015-2016 Canonical Ltd. |
523 | * |
524 | * This file is part of webbrowser-app. |
525 | * |
526 | @@ -62,6 +62,7 @@ |
527 | |
528 | width: height |
529 | |
530 | + activeFocusOnPress: false |
531 | onTriggered: root.back() |
532 | anchors { |
533 | top: parent.top |
534 | |
535 | === modified file 'src/app/webbrowser/DownloadDelegate.qml' |
536 | --- src/app/webbrowser/DownloadDelegate.qml 2016-01-12 11:40:57 +0000 |
537 | +++ src/app/webbrowser/DownloadDelegate.qml 2016-02-11 08:27:04 +0000 |
538 | @@ -67,6 +67,7 @@ |
539 | left: parent.left |
540 | leftMargin: units.gu(2) |
541 | right: parent.right |
542 | + rightMargin: units.gu(2) |
543 | } |
544 | |
545 | Item { |
546 | |
547 | === modified file 'src/app/webbrowser/DownloadsPage.qml' |
548 | --- src/app/webbrowser/DownloadsPage.qml 2016-01-28 18:40:31 +0000 |
549 | +++ src/app/webbrowser/DownloadsPage.qml 2016-02-11 08:27:04 +0000 |
550 | @@ -148,7 +148,7 @@ |
551 | ListView { |
552 | id: downloadsListView |
553 | clip: true |
554 | - focus: true |
555 | + focus: !exportPeerPicker.focus |
556 | |
557 | anchors { |
558 | fill: parent |
559 | @@ -223,6 +223,23 @@ |
560 | |
561 | Keys.onEnterPressed: currentItem.clicked() |
562 | Keys.onReturnPressed: currentItem.clicked() |
563 | + Keys.onEscapePressed: { |
564 | + if (selectMode) { |
565 | + selectMode = false |
566 | + } else { |
567 | + event.accepted = false |
568 | + } |
569 | + } |
570 | + Keys.onSpacePressed: { |
571 | + if (selectMode || pickingMode) { |
572 | + currentItem.clicked() |
573 | + } |
574 | + } |
575 | + Keys.onDeletePressed: { |
576 | + if (!selectMode && !pickingMode) { |
577 | + currentItem.removed() |
578 | + } |
579 | + } |
580 | } |
581 | |
582 | Label { |
583 | @@ -243,6 +260,7 @@ |
584 | ContentPeerPicker { |
585 | id: exportPeerPicker |
586 | visible: false |
587 | + focus: visible |
588 | anchors.fill: parent |
589 | handler: ContentHandler.Destination |
590 | property string path |
591 | @@ -254,9 +272,8 @@ |
592 | } |
593 | visible = false |
594 | } |
595 | - onCancelPressed: { |
596 | - visible = false |
597 | - } |
598 | + onCancelPressed: visible = false |
599 | + Keys.onEscapePressed: visible = false |
600 | } |
601 | |
602 | } |
603 | |
604 | === modified file 'src/app/webbrowser/ExpandedHistoryView.qml' |
605 | --- src/app/webbrowser/ExpandedHistoryView.qml 2015-11-23 10:35:05 +0000 |
606 | +++ src/app/webbrowser/ExpandedHistoryView.qml 2016-02-11 08:27:04 +0000 |
607 | @@ -1,5 +1,5 @@ |
608 | /* |
609 | - * Copyright 2014-2015 Canonical Ltd. |
610 | + * Copyright 2014-2016 Canonical Ltd. |
611 | * |
612 | * This file is part of webbrowser-app. |
613 | * |
614 | @@ -20,7 +20,7 @@ |
615 | import Ubuntu.Components 1.3 |
616 | import ".." |
617 | |
618 | -Item { |
619 | +FocusScope { |
620 | id: expandedHistoryView |
621 | |
622 | property alias model: entriesListView.model |
623 | @@ -44,13 +44,16 @@ |
624 | ListView { |
625 | id: entriesListView |
626 | |
627 | + focus: true |
628 | + clip: true |
629 | + |
630 | anchors { |
631 | top: header.bottom |
632 | + topMargin: units.gu(1.5) |
633 | bottom: parent.bottom |
634 | + bottomMargin: units.gu(1.5) |
635 | left: parent.left |
636 | right: parent.right |
637 | - margins: units.gu(1.5) |
638 | - leftMargin: 0 |
639 | } |
640 | |
641 | section.property: "lastVisitDate" |
642 | @@ -75,6 +78,13 @@ |
643 | onClicked: expandedHistoryView.historyEntryClicked(model.url) |
644 | onRemoved: expandedHistoryView.historyEntryRemoved(model.url) |
645 | } |
646 | + |
647 | + highlight: ListViewHighlight {} |
648 | + |
649 | + Keys.onEnterPressed: currentItem.clicked() |
650 | + Keys.onReturnPressed: currentItem.clicked() |
651 | + Keys.onDeletePressed: currentItem.removed() |
652 | + Keys.onEscapePressed: done() |
653 | } |
654 | |
655 | Item { |
656 | @@ -106,8 +116,8 @@ |
657 | top: parent.top |
658 | topMargin: -units.gu(0.7) |
659 | } |
660 | - icon: expandedHistoryView.model.lastVisitedIcon |
661 | - title: expandedHistoryView.model.domain |
662 | + icon: model ? model.lastVisitedIcon : "" |
663 | + title: model ? model.domain : "" |
664 | url: i18n.tr("%1 page", "%1 pages", entriesListView.count).arg(entriesListView.count) |
665 | enabled: false |
666 | } |
667 | |
668 | === modified file 'src/app/webbrowser/HistoryView.qml' |
669 | --- src/app/webbrowser/HistoryView.qml 2015-12-22 18:15:49 +0000 |
670 | +++ src/app/webbrowser/HistoryView.qml 2016-02-11 08:27:04 +0000 |
671 | @@ -1,5 +1,5 @@ |
672 | /* |
673 | - * Copyright 2014-2015 Canonical Ltd. |
674 | + * Copyright 2014-2016 Canonical Ltd. |
675 | * |
676 | * This file is part of webbrowser-app. |
677 | * |
678 | @@ -22,7 +22,7 @@ |
679 | import webbrowserapp.private 0.1 |
680 | import "." as Local |
681 | |
682 | -Item { |
683 | +FocusScope { |
684 | id: historyView |
685 | |
686 | signal seeMoreEntriesClicked(var model) |
687 | @@ -48,12 +48,14 @@ |
688 | id: domainsListView |
689 | objectName: "domainsListView" |
690 | |
691 | + focus: true |
692 | + currentIndex: 0 |
693 | + |
694 | anchors { |
695 | top: topBar.bottom |
696 | left: parent.left |
697 | right: parent.right |
698 | bottom: toolbar.top |
699 | - rightMargin: units.gu(2) |
700 | } |
701 | |
702 | model: SortFilterModel { |
703 | @@ -77,6 +79,8 @@ |
704 | width: parent.width |
705 | height: units.gu(5) |
706 | |
707 | + readonly property int modelIndex: index |
708 | + |
709 | title: model.domain |
710 | url: lastVisitedTitle |
711 | icon: model.lastVisitedIcon |
712 | @@ -96,6 +100,12 @@ |
713 | } |
714 | } |
715 | } |
716 | + |
717 | + highlight: ListViewHighlight {} |
718 | + |
719 | + Keys.onEnterPressed: currentItem.clicked() |
720 | + Keys.onReturnPressed: currentItem.clicked() |
721 | + Keys.onDeletePressed: currentItem.removed() |
722 | } |
723 | |
724 | Local.Toolbar { |
725 | |
726 | === modified file 'src/app/webbrowser/ListViewHighlight.qml' |
727 | --- src/app/webbrowser/ListViewHighlight.qml 2016-01-28 16:48:27 +0000 |
728 | +++ src/app/webbrowser/ListViewHighlight.qml 2016-02-11 08:27:04 +0000 |
729 | @@ -18,6 +18,7 @@ |
730 | |
731 | import QtQuick 2.4 |
732 | import Ubuntu.Components 1.3 |
733 | +import Unity.InputInfo 0.1 |
734 | |
735 | Rectangle { |
736 | color: "transparent" |
737 | @@ -26,6 +27,14 @@ |
738 | color: UbuntuColors.orange |
739 | } |
740 | radius: units.gu(0.3) |
741 | - visible: (ListView.view && ListView.view.activeFocus) || |
742 | - (GridView.view && GridView.view.activeFocus) |
743 | + visible: hasKeyboard && |
744 | + ((ListView.view && ListView.view.activeFocus) || |
745 | + (GridView.view && GridView.view.activeFocus)) |
746 | + |
747 | + readonly property bool hasKeyboard: keyboardModel.count > 0 |
748 | + |
749 | + InputDeviceModel { |
750 | + id: keyboardModel |
751 | + deviceFilter: InputInfo.Keyboard |
752 | + } |
753 | } |
754 | |
755 | === modified file 'src/app/webbrowser/NewTabView.qml' |
756 | --- src/app/webbrowser/NewTabView.qml 2015-12-15 11:17:58 +0000 |
757 | +++ src/app/webbrowser/NewTabView.qml 2016-02-11 08:27:04 +0000 |
758 | @@ -1,5 +1,5 @@ |
759 | /* |
760 | - * Copyright 2014-2015 Canonical Ltd. |
761 | + * Copyright 2014-2016 Canonical Ltd. |
762 | * |
763 | * This file is part of webbrowser-app. |
764 | * |
765 | @@ -19,10 +19,11 @@ |
766 | import QtQuick 2.4 |
767 | import Qt.labs.settings 1.0 |
768 | import Ubuntu.Components 1.3 |
769 | +import Ubuntu.Components.ListItems 1.3 as ListItems |
770 | import webbrowserapp.private 0.1 |
771 | import "." |
772 | |
773 | -Item { |
774 | +FocusScope { |
775 | id: newTabView |
776 | |
777 | property Settings settingsObject |
778 | @@ -51,6 +52,18 @@ |
779 | seeMoreBookmarksView = false |
780 | } |
781 | } |
782 | + |
783 | + function ensureCurrentItemVisible(container, currentItem) { |
784 | + if (container.activeFocus && currentItem) { |
785 | + var top = container.y + currentItem.mapToItem(container, 0, 0).y |
786 | + var height = currentItem.height |
787 | + if (top < flickable.contentY) { |
788 | + flickable.contentY = top |
789 | + } else if ((flickable.contentY + flickable.height) < (top + height)) { |
790 | + flickable.contentY = top + height - flickable.height |
791 | + } |
792 | + } |
793 | + } |
794 | } |
795 | |
796 | Rectangle { |
797 | @@ -59,160 +72,259 @@ |
798 | } |
799 | |
800 | Flickable { |
801 | + id: flickable |
802 | anchors.fill: parent |
803 | - contentHeight: internal.seeMoreBookmarksView ? |
804 | - bookmarksFolderListViewLoader.height + units.gu(6) : |
805 | - contentColumn.height |
806 | - |
807 | - Column { |
808 | - id: contentColumn |
809 | + contentHeight: contentScope.height |
810 | + focus: true |
811 | + |
812 | + onActiveFocusChanged: { |
813 | + if (activeFocus) { |
814 | + contentScope.forceActiveFocus() |
815 | + } |
816 | + } |
817 | + |
818 | + Behavior on contentY { |
819 | + UbuntuNumberAnimation {} |
820 | + } |
821 | + |
822 | + FocusScope { |
823 | + id: contentScope |
824 | anchors { |
825 | left: parent.left |
826 | right: parent.right |
827 | - rightMargin: units.gu(1.5) |
828 | } |
829 | height: childrenRect.height |
830 | |
831 | - Row { |
832 | + Item { |
833 | + id: bookmarkListHeader |
834 | + objectName: "bookmarkListHeader" |
835 | height: units.gu(6) |
836 | anchors { |
837 | + top: parent.top |
838 | left: parent.left |
839 | - leftMargin: units.gu(1.5) |
840 | right: parent.right |
841 | } |
842 | - spacing: units.gu(1.5) |
843 | - |
844 | - Icon { |
845 | - id: starredIcon |
846 | - color: "#dd4814" |
847 | - name: "starred" |
848 | - |
849 | - height: units.gu(2) |
850 | - width: height |
851 | - |
852 | + |
853 | + Row { |
854 | anchors { |
855 | - leftMargin: units.gu(1) |
856 | - topMargin: units.gu(1) |
857 | - verticalCenter: moreButton.verticalCenter |
858 | - } |
859 | - } |
860 | - |
861 | - Label { |
862 | - width: parent.width - starredIcon.width - moreButton.width - units.gu(3) |
863 | - anchors.verticalCenter: moreButton.verticalCenter |
864 | - |
865 | - text: i18n.tr("Bookmarks") |
866 | - fontSize: "small" |
867 | - } |
868 | - |
869 | - Button { |
870 | - id: moreButton |
871 | - objectName: "bookmarks.moreButton" |
872 | - height: parent.height - units.gu(2) |
873 | - |
874 | - anchors { top: parent.top; topMargin: units.gu(1) } |
875 | - |
876 | - strokeColor: UbuntuColors.darkGrey |
877 | - |
878 | - visible: internal.numberOfBookmarks > 4 |
879 | - |
880 | - text: internal.seeMoreBookmarksView ? i18n.tr("Less") : i18n.tr("More") |
881 | - |
882 | - onClicked: internal.seeMoreBookmarksView = !internal.seeMoreBookmarksView |
883 | - } |
884 | - } |
885 | - |
886 | - Rectangle { |
887 | - height: units.gu(0.1) |
888 | + fill: parent |
889 | + leftMargin: units.gu(2) |
890 | + rightMargin: units.gu(2) |
891 | + } |
892 | + spacing: units.gu(1.5) |
893 | + |
894 | + Icon { |
895 | + id: starredIcon |
896 | + color: "#dd4814" |
897 | + name: "starred" |
898 | + |
899 | + height: units.gu(2) |
900 | + width: height |
901 | + |
902 | + anchors { |
903 | + leftMargin: units.gu(1) |
904 | + topMargin: units.gu(1) |
905 | + verticalCenter: moreButton.verticalCenter |
906 | + } |
907 | + } |
908 | + |
909 | + Label { |
910 | + width: parent.width - starredIcon.width - moreButton.width - units.gu(3) |
911 | + anchors.verticalCenter: moreButton.verticalCenter |
912 | + |
913 | + text: i18n.tr("Bookmarks") |
914 | + fontSize: "small" |
915 | + } |
916 | + |
917 | + Button { |
918 | + id: moreButton |
919 | + objectName: "bookmarks.moreButton" |
920 | + height: parent.height - units.gu(2) |
921 | + anchors { top: parent.top; topMargin: units.gu(1) } |
922 | + activeFocusOnPress: false |
923 | + |
924 | + strokeColor: UbuntuColors.darkGrey |
925 | + visible: internal.numberOfBookmarks > 4 |
926 | + text: internal.seeMoreBookmarksView ? i18n.tr("Less") : i18n.tr("More") |
927 | + |
928 | + onClicked: { |
929 | + internal.seeMoreBookmarksView = !internal.seeMoreBookmarksView |
930 | + bookmarkListHeader.focus = true |
931 | + } |
932 | + } |
933 | + } |
934 | + |
935 | + Keys.onEnterPressed: moreButton.clicked() |
936 | + Keys.onReturnPressed: moreButton.clicked() |
937 | + Keys.onSpacePressed: moreButton.clicked() |
938 | + |
939 | + Keys.onDownPressed: { |
940 | + if (internal.seeMoreBookmarksView) { |
941 | + bookmarksFolderListViewLoader.focus = true |
942 | + } else { |
943 | + bookmarkList.focus = true |
944 | + } |
945 | + } |
946 | + |
947 | + onActiveFocusChanged: internal.ensureCurrentItemVisible(this, this) |
948 | + } |
949 | + |
950 | + ListViewHighlight { |
951 | + anchors.fill: bookmarkListHeader |
952 | + visible: hasKeyboard && bookmarkListHeader.activeFocus |
953 | + } |
954 | + |
955 | + ListItems.ThinDivider { |
956 | + id: bookmarkListDivider |
957 | anchors { |
958 | + top: bookmarkListHeader.bottom |
959 | left: parent.left |
960 | - leftMargin: units.gu(1.5) |
961 | + leftMargin: units.gu(2) |
962 | right: parent.right |
963 | + rightMargin: units.gu(2) |
964 | } |
965 | - color: "#d3d3d3" |
966 | + opacity: bookmarkListHeader.activeFocus ? 0 : 1 |
967 | } |
968 | |
969 | Loader { |
970 | id: bookmarksFolderListViewLoader |
971 | - |
972 | anchors { |
973 | + top: bookmarkListDivider.bottom |
974 | left: parent.left |
975 | right: parent.right |
976 | } |
977 | - |
978 | - height: status == Loader.Ready ? item.height : 0 |
979 | - |
980 | active: internal.seeMoreBookmarksView |
981 | + height: active ? item.height : 0 |
982 | |
983 | sourceComponent: BookmarksFoldersView { |
984 | + focus: true |
985 | + interactive: false |
986 | + |
987 | homeBookmarkUrl: newTabView.settingsObject.homepage |
988 | |
989 | onBookmarkClicked: newTabView.bookmarkClicked(url) |
990 | onBookmarkRemoved: newTabView.bookmarkRemoved(url) |
991 | + |
992 | + onCurrentItemChanged: internal.ensureCurrentItemVisible(bookmarksFolderListViewLoader, currentItem) |
993 | + onActiveFocusChanged: internal.ensureCurrentItemVisible(bookmarksFolderListViewLoader, currentItem) |
994 | + } |
995 | + |
996 | + Keys.onUpPressed: { |
997 | + if (moreButton.visible) { |
998 | + bookmarkListHeader.focus = true |
999 | + } else { |
1000 | + event.accepted = false |
1001 | + } |
1002 | } |
1003 | } |
1004 | |
1005 | - Column { |
1006 | - id: bookmarksColumn |
1007 | + Loader { |
1008 | + id: bookmarkList |
1009 | anchors { |
1010 | + top: bookmarkListDivider.bottom |
1011 | left: parent.left |
1012 | right: parent.right |
1013 | } |
1014 | - |
1015 | - opacity: internal.seeMoreBookmarksView ? 0.0 : 1.0 |
1016 | - Behavior on opacity { UbuntuNumberAnimation {} } |
1017 | - visible: opacity > 0 |
1018 | - |
1019 | - // Force the height to be updated when bookmarks are removed |
1020 | - // in another new tab |
1021 | - height: units.gu(5) * (Math.min(internal.bookmarksCountLimit, internal.numberOfBookmarks) + 1) |
1022 | - spacing: 0 |
1023 | - |
1024 | - UrlDelegate { |
1025 | - objectName: "homepageBookmark" |
1026 | - anchors { |
1027 | - left: parent.left |
1028 | - right: parent.right |
1029 | - } |
1030 | - height: units.gu(5) |
1031 | - |
1032 | - title: i18n.tr('Homepage') |
1033 | - |
1034 | - leadingActions: null |
1035 | - |
1036 | - url: newTabView.settingsObject.homepage |
1037 | - onClicked: newTabView.bookmarkClicked(url) |
1038 | + active: !internal.seeMoreBookmarksView |
1039 | + height: active ? item.height : 0 |
1040 | + focus: true |
1041 | + |
1042 | + LimitProxyModel { |
1043 | + id: limitedBookmarksModel |
1044 | + sourceModel: BookmarksModel |
1045 | + limit: internal.bookmarksCountLimit |
1046 | } |
1047 | |
1048 | - UrlsList { |
1049 | + sourceComponent: ListView { |
1050 | objectName: "bookmarksList" |
1051 | - anchors { |
1052 | - left: parent.left |
1053 | - right: parent.right |
1054 | - } |
1055 | - |
1056 | - spacing: 0 |
1057 | - limit: internal.bookmarksCountLimit |
1058 | - |
1059 | - model: BookmarksModel |
1060 | - |
1061 | - onUrlClicked: newTabView.bookmarkClicked(url) |
1062 | - onUrlRemoved: newTabView.bookmarkRemoved(url) |
1063 | + focus: true |
1064 | + interactive: false |
1065 | + readonly property real delegateHeight: units.gu(5) |
1066 | + height: count * delegateHeight |
1067 | + |
1068 | + model: limitedBookmarksModel.count + 1 |
1069 | + |
1070 | + delegate: UrlDelegate { |
1071 | + objectName: (index == 0) ? "homepageBookmark" : "bookmark_%1".arg(index) |
1072 | + anchors { |
1073 | + left: parent.left |
1074 | + right: parent.right |
1075 | + } |
1076 | + height: delegateHeight |
1077 | + removable: index > 0 |
1078 | + |
1079 | + readonly property var data: BookmarksModel.count ? limitedBookmarksModel.get(index - 1) : null |
1080 | + icon: (index > 0) ? data.icon : "" |
1081 | + title: (index > 0) ? data.title : i18n.tr("Homepage") |
1082 | + url: (index > 0) ? data.url : newTabView.settingsObject.homepage |
1083 | + |
1084 | + onClicked: newTabView.bookmarkClicked(url) |
1085 | + onRemoved: { |
1086 | + if (removable) { |
1087 | + newTabView.bookmarkRemoved(url) |
1088 | + } |
1089 | + } |
1090 | + } |
1091 | + |
1092 | + highlight: ListViewHighlight {} |
1093 | + |
1094 | + Keys.onEnterPressed: currentItem.clicked() |
1095 | + Keys.onReturnPressed: currentItem.clicked() |
1096 | + Keys.onDeletePressed: currentItem.removed() |
1097 | + |
1098 | + // Setting 'interactive' to false to prevent flicks also disables |
1099 | + // keyboard navigation, so it needs to be manually implemented. |
1100 | + Keys.onUpPressed: { |
1101 | + var current = currentIndex |
1102 | + decrementCurrentIndex() |
1103 | + if (currentIndex == current) { |
1104 | + event.accepted = false |
1105 | + } |
1106 | + } |
1107 | + Keys.onDownPressed: { |
1108 | + var current = currentIndex |
1109 | + incrementCurrentIndex() |
1110 | + if (currentIndex == current) { |
1111 | + event.accepted = false |
1112 | + } |
1113 | + } |
1114 | + |
1115 | + onCurrentItemChanged: internal.ensureCurrentItemVisible(bookmarkList, currentItem) |
1116 | + onActiveFocusChanged: internal.ensureCurrentItemVisible(bookmarkList, currentItem) |
1117 | + } |
1118 | + |
1119 | + Keys.onUpPressed: { |
1120 | + if (moreButton.visible) { |
1121 | + bookmarkListHeader.focus = true |
1122 | + } else { |
1123 | + event.accepted = false |
1124 | + } |
1125 | + } |
1126 | + Keys.onDownPressed: { |
1127 | + if (topSitesGrid.visible) { |
1128 | + topSitesGrid.focus = true |
1129 | + } else { |
1130 | + event.accepted = false |
1131 | + } |
1132 | } |
1133 | } |
1134 | |
1135 | Item { |
1136 | - height: units.gu(6) |
1137 | + id: topSitesHeader |
1138 | anchors { |
1139 | + top: bookmarkList.bottom |
1140 | left: parent.left |
1141 | - leftMargin: units.gu(1.5) |
1142 | right: parent.right |
1143 | } |
1144 | + visible: !internal.seeMoreBookmarksView |
1145 | + height: visible ? units.gu(6) : 0 |
1146 | |
1147 | Label { |
1148 | anchors { |
1149 | left: parent.left |
1150 | + leftMargin: units.gu(2) |
1151 | right: parent.right |
1152 | + rightMargin: units.gu(2) |
1153 | bottom: parent.bottom |
1154 | bottomMargin: units.gu(1) |
1155 | } |
1156 | @@ -225,28 +337,28 @@ |
1157 | } |
1158 | } |
1159 | |
1160 | - Rectangle { |
1161 | - height: units.gu(0.1) |
1162 | + ListItems.ThinDivider { |
1163 | + id: topSitesDivider |
1164 | anchors { |
1165 | + top: topSitesHeader.bottom |
1166 | left: parent.left |
1167 | leftMargin: units.gu(2) |
1168 | right: parent.right |
1169 | + rightMargin: units.gu(2) |
1170 | } |
1171 | - color: "#d3d3d3" |
1172 | - |
1173 | - opacity: internal.seeMoreBookmarksView ? 0.0 : 1.0 |
1174 | - Behavior on opacity { UbuntuNumberAnimation {} } |
1175 | + visible: topSitesHeader.visible |
1176 | } |
1177 | |
1178 | Label { |
1179 | objectName: "notopsites" |
1180 | |
1181 | - height: units.gu(11) |
1182 | anchors { |
1183 | + top: topSitesDivider.bottom |
1184 | left: parent.left |
1185 | right: parent.right |
1186 | } |
1187 | - visible: topSitesModel.count == 0 |
1188 | + visible: !internal.seeMoreBookmarksView && (topSitesModel.count == 0) |
1189 | + height: visible ? units.gu(11) : 0 |
1190 | |
1191 | horizontalAlignment: Text.AlignHCenter |
1192 | verticalAlignment: Text.AlignVCenter |
1193 | @@ -255,36 +367,26 @@ |
1194 | color: UbuntuColors.darkGrey |
1195 | } |
1196 | |
1197 | - Item { |
1198 | + FocusScope { |
1199 | + id: topSitesGrid |
1200 | anchors { |
1201 | + top: topSitesDivider.bottom |
1202 | left: parent.left |
1203 | right: parent.right |
1204 | - |
1205 | - // The UrlPreviewGrid's highlight extends to the left of the |
1206 | - // grid itself by a margin. |
1207 | - // Since we are clipping the parent we need to prevent the |
1208 | - // highlight from being clipped away at the left edge. |
1209 | - // We do this by shifting the parent left and the contents right |
1210 | - // by an amount equal to the highlight's margin. |
1211 | - leftMargin: units.gu(2) - grid.horizontalMargin |
1212 | - |
1213 | - // The right margin should be 2gu, which is set on all cells |
1214 | - // of the UrlPreviewGrid already. However the parent Column |
1215 | - // has 1.5gu right margin, so we are compensating for that |
1216 | - // here instead of removing it from the Column itself and |
1217 | - // reassigning it to all Column children except this one. |
1218 | - rightMargin: - contentColumn.anchors.rightMargin |
1219 | } |
1220 | - height: grid.contentHeight + units.gu(1) |
1221 | + visible: !internal.seeMoreBookmarksView && (topSitesModel.count > 0) |
1222 | + height: visible ? grid.contentHeight + units.gu(1) : 0 |
1223 | clip: true |
1224 | |
1225 | UrlPreviewGrid { |
1226 | id: grid |
1227 | objectName: "topSitesList" |
1228 | + focus: true |
1229 | anchors { |
1230 | left: parent.left |
1231 | - leftMargin: grid.horizontalMargin |
1232 | + leftMargin: units.gu(2) |
1233 | right: parent.right |
1234 | + rightMargin: units.gu(2) |
1235 | top: parent.top |
1236 | topMargin: units.gu(2) |
1237 | bottom: parent.bottom |
1238 | @@ -298,9 +400,6 @@ |
1239 | visible: opacity > 0 |
1240 | interactive: false |
1241 | |
1242 | - // No highlight as this view doesn’t support keyboard navigation |
1243 | - highlight: null |
1244 | - |
1245 | model: LimitProxyModel { |
1246 | limit: 10 |
1247 | sourceModel: topSitesModel |
1248 | @@ -312,7 +411,23 @@ |
1249 | HistoryModel.hide(url) |
1250 | PreviewManager.checkDelete(url) |
1251 | } |
1252 | + |
1253 | + // Setting 'interactive' to false to prevent flicks also disables |
1254 | + // keyboard navigation, so it needs to be manually implemented. |
1255 | + Keys.onLeftPressed: moveCurrentIndexLeft() |
1256 | + Keys.onRightPressed: moveCurrentIndexRight() |
1257 | + |
1258 | + onCurrentItemChanged: internal.ensureCurrentItemVisible(topSitesGrid, currentItem) |
1259 | + onActiveFocusChanged: internal.ensureCurrentItemVisible(topSitesGrid, currentItem) |
1260 | + |
1261 | + onCountChanged: { |
1262 | + if (activeFocus && (count == 0)) { |
1263 | + bookmarkList.focus = true |
1264 | + } |
1265 | + } |
1266 | } |
1267 | + |
1268 | + Keys.onUpPressed: bookmarkList.focus = true |
1269 | } |
1270 | } |
1271 | } |
1272 | |
1273 | === modified file 'src/app/webbrowser/NewTabViewWide.qml' |
1274 | --- src/app/webbrowser/NewTabViewWide.qml 2015-11-23 09:41:48 +0000 |
1275 | +++ src/app/webbrowser/NewTabViewWide.qml 2016-02-11 08:27:04 +0000 |
1276 | @@ -1,5 +1,5 @@ |
1277 | /* |
1278 | - * Copyright 2015 Canonical Ltd. |
1279 | + * Copyright 2015-2016 Canonical Ltd. |
1280 | * |
1281 | * This file is part of webbrowser-app. |
1282 | * |
1283 | @@ -31,7 +31,6 @@ |
1284 | signal bookmarkClicked(url url) |
1285 | signal bookmarkRemoved(url url) |
1286 | signal historyEntryClicked(url url) |
1287 | - signal releasingKeyboardFocus() |
1288 | |
1289 | Keys.onTabPressed: selectedIndex = (selectedIndex + 1) % 2 |
1290 | Keys.onBacktabPressed: selectedIndex = Math.abs((selectedIndex - 1) % 2) |
1291 | @@ -56,16 +55,9 @@ |
1292 | BookmarksFoldersViewWide { |
1293 | id: bookmarksFoldersViewWide |
1294 | |
1295 | - Keys.onUpPressed: newTabViewWide.releasingKeyboardFocus() |
1296 | onBookmarkClicked: newTabViewWide.bookmarkClicked(url) |
1297 | onBookmarkRemoved: newTabViewWide.bookmarkRemoved(url) |
1298 | |
1299 | - // Relinquish focus as the presses and releases that compose the |
1300 | - // drag will move the keyboard focus in a location unexpected |
1301 | - // for the user. This way it will go back to the address bar and |
1302 | - // the user can predictably resume keyboard interaction from there. |
1303 | - onDragStarted: newTabViewWide.releasingKeyboardFocus() |
1304 | - |
1305 | anchors { |
1306 | top: sectionsGroup.bottom |
1307 | left: parent.left |
1308 | @@ -105,10 +97,8 @@ |
1309 | onActivated: newTabViewWide.historyEntryClicked(url) |
1310 | onRemoved: { |
1311 | HistoryModel.hide(url) |
1312 | - if (topSitesModel.count === 0) newTabViewWide.releasingKeyboardFocus() |
1313 | PreviewManager.checkDelete(url) |
1314 | } |
1315 | - onReleasingKeyboardFocus: newTabViewWide.releasingKeyboardFocus() |
1316 | } |
1317 | |
1318 | Scrollbar { |
1319 | |
1320 | === modified file 'src/app/webbrowser/ToolbarAction.qml' |
1321 | --- src/app/webbrowser/ToolbarAction.qml 2015-09-22 01:26:42 +0000 |
1322 | +++ src/app/webbrowser/ToolbarAction.qml 2016-02-11 08:27:04 +0000 |
1323 | @@ -28,6 +28,7 @@ |
1324 | |
1325 | opacity: enabled ? 1.0 : 0.3 |
1326 | width: Math.max(label.paintedWidth, icon.width) |
1327 | + activeFocusOnPress: false |
1328 | |
1329 | Item { |
1330 | anchors { |
1331 | |
1332 | === modified file 'src/app/webbrowser/UrlDelegate.qml' |
1333 | --- src/app/webbrowser/UrlDelegate.qml 2015-10-09 03:10:13 +0000 |
1334 | +++ src/app/webbrowser/UrlDelegate.qml 2016-02-11 08:27:04 +0000 |
1335 | @@ -1,5 +1,5 @@ |
1336 | /* |
1337 | - * Copyright 2014-2015 Canonical Ltd. |
1338 | + * Copyright 2014-2016 Canonical Ltd. |
1339 | * |
1340 | * This file is part of webbrowser-app. |
1341 | * |
1342 | @@ -40,6 +40,8 @@ |
1343 | verticalCenter: parent.verticalCenter |
1344 | left: parent.left |
1345 | leftMargin: units.gu(1.5) |
1346 | + right: parent.right |
1347 | + rightMargin: units.gu(1.5) |
1348 | } |
1349 | spacing: units.gu(1) |
1350 | |
1351 | @@ -60,12 +62,18 @@ |
1352 | } |
1353 | |
1354 | Column { |
1355 | - width: urlDelegate.width - headerComponentLoader.width - iconContainer.width - parent.spacing |
1356 | - height: parent.height |
1357 | + width: parent.width - headerComponentLoader.width - iconContainer.width - parent.spacing - (headerComponentLoader.sourceComponent ? parent.spacing : 0) |
1358 | + anchors { |
1359 | + top: parent.top |
1360 | + bottom: parent.bottom |
1361 | + } |
1362 | |
1363 | Label { |
1364 | id: title |
1365 | - |
1366 | + anchors { |
1367 | + left: parent.left |
1368 | + right: parent.right |
1369 | + } |
1370 | fontSize: "x-small" |
1371 | color: UbuntuColors.darkGrey |
1372 | wrapMode: Text.Wrap |
1373 | @@ -75,7 +83,10 @@ |
1374 | |
1375 | Label { |
1376 | id: url |
1377 | - |
1378 | + anchors { |
1379 | + left: parent.left |
1380 | + right: parent.right |
1381 | + } |
1382 | fontSize: "xx-small" |
1383 | color: UbuntuColors.darkGrey |
1384 | wrapMode: Text.Wrap |
1385 | |
1386 | === modified file 'src/app/webbrowser/UrlPreviewDelegate.qml' |
1387 | --- src/app/webbrowser/UrlPreviewDelegate.qml 2015-10-16 07:55:02 +0000 |
1388 | +++ src/app/webbrowser/UrlPreviewDelegate.qml 2016-02-11 08:27:04 +0000 |
1389 | @@ -117,12 +117,16 @@ |
1390 | Component { |
1391 | id: contextMenuComponent |
1392 | ActionSelectionPopover { |
1393 | + objectName: "urlPreviewDelegate.contextMenu" |
1394 | grabDismissAreaEvents: true |
1395 | actions: ActionList { |
1396 | Action { |
1397 | objectName: "delete" |
1398 | text: i18n.tr("Remove") |
1399 | - onTriggered: preview.removed() |
1400 | + onTriggered: { |
1401 | + preview.removed() |
1402 | + preview.GridView.view.forceActiveFocus() |
1403 | + } |
1404 | } |
1405 | } |
1406 | } |
1407 | |
1408 | === modified file 'src/app/webbrowser/UrlPreviewGrid.qml' |
1409 | --- src/app/webbrowser/UrlPreviewGrid.qml 2016-01-28 18:14:51 +0000 |
1410 | +++ src/app/webbrowser/UrlPreviewGrid.qml 2016-02-11 08:27:04 +0000 |
1411 | @@ -17,10 +17,7 @@ |
1412 | */ |
1413 | |
1414 | import QtQuick 2.4 |
1415 | -import Qt.labs.settings 1.0 |
1416 | import Ubuntu.Components 1.3 |
1417 | -import webbrowserapp.private 0.1 |
1418 | -import ".." |
1419 | |
1420 | GridView { |
1421 | id: grid |
1422 | @@ -33,9 +30,6 @@ |
1423 | |
1424 | signal activated(url url) |
1425 | signal removed(url url) |
1426 | - signal releasingKeyboardFocus() |
1427 | - |
1428 | - currentIndex: 0 |
1429 | |
1430 | cellWidth: previewWidth + horizontalMargin * 2 |
1431 | cellHeight: previewHeight + verticalMargin * 2 + units.gu(4) // height of text + favicon + margins in delegate |
1432 | @@ -59,8 +53,9 @@ |
1433 | } |
1434 | |
1435 | highlight: Item { |
1436 | - visible: GridView.view && GridView.view.activeFocus |
1437 | + visible: viewHighlight.hasKeyboard && GridView.view && GridView.view.activeFocus |
1438 | ListViewHighlight { |
1439 | + id: viewHighlight |
1440 | visible: true |
1441 | width: previewWidth + units.gu(2) |
1442 | height: previewHeight + units.gu(5) |
1443 | @@ -75,15 +70,27 @@ |
1444 | |
1445 | Keys.onDeletePressed: removed(currentItem.url) |
1446 | |
1447 | - Keys.onLeftPressed: { |
1448 | - var i = grid.currentIndex |
1449 | - grid.moveCurrentIndexLeft() |
1450 | - if (i === grid.currentIndex) grid.releasingKeyboardFocus() |
1451 | - } |
1452 | - |
1453 | Keys.onUpPressed: { |
1454 | - var i = grid.currentIndex |
1455 | - grid.moveCurrentIndexUp() |
1456 | - if (i === grid.currentIndex) grid.releasingKeyboardFocus() |
1457 | + var current = currentIndex |
1458 | + moveCurrentIndexUp() |
1459 | + if (current == currentIndex) { |
1460 | + event.accepted = false |
1461 | + } |
1462 | + } |
1463 | + Keys.onDownPressed: { |
1464 | + var current = currentIndex |
1465 | + moveCurrentIndexDown() |
1466 | + if (currentIndex == current) { |
1467 | + event.accepted = false |
1468 | + } |
1469 | + } |
1470 | + |
1471 | + Timer { |
1472 | + // Work around a weird issue with the use of a LimitProxyModel in a |
1473 | + // grid view, where the currentIndex is changed when populating the |
1474 | + // model. |
1475 | + running: true |
1476 | + interval: 1 |
1477 | + onTriggered: grid.currentIndex = 0 |
1478 | } |
1479 | } |
1480 | |
1481 | === removed file 'src/app/webbrowser/UrlsList.qml' |
1482 | --- src/app/webbrowser/UrlsList.qml 2015-10-08 14:47:13 +0000 |
1483 | +++ src/app/webbrowser/UrlsList.qml 1970-01-01 00:00:00 +0000 |
1484 | @@ -1,52 +0,0 @@ |
1485 | -/* |
1486 | - * Copyright 2014-2015 Canonical Ltd. |
1487 | - * |
1488 | - * This file is part of webbrowser-app. |
1489 | - * |
1490 | - * webbrowser-app is free software; you can redistribute it and/or modify |
1491 | - * it under the terms of the GNU General Public License as published by |
1492 | - * the Free Software Foundation; version 3. |
1493 | - * |
1494 | - * webbrowser-app is distributed in the hope that it will be useful, |
1495 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1496 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1497 | - * GNU General Public License for more details. |
1498 | - * |
1499 | - * You should have received a copy of the GNU General Public License |
1500 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1501 | - */ |
1502 | - |
1503 | -import QtQuick 2.4 |
1504 | -import Ubuntu.Components 1.3 |
1505 | - |
1506 | -Column { |
1507 | - id: urlsList |
1508 | - |
1509 | - property alias model: urlsListRepeater.model |
1510 | - property int limit: -1 |
1511 | - |
1512 | - signal urlClicked(url url) |
1513 | - signal urlRemoved(url url) |
1514 | - |
1515 | - spacing: units.gu(1) |
1516 | - |
1517 | - Repeater { |
1518 | - id: urlsListRepeater |
1519 | - |
1520 | - delegate: Loader { |
1521 | - active: limit < 0 || index < limit |
1522 | - sourceComponent: UrlDelegate{ |
1523 | - id: urlDelegate |
1524 | - width: urlsList.width |
1525 | - height: units.gu(5) |
1526 | - |
1527 | - icon: model ? model.icon : "" |
1528 | - title: model.title ? model.title : model.url |
1529 | - url: model ? model.url : "" |
1530 | - |
1531 | - onClicked: urlsList.urlClicked(model.url) |
1532 | - onRemoved: urlsList.urlRemoved(model.url) |
1533 | - } |
1534 | - } |
1535 | - } |
1536 | -} |
1537 | |
1538 | === modified file 'tests/autopilot/webbrowser_app/emulators/browser.py' |
1539 | --- tests/autopilot/webbrowser_app/emulators/browser.py 2016-02-11 08:27:04 +0000 |
1540 | +++ tests/autopilot/webbrowser_app/emulators/browser.py 2016-02-11 08:27:04 +0000 |
1541 | @@ -600,7 +600,12 @@ |
1542 | return self.select_single(UrlDelegate, objectName="homepageBookmark") |
1543 | |
1544 | def get_bookmarks_list(self): |
1545 | - return self.select_single(UrlsList, objectName="bookmarksList") |
1546 | + return self.select_single(objectName="bookmarksList") |
1547 | + |
1548 | + def get_bookmark_delegates(self): |
1549 | + list = self.get_bookmarks_list() |
1550 | + return sorted(list.select_many(UrlDelegate), |
1551 | + key=lambda delegate: delegate.globalRect.y) |
1552 | |
1553 | def get_top_sites_list(self): |
1554 | return self.select_single(UrlPreviewGrid, objectName="topSitesList") |
1555 | @@ -666,16 +671,6 @@ |
1556 | return [folder.name for folder in self.get_folders_list()] |
1557 | |
1558 | |
1559 | -class UrlsList(uitk.UbuntuUIToolkitCustomProxyObjectBase): |
1560 | - |
1561 | - def get_delegates(self): |
1562 | - return sorted(self.select_many(UrlDelegate), |
1563 | - key=lambda delegate: delegate.globalRect.y) |
1564 | - |
1565 | - def get_urls(self): |
1566 | - return [delegate.url for delegate in self.get_delegates()] |
1567 | - |
1568 | - |
1569 | class UrlPreviewGrid(uitk.UbuntuUIToolkitCustomProxyObjectBase): |
1570 | |
1571 | def get_delegates(self): |
1572 | @@ -742,13 +737,11 @@ |
1573 | class BookmarksFoldersView(uitk.UbuntuUIToolkitCustomProxyObjectBase): |
1574 | |
1575 | def get_delegates(self): |
1576 | - return sorted(self.select_many("QQuickItem", |
1577 | - objectName="bookmarkFolderDelegate"), |
1578 | + return sorted(self.select_many(objectName="bookmarkFolderDelegate"), |
1579 | key=lambda delegate: delegate.globalRect.y) |
1580 | |
1581 | def get_folder_delegate(self, folder): |
1582 | - return self.select_single("QQuickItem", |
1583 | - objectName="bookmarkFolderDelegate", |
1584 | + return self.select_single(objectName="bookmarkFolderDelegate", |
1585 | folderName=folder) |
1586 | |
1587 | def get_urls_from_folder(self, folder): |
1588 | @@ -756,8 +749,7 @@ |
1589 | key=lambda delegate: delegate.globalRect.y) |
1590 | |
1591 | def get_header_from_folder(self, folder): |
1592 | - return folder.wait_select_single("QQuickItem", |
1593 | - objectName="bookmarkFolderHeader") |
1594 | + return folder.wait_select_single(objectName="bookmarkFolderHeader") |
1595 | |
1596 | |
1597 | class ContextMenuBase(uitk.UbuntuUIToolkitCustomProxyObjectBase): |
1598 | |
1599 | === modified file 'tests/autopilot/webbrowser_app/tests/test_new_tab_view.py' |
1600 | --- tests/autopilot/webbrowser_app/tests/test_new_tab_view.py 2016-01-14 14:43:02 +0000 |
1601 | +++ tests/autopilot/webbrowser_app/tests/test_new_tab_view.py 2016-02-11 08:27:04 +0000 |
1602 | @@ -238,8 +238,7 @@ |
1603 | self.main_window.wait_until_page_loaded(url) |
1604 | |
1605 | def test_open_bookmark(self): |
1606 | - bookmarks = self.new_tab_view.get_bookmarks_list() |
1607 | - bookmark = bookmarks.get_delegates()[1] |
1608 | + bookmark = self.new_tab_view.get_bookmark_delegates()[2] |
1609 | url = bookmark.url |
1610 | self.pointing_device.click_object(bookmark) |
1611 | self.new_tab_view.wait_until_destroyed() |
1612 | @@ -264,9 +263,8 @@ |
1613 | bookmarks = self.new_tab_view.get_bookmarks_list() |
1614 | top_sites = self.new_tab_view.get_top_sites_list() |
1615 | self.assertThat(top_sites.visible, Equals(True)) |
1616 | - # When the bookmarks list is collapsed, it shows a maximum of 4 entries |
1617 | - self.assertThat(lambda: len(bookmarks.get_delegates()), |
1618 | - Eventually(Equals(4))) |
1619 | + # When the bookmarks list is collapsed, it shows a maximum of 5 entries |
1620 | + self.assertThat(bookmarks.count, Eventually(Equals(5))) |
1621 | # When expanded, it shows all entries |
1622 | more_button = self.new_tab_view.get_bookmarks_more_button() |
1623 | self.assertThat(more_button.visible, Equals(True)) |
1624 | @@ -280,18 +278,17 @@ |
1625 | # Collapse again |
1626 | self.assertThat(more_button.visible, Equals(True)) |
1627 | self.pointing_device.click_object(more_button) |
1628 | - self.assertThat(lambda: len(bookmarks.get_delegates()), |
1629 | - Eventually(Equals(4))) |
1630 | + bookmarks = self.new_tab_view.get_bookmarks_list() |
1631 | + self.assertThat(bookmarks.count, Eventually(Equals(5))) |
1632 | self.assertThat(top_sites.visible, Eventually(Equals(True))) |
1633 | |
1634 | def _remove_first_bookmark(self): |
1635 | - bookmarks = self.new_tab_view.get_bookmarks_list() |
1636 | - delegate = bookmarks.get_delegates()[0] |
1637 | - url = delegate.url |
1638 | - delegate.trigger_leading_action("leadingAction.delete", |
1639 | - delegate.wait_until_destroyed) |
1640 | - self.assertThat(lambda: bookmarks.get_urls()[0], |
1641 | - Eventually(NotEquals(url))) |
1642 | + bookmark = self.new_tab_view.get_bookmark_delegates()[1] |
1643 | + url = bookmark.url |
1644 | + bookmark.trigger_leading_action("leadingAction.delete", lambda: None) |
1645 | + self.assertThat( |
1646 | + lambda: self.new_tab_view.get_bookmark_delegates()[1].url, |
1647 | + Eventually(NotEquals(url))) |
1648 | |
1649 | def _remove_first_bookmark_from_folder(self, folder): |
1650 | folders = self.new_tab_view.get_bookmarks_folder_list_view() |
1651 | @@ -314,14 +311,12 @@ |
1652 | |
1653 | def test_remove_bookmarks_when_collapsed(self): |
1654 | bookmarks = self.new_tab_view.get_bookmarks_list() |
1655 | - self.assertThat(lambda: len(bookmarks.get_delegates()), |
1656 | - Eventually(Equals(4))) |
1657 | + self.assertThat(bookmarks.count, Eventually(Equals(5))) |
1658 | more_button = self.new_tab_view.get_bookmarks_more_button() |
1659 | for i in range(3): |
1660 | self._remove_first_bookmark() |
1661 | self.assertThat(more_button.visible, Eventually(Equals(i < 1))) |
1662 | - self.assertThat(len(bookmarks.get_delegates()), |
1663 | - Equals(4 if (i < 2) else 3)) |
1664 | + self.assertThat(bookmarks.count, Equals(5 if (i < 2) else 4)) |
1665 | |
1666 | def test_remove_bookmarks_when_expanded(self): |
1667 | more_button = self.new_tab_view.get_bookmarks_more_button() |
1668 | |
1669 | === modified file 'tests/unittests/qml/CMakeLists.txt' |
1670 | --- tests/unittests/qml/CMakeLists.txt 2015-12-17 16:32:26 +0000 |
1671 | +++ tests/unittests/qml/CMakeLists.txt 2016-02-11 08:27:04 +0000 |
1672 | @@ -35,6 +35,7 @@ |
1673 | include_directories( |
1674 | ${webbrowser-common_SOURCE_DIR} |
1675 | ${webbrowser-app_SOURCE_DIR} |
1676 | + ${unity8_SOURCE_DIR}/plugins |
1677 | ) |
1678 | target_link_libraries(${TEST} |
1679 | Qt5::Core |
1680 | @@ -44,6 +45,7 @@ |
1681 | Qt5::Quick |
1682 | Qt5::QuickTest |
1683 | Qt5::Sql |
1684 | + InputInfo |
1685 | ) |
1686 | add_test(${TEST} ${XVFB_COMMAND} ${CMAKE_CURRENT_BINARY_DIR}/${TEST} |
1687 | -input ${CMAKE_CURRENT_SOURCE_DIR} |
1688 | |
1689 | === modified file 'tests/unittests/qml/tst_BookmarksView.qml' |
1690 | --- tests/unittests/qml/tst_BookmarksView.qml 2015-11-17 17:19:13 +0000 |
1691 | +++ tests/unittests/qml/tst_BookmarksView.qml 2016-02-11 08:27:04 +0000 |
1692 | @@ -1,5 +1,5 @@ |
1693 | /* |
1694 | - * Copyright 2015 Canonical Ltd. |
1695 | + * Copyright 2015-2016 Canonical Ltd. |
1696 | * |
1697 | * This file is part of webbrowser-app. |
1698 | * |
1699 | @@ -17,19 +17,22 @@ |
1700 | */ |
1701 | |
1702 | import QtQuick 2.4 |
1703 | +import QtQuick.Window 2.2 |
1704 | import QtTest 1.0 |
1705 | import "../../../src/app/webbrowser" |
1706 | import webbrowserapp.private 0.1 |
1707 | |
1708 | -Item { |
1709 | +FocusScope { |
1710 | id: root |
1711 | |
1712 | + focus: true |
1713 | width: 300 |
1714 | height: 500 |
1715 | |
1716 | BookmarksView { |
1717 | id: view |
1718 | anchors.fill: parent |
1719 | + focus: true |
1720 | homepageUrl: "http://example.com/homepage" |
1721 | } |
1722 | |
1723 | @@ -58,7 +61,7 @@ |
1724 | function init() { |
1725 | BookmarksModel.databasePath = ":memory:" |
1726 | populate() |
1727 | - view.forceActiveFocus() |
1728 | + verify(view.activeFocus) |
1729 | compare(bookmarkEntryClickedSpy.count, 0) |
1730 | compare(doneSpy.count, 0) |
1731 | compare(newTabClickedSpy.count, 0) |
1732 | @@ -110,5 +113,81 @@ |
1733 | swipeToDeleteAndConfirm(bookmark) |
1734 | tryCompare(BookmarksModel, "count", 2) |
1735 | } |
1736 | + |
1737 | + function test_keyboard_navigation() { |
1738 | + var listview = findChild(view, "bookmarksFolderListView") |
1739 | + waitForRendering(listview) |
1740 | + verify(listview.activeFocus) |
1741 | + |
1742 | + var firstHeader = findChild(listview, "bookmarkFolderHeader") |
1743 | + verify(firstHeader.activeFocus) |
1744 | + var firstFolder = firstHeader.parent |
1745 | + compare(firstFolder.folderName, "") |
1746 | + verify(firstFolder.expanded) |
1747 | + |
1748 | + keyClick(Qt.Key_Up) |
1749 | + verify(firstHeader.activeFocus) |
1750 | + |
1751 | + keyClick(Qt.Key_Space) |
1752 | + verify(!firstFolder.expanded) |
1753 | + |
1754 | + keyClick(Qt.Key_Space) |
1755 | + verify(firstFolder.expanded) |
1756 | + |
1757 | + keyClick(Qt.Key_Up) |
1758 | + verify(firstHeader.activeFocus) |
1759 | + |
1760 | + keyClick(Qt.Key_Down) |
1761 | + verify(findChild(firstFolder, "urlDelegate_0").activeFocus) |
1762 | + |
1763 | + keyClick(Qt.Key_Enter) |
1764 | + compare(bookmarkEntryClickedSpy.count, 1) |
1765 | + compare(bookmarkEntryClickedSpy.signalArguments[0][0], "http://example.com/homepage") |
1766 | + |
1767 | + keyClick(Qt.Key_Down) |
1768 | + verify(findChild(firstFolder, "urlDelegate_1").activeFocus) |
1769 | + |
1770 | + keyClick(Qt.Key_Return) |
1771 | + compare(bookmarkEntryClickedSpy.count, 2) |
1772 | + compare(bookmarkEntryClickedSpy.signalArguments[1][0], "http://example.com") |
1773 | + |
1774 | + keyClick(Qt.Key_Delete) |
1775 | + compare(BookmarksModel.count, 2) |
1776 | + verify(findChild(firstFolder, "urlDelegate_0").activeFocus) |
1777 | + |
1778 | + keyClick(Qt.Key_Down) |
1779 | + var secondHeader = root.Window.activeFocusItem |
1780 | + compare(secondHeader.objectName, "bookmarkFolderHeader") |
1781 | + var secondFolder = secondHeader.parent |
1782 | + compare(secondFolder.folderName, "FolderA") |
1783 | + verify(!secondFolder.expanded) |
1784 | + |
1785 | + keyClick(Qt.Key_Down) |
1786 | + var thirdHeader = root.Window.activeFocusItem |
1787 | + compare(thirdHeader.objectName, "bookmarkFolderHeader") |
1788 | + var thirdFolder = thirdHeader.parent |
1789 | + compare(thirdFolder.folderName, "FolderB") |
1790 | + verify(!thirdFolder.expanded) |
1791 | + |
1792 | + keyClick(Qt.Key_Down) |
1793 | + verify(thirdHeader.activeFocus) |
1794 | + |
1795 | + keyClick(Qt.Key_Delete) |
1796 | + verify(thirdHeader.activeFocus) |
1797 | + |
1798 | + keyClick(Qt.Key_Space) |
1799 | + verify(thirdFolder.expanded) |
1800 | + |
1801 | + keyClick(Qt.Key_Down) |
1802 | + verify(findChild(thirdFolder, "urlDelegate_0").activeFocus) |
1803 | + |
1804 | + keyClick(Qt.Key_Delete) |
1805 | + compare(BookmarksModel.count, 1) |
1806 | + verify(!thirdFolder.active) |
1807 | + verify(secondFolder.activeFocus) |
1808 | + |
1809 | + keyClick(Qt.Key_Space) |
1810 | + verify(secondFolder.expanded) |
1811 | + } |
1812 | } |
1813 | } |
1814 | |
1815 | === modified file 'tests/unittests/qml/tst_HistoryView.qml' |
1816 | --- tests/unittests/qml/tst_HistoryView.qml 2015-12-17 16:32:26 +0000 |
1817 | +++ tests/unittests/qml/tst_HistoryView.qml 2016-02-11 08:27:04 +0000 |
1818 | @@ -1,5 +1,5 @@ |
1819 | /* |
1820 | - * Copyright 2015 Canonical Ltd. |
1821 | + * Copyright 2015-2016 Canonical Ltd. |
1822 | * |
1823 | * This file is part of webbrowser-app. |
1824 | * |
1825 | @@ -17,17 +17,19 @@ |
1826 | */ |
1827 | |
1828 | import QtQuick 2.4 |
1829 | +import QtQuick.Window 2.2 |
1830 | import QtTest 1.0 |
1831 | import "../../../src/app/webbrowser" |
1832 | import webbrowserapp.private 0.1 |
1833 | |
1834 | -Item { |
1835 | +FocusScope { |
1836 | id: root |
1837 | |
1838 | + focus: true |
1839 | width: 300 |
1840 | height: 500 |
1841 | |
1842 | - readonly property var historyView: historyViewLoader.item |
1843 | + readonly property Item historyView: historyViewLoader.item |
1844 | |
1845 | Loader { |
1846 | id: historyViewLoader |
1847 | @@ -65,8 +67,9 @@ |
1848 | HistoryModel.databasePath = ":memory:" |
1849 | populate() |
1850 | historyViewLoader.active = true |
1851 | + historyView.loadModel() |
1852 | waitForRendering(historyView) |
1853 | - historyView.loadModel() |
1854 | + verify(historyView.activeFocus) |
1855 | var domainsList = findChild(historyView, "domainsListView") |
1856 | waitForRendering(domainsList) |
1857 | tryCompare(domainsList, "count", 3) |
1858 | @@ -82,6 +85,7 @@ |
1859 | } |
1860 | |
1861 | function cleanup() { |
1862 | + historyViewLoader.active = false |
1863 | HistoryModel.databasePath = "" |
1864 | seeMoreEntriesClickedSpy.clear() |
1865 | doneSpy.clear() |
1866 | @@ -185,5 +189,47 @@ |
1867 | clickItem(deleteButton) |
1868 | tryCompare(HistoryModel, "count", 0) |
1869 | } |
1870 | + |
1871 | + function test_keyboard_navigation() { |
1872 | + var listview = findChild(historyView, "domainsListView") |
1873 | + verify(listview.activeFocus) |
1874 | + var domains = getListItems(listview, "historyViewDomainDelegate") |
1875 | + |
1876 | + function check_current(index) { |
1877 | + compare(listview.currentIndex, index) |
1878 | + var current = root.Window.activeFocusItem |
1879 | + compare(current.objectName, "historyViewDomainDelegate") |
1880 | + compare(current.modelIndex, index) |
1881 | + compare(current.title, domains[index].title) |
1882 | + verify(current.activeFocus) |
1883 | + return current |
1884 | + } |
1885 | + |
1886 | + var current = check_current(0) |
1887 | + |
1888 | + keyClick(Qt.Key_Up) |
1889 | + verify(current.activeFocus) |
1890 | + |
1891 | + keyClick(Qt.Key_Enter) |
1892 | + compare(seeMoreEntriesClickedSpy.count, 1) |
1893 | + compare(seeMoreEntriesClickedSpy.signalArguments[0][0].domain, domains[0].title) |
1894 | + |
1895 | + keyClick(Qt.Key_Down) |
1896 | + current = check_current(1) |
1897 | + |
1898 | + keyClick(Qt.Key_Return) |
1899 | + compare(seeMoreEntriesClickedSpy.count, 2) |
1900 | + compare(seeMoreEntriesClickedSpy.signalArguments[1][0].domain, domains[1].title) |
1901 | + |
1902 | + keyClick(Qt.Key_Down) |
1903 | + current = check_current(2) |
1904 | + |
1905 | + keyClick(Qt.Key_Down) |
1906 | + verify(current.activeFocus) |
1907 | + |
1908 | + keyClick(Qt.Key_Delete) |
1909 | + tryCompare(listview, 'currentIndex', 1) |
1910 | + current = check_current(1) |
1911 | + } |
1912 | } |
1913 | } |
1914 | |
1915 | === added file 'tests/unittests/qml/tst_NewTabView.qml' |
1916 | --- tests/unittests/qml/tst_NewTabView.qml 1970-01-01 00:00:00 +0000 |
1917 | +++ tests/unittests/qml/tst_NewTabView.qml 2016-02-11 08:27:04 +0000 |
1918 | @@ -0,0 +1,292 @@ |
1919 | +/* |
1920 | + * Copyright 2016 Canonical Ltd. |
1921 | + * |
1922 | + * This file is part of webbrowser-app. |
1923 | + * |
1924 | + * webbrowser-app is free software; you can redistribute it and/or modify |
1925 | + * it under the terms of the GNU General Public License as published by |
1926 | + * the Free Software Foundation; version 3. |
1927 | + * |
1928 | + * webbrowser-app is distributed in the hope that it will be useful, |
1929 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1930 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1931 | + * GNU General Public License for more details. |
1932 | + * |
1933 | + * You should have received a copy of the GNU General Public License |
1934 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1935 | + */ |
1936 | + |
1937 | +import QtQuick 2.4 |
1938 | +import QtQuick.Window 2.2 |
1939 | +import QtTest 1.0 |
1940 | +import Qt.labs.settings 1.0 |
1941 | +import "../../../src/app/webbrowser" |
1942 | +import webbrowserapp.private 0.1 |
1943 | + |
1944 | +FocusScope { |
1945 | + id: root |
1946 | + |
1947 | + focus: true |
1948 | + width: 350 |
1949 | + height: 500 |
1950 | + |
1951 | + Loader { |
1952 | + id: newTabViewLoader |
1953 | + anchors.fill: parent |
1954 | + focus: true |
1955 | + active: false |
1956 | + sourceComponent: NewTabView { |
1957 | + focus: true |
1958 | + anchors.fill: parent |
1959 | + settingsObject: Settings { |
1960 | + property url homepage: "http://example.com/homepage" |
1961 | + } |
1962 | + } |
1963 | + } |
1964 | + |
1965 | + readonly property Item view: newTabViewLoader.item |
1966 | + |
1967 | + SignalSpy { |
1968 | + id: bookmarkClickedSpy |
1969 | + target: view |
1970 | + signalName: "bookmarkClicked" |
1971 | + } |
1972 | + |
1973 | + SignalSpy { |
1974 | + id: bookmarkRemovedSpy |
1975 | + target: view |
1976 | + signalName: "bookmarkRemoved" |
1977 | + } |
1978 | + |
1979 | + SignalSpy { |
1980 | + id: historyEntryClickedSpy |
1981 | + target: view |
1982 | + signalName: "historyEntryClicked" |
1983 | + } |
1984 | + |
1985 | + SignalSpy { |
1986 | + id: countChangedSpy |
1987 | + signalName: "countChanged" |
1988 | + } |
1989 | + |
1990 | + WebbrowserTestCase { |
1991 | + name: "NewTabView" |
1992 | + when: windowShown |
1993 | + |
1994 | + function init() { |
1995 | + HistoryModel.databasePath = ":memory:" |
1996 | + BookmarksModel.databasePath = ":memory:" |
1997 | + populate() |
1998 | + newTabViewLoader.active = true |
1999 | + waitForRendering(view) |
2000 | + verify(view.activeFocus) |
2001 | + compare(bookmarkClickedSpy.count, 0) |
2002 | + compare(bookmarkRemovedSpy.count, 0) |
2003 | + compare(historyEntryClickedSpy.count, 0) |
2004 | + } |
2005 | + |
2006 | + function populate() { |
2007 | + HistoryModel.add("http://example.com/foo", "foo", "") |
2008 | + HistoryModel.add("http://example.org/bar", "bar", "") |
2009 | + HistoryModel.add("http://example.net/baz", "baz", "") |
2010 | + HistoryModel.add("http://example.net/qux", "qux", "") |
2011 | + HistoryModel.add("http://example.net/norf", "norf", "") |
2012 | + compare(HistoryModel.count, 5) |
2013 | + |
2014 | + BookmarksModel.add("http://example.com", "Example", "", "") |
2015 | + BookmarksModel.add("http://example.org/a", "Example a", "", "FolderA") |
2016 | + BookmarksModel.add("http://example.org/b", "Example b", "", "FolderB") |
2017 | + BookmarksModel.add("http://example.org/c", "Example c", "", "FolderC") |
2018 | + BookmarksModel.add("http://example.org/d", "Example d", "", "FolderD") |
2019 | + compare(BookmarksModel.count, 5) |
2020 | + } |
2021 | + |
2022 | + function cleanup() { |
2023 | + newTabViewLoader.active = false |
2024 | + BookmarksModel.databasePath = "" |
2025 | + HistoryModel.databasePath = "" |
2026 | + bookmarkClickedSpy.clear() |
2027 | + bookmarkRemovedSpy.clear() |
2028 | + historyEntryClickedSpy.clear() |
2029 | + } |
2030 | + |
2031 | + function verify_bookmarks_expanded(expected) { |
2032 | + if (expected) { |
2033 | + compare(findChild(view, "bookmarksList"), null) |
2034 | + compare(findChild(view, "bookmarksFolderListView").objectName, |
2035 | + "bookmarksFolderListView") |
2036 | + } else { |
2037 | + compare(findChild(view, "bookmarksList").objectName, |
2038 | + "bookmarksList") |
2039 | + compare(findChild(view, "bookmarksFolderListView"), null) |
2040 | + } |
2041 | + } |
2042 | + |
2043 | + function check_focused_item(objectName) { |
2044 | + var focused = root.Window.activeFocusItem |
2045 | + verify(focused !== null) |
2046 | + compare(focused.objectName, objectName) |
2047 | + return focused |
2048 | + } |
2049 | + |
2050 | + function test_click_bookmark() { |
2051 | + var listview = findChild(view, "bookmarksList") |
2052 | + |
2053 | + var homepage = findChild(listview, "homepageBookmark") |
2054 | + clickItem(homepage) |
2055 | + compare(bookmarkClickedSpy.count, 1) |
2056 | + compare(bookmarkClickedSpy.signalArguments[0][0], |
2057 | + view.settingsObject.homepage) |
2058 | + |
2059 | + var bookmark = findChild(listview, "bookmark_1") |
2060 | + clickItem(bookmark) |
2061 | + compare(bookmarkClickedSpy.count, 2) |
2062 | + compare(bookmarkClickedSpy.signalArguments[1][0], bookmark.url) |
2063 | + } |
2064 | + |
2065 | + function test_delete_bookmark() { |
2066 | + var listview = findChild(view, "bookmarksList") |
2067 | + var bookmark = findChild(listview, "bookmark_2") |
2068 | + swipeToDeleteAndConfirm(bookmark) |
2069 | + bookmarkRemovedSpy.wait() |
2070 | + compare(bookmarkRemovedSpy.count, 1) |
2071 | + compare(bookmarkRemovedSpy.signalArguments[0][0], bookmark.url) |
2072 | + } |
2073 | + |
2074 | + function test_expand_bookmarks() { |
2075 | + verify_bookmarks_expanded(false) |
2076 | + var button = findChild(view, "bookmarks.moreButton") |
2077 | + clickItem(button) |
2078 | + verify_bookmarks_expanded(true) |
2079 | + clickItem(button) |
2080 | + verify_bookmarks_expanded(false) |
2081 | + } |
2082 | + |
2083 | + function test_click_top_site() { |
2084 | + var grid = findChild(view, "topSitesList") |
2085 | + compare(grid.count, 5) |
2086 | + var topsites = getListItems(grid, "topSiteItem") |
2087 | + compare(topsites.length, 5) |
2088 | + var topsite = topsites[3] |
2089 | + clickItem(topsite) |
2090 | + compare(historyEntryClickedSpy.count, 1) |
2091 | + compare(historyEntryClickedSpy.signalArguments[0][0], topsite.url) |
2092 | + } |
2093 | + |
2094 | + function test_delete_top_site() { |
2095 | + var grid = findChild(view, "topSitesList") |
2096 | + compare(grid.count, 5) |
2097 | + var topsite = getListItems(grid, "topSiteItem")[1] |
2098 | + clickItem(topsite, Qt.RightButton) |
2099 | + var contextMenu = findChild(root, "urlPreviewDelegate.contextMenu") |
2100 | + var action = findChild(contextMenu, "delete_button") |
2101 | + clickItem(action) |
2102 | + compare(grid.count, 4) |
2103 | + } |
2104 | + |
2105 | + function test_keyboard_navigation() { |
2106 | + var bookmarksList = findChild(view, "bookmarksList") |
2107 | + verify(bookmarksList.activeFocus) |
2108 | + check_focused_item("homepageBookmark") |
2109 | + |
2110 | + keyClick(Qt.Key_Up) |
2111 | + check_focused_item("bookmarkListHeader") |
2112 | + |
2113 | + verify_bookmarks_expanded(false) |
2114 | + keyClick(Qt.Key_Enter) |
2115 | + verify_bookmarks_expanded(true) |
2116 | + keyClick(Qt.Key_Return) |
2117 | + verify_bookmarks_expanded(false) |
2118 | + keyClick(Qt.Key_Space) |
2119 | + verify_bookmarks_expanded(true) |
2120 | + keyClick(Qt.Key_Enter) |
2121 | + verify_bookmarks_expanded(false) |
2122 | + |
2123 | + keyClick(Qt.Key_Up) |
2124 | + check_focused_item("bookmarkListHeader") |
2125 | + |
2126 | + keyClick(Qt.Key_Down) |
2127 | + check_focused_item("homepageBookmark") |
2128 | + |
2129 | + keyClick(Qt.Key_Delete) |
2130 | + compare(bookmarkRemovedSpy.count, 0) |
2131 | + |
2132 | + keyClick(Qt.Key_Enter) |
2133 | + compare(bookmarkClickedSpy.count, 1) |
2134 | + compare(bookmarkClickedSpy.signalArguments[0][0], |
2135 | + view.settingsObject.homepage) |
2136 | + |
2137 | + keyClick(Qt.Key_Down) |
2138 | + var bookmark = check_focused_item("bookmark_1") |
2139 | + |
2140 | + keyClick(Qt.Key_Delete) |
2141 | + compare(bookmarkRemovedSpy.count, 1) |
2142 | + compare(bookmarkRemovedSpy.signalArguments[0][0], bookmark.url) |
2143 | + |
2144 | + keyClick(Qt.Key_Down) |
2145 | + keyClick(Qt.Key_Down) |
2146 | + keyClick(Qt.Key_Down) |
2147 | + check_focused_item("bookmark_4") |
2148 | + |
2149 | + keyClick(Qt.Key_Down) |
2150 | + var grid = findChild(view, "topSitesList") |
2151 | + verify(grid.activeFocus) |
2152 | + compare(grid.currentIndex, 0) |
2153 | + var topsite = check_focused_item("topSiteItem") |
2154 | + |
2155 | + keyClick(Qt.Key_Enter) |
2156 | + compare(historyEntryClickedSpy.count, 1) |
2157 | + compare(historyEntryClickedSpy.signalArguments[0][0], topsite.url) |
2158 | + |
2159 | + keyClick(Qt.Key_Return) |
2160 | + compare(historyEntryClickedSpy.count, 2) |
2161 | + compare(historyEntryClickedSpy.signalArguments[1][0], topsite.url) |
2162 | + |
2163 | + keyClick(Qt.Key_Right) |
2164 | + compare(grid.currentIndex, 1) |
2165 | + check_focused_item("topSiteItem") |
2166 | + |
2167 | + keyClick(Qt.Key_Down) |
2168 | + compare(grid.currentIndex, 3) |
2169 | + check_focused_item("topSiteItem") |
2170 | + |
2171 | + keyClick(Qt.Key_Down) |
2172 | + compare(grid.currentIndex, 3) |
2173 | + check_focused_item("topSiteItem") |
2174 | + |
2175 | + keyClick(Qt.Key_Left) |
2176 | + compare(grid.currentIndex, 2) |
2177 | + check_focused_item("topSiteItem") |
2178 | + |
2179 | + keyClick(Qt.Key_Down) |
2180 | + compare(grid.currentIndex, 4) |
2181 | + check_focused_item("topSiteItem") |
2182 | + |
2183 | + keyClick(Qt.Key_Down) |
2184 | + compare(grid.currentIndex, 4) |
2185 | + check_focused_item("topSiteItem") |
2186 | + |
2187 | + keyClick(Qt.Key_Left) |
2188 | + compare(grid.currentIndex, 3) |
2189 | + check_focused_item("topSiteItem") |
2190 | + |
2191 | + var notopsiteslabel = findChild(view, "notopsites") |
2192 | + verify(!notopsiteslabel.visible) |
2193 | + compare(grid.count, 5) |
2194 | + countChangedSpy.target = grid |
2195 | + for (var i = 4; i >= 0; --i) { |
2196 | + keyClick(Qt.Key_Delete) |
2197 | + countChangedSpy.wait() |
2198 | + compare(grid.count, i) |
2199 | + compare(grid.currentIndex, i - 1) |
2200 | + } |
2201 | + compare(grid.count, 0) |
2202 | + verify(notopsiteslabel.visible) |
2203 | + bookmarksList = findChild(view, "bookmarksList") |
2204 | + verify(bookmarksList.activeFocus) |
2205 | + |
2206 | + keyClick(Qt.Key_Down) |
2207 | + verify(bookmarksList.activeFocus) |
2208 | + } |
2209 | + } |
2210 | +} |
2211 | |
2212 | === modified file 'tests/unittests/qml/tst_NewTabViewWide.qml' |
2213 | --- tests/unittests/qml/tst_NewTabViewWide.qml 2015-11-17 17:16:37 +0000 |
2214 | +++ tests/unittests/qml/tst_NewTabViewWide.qml 2016-02-11 08:27:04 +0000 |
2215 | @@ -1,5 +1,5 @@ |
2216 | /* |
2217 | - * Copyright 2015 Canonical Ltd. |
2218 | + * Copyright 2015-2016 Canonical Ltd. |
2219 | * |
2220 | * This file is part of webbrowser-app. |
2221 | * |
2222 | @@ -43,11 +43,6 @@ |
2223 | } |
2224 | |
2225 | SignalSpy { |
2226 | - id: releasingKeyboardFocusSpy |
2227 | - signalName: "releasingKeyboardFocus" |
2228 | - } |
2229 | - |
2230 | - SignalSpy { |
2231 | id: historyEntryClickedSpy |
2232 | signalName: "historyEntryClicked" |
2233 | } |
2234 | @@ -76,8 +71,6 @@ |
2235 | |
2236 | view.focus = true |
2237 | |
2238 | - releasingKeyboardFocusSpy.target = view |
2239 | - releasingKeyboardFocusSpy.clear() |
2240 | historyEntryClickedSpy.target = view |
2241 | historyEntryClickedSpy.clear() |
2242 | bookmarkClickedSpy.target = view |
2243 | @@ -163,10 +156,8 @@ |
2244 | compare(list.currentIndex, 0) |
2245 | keyClick(Qt.Key_Up) |
2246 | compare(list.currentIndex, 0) |
2247 | - compare(releasingKeyboardFocusSpy.count, 1) |
2248 | keyClick(Qt.Key_Left) |
2249 | compare(list.currentIndex, 0) |
2250 | - compare(releasingKeyboardFocusSpy.count, 2) |
2251 | } |
2252 | |
2253 | function test_activate_topsites_by_keyboard() { |
2254 | |
2255 | === modified file 'tests/unittests/qml/tst_QmlTests.cpp' |
2256 | --- tests/unittests/qml/tst_QmlTests.cpp 2015-12-17 16:32:26 +0000 |
2257 | +++ tests/unittests/qml/tst_QmlTests.cpp 2016-02-11 08:27:04 +0000 |
2258 | @@ -1,5 +1,5 @@ |
2259 | /* |
2260 | - * Copyright 2013-2015 Canonical Ltd. |
2261 | + * Copyright 2013-2016 Canonical Ltd. |
2262 | * |
2263 | * This file is part of webbrowser-app. |
2264 | * |
2265 | @@ -37,13 +37,7 @@ |
2266 | #include "searchengine.h" |
2267 | #include "tabs-model.h" |
2268 | #include "text-search-filter-model.h" |
2269 | - |
2270 | -static QObject* FileOperations_singleton_factory(QQmlEngine* engine, QJSEngine* scriptEngine) |
2271 | -{ |
2272 | - Q_UNUSED(engine); |
2273 | - Q_UNUSED(scriptEngine); |
2274 | - return new FileOperations(); |
2275 | -} |
2276 | +#include "Unity/InputInfo/qdeclarativeinputdevicemodel_p.h" |
2277 | |
2278 | class TestContext : public QObject |
2279 | { |
2280 | @@ -126,60 +120,51 @@ |
2281 | }; |
2282 | |
2283 | class HistoryModelMock : public HistoryModel { |
2284 | - Q_OBJECT |
2285 | + Q_OBJECT |
2286 | |
2287 | public: |
2288 | - static bool compareHistoryEntries(const HistoryEntry& a, const HistoryEntry& b) { |
2289 | - return a.lastVisit < b.lastVisit; |
2290 | - } |
2291 | - |
2292 | - Q_INVOKABLE int addByDate(const QUrl& url, const QString& title, const QDateTime& date) |
2293 | - { |
2294 | - int index = getEntryIndex(url); |
2295 | - int visitsToAdd = 1; |
2296 | - if (index == -1) { |
2297 | - add(url, title, QString()); |
2298 | - index = getEntryIndex(url); |
2299 | - visitsToAdd = 0; |
2300 | - } |
2301 | - |
2302 | - // Since this is useful only for testing and efficiency is not critical |
2303 | - // we reorder the model and reset it every time we add a new item by date |
2304 | - // to keep things simple. |
2305 | - beginResetModel(); |
2306 | - HistoryEntry entry = m_entries.takeAt(index); |
2307 | - entry.lastVisit = date; |
2308 | - entry.visits = entry.visits + visitsToAdd; |
2309 | - m_entries.append(entry); |
2310 | - std::sort(m_entries.begin(), m_entries.end(), compareHistoryEntries); |
2311 | - endResetModel(); |
2312 | - |
2313 | - updateExistingEntryInDatabase(entry); |
2314 | - |
2315 | - return entry.visits; |
2316 | - } |
2317 | + static bool compareHistoryEntries(const HistoryEntry& a, const HistoryEntry& b) { |
2318 | + return a.lastVisit < b.lastVisit; |
2319 | + } |
2320 | + |
2321 | + Q_INVOKABLE int addByDate(const QUrl& url, const QString& title, const QDateTime& date) |
2322 | + { |
2323 | + int index = getEntryIndex(url); |
2324 | + int visitsToAdd = 1; |
2325 | + if (index == -1) { |
2326 | + add(url, title, QString()); |
2327 | + index = getEntryIndex(url); |
2328 | + visitsToAdd = 0; |
2329 | + } |
2330 | + |
2331 | + // Since this is useful only for testing and efficiency is not critical |
2332 | + // we reorder the model and reset it every time we add a new item by date |
2333 | + // to keep things simple. |
2334 | + beginResetModel(); |
2335 | + HistoryEntry entry = m_entries.takeAt(index); |
2336 | + entry.lastVisit = date; |
2337 | + entry.visits = entry.visits + visitsToAdd; |
2338 | + m_entries.append(entry); |
2339 | + std::sort(m_entries.begin(), m_entries.end(), compareHistoryEntries); |
2340 | + endResetModel(); |
2341 | + |
2342 | + updateExistingEntryInDatabase(entry); |
2343 | + |
2344 | + return entry.visits; |
2345 | + } |
2346 | }; |
2347 | |
2348 | -static QObject* TestContext_singleton_factory(QQmlEngine* engine, QJSEngine* scriptEngine) |
2349 | -{ |
2350 | - Q_UNUSED(engine); |
2351 | - Q_UNUSED(scriptEngine); |
2352 | - return new TestContext(); |
2353 | -} |
2354 | - |
2355 | -static QObject* BookmarksModel_singleton_factory(QQmlEngine* engine, QJSEngine* scriptEngine) |
2356 | -{ |
2357 | - Q_UNUSED(engine); |
2358 | - Q_UNUSED(scriptEngine); |
2359 | - return new BookmarksModel(); |
2360 | -} |
2361 | - |
2362 | -static QObject* HistoryModel_singleton_factory(QQmlEngine* engine, QJSEngine* scriptEngine) |
2363 | -{ |
2364 | - Q_UNUSED(engine); |
2365 | - Q_UNUSED(scriptEngine); |
2366 | - return new HistoryModelMock(); |
2367 | -} |
2368 | +#define MAKE_SINGLETON_FACTORY(type) \ |
2369 | + static QObject* type##_singleton_factory(QQmlEngine* engine, QJSEngine* scriptEngine) { \ |
2370 | + Q_UNUSED(engine); \ |
2371 | + Q_UNUSED(scriptEngine); \ |
2372 | + return new type(); \ |
2373 | + } |
2374 | + |
2375 | +MAKE_SINGLETON_FACTORY(FileOperations) |
2376 | +MAKE_SINGLETON_FACTORY(BookmarksModel) |
2377 | +MAKE_SINGLETON_FACTORY(HistoryModelMock) |
2378 | +MAKE_SINGLETON_FACTORY(TestContext) |
2379 | |
2380 | int main(int argc, char** argv) |
2381 | { |
2382 | @@ -191,7 +176,7 @@ |
2383 | qmlRegisterType<TabsModel>(browserUri, 0, 1, "TabsModel"); |
2384 | qmlRegisterSingletonType<BookmarksModel>(browserUri, 0, 1, "BookmarksModel", BookmarksModel_singleton_factory); |
2385 | qmlRegisterType<BookmarksFolderListModel>(browserUri, 0, 1, "BookmarksFolderListModel"); |
2386 | - qmlRegisterSingletonType<HistoryModel>(browserUri, 0, 1, "HistoryModel", HistoryModel_singleton_factory); |
2387 | + qmlRegisterSingletonType<HistoryModel>(browserUri, 0, 1, "HistoryModel", HistoryModelMock_singleton_factory); |
2388 | qmlRegisterType<HistoryDomainModel>(browserUri, 0, 1, "HistoryDomainModel"); |
2389 | qmlRegisterType<HistoryDomainListModel>(browserUri, 0, 1, "HistoryDomainListModel"); |
2390 | qmlRegisterType<HistoryLastVisitDateListModel>(browserUri, 0, 1, "HistoryLastVisitDateListModel"); |
2391 | @@ -202,6 +187,10 @@ |
2392 | const char* testUri = "webbrowsertest.private"; |
2393 | qmlRegisterSingletonType<TestContext>(testUri, 0, 1, "TestContext", TestContext_singleton_factory); |
2394 | |
2395 | + const char* inputInfoUri = "Unity.InputInfo"; |
2396 | + qmlRegisterType<QDeclarativeInputDeviceModel>(inputInfoUri, 0, 1, "InputDeviceModel"); |
2397 | + qmlRegisterType<QInputDevice>(inputInfoUri, 0, 1, "InputInfo"); |
2398 | + |
2399 | return quick_test_main(argc, argv, "QmlTests", nullptr); |
2400 | } |
2401 |
FAILED: Continuous integration, rev:1359 jenkins. qa.ubuntu. com/job/ webbrowser- app-ci/ 2608/ jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- vivid-touch/ 6349/console jenkins. qa.ubuntu. com/job/ webbrowser- app-vivid- amd64-ci/ 1361/console jenkins. qa.ubuntu. com/job/ webbrowser- app-vivid- armhf-ci/ 1361/console jenkins. qa.ubuntu. com/job/ webbrowser- app-vivid- i386-ci/ 1361/console jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- vivid-armhf/ 6360/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/webbrowser- app-ci/ 2608/rebuild
http://