aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Uebernickel <lars.uebernickel@canonical.com>2012-11-27 15:14:26 +0100
committerLars Uebernickel <lars.uebernickel@canonical.com>2012-11-27 15:14:26 +0100
commite8e99703ef0c565f07a9d1eba03c1003d82ff697 (patch)
tree465e749b6a501187c25981c103125bf7abdaa32f
parentc9ddfbead428ec96459cd80b57aba6ad6ed0492a (diff)
downloadayatana-indicator-messages-e8e99703ef0c565f07a9d1eba03c1003d82ff697.tar.gz
ayatana-indicator-messages-e8e99703ef0c565f07a9d1eba03c1003d82ff697.tar.bz2
ayatana-indicator-messages-e8e99703ef0c565f07a9d1eba03c1003d82ff697.zip
Allow adding actions to MessagingMenuMessage
-rw-r--r--common/com.canonical.indicator.messages.application.xml4
-rw-r--r--libmessaging-menu/messaging-menu-app.c28
-rw-r--r--libmessaging-menu/messaging-menu-message.c160
-rw-r--r--libmessaging-menu/messaging-menu-message.h6
-rw-r--r--src/im-application-list.c6
5 files changed, 176 insertions, 28 deletions
diff --git a/common/com.canonical.indicator.messages.application.xml b/common/com.canonical.indicator.messages.application.xml
index 552b6a4..f37cd25 100644
--- a/common/com.canonical.indicator.messages.application.xml
+++ b/common/com.canonical.indicator.messages.application.xml
@@ -5,7 +5,7 @@
<arg type="a(sssuxsb)" name="sources" direction="out" />
</method>
<method name="ListMessages">
- <arg type="a(sssssxb)" name="message" direction="out" />
+ <arg type="a(sssssxa(ssgav)b)" name="message" direction="out" />
</method>
<method name="ActivateSource">
<arg type="s" name="source_id" direction="in" />
@@ -28,7 +28,7 @@
<arg type="s" name="source_id" direction="in" />
</signal>
<signal name="MessageAdded">
- <arg type="(sssssxb)" name="message" direction="in" />
+ <arg type="(sssssxa(ssgav)b)" name="message" direction="in" />
</signal>
<signal name="MessageRemoved">
<arg type="s" name="message_id" direction="in" />
diff --git a/libmessaging-menu/messaging-menu-app.c b/libmessaging-menu/messaging-menu-app.c
index d037da9..491c123 100644
--- a/libmessaging-menu/messaging-menu-app.c
+++ b/libmessaging-menu/messaging-menu-app.c
@@ -152,6 +152,9 @@ static void global_status_changed (IndicatorMessagesService *service,
const gchar *status_str,
gpointer user_data);
+/* in messaging-menu-message.c */
+GVariant * messaging_menu_message_to_variant (MessagingMenuMessage *msg);
+
static void
source_free (gpointer data)
{
@@ -188,29 +191,6 @@ source_to_variant (Source *source)
return v;
}
-static GVariant *
-messaging_menu_message_to_variant (MessagingMenuMessage *message)
-{
- GVariant *v;
- GIcon *icon;
- gchar *iconstr;
-
- icon = messaging_menu_message_get_icon (message);
- iconstr = icon ? g_icon_to_string (icon) : NULL;
-
- v = g_variant_new ("(sssssxb)", messaging_menu_message_get_id (message),
- iconstr ? iconstr : "",
- messaging_menu_message_get_title (message),
- messaging_menu_message_get_subtitle (message),
- messaging_menu_message_get_body (message),
- messaging_menu_message_get_time (message),
- messaging_menu_message_get_draws_attention (message));
-
- g_free (iconstr);
-
- return v;
-}
-
static gchar *
messaging_menu_app_get_dbus_object_path (MessagingMenuApp *app)
{
@@ -571,7 +551,7 @@ messaging_menu_app_list_messages (IndicatorMessagesApplication *app_interface,
GHashTableIter iter;
MessagingMenuMessage *message;
- g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(sssssxb)"));
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(sssssxa(ssgav)b)"));
g_hash_table_iter_init (&iter, app->messages);
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &message))
diff --git a/libmessaging-menu/messaging-menu-message.c b/libmessaging-menu/messaging-menu-message.c
index f5cb18c..cf050d3 100644
--- a/libmessaging-menu/messaging-menu-message.c
+++ b/libmessaging-menu/messaging-menu-message.c
@@ -32,6 +32,8 @@ struct _MessagingMenuMessage
gchar *body;
gint64 time;
gboolean draws_attention;
+
+ GSList *actions;
};
G_DEFINE_TYPE (MessagingMenuMessage, messaging_menu_message, G_TYPE_OBJECT);
@@ -51,6 +53,31 @@ enum
static GParamSpec *properties[NUM_PROPERTIES];
+typedef struct
+{
+ gchar *id;
+ gchar *label;
+ GVariantType *parameter_type;
+ GVariant *parameter_hint;
+} Action;
+
+static void
+action_free (gpointer data)
+{
+ Action *action = data;
+
+ g_free (action->id);
+ g_free (action->label);
+
+ if (action->parameter_type)
+ g_variant_type_free (action->parameter_type);
+
+ if (action->parameter_hint)
+ g_variant_unref (action->parameter_hint);
+
+ g_slice_free (Action, action);
+}
+
static void
messaging_menu_message_dispose (GObject *object)
{
@@ -71,6 +98,9 @@ messaging_menu_message_finalize (GObject *object)
g_free (msg->subtitle);
g_free (msg->body);
+ g_slist_free_full (msg->actions, action_free);
+ msg->actions = NULL;
+
G_OBJECT_CLASS (messaging_menu_message_parent_class)->finalize (object);
}
@@ -370,3 +400,133 @@ messaging_menu_message_set_draws_attention (MessagingMenuMessage *msg,
msg->draws_attention = draws_attention;
g_object_notify_by_pspec (G_OBJECT (msg), properties[PROP_DRAWS_ATTENTION]);
}
+
+/**
+ * messaging_menu_message_add_action:
+ * @msg: a #MessagingMenuMessage
+ * @id: unique id of the action
+ * @label: (allow-none): label of the action
+ * @parameter_type: (allow-none): a #GVariantType
+ * @parameter_hint: (allow-none): a #GVariant suggesting a valid range
+ * for parameters
+ *
+ * Adds an action with @id and @label to @message. Actions are an
+ * alternative way for users to activate a message. Note that messages
+ * can still be activated without an action.
+ *
+ * If @parameter_type is non-%NULL, the action is able to receive user
+ * input in addition to simply activating the action. Currently, only
+ * string parameters are supported.
+ *
+ * A list of predefined parameters can be supplied as a #GVariant array
+ * of @parameter_type in @parameter_hint. If @parameter_hint is
+ * floating, it will be consumed.
+ *
+ * It is recommended to add at most two actions to a message.
+ */
+void
+messaging_menu_message_add_action (MessagingMenuMessage *msg,
+ const gchar *id,
+ const gchar *label,
+ const GVariantType *parameter_type,
+ GVariant *parameter_hint)
+{
+ Action *action;
+
+ g_return_if_fail (MESSAGING_MENU_IS_MESSAGE (msg));
+ g_return_if_fail (id != NULL);
+
+ action = g_slice_new (Action);
+ action->id = g_strdup (id);
+ action->label = g_strdup (label);
+ action->parameter_type = parameter_type ? g_variant_type_copy (parameter_type) : NULL;
+ action->parameter_hint = parameter_hint ? g_variant_ref_sink (parameter_hint) : NULL;
+
+ msg->actions = g_slist_append (msg->actions, action);
+}
+
+static GVariant *
+action_to_variant (Action *action)
+{
+ GVariantBuilder builder;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("(ssgav)"));
+
+ g_variant_builder_add (&builder, "s", action->id);
+ g_variant_builder_add (&builder, "s", action->label ? action->label : "");
+
+ if (action->parameter_type)
+ {
+ gchar *type = g_variant_type_dup_string (action->parameter_type);
+ g_variant_builder_add (&builder, "g", type);
+ g_free (type);
+ }
+ else
+ g_variant_builder_add (&builder, "g", "");
+
+ g_variant_builder_open (&builder, G_VARIANT_TYPE ("av"));
+ if (action->parameter_hint)
+ g_variant_builder_add (&builder, "v", action->parameter_hint);
+ g_variant_builder_close (&builder);
+
+ return g_variant_builder_end (&builder);
+}
+
+/*<internal>
+ * messaging_menu_message_to_variant:
+ * @msg: a #MessagingMenuMessage
+ *
+ * Serializes @msg to a #GVariant of the form (sssssxa(ssgav)b):
+ *
+ * id
+ * icon
+ * title
+ * subtitle
+ * body
+ * time
+ * array of actions: id
+ * label
+ * parameter_type
+ * parameter_hint (0 or 1 elements)
+ * draws_attention
+ *
+ * Returns: a new floating #GVariant instance
+ */
+GVariant *
+messaging_menu_message_to_variant (MessagingMenuMessage *msg)
+{
+ GVariantBuilder builder;
+ GSList *it;
+
+ g_return_val_if_fail (MESSAGING_MENU_IS_MESSAGE (msg), NULL);
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("(sssssxa(ssgav)b)"));
+
+ g_variant_builder_add (&builder, "s", msg->id);
+
+ if (msg->icon)
+ {
+ gchar *iconstr;
+
+ iconstr = g_icon_to_string (msg->icon);
+ g_variant_builder_add (&builder, "s", iconstr);
+
+ g_free (iconstr);
+ }
+ else
+ g_variant_builder_add (&builder, "s", "");
+
+ g_variant_builder_add (&builder, "s", msg->title ? msg->title : "");
+ g_variant_builder_add (&builder, "s", msg->subtitle ? msg->subtitle : "");
+ g_variant_builder_add (&builder, "s", msg->body ? msg->body : "");
+ g_variant_builder_add (&builder, "x", msg->time);
+
+ g_variant_builder_open (&builder, G_VARIANT_TYPE ("a(ssgav)"));
+ for (it = msg->actions; it; it = it->next)
+ g_variant_builder_add_value (&builder, action_to_variant (it->data));
+ g_variant_builder_close (&builder);
+
+ g_variant_builder_add (&builder, "b", msg->draws_attention);
+
+ return g_variant_builder_end (&builder);
+}
diff --git a/libmessaging-menu/messaging-menu-message.h b/libmessaging-menu/messaging-menu-message.h
index 068247b..4708246 100644
--- a/libmessaging-menu/messaging-menu-message.h
+++ b/libmessaging-menu/messaging-menu-message.h
@@ -59,6 +59,12 @@ gboolean messaging_menu_message_get_draws_attention (MessagingMe
void messaging_menu_message_set_draws_attention (MessagingMenuMessage *msg,
gboolean draws_attention);
+void messaging_menu_message_add_action (MessagingMenuMessage *msg,
+ const gchar *id,
+ const gchar *label,
+ const GVariantType *parameter_type,
+ GVariant *parameter_hint);
+
G_END_DECLS
#endif
diff --git a/src/im-application-list.c b/src/im-application-list.c
index d766f24..4eaaed0 100644
--- a/src/im-application-list.c
+++ b/src/im-application-list.c
@@ -509,13 +509,14 @@ im_application_list_message_added (Application *app,
const gchar *subtitle;
const gchar *body;
gint64 time;
+ GVariantIter *action_iter;
gboolean draws_attention;
GSimpleAction *action;
GIcon *app_icon;
gchar *app_iconstr;
- g_variant_get (message, "(&s&s&s&s&sxb)",
- &id, &iconstr, &title, &subtitle, &body, &time, &draws_attention);
+ g_variant_get (message, "(&s&s&s&s&sxa(ssgav)b)",
+ &id, &iconstr, &title, &subtitle, &body, &time, &action_iter, &draws_attention);
app_icon = g_app_info_get_icon (G_APP_INFO (app->info));
app_iconstr = app_icon ? g_icon_to_string (app_icon) : NULL;
@@ -528,6 +529,7 @@ im_application_list_message_added (Application *app,
g_signal_emit (app->list, signals[MESSAGE_ADDED], 0,
app->id, app_iconstr, id, iconstr, title, subtitle, body, time, draws_attention);
+ g_variant_iter_free (action_iter);
g_free (app_iconstr);
g_object_unref (action);
}