diff --git a/kexi/plugins/reports/kexidbreportdata.cpp b/kexi/plugins/reports/kexidbreportdata.cpp index 376543d65ba..f762084b446 100644 --- a/kexi/plugins/reports/kexidbreportdata.cpp +++ b/kexi/plugins/reports/kexidbreportdata.cpp @@ -1,404 +1,403 @@ /* * Kexi Report Plugin * Copyright (C) 2007-2009 by Adam Pigg (adam@piggz.co.uk) -* Copyright (C) 2015 Jarosław Staniek +* Copyright (C) 2015-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 "kexidbreportdata.h" #include "kexireportview.h" #include #include #include #include class KexiDBReportData::Private { public: explicit Private(KexiDB::Connection *pDb, KexiReportView *v) : cursor(0), connection(pDb), view(v), originalSchema(0), copySchema(0) { } ~Private() { delete copySchema; delete originalSchema; delete cursor; } QString objectName; + QString objectClass; KexiDB::Cursor *cursor; KexiDB::Connection * const connection; KexiReportView * const view; KexiDB::QuerySchema *originalSchema; KexiDB::QuerySchema *copySchema; }; -KexiDBReportData::KexiDBReportData (const QString &objectName, - KexiDB::Connection * pDb, KexiReportView *view) - : d(new Private(pDb, view)) -{ - d->objectName = objectName; - getSchema(); -} - KexiDBReportData::KexiDBReportData(const QString& objectName, - const QString& partClass, + const QString& objectClass, KexiDB::Connection* pDb, KexiReportView *view) : d(new Private(pDb, view)) { d->objectName = objectName; - getSchema(partClass); + d->objectClass = objectClass; + getSchema(); } void KexiDBReportData::setSorting(const QList& sorting) { if (d->copySchema) { if (sorting.isEmpty()) return; KexiDB::OrderByColumnList order; for (int i = 0; i < sorting.count(); i++) { order.appendField(*d->copySchema, sorting[i].field, sorting[i].order == Qt::AscendingOrder); } d->copySchema->setOrderByColumnList(order); } else { kDebug() << "Unable to sort null schema"; } } void KexiDBReportData::addExpression(const QString& field, const QVariant& value, int relation) { if (d->copySchema) { KexiDB::Field *fld = d->copySchema->findTableField(field); if (fld) { d->copySchema->addToWhereExpression(fld, value, relation); } } else { kDebug() << "Unable to add expresstion to null schema"; } } KexiDBReportData::~KexiDBReportData() { close(); delete d; } bool KexiDBReportData::open() { if ( d->connection && d->cursor == 0 ) { if ( d->objectName.isEmpty() ) { d->cursor = d->connection->prepareQuery("SELECT '' AS expr1 FROM kexi__db WHERE kexi__db.db_property = 'kexidb_major_ver'"); } else if ( d->copySchema) { kDebug() << "Opening cursor.." << d->copySchema->debugString(); d->cursor = d->connection->prepareQuery(*d->copySchema, KexiDB::Cursor::Buffered); } if (d->cursor) { bool ok = d->view->setData(d->cursor); if (ok) { kDebug() << "Moving to first record.."; if (!d->cursor->moveFirst()) { ok = !d->cursor->error(); } } return ok; } } return false; } bool KexiDBReportData::close() { if ( d->cursor ) { d->cursor->close(); delete d->cursor; d->cursor = 0; } return true; } -bool KexiDBReportData::getSchema(const QString& partClass) +bool KexiDBReportData::getSchema() { if (d->connection) { delete d->originalSchema; d->originalSchema = 0; delete d->copySchema; d->copySchema = 0; - if ((partClass.isEmpty() || partClass == "org.kexi-project.table") + if ((d->objectClass.isEmpty() || d->objectClass == "org.kexi-project.table") && d->connection->tableSchema(d->objectName)) { kDebug() << d->objectName << "is a table.."; d->originalSchema = new KexiDB::QuerySchema(*(d->connection->tableSchema(d->objectName))); } - else if ((partClass.isEmpty() || partClass == "org.kexi-project.query") + else if ((d->objectClass.isEmpty() || d->objectClass == "org.kexi-project.query") && d->connection->querySchema(d->objectName)) { kDebug() << d->objectName << "is a query.."; d->connection->querySchema(d->objectName)->debug(); d->originalSchema = new KexiDB::QuerySchema(*(d->connection->querySchema(d->objectName))); } if (d->originalSchema) { kDebug() << "Original:" << d->connection->selectStatement(*d->originalSchema); d->originalSchema->debug(); d->copySchema = new KexiDB::QuerySchema(*d->originalSchema); d->copySchema->debug(); kDebug() << "Copy:" << d->connection->selectStatement(*d->copySchema); } return true; } return false; } QString KexiDBReportData::sourceName() const { return d->objectName; } +QString KexiDBReportData::sourceClass() const +{ + return d->objectClass; +} + int KexiDBReportData::fieldNumber ( const QString &fld ) const { if (!d->cursor || !d->cursor->query()) { return -1; } const KexiDB::QueryColumnInfo::Vector fieldsExpanded( d->cursor->query()->fieldsExpanded(KexiDB::QuerySchema::Unique)); for (int i = 0; i < fieldsExpanded.size() ; ++i) { if (0 == QString::compare(fld, fieldsExpanded[i]->aliasOrName(), Qt::CaseInsensitive)) { return i; } } return -1; } QStringList KexiDBReportData::fieldNames() const { if (!d->originalSchema) { return QStringList(); } QStringList names; const KexiDB::QueryColumnInfo::Vector fieldsExpanded( d->originalSchema->fieldsExpanded(KexiDB::QuerySchema::Unique)); for (int i = 0; i < fieldsExpanded.size(); i++) { //! @todo in some Kexi mode captionOrAliasOrName() would be used here (more user-friendly) names.append(fieldsExpanded[i]->aliasOrName()); } return names; } QVariant KexiDBReportData::value ( unsigned int i ) const { if ( d->cursor ) return d->cursor->value ( i ); return QVariant(); } QVariant KexiDBReportData::value ( const QString &fld ) const { int i = fieldNumber ( fld ); if ( d->cursor ) return d->cursor->value ( i ); return QVariant(); } bool KexiDBReportData::moveNext() { if ( d->cursor ) return d->cursor->moveNext(); return false; } bool KexiDBReportData::movePrevious() { if ( d->cursor ) return d->cursor->movePrev(); return false; } bool KexiDBReportData::moveFirst() { if ( d->cursor ) return d->cursor->moveFirst(); return false; } bool KexiDBReportData::moveLast() { if ( d->cursor ) return d->cursor->moveLast(); return false; } qint64 KexiDBReportData::at() const { if ( d->cursor ) return d->cursor->at(); return 0; } qint64 KexiDBReportData::recordCount() const { if ( d->copySchema ) { return KexiDB::rowCount ( *d->copySchema ); } else { return 1; } } QStringList KexiDBReportData::scriptList(const QString& interpreter) const { QStringList scripts; if( d->connection) { QList scriptids = d->connection->objectIds(KexiPart::ScriptObjectType); QStringList scriptnames = d->connection->objectNames(KexiPart::ScriptObjectType); QString script; int i; i = 0; kDebug() << scriptids << scriptnames; kDebug() << interpreter; //A blank entry scripts << ""; foreach(int id, scriptids) { kDebug() << "ID:" << id; tristate res; res = d->connection->loadDataBlock(id, script, QString()); if (res == true) { QDomDocument domdoc; bool parsed = domdoc.setContent(script, false); QDomElement scriptelem = domdoc.namedItem("script").toElement(); if (parsed && !scriptelem.isNull()) { if (interpreter == scriptelem.attribute("language") && scriptelem.attribute("scripttype") == "object") { scripts << scriptnames[i]; } } else { kDebug() << "Unable to parse script"; } } else { kDebug() << "Unable to loadDataBlock"; } ++i; } kDebug() << scripts; } return scripts; } QString KexiDBReportData::scriptCode(const QString& scriptname, const QString& language) const { QString scripts; if (d->connection) { QList scriptids = d->connection->objectIds(KexiPart::ScriptObjectType); QStringList scriptnames = d->connection->objectNames(KexiPart::ScriptObjectType); int i = 0; QString script; foreach(int id, scriptids) { kDebug() << "ID:" << id; tristate res; res = d->connection->loadDataBlock(id, script, QString()); if (res == true) { QDomDocument domdoc; bool parsed = domdoc.setContent(script, false); if (! parsed) { kDebug() << "XML parsing error"; return QString(); } QDomElement scriptelem = domdoc.namedItem("script").toElement(); if (scriptelem.isNull()) { kDebug() << "script domelement is null"; return QString(); } QString interpretername = scriptelem.attribute("language"); kDebug() << language << interpretername; kDebug() << scriptelem.attribute("scripttype"); kDebug() << scriptname << scriptnames[i]; if (language == interpretername && (scriptelem.attribute("scripttype") == "module" || scriptname == scriptnames[i])) { scripts += '\n' + scriptelem.text().toUtf8(); } ++i; } else { kDebug() << "Unable to loadDataBlock"; } } } return scripts; } QStringList KexiDBReportData::dataSources() const { //Get the list of queries in the database QStringList qs; if (d->connection && d->connection->isConnected()) { QList tids = d->connection->tableIds(); qs << ""; for (int i = 0; i < tids.size(); ++i) { KexiDB::TableSchema* tsc = d->connection->tableSchema(tids[i]); if (tsc) qs << tsc->name(); } QList qids = d->connection->queryIds(); qs << ""; for (int i = 0; i < qids.size(); ++i) { KexiDB::QuerySchema* qsc = d->connection->querySchema(qids[i]); if (qsc) qs << qsc->name(); } } return qs; } KoReportData* KexiDBReportData::create(const QString& source) const { - return new KexiDBReportData(source, d->connection, d->view); + return new KexiDBReportData(source, QString(), d->connection, d->view); } diff --git a/kexi/plugins/reports/kexidbreportdata.h b/kexi/plugins/reports/kexidbreportdata.h index 7fb20c22e55..12455811069 100644 --- a/kexi/plugins/reports/kexidbreportdata.h +++ b/kexi/plugins/reports/kexidbreportdata.h @@ -1,84 +1,83 @@ /* * Kexi Report Plugin * Copyright (C) 2007-2009 by Adam Pigg (adam@piggz.co.uk) -* Copyright (C) 2015 Jarosław Staniek +* Copyright (C) 2015-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 __KEXIDBREPORTDATA_H__ #define __KEXIDBREPORTDATA_H__ #include #include #include #include #include class KexiReportView; /** */ class KexiDBReportData : public KoReportData { public: - KexiDBReportData(const QString &objectName, KexiDB::Connection *conn, KexiReportView *view); - /*! - * @a partClass specifies @a objectName type: a table or query. + * @a objectClass specifies @a objectName type: a table or query. * Types accepted: * -"org.kexi-project.table" * -"org.kexi-project.query" * -empty QString() - attempt to resolve @a objectName */ - KexiDBReportData(const QString &objectName, const QString& partClass, KexiDB::Connection *conn, KexiReportView *view); + KexiDBReportData(const QString &objectName, const QString& objectClass, KexiDB::Connection *conn, KexiReportView *view); virtual ~KexiDBReportData(); virtual QStringList fieldNames() const; virtual void setSorting(const QList& sorting); virtual void addExpression(const QString &field, const QVariant &value, int relation = '='); virtual QString sourceName() const; + virtual QString sourceClass() const; virtual int fieldNumber(const QString &field) const; virtual QVariant value(unsigned int) const; virtual QVariant value(const QString &field) const; virtual bool open(); virtual bool close(); virtual bool moveNext(); virtual bool movePrevious(); virtual bool moveFirst(); virtual bool moveLast(); virtual qint64 at() const; virtual qint64 recordCount() const; //Utility Functions virtual QStringList scriptList(const QString& language) const; virtual QString scriptCode(const QString& script, const QString& language) const; virtual QStringList dataSources() const; virtual KoReportData* create(const QString &source) const; private: class Private; Private * const d; - bool getSchema(const QString& partClass = QString()); + bool getSchema(); }; #endif diff --git a/kexi/plugins/reports/kexireportdesignview.cpp b/kexi/plugins/reports/kexireportdesignview.cpp index 3697c1369cd..26b976042ef 100644 --- a/kexi/plugins/reports/kexireportdesignview.cpp +++ b/kexi/plugins/reports/kexireportdesignview.cpp @@ -1,208 +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) { m_reportDesigner->setReportData(kodata); tempData()->connectionDefinition = m_sourceSelector->connectionData(); + setDirty(true); } void KexiReportDesignView::triggerAction(const QString &action) { m_reportDesigner->slotItem(action); } diff --git a/kexi/plugins/reports/kexireportpart.cpp b/kexi/plugins/reports/kexireportpart.cpp index 484c16701c1..022f81ef138 100644 --- a/kexi/plugins/reports/kexireportpart.cpp +++ b/kexi/plugins/reports/kexireportpart.cpp @@ -1,217 +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(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; - - td->name = window->partItem()->name(); 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/kexireportpart.h b/kexi/plugins/reports/kexireportpart.h index 1638a195c0f..5956c5d8d6c 100644 --- a/kexi/plugins/reports/kexireportpart.h +++ b/kexi/plugins/reports/kexireportpart.h @@ -1,83 +1,84 @@ /* * 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 . */ #ifndef _KEXIREPORTPART_H_ #define _KEXIREPORTPART_H_ #include #include #include #include /** * @short Application Main Window * @author Adam Pigg * @version 0.1 */ class KexiReportPart : public KexiPart::Part { Q_OBJECT public: /** * Default Constructor */ KexiReportPart(QObject *parent, const QVariantList &l); /** * Default Destructor */ virtual ~KexiReportPart(); virtual KexiView* createView(QWidget *parent, KexiWindow* win, KexiPart::Item &item, Kexi::ViewMode = Kexi::DataViewMode, QMap* staticObjectArgs = 0); virtual KexiWindowData* createWindowData(KexiWindow* window); virtual void setupCustomPropertyPanelTabs(KTabWidget *tab); virtual void initPartActions(); class TempData : public KexiWindowData { public: explicit TempData(QObject* parent); QDomElement reportDefinition; QDomElement connectionDefinition; /*! true, if \a document member has changed in previous view. Used on view switching. Check this flag to see if we should refresh data for DataViewMode. */ bool reportSchemaChangedInPreviousView; QString name; + QString className; //!< org.kexi-project.table or org.kexi-project.query }; virtual KLocalizedString i18nMessage(const QString& englishMessage, KexiWindow* window) const; private Q_SLOTS: void slotToolboxActionTriggered(bool checked); //! Unchecks toolbox action for @a entity after it is used. void slotItemInserted(const QString& entity); private: QString loadReport(const QString&); class Private; Private* d; }; #endif // _KEXIREPORTPART_H_ diff --git a/kexi/plugins/reports/kexireportview.cpp b/kexi/plugins/reports/kexireportview.cpp index b18ec9dfd6b..01262134be7 100644 --- a/kexi/plugins/reports/kexireportview.cpp +++ b/kexi/plugins/reports/kexireportview.cpp @@ -1,529 +1,530 @@ /* * Kexi Report Plugin * Copyright (C) 2007-2008 by Adam Pigg (adam@piggz.co.uk) - Copyright (C) 2014 Jarosław Staniek + 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); } if (!reportData) { - reportData = new KexiDBReportData(QString(), KexiMainWindowIface::global()->project()->dbConnection(), this); + reportData = new KexiDBReportData(QString(), QString(), + KexiMainWindowIface::global()->project()->dbConnection(), this); } m_preRenderer->setSourceData(reportData); - - m_preRenderer->setName(tempData()->name); + 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(QDomElement e) +KoReportData* KexiReportView::sourceData(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 7263e8dfd13..8389e9c9827 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(QDomElement e); + KoReportData* sourceData(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 ba8281b350d..18af85565ba 100644 --- a/kexi/plugins/reports/kexisourceselector.cpp +++ b/kexi/plugins/reports/kexisourceselector.cpp @@ -1,217 +1,222 @@ /* * Kexi Report Plugin * Copyright (C) 2007-2009 by Adam Pigg (adam@piggz.co.uk) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include "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())); 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->setCurrentIndex(d->internalSource->findText(c.attribute("source"))); + 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()); } 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() { 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(), 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; } #endif #else if (d->internalSource->isSelectionValid()) { d->kexiDBData = new KexiDBReportData(d->internalSource->selectedName(), d->conn); return d->kexiDBData; } #endif return 0; } void KexiSourceSelector::setDataClicked() { emit(setData(sourceData())); } diff --git a/kexi/plugins/reports/krscriptfunctions.cpp b/kexi/plugins/reports/krscriptfunctions.cpp index a8ec9529651..49aa8f040d0 100644 --- a/kexi/plugins/reports/krscriptfunctions.cpp +++ b/kexi/plugins/reports/krscriptfunctions.cpp @@ -1,110 +1,115 @@ /* * Kexi Report Plugin * Copyright (C) 2007-2008 by Adam Pigg - * Copyright (C) 2012 Jarosław Staniek + * Copyright (C) 2012-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 "krscriptfunctions.h" #include #include #include KRScriptFunctions::KRScriptFunctions(const KoReportData* kodata, KexiDB::Connection* conn) { m_cursor = kodata; m_connection = conn; - if (m_connection->tableSchema(kodata->sourceName())) { - m_source = kodata->sourceName(); - } else if (m_connection->querySchema(kodata->sourceName())) { - m_source = m_connection->selectStatement(*(m_connection->querySchema(kodata->sourceName()))); + if (kodata->sourceClass().isEmpty() || kodata->sourceClass() == "org.kexi-project.table") { + if (m_connection->tableSchema(kodata->sourceName())) { + m_source = kodata->sourceName(); + } + } + if (m_source.isEmpty() && (kodata->sourceClass().isEmpty() || kodata->sourceClass() == "org.kexi-project.query")) { + if (m_connection->querySchema(kodata->sourceName())) { + m_source = m_connection->selectStatement(*(m_connection->querySchema(kodata->sourceName()))); + } } } KRScriptFunctions::~KRScriptFunctions() { } void KRScriptFunctions::setWhere(const QString&w) { m_where = w; } qreal KRScriptFunctions::math(const QString &function, const QString &field) { qreal ret; QString sql = "SELECT " + function + '(' + field + ") FROM (" + m_source + ')' ; if (!m_where.isEmpty()) { sql += " WHERE(" + m_where + ')'; } kDebug() << sql; KexiDB::Cursor *curs = m_connection->executeQuery(sql); if (curs) { ret = curs->value(0).toDouble(); } else { ret = 0.0; } delete curs; return ret; } qreal KRScriptFunctions::sum(const QString &field) { return math("SUM", field); } qreal KRScriptFunctions::avg(const QString &field) { return math("AVG", field); } qreal KRScriptFunctions::min(const QString &field) { return math("MIN", field); } qreal KRScriptFunctions::max(const QString &field) { return math("MAX", field); } qreal KRScriptFunctions::count(const QString &field) { return math("COUNT", field); } QVariant KRScriptFunctions::value(const QString &field) { QVariant val; if (!m_cursor) { kDebug() << "No cursor to get value of field " << field; return val; } QStringList fields = m_cursor->fieldNames(); val = m_cursor->value(fields.indexOf(field)); if (val.type() == QVariant::String) { // UTF-8 values are expected so convert this return val.toString().toUtf8(); } return val; } diff --git a/libs/koreport/common/KoReportData.cpp b/libs/koreport/common/KoReportData.cpp index 4586b4dcf69..1189cd5cae2 100644 --- a/libs/koreport/common/KoReportData.cpp +++ b/libs/koreport/common/KoReportData.cpp @@ -1,80 +1,85 @@ /* Calligra/Kexi report engine * Copyright (C) 2007-2010 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 "KoReportData.h" #include KoReportData::~KoReportData() { } KoReportData::SortedField::SortedField() : order(Qt::AscendingOrder) { } QStringList KoReportData::fieldKeys() const { return fieldNames(); } QString KoReportData::sourceName() const { return QString(); } +QString KoReportData::sourceClass() const +{ + return QString(); +} + void KoReportData::setSorting(const QList &sorting) { Q_UNUSED(sorting); } void KoReportData::addExpression(const QString &field, const QVariant &value, int relation) { Q_UNUSED(field); Q_UNUSED(value); Q_UNUSED(relation); } QStringList KoReportData::scriptList(const QString &language) const { Q_UNUSED(language); return QStringList(); } QString KoReportData::scriptCode(const QString &script, const QString &language) const { Q_UNUSED(script); Q_UNUSED(language); return QString(); } QStringList KoReportData::dataSources() const { return QStringList(); } QStringList KoReportData::dataSourceNames() const { return dataSources(); } KoReportData* KoReportData::create(const QString &source) const { Q_UNUSED(source); return 0; } diff --git a/libs/koreport/common/KoReportData.h b/libs/koreport/common/KoReportData.h index aa32fb42e1f..e2925852fd3 100644 --- a/libs/koreport/common/KoReportData.h +++ b/libs/koreport/common/KoReportData.h @@ -1,116 +1,119 @@ /* Calligra/Kexi report engine * Copyright (C) 2007-2010 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 __KOREPORTDATA_H__ #define __KOREPORTDATA_H__ #include "koreport_export.h" #include /** */ class KOREPORT_EXPORT KoReportData { public: virtual ~KoReportData(); //! Describes sorting for single field /*! By default the order is ascending. */ class KOREPORT_EXPORT SortedField { public: SortedField(); QString field; Qt::SortOrder order; }; //!Open the dataset virtual bool open() = 0; //!Close the dataset virtual bool close() = 0; //!Move to the next record virtual bool moveNext() = 0; //!Move to the previous record virtual bool movePrevious() = 0; //!Move to the first record virtual bool moveFirst() = 0; //!Move to the last record virtual bool moveLast() = 0; //!Return the current position in the dataset virtual qint64 at() const = 0; //!Return the total number of records virtual qint64 recordCount() const = 0; //!Return the index number of the field given by nane field virtual int fieldNumber(const QString &field) const = 0; //!Return the list of field names virtual QStringList fieldNames() const = 0; //!Return the list of field keys. Returns fieldNames() by default virtual QStringList fieldKeys() const; //!Return the value of the field at the given position for the current record virtual QVariant value(unsigned int) const = 0; //!Return the value of the field fir the given name for the current record virtual QVariant value(const QString &field) const = 0; //!Return the name of this source virtual QString sourceName() const; + //! @return the class name of this source + virtual QString sourceClass() const; + //!Sets the sorting for the data //!Should be called before open() so that the data source can be edited accordingly //!Default impl does nothing virtual void setSorting(const QList &sorting); /** @brief Adds an expression to the data source */ virtual void addExpression(const QString &field, const QVariant &value, int relation = '='); //!Utility Functions //!TODO These are probably eligable to be moved into a new class //!Allow the reportdata implementation to return a list of possible scripts for a given language virtual QStringList scriptList(const QString& language) const; //!Allow the reportdata implementation to return some script code based on a specific script name //!and a language, as set in the report virtual QString scriptCode(const QString& script, const QString& language) const; //!Return a list of data sources possible for advanced controls virtual QStringList dataSources() const; //!Return a list of data source names possible for advanced controls. //!Returns dataSources() by default virtual QStringList dataSourceNames() const; //! Creates a new instance with data source. Default implementation returns @c nullptr. //! @a source is a driver-specific identifier. //! Owner of the returned pointer is the caller. virtual KoReportData* create(const QString &source) const Q_REQUIRED_RESULT; }; #endif diff --git a/libs/koreport/renderer/KoReportPreRenderer.cpp b/libs/koreport/renderer/KoReportPreRenderer.cpp index 04f3b8836a7..283d8f1a1df 100644 --- a/libs/koreport/renderer/KoReportPreRenderer.cpp +++ b/libs/koreport/renderer/KoReportPreRenderer.cpp @@ -1,716 +1,711 @@ /* * 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; } 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; delete m_kodata; m_postProcText.clear(); return true; } //===========================KoReportPreRenderer=============================== KoReportPreRenderer::KoReportPreRenderer(const QDomElement & pDocument) : d(new KoReportPreRendererPrivate()) { setDom(pDocument); } KoReportPreRenderer::~KoReportPreRenderer() { delete d; } -void KoReportPreRenderer::setName(const QString &n) -{ - d->m_reportData->setName(n); -} - 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) { 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 2369532d888..c2cd873f9d1 100644 --- a/libs/koreport/renderer/KoReportPreRenderer.h +++ b/libs/koreport/renderer/KoReportPreRenderer.h @@ -1,70 +1,65 @@ /* * 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*); void registerScriptObject(QObject*, const QString&); bool generateDocument(); ORODocument *document(); - /** - @brief Set the name of the report so that it can be used internally by the script engine - */ - void setName(const QString &); - 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 a85ae5986be..c7a87b7527b 100644 --- a/libs/koreport/wrtembed/KoReportDesigner.cpp +++ b/libs/koreport/wrtembed/KoReportDesigner.cpp @@ -1,1346 +1,1343 @@ /* * 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; } ///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) { - //kDebug(); - if (kodata) { - m_kordata = kodata; - slotPageButton_Pressed(); - setModified(true); - emit reportDataChanged(); - } + 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); }