qtmobility/src/location/gconfitem.cpp
changeset 4 90517678cc4f
child 8 71781823f776
equal deleted inserted replaced
1:2b40d63a9c3d 4:90517678cc4f
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Mobility Components.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include <QString>
       
    43 #include <QStringList>
       
    44 #include <QByteArray>
       
    45 #include <QVariant>
       
    46 #include <QtDebug>
       
    47 
       
    48 #include "gconfitem.h"
       
    49 
       
    50 #include <glib.h>
       
    51 #include <gconf/gconf-value.h>
       
    52 #include <gconf/gconf-client.h>
       
    53 
       
    54 struct GConfItemPrivate {
       
    55     QString key;
       
    56     QVariant value;
       
    57     guint notify_id;
       
    58 
       
    59     static void notify_trampoline(GConfClient*, guint, GConfEntry *, gpointer);
       
    60 };
       
    61 
       
    62 #define withClient(c) for(GConfClient *c = (g_type_init(), gconf_client_get_default()); c; g_object_unref(c), c=NULL)
       
    63 
       
    64 static QByteArray convertKey (QString key)
       
    65 {
       
    66     if (key.startsWith('/'))
       
    67         return key.toUtf8();
       
    68     else
       
    69     {
       
    70         qWarning() << "Using dot-separated key names with GConfItem is deprecated.";
       
    71         qWarning() << "Please use" << '/' + key.replace('.', '/') << "instead of" << key;
       
    72         return '/' + key.replace('.', '/').toUtf8();
       
    73     }
       
    74 }
       
    75 
       
    76 static QString convertKey(const char *key)
       
    77 {
       
    78     return QString::fromUtf8(key);
       
    79 }
       
    80 
       
    81 static QVariant convertValue(GConfValue *src)
       
    82 {
       
    83     if (!src) {
       
    84         return QVariant();
       
    85     } else {
       
    86         switch (src->type) {
       
    87         case GCONF_VALUE_INVALID:
       
    88             return QVariant(QVariant::Invalid);
       
    89         case GCONF_VALUE_BOOL:
       
    90             return QVariant((bool)gconf_value_get_bool(src));
       
    91         case GCONF_VALUE_INT:
       
    92             return QVariant(gconf_value_get_int(src));
       
    93         case GCONF_VALUE_FLOAT:
       
    94             return QVariant(gconf_value_get_float(src));
       
    95         case GCONF_VALUE_STRING:
       
    96             return QVariant(QString::fromUtf8(gconf_value_get_string(src)));
       
    97         case GCONF_VALUE_LIST:
       
    98             switch (gconf_value_get_list_type(src)) {
       
    99             case GCONF_VALUE_STRING:
       
   100                 {
       
   101                     QStringList result;
       
   102                     for (GSList *elts = gconf_value_get_list(src); elts; elts = elts->next)
       
   103                         result.append(QString::fromUtf8(gconf_value_get_string((GConfValue *)elts->data)));
       
   104                     return QVariant(result);
       
   105                 }
       
   106             default:
       
   107                 {
       
   108                     QList<QVariant> result;
       
   109                     for (GSList *elts = gconf_value_get_list(src); elts; elts = elts->next)
       
   110                         result.append(convertValue((GConfValue *)elts->data));
       
   111                     return QVariant(result);
       
   112                 }
       
   113             }
       
   114         case GCONF_VALUE_SCHEMA:
       
   115         default:
       
   116             return QVariant();
       
   117         }
       
   118     }
       
   119 }
       
   120 
       
   121 static GConfValue *convertString(const QString &str)
       
   122 {
       
   123     GConfValue *v = gconf_value_new (GCONF_VALUE_STRING);
       
   124     gconf_value_set_string (v, str.toUtf8().data());
       
   125     return v;
       
   126 }
       
   127 
       
   128 static GConfValueType primitiveType (const QVariant &elt)
       
   129 {
       
   130     switch(elt.type()) {
       
   131     case QVariant::String:
       
   132         return GCONF_VALUE_STRING;
       
   133     case QVariant::Int:
       
   134         return GCONF_VALUE_INT;
       
   135     case QVariant::Double:
       
   136         return GCONF_VALUE_FLOAT;
       
   137     case QVariant::Bool:
       
   138         return GCONF_VALUE_BOOL;
       
   139     default:
       
   140         return GCONF_VALUE_INVALID;
       
   141     }
       
   142 }
       
   143 
       
   144 static GConfValueType uniformType(const QList<QVariant> &list)
       
   145 {
       
   146     GConfValueType result = GCONF_VALUE_INVALID;
       
   147 
       
   148     foreach (const QVariant &elt, list) {
       
   149         GConfValueType elt_type = primitiveType (elt);
       
   150 
       
   151         if (elt_type == GCONF_VALUE_INVALID)
       
   152             return GCONF_VALUE_INVALID;
       
   153 
       
   154         if (result == GCONF_VALUE_INVALID)
       
   155             result = elt_type;
       
   156         else if (result != elt_type)
       
   157             return GCONF_VALUE_INVALID;
       
   158     }
       
   159 
       
   160     if (result == GCONF_VALUE_INVALID)
       
   161         return GCONF_VALUE_STRING;  // empty list.
       
   162     else
       
   163         return result;
       
   164 }
       
   165 
       
   166 static int convertValue(const QVariant &src, GConfValue **valp)
       
   167 {
       
   168     GConfValue *v;
       
   169 
       
   170     switch(src.type()) {
       
   171     case QVariant::Invalid:
       
   172         v = NULL;
       
   173         break;
       
   174     case QVariant::Bool:
       
   175         v = gconf_value_new (GCONF_VALUE_BOOL);
       
   176         gconf_value_set_bool (v, src.toBool());
       
   177         break;
       
   178     case QVariant::Int:
       
   179         v = gconf_value_new (GCONF_VALUE_INT);
       
   180         gconf_value_set_int (v, src.toInt());
       
   181         break;
       
   182     case QVariant::Double:
       
   183         v = gconf_value_new (GCONF_VALUE_FLOAT);
       
   184         gconf_value_set_float (v, src.toDouble());
       
   185         break;
       
   186     case QVariant::String:
       
   187         v = convertString(src.toString());
       
   188         break;
       
   189     case QVariant::StringList:
       
   190         {
       
   191             GSList *elts = NULL;
       
   192             v = gconf_value_new(GCONF_VALUE_LIST);
       
   193             gconf_value_set_list_type(v, GCONF_VALUE_STRING);
       
   194             foreach (const QString &str, src.toStringList())
       
   195                 elts = g_slist_prepend(elts, convertString(str));
       
   196             gconf_value_set_list_nocopy(v, g_slist_reverse(elts));
       
   197             break;
       
   198         }
       
   199     case QVariant::List:
       
   200         {
       
   201             GConfValueType elt_type = uniformType(src.toList());
       
   202             if (elt_type == GCONF_VALUE_INVALID)
       
   203                 v = NULL;
       
   204             else
       
   205             {
       
   206                 GSList *elts = NULL;
       
   207                 v = gconf_value_new(GCONF_VALUE_LIST);
       
   208                 gconf_value_set_list_type(v, elt_type);
       
   209                 foreach (const QVariant &elt, src.toList())
       
   210                 {
       
   211                     GConfValue *val = NULL;
       
   212                     convertValue(elt, &val);  // guaranteed to succeed.
       
   213                     elts = g_slist_prepend(elts, val);
       
   214                 }
       
   215                 gconf_value_set_list_nocopy(v, g_slist_reverse(elts));
       
   216             }
       
   217             break;
       
   218         }
       
   219     default:
       
   220         return 0;
       
   221     }
       
   222 
       
   223     *valp = v;
       
   224     return 1;
       
   225 }
       
   226 
       
   227 void GConfItemPrivate::notify_trampoline (GConfClient*,
       
   228                                              guint,
       
   229                                              GConfEntry *,
       
   230                                              gpointer data)
       
   231 {
       
   232     GConfItem *item = (GConfItem *)data;
       
   233     item->update_value (true);
       
   234 }
       
   235 
       
   236 void GConfItem::update_value (bool emit_signal)
       
   237 {
       
   238     QVariant new_value;
       
   239 
       
   240     withClient(client) {
       
   241         GError *error = NULL;
       
   242         QByteArray k = convertKey(priv->key);
       
   243         GConfValue *v = gconf_client_get(client, k.data(), &error);
       
   244 
       
   245         if (error) {
       
   246             qWarning() << error->message;
       
   247             g_error_free (error);
       
   248             new_value = priv->value;
       
   249         } else {
       
   250             new_value = convertValue(v);
       
   251             if (v)
       
   252                 gconf_value_free(v);
       
   253         }
       
   254     }
       
   255 
       
   256     if (new_value != priv->value) {
       
   257         priv->value = new_value;
       
   258         if (emit_signal)
       
   259             emit valueChanged();
       
   260     }
       
   261 }
       
   262 
       
   263 QString GConfItem::key() const
       
   264 {
       
   265     return priv->key;
       
   266 }
       
   267 
       
   268 QVariant GConfItem::value() const
       
   269 {
       
   270     return priv->value;
       
   271 }
       
   272 
       
   273 QVariant GConfItem::value(const QVariant &def) const
       
   274 {
       
   275     if (priv->value.isNull())
       
   276         return def;
       
   277     else
       
   278         return priv->value;
       
   279 }
       
   280 
       
   281 void GConfItem::set(const QVariant &val)
       
   282 {
       
   283     withClient(client) {
       
   284         QByteArray k = convertKey(priv->key);
       
   285         GConfValue *v;
       
   286         if (convertValue(val, &v)) {
       
   287             GError *error = NULL;
       
   288 
       
   289             if (v) {
       
   290                 gconf_client_set(client, k.data(), v, &error);
       
   291                 gconf_value_free(v);
       
   292             } else {
       
   293                 gconf_client_unset(client, k.data(), &error);
       
   294             }
       
   295 
       
   296             if (error) {
       
   297                 qWarning() << error->message;
       
   298                 g_error_free(error);
       
   299             } else if (priv->value != val) {
       
   300                 priv->value = val;
       
   301                 emit valueChanged();
       
   302             }
       
   303 
       
   304         } else
       
   305             qWarning() << "Can't store a" << val.typeName();
       
   306     }
       
   307 }
       
   308 
       
   309 void GConfItem::unset() {
       
   310     set(QVariant());
       
   311 }
       
   312 
       
   313 QList<QString> GConfItem::listDirs() const
       
   314 {
       
   315     QList<QString> children;
       
   316 
       
   317     withClient(client) {
       
   318         QByteArray k = convertKey(priv->key);
       
   319         GSList *dirs = gconf_client_all_dirs(client, k.data(), NULL);
       
   320         for (GSList *d = dirs; d; d = d->next) {
       
   321             children.append(convertKey((char *)d->data));
       
   322             g_free (d->data);
       
   323         }
       
   324         g_slist_free (dirs);
       
   325     }
       
   326 
       
   327     return children;
       
   328 }
       
   329 
       
   330 QList<QString> GConfItem::listEntries() const
       
   331 {
       
   332     QList<QString> children;
       
   333 
       
   334     withClient(client) {
       
   335         QByteArray k = convertKey(priv->key);
       
   336         GSList *entries = gconf_client_all_entries(client, k.data(), NULL);
       
   337         for (GSList *e = entries; e; e = e->next) {
       
   338             children.append(convertKey(((GConfEntry *)e->data)->key));
       
   339             gconf_entry_free ((GConfEntry *)e->data);
       
   340         }
       
   341         g_slist_free (entries);
       
   342     }
       
   343 
       
   344     return children;
       
   345 }
       
   346 
       
   347 GConfItem::GConfItem(const QString &key, QObject *parent)
       
   348     : QObject (parent)
       
   349 {
       
   350     priv = new GConfItemPrivate;
       
   351     priv->key = key;
       
   352     withClient(client) {
       
   353         update_value (false);
       
   354         QByteArray k = convertKey(priv->key);
       
   355         gconf_client_add_dir (client, k.data(), GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
       
   356         priv->notify_id = gconf_client_notify_add (client, k.data(),
       
   357                                                    GConfItemPrivate::notify_trampoline, this,
       
   358                                                    NULL, NULL);
       
   359     }
       
   360 }
       
   361 
       
   362 GConfItem::~GConfItem()
       
   363 {
       
   364     withClient(client) {
       
   365         QByteArray k = convertKey(priv->key);
       
   366         gconf_client_notify_remove (client, priv->notify_id);
       
   367         gconf_client_remove_dir (client, k.data(), NULL);
       
   368     }
       
   369     delete priv;
       
   370 }