00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "slotproxy.h"
00023
00024 #include <QtCore/QMetaEnum>
00025 #include <QtCore/QMetaType>
00026 #include <QtCore/QDebug>
00027 #include <QtGui/QWidget>
00028
00029 #include <kjs/interpreter.h>
00030
00031 #include "variant_binding.h"
00032 #include "qobject_binding.h"
00033
00034
00035
00036 using namespace KJSEmbed;
00037
00038 SlotProxy::SlotProxy(KJS::JSObject *obj, KJS::Interpreter *interpreter, QObject *parent, const QByteArray &signature)
00039 : QObject(parent), m_interpreter(interpreter), m_object(obj)
00040 {
00041 m_signature = QMetaObject::normalizedSignature( signature );
00042 uint signatureSize = m_signature.size() + 1;
00043
00044
00045 m_data[0] = 1;
00046 m_data[1] = 0;
00047 m_data[2] = 0;
00048 m_data[3] = 0;
00049 m_data[4] = 1;
00050 m_data[5] = 10;
00051 m_data[6] = 0;
00052 m_data[7] = 0;
00053 m_data[8] = 0;
00054 m_data[9] = 0;
00055
00056 m_data[10] = 10;
00057 m_data[11] = 10 + signatureSize;
00058 m_data[12] = 10 + signatureSize;
00059 m_data[13] = 10 + signatureSize;
00060 m_data[14] = 0x0a;
00061 m_data[15] = 0;
00062
00063 m_stringData = QByteArray("SlotProxy\0", 10);
00064 m_stringData += m_signature;
00065 m_stringData += QByteArray("\0\0", 2);
00066
00067 staticMetaObject.d.superdata = &QObject::staticMetaObject;
00068 staticMetaObject.d.stringdata = m_stringData.data();
00069 staticMetaObject.d.data = m_data;
00070 staticMetaObject.d.extradata = 0;
00071 #ifdef DEBUG_SLOTPROXY
00072 qDebug() << "SlotProxy() obj=" << this << " m_signature=" << m_signature;
00073 #endif
00074 }
00075
00076 SlotProxy::~SlotProxy()
00077 {
00078 #ifdef DEBUG_SLOTPROXY
00079 qDebug() << "??????SlotProxy::~SlotProxy() obj=" << this <<" m_signature=" << m_signature;
00080 #endif
00081 }
00082
00083 const QMetaObject *SlotProxy::metaObject() const
00084 {
00085 return &staticMetaObject;
00086 }
00087
00088 void *SlotProxy::qt_metacast(const char *_clname)
00089 {
00090 if (!_clname) return 0;
00091 if (!strcmp(_clname, m_stringData))
00092 return static_cast<void*>(const_cast<SlotProxy*>(this));
00093 return QObject::qt_metacast(_clname);
00094 }
00095
00096 KJS::JSValue *SlotProxy::callMethod( const QByteArray & methodName, void **_a )
00097 {
00098 #ifdef DEBUG_SLOTPROXY
00099 qDebug() << "SlotProxy::callMethod(" << methodName << ",_a) obj=" << this;
00100 #endif
00101 KJS::ExecState *exec = m_interpreter->globalExec();
00102 exec->clearException();
00103
00104
00105
00106 KJS::List args = convertArguments(exec, _a);
00107 KJS::Identifier id = KJS::Identifier( KJS::UString(methodName.data()));
00108 KJS::JSObject *fun = m_object->get(exec, id )->toObject( exec );
00109 KJS::JSValue *retValue;
00110 if ( !fun->implementsCall() )
00111 {
00112 #ifdef DEBUG_SLOTPROXY
00113 qDebug() << "SlotProxy::callMethod got bad handler";
00114 #endif
00115 QString msg = i18n( "Bad slot handler: Object %1 Identifier %2 Method %3 Signature: %4.",
00116 m_object->className().ascii(),
00117 id.ascii(),
00118 methodName.data(),
00119 QString(m_signature));
00120
00121 retValue = throwError(exec, KJS::TypeError, msg);
00122 }
00123 else
00124 retValue = fun->call(exec, m_object, args);
00125
00126 if( exec->hadException() )
00127 {
00128 #ifdef DEBUG_SLOTPROXY
00129 qDebug() << "SlotProxy::callMethod had exception";
00130 #endif
00131 if (m_interpreter->shouldPrintExceptions())
00132 {
00133 KJS::JSLock lock;
00134 KJS::JSObject* exceptObj = exec->exception()->toObject(exec);
00135 QString message = toQString(exceptObj->toString(exec));
00136 QString sourceURL = toQString(exceptObj->get(exec, "sourceURL")->toString(exec));
00137 int sourceId = exceptObj->get(exec, "sourceId")->toUInt32(exec);
00138
00139 int line = exceptObj->get(exec, "line")->toUInt32(exec);
00140 (*KJSEmbed::conerr()) << i18n("Exception calling '%1' slot from %2:%3:%4", QString(methodName), !sourceURL.isEmpty() ? sourceURL : QString::number(sourceId), line, message) << endl;
00141 }
00142
00143
00144 exec->clearException();
00145
00146 return KJS::jsNull();
00147 }
00148 else
00149 {
00150 if( retValue->type() == 1 || retValue->type() == 0)
00151 {
00152 return KJS::jsNull();
00153 }
00154 }
00155 return retValue;
00156 }
00157
00158 KJS::List SlotProxy::convertArguments(KJS::ExecState *exec, void **_a )
00159 {
00160 KJS::List args;
00161 int offset = metaObject()->indexOfMethod(m_signature);
00162 QMetaMethod method = metaObject()->method(offset);
00163 QList<QByteArray> params = method.parameterTypes();
00164 int idx = 1;
00165 #ifdef DEBUG_SLOTPROXY
00166 qDebug() << "SlotProxy::convertArguments(): obj=" << this << " m_signature=" << m_signature << " offset=" << offset << " params=" << params ;
00167 #endif
00168 foreach( const QByteArray ¶m, params )
00169 {
00170 #ifdef DEBUG_SLOTPROXY
00171 int type = QMetaType::type( param.constData() );
00172 qDebug("\tGot a %d - %s - _a[%d] = %p", type, param.data(), idx, _a[idx]);
00173 qDebug("\t QMetaType::type()=%d", QMetaType::type(QByteArray("Pinya::") + param.constData()));
00174 #endif
00175 int tp = QVariant::nameToType(param.constData());
00176 switch(tp)
00177 {
00178 case QVariant::Int:
00179 args.append(KJS::jsNumber(*(int*)_a[idx]));
00180 break;
00181 case QVariant::UInt:
00182 args.append(KJS::jsNumber(*(uint*)_a[idx]));
00183 break;
00184 case QVariant::LongLong:
00185 args.append(KJS::jsNumber(*(qlonglong*)_a[idx]));
00186 break;
00187 case QVariant::ULongLong:
00188 args.append(KJS::jsNumber(*(qulonglong*)_a[idx]));
00189 break;
00190 case QVariant::Double:
00191 args.append(KJS::jsNumber(*(double*)_a[idx]));
00192 break;
00193 case QVariant::Bool:
00194 args.append(KJS::jsBoolean(*(bool*)_a[idx]));
00195 break;
00196 case QVariant::String:
00197 args.append(KJS::jsString((*reinterpret_cast<QString(*)>(_a[idx]))));
00198 break;
00199 case QVariant::UserType:
00200 {
00201 KJS::JSObject* returnValue;
00202 KJS::JSObject* parent = exec->dynamicInterpreter()->globalObject();
00203 QByteArray typeName = param.constData();
00204 bool isPtr = typeName.contains("*");
00205 if (isPtr)
00206 typeName.replace("*", "");
00207 #ifdef DEBUG_SLOTPROXY
00208 qDebug() << "\tQVariant::UserType: typeName=" << typeName << " param=" << param.constData() << " isPtr" << isPtr;
00209 #endif
00210 if ( parent->hasProperty( exec, KJS::Identifier(toUString(typeName))) )
00211 {
00212 QObject* qObj;
00213 if (isPtr &&
00214 ((qObj = *reinterpret_cast<QObject**>(_a[idx])) != 0))
00215 {
00216 #ifdef DEBUG_SLOTPROXY
00217 qDebug() << "qObj=" << qObj;
00218 #endif
00219 Pointer<QObject> pov(*reinterpret_cast<QObject*(*)>(_a[idx]));
00220 returnValue = StaticConstructor::bind(exec, typeName, pov);
00221 if ( returnValue )
00222 {
00223 args.append(returnValue);
00224 break;
00225 }
00226 else
00227 {
00228 #ifdef DEBUG_SLOTPROXY
00229 qDebug("\t\tNo binding retrieved");
00230 #endif
00231 returnValue = StaticConstructor::construct( exec, parent, toUString(typeName) );
00232 if( returnValue )
00233 {
00234 if(QObjectBinding *objImp = KJSEmbed::extractBindingImp<QObjectBinding>(exec, returnValue))
00235 {
00236 #ifdef DEBUG_SLOTPROXY
00237 qDebug() << "\t\t\tFound QObjectBinding";
00238 #endif
00239 objImp->setOwnership( KJSEmbed::ObjectBinding::JSOwned );
00240 objImp->setObject(qObj);
00241 if (qObj->parent() != 0)
00242 objImp->setOwnership(KJSEmbed::ObjectBinding::QObjOwned);
00243 else
00244 objImp->setOwnership(KJSEmbed::ObjectBinding::CPPOwned);
00245 args.append(returnValue);
00246 break;
00247 }
00248 }
00249 }
00250 }
00251 }
00252 else
00253 {
00254 #ifdef DEBUG_SLOTPROXY
00255 qDebug("\t\tNo binding registered");
00256 #endif
00257 KJS::JSObject* returnValue = 0;
00258 switch( QMetaType::type( param.constData() ) )
00259 {
00260 case QMetaType::QObjectStar: {
00261 QObject* obj = (*reinterpret_cast< QObject*(*)>( _a[idx] ));
00262 returnValue = KJSEmbed::createQObject(exec, obj, KJSEmbed::ObjectBinding::QObjOwned);
00263 } break;
00264 case QMetaType::QWidgetStar: {
00265 QWidget* obj = (*reinterpret_cast< QWidget*(*)>( _a[idx] ));
00266 returnValue = KJSEmbed::createQObject(exec, obj, KJSEmbed::ObjectBinding::QObjOwned);
00267 } break;
00268 default: {
00269 #ifdef DEBUG_SLOTPROXY
00270 qDebug("\t\tInvalid type !");
00271 #endif
00272 } break;
00273 }
00274 if( returnValue ) {
00275 args.append(returnValue);
00276 break;
00277 }
00278 }
00279 }
00280 case QVariant::StringList:
00281 case QVariant::List:
00282 case QVariant::Map:
00283 default:
00284
00285 QVariant variant(tp, _a[idx]);
00286 args.append( KJSEmbed::convertToValue(exec,variant) );
00287 break;
00288 }
00289 ++idx;
00290 }
00291
00292 return args;
00293 }
00294
00295 int SlotProxy::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
00296 {
00297 #ifdef DEBUG_SLOTPROXY
00298 qDebug("SlotProxy::qt_metacall(_c=%d, _id=%d, _a=%p _a[0]=%p _a[1]=%p) obj=", _c, _id, _a, _a[0], _a[1], this);
00299 #endif
00300 _id = QObject::qt_metacall(_c, _id, _a);
00301 if (_id < 0)
00302 return _id;
00303 if (_c == QMetaObject::InvokeMetaMethod)
00304 {
00305 switch (_id)
00306 {
00307 case 0: {
00308
00309 QByteArray method = m_signature.left(m_signature.indexOf('('));
00310 KJS::JSValue *result = callMethod(method, _a);
00311 m_tmpResult = convertToVariant(m_interpreter->globalExec(), result);
00312 #ifdef DEBUG_SLOTPROXY
00313 qDebug()<<"SlotProxy::qt_metacall result="<<m_tmpResult.toString();
00314 #endif
00315 _a[0] = &(m_tmpResult);
00316 } break;
00317 }
00318 _id -= 1;
00319 }
00320 return _id;
00321 }
00322
00323