/*
 *  Copyright (C) 2002  Ricardo Fernández Pascual
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <glib/gi18n.h>
#include "gul-glade.h"
#include "bookmarks-single-editor.h"
#include "gul-gobject-misc.h"
#include "gul-string.h"
#include "gul-state.h"
#include "eel-gconf-extensions.h"
#include "prefs-strings.h"
#include <gtk/gtktextbuffer.h>
#include <gtk/gtktextview.h>
#include <gtk/gtktogglebutton.h>
#include <gtk/gtkspinbutton.h>
#include <gtk/gtklabel.h>
#include <gtk/gtkcomboboxentry.h>
#include <libgnomeui/gnome-pixmap-entry.h>
#include "bookmarks-tree-view.h"

#include <gdk/gdkkeysyms.h>
#include <string.h>
#include <time.h>

/**
 * Private data
 */
struct _GbSingleEditorPrivate {
	GbBookmark *bm;

	gboolean widgets_and_signals_inited;
	guint no_update;

	GbSingleEditorDisablePolicy disable_policy;

	GtkWidget *window;
	GtkWidget *parents_scrolledwindow;
	GbTreeView *parents_treeview;
	GbTreeModel *parents_treemodel;
	GtkWidget *alias_label;
	GtkWidget *smart_entry_width_hbox;

	GtkWidget *close_button;
};

/**
 * Private functions, only availble from this file
 */
static void		gb_single_editor_class_init		(GbSingleEditorClass *klass);
static void		gb_single_editor_init			(GbSingleEditor *e);
static void		gb_single_editor_init_widgets_impl	(GbSingleEditor *e);
static void		gb_single_editor_bookmark_changed_cb	(GbBookmark *b, GbSingleEditor *e);
static void		gb_single_editor_finalize_impl		(GObject *o);
static void		gb_single_editor_update_controls	(GbSingleEditor *e);
static void		gb_single_editor_set_bookmark_internal	(GbSingleEditor *e, GbBookmark *b);


static void		gb_single_editor_name_entry_changed_cb	(GtkWidget *edited,
								 GbSingleEditor *e);
static void		gb_single_editor_smarturl_entry_changed_cb (GtkWidget *edited,
								    GbSingleEditor *e);
static void		gb_single_editor_smart_entry_width_spinbutton_value_changed_cb (GtkWidget *edited, 
											GbSingleEditor *e);
static void		gb_single_editor_location_entry_changed_cb (GtkWidget *edited,
								    GbSingleEditor *e);
static void		gb_single_editor_notes_text_buffer_changed_cb (GtkWidget *edited,
								       GbSingleEditor *e);
static void		gb_single_editor_nicks_entry_changed_cb	(GtkWidget *edited,
								 GbSingleEditor *e);
static void		gb_single_editor_create_toolbar_checkbox_toggled_cb (GtkWidget *edited,
									     GbSingleEditor *e);
static void		gb_single_editor_add_to_context_checkbox_toggled_cb (GtkWidget *edited,
									     GbSingleEditor *e);
static void 		gb_single_editor_image_pixmapentry_changed_cb (GtkWidget *edited,
								      GbSingleEditor *e);
static void		gb_single_editor_parameter_encoding_combo_changed_cb (GtkWidget *edited,
									      GbSingleEditor *e);


static gpointer g_object_class;

/**
 * SingleEditor object
 */

MAKE_GET_TYPE (gb_single_editor, "GbSingleEditor", GbSingleEditor, gb_single_editor_class_init, 
	       gb_single_editor_init, G_TYPE_OBJECT);

static void
gb_single_editor_class_init (GbSingleEditorClass *klass)
{
	G_OBJECT_CLASS (klass)->finalize = gb_single_editor_finalize_impl;
	klass->init_widgets = gb_single_editor_init_widgets_impl;

	g_object_class = g_type_class_peek_parent (klass);
}

static void 
gb_single_editor_init (GbSingleEditor *e)
{
	GbSingleEditorPrivate *p = g_new0 (GbSingleEditorPrivate, 1);
	e->priv = p;
	p->disable_policy = GB_SINGLE_EDITOR_DISABLE_POLICY_HIDE;
}

static void
gb_single_editor_finalize_impl (GObject *o)
{
	GbSingleEditor *e = GB_SINGLE_EDITOR (o);
	GbSingleEditorPrivate *p = e->priv;

	gb_single_editor_set_bookmark_internal (e, NULL);

	if (p->parents_treemodel)
	{
		g_object_unref (p->parents_treemodel);
	}
	
	g_free (p);
	
	G_OBJECT_CLASS (g_object_class)->finalize (o);

}

void
gb_single_editor_init_widgets (GbSingleEditor *e)
{
	GbSingleEditorClass *klass = GB_SINGLE_EDITOR_GET_CLASS (e);
	return klass->init_widgets (e);
}

static void
parents_treeview_bookmark_check_toggled (GbTreeView *tv, GbBookmark *b, GbSingleEditor *e)
{
	GbSingleEditorPrivate *p;
	gboolean current;

	g_return_if_fail (GB_IS_SINGLE_EDITOR (e));
	g_return_if_fail (GB_IS_FOLDER (b));
	p = e->priv;
	g_return_if_fail (GB_IS_BOOKMARK (p->bm));

	current = gb_folder_has_child_or_alias (GB_FOLDER (b), p->bm);
	if (current)
	{
		gb_folder_remove_child_or_aliases (GB_FOLDER (b), p->bm);
	}
	else
	{
		gb_bookmark_ensure_alias_under (p->bm, GB_FOLDER (b));
	}
}

static gboolean
gb_single_editor_close_on_ctrl_enter (GtkWidget *widget, GdkEventKey *event,
				      GbSingleEditor *e)
{
	if ((event->state & GDK_CONTROL_MASK) && 
	    ((event->keyval == GDK_Return) ||  (event->keyval == GDK_KP_Enter)))
	{
		gtk_widget_destroy (e->priv->window);
		return TRUE;
	}
	return FALSE;
}


static void
gb_single_editor_move_to_next (GtkWidget *widget, GbSingleEditor *e)
{
	gtk_widget_child_focus (e->priv->window, GTK_DIR_TAB_FORWARD);
}

static void
gb_single_editor_init_widgets_impl (GbSingleEditor *e)
{
	GbSingleEditorPrivate *p = e->priv;
	WidgetLookup lookups[] = {
		{ "bookmarks_properties_window", &p->window },
		{ "bookmarks_properties_name_label", &e->name_label },
		{ "bookmarks_properties_name_entry", &e->name_entry },
		{ "bookmarks_properties_smarturl_label", &e->smarturl_label },
		{ "bookmarks_properties_smarturl_entry", &e->smarturl_entry },
		{ "bookmarks_properties_date_added_label", &e->date_added_label },
		{ "bookmarks_properties_date_added_value_label", &e->date_added_value_label },
		{ "bookmarks_properties_date_modified_label", &e->date_modified_label },
		{ "bookmarks_properties_date_modified_value_label", &e->date_modified_value_label },
		{ "bookmarks_properties_date_visited_label", &e->date_visited_label },
		{ "bookmarks_properties_date_visited_value_label", &e->date_visited_value_label },
		{ "bookmarks_properties_smart_entry_width_label", &e->smart_entry_width_label },
		{ "bookmarks_properties_smart_entry_width_spinbutton", &e->smart_entry_width_spinbutton },
		{ "bookmarks_properties_smart_entry_width_hbox", &p->smart_entry_width_hbox },
		{ "bookmarks_properties_parameter_encoding_label", &e->parameter_encoding_label },
		{ "bookmarks_properties_parameter_encoding_combo", &e->parameter_encoding_combo },
		{ "bookmarks_properties_location_label", &e->location_label },
		{ "bookmarks_properties_location_entry", &e->location_entry },
		{ "bookmarks_properties_notes_textview", &e->notes_textview },
		{ "bookmarks_properties_nicks_label", &e->nicks_label },
		{ "bookmarks_properties_nicks_entry", &e->nicks_entry },
		{ "bookmarks_properties_create_toolbar_checkbox", &e->create_toolbar_checkbox },
		{ "bookmarks_properties_add_to_context_checkbox", &e->add_to_context_checkbox },
		{ "bookmarks_properties_image_label", &e->image_label },
		{ "bookmarks_properties_image_pixmapentry", &e->image_pixmapentry },
		{ "bookmarks_properties_parents_scrolledwindow", &p->parents_scrolledwindow },
		{ "bookmarks_properties_alias_label", &p->alias_label },
		{ "bookmarks_properties_close_button", &p->close_button },
		{ NULL, NULL }
	};
	GladeXML *gxml = gul_glade_widget_new ("bookmarks-editor.glade", "bookmarks_properties_window",
					       NULL, e);
	gul_glade_lookup_widgets (gxml, lookups);
	g_object_unref (gxml);
	
	g_object_weak_ref (G_OBJECT (p->window), (GWeakNotify) g_object_unref, e);
	gul_state_monitor_window (p->window, "Bookmark Properties", 370, 390);

	p->parents_treeview = gb_tree_view_new ();
	gb_tree_view_set_check_visible (p->parents_treeview, TRUE);
	gb_tree_view_set_location_visible (p->parents_treeview, FALSE);
	gb_tree_view_set_double_click_action (p->parents_treeview, GB_TV_NONE);
	g_signal_connect (p->parents_treeview, "bookmark-check-toggled",
			  G_CALLBACK (parents_treeview_bookmark_check_toggled), e);
	gtk_widget_show (GTK_WIDGET (p->parents_treeview));
	gtk_container_add (GTK_CONTAINER (p->parents_scrolledwindow), GTK_WIDGET (p->parents_treeview));
	gtk_label_set_mnemonic_widget (GTK_LABEL (p->alias_label), GTK_WIDGET (p->parents_treeview));

	/* Hook up the close button */
	g_signal_connect_swapped (p->close_button, "clicked",
				  G_CALLBACK (gtk_widget_destroy), e->priv->window);

	/* Setup CTRL+Enter to close the window */
	g_signal_connect (e->name_entry, "key-press-event",
			  G_CALLBACK (gb_single_editor_close_on_ctrl_enter), e);
	g_signal_connect (e->smarturl_entry, "key-press-event",
			  G_CALLBACK (gb_single_editor_close_on_ctrl_enter), e);
	g_signal_connect (e->location_entry, "key-press-event",
			  G_CALLBACK (gb_single_editor_close_on_ctrl_enter), e);
	g_signal_connect (e->nicks_entry, "key-press-event",
			  G_CALLBACK (gb_single_editor_close_on_ctrl_enter), e);
	g_signal_connect (p->parents_treeview, "key-press-event",
			  G_CALLBACK (gb_single_editor_close_on_ctrl_enter), e);
	g_signal_connect (e->smart_entry_width_spinbutton, "key-press-event",
			  G_CALLBACK (gb_single_editor_close_on_ctrl_enter), e);
	g_signal_connect (e->notes_textview, "key-press-event",
			  G_CALLBACK (gb_single_editor_close_on_ctrl_enter), e);
	g_signal_connect (GTK_BIN (e->parameter_encoding_combo)->child, "key-press-event",
			  G_CALLBACK (gb_single_editor_close_on_ctrl_enter), e);

	/* Setup Enter to move to the next widget */
	g_signal_connect (GTK_ENTRY (e->name_entry), "activate", 
			  G_CALLBACK (gb_single_editor_move_to_next), e);
	g_signal_connect (GTK_ENTRY (e->nicks_entry), "activate", 
			  G_CALLBACK (gb_single_editor_move_to_next), e);
	g_signal_connect (GTK_ENTRY (e->smarturl_entry), "activate", 
			  G_CALLBACK (gb_single_editor_move_to_next), e);
	g_signal_connect (GTK_ENTRY (e->location_entry), "activate", 
			  G_CALLBACK (gb_single_editor_move_to_next), e);
	g_signal_connect (GTK_ENTRY (GTK_BIN (e->parameter_encoding_combo)->child), "activate", 
			  G_CALLBACK (gb_single_editor_move_to_next), e);
}

void 
gb_single_editor_init_widgets_and_signals (GbSingleEditor *e)
{
	GbSingleEditorPrivate *p = e->priv;

	if (p->widgets_and_signals_inited)
	{
		return;
	}
	
	p->widgets_and_signals_inited = TRUE;
	
	gb_single_editor_init_widgets (e);

	if (e->notes_textview)
	{
		GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (e->notes_textview));
		g_signal_connect (buffer, "changed",
				  G_CALLBACK (gb_single_editor_notes_text_buffer_changed_cb), e);
	}
	
	if (e->name_entry)
	{
		g_signal_connect (e->name_entry, "changed",
				  G_CALLBACK (gb_single_editor_name_entry_changed_cb), e);
	}

	if (e->smarturl_entry)
	{
		g_signal_connect (e->smarturl_entry, "changed",
				  G_CALLBACK (gb_single_editor_smarturl_entry_changed_cb), e);
	}
	
	if (e->smart_entry_width_spinbutton)
	{
		g_signal_connect (e->smart_entry_width_spinbutton, "value-changed",
				  G_CALLBACK (gb_single_editor_smart_entry_width_spinbutton_value_changed_cb), e);
	}

	if (e->location_entry)
	{
		g_signal_connect (e->location_entry, "changed",
				  G_CALLBACK (gb_single_editor_location_entry_changed_cb), e);
	}
	
	if (e->nicks_entry)
	{
		g_signal_connect (e->nicks_entry, "changed", 
				  G_CALLBACK (gb_single_editor_nicks_entry_changed_cb), e);
	}
	
	if (e->create_toolbar_checkbox)
	{
		g_signal_connect (e->create_toolbar_checkbox, "toggled",
				  G_CALLBACK (gb_single_editor_create_toolbar_checkbox_toggled_cb), e);
	}
	
	if (e->add_to_context_checkbox)
	{
		g_signal_connect (e->add_to_context_checkbox, "toggled",
				  G_CALLBACK (gb_single_editor_add_to_context_checkbox_toggled_cb), e);
	}
	
	if (e->image_pixmapentry)
	{
		g_signal_connect (e->image_pixmapentry, "changed",
				  G_CALLBACK (gb_single_editor_image_pixmapentry_changed_cb), e);
		gtk_label_set_mnemonic_widget (GTK_LABEL (e->image_label), e->image_pixmapentry);
	}
	
	if (GTK_COMBO_BOX_ENTRY (e->parameter_encoding_combo))
	{
		g_signal_connect (GTK_BIN (e->parameter_encoding_combo)->child, "changed",
				  G_CALLBACK (gb_single_editor_parameter_encoding_combo_changed_cb), e);
	}
}

GbSingleEditor *
gb_single_editor_new (void)
{
	GbSingleEditor *ret = g_object_new (GB_TYPE_SINGLE_EDITOR, NULL);
	return ret;
}

void
gb_single_editor_show (GbSingleEditor *editor)
{
	gb_single_editor_init_widgets_and_signals (editor);
	gtk_widget_show (GTK_WIDGET (editor->priv->window));
}

GbBookmark *
gb_single_editor_get_bookmark (GbSingleEditor *e)
{
	return e->priv->bm;
}

static void
gb_single_editor_set_bookmark_internal (GbSingleEditor *e, GbBookmark *b)
{
	if (e->priv->bm)
	{
		g_signal_handlers_disconnect_matched (e->priv->bm, G_SIGNAL_MATCH_DATA, 0, 0, 
						      NULL, NULL, e);
		g_object_unref (e->priv->bm);
	}

	e->priv->bm = b;

	if (b)
	{
		g_object_ref (b);
		g_signal_connect (b, "modified", G_CALLBACK (gb_single_editor_bookmark_changed_cb), e);
	}
}

void
gb_single_editor_set_bookmark (GbSingleEditor *e, GbBookmark *b)
{
	GbSingleEditorPrivate *p = e->priv;

	gb_single_editor_set_bookmark_internal (e, b);
	gb_single_editor_update_controls (e);
	
	if (p->parents_treemodel)
	{
		g_object_unref (p->parents_treemodel);
		p->parents_treemodel = NULL;
	}

	if (p->parents_treeview)
	{
		if (b)
		{
			GSList *parents = gb_bookmark_get_all_alias_parents (b);
			GSList *li;
			p->parents_treemodel = gb_tree_model_new_for_set (b->set);
			gb_tree_model_set_only_folders (p->parents_treemodel, TRUE);
			gb_tree_model_set_check (p->parents_treemodel,
						 (GbTreeModelCheckFunc) gb_folder_has_child_or_alias, b);
			gb_tree_view_set_model (p->parents_treeview, p->parents_treemodel);
			for (li = parents; li; li = li->next)
			{
				gb_tree_view_ensure_expanded (p->parents_treeview, li->data);
			}
			g_slist_free (parents);
		}
	}
}

void
gb_single_editor_set_disable_policy (GbSingleEditor *e, GbSingleEditorDisablePolicy policy)
{
	GbSingleEditorPrivate *p = e->priv;
	p->disable_policy = policy;
}

static void
safe_gtk_widget_disable (GtkWidget *w)
{
	if (w)
	{
		gtk_widget_set_sensitive (w, FALSE);
	}
}

static void
safe_gtk_widget_enable (GtkWidget *w)
{
	if (w)
	{
		gtk_widget_set_sensitive (w, TRUE);
	}
}

static void
safe_gtk_widget_show (GtkWidget *w)
{
	if (w)
	{
		gtk_widget_show (w);
	}
}

static void
safe_gtk_widget_hide (GtkWidget *w)
{
	if (w)
	{
		gtk_widget_hide (w);
	}
}

static gchar *
gb_single_editor_format_time (GTime t)
{
	if (t > 0)
	{
		gchar buffer[256];
		int length;
		struct tm stm;
		time_t tt = t;

		/* Convert to local time */
		localtime_r (&tt, &stm);
		length = strftime (buffer, sizeof(buffer), _("%a, %b %-d %Y at %-I:%M %p"),
				   &stm);
		buffer[length] = '\0';		

		return g_locale_to_utf8 (buffer, -1, NULL, NULL, NULL);
	}
	return NULL;
}


static void
gb_single_editor_update_controls (GbSingleEditor *e)
{
	/* TODO: blank all fields when disabling them. */
	
	GbSingleEditorPrivate *p = e->priv;

	void (*disable) (GtkWidget *) = p->disable_policy == GB_SINGLE_EDITOR_DISABLE_POLICY_HIDE 
		? safe_gtk_widget_hide : safe_gtk_widget_disable;
	void (*enable) (GtkWidget *) = p->disable_policy == GB_SINGLE_EDITOR_DISABLE_POLICY_HIDE
		? safe_gtk_widget_show : safe_gtk_widget_enable;

	gb_single_editor_init_widgets_and_signals (e);

	p->no_update++;

	if (!p->bm)
	{
		if (e->notes_textview)
		{
			GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (e->notes_textview));
			gtk_text_buffer_set_text (buffer, "", -1);
		}

		if (e->name_entry)
		{
			gtk_entry_set_text (GTK_ENTRY (e->name_entry), "");
		}

		if (e->nicks_entry)
		{
			gtk_entry_set_text (GTK_ENTRY (e->nicks_entry), "");
		}

		if (e->smarturl_entry)
		{
			gtk_entry_set_text (GTK_ENTRY (e->smarturl_entry), "");
		}

		if (e->location_entry)
		{
			gtk_entry_set_text (GTK_ENTRY (e->location_entry), "");
		}

		disable (e->name_entry);
		disable (e->name_label);
		disable (e->nicks_entry);
		disable (e->nicks_label);
		disable (e->notes_label);
		disable (e->notes_textview);
		disable (e->location_entry);
		disable (e->location_label);
		disable (e->date_visited_value_label);
		disable (e->date_visited_label);
		disable (e->smart_entry_width_spinbutton);
		disable (e->smart_entry_width_label);
		disable (e->smarturl_entry);
		disable (e->smarturl_label);
		disable (e->parameter_encoding_combo);
		disable (e->parameter_encoding_label);
		disable (e->create_toolbar_checkbox);
		disable (e->more_properties_button);

		p->no_update--;
		return;		
	}

	enable (e->more_properties_button);

	if (e->name_entry)
	{
		gtk_entry_set_text (GTK_ENTRY (e->name_entry), p->bm->name);
		enable (e->name_entry);
		enable (e->name_label);
	}

	if (e->notes_textview)
	{
		GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (e->notes_textview));
		GtkTextIter begin, end;
		char * text;

		/* Fix bug 97262, don't update the text if it won't change it, 
		 * this stops the cursor being moved to the end */
		gtk_text_buffer_get_start_iter (buffer, &begin);
		gtk_text_buffer_get_end_iter (buffer, &end);
		text = gtk_text_buffer_get_text (buffer, &begin, &end, TRUE);
		if (strcmp (text, p->bm->notes))
		{
			gtk_text_buffer_set_text (buffer, p->bm->notes, -1);
		}

		g_free (text);
		enable (e->notes_textview);
		enable (e->notes_label);
	}

	if (e->add_to_context_checkbox)
	{
		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (e->add_to_context_checkbox), 
					      p->bm->add_to_context_menu);
		enable (e->add_to_context_checkbox);
	}

	if (e->date_added_value_label)
	{
		char *s = gb_single_editor_format_time (p->bm->time_added);
		if (!s) s = g_strdup_printf( "<i>&lt;%s&gt;</i>", _("Not specified"));
		gtk_label_set_markup (GTK_LABEL (e->date_added_value_label), s);
		g_free (s);
		enable (e->date_added_value_label);
	}

	if (e->date_modified_value_label)
	{
		/* The entry was 'modified' when it was added */
		GTime t = p->bm->time_modified ? p->bm->time_modified : p->bm->time_added;
		gchar *s = gb_single_editor_format_time (t);
		if (!s) s = g_strdup_printf( "<i>&lt;%s&gt;</i>", _("Not specified"));
		gtk_label_set_markup (GTK_LABEL (e->date_modified_value_label), s);
		g_free (s);
		enable (e->date_modified_value_label);
	}

	if (e->image_pixmapentry)
	{
		gnome_file_entry_set_filename (GNOME_FILE_ENTRY (e->image_pixmapentry),
					       p->bm->pixmap_file);
		enable (e->image_pixmapentry);
	}
	
	if (GB_IS_SITE (p->bm))
	{
		if (e->location_entry)
		{
			gtk_entry_set_text (GTK_ENTRY (e->location_entry), GB_SITE (p->bm)->url);
			enable (e->location_entry);
			enable (e->location_label);
		}

		if (e->date_visited_value_label)
		{
			gchar *s = gb_single_editor_format_time (GB_SITE (p->bm)->time_visited);
			if (!s) s = g_strdup_printf( "<i>&lt;%s&gt;</i>", _("Not specified"));
			gtk_label_set_markup (GTK_LABEL (e->date_visited_value_label), s);
			g_free (s);
			enable (e->date_visited_value_label);
		}
		if (e->nicks_entry)
		{
			gtk_entry_set_text (GTK_ENTRY (e->nicks_entry), p->bm->nick);
			enable (e->nicks_entry);
			enable (e->nicks_label);
		}
	}
	else
	{
		if (e->location_entry)
		{
			gtk_entry_set_text (GTK_ENTRY (e->location_entry), "");
		}
		if (e->nicks_entry)
		{
			gtk_entry_set_text (GTK_ENTRY (e->nicks_entry), "");
		}
		disable (e->location_entry);
		disable (e->location_label);
		disable (e->date_visited_value_label);
		disable (e->date_visited_label);
		disable (e->nicks_entry);
		disable (e->nicks_label);
	}

	if (GB_IS_SMART_SITE (p->bm))
	{
		if (e->smart_entry_width_spinbutton)
		{
			guint width = gb_smart_site_get_entry_size (GB_SMART_SITE (p->bm), 0);
			gtk_spin_button_set_value (GTK_SPIN_BUTTON (e->smart_entry_width_spinbutton), width);
			enable (e->smart_entry_width_spinbutton);
			enable (e->smart_entry_width_label);
			enable (p->smart_entry_width_hbox);
		}

		if (e->smarturl_entry)
		{
			gchar * smarturl = gb_smart_site_get_smarturl (GB_SMART_SITE (p->bm));
			gtk_entry_set_text (GTK_ENTRY (e->smarturl_entry), smarturl);
			g_free (smarturl);
			enable (e->smarturl_entry);
			enable (e->smarturl_label);
		}

		if (e->parameter_encoding_combo)
		{
			gchar *encoding = gb_smart_site_get_encoding (GB_SMART_SITE (p->bm));
			gtk_entry_set_text (GTK_ENTRY (GTK_BIN (e->parameter_encoding_combo)->child), encoding);
			g_free (encoding);
			enable (e->parameter_encoding_combo);
			enable (e->parameter_encoding_label);
		}
	}
	else
	{
		disable (e->smart_entry_width_spinbutton);
		disable (e->smart_entry_width_label);
		disable (p->smart_entry_width_hbox);
		if (e->smarturl_entry)
		{
			gtk_entry_set_text (GTK_ENTRY (e->smarturl_entry), "");
		}
		disable (e->smarturl_entry);
		disable (e->smarturl_label);
		disable (e->parameter_encoding_combo);
		disable (e->parameter_encoding_label);
	}

	if (GB_IS_FOLDER (p->bm))
	{
		if (e->create_toolbar_checkbox)
		{
			gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (e->create_toolbar_checkbox), 
						      GB_FOLDER (p->bm)->create_toolbar);
			enable (e->create_toolbar_checkbox);
		}
	}
	else
	{
		disable (e->create_toolbar_checkbox);
	}

	p->no_update--;
}

static void
gb_single_editor_bookmark_changed_cb (GbBookmark *b, GbSingleEditor *e)
{
	g_return_if_fail (e->priv->bm == b);
	
	gb_single_editor_update_controls (e);
}

static void
gb_single_editor_name_entry_changed_cb	(GtkWidget *edited,
					 GbSingleEditor *e)
{
	GbSingleEditorPrivate *p = e->priv;
	gchar *s;

	if (p->no_update > 0) return;
	
	g_return_if_fail (GB_IS_BOOKMARK (p->bm));

	s = gtk_editable_get_chars (GTK_EDITABLE (e->name_entry), 0, -1);
	gb_bookmark_set_name (p->bm, s);
	gb_bookmark_set_time_modified_now (p->bm);
	g_free (s);
}

static void
gb_single_editor_smarturl_entry_changed_cb (GtkWidget *edited,
					    GbSingleEditor *e)
{
	GbSingleEditorPrivate *p = e->priv;
	gchar *s;

	if (p->no_update > 0) return;
	
	g_return_if_fail (GB_IS_SMART_SITE (p->bm));

	s = gtk_editable_get_chars (GTK_EDITABLE (e->smarturl_entry), 0, -1);
	gb_smart_site_set_smarturl (GB_SMART_SITE (p->bm), s);
	gb_bookmark_set_time_modified_now (p->bm);
	g_free (s);
}

static void
gb_single_editor_location_entry_changed_cb (GtkWidget *edited,
					    GbSingleEditor *e)
{
	GbSingleEditorPrivate *p = e->priv;
	gchar *s;

	if (p->no_update > 0) return;
	
	g_return_if_fail (GB_IS_SITE (p->bm));

	s = gtk_editable_get_chars (GTK_EDITABLE (e->location_entry), 0, -1);
	gb_site_set_url (GB_SITE (p->bm), s);
	gb_bookmark_set_time_modified_now (p->bm);
	g_free (s);
}

static void
gb_single_editor_smart_entry_width_spinbutton_value_changed_cb (GtkWidget *spinbutton, GbSingleEditor *e)
{
	GbSingleEditorPrivate *p = e->priv;
	guint width;

	if (p->no_update > 0) return;

	g_return_if_fail (GB_IS_SMART_SITE (p->bm));

	width = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (e->smart_entry_width_spinbutton));

	gb_smart_site_set_entry_size (GB_SMART_SITE (p->bm), 0, width);
	gb_bookmark_set_time_modified_now (p->bm);
}

static void
gb_single_editor_notes_text_buffer_changed_cb (GtkWidget *edited,
					       GbSingleEditor *e)
{
	GbSingleEditorPrivate *p = e->priv;
	GtkTextBuffer *b;
	GtkTextIter begin, end;
	gchar *notes;

	if (p->no_update > 0) return;

	g_return_if_fail (GB_IS_BOOKMARK (p->bm));

	b = gtk_text_view_get_buffer (GTK_TEXT_VIEW (e->notes_textview));
	gtk_text_buffer_get_start_iter (b, &begin);
	gtk_text_buffer_get_end_iter (b, &end);
	notes = gtk_text_buffer_get_text (b, &begin, &end, TRUE);
	gb_bookmark_set_notes (p->bm, notes);
	gb_bookmark_set_time_modified_now (p->bm);
	g_free (notes);

}

static void
gb_single_editor_nicks_entry_changed_cb	(GtkWidget *edited,
					 GbSingleEditor *e)
{
	GbSingleEditorPrivate *p = e->priv;
	gchar *s;

	if (p->no_update > 0) return;
	
	g_return_if_fail (GB_IS_BOOKMARK (p->bm));

	s = gtk_editable_get_chars (GTK_EDITABLE (e->nicks_entry), 0, -1);
	gb_bookmark_set_nick (p->bm, s);
	gb_bookmark_set_time_modified_now (p->bm);
	g_free (s);

}

static void
gb_single_editor_create_toolbar_checkbox_toggled_cb (GtkWidget *edited,
						     GbSingleEditor *e)
{
	GbSingleEditorPrivate *p = e->priv;
	gboolean val;

	if (p->no_update > 0) return;
	
	g_return_if_fail (GB_IS_FOLDER (p->bm));

	val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (e->create_toolbar_checkbox));
	gb_folder_set_create_toolbar (GB_FOLDER (p->bm), val);
	gb_bookmark_set_time_modified_now (p->bm);

}

static void
gb_single_editor_add_to_context_checkbox_toggled_cb (GtkWidget *edited,
						     GbSingleEditor *e)
{
	GbSingleEditorPrivate *p = e->priv;
	gboolean val;

	if (p->no_update > 0) return;
	
	g_return_if_fail (GB_IS_BOOKMARK (p->bm));

	val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (e->add_to_context_checkbox));
	gb_bookmark_set_add_to_context_menu (p->bm, val);
	gb_bookmark_set_time_modified_now (p->bm);

}

static void
gb_single_editor_image_pixmapentry_changed_cb (GtkWidget *edited,
						GbSingleEditor *e)
{
	GbSingleEditorPrivate *p = e->priv;
	gchar *s;

	if (p->no_update > 0) return;
	
	g_return_if_fail (GB_IS_BOOKMARK (p->bm));

	s = gtk_editable_get_chars (GTK_EDITABLE (e->image_pixmapentry), 0, -1);
	gb_bookmark_set_pixmap (p->bm, s);
	gb_bookmark_set_time_modified_now (p->bm);
	g_free (s);

}

static void
gb_single_editor_parameter_encoding_combo_changed_cb (GtkWidget *edited,
						      GbSingleEditor *e)
{
	GbSingleEditorPrivate *p = e->priv;
	gchar *s;

	if (p->no_update > 0) return;
	
	g_return_if_fail (GB_IS_SMART_SITE (p->bm));

	s = gtk_editable_get_chars (GTK_EDITABLE (GTK_BIN (e->parameter_encoding_combo)->child), 0, -1);
	gb_smart_site_set_encoding (GB_SMART_SITE (p->bm), s);
	gb_bookmark_set_time_modified_now (p->bm);
	g_free (s);
}

