Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. saving a custom Unit* class

saving a custom Unit* class

Scheduled Pinned Locked Moved Unsolved General and Desktop
12 Posts 3 Posters 4.6k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    AndreAhmed
    wrote on last edited by
    #1

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

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      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.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • A Offline
        A Offline
        AndreAhmed
        wrote on last edited by
        #3

        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

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          Can you share your operators implementation ?

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          0
          • A Offline
            A Offline
            AndreAhmed
            wrote on last edited by
            #5

            why I can't save a pointer qproperty like Unit*.
            that's what the error says
            QVariant::save: unable to save type 'Unit*'

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

              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;
              }
              

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              1
              • A Offline
                A Offline
                AndreAhmed
                wrote on last edited by
                #7

                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 message

                error: 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 type

                Q_DECLARE_METATYPE(Unit)
                Q_DECLARE_METATYPE(Unit*)

                1 Reply Last reply
                0
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  Unit is a QObject base class you shouldn't call Q_DECLARE_METATYPE on it.

                  Where are you doing the declaration and registrations ?

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  1 Reply Last reply
                  0
                  • A Offline
                    A Offline
                    AndreAhmed
                    wrote on last edited by
                    #9

                    I'm doing it in main()

                    1 Reply Last reply
                    0
                    • SGaistS Offline
                      SGaistS Offline
                      SGaist
                      Lifetime Qt Champion
                      wrote on last edited by
                      #10

                      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.

                      Interested in AI ? www.idiap.ch
                      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                      1 Reply Last reply
                      0
                      • A Offline
                        A Offline
                        AndreAhmed
                        wrote on last edited by
                        #11

                        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)

                        kshegunovK 1 Reply Last reply
                        0
                        • A AndreAhmed

                          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)

                          kshegunovK Offline
                          kshegunovK Offline
                          kshegunov
                          Moderators
                          wrote on last edited by
                          #12

                          @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
                          {
                          }
                          

                          Read and abide by the Qt Code of Conduct

                          1 Reply Last reply
                          0

                          • Login

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • Users
                          • Groups
                          • Search
                          • Get Qt Extensions
                          • Unsolved