1 /*
2  * Copyright (C) 2009 - 2012 Vivien Malerba <malerba@gnome-db.org>
3  * Copyright (C) 2010 David King <davidk@openismus.com>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18  */
19 
20 #include <glib/gi18n-lib.h>
21 #include <string.h>
22 #include <libgda/libgda.h>
23 #include <sql-parser/gda-sql-parser.h>
24 #include "mgr-favorites.h"
25 #include "support.h"
26 #include <libgda/gda-debug-macros.h>
27 
28 /* asynchronous (in idle loop) icon resolution */
29 typedef struct {
30         GdaTreeNode *node;
31         gchar *dn;
32 } IconResolutionData;
33 static void
icon_resolution_data_free(IconResolutionData * data)34 icon_resolution_data_free (IconResolutionData *data)
35 {
36         g_object_unref (G_OBJECT (data->node));
37         g_free (data->dn);
38         g_free (data);
39 }
40 
41 struct _MgrFavoritesPriv {
42 	BrowserConnection    *bcnc;
43 	ToolsFavoritesType  fav_type;
44 	gint                  order_key;
45 
46 	GSList               *icons_resol_list; /* list of IconResolutionData pointers */
47         guint                 icons_resol_timer;
48 };
49 
50 static void mgr_favorites_class_init (MgrFavoritesClass *klass);
51 static void mgr_favorites_init       (MgrFavorites *tmgr1, MgrFavoritesClass *klass);
52 static void mgr_favorites_dispose    (GObject *object);
53 static void mgr_favorites_set_property (GObject *object,
54 					guint param_id,
55 					const GValue *value,
56 					GParamSpec *pspec);
57 static void mgr_favorites_get_property (GObject *object,
58 					guint param_id,
59 					GValue *value,
60 					GParamSpec *pspec);
61 
62 /* virtual methods */
63 static GSList *mgr_favorites_update_children (GdaTreeManager *manager, GdaTreeNode *node,
64 					    const GSList *children_nodes, gboolean *out_error, GError **error);
65 
66 static GObjectClass *parent_class = NULL;
67 
68 /* properties */
69 enum {
70         PROP_0,
71 	PROP_BROWSER_CNC
72 };
73 
74 /*
75  * MgrFavorites class implementation
76  * @klass:
77  */
78 static void
mgr_favorites_class_init(MgrFavoritesClass * klass)79 mgr_favorites_class_init (MgrFavoritesClass *klass)
80 {
81 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
82 
83 	parent_class = g_type_class_peek_parent (klass);
84 
85 	/* virtual methods */
86 	((GdaTreeManagerClass*) klass)->update_children = mgr_favorites_update_children;
87 
88 	/* Properties */
89         object_class->set_property = mgr_favorites_set_property;
90         object_class->get_property = mgr_favorites_get_property;
91 
92 	g_object_class_install_property (object_class, PROP_BROWSER_CNC,
93                                          g_param_spec_object ("browser-connection", NULL, "Connection to use",
94                                                               BROWSER_TYPE_CONNECTION,
95                                                               G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
96 	object_class->dispose = mgr_favorites_dispose;
97 }
98 
99 static void
mgr_favorites_init(MgrFavorites * mgr,G_GNUC_UNUSED MgrFavoritesClass * klass)100 mgr_favorites_init (MgrFavorites *mgr, G_GNUC_UNUSED MgrFavoritesClass *klass)
101 {
102 	mgr->priv = g_new0 (MgrFavoritesPriv, 1);
103 }
104 
105 static void
mgr_favorites_dispose(GObject * object)106 mgr_favorites_dispose (GObject *object)
107 {
108 	MgrFavorites *mgr = (MgrFavorites *) object;
109 
110 	if (mgr->priv) {
111 		if (mgr->priv->bcnc)
112 			g_object_unref (mgr->priv->bcnc);
113 
114 		if (mgr->priv->icons_resol_timer) {
115                         g_source_remove (mgr->priv->icons_resol_timer);
116                         mgr->priv->icons_resol_timer = 0;
117                 }
118 
119                 if (mgr->priv->icons_resol_list) {
120                         g_slist_foreach (mgr->priv->icons_resol_list, (GFunc) icon_resolution_data_free, NULL);
121                         g_slist_free (mgr->priv->icons_resol_list);
122                         mgr->priv->icons_resol_list = NULL;
123                 }
124 
125 		g_free (mgr->priv);
126 		mgr->priv = NULL;
127 	}
128 
129 	/* chain to parent class */
130 	parent_class->dispose (object);
131 }
132 
133 /**
134  * mgr_favorites_get_type
135  *
136  * Returns: the GType
137  */
138 GType
mgr_favorites_get_type(void)139 mgr_favorites_get_type (void)
140 {
141         static GType type = 0;
142 
143         if (G_UNLIKELY (type == 0)) {
144                 static GMutex registering;
145                 static const GTypeInfo info = {
146                         sizeof (MgrFavoritesClass),
147                         (GBaseInitFunc) NULL,
148                         (GBaseFinalizeFunc) NULL,
149                         (GClassInitFunc) mgr_favorites_class_init,
150                         NULL,
151                         NULL,
152                         sizeof (MgrFavorites),
153                         0,
154                         (GInstanceInitFunc) mgr_favorites_init,
155 			0
156                 };
157 
158                 g_mutex_lock (&registering);
159                 if (type == 0)
160                         type = g_type_register_static (GDA_TYPE_TREE_MANAGER, "MgrFavorites", &info, 0);
161                 g_mutex_unlock (&registering);
162         }
163         return type;
164 }
165 
166 static void
mgr_favorites_set_property(GObject * object,guint param_id,const GValue * value,GParamSpec * pspec)167 mgr_favorites_set_property (GObject *object,
168 				   guint param_id,
169 				   const GValue *value,
170 				   GParamSpec *pspec)
171 {
172         MgrFavorites *mgr;
173 
174         mgr = MGR_FAVORITES (object);
175         if (mgr->priv) {
176                 switch (param_id) {
177 		case PROP_BROWSER_CNC:
178 			mgr->priv->bcnc = (BrowserConnection*) g_value_get_object (value);
179 			if (mgr->priv->bcnc)
180 				g_object_ref (mgr->priv->bcnc);
181 
182 			break;
183 		default:
184 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
185 			break;
186                 }
187         }
188 }
189 
190 static void
mgr_favorites_get_property(GObject * object,guint param_id,GValue * value,GParamSpec * pspec)191 mgr_favorites_get_property (GObject *object,
192 				   guint param_id,
193 				   GValue *value,
194 				   GParamSpec *pspec)
195 {
196         MgrFavorites *mgr;
197 
198         mgr = MGR_FAVORITES (object);
199         if (mgr->priv) {
200                 switch (param_id) {
201 		case PROP_BROWSER_CNC:
202 			g_value_set_object (value, mgr->priv->bcnc);
203 			break;
204 		default:
205 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
206 			break;
207                 }
208         }
209 }
210 
211 /**
212  * mgr_favorites_new
213  * @bcnc: a #BrowserConnection object
214  * @type: the type of favorites to handle
215  * @order_key: ordering key, see gda_tools_favorites_add()
216  *
217  * Creates a new #GdaTreeManager object which will add one tree node for each favorite of the @type type
218  *
219  * Returns: a new #GdaTreeManager object
220  */
221 GdaTreeManager*
mgr_favorites_new(BrowserConnection * bcnc,ToolsFavoritesType type,gint order_key)222 mgr_favorites_new (BrowserConnection *bcnc, ToolsFavoritesType type, gint order_key)
223 {
224 	MgrFavorites *mgr;
225 	g_return_val_if_fail (BROWSER_IS_CONNECTION (bcnc), NULL);
226 
227 	mgr = (MgrFavorites*) g_object_new (MGR_FAVORITES_TYPE,
228 					    "browser-connection", bcnc, NULL);
229 	mgr->priv->fav_type = type;
230 	mgr->priv->order_key = order_key;
231 	return (GdaTreeManager*) mgr;
232 }
233 
234 static gchar *
create_summary_for_statement(BrowserConnection * bcnc,const gchar * sql)235 create_summary_for_statement (BrowserConnection *bcnc, const gchar *sql)
236 {
237 	GdaSqlParser *parser;
238 	GString *string;
239 	GdaBatch *batch;
240 
241 	parser = browser_connection_create_parser (bcnc);
242 	string = g_string_new ("");
243 
244 	batch = gda_sql_parser_parse_string_as_batch (parser, sql, NULL, NULL);
245 	if (batch) {
246 		const GSList *stmt_list;
247 		stmt_list = gda_batch_get_statements (batch);
248 		if (!stmt_list || !(stmt_list->data))
249 			g_string_append (string, _("Empty statement"));
250 		else if (stmt_list->next)
251 			g_string_append (string, _("Multiple statements"));
252 		else {
253 			switch (gda_statement_get_statement_type (GDA_STATEMENT (stmt_list->data))) {
254 			case GDA_SQL_STATEMENT_SELECT:
255 				g_string_append (string, _("SELECT statement"));
256 				break;
257 			case GDA_SQL_STATEMENT_INSERT:
258 				g_string_append (string, _("INSERT statement"));
259 				break;
260 			case GDA_SQL_STATEMENT_UPDATE:
261 				g_string_append (string, _("UPDATE statement"));
262 				break;
263 			case GDA_SQL_STATEMENT_DELETE:
264 				g_string_append (string, _("DELETE statement"));
265 				break;
266 			case GDA_SQL_STATEMENT_COMPOUND:
267 				g_string_append (string, _("COMPOUND SELECT statement"));
268 				break;
269 			case GDA_SQL_STATEMENT_BEGIN:
270 				g_string_append (string, _("BEGIN statement"));
271 				break;
272 			case GDA_SQL_STATEMENT_ROLLBACK:
273 				g_string_append (string, _("ROLLBACK statement"));
274 				break;
275 			case GDA_SQL_STATEMENT_COMMIT:
276 				g_string_append (string, _("COMMIT statement"));
277 				break;
278 			case GDA_SQL_STATEMENT_SAVEPOINT:
279 				g_string_append (string, _("ADD SAVEPOINT statement"));
280 				break;
281 			case GDA_SQL_STATEMENT_ROLLBACK_SAVEPOINT:
282 				g_string_append (string, _("ROLLBACK SAVEPOINT statement"));
283 				break;
284 			case GDA_SQL_STATEMENT_DELETE_SAVEPOINT:
285 				g_string_append (string, _("DELETE SAVEPOINT statement"));
286 				break;
287 			case GDA_SQL_STATEMENT_UNKNOWN:
288 				g_string_append (string, _("Unknown statement"));
289 				break;
290 			case GDA_SQL_STATEMENT_NONE:
291 				g_string_append (string, _("Empty statement"));
292 				break;
293 			}
294 		}
295 
296 		/* parameters */
297 		GdaSet *params;
298 		if (gda_batch_get_parameters (batch, &params, NULL) && params) {
299 			GSList *list;
300 			GdaHolder *holder;
301 			for (list = params->holders; list; list = list->next) {
302 				holder = GDA_HOLDER (list->data);
303 				g_string_append_c (string, '\n');
304 				g_string_append (string, gda_holder_get_id (holder));
305 				g_string_append (string, "::");
306 				g_string_append (string, gda_g_type_to_string (gda_holder_get_g_type (holder)));
307 				if (! gda_holder_get_not_null (holder))
308 					g_string_append (string, "::null");
309 			}
310 			g_object_unref (params);
311                 }
312 
313 		g_object_unref (batch);
314 	}
315 	else {
316 		gint len;
317 		gchar *tmp;
318 		tmp = g_strdup (sql);
319 		len = strlen (sql);
320 		if (len > 40)
321 			tmp [40] = 0;
322 		g_string_append (string, tmp);
323 		g_free (tmp);
324 	}
325 
326 	g_object_unref (parser);
327 	return g_string_free (string, FALSE);
328 }
329 
330 /*
331  * Build a hash where key = contents as a string, and value = GdaTreeNode
332  */
333 static GHashTable *
hash_for_existing_nodes(const GSList * nodes)334 hash_for_existing_nodes (const GSList *nodes)
335 {
336 	GHashTable *hash;
337 	const GSList *list;
338 
339 	hash = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, NULL);
340 	for (list = nodes; list; list = list->next) {
341 		const GValue *cvalue;
342 		cvalue = gda_tree_node_get_node_attribute ((GdaTreeNode*) list->data, MGR_FAVORITES_ID_ATT_NAME);
343 		if (cvalue && (G_VALUE_TYPE (cvalue) == G_TYPE_INT)) {
344 			gint id;
345 			id = g_value_get_int (cvalue);
346 			if (id >= 0) {
347 				gint *key = g_new0 (gint, 1);
348 				*key = id;
349 				g_hash_table_insert (hash, (gpointer) key, list->data);
350 			}
351 		}
352 	}
353 	return hash;
354 }
355 
356 static gboolean icons_resol_cb (MgrFavorites *mgr);
357 
358 static GSList *
mgr_favorites_update_children(GdaTreeManager * manager,GdaTreeNode * node,const GSList * children_nodes,gboolean * out_error,GError ** error)359 mgr_favorites_update_children (GdaTreeManager *manager, GdaTreeNode *node, const GSList *children_nodes,
360 			       gboolean *out_error, GError **error)
361 {
362 	MgrFavorites *mgr = MGR_FAVORITES (manager);
363 	GSList *nodes_list = NULL;
364 	GHashTable *ehash = NULL;
365 	GSList *fav_list;
366 	GError *lerror = NULL;
367 	BrowserConnection *bcnc;
368 
369 	if (out_error)
370 		*out_error = FALSE;
371 
372 	if (children_nodes)
373 		ehash = hash_for_existing_nodes (children_nodes);
374 
375 	bcnc = mgr->priv->bcnc;
376 	fav_list = gda_tools_favorites_list (browser_connection_get_favorites (bcnc),
377 					   0, mgr->priv->fav_type,
378 					   mgr->priv->order_key, &lerror);
379 	if (fav_list) {
380 		GSList *list;
381 		gint pos;
382 		for (list = fav_list, pos = 0; list; list = list->next, pos ++) {
383 			ToolsFavoritesAttributes *fav = (ToolsFavoritesAttributes *) list->data;
384 			GdaTreeNode* snode = NULL;
385 			GValue *av;
386 
387 			if (ehash)
388 				snode = g_hash_table_lookup (ehash, &(fav->id));
389 
390 
391 			if (snode) {
392 				/* use the same node */
393 				g_object_ref (G_OBJECT (snode));
394 			}
395 
396 			if (fav->type == GDA_TOOLS_FAVORITES_TABLES) {
397 				if (!snode) {
398 					GdaQuarkList *ql;
399 					const gchar *fname = NULL;
400 
401 					ql = gda_quark_list_new_from_string (fav->contents);
402 					if (!ql || !(fname = gda_quark_list_find (ql, "OBJ_SHORT_NAME"))) {
403 						g_warning ("Invalid TABLE favorite format: %s", fav->contents);
404 					}
405 					else {
406 						snode = gda_tree_manager_create_node (manager, node, NULL);
407 						g_value_set_string ((av = gda_value_new (G_TYPE_STRING)), fname);
408 						gda_tree_node_set_node_attribute (snode, "markup", av, NULL);
409 						gda_value_free (av);
410 
411 						g_value_set_string ((av = gda_value_new (G_TYPE_STRING)),
412 								    fav->contents);
413 						gda_tree_node_set_node_attribute (snode,
414 										  MGR_FAVORITES_CONTENTS_ATT_NAME,
415 										  av, NULL);
416 						gda_value_free (av);
417 
418 
419 						g_value_set_int ((av = gda_value_new (G_TYPE_INT)), fav->id);
420 						gda_tree_node_set_node_attribute (snode,
421 										  MGR_FAVORITES_ID_ATT_NAME,
422 										  av, NULL);
423 						gda_value_free (av);
424 
425 						g_value_set_uint ((av = gda_value_new (G_TYPE_UINT)), fav->type);
426 						gda_tree_node_set_node_attribute (snode,
427 										  MGR_FAVORITES_TYPE_ATT_NAME,
428 										  av, NULL);
429 						gda_value_free (av);
430 
431 						/* icon */
432 						GdkPixbuf *pixbuf;
433 						pixbuf = browser_get_pixbuf_icon (BROWSER_ICON_TABLE);
434 						av = gda_value_new (G_TYPE_OBJECT);
435 						g_value_set_object (av, pixbuf);
436 						gda_tree_node_set_node_attribute (snode, "icon", av, NULL);
437 						gda_value_free (av);
438 					}
439 					if (ql)
440 						gda_quark_list_free (ql);
441 				}
442 			}
443 			else if (fav->type == GDA_TOOLS_FAVORITES_DIAGRAMS) {
444 				if (!snode) {
445 					snode = gda_tree_manager_create_node (manager, node, NULL);
446 
447 					g_value_set_int ((av = gda_value_new (G_TYPE_INT)), fav->id);
448 					gda_tree_node_set_node_attribute (snode,
449 									  MGR_FAVORITES_ID_ATT_NAME,
450 									  av, NULL);
451 					gda_value_free (av);
452 
453 					g_value_set_uint ((av = gda_value_new (G_TYPE_UINT)), fav->type);
454 					gda_tree_node_set_node_attribute (snode,
455 									  MGR_FAVORITES_TYPE_ATT_NAME,
456 									  av, NULL);
457 					gda_value_free (av);
458 
459 					/* icon */
460 					GdkPixbuf *pixbuf;
461 					pixbuf = browser_get_pixbuf_icon (BROWSER_ICON_DIAGRAM);
462 					av = gda_value_new (G_TYPE_OBJECT);
463 					g_value_set_object (av, pixbuf);
464 					gda_tree_node_set_node_attribute (snode, "icon", av, NULL);
465 					gda_value_free (av);
466 				}
467 
468 				g_value_set_string ((av = gda_value_new (G_TYPE_STRING)),
469 						    fav->contents);
470 				gda_tree_node_set_node_attribute (snode,
471 								  MGR_FAVORITES_CONTENTS_ATT_NAME,
472 								  av, NULL);
473 				gda_value_free (av);
474 
475 				g_value_set_string ((av = gda_value_new (G_TYPE_STRING)), fav->name);
476 				gda_tree_node_set_node_attribute (snode, "markup", av, NULL);
477 				gda_value_free (av);
478 			}
479 			else if (fav->type == GDA_TOOLS_FAVORITES_QUERIES) {
480 				if (!snode) {
481 					snode = gda_tree_manager_create_node (manager, node, NULL);
482 
483 					g_value_set_int ((av = gda_value_new (G_TYPE_INT)), fav->id);
484 					gda_tree_node_set_node_attribute (snode,
485 									  MGR_FAVORITES_ID_ATT_NAME,
486 									  av, NULL);
487 					gda_value_free (av);
488 
489 					g_value_set_int ((av = gda_value_new (G_TYPE_INT)), pos);
490 					gda_tree_node_set_node_attribute (snode,
491 									  MGR_FAVORITES_POSITION_ATT_NAME,
492 									  av, NULL);
493 					gda_value_free (av);
494 				}
495 
496 				/* is action */
497 				gboolean is_action = FALSE;
498 				GSList *favlist;
499 				GdkPixbuf *pixbuf;
500 				favlist = gda_tools_favorites_list (browser_connection_get_favorites (bcnc),
501 								  0, GDA_TOOLS_FAVORITES_ACTIONS,
502 								  -1, NULL);
503 				if (favlist) {
504 					gchar *tmp;
505 					tmp = g_strdup_printf ("QUERY%d", fav->id);
506 					GSList *list;
507 					for (list = favlist; list; list = list->next) {
508 						ToolsFavoritesAttributes *afav;
509 						afav = (ToolsFavoritesAttributes*) list->data;
510 						if (!strcmp (afav->contents, tmp)) {
511 							is_action = TRUE;
512 							break;
513 						}
514 					}
515 					g_free (tmp);
516 					gda_tools_favorites_free_list (favlist);
517 				}
518 				if (is_action)
519 					pixbuf = browser_get_pixbuf_icon (BROWSER_ICON_ACTION);
520 				else
521 					pixbuf = browser_get_pixbuf_icon (BROWSER_ICON_QUERY);
522 				av = gda_value_new (G_TYPE_OBJECT);
523 				g_value_set_object (av, pixbuf);
524 				gda_tree_node_set_node_attribute (snode, "icon", av, NULL);
525 				gda_value_free (av);
526 
527 				/* summary */
528 				g_value_take_string ((av = gda_value_new (G_TYPE_STRING)),
529 						     create_summary_for_statement (bcnc, fav->contents));
530 				gda_tree_node_set_node_attribute (snode, "summary", av, NULL);
531 				gda_value_free (av);
532 
533 				g_value_set_string ((av = gda_value_new (G_TYPE_STRING)),
534 						    fav->contents);
535 				gda_tree_node_set_node_attribute (snode,
536 								  MGR_FAVORITES_CONTENTS_ATT_NAME,
537 								  av, NULL);
538 				gda_value_free (av);
539 
540 				g_value_set_string ((av = gda_value_new (G_TYPE_STRING)), fav->name);
541 				gda_tree_node_set_node_attribute (snode, MGR_FAVORITES_NAME_ATT_NAME,
542 								  av, NULL);
543 				gda_value_free (av);
544 			}
545 			else if (fav->type == GDA_TOOLS_FAVORITES_DATA_MANAGERS) {
546 				if (!snode) {
547 					snode = gda_tree_manager_create_node (manager, node, NULL);
548 
549 					g_value_set_int ((av = gda_value_new (G_TYPE_INT)), fav->id);
550 					gda_tree_node_set_node_attribute (snode,
551 									  MGR_FAVORITES_ID_ATT_NAME,
552 									  av, NULL);
553 					gda_value_free (av);
554 
555 					g_value_set_int ((av = gda_value_new (G_TYPE_INT)), pos);
556 					gda_tree_node_set_node_attribute (snode,
557 									  MGR_FAVORITES_POSITION_ATT_NAME,
558 									  av, NULL);
559 					gda_value_free (av);
560 
561 					g_value_set_uint ((av = gda_value_new (G_TYPE_UINT)), fav->type);
562                                                 gda_tree_node_set_node_attribute (snode,
563                                                                                   MGR_FAVORITES_TYPE_ATT_NAME,
564                                                                                   av, NULL);
565                                         gda_value_free (av);
566 
567 					/* icon */
568 					GdkPixbuf *pixbuf;
569 					pixbuf = browser_get_pixbuf_icon (BROWSER_ICON_TABLE);
570 					av = gda_value_new (G_TYPE_OBJECT);
571 					g_value_set_object (av, pixbuf);
572 					gda_tree_node_set_node_attribute (snode, "icon", av, NULL);
573 					gda_value_free (av);
574 				}
575 
576 				g_value_set_string ((av = gda_value_new (G_TYPE_STRING)),
577 						    fav->contents);
578 				gda_tree_node_set_node_attribute (snode,
579 								  MGR_FAVORITES_CONTENTS_ATT_NAME,
580 								  av, NULL);
581 				gda_value_free (av);
582 
583 				g_value_set_string ((av = gda_value_new (G_TYPE_STRING)), fav->name);
584 				gda_tree_node_set_node_attribute (snode, MGR_FAVORITES_NAME_ATT_NAME,
585 								  av, NULL);
586 				gda_value_free (av);
587 			}
588 #ifdef HAVE_LDAP
589 			else if (fav->type == GDA_TOOLS_FAVORITES_LDAP_DN) {
590 				if (!snode) {
591 					/* favorite ID */
592 					snode = gda_tree_manager_create_node (manager, node, NULL);
593 
594 					g_value_set_int ((av = gda_value_new (G_TYPE_INT)), fav->id);
595 					gda_tree_node_set_node_attribute (snode,
596 									  MGR_FAVORITES_ID_ATT_NAME,
597 									  av, NULL);
598 					gda_value_free (av);
599 
600 					/* icon */
601 					GdkPixbuf *pixbuf;
602 					pixbuf = browser_get_pixbuf_icon (BROWSER_ICON_LDAP_ENTRY);
603 
604 					av = gda_value_new (G_TYPE_OBJECT);
605 					g_value_set_object (av, pixbuf);
606 					gda_tree_node_set_node_attribute (snode, "icon", av, NULL);
607 					gda_value_free (av);
608 
609 					g_value_set_uint ((av = gda_value_new (G_TYPE_UINT)), fav->type);
610 					gda_tree_node_set_node_attribute (snode,
611 									  MGR_FAVORITES_TYPE_ATT_NAME,
612 									  av, NULL);
613                                         gda_value_free (av);
614 
615 					IconResolutionData *data;
616 					data = g_new0 (IconResolutionData, 1);
617 					data->node = g_object_ref (snode);
618 					data->dn = g_strdup (fav->name);
619 					mgr->priv->icons_resol_list = g_slist_prepend (mgr->priv->icons_resol_list, data);
620 					if (mgr->priv->icons_resol_timer == 0)
621 						mgr->priv->icons_resol_timer = g_idle_add ((GSourceFunc) icons_resol_cb, mgr);
622 				}
623 
624 				gchar **dna;
625 				GString *tmpstring;
626 				dna = gda_ldap_dn_split (fav->name, FALSE);
627 				tmpstring = g_string_new ("");
628 				if (dna) {
629 					if (dna[0]) {
630 						if (dna[1])
631 							g_string_append_printf (tmpstring,
632 										"<b>%s</b>,%s",
633 										dna[0], dna[1]);
634 						else
635 							g_string_append_printf (tmpstring,
636 										"<b>%s</b>",
637 										dna[0]);
638 					}
639 					else {
640 						gchar *tmp;
641 						tmp = g_markup_escape_text (fav->name, -1);
642 						g_string_append (tmpstring, tmp);
643 						g_free (tmp);
644 					}
645 					g_strfreev (dna);
646 				}
647 				else {
648 					gchar *tmp;
649 					tmp = g_markup_escape_text (fav->name, -1);
650 					g_string_append (tmpstring, tmp);
651 					g_free (tmp);
652 				}
653 
654 				if (fav->descr && *fav->descr) {
655 					gchar *tmp;
656 					tmp = g_markup_escape_text (fav->descr, -1);
657 					g_string_append_printf (tmpstring,
658 								"\n<small>%s</small>", tmp);
659 					g_free (tmp);
660 
661 					g_value_set_string ((av = gda_value_new (G_TYPE_STRING)),
662 							    fav->descr);
663 					gda_tree_node_set_node_attribute (snode, "descr", av, NULL);
664 					gda_value_free (av);
665 				}
666 
667 				g_value_take_string ((av = gda_value_new (G_TYPE_STRING)),
668 						     g_string_free (tmpstring, FALSE));
669 				gda_tree_node_set_node_attribute (snode, "markup", av, NULL);
670 				gda_value_free (av);
671 
672 				g_value_set_string ((av = gda_value_new (G_TYPE_STRING)),
673 						    fav->name);
674 				gda_tree_node_set_node_attribute (snode,
675 								  MGR_FAVORITES_CONTENTS_ATT_NAME,
676 								  av, NULL);
677 				gda_value_free (av);
678 			}
679 			else if (fav->type == GDA_TOOLS_FAVORITES_LDAP_CLASS) {
680 				if (!snode) {
681 					/* favorite ID */
682 					snode = gda_tree_manager_create_node (manager, node, NULL);
683 
684 					g_value_set_int ((av = gda_value_new (G_TYPE_INT)), fav->id);
685 					gda_tree_node_set_node_attribute (snode,
686 									  MGR_FAVORITES_ID_ATT_NAME,
687 									  av, NULL);
688 					gda_value_free (av);
689 
690 					/* icon */
691 					GdkPixbuf *pixbuf;
692 					GdaLdapClass *lcl;
693 					lcl = browser_connection_get_class_info (bcnc, fav->name);
694 					pixbuf = browser_get_pixbuf_for_ldap_class (lcl ? lcl->kind : GDA_LDAP_CLASS_KIND_UNKNOWN);
695 					av = gda_value_new (G_TYPE_OBJECT);
696 					g_value_set_object (av, pixbuf);
697 					gda_tree_node_set_node_attribute (snode, "icon", av, NULL);
698 					gda_value_free (av);
699 
700 					g_value_set_uint ((av = gda_value_new (G_TYPE_UINT)), fav->type);
701                                                 gda_tree_node_set_node_attribute (snode,
702                                                                                   MGR_FAVORITES_TYPE_ATT_NAME,
703                                                                                   av, NULL);
704                                         gda_value_free (av);
705 				}
706 
707 				GString *tmpstring;
708 				gchar *tmp;
709 
710 				tmpstring = g_string_new ("");
711 				tmp = g_markup_escape_text (fav->name, -1);
712 				g_string_append (tmpstring, tmp);
713 				g_free (tmp);
714 
715 				if (fav->descr && *fav->descr) {
716 					gchar *tmp;
717 					tmp = g_markup_escape_text (fav->descr, -1);
718 					g_string_append_printf (tmpstring,
719 								"\n<small>%s</small>", tmp);
720 					g_free (tmp);
721 
722 					g_value_set_string ((av = gda_value_new (G_TYPE_STRING)),
723 							    fav->descr);
724 					gda_tree_node_set_node_attribute (snode, "descr", av, NULL);
725 					gda_value_free (av);
726 				}
727 
728 				g_value_take_string ((av = gda_value_new (G_TYPE_STRING)),
729 						     g_string_free (tmpstring, FALSE));
730 				gda_tree_node_set_node_attribute (snode, "markup", av, NULL);
731 				gda_value_free (av);
732 
733 				g_value_set_string ((av = gda_value_new (G_TYPE_STRING)),
734 						    fav->name);
735 				gda_tree_node_set_node_attribute (snode,
736 								  MGR_FAVORITES_CONTENTS_ATT_NAME,
737 								  av, NULL);
738 				gda_value_free (av);
739 			}
740 #endif
741 			else {
742 				TO_IMPLEMENT;
743 			}
744 			if (snode)
745 				nodes_list = g_slist_prepend (nodes_list, snode);
746 		}
747 		gda_tools_favorites_free_list (fav_list);
748 	}
749 	else if (lerror) {
750 		if (out_error)
751 			*out_error = TRUE;
752 		g_propagate_error (error, lerror);
753 
754 		GdaTreeNode* snode = NULL;
755 		gchar *str;
756 		GValue *value;
757 
758 		str = g_strdup_printf ("<i>%s</i>", _("Getting\nfavorites..."));
759 		snode = gda_tree_manager_create_node (manager, node, str);
760 		g_value_take_string ((value = gda_value_new (G_TYPE_STRING)), str);
761 		gda_tree_node_set_node_attribute (snode, "markup", value, NULL);
762 		nodes_list = g_slist_prepend (nodes_list, snode);
763 	}
764 	else {
765 		GdaTreeNode* snode = NULL;
766 		gchar *str;
767 		GValue *value;
768 
769 		if (mgr->priv->fav_type & GDA_TOOLS_FAVORITES_TABLES) {
770 			str = g_strdup_printf ("<i>%s</i>", _("No favorite:\ndrag item to\ndefine one"));
771 			snode = gda_tree_manager_create_node (manager, node, str);
772 			g_value_take_string ((value = gda_value_new (G_TYPE_STRING)), str);
773 			gda_tree_node_set_node_attribute (snode, "markup", value, NULL);
774 			nodes_list = g_slist_prepend (nodes_list, snode);
775 		}
776 	}
777 
778 	if (ehash)
779 		g_hash_table_destroy (ehash);
780 
781 	return g_slist_reverse (nodes_list);
782 }
783 
784 static void
icon_fetched_cb(G_GNUC_UNUSED BrowserConnection * bcnc,GdkPixbuf * pixbuf,GdaTreeNode * node,G_GNUC_UNUSED GError * error)785 icon_fetched_cb (G_GNUC_UNUSED BrowserConnection *bcnc,
786 		 GdkPixbuf *pixbuf, GdaTreeNode *node, G_GNUC_UNUSED GError *error)
787 {
788 	if (pixbuf) {
789 		GValue *av;
790 		av = gda_value_new (G_TYPE_OBJECT);
791 		g_value_set_object (av, pixbuf);
792 		gda_tree_node_set_node_attribute (node, "icon", av, NULL);
793 		gda_value_free (av);
794 	}
795 	g_object_unref (node);
796 }
797 
798 #ifdef HAVE_LDAP
799 static gboolean
icons_resol_cb(MgrFavorites * mgr)800 icons_resol_cb (MgrFavorites *mgr)
801 {
802         if (mgr->priv->icons_resol_timer == 0)
803                 return FALSE;
804         if (mgr->priv->icons_resol_list) {
805                 IconResolutionData *data;
806                 data = (IconResolutionData*) mgr->priv->icons_resol_list->data;
807                 mgr->priv->icons_resol_list = g_slist_delete_link (mgr->priv->icons_resol_list,
808                                                                    mgr->priv->icons_resol_list);
809 
810 		if (browser_connection_ldap_icon_for_dn (mgr->priv->bcnc, data->dn,
811 							 (BrowserConnectionJobCallback) icon_fetched_cb,
812 							 g_object_ref (data->node), NULL) == 0)
813 			g_object_unref (data->node);
814                 icon_resolution_data_free (data);
815         }
816 
817         if (! mgr->priv->icons_resol_list) {
818                 mgr->priv->icons_resol_timer = 0;
819                 return FALSE;
820         }
821         else
822                 return TRUE;
823 }
824 #endif
825