[tepl] Amtk utils: be able to bind detailed GAction name to GtkAction
- From: Sébastien Wilmet <swilmet src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tepl] Amtk utils: be able to bind detailed GAction name to GtkAction
- Date: Wed, 25 Oct 2017 10:36:18 +0000 (UTC)
commit 6088dccf37d4f6a4df5c7e59b3d046bc89fb361d
Author: Sébastien Wilmet <swilmet gnome org>
Date: Wed Oct 25 11:02:39 2017 +0200
Amtk utils: be able to bind detailed GAction name to GtkAction
It's not an API break, simple GAction names (with a NULL GVariant param)
still work fine.
amtk/amtk-utils.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++------
amtk/amtk-utils.h | 2 +-
2 files changed, 102 insertions(+), 13 deletions(-)
---
diff --git a/amtk/amtk-utils.c b/amtk/amtk-utils.c
index 589b8fb..9e247e9 100644
--- a/amtk/amtk-utils.c
+++ b/amtk/amtk-utils.c
@@ -183,18 +183,36 @@ amtk_utils_recent_chooser_menu_get_item_uri (GtkRecentChooserMenu *menu,
return item_uri;
}
+static gboolean
+variant_type_equal_null_safe (const GVariantType *type1,
+ const GVariantType *type2)
+{
+ if (type1 == NULL || type2 == NULL)
+ {
+ return type1 == NULL && type2 == NULL;
+ }
+
+ return g_variant_type_equal (type1, type2);
+}
+
+#define AMTK_GVARIANT_PARAM_KEY "amtk-gvariant-param-key"
+
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
static void
gtk_action_activate_cb (GtkAction *gtk_action,
GAction *g_action)
{
- g_action_activate (g_action, NULL);
+ GVariant *param;
+
+ param = g_object_get_data (G_OBJECT (gtk_action), AMTK_GVARIANT_PARAM_KEY);
+ g_action_activate (g_action, param);
}
/**
* amtk_utils_bind_g_action_to_gtk_action:
* @g_action_map: a #GActionMap.
- * @g_action_name: a #GAction name present in @g_action_map.
+ * @detailed_g_action_name: a detailed #GAction name; the #GAction must be
+ * present in @g_action_map.
* @gtk_action_group: a #GtkActionGroup.
* @gtk_action_name: a #GtkAction name present in @gtk_action_group.
*
@@ -202,9 +220,18 @@ gtk_action_activate_cb (GtkAction *gtk_action,
* when #GtkUIManager and #GtkAction are still used. Porting to #GAction should
* be the first step.
*
+ * For @detailed_g_action_name, see the g_action_parse_detailed_name() function.
+ * The `"app."` or `"win."` prefix (or any other #GActionMap prefix) must not be
+ * included in @detailed_g_action_name. For example a valid
+ * @detailed_g_action_name is `"open"` or `"insert-command::foobar"`.
+ *
+ * The same #GAction can be bound to several #GtkAction's (with different
+ * parameter values for the #GAction), but the reverse is not true, one
+ * #GtkAction cannot be bound to several #GAction's.
+ *
* This function:
- * - Calls g_action_activate() (with a %NULL #GVariant parameter) when the
- * #GtkAction #GtkAction::activate signal is emitted.
+ * - Calls g_action_activate() when the #GtkAction #GtkAction::activate signal
+ * is emitted.
* - Binds the #GAction #GAction:enabled property to the #GtkAction
* #GtkAction:sensitive property. The binding is done with the
* %G_BINDING_BIDIRECTIONAL and %G_BINDING_SYNC_CREATE flags, the source is
@@ -213,31 +240,89 @@ gtk_action_activate_cb (GtkAction *gtk_action,
* When using this function, you should set the callback to %NULL in the
* corresponding #GtkActionEntry.
*
- * Since: 3.0
+ * Since: 3.2
*/
void
amtk_utils_bind_g_action_to_gtk_action (GActionMap *g_action_map,
- const gchar *g_action_name,
+ const gchar *detailed_g_action_name,
GtkActionGroup *gtk_action_group,
const gchar *gtk_action_name)
{
+ gchar *g_action_name = NULL;
+ GVariant *target_value = NULL;
GAction *g_action;
- const GVariantType *param_type;
GtkAction *gtk_action;
+ GError *error = NULL;
g_return_if_fail (G_IS_ACTION_MAP (g_action_map));
- g_return_if_fail (g_action_name != NULL);
+ g_return_if_fail (detailed_g_action_name != NULL);
g_return_if_fail (GTK_IS_ACTION_GROUP (gtk_action_group));
g_return_if_fail (gtk_action_name != NULL);
+ g_action_parse_detailed_name (detailed_g_action_name,
+ &g_action_name,
+ &target_value,
+ &error);
+
+ /* The doc of g_action_parse_detailed_name() doesn't explain if it
+ * returns a floating ref for the GVariant.
+ */
+ if (target_value != NULL &&
+ g_variant_is_floating (target_value))
+ {
+ g_variant_ref_sink (target_value);
+ }
+
+ if (error != NULL)
+ {
+ g_warning ("Error when parsing detailed GAction name '%s': %s",
+ detailed_g_action_name,
+ error->message);
+
+ g_clear_error (&error);
+ goto out;
+ }
+
g_action = g_action_map_lookup_action (g_action_map, g_action_name);
- g_return_if_fail (g_action != NULL);
+ if (g_action == NULL)
+ {
+ g_warn_if_reached ();
+ goto out;
+ }
- param_type = g_action_get_parameter_type (g_action);
- g_return_if_fail (param_type == NULL);
+ /* Sanity check, ensure that the GVariant target has the good type. */
+ {
+ const GVariantType *g_action_param_type;
+ const GVariantType *target_value_type = NULL;
+
+ g_action_param_type = g_action_get_parameter_type (g_action);
+
+ if (target_value != NULL)
+ {
+ target_value_type = g_variant_get_type (target_value);
+ }
+
+ if (!variant_type_equal_null_safe (g_action_param_type, target_value_type))
+ {
+ g_warn_if_reached ();
+ goto out;
+ }
+ }
gtk_action = gtk_action_group_get_action (gtk_action_group, gtk_action_name);
- g_return_if_fail (gtk_action != NULL);
+ if (gtk_action == NULL)
+ {
+ g_warn_if_reached ();
+ goto out;
+ }
+
+ if (target_value != NULL)
+ {
+ g_object_set_data_full (G_OBJECT (gtk_action),
+ AMTK_GVARIANT_PARAM_KEY,
+ g_variant_ref (target_value),
+ (GDestroyNotify)g_variant_unref);
+ }
g_signal_connect_object (gtk_action,
"activate",
@@ -248,5 +333,9 @@ amtk_utils_bind_g_action_to_gtk_action (GActionMap *g_action_map,
g_object_bind_property (g_action, "enabled",
gtk_action, "sensitive",
G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+
+out:
+ g_free (g_action_name);
+ g_clear_pointer (&target_value, (GDestroyNotify)g_variant_unref);
}
G_GNUC_END_IGNORE_DEPRECATIONS
diff --git a/amtk/amtk-utils.h b/amtk/amtk-utils.h
index d3ac23b..cceadb3 100644
--- a/amtk/amtk-utils.h
+++ b/amtk/amtk-utils.h
@@ -45,7 +45,7 @@ gchar * amtk_utils_recent_chooser_menu_get_item_uri (GtkRecentChooserMenu
*menu
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
void amtk_utils_bind_g_action_to_gtk_action (GActionMap *g_action_map,
- const gchar *g_action_name,
+ const gchar *detailed_g_action_name,
GtkActionGroup *gtk_action_group,
const gchar *gtk_action_name);
G_GNUC_END_IGNORE_DEPRECATIONS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]