diff --git a/src/common/KReportDocument.cpp b/src/common/KReportDocument.cpp index 61277c86..aa223622 100644 --- a/src/common/KReportDocument.cpp +++ b/src/common/KReportDocument.cpp @@ -1,387 +1,388 @@ /* 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; KReportPrivate::PageLayout pageLayout; QString pageSize; QString labelType; }; void KReportDocument::init() { m_pageHeaderFirst = m_pageHeaderOdd = m_pageHeaderEven = m_pageHeaderLast = m_pageHeaderAny = nullptr; m_pageFooterFirst = m_pageFooterOdd = m_pageFooterEven = m_pageFooterLast = m_pageFooterAny = nullptr; m_reportHeader = m_reportFooter = nullptr; } KReportDocument::KReportDocument(QObject *parent) : QObject(parent), m_detailSection(nullptr), d(new Private()) { init(); d->valid = true; } KReportDocument::KReportDocument(const QDomElement & elemSource, QObject *parent) : QObject(parent), m_detailSection(nullptr), 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->pageLayout.setMode(QPageLayout::FullPageMode); if (pagetype == QLatin1String("predefined")) { setPageSize(elemThis.attribute(QLatin1String("report:page-size"), QLatin1String("A4"))); 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")); + kreportDebug() << "Setting custom page size in document to " << KReportUnit::parseValue(elemThis.attribute(QLatin1String("report:custom-page-width"), QLatin1String("5.0cm"))) << KReportUnit::parseValue(elemThis.attribute(QLatin1String("report:custom-page-height"), QLatin1String("5.0cm"))) ; + QPageSize custom(QSize(KReportUnit::parseValue(elemThis.attribute(QLatin1String("report:custom-page-width"), QLatin1String("5.0cm"))) , KReportUnit::parseValue(elemThis.attribute(QLatin1String("report:custom-page-height"), QLatin1String("5.0cm"))) ), QString(), QPageSize::ExactMatch); 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->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::Type::PageHeaderFirst: m_pageHeaderFirst = sd; break; case KReportSectionData::Type::PageHeaderOdd: m_pageHeaderOdd = sd; break; case KReportSectionData::Type::PageHeaderEven: m_pageHeaderEven = sd; break; case KReportSectionData::Type::PageHeaderLast: m_pageHeaderLast = sd; break; case KReportSectionData::Type::PageHeaderAny: m_pageHeaderAny = sd; break; case KReportSectionData::Type::ReportHeader: m_reportHeader = sd; break; case KReportSectionData::Type::ReportFooter: m_reportFooter = sd; break; case KReportSectionData::Type::PageFooterFirst: m_pageFooterFirst = sd; break; case KReportSectionData::Type::PageFooterOdd: m_pageFooterOdd = sd; break; case KReportSectionData::Type::PageFooterEven: m_pageFooterEven = sd; break; case KReportSectionData::Type::PageFooterLast: m_pageFooterLast = sd; break; case KReportSectionData::Type::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 = static_cast(KReportSectionData::Type::PageHeaderFirst); i <= static_cast(KReportSectionData::Type::PageFooterAny); i++) { KReportSectionData *sec = section(static_cast(i)); if (sec) { obs << sec->objects(); } } if (m_detailSection) { //kreportDebug() << "Number of groups: " << m_detailSection->m_groupList.count(); foreach(KReportDetailGroupSectionData* g, m_detailSection->groupList) { if (g->groupHeader) { obs << g->groupHeader->objects(); } if (g->groupFooter) { obs << g->groupFooter->objects(); } } if (m_detailSection->detailSection) obs << m_detailSection->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 nullptr; } QList KReportDocument::sections() const { QList secs; for (int i = static_cast(KReportSectionData::Type::PageHeaderFirst); i <= static_cast(KReportSectionData::Type::PageFooterAny); i++) { KReportSectionData *sec = section(static_cast(i)); if (sec) { secs << sec; } } if (m_detailSection) { //kreportDebug() << "Number of groups: " << m_detailSection->m_groupList.count(); foreach(KReportDetailGroupSectionData* g, m_detailSection->groupList) { if (g->groupHeader) { secs << g->groupHeader; } if (g->groupFooter) { secs << g->groupFooter; } } if (m_detailSection->detailSection) secs << m_detailSection->detailSection; } return secs; } KReportSectionData* KReportDocument::section(const QString& sn) const { QList secs = sections(); foreach(KReportSectionData *sec, secs) { if (sec->name() == sn) { return sec; } } return nullptr; } KReportSectionData* KReportDocument::section(KReportSectionData::Type type) const { KReportSectionData *sec; switch (type) { case KReportSectionData::Type::PageHeaderAny: sec = m_pageHeaderAny; break; case KReportSectionData::Type::PageHeaderEven: sec = m_pageHeaderEven; break; case KReportSectionData::Type::PageHeaderOdd: sec = m_pageHeaderOdd; break; case KReportSectionData::Type::PageHeaderFirst: sec = m_pageHeaderFirst; break; case KReportSectionData::Type::PageHeaderLast: sec = m_pageHeaderLast; break; case KReportSectionData::Type::PageFooterAny: sec = m_pageFooterAny; break; case KReportSectionData::Type::PageFooterEven: sec = m_pageFooterEven; break; case KReportSectionData::Type::PageFooterOdd: sec = m_pageFooterOdd; break; case KReportSectionData::Type::PageFooterFirst: sec = m_pageFooterFirst; break; case KReportSectionData::Type::PageFooterLast: sec = m_pageFooterLast; break; case KReportSectionData::Type::ReportHeader: sec = m_reportHeader; break; case KReportSectionData::Type::ReportFooter: sec = m_reportFooter; break; default: sec = nullptr; } return sec; } QPageLayout KReportDocument::pageLayout() const { 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/KReportPageSize.cpp b/src/common/KReportPageSize.cpp index 7505af5e..46509d00 100644 --- a/src/common/KReportPageSize.cpp +++ b/src/common/KReportPageSize.cpp @@ -1,92 +1,94 @@ /* This file is part of the KDE project Copyright (C) 2015 by 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 "KReportPageSize.h" #include #include struct KReportPageSizeInfo { const char *name; struct { const char *source; const char *comment; } description; QPageSize::PageSizeId pageSize; }; static const KReportPageSizeInfo pageSizeInfo[] = { { "A3", QT_TRANSLATE_NOOP3("KReportPageFormat", "A3", ""), QPageSize::A3}, { "A4", QT_TRANSLATE_NOOP3("KReportPageFormat", "A4", ""), QPageSize::A4}, { "A5", QT_TRANSLATE_NOOP3("KReportPageFormat", "A5", ""), QPageSize::A5}, { "Letter", QT_TRANSLATE_NOOP3("KReportPageFormat", "US Letter", "Usually don't translate literally, use \"US Letter\""), QPageSize::Letter}, { "Legal", QT_TRANSLATE_NOOP3("KReportPageFormat", "US Legal", "Usually don't translate literally, use \"US Legal\""), QPageSize::Legal}, { "Screen", QT_TRANSLATE_NOOP3("KReportPageFormat", "Screen", ""), QPageSize::A4}, + { "Custom", QT_TRANSLATE_NOOP3("KReportPageFormat", "Custom", ""), QPageSize::Custom}, { "", {"", ""}, QPageSize::LastPageSize} + }; QStringList KReportPageSize::pageFormatNames() { QStringList lst; for (int i = 0; pageSizeInfo[i].pageSize != QPageSize::LastPageSize ;i++) { lst << QCoreApplication::translate("KReportPageFormat", pageSizeInfo[ i ].description.source, pageSizeInfo[ i ].description.comment); } return lst; } QStringList KReportPageSize::pageFormatKeys() { QStringList lst; for (int i = 0; pageSizeInfo[i].pageSize != QPageSize::LastPageSize ;i++) { lst << QLatin1String(pageSizeInfo[ i ].name); } return lst; } QPageSize::PageSizeId KReportPageSize::defaultSize() { QPrinterInfo printerInfo = QPrinterInfo::defaultPrinter(); QPageSize size = printerInfo.defaultPageSize(); if (size.isValid()) { return size.id(); } return QPageSize::A4; } QString KReportPageSize::pageSizeKey(QPageSize::PageSizeId id) { for (int i = 0; pageSizeInfo[i].pageSize != QPageSize::LastPageSize ;i++) { if (pageSizeInfo[i].pageSize == id) { return QLatin1String(pageSizeInfo[i].name); } } return QString(); } QPageSize::PageSizeId KReportPageSize::pageSize(const QString &size) { for (int i = 0; pageSizeInfo[i].pageSize != QPageSize::LastPageSize ;i++) { if (QLatin1String(pageSizeInfo[i].name) == size) { return pageSizeInfo[i].pageSize; } } return defaultSize(); } diff --git a/src/renderer/KReportPage.cpp b/src/renderer/KReportPage.cpp index 1b4cdba4..94d37893 100644 --- a/src/renderer/KReportPage.cpp +++ b/src/renderer/KReportPage.cpp @@ -1,130 +1,116 @@ /* 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 "KReportPage.h" #include "KReportRendererBase.h" #include "KReportUnit.h" #include "KReportRenderObjects.h" #include "KReportUtils_p.h" #include "kreport_debug.h" #include #include #include #include #include //! @internal class Q_DECL_HIDDEN KReportPage::Private { public: explicit Private(ORODocument *document) : reportDocument(document) {} ~Private() { delete renderer; } QPointer reportDocument; int page; QPixmap pixmap; KReportRendererFactory factory; KReportRendererBase *renderer; QTimer renderTimer; }; KReportPage::KReportPage(QWidget *parent, ORODocument *document) : QObject(parent), QGraphicsRectItem() , d(new Private(document)) { Q_ASSERT(document); int pageWidth; int pageHeight; - QString pageSize = d->reportDocument->pageLayout().pageSize().name(); - pageWidth = d->reportDocument->pageLayout().fullRectPixels(KReportPrivate::dpiX()).width(); pageHeight = d->reportDocument->pageLayout().fullRectPixels(KReportPrivate::dpiX()).height(); -//TODO remove after check -#if 0 - if (pageSize == QLatin1String("Custom")) { - // if this is custom sized sheet of paper we will just use those values - - } else { - // lookup the correct size information for the specified size paper - pageWidth = d->reportDocument->pageOptions().pixelSize().width(); - pageHeight = d->reportDocument->pageOptions().pixelSize().height(); - } -#endif - setRect(0, 0, pageWidth, pageHeight); //kreportDebug() << "PAGE IS " << pageWidth << "x" << pageHeight; d->pixmap = QPixmap(pageWidth, pageHeight); d->renderer = d->factory.createInstance(QLatin1String("screen")); connect(d->reportDocument, SIGNAL(updated(int)), this, SLOT(pageUpdated(int))); d->renderTimer.setSingleShot(true); connect(&d->renderTimer, SIGNAL(timeout()), this, SLOT(renderCurrentPage())); renderPage(1); } KReportPage::~KReportPage() { delete d; } void KReportPage::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) { Q_UNUSED(option); Q_UNUSED(widget); painter->drawPixmap(QPoint(0, 0), d->pixmap); } void KReportPage::renderPage(int page) { d->page = page - 1; d->pixmap.fill(); QPainter qp(&d->pixmap); if (d->reportDocument) { KReportRendererContext cxt; cxt.setPainter(&qp); (void)d->renderer->render(cxt, d->reportDocument, d->page); } update(); } void KReportPage::pageUpdated(int pageNo) { //kreportDebug() << pageNo << d->page; //Refresh this page if it changes if (pageNo == d->page) { //kreportDebug() << "Current page updated"; d->renderTimer.start(100); } } void KReportPage::renderCurrentPage() { renderPage(d->page + 1); } diff --git a/src/renderer/KReportPrintRenderer_p.cpp b/src/renderer/KReportPrintRenderer_p.cpp index f2821c84..c5d3549c 100644 --- a/src/renderer/KReportPrintRenderer_p.cpp +++ b/src/renderer/KReportPrintRenderer_p.cpp @@ -1,247 +1,247 @@ /* 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 "KReportPrintRenderer_p.h" #include "kreport_debug.h" #include "KReportRenderObjects.h" #include "KReportPageSize.h" #include "KReportUtils_p.h" #include #include #include namespace KReportPrivate { PrintRenderer::PrintRenderer() { } PrintRenderer::~PrintRenderer() { } bool PrintRenderer::setupPrinter( ORODocument * document, QPrinter * pPrinter) { if (document == nullptr || pPrinter == nullptr) return false; pPrinter->setCreator(QLatin1String("KReport Print Renderer")); pPrinter->setDocName(document->title()); pPrinter->setFullPage(true); pPrinter->setOrientation((document->pageLayout().orientation() == QPageLayout::Portrait ? QPrinter::Portrait : QPrinter::Landscape)); pPrinter->setPageOrder(QPrinter::FirstPageFirst); - if (!document->pageLayout().pageSize().isValid()) { - pPrinter->setPageSize(QPrinter::Custom); - } else { +// if (!document->pageLayout().pageSize().isValid()) { +// pPrinter->setPageSize(QPageSize(QSize(document->pageLayout().getCustomWidth(), document->pageLayout().getCustomHeight()), QLatin1String("Custom")); +// } else { pPrinter->setPageSize(QPageSize(document->pageLayout().pageSize())); - } +// } return true; } bool PrintRenderer::render(const KReportRendererContext &context, ORODocument *document, int page) { Q_UNUSED(page); if (document == nullptr || context.printer() == nullptr || context.painter() == nullptr) return false; setupPrinter(document, context.printer()); bool endWhenComplete = false; if (!context.painter()->isActive()) { endWhenComplete = true; if (!context.painter()->begin(context.printer())) return false; } int fromPage = context.printer()->fromPage(); if (fromPage > 0) fromPage -= 1; int toPage = context.printer()->toPage(); if (toPage == 0 || toPage > document->pageCount()) toPage = document->pageCount(); qreal scaleX = context.printer()->resolution() / qreal(KReportPrivate::dpiX()); qreal scaleY = context.printer()->resolution() / qreal(KReportPrivate::dpiY()); for (int copy = 0; copy < context.printer()->numCopies(); copy++) { for (int page = fromPage; page < toPage; page++) { if (page > fromPage) context.printer()->newPage(); OROPage * p = document->page(page); if (context.printer()->pageOrder() == QPrinter::LastPageFirst) p = document->page(toPage - 1 - page); // Render Page Objects for (int i = 0; i < p->primitiveCount(); i++) { OROPrimitive * prim = p->primitive(i); prim->setPosition(QPointF(prim->position().x() * scaleX, prim->position().y() * scaleY)); prim->setSize(QSizeF(prim->size().width() * scaleX, prim->size().height() * scaleY)); //kreportDebug() << "Rendering object" << i << "type" << prim->type(); if (OROTextBox *tb = dynamic_cast(prim)) { QPointF ps = tb->position(); QSizeF sz = tb->size(); QRectF rc = QRectF(ps.x(), ps.y(), sz.width(), sz.height()); context.painter()->save(); //Background QColor bg = tb->textStyle().backgroundColor; bg.setAlphaF(0.01 * tb->textStyle().backgroundOpacity); //_painter()->setBackgroundMode(Qt::OpaqueMode); context.painter()->fillRect(rc, bg); //Text context.painter()->setBackgroundMode(Qt::TransparentMode); context.painter()->setFont(tb->textStyle().font); context.painter()->setPen(tb->textStyle().foregroundColor); context.painter()->drawText(rc, tb->flags(), tb->text()); //outer line context.painter()->setPen(QPen(tb->lineStyle().color(), tb->lineStyle().weight() * scaleX, tb->lineStyle().penStyle())); context.painter()->drawRect(rc); //Reset back to defaults for next element context.painter()->restore(); } else if (OROLine *ln = dynamic_cast(prim)) { QPointF s = ln->startPoint(); QPointF e(ln->endPoint().x() * scaleX, ln->endPoint().y() * scaleY); //QPen pen ( _painter()->pen() ); QPen pen(ln->lineStyle().color(), ln->lineStyle().weight() * scaleX, ln->lineStyle().penStyle()); context.painter()->save(); context.painter()->setRenderHint(QPainter::Antialiasing, true); context.painter()->setPen(pen); context.painter()->drawLine(QLineF(s.x(), s.y(), e.x(), e.y())); context.painter()->setRenderHint(QPainter::Antialiasing, false); context.painter()->restore(); } else if (OROImage *im = dynamic_cast(prim)) { QPointF ps = im->position(); QSizeF sz = im->size(); QRectF rc = QRectF(ps.x(), ps.y(), sz.width(), sz.height()); QImage img = im->image(); if (im->isScaled()) img = img.scaled(rc.size().toSize(), (Qt::AspectRatioMode) im->aspectRatioMode(), (Qt::TransformationMode) im->transformationMode()); QRectF sr = QRectF(QPointF(0.0, 0.0), rc.size().boundedTo(img.size())); context.painter()->drawImage(rc.topLeft(), img, sr); } else if (ORORect *re = dynamic_cast(prim)) { QPointF ps = re->position(); QSizeF sz = re->size(); QRectF rc = QRectF(ps.x(), ps.y(), sz.width(), sz.height()); context.painter()->save(); context.painter()->setPen(re->pen()); context.painter()->setBrush(re->brush()); context.painter()->drawRect(rc); context.painter()->restore(); } else if (OROEllipse *re = dynamic_cast(prim)) { QPointF ps = re->position(); QSizeF sz = re->size(); QRectF rc = QRectF(ps.x(), ps.y(), sz.width(), sz.height()); context.painter()->save(); context.painter()->setPen(re->pen()); context.painter()->setBrush(re->brush()); context.painter()->drawEllipse(rc); context.painter()->restore(); } else if (OROPicture *im = dynamic_cast(prim)) { QPointF ps = im->position(); QSizeF sz = im->size(); QRectF rc = QRectF(ps.x(), ps.y(), sz.width(), sz.height()); context.painter()->drawPicture(rc.topLeft(), *(im->picture())); } else if (OROCheckBox *chk = dynamic_cast(prim)) { QPointF ps = chk->position(); QSizeF sz = chk->size(); QRectF rc = QRectF(ps.x(), ps.y(), sz.width(), sz.height()); context.painter()->save(); context.painter()->setBackgroundMode(Qt::OpaqueMode); context.painter()->setRenderHint(QPainter::Antialiasing); context.painter()->setPen(chk->foregroundColor()); if (chk->lineStyle().penStyle() == Qt::NoPen || chk->lineStyle().weight() <= 0) { context.painter()->setPen(QPen(Qt::lightGray)); } else { context.painter()->setPen(QPen(chk->lineStyle().color(), chk->lineStyle().weight() * scaleX, chk->lineStyle().penStyle())); } qreal ox = sz.width() / 5; qreal oy = sz.height() / 5; //Checkbox Style if (chk->checkType() == OROCheckBox::Type::Cross) { context.painter()->drawRoundedRect(rc, sz.width() / 10 , sz.height() / 10); if (chk->value()) { QPen lp; lp.setColor(chk->foregroundColor()); lp.setWidth(ox > oy ? oy : ox); context.painter()->setPen(lp); context.painter()->drawLine(QPointF(ox, oy) + ps, QPointF(sz.width() - ox, sz.height() - oy) + ps); context.painter()->drawLine(QPointF(ox, sz.height() - oy) + ps, QPoint(sz.width() - ox, oy) + ps); } } else if (chk->checkType() == OROCheckBox::Type::Dot) { //Radio Style context.painter()->drawEllipse(rc); if (chk->value()) { QBrush lb(chk->foregroundColor()); context.painter()->setBrush(lb); context.painter()->setPen(Qt::NoPen); context.painter()->drawEllipse(rc.center(), sz.width() / 2 - ox, sz.height() / 2 - oy); } } else { //Tickbox Style context.painter()->drawRoundedRect(rc, sz.width() / 10 , sz.height() / 10); if (chk->value()) { QPen lp; lp.setColor(chk->foregroundColor()); lp.setWidth(ox > oy ? oy : ox); context.painter()->setPen(lp); context.painter()->drawLine(QPointF(ox, sz.height() / 2) + ps, QPointF(sz.width() / 2, sz.height() - oy) + ps); context.painter()->drawLine(QPointF(sz.width() / 2, sz.height() - oy) + ps, QPointF(sz.width() - ox, oy) + ps); } } context.painter()->restore(); } } } } if (endWhenComplete) context.painter()->end(); return true; } } diff --git a/src/wrtembed/KReportDesigner.cpp b/src/wrtembed/KReportDesigner.cpp index e584665a..b3745447 100644 --- a/src/wrtembed/KReportDesigner.cpp +++ b/src/wrtembed/KReportDesigner.cpp @@ -1,1537 +1,1553 @@ /* 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(){} ~Private() { delete dataSource; } 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 *customHeight; - KProperty *customWidth; + 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 }; KReportDesigner::KReportDesigner(QWidget * parent) : QWidget(parent), d(new Private()) { KReportPluginManager::self(); // this loads icons early enough 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->hruler = new KReportRuler(this, Qt::Horizontal, d->zoomHandler); d->pageButton = new KReportPropertiesButton(this); 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; } KReportDesigner::KReportDesigner(QWidget *parent, const QDomElement &data) : KReportDesigner(parent) { 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"), QLatin1String("javascript")); if (d->originalInterpreter.isEmpty()) { d->originalInterpreter = QLatin1String("javascript"); } 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("")))); + d->pageSize->setValue(QLatin1String("Custom")); + d->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")))); 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)) == nullptr) { 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->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->customWidth->value().toDouble()); - KReportUtils::setAttribute(&pagestyle, QLatin1String("report:custom-page-height"), d->customHeight->value().toDouble()); + 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 -// 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); + 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); } 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 = 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(); + 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(); - 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(); + 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 width; + 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); 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); - d->itemSet = s; - emit propertySetChanged(); + 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))); } 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/KReportDesignerSection.cpp b/src/wrtembed/KReportDesignerSection.cpp index 62360b1e..8310d794 100644 --- a/src/wrtembed/KReportDesignerSection.cpp +++ b/src/wrtembed/KReportDesignerSection.cpp @@ -1,429 +1,432 @@ /* 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) +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 } - slotSceneClicked(); // switches property set to this section - + + 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->sectionRuler->setRulerLength(h); d->scene->setSceneRect(0, 0, d->scene->width(), h); d->sceneView->resizeContents(QSize(d->scene->width(), h)); 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")))); 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 QString reportItemName = n.mid(qstrlen("report:")); if (reportItemName == QLatin1String("line")) { (new KReportDesignerItemLine(node, d->sceneView->designer(), d->scene))->setVisible(true); continue; } 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()); KReportDesigner::addMetaProperties(item->propertySet(), plugin->metaData()->name(), plugin->metaData()->iconName()); } continue; } } } 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); + 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" diff --git a/src/wrtembed/KReportDesignerSection.h b/src/wrtembed/KReportDesignerSection.h index 45ab8130..924f4043 100644 --- a/src/wrtembed/KReportDesignerSection.h +++ b/src/wrtembed/KReportDesignerSection.h @@ -1,91 +1,91 @@ /* 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 . */ #ifndef __REPORTSECTION_H__ #define __REPORTSECTION_H__ #include #include "kreport_export.h" // forward declarations class QDomNode; class QDomDocument; class QDomElement; class QGraphicsItem; typedef QList QGraphicsItemList; class KPropertySet; class KProperty; class KReportDesigner; class KReportZoomHandler; // // Class ReportSection // // This class is the base to all Report Section's visual representation. // It contains the basic data and interface that all the sections need to work. // class KREPORT_EXPORT KReportDesignerSection : public QWidget { Q_OBJECT public: ~KReportDesignerSection() override; void setTitle(const QString & s); void buildXML(QDomDocument *doc, QDomElement *section); void initFromXML(const QDomNode & section); QSize sizeHint() const override; /** * @brief Return the items in the section * Only return top-level items ... ie, items with no parent item * because child items are not full report-items, they are implementation * details of a report item and do not need to be counted individually * * @return QGraphicsItemList */ QGraphicsItemList items() const; void setSectionCursor(const QCursor&); void unsetSectionCursor(); protected Q_SLOTS: - void slotResizeBarDragged(int delta); + void slotResizeBarDragged(int delta, bool changeSet = true); protected: explicit KReportDesignerSection(KReportDesigner * rptdes, const KReportZoomHandler &zoomHandler); private Q_SLOTS: void slotPageOptionsChanged(KPropertySet &); void slotSceneClicked(); void slotPropertyChanged(KPropertySet &, KProperty &); private: Q_DISABLE_COPY(KReportDesignerSection) class Private; Private * const d; friend class KReportDesigner; friend class KReportDesignerSectionTitle; }; #endif