source: trunk/src/3rdparty/libgq/gconf/gconfitem.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 10.3 KB
Line 
1/* * This file is part of libgq *
2 *
3 * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 * All rights reserved.
5 *
6 * Contact: Marius Vollmer <marius.vollmer@nokia.com>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * version 2.1 as published by the Free Software Foundation.
11 *
12 * This library is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#include <QString>
25#include <QStringList>
26#include <QByteArray>
27#include <QVariant>
28#include <QtDebug>
29
30#include "gconfitem.h"
31
32#include <glib.h>
33#include <gconf/gconf-value.h>
34#include <gconf/gconf-client.h>
35
36struct GConfItemPrivate {
37 QString key;
38 QVariant value;
39 guint notify_id;
40
41 static void notify_trampoline(GConfClient*, guint, GConfEntry *, gpointer);
42};
43
44/* We get the default client and never release it, on purpose, to
45 avoid disconnecting from the GConf daemon when a program happens to
46 not have any GConfItems for short periods of time.
47 */
48static GConfClient *
49get_gconf_client ()
50{
51 static bool initialized = false;
52 static GConfClient *client;
53
54 if (initialized)
55 return client;
56
57 g_type_init ();
58 client = gconf_client_get_default();
59 initialized = true;
60
61 return client;
62}
63
64/* Sometimes I like being too clever...
65 */
66#define withClient(c) for (GConfClient *c = get_gconf_client (); c; c = NULL)
67
68static QByteArray convertKey (QString key)
69{
70 if (key.startsWith('/'))
71 return key.toUtf8();
72 else
73 {
74 qWarning() << "Using dot-separated key names with GConfItem is deprecated.";
75 qWarning() << "Please use" << '/' + key.replace('.', '/') << "instead of" << key;
76 return '/' + key.replace('.', '/').toUtf8();
77 }
78}
79
80static QString convertKey(const char *key)
81{
82 return QString::fromUtf8(key);
83}
84
85static QVariant convertValue(GConfValue *src)
86{
87 if (!src) {
88 return QVariant();
89 } else {
90 switch (src->type) {
91 case GCONF_VALUE_INVALID:
92 return QVariant(QVariant::Invalid);
93 case GCONF_VALUE_BOOL:
94 return QVariant((bool)gconf_value_get_bool(src));
95 case GCONF_VALUE_INT:
96 return QVariant(gconf_value_get_int(src));
97 case GCONF_VALUE_FLOAT:
98 return QVariant(gconf_value_get_float(src));
99 case GCONF_VALUE_STRING:
100 return QVariant(QString::fromUtf8(gconf_value_get_string(src)));
101 case GCONF_VALUE_LIST:
102 switch (gconf_value_get_list_type(src)) {
103 case GCONF_VALUE_STRING:
104 {
105 QStringList result;
106 for (GSList *elts = gconf_value_get_list(src); elts; elts = elts->next)
107 result.append(QString::fromUtf8(gconf_value_get_string((GConfValue *)elts->data)));
108 return QVariant(result);
109 }
110 default:
111 {
112 QList<QVariant> result;
113 for (GSList *elts = gconf_value_get_list(src); elts; elts = elts->next)
114 result.append(convertValue((GConfValue *)elts->data));
115 return QVariant(result);
116 }
117 }
118 case GCONF_VALUE_SCHEMA:
119 default:
120 return QVariant();
121 }
122 }
123}
124
125static GConfValue *convertString(const QString &str)
126{
127 GConfValue *v = gconf_value_new (GCONF_VALUE_STRING);
128 gconf_value_set_string (v, str.toUtf8().data());
129 return v;
130}
131
132static GConfValueType primitiveType (const QVariant &elt)
133{
134 switch(elt.type()) {
135 case QVariant::String:
136 return GCONF_VALUE_STRING;
137 case QVariant::Int:
138 return GCONF_VALUE_INT;
139 case QVariant::Double:
140 return GCONF_VALUE_FLOAT;
141 case QVariant::Bool:
142 return GCONF_VALUE_BOOL;
143 default:
144 return GCONF_VALUE_INVALID;
145 }
146}
147
148static GConfValueType uniformType(const QList<QVariant> &list)
149{
150 GConfValueType result = GCONF_VALUE_INVALID;
151
152 foreach (const QVariant &elt, list) {
153 GConfValueType elt_type = primitiveType (elt);
154
155 if (elt_type == GCONF_VALUE_INVALID)
156 return GCONF_VALUE_INVALID;
157
158 if (result == GCONF_VALUE_INVALID)
159 result = elt_type;
160 else if (result != elt_type)
161 return GCONF_VALUE_INVALID;
162 }
163
164 if (result == GCONF_VALUE_INVALID)
165 return GCONF_VALUE_STRING; // empty list.
166 else
167 return result;
168}
169
170static int convertValue(const QVariant &src, GConfValue **valp)
171{
172 GConfValue *v;
173
174 switch(src.type()) {
175 case QVariant::Invalid:
176 v = NULL;
177 break;
178 case QVariant::Bool:
179 v = gconf_value_new (GCONF_VALUE_BOOL);
180 gconf_value_set_bool (v, src.toBool());
181 break;
182 case QVariant::Int:
183 v = gconf_value_new (GCONF_VALUE_INT);
184 gconf_value_set_int (v, src.toInt());
185 break;
186 case QVariant::Double:
187 v = gconf_value_new (GCONF_VALUE_FLOAT);
188 gconf_value_set_float (v, src.toDouble());
189 break;
190 case QVariant::String:
191 v = convertString(src.toString());
192 break;
193 case QVariant::StringList:
194 {
195 GSList *elts = NULL;
196 v = gconf_value_new(GCONF_VALUE_LIST);
197 gconf_value_set_list_type(v, GCONF_VALUE_STRING);
198 foreach (const QString &str, src.toStringList())
199 elts = g_slist_prepend(elts, convertString(str));
200 gconf_value_set_list_nocopy(v, g_slist_reverse(elts));
201 break;
202 }
203 case QVariant::List:
204 {
205 GConfValueType elt_type = uniformType(src.toList());
206 if (elt_type == GCONF_VALUE_INVALID)
207 v = NULL;
208 else
209 {
210 GSList *elts = NULL;
211 v = gconf_value_new(GCONF_VALUE_LIST);
212 gconf_value_set_list_type(v, elt_type);
213 foreach (const QVariant &elt, src.toList())
214 {
215 GConfValue *val = NULL;
216 convertValue(elt, &val); // guaranteed to succeed.
217 elts = g_slist_prepend(elts, val);
218 }
219 gconf_value_set_list_nocopy(v, g_slist_reverse(elts));
220 }
221 break;
222 }
223 default:
224 return 0;
225 }
226
227 *valp = v;
228 return 1;
229}
230
231void GConfItemPrivate::notify_trampoline (GConfClient*,
232 guint,
233 GConfEntry *,
234 gpointer data)
235{
236 GConfItem *item = (GConfItem *)data;
237 item->update_value (true);
238}
239
240void GConfItem::update_value (bool emit_signal)
241{
242 QVariant new_value;
243
244 withClient(client) {
245 GError *error = NULL;
246 QByteArray k = convertKey(priv->key);
247 GConfValue *v = gconf_client_get(client, k.data(), &error);
248
249 if (error) {
250 qWarning() << error->message;
251 g_error_free (error);
252 new_value = priv->value;
253 } else {
254 new_value = convertValue(v);
255 if (v)
256 gconf_value_free(v);
257 }
258 }
259
260 if (new_value != priv->value) {
261 priv->value = new_value;
262 if (emit_signal)
263 emit valueChanged();
264 }
265}
266
267QString GConfItem::key() const
268{
269 return priv->key;
270}
271
272QVariant GConfItem::value() const
273{
274 return priv->value;
275}
276
277QVariant GConfItem::value(const QVariant &def) const
278{
279 if (priv->value.isNull())
280 return def;
281 else
282 return priv->value;
283}
284
285void GConfItem::set(const QVariant &val)
286{
287 withClient(client) {
288 QByteArray k = convertKey(priv->key);
289 GConfValue *v;
290 if (convertValue(val, &v)) {
291 GError *error = NULL;
292
293 if (v) {
294 gconf_client_set(client, k.data(), v, &error);
295 gconf_value_free(v);
296 } else {
297 gconf_client_unset(client, k.data(), &error);
298 }
299
300 if (error) {
301 qWarning() << error->message;
302 g_error_free(error);
303 } else if (priv->value != val) {
304 priv->value = val;
305 emit valueChanged();
306 }
307
308 } else
309 qWarning() << "Can't store a" << val.typeName();
310 }
311}
312
313void GConfItem::unset() {
314 set(QVariant());
315}
316
317QList<QString> GConfItem::listDirs() const
318{
319 QList<QString> children;
320
321 withClient(client) {
322 QByteArray k = convertKey(priv->key);
323 GSList *dirs = gconf_client_all_dirs(client, k.data(), NULL);
324 for (GSList *d = dirs; d; d = d->next) {
325 children.append(convertKey((char *)d->data));
326 g_free (d->data);
327 }
328 g_slist_free (dirs);
329 }
330
331 return children;
332}
333
334QList<QString> GConfItem::listEntries() const
335{
336 QList<QString> children;
337
338 withClient(client) {
339 QByteArray k = convertKey(priv->key);
340 GSList *entries = gconf_client_all_entries(client, k.data(), NULL);
341 for (GSList *e = entries; e; e = e->next) {
342 children.append(convertKey(((GConfEntry *)e->data)->key));
343 gconf_entry_free ((GConfEntry *)e->data);
344 }
345 g_slist_free (entries);
346 }
347
348 return children;
349}
350
351GConfItem::GConfItem(const QString &key, QObject *parent)
352 : QObject (parent)
353{
354 priv = new GConfItemPrivate;
355 priv->key = key;
356 priv->notify_id = 0;
357 withClient(client) {
358 update_value (false);
359 QByteArray k = convertKey(priv->key);
360 gconf_client_add_dir (client, k.data(), GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
361 priv->notify_id = gconf_client_notify_add (client, k.data(),
362 GConfItemPrivate::notify_trampoline, this,
363 NULL, NULL);
364 }
365}
366
367GConfItem::~GConfItem()
368{
369 withClient(client) {
370 QByteArray k = convertKey(priv->key);
371 if (priv->notify_id)
372 gconf_client_notify_remove (client, priv->notify_id);
373 gconf_client_remove_dir (client, k.data(), NULL);
374 }
375 delete priv;
376}
Note: See TracBrowser for help on using the repository browser.