File indexing completed on 2024-05-26 04:38:02

0001 /*
0002  * Copyright (C) 2016 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 #include "AcbfTextlayer.h"
0023 #include "AcbfTextarea.h"
0024 
0025 #include <QXmlStreamReader>
0026 #include <QXmlStreamWriter>
0027 
0028 #include <acbf_debug.h>
0029 
0030 using namespace AdvancedComicBookFormat;
0031 
0032 class Textlayer::Private
0033 {
0034 public:
0035     Private() {}
0036     QString language;
0037     QString bgcolor;
0038     QList<Textarea*> textareas;
0039 };
0040 
0041 Textlayer::Textlayer(Page* parent)
0042     : QObject(parent)
0043     , d(new Private)
0044 {
0045     static const int typeId = qRegisterMetaType<Textlayer*>("Textlayer*");
0046     Q_UNUSED(typeId);
0047 }
0048 
0049 Textlayer::~Textlayer() = default;
0050 
0051 void Textlayer::toXml(QXmlStreamWriter* writer)
0052 {
0053     writer->writeStartElement(QStringLiteral("text-layer"));
0054     if(!d->language.isEmpty()) {
0055         writer->writeAttribute(QStringLiteral("lang"), d->language);
0056     }
0057     if(!d->bgcolor.isEmpty()) {
0058         writer->writeAttribute(QStringLiteral("bgcolor"), d->bgcolor);
0059     }
0060 
0061     for(Textarea* area : d->textareas) {
0062         area->toXml(writer);
0063     }
0064 
0065     writer->writeEndElement();
0066 }
0067 
0068 bool Textlayer::fromXml(QXmlStreamReader *xmlReader, const QString& xmlData)
0069 {
0070     setBgcolor(xmlReader->attributes().value(QStringLiteral("bgcolor")).toString());
0071     setLanguage(xmlReader->attributes().value(QStringLiteral("lang")).toString());
0072     while(xmlReader->readNextStartElement())
0073     {
0074         if(xmlReader->name() == QStringLiteral("text-area"))
0075         {
0076             Textarea* newArea = new Textarea(this);
0077             if(!newArea->fromXml(xmlReader, xmlData)) {
0078                 return false;
0079             }
0080             d->textareas.append(newArea);
0081         }
0082         else
0083         {
0084             qCWarning(ACBF_LOG) << Q_FUNC_INFO << "currently unsupported subsection:" << xmlReader->name();
0085             xmlReader->skipCurrentElement();
0086         }
0087     }
0088     if (xmlReader->hasError()) {
0089         qCWarning(ACBF_LOG) << Q_FUNC_INFO << "Failed to read ACBF XML document at token" << xmlReader->name() << "(" << xmlReader->lineNumber() << ":" << xmlReader->columnNumber() << ") The reported error was:" << xmlReader->errorString();
0090     }
0091     qCDebug(ACBF_LOG) << Q_FUNC_INFO << "Created a text layer with" << d->textareas.count() << "text areas";
0092     return !xmlReader->hasError();
0093 }
0094 
0095 QString Textlayer::language() const
0096 {
0097     return d->language;
0098 }
0099 
0100 void Textlayer::setLanguage(const QString& language)
0101 {
0102     d->language = language;
0103     emit languageChanged();
0104 }
0105 
0106 QString Textlayer::bgcolor() const
0107 {
0108     if (d->bgcolor.isEmpty()) {
0109         Page* page = qobject_cast<Page*>(parent());
0110         if (page) {
0111             return page->bgcolor();
0112         }
0113     }
0114     return d->bgcolor;
0115 }
0116 
0117 void Textlayer::setBgcolor(const QString& newColor)
0118 {
0119     d->bgcolor = newColor;
0120     emit bgcolorChanged();
0121 }
0122 
0123 QObjectList Textlayer::textareas() const
0124 {
0125     QObjectList areas;
0126     for (Textarea* area : d->textareas) {
0127         areas << area;
0128     }
0129     return areas;
0130 }
0131 
0132 int Textlayer::textAreaIndex(Textarea* textarea)
0133 {
0134     return d->textareas.indexOf(textarea);
0135 }
0136 
0137 Textarea * Textlayer::textarea(int index) const
0138 {
0139     return d->textareas.at(index);
0140 }
0141 
0142 int Textlayer::textareaIndex(Textarea* textarea) const
0143 {
0144     return d->textareas.indexOf(textarea);
0145 }
0146 
0147 void Textlayer::addTextarea(Textarea* textarea, int index)
0148 {
0149     if(index > -1 && d->textareas.count() < index) {
0150         d->textareas.insert(index, textarea);
0151     }
0152     else {
0153         d->textareas.append(textarea);
0154     }
0155     Q_EMIT textareaAdded(textarea);
0156     Q_EMIT textareasChanged();
0157     Q_EMIT textareaPointStringsChanged();
0158 }
0159 
0160 void Textlayer::addTextarea(int index)
0161 {
0162     Textarea* text = new Textarea(this);
0163     addTextarea(text, index);
0164 }
0165 
0166 void Textlayer::removeTextarea(Textarea* textarea)
0167 {
0168     d->textareas.removeAll(textarea);
0169     Q_EMIT textareasChanged();
0170     Q_EMIT textareaPointStringsChanged();
0171 }
0172 
0173 void Textlayer::removeTextarea(int index)
0174 {
0175     removeTextarea(textarea(index));
0176 }
0177 
0178 bool Textlayer::swapTextareas(int swapThis, int withThis)
0179 {
0180     bool success{false};
0181     if (swapThis > -1 && swapThis < d->textareas.count() && withThis > -1 && withThis < d->textareas.count()) {
0182         d->textareas.swapItemsAt(swapThis, withThis);
0183         InternalReferenceObject* first = qobject_cast<InternalReferenceObject*>(d->textareas[swapThis]);
0184         InternalReferenceObject* second = qobject_cast<InternalReferenceObject*>(d->textareas[withThis]);
0185         Q_EMIT first->propertyDataChanged();
0186         Q_EMIT second->propertyDataChanged();
0187         Q_EMIT textareasChanged();
0188         Q_EMIT textareaPointStringsChanged();
0189         success = true;
0190     } else {
0191         qCWarning(ACBF_LOG) << "There was an attempt to swap two textareas, and at least one of them was outside the bounds of the current list of textareas in this layer:" << this << swapThis << withThis;
0192     }
0193     return success;
0194 }
0195 
0196 QStringList Textlayer::textareaPointStrings()
0197 {
0198     QStringList textAreaList;
0199     for (int i=0; i<d->textareas.size(); i++) {
0200         QStringList points;
0201         for (int p=0; p< textarea(i)->pointCount(); p++) {
0202             points.append(QString("%1,%2").arg(textarea(i)->point(p).x()).arg(textarea(i)->point(p).y()));
0203         }
0204         textAreaList.append(points.join(" "));
0205     }
0206     return textAreaList;
0207 }