[balsa/gtk3] Add menu accelerator keys to the source-viewer
- From: Peter Bloomfield <PeterB src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [balsa/gtk3] Add menu accelerator keys to the source-viewer
- Date: Sun, 21 Jul 2013 20:02:16 +0000 (UTC)
commit 92ca6be53896dd4acc34f77330cfa3c796d16058
Author: Peter Bloomfield <PeterBloomfield bellsouth net>
Date: Sun Jul 21 16:00:35 2013 -0400
Add menu accelerator keys to the source-viewer
* libbalsa/application-helpers.c (accel_info_free),
(accel_activate), (extract_accel_from_menu_item),
(extract_accels_from_menu), (libbalsa_window_get_accel_group),
(libbalsa_window_get_menu_bar): new file defining
libbalsa_window_get_menu_bar.
* libbalsa/application-helpers.h: ditto.
* libbalsa/Makefile.am: add them to SOURCES.
* libbalsa/source-viewer.c: use libbalsa_window_get_menu_bar to
construct the menu-bar and add the accelerators to the window.
ChangeLog | 12 +++
libbalsa/Makefile.am | 2 +
libbalsa/application-helpers.c | 188 ++++++++++++++++++++++++++++++++++++++++
libbalsa/application-helpers.h | 40 +++++++++
libbalsa/source-viewer.c | 64 ++++++--------
5 files changed, 267 insertions(+), 39 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index b178d2a..3d62c4a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
2013-07-21 Peter Bloomfield
+ * libbalsa/application-helpers.c (accel_info_free),
+ (accel_activate), (extract_accel_from_menu_item),
+ (extract_accels_from_menu), (libbalsa_window_get_accel_group),
+ (libbalsa_window_get_menu_bar): new file defining
+ libbalsa_window_get_menu_bar.
+ * libbalsa/application-helpers.h: ditto.
+ * libbalsa/Makefile.am: add them to SOURCES.
+ * libbalsa/source-viewer.c: use libbalsa_window_get_menu_bar to
+ construct the menu-bar and add the accelerators to the window.
+
+2013-07-21 Peter Bloomfield
+
More GtkStock deprecation cleanup
* src/balsa-index.c (bndx_popup_menu_create),
diff --git a/libbalsa/Makefile.am b/libbalsa/Makefile.am
index 00bda16..8be3815 100644
--- a/libbalsa/Makefile.am
+++ b/libbalsa/Makefile.am
@@ -66,6 +66,8 @@ libbalsa_a_SOURCES = \
address-view.h \
address.c \
address.h \
+ application-helpers.c \
+ application-helpers.h \
body.c \
body.h \
cell-renderer-button.c \
diff --git a/libbalsa/application-helpers.c b/libbalsa/application-helpers.c
new file mode 100644
index 0000000..1d7d49d
--- /dev/null
+++ b/libbalsa/application-helpers.c
@@ -0,0 +1,188 @@
+/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */
+/* Balsa E-Mail Client
+ * Copyright (C) 1998-2013 Stuart Parmenter and others, see AUTHORS file.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Helpers for GtkApplicationWindow
+ *
+ * Currently only one helper
+ */
+
+#if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H
+# include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include <gtk/gtk.h>
+#include <string.h>
+#include "application-helpers.h"
+
+/*
+ * libbalsa_window_get_menu_bar
+ *
+ * Construct a menu-bar for a GtkApplicationWindow that does not use the
+ * GApplication's menubar
+ *
+ * window the GtkApplicationWindow
+ * entries array of GActionEntry structures
+ * n_entries length of the array
+ * ui_file filename for GtkBuilder input defining a menu named
+ * "menubar"
+ *
+ * returns: the GtkMenuBar
+ */
+
+typedef struct {
+ GAction *action;
+ GVariant *parameter;
+} AccelInfo;
+
+static void
+accel_info_free(AccelInfo * info)
+{
+ if (info->parameter)
+ g_variant_unref(info->parameter);
+ g_free(info);
+}
+
+static gboolean
+accel_activate(GtkAccelGroup * accel_group,
+ GObject * acceleratable,
+ guint keyval,
+ GdkModifierType modifier,
+ gpointer user_data)
+{
+ AccelInfo *info = user_data;
+
+ g_action_activate(info->action, info->parameter);
+
+ return TRUE;
+}
+
+static void
+extract_accel_from_menu_item(GMenuModel * model,
+ gint item,
+ GActionMap * action_map,
+ GtkAccelGroup * accel_group)
+{
+ GMenuAttributeIter *iter;
+ const gchar *key;
+ GVariant *value;
+ const gchar *accel = NULL;
+ const gchar *action = NULL;
+ GVariant *target = NULL;
+
+ iter = g_menu_model_iterate_item_attributes(model, item);
+ while (g_menu_attribute_iter_get_next(iter, &key, &value)) {
+ if (g_str_equal(key, "action")
+ && g_variant_is_of_type(value, G_VARIANT_TYPE_STRING))
+ action = g_variant_get_string(value, NULL);
+ else if (g_str_equal(key, "accel")
+ && g_variant_is_of_type(value, G_VARIANT_TYPE_STRING))
+ accel = g_variant_get_string(value, NULL);
+ else if (g_str_equal(key, "target"))
+ target = g_variant_ref(value);
+ g_variant_unref(value);
+ }
+ g_object_unref(iter);
+
+ if (accel && action) {
+ guint accel_key;
+ GdkModifierType accel_mods;
+ AccelInfo *info;
+ const gchar *basename;
+ GClosure *closure;
+
+ gtk_accelerator_parse(accel, &accel_key, &accel_mods);
+ basename = strchr(action, '.');
+ basename = basename ? basename + 1 : action;
+ info = g_new(AccelInfo, 1);
+ info->action = g_action_map_lookup_action(action_map, basename);
+ info->parameter = target ? g_variant_ref(target) : NULL;
+ closure = g_cclosure_new(G_CALLBACK(accel_activate), info,
+ (GClosureNotify) accel_info_free);
+ gtk_accel_group_connect(accel_group, accel_key, accel_mods, 0,
+ closure);
+ }
+
+ if (target)
+ g_variant_unref(target);
+}
+
+static void
+extract_accels_from_menu(GMenuModel * model,
+ GActionMap * action_map,
+ GtkAccelGroup * accel_group)
+{
+ gint i;
+ GMenuLinkIter *iter;
+ const gchar *key;
+ GMenuModel *m;
+
+ for (i = 0; i < g_menu_model_get_n_items(model); i++) {
+ extract_accel_from_menu_item(model, i, action_map, accel_group);
+
+ iter = g_menu_model_iterate_item_links(model, i);
+ while (g_menu_link_iter_get_next(iter, &key, &m)) {
+ extract_accels_from_menu(m, action_map, accel_group);
+ g_object_unref(m);
+ }
+ g_object_unref(iter);
+ }
+}
+
+static GtkAccelGroup *
+libbalsa_window_get_accel_group(GMenuModel * model,
+ GActionMap * action_map)
+{
+ GtkAccelGroup *accel_group;
+
+ accel_group = gtk_accel_group_new();
+ extract_accels_from_menu(model, action_map, accel_group);
+
+ return accel_group;
+}
+
+GtkWidget *
+libbalsa_window_get_menu_bar(GtkApplicationWindow * window,
+ const GActionEntry * entries,
+ gint n_entries,
+ const gchar * ui_file,
+ GError ** error)
+{
+ GActionMap *map = G_ACTION_MAP(window);
+ GtkBuilder *builder;
+ GtkWidget *menu_bar = NULL;
+
+ g_action_map_add_action_entries(map, entries, n_entries, window);
+
+ builder = gtk_builder_new();
+ if (gtk_builder_add_from_file(builder, ui_file, error)) {
+ GMenuModel *menu_model;
+ GtkAccelGroup *accel_group;
+
+ menu_model =
+ G_MENU_MODEL(gtk_builder_get_object(builder, "menubar"));
+
+ menu_bar = gtk_menu_bar_new_from_model(menu_model);
+
+ accel_group = libbalsa_window_get_accel_group(menu_model, map);
+ gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);
+ }
+ g_object_unref(builder);
+
+ return menu_bar;
+}
diff --git a/libbalsa/application-helpers.h b/libbalsa/application-helpers.h
new file mode 100644
index 0000000..91a41b6
--- /dev/null
+++ b/libbalsa/application-helpers.h
@@ -0,0 +1,40 @@
+/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */
+/* Balsa E-Mail Client
+ * Copyright (C) 1998-2013 Stuart Parmenter and others, see AUTHORS file.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Helpers for GtkApplicationWindow
+ *
+ * Currently only one helper
+ */
+
+#ifndef __LIBBALSA_APPLICATION_HELPERS_H__
+#define __LIBBALSA_APPLICATION_HELPERS_H__
+
+#ifndef BALSA_VERSION
+#error "Include config.h before this file."
+#endif
+
+#include <gtk/gtk.h>
+
+GtkWidget *libbalsa_window_get_menu_bar(GtkApplicationWindow * window,
+ const GActionEntry * entries,
+ gint n_entries,
+ const gchar * ui_file,
+ GError ** error);
+
+#endif /* __LIBBALSA_APPLICATION_HELPERS_H__ */
diff --git a/libbalsa/source-viewer.c b/libbalsa/source-viewer.c
index 99dc72c..9d00f70 100644
--- a/libbalsa/source-viewer.c
+++ b/libbalsa/source-viewer.c
@@ -28,6 +28,7 @@
#include <stdio.h>
+#include "application-helpers.h"
#include "misc.h"
#include "libbalsa.h"
#include "libbalsa_private.h"
@@ -183,41 +184,6 @@ lsv_window_destroy_notify(LibBalsaSourceViewerInfo * lsvi)
pops up a window containing the source of the message msg.
*/
-static GtkWidget*
-lsv_app_set_menus(GtkWindow * app, GAction ** action)
-{
- GtkWidget *window;
- GtkWidget *menu_bar = NULL;
- GtkBuilder *builder;
- GError *err = NULL;
-
- window = GTK_WIDGET(app);
-
- g_action_map_add_action_entries(G_ACTION_MAP(app), win_entries,
- G_N_ELEMENTS(win_entries), window);
- *action = g_action_map_lookup_action(G_ACTION_MAP(app), "lsv-escape");
-
- builder = gtk_builder_new();
- if (gtk_builder_add_from_file(builder,
- BALSA_DATA_PREFIX "/ui/source-viewer.ui",
- &err)) {
- GMenuModel *menu_model;
-
- menu_model =
- G_MENU_MODEL(gtk_builder_get_object(builder, "menubar"));
- menu_bar = gtk_menu_bar_new_from_model(menu_model);
- } else {
- g_print("%s error: %s\n", __func__, err->message);
- libbalsa_information(LIBBALSA_INFORMATION_WARNING,
- _("Error adding from %s: %s\n"),
- "source-viewer.ui", err->message);
- g_error_free(err);
- }
- g_object_unref(builder);
-
- return menu_bar;
-}
-
static void
lsv_size_allocate_cb(GtkWindow * window, GtkAllocation * alloc,
LibBalsaSourceViewerInfo * lsvi)
@@ -244,9 +210,11 @@ libbalsa_show_message_source(GtkApplication * application,
PangoFontDescription *desc;
GtkWidget *vbox, *interior;
GtkWidget *window;
- GAction *escape_action = NULL;
- LibBalsaSourceViewerInfo *lsvi;
+ gchar *ui_file;
GtkWidget *menu_bar;
+ GError *err = NULL;
+ LibBalsaSourceViewerInfo *lsvi;
+ GAction *escape_action;
g_return_if_fail(msg);
g_return_if_fail(MAILBOX_OPEN(msg->mailbox));
@@ -272,9 +240,24 @@ libbalsa_show_message_source(GtkApplication * application,
gtk_window_set_title(GTK_WINDOW(window), _("Message Source"));
gtk_window_set_wmclass(GTK_WINDOW(window), "message-source", "Balsa");
gtk_window_set_default_size(GTK_WINDOW(window), *width, *height);
- vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 1);
- menu_bar = lsv_app_set_menus(GTK_WINDOW(window), &escape_action);
+ ui_file = g_build_filename(BALSA_DATA_PREFIX, "ui", "source-viewer.ui",
+ NULL);
+ menu_bar = libbalsa_window_get_menu_bar(GTK_APPLICATION_WINDOW(window),
+ win_entries,
+ G_N_ELEMENTS(win_entries),
+ ui_file, &err);
+ if (!menu_bar) {
+ libbalsa_information(LIBBALSA_INFORMATION_WARNING,
+ _("Error adding from %s: %s\n"), ui_file,
+ err->message);
+ g_free(ui_file);
+ g_error_free(err);
+ return;
+ }
+ g_free(ui_file);
+
+ vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 1);
#if HAVE_MACOSX_DESKTOP
libbalsa_macosx_menu(window, GTK_MENU_SHELL(menu_bar));
#else
@@ -298,6 +281,9 @@ libbalsa_show_message_source(GtkApplication * application,
G_CALLBACK(lsv_size_allocate_cb), lsvi);
gtk_widget_show_all(window);
+
+ escape_action =
+ g_action_map_lookup_action(G_ACTION_MAP(window), "lsv-escape");
lsv_escape_change_state(G_SIMPLE_ACTION(escape_action),
g_variant_new_boolean(*escape_specials),
window);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]