Enum在QMetaObject中的分布:
QMetaEnum 类用来管理对应的enum结构,方面查询等操作,下面是它的定义
class Q_CORE_EXPORT QMetaEnum
{
public:
Q_DECL_CONSTEXPR inline QMetaEnum() : mobj(Q_NULLPTR), handle(0) {}
const char *name() const;
bool isFlag() const;
int keyCount() const;
const char *key(int index) const;
int value(int index) const;
const char *scope() const;
int keyToValue(const char *key, bool *ok = Q_NULLPTR) const;
const char* valueToKey(int value) const;
int keysToValue(const char * keys, bool *ok = Q_NULLPTR) const;
QByteArray valueToKeys(int value) const;
inline const QMetaObject *enclosingMetaObject() const { return mobj; }
inline bool isValid() const { return name() != Q_NULLPTR; }
template<typename T> static QMetaEnum fromType() {
Q_STATIC_ASSERT_X(QtPrivate::IsQEnumHelper<T>::Value,
"QMetaEnum::fromType only works with enums declared as Q_ENUM or Q_FLAG");
const QMetaObject *metaObject = qt_getEnumMetaObject(T());
const char *name = qt_getEnumName(T());
return metaObject->enumerator(metaObject->indexOfEnumerator(name));
}
private:
const QMetaObject *mobj;
uint handle;
friend struct QMetaObject;
};
const QMetaObject *mobj;
uint handle;
所有的操作基于这两个成员,hadnle 是该枚举节 相对整个结构的偏移量
1、const char *QMetaEnum::name() const 返回枚举类型的名称字符串
const char *QMetaEnum::name() const
{
if (!mobj)
return 0;
return rawStringData(mobj, mobj->d.data[handle]);
}
2、int QMetaEnum::keyCount() const 返回Key的数量
int QMetaEnum::keyCount() const
{
if (!mobj)
return 0;
return mobj->d.data[handle + 2]; 枚举节的第三个int值是Key的数量
}
3、const char *QMetaEnum::key(int index) const 返回index索引的Key的名称字符串
const char *QMetaEnum::key(int index) const
{
if (!mobj)
return 0;
int count = mobj->d.data[handle + 2]; 数量
int data = mobj->d.data[handle + 3]; Key节的偏移
if (index >= 0 && index < count)
return rawStringData(mobj, mobj->d.data[data + 2*index]); 每个Key节 两个Int
return 0;
}
4、int QMetaEnum:: value (int index) const 返回index索引的Key的值
int QMetaEnum::value(int index) const
{
if (!mobj)
return 0;
int count = mobj->d.data[handle + 2];
int data = mobj->d.data[handle + 3];
if (index >= 0 && index < count)
return mobj->d.data[data + 2*index + 1]; Key节的第二个Int是其值
return -1;
}
5、 bool QMetaEnum:: isFlag() const 是否使用标记
/*!
Returns \c true if this enumerator is used as a flag; otherwise returns
false.
When used as flags, enumerators can be combined using the OR
operator.
\sa keysToValue(), valueToKeys()
*/
bool QMetaEnum::isFlag() const
{
return mobj && mobj->d.data[handle + 1];
}
6、const char *QMetaEnum::scope() const 返回所属类名
const char *QMetaEnum::scope() const
{
return mobj ? objectClassName(mobj) : 0;
}
7、int QMetaEnum:: keyToValue (const char *key, bool *ok) const 根据Key名返回对应的值
int QMetaEnum::keyToValue(const char *key, bool *ok) const
{
if (ok != 0)
*ok = false;
if (!mobj || !key)
return -1;
uint scope = 0;
const char *qualified_key = key;
const char *s = key + qstrlen(key);
while (s > key && *s != ':')
--s;
if (s > key && *(s-1)==':') {
scope = s - key - 1;
key += scope + 2;
}
int count = mobj->d.data[handle + 2];
int data = mobj->d.data[handle + 3];
for (int i = 0; i < count; ++i) {
const QByteArray className = stringData(mobj, priv(mobj->d.data)->className);
if ((!scope || (className.size() == int(scope) && strncmp(qualified_key, className.constData(), scope) == 0))
&& strcmp(key, rawStringData(mobj, mobj->d.data[data + 2*i])) == 0) {
if (ok != 0)
*ok = true;
return mobj->d.data[data + 2*i + 1];
}
}
return -1;
}
8、const char* QMetaEnum::valueToKey(int value) const 根据值返回Key 名
const char* QMetaEnum::valueToKey(int value) const
{
if (!mobj)
return 0;
int count = mobj->d.data[handle + 2];
int data = mobj->d.data[handle + 3];
for (int i = 0; i < count; ++i)
if (value == (int)mobj->d.data[data + 2*i + 1])
return rawStringData(mobj, mobj->d.data[data + 2*i]);
return 0;
}