1 /*
2 A library to communicate a menu object set accross DBus and
3 track updates and maintain consistency.
4
5 Copyright 2011 Canonical Ltd.
6
7 Authors:
8 Ted Gould <ted@canonical.com>
9
10 This program is free software: you can redistribute it and/or modify it
11 under the terms of either or both of the following licenses:
12
13 1) the GNU Lesser General Public License version 3, as published by the
14 Free Software Foundation; and/or
15 2) the GNU Lesser General Public License version 2.1, as published by
16 the Free Software Foundation.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranties of
20 MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
21 PURPOSE. See the applicable version of the GNU Lesser General Public
22 License for more details.
23
24 You should have received a copy of both the GNU Lesser General Public
25 License version 3 and version 2.1 along with this program. If not, see
26 <http://www.gnu.org/licenses/>
27 */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include <glib/gi18n-lib.h>
34
35 #include "defaults.h"
36 #include "menuitem.h"
37 #include "client.h"
38
39 struct _DbusmenuDefaultsPrivate {
40 GHashTable * types;
41 };
42
43 typedef struct _DefaultEntry DefaultEntry;
44 struct _DefaultEntry {
45 GVariantType * type;
46 GVariant * value;
47 };
48
49 #define DBUSMENU_DEFAULTS_GET_PRIVATE(o) \
50 (G_TYPE_INSTANCE_GET_PRIVATE ((o), DBUSMENU_TYPE_DEFAULTS, DbusmenuDefaultsPrivate))
51
52 static void dbusmenu_defaults_class_init (DbusmenuDefaultsClass *klass);
53 static void dbusmenu_defaults_init (DbusmenuDefaults *self);
54 static void dbusmenu_defaults_dispose (GObject *object);
55 static void dbusmenu_defaults_finalize (GObject *object);
56
57 static DefaultEntry * entry_create (const GVariantType * type, GVariant * variant);
58 static void entry_destroy (gpointer entry);
59
60 G_DEFINE_TYPE (DbusmenuDefaults, dbusmenu_defaults, G_TYPE_OBJECT);
61
62 static void
dbusmenu_defaults_class_init(DbusmenuDefaultsClass * klass)63 dbusmenu_defaults_class_init (DbusmenuDefaultsClass *klass)
64 {
65 GObjectClass *object_class = G_OBJECT_CLASS (klass);
66
67 g_type_class_add_private (klass, sizeof (DbusmenuDefaultsPrivate));
68
69 object_class->dispose = dbusmenu_defaults_dispose;
70 object_class->finalize = dbusmenu_defaults_finalize;
71 return;
72 }
73
74 static void
dbusmenu_defaults_init(DbusmenuDefaults * self)75 dbusmenu_defaults_init (DbusmenuDefaults *self)
76 {
77 self->priv = DBUSMENU_DEFAULTS_GET_PRIVATE(self);
78
79 self->priv->types = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_hash_table_destroy);
80
81 /* Standard defaults */
82 dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_VISIBLE, G_VARIANT_TYPE_BOOLEAN, g_variant_new_boolean(TRUE));
83 dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_ENABLED, G_VARIANT_TYPE_BOOLEAN, g_variant_new_boolean(TRUE));
84 dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_LABEL, G_VARIANT_TYPE_STRING, g_variant_new_string(_("Label Empty")));
85 dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_ICON_NAME, G_VARIANT_TYPE_STRING, NULL);
86 dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_ICON_DATA, G_VARIANT_TYPE("ay"), NULL);
87 dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE, G_VARIANT_TYPE_STRING, NULL);
88 dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, G_VARIANT_TYPE_INT32, NULL);
89 dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_SHORTCUT, G_VARIANT_TYPE("aas"), NULL);
90 dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY, G_VARIANT_TYPE_STRING, NULL);
91 dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_DISPOSITION, G_VARIANT_TYPE_STRING, g_variant_new_string(DBUSMENU_MENUITEM_DISPOSITION_NORMAL));
92 dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_ACCESSIBLE_DESC,G_VARIANT_TYPE_STRING, NULL);
93
94 /* Separator defaults */
95 dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_SEPARATOR, DBUSMENU_MENUITEM_PROP_VISIBLE, G_VARIANT_TYPE_BOOLEAN, g_variant_new_boolean(TRUE));
96
97 return;
98 }
99
100 static void
dbusmenu_defaults_dispose(GObject * object)101 dbusmenu_defaults_dispose (GObject *object)
102 {
103 DbusmenuDefaults * self = DBUSMENU_DEFAULTS(object);
104
105 if (self->priv->types != NULL) {
106 g_hash_table_destroy(self->priv->types);
107 self->priv->types = NULL;
108 }
109
110 G_OBJECT_CLASS (dbusmenu_defaults_parent_class)->dispose (object);
111 return;
112 }
113
114 static void
dbusmenu_defaults_finalize(GObject * object)115 dbusmenu_defaults_finalize (GObject *object)
116 {
117
118 G_OBJECT_CLASS (dbusmenu_defaults_parent_class)->finalize (object);
119 return;
120 }
121
122 /* Create a new entry based on the info provided */
123 static DefaultEntry *
entry_create(const GVariantType * type,GVariant * variant)124 entry_create (const GVariantType * type, GVariant * variant)
125 {
126 DefaultEntry * defentry = g_new0(DefaultEntry, 1);
127
128 if (type != NULL) {
129 defentry->type = g_variant_type_copy(type);
130 }
131
132 if (variant != NULL) {
133 defentry->value = variant;
134 g_variant_ref_sink(variant);
135 }
136
137 return defentry;
138 }
139
140 /* Destroy an entry */
141 static void
entry_destroy(gpointer entry)142 entry_destroy (gpointer entry)
143 {
144 DefaultEntry * defentry = (DefaultEntry *)entry;
145
146 if (defentry->type != NULL) {
147 g_variant_type_free(defentry->type);
148 defentry->type = NULL;
149 }
150
151 if (defentry->value != NULL) {
152 g_variant_unref(defentry->value);
153 defentry->value = NULL;
154 }
155
156 g_free(defentry);
157 return;
158 }
159
160 static DbusmenuDefaults * default_defaults = NULL;
161
162 /*
163 * dbusmenu_defaults_ref_default:
164 *
165 * Get a reference to the default instance. If it doesn't exist this
166 * function will create it.
167 *
168 * Return value: (transfer full): A reference to the defaults
169 */
170 DbusmenuDefaults *
dbusmenu_defaults_ref_default(void)171 dbusmenu_defaults_ref_default (void)
172 {
173 if (default_defaults == NULL) {
174 default_defaults = DBUSMENU_DEFAULTS(g_object_new(DBUSMENU_TYPE_DEFAULTS, NULL));
175 g_object_add_weak_pointer(G_OBJECT(default_defaults), (gpointer *)&default_defaults);
176 } else {
177 g_object_ref(default_defaults);
178 }
179
180 return default_defaults;
181 }
182
183 /*
184 * dbusmenu_defaults_default_set:
185 * @defaults: The #DbusmenuDefaults object to add to
186 * @type: (allow-none): The #DbusmenuMenuitem type for this default if #NULL will default to #DBUSMENU_CLIENT_TYPE_DEFAULT
187 * @property: Property name for the default
188 * @prop_type: (allow-none): Type of the property for runtime checking. To disable checking set to #NULL.
189 * @value: (allow-none): Default value for @property. #NULL if by default it is unset, but you want type checking from @prop_type.
190 *
191 * Sets up an entry in the defaults database for a given @property
192 * and menuitem type @type. @prop_type and @value can both be #NULL
193 * but both of them can not.
194 */
195 void
dbusmenu_defaults_default_set(DbusmenuDefaults * defaults,const gchar * type,const gchar * property,const GVariantType * prop_type,GVariant * value)196 dbusmenu_defaults_default_set (DbusmenuDefaults * defaults, const gchar * type, const gchar * property, const GVariantType * prop_type, GVariant * value)
197 {
198 g_return_if_fail(DBUSMENU_IS_DEFAULTS(defaults));
199 g_return_if_fail(property != NULL);
200 g_return_if_fail(prop_type != NULL || value != NULL);
201
202 if (type == NULL) {
203 type = DBUSMENU_CLIENT_TYPES_DEFAULT;
204 }
205
206 GHashTable * prop_table = (GHashTable *)g_hash_table_lookup(defaults->priv->types, type);
207
208 /* We've never had a default for this type, so we need
209 to create a table for it. */
210 if (prop_table == NULL) {
211 prop_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, entry_destroy);
212
213 g_hash_table_insert(prop_table, g_strdup(property), entry_create(prop_type, value));
214 g_hash_table_insert(defaults->priv->types, g_strdup(type), prop_table);
215 } else {
216 g_hash_table_replace(prop_table, g_strdup(property), entry_create(prop_type, value));
217 }
218
219 return;
220 }
221
222 /*
223 * dbusmenu_defaults_default_get:
224 * @defaults: The default database to use
225 * @type: (allow-none): The #DbusmenuMenuitem type for this default if #NULL will default to #DBUSMENU_CLIENT_TYPE_DEFAULT
226 * @property: Property name to lookup
227 *
228 * Gets an entry in the database for a give @property and @type.
229 *
230 * Return value: (transfer none): Returns a variant that does not
231 * have its ref count increased. If you want to keep it, you should
232 * do that.
233 */
234 GVariant *
dbusmenu_defaults_default_get(DbusmenuDefaults * defaults,const gchar * type,const gchar * property)235 dbusmenu_defaults_default_get (DbusmenuDefaults * defaults, const gchar * type, const gchar * property)
236 {
237 g_return_val_if_fail(DBUSMENU_IS_DEFAULTS(defaults), NULL);
238 g_return_val_if_fail(property != NULL, NULL);
239
240 if (type == NULL) {
241 type = DBUSMENU_CLIENT_TYPES_DEFAULT;
242 }
243
244 GHashTable * prop_table = (GHashTable *)g_hash_table_lookup(defaults->priv->types, type);
245
246 if (prop_table == NULL) {
247 return NULL;
248 }
249
250 DefaultEntry * entry = (DefaultEntry *)g_hash_table_lookup(prop_table, property);
251
252 if (entry == NULL) {
253 return NULL;
254 }
255
256 return entry->value;
257 }
258
259 /*
260 * dbusmenu_defaults_default_get_type:
261 * @defaults: The default database to use
262 * @type: (allow-none): The #DbusmenuMenuitem type for this default if #NULL will default to #DBUSMENU_CLIENT_TYPE_DEFAULT
263 * @property: Property name to lookup
264 *
265 * Gets the type for an entry in the database for a give @property and @type.
266 *
267 * Return value: (transfer none): Returns a type for the given
268 * @property value.
269 */
270 GVariantType *
dbusmenu_defaults_default_get_type(DbusmenuDefaults * defaults,const gchar * type,const gchar * property)271 dbusmenu_defaults_default_get_type (DbusmenuDefaults * defaults, const gchar * type, const gchar * property)
272 {
273 g_return_val_if_fail(DBUSMENU_IS_DEFAULTS(defaults), NULL);
274 g_return_val_if_fail(property != NULL, NULL);
275
276 if (type == NULL) {
277 type = DBUSMENU_CLIENT_TYPES_DEFAULT;
278 }
279
280 GHashTable * prop_table = (GHashTable *)g_hash_table_lookup(defaults->priv->types, type);
281
282 if (prop_table == NULL) {
283 return NULL;
284 }
285
286 DefaultEntry * entry = (DefaultEntry *)g_hash_table_lookup(prop_table, property);
287
288 if (entry == NULL) {
289 return NULL;
290 }
291
292 return entry->type;
293 }
294
295