Finding locations with QDesktopServices

Published Tuesday February 26th, 2008
15 Comments on Finding locations with QDesktopServices
Posted in KDE, Qt

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");
    ...
Do you like this? Share it
Share on LinkedInGoogle+Share on FacebookTweet about this on Twitter

Posted in KDE, Qt

15 comments

Robin says:

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.

Ralf says:

These are the tiny things for which I love Qt! Great!

Will says:

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?

Erik says:

@Will: It is. He should use QDir::mkpath()

Fabrizio says:

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() πŸ˜‰

Benjamin Meyer says:

mkpath() is correct, mkdir() will only make one directory so it would fail. I have modified the example code, thanks

Erik says:

@Fabrizio: $HOME/.organizationName/applicationName/ ?

Benjamin Meyer says:

@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”

steve says:

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.

Jeff says:

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.

Fabrizio says:

@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 πŸ™‚

Benjamin Meyer says:

@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.

Benjamin Meyer says:

@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).

Felix Ritter says:

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()?

Benjamin Meyer says:

@Felix, thanks for the heads up on that. I’ll confirm that is correct and make the necessary changes.

Commenting closed.

Get started today with Qt Download now