0

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<Unit*>("Unit*"); but I get the following error

/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();
}

UPDATE:

now I tried to write

QDataStream& operator<<(QDataStream& out, const Unit& v) {
    out << v.userValue();
    return out;
}

QDataStream& operator>>(QDataStream& in, Unit& v) {
    in >> v.userValue();
    return in;
}

and I get

/home/ahmed/server/elec/software_t/backup17/checko5/eracommon5/src/cpp/system/unit/unit.cpp:21: error: ambiguous overload for 'operator<<' (operand types are 'QDataStream' and 'qreal {aka double}')
     out << v.userValue();
         ^

UPDATE2 :

QDataStream &Unit::operator <<(QDataStream &out,  Unit &val)
{
    out << val.userValue();
    return out;
}

QDataStream &Unit::operator >>(QDataStream &out,  Unit &val)
{
    in >> val.userValue();
    return in;
}

Update 3:

Unit::Unit(int unit, QObject *parent)
    : EraObject(parent),
      m_value(0.0),
      m_unit(unit)
{
    connect(eApp->systemController()->unitManager(),&UnitManager::onUnitChanged,this,&Unit::changeUnit);
    qRegisterMetaTypeStreamOperators<Unit>("Unit");

}

Unit::Unit(const Unit &other)
{
    m_value = other.m_value;
    m_unit = other.m_unit;
}


QDataStream &operator<<(QDataStream &out, const Unit &unit)
{
    out << unit.value();
    return out;
}
QDataStream &operator>>(QDataStream &in, Unit &unit)
{
    in >> unit.value();
    return in;
}
andreahmed
  • 135
  • 1
  • 1
  • 9
  • 1
    Are you trying to persist a pointer to file? – alediaferia Apr 26 '16 at 11:08
  • 3
    I think this is pretty much the same as: http://stackoverflow.com/questions/18144377/writing-and-reading-custom-class-to-qsettings – David van rijn Apr 26 '16 at 11:09
  • @Davidvanrijn I have read but I don't know how to use those code there – andreahmed Apr 26 '16 at 11:13
  • @alediaferia what should I do to save the value of the pointer in the file ? – andreahmed Apr 26 '16 at 11:14
  • when I write qRegisterMetaTypeStreamOperators("Unit*"); it says /usr/include/qt/QtCore/qvariant.h:465: error: 'QVariant::QVariant(void*)' is private inline QVariant(void *) Q_DECL_EQ_DELETE; ^ – andreahmed Apr 26 '16 at 11:17
  • above that error, it should either say something like `instantiated from here` or `within this context` with a file and a line number. This should tell you why it is trying to use this constructor. But i think it is because qRegisterMetaTypeStreamOperators<> doesn't take pointer types. – David van rijn Apr 26 '16 at 11:41
  • @Davidvanrijn so how would I save a Unit* to the file ? – andreahmed Apr 26 '16 at 11:44
  • @Davidvanrijn Can you write a full solution as answer please. I'm very much confued and don't know what to do – andreahmed Apr 26 '16 at 11:44
  • @alediaferia can you write an answer please ? – andreahmed Apr 26 '16 at 11:47
  • now its stored as ASTMD3828c\%20Default\Ta=@Variant(\0\0\0\x7f\0\0\0\x6Unit*\0) – andreahmed Apr 26 '16 at 11:48
  • Remove the non-const overload of `ostream::operator<<" and see if that solves the overload resolution problem. – jonspaceharper Apr 26 '16 at 12:00
  • @JonHarper see my updated code, now I get /home/ahmed/server/elec/software_t/backup17/checko5/eracommon5/src/cpp/system/unit/unit.cpp:23: error: 'QDataStream& Unit::operator<<(QDataStream&, Unit&)' must take exactly one argument QDataStream &Unit::operator <<(QDataStream &out, Unit &val) ^ – andreahmed Apr 26 '16 at 12:01
  • I need more coffee. You're defining operators for `Unit`, not `QDataStream`. Your stream operator in function should have the signature: `QDataStream &QDataStream::operator...` Please ignore my `const` remark. I thought you were overloading one operator, not defining two. – jonspaceharper Apr 26 '16 at 12:16
  • What type does `Unit::userValue()` return? – jonspaceharper Apr 26 '16 at 12:17
  • it returns a qreal – andreahmed Apr 26 '16 at 12:24
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/110268/discussion-between-andreahmed-and-jon-harper). – andreahmed Apr 26 '16 at 12:24
  • @Kuba Ober can you solve this please – andreahmed Apr 26 '16 at 12:35
  • "I have read but I don't know how to use those code there" That's not a problem with the question, though, and that doesn't make your question any less of a duplicate. – Kuba hasn't forgotten Monica Apr 26 '16 at 14:02
  • @KubaOber what do you want to know and I can write it – andreahmed Apr 26 '16 at 14:03

1 Answers1

0

Here's the documentation for qRegisterMetaTypeStreamOperators(). Start there to fix your streaming operators, i.e. it should look like this:

QDataStream &operator<<(QDataStream &out, const Unit &unit);
QDataStream &operator>>(QDataStream &out, Unit &unit);

Otherwise, that portion of your code is correct.

The second fix is that you cannot register a pointer with QMetaType. You need to register the type itself:

qRegisterMetaTypeStreamOperators<Unit>("Unit");

Lastly, qRegisterMetaType() and qRegisterMetaTypeStreamOperators() should be called only once (you have called qRegisterMetaType() as well, right?). If you note the documentation for QMetaType::load(), these functions should only be called once (e.g. in int main() or some other initialization code.

jonspaceharper
  • 4,207
  • 2
  • 22
  • 42
  • is QDataStream &operator<<(QDataStream &out, const Unit &unit); QDataStream &operator>>(QDataStream &out, Unit &unit); should be a member function or it should be free in the class? – andreahmed Apr 26 '16 at 12:51
  • now I get /home/ahmed/server/elec/software_t/backup17/checko5/eracommon5/src/cpp/system/unit/unit.cpp:57: error: no match for 'operator>>' (operand types are 'QDataStream' and 'qreal {aka double}') in >> unit.value(); ^ – andreahmed Apr 26 '16 at 13:16