Add buttons to image viewer
This commit is contained in:
parent
595714f9f6
commit
a8e1ece1ea
2
TODO.md
2
TODO.md
|
@ -1,9 +1,9 @@
|
||||||
# TODO
|
# TODO
|
||||||
|
|
||||||
- Image viewer:
|
- Image viewer:
|
||||||
|
- stop timeline gif on ctrl+o
|
||||||
- open externally in context menu in timeline thumbnail
|
- open externally in context menu in timeline thumbnail
|
||||||
- hflickable support kinetic scrolling disabler and speed/decel settings
|
- hflickable support kinetic scrolling disabler and speed/decel settings
|
||||||
- buttons (include a working GIF play/pause)
|
|
||||||
- keyboard controls
|
- keyboard controls
|
||||||
|
|
||||||
- clipboard preview doesn't update when copied image changes until second time
|
- clipboard preview doesn't update when copied image changes until second time
|
||||||
|
|
|
@ -259,7 +259,6 @@ class Backend:
|
||||||
while True:
|
while True:
|
||||||
for client in self.clients.values():
|
for client in self.clients.values():
|
||||||
if client.healthy:
|
if client.healthy:
|
||||||
print( client, client.first_sync_done)
|
|
||||||
return client
|
return client
|
||||||
|
|
||||||
if failures and failures % 300 == 0:
|
if failures and failures % 300 == 0:
|
||||||
|
|
|
@ -17,6 +17,7 @@ Image {
|
||||||
property alias radius: roundMask.radius
|
property alias radius: roundMask.radius
|
||||||
property alias showProgressBar: progressBarLoader.active
|
property alias showProgressBar: progressBarLoader.active
|
||||||
property bool pause: ! window.settings.media.autoPlayGIF
|
property bool pause: ! window.settings.media.autoPlayGIF
|
||||||
|
property real speed: 1
|
||||||
|
|
||||||
readonly property int circleRadius:
|
readonly property int circleRadius:
|
||||||
Math.ceil(Math.max(image.width, image.height))
|
Math.ceil(Math.max(image.width, image.height))
|
||||||
|
@ -66,6 +67,7 @@ Image {
|
||||||
// but caching GIFs is expansive.
|
// but caching GIFs is expansive.
|
||||||
cache: ! Qt.resolvedUrl(source).startsWith("file://")
|
cache: ! Qt.resolvedUrl(source).startsWith("file://")
|
||||||
paused: ! visible || window.hidden || image.pause
|
paused: ! visible || window.hidden || image.pause
|
||||||
|
speed: image.speed
|
||||||
|
|
||||||
layer.enabled: image.radius !== 0
|
layer.enabled: image.radius !== 0
|
||||||
layer.effect: OpacityMask { maskSource: roundMask }
|
layer.effect: OpacityMask { maskSource: roundMask }
|
||||||
|
|
|
@ -19,8 +19,17 @@ HPopup {
|
||||||
|
|
||||||
property bool alternateScaling: false
|
property bool alternateScaling: false
|
||||||
property bool activedFullScreen: false
|
property bool activedFullScreen: false
|
||||||
|
property bool imagesPaused: false
|
||||||
|
property real imagesRotation: 0
|
||||||
|
property real animatedRotationTarget: 0
|
||||||
|
property real imagesSpeed: 1
|
||||||
|
property var availableSpeeds: [16, 8, 2, 1.75, 1.5, 1.25, 1, 0.75, 0.5]
|
||||||
|
|
||||||
readonly property alias canvas: canvas
|
readonly property alias canvas: canvas
|
||||||
|
readonly property alias buttons: buttons
|
||||||
|
|
||||||
|
readonly property bool isAnimated:
|
||||||
|
canvas.thumbnail.animated || canvas.full.animated
|
||||||
|
|
||||||
readonly property bool imageLargerThanWindow:
|
readonly property bool imageLargerThanWindow:
|
||||||
overallSize.width > window.width || overallSize.height > window.height
|
overallSize.width > window.width || overallSize.height > window.height
|
||||||
|
@ -57,7 +66,7 @@ HPopup {
|
||||||
if (! imageLargerThanWindow) popup.alternateScaling = false
|
if (! imageLargerThanWindow) popup.alternateScaling = false
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleFulLScreen() {
|
function toggleFullScreen() {
|
||||||
const isFull = window.visibility === Window.FullScreen
|
const isFull = window.visibility === Window.FullScreen
|
||||||
return isFull ? exitFullScreen() : showFullScreen()
|
return isFull ? exitFullScreen() : showFullScreen()
|
||||||
}
|
}
|
||||||
|
@ -68,6 +77,15 @@ HPopup {
|
||||||
|
|
||||||
onAboutToHide: exitFullScreen()
|
onAboutToHide: exitFullScreen()
|
||||||
|
|
||||||
|
HNumberAnimation {
|
||||||
|
target: popup
|
||||||
|
property: "imagesRotation"
|
||||||
|
from: popup.imagesRotation
|
||||||
|
to: popup.animatedRotationTarget
|
||||||
|
easing.type: Easing.OutCirc
|
||||||
|
onToChanged: restart()
|
||||||
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
implicitWidth: window.width
|
implicitWidth: window.width
|
||||||
implicitHeight: window.height
|
implicitHeight: window.height
|
||||||
|
@ -77,5 +95,13 @@ HPopup {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
viewer: popup
|
viewer: popup
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ViewerButtons {
|
||||||
|
id: buttons
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
width: Math.min(calculatedWidth, parent.width)
|
||||||
|
viewer: popup
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
90
src/gui/Popups/ImageViewerPopup/ViewerButtons.qml
Normal file
90
src/gui/Popups/ImageViewerPopup/ViewerButtons.qml
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
import QtQuick 2.12
|
||||||
|
import QtQuick.Window 2.12
|
||||||
|
import "../../Base"
|
||||||
|
|
||||||
|
HFlow {
|
||||||
|
property HPopup viewer
|
||||||
|
|
||||||
|
readonly property real calculatedWidth:
|
||||||
|
(closeButton.implicitWidth * visibleChildren.length) + theme.spacing
|
||||||
|
|
||||||
|
|
||||||
|
HButton {
|
||||||
|
id: playButton
|
||||||
|
icon.name: viewer.imagesPaused ? "image-play" : "image-pause"
|
||||||
|
toolTip.text: viewer.imagesPaused ? qsTr("Play") : qsTr("Pause")
|
||||||
|
onClicked: viewer.imagesPaused = ! viewer.imagesPaused
|
||||||
|
visible: viewer.isAnimated
|
||||||
|
}
|
||||||
|
|
||||||
|
HButton {
|
||||||
|
text: qsTr("%1x").arg(utils.round(viewer.imagesSpeed))
|
||||||
|
label.font.pixelSize: theme.fontSize.big
|
||||||
|
height: playButton.height
|
||||||
|
topPadding: 0
|
||||||
|
bottomPadding: 0
|
||||||
|
toolTip.text: qsTr("Change speed")
|
||||||
|
onClicked: speedMenu.popup()
|
||||||
|
visible: viewer.isAnimated
|
||||||
|
}
|
||||||
|
|
||||||
|
HButton {
|
||||||
|
icon.name: "image-rotate-left"
|
||||||
|
toolTip.text: qsTr("Rotate left")
|
||||||
|
autoRepeat: true
|
||||||
|
autoRepeatDelay: 20
|
||||||
|
autoRepeatInterval: theme.animationDuration * 3
|
||||||
|
onPressed: viewer.animatedRotationTarget -= 45
|
||||||
|
}
|
||||||
|
|
||||||
|
HButton {
|
||||||
|
icon.name: "image-rotate-right"
|
||||||
|
toolTip.text: qsTr("Rotate right")
|
||||||
|
autoRepeat: true
|
||||||
|
autoRepeatDelay: 20
|
||||||
|
autoRepeatInterval: theme.animationDuration * 3
|
||||||
|
onPressed: viewer.animatedRotationTarget += 45
|
||||||
|
}
|
||||||
|
|
||||||
|
HButton {
|
||||||
|
icon.name: "image-alt-scale-mode"
|
||||||
|
toolTip.text:
|
||||||
|
viewer.imageLargerThanWindow ?
|
||||||
|
qsTr("Expand to original size") :
|
||||||
|
qsTr("Expand to screen")
|
||||||
|
|
||||||
|
checked: viewer.alternateScaling
|
||||||
|
onClicked: viewer.alternateScaling = ! viewer.alternateScaling
|
||||||
|
}
|
||||||
|
|
||||||
|
HButton {
|
||||||
|
icon.name: "image-fullscreen"
|
||||||
|
toolTip.text: qsTr("Fullscreen")
|
||||||
|
checked: window.visibility === Window.FullScreen
|
||||||
|
onClicked: viewer.toggleFullScreen()
|
||||||
|
visible: Qt.application.supportsMultipleWindows
|
||||||
|
}
|
||||||
|
|
||||||
|
HButton {
|
||||||
|
id: closeButton // always visible
|
||||||
|
icon.name: "image-close"
|
||||||
|
toolTip.text: qsTr("Close")
|
||||||
|
onClicked: viewer.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
HMenu {
|
||||||
|
id: speedMenu
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: viewer.availableSpeeds
|
||||||
|
|
||||||
|
HMenuItem {
|
||||||
|
text: qsTr("%1x").arg(modelData)
|
||||||
|
onClicked: viewer.imagesSpeed = modelData
|
||||||
|
label.horizontalAlignment: HLabel.AlignHCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -68,6 +68,9 @@ HFlickable {
|
||||||
|
|
||||||
Math.min(window.height, viewer.overallSize.height)
|
Math.min(window.height, viewer.overallSize.height)
|
||||||
|
|
||||||
|
pause: viewer.imagesPaused
|
||||||
|
speed: viewer.imagesSpeed
|
||||||
|
rotation: viewer.imagesRotation
|
||||||
fillMode: HMxcImage.PreserveAspectFit
|
fillMode: HMxcImage.PreserveAspectFit
|
||||||
title: viewer.thumbnailTitle
|
title: viewer.thumbnailTitle
|
||||||
mxc: viewer.thumbnailMxc
|
mxc: viewer.thumbnailMxc
|
||||||
|
@ -109,6 +112,9 @@ HFlickable {
|
||||||
id: full
|
id: full
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
thumbnail: false
|
thumbnail: false
|
||||||
|
pause: viewer.imagesPaused
|
||||||
|
speed: viewer.imagesSpeed
|
||||||
|
rotation: viewer.imagesRotation
|
||||||
fillMode: parent.fillMode
|
fillMode: parent.fillMode
|
||||||
title: viewer.fullTitle
|
title: viewer.fullTitle
|
||||||
mxc: viewer.fullMxc
|
mxc: viewer.fullMxc
|
||||||
|
@ -131,7 +137,7 @@ HFlickable {
|
||||||
viewer.alternateScaling = ! viewer.alternateScaling :
|
viewer.alternateScaling = ! viewer.alternateScaling :
|
||||||
resetScaleAnimation.start()
|
resetScaleAnimation.start()
|
||||||
}
|
}
|
||||||
onDoubleTapped: viewer.toggleFulLScreen()
|
onDoubleTapped: viewer.toggleFullScreen()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
6
src/icons/thin/image-pause.svg
Normal file
6
src/icons/thin/image-pause.svg
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g stroke-width=".948329" transform="matrix(.99588888 0 0 .99588888 .04926 .049334)">
|
||||||
|
<path d="m8.928091 20.993272h-4v-17.9865437h4z"/>
|
||||||
|
<path d="m19.035955 3.0067283h-4v17.9865437h4z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 306 B |
3
src/icons/thin/image-play.svg
Normal file
3
src/icons/thin/image-play.svg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="m3 22v-20l18 10z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 124 B |
3
src/icons/thin/image-speed.svg
Normal file
3
src/icons/thin/image-speed.svg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="m15.91 13.34 2.636-4.026-.454-.406-3.673 3.099c-.675-.138-1.402.068-1.894.618-.736.823-.665 2.088.159 2.824s2.088.665 2.824-.159c.492-.55.615-1.295.402-1.95zm-3.91-10.646v-2.694h4v2.694c-1.439-.243-2.592-.238-4 0zm8.851 2.064 1.407-1.407 1.414 1.414-1.321 1.321c-.462-.484-.964-.927-1.5-1.328zm-18.851 4.242h8v2h-8zm-2 4h8v2h-8zm3 4h7v2h-7zm21-3c0 5.523-4.477 10-10 10-2.79 0-5.3-1.155-7.111-3h3.28c1.138.631 2.439 1 3.831 1 4.411 0 8-3.589 8-8s-3.589-8-8-8c-1.392 0-2.693.369-3.831 1h-3.28c1.811-1.845 4.321-3 7.111-3 5.523 0 10 4.477 10 10z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 650 B |
Loading…
Reference in New Issue
Block a user