Merge lp:~unity-team/unity8/scope-settings into lp:unity8
- scope-settings
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Michał Sawicz |
Approved revision: | 1151 |
Merged at revision: | 1214 |
Proposed branch: | lp:~unity-team/unity8/scope-settings |
Merge into: | lp:unity8 |
Prerequisite: | lp:~unity-team/unity8/alt_nav_support |
Diff against target: |
1676 lines (+1093/-74) 28 files modified
qml/Dash/Dash.qml (+1/-1) qml/Dash/DashContent.qml (+4/-4) qml/Dash/GenericScopeView.qml (+67/-26) qml/Dash/PageHeader.qml (+9/-3) qml/Dash/PreviewListView.qml (+11/-1) qml/Dash/ScopeSettings/ScopeSetting.qml (+37/-0) qml/Dash/ScopeSettings/ScopeSettingBoolean.qml (+61/-0) qml/Dash/ScopeSettings/ScopeSettingList.qml (+50/-0) qml/Dash/ScopeSettings/ScopeSettingNumber.qml (+21/-0) qml/Dash/ScopeSettings/ScopeSettingString.qml (+83/-0) qml/Dash/ScopeSettings/ScopeSettingsWidgetFactory.qml (+57/-0) qml/Dash/ScopeSettingsPage.qml (+62/-0) qml/Dash/ScopesOverview.qml (+2/-0) tests/autopilot/unity8/shell/emulators/dash.py (+5/-5) tests/mocks/Unity/CMakeLists.txt (+2/-0) tests/mocks/Unity/fake_scope.cpp (+3/-1) tests/mocks/Unity/fake_scope.h (+1/-0) tests/mocks/Unity/fake_settingsmodel.cpp (+95/-0) tests/mocks/Unity/fake_settingsmodel.h (+54/-0) tests/mocks/Unity/fake_unity_plugin.cpp (+2/-0) tests/qmltests/CMakeLists.txt (+5/-0) tests/qmltests/Dash/Previews/tst_PreviewWidgetFactory.qml (+1/-1) tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingBoolean.qml (+62/-0) tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingList.qml (+84/-0) tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingNumber.qml (+98/-0) tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingString.qml (+88/-0) tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingsWidgetFactory.qml (+65/-0) tests/qmltests/Dash/tst_GenericScopeView.qml (+63/-32) |
To merge this branch: | bzr merge lp:~unity-team/unity8/scope-settings |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
Michał Sawicz | Approve | ||
Review via email: mp+232296@code.launchpad.net |
This proposal supersedes a proposal from 2014-08-08.
Commit message
Add scope settings UI
Accessible through the page header in scope pages on supported scopes.
Description of the change
* Are there any related MPs required for this MP to build/function as expected? Please list.
No
* Did you perform an exploratory manual test run of your code change and any related functionality?
Yes
* Did you make sure that your branch does not contain spurious tags?
Yes
* If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
n/a
* If you changed the UI, has there been a design review?
There are no final designs yet, but this is consistent with the rest of the UI
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1114
http://
Executed test runs:
UNSTABLE: http://
FAILURE: 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 : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1115
http://
Executed test runs:
UNSTABLE: http://
FAILURE: 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 : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1116
http://
Executed test runs:
UNSTABLE: http://
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://
Michał Sawicz (saviq) wrote : Posted in a previous version of this proposal | # |
Please delete tag 7.85+14.
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1117
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
SUCCESS: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1120
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: 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 : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1121
http://
Executed test runs:
UNSTABLE: http://
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 : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1122
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Michał Sawicz (saviq) wrote : Posted in a previous version of this proposal | # |
You need to disable dash overview when in settings.
Fields don't get focus when tapped on list item.
I assume there's no way to override the color of:
- labels in ItemSelector
- checkbox? should it?
Previews are always opened starting at the first one, not the one clicked. Rebase on lp:~saviq/unity8/fix-horizontal-list-activation and add tests to ensure which item is opened. Doesn't even conflict (but you do need to replace previewListView with subPageLoader).
More to come.
Michał Sawicz (saviq) wrote : Posted in a previous version of this proposal | # |
See inline.
Didn't review tests yet, will review after other review comments are addressed.
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1123
http://
Executed test runs:
UNSTABLE: http://
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 : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1126
http://
Executed test runs:
FAILURE: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1127
http://
Executed test runs:
UNSTABLE: http://
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 : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1129
http://
Executed test runs:
FAILURE: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1129
http://
Executed test runs:
FAILURE: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:1129
http://
Executed test runs:
SUCCESS: http://
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://
Andrea Cimitan (cimi) : Posted in a previous version of this proposal | # |
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1132
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: 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 : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1133
http://
Executed test runs:
UNSTABLE: http://
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 : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1134
http://
Executed test runs:
UNSTABLE: http://
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://
Michał Sawicz (saviq) wrote : Posted in a previous version of this proposal | # |
See inline. There's a bunch of unanswered comments in the previous review, please answer them too.
Re: shown split or separate, I'd rather merge them unless there's a real reason why not to.
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:1136
http://
Executed test runs:
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:1140
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Andrea Cimitan (cimi) : Posted in a previous version of this proposal | # |
Michał Sawicz (saviq) wrote : Posted in a previous version of this proposal | # |
Do we really only want to show this once the loader is ready? There will be a delay between user tapping and the page going in on screen? OTOH that gives us protection from a broken subpage, so maybe that's fine...
Otherwise see inline.
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:1141
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Michał Sawicz (saviq) : Posted in a previous version of this proposal | # |
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:1144
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:1147
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1149
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Michał Sawicz (saviq) : | # |
- 1150. By Andrea Cimitan
-
Add link to bug
- 1151. By Andrea Cimitan
-
Fixed indent
Michał Sawicz (saviq) wrote : | # |
* Did you perform an exploratory manual test run of the code change and any related functionality?
Y, works!
* Did CI run pass? If not, please explain why.
Y
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1150
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file 'qml/Dash/Dash.qml' |
2 | --- qml/Dash/Dash.qml 2014-08-08 09:41:13 +0000 |
3 | +++ qml/Dash/Dash.qml 2014-08-27 08:28:24 +0000 |
4 | @@ -341,7 +341,7 @@ |
5 | objectName: "overviewDragHandle" |
6 | z: 1 |
7 | direction: Direction.Upwards |
8 | - enabled: !dashContent.previewShown && |
9 | + enabled: !dashContent.subPageShown && |
10 | dashContent.currentScope && |
11 | dashContent.currentScope.searchQuery == "" && |
12 | (overviewController.progress == 0 || dragging) |
13 | |
14 | === modified file 'qml/Dash/DashContent.qml' |
15 | --- qml/Dash/DashContent.qml 2014-08-08 08:47:36 +0000 |
16 | +++ qml/Dash/DashContent.qml 2014-08-27 08:28:24 +0000 |
17 | @@ -27,8 +27,8 @@ |
18 | readonly property alias currentIndex: dashContentList.currentIndex |
19 | readonly property string currentScopeId: dashContentList.currentItem ? dashContentList.currentItem.scopeId : "" |
20 | readonly property var currentScope: dashContentList.currentItem ? dashContentList.currentItem.theScope : null |
21 | - readonly property bool previewShown: dashContentList.currentItem && dashContentList.currentItem.item ? |
22 | - dashContentList.currentItem.item.previewShown : false |
23 | + readonly property bool subPageShown: dashContentList.currentItem && dashContentList.currentItem.item ? |
24 | + dashContentList.currentItem.item.subPageShown : false |
25 | readonly property bool processing: dashContentList.currentItem && dashContentList.currentItem.item |
26 | && dashContentList.currentItem.item.processing || false |
27 | readonly property bool pageHeaderTotallyVisible: dashContentList.currentItem && dashContentList.currentItem.item |
28 | @@ -96,8 +96,7 @@ |
29 | id: dashContentList |
30 | objectName: "dashContentList" |
31 | |
32 | - interactive: dashContent.scopes.loaded && currentItem && !currentItem.moving && !currentItem.navigationShown |
33 | - |
34 | + interactive: dashContent.scopes.loaded && currentItem && !currentItem.moving && !currentItem.navigationShown && !currentItem.subPageShown |
35 | anchors.fill: parent |
36 | orientation: ListView.Horizontal |
37 | boundsBehavior: Flickable.DragAndOvershootBounds |
38 | @@ -137,6 +136,7 @@ |
39 | |
40 | readonly property bool moving: item ? item.moving : false |
41 | readonly property bool navigationShown: item ? item.navigationShown : false |
42 | + readonly property bool subPageShown: item ? item.subPageShown : false |
43 | readonly property var categoryView: item ? item.categoryView : null |
44 | readonly property var theScope: scope |
45 | |
46 | |
47 | === modified file 'qml/Dash/GenericScopeView.qml' |
48 | --- qml/Dash/GenericScopeView.qml 2014-08-27 08:28:24 +0000 |
49 | +++ qml/Dash/GenericScopeView.qml 2014-08-27 08:28:24 +0000 |
50 | @@ -34,7 +34,7 @@ |
51 | property bool enableHeightBehaviorOnNextCreation: false |
52 | property var categoryView: categoryView |
53 | property bool showPageHeader: true |
54 | - readonly property alias previewShown: previewListView.open |
55 | + readonly property alias subPageShown: subPageLoader.subPageShown |
56 | property int paginationCount: 0 |
57 | property int paginationIndex: 0 |
58 | property alias pageHeaderTotallyVisible: categoryView.pageHeaderTotallyVisible |
59 | @@ -43,7 +43,7 @@ |
60 | style: scope ? scope.customizations : {} |
61 | } |
62 | |
63 | - readonly property bool processing: scope ? scope.searchInProgress || previewListView.processing : false |
64 | + readonly property bool processing: scope ? scope.searchInProgress || subPageLoader.processing : false |
65 | |
66 | signal backClicked() |
67 | |
68 | @@ -56,7 +56,7 @@ |
69 | } |
70 | |
71 | function closePreview() { |
72 | - previewListView.open = false; |
73 | + subPageLoader.closeSubPage() |
74 | } |
75 | |
76 | function itemClicked(index, result, item, itemModel, resultsModel, limitedCategoryItemCount) { |
77 | @@ -80,19 +80,19 @@ |
78 | if (limitedCategoryItemCount > 0) { |
79 | previewLimitModel.model = resultsModel; |
80 | previewLimitModel.limit = limitedCategoryItemCount; |
81 | - previewListView.model = previewLimitModel; |
82 | + subPageLoader.model = previewLimitModel; |
83 | } else { |
84 | - previewListView.model = resultsModel; |
85 | + subPageLoader.model = resultsModel; |
86 | } |
87 | - previewListView.currentIndex = -1; |
88 | - previewListView.currentIndex = index; |
89 | - previewListView.open = true; |
90 | + subPageLoader.initialIndex = -1; |
91 | + subPageLoader.initialIndex = index; |
92 | + subPageLoader.openSubPage("preview"); |
93 | } |
94 | |
95 | Binding { |
96 | target: scope |
97 | property: "isActive" |
98 | - value: isCurrent && !previewListView.open |
99 | + value: isCurrent && !subPageLoader.open |
100 | } |
101 | |
102 | SortFilterProxyModel { |
103 | @@ -105,10 +105,10 @@ |
104 | } |
105 | |
106 | onIsCurrentChanged: { |
107 | - if (showPageHeader) { |
108 | + if (pageHeaderLoader.item && showPageHeader) { |
109 | pageHeaderLoader.item.resetSearch(); |
110 | } |
111 | - previewListView.open = false; |
112 | + subPageLoader.closeSubPage(); |
113 | } |
114 | |
115 | Binding { |
116 | @@ -127,8 +127,8 @@ |
117 | |
118 | Connections { |
119 | target: scopeView.scope |
120 | - onShowDash: previewListView.open = false; |
121 | - onHideDash: previewListView.open = false; |
122 | + onShowDash: subPageLoader.closeSubPage() |
123 | + onHideDash: subPageLoader.closeSubPage() |
124 | } |
125 | |
126 | Rectangle { |
127 | @@ -141,7 +141,7 @@ |
128 | id: categoryView |
129 | objectName: "categoryListView" |
130 | |
131 | - x: previewListView.open ? -width : 0 |
132 | + x: subPageLoader.open ? -width : 0 |
133 | Behavior on x { UbuntuNumberAnimation { } } |
134 | width: parent.width |
135 | height: floatingSeeLess.visible ? parent.height - floatingSeeLess.height + floatingSeeLess.yOffset |
136 | @@ -149,7 +149,7 @@ |
137 | clip: height != parent.height |
138 | |
139 | model: scopeView.categories |
140 | - forceNoClip: previewListView.open |
141 | + forceNoClip: subPageLoader.open |
142 | pixelAligned: true |
143 | interactive: !navigationShown |
144 | |
145 | @@ -294,10 +294,10 @@ |
146 | // If the filter animation will be seen start it, otherwise, just flip the switch |
147 | var shrinkingVisible = !shouldExpand && y + item.collapsedHeight + seeAll.height < categoryView.height; |
148 | var growingVisible = shouldExpand && y + height < categoryView.height; |
149 | - if (!previewListView.open || shouldExpand) { |
150 | + if (!subPageLoader.open || shouldExpand) { |
151 | var animate = shrinkingVisible || growingVisible; |
152 | baseItem.expand(shouldExpand, animate) |
153 | - if (shouldExpand && !previewListView.open) { |
154 | + if (shouldExpand && !subPageLoader.open) { |
155 | categoryView.maximizeVisibleArea(index, item.expandedHeight + seeAll.height); |
156 | } |
157 | } |
158 | @@ -428,6 +428,7 @@ |
159 | searchHint: scopeView.scope && scopeView.scope.searchHint || i18n.tr("Search") |
160 | showBackButton: scopeView.hasBackAction |
161 | searchEntryEnabled: true |
162 | + settingsEnabled: scopeView.scope && scopeView.scope.settings && scopeView.scope.settings.count > 0 || false |
163 | scopeStyle: scopeView.scopeStyle |
164 | paginationCount: scopeView.paginationCount |
165 | paginationIndex: scopeView.paginationIndex |
166 | @@ -441,6 +442,7 @@ |
167 | } |
168 | |
169 | onBackClicked: scopeView.backClicked() |
170 | + onSettingsClicked: subPageLoader.openSubPage("settings") |
171 | } |
172 | } |
173 | } |
174 | @@ -501,21 +503,60 @@ |
175 | id: previewLimitModel |
176 | } |
177 | |
178 | - PreviewListView { |
179 | - id: previewListView |
180 | - objectName: "previewListView" |
181 | + Loader { |
182 | + id: subPageLoader |
183 | + objectName: "subPageLoader" |
184 | visible: x != width |
185 | - scope: scopeView.scope |
186 | - scopeStyle: scopeView.scopeStyle |
187 | width: parent.width |
188 | height: parent.height |
189 | anchors.left: categoryView.right |
190 | |
191 | - onOpenChanged: { |
192 | - if (showPageHeader) { |
193 | - pageHeaderLoader.item.unfocus(); |
194 | + property bool open: false |
195 | + property var scope: scopeView.scope |
196 | + property var scopeStyle: scopeView.scopeStyle |
197 | + property int initialIndex: -1 |
198 | + property var model: null |
199 | + |
200 | + readonly property bool processing: item && item.processing || false |
201 | + readonly property int count: item && item.count || 0 |
202 | + readonly property int currentIndex: item && item.currentIndex || 0 |
203 | + readonly property var currentItem: item && item.currentItem || null |
204 | + |
205 | + property string subPage: "" |
206 | + readonly property bool subPageShown: visible && status === Loader.Ready |
207 | + |
208 | + function openSubPage(page) { |
209 | + subPage = page; |
210 | + } |
211 | + |
212 | + function closeSubPage() { |
213 | + open = false; |
214 | + } |
215 | + |
216 | + source: switch(subPage) { |
217 | + case "preview": return "PreviewListView.qml"; |
218 | + case "settings": return "ScopeSettingsPage.qml"; |
219 | + default: return ""; |
220 | + } |
221 | + |
222 | + onLoaded: { |
223 | + item.scope = Qt.binding(function() { return subPageLoader.scope; } ) |
224 | + item.scopeStyle = Qt.binding(function() { return subPageLoader.scopeStyle; } ) |
225 | + if (subPage == "preview") { |
226 | + item.open = Qt.binding(function() { return subPageLoader.open; } ) |
227 | + item.initialIndex = Qt.binding(function() { return subPageLoader.initialIndex; } ) |
228 | + item.model = Qt.binding(function() { return subPageLoader.model; } ) |
229 | } |
230 | + open = true; |
231 | + } |
232 | + |
233 | + onOpenChanged: pageHeaderLoader.item.unfocus() |
234 | + |
235 | + onVisibleChanged: if (!visible) subPage = "" |
236 | + |
237 | + Connections { |
238 | + target: subPageLoader.item |
239 | + onBackClicked: subPageLoader.closeSubPage() |
240 | } |
241 | } |
242 | - |
243 | } |
244 | |
245 | === modified file 'qml/Dash/PageHeader.qml' |
246 | --- qml/Dash/PageHeader.qml 2014-08-27 08:28:24 +0000 |
247 | +++ qml/Dash/PageHeader.qml 2014-08-27 08:28:24 +0000 |
248 | @@ -31,6 +31,7 @@ |
249 | property string title |
250 | |
251 | property bool searchEntryEnabled: false |
252 | + property bool settingsEnabled: false |
253 | property ListModel searchHistory: SearchHistoryModel |
254 | property alias searchQuery: searchTextField.text |
255 | property alias searchHint: searchTextField.placeholderText |
256 | @@ -44,6 +45,7 @@ |
257 | property var scopeStyle: null |
258 | |
259 | signal backClicked() |
260 | + signal settingsClicked() |
261 | |
262 | onScopeStyleChanged: refreshLogo() |
263 | onSearchQueryChanged: { |
264 | @@ -246,9 +248,7 @@ |
265 | backAction: Action { |
266 | iconName: "back" |
267 | visible: root.showBackButton |
268 | - onTriggered: { |
269 | - root.backClicked(); |
270 | - } |
271 | + onTriggered: root.backClicked() |
272 | } |
273 | |
274 | actions: [ |
275 | @@ -260,6 +260,12 @@ |
276 | headerContainer.showSearch = true; |
277 | searchTextField.forceActiveFocus(); |
278 | } |
279 | + }, |
280 | + Action { |
281 | + objectName: "settings" |
282 | + iconName: "settings" |
283 | + visible: root.settingsEnabled |
284 | + onTriggered: root.settingsClicked() |
285 | } |
286 | ] |
287 | } |
288 | |
289 | === modified file 'qml/Dash/PreviewListView.qml' |
290 | --- qml/Dash/PreviewListView.qml 2014-08-27 08:28:24 +0000 |
291 | +++ qml/Dash/PreviewListView.qml 2014-08-27 08:28:24 +0000 |
292 | @@ -23,6 +23,7 @@ |
293 | Item { |
294 | id: root |
295 | |
296 | + property int initialIndex: -1 |
297 | property var scope: null |
298 | property var scopeStyle: null |
299 | |
300 | @@ -37,6 +38,8 @@ |
301 | readonly property bool processing: currentItem && (!currentItem.previewModel.loaded |
302 | || currentItem.previewModel.processingAction) |
303 | |
304 | + signal backClicked() |
305 | + |
306 | PageHeader { |
307 | id: header |
308 | objectName: "pageHeader" |
309 | @@ -46,7 +49,7 @@ |
310 | searchEntryEnabled: false |
311 | scopeStyle: root.scopeStyle |
312 | |
313 | - onBackClicked: root.open = false |
314 | + onBackClicked: root.backClicked() |
315 | } |
316 | |
317 | ListView { |
318 | @@ -80,6 +83,13 @@ |
319 | } |
320 | } |
321 | |
322 | + onCountChanged: { |
323 | + if (count > 0 && initialIndex >= 0) { |
324 | + currentIndex = initialIndex; |
325 | + initialIndex = -1; |
326 | + } |
327 | + } |
328 | + |
329 | delegate: Previews.Preview { |
330 | id: preview |
331 | objectName: "preview" + index |
332 | |
333 | === added directory 'qml/Dash/ScopeSettings' |
334 | === added file 'qml/Dash/ScopeSettings/ScopeSetting.qml' |
335 | --- qml/Dash/ScopeSettings/ScopeSetting.qml 1970-01-01 00:00:00 +0000 |
336 | +++ qml/Dash/ScopeSettings/ScopeSetting.qml 2014-08-27 08:28:24 +0000 |
337 | @@ -0,0 +1,37 @@ |
338 | +/* |
339 | + * Copyright (C) 2014 Canonical, Ltd. |
340 | + * |
341 | + * This program is free software; you can redistribute it and/or modify |
342 | + * it under the terms of the GNU General Public License as published by |
343 | + * the Free Software Foundation; version 3. |
344 | + * |
345 | + * This program is distributed in the hope that it will be useful, |
346 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
347 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
348 | + * GNU General Public License for more details. |
349 | + * |
350 | + * You should have received a copy of the GNU General Public License |
351 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
352 | + */ |
353 | + |
354 | +import QtQuick 2.2 |
355 | +import Ubuntu.Components 1.1 |
356 | + |
357 | +/*! Interface for settings widgets. */ |
358 | + |
359 | +Item { |
360 | + //! The ScopeStyle component. |
361 | + property var scopeStyle: null |
362 | + |
363 | + //! Variable used to contain widget's data |
364 | + property var widgetData: null |
365 | + |
366 | + /*! \brief This signal should be emitted when a setting action was updated. |
367 | + * |
368 | + * \param value the new setting value. |
369 | + */ |
370 | + signal updated(var value) |
371 | + |
372 | + //! \internal |
373 | + readonly property real settingMargins: units.gu(2) |
374 | +} |
375 | |
376 | === added file 'qml/Dash/ScopeSettings/ScopeSettingBoolean.qml' |
377 | --- qml/Dash/ScopeSettings/ScopeSettingBoolean.qml 1970-01-01 00:00:00 +0000 |
378 | +++ qml/Dash/ScopeSettings/ScopeSettingBoolean.qml 2014-08-27 08:28:24 +0000 |
379 | @@ -0,0 +1,61 @@ |
380 | +/* |
381 | + * Copyright (C) 2014 Canonical, Ltd. |
382 | + * |
383 | + * This program is free software; you can redistribute it and/or modify |
384 | + * it under the terms of the GNU General Public License as published by |
385 | + * the Free Software Foundation; version 3. |
386 | + * |
387 | + * This program is distributed in the hope that it will be useful, |
388 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
389 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
390 | + * GNU General Public License for more details. |
391 | + * |
392 | + * You should have received a copy of the GNU General Public License |
393 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
394 | + */ |
395 | + |
396 | +import QtQuick 2.2 |
397 | +import Ubuntu.Components 1.1 |
398 | +import Ubuntu.Components.ListItems 1.0 as ListItem |
399 | + |
400 | +ScopeSetting { |
401 | + id: root |
402 | + height: listItem.height |
403 | + |
404 | + ListItem.Empty { |
405 | + id: listItem |
406 | + |
407 | + onClicked: { |
408 | + control.checked = !control.checked; |
409 | + updated(control.checked); |
410 | + } |
411 | + |
412 | + Label { |
413 | + anchors { |
414 | + left: parent.left |
415 | + leftMargin: settingMargins |
416 | + right: control.left |
417 | + rightMargin: units.gu(1) |
418 | + verticalCenter: parent.verticalCenter |
419 | + } |
420 | + text: widgetData.displayName |
421 | + elide: Text.ElideMiddle |
422 | + maximumLineCount: 2 |
423 | + wrapMode: Text.Wrap |
424 | + color: scopeStyle ? scopeStyle.foreground : Theme.palette.normal.baseText |
425 | + } |
426 | + |
427 | + CheckBox { |
428 | + id: control |
429 | + objectName: "control" |
430 | + anchors { |
431 | + right: parent.right |
432 | + rightMargin: settingMargins |
433 | + verticalCenter: parent.verticalCenter |
434 | + } |
435 | + checked: widgetData.value |
436 | + |
437 | + onTriggered: root.updated(checked) |
438 | + } |
439 | + } |
440 | +} |
441 | |
442 | === added file 'qml/Dash/ScopeSettings/ScopeSettingList.qml' |
443 | --- qml/Dash/ScopeSettings/ScopeSettingList.qml 1970-01-01 00:00:00 +0000 |
444 | +++ qml/Dash/ScopeSettings/ScopeSettingList.qml 2014-08-27 08:28:24 +0000 |
445 | @@ -0,0 +1,50 @@ |
446 | +/* |
447 | + * Copyright (C) 2014 Canonical, Ltd. |
448 | + * |
449 | + * This program is free software; you can redistribute it and/or modify |
450 | + * it under the terms of the GNU General Public License as published by |
451 | + * the Free Software Foundation; version 3. |
452 | + * |
453 | + * This program is distributed in the hope that it will be useful, |
454 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
455 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
456 | + * GNU General Public License for more details. |
457 | + * |
458 | + * You should have received a copy of the GNU General Public License |
459 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
460 | + */ |
461 | + |
462 | +import QtQuick 2.2 |
463 | +import Ubuntu.Components 1.1 |
464 | +import Ubuntu.Components.ListItems 1.0 as ListItem |
465 | + |
466 | +ScopeSetting { |
467 | + id: root |
468 | + |
469 | + // FIXME workaround for: https://bugs.launchpad.net/ubuntu/+source/ubuntu-ui-toolkit/+bug/1355830 |
470 | + height: listItem.currentlyExpanded ? listItem.itemHeight * widgetData.properties["values"].length + units.gu(6) : listItem.height |
471 | + |
472 | + property int initialValue: -1 |
473 | + |
474 | + ListItem.ItemSelector { |
475 | + id: listItem |
476 | + objectName: "control" |
477 | + anchors { |
478 | + left: parent.left |
479 | + right: parent.right |
480 | + } |
481 | + text: widgetData.displayName |
482 | + model: widgetData.properties["values"] |
483 | + |
484 | + onSelectedIndexChanged: { |
485 | + if (root.initialValue >= 0) { |
486 | + var tmpValue = root.initialValue; |
487 | + root.initialValue = -1; |
488 | + selectedIndex = tmpValue; |
489 | + return; |
490 | + } |
491 | + |
492 | + root.updated(selectedIndex); |
493 | + } |
494 | + } |
495 | +} |
496 | |
497 | === added file 'qml/Dash/ScopeSettings/ScopeSettingNumber.qml' |
498 | --- qml/Dash/ScopeSettings/ScopeSettingNumber.qml 1970-01-01 00:00:00 +0000 |
499 | +++ qml/Dash/ScopeSettings/ScopeSettingNumber.qml 2014-08-27 08:28:24 +0000 |
500 | @@ -0,0 +1,21 @@ |
501 | +/* |
502 | + * Copyright (C) 2014 Canonical, Ltd. |
503 | + * |
504 | + * This program is free software; you can redistribute it and/or modify |
505 | + * it under the terms of the GNU General Public License as published by |
506 | + * the Free Software Foundation; version 3. |
507 | + * |
508 | + * This program is distributed in the hope that it will be useful, |
509 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
510 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
511 | + * GNU General Public License for more details. |
512 | + * |
513 | + * You should have received a copy of the GNU General Public License |
514 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
515 | + */ |
516 | + |
517 | +import QtQuick 2.2 |
518 | + |
519 | +ScopeSettingString { |
520 | + mode: "number" |
521 | +} |
522 | |
523 | === added file 'qml/Dash/ScopeSettings/ScopeSettingString.qml' |
524 | --- qml/Dash/ScopeSettings/ScopeSettingString.qml 1970-01-01 00:00:00 +0000 |
525 | +++ qml/Dash/ScopeSettings/ScopeSettingString.qml 2014-08-27 08:28:24 +0000 |
526 | @@ -0,0 +1,83 @@ |
527 | +/* |
528 | + * Copyright (C) 2014 Canonical, Ltd. |
529 | + * |
530 | + * This program is free software; you can redistribute it and/or modify |
531 | + * it under the terms of the GNU General Public License as published by |
532 | + * the Free Software Foundation; version 3. |
533 | + * |
534 | + * This program is distributed in the hope that it will be useful, |
535 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
536 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
537 | + * GNU General Public License for more details. |
538 | + * |
539 | + * You should have received a copy of the GNU General Public License |
540 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
541 | + */ |
542 | + |
543 | +import QtQuick 2.2 |
544 | +import Ubuntu.Components 1.1 |
545 | +import Ubuntu.Components.ListItems 1.0 as ListItem |
546 | + |
547 | +ScopeSetting { |
548 | + id: root |
549 | + height: listItem.height |
550 | + |
551 | + property string mode: "string" |
552 | + |
553 | + ListItem.Empty { |
554 | + id: listItem |
555 | + onClicked: { |
556 | + control.forceActiveFocus(); |
557 | + control.selectAll(); |
558 | + } |
559 | + |
560 | + Label { |
561 | + id: label |
562 | + anchors { |
563 | + left: parent.left |
564 | + leftMargin: settingMargins |
565 | + right: control.left |
566 | + rightMargin: units.gu(1) |
567 | + verticalCenter: parent.verticalCenter |
568 | + } |
569 | + text: widgetData.displayName |
570 | + elide: Text.ElideMiddle |
571 | + maximumLineCount: 2 |
572 | + wrapMode: Text.Wrap |
573 | + color: scopeStyle ? scopeStyle.foreground : Theme.palette.normal.baseText |
574 | + } |
575 | + |
576 | + TextField { |
577 | + id: control |
578 | + objectName: "control" |
579 | + anchors { |
580 | + right: parent.right |
581 | + rightMargin: settingMargins |
582 | + verticalCenter: parent.verticalCenter |
583 | + } |
584 | + width: root.mode == "number" ? units.gu(8) : units.gu(12) |
585 | + text: widgetData.value |
586 | + color: scopeStyle ? scopeStyle.foreground : Theme.palette.normal.fieldText |
587 | + validator: root.mode == "number" ? doubleValidator : null |
588 | + hasClearButton: root.mode == "number" ? false : true |
589 | + |
590 | + DoubleValidator { |
591 | + id: doubleValidator |
592 | + } |
593 | + |
594 | + function updateText() { |
595 | + if (acceptableInput) { |
596 | + text = displayText; |
597 | + root.updated(text); |
598 | + } |
599 | + } |
600 | + |
601 | + onAccepted: updateText() |
602 | + onActiveFocusChanged: { |
603 | + if (!activeFocus) { |
604 | + updateText(); |
605 | + } |
606 | + } |
607 | + } |
608 | + } |
609 | +} |
610 | |
611 | === added file 'qml/Dash/ScopeSettings/ScopeSettingsWidgetFactory.qml' |
612 | --- qml/Dash/ScopeSettings/ScopeSettingsWidgetFactory.qml 1970-01-01 00:00:00 +0000 |
613 | +++ qml/Dash/ScopeSettings/ScopeSettingsWidgetFactory.qml 2014-08-27 08:28:24 +0000 |
614 | @@ -0,0 +1,57 @@ |
615 | +/* |
616 | + * Copyright (C) 2014 Canonical, Ltd. |
617 | + * |
618 | + * This program is free software; you can redistribute it and/or modify |
619 | + * it under the terms of the GNU General Public License as published by |
620 | + * the Free Software Foundation; version 3. |
621 | + * |
622 | + * This program is distributed in the hope that it will be useful, |
623 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
624 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
625 | + * GNU General Public License for more details. |
626 | + * |
627 | + * You should have received a copy of the GNU General Public License |
628 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
629 | + */ |
630 | + |
631 | +import QtQuick 2.2 |
632 | + |
633 | +//! \brief This component loads the widgets based on type. |
634 | + |
635 | +Loader { |
636 | + id: root |
637 | + |
638 | + //! The ScopeStyle component. |
639 | + property var scopeStyle: null |
640 | + |
641 | + //! Variable used to contain widget's data |
642 | + property var widgetData: null |
643 | + |
644 | + //! Triggered signal forwarded from the widgets. |
645 | + signal updated(var value) |
646 | + |
647 | + source: widgetSource |
648 | + |
649 | + //! \cond private |
650 | + property url widgetSource: { |
651 | + switch (widgetData.type) { |
652 | + case "boolean": return "ScopeSettingBoolean.qml"; |
653 | + case "list": return "ScopeSettingList.qml"; |
654 | + case "number": return "ScopeSettingNumber.qml"; |
655 | + case "string": return "ScopeSettingString.qml"; |
656 | + default: return ""; |
657 | + } |
658 | + } |
659 | + //! \endcond |
660 | + |
661 | + onLoaded: { |
662 | + if (item.hasOwnProperty("initialValue")) item.initialValue = root.widgetData.value; |
663 | + item.widgetData = Qt.binding(function() { return root.widgetData; } ) |
664 | + item.scopeStyle = Qt.binding(function() { return root.scopeStyle; } ) |
665 | + } |
666 | + |
667 | + Connections { |
668 | + target: root.item |
669 | + onUpdated: if (value !== widgetData.value) root.updated(value) |
670 | + } |
671 | +} |
672 | |
673 | === added file 'qml/Dash/ScopeSettingsPage.qml' |
674 | --- qml/Dash/ScopeSettingsPage.qml 1970-01-01 00:00:00 +0000 |
675 | +++ qml/Dash/ScopeSettingsPage.qml 2014-08-27 08:28:24 +0000 |
676 | @@ -0,0 +1,62 @@ |
677 | +/* |
678 | + * Copyright (C) 2014 Canonical, Ltd. |
679 | + * |
680 | + * This program is free software; you can redistribute it and/or modify |
681 | + * it under the terms of the GNU General Public License as published by |
682 | + * the Free Software Foundation; version 3. |
683 | + * |
684 | + * This program is distributed in the hope that it will be useful, |
685 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
686 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
687 | + * GNU General Public License for more details. |
688 | + * |
689 | + * You should have received a copy of the GNU General Public License |
690 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
691 | + */ |
692 | + |
693 | +import QtQuick 2.2 |
694 | +import Ubuntu.Components 1.1 |
695 | +import Unity 0.2 |
696 | +import "../Components" |
697 | +import "ScopeSettings" |
698 | + |
699 | +Item { |
700 | + id: root |
701 | + |
702 | + property var scope: null |
703 | + property var scopeStyle: null |
704 | + |
705 | + signal backClicked() |
706 | + |
707 | + PageHeader { |
708 | + id: header |
709 | + objectName: "pageHeader" |
710 | + width: parent.width |
711 | + title: scope ? scope.name : "" |
712 | + showBackButton: true |
713 | + scopeStyle: root.scopeStyle |
714 | + |
715 | + onBackClicked: root.backClicked() |
716 | + } |
717 | + |
718 | + ListView { |
719 | + id: scopeSettings |
720 | + objectName: "scopeSettings" |
721 | + anchors { |
722 | + top: header.bottom |
723 | + bottom: parent.bottom |
724 | + left: parent.left |
725 | + right: parent.right |
726 | + } |
727 | + model: root.scope ? root.scope.settings : null |
728 | + |
729 | + delegate: ScopeSettingsWidgetFactory { |
730 | + objectName: "scopeSettingItem" + index |
731 | + width: root.width |
732 | + widgetData: model |
733 | + scopeStyle: root.scopeStyle |
734 | + |
735 | + onUpdated: model.value = value; |
736 | + } |
737 | + } |
738 | +} |
739 | |
740 | === modified file 'qml/Dash/ScopesOverview.qml' |
741 | --- qml/Dash/ScopesOverview.qml 2014-08-27 08:28:24 +0000 |
742 | +++ qml/Dash/ScopesOverview.qml 2014-08-27 08:28:24 +0000 |
743 | @@ -468,6 +468,8 @@ |
744 | width: parent.width |
745 | height: parent.height |
746 | anchors.left: scopesOverviewContent.right |
747 | + |
748 | + onBackClicked: open = false |
749 | } |
750 | |
751 | Item { |
752 | |
753 | === modified file 'tests/autopilot/unity8/shell/emulators/dash.py' |
754 | --- tests/autopilot/unity8/shell/emulators/dash.py 2014-08-14 01:29:20 +0000 |
755 | +++ tests/autopilot/unity8/shell/emulators/dash.py 2014-08-27 08:28:24 +0000 |
756 | @@ -140,10 +140,9 @@ |
757 | |
758 | def enter_search_query(self, query): |
759 | current_header = self._get_current_page_header() |
760 | - self.pointing_device.move(current_header.globalRect.x + |
761 | - current_header.width - current_header.height / 4, |
762 | - current_header.globalRect.y + |
763 | - current_header.height / 4) |
764 | + search_button = current_header.select_single(objectName="search_header_button") |
765 | + self.pointing_device.move(search_button.globalRect.x + search_button.width / 2, |
766 | + search_button.globalRect.y + search_button.height / 2) |
767 | self.pointing_device.click() |
768 | headerContainer = current_header.select_single( |
769 | objectName="headerContainer") |
770 | @@ -186,7 +185,8 @@ |
771 | # --elopio - 2014-1-14 |
772 | self.click_scope_item(category, app_name) |
773 | preview_list = self.wait_select_single( |
774 | - 'PreviewListView', objectName='previewListView') |
775 | + 'QQuickLoader', objectName='subPageLoader') |
776 | + preview_list.subPageShown.wait_for(True) |
777 | preview_list.x.wait_for(0) |
778 | return preview_list.select_single( |
779 | Preview, objectName='preview{}'.format(preview_list.currentIndex)) |
780 | |
781 | === modified file 'tests/mocks/Unity/CMakeLists.txt' |
782 | --- tests/mocks/Unity/CMakeLists.txt 2014-08-25 10:05:13 +0000 |
783 | +++ tests/mocks/Unity/CMakeLists.txt 2014-08-27 08:28:24 +0000 |
784 | @@ -24,6 +24,7 @@ |
785 | fake_scope.cpp |
786 | fake_scopes.cpp |
787 | fake_scopesoverview.cpp |
788 | + fake_settingsmodel.cpp |
789 | fake_categories.cpp |
790 | fake_navigation.cpp |
791 | fake_resultsmodel.cpp |
792 | @@ -39,6 +40,7 @@ |
793 | ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/ResultsModelInterface.h |
794 | ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/ScopeInterface.h |
795 | ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/ScopesInterface.h |
796 | + ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/SettingsModelInterface.h |
797 | ) |
798 | |
799 | add_library(FakeUnityQml MODULE ${UnityQML_SOURCES}) |
800 | |
801 | === modified file 'tests/mocks/Unity/fake_scope.cpp' |
802 | --- tests/mocks/Unity/fake_scope.cpp 2014-08-27 08:28:24 +0000 |
803 | +++ tests/mocks/Unity/fake_scope.cpp 2014-08-27 08:28:24 +0000 |
804 | @@ -22,6 +22,7 @@ |
805 | #include "fake_navigation.h" |
806 | #include "fake_resultsmodel.h" |
807 | #include "fake_scopes.h" |
808 | +#include "fake_settingsmodel.h" |
809 | |
810 | Scope::Scope(Scopes* parent) : Scope(QString(), QString(), false, parent) |
811 | { |
812 | @@ -39,6 +40,7 @@ |
813 | , m_previewRendererName("preview-generic") |
814 | , m_categories(new Categories(categories, this)) |
815 | , m_openScope(nullptr) |
816 | + , m_settings(new SettingsModel(this)) |
817 | { |
818 | } |
819 | |
820 | @@ -94,7 +96,7 @@ |
821 | |
822 | unity::shell::scopes::SettingsModelInterface* Scope::settings() const |
823 | { |
824 | - return nullptr; |
825 | + return m_settings; |
826 | } |
827 | |
828 | QString Scope::noResultsHint() const |
829 | |
830 | === modified file 'tests/mocks/Unity/fake_scope.h' |
831 | --- tests/mocks/Unity/fake_scope.h 2014-08-07 08:52:59 +0000 |
832 | +++ tests/mocks/Unity/fake_scope.h 2014-08-27 08:28:24 +0000 |
833 | @@ -96,6 +96,7 @@ |
834 | |
835 | unity::shell::scopes::CategoriesInterface* m_categories; |
836 | unity::shell::scopes::ScopeInterface* m_openScope; |
837 | + unity::shell::scopes::SettingsModelInterface* m_settings; |
838 | }; |
839 | |
840 | #endif // FAKE_SCOPE_H |
841 | |
842 | === added file 'tests/mocks/Unity/fake_settingsmodel.cpp' |
843 | --- tests/mocks/Unity/fake_settingsmodel.cpp 1970-01-01 00:00:00 +0000 |
844 | +++ tests/mocks/Unity/fake_settingsmodel.cpp 2014-08-27 08:28:24 +0000 |
845 | @@ -0,0 +1,95 @@ |
846 | +/* |
847 | + * Copyright (C) 2014 Canonical, Ltd. |
848 | + * |
849 | + * This program is free software; you can redistribute it and/or modify |
850 | + * it under the terms of the GNU General Public License as published by |
851 | + * the Free Software Foundation; version 3. |
852 | + * |
853 | + * This program is distributed in the hope that it will be useful, |
854 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
855 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
856 | + * GNU General Public License for more details. |
857 | + * |
858 | + * You should have received a copy of the GNU General Public License |
859 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
860 | + */ |
861 | + |
862 | +#include "fake_settingsmodel.h" |
863 | + |
864 | +SettingsModel::SettingsModel(QObject* parent) : |
865 | + SettingsModelInterface(parent) { |
866 | + { |
867 | + QVariantMap parameters; |
868 | + m_data << QSharedPointer<Data>(new Data("boolean-setting", "Boolean Setting", "boolean", parameters, true)); |
869 | + } |
870 | + { |
871 | + QVariantMap parameters; |
872 | + parameters["values"] = QVariantList() << "First" << "Second" << "Third"; |
873 | + m_data << QSharedPointer<Data>(new Data("list-setting", "List Setting", "list", parameters, 1)); |
874 | + } |
875 | + { |
876 | + QVariantMap parameters; |
877 | + m_data << QSharedPointer<Data>(new Data("number-setting", "Number Setting", "number", parameters, 1.23)); |
878 | + } |
879 | + { |
880 | + QVariantMap parameters; |
881 | + m_data << QSharedPointer<Data>(new Data("string-setting", "String Setting", "string", parameters, "flibble")); |
882 | + } |
883 | +} |
884 | + |
885 | +QVariant SettingsModel::data(const QModelIndex& index, int role) const { |
886 | + int row = index.row(); |
887 | + QVariant result; |
888 | + |
889 | + if (row < m_data.size()) { |
890 | + auto data = m_data[row]; |
891 | + |
892 | + switch (role) { |
893 | + case Roles::RoleSettingId: |
894 | + result = data->id; |
895 | + break; |
896 | + case Roles::RoleDisplayName: |
897 | + result = data->displayName; |
898 | + break; |
899 | + case Roles::RoleType: |
900 | + result = data->type; |
901 | + break; |
902 | + case Roles::RoleProperties: |
903 | + result = data->properties; |
904 | + break; |
905 | + case Roles::RoleValue: { |
906 | + result = data->value; |
907 | + break; |
908 | + } |
909 | + default: |
910 | + break; |
911 | + } |
912 | + } |
913 | + |
914 | + return result; |
915 | +} |
916 | + |
917 | +bool SettingsModel::setData(const QModelIndex &index, const QVariant &value, int role) { |
918 | + int row = index.row(); |
919 | + if (row < m_data.size()) { |
920 | + switch (role) { |
921 | + case SettingsModelInterface::RoleValue: { |
922 | + auto data = m_data[row]; |
923 | + data->value = value; |
924 | + return true; |
925 | + } |
926 | + default: |
927 | + break; |
928 | + } |
929 | + } |
930 | + |
931 | + return false; |
932 | +} |
933 | + |
934 | +int SettingsModel::rowCount(const QModelIndex&) const { |
935 | + return count(); |
936 | +} |
937 | + |
938 | +int SettingsModel::count() const { |
939 | + return m_data.size(); |
940 | +} |
941 | |
942 | === added file 'tests/mocks/Unity/fake_settingsmodel.h' |
943 | --- tests/mocks/Unity/fake_settingsmodel.h 1970-01-01 00:00:00 +0000 |
944 | +++ tests/mocks/Unity/fake_settingsmodel.h 2014-08-27 08:28:24 +0000 |
945 | @@ -0,0 +1,54 @@ |
946 | +/* |
947 | + * Copyright (C) 2014 Canonical, Ltd. |
948 | + * |
949 | + * This program is free software; you can redistribute it and/or modify |
950 | + * it under the terms of the GNU General Public License as published by |
951 | + * the Free Software Foundation; version 3. |
952 | + * |
953 | + * This program is distributed in the hope that it will be useful, |
954 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
955 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
956 | + * GNU General Public License for more details. |
957 | + * |
958 | + * You should have received a copy of the GNU General Public License |
959 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
960 | + */ |
961 | + |
962 | +#ifndef FAKE_SETTINGSMODEL_H |
963 | +#define FAKE_SETTINGSMODEL_H |
964 | + |
965 | +#include <unity/shell/scopes/SettingsModelInterface.h> |
966 | + |
967 | +#include <QList> |
968 | +#include <QSharedPointer> |
969 | + |
970 | +class SettingsModel: public unity::shell::scopes::SettingsModelInterface { |
971 | +Q_OBJECT |
972 | + |
973 | + struct Data { |
974 | + QString id; |
975 | + QString displayName; |
976 | + QString type; |
977 | + QVariant properties; |
978 | + QVariant value; |
979 | + |
980 | + Data(QString const& id_, QString const& displayName_, |
981 | + QString const& type_, QVariant const& properties_, |
982 | + QVariant const& value_) : |
983 | + id(id_), displayName(displayName_), type(type_), |
984 | + properties(properties_), value(value_) {} |
985 | + }; |
986 | + |
987 | +public: |
988 | + explicit SettingsModel(QObject* parent = 0); |
989 | + ~SettingsModel() = default; |
990 | + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; |
991 | + bool setData(const QModelIndex&index, const QVariant& value, int role = Qt::EditRole) override; |
992 | + int rowCount(const QModelIndex& parent = QModelIndex()) const override; |
993 | + int count() const override; |
994 | + |
995 | +protected: |
996 | + QList<QSharedPointer<Data>> m_data; |
997 | +}; |
998 | + |
999 | +#endif // FAKE_SETTINGSMODEL_H |
1000 | |
1001 | === modified file 'tests/mocks/Unity/fake_unity_plugin.cpp' |
1002 | --- tests/mocks/Unity/fake_unity_plugin.cpp 2014-08-11 09:57:29 +0000 |
1003 | +++ tests/mocks/Unity/fake_unity_plugin.cpp 2014-08-27 08:28:24 +0000 |
1004 | @@ -26,6 +26,7 @@ |
1005 | #include "fake_previewmodel.h" |
1006 | #include "fake_previewwidgetmodel.h" |
1007 | #include "fake_resultsmodel.h" |
1008 | +#include "fake_settingsmodel.h" |
1009 | |
1010 | // External |
1011 | #include <glib-object.h> |
1012 | @@ -43,6 +44,7 @@ |
1013 | qmlRegisterType<Scopes>(uri, 0, 2, "Scopes"); |
1014 | qmlRegisterType<Scope>(uri, 0, 2, "MockScope"); |
1015 | qmlRegisterUncreatableType<unity::shell::scopes::ScopeInterface>(uri, 0, 2, "Scope", "Can't create Scope object in QML."); |
1016 | + qmlRegisterUncreatableType<unity::shell::scopes::SettingsModelInterface>(uri, 0, 2, "SettingsModel", "Can't create SettingsModel object in QML."); |
1017 | qmlRegisterUncreatableType<unity::shell::scopes::NavigationInterface>(uri, 0, 2, "Navigation", "Can't create Navigation object in QML."); |
1018 | qmlRegisterUncreatableType<unity::shell::scopes::CategoriesInterface>(uri, 0, 2, "Categories", "Can't create Categories object in QML."); |
1019 | qmlRegisterUncreatableType<unity::shell::scopes::PreviewModelInterface>(uri, 0, 2, "PreviewModel", "Can't create new PreviewModel in QML. Get them from PreviewStack instance."); |
1020 | |
1021 | === modified file 'tests/qmltests/CMakeLists.txt' |
1022 | --- tests/qmltests/CMakeLists.txt 2014-08-27 08:28:24 +0000 |
1023 | +++ tests/qmltests/CMakeLists.txt 2014-08-27 08:28:24 +0000 |
1024 | @@ -55,6 +55,11 @@ |
1025 | add_qml_test(Dash/Previews PreviewVideoPlayback) |
1026 | add_qml_test(Dash/Previews PreviewWidgetFactory) |
1027 | add_qml_test(Dash/Previews PreviewZoomableImage) |
1028 | +add_qml_test(Dash/ScopeSettings ScopeSettingBoolean) |
1029 | +add_qml_test(Dash/ScopeSettings ScopeSettingList) |
1030 | +add_qml_test(Dash/ScopeSettings ScopeSettingNumber) |
1031 | +add_qml_test(Dash/ScopeSettings ScopeSettingString) |
1032 | +add_qml_test(Dash/ScopeSettings ScopeSettingsWidgetFactory) |
1033 | add_qml_test(Greeter Lockscreen ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full") |
1034 | add_qml_test(Greeter MultiGreeter ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full") |
1035 | add_qml_test(Greeter SingleGreeter ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single") |
1036 | |
1037 | === modified file 'tests/qmltests/Dash/Previews/tst_PreviewWidgetFactory.qml' |
1038 | --- tests/qmltests/Dash/Previews/tst_PreviewWidgetFactory.qml 2014-08-27 08:28:24 +0000 |
1039 | +++ tests/qmltests/Dash/Previews/tst_PreviewWidgetFactory.qml 2014-08-27 08:28:24 +0000 |
1040 | @@ -94,7 +94,7 @@ |
1041 | factory.widgetData = { type: data.type }; |
1042 | factory.widgetType = data.type; |
1043 | |
1044 | - verify(("" + factory.source).indexOf(data.source) != -1); |
1045 | + verify((String(factory.source)).indexOf(data.source) != -1); |
1046 | } |
1047 | } |
1048 | } |
1049 | |
1050 | === added directory 'tests/qmltests/Dash/ScopeSettings' |
1051 | === added file 'tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingBoolean.qml' |
1052 | --- tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingBoolean.qml 1970-01-01 00:00:00 +0000 |
1053 | +++ tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingBoolean.qml 2014-08-27 08:28:24 +0000 |
1054 | @@ -0,0 +1,62 @@ |
1055 | +/* |
1056 | + * Copyright 2014 Canonical Ltd. |
1057 | + * |
1058 | + * This program is free software; you can redistribute it and/or modify |
1059 | + * it under the terms of the GNU General Public License as published by |
1060 | + * the Free Software Foundation; version 3. |
1061 | + * |
1062 | + * This program is distributed in the hope that it will be useful, |
1063 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1064 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1065 | + * GNU General Public License for more details. |
1066 | + * |
1067 | + * You should have received a copy of the GNU General Public License |
1068 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1069 | + */ |
1070 | + |
1071 | +import QtQuick 2.0 |
1072 | +import Ubuntu.Components 1.1 |
1073 | +import QtTest 1.0 |
1074 | +import "../../../../qml/Dash/ScopeSettings" |
1075 | +import Unity.Test 0.1 as UT |
1076 | + |
1077 | +Rectangle { |
1078 | + id: root |
1079 | + width: units.gu(40) |
1080 | + height: units.gu(80) |
1081 | + |
1082 | + property var settingData: { |
1083 | + "displayName" : "Mock boolean setting", |
1084 | + "value": true |
1085 | + } |
1086 | + |
1087 | + ScopeSettingBoolean { |
1088 | + id: scopeSetting |
1089 | + widgetData: settingData |
1090 | + width: parent.width |
1091 | + } |
1092 | + |
1093 | + SignalSpy { |
1094 | + id: spy |
1095 | + target: scopeSetting |
1096 | + signalName: "updated" |
1097 | + } |
1098 | + |
1099 | + UT.UnityTestCase { |
1100 | + id: testCase |
1101 | + name: "ScopeSettingBoolean" |
1102 | + when: windowShown |
1103 | + |
1104 | + function test_updated() { |
1105 | + var control = findChild(scopeSetting, "control"); |
1106 | + mouseClick(control, control.width / 2, control.height / 2); |
1107 | + spy.wait(); |
1108 | + compare(spy.signalArguments[0][0], false); |
1109 | + |
1110 | + spy.clear(); |
1111 | + mouseClick(scopeSetting, scopeSetting.width / 2, scopeSetting.height / 2); |
1112 | + spy.wait(); |
1113 | + compare(spy.signalArguments[0][0], true); |
1114 | + } |
1115 | + } |
1116 | +} |
1117 | |
1118 | === added file 'tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingList.qml' |
1119 | --- tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingList.qml 1970-01-01 00:00:00 +0000 |
1120 | +++ tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingList.qml 2014-08-27 08:28:24 +0000 |
1121 | @@ -0,0 +1,84 @@ |
1122 | +/* |
1123 | + * Copyright 2014 Canonical Ltd. |
1124 | + * |
1125 | + * This program is free software; you can redistribute it and/or modify |
1126 | + * it under the terms of the GNU General Public License as published by |
1127 | + * the Free Software Foundation; version 3. |
1128 | + * |
1129 | + * This program is distributed in the hope that it will be useful, |
1130 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1131 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1132 | + * GNU General Public License for more details. |
1133 | + * |
1134 | + * You should have received a copy of the GNU General Public License |
1135 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1136 | + */ |
1137 | + |
1138 | +import QtQuick 2.0 |
1139 | +import Ubuntu.Components 1.1 |
1140 | +import QtTest 1.0 |
1141 | +import "../../../../qml/Dash/ScopeSettings" |
1142 | +import Unity.Test 0.1 as UT |
1143 | + |
1144 | +Rectangle { |
1145 | + id: root |
1146 | + width: units.gu(40) |
1147 | + height: units.gu(80) |
1148 | + |
1149 | + property var settingData: { |
1150 | + "displayName" : "Mock list setting", |
1151 | + "properties": { "values" : [ "first", "second", "third" ] } |
1152 | + } |
1153 | + |
1154 | + ScopeSettingList { |
1155 | + id: scopeSetting |
1156 | + width: parent.width |
1157 | + widgetData: settingData |
1158 | + } |
1159 | + |
1160 | + SignalSpy { |
1161 | + id: spy |
1162 | + target: scopeSetting |
1163 | + signalName: "updated" |
1164 | + } |
1165 | + |
1166 | + UT.UnityTestCase { |
1167 | + id: testCase |
1168 | + name: "ScopeSettingList" |
1169 | + when: windowShown |
1170 | + |
1171 | + property var control: findChild(scopeSetting, "control") |
1172 | + |
1173 | + function cleanup() { |
1174 | + control.selectedIndex = 0; |
1175 | + spy.clear(); |
1176 | + } |
1177 | + |
1178 | + function test_initialValue() { |
1179 | + // there's no initialIndex, so we workaround, testing is difficult too https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/1362031 |
1180 | + var newObject = Qt.createQmlObject('import "../../../../qml/Dash/ScopeSettings" \n\ |
1181 | + ScopeSettingList { initialValue: 2; }', root, "dynamicScopeSettingList"); |
1182 | + newObject.widgetData = settingData; |
1183 | + var controlDynamic = findChild(newObject, "control"); |
1184 | + tryCompare(controlDynamic, "selectedIndex", 2); |
1185 | + } |
1186 | + |
1187 | + function test_updated_data() { |
1188 | + return [ |
1189 | + { tag: "current", index: 0, updated: false }, |
1190 | + { tag: "second", index: 1, updated: true }, |
1191 | + { tag: "third", index: 2, updated: true } |
1192 | + ] |
1193 | + } |
1194 | + |
1195 | + function test_updated(data) { |
1196 | + control.selectedIndex = data.index; |
1197 | + if (data.updated) { |
1198 | + spy.wait(); |
1199 | + compare(spy.signalArguments[0][0], data.index); |
1200 | + } else { |
1201 | + compare(spy.count, 0); |
1202 | + } |
1203 | + } |
1204 | + } |
1205 | +} |
1206 | |
1207 | === added file 'tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingNumber.qml' |
1208 | --- tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingNumber.qml 1970-01-01 00:00:00 +0000 |
1209 | +++ tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingNumber.qml 2014-08-27 08:28:24 +0000 |
1210 | @@ -0,0 +1,98 @@ |
1211 | +/* |
1212 | + * Copyright 2014 Canonical Ltd. |
1213 | + * |
1214 | + * This program is free software; you can redistribute it and/or modify |
1215 | + * it under the terms of the GNU General Public License as published by |
1216 | + * the Free Software Foundation; version 3. |
1217 | + * |
1218 | + * This program is distributed in the hope that it will be useful, |
1219 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1220 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1221 | + * GNU General Public License for more details. |
1222 | + * |
1223 | + * You should have received a copy of the GNU General Public License |
1224 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1225 | + */ |
1226 | + |
1227 | +import QtQuick 2.0 |
1228 | +import Ubuntu.Components 1.1 |
1229 | +import QtTest 1.0 |
1230 | +import "../../../../qml/Dash/ScopeSettings" |
1231 | +import Unity.Test 0.1 as UT |
1232 | + |
1233 | +Rectangle { |
1234 | + id: root |
1235 | + width: units.gu(40) |
1236 | + height: units.gu(80) |
1237 | + |
1238 | + property var settingData: { |
1239 | + "displayName" : "Mock number setting", |
1240 | + "value": 0.2 |
1241 | + } |
1242 | + |
1243 | + ScopeSettingNumber { |
1244 | + id: scopeSetting |
1245 | + widgetData: settingData |
1246 | + width: parent.width |
1247 | + } |
1248 | + |
1249 | + SignalSpy { |
1250 | + id: spy |
1251 | + target: scopeSetting |
1252 | + signalName: "updated" |
1253 | + } |
1254 | + |
1255 | + UT.UnityTestCase { |
1256 | + id: testCase |
1257 | + name: "ScopeSettingNumber" |
1258 | + when: windowShown |
1259 | + |
1260 | + property var control: findChild(scopeSetting, "control") |
1261 | + property real newNumber: 11.7 |
1262 | + |
1263 | + function cleanup() { |
1264 | + control.focus = false; |
1265 | + control.text = settingData.value; |
1266 | + spy.clear(); |
1267 | + } |
1268 | + |
1269 | + function test_updated_on_unfocus() { |
1270 | + mouseClick(control, control.width / 2, control.height / 2); |
1271 | + control.selectAll(); |
1272 | + control.cut(); |
1273 | + control.insert(0, newNumber); |
1274 | + control.focus = false; |
1275 | + spy.wait(); |
1276 | + verify(spy.signalArguments[0][0] == newNumber); |
1277 | + } |
1278 | + |
1279 | + function test_updated_on_accepted() { |
1280 | + mouseClick(control, control.width / 2, control.height / 2); |
1281 | + control.selectAll(); |
1282 | + control.cut(); |
1283 | + control.insert(0, newNumber); |
1284 | + control.accepted(); |
1285 | + spy.wait(); |
1286 | + verify(spy.signalArguments[0][0] == newNumber); |
1287 | + } |
1288 | + |
1289 | + function test_selection_on_listitem_click() { |
1290 | + mouseClick(scopeSetting, 0, scopeSetting.height / 2); |
1291 | + compare(control.focus, true); |
1292 | + // we're checking that selectAll() is being called by omitting it here |
1293 | + control.cut(); |
1294 | + control.insert(0, newNumber); |
1295 | + verify(control.displayText == newNumber); |
1296 | + } |
1297 | + |
1298 | + function test_unacceptable_input() { |
1299 | + mouseClick(control, control.width / 2, control.height / 2); |
1300 | + control.selectAll(); |
1301 | + control.cut(); |
1302 | + control.insert(0, "not valid"); |
1303 | + control.accepted(); |
1304 | + compare(spy.count, 0); |
1305 | + compare(control.displayText, ""); |
1306 | + } |
1307 | + } |
1308 | +} |
1309 | |
1310 | === added file 'tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingString.qml' |
1311 | --- tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingString.qml 1970-01-01 00:00:00 +0000 |
1312 | +++ tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingString.qml 2014-08-27 08:28:24 +0000 |
1313 | @@ -0,0 +1,88 @@ |
1314 | +/* |
1315 | + * Copyright 2014 Canonical Ltd. |
1316 | + * |
1317 | + * This program is free software; you can redistribute it and/or modify |
1318 | + * it under the terms of the GNU General Public License as published by |
1319 | + * the Free Software Foundation; version 3. |
1320 | + * |
1321 | + * This program is distributed in the hope that it will be useful, |
1322 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1323 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1324 | + * GNU General Public License for more details. |
1325 | + * |
1326 | + * You should have received a copy of the GNU General Public License |
1327 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1328 | + */ |
1329 | + |
1330 | +import QtQuick 2.0 |
1331 | +import Ubuntu.Components 1.1 |
1332 | +import QtTest 1.0 |
1333 | +import "../../../../qml/Dash/ScopeSettings" |
1334 | +import Unity.Test 0.1 as UT |
1335 | + |
1336 | +Rectangle { |
1337 | + id: root |
1338 | + width: units.gu(40) |
1339 | + height: units.gu(80) |
1340 | + |
1341 | + property var settingData: { |
1342 | + "displayName" : "Mock string setting", |
1343 | + "value": "mock string" |
1344 | + } |
1345 | + |
1346 | + ScopeSettingString { |
1347 | + id: scopeSetting |
1348 | + widgetData: settingData |
1349 | + width: parent.width |
1350 | + } |
1351 | + |
1352 | + SignalSpy { |
1353 | + id: spy |
1354 | + target: scopeSetting |
1355 | + signalName: "updated" |
1356 | + } |
1357 | + |
1358 | + UT.UnityTestCase { |
1359 | + id: testCase |
1360 | + name: "ScopeSettingString" |
1361 | + when: windowShown |
1362 | + |
1363 | + property var control: findChild(scopeSetting, "control") |
1364 | + property string newText: "new text to compare" |
1365 | + |
1366 | + function cleanup() { |
1367 | + control.focus = false; |
1368 | + control.text = settingData.value; |
1369 | + spy.clear(); |
1370 | + } |
1371 | + |
1372 | + function test_updated_on_unfocus() { |
1373 | + mouseClick(control, control.width / 2, control.height / 2); |
1374 | + control.selectAll(); |
1375 | + control.cut(); |
1376 | + control.insert(0, newText); |
1377 | + control.focus = false; |
1378 | + spy.wait(); |
1379 | + compare(spy.signalArguments[0][0], newText); |
1380 | + } |
1381 | + |
1382 | + function test_updated_on_accepted() { |
1383 | + mouseClick(control, control.width / 2, control.height / 2); |
1384 | + control.selectAll(); |
1385 | + control.cut(); |
1386 | + control.insert(0, newText); |
1387 | + control.accepted(); |
1388 | + spy.wait(); |
1389 | + compare(spy.signalArguments[0][0], newText); |
1390 | + } |
1391 | + |
1392 | + function test_selection_on_listitem_click() { |
1393 | + mouseClick(scopeSetting, 0, scopeSetting.height / 2); |
1394 | + compare(control.focus, true); |
1395 | + // we're checking that selectAll() is being called by omitting it here |
1396 | + control.cut(); |
1397 | + control.insert(0, newText); |
1398 | + compare(control.displayText, newText); |
1399 | + } |
1400 | + } |
1401 | +} |
1402 | |
1403 | === added file 'tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingsWidgetFactory.qml' |
1404 | --- tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingsWidgetFactory.qml 1970-01-01 00:00:00 +0000 |
1405 | +++ tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingsWidgetFactory.qml 2014-08-27 08:28:24 +0000 |
1406 | @@ -0,0 +1,65 @@ |
1407 | +/* |
1408 | + * Copyright 2014 Canonical Ltd. |
1409 | + * |
1410 | + * This program is free software; you can redistribute it and/or modify |
1411 | + * it under the terms of the GNU General Public License as published by |
1412 | + * the Free Software Foundation; version 3. |
1413 | + * |
1414 | + * This program is distributed in the hope that it will be useful, |
1415 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1416 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1417 | + * GNU General Public License for more details. |
1418 | + * |
1419 | + * You should have received a copy of the GNU General Public License |
1420 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1421 | + */ |
1422 | + |
1423 | +import QtQuick 2.0 |
1424 | +import Ubuntu.Components 1.1 |
1425 | +import QtTest 1.0 |
1426 | +import "../../../../qml/Dash/ScopeSettings" |
1427 | +import Unity.Test 0.1 as UT |
1428 | + |
1429 | +Rectangle { |
1430 | + id: root |
1431 | + width: units.gu(40) |
1432 | + height: units.gu(80) |
1433 | + |
1434 | + property var settingData: { |
1435 | + "type": "", |
1436 | + "displayName" : "Mock setting", |
1437 | + "value": "1", |
1438 | + "properties": { "values" : [ "first", "second", "third" ] } |
1439 | + } |
1440 | + |
1441 | + ScopeSettingsWidgetFactory { |
1442 | + id: scopeSettingsWidgetFactory |
1443 | + anchors { |
1444 | + left: parent.left |
1445 | + right: parent.right |
1446 | + } |
1447 | + } |
1448 | + |
1449 | + UT.UnityTestCase { |
1450 | + id: testCase |
1451 | + name: "ScopeSettingWidgetFactory" |
1452 | + when: windowShown |
1453 | + |
1454 | + function test_mapping_data() { |
1455 | + return [ |
1456 | + { tag: "Boolean", type: "boolean", source: "ScopeSettingBoolean.qml" }, |
1457 | + { tag: "List", type: "list", source: "ScopeSettingList.qml" }, |
1458 | + { tag: "Number", type: "number", source: "ScopeSettingNumber.qml" }, |
1459 | + { tag: "String", type: "string", source: "ScopeSettingString.qml" } |
1460 | + ]; |
1461 | + } |
1462 | + |
1463 | + function test_mapping(data) { |
1464 | + var newSettingData = settingData; |
1465 | + newSettingData.type = data.type; |
1466 | + scopeSettingsWidgetFactory.widgetData = newSettingData; |
1467 | + |
1468 | + verify((String(scopeSettingsWidgetFactory.source)).indexOf(data.source) != -1); |
1469 | + } |
1470 | + } |
1471 | +} |
1472 | |
1473 | === modified file 'tests/qmltests/Dash/tst_GenericScopeView.qml' |
1474 | --- tests/qmltests/Dash/tst_GenericScopeView.qml 2014-08-27 08:28:24 +0000 |
1475 | +++ tests/qmltests/Dash/tst_GenericScopeView.qml 2014-08-27 08:28:24 +0000 |
1476 | @@ -39,6 +39,8 @@ |
1477 | |
1478 | Scopes { |
1479 | id: scopes |
1480 | + // for tryGenericScopeView |
1481 | + onLoadedChanged: if (loaded) genericScopeView.scope = scopes.getScope(2); |
1482 | } |
1483 | |
1484 | SignalSpy { |
1485 | @@ -59,7 +61,7 @@ |
1486 | name: "GenericScopeView" |
1487 | when: scopes.loaded && windowShown |
1488 | |
1489 | - property Item previewListView: findChild(genericScopeView, "previewListView") |
1490 | + property Item subPageLoader: findChild(genericScopeView, "subPageLoader") |
1491 | property Item header: findChild(genericScopeView, "scopePageHeader") |
1492 | |
1493 | function init() { |
1494 | @@ -94,24 +96,24 @@ |
1495 | tryCompare(genericScopeView.scope, "isActive", false) |
1496 | genericScopeView.isCurrent = true |
1497 | tryCompare(genericScopeView.scope, "isActive", true) |
1498 | - testCase.previewListView.open = true |
1499 | + testCase.subPageLoader.open = true |
1500 | tryCompare(genericScopeView.scope, "isActive", false) |
1501 | - testCase.previewListView.open = false |
1502 | + testCase.subPageLoader.open = false |
1503 | tryCompare(genericScopeView.scope, "isActive", true) |
1504 | genericScopeView.isCurrent = false |
1505 | tryCompare(genericScopeView.scope, "isActive", false) |
1506 | } |
1507 | |
1508 | function test_showDash() { |
1509 | - testCase.previewListView.open = true; |
1510 | + testCase.subPageLoader.open = true; |
1511 | genericScopeView.scope.showDash(); |
1512 | - tryCompare(testCase.previewListView, "open", false); |
1513 | + tryCompare(testCase.subPageLoader, "open", false); |
1514 | } |
1515 | |
1516 | function test_hideDash() { |
1517 | - testCase.previewListView.open = true; |
1518 | + testCase.subPageLoader.open = true; |
1519 | genericScopeView.scope.hideDash(); |
1520 | - tryCompare(testCase.previewListView, "open", false); |
1521 | + tryCompare(testCase.subPageLoader, "open", false); |
1522 | } |
1523 | |
1524 | function test_searchQuery() { |
1525 | @@ -214,7 +216,7 @@ |
1526 | |
1527 | openPreview(4, 0); |
1528 | |
1529 | - compare(testCase.previewListView.count, 12, "There should only be 12 items in preview."); |
1530 | + compare(testCase.subPageLoader.count, 12, "There should only be 12 items in preview."); |
1531 | |
1532 | closePreview(); |
1533 | } |
1534 | @@ -276,19 +278,21 @@ |
1535 | true); |
1536 | var tile = findChild(findChild(genericScopeView, category), "delegate"+delegate); |
1537 | mouseClick(tile, tile.width / 2, tile.height / 2); |
1538 | - tryCompare(testCase.previewListView, "open", true); |
1539 | - tryCompare(testCase.previewListView, "x", 0); |
1540 | + tryCompare(testCase.subPageLoader, "open", true); |
1541 | + tryCompare(testCase.subPageLoader, "x", 0); |
1542 | } |
1543 | |
1544 | function closePreview() { |
1545 | - var closePreviewMouseArea = findChild(genericScopeView, "innerPageHeader"); |
1546 | + var closePreviewMouseArea = findChild(subPageLoader.item, "pageHeader"); |
1547 | mouseClick(closePreviewMouseArea, units.gu(2), units.gu(2)); |
1548 | |
1549 | - tryCompare(testCase.previewListView, "open", false); |
1550 | + tryCompare(testCase.subPageLoader, "open", false); |
1551 | + tryCompare(testCase.subPageLoader, "visible", false); |
1552 | } |
1553 | |
1554 | function test_previewOpenClose() { |
1555 | - tryCompare(testCase.previewListView, "open", false); |
1556 | + tryCompare(testCase.subPageLoader, "open", false); |
1557 | + tryCompare(testCase.subPageLoader, "visible", false); |
1558 | |
1559 | var categoryListView = findChild(genericScopeView, "categoryListView"); |
1560 | categoryListView.positionAtBeginning(); |
1561 | @@ -300,7 +304,7 @@ |
1562 | function test_showPreviewCarousel() { |
1563 | var category = scrollToCategory("dashCategory1"); |
1564 | |
1565 | - tryCompare(testCase.previewListView, "open", false); |
1566 | + tryCompare(testCase.subPageLoader, "open", false); |
1567 | |
1568 | var tile = findChild(category, "carouselDelegate1"); |
1569 | verify(tile, "Could not find delegate"); |
1570 | @@ -308,14 +312,14 @@ |
1571 | mouseClick(tile, tile.width / 2, tile.height / 2); |
1572 | tryCompare(tile, "explicitlyScaled", true); |
1573 | mouseClick(tile, tile.width / 2, tile.height / 2); |
1574 | - tryCompare(testCase.previewListView, "open", true); |
1575 | - tryCompare(testCase.previewListView, "x", 0); |
1576 | + tryCompare(testCase.subPageLoader, "open", true); |
1577 | + tryCompare(testCase.subPageLoader, "x", 0); |
1578 | |
1579 | closePreview(); |
1580 | |
1581 | mousePress(tile, tile.width / 2, tile.height / 2); |
1582 | - tryCompare(testCase.previewListView, "open", true); |
1583 | - tryCompare(testCase.previewListView, "x", 0); |
1584 | + tryCompare(testCase.subPageLoader, "open", true); |
1585 | + tryCompare(testCase.subPageLoader, "x", 0); |
1586 | mouseRelease(tile, tile.width / 2, tile.height / 2); |
1587 | |
1588 | closePreview(); |
1589 | @@ -324,20 +328,20 @@ |
1590 | function test_showPreviewHorizontalList() { |
1591 | var category = scrollToCategory("dashCategory18"); |
1592 | |
1593 | - tryCompare(testCase.previewListView, "open", false); |
1594 | + tryCompare(testCase.subPageLoader, "open", false); |
1595 | |
1596 | var tile = findChild(category, "delegate1"); |
1597 | verify(tile, "Could not find delegate"); |
1598 | |
1599 | mouseClick(tile, tile.width / 2, tile.height / 2); |
1600 | - tryCompare(testCase.previewListView, "open", true); |
1601 | - tryCompare(testCase.previewListView, "x", 0); |
1602 | + tryCompare(testCase.subPageLoader, "open", true); |
1603 | + tryCompare(testCase.subPageLoader, "x", 0); |
1604 | |
1605 | closePreview(); |
1606 | |
1607 | mousePress(tile, tile.width / 2, tile.height / 2); |
1608 | - tryCompare(testCase.previewListView, "open", true); |
1609 | - tryCompare(testCase.previewListView, "x", 0); |
1610 | + tryCompare(testCase.subPageLoader, "open", true); |
1611 | + tryCompare(testCase.subPageLoader, "x", 0); |
1612 | mouseRelease(tile, tile.width / 2, tile.height / 2); |
1613 | |
1614 | closePreview(); |
1615 | @@ -347,25 +351,52 @@ |
1616 | var categoryListView = findChild(genericScopeView, "categoryListView"); |
1617 | categoryListView.positionAtBeginning(); |
1618 | |
1619 | - tryCompare(testCase.previewListView, "open", false); |
1620 | - var previewListViewList = findChild(previewListView, "listView"); |
1621 | + tryCompare(testCase.subPageLoader, "open", false); |
1622 | |
1623 | openPreview(); |
1624 | + var previewListViewList = findChild(subPageLoader.item, "listView"); |
1625 | |
1626 | // flick to the next previews |
1627 | - tryCompare(testCase.previewListView, "count", 15); |
1628 | - for (var i = 1; i < testCase.previewListView.count; ++i) { |
1629 | - mouseFlick(testCase.previewListView, testCase.previewListView.width - units.gu(1), |
1630 | - testCase.previewListView.height / 2, |
1631 | + tryCompare(testCase.subPageLoader, "count", 15); |
1632 | + for (var i = 1; i < testCase.subPageLoader.count; ++i) { |
1633 | + mouseFlick(testCase.subPageLoader.item, testCase.subPageLoader.width - units.gu(1), |
1634 | + testCase.subPageLoader.height / 2, |
1635 | units.gu(2), |
1636 | - testCase.previewListView.height / 2); |
1637 | + testCase.subPageLoader.height / 2); |
1638 | tryCompare(previewListViewList, "moving", false); |
1639 | - tryCompare(testCase.previewListView.currentItem, "objectName", "preview" + i); |
1640 | - |
1641 | + tryCompare(testCase.subPageLoader.currentItem, "objectName", "preview" + i); |
1642 | } |
1643 | closePreview(); |
1644 | } |
1645 | |
1646 | + function test_settingsOpenClose() { |
1647 | + waitForRendering(genericScopeView); |
1648 | + verify(header, "Could not find the header."); |
1649 | + var innerHeader = findChild(header, "innerPageHeader"); |
1650 | + verify(innerHeader, "Could not find the inner header"); |
1651 | + |
1652 | + // open |
1653 | + tryCompare(testCase.subPageLoader, "open", false); |
1654 | + tryCompare(testCase.subPageLoader, "visible", false); |
1655 | + var settings = findChild(innerHeader, "settings_header_button"); |
1656 | + mouseClick(settings, settings.width / 2, settings.height / 2); |
1657 | + tryCompare(testCase.subPageLoader, "open", true); |
1658 | + tryCompareFunction(function() { return (String(subPageLoader.source)).indexOf("ScopeSettingsPage.qml") != -1; }, true); |
1659 | + tryCompare(genericScopeView, "subPageShown", true); |
1660 | + compare(testCase.subPageLoader.subPage, "settings"); |
1661 | + tryCompare(testCase.subPageLoader, "x", 0); |
1662 | + |
1663 | + // close |
1664 | + var settingsHeader = findChild(testCase.subPageLoader.item, "pageHeader"); |
1665 | + mouseClick(settingsHeader, units.gu(2), units.gu(2)); |
1666 | + tryCompare(testCase.subPageLoader, "open", false); |
1667 | + tryCompare(genericScopeView, "subPageShown", false); |
1668 | + var categoryListView = findChild(genericScopeView, "categoryListView"); |
1669 | + tryCompare(categoryListView, "x", 0); |
1670 | + tryCompare(testCase.subPageLoader, "visible", false); |
1671 | + tryCompare(testCase.subPageLoader, "source", ""); |
1672 | + } |
1673 | + |
1674 | function test_header_style_data() { |
1675 | return [ |
1676 | { tag: "Default", index: 0, foreground: UbuntuColors.darkGrey, background: "color:///#f5f5f5", logo: "" }, |
FAILED: Continuous integration, rev:1113 jenkins. qa.ubuntu. com/job/ unity8- ci/3844/ jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- utopic- touch/3273/ console jenkins. qa.ubuntu. com/job/ unity-phablet- qmluitests- utopic/ 846/console jenkins. qa.ubuntu. com/job/ unity8- utopic- amd64-ci/ 938/console jenkins. qa.ubuntu. com/job/ unity8- utopic- armhf-ci/ 938/console jenkins. qa.ubuntu. com/job/ unity8- utopic- i386-ci/ 938/console jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- armhf/4518/ console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/unity8- ci/3844/ rebuild
http://