//
#include <private/qqmlrefcount_p.h>
+#include <private/qflagpointer_p.h>
#include "qqmlcleanup_p.h"
#include "qqmlnotifier_p.h"
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
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)
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; }
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; }
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) &&
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 {
};
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
};
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
QString name(QObject *);
QString name(const QMetaObject *);
+ void markAsOverrideOf(QQmlPropertyData *predecessor);
+
private:
friend class QQmlPropertyCache;
void lazyLoad(const QMetaProperty &, QQmlEngine *engine = 0);
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 *);
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();
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;
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;
overrideIndexIsProperty = false;
overrideIndex = -1;
revision = 0;
- metaObjectOffset = -1;
+ metaObjectOffset = -1;
flags = 0;
}
coreIndex == other.coreIndex &&
notifyIndex == other.notifyIndex &&
revision == other.revision &&
- (!isValueTypeVirtual() ||
- (valueTypeCoreIndex == other.valueTypeCoreIndex &&
+ (!isValueTypeVirtual() ||
+ (valueTypeCoreIndex == other.valueTypeCoreIndex &&
valueTypePropType == other.valueTypePropType));
}
int QQmlPropertyRawData::encodedIndex() const
{
- return isValueTypeVirtual()?(coreIndex | (valueTypeCoreIndex << 24)):coreIndex;
+ return isValueTypeVirtual()?(coreIndex | (valueTypeCoreIndex << 16)):coreIndex;
}
QQmlPropertyData *
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