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

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  * Copyright (C) 2010-2018 Jarosław Staniek <staniek@kde.org>
0005  *
0006  * This library is free software; you can redistribute it and/or
0007  * modify it under the terms of the GNU Lesser General Public
0008  * License as published by the Free Software Foundation; either
0009  * version 2.1 of the License, or (at your option) any later version.
0010  *
0011  * This library is distributed in the hope that it will be useful,
0012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0014  * Lesser General Public License for more details.
0015  *
0016  * You should have received a copy of the GNU Lesser General Public
0017  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
0018  */
0019 
0020 #include "KReportSectionData.h"
0021 #include "KReportDesigner.h"
0022 #include "KReportDocument.h"
0023 #include "KReportItemLine.h"
0024 #include "KReportPluginInterface.h"
0025 #include "KReportPluginManager.h"
0026 #include "KReportItemLine.h"
0027 #include "KReportDesigner.h"
0028 #include "KReportUtils.h"
0029 #include "KReportUtils_p.h"
0030 #include "kreport_debug.h"
0031 
0032 #include <KPropertySet>
0033 
0034 #include <QDomElement>
0035 
0036 class Q_DECL_HIDDEN KReportSectionData::Private
0037 {
0038 public:
0039     explicit Private(KReportSectionData *data, const QDomElement &elemSource) : q(data)
0040     {
0041         if (!elemSource.isNull()) {
0042             q->setObjectName(elemSource.tagName());
0043             type = sectionTypeFromString(KReportUtils::readSectionTypeNameAttribute(elemSource));
0044         }
0045         createProperties(elemSource);
0046         if (!elemSource.isNull()) {
0047             loadXml(elemSource);
0048         }
0049         set.clearModifiedFlags();
0050     }
0051 
0052     ~Private()
0053     {
0054         qDeleteAll(objects);
0055     }
0056 
0057     void setHeight(qreal ptHeight, KProperty::ValueOptions options);
0058 
0059     static bool zLessThan(KReportItemBase* s1, KReportItemBase* s2);
0060     static bool xLessThan(KReportItemBase* s1, KReportItemBase* s2);
0061 
0062     KReportSectionData * const q;
0063     KPropertySet set;
0064     KProperty *backgroundColor;
0065     KProperty *height;
0066     QList<KReportItemBase *> objects;
0067     KReportUnit unit = KReportUnit(DEFAULT_UNIT_TYPE);
0068     Type type = Type::None;
0069     bool valid = true;
0070 
0071 private:
0072     void createProperties(const QDomElement &elemSource);
0073     void loadXml(const QDomElement &elemSource);
0074 };
0075 
0076 KReportSectionData::KReportSectionData(QObject *parent)
0077     : KReportSectionData(QDomElement(), parent)
0078 {
0079 }
0080 
0081 KReportSectionData::KReportSectionData(const QDomElement & elemSource, QObject *parent)
0082  : QObject(parent), d(new Private(this, elemSource))
0083 {
0084 }
0085 
0086 void KReportSectionData::Private::loadXml(const QDomElement &elemSource)
0087 {
0088     if (q->objectName() != QLatin1String("report:section") || type == KReportSectionData::Type::None) {
0089         valid = false;
0090         return;
0091     }
0092 
0093     KReportPluginManager* manager = KReportPluginManager::self();
0094 
0095     QDomNodeList section = elemSource.childNodes();
0096     for (int nodeCounter = 0; nodeCounter < section.count(); nodeCounter++) {
0097         QDomElement elemThis = section.item(nodeCounter).toElement();
0098         QString n = elemThis.tagName();
0099         if (n.startsWith(QLatin1String("report:"))) {
0100             KReportItemBase *krobj = nullptr;
0101             QString reportItemName = n.mid(qstrlen("report:"));
0102             if (reportItemName == QLatin1String("line")) {
0103                 KReportItemLine * line = new KReportItemLine(elemThis);
0104                 krobj = line;
0105             } else {
0106                 KReportPluginInterface *plugin = manager->plugin(reportItemName);
0107                 if (plugin) {
0108                     QObject *obj = plugin->createRendererInstance(elemThis);
0109                     if (obj) {
0110                         krobj = dynamic_cast<KReportItemBase*>(obj);
0111                     }
0112                 }
0113             }
0114             if (krobj) {
0115                 krobj->propertySet()->clearModifiedFlags();
0116                 objects.append(krobj);
0117             } else {
0118                 kreportWarning() << "Could not create element of type" << reportItemName;
0119             }
0120         } else {
0121             kreportWarning() << "While parsing section encountered an unknown element:" << n;
0122         }
0123     }
0124     std::sort(objects.begin(), objects.end(), zLessThan);
0125     valid = true;
0126 }
0127 
0128 KReportSectionData::~KReportSectionData()
0129 {
0130     delete d;
0131 }
0132 
0133 KReportUnit KReportSectionData::unit() const
0134 {
0135     return d->unit;
0136 }
0137 
0138 void KReportSectionData::setUnit(const KReportUnit &u)
0139 {
0140     if (d->unit == u) {
0141         return;
0142     }
0143     // convert values
0144     KReportUnit oldunit = d->unit;
0145     d->unit = u;
0146 
0147     d->height->setValue(KReportUnit::convertFromUnitToUnit(d->height->value().toReal(), oldunit, u),
0148                        KProperty::ValueOption::IgnoreOld);
0149     d->height->setOption("suffix", u.symbol());
0150 }
0151 
0152 bool KReportSectionData::Private::zLessThan(KReportItemBase* s1, KReportItemBase* s2)
0153 {
0154     return s1->z() < s2->z();
0155 }
0156 
0157 bool KReportSectionData::Private::xLessThan(KReportItemBase* s1, KReportItemBase* s2)
0158 {
0159     return s1->position().toPoint().x() < s2->position().toPoint().x();
0160 }
0161 
0162 void KReportSectionData::Private::createProperties(const QDomElement & elemSource)
0163 {
0164     KReportDesigner::addMetaProperties(&set, KReportSectionData::tr("Section", "Report section"),
0165                                        QLatin1String("kreport-section-element"));
0166     height = new KProperty("height", 0.0, tr("Height"));
0167     backgroundColor = new KProperty(
0168         "background-color",
0169         KReportUtils::attr(elemSource, QLatin1String("fo:background-color"), QColor(Qt::white)),
0170         tr("Background Color"));
0171     height->setOption("unit", QLatin1String("cm"));
0172     if (!elemSource.isNull()) {
0173         height->setValue(unit.convertFromPoint(
0174             KReportUtils::readSizeAttributes(
0175                 elemSource, QSizeF(DEFAULT_SECTION_SIZE_PT, DEFAULT_SECTION_SIZE_PT))
0176                 .height()));
0177     }
0178 
0179     set.addProperty(height);
0180     set.addProperty(backgroundColor);
0181     set.clearModifiedFlags();
0182 }
0183 
0184 QString KReportSectionData::name() const
0185 {
0186     return (objectName() + QLatin1Char('-') + sectionTypeString(d->type));
0187 }
0188 
0189 QString KReportSectionData::sectionTypeString(KReportSectionData::Type type)
0190 {
0191 //! @todo use QMap
0192     QString sectiontype;
0193     switch (type) {
0194     case KReportSectionData::Type::PageHeaderAny:
0195         sectiontype = QLatin1String("header-page-any");
0196         break;
0197     case KReportSectionData::Type::PageHeaderEven:
0198         sectiontype = QLatin1String("header-page-even");
0199         break;
0200     case KReportSectionData::Type::PageHeaderOdd:
0201         sectiontype = QLatin1String("header-page-odd");
0202         break;
0203     case KReportSectionData::Type::PageHeaderFirst:
0204         sectiontype = QLatin1String("header-page-first");
0205         break;
0206     case KReportSectionData::Type::PageHeaderLast:
0207         sectiontype = QLatin1String("header-page-last");
0208         break;
0209     case KReportSectionData::Type::PageFooterAny:
0210         sectiontype = QLatin1String("footer-page-any");
0211         break;
0212     case KReportSectionData::Type::PageFooterEven:
0213         sectiontype = QLatin1String("footer-page-even");
0214         break;
0215     case KReportSectionData::Type::PageFooterOdd:
0216         sectiontype = QLatin1String("footer-page-odd");
0217         break;
0218     case KReportSectionData::Type::PageFooterFirst:
0219         sectiontype = QLatin1String("footer-page-first");
0220         break;
0221     case KReportSectionData::Type::PageFooterLast:
0222         sectiontype = QLatin1String("footer-page-last");
0223         break;
0224     case KReportSectionData::Type::ReportHeader:
0225         sectiontype = QLatin1String("header-report");
0226         break;
0227     case KReportSectionData::Type::ReportFooter:
0228         sectiontype = QLatin1String("footer-report");
0229         break;
0230     case KReportSectionData::Type::GroupHeader:
0231         sectiontype = QLatin1String("group-header");
0232         break;
0233     case KReportSectionData::Type::GroupFooter:
0234         sectiontype = QLatin1String("group-footer");
0235         break;
0236     case KReportSectionData::Type::Detail:
0237         sectiontype = QLatin1String("detail");
0238         break;
0239     default:
0240         break;
0241     }
0242 
0243     return sectiontype;
0244 }
0245 
0246 KReportSectionData::Type KReportSectionData::sectionTypeFromString(const QString& s)
0247 {
0248 //! @todo use QMap
0249     KReportSectionData::Type type;
0250     //kreportDebug() << "Determining section type for " << s;
0251     if (s == QLatin1String("header-page-any"))
0252         type = KReportSectionData::Type::PageHeaderAny;
0253     else if (s == QLatin1String("header-page-even"))
0254         type = KReportSectionData::Type::PageHeaderEven;
0255     else if (s == QLatin1String("header-page-odd"))
0256         type = KReportSectionData::Type::PageHeaderOdd;
0257     else if (s == QLatin1String("header-page-first"))
0258         type = KReportSectionData::Type::PageHeaderFirst;
0259     else if (s == QLatin1String("header-page-last"))
0260         type = KReportSectionData::Type::PageHeaderLast;
0261     else if (s == QLatin1String("header-report"))
0262         type = KReportSectionData::Type::ReportHeader;
0263     else if (s == QLatin1String("footer-page-any"))
0264         type = KReportSectionData::Type::PageFooterAny;
0265     else if (s == QLatin1String("footer-page-even"))
0266         type = KReportSectionData::Type::PageFooterEven;
0267     else if (s == QLatin1String("footer-page-odd"))
0268         type = KReportSectionData::Type::PageFooterOdd;
0269     else if (s == QLatin1String("footer-page-first"))
0270         type = KReportSectionData::Type::PageFooterFirst;
0271     else if (s == QLatin1String("footer-page-last"))
0272         type = KReportSectionData::Type::PageFooterLast;
0273     else if (s == QLatin1String("footer-report"))
0274         type = KReportSectionData::Type::ReportFooter;
0275     else if (s == QLatin1String("group-header"))
0276         type = KReportSectionData::Type::GroupHeader;
0277     else if (s == QLatin1String("group-footer"))
0278         type = KReportSectionData::Type::GroupFooter;
0279     else if (s == QLatin1String("detail"))
0280         type = KReportSectionData::Type::Detail;
0281     else
0282         type = KReportSectionData::Type::None;
0283 
0284     return type;
0285 }
0286 
0287 qreal KReportSectionData::height() const
0288 {
0289     return d->unit.convertToPoint(d->height->value().toReal());
0290 }
0291 
0292 void KReportSectionData::setHeight(qreal ptHeight, KProperty::ValueOptions options)
0293 {
0294     d->height->setValue(d->unit.convertFromPoint(ptHeight), options);
0295 }
0296 
0297 void KReportSectionData::setHeight(qreal ptHeight)
0298 {
0299     setHeight(ptHeight, KProperty::ValueOptions());
0300 }
0301 
0302 KPropertySet* KReportSectionData::propertySet()
0303 {
0304     return &d->set;
0305 }
0306 
0307 const KPropertySet* KReportSectionData::propertySet() const
0308 {
0309     return &d->set;
0310 }
0311 
0312 bool KReportSectionData::isValid() const
0313 {
0314     return d->valid;
0315 }
0316 
0317 QList<KReportItemBase*> KReportSectionData::objects() const
0318 {
0319     return d->objects;
0320 }
0321 
0322 QColor KReportSectionData::backgroundColor() const
0323 {
0324     return d->backgroundColor->value().value<QColor>();
0325 }
0326 
0327 void KReportSectionData::setBackgroundColor(const QColor &color)
0328 {
0329     d->backgroundColor->setValue(color);
0330 }
0331 
0332 KReportSectionData::Type KReportSectionData::type() const
0333 {
0334     return d->type;
0335 }
0336 
0337 KReportItemBase* KReportSectionData::object(int index)
0338 {
0339     return d->objects.value(index);
0340 }