aboutsummaryrefslogtreecommitdiff
path: root/src/messages-service.c
diff options
context:
space:
mode:
authorLars Uebernickel <lars.uebernickel@canonical.com>2012-08-21 12:07:19 +0200
committerLars Uebernickel <lars.uebernickel@canonical.com>2012-08-21 12:07:19 +0200
commit374fa7bb7eb2526f1cf19bf85edd5793d8ef569b (patch)
treeeae99c80f31d940226680a31100024cd2b4a71c4 /src/messages-service.c
parent13f2b1bb69fb69aadcdc838b2321aa2b01657e06 (diff)
parent5df53a2c98d806f3b266d0032986d4dab3beb7a3 (diff)
downloadayatana-indicator-messages-374fa7bb7eb2526f1cf19bf85edd5793d8ef569b.tar.gz
ayatana-indicator-messages-374fa7bb7eb2526f1cf19bf85edd5793d8ef569b.tar.bz2
ayatana-indicator-messages-374fa7bb7eb2526f1cf19bf85edd5793d8ef569b.zip
Merge lp:~larsu/indicator-messags/towards-q-redesign
This branch introduces libmessaging-menu, a new library for applications to integrate with the messaging menu. Libindicate is not supported anymore. libmessaging-menu uses GMenuModel to communicate with indicator-messages-service. In order to take advantage of GMenuModel's architecture (re-exporting menus on a different path), the service now also sends its menu as a GMenuModel to the panel plugin. The plugin uses gtk_menu_new_from_model to create the menu widgets. Custom menu items are created by a small gtk+ patch that watches for x-canonical-type attributes. The branch also contains most of the design changes for quantal.
Diffstat (limited to 'src/messages-service.c')
-rw-r--r--src/messages-service.c1727
1 files changed, 335 insertions, 1392 deletions
diff --git a/src/messages-service.c b/src/messages-service.c
index 078cee3..7654e1f 100644
--- a/src/messages-service.c
+++ b/src/messages-service.c
@@ -20,1512 +20,461 @@ You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <string.h>
-#include <locale.h>
-#include <libintl.h>
#include <config.h>
-#include <pango/pango-utils.h>
-#include <libindicate/listener.h>
+#include <locale.h>
#include <libindicator/indicator-service.h>
#include <gio/gio.h>
+#include <gio/gdesktopappinfo.h>
#include <glib/gi18n.h>
-#include <libdbusmenu-glib/client.h>
-#include <libdbusmenu-glib/server.h>
-
-#include "im-menu-item.h"
-#include "app-menu-item.h"
-#include "launcher-menu-item.h"
+#include "app-section.h"
#include "dbus-data.h"
-#include "dirs.h"
-#include "messages-service-dbus.h"
-#include "seen-db.h"
-#include "status-items.h"
-
-static IndicatorService * service = NULL;
-static IndicateListener * listener = NULL;
-static GList * serverList = NULL;
-static GList * launcherList = NULL;
-
-static DbusmenuMenuitem * root_menuitem = NULL;
-static DbusmenuMenuitem * status_separator = NULL;
-static DbusmenuMenuitem * clear_attention = NULL;
-static GMainLoop * mainloop = NULL;
-
-static MessageServiceDbus * dbus_interface = NULL;
-
-#define DESKTOP_FILE_GROUP "Messaging Menu"
-#define DESKTOP_FILE_KEY_DESKTOP "DesktopFile"
-
-static void server_shortcut_added (AppMenuItem * appitem, DbusmenuMenuitem * mi, gpointer data);
-static void server_shortcut_removed (AppMenuItem * appitem, DbusmenuMenuitem * mi, gpointer data);
-static void server_count_changed (AppMenuItem * appitem, guint count, gpointer data);
-static void server_name_changed (AppMenuItem * appitem, gchar * name, gpointer data);
-static void im_time_changed (ImMenuItem * imitem, glong seconds, gpointer data);
-static void resort_menu (DbusmenuMenuitem * menushell);
-static void indicator_removed (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gpointer data);
-static void check_eclipses (AppMenuItem * ai);
-static void remove_eclipses (AppMenuItem * ai);
-static gboolean build_launcher (gpointer data);
-static gboolean build_launcher_keyfile (gpointer data);
-static void build_launcher_core (const gchar * desktop);
-static gboolean build_launchers (gpointer data);
-static gboolean blacklist_init (gpointer data);
-static gboolean blacklist_add (gpointer data);
-static gchar * desktop_file_from_keyfile (const gchar * definition_file);
-static gboolean blacklist_keyfile_add (gpointer udata);
-static void blacklist_add_core (gchar * desktop, gchar * definition);
-static gboolean blacklist_remove (gpointer data);
-static void blacklist_dir_changed (GFileMonitor * monitor, GFile * file, GFile * other_file, GFileMonitorEvent event_type, gpointer user_data);
-static void app_dir_changed (GFileMonitor * monitor, GFile * file, GFile * other_file, GFileMonitorEvent event_type, gpointer user_data);
-static gboolean destroy_launcher (gpointer data);
-static void check_hidden (void);
+#include "gactionmuxer.h"
+#include "gsettingsstrv.h"
+#include "gmenuutils.h"
+#include "indicator-messages-service.h"
+static GHashTable *applications;
-/*
- * Server List
- */
-
-typedef struct _serverList_t serverList_t;
-struct _serverList_t {
- IndicateListenerServer * server;
- AppMenuItem * menuitem;
- DbusmenuMenuitem * separator;
- gboolean attention;
- guint count;
- GList * imList;
-};
+IndicatorMessagesService *messages_service;
+static GSimpleActionGroup *actions;
+static GActionMuxer *action_muxer;
+static GMenu *toplevel_menu;
+static GMenu *menu;
+static GMenuModel *chat_section;
+static GSettings *settings;
-static gint
-serverList_equal (gconstpointer a, gconstpointer b)
-{
- serverList_t * pa, * pb;
- pa = (serverList_t *)a;
- pb = (serverList_t *)b;
+static gchar *
+g_app_info_get_simple_id (GAppInfo *appinfo)
+{
+ const gchar *id;
- const gchar * pan = INDICATE_LISTENER_SERVER_DBUS_NAME(pa->server);
- const gchar * pbn = INDICATE_LISTENER_SERVER_DBUS_NAME(pb->server);
- const gchar * pap = indicate_listener_server_get_dbuspath(pa->server);
- const gchar * pbp = indicate_listener_server_get_dbuspath(pb->server);
+ id = g_app_info_get_id (appinfo);
+ if (!id)
+ return NULL;
- if (g_strcmp0(pan, pbn) == 0)
- return g_strcmp0(pap, pbp);
+ if (g_str_has_suffix (id, ".desktop"))
+ return g_strndup (id, strlen (id) - 8);
else
- return 1;
+ return g_strdup (id);
}
-static gint
-serverList_sort (gconstpointer a, gconstpointer b)
+static void
+actions_changed (GObject *object,
+ GParamSpec *pspec,
+ gpointer user_data)
{
- serverList_t * pa, * pb;
+ AppSection *section = APP_SECTION (object);
+ gchar *id;
+ GActionGroup *actions;
- pa = (serverList_t *)a;
- pb = (serverList_t *)b;
+ id = g_app_info_get_simple_id (app_section_get_app_info (section));
+ actions = app_section_get_actions (section);
- const gchar * pan = app_menu_item_get_name(pa->menuitem);
- const gchar * pbn = app_menu_item_get_name(pb->menuitem);
-
- return g_strcmp0(pan, pbn);
+ g_action_muxer_insert (action_muxer, id, actions);
+ g_free (id);
}
-/*
- * Item List
- */
-
-typedef struct _imList_t imList_t;
-struct _imList_t {
- IndicateListenerServer * server;
- IndicateListenerIndicator * indicator;
- DbusmenuMenuitem * menuitem;
- gulong timechange_cb;
- gulong attentionchange_cb;
-};
static gboolean
-imList_equal (gconstpointer a, gconstpointer b)
-{
- imList_t * pa, * pb;
-
- pa = (imList_t *)a;
- pb = (imList_t *)b;
-
- const gchar * pas = INDICATE_LISTENER_SERVER_DBUS_NAME(pa->server);
- const gchar * pbs = INDICATE_LISTENER_SERVER_DBUS_NAME(pb->server);
-
- guint pai = INDICATE_LISTENER_INDICATOR_ID(pa->indicator);
- guint pbi = INDICATE_LISTENER_INDICATOR_ID(pb->indicator);
-
- g_debug("\tComparing (%s %d) to (%s %d)", pas, pai, pbs, pbi);
-
- return !((!g_strcmp0(pas, pbs)) && (pai == pbi));
-}
-
-static gint
-imList_sort (gconstpointer a, gconstpointer b)
-{
- imList_t * pa, * pb;
-
- pa = (imList_t *)a;
- pb = (imList_t *)b;
-
- return (gint)(im_menu_item_get_seconds(IM_MENU_ITEM(pb->menuitem)) - im_menu_item_get_seconds(IM_MENU_ITEM(pa->menuitem)));
-}
-
-/*
- * Launcher List
- */
-
-typedef struct _launcherList_t launcherList_t;
-struct _launcherList_t {
- LauncherMenuItem * menuitem;
- DbusmenuMenuitem * separator;
- GList * appdiritems;
-};
-
-static gint
-launcherList_sort (gconstpointer a, gconstpointer b)
+app_section_draws_attention (gpointer key,
+ gpointer value,
+ gpointer user_data)
{
- launcherList_t * pa, * pb;
-
- pa = (launcherList_t *)a;
- pb = (launcherList_t *)b;
-
- const gchar * pan = launcher_menu_item_get_name(pa->menuitem);
- const gchar * pbn = launcher_menu_item_get_name(pb->menuitem);
-
- return g_strcmp0(pan, pbn);
+ AppSection *section = value;
+ return app_section_get_draws_attention (section);
}
static void
-launcherList_count_helper (gpointer data, gpointer user_data)
+draws_attention_changed (GObject *object,
+ GParamSpec *pspec,
+ gpointer user_data)
{
- guint * count = (guint *)user_data;
- launcherList_t * li = (launcherList_t *)data;
-
- if (!launcher_menu_item_get_eclipsed(li->menuitem)) {
- *count = *count + 1;
- }
-
- return;
-}
-
-static guint
-launcherList_count (void)
-{
- guint count = 0;
-
- g_list_foreach(launcherList, launcherList_count_helper, &count);
-
- return count;
-}
-
-/*
- * Black List
- */
-
-static GHashTable * blacklist = NULL;
-static GFileMonitor * blacklistdirmon = NULL;
-
-/* Initialize the black list and start to setup
- handlers for it. */
-static gboolean
-blacklist_init (gpointer data)
-{
- blacklist = g_hash_table_new_full(g_str_hash, g_str_equal,
- g_free, g_free);
-
- gchar * blacklistdir = g_build_filename(g_get_user_config_dir(), USER_BLACKLIST_DIR, NULL);
- g_debug("Looking at blacklist: %s", blacklistdir);
- if (!g_file_test(blacklistdir, G_FILE_TEST_IS_DIR)) {
- g_free(blacklistdir);
- return FALSE;
- }
-
- GFile * filedir = g_file_new_for_path(blacklistdir);
- blacklistdirmon = g_file_monitor_directory(filedir, G_FILE_MONITOR_NONE, NULL, NULL);
- if (blacklistdirmon != NULL) {
- g_signal_connect(G_OBJECT(blacklistdirmon), "changed", G_CALLBACK(blacklist_dir_changed), NULL);
- }
-
- GError * error = NULL;
- GDir * dir = g_dir_open(blacklistdir, 0, &error);
- if (dir == NULL) {
- g_warning("Unable to open blacklist directory (%s): %s", blacklistdir, error == NULL ? "No Message" : error->message);
- g_error_free(error);
- g_free(blacklistdir);
- return FALSE;
- }
+ GSimpleAction *messages;
+ GSimpleAction *clear;
+ gboolean attention;
- const gchar * filename = NULL;
- while ((filename = g_dir_read_name(dir)) != NULL) {
- g_debug("Found file: %s", filename);
- gchar * path = g_build_filename(blacklistdir, filename, NULL);
- if (g_str_has_suffix(path, "keyfile")) {
- g_idle_add(blacklist_keyfile_add, path);
- } else {
- g_idle_add(blacklist_add, path);
- }
- }
+ messages = G_SIMPLE_ACTION (g_simple_action_group_lookup (actions, "messages"));
+ clear = G_SIMPLE_ACTION (g_simple_action_group_lookup (actions, "clear"));
+ g_return_if_fail (messages != NULL && clear != NULL);
- g_dir_close(dir);
- g_free(blacklistdir);
+ attention = g_hash_table_find (applications, app_section_draws_attention, NULL) != NULL;
- return FALSE;
+ g_simple_action_set_state (messages, g_variant_new_boolean (attention));
+ g_simple_action_set_enabled (clear, attention);
}
-/* Parses through a keyfile to find the desktop file entry and
- pushes them into the blacklist. */
static gboolean
-blacklist_keyfile_add (gpointer udata)
+app_section_uses_chat (gpointer key,
+ gpointer value,
+ gpointer user_data)
{
- gchar * definition_file = (gchar *)udata;
- gchar * desktopfile = desktop_file_from_keyfile(definition_file);
- if (desktopfile != NULL) {
- blacklist_add_core(desktopfile, definition_file);
- g_free(desktopfile);
- }
- return FALSE;
+ AppSection *section = value;
+ return app_section_get_uses_chat_status (section);
}
-/* Takes a keyfile and finds the desktop file in it for
- us. With some error handling. */
-static gchar *
-desktop_file_from_keyfile (const gchar * definition_file)
+static void
+uses_chat_status_changed (GObject *object,
+ GParamSpec *pspec,
+ gpointer user_data)
{
- GKeyFile * keyfile = g_key_file_new();
- GError * error = NULL;
+ gboolean show_chat;
+ GMenuModel *first_section;
- if (!g_key_file_load_from_file(keyfile, definition_file, G_KEY_FILE_NONE, &error)) {
- g_warning("Unable to load keyfile '%s' because: %s", definition_file, error == NULL ? "unknown" : error->message);
- g_error_free(error);
- g_key_file_free(keyfile);
- return NULL;
- }
+ show_chat = g_hash_table_find (applications, app_section_uses_chat, NULL) != NULL;
- if (!g_key_file_has_group(keyfile, DESKTOP_FILE_GROUP)) {
- g_warning("Unable to use keyfile '%s' as it has no '" DESKTOP_FILE_GROUP "' group.", definition_file);
- g_key_file_free(keyfile);
- return NULL;
+ first_section = g_menu_model_get_item_link (G_MENU_MODEL (menu), 0, G_MENU_LINK_SECTION);
+ if (first_section == chat_section) {
+ if (!show_chat)
+ g_menu_remove (menu, 0);
}
-
- if (!g_key_file_has_key(keyfile, DESKTOP_FILE_GROUP, DESKTOP_FILE_KEY_DESKTOP, &error)) {
- g_warning("Unable to use keyfile '%s' as there is no key '" DESKTOP_FILE_KEY_DESKTOP "' in the group '" DESKTOP_FILE_GROUP "' because: %s", definition_file, error == NULL ? "unknown" : error->message);
- g_error_free(error);
- g_key_file_free(keyfile);
- return NULL;
+ else {
+ if (show_chat)
+ g_menu_insert_section (menu, 0, NULL, chat_section);
}
-
- gchar * desktopfile = g_key_file_get_string(keyfile, DESKTOP_FILE_GROUP, DESKTOP_FILE_KEY_DESKTOP, &error);
- g_key_file_free(keyfile);
- return desktopfile;
}
-/* Check if path is a symlink and return its target if it is */
-static gchar *
-get_symlink_target (const gchar *path)
+static AppSection *
+add_application (const gchar *desktop_id)
{
- GFile *file;
- GFileInfo *fileinfo;
- gchar *target = NULL;
-
- file = g_file_new_for_path (path);
+ GDesktopAppInfo *appinfo;
+ gchar *id;
+ AppSection *section;
- fileinfo = g_file_query_info (file, "standard::is-symlink",
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- NULL, NULL);
- g_object_unref (file);
-
- if (!fileinfo)
+ appinfo = g_desktop_app_info_new (desktop_id);
+ if (!appinfo) {
+ g_warning ("could not add '%s', there's no desktop file with that id", desktop_id);
return NULL;
+ }
- if (g_file_info_get_is_symlink (fileinfo))
- target = g_strdup (g_file_info_get_symlink_target (fileinfo));
+ id = g_app_info_get_simple_id (G_APP_INFO (appinfo));
+ section = g_hash_table_lookup (applications, id);
- g_object_unref (fileinfo);
- return target;
-}
+ if (!section) {
+ GMenuItem *menuitem;
-/* Add a definition file into the black list and eclipse
- any launchers that have the same file. */
-static gboolean
-blacklist_add (gpointer udata)
-{
- gchar * definition_file = (gchar *)udata;
- gchar * symlink_target = get_symlink_target (definition_file);
- gchar * contents = NULL;
+ section = app_section_new(appinfo);
+ g_hash_table_insert (applications, g_strdup (id), section);
- if (symlink_target)
- {
- blacklist_add_core (symlink_target, definition_file);
- g_free (symlink_target);
- }
- else if (g_str_has_suffix (definition_file, ".desktop"))
- {
- blacklist_add_core(definition_file, definition_file);
- }
- else if (g_file_get_contents (definition_file, &contents, NULL, NULL))
- {
- gchar *trimmed = pango_trim_string (contents);
- blacklist_add_core (trimmed, definition_file);
- g_free (trimmed);
- g_free (contents);
+ g_action_muxer_insert (action_muxer, id, app_section_get_actions (section));
+ g_signal_connect (section, "notify::actions",
+ G_CALLBACK (actions_changed), NULL);
+ g_signal_connect (section, "notify::draws-attention",
+ G_CALLBACK (draws_attention_changed), NULL);
+ g_signal_connect (section, "notify::uses-chat-status",
+ G_CALLBACK (uses_chat_status_changed), NULL);
+
+ /* TODO insert it at the right position (alphabetically by application name) */
+ menuitem = g_menu_item_new_section (NULL, app_section_get_menu (section));
+ g_menu_item_set_attribute (menuitem, "action-namespace", "s", id);
+ g_menu_insert_item (menu, g_menu_model_get_n_items (G_MENU_MODEL (menu)) -1, menuitem);
+ g_object_unref (menuitem);
}
- else
- g_warning ("invalid blacklist entry: %s", definition_file);
- return FALSE;
+ g_free (id);
+ g_object_unref (appinfo);
+ return section;
}
-/* This takes a desktop file and tries to add it to the black
- list for applications in the messaging menu. If it can,
- then the launcher item gets marked as eclipsed and hidden
- from the user. */
static void
-blacklist_add_core (gchar * desktop, gchar * definition)
+remove_application (const char *desktop_id)
{
- gchar *basename = g_path_get_basename(desktop);
-
- /* Check for conflicts */
- gpointer data = g_hash_table_lookup(blacklist, basename);
- if (data != NULL) {
- gchar * oldfile = (gchar *)data;
- if (!g_strcmp0(oldfile, definition)) {
- g_warning("Already added file '%s'", oldfile);
- } else {
- g_warning("Already have desktop file '%s' in blacklist file '%s' not adding from '%s'", desktop, oldfile, definition);
- }
-
- g_free(basename);
- return;
- }
+ GDesktopAppInfo *appinfo;
+ gchar *id;
+ AppSection *section;
- /* Actually blacklist this thing */
- g_hash_table_insert(blacklist, g_strdup(basename), g_strdup(definition));
- g_debug("Adding Blacklist item '%s' for desktop '%s'", definition, desktop);
-
- /* Go through and eclipse folks */
- GList * launcher;
- for (launcher = launcherList; launcher != NULL; launcher = launcher->next) {
- launcherList_t * item = (launcherList_t *)launcher->data;
- gchar * item_basename = g_path_get_basename(launcher_menu_item_get_desktop(item->menuitem));
- if (!g_strcmp0(basename, item_basename)) {
- launcher_menu_item_set_eclipsed(item->menuitem, TRUE);
- dbusmenu_menuitem_property_set_bool(item->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- }
- g_free(item_basename);
+ appinfo = g_desktop_app_info_new (desktop_id);
+ if (!appinfo) {
+ g_warning ("could not remove '%s', there's no desktop file with that id", desktop_id);
+ return;
}
- check_hidden();
- /* Shouldn't need a resort here as hiding shouldn't cause things to
- move other than this item disappearing. */
+ id = g_app_info_get_simple_id (G_APP_INFO (appinfo));
- g_free(basename);
- return;
-}
+ section = g_hash_table_lookup (applications, id);
+ if (section) {
+ int pos = g_menu_find_section (menu, app_section_get_menu (section));
+ if (pos >= 0)
+ g_menu_remove (menu, pos);
+ g_action_muxer_remove (action_muxer, id);
-/* Remove a black list item based on the definition file
- and uneclipse those launchers blocked by it. */
-static gboolean
-blacklist_remove (gpointer data)
-{
- gchar * definition_file = (gchar *)data;
- g_debug("Removing: %s", definition_file);
-
- GHashTableIter iter;
- gpointer key, value;
- gboolean found = FALSE;
-
- g_hash_table_iter_init(&iter, blacklist);
- while (g_hash_table_iter_next(&iter, &key, &value)) {
- if (!g_strcmp0((gchar *)value, definition_file)) {
- found = TRUE;
- break;
- }
+ g_signal_handlers_disconnect_by_func (section, actions_changed, NULL);
+ g_signal_handlers_disconnect_by_func (section, draws_attention_changed, NULL);
+ g_signal_handlers_disconnect_by_func (section, uses_chat_status_changed, NULL);
}
-
- if (!found) {
- g_debug("\tNot found!");
- return FALSE;
+ else {
+ g_warning ("could not remove '%s', it's not registered", desktop_id);
}
-
- GList * launcheritem;
- for (launcheritem = launcherList; launcheritem != NULL; launcheritem = launcheritem->next) {
- launcherList_t * li = (launcherList_t *)launcheritem->data;
- if (!g_strcmp0(launcher_menu_item_get_desktop(li->menuitem), (gchar *)key)) {
- GList * serveritem;
- for (serveritem = serverList; serveritem != NULL; serveritem = serveritem->next) {
- serverList_t * si = (serverList_t *)serveritem->data;
- if (!g_strcmp0(app_menu_item_get_desktop(si->menuitem), (gchar *)key)) {
- break;
- }
- }
- if (serveritem == NULL) {
- launcher_menu_item_set_eclipsed(li->menuitem, FALSE);
- dbusmenu_menuitem_property_set_bool(li->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
- }
- }
- }
-
- if (!g_hash_table_remove(blacklist, key)) {
- g_warning("Unable to remove '%s' with value '%s'", definition_file, (gchar *)key);
- }
-
- check_hidden();
- resort_menu(root_menuitem);
-
- return FALSE;
+
+ g_hash_table_remove (applications, id);
+ g_free (id);
+ g_object_unref (appinfo);
}
-/* Check to see if a particular desktop file is
- in the blacklist. */
+/* This function turns a specific desktop id into a menu
+ item and registers it appropriately with everyone */
static gboolean
-blacklist_check (const gchar * desktop_file)
+build_launcher (gpointer data)
{
- gchar *basename = g_path_get_basename(desktop_file);
- gboolean found;
+ gchar *desktop_id = data;
- g_debug("Checking blacklist for: %s", basename);
+ add_application (desktop_id);
- if (blacklist && g_hash_table_lookup(blacklist, basename)) {
- g_debug("\tFound!");
- found = TRUE;
- }
- else
- found = FALSE;
-
- g_free(basename);
- return found;
-}
-
-/* A callback everytime the blacklist directory changes
- in some way. It needs to handle that. */
-static void
-blacklist_dir_changed (GFileMonitor * monitor, GFile * file, GFile * other_file, GFileMonitorEvent event_type, gpointer user_data)
-{
- g_debug("Blacklist directory changed!");
-
- switch (event_type) {
- case G_FILE_MONITOR_EVENT_DELETED: {
- gchar * path = g_file_get_path(file);
- g_debug("\tDelete: %s", path);
- g_idle_add(blacklist_remove, path);
- break;
- }
- case G_FILE_MONITOR_EVENT_CREATED: {
- gchar * path = g_file_get_path(file);
- g_debug("\tCreate: %s", path);
- g_idle_add(blacklist_add, path);
- break;
- }
- default:
- break;
- }
-
- return;
+ g_free (desktop_id);
+ return FALSE;
}
-/*
- * More code
- */
-
-/* Goes through all the servers and sees if any of them
- want attention. If they do, then well we'll give it
- to them. If they don't, let's not bother the user
- any, shall we? */
-static void
-check_attention (void)
+/* This function goes through all the launchers that we're
+ supposed to be grabbing and decides to show turn them
+ into menu items or not. It doens't do the work, but it
+ makes the decision. */
+static gboolean
+build_launchers (gpointer data)
{
- GList * pointer;
- for (pointer = serverList; pointer != NULL; pointer = g_list_next(pointer)) {
- serverList_t * slt = (serverList_t *)pointer->data;
- if (slt->attention) {
- message_service_dbus_set_attention(dbus_interface, TRUE);
- return;
- }
- }
- message_service_dbus_set_attention(dbus_interface, FALSE);
- return;
-}
+ gchar **applications = g_settings_get_strv (settings, "applications");
+ gchar **app;
-/* This checks a server listing to see if it should
- have attention. It can get attention through it's
- count or by having an indicator that is requestion
- attention. */
-static void
-server_attention (serverList_t * slt)
-{
- /* Count, easy yes and out. */
- if (slt->count > 0) {
- slt->attention = TRUE;
- return;
- }
+ g_return_val_if_fail (applications != NULL, FALSE);
- /* Check to see if any of the indicators want attention */
- GList * pointer;
- for (pointer = slt->imList; pointer != NULL; pointer = g_list_next(pointer)) {
- imList_t * ilt = (imList_t *)pointer->data;
- if (im_menu_item_get_attention(IM_MENU_ITEM(ilt->menuitem))) {
- slt->attention = TRUE;
- return;
- }
+ for (app = applications; *app; app++)
+ {
+ g_idle_add(build_launcher, g_strdup (*app));
}
- /* Nope, no one */
- slt->attention = FALSE;
- return;
+ g_strfreev (applications);
+ return FALSE;
}
-/* A new server has been created on the indicate bus.
- We need to check to see if we like it. And build
- structures for it if so. */
static void
-server_added (IndicateListener * listener, IndicateListenerServer * server, gchar * type, gpointer data)
-{
- g_debug("Server Added '%s' of type '%s'.", INDICATE_LISTENER_SERVER_DBUS_NAME(server), type);
- if (type == NULL) {
- return;
- }
-
- if (type[0] == '\0') {
- return;
- }
-
- if (strncmp(type, "message", strlen("message"))) {
- g_debug("\tServer type '%s' is not a message based type.", type);
- return;
- }
-
- DbusmenuMenuitem * menushell = DBUSMENU_MENUITEM(data);
- if (menushell == NULL) {
- g_error("\tData in callback is not a menushell");
- return;
- }
-
- /* Build the Menu item */
- AppMenuItem * menuitem = app_menu_item_new(listener, server);
-
- /* Build a possible server structure */
- serverList_t * sl_item = g_new0(serverList_t, 1);
- sl_item->server = server;
- sl_item->menuitem = menuitem;
- sl_item->imList = NULL;
- sl_item->attention = FALSE;
- sl_item->count = 0;
-
- /* Incase we got an indicator first */
- GList * alreadythere = g_list_find_custom(serverList, sl_item, serverList_equal);
- if (alreadythere != NULL) {
- /* Use the one we already had */
- g_free(sl_item);
- sl_item = (serverList_t *)alreadythere->data;
- sl_item->menuitem = menuitem;
- serverList = g_list_sort(serverList, serverList_sort);
- } else {
- /* Insert the new one in the list */
- serverList = g_list_insert_sorted(serverList, sl_item, serverList_sort);
- }
-
- /* Build a separator */
- sl_item->separator = dbusmenu_menuitem_new();
- dbusmenu_menuitem_property_set(sl_item->separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
-
- /* Connect the signals up to the menu item */
- g_signal_connect(G_OBJECT(menuitem), APP_MENU_ITEM_SIGNAL_COUNT_CHANGED, G_CALLBACK(server_count_changed), sl_item);
- g_signal_connect(G_OBJECT(menuitem), APP_MENU_ITEM_SIGNAL_NAME_CHANGED, G_CALLBACK(server_name_changed), menushell);
- g_signal_connect(G_OBJECT(menuitem), APP_MENU_ITEM_SIGNAL_SHORTCUT_ADDED, G_CALLBACK(server_shortcut_added), menushell);
- g_signal_connect(G_OBJECT(menuitem), APP_MENU_ITEM_SIGNAL_SHORTCUT_REMOVED, G_CALLBACK(server_shortcut_removed), menushell);
-
- /* Put our new menu item in, with the separator behind it.
- resort_menu will take care of whether it should be hidden
- or not. */
- dbusmenu_menuitem_child_append(menushell, DBUSMENU_MENUITEM(menuitem));
-
- GList * shortcuts = app_menu_item_get_items(sl_item->menuitem);
- while (shortcuts != NULL) {
- DbusmenuMenuitem * mi = DBUSMENU_MENUITEM(shortcuts->data);
- g_debug("\tAdding shortcut: %s", dbusmenu_menuitem_property_get(mi, DBUSMENU_MENUITEM_PROP_LABEL));
- dbusmenu_menuitem_child_append(menushell, mi);
- shortcuts = g_list_next(shortcuts);
- }
-
- dbusmenu_menuitem_child_append(menushell, DBUSMENU_MENUITEM(sl_item->separator));
-
- resort_menu(menushell);
- check_hidden();
-
- return;
-}
-
-/* Server shortcut has been added */
-static void
-server_shortcut_added (AppMenuItem * appitem, DbusmenuMenuitem * mi, gpointer data)
-{
- g_debug("Application Shortcut added: %s", mi != NULL ? dbusmenu_menuitem_property_get(mi, DBUSMENU_MENUITEM_PROP_LABEL) : "none");
- DbusmenuMenuitem * shell = DBUSMENU_MENUITEM(data);
- if (mi != NULL) {
- dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_ICON_NAME, DBUSMENU_MENUITEM_ICON_NAME_BLANK);
- dbusmenu_menuitem_child_append(shell, mi);
- }
- resort_menu(shell);
- return;
-}
-
-/* Server shortcut has been removed */
-static void
-server_shortcut_removed (AppMenuItem * appitem, DbusmenuMenuitem * mi, gpointer data)
+service_shutdown (IndicatorService * service, gpointer user_data)
{
- g_debug("Application Shortcut removed: %s", mi != NULL ? dbusmenu_menuitem_property_get(mi, DBUSMENU_MENUITEM_PROP_LABEL) : "none");
- DbusmenuMenuitem * shell = DBUSMENU_MENUITEM(data);
- dbusmenu_menuitem_child_delete(shell, mi);
- return;
-}
+ GMainLoop *mainloop = user_data;
-/* The name of a server has changed, we probably
- need to reorder the menu to keep it in alphabetical
- order. This happens often after we read the destkop
- file from disk. */
-static void
-server_name_changed (AppMenuItem * appitem, gchar * name, gpointer data)
-{
- serverList = g_list_sort(serverList, serverList_sort);
- check_eclipses(appitem);
- resort_menu(DBUSMENU_MENUITEM(data));
- return;
+ g_warning("Shutting down service!");
+ g_main_loop_quit(mainloop);
}
-/* If the count on the server changes, we need to know
- whether that should be grabbing attention or not. If
- it is, we need to reevaluate whether the whole thing
- should be grabbing attention or not. */
static void
-server_count_changed (AppMenuItem * appitem, guint count, gpointer data)
+app_section_remove_attention (gpointer key,
+ gpointer value,
+ gpointer user_data)
{
- serverList_t * slt = (serverList_t *)data;
- slt->count = count;
-
- if (count == 0 && slt->attention) {
- /* Regen based on indicators if the count isn't going to cause it. */
- server_attention(slt);
- /* If we're dropping let's see if we're the last. */
- if (!slt->attention) {
- check_attention();
- }
- }
-
- if (count != 0 && !slt->attention) {
- slt->attention = TRUE;
- /* Let's tell everyone about us! */
- message_service_dbus_set_attention(dbus_interface, TRUE);
- }
-
- return;
+ AppSection *section = value;
+ app_section_clear_draws_attention (section);
}
-/* Respond to the IM entrie's time changing
- which results in it needing to resort the list
- and rebuild the menu to match. */
static void
-im_time_changed (ImMenuItem * imitem, glong seconds, gpointer data)
+clear_action_activate (GSimpleAction *simple,
+ GVariant *param,
+ gpointer user_data)
{
- serverList_t * sl = (serverList_t *)data;
- sl->imList = g_list_sort(sl->imList, imList_sort);
- resort_menu(root_menuitem);
- return;
+ g_hash_table_foreach (applications, app_section_remove_attention, NULL);
}
-/* The IM entrie's request for attention has changed
- so we need to pass that up the stack. */
static void
-im_attention_changed (ImMenuItem * imitem, gboolean requestit, gpointer data)
+radio_item_activate (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
{
- serverList_t * sl = (serverList_t *)data;
-
- if (requestit) {
- sl->attention = TRUE;
- message_service_dbus_set_attention(dbus_interface, TRUE);
- } else {
- server_attention(sl);
- if (!sl->attention) {
- check_attention();
- }
- }
-
- return;
+ g_action_change_state (G_ACTION (action), parameter);
}
-/* Run when a server is removed from the indicator bus. It figures
- out if we have it somewhere, and if so then we dump it out and
- clean up all of it's entries. */
-static void
-server_removed (IndicateListener * listener, IndicateListenerServer * server, gchar * type, gpointer data)
+static gboolean
+g_action_state_equal (GAction *action,
+ GVariant *value)
{
- /* Look for the server */
- g_debug("Removing server: %s", INDICATE_LISTENER_SERVER_DBUS_NAME(server));
- serverList_t slt = {0};
- slt.server = server;
- GList * lookup = g_list_find_custom(serverList, &slt, serverList_equal);
-
- /* If we don't have it, exit */
- if (lookup == NULL) {
- g_debug("\tUnable to find server: %s", INDICATE_LISTENER_SERVER_DBUS_NAME(server));
- return;
- }
-
- serverList_t * sltp = (serverList_t *)lookup->data;
-
- /* Removing indicators from this server */
- while (sltp->imList) {
- imList_t * imitem = (imList_t *)sltp->imList->data;
- indicator_removed(listener, server, imitem->indicator, data);
- }
+ GVariant *state;
+ gboolean eq;
- /* Remove from the server list */
- serverList = g_list_remove(serverList, sltp);
-
- /* Remove launchers this could be eclipsing */
- remove_eclipses(sltp->menuitem);
-
- /* If there is a menu item, let's get rid of it. */
- if (sltp->menuitem != NULL) {
- /* If there are shortcuts remove them */
- GList * shortcuts = app_menu_item_get_items(sltp->menuitem);
- while (shortcuts != NULL) {
- g_debug("\tRemoving shortcut: %s", dbusmenu_menuitem_property_get(DBUSMENU_MENUITEM(shortcuts->data), DBUSMENU_MENUITEM_PROP_LABEL));
- dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(shortcuts->data), DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- dbusmenu_menuitem_child_delete(DBUSMENU_MENUITEM(data), DBUSMENU_MENUITEM(shortcuts->data));
- shortcuts = g_list_next(shortcuts);
- }
-
- g_debug("\tRemoving item");
- dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(sltp->menuitem), DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- dbusmenu_menuitem_child_delete(DBUSMENU_MENUITEM(data), DBUSMENU_MENUITEM(sltp->menuitem));
- g_object_unref(G_OBJECT(sltp->menuitem));
- } else {
- g_debug("\tNo menuitem");
- }
-
- /* If there is a separator, let's get rid of it. */
- if (sltp->separator != NULL) {
- g_debug("\tRemoving separator");
- dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(sltp->separator), DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- dbusmenu_menuitem_child_delete(DBUSMENU_MENUITEM(data), DBUSMENU_MENUITEM(sltp->separator));
- g_object_unref(G_OBJECT(sltp->separator));
- } else {
- g_debug("\tNo separator");
- }
-
- if (sltp->attention) {
- /* Check to see if this was the server causing the menu item to
- be lit up. */
- check_attention();
- }
+ state = g_action_get_state (action);
+ g_return_val_if_fail (state != NULL, FALSE);
- g_free(sltp);
+ eq = g_variant_equal (state, value);
- check_hidden();
-
- return;
+ g_variant_unref (state);
+ return eq;
}
-typedef struct _menushell_location menushell_location_t;
-struct _menushell_location {
- const IndicateListenerServer * server;
- gint position;
- gboolean found;
-};
-
static void
-menushell_foreach_cb (DbusmenuMenuitem * data_mi, gpointer data_ms) {
- menushell_location_t * msl = (menushell_location_t *)data_ms;
-
- if (msl->found) return;
-
- if (!IS_APP_MENU_ITEM(data_mi)) {
- msl->position++;
- return;
- }
-
- AppMenuItem * appmenu = APP_MENU_ITEM(data_mi);
- if (!g_strcmp0(INDICATE_LISTENER_SERVER_DBUS_NAME((IndicateListenerServer*)msl->server), INDICATE_LISTENER_SERVER_DBUS_NAME(app_menu_item_get_server(appmenu)))) {
- msl->found = TRUE;
- /* Return a position at the end of our shortcuts */
- msl->position += g_list_length(app_menu_item_get_items(appmenu));
- } else {
- msl->position++;
- }
-
- return;
-}
-
-static void
-check_hidden (void)
+change_status_action (GSimpleAction *action,
+ GVariant *value,
+ gpointer user_data)
{
- g_debug("Checking Hidden...");
- gboolean hide = FALSE;
- if (launcherList_count() == 0) {
- g_debug("\tZero Launchers");
- /* If we don't have visible launchers we need to look more */
- if (g_list_length(serverList) == 0) {
- g_debug("\tZero Applications");
- hide = TRUE;
- }
- }
+ const gchar *status;
- message_service_dbus_set_icon(dbus_interface, hide);
- return;
-}
+ g_variant_get (value, "&s", &status);
-/* This function takes care of putting the menu in the right order.
- It basically it rebuilds the order by looking through all the
- applications and launchers and puts them in the right place. The
- menu functions will handle the cases where they don't move so this
- is a good way to ensure everything is right. */
-static void
-resort_menu (DbusmenuMenuitem * menushell)
-{
- guint position = 0;
- GList * serverentry;
- GList * launcherentry = launcherList;
-
- g_debug("Reordering Menu:");
-
- if (DBUSMENU_IS_MENUITEM(status_separator)) {
- position = dbusmenu_menuitem_get_position(status_separator, root_menuitem) + 1;
- g_debug("\tPriming with location of status separator: %d", position);
- }
+ g_return_if_fail (g_str_equal (status, "available") ||
+ g_str_equal (status, "away")||
+ g_str_equal (status, "busy") ||
+ g_str_equal (status, "invisible") ||
+ g_str_equal (status, "offline"));
- for (serverentry = serverList; serverentry != NULL; serverentry = serverentry->next) {
- serverList_t * si = (serverList_t *)serverentry->data;
-
- /* Looking to see if there are any launchers we need to insert
- into the menu structure. We put as many as we need to. */
- if (launcherentry != NULL) {
- launcherList_t * li = (launcherList_t *)launcherentry->data;
- while (launcherentry != NULL && g_strcmp0(launcher_menu_item_get_name(li->menuitem), app_menu_item_get_name(si->menuitem)) < 0) {
- /* Putting the launcher item in */
- g_debug("\tMoving launcher '%s' to position %d", launcher_menu_item_get_name(li->menuitem), position);
- dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(li->menuitem), position);
- position++;
-
- /* Inserting the shortcuts from the launcher */
- GList * shortcuts = launcher_menu_item_get_items(li->menuitem);
- while (shortcuts != NULL) {
- g_debug("\t\tMoving shortcut to position %d", position);
- dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(shortcuts->data), position);
- position++;
- shortcuts = g_list_next(shortcuts);
- }
-
- /* Putting the launcher separator in */
- g_debug("\tMoving launcher separator to position %d", position);
- dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(li->separator), position);
- if (!launcher_menu_item_get_eclipsed(li->menuitem)) {
- /* Only clear the visiblity if we're not eclipsed */
- dbusmenu_menuitem_property_set_bool(li->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
- }
- position++;
-
- launcherentry = launcherentry->next;
- if (launcherentry != NULL) {
- li = (launcherList_t *)launcherentry->data;
- }
- }
- }
-
- /* Putting the app menu item in */
- if (si->menuitem != NULL) {
- g_debug("\tMoving app %s to position %d", INDICATE_LISTENER_SERVER_DBUS_NAME(si->server), position);
- dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(si->menuitem), position);
- position++;
-
- /* Inserting the shortcuts from the launcher */
- GList * shortcuts = app_menu_item_get_items(si->menuitem);
- while (shortcuts != NULL) {
- g_debug("\t\tMoving shortcut to position %d", position);
- dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(shortcuts->data), position);
- position++;
- shortcuts = g_list_next(shortcuts);
- }
- }
-
- /* Putting all the indicators that are related to this application
- after it. */
- GList * imentry;
- for (imentry = si->imList; imentry != NULL; imentry = imentry->next) {
- imList_t * imi = (imList_t *)imentry->data;
-
- if (imi->menuitem != NULL) {
- g_debug("\tMoving indicator on %s id %d to position %d", INDICATE_LISTENER_SERVER_DBUS_NAME(imi->server), INDICATE_LISTENER_INDICATOR_ID(imi->indicator), position);
-
- if (si->menuitem == NULL || !dbusmenu_menuitem_property_get_bool(DBUSMENU_MENUITEM(si->menuitem), DBUSMENU_MENUITEM_PROP_VISIBLE)) {
- dbusmenu_menuitem_property_set_bool(imi->menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- } else {
- dbusmenu_menuitem_property_set_bool(imi->menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
- }
-
- dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(imi->menuitem), position);
- position++;
- }
- }
-
- /* Lastly putting the separator in */
- if (si->separator != NULL) {
- g_debug("\tMoving app %s separator to position %d", INDICATE_LISTENER_SERVER_DBUS_NAME(si->server), position);
-
- if (si->menuitem == NULL || !dbusmenu_menuitem_property_get_bool(DBUSMENU_MENUITEM(si->menuitem), DBUSMENU_MENUITEM_PROP_VISIBLE)) {
- dbusmenu_menuitem_property_set_bool(si->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- /* Note, this isn't the last if we can't see it */
- } else {
- dbusmenu_menuitem_property_set_bool(si->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
- }
-
- dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(si->separator), position);
- position++;
- }
+ if (!g_action_state_equal (G_ACTION (action), value)) {
+ g_message ("%s", status);
+ g_simple_action_set_state (action, value);
+ indicator_messages_service_emit_status_changed (messages_service, status);
}
-
- /* Put any leftover launchers in at the end of the list. */
- while (launcherentry != NULL) {
- launcherList_t * li = (launcherList_t *)launcherentry->data;
-
- /* Putting the launcher in */
- g_debug("\tMoving launcher '%s' to position %d", launcher_menu_item_get_name(li->menuitem), position);
- dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(li->menuitem), position);
- position++;
-
- /* Inserting the shortcuts from the launcher */
- GList * shortcuts = launcher_menu_item_get_items(li->menuitem);
- while (shortcuts != NULL) {
- g_debug("\t\tMoving shortcut to position %d", position);
- dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(shortcuts->data), position);
- position++;
- shortcuts = g_list_next(shortcuts);
- }
-
- /* Putting the launcher separator in */
- g_debug("\tMoving launcher separator to position %d", position);
- dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(li->separator), position);
- if (!launcher_menu_item_get_eclipsed(li->menuitem)) {
- /* Only clear the visiblity if we're not eclipsed */
- dbusmenu_menuitem_property_set_bool(li->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
- }
- position++;
-
- launcherentry = launcherentry->next;
- }
-
- if (clear_attention != NULL) {
- dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), clear_attention, position);
- position++; /* Not needed, but reduce bugs on code tacked on here, compiler will remove */
- }
-
- return;
}
-/* Responding to a new indicator showing up on the bus. We
- need to create a menuitem for it and start populating the
- internal structures to track it. */
static void
-indicator_added (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gpointer data)
-{
- DbusmenuMenuitem * menushell = DBUSMENU_MENUITEM(data);
- if (menushell == NULL) {
- g_error("Data in callback is not a menushell");
+register_application (IndicatorMessagesService *service,
+ GDBusMethodInvocation *invocation,
+ const gchar *desktop_id,
+ const gchar *menu_path,
+ gpointer user_data)
+{
+ AppSection *section;
+ GDBusConnection *bus;
+ const gchar *sender;
+
+ section = add_application (desktop_id);
+ if (!section)
return;
- }
- imList_t * listItem = g_new0(imList_t, 1);
- listItem->server = server;
- listItem->indicator = indicator;
-
- /* Building the IM Menu Item which is a subclass
- of DBus Menuitem */
- ImMenuItem * menuitem = im_menu_item_new(listener, server, indicator);
- listItem->menuitem = DBUSMENU_MENUITEM(menuitem);
-
- /* Looking for a server entry to attach this indicator
- to. If we can't find one then we have to build one
- and attach the indicator to it. */
- serverList_t sl_item_local = {0};
- serverList_t * sl_item = NULL;
- sl_item_local.server = server;
- GList * serverentry = g_list_find_custom(serverList, &sl_item_local, serverList_equal);
-
- if (serverentry == NULL) {
- /* This sucks, we got an indicator before the server. I guess
- that's the joy of being asynchronous */
- sl_item = g_new0(serverList_t, 1);
- sl_item->server = server;
- sl_item->menuitem = NULL;
- sl_item->imList = NULL;
- sl_item->attention = FALSE;
- sl_item->count = 0;
- sl_item->separator = NULL;
-
- serverList = g_list_insert_sorted(serverList, sl_item, serverList_sort);
- } else {
- sl_item = (serverList_t *)serverentry->data;
- }
+ bus = g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (service));
+ sender = g_dbus_method_invocation_get_sender (invocation);
- /* Added a this entry into the IM list */
- sl_item->imList = g_list_insert_sorted(sl_item->imList, listItem, imList_sort);
- listItem->timechange_cb = g_signal_connect(G_OBJECT(menuitem), IM_MENU_ITEM_SIGNAL_TIME_CHANGED, G_CALLBACK(im_time_changed), sl_item);
- listItem->attentionchange_cb = g_signal_connect(G_OBJECT(menuitem), IM_MENU_ITEM_SIGNAL_ATTENTION_CHANGED, G_CALLBACK(im_attention_changed), sl_item);
-
- /* Check the length of the list. If we've got more inidactors
- than we allow. Well. Someone's gotta pay. Sorry. I didn't
- want to do this, but you did it to yourself. */
- if (g_list_length(sl_item->imList) > MAX_NUMBER_OF_INDICATORS) {
- GList * indicatoritem;
- gint count;
- for (indicatoritem = sl_item->imList, count = 0; indicatoritem != NULL; indicatoritem = g_list_next(indicatoritem), count++) {
- imList_t * im = (imList_t *)indicatoritem->data;
- im_menu_item_show(IM_MENU_ITEM(im->menuitem), count < MAX_NUMBER_OF_INDICATORS);
- }
- }
+ app_section_set_object_path (section, bus, sender, menu_path);
+ g_settings_strv_append_unique (settings, "applications", desktop_id);
- /* Placing the item into the shell. Look to see if
- we can find our server and slip in there. Otherwise
- we'll just append. */
- menushell_location_t msl;
- msl.found = FALSE;
- msl.position = 0;
- msl.server = server;
-
- dbusmenu_menuitem_foreach(DBUSMENU_MENUITEM(menushell), menushell_foreach_cb, &msl);
- if (msl.found) {
- dbusmenu_menuitem_child_add_position(menushell, DBUSMENU_MENUITEM(menuitem), msl.position);
- } else {
- g_warning("Unable to find server menu item");
- dbusmenu_menuitem_child_append(menushell, DBUSMENU_MENUITEM(menuitem));
- resort_menu (root_menuitem);
- }
-
- return;
+ indicator_messages_service_complete_register_application (service, invocation);
}
-/* Process and indicator getting removed from the system. We
- first need to ensure that it's one of ours and figure out
- where we put it. When we find all that out we can go through
- the process of removing the effect it had on the system. */
static void
-indicator_removed (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gpointer data)
+unregister_application (IndicatorMessagesService *service,
+ GDBusMethodInvocation *invocation,
+ const gchar *desktop_id,
+ gpointer user_data)
{
- g_debug("Removing %s %d", INDICATE_LISTENER_SERVER_DBUS_NAME(server), INDICATE_LISTENER_INDICATOR_ID(indicator));
-
- gboolean removed = FALSE;
+ remove_application (desktop_id);
+ g_settings_strv_remove (settings, "applications", desktop_id);
- /* Find the server that was related to this item */
- serverList_t sl_item_local = {0};
- serverList_t * sl_item = NULL;
- sl_item_local.server = server;
- GList * serverentry = g_list_find_custom(serverList, &sl_item_local, serverList_equal);
- if (serverentry == NULL) {
- /* We didn't care about that server */
- return;
- }
- sl_item = (serverList_t *)serverentry->data;
-
- /* Look in the IM Hash Table */
- imList_t listData = {0};
- listData.server = server;
- listData.indicator = indicator;
-
- GList * listItem = g_list_find_custom(sl_item->imList, &listData, imList_equal);
- DbusmenuMenuitem * menuitem = NULL;
- imList_t * ilt = NULL;
- if (listItem != NULL) {
- ilt = (imList_t *)listItem->data;
- menuitem = ilt->menuitem;
- }
-
- /* If we found a menu item and an imList_t item then
- we can go ahead and remove it. Otherwise we can
- skip this and exit. */
- if (!removed && menuitem != NULL) {
- sl_item->imList = g_list_remove(sl_item->imList, ilt);
- g_signal_handler_disconnect(menuitem, ilt->timechange_cb);
- g_signal_handler_disconnect(menuitem, ilt->attentionchange_cb);
- g_free(ilt);
-
- if (im_menu_item_get_attention(IM_MENU_ITEM(menuitem)) && im_menu_item_shown(IM_MENU_ITEM(menuitem))) {
- /* If the removed indicator menu item was asking for
- attention we need to see if this server should still
- be asking for attention. */
- server_attention(sl_item);
- /* If the server is no longer asking for attention then
- we need to check if the whole system should be. */
- if (!sl_item->attention) {
- check_attention();
- }
- }
-
- if (im_menu_item_shown(IM_MENU_ITEM(menuitem)) && g_list_length(sl_item->imList) >= MAX_NUMBER_OF_INDICATORS) {
- /* In this case we need to show a different indicator
- becasue a shown one has left. But we're going to be
- easy and set all the values. */
- GList * indicatoritem;
- gint count;
- for (indicatoritem = sl_item->imList, count = 0; indicatoritem != NULL; indicatoritem = g_list_next(indicatoritem), count++) {
- imList_t * im = (imList_t *)indicatoritem->data;
- im_menu_item_show(IM_MENU_ITEM(im->menuitem), count < MAX_NUMBER_OF_INDICATORS);
- }
- }
-
- /* Hide the item immediately, and then remove it
- which might take a little longer. */
- dbusmenu_menuitem_property_set_bool(menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- dbusmenu_menuitem_child_delete(DBUSMENU_MENUITEM(data), menuitem);
- removed = TRUE;
- }
-
- if (!removed) {
- g_warning("We were asked to remove %s %d but we didn't.", INDICATE_LISTENER_SERVER_DBUS_NAME(server), INDICATE_LISTENER_INDICATOR_ID(indicator));
- }
-
- return;
+ indicator_messages_service_complete_unregister_application (service, invocation);
}
static void
-app_dir_changed (GFileMonitor * monitor, GFile * file, GFile * other_file, GFileMonitorEvent event_type, gpointer user_data)
+set_status (IndicatorMessagesService *service,
+ GDBusMethodInvocation *invocation,
+ const gchar *status_str,
+ gpointer user_data)
{
- gchar * directory = (gchar *)user_data;
- g_debug("Application directory changed: %s", directory);
-
- switch (event_type) {
- case G_FILE_MONITOR_EVENT_DELETED: {
- gchar * path = g_file_get_path(file);
- g_debug("\tDelete: %s", path);
- g_idle_add(destroy_launcher, path);
- break;
- }
- case G_FILE_MONITOR_EVENT_CREATED: {
- gchar * path = g_file_get_path(file);
- g_debug("\tCreate: %s", path);
- if (g_str_has_suffix(path, "keyfile")) {
- g_idle_add(build_launcher_keyfile, path);
- } else {
- g_idle_add(build_launcher, path);
- }
- break;
- }
- default:
- break;
- }
+ GAction *status;
- return;
-}
+ status = g_simple_action_group_lookup (actions, "status");
+ g_return_if_fail (status != NULL);
-/* Check to see if a new desktop file causes
- any of the launchers to be eclipsed by a running
- process */
-static void
-check_eclipses (AppMenuItem * ai)
-{
- g_debug("Checking eclipsing");
- const gchar * aidesktop = app_menu_item_get_desktop(ai);
- if (aidesktop == NULL) return;
- g_debug("\tApp desktop: %s", aidesktop);
-
- GList * llitem;
- for (llitem = launcherList; llitem != NULL; llitem = llitem->next) {
- launcherList_t * ll = (launcherList_t *)llitem->data;
- const gchar * lidesktop = launcher_menu_item_get_desktop(ll->menuitem);
- g_debug("\tLauncher desktop: %s", lidesktop);
-
- if (!g_strcmp0(aidesktop, lidesktop)) {
- launcher_menu_item_set_eclipsed(ll->menuitem, TRUE);
- dbusmenu_menuitem_property_set_bool(ll->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- break;
- }
- }
+ g_action_change_state (status, g_variant_new_string (status_str));
- return;
+ indicator_messages_service_complete_set_status (service, invocation);
}
-/* Remove any eclipses that might have been caused
- by this app item that is now retiring */
-static void
-remove_eclipses (AppMenuItem * ai)
+static GSimpleActionGroup *
+create_action_group (void)
{
- const gchar * aidesktop = app_menu_item_get_desktop(ai);
- if (aidesktop == NULL) return;
-
- if (blacklist_check(aidesktop)) return;
-
- GList * llitem;
- for (llitem = launcherList; llitem != NULL; llitem = llitem->next) {
- launcherList_t * ll = (launcherList_t *)llitem->data;
- const gchar * lidesktop = launcher_menu_item_get_desktop(ll->menuitem);
-
- if (!g_strcmp0(aidesktop, lidesktop)) {
- launcher_menu_item_set_eclipsed(ll->menuitem, FALSE);
- dbusmenu_menuitem_property_set_bool(ll->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
- break;
- }
- }
+ GSimpleActionGroup *actions;
+ GSimpleAction *messages;
+ GSimpleAction *clear;
+ GSimpleAction *status;
- return;
-}
-
-/* Remove a launcher from the system. We need to figure
- out what it's up to! */
-static gboolean
-destroy_launcher (gpointer data)
-{
- gchar * appdirentry = (gchar *)data;
-
- GList * listitem;
- GList * direntry;
- launcherList_t * li;
- gchar * appdir;
-
- for (listitem = launcherList; listitem != NULL; listitem = listitem->next) {
- li = (launcherList_t *)listitem->data;
- for (direntry = li->appdiritems; direntry != NULL; direntry = direntry->next) {
- appdir = (gchar *)direntry->data;
- if (!g_strcmp0(appdir, appdirentry)) {
- break;
- }
- }
-
- if (direntry != NULL) {
- break;
- }
- }
+ actions = g_simple_action_group_new ();
- if (listitem == NULL) {
- g_warning("Removed '%s' by the way of it not seeming to exist anywhere.", appdirentry);
- return FALSE;
- }
+ /* state of the messages action mirrors "draws-attention" */
+ messages = g_simple_action_new_stateful ("messages", G_VARIANT_TYPE ("b"),
+ g_variant_new_boolean (FALSE));
- if (g_list_length(li->appdiritems) > 1) {
- /* Just remove this item, and we can move on */
- g_debug("Just removing file entry: %s", appdir);
- li->appdiritems = g_list_remove(li->appdiritems, appdir);
- g_free(appdir);
- return FALSE;
- }
+ status = g_simple_action_new_stateful ("status", G_VARIANT_TYPE ("s"),
+ g_variant_new ("s", "offline"));
+ g_signal_connect (status, "activate", G_CALLBACK (radio_item_activate), NULL);
+ g_signal_connect (status, "change-state", G_CALLBACK (change_status_action), NULL);
- /* Full Destroy */
- g_free(appdir);
- g_list_free(li->appdiritems);
-
- if (li->menuitem != NULL) {
- /* If there are shortcuts remove them */
- GList * shortcuts = launcher_menu_item_get_items(li->menuitem);
- while (shortcuts != NULL) {
- dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(shortcuts->data), DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- dbusmenu_menuitem_child_delete(DBUSMENU_MENUITEM(data), DBUSMENU_MENUITEM(shortcuts->data));
- shortcuts = g_list_next(shortcuts);
- }
-
- dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(li->menuitem), DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- dbusmenu_menuitem_child_delete(root_menuitem, DBUSMENU_MENUITEM(li->menuitem));
- g_object_unref(G_OBJECT(li->menuitem));
- li->menuitem = NULL;
- }
+ clear = g_simple_action_new ("clear", NULL);
+ g_simple_action_set_enabled (clear, FALSE);
+ g_signal_connect (clear, "activate", G_CALLBACK (clear_action_activate), NULL);
- launcherList = g_list_remove(launcherList, li);
- g_free(li);
+ g_simple_action_group_insert (actions, G_ACTION (messages));
+ g_simple_action_group_insert (actions, G_ACTION (status));
+ g_simple_action_group_insert (actions, G_ACTION (clear));
- return FALSE;
+ return actions;
}
-/* This function turns a specific file into a menu
- item and registers it appropriately with everyone */
-static gboolean
-build_launcher (gpointer data)
+static GMenuModel *
+create_status_section (void)
{
- /* Read the file get the data */
- gchar * path = (gchar *)data;
- g_debug("\tpath: %s", path);
- gchar * desktop = NULL;
-
- g_file_get_contents(path, &desktop, NULL, NULL);
-
- if (desktop == NULL) {
- g_free(path);
- return FALSE;
- }
+ GMenu *menu;
- gchar * trimdesktop = pango_trim_string(desktop);
- g_free(desktop);
- g_debug("\tcontents: %s", trimdesktop);
+ menu = g_menu_new ();
+ g_menu_append_with_icon_name (menu, _("Available"), "user-available", "status::available");
+ g_menu_append_with_icon_name (menu, _("Away"), "user-away", "status::away");
+ g_menu_append_with_icon_name (menu, _("Busy"), "user-busy", "status::busy");
+ g_menu_append_with_icon_name (menu, _("Invisible"), "user-invisible", "status::invisible");
+ g_menu_append_with_icon_name (menu, _("Offline"), "user-offline", "status::offline");
- build_launcher_core(trimdesktop);
- g_free(trimdesktop);
- g_free(path);
- return FALSE;
-}
-
-/* Use a key file to find the desktop file. */
-static gboolean
-build_launcher_keyfile (gpointer data)
-{
- gchar * path = (gchar *)data;
- gchar * desktop = desktop_file_from_keyfile (path);
- if (desktop != NULL) {
- build_launcher_core(desktop);
- g_free(desktop);
- }
- g_free(path);
- return FALSE;
+ return G_MENU_MODEL (menu);
}
-/* The core action of dealing with a desktop file that should
- be a launcher */
static void
-build_launcher_core (const gchar * desktop)
+got_bus (GObject *object,
+ GAsyncResult * res,
+ gpointer user_data)
{
- /* Check to see if we already have a launcher */
- GList * listitem;
- for (listitem = launcherList; listitem != NULL; listitem = listitem->next) {
- launcherList_t * li = (launcherList_t *)listitem->data;
- if (!g_strcmp0(launcher_menu_item_get_desktop(li->menuitem), desktop)) {
- break;
- }
- }
-
- if (listitem == NULL) {
- /* If not */
- /* Build the item */
- launcherList_t * ll = g_new0(launcherList_t, 1);
- ll->menuitem = launcher_menu_item_new(desktop);
- ll->appdiritems = g_list_append(NULL, g_strdup(desktop));
-
- /* Build a separator */
- ll->separator = dbusmenu_menuitem_new();
- dbusmenu_menuitem_property_set(ll->separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
-
- /* Add it to the list */
- launcherList = g_list_insert_sorted(launcherList, ll, launcherList_sort);
-
- /* Add it to the menu */
- dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(ll->menuitem), DBUSMENU_MENUITEM_PROP_TYPE, APPLICATION_MENUITEM_TYPE);
- dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(ll->menuitem));
- GList * shortcuts = launcher_menu_item_get_items(ll->menuitem);
- while (shortcuts != NULL) {
- dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(shortcuts->data));
- shortcuts = g_list_next(shortcuts);
- }
- dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(ll->separator));
-
- /* If we're in the black list or we've gotten eclipsed
- by something else, hide the item and the separator. */
- if (blacklist_check(launcher_menu_item_get_desktop(ll->menuitem)) ||
- launcher_menu_item_get_eclipsed(ll->menuitem)) {
- launcher_menu_item_set_eclipsed(ll->menuitem, TRUE);
- dbusmenu_menuitem_property_set_bool(ll->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- }
-
- /* Check to see if any of the current applications should
- be eclipsing us. */
- GList * server;
- for (server = serverList; server != NULL; server = g_list_next(server)) {
- serverList_t * slt = (serverList_t *)server->data;
- check_eclipses(slt->menuitem);
- }
-
- resort_menu(root_menuitem);
- check_hidden();
- } else {
- /* If so add ourselves */
- launcherList_t * ll = (launcherList_t *)listitem->data;
- ll->appdiritems = g_list_append(ll->appdiritems, g_strdup(desktop));
- }
-
- return;
-}
+ GDBusConnection *bus;
+ GError *error = NULL;
-/* This function goes through all the launchers that we're
- supposed to be grabbing and decides to show turn them
- into menu items or not. It doens't do the work, but it
- makes the decision. */
-static gboolean
-build_launchers (gpointer data)
-{
- gchar * directory = (gchar *)data;
-
- if (!g_file_test(directory, G_FILE_TEST_IS_DIR)) {
- return FALSE;
+ bus = g_bus_get_finish (res, &error);
+ if (!bus) {
+ g_warning ("unable to connect to the session bus: %s", error->message);
+ g_error_free (error);
+ return;
}
- GFile * filedir = g_file_new_for_path(directory);
- GFileMonitor * dirmon = g_file_monitor_directory(filedir, G_FILE_MONITOR_NONE, NULL, NULL);
- if (dirmon != NULL) {
- g_signal_connect(G_OBJECT(dirmon), "changed", G_CALLBACK(app_dir_changed), directory);
+ g_dbus_connection_export_action_group (bus, INDICATOR_MESSAGES_DBUS_OBJECT,
+ G_ACTION_GROUP (action_muxer), &error);
+ if (error) {
+ g_warning ("unable to export action group on dbus: %s", error->message);
+ g_error_free (error);
+ return;
}
- GError * error = NULL;
- GDir * dir = g_dir_open(directory, 0, &error);
- if (dir == NULL) {
- g_warning("Unable to open system apps directory: %s", error->message);
- g_error_free(error);
- return FALSE;
+ g_dbus_connection_export_menu_model (bus, INDICATOR_MESSAGES_DBUS_OBJECT,
+ G_MENU_MODEL (toplevel_menu), &error);
+ if (error) {
+ g_warning ("unable to export menu on dbus: %s", error->message);
+ g_error_free (error);
+ return;
}
- const gchar * filename = NULL;
- while ((filename = g_dir_read_name(dir)) != NULL) {
- g_debug("Found file: %s", filename);
- gchar * path = g_build_filename(directory, filename, NULL);
- if (g_str_has_suffix(path, "keyfile")) {
- g_idle_add(build_launcher_keyfile, path);
- } else {
- g_idle_add(build_launcher, path);
- }
+ g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (messages_service),
+ bus, INDICATOR_MESSAGES_DBUS_SERVICE_OBJECT,
+ &error);
+ if (error) {
+ g_warning ("unable to export messages service on dbus: %s", error->message);
+ g_error_free (error);
+ return;
}
- g_dir_close(dir);
- launcherList = g_list_sort(launcherList, launcherList_sort);
- return FALSE;
-}
-
-static void
-service_shutdown (IndicatorService * service, gpointer user_data)
-{
- g_warning("Shutting down service!");
- g_main_loop_quit(mainloop);
- return;
+ g_object_unref (bus);
}
-/* Respond to changing status by updating the icon that
- is on the panel */
-static void
-status_update_callback (void)
-{
- return;
-}
-
-/* The clear attention item has been clicked on, what to do? */
-static void
-clear_attention_activate (DbusmenuMenuitem * mi, guint timestamp, MessageServiceDbus * dbus)
-{
- message_service_dbus_set_attention(dbus, FALSE);
- return;
-}
-
-/* Handle an update of the active state to ensure that we're
- only enabled when we could do something. */
-static void
-clear_attention_handler (MessageServiceDbus * msd, gboolean attention, DbusmenuMenuitem * clearitem)
-{
- dbusmenu_menuitem_property_set_bool(clearitem, DBUSMENU_MENUITEM_PROP_ENABLED, attention);
- return;
-}
-
-/* Oh, if you don't know what main() is for
- we really shouldn't be talking. */
int
main (int argc, char ** argv)
{
+ GMainLoop * mainloop = NULL;
+ IndicatorService * service = NULL;
+ GMenuItem *header;
+ GIcon *icon;
+ gchar *iconstr;
+
/* Glib init */
g_type_init();
+ mainloop = g_main_loop_new (NULL, FALSE);
+
/* Create the Indicator Service interface */
service = indicator_service_new_version(INDICATOR_MESSAGES_DBUS_NAME, 1);
- g_signal_connect(service, INDICATOR_SERVICE_SIGNAL_SHUTDOWN, G_CALLBACK(service_shutdown), NULL);
+ g_signal_connect(service, INDICATOR_SERVICE_SIGNAL_SHUTDOWN, G_CALLBACK(service_shutdown), mainloop);
/* Setting up i18n and gettext. Apparently, we need
all of these. */
@@ -1533,58 +482,52 @@ main (int argc, char ** argv)
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
textdomain (GETTEXT_PACKAGE);
- /* Create the Seen DB */
- seen_db_init();
-
/* Bring up the service DBus interface */
- dbus_interface = message_service_dbus_new();
-
- /* Build the base menu */
- root_menuitem = dbusmenu_menuitem_new();
- DbusmenuServer * server = dbusmenu_server_new(INDICATOR_MESSAGES_DBUS_OBJECT);
- dbusmenu_server_set_root(server, root_menuitem);
-
- /* Add status items */
- GList * statusitems = status_items_build(&status_update_callback);
- while (statusitems != NULL) {
- dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(statusitems->data));
- statusitems = g_list_next(statusitems);
- }
- status_separator = dbusmenu_menuitem_new();
- dbusmenu_menuitem_property_set(status_separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
- dbusmenu_menuitem_child_append(root_menuitem, status_separator);
-
- /* Add in the clear attention item */
- clear_attention = dbusmenu_menuitem_new();
- dbusmenu_menuitem_property_set(clear_attention, DBUSMENU_MENUITEM_PROP_LABEL, _("Clear"));
- dbusmenu_menuitem_child_append(root_menuitem, clear_attention);
- g_signal_connect(G_OBJECT(dbus_interface), MESSAGE_SERVICE_DBUS_SIGNAL_ATTENTION_CHANGED, G_CALLBACK(clear_attention_handler), clear_attention);
- g_signal_connect(G_OBJECT(clear_attention), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(clear_attention_activate), dbus_interface);
-
- /* Start up the libindicate listener */
- listener = indicate_listener_ref_default();
- serverList = NULL;
-
- g_signal_connect(listener, INDICATE_LISTENER_SIGNAL_INDICATOR_ADDED, G_CALLBACK(indicator_added), root_menuitem);
- g_signal_connect(listener, INDICATE_LISTENER_SIGNAL_INDICATOR_REMOVED, G_CALLBACK(indicator_removed), root_menuitem);
- g_signal_connect(listener, INDICATE_LISTENER_SIGNAL_SERVER_ADDED, G_CALLBACK(server_added), root_menuitem);
- g_signal_connect(listener, INDICATE_LISTENER_SIGNAL_SERVER_REMOVED, G_CALLBACK(server_removed), root_menuitem);
-
- /* Find launchers by looking through the config directories
- in the idle loop */
- g_idle_add(blacklist_init, NULL);
- g_idle_add(build_launchers, SYSTEM_APPS_DIR);
- g_idle_add(build_launchers, SYSTEM_APPS_DIR_OLD);
- gchar * userdir = g_build_filename(g_get_user_config_dir(), USER_APPS_DIR, NULL);
- g_idle_add(build_launchers, userdir);
-
- /* Let's run a mainloop */
- mainloop = g_main_loop_new(NULL, FALSE);
+ messages_service = indicator_messages_service_skeleton_new ();
+
+ g_bus_get (G_BUS_TYPE_SESSION, NULL, got_bus, NULL);
+
+ actions = create_action_group ();
+
+ action_muxer = g_action_muxer_new ();
+ g_action_muxer_insert (action_muxer, NULL, G_ACTION_GROUP (actions));
+
+ g_signal_connect (messages_service, "handle-register-application",
+ G_CALLBACK (register_application), NULL);
+ g_signal_connect (messages_service, "handle-unregister-application",
+ G_CALLBACK (unregister_application), NULL);
+ g_signal_connect (messages_service, "handle-set-status",
+ G_CALLBACK (set_status), NULL);
+
+ menu = g_menu_new ();
+ chat_section = create_status_section ();
+ g_menu_append (menu, _("Clear"), "clear");
+
+ icon = g_themed_icon_new ("indicator-messages");
+ iconstr = g_icon_to_string (icon);
+
+ toplevel_menu = g_menu_new ();
+ header = g_menu_item_new (NULL, "messages");
+ g_menu_item_set_submenu (header, G_MENU_MODEL (menu));
+ g_menu_item_set_attribute (header, "x-canonical-icon", "s", iconstr);
+ g_menu_item_set_attribute (header, "x-canonical-accessible-description", "s", _("Messages"));
+ g_menu_append_item (toplevel_menu, header);
+ g_object_unref (header);
+
+ settings = g_settings_new ("com.canonical.indicator.messages");
+
+ applications = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+
+ g_idle_add(build_launchers, NULL);
+
g_main_loop_run(mainloop);
/* Clean up */
- status_items_cleanup();
- g_free(userdir);
-
+ g_free (iconstr);
+ g_object_unref (icon);
+ g_object_unref (messages_service);
+ g_object_unref (chat_section);
+ g_object_unref (settings);
+ g_hash_table_unref (applications);
return 0;
}