libqutim  0.3.2.0
config.h
Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** qutIM - instant messenger
00004 **
00005 ** Copyright © 2011 Ruslan Nigmatullin <euroelessar@yandex.ru>
00006 **
00007 *****************************************************************************
00008 **
00009 ** $QUTIM_BEGIN_LICENSE$
00010 ** This program is free software: you can redistribute it and/or modify
00011 ** it under the terms of the GNU General Public License as published by
00012 ** the Free Software Foundation, either version 3 of the License, or
00013 ** (at your option) any later version.
00014 **
00015 ** This program is distributed in the hope that it will be useful,
00016 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00018 ** See the GNU General Public License for more details.
00019 **
00020 ** You should have received a copy of the GNU General Public License
00021 ** along with this program.  If not, see http://www.gnu.org/licenses/.
00022 ** $QUTIM_END_LICENSE$
00023 **
00024 ****************************************************************************/
00025 
00026 #ifndef CONFIG_H
00027 #define CONFIG_H
00028 
00029 #include "libqutim_global.h"
00030 #include <QVariant>
00031 #include <QSharedData>
00032 #include <QMetaTypeId>
00033 
00034 namespace qutim_sdk_0_3
00035 {
00036 #ifndef Q_QDOC
00037 namespace EnumDetectorHelper
00038 {
00039     typedef quint8 Yes;
00040     typedef quint16 No;
00041 
00042     // Check if type can be casted to int
00043     inline Yes is_int_type(int) { return Yes(); }
00044     inline No is_int_type(...) { return No(); }
00045 
00046     template <int Defined, int Size>
00047             class Helper
00048     {
00049     public:
00050         static No value() { return No(); }
00051     };
00052 
00053     template <>
00054             class Helper<0, sizeof(Yes)>
00055     {
00056     public:
00057         static Yes value() { return Yes(); }
00058     };
00059 
00060     template <typename T, int IsEnum>
00061             class VariantCastHelper
00062     {
00063     public:
00064         static QVariant convertToVariant(const T &t)
00065         { return QVariant::fromValue(t); }
00066         static T convertFromVariant(const QVariant &t)
00067         { return t.value<T>(); }
00068     };
00069 
00070     template <typename T>
00071             class VariantCastHelper <T, sizeof(Yes)>
00072     {
00073     public:
00074         static QVariant convertToVariant(const T &t)
00075         { return QVariant::fromValue(int(t)); }
00076         static T convertFromVariant(const QVariant &v)
00077         { return static_cast<T>(v.toInt()); }
00078     };
00079 
00080     template <typename T, int Defined>
00081             class VariantCastHelper3
00082     {
00083     public:
00084         static QVariant convertToVariant(const T &t)
00085         {
00086             return VariantCastHelper<T, sizeof(No)>::convertToVariant(t);
00087         }
00088         static T convertFromVariant(const QVariant &v)
00089         {
00090             return VariantCastHelper<T, sizeof(No)>::convertFromVariant(v);
00091         }
00092     };
00093 
00094     // Enums are not registered in Qt meta system and they can be casted to int easily
00095     template <typename T>
00096             class VariantCastHelper3 <T, 0>
00097     {
00098     public:
00099         static QVariant convertToVariant(const T &t)
00100         {
00101             return VariantCastHelper<T, sizeof(Helper<QMetaTypeId2<T>::Defined, sizeof(is_int_type(*reinterpret_cast<T*>(0)))>::value())>::convertToVariant(t);
00102         }
00103         static T convertFromVariant(const QVariant &v)
00104         {
00105             return VariantCastHelper<T, sizeof(Helper<QMetaTypeId2<T>::Defined, sizeof(is_int_type(*reinterpret_cast<T*>(0)))>::value())>::convertFromVariant(v);
00106         }
00107     };
00108 
00109     // Enums are not registered in Qt meta system, so check it before possibility of cast to int
00110     // because QByteArray has "operator int()" in private section
00111     template <typename T>
00112             class VariantCastHelper2
00113     {
00114     public:
00115         static QVariant convertToVariant(const T &t)
00116         {
00117             return VariantCastHelper3<T, QMetaTypeId2<T>::Defined>::convertToVariant(t);
00118         }
00119         static T convertFromVariant(const QVariant &v)
00120         {
00121             return VariantCastHelper3<T, QMetaTypeId2<T>::Defined>::convertFromVariant(v);
00122         }
00123     };
00124 }
00125 #endif
00126 class ConfigPrivate;
00127 class ConfigBackend;
00128 class ConfigBackendPrivate;
00129 
00130 class LIBQUTIM_EXPORT Config
00131 {
00132     Q_DECLARE_PRIVATE(Config)
00133 public:
00134     enum ValueFlag { Normal = 0x00, Crypted = 0x01 };
00135     Q_DECLARE_FLAGS(ValueFlags, ValueFlag)
00136 
00137     Config(const QVariantList &list);
00138     Config(QVariantList *list);
00139     Config(const QVariantMap &map);
00140     Config(QVariantMap *map);
00141     Config(const QString &path = QString());
00142     Config(const QString &path, ConfigBackend *backend);
00143     Config(const QStringList &paths);
00144     Config(const QString &path, const QVariantList &fallbacks);
00145     Config(const QString &path, const QVariant &fallback);
00146     Config(const Config &other);
00147     Config &operator =(const Config &other);
00148     virtual ~Config();
00149 
00150     Config group(const QString &name) Q_REQUIRED_RESULT;
00151     QStringList childGroups() const Q_REQUIRED_RESULT;
00152     QStringList childKeys() const Q_REQUIRED_RESULT;
00153     bool hasChildGroup(const QString &name) const Q_REQUIRED_RESULT;
00154     bool hasChildKey(const QString &name) const Q_REQUIRED_RESULT;
00155     void beginGroup(const QString &name);
00156     void endGroup();
00157     void remove(const QString &name);
00158 
00159     Config arrayElement(int index) Q_REQUIRED_RESULT;
00160     int beginArray(const QString &name);
00161     void endArray();
00162     int arraySize() const Q_REQUIRED_RESULT;
00163     void setArrayIndex(int index);
00164     void remove(int index);
00165 
00166     QVariant rootValue(const QVariant &def = QVariant(), ValueFlags type = Normal) const Q_REQUIRED_RESULT;
00167     template<typename T>
00168     T value(const QString &key, const T &def = T(), ValueFlags type = Normal) const Q_REQUIRED_RESULT;
00169     QVariant value(const QString &key, const QVariant &def = QVariant(), ValueFlags type = Normal) const Q_REQUIRED_RESULT;
00170     inline QString value(const QString &key, const QLatin1String &def, ValueFlags type = Normal) const Q_REQUIRED_RESULT;
00171     inline QString value(const QString &key, const char *def, ValueFlags type = Normal) const Q_REQUIRED_RESULT;
00172     template <int N>
00173     QString value(const QString &key, const char (&def)[N], ValueFlags type = Normal) const Q_REQUIRED_RESULT;
00174     template<typename T>
00175     void setValue(const QString &key, const T &value, ValueFlags type = Normal);
00176     void setValue(const QString &key, const QVariant &value, ValueFlags type = Normal);
00177     inline void setValue(const QString &key, const QLatin1String &value, ValueFlags type = Normal);
00178     inline void setValue(const QString &key, const char *value, ValueFlags type = Normal);
00179     template <int N>
00180     void setValue(const QString &key, const char (&value)[N], ValueFlags type = Normal);
00181 
00182     void sync();
00183 
00184     typedef void (*SaveOperator)(QVariant &, const void *);
00185     typedef void (*LoadOperator)(const QVariant &, void *);
00186     static void registerType(int type, SaveOperator saveOp, LoadOperator loadOp);
00187 private:
00188     QExplicitlySharedDataPointer<ConfigPrivate> d_ptr;
00189 };
00190 
00191 template <typename T>
00192 void configSaveHelper(QVariant &var, const T *t)
00193 {
00194     var = QVariant::fromValue(t);
00195 }
00196 
00197 template <typename T>
00198 void configLoadHelper(const QVariant &var, T *t)
00199 {
00200     *t = var.value<T>();
00201 }
00202 
00203 template <typename T>
00204 void registerConfigType(T * /* dummy */ = 0)
00205 {
00206     typedef void (*SavePtr)(QVariant &, const T *);
00207     typedef void (*LoadPtr)(const QVariant &, T *);
00208     SavePtr sptr = configSaveHelper<T>();
00209     LoadPtr lptr = configLoadHelper<T>();
00210 
00211     Config::registerType(qRegisterMetaType<T>(),
00212                          reinterpret_cast<Config::SaveOperator>(sptr),
00213                          reinterpret_cast<Config::LoadOperator>(lptr));
00214 }
00215 
00216 typedef Config ConfigBase;
00217 typedef Config ConfigGroup;
00218 
00219 class LIBQUTIM_EXPORT ConfigBackend : public QObject
00220 {
00221     Q_OBJECT
00222     Q_DECLARE_PRIVATE(ConfigBackend)
00223 public:
00224     ConfigBackend();
00225     virtual ~ConfigBackend();
00226 
00227     virtual QVariant load(const QString &file) = 0;
00228     virtual void save(const QString &file, const QVariant &entry) = 0;
00229 
00230     QByteArray name() const;
00231 protected:
00232     virtual void virtual_hook(int id, void *data);
00233 private:
00234     QScopedPointer<ConfigBackendPrivate> d_ptr;
00235 };
00236 
00237 template<typename T>
00238 Q_INLINE_TEMPLATE T Config::value(const QString &key, const T &def, Config::ValueFlags type) const
00239 {
00240     QVariant defVar = EnumDetectorHelper::VariantCastHelper2<T>::convertToVariant(def);
00241     return EnumDetectorHelper::VariantCastHelper2<T>::convertFromVariant(value(key, defVar, type));
00242 }
00243 
00244 template<typename T>
00245 Q_INLINE_TEMPLATE void Config::setValue(const QString &key, const T &value, Config::ValueFlags type)
00246 {
00247     setValue(key, EnumDetectorHelper::VariantCastHelper2<T>::convertToVariant(value), type);
00248 }
00249 
00250 QString Config::value(const QString &key, const QLatin1String &def, ValueFlags type) const
00251 {
00252     return value(key, QString(def), type);
00253 }
00254 
00255 QString Config::value(const QString &key, const char *def, ValueFlags type) const
00256 {
00257     return value(key, QString::fromUtf8(def), type);
00258 }
00259 
00260 template <int N>
00261 Q_INLINE_TEMPLATE QString Config::value(const QString &key, const char (&def)[N], ValueFlags type) const
00262 {
00263     return value(key, QString::fromUtf8(def, N-1), type);
00264 }
00265 
00266 void Config::setValue(const QString &key, const QLatin1String &value, ValueFlags type)
00267 {
00268     setValue(key, QString(value), type);
00269 }
00270 
00271 void Config::setValue(const QString &key, const char *value, ValueFlags type)
00272 {
00273     setValue(key, QString::fromUtf8(value), type);
00274 }
00275 
00276 template <int N>
00277 Q_INLINE_TEMPLATE void Config::setValue(const QString &key, const char (&value)[N], ValueFlags type)
00278 {
00279     setValue(key, QString::fromUtf8(value, N-1), type);
00280 }
00281 }
00282 
00283 // Config() is synonym for Config("profile"), so redefine construct method for it
00284 template <>
00285 Q_INLINE_TEMPLATE void *qMetaTypeConstructHelper<qutim_sdk_0_3::Config>(const qutim_sdk_0_3::Config *t)
00286 {
00287 if (!t) {
00288     return new qutim_sdk_0_3::Config(QVariantMap());
00289 }
00290 return new qutim_sdk_0_3::Config(*t);
00291 }
00292 
00293 Q_DECLARE_METATYPE(qutim_sdk_0_3::Config)
00294 
00295 #endif // CONFIG_H
00296