Save QList<int> to QSettings
Asked Answered
B

3

13

I want to save a QList<int> to my QSettings without looping through it.
I know that I could use writeArray() and a loop to save all items or to write the QList to a QByteArray and save this but then it is not human readable in my INI file..

Currently I am using the following to transform my QList<int> to QList<QVariant>:

QList<QVariant> variantList;
//Temp is the QList<int>
for (int i = 0; i < temp.size(); i++)
  variantList.append(temp.at(i));

And to save this QList<Variant> to my Settings I use the following code:

QVariant list;
list.setValue(variantList);
//saveSession is my QSettings object
saveSession.setValue("MyList", list);

The QList is correctly saved to my INI file as I can see (comma seperated list of my ints)
But the function crashes on exit.
I already tried to use a pointer to my QSettings object instead but then it crashes on deleting the pointer ..

Boito answered 16/3, 2010 at 8:20 Comment(3)
What I don't get is that in order to create you QVariant list you loop through your int list, which precisely you try to avoid. Am I missing something?Apogamy
No .. I thought that I can directly save my QList<int> but it seem to only work with QList<QVariant> .. The thing I want to avoid is to save the List with writeArray, because the list should be written within another writeArray command and I dont know if this would work ..Boito
I realized it now as a QString.. Instead of looping through my QList<int> to create a QList<QVariant> I append the values to a QString (comma seperated) as I like it to be shown in INI file and on Load I split the String (by ',') and create my QList<int> again.Boito
T
25

QSettings::setValue() needs QVariant as a second parameter. To pass QList as QVariant, you have to declare it as a Qt meta type. Here's the code snippet that demonstrates how to register a type as meta type:

#include <QCoreApplication>
#include <QDebug>
#include <QMetaType>
#include <QSettings>
#include <QVariant>

Q_DECLARE_METATYPE(QList<int>)

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qRegisterMetaTypeStreamOperators<QList<int> >("QList<int>");

    QList<int> myList;
    myList.append(1);
    myList.append(2);
    myList.append(3);

    QSettings settings("Moose Soft", "Facturo-Pro");
    settings.setValue("foo", QVariant::fromValue(myList));
    QList<int> myList2 = settings.value("foo").value<QList<int> >();
    qDebug() << myList2;

    return 0;
}
Terrorist answered 16/3, 2010 at 11:56 Comment(1)
Hmm.. I know how to use metatypes, I am using them already. But if I declare my QList<int> as metatype and save it to my settings, the data is saved as bytestream.. means that no one can read / change it directly in the ini .. But no crash occurs!! :)Boito
W
1

You might have to register QList as a meta-type of its own for it to work. This is a good starting point to read up on meta-types in Qt: http://qt.nokia.com/doc/4.6/qmetatype.html#details .

Wolgast answered 16/3, 2010 at 11:38 Comment(1)
Yes it is working after registering as a metatype (although it is saved as a bytestream).. But there is no error, when I pass a QList<QVariant> to setValue. Therefore I expect it to work.. And if I look at the INI file, the list is saved comma seperated with the values in it, only the destructor of the QList crashes for some reason...Boito
I
1

I was also struggling with this ... and I believe I now have a decent solution.

I hope this saves someone the trouble, it caused me.

#include <QCoreApplication>
#include <QSettings>
#include <QList>
#include <QDataStream>
#include <QVariant>
#include <QVariantList>
#include <QDebug>
#include <deque>


template <class T> static QVariant toVariant(const QList<T> &list)
{
    QVariantList variantList;
    variantList.reserve(list.size());
    for (const auto& v : list)
    {
        variantList.append(v);
    }
    return variantList;
}

template <class T> static QList<T> toList(const QVariant &qv)
{
    QList <T> dataList;
    foreach(QVariant v, qv.value<QVariantList>()) {
        dataList << v.value<T>();
    }
    return dataList;
}



void Gen()
{
    QList<QString> data {"hello", "world","how", "are", "you"};
    QList<int> ages {10,20,30,40};
    QSettings setup("stuff.ini", QSettings::IniFormat);
    setup.beginWriteArray("rules");
    for (int groups=0;groups<3;groups++)
    {
        setup.setArrayIndex(groups);
        setup.setValue("rule",QString("Rule-%1").arg(groups));
        setup.setValue("data", toVariant (data));
        setup.setValue("ages", toVariant (ages));
    }
    setup.endArray();
    setup.sync();
}


void Read()
{
    QSettings setupR("stuff.ini", QSettings::IniFormat);
    int rule_count = setupR.beginReadArray("rules");
    for (int groups=0;groups<rule_count;groups++)
    {
        setupR.setArrayIndex(groups);

        QString nameRead = setupR.value("rule").toString();
        QList<QString> dataRead =  toList<QString>(setupR.value("data"));
        qDebug() << "Rule " << groups;
        qDebug() << "Rule Read" << nameRead;
        qDebug() << "Data Read2" << dataRead;
    }

}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    // Write
    Gen();
    // Read
    Read();
    exit(0);
    //return a.exec();
}

You should end up with an INI file which looks like this ...

[rules]
1\ages=10, 20, 30, 40
1\data=hello, world, how, are, you
1\rule=Rule-0
2\ages=10, 20, 30, 40
2\data=hello, world, how, are, you
2\rule=Rule-1
3\ages=10, 20, 30, 40
3\data=hello, world, how, are, you
3\rule=Rule-2
size=3

The nice thing here is you can edit this outside of QT (Just be careful) ...

Inguinal answered 1/12, 2020 at 9:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.