diff --git a/src/core/ksharedconfig.cpp b/src/core/ksharedconfig.cpp index 0b2b9c3..0530aba 100644 --- a/src/core/ksharedconfig.cpp +++ b/src/core/ksharedconfig.cpp @@ -1,149 +1,160 @@ /* This file is part of the KDE libraries Copyright (c) 1999 Preston Brown Copyright (C) 1997-1999 Matthias Kalle Dalheimer (kalle@kde.org) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "ksharedconfig.h" #include "kconfigbackend_p.h" #include "kconfiggroup.h" #include "kconfig_p.h" #include #include #include void _k_globalMainConfigSync(); class GlobalSharedConfigList : public QList { public: GlobalSharedConfigList() : wasTestModeEnabled(false) { if (!qApp || QThread::currentThread() == qApp->thread()) { // We want to force the sync() before the QCoreApplication // instance is gone. Otherwise we trigger a QLockFile::lock() // after QCoreApplication is gone, calling qAppName() for a non // existent app... qAddPostRoutine(&_k_globalMainConfigSync); } // In other threads, QThreadStorage takes care of deleting the GlobalSharedConfigList when // the thread exits. } // in addition to the list, we need to hold the main config, // so that it's not created and destroyed all the time. KSharedConfigPtr mainConfig; bool wasTestModeEnabled; }; static QThreadStorage s_storage; template T * perThreadGlobalStatic() { if (!s_storage.hasLocalData()) { s_storage.setLocalData(new T); } return s_storage.localData(); } // Q_GLOBAL_STATIC(GlobalSharedConfigList, globalSharedConfigList), but per thread: static GlobalSharedConfigList *globalSharedConfigList() { return perThreadGlobalStatic(); } void _k_globalMainConfigSync() { KSharedConfigPtr mainConfig = globalSharedConfigList()->mainConfig; if (mainConfig) { mainConfig->sync(); } } KSharedConfigPtr KSharedConfig::openConfig(const QString &_fileName, OpenFlags flags, QStandardPaths::StandardLocation resType) { QString fileName(_fileName); GlobalSharedConfigList *list = globalSharedConfigList(); if (fileName.isEmpty() && !flags.testFlag(KConfig::SimpleConfig)) { // Determine the config file name that KConfig will make up (see KConfigPrivate::changeFileName) fileName = KConfig::mainConfigName(); } if (!list->wasTestModeEnabled && QStandardPaths::isTestModeEnabled()) { list->wasTestModeEnabled = true; list->clear(); list->mainConfig = nullptr; } for (auto cfg : qAsConst(*list)) { if (cfg->name() == fileName && cfg->d_ptr->openFlags == flags && cfg->locationType() == resType // cfg->backend()->type() == backend ) { return KSharedConfigPtr(cfg); } } KSharedConfigPtr ptr(new KSharedConfig(fileName, flags, resType)); if (_fileName.isEmpty() && flags == FullConfig && resType == QStandardPaths::GenericConfigLocation) { list->mainConfig = ptr; const bool isMainThread = !qApp || QThread::currentThread() == qApp->thread(); static bool userWarned = false; if (isMainThread && !userWarned) { userWarned = true; const bool isReadOnly = qEnvironmentVariableIsEmpty("KDE_HOME_READONLY"); if (isReadOnly && QCoreApplication::applicationName() != QLatin1String("kdialog")) { if (ptr->group("General").readEntry(QStringLiteral("warn_unwritable_config"), true)) { ptr->isConfigWritable(true); } } } } return ptr; } +KSharedConfig::Ptr KSharedConfig::openStateConfig(const QString &_fileName) +{ + QString fileName(_fileName); + + if (fileName.isEmpty()) { + fileName = QCoreApplication::applicationName() + QLatin1String("staterc"); + } + + return openConfig(fileName, SimpleConfig, QStandardPaths::AppDataLocation); +} + KSharedConfig::KSharedConfig(const QString &fileName, OpenFlags flags, QStandardPaths::StandardLocation resType) : KConfig(fileName, flags, resType) { globalSharedConfigList()->append(this); } KSharedConfig::~KSharedConfig() { if (s_storage.hasLocalData()) { globalSharedConfigList()->removeAll(this); } } KConfigGroup KSharedConfig::groupImpl(const QByteArray &groupName) { KSharedConfigPtr ptr(this); return KConfigGroup(ptr, groupName.constData()); } const KConfigGroup KSharedConfig::groupImpl(const QByteArray &groupName) const { const KSharedConfigPtr ptr(const_cast(this)); return KConfigGroup(ptr, groupName.constData()); } diff --git a/src/core/ksharedconfig.h b/src/core/ksharedconfig.h index e3a06b2..0a35f9f 100644 --- a/src/core/ksharedconfig.h +++ b/src/core/ksharedconfig.h @@ -1,92 +1,114 @@ /* This file is part of the KDE libraries Copyright (c) 1999 Preston Brown Copyright (C) 1997-1999 Matthias Kalle Dalheimer (kalle@kde.org) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KSHAREDCONFIG_H #define KSHAREDCONFIG_H #include #include /** * \class KSharedConfig ksharedconfig.h * * KConfig variant using shared memory * * KSharedConfig provides a shared (reference counted) variant * of KConfig. This allows you to use manipulate the same configuration * files from different places in your code without worrying about * accidentally overwriting changes. * * The openConfig() method is threadsafe: every thread gets a separate repository * of shared KConfig objects. This means, however, that you'll be responsible for * synchronizing the instances of KConfig for the same filename between threads, * using reparseConfiguration after a manual change notification, just like you have * to do between processes. */ class KCONFIGCORE_EXPORT KSharedConfig : public KConfig, public QSharedData //krazy:exclude=dpointer (only for refcounting) { public: typedef QExplicitlySharedDataPointer Ptr; public: /** * Creates a KSharedConfig object to manipulate a configuration file * * If an absolute path is specified for @p fileName, that file will be used * as the store for the configuration settings. If a non-absolute path * is provided, the file will be looked for in the standard directory * specified by @p type. If no path is provided, a default * configuration file will be used based on the name of the main * application component. * * @p mode determines whether the user or global settings will be allowed * to influence the values returned by this object. See KConfig::OpenFlags for * more details. * * @param fileName the configuration file to open. If empty, it will be determined * automatically (from --config on the command line, otherwise * from the application name + "rc") * @param mode how global settings should affect the configuration * options exposed by this KConfig object * @param type The standard directory to look for the configuration * file in (see QStandardPaths) * * @sa KConfig */ static KSharedConfig::Ptr openConfig(const QString &fileName = QString(), OpenFlags mode = FullConfig, QStandardPaths::StandardLocation type = QStandardPaths::GenericConfigLocation); + /** + * Creates a KSharedConfig object to manipulate a configuration file suitable + * for storing state information. Use this for storing information that is + * changing frequently and should not be saved by configuration backup + * utilities. + * + * If an absolute path is specified for @p fileName, that file will be used + * as the store for the configuration settings. If a non-absolute path + * is provided, the file will be looked for in the standard data directory + * (QStandardPaths::AppDataLocation). If no path is provided, a default + * configuration file will be used based on the name of the main + * application component. + * + * @param fileName the configuration file to open. If empty, it will be determined + * automatically from the application name + "staterc" + * + * @since 5.67 + * + * @sa KConfig + */ + static KSharedConfig::Ptr openStateConfig(const QString &fileName = QString()); + ~KSharedConfig() override; private: Q_DISABLE_COPY(KSharedConfig) KConfigGroup groupImpl(const QByteArray &aGroup) override; const KConfigGroup groupImpl(const QByteArray &aGroup) const override; KSharedConfig(const QString &file, OpenFlags mode, QStandardPaths::StandardLocation resourceType); }; typedef KSharedConfig::Ptr KSharedConfigPtr; #endif // multiple inclusion guard