Kirigami-addons

AlbumMaximizeComponent.qml
1// SPDX-FileCopyrightText: 2023 James Graham <james.h.graham@protonmail.com>
2// SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
3
4import QtQuick
5import QtQuick.Controls as QQC2
6import QtQuick.Layouts
7import Qt.labs.qmlmodels
8
9import org.kde.kirigami as Kirigami
10import org.kde.kirigamiaddons.components as KirigamiComponents
11
12/**
13 * @brief A popup that covers the entire window to show an album of 1 or more media items.
14 *
15 * The component supports a model with one or more media components (images or
16 * videos) which can be scrolled through.
17 *
18 * Example:
19 * @code
20 * Components.AlbumMaximizeComponent {
21 * id: root
22 * property list<AlbumModelItem> model: [
23 * AlbumModelItem {
24 * type: AlbumModelItem.Image
25 * source: "path/to/source"
26 * tempSource: "path/to/tempSource"
27 * caption: "caption text"
28 * },
29 * AlbumModelItem {
30 * type: AlbumModelItem.Video
31 * source: "path/to/source"
32 * tempSource: "path/to/tempSource"
33 * caption: "caption text"
34 * }
35 * ]
36 * initialIndex: 0
37 * model: model
38 * }
39 * @endcode
40 *
41 * @note The model doesn't have to be create using AlbumModelItem, it just
42 * requires the same roles (i.e. type, source, tempSource (optional) and
43 * caption (optional)).
44 *
45 * @inherit AbstractMaximizeComponent
46 */
47AbstractMaximizeComponent {
48 id: root
49
50 /**
51 * @brief Model containing the media item to be shown.
52 *
53 * The model can be either a qml or a c++ model but each item needs to have the
54 * values defined in AlbumModelItem.qml (note a list of these is the easiest
55 * way to create a qml model).
56 */
57 property var model
58
59 /**
60 * @brief The index of the initial item that should be visible.
61 */
62 property int initialIndex: -1
63
64 /**
65 * @brief Whether the caption should be shown.
66 */
67 property bool showCaption: true
68
69 /**
70 * @brief Whether the caption is hidden by the user.
71 */
72 property bool hideCaption: false
74 /**
75 * @brief Whether any video media should auto-load.
76 *
77 * @deprecated due to changes in the Video API this will be removed in KF6. It
78 * currently does nothing but is kept to avoid breakage. The loss
79 * of this API has been worked around in a way that doesn't break KF5.
80 */
81 property bool autoLoad: true
82
83 /**
84 * @brief Whether any video media should auto-play.
85 */
86 property bool autoPlay: true
87
88 /**
89 * @brief The default action triggered when the video download button is pressed.
90 *
91 * The download button is only available when the video source is empty (i.e. QUrl()
92 * or "")
93 *
94 * This exists as a property so that the default action can be overridden. The most
95 * common use case for this is where a custom URI scheme is used for example.
96 *
97 * @sa DownloadAction
98 */
99 property DownloadAction downloadAction
100
101 /**
102 * @brief The default action triggered when the play button is pressed.
104 * This exists as a property so that the action can be overridden. For example
105 * if you want to be able to interface with a media manager.
106 */
107 property Kirigami.Action playAction
108
109 /**
110 * @brief The default action triggered when the pause button is pressed.
112 * This exists as a property so that the action can be overridden. For example
113 * if you want to be able to interface with a media manager.
114 */
115 property Kirigami.Action pauseAction
116
117 /**
118 * @brief The current item in the view.
119 */
120 property alias currentItem: view.currentItem
121
122 /**
123 * @brief Emitted when the content image is right clicked.
124 */
125 signal itemRightClicked()
126
127 /**
128 * @brief Emitted when the save item button is pressed.
129 *
130 * The application needs use this signal to trigger the process to save the
131 * file.
132 */
133 signal saveItem()
134
135 actions: [
136 Kirigami.Action {
137 text: i18nd("kirigami-addons6", "Zoom in")
138 icon.name: "zoom-in"
139 onTriggered: view.currentItem.scaleFactor = Math.min(view.currentItem.scaleFactor + 0.25, 3)
140 },
141 Kirigami.Action {
142 text: i18nd("kirigami-addons6", "Zoom out")
143 icon.name: "zoom-out"
144 onTriggered: view.currentItem.scaleFactor = Math.max(view.currentItem.scaleFactor - 0.25, 0.25)
145 },
146 Kirigami.Action {
147 visible: view.currentItem.type === AlbumModelItem.Image
148 text: i18nd("kirigami-addons6", "Rotate left")
149 icon.name: "object-rotate-left"
150 onTriggered: view.currentItem.rotationAngle = view.currentItem.rotationAngle - 90
151 },
152 Kirigami.Action {
153 visible: view.currentItem.type === AlbumModelItem.Image
154 text: i18nd("kirigami-addons6", "Rotate right")
155 icon.name: "object-rotate-right"
156 onTriggered: view.currentItem.rotationAngle = view.currentItem.rotationAngle + 90
157 },
158 Kirigami.Action {
159 text: hideCaption ? i18ndc("kirigami-addons6", "@action:intoolbar", "Show caption") : i18ndc("kirigami-addons6", "@action:intoolbar", "Hide caption")
160 icon.name: "add-subtitle"
161 visible: root.showCaption && view.currentItem.caption
162 onTriggered: hideCaption = !hideCaption
163 },
164 Kirigami.Action {
165 text: i18nd("kirigami-addons6", "Save as")
166 icon.name: "document-save"
167 onTriggered: saveItem()
168 }
169 ]
170
171 content: ListView {
172 id: view
173 Layout.fillWidth: true
174 Layout.fillHeight: true
175 interactive: !hoverHandler.hovered && count > 1
176 snapMode: ListView.SnapOneItem
177 highlightRangeMode: ListView.StrictlyEnforceRange
178 highlightMoveDuration: 0
179 focus: true
180 keyNavigationEnabled: true
181 keyNavigationWraps: false
182 model: root.model
183 orientation: ListView.Horizontal
184 clip: true
185 delegate: DelegateChooser {
186 role: "type"
187 DelegateChoice {
188 roleValue: AlbumModelItem.Image
189 ImageMaximizeDelegate {
190 width: ListView.view.width
191 height: ListView.view.height
192
193 onItemRightClicked: root.itemRightClicked()
194 onBackgroundClicked: root.close()
195 }
196 }
197 DelegateChoice {
198 roleValue: AlbumModelItem.Video
199 VideoMaximizeDelegate {
200 id: videoMaximizeDelegate
201 width: ListView.view.width
202 height: ListView.view.height
203
204 autoPlay: root.autoPlay
205 // Make sure that the default action in the delegate is used if not overridden
206 downloadAction: root.downloadAction ? root.downloadAction : undefined
207 StateGroup {
208 states: State {
209 when: root.playAction
210 PropertyChanges {
211 target: videoMaximizeDelegate
212 playAction: root.playAction
213 }
214 }
215 }
216 StateGroup {
217 states: State {
218 when: root.pauseAction
219 PropertyChanges {
220 target: videoMaximizeDelegate
221 pauseAction: root.pauseAction
222 }
223 }
224 }
225
226 onItemRightClicked: root.itemRightClicked()
227 onBackgroundClicked: root.close()
228 }
229 }
230 }
231
232 KirigamiComponents.FloatingButton {
233 anchors {
234 left: parent.left
235 leftMargin: Kirigami.Units.largeSpacing
236 verticalCenter: parent.verticalCenter
237 }
238 width: Kirigami.Units.gridUnit * 2
239 height: width
240 icon.name: "arrow-left"
241 visible: !Kirigami.Settings.isMobile && view.currentIndex > 0
242 Keys.forwardTo: view
243 Accessible.name: i18nd("kirigami-addons6", "Previous image")
244 onClicked: {
245 view.currentItem.pause()
246 view.currentIndex -= 1
247 if (root.autoPlay) {
248 view.currentItem.playAction.trigger()
249 }
250 }
251 }
252 KirigamiComponents.FloatingButton {
253 anchors {
254 right: parent.right
255 rightMargin: Kirigami.Units.largeSpacing
256 verticalCenter: parent.verticalCenter
257 }
258 width: Kirigami.Units.gridUnit * 2
259 height: width
260 icon.name: "arrow-right"
261 visible: !Kirigami.Settings.isMobile && view.currentIndex < view.count - 1
262 Keys.forwardTo: view
263 Accessible.name: i18nd("kirigami-addons6", "Next image")
264 onClicked: {
265 view.currentItem.pause()
266 view.currentIndex += 1
267 if (root.autoPlay) {
268 view.currentItem.playAction.trigger()
269 }
270 }
271 }
272 HoverHandler {
273 id: hoverHandler
274 acceptedDevices: PointerDevice.Mouse
275 }
276 }
277
278 footer: QQC2.Control {
279 visible: root.showCaption && view.currentItem.caption && !root.hideCaption
280 contentItem: QQC2.ScrollView {
281 anchors.fill: parent
282 QQC2.ScrollBar.vertical.policy: QQC2.ScrollBar.AlwaysOn
283 QQC2.ScrollBar.horizontal.policy: QQC2.ScrollBar.AsNeeded
284 contentWidth: captionLabel.width - captionLabel.padding * 2
285 contentItem: Flickable {
286 width: root.width
287 height: parent.height
288 contentWidth: captionLabel.width
289 contentHeight: captionLabel.height - captionLabel.padding * 2 + Kirigami.Units.largeSpacing
290
291 QQC2.Label {
292 id: captionLabel
293 wrapMode: Text.WordWrap
294 text: view.currentItem.caption
295 padding: Kirigami.Units.largeSpacing
296 width: root.width - padding * 2
297 }
298 }
299 }
300
301 background: Rectangle {
302 color: Kirigami.Theme.alternateBackgroundColor
303 }
304
305 Kirigami.Separator {
306 anchors {
307 left: parent.left
308 right: parent.right
309 bottom: parent.top
310 }
311 height: 1
312 }
313 }
314
315 parent: applicationWindow().overlay
316 closePolicy: QQC2.Popup.CloseOnEscape
317 width: parent.width
318 height: parent.height
319 modal: true
320 padding: 0
321 background: Item {}
322
323 onAboutToShow: {
324 if (root.initialIndex != -1 && root.initialIndex >= 0) {
325 view.currentIndex = initialIndex
326 }
327 }
328}
An object container for defining content items to show in a AlbumMaximizeComponent.
This component is a button that can be displayed at the bottom of a page.
QString i18ndc(const char *domain, const char *context, const char *text, const TYPE &arg...)
QString i18nd(const char *domain, const char *text, const TYPE &arg...)
QString & fill(QChar ch, qsizetype size)
QTextStream & left(QTextStream &stream)
QTextStream & right(QTextStream &stream)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri May 3 2024 11:46:57 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.