3 // Author: Frantisek Vacek <fanda.vacek@volny.cz>, (C) 2007
5 // Copyright: See COPYING file that comes with this distribution
8 #include "qfscriptdriver.h"
10 #include <qffileutils.h>
11 #include <qfsqlquery.h>
12 #include <qfxmltable.h>
13 #include <qfappdbconnectioninterface.h>
15 #include <qfsearchdirs.h>
17 #include <QScriptEngine>
18 #include <QScriptValueIterator>
20 #include <qflogcust.h>
22 //=========================================================
24 //=========================================================
25 QStringList
QFScriptDriver::f_path
;
27 QFScriptDriver::QFScriptDriver(QObject
*parent
)
28 : QObject(parent
), f_scriptEngine(NULL
)
32 QFScriptDriver::~QFScriptDriver()
36 QScriptEngine
* QFScriptDriver::scriptEngine()
39 f_scriptEngine
= new QScriptEngine(this);
40 //qfInfo() << "created script engine:" << f_scriptEngine;
41 QScriptValue sv
= f_scriptEngine
->newQObject(this);
42 f_scriptEngine
->globalObject().setProperty("driver", sv
);
43 QString code
= loadModuleObjectCode("qf.qf");
46 evaluate("qf.config.isDebug = true");
49 return f_scriptEngine
;
52 QScriptValue
QFScriptDriver::resolveFunction(const QString
& function_name
, const QString
& script_name
, bool throw_exc
)
54 qfTrash() << QF_FUNC_NAME
<< "fn:" << function_name
<< "script:" << script_name
<< "throw_exc:" << throw_exc
;
55 //QScriptValue sv = scriptEngine()->evaluate(function_name);
56 QScriptValue sv
= scriptEngine()->evaluate("qf.getObject("SARG(function_name
)")");
58 if(!sv
.isFunction()) {
60 if(!script_name
.isEmpty()) {
62 QString code
= loadScriptCode(script_name
, &found_fn
);
63 if(!found_fn
.isEmpty()) {
64 evaluate(code
, throw_exc
);
65 //sv = scriptEngine()->evaluate(function_name);
66 sv
= scriptEngine()->evaluate("qf.getObject("SARG(function_name
)")");
67 if(throw_exc
&& !sv
.isFunction()) QF_EXCEPTION(tr("Skript '%1' neobsahuje funkci '%2'.").arg(script_name
).arg(function_name
));
69 else if(throw_exc
) QF_EXCEPTION(tr("Skript '%1' nebyl nalezen.").arg(script_name
));
71 else if(throw_exc
) QF_EXCEPTION(tr("Nazev skriptu je prazdny.").arg(script_name
));
76 QScriptValue
QFScriptDriver::resolveModuleObjectFunction(const QString
& function_name
, const QString
& module_name
, bool throw_exc
)
78 qfLogFuncFrame() << "fn:" << function_name
<< "module_name:" << module_name
<< "throw_exc:" << throw_exc
;
79 QString fn
= module_name
+ "." + function_name
;
80 /// tohle by melo fungovat stejne, ale pokud modul obsahuje klicove slovo javascriptu, tak NE
81 ///QScriptValue sv = scriptEngine()->evaluate(fn);
82 QScriptValue sv
= scriptEngine()->evaluate("qf.getObject("SARG(fn
)")");
84 if(!sv
.isFunction()) {
85 sv
= moduleObject(module_name
, throw_exc
);
87 sv
= scriptEngine()->evaluate("qf.getObject("SARG(fn
)")");
88 if(throw_exc
&& !sv
.isFunction()) QF_EXCEPTION(tr("Modul '%1' neobsahuje funkci '%2'.").arg(module_name
).arg(function_name
));
92 if(throw_exc
) QF_EXCEPTION(tr("Modul '%1' neni objekt ani funkce.").arg(module_name
));
98 QStringList
QFScriptDriver::functionList(const QString
& script_name
)
102 QString code
= loadScriptCode(script_name
, &found_fn
);
103 if(!found_fn
.isEmpty()) {
104 QRegExp
rx("function\\s+([A-Za-z]\\w*)\\s*\\(\\s*\\)");
106 while((ix
= rx
.indexIn(code
, ix
)) != -1) {
107 ix
+= rx
.matchedLength();
108 fnc_lst
<< rx
.capturedTexts()[1];
114 QStringList & QFScriptDriver::searchPathRef()
116 if(f_path.isEmpty()) {
117 f_path << QFFileUtils::joinPath(QFFileUtils::appDir(), "script");
118 f_path << ":/libqf/script";
123 QString
QFScriptDriver::resolveIncludes(const QString
& code
, const QString
& code_file
)
125 qfLogFuncFrame() << "code_file:" << code_file
;
126 //qfTrash() << "code:\n" << code;
131 static const QString s_wrap = "#wrap_module";
132 if(ret.indexOf(s_wrap) >= 0) {
133 QRegExp rx_declare("#declare_module\\s*\\(([A-Za-z_][A-Za-z0-9_]*)\\)");
134 int ix = rx_declare.indexIn(ret);
135 if(ix < 0) QF_EXCEPTION("#wrap_module withouth #declare_module in " + code_file);
137 QString declare_replace = rx_declare.cap(0);
138 QString obj_name = rx_declare.cap(1).trimmed();
139 if(obj_name.isEmpty()) QF_EXCEPTION("#declare_module() object name is empty");
141 static const QString s_prefix = "if(!qf.getObject('${MODULE_NAME}')) { (function()";
142 static const QString s_postfix = ")(); }";
143 static const QString s_declare = "qf.declare('${MODULE_NAME}', %1);";
145 ret.replace(declare_replace, s_declare.arg(obj_name));
146 ret.replace(s_wrap, s_prefix);
152 static QRegExp re_include
;
153 if(re_include
.isEmpty()) {
154 re_include
= QRegExp("#include\\s*\"(.+)\"");
155 re_include
.setMinimal(true);
158 while ((pos
= re_include
.indexIn(code
, pos
)) != -1) {
159 QString inc
= re_include
.cap(0);
160 QString fn
= re_include
.cap(1);
161 qfTrash() << "\t found:" << inc
;
162 pos
+= re_include
.matchedLength();
163 QFSearchDirs sd
= searchDirs();
164 //QStringList path = searchPathRef();
165 QString code_file_path
= QFFileUtils::path(code_file
);
166 //if(!path.contains(code_file_path)) searchPathRef().prepend(code_file_path);
167 if(!code_file_path
.isEmpty()) {
168 searchDirsRef().prependDir(code_file_path
);
171 QString inc_code
= loadScriptCode(fn
, &found_fn
);
172 searchDirsRef() = sd
;
173 if(found_fn
.isEmpty()) {
174 qfWarning() << "can't resolve include " << inc
;
177 ret
.replace(inc
, inc_code
);
178 qfTrash() << "\t resolved";
184 static QString
replace_module_name(const QString
&code
, const QString
& module_object_name
)
186 static const QString s_mn
= "${MODULE_NAME}";
188 return s
.replace(s_mn
, module_object_name
);
191 QString
QFScriptDriver::loadModuleObjectCode(const QString
& module_object_name
, QString
*found_file_name
)
193 qfLogFuncFrame() << "module_object_name:" << module_object_name
;
194 QString fn
= module_object_name
;
195 fn
= fn
.replace('.', '/') + ".js";
197 QString code
= QFScriptDriver::loadScriptCode(fn
, &ffn
);
199 code
= replace_module_name(code
, module_object_name
);
200 if(found_file_name
) *found_file_name
= ffn
;
205 QString
QFScriptDriver::loadScriptCode(const QString
& script_name
, QString
*found_file_name
)
207 qfLogFuncFrame() << "script_name:" << script_name
;
210 QString fn
= searchDirs().findFile(script_name
);
212 foreach(QString s, searchPathRef()) {
213 QString s2 = QFFileUtils::joinPath(s, script_name);
214 qfTrash() << "\t trying:" << s2;
215 if(QFile::exists(s2)) {
222 if(QFile::exists(script_name
)) fn
= script_name
;
226 if(f
.open(QFile::ReadOnly
)) {
227 qfTrash() << "\t opening script:" << fn
;
229 QByteArray ba
= f
.readAll();
230 ret
= QString::fromUtf8(ba
.constData(), ba
.size());
231 ret
= resolveIncludes(ret
, fn
);
234 if(found_file_name
) *found_file_name
= found_fn
;
240 QScriptValue QFScriptDriver::evaluateFirstFunction(const QString & script_name, bool throw_exc) throw( QFException )
242 QStringList fnc_lst = functionList(script_name);
243 if(fnc_lst.isEmpty()) QF_EXCEPTION(tr("Skript %1 nebyl nalezen nebo neobsahuje zadne funkce.").arg(script_name));
245 sv = evaluateFunction(fnc_lst[0], script_name, throw_exc);
250 static QString
number_lines(const QString
&code
)
252 QStringList code_lines
= code
.split('\n');
253 QStringList lines_with_numbers
;
255 foreach(QString s
, code_lines
) lines_with_numbers
<< QString::number(++n
) + ": " + s
;
256 return lines_with_numbers
.join("\n");
259 QScriptValue
QFScriptDriver::evaluate(const QString
& script_code
, bool throw_exc
) throw( QFException
)
262 QScriptEngine
*eng
= scriptEngine();
263 qfTrash().color(QFLog::Yellow
) << script_code
.mid(0, 380);
264 //qfTrash() << dumpContext();
265 QScriptValue ret
= eng
->evaluate(script_code
);
266 if(throw_exc
&& eng
->hasUncaughtException()) {
267 QString s
= tr("Vyjjimka \n%3\n pri provadeni skriptu na radku %1\n%2\n\n%4")
268 .arg(eng
->uncaughtExceptionLineNumber())
269 .arg(eng
->uncaughtExceptionBacktrace().join("\n")).arg(ret
.toString()).arg(number_lines(script_code
));
272 if(ret
.isError() && throw_exc
) {
273 QF_EXCEPTION(ret
.toString());
275 qfTrash() << "\t return:" << scriptValueToJsonString(ret
);
279 QScriptValue
QFScriptDriver::evaluateScript(const QString
& script_name
, bool throw_exc
) throw( QFException
)
282 QString script_code
= loadScriptCode(script_name
, &found_fn
);
283 if(found_fn
.isEmpty()) {
284 if(throw_exc
) QF_EXCEPTION(tr("Skript '%1' nebyl nalezen.").arg(script_name
));
286 qfWarning() << "script code" << script_name
<< "load error";
287 return QScriptValue();
290 return evaluate(script_code
, throw_exc
);
293 QScriptValue
QFScriptDriver::moduleObject(const QString
& module_name
, bool throw_exc
) throw( QFException
)
295 qfLogFuncFrame() << "module_name:" << module_name
<< "throw_exc:" << throw_exc
;
296 /// tohle by melo fungovat stejne, ale pokud modul obsahuje klicove slovo javascriptu, tak NE
297 ///QScriptValue sv = scriptEngine()->evaluate(module_name);
298 QScriptValue sv
= scriptEngine()->evaluate("qf.getObject("SARG(module_name
)")");
299 qfTrash() << "\t sv:" << sv
.toString();
300 if(!sv
.isObject() || sv
.isError()) {
301 qfTrash() << "\t not found, try to load it";
303 QString code
= loadModuleObjectCode(module_name
, &ffn
);
305 if(throw_exc
) QF_EXCEPTION(tr("Can't load code for module object: '%1'.").arg(module_name
));
306 return QScriptValue();
308 evaluate(code
, throw_exc
);
309 sv
= scriptEngine()->evaluate("qf.getObject("SARG(module_name
)")");
310 //sv = scriptEngine()->evaluate(module_name);
311 //qfInfo() << QFScriptDriver::scriptValueToJsonString(sv);
312 if(!sv
.isObject() || sv
.isError()) {
314 if(throw_exc
) QF_EXCEPTION(tr("Load module object error '%1'.").arg(module_name
));
317 if(throw_exc
) QF_EXCEPTION(tr("Load module object error '%1' is neighter object nor function.").arg(module_name
));
325 QScriptValue QFScriptDriver::callObjectFunction(const QString function_name, const QString & object_name, const QScriptValue & this_object, const QScriptValueList & args, bool throw_exc) throw( QFException )
327 //QString object_name = module_name;
328 //object_name.replace('.', '_');
329 return callFunction(module_name + "." + function_name, object_name, this_object, args, throw_exc);
333 QScriptValue
QFScriptDriver::callModuleObjectFunction(const QString function_name
, const QString
& module_object_name
, const QScriptValue
& this_object
, const QScriptValueList
& args
, bool throw_exc
) throw( QFException
)
336 qfTrash().color(QFLog::Green
) << "function_name:" << function_name
<< "module_name:" << module_object_name
;
337 QScriptValue sv
= resolveModuleObjectFunction(function_name
, module_object_name
, throw_exc
);
338 qfTrash() << "\t fn:" << sv
.toString();
339 qfTrash() << "\t this_object:" << this_object
.toString();
340 sv
= callFunction(sv
, this_object
, args
, throw_exc
);
344 QScriptValue
QFScriptDriver::callFunction(const QString function_name
, const QString
& script_name
, const QScriptValue
& this_object
, const QScriptValueList
& args
, bool throw_exc
) throw( QFException
)
347 qfTrash().color(QFLog::Green
) << "function_name:" << function_name
<< "script_name:" << script_name
;
348 QScriptValue sv
= resolveFunction(function_name
, script_name
, throw_exc
);
349 QScriptValue this_o
= this_object
;
350 if(!this_o
.isValid()) {
351 QStringList sl
= function_name
.split('.');
354 this_o
= evaluate(sl
.join("."), throw_exc
);
357 qfTrash() << "\t fn:" << sv
.toString();
358 qfTrash() << "\t this_object:" << this_o
.toString();
359 sv
= callFunction(sv
, this_o
, args
, throw_exc
);
363 QScriptValue
QFScriptDriver::callFunction(QScriptValue
& fn
, const QScriptValue
& this_object
, const QScriptValueList
& args
, bool throw_exc
) throw( QFException
)
366 if(throw_exc
&& !fn
.isFunction()) {
367 QString s
= tr("Objekt neni funkce.");
370 QScriptValue ret
= fn
.call(this_object
, args
);
371 QScriptEngine
*eng
= fn
.engine();
372 if(throw_exc
&& eng
->hasUncaughtException()) {
373 QString s
= tr("Vyjjimka ve funkci na radku %1\n%2\n\n%3")
374 .arg(eng
->uncaughtExceptionLineNumber())
375 .arg(eng
->uncaughtExceptionBacktrace().join("\n"))
376 .arg(number_lines(fn
.toString()));
382 void QFScriptDriver::log(int level
, const QString
& message
)
384 //qfInfo() << QF_FUNC_NAME;
385 QFLog(level
, QString("%1:%2").arg("#script").arg('#')) << message
;
388 QScriptValue
QFScriptDriver::variantToScriptValue(const QVariant
& v
)
391 //qfInfo() << "value:" << v.toString() << "type:" << QVariant::typeToName(v.type());
393 case QVariant::String
:
394 ret
= QScriptValue(scriptEngine(), v
.toString());
397 ret
= QScriptValue(scriptEngine(), v
.toBool());
400 ret
= QScriptValue(scriptEngine(), v
.toInt());
403 ret
= QScriptValue(scriptEngine(), v
.toUInt());
405 case QVariant::Double
:
406 //qfInfo() << "double:" << v.toDouble();
407 ret
= QScriptValue(scriptEngine(), v
.toDouble());
411 case QVariant::DateTime
:
412 ret
= scriptEngine()->newDate(v
.toDateTime());
416 ret
= scriptEngine()->newArray();
418 foreach(QVariant v1
, v
.toList()) {
419 ret
.setProperty(ix
++, variantToScriptValue(v1
));
425 ret
= scriptEngine()->newObject();
426 //qfInfo() << "map" << ret.toString();
427 QMapIterator
<QString
, QVariant
> it(v
.toMap());
428 while (it
.hasNext()) {
430 QString key
= it
.key();
431 QVariant val
= it
.value();
432 ret
.setProperty(key
, variantToScriptValue(val
));
437 if(v
.isNull()) ret
= scriptEngine()->nullValue();
438 else ret
= scriptEngine()->newVariant(v
);
443 QVariant
QFScriptDriver::scriptValueToVariant(const QScriptValue
& sv
)
445 qfLogFuncFrame() << "sv:" << sv
.toString() << "__qfTypeName:" << sv
.property("__qfTypeName").toString();
448 if(sv
.property("__qfTypeName").toString() == "qf.sql.ResultSet") {
449 QFXmlTableDocument doc
;
450 QFXmlTable xt
= doc
.toTable();
452 QScriptValue flds
= sv
.property("fields");
453 QScriptValueIterator
it(flds
);
454 while (it
.hasNext()) {
456 //qfInfo() << it.name() << ": " << it.value().toString();
457 QScriptValue fld
= it
.value();
458 QByteArray ba
= fld
.property("type").toString().toAscii();
459 xt
.appendColumn(fld
.property("name").toString(), QVariant::nameToType(ba
.constData()));
463 QScriptValue rows
= sv
.property("rows");
464 QScriptValueIterator
it(rows
);
465 while (it
.hasNext()) {
467 QScriptValue row
= it
.value();
468 QFXmlTableRow xr
= xt
.appendRow();
469 QScriptValueIterator
it2(row
.property("values"));
470 while (it2
.hasNext()) {
472 xr
.setValue(it2
.name().toInt(), it2
.value().toVariant());
477 //qfInfo() << scriptValueToJsonString(sv);
478 //qfInfo() << doc.toString();
481 ret
= sv
.toVariant();
485 qfTrash() << "\t isDate:" << sv
.isDate() << "toDate:" << sv
.toDateTime().toString();
486 ret
= sv
.toVariant();
488 qfTrash() << "\t return:" << ret
.toString() << "type:" << QVariant::typeToName(ret
.type());
492 QString
QFScriptDriver::scriptValueToJsonString(const QScriptValue
& sv
)
494 //qfLogFuncFrame() << sv.toString();
495 //static int limit = 0;
498 ret
= QFJson::variantToString(sv
.toString());
500 else if(sv
.isArray()) {
502 int len
= sv
.property("length").toInt32();
503 for(int i
=0; i
<len
; i
++) {
504 QScriptValue v
= sv
.property((quint32
)i
);
505 sl
<< scriptValueToJsonString(v
);
507 ret
= '[' + sl
.join(",") + ']';
509 else if(sv
.isObject()) {
511 QScriptValueIterator
it(sv
);
512 while(it
.hasNext()) {
514 QString k
= it
.name();
515 QScriptValue v
= it
.value();
517 if(k
== "prototype") {
519 //val_str = v.toString();
521 else if(k
== "stack") {
522 val_str
= "stackTrace";
525 if(sv
.isFunction()) {
526 val_str
= "function()";
529 //qfTrash() << "OBJECT key:" << k << "value:" << v.toString();
530 val_str
= scriptValueToJsonString(v
);
533 QString s
= k
+ ":" + val_str
;
536 ret
= '{' + sl
.join(",") + '}';
541 //qfTrash() << "\treturn:" << ret;
545 QString
QFScriptDriver::dumpContext()
548 QScriptContext
*ctx
= scriptEngine()->currentContext();
549 sl
<< "============ CONTEXT DUMP =============";
550 sl
<< "context addr: " + ((ctx
)? QString::number((long)ctx
, 16): "NULL");
554 QScriptContext
*ctx1
= ctx
->parentContext();
556 sl1
<< QString::number((long)ctx1
, 16);
557 ctx1
= ctx1
->parentContext();
559 sl
<< "parents: \n\t" + sl1
.join("\n\t");
561 sl
<< "engine addr: " + QString::number((long)ctx
->engine(), 16);
562 sl
<< "this object: " + ctx
->thisObject().toString();
563 sl
<< "callee: " + ctx
->callee().toString();
564 sl
<< "backtrace: \n\t" + ctx
->backtrace().join("\n\t");
566 return sl
.join("\n");
569 //=========================================================
571 //=========================================================
572 #ifdef QF_SCRIPT_DRIVER_CACHE_SCRIPT_CODES
573 QFSqlScriptDriver::ScriptCodeMap
QFSqlScriptDriver::scriptCodeMap
;
575 QFSqlScriptDriver::QFSqlScriptDriver(QObject
* parent
)
576 : QFScriptDriver(parent
)
578 f_scriptTableName
= "scripts";
579 f_keyFieldName
= "ckey";
580 f_codeFieldName
= "code";
583 QStringList
QFSqlScriptDriver::availableScriptNames(const QString
&path
)
585 static QString s_qs
= "SELECT ${KEY_FLDNAME} FROM ${SCRIPT_TBLNAME} %1 ORDER BY ${KEY_FLDNAME}";
588 QFSqlQuery
q(appConnection());
589 QString domain_filter
= path
.trimmed();
590 if(!domain_filter
.isEmpty()) {
591 domain_filter
= QString("WHERE ${KEY_FLDNAME} LIKE '%1.%'").arg(domain_filter
);
593 QString qs
= s_qs
.arg(domain_filter
);
594 qs
= correctNames(qs
);
598 ret
<< q
.value(0).toString();
599 //qfTrash() << "\t src from DB:" << src;
604 QString
QFSqlScriptDriver::loadScriptCode(const QString
& script_name
, QString
* found_file_name_ptr
)
606 qfLogFuncFrame() << script_name
;
609 #ifdef QF_SCRIPT_DRIVER_CACHE_SCRIPT_CODES
610 if(scriptCodeMap
.contains(script_name
)) {
611 src
= scriptCodeMap
.value(script_name
).code
;
612 found_fn
= script_name
;
617 QFSqlQuery
q(appConnection());
618 static const QString s_qs
= "SELECT ${CODE_FLDNAME} FROM ${SCRIPT_TBLNAME} WHERE ${KEY_FLDNAME}='%1'";
619 QString qs
= s_qs
.arg(script_name
);
620 qs
= correctNames(qs
);
624 src
= q
.value(0).toString();
625 //src = unescapeScriptCodeFromSQL(q.value(0).toString());
626 src
= resolveIncludes(src
, script_name
);
627 #ifdef QF_SCRIPT_DRIVER_CACHE_SCRIPT_CODES
628 scriptCodeMap
[script_name
] = ScriptCode(src
);
630 found_fn
= script_name
;
631 qfTrash() << "\t found";
634 if(found_fn
.isEmpty()) {
635 src
= QFScriptDriver::loadScriptCode(script_name
, &found_fn
);
636 #ifdef QF_SCRIPT_DRIVER_CACHE_SCRIPT_CODES
637 if(!found_fn
.isEmpty()) scriptCodeMap
[script_name
] = ScriptCode(src
);
640 if(found_file_name_ptr
) *found_file_name_ptr
= found_fn
;
645 QString
QFSqlScriptDriver::loadModuleObjectCode(const QString
& module_object_name
, QString
* found_file_name
)
647 qfLogFuncFrame() << "module_object_name:" << module_object_name
;
649 QString code
= QFSqlScriptDriver::loadScriptCode(module_object_name
, &ffn
);
651 code
= QFScriptDriver::loadModuleObjectCode(module_object_name
, &ffn
);
654 code
= replace_module_name(code
, module_object_name
);
656 if(found_file_name
) *found_file_name
= ffn
;
660 void QFSqlScriptDriver::saveScriptCode(const QString
& script_name
, const QString
& script_code
)
662 qfTrash() << QF_FUNC_NAME
<< script_name
;
664 qs
= "INSERT INTO ${SCRIPT_TBLNAME} (${KEY_FLDNAME}, ${CODE_FLDNAME})"
665 " VALUES('%1', '%2')"
666 " ON DUPLICATE KEY UPDATE ${CODE_FLDNAME} = VALUES(${CODE_FLDNAME})";
667 qs
= qs
.arg(script_name
).arg(script_code
);
668 qs
= correctNames(qs
);
669 QFSqlQuery
q(appConnection());
674 void QFSqlScriptDriver::deleteScriptCode(const QString
& script_name
)
676 qfTrash() << QF_FUNC_NAME
<< script_name
;
678 qs
= "DELETE FROM ${SCRIPT_TBLNAME}"
679 " WHERE ${KEY_FLDNAME} = '%1'";
680 qs
= qs
.arg(script_name
);
681 qs
= correctNames(qs
);
682 QFSqlQuery
q(appConnection());
687 QScriptValue
QFSqlScriptDriver::execSql(const QString
& query
)
689 qfLogFuncFrame() << "query:" << query
;
691 QFSqlQuery
q(appConnection());
694 QSqlRecord rec
= q
.record();
695 QScriptEngine
*eng
= scriptEngine();
696 QScriptValue fields
= eng
->newArray(rec
.count());
697 for(int i
=0; i
<rec
.count(); i
++) {
698 QSqlField fld
= rec
.field(i
);
699 QScriptValue field
= eng
->newObject();
700 field
.setProperty("name", QScriptValue(eng
, fld
.name()));
701 field
.setProperty("type", QScriptValue(eng
, QVariant::typeToName(fld
.type())));
702 fields
.setProperty((quint32
)i
, field
);
704 qfTrash() << "\t fields:" << scriptValueToJsonString(fields
);
705 qfTrash() << "\t looking for QFSqlResultSet, script engine:" << scriptEngine();
706 QScriptValue resultset_ctor
= evaluate("qf.require('qf.sql.ResultSet')");
707 //if(!ctor.isFunction()) { QF_EXCEPTION("QFSqlResultSet javascript initialization error."); }
708 //qfTrash() << ctor.toString();
709 if(!resultset_ctor
.isFunction()) { QF_EXCEPTION("qf.sql.Sql.ResultSet javascript initialization error."); }
711 //qfInfo() << "\t fields:" << scriptValueToJsonString(fields);
712 QScriptValueList ctor_params_for_fields
;
713 ctor_params_for_fields
<< fields
;
714 QScriptValue result_set
= resultset_ctor
.construct(ctor_params_for_fields
);
715 //qfInfo() << "\t result_set:" << scriptValueToJsonString(result_set);
716 QScriptValue fn_append_row
= result_set
.property("appendRow");
717 if(!fn_append_row
.isFunction()) { QF_EXCEPTION("qf.sql.ResultSet.appendRow() javascript lookup error."); }
718 QScriptValue sqlrow_ctor
= evaluate("qf.require('qf.sql.Row')");
719 //QScriptValue fn_set_value = ctor.property("setValue");
720 //if(!fn_set_value.isFunction()) { QF_EXCEPTION("SqlRow::setValue() javascript lookup error."); }
721 QScriptValueList set_value_args
;
722 set_value_args
<< QScriptValue() << QScriptValue();
723 //qfInfo() << "SqlRow:" << eng->evaluate("SqlRow.prototype.setValue").toString();
724 //qfInfo() << "SqlRow.prototype:" << scriptValueToJsonString(eng->evaluate("SqlRow.prototype"));
725 /// pozor QtScript funkce prototype() vraci jiny objekt (property __proto__) nez obj.prototype volany z Javascriptu
726 /// var o = new Object();
727 /// (o.__proto__ === Object.prototype); // this evaluates to true
728 /// presto tohle funguje
729 QScriptValue set_value
= eng
->evaluate("qf.sql.Row.prototype.setValue");
731 ///QScriptValue set_value = sqlrow_ctor.prototype().property("setValue");
733 ///QScriptValue set_value = sqlrow_ctor.property("__proto__").property("setValue");
734 //qfInfo() << "setValue:" << set_value.toString();
735 if(!set_value
.isFunction()) { QF_EXCEPTION("QFSqlRow::setValue() javascript lookup error."); }
737 QScriptValue row
= sqlrow_ctor
.construct(ctor_params_for_fields
);
739 ///QScriptValue set_value = row.property("setValue");
740 //if(!set_value.isFunction()) { QF_EXCEPTION("SqlRow::setValue() javascript lookup error."); }
741 for(int i
=0; i
<rec
.count(); i
++) {
742 QVariant val
= q
.value(i
);
743 set_value_args
[0] = QScriptValue(eng
, i
);
744 set_value_args
[1] = variantToScriptValue(val
);
745 //qfInfo() << "value:" << val.toString() << "type:" << QVariant::typeToName(val.type());
746 //set_value.call(row, set_value_args);
747 callFunction(set_value
, row
, set_value_args
);
749 //qfTrash() << "appendRow:" << scriptValueToJsonString(append_row) << append_row.toString();
750 //qfTrash() << "appending row:" << scriptValueToJsonString(row);
751 callFunction(fn_append_row
,result_set
, QScriptValueList() << row
);
755 //qfTrash() << "execSql ret:" << scriptValueToJsonString(ret);
759 QString
QFSqlScriptDriver::correctNames(const QString
& _s
)
762 s
.replace("${SCRIPT_TBLNAME}", scriptTableName());
763 s
.replace("${KEY_FLDNAME}", keyFieldName());
764 s
.replace("${CODE_FLDNAME}", codeFieldName());
768 void QFScriptDriver::resetEngine()
771 qfTrash().color(QFLog::Yellow
) << "deleting script engine";
772 SAFE_DELETE(f_scriptEngine
);
776 QScriptEngine
* QFSqlScriptDriver::scriptEngine()
778 return QFScriptDriver::scriptEngine();
780 if(!f_scriptEngine) {
781 QFScriptDriver::scriptEngine();
782 /// QFSqlResultSet nahraju hned, protoze nahravani ve funkci execSql(), sice funguje, ale je-li tato funkce volana ze skriptu, QFSqlResultSet stejne nezustane v namespace enginu.
783 evaluateScript("qfsql.js");
784 QScriptValue ctor = f_scriptEngine->evaluate("QFSqlResultSet");
785 if(!ctor.isFunction()) qfError() << "QFSqlResultSet javascript initialization error.";
787 return f_scriptEngine;
791 QFSqlConnection
& QFSqlScriptDriver::appConnection()
793 QCoreApplication
*core_app
= QCoreApplication::instance();
794 QFAppDbConnectionInterface
*ifc
= dynamic_cast<QFAppDbConnectionInterface
*>(core_app
); /// cross cast
795 if(ifc
) return ifc
->connection();
796 QF_EXCEPTION("No QFDbAppConfigInterface");
797 return QFAppDbConnectionInterface::dummyConnection();
800 QFSearchDirs
& QFScriptDriver::searchDirsRef()
802 static QFSearchDirs sd
;
803 if(sd
.dirs().isEmpty()) {
804 sd
.appendDir(QFFileUtils::joinPath(QFFileUtils::appDir(), "script"));
805 sd
.appendDir(":/libqfcore/script");
810 void QFScriptDriver::prependSearchDir(const QString
& dir
)
812 searchDirsRef().prependDir(dir
);