From 992c53e19aeb50023ea37cfb9721549b344fbb52 Mon Sep 17 00:00:00 2001 From: Arin Alexander Date: Thu, 31 Aug 2017 02:53:34 +0300 Subject: [PATCH] TOC generation has been changed --- ...t1_report_header_group_subdetail_TOC.lrxml | 370 +++++++++++++----- include/lrdatasourcemanagerintf.h | 1 - include/lrglobal.h | 3 +- limereport/items/lrtextitem.cpp | 24 +- limereport/items/lrtextitem.h | 1 + limereport/lrbasedesignintf.h | 2 +- limereport/lrdatadesignintf.cpp | 54 ++- limereport/lrdatadesignintf.h | 4 + limereport/lrdatasourcemanager.cpp | 22 +- limereport/lrdatasourcemanager.h | 7 + limereport/lrdatasourcemanagerintf.h | 1 - limereport/lrglobal.h | 3 +- limereport/lritemdesignintf.cpp | 10 + limereport/lritemdesignintf.h | 10 +- limereport/lrpageitemdesignintf.cpp | 2 +- limereport/lrpageitemdesignintf.h | 4 +- limereport/lrreportengine.cpp | 28 +- limereport/lrreportrender.cpp | 53 ++- limereport/lrreportrender.h | 9 +- limereport/lrscriptenginemanager.cpp | 77 ++-- limereport/lrscriptenginemanager.h | 7 +- 21 files changed, 515 insertions(+), 177 deletions(-) diff --git a/demo_r1/demo_reports/demoReport1_report_header_group_subdetail_TOC.lrxml b/demo_r1/demo_reports/demoReport1_report_header_group_subdetail_TOC.lrxml index ca60553..732b484 100644 --- a/demo_r1/demo_reports/demoReport1_report_header_group_subdetail_TOC.lrxml +++ b/demo_r1/demo_reports/demoReport1_report_header_group_subdetail_TOC.lrxml @@ -1,27 +1,27 @@ - + - + page2 - + - + - + TOC - + - + DataBand1 - + - + TextItem1 - + @@ -37,7 +37,7 @@ - + @@ -49,18 +49,19 @@ - - + + + - + TextItem2 - + @@ -71,12 +72,19 @@ - $D{tableofcontens.Page number} + $S{ +getFieldByKeyField( + "tableofcontens", + "Page number", + "Content Key", + "$D{tableofcontens.Content Key}" +) +} - + @@ -96,6 +104,7 @@ + @@ -145,25 +154,25 @@ - + page1 - + - + - + ReportPage1 - + - + ReportHeader1 - + - + TextItem1 - + @@ -180,7 +189,7 @@ Report - + @@ -200,10 +209,11 @@ Report + - + ImageItem1 - + @@ -224,9 +234,9 @@ Report
- + ShapeItem1 - + @@ -246,9 +256,9 @@ Report - + ShapeItem2 - + @@ -268,9 +278,9 @@ Report - + TextItem9 - + @@ -286,7 +296,7 @@ Report - + @@ -306,10 +316,11 @@ Report + - + TextItem10 - + @@ -325,7 +336,7 @@ Report - + @@ -345,6 +356,7 @@ Report + @@ -354,7 +366,7 @@ Report - + @@ -363,13 +375,13 @@ Report - + DataBand1 - + - + TextItem3 - + @@ -385,7 +397,7 @@ Report - + @@ -405,10 +417,11 @@ Report + - + TextItem4 - + @@ -424,7 +437,7 @@ Report - + @@ -444,10 +457,11 @@ Report + - + TextItem12 - + @@ -463,7 +477,7 @@ Report - + @@ -483,10 +497,11 @@ Report + - + TextItem16 - + @@ -502,7 +517,7 @@ Report - + @@ -522,10 +537,11 @@ Report + - + TextItem17 - + @@ -541,7 +557,7 @@ Report - + @@ -561,6 +577,7 @@ Report + @@ -570,7 +587,7 @@ Report - + @@ -588,13 +605,13 @@ Report - + GroupBandHeader1 - + - + TextItem2 - + @@ -610,7 +627,7 @@ Report - + @@ -630,10 +647,11 @@ Report + - + ShapeItem3 - + @@ -653,9 +671,9 @@ Report - + TextItem11 - + @@ -671,7 +689,7 @@ Report - + @@ -691,6 +709,7 @@ Report + @@ -700,7 +719,7 @@ Report - + DataBand1 @@ -714,13 +733,13 @@ Report - + SubDetailBand1 - + - + TextItem5 - + @@ -736,7 +755,7 @@ Report - + @@ -756,10 +775,11 @@ Report + - + TextItem6 - + @@ -775,7 +795,7 @@ Report - + @@ -795,10 +815,11 @@ Report + - + TextItem7 - + @@ -814,7 +835,7 @@ Report - + @@ -834,10 +855,11 @@ Report + - + TextItem13 - + @@ -853,7 +875,7 @@ Report - + @@ -873,6 +895,7 @@ Report + @@ -882,7 +905,7 @@ Report - + DataBand1 @@ -896,13 +919,13 @@ Report - + SubDetailFooterBand1 - + - + TextItem8 - + @@ -918,7 +941,7 @@ Report - + @@ -938,10 +961,11 @@ Report + - + TextItem14 - + @@ -957,7 +981,7 @@ Report - + @@ -977,10 +1001,11 @@ Report + - + TextItem15 - + @@ -996,7 +1021,7 @@ Report - + @@ -1016,10 +1041,11 @@ Report + - + ShapeItem4 - + @@ -1047,7 +1073,7 @@ Report - + SubDetailBand1 @@ -1057,6 +1083,128 @@ Report + + PageFooter1 + + + + TextItem18 + + + + + PageFooter1 + + + + + + + Page $V{#PAGE} from $V{#PAGE_COUNT} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ReportPage1 + + + + + + + + + + + + + + + PageHeader18 + + + + TextItem19 + + + + + PageHeader18 + + + + + + + Page $V{#PAGE} from $V{#PAGE_COUNT} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ReportPage1 + + + + + + + + + + + + + @@ -1080,10 +1228,10 @@ Report - + datasources - + northwind QSQLITE @@ -1096,7 +1244,7 @@ Report - + orders Select * from orders @@ -1106,7 +1254,7 @@ limit 50 - + orderitems Select * from orderitems @@ -1119,18 +1267,26 @@ where orderid = $D{orders.orderid} - + - ReportPage1_DataBand1.bandRegistred.connect(SB1AfterData); -ReportPage1_SubDetailBand1.bandRegistred.connect(SB2AfterData); + ReportPage1_DataBand1.afterRender.connect(SB1AfterData); +ReportPage1_SubDetailBand1.afterRender.connect(SB2AfterData); +ReportPage1_GroupBandHeader1.afterRender.connect(SB3AfterData); + +var firstLevel = "&nbsp;&nbsp;&nbsp;&nbsp;"; +var secondLevel = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"; function SB1AfterData(){ - addTableOfContensItem(getField("orders.OrderID"),getField("orders.OrderID"), getVariable("#PAGE")); + addTableOfContensItem(getField("orders.OrderID"),firstLevel+getField("orders.OrderID")); } function SB2AfterData(){ - addTableOfContensItem(getField("orders.OrderID")+getField("orderItems.ProductName"), getField("orderItems.ProductName"), getVariable("#PAGE"), 5); + addTableOfContensItem(getField("orders.OrderID")+getField("orderItems.ProductName"), secondLevel+"<i>"+getField("orderItems.ProductName")+"</i>"); +} + +function SB3AfterData(){ + addTableOfContensItem(getField("orders.CompanyName"), "<b>"+getField("orders.CompanyName")+"</b>"); } diff --git a/include/lrdatasourcemanagerintf.h b/include/lrdatasourcemanagerintf.h index e3a6ce7..c0b345e 100644 --- a/include/lrdatasourcemanagerintf.h +++ b/include/lrdatasourcemanagerintf.h @@ -56,7 +56,6 @@ public: virtual void clearUserVariables()=0; virtual ICallbackDatasource* createCallbackDatasource(const QString& name) = 0; virtual void registerDbCredentialsProvider(IDbCredentialsProvider* provider) = 0; - //virtual void addCallbackDatasource(ICallbackDatasource* datasource, const QString& name) = 0; }; } diff --git a/include/lrglobal.h b/include/lrglobal.h index 297022d..a8ed17d 100644 --- a/include/lrglobal.h +++ b/include/lrglobal.h @@ -83,6 +83,7 @@ namespace Const{ const qreal SELECTION_OPACITY = 0.3; const QString FIELD_RX = "\\$D\\s*\\{\\s*([^{}]*)\\s*\\}"; const QString VARIABLE_RX = "\\$V\\s*\\{\\s*([^{}]*)\\s*\\}"; + const QString NAMED_VARIABLE_RX = "\\$V\\s*\\{\\s*(%1)\\s*\\}"; const QString SCRIPT_RX = "\\$S\\s*\\{(.*)\\}"; //const QString GROUP_FUNCTION_PARAM_RX = "\\(\\s*(((?:\\\"?\\$D\\s*\\{\\s*)|(?:\\\"?\\$V\\s*\\{\\s*)|(?:\\\"))(\\w+\\.?\\w+)((?:\\\")|(?:\\s*\\}\\\"?\\s*)))\\s*,\\s*\\\"(\\w+)\\\"\\s*\\)"; @@ -108,7 +109,7 @@ namespace Const{ QVector normalizeCaptures(const QRegExp ®); enum ExpandType {EscapeSymbols, NoEscapeSymbols, ReplaceHTMLSymbols}; - enum RenderPass {FirstPass, SecondPass}; + enum RenderPass {FirstPass = 1, SecondPass = 2}; enum ArrangeType {AsNeeded, Force}; enum PreviewHint{ShowAllPreviewBars = 0, HidePreviewToolBar = 1, diff --git a/limereport/items/lrtextitem.cpp b/limereport/items/lrtextitem.cpp index 3876496..4689ebb 100644 --- a/limereport/items/lrtextitem.cpp +++ b/limereport/items/lrtextitem.cpp @@ -339,7 +339,7 @@ void TextItem::updateLayout() bool TextItem::isNeedExpandContent() const { QRegExp rx("$*\\{[^{]*\\}"); - return content().contains(rx); + return content().contains(rx) || isContentBackedUp(); } QString TextItem::replaceBR(QString text) @@ -733,23 +733,35 @@ void TextItem::setAlignment(Qt::Alignment value) void TextItem::expandContent(DataSourceManager* dataManager, RenderPass pass) { QString context=content(); - ExpandType expandType = (allowHTML() && !allowHTMLInFields())?ReplaceHTMLSymbols:NoEscapeSymbols; + foreach (QString variableName, dataManager->variableNamesByRenderPass(SecondPass)) { + QRegExp rx(QString(Const::NAMED_VARIABLE_RX).arg(variableName)); + if (context.contains(rx) && pass == FirstPass){ + backupContent(); + break; + } + } + + ExpandType expandType = (allowHTML() && !allowHTMLInFields()) ? ReplaceHTMLSymbols : NoEscapeSymbols; switch(pass){ case FirstPass: if (!fillInSecondPass()){ context=expandUserVariables(context, pass, expandType, dataManager); context=expandScripts(context, dataManager); context=expandDataFields(context, expandType, dataManager); + } else { + context=expandDataFields(context, expandType, dataManager); } break; - case SecondPass:; + case SecondPass: + if (isContentBackedUp()) { + restoreContent(); + context = content(); + } context=expandUserVariables(context, pass, expandType, dataManager); context=expandScripts(context, dataManager); - if (fillInSecondPass()) - context=expandDataFields(context, expandType, dataManager); } - if (expandType == NoEscapeSymbols && !m_varValue.isNull() &&m_valueType!=Default) { + if (expandType == NoEscapeSymbols && !m_varValue.isNull() &&m_valueType != Default) { setContent(formatFieldValue()); } else { setContent(context); diff --git a/limereport/items/lrtextitem.h b/limereport/items/lrtextitem.h index 6dc735b..d8f3bd4 100644 --- a/limereport/items/lrtextitem.h +++ b/limereport/items/lrtextitem.h @@ -71,6 +71,7 @@ class TextItem : public LimeReport::ContentItemDesignIntf, IPageInit { Q_PROPERTY(BrushStyle backgroundBrushStyle READ backgroundBrushStyle WRITE setBackgroundBrushStyle) Q_PROPERTY(qreal textIndent READ textIndent WRITE setTextIndent) Q_PROPERTY(Qt::LayoutDirection textLayoutDirection READ textLayoutDirection WRITE setTextLayoutDirection) + Q_PROPERTY(bool fillInSecondPass READ fillInSecondPass WRITE setFillInSecondPass) public: enum AutoWidth{NoneAutoWidth,MaxWordLength,MaxStringLength}; diff --git a/limereport/lrbasedesignintf.h b/limereport/lrbasedesignintf.h index f3ce631..5e86669 100644 --- a/limereport/lrbasedesignintf.h +++ b/limereport/lrbasedesignintf.h @@ -96,7 +96,7 @@ class BaseDesignIntf : Q_PROPERTY(int borderLineSize READ borderLineSize WRITE setBorderLineSize) Q_PROPERTY(bool isVisible READ isVisible WRITE setItemVisible DESIGNABLE false) Q_PROPERTY(QColor borderColor READ borderColor WRITE setBorderColor) - Q_PROPERTY(bool fillInSecondPass READ fillInSecondPass WRITE setFillInSecondPass) + friend class ReportRender; public: enum BGMode { TransparentMode, OpaqueMode}; diff --git a/limereport/lrdatadesignintf.cpp b/limereport/lrdatadesignintf.cpp index 9f5e64d..3cdb434 100644 --- a/limereport/lrdatadesignintf.cpp +++ b/limereport/lrdatadesignintf.cpp @@ -291,6 +291,16 @@ QVariant ModelToDataSource::data(const QString &columnName) return m_model->data(m_model->index(currentRow(),columnIndexByName(columnName))); } +QVariant ModelToDataSource::dataByKeyField(const QString& columnName, const QString& keyColumnName, QVariant keyData) +{ + for( int i=0; i < m_model->rowCount(); ++i ){ + if (m_model->data(m_model->index(i, columnIndexByName(keyColumnName))) == keyData){ + return m_model->data(m_model->index(i, columnIndexByName(columnName))); + } + } + return QVariant(); +} + int ModelToDataSource::columnCount() { if (isInvalid()) return 0; @@ -702,17 +712,24 @@ void CallbackDatasource::first(){ else m_eof = !result; } +QVariant CallbackDatasource::callbackData(const QString& columnName, int row) +{ + CallbackInfo info; + QVariant result; + info.dataType = CallbackInfo::ColumnData; + info.columnName = columnName; + info.index = row; + emit getCallbackData(info, result); + return result; +} + QVariant CallbackDatasource::data(const QString& columnName) { QVariant result; if (!bof()) { if (!m_getDataFromCache){ - CallbackInfo info; - info.dataType = CallbackInfo::ColumnData; - info.columnName = columnName; - info.index = m_currentRow; - emit getCallbackData(info,result); + result = callbackData(columnName, m_currentRow); } else { result = m_valuesCache[columnName]; } @@ -720,6 +737,31 @@ QVariant CallbackDatasource::data(const QString& columnName) return result; } +QVariant CallbackDatasource::dataByKeyField(const QString& columnName, const QString& keyColumnName, QVariant keyData) +{ + int backupCurrentRow = m_currentRow; + int currentRow = 0; + QVariant result = QVariant(); + first(); + if (!checkIfEmpty()){ + do { + QVariant key = callbackData(keyColumnName, currentRow); + if (key == keyData){ + result = callbackData(columnName, currentRow); + break; + } + currentRow++; + } while (next()); + } + + first(); + if (backupCurrentRow != -1){ + for (int i = 0; i < backupCurrentRow; ++i) + next(); + } + return result; +} + int CallbackDatasource::columnCount(){ CallbackInfo info; if (m_columnCount == -1){ @@ -781,7 +823,7 @@ int CallbackDatasource::columnIndexByName(QString name) bool CallbackDatasource::checkNextRecord(int recordNum){ if (bof()) checkIfEmpty(); if (m_rowCount > 0) { - return (m_currentRow < (m_rowCount-1)); + return (recordNum < (m_rowCount-1)); } else { QVariant result = false; CallbackInfo info; diff --git a/limereport/lrdatadesignintf.h b/limereport/lrdatadesignintf.h index e51a3af..3a91a30 100644 --- a/limereport/lrdatadesignintf.h +++ b/limereport/lrdatadesignintf.h @@ -58,6 +58,7 @@ public: virtual bool bof() = 0; virtual bool eof() = 0; virtual QVariant data(const QString& columnName) = 0; + virtual QVariant dataByKeyField(const QString& columnName, const QString& keyColumnName, QVariant keyData) = 0; virtual int columnCount() = 0; virtual QString columnNameByIndex(int columnIndex) = 0; virtual int columnIndexByName(QString name) = 0; @@ -359,6 +360,7 @@ public: bool eof(); bool bof(); QVariant data(const QString& columnName); + QVariant dataByKeyField(const QString& columnName, const QString& keyColumnName, QVariant keyData); int columnCount(); QString columnNameByIndex(int columnIndex); int columnIndexByName(QString name); @@ -390,6 +392,7 @@ public: bool bof(){return m_currentRow == -1;} bool eof(){return m_eof;} QVariant data(const QString &columnName); + QVariant dataByKeyField(const QString& columnName, const QString& keyColumnName, QVariant keyData); int columnCount(); QString columnNameByIndex(int columnIndex); int columnIndexByName(QString name); @@ -407,6 +410,7 @@ private: int m_rowCount; QHash m_valuesCache; bool m_getDataFromCache; + QVariant callbackData(const QString& columnName, int row); }; class CallbackDatasourceHolder :public QObject, public IDataSourceHolder{ diff --git a/limereport/lrdatasourcemanager.cpp b/limereport/lrdatasourcemanager.cpp index 83b438c..09cf5c6 100644 --- a/limereport/lrdatasourcemanager.cpp +++ b/limereport/lrdatasourcemanager.cpp @@ -224,7 +224,7 @@ DataSourceManager::DataSourceManager(QObject *parent) : m_groupFunctionFactory.registerFunctionCreator(QLatin1String("AVG"),new ConstructorGroupFunctionCreator); m_groupFunctionFactory.registerFunctionCreator(QLatin1String("MIN"),new ConstructorGroupFunctionCreator); m_groupFunctionFactory.registerFunctionCreator(QLatin1String("MAX"),new ConstructorGroupFunctionCreator); - setSystemVariable(QLatin1String("#PAGE"),1,FirstPass); + setSystemVariable(QLatin1String("#PAGE"),1,SecondPass); setSystemVariable(QLatin1String("#PAGE_COUNT"),0,SecondPass); setSystemVariable(QLatin1String("#IS_LAST_PAGEFOOTER"),false,FirstPass); setSystemVariable(QLatin1String("#IS_FIRST_PAGEFOOTER"),false,FirstPass); @@ -1377,6 +1377,15 @@ QVariant DataSourceManager::fieldData(const QString &fieldName) return QVariant(); } +QVariant DataSourceManager::fieldDataByKey(const QString& datasourceName, const QString& valueFieldName, const QString& keyFieldName, QVariant keyValue) +{ + IDataSource* ds = dataSource(datasourceName); + if (ds){ + return ds->dataByKeyField(valueFieldName, keyFieldName, keyValue); + } + return QVariant(); +} + QVariant DataSourceManager::variable(const QString &variableName) { if (m_userVariables.containsVariable(variableName)) @@ -1403,6 +1412,17 @@ QStringList DataSourceManager::variableNames() return m_reportVariables.variableNames(); } +QStringList DataSourceManager::variableNamesByRenderPass(RenderPass pass) +{ + QStringList result; + foreach(QString variableName, m_reportVariables.variableNames()){ + if (m_reportVariables.variablePass(variableName) == pass){ + result.append(variableName); + } + } + return result; +} + QStringList DataSourceManager::namesOfUserVariables(){ return m_userVariables.variableNames(); } diff --git a/limereport/lrdatasourcemanager.h b/limereport/lrdatasourcemanager.h index ea77064..5483b55 100644 --- a/limereport/lrdatasourcemanager.h +++ b/limereport/lrdatasourcemanager.h @@ -126,6 +126,7 @@ public: QVariant variable(const QString& variableName); RenderPass variablePass(const QString& name); QStringList variableNames(); + QStringList variableNamesByRenderPass(RenderPass pass); QStringList namesOfUserVariables(); VarDesc::VarType variableType(const QString& name); bool variableIsSystem(const QString& name); @@ -161,6 +162,12 @@ public: QStringList fieldNames(const QString& datasourceName); bool containsField(const QString& fieldName); QVariant fieldData(const QString& fieldName); + QVariant fieldDataByKey( + const QString& datasourceName, + const QString& valueFieldName, + const QString& keyFieldName, + QVariant keyValue + ); QString extractDataSource(const QString& fieldName); QString extractFieldName(const QString& fieldName); diff --git a/limereport/lrdatasourcemanagerintf.h b/limereport/lrdatasourcemanagerintf.h index e3a6ce7..c0b345e 100644 --- a/limereport/lrdatasourcemanagerintf.h +++ b/limereport/lrdatasourcemanagerintf.h @@ -56,7 +56,6 @@ public: virtual void clearUserVariables()=0; virtual ICallbackDatasource* createCallbackDatasource(const QString& name) = 0; virtual void registerDbCredentialsProvider(IDbCredentialsProvider* provider) = 0; - //virtual void addCallbackDatasource(ICallbackDatasource* datasource, const QString& name) = 0; }; } diff --git a/limereport/lrglobal.h b/limereport/lrglobal.h index 297022d..a8ed17d 100644 --- a/limereport/lrglobal.h +++ b/limereport/lrglobal.h @@ -83,6 +83,7 @@ namespace Const{ const qreal SELECTION_OPACITY = 0.3; const QString FIELD_RX = "\\$D\\s*\\{\\s*([^{}]*)\\s*\\}"; const QString VARIABLE_RX = "\\$V\\s*\\{\\s*([^{}]*)\\s*\\}"; + const QString NAMED_VARIABLE_RX = "\\$V\\s*\\{\\s*(%1)\\s*\\}"; const QString SCRIPT_RX = "\\$S\\s*\\{(.*)\\}"; //const QString GROUP_FUNCTION_PARAM_RX = "\\(\\s*(((?:\\\"?\\$D\\s*\\{\\s*)|(?:\\\"?\\$V\\s*\\{\\s*)|(?:\\\"))(\\w+\\.?\\w+)((?:\\\")|(?:\\s*\\}\\\"?\\s*)))\\s*,\\s*\\\"(\\w+)\\\"\\s*\\)"; @@ -108,7 +109,7 @@ namespace Const{ QVector normalizeCaptures(const QRegExp ®); enum ExpandType {EscapeSymbols, NoEscapeSymbols, ReplaceHTMLSymbols}; - enum RenderPass {FirstPass, SecondPass}; + enum RenderPass {FirstPass = 1, SecondPass = 2}; enum ArrangeType {AsNeeded, Force}; enum PreviewHint{ShowAllPreviewBars = 0, HidePreviewToolBar = 1, diff --git a/limereport/lritemdesignintf.cpp b/limereport/lritemdesignintf.cpp index a830c96..e9363e0 100644 --- a/limereport/lritemdesignintf.cpp +++ b/limereport/lritemdesignintf.cpp @@ -122,4 +122,14 @@ QMap ContentItemDesignIntf::getStringForTranslation(){ return map; } +bool ContentItemDesignIntf::isContentBackedUp() const +{ + return m_contentBackedUp; +} + +void ContentItemDesignIntf::setContentBackedUp(bool contentBackedUp) +{ + m_contentBackedUp = contentBackedUp; +} + }// namespace LimeReport diff --git a/limereport/lritemdesignintf.h b/limereport/lritemdesignintf.h index f07fd9f..44f0363 100644 --- a/limereport/lritemdesignintf.h +++ b/limereport/lritemdesignintf.h @@ -61,6 +61,7 @@ private: class Spacer :public ItemDesignIntf{ public: Spacer(QObject* owner,QGraphicsItem* parent); + bool isEmpty() const {return true;} protected: BaseDesignIntf* createSameTypeItem(QObject *owner, QGraphicsItem *parent){ return new Spacer(owner, parent); @@ -72,10 +73,17 @@ class ContentItemDesignIntf : public ItemDesignIntf Q_OBJECT public: ContentItemDesignIntf(const QString& xmlTypeName, QObject* owner = 0,QGraphicsItem* parent = 0) - :ItemDesignIntf(xmlTypeName,owner,parent){} + :ItemDesignIntf(xmlTypeName,owner,parent), m_contentBackedUp(false){} virtual QString content() const = 0; virtual void setContent(const QString& value) = 0; QMap getStringForTranslation(); + void backupContent(){ m_contentBackUp = content(); m_contentBackedUp = true;} + void restoreContent() {setContent(m_contentBackUp);} + bool isContentBackedUp() const; + void setContentBackedUp(bool contentBackedUp); +private: + QString m_contentBackUp; + bool m_contentBackedUp; }; class LayoutDesignIntf : public ItemDesignIntf{ diff --git a/limereport/lrpageitemdesignintf.cpp b/limereport/lrpageitemdesignintf.cpp index 95b9144..ac7b5b6 100644 --- a/limereport/lrpageitemdesignintf.cpp +++ b/limereport/lrpageitemdesignintf.cpp @@ -331,7 +331,7 @@ void PageItemDesignIntf::initColumnsPos(QVector &posByColumns, qreal pos, } } -bool PageItemDesignIntf::getIsTOC() const +bool PageItemDesignIntf::isTOC() const { return m_isTOC; } diff --git a/limereport/lrpageitemdesignintf.h b/limereport/lrpageitemdesignintf.h index c39788a..d484492 100644 --- a/limereport/lrpageitemdesignintf.h +++ b/limereport/lrpageitemdesignintf.h @@ -55,7 +55,7 @@ class PageItemDesignIntf : public LimeReport::ItemsContainerDesignInft Q_PROPERTY(bool resetPageNumber READ resetPageNumber WRITE setResetPageNumber) Q_PROPERTY(bool isExtendedInDesignMode READ isExtendedInDesignMode WRITE setExtendedInDesignMode) Q_PROPERTY(int extendedHeight READ extendedHeight WRITE setExtendedHeight) - Q_PROPERTY(bool pageIsTOC READ getIsTOC WRITE setIsTOC) + Q_PROPERTY(bool pageIsTOC READ isTOC WRITE setIsTOC) friend class ReportRender; public: enum Orientation { Portrait, Landscape }; @@ -127,7 +127,7 @@ public: int extendedHeight() const; void setExtendedHeight(int extendedHeight); - bool getIsTOC() const; + bool isTOC() const; void setIsTOC(bool isTOC); signals: void beforeFirstPageRendered(); diff --git a/limereport/lrreportengine.cpp b/limereport/lrreportengine.cpp index f47f7e3..e582fc2 100644 --- a/limereport/lrreportengine.cpp +++ b/limereport/lrreportengine.cpp @@ -914,29 +914,35 @@ ReportPages ReportEnginePrivate::renderToPages() emit renderStarted(); foreach(PageDesignIntf* page , m_pages){ - if (!page->pageItem()->getIsTOC()){ + if (!page->pageItem()->isTOC()){ page->setReportSettings(&m_reportSettings); result.append(m_reportRender->renderPageToPages(page)); } } - bool isFirst = true; // m_reportRender->secondRenderPass(result); - foreach(PageDesignIntf* page , m_pages){ - if (page->pageItem()->getIsTOC()){ + for (int i=0; ipageItem()->isTOC()){ page->setReportSettings(&m_reportSettings); - if (isFirst){ - ReportPages pages = m_reportRender->renderPageToPages(page); - for (int i=0; i1) secondPage = m_pages.at(1); + ReportPages pages = m_reportRender->renderTOC( + page, + true, + secondPage && secondPage->pageItem()->resetPageNumber() + ); + for (int j=0; jrenderPageToPages(page)); + } } - isFirst = false; } m_reportRender->secondRenderPass(result); diff --git a/limereport/lrreportrender.cpp b/limereport/lrreportrender.cpp index 8b64082..cd701c7 100644 --- a/limereport/lrreportrender.cpp +++ b/limereport/lrreportrender.cpp @@ -148,7 +148,7 @@ void ReportRender::renameChildItems(BaseDesignIntf *item){ ReportRender::ReportRender(QObject *parent) :QObject(parent), m_renderPageItem(0), m_pageCount(0), - m_lastDataBand(0), m_lastRenderedFooter(0), m_currentColumn(0) + m_lastDataBand(0), m_lastRenderedFooter(0), m_currentColumn(0), m_renderingFirstTOC(false) { initColumns(); } @@ -188,15 +188,24 @@ void ReportRender::initDatasource(const QString& name){ } } -void ReportRender::renderPage(PageDesignIntf* patternPage) +void ReportRender::renderPage(PageDesignIntf* patternPage, bool isTOC, bool isFirst, bool resetPageNumbers) { m_curentNameIndex = 0; m_patternPageItem = patternPage->pageItem(); + m_renderingFirstTOC = isTOC && isFirst; - if (m_patternPageItem->resetPageNumber() && m_pageCount>0) { + if (m_patternPageItem->resetPageNumber() && m_pageCount>0 && !isTOC) { resetPageNumber(PageReset); } + if (m_renderingFirstTOC && resetPageNumbers){ + PagesRange range; + range.firstPage = 0; + range.lastPage = 0; + m_ranges.insert(0,range); + m_pageCount = 0; + } + m_renderCanceled = false; BandDesignIntf* reportFooter = m_patternPageItem->bandByType(BandDesignIntf::ReportFooter); m_reportFooterHeight = 0; @@ -238,6 +247,12 @@ void ReportRender::renderPage(PageDesignIntf* patternPage) renderBand(tearOffBand, 0, StartNewPageAsNeeded); savePage(true); + + if (m_renderingFirstTOC && resetPageNumbers && m_ranges.count()>1){ + m_ranges[1].firstPage = m_ranges.at(0).lastPage+1; + m_ranges[1].lastPage += m_ranges.at(0).lastPage+1; + } + #ifndef USE_QJSENGINE ScriptEngineManager::instance().scriptEngine()->popContext(); #endif @@ -267,6 +282,11 @@ ReportPages ReportRender::renderPageToPages(PageDesignIntf *patternPage) return m_renderedPages; } +ReportPages ReportRender::renderTOC(PageDesignIntf* patternPage, bool first, bool resetPages){ + renderPage(patternPage, true, first, resetPages); + return m_renderedPages; +} + void ReportRender::initRenderPage() { if (!m_renderPageItem) { @@ -1038,11 +1058,21 @@ void ReportRender::updateTOC(BaseDesignIntf* item, int pageNumber){ void ReportRender::secondRenderPass(ReportPages renderedPages) { + + if (!m_scriptEngineContext->tableOfContens()->isEmpty()){ + for(int i=0; ichildBaseItems()){ + updateTOC(item, findPageNumber(i)); + } + } + } + for(int i=0; isetReportVariable("#PAGE",findPageNumber(i)); m_datasources->setReportVariable("#PAGE_COUNT",findLastPageNumber(i)); foreach(BaseDesignIntf* item, page->childBaseItems()){ - if (!m_scriptEngineContext->tableOfContens()->isEmpty()) updateTOC(item, i+1); item->updateItemSize(m_datasources, SecondPass); } } @@ -1155,7 +1185,7 @@ void ReportRender::resetPageNumber(ResetPageNuberType resetType) { PagesRange range; if (!m_ranges.isEmpty()){ - m_ranges.last().lastPage = (resetType == BandReset)? m_pageCount : m_pageCount-1; + currentRange().lastPage = (resetType == BandReset)? m_pageCount : m_pageCount-1; range.firstPage = m_pageCount+((resetType == BandReset)? 1 : 0); } else { range.firstPage = m_pageCount; @@ -1175,6 +1205,15 @@ int ReportRender::findLastPageNumber(int currentPage) return 0; } +int ReportRender::findPageNumber(int currentPage) +{ + foreach (PagesRange range, m_ranges) { + if ( range.firstPage<= (currentPage) && range.lastPage>= (currentPage) ) + return (currentPage - range.firstPage)+1; + } + return 0; +} + void ReportRender::cutGroups() { m_popupedExpression.clear(); @@ -1302,13 +1341,13 @@ void ReportRender::savePage(bool isLast) } } - if (m_ranges.last().lastPage==0 && m_ranges.count()>1) { + if (currentRange(m_renderingFirstTOC).lastPage==0 && m_ranges.count()>1) { m_datasources->setReportVariable("#PAGE",1); } else { m_datasources->setReportVariable("#PAGE",m_datasources->variable("#PAGE").toInt()+1); } - m_ranges.last().lastPage = m_pageCount; + currentRange(m_renderingFirstTOC).lastPage = m_pageCount; BandDesignIntf* pageFooter = m_renderPageItem->bandByType(BandDesignIntf::PageFooter); if (pageFooter) pageFooter->setBandIndex(++m_currentIndex); diff --git a/limereport/lrreportrender.h b/limereport/lrreportrender.h index a0a72db..182a8fb 100644 --- a/limereport/lrreportrender.h +++ b/limereport/lrreportrender.h @@ -82,6 +82,7 @@ public: PageItemDesignIntf::Ptr pageAt(int index); QString renderPageToString(PageDesignIntf *patternPage); ReportPages renderPageToPages(PageDesignIntf *patternPage); + ReportPages renderTOC(PageDesignIntf* patternPage, bool first, bool resetPages); void secondRenderPass(ReportPages renderedPages); signals: void pageRendered(int renderedPageCount); @@ -95,7 +96,7 @@ private: void initGroups(); void clearPageMap(); - void renderPage(PageDesignIntf *patternPage); + void renderPage(PageDesignIntf *patternPage, bool isTOC = false, bool isFirst = false, bool resetPageNumbers = false); BandDesignIntf* renderBand(BandDesignIntf *patternBand, BandDesignIntf *bandData, DataRenderMode mode = NotStartNewPage, bool isLast = false); void renderDataBand(BandDesignIntf* dataBand); void renderPageHeader(PageItemDesignIntf* patternPage); @@ -147,6 +148,7 @@ private: void startNewPage(bool isFirst = false); void resetPageNumber(ResetPageNuberType resetType); int findLastPageNumber(int currentPage); + int findPageNumber(int currentPage); void savePage(bool isLast = false); QString toString(); void initColumns(); @@ -159,6 +161,7 @@ private: void renameChildItems(BaseDesignIntf *item); void renderGroupFooterByHeader(BandDesignIntf *groupHeader); void updateTOC(BaseDesignIntf* item, int pageNumber); + PagesRange& currentRange(bool isTOC = false){ return (isTOC) ? m_ranges.first(): m_ranges.last();} private: DataSourceManager* m_datasources; ScriptEngineContext* m_scriptEngineContext; @@ -188,9 +191,7 @@ private: QList m_ranges; QVector m_columnedBandItems; unsigned long long m_curentNameIndex; - - - + bool m_renderingFirstTOC; }; } // namespace LimeReport #endif // LRREPORTRENDER_H diff --git a/limereport/lrscriptenginemanager.cpp b/limereport/lrscriptenginemanager.cpp index 1496021..9fc11f3 100644 --- a/limereport/lrscriptenginemanager.cpp +++ b/limereport/lrscriptenginemanager.cpp @@ -364,21 +364,21 @@ QString ScriptEngineManager::expandUserVariables(QString context, RenderPass pas pos += rx.matchedLength(); if (dataManager()->containsVariable(variable) ){ try { - if (pass==dataManager()->variablePass(variable)){ - varValue = dataManager()->variable(variable); - switch (expandType){ - case EscapeSymbols: - context.replace(rx.cap(0),escapeSimbols(varValue.toString())); - break; - case NoEscapeSymbols: - context.replace(rx.cap(0),varValue.toString()); - break; - case ReplaceHTMLSymbols: - context.replace(rx.cap(0),replaceHTMLSymbols(varValue.toString())); - break; - } - pos=0; + + varValue = dataManager()->variable(variable); + switch (expandType){ + case EscapeSymbols: + context.replace(rx.cap(0),escapeSimbols(varValue.toString())); + break; + case NoEscapeSymbols: + context.replace(rx.cap(0),varValue.toString()); + break; + case ReplaceHTMLSymbols: + context.replace(rx.cap(0),replaceHTMLSymbols(varValue.toString())); + break; } + pos=0; + } catch (ReportError e){ dataManager()->putError(e.what()); if (!dataManager()->reportSettings() || dataManager()->reportSettings()->suppressAbsentFieldsAndVarsWarnings()) @@ -540,12 +540,12 @@ QVariant ScriptEngineManager::evaluateScript(const QString& script){ return QVariant(); } -void ScriptEngineManager::addTableOfContensItem(const QString& uniqKey, const QString& content, int pageNumber, int indent) +void ScriptEngineManager::addTableOfContensItem(const QString& uniqKey, const QString& content, int indent) { Q_ASSERT(m_context != 0); if (m_context){ BandDesignIntf* currentBand = m_context->getCurrentBand(); - m_context->tableOfContens()->setItem(uniqKey, content, pageNumber, indent); + m_context->tableOfContens()->setItem(uniqKey, content, 0, indent); if (currentBand) currentBand->addBookmark(uniqKey, content); } @@ -764,6 +764,25 @@ bool ScriptEngineManager::createGetFieldFunction() return addFunction(fd); } +bool ScriptEngineManager::createGetFieldByKeyFunction() +{ + JSFunctionDesc fd; + fd.setManager(m_functionManager); + fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME); + fd.setCategory(tr("GENERAL")); + fd.setName("getFieldByKeyField"); + fd.setDescription("getFieldByKeyField(\""+tr("Datasource")+"\", \""+ + tr("ValueField")+"\",\""+ + tr("KeyField")+"\", \""+ + tr("KeyFieldValue")+"\")" + ); + fd.setScriptWrapper(QString("function getFieldByKeyField(datasource, valueFieldName, keyFieldName, keyValue){" + "return %1.getFieldByKeyField(datasource, valueFieldName, keyFieldName, keyValue);}" + ).arg(LimeReport::Const::FUNCTION_MANAGER_NAME) + ); + return addFunction(fd); +} + bool ScriptEngineManager::createAddTableOfContensItemFunction() { JSFunctionDesc fd; @@ -771,9 +790,9 @@ bool ScriptEngineManager::createAddTableOfContensItemFunction() fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME); fd.setCategory(tr("GENERAL")); fd.setName("addTableOfContensItem"); - fd.setDescription("addTableOfContensItem(\""+tr("Unique identifier")+" \""+tr("Content")+"\", \""+tr("Page Number")+", \""+tr("Indent")+"\")"); - fd.setScriptWrapper(QString("function addTableOfContensItem(uniqKey, content, pageNumber, indent){" - "return %1.addTableOfContensItem(uniqKey, content, pageNumber, indent);}" + fd.setDescription("addTableOfContensItem(\""+tr("Unique identifier")+" \""+tr("Content")+"\", \""+tr("Indent")+"\")"); + fd.setScriptWrapper(QString("function addTableOfContensItem(uniqKey, content, indent){" + "return %1.addTableOfContensItem(uniqKey, content, indent);}" ).arg(LimeReport::Const::FUNCTION_MANAGER_NAME) ); return addFunction(fd); @@ -814,6 +833,7 @@ ScriptEngineManager::ScriptEngineManager() #endif createSetVariableFunction(); createGetFieldFunction(); + createGetFieldByKeyFunction(); createGetVariableFunction(); #ifndef USE_QJSENGINE QScriptValue colorCtor = m_scriptEngine->newFunction(constructColor); @@ -1466,9 +1486,15 @@ QVariant ScriptFunctionsManager::getField(const QString &field) return dm->fieldData(field); } -void ScriptFunctionsManager::addTableOfContensItem(const QString& uniqKey, const QString& content, int pageNumber, int indent) +QVariant ScriptFunctionsManager::getFieldByKeyField(const QString& datasourceName, const QString& valueFieldName, const QString& keyFieldName, QVariant keyValue) { - scriptEngineManager()->addTableOfContensItem(uniqKey, content, pageNumber, indent); + DataSourceManager* dm = scriptEngineManager()->dataManager(); + return dm->fieldDataByKey(datasourceName, valueFieldName, keyFieldName, keyValue); +} + +void ScriptFunctionsManager::addTableOfContensItem(const QString& uniqKey, const QString& content, int indent) +{ + scriptEngineManager()->addTableOfContensItem(uniqKey, content, indent); } void ScriptFunctionsManager::clearTableOfContens() @@ -1532,6 +1558,7 @@ void TableOfContens::setItem(const QString& uniqKey, const QString& content, int item->content = content; item->pageNumber = pageNumber; item->indent = indent; + item->uniqKey = uniqKey; m_tableOfContens.append(item); m_hash.insert(uniqKey, item); } @@ -1541,7 +1568,7 @@ void TableOfContens::setItem(const QString& uniqKey, const QString& content, int void TableOfContens::slotOneSlotDS(CallbackInfo info, QVariant& data) { QStringList columns; - columns << "Content" << "Page number"; + columns << "Content" << "Page number" << "Content Key"; switch (info.dataType) { case LimeReport::CallbackInfo::RowCount: @@ -1557,9 +1584,11 @@ void TableOfContens::slotOneSlotDS(CallbackInfo info, QVariant& data) case LimeReport::CallbackInfo::ColumnData: if (info.index < m_tableOfContens.count()){ ContentItem* item = m_tableOfContens.at(info.index); - if (info.columnName == "Content") + if (info.columnName.compare("Content",Qt::CaseInsensitive) == 0) data = item->content.rightJustified(item->indent+item->content.size()); - else + if (info.columnName.compare("Content Key",Qt::CaseInsensitive) == 0) + data = item->uniqKey; + if (info.columnName.compare("Page number",Qt::CaseInsensitive) == 0) data = QString::number(item->pageNumber); } break; diff --git a/limereport/lrscriptenginemanager.h b/limereport/lrscriptenginemanager.h index e8ce2f6..717a693 100644 --- a/limereport/lrscriptenginemanager.h +++ b/limereport/lrscriptenginemanager.h @@ -63,6 +63,7 @@ struct ContentItem { QString content; int indent; int pageNumber; + QString uniqKey; }; class TableOfContens : public QObject{ @@ -278,8 +279,9 @@ public: Q_INVOKABLE void setVariable(const QString& name, QVariant value); Q_INVOKABLE QVariant getVariable(const QString& name); Q_INVOKABLE QVariant getField(const QString& field); + Q_INVOKABLE QVariant getFieldByKeyField(const QString& datasourceName, const QString& valueFieldName, const QString& keyFieldName, QVariant keyValue); Q_INVOKABLE QVariant color(const QString& color){ return QColor(color);} - Q_INVOKABLE void addTableOfContensItem(const QString& uniqKey, const QString& content, int pageNumber, int indent = 0); + Q_INVOKABLE void addTableOfContensItem(const QString& uniqKey, const QString& content, int indent = 0); Q_INVOKABLE void clearTableOfContens(); #ifdef USE_QJSENGINE Q_INVOKABLE QFont font(const QString& family, int pointSize = -1, bool bold = false, bool italic = false, bool underLine = false); @@ -320,7 +322,7 @@ public: QString expandDataFields(QString context, ExpandType expandType, QVariant &varValue, QObject* reportItem); QString expandScripts(QString context, QVariant &varValue, QObject* reportItem); QVariant evaluateScript(const QString &script); - void addTableOfContensItem(const QString& uniqKey, const QString& content, int pageNumber, int indent); + void addTableOfContensItem(const QString& uniqKey, const QString& content, int indent); void clearTableOfContens(); protected: @@ -340,6 +342,7 @@ private: bool createSetVariableFunction(); bool createGetVariableFunction(); bool createGetFieldFunction(); + bool createGetFieldByKeyFunction(); bool createAddTableOfContensItemFunction(); bool createClearTableOfContensFunction(); private: