Unity 8
 All Classes Functions Properties
DashContent.qml
1 /*
2  * Copyright (C) 2013, 2014 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.2
20 import "../Components"
21 
22 Item {
23  id: dashContent
24 
25  property var model: null
26  property var scopes: null
27  readonly property alias currentIndex: dashContentList.currentIndex
28  property alias previewOpen: previewListView.open
29 
30  property ListModel searchHistory
31 
32  signal scopeLoaded(string scopeId)
33  signal gotoScope(string scopeId)
34  signal openScope(var scope)
35 
36  // If we set the current scope index before the scopes have been added,
37  // then we need to wait until the loaded signals gets emitted from the scopes
38  property var set_current_index: undefined
39  Connections {
40  target: scopes
41  onLoadedChanged: {
42  if (scopes.loaded && set_current_index != undefined) {
43  setCurrentScopeAtIndex(set_current_index[0], set_current_index[1], set_current_index[2]);
44  set_current_index = undefined;
45  }
46  }
47  }
48 
49  function setCurrentScopeAtIndex(index, animate, reset) {
50  // if the scopes haven't loaded yet, then wait until they are.
51  if (!scopes.loaded) {
52  set_current_index = [ index, animate, reset ]
53  return;
54  }
55 
56  var storedMoveDuration = dashContentList.highlightMoveDuration
57  var storedMoveSpeed = dashContentList.highlightMoveVelocity
58  if (!animate) {
59  dashContentList.highlightMoveVelocity = units.gu(4167)
60  dashContentList.highlightMoveDuration = 0
61  }
62 
63  set_current_index = undefined;
64 
65  if (dashContentList.count > index)
66  {
67  dashContentList.currentIndex = index
68 
69  if (reset) {
70  dashContentList.currentItem.item.positionAtBeginning()
71  }
72  }
73 
74  if (!animate) {
75  dashContentList.highlightMoveDuration = storedMoveDuration
76  dashContentList.highlightMoveVelocity = storedMoveSpeed
77  }
78  }
79 
80  function closeScope(scope) {
81  dashContentList.currentItem.theScope.closeScope(scope)
82  }
83 
84  function closePreview() {
85  previewListView.open = false;
86  }
87 
88  Item {
89  id: dashContentListHolder
90 
91  x: previewListView.open ? -width : 0
92  Behavior on x { UbuntuNumberAnimation { } }
93  width: parent.width
94  height: parent.height
95 
96  ListView {
97  id: dashContentList
98  objectName: "dashContentList"
99 
100  interactive: dashContent.scopes.loaded && !previewListView.open && currentItem && !currentItem.moving
101 
102  anchors.fill: parent
103  model: dashContent.model
104  orientation: ListView.Horizontal
105  boundsBehavior: Flickable.DragAndOvershootBounds
106  flickDeceleration: units.gu(625)
107  maximumFlickVelocity: width * 5
108  snapMode: ListView.SnapOneItem
109  highlightMoveDuration: 250
110  highlightRangeMode: ListView.StrictlyEnforceRange
111  // TODO Investigate if we can switch to a smaller cache buffer when/if UbuntuShape gets more performant
112  cacheBuffer: 1073741823
113  onMovementStarted: currentItem.item.showHeader();
114  clip: parent.x != 0
115 
116  // If the number of items is less than the current index, then need to reset to another item.
117  onCountChanged: {
118  if (count > 0) {
119  if (currentIndex >= count) {
120  dashContent.setCurrentScopeAtIndex(count-1, true, true)
121  } else if (currentIndex < 0) {
122  // setting currentIndex directly, cause we don't want to loose set_current_index
123  dashContentList.currentIndex = 0
124  }
125  }
126  }
127 
128  delegate:
129  Loader {
130  width: ListView.view.width
131  height: ListView.view.height
132  asynchronous: true
133  // TODO This if will eventually go away since we're killing DashApps.qml
134  // once we move app closing to the spread
135  source: (scope.id == "clickscope") ? "DashApps.qml" : "GenericScopeView.qml"
136  objectName: scope.id + " loader"
137 
138  readonly property bool moving: item ? item.moving : false
139  readonly property var categoryView: item ? item.categoryView : null
140  readonly property Scope theScope: scope
141 
142  // these are needed for autopilot tests
143  readonly property string scopeId: scope.id
144  readonly property bool isCurrent: ListView.isCurrentItem
145  readonly property bool isLoaded: status == Loader.Ready
146 
147  onLoaded: {
148  item.objectName = scope.id
149  item.pageHeader = dashPageHeader;
150  item.previewListView = previewListView;
151  item.scope = Qt.binding(function() { return scope })
152  item.isCurrent = Qt.binding(function() { return visible && ListView.isCurrentItem })
153  item.tabBarHeight = dashPageHeader.implicitHeight;
154  dashContent.scopeLoaded(item.scope.id)
155  }
156  Connections {
157  target: isCurrent ? scope : null
158  onGotoScope: {
159  // Note here scopeId is the signal parameter and not the loader property
160  dashContent.gotoScope(scopeId);
161  }
162  onOpenScope: {
163  dashContent.openScope(scope);
164  }
165  }
166 
167  Component.onDestruction: active = false
168  }
169  }
170 
171  PageHeader {
172  id: dashPageHeader
173  objectName: "pageHeader"
174  width: parent.width
175  searchEntryEnabled: true
176  searchHistory: dashContent.searchHistory
177  scope: dashContentList.currentItem && dashContentList.currentItem.theScope
178 
179  childItem: TabBar {
180  id: tabBar
181  objectName: "tabbar"
182  height: units.gu(6.5)
183  width: parent.width
184  style: DashContentTabBarStyle {}
185 
186  model: dashContentList.model
187 
188  onSelectedIndexChanged: {
189  if (dashContentList.currentIndex == -1 && tabBar.selectedIndex != -1) {
190  // TODO This together with the Timer below
191  // are a workaround for the first tab sometimes not showing the text.
192  // But Tabs are going away in the future so not sure if makes
193  // sense invetigating what's the problem at this stage
194  selectionModeTimer.restart();
195  }
196  dashContentList.currentIndex = selectedIndex;
197  }
198 
199  Connections {
200  target: dashContentList
201  onCurrentIndexChanged: {
202  tabBar.selectedIndex = dashContentList.currentIndex
203  }
204  }
205 
206  Timer {
207  id: selectionModeTimer
208  interval: 1
209  onTriggered: tabBar.selectionMode = false
210  }
211  }
212  }
213  }
214 
215  PreviewListView {
216  id: previewListView
217  objectName: "dashContentPreviewList"
218  visible: x != width
219  scope: dashContentList.currentItem ? dashContentList.currentItem.theScope : null
220  pageHeader: dashPageHeader
221  width: parent.width
222  height: parent.height
223  anchors.left: dashContentListHolder.right
224  }
225 }