on xenial help sign in
Add TabBar to the Dash header navigation
99cc5b5Albert Astals
plugins/Utils/qsortfilterproxymodelqml.cpp+12
@@ -68,6 +68,18 @@ QSortFilterProxyModelQML::setModel(QAbstractItemModel *itemModel)
68 }
68 }
69}
69}
70
70
71+QVariantMap
72+QSortFilterProxyModelQML::get(int row)
73+{
74+ QVariantMap res;
75+ const QHash<int, QByteArray> roles = roleNames();
76+ auto it = roles.begin();
77+ for ( ; it != roles.end(); ++it) {
78+ res[*it] = data(row, it.key());
79+ }
80+ return res;
81+}
82+
71QVariant
83QVariant
72QSortFilterProxyModelQML::data(int row, int role)
84QSortFilterProxyModelQML::data(int row, int role)
73{
85{
plugins/Utils/qsortfilterproxymodelqml.h+1
@@ -31,6 +31,7 @@ class QSortFilterProxyModelQML : public QSortFilterProxyModel
31public:
31public:
32 explicit QSortFilterProxyModelQML(QObject *parent = 0);
32 explicit QSortFilterProxyModelQML(QObject *parent = 0);
33
33
34+ Q_INVOKABLE QVariantMap get(int row); // Use with caution, it can be slow to query all the roles
34 Q_INVOKABLE QVariant data(int row, int role);
35 Q_INVOKABLE QVariant data(int row, int role);
35 Q_INVOKABLE int count();
36 Q_INVOKABLE int count();
36 Q_INVOKABLE int findFirst(int role, const QVariant& value) const;
37 Q_INVOKABLE int findFirst(int role, const QVariant& value) const;
qml/Components/PageHeader.qml+13−37
@@ -21,17 +21,12 @@ import Ubuntu.Components.ListItems 0.1 as ListItem
21import Unity 0.1
21import Unity 0.1
22
22
23Item {
23Item {
24− /*!
24+ id: root
25− \preliminary
26− The text that is shown inside the Page Header
27− \qmlproperty string text
28− */
29− property alias text: label.text
30−
31 property bool searchEntryEnabled: false
25 property bool searchEntryEnabled: false
32 property alias searchQuery: searchField.text
26 property alias searchQuery: searchField.text
33 property ListModel searchHistory
27 property ListModel searchHistory
34 property Scope scope
28 property Scope scope
29+ property alias childItem: itemContainer.children
35
30
36 height: units.gu(8.5)
31 height: units.gu(8.5)
37 implicitHeight: units.gu(8.5)
32 implicitHeight: units.gu(8.5)
@@ -82,29 +77,10 @@ Item {
82 height: childrenRect.height
77 height: childrenRect.height
83
78
84 Item {
79 Item {
85− id: textContainer
80+ id: itemContainer
86
81
87− width: header.width
82+ width: searchContainer.narrowMode ? header.width : header.width - searchContainer.width
88 height: header.height
83 height: header.height
89−
90− Label {
91− id: label
92− anchors {
93− left: parent.left
94− leftMargin: units.gu(2)
95− right: parent.right
96− verticalCenter: parent.verticalCenter
97− }
98−
99− color: Theme.palette.selected.backgroundText
100− opacity: 0.8
101− font.family: "Ubuntu"
102− font.weight: Font.Light
103− fontSize: "x-large"
104− elide: Text.ElideRight
105− style: Text.Raised
106− styleColor: "black"
107− }
108 }
84 }
109
85
110 Item {
86 Item {
@@ -115,12 +91,12 @@ Item {
115 property bool popoverShouldOpen: false
91 property bool popoverShouldOpen: false
116 property bool popoverShouldClose: false
92 property bool popoverShouldClose: false
117
93
118− property bool narrowMode: parent.width < label.contentWidth + units.gu(50)
94+ property bool narrowMode: parent.width < units.gu(80)
119
95
120 property bool active: searchField.text != "" || searchField.activeFocus
96 property bool active: searchField.text != "" || searchField.activeFocus
121 property var popover: null
97 property var popover: null
122
98
123− anchors.right: textContainer.right
99+ anchors.right: headerContainer.right
124 height: header.height
100 height: header.height
125
101
126 state:
102 state:
@@ -255,13 +231,13 @@ Item {
255 states: [
231 states: [
256 State {
232 State {
257 name: "wide"
233 name: "wide"
258− AnchorChanges { target: textContainer; anchors.top: headerContainer.top }
234+ AnchorChanges { target: itemContainer; anchors.top: headerContainer.top }
259− AnchorChanges { target: searchContainer; anchors.left: undefined; anchors.top: textContainer.top }
235+ AnchorChanges { target: searchContainer; anchors.left: undefined; anchors.top: itemContainer.top }
260 },
236 },
261 State {
237 State {
262 name: "narrow"
238 name: "narrow"
263 PropertyChanges { target: searchField; highlighted: true }
239 PropertyChanges { target: searchField; highlighted: true }
264− AnchorChanges { target: textContainer; anchors.top: searchContainer.bottom }
240+ AnchorChanges { target: itemContainer; anchors.top: searchContainer.bottom }
265 AnchorChanges { target: searchContainer; anchors.left: headerContainer.left; anchors.top: headerContainer.top }
241 AnchorChanges { target: searchContainer; anchors.left: headerContainer.left; anchors.top: headerContainer.top }
266 },
242 },
267 State {
243 State {
@@ -299,7 +275,7 @@ Item {
299 ParallelAnimation {
275 ParallelAnimation {
300 NumberAnimation { targets: [searchContainer, searchField]; property: "width"; duration: 200; easing.type: Easing.InOutQuad }
276 NumberAnimation { targets: [searchContainer, searchField]; property: "width"; duration: 200; easing.type: Easing.InOutQuad }
301 PropertyAction { target: primaryImage; property: "source" }
277 PropertyAction { target: primaryImage; property: "source" }
302− AnchorAnimation { targets: [searchContainer, textContainer]; duration: 200; easing.type: Easing.InOutQuad }
278+ AnchorAnimation { targets: [searchContainer, itemContainer]; duration: 200; easing.type: Easing.InOutQuad }
303 }
279 }
304 ScriptAction { script: if (searchContainer.popoverShouldOpen) { searchContainer.openPopover(); } }
280 ScriptAction { script: if (searchContainer.popoverShouldOpen) { searchContainer.openPopover(); } }
305 }
281 }
@@ -308,14 +284,14 @@ Item {
308 to: "inactive"
284 to: "inactive"
309 ScriptAction { script: if (searchContainer.popoverShouldClose) { searchContainer.closePopover(); } }
285 ScriptAction { script: if (searchContainer.popoverShouldClose) { searchContainer.closePopover(); } }
310 NumberAnimation { targets: [searchContainer, searchField] ; property: "width"; duration: 200; easing.type: Easing.InOutQuad }
286 NumberAnimation { targets: [searchContainer, searchField] ; property: "width"; duration: 200; easing.type: Easing.InOutQuad }
311− AnchorAnimation { targets: [searchContainer, textContainer]; duration: 200; easing.type: Easing.InOutQuad }
287+ AnchorAnimation { targets: [searchContainer, itemContainer]; duration: 200; easing.type: Easing.InOutQuad }
312 },
288 },
313 Transition {
289 Transition {
314 to: "narrowActive"
290 to: "narrowActive"
315 SequentialAnimation {
291 SequentialAnimation {
316 ParallelAnimation {
292 ParallelAnimation {
317 NumberAnimation { targets: [searchContainer, searchField] ; property: "width"; duration: 200; easing.type: Easing.OutQuad }
293 NumberAnimation { targets: [searchContainer, searchField] ; property: "width"; duration: 200; easing.type: Easing.OutQuad }
318− AnchorAnimation { targets: [searchContainer, textContainer]; duration: 200; easing.type: Easing.InOutQuad }
294+ AnchorAnimation { targets: [searchContainer, itemContainer]; duration: 200; easing.type: Easing.InOutQuad }
319 }
295 }
320 ScriptAction { script: if (searchContainer.popoverShouldOpen) { searchContainer.openPopover(); } }
296 ScriptAction { script: if (searchContainer.popoverShouldOpen) { searchContainer.openPopover(); } }
321 }
297 }
@@ -324,7 +300,7 @@ Item {
324 to: "narrowInactive"
300 to: "narrowInactive"
325 ScriptAction { script: if (searchContainer.popoverShouldClose) { searchContainer.closePopover(); } }
301 ScriptAction { script: if (searchContainer.popoverShouldClose) { searchContainer.closePopover(); } }
326 NumberAnimation { targets: [searchContainer, searchField] ; property: "width"; duration: 200; easing.type: Easing.OutQuad }
302 NumberAnimation { targets: [searchContainer, searchField] ; property: "width"; duration: 200; easing.type: Easing.OutQuad }
327− AnchorAnimation { targets: [searchContainer, textContainer]; duration: 200; easing.type: Easing.InOutQuad }
303+ AnchorAnimation { targets: [searchContainer, itemContainer]; duration: 200; easing.type: Easing.InOutQuad }
328 }
304 }
329 ]
305 ]
330
306
qml/Components/PageHeaderLabel.qmlnew file+41
@@ -0,0 +1,41 @@
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+
20+PageHeader {
21+ property alias text: label.text
22+
23+ childItem: Label {
24+ id: label
25+ anchors {
26+ left: parent.left
27+ leftMargin: units.gu(2)
28+ right: parent.right
29+ verticalCenter: parent.verticalCenter
30+ }
31+
32+ color: Theme.palette.selected.backgroundText
33+ opacity: 0.8
34+ font.family: "Ubuntu"
35+ font.weight: Font.Light
36+ fontSize: "x-large"
37+ elide: Text.ElideRight
38+ style: Text.Raised
39+ styleColor: "black"
40+ }
41+}
qml/Dash/Dash.qml−18
@@ -66,11 +66,6 @@ Showable {
66 model: filteredScopes
66 model: filteredScopes
67 scopes: scopes
67 scopes: scopes
68 searchHistory: dash.searchHistory
68 searchHistory: dash.searchHistory
69− onMovementStarted: dashbar.startNavigation()
70− onMovementEnded: dashbar.stopNavigation()
71− onContentFlickStarted: dashbar.finishNavigation()
72− onContentEndReached: dashbar.finishNavigation()
73− onPreviewShown: dashbar.finishNavigation()
74 onScopeLoaded: {
69 onScopeLoaded: {
75 if (scopeId == dash.showScopeOnLoaded) {
70 if (scopeId == dash.showScopeOnLoaded) {
76 dash.setCurrentScope(scopeId, false, false)
71 dash.setCurrentScope(scopeId, false, false)
@@ -80,17 +75,4 @@ Showable {
80 scale: dash.contentScale
75 scale: dash.contentScale
81 clip: scale != 1.0
76 clip: scale != 1.0
82 }
77 }
83−
84− DashBar {
85− id: dashbar
86− objectName: "dashbar"
87− anchors.bottom: parent.bottom
88− anchors.left: parent.left
89− anchors.right: parent.right
90− model: filteredScopes
91− currentIndex: dashContent.currentIndex
92− onItemSelected: dashContent.setCurrentScopeAtIndex(index, true, false)
93− opacity: dash.contentScale == 1.0 ? 1.0 : 0.0
94− Behavior on opacity { NumberAnimation { easing.type: Easing.OutQuad; duration: 150 } }
95− }
96}
78}
qml/Dash/DashApps.qml−3
@@ -29,9 +29,6 @@ GenericScopeView {
29 property var mainStageApplicationsModel: shell.applicationManager.mainStageApplications
29 property var mainStageApplicationsModel: shell.applicationManager.mainStageApplications
30 property var sideStageApplicationModel: shell.applicationManager.sideStageApplications
30 property var sideStageApplicationModel: shell.applicationManager.sideStageApplications
31
31
32− //FIXME an alias to itself shouldn't be required. More than likely a Qt bug. Try removing with newer Qt.
33− property alias searchHistory: scopeView.searchHistory
34−
35 ListModel {
32 ListModel {
36 id: dummyVisibilityModifier
33 id: dummyVisibilityModifier
37
34
qml/Dash/DashBar.qmldeleted−128
@@ -1,128 +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 Unity 0.1
20−
21−Item {
22− id: dashBar
23−
24− property var model
25− property alias currentIndex: row.currentIndex
26−
27− property int lineHeight: units.dp(2)
28− property int itemSize: units.gu(7)
29− property int iconSize: units.gu(3.5)
30−
31− signal itemSelected(int index)
32−
33− width: units.gu(40)
34− height: units.gu(6)
35−
36− function startNavigation() {
37− timeout.stop()
38− panel.open()
39− }
40−
41− function stopNavigation() {
42− timeout.restart()
43− }
44−
45− function finishNavigation() {
46− panel.close()
47− }
48−
49− Timer {
50− id: timeout
51− interval: 1500
52− running: false
53− repeat: false
54− onTriggered: finishNavigation()
55− }
56−
57− Panel {
58− id: panel
59− objectName: "panel"
60− anchors.fill: parent
61−
62− locked: true // TODO: remove this when lp bug #1179569 will be fixed
63−
64− Rectangle {
65− color: "black"
66− anchors.fill: parent
67−
68− ListView {
69− id: row
70− objectName: "row"
71− model: dashBar.model
72− orientation: ListView.Horizontal
73− width: Math.min(Math.max(dashBar.width/2, units.gu(40)), count * itemSize)
74− height: parent.height
75− anchors.horizontalCenter: parent.horizontalCenter
76− onMovingChanged: if (moving) { timeout.stop() } else { timeout.restart() }
77− interactive: visibleArea.widthRatio < 1 && panel.opened
78− highlightFollowsCurrentItem: false
79−
80− onCurrentItemChanged: {
81− highlightLine.width = currentItem.width
82− highlightLine.x = x + currentItem.x
83− }
84−
85− delegate:
86− // FIXME: Use Panel's integrated trigger() once that works again.
87− MouseArea {
88− width: itemSize
89− height: dashBar.height
90− anchors.top: parent.top
91−
92− onClicked: {
93− dashBar.itemSelected(index)
94− timeout.restart()
95− }
96−
97− Image {
98− anchors.centerIn: parent
99− source: scope.iconHint
100− sourceSize { width: iconSize; height: iconSize }
101− // opacity: index == currentIndex ? 1 : 1 // same opacity for now
102− }
103− }
104− }
105− }
106− }
107−
108− Rectangle {
109− anchors {
110− left: parent.left
111− right: parent.right
112− bottom: parent.bottom
113− }
114− height: dashBar.lineHeight
115− color: "black"
116−
117− Rectangle {
118− id: highlightLine
119− color: Theme.palette.selected.foreground
120− height: parent.height
121− anchors.bottom: parent.bottom
122− z: 1
123−
124− Behavior on x {NumberAnimation { duration: 150; easing.type: Easing.OutCubic}}
125− Behavior on width {NumberAnimation { duration: 150; easing.type: Easing.OutCubic}}
126− }
127− }
128−}
qml/Dash/DashContent.qml+123−62
@@ -17,6 +17,7 @@
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19import Unity 0.1
19import Unity 0.1
20+import "../Components"
20
21
21Item {
22Item {
22 id: dashContent
23 id: dashContent
@@ -33,7 +34,6 @@ Item {
33 signal movementEnded()
34 signal movementEnded()
34 signal contentFlickStarted()
35 signal contentFlickStarted()
35 signal contentEndReached()
36 signal contentEndReached()
36− signal previewShown()
37 signal scopeLoaded(string scopeId)
37 signal scopeLoaded(string scopeId)
38 signal positionedAtBeginning()
38 signal positionedAtBeginning()
39
39
@@ -80,77 +80,138 @@ Item {
80 }
80 }
81 }
81 }
82
82
83− ListView {
83+ Item {
84− id: dashContentList
84+ id: dashContentListHolder
85− objectName: "dashContentList"
86−
87− interactive: dashContent.scopes.loaded && !currentItem.previewShown && !currentItem.moving
88−
89 anchors.fill: parent
85 anchors.fill: parent
86+
87+ ListView {
88+ id: dashContentList
89+ objectName: "dashContentList"
90+
91+ interactive: dashContent.scopes.loaded && !previewListView.onScreen && !currentItem.moving
92+
93+ anchors.fill: parent
90− model: dashContent.model
94+ model: dashContent.model
91− orientation: ListView.Horizontal
95+ orientation: ListView.Horizontal
92− boundsBehavior: Flickable.DragAndOvershootBounds
96+ boundsBehavior: Flickable.DragAndOvershootBounds
93− flickDeceleration: units.gu(625)
97+ flickDeceleration: units.gu(625)
94− maximumFlickVelocity: width * 5
98+ maximumFlickVelocity: width * 5
95− snapMode: ListView.SnapOneItem
99+ snapMode: ListView.SnapOneItem
96− highlightMoveDuration: 250
100+ highlightMoveDuration: 250
97− highlightRangeMode: ListView.StrictlyEnforceRange
101+ highlightRangeMode: ListView.StrictlyEnforceRange
98− /* FIXME: workaround rendering issue due to use of ShaderEffectSource in
102+ // TODO Investigate if we can switch to a smaller cache buffer when/if UbuntuShape gets more performant
99− UbuntuShape. While switching from the home scope to the People scope the
100− rendering would block midway.
101− */
102− cacheBuffer: 2147483647
103+ cacheBuffer: 1073741823
103− onMovementStarted: dashContent.movementStarted()
104+ onMovementStarted: dashContent.movementStarted()
104− onMovementEnded: dashContent.movementEnded()
105+ onMovementEnded: dashContent.movementEnded()
105−
106+
106− // If the number of items is less than the current index, then need to reset to another item.
107+ // If the number of items is less than the current index, then need to reset to another item.
107− onCountChanged: {
108+ onCountChanged: {
108− if (count > 0) {
109+ if (count > 0) {
109− if (currentIndex >= count) {
110+ if (currentIndex >= count) {
110− dashContent.setCurrentScopeAtIndex(count-1, true, true)
111+ dashContent.setCurrentScopeAtIndex(count-1, true, true)
111− } else if (currentIndex < 0) {
112+ } else if (currentIndex < 0) {
112− // setting currentIndex directly, cause we don't want to loose set_current_index
113+ // setting currentIndex directly, cause we don't want to loose set_current_index
113− dashContent.currentIndex = 0
114+ dashContent.currentIndex = 0
115+ }
114 }
116 }
115 }
117 }
118+
119+ delegate:
120+ Loader {
121+ width: ListView.view.width
122+ height: ListView.view.height
123+ asynchronous: true
124+ source: scopeMapper.map(scope.id)
125+ objectName: scope.id + " loader"
126+
127+ readonly property bool moving: item ? item.moving : false
128+ readonly property var categoryView: item ? item.categoryView : null
129+ readonly property Scope theScope: scope
130+
131+ // these are needed for autopilot tests
132+ readonly property string scopeId: scope.id
133+ readonly property bool isCurrent: ListView.isCurrentItem
134+ readonly property bool isLoaded: status == Loader.Ready
135+
136+ onLoaded: {
137+ item.scope = Qt.binding(function() { return scope })
138+ item.isCurrent = Qt.binding(function() { return visible && ListView.isCurrentItem })
139+ item.tabBarHeight = pageHeader.implicitHeight;
140+ item.pageHeader = pageHeader;
141+ item.openEffect = openEffect;
142+ item.previewListView = previewListView;
143+ dashContentList.movementStarted.connect(item.movementStarted)
144+ dashContent.positionedAtBeginning.connect(item.positionedAtBeginning)
145+ dashContent.scopeLoaded(item.scope.id)
146+ }
147+ Connections {
148+ target: item
149+ ignoreUnknownSignals: true
150+ onEndReached: contentEndReached()
151+ }
152+
153+ Component.onDestruction: active = false
154+ }
116 }
155 }
117
156
118− delegate:
157+ PageHeader {
119− Loader {
158+ id: pageHeader
120− width: ListView.view.width
159+ width: parent.width
121− height: ListView.view.height
160+ searchEntryEnabled: true
122− asynchronous: true
161+ searchHistory: dashContent.searchHistory
123− source: scopeMapper.map(scope.id)
162+
163+ childItem: TabBar {
164+ id: tabBar
124− objectName: scope.id + " loader"
165+ objectName: "tabbar"
125−
166+ height: units.gu(7)
126− readonly property bool previewShown: item ? item.previewShown : false
167+ width: parent.width
127− readonly property bool moving: item ? item.moving : false
168+ selectionMode: false
128−
169+ style: DashContentTabBarStyle {}
129− // these are needed for autopilot tests
170+
130− readonly property string scopeId: scope.id
171+ model: dashContentList.model
131− readonly property bool isCurrent: ListView.isCurrentItem
172+
132− readonly property bool isLoaded: status == Loader.Ready
173+ onSelectedIndexChanged: {
133−
174+ dashContentList.currentIndex = selectedIndex;
134− onLoaded: {
135− item.scope = Qt.binding(function() { return scope })
136− item.isCurrent = Qt.binding(function() { return visible && ListView.isCurrentItem })
137− item.searchHistory = Qt.binding(function() { return dashContent.searchHistory })
138− dashContentList.movementStarted.connect(item.movementStarted)
139− dashContent.positionedAtBeginning.connect(item.positionedAtBeginning)
140− dashContent.scopeLoaded(item.scope.id)
141 }
175 }
176+
142 Connections {
177 Connections {
143− target: item
178+ target: dashContentList
144− ignoreUnknownSignals: true
179+ onCurrentIndexChanged: {
145− onEndReached: contentEndReached()
180+ tabBar.selectedIndex = dashContentList.currentIndex
146− onPreviewShownChanged: {
147− if (item.previewShown) {
148− dashContent.previewShown()
149− }
150 }
181 }
151 }
182 }
152
183
153− Component.onDestruction: active = false
184+ Connections {
185+ target: model
186+ onCountChanged: {
187+ if (tabBar.selectedIndex < 0 && model.count > 0)
188+ tabBar.selectedIndex = 0;
189+ }
190+ }
191+
192+ Component.onCompleted: {
193+ __styleInstance.headerTextStyle = Text.Raised
194+ __styleInstance.headerTextStyleColor = "black"
195+ }
154 }
196 }
197+ }
198+ }
199+
200+ DashContentOpenEffect {
201+ id: openEffect
202+ anchors {
203+ fill: parent
204+ bottomMargin: -bottomOverflow
205+ }
206+ sourceItem: dashContentListHolder
207+ previewListView: previewListView
208+ }
209+
210+ PreviewListView {
211+ id: previewListView
212+ openEffect: openEffect
213+ categoryView: dashContentList.currentItem ? dashContentList.currentItem.categoryView : null
214+ scope: dashContentList.currentItem ? dashContentList.currentItem.theScope : null
215+ anchors.fill: parent
155 }
216 }
156}
217}
qml/Dash/DashContentOpenEffect.qmlnew file+57
@@ -0,0 +1,57 @@
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 "../Components"
20+
21+OpenEffect {
22+ property PreviewListView previewListView: null
23+
24+ objectName: "openEffect"
25+ anchors {
26+ fill: parent
27+ bottomMargin: -bottomOverflow
28+ }
29+
30+ enabled: gap > 0.0
31+
32+ topGapPx: (1 - gap) * positionPx
33+ topOpacity: (1 - gap * 1.2)
34+ bottomGapPx: positionPx + gap * (targetBottomGapPx - positionPx)
35+ bottomOverflow: units.gu(20)
36+ live: !expansionAnimation.running
37+
38+ property int targetBottomGapPx: height - units.gu(8) - bottomOverflow
39+ property real gap: previewListView.open ? 1.0 : 0.0
40+
41+ Behavior on gap {
42+ NumberAnimation {
43+ id: expansionAnimation
44+ duration: 200
45+ easing.type: Easing.InOutQuad
46+ onRunningChanged: {
47+ if (!previewListView.open && !running) {
48+ previewListView.onScreen = false
49+ }
50+ }
51+ }
52+ }
53+ Behavior on positionPx {
54+ enabled: previewListView.open
55+ UbuntuNumberAnimation {}
56+ }
57+}
qml/Dash/DashContentTabBarStyle.qmlnew file+21
@@ -0,0 +1,21 @@
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 Ubuntu.Components.Themes.Ambiance 0.1
18+
19+TabBarStyle {
20+ indicatorImageSource: "graphics/tabbarchevron.png"
21+}
qml/Dash/GenericScopeView.qml+28−228
@@ -27,15 +27,18 @@ FocusScope {
27 property Scope scope
27 property Scope scope
28 property SortFilterProxyModel categories: categoryFilter
28 property SortFilterProxyModel categories: categoryFilter
29 property bool isCurrent
29 property bool isCurrent
30− property ListModel searchHistory
31 property alias moving: categoryView.moving
30 property alias moving: categoryView.moving
31+ property int tabBarHeight: 0
32+ property PageHeader pageHeader: null
33+ property OpenEffect openEffect: null
34+ property Item previewListView: null
32
35
33 signal endReached
36 signal endReached
34 signal movementStarted
37 signal movementStarted
35 signal positionedAtBeginning
38 signal positionedAtBeginning
36
39
37− readonly property alias previewShown: previewListView.onScreen
38 property bool enableHeightBehaviorOnNextCreation: false
40 property bool enableHeightBehaviorOnNextCreation: false
41+ property var categoryView: categoryView
39
42
40 // FIXME delay the search so that daemons have time to settle, note that
43 // FIXME delay the search so that daemons have time to settle, note that
41 // removing this will break ScopeView::test_changeScope
44 // removing this will break ScopeView::test_changeScope
@@ -84,12 +87,14 @@ FocusScope {
84 target: scopeView.scope
87 target: scopeView.scope
85 property: "searchQuery"
88 property: "searchQuery"
86 value: pageHeader.searchQuery
89 value: pageHeader.searchQuery
90+ when: isCurrent
87 }
91 }
88
92
89 Binding {
93 Binding {
90 target: pageHeader
94 target: pageHeader
91 property: "searchQuery"
95 property: "searchQuery"
92 value: scopeView.scope.searchQuery
96 value: scopeView.scope.searchQuery
97+ when: isCurrent
93 }
98 }
94
99
95 Connections {
100 Connections {
@@ -119,6 +124,10 @@ FocusScope {
119 property string expandedCategoryId: ""
124 property string expandedCategoryId: ""
120 signal correctExpandedCategory();
125 signal correctExpandedCategory();
121
126
127+ onContentYChanged: pageHeader.positionRealHeader();
128+ onOriginYChanged: pageHeader.positionRealHeader();
129+ onContentHeightChanged: pageHeader.positionRealHeader();
130+
122 Behavior on contentY {
131 Behavior on contentY {
123 enabled: previewListView.open
132 enabled: previewListView.open
124 UbuntuNumberAnimation {}
133 UbuntuNumberAnimation {}
@@ -176,7 +185,7 @@ FocusScope {
176 target: rendererLoader.item
185 target: rendererLoader.item
177 onClicked: {
186 onClicked: {
178 // Prepare the preview in case activate() triggers a preview only
187 // Prepare the preview in case activate() triggers a preview only
179− effect.positionPx = Math.max(mapToItem(categoryView, 0, itemY).y, pageHeader.height + categoryView.stickyHeaderHeight);
188+ openEffect.positionPx = Math.max(mapToItem(categoryView, 0, itemY).y, pageHeader.height + categoryView.stickyHeaderHeight);
180 previewListView.categoryId = categoryId
189 previewListView.categoryId = categoryId
181 previewListView.categoryDelegate = rendererLoader.item
190 previewListView.categoryDelegate = rendererLoader.item
182 previewListView.model = target.model;
191 previewListView.model = target.model;
@@ -197,7 +206,7 @@ FocusScope {
197 }
206 }
198 }
207 }
199 onPressAndHold: {
208 onPressAndHold: {
200− effect.positionPx = Math.max(mapToItem(categoryView, 0, itemY).y, pageHeader.height + categoryView.stickyHeaderHeight);
209+ openEffect.positionPx = Math.max(mapToItem(categoryView, 0, itemY).y, pageHeader.height + categoryView.stickyHeaderHeight);
201 previewListView.categoryId = categoryId
210 previewListView.categoryId = categoryId
202 previewListView.categoryDelegate = rendererLoader.item
211 previewListView.categoryDelegate = rendererLoader.item
203 previewListView.model = target.model;
212 previewListView.model = target.model;
@@ -288,14 +297,20 @@ FocusScope {
288 categoryView.expandedCategoryId = "";
297 categoryView.expandedCategoryId = "";
289 }
298 }
290 }
299 }
291− pageHeader: PageHeader {
300+ pageHeader: Item {
292− id: pageHeader
301+ implicitHeight: scopeView.tabBarHeight
293− objectName: "pageHeader"
302+ onHeightChanged: {
294− width: categoryView.width
303+ if (scopeView.pageHeader) {
295− text: scopeView.scope.name
304+ scopeView.pageHeader.height = height;
296− searchEntryEnabled: true
305+ }
306+ }
307+ onYChanged: positionRealHeader();
308+
309+ function positionRealHeader() {
297− scope: scopeView.scope
310+ if (scopeView.pageHeader) {
298− searchHistory: scopeView.searchHistory
311+ scopeView.pageHeader.y = y + parent.y;
312+ }
313+ }
299 }
314 }
300 }
315 }
301
316
@@ -346,44 +361,6 @@ FocusScope {
346 }
361 }
347 }
362 }
348
363
349− OpenEffect {
350− id: effect
351− objectName: "openEffect"
352− anchors {
353− fill: parent
354− bottomMargin: -bottomOverflow
355− }
356− sourceItem: categoryView
357−
358− enabled: gap > 0.0
359−
360− topGapPx: (1 - gap) * positionPx
361− topOpacity: (1 - gap * 1.2)
362− bottomGapPx: positionPx + gap * (targetBottomGapPx - positionPx)
363− bottomOverflow: units.gu(20)
364− live: !expansionAnimation.running
365−
366− property int targetBottomGapPx: height - units.gu(8) - bottomOverflow
367− property real gap: previewListView.open ? 1.0 : 0.0
368−
369− Behavior on gap {
370− NumberAnimation {
371− id: expansionAnimation
372− duration: 200
373− easing.type: Easing.InOutQuad
374− onRunningChanged: {
375− if (!previewListView.open && !running) {
376− previewListView.onScreen = false
377− }
378− }
379− }
380− }
381− Behavior on positionPx {
382− enabled: previewListView.open
383− UbuntuNumberAnimation {}
384− }
385− }
386−
387 Connections {
364 Connections {
388 target: scopeView.scope
365 target: scopeView.scope
389 onPreviewReady: {
366 onPreviewReady: {
@@ -402,190 +379,13 @@ FocusScope {
402 }
379 }
403 }
380 }
404
381
405− PreviewDelegateMapper {
406− id: previewDelegateMapper
407− }
408−
409− ListView {
410− id: previewListView
411− objectName: "previewListView"
412− height: effect.bottomGapPx - effect.topGapPx
413− anchors {
414− top: parent.top
415− topMargin: effect.topGapPx
416− left: parent.left
417− right: parent.right
418− }
419− orientation: ListView.Horizontal
420− highlightRangeMode: ListView.StrictlyEnforceRange
421− snapMode: ListView.SnapOneItem
422− boundsBehavior: Flickable.DragAndOvershootBounds
423− highlightMoveDuration: 250
424− flickDeceleration: units.gu(625)
425− maximumFlickVelocity: width * 5
426− cacheBuffer: 0
427−
428− // To be set before opening the preview
429− property string categoryId: ""
430− property var categoryDelegate
431−
432− // because the ListView is built asynchronous, setting the
433− // currentIndex directly won't work. We need to refresh it
434− // when the first preview is ready to be displayed.
435− property bool init: true
436−
437− onCurrentIndexChanged: {
438− var row = Math.floor(currentIndex / categoryDelegate.columns);
439− if (categoryDelegate.collapsedRowCount <= row) {
440− categoryView.expandedCategoryId = categoryId
441− }
442−
443− if (open) {
444− categoryDelegate.highlightIndex = currentIndex
445− }
446−
447− if (!init && model !== undefined) {
448− var item = model.get(currentIndex)
449− scopeView.scope.preview(item.uri, item.icon, item.category, 0, item.mimetype, item.title, item.comment, item.dndUri, item.metadata)
450− }
451−
452− // Adjust contentY in case we need to change to it to show the next row
453− if (categoryDelegate.rows > 1) {
454− var itemY = categoryView.contentItem.mapFromItem(categoryDelegate.currentItem).y;
455−
456− // Find new contentY and effect.postionPx
457− var newContentY = itemY - effect.positionPx - categoryDelegate.verticalSpacing;
458−
459− // Make sure the item is not covered by a header. Move the effect split down if necessary
460− var headerHeight = pageHeader.height + categoryView.stickyHeaderHeight;
461− var effectAdjust = Math.max(effect.positionPx, headerHeight);
462−
463− // Make sure we don't overscroll the listview. If yes, adjust effect position
464− if (newContentY < 0) {
465− effectAdjust += newContentY;
466− newContentY = 0;
467− }
468− if (newContentY > Math.max(0, categoryView.contentHeight - categoryView.height)) {
469− effectAdjust += -(categoryView.contentHeight - categoryView.height) + newContentY
470− newContentY = categoryView.contentHeight - categoryView.height;
471− }
472−
473− effect.positionPx = effectAdjust;
474− categoryView.contentY = newContentY;
475− }
476− }
477−
478− property bool open: false
479− property bool onScreen: false
480−
481− onOpenChanged: {
482− if (open) {
483− onScreen = true;
484− categoryDelegate.highlightIndex = currentIndex;
485− pageHeader.unfocus();
486− } else {
487− // Cancel any pending preview requests or actions
488− if (previewListView.currentItem.previewData !== undefined) {
489− previewListView.currentItem.previewData.cancelAction();
490− }
491− scopeView.scope.cancelActivation();
492− model = undefined;
493− categoryView.correctExpandedCategory();
494− categoryDelegate.highlightIndex = -1;
495− }
496− }
497−
498− Rectangle {
499− anchors.fill: parent
500− color: Qt.rgba(0, 0, 0, .3)
501− z: -1
502− }
503−
504− delegate: Loader {
505− id: previewLoader
506− objectName: "previewLoader" + index
507− height: previewListView.height
508− width: previewListView.width
509− asynchronous: true
510− source: previewListView.onScreen ?
511− (previewData !== undefined ? previewDelegateMapper.map(previewData.rendererName) : "DashPreviewPlaceholder.qml") : ""
512−
513− onPreviewDataChanged: {
514− if (previewData !== undefined && source.toString().indexOf("DashPreviewPlaceholder.qml") != -1) {
515− previewLoader.opacity = 0;
516− }
517− }
518−
519− onSourceChanged: {
520− if (previewData !== undefined) {
521− fadeIn.start()
522− }
523− }
524−
525− PropertyAnimation {
526− id: fadeIn
527− target: previewLoader
528− property: "opacity"
529− from: 0.0
530− to: 1.0
531− duration: UbuntuAnimation.BriskDuration
532− }
533−
534− property var previewData
535− property bool valid: item !== null
536−
537− onLoaded: {
538− if (previewListView.onScreen && previewData !== undefined) {
539− item.previewData = Qt.binding(function() { return previewData })
540− item.isCurrent = Qt.binding(function() { return ListView.isCurrentItem })
541− }
542− }
543−
544− Connections {
545− ignoreUnknownSignals: true
546− target: item
547− onClose: {
548− previewListView.open = false
549− }
550− }
551−
552− function closePreviewSpinner() {
553− if (item) {
554− item.showProcessingAction = false;
555− }
556− }
557− }
558− }
559−
560− Image {
561− objectName: "pointerArrow"
562− anchors {
563− top: previewListView.bottom
564− left: parent.left
565− leftMargin: previewListView.categoryDelegate !== undefined && previewListView.categoryDelegate.currentItem ?
566− previewListView.categoryDelegate.currentItem.center + (-width + margins) / 2 : 0
567−
568− Behavior on leftMargin {
569− SmoothedAnimation {
570− duration: UbuntuAnimation.FastDuration
571− }
572− }
573− }
574− height: units.gu(1)
575− width: units.gu(2)
576− property int margins: previewListView.categoryDelegate ? previewListView.categoryDelegate.margins : 0
577− opacity: previewListView.open ? .5 : 0
578−
579− source: "graphics/tooltip_arrow.png"
580− }
581−
582 // TODO: Move as InverseMouseArea to DashPreview
382 // TODO: Move as InverseMouseArea to DashPreview
583 MouseArea {
383 MouseArea {
584 objectName: "closePreviewMouseArea"
384 objectName: "closePreviewMouseArea"
585 enabled: previewListView.onScreen
385 enabled: previewListView.onScreen
586 anchors {
386 anchors {
587 fill: parent
387 fill: parent
588− topMargin: effect.bottomGapPx
388+ topMargin: openEffect.bottomGapPx
589 }
389 }
590 onClicked: {
390 onClicked: {
591 previewListView.open = false;
391 previewListView.open = false;
qml/Dash/PreviewListView.qmlnew file+212
@@ -0,0 +1,212 @@
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 Unity 0.1
20+import "../Components"
21+
22+Item {
23+ property OpenEffect openEffect: null
24+ property ScopeListView categoryView: null
25+ property Scope scope: null
26+
27+ property alias open: previewListView.open
28+ property alias onScreen: previewListView.onScreen
29+ property alias categoryId: previewListView.categoryId
30+ property alias categoryDelegate: previewListView.categoryDelegate
31+ property alias init: previewListView.init
32+ property alias model: previewListView.model
33+ property alias currentIndex: previewListView.currentIndex
34+ property alias currentItem: previewListView.currentItem
35+
36+ Image {
37+ objectName: "pointerArrow"
38+ anchors {
39+ top: previewListView.bottom
40+ left: parent.left
41+ leftMargin: previewListView.categoryDelegate !== undefined && previewListView.categoryDelegate.currentItem ?
42+ previewListView.categoryDelegate.currentItem.center + (-width + margins) / 2 : 0
43+
44+ Behavior on leftMargin {
45+ SmoothedAnimation {
46+ duration: UbuntuAnimation.FastDuration
47+ }
48+ }
49+ }
50+ height: units.gu(1)
51+ width: units.gu(2)
52+ property int margins: previewListView.categoryDelegate ? previewListView.categoryDelegate.margins : 0
53+ opacity: previewListView.open ? .5 : 0
54+
55+ source: "graphics/tooltip_arrow.png"
56+ }
57+
58+ ListView {
59+ id: previewListView
60+ objectName: "previewListView"
61+ height: openEffect.bottomGapPx - openEffect.topGapPx
62+ anchors {
63+ top: parent.top
64+ topMargin: openEffect.topGapPx
65+ left: parent.left
66+ right: parent.right
67+ }
68+ orientation: ListView.Horizontal
69+ highlightRangeMode: ListView.StrictlyEnforceRange
70+ snapMode: ListView.SnapOneItem
71+ boundsBehavior: Flickable.DragAndOvershootBounds
72+ highlightMoveDuration: 250
73+ flickDeceleration: units.gu(625)
74+ maximumFlickVelocity: width * 5
75+ cacheBuffer: 0
76+
77+ // To be set before opening the preview
78+ property string categoryId: ""
79+ property var categoryDelegate
80+
81+ // because the ListView is built asynchronous, setting the
82+ // currentIndex directly won't work. We need to refresh it
83+ // when the first preview is ready to be displayed.
84+ property bool init: true
85+
86+ PreviewDelegateMapper {
87+ id: previewDelegateMapper
88+ }
89+
90+ onCurrentIndexChanged: {
91+ var row = Math.floor(currentIndex / categoryDelegate.columns);
92+ if (categoryDelegate.collapsedRowCount <= row) {
93+ categoryView.expandedCategoryId = categoryId
94+ }
95+
96+ if (open) {
97+ categoryDelegate.highlightIndex = currentIndex
98+ }
99+
100+ if (!init && model !== undefined) {
101+ var item = model.get(currentIndex)
102+ scope.preview(item.uri, item.icon, item.category, 0, item.mimetype, item.title, item.comment, item.dndUri, item.metadata)
103+ }
104+
105+ // Adjust contentY in case we need to change to it to show the next row
106+ if (categoryDelegate.rows > 1) {
107+ var itemY = categoryView.contentItem.mapFromItem(categoryDelegate.currentItem).y;
108+
109+ // Find new contentY and effect.postionPx
110+ var newContentY = itemY - openEffect.positionPx - categoryDelegate.verticalSpacing;
111+
112+ // Make sure the item is not covered by a header. Move the effect split down if necessary
113+ var headerHeight = pageHeader.height + categoryView.stickyHeaderHeight;
114+ var effectAdjust = Math.max(openEffect.positionPx, headerHeight);
115+
116+ // Make sure we don't overscroll the listview. If yes, adjust effect position
117+ if (newContentY < 0) {
118+ effectAdjust += newContentY;
119+ newContentY = 0;
120+ }
121+ if (newContentY > Math.max(0, categoryView.contentHeight - categoryView.height)) {
122+ effectAdjust += -(categoryView.contentHeight - categoryView.height) + newContentY
123+ newContentY = categoryView.contentHeight - categoryView.height;
124+ }
125+
126+ openEffect.positionPx = effectAdjust;
127+ categoryView.contentY = newContentY;
128+ }
129+ }
130+
131+ property bool open: false
132+ property bool onScreen: false
133+
134+ onOpenChanged: {
135+ if (open) {
136+ onScreen = true;
137+ categoryDelegate.highlightIndex = currentIndex;
138+ pageHeader.unfocus();
139+ } else {
140+ // Cancel any pending preview requests or actions
141+ if (previewListView.currentItem.previewData !== undefined) {
142+ previewListView.currentItem.previewData.cancelAction();
143+ }
144+ scope.cancelActivation();
145+ model = undefined;
146+ categoryView.correctExpandedCategory();
147+ categoryDelegate.highlightIndex = -1;
148+ }
149+ }
150+
151+ Rectangle {
152+ anchors.fill: parent
153+ color: Qt.rgba(0, 0, 0, .3)
154+ z: -1
155+ }
156+
157+ delegate: Loader {
158+ id: previewLoader
159+ objectName: "previewLoader" + index
160+ height: previewListView.height
161+ width: previewListView.width
162+ asynchronous: true
163+ source: previewListView.onScreen ?
164+ (previewData !== undefined ? previewDelegateMapper.map(previewData.rendererName) : "DashPreviewPlaceholder.qml") : ""
165+
166+ onPreviewDataChanged: {
167+ if (previewData !== undefined && source.toString().indexOf("DashPreviewPlaceholder.qml") != -1) {
168+ previewLoader.opacity = 0;
169+ }
170+ }
171+
172+ onSourceChanged: {
173+ if (previewData !== undefined) {
174+ fadeIn.start()
175+ }
176+ }
177+
178+ PropertyAnimation {
179+ id: fadeIn
180+ target: previewLoader
181+ property: "opacity"
182+ from: 0.0
183+ to: 1.0
184+ duration: UbuntuAnimation.BriskDuration
185+ }
186+
187+ property var previewData
188+ property bool valid: item !== null
189+
190+ onLoaded: {
191+ if (previewListView.onScreen && previewData !== undefined) {
192+ item.previewData = Qt.binding(function() { return previewData })
193+ item.isCurrent = Qt.binding(function() { return ListView.isCurrentItem })
194+ }
195+ }
196+
197+ Connections {
198+ ignoreUnknownSignals: true
199+ target: item
200+ onClose: {
201+ previewListView.open = false
202+ }
203+ }
204+
205+ function closePreviewSpinner() {
206+ if (item) {
207+ item.showProcessingAction = false;
208+ }
209+ }
210+ }
211+ }
212+}
qml/Dash/graphics/tabbarchevron@27.pngnew file

Binary file not shown.

qml/Hud/HudParametrizedActionsPage.qml+1−1
@@ -89,7 +89,7 @@ Item {
89 anchors.left: parent.left
89 anchors.left: parent.left
90 anchors.right: parent.right
90 anchors.right: parent.right
91
91
92− PageHeader {
92+ PageHeaderLabel {
93 id: header
93 id: header
94 anchors.top: parent.top
94 anchors.top: parent.top
95 anchors.left: parent.left
95 anchors.left: parent.left
tests/mocks/Unity/fake_scopes.cpp+3
@@ -35,6 +35,7 @@ Scopes::Scopes(QObject *parent)
35 m_roles[Scopes::RoleScope] = "scope";
35 m_roles[Scopes::RoleScope] = "scope";
36 m_roles[Scopes::RoleId] = "id";
36 m_roles[Scopes::RoleId] = "id";
37 m_roles[Scopes::RoleVisible] = "visible";
37 m_roles[Scopes::RoleVisible] = "visible";
38+ m_roles[Scopes::RoleTitle] = "title";
38
39
39 QObject::connect(this, SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SIGNAL(countChanged()));
40 QObject::connect(this, SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SIGNAL(countChanged()));
40 QObject::connect(this, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), this, SIGNAL(countChanged()));
41 QObject::connect(this, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), this, SIGNAL(countChanged()));
@@ -110,6 +111,8 @@ QVariant Scopes::data(const QModelIndex& index, int role) const
110 return QVariant::fromValue(scope->id());
111 return QVariant::fromValue(scope->id());
111 } else if (role == Scopes::RoleVisible) {
112 } else if (role == Scopes::RoleVisible) {
112 return QVariant::fromValue(scope->visible());
113 return QVariant::fromValue(scope->visible());
114+ } else if (role == Scopes::RoleTitle) {
115+ return QVariant::fromValue(scope->name());
113 } else {
116 } else {
114 return QVariant();
117 return QVariant();
115 }
118 }
tests/mocks/Unity/fake_scopes.h+2−1
@@ -41,7 +41,8 @@ public:
41 enum Roles {
41 enum Roles {
42 RoleScope,
42 RoleScope,
43 RoleId,
43 RoleId,
44− RoleVisible
44+ RoleVisible,
45+ RoleTitle
45 };
46 };
46
47
47 Q_INVOKABLE int rowCount(const QModelIndex& parent = QModelIndex()) const;
48 Q_INVOKABLE int rowCount(const QModelIndex& parent = QModelIndex()) const;
tests/qmltests/CMakeLists.txt+1−2
@@ -37,9 +37,8 @@ add_qml_test(Components Stage IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS}
37 ${CMAKE_BINARY_DIR}/tests/mocks
37 ${CMAKE_BINARY_DIR}/tests/mocks
38 ${CMAKE_BINARY_DIR}/plugins)
38 ${CMAKE_BINARY_DIR}/plugins)
39add_qml_test(Components Tile)
39add_qml_test(Components Tile)
40−add_qml_test(Components PageHeader)
40+add_qml_test(Components PageHeaderLabel)
41add_qml_test(Dash Dash IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
41add_qml_test(Dash Dash IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
42−add_qml_test(Dash DashBar IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${CMAKE_CURRENT_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
43add_qml_test(Dash DashContent IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
42add_qml_test(Dash DashContent IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
44add_qml_test(Dash DashPreview)
43add_qml_test(Dash DashPreview)
45add_qml_test(Dash GenericPreview)
44add_qml_test(Dash GenericPreview)
tests/qmltests/Components/tst_PageHeader.qml → tests/qmltests/Components/tst_PageHeaderLabel.qmlrenamed+2−2
@@ -31,7 +31,7 @@ Item {
31 }
31 }
32
32
33 UT.UnityTestCase {
33 UT.UnityTestCase {
34− name: "PageHeaderTest"
34+ name: "PageHeaderLabelTest"
35 when: windowShown
35 when: windowShown
36
36
37 property alias searchEnabled : pageHeader.searchEntryEnabled
37 property alias searchEnabled : pageHeader.searchEntryEnabled
@@ -204,7 +204,7 @@ Item {
204 anchors.fill: parent
204 anchors.fill: parent
205 spacing: units.gu(1)
205 spacing: units.gu(1)
206
206
207− PageHeader {
207+ PageHeaderLabel {
208 id: pageHeader
208 id: pageHeader
209 anchors {
209 anchors {
210 left: parent.left
210 left: parent.left
tests/qmltests/Dash/qml/FakeScopeView.qml+1
@@ -23,6 +23,7 @@ GenericScopeView {
23 id: fakeScopeView
23 id: fakeScopeView
24
24
25 property alias backColor : back.color
25 property alias backColor : back.color
26+ property var categoryView: null
26
27
27 onEndReached: {
28 onEndReached: {
28 if (scope != undefined && shell != undefined && shell.scopeStatus != undefined) {
29 if (scope != undefined && shell != undefined && shell.scopeStatus != undefined) {
tests/qmltests/Dash/tst_Dash.qml+6−8
@@ -25,8 +25,6 @@ Item {
25 width: units.gu(40)
25 width: units.gu(40)
26 height: units.gu(80)
26 height: units.gu(80)
27
27
28− property ListModel searchHistory : ListModel {}
29−
30 Dash {
28 Dash {
31 id: dash
29 id: dash
32 anchors.fill: parent
30 anchors.fill: parent
@@ -83,14 +81,14 @@ Item {
83 // wait for scopes to load
81 // wait for scopes to load
84 tryCompare(scopes, "loaded", true);
82 tryCompare(scopes, "loaded", true);
85
83
86− var dashbar = findChild(dash, "dashbar");
84+ var tabbar = findChild(dash, "tabbar");
87− verify(dashbar != undefined)
85+ verify(tabbar != undefined)
88 var dashContent = findChild(dash, "dashContent");
86 var dashContent = findChild(dash, "dashContent");
89 var current_index = dashContent.currentIndex;
87 var current_index = dashContent.currentIndex;
90
88
91 dash.setCurrentScope(data.tag, true /* animate */, false /* reset */);
89 dash.setCurrentScope(data.tag, true /* animate */, false /* reset */);
92 compare(dashContent.currentIndex, data.shouldBeVisible ? data.visualIndex : current_index);
90 compare(dashContent.currentIndex, data.shouldBeVisible ? data.visualIndex : current_index);
93− compare(dashbar.currentIndex, data.shouldBeVisible ? data.visualIndex : current_index);
91+ compare(tabbar.selectedIndex, data.shouldBeVisible ? data.visualIndex : current_index);
94 }
92 }
95
93
96 function test_show_scope_on_load_data() {
94 function test_show_scope_on_load_data() {
@@ -127,12 +125,12 @@ Item {
127 // wait for scopes to load
125 // wait for scopes to load
128 tryCompare(scopes, "loaded", true);
126 tryCompare(scopes, "loaded", true);
129
127
130− var dashbar = findChild(dash, "dashbar");
128+ var tabbar = findChild(dash, "tabbar");
131− verify(dashbar != undefined)
129+ verify(tabbar != undefined)
132 var dashContent = findChild(dash, "dashContent");
130 var dashContent = findChild(dash, "dashContent");
133 var current_index = dashContent.currentIndex;
131 var current_index = dashContent.currentIndex;
134
132
135− dashbar.itemSelected(data.visualIndex);
133+ tabbar.selectedIndex = data.visualIndex;
136 compare(dashContent.currentIndex, data.shouldBeVisible ? data.visualIndex : current_index);
134 compare(dashContent.currentIndex, data.shouldBeVisible ? data.visualIndex : current_index);
137 }
135 }
138 }
136 }
tests/qmltests/Dash/tst_DashBar.qmldeleted−111
@@ -1,111 +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 Unity 0.1
20−import ".."
21−import "../../../qml/Dash"
22−import Ubuntu.Components 0.1
23−import Unity.Test 0.1 as UT
24−
25−Item {
26− width: units.gu(40)
27− height: units.gu(71)
28−
29− DashBar {
30− id: dashBar
31−
32− anchors {
33− left: parent.left
34− right: parent.right
35− bottom: parent.bottom
36− }
37− model: scopes
38− onItemSelected: currentIndex = index
39− }
40−
41− Scopes {
42− id: scopes
43− }
44−
45− SignalSpy {
46− id: signalSpy
47− signalName: "itemSelected"
48− target: dashBar
49− }
50−
51− UT.UnityTestCase {
52− name: "DashBar"
53− when: scopes.loaded
54−
55− property alias model: dashBar.model
56− property alias currentIndex: dashBar.currentIndex
57−
58− readonly property alias lineHeight: dashBar.lineHeight
59− readonly property alias itemSize: dashBar.itemSize
60− readonly property alias iconSize: dashBar.iconSize
61− readonly property var panel: findChild(dashBar, "panel");
62−
63− function initTestCase() {
64− currentIndex = 2
65− }
66−
67− function waitForAnimationToEnd() {
68− compare(panel.animating, true) // check the animation started
69− tryCompare(panel, "animating", false) // wait till the animation ends
70− }
71−
72− function closePanel() {
73− dashBar.finishNavigation()
74− waitForAnimationToEnd()
75− tryCompare(panel, "opened", false)
76− }
77−
78− function openPanel() {
79− dashBar.startNavigation()
80− waitForAnimationToEnd()
81− tryCompare(panel, "opened", true)
82− }
83−
84− function test_navigationAndHide() {
85− openPanel()
86− closePanel()
87− }
88−
89− function test_itemSelected() {
90− openPanel()
91−
92− var row = findChild(dashBar, "row");
93− tryCompareFunction(function(){return row.width > 0;}, true);
94− for (var i = 0; i < model.rowCount(); i++) {
95− // coordinate x in the middle of item with index 'i'
96− var x = row.x + (row.width / model.rowCount()) * i + itemSize / 2
97−
98− // FIXME workaround for a bug in SignalSpy
99− signalSpy.clear()
100−
101− // (item, x, y, button, modifiers, delay)
102− mouseClick(panel, x, row.height / 2, Qt.LeftButton, Qt.NoModifier, 0)
103− compare(signalSpy.count > 0, true, "signal itemSelected not triggered")
104− compare(signalSpy.signalArguments[0][0], i, "signal itemSelected emitted unexpected index");
105− tryCompare(dashBar, "currentIndex", i);
106− }
107−
108− closePanel()
109− }
110− }
111−}
tests/qmltests/Dash/tst_DashContent.qml+67−4
@@ -17,9 +17,11 @@
17import QtQuick 2.0
17import QtQuick 2.0
18import QtTest 1.0
18import QtTest 1.0
19import "../../../qml/Dash"
19import "../../../qml/Dash"
20+import "../../../qml/Components"
20import Ubuntu.Components 0.1
21import Ubuntu.Components 0.1
21import Unity 0.1
22import Unity 0.1
22import Unity.Test 0.1 as UT
23import Unity.Test 0.1 as UT
24+import Utils 0.1
23
25
24Item {
26Item {
25 id: shell
27 id: shell
@@ -54,11 +56,13 @@ Item {
54 id: dashContent
56 id: dashContent
55 anchors.fill: parent
57 anchors.fill: parent
56
58
59+ model: SortFilterProxyModel {
57− model: scopesModel
60+ model: scopesModel
61+ }
58 scopes : scopesModel
62 scopes : scopesModel
59
63
60 scopeMapper : scopeDelegateMapper
64 scopeMapper : scopeDelegateMapper
61− searchHistory: ListModel {}
65+ searchHistory: SearchHistoryModel {}
62 }
66 }
63
67
64 ScopeDelegateMapper {
68 ScopeDelegateMapper {
@@ -109,9 +113,10 @@ Item {
109
113
110 UT.UnityTestCase {
114 UT.UnityTestCase {
111 name: "DashContent"
115 name: "DashContent"
112− when: windowShown
116+ when: scopesModel.loaded
113
117
114 function init() {
118 function init() {
119+ scopesModel.clear();
115 scopesModel.load();
120 scopesModel.load();
116 }
121 }
117
122
@@ -268,6 +273,65 @@ Item {
268 tryCompare(scopesModel.get(2), "isActive", data.active2);
273 tryCompare(scopesModel.get(2), "isActive", data.active2);
269 }
274 }
270
275
276+ function doFindMusicButton(parent) {
277+ for (var i = 0; i < parent.children.length; i++) {
278+ var c = parent.children[i];
279+ if (UT.Util.isInstanceOf(c, "AbstractButton") && parent.x >= 0) {
280+ for (var ii = 0; ii < c.children.length; ii++) {
281+ var cc = c.children[ii];
282+ if (UT.Util.isInstanceOf(cc, "Label") && cc.text == "Music") {
283+ return c;
284+ }
285+ }
286+ }
287+ var r = doFindMusicButton(c);
288+ if (r !== undefined) {
289+ return r;
290+ }
291+ }
292+ return undefined;
293+ }
294+
295+ function findMusicButton() {
296+ // We need to find a AbstractButton that has a Label child
297+ // with text Music and it's parent x is >= 0
298+ var tabbar = findChild(dashContent, "tabbar");
299+ return doFindMusicButton(tabbar);
300+ }
301+
302+ function test_tabBar_index_change() {
303+ tryCompare(scopesModel, "loaded", true);
304+ var tabbar = findChild(dashContent, "tabbar");
305+
306+ compare(dashContent.currentIndex, 0);
307+ tryCompare(tabbar, "selectedIndex", 0);
308+ tryCompare(tabbar, "selectionMode", false);
309+
310+ mouseClick(tabbar, units.gu(5), units.gu(5))
311+
312+ tryCompare(tabbar, "selectionMode", true);
313+ tryCompare(tabbar, "selectedIndex", 0);
314+ tryCompare(dashContent, "currentIndex", 0);
315+
316+ var button;
317+ tryCompareFunction(function() { button = findMusicButton(); return button != undefined; }, true);
318+ waitForRendering(button);
319+
320+ mouseClick(button, button.width / 2, button.height / 2)
321+
322+ tryCompare(tabbar, "selectionMode", false);
323+ tryCompare(tabbar, "selectedIndex", 1);
324+ tryCompare(dashContent, "currentIndex", 1);
325+ }
326+
327+ function test_tabBar_listens_to_index_change() {
328+ var tabbar = findChild(dashContent, "tabbar");
329+ tryCompare(dashContent, "currentIndex", 0);
330+ compare(tabbar.selectedIndex, 0);
331+ dashContent.currentIndex = 1;
332+ compare(tabbar.selectedIndex, 1);
333+ }
334+
271 function checkFlickMovingAndNotInteractive()
335 function checkFlickMovingAndNotInteractive()
272 {
336 {
273 var dashContentList = findChild(dashContent, "dashContentList");
337 var dashContentList = findChild(dashContent, "dashContentList");
@@ -282,7 +346,6 @@ Item {
282 return dashContentList.currentItem.moving && !dashContentList.interactive;
346 return dashContentList.currentItem.moving && !dashContentList.interactive;
283 }
347 }
284
348
285−
286 function test_hswipe_disabled_vswipe() {
349 function test_hswipe_disabled_vswipe() {
287 var dashContentList = findChild(dashContent, "dashContentList");
350 var dashContentList = findChild(dashContent, "dashContentList");
288
351
tests/qmltests/Dash/tst_GenericScopeView.qml+49−28
@@ -41,54 +41,83 @@ Item {
41 signal mainStageFocusedApplicationChanged()
41 signal mainStageFocusedApplicationChanged()
42 }
42 }
43
43
44+ PreviewListView {
45+ id: previewListView
46+ anchors.fill: parent
47+ openEffect: openEffect
48+ categoryView: genericScopeView.categoryView
49+ scope: genericScopeView.scope
50+ }
51+
52+ DashContentOpenEffect {
53+ id: openEffect
54+ previewListView: previewListView
55+ }
56+
57+ PageHeaderLabel {
58+ id: pageHeader
59+ searchHistory: SearchHistoryModel {}
60+ }
61+
44 GenericScopeView {
62 GenericScopeView {
45 id: genericScopeView
63 id: genericScopeView
46 anchors.fill: parent
64 anchors.fill: parent
47− searchHistory: SearchHistoryModel {}
65+ previewListView: previewListView
66+ openEffect: openEffect
67+ pageHeader: pageHeader
68+ tabBarHeight: pageHeader.implicitHeight
48
69
49 UT.UnityTestCase {
70 UT.UnityTestCase {
50 name: "GenericScopeView"
71 name: "GenericScopeView"
51 when: scopes.loaded
72 when: scopes.loaded
52
73
53− function test_isCurrent() {
74+ function test_isCurrent() {
54− var pageHeader = findChild(genericScopeView, "pageHeader");
55− var previewListView = findChild(genericScopeView, "previewListView");
56 genericScopeView.isCurrent = true
75 genericScopeView.isCurrent = true
57 pageHeader.searchQuery = "test"
76 pageHeader.searchQuery = "test"
58 previewListView.open = true
77 previewListView.open = true
59 genericScopeView.isCurrent = false
78 genericScopeView.isCurrent = false
60 tryCompare(pageHeader, "searchQuery", "")
79 tryCompare(pageHeader, "searchQuery", "")
61− tryCompare(genericScopeView, "previewShown", false);
80+ tryCompare(previewListView, "open", false);
62 }
81 }
63
82
64 function test_showDash() {
83 function test_showDash() {
65− var previewListView = findChild(genericScopeView, "previewListView");
66 previewListView.open = true;
84 previewListView.open = true;
85+ tryCompare(openEffect, "live", true);
67 scopes.get(0).showDash();
86 scopes.get(0).showDash();
68− tryCompare(genericScopeView, "previewShown", false);
87+ tryCompare(previewListView, "open", false);
88+ tryCompare(openEffect, "live", true);
69 }
89 }
70
90
71 function test_hideDash() {
91 function test_hideDash() {
72− var previewListView = findChild(genericScopeView, "previewListView");
73 previewListView.open = true;
92 previewListView.open = true;
74 scopes.get(0).hideDash();
93 scopes.get(0).hideDash();
75− tryCompare(genericScopeView, "previewShown", false);
94+ tryCompare(previewListView, "open", false);
76 }
95 }
77
96
78 function openPreview() {
97 function openPreview() {
79 var categoryListView = findChild(genericScopeView, "categoryListView");
98 var categoryListView = findChild(genericScopeView, "categoryListView");
80 categoryListView.positionAtBeginning();
99 categoryListView.positionAtBeginning();
81
100
101+ tryCompareFunction(function() {
102+ var tile = findChild(findChild(genericScopeView, "0"), "delegate0");
103+ return tile != undefined;
104+ },
105+ true);
82 var tile = findChild(findChild(genericScopeView, "0"), "delegate0");
106 var tile = findChild(findChild(genericScopeView, "0"), "delegate0");
83 mouseClick(tile, tile.width / 2, tile.height / 2);
107 mouseClick(tile, tile.width / 2, tile.height / 2);
84− var openEffect = findChild(genericScopeView, "openEffect");
108+ tryCompare(previewListView, "open", true);
85 tryCompare(openEffect, "gap", 1);
109 tryCompare(openEffect, "gap", 1);
86 }
110 }
87
111
88 function checkArrowPosition(index) {
112 function checkArrowPosition(index) {
113+ tryCompareFunction(function() {
114+ var tile = findChild(findChild(genericScopeView, "0"), "delegate" + index);
115+ return tile != undefined;
116+ },
117+ true);
89 var tile = findChild(findChild(genericScopeView, "0"), "delegate" + index);
118 var tile = findChild(findChild(genericScopeView, "0"), "delegate" + index);
90 var tileCenter = tile.x + tile.width/2;
119 var tileCenter = tile.x + tile.width/2;
91− var pointerArrow = findChild(genericScopeView, "pointerArrow");
120+ var pointerArrow = findChild(previewListView, "pointerArrow");
92 var pointerArrowCenter = pointerArrow.x + pointerArrow.width/2;
121 var pointerArrowCenter = pointerArrow.x + pointerArrow.width/2;
93 compare(pointerArrowCenter, tileCenter, "Pointer did not move to tile");
122 compare(pointerArrowCenter, tileCenter, "Pointer did not move to tile");
94 }
123 }
@@ -97,9 +126,7 @@ Item {
97 var closePreviewMouseArea = findChild(genericScopeView, "closePreviewMouseArea");
126 var closePreviewMouseArea = findChild(genericScopeView, "closePreviewMouseArea");
98 mouseClick(closePreviewMouseArea, closePreviewMouseArea.width / 2, closePreviewMouseArea.height / 2);
127 mouseClick(closePreviewMouseArea, closePreviewMouseArea.width / 2, closePreviewMouseArea.height / 2);
99
128
100− var previewListView = findChild(genericScopeView, "previewListView");
101 tryCompare(previewListView, "open", false);
129 tryCompare(previewListView, "open", false);
102− var openEffect = findChild(genericScopeView, "openEffect");
103 tryCompare(openEffect, "gap", 0);
130 tryCompare(openEffect, "gap", 0);
104
131
105 var categoryListView = findChild(genericScopeView, "categoryListView");
132 var categoryListView = findChild(genericScopeView, "categoryListView");
@@ -108,13 +135,12 @@ Item {
108 }
135 }
109
136
110 function test_previewOpenClose() {
137 function test_previewOpenClose() {
111− var previewListView = findChild(genericScopeView, "previewListView");
112 tryCompare(previewListView, "open", false);
138 tryCompare(previewListView, "open", false);
113
139
114 openPreview();
140 openPreview();
115
141
116 // check for it opening successfully
142 // check for it opening successfully
117− var currentPreviewItem = findChild(genericScopeView, "previewLoader0");
143+ var currentPreviewItem = findChild(previewListView, "previewLoader0");
118 tryCompareFunction(function() {
144 tryCompareFunction(function() {
119 var parts = currentPreviewItem.source.toString().split("/");
145 var parts = currentPreviewItem.source.toString().split("/");
120 var name = parts[parts.length - 1];
146 var name = parts[parts.length - 1];
@@ -138,26 +164,23 @@ Item {
138 var categoryListView = findChild(genericScopeView, "categoryListView");
164 var categoryListView = findChild(genericScopeView, "categoryListView");
139 categoryListView.positionAtBeginning();
165 categoryListView.positionAtBeginning();
140 waitForRendering(categoryListView);
166 waitForRendering(categoryListView);
141− categoryListView.flick(0, -units.gu(80));
167+ categoryListView.flick(0, -units.gu(60));
142 tryCompare(categoryListView.flicking, false);
168 tryCompare(categoryListView.flicking, false);
143
169
144 var tile = findChild(findChild(genericScopeView, "0"), "delegate0");
170 var tile = findChild(findChild(genericScopeView, "0"), "delegate0");
145 mouseClick(tile, tile.width / 2, tile.height - 1);
171 mouseClick(tile, tile.width / 2, tile.height - 1);
146− var openEffect = findChild(genericScopeView, "openEffect");
147 tryCompare(openEffect, "gap", 1);
172 tryCompare(openEffect, "gap", 1);
148
173
149− var pageHeader = findChild(genericScopeView, "pageHeader");
150 verify(openEffect.positionPx >= pageHeader.height + categoryListView.stickyHeaderHeight);
174 verify(openEffect.positionPx >= pageHeader.height + categoryListView.stickyHeaderHeight);
151 }
175 }
152
176
153 function test_previewCycle() {
177 function test_previewCycle() {
154− var previewListView = findChild(genericScopeView, "previewListView");
155 tryCompare(previewListView, "open", false);
178 tryCompare(previewListView, "open", false);
156
179
157 openPreview();
180 openPreview();
158
181
159 // wait for it to be loaded
182 // wait for it to be loaded
160− var currentPreviewItem = findChild(genericScopeView, "previewLoader0");
183+ var currentPreviewItem = findChild(previewListView, "previewLoader0");
161 tryCompareFunction(function() {
184 tryCompareFunction(function() {
162 var parts = currentPreviewItem.source.toString().split("/");
185 var parts = currentPreviewItem.source.toString().split("/");
163 var name = parts[parts.length - 1];
186 var name = parts[parts.length - 1];
@@ -179,7 +202,7 @@ Item {
179 previewListView.height / 2);
202 previewListView.height / 2);
180
203
181 // wait for it to be loaded
204 // wait for it to be loaded
182− var nextPreviewItem = findChild(genericScopeView, "previewLoader" + i);
205+ var nextPreviewItem = findChild(previewListView, "previewLoader" + i);
183 tryCompareFunction(function() {
206 tryCompareFunction(function() {
184 var parts = nextPreviewItem.source.toString().split("/");
207 var parts = nextPreviewItem.source.toString().split("/");
185 var name = parts[parts.length - 1];
208 var name = parts[parts.length - 1];
@@ -206,11 +229,12 @@ Item {
206
229
207 function test_show_spinner() {
230 function test_show_spinner() {
208 openPreview();
231 openPreview();
209− var previewListView = findChild(genericScopeView, "previewListView");
232+ var previewLoader = findChild(previewListView, "previewLoader0");
210− var previewLoader = findChild(genericScopeView, "previewLoader0");
233+ tryCompare(previewLoader, "progress", 1.0);
234+ tryCompareFunction(function() { return previewLoader.item != undefined; }, true);
211
235
212 previewLoader.item.showProcessingAction = true;
236 previewLoader.item.showProcessingAction = true;
213− var waitingForAction = findChild(genericScopeView, "waitingForActionMouseArea");
237+ var waitingForAction = findChild(previewListView, "waitingForActionMouseArea");
214 tryCompare(waitingForAction, "enabled", true);
238 tryCompare(waitingForAction, "enabled", true);
215 previewLoader.closePreviewSpinner();
239 previewLoader.closePreviewSpinner();
216 tryCompare(waitingForAction, "enabled", false);
240 tryCompare(waitingForAction, "enabled", false);
@@ -252,12 +276,10 @@ Item {
252 tryCompareFunction(function() { return findChild(genericScopeView, "carouselDelegate") != undefined; }, true);
276 tryCompareFunction(function() { return findChild(genericScopeView, "carouselDelegate") != undefined; }, true);
253 var tile = findChild(genericScopeView, "carouselDelegate");
277 var tile = findChild(genericScopeView, "carouselDelegate");
254 mouseClick(tile, tile.width / 2, tile.height / 2);
278 mouseClick(tile, tile.width / 2, tile.height / 2);
255− var openEffect = findChild(genericScopeView, "openEffect");
256 tryCompare(openEffect, "gap", 1);
279 tryCompare(openEffect, "gap", 1);
257
280
258 // check for it opening successfully
281 // check for it opening successfully
259− var previewListView = findChild(genericScopeView, "previewListView");
260− var currentPreviewItem = findChild(genericScopeView, "previewLoader0");
282+ var currentPreviewItem = findChild(previewListView, "previewLoader0");
261 tryCompareFunction(function() {
283 tryCompareFunction(function() {
262 var parts = currentPreviewItem.source.toString().split("/");
284 var parts = currentPreviewItem.source.toString().split("/");
263 var name = parts[parts.length - 1];
285 var name = parts[parts.length - 1];
@@ -303,7 +325,6 @@ Item {
303 tryCompareFunction(
325 tryCompareFunction(
304 function() {
326 function() {
305 var header0 = findChild(genericScopeView, "dashSectionHeader0")
327 var header0 = findChild(genericScopeView, "dashSectionHeader0")
306− var pageHeader = findChild(genericScopeView, "pageHeader");
307 return header0.y == pageHeader.height;
328 return header0.y == pageHeader.height;
308 },
329 },
309 true);
330 true);