diff --git a/src/common/KReportDesign_p.h b/src/common/KReportDesign_p.h index fc5fb733..fa252787 100644 --- a/src/common/KReportDesign_p.h +++ b/src/common/KReportDesign_p.h @@ -1,129 +1,130 @@ /* 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-2015 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 KREPORTDESIGN_P_H #define KREPORTDESIGN_P_H #include "KReportDesign.h" #include "KReportUnit.h" +#include "KReportUtils_p.h" #include #include #include class QDomDocument; class QDomElement; class KReportPluginInterface; static const bool DEFAULT_SHOW_GRID = true; static const bool DEFAULT_SNAP_TO_GRID = true; static const int DEFAULT_GRID_DIVISIONS = 4; static const KReportUnit DEFAULT_UNIT = KReportUnit(KReportUnit::Centimeter); static const int DEFAULT_PAGE_MARGIN = CM_TO_POINT(1.0); static const QPageSize::PageSizeId DEFAULT_PAGE_SIZE = QPageSize::A4; static const QPageLayout::Orientation DEFAULT_PAGE_ORIENTATION = QPageLayout::Landscape; class Q_DECL_HIDDEN KReportDesign::Private { public: explicit Private(KReportDesign *design); ~Private(); QDomElement requiredChildElement(const QDomElement &parent, const char* childElementName, KReportDesignReadingStatus *status) const; void unexpectedElement(const QDomElement &element, KReportDesignReadingStatus *status) const; //! Processes document @a doc and sets status @a status bool processDocument(const QDomDocument &doc, KReportDesignReadingStatus *status); //! Processes @a el, a child of /report:content element and sets status @a status bool processContentElementChild(const QDomElement &el, KReportDesignReadingStatus *status); //! Processes @a el, a child of /report:content/report:body element and sets status @a status bool processBodyElementChild(const QDomElement &el, KReportDesignReadingStatus *status); //! Processes @a el, a /report:content/report:body/report:section element and sets status @a status KReportSection processSectionElement(const QDomElement &el, KReportDesignReadingStatus *status); //! Processes @a el, //! a child of /report:content/report:body/report:section element //! or a child of /report:content/report:body/report:detail/report:section element //! and sets status @a status. //! It is probably the lowest level in hierarchy and @a el refers to a single report element. KReportElement processSectionElementChild(const QDomElement &el, KReportDesignReadingStatus *status); //! Processes @a el, a child of /report:content/report:body/report:detail element and sets status @a status bool processDetailElement(const QDomElement &el, KReportDesignReadingStatus *status); //! Processes @a el, a /report:content/report:body/report:detail/report:group element and sets status @a status bool processGroupElement(const QDomElement &el, KReportDesignReadingStatus *status); KReportPluginInterface* findPlugin(const QString &typeName, const QDomElement &el, KReportDesignReadingStatus *status); KReportDesign * const q; // Visual settings only bool showGrid; bool snapToGrid; int gridDivisions; KReportUnit pageUnit; // END OF: Visual settings only QString title; - QPageLayout pageLayout; + KReportPrivate::PageLayout pageLayout; QVarLengthArray sections; #ifdef KREPORT_SCRIPTING QString script; QString originalInterpreter; //!< used for backward-compatibility to save the original #endif }; class KReportDesignGlobal { public: KReportDesignGlobal(); static KReportDesignGlobal* self(); struct SectionTypeInfo { KReportSection::Type type; const char *name; }; KReportSection::Type sectionType(const QString& typeName); QString sectionTypeName(KReportSection::Type sectionType); - QPageLayout defaultPageLayout; + KReportPrivate::PageLayout defaultPageLayout; qreal defaultSectionHeight; QColor defaultSectionBackgroundColor; private: void initSectionTypes(); static const SectionTypeInfo sectionTypes[]; QHash sectionTypesForName; QHash sectionTypeNames; }; #endif diff --git a/src/common/KReportDocument.cpp b/src/common/KReportDocument.cpp index 98219776..d4400f32 100644 --- a/src/common/KReportDocument.cpp +++ b/src/common/KReportDocument.cpp @@ -1,384 +1,384 @@ /* This file is part of the KDE project * 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 "KReportDocument.h" #include "KReportUnit.h" #include "KReportDetailSectionData.h" #include "KReportItemBase.h" #include "KReportUtils_p.h" #include "KReportPageSize.h" #include #include #include "kreport_debug.h" class Q_DECL_HIDDEN KReportDocument::Private { public: bool valid; QString title; QString name; QString query; #ifdef KREPORT_SCRIPTING QString script; QString interpreter; #endif bool externalData; - QPageLayout page; + KReportPrivate::PageLayout pageLayout; QString pageSize; QString labelType; }; void KReportDocument::init() { m_pageHeaderFirst = m_pageHeaderOdd = m_pageHeaderEven = m_pageHeaderLast = m_pageHeaderAny = 0; m_pageFooterFirst = m_pageFooterOdd = m_pageFooterEven = m_pageFooterLast = m_pageFooterAny = 0; m_reportHeader = m_reportFooter = 0; } KReportDocument::KReportDocument(QObject *parent) : QObject(parent), m_detailSection(0), d(new Private()) { init(); d->valid = true; } KReportDocument::KReportDocument(const QDomElement & elemSource, QObject *parent) : QObject(parent), m_detailSection(0), d(new Private()) { d->valid = false; init(); //kreportDebug(); if (elemSource.tagName() != QLatin1String("report:content")) { kreportWarning() << "QDomElement is not tag" << elemSource.text(); return; } QDomNodeList sections = elemSource.childNodes(); for (int nodeCounter = 0; nodeCounter < sections.count(); nodeCounter++) { QDomElement elemThis = sections.item(nodeCounter).toElement(); if (elemThis.tagName() == QLatin1String("report:title")) { d->title = elemThis.text(); #ifdef KREPORT_SCRIPTING } else if (elemThis.tagName() == QLatin1String("report:script")) { d->script = elemThis.text(); d->interpreter = elemThis.attribute(QLatin1String("report:script-interpreter")); #endif } else if (elemThis.tagName() == QLatin1String("report:page-style")) { QString pagetype = elemThis.firstChild().nodeValue(); //Full page mode is required to allow margins to be set to whatever the user has specified - d->page.setMode(QPageLayout::FullPageMode); + d->pageLayout.setMode(QPageLayout::FullPageMode); if (pagetype == QLatin1String("predefined")) { setPageSize(elemThis.attribute(QLatin1String("report:page-size"), QLatin1String("A4"))); - d->page.setPageSize(QPageSize(KReportPageSize::pageSize(pageSize()))); + d->pageLayout.setPageSize(QPageSize(KReportPageSize::pageSize(pageSize()))); } else if (pagetype == QLatin1String("custom")) { QPageSize custom(QSize(elemThis.attribute(QLatin1String("report:custom-page-width"), QString()).toFloat() , elemThis.attribute(QLatin1String("report:custom-page-height"), QString()).toFloat()), QLatin1String("Custom")); - d->page.setPageSize(custom); + d->pageLayout.setPageSize(custom); } else if (pagetype == QLatin1String("label")) { setLabelType(elemThis.firstChild().nodeValue()); } //! @todo add config for default margins or add within templates support - d->page.setUnits(QPageLayout::Point); - d->page.setLeftMargin(KReportUnit::parseValue(elemThis.attribute(QLatin1String("fo:margin-left"), QLatin1String("1.0cm")))); - d->page.setRightMargin(KReportUnit::parseValue(elemThis.attribute(QLatin1String("fo:margin-right"), QLatin1String("1.0cm")))); - d->page.setTopMargin(KReportUnit::parseValue(elemThis.attribute(QLatin1String("fo:margin-top"), QLatin1String("1.0cm")))); - d->page.setBottomMargin(KReportUnit::parseValue(elemThis.attribute(QLatin1String("fo:margin-bottom"), QLatin1String("1.0cm")))); - d->page.setOrientation(elemThis.attribute(QLatin1String("report:print-orientation"), QLatin1String("portrait")) == QLatin1String("portrait") ? QPageLayout::Portrait : QPageLayout::Landscape); + d->pageLayout.setUnits(QPageLayout::Point); + d->pageLayout.setLeftMargin(KReportUnit::parseValue(elemThis.attribute(QLatin1String("fo:margin-left"), QLatin1String("1.0cm")))); + d->pageLayout.setRightMargin(KReportUnit::parseValue(elemThis.attribute(QLatin1String("fo:margin-right"), QLatin1String("1.0cm")))); + d->pageLayout.setTopMargin(KReportUnit::parseValue(elemThis.attribute(QLatin1String("fo:margin-top"), QLatin1String("1.0cm")))); + d->pageLayout.setBottomMargin(KReportUnit::parseValue(elemThis.attribute(QLatin1String("fo:margin-bottom"), QLatin1String("1.0cm")))); + d->pageLayout.setOrientation(elemThis.attribute(QLatin1String("report:print-orientation"), QLatin1String("portrait")) == QLatin1String("portrait") ? QPageLayout::Portrait : QPageLayout::Landscape); } else if (elemThis.tagName() == QLatin1String("report:body")) { QDomNodeList sectionlist = elemThis.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")) { KReportSectionData * sd = new KReportSectionData(sec.toElement(), this); if (!sd->isValid()) { kreportDebug() << "Invalid section"; delete sd; } else { //kreportDebug() << "Adding section of type " << sd->type(); switch (sd->type()) { case KReportSectionData::PageHeaderFirst: m_pageHeaderFirst = sd; break; case KReportSectionData::PageHeaderOdd: m_pageHeaderOdd = sd; break; case KReportSectionData::PageHeaderEven: m_pageHeaderEven = sd; break; case KReportSectionData::PageHeaderLast: m_pageHeaderLast = sd; break; case KReportSectionData::PageHeaderAny: m_pageHeaderAny = sd; break; case KReportSectionData::ReportHeader: m_reportHeader = sd; break; case KReportSectionData::ReportFooter: m_reportFooter = sd; break; case KReportSectionData::PageFooterFirst: m_pageFooterFirst = sd; break; case KReportSectionData::PageFooterOdd: m_pageFooterOdd = sd; break; case KReportSectionData::PageFooterEven: m_pageFooterEven = sd; break; case KReportSectionData::PageFooterLast: m_pageFooterLast = sd; break; case KReportSectionData::PageFooterAny: m_pageFooterAny = sd; break; default: ; } } } else if (sn == QLatin1String("report:detail")) { KReportDetailSectionData * dsd = new KReportDetailSectionData(sec.toElement(), this); if (dsd->isValid()) { m_detailSection = dsd; } else { kreportDebug() << "Invalid detail section"; delete dsd; } } } else { kreportWarning() << "Encountered an unknown Element: " << elemThis.tagName(); } } } d->valid = true; } } KReportDocument::~KReportDocument() { delete d; } QList KReportDocument::objects() const { QList obs; for (int i = 1; i <= KReportSectionData::PageFooterAny; i++) { KReportSectionData *sec = section((KReportSectionData::Section)i); if (sec) { obs << sec->objects(); } } if (m_detailSection) { //kreportDebug() << "Number of groups: " << m_detailSection->m_groupList.count(); foreach(KReportDetailGroupSectionData* g, m_detailSection->m_groupList) { if (g->m_groupHeader) { obs << g->m_groupHeader->objects(); } if (g->m_groupFooter) { obs << g->m_groupFooter->objects(); } } if (m_detailSection->m_detailSection) obs << m_detailSection->m_detailSection->objects(); } /*kreportDebug() << "Object List:"; foreach(KReportItemBase* o, obs) { kreportDebug() << o->entityName(); }*/ return obs; } KReportItemBase* KReportDocument::object(const QString& n) const { QList obs = objects(); foreach(KReportItemBase* o, obs) { if (o->entityName() == n) { return o; } } return 0; } QList KReportDocument::sections() const { QList secs; for (int i = 0; i < 12 ; ++i) { KReportSectionData *sec = section((KReportSectionData::Section)(i + 1)); if (sec) { secs << sec; } } if (m_detailSection) { //kreportDebug() << "Number of groups: " << m_detailSection->m_groupList.count(); foreach(KReportDetailGroupSectionData* g, m_detailSection->m_groupList) { if (g->m_groupHeader) { secs << g->m_groupHeader; } if (g->m_groupFooter) { secs << g->m_groupFooter; } } if (m_detailSection->m_detailSection) secs << m_detailSection->m_detailSection; } return secs; } KReportSectionData* KReportDocument::section(const QString& sn) const { QList secs = sections(); foreach(KReportSectionData *sec, secs) { if (sec->name() == sn) { return sec; } } return 0; } KReportSectionData* KReportDocument::section(KReportSectionData::Section s) const { KReportSectionData *sec; switch (s) { case KReportSectionData::PageHeaderAny: sec = m_pageHeaderAny; break; case KReportSectionData::PageHeaderEven: sec = m_pageHeaderEven; break; case KReportSectionData::PageHeaderOdd: sec = m_pageHeaderOdd; break; case KReportSectionData::PageHeaderFirst: sec = m_pageHeaderFirst; break; case KReportSectionData::PageHeaderLast: sec = m_pageHeaderLast; break; case KReportSectionData::PageFooterAny: sec = m_pageFooterAny; break; case KReportSectionData::PageFooterEven: sec = m_pageFooterEven; break; case KReportSectionData::PageFooterOdd: sec = m_pageFooterOdd; break; case KReportSectionData::PageFooterFirst: sec = m_pageFooterFirst; break; case KReportSectionData::PageFooterLast: sec = m_pageFooterLast; break; case KReportSectionData::ReportHeader: sec = m_reportHeader; break; case KReportSectionData::ReportFooter: sec = m_reportFooter; break; default: sec = 0; } return sec; } QPageLayout KReportDocument::pageLayout() const { - return d->page; + return d->pageLayout; } bool KReportDocument::isValid() const { return d->valid; } QString KReportDocument::title() const { return d->title; } bool KReportDocument::externalData() const { return d->externalData; } QString KReportDocument::interpreter() const { return d->interpreter; } QString KReportDocument::name() const { return d->name; } void KReportDocument::setName(const QString& n) { d->name = n; } QString KReportDocument::query() const { return d->query; } QString KReportDocument::script() const { return d->script; } QString KReportDocument::pageSize() { return d->pageSize; } void KReportDocument::setPageSize(const QString& size) { d->pageSize = size; } QString KReportDocument::labelType() const { return d->labelType; } void KReportDocument::setLabelType(const QString& label) { d->labelType = label; } diff --git a/src/common/KReportRenderObjects.cpp b/src/common/KReportRenderObjects.cpp index 233ffb9a..5a25a70c 100644 --- a/src/common/KReportRenderObjects.cpp +++ b/src/common/KReportRenderObjects.cpp @@ -1,967 +1,968 @@ /* 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) * * 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 "KReportRenderObjects.h" +#include "KReportUtils_p.h" #include "kreport_debug.h" // Helper functions static bool xLessThan(OROPrimitive* s1, OROPrimitive* s2) { return s1->position().x() < s2->position().x(); } // // ORODocument // class Q_DECL_HIDDEN ORODocument::Private { public: Private(); ~Private(); QString title; QList pages; QList sections; - QPageLayout pageLayout; + KReportPrivate::PageLayout pageLayout; }; ORODocument::Private::Private() { } ORODocument::Private::~Private() { qDeleteAll(pages); qDeleteAll(sections); } ORODocument::ORODocument(const QString& title) : d(new Private()) { d->title = title; } ORODocument::~ORODocument() { delete d; } void ORODocument::setTitle(const QString &title) { d->title = title; } OROPage* ORODocument::page(int index) { return d->pages.value(index); } const OROPage * ORODocument::page(int index) const { return d->pages.value(index); } void ORODocument::addPage(OROPage* p) { if (p == 0) { return; } if (p->document() != 0 && p->document() != this) { return; } p->setDocument(this); d->pages.append(p); } OROSection* ORODocument::section(int pnum) { return d->sections.value(pnum); } const OROSection * ORODocument::section(int index) const { return d->sections.value(index); } void ORODocument::addSection(OROSection* s) { if (s == 0) return; if (s->document() != 0 && s->document() != this) { return; } s->setDocument(this); d->sections.append(s); } void ORODocument::setPageLayout(const QPageLayout & options) { d->pageLayout = options; } void ORODocument::notifyChange(int pageNo) { emit(updated(pageNo)); } QPageLayout ORODocument::pageLayout() const { return d->pageLayout; } int ORODocument::pageCount() const { return d->pages.count(); } int ORODocument::sectionCount() const { return d->sections.count(); } QString ORODocument::title() const { return d->title; } void ORODocument::removePage(OROPage* page) { d->pages.removeOne(page); delete page; } void ORODocument::takePage(OROPage* page) { d->pages.removeOne(page); } void ORODocument::removeSection(OROSection* section) { d->sections.removeOne(section); delete section; } void ORODocument::takeSection(OROSection* section) { d->sections.removeOne(section); } int ORODocument::pageIndex(const OROPage* page) const { return d->pages.indexOf(const_cast(page)); } // // OROPage // class Q_DECL_HIDDEN OROPage::Private { public: Private(); ~Private(); ORODocument *document; QList primitives; }; OROPage::Private::Private() { } OROPage::Private::~Private() { qDeleteAll(primitives); } OROPage::OROPage(ORODocument * pDocument) : d(new Private()) { d->document = pDocument; } OROPage::~OROPage() { if (d->document) { d->document->takePage(this); } delete d; } int OROPage::pageNumber() const { if (d->document) { return d->document->pageIndex(this); } return -1; } OROPrimitive* OROPage::primitive(int index) { return d->primitives.value(index); } const OROPrimitive * OROPage::primitive(int index) const { return d->primitives.value(index); } void OROPage::insertPrimitive(OROPrimitive* p, int index) { //kreportDebug() << "Adding primitive" << p->type() << "to page" << page(); if (p == 0) return; p->setPage(this); if (index == -1) { d->primitives.append(p); } else { d->primitives.insert(index, p); } #if 0 //TODO if (notify) { if (d->document) { d->document->notifyChange(pageNumber()); } } #endif } ORODocument * OROPage::document() { return d->document; } const ORODocument * OROPage::document() const { return d->document; } int OROPage::primitiveCount() const { return d->primitives.count(); } void OROPage::setDocument(ORODocument* doc) { d->document = doc; } void OROPage::removePrimitive(OROPrimitive* primitive) { d->primitives.removeOne(primitive); delete primitive; } void OROPage::takePrimitive(OROPrimitive* primitive) { d->primitives.removeOne(primitive); } // // OROSection // class Q_DECL_HIDDEN OROSection::Private { public: Private(); ~Private(); ORODocument * document; QList primitives; qint64 row = 0; int height = 0; KReportSectionData::Section type = KReportSectionData::None; QColor backgroundColor = Qt::white; }; OROSection::Private::Private() { } OROSection::Private::~Private() { qDeleteAll(primitives); primitives.clear(); } OROSection::OROSection(ORODocument* doc) : d(new Private()) { d->document = doc; } OROSection::~OROSection() { if (d->document) { d->document->takeSection(this); } delete d; } OROPrimitive* OROSection::primitive(int index) { return d->primitives.value(index); } const OROPrimitive * OROSection::primitive(int index) const { return d->primitives.value(index); } void OROSection::addPrimitive(OROPrimitive* primitive) { if (primitive == 0) return; d->primitives.append(primitive); } void OROSection::setHeight(int h) { d->height = h; } int OROSection::height() const { return d->height; } void OROSection::setBackgroundColor(const QColor& color) { d->backgroundColor = color; } QColor OROSection::backgroundColor() const { return d->backgroundColor; } void OROSection::sortPrimitives(Qt::Orientation orientation) { if (orientation == Qt::Horizontal) { qSort(d->primitives.begin(), d->primitives.end(), xLessThan); } } ORODocument * OROSection::document() { return d->document; } const ORODocument * OROSection::document() const { return d->document; } int OROSection::primitiveCount() const { return d->primitives.count(); } void OROSection::setType(KReportSectionData::Section t) { d->type = t; } KReportSectionData::Section OROSection::type() const { return d->type; } void OROSection::setDocument(ORODocument* doc) { d->document = doc; } // // OROPrimitive // class Q_DECL_HIDDEN OROPrimitive::Private { public: OROPage * page = nullptr; QPointF position; QSizeF size; }; OROPrimitive::OROPrimitive() : d(new Private()) { } OROPrimitive::~OROPrimitive() { if (d->page) { d->page->takePrimitive(this); } delete d; } void OROPrimitive::setPosition(const QPointF& pos) { d->position = pos; } void OROPrimitive::setSize(const QSizeF & s) { d->size = s; } OROPage * OROPrimitive::page() { return d->page; } const OROPage * OROPrimitive::page() const { return d->page; } QPointF OROPrimitive::position() const { return d->position; } QSizeF OROPrimitive::size() const { return d->size; } void OROPrimitive::setPage(OROPage* page) { d->page = page; } // // OROTextBox // class Q_DECL_HIDDEN OROTextBox::Private { public: Private(); ~Private(); QString text; KRTextStyleData textStyle; KReportLineStyle lineStyle; Qt::Alignment alignment; int flags; // Qt::AlignmentFlag and Qt::TextFlag OR'd bool wordWrap; bool canGrow; bool requiresPostProcessing; }; OROTextBox::Private::Private() { flags = 0; wordWrap = false; canGrow = false; requiresPostProcessing = false; lineStyle.setColor(Qt::black); lineStyle.setWidth(0); lineStyle.setPenStyle(Qt::NoPen); } OROTextBox::Private::~Private() { } OROTextBox::OROTextBox() : d(new Private()) { } OROTextBox::~OROTextBox() { delete d; } void OROTextBox::setText(const QString & s) { d->text = s; } void OROTextBox::setTextStyle(const KRTextStyleData & ts) { d->textStyle = ts; } void OROTextBox::setLineStyle(const KReportLineStyle & ls) { d->lineStyle = ls; } void OROTextBox::setFont(const QFont & f) { d->textStyle.font = f; } void OROTextBox::setFlags(int f) { d->flags = f; } bool OROTextBox::canGrow() const { return d->canGrow; } int OROTextBox::flags() const { return d->flags; } KReportLineStyle OROTextBox::lineStyle() const { return d->lineStyle; } bool OROTextBox::requiresPostProcessing() const { return d->requiresPostProcessing; } void OROTextBox::setCanGrow(bool grow) { d->canGrow = grow; } void OROTextBox::setRequiresPostProcessing(bool pp) { d->requiresPostProcessing = pp; } void OROTextBox::setWordWrap(bool ww) { d->wordWrap = ww; } QString OROTextBox::text() const { return d->text; } KRTextStyleData OROTextBox::textStyle() const { return d->textStyle; } bool OROTextBox::wordWrap() const { return d->wordWrap; } OROPrimitive* OROTextBox::clone() const { OROTextBox *theClone = new OROTextBox(); theClone->setSize(size()); theClone->setPosition(position()); theClone->setText(text()); theClone->setTextStyle(textStyle()); theClone->setLineStyle(lineStyle()); theClone->setFlags(flags()); theClone->setCanGrow(canGrow()); theClone->setWordWrap(wordWrap()); theClone->setRequiresPostProcessing(requiresPostProcessing()); return theClone; } // // OROLine // class Q_DECL_HIDDEN OROLine::Private { public: QPointF endPoint; KReportLineStyle lineStyle; }; OROLine::OROLine() : d(new Private()) { } OROLine::~OROLine() { delete d; } void OROLine::setStartPoint(const QPointF & p) { setPosition(p); } void OROLine::setEndPoint(const QPointF & p) { d->endPoint = p; } void OROLine::setLineStyle(const KReportLineStyle& style) { d->lineStyle = style; } QPointF OROLine::endPoint() const { return d->endPoint; } KReportLineStyle OROLine::lineStyle() const { return d->lineStyle; } OROPrimitive* OROLine::clone() const { OROLine *theClone = new OROLine(); theClone->setStartPoint(position()); theClone->setEndPoint(endPoint()); theClone->setLineStyle(lineStyle()); return theClone; } // // OROImage // class Q_DECL_HIDDEN OROImage::Private { public: QImage image; bool scaled; Qt::TransformationMode transformFlags; Qt::AspectRatioMode aspectFlags; }; OROImage::OROImage() : d(new Private()) { d->scaled = false; d->transformFlags = Qt::FastTransformation; d->aspectFlags = Qt::IgnoreAspectRatio; } OROImage::~OROImage() { delete d; } void OROImage::setImage(const QImage & img) { d->image = img; } void OROImage::setScaled(bool b) { d->scaled = b; } void OROImage::setTransformationMode(Qt::TransformationMode transformation) { d->transformFlags = transformation; } void OROImage::setAspectRatioMode(Qt::AspectRatioMode aspectRatioMode) { d->aspectFlags = aspectRatioMode; } Qt::AspectRatioMode OROImage::aspectRatioMode() const { return d->aspectFlags; } QImage OROImage::image() const { return d->image; } bool OROImage::isScaled() const { return d->scaled; } Qt::TransformationMode OROImage::transformationMode() const { return d->transformFlags; } OROPrimitive* OROImage::clone() const { OROImage *theClone = new OROImage(); theClone->setSize(size()); theClone->setPosition(position()); theClone->setImage(image()); theClone->setScaled(isScaled()); theClone->setTransformationMode(transformationMode()); theClone->setAspectRatioMode(aspectRatioMode()); return theClone; } // // OROPicture // class Q_DECL_HIDDEN OROPicture::Private { public: QPicture picture; }; OROPicture::OROPicture() : d(new Private()) { } OROPicture::~OROPicture() { delete d; } OROPrimitive* OROPicture::clone() const { OROPicture *theClone = new OROPicture(); theClone->setSize(size()); theClone->setPosition(position()); // theClone->setPicture(*(picture()ddddddds)); return theClone; } QPicture* OROPicture::picture() { return &d->picture; } void OROPicture::setPicture(const QPicture& p) { d->picture = p; } // // ORORect // class Q_DECL_HIDDEN ORORect::Private { public: QPen pen; QBrush brush; }; ORORect::ORORect() : d(new Private()) { } ORORect::~ORORect() { delete d; } void ORORect::setRect(const QRectF & r) { setPosition(r.topLeft()); setSize(r.size()); } void ORORect::setPen(const QPen & p) { d->pen = p; } void ORORect::setBrush(const QBrush & b) { d->brush = b; } QBrush ORORect::brush() const { return d->brush; } QPen ORORect::pen() const { return d->pen; } QRectF ORORect::rect() const { return QRectF(position(), size()); } OROPrimitive* ORORect::clone() const { ORORect *theClone = new ORORect(); theClone->setSize(size()); theClone->setPosition(position()); theClone->setPen(pen()); theClone->setBrush(brush()); return theClone; } // // OROEllipse // class Q_DECL_HIDDEN OROEllipse::Private { public: QPen pen; QBrush brush; }; OROEllipse::OROEllipse() : d(new Private()) { } OROEllipse::~OROEllipse() { delete d; } void OROEllipse::setRect(const QRectF & r) { setPosition(r.topLeft()); setSize(r.size()); } void OROEllipse::setPen(const QPen & p) { d->pen = p; } void OROEllipse::setBrush(const QBrush & b) { d->brush = b; } QBrush OROEllipse::brush() const { return d->brush; } QPen OROEllipse::pen() const { return d->pen; } QRectF OROEllipse::rect() const { return QRectF(position(), size()); } OROPrimitive* OROEllipse::clone() const { OROEllipse *theClone = new OROEllipse(); theClone->setSize(size()); theClone->setPosition(position()); theClone->setPen(pen()); theClone->setBrush(brush()); return theClone; } // // OROCheck // class Q_DECL_HIDDEN OROCheckBox::Private { public: OROCheckBox::Type checkType; bool value; KReportLineStyle lineStyle; QColor foregroundColor; }; OROCheckBox::OROCheckBox() : d(new Private()) { d->value = false; } OROCheckBox::~OROCheckBox() { delete d; } OROCheckBox::Type OROCheckBox::checkType() const { return d->checkType; } QColor OROCheckBox::foregroundColor() const { return d->foregroundColor; } KReportLineStyle OROCheckBox::lineStyle() const { return d->lineStyle; } void OROCheckBox::setForegroundColor(const QColor& fg) { d->foregroundColor = fg; } void OROCheckBox::setLineStyle(const KReportLineStyle& ls) { d->lineStyle = ls; } void OROCheckBox::setValue(bool v) { d->value = v; } bool OROCheckBox::value() const { return d->value; } void OROCheckBox::setCheckType(Type type) { if (type == Cross || type == Tick || type == Dot) { d->checkType = type; } else { d->checkType = Cross; } } OROPrimitive* OROCheckBox::clone() const { OROCheckBox *theClone = new OROCheckBox(); theClone->setSize(size()); theClone->setPosition(position()); theClone->setLineStyle(lineStyle()); theClone->setForegroundColor(foregroundColor()); theClone->setValue(value()); theClone->setCheckType(checkType()); return theClone; } diff --git a/src/common/KReportUtils_p.cpp b/src/common/KReportUtils_p.cpp index e0ece2d5..a11f6440 100644 --- a/src/common/KReportUtils_p.cpp +++ b/src/common/KReportUtils_p.cpp @@ -1,313 +1,327 @@ /* This file is part of the KDE project Copyright (C) 2015-2016 Jarosław Staniek Copyright (C) 2016 Adam Pigg This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "KReportUtils_p.h" #include "config-kreport.h" #ifdef Q_OS_WIN #define KPATH_SEPARATOR ';' #else #define KPATH_SEPARATOR ':' #endif class KReportDpiSingleton { public: KReportDpiSingleton(); int m_dpiX; int m_dpiY; }; KReportDpiSingleton::KReportDpiSingleton() { // Another way to get the DPI of the display would be QPaintDeviceMetrics, // but we have no widget here (and moving this to KoView wouldn't allow // using this from the document easily). #ifdef Q_WS_X11 m_dpiX = QX11Info::appDpiX(); m_dpiY = QX11Info::appDpiY(); #else QDesktopWidget *w = QApplication::desktop(); if (w) { m_dpiX = w->logicalDpiX(); m_dpiY = w->logicalDpiY(); } else { m_dpiX = 96; m_dpiY = 96; } #endif } Q_GLOBAL_STATIC(KReportDpiSingleton, s_instance) namespace KReportPrivate { bool fileReadable(const QString &path) { return !path.isEmpty() && QFileInfo(path).isReadable(); } QStringList correctStandardLocations(const QString &privateName, QStandardPaths::StandardLocation location, const QString &extraLocation) { QStringList result; if (!privateName.isEmpty()) { QRegularExpression re(QLatin1Char('/') + QCoreApplication::applicationName() + QLatin1Char('$')); QStringList standardLocations(QStandardPaths::standardLocations(location)); if (!extraLocation.isEmpty()) { standardLocations.append(extraLocation); } for(const QString &dir : standardLocations) { if (dir.indexOf(re) != -1) { QString realDir(dir); realDir.replace(re, QLatin1Char('/') + privateName); result.append(realDir); } } } return result; } QString locateFile(const QString &privateName, const QString& path, QStandardPaths::StandardLocation location, const QString &extraLocation) { // let QStandardPaths handle this, it will look for app local stuff QString fullPath = QFileInfo( QStandardPaths::locate(location, path)).canonicalFilePath(); if (fileReadable(fullPath)) { return fullPath; } // Try extra location fullPath = QFileInfo(extraLocation + QLatin1Char('/') + path).canonicalFilePath(); if (fileReadable(fullPath)) { return fullPath; } // Try in PATH subdirs, useful for running apps from the build dir, without installing for(const QByteArray &pathDir : qgetenv("PATH").split(KPATH_SEPARATOR)) { const QString dataDirFromPath = QFileInfo(QFile::decodeName(pathDir) + QStringLiteral("/data/") + path).canonicalFilePath(); if (fileReadable(dataDirFromPath)) { return dataDirFromPath; } } const QStringList correctedStandardLocations(correctStandardLocations(privateName, location, extraLocation)); for(const QString &dir : correctedStandardLocations) { fullPath = QFileInfo(dir + QLatin1Char('/') + path).canonicalFilePath(); if (fileReadable(fullPath)) { return fullPath; } } return QString(); } bool registerIconsResource(const QString &privateName, const QString& path, QStandardPaths::StandardLocation location, const QString &resourceRoot, const QString &extraLocation, QString *errorMessage, QString *detailedErrorMessage) { const QString fullPath = locateFile(privateName, path, location, extraLocation); if (fullPath.isEmpty() || !QFileInfo(fullPath).isReadable() || !QResource::registerResource(fullPath, resourceRoot)) { QStringList triedLocations(QStandardPaths::standardLocations(location)); if (!extraLocation.isEmpty()) { triedLocations.append(extraLocation); } triedLocations.append(correctStandardLocations(privateName, location, extraLocation)); const QString triedLocationsString = QLocale().createSeparatedList(triedLocations); #ifdef QT_ONLY *errorMessage = QString("Could not open icon resource file %1.").arg(path); *detailedErrorMessage = QString("Tried to find in %1.").arg(triedLocationsString); #else //! @todo 3.1 Re-add translation *errorMessage = /*QObject::tr*/ QString::fromLatin1( "Could not open icon resource file \"%1\". " "Application will not start. " "Please check if it is properly installed.") .arg(QFileInfo(path).fileName()); //! @todo 3.1 Re-add translation *detailedErrorMessage = QString::fromLatin1("Tried to find in %1.").arg(triedLocationsString); #endif return false; } *errorMessage = QString(); *detailedErrorMessage = QString(); return true; } bool registerGlobalIconsResource(const QString &themeName, QString *errorMessage, QString *detailedErrorMessage) { QString extraLocation; #ifdef CMAKE_INSTALL_FULL_ICONDIR extraLocation = QDir::fromNativeSeparators(QFile::decodeName(CMAKE_INSTALL_FULL_ICONDIR)); if (extraLocation.endsWith("/icons")) { extraLocation.chop(QLatin1String("/icons").size()); } #elif defined(Q_OS_WIN) extraLocation = QCoreApplication::applicationDirPath() + QStringLiteral("/data"); #endif return registerIconsResource(QString(), QString::fromLatin1("icons/%1/%1-icons.rcc").arg(themeName), QStandardPaths::GenericDataLocation, QStringLiteral("/icons/") + themeName, extraLocation, errorMessage, detailedErrorMessage); } bool registerGlobalIconsResource(const QString &themeName) { QString errorMessage; QString detailedErrorMessage; if (!registerGlobalIconsResource(themeName, &errorMessage, &detailedErrorMessage)) { if (detailedErrorMessage.isEmpty()) { KMessageBox::error(nullptr, errorMessage); } else { KMessageBox::detailedError(nullptr, errorMessage, detailedErrorMessage); } qWarning() << qPrintable(errorMessage); return false; } return true; } bool registerGlobalIconsResource() { return registerGlobalIconsResource(supportedIconTheme); } bool setupPrivateIconsResource(const QString &privateName, const QString& path, const QString &themeName, QString *errorMessage, QString *detailedErrorMessage, const QString &prefix) { // Register application's resource first to have priority over the theme. // Some icons may exists in both resources. if (!registerIconsResource(privateName, path, QStandardPaths::AppDataLocation, QString(), QString(), errorMessage, detailedErrorMessage)) { return false; } bool changeTheme = false; #ifdef QT_GUI_LIB QIcon::setThemeSearchPaths(QStringList() << prefix << QIcon::themeSearchPaths()); changeTheme = 0 != QIcon::themeName().compare(themeName, Qt::CaseInsensitive); if (changeTheme) { QIcon::setThemeName(themeName); } #endif KConfigGroup cg(KSharedConfig::openConfig(), "Icons"); changeTheme = changeTheme || 0 != cg.readEntry("Theme", QString()).compare(themeName, Qt::CaseInsensitive); // tell KIconLoader an co. about the theme if (changeTheme) { cg.writeEntry("Theme", themeName); cg.sync(); } return true; } bool setupPrivateIconsResourceWithMessage(const QString &privateName, const QString& path, const QString &themeName, QString *errorMessage, QString *detailedErrorMessage, const QString &prefix) { if (!setupPrivateIconsResource(privateName, path, themeName, errorMessage, detailedErrorMessage, prefix)) { if (detailedErrorMessage->isEmpty()) { KMessageBox::error(nullptr, *errorMessage); } else { KMessageBox::detailedError(nullptr, *errorMessage, *detailedErrorMessage); } return false; } return true; } bool setupPrivateIconsResourceWithMessage(const QString &privateName, const QString& path, QString *errorMessage, QString *detailedErrorMessage, const QString &prefix) { return setupPrivateIconsResourceWithMessage(privateName, path, supportedIconTheme, errorMessage, detailedErrorMessage, prefix); } bool setupPrivateIconsResourceWithMessage(const QString &privateName, const QString& path, QtMsgType messageType, const QString &prefix) { QString errorMessage; QString detailedErrorMessage; if (!setupPrivateIconsResourceWithMessage(privateName, path, &errorMessage, &detailedErrorMessage, prefix)) { if (messageType == QtFatalMsg) { qFatal("%s %s", qPrintable(errorMessage), qPrintable(detailedErrorMessage)); } else { qWarning() << qPrintable(errorMessage) << qPrintable(detailedErrorMessage); } return false; } return true; } bool setupGlobalIconTheme() { if (0 != QIcon::themeName().compare(supportedIconTheme, Qt::CaseInsensitive)) { const QString message = QString::fromLatin1( "\"%1\" supports only \"%2\" icon theme but current system theme is \"%3\". " "Application's icon theme will be changed to \"%2\". " "Please consider adding support for other themes to %4.") .arg(QLatin1String(KREPORT_BASE_NAME)).arg(supportedIconTheme).arg(QIcon::themeName()) .arg(QCoreApplication::applicationName()); qDebug() << qPrintable(message); if (!registerGlobalIconsResource()) { // don't fail, just warn const QString message = QString::fromLatin1( "Failed to set icon theme to \"%1\". Icons in the application will be inconsistent. " "Please install .rcc file(s) for the system theme.") .arg(supportedIconTheme); qDebug() << qPrintable(message); return false; } } return true; } int dpiX() { return s_instance->m_dpiX; } int dpiY() { return s_instance->m_dpiY; } +PageLayout::PageLayout() : QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF(0,0,0,0)) +{ +} + +PageLayout::PageLayout(const QPageLayout& pageLayout) : QPageLayout(pageLayout) +{ +} + +KReportPrivate::PageLayout & PageLayout::operator=(const QPageLayout& other) +{ + QPageLayout::operator=(other); + return *this; +} + } diff --git a/src/common/KReportUtils_p.h b/src/common/KReportUtils_p.h index 5d4351b1..bbe09010 100644 --- a/src/common/KReportUtils_p.h +++ b/src/common/KReportUtils_p.h @@ -1,173 +1,185 @@ /* This file is part of the KDE project 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 Library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KREPORTUTILS_P_H #define KREPORTUTILS_P_H #include #include #include #include #include #include #include #include #include #include #include #include +#include #ifdef Q_WS_X11 #include #else #include #endif // This is a private code made inline for use in the lib and examples. //! @todo Move to a shared lib to use in other Kexi libraries as well. namespace KReportPrivate { //! @todo Support other themes const QString supportedIconTheme = QLatin1String("breeze"); //! @brief @return true if @a path is readable bool fileReadable(const QString &path); //! @brief Used for a workaround: locations for QStandardPaths::AppDataLocation end with app name. //! If this is not an expected app but for example a test app, replace //! the subdir name with app name so we can find resource file(s). QStringList correctStandardLocations(const QString &privateName, QStandardPaths::StandardLocation location, const QString &extraLocation); /*! @brief Locates a file path for specified parameters * @param privateName Name to be used instead of application name for resource lookup * @param path Relative path to the resource file * @param location Standard file location to use for file lookup * @param extraLocation Extra directory path for file lookup * @return Empty string on failure */ QString locateFile(const QString &privateName, const QString& path, QStandardPaths::StandardLocation location, const QString &extraLocation); /*! @brief Registers icons resource file * @param privateName Name to be used instead of application name for resource lookup * @param path Relative path to the resource file * @param location Standard file location to use for file lookup * @param resourceRoot A resource root for QResource::registerResource() * @param errorMessage On failure it is set to a brief error message. * @param errorDescription On failure it is set to a detailed error message. * other for warning */ bool registerIconsResource(const QString &privateName, const QString& path, QStandardPaths::StandardLocation location, const QString &resourceRoot, const QString &extraLocation, QString *errorMessage, QString *detailedErrorMessage); /*! @brief Registers a global icon resource file * @param themeName A name of icon theme to use. * @param errorMessage On failure it is set to a brief error message. * @param errorDescription On failure it is set to a detailed error message. * other for warning */ bool registerGlobalIconsResource(const QString &themeName, QString *errorMessage, QString *detailedErrorMessage); /*! @brief Registers a global icon resource file * @param themeName A name of icon theme to use. */ bool registerGlobalIconsResource(const QString &themeName); /*! @brief Registers a global icon resource file for default theme name. */ bool registerGlobalIconsResource(); /*! @brief Sets up a private icon resource file * @return @c false on failure and sets error message. Does not warn or exit on failure. * @param privateName Name to be used instead of application name for resource lookup * @param path Relative path to the resource file * @param themeName Icon theme to use. It affects filename. * @param errorMessage On failure it is set to a brief error message * @param errorDescription On failure it is set to a detailed error message * other for warning * @param prefix Resource path prefix. The default is useful for library-global resource, * other values is useful for plugins. */ bool setupPrivateIconsResource(const QString &privateName, const QString& path, const QString &themeName, QString *errorMessage, QString *detailedErrorMessage, const QString &prefix = QLatin1String(":/icons")); /*! @brief Sets up a private icon resource file * @return @c false on failure and sets error message. * @param privateName Name to be used instead of application name for resource lookup * @param path Relative path to the resource file * @param themeName Icon theme to use. It affects filename. * @param errorMessage On failure it is set to a brief error message. * @param errorDescription On failure it is set to a detailed error message. * other for warning * @param prefix Resource path prefix. The default is useful for library-global resource, * other values is useful for plugins. */ bool setupPrivateIconsResourceWithMessage(const QString &privateName, const QString& path, const QString &themeName, QString *errorMessage, QString *detailedErrorMessage, const QString &prefix = QLatin1String(":/icons")); /*! @overload setupPrivateIconsResourceWithMessage(QString &privateName, const QString& path, const QString &themeName, QString *errorMessage, QString *detailedErrorMessage, const QString &prefix = QLatin1String(":/icons")) Uses default theme name. */ bool setupPrivateIconsResourceWithMessage(const QString &privateName, const QString& path, QString *errorMessage, QString *detailedErrorMessage, const QString &prefix = QLatin1String(":/icons")); /*! @brief Sets up a private icon resource file * Warns on failure and returns @c false. * @param privateName Name to be used instead of application name for resource lookup * @param path Relative path to the resource file * @param messageType Type of message to use on error, QtFatalMsg for fatal exit and any * other for warning * @param prefix Resource path prefix. The default is useful for library-global resource, * other values is useful for plugins. */ bool setupPrivateIconsResourceWithMessage(const QString &privateName, const QString& path, QtMsgType messageType, const QString &prefix = QLatin1String(":/icons")); //! Sets up a global icon theme if it is different from supported. //! Warns on failure and returns @c false. bool setupGlobalIconTheme(); int dpiX(); int dpiY(); +//! This class is wrapper that fixes a critical QTBUG-47551 bug in default constructor of QPageLayout +//! Default constructor of QPageLayout does not initialize units. +//! https://bugreports.qt.io/browse/QTBUG-47551 +//! @todo remove this class and go back to QPageLayout when the faulty QPageLayout implementations are no longer on the wild. That's probably for Qt 6. +class PageLayout: public QPageLayout { +public: + PageLayout(); + PageLayout(const QPageLayout& pageLayout); + PageLayout& operator=(const QPageLayout& other); +}; + } // KReportPrivate #endif diff --git a/src/wrtembed/KReportDesigner.cpp b/src/wrtembed/KReportDesigner.cpp index d43d2175..e82a91f4 100644 --- a/src/wrtembed/KReportDesigner.cpp +++ b/src/wrtembed/KReportDesigner.cpp @@ -1,1534 +1,1533 @@ /* 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 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 "KReportDesignerSection.h" #include "KReportDesignerSectionScene.h" #include "KReportDesignerSectionView.h" #include "KReportDesignerSectionDetailGroup.h" #include "KReportPropertiesButton.h" #include "KReportSectionEditor.h" #include "KReportDesignerSectionDetail.h" #include "KReportDesignerItemLine.h" #include "KReportRuler_p.h" #include "KReportZoomHandler.h" #include "KReportPageSize.h" #include "KReportUtils_p.h" #include "KReportUtils.h" #include "KReportPluginInterface.h" #include "KReportPluginManager.h" #include "KReportSection.h" #include "KReportPluginMetaData.h" #include "kreport_debug.h" #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 = ReportWriterSectionData::MA_None; } virtual ~ReportWriterSectionData() { } 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; MouseAction mouseAction; QString insertItem; QList copy_list; QList cut_list; }; //! @internal class Q_DECL_HIDDEN KReportDesigner::Private { public: Private(){} ~Private() { delete zoom; delete sectionData; delete set; delete kordata; } QGridLayout *grid; KReportRuler *hruler; KReportZoomHandler *zoom; 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 *itmset; KProperty *title; KProperty *pageSize; KProperty *orientation; KProperty *unit; KProperty *customHeight; KProperty *customWidth; 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 KReportData *kordata = nullptr; }; KReportDesigner::KReportDesigner(QWidget * parent) : QWidget(parent), d(new Private()) { init(); } void KReportDesigner::init() { KReportPluginManager::self(); // this loads icons early enough d->sectionData = new ReportWriterSectionData(); createProperties(); 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); d->vboxlayout = new QVBoxLayout(); d->vboxlayout->setSpacing(0); d->vboxlayout->setMargin(0); d->vboxlayout->setSizeConstraint(QLayout::SetFixedSize); //Create nice rulers d->zoom = new KReportZoomHandler(); d->hruler = new KReportRuler(this, Qt::Horizontal, d->zoom); d->pageButton = new KReportPropertiesButton(this); d->hruler->setUnit(KReportUnit(KReportUnit::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)); 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); connect(d->set, SIGNAL(propertyChanged(KPropertySet&,KProperty&)), this, SLOT(slotPropertyChanged(KPropertySet&,KProperty&))); changeSet(d->set); } KReportDesigner::~KReportDesigner() { delete d; } ///The loading Code KReportDesigner::KReportDesigner(QWidget *parent, const QDomElement &data) : QWidget(parent), d(new Private()) { init(); 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()); #ifdef KREPORT_SCRIPTING } else if (n == QLatin1String("report:script")) { d->originalInterpreter = it.toElement().attribute(QLatin1String("report:script-interpreter")); d->originalScript = it.firstChild().nodeValue(); d->script->setValue(d->originalScript); if (d->originalInterpreter != QLatin1String("javascript") && d->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); } #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"))); } //! @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"))); } else if (pagetype == QLatin1String("custom")) { d->pageSize->setValue(QLatin1String("custom")); d->customHeight->setValue(KReportUnit::parseValue(it.toElement().attribute(QLatin1String("report:custom-page-height"), QLatin1String("")))); d->customWidth->setValue(KReportUnit::parseValue(it.toElement().attribute(QLatin1String("report:custom-page-widtht"), 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")))); d->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)) == 0) { insertSection(KReportSectionData::sectionTypeFromString(sectiontype)); section(KReportSectionData::sectionTypeFromString(sectiontype))->initFromXML(sec); } } else if (sn == QLatin1String("report:detail")) { KReportDesignerSectionDetail * rsd = new KReportDesignerSectionDetail(this); rsd->initFromXML(&sec); 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); } ///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->script->value().toString().isEmpty()) { if (d->script->value().toString() != d->originalScript || d->originalInterpreter == QLatin1String("qtscript")) { //The script has changed so force interpreter to 'javascript'. Also set if was using qtscript saveInterpreter = QLatin1String("javascript"); } else { saveInterpreter = d->originalInterpreter; } 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->customWidth->value().toDouble()); KReportUtils::setAttribute(&pagestyle, QLatin1String("report:custom-page-height"), d->customHeight->value().toDouble()); } 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 = KReportSectionData::PageHeaderFirst; i <= KReportSectionData::PageFooterAny; ++i) { KReportDesignerSection *sec = section((KReportSectionData::Section)i); if (sec) { domsection = doc.createElement(QLatin1String("report:section")); domsection.setAttribute(QLatin1String("report:section-type"), KReportSectionData::sectionTypeString(KReportSectionData::Section(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::setReportData(KReportData* kodata) { if (d->kordata == kodata) { return; } delete d->kordata; d->kordata = kodata; slotPageButton_Pressed(); setModified(true); emit reportDataChanged(); } KReportDesignerSection * KReportDesigner::section(KReportSectionData::Section s) const { KReportDesignerSection *sec; switch (s) { case KReportSectionData::PageHeaderAny: sec = d->pageHeaderAny; break; case KReportSectionData::PageHeaderEven: sec = d->pageHeaderEven; break; case KReportSectionData::PageHeaderOdd: sec = d->pageHeaderOdd; break; case KReportSectionData::PageHeaderFirst: sec = d->pageHeaderFirst; break; case KReportSectionData::PageHeaderLast: sec = d->pageHeaderLast; break; case KReportSectionData::PageFooterAny: sec = d->pageFooterAny; break; case KReportSectionData::PageFooterEven: sec = d->pageFooterEven; break; case KReportSectionData::PageFooterOdd: sec = d->pageFooterOdd; break; case KReportSectionData::PageFooterFirst: sec = d->pageFooterFirst; break; case KReportSectionData::PageFooterLast: sec = d->pageFooterLast; break; case KReportSectionData::ReportHeader: sec = d->reportHeader; break; case KReportSectionData::ReportFooter: sec = d->reportFooter; break; default: sec = 0; } return sec; } void KReportDesigner::removeSection(KReportSectionData::Section s) { KReportDesignerSection* sec = section(s); if (sec) { delete sec; switch (s) { case KReportSectionData::PageHeaderAny: d->pageHeaderAny = 0; break; case KReportSectionData::PageHeaderEven: sec = d->pageHeaderEven = 0; break; case KReportSectionData::PageHeaderOdd: d->pageHeaderOdd = 0; break; case KReportSectionData::PageHeaderFirst: d->pageHeaderFirst = 0; break; case KReportSectionData::PageHeaderLast: d->pageHeaderLast = 0; break; case KReportSectionData::PageFooterAny: d->pageFooterAny = 0; break; case KReportSectionData::PageFooterEven: d->pageFooterEven = 0; break; case KReportSectionData::PageFooterOdd: d->pageFooterOdd = 0; break; case KReportSectionData::PageFooterFirst: d->pageFooterFirst = 0; break; case KReportSectionData::PageFooterLast: d->pageFooterLast = 0; break; case KReportSectionData::ReportHeader: d->reportHeader = 0; break; case KReportSectionData::ReportFooter: d->reportFooter = 0; break; default: sec = 0; } setModified(true); adjustSize(); } } void KReportDesigner::insertSection(KReportSectionData::Section s) { KReportDesignerSection* sec = section(s); if (!sec) { int idx = 0; for (int i = 1; i <= s; ++i) { if (section((KReportSectionData::Section)i)) idx++; } if (s > KReportSectionData::ReportHeader) idx++; //kreportDebug() << idx; KReportDesignerSection *rs = new KReportDesignerSection(this); d->vboxlayout->insertWidget(idx, rs); switch (s) { case KReportSectionData::PageHeaderAny: rs->setTitle(tr("Page Header (Any)")); d->pageHeaderAny = rs; break; case KReportSectionData::PageHeaderEven: rs->setTitle(tr("Page Header (Even)")); d->pageHeaderEven = rs; break; case KReportSectionData::PageHeaderOdd: rs->setTitle(tr("Page Header (Odd)")); d->pageHeaderOdd = rs; break; case KReportSectionData::PageHeaderFirst: rs->setTitle(tr("Page Header (First)")); d->pageHeaderFirst = rs; break; case KReportSectionData::PageHeaderLast: rs->setTitle(tr("Page Header (Last)")); d->pageHeaderLast = rs; break; case KReportSectionData::PageFooterAny: rs->setTitle(tr("Page Footer (Any)")); d->pageFooterAny = rs; break; case KReportSectionData::PageFooterEven: rs->setTitle(tr("Page Footer (Even)")); d->pageFooterEven = rs; break; case KReportSectionData::PageFooterOdd: rs->setTitle(tr("Page Footer (Odd)")); d->pageFooterOdd = rs; break; case KReportSectionData::PageFooterFirst: rs->setTitle(tr("Page Footer (First)")); d->pageFooterFirst = rs; break; case KReportSectionData::PageFooterLast: rs->setTitle(tr("Page Footer (Last)")); d->pageFooterLast = rs; break; case KReportSectionData::ReportHeader: rs->setTitle(tr("Report Header")); d->reportHeader = rs; break; case KReportSectionData::ReportFooter: rs->setTitle(tr("Report Footer")); d->reportFooter = rs; break; //These sections cannot be inserted this way case KReportSectionData::None: case KReportSectionData::GroupHeader: case KReportSectionData::GroupFooter: case KReportSectionData::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::itemPropertySet() const { return d->itmset; } KReportData *KReportDesigner::reportData() const { return d->kordata; } 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 mod) { d->modified = mod; if (d->modified) { emit dirty(); } } QStringList KReportDesigner::fieldNames() const { QStringList qs; qs << QString(); if (d->kordata) qs << d->kordata->fieldNames(); return qs; } QStringList KReportDesigner::fieldKeys() const { QStringList qs; qs << QString(); if (d->kordata) qs << d->kordata->fieldKeys(); return qs; } void KReportDesigner::createProperties() { QStringList keys, strings; d->set = new KPropertySet; 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")); keys.clear(); keys = KReportPageSize::pageFormatKeys(); strings = KReportPageSize::pageFormatNames(); QString defaultKey = KReportPageSize::pageSizeKey(KReportPageSize::defaultSize()); d->pageSize = new KProperty("page-size", keys, strings, defaultKey, tr("Page Size")); keys.clear(); strings.clear(); keys << QLatin1String("portrait") << QLatin1String("landscape"); strings << tr("Portrait") << tr("Landscape"); d->orientation = new KProperty("print-orientation", keys, strings, QLatin1String("portrait"), tr("Page Orientation")); keys.clear(); strings.clear(); strings = KReportUnit::listOfUnitNameForUi(KReportUnit::HidePixel); QString unit; foreach(const QString &un, strings) { unit = un.mid(un.indexOf(QLatin1String("(")) + 1, 2); keys << unit; } d->unit = new KProperty("page-unit", keys, strings, 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::Centimeter).fromUserValue(1.0), tr("Left Margin"), tr("Left Margin"), KProperty::Double); d->rightMargin = new KProperty("margin-right", KReportUnit(KReportUnit::Centimeter).fromUserValue(1.0), tr("Right Margin"), tr("Right Margin"), KProperty::Double); d->topMargin = new KProperty("margin-top", KReportUnit(KReportUnit::Centimeter).fromUserValue(1.0), tr("Top Margin"), tr("Top Margin"), KProperty::Double); d->bottomMargin = new KProperty("margin-bottom", KReportUnit(KReportUnit::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->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", QStringList(), QStringList(), QString(), tr("Object Script")); d->set->addProperty(d->script); #endif // KProperty* _customHeight; // KProperty* _customWidth; } /** @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); } } void KReportDesigner::slotPageButton_Pressed() { #ifdef KREPORT_SCRIPTING if (d->kordata) { QStringList sl = d->kordata->scriptList(); sl.prepend(QLatin1String("")); d->script->setListData(sl, sl); } 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 { - QPageLayout layout; - layout.setPageSize(QPageSize(KReportPageSize::pageSize(d->set->property("page-size").value().toString()))); - layout.setOrientation(d->set->property("print-orientation").value().toString() == QLatin1String("portrait") ? QPageLayout::Portrait : QPageLayout::Landscape); + 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));; + QSize pageSizePx = layout.fullRectPixels(KReportPrivate::dpiX()).size(); int width = pageSizePx.width(); width = width - POINT_TO_INCH(d->set->property("margin-left").value().toDouble()) * KReportPrivate::dpiX(); width = width - POINT_TO_INCH(d->set->property("margin-right").value().toDouble()) * KReportPrivate::dpiX(); return width; } 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 = 0; } KReportUnit KReportDesigner::pageUnit() const { QString u; bool found; u = d->unit->value().toString(); KReportUnit unit = KReportUnit::fromSymbol(u, &found); if (!found) { unit = KReportUnit(KReportUnit::Centimeter); } return 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::MA_Insert) { QGraphicsItem * item = 0; QString classString; QString iconName; if (d->sectionData->insertItem == 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->insertItem); 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); changeSet(set); if (v && v->designer()) { v->designer()->setModified(true); } emit itemInserted(d->sectionData->insertItem); } } d->sectionData->mouseAction = ReportWriterSectionData::MA_None; d->sectionData->insertItem.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); d->itmset = s; emit propertySetChanged(); } // // Actions // void KReportDesigner::slotItem(const QString &entity) { //kreportDebug() << entity; d->sectionData->mouseAction = ReportWriterSectionData::MA_Insert; d->sectionData->insertItem = entity; setSectionCursor(QCursor(Qt::CrossCursor)); } void KReportDesigner::slotEditDelete() { QGraphicsItem * item = 0; 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::MA_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 = 0; if (activeItems.count() == 1) { activeItem = activeItems.first(); } canvas->clearSelection(); d->sectionData->mouseAction = ReportWriterSectionData::MA_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))); } 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::MA_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(); } KReportZoomHandler* KReportDesigner::zoomHandler() const { return d->zoom; } QString KReportDesigner::suggestEntityName(const QString &n) const { KReportDesignerSection *sec; int itemCount = 0; //Count items in the main sections for (int i = 1; i <= KReportSectionData::PageFooterAny; i++) { sec = section((KReportSectionData::Section) 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(n + QString::number(itemCount))) { itemCount++; } return n + QString::number(itemCount); } bool KReportDesigner::isEntityNameUnique(const QString &n, KReportItemBase* ignore) const { KReportDesignerSection *sec; bool unique = true; //Check items in the main sections for (int i = 1; i <= KReportSectionData::PageFooterAny; i++) { sec = section((KReportSectionData::Section)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() == n && 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() == n && 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() == n && 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() == 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 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); }