Qt4.4 how to get the user settings path - c++

linux: $HOME/.config
windows: %APPDATA%
mac os: $HOME/.config
It can be set using http://qt-project.org/doc/qt-4.8/qsettings.html#setPath, but it seems as I am not able to retrieve it.
http://qt-project.org/doc/qt-4.8/qlibraryinfo.html#location QLibraryInfo::LibrariesPath returns the system wide settings dir, which is not what I want.
Any ideas, or do I have to code it separately for each platform?
€: I want to create a sub directory, and store files into it. (You may punish me if this is a bad idea)

This might not answer your question directly: if you want to store per-user persistent data, shouldn't you use QDesktopServices::storageLocation(QDesktopServices::DataLocation) instead?

This is a nasty workaround. First you create QSettings, then get its location.
QSettings cfg(QSettings::IniFormat, QSettings::UserScope,
"organization", "application");
QString config_dir = QFileInfo(cfg.fileName()).absolutePath() + "/";
Credits go to the Qt Centre forum.
QSettings stores the default config in the user AppData directory. See documentation for QSettings. Also this code instructs to store the config in the Ini file format.

this works on both qt 4 and qt 5
QApplication::setApplicationName("MyApp");
QApplication::setOrganizationName("Me");
QString homePath;
#if QT_VERSION >= 0x050000
homePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
#else
homePath = QDesktopServices::storageLocation(QDesktopServices::DataLocation);
#endif

Why do you need to know the settings path? If you are going to put settings in it, you could use QSettings. I could see making a subdirectory to hold various settings, but it seems like the easiest way would be to use QSettings directly.

As far as I can tell, you can't retrieve the path. In the Qt source, src/corelib/io/qsettings.cpp, there is a function to get the path:
static QString getPath(QSettings::Format format, QSettings::Scope scope)
{
...
but it's not accessible from code using Qt. You can't copy it and use it either, because it uses internal Qt globals to store the path...
EDIT: A solution was posted, using QDesktopServices.storageLocation(QDesktopServices.DataLocation) but it doesn't do exactly what the question was asking for, i.e. if I set a custom path using QSettings.setPath() it doesn't reflect the change.

What platform are you at?
Might be related or not but in windows, the default is to write QSettings to the registry.

I read more into the question than there was as it was originally posted. It is clearer after the edits. Ok, so can't you use..
QString QSettings::fileName () const
Returns the path where settings are written to using this QSettings object are stored.
On Windows, if the format is QSettings::NativeFormat, the return value is a system registry path, not a file path.

Related

How to use Windows environment variables in Qt5

I'm working on a project, where I wanted to access a sound file from C:/Windows/media, but to keep it more general, I want to use some environment variable from the user's system.
This code works At the moment
soundURL = QUrl::fromUserInput(soundFilename,
QStringLiteral("C:/Windows/media"),
QUrl::AssumeLocalFile);
I have tried the below code, doesn't work
soundURL = QUrl::fromUserInput(soundFilename,
QStringLiteral((%%WINDIR%%)+"/media"),
QUrl::AssumeLocalFile);
How can I make use of %WINDIR% to make the path simpler and more general?
Qt5 exposes several functions to retrieve the value stored in an environment variable, namely qgetenv and qEnvironmentVariable.
As you seem to target Windows, the safer is to use QString qEnvironmentVariable(const char *varName)
QString winDirPath = qEnvironmentVariable("WINDIR");
if (!winDirPath.isNull()) {
// the environment variable WINDIR exists and has been retrieved
} else {
// the environment variable does not exists in this system
}
string path(getenv("WINDIR"));
will put %WINDIR% in a std::string. I would expect you can do the same with Qt types.
You're probably better off using Qt Standard Paths http://doc.qt.io/qt-5/qstandardpaths.html. Messing with %WINDIR% is a bit dangerous.

How to get a settings storage path in a cross-platform way in Qt?

My program needs to read/write a text (just a few lines) file with its settings to disk. To specify a path in code may work well on one platform, like windows, but if runs it on Linux, the path is not cross platform.
I am looking for a similar solution to QSettings that saves settings to different paths or has its native ways to handle this. Programmers don't need to do with the details. But the text file is not suitable to be saved as a value in QSettings.
No user interaction should be needed to obtain such path. The text file should persist across application restarts. It can't be a temporary file.
Is there an existing solution in Qt and what is the API that should be used?
The location of application-specific settings storage differs across platforms. Qt 5 provides a sensible solution via QStandardPaths.
Generally, you'd store per-user settings in QStandardPaths::writableLocation(QStandardPaths::AppDataLocation). If you wish the settings not to persist in the user's roaming profile on Windows, you can use QStandardPaths::AppLocalDataLocation, it has the meaning of AppDataLocation on non-Windows platforms.
Before you can use the standard paths, you must set your application name via QCoreApplication::setApplicationName, and your organization's name using setOrganizationName or setOrganizationDomain. The path will depend on these, so make sure they are unique for you. If you ever change them, you'll lose access to old settings, so make sure you stick with name and domain that makes sense for you.
The path is not guaranteed to exist. If it doesn't, you must create it yourself, e.g. using QDir::mkpath.
int main(int argc, char ** argv) {
QApplication app{argc, argv};
app.setOrganizationDomain("stackoverflow.com");
app.setApplicationName("Q32525196.A32535544");
auto path = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
if (path.isEmpty()) qFatal("Cannot determine settings storage location");
QDir d{path};
if (d.mkpath(d.absolutePath()) && QDir::setCurrentPath(d.absolutePath())) {
qDebug() << "settings in" << QDir::currentPath();
QFile f{"settings.txt"};
if (f.open(QIODevice::WriteOnly | QIODevice::Truncate))
f.write("Hello, World");
}
}
If you want to save some user related data, you can get user home directory path using QDir::homePath().
There is QDir to handle paths to dirs, QFileInfo for platform independent file information and QDir's homePath()
My proposal is to use these classes and use QDir::home() or QDir::homePath() to find a directory where to write to, since the user has write permissions in his homedir and it exists on each platform.
You can store file in application directory. Take a look at QCoreApplication::applicationDirPath().
From Qt documentation:
Returns the directory that contains the application executable.

Read window's registry in QT

I want to list all application which had been installed by reading uninstall registry file from HKEY_CURRENT_USER. But look like it can't be done by using QSettings, for some security reason ( i guess ).
QSettings maya("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall
People suggest to use WinAPI to accomplish this (at least, on Window platform)
Can somebody guide me how to add and use this lib please?
Thank
In order to get the list of all sub items under the "Uninstall" one in the Windows registry you need to use QSettings::childGroups() function, i.e:
QSettings m("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
QSettings::NativeFormat);
QStringList ak = m.childGroups();
This will return the list of all installed applications.
UPDATE:
After getting the list of installed applications one can read the installation details. There are two ways for doing that. For example to read the "UinstallPath" key for "Autodesk Maya 2014" application:
m.beginGroup("Autodesk Maya 2014");
QString path = m.value("UninstallPath").toString();
m.endGroup();
or simply:
QString path = m.value("Autodesk Maya 2014/UninstallPath").toString();

Can I use applicationDirPath() to access resources at a higher directory level?

In the application that I am developing (using C++ and Qt), I am using QApplication::applicationDirPath() to access some resources, with respect of the application's path.
As an example, since I want to open a HTML manual from the application, I act this way:
void MainWindow::on_actionHelp_triggered()
{
QString link = QApplication::applicationDirPath() + "/Guide/guide.html";
bool r = QDesktopServices::openUrl(QUrl::fromLocalFile(link));
}
This snippet works if the project's structure presents the path "ProjectName/bin/Release/Guide/guide.html" (since the .exe file is in "ProjectName/bin/Release/AppName.exe").
But what can I do to refer to a higher-directory-level resource? As an example, I wish my HTML file to be in "ProjectName/data/Guide/guide.html". But this way, it seems not possible to compose the path in the way I'm acting.
EDIT: After #olive's comment, I wish to clarify a thing:
"Why am I not using '../'?"
Because it won't work from Visual Studio, where I am massively launch the application to test it. From VS, in fact, I shall use "../data/Guide/guide.html", when "from the outside", I'd have to do "../../data/Guide/guide.html".
That's why (I think) QApplication::applicationDirPath() exists. However, I am not an expert, so don't blame me and correct any eventual mistake of mine, please!
Just use ... QApplication::applicationDirPath() + "/../../data/Guide/guide.html" is perfectly valid path!
Of course there is another problem. When the application is installed, the relative path will probably be different again. You either need to configure the paths in visual studio so that the relative path works both during development and after deployment, or you need to detect the layout.

How to use Qt/C++ to create/read/write files and store settings local with the program

I'm an unfortunate beginner at C++ and using the Qt GUI designer program seemed perfect for my needs, except I'm having problems trying to write out the code necessary for this. I could use the QSettings string to store local settings on the hard drive, but I personally hate it when programs do the %HOME_LOCAL%\APPS_SETTINGS bull that some do. I need to save a text file for both settings and a local\host database, within the program directory, to remember strings to read from later.
What is the line of code I need to make use of a local host text database or is there a better option? And how can I store that with the local program inside its directory?
You can use QSettings with any file, with constructor QSettings::QSettings ( const QString & fileName, Format format, QObject * parent = 0 ).
To get the program directory, you can use QCoreApplication::applicationDirPath().
So, answer to your question, statement to put after creation of QApplication instance:
QSettings *settings = new QSettings(
QCoreApplication::applicationDirPath() + "/settings.ini",
QSettings::IniFormat,
qApp);
But, as noted in the comments under question, if you're making your program for general distribution, you should use the OS default. Examine all the constructors of QSettings to see what it can do. User does not often have write permission in the application directory. Note that you can also store settings to Windows registry with QSettings::NativeFormat.