Unity 8
ScopesListCategory.qml
1 /*
2  * Copyright (C) 2014,2015 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.4
18 import Ubuntu.Components 1.3
19 import Dash 0.1
20 import "../Components/ListItems" as ListItems
21 
22 Item {
23  id: root
24 
25  property alias model: list.model
26  property alias title: header.text
27  property var scopeStyle
28  property bool editMode: false
29  property bool isFavoritesFeed: false
30  property bool isAlsoInstalled: false
31 
32  visible: !editMode || isFavoritesFeed
33 
34  signal requestFavorite(string scopeId, bool favorite)
35  signal requestEditMode()
36  signal requestScopeMoveTo(string scopeId, int index)
37  signal requestActivate(var result)
38  signal requestRestore(string scopeId)
39 
40  implicitHeight: visible ? childrenRect.height : 0
41 
42  ListItems.Header {
43  id: header
44  width: root.width
45  height: units.gu(5)
46  color: scopeStyle ? scopeStyle.foreground : theme.palette.normal.baseText
47  }
48 
49  readonly property double listItemHeight: units.gu(6)
50 
51  ListView {
52  id: list
53  objectName: "scopesListCategoryInnerList"
54 
55  readonly property double targetHeight: model.count * listItemHeight
56  clip: height != targetHeight
57  height: targetHeight
58  Behavior on height { enabled: visible; UbuntuNumberAnimation { } }
59  width: parent.width
60  interactive: false
61 
62  anchors.top: header.bottom
63  delegate: Loader {
64  id: loader
65  readonly property bool addDropHint: {
66  if (dragMarker.visible) {
67  if (dragItem.originalIndex > index) {
68  return dragMarker.index == index;
69  } else {
70  return dragMarker.index == index - 1;
71  }
72  } else {
73  return false;
74  }
75  }
76  asynchronous: true
77  width: root.width
78  height: listItemHeight + (addDropHint ? units.gu(2) : 0)
79  clip: height < listItemHeight
80  Behavior on height { enabled: visible; UbuntuNumberAnimation { } }
81  sourceComponent: ScopesListCategoryItem {
82  objectName: "delegate" + model.scopeId
83 
84  width: root.width
85  topMargin: height > listItemHeight ? height - listItemHeight : 0
86 
87  icon: model.art || model.mascot || ""
88  text: model.title || ""
89  subtext: model.subtitle || ""
90  showStar: model.scopeId !== "clickscope" && (root.isFavoritesFeed || root.isAlsoInstalled)
91  isFavorite: root.isFavoritesFeed
92 
93  hideChildren: dragItem.loaderToShrink == loader
94 
95  onClicked: {
96  if (!editMode) {
97  if (root.isFavoritesFeed)
98  root.requestRestore(model.scopeId);
99  else
100  root.requestActivate(result);
101  }
102  }
103  onPressAndHold: {
104  if (!editMode) {
105  root.requestEditMode();
106  }
107  }
108  onRequestFavorite: root.requestFavorite(model.scopeId, favorite);
109  onHandlePressed: {
110  if (editMode) {
111  handle.drag.target = dragItem;
112  handle.drag.maximumX = units.gu(1);
113  handle.drag.minimumX = units.gu(1);
114  handle.drag.minimumY = list.y - dragItem.height / 2;
115  handle.drag.maximumY = list.y + list.height - dragItem.height / 2
116  dragItem.icon = icon;
117  dragItem.text = text;
118  dragItem.subtext = subtext;
119  dragItem.originalY = mapToItem(root, 0, 0).y;
120  dragItem.originalIndex = index;
121  dragItem.y = dragItem.originalY;
122  dragItem.x = units.gu(1);
123  dragItem.visible = true;
124  dragItem.loaderToShrink = loader;
125  }
126  }
127  onHandleReleased: {
128  if (dragItem.visible) {
129  handle.drag.target = undefined;
130  dragItem.visible = false;
131  if (dragMarker.visible && dragMarker.index != index) {
132  root.requestScopeMoveTo(model.scopeId, dragMarker.index);
133  }
134  dragMarker.visible = false;
135  dragItem.loaderToShrink.height = listItemHeight;
136  dragItem.loaderToShrink = null;
137  }
138  }
139  }
140  }
141  }
142 
143  ListItems.ThinDivider {
144  id: dragMarker
145  visible: false
146  anchors {
147  leftMargin: units.gu(1)
148  rightMargin: units.gu(1)
149  }
150  property int index: {
151  var i = Math.round((dragItem.y - list.y + dragItem.height/2) / listItemHeight);
152  if (i < 0) i = 0;
153  if (i >= model.count - 1) i = model.count - 1;
154  return i;
155  }
156  y: list.y + index * listItemHeight + units.gu(1)
157  }
158 
159  ScopesListCategoryItem {
160  id: dragItem
161 
162  property real originalY
163  property int originalIndex
164  property var loaderToShrink: null
165 
166  objectName: "dragItem"
167  visible: false
168  showStar: false
169  width: root.width
170  height: listItemHeight
171  opacity: 0.9
172 
173  onYChanged: {
174  if (!dragMarker.visible && Math.abs(y - originalY) > height / 2) {
175  dragMarker.visible = true;
176  loaderToShrink.height = 0;
177  }
178  }
179  }
180 }