Merge lp:~saviq/unity8/card-visual-tweaks into lp:unity8

Proposed by Michał Sawicz
Status: Superseded
Proposed branch: lp:~saviq/unity8/card-visual-tweaks
Merge into: lp:unity8
Diff against target: 2247 lines (+830/-318)
50 files modified
build.sh (+1/-0)
cmake/modules/QmlTest.cmake (+2/-1)
debian/control (+1/-0)
plugins/Dash/CardAttributes.qml (+1/-1)
plugins/Dash/CardCreator.js (+12/-10)
plugins/Dash/listviewwithpageheader.cpp (+28/-7)
plugins/Dash/listviewwithpageheader.h (+8/-0)
qml/Dash/CardGrid.qml (+2/-1)
qml/Dash/CardHorizontalList.qml (+1/-1)
qml/Dash/CardTool.qml (+27/-19)
qml/Dash/CardVerticalJournal.qml (+2/-1)
qml/Dash/DashContent.qml (+1/-0)
qml/Dash/DashRenderer.qml (+4/-0)
qml/Dash/GenericScopeView.qml (+111/-22)
qml/Dash/ScopeListView.qml (+1/-0)
qml/Dash/ScopesOverviewAll.qml (+2/-0)
qml/Dash/ScopesOverviewFavorites.qml (+1/-1)
tests/autopilot/unity8/shell/emulators/dash.py (+2/-2)
tests/mocks/Ubuntu/CMakeLists.txt (+1/-0)
tests/mocks/Ubuntu/Connectivity/CMakeLists.txt (+10/-0)
tests/mocks/Ubuntu/Connectivity/networking-status.cpp (+65/-0)
tests/mocks/Ubuntu/Connectivity/networking-status.h (+73/-0)
tests/mocks/Ubuntu/Connectivity/plugin.cpp (+46/-0)
tests/mocks/Ubuntu/Connectivity/plugin.h (+35/-0)
tests/mocks/Ubuntu/Connectivity/qmldir (+2/-0)
tests/mocks/Unity/fake_categories.cpp (+100/-141)
tests/mocks/Unity/fake_categories.h (+7/-12)
tests/mocks/Unity/fake_resultsmodel.cpp (+9/-0)
tests/mocks/Unity/fake_resultsmodel.h (+3/-0)
tests/mocks/Unity/fake_scope.cpp (+17/-0)
tests/mocks/Unity/fake_scope.h (+2/-0)
tests/plugins/Dash/CMakeLists.txt (+3/-3)
tests/plugins/Dash/cardcreator/1.res (+6/-5)
tests/plugins/Dash/cardcreator/2.res (+7/-7)
tests/plugins/Dash/cardcreator/3.res (+8/-8)
tests/plugins/Dash/cardcreator/4.res (+8/-8)
tests/plugins/Dash/cardcreator/5.res (+8/-8)
tests/plugins/Dash/cardcreator/6.res (+6/-8)
tests/plugins/Dash/cardcreator/7.res (+8/-8)
tests/plugins/Dash/listviewwithpageheadertest.cpp (+39/-0)
tests/plugins/Dash/listviewwithpageheadertest.qml (+1/-0)
tests/plugins/Dash/listviewwithpageheadertestsection.qml (+1/-0)
tests/plugins/Dash/listviewwithpageheadertestsectionexternalmodel.qml (+1/-0)
tests/plugins/Ubuntu/Gestures/CMakeLists.txt (+1/-1)
tests/qmltests/Components/CMakeLists.txt (+1/-1)
tests/qmltests/Dash/CardHelpers.js (+1/-12)
tests/qmltests/Dash/tst_Card.qml (+21/-0)
tests/qmltests/Dash/tst_CardTool.qml (+29/-21)
tests/qmltests/Dash/tst_Dash.qml (+1/-2)
tests/qmltests/Dash/tst_GenericScopeView.qml (+103/-7)
To merge this branch: bzr merge lp:~saviq/unity8/card-visual-tweaks
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
Alejandro J. Cura (community) Needs Fixing
Review via email: mp+233392@code.launchpad.net

This proposal has been superseded by a proposal from 2014-09-11.

Commit message

Tweak card header to match the spec

- title is Medium only if subtitle is non-empty
- title is only centered if explicitly requested by the scope ("align": "center" in components), with only one allowed line
- subtitle is x-small
- highlighted attribute is Bold
- emblem is allowed non-square

Description of the change

* Are there any related MPs required for this MP to build/function as expected? Please list.
All scopes that want center alignment need to adapt
 * Did you perform an exploratory manual test run of your code change and any related functionality?
Y
 * Did you make sure that your branch does not contain spurious tags?
Y
 * 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?
This comes from design, see the referenced bugs.

To post a comment you must log in.
lp:~saviq/unity8/card-visual-tweaks updated
1234. By Michał Sawicz

Bigger coverage.

1235. By Michał Sawicz

Unneeded layout assignment.

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

Tested the debs produced by jenkins on mako, it looks much nicer overall, but the title is still centered by default.

I'm attaching a screenshot to show this.

review: Needs Fixing
Revision history for this message
Alejandro J. Cura (alecu) wrote :
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Chris Wayne (cwayne) wrote :

I've verified that this makes rectangular emblems look *much* better, but I'm still seeing the titles centered by default as well

lp:~saviq/unity8/card-visual-tweaks updated
1236. By Michał Sawicz

Fix title alignment test and binding, clean up old components from CardHelpers.js

1237. By Michał Sawicz

Fix typo

Revision history for this message
Michał Sawicz (saviq) wrote :

Yeah, shouldn't have worked so late... Fixed the tests and alignment, as well as the single-line enforcing, even though I expect we won't be doing that in the end.

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

Verified that emblems look better + Titles are now left-aligned as expected

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
lp:~saviq/unity8/card-visual-tweaks updated
1238. By Michał Sawicz

Merge trunk.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
lp:~saviq/unity8/card-visual-tweaks updated
1239. By Michał Sawicz

Merge lp:~unity-team/unity8/scopes_more_things_on_memory

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'build.sh'
2--- build.sh 2014-08-14 13:37:22 +0000
3+++ build.sh 2014-09-11 16:03:35 +0000
4@@ -51,6 +51,7 @@
5 qtdeclarative5-ubuntu-settings-components \
6 qtdeclarative5-ubuntu-telephony0.1 \
7 qtdeclarative5-ubuntu-thumbnailer0.1 \
8+ qml-module-ubuntu-connectivity \
9 unity-notifications-impl \
10 ubuntu-mobile-icons \
11 unity-scope-home \
12
13=== modified file 'cmake/modules/QmlTest.cmake'
14--- cmake/modules/QmlTest.cmake 2014-08-07 15:32:25 +0000
15+++ cmake/modules/QmlTest.cmake 2014-09-11 16:03:35 +0000
16@@ -131,7 +131,7 @@
17 add_manual_qml_test(${SUBPATH} ${COMPONENT_NAME} ${ARGN})
18 endmacro(add_qml_test_internal)
19
20-macro(add_binary_qml_test CLASS_NAME LD_PATH DEPS)
21+macro(add_binary_qml_test CLASS_NAME LD_PATH DEPS ENVVAR)
22 set(testCommand
23 LD_LIBRARY_PATH=${LD_PATH}
24 ${CMAKE_CURRENT_BINARY_DIR}/${CLASS_NAME}TestExec
25@@ -148,6 +148,7 @@
26 endif()
27 set(xvfbtestCommand
28 ${LD_PRELOAD_PATH}
29+ ${ENVVAR}
30 LD_LIBRARY_PATH=${LD_PATH}
31 xvfb-run --server-args "-screen 0 1024x768x24" --auto-servernum
32 ${CMAKE_CURRENT_BINARY_DIR}/${CLASS_NAME}TestExec
33
34=== modified file 'debian/control'
35--- debian/control 2014-09-03 07:58:32 +0000
36+++ debian/control 2014-09-11 16:03:35 +0000
37@@ -173,6 +173,7 @@
38 libhardware2,
39 libunity-core-6.0-9,
40 pay-service,
41+ qml-module-ubuntu-connectivity,
42 ${misc:Depends},
43 ${shlibs:Depends},
44 Provides: unity-launcher-impl,
45
46=== modified file 'plugins/Dash/CardAttributes.qml'
47--- plugins/Dash/CardAttributes.qml 2014-08-16 12:41:11 +0000
48+++ plugins/Dash/CardAttributes.qml 2014-09-11 16:03:35 +0000
49@@ -59,7 +59,7 @@
50 text: "value" in modelData && modelData["value"] || "";
51 elide: Text.ElideRight
52 maximumLineCount: 1
53- font.weight: "style" in modelData && modelData["style"] == "highlighted" ? Font.DemiBold : Font.Light
54+ font.weight: "style" in modelData && modelData["style"] === "highlighted" ? Font.Bold : Font.Light
55 fontSize: "small"
56 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale)
57 color: grid.color
58
59=== modified file 'plugins/Dash/CardCreator.js'
60--- plugins/Dash/CardCreator.js 2014-08-29 08:19:53 +0000
61+++ plugins/Dash/CardCreator.js 2014-09-11 16:03:35 +0000
62@@ -84,7 +84,8 @@
63 } \n\
64 image: Image { \n\
65 objectName: "artImage"; \n\
66- source: cardData && cardData["art"] || ""; \n\
67+ property bool doLoadSource: !NetworkingStatus.limitedBandwith; \n\
68+ source: { if (root.visible) doLoadSource = true; return doLoadSource && cardData && cardData["art"] || ""; } \n\
69 cache: true; \n\
70 asynchronous: root.asynchronous; \n\
71 fillMode: Image.PreserveAspectCrop; \n\
72@@ -195,7 +196,8 @@
73 objectName: "mascotImage"; \n\
74 anchors { %1 } \n\
75 readonly property int maxSize: Math.max(width, height) * 4; \n\
76- source: cardData && cardData["mascot"] || ""; \n\
77+ property bool doLoadSource: !NetworkingStatus.limitedBandwith; \n\
78+ source: { if (root.visible) doLoadSource = true; return doLoadSource && cardData && cardData["mascot"] || ""; } \n\
79 width: units.gu(6); \n\
80 height: units.gu(5.625); \n\
81 sourceSize { width: maxSize; height: maxSize } \n\
82@@ -215,18 +217,18 @@
83 elide: Text.ElideRight; \n\
84 fontSize: "small"; \n\
85 wrapMode: Text.Wrap; \n\
86- maximumLineCount: 2; \n\
87+ maximumLineCount: horizontalAlignment === Text.AlignHCenter ? 1 : 2; \n\
88 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale); \n\
89 color: %2; \n\
90 visible: showHeader %3; \n\
91 text: root.title; \n\
92- font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal; \n\
93- horizontalAlignment: root.headerAlignment; \n\
94+ font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal; \n\
95+ horizontalAlignment: root.titleAlignment; \n\
96 }\n';
97
98 // %1 is used as extra anchors of emblemIcon
99 // %2 is used as color of emblemIcon
100-var kEmblemIconCode = 'Icon { \n\
101+var kEmblemIconCode = 'StatusIcon { \n\
102 id: emblemIcon; \n\
103 objectName: "emblemIcon"; \n\
104 anchors { \n\
105@@ -236,7 +238,6 @@
106 } \n\
107 source: cardData && cardData["emblem"] || ""; \n\
108 color: %2; \n\
109- width: height; \n\
110 height: source != "" ? titleLabel.font.pixelSize : 0; \n\
111 }\n';
112
113@@ -258,13 +259,12 @@
114 anchors { %1 } \n\
115 anchors.topMargin: units.dp(2); \n\
116 elide: Text.ElideRight; \n\
117- fontSize: "small"; \n\
118+ fontSize: "x-small"; \n\
119 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale); \n\
120 color: %2; \n\
121 visible: titleLabel.visible && titleLabel.text; \n\
122 text: cardData && cardData["subtitle"] || ""; \n\
123 font.weight: Font.Light; \n\
124- horizontalAlignment: root.headerAlignment; \n\
125 }\n';
126
127 // %1 is used as anchors of attributesRow
128@@ -310,7 +310,7 @@
129 property var artShapeBorderSource: undefined; \n\
130 property real fontScale: 1.0; \n\
131 property var scopeStyle: null; \n\
132- property int headerAlignment: Text.AlignLeft; \n\
133+ property int titleAlignment: Text.AlignLeft; \n\
134 property int fixedHeaderHeight: -1; \n\
135 property size fixedArtShapeSize: Qt.size(-1, -1); \n\
136 readonly property string title: cardData && cardData["title"] || ""; \n\
137@@ -655,6 +655,8 @@
138 function createCardComponent(parent, template, components) {
139 var imports = 'import QtQuick 2.2; \n\
140 import Ubuntu.Components 1.1; \n\
141+ import Ubuntu.Settings.Components 0.1; \n\
142+ import Ubuntu.Connectivity 1.0; \n\
143 import Dash 0.1;\n\
144 import Utils 0.1;\n';
145 var card = cardString(template, components);
146
147=== modified file 'plugins/Dash/listviewwithpageheader.cpp'
148--- plugins/Dash/listviewwithpageheader.cpp 2014-09-01 10:45:25 +0000
149+++ plugins/Dash/listviewwithpageheader.cpp 2014-09-11 16:03:35 +0000
150@@ -104,8 +104,6 @@
151 #pragma GCC diagnostic pop
152 // #include <private/qquickrectangle_p.h>
153
154-static const qreal bufferRatio = 0.5;
155-
156 qreal ListViewWithPageHeader::ListItem::height() const
157 {
158 return m_item->height() + (m_sectionItem ? m_sectionItem->height() : 0);
159@@ -158,6 +156,7 @@
160 , m_forceNoClip(false)
161 , m_inLayout(false)
162 , m_inContentHeightKeepHeaderShown(false)
163+ , m_cacheBuffer(0)
164 {
165 m_clipItem = new QQuickItem(contentItem());
166 // m_clipItem = new QQuickRectangle(contentItem());
167@@ -335,6 +334,20 @@
168 return m_headerItemShownHeight;
169 }
170
171+qreal ListViewWithPageHeader::cacheBuffer() const
172+{
173+ return m_cacheBuffer;
174+}
175+
176+void ListViewWithPageHeader::setCacheBuffer(qreal cacheBuffer)
177+{
178+ if (cacheBuffer != m_cacheBuffer) {
179+ m_cacheBuffer = cacheBuffer;
180+ Q_EMIT cacheBufferChanged();
181+ polish();
182+ }
183+}
184+
185 void ListViewWithPageHeader::positionAtBeginning()
186 {
187 if (m_delegateModel->count() <= 0)
188@@ -356,8 +369,7 @@
189 // Create the subsequent items
190 int modelIndex = 1;
191 qreal pos = item->y() + item->height();
192- const qreal buffer = height() * bufferRatio;
193- const qreal bufferTo = height() + buffer;
194+ const qreal bufferTo = height() + m_cacheBuffer;
195 while (modelIndex < m_delegateModel->count() && pos <= bufferTo) {
196 if (!(item = createItem(modelIndex, false)))
197 break;
198@@ -409,6 +421,16 @@
199 }
200 }
201
202+Q_INVOKABLE int ListViewWithPageHeader::firstCreatedIndex() const
203+{
204+ return m_firstVisibleIndex;
205+}
206+
207+Q_INVOKABLE int ListViewWithPageHeader::createdItemCount() const
208+{
209+ return m_visibleItems.count();
210+}
211+
212 QQuickItem *ListViewWithPageHeader::item(int modelIndex) const
213 {
214 ListItem *item = itemAtIndex(modelIndex);
215@@ -593,11 +615,10 @@
216 return;
217 }
218
219- const qreal buffer = height() * bufferRatio;
220 const qreal from = contentY();
221 const qreal to = from + height();
222- const qreal bufferFrom = from - buffer;
223- const qreal bufferTo = to + buffer;
224+ const qreal bufferFrom = from - m_cacheBuffer;
225+ const qreal bufferTo = to + m_cacheBuffer;
226
227 bool added = addVisibleItems(from, to, false);
228 bool removed = removeNonVisibleItems(bufferFrom, bufferTo);
229
230=== modified file 'plugins/Dash/listviewwithpageheader.h'
231--- plugins/Dash/listviewwithpageheader.h 2014-09-01 10:45:25 +0000
232+++ plugins/Dash/listviewwithpageheader.h 2014-09-11 16:03:35 +0000
233@@ -54,6 +54,7 @@
234 Q_PROPERTY(bool forceNoClip READ forceNoClip WRITE setForceNoClip NOTIFY forceNoClipChanged)
235 Q_PROPERTY(int stickyHeaderHeight READ stickyHeaderHeight NOTIFY stickyHeaderHeightChanged)
236 Q_PROPERTY(qreal headerItemShownHeight READ headerItemShownHeight NOTIFY headerItemShownHeightChanged)
237+ Q_PROPERTY(qreal cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY cacheBufferChanged)
238
239 friend class ListViewWithPageHeaderTest;
240 friend class ListViewWithPageHeaderTestSection;
241@@ -84,8 +85,13 @@
242 int stickyHeaderHeight() const;
243 qreal headerItemShownHeight() const;
244
245+ qreal cacheBuffer() const;
246+ void setCacheBuffer(qreal cacheBuffer);
247+
248 Q_INVOKABLE void positionAtBeginning();
249 Q_INVOKABLE void showHeader();
250+ Q_INVOKABLE int firstCreatedIndex() const;
251+ Q_INVOKABLE int createdItemCount() const;
252 Q_INVOKABLE QQuickItem *item(int modelIndex) const;
253
254 // The index has to be created for this to try to do something
255@@ -103,6 +109,7 @@
256 void forceNoClipChanged();
257 void stickyHeaderHeightChanged();
258 void headerItemShownHeightChanged();
259+ void cacheBufferChanged();
260
261 protected:
262 void componentComplete() override;
263@@ -197,6 +204,7 @@
264 bool m_forceNoClip;
265 bool m_inLayout;
266 bool m_inContentHeightKeepHeaderShown;
267+ qreal m_cacheBuffer;
268
269 // Qt 5.0 doesn't like releasing the items just after itemCreated
270 // so we delay the releasing until the next updatePolish
271
272=== modified file 'qml/Dash/CardGrid.qml'
273--- qml/Dash/CardGrid.qml 2014-07-29 08:57:29 +0000
274+++ qml/Dash/CardGrid.qml 2014-09-11 16:03:35 +0000
275@@ -55,6 +55,7 @@
276 delegate: Item {
277 width: grid.cellWidth
278 height: grid.cellHeight
279+ visible: y + height >= root.visibleRangeBegin && y <= root.visibleRangeEnd
280 Loader {
281 id: loader
282 sourceComponent: cardTool.cardComponent
283@@ -68,7 +69,7 @@
284 item.cardData = Qt.binding(function() { return model; });
285 item.template = Qt.binding(function() { return cardTool.template; });
286 item.components = Qt.binding(function() { return cardTool.components; });
287- item.headerAlignment = Qt.binding(function() { return cardTool.headerAlignment; });
288+ item.titleAlignment = Qt.binding(function() { return cardTool.titleAlignment; });
289 item.scopeStyle = root.scopeStyle;
290 }
291 Connections {
292
293=== modified file 'qml/Dash/CardHorizontalList.qml'
294--- qml/Dash/CardHorizontalList.qml 2014-08-15 14:21:42 +0000
295+++ qml/Dash/CardHorizontalList.qml 2014-09-11 16:03:35 +0000
296@@ -49,7 +49,7 @@
297 item.cardData = Qt.binding(function() { return model; });
298 item.template = Qt.binding(function() { return cardTool.template; });
299 item.components = Qt.binding(function() { return cardTool.components; });
300- item.headerAlignment = Qt.binding(function() { return cardTool.headerAlignment; });
301+ item.titleAlignment = Qt.binding(function() { return cardTool.titleAlignment; });
302 item.scopeStyle = root.scopeStyle;
303 }
304 Connections {
305
306=== modified file 'qml/Dash/CardTool.qml'
307--- qml/Dash/CardTool.qml 2014-09-08 14:11:57 +0000
308+++ qml/Dash/CardTool.qml 2014-09-11 16:03:35 +0000
309@@ -131,21 +131,26 @@
310 property size artShapeSize: cardLoader.item ? cardLoader.item.artShapeSize : 0
311
312 /*!
313- \brief Desired alignment of header components.
314+ \brief Desired alignment of title
315 */
316- readonly property int headerAlignment: {
317- var subtitle = components["subtitle"];
318- var price = components["price"];
319- var summary = components["summary"];
320-
321- var hasSubtitle = subtitle && (typeof subtitle === "string" || subtitle["field"])
322- var hasPrice = price && (typeof price === "string" || subtitle["field"]);
323- var hasSummary = summary && (typeof summary === "string" || summary["field"])
324-
325- var isOnlyTextComponent = !hasSubtitle && !hasPrice && !hasSummary;
326- if (!isOnlyTextComponent) return Text.AlignLeft;
327-
328- return (template["card-layout"] === "horizontal") ? Text.AlignLeft : Text.AlignHCenter;
329+ readonly property int titleAlignment: {
330+ if (template["card-layout"] === "horizontal"
331+ || typeof components["title"] !== "object"
332+ || components["title"]["align"] !== "center") return Text.AlignLeft;
333+
334+ var keys = ["mascot", "emblem", "subtitle", "attributes", "summary"];
335+
336+ for (var key in keys) {
337+ key = keys[key];
338+ try {
339+ if (typeof components[key] === "string"
340+ || typeof components[key]["field"] === "string") return Text.AlignLeft;
341+ } catch (e) {
342+ continue;
343+ }
344+ }
345+
346+ return Text.AlignHCenter;
347 }
348
349 QtObject {
350@@ -169,16 +174,19 @@
351
352 Item {
353 id: attributesModel
354- property int numOfAttributes: {
355+ property int numOfAttributes: 0
356+ property var model: []
357+ property bool hasAttributes: {
358 var attributes = components["attributes"];
359- if ((attributes != undefined) && attributes["field"]) {
360+ var hasAttributesFlag = (attributes != undefined) && attributes["field"];
361+
362+ if (hasAttributesFlag) {
363 if (attributes["max-count"]) {
364- return attributes["max-count"];
365+ numOfAttributes = attributes["max-count"];
366 }
367 }
368- return 0;
369+ return hasAttributesFlag
370 }
371- property var model: []
372
373 onNumOfAttributesChanged: {
374 model = []
375
376=== modified file 'qml/Dash/CardVerticalJournal.qml'
377--- qml/Dash/CardVerticalJournal.qml 2014-07-29 08:57:29 +0000
378+++ qml/Dash/CardVerticalJournal.qml 2014-09-11 16:03:35 +0000
379@@ -49,6 +49,7 @@
380 id: loader
381 sourceComponent: cardTool.cardComponent
382 width: cardTool.cardWidth
383+ visible: y + height >= root.visibleRangeBegin && y <= root.visibleRangeEnd
384 onLoaded: {
385 item.objectName = "delegate" + index;
386 item.fixedArtShapeSize = Qt.binding(function() { return cardTool.artShapeSize; });
387@@ -56,7 +57,7 @@
388 item.cardData = Qt.binding(function() { return model; });
389 item.template = Qt.binding(function() { return cardTool.template; });
390 item.components = Qt.binding(function() { return cardTool.components; });
391- item.headerAlignment = Qt.binding(function() { return cardTool.headerAlignment; });
392+ item.titleAlignment = Qt.binding(function() { return cardTool.titleAlignment; });
393 item.scopeStyle = root.scopeStyle;
394 }
395 Connections {
396
397=== modified file 'qml/Dash/DashContent.qml'
398--- qml/Dash/DashContent.qml 2014-08-27 15:35:52 +0000
399+++ qml/Dash/DashContent.qml 2014-09-11 16:03:35 +0000
400@@ -177,6 +177,7 @@
401 dashContent.scopeLoaded(item.scope.id)
402 item.paginationCount = Qt.binding(function() { return dashContentList.count } )
403 item.paginationIndex = Qt.binding(function() { return dashContentList.currentIndex } )
404+ item.holdingList = dashContentList;
405 }
406 Connections {
407 target: isCurrent ? scope : null
408
409=== modified file 'qml/Dash/DashRenderer.qml'
410--- qml/Dash/DashRenderer.qml 2014-07-29 08:57:29 +0000
411+++ qml/Dash/DashRenderer.qml 2014-09-11 16:03:35 +0000
412@@ -27,6 +27,10 @@
413
414 property int displayMarginEnd: 0
415
416+ property int visibleRangeBegin: 0
417+
418+ property int visibleRangeEnd: 0
419+
420 property real originY: 0
421
422 // The model to renderer
423
424=== modified file 'qml/Dash/GenericScopeView.qml'
425--- qml/Dash/GenericScopeView.qml 2014-09-08 14:15:01 +0000
426+++ qml/Dash/GenericScopeView.qml 2014-09-11 16:03:35 +0000
427@@ -38,6 +38,7 @@
428 property int paginationCount: 0
429 property int paginationIndex: 0
430 property alias pageHeaderTotallyVisible: categoryView.pageHeaderTotallyVisible
431+ property var holdingList: null
432
433 property var scopeStyle: ScopeStyle {
434 style: scope ? scope.customizations : {}
435@@ -47,6 +48,10 @@
436
437 signal backClicked()
438
439+ onScopeChanged: {
440+ floatingSeeLess.companionBase = null;
441+ }
442+
443 function positionAtBeginning() {
444 categoryView.positionAtBeginning()
445 }
446@@ -152,11 +157,55 @@
447 forceNoClip: subPageLoader.open
448 pixelAligned: true
449
450- property Item expandedCategoryItem: null
451+ property string expandedCategoryId: ""
452+ property int runMaximizeAfterSizeChanges: 0
453
454 readonly property bool pageHeaderTotallyVisible: scopeView.showPageHeader &&
455 ((headerItemShownHeight == 0 && categoryView.contentY <= categoryView.originY) || (headerItemShownHeight == pageHeaderLoader.item.height))
456
457+ onExpandedCategoryIdChanged: {
458+ var firstCreated = firstCreatedIndex();
459+ var shrinkingAny = false;
460+ var shrinkHeightDifference = 0;
461+ for (var i = 0; i < createdItemCount(); ++i) {
462+ var baseItem = item(firstCreated + i);
463+ if (baseItem.expandable) {
464+ var shouldExpand = baseItem.category === expandedCategoryId;
465+ if (shouldExpand != baseItem.expanded) {
466+
467+ var animate = false;
468+ if (!subPageLoader.open) {
469+ var animateShrinking = !shouldExpand && baseItem.y + baseItem.item.collapsedHeight + baseItem.seeAll.height < categoryView.height;
470+ var animateGrowing = shouldExpand && baseItem.y + baseItem.height < categoryView.height;
471+ animate = shrinkingAny || animateShrinking || animateGrowing;
472+ }
473+
474+ if (!shouldExpand) {
475+ shrinkingAny = true;
476+ shrinkHeightDifference = baseItem.item.expandedHeight - baseItem.item.collapsedHeight;
477+ }
478+
479+ if (shouldExpand && !subPageLoader.open) {
480+ if (!shrinkingAny) {
481+ categoryView.maximizeVisibleArea(firstCreated + i, baseItem.item.expandedHeight + baseItem.seeAll.height);
482+ } else {
483+ // If the space that shrkinking is smaller than the one we need to grow we'll call maximizeVisibleArea
484+ // after the shrink/grow animation ends
485+ var growHeightDifference = baseItem.item.expandedHeight - baseItem.item.collapsedHeight;
486+ if (growHeightDifference > shrinkHeightDifference) {
487+ runMaximizeAfterSizeChanges = 2;
488+ } else {
489+ runMaximizeAfterSizeChanges = 0;
490+ }
491+ }
492+ }
493+
494+ baseItem.expand(shouldExpand, animate);
495+ }
496+ }
497+ }
498+ }
499+
500 delegate: ListItems.Base {
501 id: baseItem
502 objectName: "dashCategory" + category
503@@ -175,6 +224,7 @@
504 readonly property string category: categoryId
505 readonly property string headerLink: model.headerLink
506 readonly property var item: rendererLoader.item
507+ readonly property var seeAll: seeAll
508
509 function expand(expand, animate) {
510 heightBehaviour.enabled = animate;
511@@ -194,13 +244,13 @@
512 // This can happen with the VJ that doesn't know how height it will be on creation
513 // so doesn't set expandable until a bit too late for onLoaded
514 if (expandable) {
515- var shouldExpand = baseItem === categoryView.expandedCategoryItem;
516+ var shouldExpand = baseItem.category === categoryView.expandedCategoryId;
517 baseItem.expand(shouldExpand, false /*animate*/);
518 }
519 }
520
521- onHeightChanged: rendererLoader.updateDelegateCreationRange();
522- onYChanged: rendererLoader.updateDelegateCreationRange();
523+ onHeightChanged: rendererLoader.updateRanges();
524+ onYChanged: rendererLoader.updateRanges();
525
526 Loader {
527 id: rendererLoader
528@@ -215,9 +265,23 @@
529 id: heightBehaviour
530 enabled: false
531 animation: UbuntuNumberAnimation {
532+ duration: UbuntuAnimation.FastDuration
533 onRunningChanged: {
534 if (!running) {
535 heightBehaviour.enabled = false
536+ if (categoryView.runMaximizeAfterSizeChanges > 0) {
537+ categoryView.runMaximizeAfterSizeChanges--;
538+ if (categoryView.runMaximizeAfterSizeChanges == 0) {
539+ var firstCreated = categoryView.firstCreatedIndex();
540+ for (var i = 0; i < categoryView.createdItemCount(); ++i) {
541+ var baseItem = categoryView.item(firstCreated + i);
542+ if (baseItem.category === categoryView.expandedCategoryId) {
543+ categoryView.maximizeVisibleArea(firstCreated + i, baseItem.item.expandedHeight + baseItem.seeAll.height);
544+ break;
545+ }
546+ }
547+ }
548+ }
549 }
550 }
551 }
552@@ -245,10 +309,10 @@
553 item.objectName = Qt.binding(function() { return categoryId })
554 item.scopeStyle = scopeView.scopeStyle;
555 if (baseItem.expandable) {
556- var shouldExpand = baseItem === categoryView.expandedCategoryItem;
557+ var shouldExpand = baseItem.category === categoryView.expandedCategoryId;
558 baseItem.expand(shouldExpand, false /*animate*/);
559 }
560- updateDelegateCreationRange();
561+ updateRanges();
562 if (scope && scope.id === "clickscope" && (categoryId === "predefined" || categoryId === "local")) {
563 // Yeah, hackish :/
564 cardTool.artShapeSize = Qt.size(units.gu(8), units.gu(7.5));
565@@ -303,13 +367,25 @@
566 }
567 }
568 }
569- onOriginYChanged: rendererLoader.updateDelegateCreationRange();
570- onContentYChanged: rendererLoader.updateDelegateCreationRange();
571- onHeightChanged: rendererLoader.updateDelegateCreationRange();
572- onContentHeightChanged: rendererLoader.updateDelegateCreationRange();
573- }
574-
575- function updateDelegateCreationRange() {
576+ onOriginYChanged: rendererLoader.updateRanges();
577+ onContentYChanged: rendererLoader.updateRanges();
578+ onHeightChanged: rendererLoader.updateRanges();
579+ onContentHeightChanged: rendererLoader.updateRanges();
580+ }
581+ Connections {
582+ target: scopeView
583+ onIsCurrentChanged: rendererLoader.updateRanges();
584+ }
585+ Connections {
586+ target: holdingList
587+ onMovingChanged: if (!moving) rendererLoader.updateRanges();
588+ }
589+
590+ function updateRanges() {
591+ if (holdingList && holdingList.moving) {
592+ return;
593+ }
594+
595 if (categoryView.moving) {
596 // Do not update the range if we are overshooting up or down, since we'll come back
597 // to the stable position and delete/create items without any reason
598@@ -321,10 +397,18 @@
599 }
600 }
601
602+ if (item && item.hasOwnProperty("visibleRangeBegin")) {
603+ item.visibleRangeBegin = Math.max(-baseItem.y, 0)
604+ item.visibleRangeEnd = item.visibleRangeBegin + Math.min(categoryView.height, rendererLoader.height)
605+ }
606+
607 if (item && item.hasOwnProperty("displayMarginBeginning")) {
608 // TODO do we need item.originY here, test 1300302 once we have a silo
609 // and we can run it on the phone
610- if (baseItem.y + baseItem.height <= 0) {
611+ if (scopeView.isCurrent) {
612+ item.displayMarginBeginning = 1073741823;
613+ item.displayMarginEnd = 1073741823;
614+ } else if (baseItem.y + baseItem.height <= 0) {
615 // Not visible (item at top of the list viewport)
616 item.displayMarginBeginning = -baseItem.height;
617 item.displayMarginEnd = 0;
618@@ -333,9 +417,9 @@
619 item.displayMarginBeginning = 0;
620 item.displayMarginEnd = -baseItem.height;
621 } else {
622- item.displayMarginBeginning = -Math.max(-baseItem.y, 0);
623- item.displayMarginEnd = -Math.max(baseItem.height - seeAll.height
624- - categoryView.height + baseItem.y, 0)
625+ item.displayMarginBeginning = Math.round(-Math.max(-baseItem.y, 0));
626+ item.displayMarginEnd = -Math.round(Math.max(baseItem.height - seeAll.height
627+ - categoryView.height + baseItem.y, 0));
628 }
629 }
630 }
631@@ -352,10 +436,11 @@
632 height: seeAllLabel.visible ? seeAllLabel.font.pixelSize + units.gu(4) : 0
633
634 onClicked: {
635- if (categoryView.expandedCategoryItem !== baseItem) {
636- categoryView.expandedCategoryItem = baseItem;
637+ if (categoryView.expandedCategoryId !== baseItem.category) {
638+ categoryView.expandedCategoryId = baseItem.category;
639+ floatingSeeLess.companionBase = baseItem;
640 } else {
641- categoryView.expandedCategoryItem = null;
642+ categoryView.expandedCategoryId = "";
643 }
644 }
645
646@@ -455,7 +540,7 @@
647 objectName: "floatingSeeLess"
648
649 property Item companionTo: companionBase ? companionBase.seeAllButton : null
650- property Item companionBase: categoryView.expandedCategoryItem
651+ property Item companionBase: null
652 property bool showBecausePosition: false
653 property real yOffset: 0
654
655@@ -467,7 +552,7 @@
656 height: seeLessLabel.font.pixelSize + units.gu(4)
657 visible: companionTo && showBecausePosition
658
659- onClicked: categoryView.expandedCategoryItem = null;
660+ onClicked: categoryView.expandedCategoryId = "";
661
662 function updateVisibility() {
663 var companionPos = companionTo.mapToItem(floatingSeeLess, 0, 0);
664@@ -476,6 +561,10 @@
665 var posToBase = floatingSeeLess.mapToItem(companionBase, 0, -yOffset).y;
666 yOffset = Math.max(0, companionBase.item.collapsedHeight - posToBase);
667 yOffset = Math.min(yOffset, height);
668+
669+ if (!showBecausePosition && categoryView.expandedCategoryId === "") {
670+ companionBase = null;
671+ }
672 }
673
674 Label {
675
676=== modified file 'qml/Dash/ScopeListView.qml'
677--- qml/Dash/ScopeListView.qml 2014-07-23 06:54:10 +0000
678+++ qml/Dash/ScopeListView.qml 2014-09-11 16:03:35 +0000
679@@ -20,4 +20,5 @@
680 ListViewWithPageHeader {
681 maximumFlickVelocity: height * 10
682 flickDeceleration: height * 2
683+ cacheBuffer: Number.MAX_VALUE
684 }
685
686=== modified file 'qml/Dash/ScopesOverviewAll.qml'
687--- qml/Dash/ScopesOverviewAll.qml 2014-07-25 08:47:40 +0000
688+++ qml/Dash/ScopesOverviewAll.qml 2014-09-11 16:03:35 +0000
689@@ -43,6 +43,8 @@
690 id: cardGrid
691 width: root.width
692 height: parent.height
693+ visibleRangeBegin: root.contentY
694+ visibleRangeEnd: root.contentY + root.height
695
696 onClicked: {
697 root.clicked(index, result, item, itemModel);
698
699=== modified file 'qml/Dash/ScopesOverviewFavorites.qml'
700--- qml/Dash/ScopesOverviewFavorites.qml 2014-07-30 10:14:35 +0000
701+++ qml/Dash/ScopesOverviewFavorites.qml 2014-09-11 16:03:35 +0000
702@@ -61,7 +61,7 @@
703 item.cardData = Qt.binding(function() { return model; });
704 item.template = Qt.binding(function() { return cardTool.template; });
705 item.components = Qt.binding(function() { return cardTool.components; });
706- item.headerAlignment = Qt.binding(function() { return cardTool.headerAlignment; });
707+ item.titleAlignment = Qt.binding(function() { return cardTool.titleAlignment; });
708 }
709
710 Connections {
711
712=== modified file 'tests/autopilot/unity8/shell/emulators/dash.py'
713--- tests/autopilot/unity8/shell/emulators/dash.py 2014-08-25 16:07:45 +0000
714+++ tests/autopilot/unity8/shell/emulators/dash.py 2014-09-11 16:03:35 +0000
715@@ -93,7 +93,7 @@
716 'No scope found with id {0}'.format(scope_id))
717
718 def _get_scope_from_loader(self, loader):
719- return loader.get_children()[0]
720+ return loader.wait_select_single('GenericScopeView');
721
722 def _open_scope_scrolling(self, scope_loader):
723 scroll = self._get_scroll_direction(scope_loader)
724@@ -102,8 +102,8 @@
725 scroll()
726 self.dash_content_list.moving.wait_for(False)
727
728+ scope_loader.isCurrent.wait_for(True)
729 scope = self._get_scope_from_loader(scope_loader)
730- scope.isCurrent.wait_for(True)
731 return scope
732
733 def _get_scroll_direction(self, scope_loader):
734
735=== modified file 'tests/mocks/Ubuntu/CMakeLists.txt'
736--- tests/mocks/Ubuntu/CMakeLists.txt 2014-08-25 10:05:13 +0000
737+++ tests/mocks/Ubuntu/CMakeLists.txt 2014-09-11 16:03:35 +0000
738@@ -1,3 +1,4 @@
739+add_subdirectory(Connectivity)
740 add_subdirectory(DownloadDaemonListener)
741 add_subdirectory(Payments)
742 add_subdirectory(SystemImage)
743
744=== added directory 'tests/mocks/Ubuntu/Connectivity'
745=== added file 'tests/mocks/Ubuntu/Connectivity/CMakeLists.txt'
746--- tests/mocks/Ubuntu/Connectivity/CMakeLists.txt 1970-01-01 00:00:00 +0000
747+++ tests/mocks/Ubuntu/Connectivity/CMakeLists.txt 2014-09-11 16:03:35 +0000
748@@ -0,0 +1,10 @@
749+add_library(connectivity-qml SHARED
750+ networking-status.cpp
751+ plugin.cpp
752+)
753+qt5_use_modules(connectivity-qml Qml)
754+
755+# copy qmldir file into build directory for shadow builds
756+file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/qmldir"
757+ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
758+ )
759
760=== added file 'tests/mocks/Ubuntu/Connectivity/networking-status.cpp'
761--- tests/mocks/Ubuntu/Connectivity/networking-status.cpp 1970-01-01 00:00:00 +0000
762+++ tests/mocks/Ubuntu/Connectivity/networking-status.cpp 2014-09-11 16:03:35 +0000
763@@ -0,0 +1,65 @@
764+/*
765+ * Copyright © 2013 Canonical Ltd.
766+ *
767+ * This program is free software: you can redistribute it and/or modify it
768+ * under the terms of the GNU Lesser General Public License version 3,
769+ * as published by the Free Software Foundation.
770+ *
771+ * This program is distributed in the hope that it will be useful,
772+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
773+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
774+ * GNU Lesser General Public License for more details.
775+ *
776+ * You should have received a copy of the GNU Lesser General Public License
777+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
778+ *
779+ * Authors:
780+ * Antti Kaijanmäki <antti.kaijanmaki@canonical.com>
781+ */
782+
783+#include "networking-status.h"
784+
785+NetworkingStatus::NetworkingStatus(QObject *parent)
786+ : QObject(parent)
787+{
788+
789+ qRegisterMetaType<NetworkingStatus::Limitations>();
790+ qRegisterMetaType<QVector<NetworkingStatus::Limitations>>();
791+ qRegisterMetaType<NetworkingStatus::Status>();
792+}
793+
794+NetworkingStatus::~NetworkingStatus()
795+{}
796+
797+QVector<NetworkingStatus::Limitations>
798+NetworkingStatus::limitations() const
799+{
800+ return m_limitations;
801+}
802+
803+NetworkingStatus::Status
804+NetworkingStatus::status() const
805+{
806+ return Status::Online;
807+}
808+
809+bool
810+NetworkingStatus::online() const
811+{
812+ return status() == Status::Online;
813+}
814+
815+bool
816+NetworkingStatus::limitedBandwith() const
817+{
818+ return limitations().contains(Limitations::Bandwith);
819+}
820+
821+void NetworkingStatus::setLimitedBandwidth(bool limited)
822+{
823+ if (limited) {
824+ m_limitations << Limitations::Bandwith;
825+ } else if (limitedBandwith()) {
826+ m_limitations.remove(m_limitations.indexOf(Limitations::Bandwith));
827+ }
828+}
829
830=== added file 'tests/mocks/Ubuntu/Connectivity/networking-status.h'
831--- tests/mocks/Ubuntu/Connectivity/networking-status.h 1970-01-01 00:00:00 +0000
832+++ tests/mocks/Ubuntu/Connectivity/networking-status.h 2014-09-11 16:03:35 +0000
833@@ -0,0 +1,73 @@
834+/*
835+ * Copyright © 2014 Canonical Ltd.
836+ *
837+ * This program is free software: you can redistribute it and/or modify it
838+ * under the terms of the GNU Lesser General Public License version 3,
839+ * as published by the Free Software Foundation.
840+ *
841+ * This program is distributed in the hope that it will be useful,
842+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
843+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
844+ * GNU Lesser General Public License for more details.
845+ *
846+ * You should have received a copy of the GNU Lesser General Public License
847+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
848+ *
849+ */
850+
851+#ifndef FAKE_NETWORKING_STATUS_H
852+#define FAKE_NETWORKING_STATUS_H
853+
854+#include <QObject>
855+#include <QVector>
856+
857+class Q_DECL_EXPORT NetworkingStatus : public QObject
858+{
859+ Q_OBJECT
860+ Q_DISABLE_COPY(NetworkingStatus)
861+
862+ Q_ENUMS(Limitations)
863+ Q_ENUMS(Status)
864+
865+ Q_PROPERTY(QVector<Limitations> limitations READ limitations NOTIFY limitationsChanged)
866+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
867+ Q_PROPERTY(bool online READ online NOTIFY onlineChanged)
868+ Q_PROPERTY(bool limitedBandwith READ limitedBandwith WRITE setLimitedBandwidth NOTIFY limitedBandwithChanged)
869+
870+public:
871+ explicit NetworkingStatus(QObject *parent = 0);
872+ virtual ~NetworkingStatus();
873+
874+ enum Limitations {
875+ Bandwith
876+ };
877+
878+ enum Status {
879+ Offline,
880+ Connecting,
881+ Online
882+ };
883+
884+ QVector<Limitations> limitations() const;
885+ Status status() const;
886+ bool online() const;
887+ bool limitedBandwith() const;
888+
889+ // Only in the fake one
890+ void setLimitedBandwidth(bool limited);
891+
892+Q_SIGNALS:
893+ void limitationsChanged();
894+ void statusChanged(Status value);
895+ void onlineChanged(bool value);
896+ void limitedBandwithChanged(bool value);
897+
898+private:
899+ QVector<NetworkingStatus::Limitations> m_limitations;
900+};
901+
902+Q_DECLARE_METATYPE(NetworkingStatus::Limitations)
903+Q_DECLARE_METATYPE(QVector<NetworkingStatus::Limitations>)
904+Q_DECLARE_METATYPE(NetworkingStatus::Status)
905+
906+#endif // FAKE_NETWORKING_STATUS_H
907
908=== added file 'tests/mocks/Ubuntu/Connectivity/plugin.cpp'
909--- tests/mocks/Ubuntu/Connectivity/plugin.cpp 1970-01-01 00:00:00 +0000
910+++ tests/mocks/Ubuntu/Connectivity/plugin.cpp 2014-09-11 16:03:35 +0000
911@@ -0,0 +1,46 @@
912+/*
913+ * Copyright © 2014 Canonical Ltd.
914+ *
915+ * This program is free software: you can redistribute it and/or modify it
916+ * under the terms of the GNU Lesser General Public License version 3,
917+ * as published by the Free Software Foundation.
918+ *
919+ * This program is distributed in the hope that it will be useful,
920+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
921+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
922+ * GNU Lesser General Public License for more details.
923+ *
924+ * You should have received a copy of the GNU Lesser General Public License
925+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
926+ *
927+ * Authors:
928+ * Antti Kaijanmäki <antti.kaijanmaki@canonical.com>
929+ */
930+
931+#include "plugin.h"
932+
933+#include <QtQml>
934+
935+#include "networking-status.h"
936+
937+static QObject *
938+networkingStatusSingletonProvider(QQmlEngine *engine, QJSEngine *scriptEngine)
939+{
940+ Q_UNUSED(scriptEngine)
941+
942+ return new NetworkingStatus(engine);
943+}
944+
945+void
946+QmlConnectivityNetworkingPlugin::registerTypes(const char *uri)
947+{
948+ // @uri Ubuntu.Connectivity
949+ qmlRegisterSingletonType<NetworkingStatus>(uri, 1, 0, "NetworkingStatus", networkingStatusSingletonProvider);
950+}
951+
952+void
953+QmlConnectivityNetworkingPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
954+{
955+ Q_UNUSED(uri);
956+ Q_UNUSED(engine);
957+}
958
959=== added file 'tests/mocks/Ubuntu/Connectivity/plugin.h'
960--- tests/mocks/Ubuntu/Connectivity/plugin.h 1970-01-01 00:00:00 +0000
961+++ tests/mocks/Ubuntu/Connectivity/plugin.h 2014-09-11 16:03:35 +0000
962@@ -0,0 +1,35 @@
963+/*
964+ * Copyright © 2014 Canonical Ltd.
965+ *
966+ * This program is free software: you can redistribute it and/or modify it
967+ * under the terms of the GNU Lesser General Public License version 3,
968+ * as published by the Free Software Foundation.
969+ *
970+ * This program is distributed in the hope that it will be useful,
971+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
972+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
973+ * GNU Lesser General Public License for more details.
974+ *
975+ * You should have received a copy of the GNU Lesser General Public License
976+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
977+ *
978+ * Authors:
979+ * Antti Kaijanmäki <antti.kaijanmaki@canonical.com>
980+ */
981+
982+#ifndef QML_CONNECTIVITY_PLUGIN_H
983+#define QML_CONNECTIVITY_PLUGIN_H
984+
985+#include <QQmlExtensionPlugin>
986+
987+class QmlConnectivityNetworkingPlugin : public QQmlExtensionPlugin {
988+ Q_OBJECT
989+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
990+ Q_INTERFACES(QQmlExtensionInterface)
991+
992+public:
993+ void registerTypes(const char *uri);
994+ void initializeEngine(QQmlEngine *engine, const char *uri);
995+};
996+
997+#endif // QML_CONNECTIVITY_PLUGIN_H
998
999=== added file 'tests/mocks/Ubuntu/Connectivity/qmldir'
1000--- tests/mocks/Ubuntu/Connectivity/qmldir 1970-01-01 00:00:00 +0000
1001+++ tests/mocks/Ubuntu/Connectivity/qmldir 2014-09-11 16:03:35 +0000
1002@@ -0,0 +1,2 @@
1003+module Ubuntu.Connectivity
1004+plugin connectivity-qml
1005
1006=== modified file 'tests/mocks/Unity/fake_categories.cpp'
1007--- tests/mocks/Unity/fake_categories.cpp 2014-08-15 14:21:42 +0000
1008+++ tests/mocks/Unity/fake_categories.cpp 2014-09-11 16:03:35 +0000
1009@@ -29,25 +29,12 @@
1010
1011 int Categories::rowCount(const QModelIndex& /*parent*/) const
1012 {
1013- return m_category_count + m_specialCategories.count();
1014+ return m_category_count;
1015 }
1016
1017-void Categories::addSpecialCategory(QString const& categoryId, QString const& name, QString const& icon, QString const& rawTemplate, QObject* countObject)
1018+void Categories::addSpecialCategory(QString const& /*categoryId*/, QString const& /*name*/, QString const& /*icon*/, QString const& /*rawTemplate*/, QObject* /*countObject*/)
1019 {
1020- CategoryData catData;
1021- catData.categoryId = categoryId;
1022- catData.name = name;
1023- catData.icon = icon;
1024- catData.rawTemplate = rawTemplate;
1025- catData.countObject = countObject;
1026-
1027- beginInsertRows(QModelIndex(), 0, 0);
1028- m_specialCategories.prepend(catData);
1029- endInsertRows();
1030-
1031- if (countObject) {
1032- connect(countObject, SIGNAL(countChanged()), this, SLOT(countChanged()));
1033- }
1034+ qFatal("Using un-implemented Categories::addSpecialCategory");
1035 }
1036
1037 bool Categories::overrideCategoryJson(QString const& /* categoryId */, QString const& /* json */)
1038@@ -55,23 +42,6 @@
1039 qFatal("Using un-implemented Categories::overrideCategoryJson");
1040 }
1041
1042-void Categories::countChanged()
1043-{
1044- QObject* countObject = sender();
1045-
1046- for (int i = 0; i < m_specialCategories.count(); ++i) {
1047- const CategoryData &catData = m_specialCategories.at(i);
1048- if (catData.countObject == countObject) {
1049- QVector<int> roles;
1050- roles.append(RoleCount);
1051-
1052- QModelIndex changedIndex(index(i));
1053- dataChanged(changedIndex, changedIndex, roles);
1054- break;
1055- }
1056- }
1057-}
1058-
1059 QVariant
1060 Categories::data(const QModelIndex& index, int role) const
1061 {
1062@@ -79,115 +49,74 @@
1063 return QVariant();
1064 }
1065
1066- ResultsModel *resultsModel = m_resultsModels[index.row()];
1067- if (!resultsModel) {
1068- resultsModel = new ResultsModel(15, index.row());
1069- m_resultsModels[index.row()] = resultsModel;
1070- }
1071- if (index.row() < m_specialCategories.count()) {
1072- const CategoryData &catData = m_specialCategories.at(index.row());
1073- switch (role) {
1074- case RoleCategoryId:
1075- return catData.categoryId;
1076- case RoleName:
1077- return catData.name;
1078- case RoleIcon:
1079- return catData.icon;
1080- case RoleRawRendererTemplate:
1081- return catData.rawTemplate;
1082- case RoleRenderer:
1083- {
1084- QVariantMap map;
1085- if (index.row() % 2 == 0) {
1086- map["category-layout"] = "grid";
1087- } else {
1088- map["category-layout"] = "carousel";
1089- map["overlay"] = true;
1090- }
1091- map["card-size"] = "small";
1092- return map;
1093- }
1094- case RoleComponents:
1095- {
1096- QVariantMap map, artMap, attributeMap;
1097+ ResultsModel *resultsModel = resultModel(index.row());
1098+ switch (role) {
1099+ case RoleCategoryId:
1100+ return QString("%1").arg(index.row());
1101+ case RoleName:
1102+ return QString("Category %1").arg(index.row());
1103+ case RoleIcon:
1104+ return "gtk-apply";
1105+ case RoleRawRendererTemplate:
1106+ qFatal("Using un-implemented RoleRawRendererTemplate Categories role");
1107+ return QVariant();
1108+ case RoleRenderer:
1109+ {
1110+ QVariantMap map;
1111+ if (index.row() % 2 == 0) {
1112+ map["category-layout"] = "grid";
1113+ } else {
1114+ map["category-layout"] = "carousel";
1115+ }
1116+ if (index.row() == 18) {
1117+ map["category-layout"] = "horizontal-list";
1118+ }
1119+ if (index.row() == 19) {
1120+ map["category-layout"] = "grid";
1121+ map["collapsed-rows"] = 0;
1122+ }
1123+ map["card-size"] = "small";
1124+
1125+ map["category-layout"] = m_layouts.value(index.row(), map["category-layout"].toString());
1126+
1127+ if (map["category-layout"] == "carousel") {
1128+ map["overlay"] = true;
1129+ }
1130+
1131+ return map;
1132+ }
1133+ case RoleComponents:
1134+ {
1135+ QVariantMap map, artMap, attributeMap;
1136+ if (index.row() % 2 != 0) {
1137+ artMap["aspect-ratio"] = QString("1.%1").arg(index.row());
1138+ } else {
1139 artMap["aspect-ratio"] = "1.0";
1140- artMap["field"] = "art";
1141- map["art"] = artMap;
1142- map["title"] = "HOLA";
1143- attributeMap["field"] = "attribute";
1144- map["attributes"] = attributeMap;
1145- return map;
1146- }
1147- case RoleHeaderLink:
1148- return QString();
1149- case RoleResults:
1150- return QVariant();
1151- case RoleCount:
1152- return catData.countObject->property("count");
1153- default:
1154- qFatal("Using un-implemented Categories role");
1155- return QVariant();
1156- }
1157- } else {
1158- switch (role) {
1159- case RoleCategoryId:
1160- return QString("%1").arg(index.row());
1161- case RoleName:
1162- return QString("Category %1").arg(index.row());
1163- case RoleIcon:
1164- return "gtk-apply";
1165- case RoleRawRendererTemplate:
1166- qFatal("Using un-implemented RoleRawRendererTemplate Categories role");
1167- return QVariant();
1168- case RoleRenderer:
1169- {
1170- QVariantMap map;
1171- if (index.row() % 2 == 0) {
1172- map["category-layout"] = "grid";
1173- } else {
1174- map["category-layout"] = "carousel";
1175- map["card-size"] = "medium";
1176- map["overlay"] = true;
1177- }
1178- if (index.row() == 18) {
1179- map["category-layout"] = "horizontal-list";
1180- }
1181- if (index.row() == 19) {
1182- map["category-layout"] = "grid";
1183- map["collapsed-rows"] = 0;
1184- }
1185- map["card-size"] = "small";
1186- return map;
1187- }
1188- case RoleComponents:
1189- {
1190- QVariantMap map, artMap, attributeMap;
1191- if (index.row() % 2 != 0) {
1192- artMap["aspect-ratio"] = QString("1.%1").arg(index.row());
1193- } else {
1194- artMap["aspect-ratio"] = "1.0";
1195- }
1196- artMap["field"] = "art";
1197- map["art"] = artMap;
1198- map["title"] = "HOLA";
1199- map["subtitle"] = "HOLA";
1200- attributeMap["field"] = "attribute";
1201- map["attributes"] = attributeMap;
1202- return map;
1203- }
1204- case RoleHeaderLink:
1205- if (index.row() == 1 || index.row() == 4) {
1206- return QString("scope://query/1");
1207- }
1208- return QString();
1209- case RoleResults:
1210- return QVariant::fromValue(resultsModel);
1211- case RoleCount:
1212- return resultsModel->rowCount();
1213- default:
1214- qFatal("Using un-implemented Categories role");
1215- return QVariant();
1216- }
1217+ }
1218+ artMap["field"] = "art";
1219+ map["art"] = artMap;
1220+ map["title"] = "HOLA";
1221+ map["subtitle"] = "HOLA";
1222+ attributeMap["field"] = "attribute";
1223+ map["attributes"] = attributeMap;
1224+ return map;
1225+ }
1226+ case RoleHeaderLink:
1227+ {
1228+ QString res;
1229+ if (index.row() == 1 || index.row() == 4) {
1230+ res = QString("scope://query/1");
1231+ }
1232+ res = m_headerLinks.value(index.row(), res);
1233+ return res;
1234+ }
1235+ case RoleResults:
1236+ return QVariant::fromValue(resultsModel);
1237+ case RoleCount:
1238+ return resultsModel->rowCount();
1239+ default:
1240+ qFatal("Using un-implemented Categories role");
1241+ return QVariant();
1242 }
1243 }
1244
1245@@ -196,3 +125,33 @@
1246 {
1247 return data(index(row, 0), role);
1248 }
1249+
1250+void Categories::setCount(int count)
1251+{
1252+ if (m_category_count != count) {
1253+ beginResetModel(); // This is just for test setup so we can be lazy and reset
1254+ m_category_count = count;
1255+ endResetModel();
1256+ }
1257+}
1258+
1259+ResultsModel* Categories::resultModel(int row) const
1260+{
1261+ ResultsModel *result = m_resultsModels[row];
1262+ if (!result) {
1263+ Categories *that = const_cast<Categories*>(this);
1264+ result = new ResultsModel(15, row, that);
1265+ m_resultsModels[row] = result;
1266+ }
1267+ return result;
1268+}
1269+
1270+void Categories::setLayout(int row, const QString &layout)
1271+{
1272+ m_layouts[row] = layout;
1273+}
1274+
1275+void Categories::setHeaderLink(int row, const QString &headerLink)
1276+{
1277+ m_headerLinks[row] = headerLink;
1278+}
1279
1280=== modified file 'tests/mocks/Unity/fake_categories.h'
1281--- tests/mocks/Unity/fake_categories.h 2014-07-11 16:39:33 +0000
1282+++ tests/mocks/Unity/fake_categories.h 2014-09-11 16:03:35 +0000
1283@@ -39,22 +39,17 @@
1284
1285 Q_INVOKABLE QVariant data(int row, int role) const;
1286
1287-private Q_SLOTS:
1288- void countChanged();
1289+ // For testing purposes
1290+ Q_INVOKABLE void setCount(int count);
1291+ Q_INVOKABLE ResultsModel* resultModel(int row) const;
1292+ Q_INVOKABLE void setLayout(int row, const QString &layout);
1293+ Q_INVOKABLE void setHeaderLink(int row, const QString &headerLink);
1294
1295 private:
1296 mutable QHash<int, ResultsModel*> m_resultsModels;
1297+ QHash<int, QString> m_layouts;
1298+ QHash<int, QString> m_headerLinks;
1299 int m_category_count;
1300-
1301- struct CategoryData {
1302- QString categoryId;
1303- QString name;
1304- QString icon;
1305- QString rawTemplate;
1306- QObject* countObject;
1307- };
1308-
1309- QList<CategoryData> m_specialCategories;
1310 };
1311
1312 #endif // FAKE_CATEGORIES_H
1313
1314=== modified file 'tests/mocks/Unity/fake_resultsmodel.cpp'
1315--- tests/mocks/Unity/fake_resultsmodel.cpp 2014-08-13 16:06:40 +0000
1316+++ tests/mocks/Unity/fake_resultsmodel.cpp 2014-09-11 16:03:35 +0000
1317@@ -44,6 +44,15 @@
1318 qFatal("Calling un-implemented ResultsModel::setCategoryId");
1319 }
1320
1321+void ResultsModel::setResultCount(int result_count)
1322+{
1323+ if (m_result_count != result_count) {
1324+ beginResetModel(); // This is just for test setup so we can be lazy and reset
1325+ m_result_count = result_count;
1326+ endResetModel();
1327+ }
1328+}
1329+
1330 int ResultsModel::rowCount(const QModelIndex& parent) const
1331 {
1332 Q_UNUSED(parent);
1333
1334=== modified file 'tests/mocks/Unity/fake_resultsmodel.h'
1335--- tests/mocks/Unity/fake_resultsmodel.h 2014-08-11 09:57:29 +0000
1336+++ tests/mocks/Unity/fake_resultsmodel.h 2014-09-11 16:03:35 +0000
1337@@ -41,6 +41,9 @@
1338 /* setters */
1339 void setCategoryId(QString const& id) override;
1340
1341+ // For testing purposes
1342+ Q_INVOKABLE void setResultCount(int result_count);
1343+
1344 private:
1345 int m_result_count;
1346 int m_categoryId;
1347
1348=== modified file 'tests/mocks/Unity/fake_scope.cpp'
1349--- tests/mocks/Unity/fake_scope.cpp 2014-08-27 08:01:40 +0000
1350+++ tests/mocks/Unity/fake_scope.cpp 2014-09-11 16:03:35 +0000
1351@@ -145,6 +145,23 @@
1352 Q_EMIT favoriteChanged();
1353 }
1354 }
1355+
1356+void Scope::setId(const QString &id)
1357+{
1358+ if (id != m_id) {
1359+ m_id = id;
1360+ Q_EMIT idChanged();
1361+ }
1362+}
1363+
1364+void Scope::setName(const QString &name)
1365+{
1366+ if (name != m_name) {
1367+ m_name = name;
1368+ Q_EMIT nameChanged();
1369+ }
1370+}
1371+
1372 void Scope::setSearchInProgress(const bool inProg)
1373 {
1374 if (inProg != m_searching) {
1375
1376=== modified file 'tests/mocks/Unity/fake_scope.h'
1377--- tests/mocks/Unity/fake_scope.h 2014-08-12 12:09:49 +0000
1378+++ tests/mocks/Unity/fake_scope.h 2014-09-11 16:03:35 +0000
1379@@ -56,6 +56,8 @@
1380 void setFormFactor(const QString& form_factor) override;
1381 void setActive(const bool) override;
1382 void setFavorite(const bool) override;
1383+ Q_INVOKABLE void setId(const QString &id); // This is not invokable in the Interface, here for testing benefits
1384+ Q_INVOKABLE void setName(const QString &name); // This is not invokable in the Interface, here for testing benefits
1385 Q_INVOKABLE void setSearchInProgress(const bool inProg); // This is not invokable in the Interface, here for testing benefits
1386
1387 Q_INVOKABLE void activate(QVariant const& result) override;
1388
1389=== modified file 'tests/plugins/Dash/CMakeLists.txt'
1390--- tests/plugins/Dash/CMakeLists.txt 2014-07-22 10:03:37 +0000
1391+++ tests/plugins/Dash/CMakeLists.txt 2014-09-11 16:03:35 +0000
1392@@ -32,7 +32,7 @@
1393 qt5_use_modules(${TESTNAME}TestExec Test Core Qml)
1394 target_link_libraries(${TESTNAME}TestExec ${Qt5Gui_LIBRARIES} ${Qt5Quick_LIBRARIES})
1395
1396- add_binary_qml_test(${TESTNAME} "" "Dash-qml")
1397+ add_binary_qml_test(${TESTNAME} "" "Dash-qml" "")
1398 endmacro()
1399
1400 add_lvwph_test(listviewwithpageheader ListViewWithPageHeader)
1401@@ -48,7 +48,7 @@
1402 qt5_use_modules(${TESTNAME}TestExec Test Core Qml)
1403 target_link_libraries(${TESTNAME}TestExec ${Qt5Gui_LIBRARIES} ${Qt5Quick_LIBRARIES})
1404
1405- add_binary_qml_test(${TESTNAME} "" "Dash-qml")
1406+ add_binary_qml_test(${TESTNAME} "" "Dash-qml" "")
1407
1408 add_executable(${TESTNAME}tryExec
1409 ${FILENAME}try.cpp
1410@@ -71,7 +71,7 @@
1411 add_executable(CardCreatorTestExec cardcreatortest.cpp)
1412 qt5_use_modules(CardCreatorTestExec Test Core Qml)
1413 target_link_libraries(CardCreatorTestExec ${Qt5Gui_LIBRARIES} ${Qt5Quick_LIBRARIES})
1414-add_binary_qml_test(CardCreator "" "Dash-qml")
1415+add_binary_qml_test(CardCreator "" "Dash-qml" "QML2_IMPORT_PATH=${CMAKE_BINARY_DIR}/tests/mocks/")
1416
1417 # plain qml test
1418 set(qmltest_DEFAULT_TARGETS qmluitests)
1419
1420=== modified file 'tests/plugins/Dash/cardcreator/1.res'
1421--- tests/plugins/Dash/cardcreator/1.res 2014-08-13 10:29:21 +0000
1422+++ tests/plugins/Dash/cardcreator/1.res 2014-09-11 16:03:35 +0000
1423@@ -6,7 +6,7 @@
1424 property var artShapeBorderSource: undefined;
1425 property real fontScale: 1.0;
1426 property var scopeStyle: null;
1427- property int headerAlignment: Text.AlignLeft;
1428+ property int titleAlignment: Text.AlignLeft;
1429 property int fixedHeaderHeight: -1;
1430 property size fixedArtShapeSize: Qt.size(-1, -1);
1431 readonly property string title: cardData && cardData["title"] || "";
1432@@ -46,7 +46,8 @@
1433 }
1434 image: Image {
1435 objectName: "artImage";
1436- source: cardData && cardData["art"] || "";
1437+ property bool doLoadSource: !NetworkingStatus.limitedBandwith;
1438+ source: { if (root.visible) doLoadSource = true; return doLoadSource && cardData && cardData["art"] || ""; }
1439 cache: true;
1440 asynchronous: root.asynchronous;
1441 fillMode: Image.PreserveAspectCrop;
1442@@ -68,13 +69,13 @@
1443 elide: Text.ElideRight;
1444 fontSize: "small";
1445 wrapMode: Text.Wrap;
1446- maximumLineCount: 2;
1447+ maximumLineCount: horizontalAlignment === Text.AlignHCenter ? 1 : 2;
1448 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
1449 color: root.scopeStyle ? root.scopeStyle.foreground : Theme.palette.normal.baseText;
1450 visible: showHeader ;
1451 text: root.title;
1452- font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
1453- horizontalAlignment: root.headerAlignment;
1454+ font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
1455+ horizontalAlignment: root.titleAlignment;
1456 }
1457 UbuntuShape {
1458 id: touchdown;
1459
1460=== modified file 'tests/plugins/Dash/cardcreator/2.res'
1461--- tests/plugins/Dash/cardcreator/2.res 2014-08-29 08:31:22 +0000
1462+++ tests/plugins/Dash/cardcreator/2.res 2014-09-11 16:03:35 +0000
1463@@ -6,7 +6,7 @@
1464 property var artShapeBorderSource: undefined;
1465 property real fontScale: 1.0;
1466 property var scopeStyle: null;
1467- property int headerAlignment: Text.AlignLeft;
1468+ property int titleAlignment: Text.AlignLeft;
1469 property int fixedHeaderHeight: -1;
1470 property size fixedArtShapeSize: Qt.size(-1, -1);
1471 readonly property string title: cardData && cardData["title"] || "";
1472@@ -67,7 +67,8 @@
1473 objectName: "mascotImage";
1474 anchors { verticalCenter: parent.verticalCenter; }
1475 readonly property int maxSize: Math.max(width, height) * 4;
1476- source: cardData && cardData["mascot"] || "";
1477+ property bool doLoadSource: !NetworkingStatus.limitedBandwith;
1478+ source: { if (root.visible) doLoadSource = true; return doLoadSource && cardData && cardData["mascot"] || ""; }
1479 width: units.gu(6);
1480 height: units.gu(5.625);
1481 sourceSize { width: maxSize; height: maxSize }
1482@@ -92,13 +93,13 @@
1483 elide: Text.ElideRight;
1484 fontSize: "small";
1485 wrapMode: Text.Wrap;
1486- maximumLineCount: 2;
1487+ maximumLineCount: horizontalAlignment === Text.AlignHCenter ? 1 : 2;
1488 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
1489 color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
1490 visible: showHeader ;
1491 text: root.title;
1492- font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
1493- horizontalAlignment: root.headerAlignment;
1494+ font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
1495+ horizontalAlignment: root.titleAlignment;
1496 }
1497 ,Label {
1498 id: subtitleLabel;
1499@@ -110,13 +111,12 @@
1500 }
1501 anchors.topMargin: units.dp(2);
1502 elide: Text.ElideRight;
1503- fontSize: "small";
1504+ fontSize: "x-small";
1505 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
1506 color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
1507 visible: titleLabel.visible && titleLabel.text;
1508 text: cardData && cardData["subtitle"] || "";
1509 font.weight: Font.Light;
1510- horizontalAlignment: root.headerAlignment;
1511 }
1512
1513 ]
1514
1515=== modified file 'tests/plugins/Dash/cardcreator/3.res'
1516--- tests/plugins/Dash/cardcreator/3.res 2014-08-13 10:29:21 +0000
1517+++ tests/plugins/Dash/cardcreator/3.res 2014-09-11 16:03:35 +0000
1518@@ -6,7 +6,7 @@
1519 property var artShapeBorderSource: undefined;
1520 property real fontScale: 1.0;
1521 property var scopeStyle: null;
1522- property int headerAlignment: Text.AlignLeft;
1523+ property int titleAlignment: Text.AlignLeft;
1524 property int fixedHeaderHeight: -1;
1525 property size fixedArtShapeSize: Qt.size(-1, -1);
1526 readonly property string title: cardData && cardData["title"] || "";
1527@@ -46,8 +46,9 @@
1528 }
1529 image: Image {
1530 objectName: "artImage";
1531- source: cardData && cardData["art"] || "";
1532- cache: true;
1533+ property bool doLoadSource: !NetworkingStatus.limitedBandwith;
1534+ source: { if (root.visible) doLoadSource = true; return doLoadSource && cardData && cardData["art"] || ""; }
1535+ cache: true;
1536 asynchronous: root.asynchronous;
1537 fillMode: Image.PreserveAspectCrop;
1538 width: root.width;
1539@@ -68,13 +69,13 @@
1540 elide: Text.ElideRight;
1541 fontSize: "small";
1542 wrapMode: Text.Wrap;
1543- maximumLineCount: 2;
1544+ maximumLineCount: horizontalAlignment === Text.AlignHCenter ? 1 : 2;
1545 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
1546 color: root.scopeStyle ? root.scopeStyle.foreground : Theme.palette.normal.baseText;
1547 visible: showHeader ;
1548 text: root.title;
1549- font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
1550- horizontalAlignment: root.headerAlignment;
1551+ font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
1552+ horizontalAlignment: root.titleAlignment;
1553 }
1554 Label {
1555 id: subtitleLabel;
1556@@ -86,13 +87,12 @@
1557 }
1558 anchors.topMargin: units.dp(2);
1559 elide: Text.ElideRight;
1560- fontSize: "small";
1561+ fontSize: "x-small";
1562 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
1563 color: root.scopeStyle ? root.scopeStyle.foreground : Theme.palette.normal.baseText;
1564 visible: titleLabel.visible && titleLabel.text;
1565 text: cardData && cardData["subtitle"] || "";
1566 font.weight: Font.Light;
1567- horizontalAlignment: root.headerAlignment;
1568 }
1569 UbuntuShape {
1570 id: touchdown;
1571
1572=== modified file 'tests/plugins/Dash/cardcreator/4.res'
1573--- tests/plugins/Dash/cardcreator/4.res 2014-08-13 10:29:21 +0000
1574+++ tests/plugins/Dash/cardcreator/4.res 2014-09-11 16:03:35 +0000
1575@@ -6,7 +6,7 @@
1576 property var artShapeBorderSource: undefined;
1577 property real fontScale: 1.0;
1578 property var scopeStyle: null;
1579- property int headerAlignment: Text.AlignLeft;
1580+ property int titleAlignment: Text.AlignLeft;
1581 property int fixedHeaderHeight: -1;
1582 property size fixedArtShapeSize: Qt.size(-1, -1);
1583 readonly property string title: cardData && cardData["title"] || "";
1584@@ -46,8 +46,9 @@
1585 objectName: "mascotImage";
1586 anchors { verticalCenter: parent.verticalCenter; }
1587 readonly property int maxSize: Math.max(width, height) * 4;
1588- source: cardData && cardData["mascot"] || "";
1589- width: units.gu(6);
1590+ property bool doLoadSource: !NetworkingStatus.limitedBandwith;
1591+ source: { if (root.visible) doLoadSource = true; return doLoadSource && cardData && cardData["mascot"] || ""; }
1592+ width: units.gu(6);
1593 height: units.gu(5.625);
1594 sourceSize { width: maxSize; height: maxSize }
1595 fillMode: Image.PreserveAspectCrop;
1596@@ -72,13 +73,13 @@
1597 elide: Text.ElideRight;
1598 fontSize: "small";
1599 wrapMode: Text.Wrap;
1600- maximumLineCount: 2;
1601+ maximumLineCount: horizontalAlignment === Text.AlignHCenter ? 1 : 2;
1602 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
1603 color: root.scopeStyle ? root.scopeStyle.foreground : Theme.palette.normal.baseText;
1604 visible: showHeader ;
1605 text: root.title;
1606- font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
1607- horizontalAlignment: root.headerAlignment;
1608+ font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
1609+ horizontalAlignment: root.titleAlignment;
1610 }
1611 ,Label {
1612 id: subtitleLabel;
1613@@ -90,13 +91,12 @@
1614 }
1615 anchors.topMargin: units.dp(2);
1616 elide: Text.ElideRight;
1617- fontSize: "small";
1618+ fontSize: "x-small";
1619 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
1620 color: root.scopeStyle ? root.scopeStyle.foreground : Theme.palette.normal.baseText;
1621 visible: titleLabel.visible && titleLabel.text;
1622 text: cardData && cardData["subtitle"] || "";
1623 font.weight: Font.Light;
1624- horizontalAlignment: root.headerAlignment;
1625 }
1626 ]
1627 }
1628
1629=== modified file 'tests/plugins/Dash/cardcreator/5.res'
1630--- tests/plugins/Dash/cardcreator/5.res 2014-08-29 08:31:22 +0000
1631+++ tests/plugins/Dash/cardcreator/5.res 2014-09-11 16:03:35 +0000
1632@@ -6,7 +6,7 @@
1633 property var artShapeBorderSource: undefined;
1634 property real fontScale: 1.0;
1635 property var scopeStyle: null;
1636- property int headerAlignment: Text.AlignLeft;
1637+ property int titleAlignment: Text.AlignLeft;
1638 property int fixedHeaderHeight: -1;
1639 property size fixedArtShapeSize: Qt.size(-1, -1);
1640 readonly property string title: cardData && cardData["title"] || "";
1641@@ -46,8 +46,9 @@
1642 }
1643 image: Image {
1644 objectName: "artImage";
1645- source: cardData && cardData["art"] || "";
1646- cache: true;
1647+ property bool doLoadSource: !NetworkingStatus.limitedBandwith;
1648+ source: { if (root.visible) doLoadSource = true; return doLoadSource && cardData && cardData["art"] || ""; }
1649+ cache: true;
1650 asynchronous: root.asynchronous;
1651 fillMode: Image.PreserveAspectCrop;
1652 width: root.width;
1653@@ -112,13 +113,13 @@
1654 elide: Text.ElideRight;
1655 fontSize: "small";
1656 wrapMode: Text.Wrap;
1657- maximumLineCount: 2;
1658+ maximumLineCount: horizontalAlignment === Text.AlignHCenter ? 1 : 2;
1659 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
1660 color: root.scopeStyle && overlayLoader.item ? root.scopeStyle.getTextColor(overlayLoader.item.luminance) : (overlayLoader.item && overlayLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
1661 visible: showHeader && overlayLoader.active;
1662 text: root.title;
1663- font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
1664- horizontalAlignment: root.headerAlignment;
1665+ font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
1666+ horizontalAlignment: root.titleAlignment;
1667 }
1668 Label {
1669 id: subtitleLabel;
1670@@ -131,13 +132,12 @@
1671 }
1672 anchors.topMargin: units.dp(2);
1673 elide: Text.ElideRight;
1674- fontSize: "small";
1675+ fontSize: "x-small";
1676 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
1677 color: root.scopeStyle && overlayLoader.item ? root.scopeStyle.getTextColor(overlayLoader.item.luminance) : (overlayLoader.item && overlayLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
1678 visible: titleLabel.visible && titleLabel.text;
1679 text: cardData && cardData["subtitle"] || "";
1680 font.weight: Font.Light;
1681- horizontalAlignment: root.headerAlignment;
1682 }
1683 UbuntuShape {
1684 id: touchdown;
1685
1686=== modified file 'tests/plugins/Dash/cardcreator/6.res'
1687--- tests/plugins/Dash/cardcreator/6.res 2014-08-29 08:31:22 +0000
1688+++ tests/plugins/Dash/cardcreator/6.res 2014-09-11 16:03:35 +0000
1689@@ -6,7 +6,7 @@
1690 property var artShapeBorderSource: undefined;
1691 property real fontScale: 1.0;
1692 property var scopeStyle: null;
1693- property int headerAlignment: Text.AlignLeft;
1694+ property int titleAlignment: Text.AlignLeft;
1695 property int fixedHeaderHeight: -1;
1696 property size fixedArtShapeSize: Qt.size(-1, -1);
1697 readonly property string title: cardData && cardData["title"] || "";
1698@@ -68,13 +68,13 @@
1699 elide: Text.ElideRight;
1700 fontSize: "small";
1701 wrapMode: Text.Wrap;
1702- maximumLineCount: 2;
1703+ maximumLineCount: horizontalAlignment === Text.AlignHCenter ? 1 : 2;
1704 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
1705 color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
1706 visible: showHeader ;
1707 text: root.title;
1708- font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
1709- horizontalAlignment: root.headerAlignment;
1710+ font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
1711+ horizontalAlignment: root.titleAlignment;
1712 }
1713 ,Label {
1714 id: subtitleLabel;
1715@@ -86,15 +86,14 @@
1716 }
1717 anchors.topMargin: units.dp(2);
1718 elide: Text.ElideRight;
1719- fontSize: "small";
1720+ fontSize: "x-small";
1721 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
1722 color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
1723 visible: titleLabel.visible && titleLabel.text;
1724 text: cardData && cardData["subtitle"] || "";
1725 font.weight: Font.Light;
1726- horizontalAlignment: root.headerAlignment;
1727 }
1728-,Icon {
1729+,StatusIcon {
1730 id: emblemIcon;
1731 objectName: "emblemIcon";
1732 anchors {
1733@@ -104,7 +103,6 @@
1734 }
1735 source: cardData && cardData["emblem"] || "";
1736 color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
1737- width: height;
1738 height: source != "" ? titleLabel.font.pixelSize : 0;
1739 }
1740
1741
1742=== modified file 'tests/plugins/Dash/cardcreator/7.res'
1743--- tests/plugins/Dash/cardcreator/7.res 2014-08-29 08:31:22 +0000
1744+++ tests/plugins/Dash/cardcreator/7.res 2014-09-11 16:03:35 +0000
1745@@ -6,7 +6,7 @@
1746 property var artShapeBorderSource: undefined;
1747 property real fontScale: 1.0;
1748 property var scopeStyle: null;
1749- property int headerAlignment: Text.AlignLeft;
1750+ property int titleAlignment: Text.AlignLeft;
1751 property int fixedHeaderHeight: -1;
1752 property size fixedArtShapeSize: Qt.size(-1, -1);
1753 readonly property string title: cardData && cardData["title"] || "";
1754@@ -67,8 +67,9 @@
1755 objectName: "mascotImage";
1756 anchors { verticalCenter: parent.verticalCenter; }
1757 readonly property int maxSize: Math.max(width, height) * 4;
1758- source: cardData && cardData["mascot"] || "";
1759- width: units.gu(6);
1760+ property bool doLoadSource: !NetworkingStatus.limitedBandwith;
1761+ source: { if (root.visible) doLoadSource = true; return doLoadSource && cardData && cardData["mascot"] || ""; }
1762+ width: units.gu(6);
1763 height: units.gu(5.625);
1764 sourceSize { width: maxSize; height: maxSize }
1765 fillMode: Image.PreserveAspectCrop;
1766@@ -93,13 +94,13 @@
1767 elide: Text.ElideRight;
1768 fontSize: "small";
1769 wrapMode: Text.Wrap;
1770- maximumLineCount: 2;
1771+ maximumLineCount: horizontalAlignment === Text.AlignHCenter ? 1 : 2;
1772 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
1773 color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
1774 visible: showHeader ;
1775 text: root.title;
1776- font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
1777- horizontalAlignment: root.headerAlignment;
1778+ font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
1779+ horizontalAlignment: root.titleAlignment;
1780 }
1781 ,Label {
1782 id: subtitleLabel;
1783@@ -111,13 +112,12 @@
1784 }
1785 anchors.topMargin: units.dp(2);
1786 elide: Text.ElideRight;
1787- fontSize: "small";
1788+ fontSize: "x-small";
1789 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
1790 color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
1791 visible: titleLabel.visible && titleLabel.text;
1792 text: cardData && cardData["subtitle"] || "";
1793 font.weight: Font.Light;
1794- horizontalAlignment: root.headerAlignment;
1795 }
1796 ,CardAttributes {
1797 id: attributesRow;
1798
1799=== modified file 'tests/plugins/Dash/listviewwithpageheadertest.cpp'
1800--- tests/plugins/Dash/listviewwithpageheadertest.cpp 2014-04-24 14:13:21 +0000
1801+++ tests/plugins/Dash/listviewwithpageheadertest.cpp 2014-09-11 16:03:35 +0000
1802@@ -28,6 +28,8 @@
1803 #include <private/qquickitem_p.h>
1804 #pragma GCC diagnostic pop
1805
1806+#include <limits>
1807+
1808 // TODO Think on how doing a test for lost items
1809 // particullary making sure that lost items are culled
1810 // and then removed in the next updatePolish cycle
1811@@ -1899,6 +1901,43 @@
1812 QTRY_COMPARE(lvwph->m_firstVisibleIndex, 0);
1813 }
1814
1815+ void testNoCacheBuffer()
1816+ {
1817+ lvwph->setCacheBuffer(0);
1818+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
1819+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1820+ verifyItem(0, 50., 150., false);
1821+ verifyItem(1, 200., 200., false);
1822+ verifyItem(2, 400., 350., false);
1823+ QCOMPARE(lvwph->m_minYExtent, 0.);
1824+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
1825+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1826+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1827+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1828+ QCOMPARE(lvwph->contentY(), 0.);
1829+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1830+ }
1831+
1832+ void testAllCacheBuffer()
1833+ {
1834+ lvwph->setCacheBuffer(std::numeric_limits<qreal>::max());
1835+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 6);
1836+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1837+ verifyItem(0, 50., 150., false);
1838+ verifyItem(1, 200., 200., false);
1839+ verifyItem(2, 400., 350., false);
1840+ verifyItem(3, 750., 350., true);
1841+ verifyItem(4, 1100., 350., true);
1842+ verifyItem(5, 1450., 350., true);
1843+ QCOMPARE(lvwph->m_minYExtent, 0.);
1844+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
1845+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1846+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1847+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1848+ QCOMPARE(lvwph->contentY(), 0.);
1849+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1850+ }
1851+
1852 private:
1853 QQuickView *view;
1854 ListViewWithPageHeader *lvwph;
1855
1856=== modified file 'tests/plugins/Dash/listviewwithpageheadertest.qml'
1857--- tests/plugins/Dash/listviewwithpageheadertest.qml 2014-04-30 10:06:33 +0000
1858+++ tests/plugins/Dash/listviewwithpageheadertest.qml 2014-09-11 16:03:35 +0000
1859@@ -60,6 +60,7 @@
1860 anchors.top: parent.top
1861 anchors.bottom: parent.bottom
1862 model: model
1863+ cacheBuffer: height * 0.5
1864 delegate: Rectangle {
1865 property bool timerDone: false
1866 width: parent.width - 20
1867
1868=== modified file 'tests/plugins/Dash/listviewwithpageheadertestsection.qml'
1869--- tests/plugins/Dash/listviewwithpageheadertestsection.qml 2014-04-30 10:06:33 +0000
1870+++ tests/plugins/Dash/listviewwithpageheadertestsection.qml 2014-09-11 16:03:35 +0000
1871@@ -60,6 +60,7 @@
1872 anchors.top: parent.top
1873 anchors.bottom: parent.bottom
1874 model: model
1875+ cacheBuffer: height * 0.5
1876 delegate: Rectangle {
1877 property bool timerDone: false
1878 width: parent.width - 20
1879
1880=== modified file 'tests/plugins/Dash/listviewwithpageheadertestsectionexternalmodel.qml'
1881--- tests/plugins/Dash/listviewwithpageheadertestsectionexternalmodel.qml 2014-04-30 10:06:33 +0000
1882+++ tests/plugins/Dash/listviewwithpageheadertestsectionexternalmodel.qml 2014-09-11 16:03:35 +0000
1883@@ -28,6 +28,7 @@
1884 anchors.top: parent.top
1885 anchors.bottom: parent.bottom
1886 model: model
1887+ cacheBuffer: height * 0.5
1888 delegate: Rectangle {
1889 property bool timerDone: false
1890 width: parent.width - 20
1891
1892=== modified file 'tests/plugins/Ubuntu/Gestures/CMakeLists.txt'
1893--- tests/plugins/Ubuntu/Gestures/CMakeLists.txt 2014-05-01 14:25:18 +0000
1894+++ tests/plugins/Ubuntu/Gestures/CMakeLists.txt 2014-09-11 16:03:35 +0000
1895@@ -19,7 +19,7 @@
1896 qt5_use_modules(${CLASSNAME}TestExec Test Core Qml Gui Quick)
1897 target_link_libraries(${CLASSNAME}TestExec UbuntuGestureQml)
1898
1899- add_binary_qml_test(${CLASSNAME} ${CMAKE_BINARY_DIR}/plugins/Ubuntu/Gestures UbuntuGesturesTestQmlFiles)
1900+ add_binary_qml_test(${CLASSNAME} ${CMAKE_BINARY_DIR}/plugins/Ubuntu/Gestures UbuntuGesturesTestQmlFiles "")
1901 add_manual_qml_test(. ${CLASSNAME} IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
1902 endmacro(add_gesture_ui_test)
1903
1904
1905=== modified file 'tests/qmltests/Components/CMakeLists.txt'
1906--- tests/qmltests/Components/CMakeLists.txt 2014-05-01 14:25:18 +0000
1907+++ tests/qmltests/Components/CMakeLists.txt 2014-09-11 16:03:35 +0000
1908@@ -10,7 +10,7 @@
1909 qt5_use_modules(DragHandleTestExec Test Core Qml Gui Quick)
1910 target_link_libraries(DragHandleTestExec UbuntuGestureQml)
1911
1912-add_binary_qml_test(DragHandle ${CMAKE_BINARY_DIR}/plugins/Ubuntu/Gestures "")
1913+add_binary_qml_test(DragHandle ${CMAKE_BINARY_DIR}/plugins/Ubuntu/Gestures "" "")
1914 add_manual_qml_test(. DragHandle IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
1915
1916 add_definitions(-DUBUNTU_GESTURES_PLUGIN_DIR="${CMAKE_BINARY_DIR}/plugins")
1917
1918=== modified file 'tests/qmltests/Dash/CardHelpers.js'
1919--- tests/qmltests/Dash/CardHelpers.js 2014-08-08 14:56:53 +0000
1920+++ tests/qmltests/Dash/CardHelpers.js 2014-09-11 16:03:35 +0000
1921@@ -16,7 +16,7 @@
1922
1923 .pragma library
1924
1925-var components = ["title", "art", "subtitle", "mascot", "emblem", "old-price", "price", "alt-price", "rating", "alt-rating", "summary", "attributes", "overlayColor"]
1926+var components = ["title", "art", "subtitle", "mascot", "emblem", "summary", "attributes", "overlayColor"]
1927
1928 var defaultLayout = ' \
1929 { \
1930@@ -37,17 +37,6 @@
1931 "overlayColor": null, \
1932 "mascot": null, \
1933 "emblem": null, \
1934- "old-price": null, \
1935- "price": null, \
1936- "alt-price": null, \
1937- "rating": { \
1938- "type": "stars", \
1939- "range": [0, 5], \
1940- "full": "image://theme/rating-star-full", \
1941- "half": "image://theme/rating-star-half", \
1942- "empty": "image://theme/rating-star-empty" \
1943- }, \
1944- "alt-rating": null, \
1945 "summary": null, \
1946 "attributes": { "max-count": 2 } \
1947 }, \
1948
1949=== modified file 'tests/qmltests/Dash/tst_Card.qml'
1950--- tests/qmltests/Dash/tst_Card.qml 2014-08-22 14:43:02 +0000
1951+++ tests/qmltests/Dash/tst_Card.qml 2014-09-11 16:03:35 +0000
1952@@ -17,6 +17,7 @@
1953 import QtQuick 2.0
1954 import QtTest 1.0
1955 import Ubuntu.Components 0.1
1956+import Ubuntu.Connectivity 1.0
1957 import Unity.Test 0.1 as UT
1958 import "../../../qml/Dash"
1959 import "CardHelpers.js" as Helpers
1960@@ -566,5 +567,25 @@
1961 verify((card.width - titleToCard.x - titleToCard.width) === units.gu(1));
1962 }
1963 }
1964+
1965+ function test_load_images_visibility_network_data() {
1966+ return [
1967+ { tag: "Visible, network", visible: true, limitedBandwith: false },
1968+ { tag: "Visible, no network", visible: true, limitedBandwith: true },
1969+ { tag: "Not Visible, network", visible: false, limitedBandwith: false },
1970+ { tag: "Not Visible, no network", visible: false, limitedBandwith: true }
1971+ ];
1972+ }
1973+
1974+ function test_load_images_visibility_network(data) {
1975+ loader.visible = data.visible;
1976+ NetworkingStatus.limitedBandwith = data.limitedBandwith;
1977+
1978+ selector.selectedIndex = 0;
1979+ waitForRendering(selector);
1980+ waitForRendering(card);
1981+
1982+ verify(data.visible || !data.limitedBandwith || artImage.source == "");
1983+ }
1984 }
1985 }
1986
1987=== modified file 'tests/qmltests/Dash/tst_CardTool.qml'
1988--- tests/qmltests/Dash/tst_CardTool.qml 2014-08-14 23:07:21 +0000
1989+++ tests/qmltests/Dash/tst_CardTool.qml 2014-09-11 16:03:35 +0000
1990@@ -85,8 +85,8 @@
1991 "layout": { "template": { "card-layout": "vertical" }, "components": { "title": "title", "subtitle": "subtitle" } }
1992 },
1993 {
1994- "name": "Title, price - horizontal",
1995- "layout": { "template": { "card-layout": "horizontal" }, "components": { "title": "title", "price": "price" } }
1996+ "name": "Title, attributes - horizontal",
1997+ "layout": { "template": { "card-layout": "horizontal" }, "components": { "title": "title", "attributes": "attributes" } }
1998 },
1999 ]
2000
2001@@ -100,6 +100,7 @@
2002 }
2003
2004 Column {
2005+ id: column
2006 width: units.gu(38)
2007 anchors { left: parent.left; top: parent.top; margins: units.gu(1) }
2008
2009@@ -111,7 +112,7 @@
2010 ]
2011
2012 delegate: Row {
2013- anchors { left: parent.left; right: parent.right; margins: units.gu(3) }
2014+ anchors { left: column.left; right: column.right; margins: units.gu(3) }
2015
2016 Label {
2017 height: units.gu(5)
2018@@ -315,28 +316,35 @@
2019 }
2020 }
2021
2022- function test_card_header_component_alignment_data() {
2023+ function test_card_title_alignment_data() {
2024 return [
2025- { tag: "Title - vertical", component: "titleLabel", property: "headerAlignment",
2026- value: Text.AlignHCenter, index: 11, layout_index: 0 },
2027- { tag: "Title - horizontal", component: "titleLabel", property: "headerAlignment",
2028- value: Text.AlignLeft, index: 12, layout_index: 0},
2029- { tag: "Title, subtitle - vertical", component: "titleLabel", property: "headerAlignment",
2030- value: Text.AlignLeft, index: 13, layout_index: 0},
2031- { tag: "Title, price - horizontal", component: "titleLabel", property: "headerAlignment",
2032- value: Text.AlignLeft, index: 14, layout_index: 0},
2033- ]
2034+ { tag: "Art, header, summary", value: Text.AlignLeft, index: 0 },
2035+ { tag: "Header, summary", value: Text.AlignLeft, index: 1 },
2036+ { tag: "Art, header", value: Text.AlignLeft, index: 2 },
2037+ { tag: "Header only", value: Text.AlignLeft, index: 3 },
2038+ { tag: "Header title only", value: Text.AlignHCenter, index: 4 },
2039+ { tag: "Header title and subtitle", value: Text.AlignLeft, index: 5 },
2040+ { tag: "Header title and mascot", value: Text.AlignLeft, index: 6 },
2041+ { tag: "Art, header, summary - small", value: Text.AlignLeft, index: 7 },
2042+ { tag: "Art, header, summary - large", value: Text.AlignLeft, index: 8 },
2043+ { tag: "Art, header, summary - horizontal", value: Text.AlignLeft, index: 9 },
2044+ { tag: "Art, header - portrait", value: Text.AlignLeft, index: 10 },
2045+ { tag: "Title - vertical", value: Text.AlignHCenter, index: 11 },
2046+ { tag: "Title - horizontal", value: Text.AlignLeft, index: 12 },
2047+ { tag: "Title, subtitle - vertical", value: Text.AlignLeft, index: 13 },
2048+ { tag: "Title, attributes - horizontal", value: Text.AlignLeft, index: 14 },
2049+ ];
2050 }
2051
2052- function test_card_header_component_alignment(data) {
2053+ function test_card_title_alignment(data) {
2054 selector.selectedIndex = data.index;
2055- if (data.hasOwnProperty("layout_index")) {
2056- layoutSelector.selectedIndex = data.layout_index;
2057- }
2058-
2059- if (data.hasOwnProperty("property")) {
2060- tryCompare(cardTool, data.property, data.value);
2061- }
2062+
2063+ tryCompare(cardTool, "titleAlignment", Text.AlignLeft);
2064+
2065+ cardTool.components['title'] = { "field": "title", "align": "center" };
2066+ cardTool.componentsChanged();
2067+
2068+ tryCompare(cardTool, "titleAlignment", data.value);
2069 }
2070
2071 function test_categoryLayout_data() {
2072
2073=== modified file 'tests/qmltests/Dash/tst_Dash.qml'
2074--- tests/qmltests/Dash/tst_Dash.qml 2014-09-08 14:14:12 +0000
2075+++ tests/qmltests/Dash/tst_Dash.qml 2014-09-11 16:03:35 +0000
2076@@ -249,8 +249,7 @@
2077 var categoryListView = findChild(dashContentList.currentItem, "categoryListView");
2078 var dashCategory2 = findChild(categoryListView, "dashCategory2");
2079 tryCompareFunction(function() {
2080- var d = findChild(dashCategory2, "delegate2");
2081- if (d) return true;
2082+ if (dashCategory2.y < 200) return true;
2083 categoryListView.contentY += 100;
2084 return false;
2085 }, true);
2086
2087=== modified file 'tests/qmltests/Dash/tst_GenericScopeView.qml'
2088--- tests/qmltests/Dash/tst_GenericScopeView.qml 2014-08-26 19:25:41 +0000
2089+++ tests/qmltests/Dash/tst_GenericScopeView.qml 2014-09-11 16:03:35 +0000
2090@@ -1,5 +1,5 @@
2091 /*
2092- * Copyright 2013 Canonical Ltd.
2093+ * Copyright 2013, 2014 Canonical Ltd.
2094 *
2095 * This program is free software; you can redistribute it and/or modify
2096 * it under the terms of the GNU General Public License as published by
2097@@ -43,6 +43,10 @@
2098 onLoadedChanged: if (loaded) genericScopeView.scope = scopes.getScope(2);
2099 }
2100
2101+ MockScope {
2102+ id: mockScope
2103+ }
2104+
2105 SignalSpy {
2106 id: spy
2107 }
2108@@ -78,18 +82,29 @@
2109 spy.signalName = "";
2110 }
2111
2112- function scrollToCategory(category) {
2113+ function scrollToCategory(categoryName) {
2114 var categoryListView = findChild(genericScopeView, "categoryListView");
2115 tryCompareFunction(function() {
2116- if (findChild(genericScopeView, category)) return true;
2117+ var category = findChild(genericScopeView, categoryName);
2118+ if (category && category.y > 0 && category.y < genericScopeView.height) return true;
2119 mouseFlick(genericScopeView, genericScopeView.width/2, genericScopeView.height,
2120 genericScopeView.width/2, genericScopeView.y)
2121 tryCompare(categoryListView, "moving", false);
2122- return findChild(genericScopeView, category) !== null;
2123+ return false;
2124 }, true);
2125
2126 tryCompareFunction(function() { return findChild(genericScopeView, "delegate0") !== null; }, true);
2127- return findChild(genericScopeView, category);
2128+ return findChild(genericScopeView, categoryName);
2129+ }
2130+
2131+ function scrollToEnd()
2132+ {
2133+ var categoryListView = findChild(genericScopeView, "categoryListView");
2134+ while (!categoryListView.atYEnd) {
2135+ mouseFlick(genericScopeView, genericScopeView.width/2, genericScopeView.height - units.gu(8),
2136+ genericScopeView.width/2, genericScopeView.y)
2137+ tryCompare(categoryListView, "moving", false);
2138+ }
2139 }
2140
2141 function test_isActive() {
2142@@ -268,7 +283,7 @@
2143 if (category === undefined) category = 0;
2144 if (delegate === undefined) delegate = 0;
2145 tryCompareFunction(function() {
2146- var cardGrid = findChild(genericScopeView, category);
2147+ var cardGrid = findChild(genericScopeView, "dashCategory"+category);
2148 if (cardGrid != null) {
2149 var tile = findChild(cardGrid, "delegate"+delegate);
2150 return tile != null;
2151@@ -276,7 +291,7 @@
2152 return false;
2153 },
2154 true);
2155- var tile = findChild(findChild(genericScopeView, category), "delegate"+delegate);
2156+ var tile = findChild(findChild(genericScopeView, "dashCategory"+category), "delegate"+delegate);
2157 mouseClick(tile, tile.width / 2, tile.height / 2);
2158 tryCompare(testCase.subPageLoader, "open", true);
2159 tryCompare(testCase.subPageLoader, "x", 0);
2160@@ -426,6 +441,87 @@
2161 compare(image.source, data.logo, "Title image has the wrong source");
2162 }
2163
2164+ function test_seeAllTwoCategoriesScenario1() {
2165+ mockScope.setId("mockScope");
2166+ mockScope.setName("Mock Scope");
2167+ mockScope.categories.setCount(2);
2168+ mockScope.categories.resultModel(0).setResultCount(50);
2169+ mockScope.categories.resultModel(1).setResultCount(15);
2170+ mockScope.categories.setLayout(0, "grid");
2171+ mockScope.categories.setLayout(1, "grid");
2172+ mockScope.categories.setHeaderLink(0, "");
2173+ mockScope.categories.setHeaderLink(1, "");
2174+ genericScopeView.scope = mockScope;
2175+ waitForRendering(genericScopeView.categoryView);
2176+
2177+ var category0 = findChild(genericScopeView, "dashCategory0")
2178+ var seeAll0 = findChild(category0, "seeAll")
2179+
2180+ waitForRendering(seeAll0);
2181+ verify(category0.expandable);
2182+ verify(!category0.expanded);
2183+
2184+ mouseClick(seeAll0, seeAll0.width / 2, seeAll0.height / 2);
2185+ verify(category0.expanded);
2186+ tryCompare(category0, "height", category0.item.expandedHeight + seeAll0.height);
2187+ tryCompare(genericScopeView.categoryView, "contentY", units.gu(13.5));
2188+
2189+ scrollToEnd();
2190+
2191+ tryCompareFunction(function() { return findChild(genericScopeView, "dashCategory1") !== null; }, true);
2192+ var category1 = findChild(genericScopeView, "dashCategory1")
2193+ var seeAll1 = findChild(category1, "seeAll")
2194+ verify(category1.expandable);
2195+ verify(!category1.expanded);
2196+
2197+ mouseClick(seeAll1, seeAll1.width / 2, seeAll1.height / 2);
2198+ verify(!category0.expanded);
2199+ verify(category1.expanded);
2200+ tryCompare(category1, "height", category1.item.expandedHeight + seeAll1.height);
2201+ tryCompareFunction(function() {
2202+ return genericScopeView.categoryView.contentY + category1.y + category1.height + genericScopeView.categoryView.pageHeader.height
2203+ == genericScopeView.categoryView.contentHeight;}
2204+ , true);
2205+ }
2206+
2207+ function test_seeAllTwoCategoriesScenario2() {
2208+ mockScope.setId("mockScope");
2209+ mockScope.setName("Mock Scope");
2210+ mockScope.categories.setCount(2);
2211+ mockScope.categories.resultModel(0).setResultCount(15);
2212+ mockScope.categories.resultModel(1).setResultCount(50);
2213+ mockScope.categories.setLayout(0, "grid");
2214+ mockScope.categories.setLayout(1, "grid");
2215+ mockScope.categories.setHeaderLink(0, "");
2216+ mockScope.categories.setHeaderLink(1, "");
2217+ genericScopeView.scope = mockScope;
2218+ waitForRendering(genericScopeView.categoryView);
2219+
2220+ var category0 = findChild(genericScopeView, "dashCategory0")
2221+ var seeAll0 = findChild(category0, "seeAll")
2222+
2223+ waitForRendering(seeAll0);
2224+ verify(category0.expandable);
2225+ verify(!category0.expanded);
2226+
2227+ mouseClick(seeAll0, seeAll0.width / 2, seeAll0.height / 2);
2228+ verify(category0.expanded);
2229+ tryCompare(category0, "height", category0.item.expandedHeight + seeAll0.height);
2230+
2231+ scrollToEnd();
2232+
2233+ var category1 = findChild(genericScopeView, "dashCategory1")
2234+ var seeAll1 = findChild(category1, "seeAll")
2235+ verify(category1.expandable);
2236+ verify(!category1.expanded);
2237+
2238+ mouseClick(seeAll1, seeAll1.width / 2, seeAll1.height / 2);
2239+ verify(!category0.expanded);
2240+ verify(category1.expanded);
2241+ tryCompare(category1, "height", category1.item.expandedHeight + seeAll1.height);
2242+ tryCompare(category1, "y", units.gu(5));
2243+ }
2244+
2245 function test_favorite_data() {
2246 return [
2247 { tag: "People", id: "MockScope1", favorite: true },

Subscribers

People subscribed via source and target branches