ckb-next  v0.2.8 at branch master
ckb-next driver for corsair devices
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ckbsettings.cpp
Go to the documentation of this file.
1 #include "ckbsettings.h"
2 #include "ckbsettingswriter.h"
3 #include <QThread>
4 #include <QMutex>
5 #include <QDebug>
6 
7 // Shared global QSettings object
8 static QSettings* _globalSettings = 0;
9 static QThread* globalThread = 0;
10 QAtomicInt cacheWritesInProgress(0);
11 // Global one-shot settings cache, to avoid reading/writing QSettings constantly
12 static QMap<QString, QVariant> globalCache;
13 // Mutexes for accessing settings
14 QMutex settingsMutex(QMutex::Recursive), settingsCacheMutex(QMutex::Recursive);
15 #define lockMutex QMutexLocker locker(backing == _globalSettings ? &settingsMutex : 0)
16 #define lockMutexStatic QMutexLocker locker(&settingsMutex)
17 #define lockMutexStatic2 QMutexLocker locker2(&settingsMutex)
18 #define lockMutexCache QMutexLocker locker(&settingsCacheMutex)
19 
20 #if QT_VERSION < QT_VERSION_CHECK(5, 5, 0)
21 #define qInfo qDebug
22 #define qWarning qDebug
23 #define qFatal qDebug
24 #define qCritical qDebug
25 #endif
26 
27 static QSettings* globalSettings(){
28  if(!_globalSettings){
30  if(!(volatile QSettings*)_globalSettings){ // Check again after locking mutex in case another thread created the object
31  // Put the settings object in a separate thread so that it won't lock up the GUI when it syncs
32  globalThread = new QThread;
33  globalThread->start();
34  _globalSettings = new QSettings;
35  qInfo() << "Path to settings is" << _globalSettings->fileName();
36  _globalSettings->moveToThread(globalThread);
37  }
38  }
39  return _globalSettings;
40 }
41 
43  return cacheWritesInProgress.load() > 0;
44 }
45 
47  if(!_globalSettings)
48  return;
49  // Wait for all writers to finish
50  while(cacheWritesInProgress.load() > 0)
51  QThread::yieldCurrentThread();
52  // Stop thread and delete objects
53  globalThread->quit();
54  globalThread->wait();
55  delete globalThread;
56  delete _globalSettings;
57  globalThread = 0;
58  _globalSettings = 0;
59 }
60 
62  backing(globalSettings()) {
63 }
64 
65 CkbSettings::CkbSettings(const QString& basePath, bool eraseExisting) :
66  backing(globalSettings()) {
67  if(basePath.isEmpty()){
68  if(eraseExisting)
69  qDebug() << "CkbSettings created with basePath = \"\" and eraseExisting = true. This is a mistake.";
70  return;
71  }
72  if(eraseExisting)
73  remove(basePath);
74  beginGroup(basePath);
75 }
76 
77 CkbSettings::CkbSettings(QSettings& settings) :
78  backing(&settings) {
79 }
80 
81 void CkbSettings::beginGroup(const QString& prefix){
82  groups.append(prefix);
83 }
84 
86  groups.removeLast();
87 }
88 
89 QStringList CkbSettings::childGroups() const {
90  QString current = pwd();
91  lockMutex;
92  if(!current.isEmpty())
93  backing->beginGroup(current);
94  QStringList res = backing->childGroups();
95  if(!current.isEmpty())
96  backing->endGroup();
97  return res;
98 }
99 
100 QStringList CkbSettings::childKeys() const {
101  QString current = pwd();
102  lockMutex;
103  if(!current.isEmpty())
104  backing->beginGroup(current);
105  QStringList res = backing->childKeys();
106  if(!current.isEmpty())
107  backing->endGroup();
108  return res;
109 }
110 
111 bool CkbSettings::contains(const QString& key) const {
112  lockMutex;
113  return backing->contains(pwd(key));
114 }
115 
116 bool CkbSettings::containsGroup(const QString &group){
117  QStringList components = group.split("/");
118  if(components.length() > 1){
119  // Find sub-group
120  SGroup group(*this, components[0]);
121  return containsGroup(QStringList(components.mid(1)).join('/'));
122  }
123  return childGroups().contains(group);
124 }
125 
126 QVariant CkbSettings::value(const QString& key, const QVariant& defaultValue) const {
127  lockMutex;
128  return backing->value(pwd(key), defaultValue);
129 }
130 
131 void CkbSettings::setValue(const QString& key, const QVariant& value){
132  // Cache the write values, save them when the object is destroyed
133  QString realKey = pwd(key);
134  writeCache[realKey] = value;
135  // Update global cache if needed
137  if(globalCache.contains(realKey))
138  globalCache[realKey] = value;
139 }
140 
141 void CkbSettings::remove(const QString& key){
142  removeCache.append(pwd(key));
143 }
144 
146  if(removeCache.isEmpty() && writeCache.isEmpty())
147  return;
148  // Save the settings from the settings thread.
149  // They have to be saved from that thread specifically to avoid performance issues
151  writer->moveToThread(globalThread);
152  QObject::staticMetaObject.invokeMethod(writer, "run", Qt::QueuedConnection);
153 }
154 
155 QVariant CkbSettings::get(const QString& key, const QVariant& defaultValue){
156  // Store these settings in a memory cache
158  if(globalCache.contains(key))
159  return globalCache.value(key);
160  // If it wasn't found in the memory cache, look for it in QSettings
162  QSettings* settings = globalSettings();
163  return globalCache[key] = settings->value(key, defaultValue);
164 }
165 
166 void CkbSettings::set(const QString& key, const QVariant& value){
167  {
169  if(globalCache.value(key) == value)
170  return;
171  globalCache[key] = value;
172  }
174  globalSettings()->setValue(key, value);
175 }
void setValue(const QString &key, const QVariant &value)
rgb * current
Definition: main.c:46
QStringList groups
Definition: ckbsettings.h:47
static void set(const QString &key, const QVariant &value)
QStringList childKeys() const
QSettings * backing
Definition: ckbsettings.h:46
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
void endGroup()
Definition: ckbsettings.cpp:85
QAtomicInt cacheWritesInProgress(0)
bool contains(const QString &key) const
static QThread * globalThread
Definition: ckbsettings.cpp:9
static void cleanUp()
Definition: ckbsettings.cpp:46
static QVariant get(const QString &key, const QVariant &defaultValue=QVariant())
Definition: keymap.h:49
QMap< QString, QVariant > writeCache
Definition: ckbsettings.h:49
bool containsGroup(const QString &group)
QMutex settingsCacheMutex(QMutex::Recursive)
void beginGroup(const QString &prefix)
Definition: ckbsettings.cpp:81
QMutex settingsMutex(QMutex::Recursive)
static QSettings * globalSettings()
Definition: ckbsettings.cpp:27
static QMap< QString, QVariant > globalCache
Definition: ckbsettings.cpp:12
static QSettings * _globalSettings
Definition: ckbsettings.cpp:8
#define lockMutexStatic
Definition: ckbsettings.cpp:16
#define lockMutexCache
Definition: ckbsettings.cpp:18
QStringList childGroups() const
Definition: ckbsettings.cpp:89
void remove(const QString &key)
#define lockMutex
Definition: ckbsettings.cpp:15
QString pwd() const
Definition: ckbsettings.h:51
QStringList removeCache
Definition: ckbsettings.h:48
#define lockMutexStatic2
Definition: ckbsettings.cpp:17
static bool isBusy()
Definition: ckbsettings.cpp:42