/*
 *  Copyright (C) 2002 Jorn Baayen
 *
 *  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 "history-dialog.h"

#include "galeon-embed-shell.h"
#include "galeon-dnd.h"
#include "galeon-shell.h"
#include "galeon-window.h"
#include "gul-gui.h"
#include "gul-string.h"
#include "gul-state.h"
#include "location-entry.h"
#include "galeon-debug.h"

#include <gtk/gtktreeview.h>
#include <gtk/gtktreestore.h>
#include <gtk/gtktreeselection.h>
#include <gtk/gtkcellrenderertext.h>
#include <glib/gi18n.h>

#define CONF_HISTORY_SEARCH_TEXT "/apps/galeon/Browsing/History/search_text"
#define CONF_HISTORY_SEARCH_TIME "/apps/galeon/Browsing/History/search_time"
#define CONF_HISTORY_HOST_GROUP "/apps/galeon/Browsing/History/host_group"

static void history_dialog_class_init (HistoryDialogClass *klass);
static void history_dialog_init (HistoryDialog *dialog);
static void history_dialog_finalize (GObject *object);
static void history_dialog_set_embedded (HistoryDialog *d,
			     	         gboolean embedded);

/* Glade callbacks */
void
history_host_checkbutton_toggled_cb (GtkWidget *widget, 
				     HistoryDialog *dialog);
void
history_time_combobox_changed_cb (GtkWidget *widget, 
				  HistoryDialog *dialog);
void
history_entry_changed_cb (GtkWidget *widget, 
			  HistoryDialog *dialog);
void
history_ok_button_clicked_cb (GtkWidget *button,
			      HistoryDialog *dialog);
void
history_clear_button_clicked_cb (GtkWidget *button,
			         HistoryDialog *dialog);


static GObjectClass *parent_class = NULL;

struct HistoryDialogPrivate
{
	GlobalHistory *gh;
	GtkTreeView *treeview;
	GtkTreeModel *model;
	HistoryFilter filter;
	gboolean group;
	gboolean embedded;
	guint filter_entry_timeout;
};

#define FILTER_ENTRY_TIMEOUT 700

enum
{
	PROP_0,
	PROP_EMBEDDED
};

enum
{
	PROP_DIALOG,
	PROP_TREEVIEW,
	PROP_WORD,
	PROP_TIME,
	PROP_GROUP
};

static GtkTargetEntry url_drag_types [] = 
{
        { GALEON_DND_URI_LIST_TYPE,   0, GALEON_DND_URI_LIST },
        { GALEON_DND_TEXT_TYPE,       0, GALEON_DND_TEXT },
        { GALEON_DND_URL_TYPE,        0, GALEON_DND_URL }
};

static const
GaleonDialogProperty properties [] =
{
	{ PROP_DIALOG, "history_dialog", NULL, PT_NORMAL, NULL },
	{ PROP_TREEVIEW, "history_treeview", NULL, PT_NORMAL, NULL },
	{ PROP_WORD, "history_entry", CONF_HISTORY_SEARCH_TEXT, PT_NORMAL, NULL },
	{ PROP_TIME, "history_time_combobox", CONF_HISTORY_SEARCH_TIME, PT_NORMAL, NULL },
	{ PROP_GROUP, "history_host_checkbutton", CONF_HISTORY_HOST_GROUP, PT_NORMAL, NULL },
	{ -1, NULL, NULL }
};

GType 
history_dialog_get_type (void)
{
        static GType history_dialog_type = 0;

        if (history_dialog_type == 0)
        {
                static const GTypeInfo our_info =
                {
                        sizeof (HistoryDialogClass),
                        NULL, /* base_init */
                        NULL, /* base_finalize */
                        (GClassInitFunc) history_dialog_class_init,
                        NULL,
                        NULL, /* class_data */
                        sizeof (HistoryDialog),
                        0, /* n_preallocs */
                        (GInstanceInitFunc) history_dialog_init
                };

                history_dialog_type = g_type_register_static (GALEON_EMBED_DIALOG_TYPE,
						              "HistoryDialog",
						              &our_info, 0);
        }

        return history_dialog_type;

}

static void
history_dialog_set_property (GObject *object,
                             guint prop_id,
                             const GValue *value,
                             GParamSpec *pspec)
{
        HistoryDialog *d = HISTORY_DIALOG (object);

        switch (prop_id)
        {
                case PROP_EMBEDDED:
                        history_dialog_set_embedded 
				(d, g_value_get_boolean (value));
                        break;
        }
}

static void
history_dialog_get_property (GObject *object,
                             guint prop_id,
                             GValue *value,
                             GParamSpec *pspec)
{
        HistoryDialog *d = HISTORY_DIALOG (object);

        switch (prop_id)
        {
                case PROP_EMBEDDED:
                        g_value_set_boolean (value, d->priv->embedded);
                        break;
        }
}


static void
history_dialog_class_init (HistoryDialogClass *klass)
{
        GObjectClass *object_class = G_OBJECT_CLASS (klass);

        parent_class = g_type_class_peek_parent (klass);

        object_class->finalize = history_dialog_finalize;
	object_class->set_property = history_dialog_set_property;
	object_class->get_property = history_dialog_get_property;

	g_object_class_install_property (object_class,
                                         PROP_EMBEDDED,
                                         g_param_spec_boolean ("embedded",
                                                               "Show embedded in another widget",
                                                               "Show embedded in another widget",
                                                               TRUE,
                                                               G_PARAM_READWRITE));
}

static void
history_dialog_row_activated_cb (GtkTreeView *tree_view, GtkTreePath *path,
               	                 GtkTreeViewColumn *column, HistoryDialog *dialog)
{
	GaleonEmbed *embed;
        GtkTreeIter iter;
        GtkTreeModel *model = gtk_tree_view_get_model (tree_view);
        char *url;

        gtk_tree_model_get_iter (model, &iter, path);
        gtk_tree_model_get (model, &iter, 1, &url, -1);

	embed = galeon_embed_dialog_get_embed (GALEON_EMBED_DIALOG(dialog));
	galeon_embed_load_url (embed, url);
	g_free (url);
}

static void
each_url_get_data_binder (GaleonDragEachSelectedItemDataGet iteratee, 
                          gpointer iterator_context, gpointer data)
{
	GtkTreeView *treeview = HISTORY_DIALOG(iterator_context)->priv->treeview;
	GtkTreeModel *model = HISTORY_DIALOG(iterator_context)->priv->model;
	GList *refs, *l;
	
	refs = gul_gui_treeview_get_selection_refs (treeview);	
	
	for (l = refs; l != NULL; l = l->next)
	{
        	char *url, *title;
		GtkTreeIter iter;
                GtkTreePath *path;

                path = gtk_tree_row_reference_get_path 
                        ((GtkTreeRowReference *)l->data); 
                gtk_tree_model_get_iter 
                        (model, &iter, path);

		gtk_tree_model_get (model, &iter, 
				    0, &title,
				    1, &url,
				    -1);

		iteratee (url, title, -1, -1, -1, -1, data);

		g_free (url);
		g_free (title);
	}

	gul_gui_treeview_free_selection_refs (refs);
}

static void
treeview_drag_data_get_cb (GtkWidget *widget,
                           GdkDragContext *context,
                           GtkSelectionData *selection_data,
                           guint info,
                           guint32 time,
                           HistoryDialog *dialog)
{
        g_assert (widget != NULL);
        g_return_if_fail (context != NULL);

        galeon_dnd_drag_data_get (widget, context, selection_data,
                info, time, dialog, each_url_get_data_binder);
}

static void
history_dialog_setup_view (HistoryDialog *dialog)
{
	GtkTreeView *treeview = dialog->priv->treeview;
	GtkTreeStore *treestore;
	GtkCellRenderer *renderer;
        GtkTreeViewColumn *column;
	GtkTreeSelection *selection;

	/* set tree model */
        treestore = gtk_tree_store_new (8,
                                        G_TYPE_STRING,
                                        G_TYPE_STRING,
                                        G_TYPE_STRING,
                                        G_TYPE_STRING,
                                        G_TYPE_INT,
					G_TYPE_POINTER,
					G_TYPE_INT,
					G_TYPE_INT);
        dialog->priv->model = GTK_TREE_MODEL(treestore);
        gtk_tree_view_set_model (treeview, 
                                 GTK_TREE_MODEL (treestore));
        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(treeview),
                                           TRUE);
        g_signal_connect (treeview, "row_activated",
                          G_CALLBACK (history_dialog_row_activated_cb), 
			  dialog);
	selection = gtk_tree_view_get_selection (treeview);
        gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);

	gtk_tree_view_enable_model_drag_source (treeview,
                                          	GDK_BUTTON1_MASK,
                                          	url_drag_types,
                                          	G_N_ELEMENTS (url_drag_types),
                                          	GDK_ACTION_COPY);
	g_signal_connect (G_OBJECT(treeview),
                          "drag_data_get",
                          G_CALLBACK(treeview_drag_data_get_cb),
                          dialog);
	
        renderer = gtk_cell_renderer_text_new ();

        gtk_tree_view_insert_column_with_attributes (treeview,
                                                     0, _("Title"),
                                                     renderer,
                                                     "text", 0,
                                                     NULL);
        column = gtk_tree_view_get_column (treeview, 0);
        gtk_tree_view_column_set_resizable (column, TRUE);
        gtk_tree_view_column_set_reorderable (column, TRUE);
	gtk_tree_view_column_set_min_width (column, 20);
	gtk_tree_view_column_set_max_width (column, 400);
        gtk_tree_view_column_set_sort_column_id (column, 0);

        gtk_tree_view_insert_column_with_attributes (treeview,
                                                     1, _("URL"),
                                                     renderer,
                                                     "text", 1,
                                                     NULL);
        column = gtk_tree_view_get_column (treeview, 1);
        gtk_tree_view_column_set_resizable (column, TRUE);
        gtk_tree_view_column_set_reorderable (column, TRUE);
	gtk_tree_view_column_set_min_width (column, 20);
	gtk_tree_view_column_set_max_width (column, 500);
        gtk_tree_view_column_set_sort_column_id (column, 1);

	gtk_tree_view_insert_column_with_attributes (treeview,
                                                     2, _("Last visited"),
                                                     renderer,
                                                     "text", 2,
                                                     NULL);
        column = gtk_tree_view_get_column (treeview, 2);
        gtk_tree_view_column_set_resizable (column, TRUE);
        gtk_tree_view_column_set_reorderable (column, TRUE);
        gtk_tree_view_column_set_sort_column_id (column, 6);

        gtk_tree_view_insert_column_with_attributes (treeview,
                                                     3, _("First visited"),
                                                     renderer,
                                                     "text", 3,
                                                     NULL);
        column = gtk_tree_view_get_column (treeview, 3);
        gtk_tree_view_column_set_resizable (column, TRUE);
        gtk_tree_view_column_set_reorderable (column, TRUE);
        gtk_tree_view_column_set_sort_column_id (column, 7);

        gtk_tree_view_insert_column_with_attributes (treeview,
                                                     4, _("Times visited"),
                                                     renderer,
                                                     "text", 4,
                                                     NULL);
        column = gtk_tree_view_get_column (treeview, 4);
        gtk_tree_view_column_set_resizable (column, TRUE);
        gtk_tree_view_column_set_reorderable (column, TRUE);
        gtk_tree_view_column_set_sort_column_id (column, 4);
}

static void
history_dialog_update_host_item (HistoryDialog *dialog, 
		   	         HistoryItem *item,
				 GtkTreeIter *iter)
{
	char last[256], first[256];
        char *text[6] = { NULL, NULL, last, first, NULL };
	
	text[0] = item->url;
        text[1] = item->url;
        gul_string_store_time_in_string (item->last, text[2]);
        gul_string_store_time_in_string (item->first, text[3]);
	
	gtk_tree_store_set (GTK_TREE_STORE (dialog->priv->model),
                            iter,
                            0, text[0],
                            1, text[1],
                            2, text[2],
                            3, text[3],
                            4, item->visits,
			    5, item,
			    6, item->last,
			    7, item->first,
                            -1);
}


static GtkTreeIter *
history_dialog_add_host_item (HistoryDialog *dialog, 
			      HistoryItem *item)
{
	GtkTreeIter iter;
	GtkTreeIter *tmp;

	if (!dialog->priv->group) return NULL;
	
	gtk_tree_store_insert (GTK_TREE_STORE (dialog->priv->model), 
                               &iter,
                               NULL,
                               0);
	
	tmp = gtk_tree_iter_copy (&iter);
	history_dialog_update_host_item (dialog, item, tmp);

	return tmp;
}

static void
history_dialog_remove_item (HistoryDialog *dialog,
		  	    HistoryItem *item,
			    GtkTreeIter *iter)
{
	gtk_tree_store_remove (GTK_TREE_STORE (dialog->priv->model), 
			       iter);
}

static void
history_dialog_update_url_item (HistoryDialog *dialog,
		  	        HistoryItem *item,
			        GtkTreeIter *iter)
{
	char last[256], first[256];
        char *text[5] = { NULL, NULL, last, first, NULL };

	text[0] = item->title;
        text[1] = item->url;
        gul_string_store_time_in_string (item->last, text[2]);
        gul_string_store_time_in_string (item->first, text[3]);

        gtk_tree_store_set (GTK_TREE_STORE (dialog->priv->model),
                            iter,
                            0, text[0],
                            1, text[1],
                            2, text[2],
                            3, text[3],
                            4, item->visits,
			    5, item,
			    6, item->last,
			    7, item->first,
                            -1);
}

static void
history_dialog_add_url_item (HistoryDialog *dialog,
			     HistoryItem *item,
			     GtkTreeIter *parent_iter)
{
	GtkTreeIter iter;
	GtkTreeIter *tmp;
	gtk_tree_store_insert (GTK_TREE_STORE (dialog->priv->model), 
                               &iter,
                               parent_iter,
                               0);
	
	tmp = gtk_tree_iter_copy (&iter);
	history_dialog_update_url_item (dialog, item, tmp);
 	gtk_tree_iter_free (tmp);
}

static void
history_dialog_add_url_items (HistoryDialog *dialog,
			      GList *items,
			      GtkTreeIter *iter)
{
	for (; items != NULL; items = items->next)
	{
		HistoryItem *item = (HistoryItem *)(items->data);
		history_dialog_add_url_item (dialog, item, iter);
	}
}

static void
history_dialog_fill_view (HistoryDialog *dialog) 
{
	GList *list, *l;
	GtkTreeIter *iter;
	
	list = global_history_get_host_list (dialog->priv->gh);

	for (l = list; l != NULL; l = l->next)
	{
		GList *urls;
		HistoryItem *item = (HistoryItem *)(l->data);

		urls = global_history_get_urls_list (dialog->priv->gh,
						     item, 
						     &dialog->priv->filter);
		if (urls)
		{	
			iter = history_dialog_add_host_item (dialog,
							     item);
			history_dialog_add_url_items (dialog, urls, iter);
			g_list_free (urls);

			if (iter)
			{
				gtk_tree_iter_free (iter);
			}
		}
	}

	g_list_free (list);
}

static void
history_dialog_clear_view (HistoryDialog *dialog)
{
	gtk_tree_store_clear (GTK_TREE_STORE(dialog->priv->model));
}

static void
history_dialog_setup_filter (HistoryDialog *dialog)
{
	GValue word = {0, };
	GValue group = {0, };
	GValue time = {0, };

	galeon_dialog_get_value (GALEON_DIALOG(dialog), PROP_WORD, &word);
	/* The cast is ok as we put the string in there using g_value_get_string */
	g_free ( (char*)dialog->priv->filter.word);
        dialog->priv->filter.word = g_value_get_string (&word);
	
	galeon_dialog_get_value (GALEON_DIALOG(dialog), PROP_TIME, &time);
        dialog->priv->filter.type = g_value_get_int (&time);

	galeon_dialog_get_value (GALEON_DIALOG(dialog), PROP_GROUP, &group);
        dialog->priv->group = g_value_get_boolean (&group);
}

static GtkTreeIter *
history_dialog_find_host_iter (HistoryDialog *dialog,
			       HistoryItem *item)
{
	GtkTreeIter iter;
	
	if (gtk_tree_model_get_iter (dialog->priv->model, &iter,
				     gtk_tree_path_new_first()) == TRUE)
	{
		do {
			GValue val = { 0, }; 
			HistoryItem *i;
			gtk_tree_model_get_value (dialog->priv->model, 
						  &iter, 5, &val);
			i = (HistoryItem *) g_value_get_pointer (&val);
			if (i == item) return gtk_tree_iter_copy (&iter); 
		}
		while (gtk_tree_model_iter_next (dialog->priv->model, &iter));
	}

	return NULL;
}

static GtkTreeIter *
history_dialog_find_site_iter (HistoryDialog *dialog,
			       GtkTreeIter *host_iter,
			       HistoryItem *item)
{
	GtkTreeIter iter;
	
	gtk_tree_model_iter_children (dialog->priv->model,
				      &iter,
				      host_iter);

	do
	{
		GValue val = { 0, }; 
		HistoryItem *i;
		gtk_tree_model_get_value (dialog->priv->model, 
					  &iter, 5, &val);
		i = (HistoryItem *) g_value_get_pointer (&val);
		if (i == item) return gtk_tree_iter_copy (&iter); 
	}
	while (gtk_tree_model_iter_next (dialog->priv->model, &iter));
	
	return NULL;
}

static void
history_item_add_cb (GlobalHistory *gh, 
		     HistoryItem *item,
		     HistoryDialog *dialog)
{
	GtkTreeIter *iter;
	HistoryItem *host;
	GList *urls_list;
	gboolean empty_list;
	
	host = global_history_get_host_from_site (dialog->priv->gh,
	  				          item);

	/* ignore urls that doesnt match current filter */
	urls_list = global_history_get_urls_list (dialog->priv->gh,
						  host,
						  &dialog->priv->filter);
	empty_list = !g_list_find (urls_list, item);
	g_list_free (urls_list);
	if (empty_list) return;
	
	iter = history_dialog_find_host_iter (dialog, host);
	if (!iter)
	{
		iter = history_dialog_add_host_item (dialog, 
						     host);
	}

	history_dialog_add_url_item (dialog, item, iter);

	if (iter)
	{
		gtk_tree_iter_free (iter);
	}
}

static void
history_item_update_cb (GlobalHistory *gh, 
		        HistoryItem *item,
		        HistoryDialog *dialog)
{
	GtkTreeIter *host_iter, *iter;
	HistoryItem *host;

	host = global_history_get_host_from_site (dialog->priv->gh,
		  				  item);
		
	host_iter = history_dialog_find_host_iter (dialog, host);

	if (host_iter)
	{
		iter = history_dialog_find_site_iter (dialog, host_iter, item);
		if (iter)
		{
			history_dialog_update_host_item (dialog, host, host_iter);
			history_dialog_update_url_item (dialog, item, iter);
			gtk_tree_iter_free (iter);
		}
		gtk_tree_iter_free (host_iter);
	}
	
}

static void
history_item_remove_cb (GlobalHistory *gh, 
		        HistoryItem *item,
		        HistoryDialog *dialog)
{
	GtkTreeIter *host_iter, *iter;
	HistoryItem *host;
	GList *urls_list;
	gboolean remove_parent;
	
	host = global_history_get_host_from_site (dialog->priv->gh,
		  				  item);
	
	urls_list = global_history_get_urls_list (dialog->priv->gh,
						  host,
						  &dialog->priv->filter);
	
	remove_parent = (g_list_length (urls_list) == 1);
	g_list_free (urls_list);
	
	host_iter = history_dialog_find_host_iter (dialog, host);
	if (host_iter)
	{
		iter = history_dialog_find_site_iter (dialog, host_iter, item);
		if (iter)
		{
			history_dialog_remove_item (dialog, item, iter);
			gtk_tree_iter_free (iter);
		}

		if (remove_parent)
		{
			history_dialog_remove_item (dialog, item, iter);
		}
			
		gtk_tree_iter_free (host_iter);
	}
}

static void
history_dialog_init (HistoryDialog *dialog)
{	
	GaleonEmbedShell *ges;
	
	dialog->priv = g_new0 (HistoryDialogPrivate, 1);

	ges = galeon_shell_get_embed_shell (galeon_shell);
	dialog->priv->gh = galeon_embed_shell_get_global_history (ges);
	g_return_if_fail (dialog->priv->gh != NULL);

	g_signal_connect (G_OBJECT(dialog->priv->gh),
			  "add",
			  G_CALLBACK (history_item_add_cb),
			  dialog);
	g_signal_connect (G_OBJECT(dialog->priv->gh),
			  "update",
			  G_CALLBACK (history_item_update_cb),
			  dialog);
	g_signal_connect (G_OBJECT(dialog->priv->gh),
			  "remove",
			  G_CALLBACK (history_item_remove_cb),
			  dialog);	
}

static void
history_dialog_set_embedded (HistoryDialog *dialog,
			     gboolean embedded)
{
	dialog->priv->embedded = embedded;

	galeon_dialog_construct (GALEON_DIALOG(dialog),
				 properties,
				 "galeon.glade", 
				 embedded ? 
				 "history_dock_box" :
				 "history_dialog");

	if (!embedded)
	{
		gul_state_monitor_window (
			galeon_dialog_get_control (GALEON_DIALOG(dialog),
				                   PROP_DIALOG),
			"History", -1, -1);
	}

	dialog->priv->treeview = GTK_TREE_VIEW (
				 galeon_dialog_get_control (GALEON_DIALOG(dialog), 
							    PROP_TREEVIEW));
	history_dialog_setup_view (dialog);
	history_dialog_setup_filter (dialog);
	history_dialog_fill_view (dialog);
}

static void
history_dialog_finalize (GObject *object)
{
	HistoryDialog *dialog;
	HistoryDialogPrivate *p;

        g_return_if_fail (object != NULL);
        g_return_if_fail (IS_HISTORY_DIALOG (object));

	dialog = HISTORY_DIALOG (object);
	p = dialog->priv;

        g_return_if_fail (dialog->priv != NULL);

	if (p->filter_entry_timeout)
	{
		g_source_remove (p->filter_entry_timeout);
	}

	g_signal_handlers_disconnect_by_func 
		(G_OBJECT(p->gh),
		 G_CALLBACK (history_item_add_cb),
		 dialog);
	g_signal_handlers_disconnect_by_func 
		(G_OBJECT(p->gh),
		 G_CALLBACK (history_item_update_cb),
		 dialog);
	g_signal_handlers_disconnect_by_func 
		(G_OBJECT(p->gh),
		 G_CALLBACK (history_item_remove_cb),
		 dialog);
	
	/* The cast is ok as we put the string in there using g_value_get_string */
	g_free ((char*)p->filter.word);
        g_free (p);

        G_OBJECT_CLASS (parent_class)->finalize (object);
}

GaleonDialog *
history_dialog_new (GaleonEmbed *embed,
		    gboolean embedded)
{
	HistoryDialog *dialog;
	
	dialog = HISTORY_DIALOG (g_object_new (HISTORY_DIALOG_TYPE,
					       "embedded", embedded,
				     	       "GaleonEmbed", embed,
				               NULL));

	return GALEON_DIALOG(dialog);
}

GaleonDialog *
history_dialog_new_with_parent (GtkWidget *window,
		                GaleonEmbed *embed,
		                gboolean embedded)
{
	HistoryDialog *dialog;
	
	dialog = HISTORY_DIALOG (g_object_new (HISTORY_DIALOG_TYPE,
					       "embedded", embedded,
				     	       "GaleonEmbed", embed,
				     	       "ParentWindow", window,
				               NULL));

	return GALEON_DIALOG(dialog);
}

void
history_host_checkbutton_toggled_cb (GtkWidget *widget, 
				     HistoryDialog *dialog)
{
	if (dialog->priv->treeview == NULL) return;
	history_dialog_clear_view (dialog);
	history_dialog_setup_filter (dialog);
	history_dialog_fill_view (dialog);
}

static gboolean
history_filter_entry_timeout_cb (gpointer data)
{
	HistoryDialog *dialog = data;
	HistoryDialogPrivate *p = dialog->priv;

	p->filter_entry_timeout = 0;

	START_PROFILER ("Clear liststore");

	history_dialog_clear_view (dialog);

	STOP_PROFILER ("Clear liststore");
	START_PROFILER ("Setting filter");

	history_dialog_setup_filter (dialog);

	STOP_PROFILER ("Setting filter");
	START_PROFILER ("Filling view");

	history_dialog_fill_view (dialog);

	STOP_PROFILER ("Filling view");

	return FALSE;
}


void
history_entry_changed_cb (GtkWidget *widget, 
			  HistoryDialog *dialog)
{
	HistoryDialogPrivate *p = dialog->priv;

	if (p->treeview == NULL) return;

	if (p->filter_entry_timeout)
	{
		g_source_remove (p->filter_entry_timeout);
	}
	
	p->filter_entry_timeout = g_timeout_add (FILTER_ENTRY_TIMEOUT, 
						 history_filter_entry_timeout_cb, dialog);
}

void
history_time_combobox_changed_cb (GtkWidget *widget, 
				  HistoryDialog *dialog)
{
	if (dialog->priv->treeview == NULL) return;
	history_dialog_clear_view (dialog);
	history_dialog_setup_filter (dialog);
	history_dialog_fill_view (dialog);
}

void
history_ok_button_clicked_cb (GtkWidget *button,
			      HistoryDialog *dialog)
{
	g_object_unref (G_OBJECT(dialog));
}

void
history_clear_button_clicked_cb (GtkWidget *button,
			         HistoryDialog *dialog)
{
	Session * session;
	const GList *windows;
	const GList *win;

	history_dialog_clear_view (dialog);
	global_history_clear (dialog->priv->gh);
	galeon_location_entry_clear_history ();

	session = galeon_shell_get_session (galeon_shell);
	windows = session_get_windows (session);

	for (win = windows; win ; win = win->next)
	{
		galeon_window_clear_history (win->data);
	} 
}

