正在重写QObject::setProperty

Overriding QObject::setProperty

本文关键字:setProperty QObject 重写      更新时间:2023-10-16

我想重写QObject::setProperty(const char*, QVariant),因为当我用包含QVariantListQVariant调用此方法时,该方法会失败,因为它没有将QVariantList转换为QList<UnknownType>

有什么建议吗?

编辑

我有一个包含的抽象类Node

Context* _context;
QMap<QString, QString> _inputsPersisted;
QMap<QString, QString> _outputsPersisted;

Node类还有一个virtual void runImplementation()和方法void run(),如下所示:

void Node::run()
{
    //get inputs from Context
    for(QMap<QString, QString>::iterator it = _inputsPersisted.begin() ; it != _inputsPersisted.end() ; ++it )
    {        
        QVariant attribute = property(it.key().toStdString().c_str());
        if(!attribute.isValid())
        {
            qWarning() << QObject::tr("%1:%2: Node::run:%3: the property %4 does not exist.").arg(__FILE__).arg(__LINE__).arg(_id.toString()).arg(it.key());
        }
        else
        {
            QVariant v = _context->getDataPersisted(it.value());
            if(!v.isValid())
                qWarning() << QObject::tr("%1:%2: Node::run:%3: %4 is not in the context.").arg(__FILE__).arg(__LINE__).arg(_id.toString()).arg(it.value());
            else
                if(v.type() != attribute.type())
                    qWarning() << QObject::tr("%1:%2: Node::run:%3: %4 and %5 have not the same type.").arg(__FILE__).arg(__LINE__).arg(_id.toString()).arg(it.key()).arg(it.value());
                else
                    if(!setProperty(it.key().toStdString().c_str(), v))
                        qWarning() << QObject::tr("%1:%2: Node::run:%3: the property %4 have not been setted.").arg(__FILE__).arg(__LINE__).arg(_id.toString()).arg(it.key());
        }
    }
    runImplementation();
    //set outputs in the Context        
    for(QMap<QString, QString>::iterator it = _outputsPersisted.begin() ; it != _outputsPersisted.end() ; ++it )
    {
        QVariant attribute = property(it.key().toStdString().c_str());
        if(!attribute.isValid())
        {
            qWarning() << QObject::tr("%1:%2: Node::run:%3: the property %4 does not exist.").arg(__FILE__).arg(__LINE__).arg(_id.toString()).arg(it.key());
        }
        else
        {
            _context->setDataPersisted(it.value(), attribute);
        }
   }

}

Context类如下:

class Context : public QObject
{
Q_OBJECT
public:
Context(Context* parent = NULL) : : _parent(parent){}
void setDataPersisted(QString name, QVariant value)
{
    if(_parent != NULL && _parent->exist(name))
        _parent->setDataPersisted(name, value);
    else
    {
        if(_stack.contains(name))
            _stack.insert(name, value);
        else
            _stack.insert(name, value);
     }
}
QVariant getDataPersisted(QString name)
{
    QVariant v;
    QMap<QString, QVariant>::iterator it = _stack.find(name);
    if(it != _stack.end())
        v.setValue(it.value());
    else
        if(_parent != NULL)
            v.setValue(_parent->getDataPersisted(name));
    return v;
}
private:
bool exist(QString name)
{
    bool contains = _stack.contains(name);
    return contains || ((_parent != NULL) && (_parent->exist(name)));
}
private:
    Context * _parent;
    QMap<QString, QVariant> _stack;
};

有了这个,Node子类可以在她的Context中放入和获取一些变量,而这只需要声明她的属性并初始化_inputsPersisted_outputsPersisted。所有的逻辑都是由Node类完成的。

现在我想添加一个机制。我想在Context中操作列表并执行append。为此,我修改了Context::setDataPersisted方法:

void setDataPersisted(QString name, QVariant value)
{
    if(_parent != NULL && _parent->exist(name))
        _parent->setDataPersisted(name, value);
    else
    {
        if(_stack.contains(name) && _stack.find(name)->value().canConvert(QVariant::List))
        {
            QVariantList toChange = qvariant_cast<QVariantList>(_stack.find(name)->value());
            toChange.append(value);
            _stack.insert(name, toChange );
        }
        else
            _stack.insert(name, value);
     }
}

这样,在setDataPersited、另一个setDataPersisted("附加")和getDataPersisted之后,数据的列表就会损坏。

使用Q_DECLARE_METATYPE宏在Qt元类型系统中注册QVariantList。这将允许将QVariantList存储为QVariant

    Q_DECLARE_METATYPE(QVariantList);
...
    QVariantList var;
    QVariant v = QVariant::fromValue<QVariantList>( var );
    QVariantList lst = v.value<QVariantList>();

QList<SomeType>转换为QVariantList:

QList<SomeType> lst1;
...
QVariantList    lst2;
for (const SomeType& st : lst1)
    lst2.append( QVariant::fromValue<SomeType>( st ) ); 

QVariantList转换为QList<SomeType>:

QVariantList    lst2;
...
QList<SomeType> lst1;
for (const QVariant& st : lst2)
    lst2.append( st.value<SomeType>() ); 

编辑1:

auto it = _stack.find(name);
if (_stack.end() == it) {
    it = _stack.insert( name, QVariant::fromValue<QVariantList>(QVariantList()) );
}
QVariantList toChange = it->value().value<QVariantList>();
toChange.append(value);
_stack.insert(name, QVariant::fromValue<QVariantList>(toChange) );