Changeset View
Changeset View
Standalone View
Standalone View
templates/scriptabletags/scriptablenode.cpp
Show All 14 Lines | 1 | /* | |||
---|---|---|---|---|---|
15 | 15 | | |||
16 | You should have received a copy of the GNU Lesser General Public | 16 | You should have received a copy of the GNU Lesser General Public | ||
17 | License along with this library. If not, see <http://www.gnu.org/licenses/>. | 17 | License along with this library. If not, see <http://www.gnu.org/licenses/>. | ||
18 | 18 | | |||
19 | */ | 19 | */ | ||
20 | 20 | | |||
21 | #include "scriptablenode.h" | 21 | #include "scriptablenode.h" | ||
22 | 22 | | |||
23 | #include <QtScript/QScriptEngine> | 23 | #include <QtQml/QJSEngine> | ||
24 | 24 | | |||
25 | #include "context.h" | 25 | #include "context.h" | ||
26 | #include "engine.h" | 26 | #include "engine.h" | ||
27 | #include "exception.h" | 27 | #include "exception.h" | ||
28 | #include "parser.h" | 28 | #include "parser.h" | ||
29 | #include "scriptablecontext.h" | 29 | #include "scriptablecontext.h" | ||
30 | #include "scriptableparser.h" | 30 | #include "scriptableparser.h" | ||
31 | 31 | | |||
32 | QScriptValue nodeToScriptValue(QScriptEngine *engine, Node *const &node) | | |||
33 | { | | |||
34 | return engine->newQObject(node); | | |||
35 | } | | |||
36 | | ||||
37 | void nodeFromScriptValue(const QScriptValue &object, Node *&out) | | |||
38 | { | | |||
39 | out = qobject_cast<Node *>(object.toQObject()); | | |||
40 | } | | |||
41 | | ||||
42 | Q_SCRIPT_DECLARE_QMETAOBJECT(ScriptableNode, Node *) | | |||
43 | | ||||
44 | QScriptValue ScriptableNodeConstructor(QScriptContext *context, | | |||
45 | QScriptEngine *engine) | | |||
46 | { | | |||
47 | auto scriptableNodeName = context->argument(0).toString(); | | |||
48 | auto concreteNode = engine->globalObject().property(scriptableNodeName); | | |||
49 | | ||||
50 | QScriptValueList args; | | |||
51 | // First is the node type | | |||
52 | for (auto i = 1; i < context->argumentCount(); ++i) { | | |||
53 | args << context->argument(i); | | |||
54 | } | | |||
55 | | ||||
56 | concreteNode.call(concreteNode, args); | | |||
57 | | ||||
58 | auto renderMethod = concreteNode.property(QStringLiteral("render")); | | |||
59 | | ||||
60 | auto object = new ScriptableNode(engine); | | |||
61 | object->setObjectName(scriptableNodeName); | | |||
62 | object->setScriptEngine(engine); | | |||
63 | object->init(concreteNode, renderMethod); | | |||
64 | return engine->newQObject(object); | | |||
65 | } | | |||
66 | | ||||
67 | ScriptableNode::ScriptableNode(QObject *parent) | 32 | ScriptableNode::ScriptableNode(QObject *parent) | ||
68 | : Node(parent), m_scriptEngine(0) | 33 | : Node(parent), m_scriptEngine(0) | ||
69 | { | 34 | { | ||
70 | } | 35 | } | ||
71 | 36 | | |||
72 | void ScriptableNode::setScriptEngine(QScriptEngine *engine) | 37 | void ScriptableNode::setScriptEngine(QJSEngine *engine) | ||
73 | { | 38 | { | ||
74 | m_scriptEngine = engine; | 39 | m_scriptEngine = engine; | ||
75 | } | 40 | } | ||
76 | 41 | | |||
77 | void ScriptableNode::init(const QScriptValue &concreteNode, | 42 | void ScriptableNode::init(const QJSValue &concreteNode, | ||
78 | const QScriptValue &renderMethod) | 43 | const QJSValue &renderMethod) | ||
79 | { | 44 | { | ||
80 | m_concreteNode = concreteNode; | 45 | m_concreteNode = concreteNode; | ||
81 | m_renderMethod = renderMethod; | 46 | m_renderMethod = renderMethod; | ||
82 | } | 47 | } | ||
83 | 48 | | |||
84 | void ScriptableNode::render(OutputStream *stream, Context *c) const | 49 | void ScriptableNode::render(OutputStream *stream, Context *c) const | ||
85 | { | 50 | { | ||
86 | ScriptableContext sc(c); | 51 | ScriptableContext sc(c); | ||
87 | auto contextObject = m_scriptEngine->newQObject(&sc); | 52 | auto contextObject = m_scriptEngine->newQObject(&sc); | ||
88 | 53 | | |||
89 | QScriptValueList args; | 54 | QJSValueList args; | ||
90 | args << contextObject; | 55 | args << contextObject; | ||
91 | 56 | | |||
92 | // Call the render method in the context of the concreteNode | 57 | // Call the render method in the context of the concreteNode | ||
93 | auto value | 58 | auto value = const_cast<QJSValue &>(m_renderMethod).callWithInstance(m_concreteNode, args); | ||
94 | = const_cast<QScriptValue &>(m_renderMethod).call(m_concreteNode, args); | | |||
95 | 59 | | |||
96 | if (value.isValid() && !value.isUndefined()) | 60 | if (!value.isError() && !value.isUndefined()) | ||
97 | (*stream) << value.toString(); | 61 | (*stream) << value.toString(); | ||
62 | | ||||
63 | if (value.isError()) | ||||
64 | throw Grantlee::Exception(TagSyntaxError, value.toString()); | ||||
98 | } | 65 | } | ||
99 | 66 | | |||
100 | ScriptableNodeFactory::ScriptableNodeFactory(QObject *parent) | 67 | ScriptableNodeFactory::ScriptableNodeFactory(QObject *parent) | ||
101 | : AbstractNodeFactory(parent), m_scriptEngine(0) | 68 | : AbstractNodeFactory(parent), m_scriptEngine(0) | ||
102 | { | 69 | { | ||
103 | } | 70 | } | ||
104 | 71 | | |||
105 | void ScriptableNodeFactory::setScriptEngine(QScriptEngine *engine) | 72 | void ScriptableNodeFactory::setScriptEngine(QJSEngine *engine) | ||
106 | { | 73 | { | ||
107 | m_scriptEngine = engine; | 74 | m_scriptEngine = engine; | ||
108 | } | 75 | } | ||
109 | 76 | | |||
110 | void ScriptableNodeFactory::setEngine(Engine *engine) | 77 | void ScriptableNodeFactory::setEngine(Engine *engine) | ||
111 | { | 78 | { | ||
112 | m_scriptEngine->setProperty("templateEngine", QVariant::fromValue(engine)); | 79 | m_scriptEngine->setProperty("templateEngine", QVariant::fromValue(engine)); | ||
113 | } | 80 | } | ||
114 | 81 | | |||
115 | void ScriptableNodeFactory::setFactory(const QScriptValue &factoryMethod) | 82 | void ScriptableNodeFactory::setFactory(const QJSValue &factoryMethod) | ||
116 | { | 83 | { | ||
117 | m_factoryMethod = factoryMethod; | 84 | m_factoryMethod = factoryMethod; | ||
118 | } | 85 | } | ||
119 | 86 | | |||
120 | Node *ScriptableNodeFactory::getNode(const QString &tagContent, Parser *p) const | 87 | Node *ScriptableNodeFactory::getNode(const QString &tagContent, Parser *p) const | ||
121 | { | 88 | { | ||
122 | if (m_scriptEngine->hasUncaughtException()) { | | |||
123 | throw Grantlee::Exception(TagSyntaxError, | | |||
124 | m_scriptEngine->uncaughtExceptionBacktrace().join( | | |||
125 | QChar::fromLatin1(' '))); | | |||
126 | } | | |||
127 | auto sp = new ScriptableParser(p, m_scriptEngine); | 89 | auto sp = new ScriptableParser(p, m_scriptEngine); | ||
128 | auto parserObject = m_scriptEngine->newQObject(sp); | 90 | auto parserObject = m_scriptEngine->newQObject(sp); | ||
129 | 91 | | |||
130 | QScriptValueList args; | 92 | QJSValueList args; | ||
131 | args << tagContent; | 93 | args << tagContent; | ||
132 | args << parserObject; | 94 | args << parserObject; | ||
133 | 95 | | |||
134 | auto factory = m_factoryMethod; | 96 | auto factory = m_factoryMethod; | ||
135 | 97 | | |||
136 | auto scriptNode = factory.call(factory, args); | 98 | QJSValue scriptNode = factory.callWithInstance(factory, args); | ||
137 | if (m_scriptEngine->hasUncaughtException()) | 99 | if (scriptNode.isError()) | ||
138 | throw Grantlee::Exception(TagSyntaxError, | 100 | throw Grantlee::Exception(TagSyntaxError, scriptNode.toString()); | ||
139 | m_scriptEngine->uncaughtExceptionBacktrace().join( | | |||
140 | QChar::fromLatin1(' '))); | | |||
141 | 101 | | |||
142 | auto node = qscriptvalue_cast<Node *>(scriptNode); | 102 | auto node = qjsvalue_cast<Node *>(scriptNode); | ||
143 | node->setParent(p); | 103 | node->setParent(p); | ||
144 | return node; | 104 | return node; | ||
145 | } | 105 | } | ||
146 | 106 | | |||
147 | QScriptEngine *ScriptableNode::engine() { return m_scriptEngine; } | 107 | QJSEngine *ScriptableNode::engine() { return m_scriptEngine; } | ||
148 | 108 | | |||
149 | void ScriptableNode::setNodeList(const QString &name, | 109 | void ScriptableNode::setNodeList(const QString &name, | ||
150 | const QObjectList &objectList) | 110 | const QList<QObject *> &objectList) | ||
151 | { | 111 | { | ||
152 | auto objectListArray = m_scriptEngine->newArray(objectList.size()); | 112 | auto objectListArray = m_scriptEngine->newArray(objectList.size()); | ||
153 | 113 | | |||
154 | for (auto i = 0; i < objectList.size(); ++i) { | 114 | for (auto i = 0; i < objectList.size(); ++i) { | ||
155 | objectListArray.setProperty(i, | 115 | objectListArray.setProperty(i, | ||
156 | m_scriptEngine->newQObject(objectList.at(i))); | 116 | m_scriptEngine->newQObject(objectList.at(i))); | ||
157 | } | 117 | } | ||
158 | m_concreteNode.setProperty(name, objectListArray); | 118 | m_concreteNode.setProperty(name, objectListArray); | ||
159 | } | 119 | } |