After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 671786 - Glade XML files cannot set an ImageMenuItem accelerator key from an Action
Glade XML files cannot set an ImageMenuItem accelerator key from an Action
Status: RESOLVED FIXED
Product: gtk+
Classification: Platform
Component: Class: GtkBuilder
unspecified
Other Linux
: Normal normal
: ---
Assigned To: GtkBuilder maintainers
GtkBuilder maintainers
: 681894 (view as bug list)
Depends on:
Blocks: 681578
 
 
Reported: 2012-03-10 18:08 UTC by DTJF
Modified: 2012-09-14 21:11 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Test case patch for gtk (3.35 KB, patch)
2012-04-20 21:49 UTC, Juan Pablo Ugarte
needs-work Details | Review
Test program using an accelerator with builder (920 bytes, patch)
2012-04-20 21:50 UTC, Juan Pablo Ugarte
none Details | Review
builder file for test program (2.06 KB, application/x-designer)
2012-04-20 21:50 UTC, Juan Pablo Ugarte
  Details
Proposed patch (5.32 KB, patch)
2012-05-08 23:52 UTC, Juan Pablo Ugarte
needs-work Details | Review
Proposed patch 2nd try (7.60 KB, patch)
2012-08-16 18:10 UTC, Juan Pablo Ugarte
none Details | Review
Proposed patch 3rd try (5.69 KB, patch)
2012-09-12 18:03 UTC, Juan Pablo Ugarte
needs-work Details | Review
improved 3rd try (5.85 KB, patch)
2012-09-13 20:06 UTC, Juan Pablo Ugarte
accepted-commit_now Details | Review

Description DTJF 2012-03-10 18:08:48 UTC
I couldn't find a way to set the accelerator key from a GtkAction to an GtkImageMenuItem with Glade. Glade XML-files don't use the <ui> interface. Instead, Glade creates an GtkActionGroup with the GtkActions and accelerators. And it connects the GtkImageMenuItems to the GtkActions. But when parsing the GUI-XML-file the Actions have no GtkAccelGroup and GtkBuilder states:

  (...): Gtk-CRITICAL **: IA__gtk_accel_label_set_accel_closure: assertion `gtk_accel_group_from_accel_closure (accel_closure) != NULL' failed

(One message for each GtkImageMenuItem with an GtkAction with accelerator key. Tested with GTK 2.24.8 and GTK 3.2.0 on Ubuntu 11.10 and XP SP2, found a similar report with example here:
  http://ubuntuforums.org/showthread.php?t=1750974)


Solution:

From my point of view the GtkAction class in GtkBuilder needs a new property to set the accel-group in GtkBuilder (similar to the 'gtk_action_set_accel_group' function):

  <property name="accel-group">accelgroupname</property>

Maybe it's good to implement a similar property to GtkActionGroup to set all GtkActions in the group to one accel-group?!

BR
Comment 1 Juan Pablo Ugarte 2012-04-20 21:28:05 UTC
I have the same problem, and I am trying to debug it now, the accelerator seems to work just fine, it seems its the menu item that is not showing the accel label properly
Comment 2 Juan Pablo Ugarte 2012-04-20 21:49:12 UTC
Created attachment 212462 [details] [review]
Test case patch for gtk
Comment 3 Juan Pablo Ugarte 2012-04-20 21:50:03 UTC
Created attachment 212463 [details] [review]
Test program using an accelerator with builder
Comment 4 Juan Pablo Ugarte 2012-04-20 21:50:34 UTC
Created attachment 212464 [details]
builder file for test program
Comment 5 Juan Pablo Ugarte 2012-05-08 23:52:47 UTC
Created attachment 213710 [details] [review]
Proposed patch

This patch adds accel-group property to GtkActionGroup which is needed to call
gtk_accel_group_connect_by_path() in gtk_action_group_buildable_custom_tag_end()
for the accel label to work in menu items.
This only works if we actually set the accel group in the action group, but I guess action group could create one itself, which would have to be set in a window to work anyway.
Comment 6 Emmanuele Bassi (:ebassi) 2012-08-02 07:58:01 UTC
Review of attachment 213710 [details] [review]:

thanks for the patch.

it would be great if you attached a patch generated by a git commit - either using git format-patch or git bz - so that we can also review the commit message as well as properly credit your contribution.

this is mostly a preliminary review: you'll need another one.

thanks again!

::: gtk/gtkactiongroup.c
@@ +244,3 @@
 							 TRUE,
 							 GTK_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class,

the property should be documented.

@@ +571,3 @@
 
+  if (private->accel_group)
+    g_object_unref (private->accel_group);

you can use g_clear_object() instead.

@@ +787,3 @@
+  private = action_group->priv;
+
+ */

you can use:

  return action_group->priv->accel_group;

here, without using a separate variable.

@@ +831,3 @@
 /**
+ * gtk_action_group_set_accel_group:
+ * @action_group: the action group

the common pattern is to use "a #TypeName" in the annotation for the first argument

@@ +832,3 @@
+ * gtk_action_group_set_accel_group:
+ * @action_group: the action group
+ * @accel_group:

missing documentation for accel_group

@@ +834,3 @@
+ * @accel_group:
+ *
+ * Sets the accelerator group to use. 

a more descriptive annotation would be nice; why would you want to do this, for instance.

@@ +847,3 @@
+
+  private = action_group->priv;
+void

you should check if accel_group is the same one stored inside the private data structure, and return if so, to avoid resetting the same AccelGroup instance.

@@ +848,3 @@
+  private = action_group->priv;
+
+void

always put the statement on a separate line; and you can use g_clear_object() instead.

@@ +851,3 @@
+
+  private->accel_group = accel_group;
+                                  GtkAccelGroup  *accel_group)

you don't need to cast to GObject; and you can assign the value returned by g_object_ref() instead of separating the lines.

::: gtk/gtkactiongroup.h
@@ +166,3 @@
 void            gtk_action_group_set_visible             (GtkActionGroup             *action_group,
 							  gboolean                    visible);
+GtkAccelGroup  *gtk_action_group_get_accel_group         (GtkActionGroup             *action_group);

you should add the GDK_AVAILABLE_IN_3_6 annotation

@@ +168,3 @@
+GtkAccelGroup  *gtk_action_group_get_accel_group         (GtkActionGroup             *action_group);
+void            gtk_action_group_set_accel_group         (GtkActionGroup             *action_group,
+                                                          GtkAccelGroup              *accel_group);

same as above, you should add the GDK_AVAILABLE_IN_3_6 annotation
Comment 7 Juan Pablo Ugarte 2012-08-16 12:47:16 UTC
*** Bug 681894 has been marked as a duplicate of this bug. ***
Comment 8 Juan Pablo Ugarte 2012-08-16 18:10:15 UTC
Created attachment 221438 [details] [review]
Proposed patch 2nd try

Hello Emmanuele, I think I fixed all your recommendations.
Anyways my biggest concern is if adding a property is the right way to fix this issue or should we do some default magic instead.
Comment 9 Tristan Van Berkom 2012-09-12 13:56:54 UTC
Review of attachment 221438 [details] [review]:

So... one stylistic comment... is that you should not cause white noise in the patch because you prefer to use the name 'private' instead of 'priv'...

The other thing is, this can be done without modifying gtkmenuitem.c (with all the accelerator semantics, I'm paranoid about changing code and I think it should be done by changing the least lines of code as possible)

The only requirement is that gtk_action_set_accel_group() must be called for every action added to the GtkActionGroup.

So my suggestion, is yes... add 'accel-group' property to GtkActionGroup and:

  a.) When actions are added to the group, set the action group's accel-group on each
      added action using gtk_action_set_accel_group()

  b.) When gtk_action_group_set_accel_group() is called; iterate over all the owned
      actions and call gtk_action_set_accel_group() with the new accel-group for each owned action

AND, to make sure GtkUIManager does not break... GtkUIManager should also set it's privately created
accel group on the action groups it creates (since right now, there is a risk that the GtkActions
which get setup directly by uimanager might get thier accel groups unset by the GtkActionGroup).

Since... this is the way that UIManager always setup accelerators on actions, I feel like this
would be safer than modifying gtkmenuitem.c to do something different.
Comment 10 Tristan Van Berkom 2012-09-12 13:57:22 UTC
Review of attachment 221438 [details] [review]:

So... one stylistic comment... is that you should not cause white noise in the patch because you prefer to use the name 'private' instead of 'priv'...

The other thing is, this can be done without modifying gtkmenuitem.c (with all the accelerator semantics, I'm paranoid about changing code and I think it should be done by changing the least lines of code as possible)

The only requirement is that gtk_action_set_accel_group() must be called for every action added to the GtkActionGroup.

So my suggestion, is yes... add 'accel-group' property to GtkActionGroup and:

  a.) When actions are added to the group, set the action group's accel-group on each
      added action using gtk_action_set_accel_group()

  b.) When gtk_action_group_set_accel_group() is called; iterate over all the owned
      actions and call gtk_action_set_accel_group() with the new accel-group for each owned action

AND, to make sure GtkUIManager does not break... GtkUIManager should also set it's privately created
accel group on the action groups it creates (since right now, there is a risk that the GtkActions
which get setup directly by uimanager might get thier accel groups unset by the GtkActionGroup).

Since... this is the way that UIManager always setup accelerators on actions, I feel like this
would be safer than modifying gtkmenuitem.c to do something different.
Comment 11 Tristan Van Berkom 2012-09-12 13:57:23 UTC
Review of attachment 221438 [details] [review]:

So... one stylistic comment... is that you should not cause white noise in the patch because you prefer to use the name 'private' instead of 'priv'...

The other thing is, this can be done without modifying gtkmenuitem.c (with all the accelerator semantics, I'm paranoid about changing code and I think it should be done by changing the least lines of code as possible)

The only requirement is that gtk_action_set_accel_group() must be called for every action added to the GtkActionGroup.

So my suggestion, is yes... add 'accel-group' property to GtkActionGroup and:

  a.) When actions are added to the group, set the action group's accel-group on each
      added action using gtk_action_set_accel_group()

  b.) When gtk_action_group_set_accel_group() is called; iterate over all the owned
      actions and call gtk_action_set_accel_group() with the new accel-group for each owned action

AND, to make sure GtkUIManager does not break... GtkUIManager should also set it's privately created
accel group on the action groups it creates (since right now, there is a risk that the GtkActions
which get setup directly by uimanager might get thier accel groups unset by the GtkActionGroup).

Since... this is the way that UIManager always setup accelerators on actions, I feel like this
would be safer than modifying gtkmenuitem.c to do something different.
Comment 12 Juan Pablo Ugarte 2012-09-12 18:03:22 UTC
Created attachment 224135 [details] [review]
Proposed patch 3rd try

Same patch but with no menuitem modification.
Works like a charm.
Comment 13 Cosimo Cecchi 2012-09-12 21:00:54 UTC
Review of attachment 224135 [details] [review]:

Looks nice, provided the question raised by Tristan about how this interacts with GtkUIManager is not a problem.
Some comments below:

::: gtk/gtkactiongroup.c
@@ +844,3 @@
+  private = action_group->priv;
+
+ * 

The return should be on a new line

@@ +848,3 @@
+  g_clear_object (&private->accel_group);
+
+ */

Since gtk_action_set_accel_group() allows for a NULL accel group to be set on it, I think we should keep the same semantics here.
This would mean
- not unconditionally ref the object here
- add an (allow none) annotation to the gtk-doc block, and an "or %NULL" string to the setter and the getter functions

::: gtk/gtkactiongroup.h
@@ +166,3 @@
 void            gtk_action_group_set_visible             (GtkActionGroup             *action_group,
 							  gboolean                    visible);
+GtkAccelGroup  *gtk_action_group_get_accel_group         (GtkActionGroup             *action_group) GDK_AVAILABLE_IN_3_6;

We usually put the annotation before the function, like

GDK_AVAILABLE_IN_3_6
void foo(bar *baz);
Comment 14 Juan Pablo Ugarte 2012-09-12 22:21:49 UTC
ops somehow I though g_object_ref() would return NULL on NULL; so that is a bug.
About UImanager, it wont interfere with it as long as you do not set an accel group on an action group you are going to use with a uimanager.
Do you think I should modify uimanager in this very same patch?
all we would have to do is use this new api gtk_action_group_set_accel_group() instead of setting the accel group on each action manually
Comment 15 Juan Pablo Ugarte 2012-09-13 20:06:43 UTC
Created attachment 224266 [details] [review]
improved 3rd try

So I took a look at gtkuimanager.c and it only call gtk_action_set_accel_group() in one place update_node() and since it already iterates over every action it is not worth to use this new API. BTW there is no way this patch can interfere with the uimanager even if you set an accel group on the action group since the uimanager will set its own accel group.
Comment 16 Matthias Clasen 2012-09-14 20:01:24 UTC
What I don't like about this patch is that it makes accel group handling more explicit - yet more places that references to accel groups are stored (in accel labels, menu items, actions, ui manager...and now action groups). Despite the fact that we really want to move in the opposite direction...

Anyway, everybody else seems to like it, so lets go with it.
Comment 17 Juan Pablo Ugarte 2012-09-14 21:11:11 UTC
Do not get me wrong I do not like accel groups either :)
Sometimes I wish we could associate actions groups directly with windows.

In any case what I am trying to do here is fix the fact that there is not way to get all this working using just GtkBuilder.

I think this is an area we have to improve/simplify in the next API break.

BTW commited in master