[KDE/Mac] QStandardPaths possible solution

Jeremy Whiting jpwhiting at kde.org
Mon Jan 5 20:51:18 UTC 2015

Ok, we've had plenty of discussion on the other thread(s) imo and should
start looking at a real solution. I see the following requirements, but
please correct me if I'm wrong.

1. It should allow adding new paths via environment variables, and probably
have a default <-- fixes CI issues on mac and also possibly runtime issues.
2. It should be fixed in Qt itself. Since Feature Freeze for Qt 5.5 is
coming up in feb this needs to start now if we hope to get the fix into 5.5
(I, for one would like this)

I've looked at Marko's patch and had to tweak it a bit to get it to apply
to qt 5.4 branch. I've attached a first try here while it builds at the
same time so I can test it.

I thought I'd also mention some long term goals/use cases for us to keep in

1. We want developers on mac to help with kde issues on mac, so getting to
the point of (install standard qt, build with kdesrc-build or manually
against it, run, profit) is a big goal for me.
2. We also want kf5 frameworks to be usable in other applications, so
having the ability to say yes, use KNewStuff3 (which stores data in a
standard place to know what it has installed, etc.) in your application on
osx is just fine and will work with any Qt >= 5.5
3. We want (maybe?) our applications to be downloadable dmg files that can
simply be copied into /Applications and run.

Actually for 3 I have some questions. On OS X do applications typically
bundle everything inside their .app or do some install for example a shared
copy of Qt or other libraries? I've seen mention of VirtualBox and other
applications on the other thread. Do they all put Qt inside their .app
folder? Do we want to do the same for kde applications to be installable
standalone, like Kate, Kanagram, Kgeography, KTuberling, KPat, etc.

4. We want macports to be able to easily create ports of our applications
and libraries. This seems like it will be provided easily if 1 is
accomplished, but may need to be kept in mind as there are some minor

So if this patch looks ok to those reading this list I'll push it to gerrit
and get the review process started. If there are things we should fix
first, let me know and I'll adapt as needed.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.kde.org/pipermail/kde-mac/attachments/20150105/55c8f8f9/attachment-0001.html>
-------------- next part --------------
diff --git a/src/corelib/io/qstandardpaths_mac.mm b/src/corelib/io/qstandardpaths_mac.mm
index 01d1c01..d2d7604 100644
--- a/src/corelib/io/qstandardpaths_mac.mm
+++ b/src/corelib/io/qstandardpaths_mac.mm
@@ -36,6 +36,11 @@
 #include <qurl.h>
 #include <private/qcore_mac_p.h>
+#include <qfile.h>
+#include <private/qfilesystemengine_p.h>
+#include <errno.h>
+#include <stdlib.h>
 #include <qcoreapplication.h>
@@ -127,7 +132,7 @@ static QString macLocation(QStandardPaths::StandardLocation type, short domain)
     if (err)
        return QString();
-   QString path = getFullPath(ref);
+    QString path = getFullPath(ref);
     if (type == QStandardPaths::AppDataLocation || type == QStandardPaths::AppLocalDataLocation || type == QStandardPaths::CacheLocation)
@@ -177,6 +182,38 @@ QString QStandardPaths::writableLocation(StandardLocation type)
+static QStringList xdgDataDirs()
+    QStringList dirs;
+    // http://standards.freedesktop.org/basedir-spec/latest/
+    QString xdgDataDirsEnv = QFile::decodeName(qgetenv("XDG_DATA_DIRS"));
+    if (xdgDataDirsEnv.isEmpty()) {
+        dirs.append(QString::fromLatin1("/opt/local/share"));
+        dirs.append(QString::fromLatin1("/Library/Application Support"));
+    } else {
+        dirs = xdgDataDirsEnv.split(QLatin1Char(':'), QString::SkipEmptyParts);
+        // Normalize paths, skip relative paths
+        QMutableListIterator<QString> it(dirs);
+        while (it.hasNext()) {
+            const QString dir = it.next();
+            if (!dir.startsWith(QLatin1Char('/')))
+                it.remove();
+            else
+                it.setValue(QDir::cleanPath(dir));
+        }
+        // Remove duplicates from the list, there's no use for duplicated
+        // paths in XDG_DATA_DIRS - if it's not found in the given
+        // directory the first time, it won't be there the second time.
+        // Plus duplicate paths causes problems for example for mimetypes,
+        // where duplicate paths here lead to duplicated mime types returned
+        // for a file, eg "text/plain,text/plain" instead of "text/plain"
+        dirs.removeDuplicates();
+    }
+    return dirs;
 QStringList QStandardPaths::standardLocations(StandardLocation type)
     QStringList dirs;
@@ -187,7 +224,15 @@ QStringList QStandardPaths::standardLocations(StandardLocation type)
+    if (type == GenericDataLocation)
+        dirs.append(xdgDataDirs());
     if (type == AppDataLocation || type == AppLocalDataLocation) {
+        QStringList xdgDirs = xdgDataDirs();
+        for (int i = 0; i < xdgDirs.count(); ++i)
+            appendOrganizationAndApp(xdgDirs[i]);
+        dirs.append(xdgDirs);
         CFBundleRef mainBundle = CFBundleGetMainBundle();
         if (mainBundle) {
             CFURLRef bundleUrl = CFBundleCopyBundleURL(mainBundle);

More information about the kde-mac mailing list