[balsa/gtk3] Restore toolbar editing



commit 29c3e9a501d25db397877656c55872962de7ca1a
Author: Peter Bloomfield <PeterBloomfield bellsouth net>
Date:   Tue Feb 17 20:39:25 2015 -0500

    Restore toolbar editing
    
        * src/main-window.c (balsa_window_get_toolbar_model),
        (bw_add_app_action_entries), (bw_add_win_action_entries),
        (balsa_window_add_action_entries), (bw_set_menus),
        (balsa_window_new):
        * src/main-window.h:
        * src/message-window.c (message_window_get_toolbar_model),
        (message_window_add_action_entries), (message_window_new):
        * src/message-window.h:
        * src/sendmsg-window.c (sendmsg_window_get_toolbar_model),
        (sendmsg_window_add_action_entries), (sendmsg_window_new):
        * src/sendmsg-window.h:
        * src/toolbar-factory.c (balsa_toolbar_model_finalize),
        (balsa_toolbar_model_init), (balsa_toolbar_remove_all),
        (tm_load_model), (tm_save_model), (balsa_toolbar_model_new),
        (tm_add_action), (balsa_toolbar_model_add_entries),
        (balsa_toolbar_model_get_current),
        (balsa_toolbar_model_is_standard),
        (balsa_toolbar_model_insert_icon), (balsa_toolbar_model_clear),
        (tm_has_second_line), (tm_populate), (tm_changed_cb),
        (tm_toolbar_weak_notify), (balsa_toolbar_new):
        * src/toolbar-factory.h:
        * src/toolbar-prefs.c (customize_dialog_cb), (wrap_toggled_cb),
        (create_toolbar_page), (tp_find_icon), (tp_page_refresh_available),
        (tp_page_refresh_current), (tp_store_set), (replace_nl_with_space):

 ChangeLog             |   29 +++++
 src/main-window.c     |   50 ++++++----
 src/main-window.h     |    1 +
 src/message-window.c  |   22 ++--
 src/message-window.h  |    1 +
 src/sendmsg-window.c  |   24 ++---
 src/sendmsg-window.h  |    1 +
 src/toolbar-factory.c |  274 ++++++++++++++++++++++++++++--------------------
 src/toolbar-factory.h |   23 ++--
 src/toolbar-prefs.c   |  100 ++++++++----------
 10 files changed, 300 insertions(+), 225 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 5e212b5..4309791 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2015-02-17  Peter Bloomfield  <pbloomfield bellsouth net>
+
+       Restore toolbar editing
+
+       * src/main-window.c (balsa_window_get_toolbar_model),
+       (bw_add_app_action_entries), (bw_add_win_action_entries),
+       (balsa_window_add_action_entries), (bw_set_menus),
+       (balsa_window_new):
+       * src/main-window.h:
+       * src/message-window.c (message_window_get_toolbar_model),
+       (message_window_add_action_entries), (message_window_new):
+       * src/message-window.h:
+       * src/sendmsg-window.c (sendmsg_window_get_toolbar_model),
+       (sendmsg_window_add_action_entries), (sendmsg_window_new):
+       * src/sendmsg-window.h:
+       * src/toolbar-factory.c (balsa_toolbar_model_finalize),
+       (balsa_toolbar_model_init), (balsa_toolbar_remove_all),
+       (tm_load_model), (tm_save_model), (balsa_toolbar_model_new),
+       (tm_add_action), (balsa_toolbar_model_add_entries),
+       (balsa_toolbar_model_get_current),
+       (balsa_toolbar_model_is_standard),
+       (balsa_toolbar_model_insert_icon), (balsa_toolbar_model_clear),
+       (tm_has_second_line), (tm_populate), (tm_changed_cb),
+       (tm_toolbar_weak_notify), (balsa_toolbar_new):
+       * src/toolbar-factory.h:
+       * src/toolbar-prefs.c (customize_dialog_cb), (wrap_toggled_cb),
+       (create_toolbar_page), (tp_find_icon), (tp_page_refresh_available),
+       (tp_page_refresh_current), (tp_store_set), (replace_nl_with_space):
+
 2015-02-16  Albrecht Dreß
 
        Disable SSLv3, with an option in the code to override, and
diff --git a/src/main-window.c b/src/main-window.c
index ef08d38..146f84a 100644
--- a/src/main-window.c
+++ b/src/main-window.c
@@ -664,22 +664,14 @@ BalsaToolbarModel *
 balsa_window_get_toolbar_model(void)
 {
     static BalsaToolbarModel *model = NULL;
-    GSList *standard;
-    guint i;
 
     if (model)
         return model;
 
-    standard = NULL;
-    for (i = 0; i < G_N_ELEMENTS(main_toolbar); i++) {
-        const BalsaToolbarEntry *entry = &main_toolbar[i];
-        standard = g_slist_prepend(standard, g_strdup(entry->action));
-        standard = g_slist_prepend(standard, g_strdup(entry->icon));
-    }
-    standard = g_slist_reverse(standard);
-
     model =
-        balsa_toolbar_model_new(BALSA_TOOLBAR_TYPE_MAIN_WINDOW, standard);
+        balsa_toolbar_model_new(BALSA_TOOLBAR_TYPE_MAIN_WINDOW,
+                                main_toolbar,
+                                G_N_ELEMENTS(main_toolbar));
     balsa_toolbar_model_add_entries(model, main_toolbar_extras,
                                     G_N_ELEMENTS(main_toolbar_extras));
 
@@ -1912,7 +1904,7 @@ threading_change_state(GSimpleAction * action,
  */
 
 static void
-bw_set_menus(BalsaWindow * window)
+bw_add_app_action_entries(GActionMap * action_map, gpointer user_data)
 {
     static GActionEntry app_entries[] = {
         {"new-message",           new_message_activated},
@@ -1930,6 +1922,14 @@ bw_set_menus(BalsaWindow * window)
         {"about",                 about_activated},
         {"quit",                  quit_activated}
     };
+
+    g_action_map_add_action_entries(action_map, app_entries,
+                                    G_N_ELEMENTS(app_entries), user_data);
+}
+
+static void
+bw_add_win_action_entries(GActionMap * action_map)
+{
     static GActionEntry win_entries[] = {
         {"new-message",           new_message_activated},
         {"continue",              continue_activated},
@@ -2019,17 +2019,27 @@ bw_set_menus(BalsaWindow * window)
         {"toggle-answered",       toggle_answered_activated},
         {"store-address",         store_address_activated}
     };
+
+    g_action_map_add_action_entries(action_map, win_entries,
+                                    G_N_ELEMENTS(win_entries), action_map);
+}
+
+void
+balsa_window_add_action_entries(GActionMap * action_map)
+{
+    bw_add_app_action_entries(action_map, NULL);
+    bw_add_win_action_entries(action_map);
+}
+
+static void
+bw_set_menus(BalsaWindow * window)
+{
     GtkBuilder *builder;
     gchar *ui_file;
     GError *err = NULL;
 
-    g_action_map_add_action_entries(G_ACTION_MAP(balsa_app.application),
-                                    app_entries, G_N_ELEMENTS(app_entries),
-                                    window);
-
-    g_action_map_add_action_entries(G_ACTION_MAP(window),
-                                    win_entries, G_N_ELEMENTS(win_entries),
-                                    window);
+    bw_add_app_action_entries(G_ACTION_MAP(balsa_app.application), window);
+    bw_add_win_action_entries(G_ACTION_MAP(window));
 
     builder = gtk_builder_new();
     ui_file = g_build_filename(BALSA_DATA_PREFIX, "ui", "main-window.ui",
@@ -2198,7 +2208,7 @@ balsa_window_new()
 
     model = balsa_window_get_toolbar_model();
 
-    window->toolbar = balsa_toolbar_new(model, G_OBJECT(window));
+    window->toolbar = balsa_toolbar_new(model, G_ACTION_MAP(window));
     gtk_box_pack_start(GTK_BOX(window->vbox), window->toolbar,
                        FALSE, FALSE, 0);
 
diff --git a/src/main-window.h b/src/main-window.h
index 46a7e0b..f5117bf 100644
--- a/src/main-window.h
+++ b/src/main-window.h
@@ -143,6 +143,7 @@ void check_new_messages_count(LibBalsaMailbox * mailbox, gboolean notify);
 void empty_trash(BalsaWindow * window);
 void update_view_menu(BalsaWindow * window);
 BalsaToolbarModel *balsa_window_get_toolbar_model(void);
+void balsa_window_add_action_entries(GActionMap * action_map);
 void balsa_window_select_all(GtkWindow * window);
 gboolean balsa_window_next_unread(BalsaWindow * window);
 
diff --git a/src/message-window.c b/src/message-window.c
index 900787a..7ee011d 100644
--- a/src/message-window.c
+++ b/src/message-window.c
@@ -186,23 +186,14 @@ BalsaToolbarModel *
 message_window_get_toolbar_model(void)
 {
     static BalsaToolbarModel *model = NULL;
-    GSList *standard;
-    guint i;
 
     if (model)
         return model;
 
-    standard = NULL;
-    for (i = 0; i < G_N_ELEMENTS(message_toolbar); i++) {
-        const BalsaToolbarEntry *entry = &message_toolbar[i];
-        standard = g_slist_prepend(standard, g_strdup(entry->action));
-        standard = g_slist_prepend(standard, g_strdup(entry->icon));
-    }
-    standard = g_slist_reverse(standard);
-
     model =
         balsa_toolbar_model_new(BALSA_TOOLBAR_TYPE_MESSAGE_WINDOW,
-                                standard);
+                                message_toolbar,
+                                G_N_ELEMENTS(message_toolbar));
     balsa_toolbar_model_add_entries(model, message_toolbar_extras,
                                     G_N_ELEMENTS(message_toolbar_extras));
 
@@ -816,6 +807,13 @@ static GActionEntry win_entries[] = {
 };
 
 void
+message_window_add_action_entries(GActionMap * action_map)
+{
+    g_action_map_add_action_entries(action_map, win_entries,
+                                    G_N_ELEMENTS(win_entries), action_map);
+}
+
+void
 message_window_new(LibBalsaMailbox * mailbox, guint msgno)
 {
     LibBalsaMessage *message;
@@ -879,7 +877,7 @@ message_window_new(LibBalsaMailbox * mailbox, guint msgno)
 
     model = message_window_get_toolbar_model();
 
-    mw->toolbar = balsa_toolbar_new(model, G_OBJECT(window));
+    mw->toolbar = balsa_toolbar_new(model, G_ACTION_MAP(window));
     gtk_box_pack_start(GTK_BOX(vbox), mw->toolbar, FALSE, FALSE, 0);
 
     gtk_window_set_wmclass(GTK_WINDOW(window), "message", "Balsa");
diff --git a/src/message-window.h b/src/message-window.h
index 8ac3ba0..231f645 100644
--- a/src/message-window.h
+++ b/src/message-window.h
@@ -30,5 +30,6 @@ typedef struct _MessageWindow MessageWindow;
 
 void message_window_new(LibBalsaMailbox * mailbox, guint msgno);
 BalsaToolbarModel *message_window_get_toolbar_model(void);
+void message_window_add_action_entries(GActionMap * action_map);
 
 #endif                         /* __MESSAGE_WINDOW_H__ */
diff --git a/src/sendmsg-window.c b/src/sendmsg-window.c
index 65134ad..140804b 100644
--- a/src/sendmsg-window.c
+++ b/src/sendmsg-window.c
@@ -4230,23 +4230,14 @@ BalsaToolbarModel *
 sendmsg_window_get_toolbar_model(void)
 {
     static BalsaToolbarModel *model = NULL;
-    GSList *standard;
-    guint i;
 
     if (model)
         return model;
 
-    standard = NULL;
-    for (i = 0; i < G_N_ELEMENTS(compose_toolbar); i++) {
-        const BalsaToolbarEntry *entry = &compose_toolbar[i];
-        standard = g_slist_prepend(standard, g_strdup(entry->action));
-        standard = g_slist_prepend(standard, g_strdup(entry->icon));
-    }
-    standard = g_slist_reverse(standard);
-
     model =
-        balsa_toolbar_model_new(BALSA_TOOLBAR_TYPE_MESSAGE_WINDOW,
-                                standard);
+        balsa_toolbar_model_new(BALSA_TOOLBAR_TYPE_COMPOSE_WINDOW,
+                                compose_toolbar,
+                                G_N_ELEMENTS(compose_toolbar));
     balsa_toolbar_model_add_entries(model, compose_toolbar_extras,
                                     G_N_ELEMENTS(compose_toolbar_extras));
 
@@ -6700,6 +6691,13 @@ static GActionEntry win_entries[] = {
     {"toolbar-send",     sw_toolbar_send_activated      }
 };
 
+void
+sendmsg_window_add_action_entries(GActionMap * action_map)
+{
+    g_action_map_add_action_entries(action_map, win_entries,
+                                    G_N_ELEMENTS(win_entries), action_map);
+}
+
 static void
 sw_menubar_foreach(GtkWidget *widget, gpointer data)
 {
@@ -6799,7 +6797,7 @@ sendmsg_window_new()
     gtk_box_pack_start(GTK_BOX(main_box), menubar, FALSE, FALSE, 0);
 #endif
 
-    bsmsg->toolbar = balsa_toolbar_new(model, G_OBJECT(window));
+    bsmsg->toolbar = balsa_toolbar_new(model, G_ACTION_MAP(window));
     gtk_box_pack_start(GTK_BOX(main_box), bsmsg->toolbar,
                        FALSE, FALSE, 0);
 
diff --git a/src/sendmsg-window.h b/src/sendmsg-window.h
index bdcb4f8..f9b2223 100644
--- a/src/sendmsg-window.h
+++ b/src/sendmsg-window.h
@@ -146,6 +146,7 @@ extern "C" {
                                                GArray * selected,
                                                SendType type);
     BalsaToolbarModel *sendmsg_window_get_toolbar_model(void);
+    void sendmsg_window_add_action_entries(GActionMap * action_map);
 
 #define SENDMSG_WINDOW_QUIT_ON_CLOSE(bsmsg) ((bsmsg)->quit_on_close=TRUE)
 
diff --git a/src/toolbar-factory.c b/src/toolbar-factory.c
index 03b7c87..f5122a5 100644
--- a/src/toolbar-factory.c
+++ b/src/toolbar-factory.c
@@ -48,8 +48,8 @@ struct BalsaToolbarModel_ {
     GObject object;
 
     GHashTable      *legal;
-    GSList          *standard;
-    GSList          *current;
+    GArray          *standard;
+    GArray          *current;
     BalsaToolbarType type;
     GtkToolbarStyle  style;
 #if HAVE_GNOME
@@ -69,9 +69,16 @@ static void
 balsa_toolbar_model_finalize(GObject * object)
 {
     BalsaToolbarModel *model = BALSA_TOOLBAR_MODEL(object);
-    g_hash_table_destroy(model->legal);
+
+    if (model->legal) {
+        g_hash_table_destroy(model->legal);
+        model->legal = NULL;
+    }
 #if HAVE_GNOME
-    g_object_unref(model->settings);
+    if (model->settings) {
+        g_object_unref(model->settings);
+        model->settings = NULL;
+    }
 #endif /* HAVE_GNOME */
     G_OBJECT_CLASS(parent_class)->finalize(object);
 }
@@ -98,7 +105,7 @@ static void
 balsa_toolbar_model_init(BalsaToolbarModel * model)
 {
     model->legal =
-        g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
+        g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
 }
 
 GType
@@ -133,7 +140,7 @@ balsa_toolbar_model_get_type()
 /* The descriptions must be SHORT */
 button_data toolbar_buttons[]={
     {"",                         N_("Separator"),       FALSE},
-    {"application-exit",             N_("Quit"),            FALSE},
+    {"application-exit",         N_("Quit"),            FALSE},
     {BALSA_PIXMAP_RECEIVE,       N_("Check"),           TRUE},
     {BALSA_PIXMAP_COMPOSE,       N_("Compose"),         TRUE},
     {BALSA_PIXMAP_CONTINUE,      N_("Continue"),        FALSE},
@@ -199,15 +206,13 @@ balsa_toolbar_sanitize_id(const gchar *id)
 }
 
 /* this should go to GTK because it modifies its internal structures. */
-void
+static void
 balsa_toolbar_remove_all(GtkWidget * widget)
 {
-    GList *child, *children;
+    GtkToolItem *item;
 
-    children = gtk_container_get_children(GTK_CONTAINER(widget));
-    for (child = children; child; child = child->next)
-        gtk_widget_destroy(child->data);
-    g_list_free(children);
+    while ((item = gtk_toolbar_get_nth_item((GtkToolbar *) widget, 0)))
+        gtk_container_remove((GtkContainer *) widget, (GtkWidget *) item);
 }
 
 /* Load and save config
@@ -217,9 +222,7 @@ static void
 tm_load_model(BalsaToolbarModel * model)
 {
     gchar *key;
-#ifdef LOADING_MODEL_IS_FIXED
     guint j;
-#endif
 
     key = g_strconcat("toolbar-", balsa_toolbar_names[model->type], NULL);
     libbalsa_conf_push_group(key);
@@ -227,22 +230,22 @@ tm_load_model(BalsaToolbarModel * model)
 
     model->style = libbalsa_conf_get_int_with_default("Style=-1", NULL);
 
-#ifdef LOADING_MODEL_IS_FIXED
-    model->current = NULL;
     for (j = 0;; j++) {
-        gchar *item;
+        BalsaToolbarEntry entry;
 
-        key = g_strdup_printf("Item%d", j);
-        item = libbalsa_conf_get_string(key);
+        key = g_strdup_printf("Action%d", j);
+        entry.action = libbalsa_conf_get_string(key);
         g_free(key);
 
-        if (!item)
+        if (!entry.action)
             break;
 
-        model->current = g_slist_prepend(model->current, item);
+        key = g_strdup_printf("Icon%d", j);
+        entry.icon = libbalsa_conf_get_string(key);
+        g_free(key);
+
+        g_array_append_val(model->current, entry);
     }
-    model->current = g_slist_reverse(model->current);
-#endif
 
     libbalsa_conf_pop_group();
 }
@@ -252,7 +255,6 @@ tm_save_model(BalsaToolbarModel * model)
 {
     gchar *key;
     guint j;
-    GSList *list;
 
     key = g_strconcat("toolbar-", balsa_toolbar_names[model->type], NULL);
     libbalsa_conf_remove_group(key);
@@ -262,11 +264,16 @@ tm_save_model(BalsaToolbarModel * model)
     if (model->style != (GtkToolbarStyle) (-1))
         libbalsa_conf_set_int("Style", model->style);
 
-    for (j = 0, list = model->current;
-         list;
-         j++, list = list->next) {
-        key = g_strdup_printf("Item%d", j);
-        libbalsa_conf_set_string(key, list->data);
+
+    for (j = 0; j < model->current->len; j++) {
+        BalsaToolbarEntry *entry;
+
+        entry = &g_array_index(model->current, BalsaToolbarEntry, j);
+        key = g_strdup_printf("Action%d", j);
+        libbalsa_conf_set_string(key, entry->action);
+        g_free(key);
+        key = g_strdup_printf("Icon%d", j);
+        libbalsa_conf_set_string(key, entry->icon);
         g_free(key);
     }
 
@@ -292,13 +299,27 @@ tm_gsettings_change_cb(GSettings   * settings,
 /* Create a BalsaToolbarModel structure.
  */
 BalsaToolbarModel *
-balsa_toolbar_model_new(BalsaToolbarType type, GSList * standard)
+balsa_toolbar_model_new(BalsaToolbarType          type,
+                        const BalsaToolbarEntry * entries,
+                        guint                     n_entries)
 {
-    BalsaToolbarModel *model =
-        g_object_new(BALSA_TYPE_TOOLBAR_MODEL, NULL);
+    guint i;
+    BalsaToolbarModel *model;
+
+    model = g_object_new(BALSA_TYPE_TOOLBAR_MODEL, NULL);
+
+    model->current = g_array_new(FALSE, FALSE, sizeof(BalsaToolbarEntry));
+    model->standard = g_array_new(FALSE, FALSE, sizeof(BalsaToolbarEntry));
+    for (i = 0; i < n_entries; i++) {
+        BalsaToolbarEntry entry;
+
+        entry.action = g_strdup(entries[i].action);
+        entry.icon   = g_strdup(entries[i].icon);
+        g_array_append_val(model->standard, entry);
+    }
 
     model->type = type;
-    model->standard = standard;
+    balsa_toolbar_model_add_entries(model, entries, n_entries);
     tm_load_model(model);
 
 #if HAVE_GNOME
@@ -323,13 +344,13 @@ balsa_toolbar_model_changed(BalsaToolbarModel * model)
 }
 
 static void
-tm_add_action(BalsaToolbarModel * model, const gchar * stock_id,
-              const gchar * name)
+tm_add_action(BalsaToolbarModel       * model,
+              const BalsaToolbarEntry * entry)
 {
     /* Check whether we have already seen this icon: */
-    if (stock_id && !g_hash_table_lookup(model->legal, stock_id))
-        g_hash_table_insert(model->legal, (gchar *) stock_id,
-                            (gchar *) name);
+    if (entry->icon && !g_hash_table_lookup(model->legal, entry->icon))
+        g_hash_table_insert(model->legal, g_strdup(entry->icon),
+                            g_strdup(entry->action));
 }
 
 void
@@ -337,11 +358,9 @@ balsa_toolbar_model_add_entries(BalsaToolbarModel       * model,
                                 const BalsaToolbarEntry * entries,
                                 guint                     n_entries)
 {
-    guint i;
-
-    for (i = 0; i < n_entries; i++) {
-        const BalsaToolbarEntry *entry = &entries[i];
-        tm_add_action(model, entry->icon, entry->action);
+    while (n_entries > 0) {
+        tm_add_action(model, entries++);
+        --n_entries;
     }
 }
 
@@ -355,16 +374,16 @@ balsa_toolbar_model_get_legal(BalsaToolbarModel * model)
 
 /* Return the current icons.
  */
-GSList *
+GArray *
 balsa_toolbar_model_get_current(BalsaToolbarModel * model)
 {
-    return model->current ? model->current : model->standard;
+    return model->current->len > 0 ?  model->current : model->standard;
 }
 
 gboolean
 balsa_toolbar_model_is_standard(BalsaToolbarModel * model)
 {
-    return model->current == NULL;
+    return model->current->len == 0;
 }
 
 /* Add an icon to the list of current icons in a BalsaToolbarModel.
@@ -375,11 +394,16 @@ balsa_toolbar_model_insert_icon(BalsaToolbarModel * model, gchar * icon,
 {
     const gchar *real_button = balsa_toolbar_sanitize_id(icon);
 
-    if (real_button)
-        model->current =
-            g_slist_insert(model->current, g_strdup(real_button),
-                           position);
-    else
+    if (real_button) {
+        BalsaToolbarEntry entry;
+
+        entry.action = g_strdup(g_hash_table_lookup(model->legal, real_button));
+        entry.icon   = g_strdup(real_button);
+        if (position >= 0)
+            g_array_insert_val(model->current, position, entry);
+        else
+            g_array_append_val(model->current, entry);
+    } else
         g_warning(_("Unknown toolbar icon \"%s\""), icon);
 }
 
@@ -388,9 +412,16 @@ balsa_toolbar_model_insert_icon(BalsaToolbarModel * model, gchar * icon,
 void
 balsa_toolbar_model_clear(BalsaToolbarModel * model)
 {
-    g_slist_foreach(model->current, (GFunc) g_free, NULL);
-    g_slist_free(model->current);
-    model->current = NULL;
+    guint j;
+
+    for (j = 0; j < model->current->len; j++) {
+        BalsaToolbarEntry *entry;
+
+        entry = &g_array_index(model->current, BalsaToolbarEntry, j);
+        g_free(entry->action);
+        g_free(entry->icon);
+    }
+    g_array_set_size(model->current, 0);
 }
 
 /* Create a new instance of a toolbar
@@ -399,13 +430,17 @@ balsa_toolbar_model_clear(BalsaToolbarModel * model)
 static gboolean
 tm_has_second_line(BalsaToolbarModel * model)
 {
-    GSList *list;
+    GArray *current;
+    guint j;
 
     /* Find out whether any button has 2 lines of text. */
-    for (list = balsa_toolbar_model_get_current(model); list;
-         list = list->next) {
-        const gchar *icon = list->data;
-        gint button = get_toolbar_button_index(icon);
+    current = balsa_toolbar_model_get_current(model);
+    for (j = 0; j < current->len; j++) {
+        const gchar *icon;
+        gint button;
+
+        icon = g_array_index(current, BalsaToolbarEntry, j).icon;
+        button = get_toolbar_button_index(icon);
 
         if (button >= 0 && strchr(balsa_toolbar_button_text(button), '\n'))
             return TRUE;
@@ -500,19 +535,78 @@ tm_set_style(GtkWidget * toolbar, BalsaToolbarModel * model)
                           model->style : tm_default_style());
 }
 
+/* Populate a model
+ */
+#define BALSA_TOOLBAR_ACTION_MAP "balsa-toolbar-action-map"
+static void
+tm_populate(GtkWidget * toolbar, BalsaToolbarModel * model)
+{
+    gboolean style_is_both;
+    gboolean make_two_line;
+    GArray *current;
+    guint j;
+    GActionMap *action_map =
+        g_object_get_data(G_OBJECT(toolbar), BALSA_TOOLBAR_ACTION_MAP);
+
+    style_is_both = (model->style == GTK_TOOLBAR_BOTH
+                     || (model->style == (GtkToolbarStyle) - 1
+                         && tm_default_style() == GTK_TOOLBAR_BOTH));
+    make_two_line = style_is_both && tm_has_second_line(model);
+
+    current = balsa_toolbar_model_get_current(model);
+    for (j = 0; j < current->len; j++) {
+        BalsaToolbarEntry *entry;
+        GtkToolItem *item;
+
+        entry = &g_array_index(current, BalsaToolbarEntry, j);
+
+        if (!*entry->action) {
+            item = gtk_separator_tool_item_new();
+        } else {
+            GtkWidget *icon;
+            GAction *action;
+            const GVariantType *type;
+            gchar *prefixed_action;
+
+            icon = gtk_image_new_from_icon_name
+                (balsa_icon_id(entry->icon), GTK_ICON_SIZE_SMALL_TOOLBAR);
+            action = g_action_map_lookup_action(action_map, entry->action);
+            if (action &&
+                (type = g_action_get_state_type(action)) &&
+                g_variant_type_equal(type, G_VARIANT_TYPE_BOOLEAN)) {
+                item = gtk_toggle_tool_button_new();
+                g_object_set(G_OBJECT(item), "icon-widget", icon,
+                             "label", entry->action, NULL);
+            } else {
+                item = gtk_tool_button_new(icon, entry->action);
+            }
+            tm_set_tool_item_label(GTK_TOOL_ITEM(item), entry->icon,
+                                   make_two_line);
+
+            prefixed_action =
+                g_strconcat(action ? "win." : "app.", entry->action, NULL);
+            gtk_actionable_set_action_name(GTK_ACTIONABLE(item),
+                                           prefixed_action);
+            g_free(prefixed_action);
+        }
+        gtk_toolbar_insert((GtkToolbar *) toolbar, item, -1);
+    }
+    gtk_widget_show_all(toolbar);
+}
+
 /* Update a real toolbar when the model has changed.
  */
 static void
 tm_changed_cb(BalsaToolbarModel * model, GtkWidget * toolbar)
 {
+    balsa_toolbar_remove_all(toolbar);
+    tm_populate(toolbar, model);
     tm_set_style(toolbar, model);
-
     tm_save_model(model);
 }
 
 typedef struct {
     BalsaToolbarModel *model;
-    GObject           *object;
     GtkWidget         *menu;
 } toolbar_info;
 
@@ -520,7 +614,6 @@ static void
 tm_toolbar_weak_notify(toolbar_info * info, GtkWidget * toolbar)
 {
     g_signal_handlers_disconnect_by_data(info->model, toolbar);
-    g_object_unref(info->object);
     g_free(info);
 }
 
@@ -744,67 +837,20 @@ tm_realize_cb(GtkWidget * toolbar, BalsaToolbarModel * model)
 }
 
 GtkWidget *balsa_toolbar_new(BalsaToolbarModel * model,
-                   /* FIXME: GActionMap        * action_map */
-                             GObject * object)
+                             GActionMap        * action_map)
 {
     toolbar_info *info;
-    GActionMap *action_map = G_ACTION_MAP(object);
-    gboolean style_is_both;
-    gboolean make_two_line;
     GtkWidget *toolbar;
-    GSList *current = balsa_toolbar_model_get_current(model);
-    GSList *l;
 
     info = g_new(toolbar_info, 1);
     info->model = model;
-    info->object = g_object_ref(object);
     info->menu = NULL;
 
-    style_is_both = (model->style == GTK_TOOLBAR_BOTH
-                     || (model->style == (GtkToolbarStyle) - 1
-                         && tm_default_style() == GTK_TOOLBAR_BOTH));
-    make_two_line = style_is_both && tm_has_second_line(model);
-
     toolbar = gtk_toolbar_new();
-    for (l = current; l; l = l->next) {
-        gchar *action_name, *icon_name;
-        GtkToolItem *item;
-
-        action_name = l->data;
-        l = l->next;
-        icon_name = l->data;
-
-        if (!*action_name) {
-            item = gtk_separator_tool_item_new();
-        } else {
-            GtkWidget *icon;
-            GAction *action;
-            const GVariantType *type;
-            gchar *prefixed_action;
-
-            icon = gtk_image_new_from_icon_name
-                (balsa_icon_id(icon_name), GTK_ICON_SIZE_SMALL_TOOLBAR);
-            action = g_action_map_lookup_action(action_map, action_name);
-            if (action &&
-                (type = g_action_get_state_type(action)) &&
-                g_variant_type_equal(type, G_VARIANT_TYPE_BOOLEAN)) {
-                item = gtk_toggle_tool_button_new();
-                g_object_set(G_OBJECT(item), "icon-widget", icon,
-                             "label", action_name, NULL);
-            } else {
-                item = gtk_tool_button_new(icon, action_name);
-            }
-            tm_set_tool_item_label(GTK_TOOL_ITEM(item), icon_name,
-                                   make_two_line);
-
-            prefixed_action =
-                g_strconcat(action ? "win." : "app.", action_name, NULL);
-            gtk_actionable_set_action_name(GTK_ACTIONABLE(item),
-                                           prefixed_action);
-            g_free(prefixed_action);
-        }
-        gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item));
-    }
+    g_object_set_data_full(G_OBJECT(toolbar), BALSA_TOOLBAR_ACTION_MAP,
+                           g_object_ref(action_map),
+                           (GDestroyNotify) g_object_unref);
+    tm_populate(toolbar, model);
 
     g_signal_connect(model, "changed", G_CALLBACK(tm_changed_cb), toolbar);
     g_signal_connect(toolbar, "realize", G_CALLBACK(tm_realize_cb), model);
diff --git a/src/toolbar-factory.h b/src/toolbar-factory.h
index e3a2f9f..cb79370 100644
--- a/src/toolbar-factory.h
+++ b/src/toolbar-factory.h
@@ -59,14 +59,10 @@ extern button_data toolbar_buttons[];
 extern const int toolbar_button_count;
 
 typedef struct {
-    const gchar *action;
-    const gchar *icon;
+    gchar *action;
+    gchar *icon;
 } BalsaToolbarEntry;
 
-void balsa_toolbar_model_add_entries(BalsaToolbarModel       * model,
-                                     const BalsaToolbarEntry * entries,
-                                     guint                     n_entries);
-
 typedef enum {
     BALSA_TOOLBAR_TYPE_MAIN_WINDOW,
     BALSA_TOOLBAR_TYPE_COMPOSE_WINDOW,
@@ -74,17 +70,21 @@ typedef enum {
 } BalsaToolbarType;
 
 void update_all_toolbars(void);
-void balsa_toolbar_remove_all(GtkWidget * toolbar);
 
 /* toolbar code for gtk+-2 */
 const gchar *balsa_toolbar_button_text(gint button);
 const gchar *balsa_toolbar_sanitize_id(const gchar * id);
 
 /* BalsaToolbarModel */
-BalsaToolbarModel *balsa_toolbar_model_new(BalsaToolbarType type,
-                                           GSList * standard);
+BalsaToolbarModel *
+    balsa_toolbar_model_new(BalsaToolbarType          type,
+                            const BalsaToolbarEntry * entries,
+                            guint                     n_entries);
+void balsa_toolbar_model_add_entries(BalsaToolbarModel       * model,
+                                     const BalsaToolbarEntry * entries,
+                                     guint                     n_entries);
 GHashTable *balsa_toolbar_model_get_legal(BalsaToolbarModel * model);
-GSList *balsa_toolbar_model_get_current(BalsaToolbarModel * model);
+GArray *balsa_toolbar_model_get_current(BalsaToolbarModel * model);
 gboolean balsa_toolbar_model_is_standard(BalsaToolbarModel * model);
 void balsa_toolbar_model_insert_icon(BalsaToolbarModel * model,
                                      gchar * icon, gint position);
@@ -94,6 +94,7 @@ void balsa_toolbar_model_clear(BalsaToolbarModel * model);
 void balsa_toolbar_model_changed(BalsaToolbarModel * model);
 
 /* BalsaToolbar */
-GtkWidget *balsa_toolbar_new(BalsaToolbarModel * model, GObject * object);
+GtkWidget *balsa_toolbar_new(BalsaToolbarModel * model,
+                             GActionMap        * map);
 
 #endif
diff --git a/src/toolbar-prefs.c b/src/toolbar-prefs.c
index 6c0229a..e7bbf4f 100644
--- a/src/toolbar-prefs.c
+++ b/src/toolbar-prefs.c
@@ -69,14 +69,11 @@ struct ToolbarPage_ {
 /* Callbacks. */
 static void tp_dialog_response_cb(GtkDialog * dialog, gint response,
                                   gpointer data);
-#if 0
 static void add_button_cb(GtkWidget *, ToolbarPage * page);
 static void remove_button_cb(GtkWidget *, ToolbarPage * page);
 static void back_button_cb(GtkWidget *, ToolbarPage * page);
 static void forward_button_cb(GtkWidget *, ToolbarPage * page);
-#endif
 static void wrap_toggled_cb(GtkWidget * widget, GtkNotebook * notebook);
-#if 0
 static void available_selection_changed_cb(GtkTreeSelection * selection,
                                            ToolbarPage * page);
 static void current_selection_changed_cb(GtkTreeSelection * selection,
@@ -92,7 +89,7 @@ static void current_row_activated_cb(GtkTreeView * treeview,
 
 /* Helpers. */
 static GtkWidget *create_toolbar_page(BalsaToolbarModel * model,
-                                      GtkUIManager * ui_manager);
+                                      GActionMap        * map);
 static GtkWidget *tp_list_new(void);
 static gboolean tp_list_iter_is_first(GtkWidget * list, GtkTreeIter * iter);
 static gboolean tp_list_iter_is_last(GtkWidget * list, GtkTreeIter * iter);
@@ -105,7 +102,6 @@ static void tp_page_remove_selected(ToolbarPage * page);
 static void tp_store_set(GtkListStore * store, GtkTreeIter * iter,
                          gint item);
 static void replace_nl_with_space(char* str);
-#endif
 
 /* Public methods. */
 
@@ -121,10 +117,8 @@ customize_dialog_cb(GtkWidget * widget, gpointer data)
     GtkWidget *wrap_button;
     GtkWidget *active_window = data;
     BalsaToolbarType   type;
-#if 0
     BalsaToolbarModel *model;
-    GtkUIManager * ui_manager;
-#endif
+    GSimpleActionGroup *group;
     GtkWidget *content_area;
 
     /* There can only be one */
@@ -159,36 +153,27 @@ customize_dialog_cb(GtkWidget * widget, gpointer data)
 
     /* The order of pages must be consistent with the BalsaToolbarType
      * enum. */
-#if 0
     model = balsa_window_get_toolbar_model();
-    ui_manager = balsa_window_ui_manager_new(NULL);
-    child = create_toolbar_page(model, ui_manager);
-    g_object_unref(ui_manager);
-#else
-    child = gtk_label_new("Sorry, this toolbar cannot be edited yet.");
-#endif
+    group = g_simple_action_group_new();
+    balsa_window_add_action_entries(G_ACTION_MAP(group));
+    child = create_toolbar_page(model, G_ACTION_MAP(group));
+    g_object_unref(group);
     gtk_notebook_append_page(GTK_NOTEBOOK(notebook), child,
                              gtk_label_new(_("Main window")));
 
-#if 0
     model = sendmsg_window_get_toolbar_model();
-    ui_manager = sendmsg_window_ui_manager_new(NULL);
-    child = create_toolbar_page(model, ui_manager);
-    g_object_unref(ui_manager);
-#else
-    child = gtk_label_new("Sorry, this toolbar cannot be edited yet.");
-#endif
+    group = g_simple_action_group_new();
+    sendmsg_window_add_action_entries(G_ACTION_MAP(group));
+    child = create_toolbar_page(model, G_ACTION_MAP(group));
+    g_object_unref(group);
     gtk_notebook_append_page(GTK_NOTEBOOK(notebook), child,
                              gtk_label_new(_("Compose window")));
 
-#if 0
     model = message_window_get_toolbar_model();
-    ui_manager = message_window_ui_manager_new(NULL);
-    child = create_toolbar_page(model, ui_manager);
-    g_object_unref(ui_manager);
-#else
-    child = gtk_label_new("Sorry, this toolbar cannot be edited yet.");
-#endif
+    group = g_simple_action_group_new();
+    message_window_add_action_entries(G_ACTION_MAP(group));
+    child = create_toolbar_page(model, G_ACTION_MAP(group));
+    g_object_unref(group);
     gtk_notebook_append_page(GTK_NOTEBOOK(notebook), child,
                              gtk_label_new(_("Message window")));
 
@@ -253,11 +238,11 @@ wrap_toggled_cb(GtkWidget * widget, GtkNotebook * notebook)
 
     for (i = 0; (child = gtk_notebook_get_nth_page(notebook, i)); i++) {
         page = g_object_get_data(G_OBJECT(child), BALSA_KEY_TOOLBAR_PAGE);
-        balsa_toolbar_model_changed(page->model);
+        if (page)
+            balsa_toolbar_model_changed(page->model);
     }
 }
 
-#if 0
 /* Button callbacks: each makes the appropriate change to the
  * page->current GtkTreeView, then refreshes the page's
  * BalsaToolbarModel and GtkToolbar; add_button_cb and remove_button_cb
@@ -355,7 +340,6 @@ current_selection_changed_cb(GtkTreeSelection * selection, ToolbarPage * page)
     gtk_widget_set_sensitive(page->forward_button, forward);
 }
 
-#endif
 /* Callback for the "response" signal of the dialog. */
 static void
 tp_dialog_response_cb(GtkDialog * dialog, gint response, gpointer data)
@@ -384,13 +368,12 @@ tp_dialog_response_cb(GtkDialog * dialog, gint response, gpointer data)
     }
 }
 
-#if 0
 /* Helpers. */
 
 /* Create a page for the main notebook.
  */
 static GtkWidget*
-create_toolbar_page(BalsaToolbarModel * model, GtkUIManager * ui_manager)
+create_toolbar_page(BalsaToolbarModel * model, GActionMap * map)
 {
     GtkWidget *outer_box;
     GtkWidget *toolbar_frame, *toolbar_scroll;
@@ -419,15 +402,8 @@ create_toolbar_page(BalsaToolbarModel * model, GtkUIManager * ui_manager)
     gtk_container_add(GTK_CONTAINER(toolbar_frame), toolbar_ctlbox);
     gtk_container_set_border_width(GTK_CONTAINER(toolbar_ctlbox), 5);
 
-    /* The ui-manager has actions but no ui, so we add an empty toolbar. */
-    gtk_ui_manager_add_ui_from_string(ui_manager,
-                                      "<ui>"
-                                      "  <toolbar name='Toolbar'/>"
-                                      "</ui>",
-                                      -1, NULL);
-
     /* The preview is an actual, fully functional toolbar */
-    page->toolbar = balsa_toolbar_new(model, G_OBJECT(ui_manager));
+    page->toolbar = balsa_toolbar_new(model, map);
     gtk_widget_set_sensitive(page->toolbar, FALSE);
 
     /* embedded in a scrolled_window */
@@ -573,6 +549,18 @@ create_toolbar_page(BalsaToolbarModel * model, GtkUIManager * ui_manager)
 
 /* Refresh the page's available GtkTreeView.
  */
+static gboolean
+tp_find_icon(GArray * array, const gchar * icon)
+{
+    guint j;
+
+    for (j = 0; j < array->len; j++) {
+        if (strcmp(icon, g_array_index(array, BalsaToolbarEntry, j).icon) == 0)
+            return TRUE;
+    }
+    return FALSE;
+}
+
 static void
 tp_page_refresh_available(ToolbarPage * page)
 {
@@ -582,7 +570,7 @@ tp_page_refresh_available(ToolbarPage * page)
     GtkTreeIter iter;
     GtkTreePath *path;
     GHashTable *legal = balsa_toolbar_model_get_legal(page->model);
-    GSList *current = balsa_toolbar_model_get_current(page->model);
+    GArray *current = balsa_toolbar_model_get_current(page->model);
     int item;
 
     /* save currently selected path, or point path to the first row */
@@ -598,9 +586,7 @@ tp_page_refresh_available(ToolbarPage * page)
         if (item > 0
             && (!g_hash_table_lookup(legal,
                                      toolbar_buttons[item].pixmap_id)
-                || g_slist_find_custom(current,
-                                       toolbar_buttons[item].pixmap_id,
-                                       (GCompareFunc) strcmp)))
+                || tp_find_icon(current, toolbar_buttons[item].pixmap_id)))
             continue;
 
         gtk_list_store_append(GTK_LIST_STORE(model), &iter);
@@ -627,7 +613,8 @@ tp_page_refresh_current(ToolbarPage * page)
     GtkTreeIter iter;
     GtkTreePath *path;
     int item;
-    GSList *list;
+    GArray *current;
+    guint j;
 
     /* save currently selected path, or point path to the first row */
     if (gtk_tree_selection_get_selected(selection, &model, &iter))
@@ -638,9 +625,13 @@ tp_page_refresh_current(ToolbarPage * page)
     }
     gtk_list_store_clear(GTK_LIST_STORE(model));
 
-    for (list = balsa_toolbar_model_get_current(page->model); list;
-         list = g_slist_next(list)) {
-        item = get_toolbar_button_index(list->data);
+    current = balsa_toolbar_model_get_current(page->model);
+    for (j = 0; j < current->len; j++) {
+        BalsaToolbarEntry *entry;
+
+        entry = &g_array_index(current, BalsaToolbarEntry, j);
+        item = get_toolbar_button_index(entry->icon);
+
         if (item < 0)
             continue;
 
@@ -798,10 +789,10 @@ tp_store_set(GtkListStore * store, GtkTreeIter * iter, gint item)
     text = g_strdup(balsa_toolbar_button_text(item));
     replace_nl_with_space(text);
     pixbuf =
-        (item > 0 ? gtk_widget_render_icon_pixbuf(customize_widget,
-                                                  toolbar_buttons[item].
-                                                  pixmap_id,
-                                                  GTK_ICON_SIZE_LARGE_TOOLBAR)
+        (item > 0
+         ? gtk_icon_theme_load_icon(gtk_icon_theme_get_default(),
+                                    toolbar_buttons[item].pixmap_id,
+                                    GTK_ICON_SIZE_LARGE_TOOLBAR, 0, NULL)
          : NULL);
     gtk_list_store_set(store, iter,
                        TP_TEXT_COLUMN, text,
@@ -894,4 +885,3 @@ replace_nl_with_space(char* str)
        str++;
     }
 }
-#endif



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]