/*
* Copyright (c) 2018 Frank Fischer <frank-fischer@shadow-soft.de>
*
* 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 2.0
import QtQml.Models 2.2
import Sailfish.Silica 1.0
import Fotokopierer 1.0
import ".."
import "../../common"
Page {
id: docpage
property var document
property bool editing: false
property bool dragging: false
ScanImage {
id: scanImage
}
Loader {
id: newPage
}
onStatusChanged: {
if (status == PageStatus.Active) {
// ensure that the C++ memory of ScanImage is freed
newPage.source = ""
scanImage.clear()
}
}
DelegateModel {
id: visualModel
delegate: PageDelegate {
id: pageDelegate
width: grid.cellWidth
height: grid.cellHeight
thumbnail: role_thumbnail != null && role_thumbnail != "" ? role_thumbnail : "image://theme/icon-l-image"
pagenumber: DelegateModel.itemsIndex + 1
creationTime: role_creationTime || new Date()
isAddButton: role_thumbnail == null
visible: !isAddButton || (!docpage.editing && !docpage.dragging)
deleting: docpage.editing
onPressed: {
if (docpage.editing) {
docpage.editing = false
docpage.dragging = true
startDragging()
}
}
// This timer is used to end dragging mode.
//
// The reason for using this timer is as follows. Dragging is
// finished by an `onReleased` event. If the event handler would set
// `dragging = false` the following `onClicked` event would trigger
// an `addPage` or `openPage` command because it comes after the
// `onReleased` event. However, because at this time `dragging ==
// false` the page seems to be in "standard" non-editing mode
// already. Therefore, instead of setting `dragging = false`
// directly the event handler will start this time whose
// `onTriggered` event will come after the `onClicked` event.
Timer {
id: endDraggingTimer
interval: 0
repeat: false
onTriggered: docpage.dragging = false
}
onReleased: {
if (docpage.dragging) {
endDraggingTimer.start()
endDragging()
}
}
onClicked: {
if (docpage.editing || docpage.dragging) {
docpage.editing = false
} else if (isAddButton) {
addPage()
} else {
openPage()
}
}
onItemMoved: visualModel.model.move(from, to)
function addPage() {
newPage.source = Qt.resolvedUrl("NewImagePage.qml")
newPage.item.scanImage = scanImage
newPage.item.destination = docpage
newPage.item.addPage.connect(function() {
scanImage.saveAndClear(document)
})
pageStack.push(newPage.item)
}
function openPage() {
pageStack.push(Qt.resolvedUrl("PagePage.qml"), { "image": role_result })
}
onDeletePage: {
docpage.dragging = false
docpage.editing = false
remorse.execute(pageDelegate, qsTr("Delete page"), function () {
document.deletePage(pageDelegate.DelegateModel.itemsIndex)
})
}
RemorseItem {
id: remorse
}
}
Component.onCompleted: {
visualModel.model = document
visualModel.items.insert({"role_thumbnail": null})
}
}
SilicaGridView {
id: grid
anchors.fill: parent
cellWidth: width / 2
cellHeight: (height - Theme.itemSizeLarge) / 2
displaced: Transition {
NumberAnimation { properties: "x,y"; duration: 200 }
}
header: PageHeader {
id: head
title: document.title
}
model: visualModel
VerticalScrollDecorator {}
MouseArea {
anchors.fill: grid
propagateComposedEvents: true
onClicked: {
if (docpage.editing) {
var index = grid.indexAt(grid.contentX + mouse.x, grid.contentY + mouse.y)
if (index == -1 || index == visualModel.count - 1) {
docpage.editing = false
} else {
mouse.accepted = false
}
} else {
mouse.accepted = false
}
}
onPressed: {
if (docpage.editing) {
var index = grid.indexAt(grid.contentX + mouse.x, grid.contentY + mouse.y)
if (index == -1 || index == visualModel.count - 1) {
docpage.editing = false
} else {
mouse.accepted = false
}
}
}
onPressAndHold: {
if (visualModel.count > 1) {
docpage.editing = true
}
}
}
property int scrollingDirection: 0
// SmoothedAnimation {
// id: upAnimation
// target: grid
// property: "contentY"
// to: 0
// running: scrollingDirection == -1
// }
// SmoothedAnimation {
// id: downAnimation
// target: grid
// property: "contentY"
// to: grid.contentHeight - grid.height
// running: scrollingDirection == 1
// }
// scrollingDirection: {
// var yCoord = grid.mapFromItem(dragArea, 0, dragArea.mouseY).y;
// if (yCoord < scrollEdgeSize) {
// -1;
// } else if (yCoord > grid.height - scrollEdgeSize) {
// 1;
// } else {
// 0;
// }
// }
}
}