From fdc06d81fd63d16b95d9a046c194a5d8878e8e81 Mon Sep 17 00:00:00 2001 From: miruka Date: Tue, 21 Jul 2020 17:34:45 -0400 Subject: [PATCH] Add info bar to image viewer --- TODO.md | 5 +- src/gui/Base/AutoDirectionLayout.qml | 2 + src/gui/Pages/Chat/Timeline/EventList.qml | 4 +- .../ImageViewerPopup/ImageViewerPopup.qml | 12 +++ .../Popups/ImageViewerPopup/ViewerButtons.qml | 14 +++ .../Popups/ImageViewerPopup/ViewerInfo.qml | 86 +++++++++++++++++++ 6 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 src/gui/Popups/ImageViewerPopup/ViewerInfo.qml diff --git a/TODO.md b/TODO.md index a5f813b7..d2c80451 100644 --- a/TODO.md +++ b/TODO.md @@ -1,9 +1,12 @@ # TODO - Image viewer: - - open externally in context menu in timeline thumbnail, also button + - auto-hide buttons & header when needed - hflickable: support kinetic scrolling disabler +- compress png in a thread +- ctrl+o: ignore mx-reply links +- verify upload cancellation - clipboard preview doesn't update when copied image changes until second time - Avatar tooltip can get displayed in front of presence menu - Use loading cursorShape diff --git a/src/gui/Base/AutoDirectionLayout.qml b/src/gui/Base/AutoDirectionLayout.qml index 2cd8ab7b..e73f28b4 100644 --- a/src/gui/Base/AutoDirectionLayout.qml +++ b/src/gui/Base/AutoDirectionLayout.qml @@ -7,6 +7,8 @@ HGridLayout { readonly property real summedImplicitWidth: utils.sumChildrenImplicitWidths(visibleChildren, columnSpacing) + readonly property bool vertical: flow === HGridLayout.TopToBottom + flow: width >= summedImplicitWidth ? diff --git a/src/gui/Pages/Chat/Timeline/EventList.qml b/src/gui/Pages/Chat/Timeline/EventList.qml index 695850da..26d57a52 100644 --- a/src/gui/Pages/Chat/Timeline/EventList.qml +++ b/src/gui/Pages/Chat/Timeline/EventList.qml @@ -406,7 +406,8 @@ Rectangle { // if forLink is empty, this must be a media event const title = - event.media_title || utils.urlFileName(event.media_url) + event.media_title || + utils.urlFileName(forLink || event.media_url) // The thumbnail/cached path will be the full GIF const fullMxc = @@ -423,6 +424,7 @@ Rectangle { fullTitle: title, fullMxc: fullMxc, fullCryptDict: JSON.parse(event.media_crypt_dict), + fullFileSize: event.media_size, overallSize: Qt.size( event.media_width || diff --git a/src/gui/Popups/ImageViewerPopup/ImageViewerPopup.qml b/src/gui/Popups/ImageViewerPopup/ImageViewerPopup.qml index ce41ff0a..3fe64652 100644 --- a/src/gui/Popups/ImageViewerPopup/ImageViewerPopup.qml +++ b/src/gui/Popups/ImageViewerPopup/ImageViewerPopup.qml @@ -15,6 +15,7 @@ HPopup { property string fullTitle property string fullMxc property var fullCryptDict + property int fullFileSize property size overallSize property bool alternateScaling: false @@ -25,6 +26,7 @@ HPopup { property real imagesSpeed: 1 property var availableSpeeds: [16, 8, 2, 1.75, 1.5, 1.25, 1, 0.75, 0.5] + readonly property alias info: info readonly property alias canvas: canvas readonly property alias buttons: buttons @@ -96,6 +98,16 @@ HPopup { viewer: popup } + ViewerInfo { + id: info + viewer: popup + width: parent.width + y: parent.width < buttons.width * 4 ? 0 : parent.height - height + maxTitleWidth: y === 0 ? -1 : buttons.x - buttons.width / 2 + + Behavior on y { HNumberAnimation {} } + } + ViewerButtons { id: buttons anchors.bottom: parent.bottom diff --git a/src/gui/Popups/ImageViewerPopup/ViewerButtons.qml b/src/gui/Popups/ImageViewerPopup/ViewerButtons.qml index 871a92e1..944074e0 100644 --- a/src/gui/Popups/ImageViewerPopup/ViewerButtons.qml +++ b/src/gui/Popups/ImageViewerPopup/ViewerButtons.qml @@ -6,14 +6,22 @@ import ".." import "../../Base" HFlow { + id: root + property HPopup viewer + property color backgroundsColor: + viewer.info.y === viewer.height - viewer.info.height ? + "transparent" : + theme.controls.button.background + readonly property real calculatedWidth: utils.sumChildrenImplicitWidths(visibleChildren) HButton { id: pause + backgroundColor: root.backgroundsColor icon.name: viewer.imagesPaused ? "image-play" : "image-pause" toolTip.text: viewer.imagesPaused ? qsTr("Play") : qsTr("Pause") onClicked: viewer.imagesPaused = ! viewer.imagesPaused @@ -26,6 +34,7 @@ HFlow { } HButton { + backgroundColor: root.backgroundsColor text: qsTr("%1x").arg(utils.round(viewer.imagesSpeed)) label.font.pixelSize: theme.fontSize.big height: pause.height @@ -58,6 +67,7 @@ HFlow { HButton { id: rotateLeft + backgroundColor: root.backgroundsColor icon.name: "image-rotate-left" toolTip.text: qsTr("Rotate left") autoRepeat: true @@ -73,6 +83,7 @@ HFlow { HButton { id: rotateRight + backgroundColor: root.backgroundsColor icon.name: "image-rotate-right" toolTip.text: qsTr("Rotate right") autoRepeat: true @@ -93,6 +104,7 @@ HFlow { HButton { id: expand + backgroundColor: root.backgroundsColor icon.name: "image-alt-scale-mode" toolTip.text: viewer.imageLargerThanWindow ? @@ -110,6 +122,7 @@ HFlow { HButton { id: fullScreen + backgroundColor: root.backgroundsColor icon.name: "image-fullscreen" toolTip.text: qsTr("Fullscreen") checked: window.visibility === Window.FullScreen @@ -124,6 +137,7 @@ HFlow { HButton { id: close // always visible + backgroundColor: root.backgroundsColor icon.name: "image-close" toolTip.text: qsTr("Close") onClicked: viewer.close() diff --git a/src/gui/Popups/ImageViewerPopup/ViewerInfo.qml b/src/gui/Popups/ImageViewerPopup/ViewerInfo.qml new file mode 100644 index 00000000..669ecec2 --- /dev/null +++ b/src/gui/Popups/ImageViewerPopup/ViewerInfo.qml @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later + +import QtQuick 2.12 +import QtQuick.Layouts 1.12 +import CppUtils 0.1 +import "../../Base" + +Rectangle { + property HPopup viewer + property int maxTitleWidth: -1 + + readonly property alias layout: layout + readonly property alias title: title + readonly property alias dimensions: dimensions + readonly property alias fileSize: fileSize + + + implicitHeight: Math.max(theme.baseElementsHeight, childrenRect.height) + color: utils.hsluv(0, 0, 0, 0.6) + + Behavior on implicitHeight { HNumberAnimation {} } + + AutoDirectionLayout { + id: layout + width: parent.width - theme.spacing * 2 + anchors.horizontalCenter: parent.horizontalCenter + columnSpacing: theme.spacing + + HLabel { + id: title + text: viewer.fullTitle + elide: HLabel.ElideMiddle + topPadding: theme.spacing / 2 + bottomPadding: topPadding + horizontalAlignment: + layout.vertical ? HLabel.AlignHCenter : HLabel.AlignLeft + + Layout.fillWidth: maxTitleWidth < 0 + Layout.maximumWidth: maxTitleWidth + } + + HSpacer { + visible: ! title.Layout.fillWidth + } + + HLabel { + id: dimensions + text: qsTr("%1 x %2") + .arg(viewer.canvas.full.implicitWidth) + .arg(viewer.canvas.full.implicitHeight) + + elide: HLabel.ElideRight + topPadding: theme.spacing / 2 + bottomPadding: topPadding + horizontalAlignment: HLabel.AlignHCenter + + Layout.fillWidth: layout.vertical + } + + HLabel { + id: fileSize + visible: viewer.fullFileSize !== 0 + text: CppUtils.formattedBytes(viewer.fullFileSize) + elide: HLabel.ElideRight + topPadding: theme.spacing / 2 + bottomPadding: topPadding + horizontalAlignment: HLabel.AlignHCenter + + Layout.fillWidth: layout.vertical + } + + HLoader { + source: "../../Base/HBusyIndicator.qml" + visible: Layout.preferredWidth > 0 + active: viewer.canvas.full.showProgressBar + + Layout.topMargin: theme.spacing / 2 + Layout.bottomMargin: Layout.topMargin + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: active ? height : 0 + Layout.preferredHeight: fileSize.implicitHeight - theme.spacing + + Behavior on Layout.preferredWidth { HNumberAnimation {} } + } + } +}