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