diff --git a/include/lrdatasourceintf.h b/include/lrdatasourceintf.h new file mode 100644 index 0000000..c2a6c90 --- /dev/null +++ b/include/lrdatasourceintf.h @@ -0,0 +1,47 @@ +#ifndef LRDATASOURCEINTF_H +#define LRDATASOURCEINTF_H +#include +#include +namespace LimeReport { + +class IDataSource { +public: + enum DatasourceMode{DESIGN_MODE,RENDER_MODE}; + typedef QSharedPointer Ptr; + virtual ~IDataSource() {} + virtual bool next() = 0; + virtual bool hasNext() = 0; + virtual bool prior() = 0; + virtual void first() = 0; + virtual void last() = 0; + 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; + virtual bool isInvalid() const = 0; + virtual QString lastError() = 0; + virtual QAbstractItemModel* model() = 0; +}; + +class IDataSourceHolder { +public: + virtual ~IDataSourceHolder(){} + virtual IDataSource* dataSource(IDataSource::DatasourceMode mode = IDataSource::RENDER_MODE) = 0; + virtual QString lastError() const = 0; + virtual bool isInvalid() const = 0; + virtual bool isOwned() const = 0; + virtual bool isEditable() const = 0; + virtual bool isRemovable() const = 0; + virtual void invalidate(IDataSource::DatasourceMode mode, bool dbWillBeClosed = false) = 0; + virtual void update() = 0; + virtual void clearErrors() = 0; +}; + +} // namespace LimeReport + +#endif // LRDATASOURCEINTF_H + + diff --git a/include/lrglobal.h b/include/lrglobal.h index bf23065..a82998f 100644 --- a/include/lrglobal.h +++ b/include/lrglobal.h @@ -82,8 +82,8 @@ namespace Const{ const qreal BAND_NAME_TEXT_OPACITY = 0.6; 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 VARIABLE_RX = "\\$V\\s*\\{\\s*(?:([^\\{\\},]*)|(?:([^\\{\\}]*)\\s*,\\s*([^\\{\\}]*)))\\s*\\}"; + const QString NAMED_VARIABLE_RX = "\\$V\\s*\\{\\s*(?:(%1)|(?:(%1)\\s*,\\s*([^\\{\\}]*)))\\s*\\}"; const QString SCRIPT_RX = "\\$S\\s*\\{(.*)\\}"; const QString GROUP_FUNCTION_PARAM_RX = "\\(\\s*((?:(?:\\\")|(?:))(?:(?:\\$(?:(?:D\\{\\s*\\w*..*\\})|(?:V\\{\\s*\\w*\\s*\\})|(?:S\\{.+\\})))|(?:\\w*))(?:(?:\\\")|(?:)))(?:(?:\\s*,\\s*(?:\\\"(\\w*)\\\"))|(?:))(?:(?:\\s*,\\s*(?:(\\w*)))|(?:))\\)"; const int DATASOURCE_INDEX = 3; @@ -94,6 +94,7 @@ namespace Const{ const QString GROUP_FUNCTION_NAME_RX = "%1\\s*\\((.*[^\\)])\\)"; const int SCENE_MARGIN = 50; const QString FUNCTION_MANAGER_NAME = "LimeReport"; + const QString DATAFUNCTIONS_MANAGER_NAME = "DatasourceFunctions"; const QString EOW("~!@#$%^&*()+{}|:\"<>?,/;'[]\\-="); const int DEFAULT_TAB_INDENTION = 4; diff --git a/limereport/designer.pri b/limereport/designer.pri index 5fb31ad..f377546 100644 --- a/limereport/designer.pri +++ b/limereport/designer.pri @@ -1,3 +1,4 @@ +include(../common.pri) DEFINES+=HAVE_REPORT_DESIGNER contains(CONFIG,dialogdesigner){ diff --git a/limereport/lrdatadesignintf.cpp b/limereport/lrdatadesignintf.cpp index 5f695e8..23b1e76 100644 --- a/limereport/lrdatadesignintf.cpp +++ b/limereport/lrdatadesignintf.cpp @@ -77,10 +77,8 @@ bool QueryHolder::runQuery(IDataSource::DatasourceMode mode) return false; } - if (!m_prepared){ - extractParams(); - if (!m_prepared) return false; - } + extractParams(); + if (!m_prepared) return false; query.prepare(m_preparedSQL); fillParams(&query); @@ -152,35 +150,13 @@ void QueryHolder::fillParams(QSqlQuery *query) void QueryHolder::extractParams() { - m_preparedSQL = replaceVariables(m_queryText); + m_preparedSQL = dataManager()->replaceVariables(m_queryText, m_aliasesToParam); m_prepared = true; } QString QueryHolder::replaceVariables(QString query) { - QRegExp rx(Const::VARIABLE_RX); - int curentAliasIndex = 0; - if (query.contains(rx)){ - int pos = -1; - while ((pos=rx.indexIn(query))!=-1){ - - QString variable=rx.cap(0); - variable.remove("$V{"); - variable.remove("}"); - - if (m_aliasesToParam.contains(variable)){ - curentAliasIndex++; - m_aliasesToParam.insert(variable+"_alias"+QString::number(curentAliasIndex),variable); - variable += "_alias"+QString::number(curentAliasIndex); - } else { - m_aliasesToParam.insert(variable,variable); - } - - query.replace(pos,rx.cap(0).length(),":"+variable); - - } - } - return query; + return dataManager()->replaceVariables(query, m_aliasesToParam); } QString QueryHolder::queryText() @@ -450,32 +426,7 @@ QString SubQueryHolder::extractField(QString source) QString SubQueryHolder::replaceFields(QString query) { - QRegExp rx(Const::FIELD_RX); - int curentAliasIndex=0; - if (query.contains(rx)){ - int pos; - while ((pos=rx.indexIn(query))!=-1){ - QString field=rx.cap(0); - field.remove("$D{"); - field.remove("}"); - - if (!m_aliasesToParam.contains(field)){ - if (field.contains(".")) - m_aliasesToParam.insert(field,field); - else - m_aliasesToParam.insert(field,m_masterDatasource+"."+field); - } else { - curentAliasIndex++; - if (field.contains(".")) - m_aliasesToParam.insert(field+"_alias"+QString::number(curentAliasIndex),field); - else - m_aliasesToParam.insert(field+"_alias"+QString::number(curentAliasIndex),m_masterDatasource+"."+field); - field+="_alias"+QString::number(curentAliasIndex); - } - query.replace(pos,rx.cap(0).length(),":"+extractField(field)); - } - } - return query; + return dataManager()->replaceFields(query, m_aliasesToParam); } SubQueryDesc::SubQueryDesc(QString queryName, QString queryText, QString connection, QString masterDatasourceName) diff --git a/limereport/lrdatasourcemanager.cpp b/limereport/lrdatasourcemanager.cpp index 5e1ee67..13a840a 100644 --- a/limereport/lrdatasourcemanager.cpp +++ b/limereport/lrdatasourcemanager.cpp @@ -451,17 +451,32 @@ QString DataSourceManager::replaceVariables(QString query, QMap QString var=rx.cap(0); var.remove("$V{"); var.remove("}"); - - if (aliasesToParam.contains(var)){ - curentAliasIndex++; - aliasesToParam.insert(var+"_v_alias"+QString::number(curentAliasIndex),var); - var += "_v_alias"+QString::number(curentAliasIndex); + if (!rx.cap(1).isEmpty()){ + if (aliasesToParam.contains(var)){ + curentAliasIndex++; + aliasesToParam.insert(var+"_v_alias"+QString::number(curentAliasIndex),var); + var += "_v_alias"+QString::number(curentAliasIndex); + } else { + aliasesToParam.insert(var,var); + } + query.replace(pos,rx.cap(0).length(),":"+var); } else { - aliasesToParam.insert(var,var); + QString varName = rx.cap(2).trimmed(); + QString varParam = rx.cap(3).trimmed(); + if (!varName.isEmpty()){ + if (!varParam.isEmpty() && varParam.compare("nobind") == 0 ){ + query.replace(pos,rx.cap(0).length(), variable(varName).toString()); + } else { + query.replace(pos,rx.cap(0).length(), + QString(tr("Uknown parametr \"%1\" for variable \"%2\" found!") + .arg(varName) + .arg(varParam)) + ); + } + } else { + query.replace(pos,rx.cap(0).length(),QString(tr("Variable \"%1\" not found!").arg(var))); + } } - - query.replace(pos,rx.cap(0).length(),":"+var); - } } return query; diff --git a/limereport/lrglobal.h b/limereport/lrglobal.h index bf23065..a82998f 100644 --- a/limereport/lrglobal.h +++ b/limereport/lrglobal.h @@ -82,8 +82,8 @@ namespace Const{ const qreal BAND_NAME_TEXT_OPACITY = 0.6; 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 VARIABLE_RX = "\\$V\\s*\\{\\s*(?:([^\\{\\},]*)|(?:([^\\{\\}]*)\\s*,\\s*([^\\{\\}]*)))\\s*\\}"; + const QString NAMED_VARIABLE_RX = "\\$V\\s*\\{\\s*(?:(%1)|(?:(%1)\\s*,\\s*([^\\{\\}]*)))\\s*\\}"; const QString SCRIPT_RX = "\\$S\\s*\\{(.*)\\}"; const QString GROUP_FUNCTION_PARAM_RX = "\\(\\s*((?:(?:\\\")|(?:))(?:(?:\\$(?:(?:D\\{\\s*\\w*..*\\})|(?:V\\{\\s*\\w*\\s*\\})|(?:S\\{.+\\})))|(?:\\w*))(?:(?:\\\")|(?:)))(?:(?:\\s*,\\s*(?:\\\"(\\w*)\\\"))|(?:))(?:(?:\\s*,\\s*(?:(\\w*)))|(?:))\\)"; const int DATASOURCE_INDEX = 3; @@ -94,6 +94,7 @@ namespace Const{ const QString GROUP_FUNCTION_NAME_RX = "%1\\s*\\((.*[^\\)])\\)"; const int SCENE_MARGIN = 50; const QString FUNCTION_MANAGER_NAME = "LimeReport"; + const QString DATAFUNCTIONS_MANAGER_NAME = "DatasourceFunctions"; const QString EOW("~!@#$%^&*()+{}|:\"<>?,/;'[]\\-="); const int DEFAULT_TAB_INDENTION = 4; diff --git a/limereport/lrscriptenginemanager.cpp b/limereport/lrscriptenginemanager.cpp index 30cd800..3c16fbb 100644 --- a/limereport/lrscriptenginemanager.cpp +++ b/limereport/lrscriptenginemanager.cpp @@ -353,7 +353,7 @@ void ScriptEngineManager::setDataManager(DataSourceManager *dataManager){ ); addFunction(describer); } - + moveQObjectToScript(new DatasourceFunctions(dataManager), LimeReport::Const::DATAFUNCTIONS_MANAGER_NAME); } } } @@ -564,6 +564,9 @@ void ScriptEngineManager::clearTableOfContents(){ ScriptValueType ScriptEngineManager::moveQObjectToScript(QObject* object, const QString objectName) { + + ScriptValueType obj = scriptEngine()->globalObject().property(objectName); + if (!obj.isNull()) delete obj.toQObject(); ScriptValueType result = scriptEngine()->newQObject(object); scriptEngine()->globalObject().setProperty(objectName, result); return result; @@ -866,7 +869,6 @@ ScriptEngineManager::ScriptEngineManager() m_scriptEngine->setDefaultPrototype(qMetaTypeId(), m_scriptEngine->newQObject(new ComboBoxPrototype())); #endif - createLineFunction(); createNumberFomatFunction(); createDateFormatFunction(); @@ -1786,8 +1788,6 @@ void LimeReport::TableOfContents::clear(){ } -//#ifdef USE_QJSENGINE - QObject* ComboBoxWrapperCreator::createWrapper(QObject *item) { QComboBox* comboBox = dynamic_cast(item); @@ -1797,7 +1797,19 @@ QObject* ComboBoxWrapperCreator::createWrapper(QObject *item) return 0; } -//#endif +bool DatasourceFunctions::next(const QString &datasourceName){ + if (m_dataManager && m_dataManager->dataSource(datasourceName)) + return m_dataManager->dataSource(datasourceName)->next(); + return false; +} + +bool DatasourceFunctions::isEOF(const QString &datasourceName) +{ + if (m_dataManager && m_dataManager->dataSource(datasourceName)) + return m_dataManager->dataSource(datasourceName)->eof(); + return false; +} + #ifndef USE_QJSENGINE void ComboBoxPrototype::addItem(const QString &text) diff --git a/limereport/lrscriptenginemanager.h b/limereport/lrscriptenginemanager.h index 076ee21..30c5d38 100644 --- a/limereport/lrscriptenginemanager.h +++ b/limereport/lrscriptenginemanager.h @@ -52,6 +52,8 @@ #include "lrscriptenginemanagerintf.h" #include "lrcallbackdatasourceintf.h" #include "lrcollection.h" +#include "lrdatasourceintf.h" +#include "lrdatasourcemanagerintf.h" namespace LimeReport{ @@ -296,6 +298,16 @@ private: QObject* createWrapper(QObject* item); }; +class DatasourceFunctions : public QObject{ + Q_OBJECT +public: + explicit DatasourceFunctions(IDataSourceManager* dataManager): m_dataManager(dataManager){} + Q_INVOKABLE bool next(const QString& datasourceName); + Q_INVOKABLE bool isEOF(const QString& datasourceName); +private: + IDataSourceManager* m_dataManager; +}; + class ScriptFunctionsManager : public QObject{ Q_OBJECT public: