One small feature that I have wanted Qt to have when writing applications was a way to get some common directories. Where is the desktop, the music directory, or even the location where I should store my data files? On Mac, Windows and Linux these have always been different. A big problem in adding this feature has been Linux with the lack of any sort of standard, but this past year with the xdg-user-dirs spec released and with distributions like Ubuntu and others adopting it I decided it was a good time to revisit the problem. In Qt 4.4 QDesktopServices got a new function, storageLocation that returns the default system directory where files of a certain type belong. The currently supported types are: Desktop, Documents, Fonts, Applications, Music, Movies, Pictures, Temp, Home, and Data. Note that storage location can return an empty string or even a directory that currently doesn’t exists such as where the Music directory should be, but the user deleted it.
In a media player you could set the initial directory of the file dialog to open the music directory.
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
QDesktopServices::storageLocation(QDesktopServices::MusicLocation),
tr("Media Files (*.ogg *.mp3 *.flac *.wav)"));
Or when looking to store some application data, say palettes for an image editor.
QString directory = QDesktopServices::storageLocation(QDesktopServices::DataLocation);
// embedded platforms currently don't define this location and you don't want to write to /foo
if (directory.isEmpty())
directory = QDir::homePath() + "/." + QCoreApplication::applicationName();
// the first time I am saving data
if (!QFile::exists(directory)) {
QDir dir;
dir.mkpath(directory);
}
// save my data
QFile file(directory + "/custompalettes.dat");
...
15 Responses to “Finding locations with QDesktopServices”
Brilliant! I’ve been looking for this. However, I’d really like the documentation to give example of the different locations, at least the DataLocation.
These are the tiny things for which I love Qt! Great!
Boy I wish I had this several years ago.
Anyways, one minor comment. I believe you cannot create a directory like that if the parent directory also does not exist, aka if you try to create /path/to/dir but /path or /path/to does not exist the make directory command will fail. Or is that no longer the case?
@Will: It is. He should use QDir::mkpath()
Rats, now I’ll have to trash all my platform-dependent code I wrote to achieve this ![]()
I’m not sure about the use of the Data location yet. I suppose it maps to APPDATA on win32. But where does it map on *nix?
Any chance this code will return the settings file path and integrate with QSettings (adding a flag for the system/user scope)?
Nevertheless, great works guys. You always know what programmers are looking for to satisfy their laziness, don’t you?
@Will: I suppose it should be QDir::mkpath() ![]()
mkpath() is correct, mkdir() will only make one directory so it would fail. I have modified the example code, thanks
@Fabrizio: $HOME/.organizationName/applicationName/ ?
@Fabrizio Under unix I followed the base-dir spec http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html and then place it inside data/$organizationName/$applicationName/ The base-dir spec doesn’t mention this case explicitly just gives guildlines so I consulted with a several of guys involved with freedesktop to make sure that the path was good. A sample result would be “~/.local/share/data/Trolltech/testapp”
You’ll still need platform some platform dependant stuff to do this properly though right? :
directory = QDir::homePath() + “/.” + QCoreApplication::applicationName();
That’s not going to work on windows, where it’ll be a completely different directory you want to write to.
Will Qt provide a way to change this value? If we default to using one of these values but provide no way for a user to say “okay, I want to change it to X and make that my new default value” then it’s only half-useful.
@Benjamin Thank you, it sounds interesting. I had to locate a dir for persistent data on Linux some time ago,but I didn’t think about the base-dir spec. It looks reasonable to me too ![]()
@Jeff There are no current plans to let you set the system default locations at least for 4.4. I have thought about adding some convenience functions on top of it to do things such as automatically creating the directory or letting you specify a fallback (ala qsettings.value(”key”, default)), but for now this function is small, simple and I will wait to see how exactly people use it before adding API that might not be needed (no api is the best api :). For now it is just a very basic cross platform function to get the system set locations.
@steve the “directory = QDir::homePath() + “/.” + QCoreApplication::applicationName();” was only the fallback if storageLocation failed to find anything. Under Windows, OS X and Linux StorageLocation will always return a value, but on embedded it currently returns QString(). Of course embedded is special in that you might not have any writable locations either…
It was more for example code purposes which I figured would be copied. A more legit example might be the Music directory which might not be set in which case you want to fall back to home if a directory is absolutely needed (unlike the file dialog example).
Very nice addition to Qt! But QDesktopServices::DataLocation for Mac OS X returns a wrong location. Application data should be stored at ~/Library/Application Support/ + QCoreApplication::applicationName() instead of ~/Library/ + QCoreApplication::applicationName()?
@Felix, thanks for the heads up on that. I’ll confirm that is correct and make the necessary changes.