具有未知列表模板参数的QVariant到QList

时间:2013-01-30 09:37:27

标签: c++ qt

我有几个QObject类,可能有QList个属性,用于存储QObject派生类的列表:

class Object : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QList<AnotherQObject*> otherObjects READ otherObjects)
public:
    QList<AnotherQObject*> otherObjects() const;
}

QList<AnotherObject*>当然已在Q_DECLARE_METATYPEqRegisterMetaType()注册。

现在我想用Qt的元对象系统读取这个属性。在我想要阅读列表的那一点上,我只关心(并且知道)列表包含指向对象的指针这一事实,这些指针来自QObject,但不是确切的类型。

当我将该属性的QVariant转换为QList<QObject *>时,该列表为空。

QObject *object = getObjectFromSomeWhere();
const char* propertyName = getPropertyNameFromSomeWhere(); // "otherObjects"

QVariant list = object->property(name);
QList<QObject *> objectList = list.value<QList<QObject *> >(); // empty

QList<AnotherQObject*> anotherObjectList = 
    static_cast<Object*>(object)->otherObjects() // not empty

是否可以访问此列表?你有其他建议吗?

编辑:虽然我发布了我的解决方案,但我仍然喜欢评论: - )

2 个答案:

答案 0 :(得分:3)

如果您使用的是Qt 5.2或更高版本,则可以使用QSequentialIterable类,而无需额外模板,修改后的宏和其他注册的开销。

http://qt-project.org/doc/qt-5/qsequentialiterable.html

如果QList<T*>中存储QVariant,其中T来自QObject,则可以从变体中获取QSequentialIterable个实例,这样您就可以迭代列表中的每个项目为QVariant。然后,您可以简单地将每个项目的值作为QObject*获取,然后添加到QList<QObject*>(确保您测试类型派生自QObject的假设) :

QList<QObject*> qobjectList;
if (variant.canConvert(QMetaType::QVariantList)) {
    QSequentialIterable iterable = variant.value<QSequentialIterable>();
    foreach (const QVariant& item, iterable) {
        QObject* object = item.value<QObject*>();
        if (object) { qobjectList.append(object); }
    }
}

答案 1 :(得分:2)

我认为我很简单地解决了这个问题。我创建了一个模板类,可以将包含QVariant的{​​{1}}转换为QList<TemplateParameter *>

我还有一个单例,它存储QList<QObject *>,从QMap<int, Converter *>映射到相应的转换器。

这允许我注册每个类,我想将它存储在属性中,如下所示:

QVariant::userType()

然后我可以转换未知的VariantToObjectListConverter::instance()->registerConverter<AnotherQObject>();

QVariants

这是必要的代码:

QVariant list = object->property("otherObjects");
QList<QObject *> objects = VariantToObjectListConverter::instance()->convert(variant);

我现在可以添加一个调用class ConverterBase { public: virtual ~ConverterBase() {} virtual QList<QObject *> convert(const QVariant &variant) const = 0; }; template<class Object> class Converter : public ConverterBase { public: QList<QObject *> convert(const QVariant &variant) const { QList<Object *> list = variant.value<QList<Object *> >(); QList<QObject *> result; Q_FOREACH(Object *object, list) result.append(object); return result; } }; class VariantToObjectListConverter { public: Q_GLOBAL_STATIC(VariantToObjectListConverter, instance) ~VariantToObjectListConverter() { QHashIterator<int, ConverterBase *> i(m_converters); while (i.hasNext()) { i.next(); delete i.value(); } } template<class Object> void registerConverter() { QVariant v = QVariant::fromValue<QList<Object *> >(QList<Object *>()); m_converters.insert(v.userType(), new Converter<Object>()); } QList<QObject *> convert(const QVariant &variant) const { ConverterBase *converter = m_converters.value(variant.userType()); if (!converter) return QList<QObject *>(); return converter->convert(variant); } private: QHash<int, ConverterBase *> m_converters; VariantToObjectListConverter() {} }; registerConverter()Q_DECLARE_METATYPE的宏,这样用户只需要调用

qRegisterMetaType()