1 /***************************************************************************
2 * This file is part of the Lime Report project *
3 * Copyright (C) 2015 by Alexander Arin *
4 * arin_a@bk.ru *
5 * *
6 ** GNU General Public License Usage **
7 * *
8 * This library is free software: you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation, either version 3 of the License, or *
11 * (at your option) any later version. *
12 * You should have received a copy of the GNU General Public License *
13 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
14 * *
15 ** GNU Lesser General Public License **
16 * *
17 * This library is free software: you can redistribute it and/or modify *
18 * it under the terms of the GNU Lesser General Public License as *
19 * published by the Free Software Foundation, either version 3 of the *
20 * License, or (at your option) any later version. *
21 * You should have received a copy of the GNU Lesser General Public *
22 * License along with this library. *
23 * If not, see <http://www.gnu.org/licenses/>. *
24 * *
25 * This library is distributed in the hope that it will be useful, *
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
28 * GNU General Public License for more details. *
29 ****************************************************************************/
30 #include <stdexcept>
31 #include <QMessageBox>
32
33 #include "lrglobal.h"
34 #include "lrreportrender.h"
35 #include "lrpagedesignintf.h"
36 #include "lrbanddesignintf.h"
37 #include "lritemdesignintf.h"
38 #include "lrscriptenginemanager.h"
39
40 #include "serializators/lrxmlreader.h"
41 #include "serializators/lrxmlwriter.h"
42
43 namespace LimeReport{
44
initColumns()45 void ReportRender::initColumns(){
46 m_maxHeightByColumn.clear();
47 m_currentStartDataPos.clear();
48 m_maxHeightByColumn.append(0);
49 m_currentStartDataPos.append(0);
50 m_currentColumn = 0;
51 }
52
isNeedToRearrangeColumnsItems()53 bool ReportRender::isNeedToRearrangeColumnsItems()
54 {
55 if (m_columnedBandItems.size()<=1) return false;
56 if (m_columnedBandItems[0]->columnsFillDirection()!=BandDesignIntf::VerticalUniform)
57 return false;
58
59 int avg = m_columnedBandItems.size()/m_columnedBandItems[0]->columnsCount();
60
61 for (int i=0;i<m_maxHeightByColumn.size();++i){
62 qreal maxHeight = 0;
63 int maxHeightColumn = 0;
64 if (m_maxHeightByColumn[i]>maxHeight){
65 maxHeight = m_maxHeightByColumn[i];
66 maxHeightColumn = i;
67 }
68 if (maxHeightColumn>0 && columnItemsCount(maxHeightColumn)<avg &&
69 maxHeight> lastColumnItem(maxHeightColumn-1)->height()
70 ){
71 return true;
72 }
73 }
74 return false;
75 }
76
lastColumnItem(int columnIndex)77 BandDesignIntf *ReportRender::lastColumnItem(int columnIndex)
78 {
79 if (columnIndex<0) return 0;
80 for(int i=0;i<m_columnedBandItems.size();++i){
81 if (m_columnedBandItems[i]->columnIndex()>columnIndex)
82 return m_columnedBandItems[i-1];
83 }
84 return m_columnedBandItems.last();
85 }
86
rearrangeColumnsItems()87 void ReportRender::rearrangeColumnsItems()
88 {
89 if (isNeedToRearrangeColumnsItems()){
90 qreal startHeight = columnHeigth(0);
91 int avg = m_columnedBandItems.size() / m_columnedBandItems[0]->columnsCount();
92 for (int i = 1; i < m_columnedBandItems[0]->columnsCount(); ++i){
93 if (columnItemsCount(i) < avg){
94 int getCount = avg * (m_columnedBandItems[0]->columnsCount()-i) - columnItemsCount(i);
95 for (int j = 0; j < getCount; ++j){
96 BandDesignIntf* band = lastColumnItem(i-1);
97 band->setPos(band->pos().x()+band->width(),m_columnedBandItems[0]->pos().y());
98 band->setColumnIndex(i);
99 }
100
101 }
102 }
103 m_renderPageItem->relocateBands();
104 m_maxHeightByColumn[0]+=startHeight-maxColumnHeight();
105 m_currentStartDataPos[0]-=startHeight-maxColumnHeight();
106 m_columnedBandItems.clear();
107 }
108 }
109
columnItemsCount(int columnIndex)110 int ReportRender::columnItemsCount(int columnIndex)
111 {
112 int result = 0;
113 foreach(BandDesignIntf* band, m_columnedBandItems){
114 if (band->columnIndex()==columnIndex)
115 ++result;
116 if (band->columnIndex()>columnIndex) break;
117 }
118 return result;
119 }
120
columnHeigth(int columnIndex)121 qreal ReportRender::columnHeigth(int columnIndex)
122 {
123 qreal result = 0;
124 for(int i=0;i<m_columnedBandItems.size();++i){
125 if (m_columnedBandItems[i]->columnIndex()==columnIndex)
126 result += m_columnedBandItems[i]->height();
127 if (m_columnedBandItems[i]->columnIndex()>columnIndex) break;
128 }
129 return result;
130 }
131
maxColumnHeight()132 qreal ReportRender::maxColumnHeight()
133 {
134 qreal result = 0;
135 for (int i=0;i<m_columnedBandItems[0]->columnsCount();++i){
136 qreal curColumnHeight = columnHeigth(i);
137 if (curColumnHeight>result) result = curColumnHeight;
138 }
139 return result;
140 }
141
renameChildItems(BaseDesignIntf * item)142 void ReportRender::renameChildItems(BaseDesignIntf *item){
143 foreach(BaseDesignIntf* child, item->childBaseItems()){
144 if (!child->childBaseItems().isEmpty()) renameChildItems(child);
145 child->setObjectName(child->metaObject()->className()+QString::number(++m_currentNameIndex));
146 }
147 }
148
ReportRender(QObject * parent)149 ReportRender::ReportRender(QObject *parent)
150 :QObject(parent), m_renderPageItem(0), m_pageCount(0),
151 m_lastRenderedHeader(0), m_lastDataBand(0), m_lastRenderedFooter(0),
152 m_currentColumn(0), m_newPageStarted(false), m_lostHeadersMoved(false)
153 {
154 initColumns();
155 }
156
setDatasources(DataSourceManager * value)157 void ReportRender::setDatasources(DataSourceManager *value)
158 {
159 m_datasources=value;
160 initVariables();
161 resetPageNumber(BandReset);
162 }
163
setScriptContext(ScriptEngineContext * scriptContext)164 void ReportRender::setScriptContext(ScriptEngineContext* scriptContext)
165 {
166 m_scriptEngineContext=scriptContext;
167 }
168
initDatasources()169 void ReportRender::initDatasources(){
170 try{
171 datasources()->setAllDatasourcesToFirst();
172 } catch(ReportError &exception){
173 //TODO possible should thow exeption
174 QMessageBox::critical(0,tr("Error"),exception.what());
175 return;
176 }
177 }
178
initDatasource(const QString & name)179 void ReportRender::initDatasource(const QString& name){
180 try{
181 if (datasources()->containsDatasource(name)){
182 IDataSource* ds = datasources()->dataSource(name);
183 if (ds)
184 ds->first();
185 }
186 } catch(ReportError &exception){
187 QMessageBox::critical(0,tr("Error"),exception.what());
188 return;
189 }
190 }
191
analizeItem(ContentItemDesignIntf * contentItem,BandDesignIntf * band)192 void ReportRender::analizeItem(ContentItemDesignIntf* contentItem, BandDesignIntf* band){
193 if (contentItem){
194 QString content = contentItem->content();
195 QVector<QString> functions;
196 foreach(const QString &functionName, m_datasources->groupFunctionNames()){
197 QRegExp rx(QString(Const::GROUP_FUNCTION_RX).arg(functionName));
198 rx.setMinimal(true);
199 if (rx.indexIn(content)>=0){
200 functions.append(functionName);
201 }
202 }
203 if (functions.size()>0)
204 m_groupfunctionItems.insert(contentItem->patternName(), functions);
205 }
206 }
207
analizeContainer(BaseDesignIntf * item,BandDesignIntf * band)208 void ReportRender::analizeContainer(BaseDesignIntf* item, BandDesignIntf* band){
209 foreach(BaseDesignIntf* child, item->childBaseItems()){
210 ContentItemDesignIntf* contentItem = dynamic_cast<ContentItemDesignIntf*>(child);
211 if (contentItem) analizeItem(contentItem, band);
212 else analizeContainer(child, band);
213 }
214 }
215
analizePage(PageItemDesignIntf * patternPage)216 void ReportRender::analizePage(PageItemDesignIntf* patternPage){
217 m_groupfunctionItems.clear();
218 foreach(BandDesignIntf* band, patternPage->bands()){
219 if (band->isFooter() || band->isHeader()){
220 analizeContainer(band,band);
221 }
222 }
223 }
224
renderPage(PageItemDesignIntf * patternPage,bool isTOC,bool,bool)225 void ReportRender::renderPage(PageItemDesignIntf* patternPage, bool isTOC, bool /*isFirst*/, bool /*resetPageNumbers*/)
226 {
227 m_currentNameIndex = 0;
228 m_patternPageItem = patternPage;
229
230 analizePage(patternPage);
231
232 if (m_patternPageItem->resetPageNumber() && m_pageCount>0 && !isTOC) {
233 resetPageNumber(PageReset);
234 }
235
236 if (m_patternPageItem->resetPageNumber() && !isTOC && m_pageCount == 0){
237 m_pagesRanges.startNewRange();
238 }
239
240 m_renderCanceled = false;
241 BandDesignIntf* reportFooter = m_patternPageItem->bandByType(BandDesignIntf::ReportFooter);
242 m_reportFooterHeight = 0;
243 if (reportFooter)
244 m_reportFooterHeight = reportFooter->height();
245
246 initGroups();
247 clearPageMap();
248
249 try{
250 datasources()->setAllDatasourcesToFirst();
251 datasources()->clearGroupFuntionsExpressions();
252 } catch(ReportError &exception){
253 //TODO possible should thow exeption
254 QMessageBox::critical(0,tr("Error"),exception.what());
255 return;
256 }
257
258 clearPageMap();
259 startNewPage(true);
260
261 renderReportHeader(m_patternPageItem, AfterPageHeader);
262
263 BandDesignIntf* lastRenderedBand = 0;
264 for (int i=0;i<m_patternPageItem->dataBandCount() && !m_renderCanceled; i++){
265 lastRenderedBand = m_patternPageItem->dataBandAt(i);
266 initDatasource(lastRenderedBand->datasourceName());
267 renderDataBand(lastRenderedBand);
268 if (i < m_patternPageItem->dataBandCount()-1) closeFooterGroup(lastRenderedBand);
269 }
270
271 if (reportFooter)
272 renderBand(reportFooter, 0, StartNewPageAsNeeded);
273 if (lastRenderedBand && lastRenderedBand->keepFooterTogether())
274 closeFooterGroup(lastRenderedBand);
275
276 BandDesignIntf* tearOffBand = m_patternPageItem->bandByType(BandDesignIntf::TearOffBand);
277 if (tearOffBand)
278 renderBand(tearOffBand, 0, StartNewPageAsNeeded);
279
280 savePage(true);
281
282 }
283
pageCount()284 int ReportRender::pageCount()
285 {
286 return m_renderedPages.count();
287 }
288
pageAt(int index)289 PageItemDesignIntf::Ptr ReportRender::pageAt(int index)
290 {
291 if ((index>m_renderedPages.count()-1)||(index<0)) throw ReportError(tr("page index out of range"));
292 else return m_renderedPages.at(index);
293 }
294
renderPageToString(PageItemDesignIntf * patternPage)295 QString ReportRender::renderPageToString(PageItemDesignIntf *patternPage)
296 {
297 renderPage(patternPage);
298 return toString();
299 }
300
renderPageToPages(PageItemDesignIntf * patternPage)301 ReportPages ReportRender::renderPageToPages(PageItemDesignIntf *patternPage)
302 {
303 renderPage(patternPage);
304 return m_renderedPages;
305 }
306
renderTOC(PageItemDesignIntf * patternPage,bool first,bool resetPages)307 ReportPages ReportRender::renderTOC(PageItemDesignIntf* patternPage, bool first, bool resetPages){
308 renderPage(patternPage, true, first, resetPages);
309 return m_renderedPages;
310 }
311
initRenderPage()312 void ReportRender::initRenderPage()
313 {
314 if (!m_renderPageItem) {
315 m_renderPageItem = new PageItemDesignIntf(m_patternPageItem->pageSize(), m_patternPageItem->pageRect());
316 m_renderPageItem->initFromItem(m_patternPageItem);
317 m_renderPageItem->setItemMode(PreviewMode);
318 m_renderPageItem->setPatternName(m_patternPageItem->objectName());
319 m_renderPageItem->setPatternItem(m_patternPageItem);
320
321 ScriptValueType svCurrentPage;
322 ScriptEngineType* se = ScriptEngineManager::instance().scriptEngine();
323
324 #ifdef USE_QJSENGINE
325 svCurrentPage = getJSValue(*se, m_renderPageItem);
326 se->globalObject().setProperty("currentPage", svCurrentPage);
327 #else
328 svCurrentPage = se->globalObject().property("currentPage");
329 if (svCurrentPage.isValid()){
330 se->newQObject(svCurrentPage, m_renderPageItem);
331 } else {
332 svCurrentPage = se->newQObject(m_renderPageItem);
333 se->globalObject().setProperty("currentPage", svCurrentPage);
334 }
335 #endif
336
337
338 }
339 }
340
initVariables()341 void ReportRender::initVariables()
342 {
343 m_datasources->setReportVariable("#PAGE",1);
344 m_datasources->setReportVariable("#PAGE_COUNT",0);
345 m_datasources->setReportVariable("#IS_LAST_PAGEFOOTER",false);
346 m_datasources->setReportVariable("#IS_FIRST_PAGEFOOTER",false);
347 }
348
clearPageMap()349 void ReportRender::clearPageMap()
350 {
351 m_renderedPages.clear();
352 }
353
containsGroupFunctions(BandDesignIntf * band)354 bool ReportRender::containsGroupFunctions(BandDesignIntf *band){
355 foreach(BaseDesignIntf* item,band->childBaseItems()){
356 ContentItemDesignIntf* contentItem = dynamic_cast<ContentItemDesignIntf*>(item);
357 if (contentItem){
358 QString content = contentItem->content();
359 foreach(QString functionName, m_datasources->groupFunctionNames()){
360 QRegExp rx(QString(Const::GROUP_FUNCTION_RX).arg(functionName));
361 if (rx.indexIn(content)>=0){
362 return true;
363 }
364 }
365 }
366 }
367 return false;
368 }
369
extractGroupFuntionsFromItem(ContentItemDesignIntf * contentItem,BandDesignIntf * band)370 void ReportRender::extractGroupFuntionsFromItem(ContentItemDesignIntf* contentItem, BandDesignIntf* band){
371 if ( contentItem && contentItem->content().contains(QRegExp("\\$S\\s*\\{.*\\}"))){
372 foreach(const QString &functionName, m_datasources->groupFunctionNames()){
373 QRegExp rx(QString(Const::GROUP_FUNCTION_RX).arg(functionName));
374 rx.setMinimal(true);
375 QRegExp rxName(QString(Const::GROUP_FUNCTION_NAME_RX).arg(functionName));
376 rxName.setMinimal(true);
377 if (rx.indexIn(contentItem->content())>=0){
378 int pos = 0;
379 while ( (pos = rx.indexIn(contentItem->content(),pos)) != -1){
380 QVector<QString> captures = normalizeCaptures(rx);
381 if (captures.size()>=3){
382 int dsIndex = captures.size() == 3 ? Const::DATASOURCE_INDEX - 1 : Const::DATASOURCE_INDEX;
383 BandDesignIntf* dataBand = m_patternPageItem->bandByName(captures.at(dsIndex));
384 if (dataBand){
385 GroupFunction* gf = datasources()->addGroupFunction(functionName,captures.at(Const::VALUE_INDEX),band->objectName(),dataBand->objectName());
386 if (gf){
387 connect(dataBand,SIGNAL(bandRendered(BandDesignIntf*)),gf,SLOT(slotBandRendered(BandDesignIntf*)));
388 }
389 } else {
390 GroupFunction* gf = datasources()->addGroupFunction(functionName,captures.at(Const::VALUE_INDEX),band->objectName(),captures.at(dsIndex));
391 gf->setInvalid(tr("Databand \"%1\" not found").arg(captures.at(dsIndex)));
392 }
393 }
394 pos += rx.matchedLength();
395 }
396 } else if (rxName.indexIn(contentItem->content())>=0){
397 GroupFunction* gf = datasources()->addGroupFunction(functionName,rxName.cap(1),band->objectName(),"");
398 gf->setInvalid(tr("Wrong using function %1").arg(functionName));
399 }
400 }
401 }
402 }
403
extractGroupFunctionsFromContainer(BaseDesignIntf * baseItem,BandDesignIntf * band)404 void ReportRender::extractGroupFunctionsFromContainer(BaseDesignIntf* baseItem, BandDesignIntf* band){
405 foreach (BaseDesignIntf* item, baseItem->childBaseItems()) {
406 ContentItemDesignIntf* contentItem = dynamic_cast<ContentItemDesignIntf*>(item);
407 if (contentItem) extractGroupFuntionsFromItem(contentItem, band);
408 else extractGroupFunctionsFromContainer(item, band);
409 }
410
411 }
412
extractGroupFunctions(BandDesignIntf * band)413 void ReportRender::extractGroupFunctions(BandDesignIntf *band)
414 {
415 extractGroupFunctionsFromContainer(band, band);
416 }
417
replaceGroupFunctionsInItem(ContentItemDesignIntf * contentItem,BandDesignIntf * band)418 void ReportRender::replaceGroupFunctionsInItem(ContentItemDesignIntf* contentItem, BandDesignIntf* band){
419 if (contentItem){
420 if (m_groupfunctionItems.contains(contentItem->patternName())){
421 QString content = contentItem->content();
422 foreach(QString functionName, m_groupfunctionItems.value(contentItem->patternName())){
423 QRegExp rx(QString(Const::GROUP_FUNCTION_RX).arg(functionName));
424 rx.setMinimal(true);
425 if (rx.indexIn(content)>=0){
426 int pos = 0;
427 while ( (pos = rx.indexIn(content,pos))!= -1 ){
428 QVector<QString> captures = normalizeCaptures(rx);
429 if (captures.size() >= 3){
430 QString expressionIndex = datasources()->putGroupFunctionsExpressions(captures.at(Const::VALUE_INDEX));
431 if (captures.size()<5){
432 content.replace(captures.at(0),QString("%1(%2,%3)").arg(functionName).arg('"'+expressionIndex+'"').arg('"'+band->objectName()+'"'));
433 } else {
434 content.replace(captures.at(0),QString("%1(%2,%3,%4)")
435 .arg(functionName)
436 .arg('"'+expressionIndex+'"')
437 .arg('"'+band->objectName()+'"')
438 .arg(captures.at(4)));
439 }
440 }
441 pos += rx.matchedLength();
442 }
443 }
444 }
445 contentItem->setContent(content);
446 }
447 }
448 }
449
replaceGroupFunctionsInContainer(BaseDesignIntf * baseItem,BandDesignIntf * band)450 void ReportRender::replaceGroupFunctionsInContainer(BaseDesignIntf* baseItem, BandDesignIntf* band)
451 {
452 foreach(BaseDesignIntf* item, baseItem->childBaseItems()){
453 ContentItemDesignIntf* contentItem = dynamic_cast<ContentItemDesignIntf*>(item);
454 if (contentItem) replaceGroupFunctionsInItem(contentItem, band);
455 else replaceGroupFunctionsInContainer(item, band);
456 }
457 }
458
replaceGroupsFunction(BandDesignIntf * band)459 void ReportRender::replaceGroupsFunction(BandDesignIntf *band)
460 {
461 replaceGroupFunctionsInContainer(band, band);
462 }
463
renderBand(BandDesignIntf * patternBand,BandDesignIntf * bandData,ReportRender::DataRenderMode mode,bool isLast)464 BandDesignIntf* ReportRender::renderBand(BandDesignIntf *patternBand, BandDesignIntf* bandData, ReportRender::DataRenderMode mode, bool isLast)
465 {
466 QCoreApplication::processEvents();
467 bool bandIsSliced = false;
468 if (patternBand){
469
470 if (patternBand->isHeader())
471 m_lastRenderedHeader = patternBand;
472
473 BandDesignIntf* bandClone = 0;
474
475 if (bandData){
476 bandClone = bandData;
477 } else {
478 bandClone = renderData(patternBand);
479 }
480
481 if (isLast) bandClone->setBootomSpace(1);
482
483 if (mode == ForcedStartPage){
484 savePage();
485 startNewPage();
486 }
487
488 if (patternBand->isFooter())
489 m_lastRenderedFooter = patternBand;
490
491 if (bandClone->useAlternateBackgroundColor()){
492 bandClone->setBackgroundColor(
493 (datasources()->variable(QLatin1String("line_")+patternBand->objectName().toLower()).toInt() %2 == 0 ?
494 bandClone->backgroundColor() :
495 bandClone->alternateBackgroundColor()
496 )
497 );
498 }
499
500 patternBand->emitBandRendered(bandClone);
501 m_scriptEngineContext->setCurrentBand(bandClone);
502 emit(patternBand->afterRender());
503
504 if ( isLast && bandClone->keepFooterTogether() && bandClone->sliceLastRow() ){
505 if (m_maxHeightByColumn[m_currentColumn] < (bandClone->height()+m_reportFooterHeight))
506 m_maxHeightByColumn[m_currentColumn] -= ((m_maxHeightByColumn[m_currentColumn]-bandClone->height())+(bandClone->height()*calcSlicePercent(bandClone->height())));
507 }
508
509 if (!bandClone->isEmpty() || patternBand->printIfEmpty()){
510 if (!registerBand(bandClone)){
511 if (patternBand && patternBand->isHeader() && patternBand->reprintOnEachPage())
512 m_reprintableBands.removeOne(patternBand);
513 if (bandClone->canBeSplitted(m_maxHeightByColumn[m_currentColumn])){
514 bandClone = sliceBand(bandClone, patternBand, isLast);
515 bandIsSliced = true;
516 } else {
517 qreal percent = (bandClone->height()-m_maxHeightByColumn[m_currentColumn])/(bandClone->height()/100);
518 if (bandClone->maxScalePercent()>=percent){
519 if (percent<bandClone->maxScalePercent()){
520 percent += 2;
521 bandClone->setScale((100-percent)/100);
522 BandDesignIntf* upperPart = dynamic_cast<BandDesignIntf*>(bandClone->cloneUpperPart(m_maxHeightByColumn[m_currentColumn]));
523 registerBand(upperPart);
524 delete bandClone;
525 bandClone = NULL;
526 }
527 } else {
528
529 if (mode==StartNewPageAsNeeded){
530 if (bandClone->columnsCount()>1 &&
531 (bandClone->columnsFillDirection()==BandDesignIntf::Vertical ||
532 bandClone->columnsFillDirection()==BandDesignIntf::VerticalUniform))
533 {
534 startNewColumn();
535 if (patternBand->bandHeader() &&
536 patternBand->bandHeader()->columnsCount()>1 &&
537 !m_lostHeadersMoved &&
538 patternBand->bandNestingLevel() == 0
539 ){
540 renderBand(patternBand->bandHeader(), 0, mode);
541 }
542 } else {
543 savePage();
544 startNewPage();
545 if (!bandIsSliced){
546 BandDesignIntf* t = renderData(patternBand);
547 t->copyBookmarks(bandClone);
548 delete bandClone;
549 bandClone = t;
550 }
551 }
552 if (!registerBand(bandClone)) {
553 BandDesignIntf* upperPart = dynamic_cast<BandDesignIntf*>(bandClone->cloneUpperPart(m_maxHeightByColumn[m_currentColumn]));
554 registerBand(upperPart);
555 delete bandClone;
556 bandClone = NULL;
557 };
558 } else {
559 bandClone->setHeight(m_maxHeightByColumn[m_currentColumn]);
560 registerBand(bandClone);
561 }
562 }
563 }
564 }
565 } else {
566 delete bandClone;
567 return 0;
568 }
569
570 if (patternBand->isFooter())
571 datasources()->clearGroupFunctionValues(patternBand->objectName());
572 return bandClone;
573 }
574 return 0;
575 }
576
renderDataBand(BandDesignIntf * dataBand)577 void ReportRender::renderDataBand(BandDesignIntf *dataBand)
578 {
579 if (dataBand == NULL )
580 return;
581
582 IDataSource* bandDatasource = 0;
583 m_lastRenderedFooter = 0;
584
585 if (!dataBand->datasourceName().isEmpty())
586 bandDatasource = datasources()->dataSource(dataBand->datasourceName());
587
588 BandDesignIntf* header = dataBand->bandHeader();
589 BandDesignIntf* footer = dataBand->bandFooter();
590
591 if (header && header->printAlways()) renderDataHeader(header);
592
593 if(bandDatasource && !bandDatasource->eof() && !m_renderCanceled){
594
595 QString varName = QLatin1String("line_")+dataBand->objectName().toLower();
596 datasources()->setReportVariable(varName,1);
597
598 if (header && header->reprintOnEachPage())
599 m_reprintableBands.append(dataBand->bandHeader());
600
601 if (header && !header->printAlways())
602 renderDataHeader(header);
603
604 renderGroupHeader(dataBand, bandDatasource, true);
605
606 bool firstTime = true;
607
608
609 while(!bandDatasource->eof() && !m_renderCanceled){
610
611 BandDesignIntf* rawData = renderData(dataBand);
612
613 if (!rawData->isEmpty() || dataBand->printIfEmpty()){
614
615 if ((firstTime && dataBand->startFromNewPage()) ||
616 (!firstTime && dataBand->startNewPage())) {
617 savePage();
618 startNewPage();
619 }
620
621 if (dataBand->tryToKeepTogether()) openDataGroup(dataBand);
622
623 if (dataBand->keepFooterTogether() && !bandDatasource->hasNext())
624 openFooterGroup(dataBand);
625
626 datasources()->updateChildrenData(dataBand->datasourceName());
627 m_lastDataBand = dataBand;
628
629 if (header && !firstTime && header->repeatOnEachRow())
630 renderBand(header, 0, StartNewPageAsNeeded);
631
632 renderBand(dataBand, rawData, StartNewPageAsNeeded, !bandDatasource->hasNext());
633 m_newPageStarted = false;
634 renderChildBands(dataBand);
635
636 }
637
638 bandDatasource->next();
639
640 datasources()->setReportVariable(varName,datasources()->variable(varName).toInt()+1);
641
642 QList<BandDesignIntf *> bandList;
643 QList<BandDesignIntf *> childList;
644
645 bandList = dataBand->childrenByType(BandDesignIntf::GroupHeader);
646 while (bandList.size() > 0)
647 {
648 childList.clear();
649 foreach (BandDesignIntf* band, bandList)
650 {
651 childList.append(band->childrenByType(BandDesignIntf::GroupHeader));
652
653 QString groupLineVar = QLatin1String("line_")+band->objectName().toLower();
654 if (datasources()->containsVariable(groupLineVar))
655 datasources()->setReportVariable(groupLineVar,datasources()->variable(groupLineVar).toInt()+1);
656 }
657 bandList = childList;
658 }
659
660 renderGroupHeader(dataBand, bandDatasource, false);
661 if (dataBand->tryToKeepTogether()) closeDataGroup(dataBand);
662 firstTime = false;
663 }
664
665 if (!dataBand->keepFooterTogether())
666 m_reprintableBands.removeOne(header);
667 if (header) recalcIfNeeded(header);
668
669 if (bandDatasource->prior()){
670 renderGroupFooter(dataBand);
671 bandDatasource->next();
672 }
673
674 if (footer && !footer->printAlways()){
675 renderBand(footer, 0, StartNewPageAsNeeded);
676 if (dataBand->keepFooterTogether())
677 m_reprintableBands.removeOne(dataBand);
678 }
679
680 datasources()->deleteVariable(varName);
681
682 } else if (bandDatasource==0) {
683 renderBand(dataBand, 0, StartNewPageAsNeeded);
684 }
685
686 if (footer && footer->printAlways()){
687 renderBand(footer, 0, StartNewPageAsNeeded);
688 if (dataBand->keepFooterTogether())
689 m_reprintableBands.removeOne(dataBand);
690 }
691 }
692
renderPageHeader(PageItemDesignIntf * patternPage)693 void ReportRender::renderPageHeader(PageItemDesignIntf *patternPage)
694 {
695 BandDesignIntf* band = patternPage->bandByType(BandDesignIntf::PageHeader);
696 if (band){
697 if (m_datasources->variable("#PAGE").toInt()!=1 ||
698 band->property("printOnFirstPage").toBool()
699 )
700 renderBand(band, 0);
701 }
702 }
703
renderReportHeader(PageItemDesignIntf * patternPage,PageRenderStage stage)704 void ReportRender::renderReportHeader(PageItemDesignIntf *patternPage, PageRenderStage stage)
705 {
706 BandDesignIntf* band = patternPage->bandByType(BandDesignIntf::ReportHeader);
707 if (band){
708 if (band->property("printBeforePageHeader").toBool() && stage == BeforePageHeader )
709 renderBand(band, 0, StartNewPageAsNeeded);
710 if (!band->property("printBeforePageHeader").toBool() && stage == AfterPageHeader )
711 renderBand(band, 0, StartNewPageAsNeeded);
712 }
713 }
714
renderPageFooter(PageItemDesignIntf * patternPage)715 void ReportRender::renderPageFooter(PageItemDesignIntf *patternPage)
716 {
717 BandDesignIntf* band = patternPage->bandByType(BandDesignIntf::PageFooter);
718 if (band){
719 BandDesignIntf* bandClone = dynamic_cast<BandDesignIntf*>(band->cloneItem(PreviewMode, m_renderPageItem, m_renderPageItem));
720 replaceGroupsFunction(bandClone);
721 bandClone->updateItemSize(m_datasources);
722 bandClone->setItemPos(m_renderPageItem->pageRect().x(),m_renderPageItem->pageRect().bottom()-bandClone->height());
723 bandClone->setHeight(m_pageFooterHeight);
724 for(int i=0;i<m_maxHeightByColumn.size();++i)
725 m_maxHeightByColumn[i]+=m_pageFooterHeight;
726 m_renderPageItem->setPageFooter(bandClone);
727 registerBand(bandClone);
728 datasources()->clearGroupFunctionValues(band->objectName());
729 }
730 }
731
renderPageItems(PageItemDesignIntf * patternPage)732 void ReportRender::renderPageItems(PageItemDesignIntf* patternPage)
733 {
734 QList<BaseDesignIntf*> pageItems;
735 foreach (BaseDesignIntf* item, patternPage->childBaseItems()) {
736 ItemDesignIntf* id = dynamic_cast<ItemDesignIntf*>(item);
737 if (id&&id->itemLocation()==ItemDesignIntf::Page){
738 BaseDesignIntf* cloneItem = item->cloneItem(m_renderPageItem->itemMode(),
739 m_renderPageItem,
740 m_renderPageItem);
741 pageItems.append(cloneItem);
742 }
743 }
744 m_renderPageItem->restoreLinks();
745 m_renderPageItem->updateSubItemsSize(FirstPass,m_datasources);
746 foreach(BaseDesignIntf* item, pageItems){
747 if (!item->isWatermark())
748 item->setZValue(item->zValue()-100000);
749 else
750 item->setZValue(item->zValue()+100000);
751 }
752 }
753
calcPageFooterHeight(PageItemDesignIntf * patternPage)754 qreal ReportRender::calcPageFooterHeight(PageItemDesignIntf *patternPage)
755 {
756 BandDesignIntf* band = patternPage->bandByType(BandDesignIntf::PageFooter);
757 if (band){
758 if (m_datasources->variable("#PAGE")!=1)
759 return band->height();
760 else if (band->property("printOnFirstPage").toBool())
761 return band->height();
762 }
763 return 0;
764 }
765
renderChildHeader(BandDesignIntf * parent,BandPrintMode printMode)766 void ReportRender::renderChildHeader(BandDesignIntf *parent, BandPrintMode printMode)
767 {
768 foreach(BandDesignIntf* band,parent->childrenByType(BandDesignIntf::SubDetailHeader)){
769 bool printAlways=false;
770 if (band->metaObject()->indexOfProperty("printAlways")>0){
771 printAlways=band->property("printAlways").toBool();
772 }
773 if (printAlways == (printMode == PrintAlwaysPrintable))
774 renderBand(band, 0, StartNewPageAsNeeded);
775 }
776 }
777
renderChildFooter(BandDesignIntf * parent,BandPrintMode printMode)778 void ReportRender::renderChildFooter(BandDesignIntf *parent, BandPrintMode printMode)
779 {
780 foreach(BandDesignIntf* band,parent->childrenByType(BandDesignIntf::SubDetailFooter)){
781 bool printAlways=false;
782 if (band->metaObject()->indexOfProperty("printAlways")>0){
783 printAlways=band->property("printAlways").toBool();
784 }
785
786 if ( (band != m_lastRenderedFooter) && (printAlways == (printMode == PrintAlwaysPrintable)) )
787 renderBand(band, 0, StartNewPageAsNeeded);
788 }
789 }
790
renderChildBands(BandDesignIntf * parentBand)791 void ReportRender::renderChildBands(BandDesignIntf *parentBand)
792 {
793 foreach(BandDesignIntf* band,parentBand->childrenByType(BandDesignIntf::SubDetailBand)){
794 IDataSource* ds = 0;
795 if (!band->datasourceName().isEmpty())
796 ds = m_datasources->dataSource(band->datasourceName());
797 if (ds) ds->first();
798 renderDataBand(band);
799 closeFooterGroup(band);
800 }
801 }
802
findRecalcableBand(BandDesignIntf * patternBand)803 BandDesignIntf* ReportRender::findRecalcableBand(BandDesignIntf* patternBand){
804
805 QList<BandDesignIntf*>::iterator it = m_recalcBands.begin();
806 for (;it !=m_recalcBands.end() ;++it){
807 if ((*it)->patternItem() == patternBand){
808 BandDesignIntf* result = (*it);
809 m_recalcBands.erase(it);
810 return result;
811 }
812 }
813 return 0;
814 }
815
recalcIfNeeded(BandDesignIntf * band)816 void ReportRender::recalcIfNeeded(BandDesignIntf* band){
817 BandDesignIntf* recalcBand = findRecalcableBand(band);
818 if (recalcBand){
819 QString bandName = recalcBand->objectName();
820 recalcBand->restoreItems();
821 recalcBand->setObjectName(recalcBand->patternItem()->objectName());
822 replaceGroupsFunction(recalcBand);
823 recalcBand->updateItemSize(datasources());
824 recalcBand->setObjectName(bandName);
825 datasources()->clearGroupFunctionValues(recalcBand->patternItem()->objectName());
826 }
827 }
828
renderDataHeader(BandDesignIntf * header)829 void ReportRender::renderDataHeader(BandDesignIntf *header)
830 {
831 recalcIfNeeded(header);
832 BandDesignIntf* renderedHeader = renderBand(header, 0);
833 if (containsGroupFunctions(header))
834 m_recalcBands.append(renderedHeader);
835 }
836
renderGroupHeader(BandDesignIntf * parentBand,IDataSource * dataSource,bool firstTime)837 void ReportRender::renderGroupHeader(BandDesignIntf *parentBand, IDataSource* dataSource, bool firstTime)
838 {
839 foreach(BandDesignIntf* band,parentBand->childrenByType(BandDesignIntf::GroupHeader)){
840 IGroupBand* gb = dynamic_cast<IGroupBand*>(band);
841 if (gb&&gb->isNeedToClose(datasources())){
842 if (band->childBands().count()>0){
843 bool didGoBack = dataSource->prior();
844 renderGroupFooterByHeader(band);
845 if (didGoBack){
846 dataSource->next();
847 }
848 }
849 closeDataGroup(band);
850 }
851
852 if (gb && !gb->isStarted()){
853 if (band->reprintOnEachPage()){
854 m_reprintableBands.append(band);
855 }
856 gb->startGroup(m_datasources);
857 openDataGroup(band);
858 BandDesignIntf* renderedHeader = 0;
859 if (!firstTime && gb->startNewPage() && !m_newPageStarted){
860 if (gb->resetPageNumber()) resetPageNumber(BandReset);
861 if (band->reprintOnEachPage()){
862 savePage();
863 startNewPage();
864 } else {
865 renderedHeader = renderBand(band, 0, ForcedStartPage);
866 }
867 } else {
868 renderedHeader = renderBand(band, 0, StartNewPageAsNeeded);
869 }
870 if (containsGroupFunctions(band))
871 m_recalcBands.append(renderedHeader);
872 }
873
874 renderGroupHeader(band, dataSource, firstTime);
875 }
876 }
877
renderGroupFooterByHeader(BandDesignIntf * groupHeader)878 void ReportRender::renderGroupFooterByHeader(BandDesignIntf* groupHeader){
879 if (groupHeader->reprintOnEachPage()) m_reprintableBands.removeOne(groupHeader);
880 foreach (BandDesignIntf* header, groupHeader->childrenByType(BandDesignIntf::GroupHeader)){
881 renderGroupFooterByHeader(header);
882 }
883 foreach (BandDesignIntf* footer, groupHeader->childrenByType(BandDesignIntf::GroupFooter)){
884 renderBand(footer, 0, StartNewPageAsNeeded);
885 }
886 closeDataGroup(groupHeader);
887 }
888
renderGroupFooter(BandDesignIntf * parentBand)889 void ReportRender::renderGroupFooter(BandDesignIntf *parentBand)
890 {
891 foreach(BandDesignIntf* band,parentBand->childrenByType(BandDesignIntf::GroupHeader)){
892 IGroupBand* gb = dynamic_cast<IGroupBand*>(band);
893 if (gb && gb->isStarted()){
894 renderGroupFooterByHeader(band);
895 }
896 }
897 }
898
initGroups()899 void ReportRender::initGroups()
900 {
901 m_datasources->clearGroupFunction();
902 foreach(BandDesignIntf* band, m_patternPageItem->childBands()){
903 if (band->isFooter()) extractGroupFunctions(band);
904 if (band->isHeader()){
905 IGroupBand* gb = dynamic_cast<IGroupBand*>(band);
906 if (gb) gb->closeGroup();
907 extractGroupFunctions(band);
908 }
909 }
910 }
911
popPageFooterGroupValues(BandDesignIntf * dataBand)912 void ReportRender::popPageFooterGroupValues(BandDesignIntf *dataBand)
913 {
914 BandDesignIntf* pageFooter = m_patternPageItem->bandByType(BandDesignIntf::PageFooter);
915 if (pageFooter){
916 foreach(GroupFunction* gf, datasources()->groupFunctionsByBand(pageFooter->objectName())){
917 if ((gf->dataBandName()==dataBand->objectName())){
918 // FIXME Probably coincidence Field and Variables
919 if ((!m_popupedExpression.contains(dataBand))||(!m_popupedExpression.values(dataBand).contains(gf->data()))){
920 m_popupedExpression.insert(dataBand,gf->data());
921 m_popupedValues.insert(QString("%1").arg((quintptr)dataBand)+'|'+gf->data(), gf->values()[gf->values().count()-1]);
922 gf->values().pop_back();
923 }
924 }
925 }
926 }
927 }
928
pushPageFooterGroupValues(BandDesignIntf * dataBand)929 void ReportRender::pushPageFooterGroupValues(BandDesignIntf *dataBand)
930 {
931 BandDesignIntf* pageFooter = m_patternPageItem->bandByType(BandDesignIntf::PageFooter);
932 if (pageFooter){
933 foreach(GroupFunction* gf, datasources()->groupFunctionsByBand(pageFooter->objectName())){
934 if ((gf->dataBandName()==dataBand->objectName())){
935 // FIXME Probably coincidence Field and Variables
936 if ((m_popupedExpression.contains(dataBand))&&(m_popupedExpression.values(dataBand).contains(gf->data()))){
937 gf->values().push_back(m_popupedValues.value(QString("%1").arg((quintptr)dataBand)+'|'+gf->data()));
938 }
939 }
940 }
941 }
942 }
943
closeGroup(BandDesignIntf * band)944 void ReportRender::closeGroup(BandDesignIntf *band)
945 {
946 QMultiMap< BandDesignIntf*, GroupBandsHolder* >::iterator it;
947 it = m_childBands.find(band);
948
949 while (it!=m_childBands.end()&&it.key()==band){
950 GroupBandsHolder* bl = it.value();
951 if (bl){
952 bl->clear();
953 delete bl;
954 }
955 ++it;
956 }
957
958 m_childBands.remove(band);
959 }
960
openDataGroup(BandDesignIntf * band)961 void ReportRender::openDataGroup(BandDesignIntf *band)
962 {
963 m_childBands.insert(band,new GroupBandsHolder(band->tryToKeepTogether()));
964 }
965
openFooterGroup(BandDesignIntf * band)966 void ReportRender::openFooterGroup(BandDesignIntf *band)
967 {
968 GroupBandsHolder* holder = new GroupBandsHolder(true);
969 holder->setIsFooterGroup();
970 m_childBands.insert(band,holder);
971 }
972
closeDataGroup(BandDesignIntf * band)973 void ReportRender::closeDataGroup(BandDesignIntf *band)
974 {
975 IGroupBand* groupBand = dynamic_cast<IGroupBand*>(band);
976 if (groupBand){
977 groupBand->closeGroup();
978 if (band->reprintOnEachPage()) m_reprintableBands.removeOne(band);
979
980 QList<BandDesignIntf*>::Iterator it = m_reprintableBands.begin();
981 while (it != m_reprintableBands.end()){
982 if ((*it)->bandIndex()>band->bandIndex())
983 it = m_reprintableBands.erase(it);
984 else
985 ++it;
986 }
987 }
988 recalcIfNeeded(band);
989 closeGroup(band);
990 }
991
closeFooterGroup(BandDesignIntf * band)992 void ReportRender::closeFooterGroup(BandDesignIntf *band){
993 closeGroup(band);
994 }
995
maxVectorValue(QVector<qreal> vector)996 qreal maxVectorValue(QVector<qreal> vector){
997 qreal curValue = 0;
998 foreach (qreal value, vector) {
999 if (curValue<value) curValue=value;
1000 }
1001 return curValue;
1002 }
1003
minVectorValue(QVector<qreal> vector)1004 qreal minVectorValue(QVector<qreal> vector){
1005 qreal curValue = vector[0];
1006 foreach (qreal value, vector) {
1007 if (curValue>value) curValue=value;
1008 }
1009 return curValue;
1010 }
1011
placeBandOnPage(BandDesignIntf * band,int columnIndex)1012 void ReportRender::placeBandOnPage(BandDesignIntf* band, int columnIndex){
1013
1014 qreal bandPos = m_currentStartDataPos[columnIndex];
1015
1016 m_currentStartDataPos[columnIndex] += band->height();
1017 m_maxHeightByColumn[columnIndex] -= band->height();
1018 band->setPos(m_renderPageItem->pageRect().x()+band->width()*columnIndex, bandPos);
1019 band->setBandIndex(++m_currentIndex);
1020 band->setColumnIndex(columnIndex);
1021
1022 m_renderPageItem->registerBand(band);
1023 m_currentColumn = columnIndex;
1024 }
1025
isMultiColumnHeader(BandDesignIntf * band)1026 bool isMultiColumnHeader(BandDesignIntf* band){
1027 return ( (band->columnsCount() > 1 ) &&
1028 (band->isHeader() &&
1029 ((band->bandNestingLevel() == 0) || (band->columnsFillDirection() == BandDesignIntf::Horizontal))));
1030 }
1031
registerBand(BandDesignIntf * band,bool registerInChildren)1032 bool ReportRender::registerBand(BandDesignIntf *band, bool registerInChildren)
1033 {
1034
1035 if (band->columnsCount() == 1 && m_maxHeightByColumn.size() > 1 ){
1036 if (band->bandType() != BandDesignIntf::PageFooter){
1037 rearrangeColumnsItems();
1038 m_currentColumn = 0;
1039 qreal minValue = minVectorValue(m_maxHeightByColumn);
1040 m_maxHeightByColumn.clear();
1041 m_maxHeightByColumn.append(minValue);
1042 qreal maxValue = maxVectorValue(m_currentStartDataPos);
1043 m_currentStartDataPos.clear();
1044 m_currentStartDataPos.append(maxValue);
1045 }
1046 }
1047
1048 if (band->columnsCount() != m_maxHeightByColumn.size()){
1049 for(int i=1;i<band->columnsCount();++i){
1050 m_maxHeightByColumn.append(m_maxHeightByColumn[0]);
1051 m_currentStartDataPos.append(m_currentStartDataPos[0]);
1052 }
1053 m_currentColumn = -1;
1054 }
1055
1056 if ( (band->columnsCount() > 1) &&
1057 (!band->isHeader() || (band->bandNestingLevel() > 0 && band->columnsFillDirection() != BandDesignIntf::Horizontal ))){
1058
1059 if (band->columnsFillDirection() == BandDesignIntf::Horizontal){
1060 if (m_currentColumn < band->columnsCount()-1)
1061 m_currentColumn = m_currentColumn+1;
1062 else
1063 m_currentColumn = 0;
1064 } else {
1065 m_currentColumn = m_currentColumn == -1 ? 0: m_currentColumn;
1066 if ((m_currentColumn !=0) &&
1067 (m_maxHeightByColumn[0] == m_maxHeightByColumn[m_currentColumn]) &&
1068 (m_maxHeightByColumn[0] >= band->height())
1069 ){
1070 m_currentColumn = 0;
1071 }
1072 }
1073 }
1074
1075 m_currentColumn = m_currentColumn == -1 ? 0: m_currentColumn;
1076
1077 if ( (band->height() <= m_maxHeightByColumn[m_currentColumn]) ||
1078 m_patternPageItem->endlessHeight() ||
1079 (isMultiColumnHeader(band) && (band->height() <= m_maxHeightByColumn[0]))
1080 ){
1081
1082 if ( (band->bandType() == BandDesignIntf::PageFooter) ){
1083 for (int i=0; i < m_maxHeightByColumn.size(); ++i)
1084 m_maxHeightByColumn[i]+=band->height();
1085 }
1086
1087 if ( isMultiColumnHeader(band)){
1088
1089 if (!band->parent()){
1090 for (int i = 0; i < band->columnsCount(); ++i){
1091 m_currentColumn = i;
1092 if (i != 0) band = dynamic_cast<BandDesignIntf*>(band->cloneItem(PreviewMode));
1093 placeBandOnPage(band, i);
1094 }
1095 } else {
1096 placeBandOnPage(band, band->columnIndex());
1097 }
1098
1099
1100 } else {
1101
1102 if (band->bandType() != BandDesignIntf::PageFooter){
1103 placeBandOnPage(band, m_currentColumn);
1104 }
1105
1106 if (band->columnsCount() > 1){
1107 m_columnedBandItems.append(band);
1108 }
1109
1110 }
1111
1112 foreach(QList<BandDesignIntf*>* list, m_childBands.values()){
1113 if (registerInChildren &&
1114 band->bandType()!=BandDesignIntf::PageHeader &&
1115 band->bandType()!=BandDesignIntf::PageFooter &&
1116 band->bandType()!=BandDesignIntf::ReportHeader &&
1117 band->bandType()!=BandDesignIntf::ReportFooter &&
1118 !list->contains(band) &&
1119 !band->reprintOnEachPage()
1120 )
1121 list->append(band);
1122 }
1123
1124 if (band->isData()) m_renderedDataBandCount++;
1125 band->setObjectName(band->objectName()+QString::number(++m_currentNameIndex));
1126 renameChildItems(band);
1127 if (m_lastDataBand){
1128 #ifdef HAVE_QT4
1129 m_lastDataBand->metaObject()->invokeMethod(m_lastDataBand,"bandRegistred");
1130 #endif
1131 #ifdef HAVE_QT5
1132 emit m_lastDataBand->bandRegistred();
1133 #endif
1134 }
1135 return true;
1136 } else return false;
1137 }
1138
calcSlicePercent(qreal height)1139 qreal ReportRender::calcSlicePercent(qreal height){
1140 return (height*3/(m_dataAreaSize))/100;
1141 }
1142
sliceBand(BandDesignIntf * band,BandDesignIntf * patternBand,bool isLast)1143 BandDesignIntf* ReportRender::sliceBand(BandDesignIntf *band, BandDesignIntf* patternBand, bool isLast)
1144 {
1145 while (band->height()>m_maxHeightByColumn[m_currentColumn]) {
1146 band = saveUppperPartReturnBottom(band,m_maxHeightByColumn[m_currentColumn],patternBand);
1147 if (!band->isEmpty()) {
1148 if (band->autoHeight()){
1149 if (band->isNeedUpdateSize(FirstPass)){
1150 band->setHeight(0);
1151 }
1152 band->updateItemSize(m_datasources);
1153 }
1154 DataBandDesignIntf* data = dynamic_cast<DataBandDesignIntf*>(band);
1155 if (isLast && data && data->keepFooterTogether() &&
1156 band->height()<m_maxHeightByColumn[m_currentColumn] && band->sliceLastRow()
1157 ){
1158 if (band->height()>(m_maxHeightByColumn[m_currentColumn]-m_reportFooterHeight)){
1159 m_maxHeightByColumn[m_currentColumn] -= ((m_maxHeightByColumn[m_currentColumn]-band->height())+(band->height()*calcSlicePercent(band->height())));
1160 }
1161 }
1162 if (registerBand(band)) break;
1163 } else break;
1164 }
1165
1166 if (band->isEmpty()) {
1167 delete band;
1168 band = 0;
1169 }
1170
1171 return band;
1172
1173 }
1174
updateTOC(BaseDesignIntf * item,int pageNumber)1175 void ReportRender::updateTOC(BaseDesignIntf* item, int pageNumber){
1176 BookmarkContainerDesignIntf* bookmarkContainer = dynamic_cast<BookmarkContainerDesignIntf*>(item);
1177 if (bookmarkContainer){
1178 TableOfContents* toc = m_scriptEngineContext->tableOfContents();
1179 foreach (QString key, bookmarkContainer->bookmarks()){
1180 toc->setItem(key, bookmarkContainer->getBookMark(key).toString(), pageNumber);
1181 }
1182 }
1183 }
1184
secondRenderPass(ReportPages renderedPages)1185 void ReportRender::secondRenderPass(ReportPages renderedPages)
1186 {
1187 if (!m_scriptEngineContext->tableOfContents()->isEmpty()){
1188 for(int i = 0; i < renderedPages.count(); ++i){
1189 PageItemDesignIntf::Ptr page = renderedPages.at(i);
1190 updateTOC(page.data(), m_pagesRanges.findPageNumber(i));
1191 foreach(BaseDesignIntf* item, page->childBaseItems()){
1192 updateTOC(item, m_pagesRanges.findPageNumber(i));
1193 }
1194 }
1195 }
1196
1197 for(int i = 0; i < renderedPages.count(); ++i){
1198 PageItemDesignIntf::Ptr page = renderedPages.at(i);
1199 m_datasources->setReportVariable("#PAGE",m_pagesRanges.findPageNumber(i));
1200 m_datasources->setReportVariable("#PAGE_COUNT",m_pagesRanges.findLastPageNumber(i));
1201 foreach(BaseDesignIntf* item, page->childBaseItems()){
1202 if (item->isNeedUpdateSize(SecondPass))
1203 item->updateItemSize(m_datasources, SecondPass);
1204 }
1205 }
1206 }
1207
createTOCMarker(bool startNewRange)1208 void ReportRender::createTOCMarker(bool startNewRange)
1209 {
1210 m_pagesRanges.addTOCMarker(startNewRange);
1211 }
1212
saveUppperPartReturnBottom(BandDesignIntf * band,int height,BandDesignIntf * patternBand)1213 BandDesignIntf *ReportRender::saveUppperPartReturnBottom(BandDesignIntf *band, int height, BandDesignIntf* patternBand)
1214 {
1215 int sliceHeight = height;
1216 BandDesignIntf* upperBandPart = dynamic_cast<BandDesignIntf*>(band->cloneUpperPart(sliceHeight));
1217 BandDesignIntf* bottomBandPart = dynamic_cast<BandDesignIntf*>(band->cloneBottomPart(sliceHeight));
1218 if (!bottomBandPart->isEmpty()){
1219 if (patternBand->keepFooterTogether())
1220 closeFooterGroup(patternBand);
1221 if (upperBandPart->isEmpty())
1222 bottomBandPart->copyBookmarks(band);
1223 }
1224 if (!upperBandPart->isEmpty()){
1225 upperBandPart->updateItemSize(m_datasources, FirstPass, height);
1226 registerBand(upperBandPart);
1227 upperBandPart->copyBookmarks(band);
1228 } else delete upperBandPart;
1229
1230 if (band->columnsCount()>1 &&
1231 (band->columnsFillDirection()==BandDesignIntf::Vertical ||
1232 band->columnsFillDirection()==BandDesignIntf::VerticalUniform)){
1233 startNewColumn();
1234 if (patternBand->bandHeader() &&
1235 patternBand->bandHeader()->columnsCount()>1 &&
1236 !m_lostHeadersMoved &&
1237 patternBand->bandNestingLevel() == 0
1238 ){
1239 renderBand(patternBand->bandHeader(), 0, StartNewPageAsNeeded);
1240 }
1241
1242 } else {
1243 savePage();
1244 startNewPage();
1245 }
1246
1247 delete band;
1248 return bottomBandPart;
1249 }
1250
renderData(BandDesignIntf * patternBand)1251 BandDesignIntf *ReportRender::renderData(BandDesignIntf *patternBand)
1252 {
1253 BandDesignIntf* bandClone = dynamic_cast<BandDesignIntf*>(patternBand->cloneItem(PreviewMode));
1254
1255 m_scriptEngineContext->baseDesignIntfToScript(patternBand->parent()->objectName(), bandClone);
1256 m_scriptEngineContext->setCurrentBand(bandClone);
1257 emit(patternBand->beforeRender());
1258
1259 if (patternBand->isFooter()){
1260 replaceGroupsFunction(bandClone);
1261 }
1262
1263 if (patternBand->isHeader()){
1264 replaceGroupsFunction(bandClone);
1265 }
1266
1267 bandClone->updateItemSize(m_datasources);
1268
1269 //m_scriptEngineContext->baseDesignIntfToScript(bandClone);
1270 emit(patternBand->afterData());
1271
1272 return bandClone;
1273 }
1274
startNewColumn()1275 void ReportRender::startNewColumn(){
1276 if (m_currentColumn < m_maxHeightByColumn.size()-1){
1277 m_currentColumn++;
1278 checkLostHeadersInPrevColumn();
1279 } else {
1280 savePage();
1281 startNewPage();
1282 }
1283 }
1284
startNewPage(bool isFirst)1285 void ReportRender::startNewPage(bool isFirst)
1286 {
1287 m_renderPageItem = 0;
1288 m_newPageStarted = true;
1289 initColumns();
1290 initRenderPage();
1291
1292 m_scriptEngineContext->baseDesignIntfToScript(m_renderPageItem->patternName(), m_renderPageItem);
1293 emit m_patternPageItem->beforeRender();
1294
1295 m_renderPageItem->setObjectName(QLatin1String("ReportPage")+QString::number(m_pageCount));
1296 m_maxHeightByColumn[m_currentColumn] = m_renderPageItem->pageRect().height();
1297 m_currentStartDataPos[m_currentColumn] = m_patternPageItem->topMargin() * Const::mmFACTOR;
1298 m_currentIndex = 0;
1299
1300 if (isFirst) {
1301 renderReportHeader(m_patternPageItem, BeforePageHeader);
1302 emit m_patternPageItem->beforeFirstPageRendered();
1303 }
1304
1305 renderPageHeader(m_patternPageItem);
1306
1307 m_pageFooterHeight = calcPageFooterHeight(m_patternPageItem)+2;
1308 m_maxHeightByColumn[m_currentColumn] -= m_pageFooterHeight;
1309 m_currentIndex = 10;
1310 m_dataAreaSize = m_maxHeightByColumn[m_currentColumn];
1311 m_renderedDataBandCount = 0;
1312
1313 foreach (BandDesignIntf* band, m_reprintableBands) {
1314 renderBand(band, 0);
1315 }
1316
1317 checkLostHeadersOnPrevPage();
1318 pasteGroups();
1319
1320 }
1321
resetPageNumber(ResetPageNuberType resetType)1322 void ReportRender::resetPageNumber(ResetPageNuberType resetType)
1323 {
1324 m_pagesRanges.startNewRange();
1325 if (resetType == PageReset)
1326 m_datasources->setReportVariable("#PAGE",1);
1327 }
1328
cutGroups()1329 void ReportRender::cutGroups()
1330 {
1331 m_popupedExpression.clear();
1332 m_popupedValues.clear();
1333 foreach(BandDesignIntf* groupBand,m_childBands.keys()){
1334 if (m_childBands.value(groupBand)->tryToKeepTogether()){
1335 foreach(BandDesignIntf* band, *m_childBands.value(groupBand)){
1336 m_renderPageItem->removeBand(band);
1337 popPageFooterGroupValues(band);
1338 band->setParent(0);
1339 band->setParentItem(0);
1340 }
1341 }
1342 }
1343
1344 }
1345
checkFooterGroup(BandDesignIntf * groupBand)1346 void ReportRender::checkFooterGroup(BandDesignIntf *groupBand)
1347 {
1348 if (m_childBands.contains(groupBand)){
1349 GroupBandsHolder* holder = m_childBands.value(groupBand);
1350 foreach(BandDesignIntf* band, *holder){
1351 qreal percent = band->height()*100 / m_dataAreaSize;
1352 if (m_renderedDataBandCount<=1 || percent>20 ){
1353 holder->removeAll(band);
1354 }
1355 }
1356 }
1357 }
1358
pasteGroups()1359 void ReportRender::pasteGroups()
1360 {
1361 BandDesignIntf* groupBand = findEnclosingGroup();
1362 if (groupBand){
1363 foreach(BandDesignIntf* band, *m_childBands.value(groupBand)){
1364 registerBand(band,false);
1365 if (band->isData()) m_renderedDataBandCount++;
1366 pushPageFooterGroupValues(band);
1367 }
1368 foreach(GroupBandsHolder* holder, m_childBands.values())
1369 holder->setTryToKeepTogether(false);
1370 }
1371 m_popupedExpression.clear();
1372 m_popupedValues.clear();
1373 }
1374
bandLessThen(BandDesignIntf * b1,BandDesignIntf * b2)1375 bool bandLessThen(BandDesignIntf* b1, BandDesignIntf* b2){
1376 return b1->bandIndex() < b2->bandIndex();
1377 }
1378
checkLostHeadersOnPrevPage()1379 void ReportRender::checkLostHeadersOnPrevPage()
1380 {
1381 QVector<BandDesignIntf*> lostHeaders;
1382
1383 if (m_renderedPages.isEmpty()) return;
1384 PageItemDesignIntf::Ptr page = m_renderedPages.last();
1385 if (page->bands().isEmpty()) return;
1386
1387 QMutableListIterator<BandDesignIntf*>it(page->bands());
1388
1389 it.toBack();
1390 if (it.hasPrevious()){
1391 if (it.previous()->isFooter()){
1392 if (it.hasPrevious()) it.previous();
1393 else return;
1394 }
1395 }
1396
1397 while (it.hasPrevious()){
1398 if (it.value()->isHeader()){
1399 if (it.value()->reprintOnEachPage()){
1400 delete it.value();
1401 } else { lostHeaders.append(it.value());}
1402 it.remove();
1403 it.previous();
1404 } else break;
1405 }
1406
1407 if (lostHeaders.size() > 0){
1408 m_lostHeadersMoved = true;
1409 qSort(lostHeaders.begin(), lostHeaders.end(), bandLessThen);
1410 foreach(BandDesignIntf* header, lostHeaders){
1411 registerBand(header);
1412 }
1413 } else {
1414 m_lostHeadersMoved = false;
1415 }
1416
1417
1418 }
1419
checkLostHeadersInPrevColumn()1420 void ReportRender::checkLostHeadersInPrevColumn()
1421 {
1422 QVector<BandDesignIntf*> lostHeaders;
1423
1424 QMutableListIterator<BandDesignIntf*>it(m_renderPageItem->bands());
1425
1426 it.toBack();
1427 if (it.hasPrevious()){
1428 if (it.previous()->isFooter()){
1429 if (it.hasPrevious()) it.previous();
1430 else return;
1431 }
1432 }
1433
1434 while (it.hasPrevious()){
1435 if (it.value()->isHeader()){
1436 if (it.value()->reprintOnEachPage()){
1437 delete it.value();
1438 } else { lostHeaders.append(it.value());}
1439 it.remove();
1440 it.previous();
1441 } else break;
1442 }
1443
1444 if (lostHeaders.size() > 0){
1445 m_lostHeadersMoved = true;
1446 qSort(lostHeaders.begin(), lostHeaders.end(), bandLessThen);
1447 foreach(BandDesignIntf* header, lostHeaders){
1448 registerBand(header);
1449 }
1450 } else {
1451 m_lostHeadersMoved = false;
1452 }
1453 }
1454
findEnclosingGroup()1455 BandDesignIntf* ReportRender::findEnclosingGroup()
1456 {
1457 BandDesignIntf* result=0;
1458 int groupIndex = -1;
1459 if (!m_childBands.isEmpty()){
1460 foreach(BandDesignIntf* gb, m_childBands.keys()){
1461 if (m_childBands.value(gb)->tryToKeepTogether()&&
1462 ((gb->bandIndex()<groupIndex)||(groupIndex==-1))
1463 ){
1464 result=gb;
1465 groupIndex=result->bandIndex();
1466 }
1467 }
1468 }
1469 return result;
1470 }
1471
savePage(bool isLast)1472 void ReportRender::savePage(bool isLast)
1473 {
1474 if (m_renderPageItem->isTOC())
1475 m_pagesRanges.addTOCPage();
1476 else
1477 m_pagesRanges.addPage();
1478
1479 m_datasources->setReportVariable("#IS_LAST_PAGEFOOTER",isLast);
1480 m_datasources->setReportVariable("#IS_FIRST_PAGEFOOTER",m_datasources->variable("#PAGE").toInt()==1);
1481
1482 renderPageItems(m_patternPageItem);
1483 checkFooterGroup(m_lastDataBand);
1484 cutGroups();
1485 rearrangeColumnsItems();
1486 m_columnedBandItems.clear();
1487
1488 BandDesignIntf* pf = m_patternPageItem->bandByType(BandDesignIntf::PageFooter);
1489 if (pf && m_datasources->variable("#PAGE").toInt()!=1 && !isLast){
1490 renderPageFooter(m_patternPageItem);
1491 } else {
1492 if (pf && pf->property("printOnFirstPage").toBool() && m_datasources->variable("#PAGE").toInt()==1){
1493 renderPageFooter(m_patternPageItem);
1494 } else if(pf && pf->property("printOnLastPage").toBool() && isLast){
1495 renderPageFooter(m_patternPageItem);
1496 }
1497 }
1498
1499 if (m_pagesRanges.currentRange(m_patternPageItem->isTOC()).firstPage == 0) {
1500 m_datasources->setReportVariable("#PAGE",1);
1501 } else {
1502 m_datasources->setReportVariable("#PAGE",m_datasources->variable("#PAGE").toInt()+1);
1503 }
1504
1505 BandDesignIntf* pageFooter = m_renderPageItem->bandByType(BandDesignIntf::PageFooter);
1506 if (pageFooter) pageFooter->setBandIndex(++m_currentIndex);
1507 m_renderedPages.append(PageItemDesignIntf::Ptr(m_renderPageItem));
1508 m_pageCount++;
1509 emit pageRendered(m_pageCount);
1510
1511 if (isLast){
1512 BandDesignIntf* ph = m_renderPageItem->bandByType(BandDesignIntf::PageHeader);
1513 if (ph && !ph->property("printOnLastPage").toBool()){
1514 delete ph;
1515 }
1516 }
1517
1518 m_renderPageItem->placeTearOffBand();
1519 m_scriptEngineContext->setCurrentPage(m_renderPageItem);
1520 emit m_patternPageItem->afterRender();
1521 if (isLast)
1522 emit m_patternPageItem->afterLastPageRendered();
1523 if (isLast && m_patternPageItem->endlessHeight()){
1524 qreal pageHeight = 0;
1525 foreach (BandDesignIntf* band, m_renderPageItem->bands()) {
1526 pageHeight += band->height();
1527 }
1528 m_renderPageItem->setHeight(pageHeight + 10 +
1529 (m_patternPageItem->topMargin() + m_patternPageItem->bottomMargin()) * Const::mmFACTOR);
1530 }
1531 }
1532
toString()1533 QString ReportRender::toString()
1534 {
1535 QScopedPointer<ItemsWriterIntf> writer(new XMLWriter());
1536 foreach(PageItemDesignIntf::Ptr page,m_renderedPages){
1537 writer->putItem(page.data());
1538 }
1539 return writer->saveToString();
1540 }
1541
~ReportRender()1542 ReportRender::~ReportRender(){
1543 m_renderedPages.clear();
1544 }
1545
cancelRender()1546 void ReportRender::cancelRender(){
1547 m_renderCanceled = true;
1548 }
1549
findLastPageNumber(int index)1550 int PagesRanges::findLastPageNumber(int index)
1551 {
1552 index++;
1553 foreach (PagesRange range, m_ranges) {
1554 if ( range.firstPage <= (index) && range.lastPage>= (index) )
1555 return (range.lastPage-(range.firstPage))+1;
1556 }
1557 return 0;
1558 }
1559
findPageNumber(int index)1560 int PagesRanges::findPageNumber(int index)
1561 {
1562 index++;
1563 foreach (PagesRange range, m_ranges) {
1564 if ( range.firstPage <= (index) && range.lastPage >= (index) )
1565 return (index - range.firstPage)+1;
1566 }
1567 return 0;
1568 }
1569
currentRange(bool isTOC)1570 PagesRange&PagesRanges::currentRange(bool isTOC)
1571 {
1572 Q_ASSERT( (isTOC && m_TOCRangeIndex!=-1) || !isTOC);
1573 if (isTOC && m_TOCRangeIndex !=-1) return m_ranges[m_TOCRangeIndex];
1574 return m_ranges.last();
1575 }
1576
startNewRange(bool isTOC)1577 void PagesRanges::startNewRange(bool isTOC)
1578 {
1579 PagesRange range;
1580 if (!m_ranges.isEmpty()){
1581 range.firstPage = 0;
1582 range.lastPage = m_ranges.last().lastPage + 1;
1583 } else {
1584 range.firstPage = 0;
1585 range.lastPage = 0;
1586 }
1587 range.isTOC = isTOC;
1588 m_ranges.append(range);
1589 if (isTOC) m_TOCRangeIndex = m_ranges.size()-1;
1590 }
1591
addTOCMarker(bool addNewRange)1592 void PagesRanges::addTOCMarker(bool addNewRange)
1593 {
1594 if ( addNewRange || m_ranges.isEmpty()){
1595 startNewRange(true);
1596 } else {
1597 m_TOCRangeIndex = m_ranges.size()-1;
1598 m_ranges.last().isTOC = true;
1599 }
1600 }
1601
addPage()1602 void PagesRanges::addPage()
1603 {
1604 if (m_ranges.isEmpty()) startNewRange();
1605 if (m_ranges.last().firstPage == 0){
1606 m_ranges.last().firstPage = m_ranges.last().lastPage == 0 ? 1 : m_ranges.last().lastPage;
1607 m_ranges.last().lastPage = m_ranges.last().lastPage == 0 ? 1 : m_ranges.last().lastPage;
1608 } else {
1609 m_ranges.last().lastPage++;
1610 }
1611 }
1612
shiftRangesNextToTOC()1613 void PagesRanges::shiftRangesNextToTOC(){
1614 for(int i = m_TOCRangeIndex+1; i < m_ranges.size(); ++i){
1615 m_ranges[i].firstPage++;
1616 m_ranges[i].lastPage++;
1617 }
1618 }
1619
addTOCPage()1620 void PagesRanges::addTOCPage()
1621 {
1622 Q_ASSERT(m_TOCRangeIndex != -1);
1623 if (m_TOCRangeIndex != -1){
1624 PagesRange& tocRange = m_ranges[m_TOCRangeIndex];
1625 if (tocRange.firstPage == 0) {
1626 tocRange.firstPage = tocRange.lastPage == 0 ? 1 : tocRange.lastPage;
1627 tocRange.lastPage = tocRange.lastPage == 0 ? 1 : tocRange.lastPage;
1628 if (tocRange.firstPage == 1 && tocRange.lastPage == 1)
1629 shiftRangesNextToTOC();
1630 } else {
1631 tocRange.lastPage++;
1632 shiftRangesNextToTOC();
1633 }
1634 }
1635 }
1636
clear()1637 void PagesRanges::clear()
1638 {
1639 m_ranges.clear();
1640 }
1641
1642 } // namespace LimeReport
1643