From 64d06c1c673253cd247947e840ba96c628c1a4b1 Mon Sep 17 00:00:00 2001 From: Jeremy Katz Date: Wed, 15 Feb 2012 18:49:31 +0100 Subject: QStandardPaths implementation configured using JSON The default JSON file is /etc/user-dirs.json, but may be overridden by setting PATH_CONFIG_HOME to the file to be used. This provides functionality similar to the XDG based QStandardPaths, but uses a JSON file to define paths, rather than the XDG A=B format. Values other than HomeLocation and TempLocation may be specified by removing the "Location" postfix, converting to upper case, and separating words with _. Values are independent. For example, CacheLocation does not depend on GenericCacheLocation. Variables specified as ${[^{]*} will be replaced with environment variables. Change-Id: I374f5e6bae498dbfa9cb4ecadf915b05fb91fc34 Reviewed-by: David Faure --- src/corelib/io/io.pri | 2 + src/corelib/io/qstandardpaths_json.cpp | 184 +++++++++++++++++++++++++++++++++ 2 files changed, 186 insertions(+) create mode 100644 src/corelib/io/qstandardpaths_json.cpp (limited to 'src/corelib/io') diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index 1a73783604..2df862e360 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -106,6 +106,8 @@ win32 { } macx-*: { SOURCES += io/qstandardpaths_mac.cpp + } else:standardpathsjson { + SOURCES += io/qstandardpaths_json.cpp } else { SOURCES += io/qstandardpaths_unix.cpp } diff --git a/src/corelib/io/qstandardpaths_json.cpp b/src/corelib/io/qstandardpaths_json.cpp new file mode 100644 index 0000000000..52b194bea8 --- /dev/null +++ b/src/corelib/io/qstandardpaths_json.cpp @@ -0,0 +1,184 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qstandardpaths.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef QT_NO_STANDARDPATHS + +QT_BEGIN_NAMESPACE + +class QStandardPathsPrivate { +public: + QStandardPathsPrivate() : object(0){} + ~QStandardPathsPrivate() { delete object.load(); } + QAtomicPointer object; +}; + +Q_GLOBAL_STATIC(QStandardPathsPrivate, configCache); + +QString QStandardPaths::writableLocation(StandardLocation type) +{ + switch (type) { + case HomeLocation: + return QDir::homePath(); // set $HOME + case TempLocation: + return QDir::tempPath(); // set $TMPDIR + default: + break; + } + + QJsonObject * localConfigObject = configCache()->object.loadAcquire(); + if (localConfigObject == 0) { + QString configHome = QFile::decodeName(qgetenv("PATH_CONFIG_HOME")); + if (configHome.isEmpty()) + configHome = QLatin1String("/etc/user-dirs.json"); + QFile file(configHome); + if (file.open(QIODevice::ReadOnly)) { + QJsonDocument configDoc = QJsonDocument::fromJson(file.readAll()); + if (configDoc.isNull()) + return QString(); + + QJsonObject myConfigObject = configDoc.object(); + localConfigObject = new QJsonObject(myConfigObject); + if (!configCache()->object.testAndSetRelease(0, localConfigObject)) { + delete localConfigObject; + localConfigObject = configCache()->object.loadAcquire(); + } + } else { + return QString(); + } + } + + QLatin1String key(""); + + switch (type) { + case DocumentsLocation: + key = QLatin1String("DOCUMENTS"); + break; + case PicturesLocation: + key = QLatin1String("PICTURES"); + break; + case MusicLocation: + key = QLatin1String("MUSIC"); + break; + case MoviesLocation: + key = QLatin1String("VIDEOS"); + break; + case DownloadLocation: + key = QLatin1String("DOWNLOAD"); + break; + case ApplicationsLocation: + key = QLatin1String("APPLICATIONS"); + break; + case CacheLocation: + key = QLatin1String("CACHE"); + break; + case GenericCacheLocation: + key = QLatin1String("GENERIC_CACHE"); + break; + case DataLocation: + key = QLatin1String("DATA"); + break; + case GenericDataLocation: + key = QLatin1String("GENERIC_DATA"); + break; + case ConfigLocation: + key = QLatin1String("CONFIG"); + break; + case RuntimeLocation: + key = QLatin1String("RUNTIME"); + break; + case DesktopLocation: + key = QLatin1String("DESKTOP"); + break; + case FontsLocation: + key = QLatin1String("FONTS"); + break; + + default: + return QString(); + } + + QJsonObject::const_iterator iter = localConfigObject->constFind(key); + if (iter == localConfigObject->constEnd() || ! iter.value().isString()) + return QString(); + QString value = iter.value().toString(); + + // optimize for a common case + value.replace(QLatin1String("${HOME}"), QFile::decodeName(qgetenv("HOME"))); + + // Do ${} format environment variable substitution if necessary + if (!value.isEmpty() && value.contains(QLatin1String("${"))) { + QRegExp varRegExp(QLatin1String("\\$\\{([^\\}]*)\\}")); + while (value.contains(varRegExp)) { + QString replacement = + QFile::decodeName(qgetenv(varRegExp.cap(1).toAscii().data())); + value.replace(varRegExp.cap(0), replacement); + } + } + return value; +} + +QStringList QStandardPaths::standardLocations(StandardLocation type) +{ + QStringList dirs; + const QString localDir = writableLocation(type); + dirs.prepend(localDir); + return dirs; +} + +QString QStandardPaths::displayName(StandardLocation type) +{ + Q_UNUSED(type); + return QString(); +} + +QT_END_NAMESPACE + +#endif // QT_NO_STANDARDPATHS -- cgit v1.2.3