midori/midori/midori-searchentry.c
2008-08-26 01:59:02 +02:00

891 lines
32 KiB
C

/*
Copyright (C) 2007-2008 Christian Dywan <christian@twotoasts.de>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
See the file COPYING for the full license text.
*/
#include "midori-searchentry.h"
#include "sokoke.h"
#include <gdk/gdkkeysyms.h>
#include <glib/gi18n.h>
struct _MidoriSearchEntry
{
GtkIconEntry parent_instance;
KatzeArray* search_engines;
KatzeItem* current_item;
};
G_DEFINE_TYPE (MidoriSearchEntry, midori_search_entry, GTK_TYPE_ICON_ENTRY)
enum
{
PROP_0,
PROP_SEARCH_ENGINES,
PROP_CURRENT_ITEM,
PROP_DIALOG
};
static void
midori_search_entry_finalize (GObject* object);
static void
midori_search_entry_set_property (GObject* object,
guint prop_id,
const GValue* value,
GParamSpec* pspec);
static void
midori_search_entry_get_property (GObject* object,
guint prop_id,
GValue* value,
GParamSpec* pspec);
static void
midori_search_entry_class_init (MidoriSearchEntryClass* class)
{
GObjectClass* gobject_class = G_OBJECT_CLASS (class);
gobject_class->finalize = midori_search_entry_finalize;
gobject_class->set_property = midori_search_entry_set_property;
gobject_class->get_property = midori_search_entry_get_property;
g_object_class_install_property (gobject_class,
PROP_SEARCH_ENGINES,
g_param_spec_object (
"search-engines",
_("Search Engines"),
_("The list of search engines"),
KATZE_TYPE_ARRAY,
G_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_CURRENT_ITEM,
g_param_spec_object (
"current-item",
_("Current Item"),
_("The currently selected item"),
KATZE_TYPE_ITEM,
G_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_DIALOG,
g_param_spec_object (
"dialog",
_("Dialog"),
_("A dialog to manage search engines"),
GTK_TYPE_DIALOG,
G_PARAM_READABLE));
}
static void
midori_search_entry_engine_activate_cb (GtkWidget* widget,
MidoriSearchEntry* search_entry)
{
KatzeItem* item;
item = (KatzeItem*)g_object_get_data (G_OBJECT (widget), "engine");
midori_search_entry_set_current_item (search_entry, item);
}
static void
midori_search_entry_manage_activate_cb (GtkWidget* menuitem,
MidoriSearchEntry* search_entry)
{
GtkWidget* dialog;
dialog = midori_search_entry_get_dialog (search_entry);
if (GTK_WIDGET_VISIBLE (dialog))
gtk_window_present (GTK_WINDOW (dialog));
else
gtk_widget_show (dialog);
}
static void
midori_search_entry_icon_released_cb (GtkWidget* widget,
GtkIconEntryPosition* pos,
gint button)
{
MidoriSearchEntry* search_entry;
KatzeArray* search_engines;
GtkWidget* menu;
guint n, i;
GtkWidget* menuitem;
KatzeItem* item;
GdkPixbuf* pixbuf;
GtkWidget* icon;
search_entry = MIDORI_SEARCH_ENTRY (widget);
search_engines = search_entry->search_engines;
menu = gtk_menu_new ();
n = katze_array_get_length (search_engines);
if (n)
{
for (i = 0; i < n; i++)
{
item = katze_array_get_nth_item (search_engines, i);
menuitem = gtk_image_menu_item_new_with_label (
katze_item_get_name (item));
pixbuf = sokoke_web_icon (katze_item_get_icon (item),
GTK_ICON_SIZE_MENU, menuitem);
icon = gtk_image_new_from_pixbuf (pixbuf);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), icon);
g_object_unref (pixbuf);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
g_object_set_data (G_OBJECT (menuitem), "engine", item);
g_signal_connect (menuitem, "activate",
G_CALLBACK (midori_search_entry_engine_activate_cb), widget);
gtk_widget_show (menuitem);
}
}
else
{
menuitem = gtk_image_menu_item_new_with_label (_("Empty"));
gtk_widget_set_sensitive (menuitem, FALSE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
gtk_widget_show (menuitem);
}
menuitem = gtk_separator_menu_item_new ();
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
gtk_widget_show (menuitem);
menuitem = gtk_image_menu_item_new_with_mnemonic (_("_Manage Search Engines"));
icon = gtk_image_new_from_stock (GTK_STOCK_PREFERENCES, GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), icon);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
g_signal_connect (menuitem, "activate",
G_CALLBACK (midori_search_entry_manage_activate_cb), widget);
gtk_widget_show (menuitem);
sokoke_widget_popup (widget, GTK_MENU (menu),
NULL, SOKOKE_MENU_POSITION_LEFT);
}
static void
_midori_search_entry_move_index (MidoriSearchEntry* search_entry,
guint n)
{
gint i;
KatzeItem* item;
i = katze_array_get_item_index (search_entry->search_engines,
search_entry->current_item);
item = katze_array_get_nth_item (search_entry->search_engines, i + n);
if (item)
midori_search_entry_set_current_item (search_entry, item);
}
static gboolean
midori_search_entry_key_press_event_cb (MidoriSearchEntry* search_entry,
GdkEventKey* event)
{
GdkModifierType state;
gint x, y;
gdk_window_get_pointer (NULL, &x, &y, &state);
if (!(state & GDK_CONTROL_MASK))
return FALSE;
switch (event->keyval)
{
case GDK_Up:
_midori_search_entry_move_index (search_entry, - 1);
return TRUE;
case GDK_Down:
_midori_search_entry_move_index (search_entry, + 1);
return TRUE;
}
return FALSE;
}
static gboolean
midori_search_entry_scroll_event_cb (MidoriSearchEntry* search_entry,
GdkEventScroll* event)
{
if (event->direction == GDK_SCROLL_DOWN)
_midori_search_entry_move_index (search_entry, + 1);
else if (event->direction == GDK_SCROLL_UP)
_midori_search_entry_move_index (search_entry, - 1);
return TRUE;
}
static void
midori_search_entry_engines_add_item_cb (KatzeArray* list,
KatzeItem* item,
MidoriSearchEntry* search_entry)
{
if (!search_entry->current_item)
midori_search_entry_set_current_item (search_entry, item);
}
static void
midori_search_entry_engines_remove_item_cb (KatzeArray* list,
KatzeItem* item,
MidoriSearchEntry* search_entry)
{
KatzeItem* found_item;
if (search_entry->current_item == item)
{
found_item = katze_array_get_nth_item (list, 0);
midori_search_entry_set_current_item (search_entry, found_item);
}
}
static void
midori_search_entry_init (MidoriSearchEntry* search_entry)
{
search_entry->search_engines = katze_array_new (KATZE_TYPE_ITEM);
search_entry->current_item = NULL;
gtk_icon_entry_set_icon_highlight (GTK_ICON_ENTRY (search_entry),
GTK_ICON_ENTRY_PRIMARY, TRUE);
g_object_connect (search_entry,
"signal::icon-released",
midori_search_entry_icon_released_cb, NULL,
"signal::key-press-event",
midori_search_entry_key_press_event_cb, NULL,
"signal::scroll-event",
midori_search_entry_scroll_event_cb, NULL,
NULL);
g_object_connect (search_entry->search_engines,
"signal-after::add-item",
midori_search_entry_engines_add_item_cb, search_entry,
"signal-after::remove-item",
midori_search_entry_engines_remove_item_cb, search_entry,
NULL);
}
static void
midori_search_entry_finalize (GObject* object)
{
MidoriSearchEntry* search_entry = MIDORI_SEARCH_ENTRY (object);
g_object_unref (search_entry->search_engines);
if (search_entry->current_item)
g_object_unref (search_entry->current_item);
G_OBJECT_CLASS (midori_search_entry_parent_class)->finalize (object);
}
static void
midori_search_entry_set_property (GObject* object,
guint prop_id,
const GValue* value,
GParamSpec* pspec)
{
MidoriSearchEntry* search_entry = MIDORI_SEARCH_ENTRY (object);
switch (prop_id)
{
case PROP_SEARCH_ENGINES:
midori_search_entry_set_search_engines (search_entry,
g_value_get_object (value));
break;
case PROP_CURRENT_ITEM:
midori_search_entry_set_current_item (search_entry,
g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
midori_search_entry_get_property (GObject* object,
guint prop_id,
GValue* value,
GParamSpec* pspec)
{
MidoriSearchEntry* search_entry = MIDORI_SEARCH_ENTRY (object);
switch (prop_id)
{
case PROP_SEARCH_ENGINES:
g_value_set_object (value, search_entry->search_engines);
break;
case PROP_CURRENT_ITEM:
g_value_set_object (value, search_entry->current_item);
break;
case PROP_DIALOG:
g_value_set_object (value, midori_search_entry_get_dialog (search_entry));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
/**
* midori_search_entry_new:
*
* Creates a new #MidoriSearchEntry.
*
* Return value: a new #MidoriSearchEntry
**/
GtkWidget*
midori_search_entry_new (void)
{
GtkWidget* search_entry = g_object_new (MIDORI_TYPE_SEARCH_ENTRY, NULL);
return search_entry;
}
/**
* midori_search_entry_get_search_engines:
* @search_entry: a #MidoriSearchEntry
*
* Retrieves the list of search engines.
*
* Return value: the list of search engines
**/
KatzeArray*
midori_search_entry_get_search_engines (MidoriSearchEntry* search_entry)
{
g_return_val_if_fail (MIDORI_IS_SEARCH_ENTRY (search_entry), NULL);
return search_entry->search_engines;
}
/**
* midori_search_entry_set_search_engines:
* @search_entry: a #MidoriSearchEntry
* @search_engines: a list of search engines
*
* Sets the list of search engines.
**/
void
midori_search_entry_set_search_engines (MidoriSearchEntry* search_entry,
KatzeArray* search_engines)
{
g_return_if_fail (MIDORI_IS_SEARCH_ENTRY (search_entry));
g_return_if_fail (katze_array_is_a (search_engines, KATZE_TYPE_ITEM));
g_object_ref (search_engines);
katze_object_assign (search_entry->search_engines, search_engines);
g_object_notify (G_OBJECT (search_entry), "search-engines");
g_object_connect (search_engines,
"signal-after::add-item",
midori_search_entry_engines_add_item_cb, search_entry,
"signal-after::remove-item",
midori_search_entry_engines_remove_item_cb, search_entry,
NULL);
}
/**
* midori_search_entry_set_current_item:
* @search_entry: a #MidoriSearchEntry
* @item: a #KatzeItem, or %NULL
*
* Looks up the specified item in the list of search engines and makes
* it the currently selected item.
*
* Pass %NULL for @item in order to unset the item.
*
* This function fails if @item is not in the current list.
**/
void
midori_search_entry_set_current_item (MidoriSearchEntry* search_entry,
KatzeItem* item)
{
GdkPixbuf* pixbuf;
g_return_if_fail (MIDORI_IS_SEARCH_ENTRY (search_entry));
g_return_if_fail (!item || KATZE_IS_ITEM (item));
pixbuf = sokoke_web_icon (item ? katze_item_get_icon (item) : NULL,
GTK_ICON_SIZE_MENU, GTK_WIDGET (search_entry));
gtk_icon_entry_set_icon_from_pixbuf (GTK_ICON_ENTRY (search_entry),
GTK_ICON_ENTRY_PRIMARY,
pixbuf);
g_object_unref (pixbuf);
if (item)
{
katze_object_assign (search_entry->current_item, g_object_ref (item));
sokoke_entry_set_default_text (GTK_ENTRY (search_entry),
katze_item_get_name (item));
}
else
{
katze_object_assign (search_entry->current_item, NULL);
sokoke_entry_set_default_text (GTK_ENTRY (search_entry), "");
}
g_object_notify (G_OBJECT (search_entry), "current-item");
}
/**
* midori_search_entry_get_current_item:
* @search_entry: a #MidoriSearchEntry
*
* Retrieves the currently selected item.
*
* Return value: the selected web item, or %NULL
**/
KatzeItem*
midori_search_entry_get_current_item (MidoriSearchEntry* search_entry)
{
g_return_val_if_fail (MIDORI_IS_SEARCH_ENTRY (search_entry), NULL);
return search_entry->current_item;
}
static void
midori_search_entry_dialog_render_icon_cb (GtkTreeViewColumn* column,
GtkCellRenderer* renderer,
GtkTreeModel* model,
GtkTreeIter* iter,
GtkWidget* treeview)
{
KatzeItem* item;
const gchar* icon;
GdkPixbuf* pixbuf;
gtk_tree_model_get (model, iter, 0, &item, -1);
icon = katze_item_get_icon (item);
if (icon)
{
pixbuf = sokoke_web_icon (icon, GTK_ICON_SIZE_DND, treeview);
g_object_set (renderer, "pixbuf", pixbuf, NULL);
if (pixbuf)
g_object_unref (pixbuf);
}
else
g_object_set (renderer, "pixbuf", NULL, NULL);
}
static void
midori_search_entry_dialog_render_text (GtkTreeViewColumn* column,
GtkCellRenderer* renderer,
GtkTreeModel* model,
GtkTreeIter* iter,
GtkWidget* treeview)
{
KatzeItem* item;
const gchar* name;
const gchar* text;
gchar* markup;
gtk_tree_model_get (model, iter, 0, &item, -1);
name = katze_item_get_name (item);
text = katze_item_get_text (item);
markup = g_markup_printf_escaped ("<b>%s</b>\n%s", name, text ? text : "");
g_object_set (renderer, "markup", markup, NULL);
g_free (markup);
}
static void
midori_search_entry_editor_name_changed_cb (GtkWidget* widget,
GtkWidget* dialog)
{
const gchar* text = gtk_entry_get_text (GTK_ENTRY (widget));
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
GTK_RESPONSE_ACCEPT, text && *text);
}
const gchar*
STR_NON_NULL (const gchar* string)
{
return string ? string : "";
}
static void
midori_search_entry_get_editor (GtkWidget* treeview,
gboolean new_engine)
{
MidoriSearchEntry* search_entry;
GtkWidget* dialog;
GtkSizeGroup* sizegroup;
KatzeItem* item;
GtkWidget* hbox;
GtkWidget* label;
GtkTreeModel* liststore;
GtkTreeIter iter;
GtkTreeSelection* selection;
GtkWidget* entry_name;
GtkWidget* entry_description;
GtkWidget* entry_uri;
GtkWidget* entry_icon;
GtkWidget* entry_token;
GtkWidget* toplevel = gtk_widget_get_toplevel (treeview);
dialog = gtk_dialog_new_with_buttons (
new_engine ? _("Add search engine") : _("Edit search engine"),
toplevel ? GTK_WINDOW (toplevel) : NULL,
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
new_engine ? GTK_STOCK_ADD : GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
NULL);
gtk_window_set_icon_name (GTK_WINDOW (dialog),
new_engine ? GTK_STOCK_ADD : GTK_STOCK_REMOVE);
gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), 5);
sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
if (new_engine)
{
item = katze_item_new ();
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
GTK_RESPONSE_ACCEPT, FALSE);
}
else
{
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
gtk_tree_selection_get_selected (selection, &liststore, &iter);
gtk_tree_model_get (liststore, &iter, 0, &item, -1);
}
hbox = gtk_hbox_new (FALSE, 8);
gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
label = gtk_label_new_with_mnemonic (_("_Name:"));
gtk_size_group_add_widget (sizegroup, label);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
entry_name = gtk_entry_new ();
g_signal_connect (entry_name, "changed",
G_CALLBACK (midori_search_entry_editor_name_changed_cb), dialog);
gtk_entry_set_activates_default (GTK_ENTRY (entry_name), TRUE);
if (!new_engine)
gtk_entry_set_text (GTK_ENTRY (entry_name),
STR_NON_NULL (katze_item_get_name (item)));
gtk_box_pack_start (GTK_BOX (hbox), entry_name, TRUE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox);
gtk_widget_show_all (hbox);
hbox = gtk_hbox_new (FALSE, 8);
gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
label = gtk_label_new_with_mnemonic (_("_Description:"));
gtk_size_group_add_widget (sizegroup, label);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
entry_description = gtk_entry_new ();
gtk_entry_set_activates_default (GTK_ENTRY (entry_description), TRUE);
if (!new_engine)
gtk_entry_set_text (GTK_ENTRY (entry_description)
, STR_NON_NULL (katze_item_get_text (item)));
gtk_box_pack_start (GTK_BOX (hbox), entry_description, TRUE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox);
gtk_widget_show_all (hbox);
hbox = gtk_hbox_new (FALSE, 8);
gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
label = gtk_label_new_with_mnemonic (_("_URL:"));
gtk_size_group_add_widget (sizegroup, label);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
entry_uri = gtk_entry_new ();
gtk_entry_set_activates_default (GTK_ENTRY (entry_uri), TRUE);
if (!new_engine)
gtk_entry_set_text (GTK_ENTRY (entry_uri)
, STR_NON_NULL (katze_item_get_uri (item)));
gtk_box_pack_start (GTK_BOX (hbox), entry_uri, TRUE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox);
gtk_widget_show_all (hbox);
hbox = gtk_hbox_new (FALSE, 8);
gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
label = gtk_label_new_with_mnemonic (_("_Icon (name or file):"));
gtk_size_group_add_widget (sizegroup, label);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
entry_icon = gtk_entry_new ();
gtk_entry_set_activates_default (GTK_ENTRY (entry_icon), TRUE);
if (!new_engine)
gtk_entry_set_text (GTK_ENTRY (entry_icon)
, STR_NON_NULL (katze_item_get_icon (item)));
gtk_box_pack_start (GTK_BOX (hbox), entry_icon, TRUE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox);
gtk_widget_show_all (hbox);
hbox = gtk_hbox_new (FALSE, 8);
gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
label = gtk_label_new_with_mnemonic (_("_Token:"));
gtk_size_group_add_widget (sizegroup, label);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
entry_token = gtk_entry_new ();
gtk_entry_set_activates_default (GTK_ENTRY (entry_token), TRUE);
if (!new_engine)
gtk_entry_set_text (GTK_ENTRY (entry_token)
, STR_NON_NULL (katze_item_get_token (item)));
gtk_box_pack_start (GTK_BOX (hbox), entry_token, TRUE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox);
gtk_widget_show_all (hbox);
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
{
g_object_set (item,
"name", gtk_entry_get_text (GTK_ENTRY (entry_name)),
"text", gtk_entry_get_text (GTK_ENTRY (entry_description)),
"uri", gtk_entry_get_text (GTK_ENTRY (entry_uri)),
"icon", gtk_entry_get_text (GTK_ENTRY (entry_icon)),
"token", gtk_entry_get_text (GTK_ENTRY (entry_token)),
NULL);
search_entry = g_object_get_data (G_OBJECT (treeview), "search-entry");
if (new_engine)
katze_array_add_item (search_entry->search_engines, item);
}
gtk_widget_destroy (dialog);
}
static void
midori_search_entry_dialog_add_cb (GtkWidget* widget,
GtkWidget* treeview)
{
MidoriSearchEntry* search_entry;
search_entry = g_object_get_data (G_OBJECT (treeview), "search-entry");
midori_search_entry_get_editor (treeview, TRUE);
}
static void
midori_search_entry_dialog_edit_cb (GtkWidget* widget,
GtkWidget* treeview)
{
MidoriSearchEntry* search_entry;
GtkTreeSelection* selection;
search_entry = g_object_get_data (G_OBJECT (treeview), "search-entry");
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
if (gtk_tree_selection_get_selected (selection, NULL, NULL))
midori_search_entry_get_editor (treeview, FALSE);
}
static void
midori_search_entry_dialog_remove_cb (GtkWidget* widget,
GtkWidget* treeview)
{
MidoriSearchEntry* search_entry;
GtkTreeSelection* selection;
GtkTreeModel* liststore;
GtkTreeIter iter;
KatzeItem* item;
KatzeArray* search_engines;
search_entry = g_object_get_data (G_OBJECT (treeview), "search-entry");
search_engines = search_entry->search_engines;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
if (gtk_tree_selection_get_selected (selection, &liststore, &iter))
{
gtk_tree_model_get (liststore, &iter, 0, &item, -1);
katze_array_remove_item (search_engines, item);
g_object_unref (item);
/* FIXME: we want to allow undo of some kind */
}
}
static void
midori_search_entry_treeview_selection_cb (GtkTreeSelection* selection,
GtkWidget* treeview)
{
gboolean selected;
GtkWidget* edit_button;
GtkWidget* remove_button;
selected = gtk_tree_selection_get_selected (selection, NULL, NULL);
edit_button = g_object_get_data (G_OBJECT (treeview), "edit-button");
remove_button = g_object_get_data (G_OBJECT (treeview), "remove-button");
gtk_widget_set_sensitive (edit_button, selected);
gtk_widget_set_sensitive (remove_button, selected);
}
static void
midori_search_entry_dialog_engines_add_item_cb (KatzeArray* list,
KatzeItem* item,
GtkWidget* treeview)
{
GtkTreeModel* liststore;
GtkTreeIter iter;
liststore = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
gtk_list_store_append (GTK_LIST_STORE (liststore), &iter);
gtk_list_store_set (GTK_LIST_STORE (liststore), &iter, 0, item, -1);
}
static void
midori_search_entry_dialog_engines_remove_item_cb (KatzeArray* list,
KatzeItem* item,
GtkWidget* treeview)
{
GtkTreeModel* liststore;
GtkTreeIter iter;
gboolean valid;
KatzeItem* found_item;
liststore = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
valid = gtk_tree_model_get_iter_first (liststore, &iter);
while (valid)
{
gtk_tree_model_get (liststore, &iter, 0, &found_item, -1);
if (found_item == item)
{
gtk_list_store_remove (GTK_LIST_STORE (liststore), &iter);
valid = FALSE;
}
else
valid = gtk_tree_model_iter_next (liststore, &iter);
}
}
static void
midori_search_entry_treeview_destroy_cb (GtkWidget* treeview,
GtkWidget* search_entry)
{
g_signal_handlers_disconnect_by_func (
MIDORI_SEARCH_ENTRY (search_entry)->search_engines,
midori_search_entry_dialog_engines_add_item_cb, treeview);
g_signal_handlers_disconnect_by_func (
MIDORI_SEARCH_ENTRY (search_entry)->search_engines,
midori_search_entry_dialog_engines_remove_item_cb, treeview);
}
/**
* midori_search_entry_get_dialog:
* @search_entry: a #MidoriSearchEntry
*
* Obtains a dialog that provides an interface for managing
* the list of search engines.
*
* A new dialog is created each time, so it may be a good idea
* to store the pointer for the life time of the dialog.
*
* Return value: a dialog
**/
GtkWidget*
midori_search_entry_get_dialog (MidoriSearchEntry* search_entry)
{
static GtkWidget* dialog = NULL;
const gchar* dialog_title;
GtkWidget* toplevel;
gint width, height;
GtkWidget* xfce_heading;
GtkWidget* hbox;
GtkTreeViewColumn* column;
GtkCellRenderer* renderer_text;
GtkCellRenderer* renderer_pixbuf;
GtkListStore* liststore;
GtkWidget* treeview;
GtkWidget* scrolled;
guint n, i;
KatzeItem* item;
GtkWidget* vbox;
GtkWidget* button;
g_return_val_if_fail (MIDORI_IS_SEARCH_ENTRY (search_entry), NULL);
/* If there is a dialog, use that. We want only one. */
if (dialog)
return dialog;
dialog_title = _("Manage search engines");
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (search_entry));
dialog = gtk_dialog_new_with_buttons (dialog_title,
toplevel ? GTK_WINDOW (toplevel) : NULL,
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
GTK_STOCK_HELP, GTK_RESPONSE_HELP,
GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
NULL);
g_signal_connect (dialog, "destroy",
G_CALLBACK (gtk_widget_destroyed), &dialog);
gtk_window_set_icon_name (GTK_WINDOW (dialog), GTK_STOCK_PROPERTIES);
/* TODO: Implement some kind of help function */
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
GTK_RESPONSE_HELP, FALSE);
sokoke_widget_get_text_size (dialog, "M", &width, &height);
gtk_window_set_default_size (GTK_WINDOW (dialog), width * 45, -1);
g_signal_connect (dialog, "response",
G_CALLBACK (gtk_widget_destroy), dialog);
/* TODO: Do we want tooltips for explainations or can we omit that?
We need mnemonics */
if ((xfce_heading = sokoke_xfce_header_new (
gtk_window_get_icon_name (GTK_WINDOW (dialog)), dialog_title)))
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
xfce_heading, FALSE, FALSE, 0);
hbox = gtk_hbox_new (FALSE, 0);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox,
TRUE, TRUE, 12);
liststore = gtk_list_store_new (1, KATZE_TYPE_ITEM);
treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (liststore));
g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)),
"changed", G_CALLBACK (midori_search_entry_treeview_selection_cb),
treeview);
g_object_set_data (G_OBJECT (treeview), "search-entry", search_entry);
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
column = gtk_tree_view_column_new ();
renderer_pixbuf = gtk_cell_renderer_pixbuf_new ();
gtk_tree_view_column_pack_start (column, renderer_pixbuf, FALSE);
gtk_tree_view_column_set_cell_data_func (column, renderer_pixbuf,
(GtkTreeCellDataFunc)midori_search_entry_dialog_render_icon_cb,
treeview, NULL);
renderer_text = gtk_cell_renderer_text_new ();
gtk_tree_view_column_pack_start (column, renderer_text, TRUE);
gtk_tree_view_column_set_cell_data_func (column, renderer_text,
(GtkTreeCellDataFunc)midori_search_entry_dialog_render_text,
treeview, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
scrolled = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_container_add (GTK_CONTAINER (scrolled), treeview);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled),
GTK_SHADOW_IN);
gtk_box_pack_start (GTK_BOX (hbox), scrolled, TRUE, TRUE, 5);
n = katze_array_get_length (search_entry->search_engines);
for (i = 0; i < n; i++)
{
item = katze_array_get_nth_item (search_entry->search_engines, i);
gtk_list_store_insert_with_values (GTK_LIST_STORE (liststore),
NULL, i, 0, item, -1);
}
g_object_unref (liststore);
g_signal_connect (treeview, "destroy",
G_CALLBACK (midori_search_entry_treeview_destroy_cb), search_entry);
vbox = gtk_vbox_new (FALSE, 4);
gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 4);
button = gtk_button_new_from_stock (GTK_STOCK_ADD);
g_signal_connect (button, "clicked",
G_CALLBACK (midori_search_entry_dialog_add_cb), treeview);
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
button = gtk_button_new_from_stock (GTK_STOCK_EDIT);
g_signal_connect (button, "clicked",
G_CALLBACK (midori_search_entry_dialog_edit_cb), treeview);
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
g_object_set_data (G_OBJECT (treeview), "edit-button", button);
if (!n)
gtk_widget_set_sensitive (button, FALSE);
button = gtk_button_new_from_stock (GTK_STOCK_REMOVE);
g_signal_connect (button, "clicked",
G_CALLBACK (midori_search_entry_dialog_remove_cb), treeview);
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
if (!n)
gtk_widget_set_sensitive (button, FALSE);
g_object_set_data (G_OBJECT (treeview), "remove-button", button);
button = gtk_label_new (""); /* This is an invisible separator */
gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 12);
button = gtk_button_new_from_stock (GTK_STOCK_GO_DOWN);
gtk_widget_set_sensitive (button, FALSE);
gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
button = gtk_button_new_from_stock (GTK_STOCK_GO_UP);
gtk_widget_set_sensitive (button, FALSE);
gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_widget_show_all (GTK_DIALOG (dialog)->vbox);
g_object_connect (search_entry->search_engines,
"signal-after::add-item",
midori_search_entry_dialog_engines_add_item_cb, treeview,
"signal-after::remove-item",
midori_search_entry_dialog_engines_remove_item_cb, treeview,
NULL);
return dialog;
}