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

/*
 *  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.
 *
 *  $Id: kz-bookmark-editor.c 2719 2006-12-31 12:21:48Z ikezoe $
 */

#include "kz-bookmark-editor.h"

#include <string.h>
#include <glib/gi18n.h>

#include "kazehakase.h"
#include "kz-window.h"
#include "kz-bookmark-edit.h"
#include "kz-actions-bookmark.h"
#include "kz-icons.h"
#include "kz-bookmarks-view.h"
#include "kz-bookmark-file.h"


enum {
	PROP_0,
	PROP_ROOT_FOLDER,
};


/* object class */
static void     dispose      (GObject          *object);
static void     set_property (GObject          *object,
                              guint             prop_id,
                              const GValue     *value,
                              GParamSpec       *pspec);
static void     get_property (GObject          *object,
                              guint             prop_id,
                              GValue           *value,
                              GParamSpec       *pspec);

/* widget event */
static gboolean delete_event (GtkWidget        *widget,
                              GdkEventAny      *event);

/* private methods */
static void     kz_bookmark_editor_set_folder_tree   (KzBookmarkEditor *editor);
static void     kz_bookmark_editor_set_bookmark_tree (KzBookmarkEditor *editor,
						      KzBookmark       *parent);

static void     cb_menu_merge_add_widget        (GtkUIManager     *merge,
						 GtkWidget        *widget,
						 GtkBox           *box);
static void     cb_folder_view_cursor_changed   (GtkTreeView      *treeview,
						 KzBookmarkEditor *editor);
static void     cb_bookmarks_view_cursor_changed(GtkTreeView      *treeview,
						 KzBookmarkEditor *editor);
static void     cb_bookmarks_view_selection_changed
						(GtkTreeSelection *selection,
						 KzBookmarkEditor *editor);
static gboolean cb_bookmarks_view_button_press  (GtkWidget        *widget,
						 GdkEventButton   *button,
						 KzBookmarkEditor *editor);

G_DEFINE_TYPE(KzBookmarkEditor, kz_bookmark_editor, GTK_TYPE_WINDOW)

static void
kz_bookmark_editor_class_init (KzBookmarkEditorClass *klass)
{
	GObjectClass *gobject_class;
	GtkWidgetClass *widget_class;

	gobject_class = (GObjectClass *)   klass;
	widget_class  = (GtkWidgetClass *) klass;

	gobject_class->dispose      = dispose;
	gobject_class->set_property = set_property;
	gobject_class->get_property = get_property;

	/* GtkWidget signals */
	widget_class->delete_event = delete_event;

	g_object_class_install_property
		(gobject_class,
		 PROP_ROOT_FOLDER,
		 g_param_spec_object (
			 "root-folder",
			 _("Root Folder"),
			 _("The root bookmark folder to show"),
			 KZ_TYPE_BOOKMARK,
			 G_PARAM_READWRITE));
}


#define SET_SENSITIVE(editor, name, sensitive)				\
{									\
	GtkAction *action;						\
	action = gtk_action_group_get_action((editor)->action_group,	\
					     (name));			\
	g_object_set(action, "sensitive", (sensitive), NULL);			\
}


static void
kz_bookmark_editor_init (KzBookmarkEditor *editor)
{
	GtkWidget *hpaned, *vpaned, *main_vbox;
	GtkWidget *scrwin[3], *treeview[2], *edit_view, *statusbar;
	GtkTreeSelection *selection;
	GtkActionGroup *actions;
	GtkAccelGroup *accel_group;
	GtkUIManager   *menu_merge;
	GError *err = NULL;

	g_object_set(G_OBJECT(editor), "allow-shrink", TRUE, NULL);

	gtk_window_set_title(GTK_WINDOW(editor),
			     _("- Kazehakase Bookmark Editor -"));
	gtk_window_set_position(GTK_WINDOW(editor),
				GTK_WIN_POS_CENTER_ON_PARENT);

	menu_merge = gtk_ui_manager_new();
	accel_group = gtk_ui_manager_get_accel_group(menu_merge);

	actions    = kz_actions_bookmark_create_group(editor, accel_group);

	/* toplevel vbox */
	main_vbox = gtk_vbox_new(FALSE, 0);
	gtk_container_add(GTK_CONTAINER(editor), main_vbox);
	gtk_widget_show(main_vbox);

	/* menu and toolbar */
	gtk_ui_manager_insert_action_group(menu_merge, actions, 0);
	g_signal_connect(menu_merge, "add_widget",
			 G_CALLBACK(cb_menu_merge_add_widget), main_vbox);
	gtk_ui_manager_add_ui_from_file(menu_merge,
					KZ_SYSCONFDIR"/kz-ui-bookmarks.xml",
					&err);
	if (err)
	{
		g_warning("%s", err->message);
		g_error_free(err);
	}
        gtk_ui_manager_ensure_update(menu_merge);

	gtk_window_add_accel_group(GTK_WINDOW(editor), 
				   gtk_ui_manager_get_accel_group(menu_merge));
	
	/* paned for main contents */
	hpaned = gtk_hpaned_new();
	gtk_box_pack_start(GTK_BOX(main_vbox), hpaned, TRUE, TRUE, 0);
	gtk_widget_show(hpaned);

	/* folder view */
	scrwin[0] = gtk_scrolled_window_new(NULL, NULL);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrwin[0]),
				       GTK_POLICY_AUTOMATIC,
				       GTK_POLICY_AUTOMATIC);
        gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrwin[0]),
					    GTK_SHADOW_IN);

	gtk_paned_add1(GTK_PANED(hpaned), scrwin[0]);

	treeview[0] = kz_bookmarks_view_new();
	gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(treeview[0]), FALSE);
	gtk_container_add(GTK_CONTAINER(scrwin[0]), treeview[0]);
	gtk_widget_show(treeview[0]);

	g_signal_connect(treeview[0], "cursor-changed",
			 G_CALLBACK(cb_folder_view_cursor_changed), editor);

	/* vpaned */
	vpaned = gtk_vpaned_new();
	gtk_paned_add2(GTK_PANED(hpaned), vpaned);
	gtk_widget_show(vpaned);

	/* bookmark view */
	scrwin[1] = gtk_scrolled_window_new(NULL, NULL);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrwin[1]),
				       GTK_POLICY_AUTOMATIC,
				       GTK_POLICY_AUTOMATIC);
        gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrwin[1]),
					    GTK_SHADOW_IN);
	gtk_paned_add1(GTK_PANED(vpaned), scrwin[1]);
	gtk_widget_show(scrwin[1]);

	treeview[1] = kz_bookmarks_view_new();
	selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview[1]));
	gtk_container_add(GTK_CONTAINER(scrwin[1]), treeview[1]);
	gtk_widget_show(treeview[1]);

	g_signal_connect(treeview[1], "cursor-changed",
			 G_CALLBACK(cb_bookmarks_view_cursor_changed), editor);
	g_signal_connect(selection, "changed",
			 G_CALLBACK(cb_bookmarks_view_selection_changed),
			 editor);
	g_signal_connect(treeview[1], "button-press-event",
			 G_CALLBACK(cb_bookmarks_view_button_press),
			 editor);

	/* Content view */
	edit_view = kz_bookmark_edit_new();
	gtk_paned_add2(GTK_PANED(vpaned), edit_view);

	/* Status bar */
	statusbar = gtk_statusbar_new();
	gtk_box_pack_start(GTK_BOX(main_vbox), statusbar, FALSE, FALSE, 0);
	gtk_widget_show(statusbar);

	/* set members of instance */
	editor->vbox           = main_vbox;
	editor->hpaned         = hpaned;
	editor->vpaned         = vpaned;
	editor->scrolledwin[0] = scrwin[0];
	editor->scrolledwin[1] = scrwin[1];
	editor->folder_view    = treeview[0];
	editor->bookmarks_view = treeview[1];
	editor->statusbar      = statusbar;
	editor->content_view   = edit_view;

	editor->root_folder    = NULL;
	editor->current_folder = NULL;

	editor->action_group   = actions;
	editor->menu_merge     = menu_merge;

	/* set default state */
	kz_bookmark_editor_restore_state(editor);

	SET_SENSITIVE(editor, "EditBookmarkItem",     FALSE);
	SET_SENSITIVE(editor, "InsertBookmark",       FALSE);
	SET_SENSITIVE(editor, "InsertFolder",         FALSE);
	SET_SENSITIVE(editor, "InsertRemoteBookmark", FALSE);
	SET_SENSITIVE(editor, "InsertSeparator",      FALSE);
	SET_SENSITIVE(editor, "RemoveBookmarkItem",   FALSE);
	SET_SENSITIVE(editor, "GoUp",                 FALSE);
}


static void
dispose (GObject *object)
{
	KzBookmarkEditor *editor = KZ_BOOKMARK_EDITOR(object);

	if (editor->root_folder)
	{
		g_object_unref(editor->root_folder);
		editor->root_folder = NULL;
	}

	if (editor->menu_merge)
		g_object_unref(editor->menu_merge);
	editor->menu_merge = NULL;

	if (editor->action_group)
		g_object_unref(editor->action_group);
	editor->action_group = NULL;

	if (G_OBJECT_CLASS (kz_bookmark_editor_parent_class)->dispose)
		G_OBJECT_CLASS (kz_bookmark_editor_parent_class)->dispose(object);
}


static void
set_property (GObject         *object,
              guint            prop_id,
              const GValue    *value,
              GParamSpec      *pspec)
{
	KzBookmarkEditor *editor = KZ_BOOKMARK_EDITOR(object);
  
	switch (prop_id)
	{
	case PROP_ROOT_FOLDER:
		if (editor->root_folder)
		{
			g_object_unref(editor->root_folder);
		}
		editor->root_folder = g_object_ref(g_value_get_object(value));

		kz_bookmark_editor_set_folder_tree(editor);
		kz_bookmark_editor_set_bookmark_tree(editor, editor->root_folder);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}


static void
get_property (GObject         *object,
              guint            prop_id,
              GValue          *value,
              GParamSpec      *pspec)
{
	KzBookmarkEditor *editor = KZ_BOOKMARK_EDITOR(object);

	switch (prop_id)
	{
	case PROP_ROOT_FOLDER:
		g_value_set_object(value, editor->root_folder);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}


static gboolean
delete_event (GtkWidget *widget, GdkEventAny *event)
{
	KzBookmarkEditor *editor;

	editor = KZ_BOOKMARK_EDITOR(widget);
	kz_bookmark_editor_store_state(editor);

	return FALSE;
}


static void
kz_bookmark_editor_set_folder_tree (KzBookmarkEditor *editor)
{
	KzBookmarksView *view;

	view = KZ_BOOKMARKS_VIEW(editor->folder_view);
	kz_bookmarks_view_set_root_folder(view, editor->root_folder,
					  TRUE, TRUE, TRUE, TRUE);
}


static void
kz_bookmark_editor_set_bookmark_tree (KzBookmarkEditor *editor,
				      KzBookmark *parent)
{
	KzBookmarksView *view;
	gboolean editable;

	g_return_if_fail(KZ_IS_BOOKMARK_EDITOR(editor));
	g_return_if_fail(!parent || kz_bookmark_is_folder(parent));

	view = KZ_BOOKMARKS_VIEW(editor->bookmarks_view);

	editor->current_folder = parent;

	kz_bookmarks_view_set_root_folder(view, parent, FALSE, FALSE, FALSE, TRUE);

	/* set sensitive */
	if (!parent || editor->root_folder == parent)
	{
		SET_SENSITIVE(editor, "GoUp", FALSE);
	}
	else
	{
		SET_SENSITIVE(editor, "GoUp", TRUE);
	}

	if (parent && !KZ_IS_BOOKMARK_FILE(parent))
		parent = kz_bookmark_get_parent_file(parent);

	if (parent && kz_bookmark_file_is_editable(KZ_BOOKMARK_FILE(parent)))
		editable = TRUE;
	else
		editable = FALSE;

	SET_SENSITIVE(editor, "InsertBookmark",       editable);
	SET_SENSITIVE(editor, "InsertFolder",         editable);
	SET_SENSITIVE(editor, "InsertRemoteBookmark", editable);
	SET_SENSITIVE(editor, "InsertSmartBookmark",  editable);
	SET_SENSITIVE(editor, "InsertSeparator",      editable);
}


GtkWidget *
kz_bookmark_editor_new (KzBookmark *bookmark)
{
	KzBookmarkEditor *editor;

	editor = KZ_BOOKMARK_EDITOR(g_object_new(KZ_TYPE_BOOKMARK_EDITOR,
						 "type", GTK_WINDOW_TOPLEVEL,
						 "root-folder", bookmark,
						 NULL));
	return GTK_WIDGET(editor);
}


void
kz_bookmark_editor_set_current (KzBookmarkEditor *editor,
				KzBookmark *bookmark)
{
	kz_bookmark_editor_folder_view_select(editor, bookmark);
}


void
kz_bookmark_editor_set_tree_mode (KzBookmarkEditor *editor,
				  gboolean tree_mode)
{
	KzBookmarksView *view;

	g_return_if_fail(KZ_IS_BOOKMARK_EDITOR(editor));

	view = KZ_BOOKMARKS_VIEW(editor->bookmarks_view);
	kz_bookmarks_view_set_root_folder(view, editor->current_folder,
					  tree_mode, FALSE, FALSE, TRUE);
}


void
kz_bookmark_editor_store_state (KzBookmarkEditor *editor)
{
	GtkAction *action;
	gint client_x, client_y, width, height;
	gboolean show_folder_view, show_edit_view;

	g_return_if_fail(KZ_IS_BOOKMARK_EDITOR(editor));

	gdk_window_get_geometry (GTK_WIDGET(editor)->window,
				 &client_x, &client_y,
				 &width, &height, NULL);

	action = gtk_action_group_get_action(editor->action_group,
					     "ShowHideFolderView");
	show_folder_view
		= gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action));

	action = gtk_action_group_get_action(editor->action_group,
					     "ShowHideContentView");
	show_edit_view
		= gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action));

	KZ_CONF_SET("BookmarkEditorWindow", "width",  width,  INT);
	KZ_CONF_SET("BookmarkEditorWindow", "height", height, INT);
	KZ_CONF_SET("BookmarkEditorWindow", "show_folder_view",
		    show_folder_view, BOOL);
	KZ_CONF_SET("BookmarkEditorWindow", "show_content_view",
		    show_edit_view, BOOL);

	width = editor->scrolledwin[0]->allocation.width;
	if (width > 8)
		KZ_CONF_SET("BookmarkEditorWindow", "folder_view_width",
			    width, INT);
	height = editor->content_view->allocation.height;
	if (height > 8)
	{
		height = editor->vpaned->allocation.height - height;
		KZ_CONF_SET("BookmarkEditorWindow",
			    "bookmarks_view_height",
			    height, INT);
	}

	/* mode */
	action = gtk_action_group_get_action(editor->action_group,
					     "TreeMode");
	if (gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)))
		KZ_CONF_SET_STR("BookmarkEditorWindow", "mode",
				"TreeMode");
	else
		KZ_CONF_SET_STR("BookmarkEditorWindow", "mode",
				"ListMode");
}


void
kz_bookmark_editor_restore_state (KzBookmarkEditor *editor)
{
	GtkAction *action;
	gint width = 600, height = 450;
	gint folder_view_width = 150, bookmarks_view_height = 230;
	gboolean show_folder_view = TRUE, show_edit_view = FALSE;
	gchar *mode;

	g_return_if_fail(KZ_IS_BOOKMARK_EDITOR(editor));

	KZ_CONF_GET("BookmarkEditorWindow", "width",  width, INT);
	KZ_CONF_GET("BookmarkEditorWindow", "height", height, INT);
	KZ_CONF_GET("BookmarkEditorWindow", "folder_view_width",
		    folder_view_width, INT);
	KZ_CONF_GET("BookmarkEditorWindow", "bookmarks_view_height",
		    bookmarks_view_height, INT);
	KZ_CONF_GET("BookmarkEditorWindow", "show_folder_view",
		    show_folder_view, BOOL);
	KZ_CONF_GET("BookmarkEditorWindow", "show_content_view",
		    show_edit_view, BOOL);
	mode = KZ_CONF_GET_STR("BookmarkEditorWindow", "mode");

	/* size */
	gtk_window_set_default_size(GTK_WINDOW(editor), width, height);

	action = gtk_action_group_get_action(editor->action_group,
					     "ShowHideFolderView");
	gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action),
				     show_folder_view);

	action = gtk_action_group_get_action(editor->action_group,
					     "ShowHideContentView");
	gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action),
				     show_edit_view);

	gtk_widget_set_size_request(GTK_WIDGET(editor->scrolledwin[0]),
				    folder_view_width, -1);
	gtk_widget_set_size_request(GTK_WIDGET(editor->scrolledwin[1]),
				    -1, bookmarks_view_height);

	/* mode */
	if (mode && !strcmp(mode, "TreeMode"))
	{
		action = gtk_action_group_get_action(editor->action_group,
						     "TreeMode");
		gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), TRUE);
	}
	else
	{
		action = gtk_action_group_get_action(editor->action_group,
						     "ListMode");
		gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), TRUE);
	}

	g_free(mode);
}


static void
cb_menu_merge_add_widget (GtkUIManager *merge, GtkWidget *widget,
			  GtkBox *box)
{
	gtk_box_pack_start (box, widget, FALSE, FALSE, 0);
	gtk_widget_show (widget);
}


static void
cb_folder_view_cursor_changed (GtkTreeView *treeview, KzBookmarkEditor *editor)
{
	GtkTreeModel *model;
	GtkTreeIter iter;
	GtkTreePath *path = NULL;
	KzBookmark *folder;

	g_return_if_fail(KZ_IS_BOOKMARK_EDITOR(editor));

	kz_bookmark_edit_clear(KZ_BOOKMARK_EDIT(editor->content_view));

	model = gtk_tree_view_get_model(treeview);

	gtk_tree_view_get_cursor (treeview, &path, NULL);
	if (!path)
	{
		kz_bookmark_edit_clear(KZ_BOOKMARK_EDIT(editor->content_view));
		return;
	}

	gtk_tree_model_get_iter(model, &iter, path);
	folder = kz_bookmarks_view_get_bookmark(model, &iter);

	if (folder)
		kz_bookmark_editor_set_bookmark_tree(editor, folder);

	gtk_tree_path_free(path);
}


static void
cb_bookmarks_view_cursor_changed (GtkTreeView *treeview,
				  KzBookmarkEditor *editor)
{
	GtkTreeModel *model;
	GtkTreeIter iter;
	GtkTreePath *path = NULL;
	KzBookmark *bookmark = NULL;

	g_return_if_fail(KZ_IS_BOOKMARK_EDITOR(editor));

	model = gtk_tree_view_get_model(treeview);

	gtk_tree_view_get_cursor (treeview, &path, NULL);
	if (!path)
	{
		kz_bookmark_edit_clear(KZ_BOOKMARK_EDIT(editor->content_view));
		return;
	}

	gtk_tree_model_get_iter(model, &iter, path);
	bookmark = kz_bookmarks_view_get_bookmark(model, &iter);

	if (bookmark)
		kz_bookmark_edit_set(KZ_BOOKMARK_EDIT(editor->content_view),
				     bookmark);

	gtk_tree_path_free(path);
}


static void
cb_bookmarks_view_selection_changed (GtkTreeSelection *selection,
				     KzBookmarkEditor *editor)
{
	GtkTreeModel *model;
	GtkTreeIter iter;
	gboolean selected;

	g_return_if_fail(KZ_IS_BOOKMARK_EDITOR(editor));

	selected = gtk_tree_selection_get_selected(selection, &model, &iter);

	if (selected)
	{
		KzBookmark *bookmark;

		bookmark = kz_bookmarks_view_get_bookmark(model, &iter);
		SET_SENSITIVE(editor, "EditBookmarkItem",
			      kz_bookmark_is_editable(bookmark));
		SET_SENSITIVE(editor, "RemoveBookmarkItem",
			      kz_bookmark_is_editable(bookmark));
	}
	else
	{
		SET_SENSITIVE(editor, "EditBookmarkItem",   FALSE);
		SET_SENSITIVE(editor, "RemoveBookmarkItem", FALSE);
		kz_bookmark_edit_clear(KZ_BOOKMARK_EDIT(editor->content_view));
#if 0
		gtk_tree_model_get_iter(model, &iter, path);
		bookmark = kz_bookmarks_view_get_bookmark(model, &iter);
		if (bookmark)
			kz_bookmark_edit_set
				(KZ_BOOKMARK_EDIT(editor->content_view),
				 bookmark);
#endif
	}
}


void
kz_bookmark_editor_folder_view_select(KzBookmarkEditor *editor,
				      KzBookmark *folder)
{
	g_return_if_fail(KZ_IS_BOOKMARK_EDITOR(editor));

	kz_bookmarks_view_select(KZ_BOOKMARKS_VIEW(editor->folder_view),
				 folder);
}


void
kz_bookmark_editor_bookmarks_view_select(KzBookmarkEditor *editor,
					 KzBookmark *bookmark)
{
	g_return_if_fail(KZ_IS_BOOKMARK_EDITOR(editor));

	kz_bookmarks_view_select(KZ_BOOKMARKS_VIEW(editor->bookmarks_view),
				 bookmark);
}


static void
create_selected_list_func (GtkTreeModel *model,
			   GtkTreePath *path, GtkTreeIter *iter,
			   gpointer data)
{
	GList **list = data;
	KzBookmark *bookmark;

	g_return_if_fail(list);

	bookmark = kz_bookmarks_view_get_bookmark(model, iter);

	if (bookmark)
		*list = g_list_append(*list, bookmark);
}


GList *
kz_bookmark_editor_get_selected_list (KzBookmarkEditor *editor)
{
	GtkTreeView *treeview = GTK_TREE_VIEW(editor->bookmarks_view);
	GtkTreeSelection *selection;
	GList *list = NULL;

	g_return_val_if_fail(KZ_IS_BOOKMARK_EDITOR(editor), NULL);

	selection = gtk_tree_view_get_selection(treeview);
	gtk_tree_selection_selected_foreach(selection,
					    create_selected_list_func,
					    &list);

	return list;
}


static gboolean
cb_bookmarks_view_button_press (GtkWidget *widget, GdkEventButton *event,
				KzBookmarkEditor *editor)
{
	GtkWindow *kz;
	GtkTreeView *treeview = GTK_TREE_VIEW(widget);
	GtkTreeModel *model = gtk_tree_view_get_model(treeview);
	GtkTreeIter iter;
	GtkTreePath *treepath = NULL;
	gboolean success;
	KzBookmark *bookmark = NULL;
	KzBookmarkEdit *edit;
	const gchar *uri = NULL;
	gboolean retval = FALSE;

	g_return_val_if_fail(KZ_IS_BOOKMARK_EDITOR(editor), FALSE);

	edit = KZ_BOOKMARK_EDIT(editor->content_view);

	kz = gtk_window_get_transient_for(GTK_WINDOW(editor));
	if (!KZ_IS_WINDOW(kz))
	{
		const GList *list = KZ_GET_WINDOW_LIST;
		if (list)
			kz = list->data;
		else
			return retval;
	}

	success = gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget),
						event->x, event->y,
						&treepath, NULL, NULL, NULL);
	if (success)
	{
		gtk_tree_model_get_iter(model, &iter, treepath);
		bookmark = kz_bookmarks_view_get_bookmark(model, &iter);
	}

	if (success && (event->type == GDK_2BUTTON_PRESS))
	{
	}
	else if (success && event->button == 2)
	{
		uri = kz_bookmark_get_link(bookmark);

		if (kz_bookmark_is_folder(bookmark))
		{
			kz_bookmark_edit_clear(edit);
			kz_bookmark_editor_set_bookmark_tree(editor, bookmark);
			kz_bookmark_editor_folder_view_select(editor, bookmark);
		}
		else if (kz_bookmark_is_separator(bookmark))
		{
			/* skip */
		}
		else if (uri)
		{
			kz_window_open_new_tab(KZ_WINDOW(kz), uri);
		}
	}
	else if (event->button == 3)
	{
		if (success)
			gtk_tree_view_set_cursor(GTK_TREE_VIEW(widget),
						 treepath, NULL, FALSE);

		kz_actions_bookmark_popup_menu_modal
			(editor, event->button, event->time);

		retval = TRUE;
	}

	if (treepath)
		gtk_tree_path_free(treepath);

	return retval;
}
