我想覆盖QObject::setProperty(const char*, QVariant)
,因为当我使用包含QVariant
的{{1}}调用此方法时,该方法会失败,因为它不会将QVariantList
转换为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
数据列表已损坏。
答案 0 :(得分:0)
使用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) );