File indexing completed on 2024-05-05 04:43:22

0001 /* This file is part of the KDE project
0002  * Copyright (C) 2001-2007 by OpenMFG, LLC (info@openmfg.com)
0003  * Copyright (C) 2007-2008 by Adam Pigg (adam@piggz.co.uk)
0004  *
0005  * This library is free software; you can redistribute it and/or
0006  * modify it under the terms of the GNU Lesser General Public
0007  * License as published by the Free Software Foundation; either
0008  * version 2.1 of the License, or (at your option) any later version.
0009  *
0010  * This library is distributed in the hope that it will be useful,
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0013  * Lesser General Public License for more details.
0014  *
0015  * You should have received a copy of the GNU Lesser General Public
0016  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
0017  */
0018 
0019 #include "KReportPreRenderer.h"
0020 #include "KReportPreRenderer_p.h"
0021 #include "KReportAsyncItemManager_p.h"
0022 #include "KReportOneRecordDataSource_p.h"
0023 
0024 #include "KReportRenderObjects.h"
0025 #include "KReportDataSource.h"
0026 #include "KReportItemBase.h"
0027 #include "KReportDocument.h"
0028 #include "KReportDetailSectionData.h"
0029 #include "KReportLabelSizeInfo.h"
0030 #include "KReportPageSize.h"
0031 #include "KReportUtils_p.h"
0032 
0033 #ifdef KREPORT_SCRIPTING
0034 #include "KReportScriptHandler.h"
0035 #include "KReportGroupTracker.h"
0036 #endif
0037 
0038 #include <QDomElement>
0039 #include <QApplication>
0040 #include "kreport_debug.h"
0041 
0042 KReportPreRendererPrivate::KReportPreRendererPrivate(KReportPreRenderer *preRenderer)
0043  : m_preRenderer(preRenderer)
0044 {
0045     m_valid = false;
0046     m_document = nullptr;
0047     m_reportDocument = nullptr;
0048     m_page = nullptr;
0049     m_yOffset = 0.0;
0050     m_topMargin = m_bottomMargin = 0.0;
0051     m_leftMargin = m_rightMargin = 0.0;
0052     m_pageCounter = 0;
0053     m_maxHeight = m_maxWidth = 0.0;
0054     m_oneRecord = new KReportPrivate::OneRecordDataSource();
0055     m_dataSource = nullptr;
0056 #ifdef KREPORT_SCRIPTING
0057     m_scriptHandler = nullptr;
0058 #endif
0059     asyncManager = new KReportPrivate::AsyncItemManager(this);
0060 
0061     connect(asyncManager, SIGNAL(finished()), this, SLOT(asyncItemsFinished()));
0062 }
0063 
0064 KReportPreRendererPrivate::~KReportPreRendererPrivate()
0065 {
0066     delete m_reportDocument;
0067     delete m_document;
0068     delete m_oneRecord;
0069     m_postProcText.clear();
0070 }
0071 
0072 void KReportPreRendererPrivate::createNewPage()
0073 {
0074     //kreportDebug();
0075     if (m_pageCounter > 0)
0076         finishCurPage(false);
0077 
0078     m_pageCounter++;
0079 
0080 #ifdef KREPORT_SCRIPTING
0081     //Update the page count script value
0082     m_scriptHandler->setPageNumber(m_pageCounter);
0083     m_scriptHandler->newPage();
0084 #endif
0085 
0086     m_page = new OROPage(nullptr);
0087     m_document->addPage(m_page);
0088 
0089     //! @todo calculate past page
0090     bool lastPage = false;
0091 
0092     m_yOffset = m_topMargin;
0093 
0094     if (m_pageCounter == 1 && m_reportDocument->section(KReportSectionData::Type::PageHeaderFirst))
0095         renderSection(*(m_reportDocument->section(KReportSectionData::Type::PageHeaderFirst)));
0096     else if (lastPage == true && m_reportDocument->section(KReportSectionData::Type::PageHeaderLast))
0097         renderSection(*(m_reportDocument->section(KReportSectionData::Type::PageHeaderLast)));
0098     else if ((m_pageCounter % 2) == 1 && m_reportDocument->section(KReportSectionData::Type::PageHeaderOdd))
0099         renderSection(*(m_reportDocument->section(KReportSectionData::Type::PageHeaderOdd)));
0100     else if ((m_pageCounter % 2) == 0 && m_reportDocument->section(KReportSectionData::Type::PageHeaderEven))
0101         renderSection(*(m_reportDocument->section(KReportSectionData::Type::PageHeaderEven)));
0102     else if (m_reportDocument->section(KReportSectionData::Type::PageHeaderAny))
0103         renderSection(*(m_reportDocument->section(KReportSectionData::Type::PageHeaderAny)));
0104 }
0105 
0106 qreal KReportPreRendererPrivate::finishCurPageSize(bool lastPage)
0107 {
0108     qreal retval = 0.0;
0109 
0110     if (lastPage && m_reportDocument->section(KReportSectionData::Type::PageFooterLast))
0111         retval = renderSectionSize(* (m_reportDocument->section(KReportSectionData::Type::PageFooterLast)));
0112     else if (m_pageCounter == 1 && m_reportDocument->section(KReportSectionData::Type::PageFooterFirst))
0113         retval = renderSectionSize(* (m_reportDocument->section(KReportSectionData::Type::PageFooterFirst)));
0114     else if ((m_pageCounter % 2) == 1 && m_reportDocument->section(KReportSectionData::Type::PageFooterOdd))
0115         retval = renderSectionSize(* (m_reportDocument->section(KReportSectionData::Type::PageFooterOdd)));
0116     else if ((m_pageCounter % 2) == 0 && m_reportDocument->section(KReportSectionData::Type::PageFooterEven))
0117         retval = renderSectionSize(* (m_reportDocument->section(KReportSectionData::Type::PageFooterEven)));
0118     else if (m_reportDocument->section(KReportSectionData::Type::PageFooterAny))
0119         retval = renderSectionSize(* (m_reportDocument->section(KReportSectionData::Type::PageFooterAny)));
0120 
0121     //kreportDebug() << retval;
0122     return retval;
0123 }
0124 
0125 qreal KReportPreRendererPrivate::finishCurPage(bool lastPage)
0126 {
0127 
0128     qreal offset = m_maxHeight - m_bottomMargin;
0129     qreal retval = 0.0;
0130     //kreportDebug() << offset;
0131 
0132     if (lastPage && m_reportDocument->section(KReportSectionData::Type::PageFooterLast)) {
0133         //kreportDebug() << "Last Footer";
0134         m_yOffset = offset - renderSectionSize(* (m_reportDocument->section(KReportSectionData::Type::PageFooterLast)));
0135         retval = renderSection(* (m_reportDocument->section(KReportSectionData::Type::PageFooterLast)));
0136     } else if (m_pageCounter == 1 && m_reportDocument->section(KReportSectionData::Type::PageFooterFirst)) {
0137         //kreportDebug() << "First Footer";
0138         m_yOffset = offset - renderSectionSize(* (m_reportDocument->section(KReportSectionData::Type::PageFooterFirst)));
0139         retval = renderSection(* (m_reportDocument->section(KReportSectionData::Type::PageFooterFirst)));
0140     } else if ((m_pageCounter % 2) == 1 && m_reportDocument->section(KReportSectionData::Type::PageFooterOdd)) {
0141         //kreportDebug() << "Odd Footer";
0142         m_yOffset = offset - renderSectionSize(* (m_reportDocument->section(KReportSectionData::Type::PageFooterOdd)));
0143         retval = renderSection(* (m_reportDocument->section(KReportSectionData::Type::PageFooterOdd)));
0144     } else if ((m_pageCounter % 2) == 0 && m_reportDocument->section(KReportSectionData::Type::PageFooterEven)) {
0145         //kreportDebug() << "Even Footer";
0146         m_yOffset = offset - renderSectionSize(* (m_reportDocument->section(KReportSectionData::Type::PageFooterEven)));
0147         retval = renderSection(* (m_reportDocument->section(KReportSectionData::Type::PageFooterEven)));
0148     } else if (m_reportDocument->section(KReportSectionData::Type::PageFooterAny)) {
0149         //kreportDebug() << "Any Footer";
0150         m_yOffset = offset - renderSectionSize(* (m_reportDocument->section(KReportSectionData::Type::PageFooterAny)));
0151         retval = renderSection(* (m_reportDocument->section(KReportSectionData::Type::PageFooterAny)));
0152     }
0153 
0154     return retval;
0155 }
0156 
0157 void KReportPreRendererPrivate::renderDetailSection(KReportDetailSectionData *detailData)
0158 {
0159     if (detailData->detailSection) {
0160         if (m_dataSource/* && !curs->eof()*/) {
0161             QStringList keys;
0162             QStringList keyValues;
0163             QList<int> shownGroups;
0164             KReportDetailGroupSectionData * grp = nullptr;
0165 
0166             bool status = m_dataSource->moveFirst();
0167             int recordCount = m_dataSource->recordCount();
0168 
0169             //kreportDebug() << "Record Count:" << recordCount;
0170 
0171             for (int i = 0; i < (int) detailData->groupList.count(); ++i) {
0172                 grp = detailData->groupList[i];
0173                 //If the group has a header or footer, then emit a change of group value
0174                 if(grp->groupFooter || grp->groupHeader) {
0175                     // we get here only if group is *shown*
0176                     shownGroups << i;
0177                     keys.append(grp->column);
0178                     if (!keys.last().isEmpty())
0179                         keyValues.append(m_dataSource->value(m_dataSource->fieldNumber(keys.last())).toString());
0180                     else
0181                         keyValues.append(QString());
0182 
0183                     //Tell interested parties we're about to render a header
0184                     emit(enteredGroup(keys.last(), keyValues.last()));
0185                 }
0186                 if (grp->groupHeader)
0187                     renderSection(*(grp->groupHeader));
0188             }
0189 
0190             while (status) {
0191                 const qint64 pos = m_dataSource->at();
0192                 //kreportDebug() << "At:" << l << "Y:" << m_yOffset << "Max Height:" << m_maxHeight;
0193                 if ((renderSectionSize(*detailData->detailSection)
0194                         + finishCurPageSize((pos + 1 == recordCount))
0195                         + m_bottomMargin + m_yOffset) >= m_maxHeight)
0196                 {
0197                     //kreportDebug() << "Next section is too big for this page";
0198                     if (pos > 0) {
0199                         m_dataSource->movePrevious();
0200                         createNewPage();
0201                         m_dataSource->moveNext();
0202                     }
0203                 }
0204 
0205                 renderSection(*(detailData->detailSection));
0206                 status = m_dataSource->moveNext();
0207 
0208                 if (status == true && keys.count() > 0) {
0209                     // check to see where it is we need to start
0210                     int pos = -1; // if it's still -1 by the time we are done then no keyValues changed
0211                     for (int i = 0; i < keys.count(); ++i) {
0212                         if (keyValues[i] != m_dataSource->value(m_dataSource->fieldNumber(keys[i])).toString()) {
0213                             pos = i;
0214                             break;
0215                         }
0216                     }
0217                     // don't bother if nothing has changed
0218                     if (pos != -1) {
0219                         // roll back the query and go ahead if all is good
0220                         status = m_dataSource->movePrevious();
0221                         if (status == true) {
0222                             // print the footers as needed
0223                             // any changes made in this for loop need to be duplicated
0224                             // below where the footers are finished.
0225                             bool do_break = false;
0226                             for (int i = shownGroups.count() - 1; i >= 0; i--) {
0227                                 if (do_break)
0228                                     createNewPage();
0229                                 do_break = false;
0230                                 grp = detailData->groupList[shownGroups.at(i)];
0231 
0232                                 if (grp->groupFooter) {
0233                                     if (renderSectionSize(*(grp->groupFooter)) + finishCurPageSize(false) + m_bottomMargin + m_yOffset >= m_maxHeight)
0234                                         createNewPage();
0235                                     renderSection(*(grp->groupFooter));
0236                                 }
0237 
0238                                 if (KReportDetailGroupSectionData::PageBreak::AfterGroupFooter == grp->pagebreak)
0239                                     do_break = true;
0240                             }
0241                             // step ahead to where we should be and print the needed headers
0242                             // if all is good
0243                             status = m_dataSource->moveNext();
0244                             if (do_break)
0245                                 createNewPage();
0246                             if (status == true) {
0247                                 for (int i = 0; i < shownGroups.count(); ++i) {
0248                                     grp = detailData->groupList[shownGroups.at(i)];
0249 
0250                                     if (grp->groupHeader) {
0251                                         if (renderSectionSize(*(grp->groupHeader)) + finishCurPageSize(false) + m_bottomMargin + m_yOffset >= m_maxHeight) {
0252                                             m_dataSource->movePrevious();
0253                                             createNewPage();
0254                                             m_dataSource->moveNext();
0255                                         }
0256 
0257                                         if (!keys[i].isEmpty())
0258                                             keyValues[i] = m_dataSource->value(m_dataSource->fieldNumber(keys[i])).toString();
0259 
0260                                         //Tell interested parties thak key values changed
0261                                         renderSection(*(grp->groupHeader));
0262                                     }
0263 
0264 
0265                                 }
0266                             }
0267                         }
0268                     }
0269                 }
0270             }
0271 
0272             if (keys.size() > 0 && m_dataSource->movePrevious()) {
0273                 // finish footers
0274                 // duplicated changes from above here
0275                 for (int i = shownGroups.count() - 1; i >= 0; i--) {
0276                     grp = detailData->groupList[shownGroups.at(i)];
0277 
0278                     if (grp->groupFooter) {
0279                         if (renderSectionSize(*(grp->groupFooter)) + finishCurPageSize(false) + m_bottomMargin + m_yOffset >= m_maxHeight)
0280                             createNewPage();
0281                         renderSection(*(grp->groupFooter));
0282                         emit(exitedGroup(keys[i], keyValues[i]));
0283                     }
0284                 }
0285             }
0286         }
0287         if (KReportDetailSectionData::PageBreak::AtEnd == detailData->pageBreak)
0288             createNewPage();
0289     }
0290 }
0291 
0292 qreal KReportPreRendererPrivate::renderSectionSize(const KReportSectionData & sectionData)
0293 {
0294     qreal intHeight = POINT_TO_INCH(sectionData.height()) * KReportPrivate::dpiX();
0295 
0296     if (sectionData.objects().count() == 0)
0297         return intHeight;
0298 
0299     QList<KReportItemBase*> objects = sectionData.objects();
0300     foreach(KReportItemBase *ob, objects) {
0301         QPointF offset(m_leftMargin, m_yOffset);
0302         //ASync objects cannot alter the section height
0303         KReportAsyncItemBase *async_ob = qobject_cast<KReportAsyncItemBase*>(ob);
0304         if (!async_ob) {
0305             QVariant itemData;
0306             if (m_dataSource) {
0307                 itemData = m_dataSource->value(ob->itemDataSource());
0308             }
0309             const int itemHeight = ob->renderSimpleData(nullptr, nullptr, offset, itemData, m_scriptHandler);
0310             if (itemHeight > intHeight) {
0311                 intHeight = itemHeight;
0312             }
0313         }
0314     }
0315 
0316     return intHeight;
0317 }
0318 
0319 qreal KReportPreRendererPrivate::renderSection(const KReportSectionData & sectionData)
0320 {
0321     qreal sectionHeight = POINT_TO_INCH(sectionData.height()) * KReportPrivate::dpiX();
0322 
0323     int itemHeight = 0;
0324     //kreportDebug() << "Name: " << sectionData.name() << " Height: " << sectionHeight
0325     //         << "Objects: " << sectionData.objects().count();
0326     emit(renderingSection(const_cast<KReportSectionData*>(&sectionData), m_page, QPointF(m_leftMargin, m_yOffset)));
0327 
0328     //Create a pre-rendered section for this section and add it to the document
0329     OROSection *sec = new OROSection(m_document);
0330     sec->setHeight(sectionData.height());
0331     sec->setBackgroundColor(sectionData.backgroundColor());
0332     sec->setType(sectionData.type());
0333     m_document->addSection(sec);
0334 
0335     //Render section background
0336     ORORect* bg = new ORORect();
0337     bg->setPen(QPen(Qt::NoPen));
0338     bg->setBrush(sectionData.backgroundColor());
0339     qreal w = m_page->document()->pageLayout().fullRectPixels(KReportPrivate::dpiX()).width() - m_page->document()->pageLayout().marginsPixels(KReportPrivate::dpiX()).right() - m_leftMargin;
0340 
0341     bg->setRect(QRectF(m_leftMargin, m_yOffset, w, sectionHeight));
0342     m_page->insertPrimitive(bg, 0);
0343 
0344     QList<KReportItemBase*> objects = sectionData.objects();
0345     foreach(KReportItemBase *ob, objects) {
0346         QPointF offset(m_leftMargin, m_yOffset);
0347         QVariant itemData = m_dataSource->value(ob->itemDataSource());
0348 
0349         if (ob->supportsSubQuery()) {
0350            itemHeight = ob->renderReportData(m_page, sec, offset, m_dataSource, m_scriptHandler);
0351         } else {
0352             KReportAsyncItemBase *async_ob = qobject_cast<KReportAsyncItemBase*>(ob);
0353             if (async_ob){
0354                 //kreportDebug() << "async object";
0355                 asyncManager->addItem(async_ob, m_page, sec, offset, async_ob->realItemData(itemData), m_scriptHandler);
0356             } else {
0357                 //kreportDebug() << "sync object";
0358                 itemHeight = ob->renderSimpleData(m_page, sec, offset, itemData, m_scriptHandler);
0359             }
0360         }
0361 
0362         if (itemHeight > sectionHeight) {
0363             sectionHeight = itemHeight;
0364         }
0365     }
0366     for (int i = 0; i < m_page->primitiveCount(); ++i) {
0367         OROPrimitive *prim = m_page->primitive(i);
0368         if (OROTextBox *text = dynamic_cast<OROTextBox*>(prim)) {
0369             if (text->requiresPostProcessing()) {
0370                 m_postProcText.append(text);
0371             }
0372         }
0373     }
0374     m_yOffset += sectionHeight;
0375 
0376     return sectionHeight;
0377 }
0378 
0379 #ifdef KREPORT_SCRIPTING
0380 void KReportPreRendererPrivate::initEngine()
0381 {
0382     delete m_scriptHandler;
0383     m_scriptHandler = new KReportScriptHandler(m_dataSource, scriptSource, m_reportDocument);
0384 
0385     connect(this, SIGNAL(enteredGroup(QString,QVariant)), m_scriptHandler, SLOT(slotEnteredGroup(QString,QVariant)));
0386 
0387     connect(this, SIGNAL(exitedGroup(QString,QVariant)), m_scriptHandler, SLOT(slotExitedGroup(QString,QVariant)));
0388 
0389     connect(this, SIGNAL(renderingSection(KReportSectionData*,OROPage*,QPointF)), m_scriptHandler, SLOT(slotEnteredSection(KReportSectionData*,OROPage*,QPointF)));
0390 }
0391 #endif
0392 
0393 void KReportPreRendererPrivate::asyncItemsFinished()
0394 {
0395     //kreportDebug() << "Finished rendering async items";
0396     asyncManager->deleteLater();
0397     emit finishedAllASyncItems();
0398 }
0399 
0400 bool KReportPreRendererPrivate::generateDocument()
0401 {
0402     if (!m_dataSource) {
0403         m_dataSource = m_oneRecord;
0404     }
0405 
0406     if (!m_valid || !m_reportDocument) {
0407         return false;
0408     }
0409 
0410     // Do this check now so we don't have to undo a lot of work later if it fails
0411     KReportLabelSizeInfo label;
0412     if (m_reportDocument->pageSize() == QLatin1String("Labels")) {
0413         label = KReportLabelSizeInfo::find(m_reportDocument->labelType());
0414         if (label.isNull()) {
0415             return false;
0416         }
0417     }
0418     //kreportDebug() << "Creating Document";
0419     m_document = new ORODocument(m_reportDocument->title());
0420 
0421     m_pageCounter  = 0;
0422     m_yOffset      = 0.0;
0423 
0424     //kreportDebug() << "Calculating Margins";
0425     if (!label.isNull()) {
0426         if (m_reportDocument->pageLayout().orientation() == QPageLayout::Portrait) {
0427             m_topMargin = (label.startY() / 100.0);
0428             m_bottomMargin = 0;
0429             m_rightMargin = 0;
0430             m_leftMargin = (label.startX() / 100.0);
0431         } else {
0432             m_topMargin = (label.startX() / 100.0);
0433             m_bottomMargin = 0;
0434             m_rightMargin = 0;
0435             m_leftMargin = (label.startY() / 100.0);
0436         }
0437     } else {
0438 
0439         m_topMargin    = m_reportDocument->pageLayout().marginsPoints().top();
0440         m_bottomMargin = m_reportDocument->pageLayout().marginsPoints().bottom();
0441         m_rightMargin  = m_reportDocument->pageLayout().marginsPoints().right();
0442         m_leftMargin   = m_reportDocument->pageLayout().marginsPoints().left();
0443         //kreportDebug() << "Margins:" << m_topMargin << m_bottomMargin << m_rightMargin << m_leftMargin;
0444      }
0445 
0446     //kreportDebug() << "Calculating Page Size";
0447     QPageLayout layout =  m_reportDocument->pageLayout();
0448     // This should reflect the information of the report page size
0449     if (m_reportDocument->pageSize() == QLatin1String("Custom")) {
0450         m_maxWidth = m_reportDocument->pageLayout().fullRectPoints().width();
0451         m_maxHeight = m_reportDocument->pageLayout().fullRectPoints().height();
0452     } else {
0453         if (!label.isNull()) {
0454             m_maxWidth = label.width();
0455             m_maxHeight = label.height();
0456             m_reportDocument->pageLayout().setPageSize(QPageSize(KReportPageSize::pageSize(label.paper())));
0457         } else {
0458             // lookup the correct size information for the specified size paper
0459             QSizeF pageSizePx = m_reportDocument->pageLayout().fullRectPixels(KReportPrivate::dpiX()).size();
0460 
0461             m_maxWidth = pageSizePx.width();
0462             m_maxHeight = pageSizePx.height();
0463         }
0464     }
0465 
0466     if (m_reportDocument->pageLayout().orientation() == QPageLayout::Landscape) {
0467         qreal tmp = m_maxWidth;
0468         m_maxWidth = m_maxHeight;
0469         m_maxHeight = tmp;
0470     }
0471 
0472     //kreportDebug() << "Page Size:" << m_maxWidth << m_maxHeight;
0473 
0474     m_document->setPageLayout(m_reportDocument->pageLayout());
0475     m_dataSource->setSorting(m_reportDocument->detail()->sortedFields);
0476     if (!m_dataSource->open()) {
0477         return false;
0478     }
0479 
0480     #ifdef KREPORT_SCRIPTING
0481     initEngine();
0482     connect(m_scriptHandler, SIGNAL(groupChanged(QMap<QString, QVariant>)),
0483             m_preRenderer, SIGNAL(groupChanged(QMap<QString, QVariant>)));
0484 
0485     //Loop through all abjects that have been registered, and register them with the script handler
0486     if (m_scriptHandler) {
0487         QMapIterator<QString, QObject*> i(m_scriptObjects);
0488         while (i.hasNext()) {
0489             i.next();
0490             m_scriptHandler->registerScriptObject(i.value(), i.key());
0491         }
0492         //execute the script, if it fails, abort and return the empty document
0493         if (!m_scriptHandler->trigger()) {
0494             m_scriptHandler->displayErrors();
0495             return m_document;
0496         }
0497     }
0498     #endif
0499 
0500     createNewPage();
0501     if (!label.isNull()) {
0502         // Label Print Run
0503         // remember the initial margin setting as we will be modifying
0504         // the value and restoring it as we move around
0505         qreal margin = m_leftMargin;
0506 
0507         m_yOffset = m_topMargin;
0508 
0509         qreal w = (label.width() / 100.0);
0510         qreal wg = (label.xGap() / 100.0);
0511         qreal h = (label.height() / 100.0);
0512         qreal hg = (label.yGap() / 100.0);
0513         int numCols = label.columns();
0514         int numRows = label.rows();
0515         qreal tmp;
0516 
0517         // flip the value around if we are printing landscape
0518         if (!(m_reportDocument->pageLayout().orientation() == QPageLayout::Portrait)) {
0519             w = (label.height() / 100.0);
0520             wg = (label.yGap() / 100.0);
0521             h = (label.width() / 100.0);
0522             hg = (label.xGap() / 100.0);
0523             numCols = label.rows();
0524             numRows = label.columns();
0525         }
0526 
0527         KReportDetailSectionData * detailData = m_reportDocument->detail();
0528         if (detailData->detailSection) {
0529             KReportDataSource *mydata = m_dataSource;
0530 
0531             if (mydata && mydata->recordCount() > 0) { /* && !((query = orqThis->getQuery())->eof()))*/
0532                 if (!mydata->moveFirst()) {
0533                     return false;
0534                 }
0535                 int row = 0;
0536                 int col = 0;
0537                 do {
0538                     tmp = m_yOffset; // store the value as renderSection changes it
0539                     renderSection(*(detailData->detailSection));
0540                     m_yOffset = tmp; // restore the value that renderSection modified
0541 
0542                     col++;
0543                     m_leftMargin += w + wg;
0544                     if (col >= numCols) {
0545                         m_leftMargin = margin; // reset back to original value
0546                         col = 0;
0547                         row++;
0548                         m_yOffset += h + hg;
0549                         if (row >= numRows) {
0550                             m_yOffset = m_topMargin;
0551                             row = 0;
0552                             createNewPage();
0553                         }
0554                     }
0555                 } while (mydata->moveNext());
0556             }
0557         }
0558 
0559     } else {
0560         // Normal Print Run
0561         if (m_reportDocument->section(KReportSectionData::Type::ReportHeader)) {
0562             renderSection(*(m_reportDocument->section(KReportSectionData::Type::ReportHeader)));
0563         }
0564 
0565         if (m_reportDocument->detail()) {
0566             renderDetailSection(m_reportDocument->detail());
0567         }
0568 
0569         if (m_reportDocument->section(KReportSectionData::Type::ReportFooter)) {
0570             if (renderSectionSize(*(m_reportDocument->section(KReportSectionData::Type::ReportFooter))) + finishCurPageSize(true) + m_bottomMargin + m_yOffset >= m_maxHeight) {
0571                 createNewPage();
0572             }
0573             renderSection(*(m_reportDocument->section(KReportSectionData::Type::ReportFooter)));
0574         }
0575     }
0576     finishCurPage(true);
0577 
0578     #ifdef KREPORT_SCRIPTING
0579     // _postProcText contains those text boxes that need to be updated
0580     // with information that wasn't available at the time it was added to the document
0581     m_scriptHandler->setPageTotal(m_document->pageCount());
0582 
0583     for (int i = 0; i < m_postProcText.size(); i++) {
0584         OROTextBox * tb = m_postProcText.at(i);
0585 
0586         m_scriptHandler->setPageNumber(tb->page()->pageNumber() + 1);
0587 
0588         tb->setText(m_scriptHandler->evaluate(tb->text()).toString());
0589     }
0590     #endif
0591 
0592     asyncManager->startRendering();
0593 
0594     #ifdef KREPORT_SCRIPTING
0595     m_scriptHandler->displayErrors();
0596     #endif
0597 
0598     if (!m_dataSource->close()) {
0599         return false;
0600     }
0601     #ifdef KREPORT_SCRIPTING
0602     delete m_scriptHandler;
0603     m_scriptHandler = nullptr;
0604     #endif
0605 
0606     if (m_dataSource != m_oneRecord) {
0607         delete m_dataSource;
0608         m_dataSource = nullptr;
0609     }
0610     m_postProcText.clear();
0611 
0612     return true;
0613 }
0614 
0615 //===========================KReportPreRenderer===============================
0616 
0617 KReportPreRenderer::KReportPreRenderer(const QDomElement &document) : d(new KReportPreRendererPrivate(this))
0618 {
0619     setDocument(document);
0620     connect(d, &KReportPreRendererPrivate::finishedAllASyncItems, this, &KReportPreRenderer::finishedAllASyncItems);
0621 }
0622 
0623 KReportPreRenderer::~KReportPreRenderer()
0624 {
0625     delete d;
0626 }
0627 
0628 void KReportPreRenderer::setName(const QString &n)
0629 {
0630     d->m_reportDocument->setName(n);
0631 }
0632 
0633 bool KReportPreRenderer::isValid() const
0634 {
0635     if (d && d->m_valid)
0636         return true;
0637     return false;
0638 }
0639 
0640 ORODocument* KReportPreRenderer::document()
0641 {
0642     return d->m_document;
0643 }
0644 
0645 bool KReportPreRenderer::generateDocument()
0646 {
0647 //    delete d->m_document;
0648     if (!d->generateDocument()) {
0649         delete d->m_document;
0650         d->m_document = nullptr;
0651     }
0652     return d->m_document;
0653 }
0654 
0655 void KReportPreRenderer::setDataSource(KReportDataSource *dataSource)
0656 {
0657     if (d && dataSource != d->m_dataSource) {
0658         delete d->m_dataSource;
0659         d->m_dataSource = dataSource;
0660     }
0661 }
0662 
0663 bool KReportPreRenderer::setDocument(const QDomElement &document)
0664 {
0665     delete d->m_document;
0666     d->m_valid = false;
0667 
0668     if (document.tagName() != QLatin1String("report:content")) {
0669         kreportWarning() << "report schema is invalid";
0670         return false;
0671     }
0672 
0673     d->m_reportDocument = new KReportDocument(document);
0674     d->m_valid = d->m_reportDocument->isValid();
0675     return isValid();
0676 }
0677 
0678 #ifdef KREPORT_SCRIPTING
0679 void KReportPreRenderer::setScriptSource(KReportScriptSource *source)
0680 {
0681     if (d) {
0682         d->scriptSource = source;
0683     }
0684 }
0685 
0686 void KReportPreRenderer::registerScriptObject(QObject* obj, const QString& name)
0687 {
0688     //kreportDebug() << name;
0689     d->m_scriptObjects[name] = obj;
0690 }
0691 
0692 KReportScriptHandler *KReportPreRenderer::scriptHandler()
0693 {
0694     return d->m_scriptHandler;
0695 }
0696 #endif
0697 
0698 const KReportDocument* KReportPreRenderer::reportData() const
0699 {
0700     return d->m_reportDocument;
0701 }