QSettings with SystemScope not saving plist file in OS X Mavericks
I have an app on OS X Mavericks (10.9.1) that uses QSettings to save some data. I can create the QSettings object like this:
@QSettings *settings = new QSettings(QSettings::UserScope, "corporation", "application");@
and the file $HOME/Library/Preferences/com.corporation.application.plist is created (as per the documentation). However, if I create the QSetting object like this:
@QSettings *settings = new QSettings(QSettings::SystemScope, "corporation", "application");@
I get no plist file created. I believe the plist file should be saved in /Library/Preferences/ com.corporation.application.plist, but that does not happen (this is perhaps not surprising, as that folder is owned by root and not writable by non-root users??). Further, the application's behavior is consistent with the settings data not being saved anywhere.
I get no notification that the settings are not saved, and it's not clear to me how I can programatically check for a failure, nor how I can determine what's wrong. I'd guess it's most likely I'm doing something wrong, but not sure what...
Urg...this is what I get for not searching adequately before posting: it seems this is a known problem, owing exactly to the permissions on /Library/Preferences ( https://bugreports.qt-project.org/browse/QTBUG-21062 ) ...looks to still be unresolved. Guess I have to use the suggested workaround of specifying a different path "/Users/Shared/Library/Preferences".
Hmm...workaround seems not to be working...what might I be doing wrong?
@QSettings *settings = new QSettings(QSettings::SystemScope, "corporation", "application");
settings->setPath(QSettings::NativeFormat, QSettings::SystemScope, path);
No plist file created at the designated path...?
It's not a bug per se, it's Apple that modified their rule. And Mavericks also introduced some new rules regarding caching of the plist.
Back to your problem, you are not using the function correctly. setPath is a static function that you must call before creating any QSettings object that will use the new path.
QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope, "/Users/Shared/Library/Preferences"); // You can call that in main.cpp after creating your QApplication
QSettings settings("corporation", "application"); // By default it uses system scope
Hope it helps
Thanks. Tried it again with the proper order, but still no go. Clobbered the prefs caches, and still nothing. Hmm...next step, probably have to build a debug lib and track down the failure... :-(
After spending a lot of time in the debugger with this, I'd say at present that SystemScope with plist files for QSettings on Mac is not a viable option for me. Instead, I've opted to use the non-native ".ini" format:
QSettings::setPath(QSettings::IniFormat, QSettings::SystemScope, path);
QSettings *settings = new QSettings(QSettings::IniFormat, QSettings::SystemScope, corporation, application);
As the intention is to have the data be "global" (different users can have access), I'm using "/Users/Shared". Doing so saves the settings in "/Users/Shared/MyCorporationName/MyAppName.ini", creating the MyCorporationName folder if it does not already exist. The (potentially new) folder and file initially have "drwxr-xr-x" and "-rw-r--r--" permissions, respectively -- that is, as one would expect with umask 0022. Haven't tested directly, but I'd expect I need to change the permissions on these in order for other users' instantiations of the app in question to be able to modify the settings.
Code archaeology notes: it seems there's a general problem with how QSettings deals with plist files, in relation to how OS X now handles plist files and caching of their content/values. Apple docs say that plist files should not be read/written to directly, but rather than the appropriate Apple APIs be used. I don't have any experience with the Apple APIs in question, but my speculation is that it may be possible to modify the Qt implementation so that it "plays well" with the system.
A possible second (and perhaps related) problem, which has been noted in the bug reports, is that the default choice for plist file storage is in /Library/Preferences, which is not user-writable. It's not entirely clear whether or not this is really a problem, though: in my experimentation, I found that the desired plist file was created, but it always remained empty. The latter phenomenon may be due to the clash with the caching system. A modified QSettings implementation may avoid this clash, and allow SystemScope plist files in /Library/Preferences to be used.
Finally, I was unable to determine why my attempts to change the path failed, when using SystemScope and plist files. My unfamiliarity with Qt code and data structures, and the techniques necessary to interrogate the latter in gdb, made it too difficult to follow why this did not seem to work for me.