File indexing completed on 2024-05-12 04:43:22

0001 /* This file is part of the KDE project
0002  * Copyright (C) 2007-2008 by Adam Pigg <adam@piggz.co.uk>
0003  * Copyright (C) 2012 Jarosław Staniek <staniek@kde.org>
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 
0019 #include "KReportScriptHandler.h"
0020 
0021 #include "KReportDataSource.h"
0022 #include "KReportScriptSource.h"
0023 #include "KReportScriptSection.h"
0024 #include "KReportScriptDebug.h"
0025 #include "KReportScriptReport.h"
0026 #include "KReportScriptDraw.h"
0027 #include "KReportScriptConstants.h"
0028 #include "KReportSectionData.h"
0029 #include "KReportItemBase.h"
0030 #include "KReportDocument.h"
0031 #include "KReportDetailSectionData.h"
0032 #include "KReportRenderObjects.h"
0033 #include "kreport_debug.h"
0034 
0035 #include <QMessageBox>
0036 #include <QJSEngine>
0037 #include <QJSValue>
0038 
0039 
0040 //Note#: this is here to save creating a new file for this interface
0041 KReportScriptSource::~KReportScriptSource()
0042 {
0043 }
0044 
0045 class Q_DECL_HIDDEN KReportScriptHandler::Private
0046 {
0047 public:
0048     Private();
0049     ~Private();
0050     KReportScriptConstants *constants;
0051     KReportScriptDebug *debug;
0052     KReportScriptDraw *draw;
0053     Scripting::Report *report;
0054     const KReportDataSource *reportDataSource;
0055     const KReportScriptSource *scriptSource;
0056     QString source;
0057     KReportDocument  *reportDocument;
0058     QJSEngine engine;
0059     QJSValue scriptValue;
0060     QMap<QString, QVariant> groups;
0061     QMap<KReportSectionData*, Scripting::Section*> sectionMap;
0062     bool suppressEvaluateErrors = false;
0063 };
0064 
0065 KReportScriptHandler::Private::Private() : constants(new KReportScriptConstants), debug(new KReportScriptDebug), draw(new KReportScriptDraw)
0066 {
0067 }
0068 
0069 KReportScriptHandler::Private::~Private()
0070 {
0071 }
0072 
0073 KReportScriptHandler::KReportScriptHandler(const KReportDataSource* reportDataSource, KReportScriptSource* scriptSource, KReportDocument* reportDocument) : d(new Private())
0074 {
0075     d->reportDocument = reportDocument;
0076     d->reportDataSource = reportDataSource;
0077     d->scriptSource = scriptSource;
0078 
0079     //Add a general report object
0080     d->report = new Scripting::Report(d->reportDocument);
0081 
0082     registerScriptObject(d->constants, QLatin1String("constants"));
0083     registerScriptObject(d->debug, QLatin1String("debug"));
0084     registerScriptObject(d->draw, QLatin1String("draw"));
0085 
0086     QJSValue r = registerScriptObject(d->report, d->reportDocument->name());
0087 
0088     //Add the sections
0089     QList<KReportSectionData*> secs = d->reportDocument->sections();
0090     foreach(KReportSectionData *sec, secs) {
0091         d->sectionMap[sec] = new Scripting::Section(sec);
0092         d->sectionMap[sec]->setParent(d->report);
0093         d->sectionMap[sec]->setObjectName(sec->name().replace(QLatin1Char('-'), QLatin1Char('_'))
0094                                          .remove(QLatin1String("report:")));
0095         QJSValue s = d->engine.newQObject(d->sectionMap[sec]);
0096         r.setProperty(d->sectionMap[sec]->objectName(), s);
0097         //kreportDebug() << "Added" << d->sectionMap[sec]->objectName() << "to report" << d->reportData->name();
0098     }
0099 }
0100 
0101 bool KReportScriptHandler::trigger()
0102 {
0103     QString code;
0104     if (d->scriptSource) {
0105         code = d->scriptSource->scriptCode(d->reportDocument->script());
0106     }
0107 
0108     if (code.isEmpty()) {
0109         return true;
0110     }
0111 
0112     d->scriptValue = d->engine.evaluate(code, d->reportDocument->script());
0113 
0114     if (d->scriptValue.isError()) {
0115         return false;
0116     }/*TODO else {
0117         kreportDebug() << "Function Names:" << d->engine->functionNames();
0118     }*/
0119     d->report->eventOnOpen();
0120     return true;
0121 }
0122 
0123 KReportScriptHandler::~KReportScriptHandler()
0124 {
0125     delete d;
0126 }
0127 
0128 void KReportScriptHandler::newPage()
0129 {
0130     if (d->report) {
0131         d->report->eventOnNewPage();
0132     }
0133 }
0134 
0135 void KReportScriptHandler::slotEnteredGroup(const QString &key, const QVariant &value)
0136 {
0137     //kreportDebug() << key << value;
0138     d->groups[key] = value;
0139     emit(groupChanged(d->groups));
0140 }
0141 void KReportScriptHandler::slotExitedGroup(const QString &key, const QVariant &value)
0142 {
0143     Q_UNUSED(value);
0144     //kreportDebug() << key << value;
0145     d->groups.remove(key);
0146     emit(groupChanged(d->groups));
0147 }
0148 
0149 void KReportScriptHandler::slotEnteredSection(KReportSectionData *section, OROPage* cp, QPointF off)
0150 {
0151     if (cp)
0152         d->draw->setPage(cp);
0153     d->draw->setOffset(off);
0154 
0155     Scripting::Section *ss = d->sectionMap[section];
0156     if (ss) {
0157         ss->eventOnRender();
0158     }
0159 }
0160 
0161 QVariant KReportScriptHandler::evaluate(const QString &code)
0162 {
0163     if (!d->scriptValue.isError()) {
0164         QJSValue result = d->engine.evaluate(code);
0165         if (!result.isError()) {
0166             return result.toVariant();
0167         } else {
0168             if (!d->suppressEvaluateErrors) {
0169                 QMessageBox msgBox;
0170                 msgBox.setText(tr("Cannot evaluate script. Error: %1\n\nDo you want to suppress further messages?\n(messages will be restored next time the report is opened)").arg(d->scriptValue.toString()));
0171                 msgBox.setDetailedText(tr("Script code:\n%1").arg(code));
0172                 msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
0173                 msgBox.setDefaultButton(QMessageBox::No);
0174                 int ret = msgBox.exec();
0175                 if (ret == QMessageBox::Yes) {
0176                     d->suppressEvaluateErrors = true;
0177                 }
0178             }
0179         }
0180     }
0181     return QVariant();
0182 }
0183 
0184 void KReportScriptHandler::displayErrors()
0185 {
0186     if (d->scriptValue.isError()) {
0187         QMessageBox::warning(nullptr, tr("Script Error"), d->scriptValue.toString());
0188     }
0189 }
0190 
0191 //! @todo KEXI3 move to kexi
0192 #if 0
0193 QString KReportScriptHandler::where()
0194 {
0195     QString w;
0196     QMap<QString, QVariant>::const_iterator i = d->groups.constBegin();
0197     while (i != d->groups.constEnd()) {
0198         w += QLatin1Char('(') + i.key() + QLatin1String(" = '") + i.value().toString() + QLatin1String("') AND ");
0199         ++i;
0200     }
0201     w.chop(4);
0202     //kreportDebug() << w;
0203     return w;
0204 }
0205 #endif
0206 
0207 QJSValue KReportScriptHandler::registerScriptObject(QObject* obj, const QString& name)
0208 {
0209     QJSValue val;
0210     val = d->engine.newQObject(obj);
0211     d->engine.globalObject().setProperty(name, val);
0212     return val;
0213 }
0214 
0215 void KReportScriptHandler::setPageNumber(int p)
0216 {
0217     d->constants->setPageNumber(p);
0218 }
0219 
0220 void KReportScriptHandler::setPageTotal(int t)
0221 {
0222     d->constants->setPageTotal(t);
0223 }