Unity 8
PreviewImageGallery.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.4
18 import Ubuntu.Components 1.3
19 import "../../Components"
20 
21 /*! This preview widget shows a horizontal list of images.
22  * The URIs for the images should be an array in widgetData["sources"].
23  * Images fall back to widgetData["fallback"] if loading fails
24  */
25 
26 PreviewWidget {
27  id: root
28  implicitHeight: units.gu(22)
29 
30  orientationLock: overlay.visible
31 
32  property Item rootItem: QuickUtils.rootItem(root)
33 
34  ListView {
35  id: previewImageListView
36  objectName: "previewImageListView"
37  spacing: units.gu(1)
38  anchors.fill: parent
39  orientation: ListView.Horizontal
40  cacheBuffer: width * 3
41  model: root.widgetData["sources"]
42  clip: true
43  highlightMoveDuration: 0 // QTBUG-53460
44 
45  onCurrentIndexChanged: overlay.updateInitialItem()
46 
47  LazyImage {
48  objectName: "placeholderScreenshot"
49  anchors {
50  top: parent.top
51  bottom: parent.bottom
52  }
53  scaleTo: "height"
54  source: "broken_image"
55  initialWidth: units.gu(13)
56  visible: previewImageListView.count == 0
57  }
58 
59  delegate: LazyImage {
60  objectName: "previewImage" + index
61  anchors {
62  top: parent.top
63  bottom: parent.bottom
64  }
65  source: modelData || root.widgetData["fallback"] || ""
66  scaleTo: "height"
67  initialWidth: units.gu(13)
68  pressed: mouseArea.pressed
69 
70  MouseArea {
71  id: mouseArea
72  anchors.fill: parent
73  onClicked: {
74  previewImageListView.currentIndex = index;
75  overlay.updateInitialItem();
76  overlay.show();
77  }
78  }
79 
80  Connections {
81  target: sourceImage
82  // If modelData would change after failing to load it would not be
83  // reloaded since the source binding is destroyed by the source = fallback
84  // But at the moment the model never changes
85  onStatusChanged: if (sourceImage.status === Image.Error) sourceImage.source = widgetData["fallback"];
86  }
87  }
88  }
89 
90  PreviewOverlay {
91  id: overlay
92  objectName: "overlay"
93  parent: rootItem
94  anchors.fill: parent
95 
96  function updateInitialItem() {
97  initialX = rootItem.mapFromItem(previewImageListView.currentItem, 0, 0).x;
98  initialY = rootItem.mapFromItem(previewImageListView.currentItem, 0, 0).y;
99  initialWidth = previewImageListView.currentItem.width;
100  initialHeight = previewImageListView.currentItem.height;
101  }
102 
103  delegate: ListView {
104  id: overlayListView
105  objectName: "overlayListView"
106  anchors.fill: parent
107  orientation: ListView.Horizontal
108  highlightRangeMode: ListView.StrictlyEnforceRange
109  highlightMoveDuration: 0
110  snapMode: ListView.SnapOneItem
111  boundsBehavior: Flickable.DragAndOvershootBounds
112  model: root.widgetData["sources"]
113  currentIndex: previewImageListView.currentIndex
114 
115  onCurrentIndexChanged: {
116  // if the index changed while overlay is visible, it was from user interaction,
117  // let's update the index of the original listview
118  if (overlay.visible) {
119  previewImageListView.highlightMoveDuration = 0;
120  previewImageListView.highlightResizeDuration = 0;
121  previewImageListView.currentIndex = currentIndex;
122  previewImageListView.highlightMoveDuration = -1;
123  previewImageListView.highlightResizeDuration = -1;
124  }
125  }
126 
127  delegate: Image {
128  id: screenshot
129  anchors {
130  top: parent.top
131  bottom: parent.bottom
132  }
133  width: overlay.width
134  source: modelData || root.widgetData["fallback"] || ""
135  fillMode: Image.PreserveAspectFit
136  sourceSize { width: screenshot.width; height: screenshot.height }
137 
138  // If modelData would change after failing to load it would not be
139  // reloaded since the source binding is destroyed by the source = fallback
140  // But at the moment the model never changes
141  onStatusChanged: if (status === Image.Error) source = widgetData["fallback"];
142  }
143 
144  MouseArea {
145  anchors.fill: parent
146  onClicked: overlay.headerShown = !overlay.headerShown
147  }
148  }
149  }
150 }