@@ -0,0 +1,158 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Pawel Stolowski <pawel.stolowski@canonical.com>
6+ *
7+ * This program is free software; you can redistribute it and/or modify
8+ * it under the terms of the GNU General Public License as published by
9+ * the Free Software Foundation; version 3.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
18+ */
19+
20+#include "variantutils.h"
21+
22+/* Returns floating ref */
23+GVariant* GVariantFromQVariant(const QVariant &var)
24+{
25+ GVariant *gv = nullptr;
26+
27+ switch (var.type()) {
28+ case QVariant::String:
29+ gv = g_variant_new_string(var.toString().toUtf8());
30+ break;
31+ case QVariant::UInt:
32+ gv = g_variant_new_uint32(var.toUInt());
33+ break;
34+ case QVariant::Int:
35+ gv = g_variant_new_int32(var.toInt());
36+ break;
37+ case QVariant::LongLong:
38+ gv = g_variant_new_int64(var.toLongLong());
39+ break;
40+ case QVariant::ULongLong:
41+ gv = g_variant_new_uint64(var.toULongLong());
42+ break;
43+ case QVariant::Double:
44+ gv = g_variant_new_double(var.toDouble());
45+ break;
46+ case QVariant::Bool:
47+ gv = g_variant_new_boolean(var.toBool());
48+ break;
49+ case QVariant::Hash: {
50+ const auto hash = var.toHash();
51+ GVariant **children = new GVariant*[hash.size()];
52+ int cnt = 0;
53+ QHash<QString, QVariant>::const_iterator it = hash.constBegin();
54+ while (it != hash.constEnd()) {
55+ GVariant *key = g_variant_new_string(it.key().toUtf8());
56+ children[cnt++] = g_variant_new_dict_entry(key, g_variant_new_variant(GVariantFromQVariant(it.value())));
57+ ++it;
58+ }
59+ gv = g_variant_new_array(G_VARIANT_TYPE("{sv}"), children, hash.size());
60+ delete [] children;
61+ break;
62+ }
63+ default:
64+ break;
65+ }
66+ return gv;
67+}
68+
69+// implementation of this conversion taken from libdee-qt private utility function.
70+QVariant QVariantFromGVariant(GVariant *value)
71+{
72+ /* We need to special-case a{sv} here as G_VARIANT_CLASS_ARRAY handles simple arrays;
73+ we need to create QVariantHash, not a list */
74+ if (g_variant_is_of_type(value, G_VARIANT_TYPE_VARDICT)) {
75+ const gsize nChildren = g_variant_n_children(value);
76+ QVariantHash hash;
77+ for (gsize i = 0; i < nChildren; ++i)
78+ {
79+ GVariant* dict_entry = g_variant_get_child_value(value, i);
80+
81+ gchar* dict_key;
82+ GVariant *dict_var;
83+ g_variant_get(dict_entry, "{&sv}", &dict_key, &dict_var);
84+ hash.insert(QString::fromUtf8(dict_key), QVariantFromGVariant(dict_var));
85+ g_variant_unref(dict_var);
86+ g_variant_unref(dict_entry);
87+ }
88+ return hash;
89+ }
90+
91+ switch (g_variant_classify(value)) {
92+ case G_VARIANT_CLASS_BOOLEAN:
93+ return QVariant((bool) g_variant_get_boolean(value));
94+ case G_VARIANT_CLASS_BYTE:
95+ return QVariant((uchar) g_variant_get_byte(value));
96+ case G_VARIANT_CLASS_INT16:
97+ return QVariant((qint16) g_variant_get_int16(value));
98+ case G_VARIANT_CLASS_UINT16:
99+ return QVariant((quint16) g_variant_get_uint16(value));
100+ case G_VARIANT_CLASS_INT32:
101+ return QVariant((qint32) g_variant_get_int32(value));
102+ case G_VARIANT_CLASS_UINT32:
103+ return QVariant((quint32) g_variant_get_uint32(value));
104+ case G_VARIANT_CLASS_INT64:
105+ return QVariant((qint64) g_variant_get_int64(value));
106+ case G_VARIANT_CLASS_UINT64:
107+ return QVariant((quint64) g_variant_get_uint64(value));
108+ case G_VARIANT_CLASS_DOUBLE:
109+ return QVariant(g_variant_get_double(value));
110+ case G_VARIANT_CLASS_STRING:
111+ return QVariant(QString::fromUtf8(g_variant_get_string(value, NULL)));
112+ case G_VARIANT_CLASS_ARRAY:
113+ case G_VARIANT_CLASS_TUPLE:
114+ {
115+ const gsize nChildren = g_variant_n_children(value);
116+ QList<QVariant> array;
117+ for (gsize i = 0; i < nChildren; ++i)
118+ {
119+ GVariant* gvariant = g_variant_get_child_value(value, i);
120+ array << QVariantFromGVariant(gvariant);
121+ g_variant_unref(gvariant);
122+ }
123+ return array;
124+ }
125+ default:
126+ /* Fallback on an empty QVariant.
127+ FIXME: Missing conversion of following GVariant types:
128+ - G_VARIANT_CLASS_HANDLE
129+ - G_VARIANT_CLASS_OBJECT_PATH
130+ - G_VARIANT_CLASS_SIGNATURE
131+ - G_VARIANT_CLASS_VARIANT
132+ - G_VARIANT_CLASS_MAYBE
133+ - G_VARIANT_CLASS_DICT_ENTRY
134+ */
135+ return QVariant();
136+ }
137+}
138+
139+unity::glib::HintsMap convertToHintsMap(const QHash<QString, QVariant> &val)
140+{
141+ unity::glib::HintsMap hintsMap;
142+ QHash<QString, QVariant>::const_iterator it = val.constBegin();
143+ while (it != val.constEnd()) {
144+ hintsMap[it.key().toStdString()] = GVariantFromQVariant(it.value());
145+ ++it;
146+ }
147+ return hintsMap;
148+}
149+
150+unity::glib::HintsMap convertToHintsMap(const QVariant &var)
151+{
152+ if (var.type() == QVariant::Hash) {
153+ unity::glib::HintsMap hintsMap;
154+ const auto hash = var.toHash();
155+ return convertToHintsMap(hash);
156+ }
157+ return unity::glib::HintsMap();
158+}