Return all expected paths in QStandardPaths::standardLocations

ApplicationsLocation and DataLocation were returning only the local path,
rather than system paths + local path.

Change-Id: I653d14e5bbe1e08c5fa1ecd5a6106336d1cd0369
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
David Faure 2012-03-15 12:05:58 +01:00 committed by Qt by Nokia
parent 8445c5ede7
commit 5ec5ce3549
2 changed files with 126 additions and 53 deletions

View File

@ -53,6 +53,16 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
static void appendOrganizationAndApp(QString &path)
{
const QString org = QCoreApplication::organizationName();
if (!org.isEmpty())
path += QLatin1Char('/') + org;
const QString appName = QCoreApplication::applicationName();
if (!appName.isEmpty())
path += QLatin1Char('/') + appName;
}
QString QStandardPaths::writableLocation(StandardLocation type) QString QStandardPaths::writableLocation(StandardLocation type)
{ {
switch (type) { switch (type) {
@ -67,12 +77,8 @@ QString QStandardPaths::writableLocation(StandardLocation type)
QString xdgCacheHome = QFile::decodeName(qgetenv("XDG_CACHE_HOME")); QString xdgCacheHome = QFile::decodeName(qgetenv("XDG_CACHE_HOME"));
if (xdgCacheHome.isEmpty()) if (xdgCacheHome.isEmpty())
xdgCacheHome = QDir::homePath() + QLatin1String("/.cache"); xdgCacheHome = QDir::homePath() + QLatin1String("/.cache");
if (type == QStandardPaths::CacheLocation) { if (type == QStandardPaths::CacheLocation)
if (!QCoreApplication::organizationName().isEmpty()) appendOrganizationAndApp(xdgCacheHome);
xdgCacheHome += QLatin1Char('/') + QCoreApplication::organizationName();
if (!QCoreApplication::applicationName().isEmpty())
xdgCacheHome += QLatin1Char('/') + QCoreApplication::applicationName();
}
return xdgCacheHome; return xdgCacheHome;
} }
case DataLocation: case DataLocation:
@ -81,12 +87,8 @@ QString QStandardPaths::writableLocation(StandardLocation type)
QString xdgDataHome = QFile::decodeName(qgetenv("XDG_DATA_HOME")); QString xdgDataHome = QFile::decodeName(qgetenv("XDG_DATA_HOME"));
if (xdgDataHome.isEmpty()) if (xdgDataHome.isEmpty())
xdgDataHome = QDir::homePath() + QLatin1String("/.local/share"); xdgDataHome = QDir::homePath() + QLatin1String("/.local/share");
if (type == QStandardPaths::DataLocation) { if (type == QStandardPaths::DataLocation)
if (!QCoreApplication::organizationName().isEmpty()) appendOrganizationAndApp(xdgDataHome);
xdgDataHome += QLatin1Char('/') + QCoreApplication::organizationName();
if (!QCoreApplication::applicationName().isEmpty())
xdgDataHome += QLatin1Char('/') + QCoreApplication::applicationName();
}
return xdgDataHome; return xdgDataHome;
} }
case ConfigLocation: case ConfigLocation:
@ -229,24 +231,49 @@ QString QStandardPaths::writableLocation(StandardLocation type)
return path; return path;
} }
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("/usr/local/share"));
dirs.append(QString::fromLatin1("/usr/share"));
} else {
dirs = xdgDataDirsEnv.split(QLatin1Char(':'));
}
return dirs;
}
QStringList QStandardPaths::standardLocations(StandardLocation type) QStringList QStandardPaths::standardLocations(StandardLocation type)
{ {
QStringList dirs; QStringList dirs;
if (type == ConfigLocation) { switch (type) {
case ConfigLocation:
{
// http://standards.freedesktop.org/basedir-spec/latest/ // http://standards.freedesktop.org/basedir-spec/latest/
QString xdgConfigDirs = QFile::decodeName(qgetenv("XDG_CONFIG_DIRS")); const QString xdgConfigDirs = QFile::decodeName(qgetenv("XDG_CONFIG_DIRS"));
if (xdgConfigDirs.isEmpty()) if (xdgConfigDirs.isEmpty())
dirs.append(QString::fromLatin1("/etc/xdg")); dirs.append(QString::fromLatin1("/etc/xdg"));
else else
dirs = xdgConfigDirs.split(QLatin1Char(':')); dirs = xdgConfigDirs.split(QLatin1Char(':'));
} else if (type == GenericDataLocation) { }
// http://standards.freedesktop.org/basedir-spec/latest/ break;
QString xdgConfigDirs = QFile::decodeName(qgetenv("XDG_DATA_DIRS")); case GenericDataLocation:
if (xdgConfigDirs.isEmpty()) { dirs = xdgDataDirs();
dirs.append(QString::fromLatin1("/usr/local/share")); break;
dirs.append(QString::fromLatin1("/usr/share")); case ApplicationsLocation:
} else dirs = xdgDataDirs();
dirs = xdgConfigDirs.split(QLatin1Char(':')); for (int i = 0; i < dirs.count(); ++i)
dirs[i].append(QLatin1String("/applications"));
break;
case DataLocation:
dirs = xdgDataDirs();
for (int i = 0; i < dirs.count(); ++i)
appendOrganizationAndApp(dirs[i]);
break;
default:
break;
} }
const QString localDir = writableLocation(type); const QString localDir = writableLocation(type);
dirs.prepend(localDir); dirs.prepend(localDir);

View File

@ -70,31 +70,48 @@ private slots:
private: private:
void setCustomLocations() { void setCustomLocations() {
m_thisDir = QFileInfo(QFINDTESTDATA("tst_qstandardpaths.cpp")).absolutePath(); m_localConfigDir = m_localConfigTempDir.path();
m_globalConfigDir = m_globalConfigTempDir.path();
qputenv("XDG_CONFIG_HOME", QFile::encodeName(m_thisDir)); qputenv("XDG_CONFIG_HOME", QFile::encodeName(m_localConfigDir));
QDir parent(m_thisDir); qputenv("XDG_CONFIG_DIRS", QFile::encodeName(m_globalConfigDir));
parent.cdUp(); m_localAppDir = m_localAppTempDir.path();
m_globalDir = parent.path(); // gives us a trailing slash m_globalAppDir = m_globalAppTempDir.path();
qputenv("XDG_CONFIG_DIRS", QFile::encodeName(m_globalDir)); qputenv("XDG_DATA_HOME", QFile::encodeName(m_localAppDir));
qputenv("XDG_DATA_DIRS", QFile::encodeName(m_globalAppDir));
} }
QString m_thisDir; void setDefaultLocations() {
QString m_globalDir; #ifdef Q_XDG_PLATFORM
qputenv("XDG_CONFIG_HOME", QByteArray());
qputenv("XDG_CONFIG_DIRS", QByteArray());
qputenv("XDG_DATA_HOME", QByteArray());
qputenv("XDG_DATA_DIRS", QByteArray());
#endif
}
// Config dirs
QString m_localConfigDir;
QTemporaryDir m_localConfigTempDir;
QString m_globalConfigDir;
QTemporaryDir m_globalConfigTempDir;
// App dirs
QString m_localAppDir;
QTemporaryDir m_localAppTempDir;
QString m_globalAppDir;
QTemporaryDir m_globalAppTempDir;
}; };
void tst_qstandardpaths::testDefaultLocations() void tst_qstandardpaths::testDefaultLocations()
{ {
#ifdef Q_XDG_PLATFORM #ifdef Q_XDG_PLATFORM
qputenv("XDG_CONFIG_HOME", QByteArray()); setDefaultLocations();
qputenv("XDG_CONFIG_DIRS", QByteArray());
const QString expectedConfHome = QDir::homePath() + QString::fromLatin1("/.config"); const QString expectedConfHome = QDir::homePath() + QString::fromLatin1("/.config");
QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation), expectedConfHome); QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation), expectedConfHome);
const QStringList confDirs = QStandardPaths::standardLocations(QStandardPaths::ConfigLocation); const QStringList confDirs = QStandardPaths::standardLocations(QStandardPaths::ConfigLocation);
QCOMPARE(confDirs.count(), 2); QCOMPARE(confDirs.count(), 2);
QVERIFY(confDirs.contains(expectedConfHome)); QVERIFY(confDirs.contains(expectedConfHome));
qputenv("XDG_DATA_HOME", QByteArray());
qputenv("XDG_DATA_DIRS", QByteArray());
const QStringList genericDataDirs = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); const QStringList genericDataDirs = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
QCOMPARE(genericDataDirs.count(), 3); QCOMPARE(genericDataDirs.count(), 3);
const QString expectedDataHome = QDir::homePath() + QString::fromLatin1("/.local/share"); const QString expectedDataHome = QDir::homePath() + QString::fromLatin1("/.local/share");
@ -104,46 +121,64 @@ void tst_qstandardpaths::testDefaultLocations()
#endif #endif
} }
static void createTestFile(const QString &fileName)
{
QFile file(fileName);
QVERIFY(file.open(QIODevice::WriteOnly));
QVERIFY(file.write("Hello"));
}
void tst_qstandardpaths::testCustomLocations() void tst_qstandardpaths::testCustomLocations()
{ {
#ifdef Q_XDG_PLATFORM #ifdef Q_XDG_PLATFORM
setCustomLocations(); setCustomLocations();
// test writableLocation() // test writableLocation()
QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation), m_thisDir); QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation), m_localConfigDir);
QString thisDir_base = QFileInfo(m_thisDir).fileName();
// test locate() // test locate()
const QString thisFileName = QString::fromLatin1("tst_qstandardpaths.cpp"); const QString thisFileName = QString::fromLatin1("aFile");
QVERIFY(QFile::exists(m_thisDir + '/' + thisFileName)); createTestFile(m_localConfigDir + QLatin1Char('/') + thisFileName);
const QString thisFile = QStandardPaths::locate(QStandardPaths::ConfigLocation, thisFileName); const QString thisFile = QStandardPaths::locate(QStandardPaths::ConfigLocation, thisFileName);
QVERIFY(!thisFile.isEmpty()); QVERIFY(!thisFile.isEmpty());
QVERIFY(thisFile.endsWith(thisFileName)); QVERIFY(thisFile.endsWith(thisFileName));
const QString dir = QStandardPaths::locate(QStandardPaths::ConfigLocation, QString::fromLatin1("../") + thisDir_base, QStandardPaths::LocateDirectory); const QString subdir = QString::fromLatin1("subdir");
QVERIFY(!dir.isEmpty()); const QString subdirPath = m_localConfigDir + QLatin1Char('/') + subdir;
const QString thisDirAsFile = QStandardPaths::locate(QStandardPaths::ConfigLocation, QString::fromLatin1("../") + thisDir_base); QVERIFY(QDir().mkdir(subdirPath));
const QString dir = QStandardPaths::locate(QStandardPaths::ConfigLocation, subdir, QStandardPaths::LocateDirectory);
QCOMPARE(dir, subdirPath);
const QString thisDirAsFile = QStandardPaths::locate(QStandardPaths::ConfigLocation, subdir);
QVERIFY(thisDirAsFile.isEmpty()); // not a file QVERIFY(thisDirAsFile.isEmpty()); // not a file
const QStringList dirs = QStandardPaths::standardLocations(QStandardPaths::ConfigLocation); const QStringList dirs = QStandardPaths::standardLocations(QStandardPaths::ConfigLocation);
QCOMPARE(dirs, QStringList() << m_thisDir << m_globalDir); QCOMPARE(dirs, QStringList() << m_localConfigDir << m_globalConfigDir);
#endif #endif
} }
// We really need QTemporaryDir for this test...
void tst_qstandardpaths::testLocateAll() void tst_qstandardpaths::testLocateAll()
{ {
#ifdef Q_XDG_PLATFORM #ifdef Q_XDG_PLATFORM
const QStringList appsDirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "applications", QStandardPaths::LocateDirectory);
foreach (const QString &dir, appsDirs)
QVERIFY2(dir.endsWith(QLatin1String("/share/applications")), qPrintable(dir));
setCustomLocations(); setCustomLocations();
const QStringList allFiles = QStandardPaths::locateAll(QStandardPaths::ConfigLocation, "qstandardpaths.pro"); const QStringList appsDirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "applications", QStandardPaths::LocateDirectory);
QVERIFY2(allFiles.count() > 0, "qstandardpaths.pro not found in config locations!"); QCOMPARE(appsDirs.count(), 0); // they don't exist yet
QCOMPARE(allFiles.first(), QString(m_thisDir + QString::fromLatin1("/qstandardpaths.pro"))); const QStringList expectedAppsDirs = QStringList() << m_localAppDir + QLatin1String("/applications")
<< m_globalAppDir + QLatin1String("/applications");
QDir().mkdir(expectedAppsDirs.at(0));
QDir().mkdir(expectedAppsDirs.at(1));
const QStringList appsDirs2 = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "applications", QStandardPaths::LocateDirectory);
QCOMPARE(appsDirs2, expectedAppsDirs);
const QStringList appsDirs3 = QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation);
QCOMPARE(appsDirs3, expectedAppsDirs);
const QString thisFileName = QString::fromLatin1("aFile");
const QStringList expectedFiles = QStringList() << m_localConfigDir + QLatin1Char('/') + thisFileName
<< m_globalConfigDir + QLatin1Char('/') + thisFileName;
createTestFile(expectedFiles.at(0));
createTestFile(expectedFiles.at(1));
const QStringList allFiles = QStandardPaths::locateAll(QStandardPaths::ConfigLocation, thisFileName);
QCOMPARE(allFiles, expectedFiles);
#endif #endif
} }
@ -163,6 +198,17 @@ void tst_qstandardpaths::testDataLocation()
const QString app = QStandardPaths::writableLocation(QStandardPaths::DataLocation); const QString app = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
QCOMPARE(app, base + "/Qt/QtTest"); QCOMPARE(app, base + "/Qt/QtTest");
} }
#ifdef Q_XDG_PLATFORM
setDefaultLocations();
const QString expectedAppDataDir = QDir::homePath() + QString::fromLatin1("/.local/share/Qt/QtTest");
QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::DataLocation), expectedAppDataDir);
const QStringList appDataDirs = QStandardPaths::standardLocations(QStandardPaths::DataLocation);
QCOMPARE(appDataDirs.count(), 3);
QCOMPARE(appDataDirs.at(0), expectedAppDataDir);
QCOMPARE(appDataDirs.at(1), QString::fromLatin1("/usr/local/share/Qt/QtTest"));
QCOMPARE(appDataDirs.at(2), QString::fromLatin1("/usr/share/Qt/QtTest"));
#endif
} }
void tst_qstandardpaths::testFindExecutable() void tst_qstandardpaths::testFindExecutable()