2009-11-17 [holger] 3.7.3cvs14
authorHolger Berndt <hb@claws-mail.org>
Tue, 17 Nov 2009 15:15:15 +0000 (15:15 +0000)
committerHolger Berndt <hb@claws-mail.org>
Tue, 17 Nov 2009 15:15:15 +0000 (15:15 +0000)
* src/prefs_toolbar.c
* src/prefs_toolbar.h
* src/toolbar.c
* src/toolbar.h
Allow plugins to register toolbar items

ChangeLog
PATCHSETS
configure.ac
src/prefs_toolbar.c
src/prefs_toolbar.h
src/toolbar.c
src/toolbar.h

index ba89a17..b5d5cb5 100644 (file)
--- 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
index 51a6021..d222e57 100644 (file)
--- a/PATCHSETS
+++ b/PATCHSETS
 ( 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
index b08bac1..8d783b8 100644 (file)
@@ -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=
 
index 65cd019..585179e 100644 (file)
@@ -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; 
index e2c43a3..e3db897 100644 (file)
 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__ */ 
index 581b845..5cc691d 100644 (file)
@@ -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));
index d0834e2..ac571f0 100644 (file)
@@ -198,6 +198,8 @@ enum {
 
        A_SEPARATOR,
 
+       A_CLAWS_PLUGINS,
+
        N_ACTION_VAL
 };