on xenial help sign in
Merge drop-filtergrid
commit6d76bc513aca4066c5f62e56f6a12fb43294b6f2 authorMichał Sawicz <michal.sawicz@canonical.com> dateTue 22 Jul 2014, 00:38 (12 years ago) parent26b299591fe606
23 files changed+194−457
tests/autopilot/.project → .project+1−1 tests/autopilot/.pydevproject → .pydevproject+3−1 .settings/Autopilot List.launch+14 .settings/Autopilot Run.launch+14 qml/Components/FilterGrid.qml−124 qml/Components/ResponsiveGridView.qml+2−1 qml/Dash/CardCarousel.qml+2−7 qml/Dash/CardFilterGrid.qml → qml/Dash/CardGrid.qml+21−22 qml/Dash/CardVerticalJournal.qml+2−21 qml/Dash/DashRenderer.qml+2−11 qml/Dash/GenericScopeView.qml+52−27 tests/autopilot/unity8/shell/emulators/dash.py+6−3 tests/autopilot/unity8/shell/tests/test_emulators.py+5−5 tests/mocks/Ubuntu/Telephony/CMakeLists.txt+1−9 tests/mocks/Unity/fake_categories.cpp+4−1 tests/mocks/Unity/fake_scope.cpp+2−2 tests/mocks/Unity/fake_scope.h+1−1 tests/mocks/Unity/fake_scopes.cpp+1 tests/qmltests/CMakeLists.txt−1 tests/qmltests/Components/tst_FilterGrid.qml−190 tests/qmltests/Dash/tst_Dash.qml+1−1 tests/qmltests/Dash/tst_DashContent.qml+15−6 tests/qmltests/Dash/tst_GenericScopeView.qml+45−23
tests/autopilot/.project → .projectrenamed+1−1
@@ -1,6 +1,6 @@
11<?xml version="1.0" encoding="UTF-8"?>
22<projectDescription>
3− <name>Unity8 Autopilot</name>
3+ <name>Unity8</name>
44 <comment></comment>
55 <projects>
66 </projects>
tests/autopilot/.pydevproject → .pydevprojectrenamed+3−1
@@ -1,7 +1,9 @@
11<?xml version="1.0" encoding="UTF-8" standalone="no"?>
22<?eclipse-pydev version="1.0"?><pydev_project>
33<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
4−<path>/Unity8 Autopilot</path>
4+<path>/Unity8/tests/autopilot</path>
5+<path>/Unity8/.bazaar</path>
6+<path>/Unity8/tests/whitespace</path>
57</pydev_pathproperty>
68<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
79<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
.settings/Autopilot List.launchnew file+14
@@ -0,0 +1,14 @@
1+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+<launchConfiguration type="org.python.pydev.debug.regularLaunchConfigurationType">
3+<stringAttribute key="bad_container_name" value="/Unity8/.pyd"/>
4+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"/>
5+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"/>
6+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
7+<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
8+</listAttribute>
9+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="/usr/bin/autopilot"/>
10+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_OTHER_WORKING_DIRECTORY" value=""/>
11+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="list unity8"/>
12+<stringAttribute key="org.python.pydev.debug.ATTR_INTERPRETER" value="__default"/>
13+<stringAttribute key="org.python.pydev.debug.ATTR_PROJECT" value="Unity8"/>
14+</launchConfiguration>
.settings/Autopilot Run.launchnew file+14
@@ -0,0 +1,14 @@
1+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+<launchConfiguration type="org.python.pydev.debug.regularLaunchConfigurationType">
3+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"/>
4+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"/>
5+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
6+<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
7+<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
8+</listAttribute>
9+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="/usr/bin/autopilot"/>
10+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_OTHER_WORKING_DIRECTORY" value=""/>
11+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="run ${string_prompt:the test suite to run:unity8}"/>
12+<stringAttribute key="org.python.pydev.debug.ATTR_INTERPRETER" value="__default"/>
13+<stringAttribute key="org.python.pydev.debug.ATTR_PROJECT" value="Unity8"/>
14+</launchConfiguration>
qml/Components/FilterGrid.qmldeleted−124
@@ -1,124 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
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 General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.0
18−import Ubuntu.Components 0.1
19−import Utils 0.1
20−import "../Components"
21−
22−/*
23− A ResponsiveGridView that can optionally have the number of rows being displayed
24− reduced to collapsedRowCount, in which case a button saying "View all (123)"
25− will be shown at the bottom. If clicked, FilterGrid will them expand vertically
26− to display all rows.
27− */
28−Item {
29− id: root
30−
31− /* Whether, when collapsed, a button should be displayed enabling the user to expand
32− the grid to its full size. */
33− readonly property bool expandable: model.count > rowsWhenCollapsed * iconTileGrid.columns
34−
35− property var model: null
36−
37− /* Maximum number of rows to be show when filter=true. */
38− property int collapsedRowCount: 2
39− property int uncollapsedRowCount: Math.ceil(model.count / columns)
40− /* Never show more rows than model would fill up. */
41− readonly property int rowsWhenCollapsed: Math.min(collapsedRowCount, uncollapsedRowCount)
42− readonly property int collapsedHeight: iconTileGrid.contentHeightForRows(rowsWhenCollapsed)
43− readonly property int uncollapsedHeight: iconTileGrid.contentHeightForRows(uncollapsedRowCount)
44−
45− property alias minimumHorizontalSpacing: iconTileGrid.minimumHorizontalSpacing
46− property alias maximumNumberOfColumns: iconTileGrid.maximumNumberOfColumns
47− property alias columns: iconTileGrid.columns
48− property alias delegateWidth: iconTileGrid.delegateWidth
49− property alias delegateHeight: iconTileGrid.delegateHeight
50− property alias verticalSpacing: iconTileGrid.verticalSpacing
51− readonly property alias margins: iconTileGrid.margins
52− property alias delegate: iconTileGrid.delegate
53− property alias cellWidth: iconTileGrid.cellWidth
54− property alias cellHeight: iconTileGrid.cellHeight
55− property alias displayMarginBeginning: iconTileGrid.displayMarginBeginning
56− property alias displayMarginEnd: iconTileGrid.displayMarginEnd
57− readonly property alias originY: iconTileGrid.originY
58− readonly property alias flicking: iconTileGrid.flicking
59− readonly property alias moving: iconTileGrid.moving
60− readonly property alias pressDelay: iconTileGrid.pressDelay
61− property alias highlightIndex: iconTileGrid.highlightIndex
62− readonly property alias currentItem: iconTileGrid.currentItem
63− readonly property alias filtered: d.filter
64−
65− QtObject {
66− id: d
67− // We do have filter and collapsed properties because we need to decouple
68− // the real filtering with the animation since the closing animation
69− // i.e. setFilter(false. true) we still need to not be filtering until
70− // the animation finishes otherwise we hide the items when the animation
71− // is still running
72− property bool filter: true
73− property bool collapsed: true
74− }
75−
76− height: d.collapsed ? root.collapsedHeight : root.uncollapsedHeight
77− clip: filterAnimation.running
78−
79− Behavior on height {
80− id: heightBehaviour
81− enabled: false
82− NumberAnimation {
83− id: filterAnimation
84− // Duration and easing here match the ListViewWithPageHeader::m_contentYAnimation
85− // otherwise since both animations can run at the same time you'll get
86− // some visual weirdness.
87− duration: 200
88− easing.type: Easing.InOutQuad
89− onRunningChanged: {
90− if (!running) {
91− d.filter = d.collapsed;
92− }
93− heightBehaviour.enabled = false;
94− }
95− }
96− }
97−
98− function setFilter(filter, animate) {
99− heightBehaviour.enabled = animate;
100− d.collapsed = filter;
101− if (!animate || !filter) {
102− d.filter = filter;
103− }
104− }
105−
106− ResponsiveGridView {
107− id: iconTileGrid
108−
109− anchors { left: parent.left; right: parent.right }
110− height: totalContentHeight
111− interactive: false
112−
113− minimumHorizontalSpacing: units.gu(0.5)
114− maximumNumberOfColumns: 6
115− delegateWidth: units.gu(11)
116− delegateHeight: units.gu(9.5)
117− verticalSpacing: units.gu(2)
118−
119− model: LimitProxyModel {
120− model: root.model
121− limit: d.filter ? rowsWhenCollapsed * iconTileGrid.columns : -1
122− }
123− }
124−}
qml/Components/ResponsiveGridView.qml+2−1
@@ -44,10 +44,11 @@ Item {
4444 property alias displayMarginBeginning: gridView.displayMarginBeginning
4545 property alias displayMarginEnd: gridView.displayMarginEnd
4646 property alias highlightIndex: gridView.highlightIndex
47+ property alias cacheBuffer: gridView.cacheBuffer
4748 readonly property alias currentItem: gridView.currentItem
4849
4950 function contentHeightForRows(rows) {
50− return rows * cellHeight + verticalSpacing
51+ return rows * cellHeight;
5152 }
5253
5354 GridView {
qml/Dash/CardCarousel.qml+2−7
@@ -21,13 +21,8 @@ import "../Components"
2121DashRenderer {
2222 id: cardCarousel
2323
24− property alias cacheBuffer: carousel.cacheBuffer
25− property alias itemComponent: carousel.itemComponent
26− property alias minimumTileWidth: carousel.minimumTileWidth
27− property alias selectedItemScaleFactor: carousel.selectedItemScaleFactor
28− property alias tileAspectRatio: carousel.tileAspectRatio
29−
30− height: carousel.implicitHeight + units.gu(6)
24+ expandedHeight: carousel.implicitHeight + units.gu(6)
25+ collapsedHeight: expandedHeight
3126
3227 Carousel {
3328 id: carousel
qml/Dash/CardFilterGrid.qml → qml/Dash/CardGrid.qmlrenamed+21−22
@@ -18,33 +18,32 @@ import QtQuick 2.0
1818import "../Components"
1919
2020DashRenderer {
21− id: genericFilterGrid
21+ id: root
2222
23− expandable: filterGrid.expandable
24− collapsedHeight: filterGrid.collapsedHeight
25− uncollapsedHeight: filterGrid.uncollapsedHeight
26− originY: filterGrid.originY
27− height: filterGrid.height
28− filtered: filterGrid.filtered
29−
30− function setFilter(filter, animate) {
31− filterGrid.setFilter(filter, animate)
23+ readonly property int collapsedRows: {
24+ if (!cardTool || !cardTool.template || typeof cardTool.template["collapsed-rows"] != "number") return 2;
25+ return cardTool.template["collapsed-rows"];
3226 }
3327
34− FilterGrid {
35− id: filterGrid
36− width: genericFilterGrid.width
28+ expandedHeight: grid.totalContentHeight
29+ collapsedHeight: Math.min(grid.contentHeightForRows(collapsedRows), expandedHeight)
30+ originY: grid.originY
31+
32+ ResponsiveGridView {
33+ id: grid
34+ anchors.fill: parent
3735 minimumHorizontalSpacing: units.gu(1)
3836 delegateWidth: cardTool.cardWidth
3937 delegateHeight: cardTool.cardHeight
4038 verticalSpacing: units.gu(1)
41− model: genericFilterGrid.model
42− collapsedRowCount: Math.min(2, cardTool && cardTool.template && cardTool.template["collapsed-rows"] || 2)
43− displayMarginBeginning: genericFilterGrid.displayMarginBeginning
44− displayMarginEnd: genericFilterGrid.displayMarginEnd
39+ model: root.model
40+ displayMarginBeginning: root.displayMarginBeginning
41+ displayMarginEnd: root.displayMarginEnd
42+ cacheBuffer: 0
43+ interactive: false
4544 delegate: Item {
46− width: filterGrid.cellWidth
47− height: filterGrid.cellHeight
45+ width: grid.cellWidth
46+ height: grid.cellHeight
4847 Loader {
4948 id: loader
5049 sourceComponent: cardTool.cardComponent
@@ -58,12 +57,12 @@ DashRenderer {
5857 item.template = Qt.binding(function() { return cardTool.template; });
5958 item.components = Qt.binding(function() { return cardTool.components; });
6059 item.headerAlignment = Qt.binding(function() { return cardTool.headerAlignment; });
61− item.scopeStyle = genericFilterGrid.scopeStyle;
60+ item.scopeStyle = root.scopeStyle;
6261 }
6362 Connections {
6463 target: loader.item
65− onClicked: genericFilterGrid.clicked(index, result)
66− onPressAndHold: genericFilterGrid.pressAndHold(index)
64+ onClicked: root.clicked(index, result)
65+ onPressAndHold: root.pressAndHold(index)
6766 }
6867 }
6968 }
qml/Dash/CardVerticalJournal.qml+2−21
@@ -23,33 +23,14 @@ DashRenderer {
2323
2424 readonly property double collapseLimit: units.gu(35)
2525
26− uncollapsedHeight: cardVerticalJournal.implicitHeight
27− collapsedHeight: Math.min(collapseLimit, cardVerticalJournal.implicitHeight)
28− expandable: uncollapsedHeight > collapseLimit
26+ expandedHeight: Math.max(cardVerticalJournal.implicitHeight, minHeight)
27+ collapsedHeight: Math.max(Math.min(collapseLimit, cardVerticalJournal.implicitHeight), minHeight)
2928
3029 // This minHeight is used as bootstrapper for the height. Vertical Journal
3130 // is special by the fact that it doesn't know how to calculate its implicit height unless we give it
3231 // enough height that it can start creating its children so we make sure it has enough height for that
3332 // in case the model is non empty
3433 readonly property double minHeight: root.model.count >= 1 ? cardVerticalJournal.rowSpacing + 1 : 0
35− height: filtered ? Math.max(collapsedHeight, minHeight) : uncollapsedHeight
36−
37− Behavior on height {
38− id: heightBehaviour
39− enabled: false
40− animation: UbuntuNumberAnimation {
41− onRunningChanged: {
42− if (!running) {
43− heightBehaviour.enabled = false
44− }
45− }
46− }
47− }
48−
49− function setFilter(filter, animate) {
50− heightBehaviour.enabled = animate;
51− filtered = filter;
52− }
5334
5435 ResponsiveVerticalJournal {
5536 id: cardVerticalJournal
qml/Dash/DashRenderer.qml+2−11
@@ -17,15 +17,9 @@
1717import QtQuick 2.0
1818
1919Item {
20− // Can the item be expanded?
21− property bool expandable: false
20+ property int collapsedHeight
2221
23− // In case it can be expanded, is it filtered
24− property bool filtered: true
25−
26− property int collapsedHeight: height
27−
28− property int uncollapsedHeight: height
22+ property int expandedHeight
2923
3024 property int displayMarginBeginning: 0
3125
@@ -50,7 +44,4 @@ Item {
5044 /// Emitted when the user pressed and held on an item
5145 /// @param index is the index of the held item
5246 signal pressAndHold(int index)
53−
54− function setFilter(filter, animate) {
55− }
5647}
qml/Dash/GenericScopeView.qml+52−27
@@ -128,11 +128,21 @@ FocusScope {
128128 highlightWhenPressed: false
129129 showDivider: false
130130
131− readonly property bool expandable: rendererLoader.item ? rendererLoader.item.expandable : false
132− readonly property bool filtered: rendererLoader.item ? rendererLoader.item.filtered : true
131+ readonly property bool expandable: {
132+ if (categoryView.model.count === 1) return false;
133+ if (cardTool.template && cardTool.template["collapsed-rows"] === 0) return false;
134+ if (item && item.expandedHeight > item.collapsedHeight) return true;
135+ return false;
136+ }
137+ property bool expanded: false
133138 readonly property string category: categoryId
134139 readonly property var item: rendererLoader.item
135140
141+ function expand(expand, animate) {
142+ heightBehaviour.enabled = animate;
143+ expanded = expand;
144+ }
145+
136146 CardTool {
137147 id: cardTool
138148 objectName: "cardTool"
@@ -142,6 +152,18 @@ FocusScope {
142152 viewWidth: parent.width
143153 }
144154
155+ onExpandableChanged: {
156+ // This can happen with the VJ that doesn't know how height it will be on creation
157+ // so doesn't set expandable until a bit too late for onLoaded
158+ if (expandable) {
159+ var shouldExpand = baseItem.category === categoryView.expandedCategoryId;
160+ baseItem.expand(shouldExpand, false /*animate*/);
161+ }
162+ }
163+
164+ onHeightChanged: rendererLoader.updateDelegateCreationRange();
165+ onYChanged: rendererLoader.updateDelegateCreationRange();
166+
145167 Loader {
146168 id: rendererLoader
147169 anchors {
@@ -151,13 +173,27 @@ FocusScope {
151173 topMargin: hasSectionHeader ? 0 : units.gu(2)
152174 }
153175
176+ Behavior on height {
177+ id: heightBehaviour
178+ enabled: false
179+ animation: UbuntuNumberAnimation {
180+ onRunningChanged: {
181+ if (!running) {
182+ heightBehaviour.enabled = false
183+ }
184+ }
185+ }
186+ }
187+
188+ height: baseItem.expandable && !baseItem.expanded ? item.collapsedHeight : item.expandedHeight
189+
154190 source: {
155191 switch (cardTool.categoryLayout) {
156192 case "carousel": return "CardCarousel.qml";
157193 case "vertical-journal": return "CardVerticalJournal.qml";
158194 case "running-apps": return "Apps/RunningApplicationsGrid.qml";
159195 case "grid":
160− default: return "CardFilterGrid.qml";
196+ default: return "CardGrid.qml";
161197 }
162198 }
163199
@@ -176,9 +212,9 @@ FocusScope {
176212 }
177213 item.objectName = Qt.binding(function() { return categoryId })
178214 item.scopeStyle = scopeView.scopeStyle;
179− if (item.expandable) {
180− var shouldFilter = categoryId != categoryView.expandedCategoryId;
181− item.setFilter(shouldFilter, false /*animate*/);
215+ if (baseItem.expandable) {
216+ var shouldExpand = categoryId === categoryView.expandedCategoryId;
217+ baseItem.expand(shouldExpand, false /*animate*/);
182218 }
183219 updateDelegateCreationRange();
184220 item.cardTool = cardTool;
@@ -211,14 +247,6 @@ FocusScope {
211247 previewListView.currentIndex = index;
212248 previewListView.open = true
213249 }
214− onExpandableChanged: {
215− // This can happen with the VJ that doesn't know how height it will be on creation
216− // so doesn't set expandable until a bit too late for onLoaded
217− if (rendererLoader.item.expandable) {
218− var shouldFilter = baseItem.category != categoryView.expandedCategoryId;
219− rendererLoader.item.setFilter(shouldFilter, false /*animate*/);
220− }
221− }
222250 }
223251 Connections {
224252 target: categoryView
@@ -227,17 +255,17 @@ FocusScope {
227255 }
228256 function collapseAllButExpandedCategory() {
229257 var item = rendererLoader.item;
230− if (item.expandable) {
231− var shouldFilter = categoryId != categoryView.expandedCategoryId;
232− if (shouldFilter != item.filter) {
258+ if (baseItem.expandable) {
259+ var shouldExpand = categoryId === categoryView.expandedCategoryId;
260+ if (shouldExpand != baseItem.expanded) {
233261 // If the filter animation will be seen start it, otherwise, just flip the switch
234− var shrinkingVisible = shouldFilter && y + item.collapsedHeight < categoryView.height;
235− var growingVisible = !shouldFilter && y + height < categoryView.height;
236− if (!previewListView.open || !shouldFilter) {
262+ var shrinkingVisible = !shouldExpand && y + item.collapsedHeight < categoryView.height;
263+ var growingVisible = shouldExpand && y + height < categoryView.height;
264+ if (!previewListView.open || shouldExpand) {
237265 var animate = shrinkingVisible || growingVisible;
238− item.setFilter(shouldFilter, animate)
239− if (!shouldFilter && !previewListView.open) {
240− categoryView.maximizeVisibleArea(index, item.uncollapsedHeight);
266+ baseItem.expand(shouldExpand, animate)
267+ if (shouldExpand && !previewListView.open) {
268+ categoryView.maximizeVisibleArea(index, item.expandedHeight);
241269 }
242270 }
243271 }
@@ -304,9 +332,6 @@ FocusScope {
304332 z: -1
305333 }
306334 }
307−
308− onHeightChanged: rendererLoader.updateDelegateCreationRange();
309− onYChanged: rendererLoader.updateDelegateCreationRange();
310335 }
311336
312337 sectionProperty: "name"
@@ -318,7 +343,7 @@ FocusScope {
318343 textColor: scopeStyle ? scopeStyle.foreground : "grey"
319344 image: {
320345 if (delegate && delegate.expandable)
321− return delegate.filtered ? "graphics/header_handlearrow.png" : "graphics/header_handlearrow2.png"
346+ return delegate.expanded ? "graphics/header_handlearrow2.png" : "graphics/header_handlearrow.png"
322347 return "";
323348 }
324349 onClicked: {
tests/autopilot/unity8/shell/emulators/dash.py+6−3
@@ -40,7 +40,7 @@ class Dash(emulators.UnityEmulatorBase):
4040
4141 def get_applications_grid(self):
4242 get_grid = self.get_scope('clickscope').wait_select_single(
43− 'CardFilterGrid', objectName='local')
43+ 'CardGrid', objectName='local')
4444 return get_grid
4545
4646 def get_application_icon(self, text):
@@ -196,9 +196,12 @@ class DashApps(GenericScopeView):
196196 category_element = self._get_category_element(category)
197197 application_cards = category_element.select_many('AbstractButton')
198198
199− # sort by y, x
199+ # sort by y, x, filter those out of view
200+ categoryBottom = category_element.globalRect.y \
201+ + category_element.height
200202 application_cards = sorted(
201− application_cards,
203+ (card for card in application_cards
204+ if card.globalRect.y < categoryBottom),
202205 key=lambda card: (card.globalRect.y, card.globalRect.x))
203206
204207 result = []
tests/autopilot/unity8/shell/tests/test_emulators.py+5−5
@@ -191,9 +191,9 @@ class DashAppsEmulatorTestCase(DashBaseTestCase):
191191 def _get_number_of_application_slots(self, category):
192192 category_element = self.applications_scope._get_category_element(
193193 category)
194− grid = category_element.select_single('CardFilterGrid')
195− filtergrid = grid.select_single('FilterGrid')
196− if (grid.filtered):
197− return filtergrid.collapsedRowCount * filtergrid.columns
194+ cardgrid = category_element.select_single('CardGrid')
195+ if (category_element.expanded):
196+ return cardgrid.select_single('QQuickGridView').count
198197 else:
199− return filtergrid.uncollapsedRowCount * filtergrid.columns
198+ return cardgrid.collapsedRows \
199+ * cardgrid.select_single('ResponsiveGridView').columns
tests/mocks/Ubuntu/Telephony/CMakeLists.txt+1−9
@@ -11,12 +11,4 @@ add_library(FakeUbuntuTelephonyQml MODULE ${FakeUbuntuTelephonyQml_SOURCES})
1111
1212qt5_use_modules(FakeUbuntuTelephonyQml Core Quick)
1313
14−# copy files into build directory for shadow builds
15−add_custom_target(UbuntuTelephonyQmlDirFile ALL
16− COMMAND cp "${CMAKE_CURRENT_SOURCE_DIR}/qmldir" ${CMAKE_CURRENT_BINARY_DIR}
17− DEPENDS qmldir
18−)
19−
20−install(TARGETS FakeUbuntuTelephonyQml
21− DESTINATION ${SHELL_INSTALL_QML}/mocks/Ubuntu/Telephony
22− )
14+add_unity8_mock(Ubuntu.Telephony 0.1 Ubuntu/Telephony TARGETS FakeUbuntuTelephonyQml)
tests/mocks/Unity/fake_categories.cpp+4−1
@@ -145,9 +145,12 @@ Categories::data(const QModelIndex& index, int role) const
145145 } else {
146146 map["category-layout"] = "carousel";
147147 map["card-size"] = "medium";
148− map["collapsed-rows"] = 2;
149148 map["overlay"] = true;
150149 }
150+ if (index.row() == 19) {
151+ map["category-layout"] = "grid";
152+ map["collapsed-rows"] = 0;
153+ }
151154 map["card-size"] = "small";
152155 return map;
153156 }
tests/mocks/Unity/fake_scope.cpp+2−2
@@ -24,7 +24,7 @@ Scope::Scope(QObject* parent) : Scope(QString(), QString(), false, parent)
2424{
2525}
2626
27−Scope::Scope(QString const& id, QString const& name, bool visible, QObject* parent)
27+Scope::Scope(QString const& id, QString const& name, bool visible, QObject* parent, int categories)
2828 : unity::shell::scopes::ScopeInterface(parent)
2929 , m_id(id)
3030 , m_name(name)
@@ -33,7 +33,7 @@ Scope::Scope(QString const& id, QString const& name, bool visible, QObject* pare
3333 , m_isActive(false)
3434 , m_currentDeparment("root")
3535 , m_previewRendererName("preview-generic")
36− , m_categories(new Categories(20, this))
36+ , m_categories(new Categories(categories, this))
3737{
3838}
3939
tests/mocks/Unity/fake_scope.h+1−1
@@ -30,7 +30,7 @@ class Scope : public unity::shell::scopes::ScopeInterface
3030
3131public:
3232 Scope(QObject* parent = 0);
33− Scope(QString const& id, QString const& name, bool visible, QObject* parent = 0);
33+ Scope(QString const& id, QString const& name, bool visible, QObject* parent = 0, int categories = 20);
3434
3535 /* getters */
3636 QString id() const override;
tests/mocks/Unity/fake_scopes.cpp+1
@@ -46,6 +46,7 @@ void Scopes::updateScopes()
4646 addScope(new Scope("MockScope2", "Music", false, this));
4747 addScope(new Scope("clickscope", "Apps", true, this));
4848 addScope(new Scope("MockScope5", "Videos", true, this));
49+ addScope(new Scope("SingleCategoryScope", "Single", true, this, 1));
4950
5051 if (!m_loaded) {
5152 m_loaded = true;
tests/qmltests/CMakeLists.txt−1
@@ -25,7 +25,6 @@ add_qml_test(Components Background)
2525add_qml_test(Components Carousel)
2626add_qml_test(Components DraggingArea)
2727add_qml_test(Components EdgeDemoOverlay)
28−add_qml_test(Components FilterGrid)
2928add_qml_test(Components LazyImage)
3029add_qml_test(Components Rating)
3130add_qml_test(Components ResponsiveFlowView)
tests/qmltests/Components/tst_FilterGrid.qmldeleted−190
@@ -1,190 +0,0 @@
1−/*
2− * Copyright 2013 Canonical Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
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 General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.0
18−import QtTest 1.0
19−import "../../../qml/Components"
20−import Ubuntu.Components.ListItems 0.1 as ListItem
21−import Ubuntu.Components 0.1
22−import Unity.Test 0.1 as UT
23−import Utils 0.1
24−
25−/*
26− You should see 6 green squares (from "A" to "F") and a button "View all (12)".
27− Once you press that button other 6 green squares (from "G" to "L") should show up.
28−*/
29−Rectangle {
30− width: gridRect.width + controls.width
31− height: units.gu(50)
32− color: "white"
33−
34− Column {
35− id: controls
36− width: units.gu(30)
37− height: parent.height
38− anchors.top: parent.top
39− anchors.right: parent.right
40− ListItem.ValueSelector {
41− id: collapsedRowCountSelector
42− text: "collapsedRowCount"
43− values: [1,2,3,4]
44− selectedIndex: 1
45− }
46− Row {
47− spacing: units.gu(1)
48− Label { anchors.verticalCenter: parent.verticalCenter
49− text: "Filter" }
50− CheckBox {
51− id: filterCheckBox
52− checked: true
53− onCheckedChanged: filterGrid.setFilter(checked, false /*animate*/)
54− }
55− }
56− }
57−
58− ListModel {
59− id: fakeModel
60− ListElement { name: "A" }
61− ListElement { name: "B" }
62− ListElement { name: "C" }
63− ListElement { name: "D" }
64− ListElement { name: "E" }
65− ListElement { name: "F" }
66− ListElement { name: "G" }
67− ListElement { name: "H" }
68− ListElement { name: "I" }
69− ListElement { name: "J" }
70− ListElement { name: "K" }
71− ListElement { name: "L" }
72− }
73−
74− ListModel {
75− id: fakeModelTwoItems
76− ListElement { name: "A" }
77− ListElement { name: "B" }
78− }
79−
80− ListModel {
81− id: fakeModelFourItems
82− ListElement { name: "A" }
83− ListElement { name: "B" }
84− ListElement { name: "C" }
85− ListElement { name: "D" }
86− }
87−
88− Rectangle {
89− id: gridRect
90− width: units.gu(30)
91− height: parent.height
92− color: "grey"
93− anchors.top: parent.top
94− anchors.left: parent.left
95−
96− FilterGrid {
97− id: filterGrid
98− anchors.fill: parent
99− model: fakeModel
100− maximumNumberOfColumns: 3
101− collapsedRowCount:
102− collapsedRowCountSelector.values[collapsedRowCountSelector.selectedIndex]
103− minimumHorizontalSpacing: units.gu(1)
104− delegateWidth: units.gu(6)
105− delegateHeight: units.gu(6)
106− verticalSpacing: units.gu(1)
107−
108− delegate: Rectangle {
109− // So that it can be identified by countVisibleDelegates()
110− property bool isGridDelegate: true
111−
112− color: "green"
113− width: units.gu(6)
114− height: units.gu(6)
115− Text {
116− anchors.centerIn: parent
117− text: name
118− }
119− }
120− }
121− }
122−
123− UT.UnityTestCase {
124− name: "FilterGrid"
125− when: windowShown
126−
127− function init() {
128− filterGrid.model = fakeModel
129− }
130−
131− function cleanup() {
132− filterCheckBox.checked = true
133− collapsedRowCountSelector.selectedIndex = 1
134− }
135−
136− function test_turningFilterOffShowsAllElements() {
137− tryCompareFunction(countVisibleDelegates, 6)
138−
139− filterCheckBox.checked = false
140−
141− tryCompareFunction(countVisibleDelegates, 12)
142− }
143−
144− function test_collapsedRowCount() {
145− for (var i = 0; i < 4; ++i) {
146− collapsedRowCountSelector.selectedIndex = i
147− // We have 3 elements per row.
148− // row count == index + 1
149− tryCompareFunction(countVisibleDelegates, 3*(i+1))
150− }
151− }
152−
153− function test_modelSizeAffectsCollapsedRowCount_data() {
154− return [
155− { tag: "2 items, collapsedRows 1", model: fakeModelTwoItems, collapsedRowCountIndex: 0,
156− rowsWhenCollapsed: 1, visibleDelegates: 2 },
157− { tag: "2 items, collapsedRows 2", model: fakeModelTwoItems, collapsedRowCountIndex: 1,
158− rowsWhenCollapsed: 1, visibleDelegates: 2 },
159− { tag: "4 items, collapsedRows 1", model: fakeModelFourItems, collapsedRowCountIndex: 0,
160− rowsWhenCollapsed: 1, visibleDelegates: 3 },
161− { tag: "4 items, collapsedRows 2", model: fakeModelFourItems, collapsedRowCountIndex: 1,
162− rowsWhenCollapsed: 2, visibleDelegates: 4 },
163− ]
164− }
165−
166− function test_modelSizeAffectsCollapsedRowCount(data) {
167− filterGrid.model = data.model
168− collapsedRowCountSelector.selectedIndex = data.collapsedRowCountIndex
169−
170− tryCompare(filterGrid, "rowsWhenCollapsed", data.rowsWhenCollapsed)
171− tryCompareFunction(countVisibleDelegates, data.visibleDelegates)
172− }
173−
174− function countVisibleDelegates() {
175− return __countVisibleDelegates(filterGrid.visibleChildren, 0)
176− }
177−
178− function __countVisibleDelegates(objList, total) {
179− for (var i = 0; i < objList.length; ++i) {
180− var child = objList[i];
181− if (child.isGridDelegate !== undefined) {
182− ++total;
183− } else {
184− total = __countVisibleDelegates(child.visibleChildren, total)
185− }
186− }
187− return total
188− }
189− }
190−}
tests/qmltests/Dash/tst_Dash.qml+1−1
@@ -86,7 +86,7 @@ Item {
8686 tryCompare(dashContentList, "count", 0);
8787 scopes.load();
8888 tryCompare(scopes, "loaded", true);
89− tryCompare(dashContentList, "count", 3);
89+ tryCompare(dashContentList, "count", 4);
9090
9191 verify(dashContentList != undefined);
9292 tryCompare(dashContentList, "currentIndex", data.visualIndex);
tests/qmltests/Dash/tst_DashContent.qml+15−6
@@ -61,6 +61,11 @@ Item {
6161 signalName: "movementStarted"
6262 }
6363
64+ SignalSpy {
65+ id: loadedSpy
66+ signalName: "loaded"
67+ }
68+
6469 UT.UnityTestCase {
6570 name: "DashContent"
6671 when: scopesModel.loaded && windowShown
@@ -78,6 +83,7 @@ Item {
7883
7984 function cleanup() {
8085 movementStartedSpy.clear();
86+ loadedSpy.clear();
8187 dashContent.visible = true;
8288
8389 var dashContentList = findChild(dashContent, "dashContentList");
@@ -116,10 +122,11 @@ Item {
116122
117123 function test_show_header_on_list_movement() {
118124 var dashContentList = findChild(dashContent, "dashContentList");
119− verify(dashContentList != undefined);
120− var categoryListView = findChild(dashContentList, "categoryListView");
121− verify(categoryListView != undefined);
125+ verify(dashContentList !== null);
126+ var scope = findChild(dashContent, "MockScope1 loader");
127+ waitForRendering(scope);
122128
129+ var categoryListView = findChild(scope, "categoryListView");
123130 waitForRendering(categoryListView);
124131
125132 categoryListView.contentY = units.gu(15);
@@ -133,10 +140,12 @@ Item {
133140
134141 function test_set_current_scope_reset() {
135142 var dashContentList = findChild(dashContent, "dashContentList");
136− verify(dashContentList != undefined);
137− var categoryListView = findChild(dashContentList, "categoryListView");
138− verify(categoryListView != undefined);
143+ verify(dashContentList, "Couldn't find dashContentList");
144+ var scope = findChild(dashContent, "MockScope1 loader");
139145
146+ tryCompare(scope, "status", Loader.Ready);
147+
148+ var categoryListView = findChild(dashContentList, "categoryListView");
140149 categoryListView.contentY = units.gu(10);
141150
142151 compare(dashContentList.currentItem.item.objectName, "MockScope1")
tests/qmltests/Dash/tst_GenericScopeView.qml+45−23
@@ -60,7 +60,7 @@ Item {
6060 genericScopeView.scope = scopes.getScope(1)
6161 shell.width = units.gu(120)
6262 genericScopeView.categoryView.positionAtBeginning();
63− tryCompare(genericScopeView.categoryView, "contentY", 0)
63+ waitForRendering(genericScopeView.categoryView);
6464 }
6565
6666 function test_isActive() {
@@ -106,8 +106,6 @@ Item {
106106 }
107107
108108 function test_filter_expand_collapse() {
109− // wait for the item to be there
110− waitForRendering(genericScopeView);
111109 tryCompareFunction(function() { return findChild(genericScopeView, "dashSectionHeader0") != null; }, true);
112110
113111 var header = findChild(genericScopeView, "dashSectionHeader0")
@@ -115,18 +113,18 @@ Item {
115113
116114 waitForRendering(header);
117115 verify(category.expandable);
118− verify(category.filtered);
116+ verify(!category.expanded);
119117
120118 var initialHeight = category.height;
121119 var middleHeight;
122120 mouseClick(header, header.width / 2, header.height / 2);
123121 tryCompareFunction(function() { middleHeight = category.height; return category.height > initialHeight; }, true);
124− tryCompare(category, "filtered", false);
122+ tryCompare(category, "expanded", true);
125123 tryCompareFunction(function() { return category.height > middleHeight; }, true);
126124
127125 mouseClick(header, header.width / 2, header.height / 2);
128126 verify(category.expandable);
129− tryCompare(category, "filtered", true);
127+ tryCompare(category, "expanded", false);
130128 }
131129
132130 function test_filter_expand_expand_collapse() {
@@ -138,51 +136,75 @@ Item {
138136
139137 var header2 = findChild(genericScopeView, "dashSectionHeader2")
140138 var category2 = findChild(genericScopeView, "dashCategory2")
141− var category2FilterGrid = category2.children[1].children[2];
142− verify(UT.Util.isInstanceOf(category2FilterGrid, "CardFilterGrid"));
143139
144140 waitForRendering(header2);
145141 verify(category2.expandable);
146− verify(category2.filtered);
142+ verify(!category2.expanded);
147143
148144 mouseClick(header2, header2.width / 2, header2.height / 2);
149− tryCompare(category2, "filtered", false);
150− tryCompare(category2FilterGrid, "filtered", false);
145+ tryCompare(category2, "expanded", true);
151146
152147 categoryListView.positionAtBeginning();
153148
154149 var header0 = findChild(genericScopeView, "dashSectionHeader0")
155150 var category0 = findChild(genericScopeView, "dashCategory0")
156151 mouseClick(header0, header0.width / 2, header0.height / 2);
157− tryCompare(category0, "filtered", false);
158− tryCompare(category2, "filtered", true);
159− tryCompare(category2FilterGrid, "filtered", true);
152+ tryCompare(category0, "expanded", true);
153+ tryCompare(category2, "expanded", false);
160154 mouseClick(header0, header0.width / 2, header0.height / 2);
161− tryCompare(category0, "filtered", true);
162− tryCompare(category2, "filtered", true);
155+ tryCompare(category0, "expanded", false);
156+ tryCompare(category2, "expanded", false);
163157 }
164158
165159 function test_narrow_delegate_ranges_expand() {
166− tryCompareFunction(function() { return findChild(genericScopeView, "dashCategory0") != undefined; }, true);
160+ tryCompareFunction(function() { return findChild(genericScopeView, "dashCategory0") !== null; }, true);
167161 var category = findChild(genericScopeView, "dashCategory0")
168− tryCompare(category, "filtered", true);
162+ tryCompare(category, "expanded", false);
169163
170164 shell.width = units.gu(20)
171165 var categoryListView = findChild(genericScopeView, "categoryListView");
172166 categoryListView.contentY = units.gu(20);
173167 var header0 = findChild(genericScopeView, "dashSectionHeader0")
174168 mouseClick(header0, header0.width / 2, header0.height / 2);
175− tryCompare(category, "filtered", false);
169+ tryCompare(category, "expanded", true);
176170 tryCompareFunction(function() { return category.item.height == genericScopeView.height - category.item.displayMarginBeginning - category.item.displayMarginEnd; }, true);
177171 mouseClick(header0, header0.width / 2, header0.height / 2);
178− tryCompare(category, "filtered", true);
172+ tryCompare(category, "expanded", false);
173+ }
174+
175+ function test_forced_category_expansion() {
176+ tryCompareFunction(function() {
177+ mouseFlick(genericScopeView, genericScopeView.width/2, genericScopeView.height,
178+ genericScopeView.width/2, genericScopeView.y)
179+ return findChild(genericScopeView, "dashCategory19") !== null;
180+ }, true);
181+ var category = findChild(genericScopeView, "dashCategory19")
182+ compare(category.expandable, false, "Category with collapsed-rows: 0 should not be expandable");
183+
184+ var grid = findChild(category, "19");
185+ verify(grid, "Could not find the category renderer.");
186+
187+ compare(grid.height, grid.expandedHeight, "Category with collapsed-rows: 0 should always be expanded.");
188+ }
189+
190+ function test_single_category_expansion() {
191+ genericScopeView.scope = scopes.getScope(4);
192+
193+ tryCompareFunction(function() { return findChild(genericScopeView, "dashCategory0") != undefined; }, true);
194+ var category = findChild(genericScopeView, "dashCategory0")
195+ compare(category.expandable, false, "Only category should not be expandable.");
196+
197+ var grid = findChild(category, "0");
198+ verify(grid, "Could not find the category renderer.");
199+
200+ compare(grid.height, grid.expandedHeight, "Only category should always be expanded");
179201 }
180202
181203 function openPreview() {
182204 tryCompareFunction(function() {
183− var filterGrid = findChild(genericScopeView, "0");
184− if (filterGrid != null) {
185− var tile = findChild(filterGrid, "delegate0");
205+ var cardGrid = findChild(genericScopeView, "0");
206+ if (cardGrid != null) {
207+ var tile = findChild(cardGrid, "delegate0");
186208 return tile != null;
187209 }
188210 return false;