X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkactiongroup.c;h=b9d6ee0837c41cb171a290e9dd687be1acd02a1d;hb=5c327ecbe573c60de2265a9622e569fd52943768;hp=803c5ef7c97702649c089b7ab61a8349e885ec8f;hpb=60b30ff5136acffc66b9e4fe27fb2509011ca896;p=~andy%2Fgtk diff --git a/gtk/gtkactiongroup.c b/gtk/gtkactiongroup.c index 803c5ef7c..b9d6ee083 100644 --- a/gtk/gtkactiongroup.c +++ b/gtk/gtkactiongroup.c @@ -29,15 +29,21 @@ */ #include +#include -#include "gtkalias.h" #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" +#include "gtkalias.h" #define GTK_ACTION_GROUP_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_ACTION_GROUP, GtkActionGroupPrivate)) @@ -84,6 +90,26 @@ static void gtk_action_group_get_property (GObject *object, 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) @@ -92,7 +118,7 @@ gtk_action_group_get_type (void) if (!type) { - static const GTypeInfo type_info = + const GTypeInfo type_info = { sizeof (GtkActionGroupClass), NULL, /* base_init */ @@ -105,10 +131,20 @@ gtk_action_group_get_type (void) (GInstanceInitFunc) gtk_action_group_init, }; - type = g_type_register_static (G_TYPE_OBJECT, "GtkActionGroup", + static 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; } @@ -134,22 +170,21 @@ gtk_action_group_class_init (GtkActionGroupClass *klass) P_("Name"), P_("A name for the action group."), NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY)); + 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, - G_PARAM_READWRITE)); + 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, - G_PARAM_READWRITE)); + GTK_PARAM_READWRITE)); /** * GtkActionGroup::connect-proxy: @@ -172,7 +207,7 @@ gtk_action_group_class_init (GtkActionGroupClass *klass) * Since: 2.4 */ action_group_signals[CONNECT_PROXY] = - g_signal_new ("connect_proxy", + g_signal_new (I_("connect_proxy"), G_OBJECT_CLASS_TYPE (klass), 0, 0, NULL, NULL, _gtk_marshal_VOID__OBJECT_OBJECT, @@ -195,7 +230,7 @@ gtk_action_group_class_init (GtkActionGroupClass *klass) * Since: 2.4 */ action_group_signals[DISCONNECT_PROXY] = - g_signal_new ("disconnect_proxy", + g_signal_new (I_("disconnect_proxy"), G_OBJECT_CLASS_TYPE (klass), 0, 0, NULL, NULL, _gtk_marshal_VOID__OBJECT_OBJECT, @@ -216,7 +251,7 @@ gtk_action_group_class_init (GtkActionGroupClass *klass) * Since: 2.4 */ action_group_signals[PRE_ACTIVATE] = - g_signal_new ("pre_activate", + g_signal_new (I_("pre_activate"), G_OBJECT_CLASS_TYPE (klass), 0, 0, NULL, NULL, _gtk_marshal_VOID__OBJECT, @@ -237,7 +272,7 @@ gtk_action_group_class_init (GtkActionGroupClass *klass) * Since: 2.4 */ action_group_signals[POST_ACTIVATE] = - g_signal_new ("post_activate", + g_signal_new (I_("post_activate"), G_OBJECT_CLASS_TYPE (klass), 0, 0, NULL, NULL, _gtk_marshal_VOID__OBJECT, @@ -251,7 +286,7 @@ gtk_action_group_class_init (GtkActionGroupClass *klass) static void remove_action (GtkAction *action) { - g_object_set (action, "action_group", NULL, NULL); + g_object_set (action, I_("action-group"), NULL, NULL); g_object_unref (action); } @@ -270,6 +305,148 @@ gtk_action_group_init (GtkActionGroup *self) self->private_data->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); + self->private_data->name = g_strdup (name); +} + +static const gchar * +gtk_action_group_buildable_get_name (GtkBuildable *buildable) +{ + GtkActionGroup *self = GTK_ACTION_GROUP (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 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 = (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 ("/", + 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. @@ -417,12 +594,13 @@ gtk_action_group_get_sensitive (GtkActionGroup *action_group) } static void -cb_set_action_sensitivity (const gchar *name, GtkAction *action) +cb_set_action_sensitivity (const gchar *name, + GtkAction *action) { - /* Minor optimization, the action_groups state only effects actions that are - * themselves sensitive */ + /* Minor optimization, the action_groups state only affects actions + * that are themselves sensitive */ if (gtk_action_get_sensitive (action)) - g_object_notify (G_OBJECT (action), "sensitive"); + _gtk_action_sync_sensitive (action); } /** @@ -435,15 +613,20 @@ cb_set_action_sensitivity (const gchar *name, GtkAction *action) * Since: 2.4 */ void -gtk_action_group_set_sensitive (GtkActionGroup *action_group, gboolean sensitive) +gtk_action_group_set_sensitive (GtkActionGroup *action_group, + gboolean sensitive) { g_return_if_fail (GTK_IS_ACTION_GROUP (action_group)); - if (action_group->private_data->sensitive ^ sensitive) + sensitive = sensitive != FALSE; + + if (action_group->private_data->sensitive != sensitive) { action_group->private_data->sensitive = sensitive; g_hash_table_foreach (action_group->private_data->actions, (GHFunc) cb_set_action_sensitivity, NULL); + + g_object_notify (G_OBJECT (action_group), "sensitive"); } } @@ -469,12 +652,13 @@ gtk_action_group_get_visible (GtkActionGroup *action_group) } static void -cb_set_action_visiblity (const gchar *name, GtkAction *action) +cb_set_action_visiblity (const gchar *name, + GtkAction *action) { - /* Minor optimization, the action_groups state only effects actions that are - * themselves sensitive */ + /* Minor optimization, the action_groups state only affects actions + * that are themselves visible */ if (gtk_action_get_visible (action)) - g_object_notify (G_OBJECT (action), "visible"); + _gtk_action_sync_visible (action); } /** @@ -487,15 +671,20 @@ cb_set_action_visiblity (const gchar *name, GtkAction *action) * Since: 2.4 */ void -gtk_action_group_set_visible (GtkActionGroup *action_group, gboolean visible) +gtk_action_group_set_visible (GtkActionGroup *action_group, + gboolean visible) { g_return_if_fail (GTK_IS_ACTION_GROUP (action_group)); - if (action_group->private_data->visible ^ visible) + visible = visible != FALSE; + + if (action_group->private_data->visible != visible) { action_group->private_data->visible = visible; g_hash_table_foreach (action_group->private_data->actions, (GHFunc) cb_set_action_visiblity, NULL); + + g_object_notify (G_OBJECT (action_group), "visible"); } } @@ -521,6 +710,21 @@ gtk_action_group_get_action (GtkActionGroup *action_group, (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) + { + g_warning ("Refusing to add non-unique action '%s' to action group '%s'", + action_name, + action_group->private_data->name); + return FALSE; + } + + return TRUE; +} + /** * gtk_action_group_add_action: * @action_group: the action group @@ -542,11 +746,14 @@ gtk_action_group_add_action (GtkActionGroup *action_group, 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); + + if (!check_unique_action (action_group, gtk_action_get_name (action))) + return; g_hash_table_insert (action_group->private_data->actions, g_strdup (gtk_action_get_name (action)), g_object_ref (action)); - g_object_set (action, "action_group", action_group, NULL); + g_object_set (action, I_("action-group"), action_group, NULL); } /** @@ -569,8 +776,8 @@ gtk_action_group_add_action (GtkActionGroup *action_group, */ void gtk_action_group_add_action_with_accel (GtkActionGroup *action_group, - GtkAction *action, - const gchar *accelerator) + GtkAction *action, + const gchar *accelerator) { gchar *accel_path; guint accel_key = 0; @@ -578,8 +785,11 @@ gtk_action_group_add_action_with_accel (GtkActionGroup *action_group, GtkStockItem stock_item; gchar *name; gchar *stock_id; + + if (!check_unique_action (action_group, gtk_action_get_name (action))) + return; - g_object_get (action, "name", &name, "stock_id", &stock_id, NULL); + g_object_get (action, "name", &name, "stock-id", &stock_id, NULL); accel_path = g_strconcat ("/", action_group->private_data->name, "/", name, NULL); @@ -714,7 +924,7 @@ shared_data_unref (gpointer data) if (shared_data->destroy) (*shared_data->destroy) (shared_data->data); - g_free (shared_data); + g_slice_free (SharedData, shared_data); } } @@ -748,7 +958,7 @@ gtk_action_group_add_actions_full (GtkActionGroup *action_group, g_return_if_fail (GTK_IS_ACTION_GROUP (action_group)); - shared_data = g_new0 (SharedData, 1); + shared_data = g_slice_new0 (SharedData); shared_data->ref_count = 1; shared_data->data = user_data; shared_data->destroy = destroy; @@ -759,14 +969,25 @@ gtk_action_group_add_actions_full (GtkActionGroup *action_group, 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, - entries[i].stock_id); + NULL); + if (entries[i].stock_id) + { + 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); + } + if (entries[i].callback) { GClosure *closure; @@ -844,7 +1065,7 @@ gtk_action_group_add_toggle_actions_full (GtkActionGroup *action_gro g_return_if_fail (GTK_IS_ACTION_GROUP (action_group)); - shared_data = g_new0 (SharedData, 1); + shared_data = g_slice_new0 (SharedData); shared_data->ref_count = 1; shared_data->data = user_data; shared_data->destroy = destroy; @@ -855,13 +1076,24 @@ gtk_action_group_add_toggle_actions_full (GtkActionGroup *action_gro 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_toggle_action_new (entries[i].name, label, tooltip, - entries[i].stock_id); + NULL); + + 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); + } gtk_toggle_action_set_active (action, entries[i].is_active); @@ -883,7 +1115,7 @@ gtk_action_group_add_toggle_actions_full (GtkActionGroup *action_gro g_object_unref (action); } - shared_data_unref (shared_data); + shared_data_unref (shared_data); } /** @@ -959,15 +1191,26 @@ gtk_action_group_add_radio_actions_full (GtkActionGroup *action_group 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, - entries[i].stock_id, + 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; @@ -1006,10 +1249,10 @@ gtk_action_group_add_radio_actions_full (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, + GtkDestroyNotify notify) { g_return_if_fail (GTK_IS_ACTION_GROUP (action_group)); @@ -1025,7 +1268,11 @@ static gchar * dgettext_swapped (const gchar *msgid, const gchar *domainname) { - return dgettext (domainname, msgid); + /* Pass through dgettext if and only if msgid is nonempty. */ + if (msgid && *msgid) + return dgettext (domainname, msgid); + else + return (gchar*) msgid; } /** @@ -1076,6 +1323,9 @@ gtk_action_group_translate_string (GtkActionGroup *action_group, g_return_val_if_fail (GTK_IS_ACTION_GROUP (action_group), string); + if (string == NULL) + return NULL; + translate_func = action_group->private_data->translate_func; translate_data = action_group->private_data->translate_data; @@ -1113,7 +1363,10 @@ _gtk_action_group_emit_pre_activate (GtkActionGroup *action_group, void _gtk_action_group_emit_post_activate (GtkActionGroup *action_group, - GtkAction *action) + GtkAction *action) { g_signal_emit (action_group, action_group_signals[POST_ACTIVATE], 0, action); } + +#define __GTK_ACTION_GROUP_C__ +#include "gtkaliasdef.c"