File indexing completed on 2024-04-21 04:41:50

0001 /* This file is part of the KDE project
0002  * Copyright (C) 2001-2007 by OpenMFG, LLC (info@openmfg.com)
0003  * Copyright (C) 2007-2008 by Adam Pigg (adam@piggz.co.uk)
0004  *
0005  * This library is free software; you can redistribute it and/or
0006  * modify it under the terms of the GNU Lesser General Public
0007  * License as published by the Free Software Foundation; either
0008  * version 2.1 of the License, or (at your option) any later version.
0009  *
0010  * This library is distributed in the hope that it will be useful,
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0013  * Lesser General Public License for more details.
0014  *
0015  * You should have received a copy of the GNU Lesser General Public
0016  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
0017  */
0018 #include "KReportRenderObjects.h"
0019 #include "KReportUtils_p.h"
0020 
0021 #include "kreport_debug.h"
0022 
0023 // Helper functions
0024 static bool xLessThan(OROPrimitive* s1, OROPrimitive* s2)
0025 {
0026     return s1->position().x() < s2->position().x();
0027 }
0028 
0029 //
0030 // ORODocument
0031 //
0032 
0033 class Q_DECL_HIDDEN ORODocument::Private
0034 {
0035 public:
0036     Private();
0037     ~Private();
0038     QString title;
0039     QList<OROPage*> pages;
0040     QList<OROSection*> sections;
0041     KReportPrivate::PageLayout pageLayout;
0042 };
0043 
0044 ORODocument::Private::Private()
0045 {
0046 
0047 }
0048 
0049 ORODocument::Private::~Private()
0050 {
0051     qDeleteAll(pages);
0052     qDeleteAll(sections);
0053 }
0054 
0055 
0056 ORODocument::ORODocument(const QString& title) : d(new Private())
0057 {
0058     d->title = title;
0059 }
0060 
0061 ORODocument::~ORODocument()
0062 {
0063     delete d;
0064 }
0065 
0066 void ORODocument::setTitle(const QString &title)
0067 {
0068     d->title = title;
0069 }
0070 
0071 OROPage* ORODocument::page(int index)
0072 {
0073     return d->pages.value(index);
0074 }
0075 
0076 const OROPage * ORODocument::page(int index) const
0077 {
0078     return d->pages.value(index);
0079 }
0080 
0081 void ORODocument::addPage(OROPage* p)
0082 {
0083     if (p == nullptr) {
0084         return;
0085     }
0086 
0087     if (p->document() != nullptr && p->document() != this) {
0088         return;
0089     }
0090 
0091     p->setDocument(this);
0092     d->pages.append(p);
0093 }
0094 
0095 OROSection* ORODocument::section(int pnum)
0096 {
0097     return d->sections.value(pnum);
0098 }
0099 
0100 const OROSection * ORODocument::section(int index) const
0101 {
0102     return d->sections.value(index);
0103 }
0104 
0105 
0106 void ORODocument::addSection(OROSection* s)
0107 {
0108     if (s == nullptr)
0109         return;
0110 
0111     if (s->document() != nullptr && s->document() != this) {
0112         return;
0113     }
0114     s->setDocument(this);
0115     d->sections.append(s);
0116 }
0117 
0118 void ORODocument::setPageLayout(const QPageLayout & options)
0119 {
0120     d->pageLayout = options;
0121 }
0122 
0123 void ORODocument::notifyChange(int pageNo)
0124 {
0125     emit(updated(pageNo));
0126 }
0127 
0128 QPageLayout ORODocument::pageLayout() const
0129 {
0130     return d->pageLayout;
0131 }
0132 
0133 int ORODocument::pageCount() const
0134 {
0135     return d->pages.count();
0136 }
0137 
0138 int ORODocument::sectionCount() const
0139 {
0140     return d->sections.count();
0141 }
0142 
0143 QString ORODocument::title() const
0144 {
0145     return d->title;
0146 }
0147 
0148 void ORODocument::removePage(OROPage* page)
0149 {
0150     d->pages.removeOne(page);
0151     delete page;
0152 }
0153 
0154 void ORODocument::takePage(OROPage* page)
0155 {
0156     d->pages.removeOne(page);
0157 }
0158 
0159 void ORODocument::removeSection(OROSection* section)
0160 {
0161     d->sections.removeOne(section);
0162     delete section;
0163 }
0164 
0165 void ORODocument::takeSection(OROSection* section)
0166 {
0167     d->sections.removeOne(section);
0168 }
0169 
0170 int ORODocument::pageIndex(const OROPage* page) const
0171 {
0172     return d->pages.indexOf(const_cast<OROPage*>(page));
0173 }
0174 
0175 //
0176 // OROPage
0177 //
0178 class Q_DECL_HIDDEN OROPage::Private
0179 {
0180 public:
0181     Private();
0182     ~Private();
0183     ORODocument *document;
0184     QList<OROPrimitive*> primitives;
0185 };
0186 
0187 OROPage::Private::Private()
0188 {
0189 }
0190 
0191 OROPage::Private::~Private()
0192 {
0193     qDeleteAll(primitives);
0194 }
0195 
0196 OROPage::OROPage(ORODocument * pDocument)
0197         : d(new Private())
0198 {
0199     d->document = pDocument;
0200 }
0201 
0202 OROPage::~OROPage()
0203 {
0204     if (d->document) {
0205         d->document->takePage(this);
0206     }
0207     delete d;
0208 }
0209 
0210 int OROPage::pageNumber() const
0211 {
0212     if (d->document) {
0213         return d->document->pageIndex(this);
0214     }
0215     return -1;
0216 }
0217 
0218 OROPrimitive* OROPage::primitive(int index)
0219 {
0220     return d->primitives.value(index);
0221 }
0222 
0223 const OROPrimitive * OROPage::primitive(int index) const
0224 {
0225     return d->primitives.value(index);
0226 }
0227 
0228 
0229 void OROPage::insertPrimitive(OROPrimitive* p, int index)
0230 {
0231     //kreportDebug() << "Adding primitive" << p->type() << "to page" << page();
0232     if (p == nullptr)
0233         return;
0234 
0235     p->setPage(this);
0236     if (index == -1) {
0237         d->primitives.append(p);
0238     } else {
0239         d->primitives.insert(index, p);
0240     }
0241 
0242 #if 0
0243 //TODO
0244     if (notify) {
0245         if (d->document) {
0246             d->document->notifyChange(pageNumber());
0247         }
0248     }
0249 #endif
0250 }
0251 
0252 ORODocument * OROPage::document()
0253 {
0254     return d->document;
0255 }
0256 
0257 const ORODocument * OROPage::document() const
0258 {
0259     return d->document;
0260 }
0261 
0262 int OROPage::primitiveCount() const
0263 {
0264     return d->primitives.count();
0265 }
0266 
0267 void OROPage::setDocument(ORODocument* doc)
0268 {
0269     d->document = doc;
0270 }
0271 
0272 void OROPage::removePrimitive(OROPrimitive* primitive)
0273 {
0274     d->primitives.removeOne(primitive);
0275     delete primitive;
0276 }
0277 
0278 void OROPage::takePrimitive(OROPrimitive* primitive)
0279 {
0280     d->primitives.removeOne(primitive);
0281 }
0282 
0283 //
0284 // OROSection
0285 //
0286 
0287 class Q_DECL_HIDDEN OROSection::Private
0288 {
0289 public:
0290     Private();
0291     ~Private();
0292     ORODocument * document;
0293     QList<OROPrimitive*> primitives;
0294     qint64 row = 0;
0295     int height = 0;
0296     KReportSectionData::Type type = KReportSectionData::Type::None;
0297     QColor backgroundColor = Qt::white;
0298 };
0299 
0300 OROSection::Private::Private()
0301 {
0302 
0303 }
0304 
0305 OROSection::Private::~Private()
0306 {
0307     qDeleteAll(primitives);
0308     primitives.clear();
0309 }
0310 
0311 OROSection::OROSection(ORODocument* doc) : d(new Private())
0312 {
0313     d->document = doc;
0314 }
0315 
0316 OROSection::~OROSection()
0317 {
0318     if (d->document) {
0319         d->document->takeSection(this);
0320     }
0321 
0322     delete d;
0323 }
0324 
0325 OROPrimitive* OROSection::primitive(int index)
0326 {
0327     return d->primitives.value(index);
0328 }
0329 
0330 const OROPrimitive * OROSection::primitive(int index) const
0331 {
0332     return d->primitives.value(index);
0333 }
0334 
0335 void OROSection::addPrimitive(OROPrimitive* primitive)
0336 {
0337     if (primitive == nullptr)
0338         return;
0339 
0340     d->primitives.append(primitive);
0341 }
0342 
0343 void OROSection::setHeight(int h)
0344 {
0345     d->height = h;
0346 }
0347 
0348 int OROSection::height() const
0349 {
0350     return d->height;
0351 }
0352 
0353 void OROSection::setBackgroundColor(const QColor& color)
0354 {
0355     d->backgroundColor = color;
0356 }
0357 
0358 QColor OROSection::backgroundColor() const
0359 {
0360     return d->backgroundColor;
0361 }
0362 
0363 void OROSection::sortPrimitives(Qt::Orientation orientation)
0364 {
0365     if (orientation == Qt::Horizontal) {
0366         std::sort(d->primitives.begin(), d->primitives.end(), xLessThan);
0367     }
0368 }
0369 
0370 ORODocument * OROSection::document()
0371 {
0372     return d->document;
0373 }
0374 
0375 const ORODocument * OROSection::document() const
0376 {
0377     return d->document;
0378 }
0379 
0380 
0381 int OROSection::primitiveCount() const
0382 {
0383     return d->primitives.count();
0384 }
0385 
0386 void OROSection::setType(KReportSectionData::Type type)
0387 {
0388     d->type = type;
0389 }
0390 
0391 KReportSectionData::Type OROSection::type() const
0392 {
0393     return d->type;
0394 }
0395 
0396 void OROSection::setDocument(ORODocument* doc)
0397 {
0398     d->document = doc;
0399 }
0400 
0401 //
0402 // OROPrimitive
0403 //
0404 
0405 class Q_DECL_HIDDEN OROPrimitive::Private
0406 {
0407 public:
0408     OROPage * page = nullptr;
0409     QPointF position;
0410     QSizeF size;
0411 };
0412 
0413 OROPrimitive::OROPrimitive()
0414         : d(new Private())
0415 {
0416 }
0417 
0418 OROPrimitive::~OROPrimitive()
0419 {
0420    if (d->page) {
0421         d->page->takePrimitive(this);
0422     }
0423 
0424     delete d;
0425 }
0426 
0427 void OROPrimitive::setPosition(const QPointF& pos)
0428 {
0429     d->position = pos;
0430 }
0431 
0432 void OROPrimitive::setSize(const QSizeF & s)
0433 {
0434     d->size = s;
0435 }
0436 
0437 OROPage * OROPrimitive::page()
0438 {
0439     return d->page;
0440 }
0441 
0442 const OROPage * OROPrimitive::page() const
0443 {
0444     return d->page;
0445 }
0446 
0447 QPointF OROPrimitive::position() const
0448 {
0449     return d->position;
0450 }
0451 
0452 QSizeF OROPrimitive::size() const
0453 {
0454     return d->size;
0455 }
0456 
0457 void OROPrimitive::setPage(OROPage* page)
0458 {
0459     d->page = page;
0460 }
0461 
0462 //
0463 // OROTextBox
0464 //
0465 
0466 class Q_DECL_HIDDEN OROTextBox::Private
0467 {
0468 public:
0469     Private();
0470     ~Private();
0471     QString text;
0472     KReportTextStyleData textStyle;
0473     KReportLineStyle lineStyle;
0474     Qt::Alignment alignment;
0475     int flags; // Qt::AlignmentFlag and Qt::TextFlag OR'd
0476     bool wordWrap;
0477     bool canGrow;
0478     bool requiresPostProcessing;
0479 
0480 };
0481 
0482 OROTextBox::Private::Private()
0483 {
0484     flags = 0;
0485     wordWrap = false;
0486     canGrow = false;
0487     requiresPostProcessing = false;
0488 
0489     lineStyle.setColor(Qt::black);
0490     lineStyle.setWeight(0);
0491     lineStyle.setPenStyle(Qt::NoPen);
0492 }
0493 
0494 OROTextBox::Private::~Private()
0495 {
0496 }
0497 
0498 OROTextBox::OROTextBox() : d(new Private())
0499 {
0500 
0501 }
0502 
0503 OROTextBox::~OROTextBox()
0504 {
0505     delete d;
0506 }
0507 
0508 void OROTextBox::setText(const QString & s)
0509 {
0510     d->text = s;
0511 }
0512 
0513 void OROTextBox::setTextStyle(const KReportTextStyleData & ts)
0514 {
0515     d->textStyle = ts;
0516 }
0517 
0518 void OROTextBox::setLineStyle(const KReportLineStyle & ls)
0519 {
0520     d->lineStyle = ls;
0521 }
0522 
0523 void OROTextBox::setFont(const QFont & f)
0524 {
0525     d->textStyle.font = f;
0526 }
0527 
0528 void OROTextBox::setFlags(int f)
0529 {
0530     d->flags = f;
0531 }
0532 
0533 bool OROTextBox::canGrow() const
0534 {
0535     return d->canGrow;
0536 }
0537 
0538 int OROTextBox::flags() const
0539 {
0540     return d->flags;
0541 }
0542 
0543 KReportLineStyle OROTextBox::lineStyle() const
0544 {
0545     return d->lineStyle;
0546 }
0547 
0548 bool OROTextBox::requiresPostProcessing() const
0549 {
0550     return d->requiresPostProcessing;
0551 }
0552 
0553 void OROTextBox::setCanGrow(bool grow)
0554 {
0555     d->canGrow = grow;
0556 }
0557 
0558 void OROTextBox::setRequiresPostProcessing(bool pp)
0559 {
0560     d->requiresPostProcessing = pp;
0561 }
0562 
0563 void OROTextBox::setWordWrap(bool ww)
0564 {
0565     d->wordWrap = ww;
0566 }
0567 
0568 QString OROTextBox::text() const
0569 {
0570     return d->text;
0571 }
0572 
0573 KReportTextStyleData OROTextBox::textStyle() const
0574 {
0575     return d->textStyle;
0576 }
0577 
0578 bool OROTextBox::wordWrap() const
0579 {
0580     return d->wordWrap;
0581 }
0582 
0583 OROPrimitive* OROTextBox::clone() const
0584 {
0585     OROTextBox *theClone = new OROTextBox();
0586     theClone->setSize(size());
0587     theClone->setPosition(position());
0588     theClone->setText(text());
0589     theClone->setTextStyle(textStyle());
0590     theClone->setLineStyle(lineStyle());
0591     theClone->setFlags(flags());
0592     theClone->setCanGrow(canGrow());
0593     theClone->setWordWrap(wordWrap());
0594     theClone->setRequiresPostProcessing(requiresPostProcessing());
0595     return theClone;
0596 }
0597 
0598 
0599 //
0600 // OROLine
0601 //
0602 
0603 class Q_DECL_HIDDEN OROLine::Private
0604 {
0605 public:
0606     QPointF endPoint;
0607     KReportLineStyle lineStyle;
0608 };
0609 
0610 OROLine::OROLine() : d(new Private())
0611 {
0612 
0613 }
0614 
0615 OROLine::~OROLine()
0616 {
0617     delete d;
0618 }
0619 
0620 void OROLine::setStartPoint(const QPointF & p)
0621 {
0622     setPosition(p);
0623 }
0624 
0625 void OROLine::setEndPoint(const QPointF & p)
0626 {
0627     d->endPoint = p;
0628 }
0629 
0630 void OROLine::setLineStyle(const KReportLineStyle& style)
0631 {
0632     d->lineStyle = style;
0633 }
0634 
0635 QPointF OROLine::endPoint() const
0636 {
0637     return d->endPoint;
0638 }
0639 
0640 KReportLineStyle OROLine::lineStyle() const
0641 {
0642     return d->lineStyle;
0643 }
0644 
0645 OROPrimitive* OROLine::clone() const
0646 {
0647     OROLine *theClone = new OROLine();
0648     theClone->setStartPoint(position());
0649     theClone->setEndPoint(endPoint());
0650     theClone->setLineStyle(lineStyle());
0651     return theClone;
0652 }
0653 
0654 //
0655 // OROImage
0656 //
0657 
0658 class Q_DECL_HIDDEN OROImage::Private
0659 {
0660 public:
0661     QImage image;
0662     bool scaled;
0663     Qt::TransformationMode transformFlags;
0664     Qt::AspectRatioMode aspectFlags;
0665 };
0666 
0667 OROImage::OROImage() : d(new Private())
0668 {
0669     d->scaled = false;
0670     d->transformFlags = Qt::FastTransformation;
0671     d->aspectFlags = Qt::IgnoreAspectRatio;
0672 }
0673 
0674 OROImage::~OROImage()
0675 {
0676     delete d;
0677 }
0678 
0679 void OROImage::setImage(const QImage & img)
0680 {
0681     d->image = img;
0682 }
0683 
0684 void OROImage::setScaled(bool b)
0685 {
0686     d->scaled = b;
0687 }
0688 
0689 void OROImage::setTransformationMode(Qt::TransformationMode transformation)
0690 {
0691     d->transformFlags = transformation;
0692 }
0693 
0694 void OROImage::setAspectRatioMode(Qt::AspectRatioMode aspectRatioMode)
0695 {
0696     d->aspectFlags = aspectRatioMode;
0697 }
0698 
0699 Qt::AspectRatioMode OROImage::aspectRatioMode() const
0700 {
0701     return d->aspectFlags;
0702 }
0703 
0704 QImage OROImage::image() const
0705 {
0706     return d->image;
0707 }
0708 
0709 bool OROImage::isScaled() const
0710 {
0711     return d->scaled;
0712 }
0713 
0714 Qt::TransformationMode OROImage::transformationMode() const
0715 {
0716     return d->transformFlags;
0717 }
0718 
0719 OROPrimitive* OROImage::clone() const
0720 {
0721     OROImage *theClone = new OROImage();
0722     theClone->setSize(size());
0723     theClone->setPosition(position());
0724     theClone->setImage(image());
0725     theClone->setScaled(isScaled());
0726     theClone->setTransformationMode(transformationMode());
0727     theClone->setAspectRatioMode(aspectRatioMode());
0728     return theClone;
0729 }
0730 
0731 //
0732 // OROPicture
0733 //
0734 
0735 class Q_DECL_HIDDEN OROPicture::Private
0736 {
0737 public:
0738     QPicture picture;
0739 };
0740 
0741 OROPicture::OROPicture() : d(new Private())
0742 {
0743 
0744 }
0745 
0746 OROPicture::~OROPicture()
0747 {
0748     delete d;
0749 }
0750 
0751 OROPrimitive* OROPicture::clone() const
0752 {
0753     OROPicture *theClone = new OROPicture();
0754     theClone->setSize(size());
0755     theClone->setPosition(position());
0756 //     theClone->setPicture(*(picture()ddddddds));
0757     return theClone;
0758 }
0759 
0760 QPicture* OROPicture::picture()
0761 {
0762     return &d->picture;
0763 }
0764 
0765 void OROPicture::setPicture(const QPicture& p)
0766 {
0767     d->picture = p;
0768 }
0769 
0770 //
0771 // ORORect
0772 //
0773 
0774 class Q_DECL_HIDDEN ORORect::Private
0775 {
0776 public:
0777     QPen pen;
0778     QBrush brush;
0779 };
0780 
0781 ORORect::ORORect() : d(new Private())
0782 {
0783 }
0784 
0785 ORORect::~ORORect()
0786 {
0787     delete d;
0788 }
0789 
0790 void ORORect::setRect(const QRectF & r)
0791 {
0792     setPosition(r.topLeft());
0793     setSize(r.size());
0794 }
0795 
0796 void ORORect::setPen(const QPen & p)
0797 {
0798     d->pen = p;
0799 }
0800 
0801 void ORORect::setBrush(const QBrush & b)
0802 {
0803     d->brush = b;
0804 }
0805 
0806 QBrush ORORect::brush() const
0807 {
0808     return d->brush;
0809 }
0810 
0811 QPen ORORect::pen() const
0812 {
0813     return d->pen;
0814 }
0815 
0816 QRectF ORORect::rect() const
0817 {
0818     return QRectF(position(), size());
0819 }
0820 
0821 OROPrimitive* ORORect::clone() const
0822 {
0823     ORORect *theClone = new ORORect();
0824     theClone->setSize(size());
0825     theClone->setPosition(position());
0826     theClone->setPen(pen());
0827     theClone->setBrush(brush());
0828     return theClone;
0829 }
0830 //
0831 // OROEllipse
0832 //
0833 
0834 class Q_DECL_HIDDEN OROEllipse::Private
0835 {
0836 public:
0837     QPen pen;
0838     QBrush brush;
0839 };
0840 
0841 OROEllipse::OROEllipse() : d(new Private())
0842 {
0843 }
0844 
0845 OROEllipse::~OROEllipse()
0846 {
0847     delete d;
0848 }
0849 
0850 void OROEllipse::setRect(const QRectF & r)
0851 {
0852     setPosition(r.topLeft());
0853     setSize(r.size());
0854 }
0855 
0856 void OROEllipse::setPen(const QPen & p)
0857 {
0858     d->pen = p;
0859 }
0860 
0861 void OROEllipse::setBrush(const QBrush & b)
0862 {
0863     d->brush = b;
0864 }
0865 
0866 QBrush OROEllipse::brush() const
0867 {
0868     return d->brush;
0869 }
0870 
0871 QPen OROEllipse::pen() const
0872 {
0873     return d->pen;
0874 }
0875 
0876 QRectF OROEllipse::rect() const
0877 {
0878     return QRectF(position(), size());
0879 }
0880 
0881 OROPrimitive* OROEllipse::clone() const
0882 {
0883     OROEllipse *theClone = new OROEllipse();
0884     theClone->setSize(size());
0885     theClone->setPosition(position());
0886     theClone->setPen(pen());
0887     theClone->setBrush(brush());
0888     return theClone;
0889 }
0890 
0891 //
0892 // OROCheck
0893 //
0894 
0895 class Q_DECL_HIDDEN OROCheckBox::Private
0896 {
0897 public:
0898     OROCheckBox::Type checkType;
0899     bool value;
0900     KReportLineStyle lineStyle;
0901     QColor foregroundColor;
0902 };
0903 
0904 OROCheckBox::OROCheckBox() : d(new Private())
0905 {
0906     d->value = false;
0907 }
0908 
0909 OROCheckBox::~OROCheckBox()
0910 {
0911     delete d;
0912 }
0913 
0914 OROCheckBox::Type OROCheckBox::checkType() const
0915 {
0916     return d->checkType;
0917 }
0918 
0919 QColor OROCheckBox::foregroundColor() const
0920 {
0921     return d->foregroundColor;
0922 }
0923 
0924 KReportLineStyle OROCheckBox::lineStyle() const
0925 {
0926     return d->lineStyle;
0927 }
0928 
0929 void OROCheckBox::setForegroundColor(const QColor& fg)
0930 {
0931     d->foregroundColor = fg;
0932 }
0933 
0934 void OROCheckBox::setLineStyle(const KReportLineStyle& ls)
0935 {
0936     d->lineStyle = ls;
0937 }
0938 
0939 void OROCheckBox::setValue(bool v)
0940 {
0941     d->value = v;
0942 }
0943 
0944 bool OROCheckBox::value() const
0945 {
0946     return d->value;
0947 }
0948 
0949 void OROCheckBox::setCheckType(Type type)
0950 {
0951     if (type == Type::Cross || type == Type::Tick || type == Type::Dot) {
0952         d->checkType = type;
0953     } else {
0954         d->checkType = Type::Cross;
0955     }
0956 }
0957 
0958 OROPrimitive* OROCheckBox::clone() const
0959 {
0960     OROCheckBox *theClone = new OROCheckBox();
0961     theClone->setSize(size());
0962     theClone->setPosition(position());
0963     theClone->setLineStyle(lineStyle());
0964     theClone->setForegroundColor(foregroundColor());
0965     theClone->setValue(value());
0966     theClone->setCheckType(checkType());
0967     return theClone;
0968 }