Group functions have been refactored. From now they can use script expression in value parameter

This commit is contained in:
Arin Alexander 2017-01-28 02:20:15 +03:00
parent 887710d728
commit afc8ad77b2
14 changed files with 333 additions and 172 deletions

View File

@ -51,4 +51,20 @@ void ReportSettings::setSuppressAbsentFieldsAndVarsWarnings(bool suppressAbsentF
m_suppressAbsentFieldsAndVarsWarnings = suppressAbsentFieldsAndVarsWarnings; 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("<","&lt;");
result.replace(">","&gt;");
return result;
}
} //namespace LimeReport } //namespace LimeReport

View File

@ -82,16 +82,21 @@ namespace Const{
//const int DATASOURCE_INDEX = 6; //const int DATASOURCE_INDEX = 6;
//const int VALUE_INDEX = 2; //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 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 int DATASOURCE_INDEX = 4; const QString GROUP_FUNCTION_PARAM_RX = "\\((?:(.+),|(?:))(?:\\\"(\\w+)\\\")\\)";
const int VALUE_INDEX = 2; const int DATASOURCE_INDEX = 3;//4;
const int EXPRESSION_ARGUMENT_INDEX = 3; 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_RX = "(%1\\s*"+GROUP_FUNCTION_PARAM_RX+")";
const QString GROUP_FUNCTION_NAME_RX = "%1\\s*\\((.*[^\\)])\\)"; const QString GROUP_FUNCTION_NAME_RX = "%1\\s*\\((.*[^\\)])\\)";
const int SCENE_MARGIN = 50; const int SCENE_MARGIN = 50;
} }
QString extractClassName(QString className); QString extractClassName(QString className);
QString escapeSimbols(const QString& value);
QString replaceHTMLSymbols(const QString &value);
enum ExpandType {EscapeSymbols, NoEscapeSymbols, ReplaceHTMLSymbols};
enum RenderPass {FirstPass, SecondPass}; enum RenderPass {FirstPass, SecondPass};
enum ArrangeType {AsNeeded, Force}; enum ArrangeType {AsNeeded, Force};
enum PreviewHint{ShowAllPreviewBars = 0, enum PreviewHint{ShowAllPreviewBars = 0,
@ -100,6 +105,7 @@ namespace Const{
HidePreviewStatusBar = 4, HidePreviewStatusBar = 4,
HideAllPreviewBar = 7, HideAllPreviewBar = 7,
PreviewBarsUserSetting = 8}; PreviewBarsUserSetting = 8};
Q_DECLARE_FLAGS(PreviewHints, PreviewHint) Q_DECLARE_FLAGS(PreviewHints, PreviewHint)
Q_FLAGS(PreviewHints) Q_FLAGS(PreviewHints)

View File

@ -34,7 +34,6 @@
#include "lrreportdesignwidget.h" #include "lrreportdesignwidget.h"
#include "qgraphicsitem.h" #include "qgraphicsitem.h"
#include "lrdesignelementsfactory.h" #include "lrdesignelementsfactory.h"
#include "lrhorizontallayout.h" #include "lrhorizontallayout.h"
#include <memory> #include <memory>
@ -241,150 +240,29 @@ QFont BaseDesignIntf::transformToSceneFont(const QFont& value) const
return f; 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("<","&lt;");
result.replace(">","&gt;");
return result;
}
QString BaseDesignIntf::expandDataFields(QString context, ExpandType expandType, DataSourceManager* dataManager) QString BaseDesignIntf::expandDataFields(QString context, ExpandType expandType, DataSourceManager* dataManager)
{ {
QRegExp rx(Const::FIELD_RX); ScriptEngineManager& sm = ScriptEngineManager::instance();
if (sm.dataManager() != dataManager) sm.setDataManager(dataManager);
if (context.contains(rx)){ return sm.expandDataFields(context, expandType, m_varValue, this);
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;
} }
QString BaseDesignIntf::expandUserVariables(QString context, RenderPass pass, ExpandType expandType, DataSourceManager* dataManager) QString BaseDesignIntf::expandUserVariables(QString context, RenderPass pass, ExpandType expandType, DataSourceManager* dataManager)
{ {
QRegExp rx(Const::VARIABLE_RX);
if (context.contains(rx)){ ScriptEngineManager& sm = ScriptEngineManager::instance();
int pos = 0; if (sm.dataManager() != dataManager) sm.setDataManager(dataManager);
while ((pos = rx.indexIn(context,pos))!=-1){ return sm.expandUserVariables(context, pass, expandType, m_varValue);
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;
} }
QString BaseDesignIntf::expandScripts(QString context, DataSourceManager* dataManager) QString BaseDesignIntf::expandScripts(QString context, DataSourceManager* dataManager)
{ {
QRegExp rx(Const::SCRIPT_RX);
if (context.contains(rx)){ ScriptEngineManager& sm = ScriptEngineManager::instance();
ScriptEngineManager::instance().setDataManager(dataManager); if (sm.dataManager() != dataManager) sm.setDataManager(dataManager);
QScriptEngine* se = ScriptEngineManager::instance().scriptEngine(); 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; i<scriptExtractor.count();++i){
QString scriptBody = expandDataFields(scriptExtractor.bodyAt(i),EscapeSymbols, dataManager);
scriptBody = expandUserVariables(scriptBody, FirstPass, EscapeSymbols, dataManager);
QScriptValue value = se->evaluate(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 void BaseDesignIntf::setupPainter(QPainter *painter) const

View File

@ -131,7 +131,7 @@ public:
}; };
enum ObjectState {ObjectLoading, ObjectLoaded, ObjectCreated}; enum ObjectState {ObjectLoading, ObjectLoaded, ObjectCreated};
enum ItemAlign {LeftItemAlign,RightItemAlign,CenterItemAlign,ParentWidthItemAlign,DesignedItemAlign}; 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(BorderLines, BorderSide)
Q_DECLARE_FLAGS(ItemMode,ItemModes) Q_DECLARE_FLAGS(ItemMode,ItemModes)
friend class SelectionMarker; friend class SelectionMarker;
@ -327,11 +327,9 @@ protected:
virtual bool drawDesignBorders() const {return true;} virtual bool drawDesignBorders() const {return true;}
virtual QColor selectionMarkerColor(){ return Const::SELECTION_COLOR;} virtual QColor selectionMarkerColor(){ return Const::SELECTION_COLOR;}
QString escapeSimbols(const QString& value); QString expandUserVariables(QString context, RenderPass pass, ExpandType expandType, DataSourceManager *dataManager);
QString replaceHTMLSymbols(const QString& value); QString expandDataFields(QString context, ExpandType expandType, DataSourceManager *dataManager);
virtual QString expandUserVariables(QString context, RenderPass pass, ExpandType expandType, DataSourceManager *dataManager); QString expandScripts(QString context, DataSourceManager *dataManager);
virtual QString expandDataFields(QString context, ExpandType expandType, DataSourceManager *dataManager);
virtual QString expandScripts(QString context, DataSourceManager *dataManager);
QVariant m_varValue; QVariant m_varValue;

View File

@ -238,6 +238,29 @@ void DataSourceManager::setDefaultDatabasePath(const QString &defaultDatabasePat
{ {
m_defaultDatabasePath = defaultDatabasePath; 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 bool DataSourceManager::designTime() const
{ {
return m_designTime; return m_designTime;
@ -702,6 +725,16 @@ bool DataSourceManager::initAndOpenDB(QSqlDatabase& db, ConnectionDesc& connecti
return connected; return connected;
} }
ReportSettings *DataSourceManager::reportSettings() const
{
return m_reportSettings;
}
void DataSourceManager::setReportSettings(ReportSettings *reportSettings)
{
m_reportSettings = reportSettings;
}
bool DataSourceManager::connectConnection(ConnectionDesc *connectionDesc) bool DataSourceManager::connectConnection(ConnectionDesc *connectionDesc)
{ {

View File

@ -192,6 +192,13 @@ public:
QString defaultDatabasePath() const; QString defaultDatabasePath() const;
void setDefaultDatabasePath(const QString &defaultDatabasePath); void setDefaultDatabasePath(const QString &defaultDatabasePath);
QString putGroupFunctionsExpressions(QString expression);
void clearGroupFuntionsExpressions();
QString getExpression(QString index);
ReportSettings *reportSettings() const;
void setReportSettings(ReportSettings *reportSettings);
signals: signals:
void loadCollectionFinished(const QString& collectionName); void loadCollectionFinished(const QString& collectionName);
void cleared(); void cleared();
@ -240,7 +247,13 @@ private:
bool m_designTime; bool m_designTime;
bool m_needUpdate; bool m_needUpdate;
QString m_defaultDatabasePath; QString m_defaultDatabasePath;
ReportSettings* m_reportSettings;
QHash<QString,int> m_groupFunctionsExpressionsMap;
QVector<QString> m_groupFunctionsExpressions;
}; };
} }
#endif // LRDATASOURCEMANAGER_H #endif // LRDATASOURCEMANAGER_H

View File

@ -51,4 +51,20 @@ void ReportSettings::setSuppressAbsentFieldsAndVarsWarnings(bool suppressAbsentF
m_suppressAbsentFieldsAndVarsWarnings = suppressAbsentFieldsAndVarsWarnings; 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("<","&lt;");
result.replace(">","&gt;");
return result;
}
} //namespace LimeReport } //namespace LimeReport

View File

@ -82,16 +82,21 @@ namespace Const{
//const int DATASOURCE_INDEX = 6; //const int DATASOURCE_INDEX = 6;
//const int VALUE_INDEX = 2; //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 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 int DATASOURCE_INDEX = 4; const QString GROUP_FUNCTION_PARAM_RX = "\\((?:(.+),|(?:))(?:\\\"(\\w+)\\\")\\)";
const int VALUE_INDEX = 2; const int DATASOURCE_INDEX = 3;//4;
const int EXPRESSION_ARGUMENT_INDEX = 3; 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_RX = "(%1\\s*"+GROUP_FUNCTION_PARAM_RX+")";
const QString GROUP_FUNCTION_NAME_RX = "%1\\s*\\((.*[^\\)])\\)"; const QString GROUP_FUNCTION_NAME_RX = "%1\\s*\\((.*[^\\)])\\)";
const int SCENE_MARGIN = 50; const int SCENE_MARGIN = 50;
} }
QString extractClassName(QString className); QString extractClassName(QString className);
QString escapeSimbols(const QString& value);
QString replaceHTMLSymbols(const QString &value);
enum ExpandType {EscapeSymbols, NoEscapeSymbols, ReplaceHTMLSymbols};
enum RenderPass {FirstPass, SecondPass}; enum RenderPass {FirstPass, SecondPass};
enum ArrangeType {AsNeeded, Force}; enum ArrangeType {AsNeeded, Force};
enum PreviewHint{ShowAllPreviewBars = 0, enum PreviewHint{ShowAllPreviewBars = 0,
@ -100,6 +105,7 @@ namespace Const{
HidePreviewStatusBar = 4, HidePreviewStatusBar = 4,
HideAllPreviewBar = 7, HideAllPreviewBar = 7,
PreviewBarsUserSetting = 8}; PreviewBarsUserSetting = 8};
Q_DECLARE_FLAGS(PreviewHints, PreviewHint) Q_DECLARE_FLAGS(PreviewHints, PreviewHint)
Q_FLAGS(PreviewHints) Q_FLAGS(PreviewHints)

View File

@ -31,6 +31,7 @@
#include "lrdatasourcemanager.h" #include "lrdatasourcemanager.h"
#include "lrbanddesignintf.h" #include "lrbanddesignintf.h"
#include "lritemdesignintf.h" #include "lritemdesignintf.h"
#include "lrscriptenginemanager.h"
#include <QRegExp> #include <QRegExp>
@ -38,23 +39,45 @@ namespace LimeReport {
void GroupFunction::slotBandRendered(BandDesignIntf *band) void GroupFunction::slotBandRendered(BandDesignIntf *band)
{ {
ScriptEngineManager& sm = ScriptEngineManager::instance();
QRegExp rxField(Const::FIELD_RX);
QRegExp rxVar(Const::VARIABLE_RX);
switch (m_dataType){ switch (m_dataType){
case Field: case Field:
if (m_dataManager->containsField(m_data)){ if (rxField.indexIn(m_data) != -1){
m_values.push_back(m_dataManager->fieldData(m_data)); QString field = rxField.cap(1);
if (m_dataManager->containsField(field)){
m_values.push_back(m_dataManager->fieldData(field));
} else { } else {
setInvalid(tr("Field \"%1\" not found").arg(m_data)); setInvalid(tr("Field \"%1\" not found").arg(m_data));
} }
}
break; break;
case Variable: case Variable:
if (m_dataManager->containsVariable(m_data)){ if (rxVar.indexIn(m_data) != -1){
m_values.push_back(m_dataManager->variable(m_data)); QString var = rxVar.cap(1);
if (m_dataManager->containsVariable(var)){
m_values.push_back(m_dataManager->variable(var));
} else { } else {
setInvalid(tr("Variable \"%1\" not found").arg(m_data)); setInvalid(tr("Variable \"%1\" not found").arg(m_data));
} }
}
break; 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:{ case ContentItem:{
ContentItemDesignIntf* item = dynamic_cast<ContentItemDesignIntf*>(band->childByName(m_data)); QString itemName = m_data;
ContentItemDesignIntf* item = dynamic_cast<ContentItemDesignIntf*>(band->childByName(itemName.remove('"')));
if (item) if (item)
m_values.push_back(item->content()); m_values.push_back(item->content());
else if (m_name.compare("COUNT",Qt::CaseInsensitive) == 0) { 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) GroupFunction::GroupFunction(const QString &expression, const QString &dataBandName, DataSourceManager* dataManager)
:m_dataBandName(dataBandName), m_dataManager(dataManager),m_isValid(true), m_errorMessage("") :m_dataBandName(dataBandName), m_dataManager(dataManager),m_isValid(true), m_errorMessage("")
{ {
m_data = expression;
QRegExp rxField(Const::FIELD_RX,Qt::CaseInsensitive); QRegExp rxField(Const::FIELD_RX,Qt::CaseInsensitive);
if (rxField.indexIn(expression)>=0){ QRegExp rxVariable(Const::VARIABLE_RX,Qt::CaseInsensitive);
m_dataType=Field; QRegExp rxScript(Const::SCRIPT_RX,Qt::CaseInsensitive);
m_data = rxField.cap(1);
if (rxScript.indexIn(expression) != -1){
m_dataType = Script;
return; return;
} }
QRegExp rxVariable(Const::VARIABLE_RX,Qt::CaseInsensitive); if (rxField.indexIn(expression) != -1){
if (rxVariable.indexIn(expression)>=0){ m_dataType=Field;
return;
}
if (rxVariable.indexIn(expression) != -1){
m_dataType = Variable; m_dataType = Variable;
m_data = rxVariable.cap(1);
return; return;
} }
m_dataType = ContentItem; 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) GroupFunction *GroupFunctionFactory::createGroupFunction(const QString &functionName, const QString &expression, const QString& dataBandName, DataSourceManager *dataManager)

View File

@ -42,7 +42,7 @@ class BandDesignIntf;
class GroupFunction : public QObject{ class GroupFunction : public QObject{
Q_OBJECT Q_OBJECT
public: public:
enum DataType{Variable,Field,Srcipt,ContentItem}; enum DataType{Variable, Field, Script, ContentItem};
GroupFunction(const QString& expression, const QString& dataBandName, DataSourceManager *dataManager); GroupFunction(const QString& expression, const QString& dataBandName, DataSourceManager *dataManager);
bool isValid(){return m_isValid;} bool isValid(){return m_isValid;}
void setInvalid(QString message){m_isValid=false,m_errorMessage=message;} void setInvalid(QString message){m_isValid=false,m_errorMessage=message;}

View File

@ -61,6 +61,7 @@ ReportEnginePrivate::ReportEnginePrivate(QObject *parent) :
m_previewWindowIcon(":/report/images/logo32"), m_previewWindowTitle(tr("Preview")), m_reportRendering(false) 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_scriptEngineContext = new ScriptEngineContext(this);
m_datasources->setObjectName("datasources"); m_datasources->setObjectName("datasources");
connect(m_datasources,SIGNAL(loadCollectionFinished(QString)),this,SLOT(slotDataSourceCollectionLoaded(QString))); connect(m_datasources,SIGNAL(loadCollectionFinished(QString)),this,SLOT(slotDataSourceCollectionLoaded(QString)));

View File

@ -236,6 +236,7 @@ void ReportRender::renderPage(PageDesignIntf* patternPage)
try{ try{
datasources()->setAllDatasourcesToFirst(); datasources()->setAllDatasourcesToFirst();
datasources()->clearGroupFuntionsExpressions();
} catch(ReportError &exception){ } catch(ReportError &exception){
//TODO possible should thow exeption //TODO possible should thow exeption
QMessageBox::critical(0,tr("Error"),exception.what()); QMessageBox::critical(0,tr("Error"),exception.what());
@ -277,7 +278,7 @@ int ReportRender::pageCount()
PageItemDesignIntf::Ptr ReportRender::pageAt(int index) 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); else return m_renderedPages.at(index);
} }
@ -368,7 +369,8 @@ void ReportRender::replaceGroupsFunction(BandDesignIntf *band)
if (rx.indexIn(content)>=0){ if (rx.indexIn(content)>=0){
int pos = 0; int pos = 0;
while ( (pos = rx.indexIn(content,pos))!= -1 ){ 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(); pos += rx.matchedLength();
} }
contentItem->setContent(content); contentItem->setContent(content);

View File

@ -309,7 +309,7 @@ QScriptValue callGroupFunction(const QString& functionName, QScriptContext* pcon
expression = " "; expression = " ";
band = pcontext->argument(0).toString(); band = pcontext->argument(0).toString();
} else { } else {
expression = pcontext->argument(0).toString(); expression = dm->getExpression(pcontext->argument(0).toString());
band = pcontext->argument(1).toString(); band = pcontext->argument(1).toString();
} }
@ -427,7 +427,7 @@ void ScriptEngineManager::setDataManager(DataSourceManager *dataManager){
if (m_dataManager){ if (m_dataManager){
foreach(QString func, m_dataManager->groupFunctionNames()){ foreach(QString func, m_dataManager->groupFunctionNames()){
if (isFunctionExists(func)) deleteFunction(func); 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){ foreach(ScriptFunctionDesc func, m_functions){
if (func.type==ScriptFunctionDesc::Native) 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; i<scriptExtractor.count();++i){
QString scriptBody = expandDataFields(scriptExtractor.bodyAt(i),EscapeSymbols, varValue, reportItem);
scriptBody = expandUserVariables(scriptBody, FirstPass, EscapeSymbols, varValue);
QScriptValue value = se->evaluate(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() void ScriptEngineManager::updateModel()
{ {

View File

@ -190,6 +190,11 @@ public:
DataSourceManager* dataManager() const {return m_dataManager;} DataSourceManager* dataManager() const {return m_dataManager;}
void setDataManager(DataSourceManager* 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: protected:
void updateModel(); void updateModel();
bool containsFunction(const QString &functionName); bool containsFunction(const QString &functionName);