diff --git a/src/acbf/AcbfPage.cpp b/src/acbf/AcbfPage.cpp index 142b90c..dd22162 100644 --- a/src/acbf/AcbfPage.cpp +++ b/src/acbf/AcbfPage.cpp @@ -1,412 +1,416 @@ /* * Copyright (C) 2015 Dan Leinir Turthra Jensen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) version 3, or any * later version accepted by the membership of KDE e.V. (or its * successor approved by the membership of KDE e.V.), which shall * act as a proxy defined in Section 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . * */ #include "AcbfPage.h" #include "AcbfTextlayer.h" #include "AcbfFrame.h" #include "AcbfJump.h" #include #include #include using namespace AdvancedComicBookFormat; class Page::Private { public: Private() : isCoverPage(false) {} QString bgcolor; QString transition; QHash title; QString imageHref; QHash textLayers; QList frames; QList jumps; bool isCoverPage; }; Page::Page(Document* parent) : QObject(parent) , d(new Private) { qRegisterMetaType("Page*"); } Page::~Page() = default; void Page::toXml(QXmlStreamWriter* writer) { if(d->isCoverPage) { writer->writeStartElement(QStringLiteral("coverpage")); } else { writer->writeStartElement(QStringLiteral("page")); } if(!d->bgcolor.isEmpty()) { writer->writeAttribute(QStringLiteral("bgcolor"), d->bgcolor); } if(!d->transition.isEmpty()) { writer->writeAttribute(QStringLiteral("transition"), d->transition); } QHashIterator titles(d->title); while(titles.hasNext()) { titles.next(); writer->writeStartElement(QStringLiteral("title")); writer->writeAttribute(QStringLiteral("lang"), titles.key()); writer->writeCharacters(titles.value()); writer->writeEndElement(); } writer->writeStartElement(QStringLiteral("image")); writer->writeAttribute(QStringLiteral("href"), d->imageHref); writer->writeEndElement(); Q_FOREACH(Textlayer* layer, d->textLayers.values()) { layer->toXml(writer); } Q_FOREACH(Frame* frame, d->frames) { frame->toXml(writer); } Q_FOREACH(Jump* jump, d->jumps) { jump->toXml(writer); } writer->writeEndElement(); } bool Page::fromXml(QXmlStreamReader *xmlReader) { setBgcolor(xmlReader->attributes().value(QStringLiteral("bgcolor")).toString()); setTransition(xmlReader->attributes().value(QStringLiteral("transition")).toString()); while(xmlReader->readNextStartElement()) { if(xmlReader->name() == QStringLiteral("title")) { d->title[xmlReader->attributes().value(QStringLiteral("lang")).toString()] = xmlReader->readElementText(); } else if(xmlReader->name() == QStringLiteral("image")) { /** * There are some acbf files out there that have backslashes in their * image href. This is probably a mistake from windows users, but not proper XML. * We should thus replace those with forward slashes so the image can be loaded. */ QString href = xmlReader->attributes().value(QStringLiteral("href")).toString(); setImageHref(href.replace(QStringLiteral("\\"), QStringLiteral("/"))); xmlReader->skipCurrentElement(); } else if(xmlReader->name() == QStringLiteral("text-layer")) { Textlayer* newLayer = new Textlayer(this); if(!newLayer->fromXml(xmlReader)) { return false; } d->textLayers[newLayer->language()] = newLayer; } else if(xmlReader->name() == QStringLiteral("frame")) { Frame* newFrame = new Frame(this); if(!newFrame->fromXml(xmlReader)) { return false; } d->frames.append(newFrame); // Frames have no child elements, so we need to force the reader to go to the next one. xmlReader->readNext(); } else if(xmlReader->name() == QStringLiteral("jump")) { Jump* newJump = new Jump(this); if(!newJump->fromXml(xmlReader)) { return false; } // Jumps have no child elements, so we need to force the reader to go to the next one. d->jumps.append(newJump); xmlReader->readNext(); } else { qWarning() << Q_FUNC_INFO << "currently unsupported subsection:" << xmlReader->name(); xmlReader->skipCurrentElement(); } } if (xmlReader->hasError()) { qWarning() << Q_FUNC_INFO << "Failed to read ACBF XML document at token" << xmlReader->name() << "(" << xmlReader->lineNumber() << ":" << xmlReader->columnNumber() << ") The reported error was:" << xmlReader->errorString(); } qDebug() << Q_FUNC_INFO << "Created page for image" << d->imageHref; return !xmlReader->hasError(); } QString Page::bgcolor() const { return d->bgcolor; } void Page::setBgcolor(const QString& newColor) { d->bgcolor = newColor; emit bgcolorChanged(); } QString Page::transition() const { return d->transition; } void Page::setTransition(const QString& transition) { d->transition = transition; emit transitionChanged(); } QStringList Page::availableTransitions() { return { QStringLiteral("fade"), // (old page fades out into background, then new page fades in) QStringLiteral("blend"), // (new page blends in the image while old page blends out) QStringLiteral("scroll_right"), // (screen scrolls to the right to a new page; reversed behavior applies when moving to previous page) QStringLiteral("scroll_down"), // (screen scrolls down to a new page; reversed behavior applies when moving to previous page) QStringLiteral("none") // (no transition animation happens) }; } QStringList Page::titleForAllLanguages() const { return d->title.values(); } QString Page::title(const QString& language) const { if (d->title.count()==0) { return ""; } if (!d->title.keys().contains(language)) { d->title.values().at(0); } QString title = d->title.value(language); if (title.isEmpty()) { title = d->title.values().at(0); } return title; } void Page::setTitle(const QString& title, const QString& language) { if(title.isEmpty()) { d->title.remove(language); } else { d->title[language] = title; } emit titlesChanged(); } QString Page::imageHref() const { return d->imageHref; } void Page::setImageHref(const QString& imageHref) { d->imageHref = imageHref; } QList Page::textLayersForAllLanguages() const { return d->textLayers.values(); } Textlayer * Page::textLayer(const QString& language) const { if (!d->textLayers.keys().contains("") && language == QString()) { return d->textLayers.values().at(0); } return d->textLayers.value(language); } void Page::setTextLayer(Textlayer* textlayer, const QString& language) { if(textlayer) { d->textLayers[language] = textlayer; } else { d->textLayers.remove(language); } emit textLayerLanguagesChanged(); } void Page::addTextLayer(const QString &language) { Textlayer* textLayer = new Textlayer(this); + textLayer->setLanguage(language); setTextLayer(textLayer, language); } void Page::removeTextLayer(const QString &language) { setTextLayer(nullptr, language); } QStringList Page::textLayerLanguages() const { + if (d->textLayers.isEmpty()) { + return QStringList(); + } return d->textLayers.keys(); } QList Page::frames() const { return d->frames; } Frame * Page::frame(int index) const { return d->frames.at(index); } int Page::frameIndex(Frame* frame) const { return d->frames.indexOf(frame); } void Page::addFrame(Frame* frame, int index) { if(index > -1 && d->frames.count() < index) { d->frames.insert(index, frame); } else { d->frames.append(frame); } emit frameCountChanged(); } void Page::removeFrame(Frame* frame) { d->frames.removeAll(frame); emit frameCountChanged(); } void Page::removeFrame(int index) { removeFrame(frame(index)); } void Page::addFrame(int index) { Frame* frame = new Frame(this); addFrame(frame, index); } bool Page::swapFrames(int swapThis, int withThis) { if(swapThis > -1 && withThis > -1) { d->frames.swap(swapThis, withThis); emit frameCountChanged(); return true; } return false; } int Page::frameCount() { return d->frames.size(); } QList Page::jumps() const { return d->jumps; } Jump * Page::jump(int index) const { return d->jumps.at(index); } int Page::jumpIndex(Jump* jump) const { return d->jumps.indexOf(jump); } void Page::addJump(Jump* jump, int index) { if(index > -1 && d->jumps.count() < index) { d->jumps.insert(index, jump); } else { d->jumps.append(jump); } emit jumpCountChanged(); } void Page::addJump(int pageIndex, int index) { Jump* jump = new Jump(this); jump->setPageIndex(pageIndex); addJump(jump, index); } void Page::removeJump(Jump* jump) { d->jumps.removeAll(jump); emit jumpCountChanged(); } void Page::removeJump(int index) { removeJump(jump(index)); } bool Page::swapJumps(int swapThis, int withThis) { if(swapThis > -1 && withThis > -1) { d->jumps.swap(swapThis, withThis); emit jumpCountChanged(); return true; } return false; } int Page::jumpCount() { return d->jumps.size(); } bool Page::isCoverPage() const { return d->isCoverPage; } void Page::setIsCoverPage(bool isCoverPage) { d->isCoverPage = isCoverPage; } diff --git a/src/creator/qml/AddPageArea.qml b/src/creator/qml/AddPageArea.qml new file mode 100644 index 0000000..3ef0dd0 --- /dev/null +++ b/src/creator/qml/AddPageArea.qml @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2018 Wolthera van Hövell tot Westerflier + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) version 3, or any + * later version accepted by the membership of KDE e.V. (or its + * successor approved by the membership of KDE e.V.), which shall + * act as a proxy defined in Section 6 of version 3 of the license. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + */ + +import QtQuick 2.2 + +import org.kde.kirigami 2.1 as Kirigami +import QtQuick.Controls 2.2 as QtControls +/** + * @brief a special overlay sheet for adding frames/textareas/jumps + */ +Kirigami.OverlaySheet { + id: root; + signal save(); + property alias type: typeComboBox.currentIndex; + property point topLeft; + property point bottomRight; + + Column { + height: childrenRect.height; + spacing: Kirigami.Units.smallSpacing; + Kirigami.Heading { + width: parent.width; + height: paintedHeight; + text: i18nc("title text for the add page area sheet", "Add Page Area"); + QtControls.Button { + id: saveButton; + anchors { + right: parent.right; + leftMargin: Kirigami.Units.smallSpacing; + } + contentItem: Kirigami.Icon { + source: "dialog-ok"; + } + height: parent.height; + width: height; + onClicked: { + root.save(); + root.close(); + } + } + QtControls.Button { + id: closeButton; + anchors { + right: saveButton.left; + rightMargin: Kirigami.Units.smallSpacing; + } + contentItem: Kirigami.Icon { + source: "dialog-cancel"; + } + height: parent.height; + width: height; + onClicked: { + root.close(); + } + } + } + Item { + width: parent.width; + height: Kirigami.Units.largeSpacing; + } + + QtControls.Label { + width: parent.width; + height: paintedHeight; + text: i18nc("label for the activity field", "Activity:"); + wrapMode: Text.WrapAtWordBoundaryOrAnywhere; + } + QtControls.ComboBox { + id: typeComboBox; + model: [i18n("Frame"), i18n("Textarea"), i18n("Jump")] + width: parent.width - Kirigami.Units.smallSpacing; + } + } +} diff --git a/src/creator/qml/BookPage.qml b/src/creator/qml/BookPage.qml index d5bf956..4cad54f 100644 --- a/src/creator/qml/BookPage.qml +++ b/src/creator/qml/BookPage.qml @@ -1,158 +1,241 @@ /* * Copyright (C) 2015 Dan Leinir Turthra Jensen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) version 3, or any * later version accepted by the membership of KDE e.V. (or its * successor approved by the membership of KDE e.V.), which shall * act as a proxy defined in Section 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . * */ import QtQuick 2.2 import org.kde.kirigami 2.1 as Kirigami /** * Page that holds an image to edit the frames on. */ Kirigami.Page { id: root; property string categoryName: "bookPage"; title: i18nc("title of the page editing sub-page for the book editor", "Page %1", root.pageTitle === "" ? root.index : root.pageTitle); property QtObject model; property QtObject currentPage; property int index: -1; property string pageUrl: ""; property string pageTitle: ""; signal save(); onIndexChanged: { if (root.index===0) { root.currentPage = root.model.acbfData.metaData.bookInfo.coverpage(); } else if (root.index > 0) { root.currentPage = root.model.acbfData.body.page(root.index-1); } root.pageTitle = root.currentPage.title(""); } actions { main: saveAndCloseAction; right: editPageDataAction; } Kirigami.Action { id: saveAndCloseAction; text: i18nc("Saves the remaining unsaved edited fields and closes the page editor", "Save and Close Page"); iconName: "dialog-ok"; onTriggered: { root.save(); root.model.setDirty(); pageStack.pop(); } } Kirigami.Action { id: editPageDataAction; text: i18nc("Saves the remaining unsaved edited fields and closes the page editor", "Save and Close Page"); iconName: "document-edit" onTriggered: pageStack.push(pageInfo) } Image { id: coverImage; anchors { fill: parent; margins: Kirigami.Units.smallSpacing; } asynchronous: true; fillMode: Image.PreserveAspectFit; source: pageUrl; width: root.width; height: root.height; property real muliplierWidth: (paintedWidth / sourceSize.width); property real muliplierHeight: (paintedHeight / sourceSize.height); property int offsetX: (width-paintedWidth)/2 property int offsetY: (height-paintedHeight)/2 Repeater { model: root.currentPage.frameCount Rectangle { width: coverImage.muliplierWidth * root.currentPage.frame(index).bounds.width; height: coverImage.muliplierHeight * root.currentPage.frame(index).bounds.height; x: coverImage.muliplierWidth * root.currentPage.frame(index).bounds.x + coverImage.offsetX y: coverImage.muliplierHeight * root.currentPage.frame(index).bounds.y + coverImage.offsetY; opacity: 0.2; color: "blue"; border.color: "blue"; Rectangle { anchors.fill: parent; border.color: "blue"; color: "transparent"; border.width: Kirigami.Units.smallSpacing; } } } Repeater { model: root.currentPage.textLayer("").textareaCount Rectangle { width: coverImage.muliplierWidth * root.currentPage.textLayer("").textarea(index).bounds.width; height: coverImage.muliplierHeight * root.currentPage.textLayer("").textarea(index).bounds.height; x: coverImage.muliplierWidth * root.currentPage.textLayer("").textarea(index).bounds.x + coverImage.offsetX y: coverImage.muliplierHeight * root.currentPage.textLayer("").textarea(index).bounds.y + coverImage.offsetY; opacity: { 0.2;} color: "red"; border.color: "red"; border.width: Kirigami.Units.smallSpacing; Rectangle { anchors.fill: parent; border.color: "red"; color: "transparent"; border.width: Kirigami.Units.smallSpacing; } } } Repeater { model: root.currentPage.jumpCount Rectangle { width: coverImage.muliplierWidth * root.currentPage.jump(index).bounds.width; height: coverImage.muliplierHeight * root.currentPage.jump(index).bounds.height; x: coverImage.muliplierWidth * root.currentPage.jump(index).bounds.x + coverImage.offsetX y: coverImage.muliplierHeight * root.currentPage.jump(index).bounds.y + coverImage.offsetY; opacity: { 0.2;} color: "green"; border.color: "green"; border.width: Kirigami.Units.smallSpacing; Rectangle { anchors.fill: parent; border.color: "green"; color: "transparent"; border.width: Kirigami.Units.smallSpacing; } } } + MouseArea { + anchors.fill: parent; + id: pointCatchArea; + property point startPoint:; + property point endPoint: ; + property bool dragging: false; + hoverEnabled: true; + + onClicked: { + if (dragging == false) { + startPoint = Qt.point(mouse.x, mouse.y); + endPoint = startPoint; + dragging = true; + } else { + if (Qt.point(mouse.x, mouse.y)!==startPoint) { + endPoint = Qt.point(mouse.x, mouse.y) + dragging = false; + createFrame(); + } + } + mouse.accepted + } + + onPositionChanged: { + if (dragging) { + endPoint = Qt.point(mouse.x, mouse.y) + } + } + + Rectangle { + x: Math.min(parent.startPoint.x, parent.endPoint.x); + y: Math.min(parent.startPoint.y, parent.endPoint.y); + width: Math.max(parent.startPoint.x, parent.endPoint.x) - Math.min(parent.startPoint.x, parent.endPoint.x); + height: Math.max(parent.startPoint.y, parent.endPoint.y) - Math.min(parent.startPoint.y, parent.endPoint.y); + opacity: 0.5; + border.color: "black"; + border.width: 1; + } + + function createFrame() { + var x = ( Math.min(startPoint.x, endPoint.x) - coverImage.offsetX ) / coverImage.muliplierWidth; + var x2 = ( Math.max(startPoint.x, endPoint.x) - coverImage.offsetX ) / coverImage.muliplierWidth; + var y = ( Math.min(startPoint.y, endPoint.y) - coverImage.offsetY ) / coverImage.muliplierHeight; + var y2 = ( Math.max(startPoint.y, endPoint.y) - coverImage.offsetY ) / coverImage.muliplierHeight; + + addPageArea.topLeft = Qt.point(x,y); + addPageArea.bottomRight = Qt.point(x2,y2); + endPoint = startPoint; + addPageArea.open(); + } + + } + + + + } Component { id: pageInfo; PageMetaInfo { page: root.currentPage; onSave: {root.pageTitle = page.title(""); root.model.setDirty();} } } + AddPageArea { + id: addPageArea + onSave: { + var index = 0; + if (type===0) { + index = root.currentPage.frameCount; + root.currentPage.addFrame(index); + root.currentPage.frame(index).setPointsFromRect(topLeft, bottomRight); + } else if (type===1) { + console.log(root.currentPage.textLayerLanguages) + console.log(root.currentPage.textLayerLanguages.length) + if (root.currentPage.textLayerLanguages.length === 0) { + console.log("gonna add a textlayer") + root.currentPage.addTextLayer("") + } + index = root.currentPage.textLayer("").textareaCount; + console.log(index); + root.currentPage.textLayer("").addTextarea(index); + root.currentPage.textLayer("").textarea(index).setPointsFromRect(topLeft, bottomRight); + } else if (type===2) { + index = root.currentPage.jumpCount; + root.currentPage.addJump(index); + root.currentPage.jump(index).setPointsFromRect(topLeft, bottomRight); + } + } + } + } diff --git a/src/creator/qml/PageMetaInfo.qml b/src/creator/qml/PageMetaInfo.qml index 5c23931..d05ed13 100644 --- a/src/creator/qml/PageMetaInfo.qml +++ b/src/creator/qml/PageMetaInfo.qml @@ -1,247 +1,269 @@ /* * Copyright (C) 2018 Wolthera van Hövell tot Westerflier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) version 3, or any * later version accepted by the membership of KDE e.V. (or its * successor approved by the membership of KDE e.V.), which shall * act as a proxy defined in Section 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . * */ import QtQuick 2.2 import QtQuick.Controls 2.2 as QtControls import org.kde.kirigami 2.1 as Kirigami /** * Page that holds an image to edit the frames on. */ import QtQuick 2.0 Kirigami.ScrollablePage { id: root; title: i18nc("title text for the page meta information editor sheet", "Edit Page Information"); property QtObject page; property string colorname: "#ffffff"; signal save(); actions { main: saveAndCloseAction; } Kirigami.Action { id: saveAndCloseAction; text: i18nc("Saves the remaining unsaved edited fields and closes the metainfo editor", "Close Editor"); iconName: "dialog-ok"; onTriggered: { root.page.setTitle(defaultTitle.text, "") root.page.bgcolor = pageBackgroundColor.text; root.save(); pageStack.pop(); } } Column { id: contentColumn; width: root.width - (root.leftPadding + root.rightPadding); height: childrenRect.height; spacing: Kirigami.Units.smallSpacing; Kirigami.Heading { width: parent.width; height: paintedHeight + Kirigami.Units.smallSpacing * 2; text: i18nc("label text for the edit field for the page title", "Title"); } Item { width: parent.width; height: Kirigami.Units.smallSpacing; } QtControls.TextField { id: defaultTitle; width: parent.width; placeholderText: i18nc("placeholder text for default page text-input", "Write to add default title"); text: root.page.title(""); onEditingFinished: root.page.setTitle(text, ""); } Kirigami.Heading { width: parent.width; height: paintedHeight + Kirigami.Units.smallSpacing * 2; text: i18nc("label text for the edit field for the page transition type", "Transition"); } Item { width: parent.width; height: Kirigami.Units.smallSpacing; } QtControls.ComboBox { id: transition; width: parent.width; model: root.page.availableTransitions(); currentIndex: root.page.transition!==""? root.page.availableTransitions().indexOf(root.page.transition): root.page.availableTransitions().indexOf("none"); onActivated: root.page.transition = currentText; } Kirigami.Heading { width: parent.width; height: paintedHeight + Kirigami.Units.smallSpacing * 2; text: i18nc("label text for the edit field for the page background color", "Background Color"); } Item { width: parent.width; height: Kirigami.Units.smallSpacing; } QtControls.TextField { id: pageBackgroundColor; width: parent.width; placeholderText: root.colorname; text: root.page.bgcolor; onEditingFinished: root.page.bgcolor = text; } Kirigami.Heading { width: parent.width; height: paintedHeight + Kirigami.Units.smallSpacing * 2; text: i18nc("label text for the edit field for the page frames", "Frames"); } ListView { width: parent.width; height: childrenRect.height; model: page.frameCount delegate: Kirigami.SwipeListItem { id: frameItem; height: Kirigami.Units.iconSizes.huge + Kirigami.Units.smallSpacing * 2; width: parent.width; supportsMouseEvents: true; actions: [ Kirigami.Action { text: i18nc("swap the position of this frame with the previous one", "Move Up"); iconName: "go-up" onTriggered: { page.swapFrames(index, index - 1); } enabled: index > 0; visible: enabled; }, Kirigami.Action { text: i18nc("swap the position of this frame with the next one", "Move Down"); iconName: "go-down" onTriggered: { page.swapFrames(index, index + 1); } enabled: index < page.frameCount - 1; visible: enabled; + }, + Kirigami.Action { + text: i18nc("remove the frame from the page", "Delete Frame"); + iconName: "list-remove" + onTriggered: page.removeFrame(index); } ] Item { anchors.fill: parent; QtControls.Label { text: i18nc("Comic book panel frame name.", "Frame %1", index+1); } } } } Kirigami.Heading { width: parent.width; height: paintedHeight + Kirigami.Units.smallSpacing * 2; text: i18nc("label text for the edit field for the page textareas", "Text Areas"); } ListView { model: page.textLayer("").textareaCount; width: parent.width; height: childrenRect.height; delegate: Kirigami.SwipeListItem { id: textAreaItem; height: Kirigami.Units.iconSizes.huge + Kirigami.Units.smallSpacing * 2; supportsMouseEvents: true; actions: [ Kirigami.Action { - text: i18nc("swap the position of this frame with the previous one", "Move Up"); + text: i18nc("swap the position of this text area with the previous one", "Move Up"); iconName: "go-up" onTriggered: { page.textLayer("").swapTextareas(index, index - 1); } enabled: index > 0; visible: enabled; }, Kirigami.Action { - text: i18nc("swap the position of this frame with the next one", "Move Down"); + text: i18nc("swap the position of this text area with the next one", "Move Down"); iconName: "go-down" onTriggered: { page.textLayer("").swapTextareas(index, index + 1); } enabled: index < page.textLayer("").textareaCount - 1; visible: enabled; + }, + Kirigami.Action { + text: i18nc("remove the text area from the page", "Delete Text Area"); + iconName: "list-remove" + onTriggered: page.textLayer("").removeTextarea(index); } ] Item { anchors.fill:parent; QtControls.Label { id: textareaLabel; text: i18nc("Comic book panel textarea name.", "Text Area %1", index+1); } QtControls.TextArea { anchors { top: textareaLabel.bottom; topMargin: Kirigami.Units.smallSpacing; } width:parent.width-Kirigami.Units.iconSizes.huge; text: page.textLayer("").textarea(index).paragraphs.join("\n\n"); onEditingFinished: page.textLayer("").textarea(index).paragraphs = text.split("\n\n"); } } } } Kirigami.Heading { width: parent.width; height: paintedHeight + Kirigami.Units.smallSpacing * 2; text: i18nc("label text for the edit field for the page jumps", "Jumps"); } ListView { model: page.jumpCount width: parent.width; height: childrenRect.height; delegate: Kirigami.SwipeListItem { id: jumpItem; height: Kirigami.Units.iconSizes.huge + Kirigami.Units.smallSpacing * 2; supportsMouseEvents: true; actions: [ Kirigami.Action { - text: i18nc("swap the position of this frame with the previous one", "Move Up"); + text: i18nc("swap the position of this jump with the previous one", "Move Up"); iconName: "go-up" onTriggered: { page.swapJumps(index, index - 1); } enabled: index > 0; visible: enabled; }, Kirigami.Action { - text: i18nc("swap the position of this frame with the next one", "Move Down"); + text: i18nc("swap the position of this jump with the next one", "Move Down"); iconName: "go-down" onTriggered: { page.swapJumps(index, index + 1); } enabled: index < page.jumpCount - 1; visible: enabled; + }, + Kirigami.Action { + text: i18nc("remove the jump from the page", "Delete Jump"); + iconName: "list-remove" + onTriggered: page.removeJump(index); } ] Item { anchors.fill:parent; QtControls.Label { id: jumpLabel; text: i18nc("Comic book panel jump name.", "Jump %1", index+1); } QtControls.Label { id: pageIndexLabel; + anchors { + top: jumpLabel.bottom; + topMargin: Kirigami.Units.smallSpacing; + } + height: jumpIndexSpin.height; text: i18nc("Label from jump page index.", "Page Index:"); } + QtControls.SpinBox { anchors { top: jumpLabel.bottom; topMargin: Kirigami.Units.smallSpacing; left: pageIndexLabel.right; leftMargin: Kirigami.Units.smallSpacing; } from: 0; to: 99; + id: jumpIndexSpin; value: page.jump(index).pageIndex; onValueChanged: { if (page.jump(index).pageIndex !== value) { page.jump(index).pageIndex = value; } } } } } } } }