Merge lp:~aacid/unity8/dash_overview into lp:unity8
- dash_overview
- Merge into trunk
Status: | Superseded | ||||
---|---|---|---|---|---|
Proposed branch: | lp:~aacid/unity8/dash_overview | ||||
Merge into: | lp:unity8 | ||||
Prerequisite: | lp:~saviq/unity8/category-header-links | ||||
Diff against target: |
2668 lines (+1767/-106) 35 files modified
data/unity8.conf (+1/-1) debian/control (+1/-1) plugins/Dash/CardCreator.js (+2/-1) plugins/Dash/ScopeStyle.qml (+2/-2) plugins/Dash/listviewwithpageheader.cpp (+2/-2) po/unity8.pot (+44/-12) qml/Components/PageHeader.qml (+26/-8) qml/Components/ResponsiveGridView.qml (+3/-3) qml/Dash/CardCarousel.qml (+2/-2) qml/Dash/CardGrid.qml (+13/-2) qml/Dash/CardVerticalJournal.qml (+1/-1) qml/Dash/Dash.qml (+138/-7) qml/Dash/DashBackground.qml (+24/-0) qml/Dash/DashContent.qml (+7/-4) qml/Dash/DashRenderer.qml (+3/-1) qml/Dash/GenericScopeView.qml (+53/-25) qml/Dash/PreviewListView.qml (+2/-2) qml/Dash/ScopesOverview.qml (+518/-0) qml/Dash/ScopesOverviewAll.qml (+54/-0) qml/Dash/ScopesOverviewFavorites.qml (+73/-0) qml/Dash/ScopesOverviewTab.qml (+74/-0) qml/Shell.qml (+2/-8) tests/autopilot/unity8/shell/emulators/dash.py (+9/-0) tests/mocks/Unity/CMakeLists.txt (+2/-1) tests/mocks/Unity/fake_resultsmodel.cpp (+2/-1) tests/mocks/Unity/fake_scope.cpp (+18/-5) tests/mocks/Unity/fake_scope.h (+6/-3) tests/mocks/Unity/fake_scopes.cpp (+43/-2) tests/mocks/Unity/fake_scopes.h (+6/-0) tests/mocks/Unity/fake_scopesoverview.cpp (+280/-0) tests/mocks/Unity/fake_scopesoverview.h (+104/-0) tests/plugins/Dash/cardcreator/5.res (+1/-0) tests/qmltests/Components/tst_PageHeader.qml (+36/-6) tests/qmltests/Dash/tst_Dash.qml (+211/-3) tests/qmltests/Dash/tst_DashContent.qml (+4/-3) |
||||
To merge this branch: | bzr merge lp:~aacid/unity8/dash_overview | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Needs Fixing | |
Unity Team | Pending | ||
Review via email: mp+227562@code.launchpad.net |
This proposal has been superseded by a proposal from 2014-07-29.
Commit message
Dash Overview
Description of the change
* Are there any related MPs required for this MP to build/function as expected?
https:/
Also we probably want to get the fix for https:/
* Did you perform an exploratory manual test run of your code change and any related functionality?
Yes, all via make tryDash right now since real scopes backend is not there yet
* 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?
Still needs to happen
- 1112. By Albert Astals Cid
-
Only vertical flick
- 1113. By Albert Astals Cid
-
Wrong merge
- 1114. By Albert Astals Cid
-
deleteLater this
For some reason i'm now getting lots of crashes in this branch when showing the overview for the second time
- 1115. By Albert Astals Cid
-
Use the root.scopeStyle
.threshold if it's there - 1116. By Albert Astals Cid
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1116
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 1117. By Albert Astals Cid
-
Fixes for the phone
Make sure we bind instead of assign since some sizes get updated later on
Force the art shape size since to be what we want - 1118. By Albert Astals Cid
-
Merge
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1117
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1118
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 1119. By Albert Astals Cid
-
Fix threshold calculation as discussed with Saviq
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1119
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 1120. By Albert Astals Cid
-
Bind scope query back
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1120
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 1121. By Albert Astals Cid
-
Use root and not parent since parent is a hidden item the flickable uses
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1121
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 1122. By Albert Astals Cid
-
App store button
- 1123. By Albert Astals Cid
-
Dark background for the overview
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1123
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 1124. By Albert Astals Cid
-
Don't show the scopes scope, it's conflicting with the dash overview
- 1125. By Albert Astals Cid
-
Merge
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1125
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 1126. By Albert Astals Cid
-
Height actually needs to be parent and not root
found by mhr3
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1126
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 1127. By Albert Astals Cid
-
Merge
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1127
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 1128. By Albert Astals Cid
-
Merge
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1128
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1128
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 1129. By Albert Astals Cid
-
Somehow this code ended up repeated, remove
- 1130. By Albert Astals Cid
-
pressAndHold has only 1 param in DashREnderer
- 1131. By Albert Astals Cid
- 1132. By Albert Astals Cid
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1130
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 1133. By Albert Astals Cid
-
Merge
- 1134. By Albert Astals Cid
-
Merge
- 1135. By Albert Astals Cid
-
Fix issue with the first time fading in to favorites not working
- 1136. By Albert Astals Cid
-
Use a ShaderEffectSource instead of changing Dash parent
Much faster rendering
- 1137. By Albert Astals Cid
-
Split into two lines
- 1138. By Albert Astals Cid
-
Some people have ridiculously narrow screens and make me lose vertical space
- 1139. By Albert Astals Cid
-
Make this totally harder to read by splitting in two lines as requested on the review
- 1140. By Albert Astals Cid
-
Add ;
- 1141. By Albert Astals Cid
-
Merge
- 1142. By Albert Astals Cid
-
require new scopes impl
- 1143. By Albert Astals Cid
-
Small catches from review
- 1144. By Albert Astals Cid
-
Convert the overrides to functions as Nick suggested
- 1145. By Albert Astals Cid
-
Merge
- 1146. By Albert Astals Cid
- 1147. By Albert Astals Cid
-
Merge lp:~canonical-platform-qa/unity8/dash-as-app-autopilot
- 1148. By Albert Astals Cid
-
Merge
- 1149. By Albert Astals Cid
-
pot_file
- 1150. By Albert Astals Cid
-
Don't remember why this is here, remove
- 1151. By Albert Astals Cid
-
Add an option for desktop_file_hint since the upstart file is using it
- 1152. By Albert Astals Cid
-
I did not want to remove this
- 1153. By Albert Astals Cid
-
We changed the formula
- 1154. By Albert Astals Cid
-
scopes scope is not there by default anymore so use another one
- 1155. By Albert Astals Cid
-
make sure the delegate is created (scroll to it)
- 1156. By Albert Astals Cid
-
bottom bar should be non opaque and taller
- 1157. By Albert Astals Cid
-
set scope active when overview is open
- 1158. By Albert Astals Cid
-
search results viewer is always current
- 1159. By Albert Astals Cid
-
Merge
- 1160. By Albert Astals Cid
-
Merge
- 1161. By Albert Astals Cid
-
Merge
- 1162. By Albert Astals Cid
-
Make the goto store button work if store is a favorite
- 1163. By Albert Astals Cid
-
"fake" dash should not be visible if we have a temp scope
- 1164. By Albert Astals Cid
-
Use icon instead of own image
- 1165. By Albert Astals Cid
-
Dash overview handle
- 1166. By Albert Astals Cid
-
enable drag handle only if overviewDragHan
dle.enabled - 1167. By Albert Astals Cid
-
Only use dashContent.
pageHeaderTotal lyVisible when there's no temp scope - 1168. By Albert Astals Cid
-
overview handle: opacity because of header pos, y because of opening
- 1169. By Albert Astals Cid
-
More update
- 1170. By Albert Astals Cid
-
hook up the search indicator
- 1171. By Albert Astals Cid
-
hook up temp scope processing
- 1172. By Albert Astals Cid
-
unfocus++
Unmerged revisions
Preview Diff
1 | === modified file 'data/unity8.conf' |
2 | --- data/unity8.conf 2014-07-16 15:51:56 +0000 |
3 | +++ data/unity8.conf 2014-07-29 11:05:57 +0000 |
4 | @@ -36,7 +36,7 @@ |
5 | |
6 | if [ -z "$UNITY_SCOPES_LIST" ]; then |
7 | # FIXME: remove once we have this in dconf |
8 | - initctl set-env UNITY_SCOPES_LIST="scopes;clickscope;musicaggregator;videoaggregator" |
9 | + initctl set-env UNITY_SCOPES_LIST="clickscope;musicaggregator;videoaggregator" |
10 | fi |
11 | |
12 | # Remove the socket if still there |
13 | |
14 | === modified file 'debian/control' |
15 | --- debian/control 2014-07-24 20:40:44 +0000 |
16 | +++ debian/control 2014-07-29 11:05:57 +0000 |
17 | @@ -23,7 +23,7 @@ |
18 | libpulse-dev, |
19 | libqmenumodel-dev (>= 0.2.8), |
20 | libqt5xmlpatterns5-dev, |
21 | - libunity-api-dev (>= 7.85), |
22 | + libunity-api-dev (>= 7.87), |
23 | libunity-mir-dev, |
24 | libusermetricsoutput1-dev, |
25 | libxcb1-dev, |
26 | |
27 | === modified file 'plugins/Dash/CardCreator.js' |
28 | --- plugins/Dash/CardCreator.js 2014-07-09 19:44:44 +0000 |
29 | +++ plugins/Dash/CardCreator.js 2014-07-29 11:05:57 +0000 |
30 | @@ -408,7 +408,7 @@ |
31 | mascotCode = kMascotImageCode.arg(anchors).arg(mascotImageVisible); |
32 | } |
33 | |
34 | - var summaryColorWithBackground = 'backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey")'; |
35 | + var summaryColorWithBackground = 'backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < (root.scopeStyle ? root.scopeStyle.threshold : 0.7) ? (root.scopeStyle ? root.scopeStyle.light : "white") : (root.scopeStyle ? root.scopeStyle.dark : "grey")'; |
36 | |
37 | var titleSubtitleCode = ""; |
38 | if (hasTitle) { |
39 | @@ -438,6 +438,7 @@ |
40 | titleAnchors = 'left: parent.left; \n\ |
41 | leftMargin: units.gu(1); \n\ |
42 | right: parent.right; \n\ |
43 | + rightMargin: units.gu(1); \n\ |
44 | top: overlayLoader.top; \n\ |
45 | topMargin: units.gu(1);\n'; |
46 | } else { |
47 | |
48 | === modified file 'plugins/Dash/ScopeStyle.qml' |
49 | --- plugins/Dash/ScopeStyle.qml 2014-07-18 18:09:13 +0000 |
50 | +++ plugins/Dash/ScopeStyle.qml 2014-07-29 11:05:57 +0000 |
51 | @@ -43,9 +43,9 @@ |
52 | |
53 | /*! \brief Luminance threshold for switching between fore and background color |
54 | |
55 | - \note If background colour is not fully opaque, it's not taken into account. |
56 | + \note If background colour is not fully opaque, the defaultLightLuminance it's taken into account instead of it. |
57 | */ |
58 | - readonly property real threshold: background.a !== 1.0 ? d.foregroundLuminance : (d.foregroundLuminance + d.backgroundLuminance) / 2 |
59 | + readonly property real threshold: background.a !== 1.0 ? (d.foregroundLuminance + d.defaultLightLuminance) / 2: (d.foregroundLuminance + d.backgroundLuminance) / 2 |
60 | |
61 | /*! \brief The lighter of foreground and background colors |
62 | |
63 | |
64 | === modified file 'plugins/Dash/listviewwithpageheader.cpp' |
65 | --- plugins/Dash/listviewwithpageheader.cpp 2014-07-25 10:47:08 +0000 |
66 | +++ plugins/Dash/listviewwithpageheader.cpp 2014-07-29 11:05:57 +0000 |
67 | @@ -822,8 +822,8 @@ |
68 | ListItem *nextItem = itemAtIndex(modelIndex + 1); |
69 | if (nextItem) { |
70 | listItem->setY(nextItem->y() - listItem->height()); |
71 | - } else if (modelIndex == 0 && m_headerItem) { |
72 | - listItem->setY(m_headerItem->height()); |
73 | + } else if (modelIndex == 0) { |
74 | + listItem->setY(m_headerItem ? m_headerItem->height() : 0); |
75 | } else if (!m_visibleItems.isEmpty()) { |
76 | lostItem = true; |
77 | } |
78 | |
79 | === modified file 'po/unity8.pot' |
80 | --- po/unity8.pot 2014-07-11 14:20:12 +0000 |
81 | +++ po/unity8.pot 2014-07-29 11:05:57 +0000 |
82 | @@ -8,7 +8,7 @@ |
83 | msgstr "" |
84 | "Project-Id-Version: unity8\n" |
85 | "Report-Msgid-Bugs-To: \n" |
86 | -"POT-Creation-Date: 2014-07-11 14:59+0200\n" |
87 | +"POT-Creation-Date: 2014-07-21 15:41+0200\n" |
88 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" |
89 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" |
90 | "Language-Team: LANGUAGE <LL@li.org>\n" |
91 | @@ -101,7 +101,7 @@ |
92 | msgid "See more" |
93 | msgstr "" |
94 | |
95 | -#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330 |
96 | +#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:356 |
97 | msgid "See less" |
98 | msgstr "" |
99 | |
100 | @@ -109,7 +109,7 @@ |
101 | msgid "Recent" |
102 | msgstr "" |
103 | |
104 | -#: qml/Dash/GenericScopeView.qml:330 |
105 | +#: qml/Dash/GenericScopeView.qml:356 |
106 | msgid "See all" |
107 | msgstr "" |
108 | |
109 | @@ -133,6 +133,22 @@ |
110 | msgid "Send" |
111 | msgstr "" |
112 | |
113 | +#: qml/Dash/ScopesOverview.qml:185 |
114 | +msgid "Manage Dash" |
115 | +msgstr "" |
116 | + |
117 | +#: qml/Dash/ScopesOverview.qml:390 |
118 | +msgid "Done" |
119 | +msgstr "" |
120 | + |
121 | +#: qml/Dash/ScopesOverviewTab.qml:36 |
122 | +msgid "Favorites" |
123 | +msgstr "" |
124 | + |
125 | +#: qml/Dash/ScopesOverviewTab.qml:54 |
126 | +msgid "All" |
127 | +msgstr "" |
128 | + |
129 | #: qml/Greeter/Greeter.qml:157 |
130 | msgid "Swipe to unlock" |
131 | msgstr "" |
132 | @@ -157,11 +173,11 @@ |
133 | msgid "Speaking..." |
134 | msgstr "" |
135 | |
136 | -#: qml/Notifications/NotificationMenuItemFactory.qml:91 |
137 | +#: qml/Notifications/NotificationMenuItemFactory.qml:97 |
138 | msgid "Show password" |
139 | msgstr "" |
140 | |
141 | -#: qml/Notifications/NotificationMenuItemFactory.qml:103 |
142 | +#: qml/Notifications/NotificationMenuItemFactory.qml:112 |
143 | msgid "Please enter SIM PIN" |
144 | msgstr "" |
145 | |
146 | @@ -173,27 +189,27 @@ |
147 | msgid "Conference" |
148 | msgstr "" |
149 | |
150 | -#: qml/Panel/Indicators/MenuItemFactory.qml:583 |
151 | +#: qml/Panel/Indicators/MenuItemFactory.qml:577 |
152 | msgid "In queue…" |
153 | msgstr "" |
154 | |
155 | -#: qml/Panel/Indicators/MenuItemFactory.qml:587 |
156 | +#: qml/Panel/Indicators/MenuItemFactory.qml:581 |
157 | msgid "Downloading" |
158 | msgstr "" |
159 | |
160 | -#: qml/Panel/Indicators/MenuItemFactory.qml:589 |
161 | +#: qml/Panel/Indicators/MenuItemFactory.qml:583 |
162 | msgid "Paused, tap to resume" |
163 | msgstr "" |
164 | |
165 | -#: qml/Panel/Indicators/MenuItemFactory.qml:591 |
166 | +#: qml/Panel/Indicators/MenuItemFactory.qml:585 |
167 | msgid "Canceled" |
168 | msgstr "" |
169 | |
170 | -#: qml/Panel/Indicators/MenuItemFactory.qml:593 |
171 | +#: qml/Panel/Indicators/MenuItemFactory.qml:587 |
172 | msgid "Finished" |
173 | msgstr "" |
174 | |
175 | -#: qml/Panel/Indicators/MenuItemFactory.qml:595 |
176 | +#: qml/Panel/Indicators/MenuItemFactory.qml:589 |
177 | msgid "Failed, tap to retry" |
178 | msgstr "" |
179 | |
180 | @@ -201,7 +217,23 @@ |
181 | msgid "Search" |
182 | msgstr "" |
183 | |
184 | -#: qml/Shell.qml:359 |
185 | +#: qml/Shell.qml:347 |
186 | +msgid "Are you sure you would like to turn power off?" |
187 | +msgstr "" |
188 | + |
189 | +#: qml/Shell.qml:349 |
190 | +msgid "Power off" |
191 | +msgstr "" |
192 | + |
193 | +#: qml/Shell.qml:360 |
194 | +msgid "Restart" |
195 | +msgstr "" |
196 | + |
197 | +#: qml/Shell.qml:369 |
198 | +msgid "Cancel" |
199 | +msgstr "" |
200 | + |
201 | +#: qml/Shell.qml:496 |
202 | #, qt-format |
203 | msgid "Please enter %1" |
204 | msgstr "" |
205 | |
206 | === modified file 'qml/Components/PageHeader.qml' |
207 | --- qml/Components/PageHeader.qml 2014-07-21 09:49:41 +0000 |
208 | +++ qml/Components/PageHeader.qml 2014-07-29 11:05:57 +0000 |
209 | @@ -24,7 +24,7 @@ |
210 | Item { |
211 | id: root |
212 | objectName: "pageHeader" |
213 | - implicitHeight: headerContainer.height + units.gu(2) + bottomContainer.height |
214 | + implicitHeight: headerContainer.height + bottomContainer.height + (showSignatureLine ? units.gu(2) : 0) |
215 | |
216 | property bool showBackButton: false |
217 | property string title |
218 | @@ -33,6 +33,7 @@ |
219 | property ListModel searchHistory: SearchHistoryModel |
220 | property alias searchQuery: searchTextField.text |
221 | property bool searchInProgress: false |
222 | + property alias showSignatureLine: bottomBorder.visible |
223 | |
224 | property alias bottomItem: bottomContainer.children |
225 | |
226 | @@ -44,6 +45,12 @@ |
227 | signal backClicked() |
228 | |
229 | onScopeStyleChanged: refreshLogo() |
230 | + onSearchQueryChanged: { |
231 | + // Make sure we are at the search page if the search query changes behind our feet |
232 | + if (searchQuery) { |
233 | + headerContainer.showSearch = true; |
234 | + } |
235 | + } |
236 | |
237 | function triggerSearch() { |
238 | if (searchEntryEnabled) { |
239 | @@ -52,6 +59,12 @@ |
240 | } |
241 | } |
242 | |
243 | + function closePopup() { |
244 | + if (headerContainer.popover != null) { |
245 | + PopupUtils.close(headerContainer.popover); |
246 | + } |
247 | + } |
248 | + |
249 | function resetSearch(keepFocus) { |
250 | if (searchHistory) { |
251 | searchHistory.addQuery(searchTextField.text); |
252 | @@ -60,9 +73,7 @@ |
253 | unfocus(); |
254 | } |
255 | searchTextField.text = ""; |
256 | - if (headerContainer.popover != null) { |
257 | - PopupUtils.close(headerContainer.popover); |
258 | - } |
259 | + closePopup(); |
260 | } |
261 | |
262 | function unfocus() { |
263 | @@ -103,9 +114,7 @@ |
264 | anchors { fill: parent; margins: units.gu(1); bottomMargin: units.gu(3) + bottomContainer.height } |
265 | visible: headerContainer.showSearch |
266 | onPressed: { |
267 | - if (headerContainer.popover) { |
268 | - PopupUtils.close(headerContainer.popover); |
269 | - } |
270 | + closePopup(); |
271 | if (!searchTextField.text) { |
272 | headerContainer.showSearch = false; |
273 | } |
274 | @@ -220,6 +229,12 @@ |
275 | root.openSearchHistory(); |
276 | } |
277 | } |
278 | + |
279 | + onTextChanged: { |
280 | + if (text != "") { |
281 | + closePopup(); |
282 | + } |
283 | + } |
284 | } |
285 | } |
286 | |
287 | @@ -244,6 +259,7 @@ |
288 | |
289 | actions: [ |
290 | Action { |
291 | + objectName: "search" |
292 | iconName: "search" |
293 | visible: root.searchEntryEnabled |
294 | onTriggered: { |
295 | @@ -296,6 +312,7 @@ |
296 | |
297 | Repeater { |
298 | id: recentSearches |
299 | + objectName: "recentSearches" |
300 | model: searchHistory |
301 | |
302 | delegate: Standard { |
303 | @@ -304,7 +321,8 @@ |
304 | onClicked: { |
305 | searchHistory.addQuery(text); |
306 | searchTextField.text = text; |
307 | - PopupUtils.close(popover); |
308 | + closePopup(); |
309 | + unfocus(); |
310 | } |
311 | } |
312 | } |
313 | |
314 | === modified file 'qml/Components/ResponsiveGridView.qml' |
315 | --- qml/Components/ResponsiveGridView.qml 2014-07-11 12:12:50 +0000 |
316 | +++ qml/Components/ResponsiveGridView.qml 2014-07-29 11:05:57 +0000 |
317 | @@ -34,7 +34,7 @@ |
318 | readonly property int cellWidth: gridView.cellWidth |
319 | readonly property int cellHeight: gridView.cellHeight |
320 | readonly property int totalContentHeight: { |
321 | - return contentHeightForRows(Math.ceil(gridView.model.count / columns)) |
322 | + return contentHeightForRows(Math.ceil(gridView.model.count / columns), cellHeight) |
323 | } |
324 | property alias interactive: gridView.interactive |
325 | readonly property alias flicking: gridView.flicking |
326 | @@ -47,8 +47,8 @@ |
327 | property alias cacheBuffer: gridView.cacheBuffer |
328 | readonly property alias currentItem: gridView.currentItem |
329 | |
330 | - function contentHeightForRows(rows) { |
331 | - return rows * cellHeight; |
332 | + function contentHeightForRows(rows, height) { |
333 | + return rows * height |
334 | } |
335 | |
336 | GridView { |
337 | |
338 | === modified file 'qml/Dash/CardCarousel.qml' |
339 | --- qml/Dash/CardCarousel.qml 2014-07-11 12:13:08 +0000 |
340 | +++ qml/Dash/CardCarousel.qml 2014-07-29 11:05:57 +0000 |
341 | @@ -48,8 +48,8 @@ |
342 | |
343 | objectName: "carouselDelegate" + index |
344 | |
345 | - function clicked() { cardCarousel.clicked(index, model.result) } |
346 | - function pressAndHold() { cardCarousel.pressAndHold(index, model.result) } |
347 | + function clicked() { cardCarousel.clicked(index, model.result, loader.item, model) } |
348 | + function pressAndHold() { cardCarousel.pressAndHold(index) } |
349 | |
350 | sourceComponent: cardTool.cardComponent |
351 | onLoaded: { |
352 | |
353 | === modified file 'qml/Dash/CardGrid.qml' |
354 | --- qml/Dash/CardGrid.qml 2014-07-18 11:35:47 +0000 |
355 | +++ qml/Dash/CardGrid.qml 2014-07-29 11:05:57 +0000 |
356 | @@ -26,10 +26,20 @@ |
357 | } |
358 | |
359 | expandedHeight: grid.totalContentHeight |
360 | - collapsedHeight: Math.min(grid.contentHeightForRows(collapsedRows), expandedHeight) |
361 | + collapsedHeight: Math.min(grid.contentHeightForRows(collapsedRows, grid.cellHeight), expandedHeight) |
362 | collapsedItemCount: collapsedRows * grid.columns |
363 | originY: grid.originY |
364 | |
365 | + function cardPosition(index) { |
366 | + var pos = {}; |
367 | + var row = Math.floor(index / grid.columns); |
368 | + var column = index % grid.columns; |
369 | + // Bit sad this is not symmetrical |
370 | + pos.x = column * grid.cellWidth + grid.margins; |
371 | + pos.y = row * grid.cellHeight; |
372 | + return pos; |
373 | + } |
374 | + |
375 | ResponsiveGridView { |
376 | id: grid |
377 | anchors.fill: parent |
378 | @@ -53,6 +63,7 @@ |
379 | item.objectName = "delegate" + index; |
380 | item.width = Qt.binding(function() { return cardTool.cardWidth; }); |
381 | item.height = Qt.binding(function() { return cardTool.cardHeight; }); |
382 | + item.fixedHeaderHeight = Qt.binding(function() { return cardTool.headerHeight; }); |
383 | item.fixedArtShapeSize = Qt.binding(function() { return cardTool.artShapeSize; }); |
384 | item.cardData = Qt.binding(function() { return model; }); |
385 | item.template = Qt.binding(function() { return cardTool.template; }); |
386 | @@ -62,7 +73,7 @@ |
387 | } |
388 | Connections { |
389 | target: loader.item |
390 | - onClicked: root.clicked(index, result) |
391 | + onClicked: root.clicked(index, result, loader.item, model) |
392 | onPressAndHold: root.pressAndHold(index) |
393 | } |
394 | } |
395 | |
396 | === modified file 'qml/Dash/CardVerticalJournal.qml' |
397 | --- qml/Dash/CardVerticalJournal.qml 2014-07-22 12:17:34 +0000 |
398 | +++ qml/Dash/CardVerticalJournal.qml 2014-07-29 11:05:57 +0000 |
399 | @@ -61,7 +61,7 @@ |
400 | } |
401 | Connections { |
402 | target: loader.item |
403 | - onClicked: root.clicked(index, result) |
404 | + onClicked: root.clicked(index, result, loader.item, model) |
405 | onPressAndHold: root.pressAndHold(index) |
406 | } |
407 | } |
408 | |
409 | === modified file 'qml/Dash/Dash.qml' |
410 | --- qml/Dash/Dash.qml 2014-07-07 08:20:04 +0000 |
411 | +++ qml/Dash/Dash.qml 2014-07-29 11:05:57 +0000 |
412 | @@ -16,6 +16,7 @@ |
413 | |
414 | import QtQuick 2.0 |
415 | import Ubuntu.Components 0.1 |
416 | +import Ubuntu.Gestures 0.1 |
417 | import Unity 0.2 |
418 | import Utils 0.1 |
419 | import "../Components" |
420 | @@ -29,6 +30,8 @@ |
421 | property string showScopeOnLoaded: "clickscope" |
422 | property real contentScale: 1.0 |
423 | |
424 | + property alias overviewHandleHeight: overviewDragHandle.height |
425 | + |
426 | function setCurrentScope(scopeId, animate, reset) { |
427 | var scopeIndex = filteredScopes.findFirst(Scopes.RoleId, scopeId) |
428 | |
429 | @@ -66,19 +69,85 @@ |
430 | filterRegExp: RegExp("^true$") |
431 | } |
432 | |
433 | + QtObject { |
434 | + id: overviewController |
435 | + objectName: "overviewController" |
436 | + |
437 | + property alias enableAnimation: progressAnimation.enabled |
438 | + property real progress: 0 |
439 | + Behavior on progress { |
440 | + id: progressAnimation |
441 | + UbuntuNumberAnimation { } |
442 | + } |
443 | + } |
444 | + |
445 | + ScopesOverview { |
446 | + id: scopesOverview |
447 | + objectName: "scopesOverview" |
448 | + anchors.fill: parent |
449 | + scope: scopes.overviewScope |
450 | + progress: overviewController.progress |
451 | + scopeScale: scopeItem.scope ? 0.4 : (1 - overviewController.progress * 0.6) |
452 | + visible: scopeScale != 1 |
453 | + currentIndex: dashContent.currentIndex |
454 | + onDone: { |
455 | + if (currentTab == 1) { |
456 | + animateDashFromAll(dashContent.currentScopeId); |
457 | + } |
458 | + hide(); |
459 | + } |
460 | + onFavoriteSelected: { |
461 | + setCurrentScope(scopeId, false, false); |
462 | + hide(); |
463 | + } |
464 | + onAllFavoriteSelected: { |
465 | + setCurrentScope(scopeId, false, false); |
466 | + animateDashFromAll(dashContent.currentScopeId); |
467 | + hide(); |
468 | + } |
469 | + onSearchSelected: { |
470 | + var scopeIndex = filteredScopes.findFirst(Scopes.RoleId, scopeId); |
471 | + if (scopeIndex >= 0) { |
472 | + // Is a favorite one |
473 | + setCurrentScope(scopeId, false, false); |
474 | + showDashFromPos(pos, size); |
475 | + hide(); |
476 | + } else { |
477 | + // Is not a favorite one, activate and get openScope |
478 | + scope.activate(result); |
479 | + } |
480 | + } |
481 | + function hide() { |
482 | + overviewController.enableAnimation = true; |
483 | + overviewController.progress = 0; |
484 | + } |
485 | + onProgressChanged: { |
486 | + if (progress == 0) { |
487 | + currentTab = scopeItem.scope ? 1 : 0; |
488 | + } |
489 | + } |
490 | + } |
491 | + |
492 | DashContent { |
493 | id: dashContent |
494 | + |
495 | + property var scopeThatOpenedScope: null |
496 | + |
497 | + parent: overviewController.progress == 0 ? dash : scopesOverview.dashItemEater |
498 | objectName: "dashContent" |
499 | - width: parent.width |
500 | - height: parent.height |
501 | + width: dash.width |
502 | + height: dash.height |
503 | model: filteredScopes |
504 | scopes: scopes |
505 | - visible: x != -width |
506 | + visible: !scopesOverview.showingNonFavoriteScope && x != -width |
507 | onGotoScope: { |
508 | dash.setCurrentScope(scopeId, true, false); |
509 | } |
510 | onOpenScope: { |
511 | + scopeThatOpenedScope = currentScope; |
512 | scopeItem.scope = scope; |
513 | + scopesOverview.currentTab = 1; |
514 | + scopesOverview.ensureAllScopeVisible(scope.id); |
515 | x = -width; |
516 | } |
517 | onScopeLoaded: { |
518 | @@ -88,25 +157,63 @@ |
519 | } |
520 | } |
521 | scale: dash.contentScale |
522 | - clip: scale != 1.0 || scopeItem.visible |
523 | + clip: scale != 1.0 || scopeItem.visible || overviewController.progress != 0 |
524 | Behavior on x { |
525 | UbuntuNumberAnimation { |
526 | + duration: overviewController.progress != 0 ? 0 : UbuntuAnimation.FastDuration |
527 | onRunningChanged: { |
528 | if (!running && dashContent.x == 0) { |
529 | - dashContent.closeScope(scopeItem.scope); |
530 | + dashContent.scopeThatOpenedScope.closeScope(scopeItem.scope); |
531 | scopeItem.scope = null; |
532 | + if (overviewController.progress == 0) { |
533 | + // Set tab to Favorites only if we are not showing the overview |
534 | + scopesOverview.currentTab = 0; |
535 | + } |
536 | } |
537 | } |
538 | } |
539 | } |
540 | + |
541 | + enabled: opacity == 1 |
542 | + opacity: scopesOverview.growingDashFromPos ? 1 : 1 - overviewController.progress |
543 | + } |
544 | + |
545 | + DashBackground |
546 | + { |
547 | + anchors.fill: scopeItem |
548 | + visible: scopeItem.visible |
549 | + parent: scopeItem.parent |
550 | + scale: scopeItem.scale |
551 | + opacity: scopeItem.opacity |
552 | } |
553 | |
554 | GenericScopeView { |
555 | id: scopeItem |
556 | - anchors.left: dashContent.right |
557 | + objectName: "dashTempScopeItem" |
558 | + |
559 | + readonly property real targetOverviewScale: { |
560 | + if (scopesOverview.currentTab == 0) { |
561 | + return 0.4; |
562 | + } else { |
563 | + return scopesOverview.allCardSize.width / scopeItem.width; |
564 | + } |
565 | + } |
566 | + readonly property real overviewProgressScale: (1 - overviewController.progress * (1 - targetOverviewScale)) |
567 | + readonly property var targetOverviewPosition: scope ? scopesOverview.allScopeCardPosition(scope.id) : null |
568 | + readonly property real overviewProgressX: scope && scopesOverview.currentTab == 1 && targetOverviewPosition ? |
569 | + overviewController.progress * (targetOverviewPosition.x - (width - scopesOverview.allCardSize.width) / 2) |
570 | + : 0 |
571 | + readonly property real overviewProgressY: scope && scopesOverview.currentTab == 1 && targetOverviewPosition ? |
572 | + overviewController.progress * (targetOverviewPosition.y - (height - scopesOverview.allCardSize.height) / 2) |
573 | + : 0 |
574 | + |
575 | + x: overviewController.progress == 0 ? dashContent.x + width : overviewProgressX |
576 | + y: overviewController.progress == 0 ? dashContent.y : overviewProgressY |
577 | width: parent.width |
578 | height: parent.height |
579 | - scale: dash.contentScale |
580 | + scale: dash.contentScale * overviewProgressScale |
581 | + enabled: opacity == 1 |
582 | + opacity: 1 - overviewController.progress |
583 | clip: scale != 1.0 |
584 | visible: scope != null |
585 | hasBackAction: true |
586 | @@ -126,4 +233,28 @@ |
587 | } |
588 | } |
589 | } |
590 | + |
591 | + EdgeDragArea { |
592 | + id: overviewDragHandle |
593 | + objectName: "overviewDragHandle" |
594 | + z: 1 |
595 | + direction: Direction.Upwards |
596 | + enabled: !dashContent.previewShown && dashContent.currentScope && dashContent.currentScope.searchQuery == "" && (overviewController.progress == 0 || dragging) |
597 | + |
598 | + readonly property real fullMovement: units.gu(20) |
599 | + |
600 | + anchors { left: parent.left; right: parent.right; bottom: parent.bottom } |
601 | + height: units.gu(2) |
602 | + |
603 | + onSceneDistanceChanged: { |
604 | + overviewController.enableAnimation = false; |
605 | + overviewController.progress = Math.max(0, Math.min(1, sceneDistance / fullMovement)); |
606 | + } |
607 | + |
608 | + onDraggingChanged: { |
609 | + overviewController.enableAnimation = true; |
610 | + overviewController.progress = (overviewController.progress > 0.7) ? 1 : 0; |
611 | + } |
612 | + } |
613 | + |
614 | } |
615 | |
616 | === added file 'qml/Dash/DashBackground.qml' |
617 | --- qml/Dash/DashBackground.qml 1970-01-01 00:00:00 +0000 |
618 | +++ qml/Dash/DashBackground.qml 2014-07-29 11:05:57 +0000 |
619 | @@ -0,0 +1,24 @@ |
620 | +/* |
621 | + * Copyright (C) 2013, 2014 Canonical, Ltd. |
622 | + * |
623 | + * This program is free software; you can redistribute it and/or modify |
624 | + * it under the terms of the GNU General Public License as published by |
625 | + * the Free Software Foundation; version 3. |
626 | + * |
627 | + * This program is distributed in the hope that it will be useful, |
628 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
629 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
630 | + * GNU General Public License for more details. |
631 | + * |
632 | + * You should have received a copy of the GNU General Public License |
633 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
634 | + */ |
635 | + |
636 | +import QtQuick 2.0 |
637 | + |
638 | +Image { |
639 | + source: anchors.fill.width > anchors.fill.height ? "graphics/paper_landscape.png" : "graphics/paper_portrait.png" |
640 | + fillMode: Image.PreserveAspectCrop |
641 | + horizontalAlignment: Image.AlignRight |
642 | + verticalAlignment: Image.AlignTop |
643 | +} |
644 | |
645 | === modified file 'qml/Dash/DashContent.qml' |
646 | --- qml/Dash/DashContent.qml 2014-07-08 19:35:59 +0000 |
647 | +++ qml/Dash/DashContent.qml 2014-07-29 11:05:57 +0000 |
648 | @@ -26,6 +26,9 @@ |
649 | property var model: null |
650 | property var scopes: null |
651 | readonly property alias currentIndex: dashContentList.currentIndex |
652 | + readonly property string currentScopeId: dashContentList.currentItem ? dashContentList.currentItem.scopeId : "" |
653 | + readonly property var currentScope: dashContentList.currentItem ? dashContentList.currentItem.theScope : null |
654 | + readonly property bool previewShown: dashContentList.currentItem && dashContentList.currentItem.item ? dashContentList.currentItem.item.previewShown : false |
655 | |
656 | signal scopeLoaded(string scopeId) |
657 | signal gotoScope(string scopeId) |
658 | @@ -76,15 +79,15 @@ |
659 | } |
660 | } |
661 | |
662 | - function closeScope(scope) { |
663 | - dashContentList.currentItem.theScope.closeScope(scope) |
664 | - } |
665 | - |
666 | Item { |
667 | id: dashContentListHolder |
668 | |
669 | anchors.fill: parent |
670 | |
671 | + DashBackground { |
672 | + anchors.fill: parent |
673 | + } |
674 | + |
675 | ListView { |
676 | id: dashContentList |
677 | objectName: "dashContentList" |
678 | |
679 | === modified file 'qml/Dash/DashRenderer.qml' |
680 | --- qml/Dash/DashRenderer.qml 2014-07-22 12:17:34 +0000 |
681 | +++ qml/Dash/DashRenderer.qml 2014-07-29 11:05:57 +0000 |
682 | @@ -41,7 +41,9 @@ |
683 | /// Emitted when the user clicked on an item |
684 | /// @param index is the index of the clicked item |
685 | /// @param result result model of the cliked item, used for activation |
686 | - signal clicked(int index, var result) |
687 | + /// @param item item that has been clicked |
688 | + /// @param itemModel model of the item |
689 | + signal clicked(int index, var result, var item, var itemModel) |
690 | |
691 | /// Emitted when the user pressed and held on an item |
692 | /// @param index is the index of the held item |
693 | |
694 | === modified file 'qml/Dash/GenericScopeView.qml' |
695 | --- qml/Dash/GenericScopeView.qml 2014-07-24 20:40:44 +0000 |
696 | +++ qml/Dash/GenericScopeView.qml 2014-07-29 11:05:57 +0000 |
697 | @@ -33,6 +33,10 @@ |
698 | property bool hasBackAction: false |
699 | property bool enableHeightBehaviorOnNextCreation: false |
700 | property var categoryView: categoryView |
701 | + property bool showPageHeader: true |
702 | + property var clickOverride: null |
703 | + property var pressAndHoldOverride: null |
704 | + readonly property alias previewShown: previewListView.open |
705 | |
706 | property var scopeStyle: ScopeStyle { |
707 | style: scope ? scope.customizations : {} |
708 | @@ -78,22 +82,24 @@ |
709 | } |
710 | |
711 | onIsCurrentChanged: { |
712 | - pageHeader.resetSearch(); |
713 | + if (showPageHeader) { |
714 | + pageHeaderLoader.item.resetSearch(); |
715 | + } |
716 | previewListView.open = false; |
717 | } |
718 | |
719 | Binding { |
720 | target: scopeView.scope |
721 | property: "searchQuery" |
722 | - value: pageHeader.searchQuery |
723 | - when: isCurrent |
724 | + value: pageHeaderLoader.item ? pageHeaderLoader.item.searchQuery : "" |
725 | + when: isCurrent && showPageHeader |
726 | } |
727 | |
728 | Binding { |
729 | - target: pageHeader |
730 | + target: pageHeaderLoader.item |
731 | property: "searchQuery" |
732 | value: scopeView.scope ? scopeView.scope.searchQuery : "" |
733 | - when: isCurrent |
734 | + when: isCurrent && showPageHeader |
735 | } |
736 | |
737 | Connections { |
738 | @@ -232,6 +238,11 @@ |
739 | Connections { |
740 | target: rendererLoader.item |
741 | onClicked: { |
742 | + if (scopeView.clickOverride) { |
743 | + scopeView.clickOverride(index, result, item, itemModel); |
744 | + return; |
745 | + } |
746 | + |
747 | if (scopeView.scope.id === "scopes" || scopeView.scope.id == "clickscope") { |
748 | // TODO Technically it is possible that calling activate() will make the scope emit |
749 | // previewRequested so that we show a preview but there's no scope that does that yet |
750 | @@ -241,7 +252,14 @@ |
751 | openPreview(index); |
752 | } |
753 | } |
754 | - onPressAndHold: openPreview(index) |
755 | + |
756 | + onPressAndHold: { |
757 | + if (scopeView.pressAndHoldOverride) { |
758 | + scopeView.pressAndHoldOverride(index); |
759 | + } else { |
760 | + openPreview(index) |
761 | + } |
762 | + } |
763 | |
764 | function openPreview(index) { |
765 | if (!rendererLoader.expanded && !seeAllLabel.visible && target.collapsedItemCount > 0) { |
766 | @@ -389,26 +407,34 @@ |
767 | } |
768 | } |
769 | |
770 | - pageHeader: PageHeader { |
771 | - id: pageHeader |
772 | - objectName: "scopePageHeader" |
773 | + pageHeader: scopeView.showPageHeader ? pageHeaderLoader : null |
774 | + Loader { |
775 | + id: pageHeaderLoader |
776 | width: parent.width |
777 | - title: scopeView.scope ? scopeView.scope.name : "" |
778 | - showBackButton: scopeView.hasBackAction |
779 | - searchEntryEnabled: true |
780 | - searchInProgress: scopeView.scope ? scopeView.scope.searchInProgress : false |
781 | - scopeStyle: scopeView.scopeStyle |
782 | - |
783 | - bottomItem: DashDepartments { |
784 | - scope: scopeView.scope |
785 | - width: parent.width <= units.gu(60) ? parent.width : units.gu(40) |
786 | - anchors.right: parent.right |
787 | - windowHeight: scopeView.height |
788 | - windowWidth: scopeView.width |
789 | - scopeStyle: scopeView.scopeStyle |
790 | + sourceComponent: scopeView.showPageHeader ? pageHeaderComponent : undefined |
791 | + Component { |
792 | + id: pageHeaderComponent |
793 | + PageHeader { |
794 | + objectName: "scopePageHeader" |
795 | + width: parent.width |
796 | + title: scopeView.scope ? scopeView.scope.name : "" |
797 | + showBackButton: scopeView.hasBackAction |
798 | + searchEntryEnabled: true |
799 | + searchInProgress: scopeView.scope ? scopeView.scope.searchInProgress : false |
800 | + scopeStyle: scopeView.scopeStyle |
801 | + |
802 | + bottomItem: DashDepartments { |
803 | + scope: scopeView.scope |
804 | + width: parent.width <= units.gu(60) ? parent.width : units.gu(40) |
805 | + anchors.right: parent.right |
806 | + windowHeight: scopeView.height |
807 | + windowWidth: scopeView.width |
808 | + scopeStyle: scopeView.scopeStyle |
809 | + } |
810 | + |
811 | + onBackClicked: scopeView.backClicked() |
812 | + } |
813 | } |
814 | - |
815 | - onBackClicked: scopeView.backClicked() |
816 | } |
817 | } |
818 | |
819 | @@ -427,7 +453,9 @@ |
820 | anchors.left: categoryView.right |
821 | |
822 | onOpenChanged: { |
823 | - pageHeader.unfocus(); |
824 | + if (showPageHeader) { |
825 | + pageHeaderLoader.item.unfocus(); |
826 | + } |
827 | } |
828 | } |
829 | |
830 | |
831 | === modified file 'qml/Dash/PreviewListView.qml' |
832 | --- qml/Dash/PreviewListView.qml 2014-07-17 13:10:45 +0000 |
833 | +++ qml/Dash/PreviewListView.qml 2014-07-29 11:05:57 +0000 |
834 | @@ -88,7 +88,7 @@ |
835 | height: previewListView.height |
836 | width: previewListView.width |
837 | |
838 | - readonly property bool ready: preview.previewModel.loaded |
839 | + readonly property bool ready: preview.previewModel && preview.previewModel.loaded |
840 | |
841 | Previews.Preview { |
842 | id: preview |
843 | @@ -108,7 +108,7 @@ |
844 | id: processingMouseArea |
845 | objectName: "processingMouseArea" |
846 | anchors.fill: parent |
847 | - enabled: !preview.previewModel.loaded || preview.previewModel.processingAction |
848 | + enabled: preview.previewModel && (!preview.previewModel.loaded || preview.previewModel.processingAction) |
849 | |
850 | ActivityIndicator { |
851 | anchors.centerIn: parent |
852 | |
853 | === added file 'qml/Dash/ScopesOverview.qml' |
854 | --- qml/Dash/ScopesOverview.qml 1970-01-01 00:00:00 +0000 |
855 | +++ qml/Dash/ScopesOverview.qml 2014-07-29 11:05:57 +0000 |
856 | @@ -0,0 +1,518 @@ |
857 | +/* |
858 | + * Copyright (C) 2014 Canonical, Ltd. |
859 | + * |
860 | + * This program is free software; you can redistribute it and/or modify |
861 | + * it under the terms of the GNU General Public License as published by |
862 | + * the Free Software Foundation; version 3. |
863 | + * |
864 | + * This program is distributed in the hope that it will be useful, |
865 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
866 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
867 | + * GNU General Public License for more details. |
868 | + * |
869 | + * You should have received a copy of the GNU General Public License |
870 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
871 | + */ |
872 | + |
873 | +import QtQuick 2.0 |
874 | +import Dash 0.1 |
875 | +import Ubuntu.Components 0.1 |
876 | +import "../Components" |
877 | + |
878 | +Item { |
879 | + id: root |
880 | + |
881 | + // Properties set by parent |
882 | + property real progress: 0 |
883 | + property var scope: null |
884 | + property int currentIndex: 0 |
885 | + property real scopeScale: 1 |
886 | + |
887 | + // Properties set and used by parent |
888 | + property alias currentTab: tabBar.currentTab |
889 | + |
890 | + // Properties used by parent |
891 | + property bool growingDashFromPos: false |
892 | + readonly property bool searching: scope && scope.searchQuery == "" |
893 | + readonly property bool showingNonFavoriteScope: tempScopeItem.scope != null |
894 | + readonly property var dashItemEater: { |
895 | + if (!forceXYScalerEater && tabBar.currentTab == 0 && middleItems.count > 0) { |
896 | + var loaderItem = middleItems.itemAt(0).item; |
897 | + return loaderItem && loaderItem.currentItem ? loaderItem.currentItem : null; |
898 | + } |
899 | + return scopesOverviewXYScaler; |
900 | + } |
901 | + readonly property size allCardSize: { |
902 | + if (middleItems.count > 1) { |
903 | + var loaderItem = middleItems.itemAt(1).item; |
904 | + if (loaderItem) { |
905 | + var cardTool = loaderItem.cardTool; |
906 | + return Qt.size(cardTool.cardWidth, cardTool.cardHeight); |
907 | + } |
908 | + } |
909 | + return Qt.size(0, 0); |
910 | + } |
911 | + |
912 | + // Internal properties |
913 | + property bool forceXYScalerEater: false |
914 | + |
915 | + signal done() |
916 | + signal favoriteSelected(var scopeId) |
917 | + signal allFavoriteSelected(var scopeId) |
918 | + signal searchSelected(var scopeId, var result, var pos, var size) |
919 | + |
920 | + Connections { |
921 | + target: scope |
922 | + onOpenScope: { |
923 | + var itemPos = scopesOverviewXYScaler.restorePosition; |
924 | + var itemSize = scopesOverviewXYScaler.restoreSize; |
925 | + scopesOverviewXYScaler.scale = itemSize.width / scopesOverviewXYScaler.width; |
926 | + if (itemPos) { |
927 | + scopesOverviewXYScaler.x = itemPos.x -(scopesOverviewXYScaler.width - scopesOverviewXYScaler.width * scopesOverviewXYScaler.scale) / 2; |
928 | + scopesOverviewXYScaler.y = itemPos.y -(scopesOverviewXYScaler.height - scopesOverviewXYScaler.height * scopesOverviewXYScaler.scale) / 2; |
929 | + } else { |
930 | + scopesOverviewXYScaler.x = 0; |
931 | + scopesOverviewXYScaler.y = 0; |
932 | + } |
933 | + scopesOverviewXYScaler.opacity = 0; |
934 | + tempScopeItem.scope = scope; |
935 | + middleItems.overrideOpacity = 0; |
936 | + scopesOverviewXYScaler.scale = 1; |
937 | + scopesOverviewXYScaler.x = 0; |
938 | + scopesOverviewXYScaler.y = 0; |
939 | + scopesOverviewXYScaler.opacity = 1; |
940 | + } |
941 | + } |
942 | + |
943 | + function animateDashFromAll(scopeId) { |
944 | + var currentScopePos = allScopeCardPosition(scopeId); |
945 | + if (currentScopePos) { |
946 | + showDashFromPos(currentScopePos, allCardSize); |
947 | + } else { |
948 | + console.log("Warning: Could not find Dash OverView All card position for scope", dashContent.currentScopeId); |
949 | + } |
950 | + } |
951 | + |
952 | + function showDashFromPos(itemPos, itemSize) { |
953 | + scopesOverviewXYScaler.scale = itemSize.width / scopesOverviewXYScaler.width; |
954 | + scopesOverviewXYScaler.x = itemPos.x -(scopesOverviewXYScaler.width - scopesOverviewXYScaler.width * scopesOverviewXYScaler.scale) / 2; |
955 | + scopesOverviewXYScaler.y = itemPos.y -(scopesOverviewXYScaler.height - scopesOverviewXYScaler.height * scopesOverviewXYScaler.scale) / 2; |
956 | + scopesOverviewXYScaler.opacity = 0; |
957 | + root.growingDashFromPos = true; |
958 | + scopesOverviewXYScaler.scale = 1; |
959 | + scopesOverviewXYScaler.x = 0; |
960 | + scopesOverviewXYScaler.y = 0; |
961 | + scopesOverviewXYScaler.opacity = 1; |
962 | + } |
963 | + |
964 | + function allScopeCardPosition(scopeId) { |
965 | + if (middleItems.count > 1) { |
966 | + var loaderItem = middleItems.itemAt(1).item; |
967 | + if (loaderItem) { |
968 | + var pos = loaderItem.scopeCardPosition(scopeId); |
969 | + return loaderItem.mapToItem(null, pos.x, pos.y); |
970 | + } |
971 | + } |
972 | + } |
973 | + |
974 | + function ensureAllScopeVisible(scopeId) { |
975 | + if (middleItems.count > 1) { |
976 | + var loaderItem = middleItems.itemAt(1).item; |
977 | + if (loaderItem) { |
978 | + var pos = loaderItem.scopeCardPosition(scopeId); |
979 | + loaderItem.contentY = Math.min(pos.y, loaderItem.contentHeight - loaderItem.height); |
980 | + } |
981 | + } |
982 | + } |
983 | + |
984 | + onProgressChanged: { |
985 | + if (progress == 0) { |
986 | + pageHeader.resetSearch(); |
987 | + pageHeader.unfocus(); // Shouldn't the previous call do this too? |
988 | + } |
989 | + } |
990 | + |
991 | + ScopeStyle { |
992 | + id: overviewScopeStyle |
993 | + style: { "foreground-color" : "white", "background-color" : "transparent" } |
994 | + } |
995 | + |
996 | + DashBackground { |
997 | + anchors.fill: parent |
998 | + source: "graphics/dark_background.jpg" |
999 | + } |
1000 | + |
1001 | + Connections { |
1002 | + target: pageHeader |
1003 | + onSearchQueryChanged: { |
1004 | + // Need this in order, otherwise something gets unhappy in rendering |
1005 | + // of the overlay in carousels because the parent of the dash dies for |
1006 | + // a moment, this way we make sure it's reparented first |
1007 | + // by forceXYScalerEater making dashItemEater return scopesOverviewXYScaler |
1008 | + // before we kill the previous parent by scope.searchQuery |
1009 | + root.forceXYScalerEater = true; |
1010 | + root.scope.searchQuery = pageHeader.searchQuery; |
1011 | + root.forceXYScalerEater = false; |
1012 | + } |
1013 | + } |
1014 | + |
1015 | + Binding { |
1016 | + target: pageHeader |
1017 | + property: "searchQuery" |
1018 | + value: scope ? scope.searchQuery : "" |
1019 | + } |
1020 | + |
1021 | + Item { |
1022 | + id: scopesOverviewContent |
1023 | + x: previewListView.open ? -width : 0 |
1024 | + Behavior on x { UbuntuNumberAnimation { } } |
1025 | + width: parent.width |
1026 | + height: parent.height |
1027 | + |
1028 | + PageHeader { |
1029 | + id: pageHeader |
1030 | + objectName: "scopesOverviewPageHeader" |
1031 | + |
1032 | + readonly property real yDisplacement: pageHeader.height + tabBar.height + tabBar.anchors.margins |
1033 | + |
1034 | + y: { |
1035 | + if (root.progress < 0.5) { |
1036 | + return -yDisplacement; |
1037 | + } else { |
1038 | + return -yDisplacement + (root.progress - 0.5) * yDisplacement * 2; |
1039 | + } |
1040 | + } |
1041 | + width: parent.width |
1042 | + clip: true |
1043 | + title: i18n.tr("Manage Dash") |
1044 | + scopeStyle: overviewScopeStyle |
1045 | + showSignatureLine: false |
1046 | + searchEntryEnabled: true |
1047 | + searchInProgress: root.scope ? root.scope.searchInProgress : false |
1048 | + } |
1049 | + |
1050 | + ScopesOverviewTab { |
1051 | + id: tabBar |
1052 | + anchors { |
1053 | + left: parent.left |
1054 | + right: parent.right |
1055 | + top: pageHeader.bottom |
1056 | + margins: units.gu(2) |
1057 | + } |
1058 | + height: units.gu(4) |
1059 | + |
1060 | + enabled: opacity == 1 |
1061 | + opacity: !scope || scope.searchQuery == "" ? 1 : 0 |
1062 | + Behavior on opacity { UbuntuNumberAnimation { } } |
1063 | + } |
1064 | + |
1065 | + Repeater { |
1066 | + id: middleItems |
1067 | + objectName: "scopesOverviewRepeater" |
1068 | + property real overrideOpacity: -1 |
1069 | + model: scope && scope.searchQuery == "" ? scope.categories : null |
1070 | + delegate: Loader { |
1071 | + id: loader |
1072 | + objectName: "scopesOverviewRepeaterChild" + index |
1073 | + |
1074 | + height: { |
1075 | + if (index == 0) { |
1076 | + return root.height; |
1077 | + } else { |
1078 | + return root.height - pageHeader.height - tabBar.height - tabBar.anchors.margins - units.gu(2) |
1079 | + } |
1080 | + } |
1081 | + width: { |
1082 | + if (index == 0) { |
1083 | + return root.width / scopeScale |
1084 | + } else { |
1085 | + return root.width |
1086 | + } |
1087 | + } |
1088 | + x: { |
1089 | + if (index == 0) { |
1090 | + return (root.width - width) / 2; |
1091 | + } else { |
1092 | + return 0; |
1093 | + } |
1094 | + } |
1095 | + anchors { |
1096 | + bottom: scopesOverviewContent.bottom |
1097 | + } |
1098 | + |
1099 | + scale: index == 0 ? scopeScale : 1 |
1100 | + |
1101 | + opacity: { |
1102 | + if (middleItems.overrideOpacity >= 0) |
1103 | + return middleItems.overrideOpacity; |
1104 | + |
1105 | + if (tabBar.currentTab != index) |
1106 | + return 0; |
1107 | + |
1108 | + return index == 0 ? 1 : root.progress; |
1109 | + } |
1110 | + Behavior on opacity { |
1111 | + enabled: root.progress == 1 |
1112 | + UbuntuNumberAnimation { } |
1113 | + } |
1114 | + enabled: opacity == 1 |
1115 | + |
1116 | + clip: index == 1 |
1117 | + |
1118 | + CardTool { |
1119 | + id: cardTool |
1120 | + objectName: "cardTool" |
1121 | + count: results.count |
1122 | + template: model.renderer |
1123 | + components: model.components |
1124 | + viewWidth: parent.width |
1125 | + } |
1126 | + |
1127 | + source: { |
1128 | + if (index == 0 && categoryId == "favorites") return "ScopesOverviewFavorites.qml"; |
1129 | + else if (index == 1 && categoryId == "all") return "ScopesOverviewAll.qml"; |
1130 | + else return ""; |
1131 | + } |
1132 | + |
1133 | + onLoaded: { |
1134 | + item.model = Qt.binding(function() { return results }) |
1135 | + item.cardTool = cardTool; |
1136 | + if (index == 0) { |
1137 | + item.scopeWidth = Qt.binding(function() { return root.width; }); |
1138 | + item.scopeHeight = Qt.binding(function() { return root.height; }); |
1139 | + item.appliedScale = Qt.binding(function() { return loader.scale }); |
1140 | + item.currentIndex = Qt.binding(function() { return root.currentIndex }); |
1141 | + } else if (index == 1) { |
1142 | + item.extraHeight = bottomBar.height; |
1143 | + } |
1144 | + } |
1145 | + |
1146 | + Connections { |
1147 | + target: loader.item |
1148 | + onClicked: { |
1149 | + if (tabBar.currentTab == 0) { |
1150 | + root.favoriteSelected(itemModel.scopeId) |
1151 | + } else { |
1152 | + var favoriteScopesItem = middleItems.itemAt(0).item; |
1153 | + var scopeIndex = favoriteScopesItem.model.scopeIndex(itemModel.scopeId); |
1154 | + if (scopeIndex >= 0) { |
1155 | + root.allFavoriteSelected(itemModel.scopeId); |
1156 | + } else { |
1157 | + // Will result in an openScope from root.scope |
1158 | + scopesOverviewXYScaler.restorePosition = item.mapToItem(null, 0, 0); |
1159 | + scopesOverviewXYScaler.restoreSize = allCardSize; |
1160 | + root.scope.activate(result); |
1161 | + } |
1162 | + } |
1163 | + } |
1164 | + onPressAndHold: { |
1165 | + // Preview can call openScope so make sure restorePosition and restoreSize are set |
1166 | + scopesOverviewXYScaler.restorePosition = undefined; |
1167 | + scopesOverviewXYScaler.restoreSize = allCardSize; |
1168 | + |
1169 | + previewListView.model = target.model; |
1170 | + previewListView.currentIndex = -1 |
1171 | + previewListView.currentIndex = index; |
1172 | + previewListView.open = true |
1173 | + } |
1174 | + } |
1175 | + } |
1176 | + } |
1177 | + |
1178 | + GenericScopeView { |
1179 | + id: searchResultsViewer |
1180 | + objectName: "searchResultsViewer" |
1181 | + anchors { |
1182 | + top: pageHeader.bottom |
1183 | + right: parent.right |
1184 | + left: parent.left |
1185 | + bottom: parent.bottom |
1186 | + } |
1187 | + scope: root.scope && root.scope.searchQuery != "" ? root.scope : null |
1188 | + scopeStyle: overviewScopeStyle |
1189 | + enabled: opacity == 1 |
1190 | + showPageHeader: false |
1191 | + clip: true |
1192 | + opacity: searchResultsViewer.scope ? 1 : 0 |
1193 | + Behavior on opacity { UbuntuNumberAnimation { } } |
1194 | + |
1195 | + clickOverride: function (index, result, item, itemModel) { |
1196 | + pageHeader.closePopup(); |
1197 | + if (itemModel.scopeId) { |
1198 | + // This can end up in openScope so save restorePosition and restoreSize |
1199 | + scopesOverviewXYScaler.restorePosition = item.mapToItem(null, 0, 0); |
1200 | + scopesOverviewXYScaler.restoreSize = Qt.size(item.width, item.height); |
1201 | + root.searchSelected(itemModel.scopeId, result, item.mapToItem(null, 0, 0), Qt.size(item.width, item.height)); |
1202 | + } else { |
1203 | + // Not a scope, just activate it |
1204 | + searchResultsViewer.scope.activate(result); |
1205 | + } |
1206 | + } |
1207 | + |
1208 | + pressAndHoldOverride: function (index) { |
1209 | + // Do nothing |
1210 | + } |
1211 | + } |
1212 | + |
1213 | + Rectangle { |
1214 | + id: bottomBar |
1215 | + color: "black" |
1216 | + height: units.gu(6) |
1217 | + width: parent.width |
1218 | + enabled: opacity == 0.4 |
1219 | + opacity: scope && scope.searchQuery == "" ? 0.4 : 0 |
1220 | + Behavior on opacity { UbuntuNumberAnimation { } } |
1221 | + y: { |
1222 | + if (root.progress < 0.5) { |
1223 | + return parent.height; |
1224 | + } else { |
1225 | + return parent.height - (root.progress - 0.5) * height * 2; |
1226 | + } |
1227 | + } |
1228 | + |
1229 | + AbstractButton { |
1230 | + objectName: "scopesOverviewDoneButton" |
1231 | + width: Math.max(label.width + units.gu(2), units.gu(10)) |
1232 | + height: units.gu(4) |
1233 | + anchors { |
1234 | + left: parent.left |
1235 | + leftMargin: units.gu(2) |
1236 | + verticalCenter: parent.verticalCenter |
1237 | + } |
1238 | + Rectangle { |
1239 | + anchors.fill: parent |
1240 | + border.color: "white" |
1241 | + border.width: units.dp(1) |
1242 | + radius: units.dp(10) |
1243 | + color: parent.pressed ? "gray" : "transparent" |
1244 | + } |
1245 | + Label { |
1246 | + id: label |
1247 | + anchors.centerIn: parent |
1248 | + text: i18n.tr("Done") |
1249 | + color: parent.pressed ? "black" : "white" |
1250 | + } |
1251 | + onClicked: root.done(); |
1252 | + } |
1253 | + |
1254 | + AbstractButton { |
1255 | + objectName: "scopesOverviewStoreButton" |
1256 | + width: Math.max(storeLabel.width, units.gu(10)) |
1257 | + height: units.gu(4) |
1258 | + anchors { |
1259 | + right: parent.right |
1260 | + verticalCenter: parent.verticalCenter |
1261 | + } |
1262 | + Image { |
1263 | + id: storeImage |
1264 | + source: "graphics/apps-scope.png" |
1265 | + anchors.horizontalCenter: parent.horizontalCenter |
1266 | + width: units.gu(2) |
1267 | + height: units.gu(2) |
1268 | + fillMode: Image.Stretch |
1269 | + } |
1270 | + Label { |
1271 | + id: storeLabel |
1272 | + anchors.horizontalCenter: parent.horizontalCenter |
1273 | + anchors.top: storeImage.bottom |
1274 | + text: i18n.tr("Store") |
1275 | + color: "white" |
1276 | + } |
1277 | + onClicked: { |
1278 | + // Just zoom from the middle |
1279 | + scopesOverviewXYScaler.restorePosition = undefined; |
1280 | + scopesOverviewXYScaler.restoreSize = allCardSize; |
1281 | + scope.performQuery("scope://com.canonical.scopes.clickstore"); |
1282 | + } |
1283 | + } |
1284 | + } |
1285 | + } |
1286 | + |
1287 | + PreviewListView { |
1288 | + id: previewListView |
1289 | + objectName: "scopesOverviewPreviewListView" |
1290 | + scope: root.scope |
1291 | + scopeStyle: overviewScopeStyle |
1292 | + visible: x != width |
1293 | + width: parent.width |
1294 | + height: parent.height |
1295 | + anchors.left: scopesOverviewContent.right |
1296 | + } |
1297 | + |
1298 | + |
1299 | + |
1300 | + Item { |
1301 | + id: scopesOverviewXYScaler |
1302 | + width: parent.width |
1303 | + height: parent.height |
1304 | + |
1305 | + clip: scale != 1.0 |
1306 | + enabled: scale == 1 |
1307 | + |
1308 | + property bool animationsEnabled: root.showingNonFavoriteScope || root.growingDashFromPos |
1309 | + |
1310 | + property var restorePosition |
1311 | + property var restoreSize |
1312 | + |
1313 | + Behavior on x { |
1314 | + enabled: scopesOverviewXYScaler.animationsEnabled |
1315 | + UbuntuNumberAnimation { } |
1316 | + } |
1317 | + Behavior on y { |
1318 | + enabled: scopesOverviewXYScaler.animationsEnabled |
1319 | + UbuntuNumberAnimation { } |
1320 | + } |
1321 | + Behavior on opacity { |
1322 | + enabled: scopesOverviewXYScaler.animationsEnabled |
1323 | + UbuntuNumberAnimation { } |
1324 | + } |
1325 | + Behavior on scale { |
1326 | + enabled: scopesOverviewXYScaler.animationsEnabled |
1327 | + UbuntuNumberAnimation { |
1328 | + onRunningChanged: { |
1329 | + if (!running) { |
1330 | + if (root.showingNonFavoriteScope && scopesOverviewXYScaler.scale != 1) { |
1331 | + root.scope.closeScope(tempScopeItem.scope); |
1332 | + tempScopeItem.scope = null; |
1333 | + } else if (root.growingDashFromPos) { |
1334 | + root.growingDashFromPos = false; |
1335 | + } |
1336 | + } |
1337 | + } |
1338 | + } |
1339 | + } |
1340 | + |
1341 | + DashBackground |
1342 | + { |
1343 | + anchors.fill: tempScopeItem |
1344 | + visible: tempScopeItem.visible |
1345 | + parent: tempScopeItem.parent |
1346 | + } |
1347 | + |
1348 | + GenericScopeView { |
1349 | + id: tempScopeItem |
1350 | + objectName: "scopesOverviewTempScopeItem" |
1351 | + |
1352 | + width: parent.width |
1353 | + height: parent.height |
1354 | + scale: dash.contentScale |
1355 | + clip: scale != 1.0 |
1356 | + visible: scope != null |
1357 | + hasBackAction: true |
1358 | + isCurrent: visible |
1359 | + onBackClicked: { |
1360 | + var v = scopesOverviewXYScaler.restoreSize.width / tempScopeItem.width; |
1361 | + scopesOverviewXYScaler.scale = v; |
1362 | + if (scopesOverviewXYScaler.restorePosition) { |
1363 | + scopesOverviewXYScaler.x = scopesOverviewXYScaler.restorePosition.x -(tempScopeItem.width - tempScopeItem.width * v) / 2; |
1364 | + scopesOverviewXYScaler.y = scopesOverviewXYScaler.restorePosition.y -(tempScopeItem.height - tempScopeItem.height * v) / 2; |
1365 | + } else { |
1366 | + scopesOverviewXYScaler.x = 0; |
1367 | + scopesOverviewXYScaler.y = 0; |
1368 | + } |
1369 | + scopesOverviewXYScaler.opacity = 0; |
1370 | + middleItems.overrideOpacity = -1; |
1371 | + } |
1372 | + } |
1373 | + } |
1374 | +} |
1375 | |
1376 | === added file 'qml/Dash/ScopesOverviewAll.qml' |
1377 | --- qml/Dash/ScopesOverviewAll.qml 1970-01-01 00:00:00 +0000 |
1378 | +++ qml/Dash/ScopesOverviewAll.qml 2014-07-29 11:05:57 +0000 |
1379 | @@ -0,0 +1,54 @@ |
1380 | +/* |
1381 | + * Copyright (C) 2014 Canonical, Ltd. |
1382 | + * |
1383 | + * This program is free software; you can redistribute it and/or modify |
1384 | + * it under the terms of the GNU General Public License as published by |
1385 | + * the Free Software Foundation; version 3. |
1386 | + * |
1387 | + * This program is distributed in the hope that it will be useful, |
1388 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1389 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1390 | + * GNU General Public License for more details. |
1391 | + * |
1392 | + * You should have received a copy of the GNU General Public License |
1393 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1394 | + */ |
1395 | + |
1396 | +import QtQuick 2.0 |
1397 | +import Ubuntu.Components 0.1 |
1398 | + |
1399 | +Flickable { |
1400 | + id: root |
1401 | + |
1402 | + property alias model: cardGrid.model |
1403 | + property alias cardTool: cardGrid.cardTool |
1404 | + |
1405 | + property real extraHeight: 0 |
1406 | + |
1407 | + signal clicked(int index, var result, var item, var itemModel) |
1408 | + signal pressAndHold(int index) |
1409 | + |
1410 | + contentHeight: cardGrid.expandedHeight + extraHeight |
1411 | + contentWidth: cardGrid.width |
1412 | + flickableDirection: Flickable.VerticalFlick |
1413 | + |
1414 | + function scopeCardPosition(scopeId) { |
1415 | + var index = model.scopeIndex(scopeId); |
1416 | + var pos = cardGrid.cardPosition(index); |
1417 | + pos.y = pos.y - root.contentY; |
1418 | + return pos; |
1419 | + } |
1420 | + |
1421 | + CardGrid { |
1422 | + id: cardGrid |
1423 | + width: root.width |
1424 | + height: parent.height |
1425 | + |
1426 | + onClicked: { |
1427 | + root.clicked(index, result, item, itemModel); |
1428 | + } |
1429 | + onPressAndHold: { |
1430 | + root.pressAndHold(index); |
1431 | + } |
1432 | + } |
1433 | +} |
1434 | |
1435 | === added file 'qml/Dash/ScopesOverviewFavorites.qml' |
1436 | --- qml/Dash/ScopesOverviewFavorites.qml 1970-01-01 00:00:00 +0000 |
1437 | +++ qml/Dash/ScopesOverviewFavorites.qml 2014-07-29 11:05:57 +0000 |
1438 | @@ -0,0 +1,73 @@ |
1439 | +/* |
1440 | + * Copyright (C) 2014 Canonical, Ltd. |
1441 | + * |
1442 | + * This program is free software; you can redistribute it and/or modify |
1443 | + * it under the terms of the GNU General Public License as published by |
1444 | + * the Free Software Foundation; version 3. |
1445 | + * |
1446 | + * This program is distributed in the hope that it will be useful, |
1447 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1448 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1449 | + * GNU General Public License for more details. |
1450 | + * |
1451 | + * You should have received a copy of the GNU General Public License |
1452 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1453 | + */ |
1454 | + |
1455 | +import QtQuick 2.0 |
1456 | + |
1457 | +Flickable { |
1458 | + id: root |
1459 | + |
1460 | + signal clicked(int index, var result, var itemModel) |
1461 | + signal pressAndHold(int index) |
1462 | + |
1463 | + property var cardTool: null |
1464 | + property real scopeHeight: 0 |
1465 | + property real scopeWidth: 0 |
1466 | + property real appliedScale: 1 |
1467 | + property int currentIndex: -1 |
1468 | + property var currentItem: repeater.itemAt(currentIndex); |
1469 | + |
1470 | + property alias model: repeater.model |
1471 | + |
1472 | + contentHeight: height |
1473 | + contentWidth: repeater.count * root.scopeWidth + units.gu(2) / appliedScale * (repeater.count - 1) |
1474 | + |
1475 | + contentX: { |
1476 | + var indexX = currentIndex * scopeWidth + units.gu(2) / appliedScale * currentIndex; |
1477 | + var newContentX = indexX - (width - scopeWidth) / 2; |
1478 | + newContentX = Math.min(Math.max(newContentX, 0), contentWidth - width); |
1479 | + return newContentX; |
1480 | + } |
1481 | + |
1482 | + Repeater { |
1483 | + id: repeater |
1484 | + objectName: "scopesOverviewFavoritesRepeater" |
1485 | + |
1486 | + delegate: Loader { |
1487 | + id: loader |
1488 | + |
1489 | + x: index * root.scopeWidth + units.gu(2) / appliedScale * index |
1490 | + asynchronous: true |
1491 | + |
1492 | + sourceComponent: cardTool.cardComponent |
1493 | + onLoaded: { |
1494 | + item.fixedArtShapeSize = Qt.binding(function() { return Qt.size(root.scopeWidth, root.scopeHeight); }); |
1495 | + item.fixedHeaderHeight = Qt.binding(function() { return cardTool.headerHeight / appliedScale; }); |
1496 | + item.fontScale = Qt.binding(function() { return 1 / appliedScale; }); |
1497 | + item.height = Qt.binding(function() { return root.scopeHeight; }); |
1498 | + item.width = Qt.binding(function() { return root.scopeWidth; }); |
1499 | + item.cardData = Qt.binding(function() { return model; }); |
1500 | + item.template = Qt.binding(function() { return cardTool.template; }); |
1501 | + item.components = Qt.binding(function() { return cardTool.components; }); |
1502 | + item.headerAlignment = Qt.binding(function() { return cardTool.headerAlignment; }); |
1503 | + } |
1504 | + |
1505 | + Connections { |
1506 | + target: loader.item |
1507 | + onClicked: root.clicked(index, result, model) |
1508 | + } |
1509 | + } |
1510 | + } |
1511 | +} |
1512 | |
1513 | === added file 'qml/Dash/ScopesOverviewTab.qml' |
1514 | --- qml/Dash/ScopesOverviewTab.qml 1970-01-01 00:00:00 +0000 |
1515 | +++ qml/Dash/ScopesOverviewTab.qml 2014-07-29 11:05:57 +0000 |
1516 | @@ -0,0 +1,74 @@ |
1517 | +/* |
1518 | + * Copyright (C) 2014 Canonical, Ltd. |
1519 | + * |
1520 | + * This program is free software; you can redistribute it and/or modify |
1521 | + * it under the terms of the GNU General Public License as published by |
1522 | + * the Free Software Foundation; version 3. |
1523 | + * |
1524 | + * This program is distributed in the hope that it will be useful, |
1525 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1526 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1527 | + * GNU General Public License for more details. |
1528 | + * |
1529 | + * You should have received a copy of the GNU General Public License |
1530 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1531 | + */ |
1532 | + |
1533 | +import QtQuick 2.3 |
1534 | +import Ubuntu.Components 0.1 |
1535 | + |
1536 | +Item { |
1537 | + id: root |
1538 | + |
1539 | + property int currentTab: 0 |
1540 | + |
1541 | + AbstractButton { |
1542 | + id: tab1 |
1543 | + height: parent.height |
1544 | + width: parent.width / 2 |
1545 | + Rectangle { |
1546 | + anchors.fill: parent |
1547 | + color: root.currentTab == 0 && root.enabled ? "white" : "transparent" |
1548 | + radius: units.dp(10) |
1549 | + } |
1550 | + Label { |
1551 | + anchors.centerIn: parent |
1552 | + text: i18n.tr("Favorites") |
1553 | + color: root.currentTab == 0 && root.enabled ? "black" : "white" |
1554 | + } |
1555 | + onClicked: root.currentTab = 0 |
1556 | + } |
1557 | + AbstractButton { |
1558 | + id: tab2 |
1559 | + objectName: "scopesOverviewAllTabButton" |
1560 | + x: width |
1561 | + height: parent.height |
1562 | + width: parent.width / 2 |
1563 | + Rectangle { |
1564 | + anchors.fill: parent |
1565 | + color: root.currentTab == 1 && root.enabled ? "white" : "transparent" |
1566 | + radius: units.dp(10) |
1567 | + } |
1568 | + Label { |
1569 | + anchors.centerIn: parent |
1570 | + text: i18n.tr("All") |
1571 | + color: root.currentTab == 1 && root.enabled ? "black" : "white" |
1572 | + } |
1573 | + onClicked: root.currentTab = 1 |
1574 | + } |
1575 | + Rectangle { |
1576 | + id: centerPiece |
1577 | + width: root.enabled ? units.dp(10) : units.dp(1) |
1578 | + height: parent.height |
1579 | + color: "white" |
1580 | + x: root.currentTab == 1 ? tab2.x : tab2.x - width |
1581 | + } |
1582 | + Rectangle { |
1583 | + id: border |
1584 | + anchors.fill: parent |
1585 | + radius: units.dp(10) |
1586 | + color: "transparent" |
1587 | + border.color: centerPiece.color |
1588 | + border.width: units.dp(1) |
1589 | + } |
1590 | +} |
1591 | |
1592 | === added file 'qml/Dash/graphics/apps-scope.png' |
1593 | Binary files qml/Dash/graphics/apps-scope.png 1970-01-01 00:00:00 +0000 and qml/Dash/graphics/apps-scope.png 2014-07-29 11:05:57 +0000 differ |
1594 | === added file 'qml/Dash/graphics/dark_background.jpg' |
1595 | Binary files qml/Dash/graphics/dark_background.jpg 1970-01-01 00:00:00 +0000 and qml/Dash/graphics/dark_background.jpg 2014-07-29 11:05:57 +0000 differ |
1596 | === modified file 'qml/Shell.qml' |
1597 | --- qml/Shell.qml 2014-07-18 15:13:35 +0000 |
1598 | +++ qml/Shell.qml 2014-07-29 11:05:57 +0000 |
1599 | @@ -125,14 +125,6 @@ |
1600 | opacity: dash.disappearingAnimationProgress |
1601 | } |
1602 | |
1603 | - Image { |
1604 | - anchors.fill: dash |
1605 | - source: shell.width > shell.height ? "Dash/graphics/paper_landscape.png" : "Dash/graphics/paper_portrait.png" |
1606 | - fillMode: Image.PreserveAspectCrop |
1607 | - horizontalAlignment: Image.AlignRight |
1608 | - verticalAlignment: Image.AlignTop |
1609 | - } |
1610 | - |
1611 | Dash { |
1612 | id: dash |
1613 | objectName: "dash" |
1614 | @@ -142,6 +134,8 @@ |
1615 | shown: disappearingAnimationProgress !== 1.0 && greeterWrapper.showProgress !== 1.0 |
1616 | enabled: disappearingAnimationProgress === 0.0 && greeterWrapper.showProgress === 0.0 && edgeDemo.dashEnabled |
1617 | |
1618 | + overviewHandleHeight: shell.edgeSize |
1619 | + |
1620 | anchors { |
1621 | fill: parent |
1622 | topMargin: panel.panelHeight |
1623 | |
1624 | === modified file 'tests/autopilot/unity8/shell/emulators/dash.py' |
1625 | --- tests/autopilot/unity8/shell/emulators/dash.py 2014-07-25 10:47:19 +0000 |
1626 | +++ tests/autopilot/unity8/shell/emulators/dash.py 2014-07-29 11:05:57 +0000 |
1627 | @@ -18,6 +18,7 @@ |
1628 | # |
1629 | |
1630 | import logging |
1631 | +import time |
1632 | import ubuntuuitoolkit |
1633 | |
1634 | from unity8.shell import emulators |
1635 | @@ -68,7 +69,9 @@ |
1636 | |
1637 | """ |
1638 | scope_loader = self._get_scope_loader(scope_id) |
1639 | + print ("open_scope", scope_id, scope_loader) |
1640 | if scope_loader.isCurrent: |
1641 | + print ("scope_loader.isCurrent") |
1642 | logger.info('The scope is already open.') |
1643 | return self._get_scope_from_loader(scope_loader) |
1644 | else: |
1645 | @@ -83,6 +86,12 @@ |
1646 | 'No scope found with id {0}'.format(scope_id)) |
1647 | |
1648 | def _get_scope_from_loader(self, loader): |
1649 | + print ("_get_scope_from_loader", loader, loader.isCurrent, loader.isLoaded, loader.get_children()) |
1650 | + i = 0 |
1651 | + time.sleep(1) |
1652 | + while len(loader.get_children()) < 1 and i < 5: |
1653 | + time.sleep(1) |
1654 | + i = i + 1 |
1655 | return loader.get_children()[0] |
1656 | |
1657 | def _open_scope_scrolling(self, scope_loader): |
1658 | |
1659 | === modified file 'tests/mocks/Unity/CMakeLists.txt' |
1660 | --- tests/mocks/Unity/CMakeLists.txt 2014-07-08 09:23:14 +0000 |
1661 | +++ tests/mocks/Unity/CMakeLists.txt 2014-07-29 11:05:57 +0000 |
1662 | @@ -6,7 +6,7 @@ |
1663 | pkg_search_module(DEE dee-1.0 REQUIRED) |
1664 | pkg_search_module(GOBJECT gobject-2.0 REQUIRED) |
1665 | pkg_search_module(DEEQT libdee-qt5 REQUIRED) |
1666 | -pkg_check_modules(SCOPES_API REQUIRED unity-shell-scopes=2) |
1667 | +pkg_check_modules(SCOPES_API REQUIRED unity-shell-scopes=3) |
1668 | |
1669 | include_directories( |
1670 | ${CMAKE_CURRENT_BINARY_DIR} |
1671 | @@ -21,6 +21,7 @@ |
1672 | set(UnityQML_SOURCES |
1673 | fake_scope.cpp |
1674 | fake_scopes.cpp |
1675 | + fake_scopesoverview.cpp |
1676 | fake_categories.cpp |
1677 | fake_department.cpp |
1678 | fake_resultsmodel.cpp |
1679 | |
1680 | === modified file 'tests/mocks/Unity/fake_resultsmodel.cpp' |
1681 | --- tests/mocks/Unity/fake_resultsmodel.cpp 2014-05-20 10:29:20 +0000 |
1682 | +++ tests/mocks/Unity/fake_resultsmodel.cpp 2014-07-29 11:05:57 +0000 |
1683 | @@ -58,8 +58,9 @@ |
1684 | case RoleUri: |
1685 | case RoleCategoryId: |
1686 | case RoleDndUri: |
1687 | + return QString(); |
1688 | case RoleResult: |
1689 | - return QString(); |
1690 | + return QString("Result.%1.%2").arg(m_categoryId).arg(index.row()); |
1691 | case RoleTitle: |
1692 | return QString("Title.%1.%2").arg(m_categoryId).arg(index.row()); |
1693 | case RoleArt: |
1694 | |
1695 | === modified file 'tests/mocks/Unity/fake_scope.cpp' |
1696 | --- tests/mocks/Unity/fake_scope.cpp 2014-07-24 20:40:57 +0000 |
1697 | +++ tests/mocks/Unity/fake_scope.cpp 2014-07-29 11:05:57 +0000 |
1698 | @@ -14,17 +14,20 @@ |
1699 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1700 | */ |
1701 | |
1702 | +#include <QDebug> |
1703 | #include <QUrl> |
1704 | |
1705 | #include "fake_scope.h" |
1706 | + |
1707 | #include "fake_department.h" |
1708 | #include "fake_resultsmodel.h" |
1709 | +#include "fake_scopes.h" |
1710 | |
1711 | -Scope::Scope(QObject* parent) : Scope(QString(), QString(), false, parent) |
1712 | +Scope::Scope(Scopes* parent) : Scope(QString(), QString(), false, parent) |
1713 | { |
1714 | } |
1715 | |
1716 | -Scope::Scope(QString const& id, QString const& name, bool visible, QObject* parent, int categories) |
1717 | +Scope::Scope(QString const& id, QString const& name, bool visible, Scopes* parent, int categories) |
1718 | : unity::shell::scopes::ScopeInterface(parent) |
1719 | , m_id(id) |
1720 | , m_name(name) |
1721 | @@ -34,6 +37,7 @@ |
1722 | , m_currentDeparment("root") |
1723 | , m_previewRendererName("preview-generic") |
1724 | , m_categories(new Categories(categories, this)) |
1725 | + , m_openScope(nullptr) |
1726 | { |
1727 | } |
1728 | |
1729 | @@ -149,7 +153,12 @@ |
1730 | |
1731 | void Scope::activate(QVariant const& result) |
1732 | { |
1733 | - Q_UNUSED(result); |
1734 | + qDebug() << "Called activate on scope" << m_id << "with result" << result; |
1735 | + if (result.toString() == "Result.2.2") { |
1736 | + Scopes *scopes = dynamic_cast<Scopes*>(parent()); |
1737 | + m_openScope = scopes->getScopeFromAll("MockScope9"); |
1738 | + Q_EMIT openScope(m_openScope); |
1739 | + } |
1740 | } |
1741 | |
1742 | PreviewStack* Scope::preview(QVariant const& result) |
1743 | @@ -165,9 +174,13 @@ |
1744 | { |
1745 | } |
1746 | |
1747 | -void Scope::closeScope(unity::shell::scopes::ScopeInterface* /*scope*/) |
1748 | +void Scope::closeScope(unity::shell::scopes::ScopeInterface* scope) |
1749 | { |
1750 | - qFatal("Scope::closeScope is not implemented"); |
1751 | + if (scope != m_openScope) { |
1752 | + qDebug() << scope << m_openScope; |
1753 | + qFatal("Scope::closeScope got wrong scope in closeScope"); |
1754 | + } |
1755 | + m_openScope = nullptr; |
1756 | } |
1757 | |
1758 | QString Scope::currentDepartmentId() const |
1759 | |
1760 | === modified file 'tests/mocks/Unity/fake_scope.h' |
1761 | --- tests/mocks/Unity/fake_scope.h 2014-07-11 16:39:33 +0000 |
1762 | +++ tests/mocks/Unity/fake_scope.h 2014-07-29 11:05:57 +0000 |
1763 | @@ -24,13 +24,15 @@ |
1764 | |
1765 | #include <QTimer> |
1766 | |
1767 | +class Scopes; |
1768 | + |
1769 | class Scope : public unity::shell::scopes::ScopeInterface |
1770 | { |
1771 | Q_OBJECT |
1772 | |
1773 | public: |
1774 | - Scope(QObject* parent = 0); |
1775 | - Scope(QString const& id, QString const& name, bool visible, QObject* parent = 0, int categories = 20); |
1776 | + Scope(Scopes* parent = 0); |
1777 | + Scope(QString const& id, QString const& name, bool visible, Scopes* parent = 0, int categories = 20); |
1778 | |
1779 | /* getters */ |
1780 | QString id() const override; |
1781 | @@ -84,7 +86,8 @@ |
1782 | |
1783 | QString m_previewRendererName; |
1784 | |
1785 | - Categories* m_categories; |
1786 | + unity::shell::scopes::CategoriesInterface* m_categories; |
1787 | + unity::shell::scopes::ScopeInterface* m_openScope; |
1788 | }; |
1789 | |
1790 | #endif // FAKE_SCOPE_H |
1791 | |
1792 | === modified file 'tests/mocks/Unity/fake_scopes.cpp' |
1793 | --- tests/mocks/Unity/fake_scopes.cpp 2014-07-11 11:45:45 +0000 |
1794 | +++ tests/mocks/Unity/fake_scopes.cpp 2014-07-29 11:05:57 +0000 |
1795 | @@ -18,6 +18,7 @@ |
1796 | |
1797 | // Self |
1798 | #include "fake_scopes.h" |
1799 | +#include "fake_scopesoverview.h" |
1800 | |
1801 | // TODO: Implement remaining pieces, like Categories (i.e. LensView now gives warnings) |
1802 | |
1803 | @@ -26,6 +27,7 @@ |
1804 | |
1805 | Scopes::Scopes(QObject *parent) |
1806 | : unity::shell::scopes::ScopesInterface(parent) |
1807 | + , m_scopesOverview(nullptr) |
1808 | , m_loaded(false) |
1809 | , timer(this) |
1810 | { |
1811 | @@ -47,10 +49,17 @@ |
1812 | addScope(new Scope("clickscope", "Apps", true, this)); |
1813 | addScope(new Scope("MockScope5", "Videos", true, this)); |
1814 | addScope(new Scope("SingleCategoryScope", "Single", true, this, 1)); |
1815 | + addScope(new Scope("MockScope4", "MS4", true, this)); |
1816 | + addScope(new Scope("MockScope6", "MS6", true, this)); |
1817 | + addScope(new Scope("MockScope7", "MS7", false, this)); |
1818 | + addScope(new Scope("MockScope8", "MS8", false, this)); |
1819 | + addScope(new Scope("MockScope9", "MS9", false, this)); |
1820 | + m_scopesOverview = new ScopesOverview(this); |
1821 | |
1822 | if (!m_loaded) { |
1823 | m_loaded = true; |
1824 | Q_EMIT loadedChanged(); |
1825 | + Q_EMIT overviewScopeChanged(); |
1826 | } |
1827 | } |
1828 | |
1829 | @@ -63,6 +72,8 @@ |
1830 | m_scopes.clear(); |
1831 | endRemoveRows(); |
1832 | } |
1833 | + delete m_scopesOverview; |
1834 | + m_scopesOverview = nullptr; |
1835 | |
1836 | if (m_loaded) { |
1837 | m_loaded = false; |
1838 | @@ -110,8 +121,22 @@ |
1839 | return m_scopes[row]; |
1840 | } |
1841 | |
1842 | -unity::shell::scopes::ScopeInterface* Scopes::getScope(QString const&) const |
1843 | -{ |
1844 | +unity::shell::scopes::ScopeInterface* Scopes::getScope(QString const &scope_id) const |
1845 | +{ |
1846 | + for (Scope *scope : m_scopes) { |
1847 | + // According to mh3 Scopes::getScope should only return non null for visible scopes |
1848 | + if (scope->id() == scope_id && scope->visible()) |
1849 | + return scope; |
1850 | + } |
1851 | + return nullptr; |
1852 | +} |
1853 | + |
1854 | +unity::shell::scopes::ScopeInterface* Scopes::getScopeFromAll(const QString& scope_id) const |
1855 | +{ |
1856 | + for (Scope *scope : m_scopes) { |
1857 | + if (scope->id() == scope_id) |
1858 | + return scope; |
1859 | + } |
1860 | return nullptr; |
1861 | } |
1862 | |
1863 | @@ -125,6 +150,22 @@ |
1864 | return m_loaded; |
1865 | } |
1866 | |
1867 | +unity::shell::scopes::ScopeInterface* Scopes::overviewScope() const |
1868 | +{ |
1869 | + return m_scopesOverview; |
1870 | +} |
1871 | + |
1872 | +QList<unity::shell::scopes::ScopeInterface *> Scopes::scopes(bool onlyVisible) const |
1873 | +{ |
1874 | + QList<unity::shell::scopes::ScopeInterface *> res; |
1875 | + for (Scope *scope : m_scopes) { |
1876 | + if (!onlyVisible || scope->visible()) { |
1877 | + res << scope; |
1878 | + } |
1879 | + } |
1880 | + return res; |
1881 | +} |
1882 | + |
1883 | void Scopes::addScope(Scope* scope) |
1884 | { |
1885 | int index = rowCount(); |
1886 | |
1887 | === modified file 'tests/mocks/Unity/fake_scopes.h' |
1888 | --- tests/mocks/Unity/fake_scopes.h 2014-05-20 14:48:08 +0000 |
1889 | +++ tests/mocks/Unity/fake_scopes.h 2014-07-29 11:05:57 +0000 |
1890 | @@ -50,12 +50,18 @@ |
1891 | QModelIndex parent ( const QModelIndex & index ) const; |
1892 | |
1893 | bool loaded() const override; |
1894 | + unity::shell::scopes::ScopeInterface* overviewScope() const override; |
1895 | + |
1896 | + // This is used as part of implementation of the other C++ code, not API |
1897 | + QList<unity::shell::scopes::ScopeInterface *> scopes(bool onlyVisible) const; |
1898 | + unity::shell::scopes::ScopeInterface* getScopeFromAll(const QString& scope_id) const; |
1899 | |
1900 | private Q_SLOTS: |
1901 | void updateScopes(); |
1902 | |
1903 | private: |
1904 | QList<Scope*> m_scopes; |
1905 | + Scope *m_scopesOverview; |
1906 | bool m_loaded; |
1907 | QTimer timer; |
1908 | }; |
1909 | |
1910 | === added file 'tests/mocks/Unity/fake_scopesoverview.cpp' |
1911 | --- tests/mocks/Unity/fake_scopesoverview.cpp 1970-01-01 00:00:00 +0000 |
1912 | +++ tests/mocks/Unity/fake_scopesoverview.cpp 2014-07-29 11:05:57 +0000 |
1913 | @@ -0,0 +1,280 @@ |
1914 | +/* |
1915 | + * Copyright (C) 2014 Canonical, Ltd. |
1916 | + * |
1917 | + * This program is free software; you can redistribute it and/or modify |
1918 | + * it under the terms of the GNU General Public License as published by |
1919 | + * the Free Software Foundation; version 3. |
1920 | + * |
1921 | + * This program is distributed in the hope that it will be useful, |
1922 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1923 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1924 | + * GNU General Public License for more details. |
1925 | + * |
1926 | + * You should have received a copy of the GNU General Public License |
1927 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1928 | + */ |
1929 | + |
1930 | +#include "fake_scopesoverview.h" |
1931 | + |
1932 | +#include "fake_scopes.h" |
1933 | + |
1934 | +#include <paths.h> |
1935 | + |
1936 | +ScopesOverview::ScopesOverview(Scopes* parent) |
1937 | + : Scope("scopesOverview", "Scopes Overview", false, parent) |
1938 | +{ |
1939 | + delete m_categories; // delete the usual categories, we're not going to use it |
1940 | + m_scopesOverviewCategories = new ScopesOverviewCategories(parent, this); |
1941 | + m_searchCategories = new ScopesOverviewSearchCategories(parent, this); |
1942 | + m_categories = m_scopesOverviewCategories; |
1943 | +} |
1944 | + |
1945 | +void ScopesOverview::setSearchQuery(const QString& search_query) |
1946 | +{ |
1947 | + Scope::setSearchQuery(search_query); |
1948 | + |
1949 | + auto origCategories = m_categories; |
1950 | + if (search_query.isEmpty()) m_categories = m_scopesOverviewCategories; |
1951 | + else m_categories = m_searchCategories; |
1952 | + |
1953 | + if (m_categories != origCategories) |
1954 | + Q_EMIT categoriesChanged(); |
1955 | +} |
1956 | + |
1957 | +Q_INVOKABLE void ScopesOverview::activate(QVariant const& result) |
1958 | +{ |
1959 | + Scopes *scopes = dynamic_cast<Scopes*>(parent()); |
1960 | + m_openScope = scopes->getScopeFromAll(result.toString()); |
1961 | + Q_EMIT openScope(m_openScope); |
1962 | +} |
1963 | + |
1964 | +ScopesOverviewCategories::ScopesOverviewCategories(Scopes *scopes, QObject* parent) |
1965 | + : unity::shell::scopes::CategoriesInterface(parent) |
1966 | + , m_scopes(scopes) |
1967 | +{ |
1968 | +} |
1969 | + |
1970 | +int ScopesOverviewCategories::rowCount(const QModelIndex& /*parent*/) const |
1971 | +{ |
1972 | + return 2; |
1973 | +} |
1974 | + |
1975 | +void ScopesOverviewCategories::addSpecialCategory(QString const&, QString const&, QString const&, QString const&, QObject*) |
1976 | +{ |
1977 | + qFatal("Using un-implemented ScopesOverviewCategories::addSpecialCategory"); |
1978 | +} |
1979 | + |
1980 | +bool ScopesOverviewCategories::overrideCategoryJson(QString const& /* categoryId */, QString const& /* json */) |
1981 | +{ |
1982 | + qFatal("Using un-implemented ScopesOverviewCategories::overrideCategoryJson"); |
1983 | +} |
1984 | + |
1985 | +QVariant |
1986 | +ScopesOverviewCategories::data(const QModelIndex& index, int role) const |
1987 | +{ |
1988 | + if (!index.isValid()) { |
1989 | + return QVariant(); |
1990 | + } |
1991 | + |
1992 | + const QString categoryId = index.row() == 0 ? "favorites" : "all"; |
1993 | + |
1994 | + unity::shell::scopes::ResultsModelInterface *resultsModel = m_resultsModels[index.row()]; |
1995 | + if (!resultsModel) { |
1996 | + QObject *that = const_cast<ScopesOverviewCategories*>(this); |
1997 | + resultsModel = new ScopesOverviewResultsModel(m_scopes->scopes(index.row() == 0), categoryId, that); |
1998 | + m_resultsModels[index.row()] = resultsModel; |
1999 | + } |
2000 | + switch (role) { |
2001 | + case RoleCategoryId: |
2002 | + return categoryId; |
2003 | + case RoleName: |
2004 | + return index.row() == 0 ? "Favorites" : "All"; |
2005 | + case RoleIcon: |
2006 | + return QVariant(); |
2007 | + case RoleRawRendererTemplate: |
2008 | + qFatal("Using un-implemented RoleRawRendererTemplate Categories role"); |
2009 | + return QVariant(); |
2010 | + case RoleRenderer: |
2011 | + { |
2012 | + QVariantMap map; |
2013 | + map["category-layout"] = "grid"; |
2014 | + map["card-size"] = "small"; |
2015 | + map["overlay"] = true; |
2016 | + return map; |
2017 | + } |
2018 | + case RoleComponents: |
2019 | + { |
2020 | + QVariantMap map, artMap; |
2021 | + artMap["aspect-ratio"] = "0.5"; |
2022 | + artMap["field"] = "art"; |
2023 | + map["art"] = artMap; |
2024 | + map["title"] = "HOLA"; |
2025 | + return map; |
2026 | + } |
2027 | + case RoleResults: |
2028 | + return QVariant::fromValue(resultsModel); |
2029 | + case RoleCount: |
2030 | + return resultsModel->rowCount(); |
2031 | + case RoleHeaderLink: |
2032 | + return QString(); |
2033 | + default: |
2034 | + qFatal("Using un-implemented Categories role"); |
2035 | + return QVariant(); |
2036 | + } |
2037 | +} |
2038 | + |
2039 | + |
2040 | + |
2041 | +ScopesOverviewSearchCategories::ScopesOverviewSearchCategories(Scopes *scopes, QObject* parent) |
2042 | + : unity::shell::scopes::CategoriesInterface(parent) |
2043 | + , m_scopes(scopes) |
2044 | +{ |
2045 | +} |
2046 | + |
2047 | +int ScopesOverviewSearchCategories::rowCount(const QModelIndex& /*parent*/) const |
2048 | +{ |
2049 | + return 2; |
2050 | +} |
2051 | + |
2052 | +void ScopesOverviewSearchCategories::addSpecialCategory(QString const&, QString const&, QString const&, QString const&, QObject*) |
2053 | +{ |
2054 | + qFatal("Using un-implemented ScopesOverviewSearchCategories::addSpecialCategory"); |
2055 | +} |
2056 | + |
2057 | +bool ScopesOverviewSearchCategories::overrideCategoryJson(QString const& /* categoryId */, QString const& /* json */) |
2058 | +{ |
2059 | + qFatal("Using un-implemented ScopesOverviewSearchCategories::overrideCategoryJson"); |
2060 | +} |
2061 | + |
2062 | +QVariant |
2063 | +ScopesOverviewSearchCategories::data(const QModelIndex& index, int role) const |
2064 | +{ |
2065 | + if (!index.isValid()) { |
2066 | + return QVariant(); |
2067 | + } |
2068 | + |
2069 | + const QString categoryId = index.row() == 0 ? "searchA" : "searchB"; |
2070 | + |
2071 | + unity::shell::scopes::ResultsModelInterface *resultsModel = m_resultsModels[index.row()]; |
2072 | + if (!resultsModel) { |
2073 | + QObject *that = const_cast<ScopesOverviewSearchCategories*>(this); |
2074 | + QList<unity::shell::scopes::ScopeInterface *> scopes; |
2075 | + if (index.row() == 0) { |
2076 | + scopes << m_scopes->getScopeFromAll("clickscope") << nullptr << m_scopes->getScopeFromAll("MockScope2"); |
2077 | + } else { |
2078 | + scopes << nullptr << m_scopes->getScopeFromAll("MockScope7") << nullptr << m_scopes->getScopeFromAll("MockScope1"); |
2079 | + } |
2080 | + resultsModel = new ScopesOverviewResultsModel(scopes, categoryId, that); |
2081 | + m_resultsModels[index.row()] = resultsModel; |
2082 | + } |
2083 | + switch (role) { |
2084 | + case RoleCategoryId: |
2085 | + return categoryId; |
2086 | + case RoleName: |
2087 | + return index.row() == 0 ? "SearchA" : "SearchB"; |
2088 | + case RoleIcon: |
2089 | + return QVariant(); |
2090 | + case RoleRawRendererTemplate: |
2091 | + qFatal("Using un-implemented RoleRawRendererTemplate Categories role"); |
2092 | + return QVariant(); |
2093 | + case RoleRenderer: |
2094 | + { |
2095 | + QVariantMap map; |
2096 | + map["category-layout"] = "grid"; |
2097 | + map["card-size"] = "small"; |
2098 | + map["overlay"] = true; |
2099 | + return map; |
2100 | + } |
2101 | + case RoleComponents: |
2102 | + { |
2103 | + QVariantMap map, artMap; |
2104 | + artMap["aspect-ratio"] = "1"; |
2105 | + artMap["field"] = "art"; |
2106 | + map["art"] = artMap; |
2107 | + map["title"] = "HOLA"; |
2108 | + return map; |
2109 | + } |
2110 | + case RoleResults: |
2111 | + return QVariant::fromValue(resultsModel); |
2112 | + case RoleCount: |
2113 | + return resultsModel->rowCount(); |
2114 | + case RoleHeaderLink: |
2115 | + return QString(); |
2116 | + default: |
2117 | + qFatal("Using un-implemented Categories role"); |
2118 | + return QVariant(); |
2119 | + } |
2120 | +} |
2121 | + |
2122 | + |
2123 | +ScopesOverviewResultsModel::ScopesOverviewResultsModel(const QList<unity::shell::scopes::ScopeInterface *> &scopes, const QString &categoryId, QObject* parent) |
2124 | + : unity::shell::scopes::ResultsModelInterface(parent) |
2125 | + , m_scopes(scopes) |
2126 | + , m_categoryId(categoryId) |
2127 | +{ |
2128 | +} |
2129 | + |
2130 | +QString ScopesOverviewResultsModel::categoryId() const |
2131 | +{ |
2132 | + return m_categoryId; |
2133 | +} |
2134 | + |
2135 | +void ScopesOverviewResultsModel::setCategoryId(QString const& /*id*/) |
2136 | +{ |
2137 | + qFatal("Calling un-implemented ScopesOverviewResultsModel::setCategoryId"); |
2138 | +} |
2139 | + |
2140 | +int ScopesOverviewResultsModel::scopeIndex(QString const& id) const |
2141 | +{ |
2142 | + const int scopeCount = count(); |
2143 | + for (int i = 0; i < scopeCount; ++i) { |
2144 | + if (m_scopes[i]->id() == id) |
2145 | + return i; |
2146 | + } |
2147 | + return -1; |
2148 | +} |
2149 | + |
2150 | +QHash<int, QByteArray> ScopesOverviewResultsModel::roleNames() const |
2151 | +{ |
2152 | + QHash<int, QByteArray> roles = unity::shell::scopes::ResultsModelInterface::roleNames(); |
2153 | + roles[RoleBackground + 1] = "scopeId"; |
2154 | + return roles; |
2155 | +} |
2156 | + |
2157 | +int ScopesOverviewResultsModel::rowCount(const QModelIndex& parent) const |
2158 | +{ |
2159 | + Q_UNUSED(parent); |
2160 | + |
2161 | + return m_scopes.count(); |
2162 | +} |
2163 | + |
2164 | +int ScopesOverviewResultsModel::count() const |
2165 | +{ |
2166 | + return rowCount(); |
2167 | +} |
2168 | + |
2169 | +QVariant |
2170 | +ScopesOverviewResultsModel::data(const QModelIndex& index, int role) const |
2171 | +{ |
2172 | + unity::shell::scopes::ScopeInterface *scope = m_scopes[index.row()]; |
2173 | + switch (role) { |
2174 | + case RoleUri: |
2175 | + case RoleCategoryId: |
2176 | + case RoleDndUri: |
2177 | + return QString(); |
2178 | + case RoleResult: |
2179 | + return scope ? scope->id() : QString("Result.%1.%2").arg(categoryId()).arg(index.row()); |
2180 | + case RoleTitle: |
2181 | + return scope ? scope->name() : QString("Title.%1.%2").arg(categoryId()).arg(index.row()); |
2182 | + case RoleArt: |
2183 | + return qmlDirectory() + "graphics/applicationIcons/dash.png"; |
2184 | + case RoleMascot: |
2185 | + case RoleEmblem: |
2186 | + case RoleSummary: |
2187 | + case RoleBackground + 1: // scopeId |
2188 | + return scope ? scope->id() : nullptr; |
2189 | + break; |
2190 | + default: |
2191 | + return QVariant(); |
2192 | + } |
2193 | +} |
2194 | |
2195 | === added file 'tests/mocks/Unity/fake_scopesoverview.h' |
2196 | --- tests/mocks/Unity/fake_scopesoverview.h 1970-01-01 00:00:00 +0000 |
2197 | +++ tests/mocks/Unity/fake_scopesoverview.h 2014-07-29 11:05:57 +0000 |
2198 | @@ -0,0 +1,104 @@ |
2199 | +/* |
2200 | + * Copyright (C) 2014 Canonical, Ltd. |
2201 | + * |
2202 | + * This program is free software; you can redistribute it and/or modify |
2203 | + * it under the terms of the GNU General Public License as published by |
2204 | + * the Free Software Foundation; version 3. |
2205 | + * |
2206 | + * This program is distributed in the hope that it will be useful, |
2207 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2208 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2209 | + * GNU General Public License for more details. |
2210 | + * |
2211 | + * You should have received a copy of the GNU General Public License |
2212 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2213 | + */ |
2214 | + |
2215 | +#ifndef FAKE_SCOPESOVERVIEW_H |
2216 | +#define FAKE_SCOPESOVERVIEW_H |
2217 | + |
2218 | +#include "fake_scope.h" |
2219 | +#include <unity/shell/scopes/ResultsModelInterface.h> |
2220 | + |
2221 | +class Scopes; |
2222 | + |
2223 | +class ScopesOverview : public Scope |
2224 | +{ |
2225 | + Q_OBJECT |
2226 | + |
2227 | +public: |
2228 | + ScopesOverview(Scopes* parent = 0); |
2229 | + |
2230 | + void setSearchQuery(const QString& search_query) override; |
2231 | + Q_INVOKABLE void activate(QVariant const& result) override; |
2232 | + |
2233 | +private: |
2234 | + unity::shell::scopes::CategoriesInterface *m_scopesOverviewCategories; |
2235 | + unity::shell::scopes::CategoriesInterface *m_searchCategories; |
2236 | +}; |
2237 | + |
2238 | +class ScopesOverviewCategories : public unity::shell::scopes::CategoriesInterface |
2239 | +{ |
2240 | + Q_OBJECT |
2241 | + |
2242 | +public: |
2243 | + ScopesOverviewCategories(Scopes *scopes, QObject* parent = 0); |
2244 | + |
2245 | + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; |
2246 | + int rowCount(const QModelIndex& parent = QModelIndex()) const override; |
2247 | + |
2248 | + Q_INVOKABLE void addSpecialCategory(QString const& categoryId, QString const& name, QString const& icon, QString const& rawTemplate, QObject* countObject) override; |
2249 | + Q_INVOKABLE bool overrideCategoryJson(QString const& categoryId, QString const& json) override; |
2250 | + |
2251 | +private: |
2252 | + mutable QHash<int, unity::shell::scopes::ResultsModelInterface*> m_resultsModels; |
2253 | + |
2254 | + Scopes *m_scopes; |
2255 | +}; |
2256 | + |
2257 | +class ScopesOverviewSearchCategories : public unity::shell::scopes::CategoriesInterface |
2258 | +{ |
2259 | + Q_OBJECT |
2260 | + |
2261 | +public: |
2262 | + ScopesOverviewSearchCategories(Scopes *scopes, QObject* parent = 0); |
2263 | + |
2264 | + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; |
2265 | + int rowCount(const QModelIndex& parent = QModelIndex()) const override; |
2266 | + |
2267 | + Q_INVOKABLE void addSpecialCategory(QString const& categoryId, QString const& name, QString const& icon, QString const& rawTemplate, QObject* countObject) override; |
2268 | + Q_INVOKABLE bool overrideCategoryJson(QString const& categoryId, QString const& json) override; |
2269 | + |
2270 | +private: |
2271 | + mutable QHash<int, unity::shell::scopes::ResultsModelInterface*> m_resultsModels; |
2272 | + |
2273 | + Scopes *m_scopes; |
2274 | +}; |
2275 | + |
2276 | +class ScopesOverviewResultsModel : public unity::shell::scopes::ResultsModelInterface |
2277 | +{ |
2278 | + Q_OBJECT |
2279 | + |
2280 | +public: |
2281 | + explicit ScopesOverviewResultsModel(const QList<unity::shell::scopes::ScopeInterface *> &scopes, const QString &categoryId, QObject* parent = 0); |
2282 | + |
2283 | + int rowCount(const QModelIndex& parent = QModelIndex()) const override; |
2284 | + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; |
2285 | + |
2286 | + /* getters */ |
2287 | + QString categoryId() const override; |
2288 | + int count() const override; |
2289 | + |
2290 | + /* setters */ |
2291 | + void setCategoryId(QString const& id) override; |
2292 | + |
2293 | + /* Special API */ |
2294 | + Q_INVOKABLE int scopeIndex(QString const& id) const; |
2295 | + QHash<int, QByteArray> roleNames() const override; |
2296 | + |
2297 | +private: |
2298 | + QList<unity::shell::scopes::ScopeInterface *> m_scopes; |
2299 | + QString m_categoryId; |
2300 | +}; |
2301 | + |
2302 | +#endif // FAKE_SCOPESOVERVIEW_H |
2303 | |
2304 | === modified file 'tests/plugins/Dash/cardcreator/5.res' |
2305 | --- tests/plugins/Dash/cardcreator/5.res 2014-07-08 12:37:34 +0000 |
2306 | +++ tests/plugins/Dash/cardcreator/5.res 2014-07-29 11:05:57 +0000 |
2307 | @@ -109,6 +109,7 @@ |
2308 | anchors { left: parent.left; |
2309 | leftMargin: units.gu(1); |
2310 | right: parent.right; |
2311 | + rightMargin: units.gu(1); |
2312 | top: overlayLoader.top; |
2313 | topMargin: units.gu(1); |
2314 | } |
2315 | |
2316 | === modified file 'tests/qmltests/Components/tst_PageHeader.qml' |
2317 | --- tests/qmltests/Components/tst_PageHeader.qml 2014-07-08 08:30:46 +0000 |
2318 | +++ tests/qmltests/Components/tst_PageHeader.qml 2014-07-29 11:05:57 +0000 |
2319 | @@ -36,6 +36,16 @@ |
2320 | |
2321 | function init() { |
2322 | searchEnabled = true; |
2323 | + |
2324 | + // Reset to initial state |
2325 | + pageHeader.searchQuery = ""; |
2326 | + pageHeader.closePopup(); |
2327 | + pageHeader.searchHistory.clear(); |
2328 | + |
2329 | + // Check initial state |
2330 | + var headerContainer = findChild(pageHeader, "headerContainer"); |
2331 | + tryCompareFunction(function() { return headerContainer.popover === null; }, true); |
2332 | + compare(pageHeader.searchHistory.count, 0); |
2333 | } |
2334 | |
2335 | function test_search_disabled() { |
2336 | @@ -80,9 +90,6 @@ |
2337 | } |
2338 | |
2339 | function test_history() { |
2340 | - pageHeader.searchHistory.clear() |
2341 | - compare(pageHeader.searchHistory.count, 0) |
2342 | - |
2343 | pageHeader.triggerSearch() |
2344 | typeString("humppa1") |
2345 | pageHeader.resetSearch() |
2346 | @@ -166,16 +173,26 @@ |
2347 | tryCompareFunction(function() { return headerContainer.popover !== null; }, true); |
2348 | |
2349 | tryCompare(headerContainer.popover, "visible", true); |
2350 | + |
2351 | + var searchTextField = findChild(pageHeader, "searchTextField"); |
2352 | + compare(searchTextField.focus, true); |
2353 | + |
2354 | + var recentSearches = findChild(headerContainer.popover, "recentSearches"); |
2355 | + mouseClick(recentSearches.itemAt(0), 0, 0); |
2356 | + |
2357 | + compare(pageHeader.searchQuery, "Search2"); |
2358 | + tryCompareFunction(function() { return headerContainer.popover === null; }, true); |
2359 | + compare(searchTextField.focus, false); |
2360 | } |
2361 | |
2362 | - function test_tap_outside_closes_popup_data() { |
2363 | + function test_popup_closing_data() { |
2364 | return [ |
2365 | { tag: "with search text", searchText: "foobar", hideSearch: false }, |
2366 | { tag: "without search text", searchText: "", hideSearch: true } |
2367 | ]; |
2368 | } |
2369 | |
2370 | - function test_tap_outside_closes_popup(data) { |
2371 | + function test_popup_closing(data) { |
2372 | searchEnabled = true; |
2373 | pageHeader.searchHistory.clear(); |
2374 | |
2375 | @@ -191,13 +208,26 @@ |
2376 | |
2377 | pageHeader.searchQuery = data.searchText; |
2378 | |
2379 | - mouseClick(root, root.width / 2, root.height - 1); |
2380 | + if (data.searchText == "") { |
2381 | + // When the text is empty the user can also close the |
2382 | + // popup by clicking outside the header instead of by starting a search |
2383 | + mouseClick(root, root.width / 2, root.height - 1); |
2384 | + } |
2385 | |
2386 | tryCompare(headerContainer, "showSearch", !data.hideSearch); |
2387 | tryCompareFunction(function() { return headerContainer.popover === null; }, true); |
2388 | |
2389 | pageHeader.resetSearch(); |
2390 | } |
2391 | + |
2392 | + function test_search_change_shows_search() { |
2393 | + var headerContainer = findChild(pageHeader, "headerContainer"); |
2394 | + compare(headerContainer.showSearch, false); |
2395 | + compare(searchQuery, ""); |
2396 | + |
2397 | + searchQuery = "H"; |
2398 | + compare(headerContainer.showSearch, true); |
2399 | + } |
2400 | } |
2401 | |
2402 | Column { |
2403 | |
2404 | === modified file 'tests/qmltests/Dash/tst_Dash.qml' |
2405 | --- tests/qmltests/Dash/tst_Dash.qml 2014-07-11 11:45:45 +0000 |
2406 | +++ tests/qmltests/Dash/tst_Dash.qml 2014-07-29 11:05:57 +0000 |
2407 | @@ -20,8 +20,6 @@ |
2408 | import Ubuntu.Components 0.1 |
2409 | import Unity.Test 0.1 as UT |
2410 | |
2411 | -// TODO We don't have any tests for the overlay scope functionality. |
2412 | - |
2413 | Item { |
2414 | id: shell |
2415 | width: units.gu(40) |
2416 | @@ -86,10 +84,220 @@ |
2417 | tryCompare(dashContentList, "count", 0); |
2418 | scopes.load(); |
2419 | tryCompare(scopes, "loaded", true); |
2420 | - tryCompare(dashContentList, "count", 4); |
2421 | + tryCompare(dashContentList, "count", 6); |
2422 | |
2423 | verify(dashContentList != undefined); |
2424 | tryCompare(dashContentList, "currentIndex", data.visualIndex); |
2425 | } |
2426 | + |
2427 | + function test_dash_overview_show_select_same_favorite() { |
2428 | + // Wait for stuff to be loaded |
2429 | + tryCompare(scopes, "loaded", true); |
2430 | + var dashContentList = findChild(dash, "dashContentList"); |
2431 | + tryCompare(dashContentList, "count", 6); |
2432 | + var mockScope1Loader = findChild(dash, "MockScope1 loader"); |
2433 | + tryCompareFunction(function() { return mockScope1Loader.item != null; }, true); |
2434 | + |
2435 | + // Show the overview |
2436 | + touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, dash.height - units.gu(18)); |
2437 | + var overviewController = findInvisibleChild(dash, "overviewController"); |
2438 | + tryCompare(overviewController, "progress", 1); |
2439 | + |
2440 | + // Make sure tab is where it should |
2441 | + var scopesOverview = findChild(dash, "scopesOverview"); |
2442 | + compare(scopesOverview.currentTab, 0); |
2443 | + |
2444 | + // Make sure stuff is loaded |
2445 | + var scopesOverviewFavoritesRepeater = findChild(dash, "scopesOverviewFavoritesRepeater"); |
2446 | + tryCompare(scopesOverviewFavoritesRepeater, "count", 6); |
2447 | + tryCompareFunction(function() { return scopesOverviewFavoritesRepeater.itemAt(0).item != null; }, true); |
2448 | + waitForRendering(scopesOverviewFavoritesRepeater.itemAt(0).item); |
2449 | + |
2450 | + // Click in first item |
2451 | + mouseClick(scopesOverviewFavoritesRepeater.itemAt(0).item, 0, 0); |
2452 | + |
2453 | + // Make sure animation went back |
2454 | + tryCompare(overviewController, "progress", 0); |
2455 | + compare(dashContentList.currentIndex, 0); |
2456 | + } |
2457 | + |
2458 | + function test_dash_overview_show_select_different_favorite() { |
2459 | + // Wait for stuff to be loaded |
2460 | + tryCompare(scopes, "loaded", true); |
2461 | + var dashContentList = findChild(dash, "dashContentList"); |
2462 | + tryCompare(dashContentList, "count", 6); |
2463 | + var mockScope1Loader = findChild(dash, "MockScope1 loader"); |
2464 | + tryCompareFunction(function() { return mockScope1Loader.item != null; }, true); |
2465 | + |
2466 | + // Show the overview |
2467 | + touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, dash.height - units.gu(18)); |
2468 | + var overviewController = findInvisibleChild(dash, "overviewController"); |
2469 | + tryCompare(overviewController, "progress", 1); |
2470 | + |
2471 | + // Make sure tab is where it should |
2472 | + var scopesOverview = findChild(dash, "scopesOverview"); |
2473 | + compare(scopesOverview.currentTab, 0); |
2474 | + |
2475 | + // Make sure stuff is loaded |
2476 | + var scopesOverviewFavoritesRepeater = findChild(dash, "scopesOverviewFavoritesRepeater"); |
2477 | + tryCompare(scopesOverviewFavoritesRepeater, "count", 6); |
2478 | + tryCompareFunction(function() { return scopesOverviewFavoritesRepeater.itemAt(0).item != null; }, true); |
2479 | + waitForRendering(scopesOverviewFavoritesRepeater.itemAt(1).item); |
2480 | + |
2481 | + // Click in first item |
2482 | + mouseClick(scopesOverviewFavoritesRepeater.itemAt(1).item, 0, 0); |
2483 | + |
2484 | + // Make sure animation went back |
2485 | + tryCompare(overviewController, "progress", 0); |
2486 | + compare(dashContentList.currentIndex, 1); |
2487 | + } |
2488 | + |
2489 | + function test_dash_overview_all_temp_scope_done_from_all() { |
2490 | + // Wait for stuff to be loaded |
2491 | + tryCompare(scopes, "loaded", true); |
2492 | + var dashContentList = findChild(dash, "dashContentList"); |
2493 | + tryCompare(dashContentList, "count", 6); |
2494 | + var mockScope1Loader = findChild(dash, "MockScope1 loader"); |
2495 | + tryCompareFunction(function() { return mockScope1Loader.item != null; }, true); |
2496 | + |
2497 | + // Show the overview |
2498 | + touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, dash.height - units.gu(18)); |
2499 | + var overviewController = findInvisibleChild(dash, "overviewController"); |
2500 | + tryCompare(overviewController, "progress", 1); |
2501 | + |
2502 | + // Make sure tab is where it should |
2503 | + var scopesOverview = findChild(dash, "scopesOverview"); |
2504 | + compare(scopesOverview.currentTab, 0); |
2505 | + |
2506 | + // Make sure stuff is loaded |
2507 | + var scopesOverviewFavoritesRepeater = findChild(dash, "scopesOverviewFavoritesRepeater"); |
2508 | + tryCompare(scopesOverviewFavoritesRepeater, "count", 6); |
2509 | + tryCompareFunction(function() { return scopesOverviewFavoritesRepeater.itemAt(0).item != null; }, true); |
2510 | + waitForRendering(scopesOverviewFavoritesRepeater.itemAt(1).item); |
2511 | + |
2512 | + // Click on the all tab |
2513 | + var scopesOverviewAllTabButton = findChild(dash, "scopesOverviewAllTabButton"); |
2514 | + mouseClick(scopesOverviewAllTabButton, 0, 0); |
2515 | + |
2516 | + // Wait for all tab to be enabled (animation finish) |
2517 | + var scopesOverviewAllView = findChild(dash, "scopesOverviewRepeaterChild1"); |
2518 | + tryCompare(scopesOverviewAllView, "enabled", true); |
2519 | + |
2520 | + // Click on a temp scope |
2521 | + var tempScopeCard = findChild(scopesOverviewAllView, "delegate1"); |
2522 | + mouseClick(tempScopeCard, 0, 0); |
2523 | + |
2524 | + // Check the bottom edge (overview) is disabled from temp scope |
2525 | + var overviewDragHandle = findChild(dash, "overviewDragHandle"); |
2526 | + compare(overviewDragHandle.enabled, false); |
2527 | + |
2528 | + // Check temp scope is there |
2529 | + var scopesOverviewTempScopeItem = findChild(dash, "scopesOverviewTempScopeItem"); |
2530 | + tryCompareFunction( function() { return scopesOverviewTempScopeItem.scope != null; }, true); |
2531 | + tryCompare(scopesOverviewTempScopeItem, "enabled", true); |
2532 | + |
2533 | + // Go back |
2534 | + var scopesOverviewTempScopeItemHeader = findChild(scopesOverviewTempScopeItem, "scopePageHeader"); |
2535 | + var backButton = findChild(findChild(scopesOverviewTempScopeItemHeader, "innerPageHeader"), "backButton"); |
2536 | + mouseClick(backButton, 0, 0); |
2537 | + |
2538 | + // Check temp scope is gone |
2539 | + var scopesOverviewTempScopeItem = findChild(dash, "scopesOverviewTempScopeItem"); |
2540 | + tryCompareFunction( function() { return scopesOverviewTempScopeItem.scope == null; }, true); |
2541 | + tryCompare(scopesOverviewTempScopeItem, "enabled", false); |
2542 | + |
2543 | + // Press on done |
2544 | + var scopesOverviewDoneButton = findChild(scopesOverview, "scopesOverviewDoneButton"); |
2545 | + mouseClick(scopesOverviewDoneButton, 0, 0); |
2546 | + |
2547 | + // Check the dash overview is gone |
2548 | + tryCompare(overviewController, "progress", 0); |
2549 | + |
2550 | + // Original list is still on 0 |
2551 | + compare(dashContentList.currentIndex, 0); |
2552 | + } |
2553 | + |
2554 | + function test_temp_scope_dash_overview_all_search_temp_scope_favorite_from_all() { |
2555 | + // Wait for stuff to be loaded |
2556 | + tryCompare(scopes, "loaded", true); |
2557 | + var dashContentList = findChild(dash, "dashContentList"); |
2558 | + tryCompare(dashContentList, "count", 6); |
2559 | + var mockScope1Loader = findChild(dash, "MockScope1 loader"); |
2560 | + tryCompareFunction(function() { return mockScope1Loader.item != null; }, true); |
2561 | + |
2562 | + // Swipe right to Apps scope |
2563 | + touchFlick(dash, dash.width - 1, units.gu(1), dash.width - units.gu(10), units.gu(1)); |
2564 | + tryCompare(dashContentList, "contentX", dashContentList.width); |
2565 | + tryCompare(dashContentList, "currentIndex", 1); |
2566 | + |
2567 | + // Click on card that opens temp scope |
2568 | + var dashCategory2 = findChild(dashContentList.currentItem, "dashCategory2"); |
2569 | + var card2 = findChild(dashCategory2, "delegate2"); |
2570 | + waitForRendering(card2); |
2571 | + mouseClick(card2, card2.width / 2, card2.height / 2); |
2572 | + |
2573 | + // Wait for temp scope to be there |
2574 | + var dashTempScopeItem = findChild(dash, "dashTempScopeItem"); |
2575 | + tryCompare(dashTempScopeItem, "x", 0); |
2576 | + |
2577 | + // Show the overview |
2578 | + touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, dash.height - units.gu(18)); |
2579 | + var overviewController = findInvisibleChild(dash, "overviewController"); |
2580 | + tryCompare(overviewController, "progress", 1); |
2581 | + |
2582 | + // Make sure tab is where it should |
2583 | + var scopesOverview = findChild(dash, "scopesOverview"); |
2584 | + compare(scopesOverview.currentTab, 1); |
2585 | + |
2586 | + // Do a search |
2587 | + var scopesOverviewPageHeader = findChild(scopesOverview, "scopesOverviewPageHeader"); |
2588 | + var searchButton = findChild(scopesOverviewPageHeader, "search_header_button"); |
2589 | + mouseClick(searchButton, 0, 0); |
2590 | + |
2591 | + // Type something |
2592 | + keyClick(Qt.Key_H); |
2593 | + |
2594 | + // Check results grid is there and the other lists are not |
2595 | + var searchResultsViewer = findChild(scopesOverview, "searchResultsViewer"); |
2596 | + var scopesOverviewRepeater = findChild(dash, "scopesOverviewRepeater"); |
2597 | + tryCompare(searchResultsViewer, "opacity", 1); |
2598 | + tryCompare(scopesOverviewRepeater, "count", 0); |
2599 | + |
2600 | + // Click on a temp scope in the search |
2601 | + var dashCategorysearchA = findChild(searchResultsViewer, "dashCategorysearchA"); |
2602 | + var cardTempScope = findChild(dashCategorysearchA, "delegate2"); |
2603 | + waitForRendering(cardTempScope); |
2604 | + mouseClick(cardTempScope, cardTempScope.width / 2, cardTempScope.height / 2); |
2605 | + |
2606 | + // Check the bottom edge (overview) is disabled from temp scope |
2607 | + var overviewDragHandle = findChild(dash, "overviewDragHandle"); |
2608 | + compare(overviewDragHandle.enabled, false); |
2609 | + |
2610 | + // Check temp scope is there |
2611 | + var scopesOverviewTempScopeItem = findChild(dash, "scopesOverviewTempScopeItem"); |
2612 | + tryCompareFunction( function() { return scopesOverviewTempScopeItem.scope != null; }, true); |
2613 | + tryCompare(scopesOverviewTempScopeItem, "enabled", true); |
2614 | + |
2615 | + // Go back |
2616 | + var scopesOverviewTempScopeItemHeader = findChild(scopesOverviewTempScopeItem, "scopePageHeader"); |
2617 | + var backButton = findChild(findChild(scopesOverviewTempScopeItemHeader, "innerPageHeader"), "backButton"); |
2618 | + mouseClick(backButton, 0, 0); |
2619 | + |
2620 | + // Check temp scope is gone |
2621 | + var scopesOverviewTempScopeItem = findChild(dash, "scopesOverviewTempScopeItem"); |
2622 | + tryCompareFunction( function() { return scopesOverviewTempScopeItem.scope == null; }, true); |
2623 | + tryCompare(scopesOverviewTempScopeItem, "enabled", false); |
2624 | + |
2625 | + // Press on a favorite |
2626 | + var dashCategorysearchB = findChild(searchResultsViewer, "dashCategorysearchB"); |
2627 | + var cardFavSearch = findChild(dashCategorysearchB, "delegate3"); |
2628 | + mouseClick(cardFavSearch, 0, 0); |
2629 | + |
2630 | + // Check the dash overview is gone |
2631 | + tryCompare(overviewController, "progress", 0); |
2632 | + |
2633 | + // Original list went to the favorite |
2634 | + compare(dashContentList.currentIndex, 0); |
2635 | + } |
2636 | } |
2637 | } |
2638 | |
2639 | === modified file 'tests/qmltests/Dash/tst_DashContent.qml' |
2640 | --- tests/qmltests/Dash/tst_DashContent.qml 2014-07-21 13:28:35 +0000 |
2641 | +++ tests/qmltests/Dash/tst_DashContent.qml 2014-07-29 11:05:57 +0000 |
2642 | @@ -73,7 +73,7 @@ |
2643 | function loadScopes() { |
2644 | scopeLoadedSpy.clear(); |
2645 | scopesModel.load(); |
2646 | - tryCompare(scopeLoadedSpy, "count", 4); |
2647 | + tryCompare(scopeLoadedSpy, "count", 10); |
2648 | } |
2649 | |
2650 | function init() { |
2651 | @@ -117,7 +117,8 @@ |
2652 | |
2653 | loadScopes(); |
2654 | |
2655 | - verify(dashContentList.currentIndex >= 0 && dashContentList.currentIndex < 5); |
2656 | + compare(dashContentList.count, 10); |
2657 | + verify(dashContentList.currentIndex >= 0 && dashContentList.currentIndex < dashContentList.count); |
2658 | } |
2659 | |
2660 | function test_show_header_on_list_movement() { |
2661 | @@ -173,7 +174,7 @@ |
2662 | |
2663 | // test greater than scope count. |
2664 | var currentScopeIndex = dashContent.currentIndex; |
2665 | - dashContent.setCurrentScopeAtIndex(8, true, false); |
2666 | + dashContent.setCurrentScopeAtIndex(18, true, false); |
2667 | compare(dashContent.currentIndex, currentScopeIndex, "Scope should not change if changing to greater index than count"); |
2668 | } |
2669 |
FAILED: Continuous integration, rev:1111 jenkins. qa.ubuntu. com/job/ unity8- ci/3501/ jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- utopic- touch/2241/ console jenkins. qa.ubuntu. com/job/ unity-phablet- qmluitests- utopic/ 503/console jenkins. qa.ubuntu. com/job/ unity8- utopic- amd64-ci/ 595/console jenkins. qa.ubuntu. com/job/ unity8- utopic- armhf-ci/ 595/console jenkins. qa.ubuntu. com/job/ unity8- utopic- i386-ci/ 595/console jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- armhf/3425/ 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/3501/ rebuild
http://