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 }