diff --git a/kexi/plugins/reports/kexidbreportdata.cpp b/kexi/plugins/reports/kexidbreportdata.cpp index 578a3bf8e72..f93585c0340 100644 --- a/kexi/plugins/reports/kexidbreportdata.cpp +++ b/kexi/plugins/reports/kexidbreportdata.cpp @@ -1,406 +1,412 @@ /* * Kexi Report Plugin * Copyright (C) 2007-2009 by Adam Pigg (adam@piggz.co.uk) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include "kexidbreportdata.h" #include #include #include #include #include class KexiDBReportData::Private { public: explicit Private(KDbConnection *pDb) : cursor(0), connection(pDb), originalSchema(0), copySchema(0) { } ~Private() { delete copySchema; delete originalSchema; delete cursor; } QString objectName; KDbCursor *cursor; KDbConnection *connection; KDbQuerySchema *originalSchema; KDbQuerySchema *copySchema; }; KexiDBReportData::KexiDBReportData (const QString &objectName, KDbConnection * pDb) : d(new Private(pDb)) { d->objectName = objectName; getSchema(); } KexiDBReportData::KexiDBReportData(const QString& objectName, const QString& pluginId, KDbConnection* pDb) : d(new Private(pDb)) { d->objectName = objectName; getSchema(pluginId); } void KexiDBReportData::setSorting(const QList& sorting) { if (d->copySchema) { if (sorting.isEmpty()) return; KDbOrderByColumnList order; for (int i = 0; i < sorting.count(); i++) { order.appendField(d->copySchema, sorting[i].field, sorting[i].order == Qt::AscendingOrder); } d->copySchema->setOrderByColumnList(order); } else { qDebug() << "Unable to sort null schema"; } } void KexiDBReportData::addExpression(const QString& field, const QVariant& value, char relation) { if (d->copySchema) { KDbField *fld = d->copySchema->findTableField(field); if (fld) { d->copySchema->addToWhereExpression(fld, value, KDbToken(relation)); } } else { qDebug() << "Unable to add expresstion to null schema"; } } KexiDBReportData::~KexiDBReportData() { close(); delete d; } bool KexiDBReportData::open() { if ( d->connection && d->cursor == 0 ) { if ( d->objectName.isEmpty() ) { return false; } else if ( d->copySchema) { qDebug() << "Opening cursor.." << *d->copySchema; d->cursor = d->connection->executeQuery ( d->copySchema, 1 ); } if ( d->cursor ) { qDebug() << "Moving to first record.."; return d->cursor->moveFirst(); } else return false; } return false; } bool KexiDBReportData::close() { if ( d->cursor ) { const bool ok = d->cursor->close(); delete d->cursor; d->cursor = 0; return ok; } return true; } bool KexiDBReportData::getSchema(const QString& pluginId) { if (d->connection) { delete d->originalSchema; d->originalSchema = 0; delete d->copySchema; d->copySchema = 0; if ((pluginId.isEmpty() || pluginId == "org.kexi-project.table") && d->connection->tableSchema(d->objectName)) { qDebug() << d->objectName << "is a table.."; d->originalSchema = new KDbQuerySchema(d->connection->tableSchema(d->objectName)); } else if ((pluginId.isEmpty() || pluginId == "org.kexi-project.query") && d->connection->querySchema(d->objectName)) { qDebug() << d->objectName << "is a query.."; qDebug() << *d->connection->querySchema(d->objectName); d->originalSchema = new KDbQuerySchema(*(d->connection->querySchema(d->objectName))); } if (d->originalSchema) { const KDbNativeStatementBuilder builder(d->connection); KDbEscapedString sql; if (builder.generateSelectStatement(&sql, d->originalSchema)) { qDebug() << "Original:" << sql; } else { qDebug() << "Original: ERROR"; } qDebug() << *d->originalSchema; d->copySchema = new KDbQuerySchema(*d->originalSchema); qDebug() << *d->copySchema; if (builder.generateSelectStatement(&sql, d->copySchema)) { qDebug() << "Copy:" << sql; } else { qDebug() << "Copy: ERROR"; } } return true; } return false; } QString KexiDBReportData::sourceName() const { return d->objectName; } int KexiDBReportData::fieldNumber ( const QString &fld ) const { if (!d->cursor || !d->cursor->query()) { return -1; } const KDbQueryColumnInfo::Vector fieldsExpanded( d->cursor->query()->fieldsExpanded(KDbQuerySchema::Unique)); for (int i = 0; i < fieldsExpanded.size() ; ++i) { if (0 == QString::compare(fld, fieldsExpanded[i]->aliasOrName(), Qt::CaseInsensitive)) { return i; } } return -1; } QStringList KexiDBReportData::fieldNames() const { if (!d->originalSchema) { return QStringList(); } QStringList names; const KDbQueryColumnInfo::Vector fieldsExpanded( d->originalSchema->fieldsExpanded(KDbQuerySchema::Unique)); for (int i = 0; i < fieldsExpanded.size(); i++) { //! @todo in some Kexi mode captionOrAliasOrName() would be used here (more user-friendly) names.append(fieldsExpanded[i]->aliasOrName()); } return names; } QVariant KexiDBReportData::value ( unsigned int i ) const { if ( d->cursor ) return d->cursor->value ( i ); return QVariant(); } QVariant KexiDBReportData::value ( const QString &fld ) const { int i = fieldNumber ( fld ); - if ( d->cursor ) + if (d->cursor && i >= 0) return d->cursor->value ( i ); return QVariant(); } bool KexiDBReportData::moveNext() { if ( d->cursor ) return d->cursor->moveNext(); return false; } bool KexiDBReportData::movePrevious() { if ( d->cursor ) return d->cursor->movePrev(); return false; } bool KexiDBReportData::moveFirst() { if ( d->cursor ) return d->cursor->moveFirst(); return false; } bool KexiDBReportData::moveLast() { if ( d->cursor ) return d->cursor->moveLast(); return false; } qint64 KexiDBReportData::at() const { if ( d->cursor ) return d->cursor->at(); return 0; } qint64 KexiDBReportData::recordCount() const { if ( d->copySchema ) { return KDb::recordCount ( d->copySchema ); } return 1; } -#ifdef KREPORT_SCRIPTING -QStringList KexiDBReportData::scriptList(const QString& interpreter) const +static bool isInterpreterSupported(const QString &interpreterName) +{ + return 0 == interpreterName.compare(QLatin1String("javascript"), Qt::CaseInsensitive) + || 0 == interpreterName.compare(QLatin1String("qtscript"), Qt::CaseInsensitive); +} + +QStringList KexiDBReportData::scriptList() const { QStringList scripts; if( d->connection) { QList scriptids = d->connection->objectIds(KexiPart::ScriptObjectType); QStringList scriptnames = d->connection->objectNames(KexiPart::ScriptObjectType); qDebug() << scriptids << scriptnames; - qDebug() << interpreter; //A blank entry scripts << ""; int i = 0; foreach(int id, scriptids) { qDebug() << "ID:" << id; tristate res; QString script; res = d->connection->loadDataBlock(id, &script, QString()); if (res == true) { QDomDocument domdoc; bool parsed = domdoc.setContent(script, false); QDomElement scriptelem = domdoc.namedItem("script").toElement(); if (parsed && !scriptelem.isNull()) { - if (interpreter == scriptelem.attribute("language") && scriptelem.attribute("scripttype") == "object") { + if (scriptelem.attribute("scripttype") == "object" + && isInterpreterSupported(scriptelem.attribute("language"))) + { scripts << scriptnames[i]; } } else { qDebug() << "Unable to parse script"; } } else { qDebug() << "Unable to loadDataBlock"; } ++i; } qDebug() << scripts; } return scripts; } -QString KexiDBReportData::scriptCode(const QString& scriptname, const QString& language) const +QString KexiDBReportData::scriptCode(const QString& scriptname) const { QString scripts; if (d->connection) { QList scriptids = d->connection->objectIds(KexiPart::ScriptObjectType); QStringList scriptnames = d->connection->objectNames(KexiPart::ScriptObjectType); int i = 0; foreach(int id, scriptids) { qDebug() << "ID:" << id; tristate res; QString script; res = d->connection->loadDataBlock(id, &script, QString()); if (res == true) { QDomDocument domdoc; bool parsed = domdoc.setContent(script, false); if (! parsed) { qDebug() << "XML parsing error"; return QString(); } QDomElement scriptelem = domdoc.namedItem("script").toElement(); if (scriptelem.isNull()) { qDebug() << "script domelement is null"; return QString(); } QString interpretername = scriptelem.attribute("language"); - qDebug() << language << interpretername; qDebug() << scriptelem.attribute("scripttype"); qDebug() << scriptname << scriptnames[i]; - if (language == interpretername && (scriptelem.attribute("scripttype") == "module" || scriptname == scriptnames[i])) { + if ((isInterpreterSupported(interpretername) && scriptelem.attribute("scripttype") == "module") + || scriptname == scriptnames[i]) + { scripts += '\n' + scriptelem.text().toUtf8(); } ++i; } else { qDebug() << "Unable to loadDataBlock"; } } } return scripts; } -#endif QStringList KexiDBReportData::dataSources() const { //Get the list of queries in the database QStringList qs; if (d->connection && d->connection->isConnected()) { QList tids = d->connection->tableIds(); qs << ""; for (int i = 0; i < tids.size(); ++i) { KDbTableSchema* tsc = d->connection->tableSchema(tids[i]); if (tsc) qs << tsc->name(); } QList qids = d->connection->queryIds(); qs << ""; for (int i = 0; i < qids.size(); ++i) { KDbQuerySchema* qsc = d->connection->querySchema(qids[i]); if (qsc) qs << qsc->name(); } } return qs; } KoReportData* KexiDBReportData::data(const QString& source) { return new KexiDBReportData(source, d->connection); } diff --git a/kexi/plugins/reports/kexidbreportdata.h b/kexi/plugins/reports/kexidbreportdata.h index 579a631965f..1538574fbe2 100644 --- a/kexi/plugins/reports/kexidbreportdata.h +++ b/kexi/plugins/reports/kexidbreportdata.h @@ -1,83 +1,82 @@ /* * Kexi Report Plugin * Copyright (C) 2007-2009 by Adam Pigg (adam@piggz.co.uk) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #ifndef __KEXIDBREPORTDATA_H__ #define __KEXIDBREPORTDATA_H__ #include #include #include #include +#include #include /** */ class KexiDBReportData : public KoReportData { public: KexiDBReportData(const QString &objectName, KDbConnection *conn); /*! * @a pluginId specifies type of @a objectName, a table or query. * Types accepted: * -"org.kexi-project.table" * -"org.kexi-project.query" * -empty QString() - attempt to resolve @a objectName */ KexiDBReportData(const QString &objectName, const QString& pluginId, KDbConnection *conn); virtual ~KexiDBReportData(); virtual QStringList fieldNames() const; virtual void setSorting(const QList& sorting); virtual void addExpression(const QString &field, const QVariant &value, char relation = '='); virtual QString sourceName() const; virtual int fieldNumber(const QString &field) const; virtual QVariant value(unsigned int) const; virtual QVariant value(const QString &field) const; virtual bool open(); virtual bool close(); virtual bool moveNext(); virtual bool movePrevious(); virtual bool moveFirst(); virtual bool moveLast(); virtual qint64 at() const; virtual qint64 recordCount() const; //Utility Functions -#ifdef KREPORT_SCRIPTING - virtual QStringList scriptList(const QString& language) const; - virtual QString scriptCode(const QString& script, const QString& language) const; -#endif + virtual QStringList scriptList() const; + virtual QString scriptCode(const QString& script) const; virtual QStringList dataSources() const; virtual KoReportData* data(const QString&); private: class Private; Private * const d; bool getSchema(const QString& pluginId = QString()); }; #endif diff --git a/kexi/plugins/reports/kexireportview.cpp b/kexi/plugins/reports/kexireportview.cpp index 34f1d9b1036..4da7c0a34fe 100644 --- a/kexi/plugins/reports/kexireportview.cpp +++ b/kexi/plugins/reports/kexireportview.cpp @@ -1,521 +1,511 @@ /* * Kexi Report Plugin * Copyright (C) 2007-2008 by Adam Pigg (adam@piggz.co.uk) Copyright (C) 2014 Jarosław Staniek * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include "kexireportview.h" #include #include "kexidbreportdata.h" #ifndef KEXI_MOBILE #include //! @todo KEXI3 #if 0 #include "keximigratereportdata.h" #endif #endif #include #include #include -#ifdef KREPORT_SCRIPTING -#include "../scripting/kexiscripting/kexiscriptadaptor.h" -#endif +//! @todo KEXI3 #include "../scripting/kexiscripting/kexiscriptadaptor.h" #include #include #include +#include #include "krscriptfunctions.h" #include #include #include #include #include #include #include #include #include #include #include #include KexiReportView::KexiReportView(QWidget *parent) : KexiView(parent), m_preRenderer(0), m_reportDocument(0) //! @todo KEXI3, m_kexi(0), m_functions(0) { setObjectName("KexiReportDesigner_DataView"); m_reportView = new KReportView(this); layout()->addWidget(m_reportView); #ifndef KEXI_MOBILE m_pageSelector = new KexiRecordNavigator(*m_reportView->scrollArea(), m_reportView); m_pageSelector->setInsertingButtonVisible(false); m_pageSelector->setInsertingEnabled(false); m_pageSelector->setLabelText(xi18nc("Page selector label", "Page:")); m_pageSelector->setButtonToolTipText(KexiRecordNavigator::ButtonFirst, xi18n("Go to first page")); m_pageSelector->setButtonWhatsThisText(KexiRecordNavigator::ButtonFirst, xi18n("Goes to first page")); m_pageSelector->setButtonToolTipText(KexiRecordNavigator::ButtonPrevious, xi18n("Go to previous page")); m_pageSelector->setButtonWhatsThisText(KexiRecordNavigator::ButtonPrevious, xi18n("Goes to previous page")); m_pageSelector->setButtonToolTipText(KexiRecordNavigator::ButtonNext, xi18n("Go to next page")); m_pageSelector->setButtonWhatsThisText(KexiRecordNavigator::ButtonNext, xi18n("Goes to next page")); m_pageSelector->setButtonToolTipText(KexiRecordNavigator::ButtonLast, xi18n("Go to last page")); m_pageSelector->setButtonWhatsThisText(KexiRecordNavigator::ButtonLast, xi18n("Goes to last page")); m_pageSelector->setNumberFieldToolTips(xi18n("Current page number"), xi18n("Number of pages")); m_pageSelector->setRecordHandler(this); #endif // -- setup local actions QList viewActions; QAction* a; #ifndef KEXI_MOBILE viewActions << (a = new QAction(koIcon("document-print"), xi18n("Print"), this)); a->setObjectName("print_report"); a->setToolTip(xi18n("Print report")); a->setWhatsThis(xi18n("Prints the current report.")); connect(a, SIGNAL(triggered()), this, SLOT(slotPrintReport())); KActionMenu *exportMenu = new KActionMenu(koIcon("document-export"), xi18nc("@title:menu","E&xport As"), this); exportMenu->setObjectName("report_export_as"); exportMenu->setDelayed(false); #endif #ifdef KEXI_MOBILE viewActions << (a = new QAction(xi18n("Export:"), this)); a->setEnabled(false); //!TODO this is a bit of a dirty way to add what looks like a label to the toolbar! // " ", not "", is said to be needed in maemo, the icon didn't display properly without it viewActions << (a = new QAction(koIcon("application-vnd.oasis.opendocument.text"), QLatin1String(" "), this)); #else exportMenu->addAction(a = new QAction(koIcon("application-vnd.oasis.opendocument.text"), xi18nc("open dialog to export as text document", "Text Document..."), this)); #endif a->setObjectName("export_as_text_document"); a->setToolTip(xi18n("Export the report as a text document (in OpenDocument Text format)")); a->setWhatsThis(xi18n("Exports the report as a text document (in OpenDocument Text format).")); a->setEnabled(true); connect(a, SIGNAL(triggered()), this, SLOT(slotExportAsTextDocument())); #ifdef KEXI_MOBILE viewActions << (a = new QAction(koIcon("application-pdf"), QLatin1String(" "), this)); #else exportMenu->addAction(a = new QAction(koIcon("application-pdf"), xi18nc("Portable Document Format...", "PDF..."), this)); #endif a->setObjectName("export_as_pdf"); a->setToolTip(xi18n("Export as PDF")); a->setWhatsThis(xi18n("Exports the current report as PDF.")); a->setEnabled(true); connect(a, SIGNAL(triggered()), this, SLOT(slotExportAsPdf())); #ifdef KEXI_MOBILE viewActions << (a = new QAction(koIcon("application-vnd.oasis.opendocument.spreadsheet"), QLatin1String(" "), this)); #else exportMenu->addAction(a = new QAction(koIcon("application-vnd.oasis.opendocument.spreadsheet"), xi18nc("open dialog to export as spreadsheet", "Spreadsheet..."), this)); #endif a->setObjectName("export_as_spreadsheet"); a->setToolTip(xi18n("Export the report as a spreadsheet (in OpenDocument Spreadsheet format)")); a->setWhatsThis(xi18n("Exports the report as a spreadsheet (in OpenDocument Spreadsheet format).")); a->setEnabled(true); connect(a, SIGNAL(triggered()), this, SLOT(slotExportAsSpreadsheet())); #ifdef KEXI_MOBILE viewActions << (a = new QAction(koIcon("text-html"), QLatin1String(" "), this)); #else exportMenu->addAction(a = new QAction(koIcon("text-html"), xi18nc("open dialog to export as web page", "Web Page..."), this)); #endif a->setObjectName("export_as_web_page"); a->setToolTip(xi18n("Export the report as a web page (in HTML format)")); a->setWhatsThis(xi18n("Exports the report as a web page (in HTML format).")); a->setEnabled(true); connect(a, SIGNAL(triggered()), this, SLOT(slotExportAsWebPage())); setViewActions(viewActions); #ifndef KEXI_MOBILE // setup main menu actions QList mainMenuActions; mainMenuActions << exportMenu; setMainMenuActions(mainMenuActions); connect(m_pageSelector, SIGNAL(nextButtonClicked()), this, SLOT(nextPage())); connect(m_pageSelector, SIGNAL(prevButtonClicked()), this, SLOT(prevPage())); connect(m_pageSelector, SIGNAL(firstButtonClicked()), this, SLOT(firstPage())); connect(m_pageSelector, SIGNAL(lastButtonClicked()), this, SLOT(lastPage())); #endif } KexiReportView::~KexiReportView() { qDebug(); delete m_preRenderer; -#ifdef KREPORT_SCRIPTING - delete m_kexi; - delete m_functions; -#endif delete m_reportDocument; } void KexiReportView::slotPrintReport() { QPrinter printer(QPrinter::HighResolution); QPainter painter; KoReportRendererBase *renderer; renderer = m_factory.createInstance("print"); QPointer dialog = new QPrintDialog(&printer, this); if (dialog->exec() == QDialog::Accepted) { KoReportRendererContext cxt; cxt.printer = &printer; cxt.painter = &painter; renderer->render(cxt, m_reportDocument); } delete dialog; delete renderer; } void KexiReportView::slotExportAsPdf() { QScopedPointer renderer(m_factory.createInstance("print")); if (renderer) { KoReportRendererContext cxt; cxt.destinationUrl = getExportUrl(QLatin1String("application/pdf"), xi18n("Export Report as PDF"), "kfiledialog:///LastVisitedPDFExportPath/", "pdf"); if (!cxt.destinationUrl.isValid()) { return; } QPrinter printer; QPainter painter; printer.setOutputFileName(cxt.destinationUrl.path()); printer.setOutputFormat(QPrinter::PdfFormat); printer.setColorMode(QPrinter::Color); painter.begin(&printer); cxt.printer = &printer; cxt.painter = &painter; if (!renderer->render(cxt, m_reportDocument)) { KMessageBox::error(this, xi18n("Exporting the report as PDF to %1 failed.", cxt.destinationUrl.toDisplayString()), xi18n("Export Failed")); } else { openExportedDocument(cxt.destinationUrl); } } } QUrl KexiReportView::getExportUrl(const QString &mimetype, const QString &caption, const QString &lastExportPath, const QString &extension) { QUrl result; QString defaultSavePath; if (lastExportPath.startsWith("kfiledialog:///")) { defaultSavePath = lastExportPath + window()->partItem()->captionOrName() + "." + extension; } // loop until an url has been chosen or the file selection has been cancelled const QMimeDatabase db; const QString filterString = db.mimeTypeForName(mimetype).filterString(); while (true) { QUrl result = QFileDialog::getSaveFileUrl(this, caption, QUrl::fromLocalFile(defaultSavePath), filterString); // not cancelled? if (result.isValid()) { if (KIO::NetAccess::exists(result, KIO::NetAccess::DestinationSide, this)) { const KMessageBox::ButtonCode answer = KMessageBox::warningContinueCancel(this, xi18n("The file %1 exists.\nDo you want to overwrite it?", result.path()), caption, KGuiItem(xi18nc("@action:button Overwrite File", "Overwrite"))); // if overwriting not wanted, let select another url if (answer == KMessageBox::Cancel) { continue; } } } // decision has been made, leave loop break; } return result; } void KexiReportView::openExportedDocument(const QUrl &destination) { const int answer = KMessageBox::questionYesNo( this, xi18n("Do you want to open exported document?"), QString(), KStandardGuiItem::open(), KStandardGuiItem::close()); if (answer == KMessageBox::Yes) { (void)new KRun(destination, this->topLevelWidget()); } } void KexiReportView::slotExportAsSpreadsheet() { KoReportRendererBase *renderer; KoReportRendererContext cxt; renderer = m_factory.createInstance("ods"); if (renderer) { cxt.destinationUrl = getExportUrl(QLatin1String("application/vnd.oasis.opendocument.spreadsheet"), xi18n("Export Report as Spreadsheet"), "kfiledialog:///LastVisitedODSExportPath/", "ods"); if (!cxt.destinationUrl.isValid()) { return; } if (!renderer->render(cxt, m_reportDocument)) { KMessageBox::error(this, xi18n("Failed to export the report as spreadsheet to %1.", cxt.destinationUrl.toDisplayString()), xi18n("Export Failed")); } else { openExportedDocument(cxt.destinationUrl); } } } void KexiReportView::slotExportAsTextDocument() { KoReportRendererBase *renderer; KoReportRendererContext cxt; renderer = m_factory.createInstance("odt"); if (renderer) { cxt.destinationUrl = getExportUrl(QLatin1String("application/vnd.oasis.opendocument.text"), xi18n("Export Report as Text Document"), "kfiledialog:///LastVisitedODTExportPath/", "odt"); if (!cxt.destinationUrl.isValid()) { return; } if (!renderer->render(cxt, m_reportDocument)) { KMessageBox::error(this, xi18n("Exporting the report as text document to %1 failed.", cxt.destinationUrl.toDisplayString()), xi18n("Export Failed")); } else { openExportedDocument(cxt.destinationUrl); } } } void KexiReportView::slotExportAsWebPage() { KoReportRendererContext cxt; KoReportRendererBase *renderer; const QString dialogTitle = xi18n("Export Report as Web Page"); cxt.destinationUrl = getExportUrl(QLatin1String("text/html"), dialogTitle, "kfiledialog:///LastVisitedHTMLExportPath/", "html"); if (!cxt.destinationUrl.isValid()) { return; } const int answer = KMessageBox::questionYesNo( this, xi18n("Would you like to export using a Cascading Style Sheet (CSS), " "which will give an output closer to the original, " "or export using a HTML Table, which outputs a much simpler format?"), dialogTitle, KGuiItem(xi18nc("@action:button", "Use CSS")), KGuiItem(xi18nc("@action:button", "Use Table"))); if (answer == KMessageBox::Yes) { renderer = m_factory.createInstance("htmlcss"); } else { renderer = m_factory.createInstance("htmltable"); } if (!renderer->render(cxt, m_reportDocument)) { KMessageBox::error(this, xi18n("Exporting the report as web page to %1 failed.", cxt.destinationUrl.toDisplayString()), xi18n("Export Failed")); } else { openExportedDocument(cxt.destinationUrl); } } tristate KexiReportView::beforeSwitchTo(Kexi::ViewMode mode, bool *dontStore) { Q_UNUSED(mode); Q_UNUSED(dontStore); return true; } tristate KexiReportView::afterSwitchFrom(Kexi::ViewMode mode) { Q_UNUSED(mode); qDebug(); if (tempData()->reportSchemaChangedInPreviousView) { qDebug() << "Schema changed"; delete m_preRenderer; qDebug() << tempData()->reportDefinition.tagName(); m_preRenderer = new KoReportPreRenderer(tempData()->reportDefinition); if (m_preRenderer->isValid()) { KoReportData *reportData = 0; if (!tempData()->connectionDefinition.isNull()) { reportData = sourceData(tempData()->connectionDefinition); } m_preRenderer->setSourceData(reportData); m_preRenderer->setName(window()->partItem()->name()); -#ifdef KREPORT_SCRIPTING //Add a kexi object to provide kexidb and extra functionality - if(!m_kexi) { - m_kexi = new KexiScriptAdaptor(); - } - m_preRenderer->registerScriptObject(m_kexi, "Kexi"); +//! @todo KEXI3 if we want this if(!m_kexi) { +// m_kexi = new KexiScriptAdaptor(); +// } +// m_preRenderer->registerScriptObject(m_kexi, "Kexi"); //If using a kexidb source, add a functions scripting object if (tempData()->connectionDefinition.attribute("type") == "internal") { - //Delete old functions - if (m_functions) { - delete m_functions; - } - m_functions = new KRScriptFunctions(reportData, KexiMainWindowIface::global()->project()->dbConnection()); m_preRenderer->registerScriptObject(m_functions, "field"); + connect(m_preRenderer, SIGNAL(groupChanged(QMap)), + m_functions, SLOT(setGroupData(QMap))); } -#endif if (m_reportDocument) { qDebug() << "=======================================Deleting old document"; delete m_reportDocument; } m_reportDocument = m_preRenderer->generate(); if (m_reportDocument) { m_reportView->setDocument(m_reportDocument); #ifndef KEXI_MOBILE m_pageSelector->setRecordCount(m_reportView->pageCount()); m_pageSelector->setCurrentRecordNumber(1); #endif } } else { KMessageBox::error(this, xi18n("Report schema appears to be invalid or corrupt"), xi18n("Opening failed")); } tempData()->reportSchemaChangedInPreviousView = false; } return true; } KoReportData* KexiReportView::sourceData(QDomElement e) { KoReportData *kodata = 0; if (e.attribute("type") == "internal" && !e.attribute("source").isEmpty()) { kodata = new KexiDBReportData(e.attribute("source"), KexiMainWindowIface::global()->project()->dbConnection()); } #ifndef KEXI_MOBILE //! @todo KEXI3 #if 0 if (e.attribute("type") == "external") { kodata = new KexiMigrateReportData(e.attribute("source")); } #endif #endif return kodata; } KexiReportPart::TempData* KexiReportView::tempData() const { return static_cast(window()->data()); } void KexiReportView::addNewRecordRequested() { } void KexiReportView::moveToFirstRecordRequested() { m_reportView->moveToFirstPage(); #ifndef KEXI_MOBILE m_pageSelector->setCurrentRecordNumber(m_reportView->currentPage()); #endif } void KexiReportView::moveToLastRecordRequested() { m_reportView->moveToLastPage(); #ifndef KEXI_MOBILE m_pageSelector->setCurrentRecordNumber(m_reportView->currentPage()); #endif } void KexiReportView::moveToNextRecordRequested() { m_reportView->moveToNextPage(); #ifndef KEXI_MOBILE m_pageSelector->setCurrentRecordNumber(m_reportView->currentPage()); #endif } void KexiReportView::moveToPreviousRecordRequested() { m_reportView->moveToPreviousPage(); #ifndef KEXI_MOBILE m_pageSelector->setCurrentRecordNumber(m_reportView->currentPage()); #endif } void KexiReportView::moveToRecordRequested(int r) { Q_UNUSED(r); } int KexiReportView::currentRecord() const { return m_reportView->currentPage(); } int KexiReportView::recordCount() const { return m_reportView->pageCount(); } diff --git a/kexi/plugins/reports/kexireportview.h b/kexi/plugins/reports/kexireportview.h index bcc6ccb4cfc..05fc6de0477 100644 --- a/kexi/plugins/reports/kexireportview.h +++ b/kexi/plugins/reports/kexireportview.h @@ -1,96 +1,93 @@ /* * Kexi Report Plugin * Copyright (C) 2007-2008 by Adam Pigg (adam@piggz.co.uk) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #ifndef KEXIREPORTVIEW_H #define KEXIREPORTVIEW_H #include #include +#include #include #include #include #include "kexireportpart.h" class KoReportPreRenderer; class ORODocument; class KReportView; -#ifdef KREPORT_SCRIPTING -class KexiScriptAdaptor; +//! @todo KEXI3 class KexiScriptAdaptor; class KRScriptFunctions; -#endif #ifndef KEXI_MOBILE class KexiRecordNavigator; #endif /** @author Adam Pigg */ class KexiReportView : public KexiView, public KexiRecordNavigatorHandler { Q_OBJECT public: explicit KexiReportView(QWidget *parent); ~KexiReportView(); virtual tristate afterSwitchFrom(Kexi::ViewMode mode); virtual tristate beforeSwitchTo(Kexi::ViewMode mode, bool *dontStore); virtual void addNewRecordRequested(); virtual void moveToFirstRecordRequested(); virtual void moveToLastRecordRequested(); virtual void moveToNextRecordRequested(); virtual void moveToPreviousRecordRequested(); virtual void moveToRecordRequested(int r); virtual int currentRecord() const; virtual int recordCount() const; private: KoReportPreRenderer *m_preRenderer; ORODocument *m_reportDocument; KReportView *m_reportView; #ifndef KEXI_MOBILE KexiRecordNavigator *m_pageSelector; #endif KexiReportPart::TempData* tempData() const; KoReportData* sourceData(QDomElement e); -#ifdef KREPORT_SCRIPTING - KexiScriptAdaptor *m_kexi; + //! @todo KEXI3 KexiScriptAdaptor *m_kexi; KRScriptFunctions *m_functions; -#endif KoReportRendererFactory m_factory; //! @todo KEXI3 add equivalent of kfiledialog:/// for lastExportPathOrVariable QUrl getExportUrl(const QString &mimetype, const QString &caption, const QString &lastExportPathOrVariable, const QString &extension); private Q_SLOTS: void slotPrintReport(); void slotExportAsPdf(); void slotExportAsSpreadsheet(); void slotExportAsWebPage(); void slotExportAsTextDocument(); void openExportedDocument(const QUrl &destination); }; #endif diff --git a/kexi/plugins/reports/krscriptfunctions.cpp b/kexi/plugins/reports/krscriptfunctions.cpp index ac7e1aa78c6..760d2add926 100644 --- a/kexi/plugins/reports/krscriptfunctions.cpp +++ b/kexi/plugins/reports/krscriptfunctions.cpp @@ -1,108 +1,122 @@ /* * Kexi Report Plugin * Copyright (C) 2007-2008 by Adam Pigg * Copyright (C) 2012 Jarosław Staniek * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include "krscriptfunctions.h" #include #include #include KRScriptFunctions::KRScriptFunctions(const KoReportData* kodata, KDbConnection* conn) { m_cursor = kodata; m_connection = conn; - m_source = kodata->sourceName(); + + if (kodata) { + m_source = kodata->sourceName(); + } } KRScriptFunctions::~KRScriptFunctions() { } -void KRScriptFunctions::setWhere(const KDbEscapedString&w) +void KRScriptFunctions::setGroupData(const QMap& groupData) { - m_where = w; + m_groupData = groupData; } qreal KRScriptFunctions::math(const QString &function, const QString &field) { - qreal ret; + QString ret = QLatin1String("0.0"); + + if (!m_connection) { + return 0.0; + } + KDbEscapedString sql = KDbEscapedString("SELECT " + function + "(" + field + ") FROM (" + m_source + ")"); - if (!m_where.isEmpty()) { - sql += " WHERE(" + m_where + ')'; + if (!m_groupData.isEmpty()) { + sql += " WHERE(" + where() + ')'; } qDebug() << sql; - KDbCursor *curs = m_connection->executeQuery(sql); - if (curs) { - ret = curs->value(0).toDouble(); - } else { - ret = 0.0; - } - delete curs; + m_connection->querySingleString(sql,&ret); - return ret; + return ret.toDouble(); } qreal KRScriptFunctions::sum(const QString &field) { return math("SUM", field); } qreal KRScriptFunctions::avg(const QString &field) { return math("AVG", field); } qreal KRScriptFunctions::min(const QString &field) { return math("MIN", field); } qreal KRScriptFunctions::max(const QString &field) { return math("MAX", field); } qreal KRScriptFunctions::count(const QString &field) { return math("COUNT", field); } QVariant KRScriptFunctions::value(const QString &field) { QVariant val; if (!m_cursor) { qDebug() << "No cursor to get value of field " << field; return val; } QStringList fields = m_cursor->fieldNames(); val = m_cursor->value(fields.indexOf(field)); if (val.type() == QVariant::String) { // UTF-8 values are expected so convert this return val.toString().toUtf8(); } return val; } +KDbEscapedString KRScriptFunctions::where() +{ + QByteArray w; + QMap::const_iterator i = m_groupData.constBegin(); + while (i != m_groupData.constEnd()) { + w += QLatin1Char('(') + i.key() + QLatin1String(" = '") + i.value().toString() + QLatin1String("') AND "); + ++i; + } + w.chop(4); + //kreportDebug() << w; + return KDbEscapedString(w); +} diff --git a/kexi/plugins/reports/krscriptfunctions.h b/kexi/plugins/reports/krscriptfunctions.h index f1830029ff3..2b300667bc7 100644 --- a/kexi/plugins/reports/krscriptfunctions.h +++ b/kexi/plugins/reports/krscriptfunctions.h @@ -1,59 +1,63 @@ /* * Kexi Report Plugin * Copyright (C) 2007-2008 by Adam Pigg (adam@piggz.co.uk) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #ifndef KRSCRIPTFUNCTIONS_H #define KRSCRIPTFUNCTIONS_H #include #include #include #include #include +#include /** @author */ -class KRScriptFunctions : public QObject +class KRScriptFunctions : public KReportGroupTracker { Q_OBJECT public: KRScriptFunctions(const KoReportData *, KDbConnection*); ~KRScriptFunctions(); private: KDbConnection *m_connection; const KoReportData *m_cursor; QString m_source; qreal math(const QString &, const QString &); - KDbEscapedString m_where; + QMap m_groupData; + + KDbEscapedString where(); + public Q_SLOTS: - void setWhere(const KDbEscapedString&); + virtual void setGroupData(const QMap &groupData); qreal sum(const QString &); qreal avg(const QString &); qreal min(const QString &); qreal max(const QString &); qreal count(const QString &); QVariant value(const QString &); }; #endif