21#include "../core/action.h"
22#include "../core/manager.h"
23#include "../core/interpreter.h"
26#include <kjs/interpreter.h>
27#include <kjs/ustring.h>
28#include <kjs/object.h>
29#include <kjs/PropertyNameArray.h>
31#include <kjs/function_object.h>
34#include <kjsembed/kjsembed.h>
35#include <kjsembed/qobject_binding.h>
36#include <kjsembed/variant_binding.h>
37#include <kjsembed/slotproxy.h>
53 case KJS::Normal: type =
"Normal";
break;
54 case KJS::Break: type =
"Break";
break;
55 case KJS::Continue: type =
"Continue";
break;
56 case KJS::ReturnValue: type =
"ReturnValue";
break;
60 case KJS::Interrupted: type =
"Interrupted";
break;
61 default: type =
"Unknown";
break;
66 if( value && value->type() == KJS::ObjectType ) {
67 KJS::JSValue* linevalue = value->getObject()->get(exec,
"line");
68 if( linevalue && linevalue->type() == KJS::NumberType )
69 lineno = linevalue->toInt32(exec);
71 const QString
message = QString(
"%1%2: %3").arg( type ).arg((lineno >= 0) ? QString(
" line %1").arg(lineno) :
"").arg(value ? value->toString(exec).qstring() :
"NULL");
79 class KjsScriptPrivate
85 KJSEmbed::Engine* m_engine;
102 QStringList m_defaultFunctionNames;
112 QHashIterator< QString, ChildrenInterface::Options > it( children->
objectOptions() );
113 while(it.hasNext()) {
118 krossdebug( QString(
"KjsScript::addFunctions sender name=%1 className=%2").arg(sender->objectName()).arg(sender->metaObject()->className()) );
119 m_autoconnect.append( sender );
126 bool publishObject(KJS::ExecState* exec,
const QString &name,
QObject*
object)
130 KJS::JSObject* obj = m_engine->addObject(
object,
name.isEmpty() ? object->objectName() : name);
132 krosswarning( QString(
"Failed to publish the QObject name=\"%1\" objectName=\"%2\"").arg(name).arg(
object ? object->objectName() :
"NULL") );
135 m_publishedObjects << QPair<KJS::JSObject*, QPointer<QObject> >(obj, object);
163 :
Script(interpreter, action)
164 , d(new KjsScriptPrivate())
166 krossdebug( QString(
"KjsScript::KjsScript") );
170 d->addFunctions(
action );
175 krossdebug( QString(
"KjsScript::~KjsScript") );
180bool KjsScript::initialize()
186 krossdebug( QString(
"KjsScript::initialize") );
188 d->m_engine =
new KJSEmbed::Engine();
190 KJS::Interpreter* kjsinterpreter = d->m_engine->interpreter();
191 kjsinterpreter->setShouldPrintExceptions(
true);
192 KJS::ExecState* exec = kjsinterpreter->globalExec();
195 d->publishObject(exec,
"self",
action());
199 d->m_defaultFunctionNames <<
"Kross";
204 for(; it !=
end; ++it)
205 d->publishObject(exec, it.key(), it.value());
211 for(; it !=
end; ++it)
212 d->publishObject(exec, it.key(), it.value());
230void KjsScript::finalize()
232 KJS::Interpreter* kjsinterpreter = d->m_engine->interpreter();
233 KJS::ExecState* exec = kjsinterpreter->globalExec();
238 for(; it !=
end; ++it) {
253 foreach(
QObject* child, obj->children() )
254 if( KJSEmbed::SlotProxy* proxy =
dynamic_cast< KJSEmbed::SlotProxy*
>(child) )
263 d->m_publishedObjects.clear();
265 d->m_autoconnect.clear();
266 d->m_defaultFunctionNames.clear();
275 krosswarning( QString(
"KjsScript::execute aborted cause initialize failed.") );
280 if(code.startsWith(
"#!"))
281 code.remove(0, code.indexOf(
'\n'));
283 QTextCodec *codec = QTextCodec::codecForLocale();
284 KJS::UString c = codec ? KJS::UString(codec->toUnicode(code)) : KJS::UString(code.data(), code.size());
286 KJSEmbed::Engine::ExitStatus exitstatus = d->m_engine->execute(c);
288 KJS::Completion
completion = d->m_engine->completion();
289 KJS::Interpreter* kjsinterpreter = d->m_engine->interpreter();
290 KJS::ExecState* exec = kjsinterpreter->globalExec();
292 if(exitstatus != KJSEmbed::Engine::Success) {
298 KJS::JSObject* kjsglobal = kjsinterpreter->globalObject();
299 if( exec->hadException() ) {
307 foreach(
QObject*
object, d->m_autoconnect) {
308 const QMetaObject* metaobject =
object->metaObject();
309 const int count = metaobject->methodCount();
310 for(
int i = 0; i < count; ++i) {
311 QMetaMethod metamethod = metaobject->method(i);
312 if( metamethod.methodType() == QMetaMethod::Signal ) {
313 const QString signature = metamethod.signature();
314 const QByteArray
name = signature.left(signature.indexOf(
'(')).toLatin1();
315 krossdebug( QString(
"KjsScript::execute function=%1").arg(
name.data()) );
317 KJS::Identifier
id = KJS::Identifier( KJS::UString(
name.data()) );
318 KJS::JSValue *functionvalue = kjsglobal->get(exec,
id);
319 if( ! functionvalue->isObject() )
321 KJS::JSObject *function = functionvalue->toObject(exec);
322 Q_ASSERT( ! exec->hadException() );
323 if( exec->hadException() )
325 if ( function && function->implementsCall() ) {
326 krossdebug( QString(
"KjsScript::execute connect function=%1 with signal=%2").arg(
name.data()).arg(signature) );
328 QByteArray sendersignal = QString(
"2%1").arg(signature).toLatin1();
329 QByteArray receiverslot = QString(
"1%1").arg(signature).toLatin1();
330 KJSEmbed::SlotProxy* receiver =
new KJSEmbed::SlotProxy(kjsglobal, exec->dynamicInterpreter(),
object, signature.toLatin1());
332 if( connect(
object, sendersignal, receiver, receiverslot) ) {
333 krossdebug( QString(
"KjsScript::execute connected function=%1 with object=%2 signal=%3").arg(
name.data()).arg(object->objectName()).arg(signature) );
336 krosswarning( QString(
"KjsScript::execute failed to connect object=%1 signal=%2").arg(object->objectName()).arg(signature) );
348 KJS::Interpreter* kjsinterpreter = d->m_engine->interpreter();
349 KJS::ExecState* exec = kjsinterpreter->globalExec();
350 KJS::JSObject* kjsglobal = kjsinterpreter->globalObject();
351 if( exec->hadException() ) {
352 return QStringList();
355 KJS::PropertyNameArray props;
356 kjsglobal->getPropertyNames(exec, props);
359 for(KJS::PropertyNameArrayIterator it = props.begin(); it != props.end(); ++it) {
360 const char*
name = it->ascii();
361 KJS::Identifier
id = KJS::Identifier(
name);
362 KJS::JSValue *value = kjsglobal->get(exec,
id);
363 if( ! value || ! value->isObject() )
365 KJS::JSObject *obj = value->toObject(exec);
366 if( ! obj || ! obj->implementsCall() || ! obj->implementsConstruct() || ! obj->classInfo() )
368 if( d->m_defaultFunctionNames.contains(
name) )
373 Q_ASSERT( ! exec->hadException() );
381 KJS::Interpreter* kjsinterpreter = d->m_engine->interpreter();
382 KJS::ExecState* exec = kjsinterpreter->globalExec();
383 KJS::JSObject* kjsglobal = kjsinterpreter->globalObject();
384 if( exec->hadException() ) {
391 KJS::Identifier
id = KJS::Identifier( KJS::UString(
name.toLatin1().data()) );
392 KJS::JSValue *functionvalue = kjsglobal->get(exec,
id);
393 Q_ASSERT( ! exec->hadException() );
395 KJS::JSObject *function = functionvalue->toObject(exec);
396 if ( ! function || ! function->implementsCall() ) {
397 krossdebug(QString(
"KjsScript::callFunction(\"%1\") No such function").arg(
name));
403 foreach(
const QVariant &variant, args) {
404 if( qVariantCanConvert< QWidget* >(variant) ) {
405 if(
QWidget* widget = qvariant_cast< QWidget* >(variant) ) {
406 kjsargs.append( KJSEmbed::createQObject(exec, widget, KJSEmbed::ObjectBinding::QObjOwned) );
407 Q_ASSERT( ! exec->hadException() );
411 if( qVariantCanConvert< QObject* >(variant) ) {
412 if(
QObject* obj = qvariant_cast< QObject* >(variant) ) {
413 kjsargs.append( KJSEmbed::createQObject(exec, obj, KJSEmbed::ObjectBinding::QObjOwned) );
414 Q_ASSERT( ! exec->hadException() );
418 KJS::JSValue* jsvalue = KJSEmbed::convertToValue(exec, variant);
419 Q_ASSERT( ! exec->hadException() );
420 kjsargs.append( jsvalue );
423 KJS::JSValue *retValue = function->call(exec, kjsglobal, kjsargs);
424 if( exec->hadException() ) {
432 QVariant result = retValue ? KJSEmbed::convertToVariant(exec, retValue) : QVariant();
433 Q_ASSERT( ! exec->hadException() );
439 QTextCodec *codec = QTextCodec::codecForLocale();
440 KJS::UString c = codec ? KJS::UString(codec->toUnicode(code)) : KJS::UString(code.data(), code.size());
442 KJSEmbed::Engine::ExitStatus exitstatus = d->m_engine->execute(c);
444 KJS::Completion
completion = d->m_engine->completion();
445 KJS::Interpreter* kjsinterpreter = d->m_engine->interpreter();
446 KJS::ExecState* exec = kjsinterpreter->globalExec();
448 if(exitstatus != KJSEmbed::Engine::Success) {
455 QVariant result = retValue ? KJSEmbed::convertToVariant(exec, retValue) : QVariant();
456 Q_ASSERT( ! exec->hadException() );
The Action class is an abstract container to deal with scripts like a single standalone script file.
Interface for managing Object collections.
QHash< QString, Options > objectOptions() const
QObject * object(const QString &name) const
@ AutoConnectSignals
auto connect signals with scripting functions.
QHash< QString, QObject * > objects() const
Interface for error-handling.
const QString errorMessage() const
void setError(const QString &errormessage, const QString &tracemessage=QString(), long lineno=-1)
Set the error message.
void clearError()
Clear the error.
Base class for interpreter implementations.
virtual ~KjsScript()
Destructor.
virtual QStringList functionNames()
KjsScript(Kross::Interpreter *interpreter, Kross::Action *action)
Constructor.
virtual void execute()
Execute the script.
static Manager & self()
Return the Manager instance.
Base class for interpreter dependent functionality each script provides.
virtual QVariant callFunction(const QString &name, const QVariantList &args=QVariantList())=0
Call a function in the script.
virtual QVariant evaluate(const QByteArray &code)=0
Evaluate some scripting code.
void message(KMessage::MessageType messageType, const QString &text, const QString &caption=QString())
const char * name(StandardAction id)
const KShortcut & completion()
void krosswarning(const QString &s)
Warning function.
void krossdebug(const QString &s)
Debugging function.
static ErrorInterface extractError(const KJS::Completion &completion, KJS::ExecState *exec)
Extract an errormessage from a KJS::Completion object.