diff --git a/src/acbf/AcbfTextarea.cpp b/src/acbf/AcbfTextarea.cpp index 283f37b..5197608 100644 --- a/src/acbf/AcbfTextarea.cpp +++ b/src/acbf/AcbfTextarea.cpp @@ -1,297 +1,300 @@ /* * Copyright (C) 2016 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 "AcbfTextarea.h" #include #include using namespace AdvancedComicBookFormat; class Textarea::Private { public: Private() : textRotation(0) + , type ("speech") + , inverted(false) + , transparent(false) {} QString bgcolor; QList points; int textRotation; QString type; bool inverted; bool transparent; QStringList paragraphs; }; Textarea::Textarea(Textlayer* parent) : QObject(parent) , d(new Private) { qRegisterMetaType("Textarea*"); connect(this, SIGNAL(pointCountChanged()), this, SIGNAL(boundsChanged())); } Textarea::~Textarea() = default; void Textarea::toXml(QXmlStreamWriter* writer) { writer->writeStartElement(QStringLiteral("text-area")); QStringList points; Q_FOREACH(const QPoint& point, d->points) { points << QStringLiteral("%1,%2").arg(QString::number(point.x())).arg(QString::number(point.y())); } writer->writeAttribute(QStringLiteral("points"), points.join(' ')); if(!d->bgcolor.isEmpty()) { writer->writeAttribute(QStringLiteral("bgcolor"), d->bgcolor); } if(d->textRotation != 0) { writer->writeAttribute(QStringLiteral("text-rotation"), QString::number(d->textRotation)); } if(!d->type.isEmpty()) { writer->writeAttribute(QStringLiteral("type"), d->type); } if(d->inverted) { // because the default is false, no need to write it otherwise... writer->writeAttribute(QStringLiteral("inverted"), QStringLiteral("true")); } if(d->transparent) { // because the default is false, no need to write it otherwise... writer->writeAttribute(QStringLiteral("transparent"), QStringLiteral("true")); } Q_FOREACH(const QString& paragraph, d->paragraphs) { writer->writeStartElement(QStringLiteral("p")); writer->writeCharacters(paragraph); writer->writeEndElement(); } writer->writeEndElement(); } bool Textarea::fromXml(QXmlStreamReader *xmlReader) { setBgcolor(xmlReader->attributes().value(QStringLiteral("bgcolor")).toString()); setTextRotation(xmlReader->attributes().value(QStringLiteral("text-rotation")).toInt()); setType(xmlReader->attributes().value(QStringLiteral("type")).toString()); setInverted(xmlReader->attributes().value(QStringLiteral("inverted")).toString().toLower() == QStringLiteral("true")); setTransparent(xmlReader->attributes().value(QStringLiteral("transparent")).toString().toLower() == QStringLiteral("true")); QStringList points = xmlReader->attributes().value(QStringLiteral("points")).toString().split(' '); Q_FOREACH(const QString& point, points) { QStringList elements = point.split(','); if(elements.length() == 2) { addPoint(QPoint(elements.at(0).toInt(), elements.at(1).toInt())); } else { qCWarning(ACBF_LOG) << "Failed to construct one of the points for a text-area. Attempted to handle the point" << point << "in the data" << points; return false; } } while(xmlReader->readNextStartElement()) { if(xmlReader->name() == QStringLiteral("p")) { d->paragraphs.append(xmlReader->readElementText(QXmlStreamReader::IncludeChildElements)); } else { qCWarning(ACBF_LOG) << Q_FUNC_INFO << "currently unsupported subsection in text-area:" << xmlReader->name(); xmlReader->skipCurrentElement(); } } if (xmlReader->hasError()) { 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(); } qCDebug(ACBF_LOG) << Q_FUNC_INFO << "Created a text area of type" << type(); return !xmlReader->hasError(); } QList Textarea::points() const { return d->points; } QPoint Textarea::point(int index) const { return d->points.at(index); } int Textarea::pointIndex(const QPoint& point) const { return d->points.indexOf(point); } void Textarea::addPoint(const QPoint& point, int index) { if(index > -1 && d->points.count() < index) { d->points.insert(index, point); } else { d->points.append(point); } emit pointCountChanged(); } void Textarea::removePoint(const QPoint& point) { d->points.removeAll(point); emit pointCountChanged(); } bool Textarea::swapPoints(const QPoint& swapThis, const QPoint& withThis) { int index1 = d->points.indexOf(swapThis); int index2 = d->points.indexOf(withThis); if(index1 > -1 && index2 > -1) { d->points.swap(index1, index2); emit pointCountChanged(); return true; } return false; } void Textarea::setPointsFromRect(const QPoint &topLeft, const QPoint &bottomRight) { QRect rect(topLeft, bottomRight); d->points.clear(); d->points.append(rect.topLeft()); d->points.append(rect.topRight()); d->points.append(rect.bottomRight()); d->points.append(rect.bottomLeft()); emit pointCountChanged(); } int Textarea::pointCount() const { return d->points.size(); } QRect Textarea::bounds() const { // Would use QPolygon here, but that requires including QTGUI. if (d->points.size()==0) { return QRect(); } QRect rect(d->points.at(0), d->points.at(1)); for (int i = 2; i < d->points.size(); i++) { QPoint p = d->points.at(i); if (rect.left() > p.x()) { rect.setLeft(p.x()); } if (rect.right() < p.x()) { rect.setRight(p.x()); } if (rect.bottom() < p.y()) { rect.setBottom(p.y()); } if (rect.top() > p.y()) { rect.setTop(p.y()); } } return rect; } QString Textarea::bgcolor() const { return d->bgcolor; } void Textarea::setBgcolor(const QString& newColor) { d->bgcolor = newColor; emit bgcolorChanged(); } void Textarea::setTextRotation(int rotation) { d->textRotation = rotation; emit textRotationChanged(); } int Textarea::textRotation() const { return d->textRotation; } QString Textarea::type() const { return d->type.isEmpty() ? "speech" : d->type; } void Textarea::setType(const QString& type) { d->type = type; emit typeChanged(); } QStringList Textarea::availableTypes() { return { QStringLiteral("speech"), // (character is speaking, text is centered) QStringLiteral("commentary"), // (accompanying commentary, text is aligned to left) QStringLiteral("formal"), // (text alignment is - justify) QStringLiteral("letter"), // (rendered in handwriting font) QStringLiteral("code"), // (rendered in monospace font) QStringLiteral("heading"), // (e.g. chapter title) QStringLiteral("audio"), // (speech emanating from an audio device, e.g., television or radio speaker, telephone, walkie-talkie, etc.) QStringLiteral("thought"), QStringLiteral("sign"), // (any kind of sign/writing, text is centered) QStringLiteral("sound"), // /new in 1.2/ }; } bool Textarea::inverted() const { return d->inverted; } void Textarea::setInverted(bool inverted) { d->inverted = inverted; emit invertedChanged(); } bool Textarea::transparent() const { return d->transparent; } void Textarea::setTransparent(bool transparent) { d->transparent = transparent; emit transparentChanged(); } QStringList Textarea::paragraphs() const { return d->paragraphs; } void Textarea::setParagraphs(const QStringList& paragraphs) { d->paragraphs = paragraphs; emit paragraphsChanged(); }