diff options
-rw-r--r-- | debian/changelog | 4 | ||||
-rw-r--r-- | debian/patches/qsettings_XDG_CONFIG_DIRS.diff | 171 | ||||
-rw-r--r-- | debian/patches/qsettings_simplify_logic.diff | 372 | ||||
-rw-r--r-- | debian/patches/series | 2 |
4 files changed, 549 insertions, 0 deletions
diff --git a/debian/changelog b/debian/changelog index b7527c4..a93aa97 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,9 @@ qtbase-opensource-src (5.7.1~20161021+dfsg-2) UNRELEASED; urgency=medium + [ Dmitry Shachnev ] + * Backport two patches to add proper support for XDG_CONFIG_DIRS to + QSettings; needed for LXQt transition (qsettings_simplify_logic.diff, + qsettings_XDG_CONFIG_DIRS.diff). -- Debian Qt/KDE Maintainers <debian-qt-kde@lists.debian.org> Sat, 22 Oct 2016 15:16:26 +0300 diff --git a/debian/patches/qsettings_XDG_CONFIG_DIRS.diff b/debian/patches/qsettings_XDG_CONFIG_DIRS.diff new file mode 100644 index 0000000..1c7974b --- /dev/null +++ b/debian/patches/qsettings_XDG_CONFIG_DIRS.diff @@ -0,0 +1,171 @@ +Description: QSettings: add proper support for XDG_CONFIG_DIRS + Update fallback mechanism for Q_XDG_PLATFORM based systems to follow the + Xdg specification. +Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=4758555f3e44af34 +Last-Update: 2016-10-22 + +--- a/src/corelib/io/qsettings.cpp ++++ b/src/corelib/io/qsettings.cpp +@@ -137,7 +137,18 @@ + + typedef QHash<QString, QConfFile *> ConfFileHash; + typedef QCache<QString, QConfFile> ConfFileCache; +-typedef QHash<int, QString> PathHash; ++namespace { ++ struct Path ++ { ++ // Note: Defining constructors explicitly because of buggy C++11 ++ // implementation in MSVC (uniform initialization). ++ Path() {} ++ Path(const QString & p, bool ud) : path(p), userDefined(ud) {} ++ QString path; ++ bool userDefined; //!< true - user defined, overridden by setPath ++ }; ++} ++typedef QHash<int, Path> PathHash; + typedef QVector<QConfFileCustomFormat> CustomFormatVector; + + Q_GLOBAL_STATIC(ConfFileHash, usedHashFunc) +@@ -1075,22 +1086,22 @@ + */ + #ifdef Q_OS_WIN + pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::UserScope), +- windowsConfigPath(CSIDL_APPDATA) + QDir::separator()); ++ Path(windowsConfigPath(CSIDL_APPDATA) + QDir::separator(), false)); + pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::SystemScope), +- windowsConfigPath(CSIDL_COMMON_APPDATA) + QDir::separator()); ++ Path(windowsConfigPath(CSIDL_COMMON_APPDATA) + QDir::separator(), false)); + #else + const QString userPath = make_user_path(); +- pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::UserScope), userPath); +- pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::SystemScope), systemPath); ++ pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::UserScope), Path(userPath, false)); ++ pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::SystemScope), Path(systemPath, false)); + #ifndef Q_OS_MAC +- pathHash->insert(pathHashKey(QSettings::NativeFormat, QSettings::UserScope), userPath); +- pathHash->insert(pathHashKey(QSettings::NativeFormat, QSettings::SystemScope), systemPath); ++ pathHash->insert(pathHashKey(QSettings::NativeFormat, QSettings::UserScope), Path(userPath, false)); ++ pathHash->insert(pathHashKey(QSettings::NativeFormat, QSettings::SystemScope), Path(systemPath, false)); + #endif + #endif // Q_OS_WIN + } + } + +-static QString getPath(QSettings::Format format, QSettings::Scope scope) ++static Path getPath(QSettings::Format format, QSettings::Scope scope) + { + Q_ASSERT((int)QSettings::NativeFormat == 0); + Q_ASSERT((int)QSettings::IniFormat == 1); +@@ -1100,14 +1111,23 @@ + if (pathHash->isEmpty()) + initDefaultPaths(&locker); + +- QString result = pathHash->value(pathHashKey(format, scope)); +- if (!result.isEmpty()) ++ Path result = pathHash->value(pathHashKey(format, scope)); ++ if (!result.path.isEmpty()) + return result; + + // fall back on INI path + return pathHash->value(pathHashKey(QSettings::IniFormat, scope)); + } + ++#if defined(QT_BUILD_INTERNAL) && defined(Q_XDG_PLATFORM) && !defined(QT_NO_STANDARDPATHS) ++// Note: Suitable only for autotests. ++void Q_AUTOTEST_EXPORT clearDefaultPaths() ++{ ++ QMutexLocker locker(&settingsGlobalMutex); ++ pathHashFunc()->clear(); ++} ++#endif // QT_BUILD_INTERNAL && Q_XDG_PLATFORM && !QT_NO_STANDARDPATHS ++ + QConfFileSettingsPrivate::QConfFileSettingsPrivate(QSettings::Format format, + QSettings::Scope scope, + const QString &organization, +@@ -1127,16 +1147,44 @@ + QString orgFile = org + extension; + + if (scope == QSettings::UserScope) { +- QString userPath = getPath(format, QSettings::UserScope); ++ Path userPath = getPath(format, QSettings::UserScope); + if (!application.isEmpty()) +- confFiles.append(QConfFile::fromName(userPath + appFile, true)); +- confFiles.append(QConfFile::fromName(userPath + orgFile, true)); ++ confFiles.append(QConfFile::fromName(userPath.path + appFile, true)); ++ confFiles.append(QConfFile::fromName(userPath.path + orgFile, true)); + } + +- QString systemPath = getPath(format, QSettings::SystemScope); +- if (!application.isEmpty()) +- confFiles.append(QConfFile::fromName(systemPath + appFile, false)); +- confFiles.append(QConfFile::fromName(systemPath + orgFile, false)); ++ Path systemPath = getPath(format, QSettings::SystemScope); ++#if defined(Q_XDG_PLATFORM) && !defined(QT_NO_STANDARDPATHS) ++ // check if the systemPath wasn't overridden by QSettings::setPath() ++ if (!systemPath.userDefined) { ++ // Note: We can't use QStandardPaths::locateAll() as we need all the ++ // possible files (not just the existing ones) and there is no way ++ // to exclude user specific (XDG_CONFIG_HOME) directory from the search. ++ QStringList dirs = QStandardPaths::standardLocations(QStandardPaths::GenericConfigLocation); ++ // remove the QStandardLocation::writableLocation() (XDG_CONFIG_HOME) ++ if (!dirs.isEmpty()) ++ dirs.takeFirst(); ++ QStringList paths; ++ if (!application.isEmpty()) { ++ paths.reserve(dirs.size() * 2); ++ for (const auto &dir : qAsConst(dirs)) ++ paths.append(dir + QLatin1Char('/') + appFile); ++ } else { ++ paths.reserve(dirs.size()); ++ } ++ for (const auto &dir : qAsConst(dirs)) ++ paths.append(dir + QLatin1Char('/') + orgFile); ++ ++ // Note: No check for existence of files is done intentionaly. ++ for (const auto &path : qAsConst(paths)) ++ confFiles.append(QConfFile::fromName(path, false)); ++ } else ++#endif // Q_XDG_PLATFORM && !QT_NO_STANDARDPATHS ++ { ++ if (!application.isEmpty()) ++ confFiles.append(QConfFile::fromName(systemPath.path + appFile, false)); ++ confFiles.append(QConfFile::fromName(systemPath.path + orgFile, false)); ++ } + + initAccess(); + } +@@ -2187,9 +2235,10 @@ + \list 1 + \li \c{$HOME/.config/MySoft/Star Runner.conf} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft/Star Runner.conf}) + \li \c{$HOME/.config/MySoft.conf} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft.conf}) +- \li \c{/etc/xdg/MySoft/Star Runner.conf} +- \li \c{/etc/xdg/MySoft.conf} ++ \li for each directory <dir> in $XDG_CONFIG_DIRS: \c{<dir>/MySoft/Star Runner.conf} ++ \li for each directory <dir> in $XDG_CONFIG_DIRS: \c{<dir>/MySoft.conf} + \endlist ++ \note If XDG_CONFIG_DIRS is unset, the default value of \c{/etc/xdg} is used. + + On \macos versions 10.2 and 10.3, these files are used by + default: +@@ -2224,9 +2273,10 @@ + \list 1 + \li \c{$HOME/.config/MySoft/Star Runner.ini} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft/Star Runner.ini}) + \li \c{$HOME/.config/MySoft.ini} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft.ini}) +- \li \c{/etc/xdg/MySoft/Star Runner.ini} +- \li \c{/etc/xdg/MySoft.ini} ++ \li for each directory <dir> in $XDG_CONFIG_DIRS: \c{<dir>/MySoft/Star Runner.ini} ++ \li for each directory <dir> in $XDG_CONFIG_DIRS: \c{<dir>/MySoft.ini} + \endlist ++ \note If XDG_CONFIG_DIRS is unset, the default value of \c{/etc/xdg} is used. + + On Windows, the following files are used: + +@@ -3378,7 +3428,7 @@ + PathHash *pathHash = pathHashFunc(); + if (pathHash->isEmpty()) + initDefaultPaths(&locker); +- pathHash->insert(pathHashKey(format, scope), path + QDir::separator()); ++ pathHash->insert(pathHashKey(format, scope), Path(path + QDir::separator(), true)); + } + + /*! diff --git a/debian/patches/qsettings_simplify_logic.diff b/debian/patches/qsettings_simplify_logic.diff new file mode 100644 index 0000000..f4b42e9 --- /dev/null +++ b/debian/patches/qsettings_simplify_logic.diff @@ -0,0 +1,372 @@ +Description: qsettings: simplify confFiles logic + Use a QVector to hold the QConfFile(s) to allow more configuration + files than the statically defined number -> this will allow considering + multiple system-wide configuration files if needed. + . + To use a dynamic container we get rid of use QScopedSharedPointer, which + actually wasn't needed anyway, as the "deref" logic was/is done manually + in the QConfFileSettingsPrivate destructor. +Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=ee35fbbf526d18d5 +Last-Update: 2016-10-22 + +--- a/src/corelib/io/qsettings.cpp ++++ b/src/corelib/io/qsettings.cpp +@@ -229,7 +229,7 @@ + // QSettingsPrivate + + QSettingsPrivate::QSettingsPrivate(QSettings::Format format) +- : format(format), scope(QSettings::UserScope /* nothing better to put */), iniCodec(0), spec(0), fallbacks(true), ++ : format(format), scope(QSettings::UserScope /* nothing better to put */), iniCodec(0), fallbacks(true), + pendingChanges(false), status(QSettings::NoError) + { + } +@@ -237,7 +237,7 @@ + QSettingsPrivate::QSettingsPrivate(QSettings::Format format, QSettings::Scope scope, + const QString &organization, const QString &application) + : format(format), scope(scope), organizationName(organization), applicationName(application), +- iniCodec(0), spec(0), fallbacks(true), pendingChanges(false), status(QSettings::NoError) ++ iniCodec(0), fallbacks(true), pendingChanges(false), status(QSettings::NoError) + { + } + +@@ -945,7 +945,7 @@ + + void QConfFileSettingsPrivate::initAccess() + { +- if (confFiles[spec]) { ++ if (!confFiles.isEmpty()) { + if (format > QSettings::IniFormat) { + if (!readFunc) + setStatus(QSettings::AccessError); +@@ -1115,7 +1115,6 @@ + : QSettingsPrivate(format, scope, organization, application), + nextPosition(0x40000000) // big positive number + { +- int i; + initFormat(); + + QString org = organization; +@@ -1130,21 +1129,14 @@ + if (scope == QSettings::UserScope) { + QString userPath = getPath(format, QSettings::UserScope); + if (!application.isEmpty()) +- confFiles[F_User | F_Application].reset(QConfFile::fromName(userPath + appFile, true)); +- confFiles[F_User | F_Organization].reset(QConfFile::fromName(userPath + orgFile, true)); ++ confFiles.append(QConfFile::fromName(userPath + appFile, true)); ++ confFiles.append(QConfFile::fromName(userPath + orgFile, true)); + } + + QString systemPath = getPath(format, QSettings::SystemScope); + if (!application.isEmpty()) +- confFiles[F_System | F_Application].reset(QConfFile::fromName(systemPath + appFile, false)); +- confFiles[F_System | F_Organization].reset(QConfFile::fromName(systemPath + orgFile, false)); +- +- for (i = 0; i < NumConfFiles; ++i) { +- if (confFiles[i]) { +- spec = i; +- break; +- } +- } ++ confFiles.append(QConfFile::fromName(systemPath + appFile, false)); ++ confFiles.append(QConfFile::fromName(systemPath + orgFile, false)); + + initAccess(); + } +@@ -1156,7 +1148,7 @@ + { + initFormat(); + +- confFiles[0].reset(QConfFile::fromName(fileName, true)); ++ confFiles.append(QConfFile::fromName(fileName, true)); + + initAccess(); + } +@@ -1167,40 +1159,39 @@ + ConfFileHash *usedHash = usedHashFunc(); + ConfFileCache *unusedCache = unusedCacheFunc(); + +- for (int i = 0; i < NumConfFiles; ++i) { +- if (confFiles[i] && !confFiles[i]->ref.deref()) { +- if (confFiles[i]->size == 0) { +- delete confFiles[i].take(); ++ for (auto conf_file : qAsConst(confFiles)) { ++ if (!conf_file->ref.deref()) { ++ if (conf_file->size == 0) { ++ delete conf_file; + } else { + if (usedHash) +- usedHash->remove(confFiles[i]->name); ++ usedHash->remove(conf_file->name); + if (unusedCache) { + QT_TRY { + // compute a better size? +- unusedCache->insert(confFiles[i]->name, confFiles[i].data(), +- 10 + (confFiles[i]->originalKeys.size() / 4)); +- confFiles[i].take(); ++ unusedCache->insert(conf_file->name, conf_file, ++ 10 + (conf_file->originalKeys.size() / 4)); + } QT_CATCH(...) { + // out of memory. Do not cache the file. +- delete confFiles[i].take(); ++ delete conf_file; + } + } else { + // unusedCache is gone - delete the entry to prevent a memory leak +- delete confFiles[i].take(); ++ delete conf_file; + } + } + } +- // prevent the ScopedPointer to deref it again. +- confFiles[i].take(); + } + } + + void QConfFileSettingsPrivate::remove(const QString &key) + { +- QConfFile *confFile = confFiles[spec].data(); +- if (!confFile) ++ if (confFiles.isEmpty()) + return; + ++ // Note: First config file is always the most specific. ++ QConfFile *confFile = confFiles.at(0); ++ + QSettingsKey theKey(key, caseSensitivity); + QSettingsKey prefix(key + QLatin1Char('/'), caseSensitivity); + QMutexLocker locker(&confFile->mutex); +@@ -1224,10 +1215,12 @@ + + void QConfFileSettingsPrivate::set(const QString &key, const QVariant &value) + { +- QConfFile *confFile = confFiles[spec].data(); +- if (!confFile) ++ if (confFiles.isEmpty()) + return; + ++ // Note: First config file is always the most specific. ++ QConfFile *confFile = confFiles.at(0); ++ + QSettingsKey theKey(key, caseSensitivity, nextPosition++); + QMutexLocker locker(&confFile->mutex); + confFile->removedKeys.remove(theKey); +@@ -1240,29 +1233,27 @@ + ParsedSettingsMap::const_iterator j; + bool found = false; + +- for (int i = 0; i < NumConfFiles; ++i) { +- if (QConfFile *confFile = confFiles[i].data()) { +- QMutexLocker locker(&confFile->mutex); +- +- if (!confFile->addedKeys.isEmpty()) { +- j = confFile->addedKeys.constFind(theKey); +- found = (j != confFile->addedKeys.constEnd()); +- } +- if (!found) { +- ensureSectionParsed(confFile, theKey); +- j = confFile->originalKeys.constFind(theKey); +- found = (j != confFile->originalKeys.constEnd() +- && !confFile->removedKeys.contains(theKey)); +- } +- +- if (found && value) +- *value = *j; ++ for (auto confFile : qAsConst(confFiles)) { ++ QMutexLocker locker(&confFile->mutex); + +- if (found) +- return true; +- if (!fallbacks) +- break; +- } ++ if (!confFile->addedKeys.isEmpty()) { ++ j = confFile->addedKeys.constFind(theKey); ++ found = (j != confFile->addedKeys.constEnd()); ++ } ++ if (!found) { ++ ensureSectionParsed(confFile, theKey); ++ j = confFile->originalKeys.constFind(theKey); ++ found = (j != confFile->originalKeys.constEnd() ++ && !confFile->removedKeys.contains(theKey)); ++ } ++ ++ if (found && value) ++ *value = *j; ++ ++ if (found) ++ return true; ++ if (!fallbacks) ++ break; + } + return false; + } +@@ -1275,34 +1266,31 @@ + QSettingsKey thePrefix(prefix, caseSensitivity); + int startPos = prefix.size(); + +- for (int i = 0; i < NumConfFiles; ++i) { +- if (QConfFile *confFile = confFiles[i].data()) { +- QMutexLocker locker(&confFile->mutex); +- +- if (thePrefix.isEmpty()) { +- ensureAllSectionsParsed(confFile); +- } else { +- ensureSectionParsed(confFile, thePrefix); +- } ++ for (auto confFile : qAsConst(confFiles)) { ++ QMutexLocker locker(&confFile->mutex); + +- j = const_cast<const ParsedSettingsMap *>( +- &confFile->originalKeys)->lowerBound( thePrefix); +- while (j != confFile->originalKeys.constEnd() && j.key().startsWith(thePrefix)) { +- if (!confFile->removedKeys.contains(j.key())) +- processChild(j.key().originalCaseKey().midRef(startPos), spec, result); +- ++j; +- } +- +- j = const_cast<const ParsedSettingsMap *>( +- &confFile->addedKeys)->lowerBound(thePrefix); +- while (j != confFile->addedKeys.constEnd() && j.key().startsWith(thePrefix)) { ++ if (thePrefix.isEmpty()) ++ ensureAllSectionsParsed(confFile); ++ else ++ ensureSectionParsed(confFile, thePrefix); ++ ++ j = const_cast<const ParsedSettingsMap *>( ++ &confFile->originalKeys)->lowerBound( thePrefix); ++ while (j != confFile->originalKeys.constEnd() && j.key().startsWith(thePrefix)) { ++ if (!confFile->removedKeys.contains(j.key())) + processChild(j.key().originalCaseKey().midRef(startPos), spec, result); +- ++j; +- } ++ ++j; ++ } + +- if (!fallbacks) +- break; ++ j = const_cast<const ParsedSettingsMap *>( ++ &confFile->addedKeys)->lowerBound(thePrefix); ++ while (j != confFile->addedKeys.constEnd() && j.key().startsWith(thePrefix)) { ++ processChild(j.key().originalCaseKey().midRef(startPos), spec, result); ++ ++j; + } ++ ++ if (!fallbacks) ++ break; + } + std::sort(result.begin(), result.end()); + result.erase(std::unique(result.begin(), result.end()), +@@ -1312,10 +1300,12 @@ + + void QConfFileSettingsPrivate::clear() + { +- QConfFile *confFile = confFiles[spec].data(); +- if (!confFile) ++ if (confFiles.isEmpty()) + return; + ++ // Note: First config file is always the most specific. ++ QConfFile *confFile = confFiles.at(0); ++ + QMutexLocker locker(&confFile->mutex); + ensureAllSectionsParsed(confFile); + confFile->addedKeys.clear(); +@@ -1327,12 +1317,9 @@ + // people probably won't be checking the status a whole lot, so in case of + // error we just try to go on and make the best of it + +- for (int i = 0; i < NumConfFiles; ++i) { +- QConfFile *confFile = confFiles[i].data(); +- if (confFile) { +- QMutexLocker locker(&confFile->mutex); +- syncConfFile(i); +- } ++ for (auto confFile : qAsConst(confFiles)) { ++ QMutexLocker locker(&confFile->mutex); ++ syncConfFile(confFile); + } + } + +@@ -1343,10 +1330,11 @@ + + QString QConfFileSettingsPrivate::fileName() const + { +- QConfFile *confFile = confFiles[spec].data(); +- if (!confFile) ++ if (confFiles.isEmpty()) + return QString(); +- return confFile->name; ++ ++ // Note: First config file is always the most specific. ++ return confFiles.at(0)->name; + } + + bool QConfFileSettingsPrivate::isWritable() const +@@ -1354,16 +1342,14 @@ + if (format > QSettings::IniFormat && !writeFunc) + return false; + +- QConfFile *confFile = confFiles[spec].data(); +- if (!confFile) ++ if (confFiles.isEmpty()) + return false; + +- return confFile->isWritable(); ++ return confFiles.at(0)->isWritable(); + } + +-void QConfFileSettingsPrivate::syncConfFile(int confFileNo) ++void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile) + { +- QConfFile *confFile = confFiles[confFileNo].data(); + bool readOnly = confFile->addedKeys.isEmpty() && confFile->removedKeys.isEmpty(); + bool ok; + +--- a/src/corelib/io/qsettings_p.h ++++ b/src/corelib/io/qsettings_p.h +@@ -236,19 +236,6 @@ + QTextCodec *codec); + static QStringList splitArgs(const QString &s, int idx); + +- /* +- The numeric values of these enums define their search order. For example, +- F_User | F_Organization is searched before F_System | F_Application, +- because their values are respectively 1 and 2. +- */ +- enum { +- F_Application = 0x0, +- F_Organization = 0x1, +- F_User = 0x0, +- F_System = 0x2, +- NumConfFiles = 4 +- }; +- + QSettings::Format format; + QSettings::Scope scope; + QString organizationName; +@@ -258,7 +245,6 @@ + protected: + QStack<QSettingsGroup> groupStack; + QString groupPrefix; +- int spec; + bool fallbacks; + bool pendingChanges; + mutable QSettings::Status status; +@@ -293,7 +279,7 @@ + private: + void initFormat(); + void initAccess(); +- void syncConfFile(int confFileNo); ++ void syncConfFile(QConfFile *confFile); + bool writeIniFile(QIODevice &device, const ParsedSettingsMap &map); + #ifdef Q_OS_MAC + bool readPlistFile(const QString &fileName, ParsedSettingsMap *map) const; +@@ -302,7 +288,7 @@ + void ensureAllSectionsParsed(QConfFile *confFile) const; + void ensureSectionParsed(QConfFile *confFile, const QSettingsKey &key) const; + +- QScopedSharedPointer<QConfFile> confFiles[NumConfFiles]; ++ QVector<QConfFile *> confFiles; + QSettings::ReadFunc readFunc; + QSettings::WriteFunc writeFunc; + QString extension; diff --git a/debian/patches/series b/debian/patches/series index c7b0d06..a82eee8 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1,4 +1,6 @@ # Backported from upstream +qsettings_simplify_logic.diff +qsettings_XDG_CONFIG_DIRS.diff no_dbus_dependency.diff # Debian specific. |