Warning, /multimedia/kasts/src/qml/ImageWithFallback.qml is written in an unsupported language. File is not indexed.
0001 /**
0002 * SPDX-FileCopyrightText: 2021-2023 Bart De Vries <bart@mogwai.be>
0003 *
0004 * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005 */
0006
0007 import QtQuick
0008 import QtQuick.Controls as Controls
0009 import QtQuick.Layouts
0010 import QtQuick.Effects
0011 import QtQuick.Window
0012
0013 import org.kde.kirigami as Kirigami
0014
0015 import org.kde.kasts
0016 import org.kde.kasts.settings
0017
0018 Item {
0019 id: root
0020 property string imageSource: "no-image"
0021 property real imageOpacity: 1
0022 property int absoluteRadius: 0
0023 property real fractionalRadius: 0.0
0024 property string imageTitle: ""
0025 property bool isLoading: false
0026 property int imageFillMode: Image.PreserveAspectCrop
0027 property bool imageResize: true
0028 property bool mipmap: false
0029
0030 // HACK: if mipmap has been set to true, then reset it AFTER image has
0031 // changed, otherwise it will be ignored
0032 onImageSourceChanged: {
0033 if (root.mipmap) {
0034 root.mipmap = true;
0035 }
0036 }
0037
0038 Loader {
0039 id: imageLoader
0040 anchors.fill: parent
0041 visible: false
0042 sourceComponent: (imageSource === "no-image" || imageSource === "") ? fallbackImg : (imageSource === "fetching" ? loaderSymbol : realImg )
0043 }
0044
0045 MultiEffect {
0046 anchors.fill: parent
0047 source: imageLoader.item
0048 opacity: root.imageOpacity
0049 maskEnabled: true
0050 maskThresholdMin: 0.5
0051 maskSpreadAtMin: 0.5
0052 maskSource: ShaderEffectSource {
0053 width: imageLoader.width
0054 height: imageLoader.height
0055 sourceItem: Rectangle {
0056 anchors.centerIn: parent
0057 width: imageLoader.adapt ? imageLoader.width : Math.min(imageLoader.width, imageLoader.height)
0058 height: imageLoader.adapt ? imageLoader.height : width
0059 radius: (absoluteRadius > 0) ? absoluteRadius : ( (fractionalRadius > 0) ? Math.min(width, height)*fractionalRadius : 0 )
0060 }
0061 }
0062 }
0063
0064 Component {
0065 id: realImg
0066 Image {
0067 anchors.fill: parent
0068 source: root.imageSource
0069 fillMode: root.imageFillMode
0070 sourceSize.width: root.imageResize ? width * Screen.devicePixelRatio : 0
0071 sourceSize.height: root.imageResize ? height * Screen.devicePixelRatio : 0
0072 asynchronous: true
0073 mipmap: root.mipmap
0074 }
0075 }
0076
0077 Component {
0078 id: fallbackImg
0079 Item {
0080 anchors.fill: parent
0081 // Add white background color in order to use coloroverlay later on
0082 Rectangle {
0083 anchors.fill: parent
0084 color: "white"
0085 }
0086 Kirigami.Icon {
0087 anchors.fill: parent
0088 source: "rss"
0089 isMask: true
0090 color: "black"
0091 }
0092 }
0093 }
0094
0095 Component {
0096 id: imageText
0097 Item {
0098 Rectangle {
0099 anchors.fill: header
0100 opacity: 0.5
0101 color: "black"
0102 }
0103
0104 Kirigami.Heading {
0105 id: header
0106 anchors.bottom: parent.bottom
0107 anchors.left: parent.left
0108 anchors.right: parent.right
0109 padding: 10
0110 text: root.imageTitle
0111 level: 3
0112 font.bold: true
0113 color: "white"
0114 wrapMode: Text.Wrap
0115 elide: Text.ElideRight
0116 }
0117 }
0118 }
0119
0120 Loader {
0121 anchors.fill: parent
0122 active: root.imageTitle !== "" && (SettingsManager.alwaysShowFeedTitles ? true : (imageSource === "no-image" || imageSource === "fetching"))
0123 sourceComponent: imageText
0124 }
0125
0126 Component {
0127 id: loaderSymbol
0128 Item {
0129 anchors.fill: parent
0130 Rectangle {
0131 color: "white"
0132 opacity: 0.5
0133 anchors.fill: parent
0134 }
0135 Controls.BusyIndicator {
0136 anchors.centerIn: parent
0137 width: parent.width / 2
0138 height: parent.height / 2
0139 }
0140 }
0141 }
0142
0143 Loader {
0144 active: isLoading
0145 sourceComponent: loaderSymbol
0146 anchors.fill: parent
0147 }
0148 }