File indexing completed on 2024-04-28 04:32:04

0001 /*
0002  * Copyright (C) 2010-2015 by Stephen Allewell
0003  * steve.allewell@gmail.com
0004  *
0005  * This program is free software; you can redistribute it and/or modify
0006  * it under the terms of the GNU General Public License as published by
0007  * the Free Software Foundation; either version 2 of the License, or
0008  * (at your option) any later version.
0009  */
0010 
0011 #include "Page.h"
0012 
0013 #include <QPainter>
0014 #include <QPrinterInfo>
0015 
0016 #include <KLocalizedString>
0017 
0018 #include "Document.h"
0019 #include "Element.h"
0020 #include "Exceptions.h"
0021 
0022 Page::Page(QPageSize pageSize, QPageLayout::Orientation orientation)
0023     : QPageLayout(
0024         pageSize,
0025         orientation,
0026         QMarginsF(Configuration::page_MarginLeft(), Configuration::page_MarginTop(), Configuration::page_MarginRight(), Configuration::page_MarginBottom()),
0027         QPageLayout::Millimeter)
0028     , m_pageNumber(0)
0029 {
0030 }
0031 
0032 Page::Page(const Page &other)
0033     : QPageLayout(other)
0034 {
0035     *this = other;
0036 }
0037 
0038 Page::~Page()
0039 {
0040     qDeleteAll(m_elements);
0041 }
0042 
0043 Page &Page::operator=(const Page &other)
0044 {
0045     if (this != &other) {
0046         qDeleteAll(m_elements);
0047         m_elements.clear();
0048 
0049         m_pageNumber = other.m_pageNumber;
0050 
0051         QListIterator<Element *> elementIterator(other.m_elements);
0052 
0053         while (elementIterator.hasNext()) {
0054             Element *element = elementIterator.next();
0055 
0056             if (element->type() != Element::Plan) {
0057                 Element *cloned = element->clone();
0058                 cloned->setParent(this);
0059                 m_elements.append(cloned);
0060 
0061                 if (cloned->type() == Element::Pattern) {
0062                     if (dynamic_cast<PatternElement *>(cloned)->showPlan()) {
0063                         cloned = dynamic_cast<PatternElement *>(cloned)->planElement();
0064                         cloned->setParent(this);
0065                         m_elements.append(cloned);
0066                     }
0067                 }
0068             }
0069         }
0070     }
0071 
0072     return *this;
0073 }
0074 
0075 int Page::pageNumber() const
0076 {
0077     return m_pageNumber;
0078 }
0079 
0080 const QList<Element *> Page::elements() const
0081 {
0082     return m_elements;
0083 }
0084 
0085 void Page::setPageNumber(int pageNumber)
0086 {
0087     m_pageNumber = pageNumber;
0088 }
0089 
0090 void Page::addElement(Element *element)
0091 {
0092     m_elements.append(element);
0093 }
0094 
0095 void Page::removeElement(Element *element)
0096 {
0097     m_elements.removeOne(element);
0098 }
0099 
0100 void Page::render(Document *document, QPainter *painter) const
0101 {
0102     painter->save();
0103 
0104     if (painter->device()->paintEngine() == nullptr) {
0105         painter->setPen(QPen(Qt::red, 0.05));
0106         painter->drawRect(painter->window().marginsRemoved(margins().toMargins()));
0107     }
0108 
0109     QListIterator<Element *> elementIterator(m_elements);
0110 
0111     while (elementIterator.hasNext()) {
0112         Element *element = elementIterator.next();
0113         element->render(document, painter);
0114     }
0115 
0116     painter->restore();
0117 }
0118 
0119 Element *Page::itemAt(const QPoint &pos) const
0120 {
0121     Element *element = nullptr;
0122 
0123     if (m_elements.count()) {
0124         QListIterator<Element *> elementIterator(m_elements);
0125         elementIterator.toBack(); // start from the end of the list
0126 
0127         while (elementIterator.hasPrevious()) {
0128             Element *testElement = elementIterator.previous();
0129 
0130             if (testElement->rectangle().contains(pos)) {
0131                 element = testElement;
0132                 break;
0133             }
0134         }
0135     }
0136 
0137     return element; // will be the element under the cursor or 0
0138 }
0139 
0140 QDataStream &operator<<(QDataStream &stream, const Page &page)
0141 {
0142     stream << qint32(page.version);
0143 
0144     stream << qint32(page.m_pageNumber) << qint32(page.pageSize().id()) << qint32(page.orientation()) << qint32(page.margins().left())
0145            << qint32(page.margins().top()) << qint32(page.margins().right()) << qint32(page.margins().bottom()) << qint32(page.m_elements.count());
0146 
0147     QListIterator<Element *> elementIterator(page.m_elements);
0148 
0149     while (elementIterator.hasNext()) {
0150         const Element *element = elementIterator.next();
0151         stream << qint32(element->type());
0152 
0153         if (element->type() != Element::Plan) {
0154             stream << *element;
0155         }
0156     }
0157 
0158     if (stream.status() != QDataStream::Ok) {
0159         throw FailedWriteFile(stream.status());
0160     }
0161 
0162     return stream;
0163 }
0164 
0165 QDataStream &operator>>(QDataStream &stream, Page &page)
0166 {
0167     qint32 version;
0168     qint32 pageNumber;
0169     qint32 pageSizeId;
0170     qint32 orientation;
0171     qint32 left;
0172     qint32 top;
0173     qint32 right;
0174     qint32 bottom;
0175     qint32 showGrid;
0176     qint32 gridX;
0177     qint32 gridY;
0178     qreal zoomFactor;
0179 
0180     stream >> version;
0181 
0182     switch (version) {
0183     case 102:
0184         stream >> pageNumber >> pageSizeId >> orientation >> left >> top >> right >> bottom;
0185         page.m_pageNumber = pageNumber;
0186         page.setPageSize(QPageSize(static_cast<QPageSize::PageSizeId>(pageSizeId)));
0187         page.setOrientation(static_cast<QPageLayout::Orientation>(orientation));
0188         page.setMargins(QMarginsF(left, top, right, bottom));
0189 
0190         page.readElements(stream);
0191         break;
0192 
0193     case 101:
0194         stream >> pageNumber >> pageSizeId >> orientation >> left >> top >> right >> bottom >> showGrid >> gridX >> gridY;
0195         page.m_pageNumber = pageNumber;
0196         page.setPageSize(QPageSize(static_cast<QPageSize::PageSizeId>(pageSizeId)));
0197         page.setOrientation(static_cast<QPageLayout::Orientation>(orientation));
0198         page.setMargins(QMarginsF(left, top, right, bottom));
0199 
0200         page.readElements(stream);
0201 
0202         stream >> zoomFactor;
0203         break;
0204 
0205     case 100:
0206         stream >> pageSizeId >> orientation >> left >> top >> right >> bottom;
0207         page.setPageSize(QPageSize(static_cast<QPageSize::PageSizeId>(pageSizeId)));
0208         page.setOrientation(static_cast<QPageLayout::Orientation>(orientation));
0209         page.setMargins(QMarginsF(left, top, right, bottom));
0210 
0211         page.readElements(stream);
0212 
0213         stream >> zoomFactor;
0214         break;
0215 
0216     default:
0217         throw InvalidFileVersion(QString(i18n("Page version %1", version)));
0218         break;
0219     }
0220 
0221     return stream;
0222 }
0223 
0224 void Page::readElements(QDataStream &stream)
0225 {
0226     qint32 elements;
0227     qint32 type;
0228     Element *element;
0229 
0230     stream >> elements;
0231 
0232     while (elements--) {
0233         stream >> type;
0234 
0235         switch (static_cast<Element::Type>(type)) {
0236         case Element::Text:
0237             element = new TextElement(this, QRect());
0238             break;
0239 
0240         case Element::Pattern:
0241             element = new PatternElement(this, QRect());
0242             break;
0243 
0244         case Element::Plan:
0245             element = nullptr; // handled by the PatternElement
0246             break;
0247 
0248         case Element::Key:
0249             element = new KeyElement(this, QRect());
0250             break;
0251 
0252         case Element::Image:
0253             element = new ImageElement(this, QRect());
0254             break;
0255 
0256         default:
0257             throw FailedReadFile(QString(i18n("Invalid element type")));
0258             break;
0259         }
0260 
0261         if (element) {
0262             stream >> *element;
0263             m_elements.append(element);
0264 
0265             if (element->type() == Element::Pattern) {
0266                 if (dynamic_cast<PatternElement *>(element)->showPlan()) {
0267                     m_elements.append(dynamic_cast<PatternElement *>(element)->planElement());
0268                 }
0269             }
0270         }
0271     }
0272 }