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

0001 /*
0002  * Copyright (C) 2021 Mahmoud Ahmed Khalil
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.Layouts 1.4
0024 import QtQuick.Controls 2.12 as QtControls
0025 import QtQuick.Dialogs 1.3
0026 
0027 import org.kde.kirigami 2.12 as Kirigami
0028 
0029 import org.kde.peruse 0.1 as Peruse
0030 
0031 /**
0032  * @brief a special overlay sheet for editing frames/textareas/jumps
0033  */
0034 Kirigami.OverlaySheet {
0035     id: root;
0036 
0037     property QtObject model;
0038     property QtObject objectToBeEdited;
0039     property int objectToBeEditedType;
0040 
0041     property string imageSource;
0042     property var pages: [];
0043     property var availableTypes: [];
0044 
0045     /**
0046      * editObject should be the proper way to modify particular objects
0047      * on a page, calling the sheet's open() won't behave as expected.
0048      */
0049     function editObject(object, type) {
0050         if(object && type !== -1) {
0051             objectToBeEdited = object;
0052             objectToBeEditedType = type;
0053 
0054             // Explicitly setting the controls
0055             switch(objectToBeEditedType) {
0056                 case BookPage.FieldTypes.Frame:
0057                     areaId.text = objectToBeEdited.id;
0058                     frameBackgroundColor.color = objectToBeEdited.bgcolor;
0059                     break;
0060                 case BookPage.FieldTypes.Textarea:
0061                     areaId.text = objectToBeEdited.id;
0062                     textAreaBackgroundColor.color = objectToBeEdited.bgcolor;
0063                     transparentSwitch.checked = objectToBeEdited.transparent;
0064                     invertedSwitch.checked = objectToBeEdited.inverted;
0065                     textRotation.value = objectToBeEdited.textRotation;
0066                     textType.currentIndex = availableTypes.indexOf(objectToBeEdited.type);
0067                     textAreaInput.text = objectToBeEdited.paragraphs.join("\n");
0068                     break;
0069                 case BookPage.FieldTypes.Jump:
0070                     pageIndexComboBox.currentIndex = objectToBeEdited.pageIndex;
0071                     jumpHref.text = objectToBeEdited.href;
0072                     break;
0073 
0074                 default:
0075                     return;
0076             }
0077 
0078             var topLeft = Qt.point(objectToBeEdited.bounds.x, objectToBeEdited.bounds.y);
0079             var bottomRight = Qt.point(objectToBeEdited.bounds.x + objectToBeEdited.bounds.width, objectToBeEdited.bounds.y + objectToBeEdited.bounds.height);
0080             var widthFull = Math.max(bottomRight.x, topLeft.x) - Math.min(bottomRight.x, topLeft.x);
0081             var heightFull = Math.max(bottomRight.y, topLeft.y) - Math.min(bottomRight.y, topLeft.y);
0082             var baseSize = Math.min(mainWindow.height, mainWindow.width)*0.3;
0083 
0084             clipRectangle.height = baseSize;
0085             clipRectangle.width = baseSize*(widthFull/heightFull);
0086             var multiplier = baseSize/heightFull;
0087             if (widthFull > heightFull) {
0088                 multiplier = baseSize/widthFull;
0089                 clipRectangle.width = baseSize;
0090                 clipRectangle.height = baseSize*(heightFull/widthFull);
0091             }
0092             preview.width = preview.sourceSize.width*multiplier;
0093             preview.height = preview.sourceSize.height*multiplier;
0094             preview.x = 0-(topLeft.x*multiplier);
0095             preview.y = 0-(topLeft.y*multiplier);
0096 
0097             open();
0098         }
0099     }
0100 
0101     onSheetOpenChanged: {
0102         if(sheetOpen) {
0103             if(!objectToBeEdited || objectToBeEditedType === -1) {
0104                 console.log("EditPageArea should be only opened via its editObject function");
0105                 close();
0106             }
0107         } else {
0108             objectToBeEdited = null;
0109             objectToBeEditedType = -1;
0110         }
0111     }
0112 
0113     showCloseButton: true
0114     header: Kirigami.Heading {
0115         text: i18nc("title text for the edit page area sheet", "Edit Page Area");
0116         Layout.fillWidth: true
0117         elide: Text.ElideRight
0118     }
0119 
0120     ColumnLayout {
0121         Rectangle {
0122             id: clipRectangle;
0123             clip:true;
0124             width: Kirigami.Units.iconSizes.huge*3;
0125             height: Kirigami.Units.iconSizes.huge*3;
0126             Layout.alignment: Qt.AlignHCenter;
0127             Image {
0128                 id: preview
0129                 source: root.imageSource;
0130             }
0131             Text {
0132                 id: textRotationGuide;
0133                 anchors.centerIn: parent;
0134                 height: 1;
0135                 color: "red";
0136                 text: i18n("Text Rotation Guide");
0137                 wrapMode: Text.WrapAtWordBoundaryOrAnywhere;
0138                 rotation: 360-textRotation.value;
0139                 visible: objectToBeEditedType == BookPage.FieldTypes.Textarea;
0140             }
0141         }
0142 
0143         Kirigami.FormLayout {
0144             Layout.fillWidth: true;
0145 
0146             QtControls.TextField {
0147                 id: areaId
0148                 Kirigami.FormData.label: i18nc("Label for the ID input field", "ID:")
0149                 placeholderText: i18nc("Placeholder text for the page area ID text-field", "Write to add an ID");
0150                 visible: objectToBeEditedType == BookPage.FieldTypes.Frame || objectToBeEditedType == BookPage.FieldTypes.Textarea
0151             }
0152             Row {
0153                 Kirigami.FormData.label: i18nc("Label for background color button", "Background color:")
0154                 visible: objectToBeEditedType == BookPage.FieldTypes.Frame;
0155                 spacing: Kirigami.Units.smallSpacing;
0156                 Rectangle {
0157                     id: frameBackgroundColor;
0158                     height: Kirigami.Units.iconSizes.medium;
0159                     width: Kirigami.Units.iconSizes.huge;
0160                     radius: 3;
0161                     border.color: Kirigami.Theme.disabledTextColor;
0162                     border.width: 1;
0163                     MouseArea {
0164                         anchors.fill: parent;
0165                         onClicked: {
0166                             backgroundColorDialog.open();
0167 
0168                         }
0169                         hoverEnabled: true;
0170                         onEntered: parent.border.color = Kirigami.Theme.hoverColor;
0171                         onExited: parent.border.color = Kirigami.Theme.disabledTextColor;
0172                     }
0173                     ColorDialog {
0174                         id: backgroundColorDialog
0175                         title: i18nc("@title color choosing dialog","Choose the background color for this frame");
0176                         color: frameBackgroundColor.color;
0177                         onAccepted: frameBackgroundColor.color = color;
0178                     }
0179                 }
0180             }
0181 
0182             Row {
0183                 visible: objectToBeEditedType == BookPage.FieldTypes.Textarea;
0184                 Kirigami.FormData.label: i18nc("Label for background color button", "Background color:")
0185                 spacing: Kirigami.Units.smallSpacing;
0186                 height: Kirigami.Units.iconSizes.medium;
0187                 Rectangle {
0188                     id: textAreaBackgroundColor;
0189                     height: Kirigami.Units.iconSizes.medium;
0190                     width: Kirigami.Units.iconSizes.huge;
0191                     radius: 3;
0192                     border.color: Kirigami.Theme.disabledTextColor;
0193                     border.width: 1;
0194                     color: objectToBeEdited && objectToBeEdited.hasOwnProperty("bgcolor")? objectToBeEdited.bgcolor : "#ffffff";
0195                     anchors.verticalCenter: parent.verticalCenter;
0196                     MouseArea {
0197                         anchors.fill: parent;
0198                         onClicked: {
0199                             textAreaBackgroundColorDialog.open();
0200 
0201                         }
0202                         hoverEnabled: true;
0203                         onEntered: parent.border.color = Kirigami.Theme.hoverColor;
0204                         onExited: parent.border.color = Kirigami.Theme.disabledTextColor;
0205                     }
0206                     ColorDialog {
0207                         id: textAreaBackgroundColorDialog
0208                         title: i18nc("@title color choosing dialog","Choose the background color for this frame");
0209                         color: textAreaBackgroundColor.color;
0210                         onAccepted: textAreaBackgroundColor.color = color;
0211                     }
0212                 }
0213             }
0214 
0215             QtControls.Switch {
0216                 id: transparentSwitch;
0217                 visible: objectToBeEditedType == BookPage.FieldTypes.Textarea;
0218                 Kirigami.FormData.label: i18nc("Option for making the background of a text area transparent", "Transparent");
0219             }
0220             QtControls.Switch {
0221                 id: invertedSwitch;
0222                 visible: objectToBeEditedType == BookPage.FieldTypes.Textarea;
0223                 Kirigami.FormData.label: i18nc("Option for making the background of a text area cause what is behind it to be inverted", "Inverted");
0224             }
0225             QtControls.Slider {
0226                 id: textRotation;
0227                 Kirigami.FormData.label: i18nc("Label for text rotation slider", "Text rotation:")
0228                 visible: objectToBeEditedType == BookPage.FieldTypes.Textarea;
0229                 from: 0
0230                 to: 360;
0231             }
0232 
0233             QtControls.ComboBox {
0234                 id: textType;
0235                 Kirigami.FormData.label: i18nc("Label for text type combobox", "Type:")
0236                 visible: objectToBeEditedType == BookPage.FieldTypes.Textarea;
0237                 model: root.availableTypes;
0238                 popup.z: 999; // HACK This is an absolute hack, but combos inside OverlaySheets have their popups show up underneath, because of fun z ordering stuff
0239             }
0240 
0241             Kirigami.ActionToolBar {
0242                 visible: textAreaInput.visible
0243                 actions: [
0244                     Kirigami.Action {
0245                         text: i18nc("Edit the link the cursor is currently positioned on (or convert the selection to a link, or add a new one if there is no selection)", "Edit Link");
0246                         icon.name: "edit-link"
0247                         onTriggered: linkDetails.edit();
0248                     }
0249                 ]
0250             }
0251             QtControls.TextArea {
0252                 id: textAreaInput;
0253                 Layout.fillWidth: true;
0254                 Kirigami.FormData.label: i18nc("Label for the text area body field", "Textarea Body:");
0255                 visible: objectToBeEditedType === BookPage.FieldTypes.Textarea;
0256                 textFormat: Qt.RichText
0257                 wrapMode: TextEdit.Wrap
0258                 focus: true
0259                 selectByMouse: true
0260                 persistentSelection: true
0261                 Peruse.TextDocumentEditor {
0262                     id: textDocumentEditor;
0263                     textDocument: textAreaInput.textDocument;
0264                 }
0265                 MouseArea {
0266                     acceptedButtons: Qt.RightButton
0267                     anchors.fill: parent
0268                     onClicked: {
0269                         mainWindow.contextDrawer.open()
0270                     }
0271                 }
0272 
0273                 function ensureVisible(rectToMakeVisible)
0274                 {
0275                     //if (root.flickable.contentX >= rectToMakeVisible.x) {
0276                         //root.flickable.contentX = rectToMakeVisible.x;
0277                     //} else if (root.flickable.contentX + root.flickable.width <= rectToMakeVisible.x + rectToMakeVisible.width) {
0278                         //root.flickable.contentX = rectToMakeVisible.x + rectToMakeVisible.width - root.flickable.width;
0279                     //}
0280                     //if (root.flickable.contentY >= rectToMakeVisible.y) {
0281                         //root.flickable.contentY = rectToMakeVisible.y;
0282                     //} else if (root.flickable.contentY + root.flickable.height <= rectToMakeVisible.y + rectToMakeVisible.height) {
0283                         //root.flickable.contentY = rectToMakeVisible.y + rectToMakeVisible.height - root.flickable.height;
0284                     //}
0285                 }
0286                 onCursorRectangleChanged: {
0287                     ensureVisible(cursorRectangle);
0288                 }
0289                 onLinkActivated: {
0290                     // This is the nastiest hack... for some reason, clicking a link does not position
0291                     // the cursor where you clicked, but rather /after/ the link you clicked. Not helpful.
0292                     textAreaInput.cursorPosition = textAreaInput.cursorPosition - 1;
0293                     linkDetails.edit();
0294                 }
0295             }
0296 
0297             QtControls.TextField {
0298                 id: jumpHref;
0299                 Kirigami.FormData.label: i18nc("Label for a text input box in which to input a hyperlink destination", "Jump Destination:");
0300                 visible: objectToBeEditedType == BookPage.FieldTypes.Jump;
0301                 placeholderText: i18nc("Placeholder text for a text input box in which to input a hyperlink destination", "Enter the jump destination here");
0302             }
0303             QtControls.ComboBox {
0304                 id: pageIndexComboBox;
0305                 Kirigami.FormData.label: i18nc("Label for the dropdown which will let you pick a page a jump will send the reader to when activated", "Page Index:")
0306                 visible: objectToBeEditedType == BookPage.FieldTypes.Jump;
0307                 model: root.pages;
0308                 popup.z: 999; // HACK This is an absolute hack, but combos inside OverlaySheets have their popups show up underneath, because of fun z ordering stuff
0309             }
0310         }
0311 
0312         QtControls.Button {
0313             id: saveButton;
0314             Layout.alignment: Qt.AlignRight
0315             text: i18nc("Button which saves the page area, and closes the dialog", "Save");
0316             Keys.onReturnPressed: saveAndClose();
0317             onClicked: saveAndClose();
0318 
0319             function saveAndClose() {
0320                 if(root.objectToBeEdited) {
0321                     switch(root.objectToBeEditedType) {
0322                         case BookPage.FieldTypes.Frame:
0323                             root.objectToBeEdited.id = areaId.text;
0324                             root.objectToBeEdited.bgcolor = frameBackgroundColor.color;
0325                             break;
0326 
0327                         case BookPage.FieldTypes.Textarea:
0328                             root.objectToBeEdited.id = areaId.text;
0329                             root.objectToBeEdited.bgcolor = textAreaBackgroundColor.color;
0330                             root.objectToBeEdited.transparent = transparentSwitch.checked;
0331                             root.objectToBeEdited.inverted = invertedSwitch.checked;
0332                             root.objectToBeEdited.paragraphs = textDocumentEditor.paragraphs();
0333                             root.objectToBeEdited.type = availableTypes[textType.currentIndex];
0334                             root.objectToBeEdited.textRotation = textRotation.value;
0335                             break;
0336 
0337                         case BookPage.FieldTypes.Jump:
0338                             root.objectToBeEdited.pageIndex = pageIndexComboBox.currentIndex;
0339                             root.objectToBeEdited.href = jumpHref.text;
0340                             break;
0341 
0342                         default:
0343                             break;
0344                     }
0345                 }
0346 
0347                 root.close();
0348             }
0349         }
0350 
0351         LinkEditorSheet {
0352             id: linkDetails;
0353             textField: textAreaInput;
0354             editorHelper: textDocumentEditor;
0355             model: root.model;
0356             rootItem.z: 200
0357         }
0358     }
0359 }