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. QSettings mismatch when read by two different classes
Forum Updated to NodeBB v4.3 + New Features

QSettings mismatch when read by two different classes

Scheduled Pinned Locked Moved Solved General and Desktop
9 Posts 4 Posters 537 Views 2 Watching
  • 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.
  • P Offline
    P Offline
    Poldi
    wrote on last edited by
    #1

    I have two classes reading the same Settings file and can't work out why one of the gives the correct results, while the other doesn't

    The class that works looks something like this

    const char *NetworkRemote::kSettingsGroup = "Remote";
    
    void NetworkRemote::Init()
    {
      QSettings s_;
      s_.beginGroup(NetworkRemote::kSettingsGroup);
      use_remote_ = s_.value("useRemote").toBool();
      local_only_ = s_.value("localOnly").toBool();
      remote_port_ = s_.value("remotePort").toInt();
      ipAddr_.setAddress(s_.value("ipAddress").toString());
    
      bool aa = s_.value("useRemote").toBool();
      bool bb = s_.value("localOnly").toBool();
      int cc = s_.value("remotePort").toInt();
      QString dd =s_.value("ipAddress").toString();
      qLog(Debug) << "Settings " << s_.fileName();
      qLog(Debug) << "Keys are " << s_.allKeys();
      qLog(Debug) << "aa = " << aa;
      qLog(Debug) << "bb = " << bb;
      qLog(Debug) << "cc = " << cc;
      qLog(Debug) << "dd = " << dd;
      
    }
    
    

    The one that fails looks something like this

    const char *NetworkRemoteSettingsPage::kSettingsGroup = "Remote";
    
    void NetworkRemoteSettingsPage::Load()
    {
    QSettings s_;
    s_.beginGroup(NetworkRemoteSettingsPage::kSettingsGroup);
    
      bool aa = s_.value("useRemote").toBool();
      bool bb = s_.value("localOnly").toBool();
      int cc = s_.value("remotePort").toInt();
      QString dd =s_.value("ipAddress").toString();
      qLog(Debug) << "Settings " << s_.fileName();
      qLog(Debug) << "Keys are " << s_.allKeys();
      qLog(Debug) << "aa = " << aa;
      qLog(Debug) << "bb = " << bb;
      qLog(Debug) << "cc = " << cc;
      qLog(Debug) << "dd = " << dd;
      
    }
    

    The terminal output for works & fails are attached
    works.png
    fails.png

    Thanks

    jsulmJ Axel SpoerlA 2 Replies Last reply
    0
    • P Poldi

      I have two classes reading the same Settings file and can't work out why one of the gives the correct results, while the other doesn't

      The class that works looks something like this

      const char *NetworkRemote::kSettingsGroup = "Remote";
      
      void NetworkRemote::Init()
      {
        QSettings s_;
        s_.beginGroup(NetworkRemote::kSettingsGroup);
        use_remote_ = s_.value("useRemote").toBool();
        local_only_ = s_.value("localOnly").toBool();
        remote_port_ = s_.value("remotePort").toInt();
        ipAddr_.setAddress(s_.value("ipAddress").toString());
      
        bool aa = s_.value("useRemote").toBool();
        bool bb = s_.value("localOnly").toBool();
        int cc = s_.value("remotePort").toInt();
        QString dd =s_.value("ipAddress").toString();
        qLog(Debug) << "Settings " << s_.fileName();
        qLog(Debug) << "Keys are " << s_.allKeys();
        qLog(Debug) << "aa = " << aa;
        qLog(Debug) << "bb = " << bb;
        qLog(Debug) << "cc = " << cc;
        qLog(Debug) << "dd = " << dd;
        
      }
      
      

      The one that fails looks something like this

      const char *NetworkRemoteSettingsPage::kSettingsGroup = "Remote";
      
      void NetworkRemoteSettingsPage::Load()
      {
      QSettings s_;
      s_.beginGroup(NetworkRemoteSettingsPage::kSettingsGroup);
      
        bool aa = s_.value("useRemote").toBool();
        bool bb = s_.value("localOnly").toBool();
        int cc = s_.value("remotePort").toInt();
        QString dd =s_.value("ipAddress").toString();
        qLog(Debug) << "Settings " << s_.fileName();
        qLog(Debug) << "Keys are " << s_.allKeys();
        qLog(Debug) << "aa = " << aa;
        qLog(Debug) << "bb = " << bb;
        qLog(Debug) << "cc = " << cc;
        qLog(Debug) << "dd = " << dd;
        
      }
      

      The terminal output for works & fails are attached
      works.png
      fails.png

      Thanks

      jsulmJ Offline
      jsulmJ Offline
      jsulm
      Lifetime Qt Champion
      wrote on last edited by
      #2

      @Poldi Maybe because in first case you have s_.beginGroup(NetworkRemote::kSettingsGroup); and in the second s_.beginGroup(NetworkRemoteSettingsPage::kSettingsGroup); ?

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

      JonBJ 1 Reply Last reply
      0
      • jsulmJ jsulm

        @Poldi Maybe because in first case you have s_.beginGroup(NetworkRemote::kSettingsGroup); and in the second s_.beginGroup(NetworkRemoteSettingsPage::kSettingsGroup); ?

        JonBJ Online
        JonBJ Online
        JonB
        wrote on last edited by
        #3

        @jsulm
        No, because code posted shows/claims both these are defined as the string "Remote".

        @Poldi
        Purely at a guess, I see one reports cc = 5053 and the other cc = 5050. These do not seem like "coincidental" values. I would look at exactly where you call these and what happens in between the calls, because it sounds like things have changed. Don't forget: QSettings does not flush changed values to file immediately, you may not be looking at what you think you are. You are not using separate threads here, are you?

        1 Reply Last reply
        0
        • P Poldi

          I have two classes reading the same Settings file and can't work out why one of the gives the correct results, while the other doesn't

          The class that works looks something like this

          const char *NetworkRemote::kSettingsGroup = "Remote";
          
          void NetworkRemote::Init()
          {
            QSettings s_;
            s_.beginGroup(NetworkRemote::kSettingsGroup);
            use_remote_ = s_.value("useRemote").toBool();
            local_only_ = s_.value("localOnly").toBool();
            remote_port_ = s_.value("remotePort").toInt();
            ipAddr_.setAddress(s_.value("ipAddress").toString());
          
            bool aa = s_.value("useRemote").toBool();
            bool bb = s_.value("localOnly").toBool();
            int cc = s_.value("remotePort").toInt();
            QString dd =s_.value("ipAddress").toString();
            qLog(Debug) << "Settings " << s_.fileName();
            qLog(Debug) << "Keys are " << s_.allKeys();
            qLog(Debug) << "aa = " << aa;
            qLog(Debug) << "bb = " << bb;
            qLog(Debug) << "cc = " << cc;
            qLog(Debug) << "dd = " << dd;
            
          }
          
          

          The one that fails looks something like this

          const char *NetworkRemoteSettingsPage::kSettingsGroup = "Remote";
          
          void NetworkRemoteSettingsPage::Load()
          {
          QSettings s_;
          s_.beginGroup(NetworkRemoteSettingsPage::kSettingsGroup);
          
            bool aa = s_.value("useRemote").toBool();
            bool bb = s_.value("localOnly").toBool();
            int cc = s_.value("remotePort").toInt();
            QString dd =s_.value("ipAddress").toString();
            qLog(Debug) << "Settings " << s_.fileName();
            qLog(Debug) << "Keys are " << s_.allKeys();
            qLog(Debug) << "aa = " << aa;
            qLog(Debug) << "bb = " << bb;
            qLog(Debug) << "cc = " << cc;
            qLog(Debug) << "dd = " << dd;
            
          }
          

          The terminal output for works & fails are attached
          works.png
          fails.png

          Thanks

          Axel SpoerlA Offline
          Axel SpoerlA Offline
          Axel Spoerl
          Moderators
          wrote on last edited by Axel Spoerl
          #4

          @Poldi
          Settings get cached and what you experience looks like a race condition on the cache.
          Try sync after the modification. If you work in different threads, mutex the settings.

          Software Engineer
          The Qt Company, Oslo

          1 Reply Last reply
          0
          • P Offline
            P Offline
            Poldi
            wrote on last edited by
            #5

            Here is a bit more detail

            Yes, the two classes are in different threads, but the changes to the config file can only be made via the gui and the class NetworkRemoteSettingsPage.

            I've attached a screenshot of the config file and the gui
            conf.png
            Another interesting observation is that the changes I make via the gui always end up in the config file; it just doesn't get read correctly
            gui.png
            Here is a more code

            void NetworkRemoteSettingsPage::Load()
            {
              ui_->portSelected->setRange(5050, 65535);
              ui_->ip_address->setText("0.0.0.0");
            
              s_.beginGroup(NetworkRemoteSettingsPage::kSettingsGroup);
            
              bool aa = s_.value("useRemote").toBool();
              bool bb = s_.value("localOnly").toBool();
              int cc = s_.value("remotePort").toInt();
              QString dd =s_.value("ipAddress").toString();
              qLog(Debug) << "Settings " << s_.fileName();
              qLog(Debug) << "Keys are " << s_.allKeys();
              qLog(Debug) << "aa = " << aa;
              qLog(Debug) << "bb = " << bb;
              qLog(Debug) << "cc = " << cc;
              qLog(Debug) << "dd = " << dd;
            
              if (s_.contains("useRemote")){
                ui_->useRemoteClient->setChecked(s_.value("useRemote", false).toBool());
                if (s_.value("useRemote").toBool()){
                  ui_->localConnectionsOnly->setCheckable(true);
                  ui_->portSelected->setReadOnly(false);
                  ui_->localConnectionsOnly->setChecked(s_.value("localOnly", true).toBool());
                  ui_->portSelected->setValue(s_.value("remotePort", 5050).toInt());
                }
                else {
                  ui_->localConnectionsOnly->setCheckable(false);
                  ui_->portSelected->setReadOnly(true);
                }
              }
              else{
                qLog(Debug) << "First time run the Network Remote";
                s_.setValue("useRemote", false);
                s_.setValue("localOnly",false);
                s_.setValue("remotePort",5050);
                s_.setValue("ipAddress","0.0.0.0");
              }
              s_.endGroup();
              DisplayIP();
            
              Init(ui_->layout_networkremotesettingspage->parentWidget());
            }
            
            void NetworkRemoteSettingsPage::Save()
            {
              s_.beginGroup(NetworkRemoteSettingsPage::kSettingsGroup);
              s_.setValue("useRemote",ui_->useRemoteClient->isChecked());
              s_.setValue("localOnly",ui_->localConnectionsOnly->isChecked());
              s_.setValue("remotePort",int(ui_->portSelected->value()));
              s_.setValue("ipAddress",ipAddr_);
              s_.endGroup();
            }
            
            
            1 Reply Last reply
            0
            • P Offline
              P Offline
              Poldi
              wrote on last edited by
              #6

              I think I found the problem

              the RemoteSettingsPage code sets up a few connectors to handle the screen changes

              NetworkRemoteSettingsPage::NetworkRemoteSettingsPage(SettingsDialog *dialog, QWidget *parent) :
                  SettingsPage(dialog,parent),
                  ui_(new Ui_NetworkRemoteSettingsPage)
              {
              
                ui_->setupUi(this);
                setWindowIcon(IconLoader::Load("network-remote", true, 0,32));
                
                QObject::connect(ui_->useRemoteClient,&QCheckBox::stateChanged, this, &NetworkRemoteSettingsPage::RemoteButtonClicked);
                QObject::connect(ui_->localConnectionsOnly, &QCheckBox::stateChanged, this, &NetworkRemoteSettingsPage::LocalConnectButtonClicked);
                QObject::connect(ui_->portSelected, &QSpinBox::valueChanged, this, &NetworkRemoteSettingsPage::PortChanged);
              }
              

              Any changes invoke a Refresh(), which incokes a (Settings) Save() and then a Load().
              My expectation is/was that the

              void NetworkRemoteSettingsPage::Load()
              

              was invoked first, but what is happening is that when the page loads it triggers the PortChanged signal (not sure why), which invokes Refresh().

              1 Reply Last reply
              0
              • P Offline
                P Offline
                Poldi
                wrote on last edited by
                #7

                I changed the events and it all works now as expected

                  QObject::connect(ui_->useRemoteClient,&QAbstractButton::clicked, this, &NetworkRemoteSettingsPage::RemoteButtonClicked);
                  QObject::connect(ui_->localConnectionsOnly, &QAbstractButton::clicked, this, &NetworkRemoteSettingsPage::LocalConnectButtonClicked);
                  QObject::connect(ui_->portSelected, &QAbstractSpinBox::editingFinished, this, &NetworkRemoteSettingsPage::PortChanged);
                
                Axel SpoerlA 1 Reply Last reply
                0
                • P Poldi

                  I changed the events and it all works now as expected

                    QObject::connect(ui_->useRemoteClient,&QAbstractButton::clicked, this, &NetworkRemoteSettingsPage::RemoteButtonClicked);
                    QObject::connect(ui_->localConnectionsOnly, &QAbstractButton::clicked, this, &NetworkRemoteSettingsPage::LocalConnectButtonClicked);
                    QObject::connect(ui_->portSelected, &QAbstractSpinBox::editingFinished, this, &NetworkRemoteSettingsPage::PortChanged);
                  
                  Axel SpoerlA Offline
                  Axel SpoerlA Offline
                  Axel Spoerl
                  Moderators
                  wrote on last edited by
                  #8

                  @Poldi
                  If one thread writes settings and the other reads it, it would still consider using settings.sync() and mutexing access to settings.

                  Software Engineer
                  The Qt Company, Oslo

                  P 1 Reply Last reply
                  3
                  • Axel SpoerlA Axel Spoerl

                    @Poldi
                    If one thread writes settings and the other reads it, it would still consider using settings.sync() and mutexing access to settings.

                    P Offline
                    P Offline
                    Poldi
                    wrote on last edited by
                    #9

                    @Axel-Spoerl Sure, although the only way to change the settings is via this one gui page.
                    Thanks

                    1 Reply Last reply
                    0
                    • P Poldi has marked this topic as solved on

                    • Login

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