on xenial help sign in
Cache more things in memory, so flicking scopes should be faster Fixes: 1336724, 1338430
69598faMichał Sawicz
@@ -51,6 +51,7 @@ install_dependencies() {
51 qtdeclarative5-ubuntu-settings-components \
51 qtdeclarative5-ubuntu-settings-components \
52 qtdeclarative5-ubuntu-telephony0.1 \
52 qtdeclarative5-ubuntu-telephony0.1 \
53 qtdeclarative5-ubuntu-thumbnailer0.1 \
53 qtdeclarative5-ubuntu-thumbnailer0.1 \
54+ qml-module-ubuntu-connectivity \
54 unity-notifications-impl \
55 unity-notifications-impl \
55 ubuntu-mobile-icons \
56 ubuntu-mobile-icons \
56 unity-scope-home \
57 unity-scope-home \
cmake/modules/QmlTest.cmake+2−1
@@ -151,7 +151,7 @@ macro(add_qml_test_internal SUBPATH COMPONENT_NAME ITERATIONS)
151 add_manual_qml_test(${SUBPATH} ${COMPONENT_NAME} ${ARGN})
151 add_manual_qml_test(${SUBPATH} ${COMPONENT_NAME} ${ARGN})
152endmacro(add_qml_test_internal)
152endmacro(add_qml_test_internal)
153
153
154−macro(add_binary_qml_test CLASS_NAME LD_PATH DEPS)
154+macro(add_binary_qml_test CLASS_NAME LD_PATH DEPS ENVVAR)
155 set(testCommand
155 set(testCommand
156 LD_LIBRARY_PATH=${LD_PATH}
156 LD_LIBRARY_PATH=${LD_PATH}
157 ${CMAKE_CURRENT_BINARY_DIR}/${CLASS_NAME}TestExec
157 ${CMAKE_CURRENT_BINARY_DIR}/${CLASS_NAME}TestExec
@@ -168,6 +168,7 @@ macro(add_binary_qml_test CLASS_NAME LD_PATH DEPS)
168 endif()
168 endif()
169 set(xvfbtestCommand
169 set(xvfbtestCommand
170 ${LD_PRELOAD_PATH}
170 ${LD_PRELOAD_PATH}
171+ ${ENVVAR}
171 LD_LIBRARY_PATH=${LD_PATH}
172 LD_LIBRARY_PATH=${LD_PATH}
172 xvfb-run --server-args "-screen 0 1024x768x24" --auto-servernum
173 xvfb-run --server-args "-screen 0 1024x768x24" --auto-servernum
173 ${CMAKE_CURRENT_BINARY_DIR}/${CLASS_NAME}TestExec
174 ${CMAKE_CURRENT_BINARY_DIR}/${CLASS_NAME}TestExec
debian/control+1
@@ -174,6 +174,7 @@ Depends: accountsservice-ubuntu-schemas (>= 0.0.3),
174 libhardware2,
174 libhardware2,
175 unity-schemas (>= 7.3.1+14.10.20140915),
175 unity-schemas (>= 7.3.1+14.10.20140915),
176 pay-service,
176 pay-service,
177+ qml-module-ubuntu-connectivity,
177 ${misc:Depends},
178 ${misc:Depends},
178 ${shlibs:Depends},
179 ${shlibs:Depends},
179Provides: unity-launcher-impl,
180Provides: unity-launcher-impl,
plugins/Dash/CardCreator.js+5−2
@@ -84,7 +84,8 @@ var kArtShapeHolderCode = 'Item { \n\
84 } \n\
84 } \n\
85 image: Image { \n\
85 image: Image { \n\
86 objectName: "artImage"; \n\
86 objectName: "artImage"; \n\
87+ property bool doLoadSource: !NetworkingStatus.limitedBandwith; \n\
87− source: cardData && cardData["art"] || ""; \n\
88+ source: { if (root.visible) doLoadSource = true; return doLoadSource && cardData && cardData["art"] || ""; } \n\
88 cache: true; \n\
89 cache: true; \n\
89 asynchronous: root.asynchronous; \n\
90 asynchronous: root.asynchronous; \n\
90 fillMode: Image.PreserveAspectCrop; \n\
91 fillMode: Image.PreserveAspectCrop; \n\
@@ -195,7 +196,8 @@ var kMascotImageCode = 'Image { \n\
195 objectName: "mascotImage"; \n\
196 objectName: "mascotImage"; \n\
196 anchors { %1 } \n\
197 anchors { %1 } \n\
197 readonly property int maxSize: Math.max(width, height) * 4; \n\
198 readonly property int maxSize: Math.max(width, height) * 4; \n\
199+ property bool doLoadSource: !NetworkingStatus.limitedBandwith; \n\
198− source: cardData && cardData["mascot"] || ""; \n\
200+ source: { if (root.visible) doLoadSource = true; return doLoadSource && cardData && cardData["mascot"] || ""; } \n\
199 width: units.gu(6); \n\
201 width: units.gu(6); \n\
200 height: units.gu(5.625); \n\
202 height: units.gu(5.625); \n\
201 sourceSize { width: maxSize; height: maxSize } \n\
203 sourceSize { width: maxSize; height: maxSize } \n\
@@ -655,6 +657,7 @@ function cardString(template, components) {
655function createCardComponent(parent, template, components) {
657function createCardComponent(parent, template, components) {
656 var imports = 'import QtQuick 2.2; \n\
658 var imports = 'import QtQuick 2.2; \n\
657 import Ubuntu.Components 1.1; \n\
659 import Ubuntu.Components 1.1; \n\
660+ import Ubuntu.Connectivity 1.0; \n\
658 import Dash 0.1;\n\
661 import Dash 0.1;\n\
659 import Utils 0.1;\n';
662 import Utils 0.1;\n';
660 var card = cardString(template, components);
663 var card = cardString(template, components);
plugins/Dash/listviewwithpageheader.cpp+18−7
@@ -104,8 +104,6 @@
104#pragma GCC diagnostic pop
104#pragma GCC diagnostic pop
105// #include <private/qquickrectangle_p.h>
105// #include <private/qquickrectangle_p.h>
106
106
107−static const qreal bufferRatio = 0.5;
108−
109qreal ListViewWithPageHeader::ListItem::height() const
107qreal ListViewWithPageHeader::ListItem::height() const
110{
108{
111 return m_item->height() + (m_sectionItem ? m_sectionItem->height() : 0);
109 return m_item->height() + (m_sectionItem ? m_sectionItem->height() : 0);
@@ -158,6 +156,7 @@ ListViewWithPageHeader::ListViewWithPageHeader()
158 , m_forceNoClip(false)
156 , m_forceNoClip(false)
159 , m_inLayout(false)
157 , m_inLayout(false)
160 , m_inContentHeightKeepHeaderShown(false)
158 , m_inContentHeightKeepHeaderShown(false)
159+ , m_cacheBuffer(0)
161{
160{
162 m_clipItem = new QQuickItem(contentItem());
161 m_clipItem = new QQuickItem(contentItem());
163// m_clipItem = new QQuickRectangle(contentItem());
162// m_clipItem = new QQuickRectangle(contentItem());
@@ -335,6 +334,20 @@ qreal ListViewWithPageHeader::headerItemShownHeight() const
335 return m_headerItemShownHeight;
334 return m_headerItemShownHeight;
336}
335}
337
336
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+
338void ListViewWithPageHeader::positionAtBeginning()
351void ListViewWithPageHeader::positionAtBeginning()
339{
352{
340 if (m_delegateModel->count() <= 0)
353 if (m_delegateModel->count() <= 0)
@@ -356,8 +369,7 @@ void ListViewWithPageHeader::positionAtBeginning()
356 // Create the subsequent items
369 // Create the subsequent items
357 int modelIndex = 1;
370 int modelIndex = 1;
358 qreal pos = item->y() + item->height();
371 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;
361 while (modelIndex < m_delegateModel->count() && pos <= bufferTo) {
373 while (modelIndex < m_delegateModel->count() && pos <= bufferTo) {
362 if (!(item = createItem(modelIndex, false)))
374 if (!(item = createItem(modelIndex, false)))
363 break;
375 break;
@@ -603,11 +615,10 @@ void ListViewWithPageHeader::refill()
603 return;
615 return;
604 }
616 }
605
617
606− const qreal buffer = height() * bufferRatio;
607 const qreal from = contentY();
618 const qreal from = contentY();
608 const qreal to = from + height();
619 const qreal to = from + height();
609− const qreal bufferFrom = from - buffer;
620+ const qreal bufferFrom = from - m_cacheBuffer;
610− const qreal bufferTo = to + buffer;
621+ const qreal bufferTo = to + m_cacheBuffer;
611
622
612 bool added = addVisibleItems(from, to, false);
623 bool added = addVisibleItems(from, to, false);
613 bool removed = removeNonVisibleItems(bufferFrom, bufferTo);
624 bool removed = removeNonVisibleItems(bufferFrom, bufferTo);
plugins/Dash/listviewwithpageheader.h+6
@@ -54,6 +54,7 @@ class ListViewWithPageHeader : public QQuickFlickable, public QQuickItemChangeLi
54 Q_PROPERTY(bool forceNoClip READ forceNoClip WRITE setForceNoClip NOTIFY forceNoClipChanged)
54 Q_PROPERTY(bool forceNoClip READ forceNoClip WRITE setForceNoClip NOTIFY forceNoClipChanged)
55 Q_PROPERTY(int stickyHeaderHeight READ stickyHeaderHeight NOTIFY stickyHeaderHeightChanged)
55 Q_PROPERTY(int stickyHeaderHeight READ stickyHeaderHeight NOTIFY stickyHeaderHeightChanged)
56 Q_PROPERTY(qreal headerItemShownHeight READ headerItemShownHeight NOTIFY headerItemShownHeightChanged)
56 Q_PROPERTY(qreal headerItemShownHeight READ headerItemShownHeight NOTIFY headerItemShownHeightChanged)
57+ Q_PROPERTY(qreal cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY cacheBufferChanged)
57
58
58 friend class ListViewWithPageHeaderTest;
59 friend class ListViewWithPageHeaderTest;
59 friend class ListViewWithPageHeaderTestSection;
60 friend class ListViewWithPageHeaderTestSection;
@@ -84,6 +85,9 @@ public:
84 int stickyHeaderHeight() const;
85 int stickyHeaderHeight() const;
85 qreal headerItemShownHeight() const;
86 qreal headerItemShownHeight() const;
86
87
88+ qreal cacheBuffer() const;
89+ void setCacheBuffer(qreal cacheBuffer);
90+
87 Q_INVOKABLE void positionAtBeginning();
91 Q_INVOKABLE void positionAtBeginning();
88 Q_INVOKABLE void showHeader();
92 Q_INVOKABLE void showHeader();
89 Q_INVOKABLE int firstCreatedIndex() const;
93 Q_INVOKABLE int firstCreatedIndex() const;
@@ -105,6 +109,7 @@ Q_SIGNALS:
105 void forceNoClipChanged();
109 void forceNoClipChanged();
106 void stickyHeaderHeightChanged();
110 void stickyHeaderHeightChanged();
107 void headerItemShownHeightChanged();
111 void headerItemShownHeightChanged();
112+ void cacheBufferChanged();
108
113
109protected:
114protected:
110 void componentComplete() override;
115 void componentComplete() override;
@@ -199,6 +204,7 @@ private:
199 bool m_forceNoClip;
204 bool m_forceNoClip;
200 bool m_inLayout;
205 bool m_inLayout;
201 bool m_inContentHeightKeepHeaderShown;
206 bool m_inContentHeightKeepHeaderShown;
207+ qreal m_cacheBuffer;
202
208
203 // Qt 5.0 doesn't like releasing the items just after itemCreated
209 // Qt 5.0 doesn't like releasing the items just after itemCreated
204 // so we delay the releasing until the next updatePolish
210 // so we delay the releasing until the next updatePolish
qml/Components/ResponsiveGridView.qml+5−1
@@ -34,7 +34,11 @@ Item {
34 readonly property int cellWidth: gridView.cellWidth
34 readonly property int cellWidth: gridView.cellWidth
35 readonly property int cellHeight: gridView.cellHeight
35 readonly property int cellHeight: gridView.cellHeight
36 readonly property int totalContentHeight: {
36 readonly property int totalContentHeight: {
37+ if (gridView.model) {
37− return contentHeightForRows(Math.ceil(gridView.model.count / columns), cellHeight)
38+ return contentHeightForRows(Math.ceil(gridView.model.count / columns), cellHeight)
39+ } else {
40+ return 0;
41+ }
38 }
42 }
39 property alias interactive: gridView.interactive
43 property alias interactive: gridView.interactive
40 readonly property alias flicking: gridView.flicking
44 readonly property alias flicking: gridView.flicking
qml/Dash/CardGrid.qml+1
@@ -55,6 +55,7 @@ DashRenderer {
55 delegate: Item {
55 delegate: Item {
56 width: grid.cellWidth
56 width: grid.cellWidth
57 height: grid.cellHeight
57 height: grid.cellHeight
58+ visible: y + height >= root.visibleRangeBegin && y <= root.visibleRangeEnd
58 Loader {
59 Loader {
59 id: loader
60 id: loader
60 sourceComponent: cardTool.cardComponent
61 sourceComponent: cardTool.cardComponent
qml/Dash/CardTool.qml+8−5
@@ -169,16 +169,19 @@ Item {
169
169
170 Item {
170 Item {
171 id: attributesModel
171 id: attributesModel
172− property int numOfAttributes: {
172+ property int numOfAttributes: 0
173+ property var model: []
174+ property bool hasAttributes: {
173 var attributes = components["attributes"];
175 var attributes = components["attributes"];
174− if ((attributes != undefined) && attributes["field"]) {
176+ var hasAttributesFlag = (attributes != undefined) && attributes["field"];
177+
178+ if (hasAttributesFlag) {
175 if (attributes["max-count"]) {
179 if (attributes["max-count"]) {
176− return attributes["max-count"];
180+ numOfAttributes = attributes["max-count"];
177 }
181 }
178 }
182 }
179− return 0;
183+ return hasAttributesFlag
180 }
184 }
181− property var model: []
182
185
183 onNumOfAttributesChanged: {
186 onNumOfAttributesChanged: {
184 model = []
187 model = []
qml/Dash/CardVerticalJournal.qml+1
@@ -49,6 +49,7 @@ DashRenderer {
49 id: loader
49 id: loader
50 sourceComponent: cardTool.cardComponent
50 sourceComponent: cardTool.cardComponent
51 width: cardTool.cardWidth
51 width: cardTool.cardWidth
52+ visible: y + height >= root.visibleRangeBegin && y <= root.visibleRangeEnd
52 onLoaded: {
53 onLoaded: {
53 item.objectName = "delegate" + index;
54 item.objectName = "delegate" + index;
54 item.fixedArtShapeSize = Qt.binding(function() { return cardTool.artShapeSize; });
55 item.fixedArtShapeSize = Qt.binding(function() { return cardTool.artShapeSize; });
qml/Dash/DashContent.qml+3
@@ -111,6 +111,8 @@ Item {
111 highlightMoveDuration: 250
111 highlightMoveDuration: 250
112 highlightRangeMode: ListView.StrictlyEnforceRange
112 highlightRangeMode: ListView.StrictlyEnforceRange
113 // TODO Investigate if we can switch to a smaller cache buffer when/if UbuntuShape gets more performant
113 // 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
114 cacheBuffer: 1073741823
116 cacheBuffer: 1073741823
115 onMovementStarted: currentItem.item.showHeader();
117 onMovementStarted: currentItem.item.showHeader();
116 clip: parent.x != 0
118 clip: parent.x != 0
@@ -177,6 +179,7 @@ Item {
177 dashContent.scopeLoaded(item.scope.id)
179 dashContent.scopeLoaded(item.scope.id)
178 item.paginationCount = Qt.binding(function() { return dashContentList.count } )
180 item.paginationCount = Qt.binding(function() { return dashContentList.count } )
179 item.paginationIndex = Qt.binding(function() { return dashContentList.currentIndex } )
181 item.paginationIndex = Qt.binding(function() { return dashContentList.currentIndex } )
182+ item.holdingList = dashContentList;
180 }
183 }
181 Connections {
184 Connections {
182 target: isCurrent ? scope : null
185 target: isCurrent ? scope : null
qml/Dash/DashNavigation.qml+1
@@ -52,6 +52,7 @@ Item {
52
52
53 Rectangle {
53 Rectangle {
54 id: blackRect
54 id: blackRect
55+ objectName: "blackRect"
55 color: "black"
56 color: "black"
56 opacity: openList && openList.currentItem && openList.currentItem.visible ? 0.5 : 0
57 opacity: openList && openList.currentItem && openList.currentItem.visible ? 0.5 : 0
57 Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
58 Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
qml/Dash/DashRenderer.qml+4
@@ -27,6 +27,10 @@ Item {
27
27
28 property int displayMarginEnd: 0
28 property int displayMarginEnd: 0
29
29
30+ property int visibleRangeBegin: 0
31+
32+ property int visibleRangeEnd: 0
33+
30 property real originY: 0
34 property real originY: 0
31
35
32 // The model to renderer
36 // The model to renderer
qml/Dash/GenericScopeView.qml+35−12
@@ -38,6 +38,7 @@ FocusScope {
38 property int paginationCount: 0
38 property int paginationCount: 0
39 property int paginationIndex: 0
39 property int paginationIndex: 0
40 property alias pageHeaderTotallyVisible: categoryView.pageHeaderTotallyVisible
40 property alias pageHeaderTotallyVisible: categoryView.pageHeaderTotallyVisible
41+ property var holdingList: null
41
42
42 property var scopeStyle: ScopeStyle {
43 property var scopeStyle: ScopeStyle {
43 style: scope ? scope.customizations : {}
44 style: scope ? scope.customizations : {}
@@ -251,8 +252,8 @@ FocusScope {
251 }
252 }
252 }
253 }
253
254
254− onHeightChanged: rendererLoader.updateDelegateCreationRange();
255+ onHeightChanged: rendererLoader.updateRanges();
255− onYChanged: rendererLoader.updateDelegateCreationRange();
256+ onYChanged: rendererLoader.updateRanges();
256
257
257 Loader {
258 Loader {
258 id: rendererLoader
259 id: rendererLoader
@@ -314,7 +315,7 @@ FocusScope {
314 var shouldExpand = baseItem.category === categoryView.expandedCategoryId;
315 var shouldExpand = baseItem.category === categoryView.expandedCategoryId;
315 baseItem.expand(shouldExpand, false /*animate*/);
316 baseItem.expand(shouldExpand, false /*animate*/);
316 }
317 }
317− updateDelegateCreationRange();
318+ updateRanges();
318 if (scope && scope.id === "clickscope" && (categoryId === "predefined" || categoryId === "local")) {
319 if (scope && scope.id === "clickscope" && (categoryId === "predefined" || categoryId === "local")) {
319 // Yeah, hackish :/
320 // Yeah, hackish :/
320 cardTool.artShapeSize = Qt.size(units.gu(8), units.gu(7.5));
321 cardTool.artShapeSize = Qt.size(units.gu(8), units.gu(7.5));
@@ -348,13 +349,25 @@ FocusScope {
348 }
349 }
349 Connections {
350 Connections {
350 target: categoryView
351 target: categoryView
351− onOriginYChanged: rendererLoader.updateDelegateCreationRange();
352+ onOriginYChanged: rendererLoader.updateRanges();
352− onContentYChanged: rendererLoader.updateDelegateCreationRange();
353+ onContentYChanged: rendererLoader.updateRanges();
353− onHeightChanged: rendererLoader.updateDelegateCreationRange();
354+ onHeightChanged: rendererLoader.updateRanges();
354− onContentHeightChanged: rendererLoader.updateDelegateCreationRange();
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();
355 }
364 }
356
365
357− function updateDelegateCreationRange() {
366+ function updateRanges() {
367+ if (holdingList && holdingList.moving) {
368+ return;
369+ }
370+
358 if (categoryView.moving) {
371 if (categoryView.moving) {
359 // Do not update the range if we are overshooting up or down, since we'll come back
372 // Do not update the range if we are overshooting up or down, since we'll come back
360 // to the stable position and delete/create items without any reason
373 // to the stable position and delete/create items without any reason
@@ -366,10 +379,20 @@ FocusScope {
366 }
379 }
367 }
380 }
368
381
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+
369 if (item && item.hasOwnProperty("displayMarginBeginning")) {
387 if (item && item.hasOwnProperty("displayMarginBeginning")) {
370 // TODO do we need item.originY here, test 1300302 once we have a silo
388 // TODO do we need item.originY here, test 1300302 once we have a silo
371 // and we can run it on the phone
389 // and we can run it on the phone
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;
372− if (baseItem.y + baseItem.height <= 0) {
395+ } else if (baseItem.y + baseItem.height <= 0) {
373 // Not visible (item at top of the list viewport)
396 // Not visible (item at top of the list viewport)
374 item.displayMarginBeginning = -baseItem.height;
397 item.displayMarginBeginning = -baseItem.height;
375 item.displayMarginEnd = 0;
398 item.displayMarginEnd = 0;
@@ -378,9 +401,9 @@ FocusScope {
378 item.displayMarginBeginning = 0;
401 item.displayMarginBeginning = 0;
379 item.displayMarginEnd = -baseItem.height;
402 item.displayMarginEnd = -baseItem.height;
380 } else {
403 } else {
381− item.displayMarginBeginning = -Math.max(-baseItem.y, 0);
404+ item.displayMarginBeginning = Math.round(-Math.max(-baseItem.y, 0));
382− item.displayMarginEnd = -Math.max(baseItem.height - seeAll.height
405+ item.displayMarginEnd = -Math.round(Math.max(baseItem.height - seeAll.height -
383− - categoryView.height + baseItem.y, 0)
406+ categoryView.height + baseItem.y, 0));
384 }
407 }
385 }
408 }
386 }
409 }
qml/Dash/ScopeListView.qml+1
@@ -20,4 +20,5 @@ import Dash 0.1
20ListViewWithPageHeader {
20ListViewWithPageHeader {
21 maximumFlickVelocity: height * 10
21 maximumFlickVelocity: height * 10
22 flickDeceleration: height * 2
22 flickDeceleration: height * 2
23+ cacheBuffer: Number.MAX_VALUE
23}
24}
qml/Dash/ScopesOverviewAll.qml+2
@@ -43,6 +43,8 @@ Flickable {
43 id: cardGrid
43 id: cardGrid
44 width: root.width
44 width: root.width
45 height: parent.height
45 height: parent.height
46+ visibleRangeBegin: root.contentY
47+ visibleRangeEnd: root.contentY + root.height
46
48
47 onClicked: {
49 onClicked: {
48 root.clicked(index, result, item, itemModel);
50 root.clicked(index, result, item, itemModel);
tests/autopilot/unity8/shell/emulators/dash.py+2−2
@@ -93,7 +93,7 @@ class Dash(emulators.UnityEmulatorBase):
93 'No scope found with id {0}'.format(scope_id))
93 'No scope found with id {0}'.format(scope_id))
94
94
95 def _get_scope_from_loader(self, loader):
95 def _get_scope_from_loader(self, loader):
96− return loader.get_children()[0]
96+ return loader.wait_select_single('GenericScopeView');
97
97
98 def _open_scope_scrolling(self, scope_loader):
98 def _open_scope_scrolling(self, scope_loader):
99 scroll = self._get_scroll_direction(scope_loader)
99 scroll = self._get_scroll_direction(scope_loader)
@@ -102,8 +102,8 @@ class Dash(emulators.UnityEmulatorBase):
102 scroll()
102 scroll()
103 self.dash_content_list.moving.wait_for(False)
103 self.dash_content_list.moving.wait_for(False)
104
104
105+ scope_loader.isCurrent.wait_for(True)
105 scope = self._get_scope_from_loader(scope_loader)
106 scope = self._get_scope_from_loader(scope_loader)
106− scope.isCurrent.wait_for(True)
107 return scope
107 return scope
108
108
109 def _get_scroll_direction(self, scope_loader):
109 def _get_scroll_direction(self, scope_loader):
tests/mocks/Ubuntu/CMakeLists.txt+1
@@ -1,3 +1,4 @@
1+add_subdirectory(Connectivity)
1add_subdirectory(DownloadDaemonListener)
2add_subdirectory(DownloadDaemonListener)
2add_subdirectory(Payments)
3add_subdirectory(Payments)
3add_subdirectory(SystemImage)
4add_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)
32 qt5_use_modules(${TESTNAME}TestExec Test Core Qml)
32 qt5_use_modules(${TESTNAME}TestExec Test Core Qml)
33 target_link_libraries(${TESTNAME}TestExec ${Qt5Gui_LIBRARIES} ${Qt5Quick_LIBRARIES})
33 target_link_libraries(${TESTNAME}TestExec ${Qt5Gui_LIBRARIES} ${Qt5Quick_LIBRARIES})
34
34
35− add_binary_qml_test(${TESTNAME} "" "Dash-qml")
35+ add_binary_qml_test(${TESTNAME} "" "Dash-qml" "")
36endmacro()
36endmacro()
37
37
38add_lvwph_test(listviewwithpageheader ListViewWithPageHeader)
38add_lvwph_test(listviewwithpageheader ListViewWithPageHeader)
@@ -48,7 +48,7 @@ macro(add_dashview_try_test FILENAME TESTNAME)
48 qt5_use_modules(${TESTNAME}TestExec Test Core Qml)
48 qt5_use_modules(${TESTNAME}TestExec Test Core Qml)
49 target_link_libraries(${TESTNAME}TestExec ${Qt5Gui_LIBRARIES} ${Qt5Quick_LIBRARIES})
49 target_link_libraries(${TESTNAME}TestExec ${Qt5Gui_LIBRARIES} ${Qt5Quick_LIBRARIES})
50
50
51− add_binary_qml_test(${TESTNAME} "" "Dash-qml")
51+ add_binary_qml_test(${TESTNAME} "" "Dash-qml" "")
52
52
53 add_executable(${TESTNAME}tryExec
53 add_executable(${TESTNAME}tryExec
54 ${FILENAME}try.cpp
54 ${FILENAME}try.cpp
@@ -71,7 +71,7 @@ add_dashview_try_test(organicgrid OrganicGrid)
71add_executable(CardCreatorTestExec cardcreatortest.cpp)
71add_executable(CardCreatorTestExec cardcreatortest.cpp)
72qt5_use_modules(CardCreatorTestExec Test Core Qml)
72qt5_use_modules(CardCreatorTestExec Test Core Qml)
73target_link_libraries(CardCreatorTestExec ${Qt5Gui_LIBRARIES} ${Qt5Quick_LIBRARIES})
73target_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/")
75
75
76# plain qml test
76# plain qml test
77set(qmltest_DEFAULT_TARGETS qmluitests)
77set(qmltest_DEFAULT_TARGETS qmluitests)
tests/plugins/Dash/cardcreator/1.res+2−1
@@ -46,7 +46,8 @@ Item {
46 }
46 }
47 image: Image {
47 image: Image {
48 objectName: "artImage";
48 objectName: "artImage";
49+ property bool doLoadSource: !NetworkingStatus.limitedBandwith;
49− source: cardData && cardData["art"] || "";
50+ source: { if (root.visible) doLoadSource = true; return doLoadSource && cardData && cardData["art"] || ""; }
50 cache: true;
51 cache: true;
51 asynchronous: root.asynchronous;
52 asynchronous: root.asynchronous;
52 fillMode: Image.PreserveAspectCrop;
53 fillMode: Image.PreserveAspectCrop;
tests/plugins/Dash/cardcreator/2.res+2−1
@@ -67,7 +67,8 @@ Image {
67 objectName: "mascotImage";
67 objectName: "mascotImage";
68 anchors { verticalCenter: parent.verticalCenter; }
68 anchors { verticalCenter: parent.verticalCenter; }
69 readonly property int maxSize: Math.max(width, height) * 4;
69 readonly property int maxSize: Math.max(width, height) * 4;
70+ property bool doLoadSource: !NetworkingStatus.limitedBandwith;
70− source: cardData && cardData["mascot"] || "";
71+ source: { if (root.visible) doLoadSource = true; return doLoadSource && cardData && cardData["mascot"] || ""; }
71 width: units.gu(6);
72 width: units.gu(6);
72 height: units.gu(5.625);
73 height: units.gu(5.625);
73 sourceSize { width: maxSize; height: maxSize }
74 sourceSize { width: maxSize; height: maxSize }
tests/plugins/Dash/cardcreator/3.res+3−2
@@ -46,8 +46,9 @@ Item {
46 }
46 }
47 image: Image {
47 image: Image {
48 objectName: "artImage";
48 objectName: "artImage";
49+ property bool doLoadSource: !NetworkingStatus.limitedBandwith;
49− source: cardData && cardData["art"] || "";
50+ source: { if (root.visible) doLoadSource = true; return doLoadSource && cardData && cardData["art"] || ""; }
50− cache: true;
51+ cache: true;
51 asynchronous: root.asynchronous;
52 asynchronous: root.asynchronous;
52 fillMode: Image.PreserveAspectCrop;
53 fillMode: Image.PreserveAspectCrop;
53 width: root.width;
54 width: root.width;
tests/plugins/Dash/cardcreator/4.res+3−2
@@ -46,8 +46,9 @@ Loader {
46 objectName: "mascotImage";
46 objectName: "mascotImage";
47 anchors { verticalCenter: parent.verticalCenter; }
47 anchors { verticalCenter: parent.verticalCenter; }
48 readonly property int maxSize: Math.max(width, height) * 4;
48 readonly property int maxSize: Math.max(width, height) * 4;
49+ property bool doLoadSource: !NetworkingStatus.limitedBandwith;
49− source: cardData && cardData["mascot"] || "";
50+ source: { if (root.visible) doLoadSource = true; return doLoadSource && cardData && cardData["mascot"] || ""; }
50− width: units.gu(6);
51+ width: units.gu(6);
51 height: units.gu(5.625);
52 height: units.gu(5.625);
52 sourceSize { width: maxSize; height: maxSize }
53 sourceSize { width: maxSize; height: maxSize }
53 fillMode: Image.PreserveAspectCrop;
54 fillMode: Image.PreserveAspectCrop;
tests/plugins/Dash/cardcreator/5.res+3−2
@@ -46,8 +46,9 @@ Item {
46 }
46 }
47 image: Image {
47 image: Image {
48 objectName: "artImage";
48 objectName: "artImage";
49+ property bool doLoadSource: !NetworkingStatus.limitedBandwith;
49− source: cardData && cardData["art"] || "";
50+ source: { if (root.visible) doLoadSource = true; return doLoadSource && cardData && cardData["art"] || ""; }
50− cache: true;
51+ cache: true;
51 asynchronous: root.asynchronous;
52 asynchronous: root.asynchronous;
52 fillMode: Image.PreserveAspectCrop;
53 fillMode: Image.PreserveAspectCrop;
53 width: root.width;
54 width: root.width;
tests/plugins/Dash/cardcreator/7.res+3−2
@@ -67,8 +67,9 @@ Image {
67 objectName: "mascotImage";
67 objectName: "mascotImage";
68 anchors { verticalCenter: parent.verticalCenter; }
68 anchors { verticalCenter: parent.verticalCenter; }
69 readonly property int maxSize: Math.max(width, height) * 4;
69 readonly property int maxSize: Math.max(width, height) * 4;
70+ property bool doLoadSource: !NetworkingStatus.limitedBandwith;
70− source: cardData && cardData["mascot"] || "";
71+ source: { if (root.visible) doLoadSource = true; return doLoadSource && cardData && cardData["mascot"] || ""; }
71− width: units.gu(6);
72+ width: units.gu(6);
72 height: units.gu(5.625);
73 height: units.gu(5.625);
73 sourceSize { width: maxSize; height: maxSize }
74 sourceSize { width: maxSize; height: maxSize }
74 fillMode: Image.PreserveAspectCrop;
75 fillMode: Image.PreserveAspectCrop;
tests/plugins/Dash/listviewwithpageheadertest.cpp+39
@@ -28,6 +28,8 @@
28#include <private/qquickitem_p.h>
28#include <private/qquickitem_p.h>
29#pragma GCC diagnostic pop
29#pragma GCC diagnostic pop
30
30
31+#include <limits>
32+
31// TODO Think on how doing a test for lost items
33// TODO Think on how doing a test for lost items
32// particullary making sure that lost items are culled
34// particullary making sure that lost items are culled
33// and then removed in the next updatePolish cycle
35// and then removed in the next updatePolish cycle
@@ -1899,6 +1901,43 @@ private Q_SLOTS:
1899 QTRY_COMPARE(lvwph->m_firstVisibleIndex, 0);
1901 QTRY_COMPARE(lvwph->m_firstVisibleIndex, 0);
1900 }
1902 }
1901
1903
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+
1902private:
1941private:
1903 QQuickView *view;
1942 QQuickView *view;
1904 ListViewWithPageHeader *lvwph;
1943 ListViewWithPageHeader *lvwph;
tests/plugins/Dash/listviewwithpageheadertest.qml+1
@@ -60,6 +60,7 @@ Rectangle {
60 anchors.top: parent.top
60 anchors.top: parent.top
61 anchors.bottom: parent.bottom
61 anchors.bottom: parent.bottom
62 model: model
62 model: model
63+ cacheBuffer: height * 0.5
63 delegate: Rectangle {
64 delegate: Rectangle {
64 property bool timerDone: false
65 property bool timerDone: false
65 width: parent.width - 20
66 width: parent.width - 20
tests/plugins/Dash/listviewwithpageheadertestsection.qml+1
@@ -60,6 +60,7 @@ Rectangle {
60 anchors.top: parent.top
60 anchors.top: parent.top
61 anchors.bottom: parent.bottom
61 anchors.bottom: parent.bottom
62 model: model
62 model: model
63+ cacheBuffer: height * 0.5
63 delegate: Rectangle {
64 delegate: Rectangle {
64 property bool timerDone: false
65 property bool timerDone: false
65 width: parent.width - 20
66 width: parent.width - 20
tests/plugins/Dash/listviewwithpageheadertestsectionexternalmodel.qml+1
@@ -28,6 +28,7 @@ Rectangle {
28 anchors.top: parent.top
28 anchors.top: parent.top
29 anchors.bottom: parent.bottom
29 anchors.bottom: parent.bottom
30 model: model
30 model: model
31+ cacheBuffer: height * 0.5
31 delegate: Rectangle {
32 delegate: Rectangle {
32 property bool timerDone: false
33 property bool timerDone: false
33 width: parent.width - 20
34 width: parent.width - 20
tests/plugins/Ubuntu/Gestures/CMakeLists.txt+1−1
@@ -19,7 +19,7 @@ macro(add_gesture_ui_test CLASSNAME)
19 qt5_use_modules(${CLASSNAME}TestExec Test Core Qml Gui Quick)
19 qt5_use_modules(${CLASSNAME}TestExec Test Core Qml Gui Quick)
20 target_link_libraries(${CLASSNAME}TestExec UbuntuGestureQml)
20 target_link_libraries(${CLASSNAME}TestExec UbuntuGestureQml)
21
21
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 "")
23 add_manual_qml_test(. ${CLASSNAME} IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
23 add_manual_qml_test(. ${CLASSNAME} IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
24endmacro(add_gesture_ui_test)
24endmacro(add_gesture_ui_test)
25
25
tests/qmltests/Components/CMakeLists.txt+1−1
@@ -10,7 +10,7 @@ add_executable(DragHandleTestExec tst_DragHandle.cpp)
10qt5_use_modules(DragHandleTestExec Test Core Qml Gui Quick)
10qt5_use_modules(DragHandleTestExec Test Core Qml Gui Quick)
11target_link_libraries(DragHandleTestExec UbuntuGestureQml)
11target_link_libraries(DragHandleTestExec UbuntuGestureQml)
12
12
13−add_binary_qml_test(DragHandle ${CMAKE_BINARY_DIR}/plugins/Ubuntu/Gestures "")
13+add_binary_qml_test(DragHandle ${CMAKE_BINARY_DIR}/plugins/Ubuntu/Gestures "" "")
14add_manual_qml_test(. DragHandle IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
14add_manual_qml_test(. DragHandle IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
15
15
16add_definitions(-DUBUNTU_GESTURES_PLUGIN_DIR="${CMAKE_BINARY_DIR}/plugins")
16add_definitions(-DUBUNTU_GESTURES_PLUGIN_DIR="${CMAKE_BINARY_DIR}/plugins")
tests/qmltests/Dash/tst_Card.qml+26
@@ -17,6 +17,7 @@
17import QtQuick 2.0
17import QtQuick 2.0
18import QtTest 1.0
18import QtTest 1.0
19import Ubuntu.Components 0.1
19import Ubuntu.Components 0.1
20+import Ubuntu.Connectivity 1.0
20import Unity.Test 0.1 as UT
21import Unity.Test 0.1 as UT
21import "../../../qml/Dash"
22import "../../../qml/Dash"
22import "CardHelpers.js" as Helpers
23import "CardHelpers.js" as Helpers
@@ -205,6 +206,11 @@ Rectangle {
205 property Item backgroundImage: findChild(card, "backgroundImage")
206 property Item backgroundImage: findChild(card, "backgroundImage")
206 property Item mascotImage: findChild(card, "mascotImage");
207 property Item mascotImage: findChild(card, "mascotImage");
207
208
209+ function init() {
210+ loader.visible = true;
211+ NetworkingStatus.limitedBandwith = false;
212+ }
213+
208 function cleanup() {
214 function cleanup() {
209 selector.selectedIndex = -1;
215 selector.selectedIndex = -1;
210 }
216 }
@@ -566,5 +572,25 @@ Rectangle {
566 verify((card.width - titleToCard.x - titleToCard.width) === units.gu(1));
572 verify((card.width - titleToCard.x - titleToCard.width) === units.gu(1));
567 }
573 }
568 }
574 }
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+ }
569 }
595 }
570}
596}
tests/qmltests/Dash/tst_Dash.qml+16−39
@@ -55,6 +55,16 @@ Item {
55 scopes.load();
55 scopes.load();
56 tryCompare(dashContentList, "currentIndex", 0);
56 tryCompare(dashContentList, "currentIndex", 0);
57 tryCompare(dashContentList, "count", 6);
57 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);
58 }
68 }
59
69
60 function get_scope_data() {
70 function get_scope_data() {
@@ -92,15 +102,6 @@ Item {
92 }
102 }
93
103
94 function test_dash_overview_show_select_same_favorite() {
104 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−
104 // Show the overview
105 // Show the overview
105 touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, dash.height - units.gu(18));
106 touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, dash.height - units.gu(18));
106 var overviewController = findInvisibleChild(dash, "overviewController");
107 var overviewController = findInvisibleChild(dash, "overviewController");
@@ -121,18 +122,12 @@ Item {
121
122
122 // Make sure animation went back
123 // Make sure animation went back
123 tryCompare(overviewController, "progress", 0);
124 tryCompare(overviewController, "progress", 0);
125+
126+ var dashContentList = findChild(dash, "dashContentList");
124 compare(dashContentList.currentIndex, 0);
127 compare(dashContentList.currentIndex, 0);
125 }
128 }
126
129
127 function test_dash_overview_show_select_different_favorite() {
130 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−
136 // Show the overview
131 // Show the overview
137 touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, dash.height - units.gu(18));
132 touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, dash.height - units.gu(18));
138 var overviewController = findInvisibleChild(dash, "overviewController");
133 var overviewController = findInvisibleChild(dash, "overviewController");
@@ -153,19 +148,11 @@ Item {
153
148
154 // Make sure animation went back
149 // Make sure animation went back
155 tryCompare(overviewController, "progress", 0);
150 tryCompare(overviewController, "progress", 0);
151+ var dashContentList = findChild(dash, "dashContentList");
156 compare(dashContentList.currentIndex, 1);
152 compare(dashContentList.currentIndex, 1);
157 }
153 }
158
154
159 function test_dash_overview_all_temp_scope_done_from_all() {
155 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−
169 // Show the overview
156 // Show the overview
170 touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, dash.height - units.gu(18));
157 touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, dash.height - units.gu(18));
171 var overviewController = findInvisibleChild(dash, "overviewController");
158 var overviewController = findInvisibleChild(dash, "overviewController");
@@ -227,20 +214,13 @@ Item {
227 tryCompare(overviewController, "progress", 0);
214 tryCompare(overviewController, "progress", 0);
228
215
229 // Original list is still on 0
216 // Original list is still on 0
217+ var dashContentList = findChild(dash, "dashContentList");
230 compare(dashContentList.currentIndex, 0);
218 compare(dashContentList.currentIndex, 0);
231 }
219 }
232
220
233 function test_temp_scope_dash_overview_all_search_temp_scope_favorite_from_all() {
221 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−
243 // Swipe right to Apps scope
222 // Swipe right to Apps scope
223+ var dashContentList = findChild(dash, "dashContentList");
244 touchFlick(dash, dash.width - 1, units.gu(1), dash.width - units.gu(10), units.gu(1));
224 touchFlick(dash, dash.width - 1, units.gu(1), dash.width - units.gu(10), units.gu(1));
245 tryCompare(dashContentList, "contentX", dashContentList.width);
225 tryCompare(dashContentList, "contentX", dashContentList.width);
246 tryCompare(dashContentList, "currentIndex", 1);
226 tryCompare(dashContentList, "currentIndex", 1);
@@ -249,8 +229,7 @@ Item {
249 var categoryListView = findChild(dashContentList.currentItem, "categoryListView");
229 var categoryListView = findChild(dashContentList.currentItem, "categoryListView");
250 var dashCategory2 = findChild(categoryListView, "dashCategory2");
230 var dashCategory2 = findChild(categoryListView, "dashCategory2");
251 tryCompareFunction(function() {
231 tryCompareFunction(function() {
252− var d = findChild(dashCategory2, "delegate2");
253− if (d) return true;
232+ if (dashCategory2.y < 200) return true;
254 categoryListView.contentY += 100;
233 categoryListView.contentY += 100;
255 return false;
234 return false;
256 }, true);
235 }, true);
@@ -340,8 +319,6 @@ Item {
340 }
319 }
341
320
342 function test_processing_indicator() {
321 function test_processing_indicator() {
343− tryCompare(scopes, "loaded", true);
344−
345 var processingIndicator = findChild(dash, "processingIndicator");
322 var processingIndicator = findChild(dash, "processingIndicator");
346 verify(processingIndicator, "Can't find the processing indicator.");
323 verify(processingIndicator, "Can't find the processing indicator.");
347
324
tests/qmltests/Dash/tst_DashContent.qml+14−1
@@ -70,7 +70,17 @@ Item {
70 function loadScopes() {
70 function loadScopes() {
71 scopeLoadedSpy.clear();
71 scopeLoadedSpy.clear();
72 scopesModel.load();
72 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);
74 }
84 }
75
85
76 function init() {
86 function init() {
@@ -467,6 +477,9 @@ Item {
467 var navigationListView = findChild(dashAltNavigationButton, "navigationListView");
477 var navigationListView = findChild(dashAltNavigationButton, "navigationListView");
468 tryCompare(navigationListView.currentItem.navigation, "loaded", true);
478 tryCompare(navigationListView.currentItem.navigation, "loaded", true);
469
479
480+ var blackRect = findChild(dashNavigation, "blackRect");
481+ tryCompare(blackRect, "opacity", 0.5);
482+
470 mouseClick(dashNavigation, dashNavigationButton.x, 0);
483 mouseClick(dashNavigation, dashNavigationButton.x, 0);
471 compare(dashNavigationButton.showList, false);
484 compare(dashNavigationButton.showList, false);
472 compare(dashAltNavigationButton.showList, false);
485 compare(dashAltNavigationButton.showList, false);
tests/qmltests/Dash/tst_GenericScopeView.qml+7−6
@@ -82,18 +82,19 @@ Item {
82 spy.signalName = "";
82 spy.signalName = "";
83 }
83 }
84
84
85− function scrollToCategory(category) {
85+ function scrollToCategory(categoryName) {
86 var categoryListView = findChild(genericScopeView, "categoryListView");
86 var categoryListView = findChild(genericScopeView, "categoryListView");
87 tryCompareFunction(function() {
87 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;
89 mouseFlick(genericScopeView, genericScopeView.width/2, genericScopeView.height,
90 mouseFlick(genericScopeView, genericScopeView.width/2, genericScopeView.height,
90 genericScopeView.width/2, genericScopeView.y)
91 genericScopeView.width/2, genericScopeView.y)
91 tryCompare(categoryListView, "moving", false);
92 tryCompare(categoryListView, "moving", false);
92− return findChild(genericScopeView, category) !== null;
93+ return false;
93 }, true);
94 }, true);
94
95
95 tryCompareFunction(function() { return findChild(genericScopeView, "delegate0") !== null; }, true);
96 tryCompareFunction(function() { return findChild(genericScopeView, "delegate0") !== null; }, true);
96− return findChild(genericScopeView, category);
97+ return findChild(genericScopeView, categoryName);
97 }
98 }
98
99
99 function scrollToEnd()
100 function scrollToEnd()
@@ -283,7 +284,7 @@ Item {
283 if (category === undefined) category = 0;
284 if (category === undefined) category = 0;
284 if (delegate === undefined) delegate = 0;
285 if (delegate === undefined) delegate = 0;
285 tryCompareFunction(function() {
286 tryCompareFunction(function() {
286− var cardGrid = findChild(genericScopeView, category);
287+ var cardGrid = findChild(genericScopeView, "dashCategory"+category);
287 if (cardGrid != null) {
288 if (cardGrid != null) {
288 var tile = findChild(cardGrid, "delegate"+delegate);
289 var tile = findChild(cardGrid, "delegate"+delegate);
289 return tile != null;
290 return tile != null;
@@ -291,7 +292,7 @@ Item {
291 return false;
292 return false;
292 },
293 },
293 true);
294 true);
294− var tile = findChild(findChild(genericScopeView, category), "delegate"+delegate);
295+ var tile = findChild(findChild(genericScopeView, "dashCategory"+category), "delegate"+delegate);
295 mouseClick(tile, tile.width / 2, tile.height / 2);
296 mouseClick(tile, tile.width / 2, tile.height / 2);
296 tryCompare(testCase.subPageLoader, "open", true);
297 tryCompare(testCase.subPageLoader, "open", true);
297 tryCompare(testCase.subPageLoader, "x", 0);
298 tryCompare(testCase.subPageLoader, "x", 0);
tests/utils/modules/Unity/Test/UnityTestCase.qml+3−2
@@ -178,9 +178,10 @@ TestCase {
178 // Keeps executing a given parameter-less function until it returns the given
178 // Keeps executing a given parameter-less function until it returns the given
179 // expected result or the timemout is reached (in which case a test failure
179 // expected result or the timemout is reached (in which case a test failure
180 // is generated)
180 // is generated)
181− function tryCompareFunction(func, expectedResult) {
181+ function tryCompareFunction(func, expectedResult, timeout) {
182 var timeSpent = 0
182 var timeSpent = 0
183+ if (timeout === undefined)
183− var timeout = 5000
184+ timeout = 5000;
184 var success = false
185 var success = false
185 var actualResult
186 var actualResult
186 while (timeSpent < timeout && !success) {
187 while (timeSpent < timeout && !success) {