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