File indexing completed on 2024-05-26 04:38:00
0001 /* 0002 * Copyright 2018 Wolthera van Hövell tot Westerflier <griffinvalley@gmail.com> 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 "AcbfFrame.h" 0023 #include <QXmlStreamReader> 0024 0025 #include <acbf_debug.h> 0026 0027 using namespace AdvancedComicBookFormat; 0028 0029 class Frame::Private 0030 { 0031 public: 0032 Private() 0033 {} 0034 QString id; 0035 QString bgcolor; 0036 QList<QPoint> points; 0037 }; 0038 0039 Frame::Frame(Page* parent) 0040 : InternalReferenceObject(InternalReferenceObject::ReferenceTarget, parent) 0041 , d(new Private) 0042 { 0043 static const int typeId = qRegisterMetaType<Frame*>("Frame*"); 0044 Q_UNUSED(typeId); 0045 connect(this, &Frame::pointCountChanged, this, &Frame::boundsChanged); 0046 0047 connect(this, &Frame::idChanged, this, &InternalReferenceObject::propertyDataChanged); 0048 connect(this, &Frame::bgcolorChanged, this, &InternalReferenceObject::propertyDataChanged); 0049 connect(this, &Frame::boundsChanged, this, &InternalReferenceObject::propertyDataChanged); 0050 } 0051 0052 Frame::~Frame() = default; 0053 0054 void Frame::toXml(QXmlStreamWriter* writer) { 0055 writer->writeStartElement(QStringLiteral("frame")); 0056 if(!d->id.isEmpty()) { 0057 writer->writeAttribute(QStringLiteral("id"), id()); 0058 } 0059 0060 QStringList points; 0061 for(const QPoint& point : d->points) { 0062 points << QStringLiteral("%1,%2").arg(QString::number(point.x())).arg(QString::number(point.y())); 0063 } 0064 writer->writeAttribute(QStringLiteral("points"), points.join(' ')); 0065 if(!d->bgcolor.isEmpty()) { 0066 writer->writeAttribute(QStringLiteral("bgcolor"), d->bgcolor); 0067 } 0068 writer->writeEndElement(); 0069 } 0070 0071 bool Frame::fromXml(QXmlStreamReader *xmlReader) 0072 { 0073 setId(xmlReader->attributes().value(QStringLiteral("id")).toString()); 0074 setBgcolor(xmlReader->attributes().value(QStringLiteral("bgcolor")).toString()); 0075 0076 QVector<QStringRef> points = xmlReader->attributes().value(QStringLiteral("points")).split(' '); 0077 for(QStringRef point : points) { 0078 QVector<QStringRef> elements = point.split(','); 0079 if(elements.length() == 2) 0080 { 0081 addPoint(QPoint(elements.at(0).toInt(), elements.at(1).toInt())); 0082 } 0083 else 0084 { 0085 qCWarning(ACBF_LOG) << "Failed to construct one of the points for a frame. Attempted to handle the point" << point << "in the data" << points; 0086 return false; 0087 } 0088 } 0089 0090 if (xmlReader->hasError()) { 0091 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(); 0092 } 0093 qCDebug(ACBF_LOG) << Q_FUNC_INFO << "Created a frame with " << points.count() << "points"; 0094 0095 return !xmlReader->hasError(); 0096 } 0097 0098 QString Frame::id() const 0099 { 0100 return d->id; 0101 } 0102 0103 void Frame::setId(const QString& newId) 0104 { 0105 if (d->id != newId) { 0106 d->id = newId; 0107 Q_EMIT idChanged(); 0108 } 0109 } 0110 0111 QList<QPoint> Frame::points() const 0112 { 0113 return d->points; 0114 } 0115 0116 QPoint Frame::point(int index) const 0117 { 0118 return d->points.at(index); 0119 } 0120 0121 int Frame::pointIndex(const QPoint& point) const 0122 { 0123 return d->points.indexOf(point); 0124 } 0125 0126 void Frame::addPoint(const QPoint& point, int index) 0127 { 0128 if(index > -1 && d->points.count() < index) { 0129 d->points.insert(index, point); 0130 } 0131 else { 0132 d->points.append(point); 0133 } 0134 emit pointCountChanged(); 0135 } 0136 0137 void Frame::removePoint(const QPoint& point) 0138 { 0139 d->points.removeAll(point); 0140 emit pointCountChanged(); 0141 } 0142 0143 bool Frame::swapPoints(const QPoint& swapThis, const QPoint& withThis) 0144 { 0145 int index1 = d->points.indexOf(swapThis); 0146 int index2 = d->points.indexOf(withThis); 0147 if(index1 > -1 && index2 > -1) { 0148 d->points.swapItemsAt(index1, index2); 0149 emit pointCountChanged(); 0150 return true; 0151 } 0152 return false; 0153 } 0154 0155 void Frame::setPointsFromRect(const QPoint &topLeft, const QPoint &bottomRight) 0156 { 0157 QRect rect(topLeft, bottomRight); 0158 d->points.clear(); 0159 d->points.append(rect.topLeft()); 0160 d->points.append(rect.topRight()); 0161 d->points.append(rect.bottomRight()); 0162 d->points.append(rect.bottomLeft()); 0163 emit pointCountChanged(); 0164 } 0165 0166 int Frame::pointCount() const 0167 { 0168 return d->points.size(); 0169 } 0170 0171 QRect Frame::bounds() const 0172 { 0173 // Would use QPolygon here, but that requires including QTGUI. 0174 if (d->points.size()==0) { 0175 return QRect(); 0176 } 0177 QRect rect(d->points.at(0), d->points.at(1)); 0178 for (int i = 2; i < d->points.size(); i++) { 0179 QPoint p = d->points.at(i); 0180 if (rect.left() > p.x()) { 0181 rect.setLeft(p.x()); 0182 } 0183 if (rect.right() < p.x()) { 0184 rect.setRight(p.x()); 0185 } 0186 if (rect.bottom() < p.y()) { 0187 rect.setBottom(p.y()); 0188 } 0189 if (rect.top() > p.y()) { 0190 rect.setTop(p.y()); 0191 } 0192 } 0193 return rect; 0194 } 0195 0196 QString Frame::bgcolor() const 0197 { 0198 return d->bgcolor; 0199 } 0200 0201 void Frame::setBgcolor(const QString& newColor) 0202 { 0203 d->bgcolor = newColor; 0204 emit bgcolorChanged(); 0205 } 0206 0207 int AdvancedComicBookFormat::Frame::localIndex() 0208 { 0209 int idx{-1}; 0210 Page* page = qobject_cast<Page*>(parent()); 0211 if (page) { 0212 idx = page->frameIndex(this); 0213 } 0214 return idx; 0215 }