c++qtqlistqsettings

Write a QList of QPair to a QSettings object


I want to persistently store a list of integer pairs, using Qt Framework.

I thought of using QList< QPair < int,int>> as a type for the list, and to store them in an .ini file using QSettings.

Unfortunately, the function QSettings::setValue raises an error:

no matching function for call to ‘QSettings::setValue(const char [19], FavoriteList&)’
note:   no known conversion for argument 2 from QList< QPair< int, int> > to ‘const QVariant&’

It seems that it cannot cast that type to a QVariant. I tried declaring it with Q_DECLARE_METATYPE, but it didn't work, it raises the same error.

Example of code that fails:

QList<QPair<int,int>> list;

if(!settings.contains("Radio/Favorites/FM"))
{
    settings.setValue("Radio/Favorites/FM", list);
}

How can I write that type to a QSettings object?


Solution

  • You simply don't have any compatible implicit conversion. The compiler doesn't know how to turn your list to a variant.

    In fact, Q_DECLARE_METATYPE shoudln't be necessary at all, at least for me the following code compiles with no errors:

      QSettings s;
      QList< QPair < int,int>> l;
      s.setValue("key", QVariant::fromValue(l));
    

    EDIT: while it doesn't get compile errors, it will still get a runtime error because it doens't know how to serialize and deserialize a list of int pairs. So you will have to tell it how:

    QDataStream &operator<<(QDataStream &out, const QList<QPair<int,int>> &l) {
      int s = l.size();
      out << s;
      if (s) for (int i = 0; i < s; ++i) out << l[i].first << l[i].second;
      return out;
    }
    QDataStream &operator>>(QDataStream &in, QList<QPair<int,int>> &l) {
      if (!l.empty()) l.clear();
      int s;
      in >> s;
      if (s) {
        l.reserve(s);
        for (int i = 0; i < s; ++i) {
          int f, sec;
          in >> f >> sec;
          l.append(QPair<int, int>(f, sec));
        }
      }
      return in;
    }
    

    And also register stream operators for the type in the meta system:

    qRegisterMetaTypeStreamOperators<QList<QPair<int,int>>>("whatever");
    

    Aaand.. it works!

      QSettings s;
      QList<QPair<int,int>> l;
      l.append(QPair<int, int>(555, 556));
      s.setValue("key", QVariant::fromValue(l));
      QList<QPair<int,int>> l1 = s.value("key").value<QList<QPair<int,int>>>();
      qDebug() << l1.at(0).first << l1.at(0).second; // 555 556