• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

Kross

  • kross
  • qts
qts/script.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * script.cpp
3 * This file is part of the KDE project
4 * copyright (C)2007-2008 by Sebastian Sauer (mail@dipe.org)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public License
15 * along with this program; see the file COPYING. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 ***************************************************************************/
19
20#include "script.h"
21
22#include <QMetaObject>
23#include <QMetaMethod>
24#include <QScriptEngine>
25#include <QScriptValueIterator>
26
27#include <kapplication.h>
28
29using namespace Kross;
30
31namespace Kross {
32
34 class EcmaScript::Private
35 {
36 public:
37 EcmaScript* m_script;
38 QScriptEngine* m_engine;
39 QScriptValue m_kross;
40 QScriptValue m_self;
41
42 explicit Private(EcmaScript* script) : m_script(script), m_engine(0) {}
43 ~Private() { delete m_engine; }
44
45 bool init() {
46 if( m_script->action()->hadError() )
47 m_script->action()->clearError();
48
49 delete m_engine;
50 m_engine = new QScriptEngine();
51 m_engine->installTranslatorFunctions();
52
53 // load the Kross QScriptExtensionPlugin plugin that provides
54 // us a bridge between Kross and QtScript. See here plugin.h
55 m_engine->importExtension("kross");
56 if( m_engine->hasUncaughtException() ) {
57 handleException();
58 delete m_engine;
59 m_engine = 0;
60 return false;
61 }
62
63 // the Kross QScriptExtensionPlugin exports the "Kross" property.
64 QScriptValue global = m_engine->globalObject();
65 m_kross = global.property("Kross");
66 Q_ASSERT( m_kross.isQObject() );
67 Q_ASSERT( ! m_engine->hasUncaughtException() );
68
69 // Attach our Kross::Action instance to be able to access it in
70 // scripts. Just like at the Kjs-backend we publish our own
71 // action as "self".
72 m_self = m_engine->newQObject( m_script->action() );
73 global.setProperty("self", m_self, QScriptValue::ReadOnly|QScriptValue::Undeletable);
74
75 { // publish the global objects.
76 QHash< QString, QObject* > objects = Manager::self().objects();
77 QHash< QString, QObject* >::Iterator it(objects.begin()), end(objects.end());
78 for(; it != end; ++it)
79 global.setProperty(it.key(), m_engine->newQObject( it.value() ) );
80 }
81
82 { // publish the local objects.
83 QHash< QString, QObject* > objects = m_script->action()->objects();
84 QHash< QString, QObject* >::Iterator it(objects.begin()), end(objects.end());
85 for(; it != end; ++it) {
86 copyEnumsToProperties( it.value() );
87 global.setProperty(it.key(), m_engine->newQObject( it.value() ) );
88 }
89 }
90
91 return ! m_engine->hasUncaughtException();
92 }
93
94 void copyEnumsToProperties(QObject* object) {
95 const QMetaObject* meta = object->metaObject();
96 for (int i = 0; i < meta->enumeratorCount(); ++i) {
97 QMetaEnum metaenum = meta->enumerator(i);
98 for (int j = 0; j < metaenum.keyCount(); ++j) {
99 object->setProperty(metaenum.key(j), metaenum.value(j));
100 }
101 }
102 }
103
104 void handleException() {
105 Q_ASSERT( m_engine );
106 Q_ASSERT( m_engine->hasUncaughtException() );
107 const QString err = m_engine->uncaughtException().toString();
108 const int linenr = m_engine->uncaughtExceptionLineNumber();
109 const QString trace = m_engine->uncaughtExceptionBacktrace().join("\n");
110 krossdebug( QString("%1, line:%2, backtrace:\n%3").arg(err).arg(linenr).arg(trace) );
111 m_script->action()->setError(err, trace, linenr);
112 m_engine->clearExceptions();
113 }
114
115 void addObject(QObject* object, const QString& name = QString()) {
116 Q_ASSERT( m_engine );
117 Q_ASSERT( ! m_engine->hasUncaughtException() );
118 QScriptValue global = m_engine->globalObject();
119 QScriptValue value = m_engine->newQObject(object);
120 global.setProperty(name.isEmpty() ? object->objectName() : name, value);
121 }
122
123 void connectFunctions(ChildrenInterface* children) {
124 Q_ASSERT( m_engine );
125 Q_ASSERT( ! m_engine->hasUncaughtException() );
126 QString eval;
127 QScriptValue global = m_engine->globalObject();
128 QHashIterator< QString, ChildrenInterface::Options > it( children->objectOptions() );
129 while(it.hasNext()) {
130 it.next();
131 if( it.value() & ChildrenInterface::AutoConnectSignals ) {
132 QObject* sender = children->object(it.key());
133 if( ! sender )
134 continue;
135 QScriptValue obj = m_engine->globalObject().property(it.key());
136 if( ! obj.isQObject() )
137 continue;
138 const QMetaObject* mo = sender->metaObject();
139 const int count = mo->methodCount();
140 for(int i = 0; i < count; ++i) {
141 QMetaMethod mm = mo->method(i);
142 const QString signature = mm.signature();
143 const QString name = signature.left(signature.indexOf('('));
144 if( mm.methodType() == QMetaMethod::Signal ) {
145 QScriptValue func = global.property(name);
146 if( ! func.isFunction() ) {
147 //krossdebug( QString("EcmaScript::connectFunctions No function to connect with %1.%2").arg(it.key()).arg(name) );
148 continue;
149 }
150 krossdebug( QString("EcmaScript::connectFunctions Connecting with %1.%2").arg(it.key()).arg(name) );
151 eval += QString("try { %1.%2.connect(%3); } catch(e) { print(e); }\n").arg(it.key()).arg(name).arg(name);
152 }
153 }
154 }
155 }
156 Q_ASSERT( ! m_engine->hasUncaughtException() );
157 if( ! eval.isNull() ) {
158 m_engine->evaluate(eval);
159 Q_ASSERT( ! m_engine->hasUncaughtException() );
160 }
161 }
162
163 };
164
165}
166
167EcmaScript::EcmaScript(Interpreter* interpreter, Action* action) : Script(interpreter, action), d(new Private(this))
168{
169 //krossdebug( QString("EcmaScript::EcmaScript") );
170}
171
172EcmaScript::~EcmaScript()
173{
174 //krossdebug( QString("EcmaScript::~EcmaScript") );
175 delete d;
176}
177
178void EcmaScript::execute()
179{
180 if( ! d->init() ) {
181 d->handleException();
182 return;
183 }
184
185 QString scriptCode = action()->code();
186 if( scriptCode.startsWith(QLatin1String("#!")) ) // remove optional shebang-line
187 scriptCode.remove(0, scriptCode.indexOf('\n'));
188
189 const QString fileName = action()->file().isEmpty() ? action()->name() : action()->file();
190
191 //krossdebug( QString("EcmaScript::execute fileName=%1 scriptCode=\n%2").arg(fileName).arg(scriptCode) );
192
193 Q_ASSERT( d->m_engine );
194
195 if( d->m_engine->hasUncaughtException() ) {
196 d->m_engine->clearExceptions();
197 }
198
199 d->m_engine->evaluate( scriptCode, fileName );
200
201 if( d->m_engine->hasUncaughtException() ) {
202 d->handleException();
203 return;
204 }
205
206 //d->connectFunctions( &Manager::self() );
207 d->connectFunctions( action() );
208}
209
210QStringList EcmaScript::functionNames()
211{
212 if( ! d->m_engine && ! d->init() ) {
213 d->handleException();
214 return QStringList();
215 }
216 QStringList names;
217 QScriptValueIterator it( d->m_engine->globalObject() );
218 while( it.hasNext() ) {
219 it.next();
220 if( it.value().isFunction() ) {
221 names << it.name();
222 }
223 }
224 return names;
225}
226
227QVariant EcmaScript::callFunction(const QString& name, const QVariantList& args)
228{
229 if( ! d->m_engine && ! d->init() ) {
230 d->handleException();
231 return QVariant();
232 }
233
234 QScriptValue obj = d->m_engine->globalObject();
235 QScriptValue function = obj.property(name);
236 if( ! function.isFunction() ) {
237 QString err = QString("No such function '%1'").arg(name);
238 krosswarning( QString("EcmaScript::callFunction %1").arg(err) );
239 setError(err);
240 return QVariant();
241 }
242
243 QScriptValueList arguments;
244 foreach(const QVariant &v, args)
245 arguments << d->m_engine->toScriptValue(v);
246 QScriptValue result = function.call(obj, arguments);
247 if( d->m_engine->hasUncaughtException() ) {
248 d->handleException();
249 return QVariant();
250 }
251 return result.toVariant();
252}
253
254QVariant EcmaScript::evaluate(const QByteArray& code)
255{
256 if( ! d->m_engine && ! d->init() ) {
257 d->handleException();
258 return QVariant();
259 }
260
261 QScriptValue result = d->m_engine->evaluate(code);
262 if( d->m_engine->hasUncaughtException() ) {
263 d->handleException();
264 return QVariant();
265 }
266 return result.toVariant();
267}
268
269QObject* EcmaScript::engine() const
270{
271 return d->m_engine;
272}
273
274#include "script.moc"
Kross::Action
The Action class is an abstract container to deal with scripts like a single standalone script file.
Definition: action.h:99
Kross::Action::name
QString name() const
Kross::Action::code
QByteArray code() const
Definition: action.cpp:318
Kross::Action::file
QString file() const
Definition: action.cpp:351
Kross::ChildrenInterface
Interface for managing Object collections.
Definition: childreninterface.h:39
Kross::ChildrenInterface::objectOptions
QHash< QString, Options > objectOptions() const
Definition: childreninterface.h:118
Kross::ChildrenInterface::object
QObject * object(const QString &name) const
Definition: childreninterface.h:97
Kross::ChildrenInterface::AutoConnectSignals
@ AutoConnectSignals
auto connect signals with scripting functions.
Definition: childreninterface.h:47
Kross::ChildrenInterface::objects
QHash< QString, QObject * > objects() const
Definition: childreninterface.h:104
Kross::EcmaScript
The EcmaScript class implements a Kross::Script to handle a single script.
Definition: qts/script.h:39
Kross::EcmaScript::engine
QObject * engine() const
Definition: qts/script.cpp:269
Kross::EcmaScript::EcmaScript
EcmaScript(Kross::Interpreter *interpreter, Kross::Action *action)
Constructor.
Definition: qts/script.cpp:167
Kross::EcmaScript::evaluate
virtual QVariant evaluate(const QByteArray &code)
Evaluate some scripting code.
Definition: qts/script.cpp:254
Kross::EcmaScript::callFunction
virtual QVariant callFunction(const QString &name, const QVariantList &args=QVariantList())
Execute a function.
Definition: qts/script.cpp:227
Kross::EcmaScript::execute
virtual void execute()
Executes the script.
Definition: qts/script.cpp:178
Kross::EcmaScript::functionNames
virtual QStringList functionNames()
Definition: qts/script.cpp:210
Kross::EcmaScript::~EcmaScript
virtual ~EcmaScript()
Destructor.
Definition: qts/script.cpp:172
Kross::ErrorInterface::setError
void setError(const QString &errormessage, const QString &tracemessage=QString(), long lineno=-1)
Set the error message.
Definition: errorinterface.h:69
Kross::ErrorInterface::clearError
void clearError()
Clear the error.
Definition: errorinterface.h:88
Kross::ErrorInterface::hadError
bool hadError() const
Definition: errorinterface.h:48
Kross::Interpreter
Base class for interpreter implementations.
Definition: core/interpreter.h:178
Kross::Manager::self
static Manager & self()
Return the Manager instance.
Definition: manager.cpp:73
Kross::Script
Base class for interpreter dependent functionality each script provides.
Definition: core/script.h:44
Kross::Script::action
Action * action() const
Definition: core/script.cpp:61
QHash
QObject
kapplication.h
name
const char * name(StandardAction id)
end
const KShortcut & end()
Kross
Definition: action.cpp:36
Kross::krosswarning
void krosswarning(const QString &s)
Warning function.
Definition: krossconfig.cpp:34
Kross::krossdebug
void krossdebug(const QString &s)
Debugging function.
Definition: krossconfig.cpp:28
script.h
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

Kross

Skip menu "Kross"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal