From 583033cb8dbf95d224bc9cc4bf4d4d097b7950f3 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Fri, 18 May 2012 23:26:54 +0200 Subject: Remove default applications This gets rid of the "Set Up " sections for Email, Chat, and Broadcast. Also, default apps don't get to override the icon and names anymore. Every app gets its real name and icon displayed. Overriding the icon with X-Ayatana-Messaging-Menu-Icon is still possible. --- test/Makefile.am | 3 --- 1 file changed, 3 deletions(-) (limited to 'test') diff --git a/test/Makefile.am b/test/Makefile.am index 1d28dc4..09bd861 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -39,8 +39,6 @@ lib_LTLIBRARIES = \ libindicator-messages-service.la libindicator_messages_service_la_HEADERS = \ - $(top_srcdir)/src/default-applications.h \ - $(top_srcdir)/src/messages-service-dbus.h \ $(top_srcdir)/src/gen-messages-service.xml.h \ $(top_srcdir)/src/im-menu-item.h \ $(top_srcdir)/src/app-menu-item.h \ @@ -51,7 +49,6 @@ libindicator_messages_service_la_HEADERS = \ $(top_srcdir)/src/status-items.h libindicator_messages_service_la_SOURCES = \ - $(top_srcdir)/src/default-applications.c \ $(top_srcdir)/src/messages-service.c \ $(top_srcdir)/src/messages-service-dbus.c \ $(top_srcdir)/src/gen-messages-service.xml.c \ -- cgit v1.2.3 From ab416588f88aa199193f234220f102788c0493c0 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Fri, 18 May 2012 23:41:22 +0200 Subject: Remove the seen db It was only really used to figure out whether one of the default apps was ever running, so that "Set up..." or the app name and actions would be shown in the menu. Since there are no default apps anymore, this is not needed either. --- src/Makefile.am | 2 - src/app-menu-item.c | 3 - src/launcher-menu-item.c | 33 ++++----- src/messages-service.c | 4 -- src/seen-db.c | 177 ----------------------------------------------- src/seen-db.h | 31 --------- test/Makefile.am | 2 - 7 files changed, 15 insertions(+), 237 deletions(-) delete mode 100644 src/seen-db.c delete mode 100644 src/seen-db.h (limited to 'test') diff --git a/src/Makefile.am b/src/Makefile.am index 0f923c7..8d48047 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -48,8 +48,6 @@ indicator_messages_service_SOURCES = \ app-menu-item.h \ launcher-menu-item.c \ launcher-menu-item.h \ - seen-db.c \ - seen-db.h \ dirs.h \ dbus-data.h \ \ diff --git a/src/app-menu-item.c b/src/app-menu-item.c index 3fb3ab8..f7b1469 100644 --- a/src/app-menu-item.c +++ b/src/app-menu-item.c @@ -30,7 +30,6 @@ with this program. If not, see . #include #include "app-menu-item.h" #include "dbus-data.h" -#include "seen-db.h" enum { COUNT_CHANGED, @@ -325,8 +324,6 @@ desktop_cb (IndicateListener * listener, IndicateListenerServer * server, const return; } - seen_db_add(value); - priv->appinfo = G_APP_INFO(g_desktop_app_info_new_from_filename(value)); g_return_if_fail(priv->appinfo != NULL); diff --git a/src/launcher-menu-item.c b/src/launcher-menu-item.c index 5e10da4..fd04f52 100644 --- a/src/launcher-menu-item.c +++ b/src/launcher-menu-item.c @@ -30,7 +30,6 @@ with this program. If not, see . #include #include "launcher-menu-item.h" #include "dbus-data.h" -#include "seen-db.h" enum { NAME_CHANGED, @@ -184,23 +183,21 @@ launcher_menu_item_new (const gchar * desktop_file) g_signal_connect(G_OBJECT(self), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(activate_cb), NULL); /* Start to build static shortcuts */ - if (seen_db_seen(desktop_file)) { - priv->ids = indicator_desktop_shortcuts_new(priv->desktop, "Messaging Menu"); - const gchar ** nicks = indicator_desktop_shortcuts_get_nicks(priv->ids); - gint i; - for (i = 0; nicks[i] != NULL; i++) { - DbusmenuMenuitem * mi = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set(mi, DBUSMENU_MENUITEM_PROP_TYPE, APPLICATION_MENUITEM_TYPE); - g_object_set_data(G_OBJECT(mi), NICK_DATA, (gpointer)nicks[i]); - - gchar *name = indicator_desktop_shortcuts_nick_get_name(priv->ids, nicks[i]); - dbusmenu_menuitem_property_set(mi, DBUSMENU_MENUITEM_PROP_LABEL, name); - g_free(name); - - g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(nick_activate_cb), self); - - priv->shortcuts = g_list_append(priv->shortcuts, mi); - } + priv->ids = indicator_desktop_shortcuts_new(priv->desktop, "Messaging Menu"); + const gchar ** nicks = indicator_desktop_shortcuts_get_nicks(priv->ids); + gint i; + for (i = 0; nicks[i] != NULL; i++) { + DbusmenuMenuitem * mi = dbusmenu_menuitem_new(); + dbusmenu_menuitem_property_set(mi, DBUSMENU_MENUITEM_PROP_TYPE, APPLICATION_MENUITEM_TYPE); + g_object_set_data(G_OBJECT(mi), NICK_DATA, (gpointer)nicks[i]); + + gchar *name = indicator_desktop_shortcuts_nick_get_name(priv->ids, nicks[i]); + dbusmenu_menuitem_property_set(mi, DBUSMENU_MENUITEM_PROP_LABEL, name); + g_free(name); + + g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(nick_activate_cb), self); + + priv->shortcuts = g_list_append(priv->shortcuts, mi); } /* Check to see if we should be eclipsed */ diff --git a/src/messages-service.c b/src/messages-service.c index 078cee3..2188ab0 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -39,7 +39,6 @@ with this program. If not, see . #include "dbus-data.h" #include "dirs.h" #include "messages-service-dbus.h" -#include "seen-db.h" #include "status-items.h" static IndicatorService * service = NULL; @@ -1533,9 +1532,6 @@ 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(); diff --git a/src/seen-db.c b/src/seen-db.c deleted file mode 100644 index 57765cc..0000000 --- a/src/seen-db.c +++ /dev/null @@ -1,177 +0,0 @@ -/* -A small database of which desktop files we've seen. - -Copyright 2010 Canonical Ltd. - -Authors: - Ted Gould - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program. If not, see . -*/ - -#include "seen-db.h" - -#define GROUP_NAME "Seen Database" -#define KEY_NAME "DesktopFiles" - -GHashTable * seendb = NULL; -gchar * filename = NULL; -gchar * dirname = NULL; -guint write_process = 0; - -/* Build the hashtable and then see if we have a keyfile that - we can get the history of desktop files we've seen. */ -void -seen_db_init(void) -{ - g_return_if_fail(seendb == NULL); - - seendb = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); - - /* Build the filename for the seen database. We're putting - it in the cache directory because it could get deleted and - it really wouldn't be a big deal. */ - if (dirname == NULL) { - dirname = g_build_filename(g_get_user_cache_dir(), "indicators", "messages", NULL); - } - if (filename == NULL) { - filename = g_build_filename(dirname, "seen-db.keyfile", NULL); - } - - if (g_file_test(filename, G_FILE_TEST_EXISTS)) { - GKeyFile * keyfile = g_key_file_new(); - - /* Load from file */ - if (!g_key_file_load_from_file(keyfile, filename, G_KEY_FILE_NONE, NULL)) { - g_key_file_free(keyfile); - keyfile = NULL; - } - - /* Check for keys */ - if (keyfile != NULL && !g_key_file_has_key(keyfile, GROUP_NAME, KEY_NAME, NULL)) { - g_warning("Seen DB '%s' does not have key '%s' in group '%s'", filename, KEY_NAME, GROUP_NAME); - g_key_file_free(keyfile); - keyfile = NULL; - } - - /* Grab them and put in DB */ - if (keyfile != NULL) { - gchar ** desktops = g_key_file_get_string_list(keyfile, GROUP_NAME, KEY_NAME, NULL, NULL); - gint i = 0; - - while (desktops[i] != NULL) { - g_hash_table_insert(seendb, - g_strdup(desktops[i]), - GINT_TO_POINTER(TRUE)); - i++; - } - - g_strfreev(desktops); - } - - /* Clean up our file */ - if (keyfile != NULL) { - g_key_file_free(keyfile); - } - } - - return; -} - -/* A function to write out the seen database after it's been - modified for a while. */ -static gboolean -write_seen_db (gpointer user_data) -{ - write_process = 0; - - /* Build up the key file */ - GKeyFile * keyfile = g_key_file_new(); - GArray * desktops = g_array_new(FALSE, FALSE, sizeof(gchar *)); - - /* Get the keys from the hashtable and make them - into an array */ - if (keyfile != NULL) { - GList * desktop_keys = g_hash_table_get_keys(seendb); - GList * head = NULL; - - for (head = desktop_keys; head != NULL; head = g_list_next(head)) { - g_array_append_val(desktops, head->data); - } - - g_list_free(desktop_keys); - } - - /* Use the array to dump the strings into the keyfile */ - g_key_file_set_string_list(keyfile, - GROUP_NAME, - KEY_NAME, - (const gchar * const *)desktops->data, - desktops->len); - g_array_free(desktops, TRUE); - - /* Dump the key file to string */ - gchar * keydump = NULL; - gsize keydumplen = 0; - keydump = g_key_file_to_data(keyfile, &keydumplen, NULL); - g_key_file_free(keyfile); - - /* Ensure the directory exists */ - if (g_mkdir_with_parents(dirname, 0700) != 0) { - g_warning("Unable to make directory: %s", dirname); - g_free(keydump); - return FALSE; - } - - /* Dump out the file */ - GError * error = NULL; - if (!g_file_set_contents(filename, keydump, keydumplen, &error)) { - g_warning("Unable to write out file '%s': %s", filename, error->message); - g_error_free(error); - } - - /* Clean up */ - g_free(keydump); - - return FALSE; -} - -/* Add a new desktop file to the seen database. Also sets up a timer - to do the write out. */ -void -seen_db_add (const gchar * desktop) -{ - /* If this is a new one, let's set up the timer. If - there's already one clear it. */ - if (!seen_db_seen(desktop)) { - if (write_process != 0) { - g_source_remove(write_process); - write_process = 0; - } - - write_process = g_timeout_add_seconds(60, write_seen_db, NULL); - } - - g_hash_table_insert(seendb, - g_strdup(desktop), - GINT_TO_POINTER(TRUE)); - - return; -} - -/* Checks to see if a desktop file has been seen. */ -gboolean -seen_db_seen (const gchar * desktop) -{ - return GPOINTER_TO_INT(g_hash_table_lookup(seendb, desktop)); -} diff --git a/src/seen-db.h b/src/seen-db.h deleted file mode 100644 index a998ff0..0000000 --- a/src/seen-db.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -A small database of which desktop files we've seen. - -Copyright 2010 Canonical Ltd. - -Authors: - Ted Gould - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program. If not, see . -*/ - -#ifndef SEEN_DB_H__ -#define SEEN_DB_H__ 1 - -#include - -void seen_db_init(void); -void seen_db_add (const gchar * desktop); -gboolean seen_db_seen (const gchar * desktop); - -#endif /* SEEN_DB_H__ */ diff --git a/test/Makefile.am b/test/Makefile.am index 09bd861..466de1e 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -43,7 +43,6 @@ libindicator_messages_service_la_HEADERS = \ $(top_srcdir)/src/im-menu-item.h \ $(top_srcdir)/src/app-menu-item.h \ $(top_srcdir)/src/launcher-menu-item.h \ - $(top_srcdir)/src/seen-db.h \ $(top_srcdir)/src/dirs.h \ $(top_srcdir)/src/dbus-data.h \ $(top_srcdir)/src/status-items.h @@ -55,7 +54,6 @@ libindicator_messages_service_la_SOURCES = \ $(top_srcdir)/src/im-menu-item.c \ $(top_srcdir)/src/app-menu-item.c \ $(top_srcdir)/src/launcher-menu-item.c \ - $(top_srcdir)/src/seen-db.c \ $(top_srcdir)/src/status-items.c libindicator_messages_service_ladir = \ -- cgit v1.2.3 From 14716e2d8d8bf7ccd8ba3ee2e9607a718bf2ff66 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 21 May 2012 16:45:58 +0200 Subject: Use a gsettings list for finding out which apps should appear in the menu Previously, this was handled by looking for .desktop files in various system and user directories. The messaging menu should not display any applications by default anymore, so a simple per-user gsettings list suffices. A neat side effect is that the hairy blacklist handling is not needed anymore, either. Small regression: apps are not configurable at runtime anymore (settings key is not listened to for changes). --- configure.ac | 2 + data/Makefile.am | 7 +- data/com.canonical.indicator.messages.gschema.xml | 12 + src/Makefile.am | 1 - src/dirs.h | 4 - src/messages-service.c | 506 +--------------------- test/Makefile.am | 1 - 7 files changed, 43 insertions(+), 490 deletions(-) create mode 100644 data/com.canonical.indicator.messages.gschema.xml delete mode 100644 src/dirs.h (limited to 'test') diff --git a/configure.ac b/configure.ac index ca879a1..148259d 100644 --- a/configure.ac +++ b/configure.ac @@ -57,6 +57,8 @@ PKG_CHECK_MODULES(APPLET, gtk+-3.0 >= $GTK_REQUIRED_VERSION AC_SUBST(APPLET_CFLAGS) AC_SUBST(APPLET_LIBS) +GLIB_GSETTINGS + ########################### # Status Provider Deps ########################### diff --git a/data/Makefile.am b/data/Makefile.am index 351601b..488ce05 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -6,6 +6,11 @@ dbus_services_DATA = indicator-messages.service %.service: %.service.in sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ -EXTRA_DIST = indicator-messages.service.in +gsettings_SCHEMAS = com.canonical.indicator.messages.gschema.xml +@GSETTINGS_RULES@ + +EXTRA_DIST = \ + $(gsettings_SCHEMAS) \ + indicator-messages.service.in CLEANFILES = indicator-messages.service diff --git a/data/com.canonical.indicator.messages.gschema.xml b/data/com.canonical.indicator.messages.gschema.xml new file mode 100644 index 0000000..d9165cd --- /dev/null +++ b/data/com.canonical.indicator.messages.gschema.xml @@ -0,0 +1,12 @@ + + + + List of applications that are shown in the messaging menu + + Applications corresponding to the desktop file ids in this list are shown in the messaging menu. + + [] + + + + diff --git a/src/Makefile.am b/src/Makefile.am index 8d48047..fa8c7a5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -48,7 +48,6 @@ indicator_messages_service_SOURCES = \ app-menu-item.h \ launcher-menu-item.c \ launcher-menu-item.h \ - dirs.h \ dbus-data.h \ \ status-items.c \ diff --git a/src/dirs.h b/src/dirs.h deleted file mode 100644 index ca322f0..0000000 --- a/src/dirs.h +++ /dev/null @@ -1,4 +0,0 @@ -#define SYSTEM_APPS_DIR "/usr/share/indicators/messages/applications" -#define SYSTEM_APPS_DIR_OLD "/etc/indicators/messages/applications" -#define USER_APPS_DIR "indicators/messages/applications" -#define USER_BLACKLIST_DIR "indicators/messages/applications-blacklist" diff --git a/src/messages-service.c b/src/messages-service.c index 2188ab0..12b1ded 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -28,6 +28,7 @@ with this program. If not, see . #include #include #include +#include #include #include @@ -37,7 +38,6 @@ with this program. If not, see . #include "app-menu-item.h" #include "launcher-menu-item.h" #include "dbus-data.h" -#include "dirs.h" #include "messages-service-dbus.h" #include "status-items.h" @@ -49,6 +49,7 @@ static GList * launcherList = NULL; static DbusmenuMenuitem * root_menuitem = NULL; static DbusmenuMenuitem * status_separator = NULL; static DbusmenuMenuitem * clear_attention = NULL; +static GSettings *settings; static GMainLoop * mainloop = NULL; static MessageServiceDbus * dbus_interface = NULL; @@ -66,18 +67,8 @@ static void indicator_removed (IndicateListener * listener, IndicateListenerServ 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); @@ -219,311 +210,6 @@ launcherList_count (void) 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; - } - - 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); - } - } - - g_dir_close(dir); - g_free(blacklistdir); - - return FALSE; -} - -/* Parses through a keyfile to find the desktop file entry and - pushes them into the blacklist. */ -static gboolean -blacklist_keyfile_add (gpointer udata) -{ - 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; -} - -/* 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) -{ - GKeyFile * keyfile = g_key_file_new(); - GError * error = NULL; - - 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; - } - - 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; - } - - 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; - } - - 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) -{ - GFile *file; - GFileInfo *fileinfo; - gchar *target = NULL; - - file = g_file_new_for_path (path); - - fileinfo = g_file_query_info (file, "standard::is-symlink", - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - NULL, NULL); - g_object_unref (file); - - if (!fileinfo) - return NULL; - - if (g_file_info_get_is_symlink (fileinfo)) - target = g_strdup (g_file_info_get_symlink_target (fileinfo)); - - g_object_unref (fileinfo); - return target; -} - -/* 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; - - 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); - } - else - g_warning ("invalid blacklist entry: %s", definition_file); - - return FALSE; -} - -/* 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) -{ - 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; - } - - /* 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); - } - - check_hidden(); - /* Shouldn't need a resort here as hiding shouldn't cause things to - move other than this item disappearing. */ - - g_free(basename); - return; -} - -/* 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; - } - } - - if (!found) { - g_debug("\tNot found!"); - return FALSE; - } - - 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; -} - -/* Check to see if a particular desktop file is - in the blacklist. */ -static gboolean -blacklist_check (const gchar * desktop_file) -{ - gchar *basename = g_path_get_basename(desktop_file); - gboolean found; - - g_debug("Checking blacklist for: %s", basename); - - 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; -} - /* * More code */ @@ -1186,36 +872,6 @@ indicator_removed (IndicateListener * listener, IndicateListenerServer * server, return; } -static void -app_dir_changed (GFileMonitor * monitor, GFile * file, GFile * other_file, GFileMonitorEvent event_type, 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; - } - - return; -} - /* Check to see if a new desktop file causes any of the launchers to be eclipsed by a running process */ @@ -1251,8 +907,6 @@ remove_eclipses (AppMenuItem * ai) 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; @@ -1268,108 +922,19 @@ remove_eclipses (AppMenuItem * ai) 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; - } - } - - if (listitem == NULL) { - g_warning("Removed '%s' by the way of it not seeming to exist anywhere.", appdirentry); - return 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; - } - - /* 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; - } - - launcherList = g_list_remove(launcherList, li); - g_free(li); - - return FALSE; -} - /* This function turns a specific file into a menu item and registers it appropriately with everyone */ static gboolean build_launcher (gpointer data) { - /* 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); + gchar *desktop_id = data; + GDesktopAppInfo *appinfo; - if (desktop == NULL) { - g_free(path); - return FALSE; - } + appinfo = g_desktop_app_info_new (desktop_id); + build_launcher_core(g_desktop_app_info_get_filename (appinfo)); - gchar * trimdesktop = pango_trim_string(desktop); - g_free(desktop); - g_debug("\tcontents: %s", trimdesktop); - - 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); + g_object_unref (appinfo); + g_free (desktop_id); return FALSE; } @@ -1411,10 +976,9 @@ build_launcher_core (const gchar * desktop) } 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)) { + /* If we've gotten eclipsed by something else, hide the item + * and the separator. */ + if (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); } @@ -1445,39 +1009,19 @@ build_launcher_core (const gchar * desktop) static gboolean build_launchers (gpointer data) { - gchar * directory = (gchar *)data; - - if (!g_file_test(directory, G_FILE_TEST_IS_DIR)) { - return FALSE; - } + gchar **applications = g_settings_get_strv (settings, "applications"); + gchar **app; - 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_return_val_if_fail (applications != NULL, FALSE); - 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; - } - - 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); - } + for (app = applications; *app; app++) + { + g_idle_add(build_launcher, g_strdup (*app)); } - g_dir_close(dir); launcherList = g_list_sort(launcherList, launcherList_sort); + + g_strfreev (applications); return FALSE; } @@ -1566,13 +1110,9 @@ main (int argc, char ** argv) 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); + settings = g_settings_new ("com.canonical.indicator.messages"); + + g_idle_add(build_launchers, NULL); /* Let's run a mainloop */ mainloop = g_main_loop_new(NULL, FALSE); @@ -1580,7 +1120,7 @@ main (int argc, char ** argv) /* Clean up */ status_items_cleanup(); - g_free(userdir); + g_object_unref (settings); return 0; } diff --git a/test/Makefile.am b/test/Makefile.am index 466de1e..9206036 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -43,7 +43,6 @@ libindicator_messages_service_la_HEADERS = \ $(top_srcdir)/src/im-menu-item.h \ $(top_srcdir)/src/app-menu-item.h \ $(top_srcdir)/src/launcher-menu-item.h \ - $(top_srcdir)/src/dirs.h \ $(top_srcdir)/src/dbus-data.h \ $(top_srcdir)/src/status-items.h -- cgit v1.2.3 From 8960bbafb9805c1e787e70bb2289cb8bc95a5f30 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 23 May 2012 21:30:00 +0200 Subject: Merge launcher- and appmenuitems --- src/Makefile.am | 2 - src/app-menu-item.c | 59 ++++++- src/launcher-menu-item.c | 362 ----------------------------------------- src/launcher-menu-item.h | 68 -------- src/messages-service.c | 415 +++++++++++++---------------------------------- test/Makefile.am | 2 - 6 files changed, 175 insertions(+), 733 deletions(-) delete mode 100644 src/launcher-menu-item.c delete mode 100644 src/launcher-menu-item.h (limited to 'test') diff --git a/src/Makefile.am b/src/Makefile.am index fa8c7a5..4fdc8a9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -46,8 +46,6 @@ indicator_messages_service_SOURCES = \ im-menu-item.h \ app-menu-item.c \ app-menu-item.h \ - launcher-menu-item.c \ - launcher-menu-item.h \ dbus-data.h \ \ status-items.c \ diff --git a/src/app-menu-item.c b/src/app-menu-item.c index 6ed00a2..48aef3e 100644 --- a/src/app-menu-item.c +++ b/src/app-menu-item.c @@ -28,6 +28,7 @@ with this program. If not, see . #include #include #include +#include #include "app-menu-item.h" #include "dbus-data.h" @@ -55,6 +56,8 @@ struct _AppMenuItemPrivate DbusmenuClient * client; DbusmenuMenuitem * root; GList * shortcuts; + GList * static_shortcuts; + IndicatorDesktopShortcuts * ids; }; #define APP_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), APP_MENU_ITEM_TYPE, AppMenuItemPrivate)) @@ -131,6 +134,7 @@ app_menu_item_init (AppMenuItem *self) priv->client = NULL; priv->root = NULL; priv->shortcuts = NULL; + priv->static_shortcuts = NULL; dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(self), DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); @@ -165,6 +169,17 @@ app_menu_item_dispose (GObject *object) priv->shortcuts = NULL; } + if (priv->static_shortcuts != NULL) { + g_list_foreach(priv->static_shortcuts, func_unref, object); + g_list_free(priv->static_shortcuts); + priv->static_shortcuts = NULL; + } + + if (priv->ids != NULL) { + g_object_unref(priv->ids); + priv->ids = NULL; + } + if (priv->root != NULL) { g_object_unref(priv->root); priv->root = NULL; @@ -201,6 +216,29 @@ app_menu_item_finalize (GObject *object) return; } +/* Respond to one of the shortcuts getting clicked on. */ +static void +nick_activate_cb (DbusmenuMenuitem * self, guint timestamp, gpointer data) +{ + gchar * nick = g_object_get_data(G_OBJECT(self), "ids-nick-data"); + AppMenuItem * mi = APP_MENU_ITEM(data); + + g_return_if_fail(nick != NULL); + g_return_if_fail(mi != NULL); + + AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(mi); + + g_return_if_fail(priv->ids != NULL); + + if (!indicator_desktop_shortcuts_nick_exec(priv->ids, nick)) { + g_warning("Unable to execute nick '%s' for desktop file '%s'", + nick, g_desktop_app_info_get_filename (priv->appinfo)); + } + + return; +} + + static void app_menu_item_set_appinfo (AppMenuItem *self, GDesktopAppInfo *appinfo) @@ -247,6 +285,24 @@ app_menu_item_set_appinfo (AppMenuItem *self, g_signal_emit(G_OBJECT(self), signals[NAME_CHANGED], 0, app_menu_item_get_name(self), TRUE); + /* Start to build static shortcuts */ + priv->ids = indicator_desktop_shortcuts_new(g_desktop_app_info_get_filename (priv->appinfo), "Messaging Menu"); + const gchar ** nicks = indicator_desktop_shortcuts_get_nicks(priv->ids); + gint i; + for (i = 0; nicks[i] != NULL; i++) { + DbusmenuMenuitem * mi = dbusmenu_menuitem_new(); + dbusmenu_menuitem_property_set(mi, DBUSMENU_MENUITEM_PROP_TYPE, APPLICATION_MENUITEM_TYPE); + g_object_set_data(G_OBJECT(mi), "ids-nick-data", (gpointer)nicks[i]); + + gchar *name = indicator_desktop_shortcuts_nick_get_name(priv->ids, nicks[i]); + dbusmenu_menuitem_property_set(mi, DBUSMENU_MENUITEM_PROP_LABEL, name); + g_free(name); + + g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(nick_activate_cb), self); + + priv->static_shortcuts = g_list_append(priv->static_shortcuts, mi); + } + g_key_file_unref(keyfile); } @@ -574,5 +630,6 @@ app_menu_item_get_items (AppMenuItem * appitem) { g_return_val_if_fail(IS_APP_MENU_ITEM(appitem), NULL); AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(appitem); - return priv->shortcuts; + return g_list_concat (g_list_copy (priv->shortcuts), + g_list_copy (priv->static_shortcuts)); } diff --git a/src/launcher-menu-item.c b/src/launcher-menu-item.c deleted file mode 100644 index fd04f52..0000000 --- a/src/launcher-menu-item.c +++ /dev/null @@ -1,362 +0,0 @@ -/* -An indicator to show information that is in messaging applications -that the user is using. - -Copyright 2009 Canonical Ltd. - -Authors: - Ted Gould - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program. If not, see . -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include -#include "launcher-menu-item.h" -#include "dbus-data.h" - -enum { - NAME_CHANGED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -typedef struct _LauncherMenuItemPrivate LauncherMenuItemPrivate; -struct _LauncherMenuItemPrivate -{ - GAppInfo * appinfo; - GKeyFile * keyfile; - gchar * desktop; - IndicatorDesktopShortcuts * ids; - GList * shortcuts; -}; - -#define LAUNCHER_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), LAUNCHER_MENU_ITEM_TYPE, LauncherMenuItemPrivate)) - -#define NICK_DATA "ids-nick-data" - -/* Prototypes */ -static void launcher_menu_item_class_init (LauncherMenuItemClass *klass); -static void launcher_menu_item_init (LauncherMenuItem *self); -static void launcher_menu_item_dispose (GObject *object); -static void launcher_menu_item_finalize (GObject *object); -static void activate_cb (LauncherMenuItem * self, guint timestamp, gpointer data); -static void nick_activate_cb (LauncherMenuItem * self, guint timestamp, gpointer data); - - -G_DEFINE_TYPE (LauncherMenuItem, launcher_menu_item, DBUSMENU_TYPE_MENUITEM); - -static void -launcher_menu_item_class_init (LauncherMenuItemClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (LauncherMenuItemPrivate)); - - object_class->dispose = launcher_menu_item_dispose; - object_class->finalize = launcher_menu_item_finalize; - - signals[NAME_CHANGED] = g_signal_new(LAUNCHER_MENU_ITEM_SIGNAL_NAME_CHANGED, - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (LauncherMenuItemClass, name_changed), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); - - return; -} - -static void -launcher_menu_item_init (LauncherMenuItem *self) -{ - g_debug("Building new Launcher Menu Item"); - LauncherMenuItemPrivate * priv = LAUNCHER_MENU_ITEM_GET_PRIVATE(self); - - priv->appinfo = NULL; - priv->desktop = NULL; - priv->keyfile = NULL; - - priv->ids = NULL; - priv->shortcuts = NULL; - - dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), DBUSMENU_MENUITEM_PROP_TYPE, APPLICATION_MENUITEM_TYPE); - - return; -} - -static void -func_unref (gpointer data, gpointer user_data) -{ - g_object_unref(G_OBJECT(data)); - return; -} - -static void -launcher_menu_item_dispose (GObject *object) -{ - LauncherMenuItem * self = LAUNCHER_MENU_ITEM(object); - LauncherMenuItemPrivate * priv = LAUNCHER_MENU_ITEM_GET_PRIVATE(self); - - if (priv->appinfo != NULL) { - g_object_unref(priv->appinfo); - priv->appinfo = NULL; - } - - if (priv->keyfile != NULL) { - g_object_unref(priv->keyfile); - priv->keyfile = NULL; - } - - if (priv->ids != NULL) { - g_object_unref(priv->ids); - priv->ids = NULL; - } - - if (priv->shortcuts != NULL) { - g_list_foreach(priv->shortcuts, func_unref, NULL); - g_list_free(priv->shortcuts); - priv->shortcuts = NULL; - } - - G_OBJECT_CLASS (launcher_menu_item_parent_class)->dispose (object); -} - -static void -launcher_menu_item_finalize (GObject *object) -{ - LauncherMenuItem * self = LAUNCHER_MENU_ITEM(object); - LauncherMenuItemPrivate * priv = LAUNCHER_MENU_ITEM_GET_PRIVATE(self); - - if (priv->desktop != NULL) { - g_free(priv->desktop); - priv->desktop = NULL; - } - - G_OBJECT_CLASS (launcher_menu_item_parent_class)->finalize (object); - - return; -} - -LauncherMenuItem * -launcher_menu_item_new (const gchar * desktop_file) -{ - LauncherMenuItem * self = g_object_new(LAUNCHER_MENU_ITEM_TYPE, NULL); - g_debug("\tDesktop file: %s", desktop_file); - - LauncherMenuItemPrivate * priv = LAUNCHER_MENU_ITEM_GET_PRIVATE(self); - - /* Parse the desktop file we've been given. */ - priv->appinfo = G_APP_INFO(g_desktop_app_info_new_from_filename(desktop_file)); - priv->keyfile = g_key_file_new(); - g_key_file_load_from_file(priv->keyfile, desktop_file, G_KEY_FILE_NONE, NULL); - priv->desktop = g_strdup(desktop_file); - - /* Set the appropriate values on this menu item based on the - app info that we've parsed */ - g_debug("\tName: %s", launcher_menu_item_get_name(self)); - - dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), DBUSMENU_MENUITEM_PROP_LABEL, launcher_menu_item_get_name(self)); - - gchar * iconstr = launcher_menu_item_get_icon(self); - dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), DBUSMENU_MENUITEM_PROP_ICON_NAME, iconstr); - g_free(iconstr); - dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(self), DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); - - g_signal_connect(G_OBJECT(self), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(activate_cb), NULL); - - /* Start to build static shortcuts */ - priv->ids = indicator_desktop_shortcuts_new(priv->desktop, "Messaging Menu"); - const gchar ** nicks = indicator_desktop_shortcuts_get_nicks(priv->ids); - gint i; - for (i = 0; nicks[i] != NULL; i++) { - DbusmenuMenuitem * mi = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set(mi, DBUSMENU_MENUITEM_PROP_TYPE, APPLICATION_MENUITEM_TYPE); - g_object_set_data(G_OBJECT(mi), NICK_DATA, (gpointer)nicks[i]); - - gchar *name = indicator_desktop_shortcuts_nick_get_name(priv->ids, nicks[i]); - dbusmenu_menuitem_property_set(mi, DBUSMENU_MENUITEM_PROP_LABEL, name); - g_free(name); - - g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(nick_activate_cb), self); - - priv->shortcuts = g_list_append(priv->shortcuts, mi); - } - - /* Check to see if we should be eclipsed */ - if (priv->appinfo == NULL) { - launcher_menu_item_set_eclipsed(self, TRUE); - } - - return self; -} - -const gchar * -launcher_menu_item_get_name (LauncherMenuItem * appitem) -{ - LauncherMenuItemPrivate * priv = LAUNCHER_MENU_ITEM_GET_PRIVATE(appitem); - - if (priv->appinfo == NULL) { - return NULL; - } else { - return g_app_info_get_name(priv->appinfo); - } -} - -/* Respond to one of the shortcuts getting clicked on. */ -static void -nick_activate_cb (LauncherMenuItem * self, guint timestamp, gpointer data) -{ - gchar * nick = (gchar *)g_object_get_data(G_OBJECT(self), NICK_DATA); - LauncherMenuItem * lmi = LAUNCHER_MENU_ITEM(data); - - g_return_if_fail(nick != NULL); - g_return_if_fail(lmi != NULL); - - LauncherMenuItemPrivate * priv = LAUNCHER_MENU_ITEM_GET_PRIVATE(lmi); - - g_return_if_fail(priv->ids != NULL); - - if (!indicator_desktop_shortcuts_nick_exec(priv->ids, nick)) { - g_warning("Unable to execute nick '%s' for desktop file '%s'", nick, priv->desktop); - } - - return; -} - -/* Figure out the appropriate icon for this launcher */ -gchar * -launcher_menu_item_get_icon (LauncherMenuItem * appitem) -{ - LauncherMenuItemPrivate * priv = LAUNCHER_MENU_ITEM_GET_PRIVATE(appitem); - gchar * retval = NULL; - - /* Check to see if there is a specific icon for the messaging - menu first. */ - if (g_key_file_has_key(priv->keyfile, G_KEY_FILE_DESKTOP_GROUP, ICON_KEY, NULL) && retval == NULL) { - GError * error = NULL; - - retval = g_key_file_get_string(priv->keyfile, G_KEY_FILE_DESKTOP_GROUP, ICON_KEY, &error); - - if (error != NULL) { - /* Can't figure out why this would happen, but sure, let's print something */ - g_warning("Error getting '" ICON_KEY "' from desktop file: %s", error->message); - g_error_free(error); - } - } - - /* If there's not, or there is an error, we'll use the one - from the application info */ - if (priv->appinfo != NULL && retval == NULL) { - GIcon * icon = g_app_info_get_icon(priv->appinfo); - retval = g_icon_to_string(icon); - } - - return retval; -} - -/* When the menu item is clicked on it tries to launch - the application that is represented by the desktop file */ -static void -activate_cb (LauncherMenuItem * self, guint timestamp, gpointer data) -{ - LauncherMenuItemPrivate * priv = LAUNCHER_MENU_ITEM_GET_PRIVATE(self); - g_return_if_fail(priv->appinfo != NULL); - - GError * error = NULL; - if (!g_app_info_launch(priv->appinfo, NULL, NULL, &error)) { - g_warning("Application failed to launch '%s' because: %s", launcher_menu_item_get_name(self), error->message); - g_error_free(error); - } - - return; -} - -const gchar * -launcher_menu_item_get_desktop (LauncherMenuItem * launchitem) -{ - g_return_val_if_fail(IS_LAUNCHER_MENU_ITEM(launchitem), NULL); - LauncherMenuItemPrivate * priv = LAUNCHER_MENU_ITEM_GET_PRIVATE(launchitem); - return priv->desktop; -} - -/* Gets the decription for the item that should - go in the messaging menu */ -const gchar * -launcher_menu_item_get_description (LauncherMenuItem * li) -{ - g_return_val_if_fail(IS_LAUNCHER_MENU_ITEM(li), NULL); - LauncherMenuItemPrivate * priv = LAUNCHER_MENU_ITEM_GET_PRIVATE(li); - return g_app_info_get_description(priv->appinfo); -} - -/* Apply the eclipse value to all the shortcuts */ -static void -eclipse_shortcuts_cb (gpointer data, gpointer user_data) -{ - DbusmenuMenuitem * mi = DBUSMENU_MENUITEM(data); - g_return_if_fail(mi != NULL); - - gboolean eclipsed = GPOINTER_TO_UINT(user_data); - - dbusmenu_menuitem_property_set_bool(mi, DBUSMENU_MENUITEM_PROP_VISIBLE, !eclipsed); - return; -} - -/* Hides the menu item based on whether it is eclipsed - or not. */ -void -launcher_menu_item_set_eclipsed (LauncherMenuItem * li, gboolean eclipsed) -{ - g_return_if_fail(IS_LAUNCHER_MENU_ITEM(li)); - LauncherMenuItemPrivate * priv = LAUNCHER_MENU_ITEM_GET_PRIVATE(li); - - g_debug("Laucher '%s' is %s", launcher_menu_item_get_name(li), eclipsed ? "now eclipsed" : "shown again"); - dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(li), DBUSMENU_MENUITEM_PROP_VISIBLE, !eclipsed); - - g_list_foreach(priv->shortcuts, eclipse_shortcuts_cb, GINT_TO_POINTER(eclipsed)); - - /* If we're being reshown let's re-evaluate how we should be - showing the label */ - if (!eclipsed) { - dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(li), DBUSMENU_MENUITEM_PROP_LABEL, launcher_menu_item_get_name(li)); - } - - return; -} - -/* Check to see if this item is eclipsed */ -gboolean -launcher_menu_item_get_eclipsed (LauncherMenuItem * li) -{ - gboolean show = dbusmenu_menuitem_property_get_bool(DBUSMENU_MENUITEM(li), DBUSMENU_MENUITEM_PROP_VISIBLE); - g_debug("Launcher check eclipse: %s", show ? "false" : "true"); - return !show; -} - -/* Gets the shortcuts that are associated with this - launcher. They're a list of DbusmenuMenuitems */ -GList * -launcher_menu_item_get_items (LauncherMenuItem * li) -{ - g_return_val_if_fail(IS_LAUNCHER_MENU_ITEM(li), NULL); - LauncherMenuItemPrivate * priv = LAUNCHER_MENU_ITEM_GET_PRIVATE(li); - return priv->shortcuts; -} diff --git a/src/launcher-menu-item.h b/src/launcher-menu-item.h deleted file mode 100644 index ace1f85..0000000 --- a/src/launcher-menu-item.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -An indicator to show information that is in messaging applications -that the user is using. - -Copyright 2009 Canonical Ltd. - -Authors: - Ted Gould - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program. If not, see . -*/ - -#ifndef __LAUNCHER_MENU_ITEM_H__ -#define __LAUNCHER_MENU_ITEM_H__ - -#include -#include - -#include - -G_BEGIN_DECLS - -#define LAUNCHER_MENU_ITEM_TYPE (launcher_menu_item_get_type ()) -#define LAUNCHER_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LAUNCHER_MENU_ITEM_TYPE, LauncherMenuItem)) -#define LAUNCHER_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), LAUNCHER_MENU_ITEM_TYPE, LauncherMenuItemClass)) -#define IS_LAUNCHER_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LAUNCHER_MENU_ITEM_TYPE)) -#define IS_LAUNCHER_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), LAUNCHER_MENU_ITEM_TYPE)) -#define LAUNCHER_MENU_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), LAUNCHER_MENU_ITEM_TYPE, LauncherMenuItemClass)) - -#define LAUNCHER_MENU_ITEM_SIGNAL_NAME_CHANGED "name-changed" - -typedef struct _LauncherMenuItem LauncherMenuItem; -typedef struct _LauncherMenuItemClass LauncherMenuItemClass; - -struct _LauncherMenuItemClass { - DbusmenuMenuitemClass parent_class; - - void (* name_changed) (gchar * name); -}; - -struct _LauncherMenuItem { - DbusmenuMenuitem parent; -}; - -GType launcher_menu_item_get_type (void); -LauncherMenuItem * launcher_menu_item_new (const gchar * desktop_file); -const gchar * launcher_menu_item_get_name (LauncherMenuItem * appitem); -const gchar * launcher_menu_item_get_desktop (LauncherMenuItem * launchitem); -const gchar * launcher_menu_item_get_description (LauncherMenuItem * li); -gchar * launcher_menu_item_get_icon (LauncherMenuItem * appitem); -void launcher_menu_item_set_eclipsed (LauncherMenuItem * li, gboolean eclipsed); -gboolean launcher_menu_item_get_eclipsed (LauncherMenuItem * li); -GList * launcher_menu_item_get_items (LauncherMenuItem * li); - -G_END_DECLS - -#endif /* __LAUNCHER_MENU_ITEM_H__ */ - diff --git a/src/messages-service.c b/src/messages-service.c index 1b01e4b..0934b9c 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -36,7 +36,6 @@ with this program. If not, see . #include "im-menu-item.h" #include "app-menu-item.h" -#include "launcher-menu-item.h" #include "dbus-data.h" #include "messages-service-dbus.h" #include "status-items.h" @@ -44,7 +43,6 @@ with this program. If not, see . 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; @@ -64,11 +62,8 @@ static void server_name_changed (AppMenuItem * appitem, gchar * name, gpointer d 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_launchers (gpointer data); -static void check_hidden (void); /* @@ -161,56 +156,6 @@ imList_sort (gconstpointer a, gconstpointer 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; -}; - -static gint -launcherList_sort (gconstpointer a, gconstpointer b) -{ - 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); -} - -static void -launcherList_count_helper (gpointer data, 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; -} - -/* - * More code - */ /* Goes through all the servers and sees if any of them want attention. If they do, then well we'll give it @@ -259,6 +204,84 @@ server_attention (serverList_t * slt) return; } +static void +desktop_cb (IndicateListener *listener, + IndicateListenerServer *server, + const gchar *value, + gpointer data) +{ + DbusmenuMenuitem * menushell = DBUSMENU_MENUITEM(data); + GList *listitem; + serverList_t * sl_item = NULL; + + /* Check to see if we already have a launcher for this app */ + for (listitem = serverList; listitem != NULL; listitem = listitem->next) { + serverList_t * slt = listitem->data; + if (!g_strcmp0(app_menu_item_get_desktop(slt->menuitem), value)) { + sl_item = slt; + break; + } + } + + if (!sl_item) { + /* Build the Menu item */ + AppMenuItem * menuitem = app_menu_item_new_with_server (listener, server); + + /* Build a possible server structure */ + 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; + + /* 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)); + + /* 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); + } + + dbusmenu_menuitem_child_append(menushell, DBUSMENU_MENUITEM(sl_item->separator)); + } + else { + app_menu_item_set_server (sl_item->menuitem, listener, server); + } + + GList * shortcuts = app_menu_item_get_items(sl_item->menuitem); + GList * shortcut = shortcuts; + while (shortcut != NULL) { + DbusmenuMenuitem * mi = DBUSMENU_MENUITEM(shortcut->data); + g_debug("\tAdding shortcut: %s", dbusmenu_menuitem_property_get(mi, DBUSMENU_MENUITEM_PROP_LABEL)); + dbusmenu_menuitem_child_append(menushell, mi); + shortcut = g_list_next(shortcut); + } + g_list_free (shortcuts); + + resort_menu(menushell); +} + /* 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. */ @@ -279,65 +302,9 @@ server_added (IndicateListener * listener, IndicateListenerServer * server, gcha 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_with_server (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; + /* fetch the desktop file before creating the menu item, in case we + * already have a launcher for it */ + indicate_listener_server_get_desktop(listener, server, desktop_cb, data); } /* Server shortcut has been added */ @@ -372,7 +339,6 @@ 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; } @@ -466,19 +432,18 @@ server_removed (IndicateListener * listener, IndicateListenerServer * server, gc /* 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); + GList * shortcut = shortcuts; + while (shortcut != NULL) { + g_debug("\tRemoving shortcut: %s", dbusmenu_menuitem_property_get(DBUSMENU_MENUITEM(shortcut->data), DBUSMENU_MENUITEM_PROP_LABEL)); + dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(shortcut->data), DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); + dbusmenu_menuitem_child_delete(DBUSMENU_MENUITEM(data), DBUSMENU_MENUITEM(shortcut->data)); + shortcut = g_list_next(shortcut); } + g_list_free (shortcuts); g_debug("\tRemoving item"); dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(sltp->menuitem), DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); @@ -506,8 +471,6 @@ server_removed (IndicateListener * listener, IndicateListenerServer * server, gc g_free(sltp); - check_hidden(); - return; } @@ -531,9 +494,12 @@ menushell_foreach_cb (DbusmenuMenuitem * data_mi, gpointer data_ms) { 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)))) { + GList *shortcuts = app_menu_item_get_items(appmenu); msl->found = TRUE; /* Return a position at the end of our shortcuts */ - msl->position += g_list_length(app_menu_item_get_items(appmenu)); + msl->position += g_list_length(shortcuts); + g_list_free (shortcuts); + } else { msl->position++; } @@ -541,24 +507,6 @@ menushell_foreach_cb (DbusmenuMenuitem * data_mi, gpointer data_ms) { return; } -static void -check_hidden (void) -{ - 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; - } - } - - message_service_dbus_set_icon(dbus_interface, hide); - return; -} - /* 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 @@ -569,7 +517,6 @@ resort_menu (DbusmenuMenuitem * menushell) { guint position = 0; GList * serverentry; - GList * launcherentry = launcherList; g_debug("Reordering Menu:"); @@ -581,41 +528,6 @@ resort_menu (DbusmenuMenuitem * menushell) 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); @@ -624,12 +536,14 @@ resort_menu (DbusmenuMenuitem * menushell) /* Inserting the shortcuts from the launcher */ GList * shortcuts = app_menu_item_get_items(si->menuitem); - while (shortcuts != NULL) { + GList * shortcut = shortcuts; + while (shortcut != NULL) { g_debug("\t\tMoving shortcut to position %d", position); - dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(shortcuts->data), position); + dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(shortcut->data), position); position++; - shortcuts = g_list_next(shortcuts); + shortcut = g_list_next(shortcut); } + g_list_free (shortcuts); } /* Putting all the indicators that are related to this application @@ -668,36 +582,6 @@ resort_menu (DbusmenuMenuitem * menushell) } } - /* 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 */ @@ -870,73 +754,22 @@ indicator_removed (IndicateListener * listener, IndicateListenerServer * server, return; } -/* 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; - } - } - - return; -} - -/* Remove any eclipses that might have been caused - by this app item that is now retiring */ -static void -remove_eclipses (AppMenuItem * ai) -{ - const gchar * aidesktop = app_menu_item_get_desktop(ai); - if (aidesktop == NULL) 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; - } - } - - return; -} - /* This function turns a specific file into a menu item and registers it appropriately with everyone */ static gboolean build_launcher (gpointer data) { gchar *desktop_id = data; - const gchar *desktop = data; GDesktopAppInfo *appinfo; + GList *listitem; appinfo = g_desktop_app_info_new (desktop_id); - desktop = g_desktop_app_info_get_filename (appinfo); /* 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)) { + for (listitem = serverList; listitem != NULL; listitem = listitem->next) { + serverList_t * slt = listitem->data; + if (!g_strcmp0(app_menu_item_get_desktop(slt->menuitem), + g_desktop_app_info_get_filename (appinfo))) { break; } } @@ -944,43 +777,29 @@ build_launcher (gpointer data) if (listitem == NULL) { /* If not */ /* Build the item */ - launcherList_t * ll = g_new0(launcherList_t, 1); - ll->menuitem = launcher_menu_item_new(desktop); + serverList_t * sl_item = g_new0(serverList_t, 1); + sl_item->menuitem = app_menu_item_new(appinfo); /* Build a separator */ - ll->separator = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set(ll->separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); + sl_item->separator = dbusmenu_menuitem_new(); + dbusmenu_menuitem_property_set(sl_item->separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); /* Add it to the list */ - launcherList = g_list_insert_sorted(launcherList, ll, launcherList_sort); + serverList = g_list_insert_sorted (serverList, sl_item, serverList_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've gotten eclipsed by something else, hide the item - * and the separator. */ - if (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); + dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(sl_item->menuitem), DBUSMENU_MENUITEM_PROP_TYPE, APPLICATION_MENUITEM_TYPE); + dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(sl_item->menuitem)); + GList * shortcuts = app_menu_item_get_items(sl_item->menuitem); + GList * shortcut = shortcuts; + while (shortcut != NULL) { + dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(shortcut->data)); + shortcut = g_list_next(shortcut); } + g_list_free (shortcuts); + dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(sl_item->separator)); resort_menu(root_menuitem); - check_hidden(); } g_object_unref (appinfo); @@ -1005,7 +824,7 @@ build_launchers (gpointer data) g_idle_add(build_launcher, g_strdup (*app)); } - launcherList = g_list_sort(launcherList, launcherList_sort); + serverList = g_list_sort(serverList, serverList_sort); g_strfreev (applications); return FALSE; diff --git a/test/Makefile.am b/test/Makefile.am index 9206036..bb58ab2 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -42,7 +42,6 @@ libindicator_messages_service_la_HEADERS = \ $(top_srcdir)/src/gen-messages-service.xml.h \ $(top_srcdir)/src/im-menu-item.h \ $(top_srcdir)/src/app-menu-item.h \ - $(top_srcdir)/src/launcher-menu-item.h \ $(top_srcdir)/src/dbus-data.h \ $(top_srcdir)/src/status-items.h @@ -52,7 +51,6 @@ libindicator_messages_service_la_SOURCES = \ $(top_srcdir)/src/gen-messages-service.xml.c \ $(top_srcdir)/src/im-menu-item.c \ $(top_srcdir)/src/app-menu-item.c \ - $(top_srcdir)/src/launcher-menu-item.c \ $(top_srcdir)/src/status-items.c libindicator_messages_service_ladir = \ -- cgit v1.2.3 From e1c600ba95e4520caf471ebf2eb9f41e2580fa98 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Thu, 24 May 2012 22:28:40 +0200 Subject: Port to gmenu, act I Work-in-progress of the gmenu port for the service. The bulk of this patch removes everything related to libindicate from the service. Only the static app launchers and their configured shortcut actions are exported for now. --- configure.ac | 2 - src/Makefile.am | 2 - src/app-menu-item.c | 474 ++++------------------------- src/app-menu-item.h | 17 +- src/dbus-data.h | 4 + src/im-menu-item.c | 586 ----------------------------------- src/im-menu-item.h | 67 ---- src/messages-service.c | 807 ++++--------------------------------------------- src/status-items.c | 89 +++--- src/status-items.h | 4 +- test/Makefile.am | 2 - 11 files changed, 175 insertions(+), 1879 deletions(-) delete mode 100644 src/im-menu-item.c delete mode 100644 src/im-menu-item.h (limited to 'test') diff --git a/configure.ac b/configure.ac index 148259d..b7602a3 100644 --- a/configure.ac +++ b/configure.ac @@ -41,7 +41,6 @@ AC_PROG_CXX GTK_REQUIRED_VERSION=3.0 GIO_UNIX_REQUIRED_VERSION=2.18 PANEL_REQUIRED_VERSION=2.0.0 -INDICATE_REQUIRED_VERSION=0.6.90 INDICATOR_REQUIRED_VERSION=0.3.19 DBUSMENUGTK_REQUIRED_VERSION=0.5.90 GLIB_REQUIRED_VERSION=2.31.20 @@ -49,7 +48,6 @@ GLIB_REQUIRED_VERSION=2.31.20 PKG_CHECK_MODULES(APPLET, gtk+-3.0 >= $GTK_REQUIRED_VERSION gio-unix-2.0 >= $GIO_UNIX_REQUIRED_VERSION indicator3-0.4 >= $INDICATOR_REQUIRED_VERSION - indicate-0.7 >= $INDICATE_REQUIRED_VERSION dbusmenu-gtk3-0.4 >= $DBUSMENUGTK_REQUIRED_VERSION glib-2.0 >= $GLIB_REQUIRED_VERSION gmodule-2.0 >= $GLIB_REQUIRED_VERSION) diff --git a/src/Makefile.am b/src/Makefile.am index 4fdc8a9..2527878 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -42,8 +42,6 @@ indicator_messages_service_SOURCES = \ messages-service-dbus.h \ gen-messages-service.xml.h \ gen-messages-service.xml.c \ - im-menu-item.c \ - im-menu-item.h \ app-menu-item.c \ app-menu-item.h \ dbus-data.h \ diff --git a/src/app-menu-item.c b/src/app-menu-item.c index 48aef3e..b5d4994 100644 --- a/src/app-menu-item.c +++ b/src/app-menu-item.c @@ -26,17 +26,13 @@ with this program. If not, see . #include #include -#include -#include +#include #include #include "app-menu-item.h" #include "dbus-data.h" enum { - COUNT_CHANGED, NAME_CHANGED, - SHORTCUT_ADDED, - SHORTCUT_REMOVED, LAST_SIGNAL }; @@ -46,18 +42,13 @@ typedef struct _AppMenuItemPrivate AppMenuItemPrivate; struct _AppMenuItemPrivate { - IndicateListener * listener; - IndicateListenerServer * server; - - gchar * type; GDesktopAppInfo * appinfo; guint unreadcount; - DbusmenuClient * client; - DbusmenuMenuitem * root; - GList * shortcuts; - GList * static_shortcuts; IndicatorDesktopShortcuts * ids; + + GMenu *menu; + GSimpleActionGroup *static_shortcuts; }; #define APP_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), APP_MENU_ITEM_TYPE, AppMenuItemPrivate)) @@ -66,16 +57,12 @@ struct _AppMenuItemPrivate static void app_menu_item_class_init (AppMenuItemClass *klass); static void app_menu_item_init (AppMenuItem *self); static void app_menu_item_dispose (GObject *object); -static void app_menu_item_finalize (GObject *object); -static void activate_cb (AppMenuItem * self, guint timestamp, gpointer data); -static void count_changed (IndicateListener * listener, IndicateListenerServer * server, guint count, gpointer data); -static void count_cb (IndicateListener * listener, IndicateListenerServer * server, guint value, gpointer data); -static void menu_cb (IndicateListener * listener, IndicateListenerServer * server, const gchar * menupath, gpointer data); -static void desktop_cb (IndicateListener * listener, IndicateListenerServer * server, const gchar * value, gpointer data); -static void update_label (AppMenuItem * self); +static void activate_cb (GSimpleAction *action, + GVariant *param, + gpointer userdata); /* GObject Boilerplate */ -G_DEFINE_TYPE (AppMenuItem, app_menu_item, DBUSMENU_TYPE_MENUITEM); +G_DEFINE_TYPE (AppMenuItem, app_menu_item, G_TYPE_OBJECT); static void app_menu_item_class_init (AppMenuItemClass *klass) @@ -85,15 +72,7 @@ app_menu_item_class_init (AppMenuItemClass *klass) g_type_class_add_private (klass, sizeof (AppMenuItemPrivate)); object_class->dispose = app_menu_item_dispose; - object_class->finalize = app_menu_item_finalize; - signals[COUNT_CHANGED] = g_signal_new(APP_MENU_ITEM_SIGNAL_COUNT_CHANGED, - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (AppMenuItemClass, count_changed), - NULL, NULL, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, 1, G_TYPE_UINT); signals[NAME_CHANGED] = g_signal_new(APP_MENU_ITEM_SIGNAL_NAME_CHANGED, G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, @@ -101,22 +80,6 @@ app_menu_item_class_init (AppMenuItemClass *klass) NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); - signals[SHORTCUT_ADDED] = g_signal_new(APP_MENU_ITEM_SIGNAL_SHORTCUT_ADDED, - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (AppMenuItemClass, shortcut_added), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, G_TYPE_OBJECT); - signals[SHORTCUT_REMOVED] = g_signal_new(APP_MENU_ITEM_SIGNAL_SHORTCUT_REMOVED, - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (AppMenuItemClass, shortcut_removed), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, G_TYPE_OBJECT); - - return; } static void @@ -125,71 +88,29 @@ app_menu_item_init (AppMenuItem *self) g_debug("Building new App Menu Item"); AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self); - priv->listener = NULL; - priv->server = NULL; - priv->type = NULL; priv->appinfo = NULL; priv->unreadcount = 0; - priv->client = NULL; - priv->root = NULL; - priv->shortcuts = NULL; - priv->static_shortcuts = NULL; - - dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(self), DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); + priv->menu = g_menu_new (); + priv->static_shortcuts = g_simple_action_group_new (); return; } -/* A wrapper to make the prototypes work for GFunc */ -static void -func_unref (gpointer data, gpointer user_data) -{ - g_signal_emit(user_data, signals[SHORTCUT_REMOVED], 0, data, TRUE); - g_object_unref(G_OBJECT(data)); - return; -} - -/* Disconnect the count_changed signal and unref the listener */ static void app_menu_item_dispose (GObject *object) { AppMenuItem * self = APP_MENU_ITEM(object); AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self); - if (priv->listener != NULL) { - g_signal_handlers_disconnect_by_func(G_OBJECT(priv->listener), count_changed, self); - g_object_unref(priv->listener); - priv->listener = NULL; - } - - if (priv->shortcuts != NULL) { - g_list_foreach(priv->shortcuts, func_unref, object); - g_list_free(priv->shortcuts); - priv->shortcuts = NULL; - } - - if (priv->static_shortcuts != NULL) { - g_list_foreach(priv->static_shortcuts, func_unref, object); - g_list_free(priv->static_shortcuts); - priv->static_shortcuts = NULL; - } + g_clear_object (&priv->menu); + g_clear_object (&priv->static_shortcuts); if (priv->ids != NULL) { g_object_unref(priv->ids); priv->ids = NULL; } - if (priv->root != NULL) { - g_object_unref(priv->root); - priv->root = NULL; - } - - if (priv->client != NULL) { - g_object_unref(priv->client); - priv->client = NULL; - } - if (priv->appinfo != NULL) { g_object_unref(priv->appinfo); priv->appinfo = NULL; @@ -198,34 +119,14 @@ app_menu_item_dispose (GObject *object) G_OBJECT_CLASS (app_menu_item_parent_class)->dispose (object); } -/* Free the memory used by our type, desktop file and application - info structures. */ -static void -app_menu_item_finalize (GObject *object) -{ - AppMenuItem * self = APP_MENU_ITEM(object); - AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self); - - if (priv->type != NULL) { - g_free(priv->type); - priv->type = NULL; - } - - G_OBJECT_CLASS (app_menu_item_parent_class)->finalize (object); - - return; -} - /* Respond to one of the shortcuts getting clicked on. */ static void -nick_activate_cb (DbusmenuMenuitem * self, guint timestamp, gpointer data) +nick_activate_cb (GSimpleAction *action, + GVariant *param, + gpointer userdata) { - gchar * nick = g_object_get_data(G_OBJECT(self), "ids-nick-data"); - AppMenuItem * mi = APP_MENU_ITEM(data); - - g_return_if_fail(nick != NULL); - g_return_if_fail(mi != NULL); - + const gchar * nick = g_action_get_name (G_ACTION (action)); + AppMenuItem * mi = APP_MENU_ITEM (userdata); AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(mi); g_return_if_fail(priv->ids != NULL); @@ -234,29 +135,24 @@ nick_activate_cb (DbusmenuMenuitem * self, guint timestamp, gpointer data) g_warning("Unable to execute nick '%s' for desktop file '%s'", nick, g_desktop_app_info_get_filename (priv->appinfo)); } - - return; } - static void app_menu_item_set_appinfo (AppMenuItem *self, GDesktopAppInfo *appinfo) { AppMenuItemPrivate *priv = APP_MENU_ITEM_GET_PRIVATE (self); + GSimpleAction *launch; + GMenuItem *menuitem; GKeyFile *keyfile; gchar *iconstr = NULL; + gchar *label; g_return_if_fail (appinfo != NULL); g_clear_object (&priv->appinfo); priv->appinfo = g_object_ref (appinfo); - dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(self), DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); - dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(self), APPLICATION_MENUITEM_PROP_RUNNING, TRUE); - - update_label(self); - keyfile = g_key_file_new(); g_key_file_load_from_file(keyfile, g_desktop_app_info_get_filename (appinfo), G_KEY_FILE_NONE, NULL); @@ -280,29 +176,47 @@ app_menu_item_set_appinfo (AppMenuItem *self, iconstr = g_icon_to_string(icon); } - dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), APPLICATION_MENUITEM_PROP_ICON, iconstr); - g_free(iconstr); + launch = g_simple_action_new ("launch", NULL); + g_signal_connect (launch, "activate", G_CALLBACK (activate_cb), self); + g_simple_action_group_insert (priv->static_shortcuts, G_ACTION (launch)); - g_signal_emit(G_OBJECT(self), signals[NAME_CHANGED], 0, app_menu_item_get_name(self), TRUE); + if (priv->unreadcount > 0) + label = g_strdup_printf("%s (%d)", app_menu_item_get_name (self), priv->unreadcount); + else + label = g_strdup(app_menu_item_get_name (self)); + + menuitem = g_menu_item_new (label, "launch"); + g_menu_item_set_attribute (menuitem, INDICATOR_MENU_ATTRIBUTE_ICON_NAME, "s", iconstr); + g_menu_append_item (priv->menu, menuitem); /* Start to build static shortcuts */ priv->ids = indicator_desktop_shortcuts_new(g_desktop_app_info_get_filename (priv->appinfo), "Messaging Menu"); const gchar ** nicks = indicator_desktop_shortcuts_get_nicks(priv->ids); gint i; for (i = 0; nicks[i] != NULL; i++) { - DbusmenuMenuitem * mi = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set(mi, DBUSMENU_MENUITEM_PROP_TYPE, APPLICATION_MENUITEM_TYPE); - g_object_set_data(G_OBJECT(mi), "ids-nick-data", (gpointer)nicks[i]); + gchar *name; + GSimpleAction *action; + GMenuItem *item; - gchar *name = indicator_desktop_shortcuts_nick_get_name(priv->ids, nicks[i]); - dbusmenu_menuitem_property_set(mi, DBUSMENU_MENUITEM_PROP_LABEL, name); - g_free(name); + name = indicator_desktop_shortcuts_nick_get_name(priv->ids, nicks[i]); + + action = g_simple_action_new (name, NULL); + g_signal_connect(action, "activate", G_CALLBACK (nick_activate_cb), self); + g_simple_action_group_insert (priv->static_shortcuts, G_ACTION (action)); - g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(nick_activate_cb), self); + item = g_menu_item_new (name, name); + g_menu_append_item (priv->menu, item); - priv->static_shortcuts = g_list_append(priv->static_shortcuts, mi); + g_object_unref (item); + g_free(name); } + g_signal_emit(G_OBJECT(self), signals[NAME_CHANGED], 0, app_menu_item_get_name(self), TRUE); + + g_free(label); + g_free(iconstr); + g_object_unref (launch); + g_object_unref (menuitem); g_key_file_unref(keyfile); } @@ -315,269 +229,19 @@ app_menu_item_new (GDesktopAppInfo *appinfo) return self; } -AppMenuItem * -app_menu_item_new_with_server (IndicateListener * listener, IndicateListenerServer * server) -{ - AppMenuItem * self = g_object_new(APP_MENU_ITEM_TYPE, NULL); - app_menu_item_set_server (self, listener, server); - return self; -} - -void -app_menu_item_set_server (AppMenuItem *self, - IndicateListener *listener, - IndicateListenerServer *server) -{ - AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self); - - /* only allow setting this once */ - g_return_if_fail (priv->listener == NULL && priv->server == NULL); - - /* Copy the listener so we can use it later */ - priv->listener = listener; - g_object_ref(G_OBJECT(listener)); - - /* Can not ref as not real GObject */ - priv->server = server; - - dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), DBUSMENU_MENUITEM_PROP_TYPE, APPLICATION_MENUITEM_TYPE); - - /* Set up listener signals */ - g_signal_connect(G_OBJECT(listener), INDICATE_LISTENER_SIGNAL_SERVER_COUNT_CHANGED, G_CALLBACK(count_changed), self); - - /* Get the values we care about from the server */ - indicate_listener_server_get_desktop(listener, server, desktop_cb, self); - indicate_listener_server_get_count(listener, server, count_cb, self); - indicate_listener_server_get_menu(listener, server, menu_cb, self); - - g_signal_connect(G_OBJECT(self), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(activate_cb), NULL); - - indicate_listener_server_show_interest(listener, server, INDICATE_INTEREST_SERVER_DISPLAY); - indicate_listener_server_show_interest(listener, server, INDICATE_INTEREST_SERVER_SIGNAL); - indicate_listener_server_show_interest(listener, server, INDICATE_INTEREST_INDICATOR_COUNT); - indicate_listener_server_show_interest(listener, server, INDICATE_INTEREST_INDICATOR_DISPLAY); - indicate_listener_server_show_interest(listener, server, INDICATE_INTEREST_INDICATOR_SIGNAL); - indicate_listener_set_server_max_indicators(listener, server, MAX_NUMBER_OF_INDICATORS); -} - static void -update_label (AppMenuItem * self) +activate_cb (GSimpleAction *action, + GVariant *param, + gpointer userdata) { - AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self); - const gchar * name = app_menu_item_get_name(self); - - if (priv->unreadcount > 0) { - /* TRANSLATORS: This is the name of the program and the number of indicators. So it - would read something like "Mail Client (5)" */ - gchar * label = g_strdup_printf(_("%s (%d)"), _(name), priv->unreadcount); - dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), APPLICATION_MENUITEM_PROP_NAME, label); - g_free(label); - } else { - dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), APPLICATION_MENUITEM_PROP_NAME, _(name)); - } - - return; -} - -/* Callback to the signal that the server count - has changed to a new value. This checks to see if - it's actually changed and if so signals everyone and - updates the label. */ -static void -count_changed (IndicateListener * listener, IndicateListenerServer * server, guint count, gpointer data) -{ - g_return_if_fail(IS_APP_MENU_ITEM(data)); - AppMenuItem * self = APP_MENU_ITEM(data); - AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self); - - if (priv->unreadcount != count) { - priv->unreadcount = count; - update_label(self); - g_signal_emit(G_OBJECT(self), signals[COUNT_CHANGED], 0, priv->unreadcount, TRUE); - } - - return; -} - -/* Callback for getting the count property off - of the server. */ -static void -count_cb (IndicateListener * listener, IndicateListenerServer * server, guint value, gpointer data) -{ - count_changed(listener, server, value, data); - return; -} - -/* Callback for when we ask the server for the path - to it's desktop file. We then turn it into an - app structure and start sucking data out of it. - Mostly the name. And the icon. */ -static void -desktop_cb (IndicateListener * listener, IndicateListenerServer * server, const gchar * value, gpointer data) -{ - g_return_if_fail(IS_APP_MENU_ITEM(data)); - AppMenuItem * self = APP_MENU_ITEM(data); - GDesktopAppInfo *appinfo; - - if (value == NULL || value[0] == '\0') { - return; - } - - appinfo = g_desktop_app_info_new_from_filename(value); - app_menu_item_set_appinfo (self, appinfo); - g_object_unref (appinfo); -} - -/* Relay this signal into causing a rebuild of the shortcuts - from those above us. */ -static void -child_added_cb (DbusmenuMenuitem * root, DbusmenuMenuitem * child, guint position, gpointer data) -{ - g_return_if_fail(IS_APP_MENU_ITEM(data)); - AppMenuItem * self = APP_MENU_ITEM(data); - AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self); - DbusmenuMenuitemProxy * mip = dbusmenu_menuitem_proxy_new(child); - - priv->shortcuts = g_list_insert(priv->shortcuts, mip, position); - - g_signal_emit(G_OBJECT(data), signals[SHORTCUT_ADDED], 0, mip, TRUE); - return; -} - -/* Relay this signal into causing a rebuild of the shortcuts - from those above us. */ -static void -child_removed_cb (DbusmenuMenuitem * root, DbusmenuMenuitem * child, gpointer data) -{ - g_return_if_fail(IS_APP_MENU_ITEM(data)); - AppMenuItem * self = APP_MENU_ITEM(data); - AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self); - - GList * pitems = priv->shortcuts; - while (pitems != NULL) { - DbusmenuMenuitemProxy * mip = DBUSMENU_MENUITEM_PROXY(pitems->data); - - if (dbusmenu_menuitem_proxy_get_wrapped(mip) == child) { - break; - } - - pitems = g_list_next(pitems); - } - - if (pitems != NULL) { - DbusmenuMenuitemProxy * mip = DBUSMENU_MENUITEM_PROXY(pitems->data); - priv->shortcuts = g_list_remove(priv->shortcuts, mip); - - g_signal_emit(G_OBJECT(data), signals[SHORTCUT_REMOVED], 0, mip, TRUE); - g_object_unref(mip); - } - - return; -} - -/* Relay this signal into causing a rebuild of the shortcuts - from those above us. */ -static void -child_moved_cb (DbusmenuMenuitem * root, DbusmenuMenuitem * child, guint newpos, guint oldpos, gpointer data) -{ - g_return_if_fail(IS_APP_MENU_ITEM(data)); - AppMenuItem * self = APP_MENU_ITEM(data); - AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self); - - DbusmenuMenuitemProxy * mip = DBUSMENU_MENUITEM_PROXY(g_list_nth_data(priv->shortcuts, oldpos)); - - if (mip != NULL) { - if (dbusmenu_menuitem_proxy_get_wrapped(mip) != child) { - mip = NULL; - } - } - - if (mip != NULL) { - priv->shortcuts = g_list_remove(priv->shortcuts, mip); - priv->shortcuts = g_list_insert(priv->shortcuts, mip, newpos); - g_signal_emit(G_OBJECT(data), signals[SHORTCUT_ADDED], 0, NULL, TRUE); - } - - return; -} - -/* We've got a new root. We need to proxy it and handle it's children - if that's a relevant thing to do. */ -static void -root_changed (DbusmenuClient * client, DbusmenuMenuitem * newroot, gpointer data) -{ - g_debug("Root Changed"); - AppMenuItem * self = APP_MENU_ITEM(data); - AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self); - - if (priv->root != NULL) { - if (dbusmenu_menuitem_get_children(DBUSMENU_MENUITEM(priv->root)) != NULL) { - g_list_foreach(priv->shortcuts, func_unref, data); - g_list_free(priv->shortcuts); - priv->shortcuts = NULL; - } - g_object_unref(priv->root); - priv->root = NULL; - } - - /* We need to proxy the new root across to the old - world of indicator land. */ - priv->root = newroot; - - if (priv->root != NULL) { - g_object_ref(priv->root); - g_signal_connect(G_OBJECT(priv->root), DBUSMENU_MENUITEM_SIGNAL_CHILD_ADDED, G_CALLBACK(child_added_cb), self); - g_signal_connect(G_OBJECT(priv->root), DBUSMENU_MENUITEM_SIGNAL_CHILD_REMOVED, G_CALLBACK(child_removed_cb), self); - g_signal_connect(G_OBJECT(priv->root), DBUSMENU_MENUITEM_SIGNAL_CHILD_MOVED, G_CALLBACK(child_moved_cb), self); - - /* See if we have any menuitems to worry about, - otherwise we'll just move along. */ - GList * children = dbusmenu_menuitem_get_children(DBUSMENU_MENUITEM(priv->root)); - if (children != NULL) { - g_debug("\tProcessing %d children", g_list_length(children)); - while (children != NULL) { - DbusmenuMenuitemProxy * mip = dbusmenu_menuitem_proxy_new(DBUSMENU_MENUITEM(children->data)); - priv->shortcuts = g_list_append(priv->shortcuts, mip); - g_signal_emit(G_OBJECT(self), signals[SHORTCUT_ADDED], 0, mip, TRUE); - children = g_list_next(children); - } - } - } - - return; -} - -/* Gets the path to menuitems if there are some. Now we need to - make them special. */ -static void -menu_cb (IndicateListener * listener, IndicateListenerServer * server, const gchar * menupath, gpointer data) -{ - g_debug("Got Menu: %s", menupath); - g_return_if_fail(IS_APP_MENU_ITEM(data)); - AppMenuItem * self = APP_MENU_ITEM(data); - AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self); - - priv->client = dbusmenu_client_new(indicate_listener_server_get_dbusname(server), menupath); - g_signal_connect(G_OBJECT(priv->client), DBUSMENU_CLIENT_SIGNAL_ROOT_CHANGED, G_CALLBACK(root_changed), self); + AppMenuItem * mi = APP_MENU_ITEM (userdata); + AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(mi); + GError *error = NULL; - DbusmenuMenuitem * root = dbusmenu_client_get_root(priv->client); - if (root != NULL) { - root_changed(priv->client, root, self); + if (!g_app_info_launch (G_APP_INFO (priv->appinfo), NULL, NULL, &error)) { + g_warning("Unable to execute application for desktop file '%s'", + g_desktop_app_info_get_filename (priv->appinfo)); } - - return; -} - -static void -activate_cb (AppMenuItem * self, guint timestamp, gpointer data) -{ - AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self); - - g_return_if_fail (priv->listener != NULL && priv->server != NULL); - - indicate_listener_display(priv->listener, priv->server, NULL, timestamp); - - return; } guint @@ -589,14 +253,6 @@ app_menu_item_get_count (AppMenuItem * appitem) return priv->unreadcount; } -IndicateListenerServer * -app_menu_item_get_server (AppMenuItem * appitem) { - g_return_val_if_fail(IS_APP_MENU_ITEM(appitem), NULL); - AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(appitem); - - return priv->server; -} - const gchar * app_menu_item_get_name (AppMenuItem * appitem) { @@ -606,9 +262,6 @@ app_menu_item_get_name (AppMenuItem * appitem) if (priv->appinfo) { return g_app_info_get_name(G_APP_INFO(priv->appinfo)); } - else if (priv->server) { - return INDICATE_LISTENER_SERVER_DBUS_NAME(priv->server); - } return NULL; } @@ -623,13 +276,10 @@ app_menu_item_get_desktop (AppMenuItem * appitem) return NULL; } -/* Get the dynamic items added onto the end of - and app entry. */ -GList * -app_menu_item_get_items (AppMenuItem * appitem) +GMenuModel * +app_menu_item_get_menu (AppMenuItem *appitem) { - g_return_val_if_fail(IS_APP_MENU_ITEM(appitem), NULL); AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(appitem); - return g_list_concat (g_list_copy (priv->shortcuts), - g_list_copy (priv->static_shortcuts)); + return G_MENU_MODEL (priv->menu); } + diff --git a/src/app-menu-item.h b/src/app-menu-item.h index 74efb6a..785a997 100644 --- a/src/app-menu-item.h +++ b/src/app-menu-item.h @@ -22,11 +22,7 @@ with this program. If not, see . #ifndef __APP_MENU_ITEM_H__ #define __APP_MENU_ITEM_H__ -#include -#include - -#include -#include +#include G_BEGIN_DECLS @@ -46,27 +42,22 @@ typedef struct _AppMenuItem AppMenuItem; typedef struct _AppMenuItemClass AppMenuItemClass; struct _AppMenuItemClass { - DbusmenuMenuitemClass parent_class; + GObjectClass parent_class; void (* count_changed) (guint count); void (* name_changed) (gchar * name); - void (* shortcut_added) (DbusmenuMenuitem * mi); - void (* shortcut_removed) (DbusmenuMenuitem * mi); }; struct _AppMenuItem { - DbusmenuMenuitem parent; + GObject parent; }; GType app_menu_item_get_type (void); AppMenuItem * app_menu_item_new (GDesktopAppInfo *appinfo); -AppMenuItem * app_menu_item_new_with_server (IndicateListener * listener, IndicateListenerServer * server); -void app_menu_item_set_server (AppMenuItem *self, IndicateListener *listener, IndicateListenerServer *server); guint app_menu_item_get_count (AppMenuItem * appitem); -IndicateListenerServer * app_menu_item_get_server (AppMenuItem * appitem); const gchar * app_menu_item_get_name (AppMenuItem * appitem); const gchar * app_menu_item_get_desktop (AppMenuItem * appitem); -GList * app_menu_item_get_items (AppMenuItem * appitem); +GMenuModel * app_menu_item_get_menu (AppMenuItem *appitem); G_END_DECLS diff --git a/src/dbus-data.h b/src/dbus-data.h index 1e82ded..d7efd86 100644 --- a/src/dbus-data.h +++ b/src/dbus-data.h @@ -25,4 +25,8 @@ have a better place to put it. */ #define ICON_KEY "X-Ayatana-Messaging-Menu-Icon" +#define INDICATOR_MENU_ATTRIBUTE_VISIBLE "indicator-visible" +#define INDICATOR_MENU_ATTRIBUTE_ENABLED "indicator-enabled" +#define INDICATOR_MENU_ATTRIBUTE_ICON_NAME "indicator-icon-name" + #endif /* __DBUS_DATA_H__ */ diff --git a/src/im-menu-item.c b/src/im-menu-item.c deleted file mode 100644 index 7466d3e..0000000 --- a/src/im-menu-item.c +++ /dev/null @@ -1,586 +0,0 @@ -/* -An indicator to show information that is in messaging applications -that the user is using. - -Copyright 2009 Canonical Ltd. - -Authors: - Ted Gould - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program. If not, see . -*/ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include -#include -#include "im-menu-item.h" -#include "dbus-data.h" - -enum { - TIME_CHANGED, - ATTENTION_CHANGED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -typedef struct _ImMenuItemPrivate ImMenuItemPrivate; - -struct _ImMenuItemPrivate -{ - IndicateListener * listener; - IndicateListenerServer * server; - IndicateListenerIndicator * indicator; - - glong creation_seconds; - glong seconds; - gchar * count; - gulong indicator_changed; - gboolean attention; - gboolean show; - - guint time_update_min; -}; - -#define IM_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), IM_MENU_ITEM_TYPE, ImMenuItemPrivate)) - -/* Prototypes */ -static void im_menu_item_class_init (ImMenuItemClass *klass); -static void im_menu_item_init (ImMenuItem *self); -static void im_menu_item_dispose (GObject *object); -static void im_menu_item_finalize (GObject *object); -static void sender_cb (IndicateListener * listener, - IndicateListenerServer * server, - IndicateListenerIndicator * indicator, - gchar * property, - const gchar * propertydata, - gpointer data); -static void time_cb (IndicateListener * listener, - IndicateListenerServer * server, - IndicateListenerIndicator * indicator, - gchar * property, - const GTimeVal * propertydata, - gpointer data); -static void icon_cb (IndicateListener * listener, - IndicateListenerServer * server, - IndicateListenerIndicator * indicator, - gchar * property, - const gchar * propertydata, - gpointer data); -static void activate_cb (ImMenuItem * self, - guint timestamp, - gpointer data); -static void indicator_modified_cb (IndicateListener * listener, - IndicateListenerServer * server, - IndicateListenerIndicator * indicator, - gchar * property, - ImMenuItem * self); - -G_DEFINE_TYPE (ImMenuItem, im_menu_item, DBUSMENU_TYPE_MENUITEM); - -static void -im_menu_item_class_init (ImMenuItemClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (ImMenuItemPrivate)); - - object_class->dispose = im_menu_item_dispose; - object_class->finalize = im_menu_item_finalize; - - signals[TIME_CHANGED] = g_signal_new(IM_MENU_ITEM_SIGNAL_TIME_CHANGED, - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ImMenuItemClass, time_changed), - NULL, NULL, - g_cclosure_marshal_VOID__LONG, - G_TYPE_NONE, 1, G_TYPE_LONG); - signals[ATTENTION_CHANGED] = g_signal_new(IM_MENU_ITEM_SIGNAL_ATTENTION_CHANGED, - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ImMenuItemClass, attention_changed), - NULL, NULL, - g_cclosure_marshal_VOID__BOOLEAN, - G_TYPE_NONE, 1, G_TYPE_BOOLEAN); - - return; -} - -static void -im_menu_item_init (ImMenuItem *self) -{ - g_debug("Building new IM Menu Item"); - ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self); - - /* Set the variables to NULL, but they should be - configured further down the line. */ - priv->listener = NULL; - priv->server = NULL; - priv->indicator = NULL; - - /* A sane default, but look below */ - priv->creation_seconds = 0; - priv->seconds = 0; - - /* Set the seconds to be the time when the item was - created incase we're not given a better time. */ - GTimeVal current_time; - g_get_current_time(¤t_time); - priv->creation_seconds = current_time.tv_sec; - - return; -} - -static void -im_menu_item_dispose (GObject *object) -{ - G_OBJECT_CLASS (im_menu_item_parent_class)->dispose (object); - - ImMenuItem * self = IM_MENU_ITEM(object); - ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self); - - if (priv->time_update_min != 0) { - g_source_remove(priv->time_update_min); - } - - g_signal_handler_disconnect(priv->listener, priv->indicator_changed); - priv->indicator_changed = 0; - - return; -} - -static void -im_menu_item_finalize (GObject *object) -{ - G_OBJECT_CLASS (im_menu_item_parent_class)->finalize (object); -} - -/* Call back for getting icon data. It just passes it along - to the indicator so that it can visualize it. Not our problem. */ -static void -icon_cb (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * property, const gchar * propertydata, gpointer data) -{ - gsize len; - guchar *icon; - icon = g_base64_decode (propertydata, &len); - dbusmenu_menuitem_property_set_byte_array(DBUSMENU_MENUITEM(data), INDICATOR_MENUITEM_PROP_ICON, icon, len); - g_free (icon); - return; -} - -/* This function takes the time and turns it into the appropriate - string to put on the right side of the menu item. Of course it - doesn't do that if there is a count set. If there's a count then - it gets that space. */ -static void -update_time (ImMenuItem * self) -{ - ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self); - - /* Count has been set, so it takes priority. */ - if (priv->count != NULL) { - return; - } - - /* Seconds hasn't been set, so we just want to keep the time - area blank. */ - if (priv->seconds == 0) { - dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), INDICATOR_MENUITEM_PROP_RIGHT, ""); - return; - } - - gchar * timestring = NULL; - - GTimeVal current_time; - g_get_current_time(¤t_time); - - guint elapsed_seconds = current_time.tv_sec - priv->seconds; - guint elapsed_minutes = elapsed_seconds / 60; - - if (elapsed_seconds % 60 > 55) { - /* We're using fuzzy timers, so we need fuzzy comparisons */ - elapsed_minutes += 1; - } - - if (elapsed_minutes < 60) { - /* TRANSLATORS: This string is used to represent the number of minutes - since an IM has occured. It is in the right column - of a menu so being brief is desirable, but one character - is not a requirement. */ - timestring = g_strdup_printf(ngettext("%d m", "%d m", elapsed_minutes), elapsed_minutes); - } else { - guint elapsed_hours = elapsed_minutes / 60; - - if (elapsed_minutes % 60 > 55) { - /* We're using fuzzy timers, so we need fuzzy comparisons */ - elapsed_hours += 1; - } - - /* TRANSLATORS: This string is used to represent the number of hours - since an IM has occured. It is in the right column - of a menu so being brief is desirable, but one character - is not a requirement. */ - timestring = g_strdup_printf(ngettext("%d h", "%d h", elapsed_hours), elapsed_hours); - } - - if (timestring != NULL) { - dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), INDICATOR_MENUITEM_PROP_RIGHT, timestring); - g_free(timestring); - } - - return; -} - -/* This is a wrapper around update_time that matches the prototype - needed to make this a timer callback. Silly. */ -static gboolean -time_update_cb (gpointer data) -{ - ImMenuItem * self = IM_MENU_ITEM(data); - - update_time(self); - - return TRUE; -} - -/* Yet another time function. This one takes the time as formated as - we get it from libindicate and turns it into the seconds that we're - looking for. It should only be called once at the init with a new - indicator and again when the value changes. */ -static void -time_cb (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * property, const GTimeVal * propertydata, gpointer data) -{ - g_debug("Got Time info"); - ImMenuItem * self = IM_MENU_ITEM(data); - if (self == NULL) { - g_error("Menu Item callback called without a menu item"); - return; - } - - if (property == NULL || g_strcmp0(property, "time")) { - g_warning("Time callback called without being sent the time."); - return; - } - - ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self); - - priv->seconds = propertydata->tv_sec; - - update_time(self); - - if (priv->time_update_min == 0) { - priv->time_update_min = g_timeout_add_seconds(60, time_update_cb, self); - } - - g_signal_emit(G_OBJECT(self), signals[TIME_CHANGED], 0, priv->seconds, TRUE); - - return; -} - -/* Returns a newly allocated string which is 'str' with all occurences of - * consecutive whitespace collapsed into single space character. */ -static gchar * -collapse_whitespace (const gchar *str) -{ - GString *result; - gboolean in_space = FALSE; - - if (!str) - return NULL; - - result = g_string_sized_new (strlen (str)); - - while (*str) { - gunichar c = g_utf8_get_char_validated (str, -1); - - if (c < 0) - break; - - if (!g_unichar_isspace (c)) { - g_string_append_unichar (result, c); - in_space = FALSE; - } - else if (!in_space) { - g_string_append_c (result, ' '); - in_space = TRUE; - } - - str = g_utf8_next_char (str); - } - - return g_string_free (result, FALSE); -} - -/* Callback from libindicate that is for getting the sender information - on a particular indicator. */ -static void -sender_cb (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * property, const gchar * propertydata, gpointer data) -{ - gchar *label; - - g_debug("Got Sender Information: %s", propertydata); - ImMenuItem * self = IM_MENU_ITEM(data); - - /* Our data should be right */ - g_return_if_fail(self != NULL); - /* We should have a property name */ - g_return_if_fail(property != NULL); - /* The Property should be sender or name */ - g_return_if_fail(!g_strcmp0(property, "sender") || !g_strcmp0(property, INDICATE_INDICATOR_MESSAGES_PROP_NAME)); - - /* We might get the sender variable returning a - null string as it doesn't exist on newer clients - but we don't want to listen to that. */ - if (!g_strcmp0(property, "sender") && propertydata[0] == '\0') { - return; - } - - label = collapse_whitespace (propertydata); - dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), INDICATOR_MENUITEM_PROP_LABEL, label); - g_free (label); - - return; -} - -/* Callback saying that the count is updated, we need to either put - that on the menu item or just remove it if the count is gone. If - that's the case we can update time. */ -static void -count_cb (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * property, const gchar * propertydata, gpointer data) -{ - g_debug("Got Count Information"); - ImMenuItem * self = IM_MENU_ITEM(data); - - /* Our data should be right */ - g_return_if_fail(self != NULL); - /* We should have a property name */ - g_return_if_fail(property != NULL); - /* The Property should be count */ - g_return_if_fail(!g_strcmp0(property, INDICATE_INDICATOR_MESSAGES_PROP_COUNT)); - - ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self); - - if (propertydata == NULL || propertydata[0] == '\0') { - /* The count is either being unset or it was never - set in the first place. */ - if (priv->count != NULL) { - g_free(priv->count); - priv->count = NULL; - update_time(self); - dbusmenu_menuitem_property_set_bool (DBUSMENU_MENUITEM (self), - INDICATOR_MENUITEM_PROP_RIGHT_IS_LOZENGE, - FALSE); - } - return; - } - - if (priv->count != NULL) { - g_free(priv->count); - } - - priv->count = g_strdup_printf("%s", propertydata); - dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), INDICATOR_MENUITEM_PROP_RIGHT, priv->count); - dbusmenu_menuitem_property_set_bool (DBUSMENU_MENUITEM (self), - INDICATOR_MENUITEM_PROP_RIGHT_IS_LOZENGE, - TRUE); - - return; -} - -/* This is getting the attention variable that's looking at whether - this indicator should be calling for attention or not. If we are, - we need to signal that. */ -static void -attention_cb (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * property, GVariant * propertydata, gpointer data) -{ - g_debug("Got Attention Information"); - ImMenuItem * self = IM_MENU_ITEM(data); - - /* Our data should be right */ - g_return_if_fail(self != NULL); - /* We should have a property name */ - g_return_if_fail(property != NULL); - /* The Property should be count */ - g_return_if_fail(!g_strcmp0(property, INDICATE_INDICATOR_MESSAGES_PROP_ATTENTION)); - - ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self); - - gboolean wantit; - if (g_variant_is_of_type(propertydata, G_VARIANT_TYPE_BOOLEAN)) { - wantit = g_variant_get_boolean(propertydata); - } else if (g_variant_is_of_type(propertydata, G_VARIANT_TYPE_STRING)) { - const gchar * propstring = g_variant_get_string(propertydata, NULL); - - if (propstring == NULL || propstring[0] == '\0' || !g_strcmp0(propstring, "false")) { - wantit = FALSE; - } else { - wantit = TRUE; - } - } else { - g_warning("Got property '%s' of an unknown type.", property); - return; - } - - if (priv->attention != wantit) { - priv->attention = wantit; - g_signal_emit(G_OBJECT(self), signals[ATTENTION_CHANGED], 0, wantit, TRUE); - } - - return; -} - -/* Callback when the item gets clicked on from the Messaging Menu */ -static void -activate_cb (ImMenuItem * self, guint timestamp, gpointer data) -{ - ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self); - - indicate_listener_display(priv->listener, priv->server, priv->indicator, timestamp); -} - -/* Callback when a property gets modified. It figures out which one - got modified and notifies the appropriate person. */ -void -indicator_modified_cb (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * property, ImMenuItem * self) -{ - ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self); - - /* Not meant for us */ - if (INDICATE_LISTENER_INDICATOR_ID(indicator) != INDICATE_LISTENER_INDICATOR_ID(priv->indicator)) return; - if (server != priv->server) return; - - /* Determine which property has been changed and request the - value go to the appropriate callback. */ - if (!g_strcmp0(property, INDICATE_INDICATOR_MESSAGES_PROP_NAME)) { - indicate_listener_get_property(listener, server, indicator, INDICATE_INDICATOR_MESSAGES_PROP_NAME, sender_cb, self); - } else if (!g_strcmp0(property, INDICATE_INDICATOR_MESSAGES_PROP_TIME)) { - indicate_listener_get_property_time(listener, server, indicator, INDICATE_INDICATOR_MESSAGES_PROP_TIME, time_cb, self); - } else if (!g_strcmp0(property, INDICATE_INDICATOR_MESSAGES_PROP_ICON)) { - indicate_listener_get_property(listener, server, indicator, INDICATE_INDICATOR_MESSAGES_PROP_ICON, icon_cb, self); - } else if (!g_strcmp0(property, INDICATE_INDICATOR_MESSAGES_PROP_COUNT)) { - indicate_listener_get_property(listener, server, indicator, INDICATE_INDICATOR_MESSAGES_PROP_COUNT, count_cb, self); - } else if (!g_strcmp0(property, INDICATE_INDICATOR_MESSAGES_PROP_ATTENTION)) { - indicate_listener_get_property_variant(listener, server, indicator, INDICATE_INDICATOR_MESSAGES_PROP_ATTENTION, attention_cb, self); - } else if (!g_strcmp0(property, "sender")) { - /* This is a compatibility string with v1 and should be removed */ - g_debug("Indicator is using 'sender' property which is a v1 string."); - indicate_listener_get_property(listener, server, indicator, "sender", sender_cb, self); - } - - return; -} - -ImMenuItem * -im_menu_item_new (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator) -{ - ImMenuItem * self = g_object_new(IM_MENU_ITEM_TYPE, NULL); - - ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self); - - priv->listener = listener; - priv->server = server; - priv->indicator = indicator; - priv->count = NULL; - priv->time_update_min = 0; - priv->attention = FALSE; - priv->show = TRUE; - - dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), DBUSMENU_MENUITEM_PROP_TYPE, INDICATOR_MENUITEM_TYPE); - - indicate_listener_displayed(listener, server, indicator, TRUE); - - indicate_listener_get_property(listener, server, indicator, INDICATE_INDICATOR_MESSAGES_PROP_NAME, sender_cb, self); - indicate_listener_get_property_time(listener, server, indicator, INDICATE_INDICATOR_MESSAGES_PROP_TIME, time_cb, self); - indicate_listener_get_property(listener, server, indicator, INDICATE_INDICATOR_MESSAGES_PROP_ICON, icon_cb, self); - indicate_listener_get_property(listener, server, indicator, INDICATE_INDICATOR_MESSAGES_PROP_COUNT, count_cb, self); - indicate_listener_get_property_variant(listener, server, indicator, INDICATE_INDICATOR_MESSAGES_PROP_ATTENTION, attention_cb, self); - indicate_listener_get_property(listener, server, indicator, "sender", sender_cb, self); - - g_signal_connect(G_OBJECT(self), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(activate_cb), NULL); - priv->indicator_changed = g_signal_connect(G_OBJECT(listener), INDICATE_LISTENER_SIGNAL_INDICATOR_MODIFIED, G_CALLBACK(indicator_modified_cb), self); - - return self; -} - -/* Gets the number of seconds for the creator - of this item. */ -glong -im_menu_item_get_seconds (ImMenuItem * menuitem) -{ - g_return_val_if_fail(IS_IM_MENU_ITEM(menuitem), 0); - - ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(menuitem); - - if (priv->seconds == 0) { - return priv->creation_seconds; - } else { - return priv->seconds; - } -} - -/* Gets whether or not this indicator item is - asking for attention or not. */ -gboolean -im_menu_item_get_attention (ImMenuItem * menuitem) -{ - g_return_val_if_fail(IS_IM_MENU_ITEM(menuitem), FALSE); - - ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(menuitem); - return priv->attention; -} - -/* This takes care of items that need to be hidden, this is - usually because they go over the count of allowed indicators. - Which is more than a little bit silly. We shouldn't do that. - But we need to enforce it to save users against bad apps. */ -void -im_menu_item_show (ImMenuItem * menuitem, gboolean show) -{ - g_return_if_fail(IS_IM_MENU_ITEM(menuitem)); - - ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(menuitem); - - if (priv->show == show) { - return; - } - - priv->show = show; - /* Tell the app what we're doing to it. If it's being - punished it needs to know about it. */ - indicate_listener_displayed(priv->listener, priv->server, priv->indicator, priv->show); - if (priv->attention) { - /* If we were asking for attention we can ask for it - again if we're being shown, otherwise no. */ - g_signal_emit(G_OBJECT(menuitem), signals[ATTENTION_CHANGED], 0, priv->show, TRUE); - } - dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(menuitem), DBUSMENU_MENUITEM_PROP_VISIBLE, priv->show ? "true" : "false"); - - return; -} - -/* Check to see if this item is shown. Accessor for the - internal variable. */ -gboolean -im_menu_item_shown (ImMenuItem * menuitem) -{ - g_return_val_if_fail(IS_IM_MENU_ITEM(menuitem), FALSE); - - ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(menuitem); - - return priv->show; -} diff --git a/src/im-menu-item.h b/src/im-menu-item.h deleted file mode 100644 index 4279c2e..0000000 --- a/src/im-menu-item.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -An indicator to show information that is in messaging applications -that the user is using. - -Copyright 2009 Canonical Ltd. - -Authors: - Ted Gould - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program. If not, see . -*/ -#ifndef __IM_MENU_ITEM_H__ -#define __IM_MENU_ITEM_H__ - -#include -#include - -#include -#include - -G_BEGIN_DECLS - -#define IM_MENU_ITEM_TYPE (im_menu_item_get_type ()) -#define IM_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), IM_MENU_ITEM_TYPE, ImMenuItem)) -#define IM_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), IM_MENU_ITEM_TYPE, ImMenuItemClass)) -#define IS_IM_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IM_MENU_ITEM_TYPE)) -#define IS_IM_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), IM_MENU_ITEM_TYPE)) -#define IM_MENU_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), IM_MENU_ITEM_TYPE, ImMenuItemClass)) - -#define IM_MENU_ITEM_SIGNAL_TIME_CHANGED "time-changed" -#define IM_MENU_ITEM_SIGNAL_ATTENTION_CHANGED "attention-changed" - -typedef struct _ImMenuItem ImMenuItem; -typedef struct _ImMenuItemClass ImMenuItemClass; - -struct _ImMenuItemClass { - DbusmenuMenuitemClass parent_class; - - void (*time_changed) (glong seconds); - void (*attention_changed) (gboolean requestit); -}; - -struct _ImMenuItem { - DbusmenuMenuitem parent; -}; - -GType im_menu_item_get_type (void); -ImMenuItem * im_menu_item_new (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator); -glong im_menu_item_get_seconds (ImMenuItem * menuitem); -gboolean im_menu_item_get_attention (ImMenuItem * menuitem); -void im_menu_item_show (ImMenuItem * menuitem, gboolean show); -gboolean im_menu_item_shown (ImMenuItem * menuitem); - -G_END_DECLS - -#endif - diff --git a/src/messages-service.c b/src/messages-service.c index 0934b9c..432846e 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -25,46 +25,27 @@ with this program. If not, see . #include #include #include -#include #include #include #include #include -#include -#include - -#include "im-menu-item.h" #include "app-menu-item.h" #include "dbus-data.h" #include "messages-service-dbus.h" #include "status-items.h" static IndicatorService * service = NULL; -static IndicateListener * listener = NULL; static GList * serverList = NULL; -static DbusmenuMenuitem * root_menuitem = NULL; -static DbusmenuMenuitem * status_separator = NULL; -static DbusmenuMenuitem * clear_attention = NULL; +static GDBusConnection *bus; +static GSimpleActionGroup *actions; +static GMenu *menu; static GSettings *settings; 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 gboolean build_launcher (gpointer data); -static gboolean build_launchers (gpointer data); - /* * Server List @@ -72,33 +53,12 @@ static gboolean build_launchers (gpointer data); typedef struct _serverList_t serverList_t; struct _serverList_t { - IndicateListenerServer * server; AppMenuItem * menuitem; - DbusmenuMenuitem * separator; gboolean attention; guint count; GList * imList; }; -static gint -serverList_equal (gconstpointer a, gconstpointer b) -{ - serverList_t * pa, * pb; - - pa = (serverList_t *)a; - pb = (serverList_t *)b; - - 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); - - if (g_strcmp0(pan, pbn) == 0) - return g_strcmp0(pap, pbp); - else - return 1; -} - static gint serverList_sort (gconstpointer a, gconstpointer b) { @@ -113,648 +73,7 @@ serverList_sort (gconstpointer a, gconstpointer b) return g_strcmp0(pan, pbn); } -/* - * 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))); -} - - -/* 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) -{ - 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; -} - -/* 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; - } - - /* 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; - } - } - - /* Nope, no one */ - slt->attention = FALSE; - return; -} - -static void -desktop_cb (IndicateListener *listener, - IndicateListenerServer *server, - const gchar *value, - gpointer data) -{ - DbusmenuMenuitem * menushell = DBUSMENU_MENUITEM(data); - GList *listitem; - serverList_t * sl_item = NULL; - - /* Check to see if we already have a launcher for this app */ - for (listitem = serverList; listitem != NULL; listitem = listitem->next) { - serverList_t * slt = listitem->data; - if (!g_strcmp0(app_menu_item_get_desktop(slt->menuitem), value)) { - sl_item = slt; - break; - } - } - - if (!sl_item) { - /* Build the Menu item */ - AppMenuItem * menuitem = app_menu_item_new_with_server (listener, server); - - /* Build a possible server structure */ - 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; - - /* 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)); - - /* 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); - } - - dbusmenu_menuitem_child_append(menushell, DBUSMENU_MENUITEM(sl_item->separator)); - } - else { - app_menu_item_set_server (sl_item->menuitem, listener, server); - } - - GList * shortcuts = app_menu_item_get_items(sl_item->menuitem); - GList * shortcut = shortcuts; - while (shortcut != NULL) { - DbusmenuMenuitem * mi = DBUSMENU_MENUITEM(shortcut->data); - g_debug("\tAdding shortcut: %s", dbusmenu_menuitem_property_get(mi, DBUSMENU_MENUITEM_PROP_LABEL)); - dbusmenu_menuitem_child_append(menushell, mi); - shortcut = g_list_next(shortcut); - } - g_list_free (shortcuts); - - resort_menu(menushell); -} - -/* 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; - } - - /* fetch the desktop file before creating the menu item, in case we - * already have a launcher for it */ - indicate_listener_server_get_desktop(listener, server, desktop_cb, data); -} - -/* 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) -{ - 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; -} - -/* 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); - resort_menu(DBUSMENU_MENUITEM(data)); - return; -} - -/* 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) -{ - 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; -} - -/* 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) -{ - serverList_t * sl = (serverList_t *)data; - sl->imList = g_list_sort(sl->imList, imList_sort); - resort_menu(root_menuitem); - return; -} - -/* 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) -{ - 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; -} - -/* 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) -{ - /* 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); - } - - /* Remove from the server list */ - serverList = g_list_remove(serverList, sltp); - - /* 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); - GList * shortcut = shortcuts; - while (shortcut != NULL) { - g_debug("\tRemoving shortcut: %s", dbusmenu_menuitem_property_get(DBUSMENU_MENUITEM(shortcut->data), DBUSMENU_MENUITEM_PROP_LABEL)); - dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(shortcut->data), DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); - dbusmenu_menuitem_child_delete(DBUSMENU_MENUITEM(data), DBUSMENU_MENUITEM(shortcut->data)); - shortcut = g_list_next(shortcut); - } - g_list_free (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(); - } - - g_free(sltp); - - return; -} - -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)))) { - GList *shortcuts = app_menu_item_get_items(appmenu); - msl->found = TRUE; - /* Return a position at the end of our shortcuts */ - msl->position += g_list_length(shortcuts); - g_list_free (shortcuts); - - } else { - msl->position++; - } - - return; -} - -/* 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; - - 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); - } - - for (serverentry = serverList; serverentry != NULL; serverentry = serverentry->next) { - serverList_t * si = (serverList_t *)serverentry->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); - GList * shortcut = shortcuts; - while (shortcut != NULL) { - g_debug("\t\tMoving shortcut to position %d", position); - dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(shortcut->data), position); - position++; - shortcut = g_list_next(shortcut); - } - g_list_free (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 (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"); - 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; - } - - /* 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); - } - } - - /* 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; -} - -/* 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) -{ - g_debug("Removing %s %d", INDICATE_LISTENER_SERVER_DBUS_NAME(server), INDICATE_LISTENER_INDICATOR_ID(indicator)); - - gboolean removed = FALSE; - - /* 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; -} - -/* This function turns a specific file into a menu +/* This function turns a specific desktop id into a menu item and registers it appropriately with everyone */ static gboolean build_launcher (gpointer data) @@ -780,26 +99,12 @@ build_launcher (gpointer data) serverList_t * sl_item = g_new0(serverList_t, 1); sl_item->menuitem = app_menu_item_new(appinfo); - /* Build a separator */ - sl_item->separator = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set(sl_item->separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); - - /* Add it to the list */ serverList = g_list_insert_sorted (serverList, sl_item, serverList_sort); - /* Add it to the menu */ - dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(sl_item->menuitem), DBUSMENU_MENUITEM_PROP_TYPE, APPLICATION_MENUITEM_TYPE); - dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(sl_item->menuitem)); - GList * shortcuts = app_menu_item_get_items(sl_item->menuitem); - GList * shortcut = shortcuts; - while (shortcut != NULL) { - dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(shortcut->data)); - shortcut = g_list_next(shortcut); - } - g_list_free (shortcuts); - dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(sl_item->separator)); - - resort_menu(root_menuitem); + /* TODO insert it at the right position (alphabetically by application name) */ + g_menu_insert_section (menu, 2, + app_menu_item_get_name (sl_item->menuitem), + app_menu_item_get_menu (sl_item->menuitem)); } g_object_unref (appinfo); @@ -838,36 +143,34 @@ service_shutdown (IndicatorService * service, gpointer user_data) return; } -/* Respond to changing status by updating the icon that - is on the panel */ static void -status_update_callback (void) +clear_action_activate (GSimpleAction *simple, + GVariant *param, + gpointer user_data) { - return; + MessageServiceDbus *msg_service = user_data; + message_service_dbus_set_attention(msg_service, FALSE); } -/* The clear attention item has been clicked on, what to do? */ static void -clear_attention_activate (DbusmenuMenuitem * mi, guint timestamp, MessageServiceDbus * dbus) +clear_action_handler (MessageServiceDbus *msd, + gboolean attention, + gpointer user_data) { - message_service_dbus_set_attention(dbus, FALSE); - return; + GSimpleAction *action = user_data; + g_simple_action_set_enabled (action, attention); } -/* 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) { + GError *error = NULL; + GActionEntry entries[] = { + { "status", NULL, "s", "'offline'", NULL }, + { "clear", clear_action_activate } + }; + GMenuModel *status_items; + /* Glib init */ g_type_init(); @@ -884,36 +187,40 @@ main (int argc, char ** argv) /* 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); + bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); + if (!bus) { + g_warning ("unable to connect to the session bus: %s", error->message); + g_error_free (error); + return 1; + } + + actions = g_simple_action_group_new (); + g_simple_action_group_add_entries (actions, entries, G_N_ELEMENTS (entries), NULL); + g_dbus_connection_export_action_group (bus, INDICATOR_MESSAGES_DBUS_OBJECT, + G_ACTION_GROUP (actions), &error); + if (error) { + g_warning ("unable to export action group on dbus: %s", error->message); + g_error_free (error); + return 1; + } + + g_signal_connect (dbus_interface, MESSAGE_SERVICE_DBUS_SIGNAL_ATTENTION_CHANGED, + G_CALLBACK(clear_action_handler), + g_action_map_lookup_action (G_ACTION_MAP (actions), "clear")); + + status_items = status_items_build (g_action_map_lookup_action (G_ACTION_MAP (actions), "status")); + + menu = g_menu_new (); + g_menu_append_section (menu, _("Status"), status_items); + g_menu_append (menu, _("Clear"), "clear"); - /* 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); + g_dbus_connection_export_menu_model (bus, INDICATOR_MESSAGES_DBUS_OBJECT, + G_MENU_MODEL (menu), &error); + if (error) { + g_warning ("unable to export menu on dbus: %s", error->message); + g_error_free (error); + return 1; } - 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); settings = g_settings_new ("com.canonical.indicator.messages"); diff --git a/src/status-items.c b/src/status-items.c index 70a2ad9..a2e3a02 100644 --- a/src/status-items.c +++ b/src/status-items.c @@ -22,10 +22,19 @@ with this program. If not, see . #include #include #include -#include #include "status-items.h" #include "status-provider.h" +#include "dbus-data.h" + +static const gchar * status_ids [STATUS_PROVIDER_STATUS_LAST] = { + /* STATUS_PROVIDER_STATUS_ONLINE, */ "available", + /* STATUS_PROVIDER_STATUS_AWAY, */ "away", + /* STATUS_PROVIDER_STATUS_DND */ "busy", + /* STATUS_PROVIDER_STATUS_INVISIBLE */ "invisible", + /* STATUS_PROVIDER_STATUS_OFFLINE, */ "offline", + /* STATUS_PROVIDER_STATUS_DISCONNECTED*/ "offline" +}; static const gchar * status_strings [STATUS_PROVIDER_STATUS_LAST] = { /* STATUS_PROVIDER_STATUS_ONLINE, */ N_("Available"), @@ -66,39 +75,40 @@ static const gchar * panel_active_icons[STATUS_PROVIDER_STATUS_LAST] = { /* Prototypes */ static gboolean provider_directory_parse (gpointer dir); static gboolean load_status_provider (gpointer dir); -static void user_status_change (DbusmenuMenuitem * item, guint timestamp, gpointer pstatus); +static void user_status_change (GSimpleAction *action, + GVariant *value, + gpointer user_data); /* Globals */ static StatusProviderStatus current_status = STATUS_PROVIDER_STATUS_DISCONNECTED; -static GList * menuitems = NULL; +static GMenu * menu; +static GAction *status_action; static GList * status_providers = NULL; -static StatusUpdateFunc update_func = NULL; /* Build the inital status items and start kicking off the async code for handling all the statuses */ -GList * -status_items_build (StatusUpdateFunc status_update_func) +GMenuModel * +status_items_build (GAction *action) { int i; - for (i = STATUS_PROVIDER_STATUS_ONLINE; i < STATUS_PROVIDER_STATUS_DISCONNECTED; i++) { - DbusmenuMenuitem * item = dbusmenu_menuitem_new(); + menu = g_menu_new (); - dbusmenu_menuitem_property_set(item, DBUSMENU_MENUITEM_PROP_LABEL, _(status_strings[i])); - dbusmenu_menuitem_property_set(item, DBUSMENU_MENUITEM_PROP_ICON_NAME, status_icons[i]); + status_action = action; + g_signal_connect (action, "change-state", G_CALLBACK (user_status_change), NULL); - dbusmenu_menuitem_property_set_bool(item, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); - dbusmenu_menuitem_property_set_bool(item, DBUSMENU_MENUITEM_PROP_ENABLED, FALSE); + for (i = STATUS_PROVIDER_STATUS_ONLINE; i < STATUS_PROVIDER_STATUS_DISCONNECTED; i++) { + GMenuItem *item = g_menu_item_new (_(status_strings[i]), NULL); - dbusmenu_menuitem_property_set(item, DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE, DBUSMENU_MENUITEM_TOGGLE_RADIO); - dbusmenu_menuitem_property_set(item, DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED); + g_menu_item_set_action_and_target (item, g_action_get_name (action), "s", status_ids[i]); - g_signal_connect(G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(user_status_change), GINT_TO_POINTER(i)); + g_menu_item_set_attribute (item, INDICATOR_MENU_ATTRIBUTE_ICON_NAME, "s", status_icons[i]); + g_menu_item_set_attribute (item, INDICATOR_MENU_ATTRIBUTE_VISIBLE, "b", TRUE); + g_menu_item_set_attribute (item, INDICATOR_MENU_ATTRIBUTE_ENABLED, "b", FALSE); - menuitems = g_list_append(menuitems, item); + g_menu_append_item (menu, item); + g_object_unref (item); } - update_func = status_update_func; - const gchar * status_providers_env = g_getenv("INDICATOR_MESSAGES_STATUS_PROVIDER_DIR"); if (status_providers_env == NULL) { g_idle_add(provider_directory_parse, STATUS_PROVIDER_DIR); @@ -106,7 +116,7 @@ status_items_build (StatusUpdateFunc status_update_func) g_idle_add(provider_directory_parse, (gpointer)status_providers_env); } - return menuitems; + return G_MENU_MODEL (menu); } /* Clean up our globals and stop with all this allocation @@ -155,38 +165,33 @@ update_status (void) current_status = status; - if (update_func != NULL) { - update_func(); - } - - GList * menu; - int i; - for (menu = menuitems, i = 0; menu != NULL && i < STATUS_PROVIDER_STATUS_DISCONNECTED; menu = g_list_next(menu), i++) { - /* If we're the seleced status or if we're disconnected - show the user that we're offline */ - if (i == current_status || (current_status == STATUS_PROVIDER_STATUS_DISCONNECTED && i == STATUS_PROVIDER_STATUS_OFFLINE)) { - dbusmenu_menuitem_property_set_int(DBUSMENU_MENUITEM(menu->data), DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED); - } else { - dbusmenu_menuitem_property_set_int(DBUSMENU_MENUITEM(menu->data), DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED); - } - - if (current_status == STATUS_PROVIDER_STATUS_DISCONNECTED) { - dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(menu->data), DBUSMENU_MENUITEM_PROP_ENABLED, FALSE); - } else { - dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(menu->data), DBUSMENU_MENUITEM_PROP_ENABLED, TRUE); - } - } + g_action_change_state (status_action, g_variant_new_string (status_ids[current_status])); return; } /* Handle the user requesting a status change */ static void -user_status_change (DbusmenuMenuitem * item, guint timestamp, gpointer pstatus) +user_status_change (GSimpleAction *action, + GVariant *value, + gpointer user_data) { - StatusProviderStatus status = GPOINTER_TO_INT(pstatus); + const gchar *status_id; + int i; + StatusProviderStatus status = STATUS_PROVIDER_STATUS_DISCONNECTED; GList * provider; + g_return_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)); + + status_id = g_variant_get_string (value, NULL); + + for (i = STATUS_PROVIDER_STATUS_ONLINE; i < STATUS_PROVIDER_STATUS_DISCONNECTED; i++) { + if (!strcmp (status_id, status_ids [i])) { + status = i; + break; + } + } + /* Set each provider to this status */ for (provider = status_providers; provider != NULL; provider = g_list_next(provider)) { status_provider_set_status(STATUS_PROVIDER(provider->data), status); diff --git a/src/status-items.h b/src/status-items.h index fe7900c..ff35dfc 100644 --- a/src/status-items.h +++ b/src/status-items.h @@ -26,9 +26,7 @@ with this program. If not, see . G_BEGIN_DECLS -typedef void (*StatusUpdateFunc) (void); - -GList * status_items_build (StatusUpdateFunc update_func); +GMenuModel * status_items_build (GAction *action); const gchar * status_current_panel_icon (gboolean alert); void status_items_cleanup (void); diff --git a/test/Makefile.am b/test/Makefile.am index bb58ab2..847d857 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -40,7 +40,6 @@ lib_LTLIBRARIES = \ libindicator_messages_service_la_HEADERS = \ $(top_srcdir)/src/gen-messages-service.xml.h \ - $(top_srcdir)/src/im-menu-item.h \ $(top_srcdir)/src/app-menu-item.h \ $(top_srcdir)/src/dbus-data.h \ $(top_srcdir)/src/status-items.h @@ -49,7 +48,6 @@ libindicator_messages_service_la_SOURCES = \ $(top_srcdir)/src/messages-service.c \ $(top_srcdir)/src/messages-service-dbus.c \ $(top_srcdir)/src/gen-messages-service.xml.c \ - $(top_srcdir)/src/im-menu-item.c \ $(top_srcdir)/src/app-menu-item.c \ $(top_srcdir)/src/status-items.c -- cgit v1.2.3 From 4f2dd60a130dcaeb4378219baca1f3d4e9637824 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Thu, 31 May 2012 18:55:06 +0200 Subject: Rename AppMenuItem to AppSection --- po/POTFILES.in | 3 - src/Makefile.am | 4 +- src/app-menu-item.c | 322 ------------------------------------------------- src/app-menu-item.h | 58 --------- src/app-section.c | 321 ++++++++++++++++++++++++++++++++++++++++++++++++ src/app-section.h | 58 +++++++++ src/messages-service.c | 18 +-- test/Makefile.am | 4 +- 8 files changed, 392 insertions(+), 396 deletions(-) delete mode 100644 src/app-menu-item.c delete mode 100644 src/app-menu-item.h create mode 100644 src/app-section.c create mode 100644 src/app-section.h (limited to 'test') diff --git a/po/POTFILES.in b/po/POTFILES.in index 051f8f3..2d93682 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -3,7 +3,4 @@ src/messages-service-dbus.c src/indicator-messages.c src/messages-service.c src/default-applications.c -src/launcher-menu-item.c -src/im-menu-item.c -src/app-menu-item.c src/status-items.c diff --git a/src/Makefile.am b/src/Makefile.am index 2527878..1dbb514 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -42,8 +42,8 @@ indicator_messages_service_SOURCES = \ messages-service-dbus.h \ gen-messages-service.xml.h \ gen-messages-service.xml.c \ - app-menu-item.c \ - app-menu-item.h \ + app-section.c \ + app-section.h \ dbus-data.h \ \ status-items.c \ diff --git a/src/app-menu-item.c b/src/app-menu-item.c deleted file mode 100644 index 7638eb5..0000000 --- a/src/app-menu-item.c +++ /dev/null @@ -1,322 +0,0 @@ -/* -An indicator to show information that is in messaging applications -that the user is using. - -Copyright 2009 Canonical Ltd. - -Authors: - Ted Gould - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program. If not, see . -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include -#include "app-menu-item.h" -#include "dbus-data.h" - -typedef struct _AppMenuItemPrivate AppMenuItemPrivate; - -struct _AppMenuItemPrivate -{ - GDesktopAppInfo * appinfo; - guint unreadcount; - - IndicatorDesktopShortcuts * ids; - - GMenu *menu; - GSimpleActionGroup *static_shortcuts; -}; - -#define APP_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), APP_MENU_ITEM_TYPE, AppMenuItemPrivate)) - -enum { - PROP_0, - PROP_APPINFO, - NUM_PROPERTIES -}; - -static GParamSpec *properties[NUM_PROPERTIES]; - -/* Prototypes */ -static void app_menu_item_class_init (AppMenuItemClass *klass); -static void app_menu_item_init (AppMenuItem *self); -static void app_menu_item_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec); -static void app_menu_item_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec); -static void app_menu_item_dispose (GObject *object); -static void activate_cb (GSimpleAction *action, - GVariant *param, - gpointer userdata); -static void app_menu_item_set_app_info (AppMenuItem *self, - GDesktopAppInfo *appinfo); - -/* GObject Boilerplate */ -G_DEFINE_TYPE (AppMenuItem, app_menu_item, G_TYPE_OBJECT); - -static void -app_menu_item_class_init (AppMenuItemClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (AppMenuItemPrivate)); - - object_class->get_property = app_menu_item_get_property; - object_class->set_property = app_menu_item_set_property; - object_class->dispose = app_menu_item_dispose; - - properties[PROP_APPINFO] = g_param_spec_object ("app-info", - "AppInfo", - "The GAppInfo for the app that this menu represents", - G_TYPE_APP_INFO, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - - g_object_class_install_properties (object_class, NUM_PROPERTIES, properties); -} - -static void -app_menu_item_init (AppMenuItem *self) -{ - g_debug("Building new App Menu Item"); - AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self); - - priv->appinfo = NULL; - priv->unreadcount = 0; - - priv->menu = g_menu_new (); - priv->static_shortcuts = g_simple_action_group_new (); - - return; -} - -static void -app_menu_item_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - AppMenuItem *self = APP_MENU_ITEM (object); - - switch (property_id) - { - case PROP_APPINFO: - g_value_set_object (value, app_menu_item_get_app_info (self)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} - -static void -app_menu_item_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - AppMenuItem *self = APP_MENU_ITEM (object); - - switch (property_id) - { - case PROP_APPINFO: - app_menu_item_set_app_info (self, g_value_get_object (value)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} -static void -app_menu_item_dispose (GObject *object) -{ - AppMenuItem * self = APP_MENU_ITEM(object); - AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self); - - g_clear_object (&priv->menu); - g_clear_object (&priv->static_shortcuts); - - if (priv->ids != NULL) { - g_object_unref(priv->ids); - priv->ids = NULL; - } - - if (priv->appinfo != NULL) { - g_object_unref(priv->appinfo); - priv->appinfo = NULL; - } - - G_OBJECT_CLASS (app_menu_item_parent_class)->dispose (object); -} - -/* Respond to one of the shortcuts getting clicked on. */ -static void -nick_activate_cb (GSimpleAction *action, - GVariant *param, - gpointer userdata) -{ - const gchar * nick = g_action_get_name (G_ACTION (action)); - AppMenuItem * mi = APP_MENU_ITEM (userdata); - AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(mi); - - g_return_if_fail(priv->ids != NULL); - - if (!indicator_desktop_shortcuts_nick_exec(priv->ids, nick)) { - g_warning("Unable to execute nick '%s' for desktop file '%s'", - nick, g_desktop_app_info_get_filename (priv->appinfo)); - } -} - -static void -app_menu_item_set_app_info (AppMenuItem *self, - GDesktopAppInfo *appinfo) -{ - AppMenuItemPrivate *priv = APP_MENU_ITEM_GET_PRIVATE (self); - GSimpleAction *launch; - GMenuItem *menuitem; - GIcon *icon; - gchar *iconstr = NULL; - gchar *label; - - g_return_if_fail (priv->appinfo == NULL); - - if (appinfo == NULL) { - g_warning ("appinfo must not be NULL"); - return; - } - - priv->appinfo = g_object_ref (appinfo); - - icon = g_app_info_get_icon (G_APP_INFO(priv->appinfo)); - iconstr = g_icon_to_string (icon); - - launch = g_simple_action_new ("launch", NULL); - g_signal_connect (launch, "activate", G_CALLBACK (activate_cb), self); - g_simple_action_group_insert (priv->static_shortcuts, G_ACTION (launch)); - - if (priv->unreadcount > 0) - label = g_strdup_printf("%s (%d)", app_menu_item_get_name (self), priv->unreadcount); - else - label = g_strdup(app_menu_item_get_name (self)); - - menuitem = g_menu_item_new (label, "launch"); - g_menu_item_set_attribute (menuitem, INDICATOR_MENU_ATTRIBUTE_ICON_NAME, "s", iconstr); - g_menu_append_item (priv->menu, menuitem); - - /* Start to build static shortcuts */ - priv->ids = indicator_desktop_shortcuts_new(g_desktop_app_info_get_filename (priv->appinfo), "Messaging Menu"); - const gchar ** nicks = indicator_desktop_shortcuts_get_nicks(priv->ids); - gint i; - for (i = 0; nicks[i] != NULL; i++) { - gchar *name; - GSimpleAction *action; - GMenuItem *item; - - name = indicator_desktop_shortcuts_nick_get_name(priv->ids, nicks[i]); - - action = g_simple_action_new (name, NULL); - g_signal_connect(action, "activate", G_CALLBACK (nick_activate_cb), self); - g_simple_action_group_insert (priv->static_shortcuts, G_ACTION (action)); - - item = g_menu_item_new (name, name); - g_menu_append_item (priv->menu, item); - - g_object_unref (item); - g_free(name); - } - - g_free(label); - g_free(iconstr); - g_object_unref (launch); - g_object_unref (menuitem); -} - -AppMenuItem * -app_menu_item_new (GDesktopAppInfo *appinfo) -{ - return g_object_new (APP_MENU_ITEM_TYPE, - "app-info", appinfo, - NULL); -} - -static void -activate_cb (GSimpleAction *action, - GVariant *param, - gpointer userdata) -{ - AppMenuItem * mi = APP_MENU_ITEM (userdata); - AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(mi); - GError *error = NULL; - - if (!g_app_info_launch (G_APP_INFO (priv->appinfo), NULL, NULL, &error)) { - g_warning("Unable to execute application for desktop file '%s'", - g_desktop_app_info_get_filename (priv->appinfo)); - } -} - -guint -app_menu_item_get_count (AppMenuItem * appitem) -{ - g_return_val_if_fail(IS_APP_MENU_ITEM(appitem), 0); - AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(appitem); - - return priv->unreadcount; -} - -const gchar * -app_menu_item_get_name (AppMenuItem * appitem) -{ - g_return_val_if_fail(IS_APP_MENU_ITEM(appitem), NULL); - AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(appitem); - - if (priv->appinfo) { - return g_app_info_get_name(G_APP_INFO(priv->appinfo)); - } - return NULL; -} - -const gchar * -app_menu_item_get_desktop (AppMenuItem * appitem) -{ - g_return_val_if_fail(IS_APP_MENU_ITEM(appitem), NULL); - AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(appitem); - if (priv->appinfo) - return g_desktop_app_info_get_filename (priv->appinfo); - else - return NULL; -} - -GMenuModel * -app_menu_item_get_menu (AppMenuItem *appitem) -{ - AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(appitem); - return G_MENU_MODEL (priv->menu); -} - -GAppInfo * -app_menu_item_get_app_info (AppMenuItem *appitem) -{ - AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(appitem); - return G_APP_INFO (priv->appinfo); -} - diff --git a/src/app-menu-item.h b/src/app-menu-item.h deleted file mode 100644 index 1fb2762..0000000 --- a/src/app-menu-item.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -An indicator to show information that is in messaging applications -that the user is using. - -Copyright 2009 Canonical Ltd. - -Authors: - Ted Gould - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program. If not, see . -*/ -#ifndef __APP_MENU_ITEM_H__ -#define __APP_MENU_ITEM_H__ - -#include - -G_BEGIN_DECLS - -#define APP_MENU_ITEM_TYPE (app_menu_item_get_type ()) -#define APP_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), APP_MENU_ITEM_TYPE, AppMenuItem)) -#define APP_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), APP_MENU_ITEM_TYPE, AppMenuItemClass)) -#define IS_APP_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), APP_MENU_ITEM_TYPE)) -#define IS_APP_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), APP_MENU_ITEM_TYPE)) -#define APP_MENU_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), APP_MENU_ITEM_TYPE, AppMenuItemClass)) - -typedef struct _AppMenuItem AppMenuItem; -typedef struct _AppMenuItemClass AppMenuItemClass; - -struct _AppMenuItemClass { - GObjectClass parent_class; -}; - -struct _AppMenuItem { - GObject parent; -}; - -GType app_menu_item_get_type (void); -AppMenuItem * app_menu_item_new (GDesktopAppInfo *appinfo); -guint app_menu_item_get_count (AppMenuItem * appitem); -const gchar * app_menu_item_get_name (AppMenuItem * appitem); -const gchar * app_menu_item_get_desktop (AppMenuItem * appitem); -GMenuModel * app_menu_item_get_menu (AppMenuItem *appitem); -GAppInfo * app_menu_item_get_app_info (AppMenuItem *appitem); - -G_END_DECLS - -#endif /* __APP_MENU_ITEM_H__ */ - diff --git a/src/app-section.c b/src/app-section.c new file mode 100644 index 0000000..5a5e838 --- /dev/null +++ b/src/app-section.c @@ -0,0 +1,321 @@ +/* +An indicator to show information that is in messaging applications +that the user is using. + +Copyright 2009 Canonical Ltd. + +Authors: + Ted Gould + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published +by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR +PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program. If not, see . +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include "app-section.h" +#include "dbus-data.h" + +typedef struct _AppSectionPrivate AppSectionPrivate; + +struct _AppSectionPrivate +{ + GDesktopAppInfo * appinfo; + guint unreadcount; + + IndicatorDesktopShortcuts * ids; + + GMenu *menu; + GSimpleActionGroup *static_shortcuts; +}; + +#define APP_SECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), APP_SECTION_TYPE, AppSectionPrivate)) + +enum { + PROP_0, + PROP_APPINFO, + NUM_PROPERTIES +}; + +static GParamSpec *properties[NUM_PROPERTIES]; + +/* Prototypes */ +static void app_section_class_init (AppSectionClass *klass); +static void app_section_init (AppSection *self); +static void app_section_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); +static void app_section_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void app_section_dispose (GObject *object); +static void activate_cb (GSimpleAction *action, + GVariant *param, + gpointer userdata); +static void app_section_set_app_info (AppSection *self, + GDesktopAppInfo *appinfo); + +/* GObject Boilerplate */ +G_DEFINE_TYPE (AppSection, app_section, G_TYPE_OBJECT); + +static void +app_section_class_init (AppSectionClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (AppSectionPrivate)); + + object_class->get_property = app_section_get_property; + object_class->set_property = app_section_set_property; + object_class->dispose = app_section_dispose; + + properties[PROP_APPINFO] = g_param_spec_object ("app-info", + "AppInfo", + "The GAppInfo for the app that this menu represents", + G_TYPE_APP_INFO, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + + g_object_class_install_properties (object_class, NUM_PROPERTIES, properties); +} + +static void +app_section_init (AppSection *self) +{ + AppSectionPrivate * priv = APP_SECTION_GET_PRIVATE(self); + + priv->appinfo = NULL; + priv->unreadcount = 0; + + priv->menu = g_menu_new (); + priv->static_shortcuts = g_simple_action_group_new (); + + return; +} + +static void +app_section_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + AppSection *self = APP_SECTION (object); + + switch (property_id) + { + case PROP_APPINFO: + g_value_set_object (value, app_section_get_app_info (self)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +app_section_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + AppSection *self = APP_SECTION (object); + + switch (property_id) + { + case PROP_APPINFO: + app_section_set_app_info (self, g_value_get_object (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} +static void +app_section_dispose (GObject *object) +{ + AppSection * self = APP_SECTION(object); + AppSectionPrivate * priv = APP_SECTION_GET_PRIVATE(self); + + g_clear_object (&priv->menu); + g_clear_object (&priv->static_shortcuts); + + if (priv->ids != NULL) { + g_object_unref(priv->ids); + priv->ids = NULL; + } + + if (priv->appinfo != NULL) { + g_object_unref(priv->appinfo); + priv->appinfo = NULL; + } + + G_OBJECT_CLASS (app_section_parent_class)->dispose (object); +} + +/* Respond to one of the shortcuts getting clicked on. */ +static void +nick_activate_cb (GSimpleAction *action, + GVariant *param, + gpointer userdata) +{ + const gchar * nick = g_action_get_name (G_ACTION (action)); + AppSection * mi = APP_SECTION (userdata); + AppSectionPrivate * priv = APP_SECTION_GET_PRIVATE(mi); + + g_return_if_fail(priv->ids != NULL); + + if (!indicator_desktop_shortcuts_nick_exec(priv->ids, nick)) { + g_warning("Unable to execute nick '%s' for desktop file '%s'", + nick, g_desktop_app_info_get_filename (priv->appinfo)); + } +} + +static void +app_section_set_app_info (AppSection *self, + GDesktopAppInfo *appinfo) +{ + AppSectionPrivate *priv = APP_SECTION_GET_PRIVATE (self); + GSimpleAction *launch; + GMenuItem *menuitem; + GIcon *icon; + gchar *iconstr = NULL; + gchar *label; + + g_return_if_fail (priv->appinfo == NULL); + + if (appinfo == NULL) { + g_warning ("appinfo must not be NULL"); + return; + } + + priv->appinfo = g_object_ref (appinfo); + + icon = g_app_info_get_icon (G_APP_INFO(priv->appinfo)); + iconstr = g_icon_to_string (icon); + + launch = g_simple_action_new ("launch", NULL); + g_signal_connect (launch, "activate", G_CALLBACK (activate_cb), self); + g_simple_action_group_insert (priv->static_shortcuts, G_ACTION (launch)); + + if (priv->unreadcount > 0) + label = g_strdup_printf("%s (%d)", app_section_get_name (self), priv->unreadcount); + else + label = g_strdup(app_section_get_name (self)); + + menuitem = g_menu_item_new (label, "launch"); + g_menu_item_set_attribute (menuitem, INDICATOR_MENU_ATTRIBUTE_ICON_NAME, "s", iconstr); + g_menu_append_item (priv->menu, menuitem); + + /* Start to build static shortcuts */ + priv->ids = indicator_desktop_shortcuts_new(g_desktop_app_info_get_filename (priv->appinfo), "Messaging Menu"); + const gchar ** nicks = indicator_desktop_shortcuts_get_nicks(priv->ids); + gint i; + for (i = 0; nicks[i] != NULL; i++) { + gchar *name; + GSimpleAction *action; + GMenuItem *item; + + name = indicator_desktop_shortcuts_nick_get_name(priv->ids, nicks[i]); + + action = g_simple_action_new (name, NULL); + g_signal_connect(action, "activate", G_CALLBACK (nick_activate_cb), self); + g_simple_action_group_insert (priv->static_shortcuts, G_ACTION (action)); + + item = g_menu_item_new (name, name); + g_menu_append_item (priv->menu, item); + + g_object_unref (item); + g_free(name); + } + + g_free(label); + g_free(iconstr); + g_object_unref (launch); + g_object_unref (menuitem); +} + +AppSection * +app_section_new (GDesktopAppInfo *appinfo) +{ + return g_object_new (APP_SECTION_TYPE, + "app-info", appinfo, + NULL); +} + +static void +activate_cb (GSimpleAction *action, + GVariant *param, + gpointer userdata) +{ + AppSection * mi = APP_SECTION (userdata); + AppSectionPrivate * priv = APP_SECTION_GET_PRIVATE(mi); + GError *error = NULL; + + if (!g_app_info_launch (G_APP_INFO (priv->appinfo), NULL, NULL, &error)) { + g_warning("Unable to execute application for desktop file '%s'", + g_desktop_app_info_get_filename (priv->appinfo)); + } +} + +guint +app_section_get_count (AppSection * self) +{ + g_return_val_if_fail(IS_APP_SECTION(self), 0); + AppSectionPrivate * priv = APP_SECTION_GET_PRIVATE(self); + + return priv->unreadcount; +} + +const gchar * +app_section_get_name (AppSection * self) +{ + g_return_val_if_fail(IS_APP_SECTION(self), NULL); + AppSectionPrivate * priv = APP_SECTION_GET_PRIVATE(self); + + if (priv->appinfo) { + return g_app_info_get_name(G_APP_INFO(priv->appinfo)); + } + return NULL; +} + +const gchar * +app_section_get_desktop (AppSection * self) +{ + g_return_val_if_fail(IS_APP_SECTION(self), NULL); + AppSectionPrivate * priv = APP_SECTION_GET_PRIVATE(self); + if (priv->appinfo) + return g_desktop_app_info_get_filename (priv->appinfo); + else + return NULL; +} + +GMenuModel * +app_section_get_menu (AppSection *self) +{ + AppSectionPrivate * priv = APP_SECTION_GET_PRIVATE(self); + return G_MENU_MODEL (priv->menu); +} + +GAppInfo * +app_section_get_app_info (AppSection *self) +{ + AppSectionPrivate * priv = APP_SECTION_GET_PRIVATE(self); + return G_APP_INFO (priv->appinfo); +} + diff --git a/src/app-section.h b/src/app-section.h new file mode 100644 index 0000000..7989824 --- /dev/null +++ b/src/app-section.h @@ -0,0 +1,58 @@ +/* +An indicator to show information that is in messaging applications +that the user is using. + +Copyright 2009 Canonical Ltd. + +Authors: + Ted Gould + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published +by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR +PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program. If not, see . +*/ +#ifndef __APP_SECTION_H__ +#define __APP_SECTION_H__ + +#include + +G_BEGIN_DECLS + +#define APP_SECTION_TYPE (app_section_get_type ()) +#define APP_SECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), APP_SECTION_TYPE, AppSection)) +#define APP_SECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), APP_SECTION_TYPE, AppSectionClass)) +#define IS_APP_SECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), APP_SECTION_TYPE)) +#define IS_APP_SECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), APP_SECTION_TYPE)) +#define APP_SECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), APP_SECTION_TYPE, AppSectionClass)) + +typedef struct _AppSection AppSection; +typedef struct _AppSectionClass AppSectionClass; + +struct _AppSectionClass { + GObjectClass parent_class; +}; + +struct _AppSection { + GObject parent; +}; + +GType app_section_get_type (void); +AppSection * app_section_new (GDesktopAppInfo *appinfo); +guint app_section_get_count (AppSection * appitem); +const gchar * app_section_get_name (AppSection * appitem); +const gchar * app_section_get_desktop (AppSection * appitem); +GMenuModel * app_section_get_menu (AppSection *appitem); +GAppInfo * app_section_get_app_info (AppSection *appitem); + +G_END_DECLS + +#endif /* __APP_SECTION_H__ */ + diff --git a/src/messages-service.c b/src/messages-service.c index 134c4ee..dcce1c5 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -30,7 +30,7 @@ with this program. If not, see . #include #include -#include "app-menu-item.h" +#include "app-section.h" #include "dbus-data.h" #include "messages-service-dbus.h" #include "status-items.h" @@ -63,14 +63,14 @@ add_application (const gchar *desktop_id, desktop_file = g_desktop_app_info_get_filename (appinfo); if (!g_hash_table_lookup (applications, desktop_file)) { - AppMenuItem *menuitem = app_menu_item_new(appinfo); + AppSection *section = app_section_new(appinfo); /* TODO insert it at the right position (alphabetically by application name) */ g_menu_insert_section (menu, 2, - app_menu_item_get_name (menuitem), - app_menu_item_get_menu (menuitem)); + app_section_get_name (section), + app_section_get_menu (section)); - g_hash_table_insert (applications, g_strdup (desktop_file), menuitem); + g_hash_table_insert (applications, g_strdup (desktop_file), section); } g_object_unref (appinfo); @@ -101,7 +101,7 @@ remove_application (const char *desktop_id) { GDesktopAppInfo *appinfo; const gchar *desktop_file; - AppMenuItem *menuitem; + AppSection *section; appinfo = g_desktop_app_info_new (desktop_id); if (!appinfo) { @@ -111,9 +111,9 @@ remove_application (const char *desktop_id) desktop_file = g_desktop_app_info_get_filename (appinfo); - menuitem = g_hash_table_lookup (applications, desktop_file); - if (menuitem) { - int pos = g_menu_find_section (menu, app_menu_item_get_menu (menuitem)); + section = g_hash_table_lookup (applications, desktop_file); + if (section) { + int pos = g_menu_find_section (menu, app_section_get_menu (section)); if (pos >= 0) g_menu_remove (menu, pos); } diff --git a/test/Makefile.am b/test/Makefile.am index 847d857..2b0f67e 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -40,7 +40,7 @@ lib_LTLIBRARIES = \ libindicator_messages_service_la_HEADERS = \ $(top_srcdir)/src/gen-messages-service.xml.h \ - $(top_srcdir)/src/app-menu-item.h \ + $(top_srcdir)/src/app-section.h \ $(top_srcdir)/src/dbus-data.h \ $(top_srcdir)/src/status-items.h @@ -48,7 +48,7 @@ libindicator_messages_service_la_SOURCES = \ $(top_srcdir)/src/messages-service.c \ $(top_srcdir)/src/messages-service-dbus.c \ $(top_srcdir)/src/gen-messages-service.xml.c \ - $(top_srcdir)/src/app-menu-item.c \ + $(top_srcdir)/src/app-section.c \ $(top_srcdir)/src/status-items.c libindicator_messages_service_ladir = \ -- cgit v1.2.3 From 6872c840672049695904d61c1a3baba22c6d9627 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Sun, 3 Jun 2012 08:33:31 +0200 Subject: Add GActionMuxer This is a new implementation of an action muxer with the same interface as the one in the gtk tree. Its implementation is considerably simpler, mostly because it doesn't need to implement GActionObservable. In addition to muxing different action groups with the . scheme, it has the notion of global, prefix-less actions. Indicator-messages needs those for the status and clear actions. --- src/Makefile.am | 5 +- src/gactionmuxer.c | 456 +++++++++++++++++++++++++++++++++++++++++++++++++ src/gactionmuxer.h | 44 +++++ src/messages-service.c | 7 +- test/Makefile.am | 6 +- 5 files changed, 513 insertions(+), 5 deletions(-) create mode 100644 src/gactionmuxer.c create mode 100644 src/gactionmuxer.h (limited to 'test') diff --git a/src/Makefile.am b/src/Makefile.am index 1dbb514..183d729 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -45,9 +45,10 @@ indicator_messages_service_SOURCES = \ app-section.c \ app-section.h \ dbus-data.h \ - \ status-items.c \ - status-items.h + status-items.h \ + gactionmuxer.c \ + gactionmuxer.h indicator_messages_service_CFLAGS = \ $(APPLET_CFLAGS) \ diff --git a/src/gactionmuxer.c b/src/gactionmuxer.c new file mode 100644 index 0000000..cccfeda --- /dev/null +++ b/src/gactionmuxer.c @@ -0,0 +1,456 @@ +/* + * Copyright 2012 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Lars Uebernickel + * Ryan Lortie + */ + +#include "gactionmuxer.h" + +#include + +/* + * SECTION:gactionmuxer + * @short_description: Aggregate several action groups + * + * #GActionMuxer is a #GActionGroup that is capable of containing other + * #GActionGroup instances. + * + * The typical use is aggregating all of the actions applicable to a + * particular context into a single action group, with namespacing. + * + * Consider the case of two action groups -- one containing actions + * applicable to an entire application (such as 'quit') and one + * containing actions applicable to a particular window in the + * application (such as 'fullscreen'). + * + * In this case, each of these action groups could be added to a + * #GActionMuxer with the prefixes "app" and "win", respectively. This + * would expose the actions as "app.quit" and "win.fullscreen" on the + * #GActionGroup interface presented by the #GActionMuxer. + * + * Activations and state change requests on the #GActionMuxer are wired + * through to the underlying action group in the expected way. + */ + +typedef GObjectClass GActionMuxerClass; + +struct _GActionMuxer +{ + GObject parent; + GActionGroup *global_actions; + GHashTable *groups; /* prefix -> subgroup */ + GHashTable *reverse; /* subgroup -> prefix */ +}; + + +static void g_action_muxer_group_init (GActionGroupInterface *iface); +static void g_action_muxer_dispose (GObject *object); +static void g_action_muxer_finalize (GObject *object); +static gchar ** g_action_muxer_list_actions (GActionGroup *group); +static void g_action_muxer_activate_action (GActionGroup *group, + const gchar *action_name, + GVariant *parameter); +static void g_action_muxer_change_action_state (GActionGroup *group, + const gchar *action_name, + GVariant *value); +static gboolean g_action_muxer_query_action (GActionGroup *group, + const gchar *action_name, + gboolean *enabled, + const GVariantType **parameter_type, + const GVariantType **state_type, + GVariant **state_hint, + GVariant **state); +static void g_action_muxer_action_added (GActionGroup *group, + gchar *action_name, + gpointer user_data); +static void g_action_muxer_action_removed (GActionGroup *group, + gchar *action_name, + gpointer user_data); +static void g_action_muxer_action_state_changed (GActionGroup *group, + gchar *action_name, + GVariant *value, + gpointer user_data); +static void g_action_muxer_action_enabled_changed (GActionGroup *group, + gchar *action_name, + gboolean enabled, + gpointer user_data); + +G_DEFINE_TYPE_WITH_CODE (GActionMuxer, g_action_muxer, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_GROUP, g_action_muxer_group_init)); + + +static void +g_action_muxer_class_init (GObjectClass *klass) +{ + klass->dispose = g_action_muxer_dispose; + klass->finalize = g_action_muxer_finalize; +} + +static void +g_action_muxer_init (GActionMuxer *muxer) +{ + muxer->global_actions = NULL; + muxer->groups = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); + muxer->reverse = g_hash_table_new (g_direct_hash, g_direct_equal); +} + +static void +g_action_muxer_group_init (GActionGroupInterface *iface) +{ + iface->list_actions = g_action_muxer_list_actions; + iface->activate_action = g_action_muxer_activate_action; + iface->change_action_state = g_action_muxer_change_action_state; + iface->query_action = g_action_muxer_query_action; +} + +static void +g_action_muxer_dispose (GObject *object) +{ + GActionMuxer *muxer = G_ACTION_MUXER (object); + GHashTableIter it; + gchar *prefix; + + g_clear_object (&muxer->global_actions); + + g_hash_table_iter_init (&it, muxer->groups); + while (g_hash_table_iter_next (&it, (gpointer *) &prefix, NULL)) + g_action_muxer_remove (muxer, prefix); +} + +static void +g_action_muxer_finalize (GObject *object) +{ + GActionMuxer *muxer = G_ACTION_MUXER (object); + + g_hash_table_unref (muxer->groups); + g_hash_table_unref (muxer->reverse); + + G_OBJECT_CLASS (g_action_muxer_parent_class)->finalize (object); +} + +static GActionGroup * +g_action_muxer_lookup_group (GActionMuxer *muxer, + const gchar *full_name, + const gchar **action_name) +{ + const gchar *sep; + GActionGroup *group; + + sep = strchr (full_name, '.'); + + if (sep) + { + gchar *prefix; + prefix = g_strndup (full_name, sep - full_name); + group = g_hash_table_lookup (muxer->groups, prefix); + g_free (prefix); + if (action_name) + *action_name = sep + 1; + } + else + { + group = muxer->global_actions; + if (action_name) + *action_name = full_name; + } + + return group; +} + +static gchar * +g_action_muxer_lookup_full_name (GActionMuxer *muxer, + GActionGroup *subgroup, + const gchar *action_name) +{ + gpointer prefix; + + if (subgroup == muxer->global_actions) + return g_strdup (action_name); + + if (g_hash_table_lookup_extended (muxer->reverse, subgroup, NULL, &prefix)) + return g_strdup_printf ("%s.%s", (gchar *) prefix, action_name); + + return NULL; +} + +static gchar ** +g_action_muxer_list_actions (GActionGroup *group) +{ + GActionMuxer *muxer = G_ACTION_MUXER (group); + GHashTableIter it; + GArray *all_actions; + gchar *prefix; + GActionGroup *subgroup; + gchar **actions; + gchar **a; + + all_actions = g_array_sized_new (TRUE, FALSE, sizeof (gchar *), 8); + + actions = g_action_group_list_actions (muxer->global_actions); + for (a = actions; *a; a++) + { + gchar *name = g_strdup (*a); + g_array_append_val (all_actions, name); + } + g_strfreev (actions); + + g_hash_table_iter_init (&it, muxer->groups); + while (g_hash_table_iter_next (&it, (gpointer *) &prefix, (gpointer *) &subgroup)) + { + actions = g_action_group_list_actions (subgroup); + for (a = actions; *a; a++) + { + gchar *full_name = g_strdup_printf ("%s.%s", prefix, *a); + g_array_append_val (all_actions, full_name); + } + g_strfreev (actions); + } + + return (gchar **) g_array_free (all_actions, FALSE); +} + +static void +g_action_muxer_activate_action (GActionGroup *group, + const gchar *action_name, + GVariant *parameter) +{ + GActionMuxer *muxer = G_ACTION_MUXER (group); + GActionGroup *subgroup; + const gchar *action; + + subgroup = g_action_muxer_lookup_group (muxer, action_name, &action); + + if (subgroup) + g_action_group_activate_action (subgroup, action, parameter); +} + +static void +g_action_muxer_change_action_state (GActionGroup *group, + const gchar *action_name, + GVariant *value) +{ + GActionMuxer *muxer = G_ACTION_MUXER (group); + GActionGroup *subgroup; + const gchar *action; + + subgroup = g_action_muxer_lookup_group (muxer, action_name, &action); + + if (subgroup) + g_action_group_change_action_state (subgroup, action, value); +} + +static gboolean +g_action_muxer_query_action (GActionGroup *group, + const gchar *action_name, + gboolean *enabled, + const GVariantType **parameter_type, + const GVariantType **state_type, + GVariant **state_hint, + GVariant **state) +{ + GActionMuxer *muxer = G_ACTION_MUXER (group); + GActionGroup *subgroup; + const gchar *action; + + subgroup = g_action_muxer_lookup_group (muxer, action_name, &action); + + if (!subgroup) + return FALSE; + + return g_action_group_query_action (subgroup, action, enabled, parameter_type, + state_type, state_hint, state); +} + +static void +g_action_muxer_action_added (GActionGroup *group, + gchar *action_name, + gpointer user_data) +{ + GActionMuxer *muxer = user_data; + gchar *full_name; + + full_name = g_action_muxer_lookup_full_name (muxer, group, action_name); + + if (full_name) + { + g_action_group_action_added (G_ACTION_GROUP (muxer), full_name); + g_free (full_name); + } +} + +static void +g_action_muxer_action_removed (GActionGroup *group, + gchar *action_name, + gpointer user_data) +{ + GActionMuxer *muxer = user_data; + gchar *full_name; + + full_name = g_action_muxer_lookup_full_name (muxer, group, action_name); + + if (full_name) + { + g_action_group_action_removed (G_ACTION_GROUP (muxer), full_name); + g_free (full_name); + } +} + +static void +g_action_muxer_action_state_changed (GActionGroup *group, + gchar *action_name, + GVariant *value, + gpointer user_data) +{ + GActionMuxer *muxer = user_data; + gchar *full_name; + + full_name = g_action_muxer_lookup_full_name (muxer, group, action_name); + + if (full_name) + { + g_action_group_action_state_changed (G_ACTION_GROUP (muxer), full_name, value); + g_free (full_name); + } +} + +static void +g_action_muxer_action_enabled_changed (GActionGroup *group, + gchar *action_name, + gboolean enabled, + gpointer user_data) +{ + GActionMuxer *muxer = user_data; + gchar *full_name; + + full_name = g_action_muxer_lookup_full_name (muxer, group, action_name); + + if (full_name) + { + g_action_group_action_enabled_changed (G_ACTION_GROUP (muxer), full_name, enabled); + g_free (full_name); + } +} + +/* + * g_action_muxer_new: + * + * Creates a new #GActionMuxer. + */ +GActionMuxer * +g_action_muxer_new (void) +{ + return g_object_new (G_TYPE_ACTION_MUXER, NULL); +} + +/* + * g_action_muxer_insert: + * @muxer: a #GActionMuxer + * @prefix: (allow-none): the prefix string for the action group, or NULL + * @group: a #GActionGroup + * + * Adds the actions in @group to the list of actions provided by @muxer. + * @prefix is prefixed to each action name, such that for each action + * x in @group, there is an equivalent action + * @prefix.x in @muxer. + * + * For example, if @prefix is "app" and @group contains an + * action called "quit", then @muxer will now contain an + * action called "app.quit". + * + * If @prefix is NULL, the actions in @group will be added + * to @muxer without prefix. + * + * There may only be one group per prefix (including the + * NULL-prefix). If a group has been added with @prefix in + * a previous call to this function, it will be removed. + * + * @prefix must not contain a dot ('.'). + */ +void +g_action_muxer_insert (GActionMuxer *muxer, + const gchar *prefix, + GActionGroup *group) +{ + gchar *prefix_copy; + gchar **actions; + gchar **action; + + g_return_if_fail (G_IS_ACTION_MUXER (muxer)); + g_return_if_fail (G_IS_ACTION_GROUP (group)); + + g_action_muxer_remove (muxer, prefix); + + if (prefix) + { + prefix_copy = g_strdup (prefix); + g_hash_table_insert (muxer->groups, prefix_copy, g_object_ref (group)); + g_hash_table_insert (muxer->reverse, group, prefix_copy); + } + else + muxer->global_actions = g_object_ref (group); + + actions = g_action_group_list_actions (group); + for (action = actions; *action; action++) + g_action_muxer_action_added (group, *action, muxer); + g_strfreev (actions); + + g_signal_connect (group, "action-added", G_CALLBACK (g_action_muxer_action_added), muxer); + g_signal_connect (group, "action-removed", G_CALLBACK (g_action_muxer_action_removed), muxer); + g_signal_connect (group, "action-enabled-changed", G_CALLBACK (g_action_muxer_action_enabled_changed), muxer); + g_signal_connect (group, "action-state-changed", G_CALLBACK (g_action_muxer_action_state_changed), muxer); +} + +/* + * g_action_muxer_remove: + * @muxer: a #GActionMuxer + * @prefix: (allow-none): the prefix of the action group to remove, or NULL + * + * Removes a #GActionGroup from the #GActionMuxer. + */ +void +g_action_muxer_remove (GActionMuxer *muxer, + const gchar *prefix) +{ + GActionGroup *subgroup; + gchar **actions; + gchar **action; + + g_return_if_fail (G_IS_ACTION_MUXER (muxer)); + + subgroup = prefix ? g_hash_table_lookup (muxer->groups, prefix) : muxer->global_actions; + if (!subgroup) + return; + + actions = g_action_group_list_actions (subgroup); + for (action = actions; *action; action++) + g_action_muxer_action_removed (subgroup, *action, muxer); + g_strfreev (actions); + + g_signal_handlers_disconnect_by_func (subgroup, g_action_muxer_action_added, muxer); + g_signal_handlers_disconnect_by_func (subgroup, g_action_muxer_action_removed, muxer); + g_signal_handlers_disconnect_by_func (subgroup, g_action_muxer_action_enabled_changed, muxer); + g_signal_handlers_disconnect_by_func (subgroup, g_action_muxer_action_state_changed, muxer); + + if (prefix) + { + g_hash_table_remove (muxer->groups, prefix); + g_hash_table_remove (muxer->reverse, subgroup); + } + else + g_clear_object (&muxer->global_actions); +} + diff --git a/src/gactionmuxer.h b/src/gactionmuxer.h new file mode 100644 index 0000000..5c5e839 --- /dev/null +++ b/src/gactionmuxer.h @@ -0,0 +1,44 @@ +/* + * Copyright 2012 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Lars Uebernickel + * Ryan Lortie + */ + +#ifndef __G_ACTION_MUXER_H__ +#define __G_ACTION_MUXER_H__ + +#include + +#define G_TYPE_ACTION_MUXER (g_action_muxer_get_type ()) +#define G_ACTION_MUXER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_ACTION_MUXER, GActionMuxer)) +#define G_IS_ACTION_MUXER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_ACTION_MUXER)) + +typedef struct _GActionMuxer GActionMuxer; + +GType g_action_muxer_get_type (void) G_GNUC_CONST; + +GActionMuxer * g_action_muxer_new (void); + +void g_action_muxer_insert (GActionMuxer *muxer, + const gchar *prefix, + GActionGroup *group); + +void g_action_muxer_remove (GActionMuxer *muxer, + const gchar *prefix); + +#endif + diff --git a/src/messages-service.c b/src/messages-service.c index 28a64a0..c1069b8 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -34,12 +34,14 @@ with this program. If not, see . #include "dbus-data.h" #include "messages-service-dbus.h" #include "status-items.h" +#include "gactionmuxer.h" static IndicatorService * service = NULL; static GHashTable *applications; static GDBusConnection *bus; static GSimpleActionGroup *actions; +static GActionMuxer *action_muxer; static GMenu *menu; static GSettings *settings; static GMainLoop * mainloop = NULL; @@ -296,8 +298,11 @@ main (int argc, char ** argv) actions = g_simple_action_group_new (); g_simple_action_group_add_entries (actions, entries, G_N_ELEMENTS (entries), NULL); + + action_muxer = g_action_muxer_new (); + g_action_muxer_insert (action_muxer, NULL, G_ACTION_GROUP (actions)); g_dbus_connection_export_action_group (bus, INDICATOR_MESSAGES_DBUS_OBJECT, - G_ACTION_GROUP (actions), &error); + G_ACTION_GROUP (action_muxer), &error); if (error) { g_warning ("unable to export action group on dbus: %s", error->message); g_error_free (error); diff --git a/test/Makefile.am b/test/Makefile.am index 2b0f67e..977c1ed 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -42,14 +42,16 @@ libindicator_messages_service_la_HEADERS = \ $(top_srcdir)/src/gen-messages-service.xml.h \ $(top_srcdir)/src/app-section.h \ $(top_srcdir)/src/dbus-data.h \ - $(top_srcdir)/src/status-items.h + $(top_srcdir)/src/status-items.h \ + $(top_srcdir)/src/gactionmuxer.h libindicator_messages_service_la_SOURCES = \ $(top_srcdir)/src/messages-service.c \ $(top_srcdir)/src/messages-service-dbus.c \ $(top_srcdir)/src/gen-messages-service.xml.c \ $(top_srcdir)/src/app-section.c \ - $(top_srcdir)/src/status-items.c + $(top_srcdir)/src/status-items.c \ + $(top_srcdir)/src/gactionmuxer.c libindicator_messages_service_ladir = \ $(includedir)/libindicator-messages-service/ -- cgit v1.2.3 From 3eb45ac840a66511537cdf2bd2c9f7c68c6e1761 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 4 Jun 2012 12:23:51 +0200 Subject: Include different header in test case to fix `make check` --- src/app-section.h | 1 + test/test-gtest.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/src/app-section.h b/src/app-section.h index 1ef191a..a81b4df 100644 --- a/src/app-section.h +++ b/src/app-section.h @@ -23,6 +23,7 @@ with this program. If not, see . #define __APP_SECTION_H__ #include +#include G_BEGIN_DECLS diff --git a/test/test-gtest.cpp b/test/test-gtest.cpp index 1cc97be..fd9fec1 100644 --- a/test/test-gtest.cpp +++ b/test/test-gtest.cpp @@ -3,10 +3,10 @@ #include extern "C" { - #include "launcher-menu-item.h" + #include "app-section.h" } -TEST(LauncherMenuItem, NameInitialized) { +TEST(AppSection, NameInitialized) { g_type_init(); EXPECT_TRUE(true); } -- cgit v1.2.3 From 7d4fcf06c92e71fa0abb1927ac21705ab88478c0 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 4 Jun 2012 18:13:24 +0200 Subject: Add a first gactionmuxer test --- test/Makefile.am | 13 +++++++- test/test-gactionmuxer.cpp | 76 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 test/test-gactionmuxer.cpp (limited to 'test') diff --git a/test/Makefile.am b/test/Makefile.am index 977c1ed..f1ab408 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,6 +1,6 @@ check_LIBRARIES = libgtest.a -check_PROGRAMS = test-gtest +check_PROGRAMS = test-gtest test-gactionmuxer TESTS = @@ -31,6 +31,17 @@ test_gtest_LDADD = \ libgtest.a +TESTS += test-gactionmuxer + +test_gactionmuxer_SOURCES = \ + test-gactionmuxer.cpp \ + $(top_srcdir)/src/gactionmuxer.c \ + $(top_srcdir)/src/gactionmuxer.h + +test_gactionmuxer_CPPFLAGS = $(APPLET_CFLAGS) $(AM_CPPFLAGS) +test_gactionmuxer_LDADD = $(APPLET_LIBS) libgtest.a + + ###################################### # Lib containing code under test ###################################### diff --git a/test/test-gactionmuxer.cpp b/test/test-gactionmuxer.cpp new file mode 100644 index 0000000..fb32452 --- /dev/null +++ b/test/test-gactionmuxer.cpp @@ -0,0 +1,76 @@ + +#include +#include +#include + +extern "C" { +#include "app-section.h" +#include "gactionmuxer.h" +} + +static gboolean +strv_contains (gchar **str_array, + const gchar *str) +{ + gchar **it; + + for (it = str_array; *it; it++) { + if (!g_strcmp0 (*it, str)) + return TRUE; + } + + return FALSE; +} + +TEST(GActionMuxerTest, General) { + const GActionEntry entries1[] = { { "one" }, { "two" }, { "three" } }; + const GActionEntry entries2[] = { { "gb" }, { "es" }, { "fr" } }; + const GActionEntry entries3[] = { { "foo" }, { "bar" } }; + GSimpleActionGroup *group1; + GSimpleActionGroup *group2; + GSimpleActionGroup *group3; + GActionMuxer *muxer; + gchar **actions; + + g_type_init (); + + group1 = g_simple_action_group_new (); + g_simple_action_group_add_entries (group1, + entries1, + G_N_ELEMENTS (entries1), + NULL); + + group2 = g_simple_action_group_new (); + g_simple_action_group_add_entries (group2, + entries2, + G_N_ELEMENTS (entries2), + NULL); + + group3 = g_simple_action_group_new (); + g_simple_action_group_add_entries (group3, + entries3, + G_N_ELEMENTS (entries3), + NULL); + + muxer = g_action_muxer_new (); + g_action_muxer_insert (muxer, "first", G_ACTION_GROUP (group1)); + g_action_muxer_insert (muxer, "second", G_ACTION_GROUP (group2)); + g_action_muxer_insert (muxer, NULL, G_ACTION_GROUP (group3)); + + actions = g_action_group_list_actions (G_ACTION_GROUP (muxer)); + EXPECT_EQ (8, g_strv_length (actions)); + EXPECT_TRUE (strv_contains (actions, "first.one")); + EXPECT_TRUE (strv_contains (actions, "first.two")); + EXPECT_TRUE (strv_contains (actions, "first.three")); + EXPECT_TRUE (strv_contains (actions, "second.gb")); + EXPECT_TRUE (strv_contains (actions, "second.es")); + EXPECT_TRUE (strv_contains (actions, "second.fr")); + EXPECT_TRUE (strv_contains (actions, "foo")); + EXPECT_TRUE (strv_contains (actions, "bar")); + g_strfreev (actions); + + g_object_unref (muxer); + g_object_unref (group1); + g_object_unref (group2); + g_object_unref (group3); +} -- cgit v1.2.3 From 6ee454ecc225d186195206465254133473bfd749 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 4 Jun 2012 18:15:46 +0200 Subject: Remove dummy test case --- test/Makefile.am | 16 +--------------- test/test-gtest.cpp | 12 ------------ 2 files changed, 1 insertion(+), 27 deletions(-) delete mode 100644 test/test-gtest.cpp (limited to 'test') diff --git a/test/Makefile.am b/test/Makefile.am index f1ab408..6ceb1d4 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,6 +1,6 @@ check_LIBRARIES = libgtest.a -check_PROGRAMS = test-gtest test-gactionmuxer +check_PROGRAMS = test-gactionmuxer TESTS = @@ -17,20 +17,6 @@ libgtest_a_CXXFLAGS = \ libgtest_a_CPPFLAGS = \ $(AM_CPPFLAGS) -TESTS += test-gtest - -test_gtest_SOURCES = \ - test-gtest.cpp -test_gtest_CPPFLAGS = \ - $(APPLET_CFLAGS) \ - $(AM_CPPFLAGS) -test_gtest_LDFLAGS = -pthread -test_gtest_LDADD = \ - $(APPLET_LIBS) \ - $(top_builddir)/src/.libs/libindicator-messages-status-provider.la \ - libgtest.a - - TESTS += test-gactionmuxer test_gactionmuxer_SOURCES = \ diff --git a/test/test-gtest.cpp b/test/test-gtest.cpp deleted file mode 100644 index fd9fec1..0000000 --- a/test/test-gtest.cpp +++ /dev/null @@ -1,12 +0,0 @@ - -#include -#include - -extern "C" { - #include "app-section.h" -} - -TEST(AppSection, NameInitialized) { - g_type_init(); - EXPECT_TRUE(true); -} -- cgit v1.2.3 From 2fee65e88f9a5de775df5fe99fe8a9a160bbbdf8 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 4 Jun 2012 18:21:11 +0200 Subject: test: remove warnings in Makefile.am (duplicate vars) --- test/Makefile.am | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'test') diff --git a/test/Makefile.am b/test/Makefile.am index 6ceb1d4..a790ba2 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -2,7 +2,7 @@ check_LIBRARIES = libgtest.a check_PROGRAMS = test-gactionmuxer -TESTS = +TESTS = $(check_PROGRAMS) AM_CPPFLAGS = $(GTEST_CPPFLAGS) \ -I${top_srcdir}/src @@ -11,13 +11,11 @@ nodist_libgtest_a_SOURCES = \ $(GTEST_SOURCE)/src/gtest-all.cc \ $(GTEST_SOURCE)/src/gtest_main.cc libgtest_a_CPPFLAGS = \ - $(GTEST_CPPFLAGS) -w + $(GTEST_CPPFLAGS) -w \ + $(AM_CPPFLAGS) libgtest_a_CXXFLAGS = \ $(AM_CXXFLAGS) -libgtest_a_CPPFLAGS = \ - $(AM_CPPFLAGS) -TESTS += test-gactionmuxer test_gactionmuxer_SOURCES = \ test-gactionmuxer.cpp \ -- cgit v1.2.3 From 2c7ad39202242c83265dcd94e384b8ad12979d83 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 4 Jun 2012 18:56:44 +0200 Subject: gactionmuxer: don't crash when no global actions are given --- src/gactionmuxer.c | 13 ++++++++----- test/test-gactionmuxer.cpp | 15 +++++++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) (limited to 'test') diff --git a/src/gactionmuxer.c b/src/gactionmuxer.c index 6c4d08b..ac3f8e4 100644 --- a/src/gactionmuxer.c +++ b/src/gactionmuxer.c @@ -227,13 +227,16 @@ g_action_muxer_list_actions (GActionGroup *group) all_actions = g_array_sized_new (TRUE, FALSE, sizeof (gchar *), 8); - actions = g_action_group_list_actions (muxer->global_actions); - for (a = actions; *a; a++) + if (muxer->global_actions) { - gchar *name = g_strdup (*a); - g_array_append_val (all_actions, name); + actions = g_action_group_list_actions (muxer->global_actions); + for (a = actions; *a; a++) + { + gchar *name = g_strdup (*a); + g_array_append_val (all_actions, name); + } + g_strfreev (actions); } - g_strfreev (actions); g_hash_table_iter_init (&it, muxer->groups); while (g_hash_table_iter_next (&it, (gpointer *) &prefix, (gpointer *) &subgroup)) diff --git a/test/test-gactionmuxer.cpp b/test/test-gactionmuxer.cpp index fb32452..9f0ac3b 100644 --- a/test/test-gactionmuxer.cpp +++ b/test/test-gactionmuxer.cpp @@ -22,6 +22,21 @@ strv_contains (gchar **str_array, return FALSE; } +TEST(GActionMuxerTest, Empty) { + GActionMuxer *muxer; + gchar **actions; + + g_type_init (); + + muxer = g_action_muxer_new (); + + actions = g_action_group_list_actions (G_ACTION_GROUP (muxer)); + EXPECT_EQ (0, g_strv_length (actions)); + + g_strfreev (actions); + g_object_unref (muxer); +} + TEST(GActionMuxerTest, General) { const GActionEntry entries1[] = { { "one" }, { "two" }, { "three" } }; const GActionEntry entries2[] = { { "gb" }, { "es" }, { "fr" } }; -- cgit v1.2.3 From a2efe98ce72aedae472637154a3e45f5ddd25675 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 4 Jun 2012 20:03:15 +0200 Subject: Test gactionmuxer more extensively --- test/test-gactionmuxer.cpp | 167 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 166 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/test/test-gactionmuxer.cpp b/test/test-gactionmuxer.cpp index 9f0ac3b..aa877fb 100644 --- a/test/test-gactionmuxer.cpp +++ b/test/test-gactionmuxer.cpp @@ -37,7 +37,7 @@ TEST(GActionMuxerTest, Empty) { g_object_unref (muxer); } -TEST(GActionMuxerTest, General) { +TEST(GActionMuxerTest, AddAndRemove) { const GActionEntry entries1[] = { { "one" }, { "two" }, { "three" } }; const GActionEntry entries2[] = { { "gb" }, { "es" }, { "fr" } }; const GActionEntry entries3[] = { { "foo" }, { "bar" } }; @@ -73,6 +73,8 @@ TEST(GActionMuxerTest, General) { g_action_muxer_insert (muxer, NULL, G_ACTION_GROUP (group3)); actions = g_action_group_list_actions (G_ACTION_GROUP (muxer)); + EXPECT_TRUE (g_action_group_has_action (G_ACTION_GROUP (muxer), "first.one")); + EXPECT_FALSE (g_action_group_has_action (G_ACTION_GROUP (muxer), "one")); EXPECT_EQ (8, g_strv_length (actions)); EXPECT_TRUE (strv_contains (actions, "first.one")); EXPECT_TRUE (strv_contains (actions, "first.two")); @@ -84,8 +86,171 @@ TEST(GActionMuxerTest, General) { EXPECT_TRUE (strv_contains (actions, "bar")); g_strfreev (actions); + g_action_muxer_remove (muxer, NULL); + EXPECT_FALSE (g_action_group_has_action (G_ACTION_GROUP (muxer), "foo")); + EXPECT_TRUE (g_action_group_has_action (G_ACTION_GROUP (muxer), "first.one")); + actions = g_action_group_list_actions (G_ACTION_GROUP (muxer)); + EXPECT_EQ (6, g_strv_length (actions)); + EXPECT_FALSE (strv_contains (actions, "foo")); + EXPECT_TRUE (strv_contains (actions, "first.one")); + g_strfreev (actions); + + g_action_muxer_remove (muxer, "first"); + EXPECT_FALSE (g_action_group_has_action (G_ACTION_GROUP (muxer), "first.two")); + EXPECT_TRUE (g_action_group_has_action (G_ACTION_GROUP (muxer), "second.es")); + actions = g_action_group_list_actions (G_ACTION_GROUP (muxer)); + EXPECT_EQ (3, g_strv_length (actions)); + EXPECT_FALSE (strv_contains (actions, "first.two")); + EXPECT_TRUE (strv_contains (actions, "second.es")); + g_strfreev (actions); + g_object_unref (muxer); g_object_unref (group1); g_object_unref (group2); g_object_unref (group3); } + +static gboolean +g_variant_equal0 (gconstpointer one, + gconstpointer two) +{ + if (one == NULL) + return two == NULL; + else + return g_variant_equal (one, two); +} + +TEST(GActionMuxerTest, ActionAttributes) { + GSimpleActionGroup *group; + GSimpleAction *action; + GActionMuxer *muxer; + gboolean enabled[2]; + const GVariantType *param_type[2]; + const GVariantType *state_type[2]; + GVariant *state_hint[2]; + GVariant *state[2]; + + g_type_init (); + + group = g_simple_action_group_new (); + action = g_simple_action_new ("one", G_VARIANT_TYPE_STRING); + g_simple_action_group_insert (group, G_ACTION (action)); + + muxer = g_action_muxer_new (); + g_action_muxer_insert (muxer, "first", G_ACTION_GROUP (group)); + + /* test two of the convenience functions */ + ASSERT_TRUE (g_action_group_get_action_enabled (G_ACTION_GROUP (muxer), "first.one")); + g_simple_action_set_enabled (action, FALSE); + ASSERT_FALSE (g_action_group_get_action_enabled (G_ACTION_GROUP (muxer), "first.one")); + + ASSERT_STREQ ((gchar *) g_action_group_get_action_parameter_type (G_ACTION_GROUP (muxer), "first.one"), + (gchar *) G_VARIANT_TYPE_STRING); + + /* query_action */ + g_action_group_query_action (G_ACTION_GROUP (group), "one", + &enabled[0], ¶m_type[0], &state_type[0], &state_hint[0], &state[0]); + g_action_group_query_action (G_ACTION_GROUP (muxer), "first.one", + &enabled[1], ¶m_type[1], &state_type[1], &state_hint[1], &state[1]); + ASSERT_EQ (enabled[0], enabled[1]); + ASSERT_STREQ ((gchar *) param_type[0], (gchar *) param_type[1]); + ASSERT_STREQ ((gchar *) state_type[0], (gchar *) state_type[1]); + ASSERT_TRUE (g_variant_equal0 ((gconstpointer) state_hint[0], (gconstpointer) state_hint[1])); + ASSERT_TRUE (g_variant_equal0 ((gconstpointer) state[0], (gconstpointer) state[1])); + + g_object_unref (action); + g_object_unref (group); + g_object_unref (muxer); +} + +typedef struct { + gboolean signal_ran; + const gchar *name; +} TestSignalClosure; + +static void +action_added (GActionGroup *group, + gchar *action_name, + gpointer user_data) +{ + TestSignalClosure *c = (TestSignalClosure *)user_data; + EXPECT_STREQ (c->name, action_name); + c->signal_ran = TRUE; +} + +static void +action_enabled_changed (GActionGroup *group, + gchar *action_name, + gboolean enabled, + gpointer user_data) +{ + TestSignalClosure *c = (TestSignalClosure *)user_data; + EXPECT_EQ (enabled, FALSE); + c->signal_ran = TRUE; +} + +static void +action_removed (GActionGroup *group, + gchar *action_name, + gpointer user_data) +{ + TestSignalClosure *c = (TestSignalClosure *)user_data; + EXPECT_STREQ (c->name, action_name); + c->signal_ran = TRUE; +} + +TEST(GActionMuxerTest, Signals) { + GSimpleActionGroup *group; + GSimpleAction *action; + GActionMuxer *muxer; + TestSignalClosure closure; + + group = g_simple_action_group_new (); + + action = g_simple_action_new ("one", G_VARIANT_TYPE_STRING); + g_simple_action_group_insert (group, G_ACTION (action)); + g_object_unref (action); + + muxer = g_action_muxer_new (); + + g_signal_connect (muxer, "action-added", + G_CALLBACK (action_added), (gpointer) &closure); + g_signal_connect (muxer, "action-enabled-changed", + G_CALLBACK (action_enabled_changed), (gpointer) &closure); + g_signal_connect (muxer, "action-removed", + G_CALLBACK (action_removed), (gpointer) &closure); + + /* add the group with "one" action and check whether the signal is emitted */ + closure.signal_ran = FALSE; + closure.name = "first.one"; + g_action_muxer_insert (muxer, "first", G_ACTION_GROUP (group)); + ASSERT_TRUE (closure.signal_ran); + + /* add a second action after the group was added to the muxer */ + closure.signal_ran = FALSE; + closure.name = "first.two"; + action = g_simple_action_new ("two", G_VARIANT_TYPE_STRING); + g_simple_action_group_insert (group, G_ACTION (action)); + ASSERT_TRUE (closure.signal_ran); + + /* disable the action */ + closure.signal_ran = FALSE; + g_simple_action_set_enabled (action, FALSE); + ASSERT_TRUE (closure.signal_ran); + g_object_unref (action); + + /* remove the first action */ + closure.signal_ran = FALSE; + closure.name = "first.one"; + g_simple_action_group_remove (group, "one"); + ASSERT_TRUE (closure.signal_ran); + + /* remove the whole group, should be notified about "first.two" */ + closure.signal_ran = FALSE; + closure.name = "first.two"; + g_action_muxer_remove (muxer, "first"); + ASSERT_TRUE (closure.signal_ran); + + g_object_unref (group); + g_object_unref (muxer); +} -- cgit v1.2.3 From 26d7cfc736224403c4cb9f6f0a91aaa78020f80c Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 4 Jun 2012 22:18:31 +0200 Subject: Link test against a static lib to clean up lcov reporting If specifying the sources in src/ directly for each test, lcov generates reports for tests itself. That's fairly useless, as the ASSERT_* branches in the tests should (hopefully) never be taken. --- test/Makefile.am | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'test') diff --git a/test/Makefile.am b/test/Makefile.am index a790ba2..26dd867 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -18,12 +18,16 @@ libgtest_a_CXXFLAGS = \ test_gactionmuxer_SOURCES = \ - test-gactionmuxer.cpp \ - $(top_srcdir)/src/gactionmuxer.c \ - $(top_srcdir)/src/gactionmuxer.h + test-gactionmuxer.cpp -test_gactionmuxer_CPPFLAGS = $(APPLET_CFLAGS) $(AM_CPPFLAGS) -test_gactionmuxer_LDADD = $(APPLET_LIBS) libgtest.a +test_gactionmuxer_CPPFLAGS = \ + $(APPLET_CFLAGS) \ + $(AM_CPPFLAGS) + +test_gactionmuxer_LDADD = \ + $(APPLET_LIBS) \ + libindicator-messages-service.la \ + libgtest.a ###################################### @@ -41,7 +45,6 @@ libindicator_messages_service_la_HEADERS = \ $(top_srcdir)/src/gactionmuxer.h libindicator_messages_service_la_SOURCES = \ - $(top_srcdir)/src/messages-service.c \ $(top_srcdir)/src/messages-service-dbus.c \ $(top_srcdir)/src/gen-messages-service.xml.c \ $(top_srcdir)/src/app-section.c \ -- cgit v1.2.3 From 0eda2f38aeb7abdb4c342305fef15388ec3fa248 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 4 Jun 2012 23:44:13 +0200 Subject: gactionmuxer: more tests --- test/test-gactionmuxer.cpp | 111 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 110 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/test/test-gactionmuxer.cpp b/test/test-gactionmuxer.cpp index aa877fb..64c0d20 100644 --- a/test/test-gactionmuxer.cpp +++ b/test/test-gactionmuxer.cpp @@ -22,6 +22,26 @@ strv_contains (gchar **str_array, return FALSE; } +TEST(GActionMuxerTest, Sanity) { + GActionMuxer *muxer; + + g_type_init (); + + g_action_muxer_insert (NULL, NULL, NULL); + g_action_muxer_remove (NULL, NULL); + + muxer = g_action_muxer_new (); + + g_action_muxer_insert (muxer, NULL, NULL); + g_action_muxer_remove (muxer, NULL); + EXPECT_FALSE (g_action_group_has_action (G_ACTION_GROUP (muxer), NULL)); + EXPECT_FALSE (g_action_group_get_action_enabled (G_ACTION_GROUP (muxer), NULL)); + EXPECT_FALSE (g_action_group_query_action (G_ACTION_GROUP (muxer), NULL, NULL, NULL, NULL, NULL, NULL)); + g_action_group_activate_action (G_ACTION_GROUP (muxer), NULL, NULL); + + g_object_unref (muxer); +} + TEST(GActionMuxerTest, Empty) { GActionMuxer *muxer; gchar **actions; @@ -104,6 +124,16 @@ TEST(GActionMuxerTest, AddAndRemove) { EXPECT_TRUE (strv_contains (actions, "second.es")); g_strfreev (actions); + g_action_muxer_insert (muxer, "second", G_ACTION_GROUP (group2)); + actions = g_action_group_list_actions (G_ACTION_GROUP (muxer)); + EXPECT_EQ (3, g_strv_length (actions)); + g_strfreev (actions); + + g_action_muxer_insert (muxer, NULL, G_ACTION_GROUP (group3)); + actions = g_action_group_list_actions (G_ACTION_GROUP (muxer)); + EXPECT_EQ (5, g_strv_length (actions)); + g_strfreev (actions); + g_object_unref (muxer); g_object_unref (group1); g_object_unref (group2); @@ -189,6 +219,17 @@ action_enabled_changed (GActionGroup *group, c->signal_ran = TRUE; } +static void +action_state_changed (GActionGroup *group, + gchar *action_name, + GVariant *value, + gpointer user_data) +{ + TestSignalClosure *c = (TestSignalClosure *)user_data; + EXPECT_STREQ (g_variant_get_string (value, NULL), "off"); + c->signal_ran = TRUE; +} + static void action_removed (GActionGroup *group, gchar *action_name, @@ -217,6 +258,8 @@ TEST(GActionMuxerTest, Signals) { G_CALLBACK (action_added), (gpointer) &closure); g_signal_connect (muxer, "action-enabled-changed", G_CALLBACK (action_enabled_changed), (gpointer) &closure); + g_signal_connect (muxer, "action-state-changed", + G_CALLBACK (action_state_changed), (gpointer) &closure); g_signal_connect (muxer, "action-removed", G_CALLBACK (action_removed), (gpointer) &closure); @@ -229,7 +272,8 @@ TEST(GActionMuxerTest, Signals) { /* add a second action after the group was added to the muxer */ closure.signal_ran = FALSE; closure.name = "first.two"; - action = g_simple_action_new ("two", G_VARIANT_TYPE_STRING); + action = g_simple_action_new_stateful ("two", G_VARIANT_TYPE_STRING, + g_variant_new_string ("on")); g_simple_action_group_insert (group, G_ACTION (action)); ASSERT_TRUE (closure.signal_ran); @@ -237,6 +281,11 @@ TEST(GActionMuxerTest, Signals) { closure.signal_ran = FALSE; g_simple_action_set_enabled (action, FALSE); ASSERT_TRUE (closure.signal_ran); + + /* change its state */ + closure.signal_ran = FALSE; + g_simple_action_set_state (action, g_variant_new_string ("off")); + ASSERT_TRUE (closure.signal_ran); g_object_unref (action); /* remove the first action */ @@ -254,3 +303,63 @@ TEST(GActionMuxerTest, Signals) { g_object_unref (group); g_object_unref (muxer); } + +static void +action_activated (GSimpleAction *simple, + GVariant *parameter, + gpointer user_data) +{ + gboolean *signal_ran = (gboolean *)user_data; + + ASSERT_STREQ (g_variant_get_string (parameter, NULL), "value"); + *signal_ran = TRUE; +} + +static void +action_change_state (GSimpleAction *simple, + GVariant *value, + gpointer user_data) +{ + gboolean *signal_ran = (gboolean *)user_data; + + ASSERT_STREQ (g_variant_get_string (value, NULL), "off"); + *signal_ran = TRUE; +} + +TEST(GActionMuxerTest, ActivateAction) { + GSimpleActionGroup *group; + GSimpleAction *action; + GActionMuxer *muxer; + gboolean signal_ran; + + group = g_simple_action_group_new (); + + action = g_simple_action_new ("one", G_VARIANT_TYPE_STRING); + g_simple_action_group_insert (group, G_ACTION (action)); + g_signal_connect (action, "activate", + G_CALLBACK (action_activated), (gpointer) &signal_ran); + g_object_unref (action); + + action = g_simple_action_new_stateful ("two", NULL, + g_variant_new_string ("on")); + g_simple_action_group_insert (group, G_ACTION (action)); + g_signal_connect (action, "change-state", + G_CALLBACK (action_change_state), (gpointer) &signal_ran); + g_object_unref (action); + + muxer = g_action_muxer_new (); + g_action_muxer_insert (muxer, "first", G_ACTION_GROUP (group)); + + signal_ran = FALSE; + g_action_group_activate_action (G_ACTION_GROUP (muxer), "first.one", + g_variant_new_string ("value")); + ASSERT_TRUE (signal_ran); + + signal_ran = FALSE; + g_action_group_change_action_state (G_ACTION_GROUP (muxer), "first.two", + g_variant_new_string ("off")); + ASSERT_TRUE (signal_ran); + + g_object_unref (group); + g_object_unref (muxer); +} -- cgit v1.2.3 From 368b17f9ab5cbe934d796ddd19f4510bbf01cab8 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 4 Jun 2012 23:47:13 +0200 Subject: testing: use EXPECT_* instead of ASSERT_* --- test/test-gactionmuxer.cpp | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'test') diff --git a/test/test-gactionmuxer.cpp b/test/test-gactionmuxer.cpp index 64c0d20..6304853 100644 --- a/test/test-gactionmuxer.cpp +++ b/test/test-gactionmuxer.cpp @@ -170,11 +170,11 @@ TEST(GActionMuxerTest, ActionAttributes) { g_action_muxer_insert (muxer, "first", G_ACTION_GROUP (group)); /* test two of the convenience functions */ - ASSERT_TRUE (g_action_group_get_action_enabled (G_ACTION_GROUP (muxer), "first.one")); + EXPECT_TRUE (g_action_group_get_action_enabled (G_ACTION_GROUP (muxer), "first.one")); g_simple_action_set_enabled (action, FALSE); - ASSERT_FALSE (g_action_group_get_action_enabled (G_ACTION_GROUP (muxer), "first.one")); + EXPECT_FALSE (g_action_group_get_action_enabled (G_ACTION_GROUP (muxer), "first.one")); - ASSERT_STREQ ((gchar *) g_action_group_get_action_parameter_type (G_ACTION_GROUP (muxer), "first.one"), + EXPECT_STREQ ((gchar *) g_action_group_get_action_parameter_type (G_ACTION_GROUP (muxer), "first.one"), (gchar *) G_VARIANT_TYPE_STRING); /* query_action */ @@ -182,11 +182,11 @@ TEST(GActionMuxerTest, ActionAttributes) { &enabled[0], ¶m_type[0], &state_type[0], &state_hint[0], &state[0]); g_action_group_query_action (G_ACTION_GROUP (muxer), "first.one", &enabled[1], ¶m_type[1], &state_type[1], &state_hint[1], &state[1]); - ASSERT_EQ (enabled[0], enabled[1]); - ASSERT_STREQ ((gchar *) param_type[0], (gchar *) param_type[1]); - ASSERT_STREQ ((gchar *) state_type[0], (gchar *) state_type[1]); - ASSERT_TRUE (g_variant_equal0 ((gconstpointer) state_hint[0], (gconstpointer) state_hint[1])); - ASSERT_TRUE (g_variant_equal0 ((gconstpointer) state[0], (gconstpointer) state[1])); + EXPECT_EQ (enabled[0], enabled[1]); + EXPECT_STREQ ((gchar *) param_type[0], (gchar *) param_type[1]); + EXPECT_STREQ ((gchar *) state_type[0], (gchar *) state_type[1]); + EXPECT_TRUE (g_variant_equal0 ((gconstpointer) state_hint[0], (gconstpointer) state_hint[1])); + EXPECT_TRUE (g_variant_equal0 ((gconstpointer) state[0], (gconstpointer) state[1])); g_object_unref (action); g_object_unref (group); @@ -267,7 +267,7 @@ TEST(GActionMuxerTest, Signals) { closure.signal_ran = FALSE; closure.name = "first.one"; g_action_muxer_insert (muxer, "first", G_ACTION_GROUP (group)); - ASSERT_TRUE (closure.signal_ran); + EXPECT_TRUE (closure.signal_ran); /* add a second action after the group was added to the muxer */ closure.signal_ran = FALSE; @@ -275,30 +275,30 @@ TEST(GActionMuxerTest, Signals) { action = g_simple_action_new_stateful ("two", G_VARIANT_TYPE_STRING, g_variant_new_string ("on")); g_simple_action_group_insert (group, G_ACTION (action)); - ASSERT_TRUE (closure.signal_ran); + EXPECT_TRUE (closure.signal_ran); /* disable the action */ closure.signal_ran = FALSE; g_simple_action_set_enabled (action, FALSE); - ASSERT_TRUE (closure.signal_ran); + EXPECT_TRUE (closure.signal_ran); /* change its state */ closure.signal_ran = FALSE; g_simple_action_set_state (action, g_variant_new_string ("off")); - ASSERT_TRUE (closure.signal_ran); + EXPECT_TRUE (closure.signal_ran); g_object_unref (action); /* remove the first action */ closure.signal_ran = FALSE; closure.name = "first.one"; g_simple_action_group_remove (group, "one"); - ASSERT_TRUE (closure.signal_ran); + EXPECT_TRUE (closure.signal_ran); /* remove the whole group, should be notified about "first.two" */ closure.signal_ran = FALSE; closure.name = "first.two"; g_action_muxer_remove (muxer, "first"); - ASSERT_TRUE (closure.signal_ran); + EXPECT_TRUE (closure.signal_ran); g_object_unref (group); g_object_unref (muxer); @@ -311,7 +311,7 @@ action_activated (GSimpleAction *simple, { gboolean *signal_ran = (gboolean *)user_data; - ASSERT_STREQ (g_variant_get_string (parameter, NULL), "value"); + EXPECT_STREQ (g_variant_get_string (parameter, NULL), "value"); *signal_ran = TRUE; } @@ -322,7 +322,7 @@ action_change_state (GSimpleAction *simple, { gboolean *signal_ran = (gboolean *)user_data; - ASSERT_STREQ (g_variant_get_string (value, NULL), "off"); + EXPECT_STREQ (g_variant_get_string (value, NULL), "off"); *signal_ran = TRUE; } @@ -353,12 +353,12 @@ TEST(GActionMuxerTest, ActivateAction) { signal_ran = FALSE; g_action_group_activate_action (G_ACTION_GROUP (muxer), "first.one", g_variant_new_string ("value")); - ASSERT_TRUE (signal_ran); + EXPECT_TRUE (signal_ran); signal_ran = FALSE; g_action_group_change_action_state (G_ACTION_GROUP (muxer), "first.two", g_variant_new_string ("off")); - ASSERT_TRUE (signal_ran); + EXPECT_TRUE (signal_ran); g_object_unref (group); g_object_unref (muxer); -- cgit v1.2.3 From bc9cd727c2bb0116c94e1bf258e257d5bff406f8 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 13 Jun 2012 17:57:09 +0200 Subject: Don't install convenience library used for the tests --- test/Makefile.am | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'test') diff --git a/test/Makefile.am b/test/Makefile.am index 26dd867..ca4965e 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -34,22 +34,20 @@ test_gactionmuxer_LDADD = \ # Lib containing code under test ###################################### -lib_LTLIBRARIES = \ +noinst_LTLIBRARIES = \ libindicator-messages-service.la -libindicator_messages_service_la_HEADERS = \ - $(top_srcdir)/src/gen-messages-service.xml.h \ - $(top_srcdir)/src/app-section.h \ - $(top_srcdir)/src/dbus-data.h \ - $(top_srcdir)/src/status-items.h \ - $(top_srcdir)/src/gactionmuxer.h - libindicator_messages_service_la_SOURCES = \ $(top_srcdir)/src/messages-service-dbus.c \ $(top_srcdir)/src/gen-messages-service.xml.c \ + $(top_srcdir)/src/gen-messages-service.xml.h \ $(top_srcdir)/src/app-section.c \ + $(top_srcdir)/src/app-section.h \ $(top_srcdir)/src/status-items.c \ - $(top_srcdir)/src/gactionmuxer.c + $(top_srcdir)/src/status-items.h \ + $(top_srcdir)/src/gactionmuxer.c \ + $(top_srcdir)/src/gactionmuxer.h + $(top_srcdir)/src/dbus-data.h libindicator_messages_service_ladir = \ $(includedir)/libindicator-messages-service/ -- cgit v1.2.3 From 3da349e33e434c13a27f956374e97c75ef0480a0 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 25 Jun 2012 22:40:59 +0200 Subject: Remove status providers Applications will be able to set and retrieve status through libmessaging-menu and telepathy. --- configure.ac | 23 -- po/POTFILES.in | 1 - src/Makefile.am | 193 +-------- ...indicator-messages-status-provider-0.5.pc.in.in | 15 - src/messages-service.c | 54 ++- src/status-items.c | 323 --------------- src/status-items.h | 36 -- src/status-provider-emesene.c | 348 ----------------- src/status-provider-emesene.h | 56 --- src/status-provider-mc5.c | 308 --------------- src/status-provider-mc5.h | 56 --- src/status-provider-mc5.list | 1 - src/status-provider-pidgin.c | 433 --------------------- src/status-provider-pidgin.h | 56 --- src/status-provider-pidgin.list | 1 - src/status-provider-telepathy.c | 385 ------------------ src/status-provider-telepathy.h | 56 --- src/status-provider-telepathy.list | 1 - src/status-provider.c | 101 ----- src/status-provider.h | 81 ---- test/Makefile.am | 8 +- 21 files changed, 53 insertions(+), 2483 deletions(-) delete mode 100644 src/indicator-messages-status-provider-0.5.pc.in.in delete mode 100644 src/status-items.c delete mode 100644 src/status-items.h delete mode 100644 src/status-provider-emesene.c delete mode 100644 src/status-provider-emesene.h delete mode 100644 src/status-provider-mc5.c delete mode 100644 src/status-provider-mc5.h delete mode 100644 src/status-provider-mc5.list delete mode 100644 src/status-provider-pidgin.c delete mode 100644 src/status-provider-pidgin.h delete mode 100644 src/status-provider-pidgin.list delete mode 100644 src/status-provider-telepathy.c delete mode 100644 src/status-provider-telepathy.h delete mode 100644 src/status-provider-telepathy.list delete mode 100644 src/status-provider.c delete mode 100644 src/status-provider.h (limited to 'test') diff --git a/configure.ac b/configure.ac index 9ef2438..11c9bd8 100644 --- a/configure.ac +++ b/configure.ac @@ -59,28 +59,6 @@ AC_SUBST(APPLET_LIBS) GLIB_GSETTINGS -########################### -# Status Provider Deps -########################### - -PKG_CHECK_MODULES(STATUS_PROVIDER_PIDGIN, dbus-glib-1) -AC_SUBST(STATUS_PROVIDER_PIDGIN_CFLAGS) -AC_SUBST(STATUS_PROVIDER_PIDGIN_LIBS) - -PKG_CHECK_MODULES(STATUS_PROVIDER_TELEPATHY, dbus-glib-1) -AC_SUBST(STATUS_PROVIDER_TELEPATHY_CFLAGS) -AC_SUBST(STATUS_PROVIDER_TELEPATHY_LIBS) - -TELEPATHYGLIB_REQUIRED_VERSION=0.9.0 -PKG_CHECK_MODULES(STATUS_PROVIDER_MC5, dbus-glib-1 - telepathy-glib >= $TELEPATHYGLIB_REQUIRED_VERSION) -AC_SUBST(STATUS_PROVIDER_MC5_CFLAGS) -AC_SUBST(STATUS_PROVIDER_MC5_LIBS) - -PKG_CHECK_MODULES(STATUS_PROVIDER_EMESENE, dbus-glib-1) -AC_SUBST(STATUS_PROVIDER_EMESENE_CFLAGS) -AC_SUBST(STATUS_PROVIDER_EMESENE_LIBS) - ########################### # gcov coverage reporting ########################### @@ -179,7 +157,6 @@ AM_GLIB_GNU_GETTEXT AC_OUTPUT([ Makefile src/Makefile -src/indicator-messages-status-provider-0.5.pc.in data/Makefile data/icons/Makefile data/icons/16x16/Makefile diff --git a/po/POTFILES.in b/po/POTFILES.in index 39d3ce7..21cd0b1 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -2,4 +2,3 @@ src/messages-service-dbus.c src/indicator-messages.c src/messages-service.c -src/status-items.c diff --git a/src/Makefile.am b/src/Makefile.am index 183d729..95a6258 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -45,8 +45,6 @@ indicator_messages_service_SOURCES = \ app-section.c \ app-section.h \ dbus-data.h \ - status-items.c \ - status-items.h \ gactionmuxer.c \ gactionmuxer.h @@ -58,12 +56,10 @@ indicator_messages_service_CFLAGS = \ -Wl,-z,defs \ -Wl,--as-needed \ -Werror \ - -DG_LOG_DOMAIN=\"Indicator-Messages\" \ - -DSTATUS_PROVIDER_DIR=\"$(STATUS_PROVIDER_DIR)\" + -DG_LOG_DOMAIN=\"Indicator-Messages\" indicator_messages_service_LDADD = \ - $(APPLET_LIBS) \ - libindicator-messages-status-provider.la + $(APPLET_LIBS) indicator_messages_service_LDFLAGS = \ $(COVERAGE_LDFLAGS) @@ -85,191 +81,6 @@ BUILT_SOURCES += \ EXTRA_DIST += \ messages-service.xml -###################################### -# Status Provider Library -###################################### - -STATUS_PROVIDER_API_VERSION = 1 -STATUS_PROVIDER_DIR = $(libexecdir)/status-providers/$(STATUS_PROVIDER_API_VERSION) -statusprovidersdir = $(STATUS_PROVIDER_DIR) -statusproviders_LTLIBRARIES = - -EXTRA_DIST += \ - indicator-messages-status-provider-0.5.pc.in.in -CLEANFILES += \ - indicator-messages-status-provider-0.5.pc - -pkgconfig_DATA = indicator-messages-status-provider-0.5.pc -pkgconfigdir = $(libdir)/pkgconfig - -%.pc: %.pc.in - sed \ - -e "s|\@status_provider_dir\@|$(STATUS_PROVIDER_DIR)|" \ - -e "s|\@status_provider_api_version\@|$(STATUS_PROVIDER_API_VERSION)|" \ - $< > $@ - -lib_LTLIBRARIES = \ - libindicator-messages-status-provider.la - -libindicator_messages_status_provider_la_HEADERS = \ - status-provider.h - -libindicator_messages_status_provider_la_SOURCES = \ - $(libindicator_messages_status_provider_HEADERS) \ - status-provider.c - -libindicator_messages_status_provider_ladir = \ - $(includedir)/libindicator-messages-status-provider-$(STATUS_PROVIDER_API_VERSION)/ - -libindicator_messages_status_provider_la_LDFLAGS = \ - -version-info $(STATUS_PROVIDER_API_VERSION):0:0 \ - -no-undefined \ - -export-symbols-regex "^[^_].*" - -libindicator_messages_status_provider_la_LIBADD = \ - $(APPLET_LIBS) - -libindicator_messages_status_provider_la_CFLAGS = \ - $(APPLET_CFLAGS) \ - -Wall -Werror - -###################################### -# Status provider: Pidgin -###################################### - -statusproviders_LTLIBRARIES += libpidgin.la -libpidgin_la_SOURCES = \ - status-provider-pidgin.h \ - status-provider-pidgin.c \ - status-provider-pidgin-marshal.h \ - status-provider-pidgin-marshal.c -libpidgin_la_CFLAGS = \ - $(APPLET_CFLAGS) \ - $(STATUS_PROVIDER_PIDGIN_CFLAGS) \ - -Wall -Werror \ - -DG_LOG_DOMAIN=\"Status-Provider-Pidgin\" -libpidgin_la_LIBADD = \ - libindicator-messages-status-provider.la \ - $(APPLET_LIBS) \ - $(STATUS_PROVIDER_PIDGIN_LIBS) -libpidgin_la_LDFLAGS = -module -avoid-version - -status-provider-pidgin-marshal.h: $(srcdir)/status-provider-pidgin.list - glib-genmarshal --header \ - --prefix=_status_provider_pidgin_marshal $(srcdir)/status-provider-pidgin.list \ - > status-provider-pidgin-marshal.h - -status-provider-pidgin-marshal.c: $(srcdir)/status-provider-pidgin.list - glib-genmarshal --body \ - --prefix=_status_provider_pidgin_marshal $(srcdir)/status-provider-pidgin.list \ - > status-provider-pidgin-marshal.c - -BUILT_SOURCES += \ - status-provider-pidgin-marshal.h \ - status-provider-pidgin-marshal.c - -EXTRA_DIST += \ - status-provider-pidgin.list - -###################################### -# Status provider: Mission Control 4 -###################################### - -statusproviders_LTLIBRARIES += libtelepathy.la -libtelepathy_la_SOURCES = \ - status-provider-telepathy.h \ - status-provider-telepathy.c \ - status-provider-telepathy-marshal.h \ - status-provider-telepathy-marshal.c -libtelepathy_la_CFLAGS = \ - $(APPLET_CFLAGS) \ - $(STATUS_PROVIDER_TELEPATHY_CFLAGS) \ - -Wall -Werror \ - -DG_LOG_DOMAIN=\"Status-Provider-Telepathy\" -libtelepathy_la_LIBADD = \ - libindicator-messages-status-provider.la \ - $(APPLET_LIBS) \ - $(STATUS_PROVIDER_TELEPATHY_LIBS) -libtelepathy_la_LDFLAGS = -module -avoid-version - -status-provider-telepathy-marshal.h: $(srcdir)/status-provider-telepathy.list - glib-genmarshal --header \ - --prefix=_status_provider_telepathy_marshal $(srcdir)/status-provider-telepathy.list \ - > status-provider-telepathy-marshal.h - -status-provider-telepathy-marshal.c: $(srcdir)/status-provider-telepathy.list - glib-genmarshal --body \ - --prefix=_status_provider_telepathy_marshal $(srcdir)/status-provider-telepathy.list \ - > status-provider-telepathy-marshal.c - -BUILT_SOURCES += \ - status-provider-telepathy-marshal.h \ - status-provider-telepathy-marshal.c - -EXTRA_DIST += \ - status-provider-telepathy.list - -###################################### -# Status provider: Mission Control 5 -###################################### - -statusproviders_LTLIBRARIES += libmc5.la -libmc5_la_SOURCES = \ - status-provider-mc5.h \ - status-provider-mc5.c \ - status-provider-mc5-marshal.h \ - status-provider-mc5-marshal.c -libmc5_la_CFLAGS = \ - $(APPLET_CFLAGS) \ - $(STATUS_PROVIDER_MC5_CFLAGS) \ - -Wall -Werror \ - -DG_LOG_DOMAIN=\"Status-Provider-MC5\" -libmc5_la_LIBADD = \ - libindicator-messages-status-provider.la \ - $(APPLET_LIBS) \ - $(STATUS_PROVIDER_MC5_LIBS) -libmc5_la_LDFLAGS = -module -avoid-version - -status-provider-mc5-marshal.h: $(srcdir)/status-provider-mc5.list - glib-genmarshal --header \ - --prefix=_status_provider_mc5_marshal $(srcdir)/status-provider-mc5.list \ - > status-provider-mc5-marshal.h - -status-provider-mc5-marshal.c: $(srcdir)/status-provider-mc5.list - glib-genmarshal --body \ - --prefix=_status_provider_mc5_marshal $(srcdir)/status-provider-mc5.list \ - > status-provider-mc5-marshal.c - -BUILT_SOURCES += \ - status-provider-mc5-marshal.h \ - status-provider-mc5-marshal.c - -EXTRA_DIST += \ - status-provider-mc5.list - -###################################### -# Status provider: Emesene -###################################### - -statusproviders_LTLIBRARIES += libemesene.la -libemesene_la_SOURCES = \ - status-provider-emesene.h \ - status-provider-emesene.c -libemesene_la_CFLAGS = \ - $(APPLET_CFLAGS) \ - $(STATUS_PROVIDER_EMESENE_CFLAGS) \ - -Wall -Werror \ - -DG_LOG_DOMAIN=\"Status-Provider-Emesene\" -libemesene_la_LIBADD = \ - libindicator-messages-status-provider.la \ - $(APPLET_LIBS) \ - $(STATUS_PROVIDER_EMESENE_LIBS) -libemesene_la_LDFLAGS = -module -avoid-version - -###################################### -# Extras -###################################### - CLEANFILES += \ $(BUILT_SOURCES) diff --git a/src/indicator-messages-status-provider-0.5.pc.in.in b/src/indicator-messages-status-provider-0.5.pc.in.in deleted file mode 100644 index 3fe4cf2..0000000 --- a/src/indicator-messages-status-provider-0.5.pc.in.in +++ /dev/null @@ -1,15 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -bindir=@bindir@ -includedir=@includedir@ - -statusproviderdir=@status_provider_dir@ - -Cflags: -I${includedir}/indicator-messages-status-provider-0.@status_provider_api_version@ -Requires: gobject-2.0 -Libs: -L${libdir} -lindicator-messages-status-provider - -Name: indicator-messages-status-provider -Description: Status providers for the indicator-messages menu. -Version: @VERSION@ diff --git a/src/messages-service.c b/src/messages-service.c index 203156e..9f4cddc 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -33,7 +33,6 @@ with this program. If not, see . #include "app-section.h" #include "dbus-data.h" #include "messages-service-dbus.h" -#include "status-items.h" #include "gactionmuxer.h" static IndicatorService * service = NULL; @@ -220,6 +219,22 @@ clear_action_activate (GSimpleAction *simple, message_service_dbus_set_attention(msg_service, FALSE); } +static void +radio_item_activate (GSimpleAction *action, + GVariant *parameter, + gpointer user_data) +{ + g_action_change_state (G_ACTION (action), parameter); +} + +static void +change_status (GSimpleAction *action, + GVariant *value, + gpointer user_data) +{ + g_message ("changing status to %s", g_variant_get_string (value, NULL)); +} + static void clear_action_handler (MessageServiceDbus *msd, gboolean attention, @@ -302,12 +317,42 @@ unregister_application (MessageServiceDbus *msd, g_strfreev (applications); } +static void +g_menu_append_with_icon (GMenu *menu, + const gchar *label, + const gchar *icon_name, + const gchar *detailed_action) +{ + GMenuItem *item; + + item = g_menu_item_new (label, detailed_action); + g_menu_item_set_attribute (item, INDICATOR_MENU_ATTRIBUTE_ICON_NAME, "s", icon_name); + + g_menu_append_item (menu, item); + g_object_unref (item); +} + +GMenuModel * +create_status_section () +{ + GMenu *menu; + + menu = g_menu_new (); + g_menu_append_with_icon (menu, _("Available"), "user-available", "status::available"); + g_menu_append_with_icon (menu, _("Away"), "user-away", "status::away"); + g_menu_append_with_icon (menu, _("Busy"), "user-busy", "status::busy"); + g_menu_append_with_icon (menu, _("Invisible"), "user-invisible", "status::invisible"); + g_menu_append_with_icon (menu, _("Offline"), "user-offline", "status::offline"); + + return G_MENU_MODEL (menu); +} + int main (int argc, char ** argv) { GError *error = NULL; GActionEntry entries[] = { - { "status", NULL, "s", "'offline'", NULL }, + { "status", radio_item_activate, "s", "'offline'", change_status }, { "clear", clear_action_activate } }; GMenuModel *status_items; @@ -357,9 +402,8 @@ main (int argc, char ** argv) g_signal_connect (dbus_interface, MESSAGE_SERVICE_DBUS_SIGNAL_UNREGISTER_APPLICATION, G_CALLBACK (unregister_application), NULL); - status_items = status_items_build (g_action_map_lookup_action (G_ACTION_MAP (actions), "status")); - menu = g_menu_new (); + status_items = create_status_section (); g_menu_append_section (menu, _("Status"), status_items); g_menu_append (menu, _("Clear"), "clear"); @@ -382,7 +426,7 @@ main (int argc, char ** argv) g_main_loop_run(mainloop); /* Clean up */ - status_items_cleanup(); + g_object_unref (status_items); g_object_unref (settings); g_hash_table_unref (applications); return 0; diff --git a/src/status-items.c b/src/status-items.c deleted file mode 100644 index a2e3a02..0000000 --- a/src/status-items.c +++ /dev/null @@ -1,323 +0,0 @@ -/* -Code to build and maintain the status adjustment menuitems. - -Copyright 2011 Canonical Ltd. - -Authors: - Ted Gould - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program. If not, see . -*/ - -#include -#include -#include - -#include "status-items.h" -#include "status-provider.h" -#include "dbus-data.h" - -static const gchar * status_ids [STATUS_PROVIDER_STATUS_LAST] = { - /* STATUS_PROVIDER_STATUS_ONLINE, */ "available", - /* STATUS_PROVIDER_STATUS_AWAY, */ "away", - /* STATUS_PROVIDER_STATUS_DND */ "busy", - /* STATUS_PROVIDER_STATUS_INVISIBLE */ "invisible", - /* STATUS_PROVIDER_STATUS_OFFLINE, */ "offline", - /* STATUS_PROVIDER_STATUS_DISCONNECTED*/ "offline" -}; - -static const gchar * status_strings [STATUS_PROVIDER_STATUS_LAST] = { - /* STATUS_PROVIDER_STATUS_ONLINE, */ N_("Available"), - /* STATUS_PROVIDER_STATUS_AWAY, */ N_("Away"), - /* STATUS_PROVIDER_STATUS_DND */ N_("Busy"), - /* STATUS_PROVIDER_STATUS_INVISIBLE */ N_("Invisible"), - /* STATUS_PROVIDER_STATUS_OFFLINE, */ N_("Offline"), - /* STATUS_PROVIDER_STATUS_DISCONNECTED*/ N_("Offline") -}; - -static const gchar * status_icons[STATUS_PROVIDER_STATUS_LAST] = { - /* STATUS_PROVIDER_STATUS_ONLINE, */ "user-available", - /* STATUS_PROVIDER_STATUS_AWAY, */ "user-away", - /* STATUS_PROVIDER_STATUS_DND, */ "user-busy", - /* STATUS_PROVIDER_STATUS_INVISIBLE, */ "user-invisible", - /* STATUS_PROVIDER_STATUS_OFFLINE */ "user-offline", - /* STATUS_PROVIDER_STATUS_DISCONNECTED */ "user-offline-panel" -}; - -static const gchar * panel_icons[STATUS_PROVIDER_STATUS_LAST] = { - /* STATUS_PROVIDER_STATUS_ONLINE, */ "indicator-messages-user-available", - /* STATUS_PROVIDER_STATUS_AWAY, */ "indicator-messages-user-away", - /* STATUS_PROVIDER_STATUS_DND, */ "indicator-messages-user-busy", - /* STATUS_PROVIDER_STATUS_INVISIBLE, */ "indicator-messages-user-invisible", - /* STATUS_PROVIDER_STATUS_OFFLINE */ "indicator-messages-user-offline", - /* STATUS_PROVIDER_STATUS_DISCONNECTED */ "indicator-messages-user-disconnected" -}; - -static const gchar * panel_active_icons[STATUS_PROVIDER_STATUS_LAST] = { - /* STATUS_PROVIDER_STATUS_ONLINE, */ "indicator-messages-new-user-available", - /* STATUS_PROVIDER_STATUS_AWAY, */ "indicator-messages-new-user-away", - /* STATUS_PROVIDER_STATUS_DND, */ "indicator-messages-new-user-busy", - /* STATUS_PROVIDER_STATUS_INVISIBLE, */ "indicator-messages-new-user-invisible", - /* STATUS_PROVIDER_STATUS_OFFLINE */ "indicator-messages-new-user-offline", - /* STATUS_PROVIDER_STATUS_DISCONNECTED */ "indicator-messages-new-user-disconnected" -}; - -/* Prototypes */ -static gboolean provider_directory_parse (gpointer dir); -static gboolean load_status_provider (gpointer dir); -static void user_status_change (GSimpleAction *action, - GVariant *value, - gpointer user_data); - -/* Globals */ -static StatusProviderStatus current_status = STATUS_PROVIDER_STATUS_DISCONNECTED; -static GMenu * menu; -static GAction *status_action; -static GList * status_providers = NULL; - -/* Build the inital status items and start kicking off the async code - for handling all the statuses */ -GMenuModel * -status_items_build (GAction *action) -{ - int i; - menu = g_menu_new (); - - status_action = action; - g_signal_connect (action, "change-state", G_CALLBACK (user_status_change), NULL); - - for (i = STATUS_PROVIDER_STATUS_ONLINE; i < STATUS_PROVIDER_STATUS_DISCONNECTED; i++) { - GMenuItem *item = g_menu_item_new (_(status_strings[i]), NULL); - - g_menu_item_set_action_and_target (item, g_action_get_name (action), "s", status_ids[i]); - - g_menu_item_set_attribute (item, INDICATOR_MENU_ATTRIBUTE_ICON_NAME, "s", status_icons[i]); - g_menu_item_set_attribute (item, INDICATOR_MENU_ATTRIBUTE_VISIBLE, "b", TRUE); - g_menu_item_set_attribute (item, INDICATOR_MENU_ATTRIBUTE_ENABLED, "b", FALSE); - - g_menu_append_item (menu, item); - g_object_unref (item); - } - - const gchar * status_providers_env = g_getenv("INDICATOR_MESSAGES_STATUS_PROVIDER_DIR"); - if (status_providers_env == NULL) { - g_idle_add(provider_directory_parse, STATUS_PROVIDER_DIR); - } else { - g_idle_add(provider_directory_parse, (gpointer)status_providers_env); - } - - return G_MENU_MODEL (menu); -} - -/* Clean up our globals and stop with all this allocation - of memory */ -void -status_items_cleanup (void) -{ - while (status_providers != NULL) { - StatusProvider * sprovider = STATUS_PROVIDER(status_providers->data); - g_object_unref(sprovider); - status_providers = g_list_remove(status_providers, sprovider); - } - - return; -} - -/* Get the icon that should be shown on the panel */ -const gchar * -status_current_panel_icon (gboolean alert) -{ - if (alert) { - return panel_active_icons[current_status]; - } else { - return panel_icons[current_status]; - } -} - -/* Update status from all the providers */ -static void -update_status (void) -{ - StatusProviderStatus status = STATUS_PROVIDER_STATUS_DISCONNECTED; - GList * provider; - - for (provider = status_providers; provider != NULL; provider = g_list_next(provider)) { - StatusProviderStatus localstatus = status_provider_get_status(STATUS_PROVIDER(provider->data)); - - if (localstatus < status) { - status = localstatus; - } - } - - if (status == current_status) { - return; - } - - current_status = status; - - g_action_change_state (status_action, g_variant_new_string (status_ids[current_status])); - - return; -} - -/* Handle the user requesting a status change */ -static void -user_status_change (GSimpleAction *action, - GVariant *value, - gpointer user_data) -{ - const gchar *status_id; - int i; - StatusProviderStatus status = STATUS_PROVIDER_STATUS_DISCONNECTED; - GList * provider; - - g_return_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)); - - status_id = g_variant_get_string (value, NULL); - - for (i = STATUS_PROVIDER_STATUS_ONLINE; i < STATUS_PROVIDER_STATUS_DISCONNECTED; i++) { - if (!strcmp (status_id, status_ids [i])) { - status = i; - break; - } - } - - /* Set each provider to this status */ - for (provider = status_providers; provider != NULL; provider = g_list_next(provider)) { - status_provider_set_status(STATUS_PROVIDER(provider->data), status); - } - - /* See what we really are now */ - update_status(); - return; -} - -/* Start parsing a directory and setting up the entires in the idle loop */ -static gboolean -provider_directory_parse (gpointer directory) -{ - const gchar * dirname = (const gchar *)directory; - g_debug("Looking for status providers in: %s", dirname); - - if (!g_file_test(dirname, G_FILE_TEST_EXISTS)) { - return FALSE; - } - - GDir * dir = g_dir_open(dirname, 0, NULL); - if (dir == NULL) { - return FALSE; - } - - const gchar * name; - while ((name = g_dir_read_name(dir)) != NULL) { - if (!g_str_has_suffix(name, G_MODULE_SUFFIX)) { - continue; - } - - gchar * fullname = g_build_filename(dirname, name, NULL); - g_idle_add(load_status_provider, fullname); - } - - g_dir_close(dir); - - return FALSE; -} - -/* Close the module as an idle function so that we know - it's all cleaned up */ -static gboolean -module_destroy_in_idle_helper (gpointer data) -{ - GModule * module = (GModule *)data; - if (module != NULL) { - g_debug("Unloading module: %s", g_module_name(module)); - g_module_close(module); - } - return FALSE; -} - -/* Set up an idle function to close the module */ -static void -module_destroy_in_idle (gpointer data) -{ - g_idle_add_full(G_PRIORITY_LOW, module_destroy_in_idle_helper, data, NULL); - return; -} - -/* Load a particular status provider */ -static gboolean -load_status_provider (gpointer dir) -{ - gchar * provider = dir; - - /* load the module */ - GModule * module = NULL; - if (g_file_test(provider, G_FILE_TEST_EXISTS)) { - g_debug("Loading status provider: %s", provider); - module = g_module_open(provider, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); - if (module == NULL) { - g_warning("Unable to open module: %s", provider); - } - } - - /* find the status provider's GType */ - GType provider_type = 0; - if (module != NULL) { - GType (*type_func) (void); - if (!g_module_symbol(module, STATUS_PROVIDER_EXPORT_S, (gpointer *)&type_func)) { - g_warning("Unable to find type symbol in: %s", provider); - } else { - provider_type = type_func(); - if (provider_type == 0) { - g_warning("Unable to create type from: %s", provider); - } - } - } - - /* instantiate the status provider */ - StatusProvider * sprovider = NULL; - if (provider_type != 0) { - sprovider = STATUS_PROVIDER(g_object_new(provider_type, NULL)); - if (sprovider == NULL) { - g_warning("Unable to build provider from: %s", provider); - } - } - - /* use the provider */ - if (sprovider != NULL) { - /* On update let's talk to all of them and create the aggregate - value to export */ - g_signal_connect(G_OBJECT(sprovider), - STATUS_PROVIDER_SIGNAL_STATUS_CHANGED, - G_CALLBACK(update_status), NULL); - - /* Attach the module object to the status provider so - that when the status provider is free'd the module - is closed automatically. */ - g_object_set_data_full(G_OBJECT(sprovider), - "status-provider-module", - module, module_destroy_in_idle); - module = NULL; /* don't close module in this func */ - - status_providers = g_list_prepend(status_providers, sprovider); - - /* Force an update to ensure a consistent state */ - update_status(); - } - - /* cleanup */ - if (module != NULL) - g_module_close(module); - g_free(provider); - return FALSE; /* only call this idle func once */ -} diff --git a/src/status-items.h b/src/status-items.h deleted file mode 100644 index ff35dfc..0000000 --- a/src/status-items.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -Code to build and maintain the status adjustment menuitems. - -Copyright 2011 Canonical Ltd. - -Authors: - Ted Gould - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program. If not, see . -*/ - -#ifndef __STATUS_ITEMS_H__ -#define __STATUS_ITEMS_H__ - -#include - -G_BEGIN_DECLS - -GMenuModel * status_items_build (GAction *action); -const gchar * status_current_panel_icon (gboolean alert); -void status_items_cleanup (void); - -G_END_DECLS - -#endif /* __STATUS_ITEMS_H__ */ - diff --git a/src/status-provider-emesene.c b/src/status-provider-emesene.c deleted file mode 100644 index 5aa6698..0000000 --- a/src/status-provider-emesene.c +++ /dev/null @@ -1,348 +0,0 @@ -/* -A small wrapper utility to load indicators and put them as menu items -into the gnome-panel using it's applet interface. - -Copyright 2011 Canonical Ltd. - -Authors: - Stefano Candori - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program. If not, see . -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "status-provider.h" -#include "status-provider-emesene.h" - -#include - -typedef enum { - EM_STATUS_ONLINE, - EM_STATUS_INVISIBLE, - EM_STATUS_BUSY, - EM_STATUS_AWAY, - EM_STATUS_IDLE, - EM_STATUS_OFFLINE -} em_status_t; - -static const StatusProviderStatus em_to_sp_map[] = { - /* EM_STATUS_ONLINE, */ STATUS_PROVIDER_STATUS_ONLINE, - /* EM_STATUS_INVISIBLE, */ STATUS_PROVIDER_STATUS_INVISIBLE, - /* EM_STATUS_BUSY, */ STATUS_PROVIDER_STATUS_DND, - /* EM_STATUS_AWAY, */ STATUS_PROVIDER_STATUS_AWAY, - /* EM_STATUS_IDLE, */ STATUS_PROVIDER_STATUS_AWAY, - /* EM_STATUS_OFFLINE, */ STATUS_PROVIDER_STATUS_OFFLINE -}; - -static const em_status_t sp_to_em_map[STATUS_PROVIDER_STATUS_LAST] = { - /* STATUS_PROVIDER_STATUS_ONLINE, */ EM_STATUS_ONLINE, - /* STATUS_PROVIDER_STATUS_AWAY, */ EM_STATUS_AWAY, - /* STATUS_PROVIDER_STATUS_DND */ EM_STATUS_BUSY, - /* STATUS_PROVIDER_STATUS_INVISIBLE*/ EM_STATUS_INVISIBLE, - /* STATUS_PROVIDER_STATUS_OFFLINE */ EM_STATUS_OFFLINE, - /* STATUS_PROVIDER_STATUS_DISCONNECTED*/ EM_STATUS_OFFLINE -}; - -typedef struct _StatusProviderEmesenePrivate StatusProviderEmesenePrivate; -struct _StatusProviderEmesenePrivate { - DBusGProxy * proxy; - DBusGProxy * dbus_proxy; - em_status_t em_status; -}; - -#define STATUS_PROVIDER_EMESENE_GET_PRIVATE(o) \ -(G_TYPE_INSTANCE_GET_PRIVATE ((o), STATUS_PROVIDER_EMESENE_TYPE, StatusProviderEmesenePrivate)) - -/* Prototypes */ -/* GObject stuff */ -static void status_provider_emesene_class_init (StatusProviderEmeseneClass *klass); -static void status_provider_emesene_init (StatusProviderEmesene *self); -static void status_provider_emesene_dispose (GObject *object); -static void status_provider_emesene_finalize (GObject *object); -/* Internal Funcs */ -static void set_status (StatusProvider * sp, StatusProviderStatus status); -static StatusProviderStatus get_status (StatusProvider * sp); -static void setup_emesene_proxy (StatusProviderEmesene * self); -static void dbus_namechange (DBusGProxy * proxy, const gchar * name, const gchar * prev, const gchar * new, StatusProviderEmesene * self); - -G_DEFINE_TYPE (StatusProviderEmesene, status_provider_emesene, STATUS_PROVIDER_TYPE); - -STATUS_PROVIDER_EXPORT_TYPE(STATUS_PROVIDER_EMESENE_TYPE) - -static void -status_provider_emesene_class_init (StatusProviderEmeseneClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (StatusProviderEmesenePrivate)); - - object_class->dispose = status_provider_emesene_dispose; - object_class->finalize = status_provider_emesene_finalize; - - StatusProviderClass * spclass = STATUS_PROVIDER_CLASS(klass); - - spclass->set_status = set_status; - spclass->get_status = get_status; - - return; -} - -static void -status_cb (DBusGProxy * proxy, DBusGProxyCall * call, gpointer userdata) -{ - StatusProviderEmesene * spe = STATUS_PROVIDER_EMESENE(userdata); - StatusProviderEmesenePrivate * priv = STATUS_PROVIDER_EMESENE_GET_PRIVATE(spe); - - GError * error = NULL; - gint status = 0; - if (!dbus_g_proxy_end_call(proxy, call, &error, G_TYPE_INT, &status, G_TYPE_INVALID)) { - g_warning("Unable to get status from Emesene: %s", error->message); - g_error_free(error); - return; - } - - priv->em_status = status; - g_signal_emit(G_OBJECT(spe), STATUS_PROVIDER_SIGNAL_STATUS_CHANGED_ID, 0, em_to_sp_map[priv->em_status], TRUE); - return; -} - -static void -changed_status (DBusGProxy * proxy, gint status, StatusProviderEmesene * spe) -{ - StatusProviderEmesenePrivate * priv = STATUS_PROVIDER_EMESENE_GET_PRIVATE(spe); - g_debug("Emesene changed status to %d", status); - priv->em_status = status; - g_signal_emit(G_OBJECT(spe), STATUS_PROVIDER_SIGNAL_STATUS_CHANGED_ID, 0, em_to_sp_map[priv->em_status], TRUE); - return; -} - -static void -proxy_destroy (DBusGProxy * proxy, StatusProviderEmesene * spe) -{ - StatusProviderEmesenePrivate * priv = STATUS_PROVIDER_EMESENE_GET_PRIVATE(spe); - - priv->proxy = NULL; - priv->em_status = EM_STATUS_OFFLINE; - - g_signal_emit(G_OBJECT(spe), STATUS_PROVIDER_SIGNAL_STATUS_CHANGED_ID, 0, em_to_sp_map[priv->em_status], TRUE); - return; -} - -static void -status_provider_emesene_init (StatusProviderEmesene *self) -{ - StatusProviderEmesenePrivate * priv = STATUS_PROVIDER_EMESENE_GET_PRIVATE(self); - - priv->proxy = NULL; - priv->em_status = EM_STATUS_OFFLINE; - - DBusGConnection * bus = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); - g_return_if_fail(bus != NULL); /* Can't do anymore DBus stuff without this, - all non-DBus stuff should be done */ - - GError * error = NULL; - - /* Set up the dbus Proxy */ - priv->dbus_proxy = dbus_g_proxy_new_for_name_owner (bus, - DBUS_SERVICE_DBUS, - DBUS_PATH_DBUS, - DBUS_INTERFACE_DBUS, - &error); - if (error != NULL) { - g_warning("Unable to connect to DBus events: %s", error->message); - g_error_free(error); - return; - } - - /* Configure the name owner changing */ - dbus_g_proxy_add_signal(priv->dbus_proxy, "NameOwnerChanged", - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_INVALID); - dbus_g_proxy_connect_signal(priv->dbus_proxy, "NameOwnerChanged", - G_CALLBACK(dbus_namechange), - self, NULL); - - setup_emesene_proxy(self); - - return; -} - -/* Watch to see if the Emesene comes up on Dbus */ -static void -dbus_namechange (DBusGProxy * proxy, const gchar * name, const gchar * prev, const gchar * new, StatusProviderEmesene * self) -{ - g_return_if_fail(name != NULL); - g_return_if_fail(new != NULL); - - if (g_strcmp0(name, "org.emesene.Service") == 0) { - setup_emesene_proxy(self); - } - return; -} - -/* Setup the Emesene proxy so that we can talk to it - and get signals from it. */ -static void -setup_emesene_proxy (StatusProviderEmesene * self) -{ - StatusProviderEmesenePrivate * priv = STATUS_PROVIDER_EMESENE_GET_PRIVATE(self); - - if (priv->proxy != NULL) { - g_debug("Doh!We were asked to set up a Emesene proxy when we already had one."); - return; - } - - DBusGConnection * bus = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); - g_return_if_fail(bus != NULL); /* Can't do anymore DBus stuff without this, - all non-DBus stuff should be done */ - - GError * error = NULL; - - /* Set up the Emesene Proxy */ - priv->proxy = dbus_g_proxy_new_for_name_owner (bus, - "org.emesene.Service", - "/org/emesene/Service", - "org.emesene.Service", - &error); - /* Report any errors */ - if (error != NULL) { - g_debug("Unable to get Emesene proxy: %s", error->message); - g_error_free(error); - } - - /* If we have a proxy, let's start using it */ - if (priv->proxy != NULL) { - /* Set the proxy to NULL if it's destroyed */ - g_object_add_weak_pointer (G_OBJECT(priv->proxy), (gpointer *)&priv->proxy); - /* If it's destroyed, let's clean up as well */ - g_signal_connect(G_OBJECT(priv->proxy), "destroy", - G_CALLBACK(proxy_destroy), self); - - /* Watching for the status change coming from the - Emesene side of things. */ - g_debug("Adding Emesene Signals"); - dbus_g_proxy_add_signal (priv->proxy, - "status_changed", - G_TYPE_INT, - G_TYPE_INVALID); - dbus_g_proxy_connect_signal(priv->proxy, - "status_changed", - G_CALLBACK(changed_status), - (void *)self, - NULL); - - /* Get the current status to update our cached - value of the status. */ - dbus_g_proxy_begin_call(priv->proxy, - "get_status", - status_cb, - self, - NULL, - G_TYPE_INVALID); - } - - return; -} - -static void -status_provider_emesene_dispose (GObject *object) -{ - StatusProviderEmesenePrivate * priv = STATUS_PROVIDER_EMESENE_GET_PRIVATE(object); - - if (priv->proxy != NULL) { - g_object_unref(priv->proxy); - priv->proxy = NULL; - } - - G_OBJECT_CLASS (status_provider_emesene_parent_class)->dispose (object); - return; -} - -static void -status_provider_emesene_finalize (GObject *object) -{ - - G_OBJECT_CLASS (status_provider_emesene_parent_class)->finalize (object); - return; -} - -/** - status_provider_emesene_new: - - Creates a new #StatusProviderEmesene object. No parameters or anything - like that. Just a convience function. - - Return value: A new instance of #StatusProviderEmesene -*/ -StatusProvider * -status_provider_emesene_new (void) -{ - return STATUS_PROVIDER(g_object_new(STATUS_PROVIDER_EMESENE_TYPE, NULL)); -} - -/* Takes the status provided generically for Status providers - and turns it into a Emesene status and sends it to Emesene. */ -static void -set_status (StatusProvider * sp, StatusProviderStatus status) -{ - g_return_if_fail(IS_STATUS_PROVIDER_EMESENE(sp)); - StatusProviderEmesenePrivate * priv = STATUS_PROVIDER_EMESENE_GET_PRIVATE(sp); - - g_debug("Emesene set status to %d", status); - if (priv->proxy == NULL) { - return; - } - - priv->em_status = sp_to_em_map[status]; - - gboolean ret = FALSE; - GError * error = NULL; - - ret = dbus_g_proxy_call(priv->proxy, - "set_status", &error, - G_TYPE_INT, priv->em_status, - G_TYPE_INVALID, - G_TYPE_INVALID); - - if (!ret) { - if (error != NULL) { - g_warning("Emesene unable to change to status: %s", error->message); - g_error_free(error); - } else { - g_warning("Emesene unable to change to status"); - } - error = NULL; - } - - g_signal_emit(G_OBJECT(sp), STATUS_PROVIDER_SIGNAL_STATUS_CHANGED_ID, 0, em_to_sp_map[priv->em_status], TRUE); - return; -} - -/* Takes the cached Emesene status and makes it into the generic - Status provider status. If there is no Emesene proxy then it - returns the disconnected state. */ -static StatusProviderStatus -get_status (StatusProvider * sp) -{ - g_return_val_if_fail(IS_STATUS_PROVIDER_EMESENE(sp), STATUS_PROVIDER_STATUS_DISCONNECTED); - StatusProviderEmesenePrivate * priv = STATUS_PROVIDER_EMESENE_GET_PRIVATE(sp); - - if (priv->proxy == NULL) { - return STATUS_PROVIDER_STATUS_DISCONNECTED; - } - - return em_to_sp_map[priv->em_status]; -} diff --git a/src/status-provider-emesene.h b/src/status-provider-emesene.h deleted file mode 100644 index 2309684..0000000 --- a/src/status-provider-emesene.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -A small wrapper utility to load indicators and put them as menu items -into the gnome-panel using it's applet interface. - -Copyright 20011 Canonical Ltd. - -Authors: - Stefano Candori - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program. If not, see . -*/ - -#ifndef __STATUS_PROVIDER_EMESENE_H__ -#define __STATUS_PROVIDER_EMESENE_H__ - -#include -#include - -#include "status-provider.h" - -G_BEGIN_DECLS - -#define STATUS_PROVIDER_EMESENE_TYPE (status_provider_emesene_get_type ()) -#define STATUS_PROVIDER_EMESENE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), STATUS_PROVIDER_EMESENE_TYPE, StatusProviderEmesene)) -#define STATUS_PROVIDER_EMESENE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), STATUS_PROVIDER_EMESENE_TYPE, StatusProviderEmeseneClass)) -#define IS_STATUS_PROVIDER_EMESENE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), STATUS_PROVIDER_EMESENE_TYPE)) -#define IS_STATUS_PROVIDER_EMESENE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), STATUS_PROVIDER_EMESENE_TYPE)) -#define STATUS_PROVIDER_EMESENE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), STATUS_PROVIDER_EMESENE_TYPE, StatusProviderEmeseneClass)) - - -typedef struct _StatusProviderEmeseneClass StatusProviderEmeseneClass; -struct _StatusProviderEmeseneClass { - StatusProviderClass parent_class; -}; - -typedef struct _StatusProviderEmesene StatusProviderEmesene; -struct _StatusProviderEmesene { - StatusProvider parent; -}; - -GType status_provider_emesene_get_type (void); -StatusProvider * status_provider_emesene_new (void); - -G_END_DECLS - -#endif diff --git a/src/status-provider-mc5.c b/src/status-provider-mc5.c deleted file mode 100644 index 3f23565..0000000 --- a/src/status-provider-mc5.c +++ /dev/null @@ -1,308 +0,0 @@ -/* -A small wrapper utility to load indicators and put them as menu items -into the gnome-panel using it's applet interface. - -Copyright 2009 Canonical Ltd. - -Authors: - Ted Gould - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program. If not, see . -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include - -#include "status-provider.h" -#include "status-provider-mc5.h" -#include "status-provider-mc5-marshal.h" - -#include -#include - -static gchar * sp_to_mc_map[STATUS_PROVIDER_STATUS_LAST] = { - /* STATUS_PROVIDER_STATUS_ONLINE, */ "available", - /* STATUS_PROVIDER_STATUS_AWAY, */ "away", - /* STATUS_PROVIDER_STATUS_DND */ "busy", - /* STATUS_PROVIDER_STATUS_INVISIBLE*/ "hidden", - /* STATUS_PROVIDER_STATUS_OFFLINE */ "offline", - /* STATUS_PROVIDER_STATUS_DISCONNECTED*/NULL -}; - -static TpConnectionPresenceType sp_to_tp_map[STATUS_PROVIDER_STATUS_LAST] = { - /* STATUS_PROVIDER_STATUS_ONLINE, */ TP_CONNECTION_PRESENCE_TYPE_AVAILABLE, - /* STATUS_PROVIDER_STATUS_AWAY, */ TP_CONNECTION_PRESENCE_TYPE_AWAY, - /* STATUS_PROVIDER_STATUS_DND */ TP_CONNECTION_PRESENCE_TYPE_BUSY, - /* STATUS_PROVIDER_STATUS_INVISIBLE*/ TP_CONNECTION_PRESENCE_TYPE_HIDDEN, - /* STATUS_PROVIDER_STATUS_OFFLINE */ TP_CONNECTION_PRESENCE_TYPE_OFFLINE, - /* STATUS_PROVIDER_STATUS_DISCONNECTED*/ TP_CONNECTION_PRESENCE_TYPE_UNSET -}; - -static StatusProviderStatus tp_to_sp_map[TP_CONNECTION_PRESENCE_TYPE_ERROR + 1] = { - /* TP_CONNECTION_PRESENCE_TYPE_UNSET */ STATUS_PROVIDER_STATUS_DISCONNECTED, - /* TP_CONNECTION_PRESENCE_TYPE_OFFLINE */ STATUS_PROVIDER_STATUS_OFFLINE, - /* TP_CONNECTION_PRESENCE_TYPE_AVAILABLE */ STATUS_PROVIDER_STATUS_ONLINE, - /* TP_CONNECTION_PRESENCE_TYPE_AWAY */ STATUS_PROVIDER_STATUS_AWAY, - /* TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY */ STATUS_PROVIDER_STATUS_AWAY, - /* TP_CONNECTION_PRESENCE_TYPE_HIDDEN */ STATUS_PROVIDER_STATUS_INVISIBLE, - /* TP_CONNECTION_PRESENCE_TYPE_BUSY */ STATUS_PROVIDER_STATUS_DND, - /* TP_CONNECTION_PRESENCE_TYPE_UNKNOWN */ STATUS_PROVIDER_STATUS_DISCONNECTED, - /* TP_CONNECTION_PRESENCE_TYPE_ERROR */ STATUS_PROVIDER_STATUS_DISCONNECTED -}; - -typedef struct _StatusProviderMC5Private StatusProviderMC5Private; -struct _StatusProviderMC5Private { - TpAccountManager * manager; - StatusProviderStatus status; - DBusGProxy * dbus_proxy; -}; - -#define STATUS_PROVIDER_MC5_GET_PRIVATE(o) \ -(G_TYPE_INSTANCE_GET_PRIVATE ((o), STATUS_PROVIDER_MC5_TYPE, StatusProviderMC5Private)) -#define MC5_WELL_KNOWN_NAME "org.freedesktop.Telepathy.AccountManager" - -/* Prototypes */ -/* GObject stuff */ -static void status_provider_mc5_class_init (StatusProviderMC5Class *klass); -static void status_provider_mc5_init (StatusProviderMC5 *self); -static void status_provider_mc5_dispose (GObject *object); -static void status_provider_mc5_finalize (GObject *object); -/* Internal Funcs */ -static void set_status (StatusProvider * sp, StatusProviderStatus status); -static StatusProviderStatus get_status (StatusProvider * sp); -static void presence_changed (TpAccountManager * eam, guint type, const gchar * type_str, const gchar * message, StatusProviderMC5 * sp); -static void dbus_namechange (DBusGProxy * proxy, const gchar * name, const gchar * prev, const gchar * new, StatusProviderMC5 * self); -static void mc5_exists_cb (DBusGProxy * proxy, gboolean exists, GError * error, gpointer userdata); - -G_DEFINE_TYPE (StatusProviderMC5, status_provider_mc5, STATUS_PROVIDER_TYPE); - -STATUS_PROVIDER_EXPORT_TYPE(STATUS_PROVIDER_MC5_TYPE) - -/* Create the class. We over ride a few functions but nothing - really shocking. Most interesting is the set and get status. */ -static void -status_provider_mc5_class_init (StatusProviderMC5Class *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (StatusProviderMC5Private)); - - object_class->dispose = status_provider_mc5_dispose; - object_class->finalize = status_provider_mc5_finalize; - - StatusProviderClass * spclass = STATUS_PROVIDER_CLASS(klass); - - spclass->set_status = set_status; - spclass->get_status = get_status; - - return; -} - -/* Build our telepathy account manager instance if we don't - have one. */ -static void -build_eam (StatusProviderMC5 * self) -{ - StatusProviderMC5Private * priv = STATUS_PROVIDER_MC5_GET_PRIVATE(self); - - if (priv->manager != NULL) { - return; - } - - priv->manager = tp_account_manager_dup(); - g_signal_connect(G_OBJECT(priv->manager), "most-available-presence-changed", G_CALLBACK(presence_changed), self); - - return; -} - -/* Creating an instance of the status provider. We set the variables - and create an TpAccountManager object. It does all the hard - work in this module of tracking MissionControl and enumerating the - accounts and all that jazz. */ -static void -status_provider_mc5_init (StatusProviderMC5 *self) -{ - StatusProviderMC5Private * priv = STATUS_PROVIDER_MC5_GET_PRIVATE(self); - - priv->status = STATUS_PROVIDER_STATUS_OFFLINE; - priv->manager = NULL; - - DBusGConnection * bus = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); - g_return_if_fail(bus != NULL); /* Can't do anymore DBus stuff without this, - all non-DBus stuff should be done */ - - GError * error = NULL; - - /* Set up the dbus Proxy */ - priv->dbus_proxy = dbus_g_proxy_new_for_name_owner (bus, - DBUS_SERVICE_DBUS, - DBUS_PATH_DBUS, - DBUS_INTERFACE_DBUS, - &error); - if (error != NULL) { - g_warning("Unable to connect to DBus events: %s", error->message); - g_error_free(error); - return; - } - - /* Configure the name owner changing */ - dbus_g_proxy_add_signal(priv->dbus_proxy, "NameOwnerChanged", - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_INVALID); - dbus_g_proxy_connect_signal(priv->dbus_proxy, "NameOwnerChanged", - G_CALLBACK(dbus_namechange), - self, NULL); - - org_freedesktop_DBus_name_has_owner_async(priv->dbus_proxy, MC5_WELL_KNOWN_NAME, mc5_exists_cb, self); - - return; -} - -/* Unref the account manager and move on. Sadly, we're - leaving the show. */ -static void -status_provider_mc5_dispose (GObject *object) -{ - StatusProviderMC5Private * priv = STATUS_PROVIDER_MC5_GET_PRIVATE(object); - - if (priv->manager != NULL) { - g_object_unref(priv->manager); - priv->manager = NULL; - } - - if (priv->dbus_proxy != NULL) { - g_object_unref(priv->dbus_proxy); - priv->dbus_proxy = NULL; - } - - G_OBJECT_CLASS (status_provider_mc5_parent_class)->dispose (object); - return; -} - -/* Pass to superclass */ -static void -status_provider_mc5_finalize (GObject *object) -{ - - G_OBJECT_CLASS (status_provider_mc5_parent_class)->finalize (object); - return; -} - -/* Watch for MC5 Coming on and off the bus. */ -static void -dbus_namechange (DBusGProxy * proxy, const gchar * name, const gchar * prev, const gchar * new, StatusProviderMC5 * self) -{ - /* g_debug("DBUS NAMECHANGE: %s %s %s", name, prev, new); */ - - if (prev[0] == '\0' && g_strcmp0(name, MC5_WELL_KNOWN_NAME) == 0) { - g_debug("MC5 Coming online"); - build_eam(self); - } - if (new[0] == '\0' && g_strcmp0(name, MC5_WELL_KNOWN_NAME) == 0) { - g_debug("MC5 going offline"); - StatusProviderMC5Private * priv = STATUS_PROVIDER_MC5_GET_PRIVATE(self); - if (priv->manager != NULL) { - g_object_unref(priv->manager); - priv->manager = NULL; - } - - priv->status = STATUS_PROVIDER_STATUS_OFFLINE; - g_signal_emit(G_OBJECT(self), STATUS_PROVIDER_SIGNAL_STATUS_CHANGED_ID, 0, priv->status, TRUE); - } - - return; -} - -/* Callback for the Dbus command to do HasOwner on - the MC5 service. If it exists, we want to have an - account manager. */ -static void -mc5_exists_cb (DBusGProxy * proxy, gboolean exists, GError * error, gpointer userdata) -{ - if (error) { - g_warning("Unable to check if MC5 is running: %s", error->message); - return; - } - - if (exists) { - build_eam(STATUS_PROVIDER_MC5(userdata)); - } - - return; -} - -/** - status_provider_mc5_new: - - Creates a new #StatusProviderMC5 object. No parameters or anything - like that. Just a convience function. - - Return value: A new instance of #StatusProviderMC5 -*/ -StatusProvider * -status_provider_mc5_new (void) -{ - return STATUS_PROVIDER(g_object_new(STATUS_PROVIDER_MC5_TYPE, NULL)); -} - -/* Setting the status in the empathy account manager. We're - basically requesting a global status. This may or may not - get applied to all accounts. It's really the best we can - hope to do. */ -static void -set_status (StatusProvider * sp, StatusProviderStatus status) -{ - StatusProviderMC5Private * priv = STATUS_PROVIDER_MC5_GET_PRIVATE(sp); - - build_eam(STATUS_PROVIDER_MC5(sp)); - tp_account_manager_set_all_requested_presences(priv->manager, sp_to_tp_map[status], sp_to_mc_map[status], ""); - - return; -} - -/* Gets the status, uses the cached value that we have. Asking - would just be painful. */ -static StatusProviderStatus -get_status (StatusProvider * sp) -{ - g_return_val_if_fail(IS_STATUS_PROVIDER_MC5(sp), STATUS_PROVIDER_STATUS_DISCONNECTED); - StatusProviderMC5Private * priv = STATUS_PROVIDER_MC5_GET_PRIVATE(sp); - - if (priv->manager == NULL) { - return STATUS_PROVIDER_STATUS_OFFLINE; - } - - return priv->status; -} - -/* A signal handler for when the TpAccountManager believes - that the global status has changed. It roughly calculates this - by finding the most available of all accounts that are active. */ -static void -presence_changed (TpAccountManager * eam, guint type, const gchar * type_str, const gchar * message, StatusProviderMC5 * sp) -{ - StatusProviderMC5Private * priv = STATUS_PROVIDER_MC5_GET_PRIVATE(sp); - - g_debug("MC5 Status changed: %d %s %s", type, type_str, message); - - if (priv->status != tp_to_sp_map[type]) { - priv->status = tp_to_sp_map[type]; - g_signal_emit(G_OBJECT(sp), STATUS_PROVIDER_SIGNAL_STATUS_CHANGED_ID, 0, priv->status, TRUE); - } - - return; -} - diff --git a/src/status-provider-mc5.h b/src/status-provider-mc5.h deleted file mode 100644 index 4d5659d..0000000 --- a/src/status-provider-mc5.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -A small wrapper utility to load indicators and put them as menu items -into the gnome-panel using it's applet interface. - -Copyright 2009 Canonical Ltd. - -Authors: - Ted Gould - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program. If not, see . -*/ - -#ifndef __STATUS_PROVIDER_MC5_H__ -#define __STATUS_PROVIDER_MC5_H__ - -#include -#include - -#include "status-provider.h" - -G_BEGIN_DECLS - -#define STATUS_PROVIDER_MC5_TYPE (status_provider_mc5_get_type ()) -#define STATUS_PROVIDER_MC5(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), STATUS_PROVIDER_MC5_TYPE, StatusProviderMC5)) -#define STATUS_PROVIDER_MC5_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), STATUS_PROVIDER_MC5_TYPE, StatusProviderMC5Class)) -#define IS_STATUS_PROVIDER_MC5(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), STATUS_PROVIDER_MC5_TYPE)) -#define IS_STATUS_PROVIDER_MC5_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), STATUS_PROVIDER_MC5_TYPE)) -#define STATUS_PROVIDER_MC5_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), STATUS_PROVIDER_MC5_TYPE, StatusProviderMC5Class)) - - -typedef struct _StatusProviderMC5Class StatusProviderMC5Class; -struct _StatusProviderMC5Class { - StatusProviderClass parent_class; -}; - -typedef struct _StatusProviderMC5 StatusProviderMC5; -struct _StatusProviderMC5 { - StatusProvider parent; -}; - -GType status_provider_mc5_get_type (void); -StatusProvider * status_provider_mc5_new (void); - -G_END_DECLS - -#endif diff --git a/src/status-provider-mc5.list b/src/status-provider-mc5.list deleted file mode 100644 index 5ab45bf..0000000 --- a/src/status-provider-mc5.list +++ /dev/null @@ -1 +0,0 @@ -VOID:UINT,STRING diff --git a/src/status-provider-pidgin.c b/src/status-provider-pidgin.c deleted file mode 100644 index 6c73d56..0000000 --- a/src/status-provider-pidgin.c +++ /dev/null @@ -1,433 +0,0 @@ -/* -A small wrapper utility to load indicators and put them as menu items -into the gnome-panel using it's applet interface. - -Copyright 2009 Canonical Ltd. - -Authors: - Ted Gould - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program. If not, see . -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "status-provider.h" -#include "status-provider-pidgin.h" -#include "status-provider-pidgin-marshal.h" - -#include - -typedef enum { - PG_STATUS_UNKNOWN, - PG_STATUS_OFFLINE, - PG_STATUS_AVAILABLE, - PG_STATUS_UNAVAILABLE, - PG_STATUS_INVISIBLE, - PG_STATUS_AWAY, - PG_STATUS_EXTENDEND_AWAY, - PG_STATUS_MOBILE, - PG_STATUS_TUNE -} pg_status_t; - -static const StatusProviderStatus pg_to_sp_map[] = { - /* PG_STATUS_UNKNOWN, */ STATUS_PROVIDER_STATUS_OFFLINE, - /* PG_STATUS_OFFLINE, */ STATUS_PROVIDER_STATUS_OFFLINE, - /* PG_STATUS_AVAILABLE, */ STATUS_PROVIDER_STATUS_ONLINE, - /* PG_STATUS_UNAVAILABLE, */ STATUS_PROVIDER_STATUS_DND, - /* PG_STATUS_INVISIBLE, */ STATUS_PROVIDER_STATUS_INVISIBLE, - /* PG_STATUS_AWAY, */ STATUS_PROVIDER_STATUS_AWAY, - /* PG_STATUS_EXTENDEND_AWAY, */ STATUS_PROVIDER_STATUS_AWAY, - /* PG_STATUS_MOBILE, */ STATUS_PROVIDER_STATUS_OFFLINE, - /* PG_STATUS_TUNE */ STATUS_PROVIDER_STATUS_OFFLINE -}; - -static const pg_status_t sp_to_pg_map[STATUS_PROVIDER_STATUS_LAST] = { - /* STATUS_PROVIDER_STATUS_ONLINE, */ PG_STATUS_AVAILABLE, - /* STATUS_PROVIDER_STATUS_AWAY, */ PG_STATUS_AWAY, - /* STATUS_PROVIDER_STATUS_DND */ PG_STATUS_UNAVAILABLE, - /* STATUS_PROVIDER_STATUS_INVISIBLE*/ PG_STATUS_INVISIBLE, - /* STATUS_PROVIDER_STATUS_OFFLINE */ PG_STATUS_OFFLINE, - /* STATUS_PROVIDER_STATUS_DISCONNECTED*/ PG_STATUS_OFFLINE -}; - -typedef struct _StatusProviderPidginPrivate StatusProviderPidginPrivate; -struct _StatusProviderPidginPrivate { - DBusGProxy * proxy; - DBusGProxy * dbus_proxy; - pg_status_t pg_status; -}; - -#define STATUS_PROVIDER_PIDGIN_GET_PRIVATE(o) \ -(G_TYPE_INSTANCE_GET_PRIVATE ((o), STATUS_PROVIDER_PIDGIN_TYPE, StatusProviderPidginPrivate)) - -/* Prototypes */ -/* GObject stuff */ -static void status_provider_pidgin_class_init (StatusProviderPidginClass *klass); -static void status_provider_pidgin_init (StatusProviderPidgin *self); -static void status_provider_pidgin_dispose (GObject *object); -static void status_provider_pidgin_finalize (GObject *object); -/* Internal Funcs */ -static void set_status (StatusProvider * sp, StatusProviderStatus status); -static StatusProviderStatus get_status (StatusProvider * sp); -static void setup_pidgin_proxy (StatusProviderPidgin * self); -static void dbus_namechange (DBusGProxy * proxy, const gchar * name, const gchar * prev, const gchar * new, StatusProviderPidgin * self); - -G_DEFINE_TYPE (StatusProviderPidgin, status_provider_pidgin, STATUS_PROVIDER_TYPE); - -STATUS_PROVIDER_EXPORT_TYPE(STATUS_PROVIDER_PIDGIN_TYPE) - -static void -status_provider_pidgin_class_init (StatusProviderPidginClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (StatusProviderPidginPrivate)); - - object_class->dispose = status_provider_pidgin_dispose; - object_class->finalize = status_provider_pidgin_finalize; - - StatusProviderClass * spclass = STATUS_PROVIDER_CLASS(klass); - - spclass->set_status = set_status; - spclass->get_status = get_status; - - return; -} - -static void -type_cb (DBusGProxy * proxy, DBusGProxyCall * call, gpointer userdata) -{ - GError * error = NULL; - gint status = 0; - if (!dbus_g_proxy_end_call(proxy, call, &error, G_TYPE_INT, &status, G_TYPE_INVALID)) { - g_warning("Unable to get type from Pidgin: %s", error->message); - g_error_free(error); - return; - } - - StatusProviderPidginPrivate * priv = STATUS_PROVIDER_PIDGIN_GET_PRIVATE(userdata); - if (status != priv->pg_status) { - priv->pg_status = status; - - g_signal_emit(G_OBJECT(userdata), STATUS_PROVIDER_SIGNAL_STATUS_CHANGED_ID, 0, pg_to_sp_map[priv->pg_status], TRUE); - } - - return; -} - -static void -saved_status_to_type (StatusProviderPidgin * spp, gint savedstatus) -{ - StatusProviderPidginPrivate * priv = STATUS_PROVIDER_PIDGIN_GET_PRIVATE(spp); - - g_debug("Pidgin figuring out type for %d", savedstatus); - dbus_g_proxy_begin_call(priv->proxy, - "PurpleSavedstatusGetType", type_cb, spp, NULL, - G_TYPE_INT, savedstatus, G_TYPE_INVALID); - - return; -} - -static void -savedstatus_cb (DBusGProxy * proxy, DBusGProxyCall * call, gpointer userdata) -{ - GError * error = NULL; - gint status = 0; - if (!dbus_g_proxy_end_call(proxy, call, &error, G_TYPE_INT, &status, G_TYPE_INVALID)) { - g_warning("Unable to get saved status from Pidgin: %s", error->message); - g_error_free(error); - return; - } - - saved_status_to_type(STATUS_PROVIDER_PIDGIN(userdata), status); - return; -} - - -static void -changed_status (DBusGProxy * proxy, gint savedstatus, GError ** error, StatusProviderPidgin * spp) -{ - saved_status_to_type(spp, savedstatus); - return; -} - -static void -proxy_destroy (DBusGProxy * proxy, StatusProviderPidgin * spp) -{ - StatusProviderPidginPrivate * priv = STATUS_PROVIDER_PIDGIN_GET_PRIVATE(spp); - - priv->proxy = NULL; - priv->pg_status = PG_STATUS_OFFLINE; - - g_signal_emit(G_OBJECT(spp), STATUS_PROVIDER_SIGNAL_STATUS_CHANGED_ID, 0, pg_to_sp_map[priv->pg_status], TRUE); - return; -} - -static void -status_provider_pidgin_init (StatusProviderPidgin *self) -{ - StatusProviderPidginPrivate * priv = STATUS_PROVIDER_PIDGIN_GET_PRIVATE(self); - - priv->proxy = NULL; - priv->pg_status = PG_STATUS_OFFLINE; - - DBusGConnection * bus = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); - g_return_if_fail(bus != NULL); /* Can't do anymore DBus stuff without this, - all non-DBus stuff should be done */ - - GError * error = NULL; - - /* Set up the dbus Proxy */ - priv->dbus_proxy = dbus_g_proxy_new_for_name_owner (bus, - DBUS_SERVICE_DBUS, - DBUS_PATH_DBUS, - DBUS_INTERFACE_DBUS, - &error); - if (error != NULL) { - g_warning("Unable to connect to DBus events: %s", error->message); - g_error_free(error); - return; - } - - /* Configure the name owner changing */ - dbus_g_proxy_add_signal(priv->dbus_proxy, "NameOwnerChanged", - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_INVALID); - dbus_g_proxy_connect_signal(priv->dbus_proxy, "NameOwnerChanged", - G_CALLBACK(dbus_namechange), - self, NULL); - - setup_pidgin_proxy(self); - - return; -} - -/* Watch to see if the Pidgin comes up on Dbus */ -static void -dbus_namechange (DBusGProxy * proxy, const gchar * name, const gchar * prev, const gchar * new, StatusProviderPidgin * self) -{ - g_return_if_fail(name != NULL); - g_return_if_fail(new != NULL); - - if (g_strcmp0(name, "im.pidgin.purple.PurpleService") == 0) { - setup_pidgin_proxy(self); - } - return; -} - -/* Setup the Pidgin proxy so that we can talk to it - and get signals from it. */ -static void -setup_pidgin_proxy (StatusProviderPidgin * self) -{ - StatusProviderPidginPrivate * priv = STATUS_PROVIDER_PIDGIN_GET_PRIVATE(self); - - if (priv->proxy != NULL) { - g_debug("Odd, we were asked to set up a Pidgin proxy when we already had one."); - return; - } - - DBusGConnection * bus = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); - g_return_if_fail(bus != NULL); /* Can't do anymore DBus stuff without this, - all non-DBus stuff should be done */ - - GError * error = NULL; - - /* Set up the Pidgin Proxy */ - priv->proxy = dbus_g_proxy_new_for_name_owner (bus, - "im.pidgin.purple.PurpleService", - "/im/pidgin/purple/PurpleObject", - "im.pidgin.purple.PurpleInterface", - &error); - /* Report any errors */ - if (error != NULL) { - g_debug("Unable to get Pidgin proxy: %s", error->message); - g_error_free(error); - } - - /* If we have a proxy, let's start using it */ - if (priv->proxy != NULL) { - /* Set the proxy to NULL if it's destroyed */ - g_object_add_weak_pointer (G_OBJECT(priv->proxy), (gpointer *)&priv->proxy); - /* If it's destroyed, let's clean up as well */ - g_signal_connect(G_OBJECT(priv->proxy), "destroy", - G_CALLBACK(proxy_destroy), self); - - /* Watching for the status change coming from the - Pidgin side of things. */ - g_debug("Adding Pidgin Signals"); - dbus_g_object_register_marshaller(_status_provider_pidgin_marshal_VOID__INT_INT, - G_TYPE_NONE, - G_TYPE_INT, - G_TYPE_INT, - G_TYPE_INVALID); - dbus_g_proxy_add_signal (priv->proxy, - "SavedstatusChanged", - G_TYPE_INT, - G_TYPE_INT, - G_TYPE_INVALID); - dbus_g_proxy_connect_signal(priv->proxy, - "SavedstatusChanged", - G_CALLBACK(changed_status), - (void *)self, - NULL); - - /* Get the current status to update our cached - value of the status. */ - dbus_g_proxy_begin_call(priv->proxy, - "PurpleSavedstatusGetCurrent", - savedstatus_cb, - self, - NULL, - G_TYPE_INVALID); - } - - return; -} - -static void -status_provider_pidgin_dispose (GObject *object) -{ - StatusProviderPidginPrivate * priv = STATUS_PROVIDER_PIDGIN_GET_PRIVATE(object); - - if (priv->proxy != NULL) { - g_object_unref(priv->proxy); - priv->proxy = NULL; - } - - G_OBJECT_CLASS (status_provider_pidgin_parent_class)->dispose (object); - return; -} - -static void -status_provider_pidgin_finalize (GObject *object) -{ - - G_OBJECT_CLASS (status_provider_pidgin_parent_class)->finalize (object); - return; -} - -/** - status_provider_pidgin_new: - - Creates a new #StatusProviderPidgin object. No parameters or anything - like that. Just a convience function. - - Return value: A new instance of #StatusProviderPidgin -*/ -StatusProvider * -status_provider_pidgin_new (void) -{ - return STATUS_PROVIDER(g_object_new(STATUS_PROVIDER_PIDGIN_TYPE, NULL)); -} - -/* Takes the status provided generically for Status providers - and turns it into a Pidgin status and sends it to Pidgin. */ -static void -set_status (StatusProvider * sp, StatusProviderStatus status) -{ - gchar * message = ""; - - g_return_if_fail(IS_STATUS_PROVIDER_PIDGIN(sp)); - StatusProviderPidginPrivate * priv = STATUS_PROVIDER_PIDGIN_GET_PRIVATE(sp); - - g_debug("\tPidgin set status to %d", status); - if (priv->proxy == NULL) { - return; - } - - priv->pg_status = sp_to_pg_map[status]; - gint status_val = 0; - gboolean ret = FALSE; - GError * error = NULL; - - ret = dbus_g_proxy_call(priv->proxy, - "PurpleSavedstatusFindTransientByTypeAndMessage", &error, - G_TYPE_INT, priv->pg_status, - G_TYPE_STRING, message, - G_TYPE_INVALID, - G_TYPE_INT, &status_val, - G_TYPE_INVALID); - - if (!ret) { - if (error != NULL) { - g_error_free(error); - } - error = NULL; - status_val = 0; - g_debug("No Pidgin saved status to apply"); - } - - if (status_val == 0) { - ret = dbus_g_proxy_call(priv->proxy, - "PurpleSavedstatusNew", &error, - G_TYPE_STRING, message, - G_TYPE_INT, priv->pg_status, - G_TYPE_INVALID, - G_TYPE_INT, &status_val, - G_TYPE_INVALID); - - if (!ret) { - status_val = 0; - if (error != NULL) { - g_warning("Unable to create Pidgin status for %d: %s", status, error->message); - g_error_free(error); - } else { - g_warning("Unable to create Pidgin status for %d", status); - } - error = NULL; - } - } - - if (status_val == 0) { - return; - } - - ret = dbus_g_proxy_call(priv->proxy, - "PurpleSavedstatusActivate", &error, - G_TYPE_INT, status_val, - G_TYPE_INVALID, - G_TYPE_INVALID); - - if (!ret) { - if (error != NULL) { - g_warning("Pidgin unable to change to status: %s", error->message); - g_error_free(error); - } else { - g_warning("Pidgin unable to change to status"); - } - error = NULL; - } - - g_signal_emit(G_OBJECT(sp), STATUS_PROVIDER_SIGNAL_STATUS_CHANGED_ID, 0, pg_to_sp_map[priv->pg_status], TRUE); - return; -} - -/* Takes the cached Pidgin status and makes it into the generic - Status provider status. If there is no Pidgin proxy then it - returns the disconnected state. */ -static StatusProviderStatus -get_status (StatusProvider * sp) -{ - g_return_val_if_fail(IS_STATUS_PROVIDER_PIDGIN(sp), STATUS_PROVIDER_STATUS_DISCONNECTED); - StatusProviderPidginPrivate * priv = STATUS_PROVIDER_PIDGIN_GET_PRIVATE(sp); - - if (priv->proxy == NULL) { - return STATUS_PROVIDER_STATUS_DISCONNECTED; - } - - return pg_to_sp_map[priv->pg_status]; -} diff --git a/src/status-provider-pidgin.h b/src/status-provider-pidgin.h deleted file mode 100644 index 54b1718..0000000 --- a/src/status-provider-pidgin.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -A small wrapper utility to load indicators and put them as menu items -into the gnome-panel using it's applet interface. - -Copyright 2009 Canonical Ltd. - -Authors: - Ted Gould - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program. If not, see . -*/ - -#ifndef __STATUS_PROVIDER_PIDGIN_H__ -#define __STATUS_PROVIDER_PIDGIN_H__ - -#include -#include - -#include "status-provider.h" - -G_BEGIN_DECLS - -#define STATUS_PROVIDER_PIDGIN_TYPE (status_provider_pidgin_get_type ()) -#define STATUS_PROVIDER_PIDGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), STATUS_PROVIDER_PIDGIN_TYPE, StatusProviderPidgin)) -#define STATUS_PROVIDER_PIDGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), STATUS_PROVIDER_PIDGIN_TYPE, StatusProviderPidginClass)) -#define IS_STATUS_PROVIDER_PIDGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), STATUS_PROVIDER_PIDGIN_TYPE)) -#define IS_STATUS_PROVIDER_PIDGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), STATUS_PROVIDER_PIDGIN_TYPE)) -#define STATUS_PROVIDER_PIDGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), STATUS_PROVIDER_PIDGIN_TYPE, StatusProviderPidginClass)) - - -typedef struct _StatusProviderPidginClass StatusProviderPidginClass; -struct _StatusProviderPidginClass { - StatusProviderClass parent_class; -}; - -typedef struct _StatusProviderPidgin StatusProviderPidgin; -struct _StatusProviderPidgin { - StatusProvider parent; -}; - -GType status_provider_pidgin_get_type (void); -StatusProvider * status_provider_pidgin_new (void); - -G_END_DECLS - -#endif diff --git a/src/status-provider-pidgin.list b/src/status-provider-pidgin.list deleted file mode 100644 index 1f953dd..0000000 --- a/src/status-provider-pidgin.list +++ /dev/null @@ -1 +0,0 @@ -VOID:INT,INT diff --git a/src/status-provider-telepathy.c b/src/status-provider-telepathy.c deleted file mode 100644 index 948e965..0000000 --- a/src/status-provider-telepathy.c +++ /dev/null @@ -1,385 +0,0 @@ -/* -A small wrapper utility to load indicators and put them as menu items -into the gnome-panel using it's applet interface. - -Copyright 2009 Canonical Ltd. - -Authors: - Ted Gould - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program. If not, see . -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "status-provider.h" -#include "status-provider-telepathy.h" -#include "status-provider-telepathy-marshal.h" - -#include - -typedef enum { - MC_STATUS_UNSET, - MC_STATUS_OFFLINE, - MC_STATUS_AVAILABLE, - MC_STATUS_AWAY, - MC_STATUS_EXTENDED_AWAY, - MC_STATUS_HIDDEN, - MC_STATUS_DND -} mc_status_t; - -static StatusProviderStatus mc_to_sp_map[] = { - /* MC_STATUS_UNSET, */ STATUS_PROVIDER_STATUS_OFFLINE, - /* MC_STATUS_OFFLINE, */ STATUS_PROVIDER_STATUS_OFFLINE, - /* MC_STATUS_AVAILABLE, */ STATUS_PROVIDER_STATUS_ONLINE, - /* MC_STATUS_AWAY, */ STATUS_PROVIDER_STATUS_AWAY, - /* MC_STATUS_EXTENDED_AWAY, */ STATUS_PROVIDER_STATUS_AWAY, - /* MC_STATUS_HIDDEN, */ STATUS_PROVIDER_STATUS_INVISIBLE, - /* MC_STATUS_DND */ STATUS_PROVIDER_STATUS_DND -}; - -static mc_status_t sp_to_mc_map[] = { - /* STATUS_PROVIDER_STATUS_ONLINE, */ MC_STATUS_AVAILABLE, - /* STATUS_PROVIDER_STATUS_AWAY, */ MC_STATUS_AWAY, - /* STATUS_PROVIDER_STATUS_DND */ MC_STATUS_DND, - /* STATUS_PROVIDER_STATUS_INVISIBLE*/ MC_STATUS_HIDDEN, - /* STATUS_PROVIDER_STATUS_OFFLINE */ MC_STATUS_OFFLINE, - /* STATUS_PROVIDER_STATUS_DISCONNECTED*/MC_STATUS_OFFLINE -}; - -typedef struct _StatusProviderTelepathyPrivate StatusProviderTelepathyPrivate; -struct _StatusProviderTelepathyPrivate { - DBusGProxy * proxy; - DBusGProxy * dbus_proxy; - mc_status_t mc_status; -}; - -#define STATUS_PROVIDER_TELEPATHY_GET_PRIVATE(o) \ -(G_TYPE_INSTANCE_GET_PRIVATE ((o), STATUS_PROVIDER_TELEPATHY_TYPE, StatusProviderTelepathyPrivate)) - -/* Prototypes */ -/* GObject stuff */ -static void status_provider_telepathy_class_init (StatusProviderTelepathyClass *klass); -static void status_provider_telepathy_init (StatusProviderTelepathy *self); -static void status_provider_telepathy_dispose (GObject *object); -static void status_provider_telepathy_finalize (GObject *object); -/* Internal Funcs */ -static void build_telepathy_proxy (StatusProviderTelepathy * self); -static void dbus_namechange (DBusGProxy * proxy, const gchar * name, const gchar * prev, const gchar * new, StatusProviderTelepathy * self); -static void set_status (StatusProvider * sp, StatusProviderStatus status); -static StatusProviderStatus get_status (StatusProvider * sp); -static void changed_status (DBusGProxy * proxy, guint status, gchar * message, StatusProvider * sp); -static void proxy_destroy (DBusGProxy * proxy, StatusProvider * sp); -static void get_status_async (DBusGProxy * proxy, DBusGProxyCall * call, gpointer userdata); - -G_DEFINE_TYPE (StatusProviderTelepathy, status_provider_telepathy, STATUS_PROVIDER_TYPE); - -STATUS_PROVIDER_EXPORT_TYPE(STATUS_PROVIDER_TELEPATHY_TYPE) - -static void -status_provider_telepathy_class_init (StatusProviderTelepathyClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (StatusProviderTelepathyPrivate)); - - object_class->dispose = status_provider_telepathy_dispose; - object_class->finalize = status_provider_telepathy_finalize; - - StatusProviderClass * spclass = STATUS_PROVIDER_CLASS(klass); - - spclass->set_status = set_status; - spclass->get_status = get_status; - - return; -} - - -static void -status_provider_telepathy_init (StatusProviderTelepathy *self) -{ - StatusProviderTelepathyPrivate * priv = STATUS_PROVIDER_TELEPATHY_GET_PRIVATE(self); - - priv->proxy = NULL; - priv->dbus_proxy = NULL; - priv->mc_status = MC_STATUS_OFFLINE; - - GError * error = NULL; - - /* Grabbing the session bus */ - DBusGConnection * bus = dbus_g_bus_get(DBUS_BUS_SESSION, &error); - if (bus == NULL) { - g_warning("Unable to connect to Session Bus: %s", error == NULL ? "No message" : error->message); - g_error_free(error); - return; - } - - /* Set up the dbus Proxy */ - priv->dbus_proxy = dbus_g_proxy_new_for_name_owner (bus, - DBUS_SERVICE_DBUS, - DBUS_PATH_DBUS, - DBUS_INTERFACE_DBUS, - &error); - if (error != NULL) { - g_warning("Unable to connect to DBus events: %s", error->message); - g_error_free(error); - return; - } - - /* Configure the name owner changing */ - dbus_g_proxy_add_signal(priv->dbus_proxy, "NameOwnerChanged", - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_INVALID); - dbus_g_proxy_connect_signal(priv->dbus_proxy, "NameOwnerChanged", - G_CALLBACK(dbus_namechange), - self, NULL); - - build_telepathy_proxy(self); - - return; -} - -/* Builds up the proxy to Mission Control and configures all of the - signals for getting info from the proxy. Also does a call to get - the inital value of the status. */ -static void -build_telepathy_proxy (StatusProviderTelepathy * self) -{ - g_debug("Building Telepathy Proxy"); - StatusProviderTelepathyPrivate * priv = STATUS_PROVIDER_TELEPATHY_GET_PRIVATE(self); - - if (priv->proxy != NULL) { - g_debug("Hmm, being asked to build a proxy we alredy have."); - return; - } - - GError * error = NULL; - - /* Grabbing the session bus */ - DBusGConnection * session_bus = dbus_g_bus_get(DBUS_BUS_SESSION, &error); - if (session_bus == NULL) { - g_warning("Unable to connect to Session Bus: %s", error == NULL ? "No message" : error->message); - g_error_free(error); - return; - } - - /* Get the proxy to Mission Control */ - priv->proxy = dbus_g_proxy_new_for_name_owner(session_bus, - "org.freedesktop.Telepathy.MissionControl", - "/org/freedesktop/Telepathy/MissionControl", - "org.freedesktop.Telepathy.MissionControl", - &error); - - if (priv->proxy != NULL) { - /* If it goes, we set the proxy to NULL */ - g_object_add_weak_pointer (G_OBJECT(priv->proxy), (gpointer *)&priv->proxy); - /* And we clean up other variables associated */ - g_signal_connect(G_OBJECT(priv->proxy), "destroy", - G_CALLBACK(proxy_destroy), self); - - /* Set up the signal handler for watching when status changes. */ - dbus_g_object_register_marshaller(_status_provider_telepathy_marshal_VOID__UINT_STRING, - G_TYPE_NONE, - G_TYPE_UINT, - G_TYPE_STRING, - G_TYPE_INVALID); - dbus_g_proxy_add_signal (priv->proxy, - "PresenceChanged", - G_TYPE_UINT, - G_TYPE_STRING, - G_TYPE_INVALID); - dbus_g_proxy_connect_signal(priv->proxy, - "PresenceChanged", - G_CALLBACK(changed_status), - (void *)self, - NULL); - - /* Do a get here, to init the status */ - dbus_g_proxy_begin_call(priv->proxy, - "GetStatus", - get_status_async, - self, - NULL, - G_TYPE_INVALID); - } else { - g_warning("Unable to connect to Mission Control"); - if (error != NULL) { - g_error_free(error); - } - } - - return; -} - -/* Watch to see if the Mission Control comes up on Dbus */ -static void -dbus_namechange (DBusGProxy * proxy, const gchar * name, const gchar * prev, const gchar * new, StatusProviderTelepathy * self) -{ - g_return_if_fail(name != NULL); - g_return_if_fail(new != NULL); - - if (g_strcmp0(name, "org.freedesktop.Telepathy.MissionControl") == 0) { - build_telepathy_proxy(self); - } - return; -} - -static void -status_provider_telepathy_dispose (GObject *object) -{ - StatusProviderTelepathyPrivate * priv = STATUS_PROVIDER_TELEPATHY_GET_PRIVATE(object); - - if (priv->proxy != NULL) { - g_object_unref(priv->proxy); - priv->proxy = NULL; - } - - G_OBJECT_CLASS (status_provider_telepathy_parent_class)->dispose (object); - return; -} - -static void -status_provider_telepathy_finalize (GObject *object) -{ - - G_OBJECT_CLASS (status_provider_telepathy_parent_class)->finalize (object); - return; -} - -/** - status_provider_telepathy_new: - - Creates a new #StatusProviderTelepathy object. No parameters or anything - like that. Just a convience function. - - Return value: A new instance of #StatusProviderTelepathy -*/ -StatusProvider * -status_provider_telepathy_new (void) -{ - return STATUS_PROVIDER(g_object_new(STATUS_PROVIDER_TELEPATHY_TYPE, NULL)); -} - -static void -set_status (StatusProvider * sp, StatusProviderStatus status) -{ - StatusProviderTelepathyPrivate * priv = STATUS_PROVIDER_TELEPATHY_GET_PRIVATE(sp); - if (priv->proxy == NULL) { - priv->mc_status = MC_STATUS_OFFLINE; - return; - } - - priv->mc_status = sp_to_mc_map[status]; - - guint mcstatus = MC_STATUS_UNSET; - gboolean ret = FALSE; - GError * error = NULL; - - ret = dbus_g_proxy_call(priv->proxy, - "GetPresence", &error, - G_TYPE_INVALID, - G_TYPE_UINT, &mcstatus, - G_TYPE_INVALID); - - /* If we can't get the get call to work, let's not set */ - if (!ret) { - if (error != NULL) { - g_error_free(error); - } - return; - } - - /* If the get call doesn't return a status, that means that there - are no clients connected. We don't want to connect them by telling - MC that we're going online -- we'd like to be more passive than that. */ - if (mcstatus == MC_STATUS_UNSET) { - return; - } - - ret = dbus_g_proxy_call(priv->proxy, - "SetPresence", &error, - G_TYPE_UINT, priv->mc_status, - G_TYPE_STRING, "", - G_TYPE_INVALID, - G_TYPE_INVALID); - - if (!ret) { - if (error != NULL) { - g_warning("Unable to set Mission Control Presence: %s", error->message); - g_error_free(error); - } else { - g_warning("Unable to set Mission Control Presence"); - } - return; - } - - return; -} - -static StatusProviderStatus -get_status (StatusProvider * sp) -{ - g_return_val_if_fail(IS_STATUS_PROVIDER_TELEPATHY(sp), STATUS_PROVIDER_STATUS_DISCONNECTED); - StatusProviderTelepathyPrivate * priv = STATUS_PROVIDER_TELEPATHY_GET_PRIVATE(sp); - - if (priv->proxy == NULL) { - return STATUS_PROVIDER_STATUS_DISCONNECTED; - } - - return mc_to_sp_map[priv->mc_status]; -} - -static void -changed_status (DBusGProxy * proxy, guint status, gchar * message, StatusProvider * sp) -{ - StatusProviderTelepathyPrivate * priv = STATUS_PROVIDER_TELEPATHY_GET_PRIVATE(sp); - priv->mc_status = status; - g_signal_emit(G_OBJECT(sp), STATUS_PROVIDER_SIGNAL_STATUS_CHANGED_ID, 0, mc_to_sp_map[priv->mc_status], TRUE); -} - -static void -proxy_destroy (DBusGProxy * proxy, StatusProvider * sp) -{ - g_debug("Signal: Mission Control proxy destroyed"); - g_signal_emit(G_OBJECT(sp), STATUS_PROVIDER_SIGNAL_STATUS_CHANGED_ID, 0, STATUS_PROVIDER_STATUS_OFFLINE, TRUE); - return; -} - -static void -get_status_async (DBusGProxy * proxy, DBusGProxyCall * call, gpointer userdata) -{ - GError * error = NULL; - guint status = 0; - if (!dbus_g_proxy_end_call(proxy, call, &error, G_TYPE_UINT, &status, G_TYPE_INVALID)) { - g_warning("Unable to get type from Mission Control: %s", error->message); - g_error_free(error); - return; - } - - StatusProviderTelepathyPrivate * priv = STATUS_PROVIDER_TELEPATHY_GET_PRIVATE(userdata); - - gboolean changed = FALSE; - if (status != priv->mc_status) { - changed = TRUE; - } - - priv->mc_status = status; - - if (changed) { - g_signal_emit(G_OBJECT(userdata), STATUS_PROVIDER_SIGNAL_STATUS_CHANGED_ID, 0, mc_to_sp_map[priv->mc_status], TRUE); - } - - return; -} diff --git a/src/status-provider-telepathy.h b/src/status-provider-telepathy.h deleted file mode 100644 index a67ee40..0000000 --- a/src/status-provider-telepathy.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -A small wrapper utility to load indicators and put them as menu items -into the gnome-panel using it's applet interface. - -Copyright 2009 Canonical Ltd. - -Authors: - Ted Gould - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program. If not, see . -*/ - -#ifndef __STATUS_PROVIDER_TELEPATHY_H__ -#define __STATUS_PROVIDER_TELEPATHY_H__ - -#include -#include - -#include "status-provider.h" - -G_BEGIN_DECLS - -#define STATUS_PROVIDER_TELEPATHY_TYPE (status_provider_telepathy_get_type ()) -#define STATUS_PROVIDER_TELEPATHY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), STATUS_PROVIDER_TELEPATHY_TYPE, StatusProviderTelepathy)) -#define STATUS_PROVIDER_TELEPATHY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), STATUS_PROVIDER_TELEPATHY_TYPE, StatusProviderTelepathyClass)) -#define IS_STATUS_PROVIDER_TELEPATHY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), STATUS_PROVIDER_TELEPATHY_TYPE)) -#define IS_STATUS_PROVIDER_TELEPATHY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), STATUS_PROVIDER_TELEPATHY_TYPE)) -#define STATUS_PROVIDER_TELEPATHY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), STATUS_PROVIDER_TELEPATHY_TYPE, StatusProviderTelepathyClass)) - - -typedef struct _StatusProviderTelepathyClass StatusProviderTelepathyClass; -struct _StatusProviderTelepathyClass { - StatusProviderClass parent_class; -}; - -typedef struct _StatusProviderTelepathy StatusProviderTelepathy; -struct _StatusProviderTelepathy { - StatusProvider parent; -}; - -GType status_provider_telepathy_get_type (void); -StatusProvider * status_provider_telepathy_new (void); - -G_END_DECLS - -#endif diff --git a/src/status-provider-telepathy.list b/src/status-provider-telepathy.list deleted file mode 100644 index 5ab45bf..0000000 --- a/src/status-provider-telepathy.list +++ /dev/null @@ -1 +0,0 @@ -VOID:UINT,STRING diff --git a/src/status-provider.c b/src/status-provider.c deleted file mode 100644 index 1139e54..0000000 --- a/src/status-provider.c +++ /dev/null @@ -1,101 +0,0 @@ -/* -A small wrapper utility to load indicators and put them as menu items -into the gnome-panel using it's applet interface. - -Copyright 2009 Canonical Ltd. - -Authors: - Ted Gould - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program. If not, see . -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "status-provider.h" - -/* Signals */ -enum { - STATUS_CHANGED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -/* GObject Boilerplate */ -static void status_provider_class_init (StatusProviderClass *klass); -static void status_provider_init (StatusProvider *self); - -G_DEFINE_TYPE (StatusProvider, status_provider, G_TYPE_OBJECT); - -static void -status_provider_class_init (StatusProviderClass *klass) -{ - // GObjectClass *object_class = G_OBJECT_CLASS (klass); - - klass->status_changed = NULL; - - klass->set_status = NULL; - klass->get_status = NULL; - - /** - StatusProvider::status-changed: - @arg0: The #StatusProvider object. - @arg1: The new status #StatusProviderStatus - - Should be emitted by subclasses everytime that the status - changes externally to us. - */ - signals[STATUS_CHANGED] = g_signal_new(STATUS_PROVIDER_SIGNAL_STATUS_CHANGED, - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET(StatusProviderClass, status_changed), - NULL, NULL, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, 1, G_TYPE_UINT); - - return; -} - -static void -status_provider_init (StatusProvider *self) -{ - - return; -} - -void -status_provider_set_status (StatusProvider * sp, StatusProviderStatus status) -{ - g_return_if_fail(IS_STATUS_PROVIDER(sp)); - - StatusProviderClass * class = STATUS_PROVIDER_GET_CLASS(sp); - g_return_if_fail(class != NULL); - g_return_if_fail(class->set_status != NULL); - - return class->set_status(sp, status); -} - -StatusProviderStatus -status_provider_get_status (StatusProvider * sp) -{ - g_return_val_if_fail(IS_STATUS_PROVIDER(sp), STATUS_PROVIDER_STATUS_OFFLINE); - - StatusProviderClass * class = STATUS_PROVIDER_GET_CLASS(sp); - g_return_val_if_fail(class->get_status != NULL, STATUS_PROVIDER_STATUS_OFFLINE); - - return class->get_status(sp); -} - diff --git a/src/status-provider.h b/src/status-provider.h deleted file mode 100644 index 45433fc..0000000 --- a/src/status-provider.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -A small wrapper utility to load indicators and put them as menu items -into the gnome-panel using it's applet interface. - -Copyright 2009 Canonical Ltd. - -Authors: - Ted Gould - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program. If not, see . -*/ - -#ifndef __STATUS_PROVIDER_H__ -#define __STATUS_PROVIDER_H__ - -#include -#include - -G_BEGIN_DECLS - -#define STATUS_PROVIDER_EXPORT_TYPE(x) GType status_provider_export_type (void) { return (x); } -#define STATUS_PROVIDER_EXPORT_S "status_provider_export_type" - -#define STATUS_PROVIDER_TYPE (status_provider_get_type ()) -#define STATUS_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), STATUS_PROVIDER_TYPE, StatusProvider)) -#define STATUS_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), STATUS_PROVIDER_TYPE, StatusProviderClass)) -#define IS_STATUS_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), STATUS_PROVIDER_TYPE)) -#define IS_STATUS_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), STATUS_PROVIDER_TYPE)) -#define STATUS_PROVIDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), STATUS_PROVIDER_TYPE, StatusProviderClass)) - -typedef enum -{ - STATUS_PROVIDER_STATUS_ONLINE, - STATUS_PROVIDER_STATUS_AWAY, - STATUS_PROVIDER_STATUS_DND, - STATUS_PROVIDER_STATUS_INVISIBLE, - STATUS_PROVIDER_STATUS_OFFLINE, - STATUS_PROVIDER_STATUS_DISCONNECTED, - /* Leave as last */ - STATUS_PROVIDER_STATUS_LAST -} -StatusProviderStatus; - -#define STATUS_PROVIDER_SIGNAL_STATUS_CHANGED "status-changed" -#define STATUS_PROVIDER_SIGNAL_STATUS_CHANGED_ID (g_signal_lookup(STATUS_PROVIDER_SIGNAL_STATUS_CHANGED, STATUS_PROVIDER_TYPE)) - -typedef struct _StatusProvider StatusProvider; -struct _StatusProvider { - GObject parent; -}; - -typedef struct _StatusProviderClass StatusProviderClass; -struct _StatusProviderClass { - GObjectClass parent_class; - - /* Signals */ - void (*status_changed) (StatusProviderStatus newstatus); - - /* Virtual Functions */ - void (*set_status) (StatusProvider * sp, StatusProviderStatus newstatus); - StatusProviderStatus (*get_status) (StatusProvider * sp); -}; - -GType status_provider_get_type (void); - -void status_provider_set_status (StatusProvider * sp, StatusProviderStatus status); -StatusProviderStatus status_provider_get_status (StatusProvider * sp); - -G_END_DECLS - -#endif diff --git a/test/Makefile.am b/test/Makefile.am index ca4965e..d0ea499 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -43,8 +43,6 @@ libindicator_messages_service_la_SOURCES = \ $(top_srcdir)/src/gen-messages-service.xml.h \ $(top_srcdir)/src/app-section.c \ $(top_srcdir)/src/app-section.h \ - $(top_srcdir)/src/status-items.c \ - $(top_srcdir)/src/status-items.h \ $(top_srcdir)/src/gactionmuxer.c \ $(top_srcdir)/src/gactionmuxer.h $(top_srcdir)/src/dbus-data.h @@ -60,12 +58,10 @@ libindicator_messages_service_la_CFLAGS = \ -Wl,-z,defs \ -Wl,--as-needed \ -Werror \ - -DG_LOG_DOMAIN=\"Indicator-Messages\" \ - -DSTATUS_PROVIDER_DIR=\"$(STATUS_PROVIDER_DIR)\" + -DG_LOG_DOMAIN=\"Indicator-Messages\" libindicator_messages_service_la_LIBADD = \ - $(APPLET_LIBS) \ - $(top_builddir)/src/.libs/libindicator-messages-status-provider.la + $(APPLET_LIBS) libindicator_messages_service_la_LDFLAGS = \ $(COVERAGE_LDFLAGS) -- cgit v1.2.3 From 193886f467b636a91d546656017de3fd0fa62677 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 27 Jun 2012 21:42:23 +0200 Subject: Use gdbus-codegen also for the server side messages service --- .bzrignore | 4 +- src/Makefile.am | 30 ++- src/indicator-messages.c | 1 - src/messages-service-dbus.c | 511 -------------------------------------------- src/messages-service-dbus.h | 65 ------ src/messages-service.c | 36 +++- test/Makefile.am | 5 +- 7 files changed, 43 insertions(+), 609 deletions(-) delete mode 100644 src/messages-service-dbus.c delete mode 100644 src/messages-service-dbus.h (limited to 'test') diff --git a/.bzrignore b/.bzrignore index 431e715..b3415fa 100644 --- a/.bzrignore +++ b/.bzrignore @@ -32,8 +32,8 @@ stamp-* /po/POTFILES /data/indicator-messages.service /src/indicator-messages-service -/src/gen-messages-service.xml.c -/src/gen-messages-service.xml.h +/src/indicator-messages-service.c +/src/indicator-messages-service.h /src/status-provider-mc5-marshal.c /src/status-provider-mc5-marshal.h /src/status-provider-pidgin-marshal.c diff --git a/src/Makefile.am b/src/Makefile.am index e9f88e6..1bc5b59 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -15,8 +15,8 @@ messaginglibdir = $(INDICATORDIR) messaginglib_LTLIBRARIES = libmessaging.la libmessaging_la_SOURCES = \ indicator-messages.c \ - gen-messages-service.xml.h \ - gen-messages-service.xml.c \ + indicator-messages-service.c \ + indicator-messages-service.h dbus-data.h libmessaging_la_CFLAGS = \ $(APPLET_CFLAGS) \ @@ -38,10 +38,8 @@ libmessaging_la_LDFLAGS = \ indicator_messages_service_SOURCES = \ messages-service.c \ - messages-service-dbus.c \ - messages-service-dbus.h \ - gen-messages-service.xml.h \ - gen-messages-service.xml.c \ + indicator-messages-service.c \ + indicator-messages-service.h \ app-section.c \ app-section.h \ dbus-data.h \ @@ -68,19 +66,17 @@ indicator_messages_service_LDADD = \ indicator_messages_service_LDFLAGS = \ $(COVERAGE_LDFLAGS) -gen-%.xml.h: %.xml - @echo "Building $@ from $<" - @echo "extern const char * _$(subst -,_,$(subst .,_,$(basename $(notdir $<))));" > $@ - -gen-%.xml.c: %.xml - @echo "Building $@ from $<" - echo "const char * _$(subst -,_,$(subst .,_,$(basename $(notdir $<)))) = " > $@ - @sed -e "s:\":\\\\\":g" -e s:^:\": -e s:\$$:\\\\n\": $< >> $@ - @echo ";" >> $@ +indicator-messages-service.c: $(top_srcdir)/src/messages-service.xml + $(AM_V_GEN) gdbus-codegen \ + --interface-prefix com.canonical.indicator.messages. \ + --generate-c-code indicator-messages-service \ + --c-namespace IndicatorMessages \ + $^ +indicator-messages-service.h: indicator-messages-service.c BUILT_SOURCES += \ - gen-messages-service.xml.h \ - gen-messages-service.xml.c + indicator-messages-service.c \ + indicator-messages-service.h EXTRA_DIST += \ messages-service.xml diff --git a/src/indicator-messages.c b/src/indicator-messages.c index 70efd52..6278461 100644 --- a/src/indicator-messages.c +++ b/src/indicator-messages.c @@ -35,7 +35,6 @@ with this program. If not, see . #include #include "dbus-data.h" -#include "gen-messages-service.xml.h" #define INDICATOR_MESSAGES_TYPE (indicator_messages_get_type ()) #define INDICATOR_MESSAGES(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_MESSAGES_TYPE, IndicatorMessages)) diff --git a/src/messages-service-dbus.c b/src/messages-service-dbus.c deleted file mode 100644 index 211b1f5..0000000 --- a/src/messages-service-dbus.c +++ /dev/null @@ -1,511 +0,0 @@ -/* -An indicator to show information that is in messaging applications -that the user is using. - -Copyright 2009 Canonical Ltd. - -Authors: - Ted Gould - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program. If not, see . -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include "messages-service-dbus.h" -#include "dbus-data.h" -#include "gen-messages-service.xml.h" - -enum { - ATTENTION_CHANGED, - ICON_CHANGED, - REGISTER_APPLICATION, - UNREGISTER_APPLICATION, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -typedef struct _MessageServiceDbusPrivate MessageServiceDbusPrivate; - -struct _MessageServiceDbusPrivate -{ - GDBusConnection * connection; - GCancellable * accounts_cancel; - GDBusProxy * accounts_user; - gboolean dot; - gboolean hidden; -}; - -#define MESSAGE_SERVICE_DBUS_GET_PRIVATE(o) \ -(G_TYPE_INSTANCE_GET_PRIVATE ((o), MESSAGE_SERVICE_DBUS_TYPE, MessageServiceDbusPrivate)) - -static void message_service_dbus_class_init (MessageServiceDbusClass *klass); -static void message_service_dbus_init (MessageServiceDbus *self); -static void message_service_dbus_dispose (GObject *object); -static void message_service_dbus_finalize (GObject *object); -static void bus_method_call (GDBusConnection * connection, - const gchar * sender, - const gchar * path, - const gchar * interface, - const gchar * method, - GVariant * params, - GDBusMethodInvocation * invocation, - gpointer user_data); - -static GDBusNodeInfo * bus_node_info = NULL; -static GDBusInterfaceInfo * bus_interface_info = NULL; -static const GDBusInterfaceVTable bus_interface_table = { - method_call: bus_method_call, - get_property: NULL, /* No properties */ - set_property: NULL /* No properties */ -}; - -G_DEFINE_TYPE (MessageServiceDbus, message_service_dbus, G_TYPE_OBJECT); - - -static void -message_service_dbus_class_init (MessageServiceDbusClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (MessageServiceDbusPrivate)); - - object_class->dispose = message_service_dbus_dispose; - object_class->finalize = message_service_dbus_finalize; - - signals[ATTENTION_CHANGED] = g_signal_new(MESSAGE_SERVICE_DBUS_SIGNAL_ATTENTION_CHANGED, - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (MessageServiceDbusClass, attention_changed), - NULL, NULL, - g_cclosure_marshal_VOID__BOOLEAN, - G_TYPE_NONE, 1, G_TYPE_BOOLEAN); - - signals[ICON_CHANGED] = g_signal_new(MESSAGE_SERVICE_DBUS_SIGNAL_ICON_CHANGED, - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (MessageServiceDbusClass, icon_changed), - NULL, NULL, - g_cclosure_marshal_VOID__BOOLEAN, - G_TYPE_NONE, 1, G_TYPE_BOOLEAN); - - signals[REGISTER_APPLICATION] = g_signal_new(MESSAGE_SERVICE_DBUS_SIGNAL_REGISTER_APPLICATION, - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, - g_cclosure_marshal_generic, - G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); - - signals[UNREGISTER_APPLICATION] = g_signal_new(MESSAGE_SERVICE_DBUS_SIGNAL_UNREGISTER_APPLICATION, - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); - - if (bus_node_info == NULL) { - GError * error = NULL; - - bus_node_info = g_dbus_node_info_new_for_xml(_messages_service, &error); - if (error != NULL) { - g_error("Unable to parse Messaging Menu Interface description: %s", error->message); - g_error_free(error); - } - } - - if (bus_interface_info == NULL) { - bus_interface_info = g_dbus_node_info_lookup_interface(bus_node_info, INDICATOR_MESSAGES_DBUS_SERVICE_INTERFACE); - - if (bus_interface_info == NULL) { - g_error("Unable to find interface '" INDICATOR_MESSAGES_DBUS_SERVICE_INTERFACE "'"); - } - } - - return; -} - -static void -connection_cb (GObject * object, GAsyncResult * res, gpointer user_data) -{ - GError * error = NULL; - GDBusConnection * connection = g_bus_get_finish(res, &error); - - if (error != NULL) { - g_error("Unable to connect to the session bus: %s", error->message); - g_error_free(error); - return; - } - - MessageServiceDbusPrivate * priv = MESSAGE_SERVICE_DBUS_GET_PRIVATE(user_data); - priv->connection = connection; - - g_dbus_connection_register_object(connection, - INDICATOR_MESSAGES_DBUS_SERVICE_OBJECT, - bus_interface_info, - &bus_interface_table, - user_data, - NULL, /* destroy */ - &error); - - if (error != NULL) { - g_error("Unable to register on session bus: %s", error->message); - g_error_free(error); - return; - } - - g_debug("Service on session bus"); - - return; -} - -static void -accounts_notify_cb (GObject *source_object, GAsyncResult *res, - gpointer user_data) -{ - GError * error = NULL; - GVariant * answer = g_dbus_proxy_call_finish(G_DBUS_PROXY(source_object), res, &error); - - if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - g_error_free(error); - return; /* Must exit before accessing freed memory */ - } - - MessageServiceDbusPrivate * priv = MESSAGE_SERVICE_DBUS_GET_PRIVATE(user_data); - - if (priv->accounts_cancel != NULL) { - g_object_unref(priv->accounts_cancel); - priv->accounts_cancel = NULL; - } - - if (error != NULL) { - g_warning("Unable to get notify accounts service of message status: %s", error->message); - g_error_free(error); - return; - } - - g_variant_unref (answer); -} - -static void -accounts_notify (MessageServiceDbus *self) -{ - MessageServiceDbusPrivate * priv = MESSAGE_SERVICE_DBUS_GET_PRIVATE(self); - - if (priv->accounts_user == NULL) - return; /* We're not able to talk to accounts service */ - - if (priv->accounts_cancel != NULL) { - /* Cancel old notify before starting new one */ - g_cancellable_cancel(priv->accounts_cancel); - g_object_unref(priv->accounts_cancel); - priv->accounts_cancel = NULL; - } - - priv->accounts_cancel = g_cancellable_new(); - g_dbus_proxy_call(priv->accounts_user, - "SetXHasMessages", - g_variant_new ("(b)", priv->dot), - G_DBUS_CALL_FLAGS_NONE, - -1, /* timeout */ - priv->accounts_cancel, - accounts_notify_cb, - self); -} - -static void -get_accounts_user_proxy_cb (GObject *source_object, GAsyncResult *res, - gpointer user_data) -{ - GError * error = NULL; - GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish(res, &error); - - if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - g_error_free(error); - return; /* Must exit before accessing freed memory */ - } - - MessageServiceDbusPrivate * priv = MESSAGE_SERVICE_DBUS_GET_PRIVATE(user_data); - - if (priv->accounts_cancel != NULL) { - g_object_unref(priv->accounts_cancel); - priv->accounts_cancel = NULL; - } - - if (error != NULL) { - g_warning("Unable to get proxy of accountsservice: %s", error->message); - g_error_free(error); - return; - } - - priv->accounts_user = proxy; - accounts_notify (MESSAGE_SERVICE_DBUS (user_data)); -} - -static void -get_accounts_user_find_user_cb (GObject *source_object, GAsyncResult *res, - gpointer user_data) -{ - GError * error = NULL; - GVariant * answer = g_dbus_proxy_call_finish(G_DBUS_PROXY(source_object), res, &error); - - /* We're done with main accounts proxy now */ - g_object_unref (source_object); - - if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - g_error_free(error); - return; /* Must exit before accessing freed memory */ - } - - MessageServiceDbusPrivate * priv = MESSAGE_SERVICE_DBUS_GET_PRIVATE(user_data); - - if (priv->accounts_cancel != NULL) { - g_object_unref(priv->accounts_cancel); - priv->accounts_cancel = NULL; - } - - if (error != NULL) { - g_warning("Unable to get object name of user from accountsservice: %s", error->message); - g_error_free(error); - return; - } - - if (!g_variant_is_of_type (answer, G_VARIANT_TYPE ("(o)"))) { - g_warning("Unexpected type from FindUserByName: %s", g_variant_get_type_string (answer)); - g_variant_unref(answer); - return; - } - - const gchar *path; - g_variant_get(answer, "(&o)", &path); - - priv->accounts_cancel = g_cancellable_new(); - g_dbus_proxy_new_for_bus(G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.freedesktop.Accounts", - path, - "org.freedesktop.Accounts.User", - priv->accounts_cancel, - get_accounts_user_proxy_cb, - user_data); - - g_variant_unref (answer); -} - -static void -get_accounts_proxy_cb (GObject *source_object, GAsyncResult *res, - gpointer user_data) -{ - GError * error = NULL; - GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish(res, &error); - - if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - g_error_free(error); - return; /* Must exit before accessing freed memory */ - } - - MessageServiceDbusPrivate * priv = MESSAGE_SERVICE_DBUS_GET_PRIVATE(user_data); - - if (priv->accounts_cancel != NULL) { - g_object_unref(priv->accounts_cancel); - priv->accounts_cancel = NULL; - } - - if (error != NULL) { - g_warning("Unable to get proxy of accountsservice: %s", error->message); - g_error_free(error); - return; - } - - priv->accounts_cancel = g_cancellable_new(); - g_dbus_proxy_call(proxy, - "FindUserByName", - g_variant_new ("(s)", g_get_user_name ()), - G_DBUS_CALL_FLAGS_NONE, - -1, /* timeout */ - priv->accounts_cancel, - get_accounts_user_find_user_cb, - user_data); -} - -static void -get_accounts_proxy (MessageServiceDbus *self) -{ - MessageServiceDbusPrivate * priv = MESSAGE_SERVICE_DBUS_GET_PRIVATE(self); - - g_return_if_fail(priv->accounts_cancel == NULL); - - priv->accounts_cancel = g_cancellable_new(); - g_dbus_proxy_new_for_bus(G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.freedesktop.Accounts", - "/org/freedesktop/Accounts", - "org.freedesktop.Accounts", - priv->accounts_cancel, - get_accounts_proxy_cb, - self); -} - -static void -message_service_dbus_init (MessageServiceDbus *self) -{ - g_bus_get(G_BUS_TYPE_SESSION, NULL, connection_cb, self); - get_accounts_proxy (self); - - MessageServiceDbusPrivate * priv = MESSAGE_SERVICE_DBUS_GET_PRIVATE(self); - - priv->dot = FALSE; - priv->hidden = FALSE; - - return; -} - -static void -message_service_dbus_dispose (GObject *object) -{ - MessageServiceDbusPrivate * priv = MESSAGE_SERVICE_DBUS_GET_PRIVATE(object); - - if (priv->connection != NULL) { - g_object_unref(priv->connection); - priv->connection = NULL; - } - - if (priv->accounts_cancel != NULL) { - g_cancellable_cancel(priv->accounts_cancel); - g_object_unref(priv->accounts_cancel); - priv->accounts_cancel = NULL; - } - - if (priv->accounts_user != NULL) { - g_object_unref(priv->accounts_user); - priv->accounts_user = NULL; - } - - G_OBJECT_CLASS (message_service_dbus_parent_class)->dispose (object); - return; -} - -static void -message_service_dbus_finalize (GObject *object) -{ - - - G_OBJECT_CLASS (message_service_dbus_parent_class)->finalize (object); - return; -} - -MessageServiceDbus * -message_service_dbus_new (void) -{ - return MESSAGE_SERVICE_DBUS(g_object_new(MESSAGE_SERVICE_DBUS_TYPE, NULL)); -} - -/* Method request off of DBus */ -static void -bus_method_call (GDBusConnection * connection, const gchar * sender, const gchar * path, const gchar * interface, const gchar * method, GVariant * params, GDBusMethodInvocation * invocation, gpointer user_data) -{ - MessageServiceDbus * ms = MESSAGE_SERVICE_DBUS(user_data); - if (ms == NULL) { return; } - - MessageServiceDbusPrivate * priv = MESSAGE_SERVICE_DBUS_GET_PRIVATE(ms); - - if (g_strcmp0("AttentionRequested", method) == 0) { - g_dbus_method_invocation_return_value(invocation, g_variant_new("(b)", priv->dot)); - return; - } else if (g_strcmp0("IconShown", method) == 0) { - g_dbus_method_invocation_return_value(invocation, g_variant_new("(b)", priv->hidden)); - return; - } else if (g_strcmp0("ClearAttention", method) == 0) { - message_service_dbus_set_attention(ms, FALSE); - g_dbus_method_invocation_return_value(invocation, NULL); - return; - } else if (g_strcmp0("RegisterApplication", method) == 0) { - const gchar *desktop_id, *object_path; - g_variant_get(params, "(&s&o)", &desktop_id, &object_path); - g_signal_emit(ms, signals[REGISTER_APPLICATION], 0, sender, desktop_id, object_path); - g_dbus_method_invocation_return_value(invocation, NULL); - } else if (g_strcmp0("UnregisterApplication", method) == 0) { - const gchar *desktop_id; - g_variant_get(params, "(&s)", &desktop_id); - g_signal_emit(ms, signals[UNREGISTER_APPLICATION], 0, desktop_id); - g_dbus_method_invocation_return_value(invocation, NULL); - } else { - g_warning("Unknown function call '%s'", method); - } - - return; -} - -void -message_service_dbus_set_attention (MessageServiceDbus * self, gboolean attention) -{ - MessageServiceDbusPrivate * priv = MESSAGE_SERVICE_DBUS_GET_PRIVATE(self); - /* Do signal */ - if (attention != priv->dot) { - priv->dot = attention; - g_signal_emit(G_OBJECT(self), signals[ATTENTION_CHANGED], 0, priv->dot, TRUE); - - if (priv->connection != NULL) { - g_dbus_connection_emit_signal(priv->connection, - NULL, - INDICATOR_MESSAGES_DBUS_SERVICE_OBJECT, - INDICATOR_MESSAGES_DBUS_SERVICE_INTERFACE, - "AttentionChanged", - g_variant_new("(b)", priv->dot), - NULL); - } - - accounts_notify (self); - } - return; -} - -void -message_service_dbus_set_icon (MessageServiceDbus * self, gboolean hidden) -{ - MessageServiceDbusPrivate * priv = MESSAGE_SERVICE_DBUS_GET_PRIVATE(self); - /* Do signal */ - if (hidden != priv->hidden) { - priv->hidden = hidden; - g_signal_emit(G_OBJECT(self), signals[ICON_CHANGED], 0, priv->hidden, TRUE); - - if (priv->connection != NULL) { - g_dbus_connection_emit_signal(priv->connection, - NULL, - INDICATOR_MESSAGES_DBUS_SERVICE_OBJECT, - INDICATOR_MESSAGES_DBUS_SERVICE_INTERFACE, - "IconChanged", - g_variant_new("(b)", priv->hidden), - NULL); - } - } - return; -} - -GDBusConnection * -message_service_dbus_get_connection (MessageServiceDbus *msd) -{ - MessageServiceDbusPrivate * priv; - - g_return_val_if_fail (IS_MESSAGE_SERVICE_DBUS (msd), NULL); - - priv = MESSAGE_SERVICE_DBUS_GET_PRIVATE(msd); - return priv->connection; -} diff --git a/src/messages-service-dbus.h b/src/messages-service-dbus.h deleted file mode 100644 index 63564b6..0000000 --- a/src/messages-service-dbus.h +++ /dev/null @@ -1,65 +0,0 @@ -/* -An indicator to show information that is in messaging applications -that the user is using. - -Copyright 2009 Canonical Ltd. - -Authors: - Ted Gould - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program. If not, see . -*/ - -#ifndef __MESSAGE_SERVICE_DBUS_H__ -#define __MESSAGE_SERVICE_DBUS_H__ - -#include -#include - -G_BEGIN_DECLS - -#define MESSAGE_SERVICE_DBUS_TYPE (message_service_dbus_get_type ()) -#define MESSAGE_SERVICE_DBUS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MESSAGE_SERVICE_DBUS_TYPE, MessageServiceDbus)) -#define MESSAGE_SERVICE_DBUS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MESSAGE_SERVICE_DBUS_TYPE, MessageServiceDbusClass)) -#define IS_MESSAGE_SERVICE_DBUS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MESSAGE_SERVICE_DBUS_TYPE)) -#define IS_MESSAGE_SERVICE_DBUS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MESSAGE_SERVICE_DBUS_TYPE)) -#define MESSAGE_SERVICE_DBUS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MESSAGE_SERVICE_DBUS_TYPE, MessageServiceDbusClass)) - -#define MESSAGE_SERVICE_DBUS_SIGNAL_ATTENTION_CHANGED "attention-changed" -#define MESSAGE_SERVICE_DBUS_SIGNAL_ICON_CHANGED "icon-changed" -#define MESSAGE_SERVICE_DBUS_SIGNAL_REGISTER_APPLICATION "register-application" -#define MESSAGE_SERVICE_DBUS_SIGNAL_UNREGISTER_APPLICATION "unregister-application" - -typedef struct _MessageServiceDbus MessageServiceDbus; -typedef struct _MessageServiceDbusClass MessageServiceDbusClass; - -struct _MessageServiceDbusClass { - GObjectClass parent_class; - - void (*attention_changed) (gboolean dot); - void (*icon_changed) (gboolean hidden); -}; - -struct _MessageServiceDbus { - GObject parent; -}; - -GType message_service_dbus_get_type (void); -MessageServiceDbus * message_service_dbus_new (void); -void message_service_dbus_set_attention (MessageServiceDbus * self, gboolean attention); -void message_service_dbus_set_icon (MessageServiceDbus * self, gboolean hidden); -GDBusConnection * message_service_dbus_get_connection (MessageServiceDbus *msd); - -G_END_DECLS - -#endif diff --git a/src/messages-service.c b/src/messages-service.c index 4bd7e0c..ec36335 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -29,13 +29,14 @@ with this program. If not, see . #include "app-section.h" #include "dbus-data.h" -#include "messages-service-dbus.h" #include "gactionmuxer.h" #include "gsettingsstrv.h" #include "gmenuutils.h" +#include "indicator-messages-service.h" static GHashTable *applications; +IndicatorMessagesService *messages_service; static GSimpleActionGroup *actions; static GActionMuxer *action_muxer; static GMenu *toplevel_menu; @@ -266,33 +267,39 @@ change_status (GSimpleAction *action, } static void -register_application (MessageServiceDbus *msd, - const gchar *sender, +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; - bus = message_service_dbus_get_connection (msd); + bus = g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (service)); + sender = g_dbus_method_invocation_get_sender (invocation); app_section_set_object_path (section, bus, sender, menu_path); - g_settings_strv_append_unique (settings, "applications", desktop_id); + + indicator_messages_service_complete_register_application (service, invocation); } static void -unregister_application (MessageServiceDbus *msd, +unregister_application (IndicatorMessagesService *service, + GDBusMethodInvocation *invocation, const gchar *desktop_id, gpointer user_data) { remove_application (desktop_id); g_settings_strv_remove (settings, "applications", desktop_id); + + indicator_messages_service_complete_unregister_application (service, invocation); } GSimpleActionGroup * @@ -371,6 +378,15 @@ got_bus (GObject *object, return; } + 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_object_unref (bus); } @@ -379,7 +395,6 @@ main (int argc, char ** argv) { GMainLoop * mainloop = NULL; IndicatorService * service = NULL; - MessageServiceDbus * dbus_interface = NULL; GMenuModel *status_items; GMenuItem *header; @@ -399,7 +414,7 @@ main (int argc, char ** argv) textdomain (GETTEXT_PACKAGE); /* Bring up the service DBus interface */ - dbus_interface = message_service_dbus_new(); + messages_service = indicator_messages_service_skeleton_new (); g_bus_get (G_BUS_TYPE_SESSION, NULL, got_bus, NULL); @@ -408,9 +423,9 @@ main (int argc, char ** argv) action_muxer = g_action_muxer_new (); g_action_muxer_insert (action_muxer, NULL, G_ACTION_GROUP (actions)); - g_signal_connect (dbus_interface, MESSAGE_SERVICE_DBUS_SIGNAL_REGISTER_APPLICATION, + g_signal_connect (messages_service, "handle-register-application", G_CALLBACK (register_application), NULL); - g_signal_connect (dbus_interface, MESSAGE_SERVICE_DBUS_SIGNAL_UNREGISTER_APPLICATION, + g_signal_connect (messages_service, "handle-unregister-application", G_CALLBACK (unregister_application), NULL); menu = g_menu_new (); @@ -434,6 +449,7 @@ main (int argc, char ** argv) g_main_loop_run(mainloop); /* Clean up */ + g_object_unref (messages_service); g_object_unref (status_items); g_object_unref (settings); g_hash_table_unref (applications); diff --git a/test/Makefile.am b/test/Makefile.am index d0ea499..ebf2da2 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -38,9 +38,8 @@ noinst_LTLIBRARIES = \ libindicator-messages-service.la libindicator_messages_service_la_SOURCES = \ - $(top_srcdir)/src/messages-service-dbus.c \ - $(top_srcdir)/src/gen-messages-service.xml.c \ - $(top_srcdir)/src/gen-messages-service.xml.h \ + $(top_srcdir)/src/indicator-messages-service.c \ + $(top_srcdir)/src/indicator-messages-service.h \ $(top_srcdir)/src/app-section.c \ $(top_srcdir)/src/app-section.h \ $(top_srcdir)/src/gactionmuxer.c \ -- cgit v1.2.3 From 5df53a2c98d806f3b266d0032986d4dab3beb7a3 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Tue, 21 Aug 2012 12:03:21 +0200 Subject: Fix out-of-tree builds (for make distcheck) --- po/POTFILES.in | 1 - test/Makefile.am | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'test') diff --git a/po/POTFILES.in b/po/POTFILES.in index 21cd0b1..edb0388 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,4 +1,3 @@ [encoding: UTF-8] -src/messages-service-dbus.c src/indicator-messages.c src/messages-service.c diff --git a/test/Makefile.am b/test/Makefile.am index ebf2da2..4671446 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -38,8 +38,8 @@ noinst_LTLIBRARIES = \ libindicator-messages-service.la libindicator_messages_service_la_SOURCES = \ - $(top_srcdir)/src/indicator-messages-service.c \ - $(top_srcdir)/src/indicator-messages-service.h \ + $(top_builddir)/src/indicator-messages-service.c \ + $(top_builddir)/src/indicator-messages-service.h \ $(top_srcdir)/src/app-section.c \ $(top_srcdir)/src/app-section.h \ $(top_srcdir)/src/gactionmuxer.c \ @@ -52,6 +52,7 @@ libindicator_messages_service_ladir = \ libindicator_messages_service_la_CFLAGS = \ $(APPLET_CFLAGS) \ $(COVERAGE_CFLAGS) \ + -I$(top_builddir)/src \ -Wall \ -Wl,-Bsymbolic-functions \ -Wl,-z,defs \ -- cgit v1.2.3