25 #include <QtCore/QObject>
26 #include <QtCore/QArgument>
27 #include <QtCore/QMetaEnum>
28 #include <QtCore/QMetaType>
29 #include <QtCore/QVariant>
30 #include <QtCore/QVector>
31 #include <QtCore/QUrl>
32 #include <QtCore/QDebug>
41 #include <kjs/array_instance.h>
42 #include <kjs/function_object.h>
46 using namespace KJSEmbed;
58 bool validSlot(
const QMetaMethod& method, QObjectBinding::AccessFlags accessflags)
60 switch( method.access() ) {
61 case QMetaMethod::Private: {
64 case QMetaMethod::Protected: {
67 case QMetaMethod::Public: {
71 if(method.attributes() & QMetaMethod::Scriptable) {
80 bool validSignal(
const QMetaMethod& method, QObjectBinding::AccessFlags accessflags)
82 switch( method.access() ) {
83 case QMetaMethod::Private: {
86 case QMetaMethod::Protected: {
89 case QMetaMethod::Public: {
93 if(method.attributes() & QMetaMethod::Scriptable) {
102 bool validProperty(
const QMetaProperty& property, QObjectBinding::AccessFlags accessflags)
104 if(property.isScriptable()) {
117 imp = KJSEmbed::extractBindingImp<KJSEmbed::QObjectBinding>(exec, args[0] );
119 return KJS::throwError(exec, KJS::GeneralError, i18n(
"Wrong object type."));
127 return KJS::throwError(exec, KJS::GeneralError, i18n(
"First argument must be a QObject."));
132 QByteArray signal =
createSignal(args[1]->toString(exec).ascii());
135 if( args.size() >= 4)
137 slot =
createSlot(args[3]->toString(exec).ascii());
138 receiverImp = KJSEmbed::extractBindingImp<KJSEmbed::QObjectBinding>(exec, args[2] );
140 receiver =
new SlotProxy(args[2]->toObject(exec), exec->dynamicInterpreter(), sender, args[3]->toString(exec).ascii() );
148 slot =
createSlot(args[2]->toString(exec).ascii());
151 const QMetaObject *senderMetaObject = sender->metaObject();
152 QMetaMethod senderMetaMethod = senderMetaObject->method( senderMetaObject->indexOfSignal(signal.constData()) );
154 const QMetaObject *receiverMetaObject = receiver->metaObject();
155 QMetaMethod receiverMetaMethod = receiverMetaObject->method( receiverMetaObject->indexOfSlot(slot.constData()) );
159 return KJS::jsBoolean(QObject::connect(sender, signal.constData(), receiver, slot.constData()));
162 return KJS::jsBoolean(
false);
164 return KJS::throwError(exec, KJS::GeneralError, i18n(
"Incorrect number of arguments."));
170 QString sig = member.signature();
171 return sig.left( sig.indexOf(
'(') ).toLatin1();
184 QObjectList children =
object->children();
185 QObjectList::Iterator
child = children.begin();
186 for( ; child != children.end(); ++
child)
188 QString objectName = (*child)->objectName();
189 if( !objectName.isEmpty() )
196 target->put(exec, KJS::Identifier(
toUString(objectName)), childObject);
203 const QMetaObject *metaObject =
object->metaObject();
204 int methods = metaObject->methodCount();
207 QMetaMethod member = metaObject->method(
idx);
211 new SlotBinding(exec,member), KJS::DontDelete|KJS::ReadOnly|KJS::Function);
216 int enums = metaObject->enumeratorCount();
219 QMetaEnum enumerator = metaObject->enumerator(
idx);
220 int keys = enumerator.keyCount();
223 target->put(exec, KJS::Identifier( enumerator.key(
key) ),
224 KJS::jsNumber(enumerator.value(
key)), KJS::DontDelete|KJS::ReadOnly);
232 , m_access( AllSlots | AllSignals | AllProperties | AllObjects )
234 if( object->parent() != 0 )
243 m_cleanupHandler =
new QObjectCleanupHandler();
250 exec->dynamicInterpreter()->globalObject()->put(exec,
"connect",
new StaticBinding(exec, &QObjectFactory::methods()[0]) );
255 if( m_cleanupHandler->isEmpty() )
259 else if( object<QObject>()->
parent() != 0 )
262 m_cleanupHandler->remove(object<QObject>());
266 m_cleanupHandler->remove(object<QObject>());
270 m_cleanupHandler->remove(object<QObject>());
273 delete m_cleanupHandler;
278 m_cleanupHandler->add(
object );
284 QObject *obj = object<QObject>();
285 const QMetaObject *meta = obj->metaObject();
286 int propIndex = meta->indexOfProperty( propertyName.ascii() );
287 if ( propIndex != -1 ) {
294 return ObjectBinding::getOwnPropertySlot( exec, propertyName, slot );
298 const KJS::Identifier &propertyName,
const KJS::PropertySlot&slot )
304 QVariant
val = obj->property( propertyName.ascii() );
305 if ( val.isValid() ) {
308 qDebug() << QString(
"propertyGetter called but no property, name was '%1'").arg(propertyName.ascii());
324 QObject *obj = object<QObject>();
325 if ( obj && !m_cleanupHandler->isEmpty() )
328 const QMetaObject *meta = obj->metaObject();
330 if (
int propIndex = meta->indexOfProperty( propertyName.ascii() ) != -1 )
332 QMetaProperty prop = meta->property(propIndex);
336 bool propSet =
false;
338 if ( prop.isEnumType() )
340 propSet = obj->setProperty( propertyName.ascii(), val.toUInt() );
342 else if ( val.isValid() )
344 propSet = obj->setProperty( propertyName.ascii(),
val );
368 ObjectBinding::put(exec, propertyName, value, attr);
373 QObject *obj = object<QObject>();
374 if ( obj && !m_cleanupHandler->isEmpty() )
377 const QMetaObject *meta = obj->metaObject();
378 if (
int propIndex = meta->indexOfProperty( propertyName.ascii() ) != -1 )
380 QMetaProperty prop = meta->property(propIndex);
384 return ObjectBinding::canPut(exec,propertyName);
395 QString s(
"%1 (%2)" );
396 s = s.arg( object<QObject>()->objectName() );
405 if( types.size() == 0 && idx == 0 )
407 if ( args.size() <=
idx )
410 if ( types.size() <=
idx )
412 const QString firstPart = i18np(
"The slot asked for %1 argument",
"The slot asked for %1 arguments", idx);
413 const QString secondPart = i18np(
"but there is only %1 available",
"but there are only %1 available", types.size());
414 errorText = i18nc(
"%1 is 'the slot asked for foo arguments', %2 is 'but there are only bar available'",
"%1, %2.");
419 QVariant::Type varianttype = QVariant::nameToType( types[idx].constData() );
421 switch( varianttype ) {
423 if( args[idx]->type() == KJS::NumberType )
424 return new Value<int>( int( args[idx]->toInteger(exec) ) );
427 if( args[idx]->type() == KJS::NumberType )
428 return new Value<uint>( uint( args[idx]->toInteger(exec) ) );
430 case QVariant::LongLong:
431 if( args[idx]->type() == KJS::NumberType )
434 case QVariant::ULongLong:
435 if( args[idx]->type() == KJS::NumberType )
438 case QVariant::Double:
439 if( args[idx]->type() == KJS::NumberType )
445 if( args[idx]->type() == KJS::BooleanType )
446 return new Value<bool>( args[idx]->toBoolean(exec) );
448 case QVariant::ByteArray:
449 if( args[idx]->type() == KJS::StringType )
452 case QVariant::String:
453 if( args[idx]->type() == KJS::StringType )
456 case QVariant::StringList:
457 if( args[idx]->type() == KJS::ObjectType )
461 if(
VariantBinding *valImp = KJSEmbed::extractBindingImp<VariantBinding>(exec,args[idx]) )
462 return new Value<QSize>( valImp->variant().value<QSize>() );
464 case QVariant::SizeF:
465 if(
VariantBinding *valImp = KJSEmbed::extractBindingImp<VariantBinding>(exec,args[idx]) )
466 return new Value<QSizeF>( valImp->variant().value<QSizeF>() );
468 case QVariant::Point:
469 if(
VariantBinding *valImp = KJSEmbed::extractBindingImp<VariantBinding>(exec,args[idx]) )
470 return new Value<QPoint>( valImp->variant().value<QPoint>() );
472 case QVariant::PointF:
473 if(
VariantBinding *valImp = KJSEmbed::extractBindingImp<VariantBinding>(exec,args[idx]) )
477 if(
VariantBinding *valImp = KJSEmbed::extractBindingImp<VariantBinding>(exec,args[idx]) )
478 return new Value<QRect>( valImp->variant().value<QRect>() );
480 case QVariant::RectF:
481 if(
VariantBinding *valImp = KJSEmbed::extractBindingImp<VariantBinding>(exec,args[idx]) )
482 return new Value<QRectF>( valImp->variant().value<QRectF>() );
484 case QVariant::Color:
485 if( args[idx]->type() == KJS::StringType )
487 if(
VariantBinding *valImp = KJSEmbed::extractBindingImp<VariantBinding>(exec,args[idx]) )
488 return new Value<QColor>( valImp->variant().value<QColor>() );
491 if( args[idx]->type() == KJS::StringType )
493 if(
VariantBinding *valImp = KJSEmbed::extractBindingImp<VariantBinding>(exec,args[idx]) )
494 return new Value<QUrl>( valImp->variant().value<QUrl>() );
497 if( args[idx]->type() == KJS::ObjectType )
501 if( args[idx]->type() == KJS::ObjectType )
504 case QVariant::UserType:
506 if( args[idx]->type() == KJS::NullType )
508 if( args[idx]->type() == KJS::StringType )
510 if( strcmp(types[idx].constData(),
"KUrl") == 0 )
513 if( args[idx]->type() == KJS::ObjectType )
515 if(
QObjectBinding *objImp = KJSEmbed::extractBindingImp<QObjectBinding>(exec, args[idx]))
521 else if(
ObjectBinding *objImp = KJSEmbed::extractBindingImp<ObjectBinding>(exec, args[idx]))
526 if(
VariantBinding *valImp = KJSEmbed::extractBindingImp<VariantBinding>(exec,args[idx]))
529 QVariant var = valImp->variant();
532 if ((var.type() == varianttype) ||
533 ((var.type() == QVariant::UserType) &&
534 (types[idx].constData() == var.typeName())))
536 else if ((var.type() != QVariant::UserType) &&
537 var.canConvert(varianttype))
540 if (var.convert(varianttype))
543 else if ((var.type() == QVariant::UserType) &&
550 QByteArray typeName = types[
idx].constData();
551 typeName.replace(
"*",
"");
552 if (qObj->inherits(typeName))
566 qDebug(
"Cast failure %s value Type %d", types[idx].constData(), args[idx]->type() );
569 KJS::JSObject* jsObj = args[
idx]->getObject();
572 const KJS::ClassInfo* ci = jsObj->classInfo();
573 if (ci && ci->className)
574 jsType = ci->className;
575 if (jsType.isEmpty())
579 if (jsType.isEmpty())
581 switch(args[idx]->type())
583 case KJS::UnspecifiedType:
584 jsType =
"jsUnspecified";
586 case KJS::NumberType:
589 case KJS::BooleanType:
590 jsType =
"jsBoolean";
592 case KJS::UndefinedType:
593 jsType =
"jsUndefined";
598 case KJS::StringType:
601 case KJS::ObjectType:
604 case KJS::GetterSetterType:
605 jsType =
"jsGetterSetter";
608 jsType = QString::number(args[idx]->type());
613 errorText = i18n(
"Failure to cast to %1 value from Type %2 (%3)",
614 types[idx].constData(), jsType,
toQString(args[idx]->toString(exec)));
621 QObjectBinding *imp = extractBindingImp<QObjectBinding>(exec,
self);
623 return KJS::jsNull();
629 int count =
object->metaObject()->methodCount();
630 QMetaMethod metaMember;
633 for(; offset < count; ++offset)
635 metaMember =
object->metaObject()->method(offset);
638 if( metaMember.parameterTypes().size() == args.size() &&
validSlot(metaMember, imp->
access()) )
652 QList<QByteArray> types = metaMember.parameterTypes();
654 QVariant::Type returnTypeId = QVariant::nameToType( metaMember.typeName() );
655 int tp = QMetaType::type( metaMember.typeName() );
658 bool returnIsMetaType = (
659 returnTypeId == QVariant::UserType ||
660 returnTypeId == QVariant::Size || returnTypeId == QVariant::SizeF ||
661 returnTypeId == QVariant::Point || returnTypeId == QVariant::PointF ||
662 returnTypeId == QVariant::Rect || returnTypeId == QVariant::RectF ||
663 returnTypeId == QVariant::Color
665 QVariant returnValue = returnIsMetaType ? QVariant(tp, (
void*)0) : QVariant(returnTypeId);
666 QGenericReturnArgument returnArgument(metaMember.typeName(), &returnValue);
667 param[0] = returnIsMetaType ? qtRet->
voidStar() : returnArgument.data();
672 qtArgs[
idx] =
getArg(exec, types, args,
idx, errorText);
674 for(
int i = 0; i <
idx; ++i)
677 return KJS::throwError(exec, KJS::GeneralError, i18n(
"Call to method '%1' failed, unable to get argument %2: %3",
m_memberName.constData(),
idx, errorText));
682 success =
object->qt_metacall(QMetaObject::InvokeMetaMethod, offset, param) < 0;
684 KJS::JSValue *jsReturnValue = 0;
686 switch( returnTypeId ) {
687 case QVariant::Invalid:
688 case QVariant::UserType: {
690 case QMetaType::QWidgetStar: {
691 QVariant v(tp, param[0]);
696 case QMetaType::QObjectStar: {
697 QVariant v(tp,param[0]);
707 if( returnIsMetaType )
708 returnValue = QVariant(tp, param[0]);
722 return jsReturnValue;
726 : KJS::InternalFunctionImp(static_cast<KJS::FunctionPrototype*>(exec->lexicalInterpreter()->builtinFunctionPrototype()),
730 int count = member.parameterNames().count();
731 putDirect( exec->propertyNames().length, count,
LengthFlags );
738 return new KJS::JSObject();
740 const QMetaObject *meta = value->metaObject();
741 KJS::JSObject *
parent = exec->dynamicInterpreter()->globalObject();
742 KJS::JSObject *returnValue;
747 clazz = meta->className();
749 #ifdef CREATEQOBJ_DIAG
750 qDebug() <<
"clazz=" << clazz;
753 if ((pos = clazz.lastIndexOf(
"::")) != -1)
754 clazz.remove(0, pos + 2);
755 #ifdef CREATEQOBJ_DIAG
756 qDebug() <<
"cleaned clazz=" << clazz;
758 if ( parent->hasProperty( exec, KJS::Identifier(
toUString(clazz)) ) )
760 #ifdef CREATEQOBJ_DIAG
761 qDebug() <<
"createQObject(): clazz=" << clazz <<
" value=" <<
value;
768 #ifdef CREATEQOBJ_DIAG
769 qDebug(
"\tresort to construct() method.");
785 KJS::throwError(exec, KJS::TypeError, i18n(
"%1 is not an Object type", clazz ));
786 return new KJS::JSObject();
791 KJS::throwError(exec, KJS::TypeError, i18n(
"Could not construct value"));
792 return new KJS::JSObject();
798 #ifdef CREATEQOBJ_DIAG
799 qDebug(
"%s not a bound type, move up the chain", meta->className() );
801 meta = meta->superClass();
829 result = KJS::jsBoolean(
object->isWidgetType());
838 QObject *
parent = KJSEmbed::extractObject<QObject>(exec, args, 0, 0);
839 object->setParent(parent);
857 {
"connect", 4, KJS::DontDelete|KJS::ReadOnly, &
callConnect },
858 {
"parent", 0, KJS::DontDelete|KJS::ReadOnly, &callParent },
859 {
"inherits", 1, KJS::DontDelete|KJS::ReadOnly, &callInherits },
860 {
"isWidgetType", 0, KJS::DontDelete|KJS::ReadOnly, &callIsWidgetType },
861 {
"setParent", 1, KJS::DontDelete|KJS::ReadOnly, &callSetParent },
862 {
"findChild", 1, KJS::DontDelete|KJS::ReadOnly, &callFindChild }