QStandardPaths: add Config and GenericData, add methods

New methods: standardLocations, locate, locateAll.

Change-Id: I60bc90f8df53727a72c4b1839ea4d1d88a204e29
Reviewed-by: Thiago Macieira (Intel) <thiago.macieira@intel.com>
This commit is contained in:
David Faure 2011-10-21 20:54:35 +02:00 committed by Qt by Nokia
parent 86558de341
commit 8f3032dfe0
6 changed files with 299 additions and 75 deletions

View File

@ -65,7 +65,8 @@ QT_BEGIN_NAMESPACE
\enum QStandardPaths::StandardLocation
This enum describes the different locations that can be queried using
methods such as QStandardPaths::storageLocation and QStandardPaths::displayName.
methods such as QStandardPaths::storageLocation, QStandardPaths::standardLocations,
and QStandardPaths::displayName.
\value DesktopLocation Returns the user's desktop directory.
\value DocumentsLocation Returns the user's document.
@ -77,19 +78,24 @@ QT_BEGIN_NAMESPACE
\value TempLocation Returns the system's temporary directory.
\value HomeLocation Returns the user's home directory.
\value DataLocation Returns a directory location where persistent
application data can be stored. QCoreApplication::applicationName
and QCoreApplication::organizationName should work on all
platforms.
application data can be stored. QCoreApplication::organizationName
and QCoreApplication::applicationName are appended to the directory location
returned for GenericDataLocation.
\value CacheLocation Returns a directory location where user-specific
non-essential (cached) data should be written.
\value GenericDataLocation Returns a directory location where persistent
data shared across applications can be stored.
\value ConfigLocation Returns a directory location where user-specific
configuration files should be written.
\sa storageLocation() displayName()
\sa storageLocation() standardLocations() displayName() locate() locateAll()
*/
/*!
\fn QString QStandardPaths::storageLocation(StandardLocation type)
Returns the default system directory where files of \a type belong, or an empty string
Returns the directory where files of \a type should be written to, or an empty string
if the location cannot be determined.
\note The storage location returned can be a directory that does not exist; i.e., it
@ -102,6 +108,74 @@ QT_BEGIN_NAMESPACE
that if executable is in ROM the folder from C drive is returned.
*/
/*!
\fn QStringList QStandardPaths::standardLocations(StandardLocation type)
Returns all the directories where files of \a type belong.
Much like the PATH variable, it returns the directories in order of priority,
starting with the user-specific storageLocation() for the \a type.
*/
// TODO add XDG_RUNTIME_DIR?
/*!
\enum QStandardPaths::LocateOption
This enum describes the different flags that can be used for
controlling the behavior of QStandardPaths::locate and
QStandardPaths::locateAll.
\value LocateFile return only files
\value LocateDirectory return only directories
*/
static bool existsAsSpecified(const QString &path, QStandardPaths::LocateOptions options)
{
if (options & QStandardPaths::LocateDirectory)
return QDir(path).exists();
return QFileInfo(path).isFile();
}
/*!
Tries to find a file or directory called \a fileName in the standard locations
for \a type.
The full path to the first file or directory (depending on \a options) found is returned.
If no such file or directory can be found, an empty string is returned.
*/
QString QStandardPaths::locate(StandardLocation type, const QString &fileName, LocateOptions options)
{
const QStringList &dirs = standardLocations(type);
for (QStringList::const_iterator dir = dirs.constBegin(); dir != dirs.constEnd(); ++dir) {
const QString path = *dir + QLatin1Char('/') + fileName;
if (existsAsSpecified(path, options))
return path;
}
return QString();
}
/*!
Tries to find all files or directories called \a fileName in the standard locations
for \a type.
The \a options flag allows to specify whether to look for files or directories.
Returns the list of all the files that were found.
*/
QStringList QStandardPaths::locateAll(StandardLocation type, const QString &fileName, LocateOptions options)
{
const QStringList &dirs = standardLocations(type);
QStringList result;
for (QStringList::const_iterator dir = dirs.constBegin(); dir != dirs.constEnd(); ++dir) {
const QString path = *dir + QLatin1Char('/') + fileName;
if (existsAsSpecified(path, options))
result.append(path);
}
return result;
}
/*!
\fn QString QStandardPaths::displayName(StandardLocation type)

View File

@ -69,11 +69,28 @@ public:
TempLocation,
HomeLocation,
DataLocation,
CacheLocation
CacheLocation,
GenericDataLocation,
ConfigLocation
};
static QString storageLocation(StandardLocation type);
static QStringList standardLocations(StandardLocation type);
enum LocateOption {
LocateFile = 0x0,
LocateDirectory = 0x1
};
Q_DECLARE_FLAGS(LocateOptions, LocateOption)
static QString locate(StandardLocation type, const QString &fileName, LocateOptions options = LocateFile);
static QStringList locateAll(StandardLocation type, const QString &fileName, LocateOptions options = LocateFile);
static QString displayName(StandardLocation type);
private:
// prevent construction
QStandardPaths();
~QStandardPaths();
};
#endif // QT_NO_STANDARDPATHS

View File

@ -56,6 +56,8 @@ QT_BEGIN_NAMESPACE
OSType translateLocation(QStandardPaths::StandardLocation type)
{
switch (type) {
case QStandardPaths::ConfigLocation:
return kPreferencesFolderType;
case QStandardPaths::DesktopLocation:
return kDesktopFolderType;
case QStandardPaths::DocumentsLocation:
@ -74,6 +76,7 @@ OSType translateLocation(QStandardPaths::StandardLocation type)
return kPictureDocumentsFolderType;
case QStandardPaths::TempLocation:
return kTemporaryFolderType;
case QStandardPaths::GenericDataLocation:
case QStandardPaths::DataLocation:
return kApplicationSupportFolderType;
case QStandardPaths::CacheLocation:
@ -94,35 +97,54 @@ static QString getFullPath(const FSRef &ref)
return QString();
}
static QString macLocation(QStandardPaths::StandardLocation type, short domain)
{
// http://developer.apple.com/documentation/Carbon/Reference/Folder_Manager/Reference/reference.html
FSRef ref;
OSErr err = FSFindFolder(domain, translateLocation(type), false, &ref);
if (err)
return QString();
QString path = getFullPath(ref);
if (type == QStandardPaths::DataLocation || type == QStandardPaths::CacheLocation) {
if (!QCoreApplication::organizationName().isEmpty())
path += QLatin1Char('/') + QCoreApplication::organizationName();
if (!QCoreApplication::applicationName().isEmpty())
path += QLatin1Char('/') + QCoreApplication::applicationName();
}
return path;
}
QString QStandardPaths::storageLocation(StandardLocation type)
{
if (type == HomeLocation)
switch (type) {
case HomeLocation:
return QDir::homePath();
case TempLocation:
return QDir::tempPath();
case GenericDataLocation:
case DataLocation:
case CacheLocation:
return macLocation(type, kUserDomain);
default:
return macLocation(type, kOnAppropriateDisk);
}
}
if (type == TempLocation)
return QDir::tempPath();
QStringList QStandardPaths::standardLocations(StandardLocation type)
{
QStringList dirs;
short domain = kOnAppropriateDisk;
if (type == DataLocation || type == CacheLocation)
domain = kUserDomain;
// http://developer.apple.com/documentation/Carbon/Reference/Folder_Manager/Reference/reference.html
FSRef ref;
OSErr err = FSFindFolder(domain, translateLocation(type), false, &ref);
if (err)
return QString();
QString path = getFullPath(ref);
if (type == DataLocation || type == CacheLocation) {
if (QCoreApplication::organizationName().isEmpty() == false)
path += QLatin1Char('/') + QCoreApplication::organizationName();
if (QCoreApplication::applicationName().isEmpty() == false)
path += QLatin1Char('/') + QCoreApplication::applicationName();
if (type == GenericDataLocation || type == DataLocation || type == CacheLocation) {
const QString path = macLocation(type, kOnAppropriateDisk);
if (!path.isEmpty())
dirs.append(path);
}
return path;
const QString localDir = storageLocation(type);
dirs.prepend(localDir);
return dirs;
}
QString QStandardPaths::displayName(StandardLocation type)

View File

@ -54,30 +54,48 @@ QT_BEGIN_NAMESPACE
QString QStandardPaths::storageLocation(StandardLocation type)
{
if (type == QStandardPaths::HomeLocation)
switch (type) {
case HomeLocation:
return QDir::homePath();
if (type == QStandardPaths::TempLocation)
case TempLocation:
return QDir::tempPath();
// http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
if (type == QStandardPaths::CacheLocation) {
QString xdgCacheHome = QLatin1String(qgetenv("XDG_CACHE_HOME"));
case CacheLocation:
{
// http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
QString xdgCacheHome = QFile::decodeName(qgetenv("XDG_CACHE_HOME"));
if (xdgCacheHome.isEmpty())
xdgCacheHome = QDir::homePath() + QLatin1String("/.cache");
xdgCacheHome += QLatin1Char('/') + QCoreApplication::organizationName()
+ QLatin1Char('/') + QCoreApplication::applicationName();
if (!QCoreApplication::organizationName().isEmpty())
xdgCacheHome += QLatin1Char('/') + QCoreApplication::organizationName();
if (!QCoreApplication::applicationName().isEmpty())
xdgCacheHome += QLatin1Char('/') + QCoreApplication::applicationName();
return xdgCacheHome;
}
if (type == QStandardPaths::DataLocation) {
QString xdgDataHome = QLatin1String(qgetenv("XDG_DATA_HOME"));
case DataLocation:
case GenericDataLocation:
{
QString xdgDataHome = QFile::decodeName(qgetenv("XDG_DATA_HOME"));
if (xdgDataHome.isEmpty())
xdgDataHome = QDir::homePath() + QLatin1String("/.local/share");
xdgDataHome += QLatin1String("/data/")
+ QCoreApplication::organizationName() + QLatin1Char('/')
+ QCoreApplication::applicationName();
if (type == QStandardPaths::DataLocation) {
if (!QCoreApplication::organizationName().isEmpty())
xdgDataHome += QLatin1Char('/') + QCoreApplication::organizationName();
if (!QCoreApplication::applicationName().isEmpty())
xdgDataHome += QLatin1Char('/') + QCoreApplication::applicationName();
}
return xdgDataHome;
}
case ConfigLocation:
{
// http://standards.freedesktop.org/basedir-spec/latest/
QString xdgConfigHome = QFile::decodeName(qgetenv("XDG_CONFIG_HOME"));
if (xdgConfigHome.isEmpty())
xdgConfigHome = QDir::homePath() + QLatin1String("/.config");
return xdgConfigHome;
}
default:
break;
}
// http://www.freedesktop.org/wiki/Software/xdg-user-dirs
QString xdgConfigHome = QLatin1String(qgetenv("XDG_CONFIG_HOME"));
@ -90,7 +108,7 @@ QString QStandardPaths::storageLocation(StandardLocation type)
// Only look for lines like: XDG_DESKTOP_DIR="$HOME/Desktop"
QRegExp exp(QLatin1String("^XDG_(.*)_DIR=(.*)$"));
while (!stream.atEnd()) {
QString line = stream.readLine();
const QString &line = stream.readLine();
if (exp.indexIn(line) != -1) {
const QStringList lst = exp.capturedTexts();
const QString key = lst.at(1);
@ -106,23 +124,35 @@ QString QStandardPaths::storageLocation(StandardLocation type)
QString key;
switch (type) {
case DesktopLocation: key = QLatin1String("DESKTOP"); break;
case DocumentsLocation: key = QLatin1String("DOCUMENTS"); break;
case PicturesLocation: key = QLatin1String("PICTURES"); break;
case MusicLocation: key = QLatin1String("MUSIC"); break;
case MoviesLocation: key = QLatin1String("VIDEOS"); break;
default: break;
case DesktopLocation:
key = QLatin1String("DESKTOP");
break;
case DocumentsLocation:
key = QLatin1String("DOCUMENTS");
break;
case PicturesLocation:
key = QLatin1String("PICTURES");
break;
case MusicLocation:
key = QLatin1String("MUSIC");
break;
case MoviesLocation:
key = QLatin1String("VIDEOS");
break;
default:
break;
}
if (!key.isEmpty() && lines.contains(key)) {
QString value = lines[key];
// value can start with $HOME
if (value.startsWith(QLatin1String("$HOME")))
value = QDir::homePath() + value.mid(5);
return value;
if (!key.isEmpty()) {
QString value = lines.value(key);
if (!value.isEmpty()) {
// value can start with $HOME
if (value.startsWith(QLatin1String("$HOME")))
value = QDir::homePath() + value.mid(5);
return value;
}
}
}
QDir emptyDir;
QString path;
switch (type) {
case DesktopLocation:
@ -148,6 +178,9 @@ QString QStandardPaths::storageLocation(StandardLocation type)
break;
case ApplicationsLocation:
path = storageLocation(GenericDataLocation) + QLatin1String("/applications");
break;
default:
break;
}
@ -155,6 +188,30 @@ QString QStandardPaths::storageLocation(StandardLocation type)
return path;
}
QStringList QStandardPaths::standardLocations(StandardLocation type)
{
QStringList dirs;
if (type == ConfigLocation) {
// http://standards.freedesktop.org/basedir-spec/latest/
QString xdgConfigDirs = QFile::decodeName(qgetenv("XDG_CONFIG_DIRS"));
if (xdgConfigDirs.isEmpty())
dirs.append(QString::fromLatin1("/etc/xdg"));
else
dirs = xdgConfigDirs.split(QLatin1Char(':'));
} else if (type == GenericDataLocation) {
// http://standards.freedesktop.org/basedir-spec/latest/
QString xdgConfigDirs = QFile::decodeName(qgetenv("XDG_DATA_DIRS"));
if (xdgConfigDirs.isEmpty()) {
dirs.append(QString::fromLatin1("/usr/local/share"));
dirs.append(QString::fromLatin1("/usr/share"));
} else
dirs = xdgConfigDirs.split(QLatin1Char(':'));
}
const QString localDir = storageLocation(type);
dirs.prepend(localDir);
return dirs;
}
QString QStandardPaths::displayName(StandardLocation type)
{
Q_UNUSED(type);

View File

@ -70,70 +70,87 @@
QT_BEGIN_NAMESPACE
QString QStandardPaths::storageLocation(StandardLocation type)
typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPWSTR, int, BOOL);
static GetSpecialFolderPath resolveGetSpecialFolderPath()
{
QString result;
static GetSpecialFolderPath gsfp = 0;
if (!gsfp) {
#ifndef Q_OS_WINCE
QSystemLibrary library(QLatin1String("shell32"));
#else
QSystemLibrary library(QLatin1String("coredll"));
#endif // Q_OS_WINCE
typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPWSTR, int, BOOL);
static GetSpecialFolderPath SHGetSpecialFolderPath =
(GetSpecialFolderPath)library.resolve("SHGetSpecialFolderPathW");
gsfp = (GetSpecialFolderPath)library.resolve("SHGetSpecialFolderPathW");
}
return gsfp;
}
static QString convertCharArray(const wchar_t *path)
{
return QDir::fromNativeSeparators(QString::fromWCharArray(path));
}
QString QStandardPaths::storageLocation(StandardLocation type)
{
QString result;
static GetSpecialFolderPath SHGetSpecialFolderPath = resolveGetSpecialFolderPath();
if (!SHGetSpecialFolderPath)
return QString();
wchar_t path[MAX_PATH];
switch (type) {
case ConfigLocation: // same as DataLocation, on Windows
case DataLocation:
case GenericDataLocation:
#if defined Q_OS_WINCE
if (SHGetSpecialFolderPath(0, path, CSIDL_APPDATA, FALSE))
#else
if (SHGetSpecialFolderPath(0, path, CSIDL_LOCAL_APPDATA, FALSE))
#endif
result = QString::fromWCharArray(path);
if (!QCoreApplication::organizationName().isEmpty())
result = result + QLatin1String("\\") + QCoreApplication::organizationName();
if (!QCoreApplication::applicationName().isEmpty())
result = result + QLatin1String("\\") + QCoreApplication::applicationName();
result = convertCharArray(path);
if (type != GenericDataLocation) {
if (!QCoreApplication::organizationName().isEmpty())
result += QLatin1Char('/') + QCoreApplication::organizationName();
if (!QCoreApplication::applicationName().isEmpty())
result += QLatin1Char('/') + QCoreApplication::applicationName();
}
break;
case DesktopLocation:
if (SHGetSpecialFolderPath(0, path, CSIDL_DESKTOPDIRECTORY, FALSE))
result = QString::fromWCharArray(path);
result = convertCharArray(path);
break;
case DocumentsLocation:
if (SHGetSpecialFolderPath(0, path, CSIDL_PERSONAL, FALSE))
result = QString::fromWCharArray(path);
result = convertCharArray(path);
break;
case FontsLocation:
if (SHGetSpecialFolderPath(0, path, CSIDL_FONTS, FALSE))
result = QString::fromWCharArray(path);
result = convertCharArray(path);
break;
case ApplicationsLocation:
if (SHGetSpecialFolderPath(0, path, CSIDL_PROGRAMS, FALSE))
result = QString::fromWCharArray(path);
result = convertCharArray(path);
break;
case MusicLocation:
if (SHGetSpecialFolderPath(0, path, CSIDL_MYMUSIC, FALSE))
result = QString::fromWCharArray(path);
result = convertCharArray(path);
break;
case MoviesLocation:
if (SHGetSpecialFolderPath(0, path, CSIDL_MYVIDEO, FALSE))
result = QString::fromWCharArray(path);
result = convertCharArray(path);
break;
case PicturesLocation:
if (SHGetSpecialFolderPath(0, path, CSIDL_MYPICTURES, FALSE))
result = QString::fromWCharArray(path);
result = convertCharArray(path);
break;
case CacheLocation:
@ -156,6 +173,42 @@ QString QStandardPaths::storageLocation(StandardLocation type)
return result;
}
QStringList QStandardPaths::standardLocations(StandardLocation type)
{
QStringList dirs;
// type-specific handling goes here
#ifndef Q_WS_WINCE
static GetSpecialFolderPath SHGetSpecialFolderPath = resolveGetSpecialFolderPath();
if (SHGetSpecialFolderPath) {
wchar_t path[MAX_PATH];
switch (type) {
case ConfigLocation: // same as DataLocation, on Windows
case DataLocation:
case GenericDataLocation:
if (SHGetSpecialFolderPath(0, path, CSIDL_COMMON_APPDATA, FALSE)) {
QString result = convertCharArray(path);
if (type != GenericDataLocation) {
if (!QCoreApplication::organizationName().isEmpty())
result += QLatin1Char('/') + QCoreApplication::organizationName();
if (!QCoreApplication::applicationName().isEmpty())
result += QLatin1Char('/') + QCoreApplication::applicationName();
}
dirs.append(result);
}
break;
default:
break;
}
}
#endif
const QString localDir = storageLocation(type);
dirs.prepend(localDir);
return dirs;
}
QString QStandardPaths::displayName(StandardLocation type)
{
Q_UNUSED(type);

View File

@ -15,6 +15,7 @@ SUBDIRS=\
qprocessenvironment \
qresourceengine \
qsettings \
qstandardpaths \
qtemporaryfile \
qtextstream \
qurl \