Warning, /graphics/peruse/src/creator/qml/BookPage.qml is written in an unsupported language. File is not indexed.

0001 /*
0002  * Copyright (C) 2015 Dan Leinir Turthra Jensen <admin@leinir.dk>
0003  *
0004  * This library is free software; you can redistribute it and/or
0005  * modify it under the terms of the GNU Lesser General Public
0006  * License as published by the Free Software Foundation; either
0007  * version 2.1 of the License, or (at your option) version 3, or any
0008  * later version accepted by the membership of KDE e.V. (or its
0009  * successor approved by the membership of KDE e.V.), which shall
0010  * act as a proxy defined in Section 6 of version 3 of the license.
0011  *
0012  * This library is distributed in the hope that it will be useful,
0013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015  * Lesser General Public License for more details.
0016  *
0017  * You should have received a copy of the GNU Lesser General Public
0018  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
0019  *
0020  */
0021 
0022 import QtQuick 2.12
0023 import QtQuick.Controls 2.12 as QQC2
0024 
0025 import org.kde.kirigami 2.7 as Kirigami
0026 /**
0027  * Page that holds an image to edit the frames on.
0028  */
0029 Kirigami.Page {
0030     id: root;
0031     property string categoryName: "bookPage";
0032     title: i18nc("title of the page editing sub-page for the book editor", "Page %1", root.pageTitle === "" ? root.index : root.pageTitle);
0033     property QtObject model;
0034     property QtObject currentPage;
0035     property QtObject currentLanguage: null;
0036     property string currentLanguageCode: currentLanguage ? currentLanguage.language : ""
0037     property int index: -1;
0038     property string pageUrl: "";
0039     property string pageTitle: "";
0040     property var pageList: [];
0041     property var textTypes: ["speech", "commentary", "formal", "letter", "code", "heading"];
0042     signal save();
0043 
0044     enum FieldTypes {
0045         Frame,
0046         Textarea,
0047         Jump
0048     }
0049 
0050     onIndexChanged: {
0051         if (root.index===0) {
0052             root.currentPage = root.model.acbfData.metaData.bookInfo.coverpage();
0053         } else if (root.index > 0) {
0054             root.currentPage = root.model.acbfData.body.page(root.index-1);
0055         }
0056         root.pageTitle = root.currentPage.title(root.currentLanguageCode);
0057         // Let's ensure there's always a default text-layer.
0058         if (root.currentPage.textLayerLanguages.length === 0) {
0059             root.currentPage.addTextLayer("")
0060         } else if (root.currentPage.textLayerLanguages.indexOf("") < 0) {
0061             root.currentPage.duplicateTextLayer(root.currentPage.textLayerLanguages[1], "");
0062         }
0063 
0064         pageList = [];
0065         for (var i=0; i<model.acbfData.body.pageCount; i++){
0066             var t = model.acbfData.body.page(i).title(root.currentLanguageCode)
0067             if (t !== "") {
0068                 pageList.push(t);
0069             } else {
0070                 pageList.push(i18n("Page %1", i+1));
0071             }
0072         }
0073     }
0074     Component.onCompleted: {
0075         root.updateTranslationActions();
0076     }
0077 
0078     actions {
0079         main: saveAndCloseAction;
0080         right: editPageDataAction;
0081         contextualActions: [
0082             Kirigami.Action {
0083                 id: translationsAction
0084                 text: i18nc("A submenu which allows the user to chose between translations of the book", "Translations")
0085                 visible: root.model.acbfData.metaData.bookInfo.languages.length > 0
0086                 Kirigami.Action {
0087                     text: i18nc("The option used to show no translation should be used", "No Translation")
0088                     onTriggered: root.currentLanguage = null
0089                     checked: root.currentLanguage === null
0090                     checkable: true
0091                     QQC2.ActionGroup.group: translationSelectionGroup
0092                 }
0093             }
0094         ]
0095     }
0096     Kirigami.Action {
0097         id: saveAndCloseAction;
0098         text: i18nc("Saves the remaining unsaved edited fields and closes the page editor", "Save and Close Page");
0099         iconName: "dialog-ok";
0100         shortcut: "Esc";
0101         enabled: !addPageArea.sheetOpen
0102         onTriggered: {
0103             root.save();
0104             root.model.setDirty();
0105             pageStack.pop();
0106         }
0107     }
0108     Kirigami.Action {
0109         id: editPageDataAction;
0110         text: i18nc("Edit the page data in detail", "Edit Page Data");
0111         iconName: "document-edit"
0112         onTriggered: pageStack.push(pageInfo)
0113     }
0114 
0115     function updateTranslationActions() {
0116         for (var i = 0 ; i < root.model.acbfData.metaData.bookInfo.languages.length ; ++i) {
0117             var language = root.model.acbfData.metaData.bookInfo.languages[i];
0118             var action = translationActionEntry.createObject(translationsAction, {language: language});
0119             translationsAction.children.push(action);
0120         }
0121     }
0122     QQC2.ActionGroup { id: translationSelectionGroup }
0123     Component {
0124         id: translationActionEntry
0125         Kirigami.Action {
0126             id: control
0127             text: language.language
0128             visible: language.show
0129             property QtObject language
0130             onTriggered: { root.currentLanguage = control.language; }
0131             checked: root.currentLanguage && root.currentLanguage === control.language
0132             checkable: true
0133             QQC2.ActionGroup.group: translationSelectionGroup
0134         }
0135     }
0136 
0137     Image {
0138         id: coverImage;
0139         anchors {
0140             fill: parent;
0141             margins: Kirigami.Units.smallSpacing;
0142         }
0143         asynchronous: true;
0144         fillMode: Image.PreserveAspectFit;
0145         source: pageUrl;
0146         width: root.width;
0147         height: root.height;
0148         property real muliplierWidth: (paintedWidth / sourceSize.width);
0149         property real muliplierHeight: (paintedHeight / sourceSize.height);
0150         property int offsetX: (width-paintedWidth)/2
0151         property int offsetY: (height-paintedHeight)/2
0152 
0153         Repeater {
0154             model: root.currentPage.framePointStrings
0155 
0156             Rectangle {
0157                 width: coverImage.muliplierWidth * root.currentPage.frame(index).bounds.width;
0158                 height: coverImage.muliplierHeight * root.currentPage.frame(index).bounds.height;
0159                 x: coverImage.muliplierWidth * root.currentPage.frame(index).bounds.x + coverImage.offsetX
0160                 y: coverImage.muliplierHeight * root.currentPage.frame(index).bounds.y + coverImage.offsetY;
0161                 border.color: "blue";
0162                 color: "transparent";
0163                 opacity: 0.5;
0164                 border.width: Kirigami.Units.smallSpacing;
0165                 Rectangle {
0166                     anchors.fill: parent;
0167                     opacity: 0.4;
0168                     color: "blue";
0169                 }
0170                 Text {
0171                     text: index+1;
0172                     anchors {
0173                         centerIn: parent;
0174                     }
0175                     color: "blue";
0176                     font.weight: Font.Bold;
0177                 }
0178 
0179                 MouseArea {
0180                     anchors.fill: parent;
0181 
0182                     onClicked: {
0183                         editPageArea.editObject(root.currentPage.frame(index), BookPage.FieldTypes.Frame);
0184                     }
0185                 }
0186             }
0187         }
0188 
0189         Repeater {
0190             model: root.currentPage.textLayer(root.currentLanguageCode).textareaPointStrings
0191 
0192             Rectangle {
0193                 width: coverImage.muliplierWidth * root.currentPage.textLayer(root.currentLanguageCode).textarea(index).bounds.width;
0194                 height: coverImage.muliplierHeight * root.currentPage.textLayer(root.currentLanguageCode).textarea(index).bounds.height;
0195                 x: coverImage.muliplierWidth * root.currentPage.textLayer(root.currentLanguageCode).textarea(index).bounds.x + coverImage.offsetX
0196                 y: coverImage.muliplierHeight * root.currentPage.textLayer(root.currentLanguageCode).textarea(index).bounds.y + coverImage.offsetY;
0197                 border.color: "red";
0198                 color: "transparent";
0199                 opacity: 0.5;
0200                 border.width: Kirigami.Units.smallSpacing;
0201                 Rectangle {
0202                     anchors.fill: parent;
0203                     opacity: 0.4;
0204                     color: "red";
0205                 }
0206                 Text {
0207                     text: index+1;
0208                     anchors {
0209                         centerIn: parent;
0210                     }
0211                     color: "red";
0212                     font.weight: Font.Bold;
0213                 }
0214 
0215                 MouseArea {
0216                     anchors.fill: parent;
0217 
0218                     onClicked: {
0219                         editPageArea.editObject(root.currentPage.textLayer(root.currentLanguageCode).textarea(index), BookPage.FieldTypes.Textarea);
0220                     }
0221                 }
0222             }
0223         }
0224 
0225         Repeater {
0226             model: root.currentPage.jumps
0227 
0228             Rectangle {
0229                 width: coverImage.muliplierWidth * modelData.bounds.width;
0230                 height: coverImage.muliplierHeight * modelData.bounds.height;
0231                 x: coverImage.muliplierWidth * modelData.bounds.x + coverImage.offsetX
0232                 y: coverImage.muliplierHeight * modelData.bounds.y + coverImage.offsetY;
0233                 border.color: "green";
0234                 color: "transparent";
0235                 opacity: 0.5;
0236                 border.width: Kirigami.Units.smallSpacing;
0237                 Rectangle {
0238                     anchors.fill: parent;
0239                     opacity: 0.4;
0240                     color: "green";
0241                 }
0242                 Text {
0243                     text: index+1;
0244                     anchors {
0245                         centerIn: parent;
0246                     }
0247                     color: "green";
0248                     font.weight: Font.Bold;
0249                 }
0250 
0251                 MouseArea {
0252                     anchors.fill: parent;
0253 
0254                     onClicked: {
0255                         editPageArea.editObject(modelData, BookPage.FieldTypes.Jump)
0256                     }
0257                 }
0258             }
0259         }
0260         MouseArea {
0261             anchors.fill: parent;
0262             id: pointCatchArea;
0263             property point startPoint: Qt.point(0,0);
0264             property point endPoint: Qt.point(0,0);
0265             property bool dragging: false;
0266             //hoverEnabled: true;
0267             preventStealing: false;
0268             propagateComposedEvents: true;
0269             property bool createNewObject: false;
0270 
0271             onClicked: {
0272                 if(!createNewObject) {
0273                     mouse.accepted = false;
0274                 } else {
0275                     createNewObject = false;
0276                 }
0277             }
0278 
0279             onPressed: {
0280                 if (dragging == false) {
0281                     startPoint = Qt.point(mouse.x, mouse.y);
0282                     endPoint = startPoint;
0283                     dragging = true;
0284                     mouse.accepted
0285                 }
0286 
0287             }
0288 
0289             onPositionChanged: {
0290                 if (dragging) {
0291                     endPoint = Qt.point(mouse.x, mouse.y)
0292                     mouse.accepted
0293                 }
0294             }
0295 
0296             onReleased: {
0297                 if (dragging) {
0298                     if (Qt.point(mouse.x, mouse.y)!==startPoint) {
0299                         endPoint = Qt.point(mouse.x, mouse.y);
0300                         createNewObject = true;
0301                         createFrame();
0302                         mouse.accepted
0303                     }
0304 
0305                     dragging = false;
0306                 }
0307 
0308             }
0309             onCanceled: {
0310                 dragging = false;
0311                 endPoint: Qt.point(0,0);
0312                 startPoint: Qt.point(0,0);
0313                 mouse.accepted = false;
0314             }
0315 
0316             Rectangle {
0317                 x: Math.min(parent.startPoint.x, parent.endPoint.x);
0318                 y: Math.min(parent.startPoint.y, parent.endPoint.y);
0319                 width: Math.max(parent.startPoint.x, parent.endPoint.x) - Math.min(parent.startPoint.x, parent.endPoint.x);
0320                 height: Math.max(parent.startPoint.y, parent.endPoint.y) - Math.min(parent.startPoint.y, parent.endPoint.y);
0321                 opacity: 0.5;
0322                 border.color: "black";
0323                 border.width: 1;
0324             }
0325 
0326             function createFrame() {
0327                 var x  = Math.max(( Math.min(startPoint.x, endPoint.x) - coverImage.offsetX ) / coverImage.muliplierWidth, 0);
0328                 var x2 = Math.min(( Math.max(startPoint.x, endPoint.x) - coverImage.offsetX ) / coverImage.muliplierWidth, coverImage.sourceSize.width);
0329                 var y  = Math.max(( Math.min(startPoint.y, endPoint.y) - coverImage.offsetY ) / coverImage.muliplierHeight, 0);
0330                 var y2 = Math.min(( Math.max(startPoint.y, endPoint.y) - coverImage.offsetY ) / coverImage.muliplierHeight, coverImage.sourceSize.height);
0331 
0332                 addPageArea.topLeft = Qt.point(x,y);
0333                 addPageArea.bottomRight = Qt.point(x2,y2);
0334                 endPoint = startPoint;
0335                 addPageArea.open();
0336             }
0337 
0338         }
0339     }
0340     Component {
0341         id: pageInfo;
0342         PageMetaInfo {
0343             colorname: root.model.acbfData.body.bgcolor !== ""? root.model.acbfData.body.bgcolor: "#ffffff";
0344             page: root.currentPage;
0345             onSave: {root.pageTitle = page.title(root.currentLanguageCode); root.model.setDirty();}
0346         }
0347     }
0348 
0349     AddPageArea {
0350         id: addPageArea
0351         imageSource: pageUrl;
0352         onAccepted: {
0353             var index = 0;
0354             var createdObject;
0355             if (type===BookPage.FieldTypes.Frame) {
0356                 index = root.currentPage.framePointStrings.length;
0357                 root.currentPage.addFrame(index);
0358                 root.currentPage.frame(index).setPointsFromRect(topLeft, bottomRight);
0359 
0360                 createdObject = root.currentPage.frame(index);
0361             } else if (type===BookPage.FieldTypes.Textarea) {
0362                 index = root.currentPage.textLayer(root.currentLanguageCode).textareaPointStrings.length;
0363                 root.currentPage.textLayer(root.currentLanguageCode).addTextarea(index);
0364                 root.currentPage.textLayer(root.currentLanguageCode).textarea(index).setPointsFromRect(topLeft, bottomRight);
0365 
0366                 createdObject = root.currentPage.textLayer(root.currentLanguageCode).textarea(index);
0367             } else if (type===BookPage.FieldTypes.Jump) {
0368                 index = root.currentPage.jumps.length;
0369                 root.currentPage.addJump(0, index);
0370                 root.currentPage.jump(index).setPointsFromRect(topLeft, bottomRight);
0371 
0372                 createdObject = root.currentPage.jump(index);
0373             }
0374 
0375             editPageArea.editObject(createdObject, type);
0376         }
0377     }
0378 
0379     EditPageArea {
0380         id: editPageArea;
0381 
0382         imageSource: pageUrl;
0383         pages: root.pageList;
0384         availableTypes: root.textTypes;
0385         model: root.model;
0386     }
0387 }