/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/*
 *  Copyright (C) 2002-2004 Hiroyuki Ikezoe
 *  Copyright (C) 2003 Takuro Ashie
 *
 *  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.
 */

#include "kz-actions.h"

#include "string.h"

#include "egg-toggle-action.h"
#include "egg-entry-action.h"
#include "egg-toolbutton.h"
#include "gtk-utils.h"
#include "intl.h"
#include "utils.h"
#include "kazehakase.h"
#include "kz-window.h"
#include "kz-tab-label.h"
#include "kz-prefs-win.h"
#include "kz-link.h"
#include "kz-links-dialog.h"
#include "mozilla.h"
#include "kz-bookmark-editor.h"
#include "kz-location-entry-action.h"
#include "kz-home-action.h"
#include "google-action.h"
#include "kz-mozembed.h"
#include "kz-actions-download.h"
#include "kz-about-dialog.h"
#include "kz-paned.h"

static GQuark bookmark_quark = 0;


static void
act_save (EggAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);
	KzMozEmbed *kzembed;

	g_return_if_fail(KZ_IS_WINDOW(kz));
	g_return_if_fail(KZ_IS_MOZ_EMBED(widget));
	
	kzembed = KZ_MOZ_EMBED(widget);
	
	/* FIXME! we need to call mozilla function. */
	kz_actions_download_open_save_dialog(kz_moz_embed_get_location(kzembed));
	/* impl_save(kzembed); */
}


static void
act_close_window (EggAction *action, KzWindow *kz)
{
	g_return_if_fail(KZ_IS_WINDOW(kz));

	kz_window_store_state(kz);
	kz_window_close_all_tab(kz);
	gtk_widget_destroy(GTK_WIDGET(kz));
}


static void
act_close_tab (EggAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);
	if (widget)
		kz_window_close_tab(kz, widget);
}


static void
act_new_window (EggAction *action, KzWindow *kz)
{
	GtkWidget *widget;

	g_return_if_fail(KZ_IS_WINDOW(kz));

	widget = kz_window_new(NULL);
	gtk_widget_show(widget);
}


static void
cb_remove_idle(KzWindow* kz)
{
	g_idle_remove_by_data(kz);
}


static gboolean
idle_focus_to_loc_ent(gpointer data)
{
	EggAction *action;
	KzWindow *kz;

	g_return_val_if_fail(KZ_IS_WINDOW(data), FALSE);
	
	kz = KZ_WINDOW(data);
	action = egg_action_group_get_action(kz->actions,"FocusLocationEntry");

	egg_action_activate(action);
	g_signal_handlers_disconnect_by_func(G_OBJECT(kz),
					     G_CALLBACK(cb_remove_idle), NULL);
	return FALSE;
}

static void
act_new_tab (EggAction *action, KzWindow *kz)
{
	gboolean focus;
	GtkWidget *widget;

	g_return_if_fail(KZ_IS_WINDOW(kz));
	widget = kz_window_open_new_tab(kz, NULL);

   	KZ_CONF_GET("Tab", "focus_open_new", focus, BOOL);
	if(focus && widget)
	{
		int num = gtk_notebook_page_num(GTK_NOTEBOOK(kz->notebook),
						widget);
		if(num != -1)
			gtk_notebook_set_current_page(GTK_NOTEBOOK(kz->notebook),
						      num);

		KZ_CONF_GET("Tab","focus_loc_ent_new", focus, BOOL);
		if(focus)
		{
			g_idle_add(idle_focus_to_loc_ent, kz);
			g_signal_connect(G_OBJECT(kz), "destroy",
					 G_CALLBACK(cb_remove_idle), NULL);
		}
	}
}


static void
act_focus_loc_ent (EggAction *action, KzWindow *kz)
{
	EggAction *loc_ent =
		egg_action_group_get_action(kz->actions,"LocationEntry");
	GtkWidget *proxy = NULL;
	if(loc_ent)
		proxy = GTK_COMBO(gtk_bin_get_child(GTK_BIN(loc_ent->proxies->data)))->entry;
	if(proxy)
		gtk_widget_grab_focus(proxy);
}

static void
act_clear_loc_ent (EggAction *action, KzWindow *kz)
{
	EggAction *loc_ent = egg_action_group_get_action(kz->actions, "LocationEntry");
	EggAction *focus_action  = egg_action_group_get_action(kz->actions,
							       "FocusLocationEntry");

	egg_entry_action_set_text(EGG_ENTRY_ACTION(loc_ent), "");
	egg_action_activate(focus_action);
}

static void
act_open_selected_links (EggAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);
	GList *list = NULL, *node;

	if (!KZ_IS_MOZ_EMBED(widget)) return;

	kz_moz_embed_get_links(KZ_MOZ_EMBED(widget), &list, TRUE);

	for (node = list; node; node = g_list_next(node))
	{
		KzLink *link = node->data;

		if (!link) continue;
		if (!link->url) continue;
		if (kz_link_filter(link)) continue;

		kz_window_open_new_tab_with_parent(KZ_WINDOW(kz), link->url,
						   widget);
	}

	g_list_foreach(list, (GFunc) kz_link_unref, NULL);
	g_list_free(list);
}


static void
act_back (EggAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);

	g_return_if_fail(KZ_IS_WINDOW(kz));

	if (KZ_IS_MOZ_EMBED(widget))
		kz_moz_embed_go_back(KZ_MOZ_EMBED(widget));
}


static void
act_forward (EggAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);

	g_return_if_fail(KZ_IS_WINDOW(kz));

	if (KZ_IS_MOZ_EMBED(widget))
		kz_moz_embed_go_forward(KZ_MOZ_EMBED(widget));
}


/*
static void
act_show_history_menu (EggAction *action, KzWindow *kz)
{
	int pos, count;
	int i;
	GtkWidget *menu;
	KzBookmark *history;
	KzMozEmbed *kzembed = KZ_MOZ_EMBED(KZ_WINDOW_CURRENT_PAGE(kz));

	history = kz_bookmark_pure_folder_new();
	kz_bookmark_set_title(history, _("History"));

	kz_moz_embed_shistory_get_pos(kzembed, &pos, &count);

	menu = kz_bookmark_menu_create_submenu(history,
					       kz);
	
	for (i = 0; i < count; i++)
	{
		KzBookmark *bookmark;
		gchar *title, *url;
	
		kz_moz_embed_shistory_get_nth (kzembed, i, FALSE,
					       &url, &title);
		bookmark = kz_bookmark_new_with_attrs(title, uri, NULL);
		kz_bookmark_prepend(history, bookmark);
		g_object_unref(bookmark);	
	}
	gtk_widget_show(menu);
	kz_actions_popup_bookmark_menu_modal(kz, history,
					     NULL,
					     NULL);
}
*/

static void
act_go_up (EggAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);

	g_return_if_fail(KZ_IS_WINDOW(kz));

	if (KZ_IS_MOZ_EMBED(widget))
		kz_moz_embed_go_up(KZ_MOZ_EMBED(widget));
}


static void
act_go_location (EggAction *action, KzWindow *kz)
{
	EggAction *entry;

	g_return_if_fail(KZ_IS_WINDOW(kz));	

	entry = egg_action_group_get_action(kz->actions, "LocationEntry");
        egg_action_activate(entry);
}


static void
act_index (EggAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);

	g_return_if_fail(KZ_IS_WINDOW(kz));

	if (KZ_IS_MOZ_EMBED(widget))
		kz_moz_embed_go_index(KZ_MOZ_EMBED(widget));
}


static void
act_contents (EggAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);

	g_return_if_fail(KZ_IS_WINDOW(kz));

	if (KZ_IS_MOZ_EMBED(widget))
		kz_moz_embed_go_contents(KZ_MOZ_EMBED(widget));
}


static void
act_start (EggAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);

	g_return_if_fail(KZ_IS_WINDOW(kz));

	if (KZ_IS_MOZ_EMBED(widget))
		kz_moz_embed_go_start(KZ_MOZ_EMBED(widget));
}


static void
act_prev (EggAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);

	g_return_if_fail(KZ_IS_WINDOW(kz));

	if (KZ_IS_MOZ_EMBED(widget))
		kz_moz_embed_go_prev(KZ_MOZ_EMBED(widget));
}


static void
act_next (EggAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);

	g_return_if_fail(KZ_IS_WINDOW(kz));

	if (KZ_IS_MOZ_EMBED(widget))
		kz_moz_embed_go_next(KZ_MOZ_EMBED(widget));
}


static void 
act_stop (EggAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);

	g_return_if_fail(KZ_IS_WINDOW(kz));

	if (KZ_IS_MOZ_EMBED(widget))
		kz_moz_embed_stop_load(KZ_MOZ_EMBED(widget));
}


static void
act_reload  (EggAction *action, KzWindow *kz)
{
	GdkModifierType state = (GdkModifierType)0;
	gint x, y;
	GtkWidget *widget;

	g_return_if_fail(KZ_IS_WINDOW(kz));

	gdk_window_get_pointer(NULL, &x, &y, &state);

	widget = KZ_WINDOW_CURRENT_PAGE(kz);

	if (KZ_IS_MOZ_EMBED(widget))
		kz_moz_embed_reload(KZ_MOZ_EMBED(widget),
				    (state & GDK_SHIFT_MASK) ?
				    GTK_MOZ_EMBED_FLAG_RELOADBYPASSPROXYANDCACHE : 
				    GTK_MOZ_EMBED_FLAG_RELOADNORMAL);
}


static void 
act_stop_all (EggAction *action, KzWindow *kz)
{
	gint i, num;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	num = gtkutil_notebook_get_n_pages(GTK_NOTEBOOK(kz->notebook));

	for (i = num - 1; i >= 0; i--)
	{
		GtkWidget *widget = KZ_WINDOW_NTH_PAGE(kz, i);

		if (KZ_IS_MOZ_EMBED(widget))
			kz_moz_embed_stop_load(KZ_MOZ_EMBED(widget));
	}
}

static void
act_show_hide_sidebar(EggAction *action, KzWindow *kz)
{
	gboolean active;
	g_return_if_fail(EGG_IS_TOGGLE_ACTION(action));
	g_return_if_fail(KZ_IS_WINDOW(kz));
	g_return_if_fail(GTK_IS_WIDGET(kz->sidebar));

	active = egg_toggle_action_get_active (EGG_TOGGLE_ACTION(action));
	if (active)
		gtk_widget_show(kz->sidebar);
	else
		gtk_widget_hide(kz->sidebar);

	KZ_WINDOW_SET_VISIBLE(kz, "StockSidebarPosMenu", active);
}

static void
act_reload_all  (EggAction *action, KzWindow *kz)
{
	GdkModifierType state = (GdkModifierType)0;
	gint x, y;
	gint i, num;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	gdk_window_get_pointer(NULL, &x, &y, &state);

	num = gtkutil_notebook_get_n_pages(GTK_NOTEBOOK(kz->notebook));

	for (i = num - 1; i >= 0; i--)
	{
		GtkWidget *widget = KZ_WINDOW_NTH_PAGE(kz, i);

		if (KZ_IS_MOZ_EMBED(widget))
			kz_moz_embed_reload(KZ_MOZ_EMBED(widget),
					    (state & GDK_SHIFT_MASK) ?
					    GTK_MOZ_EMBED_FLAG_RELOADBYPASSCACHE : 
					    GTK_MOZ_EMBED_FLAG_RELOADNORMAL);
	}
}


static void 
act_view_source (EggAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);

	if (!KZ_IS_MOZ_EMBED(widget)) return;
	
	kz_moz_embed_view_source(KZ_MOZ_EMBED(widget));
}


static void
act_search (EggAction *action, KzWindow *kz)
{
	g_return_if_fail(EGG_IS_ACTION(action));
	g_return_if_fail(KZ_IS_WINDOW(kz));

	gtk_widget_grab_focus(kz->find_area);
}


static void
act_prev_tab (EggAction *action, KzWindow *kz)
{
	g_return_if_fail(KZ_IS_WINDOW(kz));

	gtk_notebook_prev_page(GTK_NOTEBOOK(kz->notebook));
}


static void
act_next_tab (EggAction *action, KzWindow *kz)
{
	g_return_if_fail(KZ_IS_WINDOW(kz));

	gtk_notebook_next_page(GTK_NOTEBOOK(kz->notebook));
}


static void
act_preference (EggAction *action, KzWindow *kz)
{
	GtkWidget *widget;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	widget = kz_prefs_win_get_instance();
	gtk_window_set_transient_for (GTK_WINDOW(widget), GTK_WINDOW(kz));
	gtk_widget_show (widget);
	gdk_window_raise(widget->window);
}


static void
act_detaild_preference (EggAction *action, KzWindow *kz)
{
	GtkWidget *widget;
	gint num;

	g_return_if_fail(KZ_IS_WINDOW(kz));

	widget = kz_window_open_new_tab(kz, "about:config");
	num = gtk_notebook_page_num(GTK_NOTEBOOK(kz->notebook), widget);
	gtk_notebook_set_current_page(GTK_NOTEBOOK(kz->notebook), num);
}


static void
act_switch_ui_beginner (EggAction *action, KzWindow *kz)
{
	const gchar *level = "beginner";

	g_return_if_fail(KZ_IS_WINDOW (kz));

	if (!egg_toggle_action_get_active(EGG_TOGGLE_ACTION(action))) return;
	KZ_CONF_SET("Global", "ui_level", level, STRING);
}


static void
act_switch_ui_medium (EggAction *action, KzWindow *kz)
{
	const gchar *level = "medium";

	g_return_if_fail(KZ_IS_WINDOW (kz));

	if (!egg_toggle_action_get_active(EGG_TOGGLE_ACTION(action))) return;
	KZ_CONF_SET("Global", "ui_level", level, STRING);
}


static void
act_switch_ui_expert (EggAction *action, KzWindow *kz)
{
	const gchar *level = "expert";

	g_return_if_fail(KZ_IS_WINDOW (kz));

	if (!egg_toggle_action_get_active(EGG_TOGGLE_ACTION(action))) return;
	KZ_CONF_SET("Global", "ui_level", level, STRING);
}


static void
act_switch_ui_custom (EggAction *action, KzWindow *kz)
{
	const gchar *level = "custom";

	g_return_if_fail(KZ_IS_WINDOW (kz));

	KZ_CONF_SET("Global", "ui_level", level, STRING);
}


static void
act_cut (EggAction *action, KzWindow *kz)
{
	GtkWidget *widget;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	widget = gtk_window_get_focus(GTK_WINDOW(kz));

        if (GTK_IS_EDITABLE (widget))
        {
                gtk_editable_cut_clipboard (GTK_EDITABLE (widget));
        }
        else
        {
                KzMozEmbed *kzembed;

                kzembed = KZ_MOZ_EMBED(KZ_WINDOW_CURRENT_PAGE (kz));
                if (!KZ_IS_MOZ_EMBED(kzembed)) return;
                kz_moz_embed_cut_selection (kzembed);
        }
}


static void
act_copy (EggAction *action, KzWindow *kz)
{
	GtkWidget *widget;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	widget = gtk_window_get_focus(GTK_WINDOW(kz));

        if (GTK_IS_EDITABLE (widget))
        {
                gtk_editable_copy_clipboard (GTK_EDITABLE (widget));
        }
        else
        {
                KzMozEmbed *kzembed;

                kzembed = KZ_MOZ_EMBED(KZ_WINDOW_CURRENT_PAGE (kz));
                if (!KZ_IS_MOZ_EMBED(kzembed)) return;
                kz_moz_embed_copy_selection (kzembed);
        }
}


static void
act_paste (EggAction *action, KzWindow *kz)
{
	GtkWidget *widget;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	widget = gtk_window_get_focus(GTK_WINDOW(kz));

        if (GTK_IS_EDITABLE (widget))
        {
                gtk_editable_paste_clipboard (GTK_EDITABLE (widget));
        }
        else
        {
                KzMozEmbed *kzembed;

                kzembed = KZ_MOZ_EMBED(KZ_WINDOW_CURRENT_PAGE (kz));
                if (!KZ_IS_MOZ_EMBED(kzembed)) return;
                kz_moz_embed_paste (kzembed);
        }
}


static void
act_select_all (EggAction *action, KzWindow *kz)
{
	GtkWidget *widget;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	widget = gtk_window_get_focus(GTK_WINDOW(kz));

        if (GTK_IS_EDITABLE (widget))
        {
                gtk_editable_select_region (GTK_EDITABLE (widget), 0, -1);
        }
        else
        {
                KzMozEmbed *kzembed;

                kzembed = KZ_MOZ_EMBED(KZ_WINDOW_CURRENT_PAGE (kz));
                if (!KZ_IS_MOZ_EMBED(kzembed)) return;
                kz_moz_embed_select_all (kzembed);
        }
}


static void
act_copy_title (EggAction *action, KzWindow *kz)
{
	GtkWidget *widget;
	const gchar *text;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	widget = KZ_WINDOW_CURRENT_PAGE(kz);
	if (!KZ_IS_MOZ_EMBED(widget)) return;

	text = kz_moz_embed_get_title(KZ_MOZ_EMBED(widget));
	gtkutil_copy_text(text);
}


static void
act_copy_url (EggAction *action, KzWindow *kz)
{
	GtkWidget *widget;
	const gchar *text;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	widget = KZ_WINDOW_CURRENT_PAGE(kz);
	if (!KZ_IS_MOZ_EMBED(widget)) return;

	text = kz_moz_embed_get_location(KZ_MOZ_EMBED(widget));
	gtkutil_copy_text(text);
}


static void
act_tab_top (EggAction *action, KzWindow *kz)
{
	g_return_if_fail(KZ_IS_WINDOW (kz));
	gtk_notebook_set_tab_pos(GTK_NOTEBOOK(kz->notebook), GTK_POS_TOP);
}


static void
act_tab_bottom (EggAction *action, KzWindow *kz)
{
	g_return_if_fail(KZ_IS_WINDOW (kz));
	gtk_notebook_set_tab_pos(GTK_NOTEBOOK(kz->notebook), GTK_POS_BOTTOM);
}


static void
act_tab_left (EggAction *action, KzWindow *kz)
{
	g_return_if_fail(KZ_IS_WINDOW (kz));
	gtk_notebook_set_tab_pos(GTK_NOTEBOOK(kz->notebook), GTK_POS_LEFT);
}


static void
act_tab_right (EggAction *action, KzWindow *kz)
{
	g_return_if_fail(KZ_IS_WINDOW (kz));
	gtk_notebook_set_tab_pos(GTK_NOTEBOOK(kz->notebook), GTK_POS_RIGHT);
}


static void
act_tab_close_backward_all (EggAction *action, KzWindow *kz)
{
	gint i, pos, num;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	pos = gtk_notebook_get_current_page(GTK_NOTEBOOK(kz->notebook));
	num = gtkutil_notebook_get_n_pages(GTK_NOTEBOOK(kz->notebook));

	for (i = pos - 1; i >= 0; i--)
	{
		GtkWidget *widget = KZ_WINDOW_NTH_PAGE(kz, i);

		kz_window_close_tab(kz, widget);
	}
}


static void
act_tab_close_forward_all (EggAction *action, KzWindow *kz)
{
	gint i, pos, num;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	pos = gtk_notebook_get_current_page(GTK_NOTEBOOK(kz->notebook));
	num = gtkutil_notebook_get_n_pages(GTK_NOTEBOOK(kz->notebook));

	for (i = num - 1; i > pos; i--)
	{
		GtkWidget *widget = KZ_WINDOW_NTH_PAGE(kz, i);

		kz_window_close_tab(kz, widget);
	}
}


static void
act_tab_close_all_without_active (EggAction *action, KzWindow *kz)
{
	gint i, pos, num;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	pos = gtk_notebook_get_current_page(GTK_NOTEBOOK(kz->notebook));
	num = gtkutil_notebook_get_n_pages(GTK_NOTEBOOK(kz->notebook));

	for (i = num - 1; i >= 0; i--)
	{
		GtkWidget *widget = KZ_WINDOW_NTH_PAGE(kz, i);

		if (i == pos) continue;
		kz_window_close_tab(kz, widget);
	}
}


static void
act_bookmark_in_new_tab (EggAction *action, KzWindow *kz)
{
	KzBookmark *bookmark;
	const gchar *uri;

	bookmark = kz_actions_get_bookmark_for_action(kz);
	g_return_if_fail(KZ_IS_BOOKMARK(bookmark));

	uri = kz_bookmark_get_link(bookmark);
	if (uri)
		kz_window_open_new_tab(kz, uri);
}


static void
open_all_bookmarks(KzWindow *kz, KzBookmark *folder, GtkWidget *parent,
		   gboolean recurse)
{
	GList *children, *node;
	const gchar *uri;

	folder = kz_actions_get_bookmark_for_action(kz);
	g_return_if_fail(KZ_IS_BOOKMARK(folder));
	g_return_if_fail(kz_bookmark_is_folder(folder));

	children = kz_bookmark_get_children(folder);
	for (node = children; node; node = g_list_next(node))
	{
		KzBookmark *item = node->data;
		GtkWidget *widget = parent;

		uri = kz_bookmark_get_link(item);
		if (uri)
			widget = kz_window_open_new_tab_with_parent(kz, uri,
								    parent);

		if (kz_bookmark_is_folder(item) && recurse)
			open_all_bookmarks(kz, item, widget, recurse);
	}
	g_list_free(children);
}


static void
act_open_all_bookmarks (EggAction *action, KzWindow *kz)
{
	KzBookmark *folder;
	GtkWidget *parent = NULL;
	const gchar *uri;

	folder = kz_actions_get_bookmark_for_action(kz);
	g_return_if_fail(KZ_IS_BOOKMARK(folder));
	g_return_if_fail(kz_bookmark_is_folder(folder));

	uri = kz_bookmark_get_link(folder);
	if (uri)
		parent = kz_window_open_new_tab_with_parent(kz, uri, parent);

	open_all_bookmarks(kz, folder, parent, FALSE);
}


static void
act_open_all_bookmarks_recursive (EggAction *action, KzWindow *kz)
{
	KzBookmark *folder;
	GtkWidget *parent = NULL;
	const gchar *uri;

	folder = kz_actions_get_bookmark_for_action(kz);
	g_return_if_fail(KZ_IS_BOOKMARK(folder));
	g_return_if_fail(kz_bookmark_is_folder(folder));

	uri = kz_bookmark_get_link(folder);
	if (uri)
		parent = kz_window_open_new_tab_with_parent(kz, uri, parent);

	open_all_bookmarks(kz, folder, parent, TRUE);
}


static void
act_add_bookmark (EggAction *action, KzWindow *kz)
{
	KzBookmark *folder, *bookmark, *sibling = NULL;
	GtkWidget *widget;
	const gchar *title, *uri;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	folder = kz_actions_get_bookmark_for_action(kz);
	g_return_if_fail(KZ_IS_BOOKMARK(folder));

	if (!kz_bookmark_is_folder(folder))
	{
		sibling = folder;
		folder = kz_bookmark_get_parent(folder);
		g_return_if_fail(KZ_IS_BOOKMARK(folder));
	}

	widget = KZ_WINDOW_CURRENT_PAGE(kz);
	if (!KZ_IS_MOZ_EMBED(widget)) return;

	title = kz_moz_embed_ensure_title(KZ_MOZ_EMBED(widget));
	uri   = kz_moz_embed_get_location(KZ_MOZ_EMBED(widget));

	if (!uri) return;

	bookmark = kz_bookmark_new_with_attrs(title, uri, NULL);
	/* FIXME! show dialog */
	if (sibling)
		kz_bookmark_insert_before(folder, bookmark, sibling);
	else
		kz_bookmark_append(folder, bookmark);
	if (kz_bookmark_is_file(folder))
		kz_bookmark_save(folder);
	g_object_unref(G_OBJECT(bookmark));
}


static void
act_remove_bookmark (EggAction *action, KzWindow *kz)
{
	KzBookmark *folder, *bookmark;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	bookmark = kz_actions_get_bookmark_for_action(kz);
	g_return_if_fail(KZ_IS_BOOKMARK(bookmark));

	folder = kz_bookmark_get_parent(bookmark);
	g_return_if_fail(KZ_IS_BOOKMARK(folder));

	kz_bookmark_remove(folder, bookmark);
	if (kz_bookmark_is_file(folder))
		kz_bookmark_save(folder);
}


static void
act_edit_bookmark (EggAction *action, KzWindow *kz)
{
	KzBookmark *folder;
	GtkWidget *widget;

	folder = kz_actions_get_bookmark_for_action(kz);
	g_return_if_fail(KZ_IS_BOOKMARK(folder));

	if (kz_bookmark_is_folder(folder))
	{
		widget = kz_bookmark_editor_new(folder);
		gtk_window_set_transient_for (GTK_WINDOW(widget), GTK_WINDOW(kz));
		gtk_widget_show (widget);
		gdk_window_raise(widget->window);
	}
	else
	{
		g_warning("Implement me!");
	}
}


static void
act_update_bookmark (EggAction *action, KzWindow *kz)
{
	KzBookmark *folder;

	folder = kz_actions_get_bookmark_for_action(kz);
	g_return_if_fail(KZ_IS_BOOKMARK(folder));
	g_return_if_fail(kz_bookmark_is_folder(folder));

	kz_bookmark_load_start(folder);
}


static void
act_extract_links (EggAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);
	GtkWidget *dialog;

	if (!GTK_IS_MOZ_EMBED(widget)) return;

	dialog = kz_links_dialog_new(kz, KZ_MOZ_EMBED(widget), FALSE);
	gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(kz));
	gtk_widget_show(dialog);
}


static void
act_extract_selected_links (EggAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);
	GtkWidget *dialog;

	if (!GTK_IS_MOZ_EMBED(widget)) return;

	dialog = kz_links_dialog_new(kz, KZ_MOZ_EMBED(widget), TRUE);
	gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(kz));
	gtk_widget_show(dialog);
}


static gchar *
get_current_session_name (void)
{
	gchar *current_session;

	current_session = KZ_CONF_GET_STR("Session", "current_session");
	if (!current_session)
	{
		current_session = g_strdup("DefaultSession");
	}
	else if (!*current_session)
	{
		g_free(current_session);
		current_session = g_strdup("DefaultSession");
	}

	return current_session;
}


static void
act_save_session (EggAction *action, KzWindow *kz)
{
	GList *list, *node;
	gchar *current_session;
	gint n_pages, i, pos;

	/* get current session name */
	current_session = get_current_session_name();

	/* clean saved session */
	list = kz_profile_enum_key(kz_session, current_session);
	for (node = list; node; node = g_list_next(node))
		kz_profile_delete_key(kz_session, current_session, node->data);
	g_list_free(list);

	/* save opened URIs */
	n_pages = gtkutil_notebook_get_n_pages(GTK_NOTEBOOK(kz->notebook));
	for (i = 0; i < n_pages; i++)
	{
		GtkWidget *widget = GTK_WIDGET(KZ_WINDOW_NTH_PAGE(kz, i));
		KzTabLabel *kztab;
		const gchar *uri;
		gboolean locked;
		gchar key[32], lockkey[32];

		if (!KZ_IS_MOZ_EMBED(widget)) continue;
		
		g_snprintf(key, G_N_ELEMENTS(key), "tab%d", i);

		uri = kz_moz_embed_get_location(KZ_MOZ_EMBED(widget));
		kz_profile_set_value(kz_session, current_session,
				     key, uri, sizeof(uri),
				     KZ_PROFILE_VALUE_TYPE_STRING);
		
		/* tab lock state */
		kztab = KZ_TAB_LABEL(gtk_notebook_get_tab_label(GTK_NOTEBOOK(kz->notebook),
								widget));
		locked = kz_tab_label_get_lock(kztab);
		g_snprintf(lockkey, G_N_ELEMENTS(lockkey), "lock%d", i);
		kz_profile_set_value(kz_session, current_session,
				     lockkey, &locked, sizeof(locked),
				     KZ_PROFILE_VALUE_TYPE_BOOL);
	}

	pos = gtk_notebook_get_current_page(GTK_NOTEBOOK(kz->notebook));
	kz_profile_set_value(kz_session, current_session,
			     "current_tab", &pos, sizeof(pos),
			     KZ_PROFILE_VALUE_TYPE_INT);

	g_free(current_session);
}


static void
act_restore_session (EggAction *action, KzWindow *kz)
{
	GList *list, *node;
	gchar *current_session;
	gint i, num, pos = 0;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	num = gtkutil_notebook_get_n_pages(GTK_NOTEBOOK(kz->notebook));
	for (i = num - 1; i >= 0; i--)
	{
		GtkWidget *widget = KZ_WINDOW_NTH_PAGE(kz, i);
		kz_window_close_tab(kz, widget);
	}

	/* get current session name */
	current_session = get_current_session_name();

	/* open saved URIs */
	i = 0;
	list = kz_profile_enum_key(kz_session, current_session);
	for (node = list; node; node = g_list_next(node))
	{
		const gchar *key = node->data;
		gchar *uri;

		if (!key_seems_sequential(key, "tab")) continue;

		uri = kz_profile_get_string(kz_session, current_session, key);
		kz_window_open_new_tab(kz, uri);
		g_free(uri);
		/*
		 * gtk_notebook_append_page() always emits 
		 * "switch-page" signal with page num which is 0 value, so
		 * we should call gtk_notebook_set_current_page with correct page number.
 		 */
		gtk_notebook_set_current_page(GTK_NOTEBOOK(kz->notebook), i);
		i++;
	}
	i = 0;
	/* set locked tab */
	for (node = list; node; node = g_list_next(node))
	{
		const gchar *key = node->data;
		gboolean locked;

		if (!key_seems_sequential(key, "lock")) continue;

		kz_profile_get_value(kz_session, current_session, key,
				     &locked, sizeof(locked),
				     KZ_PROFILE_VALUE_TYPE_BOOL);
		if (locked)
		{
			GtkWidget *child;
			KzTabLabel *kztab;
			child = KZ_WINDOW_NTH_PAGE(kz, i);
			kztab = KZ_TAB_LABEL(gtk_notebook_get_tab_label(GTK_NOTEBOOK(kz->notebook),
									child));
			kz_tab_label_set_lock(kztab, TRUE);
		}
		i++;
	}
	g_list_free(list);

	kz_profile_get_value(kz_session, current_session,
			     "current_tab", &pos, sizeof(pos),
			     KZ_PROFILE_VALUE_TYPE_INT);
	gtk_notebook_set_current_page(GTK_NOTEBOOK(kz->notebook), pos);

	g_free(current_session);
}


static void
act_about (EggAction *action, KzWindow *kz)
{
	g_return_if_fail(KZ_IS_WINDOW(kz));
	kz_about_dialog_new(kz);
}


static void
act_copy_tab (EggAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);
	KzMozEmbed *kzembed, *dkzembed;

	g_return_if_fail(KZ_IS_WINDOW(kz));
	g_return_if_fail(KZ_IS_MOZ_EMBED(widget));
	
	kzembed  = KZ_MOZ_EMBED(widget);	
	dkzembed = KZ_MOZ_EMBED(kz_window_open_new_tab(kz, NULL));

	kz_moz_embed_copy_page(kzembed, dkzembed);
	kz_moz_embed_shistory_copy(kzembed, dkzembed, TRUE, TRUE, TRUE);
}


static void
act_paned_left (EggAction *action, KzWindow *kz)
{
	g_return_if_fail(KZ_IS_WINDOW(kz));

	kz_paned_set_position(KZ_PANED(kz->pane), GTK_POS_LEFT);
}


static void
act_paned_right (EggAction *action, KzWindow *kz)
{
	g_return_if_fail(KZ_IS_WINDOW(kz));

	kz_paned_set_position(KZ_PANED(kz->pane), GTK_POS_RIGHT);
}


static void
act_paned_top (EggAction *action, KzWindow *kz)
{
	g_return_if_fail(KZ_IS_WINDOW(kz));

	kz_paned_set_position(KZ_PANED(kz->pane), GTK_POS_TOP);
}


static void
act_paned_bottom (EggAction *action, KzWindow *kz)
{
	g_return_if_fail(KZ_IS_WINDOW(kz));

	kz_paned_set_position(KZ_PANED(kz->pane), GTK_POS_BOTTOM);
}


#define CTRL "<control>"
#define SHFT "<shift>"
#define SFCT "<shift><control>"
#define ALT  "<alt>"
EggActionGroupEntry kz_actions[] =
{
  {"StockFileMenu",        N_("_File"),       NULL, NULL, NULL, NULL, NULL},
  {"StockEditMenu",        N_("_Edit"),       NULL, NULL, NULL, NULL, NULL},
  {"StockViewMenu",        N_("_View"),       NULL, NULL, NULL, NULL, NULL},
  {"StockTabMenu",         N_("_Tab"),        NULL, NULL, NULL, NULL, NULL},
  {"StockGoMenu",          N_("_Go"),         NULL, NULL, NULL, NULL, NULL},
  {"StockBookmarksMenu",   N_("_Bookmarks"),  NULL, NULL, NULL, NULL, NULL},
  {"StockToolsMenu",       N_("Too_ls"),      NULL, NULL, NULL, NULL, NULL},
  {"StockHelpMenu",        N_("_Help"),       NULL, NULL, NULL, NULL, NULL},
  {"StockUILevelMenu",     N_("UI Level"),    NULL, NULL, NULL, NULL, NULL},
  {"StockTabPosMenu",      N_("Tab _position"),    NULL, NULL, NULL, NULL, NULL},
  {"StockSidebarPosMenu",  N_("Sidebar position"), NULL, NULL, NULL, NULL, NULL},
  {"StockInputMethodMenu", N_("Input Methods"),    NULL, NULL, NULL, NULL, NULL},
  {"StockSessionMenu",     N_("Session"),     NULL, NULL, NULL, NULL, NULL},
  {"StockProxyMenu",       N_("Proxy"),       NULL, NULL, NULL, NULL, NULL},
  { "FakeToplevel",       (""),                 NULL, NULL, NULL, NULL, NULL },

  {"NewWindow",     N_("_New Window"),    GTK_STOCK_NEW,        CTRL"N",  NULL, G_CALLBACK(act_new_window),   NULL},
  {"NewTab",        N_("New _Tab"),       GTK_STOCK_NEW,        CTRL"T",  NULL, G_CALLBACK(act_new_tab),      NULL},

  {"FocusLocationEntry",        N_("Move keyboard focus to location entry"),  NULL, NULL, NULL, G_CALLBACK(act_focus_loc_ent),      NULL},
  {"ClearLocationEntry",        N_("Clear location entry and move keyboard focus to location entry"),  NULL, NULL, NULL, G_CALLBACK(act_clear_loc_ent),      NULL},

  {"OpenSelectedLinks", N_("Open selected links"), GTK_STOCK_OPEN, CTRL"G",  NULL, G_CALLBACK(act_open_selected_links), NULL},

  {"CloseWindow",   N_("_Close Window"),  GTK_STOCK_CLOSE,      CTRL"Q",  NULL, G_CALLBACK(act_close_window), NULL},
  {"CloseTab",      N_("Close Ta_b"),     GTK_STOCK_CLOSE,      CTRL"W",  NULL, G_CALLBACK(act_close_tab),    NULL},

  {"SavePage",      N_("Save A_s"),     GTK_STOCK_SAVE_AS,      CTRL"S",  NULL, G_CALLBACK(act_save),    NULL},
	
  {"Cut",           N_("C_ut"),        GTK_STOCK_CUT,  CTRL"X", NULL, G_CALLBACK(act_cut),        NULL},
  {"Copy",          N_("_Copy"),       GTK_STOCK_COPY, CTRL"C", NULL, G_CALLBACK(act_copy),       NULL},
  {"Paste",         N_("_Paste"),      GTK_STOCK_PASTE,CTRL"V", NULL, G_CALLBACK(act_paste),      NULL},
  {"SelectAll",     N_("Select _All"), NULL,           CTRL"A", NULL, G_CALLBACK(act_select_all), NULL},
  {"CopyTitle",     N_("Copy _Title"), GTK_STOCK_COPY, NULL,    NULL, G_CALLBACK(act_copy_title), NULL},
  {"CopyURL",       N_("Copy _URL"),   GTK_STOCK_COPY, NULL,    NULL, G_CALLBACK(act_copy_url),   NULL},
  {"Preference",    N_("_Preference..."), GTK_STOCK_PREFERENCES,NULL,     NULL, G_CALLBACK(act_preference),   NULL},
  {"DetailedPreference", N_("_Detailed Preference"), GTK_STOCK_PREFERENCES,NULL, NULL, G_CALLBACK(act_detaild_preference), NULL},

  {"Back",          N_("_Back"),          GTK_STOCK_GO_BACK,    ALT"Left",  NULL, G_CALLBACK(act_back),         NULL},
  {"Forward",       N_("_Forward"),       GTK_STOCK_GO_FORWARD, ALT"Right", NULL, G_CALLBACK(act_forward),      NULL},
  {"Reload",        N_("_Reload"),        GTK_STOCK_REFRESH,    CTRL"R",  NULL, G_CALLBACK(act_reload),       NULL},

  {"GoUp",          N_("Go _Up"),         GTK_STOCK_GO_UP,      ALT"Up",  NULL, G_CALLBACK(act_go_up),         NULL},
  {"GotoLocation",  N_("Go to _Location"),GTK_STOCK_JUMP_TO,    NULL,  NULL, G_CALLBACK(act_go_location),         NULL},

  {"Index",         N_("Index"),         GTK_STOCK_INDEX,      NULL, NULL, G_CALLBACK(act_index),    NULL},
  {"Contents",      N_("Contents"),      GTK_STOCK_GOTO_TOP,   NULL, NULL, G_CALLBACK(act_contents), NULL},
  {"Start",         N_("Start"),         GTK_STOCK_GOTO_FIRST, NULL, NULL, G_CALLBACK(act_start)   , NULL},
  {"Prev",          N_("Prev"),          GTK_STOCK_GO_BACK,    NULL, NULL, G_CALLBACK(act_prev),     NULL},
  {"Next",          N_("Next"),          GTK_STOCK_GO_FORWARD, NULL, NULL, G_CALLBACK(act_next),     NULL},

  {"Stop",          N_("_Stop"),          GTK_STOCK_STOP,       "Escape", NULL, G_CALLBACK(act_stop),         NULL},
  {"ReloadAll",     N_("Reload all"),     GTK_STOCK_REFRESH,    NULL,     NULL, G_CALLBACK(act_reload_all),   NULL},
  {"StopAll",       N_("Stop all"),       GTK_STOCK_STOP,       NULL,     NULL, G_CALLBACK(act_stop_all),     NULL},

  {"ViewPageSource", N_("ViewPageSource"), NULL, NULL, NULL, G_CALLBACK(act_view_source), NULL},

  {"ShowHideSidebar", N_("Sidebar"), NULL, NULL, NULL, G_CALLBACK(act_show_hide_sidebar), NULL, TOGGLE_ACTION},
  {"SidebarPosTop",   N_("Sidebar _Top"),    NULL, NULL, NULL, G_CALLBACK(act_paned_top),    NULL, RADIO_ACTION, NULL},
  {"SidebarPosBottom",N_("Sidebar _Bottom"), NULL, NULL, NULL, G_CALLBACK(act_paned_bottom), NULL, RADIO_ACTION, "SidebarPosTop"},
  {"SidebarPosLeft",  N_("Sidebar _Left"),   NULL, NULL, NULL, G_CALLBACK(act_paned_left),   NULL, RADIO_ACTION, "SidebarPosBottom"},
  {"SidebarPosRight", N_("Sidebar _Right"),  NULL, NULL, NULL, G_CALLBACK(act_paned_right),  NULL, RADIO_ACTION, "SidebarPosLeft"},

  {"UILevelBeginner", N_("Beginner"), NULL, NULL, NULL, G_CALLBACK(act_switch_ui_beginner), NULL, RADIO_ACTION, NULL},
  {"UILevelMedium",   N_("Medium"),   NULL, NULL, NULL, G_CALLBACK(act_switch_ui_medium),   NULL, RADIO_ACTION, "UILevelBeginner"},
  {"UILevelExpert",   N_("Expert"),   NULL, NULL, NULL, G_CALLBACK(act_switch_ui_expert),   NULL, RADIO_ACTION, "UILevelMedium"},
  {"UILevelCustom",   N_("Custom"),   NULL, NULL, NULL, G_CALLBACK(act_switch_ui_custom),   NULL, RADIO_ACTION, "UILevelExpert"},

/*
  {"LocationEntry", N_("Location Entry"), GTK_STOCK_NEW,        NULL,     NULL, G_CALLBACK(act_location_enter), NULL, HISTORY_ACTION},
*/

  {"Search",        N_("Search"),         NULL,                 CTRL"F",  NULL, G_CALLBACK(act_search),       NULL},
  {"PrevTab",       N_("_Previous Tab"),      GTK_STOCK_GO_BACK,    ALT"L",   NULL, G_CALLBACK(act_prev_tab),     NULL},
  {"NextTab",       N_("_Next Tab"),     GTK_STOCK_GO_FORWARD, ALT"R",   NULL, G_CALLBACK(act_next_tab),    NULL},

  {"CopyTab",       N_("_Copy Tab"),   NULL, NULL, NULL, G_CALLBACK(act_copy_tab), NULL},

  {"TabPosTop",     N_("Tab _Top"),    NULL, NULL, NULL, G_CALLBACK(act_tab_top),    NULL, RADIO_ACTION, NULL},
  {"TabPosBottom",  N_("Tab _Bottom"), NULL, NULL, NULL, G_CALLBACK(act_tab_bottom), NULL, RADIO_ACTION, "TabPosTop"},
  {"TabPosLeft",    N_("Tab _Left"),   NULL, NULL, NULL, G_CALLBACK(act_tab_left),   NULL, RADIO_ACTION, "TabPosBottom"},
  {"TabPosRight",   N_("Tab _Right"),  NULL, NULL, NULL, G_CALLBACK(act_tab_right),  NULL, RADIO_ACTION, "TabPosLeft"},

  {"CloseAllBackwardTab",  N_("Close all _backward tabs"),  GTK_STOCK_CLOSE, NULL, NULL, G_CALLBACK(act_tab_close_backward_all),  NULL},
  {"CloseAllForwardTab", N_("Close all _forward tabs"), GTK_STOCK_CLOSE, NULL, NULL, G_CALLBACK(act_tab_close_forward_all), NULL},
  {"CloseAllTabWithoutActive", N_("Close all tabs without _active"), GTK_STOCK_CLOSE, NULL, NULL, G_CALLBACK(act_tab_close_all_without_active), NULL},

  {"OpenBookmarkInNewTab",      N_("Open the bookmark in new _tab"),   NULL, NULL,  NULL, G_CALLBACK(act_bookmark_in_new_tab), NULL},
  {"OpenAllBookmarks",          N_("Open a_ll bookmarks"),             NULL, NULL,  NULL, G_CALLBACK(act_open_all_bookmarks),  NULL},
  {"OpenAllBookmarksRecursive", N_("Open all bookmarks _recursively"), NULL, NULL,  NULL, G_CALLBACK(act_open_all_bookmarks_recursive),  NULL},
  {"AddBookmark",               N_("_Add bookmark"),                   NULL, NULL,  NULL, G_CALLBACK(act_add_bookmark),        NULL},
  {"RemoveBookmark",            N_("_Remove the bookmark"),            NULL, NULL,  NULL, G_CALLBACK(act_remove_bookmark),     NULL},
  {"EditBookmarks",             N_("_Edit bookmarks"),                 NULL, NULL,  NULL, G_CALLBACK(act_edit_bookmark),       NULL},
  {"UpdateBookmarkFolder",      N_("_Update bookmark folder"),         NULL, NULL,  NULL, G_CALLBACK(act_update_bookmark),     NULL},

  {"ExtractLinks", N_("_Extract links"), NULL, NULL,  NULL, G_CALLBACK(act_extract_links), NULL},
  {"ExtractSelectedLinks", N_("E_xtract selected links"), NULL, NULL,  NULL, G_CALLBACK(act_extract_selected_links), NULL},

  {"SaveSession",    N_("Save session"),    NULL, NULL, NULL, G_CALLBACK(act_save_session),    NULL},
  {"RestoreSession", N_("Restore session"), NULL, NULL, NULL, G_CALLBACK(act_restore_session), NULL},
  /* {"SaveSessionAs", N_("Save session as ..."),        NULL, NULL, NULL, G_CALLBACK(act_save_session),   NULL}, */
  /* {"DeleteSession", N_("Delete current session"),     NULL, NULL, NULL, G_CALLBACK(act_save_session),   NULL}, */
  /* {"SwitchSession", N_("Switch current session ..."), NULL, NULL, NULL, G_CALLBACK(act_switch_session), NULL}, */
  {"About",        N_("About Kazehakase"),  NULL, NULL, NULL, G_CALLBACK(act_about),      NULL},
};
const gint kz_actions_len = G_N_ELEMENTS(kz_actions);


static void
set_popup_menu_sensitive (KzWindow *kz, KzBookmark *bookmark)
{
	KzBookmark *parent;
	EggAction *action;
	gboolean has_link, is_folder, has_children;
	gboolean is_editable, parent_is_editable, is_file;

	g_return_if_fail(kz && bookmark);

	parent = kz_bookmark_get_parent(bookmark);

	has_link = kz_bookmark_get_link(bookmark) ? TRUE : FALSE;
	is_folder = kz_bookmark_is_folder(bookmark);
	has_children = kz_bookmark_has_children(bookmark);
	is_editable = kz_bookmark_is_editable(bookmark);
	parent_is_editable = parent && kz_bookmark_is_editable(parent)
			   ? TRUE : FALSE;
	is_file = kz_bookmark_is_file(bookmark);

	action = egg_action_group_get_action(kz->actions,
					     "OpenBookmarkInNewTab");
	egg_action_set_sensitive(action, has_link);

	action = egg_action_group_get_action(kz->actions,
					     "OpenAllBookmarks");
	egg_action_set_sensitive(action, is_folder && has_children);

	action = egg_action_group_get_action(kz->actions,
					     "AddBookmark");
	egg_action_set_sensitive(action, (is_folder && is_editable) ||
					 (parent_is_editable));

	action = egg_action_group_get_action(kz->actions,
					     "RemoveBookmark");
	egg_action_set_sensitive(action, parent_is_editable);

	action = egg_action_group_get_action(kz->actions,
					     "EditBookmarks");
	egg_action_set_sensitive(action, is_editable);

	action = egg_action_group_get_action(kz->actions,
					     "UpdateBookmarkFolder");
	egg_action_set_sensitive(action, is_file);
}


static void
combine_favicon(EggAction *action, const gchar *uri, KzWindow *kz)
{
	GtkWidget *widget;
	GSList *node;
	KzFavicon *kzfav = kz->kzfav;

	for (node = action->proxies; node; node = g_slist_next(node))
	{
		GtkWidget *image;
		GdkPixbuf *favicon = NULL;
		if (!GTK_IS_WIDGET(node->data))
			continue;

		widget = GTK_WIDGET(node->data);
		
		if (!GTK_IS_IMAGE_MENU_ITEM(widget) && 
		    !EGG_IS_TOOL_BUTTON(widget))
			continue;

		if (GTK_IS_IMAGE_MENU_ITEM(widget))
		{
			favicon = kz_favicon_get_pixbuf(kzfav, uri,
							GTK_ICON_SIZE_MENU);
			image = gtk_image_menu_item_get_image(GTK_IMAGE_MENU_ITEM(widget));
			gtkutil_superpose_pixbuf(image, favicon,
						 action->stock_id,
						 GTK_ICON_SIZE_MENU);
		}
		else if (EGG_IS_TOOL_BUTTON(widget))
		{
			favicon = kz_favicon_get_pixbuf(kzfav, uri,
							GTK_ICON_SIZE_BUTTON);
			image = EGG_TOOL_BUTTON(widget)->icon;
			gtkutil_superpose_pixbuf(image, favicon,
						 action->stock_id,
						 GTK_ICON_SIZE_BUTTON);
		}
		if (favicon)
			g_object_unref(favicon);
	}
}


void
kz_actions_set_selection_sensitive (KzWindow *kz, KzMozEmbed *kzembed)
{
	GtkWidget *focus;
	gboolean can_copy = FALSE, can_cut = FALSE, can_paste = FALSE;

	focus = gtk_window_get_focus(GTK_WINDOW(kz));

#warning FIXME! /* should track all GtkEditable's event and Mozilla's selection */
	if (kzembed && !kz_moz_embed_selection_is_collapsed(kzembed))
	{
		KZ_WINDOW_SET_SENSITIVE(kz, "OpenSelectedLinks", TRUE);
	}
	else
	{
		KZ_WINDOW_SET_SENSITIVE(kz, "OpenSelectedLinks", FALSE);
	}

	if (GTK_IS_EDITABLE(focus))
	{
		gboolean selected = FALSE;
		selected = gtk_editable_get_selection_bounds
				(GTK_EDITABLE(focus), NULL, NULL);
		if (selected)
		{
			can_cut   = TRUE;
			can_copy  = TRUE;
		}
		can_paste = TRUE;
	}
	else if (KZ_IS_MOZ_EMBED(kzembed))
	{
		can_cut   = kz_moz_embed_can_cut_selection(kzembed);
		can_copy  = kz_moz_embed_can_copy_selection(kzembed);
		can_paste = kz_moz_embed_can_paste(kzembed);
	}

	KZ_WINDOW_SET_SENSITIVE(kz, "Cut",   can_cut);
	KZ_WINDOW_SET_SENSITIVE(kz, "Copy",  can_copy);
	KZ_WINDOW_SET_SENSITIVE(kz, "Paste", can_paste);	
}


void
kz_actions_set_sensitive (KzWindow *kz, KzMozEmbed *kzembed)
{
	KzTabLabel *kztab;
	gboolean can_go_back = FALSE;
	gboolean can_go_forward = FALSE;
	gboolean can_go_up = FALSE;
	gboolean can_stop = FALSE;
	gboolean can_stop_all = FALSE;
	gboolean can_go_index = FALSE, can_go_contents = FALSE,
		 can_go_start = FALSE, can_go_prev = FALSE, can_go_next = FALSE;
	gboolean can_close_tab = TRUE;
	gint i, num, pos = 0;
	EggAction *action;
	gboolean active;

	g_return_if_fail (KZ_IS_WINDOW(kz));
	/* g_return_if_fail (KZ_IS_MOZ_EMBED (kzembed)); */

	num = gtkutil_notebook_get_n_pages(GTK_NOTEBOOK(kz->notebook));

	if (kzembed)
	{
		kztab = KZ_TAB_LABEL(kz_window_get_tab_label(kz, GTK_WIDGET(kzembed)));

		can_stop        = kz_moz_embed_is_loading(kzembed);
		can_go_back     = kz_moz_embed_can_go_back(kzembed);
		can_go_forward  = kz_moz_embed_can_go_forward(kzembed);
		can_go_up       = kz_moz_embed_can_go_up(kzembed);
		can_go_index    = kz_moz_embed_can_go_index(kzembed);
		can_go_contents = kz_moz_embed_can_go_contents(kzembed);
		can_go_start    = kz_moz_embed_can_go_start(kzembed);
		can_go_prev     = kz_moz_embed_can_go_prev(kzembed);
		can_go_next     = kz_moz_embed_can_go_next(kzembed);
		
		can_close_tab = !kz_tab_label_get_lock(kztab);

		pos = gtk_notebook_page_num(GTK_NOTEBOOK(kz->notebook),
					    GTK_WIDGET(kzembed));
		for (i = 0; i< num; i++)
		{
			GtkWidget *widget;

			widget = KZ_WINDOW_NTH_PAGE(kz, i);
			if (!KZ_IS_MOZ_EMBED(widget)) continue;
			can_stop_all
				= kz_moz_embed_is_loading(KZ_MOZ_EMBED(widget));
			if (can_stop_all) break;
		}
	}

	if (num > 0)
	{
		KZ_WINDOW_SET_SENSITIVE(kz, "Back",      can_go_back);
		action = egg_action_group_get_action(kz->actions,
						     "Back");
		if (can_go_back)
		{
			gchar *uri = NULL, *title = NULL;
			kz_moz_embed_shistory_get_nth(kzembed, -1,
						      TRUE, &uri, &title);
			if (uri)
			{
				combine_favicon(action, uri, kz);
				g_free(uri);
			}
			if (title)
				g_free(title);
		}
		else 
			combine_favicon(action, NULL, kz);

		KZ_WINDOW_SET_SENSITIVE(kz, "Forward",   can_go_forward);
		action = egg_action_group_get_action(kz->actions,
						     "Forward");
		if (can_go_forward)
		{
			gchar *uri = NULL, *title = NULL;
			kz_moz_embed_shistory_get_nth(kzembed, 1,
						      TRUE, &uri, &title);
			if (uri)
			{
				combine_favicon(action, uri, kz);
				g_free(uri);
			}
			if (title)
				g_free(title);
		}
		else 
			combine_favicon(action, NULL, kz);

		KZ_WINDOW_SET_SENSITIVE(kz, "GoUp",      can_go_up);
		KZ_WINDOW_SET_VISIBLE  (kz, "Stop",      can_stop);
		KZ_WINDOW_SET_VISIBLE  (kz, "Reload",    !can_stop);
		KZ_WINDOW_SET_SENSITIVE(kz, "Stop",      can_stop);
		KZ_WINDOW_SET_SENSITIVE(kz, "Reload",    !can_stop);
		KZ_WINDOW_SET_SENSITIVE(kz, "StopAll",   can_stop_all);
		KZ_WINDOW_SET_SENSITIVE(kz, "ReloadAll", TRUE);
		KZ_WINDOW_SET_SENSITIVE(kz, "CloseTab",  can_close_tab);
		KZ_WINDOW_SET_SENSITIVE(kz, "Search",    TRUE);
		KZ_WINDOW_SET_SENSITIVE(kz, "ExtractLinks", TRUE);
		KZ_WINDOW_SET_SENSITIVE(kz, "CopyTitle",    TRUE);
		KZ_WINDOW_SET_SENSITIVE(kz, "CopyURL",      TRUE);
		KZ_WINDOW_SET_SENSITIVE(kz, "Index",    can_go_index);
		KZ_WINDOW_SET_SENSITIVE(kz, "Contents", can_go_contents);
		KZ_WINDOW_SET_SENSITIVE(kz, "Start",    can_go_start);
		KZ_WINDOW_SET_SENSITIVE(kz, "Prev",     can_go_prev);
		KZ_WINDOW_SET_SENSITIVE(kz, "Next",     can_go_next);
		KZ_WINDOW_SET_VISIBLE  (kz, "Index",    can_go_index);
		KZ_WINDOW_SET_VISIBLE  (kz, "Contents", can_go_contents);
		KZ_WINDOW_SET_VISIBLE  (kz, "Start",    can_go_start);
		KZ_WINDOW_SET_VISIBLE  (kz, "Prev",     can_go_prev);
		KZ_WINDOW_SET_VISIBLE  (kz, "Next",     can_go_next);

		action = egg_action_group_get_action(kz->actions,
						     "PrevTab");
		if (pos == 0)
		{
			KZ_WINDOW_SET_SENSITIVE(kz, "PrevTab", FALSE);
			combine_favicon(action, NULL, kz);
		}
		else
		{
			KzMozEmbed *prev = KZ_MOZ_EMBED(KZ_WINDOW_NTH_PAGE(kz, pos - 1));
			const gchar* uri = kz_moz_embed_get_location(prev);
			/* set favicon */
			combine_favicon(action, uri, kz);
			KZ_WINDOW_SET_SENSITIVE(kz, "PrevTab", TRUE);
		}

		action = egg_action_group_get_action(kz->actions,
						     "NextTab");
		if (pos == num - 1)
		{
			KZ_WINDOW_SET_SENSITIVE(kz, "NextTab", FALSE);
			combine_favicon(action,	NULL, kz);
		}
		else
		{
			KzMozEmbed *next = KZ_MOZ_EMBED(KZ_WINDOW_NTH_PAGE(kz, pos + 1));
			const gchar* uri = kz_moz_embed_get_location(next);
			/* set favicon */
			combine_favicon(action,	uri, kz);
			KZ_WINDOW_SET_SENSITIVE(kz, "NextTab", TRUE);
		}
	}
	else
	{
		KZ_WINDOW_SET_SENSITIVE(kz, "Back",      FALSE);
		KZ_WINDOW_SET_SENSITIVE(kz, "Forward",   FALSE);
		KZ_WINDOW_SET_VISIBLE  (kz, "Stop",      FALSE);
		KZ_WINDOW_SET_VISIBLE  (kz, "Reload",    TRUE);
		KZ_WINDOW_SET_SENSITIVE(kz, "Stop",      FALSE);
		KZ_WINDOW_SET_SENSITIVE(kz, "Reload",    FALSE);
		KZ_WINDOW_SET_SENSITIVE(kz, "StopAll",   FALSE);
		KZ_WINDOW_SET_SENSITIVE(kz, "ReloadAll", FALSE);
		KZ_WINDOW_SET_SENSITIVE(kz, "CloseTab",  FALSE);
		KZ_WINDOW_SET_SENSITIVE(kz, "PrevTab",   FALSE);
		KZ_WINDOW_SET_SENSITIVE(kz, "NextTab",  FALSE);
		KZ_WINDOW_SET_SENSITIVE(kz, "Search",    FALSE);
		KZ_WINDOW_SET_SENSITIVE(kz, "ExtractLinks", FALSE);
		KZ_WINDOW_SET_SENSITIVE(kz, "CopyTitle",    FALSE);
		KZ_WINDOW_SET_SENSITIVE(kz, "CopyURL",      FALSE);
	}

	if (num > 1)
	{
		if (pos == 0)
		{
			KZ_WINDOW_SET_SENSITIVE(kz, "CloseAllBackwardTab", FALSE);
		}
		else
		{
			KZ_WINDOW_SET_SENSITIVE(kz, "CloseAllBackwardTab", TRUE);
		}

		if (pos == num - 1)
		{
			KZ_WINDOW_SET_SENSITIVE(kz, "CloseAllForwardTab", FALSE);
		}
		else
		{
			KZ_WINDOW_SET_SENSITIVE(kz, "CloseAllForwardTab", TRUE);
		}

		KZ_WINDOW_SET_SENSITIVE(kz, "CloseAllTabWithoutActive", TRUE);
	}
	else
	{
		KZ_WINDOW_SET_SENSITIVE(kz, "CloseAllBackwardTab",      FALSE);
		KZ_WINDOW_SET_SENSITIVE(kz, "CloseAllForwardTab",       FALSE);
		KZ_WINDOW_SET_SENSITIVE(kz, "CloseAllTabWithoutActive", FALSE);
	}

	kz_actions_set_selection_sensitive (kz, kzembed);
	
	/* Sidebar position menu */
	action = egg_action_group_get_action(kz->actions,
					     "ShowHideSidebar");
	active = egg_toggle_action_get_active(EGG_TOGGLE_ACTION(action));
	KZ_WINDOW_SET_VISIBLE(kz, "StockSidebarPosMenu", active);

	set_popup_menu_sensitive(kz, kz_bookmark);
}


void
add_accel_entry(EggAction *action, GtkAccelGroup *accel_group,
		const gchar *key)
{
	guint accel_key = 0;
	GdkModifierType accel_mods = 0;
	gchar *accel_path;

	accel_path = g_strconcat("<Actions>/KzWindow/",
				 egg_action_get_name(action),
				 NULL);

	if (accel_group)
		egg_action_set_accelerator(action, accel_group,
					   accel_path);
	gtk_accelerator_parse(key,
			      &accel_key,
			      &accel_mods);
	if (accel_key)
		gtk_accel_map_add_entry(accel_path, accel_key, accel_mods);

	g_free(accel_path);
}


EggActionGroup *
kz_actions_create_group (KzWindow *kz, GtkAccelGroup *accel_group)
{
	EggActionGroup *action_group;
	EggAction *action;
	gint i;

	action_group = egg_action_group_new("KzWindow");
	if (accel_group)
		egg_action_group_set_accel_group(action_group, accel_group);

	for (i = 0; i < kz_actions_len; i++)
		kz_actions[i].user_data = kz;

	egg_action_group_add_actions (action_group,
				      kz_actions,
				      kz_actions_len);

	for (i = 0; i < kz_actions_len; i++)
		kz_actions[i].user_data = NULL;

	/* Location Entry Action */
	{
		action = EGG_ACTION(kz_location_entry_action_new(kz));
		egg_action_group_add_action(action_group, action);
		g_object_unref(action);
	}

	/* Home Action */
	{
		action = EGG_ACTION(kz_home_action_new(kz_home, kz));
		egg_action_group_add_action(action_group, action);
		add_accel_entry(action, accel_group, "<alt>Home");
		g_object_unref(action);
	}

	/* Google Action */
	{
		action = EGG_ACTION(google_action_new(kz));
		egg_action_group_add_action(action_group, action);
		g_object_unref(action);
	}

	return action_group;
}


GCallback
kz_actions_get_func_from_name (const gchar *name)
{
	gint i;

	if (!name || !*name) return NULL;

	for (i = 0; i < kz_actions_len; i++)
		if (!strcmp(name, kz_actions[i].name))
			return kz_actions[i].callback;

	return NULL;
}


KzBookmark *
kz_actions_get_bookmark_for_action (KzWindow *kz)
{
	KzBookmark *bookmark;

	g_return_val_if_fail(KZ_IS_WINDOW(kz), NULL);

	if (!bookmark_quark)
		bookmark_quark = g_quark_from_string("KzAction::KzBookmark");
	bookmark = g_object_get_qdata(G_OBJECT(kz), bookmark_quark);

	if (KZ_IS_BOOKMARK(bookmark))
		return bookmark;

	return kz_bookmark;
}


void
kz_actions_set_bookmark_for_action (KzWindow *kz, KzBookmark *bookmark)
{
	g_return_if_fail(KZ_IS_WINDOW(kz));
	g_return_if_fail(!bookmark || KZ_IS_BOOKMARK(bookmark));

	if (!bookmark_quark)
		bookmark_quark = g_quark_from_string("KzAction::KzBookmark");
	g_object_set_qdata(G_OBJECT(kz), bookmark_quark, bookmark);
}


static void
cb_popup_menu_hide (void)
{
	gtk_main_quit();
}


void
kz_actions_popup_bookmark_menu_modal (KzWindow *kz, KzBookmark *bookmark,
				      guint button, guint time)
{
	GtkWidget *popup_menu = NULL;
	gchar path[64];

	g_return_if_fail(KZ_IS_BOOKMARK(bookmark));

	kz_actions_set_bookmark_for_action (kz, bookmark);

	g_snprintf(path, sizeof(path), "/popups/BookmarkPopup%s",
		   kz_ui_level_to_suffix(kz_ui_level()));
	popup_menu = egg_menu_merge_get_widget(kz->menu_merge, path);
	if (!popup_menu) return;

	g_signal_connect(G_OBJECT(popup_menu), "hide",
			 G_CALLBACK(cb_popup_menu_hide), NULL);
	set_popup_menu_sensitive (kz, bookmark);
	gtk_menu_popup(GTK_MENU(popup_menu), NULL, NULL,
		       NULL, NULL, button, time);
	gtk_main();
	g_signal_handlers_disconnect_by_func(G_OBJECT(popup_menu),
					     G_CALLBACK(cb_popup_menu_hide),
					     NULL);

	kz_actions_set_bookmark_for_action (kz, NULL);

	set_popup_menu_sensitive (kz, kz_bookmark);
}

