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