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 }