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