on xenial help sign in
Cache more things in memory, so flicking scopes should be faster Fixes: 1336724, 1338430

Approved by: Andrea Cimitan

commit69598fa0fb35fa37537858d9d13eefde5fd2e7ed authorMichał Sawicz <michal.sawicz@canonical.com> dateMon 6 Oct 2014, 07:59 (12 years ago) parent9d2fe6135952de
42 files changed+456−93
build.sh+1 cmake/modules/QmlTest.cmake+2−1 debian/control+1 plugins/Dash/CardCreator.js+5−2 plugins/Dash/listviewwithpageheader.cpp+18−7 plugins/Dash/listviewwithpageheader.h+6 qml/Components/ResponsiveGridView.qml+5−1 qml/Dash/CardGrid.qml+1 qml/Dash/CardTool.qml+8−5 qml/Dash/CardVerticalJournal.qml+1 qml/Dash/DashContent.qml+3 qml/Dash/DashNavigation.qml+1 qml/Dash/DashRenderer.qml+4 qml/Dash/GenericScopeView.qml+35−12 qml/Dash/ScopeListView.qml+1 qml/Dash/ScopesOverviewAll.qml+2 tests/autopilot/unity8/shell/emulators/dash.py+2−2 tests/mocks/Ubuntu/CMakeLists.txt+1 tests/mocks/Ubuntu/Connectivity/CMakeLists.txt+10 tests/mocks/Ubuntu/Connectivity/networking-status.cpp+64 tests/mocks/Ubuntu/Connectivity/networking-status.h+73 tests/mocks/Ubuntu/Connectivity/plugin.cpp+46 tests/mocks/Ubuntu/Connectivity/plugin.h+35 tests/mocks/Ubuntu/Connectivity/qmldir+2 tests/plugins/Dash/CMakeLists.txt+3−3 tests/plugins/Dash/cardcreator/1.res+2−1 tests/plugins/Dash/cardcreator/2.res+2−1 tests/plugins/Dash/cardcreator/3.res+3−2 tests/plugins/Dash/cardcreator/4.res+3−2 tests/plugins/Dash/cardcreator/5.res+3−2 tests/plugins/Dash/cardcreator/7.res+3−2 tests/plugins/Dash/listviewwithpageheadertest.cpp+39 tests/plugins/Dash/listviewwithpageheadertest.qml+1 tests/plugins/Dash/listviewwithpageheadertestsection.qml+1 tests/plugins/Dash/listviewwithpageheadertestsectionexternalmodel.qml+1 tests/plugins/Ubuntu/Gestures/CMakeLists.txt+1−1 tests/qmltests/Components/CMakeLists.txt+1−1 tests/qmltests/Dash/tst_Card.qml+26 tests/qmltests/Dash/tst_Dash.qml+16−39 tests/qmltests/Dash/tst_DashContent.qml+14−1 tests/qmltests/Dash/tst_GenericScopeView.qml+7−6 tests/utils/modules/Unity/Test/UnityTestCase.qml+3−2
build.sh+1
@@ -51,6 +51,7 @@ install_dependencies() {
5151 qtdeclarative5-ubuntu-settings-components \
5252 qtdeclarative5-ubuntu-telephony0.1 \
5353 qtdeclarative5-ubuntu-thumbnailer0.1 \
54+ qml-module-ubuntu-connectivity \
5455 unity-notifications-impl \
5556 ubuntu-mobile-icons \
5657 unity-scope-home \
cmake/modules/QmlTest.cmake+2−1
@@ -151,7 +151,7 @@ macro(add_qml_test_internal SUBPATH COMPONENT_NAME ITERATIONS)
151151 add_manual_qml_test(${SUBPATH} ${COMPONENT_NAME} ${ARGN})
152152endmacro(add_qml_test_internal)
153153
154−macro(add_binary_qml_test CLASS_NAME LD_PATH DEPS)
154+macro(add_binary_qml_test CLASS_NAME LD_PATH DEPS ENVVAR)
155155 set(testCommand
156156 LD_LIBRARY_PATH=${LD_PATH}
157157 ${CMAKE_CURRENT_BINARY_DIR}/${CLASS_NAME}TestExec
@@ -168,6 +168,7 @@ macro(add_binary_qml_test CLASS_NAME LD_PATH DEPS)
168168 endif()
169169 set(xvfbtestCommand
170170 ${LD_PRELOAD_PATH}
171+ ${ENVVAR}
171172 LD_LIBRARY_PATH=${LD_PATH}
172173 xvfb-run --server-args "-screen 0 1024x768x24" --auto-servernum
173174 ${CMAKE_CURRENT_BINARY_DIR}/${CLASS_NAME}TestExec
debian/control+1
@@ -174,6 +174,7 @@ Depends: accountsservice-ubuntu-schemas (>= 0.0.3),
174174 libhardware2,
175175 unity-schemas (>= 7.3.1+14.10.20140915),
176176 pay-service,
177+ qml-module-ubuntu-connectivity,
177178 ${misc:Depends},
178179 ${shlibs:Depends},
179180Provides: unity-launcher-impl,
plugins/Dash/CardCreator.js+5−2
@@ -84,7 +84,8 @@ var kArtShapeHolderCode = 'Item { \n\
8484 } \n\
8585 image: Image { \n\
8686 objectName: "artImage"; \n\
87− source: cardData && cardData["art"] || ""; \n\
87+ property bool doLoadSource: !NetworkingStatus.limitedBandwith; \n\
88+ source: { if (root.visible) doLoadSource = true; return doLoadSource && cardData && cardData["art"] || ""; } \n\
8889 cache: true; \n\
8990 asynchronous: root.asynchronous; \n\
9091 fillMode: Image.PreserveAspectCrop; \n\
@@ -195,7 +196,8 @@ var kMascotImageCode = 'Image { \n\
195196 objectName: "mascotImage"; \n\
196197 anchors { %1 } \n\
197198 readonly property int maxSize: Math.max(width, height) * 4; \n\
198− source: cardData && cardData["mascot"] || ""; \n\
199+ property bool doLoadSource: !NetworkingStatus.limitedBandwith; \n\
200+ source: { if (root.visible) doLoadSource = true; return doLoadSource && cardData && cardData["mascot"] || ""; } \n\
199201 width: units.gu(6); \n\
200202 height: units.gu(5.625); \n\
201203 sourceSize { width: maxSize; height: maxSize } \n\
@@ -655,6 +657,7 @@ function cardString(template, components) {
655657function createCardComponent(parent, template, components) {
656658 var imports = 'import QtQuick 2.2; \n\
657659 import Ubuntu.Components 1.1; \n\
660+ import Ubuntu.Connectivity 1.0; \n\
658661 import Dash 0.1;\n\
659662 import Utils 0.1;\n';
660663 var card = cardString(template, components);
plugins/Dash/listviewwithpageheader.cpp+18−7
@@ -104,8 +104,6 @@
104104#pragma GCC diagnostic pop
105105// #include <private/qquickrectangle_p.h>
106106
107−static const qreal bufferRatio = 0.5;
108−
109107qreal ListViewWithPageHeader::ListItem::height() const
110108{
111109 return m_item->height() + (m_sectionItem ? m_sectionItem->height() : 0);
@@ -158,6 +156,7 @@ ListViewWithPageHeader::ListViewWithPageHeader()
158156 , m_forceNoClip(false)
159157 , m_inLayout(false)
160158 , m_inContentHeightKeepHeaderShown(false)
159+ , m_cacheBuffer(0)
161160{
162161 m_clipItem = new QQuickItem(contentItem());
163162// m_clipItem = new QQuickRectangle(contentItem());
@@ -335,6 +334,20 @@ qreal ListViewWithPageHeader::headerItemShownHeight() const
335334 return m_headerItemShownHeight;
336335}
337336
337+qreal ListViewWithPageHeader::cacheBuffer() const
338+{
339+ return m_cacheBuffer;
340+}
341+
342+void ListViewWithPageHeader::setCacheBuffer(qreal cacheBuffer)
343+{
344+ if (cacheBuffer != m_cacheBuffer) {
345+ m_cacheBuffer = cacheBuffer;
346+ Q_EMIT cacheBufferChanged();
347+ polish();
348+ }
349+}
350+
338351void ListViewWithPageHeader::positionAtBeginning()
339352{
340353 if (m_delegateModel->count() <= 0)
@@ -356,8 +369,7 @@ void ListViewWithPageHeader::positionAtBeginning()
356369 // Create the subsequent items
357370 int modelIndex = 1;
358371 qreal pos = item->y() + item->height();
359− const qreal buffer = height() * bufferRatio;
360− const qreal bufferTo = height() + buffer;
372+ const qreal bufferTo = height() + m_cacheBuffer;
361373 while (modelIndex < m_delegateModel->count() && pos <= bufferTo) {
362374 if (!(item = createItem(modelIndex, false)))
363375 break;
@@ -603,11 +615,10 @@ void ListViewWithPageHeader::refill()
603615 return;
604616 }
605617
606− const qreal buffer = height() * bufferRatio;
607618 const qreal from = contentY();
608619 const qreal to = from + height();
609− const qreal bufferFrom = from - buffer;
610− const qreal bufferTo = to + buffer;
620+ const qreal bufferFrom = from - m_cacheBuffer;
621+ const qreal bufferTo = to + m_cacheBuffer;
611622
612623 bool added = addVisibleItems(from, to, false);
613624 bool removed = removeNonVisibleItems(bufferFrom, bufferTo);
plugins/Dash/listviewwithpageheader.h+6
@@ -54,6 +54,7 @@ class ListViewWithPageHeader : public QQuickFlickable, public QQuickItemChangeLi
5454 Q_PROPERTY(bool forceNoClip READ forceNoClip WRITE setForceNoClip NOTIFY forceNoClipChanged)
5555 Q_PROPERTY(int stickyHeaderHeight READ stickyHeaderHeight NOTIFY stickyHeaderHeightChanged)
5656 Q_PROPERTY(qreal headerItemShownHeight READ headerItemShownHeight NOTIFY headerItemShownHeightChanged)
57+ Q_PROPERTY(qreal cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY cacheBufferChanged)
5758
5859 friend class ListViewWithPageHeaderTest;
5960 friend class ListViewWithPageHeaderTestSection;
@@ -84,6 +85,9 @@ public:
8485 int stickyHeaderHeight() const;
8586 qreal headerItemShownHeight() const;
8687
88+ qreal cacheBuffer() const;
89+ void setCacheBuffer(qreal cacheBuffer);
90+
8791 Q_INVOKABLE void positionAtBeginning();
8892 Q_INVOKABLE void showHeader();
8993 Q_INVOKABLE int firstCreatedIndex() const;
@@ -105,6 +109,7 @@ Q_SIGNALS:
105109 void forceNoClipChanged();
106110 void stickyHeaderHeightChanged();
107111 void headerItemShownHeightChanged();
112+ void cacheBufferChanged();
108113
109114protected:
110115 void componentComplete() override;
@@ -199,6 +204,7 @@ private:
199204 bool m_forceNoClip;
200205 bool m_inLayout;
201206 bool m_inContentHeightKeepHeaderShown;
207+ qreal m_cacheBuffer;
202208
203209 // Qt 5.0 doesn't like releasing the items just after itemCreated
204210 // so we delay the releasing until the next updatePolish
qml/Components/ResponsiveGridView.qml+5−1
@@ -34,7 +34,11 @@ Item {
3434 readonly property int cellWidth: gridView.cellWidth
3535 readonly property int cellHeight: gridView.cellHeight
3636 readonly property int totalContentHeight: {
37− return contentHeightForRows(Math.ceil(gridView.model.count / columns), cellHeight)
37+ if (gridView.model) {
38+ return contentHeightForRows(Math.ceil(gridView.model.count / columns), cellHeight)
39+ } else {
40+ return 0;
41+ }
3842 }
3943 property alias interactive: gridView.interactive
4044 readonly property alias flicking: gridView.flicking
qml/Dash/CardGrid.qml+1
@@ -55,6 +55,7 @@ DashRenderer {
5555 delegate: Item {
5656 width: grid.cellWidth
5757 height: grid.cellHeight
58+ visible: y + height >= root.visibleRangeBegin && y <= root.visibleRangeEnd
5859 Loader {
5960 id: loader
6061 sourceComponent: cardTool.cardComponent
qml/Dash/CardTool.qml+8−5
@@ -169,16 +169,19 @@ Item {
169169
170170 Item {
171171 id: attributesModel
172− property int numOfAttributes: {
172+ property int numOfAttributes: 0
173+ property var model: []
174+ property bool hasAttributes: {
173175 var attributes = components["attributes"];
174− if ((attributes != undefined) && attributes["field"]) {
176+ var hasAttributesFlag = (attributes != undefined) && attributes["field"];
177+
178+ if (hasAttributesFlag) {
175179 if (attributes["max-count"]) {
176− return attributes["max-count"];
180+ numOfAttributes = attributes["max-count"];
177181 }
178182 }
179− return 0;
183+ return hasAttributesFlag
180184 }
181− property var model: []
182185
183186 onNumOfAttributesChanged: {
184187 model = []
qml/Dash/CardVerticalJournal.qml+1
@@ -49,6 +49,7 @@ DashRenderer {
4949 id: loader
5050 sourceComponent: cardTool.cardComponent
5151 width: cardTool.cardWidth
52+ visible: y + height >= root.visibleRangeBegin && y <= root.visibleRangeEnd
5253 onLoaded: {
5354 item.objectName = "delegate" + index;
5455 item.fixedArtShapeSize = Qt.binding(function() { return cardTool.artShapeSize; });
qml/Dash/DashContent.qml+3
@@ -111,6 +111,8 @@ Item {
111111 highlightMoveDuration: 250
112112 highlightRangeMode: ListView.StrictlyEnforceRange
113113 // TODO Investigate if we can switch to a smaller cache buffer when/if UbuntuShape gets more performant
114+ // 1073741823 is s^30 -1. A quite big number so that you have "infinite" cache, but not so
115+ // big so that if you add if with itself you're outside the 2^31 int range
114116 cacheBuffer: 1073741823
115117 onMovementStarted: currentItem.item.showHeader();
116118 clip: parent.x != 0
@@ -177,6 +179,7 @@ Item {
177179 dashContent.scopeLoaded(item.scope.id)
178180 item.paginationCount = Qt.binding(function() { return dashContentList.count } )
179181 item.paginationIndex = Qt.binding(function() { return dashContentList.currentIndex } )
182+ item.holdingList = dashContentList;
180183 }
181184 Connections {
182185 target: isCurrent ? scope : null
qml/Dash/DashNavigation.qml+1
@@ -52,6 +52,7 @@ Item {
5252
5353 Rectangle {
5454 id: blackRect
55+ objectName: "blackRect"
5556 color: "black"
5657 opacity: openList && openList.currentItem && openList.currentItem.visible ? 0.5 : 0
5758 Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
qml/Dash/DashRenderer.qml+4
@@ -27,6 +27,10 @@ Item {
2727
2828 property int displayMarginEnd: 0
2929
30+ property int visibleRangeBegin: 0
31+
32+ property int visibleRangeEnd: 0
33+
3034 property real originY: 0
3135
3236 // The model to renderer
qml/Dash/GenericScopeView.qml+35−12
@@ -38,6 +38,7 @@ FocusScope {
3838 property int paginationCount: 0
3939 property int paginationIndex: 0
4040 property alias pageHeaderTotallyVisible: categoryView.pageHeaderTotallyVisible
41+ property var holdingList: null
4142
4243 property var scopeStyle: ScopeStyle {
4344 style: scope ? scope.customizations : {}
@@ -251,8 +252,8 @@ FocusScope {
251252 }
252253 }
253254
254− onHeightChanged: rendererLoader.updateDelegateCreationRange();
255− onYChanged: rendererLoader.updateDelegateCreationRange();
255+ onHeightChanged: rendererLoader.updateRanges();
256+ onYChanged: rendererLoader.updateRanges();
256257
257258 Loader {
258259 id: rendererLoader
@@ -314,7 +315,7 @@ FocusScope {
314315 var shouldExpand = baseItem.category === categoryView.expandedCategoryId;
315316 baseItem.expand(shouldExpand, false /*animate*/);
316317 }
317− updateDelegateCreationRange();
318+ updateRanges();
318319 if (scope && scope.id === "clickscope" && (categoryId === "predefined" || categoryId === "local")) {
319320 // Yeah, hackish :/
320321 cardTool.artShapeSize = Qt.size(units.gu(8), units.gu(7.5));
@@ -348,13 +349,25 @@ FocusScope {
348349 }
349350 Connections {
350351 target: categoryView
351− onOriginYChanged: rendererLoader.updateDelegateCreationRange();
352− onContentYChanged: rendererLoader.updateDelegateCreationRange();
353− onHeightChanged: rendererLoader.updateDelegateCreationRange();
354− onContentHeightChanged: rendererLoader.updateDelegateCreationRange();
352+ onOriginYChanged: rendererLoader.updateRanges();
353+ onContentYChanged: rendererLoader.updateRanges();
354+ onHeightChanged: rendererLoader.updateRanges();
355+ onContentHeightChanged: rendererLoader.updateRanges();
356+ }
357+ Connections {
358+ target: scopeView
359+ onIsCurrentChanged: rendererLoader.updateRanges();
360+ }
361+ Connections {
362+ target: holdingList
363+ onMovingChanged: if (!moving) rendererLoader.updateRanges();
355364 }
356365
357− function updateDelegateCreationRange() {
366+ function updateRanges() {
367+ if (holdingList && holdingList.moving) {
368+ return;
369+ }
370+
358371 if (categoryView.moving) {
359372 // Do not update the range if we are overshooting up or down, since we'll come back
360373 // to the stable position and delete/create items without any reason
@@ -366,10 +379,20 @@ FocusScope {
366379 }
367380 }
368381
382+ if (item && item.hasOwnProperty("visibleRangeBegin")) {
383+ item.visibleRangeBegin = Math.max(-baseItem.y, 0)
384+ item.visibleRangeEnd = item.visibleRangeBegin + Math.min(categoryView.height, rendererLoader.height)
385+ }
386+
369387 if (item && item.hasOwnProperty("displayMarginBeginning")) {
370388 // TODO do we need item.originY here, test 1300302 once we have a silo
371389 // and we can run it on the phone
372− if (baseItem.y + baseItem.height <= 0) {
390+ if (scopeView.isCurrent) {
391+ // 1073741823 is s^30 -1. A quite big number so that you have "infinite" display margin, but not so
392+ // big so that if you add if with itself you're outside the 2^31 int range
393+ item.displayMarginBeginning = 1073741823;
394+ item.displayMarginEnd = 1073741823;
395+ } else if (baseItem.y + baseItem.height <= 0) {
373396 // Not visible (item at top of the list viewport)
374397 item.displayMarginBeginning = -baseItem.height;
375398 item.displayMarginEnd = 0;
@@ -378,9 +401,9 @@ FocusScope {
378401 item.displayMarginBeginning = 0;
379402 item.displayMarginEnd = -baseItem.height;
380403 } else {
381− item.displayMarginBeginning = -Math.max(-baseItem.y, 0);
382− item.displayMarginEnd = -Math.max(baseItem.height - seeAll.height
383− - categoryView.height + baseItem.y, 0)
404+ item.displayMarginBeginning = Math.round(-Math.max(-baseItem.y, 0));
405+ item.displayMarginEnd = -Math.round(Math.max(baseItem.height - seeAll.height -
406+ categoryView.height + baseItem.y, 0));
384407 }
385408 }
386409 }
qml/Dash/ScopeListView.qml+1
@@ -20,4 +20,5 @@ import Dash 0.1
2020ListViewWithPageHeader {
2121 maximumFlickVelocity: height * 10
2222 flickDeceleration: height * 2
23+ cacheBuffer: Number.MAX_VALUE
2324}
qml/Dash/ScopesOverviewAll.qml+2
@@ -43,6 +43,8 @@ Flickable {
4343 id: cardGrid
4444 width: root.width
4545 height: parent.height
46+ visibleRangeBegin: root.contentY
47+ visibleRangeEnd: root.contentY + root.height
4648
4749 onClicked: {
4850 root.clicked(index, result, item, itemModel);
tests/autopilot/unity8/shell/emulators/dash.py+2−2
@@ -93,7 +93,7 @@ class Dash(emulators.UnityEmulatorBase):
9393 'No scope found with id {0}'.format(scope_id))
9494
9595 def _get_scope_from_loader(self, loader):
96− return loader.get_children()[0]
96+ return loader.wait_select_single('GenericScopeView');
9797
9898 def _open_scope_scrolling(self, scope_loader):
9999 scroll = self._get_scroll_direction(scope_loader)
@@ -102,8 +102,8 @@ class Dash(emulators.UnityEmulatorBase):
102102 scroll()
103103 self.dash_content_list.moving.wait_for(False)
104104
105+ scope_loader.isCurrent.wait_for(True)
105106 scope = self._get_scope_from_loader(scope_loader)
106− scope.isCurrent.wait_for(True)
107107 return scope
108108
109109 def _get_scroll_direction(self, scope_loader):
tests/mocks/Ubuntu/CMakeLists.txt+1
@@ -1,3 +1,4 @@
1+add_subdirectory(Connectivity)
12add_subdirectory(DownloadDaemonListener)
23add_subdirectory(Payments)
34add_subdirectory(SystemImage)
tests/mocks/Ubuntu/Connectivity/CMakeLists.txtnew file+10
@@ -0,0 +1,10 @@
1+add_library(connectivity-qml SHARED
2+ networking-status.cpp
3+ plugin.cpp
4+)
5+qt5_use_modules(connectivity-qml Qml)
6+
7+# copy qmldir file into build directory for shadow builds
8+file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/qmldir"
9+ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
10+ )
tests/mocks/Ubuntu/Connectivity/networking-status.cppnew file+64
@@ -0,0 +1,64 @@
1+/*
2+ * Copyright © 2014 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU Lesser General Public License version 3,
6+ * as published by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Antti Kaijanmäki <antti.kaijanmaki@canonical.com>
18+ */
19+
20+#include "networking-status.h"
21+
22+NetworkingStatus::NetworkingStatus(QObject *parent)
23+ : QObject(parent)
24+{
25+ qRegisterMetaType<NetworkingStatus::Limitations>();
26+ qRegisterMetaType<QVector<NetworkingStatus::Limitations>>();
27+ qRegisterMetaType<NetworkingStatus::Status>();
28+}
29+
30+NetworkingStatus::~NetworkingStatus()
31+{}
32+
33+QVector<NetworkingStatus::Limitations>
34+NetworkingStatus::limitations() const
35+{
36+ return m_limitations;
37+}
38+
39+NetworkingStatus::Status
40+NetworkingStatus::status() const
41+{
42+ return Status::Online;
43+}
44+
45+bool
46+NetworkingStatus::online() const
47+{
48+ return status() == Status::Online;
49+}
50+
51+bool
52+NetworkingStatus::limitedBandwith() const
53+{
54+ return limitations().contains(Limitations::Bandwith);
55+}
56+
57+void NetworkingStatus::setLimitedBandwidth(bool limited)
58+{
59+ if (limited) {
60+ m_limitations << Limitations::Bandwith;
61+ } else if (limitedBandwith()) {
62+ m_limitations.remove(m_limitations.indexOf(Limitations::Bandwith));
63+ }
64+}
tests/mocks/Ubuntu/Connectivity/networking-status.hnew file+73
@@ -0,0 +1,73 @@
1+/*
2+ * Copyright © 2014 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU Lesser General Public License version 3,
6+ * as published by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ */
17+
18+#ifndef FAKE_NETWORKING_STATUS_H
19+#define FAKE_NETWORKING_STATUS_H
20+
21+#include <QObject>
22+#include <QVector>
23+
24+class Q_DECL_EXPORT NetworkingStatus : public QObject
25+{
26+ Q_OBJECT
27+ Q_DISABLE_COPY(NetworkingStatus)
28+
29+ Q_ENUMS(Limitations)
30+ Q_ENUMS(Status)
31+
32+ Q_PROPERTY(QVector<Limitations> limitations READ limitations NOTIFY limitationsChanged)
33+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
34+ Q_PROPERTY(bool online READ online NOTIFY onlineChanged)
35+ Q_PROPERTY(bool limitedBandwith READ limitedBandwith WRITE setLimitedBandwidth NOTIFY limitedBandwithChanged)
36+
37+public:
38+ explicit NetworkingStatus(QObject *parent = 0);
39+ virtual ~NetworkingStatus();
40+
41+ enum Limitations {
42+ Bandwith
43+ };
44+
45+ enum Status {
46+ Offline,
47+ Connecting,
48+ Online
49+ };
50+
51+ QVector<Limitations> limitations() const;
52+ Status status() const;
53+ bool online() const;
54+ bool limitedBandwith() const;
55+
56+ // Only in the fake one
57+ void setLimitedBandwidth(bool limited);
58+
59+Q_SIGNALS:
60+ void limitationsChanged();
61+ void statusChanged(Status value);
62+ void onlineChanged(bool value);
63+ void limitedBandwithChanged(bool value);
64+
65+private:
66+ QVector<NetworkingStatus::Limitations> m_limitations;
67+};
68+
69+Q_DECLARE_METATYPE(NetworkingStatus::Limitations)
70+Q_DECLARE_METATYPE(QVector<NetworkingStatus::Limitations>)
71+Q_DECLARE_METATYPE(NetworkingStatus::Status)
72+
73+#endif // FAKE_NETWORKING_STATUS_H
tests/mocks/Ubuntu/Connectivity/plugin.cppnew file+46
@@ -0,0 +1,46 @@
1+/*
2+ * Copyright © 2014 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU Lesser General Public License version 3,
6+ * as published by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Antti Kaijanmäki <antti.kaijanmaki@canonical.com>
18+ */
19+
20+#include "plugin.h"
21+
22+#include <QtQml>
23+
24+#include "networking-status.h"
25+
26+static QObject *
27+networkingStatusSingletonProvider(QQmlEngine *engine, QJSEngine *scriptEngine)
28+{
29+ Q_UNUSED(scriptEngine)
30+
31+ return new NetworkingStatus(engine);
32+}
33+
34+void
35+QmlConnectivityNetworkingPlugin::registerTypes(const char *uri)
36+{
37+ // @uri Ubuntu.Connectivity
38+ qmlRegisterSingletonType<NetworkingStatus>(uri, 1, 0, "NetworkingStatus", networkingStatusSingletonProvider);
39+}
40+
41+void
42+QmlConnectivityNetworkingPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
43+{
44+ Q_UNUSED(uri);
45+ Q_UNUSED(engine);
46+}
tests/mocks/Ubuntu/Connectivity/plugin.hnew file+35
@@ -0,0 +1,35 @@
1+/*
2+ * Copyright © 2014 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU Lesser General Public License version 3,
6+ * as published by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Antti Kaijanmäki <antti.kaijanmaki@canonical.com>
18+ */
19+
20+#ifndef QML_CONNECTIVITY_PLUGIN_H
21+#define QML_CONNECTIVITY_PLUGIN_H
22+
23+#include <QQmlExtensionPlugin>
24+
25+class QmlConnectivityNetworkingPlugin : public QQmlExtensionPlugin {
26+ Q_OBJECT
27+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
28+ Q_INTERFACES(QQmlExtensionInterface)
29+
30+public:
31+ void registerTypes(const char *uri);
32+ void initializeEngine(QQmlEngine *engine, const char *uri);
33+};
34+
35+#endif // QML_CONNECTIVITY_PLUGIN_H
tests/mocks/Ubuntu/Connectivity/qmldirnew file+2
@@ -0,0 +1,2 @@
1+module Ubuntu.Connectivity
2+plugin connectivity-qml
tests/plugins/Dash/CMakeLists.txt+3−3
@@ -32,7 +32,7 @@ macro(add_lvwph_test FILENAME TESTNAME)
3232 qt5_use_modules(${TESTNAME}TestExec Test Core Qml)
3333 target_link_libraries(${TESTNAME}TestExec ${Qt5Gui_LIBRARIES} ${Qt5Quick_LIBRARIES})
3434
35− add_binary_qml_test(${TESTNAME} "" "Dash-qml")
35+ add_binary_qml_test(${TESTNAME} "" "Dash-qml" "")
3636endmacro()
3737
3838add_lvwph_test(listviewwithpageheader ListViewWithPageHeader)
@@ -48,7 +48,7 @@ macro(add_dashview_try_test FILENAME TESTNAME)
4848 qt5_use_modules(${TESTNAME}TestExec Test Core Qml)
4949 target_link_libraries(${TESTNAME}TestExec ${Qt5Gui_LIBRARIES} ${Qt5Quick_LIBRARIES})
5050
51− add_binary_qml_test(${TESTNAME} "" "Dash-qml")
51+ add_binary_qml_test(${TESTNAME} "" "Dash-qml" "")
5252
5353 add_executable(${TESTNAME}tryExec
5454 ${FILENAME}try.cpp
@@ -71,7 +71,7 @@ add_dashview_try_test(organicgrid OrganicGrid)
7171add_executable(CardCreatorTestExec cardcreatortest.cpp)
7272qt5_use_modules(CardCreatorTestExec Test Core Qml)
7373target_link_libraries(CardCreatorTestExec ${Qt5Gui_LIBRARIES} ${Qt5Quick_LIBRARIES})
74−add_binary_qml_test(CardCreator "" "Dash-qml")
74+add_binary_qml_test(CardCreator "" "Dash-qml" "QML2_IMPORT_PATH=${CMAKE_BINARY_DIR}/tests/mocks/")
7575
7676# plain qml test
7777set(qmltest_DEFAULT_TARGETS qmluitests)
tests/plugins/Dash/cardcreator/1.res+2−1
@@ -46,7 +46,8 @@ Item {
4646 }
4747 image: Image {
4848 objectName: "artImage";
49− source: cardData && cardData["art"] || "";
49+ property bool doLoadSource: !NetworkingStatus.limitedBandwith;
50+ source: { if (root.visible) doLoadSource = true; return doLoadSource && cardData && cardData["art"] || ""; }
5051 cache: true;
5152 asynchronous: root.asynchronous;
5253 fillMode: Image.PreserveAspectCrop;
tests/plugins/Dash/cardcreator/2.res+2−1
@@ -67,7 +67,8 @@ Image {
6767 objectName: "mascotImage";
6868 anchors { verticalCenter: parent.verticalCenter; }
6969 readonly property int maxSize: Math.max(width, height) * 4;
70− source: cardData && cardData["mascot"] || "";
70+ property bool doLoadSource: !NetworkingStatus.limitedBandwith;
71+ source: { if (root.visible) doLoadSource = true; return doLoadSource && cardData && cardData["mascot"] || ""; }
7172 width: units.gu(6);
7273 height: units.gu(5.625);
7374 sourceSize { width: maxSize; height: maxSize }
tests/plugins/Dash/cardcreator/3.res+3−2
@@ -46,8 +46,9 @@ Item {
4646 }
4747 image: Image {
4848 objectName: "artImage";
49− source: cardData && cardData["art"] || "";
50− cache: true;
49+ property bool doLoadSource: !NetworkingStatus.limitedBandwith;
50+ source: { if (root.visible) doLoadSource = true; return doLoadSource && cardData && cardData["art"] || ""; }
51+ cache: true;
5152 asynchronous: root.asynchronous;
5253 fillMode: Image.PreserveAspectCrop;
5354 width: root.width;
tests/plugins/Dash/cardcreator/4.res+3−2
@@ -46,8 +46,9 @@ Loader {
4646 objectName: "mascotImage";
4747 anchors { verticalCenter: parent.verticalCenter; }
4848 readonly property int maxSize: Math.max(width, height) * 4;
49− source: cardData && cardData["mascot"] || "";
50− width: units.gu(6);
49+ property bool doLoadSource: !NetworkingStatus.limitedBandwith;
50+ source: { if (root.visible) doLoadSource = true; return doLoadSource && cardData && cardData["mascot"] || ""; }
51+ width: units.gu(6);
5152 height: units.gu(5.625);
5253 sourceSize { width: maxSize; height: maxSize }
5354 fillMode: Image.PreserveAspectCrop;
tests/plugins/Dash/cardcreator/5.res+3−2
@@ -46,8 +46,9 @@ Item {
4646 }
4747 image: Image {
4848 objectName: "artImage";
49− source: cardData && cardData["art"] || "";
50− cache: true;
49+ property bool doLoadSource: !NetworkingStatus.limitedBandwith;
50+ source: { if (root.visible) doLoadSource = true; return doLoadSource && cardData && cardData["art"] || ""; }
51+ cache: true;
5152 asynchronous: root.asynchronous;
5253 fillMode: Image.PreserveAspectCrop;
5354 width: root.width;
tests/plugins/Dash/cardcreator/7.res+3−2
@@ -67,8 +67,9 @@ Image {
6767 objectName: "mascotImage";
6868 anchors { verticalCenter: parent.verticalCenter; }
6969 readonly property int maxSize: Math.max(width, height) * 4;
70− source: cardData && cardData["mascot"] || "";
71− width: units.gu(6);
70+ property bool doLoadSource: !NetworkingStatus.limitedBandwith;
71+ source: { if (root.visible) doLoadSource = true; return doLoadSource && cardData && cardData["mascot"] || ""; }
72+ width: units.gu(6);
7273 height: units.gu(5.625);
7374 sourceSize { width: maxSize; height: maxSize }
7475 fillMode: Image.PreserveAspectCrop;
tests/plugins/Dash/listviewwithpageheadertest.cpp+39
@@ -28,6 +28,8 @@
2828#include <private/qquickitem_p.h>
2929#pragma GCC diagnostic pop
3030
31+#include <limits>
32+
3133// TODO Think on how doing a test for lost items
3234// particullary making sure that lost items are culled
3335// and then removed in the next updatePolish cycle
@@ -1899,6 +1901,43 @@ private Q_SLOTS:
18991901 QTRY_COMPARE(lvwph->m_firstVisibleIndex, 0);
19001902 }
19011903
1904+ void testNoCacheBuffer()
1905+ {
1906+ lvwph->setCacheBuffer(0);
1907+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
1908+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1909+ verifyItem(0, 50., 150., false);
1910+ verifyItem(1, 200., 200., false);
1911+ verifyItem(2, 400., 350., false);
1912+ QCOMPARE(lvwph->m_minYExtent, 0.);
1913+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
1914+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1915+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1916+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1917+ QCOMPARE(lvwph->contentY(), 0.);
1918+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1919+ }
1920+
1921+ void testAllCacheBuffer()
1922+ {
1923+ lvwph->setCacheBuffer(std::numeric_limits<qreal>::max());
1924+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 6);
1925+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1926+ verifyItem(0, 50., 150., false);
1927+ verifyItem(1, 200., 200., false);
1928+ verifyItem(2, 400., 350., false);
1929+ verifyItem(3, 750., 350., true);
1930+ verifyItem(4, 1100., 350., true);
1931+ verifyItem(5, 1450., 350., true);
1932+ QCOMPARE(lvwph->m_minYExtent, 0.);
1933+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
1934+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1935+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1936+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1937+ QCOMPARE(lvwph->contentY(), 0.);
1938+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1939+ }
1940+
19021941private:
19031942 QQuickView *view;
19041943 ListViewWithPageHeader *lvwph;
tests/plugins/Dash/listviewwithpageheadertest.qml+1
@@ -60,6 +60,7 @@ Rectangle {
6060 anchors.top: parent.top
6161 anchors.bottom: parent.bottom
6262 model: model
63+ cacheBuffer: height * 0.5
6364 delegate: Rectangle {
6465 property bool timerDone: false
6566 width: parent.width - 20
tests/plugins/Dash/listviewwithpageheadertestsection.qml+1
@@ -60,6 +60,7 @@ Rectangle {
6060 anchors.top: parent.top
6161 anchors.bottom: parent.bottom
6262 model: model
63+ cacheBuffer: height * 0.5
6364 delegate: Rectangle {
6465 property bool timerDone: false
6566 width: parent.width - 20
tests/plugins/Dash/listviewwithpageheadertestsectionexternalmodel.qml+1
@@ -28,6 +28,7 @@ Rectangle {
2828 anchors.top: parent.top
2929 anchors.bottom: parent.bottom
3030 model: model
31+ cacheBuffer: height * 0.5
3132 delegate: Rectangle {
3233 property bool timerDone: false
3334 width: parent.width - 20
tests/plugins/Ubuntu/Gestures/CMakeLists.txt+1−1
@@ -19,7 +19,7 @@ macro(add_gesture_ui_test CLASSNAME)
1919 qt5_use_modules(${CLASSNAME}TestExec Test Core Qml Gui Quick)
2020 target_link_libraries(${CLASSNAME}TestExec UbuntuGestureQml)
2121
22− add_binary_qml_test(${CLASSNAME} ${CMAKE_BINARY_DIR}/plugins/Ubuntu/Gestures UbuntuGesturesTestQmlFiles)
22+ add_binary_qml_test(${CLASSNAME} ${CMAKE_BINARY_DIR}/plugins/Ubuntu/Gestures UbuntuGesturesTestQmlFiles "")
2323 add_manual_qml_test(. ${CLASSNAME} IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
2424endmacro(add_gesture_ui_test)
2525
tests/qmltests/Components/CMakeLists.txt+1−1
@@ -10,7 +10,7 @@ add_executable(DragHandleTestExec tst_DragHandle.cpp)
1010qt5_use_modules(DragHandleTestExec Test Core Qml Gui Quick)
1111target_link_libraries(DragHandleTestExec UbuntuGestureQml)
1212
13−add_binary_qml_test(DragHandle ${CMAKE_BINARY_DIR}/plugins/Ubuntu/Gestures "")
13+add_binary_qml_test(DragHandle ${CMAKE_BINARY_DIR}/plugins/Ubuntu/Gestures "" "")
1414add_manual_qml_test(. DragHandle IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
1515
1616add_definitions(-DUBUNTU_GESTURES_PLUGIN_DIR="${CMAKE_BINARY_DIR}/plugins")
tests/qmltests/Dash/tst_Card.qml+26
@@ -17,6 +17,7 @@
1717import QtQuick 2.0
1818import QtTest 1.0
1919import Ubuntu.Components 0.1
20+import Ubuntu.Connectivity 1.0
2021import Unity.Test 0.1 as UT
2122import "../../../qml/Dash"
2223import "CardHelpers.js" as Helpers
@@ -205,6 +206,11 @@ Rectangle {
205206 property Item backgroundImage: findChild(card, "backgroundImage")
206207 property Item mascotImage: findChild(card, "mascotImage");
207208
209+ function init() {
210+ loader.visible = true;
211+ NetworkingStatus.limitedBandwith = false;
212+ }
213+
208214 function cleanup() {
209215 selector.selectedIndex = -1;
210216 }
@@ -566,5 +572,25 @@ Rectangle {
566572 verify((card.width - titleToCard.x - titleToCard.width) === units.gu(1));
567573 }
568574 }
575+
576+ function test_load_images_visibility_network_data() {
577+ return [
578+ { tag: "Visible, network", visible: true, limitedBandwith: false },
579+ { tag: "Visible, no network", visible: true, limitedBandwith: true },
580+ { tag: "Not Visible, network", visible: false, limitedBandwith: false },
581+ { tag: "Not Visible, no network", visible: false, limitedBandwith: true }
582+ ];
583+ }
584+
585+ function test_load_images_visibility_network(data) {
586+ loader.visible = data.visible;
587+ NetworkingStatus.limitedBandwith = data.limitedBandwith;
588+
589+ selector.selectedIndex = 0;
590+ waitForRendering(selector);
591+ waitForRendering(card);
592+
593+ verify(data.visible || !data.limitedBandwith || artImage.source == "");
594+ }
569595 }
570596}
tests/qmltests/Dash/tst_Dash.qml+16−39
@@ -55,6 +55,16 @@ Item {
5555 scopes.load();
5656 tryCompare(dashContentList, "currentIndex", 0);
5757 tryCompare(dashContentList, "count", 6);
58+ tryCompare(scopes, "loaded", true);
59+ tryCompareFunction(function() {
60+ var mockScope1Loader = findChild(dash, "MockScope1 loader");
61+ return mockScope1Loader && mockScope1Loader.item != null; },
62+ true, 15000);
63+ tryCompareFunction(function() {
64+ var mockScope1Loader = findChild(dash, "MockScope1 loader");
65+ return mockScope1Loader && mockScope1Loader.status === Loader.Ready; },
66+ true, 15000);
67+ waitForRendering(findChild(dash, "MockScope1 loader").item);
5868 }
5969
6070 function get_scope_data() {
@@ -92,15 +102,6 @@ Item {
92102 }
93103
94104 function test_dash_overview_show_select_same_favorite() {
95− // Wait for stuff to be loaded
96− tryCompare(scopes, "loaded", true);
97− var dashContentList = findChild(dash, "dashContentList");
98− tryCompare(dashContentList, "count", 6);
99− tryCompareFunction(function() {
100− var mockScope1Loader = findChild(dash, "MockScope1 loader");
101− return mockScope1Loader && mockScope1Loader.item != null; },
102− true);
103−
104105 // Show the overview
105106 touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, dash.height - units.gu(18));
106107 var overviewController = findInvisibleChild(dash, "overviewController");
@@ -121,18 +122,12 @@ Item {
121122
122123 // Make sure animation went back
123124 tryCompare(overviewController, "progress", 0);
125+
126+ var dashContentList = findChild(dash, "dashContentList");
124127 compare(dashContentList.currentIndex, 0);
125128 }
126129
127130 function test_dash_overview_show_select_different_favorite() {
128− // Wait for stuff to be loaded
129− tryCompare(scopes, "loaded", true);
130− var dashContentList = findChild(dash, "dashContentList");
131− tryCompare(dashContentList, "count", 6);
132− tryCompareFunction(function() { return findChild(dash, "MockScope1 loader") != null; }, true);
133− var mockScope1Loader = findChild(dash, "MockScope1 loader");
134− tryCompare(mockScope1Loader, "status", Loader.Ready);
135−
136131 // Show the overview
137132 touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, dash.height - units.gu(18));
138133 var overviewController = findInvisibleChild(dash, "overviewController");
@@ -153,19 +148,11 @@ Item {
153148
154149 // Make sure animation went back
155150 tryCompare(overviewController, "progress", 0);
151+ var dashContentList = findChild(dash, "dashContentList");
156152 compare(dashContentList.currentIndex, 1);
157153 }
158154
159155 function test_dash_overview_all_temp_scope_done_from_all() {
160− // Wait for stuff to be loaded
161− tryCompare(scopes, "loaded", true);
162− var dashContentList = findChild(dash, "dashContentList");
163− tryCompare(dashContentList, "count", 6);
164− tryCompareFunction(function() {
165− var mockScope1Loader = findChild(dash, "MockScope1 loader");
166− return mockScope1Loader && mockScope1Loader.item != null; },
167− true);
168−
169156 // Show the overview
170157 touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, dash.height - units.gu(18));
171158 var overviewController = findInvisibleChild(dash, "overviewController");
@@ -227,20 +214,13 @@ Item {
227214 tryCompare(overviewController, "progress", 0);
228215
229216 // Original list is still on 0
217+ var dashContentList = findChild(dash, "dashContentList");
230218 compare(dashContentList.currentIndex, 0);
231219 }
232220
233221 function test_temp_scope_dash_overview_all_search_temp_scope_favorite_from_all() {
234− // Wait for stuff to be loaded
235− tryCompare(scopes, "loaded", true);
236− var dashContentList = findChild(dash, "dashContentList");
237− tryCompare(dashContentList, "count", 6);
238− tryCompareFunction(function() {
239− var mockScope1Loader = findChild(dash, "MockScope1 loader");
240− return mockScope1Loader && mockScope1Loader.item != null; },
241− true);
242−
243222 // Swipe right to Apps scope
223+ var dashContentList = findChild(dash, "dashContentList");
244224 touchFlick(dash, dash.width - 1, units.gu(1), dash.width - units.gu(10), units.gu(1));
245225 tryCompare(dashContentList, "contentX", dashContentList.width);
246226 tryCompare(dashContentList, "currentIndex", 1);
@@ -249,8 +229,7 @@ Item {
249229 var categoryListView = findChild(dashContentList.currentItem, "categoryListView");
250230 var dashCategory2 = findChild(categoryListView, "dashCategory2");
251231 tryCompareFunction(function() {
252− var d = findChild(dashCategory2, "delegate2");
253− if (d) return true;
232+ if (dashCategory2.y < 200) return true;
254233 categoryListView.contentY += 100;
255234 return false;
256235 }, true);
@@ -340,8 +319,6 @@ Item {
340319 }
341320
342321 function test_processing_indicator() {
343− tryCompare(scopes, "loaded", true);
344−
345322 var processingIndicator = findChild(dash, "processingIndicator");
346323 verify(processingIndicator, "Can't find the processing indicator.");
347324
tests/qmltests/Dash/tst_DashContent.qml+14−1
@@ -70,7 +70,17 @@ Item {
7070 function loadScopes() {
7171 scopeLoadedSpy.clear();
7272 scopesModel.load();
73− tryCompare(scopeLoadedSpy, "count", 6);
73+ tryCompare(scopeLoadedSpy, "count", 6, 15000);
74+ tryCompare(scopesModel, "loaded", true);
75+ tryCompareFunction(function() {
76+ var mockScope1Loader = findChild(shell, "MockScope1 loader");
77+ return mockScope1Loader && mockScope1Loader.item != null; },
78+ true, 15000);
79+ tryCompareFunction(function() {
80+ var mockScope1Loader = findChild(shell, "MockScope1 loader");
81+ return mockScope1Loader && mockScope1Loader.status === Loader.Ready; },
82+ true, 15000);
83+ waitForRendering(findChild(shell, "MockScope1 loader").item);
7484 }
7585
7686 function init() {
@@ -467,6 +477,9 @@ Item {
467477 var navigationListView = findChild(dashAltNavigationButton, "navigationListView");
468478 tryCompare(navigationListView.currentItem.navigation, "loaded", true);
469479
480+ var blackRect = findChild(dashNavigation, "blackRect");
481+ tryCompare(blackRect, "opacity", 0.5);
482+
470483 mouseClick(dashNavigation, dashNavigationButton.x, 0);
471484 compare(dashNavigationButton.showList, false);
472485 compare(dashAltNavigationButton.showList, false);
tests/qmltests/Dash/tst_GenericScopeView.qml+7−6
@@ -82,18 +82,19 @@ Item {
8282 spy.signalName = "";
8383 }
8484
85− function scrollToCategory(category) {
85+ function scrollToCategory(categoryName) {
8686 var categoryListView = findChild(genericScopeView, "categoryListView");
8787 tryCompareFunction(function() {
88− if (findChild(genericScopeView, category)) return true;
88+ var category = findChild(genericScopeView, categoryName);
89+ if (category && category.y > 0 && category.y < genericScopeView.height) return true;
8990 mouseFlick(genericScopeView, genericScopeView.width/2, genericScopeView.height,
9091 genericScopeView.width/2, genericScopeView.y)
9192 tryCompare(categoryListView, "moving", false);
92− return findChild(genericScopeView, category) !== null;
93+ return false;
9394 }, true);
9495
9596 tryCompareFunction(function() { return findChild(genericScopeView, "delegate0") !== null; }, true);
96− return findChild(genericScopeView, category);
97+ return findChild(genericScopeView, categoryName);
9798 }
9899
99100 function scrollToEnd()
@@ -283,7 +284,7 @@ Item {
283284 if (category === undefined) category = 0;
284285 if (delegate === undefined) delegate = 0;
285286 tryCompareFunction(function() {
286− var cardGrid = findChild(genericScopeView, category);
287+ var cardGrid = findChild(genericScopeView, "dashCategory"+category);
287288 if (cardGrid != null) {
288289 var tile = findChild(cardGrid, "delegate"+delegate);
289290 return tile != null;
@@ -291,7 +292,7 @@ Item {
291292 return false;
292293 },
293294 true);
294− var tile = findChild(findChild(genericScopeView, category), "delegate"+delegate);
295+ var tile = findChild(findChild(genericScopeView, "dashCategory"+category), "delegate"+delegate);
295296 mouseClick(tile, tile.width / 2, tile.height / 2);
296297 tryCompare(testCase.subPageLoader, "open", true);
297298 tryCompare(testCase.subPageLoader, "x", 0);
tests/utils/modules/Unity/Test/UnityTestCase.qml+3−2
@@ -178,9 +178,10 @@ TestCase {
178178 // Keeps executing a given parameter-less function until it returns the given
179179 // expected result or the timemout is reached (in which case a test failure
180180 // is generated)
181− function tryCompareFunction(func, expectedResult) {
181+ function tryCompareFunction(func, expectedResult, timeout) {
182182 var timeSpent = 0
183− var timeout = 5000
183+ if (timeout === undefined)
184+ timeout = 5000;
184185 var success = false
185186 var actualResult
186187 while (timeSpent < timeout && !success) {