Warning, /graphics/okular/mobile/components/DocumentView.qml is written in an unsupported language. File is not indexed.

0001 /*
0002     SPDX-FileCopyrightText: 2015 Marco Martin <mart@kde.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 import QtQuick 2.15
0008 import QtQuick.Controls 2.15 as QQC2
0009 import org.kde.okular 2.0
0010 import "./private"
0011 
0012 /**
0013  * A touchscreen optimized view for a document
0014  * 
0015  * It supports changing pages by a swipe gesture, pinch zoom
0016  * and flicking to scroll around
0017  */
0018 QQC2.ScrollView {
0019     id: root
0020     property DocumentItem document
0021     property PageItem page: mouseArea.currPageDelegate.pageItem
0022     signal clicked
0023     
0024     //NOTE: on some themes it tries to set the flickable to interactive
0025     //but we need it always non interactive as we need to manage
0026     //dragging by ourselves
0027     Component.onCompleted: flick.interactive = false
0028     Flickable {
0029         id: flick
0030         interactive: false
0031         onWidthChanged: resizeTimer.restart()
0032         onHeightChanged: resizeTimer.restart()
0033         
0034         Component.onCompleted: {
0035             flick.contentWidth = flick.width
0036             flick.contentHeight = flick.width / mouseArea.currPageDelegate.pageRatio
0037         }
0038         Connections {
0039             target: root.document
0040             function onUrlChanged() {
0041                 resizeTimer.restart()
0042             }
0043         }
0044         Timer {
0045             id: resizeTimer
0046             interval: 250
0047             onTriggered: {
0048                 flick.contentWidth = flick.width
0049                 flick.contentHeight = flick.width / mouseArea.currPageDelegate.pageRatio
0050             }
0051         }
0052 
0053         PinchArea {
0054             width: flick.contentWidth
0055             height: flick.contentHeight
0056 
0057             property real initialWidth
0058             property real initialHeight
0059 
0060             onPinchStarted: {
0061                 initialWidth = mouseArea.currPageDelegate.implicitWidth * mouseArea.currPageDelegate.scaleFactor
0062                 initialHeight = mouseArea.currPageDelegate.implicitHeight * mouseArea.currPageDelegate.scaleFactor
0063             }
0064 
0065             onPinchUpdated: {
0066                 // adjust content pos due to drag
0067                 flick.contentX += pinch.previousCenter.x - pinch.center.x
0068                 flick.contentY += pinch.previousCenter.y - pinch.center.y
0069 
0070                 // resize content
0071                 //use the scale property during pinch, for speed reasons
0072                 if (initialHeight * pinch.scale > flick.height &&
0073                     initialHeight * pinch.scale < flick.height * 3) {
0074                     mouseArea.scale = pinch.scale;
0075                 }
0076                 resizeTimer.stop();
0077                 flick.returnToBounds();
0078             }
0079             onPinchFinished: {
0080                 flick.resizeContent(Math.max(flick.width+1, initialWidth * mouseArea.scale), Math.max(flick.height, initialHeight * mouseArea.scale), pinch.center);
0081                 mouseArea.scale = 1;
0082 
0083                 resizeTimer.stop()
0084                 flick.returnToBounds();
0085             }
0086             MouseArea {
0087                 id: mouseArea
0088                 width: parent.width
0089                 height: parent.height
0090 
0091                 property real oldMouseX
0092                 property real oldMouseY
0093                 property real startMouseX
0094                 property real startMouseY
0095                 property bool incrementing: true
0096                 property Item currPageDelegate: page1
0097                 property Item prevPageDelegate: page2
0098                 property Item nextPageDelegate: page3
0099 
0100                 onPressed: {
0101                     var pos = mapToItem(flick, mouse.x, mouse.y);
0102                     startMouseX = oldMouseX = pos.x;
0103                     startMouseY = oldMouseY = pos.y;
0104                 }
0105                 onPositionChanged: {
0106                     var pos = mapToItem(flick, mouse.x, mouse.y);
0107 
0108                     flick.contentY = Math.max(0, Math.min(flick.contentHeight - flick.height, flick.contentY - (pos.y - oldMouseY)));
0109 
0110                     if ((pos.x - oldMouseX > 0 && flick.atXBeginning) ||
0111                         (pos.x - oldMouseX < 0 && flick.atXEnd)) {
0112                         currPageDelegate.x += pos.x - oldMouseX;
0113                         mouseArea.incrementing = currPageDelegate.x <= 0;
0114                     } else {
0115                         flick.contentX = Math.max(0, Math.min(flick.contentWidth - flick.width, flick.contentX - (pos.x - oldMouseX)));
0116                     }
0117 
0118                     oldMouseX = pos.x;
0119                     oldMouseY = pos.y;
0120                 }
0121                 onReleased: {
0122                     if (root.document.currentPage > 0 &&
0123                         currPageDelegate.x > width/6) {
0124                         switchAnimation.running = true;
0125                     } else if (root.document.currentPage < document.pageCount-1 &&
0126                         currPageDelegate.x < -width/6) {
0127                         switchAnimation.running = true;
0128                     } else {
0129                         resetAnim.running = true;
0130                     }
0131                 }
0132                 onCanceled: {
0133                     resetAnim.running = true;
0134                 }
0135                 onDoubleClicked: {
0136                     flick.contentWidth = flick.width
0137                     flick.contentHeight = flick.width / mouseArea.currPageDelegate.pageRatio
0138                 }
0139                 onClicked: {
0140                     var pos = mapToItem(flick, mouse.x, mouse.y);
0141                     if (Math.abs(startMouseX - pos.x) < 20 &&
0142                         Math.abs(startMouseY - pos.y) < 20) {
0143                         root.clicked();
0144                     }
0145                 }
0146                 onWheel: {
0147                     if (wheel.modifiers & Qt.ControlModifier) {
0148                         //generate factors between 0.8 and 1.2
0149                         var factor = (((wheel.angleDelta.y / 120)+1) / 5 )+ 0.8;
0150 
0151                         var newWidth = flick.contentWidth * factor;
0152                         var newHeight = flick.contentHeight * factor;
0153 
0154                         if (newWidth < flick.width || newHeight < flick.height ||
0155                             newHeight > flick.height * 3) {
0156                             return;
0157                         }
0158 
0159                         flick.resizeContent(newWidth, newHeight, Qt.point(wheel.x, wheel.y));
0160                         flick.returnToBounds();
0161                         resizeTimer.stop();
0162                     } else {
0163                         flick.contentY = Math.min(flick.contentHeight-flick.height, Math.max(0, flick.contentY - wheel.angleDelta.y));
0164                     }
0165                 }
0166 
0167                 PageView {
0168                     id: page1
0169                     document: root.document
0170                     z: 2
0171                 }
0172                 PageView {
0173                     id: page2
0174                     document: root.document
0175                     z: 1
0176                 }
0177                 PageView {
0178                     id: page3
0179                     document: root.document
0180                     z: 0
0181                 }
0182 
0183                     
0184                 Binding {
0185                     target: mouseArea.currPageDelegate
0186                     property: "pageNumber"
0187                     value: root.document.currentPage
0188                 }
0189                 Binding {
0190                     target: mouseArea.currPageDelegate
0191                     property: "visible"
0192                     value: true
0193                 }
0194 
0195                 Binding {
0196                     target: mouseArea.prevPageDelegate
0197                     property: "pageNumber"
0198                     value: root.document.currentPage - 1
0199                 }
0200                 Binding {
0201                     target: mouseArea.prevPageDelegate
0202                     property: "visible"
0203                     value: !mouseArea.incrementing && root.document.currentPage > 0
0204                 }
0205 
0206                 Binding {
0207                     target: mouseArea.nextPageDelegate
0208                     property: "pageNumber"
0209                     value: root.document.currentPage + 1
0210                 }
0211                 Binding {
0212                     target: mouseArea.nextPageDelegate
0213                     property: "visible"
0214                     value: mouseArea.incrementing && root.document.currentPage < document.pageCount-1
0215                 }
0216                 
0217                 SequentialAnimation {
0218                     id: switchAnimation
0219                     ParallelAnimation {
0220                         NumberAnimation {
0221                             target: flick
0222                             properties: "contentY"
0223                             to: 0
0224                             easing.type: Easing.InQuad
0225                             //hardcoded number, we would need units from kirigami
0226                             //which cannot depend from here
0227                             duration: 250
0228                         }
0229                         NumberAnimation {
0230                             target: mouseArea.currPageDelegate
0231                             properties: "x"
0232                             to: mouseArea.incrementing ? -mouseArea.currPageDelegate.width : mouseArea.currPageDelegate.width
0233                             easing.type: Easing.InQuad
0234                             //hardcoded number, we would need units from kirigami
0235                             //which cannot depend from here
0236                             duration: 250
0237                         }
0238                     }
0239                     ScriptAction {
0240                         script: {
0241                             mouseArea.currPageDelegate.z = 0;
0242                             mouseArea.prevPageDelegate.z = 1;
0243                             mouseArea.nextPageDelegate.z = 2;
0244                         }
0245                     }
0246                     ScriptAction {
0247                         script: {
0248                             mouseArea.currPageDelegate.x = 0
0249                             var oldCur = mouseArea.currPageDelegate;
0250                             var oldPrev = mouseArea.prevPageDelegate;
0251                             var oldNext = mouseArea.nextPageDelegate;
0252 
0253                             if (mouseArea.incrementing) {
0254                                 root.document.currentPage++;
0255                                 mouseArea.currPageDelegate = oldNext;
0256                                 mouseArea.prevPageDelegate = oldCur;
0257                                 mouseArea. nextPageDelegate = oldPrev;
0258                             } else {
0259                                 root.document.currentPage--;
0260                                 mouseArea.currPageDelegate = oldPrev;
0261                                 mouseArea.nextPageDelegate = oldCur;
0262                                 mouseArea.prevPageDelegate = oldNext;
0263                             }
0264                             mouseArea.currPageDelegate.z = 2;
0265                             mouseArea.prevPageDelegate.z = 1;
0266                             mouseArea.nextPageDelegate.z = 0;
0267                         }
0268                     }
0269                 }
0270                 NumberAnimation {
0271                     id: resetAnim
0272                     target: mouseArea.currPageDelegate
0273                     properties: "x"
0274                     to: 0
0275                     easing.type: Easing.InQuad
0276                     duration: 250
0277                 }
0278             }
0279         }
0280     }
0281 }