[glib/application] add GAction class, tests
- From: Ryan Lortie <ryanl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/application] add GAction class, tests
- Date: Thu, 12 Aug 2010 15:00:13 +0000 (UTC)
commit 2db4d38358e0568c0f45a7d143c4f6ad1d0d3f9f
Author: Ryan Lortie <desrt desrt ca>
Date: Thu Aug 12 10:59:41 2010 -0400
add GAction class, tests
gio/Makefile.am | 1 +
gio/gaction.c | 327 +++++++++++++++++++++++++++++++++++++++++++++++++
gio/gaction.h | 111 +++++++++++++++++
gio/gio.h | 1 +
gio/giotypes.h | 1 +
gio/tests/.gitignore | 1 +
gio/tests/Makefile.am | 3 +
gio/tests/actions.c | 81 ++++++++++++
8 files changed, 526 insertions(+), 0 deletions(-)
---
diff --git a/gio/Makefile.am b/gio/Makefile.am
index 46c6c8a..53a482b 100644
--- a/gio/Makefile.am
+++ b/gio/Makefile.am
@@ -260,6 +260,7 @@ SUBDIRS += tests
libgio_2_0_la_SOURCES = \
gappinfo.c \
+ gaction.c \
gapplicationimpl-dbus-interface.h \
gapplicationimpl-dbus-interface.c \
gapplicationcommandline.c\
diff --git a/gio/gaction.c b/gio/gaction.c
new file mode 100644
index 0000000..e0e8383
--- /dev/null
+++ b/gio/gaction.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright © 2010 Codethink Limited
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Ryan Lortie <desrt desrt ca>
+ */
+
+#include "gaction.h"
+
+G_DEFINE_TYPE (GAction, g_action, G_TYPE_OBJECT)
+
+struct _GActionPrivate
+{
+ gchar *name;
+ GVariantType *parameter_type;
+ gboolean enabled;
+
+ GVariantType *state_type;
+ GVariant *state_range;
+ GVariant *state;
+};
+
+enum
+{
+ PROP_NONE,
+ PROP_NAME,
+ PROP_PARAMETER_TYPE,
+ PROP_ENABLED,
+ PROP_STATE_TYPE,
+ PROP_STATE_RANGE,
+ PROP_STATE
+};
+
+enum
+{
+ SIGNAL_ACTIVATE,
+ NR_SIGNALS
+};
+
+static guint g_action_signals[NR_SIGNALS];
+
+static void
+g_action_set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ GAction *action = G_ACTION (object);
+
+ switch (prop_id)
+ {
+ case PROP_NAME:
+ g_assert (action->priv->name == NULL);
+ action->priv->name = g_value_dup_string (value);
+ break;
+
+ case PROP_PARAMETER_TYPE:
+ g_assert (action->priv->parameter_type == NULL);
+ action->priv->parameter_type = g_value_dup_boxed (value);
+ break;
+
+ case PROP_ENABLED:
+ g_action_set_enabled (action, g_value_get_boolean (value));
+ break;
+
+ case PROP_STATE_TYPE:
+ g_assert (action->priv->state_type == NULL);
+ action->priv->state_type = g_value_dup_boxed (value);
+ break;
+
+ case PROP_STATE_RANGE:
+ g_assert (action->priv->state_range == NULL);
+ action->priv->state_range = g_value_dup_variant (value);
+ break;
+
+ case PROP_STATE:
+ g_action_set_state (action, g_value_get_variant (value));
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static void
+g_action_get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+ GAction *action = G_ACTION (object);
+
+ switch (prop_id)
+ {
+ case PROP_NAME:
+ g_value_set_string (value, g_action_get_name (action));
+ break;
+
+ case PROP_PARAMETER_TYPE:
+ g_value_set_boxed (value, g_action_get_parameter_type (action));
+ break;
+
+ case PROP_ENABLED:
+ g_value_set_boolean (value, g_action_get_enabled (action));
+ break;
+
+ case PROP_STATE_TYPE:
+ g_value_set_boxed (value, g_action_get_state_type (action));
+ break;
+
+ case PROP_STATE_RANGE:
+ g_value_set_variant (value, g_action_get_state_range (action));
+ break;
+
+ case PROP_STATE:
+ g_value_set_variant (value, g_action_get_state (action));
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static void
+g_action_finalize (GObject *object)
+{
+ GAction *action = G_ACTION (object);
+
+ g_free (action->priv->name);
+ if (action->priv->parameter_type)
+ g_variant_type_free (action->priv->parameter_type);
+ if (action->priv->state_type)
+ g_variant_type_free (action->priv->state_type);
+ if (action->priv->state_range)
+ g_variant_unref (action->priv->state_range);
+ if (action->priv->state)
+ g_variant_unref (action->priv->state);
+
+ G_OBJECT_CLASS (g_action_parent_class)
+ ->finalize (object);
+}
+
+void
+g_action_init (GAction *action)
+{
+ action->priv = G_TYPE_INSTANCE_GET_PRIVATE (action,
+ G_TYPE_ACTION,
+ GActionPrivate);
+}
+
+void
+g_action_class_init (GActionClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ object_class->get_property = g_action_get_property;
+ object_class->set_property = g_action_set_property;
+ object_class->finalize = g_action_finalize;
+
+ g_action_signals[SIGNAL_ACTIVATE] =
+ g_signal_new ("activate", G_TYPE_ACTION, G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GActionClass, activate),
+ NULL, NULL, g_cclosure_marshal_VOID__VARIANT,
+ G_TYPE_NONE, 1, G_TYPE_VARIANT);
+
+ g_object_class_install_property (object_class, PROP_NAME,
+ g_param_spec_string ("name", "action name",
+ "the name used to invoke the action",
+ NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (object_class, PROP_PARAMETER_TYPE,
+ g_param_spec_boxed ("parameter-type", "parameter type",
+ "the type of GVariant passed to activate()",
+ G_TYPE_VARIANT_TYPE, G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (object_class, PROP_ENABLED,
+ g_param_spec_boolean ("enabled", "enabled",
+ "if the action can be activated",
+ TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (object_class, PROP_STATE_TYPE,
+ g_param_spec_boxed ("state-type", "state type",
+ "the type of the state kept by the action",
+ G_TYPE_VARIANT_TYPE, G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (object_class, PROP_STATE_RANGE,
+ g_param_spec_variant ("state-range", "state range",
+ "the range of possible values for state",
+ G_VARIANT_TYPE_ARRAY, NULL, G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (object_class, PROP_STATE,
+ g_param_spec_variant ("state", "state", "the state the action is in",
+ G_VARIANT_TYPE_ANY, NULL, G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+ g_type_class_add_private (class, sizeof (GActionPrivate));
+}
+
+void
+g_action_set_state (GAction *action,
+ GVariant *value)
+{
+ if (action->priv->state == value)
+ return;
+
+ g_return_if_fail (G_IS_ACTION (action));
+ g_return_if_fail ((action->priv->state_type == NULL && value == NULL) ||
+ g_variant_is_of_type (value, action->priv->state_type));
+
+ g_variant_ref_sink (value);
+
+ if (!action->priv->state || !g_variant_equal (action->priv->state, value))
+ {
+ if (action->priv->state)
+ g_variant_unref (action->priv->state);
+
+ action->priv->state = g_variant_ref (value);
+
+ g_object_notify (G_OBJECT (action), "state");
+ }
+
+ g_variant_unref (value);
+}
+
+GVariant *
+g_action_get_state (GAction *action)
+{
+ g_return_val_if_fail (G_IS_ACTION (action), NULL);
+
+ return action->priv->state;
+}
+
+const gchar *
+g_action_get_name (GAction *action)
+{
+ g_return_val_if_fail (G_IS_ACTION (action), NULL);
+
+ return action->priv->name;
+}
+
+const GVariantType *
+g_action_get_parameter_type (GAction *action)
+{
+ g_return_val_if_fail (G_IS_ACTION (action), NULL);
+
+ return action->priv->parameter_type;
+}
+
+const GVariantType *
+g_action_get_state_type (GAction *action)
+{
+ g_return_val_if_fail (G_IS_ACTION (action), NULL);
+
+ return action->priv->state_type;
+}
+
+GVariant *
+g_action_get_state_range (GAction *action)
+{
+ g_return_val_if_fail (G_IS_ACTION (action), NULL);
+
+ return action->priv->state_range;
+}
+
+gboolean
+g_action_get_enabled (GAction *action)
+{
+ g_return_val_if_fail (G_IS_ACTION (action), FALSE);
+
+ return action->priv->enabled;
+}
+
+void
+g_action_set_enabled (GAction *action,
+ gboolean enabled)
+{
+ g_return_if_fail (G_IS_ACTION (action));
+
+ enabled = !!enabled;
+
+ if (action->priv->enabled != enabled)
+ {
+ action->priv->enabled = enabled;
+ g_object_notify (G_OBJECT (action), "enabled");
+ }
+}
+
+void
+g_action_activate (GAction *action,
+ GVariant *parameter)
+{
+ g_return_if_fail (G_IS_ACTION (action));
+
+ g_return_if_fail (action->priv->parameter_type == NULL ?
+ parameter == NULL :
+ (parameter != NULL &&
+ g_variant_is_of_type (parameter,
+ action->priv->parameter_type)));
+
+ if (action->priv->enabled)
+ g_signal_emit (action, g_action_signals[SIGNAL_ACTIVATE], 0, parameter);
+}
+
+GAction *
+g_action_new (const gchar *name,
+ const GVariantType *parameter_type)
+{
+ return g_object_new (G_TYPE_ACTION,
+ "name", name,
+ "parameter-type", parameter_type,
+ NULL);
+}
diff --git a/gio/gaction.h b/gio/gaction.h
new file mode 100644
index 0000000..6a8b953
--- /dev/null
+++ b/gio/gaction.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright © 2010 Codethink Limited
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Ryan Lortie <desrt desrt ca>
+ */
+
+#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION)
+#error "Only <gio/gio.h> can be included directly."
+#endif
+
+#ifndef __G_ACTION_H__
+#define __G_ACTION_H__
+
+#include <gio/giotypes.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_ACTION (g_action_get_type ())
+#define G_ACTION(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
+ G_TYPE_ACTION, GAction))
+#define G_ACTION_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), \
+ G_TYPE_ACTION, GActionClass))
+#define G_IS_ACTION(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), G_TYPE_ACTION))
+#define G_IS_ACTION_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), G_TYPE_ACTION))
+#define G_ACTION_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), \
+ G_TYPE_ACTION, GActionClass))
+
+typedef struct _GActionPrivate GActionPrivate;
+typedef struct _GActionClass GActionClass;
+
+/**
+ * GAction:
+ *
+ * The <structname>GAction</structname> structure contains private
+ * data and should only be accessed using the provided API
+ *
+ * Since: 2.26
+ */
+struct _GAction
+{
+ /*< private >*/
+ GObject parent_instance;
+
+ GActionPrivate *priv;
+};
+
+/**
+ * GActionClass:
+ *
+ * The <structname>GActionClass</structname> structure contains
+ * private data only
+ *
+ * Since: 2.26
+ */
+struct _GActionClass
+{
+ /*< private >*/
+ GObjectClass parent_class;
+
+ /*< public >*/
+ void (* activate) (GAction *action,
+ GVariant *parameter);
+
+ /*< private >*/
+ gpointer padding[12];
+};
+
+GType g_action_get_type (void) G_GNUC_CONST;
+
+GAction * g_action_new (const gchar *name,
+ const GVariantType *parameter_type);
+
+GAction * g_action_new_stateful (const gchar *name,
+ const GVariantType *parameter_type,
+ const GVariantType *state_type,
+ GVariant *state_range,
+ GVariant *state);
+
+const gchar * g_action_get_name (GAction *action);
+const GVariantType * g_action_get_parameter_type (GAction *action);
+const GVariantType * g_action_get_state_type (GAction *action);
+GVariant * g_action_get_state_range (GAction *action);
+
+gboolean g_action_get_enabled (GAction *action);
+void g_action_set_enabled (GAction *action,
+ gboolean enabled);
+
+GVariant * g_action_get_state (GAction *action);
+void g_action_set_state (GAction *action,
+ GVariant *value);
+
+void g_action_activate (GAction *action,
+ GVariant *parameter);
+G_END_DECLS
+
+#endif /* __G_ACTION_H__ */
diff --git a/gio/gio.h b/gio/gio.h
index a80ed84..8cbdc0c 100644
--- a/gio/gio.h
+++ b/gio/gio.h
@@ -28,6 +28,7 @@
#include <gio/giotypes.h>
#include <gio/gappinfo.h>
+#include <gio/gaction.h>
#include <gio/gapplication.h>
#include <gio/gasyncinitable.h>
#include <gio/gasyncresult.h>
diff --git a/gio/giotypes.h b/gio/giotypes.h
index 64b730b..8394e8e 100644
--- a/gio/giotypes.h
+++ b/gio/giotypes.h
@@ -47,6 +47,7 @@ typedef struct _GSimplePermission GSimplePermission;
typedef struct _GZlibCompressor GZlibCompressor;
typedef struct _GZlibDecompressor GZlibDecompressor;
+typedef struct _GAction GAction;
typedef struct _GApplication GApplication;
typedef struct _GApplicationCommandLine GApplicationCommandLine;
typedef struct _GSettingsBackend GSettingsBackend;
diff --git a/gio/tests/.gitignore b/gio/tests/.gitignore
index 8b9e2ce..6cd873f 100644
--- a/gio/tests/.gitignore
+++ b/gio/tests/.gitignore
@@ -1,3 +1,4 @@
+actions
appinfo
appinfo-test
application
diff --git a/gio/tests/Makefile.am b/gio/tests/Makefile.am
index 78fca6d..09927dc 100644
--- a/gio/tests/Makefile.am
+++ b/gio/tests/Makefile.am
@@ -23,6 +23,7 @@ progs_ldadd = \
$(top_builddir)/gio/libgio-2.0.la
TEST_PROGS += \
+ actions \
memory-input-stream \
memory-output-stream \
readwrite \
@@ -98,6 +99,8 @@ if OS_WIN32
TEST_PROGS += win32-streams
endif
+actions_LDADD = $(progs_ldadd)
+
memory_input_stream_SOURCES = memory-input-stream.c
memory_input_stream_LDADD = $(progs_ldadd)
diff --git a/gio/tests/actions.c b/gio/tests/actions.c
new file mode 100644
index 0000000..326bb59
--- /dev/null
+++ b/gio/tests/actions.c
@@ -0,0 +1,81 @@
+#include <gio/gio.h>
+#include <stdlib.h>
+
+typedef struct
+{
+ GVariant *params;
+ gboolean did_run;
+} Activation;
+
+static void
+activate (GAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ Activation *activation = user_data;
+
+ if (parameter)
+ activation->params = g_variant_ref (parameter);
+ else
+ activation->params = NULL;
+ activation->did_run = TRUE;
+}
+
+static void
+test_basic (void)
+{
+ Activation a = { 0, };
+ GAction *action;
+
+ action = g_action_new ("foo", NULL);
+ g_signal_connect (action, "activate", G_CALLBACK (activate), &a);
+ g_assert (!a.did_run);
+ g_action_activate (action, NULL);
+ g_assert (a.did_run);
+ a.did_run = FALSE;
+
+ g_action_set_enabled (action, FALSE);
+ g_action_activate (action, NULL);
+ g_assert (!a.did_run);
+
+ if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
+ {
+ g_action_activate (action, g_variant_new_string ("xxx"));
+ exit (0);
+ }
+ g_test_trap_assert_failed ();
+
+ g_object_unref (action);
+ g_assert (!a.did_run);
+
+ action = g_action_new ("foo", G_VARIANT_TYPE_STRING);
+ g_signal_connect (action, "activate", G_CALLBACK (activate), &a);
+ g_assert (!a.did_run);
+ g_action_activate (action, g_variant_new_string ("Hello world"));
+ g_assert (a.did_run);
+ g_assert_cmpstr (g_variant_get_string (a.params, NULL), ==, "Hello world");
+ g_variant_unref (a.params);
+ a.did_run = FALSE;
+
+ if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
+ {
+ g_action_activate (action, NULL);
+ exit (0);
+ }
+
+ g_test_trap_assert_failed ();
+
+ g_object_unref (action);
+ g_assert (!a.did_run);
+}
+
+int
+main (int argc, char **argv)
+{
+ g_type_init ();
+ g_test_init (&argc, &argv, NULL);
+
+ g_test_add_func ("/actions/basic", test_basic);
+
+ return g_test_run ();
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]