moment/src/gui/Base/HImage.qml

163 lines
4.5 KiB
QML
Raw Normal View History

2019-12-19 22:46:16 +11:00
// SPDX-License-Identifier: LGPL-3.0-or-later
import QtQuick 2.12
2020-03-16 05:14:05 +11:00
import QtGraphicalEffects 1.12
Image {
id: image
2020-03-16 05:14:05 +11:00
property bool circle: radius === circleRadius
property bool broken: image.status === Image.Error
2019-09-13 06:16:35 +10:00
property bool animate: true
property bool animated:
utils.urlExtension(image.source).toLowerCase() === "gif"
2020-07-17 21:26:31 +10:00
property int animatedFillMode: AnimatedImage.PreserveAspectFit
2020-03-16 05:14:05 +11:00
property alias radius: roundMask.radius
property alias showProgressBar: progressBarLoader.active
property bool pause: ! window.settings.media.autoPlayGIF
2019-09-13 06:23:30 +10:00
2020-03-16 05:14:05 +11:00
readonly property int circleRadius:
Math.ceil(Math.max(image.width, image.height))
readonly property int animatedPaintedWidth:
animatedLoader.item ? animatedLoader.item.paintedWidth : 0
readonly property int animatedPaintedHeight:
animatedLoader.item ? animatedLoader.item.paintedHeight : 0
function reload() {
// Can be reimplemented in components inheriting HImage
const oldSource = source
source = ""
source = oldSource
}
2019-09-13 06:16:35 +10:00
autoTransform: true
asynchronous: true
fillMode: Image.PreserveAspectFit
cache: ! (animate && animated) &&
(sourceSize.width + sourceSize.height) <= 512
layer.enabled: radius !== 0
layer.effect: OpacityMask { maskSource: roundMask }
2019-09-13 06:16:35 +10:00
Component {
2019-09-13 07:27:26 +10:00
id: animatedImageComponent
2019-09-13 06:16:35 +10:00
AnimatedImage {
2019-09-13 07:27:26 +10:00
id: animatedImage
2019-09-13 06:16:35 +10:00
source: image.source
autoTransform: image.autoTransform
asynchronous: image.asynchronous
2020-07-17 21:26:31 +10:00
fillMode: image.animatedFillMode
2019-09-13 06:16:35 +10:00
mirror: image.mirror
mipmap: image.mipmap
smooth: image.smooth
horizontalAlignment: image.horizontalAlignment
verticalAlignment: image.verticalAlignment
// Online GIFs won't be able to loop if cache is set to false,
// but caching GIFs is expansive.
cache: ! Qt.resolvedUrl(source).startsWith("file://")
paused: ! visible || window.hidden || image.pause
layer.enabled: image.radius !== 0
layer.effect: OpacityMask { maskSource: roundMask }
2020-03-16 15:15:47 +11:00
// Hack to make the non-animated image behind this one
// basically invisible
2020-07-17 21:26:31 +10:00
Binding {
target: image
property: "fillMode"
value: Image.Pad
}
2020-03-16 15:15:47 +11:00
Binding {
target: image
property: "sourceSize.width"
value: 1
}
Binding {
target: image
property: "sourceSize.height"
value: 1
}
HButton {
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.leftMargin: theme.spacing / 2
anchors.bottomMargin: theme.spacing / 2
enableRadius: true
icon.name: image.pause ? "player-play" : "player-pause"
iconItem.small: true
visible: parent.width > width * 2 && parent.height > height * 2
onClicked: image.pause = ! image.pause
2019-09-13 07:27:26 +10:00
}
2019-09-13 06:16:35 +10:00
}
}
HLoader {
id: animatedLoader
2019-09-13 06:16:35 +10:00
anchors.fill: parent
2019-09-13 07:27:26 +10:00
sourceComponent: animate && animated ? animatedImageComponent : null
2019-09-13 06:16:35 +10:00
}
2019-10-28 07:35:58 +11:00
HLoader {
id: progressBarLoader
readonly property alias progress: image.progress
readonly property Component determinate: HCircleProgressBar {
progress: image.progress
}
2019-10-28 07:35:58 +11:00
anchors.centerIn: parent
2020-07-19 13:37:55 +10:00
width: Math.min(
96 * theme.uiScale, Math.min(parent.width, parent.height) * 0.5,
)
2019-11-07 06:47:18 +11:00
height: width
active:
image.visible &&
image.opacity > 0.01 &&
image.status === Image.Loading
sourceComponent: HBusyIndicator {}
2019-10-28 07:35:58 +11:00
onProgressChanged:
if (progress > 0 && progress < 1) sourceComponent = determinate
2019-10-28 07:35:58 +11:00
}
HIcon {
anchors.centerIn: parent
visible: image.broken
svgName: "broken-image"
colorize: theme.colors.negativeBackground
}
2020-03-16 05:14:05 +11:00
Rectangle {
id: roundMask
anchors.fill: parent
visible: false
}
Timer {
property int retries: 0
running: image.broken
repeat: true
interval:
Math.min(60, 0.2 * Math.pow(2, Math.min(1000, retries) - 1)) * 1000
onTriggered: {
image.reload()
retries += 1
}
}
}