qsettings 保存自定义结构体(QVariant与自定义结构体相互转化)

参考博文:QVariant与自定义数据类型转换的方法。

这里摘取其关键内容:

1、将自定义数据类型使用Q_DECLARE_METATYPE宏进行声明,便于编译器识别。

2、在插入对象的时候,声明QVariant对象,使用其setValue方法添加自定义对象。

3、在读取的时候,采用QVariant对象的value方法返回自定义对象。

写入:

    • //类型转换
    • QVariant v;
    • v.setValue(MyStruct); 

      读取:
    • //转换为自定义的结构体实例
    • MyStruct s = v.value<MyStruct>(); 

      参考了博文后写了自己的结构体,但是在用qsettings读出某一条记录时提示错误:

      QVariant::load: unable to load type 1055.

      同时,在写qsettings,会提示如下错误:

      QVariant::save: unable to save type ‘DownloadFinishItemInfo‘ (type id: 1055).(其中DownloadFinishItemInfo为自定义结构体)

      针对以上问题,加入如下补充后问题得到解决:

      1、在用qsettings读出某一条记录前需增加qRegisterMetaTypeStreamOperators的声明;

      2、需要重载关于自定义结构体的输入和输出操作符。

      个人猜测:对于qsettings要保存自定义的结构体,其实就是保存到硬盘的配置文件中,所以需要对这个结构体有读出和写入的api,这里是重载输入和输出操作符,这样,在用qsettings保存一条记录的时候,就用该结构体的输出操作符把结构体内容读出到流,然后把流中的内容保存到文件,同样,在用qsettings读出一条记录时,就需要用到该结构体的输出操作符,把结构体内容输出到流,然后我们才能从流中读到该结构体的内容。

      上代码:

      .h:

      /*已下载的任务的信息*/

      #ifndef DOWNLOADFINISHITEMINFO_H
      #define DOWNLOADFINISHITEMINFO_H

      #include <QMetaType>
      #include <QString>
      #include <QDataStream>

      class DownloadFinishItemInfo
      {
      public:
          DownloadFinishItemInfo();

      QString downloadTime; //下载时间
          QString softwareName; //软件名
          QString softwareIconPath;//图标路径
          QString softwareTotalSizeStr; //总大小的字符串表示
      };

      Q_DECLARE_METATYPE(DownloadFinishItemInfo)  //将自定义数据类型使用Q_DECLARE_METATYPE宏进行声明,便于编译器识别

      QDataStream &    operator<<(QDataStream &out, const DownloadFinishItemInfo info);
      QDataStream &    operator>>(QDataStream &out, DownloadFinishItemInfo &info);

      #endif // DOWNLOADFINISHITEMINFO_H

      .cpp:

      #include "downloadfinishiteminfo.h"
      #include <QMetaType>
      #include <QDebug>

      DownloadFinishItemInfo::DownloadFinishItemInfo()
      {
          
      }

      QDataStream &    operator<<(QDataStream &out, const DownloadFinishItemInfo info)  //定义怎么把自定义结构体的数据写入一条qsettings
      {

      out << info.downloadTime.toStdString().c_str() \
              << info.softwareIconPath.toStdString().c_str() \
              << info.softwareName.toStdString().c_str() \
              << info.softwareTotalSizeStr.toStdString().c_str();
      //    qDebug() << "*****************" << info.downloadTime.toStdString().c_str() \
      //        << info.softwareIconPath.toStdString().c_str() \
      //        << info.softwareName.toStdString().c_str() \
      //        << info.softwareTotalSizeStr.toStdString().c_str();

      return out;
      }

      QDataStream &    operator>>(QDataStream &out, DownloadFinishItemInfo& info)  //定义怎么把从qsettings读出的一条数据保存到自定义结构体中
      {
          char *str1= new char(100);
          char *str2= new char(100);
          char *str3= new char(100);
          char *str4= new char(100);
          out >> str1;
          //qDebug() << "@@@@@@@@" <<str1;
          info.downloadTime.toStdString().clear();
          info.downloadTime.append(str1);

      out >> str2;
          //qDebug() << "@@@@@@@@" <<str2;
          info.softwareIconPath.toStdString().clear();
          info.softwareIconPath.append(str2);

      out >> str3;
          //qDebug() << "@@@@@@@@" <<str3;
          info.softwareName.toStdString().clear();
          info.softwareName.append(str3);

      out >> str4;
          //qDebug() << "@@@@@@@@" <<str4;
          info.softwareTotalSizeStr.toStdString().clear();
          info.softwareTotalSizeStr.append(str4);
          //qDebug() << "&&&&&&&&&" <<str;
          //out >>&(info.downloadTime);
          delete str1;
          delete str2;
          delete str3;
          delete str4;
          return out;
      }

    • 读取和写入setting:
    • void DownloadProWidget::WriteDownloadFinishedTask(DownloadFinishItemInfo info)
      {
          //写进配置文件(保存3天内的已下载任务)
          QSettings *pSettings = new QSettings("downloadFinished.ini", QSettings::IniFormat, this);

      pSettings->beginGroup("Withinthreedays");
          QVariant variant;

      DownloadFinishItemInfo info1;
          info = info1;
          variant.setValue(info);
          pSettings->setValue(info.softwareName, variant);
          pSettings->endGroup();

      }

      QList<DownloadFinishItemInfo> DownloadProWidget::ReadDownloadFinishedTask()
      {
          qRegisterMetaTypeStreamOperators<DownloadFinishItemInfo>("DownloadFinishItemInfo");  //关键,不然读出来的都是空

      //读取配置文件(3天内的已下载任务)
          QSettings *pSettings = new QSettings("downloadFinished.ini", QSettings::IniFormat, this);

      //读取所有key
          QStringList keyList = pSettings->allKeys();

      QList<DownloadFinishItemInfo> infoList;

      //保存所有信息
          int length = keyList.length();
          for(int i = 0; i < length; i++)
          {
              QVariant variant = pSettings->value(keyList.at(i));
              DownloadFinishItemInfo info = variant.value<DownloadFinishItemInfo>();
              infoList.append(info);

      }
          return infoList;
      }

http://blog.csdn.net/u013281495/article/details/50970725

时间: 2024-10-07 20:16:54

qsettings 保存自定义结构体(QVariant与自定义结构体相互转化)的相关文章

自定义数据类型使用QVariant转换的方法

QVariant类型的放入和取出必须是相对应的,你放入一个int就必须按int取出,不能用toString(), Qt不会帮你自动转换. 数据核心无非就是一个 union,和一个标记类型的type:传递的是整数 123,那么它union存储整数123,同时type标志Int:如果传递字符串,union存储字符串的指针,同时type标志QString. QVariant 属于 Qt 的Core模块,属于Qt的底层核心之一,ActiveQt.QtScript.QtDeclarative等都严重依赖于

常规功能和模块自定义系统(cfcmms)—006Extjs的目录结构和mvvm介绍

常规功能和模块自定义系统(cfcmms)-006Extjs的目录结构和mvvm介绍 在eclipse中打开cfcmms项目,展开后目录结构如下图所示,图中简单的注释了一下各个目录和文件的说明.由于extjs6默认使用的是mvvm架构,如果想要使用extjs的MVC,需要在app下加入controller目录,把所有的控制器都放在此目录之下即可. 打开浏览器,输入网址 http://localhost:1841/,则会显示此项目默认生成的示例.如下图所示. 系统的文件加载过程,在浏览器输入网址后,

自定义View 篇一--------《自定义View流程分析》

本文部分内容参考自掘金网:点击打开链接 坐标图解: 概述 Android已经为我们提供了大量的View供我们使用,但是可能有时候这些组件不能满足我们的需求,这时候就需要自定义控件了.自定义控件对于初学者总是感觉是一种复杂的技术.因为里面涉及到的知识点会比较多.但是任何复杂的技术后面都是一点点简单知识的积累.通过对自定义控件的学习去可以更深入的掌握android的相关知识点,所以学习android自定义控件是很有必要的.所以,今天写的是怎么去自定义一个控件.而不是里面涉及到的细化知识点.一个东西我

常规功能和模块自定义系统 (cfcmms)—015模块自定义概述(2权限)

常规功能和模块自定义系统 (cfcmms)-015模块自定义概述(2权限) 模块的权限的自定义也是这个系统的重要部分.在本系统中现在模块的权限有三大类:模块操作权限.记录可视范围限定.附加操作权限. 模块操作权限:可以对模块进行浏览.新增.修改.删除.审核.审批等的设置.可以通过生成和隐藏相应的按钮来具体控制权限的设置.如某人无删除权限,则在该模块的操作界面上没有删除按钮.对于一般的管理系统而言这些功能基本上是够用了. 记录可视范围限定:可以在任意模块加上可视范围的限定.在某个父模块上加上可视范

DRF认证、自定义认证和权限、自定义权限

源码分析 """ 1)APIView的dispath(self, request, *args, **kwargs) 2)dispath方法内 self.initial(request, *args, **kwargs) 进入三大认证 # 认证组件:校验用户 - 游客.合法用户.非法用户 # 游客:代表校验通过,直接进入下一步校验(权限校验) # 合法用户:代表校验通过,将用户存储在request.user中,再进入下一步校验(权限校验) # 非法用户:代表校验失败,抛出异常

C语言结构体,C语言结构体指针,java对象引用,传值,传地址,传引用

C语言结构体,C语言结构体指针,java对象引用,传值,传地址,传引用 传值 把实参的值赋值给行参 那么对行参的修改,不会影响实参的值 传地址 传值的一种特殊方式,只是他传递的是地址,不是普通的如int 那么传地址以后,实参和行参都指向同一个对象 传引用 真正的以地址的方式传递参数 传递以后,行参和实参都是同一个对象,只是他们名字不同而已 对行参的修改将影响实参的值 所谓变量是内存地址的一个抽象名字,在静态编译的程序中,所有变量名都会在编译时转换成内存地址,机器不知道变量名,只知道地址. C 语

超酷的计步器APP——炫酷功能实现,自定义水波纹特效、自定义炫酷开始按钮、属性动画的综合体验

超酷的计步器APP--炫酷功能实现,自定义水波纹特效.自定义炫酷开始按钮.属性动画的综合体验 好久没写博客了,没给大家分享技术了,真是有些惭愧.这段时间我在找工作,今年Android的行情也不怎么好,再加上我又是一个应届生,所以呢,更是不好找了.但是我没有放弃,经过自己的不懈努力,还是找到了自己喜欢的Android工作,心里的一块石头终于落下了.但是迎接我来的是更多的挑战,我喜欢那种不断的挑战自我,在困难中让自己变得更强大的感觉.相信阳光总在风雨后,因为每一个你不满意的现在,都有一个你没有努力的

自定义View(一),初识自定义View

看了无数资料,总结一下自定义View 先明白一个自定义View的三大流程 onMeasure() 测量,决定View的大小 onLayout() 布局,决定View在ViewGroup中的位置 onDraw() 绘制,画出这个View的内容 这三个方法都存在于View类中,我们自定义View需要针对这三个方法做出修改来达到我们需要的目标或功能 先来一个最基本的例子,我们单纯的画一个圆,我们只需修改onDraw()方法即可 MyCustomVew.java public class MyCusto

常规功能和模块自定义系统(cfcmms)—004可自定义的项目

常规功能和模块自定义系统(cfcmms)-004可自定义的项目 可以在前台浏览器里可进行的配置项目如下图: 版权声明:本文为博主原创文章,未经博主允许不得转载.