Frameworks/Porting Notes/KStandardDirs: Difference between revisions

From KDE Community Wiki
No edit summary
No edit summary
 
(2 intermediate revisions by 2 users not shown)
Line 8: Line 8:
<pre>
<pre>
     KStandardDirs "data" -&gt; QStandardPaths::GenericDataLocation
     KStandardDirs "data" -&gt; QStandardPaths::GenericDataLocation
     KStandardDirs "appdata" -&gt; QStandardPaths::DataLocation
     KStandardDirs "appdata" -&gt; QStandardPaths::AppDataLocation // or AppLocalDataLocation
     KStandardDirs "config" -&gt; QStandardPaths::GenericConfigLocation
     KStandardDirs "config" -&gt; QStandardPaths::GenericConfigLocation
     KStandardDirs "xdgdata-apps" -&gt; QStandardPaths::ApplicationsLocation
     KStandardDirs "xdgdata-apps" -&gt; QStandardPaths::ApplicationsLocation
Line 45: Line 45:
Example using entryList:
Example using entryList:
<syntaxhighlight lang="cpp-qt">
<syntaxhighlight lang="cpp-qt">
     QStringList files = dirs()-&gt;findAllResources("data", "foo/bar/*.desktop")
     QStringList files = dirs()->findAllResources("data", "foo/bar/*.desktop")
</syntaxhighlight>
becomes:
becomes:
<syntaxhighlight lang="cpp-qt">
     QStringList files;
     QStringList files;
     const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "foo/bar", QStandardPaths::LocateDirectory);
     const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "foo/bar", QStandardPaths::LocateDirectory);
     Q_FOREACH (const QString&amp; dir, dirs) {
     Q_FOREACH (const QString& dir, dirs) {
         const QStringList fileNames = QDir(dir).entryList(QStringList() &lt;&lt; QStringLiteral("*.desktop"));
         const QStringList fileNames = QDir(dir).entryList(QStringList() << QStringLiteral("*.desktop"));
         Q_FOREACH (const QString&amp; file, fileNames) {
         Q_FOREACH (const QString& file, fileNames) {
             files.append(dir + '/' + file);
             files.append(dir + '/' + file);
         }
         }
Line 60: Line 62:
     QStringList files;
     QStringList files;
     const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "foo/bar", QStandardPaths::LocateDirectory);
     const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "foo/bar", QStandardPaths::LocateDirectory);
     Q_FOREACH (const QString&amp; dir, dirs) {
     Q_FOREACH (const QString& dir, dirs) {
         QDirIterator it(dir, QStringList() &lt;&lt; QStringLiteral("*.desktop"));
         QDirIterator it(dir, QStringList() << QStringLiteral("*.desktop"));
         while (it.hasNext()) {
         while (it.hasNext()) {
             files.append(it.next());
             files.append(it.next());
Line 70: Line 72:
<syntaxhighlight lang="cpp-qt">
<syntaxhighlight lang="cpp-qt">
     const QStringList localeDirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("locale"), QStandardPaths::LocateDirectory);
     const QStringList localeDirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("locale"), QStandardPaths::LocateDirectory);
     Q_FOREACH (const QString &amp;localeDir, localeDirs) {
     Q_FOREACH (const QString &localeDir, localeDirs) {
         const QStringList entries = QDir(localeDir).entryList(QDir::Dirs);
         const QStringList entries = QDir(localeDir).entryList(QDir::Dirs);
         Q_FOREACH (const QString &amp;d, entries) {
         Q_FOREACH (const QString &d, entries) {
             if (QFile::exists(localeDir + '/' + d + "/entry.desktop")) {
             if (QFile::exists(localeDir + '/' + d + "/entry.desktop")) {
                 // ...
                 // ...
Line 96: Line 98:
QStandardPaths::locate(QStandardPaths::GenericDataLocation, "ksgmltools2/" + fileName);
QStandardPaths::locate(QStandardPaths::GenericDataLocation, "ksgmltools2/" + fileName);
</syntaxhighlight>
</syntaxhighlight>
For relativeLocation, see the helper method in the documentation for the method in kstandarddirs.h.

Latest revision as of 09:25, 10 September 2019

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::AppDataLocation // or AppLocalDataLocation
    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()->findAllResources("data", "foo/bar/*.desktop")

becomes:

    QStringList files;
    const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "foo/bar", QStandardPaths::LocateDirectory);
    Q_FOREACH (const QString& dir, dirs) {
        const QStringList fileNames = QDir(dir).entryList(QStringList() << QStringLiteral("*.desktop"));
        Q_FOREACH (const QString& 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& dir, dirs) {
        QDirIterator it(dir, QStringList() << 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 &localeDir, localeDirs) {
        const QStringList entries = QDir(localeDir).entryList(QDir::Dirs);
        Q_FOREACH (const QString &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);

For relativeLocation, see the helper method in the documentation for the method in kstandarddirs.h.