/ggap/gscript/script.cpp
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
- #include "gscript/script-p.h"
- #include "gscript/webwindow.h"
- #include "gscript/session.h"
- #include "gscript/canvas.h"
- #include "gscript/canvas-p.h"
- #include "gscript/canvasview.h"
- #include "gscript/form.h"
- #include "gscript/webview.h"
- #include "ggap/worksheet.h"
- #include "ggap/wswindow.h"
- #include <mws/worksheet.h>
- #include <mws/buffer.h>
- #include <mws/textblock.h>
- #include <moo/debug.h>
- #include <moo/macros.h>
- #include <moo/utils.h>
- #include <QtScript>
- #include <QDesktopServices>
- #include "gscript/gscript-types.h"
- using namespace gs;
- ScriptRunner::ScriptRunner(QObject *parent) :
- QObject(parent)
- {
- }
- ScriptRunner::~ScriptRunner()
- {
- }
- void ScriptRunner::setupEngine(QScriptEngine&, QScriptValue&)
- {
- }
- static void bindMethods(QScriptValue &global_obj, const QScriptValue &self)
- {
- QObject *obj = self.toQObject();
- const QMetaObject *meta = obj->metaObject();
- for (int i = 0; i < meta->methodCount(); ++i)
- {
- const QMetaMethod meth = meta->method(i);
- if (meth.access() == QMetaMethod::Public &&
- meth.methodType() == QMetaMethod::Method)
- {
- QString s = meth.signature();
- QString name = s.mid(0, s.indexOf('('));
- global_obj.setProperty(name, self.property(name));
- }
- }
- }
- bool ScriptRunner::runScript(const QString &script, const QString &filename, QString *error)
- {
- QScriptEngine engine;
- QScriptValue self = engine.newQObject(this);
- QScriptValue global_obj = engine.globalObject();
- bindMethods(global_obj, self);
- global_obj.setProperty("app", engine.newQObject(qApp));
- registerMetaTypes(&engine);
- QScriptValue val = engine.evaluate(moo::util::getFileText(":/script/scriptrunner.js"));
- if (val.isError())
- qCritical(":/script/scriptrunner.js: %s", qPrintable(val.toString()));
- setupEngine(engine, global_obj);
- QScriptValue ret = engine.evaluate(script, filename);
- mDebug("script") << "result:" << ret.toString();
- if (ret.isError())
- {
- qCritical("error in script: %s", qPrintable(ret.toString()));
- if (error)
- *error = ret.toString();
- }
- return !ret.isError();
- }
- bool ScriptRunner::runScript(const QString &script, QString *error)
- {
- mDebug("script") << "running script:" << script;
- return runScript(script, QString(), error);
- }
- bool ScriptRunner::runFile(const QString &filename, QString *error)
- {
- mDebug("script") << "running file:" << filename;
- QString errorHere;
- QString text = moo::util::getFileText(filename, &errorHere);
- if (!errorHere.isEmpty())
- {
- if (error)
- *error = QString("Could not read script file `%1': %2").arg(filename).arg(errorHere);
- return false;
- }
- return runScript(text, filename, error);
- }
- SessionScript::SessionScript(Session *session, QObject *parent) :
- ScriptRunner(parent),
- session(session)
- {
- }
- SessionScript::~SessionScript()
- {
- }
- void SessionScript::setupEngine(QScriptEngine &engine, QScriptValue &global_obj)
- {
- ScriptRunner::setupEngine(engine, global_obj);
- global_obj.setProperty("session", engine.newQObject(session));
- addScriptHelpers(engine, global_obj, session);
- }
- void gs::setObjectProperties(QObject *object, const QVariantMap &props)
- {
- m_return_if_fail(object != 0);
- for (QVariantMap::const_iterator i = props.begin(); i != props.end(); ++i)
- {
- if (!object->setProperty(qPrintable(i.key()), i.value()))
- qCritical() << "could not set property " << i.key();
- }
- }
- WorksheetScript::WorksheetScript(ggap::Worksheet *ws, Session *session, QObject *parent) :
- SessionScript(session, parent),
- ws(ws)
- {
- }
- WorksheetScript::~WorksheetScript()
- {
- }
- bool WorksheetScript::openUrl(const QString &url)
- {
- return QDesktopServices::openUrl(url);
- }
- void WorksheetScript::setupEngine(QScriptEngine &engine, QScriptValue &global_obj)
- {
- SessionScript::setupEngine(engine, global_obj);
- global_obj.setProperty("worksheet", engine.newQObject(ws));
- }
- //void WorksheetScript::embedObject(int id, const QVariantMap ¶ms)
- //{
- // QObject *obj = session->objectById(id);
- // m_return_if_fail(obj != 0);
- //
- // QWidget *wid = 0;
- //
- // if (Viewable *v = dynamic_cast<Viewable*>(obj))
- // wid = v->createWidget();
- // else
- // wid = dynamic_cast<QWidget*>(obj);
- //
- // m_return_if_fail(wid != 0);
- // ws->embedWidget(wid, params);
- //}
- class GapConverter
- {
- public:
- GapConverter(Session *session)
- : _session(session)
- {
- }
- template<typename T>
- void serialize(const T &val, QTextStream &out);
- template<typename T>
- void serializeList(const QList<T> &list, QTextStream &out);
- private:
- Session *_session;
- };
- template<>
- void GapConverter::serialize(const QVariant &val, QTextStream &out);
- template<>
- void GapConverter::serialize(const QString &str, QTextStream &out);
- template<>
- void GapConverter::serialize(const QByteArray &ar, QTextStream &out)
- {
- out << '\"';
- foreach (unsigned ch, ar)
- {
- if (ch >= 32 && ch <= 126)
- {
- out << QChar(ch);
- }
- else
- {
- out << '\\';
- QString s = QString::number((unsigned) ch, 8);
- for (int i = 0; i < 3 - s.length(); ++i)
- out << '0';
- out << s;
- }
- }
- out << '\"';
- }
- template<>
- void GapConverter::serialize(QObject *const &obj, QTextStream &out)
- {
- if (!obj)
- {
- qCritical("oops");
- out << "GSNull";
- return;
- }
- int id = _session->wrapObject(obj);
- if (!id)
- {
- qCritical("oops");
- out << "GSNull";
- return;
- }
- out << "_GSWrapObject(" << id << ", ";
- serialize(QString(obj->metaObject()->className()), out);
- out << ")";
- }
- template<>
- void GapConverter::serialize(const QString &str, QTextStream &out)
- {
- serialize(str.toUtf8(), out);
- }
- template<>
- void GapConverter::serialize(const QChar &ch, QTextStream &out)
- {
- serialize(QString(ch), out);
- }
- template<>
- void GapConverter::serialize(const qlonglong &i, QTextStream &out)
- {
- out << i;
- }
- template<>
- void GapConverter::serialize(const qulonglong &u, QTextStream &out)
- {
- out << u;
- }
- template<>
- void GapConverter::serialize(const double &d, QTextStream &out)
- {
- if ((qlonglong) d == d)
- serialize((qlonglong) d, out);
- else if ((qulonglong) d == d)
- serialize((qulonglong) d, out);
- else
- {
- out << "Float(\"";
- out << d;
- out << "\")";
- }
- }
- template<typename T>
- void GapConverter::serializeList(const QList<T> &list, QTextStream &out)
- {
- out << "[";
- bool first = true;
- foreach (const T &elm, list)
- {
- if (!first)
- out << ", ";
- serialize(elm, out);
- first = false;
- }
- out << "]";
- }
- template<>
- void GapConverter::serialize(const QVariantList &list, QTextStream &out)
- {
- serializeList(list, out);
- }
- template<>
- void GapConverter::serialize(const QStringList &list, QTextStream &out)
- {
- serializeList(list, out);
- }
- template<>
- void GapConverter::serialize(const QVariantMap &map, QTextStream &out)
- {
- out << "rec(";
- for (QVariantMap::const_iterator iter = map.begin(); iter != map.end(); ++iter)
- {
- if (iter != map.begin())
- out << ", ";
- out << iter.key() << ":=";
- serialize(iter.value(), out);
- }
- out << ")";
- }
- template<>
- void GapConverter::serialize(const QSize &size, QTextStream &out)
- {
- out << "[" << size.width() << ", " << size.height() << "]";
- }
- template<>
- void GapConverter::serialize(const QSizeF &size, QTextStream &out)
- {
- out << "[";
- serialize(size.width(), out);
- out << ", ";
- serialize(size.height(), out);
- out << "]";
- }
- template<>
- void GapConverter::serialize(const QVariant &var, QTextStream &out)
- {
- switch (var.type())
- {
- default:
- qCritical() << "unknown variant type";
- out << "fail";
- break;
- case QMetaType::QObjectStar:
- serialize(var.value<QObject*>(), out);
- break;
- case QVariant::Invalid:
- out << "GSNull";
- break;
- case QVariant::Bool:
- out << (var.toBool() ? "true" : "false");
- break;
- case QVariant::ByteArray:
- serialize(var.toByteArray(), out);
- break;
- case QVariant::Char:
- serialize(var.toChar(), out);
- break;
- case QVariant::Double:
- serialize(var.toDouble(), out);
- break;
- case QVariant::Int:
- serialize((qlonglong) var.toInt(), out);
- break;
- case QVariant::List:
- serialize(var.toList(), out);
- break;
- case QVariant::LongLong:
- serialize(var.toLongLong(), out);
- break;
- case QVariant::Map:
- serialize(var.toMap(), out);
- break;
- case QVariant::String:
- serialize(var.toString(), out);
- break;
- case QVariant::StringList:
- serialize(var.toStringList(), out);
- break;
- case QVariant::UInt:
- serialize((qulonglong) var.toUInt(), out);
- break;
- case QVariant::ULongLong:
- serialize(var.toULongLong(), out);
- break;
- case QVariant::Url:
- serialize(var.toUrl().toString(), out);
- break;
- case QVariant::Size:
- serialize(var.toSize(), out);
- break;
- case QVariant::SizeF:
- serialize(var.toSizeF(), out);
- break;
- }
- }
- void SessionScript::postSignal(Session *session, int objId, const QString &signalName, int requestId, const QString &funcName, const QVariant &funcData)
- {
- QVariantList data;
- QVariantList sig_data_list;
- if (requestId)
- sig_data_list << requestId;
- sig_data_list << funcName << funcData;
- QVariant sig_data(sig_data_list);
- // ["signal", obj_id, signalName, [requestId, funcName, funcData]]
- data << "signal" << objId << signalName << sig_data;
- QString text;
- QTextStream out(&text);
- GapConverter(session).serialize(data, out);
- session->callGap(text);
- }
- void SessionScript::sendResult(int requestId, const QVariant &value)
- {
- QVariantList data;
- // ["response", requestId, value]
- data << "response" << requestId << value;
- QString text;
- QTextStream out(&text);
- GapConverter(session).serialize(data, out);
- session->callGap(text);
- }
- void gs::addScriptHelpers(QScriptEngine &engine, QScriptValue &globalObj, Session *session)
- {
- addScriptHelper<ScriptHelper_QWidget>(engine, globalObj, session, "_ggap_QWidget");
- addWebViewScriptHelpers(engine, globalObj, session);
- addCanvasScriptHelpers(engine, globalObj, session);
- addFormScriptHelpers(engine, globalObj, session);
- }
- void gs::setupInstance(QObject *obj, Session *session)
- {
- if (QWebView *view = dynamic_cast<QWebView*>(obj))
- setupWebView(view, session);
- else if (QWebPage *page = dynamic_cast<QWebPage*>(obj))
- setupWebPage(page, session);
- }