diff --git a/src/corelib/io/qstandardpaths.cpp b/src/corelib/io/qstandardpaths.cpp index b41aee55d2f..2e16c6d1ae1 100644 --- a/src/corelib/io/qstandardpaths.cpp +++ b/src/corelib/io/qstandardpaths.cpp @@ -142,6 +142,10 @@ QT_BEGIN_NAMESPACE \value AppLocalDataLocation Returns the local settings path on the Windows operating system. On all other platforms, it returns the same value as AppDataLocation. This enum value was added in Qt 5.4. + \value AppConfigLocation Returns a directory location where user-specific + configuration files should be written. This is an application-specific directory, + and the returned path is never empty. + This enum value was added in Qt 5.5. The following table gives examples of paths on different operating systems. The first path is the writable path (unless noted). Other, additional @@ -206,6 +210,9 @@ QT_BEGIN_NAMESPACE \row \li AppLocalDataLocation \li "~/Library/Application Support/", "/Library/Application Support/". "/../Resources" \li "C:/Users//AppData/Local/", "C:/ProgramData/", "", "/data" + \row \li AppConfigLocation + \li "~/Library/Preferences/" + \li "C:/Users//AppData/Local/", "C:/ProgramData/" \endtable \table @@ -267,6 +274,9 @@ QT_BEGIN_NAMESPACE \row \li AppLocalDataLocation \li "/data", "/app/native/assets" \li "~/.local/share/", "/usr/local/share/", "/usr/share/" + \row \li AppConfigLocation + \li "/data/Settings" + \li "~/.config/", "/etc/xdg/" \endtable \table @@ -307,6 +317,8 @@ QT_BEGIN_NAMESPACE \li "/cache" (there is no shared cache) \row \li AppDataLocation \li "/files", "//files" + \row \li AppConfigLocation + \li "/files/settings" \endtable In the table above, \c is usually the organization name, the @@ -565,6 +577,8 @@ QString QStandardPaths::displayName(StandardLocation type) case AppDataLocation: case AppLocalDataLocation: return QCoreApplication::translate("QStandardPaths", "Application Data"); + case AppConfigLocation: + return QCoreApplication::translate("QStandardPaths", "Application Configuration"); } // not reached return QString(); @@ -585,7 +599,7 @@ QString QStandardPaths::displayName(StandardLocation type) This affects the locations into which test programs might write files: GenericDataLocation, DataLocation, ConfigLocation, GenericConfigLocation, - GenericCacheLocation, CacheLocation. + AppConfigLocation, GenericCacheLocation, CacheLocation. Other locations are not affected. On Unix, \c XDG_DATA_HOME is set to \e ~/.qttest/share, \c XDG_CONFIG_HOME is diff --git a/src/corelib/io/qstandardpaths.h b/src/corelib/io/qstandardpaths.h index e3054502408..60e53fe117b 100644 --- a/src/corelib/io/qstandardpaths.h +++ b/src/corelib/io/qstandardpaths.h @@ -64,6 +64,7 @@ public: GenericCacheLocation, GenericConfigLocation, AppDataLocation, + AppConfigLocation, AppLocalDataLocation = DataLocation }; diff --git a/src/corelib/io/qstandardpaths_android.cpp b/src/corelib/io/qstandardpaths_android.cpp index 958b4ea4869..b887e107e74 100644 --- a/src/corelib/io/qstandardpaths_android.cpp +++ b/src/corelib/io/qstandardpaths_android.cpp @@ -233,6 +233,7 @@ QString QStandardPaths::writableLocation(StandardLocation type) return getExternalStoragePublicDirectory("DIRECTORY_DOWNLOADS"); case QStandardPaths::GenericConfigLocation: case QStandardPaths::ConfigLocation: + case QStandardPaths::AppConfigLocation: return getFilesDir() + testDir() + QLatin1String("/settings"); case QStandardPaths::GenericDataLocation: return getExternalStorageDirectory() + testDir(); diff --git a/src/corelib/io/qstandardpaths_blackberry.cpp b/src/corelib/io/qstandardpaths_blackberry.cpp index 02d7c110aef..473da7542c7 100644 --- a/src/corelib/io/qstandardpaths_blackberry.cpp +++ b/src/corelib/io/qstandardpaths_blackberry.cpp @@ -69,6 +69,7 @@ QString QStandardPaths::writableLocation(StandardLocation type) return QDir::homePath() + testModeInsert() + QLatin1String("/Cache"); case ConfigLocation: case GenericConfigLocation: + case AppConfigLocation: return QDir::homePath() + testModeInsert() + QLatin1String("/Settings"); case GenericDataLocation: return sharedRoot + testModeInsert() + QLatin1String("/misc"); diff --git a/src/corelib/io/qstandardpaths_ios.mm b/src/corelib/io/qstandardpaths_ios.mm index 9b500f4623d..449c66fe0c9 100644 --- a/src/corelib/io/qstandardpaths_ios.mm +++ b/src/corelib/io/qstandardpaths_ios.mm @@ -103,6 +103,7 @@ QString QStandardPaths::writableLocation(StandardLocation type) break; case ConfigLocation: case GenericConfigLocation: + case AppConfigLocation: location = pathForDirectory(NSDocumentDirectory); break; case DownloadLocation: diff --git a/src/corelib/io/qstandardpaths_mac.mm b/src/corelib/io/qstandardpaths_mac.mm index 01d1c01f784..4cd71d7d52b 100644 --- a/src/corelib/io/qstandardpaths_mac.mm +++ b/src/corelib/io/qstandardpaths_mac.mm @@ -53,6 +53,7 @@ OSType translateLocation(QStandardPaths::StandardLocation type) switch (type) { case QStandardPaths::ConfigLocation: case QStandardPaths::GenericConfigLocation: + case QStandardPaths::AppConfigLocation: return kPreferencesFolderType; case QStandardPaths::DesktopLocation: return kDesktopFolderType; @@ -129,7 +130,8 @@ static QString macLocation(QStandardPaths::StandardLocation type, short domain) QString path = getFullPath(ref); - if (type == QStandardPaths::AppDataLocation || type == QStandardPaths::AppLocalDataLocation || type == QStandardPaths::CacheLocation) + if (type == QStandardPaths::AppDataLocation || type == QStandardPaths::AppLocalDataLocation || + type == QStandardPaths::CacheLocation || type == QStandardPaths::AppConfigLocation) appendOrganizationAndApp(path); return path; } @@ -155,7 +157,11 @@ QString QStandardPaths::writableLocation(StandardLocation type) return path; case GenericConfigLocation: case ConfigLocation: - return qttestDir + QLatin1String("/Preferences"); + case AppConfigLocation: + path = qttestDir + QLatin1String("/Preferences"); + if (type == AppConfigLocation) + appendOrganizationAndApp(path); + return path; default: break; } diff --git a/src/corelib/io/qstandardpaths_unix.cpp b/src/corelib/io/qstandardpaths_unix.cpp index 2ad6dfa1214..94dcbaff9a0 100644 --- a/src/corelib/io/qstandardpaths_unix.cpp +++ b/src/corelib/io/qstandardpaths_unix.cpp @@ -97,6 +97,7 @@ QString QStandardPaths::writableLocation(StandardLocation type) } case ConfigLocation: case GenericConfigLocation: + case AppConfigLocation: { // http://standards.freedesktop.org/basedir-spec/latest/ QString xdgConfigHome = QFile::decodeName(qgetenv("XDG_CONFIG_HOME")); @@ -104,6 +105,8 @@ QString QStandardPaths::writableLocation(StandardLocation type) xdgConfigHome = QDir::homePath() + QLatin1String("/.qttest/config"); if (xdgConfigHome.isEmpty()) xdgConfigHome = QDir::homePath() + QLatin1String("/.config"); + if (type == AppConfigLocation) + appendOrganizationAndApp(xdgConfigHome); return xdgConfigHome; } case RuntimeLocation: @@ -278,21 +281,31 @@ static QStringList xdgDataDirs() return dirs; } +static QStringList xdgConfigDirs() +{ + QStringList dirs; + // http://standards.freedesktop.org/basedir-spec/latest/ + const QString xdgConfigDirs = QFile::decodeName(qgetenv("XDG_CONFIG_DIRS")); + if (xdgConfigDirs.isEmpty()) + dirs.append(QString::fromLatin1("/etc/xdg")); + else + dirs = xdgConfigDirs.split(QLatin1Char(':')); + return dirs; +} + QStringList QStandardPaths::standardLocations(StandardLocation type) { QStringList dirs; switch (type) { case ConfigLocation: case GenericConfigLocation: - { - // http://standards.freedesktop.org/basedir-spec/latest/ - const QString xdgConfigDirs = QFile::decodeName(qgetenv("XDG_CONFIG_DIRS")); - if (xdgConfigDirs.isEmpty()) - dirs.append(QString::fromLatin1("/etc/xdg")); - else - dirs = xdgConfigDirs.split(QLatin1Char(':')); - } - break; + dirs = xdgConfigDirs(); + break; + case AppConfigLocation: + dirs = xdgConfigDirs(); + for (int i = 0; i < dirs.count(); ++i) + appendOrganizationAndApp(dirs[i]); + break; case GenericDataLocation: dirs = xdgDataDirs(); break; diff --git a/src/corelib/io/qstandardpaths_win.cpp b/src/corelib/io/qstandardpaths_win.cpp index 5e56db3797c..8fe4be0d5cd 100644 --- a/src/corelib/io/qstandardpaths_win.cpp +++ b/src/corelib/io/qstandardpaths_win.cpp @@ -98,6 +98,7 @@ QString QStandardPaths::writableLocation(StandardLocation type) switch (type) { case ConfigLocation: // same as AppLocalDataLocation, on Windows case GenericConfigLocation: // same as GenericDataLocation on Windows + case AppConfigLocation: case AppDataLocation: case AppLocalDataLocation: case GenericDataLocation: @@ -195,6 +196,7 @@ QStringList QStandardPaths::standardLocations(StandardLocation type) switch (type) { case ConfigLocation: // same as AppLocalDataLocation, on Windows (oversight, but too late to fix it) case GenericConfigLocation: // same as GenericDataLocation, on Windows + case AppConfigLocation: // same as AppLocalDataLocation, that one on purpose case AppDataLocation: case AppLocalDataLocation: case GenericDataLocation: diff --git a/src/corelib/io/qstandardpaths_winrt.cpp b/src/corelib/io/qstandardpaths_winrt.cpp index 5c09b4814d5..6aa31bf296d 100644 --- a/src/corelib/io/qstandardpaths_winrt.cpp +++ b/src/corelib/io/qstandardpaths_winrt.cpp @@ -67,6 +67,7 @@ QString QStandardPaths::writableLocation(StandardLocation type) switch (type) { case ConfigLocation: // same as AppLocalDataLocation, on Windows case GenericConfigLocation: // same as GenericDataLocation, on Windows + case AppConfigLocation: case AppDataLocation: case AppLocalDataLocation: case GenericDataLocation: { diff --git a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp index 21e020404be..8dc9838e4f3 100644 --- a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp +++ b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp @@ -48,7 +48,8 @@ #define Q_XDG_PLATFORM #endif -static const int MaxStandardLocation = QStandardPaths::AppDataLocation; +// Update this when adding new enum values; update enumNames too +static const int MaxStandardLocation = QStandardPaths::AppConfigLocation; class tst_qstandardpaths : public QObject { @@ -61,6 +62,7 @@ private slots: void enableTestMode(); void testLocateAll(); void testDataLocation(); + void testAppConfigLocation(); void testFindExecutable_data(); void testFindExecutable(); void testFindExecutableLinkToDirectory(); @@ -122,7 +124,8 @@ static const char * const enumNames[MaxStandardLocation + 1 - int(QStandardPaths "DownloadLocation", "GenericCacheLocation", "GenericConfigLocation", - "AppDataLocation" + "AppDataLocation", + "AppConfigLocation" }; void tst_qstandardpaths::dump() @@ -305,6 +308,27 @@ void tst_qstandardpaths::testDataLocation() QCOMPARE(appDataDirs.at(1), QString::fromLatin1("/usr/local/share/Qt/QtTest")); QCOMPARE(appDataDirs.at(2), QString::fromLatin1("/usr/share/Qt/QtTest")); #endif + + // reset for other tests + QCoreApplication::setOrganizationName(QString()); + QCoreApplication::setApplicationName(QString()); +} + +void tst_qstandardpaths::testAppConfigLocation() +{ + // On all platforms where applications are not sandboxed, + // AppConfigLocation should be GenericConfigLocation / organization name / app name +#if !defined(Q_OS_BLACKBERRY) && !defined(Q_OS_ANDROID) && !defined(Q_OS_WINRT) + const QString base = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); + QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation), base + "/tst_qstandardpaths"); + QCoreApplication::setOrganizationName("Qt"); + QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation), base + "/Qt/tst_qstandardpaths"); + QCoreApplication::setApplicationName("QtTest"); + QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation), base + "/Qt/QtTest"); + // reset for other tests + QCoreApplication::setOrganizationName(QString()); + QCoreApplication::setApplicationName(QString()); +#endif } #ifndef Q_OS_WIN