PageRenderTime 67ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/ggap/gscript/script.cpp

https://bitbucket.org/muntyan/ggap
C++ | 438 lines | 369 code | 52 blank | 17 comment | 33 complexity | 00fea52734953f2aa96d620bad6eed46 MD5 | raw file
Possible License(s): GPL-2.0, CC-BY-SA-3.0
  1. #include "gscript/script-p.h"
  2. #include "gscript/webwindow.h"
  3. #include "gscript/session.h"
  4. #include "gscript/canvas.h"
  5. #include "gscript/canvas-p.h"
  6. #include "gscript/canvasview.h"
  7. #include "gscript/form.h"
  8. #include "gscript/webview.h"
  9. #include "ggap/worksheet.h"
  10. #include "ggap/wswindow.h"
  11. #include <mws/worksheet.h>
  12. #include <mws/buffer.h>
  13. #include <mws/textblock.h>
  14. #include <moo/debug.h>
  15. #include <moo/macros.h>
  16. #include <moo/utils.h>
  17. #include <QtScript>
  18. #include <QDesktopServices>
  19. #include "gscript/gscript-types.h"
  20. using namespace gs;
  21. ScriptRunner::ScriptRunner(QObject *parent) :
  22. QObject(parent)
  23. {
  24. }
  25. ScriptRunner::~ScriptRunner()
  26. {
  27. }
  28. void ScriptRunner::setupEngine(QScriptEngine&, QScriptValue&)
  29. {
  30. }
  31. static void bindMethods(QScriptValue &global_obj, const QScriptValue &self)
  32. {
  33. QObject *obj = self.toQObject();
  34. const QMetaObject *meta = obj->metaObject();
  35. for (int i = 0; i < meta->methodCount(); ++i)
  36. {
  37. const QMetaMethod meth = meta->method(i);
  38. if (meth.access() == QMetaMethod::Public &&
  39. meth.methodType() == QMetaMethod::Method)
  40. {
  41. QString s = meth.signature();
  42. QString name = s.mid(0, s.indexOf('('));
  43. global_obj.setProperty(name, self.property(name));
  44. }
  45. }
  46. }
  47. bool ScriptRunner::runScript(const QString &script, const QString &filename, QString *error)
  48. {
  49. QScriptEngine engine;
  50. QScriptValue self = engine.newQObject(this);
  51. QScriptValue global_obj = engine.globalObject();
  52. bindMethods(global_obj, self);
  53. global_obj.setProperty("app", engine.newQObject(qApp));
  54. registerMetaTypes(&engine);
  55. QScriptValue val = engine.evaluate(moo::util::getFileText(":/script/scriptrunner.js"));
  56. if (val.isError())
  57. qCritical(":/script/scriptrunner.js: %s", qPrintable(val.toString()));
  58. setupEngine(engine, global_obj);
  59. QScriptValue ret = engine.evaluate(script, filename);
  60. mDebug("script") << "result:" << ret.toString();
  61. if (ret.isError())
  62. {
  63. qCritical("error in script: %s", qPrintable(ret.toString()));
  64. if (error)
  65. *error = ret.toString();
  66. }
  67. return !ret.isError();
  68. }
  69. bool ScriptRunner::runScript(const QString &script, QString *error)
  70. {
  71. mDebug("script") << "running script:" << script;
  72. return runScript(script, QString(), error);
  73. }
  74. bool ScriptRunner::runFile(const QString &filename, QString *error)
  75. {
  76. mDebug("script") << "running file:" << filename;
  77. QString errorHere;
  78. QString text = moo::util::getFileText(filename, &errorHere);
  79. if (!errorHere.isEmpty())
  80. {
  81. if (error)
  82. *error = QString("Could not read script file `%1': %2").arg(filename).arg(errorHere);
  83. return false;
  84. }
  85. return runScript(text, filename, error);
  86. }
  87. SessionScript::SessionScript(Session *session, QObject *parent) :
  88. ScriptRunner(parent),
  89. session(session)
  90. {
  91. }
  92. SessionScript::~SessionScript()
  93. {
  94. }
  95. void SessionScript::setupEngine(QScriptEngine &engine, QScriptValue &global_obj)
  96. {
  97. ScriptRunner::setupEngine(engine, global_obj);
  98. global_obj.setProperty("session", engine.newQObject(session));
  99. addScriptHelpers(engine, global_obj, session);
  100. }
  101. void gs::setObjectProperties(QObject *object, const QVariantMap &props)
  102. {
  103. m_return_if_fail(object != 0);
  104. for (QVariantMap::const_iterator i = props.begin(); i != props.end(); ++i)
  105. {
  106. if (!object->setProperty(qPrintable(i.key()), i.value()))
  107. qCritical() << "could not set property " << i.key();
  108. }
  109. }
  110. WorksheetScript::WorksheetScript(ggap::Worksheet *ws, Session *session, QObject *parent) :
  111. SessionScript(session, parent),
  112. ws(ws)
  113. {
  114. }
  115. WorksheetScript::~WorksheetScript()
  116. {
  117. }
  118. bool WorksheetScript::openUrl(const QString &url)
  119. {
  120. return QDesktopServices::openUrl(url);
  121. }
  122. void WorksheetScript::setupEngine(QScriptEngine &engine, QScriptValue &global_obj)
  123. {
  124. SessionScript::setupEngine(engine, global_obj);
  125. global_obj.setProperty("worksheet", engine.newQObject(ws));
  126. }
  127. //void WorksheetScript::embedObject(int id, const QVariantMap &params)
  128. //{
  129. // QObject *obj = session->objectById(id);
  130. // m_return_if_fail(obj != 0);
  131. //
  132. // QWidget *wid = 0;
  133. //
  134. // if (Viewable *v = dynamic_cast<Viewable*>(obj))
  135. // wid = v->createWidget();
  136. // else
  137. // wid = dynamic_cast<QWidget*>(obj);
  138. //
  139. // m_return_if_fail(wid != 0);
  140. // ws->embedWidget(wid, params);
  141. //}
  142. class GapConverter
  143. {
  144. public:
  145. GapConverter(Session *session)
  146. : _session(session)
  147. {
  148. }
  149. template<typename T>
  150. void serialize(const T &val, QTextStream &out);
  151. template<typename T>
  152. void serializeList(const QList<T> &list, QTextStream &out);
  153. private:
  154. Session *_session;
  155. };
  156. template<>
  157. void GapConverter::serialize(const QVariant &val, QTextStream &out);
  158. template<>
  159. void GapConverter::serialize(const QString &str, QTextStream &out);
  160. template<>
  161. void GapConverter::serialize(const QByteArray &ar, QTextStream &out)
  162. {
  163. out << '\"';
  164. foreach (unsigned ch, ar)
  165. {
  166. if (ch >= 32 && ch <= 126)
  167. {
  168. out << QChar(ch);
  169. }
  170. else
  171. {
  172. out << '\\';
  173. QString s = QString::number((unsigned) ch, 8);
  174. for (int i = 0; i < 3 - s.length(); ++i)
  175. out << '0';
  176. out << s;
  177. }
  178. }
  179. out << '\"';
  180. }
  181. template<>
  182. void GapConverter::serialize(QObject *const &obj, QTextStream &out)
  183. {
  184. if (!obj)
  185. {
  186. qCritical("oops");
  187. out << "GSNull";
  188. return;
  189. }
  190. int id = _session->wrapObject(obj);
  191. if (!id)
  192. {
  193. qCritical("oops");
  194. out << "GSNull";
  195. return;
  196. }
  197. out << "_GSWrapObject(" << id << ", ";
  198. serialize(QString(obj->metaObject()->className()), out);
  199. out << ")";
  200. }
  201. template<>
  202. void GapConverter::serialize(const QString &str, QTextStream &out)
  203. {
  204. serialize(str.toUtf8(), out);
  205. }
  206. template<>
  207. void GapConverter::serialize(const QChar &ch, QTextStream &out)
  208. {
  209. serialize(QString(ch), out);
  210. }
  211. template<>
  212. void GapConverter::serialize(const qlonglong &i, QTextStream &out)
  213. {
  214. out << i;
  215. }
  216. template<>
  217. void GapConverter::serialize(const qulonglong &u, QTextStream &out)
  218. {
  219. out << u;
  220. }
  221. template<>
  222. void GapConverter::serialize(const double &d, QTextStream &out)
  223. {
  224. if ((qlonglong) d == d)
  225. serialize((qlonglong) d, out);
  226. else if ((qulonglong) d == d)
  227. serialize((qulonglong) d, out);
  228. else
  229. {
  230. out << "Float(\"";
  231. out << d;
  232. out << "\")";
  233. }
  234. }
  235. template<typename T>
  236. void GapConverter::serializeList(const QList<T> &list, QTextStream &out)
  237. {
  238. out << "[";
  239. bool first = true;
  240. foreach (const T &elm, list)
  241. {
  242. if (!first)
  243. out << ", ";
  244. serialize(elm, out);
  245. first = false;
  246. }
  247. out << "]";
  248. }
  249. template<>
  250. void GapConverter::serialize(const QVariantList &list, QTextStream &out)
  251. {
  252. serializeList(list, out);
  253. }
  254. template<>
  255. void GapConverter::serialize(const QStringList &list, QTextStream &out)
  256. {
  257. serializeList(list, out);
  258. }
  259. template<>
  260. void GapConverter::serialize(const QVariantMap &map, QTextStream &out)
  261. {
  262. out << "rec(";
  263. for (QVariantMap::const_iterator iter = map.begin(); iter != map.end(); ++iter)
  264. {
  265. if (iter != map.begin())
  266. out << ", ";
  267. out << iter.key() << ":=";
  268. serialize(iter.value(), out);
  269. }
  270. out << ")";
  271. }
  272. template<>
  273. void GapConverter::serialize(const QSize &size, QTextStream &out)
  274. {
  275. out << "[" << size.width() << ", " << size.height() << "]";
  276. }
  277. template<>
  278. void GapConverter::serialize(const QSizeF &size, QTextStream &out)
  279. {
  280. out << "[";
  281. serialize(size.width(), out);
  282. out << ", ";
  283. serialize(size.height(), out);
  284. out << "]";
  285. }
  286. template<>
  287. void GapConverter::serialize(const QVariant &var, QTextStream &out)
  288. {
  289. switch (var.type())
  290. {
  291. default:
  292. qCritical() << "unknown variant type";
  293. out << "fail";
  294. break;
  295. case QMetaType::QObjectStar:
  296. serialize(var.value<QObject*>(), out);
  297. break;
  298. case QVariant::Invalid:
  299. out << "GSNull";
  300. break;
  301. case QVariant::Bool:
  302. out << (var.toBool() ? "true" : "false");
  303. break;
  304. case QVariant::ByteArray:
  305. serialize(var.toByteArray(), out);
  306. break;
  307. case QVariant::Char:
  308. serialize(var.toChar(), out);
  309. break;
  310. case QVariant::Double:
  311. serialize(var.toDouble(), out);
  312. break;
  313. case QVariant::Int:
  314. serialize((qlonglong) var.toInt(), out);
  315. break;
  316. case QVariant::List:
  317. serialize(var.toList(), out);
  318. break;
  319. case QVariant::LongLong:
  320. serialize(var.toLongLong(), out);
  321. break;
  322. case QVariant::Map:
  323. serialize(var.toMap(), out);
  324. break;
  325. case QVariant::String:
  326. serialize(var.toString(), out);
  327. break;
  328. case QVariant::StringList:
  329. serialize(var.toStringList(), out);
  330. break;
  331. case QVariant::UInt:
  332. serialize((qulonglong) var.toUInt(), out);
  333. break;
  334. case QVariant::ULongLong:
  335. serialize(var.toULongLong(), out);
  336. break;
  337. case QVariant::Url:
  338. serialize(var.toUrl().toString(), out);
  339. break;
  340. case QVariant::Size:
  341. serialize(var.toSize(), out);
  342. break;
  343. case QVariant::SizeF:
  344. serialize(var.toSizeF(), out);
  345. break;
  346. }
  347. }
  348. void SessionScript::postSignal(Session *session, int objId, const QString &signalName, int requestId, const QString &funcName, const QVariant &funcData)
  349. {
  350. QVariantList data;
  351. QVariantList sig_data_list;
  352. if (requestId)
  353. sig_data_list << requestId;
  354. sig_data_list << funcName << funcData;
  355. QVariant sig_data(sig_data_list);
  356. // ["signal", obj_id, signalName, [requestId, funcName, funcData]]
  357. data << "signal" << objId << signalName << sig_data;
  358. QString text;
  359. QTextStream out(&text);
  360. GapConverter(session).serialize(data, out);
  361. session->callGap(text);
  362. }
  363. void SessionScript::sendResult(int requestId, const QVariant &value)
  364. {
  365. QVariantList data;
  366. // ["response", requestId, value]
  367. data << "response" << requestId << value;
  368. QString text;
  369. QTextStream out(&text);
  370. GapConverter(session).serialize(data, out);
  371. session->callGap(text);
  372. }
  373. void gs::addScriptHelpers(QScriptEngine &engine, QScriptValue &globalObj, Session *session)
  374. {
  375. addScriptHelper<ScriptHelper_QWidget>(engine, globalObj, session, "_ggap_QWidget");
  376. addWebViewScriptHelpers(engine, globalObj, session);
  377. addCanvasScriptHelpers(engine, globalObj, session);
  378. addFormScriptHelpers(engine, globalObj, session);
  379. }
  380. void gs::setupInstance(QObject *obj, Session *session)
  381. {
  382. if (QWebView *view = dynamic_cast<QWebView*>(obj))
  383. setupWebView(view, session);
  384. else if (QWebPage *page = dynamic_cast<QWebPage*>(obj))
  385. setupWebPage(page, session);
  386. }