aboutsummaryrefslogtreecommitdiff
path: root/libmessaging-menu
diff options
context:
space:
mode:
Diffstat (limited to 'libmessaging-menu')
-rw-r--r--libmessaging-menu/messaging-menu-app.c77
-rw-r--r--libmessaging-menu/messaging-menu-message.c175
-rw-r--r--libmessaging-menu/messaging-menu-message.h6
3 files changed, 209 insertions, 49 deletions
diff --git a/libmessaging-menu/messaging-menu-app.c b/libmessaging-menu/messaging-menu-app.c
index d037da9..7e61324 100644
--- a/libmessaging-menu/messaging-menu-app.c
+++ b/libmessaging-menu/messaging-menu-app.c
@@ -126,7 +126,6 @@ enum {
enum {
ACTIVATE_SOURCE,
- ACTIVATE_MESSAGE,
STATUS_CHANGED,
N_SIGNALS
};
@@ -152,6 +151,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 +190,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)
{
@@ -386,27 +365,6 @@ messaging_menu_app_class_init (MessagingMenuAppClass *class)
G_TYPE_NONE, 1, G_TYPE_STRING);
/**
- * MessagingMenuApp::activate-message:
- * @mmapp: the #MessagingMenuApp
- * @message: the activated #MessagingMenuMessage
- *
- * Emitted when the user has activated a message. The message is
- * immediately removed from the application's menu, handlers of this
- * signal do not need to call messaging_menu_app_remove_message().
- *
- * To get notified about the activation of a specific message, set the
- * signal's detail to the message id.
- */
- signals[ACTIVATE_MESSAGE] = g_signal_new ("activate-message",
- MESSAGING_MENU_TYPE_APP,
- G_SIGNAL_RUN_FIRST |
- G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1, MESSAGING_MENU_TYPE_MESSAGE);
-
- /**
* MessagingMenuApp::status-changed:
* @mmapp: the #MessagingMenuApp
* @status: a #MessagingMenuStatus
@@ -571,11 +529,11 @@ 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(sssssxaa{sv}b)"));
g_hash_table_iter_init (&iter, app->messages);
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &message))
- g_variant_builder_add_value (&builder, messaging_menu_message_to_variant (message));
+ g_variant_builder_add_value (&builder, _messaging_menu_message_to_variant (message));
indicator_messages_application_complete_list_messages (app_interface,
invocation,
@@ -588,6 +546,8 @@ static gboolean
messaging_menu_app_activate_message (IndicatorMessagesApplication *app_interface,
GDBusMethodInvocation *invocation,
const gchar *message_id,
+ const gchar *action_id,
+ GVariant *params,
gpointer user_data)
{
MessagingMenuApp *app = user_data;
@@ -596,7 +556,26 @@ messaging_menu_app_activate_message (IndicatorMessagesApplication *app_interface
msg = g_hash_table_lookup (app->messages, message_id);
if (msg)
{
- g_signal_emit (app, signals[ACTIVATE_MESSAGE], g_quark_from_string (message_id), msg);
+ if (*action_id)
+ {
+ gchar *signal;
+
+ signal = g_strconcat ("activate::", action_id, NULL);
+
+ if (g_variant_n_children (params))
+ {
+ GVariant *param = g_variant_get_child_value (params, 0);
+ g_signal_emit_by_name (msg, signal, action_id, param);
+ g_variant_unref (param);
+ }
+ else
+ g_signal_emit_by_name (msg, signal, action_id, NULL);
+
+ g_free (signal);
+ }
+ else
+ g_signal_emit_by_name (msg, "activate", NULL, NULL);
+
/* Activate implies removing the message, no need for MessageRemoved */
messaging_menu_app_remove_message_internal (app, message_id);
@@ -1368,7 +1347,7 @@ messaging_menu_app_append_message (MessagingMenuApp *app,
g_hash_table_insert (app->messages, g_strdup (id), g_object_ref (msg));
indicator_messages_application_emit_message_added (app->app_interface,
- messaging_menu_message_to_variant (msg));
+ _messaging_menu_message_to_variant (msg));
if (source_id)
{
diff --git a/libmessaging-menu/messaging-menu-message.c b/libmessaging-menu/messaging-menu-message.c
index f5cb18c..b81cbea 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);
}
@@ -215,6 +245,26 @@ messaging_menu_message_class_init (MessagingMenuMessageClass *klass)
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (klass, NUM_PROPERTIES, properties);
+
+ /**
+ * MessagingMenuMessage::activate:
+ * @msg: the #MessagingMenuMessage
+ * @action: (allow-none): the id of activated action, or %NULL
+ * @parameter: (allow-none): activation parameter, or %NULL
+ *
+ * Emitted when the user has activated the message. The message is
+ * immediately removed from the application's menu, handlers of this
+ * signal do not need to call messaging_menu_app_remove_message().
+ */
+ g_signal_new ("activate",
+ MESSAGING_MENU_TYPE_MESSAGE,
+ G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_NONE, 2,
+ G_TYPE_STRING,
+ G_TYPE_VARIANT);
}
static void
@@ -370,3 +420,128 @@ 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 ("a{sv}"));
+
+ g_variant_builder_add (&builder, "{sv}", "name", g_variant_new_string (action->id));
+
+ if (action->label)
+ g_variant_builder_add (&builder, "{sv}", "label", g_variant_new_string (action->label));
+
+ if (action->parameter_type)
+ {
+ gchar *type = g_variant_type_dup_string (action->parameter_type);
+ g_variant_builder_add (&builder, "{sv}", "parameter-type", g_variant_new_signature (type));
+ g_free (type);
+ }
+
+ if (action->parameter_hint)
+ g_variant_builder_add (&builder, "{sv}", "parameter-hint", action->parameter_hint);
+
+ return g_variant_builder_end (&builder);
+}
+
+/*<internal>
+ * _messaging_menu_message_to_variant:
+ * @msg: a #MessagingMenuMessage
+ *
+ * Serializes @msg to a #GVariant of the form (sssssxaa{sv}b):
+ *
+ * id
+ * icon
+ * title
+ * subtitle
+ * body
+ * time
+ * array of action dictionaries
+ * 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 ("(sssssxaa{sv}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 ("aa{sv}"));
+ 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