fix bug 605957 'shortcuts in popup-menu'
authorPaul Mangan <paul@claws-mail.org>
Sun, 5 Jan 2003 12:28:18 +0000 (12:28 +0000)
committerPaul Mangan <paul@claws-mail.org>
Sun, 5 Jan 2003 12:28:18 +0000 (12:28 +0000)
ChangeLog.claws
configure.in
src/gtk/menu.c
src/gtk/menu.h
src/mainwindow.c
src/summaryview.c

index d91192e..210df8e 100644 (file)
@@ -1,3 +1,14 @@
+2003-01-05 [paul]      0.8.8claws45
+
+       * src/mainwindow.c
+         src/sumamryview.c
+         src/gtk/menu.[ch]
+               fix bug 605957 'shortcuts in popup-menu'
+               make user-defined shortcuts work
+               show shortcuts that are already defined
+               in the main menu
+               Patch submitted by Luke Plant
+
 2003-01-05 [alfons]    0.8.8claws44
 
        * src/mainwindow.c
index 9205697..3876cd9 100644 (file)
@@ -11,7 +11,7 @@ MINOR_VERSION=8
 MICRO_VERSION=8
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=claws44
+EXTRA_VERSION=claws45
 VERSION=$MAJOR_VERSION.$MINOR_VERSION.$MICRO_VERSION$EXTRA_VERSION
 
 dnl set $target
index 1fe647f..2bbf7ca 100644 (file)
 
 static gchar *menu_translate(const gchar *path, gpointer data);
 
+static void menu_item_add_accel( GtkWidget *widget, guint accel_signal_id, GtkAccelGroup *accel_group,
+                                guint accel_key, GdkModifierType accel_mods, GtkAccelFlags accel_flags,
+                                gpointer user_data);
+
+static void menu_item_remove_accel(GtkWidget *widget, GtkAccelGroup *accel_group,
+                                  guint accel_key, GdkModifierType accel_mods,
+                                  gpointer user_data);
+
+static void connect_accel_change_signals(GtkWidget* widget, GtkWidget *wid2) ;
+
+
 GtkWidget *menubar_create(GtkWidget *window, GtkItemFactoryEntry *entries,
                          guint n_entries, const gchar *path, gpointer data)
 {
@@ -195,3 +206,106 @@ gint menu_find_option_menu_index(GtkOptionMenu *optmenu, gpointer data,
        return -1;
 }
 
+/* call backs for accelerator changes on selected menu items */
+static void menu_item_add_accel( GtkWidget *widget, guint accel_signal_id, GtkAccelGroup *accel_group,
+                                guint accel_key, GdkModifierType accel_mods, GtkAccelFlags accel_flags,
+                                gpointer user_data)
+{
+       GtkWidget *connected = GTK_WIDGET(user_data);   
+       if (gtk_signal_n_emissions_by_name(GTK_OBJECT(widget),"add_accelerator") > 1 ) return;
+       gtk_widget_remove_accelerators(connected,"activate",FALSE);
+       /* lock _this_ widget */
+       gtk_accel_group_lock_entry(accel_group,accel_key,accel_mods);
+       /* modify the _other_ widget */
+       gtk_widget_add_accelerator(connected, "activate",
+                                  gtk_item_factory_from_widget(connected)->accel_group,
+                                  accel_key, accel_mods,
+                                  GTK_ACCEL_VISIBLE );
+       gtk_accel_group_unlock_entry(accel_group,accel_key,accel_mods);                            
+}
+
+static void menu_item_remove_accel(GtkWidget *widget, GtkAccelGroup *accel_group,
+                                  guint accel_key, GdkModifierType accel_mods,
+                                  gpointer user_data)
+{      
+       GtkWidget *wid = GTK_WIDGET(user_data);
+
+       if (gtk_signal_n_emissions_by_name(GTK_OBJECT(widget),
+           "remove_accelerator") > 2 )
+               return;
+       gtk_widget_remove_accelerators(wid,"activate",FALSE);
+}
+
+static void connect_accel_change_signals(GtkWidget* widget, GtkWidget *wid2) 
+{
+       gtk_signal_connect_after(GTK_OBJECT(widget), "add_accelerator", 
+                                menu_item_add_accel, wid2);
+       gtk_signal_connect_after(GTK_OBJECT(widget), "remove_accelerator", 
+                                menu_item_remove_accel, wid2);
+}
+
+void menu_connect_identical_items(void)
+{
+       gint n;
+       GtkWidget *item1;
+       GtkWidget *item2;
+
+       static const struct {   
+               const gchar *path1;
+               const gchar *path2;
+       } pairs[] = {
+               {"<Main>/Message/Reply",                        "<SummaryView>/Reply"},
+               {"<Main>/Message/Reply to/all",                 "<SummaryView>/Reply to/all"},
+               {"<Main>/Message/Reply to/sender",              "<SummaryView>/Reply to/sender"},
+               {"<Main>/Message/Reply to/mailing list",        "<SummaryView>/Reply to/mailing list"},
+               {"<Main>/Message/Follow-up and reply to",       "<SummaryView>/Follow-up and reply to"},
+               {"<Main>/Message/Forward",                      "<SummaryView>/Forward"},
+               {"<Main>/Message/Redirect",                     "<SummaryView>/Redirect"},
+               {"<Main>/Message/Re-edit",                      "<SummaryView>/Re-edit"},
+               {"<Main>/Message/Move...",                      "<SummaryView>/Move..."},
+               {"<Main>/Message/Copy...",                      "<SummaryView>/Copy..."},
+               {"<Main>/Message/Delete",                       "<SummaryView>/Delete"},
+               {"<Main>/Message/Cancel a news message",        "<SummaryView>/Cancel a news message"},
+               {"<Main>/Tools/Execute",                        "<SummaryView>/Execute"},
+               {"<Main>/Message/Mark/Mark",                    "<SummaryView>/Mark/Mark"},
+               {"<Main>/Message/Mark/Unmark",                  "<SummaryView>/Mark/Unmark"},
+               {"<Main>/Message/Mark/Mark as unread",          "<SummaryView>/Mark/Mark as unread"},
+               {"<Main>/Message/Mark/Mark as read",            "<SummaryView>/Mark/Mark as read"},
+               {"<Main>/Message/Mark/Mark all read",           "<SummaryView>/Mark/Mark all read"},
+               {"<Main>/Tools/Add sender to address book",     "<SummaryView>/Add sender to address book"},
+               {"<Main>/Tools/Create filter rule/Automatically",       "<SummaryView>/Create filter rule/Automatically"},
+               {"<Main>/Tools/Create filter rule/by From",     "<SummaryView>/Create filter rule/by From"},
+               {"<Main>/Tools/Create filter rule/by To",       "<SummaryView>/Create filter rule/by To"},
+               {"<Main>/Tools/Create filter rule/by Subject",  "<SummaryView>/Create filter rule/by Subject"},
+               {"<Main>/View/Open in new window",              "<SummaryView>/View/Open in new window"},
+               {"<Main>/View/Message source",                  "<SummaryView>/View/Source"},
+               {"<Main>/View/Show all headers",                "<SummaryView>/View/All header"},
+               {"<Main>/File/Save as...",                      "<SummaryView>/Save as..."},
+               {"<Main>/File/Print...",                        "<SummaryView>/Print..."},
+               {"<Main>/Edit/Select all",                      "<SummaryView>/Select all"},
+               {"<Main>/Edit/Select thread",                   "<SummaryView>/Select thread"}           
+       };
+
+       const gint numpairs = sizeof pairs / sizeof pairs[0];
+       for (n = 0; n < numpairs; n++) {
+               /* get widgets from the paths */
+
+               item1 = gtk_item_factory_get_widget
+                               (gtk_item_factory_from_path(pairs[n].path1),pairs[n].path1);            
+               item2 = gtk_item_factory_get_widget
+                               (gtk_item_factory_from_path(pairs[n].path2),pairs[n].path2);            
+
+               if (item1 && item2) {
+                       /* connect widgets both ways around */
+                       connect_accel_change_signals(item2,item1);
+                       connect_accel_change_signals(item1,item2);
+               } else { 
+                       if (!item1) debug_print(" ** Menu item not found: %s\n",pairs[n].path1);
+                       if (!item2) debug_print(" ** Menu item not found: %s\n",pairs[n].path2);
+               }                               
+       }
+}
+
+
+
+       
index 0ec4b38..4e7e2bb 100644 (file)
@@ -75,4 +75,6 @@ gint menu_find_option_menu_index(GtkOptionMenu                *optmenu,
                                 gpointer                data,
                                 GCompareFunc            func);
 
+void menu_connect_identical_items(void);
+
 #endif /* __MENU_H__ */
index 0b3f8b1..ddedc9d 100644 (file)
@@ -973,6 +973,20 @@ MainWindow *main_window_create(SeparateType type)
        /* create actions menu */
        update_mainwin_actions_menu(ifactory, mainwin);
 
+       /* attach accel groups to main window */
+#define        ADD_MENU_ACCEL_GROUP_TO_WINDOW(menu,win)        \
+       gtk_window_add_accel_group                      \
+               (GTK_WINDOW(win),                       \
+                gtk_item_factory_from_widget(menu)->accel_group)                
+       
+       ADD_MENU_ACCEL_GROUP_TO_WINDOW(summaryview->popupmenu,mainwin->window);
+       
+       /* connect the accelerators for equivalent 
+          menu items in different menus             */
+       menu_connect_identical_items();
+
+
+       
        /* show main window */
        gtk_widget_set_uposition(mainwin->window,
                                 prefs_common.mainwin_x,
index 9cb2846..638600e 100644 (file)
@@ -395,30 +395,30 @@ GtkTargetEntry summary_drag_types[1] =
 
 static GtkItemFactoryEntry summary_popup_entries[] =
 {
-       {N_("/_Reply"),                 NULL, summary_reply_cb, COMPOSE_REPLY, NULL},
+       {N_("/_Reply"),                 "<control>R", summary_reply_cb, COMPOSE_REPLY, NULL},
        {N_("/Repl_y to"),              NULL, NULL,             0, "<Branch>"},
-       {N_("/Repl_y to/_all"),         NULL, summary_reply_cb, COMPOSE_REPLY_TO_ALL, NULL},
+       {N_("/Repl_y to/_all"),         "<shift><control>R", summary_reply_cb,  COMPOSE_REPLY_TO_ALL, NULL},
        {N_("/Repl_y to/_sender"),      NULL, summary_reply_cb, COMPOSE_REPLY_TO_SENDER, NULL},
        {N_("/Repl_y to/mailing _list"),
-                                       NULL, summary_reply_cb, COMPOSE_REPLY_TO_LIST, NULL},
+                                       "<control>L", summary_reply_cb, COMPOSE_REPLY_TO_LIST, NULL},
        {N_("/Follow-up and reply to"), NULL, summary_reply_cb, COMPOSE_FOLLOWUP_AND_REPLY_TO, NULL},
        {N_("/---"),                    NULL, NULL,             0, "<Separator>"},
-       {N_("/_Forward"),               NULL, summary_reply_cb, COMPOSE_FORWARD, NULL},
+       {N_("/_Forward"),               "<control><alt>F", summary_reply_cb, COMPOSE_FORWARD, NULL},
        {N_("/Redirect"),               NULL, summary_reply_cb, COMPOSE_REDIRECT, NULL},
        {N_("/---"),                    NULL, NULL,             0, "<Separator>"},
        {N_("/Re-_edit"),               NULL, summary_reedit,   0, NULL},
        {N_("/---"),                    NULL, NULL,             0, "<Separator>"},
-       {N_("/M_ove..."),               NULL, summary_move_to,  0, NULL},
-       {N_("/_Copy..."),               NULL, summary_copy_to,  0, NULL},
-       {N_("/_Delete"),                NULL, summary_delete,   0, NULL},
+       {N_("/M_ove..."),               "<control>O", summary_move_to,  0, NULL},
+       {N_("/_Copy..."),               "<shift><control>O", summary_copy_to,   0, NULL},
+       {N_("/_Delete"),                "<control>D", summary_delete,   0, NULL},
        {N_("/Cancel a news message"),  NULL, summary_cancel,   0, NULL},
-       {N_("/E_xecute"),               NULL, summary_execute_cb,       0, NULL},
+       {N_("/E_xecute"),               "X", summary_execute_cb,        0, NULL},
        {N_("/---"),                    NULL, NULL,             0, "<Separator>"},
        {N_("/_Mark"),                  NULL, NULL,             0, "<Branch>"},
-       {N_("/_Mark/_Mark"),            NULL, summary_mark,     0, NULL},
-       {N_("/_Mark/_Unmark"),          NULL, summary_unmark,   0, NULL},
+       {N_("/_Mark/_Mark"),            "<shift>asterisk", summary_mark,        0, NULL},
+       {N_("/_Mark/_Unmark"),          "U", summary_unmark,    0, NULL},
        {N_("/_Mark/---"),              NULL, NULL,             0, "<Separator>"},
-       {N_("/_Mark/Mark as unr_ead"),  NULL, summary_mark_as_unread, 0, NULL},
+       {N_("/_Mark/Mark as unr_ead"),  "<shift>exclam", summary_mark_as_unread, 0, NULL},
        {N_("/_Mark/Mark as rea_d"),    NULL, summary_mark_as_read, 0, NULL},
        {N_("/_Mark/Mark all read"),    NULL, summary_mark_all_read, 0, NULL},
        {N_("/_Mark/Ignore thread"),    NULL, summary_ignore_thread, 0, NULL},
@@ -440,16 +440,16 @@ static GtkItemFactoryEntry summary_popup_entries[] =
        {N_("/---"),                    NULL, NULL,             0, "<Separator>"},
        {N_("/_View"),                  NULL, NULL,             0, "<Branch>"},
        {N_("/_View/Open in new _window"),
-                                       NULL, summary_open_msg, 0, NULL},
-       {N_("/_View/_Source"),          NULL, summary_view_source, 0, NULL},
-       {N_("/_View/All _header"),      NULL, summary_show_all_header_cb, 0, "<ToggleItem>"},
+                                       "<control><alt>N", summary_open_msg,    0, NULL},
+       {N_("/_View/_Source"),          "<control>U", summary_view_source, 0, NULL},
+       {N_("/_View/All _header"),      "<control>H", summary_show_all_header_cb, 0, "<ToggleItem>"},
        {N_("/---"),                    NULL, NULL,             0, "<Separator>"},
-       {N_("/_Save as..."),            NULL, summary_save_as,  0, NULL},
+       {N_("/_Save as..."),            "<control>S", summary_save_as,  0, NULL},
        {N_("/_Print..."),              NULL, summary_print,    0, NULL},
        {N_("/---"),                    NULL, NULL,             0, "<Separator>"},
-       {N_("/Select _all"),            NULL, summary_select_all, 0, NULL},
+       {N_("/Select _all"),            "<control>A", summary_select_all, 0, NULL},
        {N_("/Select t_hread"),         NULL, summary_select_thread, 0, NULL}
-};
+};  /* see also list in menu_connect_identical_items() in menu.c if this changes */
 
 static const gchar *const col_label[N_SUMMARY_COLS] = {
        N_("M"),        /* S_COL_MARK    */