Merge lp:~uriboni/webbrowser-app/new-tab-wide-format into lp:webbrowser-app
- new-tab-wide-format
- Merge into trunk
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 | ||||||||
Related bugs: |
|
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/
This adds a build dependency on qml-module-
Description of the change
Implement the widescreen/
It requires the new Sections UITK component which is currently in the staging branch: lp:~ubuntu-sdk-team/ubuntu-ui-toolkit/staging
- 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
PS Jenkins bot (ps-jenkins) wrote : | # |
- 1078. By Ugo Riboni
-
Fix copyright header
- 1079. By Ugo Riboni
-
Revert changes to UrlsList as we are not using it anymore
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1079
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 1080. By Ugo Riboni
-
Add qt.labs.settings as build dep
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1080
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 1081. By Ugo Riboni
-
Revert previous commit and actually commit the change to the debian dependencies
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1081
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
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:/
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:
2: FAIL! : QmlTests:
2: Actual (): 0
2: Expected (): 1
2: Loc: [/home/
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?
- 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
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1083
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 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
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.
> Go/edit#
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:/
> 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:
> failing:
> 2: FAIL! :
> QmlTests:
> values are not the same
> 2: Actual (): 0
> 2: Expected (): 1
> 2: Loc: [/home/
> app/tests/
This is caused by a recent change in the UITK staging branch. I submitted a bug to track it: https:/
> 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
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1086
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 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
Olivier Tilloy (osomon) wrote : | # |
Why is there a new "selectedIndexN
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://
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: newTabViewLoade
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-
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1087
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
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.
- 1090. By Ugo Riboni
-
Fix incorrect item reference that prevented dropping bookmarks to work
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1089
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1090
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Olivier Tilloy (osomon) wrote : | # |
In debian/control, the build dependency and runtime dependency of webbrowser-app on qtdeclarative5-
- 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
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1102
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1103
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 1104. By Ugo Riboni
-
Reimplement the drag and drop test as autopilot tests
Ugo Riboni (uriboni) wrote : | # |
All other items that are not specifically mentioned here should have been fixed or addressed.
> Why is there a new "selectedIndexN
> 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.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1104
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
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-
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
Even with the above fixed, I’m seeing 3 errors when running the autopilot tests for test_new_tab_view on my desktop:
webbrowser_
webbrowser_
webbrowser_
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.
item.
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.
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
> 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.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1109
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://
- 1110. By Ugo Riboni
-
Merge changes from trunk
- 1111. By Ugo Riboni
-
Bump import to 2.4 in newly added unit test file
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1110
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://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1111
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
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).
- 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
Ugo Riboni (uriboni) wrote : | # |
All fixed and yes, the problem with TAB is caused by bug #1481233
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1112
http://
Executed test runs:
UNSTABLE: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 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
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1114
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://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1116
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://
Olivier Tilloy (osomon) wrote : | # |
I’m reliably getting 4 autopilot test failures on my desktop:
webbrowser_
webbrowser_
webbrowser_
webbrowser_
- 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
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1117
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Olivier Tilloy (osomon) wrote : | # |
Still seeing 3 autopilot failures on desktop:
webbrowser_
webbrowser_
webbrowser_
- 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
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1119
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://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1122
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://
Olivier Tilloy (osomon) wrote : | # |
This looks good now.
Preview Diff
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); |
FAILED: Continuous integration, rev:1075 jenkins. qa.ubuntu. com/job/ webbrowser- app-ci/ 2010/ jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- vivid-touch/ 3514/console jenkins. qa.ubuntu. com/job/ webbrowser- app-vivid- amd64-ci/ 764/console jenkins. qa.ubuntu. com/job/ webbrowser- app-vivid- armhf-ci/ 764/console jenkins. qa.ubuntu. com/job/ webbrowser- app-vivid- i386-ci/ 764/console jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- vivid-armhf/ 3511/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/ 2010/rebuild
http://