diff --git a/kexi/plugins/reports/kexireportdesignview.cpp b/kexi/plugins/reports/kexireportdesignview.cpp index 26b976042ef..5820e27032c 100644 --- a/kexi/plugins/reports/kexireportdesignview.cpp +++ b/kexi/plugins/reports/kexireportdesignview.cpp @@ -1,209 +1,209 @@ /* * Kexi Report Plugin * Copyright (C) 2007-2009 by Adam Pigg * Copyright (C) 2011 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 "kexireportdesignview.h" #include #include #include #include #include "kexisourceselector.h" #include #include KexiReportDesignView::KexiReportDesignView(QWidget *parent, KexiSourceSelector *s) : KexiView(parent) { m_scrollArea = new QScrollArea(this); layout()->addWidget(m_scrollArea); m_sourceSelector = s; m_reportDesigner = 0; m_editCutAction = KStandardAction::cut(this); m_editCutAction->setProperty("iconOnly", true); m_editCopyAction = KStandardAction::copy(this); m_editCopyAction->setProperty("iconOnly", true); m_editPasteAction = KStandardAction::paste(this); m_editPasteAction->setProperty("iconOnly", true); const KGuiItem del = KStandardGuiItem::del(); m_editDeleteAction = new KAction(del.icon(), del.text(), this); m_editDeleteAction->setObjectName("editdelete"); m_editDeleteAction->setToolTip(del.toolTip()); m_editDeleteAction->setWhatsThis(del.whatsThis()); m_editDeleteAction->setProperty("iconOnly", true); m_sectionEdit = new KAction(i18n("Edit Sections"), this); m_sectionEdit->setObjectName("sectionedit"); m_itemRaiseAction = new KAction(koIcon("arrow-up"), i18n("Raise"), this); m_itemRaiseAction->setObjectName("itemraise"); m_itemLowerAction = new KAction(koIcon("arrow-down"), i18n("Lower"), this); m_itemLowerAction->setObjectName("itemlower"); QList al; KAction *sep = new KAction(QString(), this); sep->setSeparator(true); al << m_editCutAction << m_editCopyAction << m_editPasteAction << m_editDeleteAction << sep << m_sectionEdit << sep << m_itemLowerAction << m_itemRaiseAction; setViewActions(al); } KexiReportDesignView::~KexiReportDesignView() { } KoProperty::Set *KexiReportDesignView::propertySet() { return m_reportDesigner->itemPropertySet(); } void KexiReportDesignView::slotDesignerPropertySetChanged() { propertySetReloaded(true); propertySetSwitched(); } KexiDB::SchemaData* KexiReportDesignView::storeNewData(const KexiDB::SchemaData& sdata, KexiView::StoreNewDataOptions options, bool &cancel) { KexiDB::SchemaData *s = KexiView::storeNewData(sdata, options, cancel); kDebug() << "new id:" << s->id(); if (!s || cancel) { delete s; return 0; } if (!storeData()) { //failure: remove object's schema data to avoid garbage KexiDB::Connection *conn = KexiMainWindowIface::global()->project()->dbConnection(); conn->removeObject(s->id()); delete s; return 0; } return s; } tristate KexiReportDesignView::storeData(bool dontAsk) { Q_UNUSED(dontAsk); QDomDocument doc("kexireport"); QDomElement root = doc.createElement("kexireport"); QDomElement conndata = m_sourceSelector->connectionData(); if (conndata.isNull()) kDebug() << "Null conn data!"; root.appendChild(m_reportDesigner->document()); root.appendChild(conndata); doc.appendChild(root); QString src = doc.toString(); kDebug() << src; if (storeDataBlock(src, "layout")) { kDebug() << "Saved OK"; setDirty(false); return true; } kDebug() << "NOT Saved OK"; return false; } tristate KexiReportDesignView::beforeSwitchTo(Kexi::ViewMode mode, bool &dontStore) { kDebug() << mode; dontStore = true; if (m_reportDesigner && mode == Kexi::DataViewMode) { kDebug() << "Saving temp data"; tempData()->reportDefinition = m_reportDesigner->document(); kDebug() << m_reportDesigner->document().toDocument().toString(); tempData()->reportSchemaChangedInPreviousView = true; } return true; } tristate KexiReportDesignView::afterSwitchFrom(Kexi::ViewMode mode) { Q_UNUSED(mode); if (tempData()->reportDefinition.isNull()) { m_reportDesigner = new KoReportDesigner(this); } else { if (m_reportDesigner) { m_scrollArea->takeWidget(); delete m_reportDesigner; m_reportDesigner = 0; } m_reportDesigner = new KoReportDesigner(this, tempData()->reportDefinition); m_sourceSelector->setConnectionData(tempData()->connectionDefinition); } connect(m_reportDesigner, SIGNAL(itemInserted(QString)), this, SIGNAL(itemInserted(QString))); m_scrollArea->setWidget(m_reportDesigner); connect(m_reportDesigner, SIGNAL(propertySetChanged()), this, SLOT(slotDesignerPropertySetChanged())); connect(m_reportDesigner, SIGNAL(dirty()), this, SLOT(setDirty())); //Added default keyboard shortcuts for the actions QShortcut *cutShortcut = new QShortcut(QKeySequence(QKeySequence::Cut), m_reportDesigner); QShortcut *copyShortcut = new QShortcut(QKeySequence(QKeySequence::Copy), m_reportDesigner); QShortcut *pasteShortcut = new QShortcut(QKeySequence(QKeySequence::Paste), m_reportDesigner); QShortcut *deleteShortcut = new QShortcut(QKeySequence(QKeySequence::Delete), m_reportDesigner); connect(cutShortcut, SIGNAL(activated()), m_reportDesigner, SLOT(slotEditCut())); connect(copyShortcut, SIGNAL(activated()), m_reportDesigner, SLOT(slotEditCopy())); connect(pasteShortcut, SIGNAL(activated()), m_reportDesigner, SLOT(slotEditPaste())); connect(deleteShortcut, SIGNAL(activated()), m_reportDesigner, SLOT(slotEditDelete())); //Edit Actions connect(m_editCutAction, SIGNAL(activated()), m_reportDesigner, SLOT(slotEditCut())); connect(m_editCopyAction, SIGNAL(activated()), m_reportDesigner, SLOT(slotEditCopy())); connect(m_editPasteAction, SIGNAL(activated()), m_reportDesigner, SLOT(slotEditPaste())); connect(m_editDeleteAction, SIGNAL(activated()), m_reportDesigner, SLOT(slotEditDelete())); connect(m_sectionEdit, SIGNAL(activated()), m_reportDesigner, SLOT(slotSectionEditor())); //Raise/Lower connect(m_itemRaiseAction, SIGNAL(activated()), m_reportDesigner, SLOT(slotRaiseSelected())); connect(m_itemLowerAction, SIGNAL(activated()), m_reportDesigner, SLOT(slotLowerSelected())); return true; } KexiReportPart::TempData* KexiReportDesignView::tempData() const { return static_cast(window()->data()); } -void KexiReportDesignView::slotSetData(KoReportData* kodata) +void KexiReportDesignView::slotSourceDataChanged() { - m_reportDesigner->setReportData(kodata); + m_reportDesigner->setReportData(m_sourceSelector->createSourceData()); tempData()->connectionDefinition = m_sourceSelector->connectionData(); setDirty(true); } void KexiReportDesignView::triggerAction(const QString &action) { m_reportDesigner->slotItem(action); } diff --git a/kexi/plugins/reports/kexireportdesignview.h b/kexi/plugins/reports/kexireportdesignview.h index 6dee95622bf..094d7c74608 100644 --- a/kexi/plugins/reports/kexireportdesignview.h +++ b/kexi/plugins/reports/kexireportdesignview.h @@ -1,83 +1,81 @@ /* * Kexi Report Plugin * Copyright (C) 2007-2009 by Adam Pigg * Copyright (C) 2011 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 . */ #ifndef KEXIREPORTDESIGNVIEW_H #define KEXIREPORTDESIGNVIEW_H #include #include #include #include #include #include class QScrollArea; class KexiSourceSelector; /** @author */ class KexiReportDesignView : public KexiView { Q_OBJECT public: KexiReportDesignView(QWidget *parent, KexiSourceSelector*); ~KexiReportDesignView(); virtual tristate afterSwitchFrom(Kexi::ViewMode mode); virtual tristate beforeSwitchTo(Kexi::ViewMode mode, bool &dontStore); void triggerAction(const QString &); Q_SIGNALS: void itemInserted(const QString& entity); private: KoReportDesigner *m_reportDesigner; KoProperty::Set *m_propertySet; KexiReportPart::TempData* tempData() const; QScrollArea * m_scrollArea; //Actions KAction *m_editCutAction; KAction *m_editCopyAction; KAction *m_editPasteAction; KAction *m_editDeleteAction; KAction *m_sectionEdit; KAction *m_parameterEdit; KAction *m_itemRaiseAction; KAction *m_itemLowerAction; KexiSourceSelector *m_sourceSelector; protected: virtual KoProperty::Set *propertySet(); virtual tristate storeData(bool dontAsk = false); virtual KexiDB::SchemaData* storeNewData(const KexiDB::SchemaData& sdata, KexiView::StoreNewDataOptions options, bool &cancel); private Q_SLOTS: void slotDesignerPropertySetChanged(); - -public Q_SLOTS: - void slotSetData(KoReportData*); + void slotSourceDataChanged(); }; #endif diff --git a/kexi/plugins/reports/kexireportpart.cpp b/kexi/plugins/reports/kexireportpart.cpp index 022f81ef138..d46693ef3b5 100644 --- a/kexi/plugins/reports/kexireportpart.cpp +++ b/kexi/plugins/reports/kexireportpart.cpp @@ -1,215 +1,215 @@ /* * Kexi Report Plugin * Copyright (C) 2007-2008 by Adam Pigg * Copyright (C) 2011 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 "kexireportpart.h" #include #include #include #include #include #include "kexireportview.h" #include "kexireportdesignview.h" #include #include #include "kexisourceselector.h" //! @internal class KexiReportPart::Private { public: Private() : toolboxActionGroup(0) { sourceSelector = 0; } ~Private() { } KexiSourceSelector *sourceSelector; QActionGroup toolboxActionGroup; QMap toolboxActionsByName; }; KexiReportPart::KexiReportPart(QObject *parent, const QVariantList &l) : KexiPart::Part(parent, i18nc("Translate this word using only lowercase alphanumeric characters (a..z, 0..9). " "Use '_' character instead of spaces. First character should be a..z character. " "If you cannot use latin characters in your language, use english word.", "report"), i18nc("tooltip", "Create new report"), i18nc("what's this", "Creates new report."), l) , d(new Private) { setInternalPropertyValue("newObjectsAreDirty", true); } KexiReportPart::~KexiReportPart() { delete d; } KLocalizedString KexiReportPart::i18nMessage( const QString& englishMessage, KexiWindow* window) const { Q_UNUSED(window); if (englishMessage == "Design of object %1 has been modified.") return ki18n(I18N_NOOP("Design of report %1 has been modified.")); if (englishMessage == "Object %1 already exists.") return ki18n(I18N_NOOP("Report %1 already exists.")); return Part::i18nMessage(englishMessage, window); } KexiView* KexiReportPart::createView(QWidget *parent, KexiWindow* window, KexiPart::Item &item, Kexi::ViewMode viewMode, QMap*) { Q_UNUSED(window); Q_UNUSED(item); KexiView* view = 0; if (viewMode == Kexi::DataViewMode) { view = new KexiReportView(parent); } else if (viewMode == Kexi::DesignViewMode) { view = new KexiReportDesignView(parent, d->sourceSelector); - connect(d->sourceSelector, SIGNAL(setData(KoReportData*)), view, SLOT(slotSetData(KoReportData*))); + connect(d->sourceSelector, SIGNAL(sourceDataChanged()), view, SLOT(slotSourceDataChanged())); connect(view, SIGNAL(itemInserted(QString)), this, SLOT(slotItemInserted(QString))); } return view; } void KexiReportPart::initPartActions() { KexiMainWindowIface *win = KexiMainWindowIface::global(); QList reportActions = KoReportDesigner::actions(&d->toolboxActionGroup); foreach(QAction* action, reportActions) { connect(action, SIGNAL(triggered(bool)), this, SLOT(slotToolboxActionTriggered(bool))); win->addToolBarAction("report", action); d->toolboxActionsByName.insert(action->objectName(), action); } } QString KexiReportPart::loadReport(const QString& name) { KexiMainWindowIface *win = KexiMainWindowIface::global(); KexiDB::Connection *conn; if (!win || !win->project() || !((conn = win->project()->dbConnection()))) { kDebug() << "failed sanity check: !win || !win->project() || !((conn = win->project()->dbConnection()))"; return QString(); } QString src, did; KexiDB::SchemaData sd; if (conn->loadObjectSchemaData(win->project()->idForClass("org.kexi-project.report"), name, sd) != true && conn->loadObjectSchemaData(win->project()->idForClass("uk.co.piggz.report"), name, sd) != true /* compat. */) { kWarning() << "failed to load schema data"; return QString(); } kDebug() << "***Object ID:" << sd.id(); if ( win->project()->dbConnection()->loadDataBlock(sd.id(), src, "layout") == true || win->project()->dbConnection()->loadDataBlock(sd.id(), src, "pgzreport_layout") == true /* compat */) { return src; } kWarning() << "Unable to load document"; return QString(); } KexiWindowData* KexiReportPart::createWindowData(KexiWindow* window) { kDebug(); const QString document(loadReport(window->partItem()->name())); KexiReportPart::TempData *td = new KexiReportPart::TempData(window); QDomDocument doc; doc.setContent(document); kDebug() << doc.toString(); QDomElement root = doc.documentElement(); QDomElement korep = root.firstChildElement("report:content"); QDomElement conn = root.firstChildElement("connection"); td->reportDefinition = korep; td->connectionDefinition = conn; return td; } KexiReportPart::TempData::TempData(QObject* parent) : KexiWindowData(parent) , reportSchemaChangedInPreviousView(true /*to force reloading on startup*/) { } void KexiReportPart::setupCustomPropertyPanelTabs(KTabWidget *tab) { if (!d->sourceSelector) { d->sourceSelector = new KexiSourceSelector(KexiMainWindowIface::global()->project(), tab); } tab->addTab(d->sourceSelector, koIcon("server-database"), QString()); tab->setTabToolTip(tab->indexOf(d->sourceSelector), i18n("Data Source")); } void KexiReportPart::slotToolboxActionTriggered(bool checked) { if (!checked) return; QObject *theSender = sender(); if (!theSender) return; QString senderName = sender()->objectName(); KexiMainWindowIface *mainwin = KexiMainWindowIface::global(); KexiWindow *win = mainwin->currentWindow(); if (!win) return; KexiView *designView = win->viewForMode(Kexi::DesignViewMode); if (designView) { KexiReportDesignView *dv = dynamic_cast(designView); if (!dv) return; dv->triggerAction(senderName); } } void KexiReportPart::slotItemInserted(const QString& entity) { Q_UNUSED(entity); // uncheck toolbox action after it is used QAction * a = d->toolboxActionGroup.checkedAction(); if (a) { a->setChecked(false); } } #include "kexireportpart.moc" diff --git a/kexi/plugins/reports/kexireportview.cpp b/kexi/plugins/reports/kexireportview.cpp index 01262134be7..2725529eaa2 100644 --- a/kexi/plugins/reports/kexireportview.cpp +++ b/kexi/plugins/reports/kexireportview.cpp @@ -1,530 +1,530 @@ /* * Kexi Report Plugin * Copyright (C) 2007-2008 by Adam Pigg (adam@piggz.co.uk) Copyright (C) 2014-2016 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 "keximigratereportdata.h" #endif #include #include #include #include #include #include #include #include #include #include #include "krscriptfunctions.h" #include #include #include #include #include #include #include #ifndef KEXI_MOBILE #include #endif #include #include #include "../scripting/kexiscripting/kexiscriptadaptor.h" KexiReportView::KexiReportView(QWidget *parent) : KexiView(parent), m_preRenderer(0), m_currentPage(0), m_pageCount(0), m_kexi(0), m_functions(0) { setObjectName("KexiReportDesigner_DataView"); m_reportView = new QGraphicsView(this); // page selector should be always visible: m_reportView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); layout()->addWidget(m_reportView); m_reportScene = new QGraphicsScene(this); m_reportScene->setSceneRect(0,0,1000,2000); m_reportView->setScene(m_reportScene); m_reportScene->setBackgroundBrush(palette().brush(QPalette::Dark)); #ifndef KEXI_MOBILE m_pageSelector = new KexiRecordNavigator(*m_reportView, m_reportView); m_pageSelector->setInsertingButtonVisible(false); m_pageSelector->setInsertingEnabled(false); m_pageSelector->setLabelText(i18n("Page")); m_pageSelector->setButtonToolTipText(KexiRecordNavigator::ButtonFirst, i18n("Go to first page")); m_pageSelector->setButtonWhatsThisText(KexiRecordNavigator::ButtonFirst, i18n("Goes to first page")); m_pageSelector->setButtonToolTipText(KexiRecordNavigator::ButtonPrevious, i18n("Go to previous page")); m_pageSelector->setButtonWhatsThisText(KexiRecordNavigator::ButtonPrevious, i18n("Goes to previous page")); m_pageSelector->setButtonToolTipText(KexiRecordNavigator::ButtonNext, i18n("Go to next page")); m_pageSelector->setButtonWhatsThisText(KexiRecordNavigator::ButtonNext, i18n("Goes to next page")); m_pageSelector->setButtonToolTipText(KexiRecordNavigator::ButtonLast, i18n("Go to last page")); m_pageSelector->setButtonWhatsThisText(KexiRecordNavigator::ButtonLast, i18n("Goes to last page")); m_pageSelector->setNumberFieldToolTips(i18n("Current page number"), i18n("Number of pages")); m_pageSelector->setRecordHandler(this); #endif // -- setup local actions QList viewActions; QAction* a; #ifndef KEXI_MOBILE viewActions << (a = new KAction(koIcon("document-print"), i18n("Print"), this)); a->setObjectName("print_report"); a->setToolTip(i18n("Print report")); a->setWhatsThis(i18n("Prints the current report.")); connect(a, SIGNAL(triggered()), this, SLOT(slotPrintReport())); KActionMenu *exportMenu = new KActionMenu(koIcon("document-export"), i18nc("@title:menu","E&xport As"), this); exportMenu->setObjectName("report_export_as"); exportMenu->setDelayed(false); #endif #ifdef KEXI_MOBILE viewActions << (a = new KAction(i18n("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 KAction(koIcon("application-vnd.oasis.opendocument.text"), QLatin1String(" "), this)); #else exportMenu->addAction(a = new KAction(koIcon("application-vnd.oasis.opendocument.text"), i18nc("open dialog to export as text document", "Text Document..."), this)); #endif a->setObjectName("export_as_text_document"); a->setToolTip(i18n("Export the report as a text document (in OpenDocument Text format)")); a->setWhatsThis(i18n("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 KAction(koIcon("application-pdf"), QLatin1String(" "), this)); #else exportMenu->addAction(a = new KAction(koIcon("application-pdf"), i18nc("Portable Document Format...", "PDF..."), this)); #endif a->setObjectName("export_as_pdf"); a->setToolTip(i18n("Export as PDF")); a->setWhatsThis(i18n("Exports the current report as PDF.")); a->setEnabled(true); connect(a, SIGNAL(triggered()), this, SLOT(slotExportAsPdf())); #ifdef KEXI_MOBILE viewActions << (a = new KAction(koIcon("application-vnd.oasis.opendocument.spreadsheet"), QLatin1String(" "), this)); #else exportMenu->addAction(a = new KAction(koIcon("application-vnd.oasis.opendocument.spreadsheet"), i18nc("open dialog to export as spreadsheet", "Spreadsheet..."), this)); #endif a->setObjectName("export_as_spreadsheet"); a->setToolTip(i18n("Export the report as a spreadsheet (in OpenDocument Spreadsheet format)")); a->setWhatsThis(i18n("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 KAction(koIcon("text-html"), QLatin1String(" "), this)); #else exportMenu->addAction(a = new KAction(koIcon("text-html"), i18nc("open dialog to export as web page", "Web Page..."), this)); #endif a->setObjectName("export_as_web_page"); a->setToolTip(i18n("Export the report as a web page (in HTML format)")); a->setWhatsThis(i18n("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() { kDebug(); delete m_preRenderer; delete m_kexi; delete m_functions; } 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_preRenderer->document()); } delete dialog; delete renderer; } void KexiReportView::slotExportAsPdf() { QScopedPointer renderer(m_factory.createInstance("print")); if (renderer) { KoReportRendererContext cxt; cxt.destinationUrl = getExportUrl(QLatin1String("application/pdf"), i18n("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_preRenderer->document())) { KMessageBox::error(this, i18n("Exporting the report as PDF to %1 failed.", cxt.destinationUrl.prettyUrl()), i18n("Export Failed")); } else { openExportedDocument(cxt.destinationUrl); } } } KUrl KexiReportView::getExportUrl(const QString &mimetype, const QString &caption, const QString &lastExportPath, const QString &extension) { KUrl 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 while (true) { result = KFileDialog::getSaveUrl(KUrl(defaultSavePath), mimetype, this, caption); // not cancelled? if (result.isValid()) { if (KIO::NetAccess::exists(result, KIO::NetAccess::DestinationSide, this)) { const int answer = KMessageBox::warningContinueCancel(this, i18n("The file %1 exists.\nDo you want to overwrite it?", result.path()), caption, KGuiItem(i18n("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 KUrl& destination) { const int answer = KMessageBox::questionYesNo( this, i18n("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"), i18n("Export Report as Spreadsheet"), "kfiledialog:///LastVisitedODSExportPath/", "ods"); if (!cxt.destinationUrl.isValid()) { return; } if (!renderer->render(cxt, m_preRenderer->document())) { KMessageBox::error(this, i18n("Failed to export the report as spreadsheet to %1.", cxt.destinationUrl.prettyUrl()), i18n("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"), i18n("Export Report as Text Document"), "kfiledialog:///LastVisitedODTExportPath/", "odt"); if (!cxt.destinationUrl.isValid()) { return; } if (!renderer->render(cxt, m_preRenderer->document())) { KMessageBox::error(this, i18n("Exporting the report as text document to %1 failed.", cxt.destinationUrl.prettyUrl()), i18n("Export Failed")); } else { openExportedDocument(cxt.destinationUrl); } } } void KexiReportView::slotExportAsWebPage() { KoReportRendererContext cxt; KoReportRendererBase *renderer; const QString dialogTitle = i18n("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, i18n("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(i18n("Use CSS")), KGuiItem(i18n("Use Table"))); if (answer == KMessageBox::Yes) { renderer = m_factory.createInstance("htmlcss"); } else { renderer = m_factory.createInstance("htmltable"); } if (!renderer->render(cxt, m_preRenderer->document())) { KMessageBox::error(this, i18n("Exporting the report as web page to %1 failed.", cxt.destinationUrl.prettyUrl()), i18n("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); if (tempData()->reportSchemaChangedInPreviousView) { tempData()->reportSchemaChangedInPreviousView = false; kDebug() << "Schema changed"; delete m_preRenderer; //kDebug() << tempData()->reportDefinition.tagName(); m_preRenderer = new KoReportPreRenderer(tempData()->reportDefinition); if (m_preRenderer->isValid()) { KoReportData *reportData = 0; if (!tempData()->connectionDefinition.isNull()) { - reportData = sourceData(tempData()->connectionDefinition); + reportData = createSourceData(tempData()->connectionDefinition); } if (!reportData) { reportData = new KexiDBReportData(QString(), QString(), KexiMainWindowIface::global()->project()->dbConnection(), this); } m_preRenderer->setSourceData(reportData); m_currentPage = 1; //Add a kexi object to provide kexidb and extra functionality 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 m_functions; // prev functions m_functions = new KRScriptFunctions(reportData, KexiMainWindowIface::global()->project()->dbConnection()); m_preRenderer->registerScriptObject(m_functions, "field"); } if (!m_preRenderer->generateDocument()) { return false; } m_pageCount = m_preRenderer->document()->pages(); #ifndef KEXI_MOBILE m_pageSelector->setRecordCount(m_pageCount); m_pageSelector->setCurrentRecordNumber(1); #endif m_reportPage = new KoReportPage(this, m_preRenderer->document()); m_reportPage->setObjectName("KexiReportPage"); m_reportScene->setSceneRect(0,0,m_reportPage->rect().width() + 40, m_reportPage->rect().height() + 40); m_reportScene->addItem(m_reportPage); m_reportPage->setPos(20,20); m_reportView->centerOn(0,0); } else { KMessageBox::error(this, i18n("Report schema appears to be invalid or corrupt"), i18n("Opening failed")); } } return true; } -KoReportData* KexiReportView::sourceData(const QDomElement &e) +KoReportData* KexiReportView::createSourceData(const QDomElement &e) { KoReportData *kodata = 0; if (e.attribute("type") == "internal") { kodata = new KexiDBReportData(e.attribute("source"), e.attribute("source-class"), KexiMainWindowIface::global()->project()->dbConnection(), this); } #ifndef KEXI_MOBILE if (e.attribute("type") == "external") { kodata = new KexiMigrateReportData(e.attribute("source")); } #endif return kodata; } KexiReportPart::TempData* KexiReportView::tempData() const { return static_cast(window()->data()); } void KexiReportView::addNewRecordRequested() { } void KexiReportView::moveToFirstRecordRequested() { if (m_currentPage != 1) { m_currentPage = 1; m_reportPage->renderPage(m_currentPage); #ifndef KEXI_MOBILE m_pageSelector->setCurrentRecordNumber(m_currentPage); #endif } } void KexiReportView::moveToLastRecordRequested() { if (m_currentPage != m_pageCount) { m_currentPage = m_pageCount; m_reportPage->renderPage(m_currentPage); #ifndef KEXI_MOBILE m_pageSelector->setCurrentRecordNumber(m_currentPage); #endif } } void KexiReportView::moveToNextRecordRequested() { if (m_currentPage < m_pageCount) { m_currentPage++; m_reportPage->renderPage(m_currentPage); #ifndef KEXI_MOBILE m_pageSelector->setCurrentRecordNumber(m_currentPage); #endif } } void KexiReportView::moveToPreviousRecordRequested() { if (m_currentPage > 1) { m_currentPage--; m_reportPage->renderPage(m_currentPage); #ifndef KEXI_MOBILE m_pageSelector->setCurrentRecordNumber(m_currentPage); #endif } } void KexiReportView::moveToRecordRequested(uint r) { Q_UNUSED(r); } int KexiReportView::currentRecord() const { return m_currentPage; } int KexiReportView::recordCount() const { return m_pageCount; } diff --git a/kexi/plugins/reports/kexireportview.h b/kexi/plugins/reports/kexireportview.h index 8389e9c9827..ee1c0f4eb96 100644 --- a/kexi/plugins/reports/kexireportview.h +++ b/kexi/plugins/reports/kexireportview.h @@ -1,93 +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 "kexireportpart.h" #include #include class KoReportPreRenderer; class ORODocument; class KoReportPage; class KexiScriptAdaptor; class KRScriptFunctions; #ifndef KEXI_MOBILE class KexiRecordNavigator; #endif #include /** @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(uint r); virtual int currentRecord() const; virtual int recordCount() const; private: KoReportPreRenderer *m_preRenderer; QGraphicsView *m_reportView; QGraphicsScene *m_reportScene; KoReportPage *m_reportPage; #ifndef KEXI_MOBILE KexiRecordNavigator *m_pageSelector; #endif int m_currentPage; int m_pageCount; KexiReportPart::TempData* tempData() const; - KoReportData* sourceData(const QDomElement &e); + KoReportData* createSourceData(const QDomElement &e); KexiScriptAdaptor *m_kexi; KRScriptFunctions *m_functions; KoReportRendererFactory m_factory; KUrl getExportUrl(const QString &mimetype, const QString &caption, const QString &lastExportPath, const QString &extension); private Q_SLOTS: void slotPrintReport(); void slotExportAsPdf(); void slotExportAsSpreadsheet(); void slotExportAsWebPage(); void slotExportAsTextDocument(); void openExportedDocument(const KUrl& destination); }; #endif diff --git a/kexi/plugins/reports/kexisourceselector.cpp b/kexi/plugins/reports/kexisourceselector.cpp index 18af85565ba..9f588007121 100644 --- a/kexi/plugins/reports/kexisourceselector.cpp +++ b/kexi/plugins/reports/kexisourceselector.cpp @@ -1,222 +1,185 @@ /* * Kexi Report Plugin * Copyright (C) 2007-2009 by Adam Pigg (adam@piggz.co.uk) +* Copyright (C) 2016 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 "kexisourceselector.h" #include "kexireportview.h" #include #include "KexiDataSourceComboBox.h" #include #include #include #include #include #include #include #include //#define NO_EXTERNAL_SOURCES #ifdef NO_EXTERNAL_SOURCES #ifdef __GNUC__ #warning enable external data sources for 2.3 #else #pragma WARNING( enable external data sources for 2.3 ) #endif #endif class KexiSourceSelector::Private { public: Private() - : kexiDBData(0) { } ~Private() { - delete kexiDBData; -#ifndef KEXI_MOBILE - delete kexiMigrateData; -#endif } KexiDB::Connection *conn; QVBoxLayout *layout; QComboBox *sourceType; KexiDataSourceComboBox *internalSource; KLineEdit *externalSource; KPushButton *setData; - - KexiDBReportData *kexiDBData; - -#ifndef KEXI_MOBILE - KexiMigrateReportData *kexiMigrateData; -#endif - }; KexiSourceSelector::KexiSourceSelector(KexiProject* project, QWidget* parent) : QWidget(parent) , d(new Private) { d->conn = project->dbConnection(); - d->kexiDBData = 0; - -#ifndef KEXI_MOBILE - d->kexiMigrateData = 0; -#endif - d->layout = new QVBoxLayout(this); d->sourceType = new QComboBox(this); d->internalSource = new KexiDataSourceComboBox(this); d->internalSource->setProject(project); d->externalSource = new KLineEdit(this); d->setData = new KPushButton(i18n("Set Data")); - connect(d->setData, SIGNAL(clicked()), this, SLOT(setDataClicked())); + connect(d->setData, SIGNAL(clicked()), this, SIGNAL(sourceDataChanged())); d->sourceType->addItem(i18n("Internal"), QVariant("internal")); d->sourceType->addItem(i18n("External"), QVariant("external")); #ifndef NO_EXTERNAL_SOURCES //!@TODO enable when adding external data d->layout->addWidget(new QLabel(i18n("Source Type:"), this)); d->layout->addWidget(d->sourceType); d->layout->addSpacing(10); #else d->sourceType->setVisible(false); d->externalSource->setVisible(false); #endif d->layout->addWidget(new QLabel(i18n("Internal Source:"), this)); d->layout->addWidget(d->internalSource); d->layout->addSpacing(10); #ifndef NO_EXTERNAL_SOURCES d->layout->addWidget(new QLabel(i18n("External Source:"), this)); d->layout->addWidget(d->externalSource); #endif d->layout->addSpacing(20); d->layout->addWidget(d->setData); d->layout->addStretch(); setLayout(d->layout); } KexiSourceSelector::~KexiSourceSelector() { delete d; } void KexiSourceSelector::setConnectionData(const QDomElement &c) { if (c.attribute("type") == "internal") { d->sourceType->setCurrentIndex(d->sourceType->findData("internal")); d->internalSource->setDataSource( c.attribute("source-class"), c.attribute("source")); } if (c.attribute("type") == "external") { d->sourceType->setCurrentIndex(d->sourceType->findText("external")); d->externalSource->setText(c.attribute("source")); } - emit setData(sourceData()); + emit sourceDataChanged(); } QDomElement KexiSourceSelector::connectionData() { kDebug(); QDomDocument dd; QDomElement conndata = dd.createElement("connection"); #ifndef NO_EXTERNAL_SOURCES //!@TODO Make a better gui for selecting external data source conndata.setAttribute("type", d->sourceType->itemData(d->sourceType->currentIndex()).toString()); if (d->sourceType->itemData(d->sourceType->currentIndex()).toString() == "internal") { conndata.setAttribute("source", d->internalSource->currentText()); const QString sourceClass(d->internalSource->selectedPartClass()); if (!sourceClass.isEmpty()) { conndata.setAttribute("source-class", sourceClass); } } else { conndata.setAttribute("source", d->externalSource->text()); } #else conndata.setAttribute("type", "internal"); conndata.setAttribute("source", d->internalSource->currentText()); #endif return conndata; } -KoReportData* KexiSourceSelector::sourceData() +KoReportData* KexiSourceSelector::createSourceData() const { - if (d->kexiDBData) { - delete d->kexiDBData; - d->kexiDBData = 0; - } - -#ifndef KEXI_MOBILE - if (d->kexiMigrateData) { - delete d->kexiMigrateData; - d->kexiMigrateData = 0; - } -#endif - //!@TODO Fix when enable external data #ifndef NO_EXTERNAL_SOURCES KexiReportView *view = 0; if (KexiMainWindowIface::global()->currentWindow()) { view = qobject_cast(KexiMainWindowIface::global()->currentWindow()->selectedView()); if (!view) { return 0; } } if (d->sourceType->itemData(d->sourceType->currentIndex()).toString() == "internal" && d->internalSource->isSelectionValid()) { - d->kexiDBData = new KexiDBReportData(d->internalSource->selectedName(), + return new KexiDBReportData(d->internalSource->selectedName(), d->internalSource->selectedPartClass(), d->conn, view); - return d->kexiDBData; } #ifndef KEXI_MOBILE if (d->sourceType->itemData(d->sourceType->currentIndex()).toString() == "external") { - d->kexiMigrateData = new KexiMigrateReportData(d->externalSource->text()); - return d->kexiMigrateData; + return new KexiMigrateReportData(d->externalSource->text()); } #endif #else if (d->internalSource->isSelectionValid()) { - d->kexiDBData = new KexiDBReportData(d->internalSource->selectedName(), d->conn); - return d->kexiDBData; + return new KexiDBReportData(d->internalSource->selectedName(), d->conn); } #endif return 0; } - -void KexiSourceSelector::setDataClicked() -{ - emit(setData(sourceData())); -} diff --git a/kexi/plugins/reports/kexisourceselector.h b/kexi/plugins/reports/kexisourceselector.h index 03f5589fcdd..0ebd1ee8b80 100644 --- a/kexi/plugins/reports/kexisourceselector.h +++ b/kexi/plugins/reports/kexisourceselector.h @@ -1,57 +1,55 @@ /* * Kexi Report Plugin * Copyright (C) 2007-2009 by Adam Pigg (adam@piggz.co.uk) +* Copyright (C) 2016 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 . */ #ifndef KEXISOURCESELECTOR_H #define KEXISOURCESELECTOR_H #include #include #include #include #include #include "kexidbreportdata.h" #include "keximigratereportdata.h" class KexiProject; //! @todo rename to KexiReportDataSourcePage //! @todo use KexiPropertyPaneViewBase class KexiSourceSelector : public QWidget { Q_OBJECT public: explicit KexiSourceSelector(KexiProject* project, QWidget* parent = 0); ~KexiSourceSelector(); - KoReportData* sourceData(); + KoReportData* createSourceData() const Q_REQUIRED_RESULT; void setConnectionData(const QDomElement &c); QDomElement connectionData(); Q_SIGNALS: - void setData(KoReportData*); - -private Q_SLOTS: - void setDataClicked(); + void sourceDataChanged(); private: class Private; Private * const d; }; #endif // KEXISOURCESELECTOR_H diff --git a/libs/koreport/renderer/KoReportPreRenderer.cpp b/libs/koreport/renderer/KoReportPreRenderer.cpp index 283d8f1a1df..7f76cbbc028 100644 --- a/libs/koreport/renderer/KoReportPreRenderer.cpp +++ b/libs/koreport/renderer/KoReportPreRenderer.cpp @@ -1,711 +1,715 @@ /* * OpenRPT report writer and rendering engine * Copyright (C) 2001-2007 by OpenMFG, LLC (info@openmfg.com) * 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 . */ #include "KoReportPreRenderer.h" #include "renderobjects.h" #include "KoReportData.h" #include #include #include #include #include #include #include "scripting/krscripthandler.h" #include #include #include "KoReportASyncItemManager.h" // // KoReportPreRendererPrivate // This class is the private class that houses all the internal // variables so we can provide a cleaner interface to the user // without presenting to them things that they don't need to see // and may change over time. // class KoReportPreRendererPrivate : public QObject { Q_OBJECT public: KoReportPreRendererPrivate(); virtual ~KoReportPreRendererPrivate(); bool m_valid; ORODocument* m_document; OROPage* m_page; KoReportReportData* m_reportData; qreal m_yOffset; // how far down the current page are we qreal m_topMargin; // value stored in the correct units qreal m_bottomMargin; // -- same as above -- qreal m_leftMargin; // -- same as above -- qreal m_rightMargin; // -- same as above -- qreal m_maxHeight; // -- same as above -- qreal m_maxWidth; // -- same as above -- int m_pageCounter; // what page are we currently on? int m_recordCount; KoReportData* m_kodata; QList m_postProcText; void createNewPage(); qreal finishCurPage(bool = false); qreal finishCurPageSize(bool = false); void renderDetailSection(KRDetailSectionData &); qreal renderSection(const KRSectionData &); qreal renderSectionSize(const KRSectionData &); ///Scripting Stuff KRScriptHandler *m_scriptHandler; void initEngine(); //! Generates m_document. Returns true on success. //! @note m_document is not removed on failure, caller should remove it. bool generateDocument(); KoReportASyncItemManager* asyncManager; QMap scriptObjects; private slots: void asyncItemsFinished(); signals: void enteredGroup(const QString&, const QVariant&); void exitedGroup(const QString&, const QVariant&); void renderingSection(KRSectionData*, OROPage*, QPointF); }; KoReportPreRendererPrivate::KoReportPreRendererPrivate() { m_valid = false; m_reportData = 0; m_document = 0; m_page = 0; m_yOffset = 0.0; m_topMargin = m_bottomMargin = 0.0; m_leftMargin = m_rightMargin = 0.0; m_pageCounter = 0; m_maxHeight = m_maxWidth = 0.0; m_kodata = 0; asyncManager = new KoReportASyncItemManager(this); connect(asyncManager, SIGNAL(finished()), this, SLOT(asyncItemsFinished())); } KoReportPreRendererPrivate::~KoReportPreRendererPrivate() { delete m_reportData; m_reportData = 0; m_postProcText.clear(); delete m_document; + delete m_kodata; } void KoReportPreRendererPrivate::createNewPage() { //kDebug(); if (m_pageCounter > 0) finishCurPage(); m_pageCounter++; //Update the page count script value m_scriptHandler->setPageNumber(m_pageCounter); m_scriptHandler->newPage(); m_page = new OROPage(0); m_document->addPage(m_page); //TODO calculate past page bool lastPage = false; m_yOffset = m_topMargin; if (m_pageCounter == 1 && m_reportData->m_pageHeaderFirst) renderSection(*(m_reportData->m_pageHeaderFirst)); else if (lastPage == true && m_reportData->m_pageHeaderLast) renderSection(*(m_reportData->m_pageHeaderLast)); else if ((m_pageCounter % 2) == 1 && m_reportData->m_pageHeaderOdd) renderSection(*(m_reportData->m_pageHeaderOdd)); else if ((m_pageCounter % 2) == 0 && m_reportData->m_pageHeaderAny) renderSection(*(m_reportData->m_pageHeaderAny)); else if (m_reportData->m_pageHeaderAny) renderSection(*(m_reportData->m_pageHeaderAny)); } qreal KoReportPreRendererPrivate::finishCurPageSize(bool lastPage) { qreal retval = 0.0; if (lastPage && m_reportData->m_pageFooterLast) retval = renderSectionSize(* (m_reportData->m_pageFooterLast)); else if (m_pageCounter == 1 && m_reportData->m_pageFooterFirst) retval = renderSectionSize(* (m_reportData->m_pageFooterFirst)); else if ((m_pageCounter % 2) == 1 && m_reportData->m_pageFooterOdd) retval = renderSectionSize(* (m_reportData->m_pageFooterOdd)); else if ((m_pageCounter % 2) == 0 && m_reportData->m_pageFooterEven) retval = renderSectionSize(* (m_reportData->m_pageFooterEven)); else if (m_reportData->m_pageFooterAny) retval = renderSectionSize(* (m_reportData->m_pageFooterAny)); //kDebug() << retval; return retval; } qreal KoReportPreRendererPrivate::finishCurPage(bool lastPage) { qreal offset = m_maxHeight - m_bottomMargin; qreal retval = 0.0; //kDebug() << offset; if (lastPage && m_reportData->m_pageFooterLast) { //kDebug() << "Last Footer"; m_yOffset = offset - renderSectionSize(* (m_reportData->m_pageFooterLast)); retval = renderSection(* (m_reportData->m_pageFooterLast)); } else if (m_pageCounter == 1 && m_reportData->m_pageFooterFirst) { //kDebug() << "First Footer"; m_yOffset = offset - renderSectionSize(* (m_reportData->m_pageFooterFirst)); retval = renderSection(* (m_reportData->m_pageFooterFirst)); } else if ((m_pageCounter % 2) == 1 && m_reportData->m_pageFooterOdd) { //kDebug() << "Odd Footer"; m_yOffset = offset - renderSectionSize(* (m_reportData->m_pageFooterOdd)); retval = renderSection(* (m_reportData->m_pageFooterOdd)); } else if ((m_pageCounter % 2) == 0 && m_reportData->m_pageFooterEven) { //kDebug() << "Even Footer"; m_yOffset = offset - renderSectionSize(* (m_reportData->m_pageFooterEven)); retval = renderSection(* (m_reportData->m_pageFooterEven)); } else if (m_reportData->m_pageFooterAny) { //kDebug() << "Any Footer"; m_yOffset = offset - renderSectionSize(* (m_reportData->m_pageFooterAny)); retval = renderSection(* (m_reportData->m_pageFooterAny)); } return retval; } void KoReportPreRendererPrivate::renderDetailSection(KRDetailSectionData & detailData) { if (detailData.m_detailSection) { if (m_kodata/* && !curs->eof()*/) { QStringList keys; QStringList keyValues; QList shownGroups; ORDetailGroupSectionData * grp = 0; bool status = m_kodata->moveFirst(); m_recordCount = m_kodata->recordCount(); //kDebug() << "Record Count:" << m_recordCount; for (int i = 0; i < (int) detailData.m_groupList.count(); ++i) { grp = detailData.m_groupList[i]; //If the group has a header or footer, then emit a change of group value if(grp->m_groupFooter || grp->m_groupHeader) { // we get here only if group is *shown* shownGroups << i; keys.append(grp->m_column); if (!keys.last().isEmpty()) keyValues.append(m_kodata->value(m_kodata->fieldNumber(keys.last())).toString()); else keyValues.append(QString()); //Tell interested parties we're about to render a header emit(enteredGroup(keys.last(), keyValues.last())); } if (grp->m_groupHeader) renderSection(*(grp->m_groupHeader)); } while (status) { long l = m_kodata->at(); //kDebug() << "At:" << l << "Y:" << m_yOffset << "Max Height:" << m_maxHeight; if (renderSectionSize(*(detailData.m_detailSection)) + finishCurPageSize((l + 1 == m_recordCount)) + m_bottomMargin + m_yOffset >= m_maxHeight) { //kDebug() << "Next section is too big for this page"; if (l > 0) { m_kodata->movePrevious(); createNewPage(); m_kodata->moveNext(); } } renderSection(*(detailData.m_detailSection)); if (m_kodata) status = m_kodata->moveNext(); if (status == true && keys.count() > 0) { // check to see where it is we need to start int pos = -1; // if it's still -1 by the time we are done then no keyValues changed for (int i = 0; i < keys.count(); ++i) { if (keyValues[i] != m_kodata->value(m_kodata->fieldNumber(keys[i])).toString()) { pos = i; break; } } // don't bother if nothing has changed if (pos != -1) { // roll back the query and go ahead if all is good status = m_kodata->movePrevious(); if (status == true) { // print the footers as needed // any changes made in this for loop need to be duplicated // below where the footers are finished. bool do_break = false; for (int i = shownGroups.count() - 1; i >= 0; i--) { if (do_break) createNewPage(); do_break = false; grp = detailData.m_groupList[shownGroups.at(i)]; if (grp->m_groupFooter) { if (renderSectionSize(*(grp->m_groupFooter)) + finishCurPageSize() + m_bottomMargin + m_yOffset >= m_maxHeight) createNewPage(); renderSection(*(grp->m_groupFooter)); } if (ORDetailGroupSectionData::BreakAfterGroupFooter == grp->m_pagebreak) do_break = true; } // step ahead to where we should be and print the needed headers // if all is good status = m_kodata->moveNext(); if (do_break) createNewPage(); if (status == true) { for (int i = 0; i < shownGroups.count(); ++i) { grp = detailData.m_groupList[shownGroups.at(i)]; if (grp->m_groupHeader) { if (renderSectionSize(*(grp->m_groupHeader)) + finishCurPageSize() + m_bottomMargin + m_yOffset >= m_maxHeight) { m_kodata->movePrevious(); createNewPage(); m_kodata->moveNext(); } if (!keys[i].isEmpty()) keyValues[i] = m_kodata->value(m_kodata->fieldNumber(keys[i])).toString(); //Tell interested parties thak key values changed renderSection(*(grp->m_groupHeader)); } } } } } } } if (keys.size() > 0 && m_kodata->movePrevious()) { // finish footers // duplicated changes from above here for (int i = shownGroups.count() - 1; i >= 0; i--) { grp = detailData.m_groupList[shownGroups.at(i)]; if (grp->m_groupFooter) { if (renderSectionSize(*(grp->m_groupFooter)) + finishCurPageSize() + m_bottomMargin + m_yOffset >= m_maxHeight) createNewPage(); renderSection(*(grp->m_groupFooter)); emit(exitedGroup(keys[i], keyValues[i])); } } } } if (KRDetailSectionData::BreakAtEnd == detailData.m_pageBreak) createNewPage(); } } qreal KoReportPreRendererPrivate::renderSectionSize(const KRSectionData & sectionData) { qreal intHeight = POINT_TO_INCH(sectionData.height()) * KoDpi::dpiY(); int itemHeight = 0; if (sectionData.objects().count() == 0) return intHeight; QList objects = sectionData.objects(); foreach(KoReportItemBase *ob, objects) { QPointF offset(m_leftMargin, m_yOffset); QVariant itemData = m_kodata->value(ob->itemDataSource()); //ASync objects cannot alter the section height KoReportASyncItemBase *async_ob = qobject_cast(ob); if (!async_ob) { itemHeight = ob->renderSimpleData(0, 0, offset, itemData, m_scriptHandler); if (itemHeight > intHeight) { intHeight = itemHeight; } } } return intHeight; } qreal KoReportPreRendererPrivate::renderSection(const KRSectionData & sectionData) { qreal sectionHeight = POINT_TO_INCH(sectionData.height()) * KoDpi::dpiY(); int itemHeight = 0; //kDebug() << "Name: " << sectionData.name() << " Height: " << sectionHeight // << "Objects: " << sectionData.objects().count(); emit(renderingSection(const_cast(§ionData), m_page, QPointF(m_leftMargin, m_yOffset))); //Create a pre-rendered section for this section and add it to the document OROSection *sec = new OROSection(m_document); sec->setHeight(sectionData.height()); sec->setBackgroundColor(sectionData.backgroundColor()); sec->setType(sectionData.type()); m_document->addSection(sec); //Render section background ORORect* bg = new ORORect(); bg->setPen(QPen(Qt::NoPen)); bg->setBrush(sectionData.backgroundColor()); qreal w = m_page->document()->pageOptions().widthPx() - m_page->document()->pageOptions().getMarginRight() - m_leftMargin; bg->setRect(QRectF(m_leftMargin, m_yOffset, w, sectionHeight)); m_page->addPrimitive(bg, true); QList objects = sectionData.objects(); foreach(KoReportItemBase *ob, objects) { QPointF offset(m_leftMargin, m_yOffset); QVariant itemData = m_kodata->value(ob->itemDataSource()); if (ob->supportsSubQuery()) { itemHeight = ob->renderReportData(m_page, sec, offset, m_kodata, m_scriptHandler); } else { KoReportASyncItemBase *async_ob = qobject_cast(ob); if (async_ob){ //kDebug() << "async object"; asyncManager->addItem(async_ob, m_page, sec, offset, async_ob->realItemData(itemData), m_scriptHandler); } else { //kDebug() << "sync object"; itemHeight = ob->renderSimpleData(m_page, sec, offset, itemData, m_scriptHandler); } } if (itemHeight > sectionHeight) { sectionHeight = itemHeight; } } for (int i = 0; i < m_page->primitives(); ++i) { OROPrimitive *prim = m_page->primitive(i); if (prim->type() == OROTextBox::TextBox) { OROTextBox *text = static_cast(prim); if (text->requiresPostProcessing()) { m_postProcText.append(text); } } } m_yOffset += sectionHeight; return sectionHeight; } void KoReportPreRendererPrivate::initEngine() { m_scriptHandler = new KRScriptHandler(m_kodata, m_reportData); connect(this, SIGNAL(enteredGroup(QString,QVariant)), m_scriptHandler, SLOT(slotEnteredGroup(QString,QVariant))); connect(this, SIGNAL(exitedGroup(QString,QVariant)), m_scriptHandler, SLOT(slotExitedGroup(QString,QVariant))); connect(this, SIGNAL(renderingSection(KRSectionData*,OROPage*,QPointF)), m_scriptHandler, SLOT(slotEnteredSection(KRSectionData*,OROPage*,QPointF))); } void KoReportPreRendererPrivate::asyncItemsFinished() { //kDebug() << "Finished rendering async items"; delete asyncManager; } bool KoReportPreRendererPrivate::generateDocument() { if (!m_valid || !m_reportData || !m_kodata) { return false; } // Do this check now so we don't have to undo a lot of work later if it fails LabelSizeInfo label; if (m_reportData->page.getPageSize() == "Labels") { label = LabelSizeInfo::find(m_reportData->page.getLabelType()); if (label.isNull()) { return false; } } m_document = new ORODocument(m_reportData->m_title); m_pageCounter = 0; m_yOffset = 0.0; //kDebug() << "Calculating Margins"; if (!label.isNull()) { if (m_reportData->page.isPortrait()) { m_topMargin = (label.startY() / 100.0); m_bottomMargin = 0; m_rightMargin = 0; m_leftMargin = (label.startX() / 100.0); } else { m_topMargin = (label.startX() / 100.0); m_bottomMargin = 0; m_rightMargin = 0; m_leftMargin = (label.startY() / 100.0); } } else { m_topMargin = m_reportData->page.getMarginTop(); m_bottomMargin = m_reportData->page.getMarginBottom(); m_rightMargin = m_reportData->page.getMarginRight(); m_leftMargin = m_reportData->page.getMarginLeft(); //kDebug() << "Margins:" << m_topMargin << m_bottomMargin << m_rightMargin << m_leftMargin; } //kDebug() << "Calculating Page Size"; ReportPageOptions rpo(m_reportData->page); // This should reflect the information of the report page size if (m_reportData->page.getPageSize() == "Custom") { m_maxWidth = m_reportData->page.getCustomWidth(); m_maxHeight = m_reportData->page.getCustomHeight(); } else { if (!label.isNull()) { m_maxWidth = label.width(); m_maxHeight = label.height(); rpo.setPageSize(label.paper()); } else { // lookup the correct size information for the specified size paper m_maxWidth = KoPageFormat::width(KoPageFormat::formatFromString(m_reportData->page.getPageSize()), KoPageFormat::Portrait); m_maxHeight = KoPageFormat::height(KoPageFormat::formatFromString(m_reportData->page.getPageSize()), KoPageFormat::Portrait); KoUnit pageUnit(KoUnit::Millimeter); m_maxWidth = KoUnit::toInch(pageUnit.fromUserValue(m_maxWidth)) * KoDpi::dpiX(); m_maxHeight = KoUnit::toInch(pageUnit.fromUserValue(m_maxHeight)) * KoDpi::dpiY(); } } if (!m_reportData->page.isPortrait()) { qreal tmp = m_maxWidth; m_maxWidth = m_maxHeight; m_maxHeight = tmp; } //kDebug() << "Page Size:" << m_maxWidth << m_maxHeight; m_document->setPageOptions(rpo); m_kodata->setSorting(m_reportData->m_detailSection->m_sortedFields); if (!m_kodata->open()) { return false; } initEngine(); //Loop through all abjects that have been registered, and register them with the script handler if (m_scriptHandler) { QMapIterator i(scriptObjects); while (i.hasNext()) { i.next(); m_scriptHandler->registerScriptObject(i.value(), i.key()); //!TODO This is a hack if (i.key() == "field") { QObject::connect(m_scriptHandler, SIGNAL(groupChanged(QString)), i.value(), SLOT(setWhere(QString))); } } } //execute the script m_scriptHandler->trigger(); createNewPage(); if (!label.isNull()) { // Label Print Run // remember the initial margin setting as we will be modifying // the value and restoring it as we move around qreal margin = m_leftMargin; m_yOffset = m_topMargin; qreal w = (label.width() / 100.0); qreal wg = (label.xGap() / 100.0); qreal h = (label.height() / 100.0); qreal hg = (label.yGap() / 100.0); int numCols = label.columns(); int numRows = label.rows(); qreal tmp; // flip the value around if we are printing landscape if (!m_reportData->page.isPortrait()) { w = (label.height() / 100.0); wg = (label.yGap() / 100.0); h = (label.width() / 100.0); hg = (label.xGap() / 100.0); numCols = label.rows(); numRows = label.columns(); } KRDetailSectionData * detailData = m_reportData->m_detailSection; if (detailData->m_detailSection) { KoReportData *mydata = m_kodata; if (mydata && mydata->recordCount() > 0) { /* && !((query = orqThis->getQuery())->eof()))*/ if (!mydata->moveFirst()) { return false; } int row = 0; int col = 0; do { tmp = m_yOffset; // store the value as renderSection changes it renderSection(*detailData->m_detailSection); m_yOffset = tmp; // restore the value that renderSection modified col++; m_leftMargin += w + wg; if (col >= numCols) { m_leftMargin = margin; // reset back to original value col = 0; row++; m_yOffset += h + hg; if (row >= numRows) { m_yOffset = m_topMargin; row = 0; createNewPage(); } } } while (mydata->moveNext()); } } } else { // Normal Print Run if (m_reportData->m_reportHeader) { renderSection(*m_reportData->m_reportHeader); } if (m_reportData->m_detailSection) { renderDetailSection(*m_reportData->m_detailSection); } if (m_reportData->m_reportFooter) { if (renderSectionSize(*m_reportData->m_reportFooter) + finishCurPageSize(true) + m_bottomMargin + m_yOffset >= m_maxHeight) { createNewPage(); } renderSection(*m_reportData->m_reportFooter); } } finishCurPage(true); // _postProcText contains those text boxes that need to be updated // with information that wasn't available at the time it was added to the document m_scriptHandler->setPageTotal(m_document->pages()); for (int i = 0; i < m_postProcText.size(); i++) { OROTextBox * tb = m_postProcText.at(i); m_scriptHandler->setPageNumber(tb->page()->page() + 1); tb->setText(m_scriptHandler->evaluate(tb->text()).toString()); } asyncManager->startRendering(); m_scriptHandler->displayErrors(); if (!m_kodata->close()) { return false; } delete m_scriptHandler; + m_scriptHandler = 0; delete m_kodata; + m_kodata = 0; m_postProcText.clear(); return true; } //===========================KoReportPreRenderer=============================== KoReportPreRenderer::KoReportPreRenderer(const QDomElement & pDocument) : d(new KoReportPreRendererPrivate()) { setDom(pDocument); } KoReportPreRenderer::~KoReportPreRenderer() { delete d; } ORODocument* KoReportPreRenderer::document() { return d->m_document; } bool KoReportPreRenderer::generateDocument() { delete d->m_document; if (!d->generateDocument()) { delete d->m_document; d->m_document = 0; } return d->m_document; } void KoReportPreRenderer::setSourceData(KoReportData *data) { - if (d && data) { + if (d && d->m_kodata != data) { + delete d->m_kodata; d->m_kodata = data; } } bool KoReportPreRenderer::setDom(const QDomElement &docReport) { if (d) { delete d->m_reportData; d->m_valid = false; if (docReport.tagName() != "report:content") { kWarning() << "report schema is invalid"; return false; } d->m_reportData = new KoReportReportData(docReport, this); d->m_valid = d->m_reportData->isValid(); } return isValid(); } bool KoReportPreRenderer::isValid() const { if (d && d->m_valid) return true; return false; } void KoReportPreRenderer::registerScriptObject(QObject* obj, const QString& name) { //kDebug() << name; d->scriptObjects[name] = obj; } const KoReportReportData* KoReportPreRenderer::reportData() const { return d->m_reportData; } #include "KoReportPreRenderer.moc" diff --git a/libs/koreport/renderer/KoReportPreRenderer.h b/libs/koreport/renderer/KoReportPreRenderer.h index c2cd873f9d1..aba193925cb 100644 --- a/libs/koreport/renderer/KoReportPreRenderer.h +++ b/libs/koreport/renderer/KoReportPreRenderer.h @@ -1,65 +1,66 @@ /* * OpenRPT report writer and rendering engine * Copyright (C) 2001-2007 by OpenMFG, LLC (info@openmfg.com) * 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 __KOREPORTPRERENDERER_H__ #define __KOREPORTPRERENDERER_H__ #include #include #include #include #include #include "koreport_export.h" #include "scripting/krscripthandler.h" class KoReportPreRendererPrivate; class ParameterList; class ORODocument; class KoReportData; // // ORPreRender // This class takes a report definition and prerenders the result to // an ORODocument that can be used to pass to any number of renderers. // class KOREPORT_EXPORT KoReportPreRenderer : public QObject { public: explicit KoReportPreRenderer(const QDomElement&); virtual ~KoReportPreRenderer(); - void setSourceData(KoReportData*); + //! Sets source data to @a data, takes ownership + void setSourceData(KoReportData *data); void registerScriptObject(QObject*, const QString&); bool generateDocument(); ORODocument *document(); bool isValid() const; const KoReportReportData *reportData() const; protected: private: KoReportPreRendererPrivate *const d; bool setDom(const QDomElement &); }; #endif // __KOREPORTPRERENDERER_H__ diff --git a/libs/koreport/wrtembed/KoReportDesigner.cpp b/libs/koreport/wrtembed/KoReportDesigner.cpp index c7a87b7527b..76074f4c0f5 100644 --- a/libs/koreport/wrtembed/KoReportDesigner.cpp +++ b/libs/koreport/wrtembed/KoReportDesigner.cpp @@ -1,1343 +1,1348 @@ /* * OpenRPT report writer and rendering engine * Copyright (C) 2001-2007 by OpenMFG, LLC * Copyright (C) 2007-2010 by Adam Pigg * Copyright (C) 2011 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 "KoReportDesigner.h" #include "reportsection.h" #include "reportscene.h" #include "reportsceneview.h" #include "reportsectiondetailgroup.h" #include "reportpropertiesbutton.h" #include "sectioneditor.h" #include "reportsectiondetail.h" #include "krutils.h" #include "KoReportPluginInterface.h" #include "KoReportDesignerItemLine.h" #include "KoReportPluginManager.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //! Also add public method for runtime? const char ns[] = "http://kexi-project.org/report/2.0"; static QDomElement propertyToElement(QDomDocument* d, KoProperty::Property* p) { QDomElement e = d->createElement("report:" + p->name().toLower()); e.appendChild(d->createTextNode(p->value().toString())); return e; } // // define and implement the ReportWriterSectionData class // a simple class to hold/hide data in the ReportHandler class // class ReportWriterSectionData { public: ReportWriterSectionData() { selected_x_offset = 0; selected_y_offset = 0; selected_items_rw = 0; mouseAction = ReportWriterSectionData::MA_None; } virtual ~ReportWriterSectionData() { selected_items_rw = 0; } enum MouseAction { MA_None = 0, MA_Insert = 1, MA_Grab = 2, MA_MoveStartPoint, MA_MoveEndPoint, MA_ResizeNW = 8, MA_ResizeN, MA_ResizeNE, MA_ResizeE, MA_ResizeSE, MA_ResizeS, MA_ResizeSW, MA_ResizeW }; int selected_x_offset; int selected_y_offset; ReportWindow * selected_items_rw; MouseAction mouseAction; QString insertItem; QList copy_list; QList cut_list; }; //! @internal class KoReportDesigner::Private { public: QGridLayout *grid; QGraphicsScene *activeScene; KoRuler *hruler; KoZoomHandler *zoom; QVBoxLayout *vboxlayout; ReportPropertiesButton *pageButton; }; KoReportDesigner::KoReportDesigner(QWidget * parent) : QWidget(parent), d(new Private()) { m_pressX = -1; m_pressY = -1; m_releaseX = -1; m_releaseY = -1; m_kordata = 0; init(); } void KoReportDesigner::init() { m_modified = false; m_detail = 0; d->hruler = 0; m_sectionData = new ReportWriterSectionData(); createProperties(); m_reportHeader = m_reportFooter = 0; m_pageHeaderFirst = m_pageHeaderOdd = m_pageHeaderEven = m_pageHeaderLast = m_pageHeaderAny = 0; m_pageFooterFirst = m_pageFooterOdd = m_pageFooterEven = m_pageFooterLast = m_pageFooterAny = 0; d->grid = new QGridLayout(this); d->grid->setSpacing(0); d->grid->setMargin(0); d->grid->setColumnStretch(1, 1); d->grid->setRowStretch(1, 1); d->grid->setSizeConstraint(QLayout::SetFixedSize); d->vboxlayout = new QVBoxLayout(); d->vboxlayout->setSpacing(0); d->vboxlayout->setMargin(0); d->vboxlayout->setSizeConstraint(QLayout::SetFixedSize); //Create nice rulers d->zoom = new KoZoomHandler(); d->hruler = new KoRuler(this, Qt::Horizontal, d->zoom); d->pageButton = new ReportPropertiesButton(this); d->hruler->setUnit(KoUnit(KoUnit::Centimeter)); d->grid->addWidget(d->pageButton, 0, 0); d->grid->addWidget(d->hruler, 0, 1); d->grid->addLayout(d->vboxlayout, 1, 0, 1, 2); d->pageButton->setMaximumSize(QSize(19, 22)); d->pageButton->setMinimumSize(QSize(19, 22)); m_detail = new ReportSectionDetail(this); d->vboxlayout->insertWidget(0, m_detail); setLayout(d->grid); connect(d->pageButton, SIGNAL(released()), this, SLOT(slotPageButton_Pressed())); emit pagePropertyChanged(*m_set); connect(m_set, SIGNAL(propertyChanged(KoProperty::Set&,KoProperty::Property&)), this, SLOT(slotPropertyChanged(KoProperty::Set&,KoProperty::Property&))); changeSet(m_set); } KoReportDesigner::~KoReportDesigner() { delete d->zoom; delete d; delete m_sectionData; delete m_set; + delete m_kordata; } ///The loading Code KoReportDesigner::KoReportDesigner(QWidget *parent, const QDomElement &data) : QWidget(parent), d(new Private()) { m_kordata = 0; init(); if (data.tagName() != "report:content") { // arg we got an xml file but not one i know of kWarning() << "root element was not "; } //kDebug() << data.text(); deleteDetail(); QDomNodeList nlist = data.childNodes(); QDomNode it; for (int i = 0; i < nlist.count(); ++i) { it = nlist.item(i); // at this level all the children we get should be Elements if (it.isElement()) { QString n = it.nodeName().toLower(); //kDebug() << n; if (n == "report:title") { setReportTitle(it.firstChild().nodeValue()); } else if (n == "report:script") { m_interpreter->setValue(it.toElement().attribute("report:script-interpreter")); m_script->setValue(it.firstChild().nodeValue()); } else if (n == "report:grid") { m_showGrid->setValue(it.toElement().attribute("report:grid-visible", QString::number(1)).toInt() != 0); m_gridSnap->setValue(it.toElement().attribute("report:grid-snap", QString::number(1)).toInt() != 0); m_gridDivisions->setValue(it.toElement().attribute("report:grid-divisions", QString::number(4)).toInt()); m_unit->setValue(it.toElement().attribute("report:page-unit", "cm")); } //TODO Load page options else if (n == "report:page-style") { QString pagetype = it.firstChild().nodeValue(); if (pagetype == "predefined") { m_pageSize->setValue(it.toElement().attribute("report:page-size", "A4")); } else if (pagetype == "custom") { m_pageSize->setValue("custom"); m_customHeight->setValue(KoUnit::parseValue(it.toElement().attribute("report:custom-page-height", ""))); m_customWidth->setValue(KoUnit::parseValue(it.toElement().attribute("report:custom-page-width", ""))); } else if (pagetype == "label") { //TODO } m_rightMargin->setValue(KoUnit::parseValue(it.toElement().attribute("fo:margin-right", "1.0cm"))); m_leftMargin->setValue(KoUnit::parseValue(it.toElement().attribute("fo:margin-left", "1.0cm"))); m_topMargin->setValue(KoUnit::parseValue(it.toElement().attribute("fo:margin-top", "1.0cm"))); m_bottomMargin->setValue(KoUnit::parseValue(it.toElement().attribute("fo:margin-bottom", "1.0cm"))); m_orientation->setValue(it.toElement().attribute("report:print-orientation", "portrait")); } else if (n == "report:body") { QDomNodeList sectionlist = it.childNodes(); QDomNode sec; for (int s = 0; s < sectionlist.count(); ++s) { sec = sectionlist.item(s); if (sec.isElement()) { QString sn = sec.nodeName().toLower(); //kDebug() << sn; if (sn == "report:section") { QString sectiontype = sec.toElement().attribute("report:section-type"); if (section(KRSectionData::sectionTypeFromString(sectiontype)) == 0) { insertSection(KRSectionData::sectionTypeFromString(sectiontype)); section(KRSectionData::sectionTypeFromString(sectiontype))->initFromXML(sec); } } else if (sn == "report:detail") { ReportSectionDetail * rsd = new ReportSectionDetail(this); rsd->initFromXML(sec); setDetail(rsd); } } else { kWarning() << "Encountered an unknown Element: " << n; } } } } else { kWarning() << "Encountered a child node of root that is not an Element"; } } this->slotPageButton_Pressed(); emit reportDataChanged(); slotPropertyChanged(*m_set, *m_unit); // set unit for all items setModified(false); } ///The saving code QDomElement KoReportDesigner::document() const { QDomDocument doc; QDomElement content = doc.createElement("report:content"); content.setAttribute("xmlns:report", ns); content.setAttribute("xmlns:fo", "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"); content.setAttribute("xmlns:svg", "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"); doc.appendChild(content); //title content.appendChild(propertyToElement(&doc, m_title)); QDomElement scr = propertyToElement(&doc, m_script); KRUtils::addPropertyAsAttribute(&scr, m_interpreter); content.appendChild(scr); QDomElement grd = doc.createElement("report:grid"); KRUtils::addPropertyAsAttribute(&grd, m_showGrid); KRUtils::addPropertyAsAttribute(&grd, m_gridDivisions); KRUtils::addPropertyAsAttribute(&grd, m_gridSnap); KRUtils::addPropertyAsAttribute(&grd, m_unit); content.appendChild(grd); // pageOptions // -- size QDomElement pagestyle = doc.createElement("report:page-style"); if (m_pageSize->value().toString() == "Custom") { pagestyle.appendChild(doc.createTextNode("custom")); KRUtils::setAttribute(pagestyle, "report:custom-page-width", m_customWidth->value().toDouble()); KRUtils::setAttribute(pagestyle, "report:custom-page-height", m_customHeight->value().toDouble()); } else if (m_pageSize->value().toString() == "Label") { pagestyle.appendChild(doc.createTextNode("label")); pagestyle.setAttribute("report:page-label-type", m_labelType->value().toString()); } else { pagestyle.appendChild(doc.createTextNode("predefined")); KRUtils::addPropertyAsAttribute(&pagestyle, m_pageSize); //pagestyle.setAttribute("report:page-size", m_pageSize->value().toString()); } // -- orientation KRUtils::addPropertyAsAttribute(&pagestyle, m_orientation); // -- margins: save as points, and not localized KRUtils::setAttribute(pagestyle, "fo:margin-top", m_topMargin->value().toDouble()); KRUtils::setAttribute(pagestyle, "fo:margin-bottom", m_bottomMargin->value().toDouble()); KRUtils::setAttribute(pagestyle, "fo:margin-right", m_rightMargin->value().toDouble()); KRUtils::setAttribute(pagestyle, "fo:margin-left", m_leftMargin->value().toDouble()); content.appendChild(pagestyle); QDomElement body = doc.createElement("report:body"); QDomElement domsection; for (int i = KRSectionData::PageHeaderFirst; i <= KRSectionData::PageFooterAny; ++i) { ReportSection *sec = section((KRSectionData::Section)i); if (sec) { domsection = doc.createElement("report:section"); domsection.setAttribute("report:section-type", KRSectionData::sectionTypeString(KRSectionData::Section(i))); sec->buildXML(doc, domsection); body.appendChild(domsection); } } QDomElement detail = doc.createElement("report:detail"); m_detail->buildXML(doc, detail); body.appendChild(detail); content.appendChild(body); return content; } void KoReportDesigner::slotSectionEditor() { QPointer se = new SectionEditor(this); se->init(this); se->exec(); delete se; } void KoReportDesigner::setReportData(KoReportData* kodata) { + if (m_kordata == kodata) { + return; + } + delete m_kordata; m_kordata = kodata; slotPageButton_Pressed(); setModified(true); emit reportDataChanged(); } ReportSection * KoReportDesigner::section(KRSectionData::Section s) const { ReportSection *sec; switch (s) { case KRSectionData::PageHeaderAny: sec = m_pageHeaderAny; break; case KRSectionData::PageHeaderEven: sec = m_pageHeaderEven; break; case KRSectionData::PageHeaderOdd: sec = m_pageHeaderOdd; break; case KRSectionData::PageHeaderFirst: sec = m_pageHeaderFirst; break; case KRSectionData::PageHeaderLast: sec = m_pageHeaderLast; break; case KRSectionData::PageFooterAny: sec = m_pageFooterAny; break; case KRSectionData::PageFooterEven: sec = m_pageFooterEven; break; case KRSectionData::PageFooterOdd: sec = m_pageFooterOdd; break; case KRSectionData::PageFooterFirst: sec = m_pageFooterFirst; break; case KRSectionData::PageFooterLast: sec = m_pageFooterLast; break; case KRSectionData::ReportHeader: sec = m_reportHeader; break; case KRSectionData::ReportFooter: sec = m_reportFooter; break; default: sec = 0; } return sec; } void KoReportDesigner::removeSection(KRSectionData::Section s) { ReportSection* sec = section(s); if (sec) { delete sec; switch (s) { case KRSectionData::PageHeaderAny: m_pageHeaderAny = 0; break; case KRSectionData::PageHeaderEven: sec = m_pageHeaderEven = 0; break; case KRSectionData::PageHeaderOdd: m_pageHeaderOdd = 0; break; case KRSectionData::PageHeaderFirst: m_pageHeaderFirst = 0; break; case KRSectionData::PageHeaderLast: m_pageHeaderLast = 0; break; case KRSectionData::PageFooterAny: m_pageFooterAny = 0; break; case KRSectionData::PageFooterEven: m_pageFooterEven = 0; break; case KRSectionData::PageFooterOdd: m_pageFooterOdd = 0; break; case KRSectionData::PageFooterFirst: m_pageFooterFirst = 0; break; case KRSectionData::PageFooterLast: m_pageFooterLast = 0; break; case KRSectionData::ReportHeader: m_reportHeader = 0; break; case KRSectionData::ReportFooter: m_reportFooter = 0; break; default: sec = 0; } setModified(true); adjustSize(); } } void KoReportDesigner::insertSection(KRSectionData::Section s) { ReportSection* sec = section(s); if (!sec) { int idx = 0; for (int i = 1; i <= s; ++i) { if (section((KRSectionData::Section)i)) idx++; } if (s > KRSectionData::ReportHeader) idx++; //kDebug() << idx; ReportSection *rs = new ReportSection(this); d->vboxlayout->insertWidget(idx, rs); switch (s) { case KRSectionData::PageHeaderAny: rs->setTitle(i18n("Page Header (Any)")); m_pageHeaderAny = rs; break; case KRSectionData::PageHeaderEven: rs->setTitle(i18n("Page Header (Even)")); m_pageHeaderEven = rs; break; case KRSectionData::PageHeaderOdd: rs->setTitle(i18n("Page Header (Odd)")); m_pageHeaderOdd = rs; break; case KRSectionData::PageHeaderFirst: rs->setTitle(i18n("Page Header (First)")); m_pageHeaderFirst = rs; break; case KRSectionData::PageHeaderLast: rs->setTitle(i18n("Page Header (Last)")); m_pageHeaderLast = rs; break; case KRSectionData::PageFooterAny: rs->setTitle(i18n("Page Footer (Any)")); m_pageFooterAny = rs; break; case KRSectionData::PageFooterEven: rs->setTitle(i18n("Page Footer (Even)")); m_pageFooterEven = rs; break; case KRSectionData::PageFooterOdd: rs->setTitle(i18n("Page Footer (Odd)")); m_pageFooterOdd = rs; break; case KRSectionData::PageFooterFirst: rs->setTitle(i18n("Page Footer (First)")); m_pageFooterFirst = rs; break; case KRSectionData::PageFooterLast: rs->setTitle(i18n("Page Footer (Last)")); m_pageFooterLast = rs; break; case KRSectionData::ReportHeader: rs->setTitle(i18n("Report Header")); m_reportHeader = rs; break; case KRSectionData::ReportFooter: rs->setTitle(i18n("Report Footer")); m_reportFooter = rs; break; //These sections cannot be inserted this way case KRSectionData::None: case KRSectionData::GroupHeader: case KRSectionData::GroupFooter: case KRSectionData::Detail: break; } rs->show(); setModified(true); adjustSize(); emit pagePropertyChanged(*m_set); } } void KoReportDesigner::setReportTitle(const QString & str) { if (reportTitle() != str) { m_title->setValue(str); setModified(true); } } QString KoReportDesigner::reportTitle() const { return m_title->value().toString(); } bool KoReportDesigner::isModified() const { return m_modified; } void KoReportDesigner::setModified(bool mod) { m_modified = mod; if (m_modified) { emit dirty(); } } QStringList KoReportDesigner::fieldNames() const { QStringList qs; qs << QString(); if (m_kordata) qs << m_kordata->fieldNames(); return qs; } QStringList KoReportDesigner::fieldKeys() const { QStringList qs; qs << QString(); if (m_kordata) qs << m_kordata->fieldKeys(); return qs; } void KoReportDesigner::createProperties() { QStringList keys, strings; m_set = new KoProperty::Set(0, "Report"); connect(m_set, SIGNAL(propertyChanged(KoProperty::Set&,KoProperty::Property&)), this, SLOT(slotPropertyChanged(KoProperty::Set&,KoProperty::Property&))); m_title = new KoProperty::Property("Title", "Report", i18n("Title"), i18n("Report Title")); keys.clear(); keys = KoPageFormat::pageFormatNames(); strings = KoPageFormat::localizedPageFormatNames(); QString defaultKey = KoPageFormat::formatString(KoPageFormat::defaultFormat()); m_pageSize = new KoProperty::Property("page-size", keys, strings, defaultKey, i18n("Page Size")); keys.clear(); strings.clear(); keys << "portrait" << "landscape"; strings << i18n("Portrait") << i18n("Landscape"); m_orientation = new KoProperty::Property("print-orientation", keys, strings, "portrait", i18n("Page Orientation")); keys.clear(); strings.clear(); strings = KoUnit::listOfUnitNameForUi(KoUnit::HidePixel); QString unit; foreach(const QString &un, strings) { unit = un.mid(un.indexOf('(') + 1, 2); keys << unit; } m_unit = new KoProperty::Property("page-unit", keys, strings, "cm", i18n("Page Unit")); m_showGrid = new KoProperty::Property("grid-visible", true, i18n("Show Grid")); m_gridSnap = new KoProperty::Property("grid-snap", true, i18n("Snap to Grid")); m_gridDivisions = new KoProperty::Property("grid-divisions", 4, i18n("Grid Divisions")); m_leftMargin = new KoProperty::Property("margin-left", KoUnit(KoUnit::Centimeter).fromUserValue(1.0), i18n("Left Margin"), i18n("Left Margin"), KoProperty::Double); m_rightMargin = new KoProperty::Property("margin-right", KoUnit(KoUnit::Centimeter).fromUserValue(1.0), i18n("Right Margin"), i18n("Right Margin"), KoProperty::Double); m_topMargin = new KoProperty::Property("margin-top", KoUnit(KoUnit::Centimeter).fromUserValue(1.0), i18n("Top Margin"), i18n("Top Margin"), KoProperty::Double); m_bottomMargin = new KoProperty::Property("margin-bottom", KoUnit(KoUnit::Centimeter).fromUserValue(1.0), i18n("Bottom Margin"), i18n("Bottom Margin"), KoProperty::Double); m_leftMargin->setOption("unit", "cm"); m_rightMargin->setOption("unit", "cm"); m_topMargin->setOption("unit", "cm"); m_bottomMargin->setOption("unit", "cm"); keys = Kross::Manager::self().interpreters(); m_interpreter = new KoProperty::Property("script-interpreter", keys, keys, keys[0], i18n("Script Interpreter")); m_script = new KoProperty::Property("script", keys, keys, QString(), i18n("Object Script")); m_set->addProperty(m_title); m_set->addProperty(m_pageSize); m_set->addProperty(m_orientation); m_set->addProperty(m_unit); m_set->addProperty(m_gridSnap); m_set->addProperty(m_showGrid); m_set->addProperty(m_gridDivisions); m_set->addProperty(m_leftMargin); m_set->addProperty(m_rightMargin); m_set->addProperty(m_topMargin); m_set->addProperty(m_bottomMargin); m_set->addProperty(m_interpreter); m_set->addProperty(m_script); // KoProperty::Property* _customHeight; // KoProperty::Property* _customWidth; } /** @brief Handle property changes */ void KoReportDesigner::slotPropertyChanged(KoProperty::Set &s, KoProperty::Property &p) { setModified(true); emit pagePropertyChanged(s); if (p.name() == "page-unit") { d->hruler->setUnit(pageUnit()); QString newstr = m_set->property("page-unit").value().toString(); m_set->property("margin-left").setOption("unit", newstr); m_set->property("margin-right").setOption("unit", newstr); m_set->property("margin-top").setOption("unit", newstr); m_set->property("margin-bottom").setOption("unit", newstr); } } void KoReportDesigner::slotPageButton_Pressed() { if (m_kordata) { QStringList sl = m_kordata->scriptList(m_interpreter->value().toString()); m_script->setListData(sl, sl); } changeSet(m_set); } QSize KoReportDesigner::sizeHint() const { int w = 0; int h = 0; if (m_pageFooterAny) h += m_pageFooterAny->sizeHint().height(); if (m_pageFooterEven) h += m_pageFooterEven->sizeHint().height(); if (m_pageFooterFirst) h += m_pageFooterFirst->sizeHint().height(); if (m_pageFooterLast) h += m_pageFooterLast->sizeHint().height(); if (m_pageFooterOdd) h += m_pageFooterOdd->sizeHint().height(); if (m_pageHeaderAny) h += m_pageHeaderAny->sizeHint().height(); if (m_pageHeaderEven) h += m_pageHeaderEven->sizeHint().height(); if (m_pageHeaderFirst) h += m_pageHeaderFirst->sizeHint().height(); if (m_pageHeaderLast) h += m_pageHeaderLast->sizeHint().height(); if (m_pageHeaderOdd) h += m_pageHeaderOdd->sizeHint().height(); if (m_reportHeader) h += m_reportHeader->sizeHint().height(); if (m_reportFooter) { h += m_reportFooter->sizeHint().height(); } if (m_detail) { h += m_detail->sizeHint().height(); w += m_detail->sizeHint().width(); } h += d->hruler->height(); return QSize(w, h); } int KoReportDesigner::pageWidthPx() const { int cw = 0; int ch = 0; int width = 0; KoPageFormat::Format pf = KoPageFormat::formatFromString(m_set->property("page-size").value().toString()); cw = POINT_TO_INCH(MM_TO_POINT(KoPageFormat::width(pf, KoPageFormat::Portrait))) * KoDpi::dpiX(); ch = POINT_TO_INCH(MM_TO_POINT(KoPageFormat::height(pf, KoPageFormat::Portrait))) * KoDpi::dpiY(); width = (m_set->property("print-orientation").value().toString() == "portrait" ? cw : ch); width = width - POINT_TO_INCH(m_set->property("margin-left").value().toDouble()) * KoDpi::dpiX(); width = width - POINT_TO_INCH(m_set->property("margin-right").value().toDouble()) * KoDpi::dpiX(); return width; } void KoReportDesigner::resizeEvent(QResizeEvent * event) { Q_UNUSED(event); //hruler->setRulerLength ( vboxlayout->geometry().width() ); d->hruler->setRulerLength(pageWidthPx()); } void KoReportDesigner::setDetail(ReportSectionDetail *rsd) { if (!m_detail) { int idx = 0; if (m_pageHeaderFirst) idx++; if (m_pageHeaderOdd) idx++; if (m_pageHeaderEven) idx++; if (m_pageHeaderLast) idx++; if (m_pageHeaderAny) idx++; if (m_reportHeader) idx++; m_detail = rsd; d->vboxlayout->insertWidget(idx, m_detail); } } void KoReportDesigner::deleteDetail() { delete m_detail; m_detail = 0; } KoUnit KoReportDesigner::pageUnit() const { QString u; bool found; u = m_unit->value().toString(); KoUnit unit = KoUnit::fromSymbol(u, &found); if (!found) { unit = KoUnit(KoUnit::Centimeter); } return unit; } void KoReportDesigner::setGridOptions(bool vis, int div) { m_showGrid->setValue(QVariant(vis)); m_gridDivisions->setValue(div); } // // methods for the sectionMouse*Event() // void KoReportDesigner::sectionContextMenuEvent(ReportScene * s, QGraphicsSceneContextMenuEvent * e) { Q_UNUSED(s); QMenu pop; bool itemsSelected = selectionCount() > 0; if (itemsSelected) { QAction *a = KStandardAction::cut(this, SLOT(slotEditCut()), &pop); pop.addAction(a); a = KStandardAction::copy(this, SLOT(slotEditCopy()), &pop); pop.addAction(a); } if (!m_sectionData->copy_list.isEmpty()) { QAction *a = KStandardAction::paste(this, SLOT(slotEditPaste()), &pop); pop.addAction(a); } if (itemsSelected) { pop.addSeparator(); const KGuiItem del = KStandardGuiItem::del(); QAction *a = new KAction(del.icon(), del.text(), &pop); a->setToolTip(del.toolTip()); a->setShortcut(QKeySequence(QKeySequence::Delete)); connect(a, SIGNAL(activated()), SLOT(slotEditDelete())); pop.addAction(a); } if (!pop.actions().isEmpty()) { pop.exec(e->screenPos()); } } void KoReportDesigner::sectionMousePressEvent(ReportSceneView * v, QMouseEvent * e) { Q_UNUSED(v); m_pressX = e->pos().x(); m_pressY = e->pos().y(); } void KoReportDesigner::sectionMouseReleaseEvent(ReportSceneView * v, QMouseEvent * e) { e->accept(); m_releaseX = e->pos().x(); m_releaseY = e->pos().y(); if (e->button() == Qt::LeftButton) { QPointF pos(m_pressX, m_pressY); QPointF end(m_releaseX, m_releaseY); if (m_releaseY >= v->scene()->height()) { m_releaseY = v->scene()->height(); end.setY(v->scene()->height()); } if (m_releaseX >= v->scene()->width()) { m_releaseX = v->scene()->width(); end.setX(v->scene()->width()); } if (m_sectionData->mouseAction == ReportWriterSectionData::MA_Insert) { QGraphicsItem * item = 0; if (m_sectionData->insertItem == "report:line") { item = new KoReportDesignerItemLine(v->designer(), v->scene(), pos, end); } else { KoReportPluginManager* pluginManager = KoReportPluginManager::self(); KoReportPluginInterface *plug = pluginManager->plugin(m_sectionData->insertItem); if (plug) { QObject *obj = plug->createDesignerInstance(v->designer(), v->scene(), pos); if (obj) { item = dynamic_cast(obj); } } else { kWarning() << "attempted to insert an unknown item"; } } if (item) { item->setVisible(true); item->setSelected(true); KoReportItemBase* baseReportItem = dynamic_cast(item); if (baseReportItem) { changeSet(baseReportItem->propertySet()); if (v && v->designer()) { v->designer()->setModified(true); } emit itemInserted(m_sectionData->insertItem); } } m_sectionData->mouseAction = ReportWriterSectionData::MA_None; m_sectionData->insertItem.clear(); unsetSectionCursor(); } } } unsigned int KoReportDesigner::selectionCount() const { if (activeScene()) return activeScene()->selectedItems().count(); else return 0; } void KoReportDesigner::changeSet(KoProperty::Set *s) { //Set the checked state of the report properties button if (s == m_set) d->pageButton->setCheckState(Qt::Checked); else d->pageButton->setCheckState(Qt::Unchecked); m_itmset = s; emit propertySetChanged(); } // // Actions // void KoReportDesigner::slotItem(const QString &entity) { m_sectionData->mouseAction = ReportWriterSectionData::MA_Insert; m_sectionData->insertItem = entity; setSectionCursor(QCursor(Qt::CrossCursor)); } void KoReportDesigner::slotEditDelete() { QGraphicsItem * item = 0; bool modified = false; while (selectionCount() > 0) { item = activeScene()->selectedItems()[0]; if (item) { QGraphicsScene * scene = item->scene(); delete item; scene->update(); m_sectionData->mouseAction = ReportWriterSectionData::MA_None; modified = true; } } activeScene()->selectedItems().clear(); m_sectionData->selected_items_rw = 0; //TODO temporary //clears cut and copy lists to make sure we do not crash //if weve deleted something in the list //should really check if an item is in the list first //and remove it. m_sectionData->cut_list.clear(); m_sectionData->copy_list.clear(); if (modified) { setModified(true); } } void KoReportDesigner::slotEditCut() { if (selectionCount() > 0) { //First delete any items that are curerntly in the list //so as not to leak memory qDeleteAll(m_sectionData->cut_list); m_sectionData->cut_list.clear(); QGraphicsItem * item = activeScene()->selectedItems().first(); bool modified = false; if (item) { m_sectionData->copy_list.clear(); for (int i = 0; i < activeScene()->selectedItems().count(); i++) { QGraphicsItem *itm = activeScene()->selectedItems()[i]; m_sectionData->cut_list.append(dynamic_cast(itm)); m_sectionData->copy_list.append(dynamic_cast(itm)); } int c = activeScene()->selectedItems().count(); for (int i = 0; i < c; i++) { QGraphicsItem *itm = activeScene()->selectedItems()[0]; activeScene()->removeItem(itm); activeScene()->update(); modified = true; } m_sectionData->selected_x_offset = 10; m_sectionData->selected_y_offset = 10; } if (modified) { setModified(true); } } } void KoReportDesigner::slotEditCopy() { if (selectionCount() < 1) return; QGraphicsItem * item = activeScene()->selectedItems().first(); if (item) { m_sectionData->copy_list.clear(); for (int i = 0; i < activeScene()->selectedItems().count(); i++) { m_sectionData->copy_list.append(dynamic_cast(activeScene()->selectedItems()[i])); } m_sectionData->selected_x_offset = 10; m_sectionData->selected_y_offset = 10; } } void KoReportDesigner::slotEditPaste() { // call the editPaste function passing it a reportsection slotEditPaste(activeScene()); } void KoReportDesigner::slotEditPaste(QGraphicsScene * canvas) { // paste a new item of the copy we have in the specified location if (!m_sectionData->copy_list.isEmpty()) { QList activeItems = canvas->selectedItems(); QGraphicsItem *activeItem = 0; if (activeItems.count() == 1) { activeItem = activeItems.first(); } canvas->clearSelection(); m_sectionData->mouseAction = ReportWriterSectionData::MA_None; //!TODO this code sucks :) //!The setPos calls only work AFTER the name has been set ?!?!? for (int i = 0; i < m_sectionData->copy_list.count(); i++) { KoReportItemBase *obj = dynamic_cast(m_sectionData->copy_list[i]); const QString type = obj ? obj->typeName() : "object"; //kDebug() << type; KoReportDesignerItemBase *ent = (m_sectionData->copy_list[i])->clone(); KoReportItemBase *new_obj = dynamic_cast(ent); new_obj->setEntityName(suggestEntityName(type)); if (activeItem) { new_obj->position().setScenePos(QPointF(activeItem->x() + 10, activeItem->y() + 10)); } else { new_obj->position().setScenePos(QPointF(0, 0)); } changeSet(new_obj->propertySet()); QGraphicsItem *pasted_ent = dynamic_cast(ent); if (pasted_ent) { pasted_ent->setSelected(true); canvas->addItem(pasted_ent); pasted_ent->show(); m_sectionData->mouseAction = ReportWriterSectionData::MA_Grab; setModified(true); } } } } void KoReportDesigner::slotRaiseSelected() { dynamic_cast(activeScene())->raiseSelected(); } void KoReportDesigner::slotLowerSelected() { dynamic_cast(activeScene())->lowerSelected(); } QGraphicsScene* KoReportDesigner::activeScene() const { return d->activeScene; } void KoReportDesigner::setActiveScene(QGraphicsScene* a) { if (d->activeScene && d->activeScene != a) d->activeScene->clearSelection(); d->activeScene = a; //Trigger an update so that the last scene redraws its title; update(); } KoZoomHandler* KoReportDesigner::zoomHandler() const { return d->zoom; } QString KoReportDesigner::suggestEntityName(const QString &n) const { ReportSection *sec; int itemCount = 0; //Count items in the main sections for (int i = 1; i <= KRSectionData::PageFooterAny; i++) { sec = section((KRSectionData::Section) i); if (sec) { const QGraphicsItemList l = sec->items(); itemCount += l.count(); } } if (m_detail) { //Count items in the group headers/footers for (int i = 0; i < m_detail->groupSectionCount(); i++) { sec = m_detail->groupSection(i)->groupHeader(); if (sec) { const QGraphicsItemList l = sec->items(); itemCount += l.count(); } sec = m_detail->groupSection(i)->groupFooter(); if (sec) { const QGraphicsItemList l = sec->items(); itemCount += l.count(); } } sec = m_detail->detailSection(); if (sec) { const QGraphicsItemList l = sec->items(); itemCount += l.count(); } } while (!isEntityNameUnique(n + QString::number(itemCount))) { itemCount++; } return n + QString::number(itemCount); } bool KoReportDesigner::isEntityNameUnique(const QString &n, KoReportItemBase* ignore) const { ReportSection *sec; bool unique = true; //Check items in the main sections for (int i = 1; i <= KRSectionData::PageFooterAny; i++) { sec = section((KRSectionData::Section)i); if (sec) { const QGraphicsItemList l = sec->items(); for (QGraphicsItemList::const_iterator it = l.constBegin(); it != l.constEnd(); ++it) { KoReportItemBase* itm = dynamic_cast(*it); if (itm && itm->entityName() == n && itm != ignore) { unique = false; break; } } if (!unique) break; } } //Count items in the group headers/footers if (unique && m_detail) { for (int i = 0; i < m_detail->groupSectionCount(); ++i) { sec = m_detail->groupSection(i)->groupHeader(); if (sec) { const QGraphicsItemList l = sec->items(); for (QGraphicsItemList::const_iterator it = l.constBegin(); it != l.constEnd(); ++it) { KoReportItemBase* itm = dynamic_cast(*it); if (itm && itm->entityName() == n && itm != ignore) { unique = false; break; } } } sec = m_detail->groupSection(i)->groupFooter(); if (unique && sec) { const QGraphicsItemList l = sec->items(); for (QGraphicsItemList::const_iterator it = l.constBegin(); it != l.constEnd(); ++it) { KoReportItemBase* itm = dynamic_cast(*it); if (itm && itm->entityName() == n && itm != ignore) { unique = false; break; } } } } } if (unique && m_detail) { sec = m_detail->detailSection(); if (sec) { const QGraphicsItemList l = sec->items(); for (QGraphicsItemList::const_iterator it = l.constBegin(); it != l.constEnd(); ++it) { KoReportItemBase* itm = dynamic_cast(*it); if (itm && itm && itm->entityName() == n && itm != ignore) { unique = false; break; } } } } return unique; } static bool actionPriortyLessThan(QAction* act1, QAction* act2) { if (act1->data().toInt() > 0 && act2->data().toInt() > 0) { return act1->data().toInt() < act2->data().toInt(); } return false; } QList KoReportDesigner::actions(QActionGroup* group) { KoReportPluginManager* manager = KoReportPluginManager::self(); QList actList = manager->actions(); KToggleAction *act = new KToggleAction(koIcon("line"), i18n("Line"), group); act->setObjectName("report:line"); act->setData(9); actList << act; qSort(actList.begin(), actList.end(), actionPriortyLessThan); int i = 0; //TODO maybe this is a bit hackish //It finds the first plugin based on the priority in userdata //The lowest oriority a plugin can have is 10 //And inserts a separator before it. bool sepInserted = false; foreach(QAction *a, actList) { ++i; if (!sepInserted && a->data().toInt() >= 10) { QAction *sep = new QAction("separator", group); sep->setSeparator(true); actList.insert(i-1, sep); sepInserted = true; } group->addAction(a); } return actList; } void KoReportDesigner::setSectionCursor(const QCursor& c) { if (m_pageFooterAny) m_pageFooterAny->setSectionCursor(c); if (m_pageFooterEven) m_pageFooterEven->setSectionCursor(c); if (m_pageFooterFirst) m_pageFooterFirst->setSectionCursor(c); if (m_pageFooterLast) m_pageFooterLast->setSectionCursor(c); if (m_pageFooterOdd) m_pageFooterOdd->setSectionCursor(c); if (m_pageHeaderAny) m_pageHeaderAny->setSectionCursor(c); if (m_pageHeaderEven) m_pageHeaderEven->setSectionCursor(c); if (m_pageHeaderFirst) m_pageHeaderFirst->setSectionCursor(c); if (m_pageHeaderLast) m_pageHeaderLast->setSectionCursor(c); if (m_pageHeaderOdd) m_pageHeaderOdd->setSectionCursor(c); if (m_detail) m_detail->setSectionCursor(c); } void KoReportDesigner::unsetSectionCursor() { if (m_pageFooterAny) m_pageFooterAny->unsetSectionCursor(); if (m_pageFooterEven) m_pageFooterEven->unsetSectionCursor(); if (m_pageFooterFirst) m_pageFooterFirst->unsetSectionCursor(); if (m_pageFooterLast) m_pageFooterLast->unsetSectionCursor(); if (m_pageFooterOdd) m_pageFooterOdd->unsetSectionCursor(); if (m_pageHeaderAny) m_pageHeaderAny->unsetSectionCursor(); if (m_pageHeaderEven) m_pageHeaderEven->unsetSectionCursor(); if (m_pageHeaderFirst) m_pageHeaderFirst->unsetSectionCursor(); if (m_pageHeaderLast) m_pageHeaderLast->unsetSectionCursor(); if (m_pageHeaderOdd) m_pageHeaderOdd->unsetSectionCursor(); if (m_detail) m_detail->unsetSectionCursor(); } qreal KoReportDesigner::countSelectionHeight() const { if (m_releaseY == -1 || m_pressY == -1) { return -1; } return qAbs(m_releaseY - m_pressY); } qreal KoReportDesigner::countSelectionWidth() const { if (m_releaseX == -1 || m_pressX == -1) { return -1; } return qAbs(m_releaseX - m_pressX); } qreal KoReportDesigner::getSelectionPressX() const { return m_pressX; } qreal KoReportDesigner::getSelectionPressY() const { return m_pressY; } QPointF KoReportDesigner::getPressPoint() const { return QPointF(m_pressX, m_pressY); } QPointF KoReportDesigner::getReleasePoint() const { return QPointF(m_releaseX, m_releaseY); } diff --git a/libs/koreport/wrtembed/KoReportDesigner.h b/libs/koreport/wrtembed/KoReportDesigner.h index 28cbe24c333..c5136004bb0 100644 --- a/libs/koreport/wrtembed/KoReportDesigner.h +++ b/libs/koreport/wrtembed/KoReportDesigner.h @@ -1,386 +1,386 @@ /* * OpenRPT report writer and rendering engine * Copyright (C) 2001-2007 by OpenMFG, LLC * Copyright (C) 2007-2008 by Adam Pigg * Copyright (C) 2011 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 . */ #ifndef REPORTDESIGNER_H #define REPORTDESIGNER_H #include #include #include #include #include #include #include #include #include #include #include #include "koreport_export.h" #include "KoReportData.h" class ReportGridOptions; class QDomDocument; class QGraphicsScene; class QActionGroup; class KoRuler; class KoZoomHandler; class QGridLayout; class ReportSectionDetail; class ReportSection; class KoUnit; class ReportScene; class QGraphicsSceneMouseEvent; class QGraphicsSceneContextMenuEvent; class ReportSceneView; class ReportWriterSectionData; class KoReportPluginInterface; class KoReportPluginManager; // // Class ReportDesigner // The ReportDesigner is the main widget for designing a report // class KOREPORT_EXPORT KoReportDesigner : public QWidget { Q_OBJECT public: qreal m_pressX; qreal m_pressY; qreal m_releaseX; qreal m_releaseY; /** @brief Constructor that create a blank designer @param widget QWidget parent */ explicit KoReportDesigner(QWidget *); /** @brief Constructor that create a designer, and loads the report described in the QDomElement @param widget QWidget parent @param element Report structure XML element */ KoReportDesigner(QWidget *, const QDomElement &data); /** @brief Desctructor */ ~KoReportDesigner(); /** @brief Sets the report data The report data interface contains functions to retrieve data and information about the fields. - @param kodata Pointer to KoReportData instance + @param kodata Pointer to KoReportData instance, ownership is transferred */ void setReportData(KoReportData* kodata); /** @brief Return a pointer to the reports data @return Pointer to report data */ const KoReportData *reportData() const { return m_kordata; } /** @brief Return a pointer to the section specified @param section KRSectionData::Section enum value of the section to return @return Pointer to report section object, or 0 if no section exists */ ReportSection* section(KRSectionData::Section) const; /** @brief Deletes the section specified @param section KRSectionData::Section enum value of the section to return */ void removeSection(KRSectionData::Section); /** @brief Create a new section and insert it into the report @param section KRSectionData::Section enum value of the section to return */ void insertSection(KRSectionData::Section); /** @brief Return a pointer to the detail section. The detail section contains the actual detail section and related group sections @return Pointer to detail section */ ReportSectionDetail* detailSection() const { return m_detail; } /** @brief Sets the title of the reportData @param title Report Title */ void setReportTitle(const QString &); /** @brief Sets the parameters for the display of the background gridpoints @param visible Grid visibility @param divisions Number of minor divisions between major points */ void setGridOptions(bool visible, int divisions); /** @brief Return the title of the report */ QString reportTitle() const; /** @brief Return an XML description of the report @return QDomElement describing the report definition */ QDomElement document() const; /** @brief Return true if the design has been modified @return modified status */ bool isModified() const; /** @return a list of field names in the selected KoReportData */ QStringList fieldNames() const; /** @return a list of field keys in the selected KoReportData The keys can be used to reference the names */ QStringList fieldKeys() const; /** @brief Calculate the width of the page in pixels given the paper size, orientation, dpi and margin @return integer value of width in pixels */ int pageWidthPx() const; /** @return the scene (section) that is currently active */ QGraphicsScene* activeScene() const; /** @brief Sets the active Scene @param scene The scene to make active */ void setActiveScene(QGraphicsScene* scene); /** @return the property set for the general report properties */ KoProperty::Set* propertySet() const { return m_set; } /** @brief Give a hint on the size of the widget */ virtual QSize sizeHint() const; /** @brief Return a pointer to the zoom handler */ KoZoomHandler* zoomHandler() const; /** @brief Return the current unit assigned to the report */ KoUnit pageUnit() const; /** @brief Handle the context menu event for a report section @param scene The associated scene (section) */ void sectionContextMenuEvent(ReportScene *, QGraphicsSceneContextMenuEvent * e); /** @brief Handle the mouse release event for a report section */ void sectionMouseReleaseEvent(ReportSceneView *, QMouseEvent * e); void sectionMousePressEvent(ReportSceneView *, QMouseEvent * e); /** @brief Sets the property set for the currently selected item @param set Property set of item */ void changeSet(KoProperty::Set *); /** @brief Return the property set for the curently selected item */ KoProperty::Set* itemPropertySet() const { return m_itmset; } /** @brief Sets the modified status, defaulting to true for modified @param modified Modified status */ void setModified(bool = true); /** @brief Return a unique name that can be used by the entity @param entity Name of entity */ QString suggestEntityName(const QString &) const; /** @brief Checks if the supplied name is unique among all entities */ bool isEntityNameUnique(const QString &, KoReportItemBase* = 0) const; /** @brief Returns a list of actions that represent the entities that can be inserted into the report. Actions are created as children of @a group and belong to the group. @return list of actions */ static QList actions(QActionGroup* group); /** @return X position of mouse when mouse press occurs */ qreal getSelectionPressX() const; /** @return Y position of mouse when mouse press occurs */ qreal getSelectionPressY() const; /** @return difference between X position of mouse release and press */ qreal countSelectionWidth() const; /** @return difference between Y position of mouse release and press */ qreal countSelectionHeight() const; /** @return point that contains X,Y coordinates of mouse press */ QPointF getPressPoint() const; /** @return point that contains X,Y coordinates of mouse press */ QPointF getReleasePoint() const; public Q_SLOTS: void slotEditDelete(); void slotEditCut(); void slotEditCopy(); void slotEditPaste(); void slotEditPaste(QGraphicsScene *); void slotItem(const QString&); void slotSectionEditor(); void slotRaiseSelected(); void slotLowerSelected(); protected: ReportSection *m_reportHeader; ReportSection *m_pageHeaderFirst; ReportSection *m_pageHeaderOdd; ReportSection *m_pageHeaderEven; ReportSection *m_pageHeaderLast; ReportSection *m_pageHeaderAny; ReportSection *m_pageFooterFirst; ReportSection *m_pageFooterOdd; ReportSection *m_pageFooterEven; ReportSection *m_pageFooterLast; ReportSection *m_pageFooterAny; ReportSection *m_reportFooter; ReportSectionDetail *m_detail; private: class Private; Private * const d; void init(); bool m_modified; // true if this document has been modified, false otherwise KoReportData *m_kordata; /** @brief Sets the detail section to the given section */ void setDetail(ReportSectionDetail *rsd); /** @brief Deletes the detail section */ void deleteDetail(); virtual void resizeEvent(QResizeEvent * event); //Properties void createProperties(); KoProperty::Set* m_set; KoProperty::Set* m_itmset; KoProperty::Property* m_title; KoProperty::Property* m_pageSize; KoProperty::Property* m_orientation; KoProperty::Property* m_unit; KoProperty::Property* m_customHeight; KoProperty::Property* m_customWidth; KoProperty::Property* m_leftMargin; KoProperty::Property* m_rightMargin; KoProperty::Property* m_topMargin; KoProperty::Property* m_bottomMargin; KoProperty::Property* m_showGrid; KoProperty::Property* m_gridDivisions; KoProperty::Property* m_gridSnap; KoProperty::Property* m_labelType; KoProperty::Property* m_interpreter; KoProperty::Property* m_script; ReportWriterSectionData *m_sectionData; unsigned int selectionCount() const; void setSectionCursor(const QCursor&); void unsetSectionCursor(); private Q_SLOTS: void slotPropertyChanged(KoProperty::Set &s, KoProperty::Property &p); /** @brief When the 'page' button in the top left is pressed, change the property set to the reports properties. */ void slotPageButton_Pressed(); Q_SIGNALS: void pagePropertyChanged(KoProperty::Set &s); void propertySetChanged(); void dirty(); void reportDataChanged(); void itemInserted(const QString& entity); }; #endif