diff options
-rw-r--r-- | ChangeLog | 15 | ||||
-rw-r--r-- | demos/gtk-demo/demo.ui | 1 | ||||
-rwxr-xr-x | gtk/gtk-builder-convert | 19 | ||||
-rw-r--r-- | gtk/gtkactiongroup.c | 126 | ||||
-rw-r--r-- | gtk/gtkuimanager.c | 33 | ||||
-rw-r--r-- | tests/buildertest.c | 1 |
6 files changed, 191 insertions, 4 deletions
@@ -1,3 +1,18 @@ +2007-07-09 Johan Dahlin,,, <jdahlin@lozenge> + + * demos/gtk-demo/demo.ui: + * gtk/gtk-builder-convert: + * gtk/gtkactiongroup.c: (gtk_action_group_buildable_init), + (gtk_action_group_buildable_add_child), + (accelerator_start_element), + (gtk_action_group_buildable_custom_tag_start), + (gtk_action_group_buildable_custom_tag_end): + * gtk/gtkuimanager.c: (child_hierarchy_changed_cb), + (gtk_ui_manager_buildable_construct_child): + * tests/buildertest.c: (test_uimanager_simple): + + Add actiongroup/action accelerator support for builder. #454654 + 2007-07-08 Matthias Clasen <mclasen@redhat.com> * gtk/gtkbuilderparser.c (pgettext): Support old-style diff --git a/demos/gtk-demo/demo.ui b/demos/gtk-demo/demo.ui index 26d668997e..1c84db2b58 100644 --- a/demos/gtk-demo/demo.ui +++ b/demos/gtk-demo/demo.ui @@ -104,6 +104,7 @@ <property name="stock_id">gtk-about</property> <signal handler="about_activate" name="activate"/> </object> + <accelerator key="F1"/> </child> </object> </child> diff --git a/gtk/gtk-builder-convert b/gtk/gtk-builder-convert index d77f8c3d16..59218d555f 100755 --- a/gtk/gtk-builder-convert +++ b/gtk/gtk-builder-convert @@ -92,6 +92,16 @@ def get_signal_nodes(node): signals.append(child) return signals +def get_accelerator_nodes(node): + assert node.tagName == 'object' + accelerators = [] + for child in node.childNodes: + if child.nodeType == Node.TEXT_NODE: + continue + if child.tagName == 'accelerator': + accelerators.append(child) + return accelerators + def get_object_node(child_node): assert child_node.tagName == 'child' nodes = [] @@ -418,6 +428,15 @@ class GtkBuilderConverter(object): group.appendChild(child) child.appendChild(action) + for accelerator in get_accelerator_nodes(node): + signal = accelerator.getAttribute('signal') + if signal_name != 'activate': + print 'Unhandled accelerator signal for %s::%s' % ( + node.getAttribute('class'), signal_name) + continue + accelerator.removeAttribute('signal') + child.appendChild(accelerator) + def _convert_sizegroup(self, node, prop): # This is Gazpacho only node.removeChild(prop) diff --git a/gtk/gtkactiongroup.c b/gtk/gtkactiongroup.c index 34ca057bb3..b9d6ee0837 100644 --- a/gtk/gtkactiongroup.c +++ b/gtk/gtkactiongroup.c @@ -29,6 +29,7 @@ */ #include <config.h> +#include <string.h> #include "gtkactiongroup.h" #include "gtkbuildable.h" @@ -39,6 +40,7 @@ #include "gtkradioaction.h" #include "gtkaccelmap.h" #include "gtkmarshalers.h" +#include "gtkbuilderprivate.h" #include "gtkprivate.h" #include "gtkintl.h" #include "gtkalias.h" @@ -97,6 +99,17 @@ static void gtk_action_group_buildable_add_child (GtkBuildable *buildable, static void gtk_action_group_buildable_set_name (GtkBuildable *buildable, const gchar *name); static const gchar* gtk_action_group_buildable_get_name (GtkBuildable *buildable); +static gboolean gtk_action_group_buildable_custom_tag_start (GtkBuildable *buildable, + GtkBuilder *builder, + GObject *child, + const gchar *tagname, + GMarkupParser *parser, + gpointer *data); +static void gtk_action_group_buildable_custom_tag_end (GtkBuildable *buildable, + GtkBuilder *builder, + GObject *child, + const gchar *tagname, + gpointer *user_data); GType gtk_action_group_get_type (void) @@ -298,6 +311,8 @@ gtk_action_group_buildable_init (GtkBuildableIface *iface) iface->add_child = gtk_action_group_buildable_add_child; iface->set_name = gtk_action_group_buildable_set_name; iface->get_name = gtk_action_group_buildable_get_name; + iface->custom_tag_start = gtk_action_group_buildable_custom_tag_start; + iface->custom_tag_end = gtk_action_group_buildable_custom_tag_end; } static void @@ -306,8 +321,8 @@ gtk_action_group_buildable_add_child (GtkBuildable *buildable, GObject *child, const gchar *type) { - gtk_action_group_add_action (GTK_ACTION_GROUP (buildable), - GTK_ACTION (child)); + gtk_action_group_add_action_with_accel (GTK_ACTION_GROUP (buildable), + GTK_ACTION (child), NULL); } static void @@ -325,6 +340,113 @@ gtk_action_group_buildable_get_name (GtkBuildable *buildable) return self->private_data->name; } +typedef struct { + GObject *child; + guint key; + guint modifiers; +} AcceleratorParserData; + +static void +accelerator_start_element (GMarkupParseContext *context, + const gchar *element_name, + const gchar **names, + const gchar **values, + gpointer user_data, + GError **error) +{ + gint i; + guint key = 0; + gint modifiers = 0; + AcceleratorParserData *parser_data = (AcceleratorParserData*)user_data; + + if (strcmp (element_name, "accelerator") != 0) + g_warning ("Unknown <accelerator> tag: %s", element_name); + + for (i = 0; names[i]; i++) + { + if (strcmp (names[i], "key") == 0) + key = gdk_keyval_from_name (values[i]); + else if (strcmp (names[i], "modifiers") == 0) + { + if (!_gtk_builder_flags_from_string (GDK_TYPE_MODIFIER_TYPE, + values[i], + &modifiers, + error)) + return; + } + } + + if (key == 0) + { + g_warning ("<accelerator> requires a key attribute"); + return; + } + parser_data->key = key; + parser_data->modifiers = (guint)modifiers; +} + +static const GMarkupParser accelerator_parser = + { + accelerator_start_element + }; + +static gboolean +gtk_action_group_buildable_custom_tag_start (GtkBuildable *buildable, + GtkBuilder *builder, + GObject *child, + const gchar *tagname, + GMarkupParser *parser, + gpointer *user_data) +{ + AcceleratorParserData *parser_data; + + if (child && strcmp (tagname, "accelerator") == 0) + { + parser_data = g_slice_new0 (AcceleratorParserData); + parser_data->child = child; + *user_data = parser_data; + *parser = accelerator_parser; + + return TRUE; + } + return FALSE; +} + +static void +gtk_action_group_buildable_custom_tag_end (GtkBuildable *buildable, + GtkBuilder *builder, + GObject *child, + const gchar *tagname, + gpointer *user_data) +{ + AcceleratorParserData *data; + + if (strcmp (tagname, "accelerator") == 0) + { + GtkActionGroup *action_group; + GtkAction *action; + gchar *accel_path; + + data = (AcceleratorParserData*)user_data; + action_group = GTK_ACTION_GROUP (buildable); + action = GTK_ACTION (child); + + accel_path = g_strconcat ("<Actions>/", + action_group->private_data->name, "/", + gtk_action_get_name (action), NULL); + + if (gtk_accel_map_lookup_entry (accel_path, NULL)) + gtk_accel_map_change_entry (accel_path, data->key, data->modifiers, TRUE); + else + gtk_accel_map_add_entry (accel_path, data->key, data->modifiers); + + gtk_action_set_accel_path (action, accel_path); + + g_free (accel_path); + g_slice_free (AcceleratorParserData, data); + } +} + /** * gtk_action_group_new: * @name: the name of the action group. diff --git a/gtk/gtkuimanager.c b/gtk/gtkuimanager.c index 3e0ac69be6..687567d3d5 100644 --- a/gtk/gtkuimanager.c +++ b/gtk/gtkuimanager.c @@ -453,6 +453,29 @@ gtk_ui_manager_buildable_add_child (GtkBuildable *buildable, pos); } +static void +child_hierarchy_changed_cb (GtkWidget *widget, + GtkWidget *unused, + GtkUIManager *uimgr) +{ + GtkWidget *toplevel; + GtkAccelGroup *group; + GSList *groups; + + toplevel = gtk_widget_get_toplevel (widget); + if (!toplevel || !GTK_IS_WINDOW (toplevel)) + return; + + group = gtk_ui_manager_get_accel_group (uimgr); + groups = gtk_accel_groups_from_object (toplevel); + if (g_slist_find (groups, group) == NULL) + gtk_window_add_accel_group (GTK_WINDOW (toplevel), group); + + g_signal_handlers_disconnect_by_func (widget, + child_hierarchy_changed_cb, + uimgr); +} + static GObject * gtk_ui_manager_buildable_construct_child (GtkBuildable *buildable, GtkBuilder *builder, @@ -464,10 +487,16 @@ gtk_ui_manager_buildable_construct_child (GtkBuildable *buildable, name = g_strdup_printf ("ui/%s", id); widget = gtk_ui_manager_get_widget (GTK_UI_MANAGER (buildable), name); if (!widget) - g_error ("Unknown ui manager child: %s\n", name); - + { + g_error ("Unknown ui manager child: %s\n", name); + g_free (name); + return NULL; + } g_free (name); + g_signal_connect (widget, "hierarchy-changed", + G_CALLBACK (child_hierarchy_changed_cb), + GTK_UI_MANAGER (buildable)); return G_OBJECT (widget); } diff --git a/tests/buildertest.c b/tests/buildertest.c index a6577d73fc..f495f88338 100644 --- a/tests/buildertest.c +++ b/tests/buildertest.c @@ -259,6 +259,7 @@ gboolean test_uimanager_simple (void) " <object class=\"GtkAction\" id=\"file\">" " <property name=\"label\">_File</property>" " </object>" + " <accelerator key=\"n\" modifiers=\"GDK_CONTROL_MASK\"/>" " </child>" " </object>" " </child>" |