Split ImageViewer components
This commit is contained in:
parent
9444225afa
commit
66a44b5251
|
@ -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,
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
81
src/gui/Popups/ImageViewerPopup/ImageViewerPopup.qml
Normal file
81
src/gui/Popups/ImageViewerPopup/ImageViewerPopup.qml
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
144
src/gui/Popups/ImageViewerPopup/ViewerCanvas.qml
Normal file
144
src/gui/Popups/ImageViewerPopup/ViewerCanvas.qml
Normal 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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user