talons

Fork of Claws Mail https://www.claws-mail
Log | Files | Refs | README | LICENSE

commit 55b0731e456ae9ea9b5c7bfed492c3c1bdca2dcf
parent 7f04adf77791ed35dda966d0c25a9637b22fbfbb
Author: Holger Berndt <hb@claws-mail.org>
Date:   Tue, 17 Nov 2009 15:15:15 +0000

2009-11-17 [holger]	3.7.3cvs14

	* src/prefs_toolbar.c
	* src/prefs_toolbar.h
	* src/toolbar.c
	* src/toolbar.h
		Allow plugins to register toolbar items

Diffstat:
MChangeLog | 8++++++++
MPATCHSETS | 1+
Mconfigure.ac | 2+-
Msrc/prefs_toolbar.c | 190+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Msrc/prefs_toolbar.h | 6++++++
Msrc/toolbar.c | 19++++++++++++++++---
Msrc/toolbar.h | 2++
7 files changed, 216 insertions(+), 12 deletions(-)

diff --git a/ChangeLog b/ChangeLog @@ -1,3 +1,11 @@ +2009-11-17 [holger] 3.7.3cvs14 + + * src/prefs_toolbar.c + * src/prefs_toolbar.h + * src/toolbar.c + * src/toolbar.h + Allow plugins to register toolbar items + 2009-11-11 [pawel] 3.7.3cvs13 * src/addressbook.c diff --git a/PATCHSETS b/PATCHSETS @@ -3887,3 +3887,4 @@ ( cvs diff -u -r 1.1.2.8 -r 1.1.2.9 src/gtk/spell_entry.c; ) > 3.7.3cvs11.patchset ( cvs diff -u -r 1.12.2.53 -r 1.12.2.54 src/gtk/prefswindow.c; ) > 3.7.3cvs12.patchset ( cvs diff -u -r 1.60.2.134 -r 1.60.2.135 src/addressbook.c; cvs diff -u -r 1.382.2.524 -r 1.382.2.525 src/compose.c; cvs diff -u -r 1.50.2.55 -r 1.50.2.56 src/compose.h; cvs diff -u -r 1.60.2.53 -r 1.60.2.54 src/filtering.c; ) > 3.7.3cvs13.patchset +( cvs diff -u -r 1.30.2.57 -r 1.30.2.58 src/prefs_toolbar.c; cvs diff -u -r 1.5.2.6 -r 1.5.2.7 src/prefs_toolbar.h; cvs diff -u -r 1.43.2.110 -r 1.43.2.111 src/toolbar.c; cvs diff -u -r 1.19.2.31 -r 1.19.2.32 src/toolbar.h; ) > 3.7.3cvs14.patchset diff --git a/configure.ac b/configure.ac @@ -12,7 +12,7 @@ MINOR_VERSION=7 MICRO_VERSION=3 INTERFACE_AGE=0 BINARY_AGE=0 -EXTRA_VERSION=13 +EXTRA_VERSION=14 EXTRA_RELEASE= EXTRA_GTK2_VERSION= diff --git a/src/prefs_toolbar.c b/src/prefs_toolbar.c @@ -48,6 +48,7 @@ #include "prefs_toolbar.h" #include "prefswindow.h" #include "prefs_gtk.h" +#include "plugin.h" enum { @@ -64,7 +65,8 @@ enum { ITEM_FUNCTION = 0, ITEM_USER_ACTION = 1, - ITEM_SEPARATOR = 2 + ITEM_SEPARATOR = 2, + ITEM_PLUGIN = 3, }; static const gint ToolbarIcons[] = @@ -158,6 +160,7 @@ typedef struct _ToolbarPage GtkWidget *item_type_combo; /* item type selection widget */ GtkWidget *item_func_combo; /* item internal function widget */ GtkWidget *item_action_combo; /* item user action widget */ + GtkWidget *item_plugin_combo; /* items registered by plugins */ GtkWidget *icon_button; /* item icon chooser widget */ GtkWidget *icon_chooser_win; @@ -171,6 +174,17 @@ typedef struct _ToolbarPage #define ERROR_MSG_NO_ICON _("Item has no icon defined.") #define ERROR_MSG_NO_TEXT _("Item has no text defined.") +typedef struct _ToolbarPluginItem ToolbarPluginItem; +struct _ToolbarPluginItem { + gchar *plugin; + gchar *item_name; + ToolbarPluginCallback cb; + gpointer cb_data; +}; + +/* items registered by plugins */ +static GHashTable *plugin_items = NULL; + static void prefs_toolbar_populate (ToolbarPage *prefs_toolbar); static void get_action_name (const gchar *entry, @@ -195,6 +209,8 @@ static void prefs_toolbar_down (GtkButton *button, static void action_selection_changed (GtkComboBox *action_combo, ToolbarPage *prefs_toolbar); +static void plugin_selection_changed (GtkComboBox *action_combo, + ToolbarPage *prefs_toolbar); static void func_selection_changed (GtkComboBox *action_combo, ToolbarPage *prefs_toolbar); @@ -337,6 +353,11 @@ static void prefs_toolbar_set_displayed(ToolbarPage *prefs_toolbar) &iter); } +static void add_item_to_plugin_combo(gpointer key, gpointer data, gpointer combo_box) +{ + gtk_combo_box_append_text(GTK_COMBO_BOX(combo_box), (const gchar*)key); +} + static void prefs_toolbar_populate(ToolbarPage *prefs_toolbar) { GSList *cur; @@ -361,8 +382,13 @@ static void prefs_toolbar_populate(ToolbarPage *prefs_toolbar) } + /* items registered by plugins */ + if(plugin_items) + g_hash_table_foreach(plugin_items, add_item_to_plugin_combo, prefs_toolbar->item_plugin_combo); + gtk_combo_box_set_active(GTK_COMBO_BOX(prefs_toolbar->item_func_combo), 0); gtk_combo_box_set_active(GTK_COMBO_BOX(prefs_toolbar->item_action_combo), 0); + gtk_combo_box_set_active(GTK_COMBO_BOX(prefs_toolbar->item_plugin_combo), 0); prefs_toolbar_set_displayed(prefs_toolbar); @@ -471,7 +497,9 @@ static void prefs_toolbar_register(GtkButton *button, ToolbarPage *prefs_toolbar g_free(event); return; } - } else + } else if(item_type == ITEM_PLUGIN) + event = toolbar_ret_descr_from_val(A_CLAWS_PLUGINS); + else event = toolbar_ret_descr_from_val(A_CLAWS_ACTIONS); text = gtk_editable_get_chars( @@ -493,7 +521,7 @@ static void prefs_toolbar_register(GtkButton *button, ToolbarPage *prefs_toolbar } g_free(text); - if(item_type != ITEM_USER_ACTION) + if((item_type != ITEM_USER_ACTION) && (item_type != ITEM_PLUGIN)) g_free(event); } @@ -557,7 +585,9 @@ static void prefs_toolbar_substitute(GtkButton *button, ToolbarPage *prefs_toolb g_free(set_event); return; } - } else + } else if(item_type == ITEM_PLUGIN) + icon_event = toolbar_ret_descr_from_val(A_CLAWS_PLUGINS); + else icon_event = toolbar_ret_descr_from_val(A_CLAWS_ACTIONS); text = gtk_editable_get_chars( @@ -578,8 +608,8 @@ static void prefs_toolbar_substitute(GtkButton *button, ToolbarPage *prefs_toolb g_free(text); g_free(set_event); - if(item_type != ITEM_USER_ACTION) - g_free(icon_event); + if((item_type != ITEM_USER_ACTION) && (item_type != ITEM_PLUGIN)) + g_free(icon_event); } } @@ -678,6 +708,7 @@ static void item_type_changed(GtkComboBox *item_type_combo, case ITEM_FUNCTION: gtk_widget_show(prefs_toolbar->item_func_combo); gtk_widget_hide(prefs_toolbar->item_action_combo); + gtk_widget_hide(prefs_toolbar->item_plugin_combo); gtk_combo_box_set_active( GTK_COMBO_BOX(prefs_toolbar->item_func_combo), 0); gtk_button_set_label(GTK_BUTTON(prefs_toolbar->icon_button), ""); @@ -691,6 +722,7 @@ static void item_type_changed(GtkComboBox *item_type_combo, case ITEM_USER_ACTION: gtk_widget_show(prefs_toolbar->item_action_combo); gtk_widget_hide(prefs_toolbar->item_func_combo); + gtk_widget_hide(prefs_toolbar->item_plugin_combo); gtk_combo_box_set_active( GTK_COMBO_BOX(prefs_toolbar->item_action_combo), 0); gtk_button_set_label(GTK_BUTTON(prefs_toolbar->icon_button), ""); @@ -710,12 +742,26 @@ static void item_type_changed(GtkComboBox *item_type_combo, GTK_COMBO_BOX(prefs_toolbar->item_func_combo), -1); gtk_combo_box_set_active( GTK_COMBO_BOX(prefs_toolbar->item_action_combo), -1); + gtk_combo_box_set_active( + GTK_COMBO_BOX(prefs_toolbar->item_plugin_combo), -1); gtk_entry_set_text(GTK_ENTRY(prefs_toolbar->item_text_entry), ""); gtk_widget_set_sensitive(prefs_toolbar->item_action_combo, FALSE); gtk_widget_set_sensitive(prefs_toolbar->item_text_entry, FALSE); + gtk_widget_set_sensitive(prefs_toolbar->item_plugin_combo, FALSE); gtk_widget_set_sensitive(prefs_toolbar->item_func_combo, FALSE); gtk_widget_set_sensitive(prefs_toolbar->icon_button, FALSE); break; + case ITEM_PLUGIN: + gtk_widget_show(prefs_toolbar->item_plugin_combo); + gtk_widget_hide(prefs_toolbar->item_func_combo); + gtk_widget_hide(prefs_toolbar->item_action_combo); + gtk_combo_box_set_active(GTK_COMBO_BOX(prefs_toolbar->item_plugin_combo), 0); + gtk_button_set_label(GTK_BUTTON(prefs_toolbar->icon_button), ""); + gtk_widget_set_sensitive(prefs_toolbar->item_text_entry, TRUE); + gtk_widget_set_sensitive(prefs_toolbar->item_plugin_combo, TRUE); + gtk_widget_set_sensitive(prefs_toolbar->icon_button, TRUE); + plugin_selection_changed(GTK_COMBO_BOX(prefs_toolbar->item_plugin_combo), prefs_toolbar); + break; } } @@ -732,6 +778,17 @@ static void action_selection_changed(GtkComboBox *action_combo, } } +static void plugin_selection_changed(GtkComboBox *action_combo, + ToolbarPage *prefs_toolbar) +{ + gchar *text = gtk_combo_box_get_active_text(GTK_COMBO_BOX(prefs_toolbar->item_plugin_combo)); + + if(text != NULL) { /* action */ + gtk_entry_set_text(GTK_ENTRY(prefs_toolbar->item_text_entry), text); + g_free(text); + } +} + static void func_selection_changed(GtkComboBox *action_combo, ToolbarPage *prefs_toolbar) { @@ -768,6 +825,7 @@ static void prefs_toolbar_create(ToolbarPage *prefs_toolbar) GtkWidget *icon_hbox; GtkWidget *item_type_combo; GtkWidget *item_action_combo; + GtkWidget *item_plugin_combo; GtkWidget *item_func_combo; GtkWidget *reg_hbox; GtkWidget *arrow; @@ -822,7 +880,7 @@ static void prefs_toolbar_create(ToolbarPage *prefs_toolbar) (GtkAttachOptions) (0), 0, 0); item_type_combo = combobox_text_new(FALSE, _("Internal Function"), - _("User Action"), _("Separator"), NULL); + _("User Action"), _("Separator"), _("Plugins"), NULL); gtk_widget_set_size_request(item_type_combo, 200, -1); gtk_table_attach(GTK_TABLE(table), item_type_combo, 1, 3, 0, 1, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), @@ -848,6 +906,13 @@ static void prefs_toolbar_create(ToolbarPage *prefs_toolbar) (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0); + /* plugin-registered items */ + item_plugin_combo = gtk_combo_box_new_text(); + gtk_widget_set_size_request(item_plugin_combo, 200, -1); + gtk_table_attach(GTK_TABLE(table), item_plugin_combo, 1, 3, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + /* toolbar item description */ label_icon_text = gtk_label_new(_("Toolbar text")); gtk_misc_set_alignment(GTK_MISC(label_icon_text), 0, 0.5); @@ -966,6 +1031,8 @@ static void prefs_toolbar_create(ToolbarPage *prefs_toolbar) G_CALLBACK(item_type_changed), prefs_toolbar); g_signal_connect(G_OBJECT(item_action_combo), "changed", G_CALLBACK(action_selection_changed), prefs_toolbar); + g_signal_connect(G_OBJECT(item_plugin_combo), "changed", + G_CALLBACK(plugin_selection_changed), prefs_toolbar); g_signal_connect(G_OBJECT(item_func_combo), "changed", G_CALLBACK(func_selection_changed), prefs_toolbar); g_signal_connect(G_OBJECT(up_btn), "clicked", @@ -980,6 +1047,7 @@ static void prefs_toolbar_create(ToolbarPage *prefs_toolbar) prefs_toolbar->item_type_combo = item_type_combo; prefs_toolbar->item_func_combo = item_func_combo; prefs_toolbar->item_action_combo= item_action_combo; + prefs_toolbar->item_plugin_combo= item_plugin_combo; prefs_toolbar->icon_button = icon_button; prefs_toolbar->item_icon_file = NULL; @@ -990,6 +1058,83 @@ ToolbarPage *prefs_toolbar_mainwindow; ToolbarPage *prefs_toolbar_composewindow; ToolbarPage *prefs_toolbar_messageview; +void prefs_toolbar_unregister_plugin_item(const gchar *plugin_name, const gchar *item_name) +{ + gchar *key; + + if(!plugin_items) + return; + + key = g_strdup_printf(plugin_name, "/", item_name, NULL); + g_hash_table_remove(plugin_items, key); + g_free(key); +} + +void prefs_toolbar_execute_plugin_item(const gchar *id) +{ + ToolbarPluginItem *value; + GSList *walk; + gboolean found; + + if(!plugin_items) { + debug_print("No plugin registered toolbar items yet\n"); + return; + } + + value = g_hash_table_lookup(plugin_items, id); + if(!value) { + debug_print("Could not find plugin toolbar item with id %s\n", id); + return; + } + + /* check if corresponding plugin is currently loaded */ + found = FALSE; + for(walk = plugin_get_list(); walk; walk = walk->next) { + const gchar *plugin_name; + Plugin *plugin = walk->data; + plugin_name = plugin_get_name(plugin); + if(!strcmp(plugin_name, value->plugin)) { + found = TRUE; + break; + } + } + if(!found) { + debug_print("Plugin '%s' is currently not loaded, cannot execute toolbar action\n", value->plugin); + return; + } + + value->cb(value->item_name, value->cb_data); +} + +static void destroy_plugin_item_hash_value(ToolbarPluginItem *item) +{ + g_free(item->plugin); + g_free(item->item_name); + g_free(item); +} + +void prefs_toolbar_register_plugin_item(const gchar *plugin_name, const gchar *item_name, ToolbarPluginCallback cb, gpointer cb_data) +{ + gchar *key; + ToolbarPluginItem *value; + + cm_return_if_fail(plugin_name && item_name); + + if(!plugin_items) { + plugin_items = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)destroy_plugin_item_hash_value); + if(!plugin_items) + return; + } + + key = g_strconcat(plugin_name, "/", item_name, NULL); + value = g_new0(ToolbarPluginItem, 1); + value->plugin = g_strdup(plugin_name); + value->item_name = g_strdup(item_name); + value->cb = cb; + value->cb_data = cb_data; + g_hash_table_insert(plugin_items, key, value); +} + void prefs_toolbar_init(void) { ToolbarPage *page; @@ -1217,15 +1362,44 @@ static gboolean set_list_selected(GtkTreeSelection *selector, g_free(item_string); } } - + gtk_widget_show(prefs_toolbar->item_action_combo); gtk_widget_hide(prefs_toolbar->item_func_combo); + gtk_widget_hide(prefs_toolbar->item_plugin_combo); g_free(icon_text); g_free(descr); return TRUE; } + + if (g_utf8_collate(toolbar_ret_descr_from_val(A_CLAWS_PLUGINS), descr) == 0) { + gint num_items, ii; + gchar *txt; + + gtk_combo_box_set_active(GTK_COMBO_BOX(prefs_toolbar->item_type_combo), ITEM_PLUGIN); + + /* set combo box correctly */ + num_items = g_hash_table_size(plugin_items); + for(ii = 0; ii < num_items; ii++) { + gtk_combo_box_set_active(GTK_COMBO_BOX(prefs_toolbar->item_plugin_combo), ii); + txt = gtk_combo_box_get_active_text(GTK_COMBO_BOX(prefs_toolbar->item_plugin_combo)); + if(!g_utf8_collate(txt, icon_text)) { + break; + } + } + if(ii == num_items) + gtk_combo_box_set_active(GTK_COMBO_BOX(prefs_toolbar->item_plugin_combo), -1); + + gtk_widget_show(prefs_toolbar->item_plugin_combo); + gtk_widget_hide(prefs_toolbar->item_func_combo); + gtk_widget_hide(prefs_toolbar->item_action_combo); + + g_free(descr); + g_free(icon_text); + return TRUE; + } + /* scan combo list for selected description an set combo item accordingly */ for (cur = prefs_toolbar->combo_action_list, item_num = 0; cur != NULL; diff --git a/src/prefs_toolbar.h b/src/prefs_toolbar.h @@ -23,4 +23,10 @@ void prefs_toolbar_init (void); void prefs_toolbar_done (void); +typedef void (*ToolbarPluginCallback)(const gchar *item_name, gpointer data); + +void prefs_toolbar_register_plugin_item(const gchar *plugin_name, const gchar *item_name, ToolbarPluginCallback cb, gpointer cb_data); +void prefs_toolbar_unregister_plugin_item(const gchar *plugin_name, const gchar *item_name); +void prefs_toolbar_execute_plugin_item(const gchar *id); + #endif /* __PREFS_CUSTOM_TOOLBAR_H__ */ diff --git a/src/toolbar.c b/src/toolbar.c @@ -136,6 +136,8 @@ static void toolbar_print_cb (GtkWidget *widget, static void toolbar_actions_execute_cb (GtkWidget *widget, gpointer data); +static void toolbar_plugins_execute_cb (GtkWidget *widget, + gpointer data); static void toolbar_send_cb (GtkWidget *widget, @@ -214,7 +216,8 @@ struct { { "A_CLAWS_ACTIONS", N_("Claws Mail Actions Feature") }, { "A_CANCEL_INC", N_("Cancel receiving") }, { "A_CLOSE", N_("Close window") }, - { "A_SEPARATOR", N_("Separator") } + { "A_SEPARATOR", N_("Separator") }, + { "A_CLAWS_PLUGINS", N_("Claws Mail Plugins") }, }; /* struct holds configuration files and a list of @@ -273,7 +276,7 @@ static gboolean toolbar_is_duplicate(gint action, ToolbarType source) { GSList *cur; - if ((action == A_SEPARATOR) || (action == A_CLAWS_ACTIONS)) + if ((action == A_SEPARATOR) || (action == A_CLAWS_ACTIONS) || (action == A_CLAWS_PLUGINS)) return FALSE; for (cur = toolbar_config[source].item_list; cur != NULL; cur = cur->next) { @@ -1618,6 +1621,12 @@ static void toolbar_actions_execute_cb(GtkWidget *widget, gpointer data) toolbar_action_execute(widget, action_list, parent, toolbar_item->type); } +static void toolbar_plugins_execute_cb(GtkWidget *widget, gpointer data) +{ + ToolbarItem *toolbar_item = data; + prefs_toolbar_execute_plugin_item(toolbar_item->text); +} + static MainWindow *get_mainwin(gpointer data) { ToolbarItem *toolbar_item = (ToolbarItem*)data; @@ -1712,7 +1721,8 @@ static void toolbar_buttons_cb(GtkWidget *widget, { A_CHECK_SPELLING, toolbar_check_spelling_cb }, #endif { A_CLAWS_ACTIONS, toolbar_actions_execute_cb }, - { A_CANCEL_INC, toolbar_cancel_inc_cb } + { A_CANCEL_INC, toolbar_cancel_inc_cb }, + { A_CLAWS_PLUGINS, toolbar_plugins_execute_cb }, }; num_items = sizeof(callbacks)/sizeof(callbacks[0]); @@ -2112,6 +2122,9 @@ Toolbar *toolbar_create(ToolbarType type, TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,_("Cancel receiving")); toolbar_data->cancel_inc_btn = item; break; + case A_CLAWS_PLUGINS: + TOOLBAR_ITEM(item,icon_wid,toolbar_item->text, toolbar_item->text); + break; default: TOOLBAR_ITEM(item,icon_wid,toolbar_item->text, toolbar_ret_descr_from_val(toolbar_item->index)); diff --git a/src/toolbar.h b/src/toolbar.h @@ -198,6 +198,8 @@ enum { A_SEPARATOR, + A_CLAWS_PLUGINS, + N_ACTION_VAL };