以人类可读的形式在 QSettings 中保存自定义 QMap 模板实例化

Save custom QMap template instantiation in QSettings in human-readable form

在我的代码中,我使用 QSettings 机制将我自己的 class MyClassQMap<unsigned int, MyClass> 中保存并加载到配置文件中。

我知道如何将我自己的类型注册到 QMetaObject,以便我可以将它们与 QVariant 一起使用。这允许使用 QSettings 保存它们。请参阅下面的工作代码。

但是,我正在写入的实际配置文件中这些类型的表示绝不是人类可读的。 有没有什么方法可以使自定义地图在文本编辑器中更具可读性,这样我就可以在 Qt 之外手动更改配置?

将我的自定义类型保存到配置的代码:

struct MyClass
{
    unsigned int id;
    QString name;
    QString value;

    friend QDataStream & operator<< (QDataStream &arch, const MyClass& c)
    {
        return arch << c.id << c.name << c.value;
    }
    friend QDataStream & operator>> (QDataStream &arch, MyClass& c)
    {
        return arch >> c.id >> c.name >> c.value;
    }
};
Q_DECLARE_METATYPE(MyClass)
typedef QMap<unsigned int, MyClass> MyMap;

int main(int argc, char *argv[])
{
   MyMap map;
    map.insert(100, {100, "name1", "value1"});
    map.insert(101, {101, "name2", "value2"});
    map.insert(200, {200, "name3", "value3"});

    qRegisterMetaTypeStreamOperators<MyMap>("MyMap");
    QSettings conf("/home/dave/temp/myfile.conf", QSettings::IniFormat);
    conf.setValue("myMapping", QVariant::fromValue(map));
    conf.sync();
}

写入的配置文件:

[General]
myMapping="@Variant([=11=][=11=][=11=]\x7f[=11=][=11=][=11=]\x13QMap<uint,MyClass>[=11=][=11=][=11=][=11=]\x3[=11=][=11=][=11=]\xc8[=11=][=11=][=11=]\xc8[=11=][=11=][=11=]\n[=11=]n[=11=]\x61[=11=]m[=11=]\x65[=11=]\x33[=11=][=11=][=11=]\f[=11=]v[=11=]\x61[=11=]l[=11=]u[=11=]\x65[=11=]\x33[=11=][=11=][=11=]\x65[=11=][=11=][=11=]\x65[=11=][=11=][=11=]\n[=11=]n[=11=]\x61[=11=]m[=11=]\x65[=11=]\x32[=11=][=11=][=11=]\f[=11=]v[=11=]\x61[=11=]l[=11=]u[=11=]\x65[=11=]\x32[=11=][=11=][=11=]\x64[=11=][=11=][=11=]\x64[=11=][=11=][=11=]\n[=11=]n[=11=]\x61[=11=]m[=11=]\x65[=11=]\x31[=11=][=11=][=11=]\f[=11=]v[=11=]\x61[=11=]l[=11=]u[=11=]\x65[=11=]\x31)"

Qt 负责 serializing/deserializing 您的地图 - 不幸的是,这没有考虑到人类可读性。

您需要手动处理整个地图的 serializing/deserializing 和 write/read QString(或类似的东西),例如

QString serialize(const QMap<int, MyClass>& mapToSerialize)
{
    QStringList result;
    for(int key : mapToSerialize.keys())
    {
        result.append("%1%2%3).arg(QString::number(i), SEPARATOR_TOKEN, serialize(mapToSerialize.value(i));
    }
    return result.join(MAP_SEPARATOR_TOKEN);
}

这当然有缺点,您 1) 需要为地图和 class 编写 serialize/deserialize 函数,以及 2) 您需要处理所有特殊情况(转义特殊字符、解析错误数据等)