Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Value Stored in QSetting is not retained after the program is restarted.

Value Stored in QSetting is not retained after the program is restarted.

Scheduled Pinned Locked Moved Unsolved General and Desktop
10 Posts 3 Posters 1.3k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    Joshi
    wrote on last edited by Joshi
    #1

    I have a class, User class which can read from a Json object and can write to Json object. As described below.

    class User
    {
    public:
        User() {}
        User(const QString& ruser_name, const QImage& rdisplay_image)
        {
            user_name = ruser_name;
            display_image = rdisplay_image;
        }
    
        QString get_user_name() const { return user_name; }
    
        void write(QJsonObject &json) const
        {
            json["user_name"] = user_name;
            json["display_image"] = getImageInJsonValueFormat(display_image);
    
        }
    
        void read(const QJsonObject &json)
        {
            if (json.contains("user_name") && json["user_name"].isString())
                user_name = json["user_name"].toString();
    
            if (json.contains("display_image"))
                display_image = getImageFromJsonValueFormat(json["display_image"]);
        }
    private:
        QString user_name;
        QImage  display_image;
    };
    

    There are two helper functions, to convert QImage from JsonValue and vice-versa. As depicted below.

    QJsonValue getImageInJsonValueFormat(const QImage& image)
    {
        QByteArray image_ByteArray;
        if (image.isNull() != true)
        {
            QBuffer image_buffer(&image_ByteArray);
            image_buffer.open(QIODevice::WriteOnly);
            image.save(&image_buffer, "png");
            auto const encoded = image_buffer.data().toBase64();
            return {QLatin1String(encoded)};
        }
        return QLatin1String("");
    }
    
    QImage getImageFromJsonValueFormat(const QJsonValue& imageJsonValue)
    {
        QImage image;
        auto const encoded = imageJsonValue.toString().toLatin1();
        image.loadFromData(QByteArray::fromBase64(encoded), "png");
        return image;
    }
    

    I have three functions. One to build the list, another to store and last one to read. As describe below

    QMap<QString, User> Build_user_list()
    {
        QMap<QString, User> user_list;
        User User1("baur",QImage("/home/Downloads/bechambaur.png"));
        user_list["baur"] = User1;
    
        User User2("Muller",QImage("/home/Downloads/GerdMuller.png"));
        user_list["Muller"] = User2;
        return user_list;
    }
    
    void StoreUserList(const QMap<QString, User> user_list)
    {
        QJsonObject userListObject;
        QJsonArray userListArray;
    
        QMapIterator<QString,User> iterator(user_list);
    
        while (iterator.hasNext())
        {
            iterator.next();
            QJsonObject userJsonObject;
            User userObj = iterator.value();
            userObj.write(userJsonObject);
            userListArray.append(userJsonObject);
        }
        userListObject["user_list"] = userListArray;
        QJsonDocument userListDoc(userListObject);
    
        QSettings user_settings;
    
        user_settings.setValue("QSettingsApplication", userListDoc);
        user_settings.sync();
    }
    
    QMap<QString, User> GetStoredList()
    {
        QMap<QString, User> user_list;
        QSettings user_settings;
        QJsonDocument userListDocRead = user_settings.value("QSettingsApplication", "").toJsonDocument();
        QJsonObject userListObjectRead = userListDocRead.object();//["userlist"];
    
        if (userListObjectRead.contains("user_list"))
        {
            if(userListObjectRead["user_list"].isArray())
            {
                QJsonArray userlistarray = userListObjectRead["user_list"].toArray();
                user_list.clear();
                for(int index = 0; index < userlistarray.size(); ++index)
                {
                    QJsonObject json_user_object = userlistarray[index].toObject();
                    User userObject;
                    userObject.read(json_user_object);
                    user_list[userObject.get_user_name()] = userObject;
                }
            }
        }
    
        return user_list;
    }
    

    In below piece of code (assuming the application is running for the first time), first call to GetStoredList results in an empty map. Later, default map is created and stored. Again GetStoredList is called, this sucessfully populates the values. However, if the application is closed and ran again, call to GetStoredList returns empty map. I expect this to fill with two objects. Whats wrong?

    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        // Why below list is empty after first successful run?
        QMap<QString, User> user_listRead = GetStoredList();
    
        if (user_listRead.size() == 0)
        {
            QMap<QString, User> user_list = Build_user_list();
            StoreUserList(user_list);
            QMap<QString, User> user_listRead = GetStoredList();
            user_listRead = GetStoredList();
            // This is is not empty, it reads contents successfully. What's wrong?
        }
        MainWindow w;
        w.show();
    
        return a.exec();
    }
    
    JonBJ 1 Reply Last reply
    0
    • J Joshi

      I have a class, User class which can read from a Json object and can write to Json object. As described below.

      class User
      {
      public:
          User() {}
          User(const QString& ruser_name, const QImage& rdisplay_image)
          {
              user_name = ruser_name;
              display_image = rdisplay_image;
          }
      
          QString get_user_name() const { return user_name; }
      
          void write(QJsonObject &json) const
          {
              json["user_name"] = user_name;
              json["display_image"] = getImageInJsonValueFormat(display_image);
      
          }
      
          void read(const QJsonObject &json)
          {
              if (json.contains("user_name") && json["user_name"].isString())
                  user_name = json["user_name"].toString();
      
              if (json.contains("display_image"))
                  display_image = getImageFromJsonValueFormat(json["display_image"]);
          }
      private:
          QString user_name;
          QImage  display_image;
      };
      

      There are two helper functions, to convert QImage from JsonValue and vice-versa. As depicted below.

      QJsonValue getImageInJsonValueFormat(const QImage& image)
      {
          QByteArray image_ByteArray;
          if (image.isNull() != true)
          {
              QBuffer image_buffer(&image_ByteArray);
              image_buffer.open(QIODevice::WriteOnly);
              image.save(&image_buffer, "png");
              auto const encoded = image_buffer.data().toBase64();
              return {QLatin1String(encoded)};
          }
          return QLatin1String("");
      }
      
      QImage getImageFromJsonValueFormat(const QJsonValue& imageJsonValue)
      {
          QImage image;
          auto const encoded = imageJsonValue.toString().toLatin1();
          image.loadFromData(QByteArray::fromBase64(encoded), "png");
          return image;
      }
      

      I have three functions. One to build the list, another to store and last one to read. As describe below

      QMap<QString, User> Build_user_list()
      {
          QMap<QString, User> user_list;
          User User1("baur",QImage("/home/Downloads/bechambaur.png"));
          user_list["baur"] = User1;
      
          User User2("Muller",QImage("/home/Downloads/GerdMuller.png"));
          user_list["Muller"] = User2;
          return user_list;
      }
      
      void StoreUserList(const QMap<QString, User> user_list)
      {
          QJsonObject userListObject;
          QJsonArray userListArray;
      
          QMapIterator<QString,User> iterator(user_list);
      
          while (iterator.hasNext())
          {
              iterator.next();
              QJsonObject userJsonObject;
              User userObj = iterator.value();
              userObj.write(userJsonObject);
              userListArray.append(userJsonObject);
          }
          userListObject["user_list"] = userListArray;
          QJsonDocument userListDoc(userListObject);
      
          QSettings user_settings;
      
          user_settings.setValue("QSettingsApplication", userListDoc);
          user_settings.sync();
      }
      
      QMap<QString, User> GetStoredList()
      {
          QMap<QString, User> user_list;
          QSettings user_settings;
          QJsonDocument userListDocRead = user_settings.value("QSettingsApplication", "").toJsonDocument();
          QJsonObject userListObjectRead = userListDocRead.object();//["userlist"];
      
          if (userListObjectRead.contains("user_list"))
          {
              if(userListObjectRead["user_list"].isArray())
              {
                  QJsonArray userlistarray = userListObjectRead["user_list"].toArray();
                  user_list.clear();
                  for(int index = 0; index < userlistarray.size(); ++index)
                  {
                      QJsonObject json_user_object = userlistarray[index].toObject();
                      User userObject;
                      userObject.read(json_user_object);
                      user_list[userObject.get_user_name()] = userObject;
                  }
              }
          }
      
          return user_list;
      }
      

      In below piece of code (assuming the application is running for the first time), first call to GetStoredList results in an empty map. Later, default map is created and stored. Again GetStoredList is called, this sucessfully populates the values. However, if the application is closed and ran again, call to GetStoredList returns empty map. I expect this to fill with two objects. Whats wrong?

      int main(int argc, char *argv[])
      {
          QApplication a(argc, argv);
      
          // Why below list is empty after first successful run?
          QMap<QString, User> user_listRead = GetStoredList();
      
          if (user_listRead.size() == 0)
          {
              QMap<QString, User> user_list = Build_user_list();
              StoreUserList(user_list);
              QMap<QString, User> user_listRead = GetStoredList();
              user_listRead = GetStoredList();
              // This is is not empty, it reads contents successfully. What's wrong?
          }
          MainWindow w;
          w.show();
      
          return a.exec();
      }
      
      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #2

      @Joshi
      Unless I am completely mad, I don't see where you think you are persisting the settings to/from external storage (.ini file, registry, whatever)? Your new QSettings() is "anonymous", no file/registry?

      1 Reply Last reply
      0
      • J Offline
        J Offline
        Joshi
        wrote on last edited by
        #3

        Thanks for response.
        I must have been more explicit in my first post. I am running this application in Ubuntu and I do not want to depend on a file location. I am more curious as to why the GetStoredList(); called second time (very independent call, everything is local to this function) reads the values successfully. Whats the difference between GetStoredList called second time in the first run and called first time in the second run?

        JonBJ 1 Reply Last reply
        0
        • J Offline
          J Offline
          Joshi
          wrote on last edited by
          #4

          I am also reading that an explicit sync of Linux is required. Looking to check where it is defined.

          1 Reply Last reply
          0
          • J Joshi

            Thanks for response.
            I must have been more explicit in my first post. I am running this application in Ubuntu and I do not want to depend on a file location. I am more curious as to why the GetStoredList(); called second time (very independent call, everything is local to this function) reads the values successfully. Whats the difference between GetStoredList called second time in the first run and called first time in the second run?

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by JonB
            #5

            @Joshi
            One of us is getting confused!

            QMap<QString, User> user_listRead = GetStoredList();
            ...
            QMap<QString, User> user_list = Build_user_list();
            StoreUserList(user_list);
            ...
            user_listRead = GetStoredList();
            

            The first call to GetStoredList(); has nothing previously saved to read from. The second GetStoredList(); gets entries just created by the StoreUserList(user_list);.

            ?

            If you want to persist settings across application runs you have to persist them somewhere, where else do you expect Linux or whatever to retrieve them from!?

            [BTW: Your code is also leaking a couple of QSettings objects. And especially given that, you will need to either sync() or explicitly destruct to save permanently.]

            J 1 Reply Last reply
            2
            • J Offline
              J Offline
              Joshi
              wrote on last edited by Joshi
              #6

              Thanks Jon

              I made a small test, exactly the same way, but this time it is plane QString object. In below example, the first read

              QString TmpString = TempSettings.value("TempLocation","").toString();)
              
              

              returns blank string during the first run. On finding blank, it is updated with some data. Application closed and restarted. Data is persistent here. That is when running application subsequently, data in TmpString is read successfully. There is something wrong with (which I am not able to get with QJsonDocument)

              
              int main(int argc, char *argv[])
              {
                  QApplication a(argc, argv);
              
                  QSettings TempSettings;
                  QString TmpString = TempSettings.value("TempLocation","").toString();
                  if (TmpString == "")
                  {
                      TempSettings.setValue("TempLocation", QString("Has this been read"));
                      TempSettings.sync();
                  }
              
              
                  // previous code
                  // Why below list is empty after first successful run?
                  QMap<QString, User> user_listRead = GetStoredList();
                  ...    
                  return a.exec();
              }
              
              
              1 Reply Last reply
              0
              • JonBJ JonB

                @Joshi
                One of us is getting confused!

                QMap<QString, User> user_listRead = GetStoredList();
                ...
                QMap<QString, User> user_list = Build_user_list();
                StoreUserList(user_list);
                ...
                user_listRead = GetStoredList();
                

                The first call to GetStoredList(); has nothing previously saved to read from. The second GetStoredList(); gets entries just created by the StoreUserList(user_list);.

                ?

                If you want to persist settings across application runs you have to persist them somewhere, where else do you expect Linux or whatever to retrieve them from!?

                [BTW: Your code is also leaking a couple of QSettings objects. And especially given that, you will need to either sync() or explicitly destruct to save permanently.]

                J Offline
                J Offline
                Joshi
                wrote on last edited by
                #7

                @JonB , I figured out the issue, but not the solution so far. The issues lies in data transforming from QVariant into QJsondoc or QSjonObject.

                Here is the simplified version of about problem

                #include <QCoreApplication>
                #include <QString>
                #include <QJsonObject>
                #include <QBuffer>
                #include <QSettings>
                #include <QJsonArray>
                #include <QJsonDocument>
                class User
                {
                public:
                    User() {}
                    User(const QString& ruser_name, const int& ruser_age)
                    {
                        user_name = ruser_name;
                        user_age = ruser_age;
                    }
                
                    QString get_user_name() const { return user_name; }
                
                    void write(QJsonObject &json) const
                    {
                        json["user_name"] = user_name;
                        json["user_age"] = user_age;
                    }
                
                    void read(const QJsonObject &json)
                    {
                        if (json.contains("user_name") && json["user_name"].isString())
                            user_name = json["user_name"].toString();
                
                        if (json.contains("user_age"))
                            user_age = json["user_name"].toInt();
                    }
                private:
                    QString user_name;
                    int user_age;
                };
                
                int main(int argc, char *argv[])
                {
                    QCoreApplication a(argc, argv);
                
                    QMap<QString, User> user_list;
                    user_list["Tom"] = User("Tom",10);
                    user_list["Henry"] = User("Henry",20);
                
                    QJsonArray userListArray;
                
                    QMapIterator<QString,User> iterator(user_list);
                
                    while (iterator.hasNext())
                    {
                        iterator.next();
                        QJsonObject userJsonObject;
                        User userObj = iterator.value();
                        userObj.write(userJsonObject);
                        userListArray.append(userJsonObject);
                    }
                
                    QJsonObject user_list_object_wrote;
                    user_list_object_wrote["user_list"] = userListArray;
                
                    QJsonDocument user_list_doc_wrote(user_list_object_wrote);
                
                    QVariant user_list_variant = user_list_doc_wrote.toVariant();
                
                    // Now read the data back into QJsonDocument/QJsonObject. Below two do not get any data.
                    QJsonDocument user_list_doc_read = user_list_variant.toJsonDocument();
                
                    QJsonObject user_list_object_read = user_list_variant.toJsonObject();
                
                    return a.exec();
                }
                
                
                jsulmJ 1 Reply Last reply
                0
                • J Joshi

                  @JonB , I figured out the issue, but not the solution so far. The issues lies in data transforming from QVariant into QJsondoc or QSjonObject.

                  Here is the simplified version of about problem

                  #include <QCoreApplication>
                  #include <QString>
                  #include <QJsonObject>
                  #include <QBuffer>
                  #include <QSettings>
                  #include <QJsonArray>
                  #include <QJsonDocument>
                  class User
                  {
                  public:
                      User() {}
                      User(const QString& ruser_name, const int& ruser_age)
                      {
                          user_name = ruser_name;
                          user_age = ruser_age;
                      }
                  
                      QString get_user_name() const { return user_name; }
                  
                      void write(QJsonObject &json) const
                      {
                          json["user_name"] = user_name;
                          json["user_age"] = user_age;
                      }
                  
                      void read(const QJsonObject &json)
                      {
                          if (json.contains("user_name") && json["user_name"].isString())
                              user_name = json["user_name"].toString();
                  
                          if (json.contains("user_age"))
                              user_age = json["user_name"].toInt();
                      }
                  private:
                      QString user_name;
                      int user_age;
                  };
                  
                  int main(int argc, char *argv[])
                  {
                      QCoreApplication a(argc, argv);
                  
                      QMap<QString, User> user_list;
                      user_list["Tom"] = User("Tom",10);
                      user_list["Henry"] = User("Henry",20);
                  
                      QJsonArray userListArray;
                  
                      QMapIterator<QString,User> iterator(user_list);
                  
                      while (iterator.hasNext())
                      {
                          iterator.next();
                          QJsonObject userJsonObject;
                          User userObj = iterator.value();
                          userObj.write(userJsonObject);
                          userListArray.append(userJsonObject);
                      }
                  
                      QJsonObject user_list_object_wrote;
                      user_list_object_wrote["user_list"] = userListArray;
                  
                      QJsonDocument user_list_doc_wrote(user_list_object_wrote);
                  
                      QVariant user_list_variant = user_list_doc_wrote.toVariant();
                  
                      // Now read the data back into QJsonDocument/QJsonObject. Below two do not get any data.
                      QJsonDocument user_list_doc_read = user_list_variant.toJsonDocument();
                  
                      QJsonObject user_list_object_read = user_list_variant.toJsonObject();
                  
                      return a.exec();
                  }
                  
                  
                  jsulmJ Offline
                  jsulmJ Offline
                  jsulm
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  @Joshi What does

                  qDebug() << user_list_doc_read;
                  

                  tell you?

                  https://forum.qt.io/topic/113070/qt-code-of-conduct

                  1 Reply Last reply
                  0
                  • J Offline
                    J Offline
                    Joshi
                    wrote on last edited by
                    #9

                    three debug statements
                    ```
                    qDebug() << "user_list_variant : <" << user_list_variant << ">" << endl;
                    qDebug() << "user_list_doc_read : <" << user_list_doc_read << ">" << endl;
                    qDebug() << "user_list_object_read : <" << user_list_object_read << ">" << endl;

                    
                    and their outputs..
                    user_list_variant : < QVariant(QVariantMap, QMap(("user_list", QVariant(QVariantList, (QVariant(QVariantMap, QMap(("user_age", QVariant(double, 20))("user_name", QVariant(QString, "Henry")))), QVariant(QVariantMap, QMap(("user_age", QVariant(double, 10))("user_name", QVariant(QString, "Tom"))))))))) > 
                    
                    user_list_doc_read : < QJsonDocument() > 
                    
                    user_list_object_read : < QJsonObject() >
                    J 1 Reply Last reply
                    0
                    • J Joshi

                      three debug statements
                      ```
                      qDebug() << "user_list_variant : <" << user_list_variant << ">" << endl;
                      qDebug() << "user_list_doc_read : <" << user_list_doc_read << ">" << endl;
                      qDebug() << "user_list_object_read : <" << user_list_object_read << ">" << endl;

                      
                      and their outputs..
                      user_list_variant : < QVariant(QVariantMap, QMap(("user_list", QVariant(QVariantList, (QVariant(QVariantMap, QMap(("user_age", QVariant(double, 20))("user_name", QVariant(QString, "Henry")))), QVariant(QVariantMap, QMap(("user_age", QVariant(double, 10))("user_name", QVariant(QString, "Tom"))))))))) > 
                      
                      user_list_doc_read : < QJsonDocument() > 
                      
                      user_list_object_read : < QJsonObject() >
                      J Offline
                      J Offline
                      Joshi
                      wrote on last edited by
                      #10

                      @jsulm , @JonB

                      Solution found:

                      QVariant::toJsonDocument does not do the opposite of QJsonDocument::toVariant.

                      Instead of using QVariant::toJsonDocument, use QJsonDocument::fromVariant, static function of QJsonDocument.

                      1 Reply Last reply
                      3

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved