X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkactiongroup.c;h=ac177e1ab3d2b6bfdf119af56b6321e03e12c735;hb=5bbbc47a4c306653e8347f7afb85a940a503f755;hp=500a49efd72d2b4347fdae6519bf2504cba41ba4;hpb=3cb958de19162d57df4c04d383f7fd52e4d818a1;p=~andy%2Fgtk
diff --git a/gtk/gtkactiongroup.c b/gtk/gtkactiongroup.c
index 500a49efd..ac177e1ab 100644
--- a/gtk/gtkactiongroup.c
+++ b/gtk/gtkactiongroup.c
@@ -14,9 +14,7 @@
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
- * License along with the Gnome Library; see the file COPYING.LIB. If not,
- * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see .
*/
/*
@@ -28,28 +26,148 @@
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
-#include
+/**
+ * SECTION:gtkactiongroup
+ * @Short_description: A group of actions
+ * @Title: GtkActionGroup
+ *
+ * Actions are organised into groups. An action group is essentially a
+ * map from names to #GtkAction objects.
+ *
+ * All actions that would make sense to use in a particular context
+ * should be in a single group. Multiple action groups may be used for a
+ * particular user interface. In fact, it is expected that most nontrivial
+ * applications will make use of multiple groups. For example, in an
+ * application that can edit multiple documents, one group holding global
+ * actions (e.g. quit, about, new), and one group per document holding
+ * actions that act on that document (eg. save, cut/copy/paste, etc). Each
+ * window's menus would be constructed from a combination of two action
+ * groups.
+ *
+ *
+ * Accelerators are handled by the GTK+ accelerator map. All actions are
+ * assigned an accelerator path (which normally has the form
+ * <Actions>/group-name/action-name)
+ * and a shortcut is associated with this accelerator path. All menuitems
+ * and toolitems take on this accelerator path. The GTK+ accelerator map
+ * code makes sure that the correct shortcut is displayed next to the menu
+ * item.
+ *
+ *
+ * GtkActionGroup as GtkBuildable
+ *
+ * The #GtkActionGroup implementation of the #GtkBuildable interface accepts
+ * #GtkAction objects as <child> elements in UI definitions.
+ *
+ * Note that it is probably more common to define actions and action groups
+ * in the code, since they are directly related to what the code can do.
+ *
+ * The GtkActionGroup implementation of the GtkBuildable interface supports
+ * a custom <accelerator> element, which has attributes named key and
+ * modifiers and allows to specify accelerators. This is similar to the
+ * <accelerator> element of #GtkWidget, the main difference is that
+ * it doesn't allow you to specify a signal.
+ *
+ *
+ * A #GtkDialog UI definition fragment.
+ *
+ *
+ *
+ *
+ *
+ *
+ * ]]>
+ *
+ *
+ */
+
+#include "config.h"
+#include
#include "gtkactiongroup.h"
+#include "gtkbuildable.h"
+#include "gtkiconfactory.h"
+#include "gtkicontheme.h"
+#include "gtkstock.h"
#include "gtktoggleaction.h"
#include "gtkradioaction.h"
#include "gtkaccelmap.h"
+#include "gtkmarshalers.h"
+#include "gtkbuilderprivate.h"
+#include "gtkprivate.h"
#include "gtkintl.h"
-#define GTK_ACTION_GROUP_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_ACTION_GROUP, GtkActionGroupPrivate))
struct _GtkActionGroupPrivate
{
gchar *name;
+ gboolean sensitive;
+ gboolean visible;
GHashTable *actions;
+ GtkAccelGroup *accel_group;
GtkTranslateFunc translate_func;
gpointer translate_data;
- GtkDestroyNotify translate_notify;
+ GDestroyNotify translate_notify;
+};
+
+enum
+{
+ CONNECT_PROXY,
+ DISCONNECT_PROXY,
+ PRE_ACTIVATE,
+ POST_ACTIVATE,
+ LAST_SIGNAL
+};
+
+enum
+{
+ PROP_0,
+ PROP_NAME,
+ PROP_SENSITIVE,
+ PROP_VISIBLE,
+ PROP_ACCEL_GROUP
};
-static void gtk_action_group_init (GtkActionGroup *self);
-static void gtk_action_group_class_init (GtkActionGroupClass *class);
+static void gtk_action_group_init (GtkActionGroup *self);
+static void gtk_action_group_class_init (GtkActionGroupClass *class);
+static void gtk_action_group_finalize (GObject *object);
+static void gtk_action_group_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gtk_action_group_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static GtkAction *gtk_action_group_real_get_action (GtkActionGroup *self,
+ const gchar *name);
+
+/* GtkBuildable */
+static void gtk_action_group_buildable_init (GtkBuildableIface *iface);
+static void gtk_action_group_buildable_add_child (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *type);
+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)
@@ -58,7 +176,7 @@ gtk_action_group_get_type (void)
if (!type)
{
- static const GTypeInfo type_info =
+ const GTypeInfo type_info =
{
sizeof (GtkActionGroupClass),
NULL, /* base_init */
@@ -71,17 +189,25 @@ gtk_action_group_get_type (void)
(GInstanceInitFunc) gtk_action_group_init,
};
- type = g_type_register_static (G_TYPE_OBJECT, "GtkActionGroup",
+ const GInterfaceInfo buildable_info =
+ {
+ (GInterfaceInitFunc) gtk_action_group_buildable_init,
+ NULL,
+ NULL
+ };
+
+ type = g_type_register_static (G_TYPE_OBJECT, I_("GtkActionGroup"),
&type_info, 0);
- }
+ g_type_add_interface_static (type,
+ GTK_TYPE_BUILDABLE,
+ &buildable_info);
+ }
return type;
}
static GObjectClass *parent_class = NULL;
-static void gtk_action_group_finalize (GObject *object);
-static GtkAction *gtk_action_group_real_get_action (GtkActionGroup *self,
- const gchar *name);
+static guint action_group_signals[LAST_SIGNAL] = { 0 };
static void
gtk_action_group_class_init (GtkActionGroupClass *klass)
@@ -92,29 +218,319 @@ gtk_action_group_class_init (GtkActionGroupClass *klass)
parent_class = g_type_class_peek_parent (klass);
gobject_class->finalize = gtk_action_group_finalize;
+ gobject_class->set_property = gtk_action_group_set_property;
+ gobject_class->get_property = gtk_action_group_get_property;
klass->get_action = gtk_action_group_real_get_action;
+ g_object_class_install_property (gobject_class,
+ PROP_NAME,
+ g_param_spec_string ("name",
+ P_("Name"),
+ P_("A name for the action group."),
+ NULL,
+ GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (gobject_class,
+ PROP_SENSITIVE,
+ g_param_spec_boolean ("sensitive",
+ P_("Sensitive"),
+ P_("Whether the action group is enabled."),
+ TRUE,
+ GTK_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class,
+ PROP_VISIBLE,
+ g_param_spec_boolean ("visible",
+ P_("Visible"),
+ P_("Whether the action group is visible."),
+ TRUE,
+ GTK_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class,
+ PROP_ACCEL_GROUP,
+ g_param_spec_object ("accel-group",
+ P_("Accelerator Group"),
+ P_("The accelerator group the actions of this group should use."),
+ GTK_TYPE_ACCEL_GROUP,
+ GTK_PARAM_READWRITE));
+
+ /**
+ * GtkActionGroup::connect-proxy:
+ * @action_group: the group
+ * @action: the action
+ * @proxy: the proxy
+ *
+ * The ::connect-proxy signal is emitted after connecting a proxy to
+ * an action in the group. Note that the proxy may have been connected
+ * to a different action before.
+ *
+ * This is intended for simple customizations for which a custom action
+ * class would be too clumsy, e.g. showing tooltips for menuitems in the
+ * statusbar.
+ *
+ * #GtkUIManager proxies the signal and provides global notification
+ * just before any action is connected to a proxy, which is probably more
+ * convenient to use.
+ *
+ * Since: 2.4
+ */
+ action_group_signals[CONNECT_PROXY] =
+ g_signal_new (I_("connect-proxy"),
+ G_OBJECT_CLASS_TYPE (klass),
+ 0, 0, NULL, NULL,
+ _gtk_marshal_VOID__OBJECT_OBJECT,
+ G_TYPE_NONE, 2,
+ GTK_TYPE_ACTION, GTK_TYPE_WIDGET);
+
+ /**
+ * GtkActionGroup::disconnect-proxy:
+ * @action_group: the group
+ * @action: the action
+ * @proxy: the proxy
+ *
+ * The ::disconnect-proxy signal is emitted after disconnecting a proxy
+ * from an action in the group.
+ *
+ * #GtkUIManager proxies the signal and provides global notification
+ * just before any action is connected to a proxy, which is probably more
+ * convenient to use.
+ *
+ * Since: 2.4
+ */
+ action_group_signals[DISCONNECT_PROXY] =
+ g_signal_new (I_("disconnect-proxy"),
+ G_OBJECT_CLASS_TYPE (klass),
+ 0, 0, NULL, NULL,
+ _gtk_marshal_VOID__OBJECT_OBJECT,
+ G_TYPE_NONE, 2,
+ GTK_TYPE_ACTION, GTK_TYPE_WIDGET);
+
+ /**
+ * GtkActionGroup::pre-activate:
+ * @action_group: the group
+ * @action: the action
+ *
+ * The ::pre-activate signal is emitted just before the @action in the
+ * @action_group is activated
+ *
+ * This is intended for #GtkUIManager to proxy the signal and provide global
+ * notification just before any action is activated.
+ *
+ * Since: 2.4
+ */
+ action_group_signals[PRE_ACTIVATE] =
+ g_signal_new (I_("pre-activate"),
+ G_OBJECT_CLASS_TYPE (klass),
+ 0, 0, NULL, NULL,
+ _gtk_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ GTK_TYPE_ACTION);
+
+ /**
+ * GtkActionGroup::post-activate:
+ * @action_group: the group
+ * @action: the action
+ *
+ * The ::post-activate signal is emitted just after the @action in the
+ * @action_group is activated
+ *
+ * This is intended for #GtkUIManager to proxy the signal and provide global
+ * notification just after any action is activated.
+ *
+ * Since: 2.4
+ */
+ action_group_signals[POST_ACTIVATE] =
+ g_signal_new (I_("post-activate"),
+ G_OBJECT_CLASS_TYPE (klass),
+ 0, 0, NULL, NULL,
+ _gtk_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ GTK_TYPE_ACTION);
+
g_type_class_add_private (gobject_class, sizeof (GtkActionGroupPrivate));
}
+
+static void
+remove_action (GtkAction *action)
+{
+ g_object_set (action, I_("action-group"), NULL, NULL);
+ g_object_unref (action);
+}
+
+static void
+gtk_action_group_init (GtkActionGroup *action_group)
+{
+ GtkActionGroupPrivate *private;
+
+ action_group->priv = G_TYPE_INSTANCE_GET_PRIVATE (action_group,
+ GTK_TYPE_ACTION_GROUP,
+ GtkActionGroupPrivate);
+ private = action_group->priv;
+
+ private->name = NULL;
+ private->sensitive = TRUE;
+ private->visible = TRUE;
+ private->actions = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL,
+ (GDestroyNotify) remove_action);
+ private->translate_func = NULL;
+ private->translate_data = NULL;
+ private->translate_notify = NULL;
+}
+
+static void
+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
+gtk_action_group_buildable_add_child (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *type)
+{
+ gtk_action_group_add_action_with_accel (GTK_ACTION_GROUP (buildable),
+ GTK_ACTION (child), NULL);
+}
+
+static void
+gtk_action_group_buildable_set_name (GtkBuildable *buildable,
+ const gchar *name)
+{
+ GtkActionGroup *self = GTK_ACTION_GROUP (buildable);
+ GtkActionGroupPrivate *private = self->priv;
+
+ private->name = g_strdup (name);
+}
+
+static const gchar *
+gtk_action_group_buildable_get_name (GtkBuildable *buildable)
+{
+ GtkActionGroup *self = GTK_ACTION_GROUP (buildable);
+ GtkActionGroupPrivate *private = self->priv;
+
+ return private->name;
+}
+
+typedef struct {
+ GObject *child;
+ guint key;
+ GdkModifierType 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;
+ GdkModifierType modifiers = 0;
+ AcceleratorParserData *parser_data = (AcceleratorParserData*)user_data;
+
+ if (strcmp (element_name, "accelerator") != 0)
+ g_warning ("Unknown 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 (" requires a key attribute");
+ return;
+ }
+ parser_data->key = key;
+ parser_data->modifiers = 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_init (GtkActionGroup *self)
+gtk_action_group_buildable_custom_tag_end (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *tagname,
+ gpointer *user_data)
{
- self->private_data = GTK_ACTION_GROUP_GET_PRIVATE (self);
- self->private_data->name = NULL;
- self->private_data->actions = g_hash_table_new_full (g_str_hash, g_str_equal,
- (GDestroyNotify) g_free,
- (GDestroyNotify) g_object_unref);
- self->private_data->translate_func = NULL;
- self->private_data->translate_data = NULL;
- self->private_data->translate_notify = NULL;
+ AcceleratorParserData *data;
+
+ if (strcmp (tagname, "accelerator") == 0)
+ {
+ GtkActionGroup *action_group;
+ GtkActionGroupPrivate *private;
+ GtkAction *action;
+ gchar *accel_path;
+
+ data = (AcceleratorParserData*)user_data;
+ action_group = GTK_ACTION_GROUP (buildable);
+ private = action_group->priv;
+ action = GTK_ACTION (child);
+
+ accel_path = g_strconcat ("/",
+ private->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
+ * @name: the name of the action group.
*
- * Creates a new #GtkActionGroup object.
+ * Creates a new #GtkActionGroup object. The name of the action group
+ * is used when associating keybindings
+ * with the actions.
*
* Returns: the new #GtkActionGroup
*
@@ -124,9 +540,11 @@ GtkActionGroup *
gtk_action_group_new (const gchar *name)
{
GtkActionGroup *self;
+ GtkActionGroupPrivate *private;
self = g_object_new (GTK_TYPE_ACTION_GROUP, NULL);
- self->private_data->name = g_strdup (name);
+ private = self->priv;
+ private->name = g_strdup (name);
return self;
}
@@ -135,27 +553,101 @@ static void
gtk_action_group_finalize (GObject *object)
{
GtkActionGroup *self;
+ GtkActionGroupPrivate *private;
self = GTK_ACTION_GROUP (object);
+ private = self->priv;
+
+ g_free (private->name);
+ private->name = NULL;
+
+ g_hash_table_destroy (private->actions);
+ private->actions = NULL;
+
+ g_clear_object (&private->accel_group);
+
+ if (private->translate_notify)
+ private->translate_notify (private->translate_data);
- g_free (self->private_data->name);
- self->private_data->name = NULL;
+ parent_class->finalize (object);
+}
- g_hash_table_destroy (self->private_data->actions);
- self->private_data->actions = NULL;
+static void
+gtk_action_group_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkActionGroup *self;
+ GtkActionGroupPrivate *private;
+ gchar *tmp;
+
+ self = GTK_ACTION_GROUP (object);
+ private = self->priv;
- if (self->private_data->translate_notify)
- self->private_data->translate_notify (self->private_data->translate_data);
+ switch (prop_id)
+ {
+ case PROP_NAME:
+ tmp = private->name;
+ private->name = g_value_dup_string (value);
+ g_free (tmp);
+ break;
+ case PROP_SENSITIVE:
+ gtk_action_group_set_sensitive (self, g_value_get_boolean (value));
+ break;
+ case PROP_VISIBLE:
+ gtk_action_group_set_visible (self, g_value_get_boolean (value));
+ break;
+ case PROP_ACCEL_GROUP:
+ gtk_action_group_set_accel_group (self, g_value_get_object (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_action_group_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkActionGroup *self;
+ GtkActionGroupPrivate *private;
+
+ self = GTK_ACTION_GROUP (object);
+ private = self->priv;
- if (parent_class->finalize)
- (* parent_class->finalize) (object);
+ switch (prop_id)
+ {
+ case PROP_NAME:
+ g_value_set_string (value, private->name);
+ break;
+ case PROP_SENSITIVE:
+ g_value_set_boolean (value, private->sensitive);
+ break;
+ case PROP_VISIBLE:
+ g_value_set_boolean (value, private->visible);
+ break;
+ case PROP_ACCEL_GROUP:
+ g_value_set_object (value, private->accel_group);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
}
static GtkAction *
gtk_action_group_real_get_action (GtkActionGroup *self,
const gchar *action_name)
{
- return g_hash_table_lookup (self->private_data->actions, action_name);
+ GtkActionGroupPrivate *private;
+
+ private = self->priv;
+
+ return g_hash_table_lookup (private->actions, action_name);
}
/**
@@ -171,9 +663,202 @@ gtk_action_group_real_get_action (GtkActionGroup *self,
const gchar *
gtk_action_group_get_name (GtkActionGroup *action_group)
{
+ GtkActionGroupPrivate *private;
+
g_return_val_if_fail (GTK_IS_ACTION_GROUP (action_group), NULL);
- return action_group->private_data->name;
+ private = action_group->priv;
+
+ return private->name;
+}
+
+/**
+ * gtk_action_group_get_sensitive:
+ * @action_group: the action group
+ *
+ * Returns %TRUE if the group is sensitive. The constituent actions
+ * can only be logically sensitive (see gtk_action_is_sensitive()) if
+ * they are sensitive (see gtk_action_get_sensitive()) and their group
+ * is sensitive.
+ *
+ * Return value: %TRUE if the group is sensitive.
+ *
+ * Since: 2.4
+ */
+gboolean
+gtk_action_group_get_sensitive (GtkActionGroup *action_group)
+{
+ GtkActionGroupPrivate *private;
+
+ g_return_val_if_fail (GTK_IS_ACTION_GROUP (action_group), FALSE);
+
+ private = action_group->priv;
+
+ return private->sensitive;
+}
+
+static void
+cb_set_action_sensitivity (const gchar *name,
+ GtkAction *action)
+{
+ /* Minor optimization, the action_groups state only affects actions
+ * that are themselves sensitive */
+ g_object_notify (G_OBJECT (action), "sensitive");
+
+}
+
+/**
+ * gtk_action_group_set_sensitive:
+ * @action_group: the action group
+ * @sensitive: new sensitivity
+ *
+ * Changes the sensitivity of @action_group
+ *
+ * Since: 2.4
+ */
+void
+gtk_action_group_set_sensitive (GtkActionGroup *action_group,
+ gboolean sensitive)
+{
+ GtkActionGroupPrivate *private;
+
+ g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
+
+ private = action_group->priv;
+ sensitive = sensitive != FALSE;
+
+ if (private->sensitive != sensitive)
+ {
+ private->sensitive = sensitive;
+ g_hash_table_foreach (private->actions,
+ (GHFunc) cb_set_action_sensitivity, NULL);
+
+ g_object_notify (G_OBJECT (action_group), "sensitive");
+ }
+}
+
+/**
+ * gtk_action_group_get_visible:
+ * @action_group: the action group
+ *
+ * Returns %TRUE if the group is visible. The constituent actions
+ * can only be logically visible (see gtk_action_is_visible()) if
+ * they are visible (see gtk_action_get_visible()) and their group
+ * is visible.
+ *
+ * Return value: %TRUE if the group is visible.
+ *
+ * Since: 2.4
+ */
+gboolean
+gtk_action_group_get_visible (GtkActionGroup *action_group)
+{
+ GtkActionGroupPrivate *private;
+
+ g_return_val_if_fail (GTK_IS_ACTION_GROUP (action_group), FALSE);
+
+ private = action_group->priv;
+
+ return private->visible;
+}
+
+/**
+ * gtk_action_group_get_accel_group:
+ * @action_group: a #GtkActionGroup
+ *
+ * Gets the accelerator group.
+ *
+ * Returns: (transfer none): the accelerator group associated with this action
+ * group or %NULL if there is none.
+ *
+ * Since: 3.6
+ */
+GtkAccelGroup *
+gtk_action_group_get_accel_group (GtkActionGroup *action_group)
+{
+ g_return_val_if_fail (GTK_IS_ACTION_GROUP (action_group), FALSE);
+
+ return action_group->priv->accel_group;
+}
+
+static void
+cb_set_action_visiblity (const gchar *name,
+ GtkAction *action)
+{
+ /* Minor optimization, the action_groups state only affects actions
+ * that are themselves visible */
+ g_object_notify (G_OBJECT (action), "visible");
+}
+
+/**
+ * gtk_action_group_set_visible:
+ * @action_group: the action group
+ * @visible: new visiblity
+ *
+ * Changes the visible of @action_group.
+ *
+ * Since: 2.4
+ */
+void
+gtk_action_group_set_visible (GtkActionGroup *action_group,
+ gboolean visible)
+{
+ GtkActionGroupPrivate *private;
+
+ g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
+
+ private = action_group->priv;
+ visible = visible != FALSE;
+
+ if (private->visible != visible)
+ {
+ private->visible = visible;
+ g_hash_table_foreach (private->actions,
+ (GHFunc) cb_set_action_visiblity, NULL);
+
+ g_object_notify (G_OBJECT (action_group), "visible");
+ }
+}
+
+static void
+gtk_action_group_accel_group_foreach (gpointer key, gpointer val, gpointer data)
+{
+ gtk_action_set_accel_group (val, data);
+}
+
+/**
+ * gtk_action_group_set_accel_group:
+ * @action_group: a #GtkActionGroup
+ * @accel_group: (allow-none): a #GtkAccelGroup to set or %NULL
+ *
+ * Sets the accelerator group to be used by every action in this group.
+ *
+ * Since: 3.6
+ */
+void
+gtk_action_group_set_accel_group (GtkActionGroup *action_group,
+ GtkAccelGroup *accel_group)
+{
+ GtkActionGroupPrivate *private;
+
+ g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
+
+ private = action_group->priv;
+
+ if (private->accel_group == accel_group)
+ return;
+
+ g_clear_object (&private->accel_group);
+
+ if (accel_group)
+ private->accel_group = g_object_ref (accel_group);
+
+ /* Set the new accel group on every action */
+ g_hash_table_foreach (private->actions,
+ gtk_action_group_accel_group_foreach,
+ accel_group);
+
+ g_object_notify (G_OBJECT (action_group), "accel-group");
}
/**
@@ -183,7 +868,7 @@ gtk_action_group_get_name (GtkActionGroup *action_group)
*
* Looks up an action in the action group by name.
*
- * Returns: the action, or %NULL if no action by that name exists
+ * Returns: (transfer none): the action, or %NULL if no action by that name exists
*
* Since: 2.4
*/
@@ -194,8 +879,27 @@ gtk_action_group_get_action (GtkActionGroup *action_group,
g_return_val_if_fail (GTK_IS_ACTION_GROUP (action_group), NULL);
g_return_val_if_fail (GTK_ACTION_GROUP_GET_CLASS (action_group)->get_action != NULL, NULL);
- return (* GTK_ACTION_GROUP_GET_CLASS (action_group)->get_action)
- (action_group, action_name);
+ return GTK_ACTION_GROUP_GET_CLASS (action_group)->get_action (action_group,
+ action_name);
+}
+
+static gboolean
+check_unique_action (GtkActionGroup *action_group,
+ const gchar *action_name)
+{
+ if (gtk_action_group_get_action (action_group, action_name) != NULL)
+ {
+ GtkActionGroupPrivate *private;
+
+ private = action_group->priv;
+
+ g_warning ("Refusing to add non-unique action '%s' to action group '%s'",
+ action_name,
+ private->name);
+ return FALSE;
+ }
+
+ return TRUE;
}
/**
@@ -203,7 +907,12 @@ gtk_action_group_get_action (GtkActionGroup *action_group,
* @action_group: the action group
* @action: an action
*
- * Adds an action object to the action group.
+ * Adds an action object to the action group. Note that this function
+ * does not set up the accel path of the action, which can lead to problems
+ * if a user tries to modify the accelerator of a menuitem associated with
+ * the action. Therefore you must either set the accel path yourself with
+ * gtk_action_set_accel_path(), or use
+ * gtk_action_group_add_action_with_accel (..., NULL).
*
* Since: 2.4
*/
@@ -211,17 +920,105 @@ void
gtk_action_group_add_action (GtkActionGroup *action_group,
GtkAction *action)
{
+ GtkActionGroupPrivate *private;
+ const gchar *name;
+
g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
g_return_if_fail (GTK_IS_ACTION (action));
- g_return_if_fail (gtk_action_get_name (action) != NULL);
- g_hash_table_insert (action_group->private_data->actions,
- g_strdup (gtk_action_get_name (action)),
+ name = gtk_action_get_name (action);
+ g_return_if_fail (name != NULL);
+
+ if (!check_unique_action (action_group, name))
+ return;
+
+ private = action_group->priv;
+
+ g_hash_table_insert (private->actions,
+ (gpointer) name,
g_object_ref (action));
+ g_object_set (action, I_("action-group"), action_group, NULL);
+
+ if (private->accel_group)
+ gtk_action_set_accel_group (action, private->accel_group);
+}
+
+/**
+ * gtk_action_group_add_action_with_accel:
+ * @action_group: the action group
+ * @action: the action to add
+ * @accelerator: (allow-none): the accelerator for the action, in
+ * the format understood by gtk_accelerator_parse(), or "" for no accelerator, or
+ * %NULL to use the stock accelerator
+ *
+ * Adds an action object to the action group and sets up the accelerator.
+ *
+ * If @accelerator is %NULL, attempts to use the accelerator associated
+ * with the stock_id of the action.
+ *
+ * Accel paths are set to
+ * <Actions>/group-name/action-name.
+ *
+ * Since: 2.4
+ */
+void
+gtk_action_group_add_action_with_accel (GtkActionGroup *action_group,
+ GtkAction *action,
+ const gchar *accelerator)
+{
+ GtkActionGroupPrivate *private;
+ gchar *accel_path;
+ guint accel_key = 0;
+ GdkModifierType accel_mods;
+ const gchar *name;
+
+ name = gtk_action_get_name (action);
+ if (!check_unique_action (action_group, name))
+ return;
+
+ private = action_group->priv;
+ accel_path = g_strconcat ("/",
+ private->name, "/", name, NULL);
+
+ if (accelerator)
+ {
+ if (accelerator[0] == 0)
+ accel_key = 0;
+ else
+ {
+ gtk_accelerator_parse (accelerator, &accel_key, &accel_mods);
+ if (accel_key == 0)
+ g_warning ("Unable to parse accelerator '%s' for action '%s'",
+ accelerator, name);
+ }
+ }
+ else
+ {
+ gchar *stock_id;
+ GtkStockItem stock_item;
+
+ g_object_get (action, "stock-id", &stock_id, NULL);
+
+ if (stock_id && gtk_stock_lookup (stock_id, &stock_item))
+ {
+ accel_key = stock_item.keyval;
+ accel_mods = stock_item.modifier;
+ }
+
+ g_free (stock_id);
+ }
+
+ if (accel_key)
+ gtk_accel_map_add_entry (accel_path, accel_key, accel_mods);
+
+ gtk_action_set_accel_path (action, accel_path);
+ gtk_action_group_add_action (action_group, action);
+
+ g_free (accel_path);
}
/**
- * gtk_action_group_removes_action:
+ * gtk_action_group_remove_action:
* @action_group: the action group
* @action: an action
*
@@ -233,14 +1030,18 @@ void
gtk_action_group_remove_action (GtkActionGroup *action_group,
GtkAction *action)
{
+ GtkActionGroupPrivate *private;
+ const gchar *name;
+
g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
g_return_if_fail (GTK_IS_ACTION (action));
- g_return_if_fail (gtk_action_get_name (action) != NULL);
- /* extra protection to make sure action->name is valid */
- g_object_ref (action);
- g_hash_table_remove (action_group->private_data->actions, gtk_action_get_name (action));
- g_object_unref (action);
+ name = gtk_action_get_name (action);
+ g_return_if_fail (name != NULL);
+
+ private = action_group->priv;
+
+ g_hash_table_remove (private->actions, name);
}
static void
@@ -259,131 +1060,378 @@ add_single_action (gpointer key,
*
* Lists the actions in the action group.
*
- * Returns: an allocated list of the action objects in the action group
- *
+ * Returns: (element-type GtkAction) (transfer container): an allocated list of the action objects in the action group
+ *
* Since: 2.4
*/
GList *
gtk_action_group_list_actions (GtkActionGroup *action_group)
{
+ GtkActionGroupPrivate *private;
GList *actions = NULL;
+
g_return_val_if_fail (GTK_IS_ACTION_GROUP (action_group), NULL);
+
+ private = action_group->priv;
- g_hash_table_foreach (action_group->private_data->actions, add_single_action, &actions);
+ g_hash_table_foreach (private->actions, add_single_action, &actions);
return g_list_reverse (actions);
}
/**
- * gtk_action_group_add_actions:
+ * gtk_action_group_add_actions: (skip)
+ * @action_group: the action group
+ * @entries: (array length=n_entries): an array of action descriptions
+ * @n_entries: the number of entries
+ * @user_data: data to pass to the action callbacks
+ *
+ * This is a convenience function to create a number of actions and add them
+ * to the action group.
+ *
+ * The "activate" signals of the actions are connected to the callbacks and
+ * their accel paths are set to
+ * <Actions>/group-name/action-name.
+ *
+ * Since: 2.4
+ */
+void
+gtk_action_group_add_actions (GtkActionGroup *action_group,
+ const GtkActionEntry *entries,
+ guint n_entries,
+ gpointer user_data)
+{
+ gtk_action_group_add_actions_full (action_group,
+ entries, n_entries,
+ user_data, NULL);
+}
+
+typedef struct _SharedData SharedData;
+
+struct _SharedData {
+ guint ref_count;
+ gpointer data;
+ GDestroyNotify destroy;
+};
+
+static void
+shared_data_unref (gpointer data)
+{
+ SharedData *shared_data = (SharedData *)data;
+
+ shared_data->ref_count--;
+ if (shared_data->ref_count == 0)
+ {
+ if (shared_data->destroy)
+ shared_data->destroy (shared_data->data);
+
+ g_slice_free (SharedData, shared_data);
+ }
+}
+
+
+/**
+ * gtk_action_group_add_actions_full: (skip)
* @action_group: the action group
- * @entries: an array of action descriptions
+ * @entries: (array length=n_entries): an array of action descriptions
* @n_entries: the number of entries
+ * @user_data: data to pass to the action callbacks
+ * @destroy: destroy notification callback for @user_data
*
- * This is a convenience routine to create a number of actions and add
- * them to the action group. Each member of the array describes an
- * action to create.
+ * This variant of gtk_action_group_add_actions() adds a #GDestroyNotify
+ * callback for @user_data.
*
* Since: 2.4
*/
void
-gtk_action_group_add_actions (GtkActionGroup *action_group,
- GtkActionGroupEntry *entries,
- guint n_entries)
+gtk_action_group_add_actions_full (GtkActionGroup *action_group,
+ const GtkActionEntry *entries,
+ guint n_entries,
+ gpointer user_data,
+ GDestroyNotify destroy)
{
+
+ /* Keep this in sync with the other
+ * gtk_action_group_add_..._actions_full() functions.
+ */
guint i;
- GtkTranslateFunc translate_func;
- gpointer translate_data;
+ SharedData *shared_data;
g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
- translate_func = action_group->private_data->translate_func;
- translate_data = action_group->private_data->translate_data;
+ shared_data = g_slice_new0 (SharedData);
+ shared_data->ref_count = 1;
+ shared_data->data = user_data;
+ shared_data->destroy = destroy;
for (i = 0; i < n_entries; i++)
{
GtkAction *action;
- GType action_type;
- gchar *accel_path;
- gchar *label;
- gchar *tooltip;
-
- switch (entries[i].entry_type) {
- case GTK_ACTION_NORMAL:
- action_type = GTK_TYPE_ACTION;
- break;
- case GTK_ACTION_TOGGLE:
- action_type = GTK_TYPE_TOGGLE_ACTION;
- break;
- case GTK_ACTION_RADIO:
- action_type = GTK_TYPE_RADIO_ACTION;
- break;
- default:
- g_warning ("unsupported action type");
- action_type = GTK_TYPE_ACTION;
- }
-
- if (translate_func)
+ const gchar *label;
+ const gchar *tooltip;
+
+ if (!check_unique_action (action_group, entries[i].name))
+ continue;
+
+ label = gtk_action_group_translate_string (action_group, entries[i].label);
+ tooltip = gtk_action_group_translate_string (action_group, entries[i].tooltip);
+
+ action = gtk_action_new (entries[i].name,
+ label,
+ tooltip,
+ NULL);
+
+ if (entries[i].stock_id)
{
- label = translate_func (entries[i].label, translate_data);
- tooltip = translate_func (entries[i].tooltip, translate_data);
+ g_object_set (action, "stock-id", entries[i].stock_id, NULL);
+ if (gtk_icon_theme_has_icon (gtk_icon_theme_get_default (),
+ entries[i].stock_id))
+ g_object_set (action, "icon-name", entries[i].stock_id, NULL);
}
- else
+
+ if (entries[i].callback)
{
- label = entries[i].label;
- tooltip = entries[i].tooltip;
+ GClosure *closure;
+
+ closure = g_cclosure_new (entries[i].callback, user_data, NULL);
+ g_closure_add_finalize_notifier (closure, shared_data,
+ (GClosureNotify)shared_data_unref);
+ shared_data->ref_count++;
+
+ g_signal_connect_closure (action, "activate", closure, FALSE);
}
+
+ gtk_action_group_add_action_with_accel (action_group,
+ action,
+ entries[i].accelerator);
+ g_object_unref (action);
+ }
+
+ shared_data_unref (shared_data);
+}
+
+/**
+ * gtk_action_group_add_toggle_actions: (skip)
+ * @action_group: the action group
+ * @entries: (array length=n_entries): an array of toggle action descriptions
+ * @n_entries: the number of entries
+ * @user_data: data to pass to the action callbacks
+ *
+ * This is a convenience function to create a number of toggle actions and add them
+ * to the action group.
+ *
+ * The "activate" signals of the actions are connected to the callbacks and
+ * their accel paths are set to
+ * <Actions>/group-name/action-name.
+ *
+ * Since: 2.4
+ */
+void
+gtk_action_group_add_toggle_actions (GtkActionGroup *action_group,
+ const GtkToggleActionEntry *entries,
+ guint n_entries,
+ gpointer user_data)
+{
+ gtk_action_group_add_toggle_actions_full (action_group,
+ entries, n_entries,
+ user_data, NULL);
+}
+
+
+/**
+ * gtk_action_group_add_toggle_actions_full: (skip)
+ * @action_group: the action group
+ * @entries: (array length=n_entries): an array of toggle action descriptions
+ * @n_entries: the number of entries
+ * @user_data: data to pass to the action callbacks
+ * @destroy: destroy notification callback for @user_data
+ *
+ * This variant of gtk_action_group_add_toggle_actions() adds a
+ * #GDestroyNotify callback for @user_data.
+ *
+ * Since: 2.4
+ */
+void
+gtk_action_group_add_toggle_actions_full (GtkActionGroup *action_group,
+ const GtkToggleActionEntry *entries,
+ guint n_entries,
+ gpointer user_data,
+ GDestroyNotify destroy)
+{
+ /* Keep this in sync with the other
+ * gtk_action_group_add_..._actions_full() functions.
+ */
+ guint i;
+ SharedData *shared_data;
- action = g_object_new (action_type,
- "name", entries[i].name,
- "label", label,
- "tooltip", tooltip,
- "stock_id", entries[i].stock_id,
- NULL);
+ g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
+
+ shared_data = g_slice_new0 (SharedData);
+ shared_data->ref_count = 1;
+ shared_data->data = user_data;
+ shared_data->destroy = destroy;
+
+ for (i = 0; i < n_entries; i++)
+ {
+ GtkToggleAction *action;
+ const gchar *label;
+ const gchar *tooltip;
+
+ if (!check_unique_action (action_group, entries[i].name))
+ continue;
+
+ label = gtk_action_group_translate_string (action_group, entries[i].label);
+ tooltip = gtk_action_group_translate_string (action_group, entries[i].tooltip);
- if (entries[i].entry_type == GTK_ACTION_RADIO &&
- entries[i].extra_data != NULL)
+ action = gtk_toggle_action_new (entries[i].name,
+ label,
+ tooltip,
+ NULL);
+
+ if (entries[i].stock_id)
{
- GtkAction *radio_action;
- GSList *group;
-
- radio_action =
- gtk_action_group_get_action (GTK_ACTION_GROUP (action_group),
- entries[i].extra_data);
- if (radio_action)
- {
- group = gtk_radio_action_get_group (GTK_RADIO_ACTION (radio_action));
- gtk_radio_action_set_group (GTK_RADIO_ACTION (action), group);
- }
+ if (gtk_icon_factory_lookup_default (entries[i].stock_id))
+ g_object_set (action, "stock-id", entries[i].stock_id, NULL);
else
- g_warning (G_STRLOC " could not look up `%s'", entries[i].extra_data);
+ g_object_set (action, "icon-name", entries[i].stock_id, NULL);
}
- if (entries[i].callback)
- g_signal_connect (action, "activate",
- entries[i].callback, entries[i].user_data);
+ gtk_toggle_action_set_active (action, entries[i].is_active);
- /* set the accel path for the menu item */
- accel_path = g_strconcat ("/", action_group->private_data->name, "/",
- entries[i].name, NULL);
- if (entries[i].accelerator)
+ if (entries[i].callback)
{
- guint accel_key = 0;
- GdkModifierType accel_mods;
+ GClosure *closure;
- gtk_accelerator_parse (entries[i].accelerator, &accel_key,
- &accel_mods);
- if (accel_key)
- gtk_accel_map_add_entry (accel_path, accel_key, accel_mods);
+ closure = g_cclosure_new (entries[i].callback, user_data, NULL);
+ g_closure_add_finalize_notifier (closure, shared_data,
+ (GClosureNotify)shared_data_unref);
+ shared_data->ref_count++;
+
+ g_signal_connect_closure (action, "activate", closure, FALSE);
}
+
+ gtk_action_group_add_action_with_accel (action_group,
+ GTK_ACTION (action),
+ entries[i].accelerator);
+ g_object_unref (action);
+ }
- gtk_action_set_accel_path (action, accel_path);
- g_free (accel_path);
+ shared_data_unref (shared_data);
+}
+
+/**
+ * gtk_action_group_add_radio_actions: (skip)
+ * @action_group: the action group
+ * @entries: (array length=n_entries): an array of radio action descriptions
+ * @n_entries: the number of entries
+ * @value: the value of the action to activate initially, or -1 if
+ * no action should be activated
+ * @on_change: the callback to connect to the changed signal
+ * @user_data: data to pass to the action callbacks
+ *
+ * This is a convenience routine to create a group of radio actions and
+ * add them to the action group.
+ *
+ * The "changed" signal of the first radio action is connected to the
+ * @on_change callback and the accel paths of the actions are set to
+ * <Actions>/group-name/action-name.
+ *
+ * Since: 2.4
+ **/
+void
+gtk_action_group_add_radio_actions (GtkActionGroup *action_group,
+ const GtkRadioActionEntry *entries,
+ guint n_entries,
+ gint value,
+ GCallback on_change,
+ gpointer user_data)
+{
+ gtk_action_group_add_radio_actions_full (action_group,
+ entries, n_entries,
+ value,
+ on_change, user_data, NULL);
+}
+
+/**
+ * gtk_action_group_add_radio_actions_full: (skip)
+ * @action_group: the action group
+ * @entries: (array length=n_entries): an array of radio action descriptions
+ * @n_entries: the number of entries
+ * @value: the value of the action to activate initially, or -1 if
+ * no action should be activated
+ * @on_change: the callback to connect to the changed signal
+ * @user_data: data to pass to the action callbacks
+ * @destroy: destroy notification callback for @user_data
+ *
+ * This variant of gtk_action_group_add_radio_actions() adds a
+ * #GDestroyNotify callback for @user_data.
+ *
+ * Since: 2.4
+ **/
+void
+gtk_action_group_add_radio_actions_full (GtkActionGroup *action_group,
+ const GtkRadioActionEntry *entries,
+ guint n_entries,
+ gint value,
+ GCallback on_change,
+ gpointer user_data,
+ GDestroyNotify destroy)
+{
+ /* Keep this in sync with the other
+ * gtk_action_group_add_..._actions_full() functions.
+ */
+ guint i;
+ GSList *group = NULL;
+ GtkRadioAction *first_action = NULL;
+
+ g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
- gtk_action_group_add_action (action_group, action);
+ for (i = 0; i < n_entries; i++)
+ {
+ GtkRadioAction *action;
+ const gchar *label;
+ const gchar *tooltip;
+
+ if (!check_unique_action (action_group, entries[i].name))
+ continue;
+
+ label = gtk_action_group_translate_string (action_group, entries[i].label);
+ tooltip = gtk_action_group_translate_string (action_group, entries[i].tooltip);
+
+ action = gtk_radio_action_new (entries[i].name,
+ label,
+ tooltip,
+ NULL,
+ entries[i].value);
+
+ if (entries[i].stock_id)
+ {
+ if (gtk_icon_factory_lookup_default (entries[i].stock_id))
+ g_object_set (action, "stock-id", entries[i].stock_id, NULL);
+ else
+ g_object_set (action, "icon-name", entries[i].stock_id, NULL);
+ }
+
+ if (i == 0)
+ first_action = action;
+
+ gtk_radio_action_set_group (action, group);
+ group = gtk_radio_action_get_group (action);
+
+ if (value == entries[i].value)
+ gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
+
+ gtk_action_group_add_action_with_accel (action_group,
+ GTK_ACTION (action),
+ entries[i].accelerator);
g_object_unref (action);
}
+
+ if (on_change && first_action)
+ g_signal_connect_data (first_action, "changed",
+ on_change, user_data,
+ (GClosureNotify)destroy, 0);
}
/**
@@ -391,11 +1439,11 @@ gtk_action_group_add_actions (GtkActionGroup *action_group,
* @action_group: a #GtkActionGroup
* @func: a #GtkTranslateFunc
* @data: data to be passed to @func and @notify
- * @notify: a #GtkDestroyNotify function to be called when @action_group is
+ * @notify: a #GDestroyNotify function to be called when @action_group is
* destroyed and when the translation function is changed again
- *
+ *
* Sets a function to be used for translating the @label and @tooltip of
- * #GtkActionGroupEntrys added by gtk_action_group_add_actions().
+ * #GtkActionEntrys added by gtk_action_group_add_actions().
*
* If you're using gettext(), it is enough to set the translation domain
* with gtk_action_group_set_translation_domain().
@@ -403,35 +1451,44 @@ gtk_action_group_add_actions (GtkActionGroup *action_group,
* Since: 2.4
**/
void
-gtk_action_group_set_translate_func (GtkActionGroup *action_group,
- GtkTranslateFunc func,
- gpointer data,
- GtkDestroyNotify notify)
+gtk_action_group_set_translate_func (GtkActionGroup *action_group,
+ GtkTranslateFunc func,
+ gpointer data,
+ GDestroyNotify notify)
{
+ GtkActionGroupPrivate *private;
+
g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
- if (action_group->private_data->translate_notify)
- action_group->private_data->translate_notify (action_group->private_data->translate_data);
+ private = action_group->priv;
+
+ if (private->translate_notify)
+ private->translate_notify (private->translate_data);
- action_group->private_data->translate_func = func;
- action_group->private_data->translate_data = data;
- action_group->private_data->translate_notify = notify;
+ private->translate_func = func;
+ private->translate_data = data;
+ private->translate_notify = notify;
}
static gchar *
dgettext_swapped (const gchar *msgid,
const gchar *domainname)
{
- return dgettext (domainname, msgid);
+ /* Pass through g_dgettext if and only if msgid is nonempty. */
+ if (msgid && *msgid)
+ return (gchar*) g_dgettext (domainname, msgid);
+ else
+ return (gchar*) msgid;
}
/**
* gtk_action_group_set_translation_domain:
* @action_group: a #GtkActionGroup
- * @domain: the translation domain to use for dgettext() calls
+ * @domain: (allow-none): the translation domain to use for g_dgettext()
+ * calls, or %NULL to use the domain set with textdomain()
*
- * Sets the translation domain and uses dgettext() for translating the
- * @label and @tooltip of #GtkActionGroupEntrys added by
+ * Sets the translation domain and uses g_dgettext() for translating the
+ * @label and @tooltip of #GtkActionEntrys added by
* gtk_action_group_add_actions().
*
* If you're not using gettext() for localization, see
@@ -450,3 +1507,74 @@ gtk_action_group_set_translation_domain (GtkActionGroup *action_group,
g_strdup (domain),
g_free);
}
+
+
+/**
+ * gtk_action_group_translate_string:
+ * @action_group: a #GtkActionGroup
+ * @string: a string
+ *
+ * Translates a string using the function set with
+ * gtk_action_group_set_translate_func(). This
+ * is mainly intended for language bindings.
+ *
+ * Returns: the translation of @string
+ *
+ * Since: 2.6
+ **/
+const gchar *
+gtk_action_group_translate_string (GtkActionGroup *action_group,
+ const gchar *string)
+{
+ GtkActionGroupPrivate *private;
+ GtkTranslateFunc translate_func;
+ gpointer translate_data;
+
+ g_return_val_if_fail (GTK_IS_ACTION_GROUP (action_group), string);
+
+ if (string == NULL)
+ return NULL;
+
+ private = action_group->priv;
+
+ translate_func = private->translate_func;
+ translate_data = private->translate_data;
+
+ if (translate_func)
+ return translate_func (string, translate_data);
+ else
+ return string;
+}
+
+/* Protected for use by GtkAction */
+void
+_gtk_action_group_emit_connect_proxy (GtkActionGroup *action_group,
+ GtkAction *action,
+ GtkWidget *proxy)
+{
+ g_signal_emit (action_group, action_group_signals[CONNECT_PROXY], 0,
+ action, proxy);
+}
+
+void
+_gtk_action_group_emit_disconnect_proxy (GtkActionGroup *action_group,
+ GtkAction *action,
+ GtkWidget *proxy)
+{
+ g_signal_emit (action_group, action_group_signals[DISCONNECT_PROXY], 0,
+ action, proxy);
+}
+
+void
+_gtk_action_group_emit_pre_activate (GtkActionGroup *action_group,
+ GtkAction *action)
+{
+ g_signal_emit (action_group, action_group_signals[PRE_ACTIVATE], 0, action);
+}
+
+void
+_gtk_action_group_emit_post_activate (GtkActionGroup *action_group,
+ GtkAction *action)
+{
+ g_signal_emit (action_group, action_group_signals[POST_ACTIVATE], 0, action);
+}