1 /*
2  * Copyright (C) 2011 Murray Cumming <murrayc@murrayc.com>
3  * Copyright (C) 2011 - 2012 Vivien Malerba <malerba@gnome-db.org>
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 <gtk/gtk.h>
23 #include <libgda/gda-tree.h>
24 #include "ldap-favorite-selector.h"
25 #include "../mgr-favorites.h"
26 #include <libgda-ui/gdaui-tree-store.h>
27 #include "../dnd.h"
28 #include "../support.h"
29 #include "marshal.h"
30 #include "../gdaui-bar.h"
31 #include <gdk/gdkkeysyms.h>
32 #include <libgda-ui/internal/popup-container.h>
33 
34 struct _LdapFavoriteSelectorPrivate {
35 	BrowserConnection *bcnc;
36 	GdaTree *tree;
37 	GtkWidget *treeview;
38 	guint idle_update_favorites;
39 
40 	GtkWidget *popup_menu;
41 	GtkWidget *popup_properties;
42 	GtkWidget *properties_name;
43 	GtkWidget *properties_descr;
44 	gint       properties_id;
45 	gint       properties_position;
46 	guint      prop_save_timeout;
47 };
48 
49 static void ldap_favorite_selector_class_init (LdapFavoriteSelectorClass *klass);
50 static void ldap_favorite_selector_init       (LdapFavoriteSelector *fsel,
51 					       LdapFavoriteSelectorClass *klass);
52 static void ldap_favorite_selector_dispose   (GObject *object);
53 
54 static void favorites_changed_cb (ToolsFavorites *bfav, LdapFavoriteSelector *fsel);
create_stream_set(void)55 
56 enum {
57 	SELECTION_CHANGED,
58 	LAST_SIGNAL
59 };
60 
61 static guint ldap_favorite_selector_signals[LAST_SIGNAL] = { 0 };
62 static GObjectClass *parent_class = NULL;
63 
64 /* columns of the resulting GtkTreeModel */
65 enum {
oi_info(char * format,...)66 	COLUMN_ID = 0,
67 	COLUMN_NAME = 1,
68 	COLUMN_ICON = 2,
69 	COLUMN_MARKUP = 3,
70 	COLUMN_POSITION = 4,
71 	COLUMN_DESCR = 5,
72 	COLUMN_FAVTYPE = 6,
73 	COLUMN_LAST
74 };
75 
76 
77 /*
oi_warn(char * format,...)78  * LdapFavoriteSelector class implementation
79  */
80 
81 static void
82 ldap_favorite_selector_class_init (LdapFavoriteSelectorClass *klass)
83 {
84 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
85 
86 	parent_class = g_type_class_peek_parent (klass);
87 
88 	/* signals */
89 	ldap_favorite_selector_signals [SELECTION_CHANGED] =
90                 g_signal_new ("selection-changed",
91                               G_TYPE_FROM_CLASS (object_class),
92                               G_SIGNAL_RUN_FIRST,
93                               G_STRUCT_OFFSET (LdapFavoriteSelectorClass, selection_changed),
94                               NULL, NULL,
95                               _ldap_marshal_VOID__INT_ENUM_STRING, G_TYPE_NONE,
96                               3, G_TYPE_INT, G_TYPE_UINT, G_TYPE_STRING);
97 	klass->selection_changed = NULL;
98 
99 	object_class->dispose = ldap_favorite_selector_dispose;
100 }
101 
102 
103 static void
104 ldap_favorite_selector_init (LdapFavoriteSelector *fsel, G_GNUC_UNUSED LdapFavoriteSelectorClass *klass)
check_xiph_comment(stream_processor * stream,int i,const char * comment,int comment_length)105 {
106 	fsel->priv = g_new0 (LdapFavoriteSelectorPrivate, 1);
107 	fsel->priv->idle_update_favorites = 0;
108 	fsel->priv->prop_save_timeout = 0;
109 
110 	gtk_orientable_set_orientation (GTK_ORIENTABLE (fsel), GTK_ORIENTATION_VERTICAL);
111 }
112 
113 static void
114 ldap_favorite_selector_dispose (GObject *object)
115 {
116 	LdapFavoriteSelector *fsel = (LdapFavoriteSelector *) object;
117 
118 	/* free memory */
119 	if (fsel->priv) {
120 		if (fsel->priv->idle_update_favorites != 0)
121 			g_source_remove (fsel->priv->idle_update_favorites);
122 		if (fsel->priv->prop_save_timeout)
123 			g_source_remove (fsel->priv->prop_save_timeout);
124 
125 		if (fsel->priv->tree)
126 			g_object_unref (fsel->priv->tree);
127 
128 		if (fsel->priv->bcnc) {
129 			g_signal_handlers_disconnect_by_func (browser_connection_get_favorites (fsel->priv->bcnc),
130 							      G_CALLBACK (favorites_changed_cb), fsel);
131 			g_object_unref (fsel->priv->bcnc);
132 		}
133 
134 		if (fsel->priv->popup_properties)
135 			gtk_widget_destroy (fsel->priv->popup_properties);
136 		if (fsel->priv->popup_menu)
137 			gtk_widget_destroy (fsel->priv->popup_menu);
138 
139 		g_free (fsel->priv);
140 		fsel->priv = NULL;
141 	}
142 
143 	parent_class->dispose (object);
144 }
145 
146 GType
147 ldap_favorite_selector_get_type (void)
148 {
149 	static GType type = 0;
150 
151 	if (G_UNLIKELY (type == 0)) {
152 		static const GTypeInfo info = {
153 			sizeof (LdapFavoriteSelectorClass),
154 			(GBaseInitFunc) NULL,
155 			(GBaseFinalizeFunc) NULL,
156 			(GClassInitFunc) ldap_favorite_selector_class_init,
157 			NULL,
158 			NULL,
159 			sizeof (LdapFavoriteSelector),
160 			0,
161 			(GInstanceInitFunc) ldap_favorite_selector_init,
162 			0
163 		};
164 		type = g_type_register_static (GTK_TYPE_BOX, "LdapFavoriteSelector",
165 					       &info, 0);
166 	}
167 	return type;
168 }
169 
170 static void
171 favorite_delete_selected (LdapFavoriteSelector *fsel)
172 {
173 	GtkTreeModel *model;
174 	GtkTreeSelection *select;
175 	GtkTreeIter iter;
176 
177 	select = gtk_tree_view_get_selection (GTK_TREE_VIEW (fsel->priv->treeview));
178 	if (gtk_tree_selection_get_selected (select, &model, &iter)) {
179 		ToolsFavorites *bfav;
180 		ToolsFavoritesAttributes fav;
181 		GError *lerror = NULL;
182 
183 		memset (&fav, 0, sizeof (ToolsFavoritesAttributes));
184 		gtk_tree_model_get (model, &iter,
185 				    COLUMN_ID, &(fav.id), -1);
186 		bfav = browser_connection_get_favorites (fsel->priv->bcnc);
187 		if (!gda_tools_favorites_delete (bfav, 0, &fav, NULL)) {
188 			browser_show_error ((GtkWindow*) gtk_widget_get_toplevel ((GtkWidget*)fsel),
189 					    _("Could not remove favorite: %s"),
190 					    lerror && lerror->message ? lerror->message : _("No detail"));
191 			if (lerror)
192 				g_error_free (lerror);
193 		}
194 	}
195 }
196 
197 static gboolean
198 key_press_event_cb (G_GNUC_UNUSED GtkTreeView *treeview, GdkEventKey *event, LdapFavoriteSelector *fsel)
199 {
200 	if (event->keyval == GDK_KEY_Delete) {
201 		favorite_delete_selected (fsel);
202 		return TRUE;
203 	}
204 	return FALSE; /* not handled */
205 }
206 
207 
208 static void
209 selection_changed_cb (GtkTreeView *treeview, G_GNUC_UNUSED GtkTreePath *path,
210 		      G_GNUC_UNUSED GtkTreeViewColumn *column, LdapFavoriteSelector *fsel)
211 {
212 	GtkTreeModel *model;
213 	GtkTreeSelection *select;
214 	GtkTreeIter iter;
215 
216 	select = gtk_tree_view_get_selection (treeview);
217 	if (gtk_tree_selection_get_selected (select, &model, &iter)) {
218 		gchar *str;
219 		gint fav_id;
220 		ToolsFavoritesType fav_type;
221 		gtk_tree_model_get (model, &iter,
222 				    COLUMN_ID, &fav_id,
223 				    COLUMN_FAVTYPE, &fav_type,
224 				    COLUMN_NAME, &str, -1);
225 		g_signal_emit (fsel, ldap_favorite_selector_signals [SELECTION_CHANGED], 0, fav_id,
226 			       fav_type, str);
227 		g_free (str);
228 	}
229 }
230 
231 static gboolean
232 prop_save_timeout (LdapFavoriteSelector *fsel)
233 {
234 	ToolsFavorites *bfav;
235 	ToolsFavoritesAttributes fav;
236 	GError *error = NULL;
237 	gboolean allok;
238 
239 	bfav = browser_connection_get_favorites (fsel->priv->bcnc);
240 
241 	memset (&fav, 0, sizeof (ToolsFavoritesAttributes));
242 	fav.id = fsel->priv->properties_id;
243 	fav.type = GDA_TOOLS_FAVORITES_LDAP_DN;
244 	fav.name = (gchar*) gtk_entry_get_text (GTK_ENTRY (fsel->priv->properties_name));
245 	fav.descr = (gchar*) gtk_entry_get_text (GTK_ENTRY (fsel->priv->properties_descr));
246 	fav.contents = (gchar*) gtk_entry_get_text (GTK_ENTRY (fsel->priv->properties_name));
247 
248 	allok = gda_tools_favorites_add (bfav, 0, &fav, ORDER_KEY_LDAP,
249 				       fsel->priv->properties_position, &error);
250 	if (! allok) {
251 		browser_show_error ((GtkWindow*) gtk_widget_get_toplevel ((GtkWidget*) fsel),
252 				    _("Could not add favorite: %s"),
253 				    error && error->message ? error->message : _("No detail"));
254 		if (error)
255 			g_error_free (error);
256 	}
257 
258 	fsel->priv->prop_save_timeout = 0;
259 	return FALSE; /* remove timeout */
260 }
261 
262 static void
263 property_changed_cb (G_GNUC_UNUSED GtkWidget *multiple, LdapFavoriteSelector *fsel)
264 {
265 	if (fsel->priv->prop_save_timeout)
266 		g_source_remove (fsel->priv->prop_save_timeout);
267 	fsel->priv->prop_save_timeout = g_timeout_add (200, (GSourceFunc) prop_save_timeout, fsel);
268 }
269 
270 static void
271 properties_activated_cb (GtkMenuItem *mitem, LdapFavoriteSelector *fsel)
272 {
273 	if (! fsel->priv->popup_properties) {
274 		GtkWidget *pcont, *vbox, *hbox, *label, *entry, *grid;
275 		gchar *str;
276 		gfloat align;
277 
278 		pcont = popup_container_new (GTK_WIDGET (mitem));
279 		vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
280 		gtk_container_add (GTK_CONTAINER (pcont), vbox);
281 
282 		label = gtk_label_new ("");
283 		str = g_strdup_printf ("<b>%s:</b>", _("Favorite's properties"));
284 		gtk_label_set_markup (GTK_LABEL (label), str);
285 		g_free (str);
286 		gtk_misc_get_alignment (GTK_MISC (label), NULL, &align);
287 		gtk_misc_set_alignment (GTK_MISC (label), 0., align);
288 		gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
289 
290 		hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); /* HIG */
291 		gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 5);
292 		label = gtk_label_new ("      ");
293 		gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
294 
295 		grid = gtk_grid_new ();
296 		gtk_box_pack_start (GTK_BOX (hbox), grid, TRUE, TRUE, 0);
297 
298 		label = gtk_label_new ("");
299 		str = g_strdup_printf ("<b>%s:</b>", _("Name"));
300 		gtk_label_set_markup (GTK_LABEL (label), str);
301 		g_free (str);
302 		gtk_misc_get_alignment (GTK_MISC (label), NULL, &align);
303 		gtk_misc_set_alignment (GTK_MISC (label), 0., align);
304 		gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
305 
306 		label = gtk_label_new ("");
307 		str = g_strdup_printf ("<b>%s:</b>", _("Description"));
308 		gtk_label_set_markup (GTK_LABEL (label), str);
309 		g_free (str);
310 		gtk_misc_set_alignment (GTK_MISC (label), 0., 0.);
311 		gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
312 
313 		entry = gtk_entry_new ();
314 		gtk_editable_set_editable (GTK_EDITABLE (entry), FALSE);
315 		gtk_grid_attach (GTK_GRID (grid), entry, 1, 0, 1, 1);
316 		fsel->priv->properties_name = entry;
317 
318 		entry = gtk_entry_new ();
319 		gtk_widget_set_size_request (entry, 200, -1);
320 		gtk_grid_attach (GTK_GRID (grid), entry, 1, 1, 1, 1);
321 		fsel->priv->properties_descr = entry;
322 		g_signal_connect (entry, "changed",
323 				  G_CALLBACK (property_changed_cb), fsel);
324 
325 		fsel->priv->popup_properties = pcont;
326 		gtk_widget_show_all (vbox);
327 	}
328 
329 	/* adjust contents */
330 	GtkTreeSelection *selection;
331 	GtkTreeModel *model;
332 	GtkTreeIter iter;
333 	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (fsel->priv->treeview));
334 	if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
335 		gchar *name, *descr;
336 
337 		gtk_tree_model_get (model, &iter,
338 				    COLUMN_ID, &(fsel->priv->properties_id),
339 				    COLUMN_POSITION, &(fsel->priv->properties_position),
340 				    COLUMN_NAME, &name,
341 				    COLUMN_DESCR, &descr, -1);
342 
343 		if (name) {
344 			gtk_entry_set_text (GTK_ENTRY (fsel->priv->properties_name), name);
345 			g_free (name);
346 		}
347 
348 		g_signal_handlers_block_by_func (fsel->priv->properties_descr,
349 						 G_CALLBACK (property_changed_cb), fsel);
350 		gtk_entry_set_text (GTK_ENTRY (fsel->priv->properties_descr), descr ? descr : "");
351 		g_signal_handlers_unblock_by_func (fsel->priv->properties_descr,
352 						   G_CALLBACK (property_changed_cb), fsel);
353 		g_free (descr);
354 
355 		gtk_widget_show (fsel->priv->popup_properties);
356 	}
357 }
358 
359 static void
360 delete_activated_cb (G_GNUC_UNUSED GtkMenuItem *mitem, LdapFavoriteSelector *fsel)
361 {
362 	favorite_delete_selected (fsel);
363 }
364 
365 static void
366 do_popup_menu (G_GNUC_UNUSED GtkWidget *widget, GdkEventButton *event, LdapFavoriteSelector *fsel)
367 {
368 	int button, event_time;
369 
370 	if (! fsel->priv->popup_menu) {
371 		GtkWidget *menu, *mitem;
372 
373 		menu = gtk_menu_new ();
374 		g_signal_connect (menu, "deactivate",
375 				  G_CALLBACK (gtk_widget_hide), NULL);
376 
377 		mitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_PROPERTIES, NULL);
378 		gtk_menu_shell_append (GTK_MENU_SHELL (menu), mitem);
379 		gtk_widget_show (mitem);
380 		g_signal_connect (mitem, "activate",
381 				  G_CALLBACK (properties_activated_cb), fsel);
382 
383 		mitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_DELETE, NULL);
384 		gtk_menu_shell_append (GTK_MENU_SHELL (menu), mitem);
385 		gtk_widget_show (mitem);
386 		g_signal_connect (mitem, "activate",
387 				  G_CALLBACK (delete_activated_cb), fsel);
388 
389 		fsel->priv->popup_menu = menu;
390 	}
391 
392 	if (event) {
393 		button = event->button;
394 		event_time = event->time;
395 	}
396 	else {
397 		button = 0;
398 		event_time = gtk_get_current_event_time ();
399 	}
400 
401 	gtk_menu_popup (GTK_MENU (fsel->priv->popup_menu), NULL, NULL, NULL, NULL,
402 			button, event_time);
403 }
404 
405 
406 static gboolean
407 popup_menu_cb (GtkWidget *widget, LdapFavoriteSelector *fsel)
408 {
409 	do_popup_menu (widget, NULL, fsel);
410 	return TRUE;
411 }
412 
413 static gboolean
414 button_press_event_cb (GtkTreeView *treeview, GdkEventButton *event, LdapFavoriteSelector *fsel)
415 {
416 	if (event->button == 3 && event->type == GDK_BUTTON_PRESS) {
417 		do_popup_menu ((GtkWidget*) treeview, event, fsel);
418 		return TRUE;
419 	}
420 
421 	return FALSE;
422 }
423 
424 static gboolean idle_update_favorites (LdapFavoriteSelector *fsel);
425 static gboolean tree_store_drag_drop_cb (GdauiTreeStore *store, const gchar *path,
426 					 GtkSelectionData *selection_ldap, LdapFavoriteSelector *fsel);
427 static gboolean tree_store_drag_can_drag_cb (GdauiTreeStore *store, const gchar *path,
428 					     LdapFavoriteSelector *fsel);
429 static gboolean tree_store_drag_get_cb (GdauiTreeStore *store, const gchar *path,
430 					GtkSelectionData *selection_ldap, LdapFavoriteSelector *fsel);
431 
432 /**
433  * ldap_favorite_selector_new
434  *
435  * Returns: a new #GtkWidget
436  */
437 GtkWidget *
438 ldap_favorite_selector_new (BrowserConnection *bcnc)
439 {
440 	LdapFavoriteSelector *fsel;
441 	GdaTreeManager *manager;
442 	gchar *signame;
443 
444 	g_return_val_if_fail (BROWSER_IS_CONNECTION (bcnc), NULL);
445 	fsel = LDAP_FAVORITE_SELECTOR (g_object_new (LDAP_FAVORITE_SELECTOR_TYPE, NULL));
446 
447 	fsel->priv->bcnc = g_object_ref (bcnc);
448 	signame = g_strdup_printf ("favorites-changed::%s",
449 				   gda_tools_favorites_type_to_string (GDA_TOOLS_FAVORITES_LDAP_DN));
450 	g_signal_connect (browser_connection_get_favorites (fsel->priv->bcnc), signame,
451 			  G_CALLBACK (favorites_changed_cb), fsel);
452 	g_free (signame);
453 	signame = g_strdup_printf ("favorites-changed::%s",
454 				   gda_tools_favorites_type_to_string (GDA_TOOLS_FAVORITES_LDAP_CLASS));
455 	g_signal_connect (browser_connection_get_favorites (fsel->priv->bcnc), signame,
456 			  G_CALLBACK (favorites_changed_cb), fsel);
457 	g_free (signame);
458 
459 	/* create tree managers */
460 	fsel->priv->tree = gda_tree_new ();
461 	manager = mgr_favorites_new (bcnc, GDA_TOOLS_FAVORITES_LDAP_DN, ORDER_KEY_LDAP);
462         gda_tree_add_manager (fsel->priv->tree, manager);
463 	g_object_unref (manager);
464 	manager = mgr_favorites_new (bcnc, GDA_TOOLS_FAVORITES_LDAP_CLASS, ORDER_KEY_LDAP);
465         gda_tree_add_manager (fsel->priv->tree, manager);
466 	g_object_unref (manager);
467 
468 	/* update the tree's contents */
469 	if (! gda_tree_update_all (fsel->priv->tree, NULL)) {
470 		if (fsel->priv->idle_update_favorites == 0)
471 			fsel->priv->idle_update_favorites = g_idle_add ((GSourceFunc) idle_update_favorites, fsel);
472 	}
473 
474 	/* header */
475 	GtkWidget *label;
476 	gchar *str;
477 	str = g_strdup_printf ("<b>%s</b>", _("Favorites"));
478 	label = gdaui_bar_new (str);
479 	g_free (str);
480 	gdaui_bar_set_icon_from_pixbuf (GDAUI_BAR (label), browser_get_pixbuf_icon (BROWSER_ICON_BOOKMARK));
481         gtk_box_pack_start (GTK_BOX (fsel), label, FALSE, FALSE, 0);
482         gtk_widget_show (label);
483 
484 	/* tree model & tree view */
485 	GtkTreeModel *model;
486 	GtkWidget *treeview;
487 	GtkCellRenderer *renderer;
488 	GtkTreeViewColumn *column;
489 
490 	model = gdaui_tree_store_new (fsel->priv->tree, COLUMN_LAST,
491 				      G_TYPE_INT, MGR_FAVORITES_ID_ATT_NAME,
492 				      G_TYPE_STRING, MGR_FAVORITES_CONTENTS_ATT_NAME,
493 				      G_TYPE_OBJECT, "icon",
494 				      G_TYPE_STRING, "markup",
495 				      G_TYPE_INT, MGR_FAVORITES_ID_ATT_NAME,
496 				      G_TYPE_STRING, "descr",
497 				      G_TYPE_UINT, MGR_FAVORITES_TYPE_ATT_NAME);
498 
499 	treeview = browser_make_tree_view (model);
500 	fsel->priv->treeview = treeview;
501 	g_object_unref (model);
502 
503 	g_signal_connect (G_OBJECT (treeview), "row-activated",
504 			  G_CALLBACK (selection_changed_cb), fsel);
505 	g_signal_connect (G_OBJECT (treeview), "key-press-event",
506 			  G_CALLBACK (key_press_event_cb), fsel);
507 	g_signal_connect (G_OBJECT (treeview), "popup-menu",
508 			  G_CALLBACK (popup_menu_cb), fsel);
509 	g_signal_connect (G_OBJECT (treeview), "button-press-event",
510 			  G_CALLBACK (button_press_event_cb), fsel);
511 
512 	/* icon */
513 	column = gtk_tree_view_column_new ();
514 
515 	renderer = gtk_cell_renderer_pixbuf_new ();
516 	gtk_tree_view_column_pack_start (column, renderer, FALSE);
517 	gtk_tree_view_column_add_attribute (column, renderer, "pixbuf", COLUMN_ICON);
518 	g_object_set ((GObject*) renderer, "yalign", 0., NULL);
519 
520 	/* text */
521 	renderer = gtk_cell_renderer_text_new ();
522 	gtk_tree_view_column_pack_start (column, renderer, TRUE);
523 	gtk_tree_view_column_add_attribute (column, renderer, "markup", COLUMN_MARKUP);
524 	gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
525 	gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
526 
527 	/* scrolled window packing */
528 	GtkWidget *sw;
529 	sw = gtk_scrolled_window_new (NULL, NULL);
530 	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
531 					     GTK_SHADOW_ETCHED_IN);
532 	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
533 					GTK_POLICY_NEVER,
534 					GTK_POLICY_AUTOMATIC);
535 	gtk_container_add (GTK_CONTAINER (sw), treeview);
536 	gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
537 
538 	gtk_box_pack_start (GTK_BOX (fsel), sw, TRUE, TRUE, 0);
539 	gtk_widget_show_all (sw);
540 
541 	/* DnD */
542 	gtk_tree_view_enable_model_drag_dest (GTK_TREE_VIEW (treeview), dbo_table, G_N_ELEMENTS (dbo_table),
543 					      GDK_ACTION_COPY);
544 	gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (treeview), GDK_BUTTON1_MASK,
545 						dbo_table, G_N_ELEMENTS (dbo_table),
546 						GDK_ACTION_COPY | GDK_ACTION_MOVE);
547 	g_signal_connect (model, "drag-drop",
548 			  G_CALLBACK (tree_store_drag_drop_cb), fsel);
549 	g_signal_connect (model, "drag-can-drag",
550 			  G_CALLBACK (tree_store_drag_can_drag_cb), fsel);
551 	g_signal_connect (model, "drag-get",
552 			  G_CALLBACK (tree_store_drag_get_cb), fsel);
553 
554 	return (GtkWidget*) fsel;
555 }
556 
557 static gboolean
558 idle_update_favorites (LdapFavoriteSelector *fsel)
559 {
560 	gboolean done;
561 	g_print ("%s()\n", __FUNCTION__);
562 	done = gda_tree_update_all (fsel->priv->tree, NULL);
563 	if (done)
564 		fsel->priv->idle_update_favorites = 0;
565 	else
566 		fsel->priv->idle_update_favorites = g_timeout_add_seconds (1, (GSourceFunc) idle_update_favorites,
567 									   fsel);
568 	return FALSE;
569 }
570 
571 static gboolean
572 tree_store_drag_drop_cb (G_GNUC_UNUSED GdauiTreeStore *store, const gchar *path,
573 			 GtkSelectionData *selection_ldap, LdapFavoriteSelector *fsel)
574 {
575 	ToolsFavorites *bfav;
576 	ToolsFavoritesAttributes fav;
577 	GError *error = NULL;
578 	gint pos;
579 	gboolean retval = TRUE;
580 	gint id;
581 	bfav = browser_connection_get_favorites (fsel->priv->bcnc);
582 
583 	id = gda_tools_favorites_find (bfav, 0, (gchar*) gtk_selection_data_get_data (selection_ldap),
584 				     &fav, NULL);
585 	if (id < 0) {
586 		memset (&fav, 0, sizeof (ToolsFavoritesAttributes));
587 		fav.id = -1;
588 		fav.type = GDA_TOOLS_FAVORITES_LDAP_DN;
589 		fav.name = (gchar*) gtk_selection_data_get_data (selection_ldap);
590 		fav.descr = NULL;
591 		fav.contents = (gchar*) gtk_selection_data_get_data (selection_ldap);
592 	}
593 
594 	pos = atoi (path);
595 	/*g_print ("%s() path => %s, pos: %d\n", __FUNCTION__, path, pos);*/
596 
597 	if (! gda_tools_favorites_add (bfav, 0, &fav, ORDER_KEY_LDAP, pos, &error)) {
598 		browser_show_error ((GtkWindow*) gtk_widget_get_toplevel ((GtkWidget*) fsel),
599 				    _("Could not add favorite: %s"),
600 				    error && error->message ? error->message : _("No detail"));
601 		if (error)
602 			g_error_free (error);
603 		retval = FALSE;
604 	}
605 
606 	if (id >= 0)
607 		gda_tools_favorites_reset_attributes (&fav);
608 
609 	return retval;
610 }
process_null(stream_processor * stream,ogg_page * page)611 
612 static gboolean
613 tree_store_drag_can_drag_cb (G_GNUC_UNUSED GdauiTreeStore *store, const gchar *path,
614 			     LdapFavoriteSelector *fsel)
615 {
616 	GdaTreeNode *node;
617 	node = gda_tree_get_node (fsel->priv->tree, path, FALSE);
618 	if (node) {
619 		const GValue *cvalue;
620 		cvalue = gda_tree_node_get_node_attribute (node, "fav_contents");
621 		if (cvalue)
622 			return TRUE;
623 	}
624 	return FALSE;
625 }
626 
627 static gboolean
628 tree_store_drag_get_cb (G_GNUC_UNUSED GdauiTreeStore *store, const gchar *path,
629 			GtkSelectionData *selection_ldap, LdapFavoriteSelector *fsel)
free_stream_set(stream_set * set)630 {
631 	GdaTreeNode *node;
632 	node = gda_tree_get_node (fsel->priv->tree, path, FALSE);
633 	if (node) {
634 		const GValue *cvalue;
635 		cvalue = gda_tree_node_get_node_attribute (node, "fav_contents");
636 		if (cvalue) {
637 			const gchar *str;
638 			str = g_value_get_string (cvalue);
639 			gtk_selection_data_set (selection_ldap, gtk_selection_data_get_target (selection_ldap),
640 						8, (guchar*) str, strlen (str));
641 			return TRUE;
642 		}
643 	}
644 	return FALSE;
645 }
646 
streams_open(stream_set * set)647 static void
648 favorites_changed_cb (G_GNUC_UNUSED ToolsFavorites *bfav, LdapFavoriteSelector *fsel)
649 {
650 	if (! gda_tree_update_all (fsel->priv->tree, NULL)) {
651 		if (fsel->priv->idle_update_favorites == 0)
652 			fsel->priv->idle_update_favorites = g_idle_add ((GSourceFunc) idle_update_favorites, fsel);
653 
654 	}
655 }
656