9

I'm trying to save a custom type to QSettings but I'm getting an error at runtime. Here's the class I'm trying to save:

#ifndef TESTCLASS_H
#define TESTCLASS_H

#include <QMetaType>
#include <QString>

class TestClass
{
public:
    QString testString;
    int testInt;
    bool testBool;
};

Q_DECLARE_METATYPE(TestClass)

#endif

And here's the code to save an instance of the class to QSettings

TestClass test;
test.testString = "Test";
test.testInt = 10;
test.testBool = false;

settings.setValue("TestGroup/TestVal", QVariant::fromValue(test));
settings.sync();

The error I get at runtime is:

QVariant::save: unable to save type 'TestClass' (type id: 1032).

ASSERT failure in QVariant::save: "Invalid type to save", file kernel\qvariant.cpp, line 2124
Invalid parameter passed to C runtime function.
Invalid parameter passed to C runtime function.

According to the documentation, the class must provide a default constructor, destructor and a copy constructor. For this class the automatically generated constructor, destructor and copy constructors would be sufficient, so I haven't provided one (though I did try it anyway to see if that was the problem). I've also used Q_DECLARE_METATYPE() so the class is known to QMetaType, so as far as I can tell I've met the requirements to use the class with QVariant.

What am I missing?

Assoluto
  • 199
  • 3
  • 12
  • 1
    Possible duplicate of [Writing and reading custom class to QSettings](https://stackoverflow.com/questions/18144377/writing-and-reading-custom-class-to-qsettings) – quimnuss Jul 20 '17 at 16:03

2 Answers2

13

You have to implement streaming. TestClass should have 2 overloaded operators <<, >>. For instance:

class TestClass
{
public:
    QString testString;
    qint32 testInt;
    friend QDataStream & operator << (QDataStream &arch, const TestClass & object)
    {
        arch << object.testString;
        arch << object.testInt;
        return arch;
    }

    friend QDataStream & operator >> (QDataStream &arch, TestClass & object)
    {
        arch >> object.testString;
        arch >> object.testInt;
        return arch;
    }
};

Q_DECLARE_METATYPE(TestClass)

Before saving instance of TestClass you have to use qRegisterMetaTypeStreamOperators function, like this:

    qRegisterMetaTypeStreamOperators<TestClass>("TestClass");
    QSettings settings(QSettings::IniFormat, QSettings::UserScope,"MySoft", "Star Runner");
    settings.setValue("TestGroup/TestVal", QVariant::fromValue(test));
    settings.sync();
Martin Delille
  • 11,360
  • 15
  • 65
  • 132
arturx64
  • 943
  • 4
  • 12
  • Thanks a lot, that solved the problem. I'll have to look over the documentation again because I didn't realise that was necessary. – Assoluto May 19 '16 at 22:01
  • How do you read it back afterwards? Do you have to do something different than the usual? – quimnuss Jul 20 '17 at 14:39
  • Nevermind: https://stackoverflow.com/questions/18144377/writing-and-reading-custom-class-to-qsettings – quimnuss Jul 20 '17 at 16:00
-3

In example you provided you should change TestClass to struct or explicitly write constructor,destructor,copy contructor.

tty6
  • 1,203
  • 11
  • 30
  • I did try explicitly writing a constructor, destructor and copy constructor but it continued to give the same error, so that doesn't seem to be the problem. – Assoluto May 19 '16 at 21:51