From: David Faure Date: Fri, 21 Oct 2011 18:54:35 +0000 (+0200) Subject: QStandardPaths: add Config and GenericData, add methods X-Git-Tag: qt-v5.0.0-alpha1~3106 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8f3032dfe080c47c6fab7244a356064ce313f050;p=profile%2Fivi%2Fqtbase.git QStandardPaths: add Config and GenericData, add methods New methods: standardLocations, locate, locateAll. Change-Id: I60bc90f8df53727a72c4b1839ea4d1d88a204e29 Reviewed-by: Thiago Macieira (Intel) --- diff --git a/src/corelib/io/qstandardpaths.cpp b/src/corelib/io/qstandardpaths.cpp index e441a21..58a6ab1 100644 --- a/src/corelib/io/qstandardpaths.cpp +++ b/src/corelib/io/qstandardpaths.cpp @@ -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) diff --git a/src/corelib/io/qstandardpaths.h b/src/corelib/io/qstandardpaths.h index 5b1bb82..1688e16 100644 --- a/src/corelib/io/qstandardpaths.h +++ b/src/corelib/io/qstandardpaths.h @@ -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 diff --git a/src/corelib/io/qstandardpaths_mac.cpp b/src/corelib/io/qstandardpaths_mac.cpp index b90cc7c..a13162c 100644 --- a/src/corelib/io/qstandardpaths_mac.cpp +++ b/src/corelib/io/qstandardpaths_mac.cpp @@ -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(); } -QString QStandardPaths::storageLocation(StandardLocation type) +static QString macLocation(QStandardPaths::StandardLocation type, short domain) { - if (type == HomeLocation) - return QDir::homePath(); - - if (type == TempLocation) - return QDir::tempPath(); + // 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(); - short domain = kOnAppropriateDisk; + QString path = getFullPath(ref); - if (type == DataLocation || type == CacheLocation) - domain = kUserDomain; + 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; +} - // 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 QStandardPaths::storageLocation(StandardLocation type) +{ + 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); + } +} - QString path = getFullPath(ref); +QStringList QStandardPaths::standardLocations(StandardLocation type) +{ + QStringList dirs; - 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) diff --git a/src/corelib/io/qstandardpaths_unix.cpp b/src/corelib/io/qstandardpaths_unix.cpp index f0c5005..5a52c25 100644 --- a/src/corelib/io/qstandardpaths_unix.cpp +++ b/src/corelib/io/qstandardpaths_unix.cpp @@ -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); diff --git a/src/corelib/io/qstandardpaths_win.cpp b/src/corelib/io/qstandardpaths_win.cpp index 7d7fbd0..497e09e 100644 --- a/src/corelib/io/qstandardpaths_win.cpp +++ b/src/corelib/io/qstandardpaths_win.cpp @@ -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); diff --git a/tests/auto/corelib/io/io.pro b/tests/auto/corelib/io/io.pro index cbe2b60..fdb8b99 100644 --- a/tests/auto/corelib/io/io.pro +++ b/tests/auto/corelib/io/io.pro @@ -15,6 +15,7 @@ SUBDIRS=\ qprocessenvironment \ qresourceengine \ qsettings \ + qstandardpaths \ qtemporaryfile \ qtextstream \ qurl \