00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "qobject_binding.h"
00024
00025 #include <QtCore/QObject>
00026 #include <QtCore/QArgument>
00027 #include <QtCore/QMetaEnum>
00028 #include <QtCore/QMetaType>
00029 #include <QtCore/QVariant>
00030 #include <QtCore/QVector>
00031 #include <QtCore/QUrl>
00032 #include <QtCore/QDebug>
00033 #include <QWidget>
00034
00035 #include "slotproxy.h"
00036 #include "eventproxy.h"
00037 #include "jseventmapper.h"
00038 #include "pointer.h"
00039 #include "variant_binding.h"
00040
00041 #include <kjs/array_instance.h>
00042 #include <kjs/function_object.h>
00043
00044
00045
00046 using namespace KJSEmbed;
00047
00048 QByteArray createSignal( const QByteArray &sig )
00049 {
00050 return '2' + sig;
00051 }
00052
00053 QByteArray createSlot( const QByteArray &slt )
00054 {
00055 return '1' + slt;
00056 }
00057
00058 bool validSlot(const QMetaMethod& method, QObjectBinding::AccessFlags accessflags)
00059 {
00060 switch( method.access() ) {
00061 case QMetaMethod::Private: {
00062 if(! (accessflags & QObjectBinding::PrivateSlots)) return false;
00063 } break;
00064 case QMetaMethod::Protected: {
00065 if(! (accessflags & QObjectBinding::ProtectedSlots)) return false;
00066 } break;
00067 case QMetaMethod::Public: {
00068 if(! (accessflags & QObjectBinding::PublicSlots)) return false;
00069 } break;
00070 }
00071 if(method.attributes() & QMetaMethod::Scriptable) {
00072 if(! (accessflags & QObjectBinding::ScriptableSlots)) return false;
00073 }
00074 else {
00075 if(! (accessflags & QObjectBinding::NonScriptableSlots)) return false;
00076 }
00077 return true;
00078 }
00079
00080 bool validSignal(const QMetaMethod& method, QObjectBinding::AccessFlags accessflags)
00081 {
00082 switch( method.access() ) {
00083 case QMetaMethod::Private: {
00084 if(! (accessflags & QObjectBinding::PrivateSignals)) return false;
00085 } break;
00086 case QMetaMethod::Protected: {
00087 if(! (accessflags & QObjectBinding::ProtectedSignals)) return false;
00088 } break;
00089 case QMetaMethod::Public: {
00090 if(! (accessflags & QObjectBinding::PublicSignals)) return false;
00091 } break;
00092 }
00093 if(method.attributes() & QMetaMethod::Scriptable) {
00094 if(! (accessflags & QObjectBinding::ScriptableSignals)) return false;
00095 }
00096 else {
00097 if(! (accessflags & QObjectBinding::NonScriptableSignals)) return false;
00098 }
00099 return true;
00100 }
00101
00102 bool validProperty(const QMetaProperty& property, QObjectBinding::AccessFlags accessflags)
00103 {
00104 if(property.isScriptable()) {
00105 if(! (accessflags & QObjectBinding::ScriptableProperties)) return false;
00106 }
00107 else {
00108 if(! (accessflags & QObjectBinding::NonScriptableProperties)) return false;
00109 }
00110 return true;
00111 }
00112
00113 KJS::JSValue *callConnect( KJS::ExecState *exec, KJS::JSObject *self, const KJS::List &args )
00114 {
00115 KJSEmbed::QObjectBinding *imp = KJSEmbed::extractBindingImp<KJSEmbed::QObjectBinding>(exec, self );
00116 if( !imp )
00117 imp = KJSEmbed::extractBindingImp<KJSEmbed::QObjectBinding>(exec, args[0] );
00118 if( !imp )
00119 return KJS::throwError(exec, KJS::GeneralError, i18n("Wrong object type."));
00120
00121
00122 if( args.size() > 2)
00123 {
00124 KJSEmbed::QObjectBinding *senderImp = KJSEmbed::extractBindingImp<KJSEmbed::QObjectBinding>(exec, args[0] );
00125 if( !senderImp )
00126 {
00127 return KJS::throwError(exec, KJS::GeneralError, i18n("First argument must be a QObject."));
00128
00129 }
00130 QObject* receiver = 0;
00131 QObject* sender = senderImp->object<QObject>();
00132 char *signal = qstrdup( createSignal(args[1]->toString(exec).ascii()).data() );
00133 char *slot = 0;
00134 KJSEmbed::QObjectBinding *receiverImp = 0;
00135 if( args.size() >= 4)
00136 {
00137 slot = qstrdup( createSlot(args[3]->toString(exec).ascii()).data() );
00138 receiverImp = KJSEmbed::extractBindingImp<KJSEmbed::QObjectBinding>(exec, args[2] );
00139 if( !receiverImp )
00140 receiver = new SlotProxy(args[2]->toObject(exec), exec->dynamicInterpreter(), sender, args[3]->toString(exec).ascii() );
00141 else
00142 receiver = receiverImp->object<QObject>();
00143 }
00144 else
00145 {
00146 receiverImp = imp;
00147 receiver = imp->object<QObject>();
00148 slot = qstrdup( createSlot(args[2]->toString(exec).ascii()).data() );
00149 }
00150
00151 const QMetaObject *senderMetaObject = sender->metaObject();
00152 QMetaMethod senderMetaMethod = senderMetaObject->method( senderMetaObject->indexOfSignal(signal) );
00153
00154 const QMetaObject *receiverMetaObject = receiver->metaObject();
00155 QMetaMethod receiverMetaMethod = receiverMetaObject->method( receiverMetaObject->indexOfSlot(slot) );
00156
00157 if( validSignal(senderMetaMethod, senderImp->access()) && ( !receiverImp || validSlot(receiverMetaMethod, receiverImp->access()) ) )
00158 {
00159 return KJS::jsBoolean(QObject::connect(sender, signal, receiver, slot));
00160 }
00161
00162 return KJS::jsBoolean(false);
00163 }
00164 return KJS::throwError(exec, KJS::GeneralError, i18n("Incorrect number of arguments."));
00165
00166 }
00167
00168 QByteArray extractMemberName( const QMetaMethod &member )
00169 {
00170 QString sig = member.signature();
00171 return sig.left( sig.indexOf('(') ).toLatin1();
00172 }
00173
00174 void QObjectBinding::publishQObject( KJS::ExecState *exec, KJS::JSObject *target, QObject *object)
00175 {
00176 KJSEmbed::QObjectBinding *imp = KJSEmbed::extractBindingImp<KJSEmbed::QObjectBinding>(exec, target);
00177 Q_ASSERT(imp);
00178
00179
00180 if (imp->access() & QObjectBinding::ChildObjects) {
00181
00182
00183
00184 QObjectList children = object->children();
00185 QObjectList::Iterator child = children.begin();
00186 for( ; child != children.end(); ++child)
00187 {
00188 QString objectName = (*child)->objectName();
00189 if( !objectName.isEmpty() )
00190 {
00191 KJS::JSObject *childObject = KJSEmbed::createQObject(exec, *child);
00192 KJSEmbed::QObjectBinding *childImp = KJSEmbed::extractBindingImp<KJSEmbed::QObjectBinding>(exec, childObject);
00193 if(childImp)
00194 {
00195 childImp->setAccess( imp->access() );
00196 target->put(exec, KJS::Identifier(toUString(objectName)), childObject);
00197 }
00198 }
00199 }
00200 }
00201
00202
00203 const QMetaObject *metaObject = object->metaObject();
00204 int methods = metaObject->methodCount();
00205 for( int idx = 0; idx < methods; ++idx )
00206 {
00207 QMetaMethod member = metaObject->method(idx);
00208 if(validSlot(member, imp->access()))
00209 {
00210 target->put(exec, KJS::Identifier( extractMemberName( member ) ),
00211 new SlotBinding(exec,member), KJS::DontDelete|KJS::ReadOnly|KJS::Function);
00212 }
00213 }
00214
00215
00216 int enums = metaObject->enumeratorCount();
00217 for( int idx = 0; idx < enums; ++idx )
00218 {
00219 QMetaEnum enumerator = metaObject->enumerator(idx);
00220 int keys = enumerator.keyCount();
00221 for( int key = 0; key < keys; ++key)
00222 {
00223 target->put(exec, KJS::Identifier( enumerator.key(key) ),
00224 KJS::jsNumber(enumerator.value(key)), KJS::DontDelete|KJS::ReadOnly);
00225 }
00226 }
00227 }
00228
00229 QObjectBinding::QObjectBinding( KJS::ExecState *exec, QObject *object )
00230 : ObjectBinding(exec, object->metaObject()->className(), object)
00231 , m_evproxy(0)
00232 , m_access( AllSlots | AllSignals | AllProperties | AllObjects )
00233 {
00234 if( object->parent() != 0 )
00235 {
00236 setOwnership( ObjectBinding::QObjOwned );
00237 }
00238 else
00239 {
00240 setOwnership( ObjectBinding::JSOwned );
00241 }
00242
00243 m_cleanupHandler = new QObjectCleanupHandler();
00244 watchObject(object);
00245
00246 StaticBinding::publish( exec, this, QObjectFactory::methods() );
00247 QObjectBinding::publishQObject(exec, this, object);
00248
00249
00250 exec->dynamicInterpreter()->globalObject()->put(exec, "connect", new StaticBinding(exec, &QObjectFactory::methods()[0]) );
00251 }
00252
00253 QObjectBinding::~QObjectBinding()
00254 {
00255 if( m_cleanupHandler->isEmpty() )
00256 {
00257 setOwnership( ObjectBinding::QObjOwned );
00258 }
00259 else if( object<QObject>()->parent() != 0 )
00260 {
00261 setOwnership( ObjectBinding::QObjOwned );
00262 m_cleanupHandler->remove(object<QObject>());
00263 }
00264 else if( ownership() != ObjectBinding::JSOwned )
00265 {
00266 m_cleanupHandler->remove(object<QObject>());
00267 }
00268 else
00269 {
00270 m_cleanupHandler->remove(object<QObject>());
00271 }
00272
00273 delete m_cleanupHandler;
00274 }
00275
00276 void QObjectBinding::watchObject( QObject *object )
00277 {
00278 m_cleanupHandler->add( object );
00279 }
00280
00281 bool QObjectBinding::getOwnPropertySlot( KJS::ExecState *exec, const KJS::Identifier &propertyName, KJS::PropertySlot &slot )
00282 {
00283
00284 QObject *obj = object<QObject>();
00285 const QMetaObject *meta = obj->metaObject();
00286 int propIndex = meta->indexOfProperty( propertyName.ascii() );
00287 if ( propIndex != -1 ) {
00288 if(! validProperty(meta->property(propIndex), m_access))
00289 return false;
00290
00291 slot.setCustom( this, propertyGetter );
00292 return true;
00293 }
00294 return ObjectBinding::getOwnPropertySlot( exec, propertyName, slot );
00295 }
00296
00297 KJS::JSValue *QObjectBinding::propertyGetter( KJS::ExecState *exec, KJS::JSObject*,
00298 const KJS::Identifier &propertyName, const KJS::PropertySlot&slot )
00299 {
00300
00301 QObjectBinding *self = static_cast<QObjectBinding *>(slot.slotBase());
00302 QObject *obj = self->object<QObject>();
00303
00304 QVariant val = obj->property( propertyName.ascii() );
00305 if ( val.isValid() ) {
00306 return convertToValue( exec, val );
00307 }
00308 qDebug() << QString("propertyGetter called but no property, name was '%1'").arg(propertyName.ascii());
00309 return 0;
00310 }
00311
00312 QObjectBinding::AccessFlags QObjectBinding::access() const
00313 {
00314 return m_access;
00315 }
00316
00317 void QObjectBinding::setAccess(QObjectBinding::AccessFlags access)
00318 {
00319 m_access = access;
00320 }
00321
00322 void QObjectBinding::put(KJS::ExecState *exec, const KJS::Identifier &propertyName, KJS::JSValue *value, int attr )
00323 {
00324 QObject *obj = object<QObject>();
00325 if ( obj && !m_cleanupHandler->isEmpty() )
00326 {
00327
00328 const QMetaObject *meta = obj->metaObject();
00329
00330 if ( int propIndex = meta->indexOfProperty( propertyName.ascii() ) != -1 )
00331 {
00332 QMetaProperty prop = meta->property(propIndex);
00333 if(! validProperty(prop, m_access))
00334 return;
00335
00336 bool propSet = false;
00337 QVariant val = convertToVariant( exec, value );
00338 if ( prop.isEnumType() )
00339 {
00340 propSet = obj->setProperty( propertyName.ascii(), val.toUInt() );
00341 }
00342 else if ( val.isValid() )
00343 {
00344 propSet = obj->setProperty( propertyName.ascii(), val );
00345 }
00346
00347
00348
00349
00350
00351
00352
00353
00354 }
00355
00356 if (JSEventMapper::mapper()->isEventHandler(propertyName) )
00357 {
00358 if ( !m_evproxy )
00359 m_evproxy = new KJSEmbed::EventProxy( this, exec->dynamicInterpreter() );
00360 if( value )
00361 m_evproxy->addFilter( JSEventMapper::mapper()->findEventType( propertyName ) );
00362 else
00363 m_evproxy->removeFilter( JSEventMapper::mapper()->findEventType( propertyName ) );
00364 }
00365 }
00366
00367
00368 ObjectBinding::put(exec, propertyName, value, attr);
00369 }
00370
00371 bool QObjectBinding::canPut(KJS::ExecState *exec, const KJS::Identifier &propertyName) const
00372 {
00373 QObject *obj = object<QObject>();
00374 if ( obj && !m_cleanupHandler->isEmpty() )
00375 {
00376
00377 const QMetaObject *meta = obj->metaObject();
00378 if ( int propIndex = meta->indexOfProperty( propertyName.ascii() ) != -1 )
00379 {
00380 QMetaProperty prop = meta->property(propIndex);
00381 return validProperty(prop, m_access) && prop.isWritable();
00382 }
00383 }
00384 return ObjectBinding::canPut(exec,propertyName);
00385 }
00386
00387 KJS::UString QObjectBinding::className() const
00388 {
00389 return toUString( typeName() );
00390 }
00391
00392 KJS::UString QObjectBinding::toString(KJS::ExecState *exec) const
00393 {
00394 Q_UNUSED( exec );
00395 QString s( "%1 (%2)" );
00396 s = s.arg( object<QObject>()->objectName() );
00397 s = s.arg( typeName() );
00398 return toUString( s );
00399 }
00400
00401 PointerBase *getArg( KJS::ExecState *exec, const QList<QByteArray> &types, const KJS::List &args, int idx, QString& errorText)
00402 {
00403
00404
00405 if( types.size() == 0 && idx == 0 )
00406 return new NullPtr();
00407 if ( args.size() <= idx )
00408 return new NullPtr();
00409
00410 if ( types.size() <= idx )
00411 {
00412 errorText = i18n("The slot asked for %1 arguments but there are only %2 arguments available.", idx, types.size());
00413 return 0;
00414 }
00415
00416 QVariant::Type varianttype = QVariant::nameToType( types[idx].constData() );
00417
00418 switch( varianttype ) {
00419 case QVariant::Int:
00420 if( args[idx]->type() == KJS::NumberType )
00421 return new Value<int>( int( args[idx]->toInteger(exec) ) );
00422 break;
00423 case QVariant::UInt:
00424 if( args[idx]->type() == KJS::NumberType )
00425 return new Value<uint>( uint( args[idx]->toInteger(exec) ) );
00426 break;
00427 case QVariant::LongLong:
00428 if( args[idx]->type() == KJS::NumberType )
00429 return new Value<qlonglong>( qlonglong( args[idx]->toInteger(exec) ) );
00430 break;
00431 case QVariant::ULongLong:
00432 if( args[idx]->type() == KJS::NumberType )
00433 return new Value<qulonglong>( qulonglong( args[idx]->toInteger(exec) ) );
00434 break;
00435 case QVariant::Double:
00436 if( args[idx]->type() == KJS::NumberType )
00437 return new Value<double>( args[idx]->toNumber(exec) );
00438
00439
00440 break;
00441 case QVariant::Bool:
00442 if( args[idx]->type() == KJS::BooleanType )
00443 return new Value<bool>( args[idx]->toBoolean(exec) );
00444 break;
00445 case QVariant::ByteArray:
00446 if( args[idx]->type() == KJS::StringType )
00447 return new Value<QByteArray>( toQString(args[idx]->toString(exec)).toUtf8() );
00448 break;
00449 case QVariant::String:
00450 if( args[idx]->type() == KJS::StringType )
00451 return new Value<QString>( toQString(args[idx]->toString(exec)) );
00452 break;
00453 case QVariant::StringList:
00454 if( args[idx]->type() == KJS::ObjectType )
00455 return new Value<QStringList>( convertArrayToStringList(exec, args[idx]) );
00456 break;
00457 case QVariant::Size:
00458 if( VariantBinding *valImp = KJSEmbed::extractBindingImp<VariantBinding>(exec,args[idx]) )
00459 return new Value<QSize>( valImp->variant().value<QSize>() );
00460 break;
00461 case QVariant::SizeF:
00462 if( VariantBinding *valImp = KJSEmbed::extractBindingImp<VariantBinding>(exec,args[idx]) )
00463 return new Value<QSizeF>( valImp->variant().value<QSizeF>() );
00464 break;
00465 case QVariant::Point:
00466 if( VariantBinding *valImp = KJSEmbed::extractBindingImp<VariantBinding>(exec,args[idx]) )
00467 return new Value<QPoint>( valImp->variant().value<QPoint>() );
00468 break;
00469 case QVariant::PointF:
00470 if( VariantBinding *valImp = KJSEmbed::extractBindingImp<VariantBinding>(exec,args[idx]) )
00471 return new Value<QPointF>( valImp->variant().value<QPointF>() );
00472 break;
00473 case QVariant::Rect:
00474 if( VariantBinding *valImp = KJSEmbed::extractBindingImp<VariantBinding>(exec,args[idx]) )
00475 return new Value<QRect>( valImp->variant().value<QRect>() );
00476 break;
00477 case QVariant::RectF:
00478 if( VariantBinding *valImp = KJSEmbed::extractBindingImp<VariantBinding>(exec,args[idx]) )
00479 return new Value<QRectF>( valImp->variant().value<QRectF>() );
00480 break;
00481 case QVariant::Color:
00482 if( args[idx]->type() == KJS::StringType )
00483 return new Value<QColor>( QColor(toQString(args[idx]->toString(exec))) );
00484 if( VariantBinding *valImp = KJSEmbed::extractBindingImp<VariantBinding>(exec,args[idx]) )
00485 return new Value<QColor>( valImp->variant().value<QColor>() );
00486 break;
00487 case QVariant::Url:
00488 if( args[idx]->type() == KJS::StringType )
00489 return new Value<QUrl>( toQString(args[idx]->toString(exec) ));
00490 if( VariantBinding *valImp = KJSEmbed::extractBindingImp<VariantBinding>(exec,args[idx]) )
00491 return new Value<QUrl>( valImp->variant().value<QUrl>() );
00492 break;
00493 case QVariant::List:
00494 if( args[idx]->type() == KJS::ObjectType )
00495 return new Value<QVariantList>( convertArrayToList(exec, args[idx]) );
00496 break;
00497 case QVariant::Map:
00498 if( args[idx]->type() == KJS::ObjectType )
00499 return new Value<QVariantMap>( convertArrayToMap(exec, args[idx]) );
00500 break;
00501 case QVariant::UserType:
00502 default:
00503 if( args[idx]->type() == KJS::NullType )
00504 return new NullPtr();
00505 if( args[idx]->type() == KJS::StringType )
00506 {
00507 if( strcmp(types[idx].constData(),"KUrl") == 0 )
00508 return new Value<QUrl>( toQString(args[idx]->toString(exec) ));
00509 }
00510 if( args[idx]->type() == KJS::ObjectType )
00511 {
00512 if(QObjectBinding *objImp = KJSEmbed::extractBindingImp<QObjectBinding>(exec, args[idx]))
00513 {
00514
00515 if( QObject* qObj = objImp->qobject<QObject>() )
00516 return new Value<void*>(qObj);
00517 }
00518 else if(ObjectBinding *objImp = KJSEmbed::extractBindingImp<ObjectBinding>(exec, args[idx]))
00519 {
00520
00521 return new Value<void*>(objImp->voidStar());
00522 }
00523 if(VariantBinding *valImp = KJSEmbed::extractBindingImp<VariantBinding>(exec,args[idx]))
00524 {
00525
00526 QVariant var = valImp->variant();
00527
00528
00529 if ((var.type() == varianttype) ||
00530 ((var.type() == QVariant::UserType) &&
00531 (types[idx].constData() == var.typeName())))
00532 return new Value<void*>(valImp->variant().data());
00533 else if ((var.type() != QVariant::UserType) &&
00534 var.canConvert(varianttype))
00535 {
00536
00537 if (var.convert(varianttype))
00538 return new Value<void*>(valImp->variant().data());
00539 }
00540 else if ((var.type() == QVariant::UserType) &&
00541 var.canConvert<QObject*>())
00542 {
00543 QObject* qObj = var.value<QObject*>();
00544 if (!qObj)
00545 qObj = reinterpret_cast<QObject*>(var.value<QWidget*>());
00546 if (qObj) {
00547 QByteArray typeName = types[idx].constData();
00548 typeName.replace("*", "");
00549 if (qObj->inherits(typeName))
00550 return new Value<void*>(qObj);
00551 }
00552 }
00553 }
00554 }
00555
00556 QVariant v = KJSEmbed::extractVariant(exec, args[idx]);
00557 if (! v.isNull())
00558 return new Value<QVariant>(v);
00559
00560 break;
00561 }
00562
00563 qDebug("Cast failure %s value Type %d", types[idx].constData(), args[idx]->type() );
00564
00565 QString jsType;
00566 KJS::JSObject* jsObj = args[idx]->getObject();
00567 if (jsObj)
00568 {
00569 const KJS::ClassInfo* ci = jsObj->classInfo();
00570 if (ci && ci->className)
00571 jsType = ci->className;
00572 if (jsType.isEmpty())
00573 jsType = toQString(jsObj->className());
00574 }
00575
00576 if (jsType.isEmpty())
00577 {
00578 switch(args[idx]->type())
00579 {
00580 case KJS::UnspecifiedType:
00581 jsType = "jsUnspecified";
00582 break;
00583 case KJS::NumberType:
00584 jsType = "jsNumber";
00585 break;
00586 case KJS::BooleanType:
00587 jsType = "jsBoolean";
00588 break;
00589 case KJS::UndefinedType:
00590 jsType = "jsUndefined";
00591 break;
00592 case KJS::NullType:
00593 jsType = "jsNull";
00594 break;
00595 case KJS::StringType:
00596 jsType = "jsString";
00597 break;
00598 case KJS::ObjectType:
00599 jsType = "jsObject";
00600 break;
00601 case KJS::GetterSetterType:
00602 jsType = "jsGetterSetter";
00603 break;
00604 default:
00605 jsType = QString::number(args[idx]->type());
00606 break;
00607 }
00608 }
00609
00610 errorText = i18n("Failure to cast to %1 value from Type %2 (%3)",
00611 types[idx].constData(), jsType, toQString(args[idx]->toString(exec)));
00612
00613 return 0;
00614 }
00615
00616 KJS::JSValue *SlotBinding::callAsFunction( KJS::ExecState *exec, KJS::JSObject *self, const KJS::List &args )
00617 {
00618 QObjectBinding *imp = extractBindingImp<QObjectBinding>(exec,self);
00619 if( imp == 0 )
00620 return KJS::jsNull();
00621
00622 PointerBase *qtArgs[10];
00623 void *param[11];
00624
00625 QObject *object = imp->object<QObject>();
00626 int count = object->metaObject()->methodCount();
00627 QMetaMethod metaMember;
00628 int offset = 0;
00629 bool success = false;
00630 for(; offset < count; ++offset)
00631 {
00632 metaMember = object->metaObject()->method(offset);
00633 if( extractMemberName(metaMember) == m_memberName )
00634 {
00635 if( metaMember.parameterTypes().size() == args.size() && validSlot(metaMember, imp->access()) )
00636 {
00637 success = true;
00638 break;
00639 }
00640 }
00641 }
00642
00643 if( !success )
00644 {
00645 return KJS::throwError(exec, KJS::GeneralError, i18n("No such method '%1'.", m_memberName.constData()));
00646
00647 }
00648
00649 QList<QByteArray> types = metaMember.parameterTypes();
00650
00651 QVariant::Type returnTypeId = QVariant::nameToType( metaMember.typeName() );
00652 int tp = QMetaType::type( metaMember.typeName() );
00653 PointerBase *qtRet = new Value<void*>(0);
00654
00655 bool returnIsMetaType = (
00656 returnTypeId == QVariant::UserType ||
00657 returnTypeId == QVariant::Size || returnTypeId == QVariant::SizeF ||
00658 returnTypeId == QVariant::Point || returnTypeId == QVariant::PointF ||
00659 returnTypeId == QVariant::Rect || returnTypeId == QVariant::RectF ||
00660 returnTypeId == QVariant::Color
00661 );
00662 QVariant returnValue = returnIsMetaType ? QVariant(tp, (void*)0) : QVariant(returnTypeId);
00663 QGenericReturnArgument returnArgument(metaMember.typeName(), &returnValue);
00664 param[0] = returnIsMetaType ? qtRet->voidStar() : returnArgument.data();
00665
00666 QString errorText;
00667 for( int idx = 0; idx < 10; ++idx)
00668 {
00669 qtArgs[idx] = getArg(exec, types, args, idx, errorText);
00670 if (!qtArgs[idx]) {
00671 for( int i = 0; i < idx; ++i)
00672 delete qtArgs[i];
00673 delete qtRet;
00674 return KJS::throwError(exec, KJS::GeneralError, i18n("Call to method '%1' failed, unable to get argument %2: %3", m_memberName.constData(), idx, errorText));
00675 }
00676 param[idx+1] = qtArgs[idx]->voidStar();
00677 }
00678
00679 success = object->qt_metacall(QMetaObject::InvokeMetaMethod, offset, param) < 0;
00680
00681 KJS::JSValue *jsReturnValue = 0;
00682 if( success ) {
00683 switch( returnTypeId ) {
00684 case QVariant::Invalid:
00685 case QVariant::UserType: {
00686 switch( tp ) {
00687 case QMetaType::QWidgetStar: {
00688 QVariant v(tp, param[0]);
00689 QWidget* widget = v.value< QWidget* >();
00690 if( widget )
00691 jsReturnValue = KJSEmbed::createQObject(exec, widget, KJSEmbed::ObjectBinding::CPPOwned);
00692 } break;
00693 case QMetaType::QObjectStar: {
00694 QVariant v(tp,param[0]);
00695 QObject* obj = v.value< QObject* >();
00696 if( obj )
00697 jsReturnValue = KJSEmbed::createQObject(exec, obj, KJSEmbed::ObjectBinding::CPPOwned);
00698 } break;
00699 default:
00700 break;
00701 }
00702 } break;
00703 default:
00704 if( returnIsMetaType )
00705 returnValue = QVariant(tp, param[0]);
00706 break;
00707 }
00708 if(! jsReturnValue)
00709 jsReturnValue = KJSEmbed::convertToValue(exec, returnValue);
00710 }
00711
00712 for( int idx = 0; idx < 10; ++idx)
00713 delete qtArgs[idx];
00714 delete qtRet;
00715
00716 if( !success )
00717 return KJS::throwError(exec, KJS::GeneralError, i18n("Call to '%1' failed.", m_memberName.constData()));
00718
00719 return jsReturnValue;
00720 }
00721
00722 SlotBinding::SlotBinding(KJS::ExecState *exec, const QMetaMethod &member )
00723 : KJS::InternalFunctionImp(static_cast<KJS::FunctionPrototype*>(exec->lexicalInterpreter()->builtinFunctionPrototype()),
00724 KJS::Identifier(toUString(extractMemberName(member))))
00725 {
00726 m_memberName = extractMemberName(member);
00727 int count = member.parameterNames().count();
00728 putDirect( exec->propertyNames().length, count, LengthFlags );
00729 }
00730
00731
00732 KJS::JSObject* KJSEmbed::createQObject(KJS::ExecState *exec, QObject *value, KJSEmbed::ObjectBinding::Ownership owner)
00733 {
00734 if ( 0 == value )
00735 return new KJS::JSObject();
00736
00737 const QMetaObject *meta = value->metaObject();
00738 KJS::JSObject *parent = exec->dynamicInterpreter()->globalObject();
00739 KJS::JSObject *returnValue;
00740 int pos;
00741 QString clazz;
00742 do
00743 {
00744 clazz = meta->className();
00745
00746 #ifdef CREATEQOBJ_DIAG
00747 qDebug() << "clazz=" << clazz;
00748 #endif
00749
00750 if ((pos = clazz.lastIndexOf("::")) != -1)
00751 clazz.remove(0, pos + 2);
00752 #ifdef CREATEQOBJ_DIAG
00753 qDebug() << "cleaned clazz=" << clazz;
00754 #endif
00755 if ( parent->hasProperty( exec, KJS::Identifier(toUString(clazz)) ) )
00756 {
00757 #ifdef CREATEQOBJ_DIAG
00758 qDebug() << "createQObject(): clazz=" << clazz << " value=" << value;
00759 #endif
00760 Pointer<QObject> pov(value);
00761 returnValue = StaticConstructor::bind(exec, clazz, pov);
00762 if ( returnValue )
00763 return returnValue;
00764
00765 #ifdef CREATEQOBJ_DIAG
00766 qDebug("\tresort to construct() method.");
00767 #endif
00768 returnValue = StaticConstructor::construct( exec, parent, toUString(clazz) );
00769 if( returnValue )
00770 {
00771
00772 KJSEmbed::QObjectBinding *imp = extractBindingImp<QObjectBinding>(exec, returnValue );
00773 if( imp )
00774 {
00775 imp->setObject( value );
00776 imp->watchObject( value );
00777 imp->setOwnership( owner );
00778 KJSEmbed::QObjectBinding::publishQObject( exec, returnValue, value);
00779 }
00780 else
00781 {
00782 KJS::throwError(exec, KJS::TypeError, i18n("%1 is not an Object type", clazz ));
00783 return new KJS::JSObject();
00784 }
00785 }
00786 else
00787 {
00788 KJS::throwError(exec, KJS::TypeError, i18n("Could not construct value"));
00789 return new KJS::JSObject();
00790 }
00791 return returnValue;
00792 }
00793 else
00794 {
00795 #ifdef CREATEQOBJ_DIAG
00796 qDebug("%s not a bound type, move up the chain", meta->className() );
00797 #endif
00798 meta = meta->superClass();
00799 }
00800
00801 }
00802 while( meta );
00803
00804 KJSEmbed::QObjectBinding *imp = new KJSEmbed::QObjectBinding(exec, value);
00805 imp->setOwnership( owner );
00806
00807 return imp;
00808 }
00809
00810 START_QOBJECT_METHOD( callParent, QObject )
00811
00812
00813
00814 if( imp->access() & QObjectBinding::GetParentObject )
00815 {
00816 QObject *parent = imp->object<QObject>()->parent();
00817 KJS::JSObject *parentObject = KJSEmbed::createQObject(exec, parent);
00818 KJSEmbed::QObjectBinding *parentImp = KJSEmbed::extractBindingImp<KJSEmbed::QObjectBinding>(exec, parentObject);
00819 if( parentImp ) {
00820 parentImp->setAccess( imp->access() );
00821 }
00822 result = parentObject;
00823 }
00824 END_QOBJECT_METHOD
00825 START_QOBJECT_METHOD( callIsWidgetType, QObject )
00826 result = KJS::jsBoolean(object->isWidgetType());
00827 END_QOBJECT_METHOD
00828 START_QOBJECT_METHOD( callInherits, QObject)
00829 QByteArray className = KJSEmbed::extractQString(exec, args, 0).toLatin1();
00830 result = KJS::jsBoolean(object->inherits(className.constData()));
00831 END_QOBJECT_METHOD
00832 START_QOBJECT_METHOD( callSetParent, QObject )
00833 if( imp->access() & QObjectBinding::SetParentObject )
00834 {
00835 QObject *parent = KJSEmbed::extractObject<QObject>(exec, args, 0, 0);
00836 object->setParent(parent);
00837 }
00838 END_QOBJECT_METHOD
00839 START_QOBJECT_METHOD( callFindChild, QObject )
00840 if( imp->access() & QObjectBinding::ChildObjects )
00841 {
00842 QString childName = KJSEmbed::extractQString(exec, args, 0);
00843 QObject *child = object->findChild<QObject*>(childName);
00844 KJS::JSObject *childObject = KJSEmbed::createQObject(exec, child);
00845 KJSEmbed::QObjectBinding *childImp = KJSEmbed::extractBindingImp<KJSEmbed::QObjectBinding>(exec, childObject);
00846 if( childImp ) {
00847 childImp->setAccess( imp->access() );
00848 }
00849 result = childObject;
00850 }
00851 END_QOBJECT_METHOD
00852
00853 START_METHOD_LUT(QObjectFactory)
00854 {"connect", 4, KJS::DontDelete|KJS::ReadOnly, &callConnect },
00855 {"parent", 0, KJS::DontDelete|KJS::ReadOnly, &callParent },
00856 {"inherits", 1, KJS::DontDelete|KJS::ReadOnly, &callInherits },
00857 {"isWidgetType", 0, KJS::DontDelete|KJS::ReadOnly, &callIsWidgetType },
00858 {"setParent", 1, KJS::DontDelete|KJS::ReadOnly, &callSetParent },
00859 {"findChild", 1, KJS::DontDelete|KJS::ReadOnly, &callFindChild }
00860 END_METHOD_LUT
00861
00862 NO_ENUMS( QObjectFactory )
00863 NO_STATICS( QObjectFactory )
00864
00865