diff --git a/src/common/KReportSectionData.cpp b/src/common/KReportSectionData.cpp index af6b7f8b..a1099ef2 100644 --- a/src/common/KReportSectionData.cpp +++ b/src/common/KReportSectionData.cpp @@ -1,216 +1,233 @@ /* This file is part of the KDE project * Copyright (C) 2001-2007 by OpenMFG, LLC (info@openmfg.com) * Copyright (C) 2007-2008 by Adam Pigg (adam@piggz.co.uk) * Copyright (C) 2010 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 "KReportSectionData.h" +#include "KReportDesigner.h" #include "KReportDocument.h" +#include "KReportItemLine.h" #include "KReportPluginInterface.h" #include "KReportPluginManager.h" -#include "KReportItemLine.h" -#include "KReportDesigner.h" +#include "KReportUtils.h" #include "kreport_debug.h" #include #include -KReportSectionData::KReportSectionData(QObject* parent) - : QObject(parent) +KReportSectionData::KReportSectionData(QObject *parent) : KReportSectionData(QDomElement(), parent) { - createProperties(QDomElement()); } -KReportSectionData::KReportSectionData(const QDomElement & elemSource, KReportDocument* report) - : QObject(report) +KReportSectionData::KReportSectionData(const QDomElement &elemSource, QObject *parent) + : QObject(parent) { - setObjectName(elemSource.tagName()); + if (elemSource.isNull()) { + m_type = Type::None; + } else { + setObjectName(elemSource.tagName()); + m_type = sectionTypeFromString(elemSource.attribute(QLatin1String("report:section-type"))); + } - m_type = sectionTypeFromString(elemSource.attribute(QLatin1String("report:section-type"))); createProperties(elemSource); + + if (elemSource.isNull()) { + m_valid = true; + } else { + loadXml(elemSource); + } + m_set->clearModifiedFlags(); +} + +void KReportSectionData::loadXml(const QDomElement &elemSource) +{ if (objectName() != QLatin1String("report:section") || m_type == KReportSectionData::Type::None) { m_valid = false; return; } - m_backgroundColor->setValue(QColor(elemSource.attribute(QLatin1String("fo:background-color")))); - KReportPluginManager* manager = KReportPluginManager::self(); QDomNodeList section = elemSource.childNodes(); for (int nodeCounter = 0; nodeCounter < section.count(); nodeCounter++) { QDomElement elemThis = section.item(nodeCounter).toElement(); QString n = elemThis.tagName(); if (n.startsWith(QLatin1String("report:"))) { + KReportItemBase *krobj = nullptr; QString reportItemName = n.mid(qstrlen("report:")); if (reportItemName == QLatin1String("line")) { KReportItemLine * line = new KReportItemLine(elemThis); - m_objects.append(line); - continue; - } - KReportPluginInterface *plugin = manager->plugin(reportItemName); - if (plugin) { - QObject *obj = plugin->createRendererInstance(elemThis); - if (obj) { - KReportItemBase *krobj = dynamic_cast(obj); - if (krobj) { - m_objects.append(krobj); + krobj = line; + } else { + KReportPluginInterface *plugin = manager->plugin(reportItemName); + if (plugin) { + QObject *obj = plugin->createRendererInstance(elemThis); + if (obj) { + krobj = dynamic_cast(obj); } - continue; } } + if (krobj) { + krobj->propertySet()->clearModifiedFlags(); + m_objects.append(krobj); + } } kreportWarning() << "While parsing section encountered an unknown element: " << n; } qSort(m_objects.begin(), m_objects.end(), zLessThan); m_valid = true; } KReportSectionData::~KReportSectionData() { delete m_set; qDeleteAll(m_objects); } bool KReportSectionData::zLessThan(KReportItemBase* s1, KReportItemBase* s2) { return s1->z() < s2->z(); } bool KReportSectionData::xLessThan(KReportItemBase* s1, KReportItemBase* s2) { return s1->position().toPoint().x() < s2->position().toPoint().x(); } void KReportSectionData::createProperties(const QDomElement & elemSource) { m_set = new KPropertySet(this); KReportDesigner::addMetaProperties(m_set, tr("Section", "Report section"), QLatin1String("kreport-section-element")); m_height = new KProperty("height", KReportUnit(KReportUnit::Type::Centimeter).fromUserValue(2.0), tr("Height")); - m_backgroundColor = new KProperty("background-color", QColor(Qt::white), tr("Background Color")); + m_backgroundColor = new KProperty( + "background-color", + KReportUtils::attr(elemSource, "fo:background-color", QColor(Qt::white)), + tr("Background Color")); m_height->setOption("unit", QLatin1String("cm")); if (!elemSource.isNull()) m_height->setValue(KReportUnit::parseValue(elemSource.attribute(QLatin1String("svg:height"), QLatin1String("2.0cm")))); m_set->addProperty(m_height); m_set->addProperty(m_backgroundColor); + m_set->clearModifiedFlags(); } QString KReportSectionData::name() const { return (objectName() + QLatin1Char('-') + sectionTypeString(m_type)); } QString KReportSectionData::sectionTypeString(KReportSectionData::Type type) { //! @todo use QMap QString sectiontype; switch (type) { case KReportSectionData::Type::PageHeaderAny: sectiontype = QLatin1String("header-page-any"); break; case KReportSectionData::Type::PageHeaderEven: sectiontype = QLatin1String("header-page-even"); break; case KReportSectionData::Type::PageHeaderOdd: sectiontype = QLatin1String("header-page-odd"); break; case KReportSectionData::Type::PageHeaderFirst: sectiontype = QLatin1String("header-page-first"); break; case KReportSectionData::Type::PageHeaderLast: sectiontype = QLatin1String("header-page-last"); break; case KReportSectionData::Type::PageFooterAny: sectiontype = QLatin1String("footer-page-any"); break; case KReportSectionData::Type::PageFooterEven: sectiontype = QLatin1String("footer-page-even"); break; case KReportSectionData::Type::PageFooterOdd: sectiontype = QLatin1String("footer-page-odd"); break; case KReportSectionData::Type::PageFooterFirst: sectiontype = QLatin1String("footer-page-first"); break; case KReportSectionData::Type::PageFooterLast: sectiontype = QLatin1String("footer-page-last"); break; case KReportSectionData::Type::ReportHeader: sectiontype = QLatin1String("header-report"); break; case KReportSectionData::Type::ReportFooter: sectiontype = QLatin1String("footer-report"); break; case KReportSectionData::Type::GroupHeader: sectiontype = QLatin1String("group-header"); break; case KReportSectionData::Type::GroupFooter: sectiontype = QLatin1String("group-footer"); break; case KReportSectionData::Type::Detail: sectiontype = QLatin1String("detail"); break; default: break; } return sectiontype; } KReportSectionData::Type KReportSectionData::sectionTypeFromString(const QString& s) { //! @todo use QMap KReportSectionData::Type type; //kreportDebug() << "Determining section type for " << s; if (s == QLatin1String("header-page-any")) type = KReportSectionData::Type::PageHeaderAny; else if (s == QLatin1String("header-page-even")) type = KReportSectionData::Type::PageHeaderEven; else if (s == QLatin1String("header-page-odd")) type = KReportSectionData::Type::PageHeaderOdd; else if (s == QLatin1String("header-page-first")) type = KReportSectionData::Type::PageHeaderFirst; else if (s == QLatin1String("header-page-last")) type = KReportSectionData::Type::PageHeaderLast; else if (s == QLatin1String("header-report")) type = KReportSectionData::Type::ReportHeader; else if (s == QLatin1String("footer-page-any")) type = KReportSectionData::Type::PageFooterAny; else if (s == QLatin1String("footer-page-even")) type = KReportSectionData::Type::PageFooterEven; else if (s == QLatin1String("footer-page-odd")) type = KReportSectionData::Type::PageFooterOdd; else if (s == QLatin1String("footer-page-first")) type = KReportSectionData::Type::PageFooterFirst; else if (s == QLatin1String("footer-page-last")) type = KReportSectionData::Type::PageFooterLast; else if (s == QLatin1String("footer-report")) type = KReportSectionData::Type::ReportFooter; else if (s == QLatin1String("group-header")) type = KReportSectionData::Type::GroupHeader; else if (s == QLatin1String("group-footer")) type = KReportSectionData::Type::GroupFooter; else if (s == QLatin1String("detail")) type = KReportSectionData::Type::Detail; else type = KReportSectionData::Type::None; return type; } diff --git a/src/common/KReportSectionData.h b/src/common/KReportSectionData.h index fe3cc9a9..b7364f3a 100644 --- a/src/common/KReportSectionData.h +++ b/src/common/KReportSectionData.h @@ -1,119 +1,123 @@ /* This file is part of the KDE project * Copyright (C) 2001-2007 by OpenMFG, LLC (info@openmfg.com) * Copyright (C) 2007-2008 by Adam Pigg (adam@piggz.co.uk) * Copyright (C) 2010 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 KREPORTSECTIONDATA_H #define KREPORTSECTIONDATA_H #include #include class KReportItemBase; class KReportDocument; class QDomElement; namespace Scripting { class Section; } // // KReportSectionData is used to store the information about a specific // section. // A section has a name and optionally extra data. `name' // reportheader, reportfooter, pageheader, pagefooter, groupheader, groupfooter or detail. // In the case of pghead and pgfoot extra would contain the page // designation (firstpage, odd, even or lastpage). class KReportSectionData : public QObject { Q_OBJECT public: enum class Type { None, PageHeaderFirst, PageHeaderOdd, PageHeaderEven, PageHeaderLast, PageHeaderAny, ReportHeader, ReportFooter, PageFooterFirst, PageFooterOdd, PageFooterEven, PageFooterLast, PageFooterAny, GroupHeader, GroupFooter, Detail }; explicit KReportSectionData(QObject* parent = nullptr); - KReportSectionData(const QDomElement &, KReportDocument* report); + + explicit KReportSectionData(const QDomElement &elemSource, QObject* parent = nullptr); + ~KReportSectionData() override; + KPropertySet* propertySet() const { return m_set; } bool isValid() const { return m_valid; } qreal height() const { return m_height->value().toDouble(); } QList objects() const { return m_objects; } QString name() const; QColor backgroundColor() const { return m_backgroundColor->value().value(); } Type type() const { return m_type; } static KReportSectionData::Type sectionTypeFromString(const QString& s); static QString sectionTypeString(KReportSectionData::Type type); protected: KPropertySet *m_set; KProperty *m_height; KProperty *m_backgroundColor; private: void createProperties(const QDomElement & elemSource); + void loadXml(const QDomElement &elemSource); QList m_objects; Type m_type; static bool zLessThan(KReportItemBase* s1, KReportItemBase* s2); static bool xLessThan(KReportItemBase* s1, KReportItemBase* s2); bool m_valid; friend class Scripting::Section; friend class KReportDesignerSection; }; #endif diff --git a/src/wrtembed/KReportDesigner.cpp b/src/wrtembed/KReportDesigner.cpp index b3745447..1561dab9 100644 --- a/src/wrtembed/KReportDesigner.cpp +++ b/src/wrtembed/KReportDesigner.cpp @@ -1,1553 +1,1587 @@ /* This file is part of the KDE project * Copyright (C) 2001-2007 by OpenMFG, LLC * Copyright (C) 2007-2010 by Adam Pigg * Copyright (C) 2011-2017 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 "KReportDesigner.h" #include "KReportDesign_p.h" #include "KReportDesignerItemLine.h" #include "KReportDesignerSection.h" #include "KReportDesignerSectionDetail.h" #include "KReportDesignerSectionDetailGroup.h" #include "KReportDesignerSectionScene.h" #include "KReportDesignerSectionView.h" #include "KReportPageSize.h" #include "KReportPluginInterface.h" #include "KReportPluginManager.h" #include "KReportPluginMetaData.h" #include "KReportPropertiesButton.h" #include "KReportRuler_p.h" #include "KReportSection.h" #include "KReportSectionEditor.h" #include "KReportUtils.h" #include "KReportUtils_p.h" #include "KReportZoomHandler_p.h" #include "kreport_debug.h" #ifdef KREPORT_SCRIPTING #include "KReportScriptSource.h" #endif #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, KProperty* p) { QDomElement e = d->createElement(QLatin1String("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; mouseAction = MouseAction::None; } virtual ~ReportWriterSectionData() { } enum class MouseAction { None = 0, Insert = 1, Grab = 2, MoveStartPoint, MoveEndPoint, ResizeNW = 8, ResizeN, ResizeNE, ResizeE, ResizeSE, ResizeS, ResizeSW, ResizeW }; int selected_x_offset; int selected_y_offset; MouseAction mouseAction; QString itemToInsert; QList copy_list; QList cut_list; }; //! @internal class Q_DECL_HIDDEN KReportDesigner::Private { public: - Private(){} + explicit Private(KReportDesigner *designer); ~Private() { delete dataSource; } + void init(const QDomElement *xml); + +#ifdef KREPORT_SCRIPTING + void updateScripts(); +#endif + + KReportDesigner * const q; + QGridLayout *grid; KReportRuler *hruler; KReportZoomHandler zoomHandler; QVBoxLayout *vboxlayout; KReportPropertiesButton *pageButton; QGraphicsScene *activeScene = nullptr; ReportWriterSectionData sectionData; KReportDesignerSection *reportHeader = nullptr; KReportDesignerSection *pageHeaderFirst = nullptr; KReportDesignerSection *pageHeaderOdd = nullptr; KReportDesignerSection *pageHeaderEven = nullptr; KReportDesignerSection *pageHeaderLast = nullptr; KReportDesignerSection *pageHeaderAny = nullptr; KReportDesignerSection *pageFooterFirst = nullptr; KReportDesignerSection *pageFooterOdd = nullptr; KReportDesignerSection *pageFooterEven = nullptr; KReportDesignerSection *pageFooterLast = nullptr; KReportDesignerSection *pageFooterAny = nullptr; KReportDesignerSection *reportFooter = nullptr; KReportDesignerSectionDetail *detail = nullptr; //Properties KPropertySet set; KPropertySet *itemSet; KProperty *title; KProperty *pageSize; KProperty *orientation; KProperty *unit; KProperty *customPageSize; KProperty *leftMargin; KProperty *rightMargin; KProperty *topMargin; KProperty *bottomMargin; KProperty *showGrid; KProperty *gridDivisions; KProperty *gridSnap; KProperty *labelType; #ifdef KREPORT_SCRIPTING KProperty *script; #endif //Actions QAction *editCutAction; QAction *editCopyAction; QAction *editPasteAction; QAction *editDeleteAction; QAction *sectionEdit; QAction *parameterEdit; QAction *itemRaiseAction; QAction *itemLowerAction; qreal pressX = -1; qreal pressY = -1; qreal releaseX = -1; qreal releaseY = -1; bool modified = false; // true if this document has been modified, false otherwise QString originalInterpreter; //Value of the script interpreter at load time QString originalScript; //Value of the script at load time KReportDataSource *dataSource = nullptr; #ifdef KREPORT_SCRIPTING KReportScriptSource *scriptSource = nullptr; #endif + +private: + void loadXml(const QDomElement &data); }; -KReportDesigner::KReportDesigner(QWidget * parent) - : QWidget(parent), d(new Private()) +KReportDesigner::Private::Private(KReportDesigner *designer) : q(designer) +{ +} + +// (must be init() instead of ctor because we are indirectly depending on initialized KReportDesigner::d here) +void KReportDesigner::Private::init(const QDomElement *xml) { KReportPluginManager::self(); // this loads icons early enough - createProperties(); - createActions(); + q->createProperties(); + q->createActions(); - 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); + grid = new QGridLayout(q); + grid->setSpacing(0); + grid->setMargin(0); + grid->setColumnStretch(1, 1); + grid->setRowStretch(1, 1); + grid->setSizeConstraint(QLayout::SetFixedSize); - d->vboxlayout = new QVBoxLayout(); - d->vboxlayout->setSpacing(0); - d->vboxlayout->setMargin(0); - d->vboxlayout->setSizeConstraint(QLayout::SetFixedSize); + vboxlayout = new QVBoxLayout(); + vboxlayout->setSpacing(0); + vboxlayout->setMargin(0); + vboxlayout->setSizeConstraint(QLayout::SetFixedSize); //Create nice rulers - d->hruler = new KReportRuler(this, Qt::Horizontal, d->zoomHandler); + hruler = new KReportRuler(nullptr, Qt::Horizontal, zoomHandler); - d->pageButton = new KReportPropertiesButton(this); + pageButton = new KReportPropertiesButton; - d->grid->addWidget(d->pageButton, 0, 0); - d->grid->addWidget(d->hruler, 0, 1); - d->grid->addLayout(d->vboxlayout, 1, 0, 1, 2); + grid->addWidget(pageButton, 0, 0); + grid->addWidget(hruler, 0, 1); + grid->addLayout(vboxlayout, 1, 0, 1, 2); - d->pageButton->setMaximumSize(QSize(19, 22)); - d->pageButton->setMinimumSize(QSize(19, 22)); + pageButton->setMaximumSize(QSize(19, 22)); + pageButton->setMinimumSize(QSize(19, 22)); - d->detail = new KReportDesignerSectionDetail(this); - d->vboxlayout->insertWidget(0, d->detail); - - setLayout(d->grid); - - connect(d->pageButton, SIGNAL(released()), this, SLOT(slotPageButton_Pressed())); - emit pagePropertyChanged(d->set); + if (!xml) { + detail = new KReportDesignerSectionDetail(q); + vboxlayout->insertWidget(0, detail); + } - connect(&d->set, SIGNAL(propertyChanged(KPropertySet&,KProperty&)), - this, SLOT(slotPropertyChanged(KPropertySet&,KProperty&))); + connect(pageButton, &KReportPropertiesButton::released, + q, &KReportDesigner::slotPageButton_Pressed); + emit q->pagePropertyChanged(set); - changeSet(&d->set); -} + connect(&set, &KPropertySet::propertyChanged, q, &KReportDesigner::slotPropertyChanged); -KReportDesigner::~KReportDesigner() -{ - delete d; + if (xml) { + loadXml(*xml); + } + set.clearModifiedFlags(); + q->changeSet(&set); } -KReportDesigner::KReportDesigner(QWidget *parent, const QDomElement &data) - : KReportDesigner(parent) +void KReportDesigner::Private::loadXml(const QDomElement &data) { if (data.tagName() != QLatin1String("report:content")) { // arg we got an xml file but not one i know of kreportWarning() << "root element was not "; } //kreportDebug() << 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(); //kreportDebug() << n; if (n == QLatin1String("report:title")) { - setReportTitle(it.firstChild().nodeValue()); + q->setReportTitle(it.firstChild().nodeValue()); #ifdef KREPORT_SCRIPTING } else if (n == QLatin1String("report:script")) { - d->originalInterpreter = it.toElement().attribute(QLatin1String("report:script-interpreter"), QLatin1String("javascript")); - if (d->originalInterpreter.isEmpty()) { - d->originalInterpreter = QLatin1String("javascript"); + originalInterpreter = it.toElement().attribute(QLatin1String("report:script-interpreter"), QLatin1String("javascript")); + if (originalInterpreter.isEmpty()) { + originalInterpreter = QLatin1String("javascript"); } - d->originalScript = it.firstChild().nodeValue(); - d->script->setValue(d->originalScript); + originalScript = it.firstChild().nodeValue(); + script->setValue(originalScript); - if (d->originalInterpreter != QLatin1String("javascript") && d->originalInterpreter != QLatin1String("qtscript")) { + if (originalInterpreter != QLatin1String("javascript") && originalInterpreter != QLatin1String("qtscript")) { QString msg = tr("This report contains scripts of type \"%1\". " "Only scripts written in JavaScript language are " "supported. To prevent losing the scripts, their type " "and content will not be changed unless you change these scripts." - ).arg(d->originalInterpreter); - QMessageBox::warning(this, tr("Unsupported Script Type"), msg); + ).arg(originalInterpreter); + QMessageBox::warning(q, tr("Unsupported Script Type"), msg); } #endif } else if (n == QLatin1String("report:grid")) { - d->showGrid->setValue(it.toElement().attribute(QLatin1String("report:grid-visible"), QString::number(1)).toInt() != 0); - d->gridSnap->setValue(it.toElement().attribute(QLatin1String("report:grid-snap"), QString::number(1)).toInt() != 0); - d->gridDivisions->setValue(it.toElement().attribute(QLatin1String("report:grid-divisions"), QString::number(4)).toInt()); - d->unit->setValue(it.toElement().attribute(QLatin1String("report:page-unit"), QLatin1String("cm"))); + showGrid->setValue(it.toElement().attribute(QLatin1String("report:grid-visible"), QString::number(1)).toInt() != 0); + gridSnap->setValue(it.toElement().attribute(QLatin1String("report:grid-snap"), QString::number(1)).toInt() != 0); + gridDivisions->setValue(it.toElement().attribute(QLatin1String("report:grid-divisions"), QString::number(4)).toInt()); + unit->setValue(it.toElement().attribute(QLatin1String("report:page-unit"), QLatin1String("cm"))); } //! @todo Load page options else if (n == QLatin1String("report:page-style")) { QString pagetype = it.firstChild().nodeValue(); if (pagetype == QLatin1String("predefined")) { - d->pageSize->setValue(it.toElement().attribute(QLatin1String("report:page-size"), QLatin1String("A4"))); + pageSize->setValue(it.toElement().attribute(QLatin1String("report:page-size"), QLatin1String("A4"))); } else if (pagetype == QLatin1String("custom")) { - d->pageSize->setValue(QLatin1String("Custom")); - d->customPageSize->setValue(QSizeF(KReportUnit::parseValue(it.toElement().attribute(QLatin1String("report:custom-page-width"), QLatin1String(""))), + pageSize->setValue(QLatin1String("Custom")); + customPageSize->setValue(QSizeF(KReportUnit::parseValue(it.toElement().attribute(QLatin1String("report:custom-page-width"), QLatin1String(""))), KReportUnit::parseValue(it.toElement().attribute(QLatin1String("report:custom-page-height"), QLatin1String(""))))); } else if (pagetype == QLatin1String("label")) { //! @todo } - d->rightMargin->setValue(KReportUnit::parseValue(it.toElement().attribute(QLatin1String("fo:margin-right"), QLatin1String("1.0cm")))); - d->leftMargin->setValue(KReportUnit::parseValue(it.toElement().attribute(QLatin1String("fo:margin-left"), QLatin1String("1.0cm")))); - d->topMargin->setValue(KReportUnit::parseValue(it.toElement().attribute(QLatin1String("fo:margin-top"), QLatin1String("1.0cm")))); - d->bottomMargin->setValue(KReportUnit::parseValue(it.toElement().attribute(QLatin1String("fo:margin-bottom"), QLatin1String("1.0cm")))); + rightMargin->setValue(KReportUnit::parseValue(it.toElement().attribute(QLatin1String("fo:margin-right"), QLatin1String("1.0cm")))); + leftMargin->setValue(KReportUnit::parseValue(it.toElement().attribute(QLatin1String("fo:margin-left"), QLatin1String("1.0cm")))); + topMargin->setValue(KReportUnit::parseValue(it.toElement().attribute(QLatin1String("fo:margin-top"), QLatin1String("1.0cm")))); + bottomMargin->setValue(KReportUnit::parseValue(it.toElement().attribute(QLatin1String("fo:margin-bottom"), QLatin1String("1.0cm")))); - d->orientation->setValue(it.toElement().attribute(QLatin1String("report:print-orientation"), QLatin1String("portrait"))); + orientation->setValue(it.toElement().attribute(QLatin1String("report:print-orientation"), QLatin1String("portrait"))); } else if (n == QLatin1String("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(); //kreportDebug() << sn; if (sn == QLatin1String("report:section")) { QString sectiontype = sec.toElement().attribute(QLatin1String("report:section-type")); - if (section(KReportSectionData::sectionTypeFromString(sectiontype)) == nullptr) { - insertSection(KReportSectionData::sectionTypeFromString(sectiontype)); - section(KReportSectionData::sectionTypeFromString(sectiontype))->initFromXML(sec); + if (q->section(KReportSectionData::sectionTypeFromString(sectiontype)) == nullptr) { + q->insertSection(KReportSectionData::sectionTypeFromString(sectiontype)); + q->section(KReportSectionData::sectionTypeFromString(sectiontype))->initFromXML(sec); } } else if (sn == QLatin1String("report:detail")) { - KReportDesignerSectionDetail * rsd = new KReportDesignerSectionDetail(this); + KReportDesignerSectionDetail * rsd = new KReportDesignerSectionDetail(q); rsd->initFromXML(&sec); - setDetail(rsd); + q->setDetail(rsd); } } else { kreportWarning() << "Encountered an unknown Element: " << n; } } } } else { kreportWarning() << "Encountered a child node of root that is not an Element"; } } - this->slotPageButton_Pressed(); - emit reportDataChanged(); - slotPropertyChanged(d->set, *d->unit); // set unit for all items - setModified(false); + updateScripts(); + emit q->reportDataChanged(); + q->slotPropertyChanged(set, *unit); // set unit for all items + q->setModified(false); +} + +#ifdef KREPORT_SCRIPTING +void KReportDesigner::Private::updateScripts() +{ + if (scriptSource) { + QStringList sl = scriptSource->scriptList(); + sl.prepend(QString()); // prepend "none" + script->setListData(sl, sl); + } +} +#endif + +// ---- + +KReportDesigner::KReportDesigner(QWidget * parent) + : QWidget(parent), d(new Private(this)) +{ + d->init(nullptr); +} + +KReportDesigner::KReportDesigner(QWidget *parent, const QDomElement &data) + : QWidget(parent), d(new Private(this)) +{ + d->init(&data); +} + +KReportDesigner::~KReportDesigner() +{ + delete d; } ///The saving code QDomElement KReportDesigner::document() const { QDomDocument doc; QString saveInterpreter; QDomElement content = doc.createElement(QLatin1String("report:content")); content.setAttribute(QLatin1String("xmlns:report"), QLatin1String(ns)); content.setAttribute(QLatin1String("xmlns:fo"), QLatin1String("urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0")); content.setAttribute(QLatin1String("xmlns:svg"), QLatin1String("urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0")); doc.appendChild(content); //title content.appendChild(propertyToElement(&doc, d->title)); #ifdef KREPORT_SCRIPTING if (d->originalInterpreter.isEmpty()) { d->originalInterpreter = QLatin1String("javascript"); } saveInterpreter = d->originalInterpreter; if (!d->script->value().toString().isEmpty()) { if (d->script->value().toString() != d->originalScript || d->originalInterpreter == QLatin1String("qtscript") || d->originalInterpreter.isEmpty() ) { //The script has changed so force interpreter to 'javascript'. Also set if was using qtscript saveInterpreter = QLatin1String("javascript"); } } QDomElement scr = propertyToElement(&doc, d->script); scr.setAttribute(QLatin1String("report:script-interpreter"), saveInterpreter); content.appendChild(scr); #endif QDomElement grd = doc.createElement(QLatin1String("report:grid")); KReportUtils::addPropertyAsAttribute(&grd, d->showGrid); KReportUtils::addPropertyAsAttribute(&grd, d->gridDivisions); KReportUtils::addPropertyAsAttribute(&grd, d->gridSnap); KReportUtils::addPropertyAsAttribute(&grd, d->unit); content.appendChild(grd); // pageOptions // -- size QDomElement pagestyle = doc.createElement(QLatin1String("report:page-style")); if (d->pageSize->value().toString() == QLatin1String("Custom")) { pagestyle.appendChild(doc.createTextNode(QLatin1String("custom"))); KReportUtils::setAttribute(&pagestyle, QLatin1String("report:custom-page-width"), d->customPageSize->value().toSizeF().width()); KReportUtils::setAttribute(&pagestyle, QLatin1String("report:custom-page-height"), d->customPageSize->value().toSizeF().height()); } else if (d->pageSize->value().toString() == QLatin1String("Label")) { pagestyle.appendChild(doc.createTextNode(QLatin1String("label"))); pagestyle.setAttribute(QLatin1String("report:page-label-type"), d->labelType->value().toString()); } else { pagestyle.appendChild(doc.createTextNode(QLatin1String("predefined"))); KReportUtils::addPropertyAsAttribute(&pagestyle, d->pageSize); //pagestyle.setAttribute("report:page-size", d->pageSize->value().toString()); } // -- orientation KReportUtils::addPropertyAsAttribute(&pagestyle, d->orientation); // -- margins: save as points, and not localized KReportUtils::setAttribute(&pagestyle, QLatin1String("fo:margin-top"), d->topMargin->value().toDouble()); KReportUtils::setAttribute(&pagestyle, QLatin1String("fo:margin-bottom"), d->bottomMargin->value().toDouble()); KReportUtils::setAttribute(&pagestyle, QLatin1String("fo:margin-right"), d->rightMargin->value().toDouble()); KReportUtils::setAttribute(&pagestyle, QLatin1String("fo:margin-left"), d->leftMargin->value().toDouble()); content.appendChild(pagestyle); QDomElement body = doc.createElement(QLatin1String("report:body")); QDomElement domsection; for (int i = static_cast(KReportSectionData::Type::PageHeaderFirst); i <= static_cast(KReportSectionData::Type::PageFooterAny); ++i) { KReportDesignerSection *sec = section(static_cast(i)); if (sec) { domsection = doc.createElement(QLatin1String("report:section")); domsection.setAttribute( QLatin1String("report:section-type"), KReportSectionData::sectionTypeString(static_cast(i))); sec->buildXML(&doc, &domsection); body.appendChild(domsection); } } QDomElement detail = doc.createElement(QLatin1String("report:detail")); d->detail->buildXML(&doc, &detail); body.appendChild(detail); content.appendChild(body); return content; } void KReportDesigner::slotSectionEditor() { KReportSectionEditor se(this); (void)se.exec(); } void KReportDesigner::setDataSource(KReportDataSource* source) { if (d->dataSource == source) { return; } delete d->dataSource; d->dataSource = source; slotPageButton_Pressed(); setModified(true); emit reportDataChanged(); } #ifdef KREPORT_SCRIPTING void KReportDesigner::setScriptSource(KReportScriptSource* source) { d->scriptSource = source; } #endif KReportDesignerSection * KReportDesigner::section(KReportSectionData::Type type) const { KReportDesignerSection *sec; switch (type) { case KReportSectionData::Type::PageHeaderAny: sec = d->pageHeaderAny; break; case KReportSectionData::Type::PageHeaderEven: sec = d->pageHeaderEven; break; case KReportSectionData::Type::PageHeaderOdd: sec = d->pageHeaderOdd; break; case KReportSectionData::Type::PageHeaderFirst: sec = d->pageHeaderFirst; break; case KReportSectionData::Type::PageHeaderLast: sec = d->pageHeaderLast; break; case KReportSectionData::Type::PageFooterAny: sec = d->pageFooterAny; break; case KReportSectionData::Type::PageFooterEven: sec = d->pageFooterEven; break; case KReportSectionData::Type::PageFooterOdd: sec = d->pageFooterOdd; break; case KReportSectionData::Type::PageFooterFirst: sec = d->pageFooterFirst; break; case KReportSectionData::Type::PageFooterLast: sec = d->pageFooterLast; break; case KReportSectionData::Type::ReportHeader: sec = d->reportHeader; break; case KReportSectionData::Type::ReportFooter: sec = d->reportFooter; break; default: sec = nullptr; } return sec; } KReportDesignerSection* KReportDesigner::createSection() { return new KReportDesignerSection(this, d->zoomHandler); } void KReportDesigner::removeSection(KReportSectionData::Type type) { KReportDesignerSection* sec = section(type); if (sec) { delete sec; switch (type) { case KReportSectionData::Type::PageHeaderAny: d->pageHeaderAny = nullptr; break; case KReportSectionData::Type::PageHeaderEven: sec = d->pageHeaderEven = nullptr; break; case KReportSectionData::Type::PageHeaderOdd: d->pageHeaderOdd = nullptr; break; case KReportSectionData::Type::PageHeaderFirst: d->pageHeaderFirst = nullptr; break; case KReportSectionData::Type::PageHeaderLast: d->pageHeaderLast = nullptr; break; case KReportSectionData::Type::PageFooterAny: d->pageFooterAny = nullptr; break; case KReportSectionData::Type::PageFooterEven: d->pageFooterEven = nullptr; break; case KReportSectionData::Type::PageFooterOdd: d->pageFooterOdd = nullptr; break; case KReportSectionData::Type::PageFooterFirst: d->pageFooterFirst = nullptr; break; case KReportSectionData::Type::PageFooterLast: d->pageFooterLast = nullptr; break; case KReportSectionData::Type::ReportHeader: d->reportHeader = nullptr; break; case KReportSectionData::Type::ReportFooter: d->reportFooter = nullptr; break; default: sec = nullptr; } setModified(true); adjustSize(); } } void KReportDesigner::insertSection(KReportSectionData::Type type) { KReportDesignerSection* sec = section(type); if (!sec) { int idx = 0; for (int i = static_cast(KReportSectionData::Type::PageHeaderFirst); i <= static_cast(type); ++i) { if (section(static_cast(i))) idx++; } if (type > KReportSectionData::Type::ReportHeader) idx++; //kreportDebug() << idx; KReportDesignerSection *rs = createSection(); d->vboxlayout->insertWidget(idx, rs); switch (type) { case KReportSectionData::Type::PageHeaderAny: rs->setTitle(tr("Page Header (Any)")); d->pageHeaderAny = rs; break; case KReportSectionData::Type::PageHeaderEven: rs->setTitle(tr("Page Header (Even)")); d->pageHeaderEven = rs; break; case KReportSectionData::Type::PageHeaderOdd: rs->setTitle(tr("Page Header (Odd)")); d->pageHeaderOdd = rs; break; case KReportSectionData::Type::PageHeaderFirst: rs->setTitle(tr("Page Header (First)")); d->pageHeaderFirst = rs; break; case KReportSectionData::Type::PageHeaderLast: rs->setTitle(tr("Page Header (Last)")); d->pageHeaderLast = rs; break; case KReportSectionData::Type::PageFooterAny: rs->setTitle(tr("Page Footer (Any)")); d->pageFooterAny = rs; break; case KReportSectionData::Type::PageFooterEven: rs->setTitle(tr("Page Footer (Even)")); d->pageFooterEven = rs; break; case KReportSectionData::Type::PageFooterOdd: rs->setTitle(tr("Page Footer (Odd)")); d->pageFooterOdd = rs; break; case KReportSectionData::Type::PageFooterFirst: rs->setTitle(tr("Page Footer (First)")); d->pageFooterFirst = rs; break; case KReportSectionData::Type::PageFooterLast: rs->setTitle(tr("Page Footer (Last)")); d->pageFooterLast = rs; break; case KReportSectionData::Type::ReportHeader: rs->setTitle(tr("Report Header")); d->reportHeader = rs; break; case KReportSectionData::Type::ReportFooter: rs->setTitle(tr("Report Footer")); d->reportFooter = rs; break; //These sections cannot be inserted this way case KReportSectionData::Type::None: case KReportSectionData::Type::GroupHeader: case KReportSectionData::Type::GroupFooter: case KReportSectionData::Type::Detail: break; } rs->show(); setModified(true); adjustSize(); emit pagePropertyChanged(d->set); } } void KReportDesigner::setReportTitle(const QString & str) { if (reportTitle() != str) { d->title->setValue(str); setModified(true); } } KPropertySet* KReportDesigner::propertySet() const { return &d->set; } KPropertySet* KReportDesigner::selectedItemPropertySet() const { return d->itemSet; } KReportDataSource *KReportDesigner::reportDataSource() const { return d->dataSource; } KReportDesignerSectionDetail * KReportDesigner::detailSection() const { return d->detail; } QString KReportDesigner::reportTitle() const { return d->title->value().toString(); } bool KReportDesigner::isModified() const { return d->modified; } void KReportDesigner::setModified(bool modified) { d->modified = modified; if (d->modified) { emit dirty(); } } QStringList KReportDesigner::fieldNames() const { QStringList qs; qs << QString(); if (d->dataSource) qs << d->dataSource->fieldNames(); return qs; } QStringList KReportDesigner::fieldKeys() const { QStringList qs; qs << QString(); if (d->dataSource) qs << d->dataSource->fieldKeys(); return qs; } void KReportDesigner::createProperties() { KReportDesigner::addMetaProperties(&d->set, tr("Report", "Main report element"), QLatin1String("kreport-report-element")); connect(&d->set, SIGNAL(propertyChanged(KPropertySet&,KProperty&)), this, SLOT(slotPropertyChanged(KPropertySet&,KProperty&))); d->title = new KProperty("title", QLatin1String("Report"), tr("Title"), tr("Report Title")); KPropertyListData *listData = new KPropertyListData(KReportPageSize::pageFormatKeys(), KReportPageSize::pageFormatNames()); QVariant defaultKey = KReportPageSize::pageSizeKey(KReportPageSize::defaultSize()); - d->pageSize = new KProperty("page-size", listData, defaultKey, tr("Page Size")); - + d->pageSize = new KProperty("page-size", listData, defaultKey, tr("Page Size")); + d->customPageSize = new KProperty("custom-page-size", QSizeF(KReportUnit(KReportUnit::Type::Centimeter).fromUserValue(10), KReportUnit(KReportUnit::Type::Centimeter).fromUserValue(10)), tr("Custom Page Size"), tr("Custom Page Size"), KProperty::SizeF); listData = new KPropertyListData({ QLatin1String("portrait"), QLatin1String("landscape") }, QVariantList{ tr("Portrait"), tr("Landscape") }); d->orientation = new KProperty("print-orientation", listData, QLatin1String("portrait"), tr("Page Orientation")); QList types(KReportUnit::allTypes()); types.removeOne(KReportUnit::Type::Pixel); listData = new KPropertyListData(KReportUnit::symbols(types), KReportUnit::descriptions(types)); d->unit = new KProperty("page-unit", listData, QLatin1String("cm"), tr("Page Unit")); d->showGrid = new KProperty("grid-visible", true, tr("Show Grid")); d->gridSnap = new KProperty("grid-snap", true, tr("Snap to Grid")); d->gridDivisions = new KProperty("grid-divisions", 4, tr("Grid Divisions")); d->leftMargin = new KProperty("margin-left", KReportUnit(KReportUnit::Type::Centimeter).fromUserValue(1.0), tr("Left Margin"), tr("Left Margin"), KProperty::Double); d->rightMargin = new KProperty("margin-right", KReportUnit(KReportUnit::Type::Centimeter).fromUserValue(1.0), tr("Right Margin"), tr("Right Margin"), KProperty::Double); d->topMargin = new KProperty("margin-top", KReportUnit(KReportUnit::Type::Centimeter).fromUserValue(1.0), tr("Top Margin"), tr("Top Margin"), KProperty::Double); d->bottomMargin = new KProperty("margin-bottom", KReportUnit(KReportUnit::Type::Centimeter).fromUserValue(1.0), tr("Bottom Margin"), tr("Bottom Margin"), KProperty::Double); d->leftMargin->setOption("unit", QLatin1String("cm")); d->rightMargin->setOption("unit", QLatin1String("cm")); d->topMargin->setOption("unit", QLatin1String("cm")); d->bottomMargin->setOption("unit", QLatin1String("cm")); d->set.addProperty(d->title); d->set.addProperty(d->pageSize); d->set.addProperty(d->customPageSize); d->set.addProperty(d->orientation); d->set.addProperty(d->unit); d->set.addProperty(d->gridSnap); d->set.addProperty(d->showGrid); d->set.addProperty(d->gridDivisions); d->set.addProperty(d->leftMargin); d->set.addProperty(d->rightMargin); d->set.addProperty(d->topMargin); d->set.addProperty(d->bottomMargin); #ifdef KREPORT_SCRIPTING d->script = new KProperty("script", new KPropertyListData, QVariant(), tr("Object Script")); d->set.addProperty(d->script); #endif - } /** @brief Handle property changes */ void KReportDesigner::slotPropertyChanged(KPropertySet &s, KProperty &p) { setModified(true); emit pagePropertyChanged(s); if (p.name() == "page-unit") { d->hruler->setUnit(pageUnit()); QString newstr = d->set.property("page-unit").value().toString(); d->set.property("margin-left").setOption("unit", newstr); d->set.property("margin-right").setOption("unit", newstr); d->set.property("margin-top").setOption("unit", newstr); d->set.property("margin-bottom").setOption("unit", newstr); d->set.property("custom-page-size").setOption("unit", newstr); } } void KReportDesigner::slotPageButton_Pressed() { #ifdef KREPORT_SCRIPTING - if (d->scriptSource) { - QStringList sl = d->scriptSource->scriptList(); - sl.prepend(QString()); - d->script->setListData(sl, sl); - } + d->updateScripts(); changeSet(&d->set); #endif } QSize KReportDesigner::sizeHint() const { int w = 0; int h = 0; if (d->pageFooterAny) h += d->pageFooterAny->sizeHint().height(); if (d->pageFooterEven) h += d->pageFooterEven->sizeHint().height(); if (d->pageFooterFirst) h += d->pageFooterFirst->sizeHint().height(); if (d->pageFooterLast) h += d->pageFooterLast->sizeHint().height(); if (d->pageFooterOdd) h += d->pageFooterOdd->sizeHint().height(); if (d->pageHeaderAny) h += d->pageHeaderAny->sizeHint().height(); if (d->pageHeaderEven) h += d->pageHeaderEven->sizeHint().height(); if (d->pageHeaderFirst) h += d->pageHeaderFirst->sizeHint().height(); if (d->pageHeaderLast) h += d->pageHeaderLast->sizeHint().height(); if (d->pageHeaderOdd) h += d->pageHeaderOdd->sizeHint().height(); if (d->reportHeader) h += d->reportHeader->sizeHint().height(); if (d->reportFooter) { h += d->reportFooter->sizeHint().height(); } if (d->detail) { h += d->detail->sizeHint().height(); w += d->detail->sizeHint().width(); } h += d->hruler->height(); return QSize(w, h); } int KReportDesigner::pageWidthPx() const { QSize pageSizePx; int pageWidth; - + if (d->set.property("page-size").value().toString() == QLatin1String("Custom")) { KReportUnit unit = pageUnit(); - + QSizeF customSize = d->set.property("custom-page-size").value().toSizeF(); QPageLayout layout(QPageSize(customSize, QPageSize::Point, QString(), QPageSize::ExactMatch), d->set.property("print-orientation").value().toString() == QLatin1String("portrait") ? QPageLayout::Portrait : QPageLayout::Landscape, QMarginsF(0,0,0,0)); - + pageSizePx = layout.fullRectPixels(KReportPrivate::dpiX()).size(); } else { QPageLayout layout = QPageLayout( QPageSize(KReportPageSize::pageSize(d->set.property("page-size").value().toString())), d->set.property("print-orientation").value().toString() == QLatin1String("portrait") ? QPageLayout::Portrait : QPageLayout::Landscape, QMarginsF(0,0,0,0)); pageSizePx = layout.fullRectPixels(KReportPrivate::dpiX()).size(); } - + pageWidth = pageSizePx.width(); pageWidth = pageWidth - POINT_TO_INCH(d->set.property("margin-left").value().toDouble()) * KReportPrivate::dpiX(); pageWidth = pageWidth - POINT_TO_INCH(d->set.property("margin-right").value().toDouble()) * KReportPrivate::dpiX(); return pageWidth; } void KReportDesigner::resizeEvent(QResizeEvent * event) { Q_UNUSED(event); d->hruler->setRulerLength(pageWidthPx()); } void KReportDesigner::setDetail(KReportDesignerSectionDetail *rsd) { if (!d->detail) { int idx = 0; if (d->pageHeaderFirst) idx++; if (d->pageHeaderOdd) idx++; if (d->pageHeaderEven) idx++; if (d->pageHeaderLast) idx++; if (d->pageHeaderAny) idx++; if (d->reportHeader) idx++; d->detail = rsd; d->vboxlayout->insertWidget(idx, d->detail); } } -void KReportDesigner::deleteDetail() -{ - delete d->detail; - d->detail = nullptr; -} KReportUnit KReportDesigner::pageUnit() const { const QString symbol = d->unit->value().toString(); KReportUnit unit(KReportUnit::symbolToType(symbol)); return unit.isValid() ? unit : DEFAULT_UNIT; } void KReportDesigner::setGridOptions(bool vis, int div) { d->showGrid->setValue(QVariant(vis)); d->gridDivisions->setValue(div); } // // methods for the sectionMouse*Event() // void KReportDesigner::sectionContextMenuEvent(KReportDesignerSectionScene * s, QGraphicsSceneContextMenuEvent * e) { Q_UNUSED(s); QMenu pop; bool itemsSelected = selectionCount() > 0; if (itemsSelected) { //! @todo KF5 use KStandardAction QAction *a = new QAction(QIcon::fromTheme(QLatin1String("edit-cut")), tr("Cut"), this); connect(a, SIGNAL(triggered()), this, SLOT(slotEditCut())); pop.addAction(a); //! @todo KF5 use KStandardAction a = new QAction(QIcon::fromTheme(QLatin1String("edit-copy")), tr("Copy"), this); connect(a, SIGNAL(triggered()), this, SLOT(slotEditCopy())); pop.addAction(a); } if (!d->sectionData.copy_list.isEmpty()) { QAction *a = new QAction(QIcon::fromTheme(QLatin1String("edit-paste")), tr("Paste"), this); connect(a, SIGNAL(triggered()), this, SLOT(slotEditPaste())); pop.addAction(a); } if (itemsSelected) { pop.addSeparator(); //! @todo KF5 use KStandard* //const KGuiItem del = KStandardGuiItem::del(); //a->setToolTip(del.toolTip()); //a->setShortcut(QKeySequence(QKeySequence::Delete)); QAction *a = new QAction(QIcon::fromTheme(QLatin1String("edit-delete")), tr("Delete"), this); connect(a, SIGNAL(triggered()), SLOT(slotEditDelete())); pop.addAction(a); } if (!pop.actions().isEmpty()) { pop.exec(e->screenPos()); } } void KReportDesigner::sectionMousePressEvent(KReportDesignerSectionView * v, QMouseEvent * e) { Q_UNUSED(v); d->pressX = e->pos().x(); d->pressY = e->pos().y(); } void KReportDesigner::sectionMouseReleaseEvent(KReportDesignerSectionView * v, QMouseEvent * e) { e->accept(); d->releaseX = e->pos().x(); d->releaseY = e->pos().y(); if (e->button() == Qt::LeftButton) { QPointF pos(d->pressX, d->pressY); QPointF end(d->releaseX, d->releaseY); if (d->releaseY >= v->scene()->height()) { d->releaseY = v->scene()->height(); end.setY(v->scene()->height()); } if (d->releaseX >= v->scene()->width()) { d->releaseX = v->scene()->width(); end.setX(v->scene()->width()); } if (d->sectionData.mouseAction == ReportWriterSectionData::MouseAction::Insert) { QGraphicsItem * item = nullptr; QString classString; QString iconName; if (d->sectionData.itemToInsert == QLatin1String("org.kde.kreport.line")) { item = new KReportDesignerItemLine(v->designer(), v->scene(), pos, end); classString = tr("Line", "Report line element"); iconName = QLatin1String("kreport-line-element"); } else { KReportPluginManager* pluginManager = KReportPluginManager::self(); KReportPluginInterface *plug = pluginManager->plugin(d->sectionData.itemToInsert); if (plug) { QObject *obj = plug->createDesignerInstance(v->designer(), v->scene(), pos); if (obj) { item = dynamic_cast(obj); classString = plug->metaData()->name(); iconName = plug->metaData()->iconName(); } } else { kreportWarning() << "attempted to insert an unknown item"; } } if (item) { item->setVisible(true); item->setSelected(true); KReportItemBase* baseReportItem = dynamic_cast(item); if (baseReportItem) { baseReportItem->setUnit(pageUnit()); KPropertySet *set = baseReportItem->propertySet(); KReportDesigner::addMetaProperties(set, classString, iconName); + set->clearModifiedFlags(); changeSet(set); if (v && v->designer()) { v->designer()->setModified(true); } emit itemInserted(d->sectionData.itemToInsert); } } d->sectionData.mouseAction = ReportWriterSectionData::MouseAction::None; d->sectionData.itemToInsert.clear(); unsetSectionCursor(); } } } unsigned int KReportDesigner::selectionCount() const { if (activeScene()) return activeScene()->selectedItems().count(); else return 0; } void KReportDesigner::changeSet(KPropertySet *s) { //Set the checked state of the report properties button if (s == &d->set) d->pageButton->setCheckState(Qt::Checked); else d->pageButton->setCheckState(Qt::Unchecked); if (d->itemSet != s) { d->itemSet = s; emit propertySetChanged(); } } // // Actions // void KReportDesigner::slotItem(const QString &entity) { //kreportDebug() << entity; d->sectionData.mouseAction = ReportWriterSectionData::MouseAction::Insert; d->sectionData.itemToInsert = entity; setSectionCursor(QCursor(Qt::CrossCursor)); } void KReportDesigner::slotEditDelete() { QGraphicsItem * item = nullptr; bool modified = false; while (selectionCount() > 0) { item = activeScene()->selectedItems().value(0); if (item) { QGraphicsScene * scene = item->scene(); delete item; scene->update(); d->sectionData.mouseAction = ReportWriterSectionData::MouseAction::None; modified = true; } } activeScene()->selectedItems().clear(); /*! @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. */ d->sectionData.cut_list.clear(); d->sectionData.copy_list.clear(); if (modified) { setModified(true); } } void KReportDesigner::slotEditCut() { if (selectionCount() > 0) { //First delete any items that are curerntly in the list //so as not to leak memory qDeleteAll(d->sectionData.cut_list); d->sectionData.cut_list.clear(); QGraphicsItem * item = activeScene()->selectedItems().first(); bool modified = false; if (item) { d->sectionData.copy_list.clear(); foreach(QGraphicsItem *item, activeScene()->selectedItems()) { d->sectionData.cut_list.append(dynamic_cast(item)); d->sectionData.copy_list.append(dynamic_cast(item)); } foreach(QGraphicsItem *item, activeScene()->selectedItems()) { activeScene()->removeItem(item); activeScene()->update(); modified = true; } d->sectionData.selected_x_offset = 10; d->sectionData.selected_y_offset = 10; } if (modified) { setModified(true); } } } void KReportDesigner::slotEditCopy() { if (selectionCount() < 1) return; QGraphicsItem * item = activeScene()->selectedItems().first(); if (item) { d->sectionData.copy_list.clear(); foreach(QGraphicsItem *item, activeScene()->selectedItems()) { d->sectionData.copy_list.append(dynamic_cast(item)); } d->sectionData.selected_x_offset = 10; d->sectionData.selected_y_offset = 10; } } void KReportDesigner::slotEditPaste() { // call the editPaste function passing it a reportsection slotEditPaste(activeScene()); } void KReportDesigner::slotEditPaste(QGraphicsScene * canvas) { // paste a new item of the copy we have in the specified location if (!d->sectionData.copy_list.isEmpty()) { QList activeItems = canvas->selectedItems(); QGraphicsItem *activeItem = nullptr; if (activeItems.count() == 1) { activeItem = activeItems.first(); } canvas->clearSelection(); d->sectionData.mouseAction = ReportWriterSectionData::MouseAction::None; //! @todo this code sucks :) //! The setPos calls only work AFTER the name has been set ?!?!? foreach(KReportDesignerItemBase *item, d->sectionData.copy_list) { KReportItemBase *obj = dynamic_cast(item); const QString type = obj ? obj->typeName() : QLatin1String("object"); //kreportDebug() << type; KReportDesignerItemBase *ent = item->clone(); KReportItemBase *new_obj = dynamic_cast(ent); if (new_obj) { new_obj->setEntityName(suggestEntityName(type)); if (activeItem) { new_obj->setPosition(KReportItemBase::positionFromScene(QPointF(activeItem->x() + 10, activeItem->y() + 10))); } else { new_obj->setPosition(KReportItemBase::positionFromScene(QPointF(0, 0))); } + new_obj->propertySet()->clearModifiedFlags(); changeSet(new_obj->propertySet()); } QGraphicsItem *pasted_ent = dynamic_cast(ent); if (pasted_ent) { pasted_ent->setSelected(true); canvas->addItem(pasted_ent); pasted_ent->show(); d->sectionData.mouseAction = ReportWriterSectionData::MouseAction::Grab; setModified(true); } } } } void KReportDesigner::slotRaiseSelected() { dynamic_cast(activeScene())->raiseSelected(); } void KReportDesigner::slotLowerSelected() { dynamic_cast(activeScene())->lowerSelected(); } QGraphicsScene* KReportDesigner::activeScene() const { return d->activeScene; } void KReportDesigner::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(); } QString KReportDesigner::suggestEntityName(const QString &name) const { KReportDesignerSection *sec; int itemCount = 0; // Count items in the main sections for (int i = static_cast(KReportSectionData::Type::PageHeaderFirst); i <= static_cast(KReportSectionData::Type::PageFooterAny); i++) { sec = section(static_cast(i)); if (sec) { const QGraphicsItemList l = sec->items(); itemCount += l.count(); } } if (d->detail) { //Count items in the group headers/footers for (int i = 0; i < d->detail->groupSectionCount(); i++) { sec = d->detail->groupSection(i)->groupHeader(); if (sec) { const QGraphicsItemList l = sec->items(); itemCount += l.count(); } sec = d->detail->groupSection(i)->groupFooter(); if (sec) { const QGraphicsItemList l = sec->items(); itemCount += l.count(); } } sec = d->detail->detailSection(); if (sec) { const QGraphicsItemList l = sec->items(); itemCount += l.count(); } } while (!isEntityNameUnique(name + QString::number(itemCount))) { itemCount++; } return name + QString::number(itemCount); } bool KReportDesigner::isEntityNameUnique(const QString &name, KReportItemBase* ignore) const { KReportDesignerSection *sec; bool unique = true; // Check items in the main sections for (int i = static_cast(KReportSectionData::Type::PageHeaderFirst); i <= static_cast(KReportSectionData::Type::PageFooterAny); i++) { sec = section(static_cast(i)); if (sec) { const QGraphicsItemList l = sec->items(); for (QGraphicsItemList::const_iterator it = l.constBegin(); it != l.constEnd(); ++it) { KReportItemBase* itm = dynamic_cast(*it); if (itm && itm->entityName() == name && itm != ignore) { unique = false; break; } } if (!unique) break; } } //Count items in the group headers/footers if (unique && d->detail) { for (int i = 0; i < d->detail->groupSectionCount(); ++i) { sec = d->detail->groupSection(i)->groupHeader(); if (sec) { const QGraphicsItemList l = sec->items(); for (QGraphicsItemList::const_iterator it = l.constBegin(); it != l.constEnd(); ++it) { KReportItemBase* itm = dynamic_cast(*it); if (itm && itm->entityName() == name && itm != ignore) { unique = false; break; } } } sec = d->detail->groupSection(i)->groupFooter(); if (unique && sec) { const QGraphicsItemList l = sec->items(); for (QGraphicsItemList::const_iterator it = l.constBegin(); it != l.constEnd(); ++it) { KReportItemBase* itm = dynamic_cast(*it); if (itm && itm->entityName() == name && itm != ignore) { unique = false; break; } } } } } if (unique && d->detail) { sec = d->detail->detailSection(); if (sec) { const QGraphicsItemList l = sec->items(); for (QGraphicsItemList::const_iterator it = l.constBegin(); it != l.constEnd(); ++it) { KReportItemBase* itm = dynamic_cast(*it); if (itm && itm->entityName() == name && 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 KReportDesigner::itemActions(QActionGroup* group) { KReportPluginManager* manager = KReportPluginManager::self(); QList actList = manager->createActions(group); //! @todo make line a real plugin so this isn't needed: QAction *act = new QAction(QIcon::fromTheme(QLatin1String("kreport-line-element")), tr("Line"), group); act->setObjectName(QLatin1String("org.kde.kreport.line")); act->setData(9); act->setCheckable(true); 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(QLatin1String("separator"), group); sep->setSeparator(true); actList.insert(i-1, sep); sepInserted = true; } if (group) { group->addAction(a); } } return actList; } QList< QAction* > KReportDesigner::designerActions() { QList al; QAction *sep = new QAction(QString(), this); sep->setSeparator(true); al << d->editCutAction << d->editCopyAction << d->editPasteAction << d->editDeleteAction << sep << d->sectionEdit << sep << d->itemLowerAction << d->itemRaiseAction; return al; } void KReportDesigner::createActions() { d->editCutAction = new QAction(QIcon::fromTheme(QLatin1String("edit-cut")), tr("Cu&t"), this); d->editCutAction->setObjectName(QLatin1String("edit_cut")); d->editCutAction->setToolTip(tr("Cut selection to clipboard")); d->editCutAction->setShortcuts(KStandardShortcut::cut()); d->editCutAction->setProperty("iconOnly", true); d->editCopyAction = new QAction(QIcon::fromTheme(QLatin1String("edit-copy")), tr("&Copy"), this); d->editCopyAction->setObjectName(QLatin1String("edit_copy")); d->editCopyAction->setToolTip(tr("Copy selection to clipboard")); d->editCopyAction->setShortcuts(KStandardShortcut::copy()); d->editCopyAction->setProperty("iconOnly", true); d->editPasteAction = new QAction(QIcon::fromTheme(QLatin1String("edit-paste")), tr("&Paste"), this); d->editPasteAction->setObjectName(QLatin1String("edit_paste")); d->editPasteAction->setToolTip(tr("Paste clipboard content")); d->editPasteAction->setShortcuts(KStandardShortcut::paste()); d->editPasteAction->setProperty("iconOnly", true); const KGuiItem del = KStandardGuiItem::del(); d->editDeleteAction = new QAction(del.icon(), del.text(), this); d->editDeleteAction->setObjectName(QLatin1String("edit_delete")); d->editDeleteAction->setToolTip(del.toolTip()); d->editDeleteAction->setWhatsThis(del.whatsThis()); d->editDeleteAction->setProperty("iconOnly", true); d->sectionEdit = new QAction(tr("Edit Sections"), this); d->sectionEdit->setObjectName(QLatin1String("section_edit")); d->itemRaiseAction = new QAction(QIcon::fromTheme(QLatin1String("arrow-up")), tr("Raise"), this); d->itemRaiseAction->setObjectName(QLatin1String("item_raise")); d->itemLowerAction = new QAction(QIcon::fromTheme(QLatin1String("arrow-down")), tr("Lower"), this); d->itemLowerAction->setObjectName(QLatin1String("item_lower")); //Edit Actions connect(d->editCutAction, SIGNAL(triggered(bool)), this, SLOT(slotEditCut())); connect(d->editCopyAction, SIGNAL(triggered(bool)), this, SLOT(slotEditCopy())); connect(d->editPasteAction, SIGNAL(triggered(bool)), this, SLOT(slotEditPaste())); connect(d->editDeleteAction, SIGNAL(triggered(bool)), this, SLOT(slotEditDelete())); connect(d->sectionEdit, SIGNAL(triggered(bool)), this, SLOT(slotSectionEditor())); //Raise/Lower connect(d->itemRaiseAction, SIGNAL(triggered(bool)), this, SLOT(slotRaiseSelected())); connect(d->itemLowerAction, SIGNAL(triggered(bool)), this, SLOT(slotLowerSelected())); } void KReportDesigner::setSectionCursor(const QCursor& c) { if (d->pageFooterAny) d->pageFooterAny->setSectionCursor(c); if (d->pageFooterEven) d->pageFooterEven->setSectionCursor(c); if (d->pageFooterFirst) d->pageFooterFirst->setSectionCursor(c); if (d->pageFooterLast) d->pageFooterLast->setSectionCursor(c); if (d->pageFooterOdd) d->pageFooterOdd->setSectionCursor(c); if (d->pageHeaderAny) d->pageHeaderAny->setSectionCursor(c); if (d->pageHeaderEven) d->pageHeaderEven->setSectionCursor(c); if (d->pageHeaderFirst) d->pageHeaderFirst->setSectionCursor(c); if (d->pageHeaderLast) d->pageHeaderLast->setSectionCursor(c); if (d->pageHeaderOdd) d->pageHeaderOdd->setSectionCursor(c); if (d->detail) d->detail->setSectionCursor(c); } void KReportDesigner::unsetSectionCursor() { if (d->pageFooterAny) d->pageFooterAny->unsetSectionCursor(); if (d->pageFooterEven) d->pageFooterEven->unsetSectionCursor(); if (d->pageFooterFirst) d->pageFooterFirst->unsetSectionCursor(); if (d->pageFooterLast) d->pageFooterLast->unsetSectionCursor(); if (d->pageFooterOdd) d->pageFooterOdd->unsetSectionCursor(); if (d->pageHeaderAny) d->pageHeaderAny->unsetSectionCursor(); if (d->pageHeaderEven) d->pageHeaderEven->unsetSectionCursor(); if (d->pageHeaderFirst) d->pageHeaderFirst->unsetSectionCursor(); if (d->pageHeaderLast) d->pageHeaderLast->unsetSectionCursor(); if (d->pageHeaderOdd) d->pageHeaderOdd->unsetSectionCursor(); if (d->detail) d->detail->unsetSectionCursor(); } qreal KReportDesigner::countSelectionHeight() const { if (d->releaseY == -1 || d->pressY == -1) { return -1; } return qAbs(d->releaseY - d->pressY); } qreal KReportDesigner::countSelectionWidth() const { if (d->releaseX == -1 || d->pressX == -1) { return -1; } return qAbs(d->releaseX - d->pressX); } qreal KReportDesigner::getSelectionPressX() const { return d->pressX; } qreal KReportDesigner::getSelectionPressY() const { return d->pressY; } QPointF KReportDesigner::getPressPoint() const { return QPointF(d->pressX, d->pressY); } QPointF KReportDesigner::getReleasePoint() const { return QPointF(d->releaseX, d->releaseY); } void KReportDesigner::plugItemActions(const QList &actList) { foreach(QAction *a, actList) { connect(a, SIGNAL(triggered(bool)), this, SLOT(slotItemTriggered(bool))); } } void KReportDesigner::slotItemTriggered(bool checked) { if (!checked) { return; } QObject *theSender = sender(); if (!theSender) { return; } slotItem(theSender->objectName()); } void KReportDesigner::addMetaProperties(KPropertySet* set, const QString &classString, const QString &iconName) { Q_ASSERT(set); KProperty *prop; set->addProperty(prop = new KProperty("this:classString", classString)); prop->setVisible(false); set->addProperty(prop = new KProperty("this:iconName", iconName)); prop->setVisible(false); } diff --git a/src/wrtembed/KReportDesigner.h b/src/wrtembed/KReportDesigner.h index 97b91f91..17282c43 100644 --- a/src/wrtembed/KReportDesigner.h +++ b/src/wrtembed/KReportDesigner.h @@ -1,360 +1,355 @@ /* This file is part of the KDE project * Copyright (C) 2001-2007 by OpenMFG, LLC * Copyright (C) 2007-2008 by Adam Pigg * Copyright (C) 2011-2017 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 KREPORTDESIGNER_H #define KREPORTDESIGNER_H #include #include "KReportDocument.h" #include "KReportDataSource.h" class KProperty; class KPropertySet; class KReportItemBase; class QGraphicsScene; class QActionGroup; class QGraphicsSceneContextMenuEvent; class QString; class KReportDesignerSectionDetail; class KReportDesignerSection; class KReportUnit; class KReportDesignerSectionScene; class KReportDesignerSectionView; class QAction; #ifdef KREPORT_SCRIPTING class KReportScriptSource; #endif // // Class ReportDesigner // The ReportDesigner is the main widget for designing a report // class KREPORT_EXPORT KReportDesigner : public QWidget { Q_OBJECT public: /** @brief Constructor that create a blank designer @param widget QWidget parent */ explicit KReportDesigner(QWidget *parent = nullptr); /** @brief Constructor that create a designer, and loads the report described in the QDomElement @param widget QWidget parent @param element Report structure XML element */ KReportDesigner(QWidget *parent, const QDomElement &data); /** @brief Desctructor */ ~KReportDesigner() override; /** @brief Sets the report data The report data interface contains functions to retrieve data and information about the fields. @param source Pointer to KReportDataSource instance, ownership is transferred */ void setDataSource(KReportDataSource* source); #ifdef KREPORT_SCRIPTING /** @brief Sets the script source for the designer The script source contains function to return scripts supplied by the parent application @param source Pointer to KReportScriptSource instance, ownership is NOT transferred as it may be an application window */ void setScriptSource(KReportScriptSource *source); #endif /** @brief Return a pointer to the reports data @return Pointer to report data */ KReportDataSource *reportDataSource() const; /** @brief Return a pointer to the section specified @param section KReportSectionData::Section enum value of the section to return @return Pointer to report section object, or 0 if no section exists */ KReportDesignerSection* section(KReportSectionData::Type type) const; /** @brief Creates new section @return Pointer to a new report section section object, ownership is transferred to the caller */ KReportDesignerSection* createSection() Q_REQUIRED_RESULT; /** @brief Deletes the section specified @param section KReportSectionData::Section enum value of the section to return */ void removeSection(KReportSectionData::Type type); /** @brief Create a new section and insert it into the report @param section KReportSectionData::Section enum value of the section to return */ void insertSection(KReportSectionData::Type type); /** @brief Return a pointer to the detail section. The detail section contains the actual detail section and related group sections @return Pointer to detail section */ KReportDesignerSectionDetail* detailSection() const; /** @brief Sets the title of the reportData @param title Report Title */ void setReportTitle(const QString &); /** @brief Sets the parameters for the display of the background gridpoints @param visible Grid visibility @param divisions Number of minor divisions between major points */ void setGridOptions(bool visible, int divisions); /** @brief Return the title of the report */ QString reportTitle() const; /** @brief Return an XML description of the report @return QDomElement describing the report definition */ QDomElement document() const; /** @brief Return true if the design has been modified @return modified status */ bool isModified() const; /** @return a list of field names in the selected KReportData */ QStringList fieldNames() const; /** @return a list of field keys in the selected KReportData The keys can be used to reference the names */ QStringList fieldKeys() const; /** @brief Calculate the width of the page in pixels given the paper size, orientation, dpi and margin @return integer value of width in pixels */ int pageWidthPx() const; /** @return the scene (section) that is currently active */ QGraphicsScene* activeScene() const; /** @brief Sets the active Scene @param scene The scene to make active */ void setActiveScene(QGraphicsScene* scene); /** @return the property set for the general report properties */ KPropertySet* propertySet() const; /** @brief Give a hint on the size of the widget */ QSize sizeHint() const override; /** @brief Return the current unit assigned to the report */ KReportUnit pageUnit() const; /** @brief Handle the context menu event for a report section @param scene The associated scene (section) */ void sectionContextMenuEvent(KReportDesignerSectionScene *s, QGraphicsSceneContextMenuEvent * e); /** @brief Handle the mouse release event for a report section */ void sectionMouseReleaseEvent(KReportDesignerSectionView *v, QMouseEvent * e); void sectionMousePressEvent(KReportDesignerSectionView *v, QMouseEvent * e); /** @brief Sets the property set for the currently selected item @param set Property set of item */ void changeSet(KPropertySet *); /** @brief Return the property set for the curently selected item */ KPropertySet* selectedItemPropertySet() const; /** @brief Sets the modified status, defaulting to true for modified @param modified Modified status */ void setModified(bool modified); /** @brief Return a unique name that can be used by the entity @param entity Name of entity */ QString suggestEntityName(const QString &name) const; /** @brief Checks if the supplied name is unique among all entities */ bool isEntityNameUnique(const QString &name, KReportItemBase *ignore = nullptr) const; /** @brief Returns a list of actions that represent the entities that can be inserted into the report. Actions are created as children of @a group and belong to the group. @return list of actions */ static QList itemActions(QActionGroup* group = nullptr); /** @brief Populates the toolbar with actions that can be applied to the report Actions are created as children of @a group and belong to the group. @return list of actions */ QList designerActions(); /** @return X position of mouse when mouse press occurs */ qreal getSelectionPressX() const; /** @return Y position of mouse when mouse press occurs */ qreal getSelectionPressY() const; /** @return difference between X position of mouse release and press */ qreal countSelectionWidth() const; /** @return difference between Y position of mouse release and press */ qreal countSelectionHeight() const; /** @return point that contains X,Y coordinates of mouse press */ QPointF getPressPoint() const; /** @return point that contains X,Y coordinates of mouse press */ QPointF getReleasePoint() const; void plugItemActions(const QList &actList); /** * @brief Adds meta-properties to the property set @a set for consumption by property editor * - "this:classString" - user-visible translated name of element type, e.g. tr("Label") * - "this:iconName" - name of user-visible icon, e.g. "kreport-label-element" * * All the properties are set to invisible. * @see propertySet() */ static void addMetaProperties(KPropertySet* set, const QString &classString, const QString &iconName); public Q_SLOTS: void slotEditDelete(); void slotEditCut(); void slotEditCopy(); void slotEditPaste(); void slotEditPaste(QGraphicsScene *); void slotItem(const QString&); void slotSectionEditor(); void slotRaiseSelected(); void slotLowerSelected(); private: /** @brief Sets the detail section to the given section */ void setDetail(KReportDesignerSectionDetail *rsd); - /** - @brief Deletes the detail section - */ - void deleteDetail(); - void resizeEvent(QResizeEvent * event) override; //Properties void createProperties(); unsigned int selectionCount() const; void setSectionCursor(const QCursor&); void unsetSectionCursor(); void createActions(); private Q_SLOTS: void slotPropertyChanged(KPropertySet &s, KProperty &p); /** @brief When the 'page' button in the top left is pressed, change the property set to the reports properties. */ void slotPageButton_Pressed(); void slotItemTriggered(bool checked); Q_SIGNALS: void pagePropertyChanged(KPropertySet &s); void propertySetChanged(); void dirty(); void reportDataChanged(); void itemInserted(const QString& entity); private: Q_DISABLE_COPY(KReportDesigner) class Private; Private * const d; }; #endif diff --git a/src/wrtembed/KReportDesignerSection.cpp b/src/wrtembed/KReportDesignerSection.cpp index 8310d794..20119054 100644 --- a/src/wrtembed/KReportDesignerSection.cpp +++ b/src/wrtembed/KReportDesignerSection.cpp @@ -1,432 +1,441 @@ /* This file is part of the KDE project * Copyright (C) 2001-2007 by OpenMFG, LLC (info@openmfg.com) * Copyright (C) 2007-2008 by Adam Pigg (adam@piggz.co.uk) * Copyright (C) 2014 Jarosław Staniek * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include "KReportDesignerSection.h" #include "KReportDesignerSectionScene.h" #include "KReportDesignerSectionView.h" #include "KReportDesigner.h" #include "KReportDesignerItemBase.h" #include "KReportUtils.h" #include "KReportPluginInterface.h" #include "KReportPluginManager.h" #include "KReportDesignerItemRectBase.h" #include "KReportDesignerItemLine.h" #include "KReportRuler_p.h" #include "KReportZoomHandler_p.h" #include "KReportUtils_p.h" #include "KReportPluginMetaData.h" #include "kreport_debug.h" #include #include #include #include #include #include #include #include #include //! @internal class ReportResizeBar : public QFrame { Q_OBJECT public: explicit ReportResizeBar(QWidget * parent = nullptr, Qt::WindowFlags f = nullptr); Q_SIGNALS: void barDragged(int delta); protected: void mouseMoveEvent(QMouseEvent * e) override; }; //! @internal class KReportDesignerSectionTitle : public QLabel { Q_OBJECT public: explicit KReportDesignerSectionTitle(QWidget *parent = nullptr); ~KReportDesignerSectionTitle() override; Q_SIGNALS: void clicked(); protected: void paintEvent(QPaintEvent* event) override; void mousePressEvent(QMouseEvent *event) override; }; //! @internal class Q_DECL_HIDDEN KReportDesignerSection::Private { public: explicit Private() {} ~Private() {} KReportDesignerSectionTitle *title; KReportDesignerSectionScene *scene; ReportResizeBar *resizeBar; KReportDesignerSectionView *sceneView; KReportDesigner*reportDesigner; KReportRuler *sectionRuler; KReportSectionData *sectionData; int dpiY; }; KReportDesignerSection::KReportDesignerSection(KReportDesigner * rptdes, const KReportZoomHandler &zoomHandler) : QWidget(rptdes) , d(new Private()) { Q_ASSERT(rptdes); d->sectionData = new KReportSectionData(this); connect(d->sectionData->propertySet(), SIGNAL(propertyChanged(KPropertySet&,KProperty&)), this, SLOT(slotPropertyChanged(KPropertySet&,KProperty&))); d->dpiY = KReportPrivate::dpiY(); d->reportDesigner = rptdes; setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); QGridLayout * glayout = new QGridLayout(this); glayout->setSpacing(0); glayout->setMargin(0); glayout->setColumnStretch(1, 1); glayout->setRowStretch(1, 1); glayout->setSizeConstraint(QLayout::SetFixedSize); // ok create the base interface d->title = new KReportDesignerSectionTitle(this); d->title->setObjectName(QLatin1String("detail")); d->title->setText(tr("Detail")); d->sectionRuler = new KReportRuler(this, Qt::Vertical, zoomHandler); d->sectionRuler->setUnit(d->reportDesigner->pageUnit()); d->scene = new KReportDesignerSectionScene(d->reportDesigner->pageWidthPx(), d->dpiY, rptdes); d->scene->setBackgroundBrush(d->sectionData->backgroundColor()); d->sceneView = new KReportDesignerSectionView(rptdes, d->scene, this); d->sceneView->setObjectName(QLatin1String("scene view")); d->sceneView->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); d->resizeBar = new ReportResizeBar(this); connect(d->resizeBar, SIGNAL(barDragged(int)), this, SLOT(slotResizeBarDragged(int))); connect(d->reportDesigner, SIGNAL(pagePropertyChanged(KPropertySet&)), this, SLOT(slotPageOptionsChanged(KPropertySet&))); connect(d->scene, SIGNAL(clicked()), this, (SLOT(slotSceneClicked()))); connect(d->scene, SIGNAL(lostFocus()), d->title, SLOT(update())); connect(d->title, SIGNAL(clicked()), this, (SLOT(slotSceneClicked()))); glayout->addWidget(d->title, 0, 0, 1, 2); glayout->addWidget(d->sectionRuler, 1, 0); glayout->addWidget(d->sceneView , 1, 1); glayout->addWidget(d->resizeBar, 2, 0, 1, 2); d->sectionRuler->setFixedWidth(d->sectionRuler->sizeHint().width()); setLayout(glayout); slotResizeBarDragged(0); } KReportDesignerSection::~KReportDesignerSection() { delete d; } void KReportDesignerSection::setTitle(const QString & s) { d->title->setText(s); } void KReportDesignerSection::slotResizeBarDragged(int delta, bool changeSet) { if (d->sceneView->designer() && d->sceneView->designer()->propertySet()->property("page-size").value().toString() == QLatin1String("Labels")) { return; // we don't want to allow this on reports that are for labels } if (changeSet) { slotSceneClicked(); // switches property set to this section } qreal h = d->scene->height() + delta; if (h < 1) h = 1; h = d->scene->gridPoint(QPointF(0, h)).y(); - d->sectionData->m_height->setValue(INCH_TO_POINT(h/d->dpiY)); + d->sectionData->m_height->setValue(INCH_TO_POINT(h / d->dpiY), + delta == 0 ? KProperty::ValueOption::IgnoreOld + : KProperty::ValueOption::None); d->sectionRuler->setRulerLength(h); d->scene->setSceneRect(0, 0, d->scene->width(), h); d->sceneView->resizeContents(QSize(d->scene->width(), h)); - d->reportDesigner->setModified(true); + if (delta != 0) { + d->reportDesigner->setModified(true); + } } void KReportDesignerSection::buildXML(QDomDocument *doc, QDomElement *section) { KReportUtils::setAttribute(section, QLatin1String("svg:height"), d->sectionData->m_height->value().toDouble()); section->setAttribute(QLatin1String("fo:background-color"), d->sectionData->backgroundColor().name()); // now get a list of all the QGraphicsItems on this scene and output them. QGraphicsItemList list = d->scene->items(); for (QGraphicsItemList::iterator it = list.begin(); it != list.end(); ++it) { KReportDesignerItemBase::buildXML((*it), doc, section); } } void KReportDesignerSection::initFromXML(const QDomNode & section) { QDomNodeList nl = section.childNodes(); QDomNode node; QString n; qreal h = KReportUnit::parseValue(section.toElement().attribute(QLatin1String("svg:height"), QLatin1String("2.0cm"))); d->sectionData->m_height->setValue(h); h = POINT_TO_INCH(h) * d->dpiY; //kreportDebug() << "Section Height: " << h; d->scene->setSceneRect(0, 0, d->scene->width(), h); slotResizeBarDragged(0); d->sectionData->m_backgroundColor->setValue(QColor(section.toElement().attribute(QLatin1String("fo:background-color"), QLatin1String("#ffffff")))); + d->sectionData->propertySet()->clearModifiedFlags(); + KReportPluginManager* manager = KReportPluginManager::self(); for (int i = 0; i < nl.count(); ++i) { node = nl.item(i); n = node.nodeName(); if (n.startsWith(QLatin1String("report:"))) { //Load objects //report:line is a special case as it is not a plugin + QObject *obj = nullptr; + KReportPluginInterface *plugin = nullptr; QString reportItemName = n.mid(qstrlen("report:")); if (reportItemName == QLatin1String("line")) { - (new KReportDesignerItemLine(node, d->sceneView->designer(), d->scene))->setVisible(true); - continue; + obj = new KReportDesignerItemLine(node, d->sceneView->designer(), d->scene); + } else { + plugin = manager->plugin(reportItemName); + if (plugin) { + obj = plugin->createDesignerInstance(node, d->reportDesigner, d->scene); + } } - KReportPluginManager* manager = KReportPluginManager::self(); - KReportPluginInterface *plugin = manager->plugin(reportItemName); - if (plugin) { - QObject *obj = plugin->createDesignerInstance(node, d->reportDesigner, d->scene); - if (obj) { - KReportDesignerItemRectBase *entity = dynamic_cast(obj); - if (entity) { - entity->setVisible(true); - } - KReportItemBase *item = dynamic_cast(obj); - if (item) { - item->setUnit(d->reportDesigner->pageUnit()); + if (obj) { + KReportDesignerItemRectBase *entity = dynamic_cast(obj); + if (entity) { + entity->setVisible(true); + } + KReportItemBase *item = dynamic_cast(obj); + if (item) { + item->setUnit(d->reportDesigner->pageUnit()); + if (plugin) { KReportDesigner::addMetaProperties(item->propertySet(), plugin->metaData()->name(), plugin->metaData()->iconName()); } - continue; + item->propertySet()->clearModifiedFlags(); } } } kreportWarning() << "Encountered unknown node while parsing section: " << n; } } QSize KReportDesignerSection::sizeHint() const { return QSize(d->scene->width() + d->sectionRuler->frameSize().width(), d->title->frameSize().height() + d->sceneView->sizeHint().height() + d->resizeBar->frameSize().height()); } void KReportDesignerSection::slotPageOptionsChanged(KPropertySet &set) { Q_UNUSED(set) KReportUnit unit = d->reportDesigner->pageUnit(); d->sectionData->m_height->setOption("unit", unit.symbol()); //update items position with unit QList itms = d->scene->items(); for (int i = 0; i < itms.size(); ++i) { KReportItemBase *obj = dynamic_cast(itms[i]); if (obj) { obj->setUnit(unit); } } d->scene->setSceneRect(0, 0, d->reportDesigner->pageWidthPx(), d->scene->height()); d->title->setMinimumWidth(d->reportDesigner->pageWidthPx() + d->sectionRuler->frameSize().width()); d->sectionRuler->setUnit(d->reportDesigner->pageUnit()); //Trigger a redraw of the background d->sceneView->resetCachedContent(); d->reportDesigner->adjustSize(); d->reportDesigner->repaint(); slotResizeBarDragged(0, false); } void KReportDesignerSection::slotSceneClicked() { d->reportDesigner->setActiveScene(d->scene); d->reportDesigner->changeSet(d->sectionData->propertySet()); } void KReportDesignerSection::slotPropertyChanged(KPropertySet &s, KProperty &p) { Q_UNUSED(s) //kreportDebug() << p.name(); //Handle Background Color if (p.name() == "background-color") { d->scene->setBackgroundBrush(p.value().value()); } if (p.name() == "height") { d->scene->setSceneRect(0, 0, d->scene->width(), POINT_TO_INCH(p.value().toDouble()) * d->dpiY); slotResizeBarDragged(0); } if (d->reportDesigner) d->reportDesigner->setModified(true); d->sceneView->resetCachedContent(); d->scene->update(); } void KReportDesignerSection::setSectionCursor(const QCursor& c) { if (d->sceneView) d->sceneView->setCursor(c); } void KReportDesignerSection::unsetSectionCursor() { if (d->sceneView) d->sceneView->unsetCursor(); } QGraphicsItemList KReportDesignerSection::items() const { QGraphicsItemList items; if (d->scene) { foreach (QGraphicsItem *itm, d->scene->items()) { if (itm->parentItem() == nullptr) { items << itm; } } } return items; } // // class ReportResizeBar // ReportResizeBar::ReportResizeBar(QWidget * parent, Qt::WindowFlags f) : QFrame(parent, f) { setCursor(QCursor(Qt::SizeVerCursor)); setFrameStyle(QFrame::HLine); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); } void ReportResizeBar::mouseMoveEvent(QMouseEvent * e) { e->accept(); emit barDragged(e->y()); } //============================================================================= KReportDesignerSectionTitle::KReportDesignerSectionTitle(QWidget*parent) : QLabel(parent) { setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); setAlignment(Qt::AlignLeft | Qt::AlignTop); setMinimumHeight(qMax(fontMetrics().lineSpacing(),16 + 2)); //16 = Small icon size } KReportDesignerSectionTitle::~KReportDesignerSectionTitle() { } //! \return true if \a o has parent \a par. static bool hasParent(QObject* par, QObject* o) { if (!o || !par) return false; while (o && o != par) o = o->parent(); return o == par; } static void replaceColors(QPixmap* original, const QColor& color) { QImage dest(original->toImage()); QPainter p(&dest); p.setCompositionMode(QPainter::CompositionMode_SourceIn); p.fillRect(dest.rect(), color); *original = QPixmap::fromImage(dest); } void KReportDesignerSectionTitle::paintEvent(QPaintEvent * event) { QPainter painter(this); KReportDesignerSection* section = dynamic_cast(parent()); if (section) { const bool current = section->d->scene == section->d->reportDesigner->activeScene(); QPalette::ColorGroup cg = QPalette::Inactive; QWidget *activeWindow = QApplication::activeWindow(); if (activeWindow) { QWidget *par = activeWindow->focusWidget(); if (qobject_cast(par)) { par = par->parentWidget(); // we're close, pick common parent } if (hasParent(par, this)) { cg = QPalette::Active; } } if (current) { painter.fillRect(rect(), palette().brush(cg, QPalette::Highlight)); } painter.setPen(palette().color(cg, current ? QPalette::HighlightedText : QPalette::WindowText)); QPixmap pixmap(QIcon::fromTheme(QLatin1String("arrow-down")).pixmap(16,16)); replaceColors(&pixmap, painter.pen().color()); const int left = 25; painter.drawPixmap(QPoint(left, (height() - pixmap.height()) / 2), pixmap); painter.drawText(rect().adjusted(left + pixmap.width() + 4, 0, 0, 0), Qt::AlignLeft | Qt::AlignVCenter, text()); } QFrame::paintEvent(event); } void KReportDesignerSectionTitle::mousePressEvent(QMouseEvent *event) { QLabel::mousePressEvent(event); if (event->button() == Qt::LeftButton) { emit clicked(); } } #include "KReportDesignerSection.moc"