Split ImageViewer components

This commit is contained in:
miruka 2020-07-20 14:27:52 -04:00
parent 9444225afa
commit 66a44b5251
4 changed files with 226 additions and 198 deletions

View File

@ -366,7 +366,7 @@ Rectangle {
forLink || (isAnimated(event) ? "" : event.media_url)
utils.makePopup(
"Popups/ImageViewerPopup.qml",
"Popups/ImageViewerPopup/ImageViewerPopup.qml",
{
thumbnailTitle: getThumbnailTitle(event),
thumbnailMxc: event.thumbnail_url,

View File

@ -1,197 +0,0 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Window 2.12
import "../Base"
HPopup {
id: popup
property alias thumbnailTitle: thumbnail.title
property alias thumbnailMxc: thumbnail.mxc
property alias thumbnailPath: thumbnail.cachedPath // optional
property alias thumbnailCryptDict: thumbnail.cryptDict
property alias fullTitle: full.title
property alias fullMxc: full.mxc
property alias fullCryptDict: full.cryptDict
property size overallSize
property bool alternateScaling: false
property bool activedFullScreen: false
readonly property bool imageLargerThanWindow:
overallSize.width > window.width || overallSize.height > window.height
readonly property bool imageEqualToWindow:
overallSize.width == window.width &&
overallSize.height == window.height
readonly property int paintedWidth:
full.status === Image.Ready ?
full.animatedPaintedWidth || full.paintedWidth :
thumbnail.animatedPaintedWidth || thumbnail.paintedWidth
readonly property int paintedHeight:
full.status === Image.Ready ?
full.animatedPaintedHeight || full.paintedHeight :
thumbnail.animatedPaintedHeight || thumbnail.paintedHeight
signal openExternallyRequested()
function showFullScreen() {
if (activedFullScreen) return
window.showFullScreen()
popup.activedFullScreen = true
if (! imageLargerThanWindow) popup.alternateScaling = true
}
function exitFullScreen() {
if (! activedFullScreen) return
window.showNormal()
popup.activedFullScreen = false
if (! imageLargerThanWindow) popup.alternateScaling = false
}
function toggleFulLScreen() {
const isFull = window.visibility === Window.FullScreen
return isFull ? exitFullScreen() : showFullScreen()
}
margins: 0
background: null
onAboutToHide: exitFullScreen()
HFlickable {
id: flickable
implicitWidth: window.width
implicitHeight: window.height
contentWidth:
Math.max(window.width, popup.paintedWidth * thumbnail.scale)
contentHeight:
Math.max(window.height, popup.paintedHeight * thumbnail.scale)
ScrollBar.vertical: null
TapHandler {
acceptedButtons: Qt.LeftButton | Qt.RightButton
onTapped: popup.close()
gesturePolicy: TapHandler.ReleaseWithinBounds
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton
onWheel: {
if (wheel.modifiers !== Qt.ControlModifier) {
wheel.accepted = false
return
}
wheel.accepted = true
const add = wheel.angleDelta.y / 120 / 5
thumbnail.scale = Math.max(
0.1, Math.min(10, thumbnail.scale + add),
)
}
}
HMxcImage {
id: thumbnail
anchors.centerIn: parent
width:
popup.alternateScaling && popup.imageLargerThanWindow ?
popup.overallSize.width :
popup.alternateScaling ?
window.width :
Math.min(window.width, popup.overallSize.width)
height:
popup.alternateScaling && popup.imageLargerThanWindow ?
popup.overallSize.height :
popup.alternateScaling ?
window.height :
Math.min(window.height, popup.overallSize.height)
fillMode: HMxcImage.PreserveAspectFit
// Use only cachedPath if set, don't waste time refetching thumb
canUpdate: ! cachedPath
Behavior on width {
HNumberAnimation { overshoot: popup.alternateScaling? 2 : 3 }
}
Behavior on height {
HNumberAnimation { overshoot: popup.alternateScaling? 2 : 3 }
}
Binding on showProgressBar {
value: false
when: ! thumbnail.show
}
HNumberAnimation {
id: resetScaleAnimation
target: thumbnail
property: "scale"
from: thumbnail.scale
to: 1
overshoot: 2
}
Timer {
// Timer to not disappear before full image is done rendering
interval: 1000
running: full.status === HMxcImage.Ready
onTriggered: thumbnail.show = false
}
HMxcImage {
id: full
anchors.fill: parent
thumbnail: false
fillMode: parent.fillMode
// Image never loads at 0 opacity or with visible: false
opacity: status === HMxcImage.Ready ? 1 : 0.01
Behavior on opacity { HNumberAnimation {} }
}
Item {
anchors.centerIn: parent
width: popup.paintedWidth
height: popup.paintedHeight
TapHandler {
gesturePolicy: TapHandler.ReleaseWithinBounds
onTapped: {
thumbnail.scale === 1 ?
popup.alternateScaling = ! popup.alternateScaling :
resetScaleAnimation.start()
}
onDoubleTapped: popup.toggleFulLScreen()
}
TapHandler {
acceptedButtons: Qt.MiddleButton
gesturePolicy: TapHandler.ReleaseWithinBounds
onTapped: popup.openExternallyRequested()
}
TapHandler {
acceptedButtons: Qt.RightButton
gesturePolicy: TapHandler.ReleaseWithinBounds
onTapped: popup.close()
}
}
}
}
}

View File

@ -0,0 +1,81 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Window 2.12
import "../../Base"
HPopup {
id: popup
property string thumbnailTitle
property string thumbnailMxc
property string thumbnailPath: ""
property var thumbnailCryptDict
property string fullTitle
property string fullMxc
property var fullCryptDict
property size overallSize
property bool alternateScaling: false
property bool activedFullScreen: false
readonly property alias canvas: canvas
readonly property bool imageLargerThanWindow:
overallSize.width > window.width || overallSize.height > window.height
readonly property bool imageEqualToWindow:
overallSize.width == window.width &&
overallSize.height == window.height
readonly property int paintedWidth:
canvas.full.status === Image.Ready ?
canvas.full.animatedPaintedWidth || canvas.full.paintedWidth :
canvas.thumbnail.animatedPaintedWidth || canvas.thumbnail.paintedWidth
readonly property int paintedHeight:
canvas.full.status === Image.Ready ?
canvas.full.animatedPaintedHeight || canvas.full.paintedHeight :
canvas.thumbnail.animatedPaintedHeight || canvas.thumbnail.paintedHeight
signal openExternallyRequested()
function showFullScreen() {
if (activedFullScreen) return
window.showFullScreen()
popup.activedFullScreen = true
if (! imageLargerThanWindow) popup.alternateScaling = true
}
function exitFullScreen() {
if (! activedFullScreen) return
window.showNormal()
popup.activedFullScreen = false
if (! imageLargerThanWindow) popup.alternateScaling = false
}
function toggleFulLScreen() {
const isFull = window.visibility === Window.FullScreen
return isFull ? exitFullScreen() : showFullScreen()
}
margins: 0
background: null
onAboutToHide: exitFullScreen()
Item {
implicitWidth: window.width
implicitHeight: window.height
ViewerCanvas {
id: canvas
anchors.fill: parent
viewer: popup
}
}
}

View File

@ -0,0 +1,144 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
import QtQuick 2.12
import QtQuick.Controls 2.12
import "../../Base"
HFlickable {
property HPopup viewer
readonly property alias thumbnail: thumbnail
readonly property alias full: full
contentWidth:
Math.max(window.width, viewer.paintedWidth * thumbnail.scale)
contentHeight:
Math.max(window.height, viewer.paintedHeight * thumbnail.scale)
ScrollBar.vertical: null
TapHandler {
acceptedButtons: Qt.LeftButton | Qt.RightButton
onTapped: viewer.close()
gesturePolicy: TapHandler.ReleaseWithinBounds
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton
onWheel: {
if (wheel.modifiers !== Qt.ControlModifier) {
wheel.accepted = false
return
}
wheel.accepted = true
const add = wheel.angleDelta.y / 120 / 5
thumbnail.scale = Math.max(
0.1, Math.min(10, thumbnail.scale + add),
)
}
}
HMxcImage {
id: thumbnail
anchors.centerIn: parent
width:
viewer.alternateScaling && viewer.imageLargerThanWindow ?
viewer.overallSize.width :
viewer.alternateScaling ?
window.width :
Math.min(window.width, viewer.overallSize.width)
height:
viewer.alternateScaling && viewer.imageLargerThanWindow ?
viewer.overallSize.height :
viewer.alternateScaling ?
window.height :
Math.min(window.height, viewer.overallSize.height)
fillMode: HMxcImage.PreserveAspectFit
title: viewer.thumbnailTitle
mxc: viewer.thumbnailMxc
cachedPath: viewer.thumbnailPath
cryptDict: viewer.thumbnailCryptDict
// Use only cachedPath if set, don't waste time refetching thumb
canUpdate: ! cachedPath
Behavior on width {
HNumberAnimation { overshoot: viewer.alternateScaling? 2 : 3 }
}
Behavior on height {
HNumberAnimation { overshoot: viewer.alternateScaling? 2 : 3 }
}
Binding on showProgressBar {
value: false
when: ! thumbnail.show
}
HNumberAnimation {
id: resetScaleAnimation
target: thumbnail
property: "scale"
from: thumbnail.scale
to: 1
overshoot: 2
}
Timer {
// Timer to not disappear before full image is done rendering
interval: 1000
running: full.status === HMxcImage.Ready
onTriggered: thumbnail.show = false
}
HMxcImage {
id: full
anchors.fill: parent
thumbnail: false
fillMode: parent.fillMode
title: viewer.fullTitle
mxc: viewer.fullMxc
cryptDict: viewer.fullCryptDict
// Image never loads at 0 opacity or with visible: false
opacity: status === HMxcImage.Ready ? 1 : 0.01
Behavior on opacity { HNumberAnimation {} }
}
Item {
anchors.centerIn: parent
width: viewer.paintedWidth
height: viewer.paintedHeight
TapHandler {
gesturePolicy: TapHandler.ReleaseWithinBounds
onTapped: {
thumbnail.scale === 1 ?
viewer.alternateScaling = ! viewer.alternateScaling :
resetScaleAnimation.start()
}
onDoubleTapped: viewer.toggleFulLScreen()
}
TapHandler {
acceptedButtons: Qt.MiddleButton
gesturePolicy: TapHandler.ReleaseWithinBounds
onTapped: viewer.openExternallyRequested()
}
TapHandler {
acceptedButtons: Qt.RightButton
gesturePolicy: TapHandler.ReleaseWithinBounds
onTapped: viewer.close()
}
}
}
}