1 /***************************************************************************
2  *   This file is part of the Lime Report project                          *
3  *   Copyright (C) 2015 by Alexander Arin                                  *
4  *   arin_a@bk.ru                                                          *
5  *                                                                         *
6  **                   GNU General Public License Usage                    **
7  *                                                                         *
8  *   This library is free software: you can redistribute it and/or modify  *
9  *   it under the terms of the GNU General Public License as published by  *
10  *   the Free Software Foundation, either version 3 of the License, or     *
11  *   (at your option) any later version.                                   *
12  *   You should have received a copy of the GNU General Public License     *
13  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
14  *                                                                         *
15  **                  GNU Lesser General Public License                    **
16  *                                                                         *
17  *   This library is free software: you can redistribute it and/or modify  *
18  *   it under the terms of the GNU Lesser General Public License as        *
19  *   published by the Free Software Foundation, either version 3 of the    *
20  *   License, or (at your option) any later version.                       *
21  *   You should have received a copy of the GNU Lesser General Public      *
22  *   License along with this library.                                      *
23  *   If not, see <http://www.gnu.org/licenses/>.                           *
24  *                                                                         *
25  *   This library is distributed in the hope that it will be useful,       *
26  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
27  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
28  *   GNU General Public License for more details.                          *
29  ****************************************************************************/
30 #include "lrscriptenginemanager.h"
31 
32 #include <QDate>
33 #include <QStringList>
34 #include <QUuid>
35 #ifdef USE_QTSCRIPTENGINE
36 #include <QScriptValueIterator>
37 #endif
38 #include <QMessageBox>
39 #ifdef HAVE_UI_LOADER
40 #include <QUiLoader>
41 #include <QBuffer>
42 #include <QWidget>
43 #endif
44 #include "lrdatasourcemanager.h"
45 #include "lrbasedesignintf.h"
46 #include "lrbanddesignintf.h"
47 #include "lrpageitemdesignintf.h"
48 
49 Q_DECLARE_METATYPE(QColor)
Q_DECLARE_METATYPE(QFont)50 Q_DECLARE_METATYPE(QFont)
51 Q_DECLARE_METATYPE(LimeReport::ScriptEngineManager *)
52 
53 #ifdef USE_QTSCRIPTENGINE
54 QScriptValue constructColor(QScriptContext *context, QScriptEngine *engine)
55 {
56      QColor color(context->argument(0).toString());
57      return engine->toScriptValue(color);
58 }
59 #endif
60 
61 namespace LimeReport{
62 
ScriptEngineNode(const QString & name,const QString & description,ScriptEngineNode::NodeType type,ScriptEngineNode * parent,const QIcon & icon)63 ScriptEngineNode::ScriptEngineNode(const QString &name, const QString &description,
64                                    ScriptEngineNode::NodeType type, ScriptEngineNode *parent, const QIcon &icon)
65     :m_name(name), m_description(description), m_icon(icon), m_type(type), m_parent(parent)
66 {}
67 
~ScriptEngineNode()68 ScriptEngineNode::~ScriptEngineNode()
69 {
70     qDeleteAll(m_childs.begin(), m_childs.end());
71 }
72 
addChild(const QString & name,const QString & description,ScriptEngineNode::NodeType type,const QIcon & icon)73 ScriptEngineNode*ScriptEngineNode::addChild(const QString& name, const QString& description,
74                                              ScriptEngineNode::NodeType type, const QIcon& icon)
75 {
76     ScriptEngineNode* res = new ScriptEngineNode(name, description, type,this,icon);
77     m_childs.push_back(res);
78     return res;
79 }
80 
row()81 int ScriptEngineNode::row()
82 {
83     if (m_parent){
84         return m_parent->m_childs.indexOf(const_cast<ScriptEngineNode*>(this));
85     }
86     return 0;
87 }
88 
clear()89 void ScriptEngineNode::clear()
90 {
91     for (int i=0; i<m_childs.count(); ++i){
92         delete m_childs[i];
93     }
94     m_childs.clear();
95 }
96 
ScriptEngineModel(ScriptEngineManager * scriptManager)97 ScriptEngineModel::ScriptEngineModel(ScriptEngineManager* scriptManager)
98     :m_rootNode(new ScriptEngineNode())
99 {
100     setScriptEngineManager(scriptManager);
101 }
102 
~ScriptEngineModel()103 ScriptEngineModel::~ScriptEngineModel() {
104     delete m_rootNode;
105 }
106 
parent(const QModelIndex & child) const107 QModelIndex ScriptEngineModel::parent(const QModelIndex& child) const
108 {
109     if (!child.isValid()) return QModelIndex();
110 
111     ScriptEngineNode* childNode = nodeFromIndex(child);
112     if (!childNode) return QModelIndex();
113 
114     ScriptEngineNode* parentNode = childNode->parent();
115     if ((parentNode == m_rootNode) || (!parentNode)) return QModelIndex();
116     return createIndex(parentNode->row(),0,parentNode);
117 }
118 
index(int row,int column,const QModelIndex & parent) const119 QModelIndex ScriptEngineModel::index(int row, int column, const QModelIndex& parent) const
120 {
121     if (!m_rootNode)
122         return QModelIndex();
123 
124     if (!hasIndex(row,column,parent))
125         return QModelIndex();
126 
127     ScriptEngineNode* parentNode;
128     if (parent.isValid()){
129         parentNode = nodeFromIndex(parent);
130     } else {
131         parentNode = m_rootNode;
132     }
133 
134     ScriptEngineNode* childNode = parentNode->child(row);
135     if (childNode){
136         return createIndex(row,column,childNode);
137     } else return QModelIndex();
138 }
139 
rowCount(const QModelIndex & parent) const140 int ScriptEngineModel::rowCount(const QModelIndex& parent) const
141 {
142     if (!m_rootNode) return 0;
143     ScriptEngineNode* parentNode;
144     if (parent.isValid())
145         parentNode = nodeFromIndex(parent);
146     else
147         parentNode = m_rootNode;
148     return parentNode->childCount();
149 }
150 
columnCount(const QModelIndex & parent) const151 int ScriptEngineModel::columnCount(const QModelIndex& parent) const
152 {
153     Q_UNUSED(parent)
154     return 1;
155 }
156 
data(const QModelIndex & index,int role) const157 QVariant ScriptEngineModel::data(const QModelIndex& index, int role) const
158 {
159     ScriptEngineNode *node = nodeFromIndex(index);
160     switch (role) {
161     case Qt::DisplayRole:
162         if (!node) return QVariant();
163         return node->name();
164         break;
165     case Qt::DecorationRole :
166         if (!node) return QIcon();
167         return node->icon();
168         break;
169     default:
170         return QVariant();
171     }
172 }
173 
setScriptEngineManager(ScriptEngineManager * scriptManager)174 void ScriptEngineModel::setScriptEngineManager(ScriptEngineManager* scriptManager)
175 {
176     m_scriptManager = scriptManager;
177     updateModel();
178 }
179 
slotScriptEngineChanged()180 void ScriptEngineModel::slotScriptEngineChanged()
181 {
182     updateModel();
183 }
184 
nodeFromIndex(const QModelIndex & index) const185 ScriptEngineNode*ScriptEngineModel::nodeFromIndex(const QModelIndex& index) const
186 {
187     if (index.isValid()){
188         return static_cast<ScriptEngineNode*>(index.internalPointer());
189     } else return m_rootNode;
190 }
191 
updateModel()192 void ScriptEngineModel::updateModel()
193 {
194     beginResetModel();
195     m_rootNode->clear();
196     QMap<QString,ScriptEngineNode*> categories;
197     foreach(ScriptFunctionDesc funcDesc, m_scriptManager->functionsDescribers()){
198         ScriptEngineNode* categ;
199         QString categoryName = (!funcDesc.category.isEmpty())?funcDesc.category:"NO CATEGORY";
200         if (categories.contains(categoryName)){
201             categ = categories.value(categoryName);
202         } else {
203             categ = m_rootNode->addChild(categoryName,"",ScriptEngineNode::Category,QIcon(":/report/images/folder"));
204             categories.insert(categoryName,categ);
205         }
206         categ->addChild(funcDesc.name,funcDesc.description,ScriptEngineNode::Function,QIcon(":/report/images/function"));
207     }
208     endResetModel();
209 }
210 
~ScriptEngineManager()211 ScriptEngineManager::~ScriptEngineManager()
212 {
213     delete m_model;
214     m_model = 0;
215     delete m_scriptEngine;
216 }
217 
isFunctionExists(const QString & functionName) const218 bool ScriptEngineManager::isFunctionExists(const QString &functionName) const
219 {
220     return m_functions.contains(functionName);
221 //    foreach (ScriptFunctionDesc desc, m_functions.values()) {
222 //        if (desc.name.compare(functionName,Qt::CaseInsensitive)==0){
223 //            return true;
224 //        }
225 //    }
226 //    return false;
227 }
228 
deleteFunction(const QString & functionsName)229 void ScriptEngineManager::deleteFunction(const QString &functionsName)
230 {
231     m_functions.remove(functionsName);
232 }
233 
addFunction(const JSFunctionDesc & functionDescriber)234 bool ScriptEngineManager::addFunction(const JSFunctionDesc &functionDescriber)
235 {
236     if (m_functions.contains(functionDescriber.name())) return false;
237     ScriptValueType functionManager = scriptEngine()->globalObject().property(functionDescriber.managerName());
238 #ifdef USE_QJSENGINE
239     if (functionManager.isUndefined()){
240 #else
241     if (!functionManager.isValid()){
242 #endif
243         functionManager = scriptEngine()->newQObject(functionDescriber.manager());
244         scriptEngine()->globalObject().setProperty(
245                     functionDescriber.managerName(),
246                     functionManager
247         );
248     }
249 
250     if (functionManager.toQObject() == functionDescriber.manager()){
251         ScriptValueType checkWrapper = scriptEngine()->evaluate(functionDescriber.scriptWrapper());
252         if (!checkWrapper.isError()){
253             ScriptFunctionDesc funct;
254             funct.name = functionDescriber.name();
255             funct.description = functionDescriber.description();
256             funct.category = functionDescriber.category();
257             funct.type = ScriptFunctionDesc::Native;
258             m_functions.insert(funct.name, funct);
259             if (m_model)
260                 m_model->updateModel();
261             return true;
262         } else {
263             m_lastError = checkWrapper.toString();
264             return false;
265         }
266     } else {
267         m_lastError = tr("Function manager with name \"%1\" already exists!");
268         return false;
269     }
270 
271 }
272 
273 #ifdef USE_QTSCRIPTENGINE
274 #if QT_VERSION > 0x050600
275 Q_DECL_DEPRECATED
276 #endif
277 bool ScriptEngineManager::addFunction(const QString& name,
278                                               QScriptEngine::FunctionSignature function,
279                                               const QString& category,
280                                               const QString& description)
281 {
282     if (!isFunctionExists(name)){
283         ScriptFunctionDesc funct;
284         funct.name = name;
285         funct.description = description;
286         funct.category = category;
287         funct.scriptValue = scriptEngine()->newFunction(function);
288         funct.scriptValue.setProperty("functionName", name);
289         funct.scriptValue.setData(m_scriptEngine->toScriptValue(this));
290         funct.type = ScriptFunctionDesc::Native;
291         m_functions.insert(name, funct);
292         if (m_model)
293             m_model->updateModel();
294         m_scriptEngine->globalObject().setProperty(funct.name, funct.scriptValue);
295         return true;
296     } else {
297         return false;
298     }
299 }
300 #endif
301 
302 bool ScriptEngineManager::addFunction(const QString& name, const QString& script, const QString& category, const QString& description)
303 {
304     ScriptValueType functionValue = m_scriptEngine->evaluate(script);
305     if (!functionValue.isError()){
306         ScriptFunctionDesc funct;
307         funct.scriptValue = functionValue;
308         funct.name =  name;
309         funct.category = category;
310         funct.description = description;
311         funct.type = ScriptFunctionDesc::Script;
312         m_functions.insert(name, funct);
313         m_model->updateModel();
314         return true;
315     } else {
316         m_lastError = functionValue.toString();
317         return false;
318     }
319 }
320 
321 QStringList ScriptEngineManager::functionsNames()
322 {
323     return m_functions.keys();
324 //    QStringList res;
325 //    foreach(ScriptFunctionDesc func, m_functions){
326 //        res<<func.name;
327 //    }
328 //    return res;
329 }
330 
331 void ScriptEngineManager::setDataManager(DataSourceManager *dataManager){
332     if (dataManager && m_dataManager != dataManager){
333         m_dataManager = dataManager;
334         if (m_dataManager){
335             foreach(QString func, m_dataManager->groupFunctionNames()){
336                 JSFunctionDesc describer(
337                     func,
338                     tr("GROUP FUNCTIONS"),
339                     func+"(\""+tr("FieldName")+"\",\""+tr("BandName")+"\")",
340                     LimeReport::Const::FUNCTION_MANAGER_NAME,
341                     m_functionManager,
342                     QString("function %1(fieldName, bandName, pageitem){\
343                             if (typeof pageitem == 'undefined') return %2.calcGroupFunction(\"%1\", fieldName, bandName); \
344                             else return %2.calcGroupFunction(\"%1\", fieldName, bandName, pageitem);}"
345                     ).arg(func)
346                      .arg(LimeReport::Const::FUNCTION_MANAGER_NAME)
347                 );
348                 addFunction(describer);
349             }
350             moveQObjectToScript(new DatasourceFunctions(dataManager), LimeReport::Const::DATAFUNCTIONS_MANAGER_NAME);
351         }
352     }
353 }
354 
355 QString ScriptEngineManager::expandUserVariables(QString context, RenderPass /* pass */, ExpandType expandType, QVariant &varValue)
356 {
357     QRegExp rx(Const::VARIABLE_RX);
358     if (context.contains(rx)){
359         int pos = 0;
360         while ((pos = rx.indexIn(context,pos))!=-1){
361             QString variable=rx.cap(1);
362             pos += rx.matchedLength();
363             if (dataManager()->containsVariable(variable) ){
364                 try {
365 
366                     varValue = dataManager()->variable(variable);
367                     switch (expandType){
368                     case EscapeSymbols:
369                         context.replace(rx.cap(0),escapeSimbols(varValue.toString()));
370                     break;
371                     case NoEscapeSymbols:
372                         context.replace(rx.cap(0),varValue.toString());
373                     break;
374                     case ReplaceHTMLSymbols:
375                         context.replace(rx.cap(0),replaceHTMLSymbols(varValue.toString()));
376                     break;
377                     }
378                     pos=0;
379 
380                 } catch (ReportError &e){
381                     dataManager()->putError(e.what());
382                     if (!dataManager()->reportSettings() || dataManager()->reportSettings()->suppressAbsentFieldsAndVarsWarnings())
383                         context.replace(rx.cap(0),e.what());
384                     else
385                         context.replace(rx.cap(0),"");
386                 }
387             } else {
388                 QString error;
389                 error = tr("Variable %1 not found").arg(variable);
390                 dataManager()->putError(error);
391                 if (!dataManager()->reportSettings() || dataManager()->reportSettings()->suppressAbsentFieldsAndVarsWarnings())
392                     context.replace(rx.cap(0),error);
393                 else
394                     context.replace(rx.cap(0),"");
395             }
396         }
397     }
398     return context;
399 }
400 
401 QString ScriptEngineManager::expandDataFields(QString context, ExpandType expandType, QVariant &varValue, QObject *reportItem)
402 {
403     QRegExp rx(Const::FIELD_RX);
404 
405     if (context.contains(rx)){
406         while ((rx.indexIn(context))!=-1){
407             QString field=rx.cap(1);
408 
409             if (dataManager()->containsField(field)) {
410                 QString fieldValue;
411                 varValue = dataManager()->fieldData(field);
412                 if (expandType == EscapeSymbols) {
413                     if (varValue.isNull()) {
414                         fieldValue="\"\"";
415                     } else {
416                         fieldValue = escapeSimbols(varValue.toString());
417                         switch (dataManager()->fieldData(field).type()) {
418                         case QVariant::Char:
419                         case QVariant::String:
420                         case QVariant::StringList:
421                         case QVariant::Date:
422                         case QVariant::DateTime:
423                             fieldValue = "\""+fieldValue+"\"";
424                             break;
425                         default:
426                             break;
427                         }
428                     }
429                 } else {
430                     if (expandType == ReplaceHTMLSymbols)
431                         fieldValue = replaceHTMLSymbols(varValue.toString());
432                     else fieldValue = varValue.toString();
433                 }
434 
435                 context.replace(rx.cap(0),fieldValue);
436 
437             } else {
438                 QString error;
439                 if (reportItem){
440                     error = tr("Field %1 not found in %2!").arg(field).arg(reportItem->objectName());
441                     dataManager()->putError(error);
442                 }
443                 varValue = QVariant();
444                 if (!dataManager()->reportSettings() || !dataManager()->reportSettings()->suppressAbsentFieldsAndVarsWarnings())
445                     context.replace(rx.cap(0),error);
446                 else
447                     context.replace(rx.cap(0),"");
448             }
449         }
450     }
451 
452     return context;
453 }
454 
455 QString ScriptEngineManager::expandScripts(QString context, QVariant& varValue, QObject *reportItem)
456 {
457     QRegExp rx(Const::SCRIPT_RX);
458 
459     if (context.contains(rx)){
460 
461         if (ScriptEngineManager::instance().dataManager() != dataManager())
462             ScriptEngineManager::instance().setDataManager(dataManager());
463 
464         ScriptEngineType* se = ScriptEngineManager::instance().scriptEngine();
465 
466         if (reportItem){
467             ScriptValueType svThis;
468 #ifdef USE_QJSENGINE
469             svThis = getJSValue(*se, reportItem);
470             se->globalObject().setProperty("THIS",svThis);
471 #else
472             svThis = se->globalObject().property("THIS");
473             if (svThis.isValid()){
474                 se->newQObject(svThis, reportItem);
475             } else {
476                 svThis = se->newQObject(reportItem);
477                 se->globalObject().setProperty("THIS",svThis);
478             }
479 #endif
480         }
481 
482         ScriptExtractor scriptExtractor(context);
483         if (scriptExtractor.parse()){
484             context = replaceScripts(context, varValue, reportItem, se, scriptExtractor.scriptTree());
485         }
486 
487     }
488     return context;
489 }
490 
491 QString ScriptEngineManager::replaceScripts(QString context, QVariant &varValue, QObject *reportItem, ScriptEngineType* se, ScriptNode *scriptTree)
492 {
493     foreach(ScriptNode* item, scriptTree->children()){
494         QString scriptBody = expandDataFields(item->body(), EscapeSymbols, varValue, reportItem);
495         if (item->children().size() > 0)
496             scriptBody = replaceScripts(scriptBody, varValue, reportItem, se, item);
497         scriptBody = expandUserVariables(scriptBody, FirstPass, EscapeSymbols, varValue);
498         ScriptValueType value = se->evaluate(scriptBody);
499 #ifdef USE_QJSENGINE
500         if (!value.isError()){
501             varValue = value.toVariant();
502             context.replace(item->script(), value.toString());
503         } else {
504             context.replace(item->script(), value.toString());
505         }
506 #else
507         if (!se->hasUncaughtException()) {
508             varValue = value.toVariant();
509             context.replace(item->script(), value.toString());
510         } else {
511             context.replace(item->script(), se->uncaughtException().toString());
512         }
513 #endif
514     }
515     return context;
516 }
517 
518 QVariant ScriptEngineManager::evaluateScript(const QString& script){
519 
520     QRegExp rx(Const::SCRIPT_RX);
521     QVariant varValue;
522 
523     if (script.contains(rx)){
524 
525         if (ScriptEngineManager::instance().dataManager()!=dataManager())
526             ScriptEngineManager::instance().setDataManager(dataManager());
527 
528         ScriptEngineType* se = ScriptEngineManager::instance().scriptEngine();
529 
530         ScriptExtractor scriptExtractor(script);
531         if (scriptExtractor.parse()){
532             QString scriptBody = expandDataFields(scriptExtractor.scriptTree()[0].body(), EscapeSymbols, varValue, 0);
533             scriptBody = expandUserVariables(scriptBody, FirstPass, EscapeSymbols, varValue);
534             ScriptValueType value = se->evaluate(scriptBody);
535 #ifdef USE_QJSENGINE
536             if (!value.isError()){
537 #else
538             if (!se->hasUncaughtException()) {
539 #endif
540                 return value.toVariant();
541             }
542         }
543     }
544     return QVariant();
545 }
546 
547 void ScriptEngineManager::addBookMark(const QString& uniqKey, const QString& content){
548     Q_ASSERT(m_context != 0);
549     if (m_context){
550         BandDesignIntf* currentBand = m_context->getCurrentBand();
551         if (currentBand)
552             currentBand->addBookmark(uniqKey, content);
553         else if (m_context->getCurrentPage()) {
554             m_context->getCurrentPage()->addBookmark(uniqKey, content);
555         }
556     }
557 
558 }
559 
560 int ScriptEngineManager::findPageIndexByBookmark(const QString &uniqKey)
561 {
562     for (int i=0; i < m_context->reportPages()->size(); ++i){
563         if (m_context->reportPages()->at(i)->bookmarks().contains(uniqKey))
564             return i+1;
565         foreach(BandDesignIntf* band, m_context->reportPages()->at(i)->bands()){
566             if (band->bookmarks().contains(uniqKey))
567                 return i+1;
568         }
569     }
570     return -1;
571 }
572 
573 void ScriptEngineManager::addTableOfContentsItem(const QString& uniqKey, const QString& content, int indent)
574 {
575     Q_ASSERT(m_context != 0);
576     if (m_context){
577         m_context->tableOfContents()->setItem(uniqKey, content, 0, indent);
578         addBookMark(uniqKey, content);
579     }
580 }
581 
582 void ScriptEngineManager::clearTableOfContents(){
583     if (m_context) {
584         if (m_context->tableOfContents())
585             m_context->tableOfContents()->clear();
586     }
587 }
588 
589 ScriptValueType ScriptEngineManager::moveQObjectToScript(QObject* object, const QString objectName)
590 {
591 
592     ScriptValueType obj = scriptEngine()->globalObject().property(objectName);
593     if (!obj.isNull()) delete obj.toQObject();
594     ScriptValueType result = scriptEngine()->newQObject(object);
595     scriptEngine()->globalObject().setProperty(objectName, result);
596     return result;
597 }
598 
599 void ScriptEngineManager::updateModel()
600 {
601 
602 }
603 
604 bool ScriptEngineManager::createLineFunction()
605 {
606     JSFunctionDesc fd;
607 
608     fd.setManager(m_functionManager);
609     fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
610     fd.setCategory(tr("SYSTEM"));
611     fd.setName("line");
612     fd.setDescription("line(\""+tr("BandName")+"\")");
613     fd.setScriptWrapper(QString("function line(bandName){ return %1.line(bandName);}").arg(LimeReport::Const::FUNCTION_MANAGER_NAME));
614 
615     return addFunction(fd);
616 
617 }
618 
619 bool ScriptEngineManager::createNumberFomatFunction()
620 {
621     JSFunctionDesc fd;
622 
623     fd.setManager(m_functionManager);
624     fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
625     fd.setCategory(tr("NUMBER"));
626     fd.setName("numberFormat");
627     fd.setDescription("numberFormat(\""+tr("Value")+"\",\""+tr("Format")+"\",\""+
628                       tr("Precision")+"\",\""+
629                       tr("Locale")+"\")"
630                       );
631     fd.setScriptWrapper(QString("function numberFormat(value, format, precision, locale){"
632                                 " if(typeof(format)==='undefined') format = \"f\"; "
633                                 " if(typeof(precision)==='undefined') precision=2; "
634                                 " if(typeof(locale)==='undefined') locale=\"\"; "
635                                 "return %1.numberFormat(value,format,precision,locale);}"
636                                ).arg(LimeReport::Const::FUNCTION_MANAGER_NAME)
637                         );
638     return addFunction(fd);
639 }
640 
641 bool ScriptEngineManager::createDateFormatFunction(){
642     JSFunctionDesc fd;
643 
644     fd.setManager(m_functionManager);
645     fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
646     fd.setCategory(tr("DATE&TIME"));
647     fd.setName("dateFormat");
648     fd.setDescription("dateFormat(\""+tr("Value")+"\",\""+tr("Format")+"\", \""+tr("Locale")+"\")");
649     fd.setScriptWrapper(QString("function dateFormat(value, format, locale){"
650                                 " if(typeof(format)==='undefined') format = \"dd.MM.yyyy\"; "
651                                 "return %1.dateFormat(value,format, locale);}"
652                                ).arg(LimeReport::Const::FUNCTION_MANAGER_NAME)
653                         );
654     return addFunction(fd);
655 }
656 
657 bool ScriptEngineManager::createTimeFormatFunction(){
658     JSFunctionDesc fd;
659 
660     fd.setManager(m_functionManager);
661     fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
662     fd.setCategory(tr("DATE&TIME"));
663     fd.setName("timeFormat");
664     fd.setDescription("timeFormat(\""+tr("Value")+"\",\""+tr("Format")+"\")");
665     fd.setScriptWrapper(QString("function timeFormat(value, format){"
666                                 " if(typeof(format)==='undefined') format = \"hh:mm\"; "
667                                 "return %1.timeFormat(value,format);}"
668                                ).arg(LimeReport::Const::FUNCTION_MANAGER_NAME)
669                         );
670     return addFunction(fd);
671 }
672 
673 bool ScriptEngineManager::createDateTimeFormatFunction(){
674     JSFunctionDesc fd;
675 
676     fd.setManager(m_functionManager);
677     fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
678     fd.setCategory(tr("DATE&TIME"));
679     fd.setName("dateTimeFormat");
680     fd.setDescription("dateTimeFormat(\""+tr("Value")+"\",\""+tr("Format")+"\", \""+tr("Locale")+"\")");
681     fd.setScriptWrapper(QString("function dateTimeFormat(value, format, locale){"
682                                 " if(typeof(format)==='undefined') format = \"dd.MM.yyyy hh:mm\"; "
683                                 "return %1.dateTimeFormat(value, format, locale);}"
684                                ).arg(LimeReport::Const::FUNCTION_MANAGER_NAME)
685                         );
686     return addFunction(fd);
687 }
688 
689 bool ScriptEngineManager::createSectotimeFormatFunction()
690 {
691     JSFunctionDesc fd;
692 
693     fd.setManager(m_functionManager);
694     fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
695     fd.setCategory(tr("DATE&TIME"));
696     fd.setName("sectotimeFormat");
697     fd.setDescription("sectotimeFormat(\""+tr("Value")+"\",\""+tr("Format")+"\")");
698     fd.setScriptWrapper(QString("function sectotimeFormat(value, format){"
699                                 " if(typeof(format)==='undefined') format = \"hh:mm:ss\"; "
700                                 "return %1.sectotimeFormat(value,format);}"
701                                ).arg(LimeReport::Const::FUNCTION_MANAGER_NAME)
702                         );
703     return addFunction(fd);
704 }
705 
706 bool ScriptEngineManager::createDateFunction(){
707 //    addFunction("date",date,"DATE&TIME","date()");
708     JSFunctionDesc fd;
709 
710     fd.setManager(m_functionManager);
711     fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
712     fd.setCategory(tr("DATE&TIME"));
713     fd.setName("date");
714     fd.setDescription("date()");
715     fd.setScriptWrapper(QString("function date(){"
716                                 "return %1.date();}"
717                                ).arg(LimeReport::Const::FUNCTION_MANAGER_NAME)
718                         );
719     return addFunction(fd);
720 }
721 
722 
723 bool ScriptEngineManager::createNowFunction(){
724 //    addFunction("now",now,"DATE&TIME","now()");
725     JSFunctionDesc fd;
726 
727     fd.setManager(m_functionManager);
728     fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
729     fd.setCategory(tr("DATE&TIME"));
730     fd.setName("now");
731     fd.setDescription("now()");
732     fd.setScriptWrapper(QString("function now(){"
733                                 "return %1.now();}"
734                                ).arg(LimeReport::Const::FUNCTION_MANAGER_NAME)
735                         );
736     return addFunction(fd);
737 }
738 
739 bool ScriptEngineManager::createCurrencyFormatFunction(){
740 //    addFunction("currencyFormat",currencyFormat,"NUMBER","currencyFormat(\""+tr("Value")+"\",\""+tr("Locale")+"\")");
741     JSFunctionDesc fd;
742 
743     fd.setManager(m_functionManager);
744     fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
745     fd.setCategory(tr("NUMBER"));
746     fd.setName("currencyFormat");
747     fd.setDescription("currencyFormat(\""+tr("Value")+"\",\""+tr("Locale")+"\")");
748     fd.setScriptWrapper(QString("function currencyFormat(value, locale){"
749                                 " if(typeof(locale)==='undefined') locale = \"\"; "
750                                 "return %1.currencyFormat(value,locale);}"
751                                ).arg(LimeReport::Const::FUNCTION_MANAGER_NAME)
752                         );
753     return addFunction(fd);
754 }
755 
756 bool ScriptEngineManager::createCurrencyUSBasedFormatFunction(){
757 //    addFunction("currencyUSBasedFormat",currencyUSBasedFormat,"NUMBER","currencyUSBasedFormat(\""+tr("Value")+",\""+tr("CurrencySymbol")+"\")");
758     JSFunctionDesc fd;
759 
760     fd.setManager(m_functionManager);
761     fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
762     fd.setCategory(tr("NUMBER"));
763     fd.setName("currencyUSBasedFormat");
764     fd.setDescription("currencyUSBasedFormat(\""+tr("Value")+",\""+tr("CurrencySymbol")+"\")");
765     fd.setScriptWrapper(QString("function currencyUSBasedFormat(value, currencySymbol){"
766                                 " if(typeof(currencySymbol)==='undefined') currencySymbol = \"\"; "
767                                 "return %1.currencyUSBasedFormat(value,currencySymbol);}"
768                                ).arg(LimeReport::Const::FUNCTION_MANAGER_NAME)
769                         );
770     return addFunction(fd);
771 }
772 
773 bool ScriptEngineManager::createSetVariableFunction(){
774 //    addFunction("setVariable", setVariable, "GENERAL", "setVariable(\""+tr("Name")+"\",\""+tr("Value")+"\")");
775     JSFunctionDesc fd;
776 
777     fd.setManager(m_functionManager);
778     fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
779     fd.setCategory(tr("GENERAL"));
780     fd.setName("setVariable");
781     fd.setDescription("setVariable(\""+tr("Name")+"\",\""+tr("Value")+"\")");
782     fd.setScriptWrapper(QString("function setVariable(name, value){"
783                                 "return %1.setVariable(name,value);}"
784                                ).arg(LimeReport::Const::FUNCTION_MANAGER_NAME)
785                         );
786     return addFunction(fd);
787 }
788 
789 bool ScriptEngineManager::createGetVariableFunction()
790 {
791     JSFunctionDesc fd;
792     fd.setManager(m_functionManager);
793     fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
794     fd.setCategory(tr("GENERAL"));
795     fd.setName("getVariable");
796     fd.setDescription("getVariable(\""+tr("Name")+"\")");
797     fd.setScriptWrapper(QString("function getVariable(name){"
798                                 "return %1.getVariable(name);}"
799                                ).arg(LimeReport::Const::FUNCTION_MANAGER_NAME)
800                         );
801     return addFunction(fd);
802 }
803 
804 bool ScriptEngineManager::createGetFieldFunction()
805 {
806     JSFunctionDesc fd;
807     fd.setManager(m_functionManager);
808     fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
809     fd.setCategory(tr("GENERAL"));
810     fd.setName("getField");
811     fd.setDescription("getField(\""+tr("Name")+"\")");
812     fd.setScriptWrapper(QString("function getField(name){"
813                                 "return %1.getField(name);}"
814                                ).arg(LimeReport::Const::FUNCTION_MANAGER_NAME)
815                         );
816     return addFunction(fd);
817 }
818 
819 bool ScriptEngineManager::createGetFieldByKeyFunction()
820 {
821     JSFunctionDesc fd;
822     fd.setManager(m_functionManager);
823     fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
824     fd.setCategory(tr("GENERAL"));
825     fd.setName("getFieldByKeyField");
826     fd.setDescription("getFieldByKeyField(\""+tr("Datasource")+"\", \""+
827                       tr("ValueField")+"\",\""+
828                       tr("KeyField")+"\", \""+
829                       tr("KeyFieldValue")+"\")"
830     );
831     fd.setScriptWrapper(QString("function getFieldByKeyField(datasource, valueFieldName, keyFieldName, keyValue){"
832                                 "return %1.getFieldByKeyField(datasource, valueFieldName, keyFieldName, keyValue);}"
833                                ).arg(LimeReport::Const::FUNCTION_MANAGER_NAME)
834                         );
835     return addFunction(fd);
836 }
837 
838 bool ScriptEngineManager::createGetFieldByRowIndex()
839 {
840     JSFunctionDesc fd;
841     fd.setManager(m_functionManager);
842     fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
843     fd.setCategory(tr("GENERAL"));
844     fd.setName("getFieldByRowIndex");
845     fd.setDescription("getFieldByRowIndex(\""+tr("FieldName")+"\", \""+
846                       tr("RowIndex")+"\")"
847     );
848     fd.setScriptWrapper(QString("function getFieldByRowIndex(fieldName, rowIndex){"
849                                 "return %1.getFieldByRowIndex(fieldName, rowIndex);}"
850                                ).arg(LimeReport::Const::FUNCTION_MANAGER_NAME)
851                         );
852     return addFunction(fd);
853 }
854 
855 bool ScriptEngineManager::createAddBookmarkFunction()
856 {
857     JSFunctionDesc fd;
858     fd.setManager(m_functionManager);
859     fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
860     fd.setCategory(tr("GENERAL"));
861     fd.setName("addBookmark");
862     fd.setDescription("addBookmark(\""+tr("Unique identifier")+" \""+tr("Content")+"\")");
863     fd.setScriptWrapper(QString("function addBookmark(uniqKey, content){"
864                                 "return %1.addBookmark(uniqKey, content);}"
865                                ).arg(LimeReport::Const::FUNCTION_MANAGER_NAME)
866                         );
867     return addFunction(fd);
868 }
869 
870 bool ScriptEngineManager::createFindPageIndexByBookmark()
871 {
872     JSFunctionDesc fd;
873     fd.setManager(m_functionManager);
874     fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
875     fd.setCategory(tr("GENERAL"));
876     fd.setName("findPageIndexByBookmark");
877     fd.setDescription("findPageIndexByBookmark(\""+tr("Unique identifier")+"\")");
878     fd.setScriptWrapper(QString("function findPageIndexByBookmark(uniqKey){"
879                                 "return %1.findPageIndexByBookmark(uniqKey);}"
880                                ).arg(LimeReport::Const::FUNCTION_MANAGER_NAME)
881                         );
882     return addFunction(fd);
883 }
884 
885 bool ScriptEngineManager::createAddTableOfContentsItemFunction()
886 {
887     JSFunctionDesc fd;
888     fd.setManager(m_functionManager);
889     fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
890     fd.setCategory(tr("GENERAL"));
891     fd.setName("addTableOfContentsItem");
892     fd.setDescription("addTableOfContentsItem(\""+tr("Unique identifier")+" \""+tr("Content")+"\", \""+tr("Indent")+"\")");
893     fd.setScriptWrapper(QString("function addTableOfContentsItem(uniqKey, content, indent){"
894                                 "return %1.addTableOfContentsItem(uniqKey, content, indent);}"
895                                ).arg(LimeReport::Const::FUNCTION_MANAGER_NAME)
896                         );
897     return addFunction(fd);
898 }
899 
900 bool ScriptEngineManager::createClearTableOfContentsFunction()
901 {
902     JSFunctionDesc fd;
903     fd.setManager(m_functionManager);
904     fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
905     fd.setCategory(tr("GENERAL"));
906     fd.setName("clearTableOfContents");
907     fd.setDescription("clearTableOfContents()");
908     fd.setScriptWrapper(QString("function clearTableOfContents(){"
909                                 "return %1.clearTableOfContents();}"
910                                ).arg(LimeReport::Const::FUNCTION_MANAGER_NAME)
911                         );
912     return addFunction(fd);
913 }
914 
915 bool ScriptEngineManager::createReopenDatasourceFunction()
916 {
917     JSFunctionDesc fd;
918     fd.setManager(m_functionManager);
919     fd.setManagerName(LimeReport::Const::FUNCTION_MANAGER_NAME);
920     fd.setCategory(tr("GENERAL"));
921     fd.setName("reopenDatasource");
922     fd.setDescription("reopenDatasource(\""+tr("datasourceName")+"\")");
923     fd.setScriptWrapper(QString("function reopenDatasource(datasourceName){"
924                                 "return %1.reopenDatasource(datasourceName);}"
925                                ).arg(LimeReport::Const::FUNCTION_MANAGER_NAME)
926                         );
927     return addFunction(fd);
928 }
929 
930 ScriptEngineManager::ScriptEngineManager()
931     :m_model(0), m_context(0), m_dataManager(0)
932 {
933     m_scriptEngine = new ScriptEngineType;
934     m_functionManager = new ScriptFunctionsManager(this);
935     m_functionManager->setScriptEngineManager(this);
936 #ifdef USE_QTSCRIPTENGINE
937     m_scriptEngine->setDefaultPrototype(qMetaTypeId<QComboBox*>(),
938                                   m_scriptEngine->newQObject(new ComboBoxPrototype()));
939 #endif
940     createLineFunction();
941     createNumberFomatFunction();
942     createDateFormatFunction();
943     createTimeFormatFunction();
944     createDateTimeFormatFunction();
945     createSectotimeFormatFunction();
946     createDateFunction();
947     createNowFunction();
948 #if QT_VERSION>0x040800
949     createCurrencyFormatFunction();
950     createCurrencyUSBasedFormatFunction();
951 #endif
952     createSetVariableFunction();
953     createGetFieldFunction();
954     createGetFieldByRowIndex();
955     createGetFieldByKeyFunction();
956     createGetVariableFunction();
957 #ifdef USE_QTSCRIPTENGINE
958     QScriptValue colorCtor = m_scriptEngine->newFunction(constructColor);
959     m_scriptEngine->globalObject().setProperty("QColor", colorCtor);
960 
961     QScriptValue fontProto(m_scriptEngine->newQObject(new QFontPrototype,QScriptEngine::ScriptOwnership));
962     m_scriptEngine->setDefaultPrototype(qMetaTypeId<QFont>(), fontProto);
963     QScriptValue fontConstructor = m_scriptEngine->newFunction(QFontPrototype::constructorQFont, fontProto);
964     m_scriptEngine->globalObject().setProperty("QFont", fontConstructor);
965 #endif
966     createAddBookmarkFunction();
967     createFindPageIndexByBookmark();
968     createAddTableOfContentsItemFunction();
969     createClearTableOfContentsFunction();
970     createReopenDatasourceFunction();
971 
972     m_model = new ScriptEngineModel(this);
973 }
974 
975 bool ScriptExtractor::parse()
976 {
977     int currentPos = 0;
978     parse(currentPos, None, m_scriptTree);
979     return m_scriptTree->children().count() > 0;
980 }
981 
982 bool ScriptExtractor::parse(int &curPos, const State& state, ScriptNode* scriptNode)
983 {
984     while (curPos<m_context.length()){
985         switch (state) {
986         case OpenBracketFound:
987             if (m_context[curPos]=='}'){
988                 return true;
989             } else {
990                 if (m_context[curPos]=='{')
991                    extractBracket(curPos, scriptNode);
992             }
993         case None:
994             if (m_context[curPos]=='$'){
995                 int startPos = curPos;
996                 if (isStartScriptLexem(curPos))
997                     extractScript(curPos, substring(m_context,startPos,curPos), scriptNode->createChildNode());
998                 if (isStartFieldLexem(curPos) || isStartVariableLexem(curPos))
999                     skipField(curPos);
1000             }
1001         default:
1002             break;
1003         }
1004         curPos++;
1005     }
1006     return false;
1007 }
1008 
1009 void ScriptExtractor::extractScript(int &curPos, const QString& startStr, ScriptNode* scriptNode)
1010 {
1011     int startPos = curPos;
1012     if (extractBracket(curPos, scriptNode)){
1013         QString scriptBody = substring(m_context,startPos+1,curPos);
1014         scriptNode->setBody(scriptBody);
1015         scriptNode->setStartLex(startStr+'{');
1016     }
1017 }
1018 
1019 void ScriptExtractor::skipField(int &curPos){
1020     while (curPos<m_context.length()) {
1021         if (m_context[curPos]=='}'){
1022             return;
1023         } else {
1024             curPos++;
1025         }
1026     }
1027 }
1028 
1029 bool ScriptExtractor::extractBracket(int &curPos, ScriptNode* scriptNode)
1030 {
1031     curPos++;
1032     return parse(curPos,OpenBracketFound, scriptNode);
1033 }
1034 
1035 bool ScriptExtractor::isStartLexem(int& curPos, QChar value){
1036     int pos = curPos+1;
1037     State ls = BuksFound;
1038     while (pos<m_context.length()){
1039         switch (ls){
1040         case BuksFound:
1041             if (m_context[pos]==value){
1042                 ls = SignFound;
1043             } else {
1044                 if (m_context[pos]!=' ')
1045                     return false;
1046             }
1047             break;
1048         case SignFound:
1049             if (m_context[pos]=='{'){
1050                 curPos=pos;
1051                 return true;
1052             } else
1053                 if (m_context[pos]!=' ')
1054                     return false;
1055         default:
1056             break;
1057         }
1058         pos++;
1059     }
1060     return false;
1061 }
1062 
1063 bool ScriptExtractor::isStartScriptLexem(int& curPos)
1064 {
1065     return isStartLexem(curPos, Const::SCRIPT_SIGN);
1066 }
1067 
1068 bool ScriptExtractor::isStartFieldLexem(int& curPos){
1069     return isStartLexem(curPos, Const::FIELD_SIGN);
1070 }
1071 
1072 bool ScriptExtractor::isStartVariableLexem(int &curPos)
1073 {
1074     return isStartLexem(curPos, Const::VARIABLE_SIGN);
1075 }
1076 
1077 
1078 QString ScriptExtractor::substring(const QString &value, int start, int end)
1079 {
1080     return value.mid(start,end-start);
1081 }
1082 
1083 QString DialogDescriber::name() const
1084 {
1085     return m_name;
1086 }
1087 
1088 void DialogDescriber::setName(const QString& name)
1089 {
1090     m_name = name;
1091 }
1092 
1093 QByteArray DialogDescriber::description() const
1094 {
1095     return m_description;
1096 }
1097 
1098 void DialogDescriber::setDescription(const QByteArray &description)
1099 {
1100     m_description = description;
1101 }
1102 
1103 #ifdef HAVE_UI_LOADER
1104 void ScriptEngineContext::addDialog(const QString& name, const QByteArray& description)
1105 {
1106     m_dialogs.push_back(DialogDescriber::create(name,description));
1107     emit dialogAdded(name);
1108 }
1109 
1110 bool ScriptEngineContext::changeDialog(const QString& name, const QByteArray& description)
1111 {
1112     foreach( DialogDescriber::Ptr describer, m_dialogs){
1113         if (describer->name().compare(name) == 0){
1114             describer->setDescription(description);
1115             {
1116                 QList<DialogPtr>::Iterator it = m_createdDialogs.begin();
1117                 while(it!=m_createdDialogs.end()){
1118                     if ((*it)->objectName()==name){
1119                         it = m_createdDialogs.erase(it);
1120                     } else {
1121                         ++it;
1122                     }
1123                 }
1124             }
1125             return true;
1126         }
1127     }
1128     return false;
1129 }
1130 
1131 bool ScriptEngineContext::changeDialogName(const QString& oldName, const QString& newName)
1132 {
1133     foreach( DialogDescriber::Ptr describer, m_dialogs){
1134         if (describer->name().compare(oldName) == 0){
1135             describer->setName(newName);
1136             {
1137                 QList<DialogPtr>::Iterator it = m_createdDialogs.begin();
1138                 while(it!=m_createdDialogs.end()){
1139                     if ((*it)->objectName()==oldName){
1140                         it = m_createdDialogs.erase(it);
1141                     } else {
1142                         ++it;
1143                     }
1144                 }
1145             }
1146             return true;
1147         }
1148     }
1149     return false;
1150 }
1151 
1152 bool ScriptEngineContext::previewDialog(const QString& dialogName)
1153 {
1154     QDialog* dialog = getDialog(dialogName);
1155     if (dialog) {
1156         dialog->exec();
1157         return true;
1158     } else {
1159         m_lastError = tr("Dialog with name: %1 can`t be created").arg(dialogName);
1160         return false;
1161     }
1162 }
1163 
1164 bool ScriptEngineContext::containsDialog(const QString& dialogName)
1165 {
1166     foreach(DialogDescriber::Ptr dialog, m_dialogs){
1167         if (dialog->name()==dialogName)
1168             return true;
1169     }
1170     return false;
1171 }
1172 
1173 void ScriptEngineContext::deleteDialog(const QString& dialogName)
1174 {
1175     {
1176         QVector<DialogDescriber::Ptr>::Iterator it = m_dialogs.begin();
1177         while(it!=m_dialogs.end()){
1178             if ((*it)->name()==dialogName){
1179                 it = m_dialogs.erase(it);
1180                 emit dialogDeleted(dialogName);
1181             } else {
1182                 ++it;
1183             }
1184         }
1185     }
1186     {
1187         QList<DialogPtr>::Iterator it = m_createdDialogs.begin();
1188         while(it!=m_createdDialogs.end()){
1189             if ((*it)->objectName()==dialogName){
1190                 it = m_createdDialogs.erase(it);
1191             } else {
1192                 ++it;
1193             }
1194         }
1195     }
1196 }
1197 
1198 #endif
1199 
1200 void ScriptEngineContext::clear()
1201 {
1202 #ifdef HAVE_UI_LOADER
1203     m_dialogs.clear();
1204     m_createdDialogs.clear();
1205 #endif
1206     m_initScript.clear();
1207     m_tableOfContents->clear();
1208     m_lastError="";
1209 }
1210 
1211 QObject* ScriptEngineContext::createElement(const QString& collectionName, const QString& elementType)
1212 {
1213     Q_UNUSED(elementType)
1214 #ifdef HAVE_UI_LOADER
1215     if (collectionName.compare("dialogs",Qt::CaseInsensitive)==0){
1216         m_dialogs.push_back(DialogDescriber::create());
1217         return m_dialogs.at(m_dialogs.count()-1).data();
1218     }
1219 #else
1220     Q_UNUSED(collectionName)
1221 #endif
1222     return 0;
1223 }
1224 
1225 int ScriptEngineContext::elementsCount(const QString& collectionName)
1226 {
1227 #ifdef HAVE_UI_LOADER
1228     if (collectionName.compare("dialogs",Qt::CaseInsensitive)==0){
1229         return m_dialogs.count();
1230     };
1231 #else
1232     Q_UNUSED(collectionName)
1233 #endif
1234     return 0;
1235 }
1236 
1237 QObject* ScriptEngineContext::elementAt(const QString& collectionName, int index)
1238 {
1239 #ifdef HAVE_UI_LOADER
1240     if (collectionName.compare("dialogs",Qt::CaseInsensitive)==0){
1241         return m_dialogs.at(index).data();
1242     };
1243 #else
1244     Q_UNUSED(collectionName)
1245     Q_UNUSED(index)
1246 #endif
1247     return 0;
1248 }
1249 
1250 void ScriptEngineContext::collectionLoadFinished(const QString& collectionName)
1251 {
1252     Q_UNUSED(collectionName);
1253 }
1254 
1255 ReportPages* ScriptEngineContext::reportPages() const
1256 {
1257     return m_reportPages;
1258 }
1259 
1260 void ScriptEngineContext::setReportPages(ReportPages *value)
1261 {
1262     m_reportPages = value;
1263 }
1264 
1265 #ifdef HAVE_UI_LOADER
1266 QDialog* ScriptEngineContext::createDialog(DialogDescriber* cont)
1267 {
1268     QUiLoader loader;
1269     QByteArray desc = cont->description();
1270     QBuffer buffer(&desc);
1271     buffer.open(QIODevice::ReadOnly);
1272     QDialog* dialog = dynamic_cast<QDialog*>(loader.load(&buffer));
1273     m_createdDialogs.push_back(QSharedPointer<QDialog>(dialog));
1274     if (cont->name().compare(dialog->objectName())){
1275         cont->setName(dialog->objectName());
1276         emit dialogNameChanged(dialog->objectName());
1277     }
1278     return dialog;
1279 }
1280 
1281 QDialog* ScriptEngineContext::findDialog(const QString& dialogName)
1282 {
1283     foreach(DialogPtr dialog, m_createdDialogs){
1284         if (dialog->objectName()==dialogName)
1285             return dialog.data();
1286     }
1287     return 0;
1288 }
1289 
1290 DialogDescriber* ScriptEngineContext::findDialogContainer(const QString& dialogName)
1291 {
1292     foreach (DialogDescriber::Ptr dialogCont , m_dialogs) {
1293         if (dialogCont->name().compare(dialogName,Qt::CaseInsensitive)==0){
1294             return dialogCont.data();
1295         }
1296     }
1297     return 0;
1298 }
1299 
1300 TableOfContents* ScriptEngineContext::tableOfContents() const
1301 {
1302     return m_tableOfContents;
1303 }
1304 
1305 void ScriptEngineContext::setTableOfContents(TableOfContents* tableOfContents)
1306 {
1307     m_tableOfContents = tableOfContents;
1308 }
1309 
1310 PageItemDesignIntf* ScriptEngineContext::getCurrentPage() const
1311 {
1312     return m_currentPage;
1313 }
1314 
1315 void ScriptEngineContext::setCurrentPage(PageItemDesignIntf* currentPage)
1316 {
1317     m_currentPage = currentPage;
1318     m_currentBand = 0;
1319 }
1320 
1321 BandDesignIntf* ScriptEngineContext::getCurrentBand() const
1322 {
1323     return m_currentBand;
1324 }
1325 
1326 void ScriptEngineContext::setCurrentBand(BandDesignIntf* currentBand)
1327 {
1328     m_currentBand = currentBand;
1329 }
1330 
1331 QDialog* ScriptEngineContext::getDialog(const QString& dialogName)
1332 {
1333     QDialog* dialog = findDialog(dialogName);
1334     if (dialog){
1335         return dialog;
1336     } else {
1337         DialogDescriber* cont = findDialogContainer(dialogName);
1338         if (cont){
1339             dialog = createDialog(cont);
1340             if (dialog)
1341                 return dialog;
1342         }
1343     }
1344     return 0;
1345 }
1346 
1347 QString ScriptEngineContext::getNewDialogName()
1348 {
1349     QString result = "Dialog";
1350     int index = m_dialogs.size() - 1;
1351     while (containsDialog(result)){
1352         index++;
1353         result = QString("Dialog%1").arg(index);
1354     }
1355     return result;
1356 }
1357 
1358 #endif
1359 
1360 void ScriptEngineContext::baseDesignIntfToScript(const QString& pageName, BaseDesignIntf* item)
1361 {
1362     if ( item ) {
1363         if (item->metaObject()->indexOfSignal("beforeRender()")!=-1)
1364             item->disconnect(SIGNAL(beforeRender()));
1365         if (item->metaObject()->indexOfSignal("afterData()")!=-1)
1366             item->disconnect(SIGNAL(afterData()));
1367         if (item->metaObject()->indexOfSignal("afterRender()")!=-1)
1368             item->disconnect(SIGNAL(afterRender()));
1369 
1370         ScriptEngineType* engine = ScriptEngineManager::instance().scriptEngine();
1371 
1372 #ifdef USE_QJSENGINE
1373         ScriptValueType sItem = getJSValue(*engine, item);
1374         QString on = item->patternName().compare(pageName) == 0 ? pageName : pageName+"_"+item->patternName();
1375         engine->globalObject().setProperty(on, sItem);
1376 #else
1377         QString on = item->patternName().compare(pageName) == 0 ? pageName : pageName+"_"+item->patternName();
1378         ScriptValueType sItem = engine->globalObject().property(on);
1379         if (sItem.isValid()){
1380             engine->newQObject(sItem, item);
1381         } else {
1382             sItem = engine->newQObject(item);
1383             engine->globalObject().setProperty(on,sItem);
1384         }
1385 #endif
1386         foreach(BaseDesignIntf* child, item->childBaseItems()){
1387             baseDesignIntfToScript(pageName, child);
1388         }
1389     }
1390 }
1391 
1392 void ScriptEngineContext::qobjectToScript(const QString& name, QObject *item)
1393 {
1394     ScriptEngineType* engine = ScriptEngineManager::instance().scriptEngine();
1395 #ifdef USE_QJSENGINE
1396         ScriptValueType sItem = getJSValue(*engine, item);
1397         engine->globalObject().setProperty(name, sItem);
1398 #else
1399         ScriptValueType sItem = engine->globalObject().property(name);
1400         if (sItem.isValid()){
1401             engine->newQObject(sItem, item);
1402         } else {
1403             sItem = engine->newQObject(item);
1404             engine->globalObject().setProperty(name,sItem);
1405         }
1406 #endif
1407 }
1408 
1409 #ifdef HAVE_UI_LOADER
1410 
1411 #ifdef USE_QJSENGINE
1412 void registerChildObjects(ScriptEngineType* se, ScriptValueType* sv){
1413     foreach(QObject* obj, sv->toQObject()->children()){
1414         ScriptValueType child = se->newQObject(obj);
1415         sv->setProperty(obj->objectName(),child);
1416         registerChildObjects(se, &child);
1417     }
1418 }
1419 #endif
1420 
1421 void ScriptEngineContext::initDialogs(){
1422     ScriptEngineType* se = ScriptEngineManager::instance().scriptEngine();
1423     foreach(DialogDescriber::Ptr dialog, dialogDescribers()){
1424         ScriptValueType sv = se->newQObject(getDialog(dialog->name()));
1425 #ifdef USE_QJSENGINE
1426         registerChildObjects(se,&sv);
1427 #endif
1428         se->globalObject().setProperty(dialog->name(),sv);
1429     }
1430 }
1431 
1432 #endif
1433 
1434 
1435 bool ScriptEngineContext::runInitScript(){
1436 
1437     ScriptEngineType* engine = ScriptEngineManager::instance().scriptEngine();
1438     ScriptEngineManager::instance().setContext(this);
1439     m_tableOfContents->clear();
1440 
1441     ScriptValueType res = engine->evaluate(initScript());
1442     if (res.isBool()) return res.toBool();
1443 #ifdef  USE_QJSENGINE
1444     if (res.isError()){
1445         QMessageBox::critical(0,tr("Error"),
1446             QString("Line %1: %2 ").arg(res.property("lineNumber").toString())
1447                                    .arg(res.toString())
1448         );
1449         return false;
1450     }
1451 #else
1452     if (engine->hasUncaughtException()) {
1453         QMessageBox::critical(0,tr("Error"),
1454             QString("Line %1: %2 ").arg(engine->uncaughtExceptionLineNumber())
1455                                    .arg(engine->uncaughtException().toString())
1456         );
1457         return false;
1458     }
1459 #endif
1460     return true;
1461 }
1462 
1463 QString ScriptEngineContext::initScript() const
1464 {
1465     return m_initScript;
1466 }
1467 
1468 void ScriptEngineContext::setInitScript(const QString& initScript)
1469 {
1470     if (m_initScript != initScript){
1471         m_initScript = initScript;
1472         m_hasChanges = true;
1473     }
1474 }
1475 
1476 DialogDescriber::Ptr DialogDescriber::create(const QString& name, const QByteArray& desc) {
1477     Ptr res(new DialogDescriber());
1478     res->setName(name);
1479     res->setDescription(desc);
1480     return res;
1481 }
1482 
1483 QString JSFunctionDesc::name() const
1484 {
1485     return m_name;
1486 }
1487 
1488 void JSFunctionDesc::setName(const QString &name)
1489 {
1490     m_name = name;
1491 }
1492 
1493 QString JSFunctionDesc::category() const
1494 {
1495     return m_category;
1496 }
1497 
1498 void JSFunctionDesc::setCategory(const QString &category)
1499 {
1500     m_category = category;
1501 }
1502 
1503 QString JSFunctionDesc::description() const
1504 {
1505     return m_description;
1506 }
1507 
1508 void JSFunctionDesc::setDescription(const QString &description)
1509 {
1510     m_description = description;
1511 }
1512 
1513 QString JSFunctionDesc::managerName() const
1514 {
1515     return m_managerName;
1516 }
1517 
1518 void JSFunctionDesc::setManagerName(const QString &managerName)
1519 {
1520     m_managerName = managerName;
1521 }
1522 
1523 QObject *JSFunctionDesc::manager() const
1524 {
1525     return m_manager;
1526 }
1527 
1528 void JSFunctionDesc::setManager(QObject *manager)
1529 {
1530     m_manager = manager;
1531 }
1532 
1533 QString JSFunctionDesc::scriptWrapper() const
1534 {
1535     return m_scriptWrapper;
1536 }
1537 
1538 void JSFunctionDesc::setScriptWrapper(const QString &scriptWrapper)
1539 {
1540     m_scriptWrapper = scriptWrapper;
1541 }
1542 
1543 QVariant ScriptFunctionsManager::calcGroupFunction(const QString &name, const QString &expressionID, const QString &bandName, QObject* currentPage)
1544 {
1545     if (m_scriptEngineManager->dataManager()){
1546         PageItemDesignIntf* pageItem = dynamic_cast<PageItemDesignIntf*>(currentPage);
1547         QString expression = m_scriptEngineManager->dataManager()->getExpression(expressionID);
1548         GroupFunction* gf =  m_scriptEngineManager->dataManager()->groupFunction(name,expression,bandName);
1549         if (gf){
1550             if (gf->isValid()){
1551                 return gf->calculate(pageItem);
1552             }else{
1553                 return gf->error();
1554             }
1555         }
1556         else {
1557             return QString(QObject::tr("Function %1 not found or have wrong arguments").arg(name));
1558         }
1559     } else {
1560         return QString(QObject::tr("Datasource manager not found"));
1561     }
1562 }
1563 
1564 QVariant ScriptFunctionsManager::calcGroupFunction(const QString& name, const QString& expressionID, const QString& bandName)
1565 {
1566     return calcGroupFunction(name, expressionID, bandName, 0);
1567 }
1568 
1569 QVariant ScriptFunctionsManager::line(const QString &bandName)
1570 {
1571     QString varName = QLatin1String("line_")+bandName.toLower();
1572     QVariant res;
1573     if (scriptEngineManager()->dataManager()->variable(varName).isValid()){
1574         res=scriptEngineManager()->dataManager()->variable(varName);
1575     } else res=QString("Variable line for band %1 not found").arg(bandName);
1576     return res;
1577 }
1578 
1579 QVariant ScriptFunctionsManager::numberFormat(QVariant value, const char &format, int precision, const QString& locale)
1580 {
1581     return (locale.isEmpty()) ? QString::number(value.toDouble(),format,precision):
1582                                 QLocale(locale).toString(value.toDouble(),format,precision);
1583 }
1584 
1585 QVariant ScriptFunctionsManager::dateFormat(QVariant value, const QString &format, const QString& locale)
1586 {
1587     return (locale.isEmpty()) ?  QLocale().toString(value.toDate(),format) :
1588                                  QLocale(locale).toString(value.toDate(),format);
1589 }
1590 
1591 QVariant ScriptFunctionsManager::timeFormat(QVariant value, const QString &format)
1592 {
1593     return QLocale().toString(value.toTime(),format);
1594 }
1595 
1596 QVariant ScriptFunctionsManager::dateTimeFormat(QVariant value, const QString &format, const QString& locale)
1597 {
1598     return (locale.isEmpty()) ? QLocale().toString(value.toDateTime(),format) :
1599                                 QLocale(locale).toString(value.toDateTime(),format);
1600 }
1601 
1602 QVariant ScriptFunctionsManager::sectotimeFormat(QVariant value, const QString &format)
1603 {
1604     int seconds = value.toInt();
1605     int minutes = seconds / 60;
1606     int hours = minutes / 60;
1607 
1608     QString result = format;
1609     bool hasHour = format.contains("h");
1610     bool hasMinute = format.contains("m");
1611     for(int len = 2; len; len--) {
1612         if(hasHour)   result.replace(QString('h').repeated(len), QString::number(hours).rightJustified(len, '0'));
1613         if(hasMinute) result.replace(QString('m').repeated(len), QString::number(hasHour ? minutes % 60 : minutes).rightJustified(len, '0'));
1614         result.replace(QString('s').repeated(len), QString::number(hasMinute ? seconds % 60 : seconds).rightJustified(len, '0'));
1615     }
1616     return result;
1617 }
1618 
1619 QVariant ScriptFunctionsManager::date()
1620 {
1621     return QDate::currentDate();
1622 }
1623 
1624 QVariant ScriptFunctionsManager::now()
1625 {
1626     return QDateTime::currentDateTime();
1627 }
1628 
1629 QVariant ScriptFunctionsManager::currencyFormat(QVariant value, const QString &locale)
1630 {
1631     QString l = (!locale.isEmpty())?locale:QLocale::system().name();
1632     return QLocale(l).toCurrencyString(value.toDouble());
1633 }
1634 
1635 QVariant ScriptFunctionsManager::currencyUSBasedFormat(QVariant value, const QString &currencySymbol)
1636 {
1637     QString CurrencySymbol = (!currencySymbol.isEmpty())?currencySymbol:QLocale::system().currencySymbol();
1638     // Format it using USA locale
1639     QString vTempStr=QLocale(QLocale::English, QLocale::UnitedStates).toCurrencyString(value.toDouble());
1640     // Replace currency symbol if necesarry
1641     if (CurrencySymbol!="") vTempStr.replace("$", CurrencySymbol);
1642     return vTempStr;
1643 }
1644 
1645 void ScriptFunctionsManager::setVariable(const QString &name, QVariant value)
1646 {
1647     DataSourceManager* dm = scriptEngineManager()->dataManager();
1648     if (dm->containsVariable(name)){
1649         dm->changeVariable(name,value);
1650     } else {
1651         dm->addVariable(name, value, VarDesc::User);
1652     }
1653 }
1654 
1655 QVariant ScriptFunctionsManager::getVariable(const QString &name)
1656 {
1657     DataSourceManager* dm = scriptEngineManager()->dataManager();
1658     return dm->variable(name);
1659 }
1660 
1661 QVariant ScriptFunctionsManager::getField(const QString &field)
1662 {
1663     DataSourceManager* dm = scriptEngineManager()->dataManager();
1664     return dm->fieldData(field);
1665 }
1666 
1667 QVariant ScriptFunctionsManager::getFieldByKeyField(const QString& datasourceName, const QString& valueFieldName, const QString& keyFieldName, QVariant keyValue)
1668 {
1669     DataSourceManager* dm = scriptEngineManager()->dataManager();
1670     return dm->fieldDataByKey(datasourceName, valueFieldName, keyFieldName, keyValue);
1671 }
1672 
1673 QVariant ScriptFunctionsManager::getFieldByRowIndex(const QString &fieldName, int rowIndex)
1674 {
1675     DataSourceManager* dm = scriptEngineManager()->dataManager();
1676     return dm->fieldDataByRowIndex(fieldName, rowIndex);
1677 }
1678 
1679 void ScriptFunctionsManager::reopenDatasource(const QString& datasourceName)
1680 {
1681     DataSourceManager* dm = scriptEngineManager()->dataManager();
1682     return dm->reopenDatasource(datasourceName);
1683 }
1684 
1685 void ScriptFunctionsManager::addBookmark(const QString &uniqKey, const QString &content)
1686 {
1687     scriptEngineManager()->addBookMark(uniqKey, content);
1688 }
1689 
1690 int ScriptFunctionsManager::findPageIndexByBookmark(const QString &uniqKey)
1691 {
1692     return scriptEngineManager()->findPageIndexByBookmark(uniqKey);
1693 }
1694 
1695 void ScriptFunctionsManager::addTableOfContentsItem(const QString& uniqKey, const QString& content, int indent)
1696 {
1697     scriptEngineManager()->addTableOfContentsItem(uniqKey, content, indent);
1698 }
1699 
1700 void ScriptFunctionsManager::clearTableOfContents()
1701 {
1702     scriptEngineManager()->clearTableOfContents();
1703 }
1704 
1705 QFont ScriptFunctionsManager::font(const QString &family, int pointSize, bool italic, bool bold, bool underLine)
1706 {
1707     QFont result (family, pointSize);
1708     result.setBold(bold);
1709     result.setItalic(italic);
1710     result.setUnderline(underLine);
1711     return result;
1712 }
1713 
1714 #ifdef USE_QJSENGINE
1715 
1716 void ScriptFunctionsManager::addItemsToComboBox(QJSValue object, const QStringList &values)
1717 {
1718     QComboBox* comboBox = dynamic_cast<QComboBox*>(object.toQObject());
1719     if (comboBox){
1720         comboBox->addItems(values);
1721     }
1722 }
1723 
1724 void ScriptFunctionsManager::addItemToComboBox(QJSValue object, const QString &value)
1725 {
1726     QComboBox* comboBox = dynamic_cast<QComboBox*>(object.toQObject());
1727     if (comboBox){
1728         comboBox->addItem(value);
1729     }
1730 }
1731 
1732 QJSValue ScriptFunctionsManager::createComboBoxWrapper(QJSValue comboBox)
1733 {
1734     QComboBox* item = dynamic_cast<QComboBox*>(comboBox.toQObject());
1735     if (item){
1736         ComboBoxWrapper* wrapper = new ComboBoxWrapper(item);
1737         return m_scriptEngineManager->scriptEngine()->newQObject(wrapper);
1738     }
1739     return QJSValue();
1740 }
1741 
1742 QJSValue ScriptFunctionsManager::createWrapper(QJSValue item)
1743 {
1744     QObject* object = item.toQObject();
1745     if (object){
1746         IWrapperCreator* wrapper = m_wrappersFactory.value(object->metaObject()->className());
1747         if (wrapper){
1748             return m_scriptEngineManager->scriptEngine()->newQObject(wrapper->createWrapper(item.toQObject()));
1749         }
1750     }
1751     return QJSValue();
1752 }
1753 
1754 #else
1755 
1756 void ScriptFunctionsManager::addItemsToComboBox(QScriptValue object, const QStringList &values)
1757 {
1758     QComboBox* comboBox = dynamic_cast<QComboBox*>(object.toQObject());
1759     if (comboBox){
1760         comboBox->addItems(values);
1761     }
1762 }
1763 
1764 void ScriptFunctionsManager::addItemToComboBox(QScriptValue object, const QString &value)
1765 {
1766     QComboBox* comboBox = dynamic_cast<QComboBox*>(object.toQObject());
1767     if (comboBox){
1768         comboBox->addItem(value);
1769     }
1770 }
1771 
1772 QScriptValue ScriptFunctionsManager::createComboBoxWrapper(QScriptValue comboBox)
1773 {
1774     QComboBox* item = dynamic_cast<QComboBox*>(comboBox.toQObject());
1775     if (item){
1776         ComboBoxWrapper* wrapper = new ComboBoxWrapper(item);
1777         return m_scriptEngineManager->scriptEngine()->newQObject(wrapper);
1778     }
1779     return QScriptValue();
1780 }
1781 
1782 QScriptValue ScriptFunctionsManager::createWrapper(QScriptValue item)
1783 {
1784     QObject* object = item.toQObject();
1785     if (object){
1786         IWrapperCreator* wrapper = m_wrappersFactory.value(object->metaObject()->className());
1787         if (wrapper){
1788             return m_scriptEngineManager->scriptEngine()->newQObject(wrapper->createWrapper(item.toQObject()));
1789         }
1790     }
1791     return QScriptValue();
1792 }
1793 
1794 #endif
1795 
1796 QFont ScriptFunctionsManager::font(QVariantMap params){
1797     if (!params.contains("family")){
1798         return QFont();
1799     } else {
1800         QFont result(params.value("family").toString());
1801         if (params.contains("pointSize"))
1802             result.setPointSize(params.value("pointSize").toInt());
1803         if (params.contains("bold"))
1804             result.setBold(params.value("bold").toBool());
1805         if (params.contains("italic"))
1806             result.setItalic(params.value("italic").toBool());
1807         if (params.contains("underline"))
1808             result.setUnderline(params.value("underline").toBool());
1809         return result;
1810     }
1811 }
1812 
1813 ScriptEngineManager *ScriptFunctionsManager::scriptEngineManager() const
1814 {
1815     return m_scriptEngineManager;
1816 }
1817 
1818 void ScriptFunctionsManager::setScriptEngineManager(ScriptEngineManager *scriptEngineManager)
1819 {
1820     m_scriptEngineManager = scriptEngineManager;
1821 }
1822 
1823 TableOfContents::~TableOfContents()
1824 {
1825     clear();
1826 }
1827 
1828 void TableOfContents::setItem(const QString& uniqKey, const QString& content, int pageNumber, int indent)
1829 {
1830     ContentItem * item = 0;
1831     if (m_hash.contains(uniqKey)){
1832         item = m_hash.value(uniqKey);
1833         item->content = content;
1834         item->pageNumber = pageNumber;
1835         if (indent>0)
1836             item->indent = indent;
1837     } else {
1838         item = new ContentItem;
1839         item->content = content;
1840         item->pageNumber = pageNumber;
1841         item->indent = indent;
1842         item->uniqKey = uniqKey;
1843         m_tableOfContents.append(item);
1844         m_hash.insert(uniqKey, item);
1845     }
1846 
1847 }
1848 
1849 void TableOfContents::slotOneSlotDS(CallbackInfo info, QVariant& data)
1850 {
1851     QStringList columns;
1852     columns << "Content" << "Page number" << "Content Key";
1853 
1854     switch (info.dataType) {
1855         case LimeReport::CallbackInfo::RowCount:
1856             data = m_tableOfContents.count();
1857             break;
1858         case LimeReport::CallbackInfo::ColumnCount:
1859             data = columns.size();
1860             break;
1861         case LimeReport::CallbackInfo::ColumnHeaderData: {
1862             data = columns.at(info.index);
1863             break;
1864         }
1865         case LimeReport::CallbackInfo::ColumnData:
1866             if (info.index < m_tableOfContents.count()){
1867                 ContentItem* item = m_tableOfContents.at(info.index);
1868                 if (info.columnName.compare("Content",Qt::CaseInsensitive) == 0)
1869                     data = item->content.rightJustified(item->indent+item->content.size());
1870                 if (info.columnName.compare("Content Key",Qt::CaseInsensitive) == 0)
1871                     data = item->uniqKey;
1872                 if (info.columnName.compare("Page number",Qt::CaseInsensitive) == 0)
1873                     data = QString::number(item->pageNumber);
1874             }
1875             break;
1876         default: break;
1877     }
1878 }
1879 
1880 void LimeReport::TableOfContents::clear(){
1881 
1882     m_hash.clear();
1883     foreach(ContentItem* item, m_tableOfContents){
1884         delete item;
1885     }
1886     m_tableOfContents.clear();
1887 
1888 }
1889 
1890 QObject* ComboBoxWrapperCreator::createWrapper(QObject *item)
1891 {
1892     QComboBox* comboBox = dynamic_cast<QComboBox*>(item);
1893     if (comboBox){
1894         return  new ComboBoxWrapper(comboBox);
1895     }
1896     return 0;
1897 }
1898 
1899 bool DatasourceFunctions::first(const QString& datasourceName)
1900 {
1901     if (m_dataManager && m_dataManager->dataSource(datasourceName)){
1902         m_dataManager->dataSource(datasourceName)->first();
1903         return true;
1904     }
1905     return false;
1906 }
1907 
1908 bool DatasourceFunctions::next(const QString &datasourceName){
1909     if (m_dataManager && m_dataManager->dataSource(datasourceName))
1910         return m_dataManager->dataSource(datasourceName)->next();
1911     return false;
1912 }
1913 
1914 bool DatasourceFunctions::prior(const QString& datasourceName)
1915 {
1916     if (m_dataManager && m_dataManager->dataSource(datasourceName))
1917         return m_dataManager->dataSource(datasourceName)->prior();
1918     return false;
1919 }
1920 
1921 bool DatasourceFunctions::isEOF(const QString &datasourceName)
1922 {
1923     if (m_dataManager && m_dataManager->dataSource(datasourceName))
1924         return m_dataManager->dataSource(datasourceName)->eof();
1925     return true;
1926 }
1927 
1928 bool DatasourceFunctions::invalidate(const QString& datasourceName)
1929 {
1930     if (m_dataManager && m_dataManager->dataSource(datasourceName)){
1931         m_dataManager->dataSourceHolder(datasourceName)->invalidate(IDataSource::RENDER_MODE);
1932         return true;
1933     }
1934     return false;
1935 }
1936 
1937 QObject* DatasourceFunctions::createTableBuilder(BaseDesignIntf* horizontalLayout)
1938 {
1939     return new TableBuilder(dynamic_cast<LimeReport::HorizontalLayout*>(horizontalLayout), dynamic_cast<DataSourceManager*>(m_dataManager));
1940 }
1941 
1942 TableBuilder::TableBuilder(HorizontalLayout* layout, DataSourceManager* dataManager)
1943     : m_horizontalLayout(layout), m_baseLayout(0), m_dataManager(dataManager)
1944 {
1945     if (m_horizontalLayout)
1946         m_patternLayout = dynamic_cast<HorizontalLayout*>(m_horizontalLayout->cloneItem(m_horizontalLayout->itemMode()));
1947 }
1948 
1949 QObject* TableBuilder::addRow()
1950 {
1951     checkBaseLayout();
1952     if (m_baseLayout && m_patternLayout){
1953         HorizontalLayout* newRow = new HorizontalLayout(m_baseLayout, m_baseLayout);
1954         newRow->setLayoutSpacing(m_horizontalLayout->layoutSpacing());
1955         for(int i = 0; i < m_horizontalLayout->childrenCount(); ++i){
1956             BaseDesignIntf* item = dynamic_cast<BaseDesignIntf*>(m_patternLayout->at(i));
1957             BaseDesignIntf* cloneItem = item->cloneItem(item->itemMode(), newRow, newRow);
1958             newRow->addChild(cloneItem);
1959         }
1960         m_baseLayout->addChild(newRow);
1961         return newRow;
1962     } else return 0;
1963 }
1964 
1965 QObject* TableBuilder::currentRow()
1966 {
1967     checkBaseLayout();
1968     if (m_baseLayout && m_baseLayout->childrenCount()>0)
1969         return m_baseLayout->at(m_baseLayout->childrenCount()-1);
1970     return 0;
1971 }
1972 
1973 void TableBuilder::fillInRowData(QObject* row)
1974 {
1975     HorizontalLayout* layout = dynamic_cast<HorizontalLayout*>(row);
1976     if (layout){
1977         for (int i = 0; i < layout->childrenCount(); ++i) {
1978             BaseDesignIntf* item = dynamic_cast<BaseDesignIntf*>(layout->at(i));
1979             DataSourceManager* dm = dynamic_cast<DataSourceManager*>(m_dataManager);
1980             if (item && dm)
1981                 item->updateItemSize(dm);
1982         }
1983     }
1984 }
1985 
1986 void TableBuilder::buildTable(const QString& datasourceName)
1987 {
1988     checkBaseLayout();
1989     m_dataManager->dataSourceHolder(datasourceName)->invalidate(IDataSource::RENDER_MODE);
1990     m_dataManager->dataSource(datasourceName)->first();
1991     bool firstTime = true;
1992     QObject* row = m_horizontalLayout;
1993     while(!m_dataManager->dataSource(datasourceName)->eof()){
1994         if (!firstTime) row =  addRow();
1995         else firstTime = false;
1996         fillInRowData(row);
1997         m_dataManager->dataSource(datasourceName)->next();
1998     }
1999 }
2000 
2001 void TableBuilder::checkBaseLayout()
2002 {
2003     if (!m_baseLayout){
2004         m_baseLayout = dynamic_cast<VerticalLayout*>(m_horizontalLayout->parentItem());
2005         if (!m_baseLayout){
2006             m_baseLayout = new VerticalLayout(m_horizontalLayout->parent(), m_horizontalLayout->parentItem());
2007             m_baseLayout->setItemLocation(m_horizontalLayout->itemLocation());
2008             m_baseLayout->setPos(m_horizontalLayout->pos());
2009             m_baseLayout->setWidth(m_horizontalLayout->width());
2010             m_baseLayout->setHeight(0);
2011             m_baseLayout->addChild(m_horizontalLayout);
2012             m_baseLayout->setObjectName(QUuid::createUuid().toString());
2013             m_baseLayout->setItemTypeName("VerticalLayout");
2014         }
2015     }
2016 }
2017 
2018 #ifdef USE_QTSCRIPTENGINE
2019 void ComboBoxPrototype::addItem(const QString &text)
2020 {
2021     QComboBox* comboBox = qscriptvalue_cast<QComboBox*>(thisObject());
2022     if (comboBox){
2023         comboBox->addItem(text);
2024     }
2025 }
2026 
2027 void ComboBoxPrototype::addItems(const QStringList &texts)
2028 {
2029     QComboBox* comboBox = qscriptvalue_cast<QComboBox*>(thisObject());
2030     if (comboBox){
2031         comboBox->addItems(texts);
2032     }
2033 }
2034 #endif
2035 
2036 } //namespace LimeReport
2037 
2038