aboutsummaryrefslogtreecommitdiff
path: root/src/im-application-list.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/im-application-list.c')
-rw-r--r--src/im-application-list.c128
1 files changed, 113 insertions, 15 deletions
diff --git a/src/im-application-list.c b/src/im-application-list.c
index 14af69b..684a2e4 100644
--- a/src/im-application-list.c
+++ b/src/im-application-list.c
@@ -21,10 +21,13 @@
#include "indicator-messages-application.h"
#include "gactionmuxer.h"
+#include "indicator-desktop-shortcuts.h"
#include <gio/gdesktopappinfo.h>
#include <string.h>
+#include "glib/gi18n.h"
+
typedef GObjectClass ImApplicationListClass;
struct _ImApplicationList
@@ -66,12 +69,12 @@ typedef struct
gchar *id;
IndicatorMessagesApplication *proxy;
GActionMuxer *muxer;
- GSimpleActionGroup *actions;
GSimpleActionGroup *source_actions;
GSimpleActionGroup *message_actions;
GActionMuxer *message_sub_actions;
GCancellable *cancellable;
gboolean draws_attention;
+ IndicatorDesktopShortcuts * shortcuts;
} Application;
@@ -108,9 +111,39 @@ application_free (gpointer data)
g_object_unref (app->message_sub_actions);
}
+ g_clear_object (&app->shortcuts);
+
g_slice_free (Application, app);
}
+/* Check to see if we have actions by getting the full list of
+ names and see if there is one. Not exactly efficient :-/ */
+static gboolean
+_g_action_group_has_actions (GActionGroup * ag)
+{
+ gchar ** list = NULL;
+ gboolean retval = FALSE;
+
+ list = g_action_group_list_actions(ag);
+ retval = (list[0] != NULL);
+ g_strfreev(list);
+
+ return retval;
+}
+
+/* Check to see if either of our action groups has any actions, if
+ so return TRUE so we get chosen! */
+static gboolean
+application_has_items (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ Application *app = value;
+
+ return _g_action_group_has_actions(G_ACTION_GROUP(app->source_actions)) ||
+ _g_action_group_has_actions(G_ACTION_GROUP(app->message_actions));
+}
+
static gboolean
application_draws_attention (gpointer key,
gpointer value,
@@ -124,18 +157,61 @@ application_draws_attention (gpointer key,
static void
im_application_list_update_draws_attention (ImApplicationList *list)
{
+ const gchar *base_icon_name;
+ const gchar *accessible_name;
const gchar *icon_name;
+ GIcon * icon;
+ GVariantBuilder builder;
GVariant *state;
- GActionGroup *main_actions;
- if (g_hash_table_find (list->applications, application_draws_attention, NULL))
- icon_name = "indicator-messages-new";
- else
- icon_name = "indicator-messages";
+ /* Figure out what type of icon we should be drawing */
+ if (g_hash_table_find (list->applications, application_draws_attention, NULL)) {
+ base_icon_name = "indicator-messages-new-%s";
+ accessible_name = _("New Messages");
+ } else {
+ base_icon_name = "indicator-messages-%s";
+ accessible_name = _("Messages");
+ }
- main_actions = g_action_muxer_get_group (list->muxer, NULL);
- state = g_variant_new ("(sssb)", "", icon_name, "Messages", TRUE);
- g_action_group_change_action_state (main_actions, "messages", state);
+ /* Include the IM state in the icon */
+ state = g_action_group_get_action_state(G_ACTION_GROUP(list->globalactions), "status");
+ icon_name = g_strdup_printf(base_icon_name, g_variant_get_string(state, NULL));
+ g_variant_unref(state);
+
+ /* Build up the dictionary of values for the state */
+ g_variant_builder_init(&builder, G_VARIANT_TYPE_DICTIONARY);
+
+ /* icon */
+ g_variant_builder_open(&builder, G_VARIANT_TYPE_DICT_ENTRY);
+ g_variant_builder_add_value(&builder, g_variant_new_string("icon"));
+ icon = g_themed_icon_new_with_default_fallbacks(icon_name);
+ g_variant_builder_add_value(&builder, g_variant_new_variant(g_icon_serialize(icon)));
+ g_object_unref(icon);
+ g_variant_builder_close(&builder);
+
+ /* accessible description */
+ g_variant_builder_open(&builder, G_VARIANT_TYPE_DICT_ENTRY);
+ g_variant_builder_add_value(&builder, g_variant_new_string("accessible-desc"));
+ g_variant_builder_add_value(&builder, g_variant_new_variant(g_variant_new_string(accessible_name)));
+ g_variant_builder_close(&builder);
+
+ /* visibility */
+ g_variant_builder_open(&builder, G_VARIANT_TYPE_DICT_ENTRY);
+ g_variant_builder_add_value(&builder, g_variant_new_string("visible"));
+ g_variant_builder_add_value(&builder, g_variant_new_variant(g_variant_new_boolean(TRUE)));
+ g_variant_builder_close(&builder);
+
+ /* Set the state */
+ g_action_group_change_action_state (G_ACTION_GROUP(list->globalactions), "messages", g_variant_builder_end(&builder));
+
+ GAction * remove_action = g_simple_action_group_lookup(list->globalactions, "remove-all");
+ if (g_hash_table_find (list->applications, application_has_items, NULL)) {
+ g_debug("Enabling remove-all");
+ g_simple_action_set_enabled(G_SIMPLE_ACTION(remove_action), TRUE);
+ } else {
+ g_debug("Disabling remove-all");
+ g_simple_action_set_enabled(G_SIMPLE_ACTION(remove_action), FALSE);
+ }
}
/* Check a source action to see if it draws */
@@ -490,7 +566,6 @@ static void
im_application_list_init (ImApplicationList *list)
{
const GActionEntry action_entries[] = {
- { "messages", NULL, NULL, "('', 'indicator-messages', 'Messages', true)", NULL },
{ "remove-all", im_application_list_remove_all }
};
@@ -498,6 +573,10 @@ im_application_list_init (ImApplicationList *list)
list->app_status = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
list->globalactions = g_simple_action_group_new ();
+ {
+ GSimpleAction * messages = g_simple_action_new_stateful("messages", G_VARIANT_TYPE("a{sv}"), g_variant_new_array(G_VARIANT_TYPE("{sv}"), NULL, 0));
+ g_simple_action_group_insert(list->globalactions, G_ACTION(messages));
+ }
g_simple_action_group_add_entries (list->globalactions, action_entries, G_N_ELEMENTS (action_entries), list);
list->statusaction = g_simple_action_new_stateful("status", G_VARIANT_TYPE_STRING, g_variant_new_string("offline"));
@@ -507,6 +586,7 @@ im_application_list_init (ImApplicationList *list)
list->muxer = g_action_muxer_new ();
g_action_muxer_insert (list->muxer, NULL, G_ACTION_GROUP (list->globalactions));
+ im_application_list_update_draws_attention (list);
}
ImApplicationList *
@@ -573,7 +653,7 @@ im_application_list_activate_app_action (GSimpleAction *action,
{
Application *app = user_data;
- g_desktop_app_info_launch_action (app->info, g_action_get_name (G_ACTION (action)), NULL);
+ indicator_desktop_shortcuts_nick_exec_with_context (app->shortcuts, g_action_get_name (G_ACTION (action)), NULL);
}
gboolean
@@ -585,6 +665,7 @@ im_application_list_add (ImApplicationList *list,
const gchar *id;
GSimpleActionGroup *actions;
GSimpleAction *launch_action;
+ IndicatorDesktopShortcuts * shortcuts = NULL;
g_return_if_fail (IM_IS_APPLICATION_LIST (list));
g_return_if_fail (desktop_id != NULL);
@@ -602,6 +683,12 @@ im_application_list_add (ImApplicationList *list,
id = g_app_info_get_id (G_APP_INFO (info));
g_return_if_fail (id != NULL);
+ {
+ const char * filename = g_desktop_app_info_get_filename(info);
+ if (filename != NULL)
+ shortcuts = indicator_desktop_shortcuts_new(filename, "Messaging Menu");
+ }
+
app = g_slice_new0 (Application);
app->info = info;
app->id = im_application_list_canonical_id (id);
@@ -611,6 +698,7 @@ im_application_list_add (ImApplicationList *list,
app->message_actions = g_simple_action_group_new ();
app->message_sub_actions = g_action_muxer_new ();
app->draws_attention = FALSE;
+ app->shortcuts = shortcuts;
actions = g_simple_action_group_new ();
@@ -618,14 +706,14 @@ im_application_list_add (ImApplicationList *list,
g_signal_connect (launch_action, "activate", G_CALLBACK (im_application_list_activate_launch), app);
g_action_map_add_action (G_ACTION_MAP (actions), G_ACTION (launch_action));
- {
- const gchar *const *app_actions;
+ if (app->shortcuts != NULL) {
+ const gchar ** nicks;
- for (app_actions = g_desktop_app_info_list_actions (app->info); *app_actions; app_actions++)
+ for (nicks = indicator_desktop_shortcuts_get_nicks (app->shortcuts); *nicks; nicks++)
{
GSimpleAction *action;
- action = g_simple_action_new (*app_actions, NULL);
+ action = g_simple_action_new (*nicks, NULL);
g_signal_connect (action, "activate", G_CALLBACK (im_application_list_activate_app_action), app);
g_action_map_add_action (G_ACTION_MAP (actions), G_ACTION (action));
@@ -715,15 +803,21 @@ im_application_list_source_changed (Application *app,
gint64 time;
const gchar *string;
gboolean draws_attention;
+ gboolean old_draw;
g_variant_get (source, "(&s&s&sux&sb)",
&id, &label, &iconstr, &count, &time, &string, &draws_attention);
+ old_draw = app_source_action_check_draw(app, id);
+
g_action_group_change_action_state (G_ACTION_GROUP (app->source_actions), id,
g_variant_new ("(uxsb)", count, time, string, draws_attention));
g_signal_emit (app->list, signals[SOURCE_CHANGED], 0, app->id, id, label, iconstr);
+ if (!old_draw && draws_attention)
+ app->draws_attention = TRUE;
+
im_application_list_update_draws_attention (app->list);
}
@@ -1091,6 +1185,8 @@ status_activated (GSimpleAction * action, GVariant * param, gpointer user_data)
g_signal_emit (list, signals[STATUS_SET], 0, status);
+ im_application_list_update_draws_attention(list);
+
return;
}
@@ -1136,6 +1232,8 @@ im_application_list_set_status (ImApplicationList * list, const gchar * id, cons
g_simple_action_set_state(list->statusaction, g_variant_new_string(status_ids[final_status]));
+ im_application_list_update_draws_attention(list);
+
return;
}