diff --git a/src/plugins/maps/KReportMapRenderer.cpp b/src/plugins/maps/KReportMapRenderer.cpp index 6dc48aa1..15cfc028 100644 --- a/src/plugins/maps/KReportMapRenderer.cpp +++ b/src/plugins/maps/KReportMapRenderer.cpp @@ -1,113 +1,125 @@ /* * Copyright (C) 2015 RadosÅ‚aw Wicik * * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "KReportMapRenderer.h" #include "KReportItemMaps.h" #include #include #include #include #include #include #include #include "kreportplugin_debug.h" KReportMapRenderer::KReportMapRenderer(QObject* parent) : QObject(parent) , m_currentJob(0) { m_marble.setMapThemeId(QLatin1String("earth/openstreetmap/openstreetmap.dgml")); m_marble.setShowOverviewMap(false); m_marble.setMapQualityForViewContext(Marble::PrintQuality, Marble::Still); m_marble.setShowCrosshairs(true); foreach(Marble::AbstractFloatItem* floatItem, m_marble.floatItems()){ if(floatItem->nameId() == QString(QLatin1String("navigation"))){ floatItem->setVisible(false); } } connect(m_marble.model()->downloadManager(), &Marble::HttpDownloadManager::progressChanged, this, &KReportMapRenderer::downloadProgres); connect(&m_marble, &Marble::MarbleMap::renderStatusChanged, this, &KReportMapRenderer::onRenderStatusChange); + connect(&m_retryTimer, &QTimer::timeout, this, &KReportMapRenderer::retryRender); } KReportMapRenderer::~KReportMapRenderer() { } void KReportMapRenderer::renderJob(KReportItemMaps* reportItemMaps) { m_currentJob = reportItemMaps; int zoom = m_currentJob->zoom(); //kreportpluginDebug() << "Map Renderer rendering" << m_currentJob->longtitude() << m_currentJob->latitude(); m_marble.setMapThemeId(m_currentJob->themeId()); //some themes enable overview map, and this must be disabled after theme switch. m_marble.setShowOverviewMap(false); m_marble.setSize(m_currentJob->size()); m_marble.centerOn(m_currentJob->longtitude(), m_currentJob->latitude()); m_marble.setRadius(pow(M_E, (zoom / 200.0))); // Create a painter that will do the painting. Marble::GeoPainter geoPainter( m_currentJob->oroImage()->picture(), m_marble.viewport(), m_marble.mapQuality() ); m_marble.paint( geoPainter, QRect() ); if (m_marble.renderStatus() == Marble::Complete) { m_currentJob->renderFinished(); + } else { + m_retryTimer.start(1000); } + } void KReportMapRenderer::onRenderStatusChange(Marble::RenderStatus renderStatus) { //kreportpluginDebug() << m_marble.renderStatus() << "|" << renderStatus; if(m_currentJob){ /*kreportpluginDebug() << this << m_currentJob << m_currentJob->longtitude() << m_currentJob->latitude() << m_currentJob->zoom() << " | status: " << renderStatus;*/ if(renderStatus == Marble::Complete){ m_currentJob->renderFinished(); } } } -void KReportMapRenderer::downloadFinished() -{ - //kreportpluginDebug() << "job:" << m_currentJob - //<< "(" << m_currentJob->latitude() << "," << m_currentJob->longtitude() << ")"; -} - void KReportMapRenderer::downloadProgres(int active, int queued) { Q_UNUSED(active) Q_UNUSED(queued) - if(m_currentJob){ - //kreportpluginDebug() << "job:" << m_currentJob - //<< "(" << m_currentJob->latitude() << "," << m_currentJob->longtitude() << ")" - //<< "active/queued:" << active << "/" << queued; + //if(m_currentJob){ + // kreportpluginDebug() << "job:" << m_currentJob + // << "(" << m_currentJob->latitude() << "," << m_currentJob->longtitude() << ")" + // << "active/queued:" << active << "/" << queued; + //} +} + +void KReportMapRenderer::retryRender() +{ + //kreportpluginDebug() << "Retrying map render"; + + // Create a painter that will do the painting. + Marble::GeoPainter geoPainter( m_currentJob->oroImage()->picture(), m_marble.viewport(), m_marble.mapQuality() ); + m_marble.paint( geoPainter, QRect() ); + + if (m_marble.renderStatus() == Marble::Complete) { + m_retryTimer.stop(); + m_currentJob->renderFinished(); } } diff --git a/src/plugins/maps/KReportMapRenderer.h b/src/plugins/maps/KReportMapRenderer.h index fe2432a1..6f7c433b 100644 --- a/src/plugins/maps/KReportMapRenderer.h +++ b/src/plugins/maps/KReportMapRenderer.h @@ -1,50 +1,54 @@ /* * Copyright (C) 2015 RadosÅ‚aw Wicik * * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef MAPRENDERER_H #define MAPRENDERER_H #include #include #include +#include + #include "kreportplugin_debug.h" class KReportItemMaps; class KReportMapRenderer : public QObject { Q_OBJECT Q_DISABLE_COPY(KReportMapRenderer) public: KReportMapRenderer(QObject* parent = 0); virtual ~KReportMapRenderer(); void renderJob(KReportItemMaps* reportItemMaps); Q_SIGNALS: void jobFinished(); private Q_SLOTS: void onRenderStatusChange(Marble::RenderStatus renderStatus); void downloadProgres(int active, int queued); - void downloadFinished(); + void retryRender(); private: Marble::MarbleMap m_marble; KReportItemMaps* m_currentJob; + + QTimer m_retryTimer; }; #endif // MAPRENDERER_H diff --git a/src/renderer/KReportPreRenderer.cpp b/src/renderer/KReportPreRenderer.cpp index ef661bd5..feafa39b 100644 --- a/src/renderer/KReportPreRenderer.cpp +++ b/src/renderer/KReportPreRenderer.cpp @@ -1,697 +1,700 @@ /* 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 "KReportPreRenderer.h" #include "KReportPreRenderer_p.h" #include "KReportAsyncItemManager_p.h" #include "KReportOneRecordData_p.h" #include "KReportRenderObjects.h" #include "KReportData.h" #include "KReportItemBase.h" #include "KReportDocument.h" #include "KReportDetailSectionData.h" #include "KReportLabelSizeInfo.h" #include "KReportPageSize.h" #include "KReportDpi.h" #ifdef KREPORT_SCRIPTING #include "scripting/KReportScriptHandler.h" #include "scripting/KReportGroupTracker.h" #endif #include #include #include "kreport_debug.h" KReportPreRendererPrivate::KReportPreRendererPrivate(KReportPreRenderer *preRenderer) : m_preRenderer(preRenderer) { m_valid = false; m_document = 0; m_reportDocument = 0; m_page = 0; m_yOffset = 0.0; m_topMargin = m_bottomMargin = 0.0; m_leftMargin = m_rightMargin = 0.0; m_pageCounter = 0; m_maxHeight = m_maxWidth = 0.0; m_oneRecord = new KReportPrivate::OneRecordData(); m_kodata = 0; #ifdef KREPORT_SCRIPTING m_scriptHandler = 0; #endif asyncManager = new KReportPrivate::AsyncItemManager(this); connect(asyncManager, SIGNAL(finished()), this, SLOT(asyncItemsFinished())); } KReportPreRendererPrivate::~KReportPreRendererPrivate() { delete m_reportDocument; delete m_document; delete m_oneRecord; m_postProcText.clear(); } void KReportPreRendererPrivate::createNewPage() { //kreportDebug(); if (m_pageCounter > 0) finishCurPage(); m_pageCounter++; #ifdef KREPORT_SCRIPTING //Update the page count script value m_scriptHandler->setPageNumber(m_pageCounter); m_scriptHandler->newPage(); #endif m_page = new OROPage(0); m_document->addPage(m_page); //! @todo calculate past page bool lastPage = false; m_yOffset = m_topMargin; if (m_pageCounter == 1 && m_reportDocument->m_pageHeaderFirst) renderSection(*(m_reportDocument->m_pageHeaderFirst)); else if (lastPage == true && m_reportDocument->m_pageHeaderLast) renderSection(*(m_reportDocument->m_pageHeaderLast)); else if ((m_pageCounter % 2) == 1 && m_reportDocument->m_pageHeaderOdd) renderSection(*(m_reportDocument->m_pageHeaderOdd)); else if ((m_pageCounter % 2) == 0 && m_reportDocument->m_pageHeaderAny) renderSection(*(m_reportDocument->m_pageHeaderAny)); else if (m_reportDocument->m_pageHeaderAny) renderSection(*(m_reportDocument->m_pageHeaderAny)); } qreal KReportPreRendererPrivate::finishCurPageSize(bool lastPage) { qreal retval = 0.0; if (lastPage && m_reportDocument->m_pageFooterLast) retval = renderSectionSize(* (m_reportDocument->m_pageFooterLast)); else if (m_pageCounter == 1 && m_reportDocument->m_pageFooterFirst) retval = renderSectionSize(* (m_reportDocument->m_pageFooterFirst)); else if ((m_pageCounter % 2) == 1 && m_reportDocument->m_pageFooterOdd) retval = renderSectionSize(* (m_reportDocument->m_pageFooterOdd)); else if ((m_pageCounter % 2) == 0 && m_reportDocument->m_pageFooterEven) retval = renderSectionSize(* (m_reportDocument->m_pageFooterEven)); else if (m_reportDocument->m_pageFooterAny) retval = renderSectionSize(* (m_reportDocument->m_pageFooterAny)); //kreportDebug() << retval; return retval; } qreal KReportPreRendererPrivate::finishCurPage(bool lastPage) { qreal offset = m_maxHeight - m_bottomMargin; qreal retval = 0.0; //kreportDebug() << offset; if (lastPage && m_reportDocument->m_pageFooterLast) { //kreportDebug() << "Last Footer"; m_yOffset = offset - renderSectionSize(* (m_reportDocument->m_pageFooterLast)); retval = renderSection(* (m_reportDocument->m_pageFooterLast)); } else if (m_pageCounter == 1 && m_reportDocument->m_pageFooterFirst) { //kreportDebug() << "First Footer"; m_yOffset = offset - renderSectionSize(* (m_reportDocument->m_pageFooterFirst)); retval = renderSection(* (m_reportDocument->m_pageFooterFirst)); } else if ((m_pageCounter % 2) == 1 && m_reportDocument->m_pageFooterOdd) { //kreportDebug() << "Odd Footer"; m_yOffset = offset - renderSectionSize(* (m_reportDocument->m_pageFooterOdd)); retval = renderSection(* (m_reportDocument->m_pageFooterOdd)); } else if ((m_pageCounter % 2) == 0 && m_reportDocument->m_pageFooterEven) { //kreportDebug() << "Even Footer"; m_yOffset = offset - renderSectionSize(* (m_reportDocument->m_pageFooterEven)); retval = renderSection(* (m_reportDocument->m_pageFooterEven)); } else if (m_reportDocument->m_pageFooterAny) { //kreportDebug() << "Any Footer"; m_yOffset = offset - renderSectionSize(* (m_reportDocument->m_pageFooterAny)); retval = renderSection(* (m_reportDocument->m_pageFooterAny)); } return retval; } void KReportPreRendererPrivate::renderDetailSection(KReportDetailSectionData *detailData) { if (detailData->m_detailSection) { if (m_kodata/* && !curs->eof()*/) { QStringList keys; QStringList keyValues; QList shownGroups; KReportDetailGroupSectionData * grp = 0; bool status = m_kodata->moveFirst(); m_recordCount = m_kodata->recordCount(); //kreportDebug() << "Record Count:" << m_recordCount; for (int i = 0; i < (int) detailData->m_groupList.count(); ++i) { grp = detailData->m_groupList[i]; //If the group has a header or footer, then emit a change of group value if(grp->m_groupFooter || grp->m_groupHeader) { // we get here only if group is *shown* shownGroups << i; keys.append(grp->m_column); if (!keys.last().isEmpty()) keyValues.append(m_kodata->value(m_kodata->fieldNumber(keys.last())).toString()); else keyValues.append(QString()); //Tell interested parties we're about to render a header emit(enteredGroup(keys.last(), keyValues.last())); } if (grp->m_groupHeader) renderSection(*(grp->m_groupHeader)); } while (status) { const qint64 pos = m_kodata->at(); //kreportDebug() << "At:" << l << "Y:" << m_yOffset << "Max Height:" << m_maxHeight; if ((renderSectionSize(*detailData->m_detailSection) + finishCurPageSize((pos + 1 == m_recordCount)) + m_bottomMargin + m_yOffset) >= m_maxHeight) { //kreportDebug() << "Next section is too big for this page"; if (pos > 0) { m_kodata->movePrevious(); createNewPage(); m_kodata->moveNext(); } } renderSection(*(detailData->m_detailSection)); if (m_kodata) status = m_kodata->moveNext(); if (status == true && keys.count() > 0) { // check to see where it is we need to start int pos = -1; // if it's still -1 by the time we are done then no keyValues changed for (int i = 0; i < keys.count(); ++i) { if (keyValues[i] != m_kodata->value(m_kodata->fieldNumber(keys[i])).toString()) { pos = i; break; } } // don't bother if nothing has changed if (pos != -1) { // roll back the query and go ahead if all is good status = m_kodata->movePrevious(); if (status == true) { // print the footers as needed // any changes made in this for loop need to be duplicated // below where the footers are finished. bool do_break = false; for (int i = shownGroups.count() - 1; i >= 0; i--) { if (do_break) createNewPage(); do_break = false; grp = detailData->m_groupList[shownGroups.at(i)]; if (grp->m_groupFooter) { if (renderSectionSize(*(grp->m_groupFooter)) + finishCurPageSize() + m_bottomMargin + m_yOffset >= m_maxHeight) createNewPage(); renderSection(*(grp->m_groupFooter)); } if (KReportDetailGroupSectionData::BreakAfterGroupFooter == grp->m_pagebreak) do_break = true; } // step ahead to where we should be and print the needed headers // if all is good status = m_kodata->moveNext(); if (do_break) createNewPage(); if (status == true) { for (int i = 0; i < shownGroups.count(); ++i) { grp = detailData->m_groupList[shownGroups.at(i)]; if (grp->m_groupHeader) { if (renderSectionSize(*(grp->m_groupHeader)) + finishCurPageSize() + m_bottomMargin + m_yOffset >= m_maxHeight) { m_kodata->movePrevious(); createNewPage(); m_kodata->moveNext(); } if (!keys[i].isEmpty()) keyValues[i] = m_kodata->value(m_kodata->fieldNumber(keys[i])).toString(); //Tell interested parties thak key values changed renderSection(*(grp->m_groupHeader)); } } } } } } } if (keys.size() > 0 && m_kodata->movePrevious()) { // finish footers // duplicated changes from above here for (int i = shownGroups.count() - 1; i >= 0; i--) { grp = detailData->m_groupList[shownGroups.at(i)]; if (grp->m_groupFooter) { if (renderSectionSize(*(grp->m_groupFooter)) + finishCurPageSize() + m_bottomMargin + m_yOffset >= m_maxHeight) createNewPage(); renderSection(*(grp->m_groupFooter)); emit(exitedGroup(keys[i], keyValues[i])); } } } } if (KReportDetailSectionData::BreakAtEnd == detailData->m_pageBreak) createNewPage(); } } qreal KReportPreRendererPrivate::renderSectionSize(const KReportSectionData & sectionData) { qreal intHeight = POINT_TO_INCH(sectionData.height()) * KReportDpi::dpiX(); int itemHeight = 0; if (sectionData.objects().count() == 0) return intHeight; QList objects = sectionData.objects(); foreach(KReportItemBase *ob, objects) { QPointF offset(m_leftMargin, m_yOffset); QVariant itemData = m_kodata->value(ob->itemDataSource()); //ASync objects cannot alter the section height KReportAsyncItemBase *async_ob = qobject_cast(ob); if (!async_ob) { itemHeight = ob->renderSimpleData(0, 0, offset, itemData, m_scriptHandler); if (itemHeight > intHeight) { intHeight = itemHeight; } } } return intHeight; } qreal KReportPreRendererPrivate::renderSection(const KReportSectionData & sectionData) { qreal sectionHeight = POINT_TO_INCH(sectionData.height()) * KReportDpi::dpiX(); int itemHeight = 0; //kreportDebug() << "Name: " << sectionData.name() << " Height: " << sectionHeight // << "Objects: " << sectionData.objects().count(); emit(renderingSection(const_cast(§ionData), m_page, QPointF(m_leftMargin, m_yOffset))); //Create a pre-rendered section for this section and add it to the document OROSection *sec = new OROSection(m_document); sec->setHeight(sectionData.height()); sec->setBackgroundColor(sectionData.backgroundColor()); sec->setType(sectionData.type()); m_document->addSection(sec); //Render section background ORORect* bg = new ORORect(); bg->setPen(QPen(Qt::NoPen)); bg->setBrush(sectionData.backgroundColor()); qreal w = m_page->document()->pageOptions().pixelSize().width() - m_page->document()->pageOptions().getMarginRight() - m_leftMargin; bg->setRect(QRectF(m_leftMargin, m_yOffset, w, sectionHeight)); m_page->addPrimitive(bg, true); QList objects = sectionData.objects(); foreach(KReportItemBase *ob, objects) { QPointF offset(m_leftMargin, m_yOffset); QVariant itemData = m_kodata->value(ob->itemDataSource()); if (ob->supportsSubQuery()) { itemHeight = ob->renderReportData(m_page, sec, offset, m_kodata, m_scriptHandler); } else { KReportAsyncItemBase *async_ob = qobject_cast(ob); if (async_ob){ //kreportDebug() << "async object"; asyncManager->addItem(async_ob, m_page, sec, offset, itemData, m_scriptHandler); } else { //kreportDebug() << "sync object"; itemHeight = ob->renderSimpleData(m_page, sec, offset, itemData, m_scriptHandler); } } if (itemHeight > sectionHeight) { sectionHeight = itemHeight; } } for (int i = 0; i < m_page->primitives(); ++i) { OROPrimitive *prim = m_page->primitive(i); if (prim->type() == OROTextBox::TextBox) { OROTextBox *text = static_cast(prim); if (text->requiresPostProcessing()) { m_postProcText.append(text); } } } m_yOffset += sectionHeight; return sectionHeight; } #ifdef KREPORT_SCRIPTING void KReportPreRendererPrivate::initEngine() { delete m_scriptHandler; m_scriptHandler = new KReportScriptHandler(m_kodata, m_reportDocument); connect(this, SIGNAL(enteredGroup(QString,QVariant)), m_scriptHandler, SLOT(slotEnteredGroup(QString,QVariant))); connect(this, SIGNAL(exitedGroup(QString,QVariant)), m_scriptHandler, SLOT(slotExitedGroup(QString,QVariant))); connect(this, SIGNAL(renderingSection(KReportSectionData*,OROPage*,QPointF)), m_scriptHandler, SLOT(slotEnteredSection(KReportSectionData*,OROPage*,QPointF))); } #endif void KReportPreRendererPrivate::asyncItemsFinished() { //kreportDebug() << "Finished rendering async items"; - delete asyncManager; + asyncManager->deleteLater(); + emit finishedAllASyncItems(); } bool KReportPreRendererPrivate::generateDocument() { if (!m_kodata) { m_kodata = m_oneRecord; } if (!m_valid || !m_reportDocument) { return false; } // Do this check now so we don't have to undo a lot of work later if it fails KReportLabelSizeInfo label; if (m_reportDocument->page.getPageSize() == QLatin1String("Labels")) { label = KReportLabelSizeInfo::find(m_reportDocument->page.getLabelType()); if (label.isNull()) { return false; } } //kreportDebug() << "Creating Document"; m_document = new ORODocument(m_reportDocument->m_title); m_pageCounter = 0; m_yOffset = 0.0; //kreportDebug() << "Calculating Margins"; if (!label.isNull()) { if (m_reportDocument->page.isPortrait()) { m_topMargin = (label.startY() / 100.0); m_bottomMargin = 0; m_rightMargin = 0; m_leftMargin = (label.startX() / 100.0); } else { m_topMargin = (label.startX() / 100.0); m_bottomMargin = 0; m_rightMargin = 0; m_leftMargin = (label.startY() / 100.0); } } else { m_topMargin = m_reportDocument->page.getMarginTop(); m_bottomMargin = m_reportDocument->page.getMarginBottom(); m_rightMargin = m_reportDocument->page.getMarginRight(); m_leftMargin = m_reportDocument->page.getMarginLeft(); //kreportDebug() << "Margins:" << m_topMargin << m_bottomMargin << m_rightMargin << m_leftMargin; } //kreportDebug() << "Calculating Page Size"; KReportPageOptions rpo(m_reportDocument->page); // This should reflect the information of the report page size if (m_reportDocument->page.getPageSize() == QLatin1String("Custom")) { m_maxWidth = m_reportDocument->page.getCustomWidth(); m_maxHeight = m_reportDocument->page.getCustomHeight(); } else { if (!label.isNull()) { m_maxWidth = label.width(); m_maxHeight = label.height(); rpo.setPageSize(label.paper()); } else { // lookup the correct size information for the specified size paper QSizeF pageSizePx = m_reportDocument->page.pixelSize(); m_maxWidth = pageSizePx.width(); m_maxHeight = pageSizePx.height(); } } if (!m_reportDocument->page.isPortrait()) { qreal tmp = m_maxWidth; m_maxWidth = m_maxHeight; m_maxHeight = tmp; } //kreportDebug() << "Page Size:" << m_maxWidth << m_maxHeight; m_document->setPageOptions(rpo); m_kodata->setSorting(m_reportDocument->m_detailSection->m_sortedFields); if (!m_kodata->open()) { return false; } #ifdef KREPORT_SCRIPTING initEngine(); connect(m_scriptHandler, SIGNAL(groupChanged(QMap)), m_preRenderer, SIGNAL(groupChanged(QMap))); //Loop through all abjects that have been registered, and register them with the script handler if (m_scriptHandler) { QMapIterator i(m_scriptObjects); while (i.hasNext()) { i.next(); m_scriptHandler->registerScriptObject(i.value(), i.key()); } //execute the script, if it fails, abort and return the empty document if (!m_scriptHandler->trigger()) { m_scriptHandler->displayErrors(); return m_document; } } #endif createNewPage(); if (!label.isNull()) { // Label Print Run // remember the initial margin setting as we will be modifying // the value and restoring it as we move around qreal margin = m_leftMargin; m_yOffset = m_topMargin; qreal w = (label.width() / 100.0); qreal wg = (label.xGap() / 100.0); qreal h = (label.height() / 100.0); qreal hg = (label.yGap() / 100.0); int numCols = label.columns(); int numRows = label.rows(); qreal tmp; // flip the value around if we are printing landscape if (!m_reportDocument->page.isPortrait()) { w = (label.height() / 100.0); wg = (label.yGap() / 100.0); h = (label.width() / 100.0); hg = (label.xGap() / 100.0); numCols = label.rows(); numRows = label.columns(); } KReportDetailSectionData * detailData = m_reportDocument->m_detailSection; if (detailData->m_detailSection) { KReportData *mydata = m_kodata; if (mydata && mydata->recordCount() > 0) { /* && !((query = orqThis->getQuery())->eof()))*/ if (!mydata->moveFirst()) { return false; } int row = 0; int col = 0; do { tmp = m_yOffset; // store the value as renderSection changes it renderSection(*(detailData->m_detailSection)); m_yOffset = tmp; // restore the value that renderSection modified col++; m_leftMargin += w + wg; if (col >= numCols) { m_leftMargin = margin; // reset back to original value col = 0; row++; m_yOffset += h + hg; if (row >= numRows) { m_yOffset = m_topMargin; row = 0; createNewPage(); } } } while (mydata->moveNext()); } } } else { // Normal Print Run if (m_reportDocument->m_reportHeader) { renderSection(*(m_reportDocument->m_reportHeader)); } if (m_reportDocument->m_detailSection) { renderDetailSection(m_reportDocument->m_detailSection); } if (m_reportDocument->m_reportFooter) { if (renderSectionSize(*(m_reportDocument->m_reportFooter)) + finishCurPageSize(true) + m_bottomMargin + m_yOffset >= m_maxHeight) { createNewPage(); } renderSection(*(m_reportDocument->m_reportFooter)); } } finishCurPage(true); #ifdef KREPORT_SCRIPTING // _postProcText contains those text boxes that need to be updated // with information that wasn't available at the time it was added to the document m_scriptHandler->setPageTotal(m_document->pages()); for (int i = 0; i < m_postProcText.size(); i++) { OROTextBox * tb = m_postProcText.at(i); m_scriptHandler->setPageNumber(tb->page()->page() + 1); tb->setText(m_scriptHandler->evaluate(tb->text()).toString()); } #endif asyncManager->startRendering(); #ifdef KREPORT_SCRIPTING m_scriptHandler->displayErrors(); #endif if (!m_kodata->close()) { return false; } #ifdef KREPORT_SCRIPTING delete m_scriptHandler; m_scriptHandler = 0; #endif if (m_kodata != m_oneRecord) { delete m_kodata; m_kodata = 0; } m_postProcText.clear(); return true; } //===========================KReportPreRenderer=============================== KReportPreRenderer::KReportPreRenderer(const QDomElement & document) : d(new KReportPreRendererPrivate(this)) { setDocument(document); + connect(d, &KReportPreRendererPrivate::finishedAllASyncItems, this, &KReportPreRenderer::finishedAllASyncItems); + } KReportPreRenderer::~KReportPreRenderer() { delete d; } void KReportPreRenderer::setName(const QString &n) { d->m_reportDocument->setName(n); } bool KReportPreRenderer::isValid() const { if (d && d->m_valid) return true; return false; } ORODocument* KReportPreRenderer::document() { return d->m_document; } bool KReportPreRenderer::generateDocument() { // delete d->m_document; if (!d->generateDocument()) { delete d->m_document; d->m_document = 0; } return d->m_document; } void KReportPreRenderer::setSourceData(KReportData *data) { if (d && data != d->m_kodata) { delete d->m_kodata; d->m_kodata = data; } } bool KReportPreRenderer::setDocument(const QDomElement &document) { delete d->m_document; d->m_valid = false; if (document.tagName() != QLatin1String("report:content")) { kreportWarning() << "report schema is invalid"; return false; } d->m_reportDocument = new KReportDocument(document); d->m_valid = d->m_reportDocument->isValid(); return isValid(); } #ifdef KREPORT_SCRIPTING void KReportPreRenderer::registerScriptObject(QObject* obj, const QString& name) { //kreportDebug() << name; d->m_scriptObjects[name] = obj; } KReportScriptHandler *KReportPreRenderer::scriptHandler() { return d->m_scriptHandler; } #endif const KReportDocument* KReportPreRenderer::reportData() const { return d->m_reportDocument; } diff --git a/src/renderer/KReportPreRenderer.h b/src/renderer/KReportPreRenderer.h index 8e6bc9df..f58e092b 100644 --- a/src/renderer/KReportPreRenderer.h +++ b/src/renderer/KReportPreRenderer.h @@ -1,82 +1,83 @@ /* 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 . */ #ifndef KREPORTPRERENDERER_H #define KREPORTPRERENDERER_H #include "config-kreport.h" #include "kreport_export.h" #include #ifdef KREPORT_SCRIPTING class KReportScriptHandler; #else #define KReportScriptHandler void #endif class KReportPreRendererPrivate; class ORODocument; class KReportData; class KReportDocument; class QDomElement; // // ORPreRender // This class takes a report definition and prerenders the result to // an ORODocument that can be used to pass to any number of renderers. // class KREPORT_EXPORT KReportPreRenderer : public QObject { Q_OBJECT public: explicit KReportPreRenderer(const QDomElement& document); virtual ~KReportPreRenderer(); //! Sets source data to @a data, takes ownership void setSourceData(KReportData* data); #ifdef KREPORT_SCRIPTING KReportScriptHandler *scriptHandler(); void registerScriptObject(QObject*, const QString&); #endif bool generateDocument(); ORODocument *document(); /** @brief Set the name of the report so that it can be used internally by the script engine */ void setName(const QString &); bool isValid() const; const KReportDocument *reportData() const; Q_SIGNALS: void groupChanged(const QMap &groupData); - + void finishedAllASyncItems(); + private: bool setDocument(const QDomElement &document); private: KReportPreRendererPrivate *const d; }; #endif // KREPORTPRERENDERER_H diff --git a/src/renderer/KReportPreRenderer_p.h b/src/renderer/KReportPreRenderer_p.h index 88398ed0..ab098f2f 100644 --- a/src/renderer/KReportPreRenderer_p.h +++ b/src/renderer/KReportPreRenderer_p.h @@ -1,101 +1,102 @@ /* 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 . */ #ifndef KREPORTPRERENDERER_P_H #define KREPORTPRERENDERER_P_H #include "config-kreport.h" #include "KReportRenderObjects.h" #include "KReportAsyncItemManager_p.h" #include "KReportDetailSectionData.h" #include namespace KReportPrivate{ class OneRecordData; } class KReportPreRenderer; /*! This class is the private class that houses all the internal variables so we can provide a cleaner interface to the user without presenting to them things that they don't need to see and may change over time. */ class KReportPreRendererPrivate : public QObject { Q_OBJECT public: KReportPreRendererPrivate(KReportPreRenderer *preRenderer); virtual ~KReportPreRendererPrivate(); KReportPreRenderer * const m_preRenderer; bool m_valid; ORODocument* m_document; OROPage* m_page; KReportDocument* m_reportDocument; qreal m_yOffset; // how far down the current page are we qreal m_topMargin; // value stored in the correct units qreal m_bottomMargin; // -- same as above -- qreal m_leftMargin; // -- same as above -- qreal m_rightMargin; // -- same as above -- qreal m_maxHeight; // -- same as above -- qreal m_maxWidth; // -- same as above -- int m_pageCounter; // what page are we currently on? int m_recordCount; KReportData* m_kodata; KReportPrivate::OneRecordData *m_oneRecord; QList m_postProcText; #ifdef KREPORT_SCRIPTING QMap m_scriptObjects; #endif void createNewPage(); qreal finishCurPage(bool = false); qreal finishCurPageSize(bool = false); void renderDetailSection(KReportDetailSectionData *detailData); qreal renderSection(const KReportSectionData &); qreal renderSectionSize(const KReportSectionData &); ///Scripting Stuff KReportScriptHandler *m_scriptHandler; #ifdef KREPORT_SCRIPTING void initEngine(); #endif //! Generates m_document. Returns true on success. //! @note m_document is not removed on failure, caller should remove it. bool generateDocument(); KReportPrivate::AsyncItemManager* asyncManager; private Q_SLOTS: void asyncItemsFinished(); Q_SIGNALS: void enteredGroup(const QString&, const QVariant&); void exitedGroup(const QString&, const QVariant&); void renderingSection(KReportSectionData*, OROPage*, QPointF); + void finishedAllASyncItems(); }; #endif // __KOREPORTPRERENDERER_P_H__ diff --git a/src/renderer/KReportView.cpp b/src/renderer/KReportView.cpp index d6b0fca3..8bcc50cd 100644 --- a/src/renderer/KReportView.cpp +++ b/src/renderer/KReportView.cpp @@ -1,158 +1,166 @@ /* This file is part of the KDE project Copyright (C) 2015 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 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 "KReportView.h" #include "KReportPage.h" #include "KReportRenderObjects.h" #include "KReportPreRenderer.h" #include "KReportRendererBase.h" #include "kreport_debug.h" #include #include #include #include #include #include #include #include #include #include //! @internal class KReportView::Private { public: explicit Private() : reportDocument(0) , reportPage(0) , currentPage(1) , pageCount(0) {} ~Private() {} ORODocument *reportDocument; QGraphicsView *reportView; QGraphicsScene *reportScene; KReportPage *reportPage; int currentPage; int pageCount; KReportRendererFactory factory; }; KReportView::KReportView(QWidget *parent) : QWidget(parent), d(new Private()) { setObjectName(QLatin1String("KReportView")); d->reportView = new QGraphicsView(this); // page selector should be always visible: d->reportView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); QVBoxLayout *l = new QVBoxLayout; l->setMargin(0); setLayout(l); layout()->addWidget(d->reportView); d->reportScene = new QGraphicsScene(this); d->reportScene->setSceneRect(0,0,1000,2000); d->reportView->setScene(d->reportScene); d->reportScene->setBackgroundBrush(palette().brush(QPalette::Dark)); } KReportView::~KReportView() { //kreportDebug(); delete d; } void KReportView::moveToFirstPage() { if (d->currentPage != 1) { d->currentPage = 1; d->reportPage->renderPage(d->currentPage); } } void KReportView::moveToLastPage() { if (d->currentPage != d->pageCount) { d->currentPage = d->pageCount; d->reportPage->renderPage(d->currentPage); } } void KReportView::moveToNextPage() { if (d->currentPage < d->pageCount) { d->currentPage++; d->reportPage->renderPage(d->currentPage); } } void KReportView::moveToPreviousPage() { if (d->currentPage > 1) { d->currentPage--; d->reportPage->renderPage(d->currentPage); } } int KReportView::currentPage() const { return d->currentPage; } int KReportView::pageCount() const { return d->pageCount; } void KReportView::setDocument(ORODocument* doc) { d->reportDocument = doc; if (d->reportPage) { delete d->reportPage; } d->pageCount = doc->pages(); d->reportPage = new KReportPage(this, d->reportDocument); d->reportPage->setObjectName(QLatin1String("KReportPage")); d->reportScene->setSceneRect(0,0,d->reportPage->rect().width() + 40, d->reportPage->rect().height() + 40); d->reportScene->addItem(d->reportPage); d->reportPage->setPos(20,20); d->reportView->centerOn(0,0); } QAbstractScrollArea* KReportView::scrollArea() { return d->reportView; } +void KReportView::refreshCurrentPage() +{ + //qDebug() << "Refreshing current page" << d->currentPage; + if (d->reportPage) { + d->reportPage->renderPage(d->currentPage); + } +} + diff --git a/src/renderer/KReportView.h b/src/renderer/KReportView.h index 93af3c85..3f8c0e5d 100644 --- a/src/renderer/KReportView.h +++ b/src/renderer/KReportView.h @@ -1,58 +1,59 @@ /* This file is part of the KDE project Copyright (C) 2015 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 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 KREPORTVIEW_H #define KREPORTVIEW_H #include #include "kreport_export.h" class ORODocument; class QAbstractScrollArea; /** * @brief Provides a simple widget for viewing a rendered report on screen * */ class KREPORT_EXPORT KReportView : public QWidget { Q_OBJECT public: explicit KReportView(QWidget *parent); ~KReportView(); void moveToFirstPage(); void moveToLastPage(); void moveToNextPage(); void moveToPreviousPage(); int currentPage() const; int pageCount() const; + void refreshCurrentPage(); void setDocument(ORODocument* doc); QAbstractScrollArea* scrollArea(); private: Q_DISABLE_COPY(KReportView) class Private; Private * const d; }; #endif