moment/src/gui/Base/HImage.qml

135 lines
3.9 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: false
2019-09-13 06:16:35 +10:00
property bool animate: true
property bool animated:
utils.urlExtension(image.source).toLowerCase() === "gif"
property bool enabledAnimatedPausing: true
2020-03-16 05:14:05 +11:00
property alias radius: roundMask.radius
property alias showProgressBar: progressBarLoader.active
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))
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
property bool userPaused: ! window.settings.media.autoPlayGIF
2019-09-13 06:16:35 +10:00
source: image.source
autoTransform: image.autoTransform
asynchronous: image.asynchronous
fillMode: image.fillMode
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 || userPaused
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
Binding {
target: image
property: "fillMode"
value: Image.Pad
}
Binding {
target: image
property: "sourceSize.width"
value: 1
}
Binding {
target: image
property: "sourceSize.height"
value: 1
}
2019-09-13 06:23:30 +10:00
TapHandler {
enabled: image.enabledAnimatedPausing
2019-09-13 06:23:30 +10:00
onTapped: parent.userPaused = ! parent.userPaused
gesturePolicy: TapHandler.ReleaseWithinBounds
2019-09-13 06:23:30 +10:00
}
2019-09-13 07:27:26 +10:00
HIcon {
2019-09-13 07:32:48 +10:00
anchors.centerIn: parent
2019-09-18 06:30:04 +10:00
svgName: "play-overlay"
2019-09-13 07:27:26 +10:00
colorize: "transparent"
dimension: Math.min(
parent.width - theme.spacing * 2,
parent.height - theme.spacing * 2,
theme.controls.image.maxPauseIndicatorSize,
)
2019-12-10 02:35:50 +11:00
scale: parent.status === Image.Ready && parent.paused ? 1 : 0
2019-09-13 07:27:26 +10:00
2019-12-16 19:42:41 +11:00
Behavior on scale { HNumberAnimation { overshoot: 4 } }
2019-09-13 07:27:26 +10:00
}
2019-09-13 06:16:35 +10:00
}
}
HLoader {
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
2019-11-07 06:47:18 +11:00
width: Math.min(parent.width, parent.height) * 0.5
height: width
active: 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: broken || image.status === Image.Error
svgName: "broken-image"
colorize: theme.colors.negativeBackground
}
2020-03-16 05:14:05 +11:00
Rectangle {
id: roundMask
anchors.fill: parent
visible: false
}
}