Skip to content

Instantly share code, notes, and snippets.

@unixod
Created August 10, 2012 15:59
Show Gist options
  • Save unixod/3315227 to your computer and use it in GitHub Desktop.
Save unixod/3315227 to your computer and use it in GitHub Desktop.
Settings class with "magic" enums (QSettings wrapper)
#include "settings.h"
#include <QSettings>
#include <QMetaEnum>
#include <QRegExp>
#include <QStringList>
Settings::Settings(){
const QMetaObject &mo = staticMetaObject;
int idx = mo.indexOfEnumerator("Key");
keys = mo.enumerator(idx);
idx = mo.indexOfEnumerator("Section");
sections = mo.enumerator(idx);
}
QVariant Settings::get(Key k, Section s){
Settings &self = instance();
QString key = self.keyPath(s, k);
return self.conf.value(key, self.defaults[key]);
}
Settings::ValueRef Settings::set(Key k, Section s){
Settings &self = instance();
return ValueRef(self, self.keyPath(s, k));
}
void Settings::setDefaults(const QString &str){
Settings &self = instance();
// section/key : value;
// section - optional
QRegExp rxRecord("^\\s*(((\\w+)/)?(\\w+))\\s*:\\s*([^\\s].{0,})\\b\\s*$");
auto kvs = str.split(QRegExp(";\\W*"), QString::SkipEmptyParts); //key-values
for(auto kv : kvs){
if(rxRecord.indexIn(kv) != -1){
QString section = rxRecord.cap(3);
QString key = rxRecord.cap(4);
QString value = rxRecord.cap(5);
int iKey = self.keys.keyToValue(key.toLocal8Bit().data());
if(iKey != -1){
int iSection = self.sections.keyToValue(section.toLocal8Bit().data());
if(section.isEmpty() || iSection != -1){
self.defaults[rxRecord.cap(1)] = value;
}
}
}
}
}
//Settings::ValueRef-----------------------------------------------------------
Settings::ValueRef &Settings::ValueRef::operator = (const QVariant &data){
parent.conf.setValue(keyPath, data);
return *this;
}
//PRIVATE METHODS--------------------------------------------------------------
QString Settings::keyPath(Section s, Key k){
auto szSection = sections.valueToKey(s);
auto szKey = keys.valueToKey(k);
return QString(s == General ? "%1" : "%2/%1").arg(szKey).arg(szSection);
}
Settings & Settings::instance(){
static Settings singleton;
return singleton;
}
#ifndef SETTINGS_H
#define SETTINGS_H
#include <QVariant>
#include <QSettings>
#include <QMetaEnum>
/**
@brief Configuration access singleton
Usage:
@code
...
...
//must be predefined somewhere in main
QApplication::setOrganizationName("Organization name");
QApplication::setApplicationName("App name");
...
...
//default values can be configured by calling (config-string can be multyline):
Settings::setDefaults("SomeKey: value1; SomeSection/SomeKey: value2");
//or
QFile f(":/defaults/config");
f.open(QIODevice::ReadOnly);
Settings::setDefaults(f.readAll());
...
...
void fun(){
...
QVariant val1 = Settings::get(Settings::SomeKey);
Settings::set(Settings::SomeKey) = "new val1";
...
QVariant val2 = Settings::get(Settings::SomeKey, Settings::SomeSection);
Settings::set(Settings::SomeKey, Settings::SomeSection) = "new val2";
...
}
@endcode
Sections and keys can be modified by changing enums only! (the class itself does not need to change)
*/
class Settings{
Q_GADGET
Q_ENUMS(Section)
Q_ENUMS(Key)
public:
enum Section{
General, //this is default section
SomeSection1,
SomeSection2
};
enum Key{
SomeKey1,
SomeKey2
};
class ValueRef{
public:
ValueRef(Settings &st, const QString &kp) :
parent(st), keyPath(kp){}
ValueRef & operator = (const QVariant &d);
private:
Settings &parent;
const QString keyPath;
};
static void setDefaults(const QString &str);
static QVariant get(Key, Section /*s*/ = General);
static ValueRef set(Key, Section /*s*/ = General);
private:
QString keyPath(Section, Key);
static Settings & instance();
QMetaEnum keys;
QMetaEnum sections;
QMap<QString, QVariant> defaults;
QSettings conf;
Settings();
Settings(const Settings &);
Settings & operator = (const Settings &);
};
#endif // SETTINGS_H
@unixod
Copy link
Author

unixod commented Aug 10, 2012

for more details see the post

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment