src/declarative/qml/qdeclarativevmemetaobject.cpp
changeset 30 5dc02b23752f
child 33 3e2da88830cd
equal deleted inserted replaced
29:b72c6db6890b 30:5dc02b23752f
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "private/qdeclarativevmemetaobject_p.h"
       
    43 
       
    44 #include "qdeclarative.h"
       
    45 #include "private/qdeclarativerefcount_p.h"
       
    46 #include "qdeclarativeexpression.h"
       
    47 #include "private/qdeclarativeexpression_p.h"
       
    48 #include "private/qdeclarativecontext_p.h"
       
    49 
       
    50 Q_DECLARE_METATYPE(QScriptValue);
       
    51 
       
    52 QT_BEGIN_NAMESPACE
       
    53 
       
    54 class QDeclarativeVMEVariant
       
    55 {
       
    56 public:
       
    57     inline QDeclarativeVMEVariant();
       
    58     inline ~QDeclarativeVMEVariant();
       
    59 
       
    60     inline const void *dataPtr() const;
       
    61     inline void *dataPtr();
       
    62     inline int dataType() const;
       
    63 
       
    64     inline QObject *asQObject();
       
    65     inline const QVariant &asQVariant();
       
    66     inline int asInt();
       
    67     inline bool asBool();
       
    68     inline double asDouble();
       
    69     inline const QString &asQString();
       
    70     inline const QUrl &asQUrl();
       
    71     inline const QColor &asQColor();
       
    72     inline const QTime &asQTime();
       
    73     inline const QDate &asQDate();
       
    74     inline const QDateTime &asQDateTime();
       
    75     inline const QScriptValue &asQScriptValue();
       
    76 
       
    77     inline void setValue(QObject *);
       
    78     inline void setValue(const QVariant &);
       
    79     inline void setValue(int);
       
    80     inline void setValue(bool);
       
    81     inline void setValue(double);
       
    82     inline void setValue(const QString &);
       
    83     inline void setValue(const QUrl &);
       
    84     inline void setValue(const QColor &);
       
    85     inline void setValue(const QTime &);
       
    86     inline void setValue(const QDate &);
       
    87     inline void setValue(const QDateTime &);
       
    88     inline void setValue(const QScriptValue &);
       
    89 private:
       
    90     int type;
       
    91     void *data[4]; // Large enough to hold all types
       
    92 
       
    93     inline void cleanup();
       
    94 };
       
    95 
       
    96 QDeclarativeVMEVariant::QDeclarativeVMEVariant()
       
    97 : type(QVariant::Invalid)
       
    98 {
       
    99 }
       
   100 
       
   101 QDeclarativeVMEVariant::~QDeclarativeVMEVariant()
       
   102 {
       
   103     cleanup();
       
   104 }
       
   105 
       
   106 void QDeclarativeVMEVariant::cleanup()
       
   107 {
       
   108     if (type == QVariant::Invalid) {
       
   109     } else if (type == QMetaType::Int ||
       
   110                type == QMetaType::Bool ||
       
   111                type == QMetaType::Double) {
       
   112         type = QVariant::Invalid;
       
   113     } else if (type == QMetaType::QObjectStar) {
       
   114         ((QDeclarativeGuard<QObject>*)dataPtr())->~QDeclarativeGuard<QObject>();
       
   115         type = QVariant::Invalid;
       
   116     } else if (type == QMetaType::QString) {
       
   117         ((QString *)dataPtr())->~QString();
       
   118         type = QVariant::Invalid;
       
   119     } else if (type == QMetaType::QUrl) {
       
   120         ((QUrl *)dataPtr())->~QUrl();
       
   121         type = QVariant::Invalid;
       
   122     } else if (type == QMetaType::QColor) {
       
   123         ((QColor *)dataPtr())->~QColor();
       
   124         type = QVariant::Invalid;
       
   125     } else if (type == QMetaType::QTime) {
       
   126         ((QTime *)dataPtr())->~QTime();
       
   127         type = QVariant::Invalid;
       
   128     } else if (type == QMetaType::QDate) {
       
   129         ((QDate *)dataPtr())->~QDate();
       
   130         type = QVariant::Invalid;
       
   131     } else if (type == QMetaType::QDateTime) {
       
   132         ((QDateTime *)dataPtr())->~QDateTime();
       
   133         type = QVariant::Invalid;
       
   134     } else if (type == qMetaTypeId<QVariant>()) {
       
   135         ((QVariant *)dataPtr())->~QVariant();
       
   136         type = QVariant::Invalid;
       
   137     } else if (type == qMetaTypeId<QScriptValue>()) {
       
   138         ((QScriptValue *)dataPtr())->~QScriptValue();
       
   139         type = QVariant::Invalid;
       
   140     }
       
   141 
       
   142 }
       
   143 
       
   144 int QDeclarativeVMEVariant::dataType() const
       
   145 {
       
   146     return type;
       
   147 }
       
   148 
       
   149 const void *QDeclarativeVMEVariant::dataPtr() const
       
   150 {
       
   151     return &data;
       
   152 }
       
   153 
       
   154 void *QDeclarativeVMEVariant::dataPtr() 
       
   155 {
       
   156     return &data;
       
   157 }
       
   158 
       
   159 QObject *QDeclarativeVMEVariant::asQObject() 
       
   160 {
       
   161     if (type != QMetaType::QObjectStar) 
       
   162         setValue((QObject *)0);
       
   163 
       
   164     return *(QDeclarativeGuard<QObject> *)(dataPtr());
       
   165 }
       
   166 
       
   167 const QVariant &QDeclarativeVMEVariant::asQVariant() 
       
   168 {
       
   169     if (type != QMetaType::QVariant)
       
   170         setValue(QVariant());
       
   171 
       
   172     return *(QVariant *)(dataPtr());
       
   173 }
       
   174 
       
   175 int QDeclarativeVMEVariant::asInt() 
       
   176 {
       
   177     if (type != QMetaType::Int)
       
   178         setValue(int(0));
       
   179 
       
   180     return *(int *)(dataPtr());
       
   181 }
       
   182 
       
   183 bool QDeclarativeVMEVariant::asBool() 
       
   184 {
       
   185     if (type != QMetaType::Bool)
       
   186         setValue(bool(false));
       
   187 
       
   188     return *(bool *)(dataPtr());
       
   189 }
       
   190 
       
   191 double QDeclarativeVMEVariant::asDouble() 
       
   192 {
       
   193     if (type != QMetaType::Double)
       
   194         setValue(double(0));
       
   195 
       
   196     return *(double *)(dataPtr());
       
   197 }
       
   198 
       
   199 const QString &QDeclarativeVMEVariant::asQString() 
       
   200 {
       
   201     if (type != QMetaType::QString)
       
   202         setValue(QString());
       
   203 
       
   204     return *(QString *)(dataPtr());
       
   205 }
       
   206 
       
   207 const QUrl &QDeclarativeVMEVariant::asQUrl() 
       
   208 {
       
   209     if (type != QMetaType::QUrl)
       
   210         setValue(QUrl());
       
   211 
       
   212     return *(QUrl *)(dataPtr());
       
   213 }
       
   214 
       
   215 const QColor &QDeclarativeVMEVariant::asQColor() 
       
   216 {
       
   217     if (type != QMetaType::QColor)
       
   218         setValue(QColor());
       
   219 
       
   220     return *(QColor *)(dataPtr());
       
   221 }
       
   222 
       
   223 const QTime &QDeclarativeVMEVariant::asQTime() 
       
   224 {
       
   225     if (type != QMetaType::QTime)
       
   226         setValue(QTime());
       
   227 
       
   228     return *(QTime *)(dataPtr());
       
   229 }
       
   230 
       
   231 const QDate &QDeclarativeVMEVariant::asQDate() 
       
   232 {
       
   233     if (type != QMetaType::QDate)
       
   234         setValue(QDate());
       
   235 
       
   236     return *(QDate *)(dataPtr());
       
   237 }
       
   238 
       
   239 const QDateTime &QDeclarativeVMEVariant::asQDateTime() 
       
   240 {
       
   241     if (type != QMetaType::QDateTime)
       
   242         setValue(QDateTime());
       
   243 
       
   244     return *(QDateTime *)(dataPtr());
       
   245 }
       
   246 
       
   247 const QScriptValue &QDeclarativeVMEVariant::asQScriptValue() 
       
   248 {
       
   249     if (type != qMetaTypeId<QScriptValue>())
       
   250         setValue(QScriptValue());
       
   251 
       
   252     return *(QScriptValue *)(dataPtr());
       
   253 }
       
   254 
       
   255 void QDeclarativeVMEVariant::setValue(QObject *v)
       
   256 {
       
   257     if (type != QMetaType::QObjectStar) {
       
   258         cleanup();
       
   259         type = QMetaType::QObjectStar;
       
   260         new (dataPtr()) QDeclarativeGuard<QObject>();
       
   261     }
       
   262     *(QDeclarativeGuard<QObject>*)(dataPtr()) = v;
       
   263 }
       
   264 
       
   265 void QDeclarativeVMEVariant::setValue(const QVariant &v)
       
   266 {
       
   267     if (type != qMetaTypeId<QVariant>()) {
       
   268         cleanup();
       
   269         type = qMetaTypeId<QVariant>();
       
   270         new (dataPtr()) QVariant(v);
       
   271     } else {
       
   272         *(QVariant *)(dataPtr()) = v;
       
   273     }
       
   274 }
       
   275 
       
   276 void QDeclarativeVMEVariant::setValue(int v)
       
   277 {
       
   278     if (type != QMetaType::Int) {
       
   279         cleanup();
       
   280         type = QMetaType::Int;
       
   281     }
       
   282     *(int *)(dataPtr()) = v;
       
   283 }
       
   284 
       
   285 void QDeclarativeVMEVariant::setValue(bool v)
       
   286 {
       
   287     if (type != QMetaType::Bool) {
       
   288         cleanup();
       
   289         type = QMetaType::Bool;
       
   290     }
       
   291     *(bool *)(dataPtr()) = v;
       
   292 }
       
   293 
       
   294 void QDeclarativeVMEVariant::setValue(double v)
       
   295 {
       
   296     if (type != QMetaType::Double) {
       
   297         cleanup();
       
   298         type = QMetaType::Double;
       
   299     }
       
   300     *(double *)(dataPtr()) = v;
       
   301 }
       
   302 
       
   303 void QDeclarativeVMEVariant::setValue(const QString &v)
       
   304 {
       
   305     if (type != QMetaType::QString) {
       
   306         cleanup();
       
   307         type = QMetaType::QString;
       
   308         new (dataPtr()) QString(v);
       
   309     } else {
       
   310         *(QString *)(dataPtr()) = v;
       
   311     }
       
   312 }
       
   313 
       
   314 void QDeclarativeVMEVariant::setValue(const QUrl &v)
       
   315 {
       
   316     if (type != QMetaType::QUrl) {
       
   317         cleanup();
       
   318         type = QMetaType::QUrl;
       
   319         new (dataPtr()) QUrl(v);
       
   320     } else {
       
   321         *(QUrl *)(dataPtr()) = v;
       
   322     }
       
   323 }
       
   324 
       
   325 void QDeclarativeVMEVariant::setValue(const QColor &v)
       
   326 {
       
   327     if (type != QMetaType::QColor) {
       
   328         cleanup();
       
   329         type = QMetaType::QColor;
       
   330         new (dataPtr()) QColor(v);
       
   331     } else {
       
   332         *(QColor *)(dataPtr()) = v;
       
   333     }
       
   334 }
       
   335 
       
   336 void QDeclarativeVMEVariant::setValue(const QTime &v)
       
   337 {
       
   338     if (type != QMetaType::QTime) {
       
   339         cleanup();
       
   340         type = QMetaType::QTime;
       
   341         new (dataPtr()) QTime(v);
       
   342     } else {
       
   343         *(QTime *)(dataPtr()) = v;
       
   344     }
       
   345 }
       
   346 
       
   347 void QDeclarativeVMEVariant::setValue(const QDate &v)
       
   348 {
       
   349     if (type != QMetaType::QDate) {
       
   350         cleanup();
       
   351         type = QMetaType::QDate;
       
   352         new (dataPtr()) QDate(v);
       
   353     } else {
       
   354         *(QDate *)(dataPtr()) = v;
       
   355     }
       
   356 }
       
   357 
       
   358 void QDeclarativeVMEVariant::setValue(const QDateTime &v)
       
   359 {
       
   360     if (type != QMetaType::QDateTime) {
       
   361         cleanup();
       
   362         type = QMetaType::QDateTime;
       
   363         new (dataPtr()) QDateTime(v);
       
   364     } else {
       
   365         *(QDateTime *)(dataPtr()) = v;
       
   366     }
       
   367 }
       
   368 
       
   369 void QDeclarativeVMEVariant::setValue(const QScriptValue &v)
       
   370 {
       
   371     if (type != qMetaTypeId<QScriptValue>()) {
       
   372         cleanup();
       
   373         type = qMetaTypeId<QScriptValue>();
       
   374         new (dataPtr()) QScriptValue(v);
       
   375     } else {
       
   376         *(QScriptValue *)(dataPtr()) = v;
       
   377     }
       
   378 }
       
   379 
       
   380 QDeclarativeVMEMetaObject::QDeclarativeVMEMetaObject(QObject *obj,
       
   381                                                      const QMetaObject *other, 
       
   382                                                      const QDeclarativeVMEMetaData *meta,
       
   383                                                      QDeclarativeCompiledData *cdata)
       
   384 : object(obj), compiledData(cdata), ctxt(QDeclarativeData::get(obj, true)->outerContext),
       
   385   metaData(meta), data(0), methods(0), parent(0)
       
   386 {
       
   387     compiledData->addref();
       
   388 
       
   389     *static_cast<QMetaObject *>(this) = *other;
       
   390     this->d.superdata = obj->metaObject();
       
   391 
       
   392     QObjectPrivate *op = QObjectPrivate::get(obj);
       
   393     if (op->metaObject)
       
   394         parent = static_cast<QAbstractDynamicMetaObject*>(op->metaObject);
       
   395     op->metaObject = this;
       
   396 
       
   397     propOffset = QAbstractDynamicMetaObject::propertyOffset();
       
   398     methodOffset = QAbstractDynamicMetaObject::methodOffset();
       
   399 
       
   400     data = new QDeclarativeVMEVariant[metaData->propertyCount];
       
   401 
       
   402     aConnected.resize(metaData->aliasCount);
       
   403     int list_type = qMetaTypeId<QDeclarativeListProperty<QObject> >();
       
   404 
       
   405     // ### Optimize
       
   406     for (int ii = 0; ii < metaData->propertyCount; ++ii) {
       
   407         int t = (metaData->propertyData() + ii)->propertyType;
       
   408         if (t == list_type) {
       
   409             listProperties.append(List(methodOffset + ii));
       
   410             data[ii].setValue(listProperties.count() - 1);
       
   411         } 
       
   412     }
       
   413 }
       
   414 
       
   415 QDeclarativeVMEMetaObject::~QDeclarativeVMEMetaObject()
       
   416 {
       
   417     compiledData->release();
       
   418     delete parent;
       
   419     delete [] data;
       
   420     delete [] methods;
       
   421 }
       
   422 
       
   423 int QDeclarativeVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
       
   424 {
       
   425     int id = _id;
       
   426     if(c == QMetaObject::WriteProperty) {
       
   427         int flags = *reinterpret_cast<int*>(a[3]);
       
   428         if (!(flags & QDeclarativePropertyPrivate::BypassInterceptor)
       
   429             && !aInterceptors.isEmpty()
       
   430             && aInterceptors.testBit(id)) {
       
   431             QPair<int, QDeclarativePropertyValueInterceptor*> pair = interceptors.value(id);
       
   432             int valueIndex = pair.first;
       
   433             QDeclarativePropertyValueInterceptor *vi = pair.second;
       
   434             int type = property(id).userType();
       
   435 
       
   436             if (type != QVariant::Invalid) {
       
   437                 if (valueIndex != -1) {
       
   438                     QDeclarativeEnginePrivate *ep = ctxt?QDeclarativeEnginePrivate::get(ctxt->engine):0;
       
   439                     QDeclarativeValueType *valueType = 0;
       
   440                     if (ep) valueType = ep->valueTypes[type];
       
   441                     else valueType = QDeclarativeValueTypeFactory::valueType(type);
       
   442                     Q_ASSERT(valueType);
       
   443 
       
   444                     valueType->setValue(QVariant(type, a[0]));
       
   445                     QMetaProperty valueProp = valueType->metaObject()->property(valueIndex);
       
   446                     vi->write(valueProp.read(valueType));
       
   447 
       
   448                     if (!ep) delete valueType;
       
   449                     return -1;
       
   450                 } else {
       
   451                     vi->write(QVariant(type, a[0]));
       
   452                     return -1;
       
   453                 }
       
   454             }
       
   455         }
       
   456     }
       
   457     if(c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty) {
       
   458         if (id >= propOffset) {
       
   459             id -= propOffset;
       
   460 
       
   461             if (id < metaData->propertyCount) {
       
   462                 int t = (metaData->propertyData() + id)->propertyType;
       
   463                 bool needActivate = false;
       
   464 
       
   465                 if (t == -1) {
       
   466 
       
   467                     if (c == QMetaObject::ReadProperty) {
       
   468                         *reinterpret_cast<QVariant *>(a[0]) = readVarPropertyAsVariant(id);
       
   469                     } else if (c == QMetaObject::WriteProperty) {
       
   470                         writeVarProperty(id, *reinterpret_cast<QVariant *>(a[0]));
       
   471                     }
       
   472 
       
   473                 } else {
       
   474 
       
   475                     if (c == QMetaObject::ReadProperty) {
       
   476                         switch(t) {
       
   477                         case QVariant::Int:
       
   478                             *reinterpret_cast<int *>(a[0]) = data[id].asInt();
       
   479                             break;
       
   480                         case QVariant::Bool:
       
   481                             *reinterpret_cast<bool *>(a[0]) = data[id].asBool();
       
   482                             break;
       
   483                         case QVariant::Double:
       
   484                             *reinterpret_cast<double *>(a[0]) = data[id].asDouble();
       
   485                             break;
       
   486                         case QVariant::String:
       
   487                             *reinterpret_cast<QString *>(a[0]) = data[id].asQString();
       
   488                             break;
       
   489                         case QVariant::Url:
       
   490                             *reinterpret_cast<QUrl *>(a[0]) = data[id].asQUrl();
       
   491                             break;
       
   492                         case QVariant::Color:
       
   493                             *reinterpret_cast<QColor *>(a[0]) = data[id].asQColor();
       
   494                             break;
       
   495                         case QVariant::Date:
       
   496                             *reinterpret_cast<QDate *>(a[0]) = data[id].asQDate();
       
   497                             break;
       
   498                         case QVariant::DateTime:
       
   499                             *reinterpret_cast<QDateTime *>(a[0]) = data[id].asQDateTime();
       
   500                             break;
       
   501                         case QMetaType::QObjectStar:
       
   502                             *reinterpret_cast<QObject **>(a[0]) = data[id].asQObject();
       
   503                             break;
       
   504                         default:
       
   505                             break;
       
   506                         }
       
   507                         if (t == qMetaTypeId<QDeclarativeListProperty<QObject> >()) {
       
   508                             int listIndex = data[id].asInt();
       
   509                             const List *list = &listProperties.at(listIndex);
       
   510                             *reinterpret_cast<QDeclarativeListProperty<QObject> *>(a[0]) = 
       
   511                                 QDeclarativeListProperty<QObject>(object, (void *)list,
       
   512                                                                   list_append, list_count, list_at, 
       
   513                                                                   list_clear);
       
   514                         }
       
   515 
       
   516                     } else if (c == QMetaObject::WriteProperty) {
       
   517 
       
   518                         switch(t) {
       
   519                         case QVariant::Int:
       
   520                             needActivate = *reinterpret_cast<int *>(a[0]) != data[id].asInt();
       
   521                             data[id].setValue(*reinterpret_cast<int *>(a[0]));
       
   522                             break;
       
   523                         case QVariant::Bool:
       
   524                             needActivate = *reinterpret_cast<bool *>(a[0]) != data[id].asBool();
       
   525                             data[id].setValue(*reinterpret_cast<bool *>(a[0]));
       
   526                             break;
       
   527                         case QVariant::Double:
       
   528                             needActivate = *reinterpret_cast<double *>(a[0]) != data[id].asDouble();
       
   529                             data[id].setValue(*reinterpret_cast<double *>(a[0]));
       
   530                             break;
       
   531                         case QVariant::String:
       
   532                             needActivate = *reinterpret_cast<QString *>(a[0]) != data[id].asQString();
       
   533                             data[id].setValue(*reinterpret_cast<QString *>(a[0]));
       
   534                             break;
       
   535                         case QVariant::Url:
       
   536                             needActivate = *reinterpret_cast<QUrl *>(a[0]) != data[id].asQUrl();
       
   537                             data[id].setValue(*reinterpret_cast<QUrl *>(a[0]));
       
   538                             break;
       
   539                         case QVariant::Color:
       
   540                             needActivate = *reinterpret_cast<QColor *>(a[0]) != data[id].asQColor();
       
   541                             data[id].setValue(*reinterpret_cast<QColor *>(a[0]));
       
   542                             break;
       
   543                         case QVariant::Date:
       
   544                             needActivate = *reinterpret_cast<QDate *>(a[0]) != data[id].asQDate();
       
   545                             data[id].setValue(*reinterpret_cast<QDate *>(a[0]));
       
   546                             break;
       
   547                         case QVariant::DateTime:
       
   548                             needActivate = *reinterpret_cast<QDateTime *>(a[0]) != data[id].asQDateTime();
       
   549                             data[id].setValue(*reinterpret_cast<QDateTime *>(a[0]));
       
   550                             break;
       
   551                         case QMetaType::QObjectStar:
       
   552                             needActivate = *reinterpret_cast<QObject **>(a[0]) != data[id].asQObject();
       
   553                             data[id].setValue(*reinterpret_cast<QObject **>(a[0]));
       
   554                             break;
       
   555                         default:
       
   556                             break;
       
   557                         }
       
   558                     }
       
   559 
       
   560                 }
       
   561 
       
   562                 if (c == QMetaObject::WriteProperty && needActivate) {
       
   563                     activate(object, methodOffset + id, 0);
       
   564                 }
       
   565 
       
   566                 return -1;
       
   567             }
       
   568 
       
   569             id -= metaData->propertyCount;
       
   570 
       
   571             if (id < metaData->aliasCount) {
       
   572 
       
   573                 QDeclarativeVMEMetaData::AliasData *d = metaData->aliasData() + id;
       
   574 
       
   575                 if (d->flags & QML_ALIAS_FLAG_PTR && c == QMetaObject::ReadProperty) 
       
   576                         *reinterpret_cast<void **>(a[0]) = 0;
       
   577 
       
   578                 if (!ctxt) return -1;
       
   579 
       
   580                 QDeclarativeContext *context = ctxt->asQDeclarativeContext();
       
   581                 QDeclarativeContextPrivate *ctxtPriv = QDeclarativeContextPrivate::get(context);
       
   582 
       
   583                 QObject *target = ctxtPriv->data->idValues[d->contextIdx].data();
       
   584                 if (!target) 
       
   585                     return -1;
       
   586 
       
   587                 if (c == QMetaObject::ReadProperty && !aConnected.testBit(id)) {
       
   588                     int sigIdx = methodOffset + id + metaData->propertyCount;
       
   589                     QMetaObject::connect(context, d->contextIdx + ctxtPriv->notifyIndex, object, sigIdx);
       
   590 
       
   591                     if (d->propertyIdx != -1) {
       
   592                         QMetaProperty prop = 
       
   593                             target->metaObject()->property(d->propertyIdx);
       
   594                         if (prop.hasNotifySignal())
       
   595                             QMetaObject::connect(target, prop.notifySignalIndex(), 
       
   596                                                  object, sigIdx);
       
   597                     }
       
   598                     aConnected.setBit(id);
       
   599                 }
       
   600 
       
   601                 if (d->propertyIdx == -1) {
       
   602                     *reinterpret_cast<QObject **>(a[0]) = target;
       
   603                     return -1;
       
   604                 } else {
       
   605                     return QMetaObject::metacall(target, c, d->propertyIdx, a);
       
   606                 }
       
   607 
       
   608             }
       
   609             return -1;
       
   610 
       
   611         }
       
   612 
       
   613     } else if(c == QMetaObject::InvokeMetaMethod) {
       
   614 
       
   615         if (id >= methodOffset) {
       
   616 
       
   617             id -= methodOffset;
       
   618             int plainSignals = metaData->signalCount + metaData->propertyCount +
       
   619                                metaData->aliasCount;
       
   620             if (id < plainSignals) {
       
   621                 QMetaObject::activate(object, _id, a);
       
   622                 return -1;
       
   623             }
       
   624 
       
   625             id -= plainSignals;
       
   626 
       
   627             if (id < metaData->methodCount) {
       
   628                 if (!ctxt->engine)
       
   629                     return -1; // We can't run the method
       
   630 
       
   631                 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(ctxt->engine);
       
   632 
       
   633                 QScriptValue function = method(id);
       
   634 
       
   635                 QScriptValueList args;
       
   636                 QDeclarativeVMEMetaData::MethodData *data = metaData->methodData() + id;
       
   637                 if (data->parameterCount) {
       
   638                     for (int ii = 0; ii < data->parameterCount; ++ii) {
       
   639                         args << ep->scriptValueFromVariant(*(QVariant *)a[ii + 1]);
       
   640                     }
       
   641                 }
       
   642                 QScriptValue rv = function.call(ep->objectClass->newQObject(object), args);
       
   643 
       
   644                 if (a[0]) *reinterpret_cast<QVariant *>(a[0]) = ep->scriptValueToVariant(rv);
       
   645 
       
   646                 return -1;
       
   647             }
       
   648             return -1;
       
   649         }
       
   650     }
       
   651 
       
   652     if (parent)
       
   653         return parent->metaCall(c, _id, a);
       
   654     else
       
   655         return object->qt_metacall(c, _id, a);
       
   656 }
       
   657 
       
   658 QScriptValue QDeclarativeVMEMetaObject::method(int index)
       
   659 {
       
   660     if (!methods) 
       
   661         methods = new QScriptValue[metaData->methodCount];
       
   662 
       
   663     if (!methods[index].isValid()) {
       
   664         QDeclarativeVMEMetaData::MethodData *data = metaData->methodData() + index;
       
   665 
       
   666         const QChar *body = 
       
   667             (const QChar *)(((const char*)metaData) + data->bodyOffset);
       
   668 
       
   669         QString code = QString::fromRawData(body, data->bodyLength);
       
   670 
       
   671         // XXX Use QScriptProgram
       
   672         // XXX We should evaluate all methods in a single big script block to 
       
   673         // improve the call time between dynamic methods defined on the same
       
   674         // object
       
   675         methods[index] = QDeclarativeExpressionPrivate::evalInObjectScope(ctxt, object, code, ctxt->url.toString(),
       
   676                                                                           data->lineNumber, 0);
       
   677     }
       
   678 
       
   679     return methods[index];
       
   680 }
       
   681 
       
   682 QScriptValue QDeclarativeVMEMetaObject::readVarProperty(int id)
       
   683 {
       
   684     if (data[id].dataType() == qMetaTypeId<QScriptValue>())
       
   685         return data[id].asQScriptValue();
       
   686     else if (data[id].dataType() == QMetaType::QObjectStar) 
       
   687         return QDeclarativeEnginePrivate::get(ctxt->engine)->objectClass->newQObject(data[id].asQObject());
       
   688     else
       
   689         return QDeclarativeEnginePrivate::get(ctxt->engine)->scriptValueFromVariant(data[id].asQVariant());
       
   690 }
       
   691 
       
   692 QVariant QDeclarativeVMEMetaObject::readVarPropertyAsVariant(int id)
       
   693 {
       
   694     if (data[id].dataType() == qMetaTypeId<QScriptValue>())
       
   695         return QDeclarativeEnginePrivate::get(ctxt->engine)->scriptValueToVariant(data[id].asQScriptValue());
       
   696     else if (data[id].dataType() == QMetaType::QObjectStar) 
       
   697         return QVariant::fromValue(data[id].asQObject());
       
   698     else 
       
   699         return data[id].asQVariant();
       
   700 }
       
   701 
       
   702 void QDeclarativeVMEMetaObject::writeVarProperty(int id, const QScriptValue &value)
       
   703 {
       
   704     data[id].setValue(value);
       
   705     activate(object, methodOffset + id, 0);
       
   706 }
       
   707 
       
   708 void QDeclarativeVMEMetaObject::writeVarProperty(int id, const QVariant &value)
       
   709 {
       
   710     if (value.userType() == QMetaType::QObjectStar) 
       
   711         data[id].setValue(qvariant_cast<QObject *>(value));
       
   712     else
       
   713         data[id].setValue(value);
       
   714     activate(object, methodOffset + id, 0);
       
   715 }
       
   716 
       
   717 void QDeclarativeVMEMetaObject::listChanged(int id)
       
   718 {
       
   719     activate(object, methodOffset + id, 0);
       
   720 }
       
   721 
       
   722 void QDeclarativeVMEMetaObject::list_append(QDeclarativeListProperty<QObject> *prop, QObject *o)
       
   723 {
       
   724     List *list = static_cast<List *>(prop->data);
       
   725     list->append(o);
       
   726     QMetaObject::activate(prop->object, list->notifyIndex, 0);
       
   727 }
       
   728 
       
   729 int QDeclarativeVMEMetaObject::list_count(QDeclarativeListProperty<QObject> *prop)
       
   730 {
       
   731     return static_cast<List *>(prop->data)->count();
       
   732 }
       
   733 
       
   734 QObject *QDeclarativeVMEMetaObject::list_at(QDeclarativeListProperty<QObject> *prop, int index)
       
   735 {
       
   736     return static_cast<List *>(prop->data)->at(index);
       
   737 }
       
   738 
       
   739 void QDeclarativeVMEMetaObject::list_clear(QDeclarativeListProperty<QObject> *prop)
       
   740 {
       
   741     List *list = static_cast<List *>(prop->data);
       
   742     list->clear();
       
   743     QMetaObject::activate(prop->object, list->notifyIndex, 0);
       
   744 }
       
   745 
       
   746 void QDeclarativeVMEMetaObject::registerInterceptor(int index, int valueIndex, QDeclarativePropertyValueInterceptor *interceptor)
       
   747 {
       
   748     if (aInterceptors.isEmpty())
       
   749         aInterceptors.resize(propertyCount() + metaData->propertyCount);
       
   750     aInterceptors.setBit(index);
       
   751     interceptors.insert(index, qMakePair(valueIndex, interceptor));
       
   752 }
       
   753 
       
   754 QScriptValue QDeclarativeVMEMetaObject::vmeMethod(int index)
       
   755 {
       
   756     if (index < methodOffset) {
       
   757         Q_ASSERT(parent);
       
   758         return static_cast<QDeclarativeVMEMetaObject *>(parent)->vmeMethod(index);
       
   759     }
       
   760     int plainSignals = metaData->signalCount + metaData->propertyCount + metaData->aliasCount;
       
   761     Q_ASSERT(index >= (methodOffset + plainSignals) && index < (methodOffset + plainSignals + metaData->methodCount));
       
   762     return method(index - methodOffset - plainSignals);
       
   763 }
       
   764 
       
   765 QScriptValue QDeclarativeVMEMetaObject::vmeProperty(int index)
       
   766 {
       
   767     if (index < propOffset) {
       
   768         Q_ASSERT(parent);
       
   769         return static_cast<QDeclarativeVMEMetaObject *>(parent)->vmeProperty(index);
       
   770     }
       
   771     return readVarProperty(index - propOffset);
       
   772 }
       
   773 
       
   774 void QDeclarativeVMEMetaObject::setVMEProperty(int index, const QScriptValue &v)
       
   775 {
       
   776     if (index < propOffset) {
       
   777         Q_ASSERT(parent);
       
   778         static_cast<QDeclarativeVMEMetaObject *>(parent)->setVMEProperty(index, v);
       
   779     }
       
   780     return writeVarProperty(index - propOffset, v);
       
   781 }
       
   782 
       
   783 QT_END_NAMESPACE