Merge lp:~uriboni/webbrowser-app/new-tab-wide-format into lp:webbrowser-app

Proposed by Ugo Riboni
Status: Merged
Merged at revision: 1128
Proposed branch: lp:~uriboni/webbrowser-app/new-tab-wide-format
Merge into: lp:webbrowser-app
Diff against target: 1928 lines (+1244/-153)
21 files modified
debian/control (+1/-0)
src/app/webbrowser/Browser.qml (+63/-27)
src/app/webbrowser/DraggableUrlDelegateWide.qml (+98/-0)
src/app/webbrowser/NewTabViewWide.qml (+317/-0)
src/app/webbrowser/UrlDelegateWide.qml (+86/-0)
src/app/webbrowser/bookmarks-folder-model.cpp (+21/-1)
src/app/webbrowser/bookmarks-folder-model.h (+1/-0)
src/app/webbrowser/bookmarks-folderlist-model.cpp (+5/-0)
src/app/webbrowser/bookmarks-folderlist-model.h (+2/-0)
tests/autopilot/webbrowser_app/emulators/browser.py (+77/-4)
tests/autopilot/webbrowser_app/tests/__init__.py (+8/-2)
tests/autopilot/webbrowser_app/tests/test_addressbar_bookmark.py (+2/-6)
tests/autopilot/webbrowser_app/tests/test_bookmark_options.py (+32/-46)
tests/autopilot/webbrowser_app/tests/test_findinpage.py (+1/-2)
tests/autopilot/webbrowser_app/tests/test_new_tab_view.py (+121/-43)
tests/autopilot/webbrowser_app/tests/test_private.py (+8/-13)
tests/autopilot/webbrowser_app/tests/test_tabs.py (+2/-6)
tests/unittests/bookmarks-folder-model/tst_BookmarksFolderModelTests.cpp (+6/-3)
tests/unittests/qml/CMakeLists.txt (+9/-0)
tests/unittests/qml/tst_NewTabViewWide.qml (+372/-0)
tests/unittests/qml/tst_QmlTests.cpp (+12/-0)
To merge this branch: bzr merge lp:~uriboni/webbrowser-app/new-tab-wide-format
Reviewer Review Type Date Requested Status
Olivier Tilloy Approve
PS Jenkins bot continuous-integration Needs Fixing
Review via email: mp+266382@code.launchpad.net

Commit message

Implement the widescreen/landscape version of the "new tab" view.
This adds a build dependency on qml-module-qt-labs-settings (for unit tests).

Description of the change

Implement the widescreen/landscape version of the "new tab" view.

It requires the new Sections UITK component which is currently in the staging branch: lp:~ubuntu-sdk-team/ubuntu-ui-toolkit/staging

To post a comment you must log in.
1075. By Ugo Riboni

Merge changes from trunk

1076. By Ugo Riboni

Remove useless import and fix flake8 errors

1077. By Ugo Riboni

Revert changes to UrlDelegate.qml as we are now using a new component instead

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1078. By Ugo Riboni

Fix copyright header

1079. By Ugo Riboni

Revert changes to UrlsList as we are not using it anymore

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1080. By Ugo Riboni

Add qt.labs.settings as build dep

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1081. By Ugo Riboni

Revert previous commit and actually commit the change to the debian dependencies

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Olivier Tilloy (osomon) wrote :

When scrolling the "top sites" view, the first item is drawn on top of the sections header. Either the header should have a higher z-order than the list view, or the list view should be clipped.

The background color of the sections header doesn’t match the visual spec (https://docs.google.com/presentation/d/1ggKmkxUFR5xCBcvkjJ4On9b4iKzEqcycz4hjc16tBGo/edit#slide=id.g2bddb9a1a_038).

In the bookmarks view, when the right panel has active focus the current folder in the left panel should still be highlighted.

In the bookmarks view, the font color for the current bookmark in the right panel shouldn’t be orange.

It seems to be that favicons in the view are too large, and that the font size for delegates is too big as well.

In the visual spec the folders list has a left margin, and folders are separated by horizontal lines.

According to the specification: « User can drag a bookmark in a folder. Bookmarks can only exist in one folder at a time ».

On my vivid desktop, with the UITK staging branch, QmlTests::NewTabLandscapeView::test_switch_sections_by_keyboard() is reliably failing:
  2: FAIL! : QmlTests::NewTabLandscapeView::test_switch_sections_by_keyboard() Compared values are not the same
  2: Actual (): 0
  2: Expected (): 1
  2: Loc: [/home/osomon/dev/phablet/browser/webbrowser-app/tests/unittests/qml/tst_NewTabLandscapeView.qml(191)]

Although not specified, there should probably be scrollbars for all the listviews.

Can you check with design whether we really want all the top sites section to not have a limit? I’d personally add a limit (maybe 10, or 20 top sites max).

Can NewTabLandscapeView be renamed NewTabViewWide?

review: Needs Fixing
1082. By Ugo Riboni

Move the Sections block to the bottom of the view so that list items will not overlap it

1083. By Ugo Riboni

Keep the current folder selected in orange even when the folder list does not have active focus

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
1084. By Ugo Riboni

Rename the components to be called *Wide instead of *Landscape

1085. By Ugo Riboni

Add scrollbars to all lists

1086. By Ugo Riboni

Add a limit of 10 items to the top sites list and unit test it

Revision history for this message
Ugo Riboni (uriboni) wrote :

> When scrolling the "top sites" view, the first item is drawn on top of the
> sections header. Either the header should have a higher z-order than the list
> view, or the list view should be clipped.

Done

> The background color of the sections header doesn’t match the visual spec (htt
> ps://docs.google.com/presentation/d/1ggKmkxUFR5xCBcvkjJ4On9b4iKzEqcycz4hjc16tB
> Go/edit#slide=id.g2bddb9a1a_038).

This and all the other visuals-related comments you made refer to the above linked document, which is the UX spec, not the visual spec. The current design follows the visual spec as closely as possible (minus some changes that will come from the UITK): https://docs.google.com/presentation/d/1woHjO8K4iqyVZZlfQ4BXL0DhYbwkEmZ7wvcUhYzHDRk/edit?pli=1#slide=id.gb81843c7e_0_42

> According to the specification: « User can drag a bookmark in a folder.
> Bookmarks can only exist in one folder at a time ».

I consulted with design and they need to provide some extra UX and visual guidance. They will do so next week but in the meantime I am adding a provisional implementation based on advice I got from James over IRC.

> On my vivid desktop, with the UITK staging branch,
> QmlTests::NewTabLandscapeView::test_switch_sections_by_keyboard() is reliably
> failing:
> 2: FAIL! :
> QmlTests::NewTabLandscapeView::test_switch_sections_by_keyboard() Compared
> values are not the same
> 2: Actual (): 0
> 2: Expected (): 1
> 2: Loc: [/home/osomon/dev/phablet/browser/webbrowser-
> app/tests/unittests/qml/tst_NewTabLandscapeView.qml(191)]

This is caused by a recent change in the UITK staging branch. I submitted a bug to track it: https://bugs.launchpad.net/ubuntu/+source/ubuntu-ui-toolkit/+bug/1481233

> Although not specified, there should probably be scrollbars for all the
> listviews.

Done

> Can you check with design whether we really want all the top sites section to
> not have a limit? I’d personally add a limit (maybe 10, or 20 top sites max).

James suggested trying with a limit of 10. This is implemented now.

> Can NewTabLandscapeView be renamed NewTabViewWide?

Done

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
1087. By Ugo Riboni

Implement a preliminary version of drag and drop support for reordering bookmarks between folders. Visual and UX design input missing so there are obvious placeholders.

1088. By Ugo Riboni

Merge changes from trunk

1089. By Ugo Riboni

Correctly honor draggable property

Revision history for this message
Olivier Tilloy (osomon) wrote :

Why is there a new "selectedIndexNewTabViewWide" setting? If, as I suspect, this is because the UX spec mandates that the state being retained, then it shouldn’t be a setting. Instead, the StateSaver should be used for that.

Favicons appear to be too large compared to the visual spec (hint: the Favicon component already has a built-in default size, you should probably not change it).

Folder names in bookmarks (left panel) shouldn’t be black when not selected, in the visual spec they appear to be darkGrey.

The spec doesn’t consider the case where a bookmark folder is empty. Can you check with design whether we should display some sort of informative message in this case, or if having an empty right panel is expected?

Can the failing unit test be temporarily skipped (http://doc.qt.io/qt-5/qml-qttest-testcase.html#skip-method) with a reference to bug #1481233 ?

If I swipe a bookmark to the right to delete it, the red delete action covers the left panel.

Bookmark dnd doesn’t seem to work here (I’m not seeing any icon appear when hovering over a bookmark). Might be due to me running a locally-built (and not installed) version of the UITK staging branch.

43 + Binding { target: newTabViewLoader.item; property: "focus"; value: newTabViewLoader.focus }
Is this really needed? A Loader is a FocusScope, so I would expect that always setting focus to true in the component being loaded would be enough to have focus handling just work.

Why was asynchronous loading removed from newTabViewLoader?

There’s now two strings for top sites: "Top Sites" and "Top sites". Can this be made consistent?

In bookmarks-folderlist-model.[h|cpp], I don’t think the count() method is necessary, you can simply define the getter for the count property to be rowCount(). And countChanged() doesn’t appear to ever be emitted, that seems wrong.

review: Needs Fixing
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Olivier Tilloy (osomon) wrote :

I am now seeing the DND icon when hovering over a bookmark, and I can drag it and drop it in another folder, but this doesn’t appear to actually move it.

review: Needs Fixing
1090. By Ugo Riboni

Fix incorrect item reference that prevented dropping bookmarks to work

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Olivier Tilloy (osomon) wrote :

In debian/control, the build dependency and runtime dependency of webbrowser-app on qtdeclarative5-ubuntu-ui-toolkit-plugin need to specify that they require a version >= 1.3.

review: Needs Fixing
1091. By Ugo Riboni

Use default size for Favicons in delegates

1092. By Ugo Riboni

Adjust folder color to match visual spec

1093. By Ugo Riboni

More fixes on the drag and drop

1094. By Ugo Riboni

Clip the lists to prevent the slide-to-delete element to cover folders

1095. By Ugo Riboni

Remove unnecessary binding for keyboard focus

1096. By Ugo Riboni

Remove async loading on the new tab view loader as it was removed by mistake by original author of the branch

1097. By Ugo Riboni

Fix case of "top sites" string to match the non-widescreen version

1098. By Ugo Riboni

More properly implement the count property of the folder list model

1099. By Ugo Riboni

Rename the settings key used to store the default section to something more clear

1100. By Ugo Riboni

Clip list items instead of lists, so that we can still drag the items without having to reparent them to the outer view

1101. By Ugo Riboni

Fix unit tests broken by previous change

1102. By Ugo Riboni

Skip test that would fail due to UITK bug

1103. By Ugo Riboni

Add a (currently failing) unit test for drag and drop, and fix a mistake in how the drag start event was being emitted

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1104. By Ugo Riboni

Reimplement the drag and drop test as autopilot tests

Revision history for this message
Ugo Riboni (uriboni) wrote :

All other items that are not specifically mentioned here should have been fixed or addressed.

> Why is there a new "selectedIndexNewTabViewWide" setting? If, as I suspect,
> this is because the UX spec mandates that the state being retained, then it
> shouldn’t be a setting. Instead, the StateSaver should be used for that.

It needs a setting because the StateSaver won't save the state when closing the app normally, and we want to remember in which section to open the view by default regardless of how the app was closed.

> The spec doesn’t consider the case where a bookmark folder is empty. Can you
> check with design whether we should display some sort of informative message
> in this case, or if having an empty right panel is expected?

I had already asked some days ago. They are working on it AFAIK.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Olivier Tilloy (osomon) wrote :

If I swipe a bookmark to the right to delete it, hovering over it still displays the grip that allows dragging it to a different folder (partially clipped by the window). I would expect this grip to be disabled/hidden while awaiting confirmation of whether to delete or not.

If I open a new tab, then open the history view (either from the drawer menu or with Ctrl+H), then close it, the sections header’s rendering is busted (the background color is drawn, but not the sections). It appears to be a focus issue, as it fixes itself if I press twice the down arrow key to focus the view again. This doesn’t happen with e.g. the settings view.

As pointed out in an earlier comment, in debian/control, the build dependency and runtime dependency of webbrowser-app on qtdeclarative5-ubuntu-ui-toolkit-plugin need to specify that they require a version >= 1.3.

When running the autopilot tests on my vivid desktop with version 1.3 of the toolkit, I need to modify line 295 of tests/autopilot/webbrowser_app/emulators/browser.py to make the tests pass: s/Icon11/Icon/. I was told by Brendan earlier today that this is a recent change in autopilot, can you apply it in this branch and verify that CI is happy with it?

Even with the above fixed, I’m seeing 3 errors when running the autopilot tests for test_new_tab_view on my desktop:
  webbrowser_app.tests.test_new_tab_view.TestNewTabViewContents.test_open_top_site
  webbrowser_app.tests.test_new_tab_view.TestNewTabViewContents.test_default_home_bookmark
  webbrowser_app.tests.test_new_tab_view.TestNewTabViewContents.test_open_bookmark

review: Needs Fixing
Revision history for this message
Olivier Tilloy (osomon) wrote :

Regarding drag and drop in unit tests: I just did a quick test, modifying test_drag() to do the following:

    function log_item_pos() { console.log("item.pos =", item.x, item.y) }
    log_item_pos()
    item.xChanged.connect(log_item_pos)
    item.yChanged.connect(log_item_pos)
    var c = centerOf(grip)
    mouseDrag(grip, c.x, c.y, -200, 100)

When running it, even though I’m not visualizing the item move, logging proves that it’s actually moving:

    qml: item.pos = 0 56
    qml: item.pos = -11 78
    qml: item.pos = -11 78
    qml: item.pos = -22 133
    qml: item.pos = -22 133
    qml: item.pos = -233 222
    qml: item.pos = -233 222
    qml: item.pos = 0 222
    qml: item.pos = 0 56

1105. By Ugo Riboni

Bump the UITK import version in debian/control

1106. By Ugo Riboni

Hide the dragging grip on bookmarks while the slide-to-delete action in progress

1107. By Ugo Riboni

Move some tests to the non-widescreen class only as the same tests are already implemented as unittests for the widescreen version and would fail in any case

1108. By Ugo Riboni

Fix a problem in how Icons are addressed in AP tests that was making some of them fail when using the uitk 1.3

1109. By Ugo Riboni

Prevent the Sections component to behave erratically when componets from 1.2 are imported while it is displayed. The real fix is to replace all imports to 1.3 but this suffices for now, while the work is being done in another branch.

Revision history for this message
Ugo Riboni (uriboni) wrote :

Fixed unless otherwise noted

> If I open a new tab, then open the history view (either from the drawer menu
> or with Ctrl+H), then close it, the sections header’s rendering is busted (the
> background color is drawn, but not the sections). It appears to be a focus
> issue, as it fixes itself if I press twice the down arrow key to focus the
> view again. This doesn’t happen with e.g. the settings view.

This is caused by the HistoryView importing Ubuntu.Components 1.2
According to the SDK team mixing imports seems to be not supported anymore. I fixed this only in HistoryView for now but the right thing to do would be to bump all imports to 1.3 to avoid other unexpected and hard to debug problems.

> When running the autopilot tests on my vivid desktop with version 1.3 of the
> toolkit, I need to modify line 295 of
> tests/autopilot/webbrowser_app/emulators/browser.py to make the tests pass:
> s/Icon11/Icon/. I was told by Brendan earlier today that this is a recent
> change in autopilot, can you apply it in this branch and verify that CI is
> happy with it?

Let's see what CI says.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1110. By Ugo Riboni

Merge changes from trunk

1111. By Ugo Riboni

Bump import to 2.4 in newly added unit test file

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Olivier Tilloy (osomon) wrote :

The 'inBookmarksView' property should be marked readonly.

Ctrl+Tab works to switch between sections, Tab doesn’t, even though there seems to be code for handling this (is it bug #1481233 ?).

If I cancel a drag (by dropping it somewhere it’s not accepted), it seems the bookmarks list’s interactivity is not restored (I cannot click and drag to move up/down the list).

review: Needs Fixing
1112. By Ugo Riboni

Merge changes from trunk

1113. By Ugo Riboni

Correctly mark a property as readonly

1114. By Ugo Riboni

Fix a bug preventing the interactivity in the boomarks list to be correctly restored at the end of a drag

Revision history for this message
Ugo Riboni (uriboni) wrote :

All fixed and yes, the problem with TAB is caused by bug #1481233

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1115. By Ugo Riboni

More fixes for correctly emitting the end of drag event

1116. By Ugo Riboni

Make it impossible to have keyboard focus within an empty list

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Olivier Tilloy (osomon) wrote :

I’m reliably getting 4 autopilot test failures on my desktop:

webbrowser_app.tests.test_private.TestPrivateView.test_url_showing_in_top_sites_in_and_out_private_mode
webbrowser_app.tests.test_bookmark_options.TestBookmarkOptions.test_save_bookmarked_url_in_new_folder
webbrowser_app.tests.test_bookmark_options.TestBookmarkOptions.test_save_bookmarked_url_in_existing_folder
webbrowser_app.tests.test_bookmark_options.TestBookmarkOptions.test_save_bookmarked_url_in_default_folder

review: Needs Fixing
1117. By Ugo Riboni

Fix some recent AP tests by smoothing away the differences between the wide and narrow new tab views via emulators and helper functions

1118. By Ugo Riboni

Remove method from main window emulator as it does not belong there

1119. By Ugo Riboni

Fix flake8

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Olivier Tilloy (osomon) wrote :

Still seeing 3 autopilot failures on desktop:

webbrowser_app.tests.test_bookmark_options.TestBookmarkOptions.test_save_bookmarked_url_in_existing_folder
webbrowser_app.tests.test_new_tab_view.TestNewTabViewContentsWide.test_remove_top_sites
webbrowser_app.tests.test_private.TestPrivateView.test_url_showing_in_top_sites_in_and_out_private_mode

review: Needs Fixing
1120. By Ugo Riboni

Refactor to fix a failing test

1121. By Ugo Riboni

Ensure correct section is always selected, not taking for granted the default

1122. By Ugo Riboni

More fixes for tests in narrow screen mode

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Olivier Tilloy (osomon) wrote :

This looks good now.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/control'
2--- debian/control 2015-08-11 11:18:36 +0000
3+++ debian/control 2015-08-12 13:42:27 +0000
4@@ -11,6 +11,7 @@
5 python3-all,
6 python3-flake8,
7 qml-module-qt-labs-folderlistmodel,
8+ qml-module-qt-labs-settings,
9 qml-module-qtquick2 (>= 5.4),
10 qml-module-qttest,
11 qt5-default,
12
13=== modified file 'src/app/webbrowser/Browser.qml'
14--- src/app/webbrowser/Browser.qml 2015-08-11 10:37:56 +0000
15+++ src/app/webbrowser/Browser.qml 2015-08-12 13:42:27 +0000
16@@ -119,12 +119,14 @@
17 property string searchEngine: settingsDefaults.searchEngine
18 property string allowOpenInBackgroundTab: settingsDefaults.allowOpenInBackgroundTab
19 property bool restoreSession: settingsDefaults.restoreSession
20+ property int newTabDefaultSection: settingsDefaults.newTabDefaultSection
21
22 function restoreDefaults() {
23 homepage = settingsDefaults.homepage
24 searchEngine = settingsDefaults.searchEngine
25 allowOpenInBackgroundTab = settingsDefaults.allowOpenInBackgroundTab
26 restoreSession = settingsDefaults.restoreSession
27+ newTabDefaultSection = settingsDefaults.newTabDefaultSection
28 }
29 }
30
31@@ -135,6 +137,7 @@
32 readonly property string searchEngine: "google"
33 readonly property string allowOpenInBackgroundTab: "default"
34 readonly property bool restoreSession: true
35+ readonly property int newTabDefaultSection: 0
36 }
37
38 FocusScope {
39@@ -219,6 +222,7 @@
40 }
41 }
42 active: false
43+ asynchronous: true
44
45 Connections {
46 target: browser
47@@ -230,35 +234,61 @@
48 }
49 }
50
51- sourceComponent: browser.incognito ? newPrivateTabViewComponent : newTabViewComponent
52+ sourceComponent: browser.incognito ? newPrivateTabView :
53+ (browser.wide ? newTabViewWide : newTabView)
54
55 Component {
56- id: newTabViewComponent
57+ id: newTabView
58
59 NewTabView {
60- historyModel: browser.historyModel
61- bookmarksModel: browser.bookmarksModel
62- settingsObject: settings
63- onBookmarkClicked: {
64- chrome.requestedUrl = url
65- currentWebview.url = url
66- tabContainer.forceActiveFocus()
67- }
68- onBookmarkRemoved: browser.bookmarksModel.remove(url)
69- onHistoryEntryClicked: {
70- chrome.requestedUrl = url
71- currentWebview.url = url
72- tabContainer.forceActiveFocus()
73- }
74- }
75- }
76-
77- Component {
78- id: newPrivateTabViewComponent
79-
80- NewPrivateTabView { }
81- }
82- asynchronous: true
83+ anchors.fill: parent
84+ historyModel: browser.historyModel
85+ bookmarksModel: browser.bookmarksModel
86+ settingsObject: settings
87+ focus: true
88+ onBookmarkClicked: {
89+ chrome.requestedUrl = url
90+ currentWebview.url = url
91+ tabContainer.forceActiveFocus()
92+ }
93+ onBookmarkRemoved: browser.bookmarksModel.remove(url)
94+ onHistoryEntryClicked: {
95+ chrome.requestedUrl = url
96+ currentWebview.url = url
97+ tabContainer.forceActiveFocus()
98+ }
99+ }
100+ }
101+
102+ Component {
103+ id: newTabViewWide
104+
105+ NewTabViewWide {
106+ anchors.fill: parent
107+ historyModel: browser.historyModel
108+ bookmarksModel: browser.bookmarksModel
109+ settingsObject: settings
110+ focus: true
111+ onBookmarkClicked: {
112+ chrome.requestedUrl = url
113+ currentWebview.url = url
114+ tabContainer.forceActiveFocus()
115+ }
116+ onBookmarkRemoved: browser.bookmarksModel.remove(url)
117+ onHistoryEntryClicked: {
118+ chrome.requestedUrl = url
119+ currentWebview.url = url
120+ tabContainer.forceActiveFocus()
121+ }
122+ onReleasingKeyboardFocus: chrome.focus = true
123+ }
124+ }
125+
126+ Component {
127+ id: newPrivateTabView
128+
129+ NewPrivateTabView { anchors.fill: parent }
130+ }
131 }
132
133 SearchEngine {
134@@ -391,7 +421,13 @@
135 canSimplifyText: !browser.wide
136 editing: activeFocus || suggestionsList.activeFocus
137
138- Keys.onDownPressed: if (suggestionsList.count) suggestionsList.focus = true
139+ Keys.onDownPressed: {
140+ if (suggestionsList.count) suggestionsList.focus = true
141+ else if (newTabViewLoader.status == Loader.Ready) {
142+ newTabViewLoader.focus = true
143+ }
144+ }
145+
146 Keys.onEscapePressed: {
147 if (chrome.findInPageMode) {
148 chrome.findInPageMode = false
149@@ -1134,7 +1170,7 @@
150 PopupUtils.open(bookmarkOptionsComponent,
151 chrome.bookmarkTogglePlaceHolder,
152 {"bookmarkUrl": url,
153- "bookmarkTitle": title})
154+ "bookmarkTitle": title})
155 }
156 }
157
158
159=== added file 'src/app/webbrowser/DraggableUrlDelegateWide.qml'
160--- src/app/webbrowser/DraggableUrlDelegateWide.qml 1970-01-01 00:00:00 +0000
161+++ src/app/webbrowser/DraggableUrlDelegateWide.qml 2015-08-12 13:42:27 +0000
162@@ -0,0 +1,98 @@
163+/*
164+ * Copyright 2015 Canonical Ltd.
165+ *
166+ * This file is part of webbrowser-app.
167+ *
168+ * webbrowser-app is free software; you can redistribute it and/or modify
169+ * it under the terms of the GNU General Public License as published by
170+ * the Free Software Foundation; version 3.
171+ *
172+ * webbrowser-app is distributed in the hope that it will be useful,
173+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
174+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
175+ * GNU General Public License for more details.
176+ *
177+ * You should have received a copy of the GNU General Public License
178+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
179+ */
180+
181+import QtQuick 2.4
182+import Ubuntu.Components 1.3
183+
184+UrlDelegateWide {
185+ id: item
186+
187+ z: Drag.active ? 1 : 0 // display on top of siblings while dragging
188+ Drag.active: gripArea.drag.active
189+ Drag.hotSpot.x: grip.x
190+ Drag.hotSpot.y: grip.y
191+ Drag.onActiveChanged: {
192+ if (item.Drag.active) {
193+ internal.positionBeforeDrag = Qt.point(x, y)
194+ item.dragStarted()
195+ }
196+ }
197+
198+ property bool draggable: true
199+ property int gripMargin: units.gu(1)
200+ signal dragStarted()
201+ signal dragEnded(var dragAndDrop)
202+
203+ // only monitors hover events without capturing any click or drag
204+ MouseArea {
205+ id: hoverArea
206+ anchors.fill: parent
207+ acceptedButtons: Qt.NoButton
208+ hoverEnabled: true
209+ }
210+
211+ Icon {
212+ id: grip
213+ objectName: "dragGrip"
214+
215+ anchors.verticalCenter: parent.verticalCenter
216+ anchors.right: parent.right
217+ anchors.rightMargin: item.gripMargin
218+
219+ width: units.gu(3)
220+ height: width
221+ name: "view-grid-symbolic"
222+
223+ opacity: item.draggable && hoverArea.containsMouse ? 1.0 : 0.0
224+ Behavior on opacity {
225+ NumberAnimation {
226+ duration: UbuntuAnimation.SnapDuration
227+ easing: UbuntuAnimation.StandardEasing
228+ }
229+ }
230+
231+ MouseArea {
232+ id: gripArea
233+ anchors.fill: parent
234+ drag.target: item.draggable ? item : null
235+ onReleased: {
236+ var result = { success: false, target: item.Drag.target }
237+ item.dragEnded(result)
238+ if (result.success) item.Drag.drop()
239+ else {
240+ item.x = internal.positionBeforeDrag.x
241+ item.y = internal.positionBeforeDrag.y
242+ item.Drag.cancel()
243+ }
244+ }
245+ }
246+ }
247+
248+ Rectangle {
249+ anchors.fill: parent
250+ color: "transparent"
251+ border.color: UbuntuColors.lightGrey
252+ border.width: 1
253+ visible: item.Drag.active
254+ }
255+
256+ QtObject {
257+ id: internal
258+ property point positionBeforeDrag
259+ }
260+}
261
262=== added file 'src/app/webbrowser/NewTabViewWide.qml'
263--- src/app/webbrowser/NewTabViewWide.qml 1970-01-01 00:00:00 +0000
264+++ src/app/webbrowser/NewTabViewWide.qml 2015-08-12 13:42:27 +0000
265@@ -0,0 +1,317 @@
266+/*
267+ * Copyright 2015 Canonical Ltd.
268+ *
269+ * This file is part of webbrowser-app.
270+ *
271+ * webbrowser-app is free software; you can redistribute it and/or modify
272+ * it under the terms of the GNU General Public License as published by
273+ * the Free Software Foundation; version 3.
274+ *
275+ * webbrowser-app is distributed in the hope that it will be useful,
276+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
277+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
278+ * GNU General Public License for more details.
279+ *
280+ * You should have received a copy of the GNU General Public License
281+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
282+ */
283+
284+import QtQuick 2.4
285+import Qt.labs.settings 1.0
286+import Ubuntu.Components 1.3
287+import webbrowserapp.private 0.1
288+import ".."
289+
290+FocusScope {
291+ id: newTabViewWide
292+
293+ property QtObject bookmarksModel
294+ property alias historyModel: historyTimeframeModel.sourceModel
295+ property QtObject settingsObject
296+ property alias selectedIndex: sections.selectedIndex
297+ readonly property bool inBookmarksView: newTabViewWide.selectedIndex === 1
298+
299+ signal bookmarkClicked(url url)
300+ signal bookmarkRemoved(url url)
301+ signal historyEntryClicked(url url)
302+ signal releasingKeyboardFocus()
303+
304+ Keys.onTabPressed: selectedIndex = (selectedIndex + 1) % 2
305+ Keys.onBacktabPressed: selectedIndex = Math.abs((selectedIndex - 1) % 2)
306+ onActiveFocusChanged: {
307+ if (activeFocus) {
308+ if (inBookmarksView) {
309+ if (sections.lastFocusedBookmarksColumn === bookmarksList &&
310+ bookmarksList.model.length === 0) {
311+ sections.lastFocusedBookmarksColumn = folders
312+ }
313+ sections.lastFocusedBookmarksColumn.focus = true
314+ }
315+ else topSitesList.focus = true
316+ }
317+ }
318+
319+ LimitProxyModel {
320+ id: topSitesModel
321+ limit: 10
322+ sourceModel: TopSitesModel {
323+ sourceModel: HistoryTimeframeModel {
324+ id: historyTimeframeModel
325+ }
326+ }
327+ }
328+
329+ Rectangle {
330+ anchors.fill: parent
331+ color: "#fbfbfb"
332+ }
333+
334+ ListView {
335+ id: folders
336+ objectName: "foldersList"
337+ visible: inBookmarksView
338+
339+ Keys.onRightPressed: if (bookmarksList.model.length > 0) bookmarksList.focus = true
340+ Keys.onDownPressed: currentIndex = Math.min(currentIndex + 1, folders.model.count - 1)
341+ Keys.onUpPressed: {
342+ if (currentIndex > 0) currentIndex = Math.max(currentIndex - 1, 0)
343+ else newTabViewWide.releasingKeyboardFocus()
344+ }
345+ onActiveFocusChanged: {
346+ if (activeFocus) {
347+ sections.lastFocusedBookmarksColumn = folders
348+ if (currentIndex < 0) currentIndex = 0
349+ }
350+ }
351+
352+ anchors {
353+ top: sectionsGroup.bottom
354+ bottom: parent.bottom
355+ left: parent.left
356+ topMargin: units.gu(2)
357+ }
358+ width: units.gu(25)
359+
360+ currentIndex: 0
361+ model: BookmarksFolderListModel {
362+ sourceModel: newTabViewWide.bookmarksModel
363+ }
364+
365+ delegate: ListItem {
366+ id: folderItem
367+ objectName: "folderItem"
368+ property var model: entries
369+ property bool isActiveFolder: ListView.isCurrentItem
370+ property bool isCurrentItem: ListView.isCurrentItem
371+ property bool isAllBookmarksFolder: folder.length === 0
372+ property alias name: dropArea.folderName
373+ divider.visible: false
374+
375+ property bool isCurrentDropTarget: dropArea.containsDrag && dropArea.drag.source.folder !== folder
376+ color: isCurrentDropTarget ? "green" :
377+ ((folders.activeFocus && isActiveFolder) ? Qt.rgba(0, 0, 0, 0.05) : "transparent")
378+
379+ Label {
380+ anchors.verticalCenter: parent.verticalCenter
381+ anchors.left: parent.left
382+ anchors.right: parent.right
383+ anchors.leftMargin: units.gu(2)
384+ anchors.rightMargin: units.gu(2)
385+
386+ fontSize: isAllBookmarksFolder ? "medium" : "small"
387+ text: isAllBookmarksFolder ? i18n.tr("All Bookmarks") : folderItem.name
388+ color: isActiveFolder ? UbuntuColors.orange : UbuntuColors.darkGrey
389+ }
390+
391+ onClicked: folders.currentIndex = index
392+
393+ DropArea {
394+ id: dropArea
395+ anchors.fill: parent
396+ property string folderName: folder
397+ }
398+ }
399+ }
400+
401+ Scrollbar {
402+ flickableItem: folders
403+ }
404+
405+ ListView {
406+ id: bookmarksList
407+ objectName: "bookmarksList"
408+ anchors {
409+ top: sectionsGroup.bottom
410+ bottom: parent.bottom
411+ left: folders.right
412+ right: parent.right
413+ topMargin: units.gu(2)
414+ }
415+ visible: inBookmarksView
416+ onActiveFocusChanged: if (activeFocus) sections.lastFocusedBookmarksColumn = bookmarksList
417+
418+ // Build a temporary model for the bookmarks list that includes, when
419+ // necessary, the homepage bookmark as a fixed first item in the list
420+ model: {
421+ if (!folders.currentItem) return null
422+
423+ var items = []
424+ if (folders.currentItem.isAllBookmarksFolder) items.push({
425+ title: i18n.tr("Homepage"),
426+ url: newTabViewWide.settingsObject.homepage,
427+ folder: ""
428+ })
429+
430+ if (!folders.currentItem.model) return null
431+ for (var i = 0; i < folders.currentItem.model.count; i++) {
432+ items.push(folders.currentItem.model.get(i))
433+ }
434+ return items
435+ }
436+
437+ currentIndex: 0
438+
439+ delegate: DraggableUrlDelegateWide {
440+ objectName: "bookmarkItem"
441+ clip: true
442+
443+ title: modelData.title
444+ icon: modelData.icon ? modelData.icon : ""
445+ url: modelData.url
446+
447+ property string folder: modelData.folder
448+ property bool isHomeBookmark: folder === "" && index === 0
449+
450+ removable: !isHomeBookmark
451+ draggable: !isHomeBookmark && contentItem.x === 0
452+ highlighted: bookmarksList.activeFocus && ListView.isCurrentItem
453+
454+ onClicked: newTabViewWide.bookmarkClicked(url)
455+ onRemoved: newTabViewWide.bookmarkRemoved(url)
456+
457+ // Larger margin to prevent interference from Scrollbar hovering area
458+ gripMargin: units.gu(4)
459+ onDragStarted: {
460+ // Remove interactivity to prevent the list from scrolling
461+ // while dragging near its margins. This ensures we can correctly
462+ // return the item to its original position on a failed drop.
463+ bookmarksList.interactive = false
464+
465+ // Relinquish focus as the presses and releases that compose the
466+ // drag will move the keyboard focus in a location unexpected
467+ // for the user. This way it will go back to the address bar and
468+ // the user can predictably resume keyboard interaction from there.
469+ newTabViewWide.releasingKeyboardFocus()
470+ }
471+ onDragEnded: {
472+ bookmarksList.interactive = true
473+
474+ if (dragAndDrop.target && dragAndDrop.target.folderName !== folder) {
475+ bookmarksModel.update(modelData.url, modelData.title,
476+ dragAndDrop.target.folderName)
477+ dragAndDrop.success = true
478+ }
479+ }
480+ }
481+
482+ Keys.onReturnPressed: newTabViewWide.bookmarkClicked(currentItem.url)
483+ Keys.onDeletePressed: {
484+ if (currentItem.removable) {
485+ newTabViewWide.bookmarkRemoved(currentItem.url)
486+ if (bookmarksList.model.length === 0) folders.focus = true
487+ }
488+ }
489+ Keys.onLeftPressed: folders.focus = true
490+ Keys.onDownPressed: currentIndex = Math.min(currentIndex + 1, model.length - 1)
491+ Keys.onUpPressed: {
492+ if (currentIndex > 0) currentIndex = Math.max(currentIndex - 1, 0)
493+ else newTabViewWide.releasingKeyboardFocus()
494+ }
495+ }
496+
497+ Scrollbar {
498+ flickableItem: bookmarksList
499+ }
500+
501+ ListView {
502+ id: topSitesList
503+ objectName: "topSitesList"
504+ anchors {
505+ top: sectionsGroup.bottom
506+ bottom: parent.bottom
507+ left: parent.left
508+ right: parent.right
509+ topMargin: units.gu(2)
510+ }
511+
512+ visible: !inBookmarksView
513+ currentIndex: 0
514+
515+ model: topSitesModel
516+ delegate: UrlDelegateWide {
517+ objectName: "topSiteItem"
518+ clip: true
519+
520+ title: model.title
521+ icon: model.icon
522+ url: model.url
523+ highlighted: topSitesList.activeFocus && ListView.isCurrentItem
524+
525+ onClicked: newTabViewWide.historyEntryClicked(url)
526+ onRemoved: newTabViewWide.historyModel.hide(url)
527+ }
528+
529+ Keys.onReturnPressed: newTabViewWide.historyEntryClicked(currentItem.url)
530+ Keys.onDeletePressed: {
531+ newTabViewWide.historyModel.hide(currentItem.url)
532+ if (topSitesList.model.count === 0) newTabViewWide.releasingKeyboardFocus()
533+ }
534+ Keys.onDownPressed: currentIndex = Math.min(currentIndex + 1, model.count - 1)
535+ Keys.onUpPressed: {
536+ if (currentIndex > 0) currentIndex = Math.max(currentIndex - 1, 0)
537+ else newTabViewWide.releasingKeyboardFocus()
538+ }
539+ }
540+
541+ Scrollbar {
542+ flickableItem: topSitesList
543+ }
544+
545+ Rectangle {
546+ id: sectionsGroup
547+ anchors {
548+ top: parent.top
549+ left: parent.left
550+ right: parent.right
551+ }
552+ color: "#dedede"
553+ height: sections.height
554+
555+ Sections {
556+ id: sections
557+ objectName: "sections"
558+ anchors {
559+ left: parent.left
560+ top: parent.top
561+ leftMargin: units.gu(1)
562+ }
563+
564+ selectedIndex: settingsObject.newTabDefaultSection
565+ onSelectedIndexChanged: {
566+ settingsObject.newTabDefaultSection = selectedIndex
567+ if (selectedIndex === 0) topSitesList.focus = true
568+ else {
569+ if (lastFocusedBookmarksColumn) lastFocusedBookmarksColumn.focus = true
570+ else folders.focus = true
571+ }
572+
573+ }
574+ property var lastFocusedBookmarksColumn: folders
575+
576+ actions: [
577+ Action { text: i18n.tr("Top sites") },
578+ Action { text: i18n.tr("Bookmarks") }
579+ ]
580+ }
581+ }
582+}
583
584=== added file 'src/app/webbrowser/UrlDelegateWide.qml'
585--- src/app/webbrowser/UrlDelegateWide.qml 1970-01-01 00:00:00 +0000
586+++ src/app/webbrowser/UrlDelegateWide.qml 2015-08-12 13:42:27 +0000
587@@ -0,0 +1,86 @@
588+/*
589+ * Copyright 2015 Canonical Ltd.
590+ *
591+ * This file is part of webbrowser-app.
592+ *
593+ * webbrowser-app is free software; you can redistribute it and/or modify
594+ * it under the terms of the GNU General Public License as published by
595+ * the Free Software Foundation; version 3.
596+ *
597+ * webbrowser-app is distributed in the hope that it will be useful,
598+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
599+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
600+ * GNU General Public License for more details.
601+ *
602+ * You should have received a copy of the GNU General Public License
603+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
604+ */
605+
606+import QtQuick 2.4
607+import Ubuntu.Components 1.3
608+import ".."
609+
610+ListItem {
611+ id: urlDelegate
612+
613+ property alias icon: icon.source
614+ property alias title: title.text
615+ property alias url: url.text
616+ property bool highlighted: false
617+ property bool removable: true
618+
619+ color: highlighted ? Qt.rgba(0, 0, 0, 0.05) : "transparent"
620+
621+ divider.visible: false
622+ height: units.gu(7)
623+
624+ signal removed()
625+
626+ Favicon {
627+ id: icon
628+ anchors {
629+ verticalCenter: parent.verticalCenter
630+ left: parent.left
631+ leftMargin: units.gu(1.5)
632+ }
633+ }
634+
635+ Column {
636+ width: parent.width - icon.width - parent.spacing
637+ anchors {
638+ left: icon.right
639+ leftMargin: units.gu(1)
640+ verticalCenter: parent.verticalCenter
641+ }
642+
643+ Label {
644+ id: title
645+
646+ fontSize: "small"
647+ color: highlighted ? UbuntuColors.orange : UbuntuColors.darkGrey
648+ wrapMode: Text.Wrap
649+ elide: Text.ElideRight
650+ maximumLineCount: 1
651+ }
652+
653+ Label {
654+ id: url
655+
656+ fontSize: "small"
657+ color: highlighted ? UbuntuColors.orange : UbuntuColors.darkGrey
658+ wrapMode: Text.Wrap
659+ elide: Text.ElideRight
660+ maximumLineCount: 1
661+ }
662+ }
663+
664+ property var _deleteAction: Action {
665+ objectName: "leadingAction.delete"
666+ iconName: "delete"
667+ onTriggered: urlDelegate.removed()
668+ }
669+
670+ leadingActions: ListItemActions {
671+ actions: removable ? [_deleteAction] : []
672+ }
673+}
674
675=== modified file 'src/app/webbrowser/bookmarks-folder-model.cpp'
676--- src/app/webbrowser/bookmarks-folder-model.cpp 2015-06-17 02:17:45 +0000
677+++ src/app/webbrowser/bookmarks-folder-model.cpp 2015-08-12 13:42:27 +0000
678@@ -34,7 +34,7 @@
679 with the same name that the filter folder name (case-sensitive
680 comparison).
681
682- When no folder name is set (null or empty string), all entries that
683+ When no folder name is set (null or empty string), all entries that
684 are not stored in any folder match.
685 */
686 BookmarksFolderModel::BookmarksFolderModel(QObject* parent)
687@@ -76,6 +76,26 @@
688 return rowCount();
689 }
690
691+QVariantMap BookmarksFolderModel::get(int row) const
692+{
693+ if (row < 0 || row >= rowCount()) {
694+ return QVariantMap();
695+ }
696+
697+ QVariantMap res;
698+ QHash<int,QByteArray> names = roleNames();
699+ QHashIterator<int, QByteArray> i(names);
700+
701+ while (i.hasNext()) {
702+ i.next();
703+ QModelIndex idx = index(row, 0);
704+ QVariant data = idx.data(i.key());
705+ res[i.value()] = data;
706+ }
707+
708+ return res;
709+}
710+
711 bool BookmarksFolderModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const
712 {
713 QModelIndex index = sourceModel()->index(source_row, 0, source_parent);
714
715=== modified file 'src/app/webbrowser/bookmarks-folder-model.h'
716--- src/app/webbrowser/bookmarks-folder-model.h 2015-06-17 02:17:45 +0000
717+++ src/app/webbrowser/bookmarks-folder-model.h 2015-08-12 13:42:27 +0000
718@@ -43,6 +43,7 @@
719 void setFolder(const QString& domain);
720
721 int count() const;
722+ Q_INVOKABLE QVariantMap get(int row) const;
723
724 Q_SIGNALS:
725 void sourceModelChanged() const;
726
727=== modified file 'src/app/webbrowser/bookmarks-folderlist-model.cpp'
728--- src/app/webbrowser/bookmarks-folderlist-model.cpp 2015-07-01 01:23:07 +0000
729+++ src/app/webbrowser/bookmarks-folderlist-model.cpp 2015-08-12 13:42:27 +0000
730@@ -99,6 +99,7 @@
731 }
732 endResetModel();
733 Q_EMIT sourceModelChanged();
734+ Q_EMIT countChanged();
735 }
736 }
737
738@@ -174,6 +175,8 @@
739 beginInsertRows(QModelIndex(), insertAt, insertAt);
740 addFolder(folder);
741 endInsertRows();
742+
743+ Q_EMIT countChanged();
744 }
745 }
746
747@@ -183,6 +186,8 @@
748 clearFolders();
749 populateModel();
750 endResetModel();
751+
752+ Q_EMIT countChanged();
753 }
754
755 void BookmarksFolderListModel::addFolder(const QString& folder)
756
757=== modified file 'src/app/webbrowser/bookmarks-folderlist-model.h'
758--- src/app/webbrowser/bookmarks-folderlist-model.h 2015-06-30 21:09:20 +0000
759+++ src/app/webbrowser/bookmarks-folderlist-model.h 2015-08-12 13:42:27 +0000
760@@ -32,6 +32,7 @@
761 Q_OBJECT
762
763 Q_PROPERTY(BookmarksModel* sourceModel READ sourceModel WRITE setSourceModel NOTIFY sourceModelChanged)
764+ Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
765
766 Q_ENUMS(Roles)
767
768@@ -58,6 +59,7 @@
769
770 Q_SIGNALS:
771 void sourceModelChanged() const;
772+ void countChanged() const;
773
774 private Q_SLOTS:
775 void onFolderAdded(const QString& folder);
776
777=== modified file 'tests/autopilot/webbrowser_app/emulators/browser.py'
778--- tests/autopilot/webbrowser_app/emulators/browser.py 2015-08-11 10:37:56 +0000
779+++ tests/autopilot/webbrowser_app/emulators/browser.py 2015-08-12 13:42:27 +0000
780@@ -130,7 +130,10 @@
781 state="shown")
782
783 def get_new_tab_view(self):
784- return self.wait_select_single("NewTabView", visible=True)
785+ if self.wide:
786+ return self.wait_select_single("NewTabViewWide", visible=True)
787+ else:
788+ return self.wait_select_single("NewTabView", visible=True)
789
790 # Since the NewPrivateTabView does not define any new QML property in its
791 # extended file, it does not report itself to autopilot with the same name
792@@ -166,9 +169,6 @@
793 except exceptions.StateNotFoundError:
794 return None
795
796- def get_bookmarks_folder_list_view(self):
797- return self.select_single(BookmarksFolderListView)
798-
799 def press_key(self, key):
800 self.keyboard.press_and_release(key)
801
802@@ -442,6 +442,68 @@
803 def get_notopsites_label(self):
804 return self.select_single("Label", objectName="notopsites")
805
806+ def get_top_site_items(self):
807+ return self.get_top_sites_list().get_delegates()
808+
809+ def get_bookmarks_folder_list_view(self):
810+ return self.select_single(BookmarksFolderListView)
811+
812+ def get_bookmarks(self, folder_name):
813+ # assumes that the "more" button has been clicked
814+ folders = self.get_bookmarks_folder_list_view()
815+ folder_delegate = folders.get_folder_delegate(folder_name)
816+ return folders.get_urls_from_folder(folder_delegate)
817+
818+ def get_folder_names(self):
819+ folders = self.get_bookmarks_folder_list_view().get_delegates()
820+ return [folder.folderName for folder in folders]
821+
822+
823+class NewTabViewWide(uitk.UbuntuUIToolkitCustomProxyObjectBase):
824+
825+ def go_to_section(self, section_index):
826+ sections = self.select_single(uitk.Sections)
827+ if not sections.selectedIndex == section_index:
828+ sections.click_section_button(section_index)
829+
830+ def get_bookmarks_list(self):
831+ self.go_to_section(1)
832+ list = self.select_single(uitk.QQuickListView,
833+ objectName="bookmarksList")
834+ return sorted(list.select_many("DraggableUrlDelegateWide",
835+ objectName="bookmarkItem"),
836+ key=lambda delegate: delegate.globalRect.y)
837+
838+ def get_top_sites_list(self):
839+ self.go_to_section(0)
840+ list = self.select_single(uitk.QQuickListView,
841+ objectName="topSitesList")
842+ return sorted(list.select_many("UrlDelegateWide",
843+ objectName="topSiteItem"),
844+ key=lambda delegate: delegate.globalRect.y)
845+
846+ def get_folders_list(self):
847+ self.go_to_section(1)
848+ list = self.select_single(uitk.QQuickListView,
849+ objectName="foldersList")
850+ return sorted(list.select_many(objectName="folderItem"),
851+ key=lambda delegate: delegate.globalRect.y)
852+
853+ def get_top_site_items(self):
854+ self.go_to_section(0)
855+ return self.get_top_sites_list()
856+
857+ def get_bookmarks(self, folder_name):
858+ folders = self.get_folders_list()
859+ matches = [folder for folder in folders if folder.name == folder_name]
860+ if not len(matches) == 1:
861+ return []
862+ self.pointing_device.click_object(matches[0])
863+ return self.get_bookmarks_list()
864+
865+ def get_folder_names(self):
866+ return [folder.name for folder in self.get_folders_list()]
867+
868
869 class UrlsList(uitk.UbuntuUIToolkitCustomProxyObjectBase):
870
871@@ -458,6 +520,17 @@
872 pass
873
874
875+class UrlDelegateWide(uitk.UCListItem):
876+
877+ pass
878+
879+
880+class DraggableUrlDelegateWide(UrlDelegateWide):
881+
882+ def get_grip(self):
883+ return self.select_single("Icon", objectName="dragGrip")
884+
885+
886 class BookmarkOptions(uitk.UbuntuUIToolkitCustomProxyObjectBase):
887
888 def get_title_text_field(self):
889
890=== modified file 'tests/autopilot/webbrowser_app/tests/__init__.py'
891--- tests/autopilot/webbrowser_app/tests/__init__.py 2015-07-09 20:26:53 +0000
892+++ tests/autopilot/webbrowser_app/tests/__init__.py 2015-08-12 13:42:27 +0000
893@@ -143,7 +143,7 @@
894 time.sleep(1)
895 return tabs_view
896
897- def open_new_tab(self):
898+ def open_new_tab(self, open_tabs_view=False, expand_view=False):
899 if (self.main_window.incognito):
900 count = len(self.main_window.get_incognito_webviews())
901 else:
902@@ -152,7 +152,8 @@
903 if self.main_window.wide:
904 self.main_window.chrome.get_tabs_bar().click_new_tab_button()
905 else:
906- # assumes the tabs view is already open
907+ if open_tabs_view:
908+ self.open_tabs_view()
909 tabs_view = self.main_window.get_tabs_view()
910 toolbar = self.main_window.get_recent_view_toolbar()
911 toolbar.click_action("newTabButton")
912@@ -175,6 +176,11 @@
913 self.main_window.address_bar.activeFocus,
914 Eventually(Equals(True)))
915
916+ if not self.main_window.wide and expand_view:
917+ more_button = new_tab_view.get_bookmarks_more_button()
918+ self.assertThat(more_button.visible, Equals(True))
919+ self.pointing_device.click_object(more_button)
920+
921 return new_tab_view
922
923 def open_settings(self):
924
925=== modified file 'tests/autopilot/webbrowser_app/tests/test_addressbar_bookmark.py'
926--- tests/autopilot/webbrowser_app/tests/test_addressbar_bookmark.py 2015-07-03 15:06:08 +0000
927+++ tests/autopilot/webbrowser_app/tests/test_addressbar_bookmark.py 2015-08-12 13:42:27 +0000
928@@ -32,9 +32,7 @@
929 bookmark_options.wait_until_destroyed()
930 self.assertThat(chrome.bookmarked, Eventually(Equals(True)))
931
932- if not self.main_window.wide:
933- self.open_tabs_view()
934- self.open_new_tab()
935+ self.open_new_tab(open_tabs_view=True)
936 url = self.base_url + "/test2"
937 self.main_window.go_to_url(url)
938 self.main_window.wait_until_page_loaded(url)
939@@ -57,9 +55,7 @@
940 self.assertThat(chrome.bookmarked, Eventually(Equals(False)))
941
942 def test_cannot_bookmark_empty_page(self):
943- if not self.main_window.wide:
944- self.open_tabs_view()
945- self.open_new_tab()
946+ self.open_new_tab(open_tabs_view=True)
947
948 if self.main_window.wide:
949 self.main_window.chrome.get_tabs_bar().select_tab(0)
950
951=== modified file 'tests/autopilot/webbrowser_app/tests/test_bookmark_options.py'
952--- tests/autopilot/webbrowser_app/tests/test_bookmark_options.py 2015-07-09 14:01:15 +0000
953+++ tests/autopilot/webbrowser_app/tests/test_bookmark_options.py 2015-08-12 13:42:27 +0000
954@@ -86,27 +86,24 @@
955 connection.commit()
956 connection.close()
957
958- def _get_bookmarks_folders_list_view(self):
959- if not self.main_window.wide:
960- self.open_tabs_view()
961- new_tab_view = self.open_new_tab()
962- more_button = new_tab_view.get_bookmarks_more_button()
963- self.assertThat(more_button.visible, Equals(True))
964- self.pointing_device.click_object(more_button)
965- return self.main_window.get_bookmarks_folder_list_view()
966-
967 def _get_bookmark_options(self):
968 address_bar = self.main_window.address_bar
969 bookmark_toggle = address_bar.get_bookmark_toggle()
970 self.pointing_device.click_object(bookmark_toggle)
971 return self.main_window.get_bookmark_options()
972
973+ def _assert_bookmark_count_in_folder(self, tab, folder_name, count):
974+ # in wide mode the list of urls in the default folder has the homepage
975+ # bookmark in it, but it does not in narrow mode
976+ if self.main_window.wide and folder_name == "":
977+ count += 1
978+
979+ urls = tab.get_bookmarks(folder_name)
980+ self.assertThat(lambda: len(urls), Eventually(Equals(count)))
981+
982 def test_save_bookmarked_url_in_default_folder(self):
983- folders = self._get_bookmarks_folders_list_view()
984- folder_delegate = folders.get_folder_delegate("")
985- self.assertThat(lambda: len(folders.get_urls_from_folder(
986- folder_delegate)),
987- Eventually(Equals(4)))
988+ new_tab = self.open_new_tab(open_tabs_view=True, expand_view=True)
989+ self._assert_bookmark_count_in_folder(new_tab, "", 4)
990
991 url = self.base_url + "/test2"
992 self.main_window.go_to_url(url)
993@@ -121,20 +118,14 @@
994
995 self.assertThat(chrome.bookmarked, Eventually(Equals(True)))
996
997- folders = self._get_bookmarks_folders_list_view()
998- folder_delegate = folders.get_folder_delegate("")
999- self.assertThat(lambda: len(folders.get_urls_from_folder(
1000- folder_delegate)),
1001- Eventually(Equals(5)))
1002+ new_tab = self.open_new_tab(open_tabs_view=True, expand_view=True)
1003+ self._assert_bookmark_count_in_folder(new_tab, "", 5)
1004
1005 def test_save_bookmarked_url_in_existing_folder(self):
1006- folders = self._get_bookmarks_folders_list_view()
1007- self.assertThat(lambda: len(folders.get_delegates()),
1008+ new_tab = self.open_new_tab(open_tabs_view=True, expand_view=True)
1009+ self.assertThat(lambda: len(new_tab.get_folder_names()),
1010 Eventually(Equals(3)))
1011- folder_delegate = folders.get_folder_delegate("Actinide")
1012- self.assertThat(lambda: len(folders.get_urls_from_folder(
1013- folder_delegate)),
1014- Eventually(Equals(1)))
1015+ self._assert_bookmark_count_in_folder(new_tab, "Actinide", 1)
1016
1017 url = self.base_url + "/test2"
1018 self.main_window.go_to_url(url)
1019@@ -158,17 +149,14 @@
1020
1021 self.assertThat(chrome.bookmarked, Eventually(Equals(True)))
1022
1023- folders = self._get_bookmarks_folders_list_view()
1024- self.assertThat(lambda: len(folders.get_delegates()),
1025+ new_tab = self.open_new_tab(open_tabs_view=True, expand_view=True)
1026+ self.assertThat(lambda: len(new_tab.get_folder_names()),
1027 Eventually(Equals(3)))
1028- folder_delegate = folders.get_folder_delegate("Actinide")
1029- self.assertThat(lambda: len(folders.get_urls_from_folder(
1030- folder_delegate)),
1031- Eventually(Equals(2)))
1032+ self._assert_bookmark_count_in_folder(new_tab, "Actinide", 2)
1033
1034 def test_save_bookmarked_url_in_new_folder(self):
1035- folders = self._get_bookmarks_folders_list_view()
1036- self.assertThat(lambda: len(folders.get_delegates()),
1037+ new_tab = self.open_new_tab(open_tabs_view=True, expand_view=True)
1038+ self.assertThat(lambda: len(new_tab.get_folder_names()),
1039 Eventually(Equals(3)))
1040
1041 url = self.base_url + "/test2"
1042@@ -205,13 +193,10 @@
1043
1044 self.assertThat(chrome.bookmarked, Eventually(Equals(True)))
1045
1046- folders = self._get_bookmarks_folders_list_view()
1047- self.assertThat(lambda: len(folders.get_delegates()),
1048+ new_tab = self.open_new_tab(open_tabs_view=True, expand_view=True)
1049+ self.assertThat(lambda: len(new_tab.get_folder_names()),
1050 Eventually(Equals(4)))
1051- folder_delegate = folders.get_folder_delegate("NewFolder")
1052- self.assertThat(lambda: len(folders.get_urls_from_folder(
1053- folder_delegate)),
1054- Eventually(Equals(1)))
1055+ self._assert_bookmark_count_in_folder(new_tab, "NewFolder", 1)
1056
1057 @testtools.skip("Temporarily skipped until popover going out of view with"
1058 " OSK is fixed http://pad.lv/1466222")
1059@@ -235,10 +220,11 @@
1060
1061 self.assertThat(chrome.bookmarked, Eventually(Equals(True)))
1062
1063- folders = self._get_bookmarks_folders_list_view()
1064- folder_delegate = folders.get_folder_delegate("")
1065- self.assertThat(lambda: len(folders.get_urls_from_folder(
1066- folder_delegate)),
1067- Eventually(Equals(5)))
1068- delegate = folders.get_urls_from_folder(folder_delegate)[0]
1069- self.assertThat(delegate.title, Equals("NewTitle"))
1070+ new_tab = self.open_new_tab(open_tabs_view=True, expand_view=True)
1071+ self._assert_bookmark_count_in_folder(new_tab, "", 5)
1072+
1073+ index = 0
1074+ if self.main_view.wide:
1075+ index += 1
1076+ bookmark = new_tab.get_bookmarks("")[index]
1077+ self.assertThat(bookmark.title, Equals("NewTitle"))
1078
1079=== modified file 'tests/autopilot/webbrowser_app/tests/test_findinpage.py'
1080--- tests/autopilot/webbrowser_app/tests/test_findinpage.py 2015-08-11 11:16:52 +0000
1081+++ tests/autopilot/webbrowser_app/tests/test_findinpage.py 2015-08-12 13:42:27 +0000
1082@@ -140,8 +140,7 @@
1083 # (that would otherwise prevent a bottom edge swipe gesture)
1084 webview = self.main_window.get_current_webview()
1085 self.pointing_device.click_object(webview)
1086- self.open_tabs_view()
1087- self.open_new_tab()
1088+ self.open_new_tab(open_tabs_view=True)
1089 self.assertThat(bar.findInPageMode, Eventually(Equals(False)))
1090
1091 def test_navigation_in_new_tab_exits_findinpage_mode(self):
1092
1093=== modified file 'tests/autopilot/webbrowser_app/tests/test_new_tab_view.py'
1094--- tests/autopilot/webbrowser_app/tests/test_new_tab_view.py 2015-07-03 15:06:08 +0000
1095+++ tests/autopilot/webbrowser_app/tests/test_new_tab_view.py 2015-08-12 13:42:27 +0000
1096@@ -26,20 +26,18 @@
1097
1098 from webbrowser_app.tests import StartOpenRemotePageTestCaseBase
1099
1100+from ubuntuuitoolkit import ToolkitException
1101+
1102
1103 class TestNewTabViewLifetime(StartOpenRemotePageTestCaseBase):
1104
1105 def test_new_tab_view_destroyed_when_browsing(self):
1106- if not self.main_window.wide:
1107- self.open_tabs_view()
1108- new_tab_view = self.open_new_tab()
1109+ new_tab_view = self.open_new_tab(open_tabs_view=True)
1110 self.main_window.go_to_url(self.base_url + "/test2")
1111 new_tab_view.wait_until_destroyed()
1112
1113 def test_new_tab_view_destroyed_when_closing_tab(self):
1114- if not self.main_window.wide:
1115- self.open_tabs_view()
1116- new_tab_view = self.open_new_tab()
1117+ new_tab_view = self.open_new_tab(open_tabs_view=True)
1118 if self.main_window.wide:
1119 self.main_window.chrome.get_tabs_bar().close_tab(1)
1120 else:
1121@@ -51,13 +49,9 @@
1122
1123 def test_new_tab_view_is_shared_between_tabs(self):
1124 # Open one new tab
1125- if not self.main_window.wide:
1126- self.open_tabs_view()
1127- new_tab_view = self.open_new_tab()
1128+ new_tab_view = self.open_new_tab(open_tabs_view=True)
1129 # Open a second new tab
1130- if not self.main_window.wide:
1131- self.open_tabs_view()
1132- new_tab_view_2 = self.open_new_tab()
1133+ new_tab_view_2 = self.open_new_tab(open_tabs_view=True)
1134 # Verify that they share the same NewTabView instance
1135 self.assertThat(new_tab_view_2.id, Equals(new_tab_view.id))
1136 # Close the second new tab, and verify that the NewTabView instance
1137@@ -123,13 +117,9 @@
1138 self.main_window.go_to_url(self.base_url + "/test2")
1139 new_private_tab_view.wait_until_destroyed()
1140 # Open one new private tab
1141- if not self.main_window.wide:
1142- self.open_tabs_view()
1143- new_private_tab_view = self.open_new_tab()
1144+ new_private_tab_view = self.open_new_tab(open_tabs_view=True)
1145 # Open a second new private tab
1146- if not self.main_window.wide:
1147- self.open_tabs_view()
1148- new_private_tab_view_2 = self.open_new_tab()
1149+ new_private_tab_view_2 = self.open_new_tab(open_tabs_view=True)
1150 # Verify that they share the same NewPrivateTabView instance
1151 self.assertThat(new_private_tab_view_2.id,
1152 Equals(new_private_tab_view.id))
1153@@ -156,16 +146,14 @@
1154 new_private_tab_view.wait_until_destroyed()
1155
1156
1157-class TestNewTabViewContents(StartOpenRemotePageTestCaseBase):
1158+class TestNewTabViewContentsBase(StartOpenRemotePageTestCaseBase):
1159
1160 def setUp(self):
1161 self.create_temporary_profile()
1162 self.populate_config()
1163 self.populate_bookmarks()
1164- super(TestNewTabViewContents, self).setUp()
1165- if not self.main_window.wide:
1166- self.open_tabs_view()
1167- self.new_tab_view = self.open_new_tab()
1168+ super(TestNewTabViewContentsBase, self).setUp()
1169+ self.new_tab_view = self.open_new_tab(open_tabs_view=True)
1170
1171 def populate_config(self):
1172 self.homepage = "http://test/test2"
1173@@ -226,6 +214,14 @@
1174 connection.commit()
1175 connection.close()
1176
1177+
1178+class TestNewTabViewContentsNarrow(TestNewTabViewContentsBase):
1179+
1180+ def setUp(self):
1181+ super(TestNewTabViewContentsNarrow, self).setUp()
1182+ if self.main_window.wide:
1183+ self.skipTest("Only on narrow form factors")
1184+
1185 def test_default_home_bookmark(self):
1186 homepage_bookmark = self.new_tab_view.get_homepage_bookmark()
1187 self.assertThat(homepage_bookmark.url, Equals(self.homepage))
1188@@ -233,10 +229,18 @@
1189 self.new_tab_view.wait_until_destroyed()
1190 self.main_window.wait_until_page_loaded(self.homepage)
1191
1192- def test_open_bookmark_when_collapsed(self):
1193+ def test_open_top_site(self):
1194+ top_sites = self.new_tab_view.get_top_sites_list()
1195+ self.assertThat(lambda: len(top_sites.get_delegates()),
1196+ Eventually(Equals(1)))
1197+ top_site = top_sites.get_delegates()[0]
1198+ url = top_site.url
1199+ self.pointing_device.click_object(top_site)
1200+ self.new_tab_view.wait_until_destroyed()
1201+ self.main_window.wait_until_page_loaded(url)
1202+
1203+ def test_open_bookmark(self):
1204 bookmarks = self.new_tab_view.get_bookmarks_list()
1205- self.assertThat(lambda: len(bookmarks.get_delegates()),
1206- Eventually(Equals(4)))
1207 bookmark = bookmarks.get_delegates()[1]
1208 url = bookmark.url
1209 self.pointing_device.click_object(bookmark)
1210@@ -247,7 +251,7 @@
1211 more_button = self.new_tab_view.get_bookmarks_more_button()
1212 self.assertThat(more_button.visible, Equals(True))
1213 self.pointing_device.click_object(more_button)
1214- folders = self.main_window.get_bookmarks_folder_list_view()
1215+ folders = self.new_tab_view.get_bookmarks_folder_list_view()
1216 folder_delegate = folders.get_folder_delegate("")
1217 self.assertThat(lambda: len(folders.get_urls_from_folder(
1218 folder_delegate)),
1219@@ -269,7 +273,7 @@
1220 more_button = self.new_tab_view.get_bookmarks_more_button()
1221 self.assertThat(more_button.visible, Equals(True))
1222 self.pointing_device.click_object(more_button)
1223- folders = self.main_window.get_bookmarks_folder_list_view()
1224+ folders = self.new_tab_view.get_bookmarks_folder_list_view()
1225 folder_delegate = folders.get_folder_delegate("")
1226 self.assertThat(lambda: len(folders.get_urls_from_folder(
1227 folder_delegate)),
1228@@ -292,7 +296,7 @@
1229 Eventually(NotEquals(url)))
1230
1231 def _remove_first_bookmark_from_folder(self, folder):
1232- folders = self.main_window.get_bookmarks_folder_list_view()
1233+ folders = self.new_tab_view.get_bookmarks_folder_list_view()
1234 folder_delegate = folders.get_folder_delegate(folder)
1235 delegate = folders.get_urls_from_folder(folder_delegate)[0]
1236 url = delegate.url
1237@@ -319,7 +323,7 @@
1238 more_button = self.new_tab_view.get_bookmarks_more_button()
1239 self.assertThat(more_button.visible, Equals(True))
1240 self.pointing_device.click_object(more_button)
1241- folders = self.main_window.get_bookmarks_folder_list_view()
1242+ folders = self.new_tab_view.get_bookmarks_folder_list_view()
1243 folder_delegate = folders.get_folder_delegate("")
1244 self.assertThat(lambda: len(folders.get_urls_from_folder(
1245 folder_delegate)),
1246@@ -335,7 +339,7 @@
1247 more_button = self.new_tab_view.get_bookmarks_more_button()
1248 self.assertThat(more_button.visible, Equals(True))
1249 self.pointing_device.click_object(more_button)
1250- folders = self.main_window.get_bookmarks_folder_list_view()
1251+ folders = self.new_tab_view.get_bookmarks_folder_list_view()
1252 self.assertThat(lambda: len(folders.get_delegates()),
1253 Eventually(Equals(3)))
1254 folder_delegate = folders.get_folder_delegate("")
1255@@ -355,7 +359,7 @@
1256 more_button = self.new_tab_view.get_bookmarks_more_button()
1257 self.assertThat(more_button.visible, Equals(True))
1258 self.pointing_device.click_object(more_button)
1259- folders = self.main_window.get_bookmarks_folder_list_view()
1260+ folders = self.new_tab_view.get_bookmarks_folder_list_view()
1261 self.assertThat(lambda: len(folders.get_delegates()),
1262 Eventually(Equals(3)))
1263 folder_delegate = folders.get_folder_delegate("Actinide")
1264@@ -378,7 +382,7 @@
1265 more_button = self.new_tab_view.get_bookmarks_more_button()
1266 self.assertThat(more_button.visible, Equals(True))
1267 self.pointing_device.click_object(more_button)
1268- folders = self.main_window.get_bookmarks_folder_list_view()
1269+ folders = self.new_tab_view.get_bookmarks_folder_list_view()
1270 self.assertThat(lambda: len(folders.get_delegates()),
1271 Eventually(Equals(3)))
1272 folder_delegate = folders.get_folder_delegate("")
1273@@ -396,16 +400,6 @@
1274 folder_delegate)),
1275 Eventually(Equals(4)))
1276
1277- def test_open_top_site(self):
1278- top_sites = self.new_tab_view.get_top_sites_list()
1279- self.assertThat(lambda: len(top_sites.get_delegates()),
1280- Eventually(Equals(1)))
1281- top_site = top_sites.get_delegates()[0]
1282- url = top_site.url
1283- self.pointing_device.click_object(top_site)
1284- self.new_tab_view.wait_until_destroyed()
1285- self.main_window.wait_until_page_loaded(url)
1286-
1287 def test_remove_top_sites(self):
1288 top_sites = self.new_tab_view.get_top_sites_list()
1289 self.assertThat(lambda: len(top_sites.get_delegates()),
1290@@ -418,3 +412,87 @@
1291 self.assertThat(lambda: len(top_sites.get_delegates()),
1292 Eventually(Equals(0)))
1293 self.assertThat(notopsites_label.visible, Eventually(Equals(True)))
1294+
1295+
1296+class TestNewTabViewContentsWide(TestNewTabViewContentsBase):
1297+
1298+ def setUp(self):
1299+ super(TestNewTabViewContentsWide, self).setUp()
1300+ if not self.main_window.wide:
1301+ self.skipTest("Only on wide form factors")
1302+
1303+ def test_remove_bookmarks(self):
1304+ view = self.new_tab_view
1305+ bookmarks = view.get_bookmarks_list()
1306+ previous_count = len(bookmarks)
1307+ bookmarks[1].trigger_leading_action("leadingAction.delete",
1308+ bookmarks[1].wait_until_destroyed)
1309+ bookmarks = view.get_bookmarks_list()
1310+ self.assertThat(len(bookmarks), Equals(previous_count - 1))
1311+ previous_count = len(bookmarks)
1312+
1313+ # verify that trying to delete the homepage bookmark is not going to
1314+ # do anything because there is no delete action on the delegate
1315+ no_delete_action = False
1316+ try:
1317+ bookmarks[0].trigger_leading_action("leadingAction.delete")
1318+ except ToolkitException:
1319+ no_delete_action = True
1320+ self.assertThat(no_delete_action, Equals(True))
1321+ self.assertThat(len(view.get_bookmarks_list()), Equals(previous_count))
1322+
1323+ def test_remove_top_sites(self):
1324+ view = self.new_tab_view
1325+ topsites = view.get_top_sites_list()
1326+ previous_count = len(topsites)
1327+ topsites[0].trigger_leading_action("leadingAction.delete",
1328+ topsites[0].wait_until_destroyed)
1329+ self.assertThat(len(view.get_top_sites_list()),
1330+ Equals(previous_count - 1))
1331+
1332+ def test_drag_bookmarks(self):
1333+ view = self.new_tab_view
1334+ folders = view.get_folders_list()
1335+ bookmarks = view.get_bookmarks_list()
1336+ previous_count = len(bookmarks)
1337+ bookmark = bookmarks[1]
1338+ title = bookmark.title
1339+ grip = bookmark.get_grip()
1340+ original_x = grip.globalRect.x
1341+ original_y = grip.globalRect.y
1342+
1343+ # Test that when hovering normal bookmarks item the grip appears
1344+ self.assertThat(grip.opacity, Equals(0))
1345+ self.pointing_device.move_to_object(bookmark)
1346+ self.assertThat(grip.opacity, Eventually(Equals(1.0)))
1347+
1348+ # Test that an item bounces back when dragged within the list itself
1349+ self.pointing_device.drag(original_x, original_y,
1350+ original_x, original_y + 200)
1351+
1352+ # Test that an item bounces back when dragged to the same folder
1353+ folder = folders[0]
1354+ folder_cx = folder.globalRect.x + folder.width / 2
1355+ folder_cy = folder.globalRect.y + folder.height / 2
1356+ self.pointing_device.drag(original_x, original_y,
1357+ folder_cx, folder_cy)
1358+
1359+ self.assertThat(lambda: (grip.globalRect.x, grip.globalRect.y),
1360+ Eventually(Equals((original_x, original_y))))
1361+
1362+ # Test that dragging an item to another folder removes it from this one
1363+ # and adds it to the target folder
1364+ folder = folders[2]
1365+ folder_cx = folder.globalRect.x + folder.width / 2
1366+ folder_cy = folder.globalRect.y + folder.height / 2
1367+ self.pointing_device.drag(original_x, original_y,
1368+ folder_cx, folder_cy)
1369+
1370+ self.assertThat(lambda: len(view.get_bookmarks_list()),
1371+ Eventually(NotEquals(previous_count)))
1372+
1373+ # Verify that the item has been added to the top of the target folder
1374+ self.pointing_device.click_object(folder)
1375+ self.assertThat(lambda: len(view.get_bookmarks_list()),
1376+ Eventually(Equals(2)))
1377+ self.assertThat(view.get_bookmarks_list()[0].title, Equals(title))
1378
1379=== modified file 'tests/autopilot/webbrowser_app/tests/test_private.py'
1380--- tests/autopilot/webbrowser_app/tests/test_private.py 2015-07-02 13:51:07 +0000
1381+++ tests/autopilot/webbrowser_app/tests/test_private.py 2015-08-12 13:42:27 +0000
1382@@ -22,12 +22,6 @@
1383
1384 class TestPrivateView(StartOpenRemotePageTestCaseBase):
1385
1386- def get_url_list_from_top_sites(self):
1387- if not self.main_window.wide:
1388- self.open_tabs_view()
1389- new_tab_view = self.open_new_tab()
1390- return new_tab_view.get_top_sites_list().get_urls()
1391-
1392 def test_going_in_and_out_private_mode(self):
1393 address_bar = self.main_window.address_bar
1394 address_bar.focus()
1395@@ -72,8 +66,9 @@
1396 self.assertTrue(self.main_window.is_new_private_tab_view_visible())
1397
1398 def test_url_showing_in_top_sites_in_and_out_private_mode(self):
1399- top_sites = self.get_url_list_from_top_sites()
1400- self.assertIn(self.url, top_sites)
1401+ new_tab = self.open_new_tab(open_tabs_view=True)
1402+ urls = [site.url for site in new_tab.get_top_site_items()]
1403+ self.assertIn(self.url, urls)
1404
1405 self.main_window.enter_private_mode()
1406 self.assertThat(self.main_window.is_in_private_mode,
1407@@ -84,13 +79,13 @@
1408 self.main_window.leave_private_mode()
1409 self.assertThat(self.main_window.is_in_private_mode,
1410 Eventually(Equals(False)))
1411- top_sites = self.get_url_list_from_top_sites()
1412- self.assertNotIn(url, top_sites)
1413+
1414+ new_tab = self.open_new_tab(open_tabs_view=True)
1415+ urls = [site.url for site in new_tab.get_top_site_items()]
1416+ self.assertNotIn(url, urls)
1417
1418 def test_public_tabs_should_not_be_visible_in_private_mode(self):
1419- if not self.main_window.wide:
1420- self.open_tabs_view()
1421- self.open_new_tab()
1422+ self.open_new_tab(open_tabs_view=True)
1423 new_tab_view = self.main_window.get_new_tab_view()
1424 url = self.base_url + "/test2"
1425 self.main_window.go_to_url(url)
1426
1427=== modified file 'tests/autopilot/webbrowser_app/tests/test_tabs.py'
1428--- tests/autopilot/webbrowser_app/tests/test_tabs.py 2015-07-02 13:51:07 +0000
1429+++ tests/autopilot/webbrowser_app/tests/test_tabs.py 2015-08-12 13:42:27 +0000
1430@@ -161,9 +161,7 @@
1431 webview.activeFocus.wait_for(True)
1432
1433 def test_webview_requests_close(self):
1434- if not self.main_window.wide:
1435- self.open_tabs_view()
1436- self.open_new_tab()
1437+ self.open_new_tab(open_tabs_view=True)
1438 url = self.base_url + "/closeself"
1439 self.main_window.go_to_url(url)
1440 self.main_window.wait_until_page_loaded(url)
1441@@ -174,9 +172,7 @@
1442 self.assert_number_webviews_eventually(1)
1443
1444 def test_last_webview_requests_close(self):
1445- if not self.main_window.wide:
1446- self.open_tabs_view()
1447- self.open_new_tab()
1448+ self.open_new_tab(open_tabs_view=True)
1449 url = self.base_url + "/closeself"
1450 self.main_window.go_to_url(url)
1451 self.main_window.wait_until_page_loaded(url)
1452
1453=== modified file 'tests/unittests/bookmarks-folder-model/tst_BookmarksFolderModelTests.cpp'
1454--- tests/unittests/bookmarks-folder-model/tst_BookmarksFolderModelTests.cpp 2015-07-02 13:16:56 +0000
1455+++ tests/unittests/bookmarks-folder-model/tst_BookmarksFolderModelTests.cpp 2015-08-12 13:42:27 +0000
1456@@ -88,18 +88,21 @@
1457
1458 void shouldFilterOutNonMatchingFolders()
1459 {
1460- bookmarks->add(QUrl("http://example.org/"), "Example Domain", QUrl(), "");
1461- bookmarks->add(QUrl("http://example.com/"), "Example Domain", QUrl(), "SampleFolder01");
1462- bookmarks->add(QUrl("http://example.net/"), "Example Domain", QUrl(), "SampleFolder02");
1463+ bookmarks->add(QUrl("http://example.org/"), "Example Domain Org", QUrl(), "");
1464+ bookmarks->add(QUrl("http://example.com/"), "Example Domain Com", QUrl(), "SampleFolder01");
1465+ bookmarks->add(QUrl("http://example.net/"), "Example Domain Net", QUrl("http://example.net/icon.png"), "SampleFolder02");
1466 model->setFolder("");
1467 QCOMPARE(model->rowCount(), 1);
1468 QCOMPARE(model->data(model->index(0, 0), BookmarksModel::Url).toUrl(), QUrl("http://example.org/"));
1469+ QCOMPARE(model->get(0).value("url").toUrl(), QUrl("http://example.org/"));
1470 model->setFolder("SampleFolder01");
1471 QCOMPARE(model->rowCount(), 1);
1472 QCOMPARE(model->data(model->index(0, 0), BookmarksModel::Url).toUrl(), QUrl("http://example.com/"));
1473+ QCOMPARE(model->get(0).value("title").toString(), QString("Example Domain Com"));
1474 model->setFolder("SampleFolder02");
1475 QCOMPARE(model->rowCount(), 1);
1476 QCOMPARE(model->data(model->index(0, 0), BookmarksModel::Url).toUrl(), QUrl("http://example.net/"));
1477+ QCOMPARE(model->get(0).value("icon").toUrl(), QUrl("http://example.net/icon.png"));
1478 model->setFolder("AnotherFolder");
1479 QCOMPARE(model->rowCount(), 0);
1480 }
1481
1482=== modified file 'tests/unittests/qml/CMakeLists.txt'
1483--- tests/unittests/qml/CMakeLists.txt 2015-07-09 20:27:00 +0000
1484+++ tests/unittests/qml/CMakeLists.txt 2015-08-12 13:42:27 +0000
1485@@ -4,6 +4,7 @@
1486 find_package(Qt5Qml REQUIRED)
1487 find_package(Qt5Quick REQUIRED)
1488 find_package(Qt5QuickTest REQUIRED)
1489+find_package(Qt5Sql REQUIRED)
1490
1491 set(XVFB_COMMAND)
1492 find_program(XVFBRUN xvfb-run)
1493@@ -16,9 +17,16 @@
1494 set(TEST tst_QmlTests)
1495 set(SOURCES
1496 ${webbrowser-common_SOURCE_DIR}/favicon-fetcher.cpp
1497+ ${webbrowser-app_SOURCE_DIR}/bookmarks-model.cpp
1498+ ${webbrowser-app_SOURCE_DIR}/bookmarks-folder-model.cpp
1499+ ${webbrowser-app_SOURCE_DIR}/bookmarks-folderlist-model.cpp
1500 ${webbrowser-app_SOURCE_DIR}/file-operations.cpp
1501+ ${webbrowser-app_SOURCE_DIR}/history-model.cpp
1502+ ${webbrowser-app_SOURCE_DIR}/history-timeframe-model.cpp
1503+ ${webbrowser-app_SOURCE_DIR}/limit-proxy-model.cpp
1504 ${webbrowser-app_SOURCE_DIR}/searchengine.cpp
1505 ${webbrowser-app_SOURCE_DIR}/tabs-model.cpp
1506+ ${webbrowser-app_SOURCE_DIR}/top-sites-model.cpp
1507 tst_QmlTests.cpp
1508 )
1509 add_executable(${TEST} ${SOURCES})
1510@@ -33,6 +41,7 @@
1511 Qt5::Qml
1512 Qt5::Quick
1513 Qt5::QuickTest
1514+ Qt5::Sql
1515 )
1516 add_test(${TEST} ${XVFB_COMMAND} ${CMAKE_CURRENT_BINARY_DIR}/${TEST}
1517 -input ${CMAKE_CURRENT_SOURCE_DIR}
1518
1519=== added file 'tests/unittests/qml/tst_NewTabViewWide.qml'
1520--- tests/unittests/qml/tst_NewTabViewWide.qml 1970-01-01 00:00:00 +0000
1521+++ tests/unittests/qml/tst_NewTabViewWide.qml 2015-08-12 13:42:27 +0000
1522@@ -0,0 +1,372 @@
1523+/*
1524+ * Copyright 2015 Canonical Ltd.
1525+ *
1526+ * This file is part of webbrowser-app.
1527+ *
1528+ * webbrowser-app is free software; you can redistribute it and/or modify
1529+ * it under the terms of the GNU General Public License as published by
1530+ * the Free Software Foundation; version 3.
1531+ *
1532+ * webbrowser-app is distributed in the hope that it will be useful,
1533+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1534+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1535+ * GNU General Public License for more details.
1536+ *
1537+ * You should have received a copy of the GNU General Public License
1538+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1539+ */
1540+
1541+import QtQuick 2.4
1542+import QtTest 1.0
1543+import Ubuntu.Test 1.0
1544+import "../../../src/app/webbrowser"
1545+import webbrowserapp.private 0.1
1546+
1547+Item {
1548+ id: root
1549+
1550+ width: 800
1551+ height: 600
1552+
1553+ Component {
1554+ id: historyModel
1555+ HistoryModel {
1556+ databasePath: ":memory:"
1557+ }
1558+ }
1559+
1560+ Component {
1561+ id: bookmarksModel
1562+ BookmarksModel {
1563+ databasePath: ":memory:"
1564+ }
1565+ }
1566+
1567+ property NewTabViewWide view
1568+ property var bookmarks
1569+ property var history
1570+ property string homepage: "http://example.com/homepage"
1571+
1572+ Component {
1573+ id: viewComponent
1574+ NewTabViewWide {
1575+ anchors.fill: parent
1576+ settingsObject: QtObject {
1577+ property url homepage: root.homepage
1578+ property int newTabDefaultSection: 0
1579+ }
1580+ bookmarksModel: bookmarks
1581+ historyModel: history
1582+ }
1583+ }
1584+
1585+ SignalSpy {
1586+ id: releasingKeyboardFocusSpy
1587+ signalName: "releasingKeyboardFocus"
1588+ }
1589+
1590+ SignalSpy {
1591+ id: historyEntryClickedSpy
1592+ signalName: "historyEntryClicked"
1593+ }
1594+
1595+ SignalSpy {
1596+ id: bookmarkClickedSpy
1597+ signalName: "bookmarkClicked"
1598+ }
1599+
1600+ SignalSpy {
1601+ id: bookmarkRemovedSpy
1602+ signalName: "bookmarkRemoved"
1603+ }
1604+
1605+ UbuntuTestCase {
1606+ name: "NewTabViewWide"
1607+ when: windowShown
1608+
1609+ function init() {
1610+ bookmarks = bookmarksModel.createObject()
1611+ history = historyModel.createObject()
1612+ view = viewComponent.createObject(root)
1613+ populate()
1614+
1615+ view.focus = true
1616+
1617+ releasingKeyboardFocusSpy.target = view
1618+ releasingKeyboardFocusSpy.clear()
1619+ historyEntryClickedSpy.target = view
1620+ historyEntryClickedSpy.clear()
1621+ bookmarkClickedSpy.target = view
1622+ bookmarkClickedSpy.clear()
1623+ bookmarkRemovedSpy.target = view
1624+ bookmarkRemovedSpy.clear()
1625+ }
1626+
1627+ function populate() {
1628+ history.add("http://example.com", "Example Com", "")
1629+ history.add("http://example.org", "Example Org", "")
1630+ history.add("http://example.net", "Example Net", "")
1631+ bookmarks.add("http://example.com", "Example Com", "", "")
1632+ bookmarks.add("http://example.org/bar", "Example Org Bar", "", "Folder B")
1633+ bookmarks.add("http://example.org/foo", "Example Org Foo", "", "Folder B")
1634+ bookmarks.add("http://example.net/a", "Example Net A", "", "Folder A")
1635+ bookmarks.add("http://example.net/b", "Example Net B", "", "Folder A")
1636+ }
1637+
1638+ function cleanup() {
1639+ history.destroy()
1640+ history = null
1641+ bookmarks.destroy()
1642+ bookmarks = null
1643+
1644+ view.destroy()
1645+ view = null
1646+ }
1647+
1648+ function clickItem(item) {
1649+ var center = centerOf(item)
1650+ mouseClick(item, center.x, center.y)
1651+ }
1652+
1653+ function getListItems(name, itemName) {
1654+ var list = findChild(view, name)
1655+ var items = []
1656+ if (list) {
1657+ // ensure all the delegates are created
1658+ list.cacheBuffer = list.count * 1000
1659+
1660+ // In some cases the ListView might add other children to the
1661+ // contentItem, so we filter the list of children to include
1662+ // only actual delegates
1663+ var children = list.contentItem.children
1664+ for (var i = 0; i < children.length; i++) {
1665+ if (children[i].objectName === itemName) {
1666+ items.push(children[i])
1667+ }
1668+ }
1669+ }
1670+ return items
1671+ }
1672+
1673+ function goToBookmarks() {
1674+ findChild(view, "sections").selectedIndex = 1
1675+ }
1676+
1677+ function test_topsites_list() {
1678+ // add 8 more top sites so that we are beyond the limit of 10
1679+ for (var i = 0; i < 8; i++) {
1680+ history.add("http://example.com/" + i, "Example Com " + i, "")
1681+ }
1682+
1683+ var items = getListItems("topSitesList", "topSiteItem")
1684+ compare(items.length, 10)
1685+ compare(items[0].title, "Example Com")
1686+ compare(items[1].title, "Example Org")
1687+ compare(items[2].title, "Example Net")
1688+ for (var i = 0; i < 7; i++) {
1689+ compare(items[i + 3].title, "Example Com " + i)
1690+ }
1691+ }
1692+
1693+ function test_folder_list() {
1694+ var items = getListItems("foldersList", "folderItem")
1695+ compare(items.length, 3)
1696+ verify(items[0].isAllBookmarksFolder)
1697+ compare(items[0].model.folder, "")
1698+ // named folder items should appear alphabetically sorted
1699+ compare(items[1].model.folder, "Folder A")
1700+ compare(items[2].model.folder, "Folder B")
1701+ }
1702+
1703+ function test_all_bookmarks_list() {
1704+ var items = getListItems("bookmarksList", "bookmarkItem")
1705+ compare(items.length, 2)
1706+ compare(items[0].url, homepage)
1707+ compare(items[1].title, "Example Com")
1708+ }
1709+
1710+ function test_switch_sections_by_keyboard() {
1711+ skip("Would fail due to UITK bug: http://pad.lv/1481233")
1712+ var sections = findChild(view, "sections")
1713+ var folders = findChild(view, "foldersList")
1714+ var bookmarks = findChild(view, "bookmarksList")
1715+ var topSites = findChild(view, "topSitesList")
1716+ compare(sections.selectedIndex, 0)
1717+ verify(topSites.visible)
1718+ verify(!folders.visible)
1719+ verify(!bookmarks.visible)
1720+
1721+ keyClick(Qt.Key_Tab)
1722+ compare(sections.selectedIndex, 1)
1723+ verify(!topSites.visible)
1724+ verify(folders.visible)
1725+ verify(bookmarks.visible)
1726+
1727+ keyClick(Qt.Key_Backtab)
1728+ compare(sections.selectedIndex, 0)
1729+ }
1730+
1731+ function test_navigate_topsites_by_keyboard() {
1732+ var items = getListItems("topSitesList", "topSiteItem")
1733+ findChild(view, "topSitesList").currentIndex = 0
1734+ verify(items[0].highlighted)
1735+ keyClick(Qt.Key_Down)
1736+ verify(!items[0].highlighted)
1737+ verify(items[1].highlighted)
1738+ keyClick(Qt.Key_Down)
1739+ verify(items[2].highlighted)
1740+ keyClick(Qt.Key_Down) // ensure no scrolling past bottom boundary
1741+ verify(items[2].highlighted)
1742+ keyClick(Qt.Key_Up)
1743+ verify(items[1].highlighted)
1744+ keyClick(Qt.Key_Up)
1745+ verify(items[0].highlighted)
1746+ keyClick(Qt.Key_Up)
1747+ verify(items[0].highlighted)
1748+ compare(releasingKeyboardFocusSpy.count, 1)
1749+ }
1750+
1751+ function test_activate_topsites_by_keyboard() {
1752+ var items = getListItems("topSitesList", "topSiteItem")
1753+ keyClick(Qt.Key_Return)
1754+ compare(historyEntryClickedSpy.count, 1)
1755+ compare(historyEntryClickedSpy.signalArguments[0][0], "http://example.com")
1756+ keyClick(Qt.Key_Down)
1757+ keyClick(Qt.Key_Return)
1758+ compare(historyEntryClickedSpy.count, 2)
1759+ compare(historyEntryClickedSpy.signalArguments[1][0], "http://example.org")
1760+ }
1761+
1762+ function test_navigate_folders_by_keyboard() {
1763+ goToBookmarks()
1764+
1765+ var foldersList = getListItems(view, "foldersList")
1766+ var folders = getListItems("foldersList", "folderItem")
1767+ verify(folders[0].isActiveFolder)
1768+
1769+ keyClick(Qt.Key_Down)
1770+ verify(!folders[0].isActiveFolder)
1771+ verify(folders[1].isActiveFolder)
1772+
1773+ // bookmarks within a folder are sorted with the first bookmarked appearing last
1774+ var items = getListItems("bookmarksList", "bookmarkItem")
1775+ compare(items[0].title, "Example Net B")
1776+ compare(items[1].title, "Example Net A")
1777+ compare(items.length, 2)
1778+
1779+ keyClick(Qt.Key_Down)
1780+ verify(folders[2].isActiveFolder)
1781+ items = getListItems("bookmarksList", "bookmarkItem")
1782+ compare(items[0].title, "Example Org Foo")
1783+ compare(items[1].title, "Example Org Bar")
1784+ compare(items.length, 2)
1785+
1786+ // verify scrolling beyond bottom of list is not allowed
1787+ keyClick(Qt.Key_Down)
1788+ verify(folders[2].isActiveFolder)
1789+
1790+ keyClick(Qt.Key_Up)
1791+ verify(folders[1].isActiveFolder)
1792+ keyClick(Qt.Key_Up)
1793+ verify(folders[0].isActiveFolder)
1794+
1795+ keyClick(Qt.Key_Up)
1796+ compare(releasingKeyboardFocusSpy.count, 1)
1797+ }
1798+
1799+ function test_switch_between_folder_and_bookmarks_by_keyboard() {
1800+ goToBookmarks()
1801+
1802+ var folders = findChild(view, "foldersList")
1803+ var bookmarks = findChild(view, "bookmarksList")
1804+
1805+ keyClick(Qt.Key_Right)
1806+ verify(bookmarks.activeFocus)
1807+ keyClick(Qt.Key_Right)
1808+ verify(bookmarks.activeFocus) // verify no circular scrolling
1809+
1810+ keyClick(Qt.Key_Left)
1811+ verify(folders.activeFocus)
1812+ keyClick(Qt.Key_Left)
1813+ verify(folders.activeFocus) // verify no circular scrolling
1814+ }
1815+
1816+ function test_activate_bookmarks_by_keyboard() {
1817+ goToBookmarks()
1818+ keyClick(Qt.Key_Right)
1819+
1820+ var items = getListItems("bookmarksList", "bookmarkItem")
1821+ keyClick(Qt.Key_Return)
1822+ compare(bookmarkClickedSpy.count, 1)
1823+ compare(bookmarkClickedSpy.signalArguments[0][0], homepage)
1824+
1825+ keyClick(Qt.Key_Down)
1826+ keyClick(Qt.Key_Return)
1827+ compare(bookmarkClickedSpy.count, 2)
1828+ compare(bookmarkClickedSpy.signalArguments[1][0], "http://example.com")
1829+ }
1830+
1831+ function test_activate_topsites_by_mouse() {
1832+ var items = getListItems("topSitesList", "topSiteItem")
1833+ clickItem(items[0])
1834+ compare(historyEntryClickedSpy.count, 1)
1835+ compare(historyEntryClickedSpy.signalArguments[0][0], "http://example.com")
1836+
1837+ clickItem(items[1])
1838+ compare(historyEntryClickedSpy.count, 2)
1839+ compare(historyEntryClickedSpy.signalArguments[1][0], "http://example.org")
1840+
1841+ }
1842+
1843+ function test_activate_bookmarks_by_mouse() {
1844+ goToBookmarks()
1845+ var items = getListItems("bookmarksList", "bookmarkItem")
1846+ clickItem(items[0])
1847+ compare(bookmarkClickedSpy.count, 1)
1848+ compare(bookmarkClickedSpy.signalArguments[0][0], homepage)
1849+
1850+ clickItem(items[1])
1851+ compare(bookmarkClickedSpy.count, 2)
1852+ compare(bookmarkClickedSpy.signalArguments[1][0], "http://example.com")
1853+ }
1854+
1855+ function test_switch_folders_by_mouse() {
1856+ goToBookmarks()
1857+ var folders = getListItems("foldersList", "folderItem")
1858+
1859+ clickItem(folders[1])
1860+ var items = getListItems("bookmarksList", "bookmarkItem")
1861+ compare(items[0].title, "Example Net B")
1862+ compare(items[1].title, "Example Net A")
1863+ compare(items.length, 2)
1864+
1865+ clickItem(folders[0])
1866+ items = getListItems("bookmarksList", "bookmarkItem")
1867+ compare(items[0].url, homepage)
1868+ compare(items[1].title, "Example Com")
1869+ compare(items.length, 2)
1870+ }
1871+
1872+ function test_remove_bookmarks_by_keyboard() {
1873+ goToBookmarks()
1874+ keyClick(Qt.Key_Right)
1875+ var items = getListItems("bookmarksList", "bookmarkItem")
1876+
1877+ // verify that trying to delete the homepage bookmark does not work
1878+ keyClick(Qt.Key_Delete)
1879+ compare(bookmarkRemovedSpy.count, 0)
1880+
1881+ keyClick(Qt.Key_Down)
1882+ keyClick(Qt.Key_Delete)
1883+ compare(bookmarkRemovedSpy.count, 1)
1884+ compare(bookmarkRemovedSpy.signalArguments[0][0], items[1].url)
1885+ }
1886+
1887+ function test_remove_top_sites_by_keyboard() {
1888+ var previous = getListItems("topSitesList", "topSiteItem")
1889+ keyClick(Qt.Key_Delete)
1890+ var items = getListItems("topSitesList", "topSiteItem")
1891+ compare(previous.length - 1, items.length)
1892+ }
1893+ }
1894+}
1895
1896=== modified file 'tests/unittests/qml/tst_QmlTests.cpp'
1897--- tests/unittests/qml/tst_QmlTests.cpp 2015-06-25 17:54:01 +0000
1898+++ tests/unittests/qml/tst_QmlTests.cpp 2015-08-12 13:42:27 +0000
1899@@ -25,10 +25,16 @@
1900 #include <QtQuickTest/QtQuickTest>
1901
1902 // local
1903+#include "bookmarks-model.h"
1904+#include "bookmarks-folderlist-model.h"
1905 #include "favicon-fetcher.h"
1906 #include "file-operations.h"
1907+#include "history-model.h"
1908+#include "history-timeframe-model.h"
1909+#include "limit-proxy-model.h"
1910 #include "searchengine.h"
1911 #include "tabs-model.h"
1912+#include "top-sites-model.h"
1913
1914 static QObject* FileOperations_singleton_factory(QQmlEngine* engine, QJSEngine* scriptEngine)
1915 {
1916@@ -116,6 +122,12 @@
1917 const char* browserUri = "webbrowserapp.private";
1918 qmlRegisterType<SearchEngine>(browserUri, 0, 1, "SearchEngine");
1919 qmlRegisterType<TabsModel>(browserUri, 0, 1, "TabsModel");
1920+ qmlRegisterType<BookmarksModel>(browserUri, 0, 1, "BookmarksModel");
1921+ qmlRegisterType<BookmarksFolderListModel>(browserUri, 0, 1, "BookmarksFolderListModel");
1922+ qmlRegisterType<HistoryModel>(browserUri, 0, 1, "HistoryModel");
1923+ qmlRegisterType<HistoryTimeframeModel>(browserUri, 0, 1, "HistoryTimeframeModel");
1924+ qmlRegisterType<LimitProxyModel>(browserUri, 0, 1, "LimitProxyModel");
1925+ qmlRegisterType<TopSitesModel>(browserUri, 0, 1, "TopSitesModel");
1926 qmlRegisterSingletonType<FileOperations>(browserUri, 0, 1, "FileOperations", FileOperations_singleton_factory);
1927
1928 qmlRegisterSingletonType<TestContext>("webbrowsertest.private", 0, 1, "TestContext", TestContext_singleton_factory);

Subscribers

People subscribed via source and target branches

to status/vote changes: