Skip to content

Commit

Permalink
make fullscreen gallery images zoomable
Browse files Browse the repository at this point in the history
  • Loading branch information
Marco Porsch committed Apr 8, 2014
1 parent 3c5eb7f commit 78a9a2b
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 71 deletions.
95 changes: 24 additions & 71 deletions src/qml/MediaGalleryView.qml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ Page {
ToolIcon {
iconId: 'toolbar-back'
onClicked: {
appWindow.pageStack.pop()
if (expanded)
expanded = !expanded
else
appWindow.pageStack.pop()
}
}

Expand Down Expand Up @@ -127,20 +130,30 @@ Page {
currentPage: galleryView.currentIndex + 1
}

Image {
ZoomableImage {
id: detailedDelegateImage
source: TMDB.image(imgType,
fullSize,
galleryView.galleryViewModel.get(galleryView.currentIndex).file_path,
{ app_locale: appLocale })
remoteSource: TMDB.image(imgType,
fullSize,
galleryView.galleryViewModel.get(galleryView.currentIndex).file_path,
{ app_locale: appLocale })
anchors {
top: detailedDelegateIndicator.bottom
topMargin: UIConstants.DEFAULT_MARGIN
left: parent.left
right: parent.right
bottom: parent.bottom
}
fillMode: Image.PreserveAspectFit

onSwipeLeft: {
galleryView.currentIndex = (galleryView.currentIndex + 1) %
galleryView.galleryViewModel.count
}
onSwipeRight: {
galleryView.currentIndex =
(galleryView.currentIndex - 1 +
galleryView.galleryViewModel.count) %
galleryView.galleryViewModel.count
}
}

ProgressBar {
Expand All @@ -152,65 +165,6 @@ Page {
value: detailedDelegateImage.progress
visible: detailedDelegateImage.status === Image.Loading
}

MouseArea {
id: detailedDelegateMouseArea
anchors.fill : parent
property bool swipeDone: false
property int startX
property int startY

Timer {
id: clickTimer
interval: 350
running: false
repeat: false
onTriggered: {
if (!parent.swipeDone) {
galleryView.expanded = !galleryView.expanded
}
parent.swipeDone = false
}
}

onClicked: {
// There's a bug in Qt Components emitting a clicked signal
// when a double click is done.
clickTimer.start()
}

onPressed: {
startX = mouse.x
startY = mouse.y
}

onReleased: {
var deltaX = mouse.x - startX
var deltaY = mouse.y - startY

// Swipe is only allowed when we're not zoomed in
if (Math.abs(deltaX) > 50 || Math.abs(deltaY) > 50) {
swipeDone = true

if (deltaX > 30) {
detailedDelegate.swipeRight()
} else if (deltaX < -30) {
detailedDelegate.swipeLeft()
}
}
}
}

function swipeRight() {
galleryView.currentIndex = (galleryView.currentIndex - 1 +
galleryView.galleryViewModel.count) %
galleryView.galleryViewModel.count
}

function swipeLeft() {
galleryView.currentIndex = (galleryView.currentIndex + 1) %
galleryView.galleryViewModel.count
}
}
}

Expand Down Expand Up @@ -247,13 +201,12 @@ Page {
color: '#2d2d2d'
anchors.fill: parent

Image {
ZoomableImage {
id: savingImage
source: saveImageSheet.visible ?
saveImageSheet.imageUrl :
''
remoteSource: saveImageSheet.visible ?
saveImageSheet.imageUrl :
''
anchors.fill: parent
fillMode: Image.PreserveAspectFit
}

ProgressBar {
Expand Down
145 changes: 145 additions & 0 deletions src/qml/ZoomableImage.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/**************************************************************************
* Butaca
* Copyright (C) 2011 - 2012 Simon Pena <spena@igalia.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
**************************************************************************/

import QtQuick 1.1
import com.nokia.meego 1.0
import com.nokia.extras 1.1

// Zoom features support (both pinch gesture and double click) taken from xkcdMeegoReader

Flickable {
id: flickable
clip: true
contentHeight: imageContainer.height
contentWidth: imageContainer.width
onHeightChanged: image.calculateSize()

property alias source: image.source
property alias status: image.status
property alias progress: image.progress
property string remoteSource: ''
signal swipeLeft()
signal swipeRight()

onRemoteSourceChanged: {
image.source = remoteSource

// in case it's cached
if (image.status == Image.Ready)
image.calculateSize()
}

Item {
id: imageContainer
width: Math.max(image.width * image.scale, flickable.width)
height: Math.max(image.height * image.scale, flickable.height)

Image {
id: image
property real prevScale
smooth: !flickable.movingVertically
anchors.centerIn: parent
fillMode: Image.PreserveAspectFit

function calculateSize() {
scale = Math.min(flickable.width / width, flickable.height / height) * 0.98;
pinchArea.minScale = scale;
prevScale = Math.min(scale, 1);
}

onScaleChanged: {
if ((width * scale) > flickable.width) {
var xoff = (flickable.width / 2 + flickable.contentX) * scale / prevScale;
flickable.contentX = xoff - flickable.width / 2;
}
if ((height * scale) > flickable.height) {
var yoff = (flickable.height / 2 + flickable.contentY) * scale / prevScale;
flickable.contentY = yoff - flickable.height / 2;
}

prevScale = scale;
}

onStatusChanged: {
if (status == Image.Ready) {
calculateSize();
} else if (status == Image.Error &&
image.source != remoteSource) {
image.source = remoteSource
}
}
}
}

PinchArea {
id: pinchArea
property real minScale: 1.0
property real lastScale: 1.0
anchors.fill: parent

pinch.target: image
pinch.minimumScale: minScale
pinch.maximumScale: 3.0

onPinchFinished: flickable.returnToBounds()
}

MouseArea {
anchors.fill : parent
property bool doubleClicked: false
property int startX
property int startY
property real startScale: pinchArea.minScale

onDoubleClicked: {
mouse.accepted = true

if (image.scale > pinchArea.minScale) {
image.scale = pinchArea.minScale
flickable.returnToBounds()
} else {
image.scale = 2.3
}
}

onPressed: {
startX = (mouse.x / image.scale)
startY = (mouse.y / image.scale)
startScale = image.scale
}

onReleased: {
if (image.scale === startScale) {
var deltaX = (mouse.x / image.scale) - startX
var deltaY = (mouse.y / image.scale) - startY

// Swipe is only allowed when we're not zoomed in
if (image.scale == pinchArea.minScale &&
(Math.abs(deltaX) > 50 || Math.abs(deltaY) > 50)) {

if (deltaX > 30) {
flickable.swipeRight()
} else if (deltaX < -30) {
flickable.swipeLeft()
}
}
}
}
}
}
1 change: 1 addition & 0 deletions src/res.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
<file>l10n/butaca.pt.qm</file>
<file>qml/MovieView.qml</file>
<file>qml/MediaGalleryView.qml</file>
<file>qml/ZoomableImage.qml</file>
<file>qml/MyGalleryPreviewer.qml</file>
<file>qml/MyModelFlowPreviewer.qml</file>
<file>qml/MyTextExpander.qml</file>
Expand Down
1 change: 1 addition & 0 deletions src/src.pro
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ OTHER_FILES += \
resources/tmdb-logo.png \
resources/indicator-rating-inverted-star.svg \
qml/MediaGalleryView.qml \
qml/ZoomableImage.qml \
qml/MyGalleryPreviewer.qml \
qml/MyModelFlowPreviewer.qml \
qml/MyTextExpander.qml \
Expand Down

0 comments on commit 78a9a2b

Please sign in to comment.