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 }