Fix leak introduced in 0853343c33e394f35c31c161b019b2aed17f9256.
[profile/ivi/qtdeclarative.git] / src / qml / qml / qqmlpropertycache_p.h
index a128cd9..ad94ed4 100644 (file)
@@ -54,6 +54,7 @@
 //
 
 #include <private/qqmlrefcount_p.h>
+#include <private/qflagpointer_p.h>
 #include "qqmlcleanup_p.h"
 #include "qqmlnotifier_p.h"
 
@@ -69,7 +70,9 @@ class QV8QObjectWrapper;
 class QQmlEngine;
 class QQmlPropertyData;
 class QQmlAccessors;
+class QMetaObjectBuilder;
 class QQmlPropertyCacheMethodArguments;
+class QQmlVMEMetaObject;
 
 // We have this somewhat awful split between RawData and Data so that RawData can be
 // used in unions.  In normal code, you should always use Data which initializes RawData
@@ -87,32 +90,38 @@ public:
         IsResettable       = 0x00000004, // Has RESET function
         IsAlias            = 0x00000008, // Is a QML alias to another property
         IsFinal            = 0x00000010, // Has FINAL flag
-        IsDirect           = 0x00000020, // Exists on a C++ QMetaObject
-        HasAccessors       = 0x00000040, // Has property accessors
+        IsOverridden       = 0x00000020, // Is overridden by a extension property
+        IsDirect           = 0x00000040, // Exists on a C++ QMetaObject
+        HasAccessors       = 0x00000080, // Has property accessors
 
         // These are mutualy exclusive
-        IsFunction         = 0x00000080, // Is an invokable
-        IsQObjectDerived   = 0x00000100, // Property type is a QObject* derived type
-        IsEnumType         = 0x00000200, // Property type is an enum
-        IsQList            = 0x00000400, // Property type is a QML list
-        IsQmlBinding       = 0x00000800, // Property type is a QQmlBinding*
-        IsQJSValue         = 0x00001000, // Property type is a QScriptValue
-        IsV8Handle         = 0x00002000, // Property type is a QQmlV8Handle
-        IsVMEProperty      = 0x00004000, // Property type is a "var" property of VMEMO
-        IsValueTypeVirtual = 0x00008000, // Property is a value type "virtual" property
-        IsQVariant         = 0x00010000, // Property is a QVariant
+        IsFunction         = 0x00000100, // Is an invokable
+        IsQObjectDerived   = 0x00000200, // Property type is a QObject* derived type
+        IsEnumType         = 0x00000400, // Property type is an enum
+        IsQList            = 0x00000800, // Property type is a QML list
+        IsQmlBinding       = 0x00001000, // Property type is a QQmlBinding*
+        IsQJSValue         = 0x00002000, // Property type is a QScriptValue
+        IsV8Handle         = 0x00004000, // Property type is a QQmlV8Handle
+        IsVarProperty      = 0x00008000, // Property type is a "var" property of VMEMO
+        IsValueTypeVirtual = 0x00010000, // Property is a value type "virtual" property
+        IsQVariant         = 0x00020000, // Property is a QVariant
 
         // Apply only to IsFunctions
-        IsVMEFunction      = 0x00020000, // Function was added by QML
-        HasArguments       = 0x00040000, // Function takes arguments
-        IsSignal           = 0x00080000, // Function is a signal
-        IsVMESignal        = 0x00100000, // Signal was added by QML
-        IsV8Function       = 0x00200000, // Function takes QQmlV8Function* args
-        IsSignalHandler    = 0x00400000, // Function is a signal handler
-        IsOverload         = 0x00800000, // Function is an overload of another function
+        IsVMEFunction      = 0x00040000, // Function was added by QML
+        HasArguments       = 0x00080000, // Function takes arguments
+        IsSignal           = 0x00100000, // Function is a signal
+        IsVMESignal        = 0x00200000, // Signal was added by QML
+        IsV8Function       = 0x00400000, // Function takes QQmlV8Function* args
+        IsSignalHandler    = 0x00800000, // Function is a signal handler
+        IsOverload         = 0x01000000, // Function is an overload of another function
+        IsCloned           = 0x02000000, // The function was marked as cloned
 
         // Internal QQmlPropertyCache flags
-        NotFullyResolved   = 0x01000000  // True if the type data is to be lazily resolved
+        NotFullyResolved   = 0x04000000, // True if the type data is to be lazily resolved
+
+        // Flags that are set based on the propType field
+        PropTypeFlagMask = IsQObjectDerived | IsEnumType | IsQList | IsQmlBinding | IsQJSValue |
+                           IsV8Handle | IsQVariant,
     };
     Q_DECLARE_FLAGS(Flags, Flag)
 
@@ -126,6 +135,7 @@ public:
     bool isResettable() const { return flags & IsResettable; }
     bool isAlias() const { return flags & IsAlias; }
     bool isFinal() const { return flags & IsFinal; }
+    bool isOverridden() const { return flags & IsOverridden; }
     bool isDirect() const { return flags & IsDirect; }
     bool hasAccessors() const { return flags & HasAccessors; }
     bool isFunction() const { return flags & IsFunction; }
@@ -135,7 +145,7 @@ public:
     bool isQmlBinding() const { return flags & IsQmlBinding; }
     bool isQJSValue() const { return flags & IsQJSValue; }
     bool isV8Handle() const { return flags & IsV8Handle; }
-    bool isVMEProperty() const { return flags & IsVMEProperty; }
+    bool isVarProperty() const { return flags & IsVarProperty; }
     bool isValueTypeVirtual() const { return flags & IsValueTypeVirtual; }
     bool isQVariant() const { return flags & IsQVariant; }
     bool isVMEFunction() const { return flags & IsVMEFunction; }
@@ -145,6 +155,7 @@ public:
     bool isV8Function() const { return flags & IsV8Function; }
     bool isSignalHandler() const { return flags & IsSignalHandler; }
     bool isOverload() const { return flags & IsOverload; }
+    bool isCloned() const { return flags & IsCloned; }
 
     bool hasOverride() const { return !(flags & IsValueTypeVirtual) &&
                                       !(flags & HasAccessors) &&
@@ -155,7 +166,7 @@ public:
     inline int getValueTypeCoreIndex() const;
 
     // Returns the "encoded" index for use with bindings.  Encoding is:
-    //     coreIndex | (valueTypeCoreIndex << 24)
+    //     coreIndex | (valueTypeCoreIndex << 16)
     inline int encodedIndex() const;
 
     union {
@@ -164,6 +175,8 @@ public:
     };
     int coreIndex;
     union {
+        // The notify index is in the range returned by QObjectPrivate::signalIndex().
+        // This is different from QMetaMethod::methodIndex().
         int notifyIndex;  // When !IsFunction
         void *arguments;  // When IsFunction && HasArguments
     };
@@ -177,10 +190,10 @@ public:
                 struct { // When IsValueTypeVirtual
                     quint16 valueTypeFlags; // flags of the access property on the value type proxy
                                             // object
-                    quint8 valueTypePropType; // The QVariant::Type of access property on the value
-                                              // type proxy object
-                    quint8 valueTypeCoreIndex; // The prop index of the access property on the value
+                    quint16 valueTypePropType; // The QVariant::Type of access property on the value
                                                // type proxy object
+                    quint16 valueTypeCoreIndex; // The prop index of the access property on the value
+                                                // type proxy object
                 };
 
                 struct { // When !IsValueTypeVirtual
@@ -216,6 +229,8 @@ public:
     QString name(QObject *);
     QString name(const QMetaObject *);
 
+    void markAsOverrideOf(QQmlPropertyData *predecessor);
+
 private:
     friend class QQmlPropertyCache;
     void lazyLoad(const QMetaProperty &, QQmlEngine *engine = 0);
@@ -223,7 +238,7 @@ private:
     bool notFullyResolved() const { return flags & NotFullyResolved; }
 };
 
-class Q_QML_EXPORT QQmlPropertyCache : public QQmlRefCount, public QQmlCleanup
+class Q_QML_PRIVATE_EXPORT QQmlPropertyCache : public QQmlRefCount, public QQmlCleanup
 {
 public:
     QQmlPropertyCache(QQmlEngine *);
@@ -243,35 +258,74 @@ public:
                 QQmlPropertyData::Flag methodFlags = QQmlPropertyData::NoFlags,
                 QQmlPropertyData::Flag signalFlags = QQmlPropertyData::NoFlags);
 
-    void append(QQmlEngine *, const QMetaObject *,
-                QQmlPropertyData::Flag propertyFlags = QQmlPropertyData::NoFlags,
-                QQmlPropertyData::Flag methodFlags = QQmlPropertyData::NoFlags,
-                QQmlPropertyData::Flag signalFlags = QQmlPropertyData::NoFlags);
-    void append(QQmlEngine *, const QMetaObject *, int revision,
-                QQmlPropertyData::Flag propertyFlags = QQmlPropertyData::NoFlags,
-                QQmlPropertyData::Flag methodFlags = QQmlPropertyData::NoFlags,
-                QQmlPropertyData::Flag signalFlags = QQmlPropertyData::NoFlags);
+    QQmlPropertyCache *copyAndReserve(QQmlEngine *, int propertyCount,
+                                      int methodCount, int signalCount);
+    void appendProperty(const QString &,
+                        quint32 flags, int coreIndex, int propType, int notifyIndex);
+    void appendProperty(const QHashedCStringRef &,
+                        quint32 flags, int coreIndex, int propType, int notifyIndex);
+    void appendSignal(const QString &, quint32, int coreIndex, const int *types = 0,
+                      const QList<QByteArray> &names = QList<QByteArray>());
+    void appendSignal(const QHashedCStringRef &, quint32, int coreIndex, const int *types = 0,
+                      const QList<QByteArray> &names = QList<QByteArray>());
+    void appendMethod(const QString &, quint32 flags, int coreIndex,
+                      const QList<QByteArray> &names = QList<QByteArray>());
+    void appendMethod(const QHashedCStringRef &, quint32 flags, int coreIndex,
+                      const QList<QByteArray> &names = QList<QByteArray>());
+
+    const QMetaObject *metaObject() const;
+    const QMetaObject *createMetaObject();
+    const QMetaObject *firstCppMetaObject() const;
+
+    template<typename K>
+    QQmlPropertyData *property(const K &key, QObject *object, QQmlContextData *context) const
+    {
+        return findProperty(stringCache.find(key), object, context);
+    }
 
-    inline QQmlPropertyData *property(const QHashedV8String &) const;
-    QQmlPropertyData *property(const QHashedStringRef &) const;
-    QQmlPropertyData *property(const QHashedCStringRef &) const;
-    QQmlPropertyData *property(const QString &) const;
     QQmlPropertyData *property(int) const;
     QQmlPropertyData *method(int) const;
+    QQmlPropertyData *signal(int index) const { return signal(index, 0); }
+    int methodIndexToSignalIndex(int) const;
     QStringList propertyNames() const;
 
+    QString defaultPropertyName() const;
+    QQmlPropertyData *defaultProperty() const;
+    QQmlPropertyCache *parent() const;
+
     inline QQmlPropertyData *overrideData(QQmlPropertyData *) const;
     inline bool isAllowedInRevision(QQmlPropertyData *) const;
 
     inline QQmlEngine *qmlEngine() const;
     static QQmlPropertyData *property(QQmlEngine *, QObject *, const QString &,
-                                              QQmlPropertyData &);
+                                              QQmlContextData *, QQmlPropertyData &);
     static QQmlPropertyData *property(QQmlEngine *, QObject *, const QHashedV8String &,
-                                              QQmlPropertyData &);
+                                              QQmlContextData *, QQmlPropertyData &);
     static int *methodParameterTypes(QObject *, int index, QVarLengthArray<int, 9> &dummy,
                                      QByteArray *unknownTypeError);
+    static int methodReturnType(QObject *, const QQmlPropertyData &data,
+                                QByteArray *unknownTypeError);
+
+    //see QMetaObjectPrivate::originalClone
+    int originalClone(int index);
+    static int originalClone(QObject *, int index);
+
+    QList<QByteArray> signalParameterNames(int index) const;
+    QString signalParameterStringForJS(int index, int *count = 0, QString *errorString = 0);
+
+    const char *className() const;
+
+    inline int propertyCount() const;
+    inline int propertyOffset() const;
+    inline int methodCount() const;
+    inline int methodOffset() const;
+    inline int signalCount() const;
+    inline int signalOffset() const;
 
     static bool isDynamicMetaObject(const QMetaObject *);
+
+    void toMetaObjectBuilder(QMetaObjectBuilder &);
+
 protected:
     virtual void destroy();
     virtual void clear();
@@ -279,25 +333,52 @@ protected:
 private:
     friend class QQmlEnginePrivate;
     friend class QV8QObjectWrapper;
+    friend class QQmlCompiler;
 
     inline QQmlPropertyCache *copy(int reserve);
 
+    void append(QQmlEngine *, const QMetaObject *, int revision,
+                QQmlPropertyData::Flag propertyFlags = QQmlPropertyData::NoFlags,
+                QQmlPropertyData::Flag methodFlags = QQmlPropertyData::NoFlags,
+                QQmlPropertyData::Flag signalFlags = QQmlPropertyData::NoFlags);
+
     // Implemented in v8/qv8qobjectwrapper.cpp
     v8::Local<v8::Object> newQObject(QObject *, QV8Engine *);
 
+    QQmlPropertyData *signal(int, QQmlPropertyCache **) const;
+
     typedef QVector<QQmlPropertyData> IndexCache;
-    typedef QStringHash<QQmlPropertyData *> StringCache;
+    typedef QStringMultiHash<QPair<int, QQmlPropertyData *> > StringCache;
     typedef QVector<int> AllowedRevisionCache;
 
+    QQmlPropertyData *findProperty(StringCache::ConstIterator it, QObject *, QQmlContextData *) const;
+    QQmlPropertyData *findProperty(StringCache::ConstIterator it, const QQmlVMEMetaObject *, QQmlContextData *) const;
+
+    QQmlPropertyData *ensureResolved(QQmlPropertyData*) const;
+
     void resolve(QQmlPropertyData *) const;
     void updateRecur(QQmlEngine *, const QMetaObject *);
 
+    template<typename K>
+    QQmlPropertyData *findNamedProperty(const K &key)
+    {
+        StringCache::mapped_type *it = stringCache.value(key);
+        return it ? it->second : 0;
+    }
+
+    template<typename K>
+    void setNamedProperty(const K &key, int index, QQmlPropertyData *data, bool isOverride)
+    {
+        stringCache.insert(key, qMakePair(index, data));
+        _hasPropertyOverrides |= isOverride;
+    }
+
     QQmlEngine *engine;
-    
-    QQmlPropertyCache *parent;
+
+    QQmlPropertyCache *_parent;
     int propertyIndexCacheStart;
     int methodIndexCacheStart;
-    int signalHanderIndexCacheStart;
+    int signalHandlerIndexCacheStart;
 
     IndexCache propertyIndexCache;
     IndexCache methodIndexCache;
@@ -306,10 +387,49 @@ private:
     AllowedRevisionCache allowedRevisionCache;
     v8::Persistent<v8::Function> constructor;
 
-    const QMetaObject *metaObject;
+    bool _hasPropertyOverrides : 1;
+    bool _ownMetaObject : 1;
+    const QMetaObject *_metaObject;
+    QByteArray _dynamicClassName;
+    QByteArray _dynamicStringData;
+    QString _defaultPropertyName;
     QQmlPropertyCacheMethodArguments *argumentsCache;
 };
-  
+
+// QQmlMetaObject serves as a wrapper around either QMetaObject or QQmlPropertyCache.
+// This is necessary as we delay creation of QMetaObject for synthesized QObjects, but
+// we don't want to needlessly generate QQmlPropertyCaches every time we encounter a
+// QObject type used in assignment or when we don't have a QQmlEngine etc.
+//
+// This class does NOT reference the propertycache.
+class QQmlEnginePrivate;
+class Q_QML_EXPORT QQmlMetaObject
+{
+public:
+    inline QQmlMetaObject();
+    inline QQmlMetaObject(QObject *);
+    inline QQmlMetaObject(const QMetaObject *);
+    inline QQmlMetaObject(QQmlPropertyCache *);
+    inline QQmlMetaObject(const QQmlMetaObject &);
+
+    inline QQmlMetaObject &operator=(const QQmlMetaObject &);
+
+    inline bool isNull() const;
+
+    inline const char *className() const;
+    inline int propertyCount() const;
+
+    inline bool hasMetaObject() const;
+    inline const QMetaObject *metaObject() const;
+
+    QQmlPropertyCache *propertyCache(QQmlEnginePrivate *) const;
+
+    static bool canConvert(const QQmlMetaObject &from, const QQmlMetaObject &to);
+
+private:
+    QBiPointer<QQmlPropertyCache, const QMetaObject> _m;
+};
+
 QQmlPropertyData::QQmlPropertyData()
 {
     propType = 0;
@@ -318,7 +438,7 @@ QQmlPropertyData::QQmlPropertyData()
     overrideIndexIsProperty = false;
     overrideIndex = -1;
     revision = 0;
-    metaObjectOffset = -1; 
+    metaObjectOffset = -1;
     flags = 0;
 }
 
@@ -334,8 +454,8 @@ bool QQmlPropertyData::operator==(const QQmlPropertyRawData &other)
            coreIndex == other.coreIndex &&
            notifyIndex == other.notifyIndex &&
            revision == other.revision &&
-           (!isValueTypeVirtual() || 
-            (valueTypeCoreIndex == other.valueTypeCoreIndex && 
+           (!isValueTypeVirtual() ||
+            (valueTypeCoreIndex == other.valueTypeCoreIndex &&
              valueTypePropType == other.valueTypePropType));
 }
 
@@ -346,7 +466,7 @@ int QQmlPropertyRawData::getValueTypeCoreIndex() const
 
 int QQmlPropertyRawData::encodedIndex() const
 {
-    return isValueTypeVirtual()?(coreIndex | (valueTypeCoreIndex << 24)):coreIndex;
+    return isValueTypeVirtual()?(coreIndex | (valueTypeCoreIndex << 16)):coreIndex;
 }
 
 QQmlPropertyData *
@@ -372,11 +492,107 @@ QQmlEngine *QQmlPropertyCache::qmlEngine() const
     return engine;
 }
 
-QQmlPropertyData *QQmlPropertyCache::property(const QHashedV8String &str) const
+int QQmlPropertyCache::propertyCount() const
+{
+    return propertyIndexCacheStart + propertyIndexCache.count();
+}
+
+int QQmlPropertyCache::propertyOffset() const
+{
+    return propertyIndexCacheStart;
+}
+
+int QQmlPropertyCache::methodCount() const
+{
+    return methodIndexCacheStart + methodIndexCache.count();
+}
+
+int QQmlPropertyCache::methodOffset() const
+{
+    return methodIndexCacheStart;
+}
+
+int QQmlPropertyCache::signalCount() const
+{
+    return signalHandlerIndexCacheStart + signalHandlerIndexCache.count();
+}
+
+int QQmlPropertyCache::signalOffset() const
+{
+    return signalHandlerIndexCacheStart;
+}
+
+QQmlMetaObject::QQmlMetaObject()
+{
+}
+
+QQmlMetaObject::QQmlMetaObject(QObject *o)
+{
+    if (o) {
+        QQmlData *ddata = QQmlData::get(o, false);
+        if (ddata && ddata->propertyCache) _m = ddata->propertyCache;
+        else _m = o->metaObject();
+    }
+}
+
+QQmlMetaObject::QQmlMetaObject(const QMetaObject *m)
+: _m(m)
+{
+}
+
+QQmlMetaObject::QQmlMetaObject(QQmlPropertyCache *m)
+: _m(m)
+{
+}
+
+QQmlMetaObject::QQmlMetaObject(const QQmlMetaObject &o)
+: _m(o._m)
+{
+}
+
+QQmlMetaObject &QQmlMetaObject::operator=(const QQmlMetaObject &o)
+{
+    _m = o._m;
+    return *this;
+}
+
+bool QQmlMetaObject::isNull() const
+{
+    return _m.isNull();
+}
+
+const char *QQmlMetaObject::className() const
+{
+    if (_m.isNull()) {
+        return 0;
+    } else if (_m.isT1()) {
+        return _m.asT1()->className();
+    } else {
+        return _m.asT2()->className();
+    }
+}
+
+int QQmlMetaObject::propertyCount() const
+{
+    if (_m.isNull()) {
+        return 0;
+    } else if (_m.isT1()) {
+        return _m.asT1()->propertyCount();
+    } else {
+        return _m.asT2()->propertyCount();
+    }
+}
+
+bool QQmlMetaObject::hasMetaObject() const
+{
+    return _m.isT2() || (!_m.isNull() && _m.asT1()->metaObject());
+}
+
+const QMetaObject *QQmlMetaObject::metaObject() const
 {
-    QQmlPropertyData **rv = stringCache.value(str);
-    if (rv && (*rv)->notFullyResolved()) resolve(*rv);
-    return rv?*rv:0;
+    if (_m.isNull()) return 0;
+    if (_m.isT1()) return _m.asT1()->createMetaObject();
+    else return _m.asT2();
 }
 
 QT_END_NAMESPACE