Unsolved saving a custom Unit* class
-
I have a class which is a QObject and it has a member which is a Unit *.
The saving is complaining that it can not save a Unit *
[26.04 12:53:21 W] QVariant::save: unable to save type 'Unit*' (type id: 1362). ```I tried to register it with ``` qRegisterMetaTypeStreamOperators
/usr/include/qt/QtCore/qvariant.h:465: error: 'QVariant::QVariant(void*)' is private inline QVariant(void *) Q_DECL_EQ_DELETE; ``` ^ Here is my loading and saving mechanism
void Profile::save(QSettings& settings) const {
for(int i=0; i<metaObject()->propertyCount(); ++i) {
const auto& p = metaObject()->property(i);
if(p.isStored(this)) {
settings.setValue(p.name(), property(p.name()));
}
}
}void Profile::load(QSettings& settings) {
for(int i=0; i<metaObject()->propertyCount(); ++i) {
const auto& p = metaObject()->property(i);
if(p.isStored(this)) {
setProperty(p.name(), settings.value(p.name()));
}
}
}here is my unit class
Unit::Unit(int unit, QObject *parent)
: EraObject(parent),
m_value(0.0),
m_unit(unit)
{
connect(eApp->systemController()->unitManager(),&UnitManager::onUnitChanged,this,&Unit::changeUnit);
}Unit::Unit(const Unit &other)
{
m_value = other.m_value;
m_unit = other.m_unit;
qRegisterMetaTypeStreamOperators<Unit*>("Unit*");
}Unit &Unit::operator=(const qreal value)
{
if (m_value == value)
return *this;m_value = value; emit userValueChanged(); return *this;
}
void Unit::loadFrom(Settings &set, bool ownGroup)
{
Q_UNUSED(ownGroup)
if(set.contains(objectName())) {
m_value = set.value(objectName(),0.0).toDouble();
emit userValueChanged();
}
}void Unit::saveTo(Settings &set, bool ownGroup, bool force)
{
Q_UNUSED(ownGroup)
Q_UNUSED(force)
set.setValue(objectName(),m_value);
}Unit::operator qreal() const
{
return m_value;
}qreal Unit::userValue() const
{
return isDefault() ? m_value : UnitManager::convertTo(m_value,m_unit);
}QString Unit::symbol() const
{
return UnitManager::symbolName(m_unit);
}void Unit::setUserValue(const qreal userValue)
{
qDebug() << "setUserValue" << this->userValue() << userValue << QString::number(m_unit,2);
if (this->userValue() == userValue)
return;if(isDefault()) m_value = userValue; else m_value = UnitManager::convertFrom(userValue,m_unit); qDebug() << "Value" << m_value; emit userValueChanged(); setDirty(RamDirty);
}
void Unit::setup(quint32 unit, const QString name, QObject *parent)
{
if(!m_unit)
m_unit = (unit << 16);
setObjectName(name);
setParent(parent);
connectDirtyWithParent(parent);
}void Unit::changeUnit(const quint32 &unit)
{
if(m_unit == unit || category() != (unit >> 16))
return;
m_unit = unit;
emit userValueChanged();
emit symbolChanged();
} -
Hi,
Did you also implement the stream operators ?
Note that there's something wrong going on here. You have implement a copy operator for your QObject based class which wrong. QObject is note a copyable class, see here for more information.
-
I implemented the stream operators >> and << and still I can't save the qobject pointer into the file settings. I don't know why. what else do you need to dig for the problem ?
and thanks for the note
-
Can you share your operators implementation ?
-
why I can't save a pointer qproperty like Unit*.
that's what the error says
QVariant::save: unable to save type 'Unit*' -
I don't know since you didn't share the complete code. Anyway, here is a dummy implementation that shows how it works:
class MyObject : public QObject { public: MyObject(QObject *parent = 0) : QObject(parent) {} QString foo() const { return _foo; } void setFoo(const QString& foo) { _foo = foo; } private: QString _foo; }; QDataStream &operator<<(QDataStream &ds, MyObject *object) { ds << object->foo(); return ds; } QDataStream &operator>>(QDataStream &ds, MyObject *object) { QString foo; ds >> foo; object->setFoo(foo); return ds; } QDebug operator<<(QDebug dbg, MyObject *object) { dbg << object->metaObject()->className() << object->foo(); return dbg; } Q_DECLARE_METATYPE(MyObject *) int main(int argc, char *argv[]) { QApplication app(argc, argv); qRegisterMetaType<MyObject *>(); qRegisterMetaTypeStreamOperators<MyObject *>(); MyObject *object = new MyObject; object->setFoo("myfoo"); QBuffer buffer; buffer.open(QBuffer::WriteOnly); QDataStream ds(&buffer); ds << object; buffer.close(); // later buffer.open(QBuffer::ReadOnly); ds.setDevice(&buffer); MyObject *object2 = new MyObject; ds >> object2; qDebug() << object2; delete object; delete object2; return 0; }
-
I'm trying to define the operators >> and << for a custom class called Unit, and I need to store a pointer.
here is how I define the functions
QDataStream &operator<<(QDataStream &out, const Unit *unit)
{
out << unit->value();
return out;
}QDataStream &operator>>(QDataStream &in, Unit *unit)
{
double value;
in >> value;
unit->setUserValue(value);
return in;
}void Unit::setUserValue(const qreal userValue)
{
qDebug() << "setUserValue" << this->userValue() << userValue << QString::number(m_unit,2);
if (this->userValue() == userValue)
return;if(isDefault()) m_value = userValue; else m_value = UnitManager::convertFrom(userValue,m_unit); qDebug() << "Value" << m_value; emit userValueChanged(); setDirty(RamDirty);
}
qRegisterMetaType<Unit*>();
qRegisterMetaTypeStreamOperators<Unit *>();
I'm getting the following compilation error messageerror: no match for 'operator>>' (operand types are 'QDataStream' and 'Unit*')
and also an error here/usr/include/qt/QtCore/qmetatype.h:771: error: invalid initialization of non-const reference of type 'quint8& {aka unsigned char&}' from an rvalue of type 'quint8 {aka unsigned char}'
stream >> static_cast<T>(t);
^
I also defined the meta typeQ_DECLARE_METATYPE(Unit)
Q_DECLARE_METATYPE(Unit*) -
Unit is a QObject base class you shouldn't call
Q_DECLARE_METATYPE
on it.Where are you doing the declaration and registrations ?
-
I'm doing it in main()
-
Something's wrong with your streaming operations, you don't save and load the same formats you use for your class. You have qreal on one side then double on another side.
You should really be precise when doing such operations.
-
I'm still getting the following error
/usr/include/qt/QtCore/qmetatype.h:771: error: no match for 'operator>>' (operand types are 'QDataStream' and 'Unit') stream >> *static_cast<T*>(t); ^
QDataStream &operator<<(QDataStream &out, const Unit *&unit) { out << unit->value(); return out; } QDataStream &operator>>(QDataStream &in, Unit *&unit) { qreal value; in >> value; unit->setUserValue(value); return in; }
In MAIN I define
qRegisterMetaType<Unit*>(); qRegisterMetaTypeStreamOperators<Unit *>(); ```in the header of Unit.h I define
Q_DECLARE_METATYPE(Unit*)
Q_DECLARE_METATYPE(Unit) -
@AndreAhmed said:
/usr/include/qt/QtCore/qmetatype.h:771: error: no match for 'operator>>' (operand types are 'QDataStream' and 'Unit')
stream >> static_cast<T>(t);Follow the compiler's error description! You're trying to save an instance of the class (i.e. an object), then you provide operators for saving a pointer to that class ... the compiler can't match one to the other.
QDataStream &operator>>(QDataStream &out, Unit *&unit)
is quite different from:
QDataStream &operator>>(QDataStream &out, Unit &unit) //< This is what you're invoking with stream >> *static_cast<Unit*>(t);
Additionally, don't pass pointer references, unless you intend on changing them ... this could have unforeseen consequences if in the implementation you do something along the lines of:
unit = nullptr;
for example.
Best is to even make a further step (although it's often considered quite over-protective) and make sure the pointer will not be moved, not only that it's pointing to a const object:
QDataStream &operator<<(QDataStream &out, const Unit * const unit) //< Forbid moving the pointer inside the implementation, not only modifying the object { } QDataStream & operator >> (QDataStream & in, Unit * const unit) //< Again, the pointer is constant, can't be modified, the object is not though { }