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

Kross

  • sources
  • kde-4.12
  • kdelibs
  • 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 
29 using namespace Kross;
30 
31 namespace 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 
167 EcmaScript::EcmaScript(Interpreter* interpreter, Action* action) : Script(interpreter, action), d(new Private(this))
168 {
169  //krossdebug( QString("EcmaScript::EcmaScript") );
170 }
171 
172 EcmaScript::~EcmaScript()
173 {
174  //krossdebug( QString("EcmaScript::~EcmaScript") );
175  delete d;
176 }
177 
178 void 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 
210 QStringList 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 
227 QVariant 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 
254 QVariant 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 
269 QObject* EcmaScript::engine() const
270 {
271  return d->m_engine;
272 }
273 
274 #include "script.moc"
QVariant
Kross::EcmaScript::functionNames
virtual QStringList functionNames()
Definition: qts/script.cpp:210
Kross::EcmaScript::execute
virtual void execute()
Executes the script.
Definition: qts/script.cpp:178
Kross::Script
Base class for interpreter dependent functionality each script provides.
Definition: core/script.h:43
kapplication.h
Kross::ChildrenInterface::objectOptions
QHash< QString, Options > objectOptions() const
Definition: childreninterface.h:118
Kross::EcmaScript::callFunction
virtual QVariant callFunction(const QString &name, const QVariantList &args=QVariantList())
Execute a function.
Definition: qts/script.cpp:227
name
const char * name(StandardAction id)
Kross::Action::file
QString file() const
Definition: action.cpp:351
QString
QHash< QString, QObject * >
QObject
Kross::Action::name
QString name() const
Definition: action.cpp:271
Kross::EcmaScript::engine
QObject * engine() const
Definition: qts/script.cpp:269
init
static void init(Action *th, const QString &name, int options=0)
Definition: action.cpp:105
Kross::ChildrenInterface::objects
QHash< QString, QObject * > objects() const
Definition: childreninterface.h:104
script.h
QStringList
Kross::ChildrenInterface
Interface for managing Object collections.
Definition: childreninterface.h:38
Kross::Action::code
QByteArray code() const
Definition: action.cpp:318
Kross::Interpreter
Base class for interpreter implementations.
Definition: core/interpreter.h:177
Kross::krosswarning
void krosswarning(const QString &s)
Warning function.
Definition: krossconfig.cpp:34
Kross::EcmaScript::~EcmaScript
virtual ~EcmaScript()
Destructor.
Definition: qts/script.cpp:172
Kross::EcmaScript::evaluate
virtual QVariant evaluate(const QByteArray &code)
Evaluate some scripting code.
Definition: qts/script.cpp:254
Kross::ChildrenInterface::object
QObject * object(const QString &name) const
Definition: childreninterface.h:97
Kross::ChildrenInterface::AutoConnectSignals
auto connect signals with scripting functions.
Definition: childreninterface.h:47
Kross::Manager::self
static Manager & self()
Return the Manager instance.
Definition: manager.cpp:73
Kross::ErrorInterface::setError
void setError(const QString &errormessage, const QString &tracemessage=QString(), long lineno=-1)
Set the error message.
Definition: errorinterface.h:69
Kross::Script::action
Action * action() const
Definition: core/script.cpp:61
Kross::Action
The Action class is an abstract container to deal with scripts like a single standalone script file...
Definition: action.h:94
Kross::EcmaScript
The EcmaScript class implements a Kross::Script to handle a single script.
Definition: qts/script.h:38
end
const KShortcut & end()
Kross::krossdebug
void krossdebug(const QString &s)
Debugging function.
Definition: krossconfig.cpp:28
Kross::EcmaScript::EcmaScript
EcmaScript(Kross::Interpreter *interpreter, Kross::Action *action)
Constructor.
Definition: qts/script.cpp:167
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:49:54 by doxygen 1.8.7 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 API Reference

Skip menu "kdelibs 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
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



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