]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkactiongroup.c
Remove usage of deprecated GtkTooltips API. Use
[~andy/gtk] / gtk / gtkactiongroup.c
index 803c5ef7c97702649c089b7ab61a8349e885ec8f..b9d6ee0837c41cb171a290e9dd687be1acd02a1d 100644 (file)
  */
 
 #include <config.h>
+#include <string.h>
 
-#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 <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.
@@ -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 ("<Actions>/",
                            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"