on ac4b821 help sign in
unity8/qml/Dash/PreviewListView.qml
212 lines 7.8 kB history raw
1/*
2 * Copyright (C) 2013 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 */
17import QtQuick 2.0
18import Ubuntu.Components 0.1
19import Unity 0.1
20import "../Components"
22Item {
23 property OpenEffect openEffect: null
24 property ScopeListView categoryView: null
25 property Scope scope: null
27 property alias open: previewListView.open
28 property alias onScreen: previewListView.onScreen
29 property alias categoryId: previewListView.categoryId
30 property alias categoryDelegate: previewListView.categoryDelegate
31 property alias init: previewListView.init
32 property alias model: previewListView.model
33 property alias currentIndex: previewListView.currentIndex
34 property alias currentItem: previewListView.currentItem
36 Image {
37 objectName: "pointerArrow"
38 anchors {
39 top: previewListView.bottom
40 left: parent.left
41 leftMargin: previewListView.categoryDelegate !== undefined && previewListView.categoryDelegate.currentItem ?
42 previewListView.categoryDelegate.currentItem.center + (-width + margins) / 2 : 0
44 Behavior on leftMargin {
45 SmoothedAnimation {
46 duration: UbuntuAnimation.FastDuration
47 }
48 }
49 }
50 height: units.gu(1)
51 width: units.gu(2)
52 property int margins: previewListView.categoryDelegate ? previewListView.categoryDelegate.margins : 0
53 opacity: previewListView.open ? .5 : 0
55 source: "graphics/tooltip_arrow.png"
56 }
58 ListView {
59 id: previewListView
60 objectName: "previewListView"
61 height: openEffect.bottomGapPx - openEffect.topGapPx
62 anchors {
63 top: parent.top
64 topMargin: openEffect.topGapPx
65 left: parent.left
66 right: parent.right
67 }
68 orientation: ListView.Horizontal
69 highlightRangeMode: ListView.StrictlyEnforceRange
70 snapMode: ListView.SnapOneItem
71 boundsBehavior: Flickable.DragAndOvershootBounds
72 highlightMoveDuration: 250
73 flickDeceleration: units.gu(625)
74 maximumFlickVelocity: width * 5
75 cacheBuffer: 0
77 // To be set before opening the preview
78 property string categoryId: ""
79 property var categoryDelegate
81 // because the ListView is built asynchronous, setting the
82 // currentIndex directly won't work. We need to refresh it
83 // when the first preview is ready to be displayed.
84 property bool init: true
86 PreviewDelegateMapper {
87 id: previewDelegateMapper
88 }
90 onCurrentIndexChanged: {
91 var row = Math.floor(currentIndex / categoryDelegate.columns);
92 if (categoryDelegate.collapsedRowCount <= row) {
93 categoryView.expandedCategoryId = categoryId
94 }
96 if (open) {
97 categoryDelegate.highlightIndex = currentIndex
98 }
100 if (!init && model !== undefined) {
101 var item = model.get(currentIndex)
102 scope.preview(item.uri, item.icon, item.category, 0, item.mimetype, item.title, item.comment, item.dndUri, item.metadata)
103 }
105 // Adjust contentY in case we need to change to it to show the next row
106 if (categoryDelegate.rows > 1) {
107 var itemY = categoryView.contentItem.mapFromItem(categoryDelegate.currentItem).y;
109 // Find new contentY and effect.postionPx
110 var newContentY = itemY - openEffect.positionPx - categoryDelegate.verticalSpacing;
112 // Make sure the item is not covered by a header. Move the effect split down if necessary
113 var headerHeight = pageHeader.height + categoryView.stickyHeaderHeight;
114 var effectAdjust = Math.max(openEffect.positionPx, headerHeight);
116 // Make sure we don't overscroll the listview. If yes, adjust effect position
117 if (newContentY < 0) {
118 effectAdjust += newContentY;
119 newContentY = 0;
120 }
121 if (newContentY > Math.max(0, categoryView.contentHeight - categoryView.height)) {
122 effectAdjust += -(categoryView.contentHeight - categoryView.height) + newContentY
123 newContentY = categoryView.contentHeight - categoryView.height;
124 }
126 openEffect.positionPx = effectAdjust;
127 categoryView.contentY = newContentY;
128 }
129 }
131 property bool open: false
132 property bool onScreen: false
134 onOpenChanged: {
135 if (open) {
136 onScreen = true;
137 categoryDelegate.highlightIndex = currentIndex;
138 pageHeader.unfocus();
139 } else {
140 // Cancel any pending preview requests or actions
141 if (previewListView.currentItem.previewData !== undefined) {
142 previewListView.currentItem.previewData.cancelAction();
143 }
144 scope.cancelActivation();
145 model = undefined;
146 categoryView.correctExpandedCategory();
147 categoryDelegate.highlightIndex = -1;
148 }
149 }
151 Rectangle {
152 anchors.fill: parent
153 color: Qt.rgba(0, 0, 0, .3)
154 z: -1
155 }
157 delegate: Loader {
158 id: previewLoader
159 objectName: "previewLoader" + index
160 height: previewListView.height
161 width: previewListView.width
162 asynchronous: true
163 source: previewListView.onScreen ?
164 (previewData !== undefined ? previewDelegateMapper.map(previewData.rendererName) : "DashPreviewPlaceholder.qml") : ""
166 onPreviewDataChanged: {
167 if (previewData !== undefined && source.toString().indexOf("DashPreviewPlaceholder.qml") != -1) {
168 previewLoader.opacity = 0;
169 }
170 }
172 onSourceChanged: {
173 if (previewData !== undefined) {
174 fadeIn.start()
175 }
176 }
178 PropertyAnimation {
179 id: fadeIn
180 target: previewLoader
181 property: "opacity"
182 from: 0.0
183 to: 1.0
184 duration: UbuntuAnimation.BriskDuration
185 }
187 property var previewData
188 property bool valid: item !== null
190 onLoaded: {
191 if (previewListView.onScreen && previewData !== undefined) {
192 item.previewData = Qt.binding(function() { return previewData })
193 item.isCurrent = Qt.binding(function() { return ListView.isCurrentItem })
194 }
195 }
197 Connections {
198 ignoreUnknownSignals: true
199 target: item
200 onClose: {
201 previewListView.open = false
202 }
203 }
205 function closePreviewSpinner() {
206 if (item) {
207 item.showProcessingAction = false;
208 }
209 }
210 }
211 }