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

0001 /* This file is part of the KDE project
0002  * Copyright (C) 2007-2008 by Adam Pigg (adam@piggz.co.uk)
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) any later version.
0008  *
0009  * This library is distributed in the hope that it will be useful,
0010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0012  * Lesser General Public License for more details.
0013  *
0014  * You should have received a copy of the GNU Lesser General Public
0015  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
0016  */
0017 
0018 #include "KReportDocument.h"
0019 #include "KReportUnit.h"
0020 #include "KReportDetailSectionData.h"
0021 #include "KReportItemBase.h"
0022 #include "KReportUtils_p.h"
0023 #include "KReportPageSize.h"
0024 
0025 #include <QDomElement>
0026 #include <QApplication>
0027 #include "kreport_debug.h"
0028 
0029 class Q_DECL_HIDDEN KReportDocument::Private
0030 {
0031 public:
0032     bool valid;
0033     QString title;
0034     QString name;
0035     QString query;
0036 #ifdef KREPORT_SCRIPTING
0037     QString script;
0038     QString interpreter;
0039 #endif
0040     bool externalData;
0041     KReportPrivate::PageLayout pageLayout;
0042     QString pageSize;
0043     QString labelType;
0044     
0045     KReportSectionData * pageHeaderFirst = nullptr;
0046     KReportSectionData * pageHeaderOdd = nullptr;
0047     KReportSectionData * pageHeaderEven = nullptr;
0048     KReportSectionData * pageHeaderLast = nullptr;
0049     KReportSectionData * pageHeaderAny = nullptr;
0050 
0051     KReportSectionData * reportHeader = nullptr;
0052     KReportSectionData * reportFooter = nullptr;
0053 
0054     KReportSectionData * pageFooterFirst = nullptr;
0055     KReportSectionData * pageFooterOdd = nullptr;
0056     KReportSectionData * pageFooterEven = nullptr;
0057     KReportSectionData * pageFooterLast = nullptr;
0058     KReportSectionData * pageFooterAny = nullptr;
0059 
0060     KReportDetailSectionData* detailSection = nullptr;
0061 };
0062 
0063 KReportDocument::KReportDocument(QObject *parent)
0064         : QObject(parent),
0065         d(new Private)
0066 {
0067     d->valid = true;
0068 }
0069 
0070 KReportDocument::KReportDocument(const QDomElement & elemSource, QObject *parent)
0071         : QObject(parent),
0072         d(new Private)
0073 {
0074     d->valid = false;
0075 
0076     if (elemSource.tagName() != QLatin1String("report:content")) {
0077         kreportWarning() << "QDomElement is not <report:content> tag"
0078                    << elemSource.text();
0079         return;
0080     }
0081     
0082     QDomNodeList sections = elemSource.childNodes();
0083     for (int nodeCounter = 0; nodeCounter < sections.count(); nodeCounter++) {
0084         QDomElement elemThis = sections.item(nodeCounter).toElement();
0085         if (elemThis.tagName() == QLatin1String("report:title")) {
0086             d->title = elemThis.text();
0087 #ifdef KREPORT_SCRIPTING
0088         } else if (elemThis.tagName() == QLatin1String("report:script")) {
0089             d->script = elemThis.text();
0090             d->interpreter = elemThis.attribute(QLatin1String("report:script-interpreter"));
0091 #endif
0092         } else if (elemThis.tagName() == QLatin1String("report:page-style")) {            
0093             QString pagetype = elemThis.firstChild().nodeValue();
0094 
0095             //Full page mode is required to allow margins to be set to whatever the user has specified
0096             d->pageLayout.setMode(QPageLayout::FullPageMode);
0097             
0098             if (pagetype == QLatin1String("predefined")) {
0099                 setPageSize(elemThis.attribute(QLatin1String("report:page-size"), QLatin1String("A4")));
0100                 d->pageLayout.setPageSize(QPageSize(KReportPageSize::pageSize(pageSize())));
0101             } else if (pagetype == QLatin1String("custom")) {
0102                 kreportDebug() << "Setting custom page size in document to " << KReportUnit::parseValue(elemThis.attribute(QLatin1String("report:custom-page-width"), QLatin1String("5.0cm"))) << KReportUnit::parseValue(elemThis.attribute(QLatin1String("report:custom-page-height"), QLatin1String("5.0cm"))) ;
0103                 QPageSize custom(QSize(KReportUnit::parseValue(elemThis.attribute(QLatin1String("report:custom-page-width"), QLatin1String("5.0cm")))  , KReportUnit::parseValue(elemThis.attribute(QLatin1String("report:custom-page-height"), QLatin1String("5.0cm"))) ), QString(), QPageSize::ExactMatch);
0104 
0105                 d->pageLayout.setPageSize(custom);
0106             } else if (pagetype == QLatin1String("label")) {
0107                 setLabelType(elemThis.firstChild().nodeValue());
0108             }
0109             //! @todo add config for default margins or add within templates support
0110             d->pageLayout.setUnits(QPageLayout::Point);
0111             d->pageLayout.setLeftMargin(KReportUnit::parseValue(elemThis.attribute(
0112                 QLatin1String("fo:margin-left"), DEFAULT_PAGE_MARGIN_STRING)));
0113             d->pageLayout.setRightMargin(KReportUnit::parseValue(elemThis.attribute(
0114                 QLatin1String("fo:margin-right"), DEFAULT_PAGE_MARGIN_STRING)));
0115             d->pageLayout.setTopMargin(KReportUnit::parseValue(elemThis.attribute(
0116                 QLatin1String("fo:margin-top"), DEFAULT_PAGE_MARGIN_STRING)));
0117             d->pageLayout.setBottomMargin(KReportUnit::parseValue(elemThis.attribute(
0118                 QLatin1String("fo:margin-bottom"), DEFAULT_PAGE_MARGIN_STRING)));
0119             d->pageLayout.setOrientation(
0120                 elemThis.attribute(QLatin1String("report:print-orientation"),
0121                                    QLatin1String("portrait"))
0122                         == QLatin1String("portrait")
0123                     ? QPageLayout::Portrait
0124                     : QPageLayout::Landscape);
0125         } else if (elemThis.tagName() == QLatin1String("report:body")) {
0126             QDomNodeList sectionlist = elemThis.childNodes();
0127             QDomNode sec;
0128 
0129             for (int s = 0; s < sectionlist.count(); ++s) {
0130                 sec = sectionlist.item(s);
0131                 if (sec.isElement()) {
0132                     QString sn = sec.nodeName().toLower();
0133                     //kreportDebug() << sn;
0134                     if (sn == QLatin1String("report:section")) {
0135                         KReportSectionData * sd = new KReportSectionData(sec.toElement(), this);
0136                         if (!sd->isValid()) {
0137                             kreportDebug() << "Invalid section";
0138                             delete sd;
0139                         } else {
0140                             //kreportDebug() << "Adding section of type " << sd->type();
0141                             switch (sd->type()) {
0142                             case KReportSectionData::Type::PageHeaderFirst:
0143                                 d->pageHeaderFirst = sd;
0144                                 break;
0145                             case KReportSectionData::Type::PageHeaderOdd:
0146                                 d->pageHeaderOdd = sd;
0147                                 break;
0148                             case KReportSectionData::Type::PageHeaderEven:
0149                                 d->pageHeaderEven = sd;
0150                                 break;
0151                             case KReportSectionData::Type::PageHeaderLast:
0152                                 d->pageHeaderLast = sd;
0153                                 break;
0154                             case KReportSectionData::Type::PageHeaderAny:
0155                                 d->pageHeaderAny = sd;
0156                                 break;
0157                             case KReportSectionData::Type::ReportHeader:
0158                                 d->reportHeader = sd;
0159                                 break;
0160                             case KReportSectionData::Type::ReportFooter:
0161                                 d->reportFooter = sd;
0162                                 break;
0163                             case KReportSectionData::Type::PageFooterFirst:
0164                                 d->pageFooterFirst = sd;
0165                                 break;
0166                             case KReportSectionData::Type::PageFooterOdd:
0167                                 d->pageFooterOdd = sd;
0168                                 break;
0169                             case KReportSectionData::Type::PageFooterEven:
0170                                 d->pageFooterEven = sd;
0171                                 break;
0172                             case KReportSectionData::Type::PageFooterLast:
0173                                 d->pageFooterLast = sd;
0174                                 break;
0175                             case KReportSectionData::Type::PageFooterAny:
0176                                 d->pageFooterAny = sd;
0177                                 break;
0178                             default:
0179                                 ;
0180                             }
0181                         }
0182 
0183                     } else if (sn == QLatin1String("report:detail")) {
0184                         KReportDetailSectionData * dsd = new KReportDetailSectionData(sec.toElement(), this);
0185 
0186                         if (dsd->isValid()) {
0187                             d->detailSection = dsd;
0188                         } else {
0189                             kreportDebug() << "Invalid detail section";
0190                             delete dsd;
0191                         }
0192                     }
0193                 } else {
0194                     kreportWarning() << "Encountered an unknown Element: "  << elemThis.tagName();
0195                 }
0196             }
0197         }
0198 
0199         d->valid = true;
0200     }
0201 }
0202 
0203 KReportDocument::~KReportDocument()
0204 {
0205     delete d;
0206 }
0207 
0208 QList<KReportItemBase*> KReportDocument::objects() const
0209 {
0210     QList<KReportItemBase*> obs;
0211     for (int i = static_cast<int>(KReportSectionData::Type::PageHeaderFirst);
0212          i <= static_cast<int>(KReportSectionData::Type::PageFooterAny); i++)
0213     {
0214         KReportSectionData *sec = section(static_cast<KReportSectionData::Type>(i));
0215         if (sec) {
0216             obs << sec->objects();
0217         }
0218     }
0219 
0220     if (d->detailSection) {
0221         //kreportDebug() << "Number of groups: " << m_detailSection->m_groupList.count();
0222         foreach(KReportDetailGroupSectionData* g, d->detailSection->groupList) {
0223             if (g->groupHeader) {
0224                 obs << g->groupHeader->objects();
0225             }
0226             if (g->groupFooter) {
0227                 obs << g->groupFooter->objects();
0228             }
0229         }
0230         if (d->detailSection->detailSection)
0231             obs << d->detailSection->detailSection->objects();
0232     }
0233 
0234     /*kreportDebug() << "Object List:";
0235     foreach(KReportItemBase* o, obs) {
0236         kreportDebug() << o->entityName();
0237     }*/
0238     return obs;
0239 }
0240 
0241 KReportItemBase* KReportDocument::object(const QString& n) const
0242 {
0243     QList<KReportItemBase*> obs = objects();
0244 
0245     foreach(KReportItemBase* o, obs) {
0246         if (o->entityName() == n) {
0247             return o;
0248         }
0249     }
0250     return nullptr;
0251 }
0252 
0253 QList<KReportSectionData*> KReportDocument::sections() const
0254 {
0255     QList<KReportSectionData*> secs;
0256     for (int i = static_cast<int>(KReportSectionData::Type::PageHeaderFirst);
0257          i <= static_cast<int>(KReportSectionData::Type::PageFooterAny); i++)
0258     {
0259         KReportSectionData *sec = section(static_cast<KReportSectionData::Type>(i));
0260         if (sec) {
0261             secs << sec;
0262         }
0263     }
0264 
0265     if (d->detailSection) {
0266         //kreportDebug() << "Number of groups: " << m_detailSection->m_groupList.count();
0267         foreach(KReportDetailGroupSectionData* g, d->detailSection->groupList) {
0268             if (g->groupHeader) {
0269                 secs << g->groupHeader;
0270             }
0271             if (g->groupFooter) {
0272                 secs << g->groupFooter;
0273             }
0274         }
0275         if (d->detailSection->detailSection)
0276             secs << d->detailSection->detailSection;
0277     }
0278 
0279     return secs;
0280 }
0281 
0282 KReportSectionData* KReportDocument::section(const QString& sn) const
0283 {
0284     QList<KReportSectionData*> secs = sections();
0285 
0286     foreach(KReportSectionData *sec, secs) {
0287         if (sec->name() == sn) {
0288             return sec;
0289         }
0290     }
0291     return nullptr;
0292 }
0293 
0294 KReportSectionData* KReportDocument::section(KReportSectionData::Type type) const
0295 {
0296     KReportSectionData *sec;
0297     switch (type) {
0298     case KReportSectionData::Type::PageHeaderAny:
0299         sec = d->pageHeaderAny;
0300         break;
0301     case KReportSectionData::Type::PageHeaderEven:
0302         sec = d->pageHeaderEven;
0303         break;
0304     case KReportSectionData::Type::PageHeaderOdd:
0305         sec = d->pageHeaderOdd;
0306         break;
0307     case KReportSectionData::Type::PageHeaderFirst:
0308         sec = d->pageHeaderFirst;
0309         break;
0310     case KReportSectionData::Type::PageHeaderLast:
0311         sec = d->pageHeaderLast;
0312         break;
0313     case KReportSectionData::Type::PageFooterAny:
0314         sec = d->pageFooterAny;
0315         break;
0316     case KReportSectionData::Type::PageFooterEven:
0317         sec = d->pageFooterEven;
0318         break;
0319     case KReportSectionData::Type::PageFooterOdd:
0320         sec = d->pageFooterOdd;
0321         break;
0322     case KReportSectionData::Type::PageFooterFirst:
0323         sec = d->pageFooterFirst;
0324         break;
0325     case KReportSectionData::Type::PageFooterLast:
0326         sec = d->pageFooterLast;
0327         break;
0328     case KReportSectionData::Type::ReportHeader:
0329         sec = d->reportHeader;
0330         break;
0331     case KReportSectionData::Type::ReportFooter:
0332         sec = d->reportFooter;
0333         break;
0334     default:
0335         sec = nullptr;
0336     }
0337     return sec;
0338 }
0339 
0340 QPageLayout KReportDocument::pageLayout() const
0341 {
0342     return d->pageLayout;
0343 }
0344 
0345 bool KReportDocument::isValid() const
0346 {
0347     return d->valid;
0348 }
0349 
0350 QString KReportDocument::title() const
0351 {
0352     return d->title;
0353 }
0354 
0355 bool KReportDocument::externalData() const
0356 {
0357     return d->externalData;
0358 }
0359 
0360 #ifdef KREPORT_SCRIPTING
0361 QString KReportDocument::script() const
0362 {
0363     return d->script;
0364 }
0365 
0366 QString KReportDocument::interpreter() const
0367 {
0368     return d->interpreter;
0369 }
0370 #endif
0371 
0372 QString KReportDocument::name() const
0373 {
0374     return d->name;
0375 }
0376 
0377 void KReportDocument::setName(const QString& n)
0378 {
0379     d->name = n;
0380 }
0381 
0382 QString KReportDocument::query() const
0383 {
0384     return d->query;
0385 }
0386 
0387 QString KReportDocument::pageSize()
0388 {
0389     return d->pageSize;
0390 }
0391 
0392 void KReportDocument::setPageSize(const QString& size)
0393 {
0394     d->pageSize = size;
0395 }
0396 
0397 QString KReportDocument::labelType() const
0398 {
0399     return d->labelType;
0400 }
0401 
0402 void KReportDocument::setLabelType(const QString& label)
0403 {
0404     d->labelType = label;
0405 }
0406 
0407 KReportDetailSectionData * KReportDocument::detail() const
0408 {
0409     return d->detailSection;
0410 }
0411