mirror of
https://github.com/fralx/LimeReport.git
synced 2024-12-23 16:22:58 +03:00
0fca7169d3
except those placed in 3rdparty directories.
1895 lines
68 KiB
C++
1895 lines
68 KiB
C++
/***************************************************************************
|
|
* This file is part of the Lime Report project *
|
|
* Copyright (C) 2021 by Alexander Arin *
|
|
* arin_a@bk.ru *
|
|
* *
|
|
** GNU General Public License Usage **
|
|
* *
|
|
* This library is free software: you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation, either version 3 of the License, or *
|
|
* (at your option) any later version. *
|
|
* You should have received a copy of the GNU General Public License *
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
|
* *
|
|
** GNU Lesser General Public License **
|
|
* *
|
|
* 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 3 of the *
|
|
* License, or (at your option) any later version. *
|
|
* You should have received a copy of the GNU Lesser General Public *
|
|
* License along with this library. *
|
|
* If not, see <http://www.gnu.org/licenses/>. *
|
|
* *
|
|
* 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 General Public License for more details. *
|
|
****************************************************************************/
|
|
#include "lrreportrender.h"
|
|
|
|
#include "lrbanddesignintf.h"
|
|
#include "lrglobal.h"
|
|
#include "lritemdesignintf.h"
|
|
#include "lrpagedesignintf.h"
|
|
#include "lrscriptenginemanager.h"
|
|
#include "serializators/lrxmlreader.h"
|
|
#include "serializators/lrxmlwriter.h"
|
|
|
|
#include <QMessageBox>
|
|
|
|
#include <stdexcept>
|
|
|
|
namespace LimeReport {
|
|
|
|
void ReportRender::initColumns()
|
|
{
|
|
m_maxHeightByColumn.clear();
|
|
m_currentStartDataPos.clear();
|
|
m_maxHeightByColumn.append(0);
|
|
m_currentStartDataPos.append(0);
|
|
m_currentColumn = 0;
|
|
}
|
|
|
|
bool ReportRender::isNeedToRearrangeColumnsItems()
|
|
{
|
|
if (m_columnedBandItems.size() <= 1)
|
|
return false;
|
|
if (m_columnedBandItems[0]->columnsFillDirection() != BandDesignIntf::VerticalUniform)
|
|
return false;
|
|
|
|
int avg = m_columnedBandItems.size() / m_columnedBandItems[0]->columnsCount();
|
|
|
|
for (int i = 0; i < m_maxHeightByColumn.size(); ++i) {
|
|
qreal maxHeight = 0;
|
|
int maxHeightColumn = 0;
|
|
if (m_maxHeightByColumn[i] > maxHeight) {
|
|
maxHeight = m_maxHeightByColumn[i];
|
|
maxHeightColumn = i;
|
|
}
|
|
if (maxHeightColumn > 0 && columnItemsCount(maxHeightColumn) < avg
|
|
&& maxHeight > lastColumnItem(maxHeightColumn - 1)->height()) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
BandDesignIntf* ReportRender::lastColumnItem(int columnIndex)
|
|
{
|
|
if (columnIndex < 0)
|
|
return 0;
|
|
for (int i = 0; i < m_columnedBandItems.size(); ++i) {
|
|
if (m_columnedBandItems[i]->columnIndex() > columnIndex)
|
|
return m_columnedBandItems[i - 1];
|
|
}
|
|
return m_columnedBandItems.last();
|
|
}
|
|
|
|
void ReportRender::rearrangeColumnsItems()
|
|
{
|
|
if (isNeedToRearrangeColumnsItems()) {
|
|
qreal startHeight = columnHeigth(0);
|
|
int avg = m_columnedBandItems.size() / m_columnedBandItems[0]->columnsCount();
|
|
for (int i = 1; i < m_columnedBandItems[0]->columnsCount(); ++i) {
|
|
if (columnItemsCount(i) < avg) {
|
|
int getCount
|
|
= avg * (m_columnedBandItems[0]->columnsCount() - i) - columnItemsCount(i);
|
|
for (int j = 0; j < getCount; ++j) {
|
|
BandDesignIntf* band = lastColumnItem(i - 1);
|
|
band->setPos(band->pos().x() + band->width(),
|
|
m_columnedBandItems[0]->pos().y());
|
|
band->setColumnIndex(i);
|
|
}
|
|
}
|
|
}
|
|
m_renderPageItem->relocateBands();
|
|
m_maxHeightByColumn[0] += startHeight - maxColumnHeight();
|
|
m_currentStartDataPos[0] -= startHeight - maxColumnHeight();
|
|
m_columnedBandItems.clear();
|
|
}
|
|
}
|
|
|
|
int ReportRender::columnItemsCount(int columnIndex)
|
|
{
|
|
int result = 0;
|
|
foreach (BandDesignIntf* band, m_columnedBandItems) {
|
|
if (band->columnIndex() == columnIndex)
|
|
++result;
|
|
if (band->columnIndex() > columnIndex)
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
qreal ReportRender::columnHeigth(int columnIndex)
|
|
{
|
|
qreal result = 0;
|
|
for (int i = 0; i < m_columnedBandItems.size(); ++i) {
|
|
if (m_columnedBandItems[i]->columnIndex() == columnIndex)
|
|
result += m_columnedBandItems[i]->height();
|
|
if (m_columnedBandItems[i]->columnIndex() > columnIndex)
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
qreal ReportRender::maxColumnHeight()
|
|
{
|
|
qreal result = 0;
|
|
for (int i = 0; i < m_columnedBandItems[0]->columnsCount(); ++i) {
|
|
qreal curColumnHeight = columnHeigth(i);
|
|
if (curColumnHeight > result)
|
|
result = curColumnHeight;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void ReportRender::renameChildItems(BaseDesignIntf* item)
|
|
{
|
|
foreach (BaseDesignIntf* child, item->childBaseItems()) {
|
|
if (!child->childBaseItems().isEmpty())
|
|
renameChildItems(child);
|
|
child->setObjectName(child->metaObject()->className()
|
|
+ QString::number(++m_currentNameIndex));
|
|
}
|
|
}
|
|
|
|
ReportRender::ReportRender(QObject* parent):
|
|
QObject(parent),
|
|
m_renderPageItem(0),
|
|
m_pageCount(0),
|
|
m_lastRenderedHeader(0),
|
|
m_lastDataBand(0),
|
|
m_lastRenderedFooter(0),
|
|
m_lastRenderedBand(0),
|
|
m_currentColumn(0),
|
|
m_newPageStarted(false),
|
|
m_lostHeadersMoved(false)
|
|
{
|
|
initColumns();
|
|
}
|
|
|
|
void ReportRender::setDatasources(DataSourceManager* value)
|
|
{
|
|
m_datasources = value;
|
|
initVariables();
|
|
resetPageNumber(BandReset);
|
|
}
|
|
|
|
void ReportRender::setScriptContext(ScriptEngineContext* scriptContext)
|
|
{
|
|
m_scriptEngineContext = scriptContext;
|
|
}
|
|
|
|
void ReportRender::initDatasources()
|
|
{
|
|
try {
|
|
datasources()->setAllDatasourcesToFirst();
|
|
} catch (ReportError& exception) {
|
|
// TODO possible should thow exeption
|
|
QMessageBox::critical(0, tr("Error"), exception.what());
|
|
return;
|
|
}
|
|
}
|
|
|
|
void ReportRender::initDatasource(const QString& name)
|
|
{
|
|
try {
|
|
if (datasources()->containsDatasource(name)) {
|
|
IDataSource* ds = datasources()->dataSource(name);
|
|
if (ds)
|
|
ds->first();
|
|
}
|
|
} catch (ReportError& exception) {
|
|
QMessageBox::critical(0, tr("Error"), exception.what());
|
|
return;
|
|
}
|
|
}
|
|
|
|
void ReportRender::analizeItem(ContentItemDesignIntf* contentItem, BandDesignIntf* band)
|
|
{
|
|
Q_UNUSED(band)
|
|
if (contentItem) {
|
|
QString content = contentItem->content();
|
|
QVector<QString> functions;
|
|
foreach (const QString& functionName, m_datasources->groupFunctionNames()) {
|
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 1)
|
|
QRegularExpression rx = getGroupFunctionRegEx(functionName);
|
|
if (content.indexOf(rx) >= 0) {
|
|
functions.append(functionName);
|
|
}
|
|
#else
|
|
QRegExp rx(QString(Const::GROUP_FUNCTION_RX).arg(functionName));
|
|
rx.setMinimal(true);
|
|
if (rx.indexIn(content) >= 0) {
|
|
functions.append(functionName);
|
|
}
|
|
#endif
|
|
}
|
|
if (functions.size() > 0)
|
|
m_groupfunctionItems.insert(contentItem->patternName(), functions);
|
|
}
|
|
}
|
|
|
|
void ReportRender::analizeContainer(BaseDesignIntf* item, BandDesignIntf* band)
|
|
{
|
|
if (item) {
|
|
foreach (BaseDesignIntf* child, item->childBaseItems()) {
|
|
ContentItemDesignIntf* contentItem = dynamic_cast<ContentItemDesignIntf*>(child);
|
|
if (contentItem)
|
|
analizeItem(contentItem, band);
|
|
else
|
|
analizeContainer(child, band);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ReportRender::analizePage(PageItemDesignIntf* patternPage)
|
|
{
|
|
m_groupfunctionItems.clear();
|
|
foreach (BandDesignIntf* band, patternPage->bands()) {
|
|
if (band->isFooter() || band->isHeader()) {
|
|
analizeContainer(band, band);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ReportRender::renderPage(PageItemDesignIntf* patternPage, bool isTOC, bool /*isFirst*/,
|
|
bool /*resetPageNumbers*/)
|
|
{
|
|
m_currentNameIndex = 0;
|
|
m_patternPageItem = patternPage;
|
|
|
|
analizePage(patternPage);
|
|
|
|
if (m_patternPageItem->resetPageNumber() && m_pageCount > 0 && !isTOC) {
|
|
resetPageNumber(PageReset);
|
|
}
|
|
|
|
if (m_patternPageItem->resetPageNumber() && !isTOC && m_pageCount == 0) {
|
|
m_pagesRanges.startNewRange();
|
|
}
|
|
|
|
m_renderCanceled = false;
|
|
BandDesignIntf* reportFooter = m_patternPageItem->bandByType(BandDesignIntf::ReportFooter);
|
|
m_reportFooterHeight = 0;
|
|
if (reportFooter)
|
|
m_reportFooterHeight = reportFooter->height();
|
|
|
|
initGroups();
|
|
clearPageMap();
|
|
|
|
try {
|
|
datasources()->setAllDatasourcesToFirst();
|
|
datasources()->clearGroupFuntionsExpressions();
|
|
} catch (ReportError& exception) {
|
|
// TODO possible should thow exeption
|
|
QMessageBox::critical(0, tr("Error"), exception.what());
|
|
return;
|
|
}
|
|
|
|
clearPageMap();
|
|
startNewPage(true);
|
|
|
|
renderReportHeader(m_patternPageItem, AfterPageHeader);
|
|
|
|
BandDesignIntf* lastRenderedBand = 0;
|
|
for (int i = 0; i < m_patternPageItem->dataBandCount() && !m_renderCanceled; i++) {
|
|
lastRenderedBand = m_patternPageItem->dataBandAt(i);
|
|
initDatasource(lastRenderedBand->datasourceName());
|
|
renderDataBand(lastRenderedBand);
|
|
if (i < m_patternPageItem->dataBandCount() - 1)
|
|
closeFooterGroup(lastRenderedBand);
|
|
}
|
|
|
|
if (reportFooter)
|
|
renderBand(reportFooter, 0, StartNewPageAsNeeded);
|
|
if (lastRenderedBand && lastRenderedBand->keepFooterTogether())
|
|
closeFooterGroup(lastRenderedBand);
|
|
|
|
BandDesignIntf* tearOffBand = m_patternPageItem->bandByType(BandDesignIntf::TearOffBand);
|
|
if (tearOffBand)
|
|
renderBand(tearOffBand, 0, StartNewPageAsNeeded);
|
|
|
|
savePage(true);
|
|
}
|
|
|
|
int ReportRender::pageCount() { return m_renderedPages.count(); }
|
|
|
|
PageItemDesignIntf::Ptr ReportRender::pageAt(int index)
|
|
{
|
|
if ((index > m_renderedPages.count() - 1) || (index < 0))
|
|
throw ReportError(tr("page index out of range"));
|
|
else
|
|
return m_renderedPages.at(index);
|
|
}
|
|
|
|
QString ReportRender::renderPageToString(PageItemDesignIntf* patternPage)
|
|
{
|
|
renderPage(patternPage);
|
|
return toString();
|
|
}
|
|
|
|
ReportPages ReportRender::renderPageToPages(PageItemDesignIntf* patternPage)
|
|
{
|
|
renderPage(patternPage);
|
|
return m_renderedPages;
|
|
}
|
|
|
|
ReportPages ReportRender::renderTOC(PageItemDesignIntf* patternPage, bool first, bool resetPages)
|
|
{
|
|
renderPage(patternPage, true, first, resetPages);
|
|
return m_renderedPages;
|
|
}
|
|
|
|
void ReportRender::initRenderPage()
|
|
{
|
|
if (!m_renderPageItem) {
|
|
m_renderPageItem
|
|
= new PageItemDesignIntf(m_patternPageItem->pageSize(), m_patternPageItem->pageRect());
|
|
m_renderPageItem->initFromItem(m_patternPageItem);
|
|
m_renderPageItem->setItemMode(PreviewMode);
|
|
m_renderPageItem->setPatternName(m_patternPageItem->objectName());
|
|
m_renderPageItem->setPatternItem(m_patternPageItem);
|
|
|
|
ScriptValueType svCurrentPage;
|
|
ScriptEngineType* se = ScriptEngineManager::instance().scriptEngine();
|
|
|
|
#ifdef USE_QJSENGINE
|
|
svCurrentPage = getJSValue(*se, m_renderPageItem);
|
|
se->globalObject().setProperty("currentPage", svCurrentPage);
|
|
#else
|
|
svCurrentPage = se->globalObject().property("currentPage");
|
|
if (svCurrentPage.isValid()) {
|
|
se->newQObject(svCurrentPage, m_renderPageItem);
|
|
} else {
|
|
svCurrentPage = se->newQObject(m_renderPageItem);
|
|
se->globalObject().setProperty("currentPage", svCurrentPage);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void ReportRender::initVariables()
|
|
{
|
|
m_datasources->setReportVariable("#PAGE", 1);
|
|
m_datasources->setReportVariable("#PAGE_COUNT", 0);
|
|
m_datasources->setReportVariable("#IS_LAST_PAGEFOOTER", false);
|
|
m_datasources->setReportVariable("#IS_FIRST_PAGEFOOTER", false);
|
|
}
|
|
|
|
void ReportRender::clearPageMap() { m_renderedPages.clear(); }
|
|
|
|
bool checkContentItem(ContentItemDesignIntf* item, DataSourceManager* datasources)
|
|
{
|
|
QString content = item->content();
|
|
foreach (QString functionName, datasources->groupFunctionNames()) {
|
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 1)
|
|
QRegularExpression rx = getGroupFunctionRegEx(functionName);
|
|
if (content.indexOf(rx) >= 0) {
|
|
return true;
|
|
}
|
|
#else
|
|
QRegExp rx(QString(Const::GROUP_FUNCTION_RX).arg(functionName));
|
|
if (rx.indexIn(content) >= 0) {
|
|
return true;
|
|
}
|
|
#endif
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool ReportRender::containsGroupFunctions(BaseDesignIntf* container)
|
|
{
|
|
if (container) {
|
|
foreach (BaseDesignIntf* item, container->childBaseItems()) {
|
|
ContentItemDesignIntf* contentItem = dynamic_cast<ContentItemDesignIntf*>(item);
|
|
if (contentItem) {
|
|
if (checkContentItem(contentItem, m_datasources))
|
|
return true;
|
|
} else {
|
|
if (containsGroupFunctions(item))
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void ReportRender::extractGroupFuntionsFromItem(ContentItemDesignIntf* contentItem,
|
|
BandDesignIntf* band)
|
|
{
|
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 1)
|
|
if (contentItem && contentItem->content().contains(getScriptRegEx())) {
|
|
foreach (const QString& functionName, m_datasources->groupFunctionNames()) {
|
|
|
|
QRegularExpression rx = getGroupFunctionRegEx(functionName);
|
|
QRegularExpression rxName = getGroupFunctionNameRegEx(functionName);
|
|
QRegularExpressionMatch match = rx.match(contentItem->content());
|
|
|
|
if (match.hasMatch()) {
|
|
|
|
QRegularExpressionMatchIterator iter = rx.globalMatch(contentItem->content());
|
|
while (iter.hasNext()) {
|
|
match = iter.next();
|
|
QVector<QString> captures = normalizeCaptures(match);
|
|
if (captures.size() >= 3) {
|
|
int dsIndex = captures.size() == 3 ? Const::DATASOURCE_INDEX - 1
|
|
: Const::DATASOURCE_INDEX;
|
|
BandDesignIntf* dataBand
|
|
= m_patternPageItem->bandByName(captures.at(dsIndex));
|
|
if (dataBand) {
|
|
GroupFunction* gf = datasources()->addGroupFunction(
|
|
functionName, captures.at(Const::VALUE_INDEX), band->objectName(),
|
|
dataBand->objectName());
|
|
if (gf) {
|
|
connect(dataBand, SIGNAL(bandRendered(BandDesignIntf*)), gf,
|
|
SLOT(slotBandRendered(BandDesignIntf*)));
|
|
connect(dataBand,
|
|
SIGNAL(bandReRendered(BandDesignIntf*, BandDesignIntf*)),
|
|
gf,
|
|
SLOT(slotBandReRendered(BandDesignIntf*, BandDesignIntf*)));
|
|
}
|
|
} else {
|
|
GroupFunction* gf = datasources()->addGroupFunction(
|
|
functionName, captures.at(Const::VALUE_INDEX), band->objectName(),
|
|
captures.at(dsIndex));
|
|
gf->setInvalid(
|
|
tr("Databand \"%1\" not found").arg(captures.at(dsIndex)));
|
|
}
|
|
}
|
|
}
|
|
|
|
} else if (contentItem->content().indexOf(rxName) >= 0) {
|
|
match = rxName.match(contentItem->content());
|
|
GroupFunction* gf = datasources()->addGroupFunction(functionName, match.captured(1),
|
|
band->objectName(), "");
|
|
gf->setInvalid(tr("Wrong using function %1").arg(functionName));
|
|
}
|
|
}
|
|
}
|
|
|
|
#else
|
|
if (contentItem && contentItem->content().contains(QRegExp("\\$S\\s*\\{.*\\}"))) {
|
|
foreach (const QString& functionName, m_datasources->groupFunctionNames()) {
|
|
QRegExp rx(QString(Const::GROUP_FUNCTION_RX).arg(functionName));
|
|
rx.setMinimal(true);
|
|
QRegExp rxName(QString(Const::GROUP_FUNCTION_NAME_RX).arg(functionName));
|
|
rxName.setMinimal(true);
|
|
if (rx.indexIn(contentItem->content()) >= 0) {
|
|
int pos = 0;
|
|
while ((pos = rx.indexIn(contentItem->content(), pos)) != -1) {
|
|
QVector<QString> captures = normalizeCaptures(rx);
|
|
if (captures.size() >= 3) {
|
|
int dsIndex = captures.size() == 3 ? Const::DATASOURCE_INDEX - 1
|
|
: Const::DATASOURCE_INDEX;
|
|
BandDesignIntf* dataBand
|
|
= m_patternPageItem->bandByName(captures.at(dsIndex));
|
|
if (dataBand) {
|
|
GroupFunction* gf = datasources()->addGroupFunction(
|
|
functionName, captures.at(Const::VALUE_INDEX), band->objectName(),
|
|
dataBand->objectName());
|
|
if (gf) {
|
|
connect(dataBand, SIGNAL(bandRendered(BandDesignIntf*)), gf,
|
|
SLOT(slotBandRendered(BandDesignIntf*)));
|
|
connect(dataBand,
|
|
SIGNAL(bandReRendered(BandDesignIntf*, BandDesignIntf*)),
|
|
gf,
|
|
SLOT(slotBandReRendered(BandDesignIntf*, BandDesignIntf*)));
|
|
}
|
|
} else {
|
|
GroupFunction* gf = datasources()->addGroupFunction(
|
|
functionName, captures.at(Const::VALUE_INDEX), band->objectName(),
|
|
captures.at(dsIndex));
|
|
gf->setInvalid(
|
|
tr("Databand \"%1\" not found").arg(captures.at(dsIndex)));
|
|
}
|
|
}
|
|
pos += rx.matchedLength();
|
|
}
|
|
} else if (rxName.indexIn(contentItem->content()) >= 0) {
|
|
GroupFunction* gf = datasources()->addGroupFunction(functionName, rxName.cap(1),
|
|
band->objectName(), "");
|
|
gf->setInvalid(tr("Wrong using function %1").arg(functionName));
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void ReportRender::extractGroupFunctionsFromContainer(BaseDesignIntf* baseItem,
|
|
BandDesignIntf* band)
|
|
{
|
|
if (baseItem) {
|
|
foreach (BaseDesignIntf* item, baseItem->childBaseItems()) {
|
|
ContentItemDesignIntf* contentItem = dynamic_cast<ContentItemDesignIntf*>(item);
|
|
if (contentItem)
|
|
extractGroupFuntionsFromItem(contentItem, band);
|
|
else
|
|
extractGroupFunctionsFromContainer(item, band);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ReportRender::extractGroupFunctions(BandDesignIntf* band)
|
|
{
|
|
extractGroupFunctionsFromContainer(band, band);
|
|
}
|
|
|
|
void ReportRender::replaceGroupFunctionsInItem(ContentItemDesignIntf* contentItem,
|
|
BandDesignIntf* band)
|
|
{
|
|
if (contentItem) {
|
|
if (m_groupfunctionItems.contains(contentItem->patternName())) {
|
|
QString content = contentItem->content();
|
|
foreach (QString functionName, m_groupfunctionItems.value(contentItem->patternName())) {
|
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 1)
|
|
QRegularExpression rx = getGroupFunctionRegEx(functionName);
|
|
QRegularExpressionMatch match = rx.match(content);
|
|
|
|
if (match.capturedStart() != -1) {
|
|
int pos = 0;
|
|
while ((pos = match.capturedStart()) != -1) {
|
|
QVector<QString> captures = normalizeCaptures(match);
|
|
if (captures.size() >= 3) {
|
|
QString expressionIndex = datasources()->putGroupFunctionsExpressions(
|
|
captures.at(Const::VALUE_INDEX));
|
|
if (captures.size() < 5) {
|
|
content.replace(captures.at(0),
|
|
QString("%1(%2,%3)")
|
|
.arg(functionName)
|
|
.arg('"' + expressionIndex + '"')
|
|
.arg('"' + band->objectName() + '"'));
|
|
} else {
|
|
content.replace(captures.at(0),
|
|
QString("%1(%2,%3,%4)")
|
|
.arg(functionName, '"' + expressionIndex + '"',
|
|
'"' + band->objectName() + '"',
|
|
captures.at(4)));
|
|
}
|
|
}
|
|
match = rx.match(content, pos + match.capturedLength());
|
|
}
|
|
}
|
|
#else
|
|
QRegExp rx(QString(Const::GROUP_FUNCTION_RX).arg(functionName));
|
|
rx.setMinimal(true);
|
|
if (rx.indexIn(content) >= 0) {
|
|
int pos = 0;
|
|
while ((pos = rx.indexIn(content, pos)) != -1) {
|
|
QVector<QString> captures = normalizeCaptures(rx);
|
|
if (captures.size() >= 3) {
|
|
QString expressionIndex = datasources()->putGroupFunctionsExpressions(
|
|
captures.at(Const::VALUE_INDEX));
|
|
if (captures.size() < 5) {
|
|
content.replace(captures.at(0),
|
|
QString("%1(%2,%3)")
|
|
.arg(functionName)
|
|
.arg('"' + expressionIndex + '"')
|
|
.arg('"' + band->objectName() + '"'));
|
|
} else {
|
|
content.replace(captures.at(0),
|
|
QString("%1(%2,%3,%4)")
|
|
.arg(functionName, '"' + expressionIndex + '"',
|
|
'"' + band->objectName() + '"',
|
|
captures.at(4)));
|
|
}
|
|
}
|
|
pos += rx.matchedLength();
|
|
}
|
|
}
|
|
|
|
#endif
|
|
}
|
|
contentItem->setContent(content);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ReportRender::replaceGroupFunctionsInContainer(BaseDesignIntf* baseItem, BandDesignIntf* band)
|
|
{
|
|
if (baseItem) {
|
|
foreach (BaseDesignIntf* item, baseItem->childBaseItems()) {
|
|
ContentItemDesignIntf* contentItem = dynamic_cast<ContentItemDesignIntf*>(item);
|
|
if (contentItem)
|
|
replaceGroupFunctionsInItem(contentItem, band);
|
|
else
|
|
replaceGroupFunctionsInContainer(item, band);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ReportRender::replaceGroupsFunction(BandDesignIntf* band)
|
|
{
|
|
replaceGroupFunctionsInContainer(band, band);
|
|
}
|
|
|
|
QColor ReportRender::makeBackgroundColor(BandDesignIntf* band)
|
|
{
|
|
if (band->useAlternateBackgroundColor()) {
|
|
return datasources()
|
|
->variable(QLatin1String("line_") + band->objectName().toLower())
|
|
.toInt()
|
|
% 2
|
|
== 0
|
|
? band->backgroundColor()
|
|
: band->alternateBackgroundColor();
|
|
}
|
|
return band->backgroundColor();
|
|
}
|
|
|
|
BandDesignIntf* ReportRender::renderBand(BandDesignIntf* patternBand, BandDesignIntf* bandData,
|
|
ReportRender::DataRenderMode mode, bool isLast)
|
|
{
|
|
QCoreApplication::processEvents();
|
|
bool bandIsSliced = false;
|
|
if (patternBand) {
|
|
|
|
if (patternBand->isHeader())
|
|
m_lastRenderedHeader = patternBand;
|
|
|
|
BandDesignIntf* bandClone = 0;
|
|
|
|
if (bandData) {
|
|
bandClone = bandData;
|
|
} else {
|
|
bandClone = renderData(patternBand);
|
|
}
|
|
|
|
if (isLast)
|
|
bandClone->setBottomSpace(1);
|
|
|
|
if (mode == ForcedStartPage) {
|
|
savePage();
|
|
startNewPage();
|
|
}
|
|
|
|
if (patternBand->isFooter())
|
|
m_lastRenderedFooter = patternBand;
|
|
|
|
bandClone->setBackgroundColor(makeBackgroundColor(bandClone));
|
|
patternBand->emitBandRendered(bandClone);
|
|
m_scriptEngineContext->setCurrentBand(bandClone);
|
|
|
|
if (isLast && bandClone->keepFooterTogether() && bandClone->sliceLastRow()) {
|
|
if (m_maxHeightByColumn[m_currentColumn] < (bandClone->height() + m_reportFooterHeight))
|
|
m_maxHeightByColumn[m_currentColumn]
|
|
-= ((m_maxHeightByColumn[m_currentColumn] - bandClone->height())
|
|
+ (bandClone->height() * calcSlicePercent(bandClone->height())));
|
|
}
|
|
|
|
if (!bandClone->isEmpty() || patternBand->printIfEmpty()) {
|
|
if (!registerBand(bandClone)) {
|
|
if (patternBand && patternBand->isHeader() && patternBand->reprintOnEachPage())
|
|
m_reprintableBands.removeOne(patternBand);
|
|
if (bandClone->canBeSplitted(m_maxHeightByColumn[m_currentColumn])) {
|
|
bandClone = sliceBand(bandClone, patternBand, isLast);
|
|
bandIsSliced = true;
|
|
} else {
|
|
qreal percent = (bandClone->height() - m_maxHeightByColumn[m_currentColumn])
|
|
/ (bandClone->height() / 100);
|
|
if (bandClone->maxScalePercent() >= percent) {
|
|
if (percent < bandClone->maxScalePercent()) {
|
|
percent += 2;
|
|
bandClone->setScale((100 - percent) / 100);
|
|
BandDesignIntf* upperPart = dynamic_cast<BandDesignIntf*>(
|
|
bandClone->cloneUpperPart(m_maxHeightByColumn[m_currentColumn]));
|
|
registerBand(upperPart);
|
|
delete bandClone;
|
|
bandClone = NULL;
|
|
}
|
|
} else {
|
|
|
|
if (mode == StartNewPageAsNeeded) {
|
|
if (bandClone->columnsCount() > 1
|
|
&& (bandClone->columnsFillDirection() == BandDesignIntf::Vertical
|
|
|| bandClone->columnsFillDirection()
|
|
== BandDesignIntf::VerticalUniform)) {
|
|
startNewColumn();
|
|
if (patternBand->bandHeader()
|
|
&& patternBand->bandHeader()->columnsCount() > 1
|
|
&& !m_lostHeadersMoved
|
|
&& patternBand->bandNestingLevel() == 0) {
|
|
renderBand(patternBand->bandHeader(), 0, mode);
|
|
}
|
|
} else {
|
|
savePage();
|
|
startNewPage();
|
|
if (!bandIsSliced) {
|
|
BandDesignIntf* t = renderData(patternBand, false);
|
|
t->copyBandAttributes(bandClone);
|
|
patternBand->emitBandReRendered(bandClone, t);
|
|
delete bandClone;
|
|
bandClone = t;
|
|
}
|
|
}
|
|
if (!registerBand(bandClone)) {
|
|
BandDesignIntf* upperPart
|
|
= dynamic_cast<BandDesignIntf*>(bandClone->cloneUpperPart(
|
|
m_maxHeightByColumn[m_currentColumn]));
|
|
registerBand(upperPart);
|
|
patternBand->emitBandReRendered(bandClone, upperPart);
|
|
delete bandClone;
|
|
bandClone = NULL;
|
|
};
|
|
} else {
|
|
bandClone->setHeight(m_maxHeightByColumn[m_currentColumn]);
|
|
registerBand(bandClone);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
delete bandClone;
|
|
return 0;
|
|
}
|
|
|
|
if (patternBand->isFooter()) {
|
|
datasources()->clearGroupFunctionValues(patternBand->objectName());
|
|
}
|
|
|
|
emit(patternBand->afterRender());
|
|
return bandClone;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void ReportRender::renderDataBand(BandDesignIntf* dataBand)
|
|
{
|
|
if (dataBand == NULL)
|
|
return;
|
|
|
|
IDataSource* bandDatasource = 0;
|
|
m_lastRenderedFooter = 0;
|
|
|
|
if (!dataBand->datasourceName().isEmpty())
|
|
bandDatasource = datasources()->dataSource(dataBand->datasourceName());
|
|
|
|
BandDesignIntf* header = dataBand->bandHeader();
|
|
BandDesignIntf* footer = dataBand->bandFooter();
|
|
|
|
if (header && header->printAlways())
|
|
renderDataHeader(header);
|
|
|
|
if (bandDatasource && !bandDatasource->eof() && !m_renderCanceled) {
|
|
|
|
QString varName = QLatin1String("line_") + dataBand->objectName().toLower();
|
|
datasources()->setReportVariable(varName, 1);
|
|
|
|
if (header && header->reprintOnEachPage())
|
|
m_reprintableBands.append(dataBand->bandHeader());
|
|
|
|
if (header && !header->printAlways())
|
|
renderDataHeader(header);
|
|
|
|
renderGroupHeader(dataBand, bandDatasource, true);
|
|
|
|
bool firstTime = true;
|
|
|
|
while (!bandDatasource->eof() && !m_renderCanceled) {
|
|
|
|
datasources()->updateChildrenData(dataBand->datasourceName());
|
|
|
|
BandDesignIntf* rawData = renderData(dataBand);
|
|
|
|
if (!rawData->isEmpty() || dataBand->printIfEmpty()) {
|
|
|
|
if ((firstTime && dataBand->startFromNewPage())
|
|
|| (!firstTime && dataBand->startNewPage())) {
|
|
savePage();
|
|
startNewPage();
|
|
}
|
|
|
|
if (dataBand->tryToKeepTogether())
|
|
openDataGroup(dataBand);
|
|
|
|
if (dataBand->keepFooterTogether() && !bandDatasource->hasNext())
|
|
openFooterGroup(dataBand);
|
|
|
|
m_lastDataBand = dataBand;
|
|
|
|
if (header && !firstTime && header->repeatOnEachRow())
|
|
renderBand(header, 0, StartNewPageAsNeeded);
|
|
|
|
renderBand(dataBand, rawData, StartNewPageAsNeeded, !bandDatasource->hasNext());
|
|
m_newPageStarted = false;
|
|
renderChildBands(dataBand);
|
|
}
|
|
|
|
bandDatasource->next();
|
|
|
|
datasources()->setReportVariable(varName, datasources()->variable(varName).toInt() + 1);
|
|
|
|
QList<BandDesignIntf*> bandList;
|
|
QList<BandDesignIntf*> childList;
|
|
|
|
bandList = dataBand->childrenByType(BandDesignIntf::GroupHeader);
|
|
while (bandList.size() > 0) {
|
|
childList.clear();
|
|
foreach (BandDesignIntf* band, bandList) {
|
|
childList.append(band->childrenByType(BandDesignIntf::GroupHeader));
|
|
|
|
QString groupLineVar = QLatin1String("line_") + band->objectName().toLower();
|
|
if (datasources()->containsVariable(groupLineVar))
|
|
datasources()->setReportVariable(
|
|
groupLineVar, datasources()->variable(groupLineVar).toInt() + 1);
|
|
}
|
|
bandList = childList;
|
|
}
|
|
|
|
renderGroupHeader(dataBand, bandDatasource, false);
|
|
if (dataBand->tryToKeepTogether())
|
|
closeDataGroup(dataBand);
|
|
firstTime = false;
|
|
}
|
|
|
|
if (!dataBand->keepFooterTogether())
|
|
m_reprintableBands.removeOne(header);
|
|
if (header)
|
|
recalcIfNeeded(header);
|
|
|
|
bool didGoBack = !bandDatasource->eof() && bandDatasource->prior();
|
|
renderGroupFooterByHeader(dataBand);
|
|
if (didGoBack) {
|
|
bandDatasource->next();
|
|
}
|
|
|
|
if (footer && !footer->printAlways()) {
|
|
renderBand(footer, 0, StartNewPageAsNeeded);
|
|
if (dataBand->keepFooterTogether())
|
|
m_reprintableBands.removeOne(dataBand);
|
|
}
|
|
|
|
datasources()->deleteVariable(varName);
|
|
|
|
} else if (bandDatasource == 0) {
|
|
renderBand(dataBand, 0, StartNewPageAsNeeded);
|
|
}
|
|
|
|
if (footer && footer->printAlways()) {
|
|
renderBand(footer, 0, StartNewPageAsNeeded);
|
|
if (dataBand->keepFooterTogether())
|
|
m_reprintableBands.removeOne(dataBand);
|
|
}
|
|
}
|
|
|
|
void ReportRender::renderPageHeader(PageItemDesignIntf* patternPage)
|
|
{
|
|
BandDesignIntf* band = patternPage->bandByType(BandDesignIntf::PageHeader);
|
|
if (band) {
|
|
if (m_datasources->variable("#PAGE").toInt() != 1
|
|
|| band->property("printOnFirstPage").toBool())
|
|
renderBand(band, 0);
|
|
}
|
|
}
|
|
|
|
void ReportRender::renderReportHeader(PageItemDesignIntf* patternPage, PageRenderStage stage)
|
|
{
|
|
BandDesignIntf* band = patternPage->bandByType(BandDesignIntf::ReportHeader);
|
|
BandDesignIntf* resBand = 0;
|
|
if (band) {
|
|
if (band->property("printBeforePageHeader").toBool() && stage == BeforePageHeader)
|
|
resBand = renderBand(band, 0, StartNewPageAsNeeded);
|
|
if (!band->property("printBeforePageHeader").toBool() && stage == AfterPageHeader)
|
|
resBand = renderBand(band, 0, StartNewPageAsNeeded);
|
|
if (resBand && containsGroupFunctions(band))
|
|
m_recalcBands.append(resBand);
|
|
}
|
|
}
|
|
|
|
void ReportRender::renderPageFooter(PageItemDesignIntf* patternPage)
|
|
{
|
|
BandDesignIntf* band = patternPage->bandByType(BandDesignIntf::PageFooter);
|
|
if (band) {
|
|
BandDesignIntf* bandClone = dynamic_cast<BandDesignIntf*>(
|
|
band->cloneItem(PreviewMode, m_renderPageItem, m_renderPageItem));
|
|
replaceGroupsFunction(bandClone);
|
|
bandClone->updateItemSize(m_datasources);
|
|
bandClone->setItemPos(m_renderPageItem->pageRect().x(),
|
|
m_renderPageItem->pageRect().bottom() - bandClone->height());
|
|
bandClone->setHeight(m_pageFooterHeight);
|
|
for (int i = 0; i < m_maxHeightByColumn.size(); ++i)
|
|
m_maxHeightByColumn[i] += m_pageFooterHeight;
|
|
m_renderPageItem->setPageFooter(bandClone);
|
|
registerBand(bandClone);
|
|
datasources()->clearGroupFunctionValues(band->objectName());
|
|
}
|
|
}
|
|
|
|
void ReportRender::renderPageItems(PageItemDesignIntf* patternPage)
|
|
{
|
|
QList<BaseDesignIntf*> pageItems;
|
|
foreach (BaseDesignIntf* item, patternPage->childBaseItems()) {
|
|
ItemDesignIntf* id = dynamic_cast<ItemDesignIntf*>(item);
|
|
if (id && id->itemLocation() == ItemDesignIntf::Page) {
|
|
BaseDesignIntf* cloneItem
|
|
= item->cloneItem(m_renderPageItem->itemMode(), m_renderPageItem, m_renderPageItem);
|
|
pageItems.append(cloneItem);
|
|
}
|
|
}
|
|
m_renderPageItem->restoreLinks();
|
|
m_renderPageItem->updateSubItemsSize(FirstPass, m_datasources);
|
|
foreach (BaseDesignIntf* item, pageItems) {
|
|
if (!item->isWatermark())
|
|
item->setZValue(item->zValue() - 100000);
|
|
else
|
|
item->setZValue(item->zValue() + 100000);
|
|
}
|
|
}
|
|
|
|
qreal ReportRender::calcPageFooterHeight(PageItemDesignIntf* patternPage)
|
|
{
|
|
BandDesignIntf* band = patternPage->bandByType(BandDesignIntf::PageFooter);
|
|
if (band) {
|
|
if (m_datasources->variable("#PAGE") != 1)
|
|
return band->height();
|
|
else if (band->property("printOnFirstPage").toBool())
|
|
return band->height();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void ReportRender::renderChildHeader(BandDesignIntf* parent, BandPrintMode printMode)
|
|
{
|
|
foreach (BandDesignIntf* band, parent->childrenByType(BandDesignIntf::SubDetailHeader)) {
|
|
bool printAlways = false;
|
|
if (band->metaObject()->indexOfProperty("printAlways") > 0) {
|
|
printAlways = band->property("printAlways").toBool();
|
|
}
|
|
if (printAlways == (printMode == PrintAlwaysPrintable))
|
|
renderBand(band, 0, StartNewPageAsNeeded);
|
|
}
|
|
}
|
|
|
|
void ReportRender::renderChildFooter(BandDesignIntf* parent, BandPrintMode printMode)
|
|
{
|
|
foreach (BandDesignIntf* band, parent->childrenByType(BandDesignIntf::SubDetailFooter)) {
|
|
bool printAlways = false;
|
|
if (band->metaObject()->indexOfProperty("printAlways") > 0) {
|
|
printAlways = band->property("printAlways").toBool();
|
|
}
|
|
|
|
if ((band != m_lastRenderedFooter) && (printAlways == (printMode == PrintAlwaysPrintable)))
|
|
renderBand(band, 0, StartNewPageAsNeeded);
|
|
}
|
|
}
|
|
|
|
void ReportRender::renderChildBands(BandDesignIntf* parentBand)
|
|
{
|
|
foreach (BandDesignIntf* band, parentBand->childrenByType(BandDesignIntf::SubDetailBand)) {
|
|
IDataSource* ds = 0;
|
|
if (!band->datasourceName().isEmpty())
|
|
ds = m_datasources->dataSource(band->datasourceName());
|
|
if (ds)
|
|
ds->first();
|
|
renderDataBand(band);
|
|
closeFooterGroup(band);
|
|
}
|
|
}
|
|
|
|
BandDesignIntf* ReportRender::findRecalcableBand(BandDesignIntf* patternBand)
|
|
{
|
|
|
|
QList<BandDesignIntf*>::iterator it = m_recalcBands.begin();
|
|
for (; it != m_recalcBands.end(); ++it) {
|
|
if ((*it)->patternItem() == patternBand) {
|
|
BandDesignIntf* result = (*it);
|
|
m_recalcBands.erase(it);
|
|
return result;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void restoreItemsWithGroupFunctions(BaseDesignIntf* container, DataSourceManager* datasources)
|
|
{
|
|
foreach (BaseDesignIntf* bi, container->childBaseItems()) {
|
|
ContentItemDesignIntf* pci = dynamic_cast<ContentItemDesignIntf*>(bi->patternItem());
|
|
if (pci && checkContentItem(pci, datasources)) {
|
|
ContentItemDesignIntf* ci = dynamic_cast<ContentItemDesignIntf*>(bi);
|
|
ci->setContent(pci->content());
|
|
} else
|
|
restoreItemsWithGroupFunctions(bi, datasources);
|
|
}
|
|
}
|
|
|
|
void ReportRender::recalcIfNeeded(BandDesignIntf* band)
|
|
{
|
|
BandDesignIntf* recalcBand = findRecalcableBand(band);
|
|
if (recalcBand) {
|
|
QString bandName = recalcBand->objectName();
|
|
restoreItemsWithGroupFunctions(recalcBand, m_datasources);
|
|
recalcBand->setObjectName(recalcBand->patternItem()->objectName());
|
|
replaceGroupsFunction(recalcBand);
|
|
recalcBand->updateItemSize(datasources());
|
|
recalcBand->setObjectName(bandName);
|
|
datasources()->clearGroupFunctionValues(recalcBand->patternItem()->objectName());
|
|
}
|
|
}
|
|
|
|
void ReportRender::renderDataHeader(BandDesignIntf* header)
|
|
{
|
|
recalcIfNeeded(header);
|
|
BandDesignIntf* renderedHeader = renderBand(header, 0, StartNewPageAsNeeded);
|
|
if (containsGroupFunctions(header))
|
|
m_recalcBands.append(renderedHeader);
|
|
}
|
|
|
|
void ReportRender::renderGroupHeader(BandDesignIntf* parentBand, IDataSource* dataSource,
|
|
bool firstTime)
|
|
{
|
|
foreach (BandDesignIntf* band, parentBand->childrenByType(BandDesignIntf::GroupHeader)) {
|
|
IGroupBand* gb = dynamic_cast<IGroupBand*>(band);
|
|
if (gb && gb->isNeedToClose(datasources())) {
|
|
if (band->childBands().count() > 0) {
|
|
bool didGoBack = !dataSource->eof() && dataSource->prior();
|
|
renderGroupFooterByHeader(band);
|
|
if (didGoBack) {
|
|
dataSource->next();
|
|
}
|
|
}
|
|
closeDataGroup(band);
|
|
}
|
|
|
|
if (gb && !gb->isStarted()) {
|
|
if (band->reprintOnEachPage()) {
|
|
m_reprintableBands.append(band);
|
|
}
|
|
gb->startGroup(m_datasources);
|
|
openDataGroup(band);
|
|
BandDesignIntf* renderedHeader = 0;
|
|
if (!firstTime && gb->startNewPage() && !m_newPageStarted) {
|
|
if (gb->resetPageNumber())
|
|
resetPageNumber(BandReset);
|
|
if (band->reprintOnEachPage()) {
|
|
savePage();
|
|
startNewPage();
|
|
} else {
|
|
renderedHeader = renderBand(band, 0, ForcedStartPage);
|
|
}
|
|
} else {
|
|
renderedHeader = renderBand(band, 0, StartNewPageAsNeeded);
|
|
}
|
|
if (containsGroupFunctions(band))
|
|
m_recalcBands.append(renderedHeader);
|
|
}
|
|
|
|
renderGroupHeader(band, dataSource, firstTime);
|
|
}
|
|
}
|
|
|
|
void ReportRender::renderGroupFooterByHeader(BandDesignIntf* groupHeader)
|
|
{
|
|
if (groupHeader->reprintOnEachPage())
|
|
m_reprintableBands.removeOne(groupHeader);
|
|
foreach (BandDesignIntf* header, groupHeader->childrenByType(BandDesignIntf::GroupHeader)) {
|
|
renderGroupFooterByHeader(header);
|
|
}
|
|
foreach (BandDesignIntf* footer, groupHeader->childrenByType(BandDesignIntf::GroupFooter)) {
|
|
renderBand(footer, 0, StartNewPageAsNeeded);
|
|
}
|
|
closeDataGroup(groupHeader);
|
|
}
|
|
|
|
void ReportRender::renderGroupFooter(BandDesignIntf* parentBand)
|
|
{
|
|
foreach (BandDesignIntf* band, parentBand->childrenByType(BandDesignIntf::GroupHeader)) {
|
|
IGroupBand* gb = dynamic_cast<IGroupBand*>(band);
|
|
if (gb && gb->isStarted()) {
|
|
renderGroupFooterByHeader(band);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ReportRender::initGroups()
|
|
{
|
|
m_datasources->clearGroupFunction();
|
|
foreach (BandDesignIntf* band, m_patternPageItem->childBands()) {
|
|
if (band->isFooter())
|
|
extractGroupFunctions(band);
|
|
if (band->isHeader()) {
|
|
IGroupBand* gb = dynamic_cast<IGroupBand*>(band);
|
|
if (gb)
|
|
gb->closeGroup();
|
|
extractGroupFunctions(band);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ReportRender::popPageFooterGroupValues(BandDesignIntf* dataBand)
|
|
{
|
|
BandDesignIntf* pageFooter = m_patternPageItem->bandByType(BandDesignIntf::PageFooter);
|
|
if (pageFooter) {
|
|
foreach (GroupFunction* gf, datasources()->groupFunctionsByBand(pageFooter->objectName())) {
|
|
if ((gf->dataBandName() == dataBand->objectName())) {
|
|
// FIXME Probably coincidence Field and Variables
|
|
if ((!m_popupedExpression.contains(dataBand))
|
|
|| (!m_popupedExpression.values(dataBand).contains(gf->data()))) {
|
|
m_popupedExpression.insert(dataBand, gf->data());
|
|
m_popupedValues.insert(QString("%1").arg((quintptr)dataBand) + '|' + gf->data(),
|
|
gf->values()[gf->values().count() - 1]);
|
|
gf->values().pop_back();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ReportRender::pushPageFooterGroupValues(BandDesignIntf* dataBand)
|
|
{
|
|
BandDesignIntf* pageFooter = m_patternPageItem->bandByType(BandDesignIntf::PageFooter);
|
|
if (pageFooter) {
|
|
foreach (GroupFunction* gf, datasources()->groupFunctionsByBand(pageFooter->objectName())) {
|
|
if ((gf->dataBandName() == dataBand->objectName())) {
|
|
// FIXME Probably coincidence Field and Variables
|
|
if ((m_popupedExpression.contains(dataBand))
|
|
&& (m_popupedExpression.values(dataBand).contains(gf->data()))) {
|
|
gf->values().push_back(m_popupedValues.value(
|
|
QString("%1").arg((quintptr)dataBand) + '|' + gf->data()));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ReportRender::closeGroup(BandDesignIntf* band)
|
|
{
|
|
QMultiMap<BandDesignIntf*, GroupBandsHolder*>::iterator it;
|
|
it = m_childBands.find(band);
|
|
|
|
while (it != m_childBands.end() && it.key() == band) {
|
|
GroupBandsHolder* bl = it.value();
|
|
if (bl) {
|
|
bl->clear();
|
|
delete bl;
|
|
}
|
|
++it;
|
|
}
|
|
|
|
m_childBands.remove(band);
|
|
}
|
|
|
|
void ReportRender::openDataGroup(BandDesignIntf* band)
|
|
{
|
|
m_childBands.insert(band, new GroupBandsHolder(band->tryToKeepTogether()));
|
|
}
|
|
|
|
void ReportRender::openFooterGroup(BandDesignIntf* band)
|
|
{
|
|
GroupBandsHolder* holder = new GroupBandsHolder(true);
|
|
holder->setIsFooterGroup();
|
|
m_childBands.insert(band, holder);
|
|
}
|
|
|
|
void ReportRender::closeDataGroup(BandDesignIntf* band)
|
|
{
|
|
IGroupBand* groupBand = dynamic_cast<IGroupBand*>(band);
|
|
if (groupBand) {
|
|
groupBand->closeGroup();
|
|
if (band->reprintOnEachPage())
|
|
m_reprintableBands.removeOne(band);
|
|
|
|
QList<BandDesignIntf*>::Iterator it = m_reprintableBands.begin();
|
|
while (it != m_reprintableBands.end()) {
|
|
if ((*it)->bandIndex() > band->bandIndex())
|
|
it = m_reprintableBands.erase(it);
|
|
else
|
|
++it;
|
|
}
|
|
}
|
|
recalcIfNeeded(band);
|
|
closeGroup(band);
|
|
}
|
|
|
|
void ReportRender::closeFooterGroup(BandDesignIntf* band) { closeGroup(band); }
|
|
|
|
qreal maxVectorValue(QVector<qreal> vector)
|
|
{
|
|
qreal curValue = 0;
|
|
foreach (qreal value, vector) {
|
|
if (curValue < value)
|
|
curValue = value;
|
|
}
|
|
return curValue;
|
|
}
|
|
|
|
qreal minVectorValue(QVector<qreal> vector)
|
|
{
|
|
qreal curValue = vector[0];
|
|
foreach (qreal value, vector) {
|
|
if (curValue > value)
|
|
curValue = value;
|
|
}
|
|
return curValue;
|
|
}
|
|
|
|
void ReportRender::placeBandOnPage(BandDesignIntf* band, int columnIndex)
|
|
{
|
|
|
|
qreal bandPos = m_currentStartDataPos[columnIndex];
|
|
|
|
m_currentStartDataPos[columnIndex] += band->height();
|
|
m_maxHeightByColumn[columnIndex] -= band->height();
|
|
band->setPos(m_renderPageItem->pageRect().x() + band->width() * columnIndex, bandPos);
|
|
band->setBandIndex(++m_currentIndex);
|
|
band->setColumnIndex(columnIndex);
|
|
|
|
m_renderPageItem->registerBand(band);
|
|
m_currentColumn = columnIndex;
|
|
}
|
|
|
|
bool isMultiColumnHeader(BandDesignIntf* band)
|
|
{
|
|
return ((band->columnsCount() > 1)
|
|
&& (band->isHeader()
|
|
&& ((band->bandNestingLevel() == 0)
|
|
|| (band->columnsFillDirection() == BandDesignIntf::Horizontal))));
|
|
}
|
|
|
|
bool ReportRender::registerBand(BandDesignIntf* band, bool registerInChildren)
|
|
{
|
|
|
|
if (band->columnsCount() == 1 && m_maxHeightByColumn.size() > 1) {
|
|
if (band->bandType() != BandDesignIntf::PageFooter) {
|
|
rearrangeColumnsItems();
|
|
m_currentColumn = 0;
|
|
qreal minValue = minVectorValue(m_maxHeightByColumn);
|
|
m_maxHeightByColumn.clear();
|
|
m_maxHeightByColumn.append(minValue);
|
|
qreal maxValue = maxVectorValue(m_currentStartDataPos);
|
|
m_currentStartDataPos.clear();
|
|
m_currentStartDataPos.append(maxValue);
|
|
}
|
|
}
|
|
|
|
if (band->columnsCount() != m_maxHeightByColumn.size()) {
|
|
for (int i = 1; i < band->columnsCount(); ++i) {
|
|
m_maxHeightByColumn.append(m_maxHeightByColumn[0]);
|
|
m_currentStartDataPos.append(m_currentStartDataPos[0]);
|
|
}
|
|
m_currentColumn = -1;
|
|
}
|
|
|
|
if ((band->columnsCount() > 1)
|
|
&& (!band->isHeader()
|
|
|| (band->bandNestingLevel() > 0
|
|
&& band->columnsFillDirection() != BandDesignIntf::Horizontal))) {
|
|
|
|
if (band->columnsFillDirection() == BandDesignIntf::Horizontal) {
|
|
if (m_currentColumn < band->columnsCount() - 1)
|
|
m_currentColumn = m_currentColumn + 1;
|
|
else
|
|
m_currentColumn = 0;
|
|
} else {
|
|
m_currentColumn = m_currentColumn == -1 ? 0 : m_currentColumn;
|
|
if ((m_currentColumn != 0)
|
|
&& (m_maxHeightByColumn[0] == m_maxHeightByColumn[m_currentColumn])
|
|
&& (m_maxHeightByColumn[0] >= band->height())) {
|
|
m_currentColumn = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
m_currentColumn = m_currentColumn == -1 ? 0 : m_currentColumn;
|
|
|
|
if ((band->height() <= m_maxHeightByColumn[m_currentColumn])
|
|
|| m_patternPageItem->endlessHeight()
|
|
|| (isMultiColumnHeader(band) && (band->height() <= m_maxHeightByColumn[0]))) {
|
|
|
|
if ((band->bandType() == BandDesignIntf::PageFooter)) {
|
|
for (int i = 0; i < m_maxHeightByColumn.size(); ++i)
|
|
m_maxHeightByColumn[i] += band->height();
|
|
}
|
|
|
|
if (isMultiColumnHeader(band)) {
|
|
|
|
if (!band->parent()) {
|
|
for (int i = 0; i < band->columnsCount(); ++i) {
|
|
m_currentColumn = i;
|
|
if (i != 0)
|
|
band = dynamic_cast<BandDesignIntf*>(band->cloneItem(PreviewMode));
|
|
placeBandOnPage(band, i);
|
|
}
|
|
} else {
|
|
placeBandOnPage(band, band->columnIndex());
|
|
}
|
|
|
|
} else {
|
|
|
|
if (band->bandType() != BandDesignIntf::PageFooter) {
|
|
placeBandOnPage(band, m_currentColumn);
|
|
}
|
|
|
|
if (band->columnsCount() > 1) {
|
|
m_columnedBandItems.append(band);
|
|
}
|
|
}
|
|
|
|
foreach (QList<BandDesignIntf*>* list, m_childBands.values()) {
|
|
if (registerInChildren && band->bandType() != BandDesignIntf::PageHeader
|
|
&& band->bandType() != BandDesignIntf::PageFooter
|
|
&& band->bandType() != BandDesignIntf::ReportHeader
|
|
&& band->bandType() != BandDesignIntf::ReportFooter && !list->contains(band)
|
|
&& !band->reprintOnEachPage())
|
|
list->append(band);
|
|
}
|
|
|
|
if (band->isData())
|
|
m_renderedDataBandCount++;
|
|
band->setObjectName(band->objectName() + QString::number(++m_currentNameIndex));
|
|
renameChildItems(band);
|
|
if (m_lastDataBand) {
|
|
#if QT_VERSION < 0x050000
|
|
m_lastDataBand->metaObject()->invokeMethod(m_lastDataBand, "bandRegistred");
|
|
#else
|
|
emit m_lastDataBand->bandRegistred();
|
|
#endif
|
|
}
|
|
if (band->bandType() != BandDesignIntf::PageFooter)
|
|
m_lastRenderedBand = band;
|
|
return true;
|
|
} else
|
|
return false;
|
|
}
|
|
|
|
qreal ReportRender::calcSlicePercent(qreal height) { return (height * 3 / (m_dataAreaSize)) / 100; }
|
|
|
|
BandDesignIntf* ReportRender::sliceBand(BandDesignIntf* band, BandDesignIntf* patternBand,
|
|
bool isLast)
|
|
{
|
|
while (band->height() > m_maxHeightByColumn[m_currentColumn]) {
|
|
band = saveUppperPartReturnBottom(band, m_maxHeightByColumn[m_currentColumn], patternBand);
|
|
if (!band->isEmpty()) {
|
|
if (band->autoHeight()) {
|
|
if (band->isNeedUpdateSize(FirstPass)) {
|
|
band->setHeight(0);
|
|
}
|
|
band->updateItemSize(m_datasources);
|
|
}
|
|
DataBandDesignIntf* data = dynamic_cast<DataBandDesignIntf*>(band);
|
|
if (isLast && data && data->keepFooterTogether()
|
|
&& band->height() < m_maxHeightByColumn[m_currentColumn] && band->sliceLastRow()) {
|
|
if (band->height()
|
|
> (m_maxHeightByColumn[m_currentColumn] - m_reportFooterHeight)) {
|
|
m_maxHeightByColumn[m_currentColumn]
|
|
-= ((m_maxHeightByColumn[m_currentColumn] - band->height())
|
|
+ (band->height() * calcSlicePercent(band->height())));
|
|
}
|
|
}
|
|
if (registerBand(band))
|
|
break;
|
|
} else
|
|
break;
|
|
}
|
|
|
|
if (band->isEmpty()) {
|
|
delete band;
|
|
band = 0;
|
|
}
|
|
|
|
return band;
|
|
}
|
|
|
|
void ReportRender::updateTOC(BaseDesignIntf* item, int pageNumber)
|
|
{
|
|
BookmarkContainerDesignIntf* bookmarkContainer
|
|
= dynamic_cast<BookmarkContainerDesignIntf*>(item);
|
|
if (bookmarkContainer) {
|
|
TableOfContents* toc = m_scriptEngineContext->tableOfContents();
|
|
foreach (QString key, bookmarkContainer->bookmarks()) {
|
|
toc->setItem(key, bookmarkContainer->getBookMark(key).toString(), pageNumber);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ReportRender::secondRenderPass(ReportPages renderedPages)
|
|
{
|
|
if (!m_scriptEngineContext->tableOfContents()->isEmpty()) {
|
|
for (int i = 0; i < renderedPages.count(); ++i) {
|
|
PageItemDesignIntf::Ptr page = renderedPages.at(i);
|
|
updateTOC(page.data(), m_pagesRanges.findPageNumber(i));
|
|
foreach (BaseDesignIntf* item, page->childBaseItems()) {
|
|
updateTOC(item, m_pagesRanges.findPageNumber(i));
|
|
}
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < renderedPages.count(); ++i) {
|
|
PageItemDesignIntf::Ptr page = renderedPages.at(i);
|
|
m_datasources->setReportVariable("#PAGE", m_pagesRanges.findPageNumber(i));
|
|
m_datasources->setReportVariable("#PAGE_COUNT", m_pagesRanges.findLastPageNumber(i));
|
|
foreach (BaseDesignIntf* item, page->childBaseItems()) {
|
|
if (item->isNeedUpdateSize(SecondPass))
|
|
item->updateItemSize(m_datasources, SecondPass);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ReportRender::createTOCMarker(bool startNewRange)
|
|
{
|
|
m_pagesRanges.addTOCMarker(startNewRange);
|
|
}
|
|
|
|
BandDesignIntf* ReportRender::saveUppperPartReturnBottom(BandDesignIntf* band, int height,
|
|
BandDesignIntf* patternBand)
|
|
{
|
|
// int sliceHeight = height;
|
|
BandDesignIntf* upperBandPart = dynamic_cast<BandDesignIntf*>(band->cloneUpperPart(height));
|
|
BandDesignIntf* bottomBandPart = dynamic_cast<BandDesignIntf*>(band->cloneBottomPart(height));
|
|
if (!bottomBandPart->isEmpty()) {
|
|
if (patternBand->keepFooterTogether())
|
|
closeFooterGroup(patternBand);
|
|
if (upperBandPart->isEmpty())
|
|
bottomBandPart->copyBookmarks(band);
|
|
}
|
|
if (!upperBandPart->isEmpty()) {
|
|
upperBandPart->setBottomSpace(0);
|
|
upperBandPart->updateItemSize(m_datasources, FirstPass, height);
|
|
registerBand(upperBandPart);
|
|
upperBandPart->copyBookmarks(band);
|
|
if (patternBand->isFooter())
|
|
closeFooterGroup(m_lastDataBand);
|
|
} else
|
|
delete upperBandPart;
|
|
|
|
if (band->columnsCount() > 1
|
|
&& (band->columnsFillDirection() == BandDesignIntf::Vertical
|
|
|| band->columnsFillDirection() == BandDesignIntf::VerticalUniform)) {
|
|
startNewColumn();
|
|
if (patternBand->bandHeader() && patternBand->bandHeader()->columnsCount() > 1
|
|
&& !m_lostHeadersMoved && patternBand->bandNestingLevel() == 0) {
|
|
renderBand(patternBand->bandHeader(), 0, StartNewPageAsNeeded);
|
|
}
|
|
|
|
} else {
|
|
savePage();
|
|
startNewPage();
|
|
}
|
|
|
|
delete band;
|
|
return bottomBandPart;
|
|
}
|
|
|
|
BandDesignIntf* ReportRender::renderData(BandDesignIntf* patternBand, bool emitBeforeRender)
|
|
{
|
|
BandDesignIntf* bandClone = dynamic_cast<BandDesignIntf*>(patternBand->cloneItem(PreviewMode));
|
|
|
|
m_scriptEngineContext->baseDesignIntfToScript(patternBand->parent()->objectName(), bandClone);
|
|
m_scriptEngineContext->setCurrentBand(bandClone);
|
|
if (emitBeforeRender)
|
|
emit(patternBand->beforeRender());
|
|
|
|
if (patternBand->isFooter()) {
|
|
replaceGroupsFunction(bandClone);
|
|
}
|
|
|
|
if (patternBand->isHeader()) {
|
|
replaceGroupsFunction(bandClone);
|
|
}
|
|
|
|
emit(patternBand->preparedForRender());
|
|
bandClone->setBottomSpace(patternBand->height() - patternBand->findMaxBottom());
|
|
bandClone->updateItemSize(m_datasources);
|
|
|
|
// m_scriptEngineContext->baseDesignIntfToScript(bandClone);
|
|
emit(patternBand->afterData());
|
|
|
|
return bandClone;
|
|
}
|
|
|
|
void ReportRender::startNewColumn()
|
|
{
|
|
if (m_currentColumn < m_maxHeightByColumn.size() - 1) {
|
|
m_currentColumn++;
|
|
checkLostHeadersInPrevColumn();
|
|
} else {
|
|
savePage();
|
|
startNewPage();
|
|
}
|
|
}
|
|
|
|
void ReportRender::startNewPage(bool isFirst)
|
|
{
|
|
m_renderPageItem = 0;
|
|
m_newPageStarted = true;
|
|
initColumns();
|
|
initRenderPage();
|
|
m_scriptEngineContext->setCurrentPage(m_renderPageItem);
|
|
m_scriptEngineContext->baseDesignIntfToScript(m_renderPageItem->patternName(),
|
|
m_renderPageItem);
|
|
emit m_patternPageItem->beforeRender();
|
|
|
|
m_renderPageItem->setObjectName(QLatin1String("ReportPage") + QString::number(m_pageCount));
|
|
m_maxHeightByColumn[m_currentColumn] = m_renderPageItem->pageRect().height();
|
|
m_currentStartDataPos[m_currentColumn] = m_patternPageItem->topMargin() * Const::mmFACTOR;
|
|
m_currentIndex = 0;
|
|
|
|
if (isFirst) {
|
|
renderReportHeader(m_patternPageItem, BeforePageHeader);
|
|
emit m_patternPageItem->beforeFirstPageRendered();
|
|
}
|
|
|
|
renderPageHeader(m_patternPageItem);
|
|
|
|
m_pageFooterHeight = calcPageFooterHeight(m_patternPageItem) + 2;
|
|
m_maxHeightByColumn[m_currentColumn] -= m_pageFooterHeight;
|
|
m_currentIndex = 10;
|
|
m_dataAreaSize = m_maxHeightByColumn[m_currentColumn];
|
|
m_renderedDataBandCount = 0;
|
|
|
|
foreach (BandDesignIntf* band, m_reprintableBands) {
|
|
renderBand(band, 0);
|
|
}
|
|
|
|
checkLostHeadersOnPrevPage();
|
|
pasteGroups();
|
|
}
|
|
|
|
void ReportRender::resetPageNumber(ResetPageNuberType resetType)
|
|
{
|
|
m_pagesRanges.startNewRange();
|
|
if (resetType == PageReset)
|
|
m_datasources->setReportVariable("#PAGE", 1);
|
|
}
|
|
|
|
void ReportRender::cutGroups()
|
|
{
|
|
m_popupedExpression.clear();
|
|
m_popupedValues.clear();
|
|
// foreach(BandDesignIntf* groupBand,m_childBands.keys()){
|
|
foreach (BandDesignIntf* groupBand, m_childBands.keys()) {
|
|
if (m_childBands.value(groupBand)->tryToKeepTogether()) {
|
|
foreach (BandDesignIntf* band, *m_childBands.value(groupBand)) {
|
|
m_renderPageItem->removeBand(band);
|
|
popPageFooterGroupValues(band);
|
|
band->setParent(0);
|
|
band->setParentItem(0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ReportRender::checkFooterGroup(BandDesignIntf* groupBand)
|
|
{
|
|
if (m_childBands.contains(groupBand)) {
|
|
GroupBandsHolder* holder = m_childBands.value(groupBand);
|
|
foreach (BandDesignIntf* band, *holder) {
|
|
qreal percent = band->height() * 100 / m_dataAreaSize;
|
|
if (m_renderedDataBandCount <= 1 || percent > 20) {
|
|
holder->removeAll(band);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ReportRender::pasteGroups()
|
|
{
|
|
BandDesignIntf* groupBand = findEnclosingGroup();
|
|
if (groupBand) {
|
|
foreach (BandDesignIntf* band, *m_childBands.value(groupBand)) {
|
|
registerBand(band, false);
|
|
if (band->isData())
|
|
m_renderedDataBandCount++;
|
|
pushPageFooterGroupValues(band);
|
|
}
|
|
foreach (GroupBandsHolder* holder, m_childBands.values())
|
|
holder->setTryToKeepTogether(false);
|
|
}
|
|
m_popupedExpression.clear();
|
|
m_popupedValues.clear();
|
|
}
|
|
|
|
bool bandLessThen(BandDesignIntf* b1, BandDesignIntf* b2)
|
|
{
|
|
return b1->bandIndex() < b2->bandIndex();
|
|
}
|
|
|
|
void ReportRender::checkLostHeadersOnPrevPage()
|
|
{
|
|
QVector<BandDesignIntf*> lostHeaders;
|
|
|
|
if (m_renderedPages.isEmpty())
|
|
return;
|
|
PageItemDesignIntf::Ptr page = m_renderedPages.last();
|
|
if (page->bands().isEmpty())
|
|
return;
|
|
|
|
QMutableListIterator<BandDesignIntf*> it(page->bands());
|
|
|
|
it.toBack();
|
|
if (it.hasPrevious()) {
|
|
if (it.previous()->isFooter()) {
|
|
if (it.hasPrevious())
|
|
it.previous();
|
|
else
|
|
return;
|
|
}
|
|
}
|
|
|
|
while (it.hasPrevious()) {
|
|
if (it.value()->isHeader()) {
|
|
if (it.value()->reprintOnEachPage()) {
|
|
delete it.value();
|
|
} else {
|
|
lostHeaders.append(it.value());
|
|
}
|
|
it.remove();
|
|
it.previous();
|
|
} else
|
|
break;
|
|
}
|
|
|
|
if (lostHeaders.size() > 0) {
|
|
m_lostHeadersMoved = true;
|
|
// std::sort(lostHeaders.begin(), lostHeaders.end(), bandLessThen);
|
|
std::sort(lostHeaders.begin(), lostHeaders.end(), bandLessThen);
|
|
foreach (BandDesignIntf* header, lostHeaders) {
|
|
registerBand(header);
|
|
}
|
|
} else {
|
|
m_lostHeadersMoved = false;
|
|
}
|
|
}
|
|
|
|
void ReportRender::checkLostHeadersInPrevColumn()
|
|
{
|
|
QVector<BandDesignIntf*> lostHeaders;
|
|
|
|
QMutableListIterator<BandDesignIntf*> it(m_renderPageItem->bands());
|
|
|
|
it.toBack();
|
|
if (it.hasPrevious()) {
|
|
if (it.previous()->isFooter()) {
|
|
if (it.hasPrevious())
|
|
it.previous();
|
|
else
|
|
return;
|
|
}
|
|
}
|
|
|
|
while (it.hasPrevious()) {
|
|
if (it.value()->isHeader()) {
|
|
if (it.value()->reprintOnEachPage()) {
|
|
delete it.value();
|
|
} else {
|
|
lostHeaders.append(it.value());
|
|
}
|
|
it.remove();
|
|
it.previous();
|
|
} else
|
|
break;
|
|
}
|
|
|
|
if (lostHeaders.size() > 0) {
|
|
m_lostHeadersMoved = true;
|
|
// std::sort(lostHeaders.begin(), lostHeaders.end(), bandLessThen);
|
|
std::sort(lostHeaders.begin(), lostHeaders.end(), bandLessThen);
|
|
foreach (BandDesignIntf* header, lostHeaders) {
|
|
registerBand(header);
|
|
}
|
|
} else {
|
|
m_lostHeadersMoved = false;
|
|
}
|
|
}
|
|
|
|
BandDesignIntf* ReportRender::findEnclosingGroup()
|
|
{
|
|
BandDesignIntf* result = 0;
|
|
int groupIndex = -1;
|
|
if (!m_childBands.isEmpty()) {
|
|
foreach (BandDesignIntf* gb, m_childBands.keys()) {
|
|
if (m_childBands.value(gb)->tryToKeepTogether()
|
|
&& ((gb->bandIndex() < groupIndex) || (groupIndex == -1))) {
|
|
result = gb;
|
|
groupIndex = result->bandIndex();
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void ReportRender::savePage(bool isLast)
|
|
{
|
|
|
|
m_datasources->setReportVariable("#IS_LAST_PAGEFOOTER", isLast);
|
|
m_datasources->setReportVariable("#IS_FIRST_PAGEFOOTER",
|
|
m_datasources->variable("#PAGE").toInt() == 1);
|
|
|
|
renderPageItems(m_patternPageItem);
|
|
|
|
if (m_renderPageItem->isEmpty() && m_renderPageItem->notPrintIfEmpty())
|
|
return;
|
|
|
|
if (m_renderPageItem->isTOC())
|
|
m_pagesRanges.addTOCPage();
|
|
else
|
|
m_pagesRanges.addPage();
|
|
|
|
checkFooterGroup(m_lastDataBand);
|
|
cutGroups();
|
|
rearrangeColumnsItems();
|
|
m_columnedBandItems.clear();
|
|
|
|
BandDesignIntf* pf = m_patternPageItem->bandByType(BandDesignIntf::PageFooter);
|
|
if (pf && m_datasources->variable("#PAGE").toInt() != 1 && !isLast) {
|
|
renderPageFooter(m_patternPageItem);
|
|
} else {
|
|
if (pf && pf->property("printOnFirstPage").toBool()
|
|
&& m_datasources->variable("#PAGE").toInt() == 1) {
|
|
renderPageFooter(m_patternPageItem);
|
|
} else if (pf && pf->property("printOnLastPage").toBool() && isLast) {
|
|
renderPageFooter(m_patternPageItem);
|
|
}
|
|
}
|
|
|
|
if (m_pagesRanges.currentRange(m_patternPageItem->isTOC()).firstPage == 0) {
|
|
m_datasources->setReportVariable("#PAGE", 1);
|
|
} else {
|
|
m_datasources->setReportVariable("#PAGE", m_datasources->variable("#PAGE").toInt() + 1);
|
|
}
|
|
|
|
m_renderedPages.append(PageItemDesignIntf::Ptr(m_renderPageItem));
|
|
m_pageCount++;
|
|
emit pageRendered(m_pageCount);
|
|
|
|
if (isLast) {
|
|
BandDesignIntf* ph = m_renderPageItem->bandByType(BandDesignIntf::PageHeader);
|
|
if (ph && !ph->property("printOnLastPage").toBool()) {
|
|
delete ph;
|
|
}
|
|
}
|
|
|
|
if (m_renderPageItem->pageFooter()) {
|
|
m_renderPageItem->pageFooter()->setBandIndex(++m_currentIndex);
|
|
if (m_renderPageItem->pageFooter()->property("removeGap").toBool()) {
|
|
m_renderPageItem->pageFooter()->setPos(m_lastRenderedBand->geometry().bottomLeft());
|
|
}
|
|
}
|
|
m_renderPageItem->placeTearOffBand();
|
|
|
|
// m_scriptEngineContext->setCurrentPage(m_renderPageItem);
|
|
emit m_patternPageItem->afterRender();
|
|
if (isLast)
|
|
emit m_patternPageItem->afterLastPageRendered();
|
|
if (isLast && m_patternPageItem->endlessHeight()) {
|
|
qreal pageHeight = 0;
|
|
foreach (BandDesignIntf* band, m_renderPageItem->bands()) {
|
|
pageHeight += band->height();
|
|
}
|
|
m_renderPageItem->setHeight(
|
|
pageHeight + 10
|
|
+ (m_patternPageItem->topMargin() + m_patternPageItem->bottomMargin())
|
|
* Const::mmFACTOR);
|
|
}
|
|
}
|
|
|
|
QString ReportRender::toString()
|
|
{
|
|
QScopedPointer<ItemsWriterIntf> writer(new XMLWriter());
|
|
foreach (PageItemDesignIntf::Ptr page, m_renderedPages) {
|
|
writer->putItem(page.data());
|
|
}
|
|
return writer->saveToString();
|
|
}
|
|
|
|
ReportRender::~ReportRender() { m_renderedPages.clear(); }
|
|
|
|
void ReportRender::cancelRender() { m_renderCanceled = true; }
|
|
|
|
int PagesRanges::findLastPageNumber(int index)
|
|
{
|
|
index++;
|
|
foreach (PagesRange range, m_ranges) {
|
|
if (range.firstPage <= (index) && range.lastPage >= (index))
|
|
return (range.lastPage - (range.firstPage)) + 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int PagesRanges::findPageNumber(int index)
|
|
{
|
|
index++;
|
|
foreach (PagesRange range, m_ranges) {
|
|
if (range.firstPage <= (index) && range.lastPage >= (index))
|
|
return (index - range.firstPage) + 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
PagesRange& PagesRanges::currentRange(bool isTOC)
|
|
{
|
|
Q_ASSERT((isTOC && m_TOCRangeIndex != -1) || !isTOC);
|
|
if (isTOC && m_TOCRangeIndex != -1)
|
|
return m_ranges[m_TOCRangeIndex];
|
|
return m_ranges.last();
|
|
}
|
|
|
|
void PagesRanges::startNewRange(bool isTOC)
|
|
{
|
|
PagesRange range;
|
|
if (!m_ranges.isEmpty()) {
|
|
range.firstPage = 0;
|
|
range.lastPage = m_ranges.last().lastPage + 1;
|
|
} else {
|
|
range.firstPage = 0;
|
|
range.lastPage = 0;
|
|
}
|
|
range.isTOC = isTOC;
|
|
m_ranges.append(range);
|
|
if (isTOC)
|
|
m_TOCRangeIndex = m_ranges.size() - 1;
|
|
}
|
|
|
|
void PagesRanges::addTOCMarker(bool addNewRange)
|
|
{
|
|
if (addNewRange || m_ranges.isEmpty()) {
|
|
startNewRange(true);
|
|
} else {
|
|
m_TOCRangeIndex = m_ranges.size() - 1;
|
|
m_ranges.last().isTOC = true;
|
|
}
|
|
}
|
|
|
|
void PagesRanges::addPage()
|
|
{
|
|
if (m_ranges.isEmpty())
|
|
startNewRange();
|
|
if (m_ranges.last().firstPage == 0) {
|
|
m_ranges.last().firstPage = m_ranges.last().lastPage == 0 ? 1 : m_ranges.last().lastPage;
|
|
m_ranges.last().lastPage = m_ranges.last().lastPage == 0 ? 1 : m_ranges.last().lastPage;
|
|
} else {
|
|
m_ranges.last().lastPage++;
|
|
}
|
|
}
|
|
|
|
void PagesRanges::shiftRangesNextToTOC()
|
|
{
|
|
for (int i = m_TOCRangeIndex + 1; i < m_ranges.size(); ++i) {
|
|
m_ranges[i].firstPage++;
|
|
m_ranges[i].lastPage++;
|
|
}
|
|
}
|
|
|
|
void PagesRanges::addTOCPage()
|
|
{
|
|
Q_ASSERT(m_TOCRangeIndex != -1);
|
|
if (m_TOCRangeIndex != -1) {
|
|
PagesRange& tocRange = m_ranges[m_TOCRangeIndex];
|
|
if (tocRange.firstPage == 0) {
|
|
tocRange.firstPage = tocRange.lastPage == 0 ? 1 : tocRange.lastPage;
|
|
tocRange.lastPage = tocRange.lastPage == 0 ? 1 : tocRange.lastPage;
|
|
if (tocRange.firstPage == 1 && tocRange.lastPage == 1)
|
|
shiftRangesNextToTOC();
|
|
} else {
|
|
tocRange.lastPage++;
|
|
shiftRangesNextToTOC();
|
|
}
|
|
}
|
|
}
|
|
|
|
void PagesRanges::clear() { m_ranges.clear(); }
|
|
|
|
} // namespace LimeReport
|