diff --git a/amberpdfqmlplugin/PdfView.qml b/amberpdfqmlplugin/PdfView.qml index 546338133261cf04c30aefd3852f98b3faf843d8..0f060202ca65448ffaf4170a9eda3738eb49c080 100644 --- a/amberpdfqmlplugin/PdfView.qml +++ b/amberpdfqmlplugin/PdfView.qml @@ -43,6 +43,7 @@ Rectangle { property alias flickable: viewFlick property bool pinchingActive: false property int lastSavedPdfViewZCoordinate: 0 + property alias scroll: viewFlick.quickScroll property var painter: paintArea property string lineColor: "red" @@ -165,7 +166,10 @@ Rectangle { function goToNextPage() { if (isScrolling) return - scrollToPage(currentIndex + 1) + if (currentIndex === maxPageIndex) + scrollToPage(minPageIndex) + else + scrollToPage(currentIndex + 1) } function goToPreviousPage() { @@ -322,7 +326,10 @@ Rectangle { } onItemScaleChanged: root.correctPosition() onClickedUrl: root.clickedUrl(url) - onClickedGoToPage: root.correctPosition() + onClickedGoToPage: { + root.correctPosition(); + viewFlick.holdViewAtPage(); + } onNoteActivated: root.noteActivate(noteText, author, pageIndex, annotationId, color, noteType) onDocumentSaved: root.documentSaved(saveStatus) onNoteRemoved: root.noteRemoved(pageIndex, noteId, result) @@ -341,7 +348,6 @@ Rectangle { property real minimumItemScale: fixedScaleValues[0] property real maximumPinchScale: root.drawMode ? 3.5 : 6.0 property real storedRootContentPosition: 0 - property real previousContentX: 0 property int previousPageIndex: 0 property real standartMaxVelocity: 1 @@ -375,20 +381,33 @@ Rectangle { function holdViewAtPage() { var itemScale = pdfView.itemScale; var scaledPageWidth = pdfView.getActualPageWidth(currentIndex) * itemScale; + var scaledPageHeight = pdfView.getActualPageHeight(currentIndex) * itemScale; var scaledSpacing = pageSpacing * itemScale; var viewWidth = width; + var viewHeight = height; - var pageStartX = currentIndex * (scaledPageWidth + scaledSpacing); + var pageStartX = pdfView.orientation == Qt.Horizontal ? currentIndex * (scaledPageWidth + scaledSpacing) : 0; var pageEndX = pageStartX + scaledPageWidth; + var pageStartY = pdfView.orientation == Qt.Vertical ? currentIndex * (scaledPageHeight + scaledSpacing) : 0; + var pageEndY = pageStartY + scaledPageHeight; + + var verticalGap = pdfView.orientation == Qt.Vertical ? Math.max(viewHeight * itemScale - scaledPageHeight, 0): 0 var newLeftEdge = contentX; var newRightEdge = contentX + viewWidth; + var newTopEdge = contentY; + var newBottomEdge = contentY + viewHeight; if (newLeftEdge < pageStartX) { contentX = pageStartX; } else if (newRightEdge > pageEndX) { contentX = pageEndX - viewWidth; } + if (newTopEdge < pageStartY - verticalGap - 1) { + contentY = pageStartY - verticalGap; + } else if (newBottomEdge > pageEndY + verticalGap + 1) { + contentY = pageEndY - viewHeight + verticalGap; + } } contentHeight: Math.max(height, (pdfView.orientation === Qt.Vertical @@ -409,6 +428,10 @@ Rectangle { pdfView.contentY = contentY } onContentXChanged: { + if (orientation == Qt.Vertical && contentX > viewFlick.contentWidth) { + contentX = pdfView.contentX; + return; + } if (viewPositionBlocker.running) return @@ -417,48 +440,49 @@ Rectangle { onMovementStarted: { if (!isPagedView) return; - previousPageIndex = currentIndex; - previousContentX = contentX; } - onMovementEnded: { + onMovementEnded: scrollToPageIfOverscrolled() + + function scrollToPageIfOverscrolled() { if (!isPagedView) return; + var itemScale = pdfView.itemScale; - var scaledPageWidth = pdfView.getActualPageWidth(currentIndex) * itemScale; + + var scaledPageSize = (orientation == Qt.Horizontal ? pdfView.getActualPageWidth(currentIndex) : pdfView.getActualPageHeight(currentIndex)) * itemScale; var scaledSpacing = pageSpacing * itemScale; - var viewWidth = width; + var viewSize = orientation == Qt.Horizontal ? width : height; + var verticalGap = (orientation == Qt.Vertical ? Math.max((viewSize - scaledPageSize) / 2, 0) : 0) - var pageStartX = previousPageIndex * (scaledPageWidth + scaledSpacing); - var pageEndX = pageStartX + scaledPageWidth; + var pageStart = previousPageIndex * (scaledPageSize + scaledSpacing); + var pageEnd = pageStart + scaledPageSize; - var leftEdgeX = contentX; - var rightEdgeX = contentX + viewWidth; + var backEdge = orientation == Qt.Horizontal ? contentX : contentY; + var frontEdge = backEdge + viewSize; - var overscrollLeft = pageStartX - leftEdgeX; - var overscrollRight = rightEdgeX - pageEndX; + var overscrollBack = pageStart - backEdge; + var overscrollFront = frontEdge - pageEnd - verticalGap; - var threshold = 0.3 * viewWidth; - if (root.deviceOrientation !== Orientation.Portrait) { - threshold = 0.15 * viewWidth; + var threshold = (viewSize + verticalGap) * 0.3; + if (root.deviceOrientation !== Orientation.Portrait && orientation == Qt.Horizontal + || root.deviceOrientation !== Orientation.Landscape && orientation == Qt.Vertical) { + threshold /= 2; } - - if (overscrollRight > threshold) { + if (overscrollFront > threshold) { scrollToPage(previousPageIndex + 1); return; } - - if (overscrollLeft > threshold) { + if (overscrollBack > threshold) { scrollToPage(previousPageIndex - 1); return; } - - if (overscrollRight > 0) { - scrollAnimation.to = pageEndX - viewWidth; + if (overscrollFront > 0) { + scrollAnimation.to = pageEnd - Math.min(viewSize, scaledPageSize); scrollAnimation.start(); - } else if (overscrollLeft > 0) { - scrollAnimation.to = pageStartX; + } else if (overscrollBack > 0) { + scrollAnimation.to = pageStart; scrollAnimation.start(); } } @@ -498,7 +522,7 @@ Rectangle { target: viewFlick duration: 100 - property: "contentX" + property: orientation == Qt.Horizontal ? "contentX" : "contentY" } Timer { @@ -532,6 +556,8 @@ Rectangle { viewFlick.cancelFlick() pinching = true startScale = pdfView.itemScale + + viewFlick.previousPageIndex = root.currentIndex; } onPinchUpdated: { viewFlick.scaleAroundPoint(pinch.center, @@ -543,8 +569,10 @@ Rectangle { paintArea.scale = pdfView.itemScale / startScale; updateBoundRectPosition(); viewFlick.returnToBounds(); - viewFlick.returnToBounds() afterPinchDelayTimer.start(); + if (pdfView.itemScale == 1) { + viewFlick.scrollToPageIfOverscrolled(); + } } Timer { diff --git a/amberpdfqmlplugin/src/pdfview.cpp b/amberpdfqmlplugin/src/pdfview.cpp index 06783a1eec29ae66680c9daa1d073a8d4e59cb48..67c94b3ecb5b178b378231b6b8d0f46e5abee758 100644 --- a/amberpdfqmlplugin/src/pdfview.cpp +++ b/amberpdfqmlplugin/src/pdfview.cpp @@ -34,7 +34,7 @@ PdfView::PdfView(QQuickItem *parent) , m_contentX(-1) , m_moveDirection(-1) , m_paintedItemsSize(-1) - , m_currentIndex(-1) + , m_currentIndex(0) , m_catchBound(0) , m_orientation(Qt::Vertical) , m_itemScale(1.0) @@ -760,7 +760,7 @@ void PdfView::setContentX(qreal contentX) if (qFuzzyCompare(double(m_contentX), double(contentX))) return; - if (m_orientation == Qt::Vertical) + if (m_orientation == Qt::Horizontal) m_moveDirection = m_contentX - contentX; m_contentX = contentX; @@ -901,17 +901,30 @@ void PdfView::scrollViewToIndex(int index) } auto pagePosition = m_mapper->actualPagePosition(index); - - QPropertyAnimation *anim = new QPropertyAnimation(this, "contentX"); + QPropertyAnimation *anim; + if (m_orientation == Qt::Horizontal) { + anim = new QPropertyAnimation(this, "contentX"); + anim->setStartValue(this->contentX()); + if (this->contentX() > pagePosition.start * m_itemScale) + anim->setEndValue((pagePosition.end - m_pageSpacing) * m_itemScale - width()); + else + anim->setEndValue(pagePosition.start * m_itemScale); + } else { + anim = new QPropertyAnimation(this, "contentY"); + anim->setStartValue(this->contentY()); + if (this->contentY() > pagePosition.start * m_itemScale) { + if ((pagePosition.end - pagePosition.start - m_pageSpacing) * m_itemScale > height()) { + anim->setEndValue((pagePosition.end - m_pageSpacing) * m_itemScale - height()); + } else { + anim->setEndValue(pagePosition.start * m_itemScale); + } + } else { + anim->setEndValue(pagePosition.start * m_itemScale); + } + } anim->setDuration(200); - anim->setStartValue(this->contentX()); - if (this->contentX() > pagePosition.start * m_itemScale) - anim->setEndValue((pagePosition.end - m_pageSpacing) * m_itemScale - width()); - else - anim->setEndValue(pagePosition.start * m_itemScale); anim->start(QAbstractAnimation::DeleteWhenStopped); connect(anim, &QVariantAnimation::finished, this, &PdfView::pageSwapAnimationEnded); - m_timer->start(1300); } @@ -924,13 +937,13 @@ void PdfView::setOrientation(Qt::Orientation orientation) m_orientation = orientation; m_mapper->setOrientation(m_orientation); - positionViewAtIndex(currentIndex); emit orientationChanged(m_orientation); - if (orientation == Qt::Horizontal && m_itemScale < 1) { + if (m_itemScale < 1) { setItemScale(1); } else { _positionPages(); } + positionViewAtIndex(currentIndex); } void PdfView::setItemScale(qreal itemScale) @@ -949,15 +962,15 @@ void PdfView::setItemScale(qreal itemScale) void PdfView::scaleAroundPoint(const QPointF ¢er, qreal newScale) { - m_contentX -= center.x() - (center.x() / (m_contentWidth * m_itemScale)) * (m_contentWidth * newScale); - m_contentY -= center.y() - (center.y() / (m_contentHeight * m_itemScale)) * (m_contentHeight * newScale); - m_itemScale = newScale; + qreal verticalGap = m_isPagedView && m_orientation == Qt::Vertical ? qMax(float(height() - getActualPageHeight(m_currentIndex) * qMax(m_itemScale, newScale)), 0.0f) : 0; + qreal coef = qMax(float(height() / (height() - getActualPageHeight(m_currentIndex))), 0.0f) / qMin(m_itemScale, newScale); + m_contentX -= center.x() * ( 1 - newScale / m_itemScale); + m_contentY -= (center.y() - coef * verticalGap) * ( 1 - newScale / m_itemScale); - _positionPages(); + setItemScale(newScale); emit contentXChanged(m_contentX); emit contentYChanged(m_contentY); - emit itemScaleChanged(m_itemScale); } void PdfView::clicked(const QPointF &point) @@ -1282,6 +1295,7 @@ void PdfView::setPageSpacing(qreal pageSpacing) return; m_pageSpacing = pageSpacing; + m_mapper->setSpacing(m_pageSpacing); emit pageSpacingChanged(m_pageSpacing); } @@ -1324,6 +1338,16 @@ void PdfView::_updateContentSize() void PdfView::_positionPages() { + if (m_isPagedView) { + if (m_orientation == Qt::Horizontal) { + setPageSpacing(width() * 1.3); + } else { + setPageSpacing(height() * 1.3); + } + } else { + setPageSpacing(SPACING_DEFAULT_VALUE); + } + auto paintStart = m_mapper->spacing(); if (m_isPagedView) @@ -1351,7 +1375,8 @@ void PdfView::_positionPages() auto pagePosition = m_mapper->actualPagePosition(pageIndex); if (m_orientation == Qt::Vertical) { - page->setY(paintStart - (qMax(0.0f, float(m_contentY)) - pagePosition.start * m_itemScale)); + page->setY(paintStart - (qMax(0.0f, float(m_contentY)) - pagePosition.start * m_itemScale) + + (m_isPagedView ? (qMax(float(height() - page->height() * m_itemScale), 0.0f)) / 2.0f : 0)); if (page->width() <= width()) page->setX((width() - page->width()) / 2.0f); @@ -1602,17 +1627,11 @@ void PdfView::_updateCurrentIndex() auto page = m_pages.value(pageIndex); if (page == nullptr) continue; - - if (m_orientation == Qt::Vertical) { - if (m_catchBound >= page->y() && m_catchBound < page->y() + page->height()) { - if (m_currentIndex != pageIndex) { - newCurrentIndex = pageIndex; - } - } - } else { - if (m_catchBound >= page->x() && m_catchBound < page->x() + page->width()) { - if (m_currentIndex != pageIndex) - newCurrentIndex = pageIndex; + if ((m_orientation == Qt::Vertical && height() / 2 >= page->y() - m_pageSpacing / 2 && height() / 2 < page->y() + page->height() + m_pageSpacing / 2) || + (m_orientation == Qt::Horizontal && width() / 2 >= page->x() - m_pageSpacing / 2 && width() / 2 < page->x() + page->width() + m_pageSpacing / 2)) { + if (m_currentIndex != pageIndex) { + newCurrentIndex = pageIndex; + break; } } } @@ -1654,16 +1673,16 @@ void PdfView::_processActivatedAnnotation(QSharedPointer annotat {width(), height()}, m_orientation, m_itemScale); - auto pageRate = targetPageSize.width() / pageGeometry.width(); - QPointF linkOnPagePosition(pageCoordinate.x() * pageRate, - (pageGeometry.height() - pageCoordinate.y()) * pageRate); + m_currentIndex = pageIndex; + emit currentIndexChanged(m_currentIndex); auto pagePosition = m_mapper->actualPagePosition(pageIndex); if (m_orientation == Qt::Vertical) { if (pageCoordinate.y() <= 0) { positionViewAtIndex(pageIndex); } else { - setContentY((pagePosition.start + (pageGeometry.height() - pageCoordinate.y()) * pageRate) * m_itemScale); + auto pageRate = targetPageSize.width() / pageGeometry.width(); + setContentY(pagePosition.start * m_itemScale + (pageGeometry.height() - pageCoordinate.y()) * pageRate); } } else { setContentX(pagePosition.start * m_itemScale); @@ -1757,9 +1776,11 @@ void PdfView::setIsPagedView(bool newIsPagedView) if (m_isPagedView == newIsPagedView) return; m_isPagedView = newIsPagedView; - + auto currentIndex = m_currentIndex; m_mapper->setIsPagedView(newIsPagedView); emit isPagedViewChanged(newIsPagedView); + _positionPages(); + scrollViewToIndex(currentIndex); } void PdfView::_preparePages() @@ -1861,8 +1882,9 @@ void PdfView::_preparePages() needPositioning = true; } - if (needPositioning) + if (needPositioning) { _positionPages(); + } } void PdfView::_preparePageChecker(PdfPageContainer *page, int pageIndex) diff --git a/application/qml/pages/ContentPage.qml b/application/qml/pages/ContentPage.qml index 3d857fcb1dab14316475ea55b4d076d77f066084..ed602c6f9474221acffbfc244f5507aa5fec4bce 100644 --- a/application/qml/pages/ContentPage.qml +++ b/application/qml/pages/ContentPage.qml @@ -101,7 +101,8 @@ Page { annotationsPaint: true notesPaint: true anchors.horizontalCenter: parent.horizontalCenter - deviceOrientation: DocumentSettings.verticalScroll(splitDocumentName()) ? Qt.Vertical : Qt.Horizontal + deviceOrientation: root.orientation + orientation: DocumentSettings.verticalScroll(splitDocumentName()) ? Qt.Vertical : Qt.Horizontal onClickedUrl: Qt.openUrlExternally(url) @@ -647,42 +648,33 @@ Page { open(d) } - onOpenedChanged: delegate.selected = opened + onOpenedChanged: { + pdfPagesView.scroll = !opened; + delegate.selected = opened; + } preferredWidth: applicationWindow.preferredWidthPopup PopupMenuCheckableItem { id: horizontalOption + checked: pdfPagesView.orientation === Qt.Horizontal + text: qsTr("Scroll pages horizontally") + onCheckedChanged: { - if (checked) { - pdfPagesView.orientation = Qt.Horizontal; - } else { - pdfPagesView.orientation = Qt.Vertical; - } - DocumentSettings.setVerticalScroll(splitDocumentName(), pdfPagesView.orientation === Qt.Vertical); + DocumentSettings.setVerticalScroll(splitDocumentName(), !checked); + pdfPagesView.orientation = checked ? Qt.Horizontal : Qt.Vertical; } - - enabled: !pdfPagesView.isPagedView - - checked: false - text: qsTr("Scroll pages horizontally") } PopupMenuCheckableItem { + checked: pdfPagesView.isPagedView + text: qsTr("Paged view") + onCheckedChanged: { - if (checked) { - pdfPagesView.orientation = Qt.Horizontal; - } else { - pdfPagesView.orientation = horizontalOption.checked ? Qt.Horizontal : Qt.Vertical; - } DocumentSettings.setIsPagedView(splitDocumentName(), checked); pdfPagesView.isPagedView = checked; - DocumentSettings.setVerticalScroll(splitDocumentName(), pdfPagesView.orientation === Qt.Vertical); } - - checked: pdfPagesView.isPagedView - text: qsTr("Paged view") } PopupMenuDividerItem {} diff --git a/application/qml/pages/NavigationPage.qml b/application/qml/pages/NavigationPage.qml index 993060ab419cc612ef25766c89fba871c6da39ab..560e5e105501eb1d26614c8fa1e7bd73148633b0 100644 --- a/application/qml/pages/NavigationPage.qml +++ b/application/qml/pages/NavigationPage.qml @@ -188,7 +188,7 @@ Page { color: palette.primaryColor } onClicked: { - sectionSelected(pageIndex) + sectionSelected(pageIndex - 1) pageStack.pop() } }