2 * Copyright (C) 2013, 2014 Canonical, Ltd.
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.
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.
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/>.
18 import Ubuntu.Components 0.1
21 import "../Components"
26 property bool forceNonInteractive: false
27 property alias scopes: dashContentList.model
28 property alias currentIndex: dashContentList.currentIndex
29 property int workaroundRestoreIndex: -1
30 readonly property string currentScopeId: dashContentList.currentItem ? dashContentList.currentItem.scopeId : ""
31 readonly property var currentScope: dashContentList.currentItem ? dashContentList.currentItem.theScope : null
32 readonly property bool subPageShown: dashContentList.currentItem && dashContentList.currentItem.item ?
33 dashContentList.currentItem.item.subPageShown : false
34 readonly property bool processing: dashContentList.currentItem && dashContentList.currentItem.item
35 && dashContentList.currentItem.item.processing || false
36 readonly property bool pageHeaderTotallyVisible: dashContentList.currentItem && dashContentList.currentItem.item
37 && dashContentList.currentItem.item.pageHeaderTotallyVisible || false
39 signal scopeLoaded(string scopeId)
40 signal gotoScope(string scopeId)
41 signal openScope(var scope)
44 // If we set the current scope index before the scopes have been added,
45 // then we need to wait until the loaded signals gets emitted from the scopes
46 property var set_current_index: undefined
50 if (scopes.loaded && set_current_index != undefined) {
51 setCurrentScopeAtIndex(set_current_index[0], set_current_index[1], set_current_index[2]);
52 set_current_index = undefined;
56 // FIXME This is to workaround a Qt bug with the model moving the current item
57 // when the list is ListView.SnapOneItem and ListView.StrictlyEnforceRange
58 // together with the code in Dash.qml
59 if (row == dashContentList.currentIndex || start == dashContentList.currentIndex) {
60 dashContent.workaroundRestoreIndex = dashContentList.currentIndex;
61 dashContentList.currentIndex = -1;
68 onOpened: dashContentList.currentItem.theScope.performQuery(uris[0])
71 function setCurrentScopeAtIndex(index, animate, reset) {
72 // if the scopes haven't loaded yet, then wait until they are.
74 set_current_index = [ index, animate, reset ]
78 var storedMoveDuration = dashContentList.highlightMoveDuration
79 var storedMoveSpeed = dashContentList.highlightMoveVelocity
81 dashContentList.highlightMoveVelocity = units.gu(4167)
82 dashContentList.highlightMoveDuration = 0
85 set_current_index = undefined;
87 if (dashContentList.count > index) {
88 dashContentList.currentIndex = index
91 dashContentList.currentItem.item.positionAtBeginning()
96 dashContentList.highlightMoveDuration = storedMoveDuration
97 dashContentList.highlightMoveVelocity = storedMoveSpeed
102 id: dashContentListHolder
112 objectName: "dashContentList"
114 interactive: !dashContent.forceNonInteractive && dashContent.scopes.loaded && currentItem
115 && !currentItem.moving && !currentItem.navigationDisableParentInteractive && !currentItem.subPageShown
117 orientation: ListView.Horizontal
118 boundsBehavior: Flickable.DragAndOvershootBounds
119 flickDeceleration: units.gu(625)
120 maximumFlickVelocity: width * 5
121 snapMode: ListView.SnapOneItem
122 highlightMoveDuration: 250
123 highlightRangeMode: ListView.StrictlyEnforceRange
124 // TODO Investigate if we can switch to a smaller cache buffer when/if UbuntuShape gets more performant
125 // 1073741823 is s^30 -1. A quite big number so that you have "infinite" cache, but not so
126 // big so that if you add if with itself you're outside the 2^31 int range
127 cacheBuffer: 1073741823
128 onMovementStarted: currentItem.item.showHeader();
131 // TODO QTBUG-40846 and QTBUG-40848
132 // The remove transition doesn't happen when removing the last item
133 // And can't work around it because index is reset to -1 regardless of
134 // ListView.delayRemove
137 SequentialAnimation {
138 PropertyAction { property: "layer.enabled"; value: true }
139 PropertyAction { property: "ListView.delayRemove"; value: true }
141 PropertyAnimation { properties: "scale"; to: 0.25; duration: UbuntuAnimation.SnapDuration }
142 PropertyAnimation { properties: "y"; to: dashContent.height; duration: UbuntuAnimation.SnapDuration }
144 PropertyAction { property: "ListView.delayRemove"; value: false }
147 removeDisplaced: Transition {
148 PropertyAnimation { property: "x"; duration: UbuntuAnimation.SnapDecision }
151 // If the number of items is less than the current index, then need to reset to another item.
154 if (currentIndex >= count) {
155 dashContent.setCurrentScopeAtIndex(count-1, true, true)
156 } else if (currentIndex < 0) {
157 // setting currentIndex directly, cause we don't want to loose set_current_index
158 dashContentList.currentIndex = 0
166 width: ListView.view.width
167 height: ListView.view.height
168 opacity: { // hide delegate if offscreen
169 var xPositionRelativetoView = ListView.view.contentX - x
170 return (xPositionRelativetoView > -width && xPositionRelativetoView < width) ? 1 : 0
173 source: "GenericScopeView.qml"
174 objectName: "scopeLoader" + index
176 readonly property bool moving: item ? item.moving : false
177 readonly property bool navigationDisableParentInteractive: item ? item.navigationDisableParentInteractive : false
178 readonly property bool subPageShown: item ? item.subPageShown : false
179 readonly property var categoryView: item ? item.categoryView : null
180 readonly property var theScope: scope
182 // these are needed for autopilot tests
183 readonly property string scopeId: scope.id
184 readonly property bool isCurrent: ListView.isCurrentItem
185 readonly property bool isLoaded: status == Loader.Ready
188 item.objectName = scope.id
189 item.scope = Qt.binding(function() { return scope })
190 item.isCurrent = Qt.binding(function() { return visible && ListView.isCurrentItem })
191 dashContent.scopeLoaded(item.scope.id)
192 item.paginationCount = Qt.binding(function() { return dashContentList.count } )
193 item.paginationIndex = Qt.binding(function() { return dashContentList.currentIndex } )
194 item.visibleToParent = Qt.binding(function() { return loader.opacity != 0 });
195 item.holdingList = dashContentList;
196 item.forceNonInteractive = Qt.binding(function() { return dashContent.forceNonInteractive } )
199 target: isCurrent ? scope : null
201 // Note here scopeId is the signal parameter and not the loader property
202 dashContent.gotoScope(scopeId);
205 dashContent.openScope(scope);
210 onClosePreview: if (item) item.closePreview()
213 Component.onDestruction: active = false