【问题标题】:Read array of custom metatype from QSettings从 QSettings 读取自定义元类型数组
【发布时间】:2013-05-14 17:29:03
【问题描述】:

我在从 QSetting 读取自定义元类型数据时遇到问题。 我有一堂课:

class MusicOwner
{
public:
    MusicOwner() :
        songs_count(0),
        id(0)
    {}

    explicit MusicOwner(const Song &owner_radio);
    Song toOwnerRadio() const;

    static QList<MusicOwner> parseMusicOwnerList(const QVariant &request_result);

private:
    friend QDataStream &operator <<(QDataStream &stream, const VkService::MusicOwner &val);
    friend QDataStream &operator >>(QDataStream &stream, VkService::MusicOwner &val);
    friend QDebug operator<< (QDebug d, const MusicOwner &owner);

    int songs_count;
    int id;
    QString name;
    QString screen_name;
    QUrl photo;
};

Q_DECLARE_METATYPE(VkService::MusicOwner)

重载:

QDataStream &operator <<(QDataStream &stream, const VkService::MusicOwner &val)
{
    stream << val.id;
    stream << val.name;
    stream << val.songs_count;
    stream << val.screen_name;
    return stream;
}

QDataStream &operator >>(QDataStream &stream, VkService::MusicOwner &val)
{
    stream >> val.id;
    stream >> val.name;
    stream >> val.songs_count;
    stream >> val.screen_name;
    return stream;
}

QDebug operator <<(QDebug d, const VkService::MusicOwner &owner)
{
    d << "MusicOwner("
      << owner.id << ","
      << owner.name << ","
      << owner.songs_count << ","
      << owner.screen_name << ")";
    return d;
}

我在程序开始的某个地方调用:

qRegisterMetaTypeStreamOperators<MusicOwner>("MusicOwner");

为了读写,我使用了两个函数: 保存工作正常,我保存的所有数据都显示在设置文件中。

void VkService::SaveBookmarks()
{
    TRACE;
    QSettings s;
    s.beginGroup(kSettingGroup);

    s.beginWriteArray("bookmarks");
    int index = 0;
    for (int i = 0; i < root_item_->rowCount(); ++i){
        auto item = root_item_->child(i);
        if (item->data(InternetModel::Role_Type).toInt() == Type_Bookmark){
            Song song = item->data(InternetModel::Role_SongMetadata).value<Song>();
            s.setArrayIndex(index);
            MusicOwner owner(song);
            qLog(Info) << "Save" << index << ":" << owner;
            s.setValue("owner", QVariant::fromValue(owner));
            ++index;
        }
    }
    s.endArray();
}

这个函数的问题,它的加载计数正确,但它加载的是空的默认构造项。

void VkService::LoadBookmarks()
{
    QSettings s;
    s.beginGroup(kSettingGroup);

    int max = s.beginReadArray("bookmarks");
    for (int i = 0; i < max; ++i){
        s.setArrayIndex(i);
        MusicOwner owner = s.value("owner").value<MusicOwner>();
        qLog(Info) << "Load" << i << ":" << owner;
        AppendBookmarkFromRadio(root_item_, owner.toOwnerRadio());
    }
    s.endArray();
}

我将它重写到新项目进行测试,但它工作正常。 我花了两个小时来找出为什么这个变体能正确读取数据但第一个变体不能。 第一个变体的所有者正确转换。甚至两种变体的设置文件中的数据都相同。

#include <QCoreApplication>
#include <QDataStream>
#include <QDebug>
#include <QUrl>
#include <QSettings>
#include <QVariant>

class MusicOwner
{
public:
    MusicOwner() :
        songs_count(0),
        id(0)
    {}

private:
    friend QDataStream &operator <<(QDataStream &stream, const MusicOwner &val);
    friend QDataStream &operator >>(QDataStream &stream, MusicOwner &val);
    friend QDebug operator<< (QDebug d, const MusicOwner &owner);

public:
    int songs_count;
    int id;
    QString name;
    QString screen_name;
    QUrl photo;
};


QDataStream &operator <<(QDataStream &stream, const MusicOwner &val)
{
    stream << val.id;
    stream << val.name;
    stream << val.songs_count;
    stream << val.screen_name;
    return stream;
}

QDataStream &operator >>(QDataStream &stream, MusicOwner &val)
{
    stream >> val.id;
    stream >> val.name;
    stream >> val.songs_count;
    stream >> val.screen_name;
    return stream;
}

QDebug operator <<(QDebug d, const MusicOwner &owner)
{
    d << "MusicOwner("
      << owner.id << ","
      << owner.name << ","
      << owner.songs_count << ","
      << owner.screen_name << ")";
    return d;
}

Q_DECLARE_METATYPE(MusicOwner)

const QString kSettingGroup = "Group";

void Save() {
    QSettings s;
    s.beginGroup(kSettingGroup);

    s.beginWriteArray("bookmarks");
    int index = 0;
    for (int i = 0; i < 100; ++i){
        if (random() % 5 == 0) {
            s.setArrayIndex(index);
            MusicOwner owner;
            owner.id = i;
            owner.name ="Hello world";
            owner.songs_count = i * 2;
            owner.screen_name = "hello_world";

            s.setValue("owner", QVariant::fromValue(owner));
            qDebug() << "Saved" << i << ":" << owner;
            ++index;
        }
    }
    s.endArray();
    qDebug() << "Saved" << index << "elements";
}

void Load() {
    QSettings s;
    s.beginGroup(kSettingGroup);

    int max = s.beginReadArray("bookmarks");
    qDebug() << "To load" << max << "elements";

    for (int i = 0; i < max; ++i){
        s.setArrayIndex(i);
        MusicOwner owner = s.value("owner").value<MusicOwner>();
        qDebug() << "\tLoaded" << i << ":" << owner;
    }
    s.endArray();
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    qRegisterMetaTypeStreamOperators<MusicOwner>("MusicOwner");
    QSettings s;

    Load();
    Save();

    return a.exec();
}

也许您会发现在此变体中使用 QSettings 的不同之处?

【问题讨论】:

    标签: c++ qt qvariant qsettings


    【解决方案1】:

    您对示例中的命名空间一点也不小心。如果您确实在非工作代码中使用命名空间,则您不能创建不使用命名空间的“最小案例”。

    以下可编译示例使用命名空间并且在 Qt 4.8 和 5.1 中都可以正常工作。请注意,这些设置在 4.8 和 5.1 之间默认不可移植,我不知道这是错误还是功能。

    #include <QCoreApplication>
    #include <QDataStream>
    #include <QDebug>
    #include <QSettings>
    #include <QVariant>
    
    namespace VkService {
    
    class MusicOwnerA
    {
        friend QDataStream &operator <<(QDataStream &stream, const MusicOwnerA &val);
        friend QDataStream &operator >>(QDataStream &stream, MusicOwnerA &val);
        friend QDebug operator<< (QDebug d, const MusicOwnerA &owner);
    public:
        MusicOwnerA() : id(0) {}
        int id;
        QString name;
    };
    
    QDataStream &operator <<(QDataStream &stream, const VkService::MusicOwnerA &val)
    {
        stream << val.id;
        stream << val.name;
        return stream;
    }
    
    QDataStream &operator >>(QDataStream &stream, VkService::MusicOwnerA &val)
    {
        stream >> val.id;
        stream >> val.name;
        return stream;
    }
    
    QDebug operator <<(QDebug d, const VkService::MusicOwnerA &owner)
    {
        d << "VkService::MusicOwnerA("
          << owner.id << ","
          << owner.name << ")";
        return d;
    }
    
    }
    
    Q_DECLARE_METATYPE(VkService::MusicOwnerA)
    
    void Save() {
        QSettings s;
        s.beginWriteArray("bookmarks");
        int index = 0;
        for (int i = 0; i < 100; ++i){
            if (random() % 5 == 0) {
                s.setArrayIndex(index);
                VkService::MusicOwnerA owner;
                owner.id = i;
                owner.name ="Hello world";
                s.setValue("owner", QVariant::fromValue(owner));
                qDebug() << "Saved" << i << ":" << owner;
                ++index;
            }
        }
        s.endArray();
        qDebug() << "Saved" << index << "elements";
    }
    
    void Load() {
        QSettings s;
        int max = s.beginReadArray("bookmarks");
        qDebug() << "To load" << max << "elements";
        for (int i = 0; i < max; ++i){
            s.setArrayIndex(i);
            VkService::MusicOwnerA owner = s.value("owner").value<VkService::MusicOwnerA>();
            qDebug() << "\tLoaded" << i << ":" << owner;
        }
        s.endArray();
    }
    
    int main(int argc, char **argv)
    {
        QCoreApplication a(argc, argv);
        a.setOrganizationDomain("16549302.stackoverflow.com");
        qRegisterMetaTypeStreamOperators<VkService::MusicOwnerA>("VkService::MusicOwnerA");
        Load();
        Save();
    }
    

    【讨论】:

    • 感谢您的回答,但我找到了解决方案。事实证明,所有元类型都在外部方法中注册。当我向其中添加所需的行时,它起作用了。对于未来,在这种情况下我应该在stackoverflow上做什么?我没有找到“删除问题”按钮。
    • 好吧,将问题标记为删除的原因相当有限。你的真的不符合条件。
    • @shed 当你自己找到答案后,你可以自己创建一个答案,描述你是如何解决的
    猜你喜欢
    • 2013-08-11
    • 2017-05-20
    • 1970-01-01
    • 2015-11-17
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多