1 /*
2 * Copyright (C) 2011 - 2012 Vivien Malerba <malerba@gnome-db.org>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #include <glib/gi18n-lib.h>
20 #include <libgda/libgda.h>
21 #include "mgr-ldap-classes.h"
22 #include "gda-tree-node.h"
23 #include <sqlite/virtual/gda-ldap-connection.h>
24
25 struct _MgrLdapClassesPriv {
26 BrowserConnection *bcnc;
27 gchar *class;
28 gboolean flat;
29 };
30
31 static void mgr_ldap_classes_class_init (MgrLdapClassesClass *klass);
32 static void mgr_ldap_classes_init (MgrLdapClasses *tmgr1, MgrLdapClassesClass *klass);
33 static void mgr_ldap_classes_dispose (GObject *object);
34
35 /* virtual methods */
36 static GSList *mgr_ldap_classes_update_children (GdaTreeManager *manager, GdaTreeNode *node,
37 const GSList *children_nodes,
38 gboolean *out_error, GError **error);
39
40 static GObjectClass *parent_class = NULL;
41
42 /*
43 * MgrLdapClasses class implementation
44 * @klass:
45 */
46 static void
mgr_ldap_classes_class_init(MgrLdapClassesClass * klass)47 mgr_ldap_classes_class_init (MgrLdapClassesClass *klass)
48 {
49 GObjectClass *object_class = G_OBJECT_CLASS (klass);
50
51 parent_class = g_type_class_peek_parent (klass);
52
53 /* virtual methods */
54 ((GdaTreeManagerClass*) klass)->update_children = mgr_ldap_classes_update_children;
55
56 object_class->dispose = mgr_ldap_classes_dispose;
57 }
58
59 static void
mgr_ldap_classes_init(MgrLdapClasses * mgr,G_GNUC_UNUSED MgrLdapClassesClass * klass)60 mgr_ldap_classes_init (MgrLdapClasses *mgr, G_GNUC_UNUSED MgrLdapClassesClass *klass)
61 {
62 g_return_if_fail (MGR_IS_LDAP_CLASSES (mgr));
63 mgr->priv = g_new0 (MgrLdapClassesPriv, 1);
64 }
65
66 static void
mgr_ldap_classes_dispose(GObject * object)67 mgr_ldap_classes_dispose (GObject *object)
68 {
69 MgrLdapClasses *mgr = (MgrLdapClasses *) object;
70
71 g_return_if_fail (MGR_IS_LDAP_CLASSES (mgr));
72
73 if (mgr->priv) {
74 if (mgr->priv->bcnc)
75 g_object_unref (mgr->priv->bcnc);
76 g_free (mgr->priv->class);
77 g_free (mgr->priv);
78 mgr->priv = NULL;
79 }
80
81 /* chain to parent class */
82 parent_class->dispose (object);
83 }
84
85 /**
86 * mgr_ldap_classes_get_type:
87 *
88 * Returns: the GType
89 */
90 GType
mgr_ldap_classes_get_type(void)91 mgr_ldap_classes_get_type (void)
92 {
93 static GType type = 0;
94
95 if (G_UNLIKELY (type == 0)) {
96 static GMutex registering;
97 static const GTypeInfo info = {
98 sizeof (MgrLdapClassesClass),
99 (GBaseInitFunc) NULL,
100 (GBaseFinalizeFunc) NULL,
101 (GClassInitFunc) mgr_ldap_classes_class_init,
102 NULL,
103 NULL,
104 sizeof (MgrLdapClasses),
105 0,
106 (GInstanceInitFunc) mgr_ldap_classes_init,
107 0
108 };
109
110 g_mutex_lock (®istering);
111 if (type == 0)
112 type = g_type_register_static (GDA_TYPE_TREE_MANAGER, "_MgrLdapClasses", &info, 0);
113 g_mutex_unlock (®istering);
114 }
115 return type;
116 }
117
118 /*
119 * mgr_ldap_classes_new:
120 * @cnc: a #GdaConnection object
121 * @flat: %TRUE if listing all the classes, if %TRUE, then @classname is ignored.
122 * @classname: (allow-none): an LDAP class or %NULL for the "top" class
123 *
124 * Creates a new #GdaTreeManager object which will list the children classes
125 *
126 * Returns: (transfer full): a new #GdaTreeManager object
127 */
128 GdaTreeManager*
mgr_ldap_classes_new(BrowserConnection * bcnc,gboolean flat,const gchar * classname)129 mgr_ldap_classes_new (BrowserConnection *bcnc, gboolean flat, const gchar *classname)
130 {
131 MgrLdapClasses *mgr;
132 g_return_val_if_fail (BROWSER_IS_CONNECTION (bcnc), NULL);
133
134 mgr = (MgrLdapClasses*) g_object_new (MGR_TYPE_LDAP_CLASSES, NULL);
135
136 mgr->priv->bcnc = g_object_ref (bcnc);
137 mgr->priv->flat = flat;
138 if (!flat) {
139 if (classname)
140 mgr->priv->class = g_strdup (classname);
141 }
142
143 return (GdaTreeManager*) mgr;
144 }
145
146 static GSList *
147 mgr_ldap_classes_update_children_flat (MgrLdapClasses *mgr, GdaTreeNode *node,
148 gboolean *out_error,
149 GError **error);
150 static GSList *
151 mgr_ldap_classes_update_children_nonflat (MgrLdapClasses *mgr, GdaTreeNode *node,
152 gboolean *out_error,
153 GError **error);
154
155 static GSList *
mgr_ldap_classes_update_children(GdaTreeManager * manager,GdaTreeNode * node,G_GNUC_UNUSED const GSList * children_nodes,gboolean * out_error,GError ** error)156 mgr_ldap_classes_update_children (GdaTreeManager *manager, GdaTreeNode *node,
157 G_GNUC_UNUSED const GSList *children_nodes, gboolean *out_error,
158 GError **error)
159 {
160 MgrLdapClasses *mgr = MGR_LDAP_CLASSES (manager);
161
162 if (mgr->priv->flat)
163 return mgr_ldap_classes_update_children_flat (mgr, node, out_error, error);
164 else
165 return mgr_ldap_classes_update_children_nonflat (mgr, node, out_error, error);
166
167 }
168
169 static gint
class_sort_func(GdaLdapClass * lcl1,GdaLdapClass * lcl2)170 class_sort_func (GdaLdapClass *lcl1, GdaLdapClass *lcl2)
171 {
172 if (lcl1->kind == lcl2->kind)
173 return g_ascii_strcasecmp (lcl1->names[0], lcl2->names[0]);
174 else
175 return lcl1->kind - lcl2->kind;
176 }
177
178 static GSList *
mgr_ldap_classes_update_children_nonflat(MgrLdapClasses * mgr,GdaTreeNode * node,gboolean * out_error,GError ** error)179 mgr_ldap_classes_update_children_nonflat (MgrLdapClasses *mgr, GdaTreeNode *node,
180 gboolean *out_error,
181 GError **error)
182 {
183 gchar *real_class = NULL;
184 if (!mgr->priv->bcnc) {
185 g_set_error (error, GDA_TREE_MANAGER_ERROR, GDA_TREE_MANAGER_UNKNOWN_ERROR,
186 "%s", _("No LDAP connection specified"));
187 if (out_error)
188 *out_error = TRUE;
189 goto onerror;
190 }
191
192 const GValue *cvalue;
193 cvalue = gda_tree_node_fetch_attribute (node, "kind");
194 if (cvalue && (G_VALUE_TYPE (cvalue) == G_TYPE_BOOLEAN) && g_value_get_boolean (cvalue))
195 return NULL;
196
197 if (node) {
198 /* looking for a dn in @node's attributes */
199 cvalue = gda_tree_node_fetch_attribute (node, "class");
200 if (cvalue && (G_VALUE_TYPE (cvalue) == G_TYPE_STRING))
201 real_class = g_value_dup_string (cvalue);
202 }
203 if (!real_class)
204 real_class = g_strdup (mgr->priv->class);
205
206 GSList *classes_list;
207 gboolean list_to_free = FALSE;
208 if (real_class) {
209 GdaLdapClass *lcl;
210 lcl = browser_connection_get_class_info (mgr->priv->bcnc, real_class);
211 if (!lcl)
212 goto onerror;
213 classes_list = (GSList*) lcl->children;
214 }
215 else {
216 /* sort by kind */
217 classes_list = g_slist_copy ((GSList*) browser_connection_get_top_classes (mgr->priv->bcnc));
218 classes_list = g_slist_sort (classes_list, (GCompareFunc) class_sort_func);
219 list_to_free = TRUE;
220 }
221
222 GSList *list = NULL;
223 const GSList *child;
224 for (child = classes_list; child; child = child->next) {
225 GdaLdapClass *sub;
226 GdaTreeNode* snode;
227 GValue *value;
228 GdkPixbuf *pixbuf;
229
230 sub = (GdaLdapClass*) child->data;
231
232 snode = gda_tree_manager_create_node ((GdaTreeManager*) mgr, node, sub->names[0]);
233
234 /* class name */
235 g_value_set_string ((value = gda_value_new (G_TYPE_STRING)), sub->names[0]);
236 gda_tree_node_set_node_attribute (snode, "class", value, NULL);
237 gda_value_free (value);
238
239 /* icon */
240 pixbuf = browser_get_pixbuf_for_ldap_class (sub->kind);
241 value = gda_value_new (G_TYPE_OBJECT);
242 g_value_set_object (value, pixbuf);
243 gda_tree_node_set_node_attribute (snode, "icon", value, NULL);
244 gda_value_free (value);
245
246 list = g_slist_prepend (list, snode);
247 }
248 if (list_to_free)
249 g_slist_free (classes_list);
250 return g_slist_reverse (list);
251
252 onerror:
253 g_free (real_class);
254 if (out_error)
255 *out_error = TRUE;
256 return NULL;
257 }
258
259 static void
classes_foreach_func(GdaLdapClass * lcl,GSList ** list)260 classes_foreach_func (GdaLdapClass *lcl, GSList **list)
261 {
262 if (!g_slist_find (*list, lcl))
263 *list = g_slist_insert_sorted (*list, lcl, (GCompareFunc) class_sort_func);
264 g_slist_foreach (lcl->children, (GFunc) classes_foreach_func, list);
265 }
266
267 static GSList *
mgr_ldap_classes_update_children_flat(MgrLdapClasses * mgr,GdaTreeNode * node,gboolean * out_error,GError ** error)268 mgr_ldap_classes_update_children_flat (MgrLdapClasses *mgr, GdaTreeNode *node,
269 gboolean *out_error,
270 GError **error)
271 {
272 if (!mgr->priv->bcnc) {
273 g_set_error (error, GDA_TREE_MANAGER_ERROR, GDA_TREE_MANAGER_UNKNOWN_ERROR,
274 "%s", _("No LDAP connection specified"));
275 if (out_error)
276 *out_error = TRUE;
277 goto onerror;
278 }
279
280 const GSList *top_classes_list;
281 GSList *list = NULL, *classes_list = NULL;
282 top_classes_list = browser_connection_get_top_classes (mgr->priv->bcnc);
283 for (list = (GSList*) top_classes_list; list; list = list->next) {
284 GdaLdapClass *lcl;
285 lcl = (GdaLdapClass*) list->data;
286 classes_list = g_slist_insert_sorted (classes_list, lcl, (GCompareFunc) class_sort_func);
287 g_slist_foreach (lcl->children, (GFunc) classes_foreach_func, &classes_list);
288 }
289
290 GSList *child;
291 GdaLdapClassKind kind = 0;
292 for (list = NULL, child = classes_list; child; child = child->next) {
293 GdaLdapClass *sub;
294 GdaTreeNode* snode;
295 GValue *value;
296 GdkPixbuf *pixbuf;
297
298 sub = (GdaLdapClass*) child->data;
299
300 if (kind != sub->kind) {
301 /* add extra node as separator */
302 const gchar *tmp;
303 tmp = browser_get_kind_for_ldap_class (sub->kind);
304 snode = gda_tree_manager_create_node ((GdaTreeManager*) mgr, node, tmp);
305 list = g_slist_prepend (list, snode);
306 kind = sub->kind;
307
308 /* marker */
309 g_value_set_boolean ((value = gda_value_new (G_TYPE_BOOLEAN)), TRUE);
310 gda_tree_node_set_node_attribute (snode, "kind", value, NULL);
311 gda_value_free (value);
312
313 /* icon */
314 pixbuf = browser_get_pixbuf_for_ldap_class (sub->kind);
315 value = gda_value_new (G_TYPE_OBJECT);
316 g_value_set_object (value, pixbuf);
317 gda_tree_node_set_node_attribute (snode, "icon", value, NULL);
318 gda_value_free (value);
319 }
320 snode = gda_tree_manager_create_node ((GdaTreeManager*) mgr, node, sub->names[0]);
321
322 /* class name */
323 g_value_set_string ((value = gda_value_new (G_TYPE_STRING)), sub->names[0]);
324 gda_tree_node_set_node_attribute (snode, "class", value, NULL);
325 gda_value_free (value);
326
327 /* icon */
328 pixbuf = browser_get_pixbuf_for_ldap_class (sub->kind);
329 value = gda_value_new (G_TYPE_OBJECT);
330 g_value_set_object (value, pixbuf);
331 gda_tree_node_set_node_attribute (snode, "icon", value, NULL);
332 gda_value_free (value);
333
334 list = g_slist_prepend (list, snode);
335 }
336 g_slist_free (classes_list);
337 return g_slist_reverse (list);
338
339 onerror:
340 if (out_error)
341 *out_error = TRUE;
342 return NULL;
343 }
344