Unity 8
 All Classes Functions Properties
DashDepartments.qml
1 /*
2  * Copyright (C) 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.2
18 import Ubuntu.Components 0.1
19 
20 AbstractButton {
21  id: root
22  objectName: "dashDepartments"
23 
24  property var scope: null
25 
26  property bool showList: false
27 
28  readonly property var currentDepartment: scope && scope.hasDepartments ? scope.getDepartment(scope.currentDepartmentId) : null
29 
30  property alias windowWidth: blackRect.width
31  property alias windowHeight: blackRect.height
32 
33  // Are we drilling down the tree or up?
34  property bool isGoingBack: false
35 
36  visible: root.currentDepartment != null
37 
38  height: visible ? units.gu(5) : 0
39 
40  onClicked: {
41  root.showList = !root.showList;
42  }
43 
44  Rectangle {
45  id: blackRect
46  color: "black"
47  opacity: departmentListView.currentItem && departmentListView.currentItem.visible ? 0.3 : 0
48  Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
49  anchors.top: departmentListView.top
50  anchors.right: parent.right
51  visible: opacity != 0
52  }
53 
54  Image {
55  anchors {
56  top: parent.top
57  left: parent.left
58  right: parent.right
59  }
60  fillMode: Image.Stretch
61  source: "graphics/dash_divider_top_lightgrad.png"
62  z: -1
63  }
64 
65  Image {
66  anchors {
67  bottom: parent.bottom
68  left: parent.left
69  right: parent.right
70  }
71  fillMode: Image.Stretch
72  source: "graphics/dash_divider_top_darkgrad.png"
73  z: -1
74  }
75 
76  Label {
77  anchors.fill: parent
78  anchors.margins: units.gu(2)
79  verticalAlignment: Text.AlignVCenter
80  text: root.currentDepartment ? root.currentDepartment.label : ""
81  color: "gray" // TODO remove once we're a separate app
82  }
83 
84  Image {
85  anchors.verticalCenter: parent.verticalCenter
86  anchors.right: parent.right
87  anchors.rightMargin: units.gu(2)
88  rotation: showList ? 180 : 0
89  source: "image://theme/dropdown-menu"
90  sourceSize.height: parent.height - units.gu(2)
91  sourceSize.width: units.gu(2)
92  fillMode: Image.PreserveAspectFit
93  }
94 
95  // departmentListView is outside root
96  ListView {
97  id: departmentListView
98  objectName: "departmentListView"
99  orientation: ListView.Horizontal
100  interactive: false
101  clip: root.width != windowWidth
102  model: ListModel {
103  id: departmentModel
104  // We have two roles
105  // departmentId: the department id of the department the list represents
106  // nullifyDepartment: overrides departmentId to be null
107  // This is used to "clear" the delegate when going "right" on the tree
108  }
109  anchors {
110  left: parent.left
111  right: parent.right
112  top: root.bottom
113  }
114  readonly property int maxHeight: (windowHeight - mapToItem(null, root.x, root.y).y) - units.gu(8)
115  property int prevHeight: maxHeight
116  height: currentItem ? currentItem.height : maxHeight
117  onHeightChanged: {
118  if (root.showList) {
119  prevHeight = currentItem.desiredHeight;
120  }
121  }
122  highlightMoveDuration: UbuntuAnimation.FastDuration
123  delegate: DashDepartmentsList {
124  objectName: "department" + index
125  visible: height != 0
126  width: departmentListView.width
127  property real desiredHeight: {
128  if (root.showList) {
129  if (department && department.loaded && x == departmentListView.contentX)
130  {
131  return Math.min(implicitHeight, departmentListView.maxHeight);
132  } else {
133  return departmentListView.prevHeight;
134  }
135  } else {
136  return 0;
137  }
138  }
139  height: desiredHeight
140  department: (nullifyDepartment || !scope) ? null : scope.getDepartment(departmentId)
141  currentDepartment: root.currentDepartment
142  onEnterDepartment: {
143  scope.loadDepartment(newDepartmentId);
144  // We only need to add a new item to the model
145  // if we have children, otherwise just load it
146  if (hasChildren) {
147  isGoingBack = false;
148  departmentModel.append({"departmentId": newDepartmentId, "nullifyDepartment": false});
149  departmentListView.currentIndex++;
150  } else {
151  showList = false;
152  }
153  }
154  onGoBackToParentClicked: {
155  scope.loadDepartment(department.parentDepartmentId);
156  isGoingBack = true;
157  departmentModel.setProperty(departmentListView.currentIndex - 1, "nullifyDepartment", false);
158  departmentListView.currentIndex--;
159  }
160  onAllDepartmentClicked: {
161  showList = false;
162  if (root.currentDepartment.parentDepartmentId == department.departmentId) {
163  // For leaves we have to go to the parent too
164  scope.loadDepartment(root.currentDepartment.parentDepartmentId);
165  }
166  }
167  }
168  onContentXChanged: {
169  if (contentX == width * departmentListView.currentIndex) {
170  if (isGoingBack) {
171  departmentModel.remove(departmentListView.currentIndex + 1);
172  } else {
173  departmentModel.setProperty(departmentListView.currentIndex - 1, "nullifyDepartment", true);
174  }
175  }
176  }
177  }
178 
179  InverseMouseArea {
180  anchors.fill: departmentListView
181  enabled: root.showList
182  onClicked: root.showList = false
183  }
184 
185  onScopeChanged: {
186  departmentModel.clear();
187  if (scope && scope.hasDepartments) {
188  departmentModel.append({"departmentId": scope.currentDepartmentId, "nullifyDepartment": false});
189  }
190  }
191 
192  Connections {
193  target: scope
194  onHasDepartmentsChanged: {
195  if (scope.hasDepartments) {
196  departmentModel.append({"departmentId": scope.currentDepartmentId, "nullifyDepartment": false});
197  } else {
198  departmentModel.clear();
199  }
200  }
201  }
202 }