Frameworks/Porting Notes/KStandardDirs

< Frameworks‎ | Porting Notes
Revision as of 23:07, 15 February 2014 by Dfaure (talk | contribs)
Jump to: navigation, search

KDE applications can keep using it, but independent frameworks should use QStandardPaths instead (although bear in mind that KStandardDirs makes some assumptions about all the frameworks being installed in the same location that the frameworks themselves do not, and KStandardDirs also required KDEDIRS to be set correctly for some resources). The porting depends on the resource type:

    KStandardDirs "data" -> QStandardPaths::GenericDataLocation
    KStandardDirs "appdata" -> QStandardPaths::DataLocation
    KStandardDirs "config" -> QStandardPaths::GenericConfigLocation
    KStandardDirs "xdgdata-apps" -> QStandardPaths::ApplicationsLocation
    KStandardDirs "cache" -> QStandardPaths::GenericCacheLocation
    KStandardDirs "socket" -> QStandardPaths::RuntimeLocation

If the resource is available in QStandardPaths (i.e. for all of the above), then the porting is simple:

    KStandardDirs::locate("data", "kmyapp/my-data") -> QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kmyapp/my-data")
    KStandardDirs::locate("services", "foo.desktop") -> QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kde5/services/foo.desktop")
    dirs.findResource("data", relPath) -> QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kmyapp/my-data")
    dirs.findDirs("data", "kconf_update") -> QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "kconf_update", QStandardPaths::LocateDirectory)
    saveLocation -> writableLocation (note that you might have to mkpath it if it doesn't exist)
    locateLocal(type, file) -> writableLocation(type) + '/' + file (you might have to mkpath the directory)
    locateLocal(tmp, file) -> QDir::tempPath() + '/' + file
    resourceDirs("xdgdata-apps") -> QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation)  (no trailing slashes anymore though)

Otherwise, you need to use GenericDataLocation and add the subdirectory name manually.

    dirs()->resourceDirs("xdgdata-icon") -> QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "icons", QStandardPaths::LocateDirectory) // xdgata-icon is the "icons" subdir under the xdg data locations
    dirs()->findAllResources("xdgdata-mime", file) -> QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "mime/" + file)
    Similarly, xdgconf-menu is QStandardPaths::GenericConfigLocation + "menus", and xdgconf-autostart is QStandardPaths::GenericConfigLocation + "autostart";
    "xdgdata-dirs" is QStandardPaths::GenericDataLocation + "desktop-directories"
    "templates" is QStandardPaths::GenericDataLocation + "templates"
    "emoticons" is QStandardPaths::GenericDataLocation + "emoticons
    "html" is QStandardPaths::GenericDataLocation + "doc/HTML"
    "sound" is QStandardPaths::GenericDataLocation + "sounds" (note the additional 's')
    "wallpaper" is QStandardPaths::GenericDataLocation + "wallpapers" (note the additional 's')
    "apps" was the kde3 "applnk" directory. Remove this compatibility code altogether, or port it to xdgdata-apps, i.e. QStandardPaths::ApplicationsLocation.
    (see kstandarddirs.cpp line 119 ff for resources that are missing here)

When the code uses wildcard filters or the Recursive flag in findAllResources, you cannot port it to one line of QStandardPaths. Either keep using KStandardDirs, or write your own filtering (QDir::entryList) or recursive listing (use QDirIterator with the Subdirectories flag). Also, check for absolute paths first, findAllResources(res, "/absolute/path") returned the path, QStandardPaths doesn't.
If NoDuplicates was used, make a unique list of relative paths first, then use locate on each one (see autostart.cpp for an example).
Example using entryList:

    QStringList files = dirs()-&gt;findAllResources("data", "foo/bar/*.desktop")
    QStringList files;
    const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "foo/bar", QStandardPaths::LocateDirectory);
    Q_FOREACH (const QString&amp; dir, dirs) {
        const QStringList fileNames = QDir(dir).entryList(QStringList() &lt;&lt; QStringLiteral("*.desktop"));
        Q_FOREACH (const QString&amp; file, fileNames) {
            files.append(dir + '/' + file);

Example using QDirIterator:

    QStringList files;
    const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "foo/bar", QStandardPaths::LocateDirectory);
    Q_FOREACH (const QString&amp; dir, dirs) {
        QDirIterator it(dir, QStringList() &lt;&lt; QStringLiteral("*.desktop"));
        while (it.hasNext()) {

On the other hand, findAllResources("locale", "*/entry.desktop") requires

    const QStringList localeDirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("locale"), QStandardPaths::LocateDirectory);
    Q_FOREACH (const QString &amp;localeDir, localeDirs) {
        const QStringList entries = QDir(localeDir).entryList(QDir::Dirs);
        Q_FOREACH (const QString &amp;d, entries) {
            if (QFile::exists(localeDir + '/' + d + "/entry.desktop")) {
                // ...

KStandardDirs::findExe (and the use of the "exe" resource) can be ported to QStandardPaths::findExecutable, except when the executable comes from libexec, in which case the path should just be hardcoded using CMAKE_INSTALL_PREFIX "/" LIBEXEC_INSTALL_DIR.

The "lib" resource was not used directly in code (the linker finds shared libs, not the code).

The "module" resource, on the other hand, was used to locate plugins. KPluginLoader now uses QT_PLUGIN_PATH instead, and looks in the kf5 subdirectory. Please email [email protected] if you would need public API for this.

A script is available in kdesdk/kde-dev-scripts/kf5/ to port some of this.

Content is available under Creative Commons License SA 4.0 unless otherwise noted.