Warning, /libraries/kirigami-addons/src/components/AlbumMaximizeComponent.qml is written in an unsupported language. File is not indexed.

0001 // SPDX-FileCopyrightText: 2023 James Graham <james.h.graham@protonmail.com>
0002 // SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0003 
0004 import QtQuick
0005 import QtQuick.Controls as QQC2
0006 import QtQuick.Layouts
0007 import Qt.labs.qmlmodels
0008 
0009 import org.kde.kirigami as Kirigami
0010 import org.kde.kirigamiaddons.components as KirigamiComponents
0011 
0012 /**
0013  * @brief A popup that covers the entire window to show an album of 1 or more media items.
0014  *
0015  * The component supports a model with one or more media components (images or
0016  * videos) which can be scrolled through.
0017  *
0018  * Example:
0019  * @code
0020  * Components.AlbumMaximizeComponent {
0021  *  id: root
0022  *  property list<AlbumModelItem> model: [
0023  *      AlbumModelItem {
0024  *          type: AlbumModelItem.Image
0025  *          source: "path/to/source"
0026  *          tempSource: "path/to/tempSource"
0027  *          caption: "caption text"
0028  *      },
0029  *      AlbumModelItem {
0030  *          type: AlbumModelItem.Video
0031  *          source: "path/to/source"
0032  *          tempSource: "path/to/tempSource"
0033  *          caption: "caption text"
0034  *      }
0035  *  ]
0036  *  initialIndex: 0
0037  *  model: model
0038  * }
0039  * @endcode
0040  *
0041  * @note The model doesn't have to be create using AlbumModelItem, it just
0042  *       requires the same roles (i.e. type, source, tempSource (optional) and
0043  *       caption (optional)).
0044  *
0045  * @inherit AbstractMaximizeComponent
0046  */
0047 AbstractMaximizeComponent {
0048     id: root
0049 
0050     /**
0051      * @brief Model containing the media item to be shown.
0052      *
0053      * The model can be either a qml or a c++ model but each item needs to have the
0054      * values defined in AlbumModelItem.qml (note a list of these is the easiest
0055      * way to create a qml model).
0056      */
0057     property var model
0058 
0059     /**
0060      * @brief The index of the initial item that should be visible.
0061      */
0062     property int initialIndex: -1
0063 
0064     /**
0065      * @brief Whether the caption should be shown.
0066      */
0067     property bool showCaption: true
0068 
0069     /**
0070      * @brief Whether the caption is hidden by the user.
0071      */
0072     property bool hideCaption: false
0073 
0074     /**
0075      * @brief Whether any video media should auto-load.
0076      *
0077      * @deprecated due to changes in the Video API this will be removed in KF6. It
0078      *             currently does nothing but is kept to avoid breakage. The loss
0079      *             of this API has been worked around in a way that doesn't break KF5.
0080      */
0081     property bool autoLoad: true
0082 
0083     /**
0084      * @brief Whether any video media should auto-play.
0085      */
0086     property bool autoPlay: true
0087 
0088     /**
0089      * @brief The default action triggered when the video download button is pressed.
0090      *
0091      * The download button is only available when the video source is empty (i.e. QUrl()
0092      * or "")
0093      *
0094      * This exists as a property so that the default action can be overridden. The most
0095      * common use case for this is where a custom URI scheme is used for example.
0096      *
0097      * @sa DownloadAction
0098      */
0099     property DownloadAction downloadAction
0100 
0101     /**
0102      * @brief Emitted when the content image is right clicked.
0103      */
0104     signal itemRightClicked()
0105 
0106     /**
0107      * @brief Emitted when the save item button is pressed.
0108      *
0109      * The application needs use this signal to trigger the process to save the
0110      * file.
0111      */
0112     signal saveItem()
0113 
0114     actions: [
0115         Kirigami.Action {
0116             text: i18nd("kirigami-addons6", "Zoom in")
0117             icon.name: "zoom-in"
0118             onTriggered: view.currentItem.scaleFactor = Math.min(view.currentItem.scaleFactor + 0.25, 3)
0119         },
0120         Kirigami.Action {
0121             text: i18nd("kirigami-addons6", "Zoom out")
0122             icon.name: "zoom-out"
0123             onTriggered: view.currentItem.scaleFactor = Math.max(view.currentItem.scaleFactor - 0.25, 0.25)
0124         },
0125         Kirigami.Action {
0126             visible: view.currentItem.type === AlbumModelItem.Image
0127             text: i18nd("kirigami-addons6", "Rotate left")
0128             icon.name: "object-rotate-left"
0129             onTriggered: view.currentItem.rotationAngle = view.currentItem.rotationAngle - 90
0130         },
0131         Kirigami.Action {
0132             visible: view.currentItem.type === AlbumModelItem.Image
0133             text: i18nd("kirigami-addons6", "Rotate right")
0134             icon.name: "object-rotate-right"
0135             onTriggered: view.currentItem.rotationAngle = view.currentItem.rotationAngle + 90
0136         },
0137         Kirigami.Action {
0138             text: hideCaption ? i18ndc("kirigami-addons6", "@action:intoolbar", "Show caption") : i18ndc("kirigami-addons6", "@action:intoolbar", "Hide caption")
0139             icon.name: "add-subtitle"
0140             visible: root.showCaption && view.currentItem.caption
0141             onTriggered: hideCaption = !hideCaption
0142         },
0143         Kirigami.Action {
0144             text: i18nd("kirigami-addons6", "Save as")
0145             icon.name: "document-save"
0146             onTriggered: saveItem()
0147         }
0148     ]
0149 
0150     content: ListView {
0151         id: view
0152         Layout.fillWidth: true
0153         Layout.fillHeight: true
0154         interactive: !hoverHandler.hovered && count > 1
0155         snapMode: ListView.SnapOneItem
0156         highlightRangeMode: ListView.StrictlyEnforceRange
0157         highlightMoveDuration: 0
0158         focus: true
0159         keyNavigationEnabled: true
0160         keyNavigationWraps: false
0161         model: root.model
0162         orientation: ListView.Horizontal
0163         clip: true
0164         delegate: DelegateChooser {
0165             role: "type"
0166             DelegateChoice {
0167                 roleValue: AlbumModelItem.Image
0168                 ImageMaximizeDelegate {
0169                     width: ListView.view.width
0170                     height: ListView.view.height
0171 
0172                     onItemRightClicked: root.itemRightClicked()
0173                     onBackgroundClicked: root.close()
0174                 }
0175             }
0176             DelegateChoice {
0177                 roleValue: AlbumModelItem.Video
0178                 VideoMaximizeDelegate {
0179                     width: ListView.view.width
0180                     height: ListView.view.height
0181 
0182                     autoPlay: root.autoPlay
0183                     // Make sure that the default action in the delegate is used if not overridden
0184                     downloadAction: root.downloadAction ? root.downloadAction : undefined
0185 
0186                     onItemRightClicked: root.itemRightClicked()
0187                     onBackgroundClicked: root.close()
0188                 }
0189             }
0190         }
0191 
0192         KirigamiComponents.FloatingButton {
0193             anchors {
0194                 left: parent.left
0195                 leftMargin: Kirigami.Units.largeSpacing
0196                 verticalCenter: parent.verticalCenter
0197             }
0198             width: Kirigami.Units.gridUnit * 2
0199             height: width
0200             icon.name: "arrow-left"
0201             visible: !Kirigami.Settings.isMobile && view.currentIndex > 0
0202             Keys.forwardTo: view
0203             Accessible.name: i18nd("kirigami-addons6", "Previous image")
0204             onClicked: {
0205                 view.currentItem.pause()
0206                 view.currentIndex -= 1
0207                 view.currentItem.play()
0208             }
0209         }
0210         KirigamiComponents.FloatingButton {
0211             anchors {
0212                 right: parent.right
0213                 rightMargin: Kirigami.Units.largeSpacing
0214                 verticalCenter: parent.verticalCenter
0215             }
0216             width: Kirigami.Units.gridUnit * 2
0217             height: width
0218             icon.name: "arrow-right"
0219             visible: !Kirigami.Settings.isMobile && view.currentIndex < view.count - 1
0220             Keys.forwardTo: view
0221             Accessible.name: i18nd("kirigami-addons6", "Next image")
0222             onClicked: {
0223                 view.currentItem.pause()
0224                 view.currentIndex += 1
0225                 view.currentItem.play()
0226             }
0227         }
0228         HoverHandler {
0229             id: hoverHandler
0230             acceptedDevices: PointerDevice.Mouse
0231         }
0232     }
0233 
0234     footer: QQC2.Control {
0235         visible: root.showCaption && view.currentItem.caption && !root.hideCaption
0236         contentItem: QQC2.ScrollView {
0237             anchors.fill: parent
0238             QQC2.ScrollBar.vertical.policy: QQC2.ScrollBar.AlwaysOn
0239             QQC2.ScrollBar.horizontal.policy: QQC2.ScrollBar.AsNeeded
0240             contentWidth: captionLabel.width - captionLabel.padding * 2
0241             contentItem: Flickable {
0242                 width: root.width
0243                 height: parent.height
0244                 contentWidth: captionLabel.width
0245                 contentHeight: captionLabel.height - captionLabel.padding * 2 + Kirigami.Units.largeSpacing
0246 
0247                 QQC2.Label {
0248                     id: captionLabel
0249                     wrapMode: Text.WordWrap
0250                     text: view.currentItem.caption
0251                     padding: Kirigami.Units.largeSpacing
0252                     width: root.width - padding * 2
0253                 }
0254             }
0255         }
0256 
0257         background: Rectangle {
0258             color: Kirigami.Theme.alternateBackgroundColor
0259         }
0260 
0261         Kirigami.Separator {
0262             anchors {
0263                 left: parent.left
0264                 right: parent.right
0265                 bottom: parent.top
0266             }
0267             height: 1
0268         }
0269     }
0270 
0271     parent: applicationWindow().overlay
0272     closePolicy: QQC2.Popup.CloseOnEscape
0273     width: parent.width
0274     height: parent.height
0275     modal: true
0276     padding: 0
0277     background: Item {}
0278 
0279     onAboutToShow: {
0280         if (root.initialIndex != -1 && root.initialIndex >= 0) {
0281             view.currentIndex = initialIndex
0282         }
0283     }
0284 }