From afc8ad77b26379cc46b5234b75f2733cfa97e9db Mon Sep 17 00:00:00 2001 From: Arin Alexander Date: Sat, 28 Jan 2017 02:20:15 +0300 Subject: [PATCH] Group functions have been refactored. From now they can use script expression in value parameter --- include/lrglobal.cpp | 16 +++ include/lrglobal.h | 14 ++- limereport/lrbasedesignintf.cpp | 144 ++--------------------- limereport/lrbasedesignintf.h | 10 +- limereport/lrdatasourcemanager.cpp | 33 ++++++ limereport/lrdatasourcemanager.h | 13 +++ limereport/lrglobal.cpp | 16 +++ limereport/lrglobal.h | 14 ++- limereport/lrgroupfunctions.cpp | 64 ++++++++--- limereport/lrgroupfunctions.h | 2 +- limereport/lrreportengine.cpp | 3 +- limereport/lrreportrender.cpp | 6 +- limereport/lrscriptenginemanager.cpp | 165 ++++++++++++++++++++++++++- limereport/lrscriptenginemanager.h | 5 + 14 files changed, 333 insertions(+), 172 deletions(-) diff --git a/include/lrglobal.cpp b/include/lrglobal.cpp index 47b31f0..5b2cdff 100644 --- a/include/lrglobal.cpp +++ b/include/lrglobal.cpp @@ -51,4 +51,20 @@ void ReportSettings::setSuppressAbsentFieldsAndVarsWarnings(bool suppressAbsentF m_suppressAbsentFieldsAndVarsWarnings = suppressAbsentFieldsAndVarsWarnings; } +QString escapeSimbols(const QString &value) +{ + QString result = value; + result.replace("\"","\\\""); + result.replace('\n',"\\n"); + return result; +} + +QString replaceHTMLSymbols(const QString &value) +{ + QString result = value; + result.replace("<","<"); + result.replace(">",">"); + return result; +} + } //namespace LimeReport diff --git a/include/lrglobal.h b/include/lrglobal.h index 3a01927..3b8aa7d 100644 --- a/include/lrglobal.h +++ b/include/lrglobal.h @@ -82,16 +82,21 @@ namespace Const{ //const int DATASOURCE_INDEX = 6; //const int VALUE_INDEX = 2; - const QString GROUP_FUNCTION_PARAM_RX = "\\(\\s*(?:(?:((?:(?:\\\"?\\$D\\s*\\{\\s*)|(?:\\\"?\\$V\\s*\\{\\s*)|(?:\\\"))((?:\\w+\\.?\\w+)|(?:\\w+))(?:(?:\\\")|(?:\\s*\\}\\\"?\\s*)))\\s*,)|(?:))\\s*\\\"(\\w+)\\\"\\s*\\)"; - const int DATASOURCE_INDEX = 4; - const int VALUE_INDEX = 2; - const int EXPRESSION_ARGUMENT_INDEX = 3; + //const QString GROUP_FUNCTION_PARAM_RX = "\\(\\s*(?:(?:((?:(?:\\\"?\\$D\\s*\\{\\s*)|(?:\\\"?\\$V\\s*\\{\\s*)|(?:\\\"?\\$S\\s*\\{\\s*)|(?:\\\"))((?:\\w+\\.?\\w+)|(?:\\w+))(?:(?:\\\")|(?:\\s*\\}\\\"?\\s*)))\\s*,)|(?:))\\s*\\\"(\\w+)\\\"\\s*\\)"; + const QString GROUP_FUNCTION_PARAM_RX = "\\((?:(.+),|(?:))(?:\\\"(\\w+)\\\")\\)"; + const int DATASOURCE_INDEX = 3;//4; + const int VALUE_INDEX = 2; //2; + const int EXPRESSION_ARGUMENT_INDEX = 1;//3; const QString GROUP_FUNCTION_RX = "(%1\\s*"+GROUP_FUNCTION_PARAM_RX+")"; const QString GROUP_FUNCTION_NAME_RX = "%1\\s*\\((.*[^\\)])\\)"; const int SCENE_MARGIN = 50; } QString extractClassName(QString className); + QString escapeSimbols(const QString& value); + QString replaceHTMLSymbols(const QString &value); + + enum ExpandType {EscapeSymbols, NoEscapeSymbols, ReplaceHTMLSymbols}; enum RenderPass {FirstPass, SecondPass}; enum ArrangeType {AsNeeded, Force}; enum PreviewHint{ShowAllPreviewBars = 0, @@ -100,6 +105,7 @@ namespace Const{ HidePreviewStatusBar = 4, HideAllPreviewBar = 7, PreviewBarsUserSetting = 8}; + Q_DECLARE_FLAGS(PreviewHints, PreviewHint) Q_FLAGS(PreviewHints) diff --git a/limereport/lrbasedesignintf.cpp b/limereport/lrbasedesignintf.cpp index 77967f4..f0f7e2b 100644 --- a/limereport/lrbasedesignintf.cpp +++ b/limereport/lrbasedesignintf.cpp @@ -34,7 +34,6 @@ #include "lrreportdesignwidget.h" #include "qgraphicsitem.h" #include "lrdesignelementsfactory.h" - #include "lrhorizontallayout.h" #include @@ -241,150 +240,29 @@ QFont BaseDesignIntf::transformToSceneFont(const QFont& value) const return f; } -QString BaseDesignIntf::escapeSimbols(const QString &value) -{ - QString result = value; - result.replace("\"","\\\""); - result.replace('\n',"\\n"); - return result; -} - -QString BaseDesignIntf::replaceHTMLSymbols(const QString &value) -{ - QString result = value; - result.replace("<","<"); - result.replace(">",">"); - return result; -} - QString BaseDesignIntf::expandDataFields(QString context, ExpandType expandType, DataSourceManager* dataManager) { - QRegExp rx(Const::FIELD_RX); - - if (context.contains(rx)){ - while ((rx.indexIn(context))!=-1){ - QString field=rx.cap(1); - - if (dataManager->containsField(field)) { - QString fieldValue; - m_varValue = dataManager->fieldData(field); - if (expandType == EscapeSymbols) { - if (dataManager->fieldData(field).isNull()) { - fieldValue="\"\""; - } else { - fieldValue = escapeSimbols(m_varValue.toString()); - switch (dataManager->fieldData(field).type()) { - case QVariant::Char: - case QVariant::String: - case QVariant::StringList: - case QVariant::Date: - case QVariant::DateTime: - fieldValue = "\""+fieldValue+"\""; - break; - default: - break; - } - } - } else { - if (expandType == ReplaceHTMLSymbols) - fieldValue = replaceHTMLSymbols(m_varValue.toString()); - else fieldValue = m_varValue.toString(); - } - - context.replace(rx.cap(0),fieldValue); - - } else { - QString error = QString("Field %1 not found in %2 !!! ").arg(field).arg(this->objectName()); - dataManager->putError(error); - if (!reportSettings() || !reportSettings()->suppressAbsentFieldsAndVarsWarnings()) - context.replace(rx.cap(0),error); - else - context.replace(rx.cap(0),""); - } - } - } - - return context; + ScriptEngineManager& sm = ScriptEngineManager::instance(); + if (sm.dataManager() != dataManager) sm.setDataManager(dataManager); + return sm.expandDataFields(context, expandType, m_varValue, this); } QString BaseDesignIntf::expandUserVariables(QString context, RenderPass pass, ExpandType expandType, DataSourceManager* dataManager) { - QRegExp rx(Const::VARIABLE_RX); - if (context.contains(rx)){ - int pos = 0; - while ((pos = rx.indexIn(context,pos))!=-1){ - QString variable=rx.cap(1); - pos += rx.matchedLength(); - if (dataManager->containsVariable(variable) ){ - try { - if (pass==dataManager->variablePass(variable)){ - m_varValue = dataManager->variable(variable); - switch (expandType){ - case EscapeSymbols: - context.replace(rx.cap(0),escapeSimbols(m_varValue.toString())); - break; - case NoEscapeSymbols: - context.replace(rx.cap(0),m_varValue.toString()); - break; - case ReplaceHTMLSymbols: - context.replace(rx.cap(0),replaceHTMLSymbols(m_varValue.toString())); - break; - } - pos=0; - } - } catch (ReportError e){ - dataManager->putError(e.what()); - if (!reportSettings() || reportSettings()->suppressAbsentFieldsAndVarsWarnings()) - context.replace(rx.cap(0),e.what()); - else - context.replace(rx.cap(0),""); - } - } else { - QString error; - error = tr("Variable %1 not found").arg(variable); - dataManager->putError(error); - if (!reportSettings() || reportSettings()->suppressAbsentFieldsAndVarsWarnings()) - context.replace(rx.cap(0),error); - else - context.replace(rx.cap(0),""); - } - } - } - return context; + + ScriptEngineManager& sm = ScriptEngineManager::instance(); + if (sm.dataManager() != dataManager) sm.setDataManager(dataManager); + return sm.expandUserVariables(context, pass, expandType, m_varValue); + } QString BaseDesignIntf::expandScripts(QString context, DataSourceManager* dataManager) { - QRegExp rx(Const::SCRIPT_RX); - if (context.contains(rx)){ - ScriptEngineManager::instance().setDataManager(dataManager); - QScriptEngine* se = ScriptEngineManager::instance().scriptEngine(); + ScriptEngineManager& sm = ScriptEngineManager::instance(); + if (sm.dataManager() != dataManager) sm.setDataManager(dataManager); + return sm.expandScripts(context,m_varValue,this); - QScriptValue svThis = se->globalObject().property("THIS"); - if (svThis.isValid()){ - se->newQObject(svThis, this); - } else { - svThis = se->newQObject(this); - se->globalObject().setProperty("THIS",svThis); - } - - ScriptExtractor scriptExtractor(context); - if (scriptExtractor.parse()){ - for(int i=0; ievaluate(scriptBody); - if (!se->hasUncaughtException()) { - m_varValue = value.toVariant(); - context.replace(scriptExtractor.scriptAt(i),value.toString()); - } else { - context.replace(scriptExtractor.scriptAt(i),se->uncaughtException().toString()); - } - } - } - } - return context; } void BaseDesignIntf::setupPainter(QPainter *painter) const diff --git a/limereport/lrbasedesignintf.h b/limereport/lrbasedesignintf.h index d6b32f6..253da8d 100644 --- a/limereport/lrbasedesignintf.h +++ b/limereport/lrbasedesignintf.h @@ -131,7 +131,7 @@ public: }; enum ObjectState {ObjectLoading, ObjectLoaded, ObjectCreated}; enum ItemAlign {LeftItemAlign,RightItemAlign,CenterItemAlign,ParentWidthItemAlign,DesignedItemAlign}; - enum ExpandType {EscapeSymbols, NoEscapeSymbols, ReplaceHTMLSymbols}; +// enum ExpandType {EscapeSymbols, NoEscapeSymbols, ReplaceHTMLSymbols}; Q_DECLARE_FLAGS(BorderLines, BorderSide) Q_DECLARE_FLAGS(ItemMode,ItemModes) friend class SelectionMarker; @@ -327,11 +327,9 @@ protected: virtual bool drawDesignBorders() const {return true;} virtual QColor selectionMarkerColor(){ return Const::SELECTION_COLOR;} - QString escapeSimbols(const QString& value); - QString replaceHTMLSymbols(const QString& value); - virtual QString expandUserVariables(QString context, RenderPass pass, ExpandType expandType, DataSourceManager *dataManager); - virtual QString expandDataFields(QString context, ExpandType expandType, DataSourceManager *dataManager); - virtual QString expandScripts(QString context, DataSourceManager *dataManager); + QString expandUserVariables(QString context, RenderPass pass, ExpandType expandType, DataSourceManager *dataManager); + QString expandDataFields(QString context, ExpandType expandType, DataSourceManager *dataManager); + QString expandScripts(QString context, DataSourceManager *dataManager); QVariant m_varValue; diff --git a/limereport/lrdatasourcemanager.cpp b/limereport/lrdatasourcemanager.cpp index 42ec024..bab241d 100644 --- a/limereport/lrdatasourcemanager.cpp +++ b/limereport/lrdatasourcemanager.cpp @@ -238,6 +238,29 @@ void DataSourceManager::setDefaultDatabasePath(const QString &defaultDatabasePat { m_defaultDatabasePath = defaultDatabasePath; } + +QString DataSourceManager::putGroupFunctionsExpressions(QString expression) +{ + if (m_groupFunctionsExpressionsMap.contains(expression)){ + return QString::number(m_groupFunctionsExpressionsMap.value(expression)); + } else { + m_groupFunctionsExpressions.append(expression); + m_groupFunctionsExpressionsMap.insert(expression, m_groupFunctionsExpressions.size()-1); + return QString::number(m_groupFunctionsExpressions.size()-1); + } +} + +void DataSourceManager::clearGroupFuntionsExpressions() +{ + m_groupFunctionsExpressionsMap.clear(); + m_groupFunctionsExpressions.clear(); +} + +QString DataSourceManager::getExpression(QString index) +{ + return m_groupFunctionsExpressions.at(index.toInt()); +} + bool DataSourceManager::designTime() const { return m_designTime; @@ -702,6 +725,16 @@ bool DataSourceManager::initAndOpenDB(QSqlDatabase& db, ConnectionDesc& connecti return connected; } +ReportSettings *DataSourceManager::reportSettings() const +{ + return m_reportSettings; +} + +void DataSourceManager::setReportSettings(ReportSettings *reportSettings) +{ + m_reportSettings = reportSettings; +} + bool DataSourceManager::connectConnection(ConnectionDesc *connectionDesc) { diff --git a/limereport/lrdatasourcemanager.h b/limereport/lrdatasourcemanager.h index a6043f0..7670b2e 100644 --- a/limereport/lrdatasourcemanager.h +++ b/limereport/lrdatasourcemanager.h @@ -192,6 +192,13 @@ public: QString defaultDatabasePath() const; void setDefaultDatabasePath(const QString &defaultDatabasePath); + QString putGroupFunctionsExpressions(QString expression); + void clearGroupFuntionsExpressions(); + QString getExpression(QString index); + + ReportSettings *reportSettings() const; + void setReportSettings(ReportSettings *reportSettings); + signals: void loadCollectionFinished(const QString& collectionName); void cleared(); @@ -240,7 +247,13 @@ private: bool m_designTime; bool m_needUpdate; QString m_defaultDatabasePath; + ReportSettings* m_reportSettings; + QHash m_groupFunctionsExpressionsMap; + QVector m_groupFunctionsExpressions; + + }; } #endif // LRDATASOURCEMANAGER_H + diff --git a/limereport/lrglobal.cpp b/limereport/lrglobal.cpp index 47b31f0..5b2cdff 100644 --- a/limereport/lrglobal.cpp +++ b/limereport/lrglobal.cpp @@ -51,4 +51,20 @@ void ReportSettings::setSuppressAbsentFieldsAndVarsWarnings(bool suppressAbsentF m_suppressAbsentFieldsAndVarsWarnings = suppressAbsentFieldsAndVarsWarnings; } +QString escapeSimbols(const QString &value) +{ + QString result = value; + result.replace("\"","\\\""); + result.replace('\n',"\\n"); + return result; +} + +QString replaceHTMLSymbols(const QString &value) +{ + QString result = value; + result.replace("<","<"); + result.replace(">",">"); + return result; +} + } //namespace LimeReport diff --git a/limereport/lrglobal.h b/limereport/lrglobal.h index 3a01927..3b8aa7d 100644 --- a/limereport/lrglobal.h +++ b/limereport/lrglobal.h @@ -82,16 +82,21 @@ namespace Const{ //const int DATASOURCE_INDEX = 6; //const int VALUE_INDEX = 2; - const QString GROUP_FUNCTION_PARAM_RX = "\\(\\s*(?:(?:((?:(?:\\\"?\\$D\\s*\\{\\s*)|(?:\\\"?\\$V\\s*\\{\\s*)|(?:\\\"))((?:\\w+\\.?\\w+)|(?:\\w+))(?:(?:\\\")|(?:\\s*\\}\\\"?\\s*)))\\s*,)|(?:))\\s*\\\"(\\w+)\\\"\\s*\\)"; - const int DATASOURCE_INDEX = 4; - const int VALUE_INDEX = 2; - const int EXPRESSION_ARGUMENT_INDEX = 3; + //const QString GROUP_FUNCTION_PARAM_RX = "\\(\\s*(?:(?:((?:(?:\\\"?\\$D\\s*\\{\\s*)|(?:\\\"?\\$V\\s*\\{\\s*)|(?:\\\"?\\$S\\s*\\{\\s*)|(?:\\\"))((?:\\w+\\.?\\w+)|(?:\\w+))(?:(?:\\\")|(?:\\s*\\}\\\"?\\s*)))\\s*,)|(?:))\\s*\\\"(\\w+)\\\"\\s*\\)"; + const QString GROUP_FUNCTION_PARAM_RX = "\\((?:(.+),|(?:))(?:\\\"(\\w+)\\\")\\)"; + const int DATASOURCE_INDEX = 3;//4; + const int VALUE_INDEX = 2; //2; + const int EXPRESSION_ARGUMENT_INDEX = 1;//3; const QString GROUP_FUNCTION_RX = "(%1\\s*"+GROUP_FUNCTION_PARAM_RX+")"; const QString GROUP_FUNCTION_NAME_RX = "%1\\s*\\((.*[^\\)])\\)"; const int SCENE_MARGIN = 50; } QString extractClassName(QString className); + QString escapeSimbols(const QString& value); + QString replaceHTMLSymbols(const QString &value); + + enum ExpandType {EscapeSymbols, NoEscapeSymbols, ReplaceHTMLSymbols}; enum RenderPass {FirstPass, SecondPass}; enum ArrangeType {AsNeeded, Force}; enum PreviewHint{ShowAllPreviewBars = 0, @@ -100,6 +105,7 @@ namespace Const{ HidePreviewStatusBar = 4, HideAllPreviewBar = 7, PreviewBarsUserSetting = 8}; + Q_DECLARE_FLAGS(PreviewHints, PreviewHint) Q_FLAGS(PreviewHints) diff --git a/limereport/lrgroupfunctions.cpp b/limereport/lrgroupfunctions.cpp index d21b4f8..c265dfc 100644 --- a/limereport/lrgroupfunctions.cpp +++ b/limereport/lrgroupfunctions.cpp @@ -31,6 +31,7 @@ #include "lrdatasourcemanager.h" #include "lrbanddesignintf.h" #include "lritemdesignintf.h" +#include "lrscriptenginemanager.h" #include @@ -38,23 +39,45 @@ namespace LimeReport { void GroupFunction::slotBandRendered(BandDesignIntf *band) { + ScriptEngineManager& sm = ScriptEngineManager::instance(); + + QRegExp rxField(Const::FIELD_RX); + QRegExp rxVar(Const::VARIABLE_RX); + switch (m_dataType){ case Field: - if (m_dataManager->containsField(m_data)){ - m_values.push_back(m_dataManager->fieldData(m_data)); - } else { - setInvalid(tr("Field \"%1\" not found").arg(m_data)); + if (rxField.indexIn(m_data) != -1){ + QString field = rxField.cap(1); + if (m_dataManager->containsField(field)){ + m_values.push_back(m_dataManager->fieldData(field)); + } else { + setInvalid(tr("Field \"%1\" not found").arg(m_data)); + } } break; case Variable: - if (m_dataManager->containsVariable(m_data)){ - m_values.push_back(m_dataManager->variable(m_data)); - } else { - setInvalid(tr("Variable \"%1\" not found").arg(m_data)); + if (rxVar.indexIn(m_data) != -1){ + QString var = rxVar.cap(1); + if (m_dataManager->containsVariable(var)){ + m_values.push_back(m_dataManager->variable(var)); + } else { + setInvalid(tr("Variable \"%1\" not found").arg(m_data)); + } } break; + case Script: + { + QVariant value = sm.evaluateScript(m_data); + if (value.isValid()){ + m_values.push_back(value); + } else { + setInvalid(tr("Wrong script syntax \"%1\" ").arg(m_data)); + } + break; + } case ContentItem:{ - ContentItemDesignIntf* item = dynamic_cast(band->childByName(m_data)); + QString itemName = m_data; + ContentItemDesignIntf* item = dynamic_cast(band->childByName(itemName.remove('"'))); if (item) m_values.push_back(item->content()); else if (m_name.compare("COUNT",Qt::CaseInsensitive) == 0) { @@ -91,24 +114,27 @@ QVariant GroupFunction::multiplication(QVariant value1, QVariant value2) GroupFunction::GroupFunction(const QString &expression, const QString &dataBandName, DataSourceManager* dataManager) :m_dataBandName(dataBandName), m_dataManager(dataManager),m_isValid(true), m_errorMessage("") { + m_data = expression; QRegExp rxField(Const::FIELD_RX,Qt::CaseInsensitive); - if (rxField.indexIn(expression)>=0){ - m_dataType=Field; - m_data = rxField.cap(1); + QRegExp rxVariable(Const::VARIABLE_RX,Qt::CaseInsensitive); + QRegExp rxScript(Const::SCRIPT_RX,Qt::CaseInsensitive); + + if (rxScript.indexIn(expression) != -1){ + m_dataType = Script; return; } - QRegExp rxVariable(Const::VARIABLE_RX,Qt::CaseInsensitive); - if (rxVariable.indexIn(expression)>=0){ - m_dataType=Variable; - m_data = rxVariable.cap(1); + if (rxField.indexIn(expression) != -1){ + m_dataType=Field; + return; + } + + if (rxVariable.indexIn(expression) != -1){ + m_dataType = Variable; return; } m_dataType = ContentItem; - m_data = expression; - m_data = m_data.remove('"'); - } GroupFunction *GroupFunctionFactory::createGroupFunction(const QString &functionName, const QString &expression, const QString& dataBandName, DataSourceManager *dataManager) diff --git a/limereport/lrgroupfunctions.h b/limereport/lrgroupfunctions.h index cfe59c2..f85a0bd 100644 --- a/limereport/lrgroupfunctions.h +++ b/limereport/lrgroupfunctions.h @@ -42,7 +42,7 @@ class BandDesignIntf; class GroupFunction : public QObject{ Q_OBJECT public: - enum DataType{Variable,Field,Srcipt,ContentItem}; + enum DataType{Variable, Field, Script, ContentItem}; GroupFunction(const QString& expression, const QString& dataBandName, DataSourceManager *dataManager); bool isValid(){return m_isValid;} void setInvalid(QString message){m_isValid=false,m_errorMessage=message;} diff --git a/limereport/lrreportengine.cpp b/limereport/lrreportengine.cpp index 62d75bb..edb7ac4 100644 --- a/limereport/lrreportengine.cpp +++ b/limereport/lrreportengine.cpp @@ -60,7 +60,8 @@ ReportEnginePrivate::ReportEnginePrivate(QObject *parent) : m_showProgressDialog(true), m_reportName(""), m_activePreview(0), m_previewWindowIcon(":/report/images/logo32"), m_previewWindowTitle(tr("Preview")), m_reportRendering(false) { - m_datasources= new DataSourceManager(this); + m_datasources = new DataSourceManager(this); + m_datasources->setReportSettings(&m_reportSettings); m_scriptEngineContext = new ScriptEngineContext(this); m_datasources->setObjectName("datasources"); connect(m_datasources,SIGNAL(loadCollectionFinished(QString)),this,SLOT(slotDataSourceCollectionLoaded(QString))); diff --git a/limereport/lrreportrender.cpp b/limereport/lrreportrender.cpp index 2b061d8..a66b95d 100644 --- a/limereport/lrreportrender.cpp +++ b/limereport/lrreportrender.cpp @@ -236,6 +236,7 @@ void ReportRender::renderPage(PageDesignIntf* patternPage) try{ datasources()->setAllDatasourcesToFirst(); + datasources()->clearGroupFuntionsExpressions(); } catch(ReportError &exception){ //TODO possible should thow exeption QMessageBox::critical(0,tr("Error"),exception.what()); @@ -277,7 +278,7 @@ int ReportRender::pageCount() PageItemDesignIntf::Ptr ReportRender::pageAt(int index) { - if ((index>m_renderedPages.count()-1)||(index<0)) throw ReportError("page index out of range"); + if ((index>m_renderedPages.count()-1)||(index<0)) throw ReportError(tr("page index out of range")); else return m_renderedPages.at(index); } @@ -368,7 +369,8 @@ void ReportRender::replaceGroupsFunction(BandDesignIntf *band) if (rx.indexIn(content)>=0){ int pos = 0; while ( (pos = rx.indexIn(content,pos))!= -1 ){ - content.replace(rx.capturedTexts().at(0),QString("%1(%2,%3)").arg(functionName).arg('"'+rx.cap(Const::EXPRESSION_ARGUMENT_INDEX)+'"').arg('"'+band->objectName()+'"')); + QString expressionIndex = datasources()->putGroupFunctionsExpressions(rx.cap(Const::VALUE_INDEX)); + content.replace(rx.capturedTexts().at(0),QString("%1(%2,%3)").arg(functionName).arg('"'+expressionIndex+'"').arg('"'+band->objectName()+'"')); pos += rx.matchedLength(); } contentItem->setContent(content); diff --git a/limereport/lrscriptenginemanager.cpp b/limereport/lrscriptenginemanager.cpp index aeca592..f69283b 100644 --- a/limereport/lrscriptenginemanager.cpp +++ b/limereport/lrscriptenginemanager.cpp @@ -309,7 +309,7 @@ QScriptValue callGroupFunction(const QString& functionName, QScriptContext* pcon expression = " "; band = pcontext->argument(0).toString(); } else { - expression = pcontext->argument(0).toString(); + expression = dm->getExpression(pcontext->argument(0).toString()); band = pcontext->argument(1).toString(); } @@ -427,7 +427,7 @@ void ScriptEngineManager::setDataManager(DataSourceManager *dataManager){ if (m_dataManager){ foreach(QString func, m_dataManager->groupFunctionNames()){ if (isFunctionExists(func)) deleteFunction(func); - addFunction(func, groupFunction,"GROUP FUNCTIONS", func+"(\""+tr("FieldName")+"\",\""+tr("BandName")+"\")"); + addFunction(func, groupFunction,"GROUP FUNCTIONS", func+"(\""+tr("Value")+"\",\""+tr("BandName")+"\")"); } foreach(ScriptFunctionDesc func, m_functions){ if (func.type==ScriptFunctionDesc::Native) @@ -437,6 +437,167 @@ void ScriptEngineManager::setDataManager(DataSourceManager *dataManager){ } } +QString ScriptEngineManager::expandUserVariables(QString context, RenderPass pass, ExpandType expandType, QVariant &varValue) +{ + QRegExp rx(Const::VARIABLE_RX); + if (context.contains(rx)){ + int pos = 0; + while ((pos = rx.indexIn(context,pos))!=-1){ + QString variable=rx.cap(1); + 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; + } + } catch (ReportError e){ + dataManager()->putError(e.what()); + if (!dataManager()->reportSettings() || dataManager()->reportSettings()->suppressAbsentFieldsAndVarsWarnings()) + context.replace(rx.cap(0),e.what()); + else + context.replace(rx.cap(0),""); + } + } else { + QString error; + error = tr("Variable %1 not found").arg(variable); + dataManager()->putError(error); + if (!dataManager()->reportSettings() || dataManager()->reportSettings()->suppressAbsentFieldsAndVarsWarnings()) + context.replace(rx.cap(0),error); + else + context.replace(rx.cap(0),""); + } + } + } + return context; +} + +QString ScriptEngineManager::expandDataFields(QString context, ExpandType expandType, QVariant &varValue, QObject *reportItem) +{ + QRegExp rx(Const::FIELD_RX); + + if (context.contains(rx)){ + while ((rx.indexIn(context))!=-1){ + QString field=rx.cap(1); + + if (dataManager()->containsField(field)) { + QString fieldValue; + varValue = dataManager()->fieldData(field); + if (expandType == EscapeSymbols) { + if (dataManager()->fieldData(field).isNull()) { + fieldValue="\"\""; + } else { + fieldValue = escapeSimbols(varValue.toString()); + switch (dataManager()->fieldData(field).type()) { + case QVariant::Char: + case QVariant::String: + case QVariant::StringList: + case QVariant::Date: + case QVariant::DateTime: + fieldValue = "\""+fieldValue+"\""; + break; + default: + break; + } + } + } else { + if (expandType == ReplaceHTMLSymbols) + fieldValue = replaceHTMLSymbols(varValue.toString()); + else fieldValue = varValue.toString(); + } + + context.replace(rx.cap(0),fieldValue); + + } else { + QString error = QString("Field %1 not found in %2 !!! ").arg(field).arg(reportItem->objectName()); + dataManager()->putError(error); + varValue = QVariant(); + if (!dataManager()->reportSettings() || !dataManager()->reportSettings()->suppressAbsentFieldsAndVarsWarnings()) + context.replace(rx.cap(0),error); + else + context.replace(rx.cap(0),""); + } + } + } + + return context; +} + +QString ScriptEngineManager::expandScripts(QString context, QVariant& varValue, QObject *reportItem) +{ + QRegExp rx(Const::SCRIPT_RX); + + if (context.contains(rx)){ + + if (ScriptEngineManager::instance().dataManager()!=dataManager()) + ScriptEngineManager::instance().setDataManager(dataManager()); + + QScriptEngine* se = ScriptEngineManager::instance().scriptEngine(); + + if (reportItem){ + QScriptValue svThis = se->globalObject().property("THIS"); + if (svThis.isValid()){ + se->newQObject(svThis, this); + } else { + svThis = se->newQObject(this); + se->globalObject().setProperty("THIS",svThis); + } + } + + ScriptExtractor scriptExtractor(context); + if (scriptExtractor.parse()){ + for(int i=0; ievaluate(scriptBody); + if (!se->hasUncaughtException()) { + varValue = value.toVariant(); + context.replace(scriptExtractor.scriptAt(i),value.toString()); + } else { + context.replace(scriptExtractor.scriptAt(i),se->uncaughtException().toString()); + } + } + } + } + return context; +} + +QVariant ScriptEngineManager::evaluateScript(const QString& script){ + + QRegExp rx(Const::SCRIPT_RX); + QVariant varValue; + + if (script.contains(rx)){ + + if (ScriptEngineManager::instance().dataManager()!=dataManager()) + ScriptEngineManager::instance().setDataManager(dataManager()); + + QScriptEngine* se = ScriptEngineManager::instance().scriptEngine(); + + ScriptExtractor scriptExtractor(script); + if (scriptExtractor.parse()){ + QString scriptBody = expandDataFields(scriptExtractor.bodyAt(0),EscapeSymbols, varValue, 0); + scriptBody = expandUserVariables(scriptBody, FirstPass, EscapeSymbols, varValue); + QScriptValue value = se->evaluate(scriptBody); + if (!se->hasUncaughtException()) { + return value.toVariant(); + } + } + } + return QVariant(); +} + void ScriptEngineManager::updateModel() { diff --git a/limereport/lrscriptenginemanager.h b/limereport/lrscriptenginemanager.h index 0c738d9..545580b 100644 --- a/limereport/lrscriptenginemanager.h +++ b/limereport/lrscriptenginemanager.h @@ -190,6 +190,11 @@ public: DataSourceManager* dataManager() const {return m_dataManager;} void setDataManager(DataSourceManager* dataManager); + QString expandUserVariables(QString context, RenderPass pass, ExpandType expandType, QVariant &varValue); + QString expandDataFields(QString context, ExpandType expandType, QVariant &varValue, QObject* reportItem); + QString expandScripts(QString context, QVariant &varValue, QObject* reportItem); + QVariant evaluateScript(const QString &script); + protected: void updateModel(); bool containsFunction(const QString &functionName);