Frameworks/Porting Notes/KStandardDirs: Difference between revisions

From KDE Community Wiki
(explain addResourceType)
No edit summary
Line 1: Line 1:
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).
'''A script is available in kdesdk/kde-dev-scripts/kf5/convert-kstandarddirs.pl to port some of this.'''
 
KStandardDirs is now in kdelibs4support. Apps can keep using it, but it is recommended to use QStandardPaths instead. Note that KStandardDirs makes some assumptions about all the frameworks being installed in the same location that the frameworks themselves do not.
 
Also note that $KDEDIRS and $KDEHOME do not exist anymore (no matter which class you use).
 
The porting depends on the resource type:
The porting depends on the resource type:
<pre>
<pre>
Line 91: Line 96:
QStandardPaths::locate(QStandardPaths::GenericDataLocation, "ksgmltools2/" + fileName);
QStandardPaths::locate(QStandardPaths::GenericDataLocation, "ksgmltools2/" + fileName);
</syntaxhighlight>
</syntaxhighlight>
'''A script is available in kdesdk/kde-dev-scripts/kf5/convert-kstandarddirs.pl to port some of this.'''

Revision as of 09:02, 7 June 2014

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

KStandardDirs is now in kdelibs4support. Apps can keep using it, but it is recommended to use QStandardPaths instead. Note that KStandardDirs makes some assumptions about all the frameworks being installed in the same location that the frameworks themselves do not.

Also note that $KDEDIRS and $KDEHOME do not exist anymore (no matter which class you use).

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")
becomes:
    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()) {
            files.append(it.next());
        }
    }

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.

With KStandardDirs, applications could even define their own resource types with addResourceType() or addResourceDir(). This was like creating an alias for a directory (relative or absolute) and using that later. With QStandardPaths there is no such mechanism, just use the subdir directly in your calls to QStandardPaths::locate/locateAll. For instance, this code:

KGlobal::dirs()->addResourceType("dtd", "data", "ksgmltools2/");
KStandardDirs::locate("dtd", fileName);

becomes

QStandardPaths::locate(QStandardPaths::GenericDataLocation, "ksgmltools2/" + fileName);