mirror of
https://github.com/fralx/LimeReport.git
synced 2024-12-23 16:22:58 +03:00
0fca7169d3
except those placed in 3rdparty directories.
2310 lines
79 KiB
C++
2310 lines
79 KiB
C++
/***************************************************************************
|
|
* This file is part of the Lime Report project *
|
|
* Copyright (C) 2021 by Alexander Arin *
|
|
* arin_a@bk.ru *
|
|
* *
|
|
** GNU General Public License Usage **
|
|
* *
|
|
* This library is free software: you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation, either version 3 of the License, or *
|
|
* (at your option) any later version. *
|
|
* You should have received a copy of the GNU General Public License *
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
|
* *
|
|
** GNU Lesser General Public License **
|
|
* *
|
|
* This library is free software: you can redistribute it and/or modify *
|
|
* it under the terms of the GNU Lesser General Public License as *
|
|
* published by the Free Software Foundation, either version 3 of the *
|
|
* License, or (at your option) any later version. *
|
|
* You should have received a copy of the GNU Lesser General Public *
|
|
* License along with this library. *
|
|
* If not, see <http://www.gnu.org/licenses/>. *
|
|
* *
|
|
* This library is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU General Public License for more details. *
|
|
****************************************************************************/
|
|
#include "lrscriptenginemanager.h"
|
|
|
|
#include <QDate>
|
|
#include <QStringList>
|
|
#include <QUuid>
|
|
#ifdef USE_QTSCRIPTENGINE
|
|
#include <QScriptValueIterator>
|
|
#endif
|
|
#include <QMessageBox>
|
|
#ifdef HAVE_UI_LOADER
|
|
#include <QBuffer>
|
|
#include <QUiLoader>
|
|
#include <QWidget>
|
|
#endif
|
|
#include "lrbanddesignintf.h"
|
|
#include "lrbasedesignintf.h"
|
|
#include "lrdatasourcemanager.h"
|
|
#include "lrpageitemdesignintf.h"
|
|
|
|
Q_DECLARE_METATYPE(QColor)
|
|
Q_DECLARE_METATYPE(QFont)
|
|
Q_DECLARE_METATYPE(LimeReport::ScriptEngineManager*)
|
|
|
|
#ifdef USE_QTSCRIPTENGINE
|
|
QScriptValue constructColor(QScriptContext* context, QScriptEngine* engine)
|
|
{
|
|
QColor color(context->argument(0).toString());
|
|
return engine->toScriptValue(color);
|
|
}
|
|
#endif
|
|
|
|
namespace LimeReport {
|
|
|
|
ScriptEngineNode::ScriptEngineNode(const QString& name, const QString& description,
|
|
ScriptEngineNode::NodeType type, ScriptEngineNode* parent,
|
|
const QIcon& icon):
|
|
m_name(name),
|
|
m_description(description),
|
|
m_icon(icon),
|
|
m_type(type),
|
|
m_parent(parent)
|
|
{
|
|
}
|
|
|
|
ScriptEngineNode::~ScriptEngineNode() { qDeleteAll(m_childs.begin(), m_childs.end()); }
|
|
|
|
ScriptEngineNode* ScriptEngineNode::addChild(const QString& name, const QString& description,
|
|
ScriptEngineNode::NodeType type, const QIcon& icon)
|
|
{
|
|
ScriptEngineNode* res = new ScriptEngineNode(name, description, type, this, icon);
|
|
m_childs.push_back(res);
|
|
return res;
|
|
}
|
|
|
|
int ScriptEngineNode::row()
|
|
{
|
|
if (m_parent) {
|
|
return m_parent->m_childs.indexOf(const_cast<ScriptEngineNode*>(this));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void ScriptEngineNode::clear()
|
|
{
|
|
for (int i = 0; i < m_childs.count(); ++i) {
|
|
delete m_childs[i];
|
|
}
|
|
m_childs.clear();
|
|
}
|
|
|
|
ScriptEngineModel::ScriptEngineModel(ScriptEngineManager* scriptManager):
|
|
m_rootNode(new ScriptEngineNode())
|
|
{
|
|
setScriptEngineManager(scriptManager);
|
|
}
|
|
|
|
ScriptEngineModel::~ScriptEngineModel() { delete m_rootNode; }
|
|
|
|
QModelIndex ScriptEngineModel::parent(const QModelIndex& child) const
|
|
{
|
|
if (!child.isValid())
|
|
return QModelIndex();
|
|
|
|
ScriptEngineNode* childNode = nodeFromIndex(child);
|
|
if (!childNode)
|
|
return QModelIndex();
|
|
|
|
ScriptEngineNode* parentNode = childNode->parent();
|
|
if ((parentNode == m_rootNode) || (!parentNode))
|
|
return QModelIndex();
|
|
return createIndex(parentNode->row(), 0, parentNode);
|
|
}
|
|
|
|
QModelIndex ScriptEngineModel::index(int row, int column, const QModelIndex& parent) const
|
|
{
|
|
if (!m_rootNode)
|
|
return QModelIndex();
|
|
|
|
if (!hasIndex(row, column, parent))
|
|
return QModelIndex();
|
|
|
|
ScriptEngineNode* parentNode;
|
|
if (parent.isValid()) {
|
|
parentNode = nodeFromIndex(parent);
|
|
} else {
|
|
parentNode = m_rootNode;
|
|
}
|
|
|
|
ScriptEngineNode* childNode = parentNode->child(row);
|
|
if (childNode) {
|
|
return createIndex(row, column, childNode);
|
|
} else
|
|
return QModelIndex();
|
|
}
|
|
|
|
int ScriptEngineModel::rowCount(const QModelIndex& parent) const
|
|
{
|
|
if (!m_rootNode)
|
|
return 0;
|
|
ScriptEngineNode* parentNode;
|
|
if (parent.isValid())
|
|
parentNode = nodeFromIndex(parent);
|
|
else
|
|
parentNode = m_rootNode;
|
|
return parentNode->childCount();
|
|
}
|
|
|
|
int ScriptEngineModel::columnCount(const QModelIndex& parent) const
|
|
{
|
|
Q_UNUSED(parent)
|
|
return 1;
|
|
}
|
|
|
|
QVariant ScriptEngineModel::data(const QModelIndex& index, int role) const
|
|
{
|
|
ScriptEngineNode* node = nodeFromIndex(index);
|
|
switch (role) {
|
|
case Qt::DisplayRole:
|
|
if (!node)
|
|
return QVariant();
|
|
return node->name();
|
|
break;
|
|
case Qt::DecorationRole:
|
|
if (!node)
|
|
return QIcon();
|
|
return node->icon();
|
|
break;
|
|
default:
|
|
return QVariant();
|
|
}
|
|
}
|
|
|
|
void ScriptEngineModel::setScriptEngineManager(ScriptEngineManager* scriptManager)
|
|
{
|
|
m_scriptManager = scriptManager;
|
|
updateModel();
|
|
}
|
|
|
|
void ScriptEngineModel::slotScriptEngineChanged() { updateModel(); }
|
|
|
|
ScriptEngineNode* ScriptEngineModel::nodeFromIndex(const QModelIndex& index) const
|
|
{
|
|
if (index.isValid()) {
|
|
return static_cast<ScriptEngineNode*>(index.internalPointer());
|
|
} else
|
|
return m_rootNode;
|
|
}
|
|
|
|
void ScriptEngineModel::updateModel()
|
|
{
|
|
beginResetModel();
|
|
m_rootNode->clear();
|
|
QMap<QString, ScriptEngineNode*> categories;
|
|
foreach (ScriptFunctionDesc funcDesc, m_scriptManager->functionsDescribers()) {
|
|
ScriptEngineNode* categ;
|
|
QString categoryName = (!funcDesc.category.isEmpty()) ? funcDesc.category : "NO CATEGORY";
|
|
if (categories.contains(categoryName)) {
|
|
categ = categories.value(categoryName);
|
|
} else {
|
|
categ = m_rootNode->addChild(categoryName, "", ScriptEngineNode::Category,
|
|
QIcon(":/report/images/folder"));
|
|
categories.insert(categoryName, categ);
|
|
}
|
|
categ->addChild(funcDesc.name, funcDesc.description, ScriptEngineNode::Function,
|
|
QIcon(":/report/images/function"));
|
|
}
|
|
endResetModel();
|
|
}
|
|
|
|
ScriptEngineManager::~ScriptEngineManager()
|
|
{
|
|
delete m_model;
|
|
m_model = 0;
|
|
delete m_scriptEngine;
|
|
}
|
|
|
|
bool ScriptEngineManager::isFunctionExists(const QString& functionName) const
|
|
{
|
|
return m_functions.contains(functionName);
|
|
// foreach (ScriptFunctionDesc desc, m_functions.values()) {
|
|
// if (desc.name.compare(functionName,Qt::CaseInsensitive)==0){
|
|
// return true;
|
|
// }
|
|
// }
|
|
// return false;
|
|
}
|
|
|
|
void ScriptEngineManager::deleteFunction(const QString& functionsName)
|
|
{
|
|
m_functions.remove(functionsName);
|
|
}
|
|
|
|
bool ScriptEngineManager::addFunction(const JSFunctionDesc& functionDescriber)
|
|
{
|
|
if (m_functions.contains(functionDescriber.name()))
|
|
return false;
|
|
ScriptValueType functionManager
|
|
= scriptEngine()->globalObject().property(functionDescriber.managerName());
|
|
#ifdef USE_QJSENGINE
|
|
if (functionManager.isUndefined()) {
|
|
#else
|
|
if (!functionManager.isValid()) {
|
|
#endif
|
|
functionManager = scriptEngine()->newQObject(functionDescriber.manager());
|
|
scriptEngine()->globalObject().setProperty(functionDescriber.managerName(),
|
|
functionManager);
|
|
}
|
|
|
|
if (functionManager.toQObject() == functionDescriber.manager()) {
|
|
ScriptValueType checkWrapper = scriptEngine()->evaluate(functionDescriber.scriptWrapper());
|
|
if (!checkWrapper.isError()) {
|
|
ScriptFunctionDesc funct;
|
|
funct.name = functionDescriber.name();
|
|
funct.description = functionDescriber.description();
|
|
funct.category = functionDescriber.category();
|
|
funct.type = ScriptFunctionDesc::Native;
|
|
m_functions.insert(funct.name, funct);
|
|
if (m_model)
|
|
m_model->updateModel();
|
|
return true;
|
|
} else {
|
|
m_lastError = checkWrapper.toString();
|
|
return false;
|
|
}
|
|
} else {
|
|
m_lastError = tr("Function manager with name \"%1\" already exists!");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
#ifdef USE_QTSCRIPTENGINE
|
|
#if QT_VERSION > 0x050600
|
|
Q_DECL_DEPRECATED
|
|
#endif
|
|
bool ScriptEngineManager::addFunction(const QString& name,
|
|
QScriptEngine::FunctionSignature function,
|
|
const QString& category, const QString& description)
|
|
{
|
|
if (!isFunctionExists(name)) {
|
|
ScriptFunctionDesc funct;
|
|
funct.name = name;
|
|
funct.description = description;
|
|
funct.category = category;
|
|
funct.scriptValue = scriptEngine()->newFunction(function);
|
|
funct.scriptValue.setProperty("functionName", name);
|
|
funct.scriptValue.setData(m_scriptEngine->toScriptValue(this));
|
|
funct.type = ScriptFunctionDesc::Native;
|
|
m_functions.insert(name, funct);
|
|
if (m_model)
|
|
m_model->updateModel();
|
|
m_scriptEngine->globalObject().setProperty(funct.name, funct.scriptValue);
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
bool ScriptEngineManager::addFunction(const QString& name, const QString& script,
|
|
const QString& category, const QString& description)
|
|
{
|
|
ScriptValueType functionValue = m_scriptEngine->evaluate(script);
|
|
if (!functionValue.isError()) {
|
|
ScriptFunctionDesc funct;
|
|
funct.scriptValue = functionValue;
|
|
funct.name = name;
|
|
funct.category = category;
|
|
funct.description = description;
|
|
funct.type = ScriptFunctionDesc::Script;
|
|
m_functions.insert(name, funct);
|
|
m_model->updateModel();
|
|
return true;
|
|
} else {
|
|
m_lastError = functionValue.toString();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
QStringList ScriptEngineManager::functionsNames()
|
|
{
|
|
return m_functions.keys();
|
|
// QStringList res;
|
|
// foreach(ScriptFunctionDesc func, m_functions){
|
|
// res<<func.name;
|
|
// }
|
|
// return res;
|
|
}
|
|
|
|
void ScriptEngineManager::setDataManager(DataSourceManager* dataManager)
|
|
{
|
|
if (dataManager && m_dataManager != dataManager) {
|
|
m_dataManager = dataManager;
|
|
if (m_dataManager) {
|
|
foreach (QString func, m_dataManager->groupFunctionNames()) {
|
|
JSFunctionDesc describer(
|
|
func, tr("GROUP FUNCTIONS"),
|
|
func + "(\"" + tr("FieldName") + "\",\"" + tr("BandName") + "\")",
|
|
LimeReport::Const::FUNCTION_MANAGER_NAME, m_functionManager,
|
|
QString("function %1(fieldName, bandName, pageitem){\
|
|
if (typeof pageitem == 'undefined') return %2.calcGroupFunction(\"%1\", fieldName, bandName); \
|
|
else return %2.calcGroupFunction(\"%1\", fieldName, bandName, pageitem);}")
|
|
.arg(func)
|
|
.arg(LimeReport::Const::FUNCTION_MANAGER_NAME));
|
|
addFunction(describer);
|
|
}
|
|
moveQObjectToScript(new DatasourceFunctions(dataManager),
|
|
LimeReport::Const::DATAFUNCTIONS_MANAGER_NAME);
|
|
}
|
|
}
|
|
}
|
|
|
|
QString ScriptEngineManager::expandUserVariables(QString context, RenderPass /* pass */,
|
|
ExpandType expandType, QVariant& varValue)
|
|
{
|
|
#if (QT_VERSION < QT_VERSION_CHECK(5, 15, 1))
|
|
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 {
|
|
|
|
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;
|
|
#else
|
|
QRegularExpression rx = getVariableRegEx();
|
|
if (context.contains(rx)) {
|
|
int pos = 0;
|
|
QRegularExpressionMatch match = rx.match(context, pos);
|
|
while (match.hasMatch()) {
|
|
|
|
QString variable = match.captured(1);
|
|
pos = match.capturedEnd();
|
|
|
|
if (dataManager()->containsVariable(variable)) {
|
|
try {
|
|
|
|
varValue = dataManager()->variable(variable);
|
|
switch (expandType) {
|
|
case EscapeSymbols:
|
|
context.replace(match.captured(0), escapeSimbols(varValue.toString()));
|
|
break;
|
|
case NoEscapeSymbols:
|
|
context.replace(match.captured(0), varValue.toString());
|
|
break;
|
|
case ReplaceHTMLSymbols:
|
|
context.replace(match.captured(0), replaceHTMLSymbols(varValue.toString()));
|
|
break;
|
|
}
|
|
|
|
pos = 0;
|
|
|
|
} catch (ReportError& e) {
|
|
dataManager()->putError(e.what());
|
|
if (!dataManager()->reportSettings()
|
|
|| dataManager()->reportSettings()->suppressAbsentFieldsAndVarsWarnings())
|
|
context.replace(match.captured(0), e.what());
|
|
else
|
|
context.replace(match.captured(0), "");
|
|
}
|
|
} else {
|
|
|
|
QString error;
|
|
error = tr("Variable %1 not found").arg(variable);
|
|
dataManager()->putError(error);
|
|
if (!dataManager()->reportSettings()
|
|
|| dataManager()->reportSettings()->suppressAbsentFieldsAndVarsWarnings())
|
|
context.replace(match.captured(0), error);
|
|
else
|
|
context.replace(match.captured(0), "");
|
|
}
|
|
|
|
match = rx.match(context, pos);
|
|
}
|
|
}
|
|
return context;
|
|
#endif
|
|
}
|
|
|
|
QString ScriptEngineManager::expandDataFields(QString context, ExpandType expandType,
|
|
QVariant& varValue, QObject* reportItem)
|
|
{
|
|
#if (QT_VERSION < QT_VERSION_CHECK(5, 15, 1))
|
|
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 (varValue.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;
|
|
if (reportItem) {
|
|
error
|
|
= tr("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;
|
|
#else
|
|
QRegularExpression rx = getFieldRegEx();
|
|
if (context.contains(rx)) {
|
|
QRegularExpressionMatch match = rx.match(context);
|
|
while (match.hasMatch()) {
|
|
|
|
QString field = match.captured(1);
|
|
|
|
if (dataManager()->containsField(field)) {
|
|
QString fieldValue;
|
|
varValue = dataManager()->fieldData(field);
|
|
if (expandType == EscapeSymbols) {
|
|
if (varValue.isNull()) {
|
|
fieldValue = "\"\"";
|
|
} else {
|
|
fieldValue = escapeSimbols(varValue.toString());
|
|
// TODO: Migrate to QMetaType
|
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
|
switch (dataManager()->fieldData(field).typeId()) {
|
|
case QMetaType::QChar:
|
|
case QMetaType::QString:
|
|
case QMetaType::QStringList:
|
|
case QMetaType::QDate:
|
|
case QMetaType::QDateTime:
|
|
fieldValue = "\"" + fieldValue + "\"";
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
#else
|
|
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;
|
|
}
|
|
#endif
|
|
}
|
|
} else {
|
|
if (expandType == ReplaceHTMLSymbols)
|
|
fieldValue = replaceHTMLSymbols(varValue.toString());
|
|
else
|
|
fieldValue = varValue.toString();
|
|
}
|
|
|
|
context.replace(match.captured(0), fieldValue);
|
|
|
|
} else {
|
|
QString error;
|
|
if (reportItem) {
|
|
error
|
|
= tr("Field %1 not found in %2!").arg(field).arg(reportItem->objectName());
|
|
dataManager()->putError(error);
|
|
}
|
|
varValue = QVariant();
|
|
if (!dataManager()->reportSettings()
|
|
|| !dataManager()->reportSettings()->suppressAbsentFieldsAndVarsWarnings())
|
|
context.replace(match.captured(0), error);
|
|
else
|
|
context.replace(match.captured(0), "");
|
|
}
|
|
match = rx.match(context);
|
|
}
|
|
}
|
|
|
|
return context;
|
|
#endif
|
|
}
|
|
|
|
QString ScriptEngineManager::expandScripts(QString context, QVariant& varValue, QObject* reportItem)
|
|
{
|
|
#if (QT_VERSION < QT_VERSION_CHECK(5, 15, 1))
|
|
QRegExp rx(Const::SCRIPT_RX);
|
|
|
|
if (context.contains(rx)) {
|
|
#else
|
|
QRegularExpression rx = getScriptRegEx();
|
|
if (context.contains(rx)) {
|
|
#endif
|
|
|
|
if (ScriptEngineManager::instance().dataManager() != dataManager())
|
|
ScriptEngineManager::instance().setDataManager(dataManager());
|
|
|
|
ScriptEngineType* se = ScriptEngineManager::instance().scriptEngine();
|
|
|
|
if (reportItem) {
|
|
ScriptValueType svThis;
|
|
#ifdef USE_QJSENGINE
|
|
svThis = getJSValue(*se, reportItem);
|
|
se->globalObject().setProperty("THIS", svThis);
|
|
#else
|
|
svThis = se->globalObject().property("THIS");
|
|
if (svThis.isValid()) {
|
|
se->newQObject(svThis, reportItem);
|
|
} else {
|
|
svThis = se->newQObject(reportItem);
|
|
se->globalObject().setProperty("THIS", svThis);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
ScriptExtractor scriptExtractor(context);
|
|
if (scriptExtractor.parse()) {
|
|
context
|
|
= replaceScripts(context, varValue, reportItem, se, scriptExtractor.scriptTree());
|
|
}
|
|
}
|
|
return context;
|
|
}
|
|
|
|
QString ScriptEngineManager::replaceScripts(QString context, QVariant& varValue,
|
|
QObject* reportItem, ScriptEngineType* se,
|
|
ScriptNode::Ptr scriptTree)
|
|
{
|
|
foreach (ScriptNode::Ptr item, scriptTree->children()) {
|
|
QString scriptBody = expandDataFields(item->body(), EscapeSymbols, varValue, reportItem);
|
|
if (item->children().size() > 0)
|
|
scriptBody = replaceScripts(scriptBody, varValue, reportItem, se, item);
|
|
scriptBody = expandUserVariables(scriptBody, FirstPass, EscapeSymbols, varValue);
|
|
ScriptValueType value = se->evaluate(scriptBody);
|
|
#ifdef USE_QJSENGINE
|
|
if (!value.isError()) {
|
|
varValue = value.toVariant();
|
|
context.replace(item->script(), value.toString());
|
|
} else {
|
|
context.replace(item->script(), value.toString());
|
|
}
|
|
#else
|
|
if (!se->hasUncaughtException()) {
|
|
varValue = value.toVariant();
|
|
context.replace(item->script(), value.toString());
|
|
} else {
|
|
context.replace(item->script(), se->uncaughtException().toString());
|
|
}
|
|
#endif
|
|
}
|
|
return context;
|
|
}
|
|
|
|
QVariant ScriptEngineManager::evaluateScript(const QString& script)
|
|
{
|
|
|
|
#if (QT_VERSION < QT_VERSION_CHECK(5, 15, 1))
|
|
QRegExp rx(Const::SCRIPT_RX);
|
|
QVariant varValue;
|
|
|
|
if (script.contains(rx)) {
|
|
#else
|
|
QRegularExpression rx = getScriptRegEx();
|
|
QVariant varValue;
|
|
|
|
if (script.contains(rx)) {
|
|
#endif
|
|
|
|
if (ScriptEngineManager::instance().dataManager() != dataManager())
|
|
ScriptEngineManager::instance().setDataManager(dataManager());
|
|
|
|
ScriptEngineType* se = ScriptEngineManager::instance().scriptEngine();
|
|
|
|
ScriptExtractor scriptExtractor(script);
|
|
if (scriptExtractor.parse()) {
|
|
QString scriptBody = expandDataFields(scriptExtractor.scriptTree()->body(),
|
|
EscapeSymbols, varValue, 0);
|
|
scriptBody = expandUserVariables(scriptBody, FirstPass, EscapeSymbols, varValue);
|
|
ScriptValueType value = se->evaluate(scriptBody);
|
|
#ifdef USE_QJSENGINE
|
|
if (!value.isError()) {
|
|
#else
|
|
if (!se->hasUncaughtException()) {
|
|
#endif
|
|
return value.toVariant();
|
|
}
|
|
}
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
void ScriptEngineManager::addBookMark(const QString& uniqKey, const QString& content)
|
|
{
|
|
Q_ASSERT(m_context != 0);
|
|
if (m_context) {
|
|
BandDesignIntf* currentBand = m_context->currentBand();
|
|
if (currentBand)
|
|
currentBand->addBookmark(uniqKey, content);
|
|
else if (m_context->currentPage()) {
|
|
m_context->currentPage()->addBookmark(uniqKey, content);
|
|
}
|
|
}
|
|
}
|
|
|
|
int ScriptEngineManager::findPageIndexByBookmark(const QString& uniqKey)
|
|
{
|
|
for (int i = 0; i < m_context->reportPages()->size(); ++i) {
|
|
if (m_context->reportPages()->at(i)->bookmarks().contains(uniqKey))
|
|
return i + 1;
|
|
foreach (BandDesignIntf* band, m_context->reportPages()->at(i)->bands()) {
|
|
if (band->bookmarks().contains(uniqKey))
|
|
return i + 1;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int ScriptEngineManager::getPageFreeSpace(PageItemDesignIntf* page)
|
|
{
|
|
if (page) {
|
|
int height = 0;
|
|
foreach (BandDesignIntf* band, page->bands()) {
|
|
if (band->type() == BandDesignIntf::Data) {
|
|
height += band->geometry().height()
|
|
* m_dataManager->dataSource(band->datasourceName())->model()->rowCount();
|
|
} else
|
|
height += band->height();
|
|
}
|
|
return page->height() - height - (page->pageFooter() ? page->pageFooter()->height() : 0);
|
|
} else
|
|
return -1;
|
|
}
|
|
|
|
void ScriptEngineManager::addTableOfContentsItem(const QString& uniqKey, const QString& content,
|
|
int indent)
|
|
{
|
|
Q_ASSERT(m_context != 0);
|
|
if (m_context) {
|
|
m_context->tableOfContents()->setItem(uniqKey, content, 0, indent);
|
|
addBookMark(uniqKey, content);
|
|
}
|
|
}
|
|
|
|
void ScriptEngineManager::clearTableOfContents()
|
|
{
|
|
if (m_context) {
|
|
if (m_context->tableOfContents())
|
|
m_context->tableOfContents()->clear();
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
void ScriptEngineManager::updateModel() { }
|
|
|
|
bool ScriptEngineManager::createLineFunction()
|
|
{
|
|
JSFunctionDesc fd;
|
|
|
|
fd.setManager(m_functionManager);
|
|
fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
|
|
fd.setCategory(tr("SYSTEM"));
|
|
fd.setName("line");
|
|
fd.setDescription("line(\"" + tr("BandName") + "\")");
|
|
fd.setScriptWrapper(QString("function line(bandName){ return %1.line(bandName);}")
|
|
.arg(LimeReport::Const::FUNCTION_MANAGER_NAME));
|
|
|
|
return addFunction(fd);
|
|
}
|
|
|
|
bool ScriptEngineManager::createNumberFomatFunction()
|
|
{
|
|
JSFunctionDesc fd;
|
|
|
|
fd.setManager(m_functionManager);
|
|
fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
|
|
fd.setCategory(tr("NUMBER"));
|
|
fd.setName("numberFormat");
|
|
fd.setDescription("numberFormat(\"" + tr("Value") + "\",\"" + tr("Format") + "\",\""
|
|
+ tr("Precision") + "\",\"" + tr("Locale") + "\")");
|
|
fd.setScriptWrapper(QString("function numberFormat(value, format, precision, locale){"
|
|
" if(typeof(format)==='undefined') format = \"f\"; "
|
|
" if(typeof(precision)==='undefined') precision=2; "
|
|
" if(typeof(locale)==='undefined') locale=\"\"; "
|
|
"return %1.numberFormat(value,format,precision,locale);}")
|
|
.arg(LimeReport::Const::FUNCTION_MANAGER_NAME));
|
|
return addFunction(fd);
|
|
}
|
|
|
|
bool ScriptEngineManager::createDateFormatFunction()
|
|
{
|
|
JSFunctionDesc fd;
|
|
|
|
fd.setManager(m_functionManager);
|
|
fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
|
|
fd.setCategory(tr("DATE&TIME"));
|
|
fd.setName("dateFormat");
|
|
fd.setDescription("dateFormat(\"" + tr("Value") + "\",\"" + tr("Format") + "\", \""
|
|
+ tr("Locale") + "\")");
|
|
fd.setScriptWrapper(QString("function dateFormat(value, format, locale){"
|
|
" if(typeof(format)==='undefined') format = \"dd.MM.yyyy\"; "
|
|
"return %1.dateFormat(value,format, locale);}")
|
|
.arg(LimeReport::Const::FUNCTION_MANAGER_NAME));
|
|
return addFunction(fd);
|
|
}
|
|
|
|
bool ScriptEngineManager::createTimeFormatFunction()
|
|
{
|
|
JSFunctionDesc fd;
|
|
|
|
fd.setManager(m_functionManager);
|
|
fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
|
|
fd.setCategory(tr("DATE&TIME"));
|
|
fd.setName("timeFormat");
|
|
fd.setDescription("timeFormat(\"" + tr("Value") + "\",\"" + tr("Format") + "\")");
|
|
fd.setScriptWrapper(QString("function timeFormat(value, format){"
|
|
" if(typeof(format)==='undefined') format = \"hh:mm\"; "
|
|
"return %1.timeFormat(value,format);}")
|
|
.arg(LimeReport::Const::FUNCTION_MANAGER_NAME));
|
|
return addFunction(fd);
|
|
}
|
|
|
|
bool ScriptEngineManager::createDateTimeFormatFunction()
|
|
{
|
|
JSFunctionDesc fd;
|
|
|
|
fd.setManager(m_functionManager);
|
|
fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
|
|
fd.setCategory(tr("DATE&TIME"));
|
|
fd.setName("dateTimeFormat");
|
|
fd.setDescription("dateTimeFormat(\"" + tr("Value") + "\",\"" + tr("Format") + "\", \""
|
|
+ tr("Locale") + "\")");
|
|
fd.setScriptWrapper(QString("function dateTimeFormat(value, format, locale){"
|
|
" if(typeof(format)==='undefined') format = \"dd.MM.yyyy hh:mm\"; "
|
|
"return %1.dateTimeFormat(value, format, locale);}")
|
|
.arg(LimeReport::Const::FUNCTION_MANAGER_NAME));
|
|
return addFunction(fd);
|
|
}
|
|
|
|
bool ScriptEngineManager::createSectotimeFormatFunction()
|
|
{
|
|
JSFunctionDesc fd;
|
|
|
|
fd.setManager(m_functionManager);
|
|
fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
|
|
fd.setCategory(tr("DATE&TIME"));
|
|
fd.setName("sectotimeFormat");
|
|
fd.setDescription("sectotimeFormat(\"" + tr("Value") + "\",\"" + tr("Format") + "\")");
|
|
fd.setScriptWrapper(QString("function sectotimeFormat(value, format){"
|
|
" if(typeof(format)==='undefined') format = \"hh:mm:ss\"; "
|
|
"return %1.sectotimeFormat(value,format);}")
|
|
.arg(LimeReport::Const::FUNCTION_MANAGER_NAME));
|
|
return addFunction(fd);
|
|
}
|
|
|
|
bool ScriptEngineManager::createDateFunction()
|
|
{
|
|
// addFunction("date",date,"DATE&TIME","date()");
|
|
JSFunctionDesc fd;
|
|
|
|
fd.setManager(m_functionManager);
|
|
fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
|
|
fd.setCategory(tr("DATE&TIME"));
|
|
fd.setName("date");
|
|
fd.setDescription("date()");
|
|
fd.setScriptWrapper(QString("function date(){"
|
|
"return %1.date();}")
|
|
.arg(LimeReport::Const::FUNCTION_MANAGER_NAME));
|
|
return addFunction(fd);
|
|
}
|
|
|
|
bool ScriptEngineManager::createNowFunction()
|
|
{
|
|
// addFunction("now",now,"DATE&TIME","now()");
|
|
JSFunctionDesc fd;
|
|
|
|
fd.setManager(m_functionManager);
|
|
fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
|
|
fd.setCategory(tr("DATE&TIME"));
|
|
fd.setName("now");
|
|
fd.setDescription("now()");
|
|
fd.setScriptWrapper(QString("function now(){"
|
|
"return %1.now();}")
|
|
.arg(LimeReport::Const::FUNCTION_MANAGER_NAME));
|
|
return addFunction(fd);
|
|
}
|
|
|
|
bool ScriptEngineManager::createCurrencyFormatFunction()
|
|
{
|
|
// addFunction("currencyFormat",currencyFormat,"NUMBER","currencyFormat(\""+tr("Value")+"\",\""+tr("Locale")+"\")");
|
|
JSFunctionDesc fd;
|
|
|
|
fd.setManager(m_functionManager);
|
|
fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
|
|
fd.setCategory(tr("NUMBER"));
|
|
fd.setName("currencyFormat");
|
|
fd.setDescription("currencyFormat(\"" + tr("Value") + "\",\"" + tr("Locale") + "\")");
|
|
fd.setScriptWrapper(QString("function currencyFormat(value, locale){"
|
|
" if(typeof(locale)==='undefined') locale = \"\"; "
|
|
"return %1.currencyFormat(value,locale);}")
|
|
.arg(LimeReport::Const::FUNCTION_MANAGER_NAME));
|
|
return addFunction(fd);
|
|
}
|
|
|
|
bool ScriptEngineManager::createCurrencyUSBasedFormatFunction()
|
|
{
|
|
// addFunction("currencyUSBasedFormat",currencyUSBasedFormat,"NUMBER","currencyUSBasedFormat(\""+tr("Value")+",\""+tr("CurrencySymbol")+"\")");
|
|
JSFunctionDesc fd;
|
|
|
|
fd.setManager(m_functionManager);
|
|
fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
|
|
fd.setCategory(tr("NUMBER"));
|
|
fd.setName("currencyUSBasedFormat");
|
|
fd.setDescription("currencyUSBasedFormat(\"" + tr("Value") + ",\"" + tr("CurrencySymbol")
|
|
+ "\")");
|
|
fd.setScriptWrapper(QString("function currencyUSBasedFormat(value, currencySymbol){"
|
|
" if(typeof(currencySymbol)==='undefined') currencySymbol = \"\"; "
|
|
"return %1.currencyUSBasedFormat(value,currencySymbol);}")
|
|
.arg(LimeReport::Const::FUNCTION_MANAGER_NAME));
|
|
return addFunction(fd);
|
|
}
|
|
|
|
bool ScriptEngineManager::createSetVariableFunction()
|
|
{
|
|
// addFunction("setVariable", setVariable, "GENERAL",
|
|
// "setVariable(\""+tr("Name")+"\",\""+tr("Value")+"\")");
|
|
JSFunctionDesc fd;
|
|
|
|
fd.setManager(m_functionManager);
|
|
fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
|
|
fd.setCategory(tr("GENERAL"));
|
|
fd.setName("setVariable");
|
|
fd.setDescription("setVariable(\"" + tr("Name") + "\",\"" + tr("Value") + "\")");
|
|
fd.setScriptWrapper(QString("function setVariable(name, value){"
|
|
"return %1.setVariable(name,value);}")
|
|
.arg(LimeReport::Const::FUNCTION_MANAGER_NAME));
|
|
return addFunction(fd);
|
|
}
|
|
|
|
bool ScriptEngineManager::createGetVariableFunction()
|
|
{
|
|
JSFunctionDesc fd;
|
|
fd.setManager(m_functionManager);
|
|
fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
|
|
fd.setCategory(tr("GENERAL"));
|
|
fd.setName("getVariable");
|
|
fd.setDescription("getVariable(\"" + tr("Name") + "\")");
|
|
fd.setScriptWrapper(QString("function getVariable(name){"
|
|
"return %1.getVariable(name);}")
|
|
.arg(LimeReport::Const::FUNCTION_MANAGER_NAME));
|
|
return addFunction(fd);
|
|
}
|
|
|
|
bool ScriptEngineManager::createGetFieldFunction()
|
|
{
|
|
JSFunctionDesc fd;
|
|
fd.setManager(m_functionManager);
|
|
fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
|
|
fd.setCategory(tr("GENERAL"));
|
|
fd.setName("getField");
|
|
fd.setDescription("getField(\"" + tr("Name") + "\")");
|
|
fd.setScriptWrapper(QString("function getField(name){"
|
|
"return %1.getField(name);}")
|
|
.arg(LimeReport::Const::FUNCTION_MANAGER_NAME));
|
|
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::createGetFieldByRowIndex()
|
|
{
|
|
JSFunctionDesc fd;
|
|
fd.setManager(m_functionManager);
|
|
fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
|
|
fd.setCategory(tr("GENERAL"));
|
|
fd.setName("getFieldByRowIndex");
|
|
fd.setDescription("getFieldByRowIndex(\"" + tr("FieldName") + "\", \"" + tr("RowIndex")
|
|
+ "\")");
|
|
fd.setScriptWrapper(QString("function getFieldByRowIndex(fieldName, rowIndex){"
|
|
"return %1.getFieldByRowIndex(fieldName, rowIndex);}")
|
|
.arg(LimeReport::Const::FUNCTION_MANAGER_NAME));
|
|
return addFunction(fd);
|
|
}
|
|
|
|
bool ScriptEngineManager::createAddBookmarkFunction()
|
|
{
|
|
JSFunctionDesc fd;
|
|
fd.setManager(m_functionManager);
|
|
fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
|
|
fd.setCategory(tr("GENERAL"));
|
|
fd.setName("addBookmark");
|
|
fd.setDescription("addBookmark(\"" + tr("Unique identifier") + " \"" + tr("Content") + "\")");
|
|
fd.setScriptWrapper(QString("function addBookmark(uniqKey, content){"
|
|
"return %1.addBookmark(uniqKey, content);}")
|
|
.arg(LimeReport::Const::FUNCTION_MANAGER_NAME));
|
|
return addFunction(fd);
|
|
}
|
|
|
|
bool ScriptEngineManager::createFindPageIndexByBookmark()
|
|
{
|
|
JSFunctionDesc fd;
|
|
fd.setManager(m_functionManager);
|
|
fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
|
|
fd.setCategory(tr("GENERAL"));
|
|
fd.setName("findPageIndexByBookmark");
|
|
fd.setDescription("findPageIndexByBookmark(\"" + tr("Unique identifier") + "\")");
|
|
fd.setScriptWrapper(QString("function findPageIndexByBookmark(uniqKey){"
|
|
"return %1.findPageIndexByBookmark(uniqKey);}")
|
|
.arg(LimeReport::Const::FUNCTION_MANAGER_NAME));
|
|
return addFunction(fd);
|
|
}
|
|
|
|
bool ScriptEngineManager::createAddTableOfContentsItemFunction()
|
|
{
|
|
JSFunctionDesc fd;
|
|
fd.setManager(m_functionManager);
|
|
fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
|
|
fd.setCategory(tr("GENERAL"));
|
|
fd.setName("addTableOfContentsItem");
|
|
fd.setDescription("addTableOfContentsItem(\"" + tr("Unique identifier") + " \"" + tr("Content")
|
|
+ "\", \"" + tr("Indent") + "\")");
|
|
fd.setScriptWrapper(QString("function addTableOfContentsItem(uniqKey, content, indent){"
|
|
"return %1.addTableOfContentsItem(uniqKey, content, indent);}")
|
|
.arg(LimeReport::Const::FUNCTION_MANAGER_NAME));
|
|
return addFunction(fd);
|
|
}
|
|
|
|
bool ScriptEngineManager::createClearTableOfContentsFunction()
|
|
{
|
|
JSFunctionDesc fd;
|
|
fd.setManager(m_functionManager);
|
|
fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
|
|
fd.setCategory(tr("GENERAL"));
|
|
fd.setName("clearTableOfContents");
|
|
fd.setDescription("clearTableOfContents()");
|
|
fd.setScriptWrapper(QString("function clearTableOfContents(){"
|
|
"return %1.clearTableOfContents();}")
|
|
.arg(LimeReport::Const::FUNCTION_MANAGER_NAME));
|
|
return addFunction(fd);
|
|
}
|
|
|
|
bool ScriptEngineManager::createReopenDatasourceFunction()
|
|
{
|
|
JSFunctionDesc fd;
|
|
fd.setManager(m_functionManager);
|
|
fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
|
|
fd.setCategory(tr("GENERAL"));
|
|
fd.setName("reopenDatasource");
|
|
fd.setDescription("reopenDatasource(\"" + tr("datasourceName") + "\")");
|
|
fd.setScriptWrapper(QString("function reopenDatasource(datasourceName){"
|
|
"return %1.reopenDatasource(datasourceName);}")
|
|
.arg(LimeReport::Const::FUNCTION_MANAGER_NAME));
|
|
return addFunction(fd);
|
|
}
|
|
|
|
bool ScriptEngineManager::createGetFieldByRowIndexEx()
|
|
{
|
|
JSFunctionDesc fd;
|
|
fd.setManager(m_functionManager);
|
|
fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
|
|
fd.setCategory(tr("GENERAL"));
|
|
fd.setName("getFieldByRowIndexEx");
|
|
fd.setDescription("getFieldByRowIndexEx(\"" + tr("FieldName") + "\", \"" + tr("RowIndex")
|
|
+ "\", \"" + tr("RoleIndex") + "\")");
|
|
fd.setScriptWrapper(QString("function getFieldByRowIndexEx(fieldName, rowIndex, role){"
|
|
"return %1.getFieldByRowIndexEx(fieldName, rowIndex, role);}")
|
|
.arg(LimeReport::Const::FUNCTION_MANAGER_NAME));
|
|
return addFunction(fd);
|
|
}
|
|
|
|
bool ScriptEngineManager::createGetFieldByRowIndexEx2()
|
|
{
|
|
JSFunctionDesc fd;
|
|
fd.setManager(m_functionManager);
|
|
fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
|
|
fd.setCategory(tr("GENERAL"));
|
|
fd.setName("getFieldByRowIndexEx2");
|
|
fd.setDescription("getFieldByRowIndexEx2(\"" + tr("FieldName") + "\", \"" + tr("RowIndex")
|
|
+ "\", \"" + tr("RoleName") + "\")");
|
|
fd.setScriptWrapper(QString("function getFieldByRowIndexEx2(fieldName, rowIndex, role){"
|
|
"return %1.getFieldByRowIndexEx2(fieldName, rowIndex, role);}")
|
|
.arg(LimeReport::Const::FUNCTION_MANAGER_NAME));
|
|
return addFunction(fd);
|
|
}
|
|
|
|
bool ScriptEngineManager::createHeaderData()
|
|
{
|
|
JSFunctionDesc fd;
|
|
fd.setManager(m_functionManager);
|
|
fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
|
|
fd.setCategory(tr("GENERAL"));
|
|
fd.setName("getHeaderData");
|
|
fd.setDescription("getHeaderData(\"" + tr("FieldName") + "\", \"" + tr("RoleName") + "\")");
|
|
fd.setScriptWrapper(QString("function getHeaderData(fieldName, role){"
|
|
"return %1.getHeaderData(fieldName, role);}")
|
|
.arg(LimeReport::Const::FUNCTION_MANAGER_NAME));
|
|
return addFunction(fd);
|
|
}
|
|
|
|
bool ScriptEngineManager::createHeaderColumnNameByIndex()
|
|
{
|
|
JSFunctionDesc fd;
|
|
fd.setManager(m_functionManager);
|
|
fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
|
|
fd.setCategory(tr("GENERAL"));
|
|
fd.setName("getHeaderColumnNameByIndex");
|
|
fd.setDescription("getHeaderColumnNameByIndex(\"" + tr("datasourceName") + "\", \""
|
|
+ tr("columnIndex") + "\")");
|
|
fd.setScriptWrapper(
|
|
QString("function getHeaderColumnNameByIndex(datasourceName, columnIndex){"
|
|
"return %1.getHeaderColumnNameByIndex(datasourceName, columnIndex);}")
|
|
.arg(LimeReport::Const::FUNCTION_MANAGER_NAME));
|
|
return addFunction(fd);
|
|
}
|
|
|
|
bool ScriptEngineManager::createColumnCount()
|
|
{
|
|
JSFunctionDesc fd;
|
|
fd.setManager(m_functionManager);
|
|
fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
|
|
fd.setCategory(tr("GENERAL"));
|
|
fd.setName("getColumnCount");
|
|
fd.setDescription("getColumnCount(\"" + tr("datasourceName") + "\")");
|
|
fd.setScriptWrapper(QString("function getColumnCount(datasourceName){"
|
|
"return %1.getColumnCount(datasourceName);}")
|
|
.arg(LimeReport::Const::FUNCTION_MANAGER_NAME));
|
|
return addFunction(fd);
|
|
}
|
|
|
|
ScriptEngineManager::ScriptEngineManager(): m_model(0), m_context(0), m_dataManager(0)
|
|
{
|
|
m_scriptEngine = new ScriptEngineType;
|
|
m_functionManager = new ScriptFunctionsManager(this);
|
|
m_functionManager->setScriptEngineManager(this);
|
|
#ifdef USE_QTSCRIPTENGINE
|
|
m_scriptEngine->setDefaultPrototype(qMetaTypeId<QComboBox*>(),
|
|
m_scriptEngine->newQObject(new ComboBoxPrototype()));
|
|
#endif
|
|
createLineFunction();
|
|
createNumberFomatFunction();
|
|
createDateFormatFunction();
|
|
createTimeFormatFunction();
|
|
createDateTimeFormatFunction();
|
|
createSectotimeFormatFunction();
|
|
createDateFunction();
|
|
createNowFunction();
|
|
#if QT_VERSION > 0x040800
|
|
createCurrencyFormatFunction();
|
|
createCurrencyUSBasedFormatFunction();
|
|
#endif
|
|
createSetVariableFunction();
|
|
createGetFieldFunction();
|
|
createGetFieldByRowIndex();
|
|
createGetFieldByKeyFunction();
|
|
createGetVariableFunction();
|
|
#ifdef USE_QTSCRIPTENGINE
|
|
QScriptValue colorCtor = m_scriptEngine->newFunction(constructColor);
|
|
m_scriptEngine->globalObject().setProperty("QColor", colorCtor);
|
|
|
|
QScriptValue fontProto(
|
|
m_scriptEngine->newQObject(new QFontPrototype, QScriptEngine::ScriptOwnership));
|
|
m_scriptEngine->setDefaultPrototype(qMetaTypeId<QFont>(), fontProto);
|
|
QScriptValue fontConstructor
|
|
= m_scriptEngine->newFunction(QFontPrototype::constructorQFont, fontProto);
|
|
m_scriptEngine->globalObject().setProperty("QFont", fontConstructor);
|
|
#endif
|
|
createAddBookmarkFunction();
|
|
createFindPageIndexByBookmark();
|
|
createAddTableOfContentsItemFunction();
|
|
createClearTableOfContentsFunction();
|
|
createReopenDatasourceFunction();
|
|
createGetFieldByRowIndexEx();
|
|
createGetFieldByRowIndexEx2();
|
|
createHeaderData();
|
|
createHeaderColumnNameByIndex();
|
|
createColumnCount();
|
|
|
|
m_model = new ScriptEngineModel(this);
|
|
}
|
|
|
|
bool ScriptExtractor::parse()
|
|
{
|
|
int currentPos = 0;
|
|
parse(currentPos, None, m_scriptTree);
|
|
return m_scriptTree->children().count() > 0;
|
|
}
|
|
|
|
bool ScriptExtractor::parse(int& curPos, const State& state, ScriptNode::Ptr scriptNode)
|
|
{
|
|
while (curPos < m_context.length()) {
|
|
switch (state) {
|
|
case OpenBracketFound:
|
|
if (m_context[curPos] == '}') {
|
|
return true;
|
|
} else {
|
|
if (m_context[curPos] == '{')
|
|
extractBracket(curPos, scriptNode);
|
|
}
|
|
case None:
|
|
if (m_context[curPos] == '$') {
|
|
int startPos = curPos;
|
|
if (isStartScriptLexem(curPos))
|
|
extractScript(curPos, substring(m_context, startPos, curPos),
|
|
scriptNode->createChildNode());
|
|
if (isStartFieldLexem(curPos) || isStartVariableLexem(curPos))
|
|
skipField(curPos);
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
curPos++;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void ScriptExtractor::extractScript(int& curPos, const QString& startStr,
|
|
ScriptNode::Ptr scriptNode)
|
|
{
|
|
int startPos = curPos;
|
|
if (extractBracket(curPos, scriptNode)) {
|
|
QString scriptBody = substring(m_context, startPos + 1, curPos);
|
|
scriptNode->setBody(scriptBody);
|
|
scriptNode->setStartLex(startStr + '{');
|
|
}
|
|
}
|
|
|
|
void ScriptExtractor::skipField(int& curPos)
|
|
{
|
|
while (curPos < m_context.length()) {
|
|
if (m_context[curPos] == '}') {
|
|
return;
|
|
} else {
|
|
curPos++;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool ScriptExtractor::extractBracket(int& curPos, ScriptNode::Ptr scriptNode)
|
|
{
|
|
curPos++;
|
|
return parse(curPos, OpenBracketFound, scriptNode);
|
|
}
|
|
|
|
bool ScriptExtractor::isStartLexem(int& curPos, QChar value)
|
|
{
|
|
int pos = curPos + 1;
|
|
State ls = BuksFound;
|
|
while (pos < m_context.length()) {
|
|
switch (ls) {
|
|
case BuksFound:
|
|
if (m_context[pos] == value) {
|
|
ls = SignFound;
|
|
} else {
|
|
if (m_context[pos] != ' ')
|
|
return false;
|
|
}
|
|
break;
|
|
case SignFound:
|
|
if (m_context[pos] == '{') {
|
|
curPos = pos;
|
|
return true;
|
|
} else if (m_context[pos] != ' ')
|
|
return false;
|
|
default:
|
|
break;
|
|
}
|
|
pos++;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool ScriptExtractor::isStartScriptLexem(int& curPos)
|
|
{
|
|
return isStartLexem(curPos, Const::SCRIPT_SIGN);
|
|
}
|
|
|
|
bool ScriptExtractor::isStartFieldLexem(int& curPos)
|
|
{
|
|
return isStartLexem(curPos, Const::FIELD_SIGN);
|
|
}
|
|
|
|
bool ScriptExtractor::isStartVariableLexem(int& curPos)
|
|
{
|
|
return isStartLexem(curPos, Const::VARIABLE_SIGN);
|
|
}
|
|
|
|
QString ScriptExtractor::substring(const QString& value, int start, int end)
|
|
{
|
|
return value.mid(start, end - start);
|
|
}
|
|
|
|
QString DialogDescriber::name() const { return m_name; }
|
|
|
|
void DialogDescriber::setName(const QString& name) { m_name = name; }
|
|
|
|
QByteArray DialogDescriber::description() const { return m_description; }
|
|
|
|
void DialogDescriber::setDescription(const QByteArray& description) { m_description = description; }
|
|
|
|
#ifdef HAVE_UI_LOADER
|
|
void ScriptEngineContext::addDialog(const QString& name, const QByteArray& description)
|
|
{
|
|
m_dialogs.push_back(DialogDescriber::create(name, description));
|
|
emit dialogAdded(name);
|
|
}
|
|
|
|
bool ScriptEngineContext::changeDialog(const QString& name, const QByteArray& description)
|
|
{
|
|
foreach (DialogDescriber::Ptr describer, m_dialogs) {
|
|
if (describer->name().compare(name) == 0) {
|
|
describer->setDescription(description);
|
|
{
|
|
QList<DialogPtr>::Iterator it = m_createdDialogs.begin();
|
|
while (it != m_createdDialogs.end()) {
|
|
if ((*it)->objectName() == name) {
|
|
it = m_createdDialogs.erase(it);
|
|
} else {
|
|
++it;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool ScriptEngineContext::changeDialogName(const QString& oldName, const QString& newName)
|
|
{
|
|
foreach (DialogDescriber::Ptr describer, m_dialogs) {
|
|
if (describer->name().compare(oldName) == 0) {
|
|
describer->setName(newName);
|
|
{
|
|
QList<DialogPtr>::Iterator it = m_createdDialogs.begin();
|
|
while (it != m_createdDialogs.end()) {
|
|
if ((*it)->objectName() == oldName) {
|
|
it = m_createdDialogs.erase(it);
|
|
} else {
|
|
++it;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool ScriptEngineContext::previewDialog(const QString& dialogName)
|
|
{
|
|
QDialog* dialog = getDialog(dialogName);
|
|
if (dialog) {
|
|
dialog->exec();
|
|
return true;
|
|
} else {
|
|
m_lastError = tr("Dialog with name: %1 can`t be created").arg(dialogName);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool ScriptEngineContext::containsDialog(const QString& dialogName)
|
|
{
|
|
foreach (DialogDescriber::Ptr dialog, m_dialogs) {
|
|
if (dialog->name() == dialogName)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void ScriptEngineContext::deleteDialog(const QString& dialogName)
|
|
{
|
|
{
|
|
QVector<DialogDescriber::Ptr>::Iterator it = m_dialogs.begin();
|
|
while (it != m_dialogs.end()) {
|
|
if ((*it)->name() == dialogName) {
|
|
it = m_dialogs.erase(it);
|
|
emit dialogDeleted(dialogName);
|
|
} else {
|
|
++it;
|
|
}
|
|
}
|
|
}
|
|
{
|
|
QList<DialogPtr>::Iterator it = m_createdDialogs.begin();
|
|
while (it != m_createdDialogs.end()) {
|
|
if ((*it)->objectName() == dialogName) {
|
|
it = m_createdDialogs.erase(it);
|
|
} else {
|
|
++it;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
void ScriptEngineContext::clear()
|
|
{
|
|
#ifdef HAVE_UI_LOADER
|
|
m_dialogs.clear();
|
|
m_createdDialogs.clear();
|
|
#endif
|
|
m_initScript.clear();
|
|
m_tableOfContents->clear();
|
|
m_lastError = "";
|
|
}
|
|
|
|
QObject* ScriptEngineContext::createElement(const QString& collectionName,
|
|
const QString& elementType)
|
|
{
|
|
Q_UNUSED(elementType)
|
|
#ifdef HAVE_UI_LOADER
|
|
if (collectionName.compare("dialogs", Qt::CaseInsensitive) == 0) {
|
|
m_dialogs.push_back(DialogDescriber::create());
|
|
return m_dialogs.at(m_dialogs.count() - 1).data();
|
|
}
|
|
#else
|
|
Q_UNUSED(collectionName)
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
int ScriptEngineContext::elementsCount(const QString& collectionName)
|
|
{
|
|
#ifdef HAVE_UI_LOADER
|
|
if (collectionName.compare("dialogs", Qt::CaseInsensitive) == 0) {
|
|
return m_dialogs.count();
|
|
};
|
|
#else
|
|
Q_UNUSED(collectionName)
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
QObject* ScriptEngineContext::elementAt(const QString& collectionName, int index)
|
|
{
|
|
#ifdef HAVE_UI_LOADER
|
|
if (collectionName.compare("dialogs", Qt::CaseInsensitive) == 0) {
|
|
return m_dialogs.at(index).data();
|
|
};
|
|
#else
|
|
Q_UNUSED(collectionName)
|
|
Q_UNUSED(index)
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
void ScriptEngineContext::collectionLoadFinished(const QString& collectionName)
|
|
{
|
|
Q_UNUSED(collectionName);
|
|
}
|
|
|
|
ReportPages* ScriptEngineContext::reportPages() const { return m_reportPages; }
|
|
|
|
void ScriptEngineContext::setReportPages(ReportPages* value) { m_reportPages = value; }
|
|
|
|
#ifdef HAVE_UI_LOADER
|
|
QDialog* ScriptEngineContext::createDialog(DialogDescriber* cont)
|
|
{
|
|
QUiLoader loader;
|
|
QByteArray desc = cont->description();
|
|
QBuffer buffer(&desc);
|
|
buffer.open(QIODevice::ReadOnly);
|
|
QDialog* dialog = dynamic_cast<QDialog*>(loader.load(&buffer));
|
|
m_createdDialogs.push_back(QSharedPointer<QDialog>(dialog));
|
|
if (cont->name().compare(dialog->objectName())) {
|
|
cont->setName(dialog->objectName());
|
|
emit dialogNameChanged(dialog->objectName());
|
|
}
|
|
return dialog;
|
|
}
|
|
|
|
QDialog* ScriptEngineContext::findDialog(const QString& dialogName)
|
|
{
|
|
foreach (DialogPtr dialog, m_createdDialogs) {
|
|
if (dialog->objectName() == dialogName)
|
|
return dialog.data();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
DialogDescriber* ScriptEngineContext::findDialogContainer(const QString& dialogName)
|
|
{
|
|
foreach (DialogDescriber::Ptr dialogCont, m_dialogs) {
|
|
if (dialogCont->name().compare(dialogName, Qt::CaseInsensitive) == 0) {
|
|
return dialogCont.data();
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#endif
|
|
|
|
TableOfContents* ScriptEngineContext::tableOfContents() const { return m_tableOfContents; }
|
|
|
|
void ScriptEngineContext::setTableOfContents(TableOfContents* tableOfContents)
|
|
{
|
|
m_tableOfContents = tableOfContents;
|
|
}
|
|
|
|
PageItemDesignIntf* ScriptEngineContext::currentPage() const { return m_currentPage; }
|
|
|
|
void ScriptEngineContext::setCurrentPage(PageItemDesignIntf* currentPage)
|
|
{
|
|
m_currentPage = currentPage;
|
|
m_currentBand = 0;
|
|
}
|
|
|
|
BandDesignIntf* ScriptEngineContext::currentBand() const { return m_currentBand; }
|
|
|
|
void ScriptEngineContext::setCurrentBand(BandDesignIntf* currentBand)
|
|
{
|
|
m_currentBand = currentBand;
|
|
}
|
|
|
|
#ifdef HAVE_UI_LOADER
|
|
|
|
QDialog* ScriptEngineContext::getDialog(const QString& dialogName)
|
|
{
|
|
QDialog* dialog = findDialog(dialogName);
|
|
if (dialog) {
|
|
return dialog;
|
|
} else {
|
|
DialogDescriber* cont = findDialogContainer(dialogName);
|
|
if (cont) {
|
|
dialog = createDialog(cont);
|
|
if (dialog)
|
|
return dialog;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
QString ScriptEngineContext::getNewDialogName()
|
|
{
|
|
QString result = "Dialog";
|
|
int index = m_dialogs.size() - 1;
|
|
while (containsDialog(result)) {
|
|
index++;
|
|
result = QString("Dialog%1").arg(index);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
#endif
|
|
|
|
void ScriptEngineContext::baseDesignIntfToScript(const QString& pageName, BaseDesignIntf* item)
|
|
{
|
|
if (item) {
|
|
if (item->metaObject()->indexOfSignal("beforeRender()") != -1)
|
|
item->disconnect(SIGNAL(beforeRender()));
|
|
if (item->metaObject()->indexOfSignal("afterData()") != -1)
|
|
item->disconnect(SIGNAL(afterData()));
|
|
if (item->metaObject()->indexOfSignal("afterRender()") != -1)
|
|
item->disconnect(SIGNAL(afterRender()));
|
|
|
|
ScriptEngineType* engine = ScriptEngineManager::instance().scriptEngine();
|
|
|
|
#ifdef USE_QJSENGINE
|
|
ScriptValueType sItem = getJSValue(*engine, item);
|
|
QString on = item->patternName().compare(pageName) == 0
|
|
? pageName
|
|
: pageName + "_" + item->patternName();
|
|
engine->globalObject().setProperty(on, sItem);
|
|
#else
|
|
QString on = item->patternName().compare(pageName) == 0
|
|
? pageName
|
|
: pageName + "_" + item->patternName();
|
|
ScriptValueType sItem = engine->globalObject().property(on);
|
|
if (sItem.isValid()) {
|
|
engine->newQObject(sItem, item);
|
|
} else {
|
|
sItem = engine->newQObject(item);
|
|
engine->globalObject().setProperty(on, sItem);
|
|
}
|
|
#endif
|
|
foreach (BaseDesignIntf* child, item->childBaseItems()) {
|
|
baseDesignIntfToScript(pageName, child);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ScriptEngineContext::qobjectToScript(const QString& name, QObject* item)
|
|
{
|
|
ScriptEngineType* engine = ScriptEngineManager::instance().scriptEngine();
|
|
#ifdef USE_QJSENGINE
|
|
ScriptValueType sItem = getJSValue(*engine, item);
|
|
engine->globalObject().setProperty(name, sItem);
|
|
#else
|
|
ScriptValueType sItem = engine->globalObject().property(name);
|
|
if (sItem.isValid()) {
|
|
engine->newQObject(sItem, item);
|
|
} else {
|
|
sItem = engine->newQObject(item);
|
|
engine->globalObject().setProperty(name, sItem);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#ifdef HAVE_UI_LOADER
|
|
|
|
#ifdef USE_QJSENGINE
|
|
void registerChildObjects(ScriptEngineType* se, ScriptValueType* root, QObject* currObj)
|
|
{
|
|
foreach (QObject* obj, currObj->children()) {
|
|
if (!obj->objectName().isEmpty()) {
|
|
ScriptValueType child = se->newQObject(obj);
|
|
root->setProperty(obj->objectName(), child);
|
|
}
|
|
registerChildObjects(se, root, obj);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void ScriptEngineContext::initDialogs()
|
|
{
|
|
ScriptEngineType* se = ScriptEngineManager::instance().scriptEngine();
|
|
foreach (DialogDescriber::Ptr dialog, dialogDescribers()) {
|
|
ScriptValueType sv = se->newQObject(getDialog(dialog->name()));
|
|
#ifdef USE_QJSENGINE
|
|
registerChildObjects(se, &sv, sv.toQObject());
|
|
#endif
|
|
se->globalObject().setProperty(dialog->name(), sv);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
bool ScriptEngineContext::runInitScript()
|
|
{
|
|
|
|
ScriptEngineType* engine = ScriptEngineManager::instance().scriptEngine();
|
|
ScriptEngineManager::instance().setContext(this);
|
|
m_tableOfContents->clear();
|
|
|
|
ScriptValueType res = engine->evaluate(initScript());
|
|
if (res.isBool())
|
|
return res.toBool();
|
|
#ifdef USE_QJSENGINE
|
|
if (res.isError()) {
|
|
QMessageBox::critical(
|
|
0, tr("Error"),
|
|
QString("Line %1: %2 ").arg(res.property("lineNumber").toString()).arg(res.toString()));
|
|
return false;
|
|
}
|
|
#else
|
|
if (engine->hasUncaughtException()) {
|
|
QMessageBox::critical(0, tr("Error"),
|
|
QString("Line %1: %2 ")
|
|
.arg(engine->uncaughtExceptionLineNumber())
|
|
.arg(engine->uncaughtException().toString()));
|
|
return false;
|
|
}
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
QString ScriptEngineContext::initScript() const { return m_initScript; }
|
|
|
|
void ScriptEngineContext::setInitScript(const QString& initScript)
|
|
{
|
|
if (m_initScript != initScript) {
|
|
m_initScript = initScript;
|
|
m_hasChanges = true;
|
|
}
|
|
}
|
|
|
|
DialogDescriber::Ptr DialogDescriber::create(const QString& name, const QByteArray& desc)
|
|
{
|
|
Ptr res(new DialogDescriber());
|
|
res->setName(name);
|
|
res->setDescription(desc);
|
|
return res;
|
|
}
|
|
|
|
QString JSFunctionDesc::name() const { return m_name; }
|
|
|
|
void JSFunctionDesc::setName(const QString& name) { m_name = name; }
|
|
|
|
QString JSFunctionDesc::category() const { return m_category; }
|
|
|
|
void JSFunctionDesc::setCategory(const QString& category) { m_category = category; }
|
|
|
|
QString JSFunctionDesc::description() const { return m_description; }
|
|
|
|
void JSFunctionDesc::setDescription(const QString& description) { m_description = description; }
|
|
|
|
QString JSFunctionDesc::managerName() const { return m_managerName; }
|
|
|
|
void JSFunctionDesc::setManagerName(const QString& managerName) { m_managerName = managerName; }
|
|
|
|
QObject* JSFunctionDesc::manager() const { return m_manager; }
|
|
|
|
void JSFunctionDesc::setManager(QObject* manager) { m_manager = manager; }
|
|
|
|
QString JSFunctionDesc::scriptWrapper() const { return m_scriptWrapper; }
|
|
|
|
void JSFunctionDesc::setScriptWrapper(const QString& scriptWrapper)
|
|
{
|
|
m_scriptWrapper = scriptWrapper;
|
|
}
|
|
|
|
QVariant ScriptFunctionsManager::calcGroupFunction(const QString& name, const QString& expressionID,
|
|
const QString& bandName, QObject* currentPage)
|
|
{
|
|
if (m_scriptEngineManager->dataManager()) {
|
|
PageItemDesignIntf* pageItem = dynamic_cast<PageItemDesignIntf*>(currentPage);
|
|
QString expression = m_scriptEngineManager->dataManager()->getExpression(expressionID);
|
|
GroupFunction* gf
|
|
= m_scriptEngineManager->dataManager()->groupFunction(name, expression, bandName);
|
|
if (gf) {
|
|
if (gf->isValid()) {
|
|
return gf->calculate(pageItem);
|
|
} else {
|
|
return gf->error();
|
|
}
|
|
} else {
|
|
return QString(QObject::tr("Function %1 not found or have wrong arguments").arg(name));
|
|
}
|
|
} else {
|
|
return QString(QObject::tr("Datasource manager not found"));
|
|
}
|
|
}
|
|
|
|
QVariant ScriptFunctionsManager::calcGroupFunction(const QString& name, const QString& expressionID,
|
|
const QString& bandName)
|
|
{
|
|
return calcGroupFunction(name, expressionID, bandName, 0);
|
|
}
|
|
|
|
QVariant ScriptFunctionsManager::line(const QString& bandName)
|
|
{
|
|
QString varName = QLatin1String("line_") + bandName.toLower();
|
|
QVariant res;
|
|
if (scriptEngineManager()->dataManager()->variable(varName).isValid()) {
|
|
res = scriptEngineManager()->dataManager()->variable(varName);
|
|
} else
|
|
res = QString("Variable line for band %1 not found").arg(bandName);
|
|
return res;
|
|
}
|
|
|
|
QVariant ScriptFunctionsManager::numberFormat(QVariant value, const char& format, int precision,
|
|
const QString& locale)
|
|
{
|
|
return (locale.isEmpty()) ? QString::number(value.toDouble(), format, precision)
|
|
: QLocale(locale).toString(value.toDouble(), format, precision);
|
|
}
|
|
|
|
QVariant ScriptFunctionsManager::dateFormat(QVariant value, const QString& format,
|
|
const QString& locale)
|
|
{
|
|
return (locale.isEmpty()) ? QLocale().toString(value.toDate(), format)
|
|
: QLocale(locale).toString(value.toDate(), format);
|
|
}
|
|
|
|
QVariant ScriptFunctionsManager::timeFormat(QVariant value, const QString& format)
|
|
{
|
|
return QLocale().toString(value.toTime(), format);
|
|
}
|
|
|
|
QVariant ScriptFunctionsManager::dateTimeFormat(QVariant value, const QString& format,
|
|
const QString& locale)
|
|
{
|
|
return (locale.isEmpty()) ? QLocale().toString(value.toDateTime(), format)
|
|
: QLocale(locale).toString(value.toDateTime(), format);
|
|
}
|
|
|
|
QVariant ScriptFunctionsManager::sectotimeFormat(QVariant value, const QString& format)
|
|
{
|
|
int seconds = value.toInt();
|
|
int minutes = seconds / 60;
|
|
int hours = minutes / 60;
|
|
|
|
QString result = format;
|
|
bool hasHour = format.contains("h");
|
|
bool hasMinute = format.contains("m");
|
|
for (int len = 2; len; len--) {
|
|
if (hasHour)
|
|
result.replace(QString('h').repeated(len),
|
|
QString::number(hours).rightJustified(len, '0'));
|
|
if (hasMinute)
|
|
result.replace(
|
|
QString('m').repeated(len),
|
|
QString::number(hasHour ? minutes % 60 : minutes).rightJustified(len, '0'));
|
|
result.replace(
|
|
QString('s').repeated(len),
|
|
QString::number(hasMinute ? seconds % 60 : seconds).rightJustified(len, '0'));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
QVariant ScriptFunctionsManager::date() { return QDate::currentDate(); }
|
|
|
|
QVariant ScriptFunctionsManager::now() { return QDateTime::currentDateTime(); }
|
|
|
|
QVariant ScriptFunctionsManager::currencyFormat(QVariant value, const QString& locale)
|
|
{
|
|
QString l = (!locale.isEmpty()) ? locale : QLocale::system().name();
|
|
return QLocale(l).toCurrencyString(value.toDouble());
|
|
}
|
|
|
|
QVariant ScriptFunctionsManager::currencyUSBasedFormat(QVariant value,
|
|
const QString& currencySymbol)
|
|
{
|
|
QString CurrencySymbol
|
|
= (!currencySymbol.isEmpty()) ? currencySymbol : QLocale::system().currencySymbol();
|
|
// Format it using USA locale
|
|
QString vTempStr
|
|
= QLocale(QLocale::English, QLocale::UnitedStates).toCurrencyString(value.toDouble());
|
|
// Replace currency symbol if necesarry
|
|
if (CurrencySymbol != "")
|
|
vTempStr.replace("$", CurrencySymbol);
|
|
return vTempStr;
|
|
}
|
|
|
|
void ScriptFunctionsManager::setVariable(const QString& name, QVariant value)
|
|
{
|
|
DataSourceManager* dm = scriptEngineManager()->dataManager();
|
|
if (dm->containsVariable(name)) {
|
|
dm->changeVariable(name, value);
|
|
} else {
|
|
dm->addVariable(name, value, VarDesc::User);
|
|
}
|
|
}
|
|
|
|
QVariant ScriptFunctionsManager::getVariable(const QString& name)
|
|
{
|
|
DataSourceManager* dm = scriptEngineManager()->dataManager();
|
|
return dm->variable(name);
|
|
}
|
|
|
|
QVariant ScriptFunctionsManager::getField(const QString& field)
|
|
{
|
|
DataSourceManager* dm = scriptEngineManager()->dataManager();
|
|
return dm->fieldData(field);
|
|
}
|
|
|
|
QVariant ScriptFunctionsManager::getFieldByKeyField(const QString& datasourceName,
|
|
const QString& valueFieldName,
|
|
const QString& keyFieldName, QVariant keyValue)
|
|
{
|
|
DataSourceManager* dm = scriptEngineManager()->dataManager();
|
|
return dm->fieldDataByKey(datasourceName, valueFieldName, keyFieldName, keyValue);
|
|
}
|
|
|
|
QVariant ScriptFunctionsManager::getFieldByRowIndex(const QString& fieldName, int rowIndex)
|
|
{
|
|
DataSourceManager* dm = scriptEngineManager()->dataManager();
|
|
return dm->fieldDataByRowIndex(fieldName, rowIndex);
|
|
}
|
|
|
|
void ScriptFunctionsManager::reopenDatasource(const QString& datasourceName)
|
|
{
|
|
DataSourceManager* dm = scriptEngineManager()->dataManager();
|
|
return dm->reopenDatasource(datasourceName);
|
|
}
|
|
|
|
void ScriptFunctionsManager::addBookmark(const QString& uniqKey, const QString& content)
|
|
{
|
|
scriptEngineManager()->addBookMark(uniqKey, content);
|
|
}
|
|
|
|
int ScriptFunctionsManager::findPageIndexByBookmark(const QString& uniqKey)
|
|
{
|
|
return scriptEngineManager()->findPageIndexByBookmark(uniqKey);
|
|
}
|
|
|
|
int ScriptFunctionsManager::getPageFreeSpace(QObject* page)
|
|
{
|
|
return scriptEngineManager()->getPageFreeSpace(dynamic_cast<PageItemDesignIntf*>(page));
|
|
}
|
|
|
|
void ScriptFunctionsManager::addTableOfContentsItem(const QString& uniqKey, const QString& content,
|
|
int indent)
|
|
{
|
|
scriptEngineManager()->addTableOfContentsItem(uniqKey, content, indent);
|
|
}
|
|
|
|
void ScriptFunctionsManager::clearTableOfContents()
|
|
{
|
|
scriptEngineManager()->clearTableOfContents();
|
|
}
|
|
|
|
QFont ScriptFunctionsManager::font(const QString& family, int pointSize, bool italic, bool bold,
|
|
bool underLine)
|
|
{
|
|
QFont result(family, pointSize);
|
|
result.setBold(bold);
|
|
result.setItalic(italic);
|
|
result.setUnderline(underLine);
|
|
return result;
|
|
}
|
|
|
|
QVariant ScriptFunctionsManager::getFieldByRowIndexEx(const QString& fieldName, int rowIndex,
|
|
const int role)
|
|
{
|
|
DataSourceManager* dm = scriptEngineManager()->dataManager();
|
|
return dm->fieldDataByRowIndex(fieldName, rowIndex, role);
|
|
}
|
|
|
|
QVariant ScriptFunctionsManager::getFieldByRowIndexEx2(const QString& fieldName, int rowIndex,
|
|
const QString& roleName)
|
|
{
|
|
DataSourceManager* dm = scriptEngineManager()->dataManager();
|
|
return dm->fieldDataByRowIndex(fieldName, rowIndex, roleName);
|
|
}
|
|
|
|
QVariant ScriptFunctionsManager::getHeaderData(const QString& fieldName, const QString& roleName)
|
|
{
|
|
DataSourceManager* dm = scriptEngineManager()->dataManager();
|
|
return dm->headerData(fieldName, roleName);
|
|
}
|
|
|
|
QVariant ScriptFunctionsManager::getHeaderColumnNameByIndex(const QString& datasourceName,
|
|
const int columnIndex)
|
|
{
|
|
DataSourceManager* dm = scriptEngineManager()->dataManager();
|
|
return dm->columnName(datasourceName, columnIndex);
|
|
}
|
|
|
|
int ScriptFunctionsManager::getColumnCount(const QString& datasourceName)
|
|
{
|
|
DataSourceManager* dm = scriptEngineManager()->dataManager();
|
|
return dm->columnCount(datasourceName);
|
|
}
|
|
|
|
#ifdef USE_QJSENGINE
|
|
|
|
void ScriptFunctionsManager::addItemsToComboBox(QJSValue object, const QStringList& values)
|
|
{
|
|
QComboBox* comboBox = dynamic_cast<QComboBox*>(object.toQObject());
|
|
if (comboBox) {
|
|
comboBox->addItems(values);
|
|
}
|
|
}
|
|
|
|
void ScriptFunctionsManager::addItemToComboBox(QJSValue object, const QString& value)
|
|
{
|
|
QComboBox* comboBox = dynamic_cast<QComboBox*>(object.toQObject());
|
|
if (comboBox) {
|
|
comboBox->addItem(value);
|
|
}
|
|
}
|
|
|
|
QJSValue ScriptFunctionsManager::createComboBoxWrapper(QJSValue comboBox)
|
|
{
|
|
QComboBox* item = dynamic_cast<QComboBox*>(comboBox.toQObject());
|
|
if (item) {
|
|
ComboBoxWrapper* wrapper = new ComboBoxWrapper(item);
|
|
return m_scriptEngineManager->scriptEngine()->newQObject(wrapper);
|
|
}
|
|
return QJSValue();
|
|
}
|
|
|
|
QJSValue ScriptFunctionsManager::createWrapper(QJSValue item)
|
|
{
|
|
QObject* object = item.toQObject();
|
|
if (object) {
|
|
IWrapperCreator* wrapper = m_wrappersFactory.value(object->metaObject()->className());
|
|
if (wrapper) {
|
|
return m_scriptEngineManager->scriptEngine()->newQObject(
|
|
wrapper->createWrapper(item.toQObject()));
|
|
}
|
|
}
|
|
return QJSValue();
|
|
}
|
|
|
|
#else
|
|
|
|
void ScriptFunctionsManager::addItemsToComboBox(QScriptValue object, const QStringList& values)
|
|
{
|
|
QComboBox* comboBox = dynamic_cast<QComboBox*>(object.toQObject());
|
|
if (comboBox) {
|
|
comboBox->addItems(values);
|
|
}
|
|
}
|
|
|
|
void ScriptFunctionsManager::addItemToComboBox(QScriptValue object, const QString& value)
|
|
{
|
|
QComboBox* comboBox = dynamic_cast<QComboBox*>(object.toQObject());
|
|
if (comboBox) {
|
|
comboBox->addItem(value);
|
|
}
|
|
}
|
|
|
|
QScriptValue ScriptFunctionsManager::createComboBoxWrapper(QScriptValue comboBox)
|
|
{
|
|
QComboBox* item = dynamic_cast<QComboBox*>(comboBox.toQObject());
|
|
if (item) {
|
|
ComboBoxWrapper* wrapper = new ComboBoxWrapper(item);
|
|
return m_scriptEngineManager->scriptEngine()->newQObject(wrapper);
|
|
}
|
|
return QScriptValue();
|
|
}
|
|
|
|
QScriptValue ScriptFunctionsManager::createWrapper(QScriptValue item)
|
|
{
|
|
QObject* object = item.toQObject();
|
|
if (object) {
|
|
IWrapperCreator* wrapper = m_wrappersFactory.value(object->metaObject()->className());
|
|
if (wrapper) {
|
|
return m_scriptEngineManager->scriptEngine()->newQObject(
|
|
wrapper->createWrapper(item.toQObject()));
|
|
}
|
|
}
|
|
return QScriptValue();
|
|
}
|
|
|
|
#endif
|
|
|
|
QFont ScriptFunctionsManager::font(QVariantMap params)
|
|
{
|
|
if (!params.contains("family")) {
|
|
return QFont();
|
|
} else {
|
|
QFont result(params.value("family").toString());
|
|
if (params.contains("pointSize"))
|
|
result.setPointSize(params.value("pointSize").toInt());
|
|
if (params.contains("bold"))
|
|
result.setBold(params.value("bold").toBool());
|
|
if (params.contains("italic"))
|
|
result.setItalic(params.value("italic").toBool());
|
|
if (params.contains("underline"))
|
|
result.setUnderline(params.value("underline").toBool());
|
|
return result;
|
|
}
|
|
}
|
|
|
|
ScriptEngineManager* ScriptFunctionsManager::scriptEngineManager() const
|
|
{
|
|
return m_scriptEngineManager;
|
|
}
|
|
|
|
void ScriptFunctionsManager::setScriptEngineManager(ScriptEngineManager* scriptEngineManager)
|
|
{
|
|
m_scriptEngineManager = scriptEngineManager;
|
|
}
|
|
|
|
TableOfContents::~TableOfContents() { clear(); }
|
|
|
|
void TableOfContents::setItem(const QString& uniqKey, const QString& content, int pageNumber,
|
|
int indent)
|
|
{
|
|
ContentItem* item = 0;
|
|
if (m_hash.contains(uniqKey)) {
|
|
item = m_hash.value(uniqKey);
|
|
item->content = content;
|
|
item->pageNumber = pageNumber;
|
|
if (indent > 0)
|
|
item->indent = indent;
|
|
} else {
|
|
item = new ContentItem;
|
|
item->content = content;
|
|
item->pageNumber = pageNumber;
|
|
item->indent = indent;
|
|
item->uniqKey = uniqKey;
|
|
m_tableOfContents.append(item);
|
|
m_hash.insert(uniqKey, item);
|
|
}
|
|
}
|
|
|
|
void TableOfContents::slotOneSlotDS(CallbackInfo info, QVariant& data)
|
|
{
|
|
QStringList columns;
|
|
columns << "Content"
|
|
<< "Page number"
|
|
<< "Content Key";
|
|
|
|
switch (info.dataType) {
|
|
case LimeReport::CallbackInfo::RowCount:
|
|
data = m_tableOfContents.count();
|
|
break;
|
|
case LimeReport::CallbackInfo::ColumnCount:
|
|
data = columns.size();
|
|
break;
|
|
case LimeReport::CallbackInfo::ColumnHeaderData: {
|
|
data = columns.at(info.index);
|
|
break;
|
|
}
|
|
case LimeReport::CallbackInfo::ColumnData:
|
|
if (info.index < m_tableOfContents.count()) {
|
|
ContentItem* item = m_tableOfContents.at(info.index);
|
|
if (info.columnName.compare("Content", Qt::CaseInsensitive) == 0)
|
|
data = item->content.rightJustified(item->indent + item->content.size());
|
|
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;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void LimeReport::TableOfContents::clear()
|
|
{
|
|
|
|
m_hash.clear();
|
|
foreach (ContentItem* item, m_tableOfContents) {
|
|
delete item;
|
|
}
|
|
m_tableOfContents.clear();
|
|
}
|
|
|
|
QObject* ComboBoxWrapperCreator::createWrapper(QObject* item)
|
|
{
|
|
QComboBox* comboBox = dynamic_cast<QComboBox*>(item);
|
|
if (comboBox) {
|
|
return new ComboBoxWrapper(comboBox);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool DatasourceFunctions::first(const QString& datasourceName)
|
|
{
|
|
if (m_dataManager && m_dataManager->dataSource(datasourceName)) {
|
|
m_dataManager->dataSource(datasourceName)->first();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool DatasourceFunctions::next(const QString& datasourceName)
|
|
{
|
|
if (m_dataManager && m_dataManager->dataSource(datasourceName))
|
|
return m_dataManager->dataSource(datasourceName)->next();
|
|
return false;
|
|
}
|
|
|
|
bool DatasourceFunctions::prior(const QString& datasourceName)
|
|
{
|
|
if (m_dataManager && m_dataManager->dataSource(datasourceName))
|
|
return m_dataManager->dataSource(datasourceName)->prior();
|
|
return false;
|
|
}
|
|
|
|
bool DatasourceFunctions::isEOF(const QString& datasourceName)
|
|
{
|
|
if (m_dataManager && m_dataManager->dataSource(datasourceName))
|
|
return m_dataManager->dataSource(datasourceName)->eof();
|
|
return true;
|
|
}
|
|
|
|
int DatasourceFunctions::rowCount(const QString& datasourceName)
|
|
{
|
|
if (m_dataManager && m_dataManager->dataSource(datasourceName))
|
|
return m_dataManager->dataSource(datasourceName)->model()->rowCount();
|
|
return 0;
|
|
}
|
|
|
|
bool DatasourceFunctions::invalidate(const QString& datasourceName)
|
|
{
|
|
if (m_dataManager && m_dataManager->dataSource(datasourceName)) {
|
|
m_dataManager->dataSourceHolder(datasourceName)->invalidate(IDataSource::RENDER_MODE);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
QObject* DatasourceFunctions::createTableBuilder(QObject* horizontalLayout)
|
|
{
|
|
LimeReport::HorizontalLayout* l = dynamic_cast<LimeReport::HorizontalLayout*>(horizontalLayout);
|
|
if (l)
|
|
return new TableBuilder(l, m_dataManager);
|
|
return 0;
|
|
}
|
|
|
|
TableBuilder::TableBuilder(HorizontalLayout* layout, DataSourceManager* dataManager):
|
|
m_horizontalLayout(layout),
|
|
m_baseLayout(0),
|
|
m_dataManager(dataManager)
|
|
{
|
|
if (m_horizontalLayout)
|
|
m_patternLayout = dynamic_cast<HorizontalLayout*>(
|
|
m_horizontalLayout->cloneItem(m_horizontalLayout->itemMode()));
|
|
}
|
|
|
|
QObject* TableBuilder::addRow()
|
|
{
|
|
checkBaseLayout();
|
|
if (m_baseLayout && m_patternLayout) {
|
|
HorizontalLayout* newRow = new HorizontalLayout(m_baseLayout, m_baseLayout);
|
|
newRow->setLayoutSpacing(m_horizontalLayout->layoutSpacing());
|
|
for (int i = 0; i < m_horizontalLayout->childrenCount(); ++i) {
|
|
BaseDesignIntf* item = dynamic_cast<BaseDesignIntf*>(m_patternLayout->at(i));
|
|
BaseDesignIntf* cloneItem = item->cloneItem(item->itemMode(), newRow, newRow);
|
|
newRow->addChild(cloneItem);
|
|
}
|
|
m_baseLayout->addChild(newRow);
|
|
return newRow;
|
|
} else
|
|
return 0;
|
|
}
|
|
|
|
QObject* TableBuilder::currentRow()
|
|
{
|
|
checkBaseLayout();
|
|
if (m_baseLayout && m_baseLayout->childrenCount() > 0)
|
|
return m_baseLayout->at(m_baseLayout->childrenCount() - 1);
|
|
return 0;
|
|
}
|
|
|
|
void TableBuilder::fillInRowData(QObject* row)
|
|
{
|
|
HorizontalLayout* layout = dynamic_cast<HorizontalLayout*>(row);
|
|
if (layout) {
|
|
for (int i = 0; i < layout->childrenCount(); ++i) {
|
|
BaseDesignIntf* item = dynamic_cast<BaseDesignIntf*>(layout->at(i));
|
|
DataSourceManager* dm = dynamic_cast<DataSourceManager*>(m_dataManager);
|
|
if (item && dm)
|
|
item->updateItemSize(dm);
|
|
}
|
|
}
|
|
}
|
|
|
|
void TableBuilder::buildTable(const QString& datasourceName)
|
|
{
|
|
checkBaseLayout();
|
|
IDataSourceHolder* dh = m_dataManager->dataSourceHolder(datasourceName);
|
|
if (dh) {
|
|
dh->invalidate(IDataSource::RENDER_MODE);
|
|
IDataSource* ds = m_dataManager->dataSource(datasourceName);
|
|
if (ds) {
|
|
bool firstTime = true;
|
|
QObject* row = m_horizontalLayout;
|
|
while (!ds->eof()) {
|
|
if (!firstTime)
|
|
row = addRow();
|
|
else
|
|
firstTime = false;
|
|
fillInRowData(row);
|
|
ds->next();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void TableBuilder::checkBaseLayout()
|
|
{
|
|
if (!m_baseLayout) {
|
|
m_baseLayout = dynamic_cast<VerticalLayout*>(m_horizontalLayout->parentItem());
|
|
if (!m_baseLayout) {
|
|
m_baseLayout = new VerticalLayout(m_horizontalLayout->parent(),
|
|
m_horizontalLayout->parentItem());
|
|
m_baseLayout->setItemLocation(m_horizontalLayout->itemLocation());
|
|
m_baseLayout->setPos(m_horizontalLayout->pos());
|
|
m_baseLayout->setWidth(m_horizontalLayout->width());
|
|
m_baseLayout->setHeight(0);
|
|
m_baseLayout->addChild(m_horizontalLayout);
|
|
m_baseLayout->setObjectName(QUuid::createUuid().toString());
|
|
m_baseLayout->setItemTypeName("VerticalLayout");
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef USE_QTSCRIPTENGINE
|
|
void ComboBoxPrototype::addItem(const QString& text)
|
|
{
|
|
QComboBox* comboBox = qscriptvalue_cast<QComboBox*>(thisObject());
|
|
if (comboBox) {
|
|
comboBox->addItem(text);
|
|
}
|
|
}
|
|
|
|
void ComboBoxPrototype::addItems(const QStringList& texts)
|
|
{
|
|
QComboBox* comboBox = qscriptvalue_cast<QComboBox*>(thisObject());
|
|
if (comboBox) {
|
|
comboBox->addItems(texts);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
} // namespace LimeReport
|