Merge lp:~osomon/webbrowser-app/newTabRefactoring-autopilot-tests into lp:webbrowser-app

Proposed by Olivier Tilloy
Status: Merged
Approved by: Olivier Tilloy
Approved revision: 914
Merged at revision: 1039
Proposed branch: lp:~osomon/webbrowser-app/newTabRefactoring-autopilot-tests
Merge into: lp:webbrowser-app
Prerequisite: lp:~rpadovani/webbrowser-app/newTabRefactoring
Diff against target: 2015 lines (+461/-1018)
23 files modified
src/app/webbrowser/Browser.qml (+7/-2)
src/app/webbrowser/CMakeLists.txt (+0/-4)
src/app/webbrowser/ExpandedHistoryView.qml (+12/-88)
src/app/webbrowser/HistoryView.qml (+46/-147)
src/app/webbrowser/NewTabView.qml (+32/-16)
src/app/webbrowser/UrlDelegate.qml (+21/-5)
src/app/webbrowser/UrlsList.qml (+13/-92)
src/app/webbrowser/history-domainlist-chronological-model.cpp (+6/-1)
src/app/webbrowser/history-domainlist-chronological-model.h (+4/-1)
src/app/webbrowser/top-sites-model.cpp (+4/-0)
src/app/webbrowser/top-sites-model.h (+2/-0)
src/app/webbrowser/upstreamcomponents/ListItemWithActions.qml (+0/-372)
src/app/webbrowser/upstreamcomponents/ListItemWithActionsCheckBox.qml (+0/-25)
src/app/webbrowser/upstreamcomponents/MultipleSelectionListView.qml (+0/-199)
src/app/webbrowser/upstreamcomponents/MultipleSelectionVisualModel.qml (+0/-31)
src/app/webbrowser/upstreamcomponents/README (+0/-20)
tests/autopilot/webbrowser_app/emulators/browser.py (+25/-7)
tests/autopilot/webbrowser_app/tests/__init__.py (+1/-1)
tests/autopilot/webbrowser_app/tests/test_new_tab_view.py (+274/-0)
tests/autopilot/webbrowser_app/tests/test_private.py (+1/-1)
tests/autopilot/webbrowser_app/tests/test_tabs.py (+3/-6)
tests/unittests/history-domainlist-chronological-model/tst_HistoryDomainListChronologicalModelTests.cpp (+5/-0)
tests/unittests/top-sites-model/tst_TopSitesModelTests.cpp (+5/-0)
To merge this branch: bzr merge lp:~osomon/webbrowser-app/newTabRefactoring-autopilot-tests
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Needs Fixing
Riccardo Padovani (community) Approve
Review via email: mp+260488@code.launchpad.net

Commit message

Remove the upstreamcomponents folder, and use components from the UITK instead.
Add autopilot tests for the new tab view.

To post a comment you must log in.
Revision history for this message
Riccardo Padovani (rpadovani) wrote :

Since LP Web UI doesn't work for MR I'm doing this review by mail,
and I'll take more time to check the diff later.

It seems to work well, autopilot tests work good, there aren't flake8 issues
and the code seems ok.

Great work Olivier :-)

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Riccardo Padovani (rpadovani) wrote :

Some things:

- onHistoryDomainRemoved: browser.historyModel.removeEntriesByDomain(domain)

Why do you remove the possibilty to delete an entire domain? Anyway, if you are sure about this, you should also remove the swype - atm you can swype the domain, but then when you click on the trash icon nothing happens.

In the ExpandedHistoryView there isn't anymore the multiple selection - I think we should be consistent and have it (or don't have it) both in ExpandedHistoryView and HistoryView

review: Needs Fixing
911. By Olivier Tilloy

Fix embarassing regression…

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

> Some things:
>
> - onHistoryDomainRemoved:
> browser.historyModel.removeEntriesByDomain(domain)
>
> Why do you remove the possibilty to delete an entire domain? Anyway, if you
> are sure about this, you should also remove the swype - atm you can swype the
> domain, but then when you click on the trash icon nothing happens.

Good catch! This is something I overlooked, I just pushed a new revision that fixes it.

> In the ExpandedHistoryView there isn't anymore the multiple selection - I
> think we should be consistent and have it (or don't have it) both in
> ExpandedHistoryView and HistoryView

We never had multiple selection in the expanded history view, so this is not a regression. If you think we should have it, feel free to file a bug against webbrowser-app and ubuntu-ux to have design comment on the idea.

Revision history for this message
Riccardo Padovani (rpadovani) wrote :

Looks good now then, thanks :-)

I opened bug #1459982 about multiple selection in history view

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

Also emit countChanged() when the model has been reset.

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

Fix invalid indices in for loop.

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

When in multiple selection mode, clicking a domain (de)selects it instead of expanding it.

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/app/webbrowser/Browser.qml'
--- src/app/webbrowser/Browser.qml 2015-06-02 14:24:15 +0000
+++ src/app/webbrowser/Browser.qml 2015-06-02 14:24:15 +0000
@@ -221,6 +221,7 @@
221 NewTabView {221 NewTabView {
222 historyModel: browser.historyModel222 historyModel: browser.historyModel
223 bookmarksModel: browser.bookmarksModel223 bookmarksModel: browser.bookmarksModel
224 settingsObject: settings
224 onBookmarkClicked: {225 onBookmarkClicked: {
225 chrome.requestedUrl = url226 chrome.requestedUrl = url
226 currentWebview.url = url227 currentWebview.url = url
@@ -624,7 +625,6 @@
624 var view = expandedHistoryViewComponent.createObject(historyViewContainer, {model: model})625 var view = expandedHistoryViewComponent.createObject(historyViewContainer, {model: model})
625 view.onHistoryEntryClicked.connect(destroy)626 view.onHistoryEntryClicked.connect(destroy)
626 }627 }
627 onHistoryDomainRemoved: browser.historyModel.removeEntriesByDomain(domain)
628 onDone: destroy()628 onDone: destroy()
629 }629 }
630 }630 }
@@ -639,7 +639,12 @@
639 browser.openUrlInNewTab(url, true)639 browser.openUrlInNewTab(url, true)
640 done()640 done()
641 }641 }
642 onHistoryEntryRemoved: browser.historyModel.removeEntryByUrl(url)642 onHistoryEntryRemoved: {
643 if (count == 1) {
644 done()
645 }
646 browser.historyModel.removeEntryByUrl(url)
647 }
643 onDone: destroy()648 onDone: destroy()
644 }649 }
645 }650 }
646651
=== modified file 'src/app/webbrowser/CMakeLists.txt'
--- src/app/webbrowser/CMakeLists.txt 2015-04-28 23:22:57 +0000
+++ src/app/webbrowser/CMakeLists.txt 2015-06-02 14:24:15 +0000
@@ -50,10 +50,6 @@
50 DESTINATION ${CMAKE_INSTALL_DATADIR}/webbrowser-app/webbrowser50 DESTINATION ${CMAKE_INSTALL_DATADIR}/webbrowser-app/webbrowser
51 FILES_MATCHING PATTERN *.png)51 FILES_MATCHING PATTERN *.png)
5252
53install(DIRECTORY upstreamcomponents
54 DESTINATION ${CMAKE_INSTALL_DATADIR}/webbrowser-app/webbrowser
55 FILES_MATCHING PATTERN *.qml)
56
57install(DIRECTORY searchengines53install(DIRECTORY searchengines
58 DESTINATION ${CMAKE_INSTALL_DATADIR}/webbrowser-app/webbrowser54 DESTINATION ${CMAKE_INSTALL_DATADIR}/webbrowser-app/webbrowser
59 FILES_MATCHING PATTERN *.xml)55 FILES_MATCHING PATTERN *.xml)
6056
=== modified file 'src/app/webbrowser/ExpandedHistoryView.qml'
--- src/app/webbrowser/ExpandedHistoryView.qml 2015-03-20 12:19:51 +0000
+++ src/app/webbrowser/ExpandedHistoryView.qml 2015-06-02 14:24:15 +0000
@@ -24,6 +24,7 @@
24 id: expandedHistoryView24 id: expandedHistoryView
2525
26 property alias model: entriesListView.model26 property alias model: entriesListView.model
27 property alias count: entriesListView.count
2728
28 signal historyEntryClicked(url url)29 signal historyEntryClicked(url url)
29 signal historyEntryRemoved(url url)30 signal historyEntryRemoved(url url)
@@ -37,19 +38,22 @@
37 ListView {38 ListView {
38 id: entriesListView39 id: entriesListView
3940
40 property var _currentSwipedItem: null
41
42 anchors {41 anchors {
43 top: header.bottom42 top: header.bottom
44 bottom: parent.bottom43 bottom: parent.bottom
45 left: parent.left44 left: parent.left
46 right: parent.right45 right: parent.right
47 margins: units.gu(2)46 margins: units.gu(1.5)
47 leftMargin: 0
48 }48 }
4949
50 section.property: "lastVisitDate"50 section.property: "lastVisitDate"
51 section.delegate: HistorySectionDelegate {51 section.delegate: HistorySectionDelegate {
52 width: parent.width52 anchors {
53 left: parent.left
54 leftMargin: units.gu(1.5)
55 right: parent.right
56 }
53 }57 }
5458
55 delegate: UrlDelegate {59 delegate: UrlDelegate {
@@ -61,91 +65,12 @@
61 title: model.title65 title: model.title
62 icon: model.icon66 icon: model.icon
6367
64 property var removalAnimation68 onClicked: expandedHistoryView.historyEntryClicked(model.url)
65 function remove() {69 onRemoved: expandedHistoryView.historyEntryRemoved(model.url)
66 removalAnimation.start()
67 }
68
69 onSwippingChanged: {
70 entriesListView._updateSwipeState(entriesDelegate)
71 }
72
73 onSwipeStateChanged: {
74 entriesListView._updateSwipeState(entriesDelegate)
75 }
76
77 leftSideAction: Action {
78 iconName: "delete"
79 text: i18n.tr("Delete")
80 onTriggered: {
81 entriesDelegate.remove()
82 }
83 }
84
85 ListView.onRemove: ScriptAction {
86 script: {
87 if (entriesListView._currentSwipedItem === entriesDelegate) {
88 entriesListView._currentSwipedItem = null
89 }
90 }
91 }
92
93 removalAnimation: SequentialAnimation {
94 alwaysRunToEnd: true
95
96 PropertyAction {
97 target: entriesDelegate
98 property: "ListView.delayRemove"
99 value: true
100 }
101
102 UbuntuNumberAnimation {
103 target: entriesDelegate
104 property: "height"
105 to: 0
106 }
107
108 PropertyAction {
109 target: entriesDelegate
110 property: "ListView.delayRemove"
111 value: false
112 }
113
114 ScriptAction {
115 script: {
116 if(entriesListView.count === 1) {
117 expandedHistoryView.done()
118 }
119 historyEntryRemoved(model.url)
120 }
121 }
122 }
123
124 onItemClicked: {
125 historyEntryClicked(model.url)
126 }
127 }
128
129 function _updateSwipeState(item) {
130 if (item.swipping) {
131 return
132 }
133
134 if (item.swipeState !== "Normal") {
135 if (entriesListView._currentSwipedItem !== item) {
136 if (entriesListView._currentSwipedItem) {
137 entriesListView._currentSwipedItem.resetSwipe()
138 }
139 entriesListView._currentSwipedItem = item
140 }
141 } else if (item.swipeState !== "Normal"
142 && entriesListView._currentSwipedItem === item) {
143 entriesListView._currentSwipedItem = null
144 }
145 }70 }
146 }71 }
14772
148 Rectangle {73 Item {
149 id: header74 id: header
15075
151 anchors {76 anchors {
@@ -155,8 +80,6 @@
155 }80 }
156 height: units.gu(8)81 height: units.gu(8)
15782
158 color: "#f6f6f6"
159
160 Rectangle {83 Rectangle {
161 anchors {84 anchors {
162 left: parent.left85 left: parent.left
@@ -178,6 +101,7 @@
178 icon: expandedHistoryView.model.lastVisitedIcon101 icon: expandedHistoryView.model.lastVisitedIcon
179 title: expandedHistoryView.model.domain102 title: expandedHistoryView.model.domain
180 url: i18n.tr("%1 page", "%1 pages", entriesListView.count).arg(entriesListView.count)103 url: i18n.tr("%1 page", "%1 pages", entriesListView.count).arg(entriesListView.count)
104 enabled: false
181 }105 }
182106
183 Button {107 Button {
184108
=== modified file 'src/app/webbrowser/HistoryView.qml'
--- src/app/webbrowser/HistoryView.qml 2015-03-20 12:19:51 +0000
+++ src/app/webbrowser/HistoryView.qml 2015-06-02 14:24:15 +0000
@@ -17,9 +17,8 @@
17 */17 */
1818
19import QtQuick 2.019import QtQuick 2.0
20import Ubuntu.Components 1.120import Ubuntu.Components 1.2
21import webbrowserapp.private 0.121import webbrowserapp.private 0.1
22import "upstreamcomponents"
2322
24Item {23Item {
25 id: historyView24 id: historyView
@@ -27,7 +26,6 @@
27 property alias historyModel: historyTimeframeModel.sourceModel26 property alias historyModel: historyTimeframeModel.sourceModel
2827
29 signal seeMoreEntriesClicked(var model)28 signal seeMoreEntriesClicked(var model)
30 signal historyDomainRemoved(var domain)
31 signal done()29 signal done()
3230
33 Rectangle {31 Rectangle {
@@ -35,37 +33,18 @@
35 color: "#f6f6f6"33 color: "#f6f6f6"
36 }34 }
3735
38 UbuntuNumberAnimation {36 ListView {
39 id: topBarOpenAnimation
40 target: topBar
41 property: "height"
42 to: units.gu(5)
43 alwaysRunToEnd: true
44 }
45
46 UbuntuNumberAnimation {
47 id: topBarCloseAnimation
48 target: topBar
49 property: "height"
50 to: 0
51 alwaysRunToEnd: true
52 }
53
54 MultipleSelectionListView {
55 id: domainsListView37 id: domainsListView
5638
57 property var _currentSwipedItem: null
58
59 anchors {39 anchors {
60 top: topBar.bottom40 top: topBar.bottom
61 left: parent.left41 left: parent.left
62 right: parent.right42 right: parent.right
63 bottom: toolbar.top43 bottom: toolbar.top
64 topMargin: units.gu(-0.5) // topMargin 2 - firstSection.topMargin 2.5
65 rightMargin: units.gu(2)44 rightMargin: units.gu(2)
66 }45 }
6746
68 listModel: HistoryDomainListChronologicalModel {47 model: HistoryDomainListChronologicalModel {
69 sourceModel: HistoryDomainListModel {48 sourceModel: HistoryDomainListModel {
70 sourceModel: HistoryTimeframeModel {49 sourceModel: HistoryTimeframeModel {
71 id: historyTimeframeModel50 id: historyTimeframeModel
@@ -80,17 +59,7 @@
80 anchors.leftMargin: units.gu(2)59 anchors.leftMargin: units.gu(2)
81 }60 }
8261
83 onSelectionDone: {62 delegate: UrlDelegate {
84 var domains = new Array();
85 for (var i=0; i < items.count; i++) {
86 domains[i] = items.get(i).model.domain
87 }
88 for (var i=0; i < domains.length; i++) {
89 historyView.historyDomainRemoved(domains[i])
90 }
91 }
92
93 listDelegate: UrlDelegate {
94 id: urlDelegate63 id: urlDelegate
95 width: parent.width64 width: parent.width
96 height: units.gu(5)65 height: units.gu(5)
@@ -99,111 +68,19 @@
99 url: lastVisitedTitle68 url: lastVisitedTitle
100 icon: model.lastVisitedIcon69 icon: model.lastVisitedIcon
10170
102 property var removalAnimation71 onClicked: {
103 function remove() {72 if (selectMode) {
104 removalAnimation.start()73 selected = !selected
105 }74 } else {
106
107 anchors {
108 left: parent.left
109 // we need to move left the favicon to align the favicon to
110 // other elements. Favicon has a container bigger than it.
111 // units.gu(3) it's the size of the favicon container
112 // units.dp(16) it's the size of the favicon
113 // the favicon is hCentered in the container
114 leftMargin: selectionMode ? - (units.gu(3) - units.dp(16)) / 2 : 0
115 }
116
117 selectionMode: domainsListView.isInSelectionMode
118 selected: domainsListView.isSelected(urlDelegate)
119
120 onSwippingChanged: {
121 domainsListView._updateSwipeState(urlDelegate)
122 }
123
124 onSwipeStateChanged: {
125 domainsListView._updateSwipeState(urlDelegate)
126 }
127
128 leftSideAction: Action {
129 iconName: "delete"
130 text: i18n.tr("Delete")
131 onTriggered: {
132 urlDelegate.remove()
133 }
134 }
135
136 ListView.onRemove: ScriptAction {
137 script: {
138 if (domainsListView._currentSwipedItem === urlDelegate) {
139 domainsListView._currentSwipedItem = null
140 }
141 }
142 }
143
144 removalAnimation: SequentialAnimation {
145 alwaysRunToEnd: true
146
147 PropertyAction {
148 target: urlDelegate
149 property: "ListView.delayRemove"
150 value: true
151 }
152
153 UbuntuNumberAnimation {
154 target: urlDelegate
155 property: "height"
156 to: 0
157 }
158
159 PropertyAction {
160 target: urlDelegate
161 property: "ListView.delayRemove"
162 value: false
163 }
164
165 ScriptAction {
166 script: {
167 historyView.historyDomainRemoved(model.domain)
168 }
169 }
170 }
171
172 onItemClicked: {
173 if (domainsListView.isInSelectionMode) {
174 if (!domainsListView.selectItem(urlDelegate)) {
175 domainsListView.deselectItem(urlDelegate)
176 }
177 }
178 else {
179 historyView.seeMoreEntriesClicked(model.entries)75 historyView.seeMoreEntriesClicked(model.entries)
180 }76 }
181 }77 }
182 onItemPressAndHold: {78 onRemoved: historyView.historyModel.removeEntriesByDomain(model.domain)
183 domainsListView.startSelection()79 onPressAndHold: {
184 domainsListView.selectItem(urlDelegate)80 selectMode = !selectMode
185 }81 if (selectMode) {
186 }82 domainsListView.ViewItems.selectedIndices = [index]
187
188 /*
189 * Functions for manage swype and multiple selection together
190 * Developed upstream
191 */
192 function _updateSwipeState(item) {
193 if (item.swipping) {
194 return
195 }
196
197 if (item.swipeState !== "Normal") {
198 if (domainsListView._currentSwipedItem !== item) {
199 if (domainsListView._currentSwipedItem) {
200 domainsListView._currentSwipedItem.resetSwipe()
201 }
202 domainsListView._currentSwipedItem = item
203 }83 }
204 } else if (item.swipeState !== "Normal"
205 && domainsListView._currentSwipedItem === item) {
206 domainsListView._currentSwipedItem = null
207 }84 }
208 }85 }
209 }86 }
@@ -253,11 +130,19 @@
253130
254 Item {131 Item {
255 id: topBar132 id: topBar
256 visible: domainsListView.isInSelectionMode133
257134 visible: domainsListView.ViewItems.selectMode
258 onVisibleChanged: visible ? topBarOpenAnimation.start() : topBarCloseAnimation.start()135 height: visible ? units.gu(5) : 0
259136
260 anchors { left: parent.left; right: parent.right; top: parent.top }137 Behavior on height {
138 UbuntuNumberAnimation {}
139 }
140
141 anchors {
142 left: parent.left
143 right: parent.right
144 top: parent.top
145 }
261146
262 Rectangle {147 Rectangle {
263 width: parent.width148 width: parent.width
@@ -281,7 +166,7 @@
281166
282 MouseArea {167 MouseArea {
283 anchors.fill: parent168 anchors.fill: parent
284 onClicked: domainsListView.cancelSelection()169 onClicked: domainsListView.ViewItems.selectMode = false
285 }170 }
286171
287 anchors.left: parent.left172 anchors.left: parent.left
@@ -297,10 +182,14 @@
297 MouseArea {182 MouseArea {
298 anchors.fill: parent183 anchors.fill: parent
299 onClicked: {184 onClicked: {
300 if (domainsListView.selectedItems.count === domainsListView.count) {185 if (domainsListView.ViewItems.selectedIndices.length === domainsListView.count) {
301 domainsListView.clearSelection()186 domainsListView.ViewItems.selectedIndices = []
302 } else {187 } else {
303 domainsListView.selectAll()188 var indices = []
189 for (var i = 0; i < domainsListView.count; ++i) {
190 indices.push(i)
191 }
192 domainsListView.ViewItems.selectedIndices = indices
304 }193 }
305 }194 }
306 }195 }
@@ -319,11 +208,21 @@
319208
320 iconName: "delete"209 iconName: "delete"
321 text: i18n.tr("Delete")210 text: i18n.tr("Delete")
322 enabled: domainsListView.selectedItems.count > 0211 enabled: domainsListView.ViewItems.selectedIndices.length > 0
323212
324 MouseArea {213 MouseArea {
325 anchors.fill: parent214 anchors.fill: parent
326 onClicked: domainsListView.endSelection()215 onClicked: {
216 var indices = domainsListView.ViewItems.selectedIndices
217 var domains = []
218 for (var i in indices) {
219 domains.push(domainsListView.model.get(indices[i]))
220 }
221 domainsListView.ViewItems.selectMode = false
222 for (var j in domains) {
223 historyModel.removeEntriesByDomain(domains[j])
224 }
225 }
327 }226 }
328227
329 anchors.right: parent.right228 anchors.right: parent.right
330229
=== modified file 'src/app/webbrowser/NewTabView.qml'
--- src/app/webbrowser/NewTabView.qml 2015-06-02 14:24:15 +0000
+++ src/app/webbrowser/NewTabView.qml 2015-06-02 14:24:15 +0000
@@ -17,8 +17,8 @@
17 */17 */
1818
19import QtQuick 2.019import QtQuick 2.0
20import Ubuntu.Components 1.120import Qt.labs.settings 1.0
21import Ubuntu.Components.ListItems 1.0 as ListItem21import Ubuntu.Components 1.2
22import webbrowserapp.private 0.122import webbrowserapp.private 0.1
23import ".."23import ".."
2424
@@ -27,6 +27,7 @@
2727
28 property QtObject bookmarksModel28 property QtObject bookmarksModel
29 property alias historyModel: historyTimeframeModel.sourceModel29 property alias historyModel: historyTimeframeModel.sourceModel
30 property Settings settingsObject
3031
31 signal bookmarkClicked(url url)32 signal bookmarkClicked(url url)
32 signal bookmarkRemoved(url url)33 signal bookmarkRemoved(url url)
@@ -45,7 +46,6 @@
45 property bool seeMoreBookmarksView: bookmarksCountLimit > 446 property bool seeMoreBookmarksView: bookmarksCountLimit > 4
46 property int bookmarksCountLimit: Math.min(4, numberOfBookmarks)47 property int bookmarksCountLimit: Math.min(4, numberOfBookmarks)
47 property int numberOfBookmarks: bookmarksModel ? bookmarksModel.count : 048 property int numberOfBookmarks: bookmarksModel ? bookmarksModel.count : 0
48 property int numberOfTopSites: historyModel ? historyModel.count : 0
4949
50 // Force the topsites section to reappear when remove a bookmark while50 // Force the topsites section to reappear when remove a bookmark while
51 // the bookmarks list is expanded and there aren't anymore > 551 // the bookmarks list is expanded and there aren't anymore > 5
@@ -72,7 +72,6 @@
72 id: contentColumn72 id: contentColumn
73 anchors {73 anchors {
74 left: parent.left74 left: parent.left
75 leftMargin: units.gu(1.5)
76 right: parent.right75 right: parent.right
77 rightMargin: units.gu(1.5)76 rightMargin: units.gu(1.5)
78 }77 }
@@ -80,7 +79,11 @@
8079
81 Row {80 Row {
82 height: units.gu(6)81 height: units.gu(6)
83 anchors { left: parent.left; right: parent.right }82 anchors {
83 left: parent.left
84 leftMargin: units.gu(1.5)
85 right: parent.right
86 }
84 spacing: units.gu(1.5)87 spacing: units.gu(1.5)
8588
86 Icon {89 Icon {
@@ -108,6 +111,7 @@
108111
109 Button {112 Button {
110 id: moreButton113 id: moreButton
114 objectName: "bookmarks.moreButton"
111 height: parent.height - units.gu(2)115 height: parent.height - units.gu(2)
112116
113 anchors { top: parent.top; topMargin: units.gu(1) }117 anchors { top: parent.top; topMargin: units.gu(1) }
@@ -129,7 +133,11 @@
129133
130 Rectangle {134 Rectangle {
131 height: units.gu(0.1)135 height: units.gu(0.1)
132 anchors { left: parent.left; right: parent.right }136 anchors {
137 left: parent.left
138 leftMargin: units.gu(1.5)
139 right: parent.right
140 }
133 color: "#d3d3d3"141 color: "#d3d3d3"
134 }142 }
135143
@@ -137,7 +145,6 @@
137 id: bookmarksColumn145 id: bookmarksColumn
138 anchors {146 anchors {
139 left: parent.left147 left: parent.left
140 leftMargin: units.gu(-1.5)
141 right: parent.right148 right: parent.right
142 }149 }
143150
@@ -147,7 +154,7 @@
147 spacing: 0154 spacing: 0
148155
149 UrlDelegate {156 UrlDelegate {
150 id: homepageBookmark157 objectName: "homepageBookmark"
151 anchors {158 anchors {
152 left: parent.left159 left: parent.left
153 right: parent.right160 right: parent.right
@@ -156,12 +163,14 @@
156163
157 title: i18n.tr('Homepage')164 title: i18n.tr('Homepage')
158165
159 url: settings.homepage166 leadingActions: null
160 onItemClicked: newTabView.bookmarkClicked(url)167
168 url: newTabView.settingsObject.homepage
169 onClicked: newTabView.bookmarkClicked(url)
161 }170 }
162171
163 UrlsList {172 UrlsList {
164 id: bookmarksList173 objectName: "bookmarksList"
165 anchors {174 anchors {
166 left: parent.left175 left: parent.left
167 right: parent.right176 right: parent.right
@@ -177,13 +186,13 @@
177 }186 }
178 }187 }
179188
180 Rectangle {189 Item {
181 height: units.gu(6)190 height: units.gu(6)
182 anchors {191 anchors {
183 left: parent.left192 left: parent.left
193 leftMargin: units.gu(1.5)
184 right: parent.right194 right: parent.right
185 }195 }
186 color: "#f6f6f6"
187196
188 Label {197 Label {
189 anchors {198 anchors {
@@ -203,7 +212,11 @@
203212
204 Rectangle {213 Rectangle {
205 height: units.gu(0.1)214 height: units.gu(0.1)
206 anchors { left: parent.left; right: parent.right }215 anchors {
216 left: parent.left
217 leftMargin: units.gu(1.5)
218 right: parent.right
219 }
207 color: "#d3d3d3"220 color: "#d3d3d3"
208221
209 opacity: internal.seeMoreBookmarksView ? 0.0 : 1.0222 opacity: internal.seeMoreBookmarksView ? 0.0 : 1.0
@@ -211,12 +224,14 @@
211 }224 }
212225
213 Label {226 Label {
227 objectName: "notopsites"
228
214 height: units.gu(11)229 height: units.gu(11)
215 anchors {230 anchors {
216 left: parent.left231 left: parent.left
217 right: parent.right232 right: parent.right
218 }233 }
219 visible: internal.numberOfTopSites === 0234 visible: topSitesModel.count == 0
220235
221 horizontalAlignment: Text.AlignHCenter236 horizontalAlignment: Text.AlignHCenter
222 verticalAlignment: Text.AlignVCenter237 verticalAlignment: Text.AlignVCenter
@@ -226,14 +241,15 @@
226 }241 }
227242
228 UrlsList {243 UrlsList {
244 objectName: "topSitesList"
229 anchors {245 anchors {
230 left: parent.left246 left: parent.left
231 leftMargin: units.gu(-1.5)
232 right: parent.right247 right: parent.right
233 }248 }
234249
235 opacity: internal.seeMoreBookmarksView ? 0.0 : 1.0250 opacity: internal.seeMoreBookmarksView ? 0.0 : 1.0
236 Behavior on opacity { UbuntuNumberAnimation {} }251 Behavior on opacity { UbuntuNumberAnimation {} }
252 visible: opacity > 0
237253
238 limit: 10254 limit: 10
239 spacing: 0255 spacing: 0
240256
=== modified file 'src/app/webbrowser/UrlDelegate.qml'
--- src/app/webbrowser/UrlDelegate.qml 2015-03-20 12:19:51 +0000
+++ src/app/webbrowser/UrlDelegate.qml 2015-06-02 14:24:15 +0000
@@ -17,20 +17,26 @@
17 */17 */
1818
19import QtQuick 2.019import QtQuick 2.0
20import Ubuntu.Components 1.120import Ubuntu.Components 1.2
21import ".."21import ".."
22import "upstreamcomponents"
2322
24ListItemWithActions {23ListItem {
25 id: urlDelegate24 id: urlDelegate
2625
27 property alias icon: icon.source26 property alias icon: icon.source
28 property alias title: title.text27 property alias title: title.text
29 property alias url: url.text28 property alias url: url.text
30 color: "#f6f6f6"29
30 divider.visible: false
31
32 signal removed()
3133
32 Row {34 Row {
33 anchors.verticalCenter: parent.verticalCenter35 anchors {
36 verticalCenter: parent.verticalCenter
37 left: parent.left
38 leftMargin: units.gu(1.5)
39 }
34 spacing: units.gu(1)40 spacing: units.gu(1)
3541
36 UbuntuShape {42 UbuntuShape {
@@ -69,4 +75,14 @@
69 }75 }
70 }76 }
71 }77 }
78
79 leadingActions: ListItemActions {
80 actions: [
81 Action {
82 objectName: "leadingAction.delete"
83 iconName: "delete"
84 onTriggered: urlDelegate.removed()
85 }
86 ]
87 }
72}88}
7389
=== modified file 'src/app/webbrowser/UrlsList.qml'
--- src/app/webbrowser/UrlsList.qml 2015-06-02 14:24:15 +0000
+++ src/app/webbrowser/UrlsList.qml 2015-06-02 14:24:15 +0000
@@ -21,6 +21,7 @@
2121
22Column {22Column {
23 id: urlsList23 id: urlsList
24
24 property alias model: urlsListRepeater.model25 property alias model: urlsListRepeater.model
25 property int limit26 property int limit
2627
@@ -29,102 +30,22 @@
2930
30 spacing: units.gu(1)31 spacing: units.gu(1)
3132
32 move: Transition { UbuntuNumberAnimation { properties: "x, y" } }
33
34 Repeater {33 Repeater {
35 id: urlsListRepeater34 id: urlsListRepeater
36 property var _currentSwipedItem: null
3735
38 delegate: Loader {36 delegate: Loader {
39 sourceComponent: (index < limit) ? realDelegate : undefined37 active: index < limit
40 Component {38 sourceComponent: UrlDelegate{
41 id: realDelegate39 id: urlDelegate
42 UrlDelegate{40 width: urlsList.width
43 id: urlDelegate41 height: units.gu(5)
44 width: urlsList.width42
45 height: units.gu(5)43 icon: model.icon
4644 title: model.title ? model.title : model.url
47 icon: model.icon45 url: model.url
48 title: model.title ? model.title : model.url46
49 url: model.url47 onClicked: urlsList.urlClicked(model.url)
5048 onRemoved: urlsList.urlRemoved(model.url)
51 onItemClicked: urlClicked(model.url)
52
53 property var removalAnimation
54 function remove() {
55 removalAnimation.start()
56 }
57
58 onSwippingChanged: {
59 urlsListRepeater._updateSwipeState(urlDelegate)
60 }
61
62 onSwipeStateChanged: {
63 urlsListRepeater._updateSwipeState(urlDelegate)
64 }
65
66 leftSideAction: Action {
67 iconName: "delete"
68 text: i18n.tr("Delete")
69 onTriggered: {
70 urlDelegate.remove()
71 }
72 }
73
74 ListView.onRemove: ScriptAction {
75 script: {
76 if (urlsListRepeater._currentSwipedItem === urlDelegate) {
77 urlsListRepeater._currentSwipedItem = null
78 }
79 }
80 }
81
82 removalAnimation: SequentialAnimation {
83 alwaysRunToEnd: true
84
85 PropertyAction {
86 target: urlDelegate
87 property: "ListView.delayRemove"
88 value: true
89 }
90
91 UbuntuNumberAnimation {
92 target: urlDelegate
93 property: "height"
94 to: 0
95 }
96
97 PropertyAction {
98 target: urlDelegate
99 property: "ListView.delayRemove"
100 value: false
101 }
102
103 ScriptAction {
104 script: {
105 urlRemoved(model.url)
106 }
107 }
108 }
109 }
110 }
111 }
112
113 function _updateSwipeState(item) {
114 if (item.swipping) {
115 return
116 }
117
118 if (item.swipeState !== "Normal") {
119 if (urlsListRepeater._currentSwipedItem !== item) {
120 if (urlsListRepeater._currentSwipedItem) {
121 urlsListRepeater._currentSwipedItem.resetSwipe()
122 }
123 urlsListRepeater._currentSwipedItem = item
124 }
125 } else if (item.swipeState !== "Normal"
126 && urlsListRepeater._currentSwipedItem === item) {
127 urlsListRepeater._currentSwipedItem = null
128 }49 }
129 }50 }
130 }51 }
13152
=== modified file 'src/app/webbrowser/history-domainlist-chronological-model.cpp'
--- src/app/webbrowser/history-domainlist-chronological-model.cpp 2014-03-12 10:59:54 +0000
+++ src/app/webbrowser/history-domainlist-chronological-model.cpp 2015-06-02 14:24:15 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright 2013 Canonical Ltd.2 * Copyright 2013-2015 Canonical Ltd.
3 *3 *
4 * This file is part of webbrowser-app.4 * This file is part of webbrowser-app.
5 *5 *
@@ -48,3 +48,8 @@
48 Q_EMIT sourceModelChanged();48 Q_EMIT sourceModelChanged();
49 }49 }
50}50}
51
52QString HistoryDomainListChronologicalModel::get(int index) const
53{
54 return data(this->index(index, 0), HistoryDomainListModel::Domain).toString();
55}
5156
=== modified file 'src/app/webbrowser/history-domainlist-chronological-model.h'
--- src/app/webbrowser/history-domainlist-chronological-model.h 2014-03-12 10:59:54 +0000
+++ src/app/webbrowser/history-domainlist-chronological-model.h 2015-06-02 14:24:15 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright 2013 Canonical Ltd.2 * Copyright 2013-2015 Canonical Ltd.
3 *3 *
4 * This file is part of webbrowser-app.4 * This file is part of webbrowser-app.
5 *5 *
@@ -21,6 +21,7 @@
2121
22// Qt22// Qt
23#include <QtCore/QSortFilterProxyModel>23#include <QtCore/QSortFilterProxyModel>
24#include <QtCore/QString>
2425
25class HistoryDomainListModel;26class HistoryDomainListModel;
2627
@@ -36,6 +37,8 @@
36 HistoryDomainListModel* sourceModel() const;37 HistoryDomainListModel* sourceModel() const;
37 void setSourceModel(HistoryDomainListModel* sourceModel);38 void setSourceModel(HistoryDomainListModel* sourceModel);
3839
40 Q_INVOKABLE QString get(int index) const;
41
39Q_SIGNALS:42Q_SIGNALS:
40 void sourceModelChanged() const;43 void sourceModelChanged() const;
41};44};
4245
=== modified file 'src/app/webbrowser/top-sites-model.cpp'
--- src/app/webbrowser/top-sites-model.cpp 2015-04-09 14:55:14 +0000
+++ src/app/webbrowser/top-sites-model.cpp 2015-06-02 14:24:15 +0000
@@ -34,6 +34,9 @@
34 setDynamicSortFilter(true);34 setDynamicSortFilter(true);
35 setSortRole(HistoryModel::Visits);35 setSortRole(HistoryModel::Visits);
36 sort(0, Qt::DescendingOrder);36 sort(0, Qt::DescendingOrder);
37 connect(this, SIGNAL(rowsInserted(const QModelIndex&, int, int)), SIGNAL(countChanged()));
38 connect(this, SIGNAL(rowsRemoved(const QModelIndex&, int, int)), SIGNAL(countChanged()));
39 connect(this, SIGNAL(modelReset()), SIGNAL(countChanged()));
37}40}
3841
39HistoryTimeframeModel* TopSitesModel::sourceModel() const42HistoryTimeframeModel* TopSitesModel::sourceModel() const
@@ -46,6 +49,7 @@
46 if (sourceModel != this->sourceModel()) {49 if (sourceModel != this->sourceModel()) {
47 QSortFilterProxyModel::setSourceModel(sourceModel);50 QSortFilterProxyModel::setSourceModel(sourceModel);
48 Q_EMIT sourceModelChanged();51 Q_EMIT sourceModelChanged();
52 Q_EMIT countChanged();
49 }53 }
50}54}
5155
5256
=== modified file 'src/app/webbrowser/top-sites-model.h'
--- src/app/webbrowser/top-sites-model.h 2015-04-08 22:17:08 +0000
+++ src/app/webbrowser/top-sites-model.h 2015-06-02 14:24:15 +0000
@@ -29,6 +29,7 @@
29 Q_OBJECT29 Q_OBJECT
3030
31 Q_PROPERTY(HistoryTimeframeModel* sourceModel READ sourceModel WRITE setSourceModel NOTIFY sourceModelChanged)31 Q_PROPERTY(HistoryTimeframeModel* sourceModel READ sourceModel WRITE setSourceModel NOTIFY sourceModelChanged)
32 Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
3233
33public:34public:
34 TopSitesModel(QObject* parent=0);35 TopSitesModel(QObject* parent=0);
@@ -38,6 +39,7 @@
3839
39Q_SIGNALS:40Q_SIGNALS:
40 void sourceModelChanged() const;41 void sourceModelChanged() const;
42 void countChanged() const;
4143
42protected:44protected:
43 // reimplemented from QSortFilterProxyModel45 // reimplemented from QSortFilterProxyModel
4446
=== removed directory 'src/app/webbrowser/upstreamcomponents'
=== removed file 'src/app/webbrowser/upstreamcomponents/ListItemWithActions.qml'
--- src/app/webbrowser/upstreamcomponents/ListItemWithActions.qml 2015-02-03 18:32:52 +0000
+++ src/app/webbrowser/upstreamcomponents/ListItemWithActions.qml 1970-01-01 00:00:00 +0000
@@ -1,372 +0,0 @@
1/*
2 * Copyright (C) 2012-2014 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17import QtQuick 2.0
18import Ubuntu.Components 1.1
19
20Item {
21 id: root
22
23 property Action leftSideAction: null
24 property list<Action> rightSideActions
25 property double defaultHeight: units.gu(8)
26 property bool locked: false
27 property Action activeAction: null
28 property var activeItem: null
29 property bool triggerActionOnMouseRelease: false
30 property color color: Theme.palette.normal.background
31 property color selectedColor: "#E6E6E6"
32 property bool selected: false
33 property bool selectionMode: false
34 property alias internalAnchors: mainContents.anchors
35 default property alias contents: mainContents.children
36
37 readonly property double actionWidth: units.gu(5)
38 readonly property double leftActionWidth: units.gu(10)
39 readonly property double actionThreshold: actionWidth * 0.4
40 readonly property double threshold: 0.4
41 readonly property string swipeState: main.x == 0 ? "Normal" : main.x > 0 ? "LeftToRight" : "RightToLeft"
42 readonly property alias swipping: mainItemMoving.running
43
44 signal itemClicked(var mouse)
45 signal itemPressAndHold(var mouse)
46
47 function returnToBoundsRTL()
48 {
49 var actionFullWidth = actionWidth + units.gu(2)
50 var xOffset = Math.abs(main.x)
51 var index = Math.min(Math.floor(xOffset / actionFullWidth), rightSideActions.length)
52
53 if (index < 1) {
54 main.x = 0
55 } else if (index === rightSideActions.length) {
56 main.x = -rightActionsView.width
57 } else {
58 main.x = -(actionFullWidth * index)
59 }
60 }
61
62 function returnToBoundsLTR()
63 {
64 var finalX = leftActionWidth
65 if (main.x > (finalX * root.threshold))
66 main.x = finalX
67 else
68 main.x = 0
69 }
70
71 function returnToBounds()
72 {
73 if (main.x < 0) {
74 returnToBoundsRTL()
75 } else if (main.x > 0) {
76 returnToBoundsLTR()
77 }
78 }
79
80 function contains(item, point)
81 {
82 return (point.x >= item.x) && (point.x <= (item.x + item.width)) && (point.y >= item.y) && (point.y <= (item.y + item.height));
83 }
84
85 function getActionAt(point)
86 {
87 if (contains(leftActionView, point)) {
88 return leftSideAction
89 } else if (contains(rightActionsView, point)) {
90 var newPoint = root.mapToItem(rightActionsView, point.x, point.y)
91 for (var i = 0; i < rightActionsRepeater.count; i++) {
92 var child = rightActionsRepeater.itemAt(i)
93 if (contains(child, newPoint)) {
94 return i
95 }
96 }
97 }
98 return -1
99 }
100
101 function updateActiveAction()
102 {
103 if ((main.x <= -root.actionWidth) &&
104 (main.x > -rightActionsView.width)) {
105 var actionFullWidth = actionWidth + units.gu(2)
106 var xOffset = Math.abs(main.x)
107 var index = Math.min(Math.floor(xOffset / actionFullWidth), rightSideActions.length)
108 index = index - 1
109 if (index > -1) {
110 root.activeItem = rightActionsRepeater.itemAt(index)
111 root.activeAction = root.rightSideActions[index]
112 }
113 } else {
114 root.activeAction = null
115 }
116 }
117
118 function resetSwipe()
119 {
120 main.x = 0
121 }
122
123 states: [
124 State {
125 name: "select"
126 when: selectionMode || selected
127 PropertyChanges {
128 target: selectionIcon
129 source: Qt.resolvedUrl("ListItemWithActionsCheckBox.qml")
130 anchors.leftMargin: units.gu(2)
131 }
132 PropertyChanges {
133 target: root
134 locked: true
135 }
136 PropertyChanges {
137 target: main
138 x: 0
139 }
140 }
141 ]
142
143 height: defaultHeight
144 clip: height !== defaultHeight
145
146 Rectangle {
147 id: leftActionView
148
149 anchors {
150 top: parent.top
151 bottom: parent.bottom
152 right: main.left
153 }
154 width: root.leftActionWidth + actionThreshold
155 visible: leftSideAction
156 color: "red"
157
158 Icon {
159 anchors {
160 centerIn: parent
161 horizontalCenterOffset: actionThreshold / 2
162 }
163 name: leftSideAction ? leftSideAction.iconName : ""
164 color: Theme.palette.selected.field
165 height: units.gu(3)
166 width: units.gu(3)
167 }
168 }
169
170 Item {
171 id: rightActionsView
172
173 anchors {
174 top: main.top
175 left: main.right
176 leftMargin: units.gu(1)
177 bottom: main.bottom
178 }
179 visible: rightSideActions.length > 0
180 width: rightActionsRepeater.count > 0 ? rightActionsRepeater.count * (root.actionWidth + units.gu(2)) + actionThreshold : 0
181 Row {
182 anchors.fill: parent
183 spacing: units.gu(2)
184 Repeater {
185 id: rightActionsRepeater
186
187 model: rightSideActions
188 Item {
189 property alias image: img
190
191 anchors {
192 top: parent.top
193 bottom: parent.bottom
194 }
195 width: root.actionWidth
196
197 Icon {
198 id: img
199
200 anchors.centerIn: parent
201 width: units.gu(3)
202 height: units.gu(3)
203 name: iconName
204 color: root.activeAction === modelData || !root.triggerActionOnMouseRelease ? UbuntuColors.lightAubergine : Theme.palette.selected.background
205 }
206 }
207 }
208 }
209 }
210
211
212 Rectangle {
213 id: main
214 objectName: "mainItem"
215
216 anchors {
217 top: parent.top
218 bottom: parent.bottom
219 }
220
221 width: parent.width
222 color: mouseArea.pressed && swipeState === "Normal" ? root.selectedColor : root.color
223
224 Loader {
225 id: selectionIcon
226
227 anchors {
228 left: main.left
229 verticalCenter: main.verticalCenter
230 }
231 width: (status === Loader.Ready) ? item.implicitWidth : 0
232 visible: (status === Loader.Ready) && (item.width === item.implicitWidth)
233 Behavior on width {
234 NumberAnimation {
235 duration: UbuntuAnimation.SnapDuration
236 }
237 }
238 }
239
240
241 Item {
242 id: mainContents
243
244 anchors {
245 left: selectionIcon.right
246 leftMargin: units.gu(2)
247 top: parent.top
248 topMargin: units.gu(1)
249 right: parent.right
250 rightMargin: units.gu(2)
251 bottom: parent.bottom
252 bottomMargin: units.gu(1)
253 }
254 }
255
256 Behavior on x {
257 UbuntuNumberAnimation {
258 id: mainItemMoving
259
260 easing.type: Easing.OutElastic
261 duration: UbuntuAnimation.SlowDuration
262 }
263 }
264 Behavior on color {
265 enabled: (root.color != root.selectedColor)
266 ColorAnimation {}
267 }
268 }
269
270 SequentialAnimation {
271 id: triggerAction
272
273 property var currentItem: root.activeItem ? root.activeItem.image : null
274
275 running: false
276 ParallelAnimation {
277 UbuntuNumberAnimation {
278 target: triggerAction.currentItem
279 property: "opacity"
280 from: 1.0
281 to: 0.0
282 duration: UbuntuAnimation.SlowDuration
283 easing {type: Easing.InOutBack; }
284 }
285 UbuntuNumberAnimation {
286 target: triggerAction.currentItem
287 properties: "width, height"
288 from: units.gu(3)
289 to: root.actionWidth
290 duration: UbuntuAnimation.SlowDuration
291 easing {type: Easing.InOutBack; }
292 }
293 }
294 PropertyAction {
295 target: triggerAction.currentItem
296 properties: "width, height"
297 value: units.gu(3)
298 }
299 PropertyAction {
300 target: triggerAction.currentItem
301 properties: "opacity"
302 value: 1.0
303 }
304 ScriptAction {
305 script: root.activeAction.triggered(root)
306 }
307 PauseAnimation {
308 duration: 500
309 }
310 UbuntuNumberAnimation {
311 target: main
312 property: "x"
313 to: 0
314
315 }
316 }
317
318 MouseArea {
319 id: mouseArea
320
321 property bool locked: root.locked || ((root.leftSideAction === null) && (root.rightSideActions.count === 0))
322 property bool manual: false
323
324 anchors.fill: parent
325 drag {
326 target: locked ? null : main
327 axis: Drag.XAxis
328 minimumX: rightActionsView.visible ? -(rightActionsView.width + root.actionThreshold) : 0
329 maximumX: leftActionView.visible ? leftActionView.width : 0
330 }
331
332 onReleased: {
333 if (root.triggerActionOnMouseRelease && root.activeAction) {
334 triggerAction.start()
335 } else {
336 root.returnToBounds()
337 root.activeAction = null
338 }
339 }
340 onClicked: {
341 if (main.x === 0) {
342 root.itemClicked(mouse)
343 } else if (main.x > 0) {
344 var action = getActionAt(Qt.point(mouse.x, mouse.y))
345 if (action && action !== -1) {
346 action.triggered(root)
347 }
348 } else {
349 var actionIndex = getActionAt(Qt.point(mouse.x, mouse.y))
350 if (actionIndex !== -1) {
351 root.activeItem = rightActionsRepeater.itemAt(actionIndex)
352 root.activeAction = root.rightSideActions[actionIndex]
353 triggerAction.start()
354 return
355 }
356 }
357 root.resetSwipe()
358 }
359
360 onPositionChanged: {
361 if (mouseArea.pressed) {
362 updateActiveAction()
363 }
364 }
365 onPressAndHold: {
366 if (main.x === 0) {
367 root.itemPressAndHold(mouse)
368 }
369 }
370 z: -1
371 }
372}
3730
=== removed file 'src/app/webbrowser/upstreamcomponents/ListItemWithActionsCheckBox.qml'
--- src/app/webbrowser/upstreamcomponents/ListItemWithActionsCheckBox.qml 2014-10-15 09:38:37 +0000
+++ src/app/webbrowser/upstreamcomponents/ListItemWithActionsCheckBox.qml 1970-01-01 00:00:00 +0000
@@ -1,25 +0,0 @@
1/*
2 * Copyright (C) 2012-2014 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17import QtQuick 2.0
18import Ubuntu.Components 1.1
19
20CheckBox {
21 checked: root.selected
22 width: implicitWidth
23 // disable item mouse area to avoid conflicts with parent mouse area
24 __mouseArea.enabled: false
25}
260
=== removed file 'src/app/webbrowser/upstreamcomponents/MultipleSelectionListView.qml'
--- src/app/webbrowser/upstreamcomponents/MultipleSelectionListView.qml 2014-10-15 09:38:37 +0000
+++ src/app/webbrowser/upstreamcomponents/MultipleSelectionListView.qml 1970-01-01 00:00:00 +0000
@@ -1,199 +0,0 @@
1/*
2 * Copyright (C) 2013 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17import QtQuick 2.0
18import Ubuntu.Components 1.1
19import Ubuntu.Components.Popups 1.0 as Popups
20
21/*!
22 \qmltype ContactSimpleListView
23 \inqmlmodule Ubuntu.Contacts 0.1
24 \ingroup ubuntu
25 \brief The MultipleSelectionListView provides a ListView with support to multiple selection
26
27 The MultipleSelectionListViewprovides a ListView with support to multiple selection which can be used by any
28 application.
29
30 Example:
31 \qml
32 import Ubuntu.Contacts 0.1
33
34 MultipleSelectionListView {
35 id: view
36 anchors.fill: paret
37 model: 100
38 delegate: Rectangle {
39 width: parent.width
40 height: 100
41 color: view.selectedItems.indexOf(index) == -1 ? "white" : "blue"
42
43 MouseArea {
44 anchors.fill: parent
45 onClicked: {
46 if (view.isInSelectionModel) {
47 view.selectItem(index)
48 }
49 }
50 onPressAndHold: view.startSelection()
51 }
52 }
53 onSelectionDone: console.debug("Selected items:" + view.selectedItems)
54 }
55 \endqml
56*/
57
58ListView {
59 id: listView
60
61 /*!
62 \qmlproperty model selectedItems
63
64 This property holds the list of selected items
65 */
66 readonly property alias selectedItems: visualModel.selectedItems
67 /*!
68 \qmlproperty bool multipleSelection
69
70 This property holds if the selection will accept multiple items or single items
71 */
72 property bool multipleSelection: true
73
74 /*!
75 \qmlproperty model listModel
76
77 This property holds the model providing data for the list.
78 */
79 property alias listModel: visualModel.model
80 /*!
81 \qmlproperty Component listDelegate
82
83 The delegate provides a template defining each item instantiated by the view.
84 */
85 property alias listDelegate: visualModel.delegate
86
87 /*!
88 \qmlproperty bool isInSelectionMode
89
90 This property holds a list with the index of selected items
91 */
92 readonly property bool isInSelectionMode: state === "selection"
93 /*!
94 This handler is called when the selection mode is finished without be canceled
95 */
96 signal selectionDone(var items)
97 /*!
98 This handler is called when the selection mode is canceled
99 */
100 signal selectionCanceled()
101
102 /*!
103 Start the selection mode on the list view.
104 */
105 function startSelection()
106 {
107 state = "selection"
108 }
109 /*!
110 Check if the item is selected
111 Returns true if the item was marked as selected or false if the item is unselected
112 */
113 function isSelected(item)
114 {
115 if (item && item.VisualDataModel) {
116 return (item.VisualDataModel.inSelected === true)
117 } else {
118 return false
119 }
120 }
121 /*!
122 Mark the item as selected
123 Returns true if the item was marked as selected or false if the item is already selected
124 */
125 function selectItem(item)
126 {
127 if (item.VisualDataModel.inSelected) {
128 return false
129 } else {
130 if (!multipleSelection) {
131 clearSelection()
132 }
133 item.VisualDataModel.inSelected = true
134 return true
135 }
136 }
137 /*!
138 Remove the index from the selected list
139 */
140 function deselectItem(item)
141 {
142 var result = false
143 if (item.VisualDataModel.inSelected) {
144 item.VisualDataModel.inSelected = false
145 result = true
146 }
147 return result
148 }
149 /*!
150 Finish the selection mode with sucess
151 */
152 function endSelection()
153 {
154 selectionDone(listView.selectedItems)
155 clearSelection()
156 state = ""
157 }
158 /*!
159 Cancel the selection
160 */
161 function cancelSelection()
162 {
163 selectionCanceled()
164 clearSelection()
165 state = ""
166 }
167 /*!
168 Remove any selected item from the selection list
169 */
170 function clearSelection()
171 {
172 if (selectedItems.count > 0) {
173 selectedItems.remove(0, selectedItems.count)
174 }
175 }
176 /*!
177 Select all items in the list
178 */
179 function selectAll()
180 {
181 if (multipleSelection) {
182 visualModel.items.addGroups(0, visualModel.items.count, ["selected"] )
183 }
184 }
185
186 model: visualModel
187
188 MultipleSelectionVisualModel {
189 id: visualModel
190 }
191
192 Component.onCompleted: {
193 // FIXME: workaround for qtubuntu not returning values depending on the grid unit definition
194 // for Flickable.maximumFlickVelocity and Flickable.flickDeceleration
195 var scaleFactor = units.gridUnit / 8;
196 maximumFlickVelocity = maximumFlickVelocity * scaleFactor;
197 flickDeceleration = flickDeceleration * scaleFactor;
198 }
199}
2000
=== removed file 'src/app/webbrowser/upstreamcomponents/MultipleSelectionVisualModel.qml'
--- src/app/webbrowser/upstreamcomponents/MultipleSelectionVisualModel.qml 2014-10-15 09:38:37 +0000
+++ src/app/webbrowser/upstreamcomponents/MultipleSelectionVisualModel.qml 1970-01-01 00:00:00 +0000
@@ -1,31 +0,0 @@
1/*
2 * Copyright (C) 2012-2013 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17import QtQuick 2.0
18
19VisualDataModel {
20 id: contactVisualModel
21
22 property alias selectedItems: selectedGroup
23
24 groups: [
25 VisualDataGroup {
26 id: selectedGroup
27
28 name: "selected"
29 }
30 ]
31}
320
=== removed file 'src/app/webbrowser/upstreamcomponents/README'
--- src/app/webbrowser/upstreamcomponents/README 2014-10-09 17:41:02 +0000
+++ src/app/webbrowser/upstreamcomponents/README 1970-01-01 00:00:00 +0000
@@ -1,20 +0,0 @@
1# Upstream components
2
3This folder houses components that were taken from upstream applications like
4the Contacts App, Address Book etc. It is important to keep these files synced
5with upstream regularly. These components will be used app until they are made
6available in the Ubuntu SDK.
7
8# Links
9
10ListItemWithActions.qml
11https://bazaar.launchpad.net/~phablet-team/address-book-app/trunk/view/head:/src/imports/Ubuntu/Contacts/ListItemWithActions.qml
12
13ListItemWithActionsCheckBox.qml
14https://bazaar.launchpad.net/~phablet-team/address-book-app/trunk/view/head:/src/imports/Ubuntu/Contacts/ListItemWithActionsCheckBox.qml
15
16MultipleSelectionListView.qml
17https://bazaar.launchpad.net/~phablet-team/address-book-app/trunk/view/head:/src/imports/Ubuntu/Contacts/MultipleSelectionListView.qml
18
19MultipleSelectionVisualModel.qml
20https://bazaar.launchpad.net/~phablet-team/address-book-app/trunk/view/head:/src/imports/Ubuntu/Contacts/MultipleSelectionVisualModel.qml
210
=== modified file 'tests/autopilot/webbrowser_app/emulators/browser.py'
--- tests/autopilot/webbrowser_app/emulators/browser.py 2015-05-20 11:31:33 +0000
+++ tests/autopilot/webbrowser_app/emulators/browser.py 2015-06-02 14:24:15 +0000
@@ -361,14 +361,32 @@
361361
362class NewTabView(uitk.UbuntuUIToolkitCustomProxyObjectBase):362class NewTabView(uitk.UbuntuUIToolkitCustomProxyObjectBase):
363363
364 def get_top_sites(self):364 def get_bookmarks_more_button(self):
365 """Return a list of the top sites URLs."""365 return self.select_single("Button", objectName="bookmarks.moreButton")
366 top_sites_list = self.wait_select_single(366
367 UrlsList, objectName="topSitesList", visible=True)367 def get_homepage_bookmark(self):
368 return top_sites_list.get_url_list()368 return self.select_single(UrlDelegate, objectName="homepageBookmark")
369
370 def get_bookmarks_list(self):
371 return self.select_single(UrlsList, objectName="bookmarksList")
372
373 def get_top_sites_list(self):
374 return self.select_single(UrlsList, objectName="topSitesList")
375
376 def get_notopsites_label(self):
377 return self.select_single("Label", objectName="notopsites")
369378
370379
371class UrlsList(uitk.UbuntuUIToolkitCustomProxyObjectBase):380class UrlsList(uitk.UbuntuUIToolkitCustomProxyObjectBase):
372381
373 def get_url_list(self):382 def get_delegates(self):
374 return [delegate.url for delegate in self.select_many("UrlDelegate")]383 return sorted(self.select_many(UrlDelegate),
384 key=lambda delegate: delegate.globalRect.y)
385
386 def get_urls(self):
387 return [delegate.url for delegate in self.get_delegates()]
388
389
390class UrlDelegate(uitk.UCListItem):
391
392 pass
375393
=== modified file 'tests/autopilot/webbrowser_app/tests/__init__.py'
--- tests/autopilot/webbrowser_app/tests/__init__.py 2015-05-20 11:37:18 +0000
+++ tests/autopilot/webbrowser_app/tests/__init__.py 2015-06-02 14:24:15 +0000
@@ -134,7 +134,7 @@
134 self.pointing_device.click_object(tabs_action)134 self.pointing_device.click_object(tabs_action)
135 else:135 else:
136 self.drag_bottom_edge_upwards(0.75)136 self.drag_bottom_edge_upwards(0.75)
137 self.main_window.get_tabs_view()137 return self.main_window.get_tabs_view()
138138
139 def open_new_tab(self):139 def open_new_tab(self):
140 if (self.main_window.incognito):140 if (self.main_window.incognito):
141141
=== added file 'tests/autopilot/webbrowser_app/tests/test_new_tab_view.py'
--- tests/autopilot/webbrowser_app/tests/test_new_tab_view.py 1970-01-01 00:00:00 +0000
+++ tests/autopilot/webbrowser_app/tests/test_new_tab_view.py 2015-06-02 14:24:15 +0000
@@ -0,0 +1,274 @@
1# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2#
3# Copyright 2015 Canonical
4#
5# This program is free software: you can redistribute it and/or modify it
6# under the terms of the GNU General Public License version 3, as published
7# by the Free Software Foundation.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17import os.path
18import sqlite3
19import time
20
21from autopilot.matchers import Eventually
22from testtools.matchers import Equals, NotEquals
23
24from webbrowser_app.tests import StartOpenRemotePageTestCaseBase
25
26
27class TestNewTabViewLifetime(StartOpenRemotePageTestCaseBase):
28
29 def test_new_tab_view_destroyed_when_browsing(self):
30 self.open_tabs_view()
31 new_tab_view = self.open_new_tab()
32 self.main_window.go_to_url(self.base_url + "/test2")
33 new_tab_view.wait_until_destroyed()
34
35 def test_new_tab_view_destroyed_when_closing_tab(self):
36 self.open_tabs_view()
37 new_tab_view = self.open_new_tab()
38 tabs_view = self.open_tabs_view()
39 tabs_view.get_previews()[0].close()
40 self.main_window.get_recent_view_toolbar().click_button("doneButton")
41 new_tab_view.wait_until_destroyed()
42
43 def test_new_tab_view_is_shared_between_tabs(self):
44 # Open one new tab
45 self.open_tabs_view()
46 new_tab_view = self.open_new_tab()
47 # Open a second new tab
48 self.open_tabs_view()
49 new_tab_view_2 = self.open_new_tab()
50 # Verify that they share the same NewTabView instance
51 self.assertThat(new_tab_view_2.id, Equals(new_tab_view.id))
52 # Close the second new tab, and verify that the NewTabView instance
53 # is still there
54 tabs_view = self.open_tabs_view()
55 tabs_view.get_previews()[0].close()
56 self.main_window.get_recent_view_toolbar().click_button("doneButton")
57 tabs_view.visible.wait_for(False)
58 self.assertThat(new_tab_view.visible, Equals(True))
59 # Close the first new tab, and verify that the NewTabView instance
60 # is destroyed
61 tabs_view = self.open_tabs_view()
62 tabs_view.get_previews()[0].close()
63 self.main_window.get_recent_view_toolbar().click_button("doneButton")
64 new_tab_view.wait_until_destroyed()
65
66 def test_new_tab_view_not_destroyed_when_closing_last_open_tab(self):
67 tabs_view = self.open_tabs_view()
68 tabs_view.get_previews()[0].close()
69 tabs_view.visible.wait_for(False)
70 new_tab_view = self.main_window.get_new_tab_view()
71 # Verify that the new tab view is not destroyed and then re-created
72 # when closing the last open tab if it was a blank one
73 tabs_view = self.open_tabs_view()
74 tabs_view.get_previews()[0].close()
75 tabs_view.visible.wait_for(False)
76 self.assertThat(new_tab_view.visible, Equals(True))
77
78
79class TestNewPrivateTabViewLifetime(StartOpenRemotePageTestCaseBase):
80
81 def test_new_private_tab_view_destroyed_when_browsing(self):
82 self.main_window.enter_private_mode()
83 new_private_tab_view = self.main_window.get_new_private_tab_view()
84 self.main_window.go_to_url(self.base_url + "/test2")
85 new_private_tab_view.wait_until_destroyed()
86
87 def test_new_private_tab_view_destroyed_when_leaving_private_mode(self):
88 self.main_window.enter_private_mode()
89 new_private_tab_view = self.main_window.get_new_private_tab_view()
90 self.main_window.leave_private_mode()
91 new_private_tab_view.wait_until_destroyed()
92
93 def test_new_private_tab_view_is_shared_between_tabs(self):
94 self.main_window.enter_private_mode()
95 new_private_tab_view = self.main_window.get_new_private_tab_view()
96 self.main_window.go_to_url(self.base_url + "/test2")
97 new_private_tab_view.wait_until_destroyed()
98 # Open one new private tab
99 self.open_tabs_view()
100 new_private_tab_view = self.open_new_tab()
101 # Open a second new private tab
102 self.open_tabs_view()
103 new_private_tab_view_2 = self.open_new_tab()
104 # Verify that they share the same NewPrivateTabView instance
105 self.assertThat(new_private_tab_view_2.id,
106 Equals(new_private_tab_view.id))
107 # Close the second new private tab, and verify that the
108 # NewPrivateTabView instance is still there
109 tabs_view = self.open_tabs_view()
110 tabs_view.get_previews()[0].close()
111 self.main_window.get_recent_view_toolbar().click_button("doneButton")
112 tabs_view.visible.wait_for(False)
113 self.assertThat(new_private_tab_view.visible, Equals(True))
114 # Close the first new private tab, and verify that the
115 # NewPrivateTabView instance is destroyed
116 tabs_view = self.open_tabs_view()
117 tabs_view.get_previews()[0].close()
118 self.main_window.get_recent_view_toolbar().click_button("doneButton")
119 new_private_tab_view.wait_until_destroyed()
120
121
122class TestNewTabViewContents(StartOpenRemotePageTestCaseBase):
123
124 def setUp(self):
125 self.create_temporary_profile()
126 self.populate_config()
127 self.populate_bookmarks()
128 super(TestNewTabViewContents, self).setUp()
129
130 def populate_config(self):
131 self.homepage = "http://test/test2"
132 config_file = os.path.join(self.config_location, "webbrowser-app.conf")
133 with open(config_file, "w") as f:
134 f.write("[General]\n")
135 f.write("homepage={}".format(self.homepage))
136
137 def populate_bookmarks(self):
138 db_path = os.path.join(self.data_location, "bookmarks.sqlite")
139 connection = sqlite3.connect(db_path)
140 connection.execute("""CREATE TABLE IF NOT EXISTS bookmarks
141 (url VARCHAR, title VARCHAR, icon VARCHAR,
142 created INTEGER);""")
143 rows = [
144 ("http://test/periodic-table/element/24/chromium",
145 "Chromium - Element Information"),
146 ("http://test/periodic-table/element/77/iridium",
147 "Iridium - Element Information"),
148 ("http://test/periodic-table/element/31/gallium",
149 "Gallium - Element Information"),
150 ("http://test/periodic-table/element/116/livermorium",
151 "Livermorium - Element Information"),
152 ("http://test/periodic-table/element/62/samarium",
153 "Samarium - Element Information"),
154 ("http://test/periodic-table/element/63/europium",
155 "Europium - Element Information"),
156 ]
157 for i, row in enumerate(rows):
158 timestamp = int(time.time()) - i * 10
159 query = "INSERT INTO bookmarks \
160 VALUES ('{}', '{}', '', {});"
161 query = query.format(row[0], row[1], timestamp)
162 connection.execute(query)
163 connection.commit()
164 connection.close()
165
166 def test_default_home_bookmark(self):
167 self.open_tabs_view()
168 new_tab_view = self.open_new_tab()
169 homepage_bookmark = new_tab_view.get_homepage_bookmark()
170 self.assertThat(homepage_bookmark.url, Equals(self.homepage))
171 self.pointing_device.click_object(homepage_bookmark)
172 new_tab_view.wait_until_destroyed()
173 self.main_window.wait_until_page_loaded(self.homepage)
174
175 def test_open_bookmark(self):
176 self.open_tabs_view()
177 new_tab_view = self.open_new_tab()
178 bookmarks = new_tab_view.get_bookmarks_list()
179 self.assertThat(lambda: len(bookmarks.get_delegates()),
180 Eventually(Equals(4)))
181 bookmark = bookmarks.get_delegates()[1]
182 url = bookmark.url
183 self.pointing_device.click_object(bookmark)
184 new_tab_view.wait_until_destroyed()
185 self.main_window.wait_until_page_loaded(url)
186
187 def test_bookmarks_section_expands_and_collapses(self):
188 self.open_tabs_view()
189 new_tab_view = self.open_new_tab()
190 bookmarks = new_tab_view.get_bookmarks_list()
191 top_sites = new_tab_view.get_top_sites_list()
192 self.assertThat(top_sites.visible, Equals(True))
193 # When the bookmarks list is collapsed, it shows a maximum of 4 entries
194 self.assertThat(lambda: len(bookmarks.get_delegates()),
195 Eventually(Equals(4)))
196 # When expanded, it shows all entries
197 more_button = new_tab_view.get_bookmarks_more_button()
198 self.assertThat(more_button.visible, Equals(True))
199 self.pointing_device.click_object(more_button)
200 self.assertThat(lambda: len(bookmarks.get_delegates()),
201 Eventually(Equals(6)))
202 self.assertThat(top_sites.visible, Eventually(Equals(False)))
203 # Collapse again
204 self.assertThat(more_button.visible, Equals(True))
205 self.pointing_device.click_object(more_button)
206 self.assertThat(lambda: len(bookmarks.get_delegates()),
207 Eventually(Equals(4)))
208 self.assertThat(top_sites.visible, Eventually(Equals(True)))
209
210 def _remove_first_bookmark(self):
211 bookmarks = self.main_window.get_new_tab_view().get_bookmarks_list()
212 delegate = bookmarks.get_delegates()[0]
213 url = delegate.url
214 delegate.trigger_leading_action("leadingAction.delete",
215 delegate.wait_until_destroyed)
216 self.assertThat(lambda: bookmarks.get_urls()[0],
217 Eventually(NotEquals(url)))
218
219 def test_remove_bookmarks_when_collapsed(self):
220 self.open_tabs_view()
221 new_tab_view = self.open_new_tab()
222 bookmarks = new_tab_view.get_bookmarks_list()
223 self.assertThat(lambda: len(bookmarks.get_delegates()),
224 Eventually(Equals(4)))
225 more_button = new_tab_view.get_bookmarks_more_button()
226 for i in range(3):
227 self._remove_first_bookmark()
228 self.assertThat(more_button.visible, Eventually(Equals(i < 1)))
229 self.assertThat(len(bookmarks.get_delegates()),
230 Equals(4 if (i < 2) else 3))
231
232 def test_remove_bookmarks_when_expanded(self):
233 self.open_tabs_view()
234 new_tab_view = self.open_new_tab()
235 bookmarks = new_tab_view.get_bookmarks_list()
236 more_button = new_tab_view.get_bookmarks_more_button()
237 self.assertThat(more_button.visible, Equals(True))
238 self.pointing_device.click_object(more_button)
239 self.assertThat(lambda: len(bookmarks.get_delegates()),
240 Eventually(Equals(6)))
241 more_button = new_tab_view.get_bookmarks_more_button()
242 top_sites = new_tab_view.get_top_sites_list()
243 for i in range(3):
244 self._remove_first_bookmark()
245 self.assertThat(len(bookmarks.get_delegates()), Equals(5 - i))
246 self.assertThat(more_button.visible, Eventually(Equals(i < 1)))
247 self.assertThat(top_sites.visible, Eventually(Equals(i > 0)))
248
249 def test_open_top_site(self):
250 self.open_tabs_view()
251 new_tab_view = self.open_new_tab()
252 top_sites = new_tab_view.get_top_sites_list()
253 self.assertThat(lambda: len(top_sites.get_delegates()),
254 Eventually(Equals(1)))
255 top_site = top_sites.get_delegates()[0]
256 url = top_site.url
257 self.pointing_device.click_object(top_site)
258 new_tab_view.wait_until_destroyed()
259 self.main_window.wait_until_page_loaded(url)
260
261 def test_remove_top_sites(self):
262 self.open_tabs_view()
263 new_tab_view = self.open_new_tab()
264 top_sites = new_tab_view.get_top_sites_list()
265 self.assertThat(lambda: len(top_sites.get_delegates()),
266 Eventually(Equals(1)))
267 notopsites_label = new_tab_view.get_notopsites_label()
268 self.assertThat(notopsites_label.visible, Eventually(Equals(False)))
269 delegate = top_sites.get_delegates()[0]
270 delegate.trigger_leading_action("leadingAction.delete",
271 delegate.wait_until_destroyed)
272 self.assertThat(lambda: len(top_sites.get_delegates()),
273 Eventually(Equals(0)))
274 self.assertThat(notopsites_label.visible, Eventually(Equals(True)))
0275
=== modified file 'tests/autopilot/webbrowser_app/tests/test_private.py'
--- tests/autopilot/webbrowser_app/tests/test_private.py 2015-05-22 19:13:31 +0000
+++ tests/autopilot/webbrowser_app/tests/test_private.py 2015-06-02 14:24:15 +0000
@@ -25,7 +25,7 @@
25 def get_url_list_from_top_sites(self):25 def get_url_list_from_top_sites(self):
26 self.open_tabs_view()26 self.open_tabs_view()
27 new_tab_view = self.open_new_tab()27 new_tab_view = self.open_new_tab()
28 return new_tab_view.get_top_sites()28 return new_tab_view.get_top_sites_list().get_urls()
2929
30 def test_going_in_and_out_private_mode(self):30 def test_going_in_and_out_private_mode(self):
31 address_bar = self.main_window.address_bar31 address_bar = self.main_window.address_bar
3232
=== modified file 'tests/autopilot/webbrowser_app/tests/test_tabs.py'
--- tests/autopilot/webbrowser_app/tests/test_tabs.py 2015-03-20 15:28:33 +0000
+++ tests/autopilot/webbrowser_app/tests/test_tabs.py 2015-06-02 14:24:15 +0000
@@ -71,8 +71,7 @@
71 self.main_window.go_to_url(url)71 self.main_window.go_to_url(url)
72 new_tab_view.wait_until_destroyed()72 new_tab_view.wait_until_destroyed()
73 self.assert_number_webviews_eventually(2)73 self.assert_number_webviews_eventually(2)
74 self.open_tabs_view()74 tabs_view = self.open_tabs_view()
75 tabs_view = self.main_window.get_tabs_view()
76 previews = tabs_view.get_previews()75 previews = tabs_view.get_previews()
77 self.assertThat(len(previews), Equals(2))76 self.assertThat(len(previews), Equals(2))
78 previews[0].close()77 previews[0].close()
@@ -150,8 +149,7 @@
150 self.assert_number_webviews_eventually(2)149 self.assert_number_webviews_eventually(2)
151150
152 def test_selecting_tab_focuses_webview(self):151 def test_selecting_tab_focuses_webview(self):
153 self.open_tabs_view()152 tabs_view = self.open_tabs_view()
154 tabs_view = self.main_window.get_tabs_view()
155 tabs_view.get_previews()[0].select()153 tabs_view.get_previews()[0].select()
156 tabs_view.visible.wait_for(False)154 tabs_view.visible.wait_for(False)
157 webview = self.main_window.get_current_webview()155 webview = self.main_window.get_current_webview()
@@ -170,8 +168,7 @@
170 self.assert_number_webviews_eventually(1)168 self.assert_number_webviews_eventually(1)
171169
172 def test_last_webview_requests_close(self):170 def test_last_webview_requests_close(self):
173 self.open_tabs_view()171 tabs_view = self.open_tabs_view()
174 tabs_view = self.main_window.get_tabs_view()
175 tabs_view.get_previews()[0].close()172 tabs_view.get_previews()[0].close()
176 tabs_view.visible.wait_for(False)173 tabs_view.visible.wait_for(False)
177 url = self.base_url + "/closeself"174 url = self.base_url + "/closeself"
178175
=== modified file 'tests/unittests/history-domainlist-chronological-model/tst_HistoryDomainListChronologicalModelTests.cpp'
--- tests/unittests/history-domainlist-chronological-model/tst_HistoryDomainListChronologicalModelTests.cpp 2014-08-12 19:57:28 +0000
+++ tests/unittests/history-domainlist-chronological-model/tst_HistoryDomainListChronologicalModelTests.cpp 2015-06-02 14:24:15 +0000
@@ -99,6 +99,11 @@
99 QCOMPARE(args.at(1).toInt(), 0);99 QCOMPARE(args.at(1).toInt(), 0);
100 QCOMPARE(args.at(2).toInt(), 0);100 QCOMPARE(args.at(2).toInt(), 0);
101 }101 }
102
103 void shouldReturnDomain() {
104 history->add(QUrl("http://example.org/"), "Example Domain", QUrl());
105 QCOMPARE(model->get(0), QString("example.org"));
106 }
102};107};
103108
104QTEST_MAIN(HistoryDomainListChronologicalModelTests)109QTEST_MAIN(HistoryDomainListChronologicalModelTests)
105110
=== modified file 'tests/unittests/top-sites-model/tst_TopSitesModelTests.cpp'
--- tests/unittests/top-sites-model/tst_TopSitesModelTests.cpp 2015-04-09 15:03:27 +0000
+++ tests/unittests/top-sites-model/tst_TopSitesModelTests.cpp 2015-06-02 14:24:15 +0000
@@ -74,17 +74,22 @@
7474
75 void shouldMatchAllWhenNothingIsHidden()75 void shouldMatchAllWhenNothingIsHidden()
76 {76 {
77 QSignalSpy spy(topsites, SIGNAL(countChanged()));
77 model->add(QUrl("http://example.org"), "Example Domain", QUrl());78 model->add(QUrl("http://example.org"), "Example Domain", QUrl());
78 model->add(QUrl("http://example.com"), "Example Domain", QUrl());79 model->add(QUrl("http://example.com"), "Example Domain", QUrl());
80 QCOMPARE(spy.count(), 2);
79 QCOMPARE(topsites->rowCount(), 2);81 QCOMPARE(topsites->rowCount(), 2);
80 }82 }
8183
82 void shouldFilterOutHiddenUrls()84 void shouldFilterOutHiddenUrls()
83 {85 {
86 QSignalSpy spy(topsites, SIGNAL(countChanged()));
84 model->add(QUrl("http://example.org"), "Example Domain", QUrl());87 model->add(QUrl("http://example.org"), "Example Domain", QUrl());
85 model->add(QUrl("http://example.com"), "Example Domain", QUrl());88 model->add(QUrl("http://example.com"), "Example Domain", QUrl());
89 QCOMPARE(spy.count(), 2);
86 QCOMPARE(topsites->rowCount(), 2);90 QCOMPARE(topsites->rowCount(), 2);
87 model->hide(QUrl("http://example.org"));91 model->hide(QUrl("http://example.org"));
92 QCOMPARE(spy.count(), 3);
88 QCOMPARE(topsites->rowCount(), 1);93 QCOMPARE(topsites->rowCount(), 1);
89 QCOMPARE(topsites->data(topsites->index(0, 0), HistoryModel::Url).toUrl(), QUrl("http://example.com"));94 QCOMPARE(topsites->data(topsites->index(0, 0), HistoryModel::Url).toUrl(), QUrl("http://example.com"));
90 }95 }

Subscribers

People subscribed via source and target branches

to status/vote changes: