Merge lp:~aacid/unity8/departments into lp:unity8
- departments
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Michał Sawicz |
Approved revision: | 953 |
Merged at revision: | 974 |
Proposed branch: | lp:~aacid/unity8/departments |
Merge into: | lp:unity8 |
Diff against target: |
1099 lines (+813/-17) 16 files modified
debian/control (+1/-1) plugins/Dash/listviewwithpageheader.cpp (+25/-5) plugins/Dash/listviewwithpageheader.h (+3/-0) qml/Components/PageHeader.qml (+16/-4) qml/Dash/DashContent.qml (+9/-1) qml/Dash/DashDepartments.qml (+202/-0) qml/Dash/DashDepartmentsList.qml (+195/-0) qml/Dash/ScopeItem.qml (+12/-0) tests/mocks/Unity/CMakeLists.txt (+2/-0) tests/mocks/Unity/fake_department.cpp (+127/-0) tests/mocks/Unity/fake_department.h (+61/-0) tests/mocks/Unity/fake_scope.cpp (+36/-1) tests/mocks/Unity/fake_scope.h (+6/-0) tests/mocks/Unity/fake_scopes.cpp (+2/-2) tests/mocks/Unity/fake_unity_plugin.cpp (+2/-0) tests/qmltests/Dash/tst_DashContent.qml (+114/-3) |
To merge this branch: | bzr merge lp:~aacid/unity8/departments |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Needs Fixing | |
Michał Sawicz | Approve | ||
Albert Astals Cid (community) | Abstain | ||
Mike Nagle | Pending | ||
Review via email:
|
Commit message
Departments support
Description of the change
* Are there any related MPs required for this MP to build/function as expected?
https:/
and
https:/
* Did you perform an exploratory manual test run of your code change and any related functionality?
Yes
* Did you make sure that your branch does not contain spurious tags?
Yes
* If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
N/A
* If you changed the UI, has there been a design review?
N/A
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:928
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 929. By Albert Astals Cid
-
Tablet mode
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Albert Astals Cid (aacid) wrote : | # |
Added the tablet mode
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:929
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michał Sawicz (saviq) wrote : | # |
Conflict?
Also, you need to bump dep on unity-api.
- 930. By Albert Astals Cid
-
Merge
- 931. By Albert Astals Cid
-
need new api
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:930
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Albert Astals Cid (aacid) wrote : | # |
> Conflict?
> Also, you need to bump dep on unity-api.
Done.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:931
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 932. By Albert Astals Cid
-
Merge
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:932
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 933. By Albert Astals Cid
-
hardcode colors in labels like we do everywhere
- 934. By Albert Astals Cid
-
We need the Dash departments in the temp scope too
This shows we need some refactoring of the code, it's not cool we need to add this into two places
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:934
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michał Sawicz (saviq) wrote : | # |
The dark overlay needs a fade in/out.
Switching between department pages feels too slow.
Chevrons look too big everywhere.
Broke it:
- open depts
- choose a subdep
- click on header to close while it's loading
→ invisible depts
We should probably have a better place for the activity indicator, 'cause it ends up stroked through with the dividers.
And we need to take this into the hands of designers, it doesn't feel great with the pages having different height as they move about.
- 935. By Albert Astals Cid
-
todo++
- 936. By Albert Astals Cid
-
rename afterLineChildItem, name wasn't great
- 937. By Albert Astals Cid
-
Animate opacity of the blackRect
- 938. By Albert Astals Cid
-
Move the movement between lists faster
- 939. By Albert Astals Cid
-
Fix the calculation of maxHeight
- 940. By Albert Astals Cid
-
better leaf detection
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Albert Astals Cid (aacid) wrote : | # |
******
Broke it:
- open depts
- choose a subdep
- click on header to close while it's loading
→ invisible depts
******
There was a logic mistake in my side, fixed.
- 941. By Albert Astals Cid
-
test for the last leaf fix
- 942. By Albert Astals Cid
-
Make the chevrons a bit smaller
- 943. By Albert Astals Cid
-
Make sure we animate the height of the list only when we need to
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:939
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:943
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 944. By Albert Astals Cid
-
Make this chevron smaller too
- 945. By Albert Astals Cid
-
Some spacing here
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michał Sawicz (saviq) wrote : | # |
See comments inline.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:944
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Albert Astals Cid (aacid) wrote : | # |
> Any reason why not anchors?
None, uses anchors now
> Anchors instead?
Ok
> ListView.
No, ListView.
> Column would save you those calculations.
Done
> Not needed?
It's better to set the contentWidth to something than 0, otherwise the flickable can decide that since your 0 in width doens't make any sense to flick vertically anyway. (This has happened in the past, not sure if still happens)
> Group anchors please.
Ok
> Shouldn't we use ThinDivider here?
Don't know, some places we use ThinDivider, some others the rectangle, i can use ThinDivider if you prefer. Also there's our ThinDivider
> Wonder if we could use ListItems from UITK here? It's a whole lotta code for something that we have in the UITK :|
Didn't see anything in the UITK that would save me much work from here. Maybe i did look wrong?
> Why do we need this? Wouldn't model: department just work? Do we need to wait for it to be loaded?
Yes, i don't want stuff to appear one by one in case the model loads very slowly
> This could probably be just one image?
Sure, done
- 946. By Albert Astals Cid
-
Use a Column
- 947. By Albert Astals Cid
-
Use anchors
- 948. By Albert Astals Cid
-
Use anchors
- 949. By Albert Astals Cid
-
Use x instead of multiplication
- 950. By Albert Astals Cid
-
Group anchors
- 951. By Albert Astals Cid
-
Use just one image
- 952. By Albert Astals Cid
-
TODO++
- 953. By Albert Astals Cid
-
Remove index == departmentListV
iew.currentInde x Since x == departmentListV
iew.contentX is more restrictive we don't need it
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michał Sawicz (saviq) wrote : | # |
* Did you perform an exploratory manual test run of the code change and any related functionality?
Yes.
* Did CI run pass? If not, please explain why.
Oh yes!
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:945
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:953
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file 'debian/control' |
2 | --- debian/control 2014-06-11 15:41:35 +0000 |
3 | +++ debian/control 2014-06-19 10:41:43 +0000 |
4 | @@ -17,7 +17,7 @@ |
5 | libpulse-dev, |
6 | libqmenumodel-dev (>= 0.2.7), |
7 | libqt5xmlpatterns5-dev, |
8 | - libunity-api-dev (>= 7.80.6), |
9 | + libunity-api-dev (>= 7.82), |
10 | libunity-mir-dev, |
11 | libusermetricsoutput1-dev, |
12 | libxcb1-dev, |
13 | |
14 | === modified file 'plugins/Dash/listviewwithpageheader.cpp' |
15 | --- plugins/Dash/listviewwithpageheader.cpp 2014-06-05 08:38:51 +0000 |
16 | +++ plugins/Dash/listviewwithpageheader.cpp 2014-06-19 10:41:43 +0000 |
17 | @@ -258,6 +258,8 @@ |
18 | if (m_headerItem) { |
19 | m_headerItem->setParentItem(contentItem()); |
20 | m_headerItem->setZ(1); |
21 | + m_previousHeaderImplicitHeight = m_headerItem->implicitHeight(); |
22 | + QQuickItemPrivate::get(m_headerItem)->addItemChangeListener(this, QQuickItemPrivate::ImplicitHeight); |
23 | } |
24 | qreal newHeaderHeight = m_headerItem ? m_headerItem->height() : 0; |
25 | if (!m_visibleItems.isEmpty() && newHeaderHeight != oldHeaderHeight) { |
26 | @@ -496,7 +498,15 @@ |
27 | |
28 | QQuickFlickable::viewportMoved(orient); |
29 | // qDebug() << "ListViewWithPageHeader::viewportMoved" << contentY(); |
30 | - qreal diff = m_previousContentY - contentY(); |
31 | + const qreal diff = m_previousContentY - contentY(); |
32 | + adjustHeader(diff); |
33 | + m_previousContentY = contentY(); |
34 | + layout(); |
35 | + polish(); |
36 | +} |
37 | + |
38 | +void ListViewWithPageHeader::adjustHeader(qreal diff) |
39 | +{ |
40 | const bool showHeaderAnimationRunning = m_contentYAnimation->isRunning() && contentYAnimationType == ContentYAnimationShowHeader; |
41 | if (m_headerItem) { |
42 | const auto oldHeaderItemShownHeight = m_headerItemShownHeight; |
43 | @@ -558,10 +568,6 @@ |
44 | adjustMinYExtent(); |
45 | } |
46 | } |
47 | - |
48 | - m_previousContentY = contentY(); |
49 | - layout(); |
50 | - polish(); |
51 | } |
52 | |
53 | void ListViewWithPageHeader::createDelegateModel() |
54 | @@ -1071,6 +1077,20 @@ |
55 | } |
56 | } |
57 | |
58 | +void ListViewWithPageHeader::itemImplicitHeightChanged(QQuickItem *item) |
59 | +{ |
60 | + if (item == m_headerItem) { |
61 | + const qreal diff = m_headerItem->implicitHeight() - m_previousHeaderImplicitHeight; |
62 | + if (diff != 0) { |
63 | + adjustHeader(diff); |
64 | + m_previousHeaderImplicitHeight = m_headerItem->implicitHeight(); |
65 | + layout(); |
66 | + polish(); |
67 | + m_contentHeightDirty = true; |
68 | + } |
69 | + } |
70 | +} |
71 | + |
72 | void ListViewWithPageHeader::headerHeightChanged(qreal newHeaderHeight, qreal oldHeaderHeight, qreal oldHeaderY) |
73 | { |
74 | const qreal heightDiff = newHeaderHeight - oldHeaderHeight; |
75 | |
76 | === modified file 'plugins/Dash/listviewwithpageheader.h' |
77 | --- plugins/Dash/listviewwithpageheader.h 2014-06-06 11:38:19 +0000 |
78 | +++ plugins/Dash/listviewwithpageheader.h 2014-06-19 10:41:43 +0000 |
79 | @@ -106,6 +106,7 @@ |
80 | void viewportMoved(Qt::Orientations orient) override; |
81 | qreal minYExtent() const override; |
82 | void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) override; |
83 | + void itemImplicitHeightChanged(QQuickItem *item) override; |
84 | void updatePolish() override; |
85 | |
86 | private Q_SLOTS: |
87 | @@ -146,6 +147,7 @@ |
88 | bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo); |
89 | ListItem *createItem(int modelIndex, bool asynchronous); |
90 | |
91 | + void adjustHeader(qreal diff); |
92 | void adjustMinYExtent(); |
93 | void updateClipItem(); |
94 | void headerHeightChanged(qreal newHeaderHeight, qreal oldHeaderHeight, qreal oldHeaderY); |
95 | @@ -178,6 +180,7 @@ |
96 | |
97 | QQuickItem *m_headerItem; |
98 | qreal m_previousContentY; |
99 | + qreal m_previousHeaderImplicitHeight; |
100 | qreal m_headerItemShownHeight; // The height of header shown when the header is shown outside its topmost position |
101 | // i.e. it's being shown after dragging down in the middle of the list |
102 | enum ContentYAnimationType { ContentYAnimationShowHeader, ContentYAnimationMaximizeVisibleArea }; |
103 | |
104 | === modified file 'qml/Components/PageHeader.qml' |
105 | --- qml/Components/PageHeader.qml 2014-06-11 15:36:51 +0000 |
106 | +++ qml/Components/PageHeader.qml 2014-06-19 10:41:43 +0000 |
107 | @@ -27,12 +27,13 @@ |
108 | property ListModel searchHistory |
109 | property var scope: null |
110 | property alias childItem: itemContainer.children |
111 | + property alias bottomItem: bottomContainer.children |
112 | property alias showBackButton: backButton.visible |
113 | |
114 | signal backClicked |
115 | |
116 | - height: units.gu(8.5) |
117 | - implicitHeight: units.gu(8.5) |
118 | + height: header.height + units.gu(2) + bottomContainer.height |
119 | + implicitHeight: header.height + units.gu(2) + bottomContainer.height |
120 | |
121 | function triggerSearch() { |
122 | if (searchEntryEnabled) searchField.forceActiveFocus() |
123 | @@ -404,9 +405,20 @@ |
124 | top: header.bottom |
125 | left: parent.left |
126 | right: parent.right |
127 | + bottom: bottomContainer.top |
128 | + } |
129 | + |
130 | + source: "graphics/PageHeaderBaseDivider.sci" |
131 | + } |
132 | + |
133 | + Item { |
134 | + id: bottomContainer |
135 | + |
136 | + anchors { |
137 | + left: parent.left |
138 | + right: parent.right |
139 | bottom: parent.bottom |
140 | } |
141 | - |
142 | - source: "graphics/PageHeaderBaseDivider.sci" |
143 | + height: childrenRect.height |
144 | } |
145 | } |
146 | |
147 | === modified file 'qml/Dash/DashContent.qml' |
148 | --- qml/Dash/DashContent.qml 2014-05-19 11:10:58 +0000 |
149 | +++ qml/Dash/DashContent.qml 2014-06-19 10:41:43 +0000 |
150 | @@ -151,7 +151,7 @@ |
151 | item.previewListView = previewListView; |
152 | item.scope = Qt.binding(function() { return scope }) |
153 | item.isCurrent = Qt.binding(function() { return visible && ListView.isCurrentItem }) |
154 | - item.tabBarHeight = dashPageHeader.implicitHeight; |
155 | + item.tabBarHeight = Qt.binding(function() { return dashPageHeader.implicitHeight; }) |
156 | dashContent.scopeLoaded(item.scope.id) |
157 | } |
158 | Connections { |
159 | @@ -217,6 +217,14 @@ |
160 | onTriggered: tabBar.selectionMode = false |
161 | } |
162 | } |
163 | + |
164 | + bottomItem: DashDepartments { |
165 | + scope: dashContentList.currentItem ? dashContentList.currentItem.theScope : null |
166 | + width: parent.width <= units.gu(60) ? parent.width : units.gu(40) |
167 | + anchors.right: parent.right |
168 | + windowHeight: dashContent.height |
169 | + windowWidth: dashContent.width |
170 | + } |
171 | } |
172 | } |
173 | |
174 | |
175 | === added file 'qml/Dash/DashDepartments.qml' |
176 | --- qml/Dash/DashDepartments.qml 1970-01-01 00:00:00 +0000 |
177 | +++ qml/Dash/DashDepartments.qml 2014-06-19 10:41:43 +0000 |
178 | @@ -0,0 +1,202 @@ |
179 | +/* |
180 | + * Copyright (C) 2014 Canonical, Ltd. |
181 | + * |
182 | + * This program is free software; you can redistribute it and/or modify |
183 | + * it under the terms of the GNU General Public License as published by |
184 | + * the Free Software Foundation; version 3. |
185 | + * |
186 | + * This program is distributed in the hope that it will be useful, |
187 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
188 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
189 | + * GNU General Public License for more details. |
190 | + * |
191 | + * You should have received a copy of the GNU General Public License |
192 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
193 | + */ |
194 | + |
195 | +import QtQuick 2.2 |
196 | +import Ubuntu.Components 0.1 |
197 | + |
198 | +AbstractButton { |
199 | + id: root |
200 | + objectName: "dashDepartments" |
201 | + |
202 | + property var scope: null |
203 | + |
204 | + property bool showList: false |
205 | + |
206 | + readonly property var currentDepartment: scope && scope.hasDepartments ? scope.getDepartment(scope.currentDepartmentId) : null |
207 | + |
208 | + property alias windowWidth: blackRect.width |
209 | + property alias windowHeight: blackRect.height |
210 | + |
211 | + // Are we drilling down the tree or up? |
212 | + property bool isGoingBack: false |
213 | + |
214 | + visible: root.currentDepartment != null |
215 | + |
216 | + height: visible ? units.gu(5) : 0 |
217 | + |
218 | + onClicked: { |
219 | + root.showList = !root.showList; |
220 | + } |
221 | + |
222 | + Rectangle { |
223 | + id: blackRect |
224 | + color: "black" |
225 | + opacity: departmentListView.currentItem && departmentListView.currentItem.visible ? 0.3 : 0 |
226 | + Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } } |
227 | + anchors.top: departmentListView.top |
228 | + anchors.right: parent.right |
229 | + visible: opacity != 0 |
230 | + } |
231 | + |
232 | + Image { |
233 | + anchors { |
234 | + top: parent.top |
235 | + left: parent.left |
236 | + right: parent.right |
237 | + } |
238 | + fillMode: Image.Stretch |
239 | + source: "graphics/dash_divider_top_lightgrad.png" |
240 | + z: -1 |
241 | + } |
242 | + |
243 | + Image { |
244 | + anchors { |
245 | + bottom: parent.bottom |
246 | + left: parent.left |
247 | + right: parent.right |
248 | + } |
249 | + fillMode: Image.Stretch |
250 | + source: "graphics/dash_divider_top_darkgrad.png" |
251 | + z: -1 |
252 | + } |
253 | + |
254 | + Label { |
255 | + anchors.fill: parent |
256 | + anchors.margins: units.gu(2) |
257 | + verticalAlignment: Text.AlignVCenter |
258 | + text: root.currentDepartment ? root.currentDepartment.label : "" |
259 | + color: "gray" // TODO remove once we're a separate app |
260 | + } |
261 | + |
262 | + Image { |
263 | + anchors.verticalCenter: parent.verticalCenter |
264 | + anchors.right: parent.right |
265 | + anchors.rightMargin: units.gu(2) |
266 | + rotation: showList ? 180 : 0 |
267 | + source: "image://theme/dropdown-menu" |
268 | + sourceSize.height: parent.height - units.gu(2) |
269 | + sourceSize.width: units.gu(2) |
270 | + fillMode: Image.PreserveAspectFit |
271 | + } |
272 | + |
273 | + // departmentListView is outside root |
274 | + ListView { |
275 | + id: departmentListView |
276 | + objectName: "departmentListView" |
277 | + orientation: ListView.Horizontal |
278 | + interactive: false |
279 | + clip: root.width != windowWidth |
280 | + model: ListModel { |
281 | + id: departmentModel |
282 | + // We have two roles |
283 | + // departmentId: the department id of the department the list represents |
284 | + // nullifyDepartment: overrides departmentId to be null |
285 | + // This is used to "clear" the delegate when going "right" on the tree |
286 | + } |
287 | + anchors { |
288 | + left: parent.left |
289 | + right: parent.right |
290 | + top: root.bottom |
291 | + } |
292 | + readonly property int maxHeight: (windowHeight - mapToItem(null, root.x, root.y).y) - units.gu(8) |
293 | + property int prevHeight: maxHeight |
294 | + height: currentItem ? currentItem.height : maxHeight |
295 | + onHeightChanged: { |
296 | + if (root.showList) { |
297 | + prevHeight = currentItem.desiredHeight; |
298 | + } |
299 | + } |
300 | + highlightMoveDuration: UbuntuAnimation.FastDuration |
301 | + delegate: DashDepartmentsList { |
302 | + objectName: "department" + index |
303 | + visible: height != 0 |
304 | + width: departmentListView.width |
305 | + property real desiredHeight: { |
306 | + if (root.showList) { |
307 | + if (department && department.loaded && x == departmentListView.contentX) |
308 | + { |
309 | + return Math.min(implicitHeight, departmentListView.maxHeight); |
310 | + } else { |
311 | + return departmentListView.prevHeight; |
312 | + } |
313 | + } else { |
314 | + return 0; |
315 | + } |
316 | + } |
317 | + height: desiredHeight |
318 | + department: (nullifyDepartment || !scope) ? null : scope.getDepartment(departmentId) |
319 | + currentDepartment: root.currentDepartment |
320 | + onEnterDepartment: { |
321 | + scope.loadDepartment(newDepartmentId); |
322 | + // We only need to add a new item to the model |
323 | + // if we have children, otherwise just load it |
324 | + if (hasChildren) { |
325 | + isGoingBack = false; |
326 | + departmentModel.append({"departmentId": newDepartmentId, "nullifyDepartment": false}); |
327 | + departmentListView.currentIndex++; |
328 | + } else { |
329 | + showList = false; |
330 | + } |
331 | + } |
332 | + onGoBackToParentClicked: { |
333 | + scope.loadDepartment(department.parentDepartmentId); |
334 | + isGoingBack = true; |
335 | + departmentModel.setProperty(departmentListView.currentIndex - 1, "nullifyDepartment", false); |
336 | + departmentListView.currentIndex--; |
337 | + } |
338 | + onAllDepartmentClicked: { |
339 | + showList = false; |
340 | + if (root.currentDepartment.parentDepartmentId == department.departmentId) { |
341 | + // For leaves we have to go to the parent too |
342 | + scope.loadDepartment(root.currentDepartment.parentDepartmentId); |
343 | + } |
344 | + } |
345 | + } |
346 | + onContentXChanged: { |
347 | + if (contentX == width * departmentListView.currentIndex) { |
348 | + if (isGoingBack) { |
349 | + departmentModel.remove(departmentListView.currentIndex + 1); |
350 | + } else { |
351 | + departmentModel.setProperty(departmentListView.currentIndex - 1, "nullifyDepartment", true); |
352 | + } |
353 | + } |
354 | + } |
355 | + } |
356 | + |
357 | + InverseMouseArea { |
358 | + anchors.fill: departmentListView |
359 | + enabled: root.showList |
360 | + onClicked: root.showList = false |
361 | + } |
362 | + |
363 | + onScopeChanged: { |
364 | + departmentModel.clear(); |
365 | + if (scope && scope.hasDepartments) { |
366 | + departmentModel.append({"departmentId": scope.currentDepartmentId, "nullifyDepartment": false}); |
367 | + } |
368 | + } |
369 | + |
370 | + Connections { |
371 | + target: scope |
372 | + onHasDepartmentsChanged: { |
373 | + if (scope.hasDepartments) { |
374 | + departmentModel.append({"departmentId": scope.currentDepartmentId, "nullifyDepartment": false}); |
375 | + } else { |
376 | + departmentModel.clear(); |
377 | + } |
378 | + } |
379 | + } |
380 | +} |
381 | |
382 | === added file 'qml/Dash/DashDepartmentsList.qml' |
383 | --- qml/Dash/DashDepartmentsList.qml 1970-01-01 00:00:00 +0000 |
384 | +++ qml/Dash/DashDepartmentsList.qml 2014-06-19 10:41:43 +0000 |
385 | @@ -0,0 +1,195 @@ |
386 | +/* |
387 | + * Copyright (C) 2014 Canonical, Ltd. |
388 | + * |
389 | + * This program is free software; you can redistribute it and/or modify |
390 | + * it under the terms of the GNU General Public License as published by |
391 | + * the Free Software Foundation; version 3. |
392 | + * |
393 | + * This program is distributed in the hope that it will be useful, |
394 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
395 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
396 | + * GNU General Public License for more details. |
397 | + * |
398 | + * You should have received a copy of the GNU General Public License |
399 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
400 | + */ |
401 | + |
402 | +import QtQuick 2.2 |
403 | +import Ubuntu.Components 0.1 |
404 | + |
405 | +Item { |
406 | + id: root |
407 | + property var department: null |
408 | + property var currentDepartment: null |
409 | + signal enterDepartment(var newDepartmentId, bool hasChildren) |
410 | + signal goBackToParentClicked() |
411 | + signal allDepartmentClicked() |
412 | + |
413 | + readonly property int itemHeight: units.gu(5) |
414 | + implicitHeight: flickable.contentHeight |
415 | + |
416 | + Rectangle { |
417 | + color: "white" |
418 | + anchors.fill: parent |
419 | + } |
420 | + |
421 | + ActivityIndicator { |
422 | + id: loadingIndicator |
423 | + anchors.centerIn: parent |
424 | + running: !(department && department.loaded) |
425 | + } |
426 | + clip: true |
427 | + |
428 | + Behavior on height { |
429 | + UbuntuNumberAnimation { |
430 | + id: heightAnimation |
431 | + duration: UbuntuAnimation.SnapDuration |
432 | + } |
433 | + } |
434 | + |
435 | + Flickable { |
436 | + id: flickable |
437 | + |
438 | + anchors.fill: parent |
439 | + |
440 | + contentHeight: column.height |
441 | + contentWidth: width |
442 | + |
443 | + Column { |
444 | + id: column |
445 | + width: parent.width |
446 | + |
447 | + // TODO: check if SDK ListItems could be used here |
448 | + // and if not make them be useful since this is a quite common pattern |
449 | + |
450 | + AbstractButton { |
451 | + id: backButton |
452 | + objectName: "backButton" |
453 | + width: parent.width |
454 | + visible: department && !department.isRoot || false |
455 | + height: itemHeight |
456 | + |
457 | + onClicked: root.goBackToParentClicked(); |
458 | + |
459 | + Image { |
460 | + id: backImage |
461 | + anchors { |
462 | + verticalCenter: parent.verticalCenter |
463 | + left: parent.left |
464 | + leftMargin: units.gu(2) |
465 | + } |
466 | + source: "image://theme/back" |
467 | + sourceSize.height: parent.height - units.gu(3) |
468 | + sourceSize.width: units.gu(3) |
469 | + fillMode: Image.PreserveAspectFit |
470 | + } |
471 | + |
472 | + Label { |
473 | + anchors { |
474 | + verticalCenter: parent.verticalCenter |
475 | + left: backImage.right |
476 | + leftMargin: units.gu(0.5) |
477 | + } |
478 | + text: department ? department.parentLabel : "" |
479 | + color: "gray" // TODO remove once we're a separate app |
480 | + } |
481 | + |
482 | + Rectangle { |
483 | + anchors { |
484 | + bottom: parent.bottom |
485 | + left: parent.left |
486 | + right: parent.right |
487 | + leftMargin: units.gu(2) |
488 | + rightMargin: units.gu(2) |
489 | + } |
490 | + color: "gray" |
491 | + opacity: 0.2 |
492 | + height: units.dp(1) |
493 | + } |
494 | + } |
495 | + |
496 | + AbstractButton { |
497 | + id: allButton |
498 | + objectName: "allButton" |
499 | + width: parent.width |
500 | + visible: department && (!department.isRoot || (root.currentDepartment && !root.currentDepartment.isRoot && root.currentDepartment.parentDepartmentId == department.departmentId)) || false |
501 | + height: itemHeight |
502 | + |
503 | + Label { |
504 | + anchors { |
505 | + verticalCenter: parent.verticalCenter |
506 | + left: parent.left |
507 | + leftMargin: units.gu(2) |
508 | + } |
509 | + text: department ? (department.allLabel != "" ? department.allLabel : department.label) : "" |
510 | + font.bold: true |
511 | + color: "gray" // TODO remove once we're a separate app |
512 | + } |
513 | + |
514 | + Rectangle { |
515 | + anchors { |
516 | + bottom: parent.bottom |
517 | + left: parent.left |
518 | + right: parent.right |
519 | + leftMargin: units.gu(2) |
520 | + rightMargin: units.gu(2) |
521 | + } |
522 | + color: "gray" |
523 | + opacity: 0.2 |
524 | + height: units.dp(1) |
525 | + } |
526 | + |
527 | + onClicked: root.allDepartmentClicked(); |
528 | + } |
529 | + |
530 | + Repeater { |
531 | + model: department && department.loaded ? department : null |
532 | + clip: true |
533 | + delegate: AbstractButton { |
534 | + objectName: root.objectName + "child" + index |
535 | + height: root.itemHeight |
536 | + width: root.width |
537 | + |
538 | + onClicked: root.enterDepartment(departmentId, hasChildren) |
539 | + |
540 | + Label { |
541 | + anchors { |
542 | + verticalCenter: parent.verticalCenter |
543 | + left: parent.left |
544 | + leftMargin: units.gu(2) |
545 | + } |
546 | + text: label |
547 | + color: "gray" // TODO remove once we're a separate app |
548 | + } |
549 | + |
550 | + Image { |
551 | + anchors { |
552 | + verticalCenter: parent.verticalCenter |
553 | + right: parent.right |
554 | + rightMargin: units.gu(2) |
555 | + } |
556 | + source: hasChildren ? "image://theme/chevron" : "graphics/tick.png" |
557 | + sourceSize.height: parent.height - units.gu(3) |
558 | + sourceSize.width: units.gu(3) |
559 | + fillMode: Image.PreserveAspectFit |
560 | + visible: hasChildren || isActive |
561 | + } |
562 | + |
563 | + Rectangle { |
564 | + anchors { |
565 | + bottom: parent.bottom |
566 | + left: parent.left |
567 | + right: parent.right |
568 | + leftMargin: units.gu(2) |
569 | + rightMargin: units.gu(2) |
570 | + } |
571 | + color: "gray" |
572 | + opacity: 0.1 |
573 | + height: units.dp(1) |
574 | + visible: index != department.count - 1 |
575 | + } |
576 | + } |
577 | + } |
578 | + } |
579 | + } |
580 | +} |
581 | |
582 | === modified file 'qml/Dash/ScopeItem.qml' |
583 | --- qml/Dash/ScopeItem.qml 2014-02-21 16:19:51 +0000 |
584 | +++ qml/Dash/ScopeItem.qml 2014-06-19 10:41:43 +0000 |
585 | @@ -31,6 +31,10 @@ |
586 | signal gotoScope(string scopeId) |
587 | signal openScope(var scope) |
588 | |
589 | + // TODO see how much code we can share |
590 | + // between here and other Dash parts, it's starting to have |
591 | + // too much duplicated code with the DashDepartments, etc |
592 | + |
593 | Item { |
594 | id: scopeViewHolder |
595 | |
596 | @@ -79,6 +83,14 @@ |
597 | fontSize: "x-large" |
598 | elide: Text.ElideRight |
599 | } |
600 | + |
601 | + bottomItem: DashDepartments { |
602 | + scope: root.scope |
603 | + width: parent.width <= units.gu(60) ? parent.width : units.gu(40) |
604 | + anchors.right: parent.right |
605 | + windowHeight: root.height |
606 | + windowWidth: root.width |
607 | + } |
608 | } |
609 | } |
610 | |
611 | |
612 | === added file 'qml/Dash/graphics/tick@30.png' |
613 | Binary files qml/Dash/graphics/tick@30.png 1970-01-01 00:00:00 +0000 and qml/Dash/graphics/tick@30.png 2014-06-19 10:41:43 +0000 differ |
614 | === modified file 'tests/mocks/Unity/CMakeLists.txt' |
615 | --- tests/mocks/Unity/CMakeLists.txt 2014-05-27 07:45:46 +0000 |
616 | +++ tests/mocks/Unity/CMakeLists.txt 2014-06-19 10:41:43 +0000 |
617 | @@ -22,12 +22,14 @@ |
618 | fake_scope.cpp |
619 | fake_scopes.cpp |
620 | fake_categories.cpp |
621 | + fake_department.cpp |
622 | fake_resultsmodel.cpp |
623 | fake_previewmodel.cpp |
624 | fake_previewstack.cpp |
625 | fake_previewwidgetmodel.cpp |
626 | fake_unity_plugin.cpp |
627 | ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/CategoriesInterface.h |
628 | + ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/DepartmentInterface.h |
629 | ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/PreviewModelInterface.h |
630 | ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/PreviewStackInterface.h |
631 | ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/PreviewWidgetModelInterface.h |
632 | |
633 | === added file 'tests/mocks/Unity/fake_department.cpp' |
634 | --- tests/mocks/Unity/fake_department.cpp 1970-01-01 00:00:00 +0000 |
635 | +++ tests/mocks/Unity/fake_department.cpp 2014-06-19 10:41:43 +0000 |
636 | @@ -0,0 +1,127 @@ |
637 | +/* |
638 | + * Copyright (C) 2014 Canonical, Ltd. |
639 | + * |
640 | + * This program is free software; you can redistribute it and/or modify |
641 | + * it under the terms of the GNU General Public License as published by |
642 | + * the Free Software Foundation; version 3. |
643 | + * |
644 | + * This program is distributed in the hope that it will be useful, |
645 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
646 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
647 | + * GNU General Public License for more details. |
648 | + * |
649 | + * You should have received a copy of the GNU General Public License |
650 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
651 | + */ |
652 | + |
653 | +#include "fake_department.h" |
654 | + |
655 | +#include "fake_scope.h" |
656 | + |
657 | +#include <QTimer> |
658 | + |
659 | +Department::Department(const QString& departmentId, const QString& label, const QString& allLabel, const QString& parentId, const QString& parentLabel, Scope* scope) |
660 | + : m_departmentId(departmentId) |
661 | + , m_label(label) |
662 | + , m_allLabel(allLabel) |
663 | + , m_parentId(parentId) |
664 | + , m_parentLabel(parentLabel) |
665 | + , m_loaded(false) |
666 | + , m_scope(scope) |
667 | +{ |
668 | + QTimer::singleShot(1500, this, SLOT(slotLoaded())); |
669 | + connect(scope, SIGNAL(currentDepartmentIdChanged()), this, SLOT(slotCurrentDepartmentChanged())); |
670 | +} |
671 | + |
672 | +QString Department::departmentId() const |
673 | +{ |
674 | + return m_departmentId; |
675 | +} |
676 | + |
677 | +QString Department::label() const |
678 | +{ |
679 | + return m_label; |
680 | +} |
681 | + |
682 | +QString Department::allLabel() const |
683 | +{ |
684 | + return m_allLabel; |
685 | +} |
686 | + |
687 | +QString Department::parentDepartmentId() const |
688 | +{ |
689 | + return m_parentId; |
690 | +} |
691 | + |
692 | +QString Department::parentLabel() const |
693 | +{ |
694 | + return m_parentLabel; |
695 | +} |
696 | + |
697 | +void Department::slotLoaded() |
698 | +{ |
699 | + m_loaded = true; |
700 | + Q_EMIT loadedChanged(); |
701 | +} |
702 | + |
703 | +bool Department::loaded() const |
704 | +{ |
705 | + return m_loaded; |
706 | +} |
707 | + |
708 | +int Department::count() const |
709 | +{ |
710 | + return rowCount(); |
711 | +} |
712 | + |
713 | +bool Department::isRoot() const |
714 | +{ |
715 | + return m_departmentId == "root"; |
716 | +} |
717 | + |
718 | +int Department::rowCount(const QModelIndex & /*parent*/) const |
719 | +{ |
720 | + if (!m_loaded || m_departmentId.startsWith("child") || m_departmentId == "middle3") |
721 | + return 0; |
722 | + else |
723 | + return 8; |
724 | +} |
725 | + |
726 | +QHash<int, QByteArray> Department::roleNames() const |
727 | +{ |
728 | + QHash<int, QByteArray> res; |
729 | + res[RoleDepartmentId] = "departmentId"; |
730 | + res[RoleLabel] = "label"; |
731 | + res[RoleHasChildren] = "hasChildren"; |
732 | + res[RoleIsActive] = "isActive"; |
733 | + return res; |
734 | +} |
735 | + |
736 | +QVariant Department::data(const QModelIndex &index, int role) const |
737 | +{ |
738 | + switch (role) { |
739 | + case RoleDepartmentId: |
740 | + if (m_departmentId == "root") |
741 | + return QString("middle%1").arg(index.row()); |
742 | + else if (m_departmentId.startsWith("middle")) |
743 | + return QString("child%1%2").arg(m_departmentId).arg(index.row()); |
744 | + break; |
745 | + case RoleLabel: |
746 | + return QString("%1Child%2").arg(m_departmentId).arg(index.row()); |
747 | + break; |
748 | + case RoleHasChildren: |
749 | + return m_departmentId == "root" && index.row() != 3; |
750 | + break; |
751 | + case RoleIsActive: |
752 | + return m_scope->currentDepartmentId() == data(index, RoleDepartmentId); |
753 | + break; |
754 | + } |
755 | + return QVariant(); |
756 | +} |
757 | + |
758 | +void Department::slotCurrentDepartmentChanged() |
759 | +{ |
760 | + // This is wasteful, should only emit it if really something changed in this |
761 | + // deparment, but this is a mock, so no need to optimize |
762 | + Q_EMIT dataChanged(index(0, 0), index(rowCount() - 1, 0), QVector<int>() << RoleIsActive); |
763 | +} |
764 | |
765 | === added file 'tests/mocks/Unity/fake_department.h' |
766 | --- tests/mocks/Unity/fake_department.h 1970-01-01 00:00:00 +0000 |
767 | +++ tests/mocks/Unity/fake_department.h 2014-06-19 10:41:43 +0000 |
768 | @@ -0,0 +1,61 @@ |
769 | +/* |
770 | + * Copyright (C) 2014 Canonical, Ltd. |
771 | + * |
772 | + * This program is free software; you can redistribute it and/or modify |
773 | + * it under the terms of the GNU General Public License as published by |
774 | + * the Free Software Foundation; version 3. |
775 | + * |
776 | + * This program is distributed in the hope that it will be useful, |
777 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
778 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
779 | + * GNU General Public License for more details. |
780 | + * |
781 | + * You should have received a copy of the GNU General Public License |
782 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
783 | + */ |
784 | + |
785 | +#ifndef FAKE_DEPARTMENT_H |
786 | +#define FAKE_DEPARTMENT_H |
787 | + |
788 | +#include <unity/shell/scopes/DepartmentInterface.h> |
789 | + |
790 | +class Scope; |
791 | + |
792 | +class Department : public unity::shell::scopes::DepartmentInterface |
793 | +{ |
794 | + Q_OBJECT |
795 | + |
796 | +public: |
797 | + Department(const QString& departmentId, const QString& label, const QString& allLabel, const QString& parentId, const QString& parentLabel, Scope* scope); |
798 | + |
799 | + QString departmentId() const override; |
800 | + QString label() const override; |
801 | + QString allLabel() const override; |
802 | + QString parentDepartmentId() const override; |
803 | + QString parentLabel() const override; |
804 | + bool loaded() const override; |
805 | + int count() const override; |
806 | + bool isRoot() const override; |
807 | + |
808 | + int rowCount(const QModelIndex &parent = QModelIndex()) const override; |
809 | + QHash<int, QByteArray> roleNames() const; |
810 | + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; |
811 | + |
812 | +public Q_SLOTS: |
813 | + void slotCurrentDepartmentChanged(); |
814 | + |
815 | +private Q_SLOTS: |
816 | + void slotLoaded(); |
817 | + |
818 | +private: |
819 | + QString m_departmentId; |
820 | + QString m_label; |
821 | + QString m_allLabel; |
822 | + QString m_parentId; |
823 | + QString m_parentLabel; |
824 | + bool m_loaded; |
825 | + QString m_currentDepartment; |
826 | + Scope *m_scope; |
827 | +}; |
828 | + |
829 | +#endif // FAKE_DEPARTMENT_H |
830 | |
831 | === modified file 'tests/mocks/Unity/fake_scope.cpp' |
832 | --- tests/mocks/Unity/fake_scope.cpp 2014-05-20 14:27:57 +0000 |
833 | +++ tests/mocks/Unity/fake_scope.cpp 2014-06-19 10:41:43 +0000 |
834 | @@ -15,6 +15,7 @@ |
835 | */ |
836 | |
837 | #include "fake_scope.h" |
838 | +#include "fake_department.h" |
839 | #include "fake_resultsmodel.h" |
840 | |
841 | Scope::Scope(QObject* parent) : Scope(QString(), QString(), false, parent) |
842 | @@ -28,6 +29,7 @@ |
843 | , m_visible(visible) |
844 | , m_searching(false) |
845 | , m_isActive(false) |
846 | + , m_currentDeparment("root") |
847 | , m_previewRendererName("preview-generic") |
848 | , m_categories(new Categories(20, this)) |
849 | { |
850 | @@ -102,7 +104,7 @@ |
851 | void Scope::setActive(const bool active) { |
852 | if (active != m_isActive) { |
853 | m_isActive = active; |
854 | - Q_EMIT isActiveChanged(active); |
855 | + Q_EMIT isActiveChanged(); |
856 | } |
857 | } |
858 | |
859 | @@ -142,3 +144,36 @@ |
860 | { |
861 | qFatal("Scope::closeScope is not implemented"); |
862 | } |
863 | + |
864 | +QString Scope::currentDepartmentId() const |
865 | +{ |
866 | + return m_currentDeparment; |
867 | +} |
868 | + |
869 | +bool Scope::hasDepartments() const |
870 | +{ |
871 | + return true; |
872 | +} |
873 | + |
874 | +unity::shell::scopes::DepartmentInterface* Scope::getDepartment(const QString& id) |
875 | +{ |
876 | + if (id.isEmpty()) |
877 | + return nullptr; |
878 | + |
879 | + QString parentId; |
880 | + QString parentLabel; |
881 | + if (id.startsWith("middle")) { |
882 | + parentId = "root"; |
883 | + parentLabel = "root"; |
884 | + } else if (id.startsWith("child")) { |
885 | + parentId = id.mid(5, 7); |
886 | + parentLabel = parentId; |
887 | + } |
888 | + return new Department(id, id, "all"+id, parentId, parentLabel, this); |
889 | +} |
890 | + |
891 | +void Scope::loadDepartment(const QString& id) |
892 | +{ |
893 | + m_currentDeparment = id; |
894 | + Q_EMIT currentDepartmentIdChanged(); |
895 | +} |
896 | |
897 | === modified file 'tests/mocks/Unity/fake_scope.h' |
898 | --- tests/mocks/Unity/fake_scope.h 2014-05-20 14:27:57 +0000 |
899 | +++ tests/mocks/Unity/fake_scope.h 2014-06-19 10:41:43 +0000 |
900 | @@ -59,6 +59,11 @@ |
901 | Q_INVOKABLE void cancelActivation() override; |
902 | Q_INVOKABLE void closeScope(unity::shell::scopes::ScopeInterface* scope) override; |
903 | |
904 | + QString currentDepartmentId() const override; |
905 | + bool hasDepartments() const override; |
906 | + Q_INVOKABLE unity::shell::scopes::DepartmentInterface* getDepartment(const QString& id) override; |
907 | + Q_INVOKABLE void loadDepartment(const QString& id) override; |
908 | + |
909 | protected: |
910 | |
911 | QString m_id; |
912 | @@ -71,6 +76,7 @@ |
913 | bool m_visible; |
914 | bool m_searching; |
915 | bool m_isActive; |
916 | + QString m_currentDeparment; |
917 | |
918 | QString m_previewRendererName; |
919 | |
920 | |
921 | === modified file 'tests/mocks/Unity/fake_scopes.cpp' |
922 | --- tests/mocks/Unity/fake_scopes.cpp 2014-05-27 11:47:59 +0000 |
923 | +++ tests/mocks/Unity/fake_scopes.cpp 2014-06-19 10:41:43 +0000 |
924 | @@ -49,7 +49,7 @@ |
925 | |
926 | if (!m_loaded) { |
927 | m_loaded = true; |
928 | - Q_EMIT loadedChanged(m_loaded); |
929 | + Q_EMIT loadedChanged(); |
930 | } |
931 | } |
932 | |
933 | @@ -65,7 +65,7 @@ |
934 | |
935 | if (m_loaded) { |
936 | m_loaded = false; |
937 | - Q_EMIT loadedChanged(m_loaded); |
938 | + Q_EMIT loadedChanged(); |
939 | } |
940 | } |
941 | |
942 | |
943 | === modified file 'tests/mocks/Unity/fake_unity_plugin.cpp' |
944 | --- tests/mocks/Unity/fake_unity_plugin.cpp 2014-05-20 15:16:49 +0000 |
945 | +++ tests/mocks/Unity/fake_unity_plugin.cpp 2014-06-19 10:41:43 +0000 |
946 | @@ -22,6 +22,7 @@ |
947 | // local |
948 | #include "fake_scopes.h" |
949 | #include "fake_categories.h" |
950 | +#include "fake_department.h" |
951 | #include "fake_previewmodel.h" |
952 | #include "fake_previewwidgetmodel.h" |
953 | #include "fake_resultsmodel.h" |
954 | @@ -42,6 +43,7 @@ |
955 | qmlRegisterType<Scopes>(uri, 0, 2, "Scopes"); |
956 | qmlRegisterType<Scope>(uri, 0, 2, "MockScope"); |
957 | qmlRegisterUncreatableType<unity::shell::scopes::ScopeInterface>(uri, 0, 2, "Scope", "Can't create Scope object in QML."); |
958 | + qmlRegisterUncreatableType<unity::shell::scopes::DepartmentInterface>(uri, 0, 2, "Department", "Can't create Department object in QML."); |
959 | qmlRegisterUncreatableType<unity::shell::scopes::CategoriesInterface>(uri, 0, 2, "Categories", "Can't create Categories object in QML."); |
960 | qmlRegisterUncreatableType<ResultsModel>(uri, 0, 2, "ResultsModel", "Can't create ResultsModel object in QML."); |
961 | qmlRegisterType<PreviewModel>(uri, 0, 2, "FakePreviewModel"); |
962 | |
963 | === modified file 'tests/qmltests/Dash/tst_DashContent.qml' |
964 | --- tests/qmltests/Dash/tst_DashContent.qml 2014-05-27 07:46:14 +0000 |
965 | +++ tests/qmltests/Dash/tst_DashContent.qml 2014-06-19 10:41:43 +0000 |
966 | @@ -124,13 +124,13 @@ |
967 | |
968 | waitForRendering(categoryListView); |
969 | |
970 | - categoryListView.contentY = units.gu(11); |
971 | - console.log("contentY", categoryListView.contentY); |
972 | + categoryListView.contentY = units.gu(15); |
973 | + tryCompare(categoryListView, "contentY", units.gu(15)); |
974 | |
975 | var startX = dashContentList.width/2; |
976 | var startY = dashContentList.height/2; |
977 | touchFlick(dashContentList, startX - units.gu(2), startY, startX, startY); |
978 | - tryCompare(categoryListView, "contentY", units.gu(11) - categoryListView.pageHeader.height); |
979 | + tryCompare(categoryListView, "contentY", units.gu(15) - categoryListView.pageHeader.height); |
980 | } |
981 | |
982 | function test_set_current_scope_reset() { |
983 | @@ -407,5 +407,116 @@ |
984 | var carouselLV = findChild(dashCategory1, "listView"); |
985 | verify(carouselLV.tileWidth / carouselLV.tileHeight == cardTool.components["art"]["aspect-ratio"]); |
986 | } |
987 | + |
988 | + function test_departments() { |
989 | + var dashDepartments = findChild(dashContent, "dashDepartments"); |
990 | + compare(dashDepartments.visible, true); |
991 | + compare(dashDepartments.showList, false); |
992 | + waitForRendering(dashDepartments); |
993 | + mouseClick(dashDepartments, 0, 0); |
994 | + compare(dashDepartments.showList, true); |
995 | + |
996 | + var departmentListView = findChild(dashDepartments, "departmentListView"); |
997 | + compare(departmentListView.count, 1); |
998 | + tryCompare(departmentListView.currentItem.department, "loaded", true); |
999 | + |
1000 | + waitForRendering(departmentListView); |
1001 | + waitForRendering(departmentListView.currentItem); |
1002 | + |
1003 | + var allButton = findChild(dashDepartments, "allButton"); |
1004 | + compare(allButton.visible, false); |
1005 | + |
1006 | + var department = findChild(dashDepartments, "department0child3"); |
1007 | + mouseClick(department, 0, 0); |
1008 | + compare(dashDepartments.showList, false); |
1009 | + tryCompare(dashDepartments.currentDepartment, "departmentId", "middle3"); |
1010 | + tryCompare(departmentListView.currentItem.department, "departmentId", "root"); |
1011 | + |
1012 | + mouseClick(dashDepartments, 0, 0); |
1013 | + compare(dashDepartments.showList, true); |
1014 | + waitForRendering(departmentListView); |
1015 | + waitForRendering(departmentListView.currentItem); |
1016 | + compare(allButton.visible, true); |
1017 | + |
1018 | + mouseClick(allButton, 0, 0); |
1019 | + compare(dashDepartments.showList, false); |
1020 | + tryCompare(dashDepartments.currentDepartment, "departmentId", "root"); |
1021 | + tryCompare(departmentListView.currentItem.department, "departmentId", "root"); |
1022 | + |
1023 | + mouseClick(dashDepartments, 0, 0); |
1024 | + compare(dashDepartments.showList, true); |
1025 | + waitForRendering(departmentListView); |
1026 | + waitForRendering(departmentListView.currentItem); |
1027 | + compare(allButton.visible, false); |
1028 | + |
1029 | + department = findChild(dashDepartments, "department0child2"); |
1030 | + mouseClick(department, 0, 0); |
1031 | + compare(dashDepartments.showList, true); |
1032 | + tryCompare(dashDepartments.currentDepartment, "departmentId", "middle2"); |
1033 | + tryCompare(departmentListView.currentItem.department, "departmentId", "middle2"); |
1034 | + |
1035 | + var departmentList1 = findChild(dashDepartments, "department1"); |
1036 | + allButton = findChild(departmentList1, "allButton"); |
1037 | + var backButton = findChild(findChild(departmentList1, "department1"), "backButton"); |
1038 | + compare(allButton.visible, true); |
1039 | + compare(backButton.visible, true); |
1040 | + |
1041 | + mouseClick(allButton, 0, 0); |
1042 | + compare(dashDepartments.showList, false); |
1043 | + tryCompare(dashDepartments.currentDepartment, "departmentId", "middle2"); |
1044 | + tryCompare(departmentListView.currentItem.department, "departmentId", "middle2"); |
1045 | + |
1046 | + mouseClick(dashDepartments, 0, 0); |
1047 | + compare(dashDepartments.showList, true); |
1048 | + waitForRendering(departmentListView); |
1049 | + waitForRendering(departmentListView.currentItem); |
1050 | + compare(allButton.visible, true); |
1051 | + compare(backButton.visible, true); |
1052 | + |
1053 | + tryCompare(departmentList1.department, "loaded", true); |
1054 | + department = findChild(dashDepartments, "department1child2"); |
1055 | + mouseClick(department, 0, 0); |
1056 | + compare(dashDepartments.showList, false); |
1057 | + tryCompare(dashDepartments.currentDepartment, "departmentId", "childmiddle22"); |
1058 | + tryCompare(departmentListView.currentItem.department, "departmentId", "middle2"); |
1059 | + |
1060 | + mouseClick(dashDepartments, 0, 0); |
1061 | + compare(dashDepartments.showList, true); |
1062 | + waitForRendering(departmentListView); |
1063 | + waitForRendering(departmentListView.currentItem); |
1064 | + |
1065 | + tryCompare(departmentList1.department, "loaded", true); |
1066 | + department = findChild(dashDepartments, "department1child3"); |
1067 | + mouseClick(department, 0, 0); |
1068 | + compare(dashDepartments.showList, false); |
1069 | + tryCompare(dashDepartments.currentDepartment, "departmentId", "childmiddle23"); |
1070 | + tryCompare(departmentListView.currentItem.department, "departmentId", "middle2"); |
1071 | + |
1072 | + mouseClick(dashDepartments, 0, 0); |
1073 | + compare(dashDepartments.showList, true); |
1074 | + waitForRendering(departmentListView); |
1075 | + waitForRendering(departmentListView.currentItem); |
1076 | + mouseClick(backButton, 0, 0); |
1077 | + |
1078 | + tryCompare(dashDepartments.currentDepartment, "departmentId", "root"); |
1079 | + tryCompare(departmentListView.currentItem.department, "departmentId", "root"); |
1080 | + compare(dashDepartments.showList, true); |
1081 | + mouseClick(dashDepartments, 0, 0); |
1082 | + compare(dashDepartments.showList, false); |
1083 | + |
1084 | + mouseClick(dashDepartments, 0, 0); |
1085 | + compare(dashDepartments.showList, true); |
1086 | + tryCompare(departmentListView.currentItem.department, "loaded", true); |
1087 | + department = findChild(dashDepartments, "department0child2"); |
1088 | + mouseClick(department, 0, 0); |
1089 | + compare(dashDepartments.showList, true); |
1090 | + departmentList1 = findChild(dashDepartments, "department1"); |
1091 | + compare(departmentList1.department.loaded, false); |
1092 | + tryCompare(dashDepartments.currentDepartment, "departmentId", "middle2"); |
1093 | + allButton = findChild(departmentList1, "allButton"); |
1094 | + tryCompare(dashDepartments.currentDepartment, "departmentId", "middle2"); |
1095 | + mouseClick(allButton, 0, 0); |
1096 | + tryCompare(dashDepartments.currentDepartment, "departmentId", "middle2"); |
1097 | + } |
1098 | } |
1099 | } |
As said by Saviq, need to limit the width to 60gu and then bring it back to 40gu so that it doesn't look weird in wide sizes