2015-06-28 14:22:35 +03:00
|
|
|
/*
|
2016-02-21 15:13:40 +03:00
|
|
|
Copyright (C) 2015-2016 Jolla Ltd.
|
2015-06-28 14:22:35 +03:00
|
|
|
Contact: Slava Monich <slava.monich@jolla.com>
|
|
|
|
|
|
|
|
You may use this file under the terms of BSD license as follows:
|
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
modification, are permitted provided that the following conditions
|
|
|
|
are met:
|
2016-10-08 14:56:14 +03:00
|
|
|
|
2015-06-28 14:22:35 +03:00
|
|
|
* Redistributions of source code must retain the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
* Redistributions in binary form must reproduce the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer in the
|
|
|
|
documentation and/or other materials provided with the distribution.
|
2016-10-08 19:57:54 +03:00
|
|
|
* Neither the name of Jolla Ltd nor the names of its contributors may
|
|
|
|
be used to endorse or promote products derived from this software
|
2016-10-08 14:56:14 +03:00
|
|
|
without specific prior written permission.
|
2015-06-28 14:22:35 +03:00
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
|
|
|
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
|
|
THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
import QtQuick 2.0
|
|
|
|
import Sailfish.Silica 1.0
|
|
|
|
import harbour.books 1.0
|
|
|
|
|
|
|
|
SilicaFlickable {
|
|
|
|
id: root
|
|
|
|
|
|
|
|
property variant book
|
|
|
|
|
|
|
|
signal closeBook()
|
|
|
|
signal pageClicked(var page)
|
|
|
|
|
2016-11-02 16:33:26 +03:00
|
|
|
property int orientation: Orientation.Portrait
|
2015-06-28 14:22:35 +03:00
|
|
|
property int _currentPage: bookListWatcher.currentIndex
|
2015-07-11 04:56:38 +03:00
|
|
|
property bool _loading: minLoadingDelay.running || bookModel.loading
|
2016-10-16 23:36:13 +03:00
|
|
|
property var _currentState: _visibilityStates[Settings.pageDetails % _visibilityStates.length]
|
2015-06-28 14:22:35 +03:00
|
|
|
readonly property var _visibilityStates: [
|
|
|
|
{ pager: false, page: false, title: false, tools: false },
|
|
|
|
{ pager: false, page: true, title: true, tools: false },
|
|
|
|
{ pager: true, page: true, title: true, tools: true }
|
|
|
|
]
|
|
|
|
|
2015-08-24 13:23:24 +03:00
|
|
|
// NOTE: These have to match ResetReason in BooksBookModel
|
|
|
|
readonly property var _loadingTextLabel: [
|
2015-11-03 01:33:58 +03:00
|
|
|
//% "Formatting..."
|
2016-10-07 18:47:27 +03:00
|
|
|
qsTrId("harbour-books-book-view-formatting"),
|
2015-08-24 13:23:24 +03:00
|
|
|
//% "Loading..."
|
2016-10-07 18:47:27 +03:00
|
|
|
qsTrId("harbour-books-book-view-loading"),
|
2015-08-24 13:23:24 +03:00
|
|
|
//% "Applying larger fonts..."
|
2016-10-07 18:47:27 +03:00
|
|
|
qsTrId("harbour-books-book-view-applying_larger_fonts"),
|
2015-08-24 13:23:24 +03:00
|
|
|
//% "Applying smaller fonts..."
|
2016-10-07 18:47:27 +03:00
|
|
|
qsTrId("harbour-books-book-view-applying_smaller_fonts")
|
2015-08-24 13:23:24 +03:00
|
|
|
]
|
|
|
|
|
2016-11-02 16:33:26 +03:00
|
|
|
interactive: (!linkMenu || !linkMenu.visible) &&
|
|
|
|
(!imageView || !imageView.visible) &&
|
|
|
|
(!footnoteView || !footnoteView.visible)
|
2016-10-08 14:56:14 +03:00
|
|
|
|
|
|
|
property var linkMenu
|
2016-10-08 19:57:54 +03:00
|
|
|
property var imageView
|
2016-11-02 16:33:26 +03:00
|
|
|
property var footnoteView
|
|
|
|
|
|
|
|
onOrientationChanged: {
|
|
|
|
if (footnoteView) {
|
|
|
|
footnoteView.cancel()
|
|
|
|
}
|
|
|
|
}
|
2016-10-08 14:56:14 +03:00
|
|
|
|
|
|
|
Component {
|
|
|
|
id: linkMenuComponent
|
2016-11-02 16:33:26 +03:00
|
|
|
BooksLinkMenu { }
|
2016-10-08 14:56:14 +03:00
|
|
|
}
|
|
|
|
|
2016-10-08 19:57:54 +03:00
|
|
|
Component {
|
|
|
|
id: imageViewComponent
|
2016-11-02 16:33:26 +03:00
|
|
|
BooksImageView { }
|
|
|
|
}
|
|
|
|
|
|
|
|
Component {
|
|
|
|
id: footnoteViewComponent
|
|
|
|
BooksFootnoteView { }
|
2016-10-08 19:57:54 +03:00
|
|
|
}
|
|
|
|
|
2015-06-28 14:22:35 +03:00
|
|
|
PullDownMenu {
|
|
|
|
MenuItem {
|
|
|
|
//% "Back to library"
|
2016-10-07 18:47:27 +03:00
|
|
|
text: qsTrId("harbour-books-book-view-back")
|
2015-06-28 14:22:35 +03:00
|
|
|
onClicked: root.closeBook()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Timer {
|
|
|
|
id: minLoadingDelay
|
|
|
|
interval: 1000
|
|
|
|
}
|
|
|
|
|
|
|
|
Timer {
|
|
|
|
id: resetPager
|
|
|
|
interval: 0
|
|
|
|
onTriggered: {
|
|
|
|
if (_currentPage >= 0) {
|
|
|
|
console.log("resetting pager to", _currentPage)
|
|
|
|
pager.currentPage = _currentPage
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BookModel {
|
|
|
|
id: bookModel
|
|
|
|
book: root.book ? root.book : null
|
|
|
|
size: bookListWatcher.size
|
|
|
|
currentPage: _currentPage
|
|
|
|
leftMargin: Theme.horizontalPageMargin
|
|
|
|
rightMargin: Theme.horizontalPageMargin
|
|
|
|
topMargin: Theme.itemSizeSmall
|
|
|
|
bottomMargin: Theme.itemSizeSmall
|
|
|
|
onJumpToPage: bookView.jumpTo(index)
|
|
|
|
onCurrentPageChanged: {
|
2016-10-08 14:56:14 +03:00
|
|
|
if (linkMenu) linkMenu.hide()
|
2015-06-28 14:22:35 +03:00
|
|
|
if (currentPage >= 0 && bookView._jumpingTo < 0) {
|
|
|
|
pager.currentPage = currentPage
|
|
|
|
}
|
|
|
|
}
|
|
|
|
onLoadingChanged: {
|
|
|
|
if (loading && !pageCount) {
|
|
|
|
minLoadingDelay.start()
|
|
|
|
bookView._jumpingTo = -1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ListWatcher {
|
|
|
|
id: bookListWatcher
|
|
|
|
listView: bookView
|
|
|
|
}
|
|
|
|
|
|
|
|
SilicaListView {
|
|
|
|
id: bookView
|
|
|
|
model: bookModel
|
|
|
|
anchors.fill: parent
|
|
|
|
flickDeceleration: maximumFlickVelocity
|
|
|
|
orientation: ListView.Horizontal
|
|
|
|
snapMode: ListView.SnapOneItem
|
|
|
|
spacing: Theme.paddingMedium
|
|
|
|
opacity: _loading ? 0 : 1
|
|
|
|
visible: opacity > 0
|
2016-10-08 14:56:14 +03:00
|
|
|
interactive: root.interactive
|
2015-06-28 14:22:35 +03:00
|
|
|
delegate: BooksPageView {
|
|
|
|
width: bookView.width
|
|
|
|
height: bookView.height
|
|
|
|
model: bookModel
|
|
|
|
page: index
|
|
|
|
leftMargin: bookModel.leftMargin
|
|
|
|
rightMargin: bookModel.rightMargin
|
|
|
|
topMargin: bookModel.topMargin
|
|
|
|
bottomMargin: bookModel.bottomMargin
|
2015-08-23 14:47:25 +03:00
|
|
|
leftSpaceReserved: pageTools.visible ? pageTools.leftSpaceUsed : 0
|
|
|
|
rightSpaceReserved: pageTools.visible ? pageTools.rightSpaceUsed: 0
|
2015-06-28 14:22:35 +03:00
|
|
|
titleVisible: _currentState.title
|
|
|
|
pageNumberVisible: _currentState.page
|
|
|
|
title: bookModel.title
|
2016-10-16 20:07:03 +03:00
|
|
|
onJumpToPage: bookView.jumpTo(page)
|
2015-06-28 14:22:35 +03:00
|
|
|
onPageClicked: {
|
|
|
|
root.pageClicked(index)
|
2016-10-16 23:36:13 +03:00
|
|
|
Settings.pageDetails = (Settings.pageDetails+ 1) % _visibilityStates.length
|
2015-06-28 14:22:35 +03:00
|
|
|
}
|
2016-10-08 19:57:54 +03:00
|
|
|
onImagePressed: {
|
|
|
|
if (_currentPage == index) {
|
|
|
|
if (!imageView) {
|
|
|
|
imageView = imageViewComponent.createObject(root)
|
|
|
|
}
|
2016-10-08 23:36:28 +03:00
|
|
|
imageView.show(url,rect)
|
2016-10-08 19:57:54 +03:00
|
|
|
}
|
|
|
|
}
|
2016-10-08 14:56:14 +03:00
|
|
|
onBrowserLinkPressed: {
|
|
|
|
if (_currentPage == index) {
|
|
|
|
if (!linkMenu) {
|
|
|
|
linkMenu = linkMenuComponent.createObject(root)
|
|
|
|
}
|
2016-11-02 16:33:26 +03:00
|
|
|
linkMenu.show(url)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
onFootnotePressed: {
|
|
|
|
if (_currentPage == index) {
|
|
|
|
if (!footnoteView) {
|
|
|
|
footnoteView = footnoteViewComponent.createObject(root)
|
|
|
|
}
|
|
|
|
footnoteView.show(touchX,touchY,text,url)
|
2016-10-08 14:56:14 +03:00
|
|
|
}
|
|
|
|
}
|
2015-06-28 14:22:35 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
property int _jumpingTo: -1
|
|
|
|
function jumpTo(page) {
|
|
|
|
if (page >=0 && page !== _currentPage) {
|
|
|
|
_jumpingTo = page
|
|
|
|
positionViewAtIndex(page, ListView.Center)
|
2016-10-08 01:09:57 +03:00
|
|
|
pager.currentPage = page
|
2015-06-28 14:22:35 +03:00
|
|
|
_jumpingTo = -1
|
|
|
|
if (_currentPage !== page) {
|
|
|
|
console.log("oops, still at", _currentPage)
|
|
|
|
resetPager.restart()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Behavior on opacity { FadeAnimation {} }
|
|
|
|
|
2015-08-23 14:47:25 +03:00
|
|
|
BooksPageTools {
|
|
|
|
id: pageTools
|
|
|
|
anchors {
|
|
|
|
top: parent.top
|
|
|
|
left: parent.left
|
|
|
|
right: parent.right
|
|
|
|
}
|
2015-06-28 14:22:35 +03:00
|
|
|
leftMargin: bookModel.leftMargin
|
|
|
|
rightMargin: bookModel.rightMargin
|
2015-08-23 14:47:25 +03:00
|
|
|
opacity: _currentState.tools ? 1 : 0
|
|
|
|
visible: opacity > 0 && book && bookModel.pageCount && !_loading
|
|
|
|
Behavior on opacity { FadeAnimation {} }
|
2015-12-13 14:46:53 +03:00
|
|
|
onIncreaseFontSize: bookModel.increaseFontSize()
|
|
|
|
onDecreaseFontSize: bookModel.decreaseFontSize()
|
2015-06-28 14:22:35 +03:00
|
|
|
}
|
|
|
|
|
2015-08-23 14:47:25 +03:00
|
|
|
BooksPager {
|
|
|
|
id: pager
|
|
|
|
anchors {
|
|
|
|
bottom: parent.bottom
|
|
|
|
bottomMargin: (Theme.itemSizeExtraSmall + 2*(bookModel.bottomMargin - height))/4
|
|
|
|
}
|
|
|
|
pageCount: bookModel.pageCount
|
|
|
|
width: parent.width
|
|
|
|
opacity: (_currentState.pager && book && bookModel.pageCount) ? 0.75 : 0
|
|
|
|
visible: opacity > 0
|
|
|
|
onPageChanged: bookView.jumpTo(page)
|
|
|
|
Behavior on opacity { FadeAnimation {} }
|
2015-06-28 14:22:35 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-12 19:37:02 +03:00
|
|
|
BooksTitleLabel {
|
|
|
|
id: titleLabel
|
|
|
|
anchors {
|
|
|
|
top: parent.top
|
|
|
|
left: parent.left
|
|
|
|
right: parent.right
|
|
|
|
leftMargin: bookModel.leftMargin
|
|
|
|
rightMargin: bookModel.rightMargin
|
|
|
|
}
|
|
|
|
text: bookModel.title
|
|
|
|
height: Theme.itemSizeExtraSmall
|
|
|
|
color: Theme.highlightColor
|
|
|
|
opacity: _loading ? 0.6 : 0
|
|
|
|
}
|
|
|
|
|
2015-07-11 04:56:38 +03:00
|
|
|
BusyIndicator {
|
|
|
|
id: busyIndicator
|
2015-06-28 14:22:35 +03:00
|
|
|
anchors.centerIn: parent
|
2015-07-11 04:56:38 +03:00
|
|
|
size: BusyIndicatorSize.Large
|
|
|
|
running: _loading
|
|
|
|
}
|
2015-07-16 23:51:57 +03:00
|
|
|
|
2015-07-11 04:56:38 +03:00
|
|
|
BooksFitLabel {
|
2015-07-16 23:51:57 +03:00
|
|
|
anchors.fill: busyIndicator
|
2015-07-11 04:56:38 +03:00
|
|
|
text: bookModel.progress > 0 ? bookModel.progress : ""
|
2015-07-16 23:51:57 +03:00
|
|
|
opacity: (_loading && bookModel.progress > 0) ? 1 : 0
|
2015-07-11 04:56:38 +03:00
|
|
|
}
|
2015-07-16 23:51:57 +03:00
|
|
|
|
2015-09-12 19:37:02 +03:00
|
|
|
Button {
|
|
|
|
//% "Cancel"
|
2016-10-07 18:47:27 +03:00
|
|
|
text: qsTrId("harbour-books-book-view-cancel_loading")
|
2015-09-12 19:37:02 +03:00
|
|
|
height: Theme.itemSizeLarge
|
|
|
|
anchors {
|
|
|
|
bottom: parent.bottom
|
|
|
|
horizontalCenter: parent.horizontalCenter
|
|
|
|
}
|
|
|
|
onClicked: root.closeBook()
|
2015-11-03 01:33:58 +03:00
|
|
|
enabled: _loading && bookModel.resetReason === BookModel.ReasonLoading
|
2015-10-30 23:59:09 +03:00
|
|
|
visible: opacity > 0
|
2015-09-12 19:37:02 +03:00
|
|
|
opacity: enabled ? 1.0 : 0.0
|
|
|
|
Behavior on opacity { FadeAnimation { } }
|
|
|
|
}
|
2016-02-21 15:13:40 +03:00
|
|
|
|
|
|
|
Label {
|
|
|
|
anchors {
|
|
|
|
top: busyIndicator.bottom
|
|
|
|
topMargin: Theme.paddingLarge
|
|
|
|
horizontalCenter: busyIndicator.horizontalCenter
|
|
|
|
|
|
|
|
}
|
|
|
|
horizontalAlignment: Text.AlignHCenter
|
|
|
|
color: Theme.highlightColor
|
|
|
|
opacity: _loading ? 1 : 0
|
|
|
|
visible: opacity > 0
|
|
|
|
Behavior on opacity { FadeAnimation {} }
|
|
|
|
text: bookModel ? _loadingTextLabel[bookModel.resetReason] : ""
|
|
|
|
}
|
2015-06-28 14:22:35 +03:00
|
|
|
}
|