QSettings mismatch when read by two different classes
-
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
Thanks
-
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
Thanks
-
@Poldi Maybe because in first case you have s_.beginGroup(NetworkRemote::kSettingsGroup); and in the second s_.beginGroup(NetworkRemoteSettingsPage::kSettingsGroup); ?
@jsulm
No, because code posted shows/claims both these are defined as the string"Remote"
.@Poldi
Purely at a guess, I see one reportscc = 5053
and the othercc = 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? -
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
Thanks
-
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
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
Here is a more codevoid 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(); }
-
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 thevoid 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().
-
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);
-
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);
@Poldi
If one thread writes settings and the other reads it, it would still consider usingsettings.sync()
and mutexing access to settings. -
@Poldi
If one thread writes settings and the other reads it, it would still consider usingsettings.sync()
and mutexing access to settings.@Axel-Spoerl Sure, although the only way to change the settings is via this one gui page.
Thanks -