Warning, /plasma/discover/discover/qml/ApplicationScreenshots.qml is written in an unsupported language. File is not indexed.

0001 /*
0002  *   SPDX-FileCopyrightText: 2012 Aleix Pol Gonzalez <aleixpol@blue-systems.com>
0003  *   SPDX-FileCopyrightText: 2020 Carl Schwan <carl@carlschwan.eu>
0004  *
0005  *   SPDX-License-Identifier: LGPL-2.0-or-later
0006  */
0007 
0008 
0009 import QtQuick 2.15
0010 import QtQuick.Layouts 1.15
0011 import QtQuick.Controls 2.15
0012 import org.kde.discover 2.0
0013 import org.kde.kirigami 2.19 as Kirigami
0014 
0015 ListView {
0016     id: root
0017     readonly property alias count: screenshotsModel.count
0018     property bool showNavigationArrows: true
0019     property alias resource: screenshotsModel.application
0020     property var resource
0021     property int failedCount: 0
0022     readonly property bool hasFailed: count !== 0 && failedCount === count
0023 
0024     spacing: Kirigami.Units.largeSpacing
0025     focus: overlay.visible
0026     orientation: Qt.Horizontal
0027     cacheBuffer: 10 // keep some screenshots in memory
0028 
0029     Keys.onLeftPressed:  if (leftAction.visible)  leftAction.trigger()
0030     Keys.onRightPressed: if (rightAction.visible) rightAction.trigger()
0031 
0032     model: ScreenshotsModel {
0033         id: screenshotsModel
0034     }
0035 
0036     property real delegateHeight: Kirigami.Units.gridUnit * 4
0037 
0038     delegate: AbstractButton {
0039         readonly property bool animated: isAnimated
0040         readonly property url imageSource: large_image_url
0041         readonly property real proportion: thumbnail.status === Image.Ready && thumbnail.sourceSize.width>1 ? thumbnail.sourceSize.height/thumbnail.sourceSize.width : 1
0042 
0043         implicitWidth: root.delegateHeight / proportion
0044         implicitHeight: root.delegateHeight
0045         opacity: hovered ? 0.7 : 1
0046 
0047         hoverEnabled: true
0048         onClicked: {
0049             root.currentIndex = model.row
0050             overlay.open()
0051         }
0052 
0053         HoverHandler {
0054             cursorShape: Qt.PointingHandCursor
0055         }
0056 
0057         background: Item {
0058             BusyIndicator {
0059                 visible: running
0060                 running: thumbnail.status === Image.Loading
0061                 anchors.centerIn: parent
0062             }
0063             Kirigami.Icon {
0064                 anchors.fill: parent
0065                 anchors.margins: Kirigami.Units.gridUnit
0066                 visible: thumbnail.status === Image.Error
0067                 source: "emblem-error"
0068             }
0069             ConditionalLoader {
0070                 id: thumbnail
0071                 anchors.fill: parent
0072                 readonly property var status: item.status
0073                 readonly property var sourceSize: item.sourceSize
0074                 condition: isAnimated
0075 
0076                 componentFalse: Component {
0077                     Image {
0078                         source: small_image_url
0079                     }
0080                 }
0081                 componentTrue: Component {
0082                     AnimatedImage {
0083                         source: small_image_url
0084                     }
0085                 }
0086 
0087                 onStatusChanged: {
0088                     if (status === Image.Error) {
0089                         root.failedCount += 1;
0090                     }
0091                 }
0092             }
0093         }
0094     }
0095 
0096     Popup {
0097         id: overlay
0098         parent: applicationWindow().overlay
0099         z: applicationWindow().globalDrawer.z + 10
0100         modal: true
0101         clip: false
0102 
0103         x: (parent.width - width)/2
0104         y: (parent.height - height)/2
0105         readonly property real proportion: overlayImage.sourceSize.width>1 ? overlayImage.sourceSize.height/overlayImage.sourceSize.width : 1
0106         height: overlayImage.status >= Image.Loading ? Kirigami.Units.gridUnit * 5 : Math.min(parent.height * 0.9, (parent.width * 0.9) * proportion, overlayImage.sourceSize.height)
0107         width: (height - 2 * padding)/proportion
0108 
0109         BusyIndicator {
0110             id: indicator
0111             visible: running
0112             running: overlayImage.status === Image.Loading
0113             anchors.centerIn: parent
0114         }
0115 
0116         Kirigami.Icon {
0117             anchors.fill: parent
0118             visible: overlayImage.status === Image.Error
0119             source: "emblem-error"
0120         }
0121 
0122         ConditionalLoader {
0123             id: overlayImage
0124             anchors.fill: parent
0125             readonly property var status: item.status
0126             readonly property var sourceSize: item.sourceSize
0127             condition: root.currentItem.animated
0128 
0129             componentFalse: Component {
0130                 Image {
0131                     source: root.currentItem ? root.currentItem.imageSource : ""
0132                     fillMode: Image.PreserveAspectFit
0133                     smooth: true
0134                 }
0135             }
0136             componentTrue: Component {
0137                 AnimatedImage {
0138                     source: root.currentItem ? root.currentItem.imageSource : ""
0139                     fillMode: Image.PreserveAspectFit
0140                     smooth: true
0141                 }
0142             }
0143 
0144             onStatusChanged: {
0145                 if (status === Image.Error) {
0146                     root.failedCount += 1;
0147                 }
0148             }
0149         }
0150 
0151         Button {
0152             anchors {
0153                 left: parent.right
0154                 bottom: parent.top
0155             }
0156             icon.name: "window-close"
0157             onClicked: overlay.close()
0158         }
0159 
0160 
0161         RoundButton {
0162             anchors {
0163                 right: parent.left
0164                 verticalCenter: parent.verticalCenter
0165             }
0166             visible: leftAction.visible
0167             icon.name: leftAction.iconName
0168             onClicked: leftAction.triggered(null)
0169         }
0170 
0171         RoundButton {
0172             anchors {
0173                 left: parent.right
0174                 verticalCenter: parent.verticalCenter
0175             }
0176             visible: rightAction.visible
0177             icon.name: rightAction.iconName
0178             onClicked: rightAction.triggered(null)
0179         }
0180 
0181         Kirigami.Action {
0182             id: leftAction
0183             icon.name: root.LayoutMirroring.enabled ? "arrow-right" : "arrow-left"
0184             enabled: overlay.visible && visible
0185             visible: root.currentIndex >= 1 && !indicator.running
0186             onTriggered: root.currentIndex = (root.currentIndex - 1) % screenshotsModel.count
0187         }
0188 
0189         Kirigami.Action {
0190             id: rightAction
0191             icon.name: root.LayoutMirroring.enabled ? "arrow-left" : "arrow-right"
0192             enabled: overlay.visible && visible
0193             visible: root.currentIndex < (root.count - 1) && !indicator.running
0194             onTriggered: root.currentIndex = (root.currentIndex + 1) % screenshotsModel.count
0195         }
0196     }
0197 
0198 
0199     clip: true
0200 
0201     RoundButton {
0202         anchors {
0203             left: parent.left
0204             leftMargin: Kirigami.Units.largeSpacing
0205             verticalCenter: parent.verticalCenter
0206         }
0207         width: Kirigami.Units.gridUnit * 2
0208         height: width
0209         icon.name: root.LayoutMirroring.enabled ? "arrow-right" : "arrow-left"
0210         visible: !Kirigami.Settings.isMobile
0211                  && root.count > 1
0212                  && root.currentIndex > 0
0213                  && root.showNavigationArrows
0214         Keys.forwardTo: [root]
0215         onClicked: root.currentIndex -= 1
0216     }
0217 
0218     RoundButton {
0219         anchors {
0220             right: parent.right
0221             rightMargin: Kirigami.Units.largeSpacing
0222             verticalCenter: parent.verticalCenter
0223         }
0224         width: Kirigami.Units.gridUnit * 2
0225         height: width
0226         icon.name: root.LayoutMirroring.enabled ? "arrow-left" : "arrow-right"
0227         visible: !Kirigami.Settings.isMobile
0228                  && root.count > 1
0229                  && root.currentIndex < root.count - 1
0230                  && root.showNavigationArrows
0231         Keys.forwardTo: [root]
0232         onClicked: root.currentIndex += 1
0233     }
0234 }