← Back to team overview

ayatana-commits team mailing list archive

[Merge] lp:~larsu/indicator-messages/notify-stopped-running into lp:indicator-messages/0.5

 

Lars Uebernickel has proposed merging lp:~larsu/indicator-messages/notify-stopped-running into lp:indicator-messages/0.5.

Requested reviews:
  PS Jenkins bot (ps-jenkins): continuous-integration
  Mathieu Trudel-Lapierre (mathieu-tl)
Related bugs:
  Bug #1154099 in Messaging Menu: "Applications are not unmarked when MessagingMenuApp is unrefed"
  https://bugs.launchpad.net/indicator-messages/+bug/1154099

For more details, see:
https://code.launchpad.net/~larsu/indicator-messages/notify-stopped-running/+merge/168201
-- 
The attached diff has been truncated due to its size.
https://code.launchpad.net/~larsu/indicator-messages/notify-stopped-running/+merge/168201
Your team ayatana-commits is subscribed to branch lp:indicator-messages/0.5.
=== added directory '.bzr-builddeb'
=== added file '.bzr-builddeb/default.conf'
--- .bzr-builddeb/default.conf	1970-01-01 00:00:00 +0000
+++ .bzr-builddeb/default.conf	2013-06-07 21:39:23 +0000
@@ -0,0 +1,2 @@
+[BUILDDEB]
+split = True

=== modified file '.bzrignore'
--- .bzrignore	2011-07-13 15:41:33 +0000
+++ .bzrignore	2013-06-07 21:39:23 +0000
@@ -1,49 +1,65 @@
-compile
-m4
-po
-src/libmessaging.la
-src/libmessaging_la-indicator-messages.lo
-config.guess.cdbs-orig
-config.sub.cdbs-orig
-debian/compat
-debian/files
-debian/indicator-messages
-debian/indicator-messages.debhelper.log
-debian/indicator-messages.postinst.debhelper
-debian/indicator-messages.postrm.debhelper
-debian/indicator-messages.substvars
-debian/stamp-autotools-files
-debian/stamp-makefile-build
-libmessaging_la-im-menu-item.lo
-src/libmessaging_la-app-menu-item.lo
-data/indicator-messages.service
-indicator-messages-service
-indicator-messages-service-activate
-src/messages-service-client.h
-src/messages-service-server.h
-po/indicator-messages.pot
-src/libmessaging_la-app-gtk-menu-item.lo
-src/gen-messages-service.xml.c
-src/gen-messages-service.xml.h
-src/libemesene.la
-src/libemesene_la-status-provider-emesene.lo
-src/libmc5.la
-src/libmc5_la-status-provider-mc5-marshal.lo
-src/libmc5_la-status-provider-mc5.lo
-src/libmessaging_la-gen-messages-service.xml.lo
-src/libpidgin.la
-src/libpidgin_la-status-provider-pidgin-marshal.lo
-src/libpidgin_la-status-provider-pidgin.lo
-src/libtelepathy.la
-src/libtelepathy_la-status-provider-telepathy-marshal.lo
-src/libtelepathy_la-status-provider-telepathy.lo
-src/status-provider-mc5-marshal.c
-src/status-provider-mc5-marshal.h
-src/status-provider-pidgin-marshal.c
-src/status-provider-pidgin-marshal.h
-src/status-provider-telepathy-marshal.c
-src/status-provider-telepathy-marshal.h
-src/libindicator-messages-status-provider.la
-src/libindicator_messages_status_provider_la-status-provider.lo
-indicator-messages-status-provider-0.5.pc
-indicator-messages-status-provider-0.5.pc.in
+Makefile
+Makefile.in
+Makefile.in.in
+*.o
+*.lo
+*.la
+*.pot
+.deps
+.libs
+*.valid
+stamp-*
+*.gcno
+*.gcda
+*.stamp
+*.gir
+*.typelib
+
+/COPYING
+/INSTALL
+/compile
+/libtool
+/config.*
+/configure
+/aclocal.m4
+/ltmain.sh
+/install-sh
+/missing
+/autom4te.cache
+/depcomp
+/mkinstalldirs
+/coverage.info
+/coveragereport
+/gtk-doc.make
+/indicator-messages-*.tar.gz
+
+/m4/*
+/po/POTFILES
+/data/indicator-messages.service
+/src/indicator-messages-service
+/src/indicator-messages-service.c
+/src/indicator-messages-service.h
+
+/libmessaging-menu/messaging-menu.pc
+/libmessaging-menu/indicator-messages-service.c
+/libmessaging-menu/indicator-messages-service.h
+
+/doc/reference/html
+/doc/reference/xml
+/doc/reference/messaging-menu-decl-list.txt
+/doc/reference/messaging-menu-decl.txt
+/doc/reference/messaging-menu-docs.sgml
+/doc/reference/messaging-menu-docs.xml
+/doc/reference/messaging-menu-overrides.txt
+/doc/reference/messaging-menu-sections.txt
+/doc/reference/messaging-menu-undeclared.txt
+/doc/reference/messaging-menu-undocumented.txt
+/doc/reference/messaging-menu-unused.txt
+/doc/reference/messaging-menu.args
+/doc/reference/messaging-menu.hierarchy
+/doc/reference/messaging-menu.interfaces
+/doc/reference/messaging-menu.prerequisites
+/doc/reference/messaging-menu.signals
+/doc/reference/messaging-menu.types
+
+/test/test-gactionmuxer

=== modified file 'Makefile.am'
--- Makefile.am	2010-10-08 22:13:11 +0000
+++ Makefile.am	2013-06-07 21:39:23 +0000
@@ -1,10 +1,27 @@
 
 SUBDIRS = \
 	src \
+	libmessaging-menu \
 	data \
 	po
 
-DISTCHECK_CONFIGURE_FLAGS = --enable-localinstall --enable-deprecations
+if ENABLE_GTK_DOC
+SUBDIRS += doc
+endif
+
+if BUILD_TESTS
+SUBDIRS += \
+	test
+
+# build src first
+test: src
+
+endif
+
+
+
+
+DISTCHECK_CONFIGURE_FLAGS = --enable-localinstall --enable-deprecations --enable-introspection --enable-gtk-doc
 
 dist-hook:
 	@if test -d "$(top_srcdir)/.bzr"; \
@@ -31,3 +48,6 @@
         else \
 			echo Failed to generate AUTHORS: not a branch >&2; \
 	fi
+
+
+include $(top_srcdir)/Makefile.am.coverage

=== added file 'Makefile.am.coverage'
--- Makefile.am.coverage	1970-01-01 00:00:00 +0000
+++ Makefile.am.coverage	2013-06-07 21:39:23 +0000
@@ -0,0 +1,48 @@
+
+# Coverage targets
+
+.PHONY: clean-gcno clean-gcda \
+	coverage-html generate-coverage-html clean-coverage-html \
+	coverage-gcovr generate-coverage-gcovr clean-coverage-gcovr
+
+clean-local: clean-gcno clean-coverage-html clean-coverage-gcovr
+
+if HAVE_GCOV
+
+clean-gcno:
+	@echo Removing old coverage instrumentation
+	-find -name '*.gcno' -print | xargs -r rm
+
+clean-gcda:
+	@echo Removing old coverage results
+	-find -name '*.gcda' -print | xargs -r rm
+  
+coverage-html: clean-gcda
+	-$(MAKE) $(AM_MAKEFLAGS) -k check
+	$(MAKE) $(AM_MAKEFLAGS) generate-coverage-html
+  
+generate-coverage-html:
+	@echo Collecting coverage data
+	$(LCOV) --directory $(top_builddir) --capture --output-file coverage.info --no-checksum --compat-libtool
+	LANG=C $(GENHTML) --prefix $(top_builddir) --output-directory coveragereport --title "Code Coverage" --legend --show-details coverage.info
+  
+clean-coverage-html: clean-gcda
+	-$(LCOV) --directory $(top_builddir) -z
+	-rm -rf coverage.info coveragereport
+
+if HAVE_GCOVR
+
+coverage-gcovr: clean-gcda
+	-$(MAKE) $(AM_MAKEFLAGS) -k check
+	$(MAKE) $(AM_MAKEFLAGS) generate-coverage-gcovr
+	
+generate-coverage-gcovr:
+	@echo Generating coverage GCOVR report
+	$(GCOVR) -x -r $(top_builddir) -o $(top_builddir)/coverage.xml
+	
+clean-coverage-gcovr: clean-gcda
+	-rm -rf $(top_builddir)/coverage.xml
+
+endif # HAVE_GCOVR
+
+endif # HAVE_GCOV

=== modified file 'NEWS'
--- NEWS	2008-12-05 03:13:41 +0000
+++ NEWS	2013-06-07 21:39:23 +0000
@@ -0,0 +1,42 @@
+
+12.10.5
+
+* fix crash caused by GError not being cleared (lp #1064314)
+* fix crash when registering an app that was previously unregistered (lp #1065169)
+* remove the icon if NULL is passed to source_set_icon (lp #1070421)
+* call gtk-update-icon-cache (lp #1060618)
+
+12.10.4
+
+* specify fallback icons for the ones with status emblem (lp #1056595)
+* make icon size consistent with the other indicators (lp #1055966)
+* libmessaging-menu: fix crash when receiving a invalid desktop id (lp #1058386)
+
+
+12.10.3
+
+* hide indicator when no application shows in the menu (lp #661059)
+* remove apps as soon as they are uninstalled (lp #864545)
+* make generated .gir compatible with vala (lp #104496)
+* draw counts as lozenges (lp #1046331)
+* show separators (lp #1048245)
+* show chat presence in the panel (lp #859905)
+* improve documentation
+
+
+12.10.2
+
+* libmessaging-menu:
+  - expand source documentation and add gtk-doc to the build system
+  - added new API: messaging_menu_app_set_source_{label,icon}
+  - fix bug: only one MessagingMenuApp was exported to the messaging menu
+
+
+12.10.1
+
+* presence icons are shown again
+* the icon is changed when a source draws attention
+* the time in source menu items is always kep current
+* fixed all g-ir-scanner warnings
+* libmessaging-menu now removes sources when they are activated
+* fixed several bugs

=== modified file 'autogen.sh'
--- autogen.sh	2009-04-05 11:03:12 +0000
+++ autogen.sh	2013-06-07 21:39:23 +0000
@@ -1,11 +1,5 @@
-#!/bin/sh
-
-PKG_NAME="indicator-messages"
-
-which gnome-autogen.sh || {
-	echo "You need gnome-common from GNOME SVN"
-	exit 1
-}
-
-USE_GNOME2_MACROS=1 \
-. gnome-autogen.sh
+#!/bin/sh -e
+
+gtkdocize
+autoreconf -i -f
+intltoolize

=== modified file 'configure.ac'
--- configure.ac	2011-09-28 15:33:24 +0000
+++ configure.ac	2013-06-07 21:39:23 +0000
@@ -1,10 +1,10 @@
 
-AC_INIT(src/indicator-messages.c)
+AC_INIT(indicator-messages, 12.10.5)
 
-AC_PREREQ(2.53)
+AC_PREREQ(2.62)
 
 AM_CONFIG_HEADER(config.h)
-AM_INIT_AUTOMAKE(indicator-messages, 0.5.0)
+AM_INIT_AUTOMAKE([check-news])
 
 AM_MAINTAINER_MODE
 
@@ -31,64 +31,73 @@
   [CFLAGS="$CFLAGS -DG_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED -DGDK_PIXBUF_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED -DGSEAL_ENABLE -DGTK_DISABLE_SINGLE_INCLUDES"]
 )
 
+# the Google Test targets are cpp
+AC_PROG_CXX
+
 ###########################
 # Dependencies 
 ###########################
 
-GTK_REQUIRED_VERSION=2.12
-GTK3_REQUIRED_VERSION=3.0
-GIO_UNIX_REQUIRED_VERSION=2.18
-PANEL_REQUIRED_VERSION=2.0.0
-INDICATE_REQUIRED_VERSION=0.4.90
+GTK_REQUIRED_VERSION=3.5.18
+GIO_UNIX_REQUIRED_VERSION=2.33.10
 INDICATOR_REQUIRED_VERSION=0.3.19
-DBUSMENUGTK_REQUIRED_VERSION=0.3.94
-
-AC_ARG_WITH([gtk],
-  [AS_HELP_STRING([--with-gtk],
-    [Which version of gtk to use for the indicator @<:@default=3@:>@])],
-  [],
-  [with_gtk=3])
-
-AS_IF([test "x$with_gtk" = x3],
-        [PKG_CHECK_MODULES(APPLET, gtk+-3.0 >= $GTK3_REQUIRED_VERSION
-                                   gio-unix-2.0 >= $GIO_UNIX_REQUIRED_VERSION
-                                   indicator3-0.4 >= $INDICATOR_REQUIRED_VERSION
-                                   indicate-0.6 >= $INDICATE_REQUIRED_VERSION
-                                   dbusmenu-gtk3-0.4 >= $DBUSMENUGTK_REQUIRED_VERSION)
-        ],
-      [test "x$with_gtk" = x2],
-        [PKG_CHECK_MODULES(APPLET, gtk+-2.0 >= $GTK_REQUIRED_VERSION
-                                   gio-unix-2.0 >= $GIO_UNIX_REQUIRED_VERSION
-                                   indicator-0.4 >= $INDICATOR_REQUIRED_VERSION
-                                   indicate-0.6 >= $INDICATE_REQUIRED_VERSION
-                                   dbusmenu-gtk-0.4 >= $DBUSMENUGTK_REQUIRED_VERSION)
-        ],
-      [AC_MSG_FAILURE([Value for --with-indicator-gtk was neither 2 nor 3])]
-)
+GLIB_REQUIRED_VERSION=2.35.4
+INTROSPECTION_REQUIRED_VERSION=1.32.0
+
+PKG_CHECK_MODULES(APPLET, gtk+-3.0 >= $GTK_REQUIRED_VERSION
+                          gio-unix-2.0 >= $GIO_UNIX_REQUIRED_VERSION
+                          indicator3-0.4 >= $INDICATOR_REQUIRED_VERSION
+                          glib-2.0 >= $GLIB_REQUIRED_VERSION
+                          gmodule-2.0 >= $GLIB_REQUIRED_VERSION)
+
+PKG_CHECK_MODULES(GIO, gio-unix-2.0 >= $GIO_UNIX_REQUIRED_VERSION)
+
 AC_SUBST(APPLET_CFLAGS)
 AC_SUBST(APPLET_LIBS)
 
-###########################
-# 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)
+GLIB_GSETTINGS
+
+GTK_DOC_CHECK([1.18], [--flavour no-tmpl])
+
+GOBJECT_INTROSPECTION_CHECK([$INTROSPECTION_REQUIRED_VERSION])
+
+###########################
+# gcov coverage reporting
+###########################
+
+m4_include([m4/gcov.m4])
+AC_TDD_GCOV
+AM_CONDITIONAL([HAVE_GCOV], [test "x$ac_cv_check_gcov" = xyes])
+AM_CONDITIONAL([HAVE_LCOV], [test "x$ac_cv_check_lcov" = xyes])
+AM_CONDITIONAL([HAVE_GCOVR], [test "x$ac_cv_check_gcovr" = xyes])
+AC_SUBST(COVERAGE_CFLAGS)
+AC_SUBST(COVERAGE_CXXFLAGS)
+AC_SUBST(COVERAGE_LDFLAGS)
+
+###########################
+# Tests
+###########################
+
+AC_ARG_ENABLE([tests],
+    [AS_HELP_STRING([--disable-tests], [Disable test scripts and tools (default=auto)])],
+    [enable_tests=${enableval}],
+    [enable_tests=auto])
+if test "x$enable_tests" != "xno"; then
+    m4_include([m4/gtest.m4])
+    CHECK_GTEST
+    AM_PATH_PYTHON(3.0,, [:])
+    AC_PYTHON_MODULE(dbusmock)
+    if test "x$have_gtest" = "xyes" -a "x$HAVE_PYMOD_DBUSMOCK" = "xyes"; then
+        enable_tests="yes"
+    else
+        if test "x$enable_tests" = "xyes"; then
+            AC_MSG_ERROR([tests were requested but gtest or dbusmock are not installed.])
+        else
+            enable_tests="no"
+        fi
+    fi
+fi
+AM_CONDITIONAL([BUILD_TESTS],[test "x$enable_tests" = "xyes"])
 
 ###########################
 # Check to see if we're local
@@ -103,16 +112,10 @@
 
 if test "x$with_localinstall" = "xyes"; then
 	INDICATORDIR="${libdir}/indicators/2/"
-	INDICATORICONSDIR="${datadir}/libindicate/icons/"
-elif test "x$with_gtk" = x2; then
-	INDICATORDIR=`$PKG_CONFIG --variable=indicatordir indicator-0.4`
-	INDICATORICONSDIR=`$PKG_CONFIG --variable=iconsdir indicator-0.4`
 else
 	INDICATORDIR=`$PKG_CONFIG --variable=indicatordir indicator3-0.4`
-	INDICATORICONSDIR=`$PKG_CONFIG --variable=iconsdir indicator3-0.4`
 fi
 AC_SUBST(INDICATORDIR)
-AC_SUBST(INDICATORICONSDIR)
 
 ###########################
 # DBus Service Info
@@ -159,7 +162,6 @@
 AC_OUTPUT([
 Makefile
 src/Makefile
-src/indicator-messages-status-provider-0.5.pc.in
 data/Makefile
 data/icons/Makefile
 data/icons/16x16/Makefile
@@ -179,6 +181,12 @@
 data/icons/scalable/status/Makefile
 data/icons/scalable/categories/Makefile
 po/Makefile.in
+test/Makefile
+libmessaging-menu/Makefile
+libmessaging-menu/messaging-menu.pc
+doc/Makefile
+doc/reference/Makefile
+doc/reference/messaging-menu-docs.xml
 ])
 
 ###########################
@@ -191,4 +199,8 @@
 
 	Prefix:        $prefix
 	Indicator Dir: $INDICATORDIR
+	tests:         $enable_tests
+	gcov:          $use_gcov
+	introspecion:  $enable_introspection
+	documentation: $enable_gtk_doc
 ])

=== modified file 'data/Makefile.am'
--- data/Makefile.am	2009-09-09 18:58:33 +0000
+++ data/Makefile.am	2013-06-07 21:39:23 +0000
@@ -6,6 +6,11 @@
 %.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

=== added file 'data/com.canonical.indicator.messages.gschema.xml'
--- data/com.canonical.indicator.messages.gschema.xml	1970-01-01 00:00:00 +0000
+++ data/com.canonical.indicator.messages.gschema.xml	2013-06-07 21:39:23 +0000
@@ -0,0 +1,12 @@
+<schemalist>
+  <schema id="com.canonical.indicator.messages" path="/com/canonical/indicator/messages/" gettext-domain="indicator-messages">
+    <key name="applications" type="as">
+      <summary>List of applications that are shown in the messaging menu</summary>
+      <description>
+        Applications corresponding to the desktop file ids in this list are shown in the messaging menu.
+      </description>
+      <default>[]</default>
+    </key>
+  </schema>
+</schemalist>
+

=== modified file 'data/icons/16x16/categories/Makefile.am'
--- data/icons/16x16/categories/Makefile.am	2010-03-04 20:23:07 +0000
+++ data/icons/16x16/categories/Makefile.am	2013-06-07 21:39:23 +0000
@@ -1,5 +1,5 @@
 
-iconsdir = $(INDICATORICONSDIR)/hicolor/16x16/categories
+iconsdir = $(datadir)/icons/hicolor/16x16/categories
 
 icons_DATA =  \
 	applications-email-panel.png \

=== modified file 'data/icons/16x16/status/Makefile.am'
--- data/icons/16x16/status/Makefile.am	2010-02-18 04:59:43 +0000
+++ data/icons/16x16/status/Makefile.am	2013-06-07 21:39:23 +0000
@@ -1,5 +1,5 @@
 
-iconsdir = $(INDICATORICONSDIR)/hicolor/16x16/status
+iconsdir = $(datadir)/icons/hicolor/16x16/status
 
 icons_DATA =  \
 	application-running.png \

=== modified file 'data/icons/22x22/categories/Makefile.am'
--- data/icons/22x22/categories/Makefile.am	2010-03-04 20:23:07 +0000
+++ data/icons/22x22/categories/Makefile.am	2013-06-07 21:39:23 +0000
@@ -1,5 +1,5 @@
 
-iconsdir = $(INDICATORICONSDIR)/hicolor/22x22/categories
+iconsdir = $(datadir)/icons/hicolor/22x22/categories
 
 icons_DATA =  \
 	applications-email-panel.png

=== modified file 'data/icons/22x22/status/Makefile.am'
--- data/icons/22x22/status/Makefile.am	2009-09-25 01:28:38 +0000
+++ data/icons/22x22/status/Makefile.am	2013-06-07 21:39:23 +0000
@@ -1,5 +1,5 @@
 
-iconsdir = $(INDICATORICONSDIR)/hicolor/22x22/status
+iconsdir = $(datadir)/icons/hicolor/22x22/status
 
 icons_DATA =  \
 	indicator-messages.png \

=== modified file 'data/icons/24x24/status/Makefile.am'
--- data/icons/24x24/status/Makefile.am	2010-02-18 04:59:43 +0000
+++ data/icons/24x24/status/Makefile.am	2013-06-07 21:39:23 +0000
@@ -1,5 +1,5 @@
 
-iconsdir = $(INDICATORICONSDIR)/hicolor/24x24/status
+iconsdir = $(datadir)/icons/hicolor/24x24/status
 
 icons_DATA =  \
 	application-running.png \

=== modified file 'data/icons/32x32/categories/Makefile.am'
--- data/icons/32x32/categories/Makefile.am	2010-03-04 20:23:07 +0000
+++ data/icons/32x32/categories/Makefile.am	2013-06-07 21:39:23 +0000
@@ -1,5 +1,5 @@
 
-iconsdir = $(INDICATORICONSDIR)/hicolor/32x32/categories
+iconsdir = $(datadir)/icons/hicolor/32x32/categories
 
 icons_DATA =  \
 	applications-email-panel.png \

=== modified file 'data/icons/32x32/status/Makefile.am'
--- data/icons/32x32/status/Makefile.am	2010-02-18 04:59:43 +0000
+++ data/icons/32x32/status/Makefile.am	2013-06-07 21:39:23 +0000
@@ -1,5 +1,5 @@
 
-iconsdir = $(INDICATORICONSDIR)/hicolor/32x32/status
+iconsdir = $(datadir)/icons/hicolor/32x32/status
 
 icons_DATA =  \
 	application-running.png \

=== modified file 'data/icons/48x48/status/Makefile.am'
--- data/icons/48x48/status/Makefile.am	2010-02-18 04:59:43 +0000
+++ data/icons/48x48/status/Makefile.am	2013-06-07 21:39:23 +0000
@@ -1,5 +1,5 @@
 
-iconsdir = $(INDICATORICONSDIR)/hicolor/48x48/status
+iconsdir = $(datadir)/icons/hicolor/48x48/status
 
 icons_DATA =  \
 	application-running.png \

=== modified file 'data/icons/Makefile.am'
--- data/icons/Makefile.am	2009-02-04 16:01:51 +0000
+++ data/icons/Makefile.am	2013-06-07 21:39:23 +0000
@@ -1,6 +1,6 @@
 SUBDIRS = scalable 16x16 22x22 24x24 32x32 48x48
 
-gtk_update_icon_cache = gtk-update-icon-cache -f -t $(pkgdatadir)/icons/hicolor
+gtk_update_icon_cache = gtk-update-icon-cache -f -t $(datadir)/icons/hicolor
 
 install-data-hook: update-icon-cache
 uninstall-hook: update-icon-cache

=== modified file 'data/icons/scalable/categories/Makefile.am'
--- data/icons/scalable/categories/Makefile.am	2010-03-04 20:23:07 +0000
+++ data/icons/scalable/categories/Makefile.am	2013-06-07 21:39:23 +0000
@@ -1,5 +1,5 @@
 
-iconsdir = $(INDICATORICONSDIR)/hicolor/scalable/categories
+iconsdir = $(datadir)/icons/hicolor/scalable/categories
 
 icons_DATA =  \
 	applications-email-panel.svg \

=== modified file 'data/icons/scalable/status/Makefile.am'
--- data/icons/scalable/status/Makefile.am	2010-02-18 04:59:43 +0000
+++ data/icons/scalable/status/Makefile.am	2013-06-07 21:39:23 +0000
@@ -1,5 +1,5 @@
 
-iconsdir = $(INDICATORICONSDIR)/hicolor/scalable/status
+iconsdir = $(datadir)/icons/hicolor/scalable/status
 
 icons_DATA =  \
 	application-running.svg \

=== added directory 'debian'
=== added file 'debian/changelog'
--- debian/changelog	1970-01-01 00:00:00 +0000
+++ debian/changelog	2013-06-07 21:39:23 +0000
@@ -0,0 +1,856 @@
+indicator-messages (12.10.6daily13.01.25-0ubuntu1) raring; urgency=low
+
+  [ Charles Kerr ]
+  * indicators call deprecated glib function g_type_init() (LP:
+    #1103087)
+
+  [ Automatic PS uploader ]
+  * Automatic snapshot from revision 335
+
+ -- Automatic PS uploader <ps-jenkins@xxxxxxxxxxxxxxxxxxx>  Fri, 25 Jan 2013 02:01:11 +0000
+
+indicator-messages (12.10.6daily12.11.22-0ubuntu1) raring; urgency=low
+
+  [ Lars Uebernickel ]
+  * Crash in g_variant_valist_get_leaf when highlighted (LP: #1081754)
+
+  [ Automatic PS uploader ]
+  * Automatic snapshot from revision 333
+
+ -- Automatic PS uploader <ps-jenkins@xxxxxxxxxxxxxxxxxxx>  Thu, 22 Nov 2012 10:02:35 +0000
+
+indicator-messages (12.10.6daily12.11.21.1-0ubuntu1) raring; urgency=low
+
+  [ Mathieu Trudel-Lapierre ]
+  * debian/rules:
+    - Use autogen.sh for dh_autoreconf.
+    - Drop the override for dh_makeshlibs.
+    - Add DPKG_GENSYMBOLS_CHECK_LEVEL=4.
+  * debian/control:
+    - Fix styling: add trailing commas at the end of lists. 
+    - Update Vcs-Bzr, Vcs-Browser fields and add a notice for developers.
+    - Add libgtest-dev to Build-Depends.
+  * Automatic snapshot from revision 329 (bootstrap):
+    - Clear the detail (count or time) of a source when another type of detail
+      is set. (LP: #1071640)
+
+  [ Automatic PS uploader ]
+  * Automatic snapshot from revision 331
+
+ -- Automatic PS uploader <ps-jenkins@xxxxxxxxxxxxxxxxxxx>  Wed, 21 Nov 2012 10:41:37 +0000
+
+indicator-messages (12.10.5-0ubuntu2) raring; urgency=low
+
+  * Upload to raring
+
+ -- Sebastien Bacher <seb128@xxxxxxxxxx>  Wed, 07 Nov 2012 15:16:08 +0100
+
+indicator-messages (12.10.5-0ubuntu1) quantal-proposed; urgency=low
+
+  * New upstream release:
+    - fix crash caused by GError not being cleared (lp #1064314)
+    - fix crash when registering an app that was previously unregistered 
+      (lp #1065169)
+    - remove the icon if NULL is passed to source_set_icon (lp #1070421)
+
+ -- Sebastien Bacher <seb128@xxxxxxxxxx>  Wed, 24 Oct 2012 17:30:45 +0200
+
+indicator-messages (12.10.4-0ubuntu1) quantal; urgency=low
+
+  * New upstream release:
+    - don't segfault if .desktop file is not installed (lp: #1058386)
+    - Use fallback icon names (without status emblems).
+      (lp: #1056595)
+
+ -- Sebastien Bacher <seb128@xxxxxxxxxx>  Tue, 02 Oct 2012 23:20:19 +0200
+
+indicator-messages (12.10.2-0ubuntu1) quantal; urgency=low
+
+  * New upstream release, includes apis to allow changing the label and
+    the icon of sources and add documentation
+  * debian/libmessaging-menu0.symbols:
+    - new version update
+  * debian/libmessaging-menu-dev.install:
+    - install the documentation
+  * debian/rules:
+    - build the documentation
+    - updated shlibs version
+    - use --with gir so gir:Depends work as it should 
+      (lp: #1044125)
+
+ -- Sebastien Bacher <seb128@xxxxxxxxxx>  Sat, 01 Sep 2012 12:36:35 +0200
+
+indicator-messages (12.10.1-0ubuntu1) quantal-proposed; urgency=low
+
+  * New upstream version
+  * debian/control:
+    - breaks on version of ported clients using libindicate
+    - set some conflicts on the old deprecated status provider binaries
+    - updated Build-Depends
+  * debian/control, debian/*.install:
+    - drop indicator-status-provider-*, those are deprecated
+    - new binaries for the libmessaging-menu library
+  * debian/libmessaging-menu0.symbols:
+    - symbol file for the new library
+  * Updated packaging to dh9, current standards
+  * Drop gtk2 build from the packaging since support for it was 
+    dropped in trunk, thanks Lars Uebernickel
+
+ -- Sebastien Bacher <seb128@xxxxxxxxxx>  Mon, 27 Aug 2012 18:56:59 +0200
+
+indicator-messages (0.6.0-0ubuntu1) precise; urgency=low
+
+  * New upstream release.
+    * Handle blank icons properly (LP: #956147)
+    * Fix telepathy offline/disconnected state bug 
+
+ -- Charles Kerr <charles.kerr@xxxxxxxxxxxxx>  Wed, 11 Apr 2012 11:09:46 -0500
+
+indicator-messages (0.5.95-0ubuntu1) precise; urgency=low
+
+  [ Charles Kerr ]
+  * New upstream release.
+    * Fix 0.5.94 blacklist regression.
+
+  [ Ken VanDine ]
+  * src/indicator-messages.c
+    * revert fix for the broken images in indicator-messages-service, it 
+      caused the service to build against gtk and we can't parallel install 
+      the service anyway
+
+ -- Ken VanDine <ken.vandine@xxxxxxxxxxxxx>  Thu, 05 Apr 2012 16:47:19 -0400
+
+indicator-messages (0.5.94-0ubuntu1) precise; urgency=low
+
+  [ Ted Gould ]
+  * New upstream release.
+    * Fix for missing icons in the messaging menu (LP: #960553)
+    * Fix i18n for description (LP: #957525)
+    * Implementing initial testing
+    * Fixing blacklists (LP: #939258)
+  * debian/control: Adding dep on libgtest-dev
+
+  [ Ken VanDine ]
+  * debian/control: Don't build depend on libgtest-dev, it isn't in main
+  * debian/rules: disable tests, they require libgtest-dev
+
+ -- Ken VanDine <ken.vandine@xxxxxxxxxxxxx>  Wed, 21 Mar 2012 17:00:10 -0400
+
+indicator-messages (0.5.93-0ubuntu2) precise; urgency=low
+
+  * src/im-menu-item.c
+    - cherry picked fix for missing icons in the messaging menu (LP: #960553)
+
+ -- Ken VanDine <ken.vandine@xxxxxxxxxxxxx>  Tue, 20 Mar 2012 16:41:13 -0400
+
+indicator-messages (0.5.93-0ubuntu1) precise; urgency=low
+  
+  * debian/control:
+    - drop build-depends on gnome-doc-utils and scrollkeeper, not required
+
+  [ Ted Gould ]
+  * New upstream release.
+    * Fixing alignment of menu items (LP: #939953)
+    * Vertically centering alignment of double high items (LP: #770486)
+    * Fixing setting of status on telepathy (LP: #943757)
+
+ -- Sebastien Bacher <seb128@xxxxxxxxxx>  Thu, 08 Mar 2012 22:11:24 +0100
+
+indicator-messages (0.5.92-0ubuntu1) precise; urgency=low
+
+  [ Ted Gould ]
+  * New upstream release.
+    * Fix goto handling (by removing) (LP: #937441, LP: #937438)
+    * Tell accountsservice when user has messages for the benefit of
+      LightDM.
+  * Dropping debian/patches: Merged upstream
+
+  [ Ken VanDine ]
+  * debian/source/format
+    - dropped "3.0 (quilt), it doesn't play well with bzr maintained packages 
+
+ -- Ken VanDine <ken.vandine@xxxxxxxxxxxxx>  Thu, 23 Feb 2012 02:48:09 -0500
+
+indicator-messages (0.5.91-0ubuntu3) precise; urgency=low
+
+  * debian/source/format:
+    - Make "3.0 (quilt)"
+  * debian/patches/tell-accounts-service.patch:
+    - Tell accountsservice when user has messages for the benefit of
+      LightDM.
+
+ -- Michael Terry <mterry@xxxxxxxxxx>  Wed, 15 Feb 2012 15:32:16 -0500
+
+indicator-messages (0.5.91-0ubuntu2) precise; urgency=low
+
+  * debian/control: build-depends on dh-autoreconf as well
+
+ -- Sebastien Bacher <seb128@xxxxxxxxxx>  Tue, 14 Feb 2012 23:50:15 +0100
+
+indicator-messages (0.5.91-0ubuntu1) precise; urgency=low
+
+  * New upstream release.
+    * Better lozenges that look nice
+  * debian/rules: Adding autoreconf and running make check
+  * debian/compat: 5
+  * debian/source/format: Dropping
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Tue, 14 Feb 2012 15:29:52 -0600
+
+indicator-messages (0.5.90-0ubuntu1) precise; urgency=low
+
+  [ Ted Gould ]
+  * New upstream release.
+    * Adding code coverage targets
+    * Match libindicate 0.6.90
+    * Updating for Dbusmenu 0.5.90
+    * Plug leak in launcher_menu_item_new
+    * Fix memory leak: Free path string.
+    * Compare server and path for multi-server clients
+    * Using the new GTK3 box API to avoid deprecations
+    * Adding a name hint
+  * debian/control: Requiring libindicate 0.6.90 and dbusmenu 0.5.90
+
+  [ Ken VanDine ]
+  * debian/rules
+    - drop no-error=deprecated-declarations from CFLAGS
+
+ -- Ken VanDine <ken.vandine@xxxxxxxxxxxxx>  Fri, 10 Feb 2012 14:29:59 -0500
+
+indicator-messages (0.5.0-1ubuntu1) precise; urgency=low
+
+  * rebuild for libindicator7
+  * debian/rules
+    - build with no-error=deprecated-declarations
+  * debian/control
+    - set ubuntu-desktop VCS and maintainer
+
+ -- Ken VanDine <ken.vandine@xxxxxxxxxxxxx>  Wed, 25 Jan 2012 09:56:59 -0500
+
+indicator-messages (0.5.0-1) experimental; urgency=low
+
+  * Merge new upstream from Ubuntu.
+
+ -- Evgeni Golov <evgeni@xxxxxxxxxx>  Wed, 19 Oct 2011 13:36:00 +0200
+
+indicator-messages (0.5.0-0ubuntu1) oneiric; urgency=low
+
+  * New upstream release.
+    * Fix memory leak (LP: #690668)
+  * Drop debian/patches/lp_690668.patch: Merged upstream
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Wed, 28 Sep 2011 10:39:26 -0500
+
+indicator-messages (0.4.95-0ubuntu1) oneiric; urgency=low
+
+  * New upstream release.
+    * Fix naming of "Clear" item
+    * Fix alignment of items to there is a consistent gutter
+  * debian/patches/lp_690668.patch: Updating
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Thu, 25 Aug 2011 09:09:20 -0500
+
+indicator-messages (0.4.94-0ubuntu1) oneiric; urgency=low
+
+  * New upstream release.
+    ∘ Fix drawing of triangles and capsules in GTK3
+    ∘ Fix Emesene statuses (LP: #817504)
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Thu, 18 Aug 2011 10:57:40 -0500
+
+indicator-messages (0.4.93-0ubuntu2) oneiric; urgency=low
+
+  * debian/rules
+    - run intltool-update to update the translations template
+
+ -- Ken VanDine <ken.vandine@xxxxxxxxxxxxx>  Fri, 12 Aug 2011 10:05:01 -0400
+
+indicator-messages (0.4.93-0ubuntu1) oneiric; urgency=low
+
+  [ Ted Gould ]
+  * New upstream release.
+    * Add an item to clear the alert
+    * Choose mail applications based on the default application
+    * Clear based on middle click
+
+  [ Ken VanDine ]
+  * debian/control
+    - Bumped build depends for libindicate to >= 0.5.90 
+  * debian/rules
+    - Fixed configure arg for gtk version
+
+ -- Ken VanDine <ken.vandine@xxxxxxxxxxxxx>  Thu, 11 Aug 2011 14:18:05 -0400
+
+indicator-messages (0.4.92-0ubuntu4) oneiric; urgency=low
+
+  * debian/control
+    - Dropped recommends for gwibber now that it is seeded
+  * cherry picked r220 from trunk 
+    - Make sure to insert in the right locations
+  * cherry picked r221 from trunk
+    - Making mail applications based on the default mail client not a 
+      hardcoded desktop file.
+
+ -- Ken VanDine <ken.vandine@xxxxxxxxxxxxx>  Fri, 05 Aug 2011 14:33:39 -0400
+
+indicator-messages (0.4.92-0ubuntu3) oneiric; urgency=low
+
+  * debian/control
+    - Added recommends for gwibber, it got missed when we dropped indicator-me
+      should get removed after we get it seeded properly
+
+ -- Ken VanDine <ken.vandine@xxxxxxxxxxxxx>  Sun, 31 Jul 2011 16:36:09 -0400
+
+indicator-messages (0.4.92-0ubuntu2) oneiric; urgency=low
+
+  * debian/control:
+    - use conflicts against indicator-me
+
+ -- Michael Vogt <michael.vogt@xxxxxxxxxx>  Fri, 29 Jul 2011 15:49:40 +0200
+
+indicator-messages (0.4.92-0ubuntu1) oneiric; urgency=low
+
+  * New upstream release.
+  * debian/control
+    - Added Replaces indicator-me
+    - Added build depends for libtelepathy-glib-dev
+    - Added new binary packages, libindicator-messages-status-provider-dev,
+      libindicator-messages-status-provider1, and each provider
+    - Make indicator-messages recommend indicator-status-provider-mc5
+  * debian/libindicator-messages-status-provider1.symbols
+    - Added symbols file
+
+ -- Ken VanDine <ken.vandine@xxxxxxxxxxxxx>  Thu, 14 Jul 2011 16:28:23 -0400
+
+indicator-messages (0.4.91-0ubuntu1) oneiric; urgency=low
+
+  [ Ted Gould ]
+  * New upstream release.
+    * Update for libindicator 0.4
+
+  [ Ken VanDine ]
+  * debian/control
+    - Bumped build depends for libindicator to >= 0.3.90
+
+ -- Ken VanDine <ken.vandine@xxxxxxxxxxxxx>  Fri, 08 Jul 2011 11:23:58 -0400
+
+indicator-messages (0.4.90-0ubuntu2) oneiric; urgency=low
+
+  * Rebuild for libdbusmenu-gtk3-4
+  * debian/control
+    - Removed duplicate build depends
+    - Dropped build depends on indicator-messages-gtk2
+
+ -- Ken VanDine <ken.vandine@xxxxxxxxxxxxx>  Tue, 28 Jun 2011 09:01:12 -0400
+
+indicator-messages (0.4.90-0ubuntu1) oneiric; urgency=low
+
+  [ Ted Gould ]
+  * New upstream release.
+    * GTK 3
+
+  [ Ken VanDine ]
+  * debian/control
+    - Bumped standards version to 3.9.2
+    - Add new binary for indicator-messages-gtk2 
+    - Make indicator-messages recommend indicator-messages-gtk2 (until unity 
+      can load gtk3 indicators)
+    - indicator-messages-gtk2 replaces indicator-messages << 0.4.90
+    - Added build depends for libdbusmenu-gtk3-dev and libindicator3-dev
+  * debian/rules
+    - build for both gtk2 and gtk3
+
+ -- Ken VanDine <ken.vandine@xxxxxxxxxxxxx>  Wed, 22 Jun 2011 12:34:43 -0400
+
+indicator-messages (0.4.0-1) unstable; urgency=low
+
+  * Merge new upstream from Ubuntu.
+  * Standards-Version: 3.9.2
+
+ -- Evgeni Golov <evgeni@xxxxxxxxxx>  Sun, 05 Jun 2011 13:16:03 +0200
+
+indicator-messages (0.4.0-0ubuntu1) natty; urgency=low
+
+  * New upstream release.
+    ∘ Set the type before other variables to get default handling more
+      reliable (LP: #723873)
+    ∘ Add support for overriding the default icon with a specific one
+      for the messaging menu (LP: #741068)
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Thu, 07 Apr 2011 12:35:36 -0500
+
+indicator-messages (0.3.92-1) unstable; urgency=low
+
+  * Merge new upstream from Ubuntu.
+  * Fix 0.3.11-0ubuntu3 changelog entry (missed a space), so that
+    bzr builddeb won't go crazy (see Debian Bug #620242)
+  * Fix debian/copyright, was refering to libdbusmenu by mistake.
+
+ -- Evgeni Golov <evgeni@xxxxxxxxxx>  Sun, 03 Apr 2011 13:37:33 +0200
+
+indicator-messages (0.3.92-0ubuntu3) natty; urgency=low
+
+  * debian/patches/lp_690668.patch
+    - Memory leak fixes (LP: #690668)
+  * debian/control
+    - Bump standards version to 3.9.1
+  * debian/source/format
+    - Use source format 3.0 (quilt)
+
+ -- Ken VanDine <ken.vandine@xxxxxxxxxxxxx>  Thu, 24 Feb 2011 12:13:33 -0500
+
+indicator-messages (0.3.92-0ubuntu2) natty; urgency=low
+
+  * src/launcher-menu-item.c
+    - Make sure menu entries are displayed for launchers that aren't running (LP: #723873)
+
+ -- Ken VanDine <ken.vandine@xxxxxxxxxxxxx>  Wed, 23 Feb 2011 16:06:37 -0500
+
+indicator-messages (0.3.92-0ubuntu1) natty; urgency=low
+
+  * New upstream release.
+    * Adding in accessible description support
+  * debian/control: libindicator version 0.3.19
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Thu, 17 Feb 2011 12:18:32 -0600
+
+indicator-messages (0.3.91-0ubuntu1) natty; urgency=low
+
+  * New upstream release.
+    * Fixing the service file
+    * Adding a log domain
+    * Fixing type handler for dbusmenu 0.3.94
+  * debian/control: dbusmenu to 0.3.94
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Thu, 27 Jan 2011 17:01:34 -0600
+
+indicator-messages (0.3.90-0ubuntu1) natty; urgency=low
+
+  [ Ted Gould ]
+  * New upstream release.
+    * GDBus Port
+    * New libindicate and dbusmenu
+
+  [ Ken VanDine ]
+  * debian/control
+    - Build depends on libindicate-dev to 0.4.91
+    - Build depends on dbusmenu to 0.3.91
+    - Set Vcs to ~ubuntu-desktop
+  * data/indicator-messages.service.in
+    - Fixed dbus interface name
+
+ -- Ken VanDine <ken.vandine@xxxxxxxxxxxxx>  Fri, 14 Jan 2011 14:50:30 -0600
+
+indicator-messages (0.3.11-0ubuntu4) natty; urgency=low
+
+  * debian/control
+    - Bump build depends for libdbusmenu-* to >= 0.3.90
+
+ -- Ken VanDine <ken.vandine@xxxxxxxxxxxxx>  Thu, 09 Dec 2010 11:39:40 -0500
+
+indicator-messages (0.3.11-0ubuntu3) UNRELEASED; urgency=low
+
+  * debian/control: package description spelling (LP: #658096)
+
+ -- Greg Auger <gregory.auger@xxxxxxxxxxxxxx>  Tue, 09 Nov 2010 18:49:38 +0000
+
+indicator-messages (0.3.11-0ubuntu2) maverick; urgency=low
+
+  * Rebuild for libindicator ABI change (LP: #637692)
+  * debian/control: depends on latest libindicator-dev 
+
+ -- Didier Roche <didrocks@xxxxxxxxxx>  Wed, 22 Sep 2010 18:39:27 +0200
+
+indicator-messages (0.3.11-0ubuntu1) maverick; urgency=low
+
+  * New upstream release.
+    * Fixing triangles by passing data to callback (LP: #623453)
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Thu, 09 Sep 2010 13:24:13 -0500
+
+indicator-messages (0.3.10-0ubuntu1) maverick; urgency=low
+
+  * New upstream release.
+    * Shifting icons into the gutter and adjusting the arrow
+      padding.
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Thu, 26 Aug 2010 15:08:31 -0500
+
+indicator-messages (0.3.9-0ubuntu1) maverick; urgency=low
+
+  * New upstream release.
+    * Remove parens from counts
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Thu, 12 Aug 2010 13:10:10 -0500
+
+indicator-messages (0.3.8-0ubuntu1) maverick; urgency=low
+
+  * New upstream release.
+    - running apps triangle indicator overlay
+    - message counters are now rendered with a nice rounded background
+
+ -- Ken VanDine <ken.vandine@xxxxxxxxxxxxx>  Thu, 29 Jul 2010 13:33:14 -0400
+
+indicator-messages (0.3.7-1) unstable; urgency=low
+
+  * Merge from Ubuntu.
+    Closes: #586132
+  * debian/control:
+    - Homepage is at LP/indicator-messages, not -applet.
+    - Update package description.
+    - Update Vcs-* fields.
+    - Standards-Version: 3.8.4.
+  * debian/copyright:
+    - Convert to DEP5 format.
+    - Add missing copyright holders of debian/.
+
+ -- Evgeni Golov <evgeni@xxxxxxxxxx>  Thu, 17 Jun 2010 13:02:37 +0200
+
+indicator-messages (0.3.7-0ubuntu1~ppa1) lucid; urgency=low
+
+  * New upstream release.
+    * When loading desktop files check to see if they've
+      already been eclipsed by an app. (LP: #549096)
+    * Track better application shortcuts and ensure that they
+      get removed when the application is. (LP: #539167)
+    * Track blacklisted apps to ensure that the messaging menu
+      hides when there is no app.  (LP: #533021)
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Fri, 21 May 2010 15:02:16 -0500
+
+indicator-messages (0.3.6-0ubuntu2) lucid; urgency=low
+
+  * Upstream Merge
+    * When loading desktop files check to see if they've
+      already been eclipsed by an app. (LP: #549096)
+    * Track better application shortcuts and ensure that they
+      get removed when the application is. (LP: #539167)
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Sat, 17 Apr 2010 13:10:42 -0500
+
+indicator-messages (0.3.6-0ubuntu1) lucid; urgency=low
+
+  * New upstream release.
+    * Fixing several bugs with regards to visibility and placement
+      if items and separators in the menu.  (LP: #446914)
+    * Changing the service management over to using libindicator
+      services and service manager for robustness.
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Thu, 01 Apr 2010 10:13:38 -0500
+
+indicator-messages (0.3.5-0ubuntu2) lucid; urgency=low
+
+  * debian/control:
+    - change the indicator-applet depends to a recommends to let other 
+      desktops use other options rather than having to trigger GNOME
+
+ -- Sebastien Bacher <seb128@xxxxxxxxxx>  Tue, 30 Mar 2010 10:35:59 +0200
+
+indicator-messages (0.3.5-0ubuntu1) lucid; urgency=low
+
+  * Upstream release 0.3.5
+    * Show which applications are running with a small icon
+      next to their entry. (LP: #438526)
+    * Shift command items to line up with application names.
+      (LP: #537312)
+    * Track applications we've seen so that we can show "Set Up"
+      text if we've not seen the app before.
+    * Fix avatar spacing to match other menu items
+    * Use standard libindicator icon handling in panel
+    * Fix translation of non-running applications (LP: #540148)
+    * Handling bools for requesting attention from apps
+    * Changing microblogging to broadcast to match Me Menu (LP: #534952)
+  * debian/control: 
+    - Updating requirement to libindicator 0.3.5
+    - Increasing dbusmenu-glib dep to 0.2.8
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Thu, 25 Mar 2010 10:53:01 -0500
+
+indicator-messages (0.3.4-0ubuntu1~ppa1) lucid; urgency=low
+
+  * Upstream release 0.3.4
+    * Fix avatar spacing to match other menu items
+    * Use standard libindicator icon handling in panel
+    * Fix translation of non-running applications (LP: #540148)
+    * Handling bools for requesting attention from apps
+    * Changing microblogging to broadcast to match Me Menu (LP: #534952)
+  * debian/control: Updating requirement to libindicator 0.3.5
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Thu, 18 Mar 2010 13:45:19 -0500
+
+indicator-messages (0.3.3-0ubuntu2) lucid; urgency=low
+
+  * src/default-applications.c
+    - string change for consistency (LP: #534952) 
+
+ -- Ken VanDine <ken.vandine@xxxxxxxxxxxxx>  Fri, 12 Mar 2010 11:44:46 -0500
+
+indicator-messages (0.3.3-0ubuntu1) lucid; urgency=low
+
+  * Upstream release 0.3.3
+    * Changing names of default applications to generic names
+    * Making icons of default applications match panel theme
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Thu, 04 Mar 2010 16:02:11 -0600
+
+indicator-messages (0.3.2-0ubuntu1) lucid; urgency=low
+
+  * Upstream release 0.3.2
+    * Removing extra ref
+    * Moving locally defined variable to use the one defined in
+      the function to fix a NULL pointer. (lp: #518547)
+    * Disconnect the count changed signal property
+    * Adding static desktop shortcuts to application items
+    * Adding dynamic application menuitems
+    * Switching application menu items to remove descriptions
+      and add in application icons
+  * debian/control:
+    * libindicator build dependency to 0.3.3
+    * dbusmenu build dependency to 0.2.5
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Thu, 18 Feb 2010 12:23:29 -0600
+
+indicator-messages (0.3.1-0ubuntu2) lucid; urgency=low
+
+  * Upstream Merge
+    * Removing extra ref
+    * Moving locally defined variable to use the one defined in
+      the function to fix a NULL pointer. (lp: #518547)
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Tue, 09 Feb 2010 09:30:10 -0600
+
+indicator-messages (0.3.1-0ubuntu1) lucid; urgency=low
+
+  * Upstream release 0.3.1
+    * Updates for dbusmenu 0.2.2
+    * Updates for libindicate 0.3.0
+  * debian/control:
+    * dbusmenu* depends to 0.2.2
+    * libindicate* depends to 0.3.0
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Thu, 04 Feb 2010 18:23:34 -0800
+
+indicator-messages (0.3.0-0ubuntu1) lucid; urgency=low
+
+  * Upstream release 0.3.0
+    - Disabling static builds.
+    - Porting to libindicator 0.3.0
+    - Adding translator comments from hours and minutes strings.
+      (LP: #456437)
+    - Upgrading to dbusmenu 0.2.0
+  * debian/control: Updating dbusmenu dependency to 0.2.0
+  * debian/control: Increasing libindicator-dev dependency to
+    0.3.0
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Fri, 08 Jan 2010 12:05:25 -0600
+
+indicator-messages (0.2.6+r156-0ubuntu2) lucid; urgency=low
+
+  * debian/control
+    - add a Breaks for indicator-applet (<< 0.3.0) 
+
+ -- Ken VanDine <ken.vandine@xxxxxxxxxxxxx>  Tue, 15 Dec 2009 11:57:42 -0500
+
+indicator-messages (0.2.6+r156-0ubuntu1) lucid; urgency=low
+
+  * New snapshot for libindicator 0.3.0
+  * debian/control
+    - Build-Depends on libindicator >= 0.3.0
+
+ -- Ken VanDine <ken.vandine@xxxxxxxxxxxxx>  Thu, 10 Dec 2009 14:35:46 -0500
+
+indicator-messages (0.2.6-0ubuntu1) karmic; urgency=low
+
+  * Upstream release 0.2.6 (LP: #446629)
+    * Building the menu after checking the blacklist so that the
+      separators are all correct.
+    * Small fix for a perspective memory leak.
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Fri, 09 Oct 2009 08:14:27 +0200
+
+indicator-messages (0.2.5-0ubuntu1) karmic; urgency=low
+
+  * Upstream release 0.2.5 (LP: #440217)
+    * Adding a check on addition of launchers to ensure icon is correctly
+      visible. (LP: #433274)
+    * Making it so that if applications don't set the time on an indicator
+      the time isn't shown in the menu. (LP: #438237)
+    * Putting icons in the right places. (LP: #436460)
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Thu, 01 Oct 2009 23:34:28 +0200
+
+indicator-messages (0.2.4-0ubuntu1) karmic; urgency=low
+
+  * Upstream release 0.2.4 (LP: #436093)
+    - Merging in the min menu width feature (LP: #428292)
+    - Merging in icon scaling branch from trunk. Now better icons (LP: #433143)
+    - Merging in updated trunk (LP: #434097 and LP: #435184)
+    - add i18n support
+    - Prevent null entries (LP: #435184)
+    - add a path for indicators in /usr/share (LP: #434097)
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Thu, 24 Sep 2009 13:07:46 -0500
+
+indicator-messages (0.2.2-0ubuntu2) karmic; urgency=low
+
+  * src/messages-service.c: initialise the translations
+
+ -- Sebastien Bacher <seb128@xxxxxxxxxx>  Tue, 15 Sep 2009 16:41:03 +0200
+
+indicator-messages (0.2.2-0ubuntu1) karmic; urgency=low
+
+  * New release (LP: #427357)
+    * Adds in separators between application groups
+    * Merging in v2-api stuff which will become 0.2.1
+  * debian/control: 
+    - Requiring > 0.2.0 of libindicate-*
+    - bump dbusmenu dependencies.
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Thu, 10 Sep 2009 09:11:57 -0500
+
+indicator-messages (0.2.0-0ubuntu2) karmic; urgency=low
+
+  * debian/control
+    - Bump build depends on dbusmenu to 0.1.0
+
+ -- Ken VanDine <ken.vandine@xxxxxxxxxxxxx>  Thu, 27 Aug 2009 21:14:46 +0200
+
+indicator-messages (0.2.0-0ubuntu1) karmic; urgency=low
+
+  [ Ted Gould ]
+  * Upstream version 0.2.0
+  * debian/control: Adding dependency information for libdbusmenu
+    to say >= 0.0.2 to match upstream build system.
+  * debian/watch: Changing to use indicator-messages project.
+
+  [ Martin Pitt ]
+  * debian/control: Update Vcs-Bzr: for new branch location.
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Thu, 27 Aug 2009 20:46:27 +0200
+
+indicator-messages (0.2.0~bzr124-0ubuntu1) karmic; urgency=low
+
+  * Update to fix build issue
+
+ -- Sebastien Bacher <seb128@xxxxxxxxxx>  Fri, 07 Aug 2009 17:12:40 +0100
+
+indicator-messages (0.2.0~bzr121-0ubuntu3) karmic; urgency=low
+
+  * Fix to dereference the application menu items correctly so that
+    the signal handlers are dropped as well. (lp: #410251)
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Wed, 05 Aug 2009 19:00:31 +0100
+
+indicator-messages (0.2.0~bzr121-0ubuntu2) karmic; urgency=low
+
+  * Run autogen.sh before upload
+
+ -- Jonathan Riddell <jriddell@xxxxxxxxxx>  Wed, 05 Aug 2009 00:42:39 +0100
+
+indicator-messages (0.2.0~bzr121-0ubuntu1) karmic; urgency=low
+
+  [ Ted Gould ]
+  * debian/control: Adding in a build dep on libindicate-gtk-dev
+  * Changes for the changing libindicate stuff.
+  * Merge in the dbusmenu changes from the dbusmenu branch
+  * debian/control: Adding in a build dependency on libdbusmenu-glib and
+    libdbusmenu-gtk to catch up with the merge.
+
+ -- Jonathan Riddell <jriddell@xxxxxxxxxx>  Wed, 05 Aug 2009 00:21:50 +0100
+
+indicator-messages (0.2.0~bzr120-0ubuntu1) jaunty; urgency=low
+
+  * Fix to track the timer. (LP: #365187)
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Wed, 13 May 2009 09:56:20 -0500
+
+indicator-messages (0.2.0~bzr119-0ubuntu1) jaunty; urgency=low
+
+  * Upstream update
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Wed, 22 Apr 2009 23:34:21 -0500
+
+indicator-messages (0.2.0~bzr116-0ubuntu3) jaunty; urgency=low
+
+  * debian/rules: Adding a rule to remove the .la/.a clutter
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Wed, 22 Apr 2009 16:46:59 -0500
+
+indicator-messages (0.2.0~bzr116-0ubuntu2) jaunty; urgency=low
+
+  * debian/control: libindicator-dev to ~bzr301
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Wed, 22 Apr 2009 15:58:45 -0500
+
+indicator-messages (0.2.0~bzr116-0ubuntu1) jaunty; urgency=low
+
+  * Upstream release
+    * Bug fixes
+    * Update API to new libindicator
+  * debian/control: Adding new dependency on libindicator-dev
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Wed, 22 Apr 2009 15:45:21 -0500
+
+indicator-messages (0.1.6-0ubuntu1) jaunty; urgency=low
+
+  * New upstream version
+    * Patch from Cody Russell to fix LP: #359018 by correctly implementing
+      the finalize functions.
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Tue, 14 Apr 2009 11:32:00 +0200
+
+indicator-messages (0.1.5-0ubuntu1) jaunty; urgency=low
+
+  * New upstream version
+    * Fixes the lifecycle of the various structures tracking the messages
+      and applications.  Fixing bugs like (LP: #355616) (LP: #352881)
+    * Fixes the visual appearance by setting the widget name to grab the
+      style settings from the main applet.  (LP: #351979)
+  * debian/control: Upgrading dependency on libindicate-dev to 0.1.5 or
+    higher as the new version requires that.
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Fri, 03 Apr 2009 16:32:49 -0500
+
+indicator-messages (0.1.4-0ubuntu1) jaunty; urgency=low
+
+  * New upstream version
+    * Adding the display of indicators that are login messages coming from
+      other applications.  (LP: #345494)
+    * Making all times displayed for IM messages relative instead of
+      absolute.  (LP: #346345)
+    * Cleaning up the server removal code.  May fix (LP: #345599), I can't
+      recreate it anymore afterwards.
+
+ -- Ted Gould <ted@xxxxxxxxxx>  Mon, 30 Mar 2009 09:40:40 +0200
+
+indicator-messages (0.1.3-0ubuntu1) jaunty; urgency=low
+
+  [ Ted Gould ]
+  * New upstream version.
+    - Now changes the icon based on non-IM indicators so that Evolution
+      works much better.  (LP: #342480)
+    - Now the menu items are in a predictable order, alphabetical.
+    - The Messages for a particular client (i.e. Pidgin) are grouped with
+      the client they're associated with.
+    - Adjusting the icon size to match the new one in the Human theme.
+    - Adjusting the build so that all the different libraries are not
+      built in a versioned manner.  Now it's just one .so, which is
+      what it should have been originally.
+
+  [ Martin Pitt ]
+  * Add debian/watch.
+  * Add bzr-builddeb configuration.
+  * debian/copyright: Fix download location.
+
+ -- Martin Pitt <martin.pitt@xxxxxxxxxx>  Thu, 19 Mar 2009 12:23:17 +0100
+
+indicator-messages (0.1-0ubuntu1) jaunty; urgency=low
+
+  * Initial release, based on DX team's PPA packaging branch.
+    (lp:~indicator-applet-developers/indicator-applet/messages-packaging)
+  * debian/control: Add Homepage:, Vcs-Bzr:, and fix package
+    description.
+  * debian/copyright: Properly describe license.
+
+ -- Martin Pitt <martin.pitt@xxxxxxxxxx>  Tue, 17 Feb 2009 11:35:38 +0100
+

=== added file 'debian/compat'
--- debian/compat	1970-01-01 00:00:00 +0000
+++ debian/compat	2013-06-07 21:39:23 +0000
@@ -0,0 +1,1 @@
+9

=== added file 'debian/control'
--- debian/control	1970-01-01 00:00:00 +0000
+++ debian/control	2013-06-07 21:39:23 +0000
@@ -0,0 +1,86 @@
+Source: indicator-messages
+Section: gnome
+Priority: optional
+Maintainer: Ubuntu Developers <ubuntu-devel-discuss@xxxxxxxxxxxxxxxx>
+XSBC-Original-Maintainer: The Ayatana Packagers <pkg-ayatana-devel@xxxxxxxxxxxxxxxxxxxxxxx>
+Uploaders: Evgeni Golov <evgeni@xxxxxxxxxx>
+Build-Depends: debhelper (>= 9),
+               dh-autoreconf,
+               dh-translations,
+               libglib2.0-dev (>= 2.35.4),
+               libgtk-3-dev (>= 3.5.12),
+               libdbus-glib-1-dev,
+               intltool,
+               libindicator3-dev,
+               libdbusmenu-glib-dev (>= 0.5.90),
+               libdbusmenu-gtk3-dev (>= 0.5.90),
+               libtelepathy-glib-dev (>= 0.9.0),
+               gobject-introspection (>= 0.9.12-4~),
+               libgirepository1.0-dev (>= 0.9.12),
+               gtk-doc-tools,
+               libgtest-dev,
+               python3-dbusmock,
+Standards-Version: 3.9.3
+Homepage: https://launchpad.net/indicator-messages
+# If you aren't a member of ~indicator-applet-developers but need to upload
+# packaging changes, just go ahead.  ~indicator-applet-developers will notice
+# and sync up the code again.
+Vcs-Bzr: https://code.launchpad.net/~indicator-applet-developers/indicator-messages/trunk.13.04
+Vcs-Browser: https://bazaar.launchpad.net/~indicator-applet-developers/indicator-messages/trunk.13.04/files
+
+Package: indicator-messages
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Recommends: indicator-applet | indicator-renderer
+Replaces: libindicator-messages-status-provider1,
+          libindicator-messages-status-provider-dev,
+          indicator-status-provider-mc5,
+          indicator-status-provider-pidgin,
+          indicator-status-provider-telepathy,
+          indicator-status-provider-emesene,
+Conflicts: libindicator-messages-status-provider1,
+           libindicator-messages-status-provider-dev,
+           indicator-status-provider-mc5,
+           indicator-status-provider-pidgin,
+           indicator-status-provider-telepathy,
+           indicator-status-provider-emesene,
+Breaks: gwibber-services (<< 3.5.4-0ubuntu1~),
+        telepathy-indicator (<< 0.3.0-0ubuntu1~),
+        thunderbird (<< 15.0+build1-0ubuntu1~),
+        xchat-indicator (<< 0.3.11-0ubuntu2~),
+        xchat-gnome-indicator (<< 0.3.11-0ubuntu2~),
+Description: indicator that collects messages that need a response
+ A place on the user's desktop that collects messages that need a response.
+ This menu provides a condensed and collected view of all of those messages
+ for quick access, but without making them annoying in times that you want
+ to ignore them.
+
+Package: libmessaging-menu0
+Architecture: any
+Section: libs
+Depends: ${shlibs:Depends},
+         ${misc:Depends},
+Description: Messaging Menu - shared library
+ This library contains information to build status providers to go into
+ the messaging menu.
+
+Package: libmessaging-menu-dev
+Architecture: any
+Section: libdevel
+Depends: ${shlibs:Depends},
+         ${misc:Depends},
+         libmessaging-menu0 (=${binary:Version}),
+         libglib2.0-dev,
+Description: Messaging Menu - library development files
+ This library contains information to build status providers to go into
+ the messaging menu.
+
+Package: gir1.2-messagingmenu-1.0
+Section: libs
+Architecture: any
+Depends: ${misc:Depends},
+         ${gir:Depends},
+Description: Messaging Menu - gir bindings
+ .
+ This package can be used by other packages using the GIRepository format
+ to generate dynamic bindings.

=== added file 'debian/copyright'
--- debian/copyright	1970-01-01 00:00:00 +0000
+++ debian/copyright	2013-06-07 21:39:23 +0000
@@ -0,0 +1,19 @@
+Format-Specification: http://svn.debian.org/wsvn/dep/web/deps/dep5.mdwn?op=file&rev=135
+Name: indicator-messages
+Maintainer: Ted Gould <ted@xxxxxxxxxxxxx>
+Source: https://launchpad.net/indicator-messages
+
+Files: *
+Copyright: 2009-2010 Ted Gould <ted@xxxxxxxxxxxxx>, Canonical Ltd.
+License: GPL-3
+
+Files: debian/*
+Copyright: 2009-2010 Evgeni Golov <evgeni@xxxxxxxxxx>
+Copyright: 2009-2010 Ted Gould <ted@xxxxxxxxxxxxx>, Canonical Ltd.
+Copyright: 2009-2010 Sebastien Bacher <seb128@xxxxxxxxxx>
+Copyright: 2009-2010 Ken VanDine <ken.vandine@xxxxxxxxxxxxx>
+License: GPL-3
+
+License: GPL-3
+ On Debian systems, the complete text of the GNU General
+ Public License version 3 can be found in `/usr/share/common-licenses/GPL-3'.

=== added file 'debian/gir1.2-messagingmenu-1.0.install'
--- debian/gir1.2-messagingmenu-1.0.install	1970-01-01 00:00:00 +0000
+++ debian/gir1.2-messagingmenu-1.0.install	2013-06-07 21:39:23 +0000
@@ -0,0 +1,1 @@
+usr/lib/girepository-1.0/*.typelib

=== added file 'debian/indicator-messages.install'
--- debian/indicator-messages.install	1970-01-01 00:00:00 +0000
+++ debian/indicator-messages.install	2013-06-07 21:39:23 +0000
@@ -0,0 +1,5 @@
+usr/lib/indicators3
+usr/lib/indicator-messages/indicator-messages-service
+usr/share/dbus-1
+usr/share/glib-2.0
+usr/share/icons

=== added file 'debian/libmessaging-menu-dev.install'
--- debian/libmessaging-menu-dev.install	1970-01-01 00:00:00 +0000
+++ debian/libmessaging-menu-dev.install	2013-06-07 21:39:23 +0000
@@ -0,0 +1,5 @@
+usr/lib/libmessaging-menu.so 
+usr/lib/pkgconfig
+usr/include /usr/
+usr/share/gir-1.0/
+usr/share/gtk-doc

=== added file 'debian/libmessaging-menu0.install'
--- debian/libmessaging-menu0.install	1970-01-01 00:00:00 +0000
+++ debian/libmessaging-menu0.install	2013-06-07 21:39:23 +0000
@@ -0,0 +1,1 @@
+usr/lib/libmessaging-menu.so.* /usr/lib/

=== added file 'debian/libmessaging-menu0.symbols'
--- debian/libmessaging-menu0.symbols	1970-01-01 00:00:00 +0000
+++ debian/libmessaging-menu0.symbols	2013-06-07 21:39:23 +0000
@@ -0,0 +1,23 @@
+libmessaging-menu.so.0 libmessaging-menu0 #MINVER#
+ messaging_menu_app_append_source@Base 12.10.0
+ messaging_menu_app_append_source_with_count@Base 12.10.0
+ messaging_menu_app_append_source_with_string@Base 12.10.0
+ messaging_menu_app_append_source_with_time@Base 12.10.0
+ messaging_menu_app_draw_attention@Base 12.10.0
+ messaging_menu_app_get_type@Base 12.10.0
+ messaging_menu_app_has_source@Base 12.10.0
+ messaging_menu_app_insert_source@Base 12.10.0
+ messaging_menu_app_insert_source_with_count@Base 12.10.0
+ messaging_menu_app_insert_source_with_string@Base 12.10.0
+ messaging_menu_app_insert_source_with_time@Base 12.10.0
+ messaging_menu_app_new@Base 12.10.0
+ messaging_menu_app_register@Base 12.10.0
+ messaging_menu_app_remove_attention@Base 12.10.0
+ messaging_menu_app_remove_source@Base 12.10.0
+ messaging_menu_app_set_source_count@Base 12.10.0
+ messaging_menu_app_set_source_icon@Base 12.10.2
+ messaging_menu_app_set_source_label@Base 12.10.2
+ messaging_menu_app_set_source_string@Base 12.10.0
+ messaging_menu_app_set_source_time@Base 12.10.0
+ messaging_menu_app_set_status@Base 12.10.0
+ messaging_menu_app_unregister@Base 12.10.0

=== added file 'debian/rules'
--- debian/rules	1970-01-01 00:00:00 +0000
+++ debian/rules	2013-06-07 21:39:23 +0000
@@ -0,0 +1,17 @@
+#!/usr/bin/make -f
+
+export DPKG_GENSYMBOLS_CHECK_LEVEL=4
+
+%:
+	dh $@ --with autoreconf,translations,gir
+
+override_dh_autoreconf:
+	NO_CONFIGURE=1 dh_autoreconf ./autogen.sh
+
+override_dh_auto_configure:
+	dh_auto_configure -- --libdir="\$${prefix}/lib" --libexecdir="\$${prefix}/lib/indicator-messages" --enable-gtk-doc
+
+override_dh_install:
+	find debian/tmp/usr/lib -name *.la -delete
+	dh_install --fail-missing
+

=== added file 'debian/watch'
--- debian/watch	1970-01-01 00:00:00 +0000
+++ debian/watch	2013-06-07 21:39:23 +0000
@@ -0,0 +1,2 @@
+version=3
+http://launchpad.net/indicator-messages/+download .*/indicator-messages-([0-9.]+)\.tar\.gz

=== added directory 'doc'
=== added file 'doc/Makefile.am'
--- doc/Makefile.am	1970-01-01 00:00:00 +0000
+++ doc/Makefile.am	2013-06-07 21:39:23 +0000
@@ -0,0 +1,1 @@
+SUBDIRS = reference

=== added directory 'doc/reference'
=== added file 'doc/reference/Makefile.am'
--- doc/reference/Makefile.am	1970-01-01 00:00:00 +0000
+++ doc/reference/Makefile.am	2013-06-07 21:39:23 +0000
@@ -0,0 +1,20 @@
+DOC_MODULE = messaging-menu
+
+DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.xml
+
+DOC_SOURCE_DIR = $(top_srcdir)/libmessaging-menu
+
+MKDB_OPTIONS=--xml-mode --output-format=xml
+
+# Used for dependencies. The docs will be rebuilt if any of these change.
+HFILE_GLOB = $(top_srcdir)/libmessaging-menu/*.h
+CFILE_GLOB = $(top_srcdir)/libmessaging-menu/*.c
+
+IGNORE_HFILES= \
+	indicator-messages-service.h \
+	gtupleaction.h
+
+INCLUDES=-I$(top_srcdir)/libmessaging-menu $(GIO_CFLAGS)
+GTKDOC_LIBS=$(top_builddir)/libmessaging-menu/libmessaging-menu.la
+
+include $(top_srcdir)/gtk-doc.make

=== added file 'doc/reference/messaging-menu-docs.xml.in'
--- doc/reference/messaging-menu-docs.xml.in	1970-01-01 00:00:00 +0000
+++ doc/reference/messaging-menu-docs.xml.in	2013-06-07 21:39:23 +0000
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC '-//OASIS//DTD DocBook XML V4.5//EN'
+                      'http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd' [
+<!ENTITY % local.common.attrib "xmlns:xi  CDATA  #FIXED 'http://www.w3.org/2003/XInclude'">
+<!ENTITY version "@PACKAGE_VERSION@">
+]>
+<book lang="en" id="messaging-menu" xmlns:xi="http://www.w3.org/2003/XInclude";>
+<title>Messaging Menu Reference Manual</title>
+  <bookinfo>
+    <title>Messaging Menu Reference Manual</title>
+    <releaseinfo>for libmessaging-menu &version;</releaseinfo>
+
+    <copyright>
+      <year>2012</year>
+      <holder>Canonical Ltd.</holder>
+    </copyright>
+  </bookinfo>
+
+  <chapter>
+    <title>API Reference</title>
+    <xi:include href="xml/messaging-menu.xml"/>
+  </chapter>
+
+  <chapter id="object-tree">
+    <title>Object Hierarchy</title>
+    <xi:include href="xml/tree_index.sgml"/>
+  </chapter>
+  <index id="api-index-full">
+    <title>API Index</title>
+    <xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
+  </index>
+  <index id="deprecated-api-index" role="deprecated">
+    <title>Index of deprecated API</title>
+    <xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
+  </index>
+
+  <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
+</book>

=== added directory 'libmessaging-menu'
=== added file 'libmessaging-menu/Makefile.am'
--- libmessaging-menu/Makefile.am	1970-01-01 00:00:00 +0000
+++ libmessaging-menu/Makefile.am	2013-06-07 21:39:23 +0000
@@ -0,0 +1,66 @@
+
+lib_LTLIBRARIES = libmessaging-menu.la
+
+libmessaging_menu_ladir = $(includedir)/messaging-menu
+
+libmessaging_menu_la_SOURCES = \
+	messaging-menu.c \
+	gtupleaction.c \
+	gtupleaction.h \
+	$(BUILT_SOURCES)
+
+libmessaging_menu_la_HEADERS = \
+	messaging-menu.h
+
+libmessaging_menu_la_LIBADD = $(GIO_LIBS)
+
+libmessaging_menu_la_CFLAGS = \
+	$(GIO_CFLAGS) \
+	-Wall
+
+libmessaging_menu_la_LDFLAGS = -export-symbols-regex "^messaging_menu_.*"
+
+BUILT_SOURCES = \
+	indicator-messages-service.c \
+	indicator-messages-service.h
+
+CLEANFILES = $(BUILT_SOURCES)
+
+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
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = messaging-menu.pc
+
+
+-include $(INTROSPECTION_MAKEFILE)
+
+INTROSPECTION_GIRS =
+INTROSPECTION_SCANNER_ARGS = --add-include-path=$(srcdir) --warn-all
+INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir)
+
+if HAVE_INTROSPECTION
+
+MessagingMenu-1.0.gir: libmessaging-menu.la
+MessagingMenu_1_0_gir_NAMESPACE = MessagingMenu
+MessagingMenu_1_0_gir_INCLUDES = GObject-2.0 Gio-2.0
+MessagingMenu_1_0_gir_CFLAGS = $(INCLUDES) $(GIO_CFLAGS)
+MessagingMenu_1_0_gir_SCANNERFLAGS = --c-include="messaging-menu.h"
+MessagingMenu_1_0_gir_LIBS = libmessaging-menu.la
+MessagingMenu_1_0_gir_FILES = messaging-menu.c messaging-menu.h
+MessagingMenu_1_0_gir_EXPORT_PACKAGES = messaging-menu
+INTROSPECTION_GIRS += MessagingMenu-1.0.gir
+
+girdir = $(datadir)/gir-1.0
+gir_DATA = $(INTROSPECTION_GIRS)
+
+typelibdir = $(libdir)/girepository-1.0
+typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
+
+CLEANFILES +=$(gir_DATA) $(typelib_DATA)
+endif

=== added file 'libmessaging-menu/gtupleaction.c'
--- libmessaging-menu/gtupleaction.c	1970-01-01 00:00:00 +0000
+++ libmessaging-menu/gtupleaction.c	2013-06-07 21:39:23 +0000
@@ -0,0 +1,354 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *     Lars Uebernickel <lars.uebernickel@xxxxxxxxxxxxx>
+ */
+
+#include "gtupleaction.h"
+
+typedef GObjectClass GTupleActionClass;
+
+struct _GTupleAction
+{
+    GObject        parent;
+
+    gchar         *name;
+    GVariantType  *type;
+    gboolean       enabled;
+
+    gsize          n_children;
+    GVariant     **children;
+};
+
+static void action_interface_init (GActionInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GTupleAction, g_tuple_action, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (G_TYPE_ACTION, action_interface_init));
+
+enum
+{
+  PROP_0,
+  PROP_NAME,
+  PROP_PARAMETER_TYPE,
+  PROP_ENABLED,
+  PROP_STATE_TYPE,
+  PROP_STATE,
+  N_PROPERTIES
+};
+
+enum
+{
+  SIGNAL_ACTIVATE,
+  N_SIGNALS
+};
+
+static GParamSpec *properties[N_PROPERTIES];
+static guint       signal_ids[N_SIGNALS];
+
+static const gchar *
+g_tuple_action_get_name (GAction *action)
+{
+  GTupleAction *tuple = G_TUPLE_ACTION (action);
+
+  return tuple->name;
+}
+
+static const GVariantType *
+g_tuple_action_get_parameter_type (GAction *action)
+{
+  return NULL;
+}
+
+static const GVariantType *
+g_tuple_action_get_state_type (GAction *action)
+{
+  GTupleAction *tuple = G_TUPLE_ACTION (action);
+
+  return tuple->type;
+}
+
+static GVariant *
+g_tuple_action_get_state_hint (GAction *action)
+{
+  return NULL;
+}
+
+static gboolean
+g_tuple_action_get_enabled (GAction *action)
+{
+  GTupleAction *tuple = G_TUPLE_ACTION (action);
+
+  return tuple->enabled;
+}
+
+static GVariant *
+g_tuple_action_get_state (GAction *action)
+{
+  GTupleAction *tuple = G_TUPLE_ACTION (action);
+  GVariant *result;
+
+  result = g_variant_new_tuple (tuple->children, tuple->n_children);
+  return g_variant_ref_sink (result);
+}
+
+static void
+g_tuple_action_set_state (GTupleAction *tuple,
+                          GVariant     *state)
+{
+  int i;
+
+  g_return_if_fail (g_variant_type_is_tuple (g_variant_get_type (state)));
+
+  if (tuple->type == NULL)
+    {
+      tuple->type = g_variant_type_copy (g_variant_get_type (state));
+      tuple->n_children = g_variant_n_children (state);
+      tuple->children = g_new0 (GVariant *, tuple->n_children);
+    }
+
+  for (i = 0; i < tuple->n_children; i++)
+    {
+      if (tuple->children[i])
+        g_variant_unref (tuple->children[i]);
+      tuple->children[i] = g_variant_get_child_value (state, i);
+    }
+
+  g_object_notify_by_pspec (G_OBJECT (tuple), properties[PROP_STATE]);
+}
+
+static void
+g_tuple_action_change_state (GAction  *action,
+                             GVariant *value)
+{
+  GTupleAction *tuple = G_TUPLE_ACTION (action);
+
+  g_return_if_fail (value != NULL);
+  g_return_if_fail (g_variant_is_of_type (value, tuple->type));
+
+  g_variant_ref_sink (value);
+
+  /* TODO add a change-state signal similar to GSimpleAction */
+  g_tuple_action_set_state (tuple, value);
+
+  g_variant_unref (value);
+}
+
+static void
+g_tuple_action_activate (GAction  *action,
+                         GVariant *parameter)
+{
+  GTupleAction *tuple = G_TUPLE_ACTION (action);
+
+  g_return_if_fail (parameter == NULL);
+
+  if (tuple->enabled)
+    g_signal_emit (tuple, signal_ids[SIGNAL_ACTIVATE], 0, NULL);
+}
+
+static void
+g_tuple_action_get_property (GObject    *object,
+                             guint       prop_id,
+                             GValue     *value,
+                             GParamSpec *pspec)
+{
+  GAction *action = G_ACTION (object);
+
+  switch (prop_id)
+    {
+    case PROP_NAME:
+      g_value_set_string (value, g_tuple_action_get_name (action));
+      break;
+
+    case PROP_PARAMETER_TYPE:
+      g_value_set_boxed (value, g_tuple_action_get_parameter_type (action));
+      break;
+
+    case PROP_ENABLED:
+      g_value_set_boolean (value, g_tuple_action_get_enabled (action));
+      break;
+
+    case PROP_STATE_TYPE:
+      g_value_set_boxed (value, g_tuple_action_get_state_type (action));
+      break;
+
+    case PROP_STATE:
+      g_value_take_variant (value, g_tuple_action_get_state (action));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+g_tuple_action_set_property (GObject      *object,
+                             guint          prop_id,
+                             const GValue *value,
+                             GParamSpec   *pspec)
+{
+  GTupleAction *tuple = G_TUPLE_ACTION (object);
+
+  switch (prop_id)
+    {
+    case PROP_NAME:
+      tuple->name = g_value_dup_string (value);
+      g_object_notify_by_pspec (object, properties[PROP_NAME]);
+      break;
+
+    case PROP_ENABLED:
+      tuple->enabled = g_value_get_boolean (value);
+      g_object_notify_by_pspec (object, properties[PROP_ENABLED]);
+      break;
+
+    case PROP_STATE:
+      g_tuple_action_set_state (tuple, g_value_get_variant (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+g_tuple_action_finalize (GObject *object)
+{
+  GTupleAction *tuple = G_TUPLE_ACTION (object);
+  int i;
+
+  g_free (tuple->name);
+  g_variant_type_free (tuple->type);
+
+  for (i = 0; i < tuple->n_children; i++)
+    g_variant_unref (tuple->children[i]);
+
+  g_free (tuple->children);
+
+  G_OBJECT_CLASS (g_tuple_action_parent_class)->finalize (object);
+}
+
+static void
+action_interface_init (GActionInterface *iface)
+{
+  iface->get_name = g_tuple_action_get_name;
+  iface->get_parameter_type = g_tuple_action_get_parameter_type;
+  iface->get_state_type = g_tuple_action_get_state_type;
+  iface->get_state_hint = g_tuple_action_get_state_hint;
+  iface->get_enabled = g_tuple_action_get_enabled;
+  iface->get_state = g_tuple_action_get_state;
+  iface->change_state = g_tuple_action_change_state;
+  iface->activate = g_tuple_action_activate;
+}
+
+static void
+g_tuple_action_class_init (GTupleActionClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+  object_class->get_property = g_tuple_action_get_property;
+  object_class->set_property = g_tuple_action_set_property;
+  object_class->finalize = g_tuple_action_finalize;
+
+  properties[PROP_NAME] = g_param_spec_string ("name",
+                                               "Name",
+                                               "The name of the action",
+                                               NULL,
+                                               G_PARAM_READWRITE |
+                                               G_PARAM_CONSTRUCT_ONLY |
+                                               G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_PARAMETER_TYPE] = g_param_spec_boxed ("parameter-type",
+                                                        "Parameter Type",
+                                                        "The variant type passed to activate",
+                                                        G_TYPE_VARIANT_TYPE,
+                                                        G_PARAM_READABLE |
+                                                        G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_ENABLED] = g_param_spec_boolean ("enabled",
+                                                   "Enabled",
+                                                   "Whether the action can be activated",
+                                                   TRUE,
+                                                   G_PARAM_READWRITE |
+                                                   G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_STATE_TYPE] = g_param_spec_boxed ("state-type",
+                                                    "State Type",
+                                                    "The variant type of the state, must be a tuple",
+                                                    G_TYPE_VARIANT_TYPE,
+                                                    G_PARAM_READABLE |
+                                                    G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_STATE] = g_param_spec_variant ("state",
+                                                 "State",
+                                                 "The state of the action",
+                                                 G_VARIANT_TYPE_TUPLE,
+                                                 NULL,
+                                                 G_PARAM_READWRITE |
+                                                 G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+
+  signal_ids[SIGNAL_ACTIVATE] = g_signal_new ("activate",
+                                              G_TYPE_TUPLE_ACTION,
+                                              G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT,
+                                              0, NULL, NULL,
+                                              g_cclosure_marshal_VOID__VARIANT,
+                                              G_TYPE_NONE, 1,
+                                              G_TYPE_VARIANT);
+}
+
+static void
+g_tuple_action_init (GTupleAction *action)
+{
+  action->enabled = TRUE;
+}
+
+GTupleAction *
+g_tuple_action_new (const gchar *name,
+                    GVariant    *initial_state)
+{
+  const GVariantType *type;
+
+  g_return_val_if_fail (name != NULL, NULL);
+  g_return_val_if_fail (initial_state != NULL, NULL);
+
+  type = g_variant_get_type (initial_state);
+  g_return_val_if_fail (g_variant_type_is_tuple (type), NULL);
+
+  return g_object_new (G_TYPE_TUPLE_ACTION,
+                       "name", name,
+                       "state", initial_state,
+                       NULL);
+}
+
+void
+g_tuple_action_set_child (GTupleAction *action,
+                          gsize         index,
+                          GVariant     *value)
+{
+  const GVariantType *type;
+
+  g_return_if_fail (G_IS_TUPLE_ACTION (action));
+  g_return_if_fail (index < action->n_children);
+  g_return_if_fail (value != NULL);
+
+  type = g_variant_get_type (value);
+  g_return_if_fail (g_variant_is_of_type (value, type));
+
+  g_variant_unref (action->children[index]);
+  action->children[index] = g_variant_ref_sink (value);
+
+  g_object_notify_by_pspec (G_OBJECT (action), properties[PROP_STATE]);
+}

=== added file 'libmessaging-menu/gtupleaction.h'
--- libmessaging-menu/gtupleaction.h	1970-01-01 00:00:00 +0000
+++ libmessaging-menu/gtupleaction.h	2013-06-07 21:39:23 +0000
@@ -0,0 +1,40 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *     Lars Uebernickel <lars.uebernickel@xxxxxxxxxxxxx>
+ */
+
+#ifndef __g_tuple_action_h__
+#define __g_tuple_action_h__
+
+#include <gio/gio.h>
+
+#define G_TYPE_TUPLE_ACTION  (g_tuple_action_get_type ())
+#define G_TUPLE_ACTION(o)    (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_TUPLE_ACTION, GTupleAction))
+#define G_IS_TUPLE_ACTION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_TUPLE_ACTION))
+
+typedef struct _GTupleAction GTupleAction;
+
+GType           g_tuple_action_get_type     (void) G_GNUC_CONST;
+
+GTupleAction *  g_tuple_action_new          (const gchar *name,
+                                             GVariant    *initial_state);
+
+void            g_tuple_action_set_child    (GTupleAction *action,
+                                             gsize         index,
+                                             GVariant     *value);
+
+#endif

=== added file 'libmessaging-menu/messaging-menu.c'
--- libmessaging-menu/messaging-menu.c	1970-01-01 00:00:00 +0000
+++ libmessaging-menu/messaging-menu.c	2013-06-07 21:39:23 +0000
@@ -0,0 +1,1199 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *     Lars Uebernickel <lars.uebernickel@xxxxxxxxxxxxx>
+ */
+
+#include "messaging-menu.h"
+#include "indicator-messages-service.h"
+
+#include <gio/gdesktopappinfo.h>
+
+/**
+ * SECTION:messaging-menu
+ * @title: MessagingMenuApp
+ * @short_description: An application section in the messaging menu
+ * @include: messaging-menu.h
+ *
+ * A #MessagingMenuApp represents an application section in the
+ * Messaging Menu.  An application section is tied to an installed
+ * application through a desktop file id, which must be passed to
+ * messaging_menu_app_new().
+ *
+ * To register the application with the Messaging Menu, call
+ * messaging_menu_app_register().  This signifies that the application
+ * should be present in the menu and be marked as "running".
+ *
+ * The first menu item in an application section represents the
+ * application itself, using the name and icon found in the associated
+ * desktop file.  Activating this item starts the application.
+ *
+ * Following the application item, the Messaging Menu inserts all
+ * shortcut actions found in the desktop file.  Actions whose
+ * <code>NotShowIn</code> keyword contains "Messaging Menu" or whose
+ * <code>OnlyShowIn</code> keyword does not contain "Messaging Menu"
+ * will not appear (the <ulink
+ * url="http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.1.html#extra-actions";>
+ * desktop file specification</ulink> contains a detailed explanation of
+ * shortcut actions.)  An application cannot add, remove, or change
+ * these shortcut items while it is running.
+ *
+ * Next, an application section contains menu items for message sources.
+ * What exactly constitutes a message source depends on the type of
+ * application:  an email client's message sources are folders
+ * containing new messages, while those of a chat program are persons
+ * that have contacted the user.
+ *
+ * A message source is represented in the menu by a label and optionally
+ * also an icon.  It can be associated with either a count, a time, or
+ * an arbitrary string, which will appear on the right side of the menu
+ * item.
+ *
+ * When the user activates a source, the source is immediately removed
+ * from the menu and the "activate-source" signal is emitted.
+ *
+ * Applications should always expose all the message sources available.
+ * However, the Messaging Menu might limit the amount of sources it
+ * displays to the user.
+ *
+ * The Messaging Menu offers users a way to set their chat status
+ * (available, away, busy, invisible, or offline) for multiple
+ * applications at once.  Applications that appear in the Messaging Menu
+ * can integrate with this by setting the
+ * "X-MessagingMenu-UsesChatSection" key in their desktop file to True.
+ * Use messaging_menu_app_set_status() to signify that the application's
+ * chat status has changed.  When the user changes status through the
+ * Messaging Menu, the ::status-changed signal will be emitted.
+ *
+ * If the application stops running without calling
+ * messaging_menu_app_unregister(), it will be marked as "not running".
+ * Its application and shortcut items stay in the menu, but all message
+ * sources are removed.  If messaging_menu_app_unregister() is called,
+ * the application section is removed completely.
+ *
+ * More information about the design and recommended usage of the
+ * Messaging Menu is available at <ulink
+ * url="https://wiki.ubuntu.com/MessagingMenu";>https://wiki.ubuntu.com/MessagingMenu</ulink>.
+ */
+
+/**
+ * MessagingMenuApp:
+ *
+ * #MessagingMenuApp is an opaque structure.
+ */
+struct _MessagingMenuApp
+{
+  GObject parent_instance;
+
+  GDesktopAppInfo *appinfo;
+  int registered;  /* -1 for unknown */
+  MessagingMenuStatus status;
+  gboolean status_set;
+  GSimpleActionGroup *source_actions;
+  GMenu *menu;
+  GDBusConnection *bus;
+
+  IndicatorMessagesService *messages_service;
+  guint watch_id;
+  guint action_export_id;
+  guint menu_export_id;
+
+  GCancellable *cancellable;
+};
+
+G_DEFINE_TYPE (MessagingMenuApp, messaging_menu_app, G_TYPE_OBJECT);
+
+enum {
+  PROP_0,
+  PROP_DESKTOP_ID,
+  N_PROPERTIES
+};
+
+enum {
+  ACTIVATE_SOURCE,
+  STATUS_CHANGED,
+  N_SIGNALS
+};
+
+static GParamSpec *properties[N_PROPERTIES];
+static guint signals[N_SIGNALS];
+
+static const gchar *status_ids[] = { "available", "away", "busy", "invisible", "offline" };
+
+static void global_status_changed (IndicatorMessagesService *service,
+                                   const gchar *status_str,
+                                   gpointer user_data);
+
+static gchar *
+messaging_menu_app_get_dbus_object_path (MessagingMenuApp *app)
+{
+  gchar *path;
+
+  if (!app->appinfo)
+    return NULL;
+
+  path = g_strconcat ("/com/canonical/indicator/messages/",
+                      g_app_info_get_id (G_APP_INFO (app->appinfo)),
+                      NULL);
+
+  g_strcanon (path, "/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", '_');
+
+  return path;
+}
+
+static void
+export_menus_and_actions (GObject      *source,
+                          GAsyncResult *res,
+                          gpointer      user_data)
+{
+  MessagingMenuApp *app = user_data;
+  GError *error = NULL;
+  gchar *object_path;
+
+  object_path = messaging_menu_app_get_dbus_object_path (app);
+  if (!object_path)
+    return;
+
+  app->bus = g_bus_get_finish (res, &error);
+  if (app->bus == NULL)
+    {
+      g_warning ("unable to connect to session bus: %s", error->message);
+      g_error_free (error);
+      return;
+    }
+
+  app->action_export_id = g_dbus_connection_export_action_group (app->bus,
+                                                                 object_path,
+                                                                 G_ACTION_GROUP (app->source_actions),
+                                                                 &error);
+  if (!app->action_export_id)
+    {
+      g_warning ("unable to export action group: %s", error->message);
+      g_clear_error (&error);
+    }
+
+  app->menu_export_id = g_dbus_connection_export_menu_model (app->bus,
+                                                             object_path,
+                                                             G_MENU_MODEL (app->menu),
+                                                             &error);
+  if (!app->menu_export_id)
+    {
+      g_warning ("unable to export menu: %s", error->message);
+      g_clear_error (&error);
+    }
+
+  g_free (object_path);
+}
+
+static void
+messaging_menu_app_set_desktop_id (MessagingMenuApp *app,
+                                   const gchar      *desktop_id)
+{
+  g_return_if_fail (desktop_id != NULL);
+
+  /* no need to clean up, it's construct only */
+  app->appinfo = g_desktop_app_info_new (desktop_id);
+  if (app->appinfo == NULL)
+    {
+      g_warning ("could not find the desktop file for '%s'",
+                 desktop_id);
+    }
+
+  g_bus_get (G_BUS_TYPE_SESSION,
+             app->cancellable,
+             export_menus_and_actions,
+             app);
+}
+
+static void
+messaging_menu_app_set_property (GObject      *object,
+                                 guint         prop_id,
+                                 const GValue *value,
+                                 GParamSpec   *pspec)
+{
+  MessagingMenuApp *app = MESSAGING_MENU_APP (object);
+
+  switch (prop_id)
+    {
+    case PROP_DESKTOP_ID:
+      messaging_menu_app_set_desktop_id (app, g_value_get_string (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+messaging_menu_app_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (messaging_menu_app_parent_class)->finalize (object);
+}
+
+static void
+messaging_menu_app_dispose (GObject *object)
+{
+  MessagingMenuApp *app = MESSAGING_MENU_APP (object);
+
+  if (app->bus)
+    {
+      if (app->action_export_id > 0)
+        g_dbus_connection_unexport_action_group (app->bus, app->action_export_id);
+
+      if (app->menu_export_id > 0)
+        g_dbus_connection_unexport_menu_model (app->bus, app->menu_export_id);
+
+      app->action_export_id = 0;
+      app->menu_export_id = 0;
+      g_object_unref (app->bus);
+      app->bus = NULL;
+    }
+
+  if (app->watch_id > 0)
+    {
+      g_bus_unwatch_name (app->watch_id);
+      app->watch_id = 0;
+    }
+
+  if (app->cancellable)
+    {
+      g_cancellable_cancel (app->cancellable);
+      g_object_unref (app->cancellable);
+      app->cancellable = NULL;
+    }
+
+  if (app->messages_service)
+    {
+      indicator_messages_service_call_application_stopped_running (app->messages_service,
+                                                                   g_app_info_get_id (G_APP_INFO (app->appinfo)),
+                                                                   NULL, NULL, NULL);
+
+      g_signal_handlers_disconnect_by_func (app->messages_service,
+                                            global_status_changed,
+                                            app);
+      g_clear_object (&app->messages_service);
+    }
+
+  g_clear_object (&app->appinfo);
+  g_clear_object (&app->source_actions);
+  g_clear_object (&app->menu);
+
+  G_OBJECT_CLASS (messaging_menu_app_parent_class)->dispose (object);
+}
+
+static void
+messaging_menu_app_class_init (MessagingMenuAppClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+  object_class->set_property = messaging_menu_app_set_property;
+  object_class->finalize = messaging_menu_app_finalize;
+  object_class->dispose = messaging_menu_app_dispose;
+
+  /**
+   * MessagingMenuApp:desktop-id:
+   *
+   * The desktop id of the application associated with this application
+   * section.  Must be given when the #MessagingMenuApp is created.
+   */
+  properties[PROP_DESKTOP_ID] = g_param_spec_string ("desktop-id",
+                                                     "Desktop Id",
+                                                     "The desktop id of the associated application",
+                                                     NULL,
+                                                     G_PARAM_WRITABLE |
+                                                     G_PARAM_CONSTRUCT_ONLY |
+                                                     G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+
+  /**
+   * MessagingMenuApp::activate-source:
+   * @mmapp: the #MessagingMenuApp
+   * @source_id: the source id that was activated
+   *
+   * Emitted when the user has activated the message source with id
+   * @source_id.  The source is immediately removed from the menu,
+   * handlers of this signal do not need to call
+   * messaging_menu_app_remove_source().
+   */
+  signals[ACTIVATE_SOURCE] = g_signal_new ("activate-source",
+                                           MESSAGING_MENU_TYPE_APP,
+                                           G_SIGNAL_RUN_FIRST |
+                                           G_SIGNAL_DETAILED,
+                                           0,
+                                           NULL, NULL,
+                                           g_cclosure_marshal_VOID__STRING,
+                                           G_TYPE_NONE, 1, G_TYPE_STRING);
+
+  /**
+   * MessagingMenuApp::status-changed:
+   * @mmapp: the #MessagingMenuApp
+   * @status: a #MessagingMenuStatus
+   *
+   * Emitted when the chat status is changed through the messaging menu.
+   *
+   * Applications which are registered to use the chat status should
+   * change their status to @status upon receiving this signal.  Call
+   * messaging_menu_app_set_status() to acknowledge that the application
+   * changed its status.
+   */
+  signals[STATUS_CHANGED] = g_signal_new ("status-changed",
+                                          MESSAGING_MENU_TYPE_APP,
+                                          G_SIGNAL_RUN_FIRST,
+                                          0,
+                                          NULL, NULL,
+                                          g_cclosure_marshal_VOID__INT,
+                                          G_TYPE_NONE, 1, G_TYPE_INT);
+}
+
+static void
+created_messages_service (GObject      *source_object,
+                          GAsyncResult *result,
+                          gpointer      user_data)
+{
+  MessagingMenuApp *app = user_data;
+  GError *error = NULL;
+
+  app->messages_service = indicator_messages_service_proxy_new_finish (result, &error);
+  if (!app->messages_service)
+    {
+      g_warning ("unable to connect to the mesaging menu service: %s", error->message);
+      g_error_free (error);
+      return;
+    }
+
+  g_signal_connect (app->messages_service, "status-changed",
+                    G_CALLBACK (global_status_changed), app);
+
+  /* sync current status */
+  if (app->registered == TRUE)
+    messaging_menu_app_register (app);
+  else if (app->registered == FALSE)
+    messaging_menu_app_unregister (app);
+  if (app->status_set)
+    messaging_menu_app_set_status (app, app->status);
+}
+
+static void
+indicator_messages_appeared (GDBusConnection *bus,
+                             const gchar     *name,
+                             const gchar     *name_owner,
+                             gpointer         user_data)
+{
+  MessagingMenuApp *app = user_data;
+
+  indicator_messages_service_proxy_new (bus,
+                                        G_DBUS_PROXY_FLAGS_NONE,
+                                        "com.canonical.indicator.messages",
+                                        "/com/canonical/indicator/messages/service",
+                                        app->cancellable,
+                                        created_messages_service,
+                                        app);
+}
+
+static void
+indicator_messages_vanished (GDBusConnection *bus,
+                             const gchar     *name,
+                             gpointer         user_data)
+{
+  MessagingMenuApp *app = user_data;
+
+  if (app->messages_service)
+    {
+      g_signal_handlers_disconnect_by_func (app->messages_service,
+                                            global_status_changed,
+                                            app);
+      g_clear_object (&app->messages_service);
+    }
+}
+
+static void
+messaging_menu_app_init (MessagingMenuApp *app)
+{
+  app->registered = -1;
+  app->status_set = FALSE;
+  app->bus = NULL;
+
+  app->action_export_id = 0;
+  app->menu_export_id = 0;
+
+  app->cancellable = g_cancellable_new ();
+
+  app->source_actions = g_simple_action_group_new ();
+  app->menu = g_menu_new ();
+
+  app->cancellable = g_cancellable_new ();
+
+  app->watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
+                                    "com.canonical.indicator.messages",
+                                    G_BUS_NAME_WATCHER_FLAGS_NONE,
+                                    indicator_messages_appeared,
+                                    indicator_messages_vanished,
+                                    app,
+                                    NULL);
+}
+
+/**
+ * messaging_menu_new:
+ * @desktop_id: a desktop file id. See g_desktop_app_info_new()
+ *
+ * Creates a new #MessagingMenuApp for the application associated with
+ * @desktop_id.
+ *
+ * The application will not show up (nor be marked as "running") in the
+ * Messaging Menu before messaging_menu_app_register() has been called.
+ *
+ * Returns: (transfer full): a new #MessagingMenuApp
+ */
+MessagingMenuApp *
+messaging_menu_app_new (const gchar *desktop_id)
+{
+  return g_object_new (MESSAGING_MENU_TYPE_APP,
+                       "desktop-id", desktop_id,
+                       NULL);
+}
+
+/**
+ * messaging_menu_app_register:
+ * @app: a #MessagingMenuApp
+ *
+ * Registers @app with the Messaging Menu.
+ *
+ * If the application doesn't already have a section in the Messaging
+ * Menu, one will be created for it.  The application will also be
+ * marked as "running".
+ *
+ * The application will be marked as "not running" as soon as @app is
+ * destroyed.  The application launcher as well as shortcut actions will
+ * remain in the menu.  To completely remove the application section
+ * from the Messaging Menu, call messaging_menu_app_unregister().
+ */
+void
+messaging_menu_app_register (MessagingMenuApp *app)
+{
+  gchar *object_path;
+
+  g_return_if_fail (MESSAGING_MENU_IS_APP (app));
+
+  app->registered = TRUE;
+
+  /* state will be synced right after connecting to the service */
+  if (!app->messages_service)
+    return;
+
+  object_path = messaging_menu_app_get_dbus_object_path (app);
+  if (!object_path)
+    return;
+
+  indicator_messages_service_call_register_application (app->messages_service,
+                                                        g_app_info_get_id (G_APP_INFO (app->appinfo)),
+                                                        object_path,
+                                                        app->cancellable,
+                                                        NULL, NULL);
+
+  g_free (object_path);
+}
+
+/**
+ * messaging_menu_app_unregister:
+ * @app: a #MessagingMenuApp
+ *
+ * Completely removes the @app from the Messaging Menu.  If the
+ * application's launcher and shortcut actions should remain in the
+ * menu, destroying @app with g_object_unref() suffices.
+ *
+ * Note: @app will remain valid and usable after this call.
+ */
+void
+messaging_menu_app_unregister (MessagingMenuApp *app)
+{
+  g_return_if_fail (MESSAGING_MENU_IS_APP (app));
+
+  app->registered = FALSE;
+
+  /* state will be synced right after connecting to the service */
+  if (!app->messages_service)
+    return;
+
+  if (!app->appinfo)
+    return;
+
+  indicator_messages_service_call_unregister_application (app->messages_service,
+                                                          g_app_info_get_id (G_APP_INFO (app->appinfo)),
+                                                          app->cancellable,
+                                                          NULL, NULL);
+}
+
+/**
+ * messaging_menu_app_set_status:
+ * @app: a #MessagingMenuApp
+ * @status: a #MessagingMenuStatus
+ *
+ * Notify the Messaging Menu that the chat status of @app has changed to
+ * @status.
+ *
+ * Connect to the ::status-changed signal to receive notification about
+ * the user changing their global chat status through the Messaging
+ * Menu.
+ *
+ * This function does nothing for applications whose desktop file does
+ * not include X-MessagingMenu-UsesChatSection.
+ */
+void
+messaging_menu_app_set_status (MessagingMenuApp    *app,
+                               MessagingMenuStatus  status)
+{
+  g_return_if_fail (MESSAGING_MENU_IS_APP (app));
+  g_return_if_fail (status >= MESSAGING_MENU_STATUS_AVAILABLE &&
+                    status <= MESSAGING_MENU_STATUS_OFFLINE);
+
+  app->status = status;
+  app->status_set = TRUE;
+
+  /* state will be synced right after connecting to the service */
+  if (!app->messages_service)
+    return;
+
+  if (!app->appinfo)
+    return;
+
+  indicator_messages_service_call_set_status (app->messages_service,
+                                              g_app_info_get_id (G_APP_INFO (app->appinfo)),
+                                              status_ids [status],
+                                              app->cancellable,
+                                              NULL, NULL);
+}
+
+static int
+status_from_string (const gchar *s)
+{
+  int i;
+
+  if (!s)
+    return -1;
+
+  for (i = 0; i <= MESSAGING_MENU_STATUS_OFFLINE; i++)
+    {
+      if (g_str_equal (s, status_ids[i]))
+        return i;
+    }
+
+  return -1;
+}
+
+static void
+global_status_changed (IndicatorMessagesService *service,
+                       const gchar *status_str,
+                       gpointer user_data)
+{
+  MessagingMenuApp *app = user_data;
+  int status;
+
+  status = status_from_string (status_str);
+  g_return_if_fail (status >= 0);
+
+  g_signal_emit (app, signals[STATUS_CHANGED], 0, status);
+}
+
+static void
+source_action_activated (GSimpleAction *action,
+                         GVariant      *parameter,
+                         gpointer       user_data)
+{
+  MessagingMenuApp *app = user_data;
+  const gchar *name = g_action_get_name (G_ACTION (action));
+  GQuark q = g_quark_from_string (name);
+
+  messaging_menu_app_remove_source (app, name);
+
+  g_signal_emit (app, signals[ACTIVATE_SOURCE], q, name);
+}
+
+static void
+messaging_menu_app_insert_source_action (MessagingMenuApp *app,
+                                         gint              position,
+                                         const gchar      *id,
+                                         GIcon            *icon,
+                                         const gchar      *label,
+                                         GVariant         *state)
+{
+  GSimpleAction *action;
+  GMenuItem *menuitem;
+
+  g_return_if_fail (MESSAGING_MENU_IS_APP (app));
+  g_return_if_fail (id != NULL);
+
+  if (g_simple_action_group_lookup (app->source_actions, id))
+    {
+      g_warning ("a source with id '%s' already exists", id);
+      return;
+    }
+
+  action = g_simple_action_new_stateful (id, NULL, state);
+  g_signal_connect (action, "activate",
+                    G_CALLBACK (source_action_activated), app);
+  g_simple_action_group_insert (app->source_actions, G_ACTION (action));
+  g_object_unref (action);
+
+  menuitem = g_menu_item_new (label, id);
+  g_menu_item_set_attribute (menuitem, "x-canonical-type", "s", "ImSourceMenuItem");
+  if (icon)
+    {
+      gchar *iconstr = g_icon_to_string (icon);
+      g_menu_item_set_attribute (menuitem, "x-canonical-icon", "s", iconstr);
+      g_free (iconstr);
+    }
+  g_menu_insert_item (app->menu, position, menuitem);
+  g_object_unref (menuitem);
+}
+
+static GSimpleAction *
+messaging_menu_app_get_source_action (MessagingMenuApp *app,
+                                      const gchar      *source_id)
+
+{
+  GAction *action;
+
+  g_return_val_if_fail (MESSAGING_MENU_IS_APP (app), NULL);
+  g_return_val_if_fail (source_id != NULL, NULL);
+
+  action = g_simple_action_group_lookup (app->source_actions, source_id);
+  if (action == NULL)
+    g_warning ("a source with id '%s' doesn't exist", source_id);
+
+  return G_SIMPLE_ACTION (action);
+}
+
+static void
+messaging_menu_app_set_source_action (MessagingMenuApp *app,
+                                      const gchar      *source_id,
+                                      guint             count,
+                                      gint64            time,
+                                      const gchar      *string)
+{
+  GSimpleAction *action;
+  GVariant *state;
+  gboolean draws_attention;
+  GVariant *new_state;
+
+  action = messaging_menu_app_get_source_action (app, source_id);
+  if (!action)
+    return;
+
+  state = g_action_get_state (G_ACTION (action));
+  g_variant_get_child (state, 3, "b", &draws_attention);
+
+  new_state = g_variant_new ("(uxsb)", count, time, string, draws_attention);
+  g_simple_action_set_state (action, new_state);
+
+  g_variant_unref (state);
+}
+
+static void
+messaging_menu_app_set_draws_attention (MessagingMenuApp *app,
+                                        const gchar      *source_id,
+                                        gboolean          draws_attention)
+{
+  GSimpleAction *action;
+  GVariant *state;
+  guint count;
+  gint64 time;
+  const gchar *string;
+  GVariant *new_state;
+
+  action = messaging_menu_app_get_source_action (app, source_id);
+  if (!action)
+    return;
+
+  state = g_action_get_state (G_ACTION (action));
+  g_variant_get (state, "(ux&sb)", &count, &time, &string, NULL);
+
+  new_state = g_variant_new ("(uxsb)", count, time, string, TRUE);
+  g_simple_action_set_state (action, new_state);
+
+  g_variant_unref (state);
+}
+
+/**
+ * messaging_menu_app_insert_source:
+ * @app: a #MessagingMenuApp
+ * @position: the position at which to insert the source
+ * @id: a unique identifier for the source to be added
+ * @icon: the icon associated with the source
+ * @label: a user-visible string best describing the source
+ *
+ * Inserts a new message source into the section representing @app.  Equivalent
+ * to calling messaging_menu_app_insert_source_with_time() with the current
+ * time.
+ *
+ * It is an error to insert a source with an @id which already exists.  Use
+ * messaging_menu_app_has_source() to find out whether there is such a source.
+ */
+void
+messaging_menu_app_insert_source (MessagingMenuApp *app,
+                                  gint              position,
+                                  const gchar      *id,
+                                  GIcon            *icon,
+                                  const gchar      *label)
+{
+  messaging_menu_app_insert_source_with_time (app, position, id, icon, label,
+                                              g_get_real_time ());
+}
+
+/**
+ * messaging_menu_app_append_source:
+ * @app: a #MessagingMenuApp
+ * @id: a unique identifier for the source to be added
+ * @icon: (allow-none): the icon associated with the source
+ * @label: a user-visible string best describing the source
+ *
+ * Appends a new message source to the end of the section representing @app.
+ * Equivalent to calling messaging_menu_app_append_source_with_time() with the
+ * current time.
+ *
+ * It is an error to add a source with an @id which already exists.  Use
+ * messaging_menu_app_has_source() to find out whether there is such a source.
+ */
+void
+messaging_menu_app_append_source (MessagingMenuApp *app,
+                                  const gchar      *id,
+                                  GIcon            *icon,
+                                  const gchar      *label)
+{
+  messaging_menu_app_insert_source (app, -1, id, icon, label);
+}
+
+/**
+ * messaging_menu_app_insert_source_with_count:
+ * @app: a #MessagingMenuApp
+ * @position: the position at which to insert the source
+ * @id: a unique identifier for the source to be added
+ * @icon: (allow-none): the icon associated with the source
+ * @label: a user-visible string best describing the source
+ * @count: the count for the source
+ *
+ * Inserts a new message source into the section representing @app and
+ * initializes it with @count.
+ *
+ * To update the count, use messaging_menu_app_set_source_count().
+ *
+ * It is an error to insert a source with an @id which already exists.  Use
+ * messaging_menu_app_has_source() to find out whether there is such a source.
+ */
+void
+messaging_menu_app_insert_source_with_count (MessagingMenuApp *app,
+                                             gint              position,
+                                             const gchar      *id,
+                                             GIcon            *icon,
+                                             const gchar      *label,
+                                             guint             count)
+{
+  messaging_menu_app_insert_source_action (app, position, id, icon, label,
+                                           g_variant_new ("(uxsb)", count, 0, "", FALSE));
+}
+
+/**
+ * messaging_menu_app_append_source_with_count:
+ * @app: a #MessagingMenuApp
+ * @id: a unique identifier for the source to be added
+ * @icon: (allow-none): the icon associated with the source
+ * @label: a user-visible string best describing the source
+ * @count: the count for the source
+ *
+ * Appends a new message source to the end of the section representing @app and
+ * initializes it with @count.
+ *
+ * To update the count, use messaging_menu_app_set_source_count().
+ *
+ * It is an error to add a source with an @id which already exists.  Use
+ * messaging_menu_app_has_source() to find out whether there is such a source.
+ */
+void messaging_menu_app_append_source_with_count (MessagingMenuApp *app,
+                                                  const gchar      *id,
+                                                  GIcon            *icon,
+                                                  const gchar      *label,
+                                                  guint             count)
+{
+  messaging_menu_app_insert_source_with_count (app, -1, id, icon, label, count);
+}
+
+/**
+ * messaging_menu_app_insert_source_with_time:
+ * @app: a #MessagingMenuApp
+ * @position: the position at which to insert the source
+ * @id: a unique identifier for the source to be added
+ * @icon: (allow-none): the icon associated with the source
+ * @label: a user-visible string best describing the source
+ * @time: the time when the source was created, in microseconds
+ *
+ * Inserts a new message source into the section representing @app and
+ * initializes it with @time.  Use messaging_menu_app_insert_source() to
+ * insert a source with the current time.
+ *
+ * To change the time, use messaging_menu_app_set_source_time().
+ *
+ * It is an error to insert a source with an @id which already exists.  Use
+ * messaging_menu_app_has_source() to find out whether there is such a source.
+ */
+void
+messaging_menu_app_insert_source_with_time (MessagingMenuApp *app,
+                                            gint              position,
+                                            const gchar      *id,
+                                            GIcon            *icon,
+                                            const gchar      *label,
+                                            gint64            time)
+{
+  messaging_menu_app_insert_source_action (app, position, id, icon, label,
+                                           g_variant_new ("(uxsb)", 0, time, "", FALSE));
+}
+
+/**
+ * messaging_menu_app_append_source_with_time:
+ * @app: a #MessagingMenuApp
+ * @id: a unique identifier for the source to be added
+ * @icon: (allow-none): the icon associated with the source
+ * @label: a user-visible string best describing the source
+ * @time: the time when the source was created, in microseconds
+ *
+ * Appends a new message source to the end of the section representing
+ * @app and initializes it with @time.  Use
+ * messaging_menu_app_append_source() to append a source with the
+ * current time.
+ *
+ * To change the time, use messaging_menu_app_set_source_time().
+ *
+ * It is an error to insert a source with an @id which already exists.  Use
+ * messaging_menu_app_has_source() to find out whether there is such a source.
+ */
+void
+messaging_menu_app_append_source_with_time (MessagingMenuApp *app,
+                                            const gchar      *id,
+                                            GIcon            *icon,
+                                            const gchar      *label,
+                                            gint64            time)
+{
+  messaging_menu_app_insert_source_with_time (app, -1, id, icon, label, time);
+}
+
+/**
+ * messaging_menu_app_insert_source_with_string:
+ * @app: a #MessagingMenuApp
+ * @position: the position at which to insert the source
+ * @id: a unique identifier for the source to be added
+ * @icon: (allow-none): the icon associated with the source
+ * @label: a user-visible string best describing the source
+ * @str: a string associated with the source
+ *
+ * Inserts a new message source into the section representing @app and
+ * initializes it with @str.
+ *
+ * To update the string, use messaging_menu_app_set_source_string().
+ *
+ * It is an error to insert a source with an @id which already exists.  Use
+ * messaging_menu_app_has_source() to find out whether there is such a source.
+ */
+void
+messaging_menu_app_insert_source_with_string (MessagingMenuApp *app,
+                                              gint              position,
+                                              const gchar      *id,
+                                              GIcon            *icon,
+                                              const gchar      *label,
+                                              const gchar      *str)
+{
+  messaging_menu_app_insert_source_action (app, position, id, icon, label,
+                                           g_variant_new ("(uxsb)", 0, 0, str, FALSE));
+}
+
+/**
+ * messaging_menu_app_append_source_with_string:
+ * @app: a #MessagingMenuApp
+ * @id: a unique identifier for the source to be added
+ * @icon: (allow-none): the icon associated with the source
+ * @label: a user-visible string best describing the source
+ * @str: a string associated with the source
+ *
+ * Appends a new message source to the end of the section representing @app and
+ * initializes it with @str.
+ *
+ * To update the string, use messaging_menu_app_set_source_string().
+ *
+ * It is an error to insert a source with an @id which already exists.  Use
+ * messaging_menu_app_has_source() to find out whether there is such a source.
+ */
+void
+messaging_menu_app_append_source_with_string (MessagingMenuApp *app,
+                                              const gchar      *id,
+                                              GIcon            *icon,
+                                              const gchar      *label,
+                                              const gchar      *str)
+{
+  messaging_menu_app_insert_source_with_string (app, -1, id, icon, label, str);
+}
+
+/**
+ * messaging_menu_app_remove_source:
+ * @app: a #MessagingMenuApp
+ * @source_id: the id of the source to remove
+ *
+ * Removes the source corresponding to @source_id from the menu.
+ */
+void
+messaging_menu_app_remove_source (MessagingMenuApp *app,
+                                  const gchar      *source_id)
+{
+  int n_items;
+  int i;
+
+  g_return_if_fail (MESSAGING_MENU_IS_APP (app));
+  g_return_if_fail (source_id != NULL);
+
+  if (g_simple_action_group_lookup (app->source_actions, source_id) == NULL)
+      return;
+
+  n_items = g_menu_model_get_n_items (G_MENU_MODEL (app->menu));
+  for (i = 0; i < n_items; i++)
+    {
+      gchar *action;
+
+      if (g_menu_model_get_item_attribute (G_MENU_MODEL (app->menu), i,
+                                           "action", "s", &action))
+        {
+          if (!g_strcmp0 (action, source_id))
+            {
+              g_menu_remove (app->menu, i);
+              break;
+            }
+
+          g_free (action);
+        }
+    }
+
+  g_simple_action_group_remove (app->source_actions, source_id);
+}
+
+/**
+ * messaging_menu_app_has_source:
+ * @app: a #MessagingMenuApp
+ * @source_id: a source id
+ *
+ * Returns: TRUE if there is a source associated with @source_id
+ */
+gboolean
+messaging_menu_app_has_source (MessagingMenuApp *app,
+                               const gchar      *source_id)
+{
+  g_return_val_if_fail (MESSAGING_MENU_IS_APP (app), FALSE);
+  g_return_val_if_fail (source_id != NULL, FALSE);
+
+  return g_simple_action_group_lookup (app->source_actions, source_id) != NULL;
+}
+
+static GMenuItem *
+g_menu_find_item_with_action (GMenu        *menu,
+                              const gchar  *action,
+                              gint         *out_pos)
+{
+  gint i;
+  gint n_elements;
+  GMenuItem *item = NULL;
+
+  n_elements = g_menu_model_get_n_items (G_MENU_MODEL (menu));
+
+  for (i = 0; i < n_elements && item == NULL; i++)
+    {
+      GVariant *attr;
+
+      item = g_menu_item_new_from_model (G_MENU_MODEL (menu), i);
+      attr = g_menu_item_get_attribute_value (item, G_MENU_ATTRIBUTE_ACTION, G_VARIANT_TYPE_STRING);
+
+      if (!g_str_equal (action, g_variant_get_string (attr, NULL)))
+        g_clear_object (&item);
+
+      g_variant_unref (attr);
+    }
+
+  if (item && out_pos)
+    *out_pos = i - 1;
+
+  return item;
+}
+
+static void
+g_menu_replace_item (GMenu     *menu,
+                     gint       pos,
+                     GMenuItem *item)
+{
+  g_menu_remove (menu, pos);
+  g_menu_insert_item (menu, pos, item);
+}
+
+/**
+ * messaging_menu_app_set_source_label:
+ * @app: a #MessagingMenuApp
+ * @source_id: a source id
+ * @label: the new label for the source
+ *
+ * Changes the label of @source_id to @label.
+ */
+void
+messaging_menu_app_set_source_label (MessagingMenuApp *app,
+                                     const gchar      *source_id,
+                                     const gchar      *label)
+{
+  gint pos;
+  GMenuItem *item;
+
+  g_return_if_fail (MESSAGING_MENU_IS_APP (app));
+  g_return_if_fail (source_id != NULL);
+  g_return_if_fail (label != NULL);
+
+  item = g_menu_find_item_with_action (app->menu, source_id, &pos);
+  if (item == NULL)
+    return;
+
+  g_menu_item_set_attribute (item, G_MENU_ATTRIBUTE_LABEL, "s", label);
+  g_menu_replace_item (app->menu, pos, item);
+
+  g_object_unref (item);
+}
+
+/**
+ * messaging_menu_app_set_source_icon:
+ * @app: a #MessagingMenuApp
+ * @source_id: a source id
+ * @icon: (allow-none): the new icon for the source
+ *
+ * Changes the icon of @source_id to @icon.
+ */
+void
+messaging_menu_app_set_source_icon (MessagingMenuApp *app,
+                                    const gchar      *source_id,
+                                    GIcon            *icon)
+{
+  gint pos;
+  GMenuItem *item;
+
+  g_return_if_fail (MESSAGING_MENU_IS_APP (app));
+  g_return_if_fail (source_id != NULL);
+
+  item = g_menu_find_item_with_action (app->menu, source_id, &pos);
+  if (item == NULL)
+    return;
+
+  if (icon)
+    {
+      gchar *iconstr;
+
+      iconstr = g_icon_to_string (icon);
+      g_menu_item_set_attribute (item, "x-canonical-icon", "s", iconstr);
+
+      g_free (iconstr);
+    }
+  else
+    {
+      g_menu_item_set_attribute_value (item, "x-canonical-icon", NULL);
+    }
+
+  g_menu_replace_item (app->menu, pos, item);
+
+  g_object_unref (item);
+}
+
+/**
+ * messaging_menu_app_set_source_count:
+ * @app: a #MessagingMenuApp
+ * @source_id: a source id
+ * @count: the new count for the source
+ *
+ * Updates the count of @source_id to @count.
+ */
+void messaging_menu_app_set_source_count (MessagingMenuApp *app,
+                                          const gchar      *source_id,
+                                          guint             count)
+{
+  messaging_menu_app_set_source_action (app, source_id, count, 0, "");
+}
+
+/**
+ * messaging_menu_app_set_source_time:
+ * @app: a #MessagingMenuApp
+ * @source_id: a source id
+ * @time: the new time for the source, in microseconds
+ *
+ * Updates the time of @source_id to @time.
+ */
+void
+messaging_menu_app_set_source_time (MessagingMenuApp *app,
+                                    const gchar      *source_id,
+                                    gint64            time)
+{
+  messaging_menu_app_set_source_action (app, source_id, 0, time, "");
+}
+
+/**
+ * messaging_menu_app_set_source_string:
+ * @app: a #MessagingMenuApp
+ * @source_id: a source id
+ * @str: the new string for the source
+ *
+ * Updates the string displayed next to @source_id to @str.
+ */
+void
+messaging_menu_app_set_source_string (MessagingMenuApp *app,
+                                      const gchar      *source_id,
+                                      const gchar      *str)
+{
+  messaging_menu_app_set_source_action (app, source_id, 0, 0, str);
+}
+
+/**
+ * messaging_menu_app_draw_attention:
+ * @app: a #MessagingMenuApp
+ * @source_id: a source id
+ *
+ * Indicates that @source_id has important unread messages.  Currently, this
+ * means that the messaging menu's envelope icon will turn blue.
+ *
+ * Use messaging_menu_app_remove_attention() to stop indicating that the source
+ * needs attention.
+ */
+void
+messaging_menu_app_draw_attention (MessagingMenuApp *app,
+                                   const gchar      *source_id)
+{
+  messaging_menu_app_set_draws_attention (app, source_id, TRUE);
+}
+
+/**
+ * messaging_menu_app_remove_attention:
+ * @app: a #MessagingMenuApp
+ * @source_id: a source id
+ *
+ * Stop indicating that @source_id needs attention.
+ *
+ * This function does not need to be called when the source is removed
+ * with messaging_menu_app_remove_source() or the user has activated the
+ * source.
+ *
+ * Use messaging_menu_app_draw_attention() to make @source_id draw attention
+ * again.
+ */
+void
+messaging_menu_app_remove_attention (MessagingMenuApp *app,
+                                     const gchar      *source_id)
+{
+  messaging_menu_app_set_draws_attention (app, source_id, TRUE);
+}

=== added file 'libmessaging-menu/messaging-menu.h'
--- libmessaging-menu/messaging-menu.h	1970-01-01 00:00:00 +0000
+++ libmessaging-menu/messaging-menu.h	2013-06-07 21:39:23 +0000
@@ -0,0 +1,148 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *     Lars Uebernickel <lars.uebernickel@xxxxxxxxxxxxx>
+ */
+
+#ifndef __messaging_menu_h__
+#define __messaging_menu_h__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define MESSAGING_MENU_TYPE_APP         messaging_menu_app_get_type()
+#define MESSAGING_MENU_APP(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), MESSAGING_MENU_TYPE_APP, MessagingMenuApp))
+#define MESSAGING_MENU_APP_CLASS(c)     (G_TYPE_CHECK_CLASS_CAST ((c), MESSAGING_MENU_TYPE_APP, MessagingMenuAppClass))
+#define MESSAGING_MENU_IS_APP(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), MESSAGING_MENU_TYPE_APP))
+
+/**
+ * MessagingMenuStatus:
+ * @MESSAGING_MENU_STATUS_AVAILABLE: available
+ * @MESSAGING_MENU_STATUS_AWAY: away
+ * @MESSAGING_MENU_STATUS_BUSY: busy
+ * @MESSAGING_MENU_STATUS_INVISIBLE: invisible
+ * @MESSAGING_MENU_STATUS_OFFLINE: offline
+ *
+ * An enumeration for the possible chat statuses the messaging menu can be in.
+ */
+typedef enum {
+  MESSAGING_MENU_STATUS_AVAILABLE,
+  MESSAGING_MENU_STATUS_AWAY,
+  MESSAGING_MENU_STATUS_BUSY,
+  MESSAGING_MENU_STATUS_INVISIBLE,
+  MESSAGING_MENU_STATUS_OFFLINE
+} MessagingMenuStatus;
+
+
+typedef GObjectClass             MessagingMenuAppClass;
+typedef struct _MessagingMenuApp MessagingMenuApp;
+
+GType               messaging_menu_app_get_type                  (void) G_GNUC_CONST;
+
+MessagingMenuApp *  messaging_menu_app_new                       (const gchar *desktop_id);
+
+void                messaging_menu_app_register                  (MessagingMenuApp *app);
+void                messaging_menu_app_unregister                (MessagingMenuApp *app);
+
+void                messaging_menu_app_set_status                (MessagingMenuApp   *app,
+                                                                  MessagingMenuStatus status);
+
+void                messaging_menu_app_insert_source             (MessagingMenuApp *app,
+                                                                  gint              position,
+                                                                  const gchar      *id,
+                                                                  GIcon            *icon,
+                                                                  const gchar      *label);
+
+void                messaging_menu_app_append_source             (MessagingMenuApp *app,
+                                                                  const gchar      *id,
+                                                                  GIcon            *icon,
+                                                                  const gchar      *label);
+
+void                messaging_menu_app_insert_source_with_count  (MessagingMenuApp *app,
+                                                                  gint              position,
+                                                                  const gchar      *id,
+                                                                  GIcon            *icon,
+                                                                  const gchar      *label,
+                                                                  guint             count);
+
+void                messaging_menu_app_append_source_with_count  (MessagingMenuApp *app,
+                                                                  const gchar      *id,
+                                                                  GIcon            *icon,
+                                                                  const gchar      *label,
+                                                                  guint             count);
+
+void                messaging_menu_app_insert_source_with_time   (MessagingMenuApp *app,
+                                                                  gint              position,
+                                                                  const gchar      *id,
+                                                                  GIcon            *icon,
+                                                                  const gchar      *label,
+                                                                  gint64            time);
+
+void                messaging_menu_app_append_source_with_time   (MessagingMenuApp *app,
+                                                                  const gchar      *id,
+                                                                  GIcon            *icon,
+                                                                  const gchar      *label,
+                                                                  gint64            time);
+
+void                messaging_menu_app_append_source_with_string (MessagingMenuApp *app,
+                                                                  const gchar      *id,
+                                                                  GIcon            *icon,
+                                                                  const gchar      *label,
+                                                                  const gchar      *str);
+
+void                messaging_menu_app_insert_source_with_string (MessagingMenuApp *app,
+                                                                  gint              position,
+                                                                  const gchar      *id,
+                                                                  GIcon            *icon,
+                                                                  const gchar      *label,
+                                                                  const gchar      *str);
+
+void                messaging_menu_app_remove_source             (MessagingMenuApp *app,
+                                                                  const gchar      *source_id);
+
+gboolean            messaging_menu_app_has_source                (MessagingMenuApp *app,
+                                                                  const gchar      *source_id);
+
+void                messaging_menu_app_set_source_label          (MessagingMenuApp *app,
+                                                                  const gchar      *source_id,
+                                                                  const gchar      *label);
+
+void                messaging_menu_app_set_source_icon           (MessagingMenuApp *app,
+                                                                  const gchar      *source_id,
+                                                                  GIcon            *icon);
+
+void                messaging_menu_app_set_source_count          (MessagingMenuApp *app,
+                                                                  const gchar      *source_id,
+                                                                  guint             count);
+
+void                messaging_menu_app_set_source_time           (MessagingMenuApp *app,
+                                                                  const gchar      *source_id,
+                                                                  gint64            time);
+
+void                messaging_menu_app_set_source_string         (MessagingMenuApp *app,
+                                                                  const gchar      *source_id,
+                                                                  const gchar      *str);
+
+void                messaging_menu_app_draw_attention            (MessagingMenuApp *app,
+                                                                  const gchar      *source_id);
+
+void                messaging_menu_app_remove_attention          (MessagingMenuApp *app,
+                                                                  const gchar      *source_id);
+
+G_END_DECLS
+
+#endif

=== added file 'libmessaging-menu/messaging-menu.pc.in'
--- libmessaging-menu/messaging-menu.pc.in	1970-01-01 00:00:00 +0000
+++ libmessaging-menu/messaging-menu.pc.in	2013-06-07 21:39:23 +0000
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@/messaging-menu
+
+Name: Messaging Menu Library
+Description: Messaging Menu client library
+Version: @VERSION@
+Requires: gio-unix-2.0
+Libs: -L${libdir} -lmessaging-menu
+Cflags: -I${includedir}

=== added directory 'm4'
=== added file 'm4/ax_python_module.m4'
--- m4/ax_python_module.m4	1970-01-01 00:00:00 +0000
+++ m4/ax_python_module.m4	2013-06-07 21:39:23 +0000
@@ -0,0 +1,49 @@
+# ===========================================================================
+#     http://www.gnu.org/software/autoconf-archive/ax_python_module.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_PYTHON_MODULE(modname[, fatal])
+#
+# DESCRIPTION
+#
+#   Checks for Python module.
+#
+#   If fatal is non-empty then absence of a module will trigger an error.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Andrew Collier <colliera@xxxxxxxxxx>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved. This file is offered as-is, without any
+#   warranty.
+
+#serial 5
+
+AU_ALIAS([AC_PYTHON_MODULE], [AX_PYTHON_MODULE])
+AC_DEFUN([AX_PYTHON_MODULE],[
+    if test -z $PYTHON;
+    then
+        PYTHON="python"
+    fi
+    PYTHON_NAME=`basename $PYTHON`
+    AC_MSG_CHECKING($PYTHON_NAME module: $1)
+	$PYTHON -c "import $1" 2>/dev/null
+	if test $? -eq 0;
+	then
+		AC_MSG_RESULT(yes)
+		eval AS_TR_CPP(HAVE_PYMOD_$1)=yes
+	else
+		AC_MSG_RESULT(no)
+		eval AS_TR_CPP(HAVE_PYMOD_$1)=no
+		#
+		if test -n "$2"
+		then
+			AC_MSG_ERROR(failed to find required module $1)
+			exit 1
+		fi
+	fi
+])

=== added file 'm4/gcov.m4'
--- m4/gcov.m4	1970-01-01 00:00:00 +0000
+++ m4/gcov.m4	2013-06-07 21:39:23 +0000
@@ -0,0 +1,86 @@
+# Checks for existence of coverage tools:
+#  * gcov
+#  * lcov
+#  * genhtml
+#  * gcovr
+# 
+# Sets ac_cv_check_gcov to yes if tooling is present
+# and reports the executables to the variables LCOV, GCOVR and GENHTML.
+AC_DEFUN([AC_TDD_GCOV],
+[
+  AC_ARG_ENABLE(gcov,
+  AS_HELP_STRING([--enable-gcov],
+		 [enable coverage testing with gcov]),
+  [use_gcov=$enableval], [use_gcov=no])
+
+  if test "x$use_gcov" = "xyes"; then
+  # we need gcc:
+  if test "$GCC" != "yes"; then
+    AC_MSG_ERROR([GCC is required for --enable-gcov])
+  fi
+
+  # Check if ccache is being used
+  AC_CHECK_PROG(SHTOOL, shtool, shtool)
+  case `$SHTOOL path $CC` in
+    *ccache*[)] gcc_ccache=yes;;
+    *[)] gcc_ccache=no;;
+  esac
+
+  if test "$gcc_ccache" = "yes" && (test -z "$CCACHE_DISABLE" || test "$CCACHE_DISABLE" != "1"); then
+    AC_MSG_ERROR([ccache must be disabled when --enable-gcov option is used. You can disable ccache by setting environment variable CCACHE_DISABLE=1.])
+  fi
+
+  lcov_version_list="1.6 1.7 1.8 1.9"
+  AC_CHECK_PROG(LCOV, lcov, lcov)
+  AC_CHECK_PROG(GENHTML, genhtml, genhtml)
+
+  if test "$LCOV"; then
+    AC_CACHE_CHECK([for lcov version], glib_cv_lcov_version, [
+      glib_cv_lcov_version=invalid
+      lcov_version=`$LCOV -v 2>/dev/null | $SED -e 's/^.* //'`
+      for lcov_check_version in $lcov_version_list; do
+        if test "$lcov_version" = "$lcov_check_version"; then
+          glib_cv_lcov_version="$lcov_check_version (ok)"
+        fi
+      done
+    ])
+  else
+    lcov_msg="To enable code coverage reporting you must have one of the following lcov versions installed: $lcov_version_list"
+    AC_MSG_ERROR([$lcov_msg])
+  fi
+
+  case $glib_cv_lcov_version in
+    ""|invalid[)]
+      lcov_msg="You must have one of the following versions of lcov: $lcov_version_list (found: $lcov_version)."
+      AC_MSG_ERROR([$lcov_msg])
+      LCOV="exit 0;"
+      ;;
+  esac
+
+  if test -z "$GENHTML"; then
+    AC_MSG_ERROR([Could not find genhtml from the lcov package])
+  fi
+
+  ac_cv_check_gcov=yes
+  ac_cv_check_lcov=yes
+
+  # Remove all optimization flags from CFLAGS
+  changequote({,})
+  CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O[0-9]*//g'`
+  changequote([,])
+
+  # Add the special gcc flags
+  COVERAGE_CFLAGS="-O0 -fprofile-arcs -ftest-coverage"
+  COVERAGE_CXXFLAGS="-O0 -fprofile-arcs -ftest-coverage"	
+  COVERAGE_LDFLAGS="-lgcov"
+
+  # Check availability of gcovr
+  AC_CHECK_PROG(GCOVR, gcovr, gcovr)
+  if test -z "$GCOVR"; then
+    ac_cv_check_gcovr=no
+  else
+    ac_cv_check_gcovr=yes
+  fi
+
+fi
+]) # AC_TDD_GCOV

=== added file 'm4/gtest.m4'
--- m4/gtest.m4	1970-01-01 00:00:00 +0000
+++ m4/gtest.m4	2013-06-07 21:39:23 +0000
@@ -0,0 +1,63 @@
+# Copyright (C) 2012 Canonical, Ltd.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+# Checks whether the gtest source is available on the system. Allows for
+# adjusting the include and source path. Sets have_gtest=yes if the source is
+# present. Sets GTEST_CPPFLAGS and GTEST_SOURCE to the preprocessor flags and
+# source location respectively.
+AC_DEFUN([CHECK_GTEST],
+[
+  AC_ARG_WITH([gtest-include-path],
+              [AS_HELP_STRING([--with-gtest-include-path],
+                              [location of the Google test headers])],
+              [GTEST_CPPFLAGS="-I$withval"])
+
+  AC_ARG_WITH([gtest-source-path],
+              [AS_HELP_STRING([--with-gtest-source-path],
+                              [location of the Google test sources, defaults to /usr/src/gtest])],
+              [GTEST_SOURCE="$withval"],
+              [GTEST_SOURCE="/usr/src/gtest"])
+
+  GTEST_CPPFLAGS="$GTEST_CPPFLAGS -I$GTEST_SOURCE"
+
+  AC_LANG_PUSH([C++])
+
+  tmp_CPPFLAGS="$CPPFLAGS"
+  CPPFLAGS="$CPPFLAGS $GTEST_CPPFLAGS"
+
+  AC_CHECK_HEADER([gtest/gtest.h])
+
+  CPPFLAGS="$tmp_CPPFLAGS"
+
+  AC_LANG_POP
+
+  AC_CHECK_FILES([$GTEST_SOURCE/src/gtest-all.cc]
+                 [$GTEST_SOURCE/src/gtest_main.cc],
+                 [have_gtest_source=yes],
+                 [have_gtest_source=no])
+
+  AS_IF([test "x$ac_cv_header_gtest_gtest_h" = xyes -a \
+              "x$have_gtest_source" = xyes],
+        [have_gtest=yes]
+        [AC_SUBST(GTEST_CPPFLAGS)]
+        [AC_SUBST(GTEST_SOURCE)],
+        [have_gtest=no])
+]) # CHECK_GTEST

=== modified file 'po/POTFILES.in'
--- po/POTFILES.in	2011-07-02 14:42:05 +0000
+++ po/POTFILES.in	2013-06-07 21:39:23 +0000
@@ -1,9 +1,3 @@
 [encoding: UTF-8]
-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

=== added file 'po/indicator-messages.pot'
--- po/indicator-messages.pot	1970-01-01 00:00:00 +0000
+++ po/indicator-messages.pot	2013-06-07 21:39:23 +0000
@@ -0,0 +1,46 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-11-16 14:53+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@xxxxxx>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../src/messages-service.c:329
+msgid "Messages"
+msgstr ""
+
+#: ../src/messages-service.c:552
+msgid "Available"
+msgstr ""
+
+#: ../src/messages-service.c:553
+msgid "Away"
+msgstr ""
+
+#: ../src/messages-service.c:554
+msgid "Busy"
+msgstr ""
+
+#: ../src/messages-service.c:555
+msgid "Invisible"
+msgstr ""
+
+#: ../src/messages-service.c:556
+msgid "Offline"
+msgstr ""
+
+#: ../src/messages-service.c:659
+msgid "Clear"
+msgstr ""

=== modified file 'src/Makefile.am'
--- src/Makefile.am	2011-07-08 19:46:06 +0000
+++ src/Makefile.am	2013-06-07 21:39:23 +0000
@@ -15,262 +15,80 @@
 messaginglib_LTLIBRARIES = libmessaging.la
 libmessaging_la_SOURCES = \
 	indicator-messages.c \
-	gen-messages-service.xml.h \
-	gen-messages-service.xml.c \
+	ido-menu-item.c \
+	ido-menu-item.h \
+	im-app-menu-item.c \
+	im-app-menu-item.h \
+	im-source-menu-item.c \
+	im-source-menu-item.h \
+	ido-detail-label.c \
+	ido-detail-label.h \
+	indicator-messages-service.c \
+	indicator-messages-service.h
 	dbus-data.h
 libmessaging_la_CFLAGS = \
 	$(APPLET_CFLAGS) \
+	$(COVERAGE_CFLAGS) \
 	-Wall \
 	-Wl,-Bsymbolic-functions \
 	-Wl,-z,defs \
 	-Wl,--as-needed \
 	-Werror \
 	-DG_LOG_DOMAIN=\"Indicator-Messages\"
-libmessaging_la_LIBADD = $(APPLET_LIBS)
-libmessaging_la_LDFLAGS = -module -avoid-version
+libmessaging_la_LIBADD = $(APPLET_LIBS) -lm
+libmessaging_la_LDFLAGS = \
+	$(COVERAGE_LDFLAGS) \
+	-module -avoid-version
 
 ######################################
 # Building the messages service
 ######################################
 
 indicator_messages_service_SOURCES = \
-	default-applications.h \
-	default-applications.c \
 	messages-service.c \
-	messages-service-dbus.c \
-	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 \
-	launcher-menu-item.c \
-	launcher-menu-item.h \
-	seen-db.c \
-	seen-db.h \
-	dirs.h \
+	indicator-messages-service.c \
+	indicator-messages-service.h \
+	app-section.c \
+	app-section.h \
 	dbus-data.h \
-	\
-	status-items.c \
-	status-items.h
+	gactionmuxer.c \
+	gactionmuxer.h \
+	gsettingsstrv.c \
+	gsettingsstrv.h \
+	gmenuutils.c \
+	gmenuutils.h
 
 indicator_messages_service_CFLAGS = \
 	$(APPLET_CFLAGS) \
+	$(COVERAGE_CFLAGS) \
 	-Wall \
 	-Wl,-Bsymbolic-functions \
 	-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
-
-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 ";" >> $@
+	$(APPLET_LIBS)
+
+indicator_messages_service_LDFLAGS = \
+	$(COVERAGE_LDFLAGS)
+
+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
 
-######################################
-# 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)
 

=== renamed file 'src/app-menu-item.c' => 'src/app-section.c'
--- src/app-menu-item.c	2011-04-06 16:24:05 +0000
+++ src/app-section.c	2013-06-07 21:39:23 +0000
@@ -2,9 +2,10 @@
 An indicator to show information that is in messaging applications
 that the user is using.
 
-Copyright 2009 Canonical Ltd.
+Copyright 2012 Canonical Ltd.
 
 Authors:
+    Lars Uebernickel <lars.uebernickel@xxxxxxxxxxxxx>
     Ted Gould <ted@xxxxxxxxxxxxx>
 
 This program is free software: you can redistribute it and/or modify it 
@@ -26,554 +27,790 @@
 
 #include <glib/gi18n.h>
 #include <gio/gdesktopappinfo.h>
-#include <libdbusmenu-glib/client.h>
-#include <libdbusmenu-glib/menuitem-proxy.h>
-#include "app-menu-item.h"
+#include <gio/gio.h>
+#include <libindicator/indicator-desktop-shortcuts.h>
+#include "app-section.h"
 #include "dbus-data.h"
-#include "default-applications.h"
-#include "seen-db.h"
+#include "gmenuutils.h"
+#include "gactionmuxer.h"
+
+struct _AppSectionPrivate
+{
+	GDesktopAppInfo * appinfo;
+	GFileMonitor *desktop_file_monitor;
+
+	IndicatorDesktopShortcuts * ids;
+
+	GMenu *menu;
+	GMenuModel *source_menu;
+
+	GSimpleActionGroup *static_shortcuts;
+	GActionGroup *source_actions;
+	GActionMuxer *muxer;
+
+	gboolean draws_attention;
+	gboolean uses_chat_status;
+	gchar *chat_status;
+
+	guint name_watch_id;
+};
 
 enum {
-	COUNT_CHANGED,
-	NAME_CHANGED,
-	SHORTCUT_ADDED,
-	SHORTCUT_REMOVED,
-	LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-typedef struct _AppMenuItemPrivate AppMenuItemPrivate;
-
-struct _AppMenuItemPrivate
-{
-	IndicateListener *            listener;
-	IndicateListenerServer *      server;
-	
-	gchar * type;
-	GAppInfo * appinfo;
-	GKeyFile * keyfile;
-	gchar * desktop;
-	guint unreadcount;
-
-	DbusmenuClient * client;
-	DbusmenuMenuitem * root;
-	GList * shortcuts;
-};
-
-#define APP_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), APP_MENU_ITEM_TYPE, AppMenuItemPrivate))
+	PROP_0,
+	PROP_APPINFO,
+	PROP_ACTIONS,
+	PROP_DRAWS_ATTENTION,
+	PROP_USES_CHAT_STATUS,
+	PROP_CHAT_STATUS,
+	NUM_PROPERTIES
+};
+
+static GParamSpec *properties[NUM_PROPERTIES];
+static guint destroy_signal;
 
 /* Prototypes */
-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 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 app_section_finalize     (GObject *object);
+static void activate_cb              (GSimpleAction *action,
+				      GVariant *param,
+				      gpointer userdata);
+static void launch_action_change_state (GSimpleAction *action,
+					GVariant      *value,
+					gpointer       user_data);
+static void app_section_set_app_info (AppSection *self,
+				      GDesktopAppInfo *appinfo);
+static gboolean any_action_draws_attention	(GActionGroup *group,
+						 const gchar *ignored_action);
+static void	action_added			(GActionGroup *group,
+						 const gchar *action_name,
+						 gpointer user_data);
+static void	action_state_changed		(GActionGroup *group,
+						 const gchar *action_name,
+						 GVariant *value,
+						 gpointer user_data);
+static void	action_removed			(GActionGroup *group,
+						 const gchar *action_name,
+						 gpointer user_data);
+static gboolean	action_draws_attention		(GVariant *state);
+static void	desktop_file_changed_cb		(GFileMonitor      *monitor,
+						 GFile             *file,
+						 GFile             *other_file,
+						 GFileMonitorEvent  event,
+						 gpointer           user_data);
 
 /* GObject Boilerplate */
-G_DEFINE_TYPE (AppMenuItem, app_menu_item, DBUSMENU_TYPE_MENUITEM);
+G_DEFINE_TYPE (AppSection, app_section, G_TYPE_OBJECT);
 
 static void
-app_menu_item_class_init (AppMenuItemClass *klass)
+app_section_class_init (AppSectionClass *klass)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (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,
-	                                      G_STRUCT_OFFSET (AppMenuItemClass, name_changed),
-	                                      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;
+	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;
+	object_class->finalize = app_section_finalize;
+
+	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);
+
+	properties[PROP_ACTIONS] = g_param_spec_object ("actions",
+							"Actions",
+							"The actions exported by this application",
+							G_TYPE_ACTION_GROUP,
+							G_PARAM_READABLE);
+
+	properties[PROP_DRAWS_ATTENTION] = g_param_spec_boolean ("draws-attention",
+								 "Draws attention",
+								 "Whether the section currently draws attention",
+								 FALSE,
+								 G_PARAM_READABLE);
+
+	properties[PROP_USES_CHAT_STATUS] = g_param_spec_boolean ("uses-chat-status",
+								  "Uses chat status",
+								  "Whether the section uses the global chat status",
+								  FALSE,
+								  G_PARAM_READABLE);
+
+	properties[PROP_CHAT_STATUS] = g_param_spec_string ("chat-status",
+							    "Chat status",
+							    "Current chat status of the application",
+							    NULL,
+							    G_PARAM_READWRITE |
+							    G_PARAM_STATIC_STRINGS);
+
+	g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
+
+	destroy_signal = g_signal_new ("destroy",
+				       APP_SECTION_TYPE,
+				       G_SIGNAL_RUN_FIRST,
+				       0,
+				       NULL, NULL,
+				       g_cclosure_marshal_VOID__VOID,
+				       G_TYPE_NONE, 0);
 }
 
 static void
-app_menu_item_init (AppMenuItem *self)
+app_section_init (AppSection *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;
+	AppSectionPrivate *priv;
+
+	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+						  APP_SECTION_TYPE,
+						  AppSectionPrivate);
+	priv = self->priv;
+
 	priv->appinfo = NULL;
-	priv->keyfile = NULL;
-	priv->desktop = NULL;
-	priv->unreadcount = 0;
-
-	priv->client = NULL;
-	priv->root = NULL;
-	priv->shortcuts = NULL;
-
-	dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(self), DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
-
-	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->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;
-	}
-
-	if (priv->keyfile != NULL) {
-		g_object_unref(priv->keyfile);
-		priv->keyfile = NULL;
-	}
-
-	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;
-	}
-
-	if (priv->desktop != NULL) {
-		g_free(priv->desktop);
-		priv->desktop = NULL;
-	}
-
-	G_OBJECT_CLASS (app_menu_item_parent_class)->finalize (object);
-
-	return;
-}
-
-AppMenuItem *
-app_menu_item_new (IndicateListener * listener, IndicateListenerServer * server)
-{
-	AppMenuItem * self = g_object_new(APP_MENU_ITEM_TYPE, NULL);
-
-	AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self);
-
-	/* 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);
-
-	return self;
-}
-
-static void
-update_label (AppMenuItem * self)
-{
-	AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self);
-	const gchar * name = get_default_name(priv->desktop);
-
-	if (name == NULL) {
-		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);
-	AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self);
-
-	if (priv->appinfo != NULL) {
-		g_object_unref(G_OBJECT(priv->appinfo));
-		priv->appinfo = NULL;
-	}
-
-	if (priv->desktop != NULL) {
-		g_free(priv->desktop);
-		priv->desktop = NULL;
-	}
-
-	if (value == NULL || value[0] == '\0') {
-		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);
-
-	priv->keyfile = g_key_file_new();
-	g_key_file_load_from_file(priv->keyfile, value, G_KEY_FILE_NONE, NULL);
-
-	priv->desktop = g_strdup(value);
-
-	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);
-
-	const gchar * def_icon = get_default_icon(priv->desktop);
-	if (def_icon == NULL) {
-		gchar * iconstr = NULL;
-
-		/* Check for the over ride key and see if we should be using that
-		   icon.  If we can't get it, then go back to the app info */
-		if (g_key_file_has_key(priv->keyfile, G_KEY_FILE_DESKTOP_GROUP, ICON_KEY, NULL) && iconstr == NULL) {
-			GError * error = NULL;
-
-			iconstr = 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);
-			}
-		}
-
-		/* For some reason that didn't work, let's try the app info */
-		if (iconstr == NULL) {
-			GIcon * icon = g_app_info_get_icon(priv->appinfo);
-			iconstr = g_icon_to_string(icon);
-		}
-
-		dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), APPLICATION_MENUITEM_PROP_ICON, iconstr);
-		g_free(iconstr);
-	} else {
-		dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), APPLICATION_MENUITEM_PROP_ICON, def_icon);
-	}
-
-	g_signal_emit(G_OBJECT(self), signals[NAME_CHANGED], 0, app_menu_item_get_name(self), TRUE);
-
-	return;
-}
-
-/* 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);
-
-	DbusmenuMenuitem * root = dbusmenu_client_get_root(priv->client);
-	if (root != NULL) {
-		root_changed(priv->client, root, self);
-	}
-
-	return;
-}
-
-static void
-activate_cb (AppMenuItem * self, guint timestamp, gpointer data)
-{
-	AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self);
-
-	indicate_listener_display(priv->listener, priv->server, NULL, timestamp);
-
-	return;
-}
-
-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;
-}
-
-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)
-{
-	g_return_val_if_fail(IS_APP_MENU_ITEM(appitem), NULL);
-	AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(appitem);
-
-	if (priv->appinfo == NULL) {
-		return INDICATE_LISTENER_SERVER_DBUS_NAME(priv->server);
-	} else {
-		return g_app_info_get_name(priv->appinfo);
-	}
-}
-
-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);
-	return priv->desktop;
-}
-
-/* Get the dynamic items added onto the end of
-   and app entry. */
-GList *
-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;
+
+	priv->menu = g_menu_new ();
+	priv->static_shortcuts = g_simple_action_group_new ();
+
+	priv->muxer = g_action_muxer_new ();
+	g_action_muxer_insert (priv->muxer, NULL, G_ACTION_GROUP (priv->static_shortcuts));
+
+	priv->draws_attention = FALSE;
+
+	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;
+
+	case PROP_DRAWS_ATTENTION:
+		g_value_set_boolean (value, app_section_get_draws_attention (self));
+		break;
+
+	case PROP_USES_CHAT_STATUS:
+		g_value_set_boolean (value, app_section_get_uses_chat_status (self));
+		break;
+
+	case PROP_CHAT_STATUS:
+		g_value_set_string (value, app_section_get_status (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;
+
+	case PROP_CHAT_STATUS:
+		app_section_set_status (self, g_value_get_string (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 = self->priv;
+
+	if (priv->desktop_file_monitor) {
+		g_signal_handlers_disconnect_by_func (priv->desktop_file_monitor, desktop_file_changed_cb, self);
+		g_clear_object (&priv->desktop_file_monitor);
+	}
+
+	g_clear_object (&priv->menu);
+	g_clear_object (&priv->static_shortcuts);
+
+	if (priv->name_watch_id) {
+		g_bus_unwatch_name (priv->name_watch_id);
+		priv->name_watch_id = 0;
+	}
+
+	if (priv->source_actions) {
+		g_action_muxer_remove  (priv->muxer, "source");
+		g_object_disconnect (priv->source_actions,
+				     "any_signal::action-added", action_added, self,
+				     "any_signal::action-state-changed", action_state_changed, self,
+				     "any_signal::action-removed", action_removed, self,
+				     NULL);
+		g_clear_object (&priv->source_actions);
+	}
+
+	g_clear_object (&priv->muxer);
+
+	g_clear_object (&priv->source_menu);
+	g_clear_object (&priv->ids);
+	g_clear_object (&priv->appinfo);
+
+	G_OBJECT_CLASS (app_section_parent_class)->dispose (object);
+}
+
+static void
+app_section_finalize (GObject *object)
+{
+	AppSection * self = APP_SECTION(object);
+
+	g_free (self->priv->chat_status);
+
+	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 = mi->priv;
+
+	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
+keyfile_loaded (GObject *source_object,
+		GAsyncResult *result,
+		gpointer user_data)
+{
+	AppSection *self = user_data;
+	gchar *contents;
+	gsize length;
+	GKeyFile *keyfile;
+	GError *error = NULL;
+
+	if (!g_file_load_contents_finish (G_FILE (source_object), result,
+					 &contents, &length, NULL, &error)) {
+		g_warning ("could not read key file: %s", error->message);
+		g_error_free (error);
+		return;
+	}
+
+	keyfile = g_key_file_new ();
+	if (!g_key_file_load_from_data (keyfile, contents, length, 0, &error)) {
+		g_warning ("could not read key file: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	self->priv->uses_chat_status = g_key_file_get_boolean (keyfile,
+							       G_KEY_FILE_DESKTOP_GROUP,
+							       "X-MessagingMenu-UsesChatSection",
+							       &error);
+
+	g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_USES_CHAT_STATUS]);
+
+	if (error) {
+		if (error->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND) {
+			g_warning ("could not read X-MessagingMenu-UsesChatSection: %s",
+				   error->message);
+		}
+		g_error_free (error);
+		goto out;
+	}
+
+out:
+	g_key_file_free (keyfile);
+	g_free (contents);
+}
+
+static void
+g_menu_clear (GMenu *menu)
+{
+	gint n_items = g_menu_model_get_n_items (G_MENU_MODEL (menu));
+
+	while (n_items--)
+		g_menu_remove (menu, 0);
+}
+
+static void
+g_simple_action_group_clear (GSimpleActionGroup *group)
+{
+	gchar **actions;
+	gchar **it;
+
+	actions = g_action_group_list_actions (G_ACTION_GROUP (group));
+	for (it = actions; *it; it++)
+		g_simple_action_group_remove (group, *it);
+
+	g_strfreev (actions);
+}
+
+static void
+app_section_update_menu (AppSection *self)
+{
+	AppSectionPrivate *priv = self->priv;
+	GSimpleAction *launch;
+	GFile *keyfile;
+	GMenuItem *item;
+	gchar *iconstr;
+	gboolean is_running;
+
+	g_menu_clear (priv->menu);
+	g_simple_action_group_clear (priv->static_shortcuts);
+
+	is_running = priv->name_watch_id > 0;
+	launch = g_simple_action_new_stateful ("launch", NULL, g_variant_new_boolean (is_running));
+	g_signal_connect (launch, "activate", G_CALLBACK (activate_cb), self);
+	g_signal_connect (launch, "change-state", G_CALLBACK (launch_action_change_state), self);
+	g_simple_action_group_insert (priv->static_shortcuts, G_ACTION (launch));
+
+	item = g_menu_item_new (g_app_info_get_name (G_APP_INFO (priv->appinfo)), "launch");
+	g_menu_item_set_attribute (item, "x-canonical-type", "s", "ImAppMenuItem");
+	iconstr = g_icon_to_string (g_app_info_get_icon (G_APP_INFO (priv->appinfo)));
+	g_menu_item_set_attribute (item, "x-canonical-icon", "s", iconstr);
+	g_free (iconstr);
+
+	g_menu_append_item (priv->menu, item);
+	g_object_unref (item);
+
+	/* 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 (nicks[i], NULL);
+		g_signal_connect(action, "activate", G_CALLBACK (nick_activate_cb), self);
+		g_simple_action_group_insert (priv->static_shortcuts, G_ACTION (action));
+		g_object_unref (action);
+
+		item = g_menu_item_new (name, nicks[i]);
+		g_menu_item_set_attribute (item, "x-canonical-type", "s", "IdoMenuItem");
+		g_menu_item_set_attribute (item, "x-canonical-icon", "s", ""); /* empty to get indentation */
+		g_menu_append_item (priv->menu, item);
+
+		g_object_unref (item);
+		g_free(name);
+	}
+
+	keyfile = g_file_new_for_path (g_desktop_app_info_get_filename (priv->appinfo));
+	g_file_load_contents_async (keyfile, NULL, keyfile_loaded, self);
+
+	g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ACTIONS]);
+
+	g_object_unref (keyfile);
+	g_object_unref (launch);
+}
+
+static void
+desktop_file_changed_cb (GFileMonitor      *monitor,
+			 GFile             *file,
+			 GFile             *other_file,
+			 GFileMonitorEvent  event,
+			 gpointer           user_data)
+{
+	AppSection *self = user_data;
+
+	if (event == G_FILE_MONITOR_EVENT_CHANGED) {
+		app_section_update_menu (self);
+	}
+	else if (event == G_FILE_MONITOR_EVENT_DELETED ||
+		 event == G_FILE_MONITOR_EVENT_UNMOUNTED) {
+		g_signal_emit (self, destroy_signal, 0);
+	}
+}
+
+static void
+app_section_set_app_info (AppSection *self,
+			  GDesktopAppInfo *appinfo)
+{
+	AppSectionPrivate *priv = self->priv;
+	GFile *desktop_file;
+	GError *error = NULL;
+
+	g_return_if_fail (priv->appinfo == NULL);
+	g_return_if_fail (priv->desktop_file_monitor == NULL);
+
+	if (appinfo == NULL) {
+		g_warning ("appinfo must not be NULL");
+		return;
+	}
+
+	priv->appinfo = g_object_ref (appinfo);
+
+	desktop_file = g_file_new_for_path (g_desktop_app_info_get_filename (appinfo));
+	priv->desktop_file_monitor = g_file_monitor (desktop_file, G_FILE_MONITOR_SEND_MOVED, NULL, &error);
+	if (priv->desktop_file_monitor == NULL) {
+		g_warning ("unable to watch desktop file: %s", error->message);
+		g_error_free (error);
+	}
+	g_signal_connect (priv->desktop_file_monitor, "changed",
+			  G_CALLBACK (desktop_file_changed_cb), self);
+
+	g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_APPINFO]);
+
+	app_section_update_menu (self);
+
+	g_object_unref (desktop_file);
+}
+
+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 = mi->priv;
+	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': %s",
+			  g_desktop_app_info_get_filename (priv->appinfo),
+			  error->message);
+		g_error_free (error);
+	}
+}
+
+static void
+launch_action_change_state (GSimpleAction *action,
+			    GVariant      *value,
+			    gpointer       user_data)
+{
+	g_simple_action_set_state (action, value);
+}
+
+const gchar *
+app_section_get_desktop (AppSection * self)
+{
+	AppSectionPrivate * priv = self->priv;
+	if (priv->appinfo)
+		return g_desktop_app_info_get_filename (priv->appinfo);
+	else
+		return NULL;
+}
+
+GActionGroup *
+app_section_get_actions (AppSection *self)
+{
+	AppSectionPrivate * priv = self->priv;
+	return G_ACTION_GROUP (priv->muxer);
+}
+
+GMenuModel *
+app_section_get_menu (AppSection *self)
+{
+	AppSectionPrivate * priv = self->priv;
+	return G_MENU_MODEL (priv->menu);
+}
+
+GAppInfo *
+app_section_get_app_info (AppSection *self)
+{
+	AppSectionPrivate * priv = self->priv;
+	return G_APP_INFO (priv->appinfo);
+}
+
+gboolean
+app_section_get_draws_attention (AppSection *self)
+{
+	AppSectionPrivate * priv = self->priv;
+	return priv->draws_attention;
+}
+
+void
+app_section_clear_draws_attention (AppSection *self)
+{
+	AppSectionPrivate * priv = self->priv;
+	gchar **action_names;
+	gchar **it;
+
+	if (priv->source_actions == NULL)
+		return;
+
+	action_names = g_action_group_list_actions (priv->source_actions);
+
+	for (it = action_names; *it; it++) {
+		GVariant *state;
+
+		state = g_action_group_get_action_state (priv->source_actions, *it);
+		if (!state)
+			continue;
+
+		/* clear draws-attention while preserving other state */
+		if (action_draws_attention (state)) {
+			guint32 count;
+			gint64 time;
+			const gchar *str;
+			GVariant *new_state;
+
+			g_variant_get (state, "(ux&sb)", &count, &time, &str, NULL);
+
+			new_state = g_variant_new ("(uxsb)", count, time, str, FALSE);
+			g_action_group_change_action_state (priv->source_actions, *it, new_state);
+		}
+
+		g_variant_unref (state);
+	}
+
+	g_strfreev (action_names);
+}
+
+static void
+application_vanished (GDBusConnection *bus,
+		      const gchar *name,
+		      gpointer user_data)
+{
+	AppSection *self = user_data;
+
+	app_section_unset_object_path (self);
+}
+
+/*
+ * app_section_set_object_path:
+ * @self: an #AppSection
+ * @bus: a #GDBusConnection
+ * @bus_name: the bus name of the application
+ * @object_path: the object path on which the app exports its actions and menus
+ *
+ * Sets the D-Bus object path exported by an instance of the application
+ * associated with @self.  Actions and menus exported on that path will be
+ * shown in the section.
+ */
+void
+app_section_set_object_path (AppSection *self,
+			     GDBusConnection *bus,
+			     const gchar *bus_name,
+			     const gchar *object_path)
+{
+	AppSectionPrivate *priv = self->priv;
+	GMenuItem *item;
+
+	g_object_freeze_notify (G_OBJECT (self));
+	app_section_unset_object_path (self);
+
+	priv->source_actions = G_ACTION_GROUP (g_dbus_action_group_get (bus, bus_name, object_path));
+	g_action_muxer_insert (priv->muxer, "source", priv->source_actions);
+
+	priv->draws_attention = any_action_draws_attention (priv->source_actions, NULL);
+	g_object_connect (priv->source_actions,
+			  "signal::action-added", action_added, self,
+			  "signal::action-state-changed", action_state_changed, self,
+			  "signal::action-removed", action_removed, self,
+			  NULL);
+
+	priv->source_menu = G_MENU_MODEL (g_dbus_menu_model_get (bus, bus_name, object_path));
+
+	item = g_menu_item_new_section (NULL, priv->source_menu);
+	g_menu_item_set_attribute (item, "action-namespace", "s", "source");
+	g_menu_append_item (priv->menu, item);
+	g_object_unref (item);
+
+	priv->name_watch_id = g_bus_watch_name_on_connection (bus, bus_name, 0,
+							      NULL, application_vanished,
+							      self, NULL);
+
+	g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ACTIONS]);
+	g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DRAWS_ATTENTION]);
+	g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_USES_CHAT_STATUS]);
+	g_object_thaw_notify (G_OBJECT (self));
+
+	g_action_group_change_action_state (G_ACTION_GROUP (priv->static_shortcuts),
+					    "launch", g_variant_new_boolean (TRUE));
+}
+
+/*
+ * app_section_unset_object_path:
+ * @self: an #AppSection
+ *
+ * Unsets the object path set with app_section_set_object_path().  The section
+ * will return to only showing application name and static shortcuts in the
+ * menu.
+ */
+void
+app_section_unset_object_path (AppSection *self)
+{
+	AppSectionPrivate *priv = self->priv;
+
+	if (priv->name_watch_id) {
+		g_bus_unwatch_name (priv->name_watch_id);
+		priv->name_watch_id = 0;
+	}
+
+	if (priv->source_actions) {
+		g_object_disconnect (priv->source_actions,
+				     "any_signal::action-added", action_added, self,
+				     "any_signal::action-state-changed", action_state_changed, self,
+				     "any_signal::action-removed", action_removed, self,
+				     NULL);
+		g_clear_object (&priv->source_actions);
+	}
+
+	if (priv->source_menu) {
+		/* the last menu item points is linked to the app's menumodel */
+		gint n_items = g_menu_model_get_n_items (G_MENU_MODEL (priv->menu));
+		g_menu_remove (priv->menu, n_items -1);
+		g_clear_object (&priv->source_menu);
+	}
+
+	priv->draws_attention = FALSE;
+	g_clear_pointer (&priv->chat_status, g_free);
+
+	g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ACTIONS]);
+	g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DRAWS_ATTENTION]);
+	g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_USES_CHAT_STATUS]);
+	g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_CHAT_STATUS]);
+
+	g_action_group_change_action_state (G_ACTION_GROUP (priv->static_shortcuts),
+					    "launch", g_variant_new_boolean (FALSE));
+}
+
+static gboolean
+action_draws_attention (GVariant *state)
+{
+	gboolean attention;
+
+	if (state && g_variant_is_of_type (state, G_VARIANT_TYPE ("(uxsb)")))
+		g_variant_get_child (state, 3, "b", &attention);
+	else
+		attention = FALSE;
+
+	return attention;
+}
+
+static gboolean
+any_action_draws_attention (GActionGroup *group,
+			    const gchar *ignored_action)
+{
+	gchar **actions;
+	gchar **it;
+	gboolean attention = FALSE;
+
+	actions = g_action_group_list_actions (group);
+
+	for (it = actions; *it && !attention; it++) {
+		GVariant *state;
+
+		if (ignored_action && g_str_equal (ignored_action, *it))
+			continue;
+
+		state = g_action_group_get_action_state (group, *it);
+		if (state) {
+			attention = action_draws_attention (state);
+			g_variant_unref (state);
+		}
+	}
+
+	g_strfreev (actions);
+	return attention;
+}
+
+static void
+action_added (GActionGroup *group,
+	      const gchar *action_name,
+	      gpointer user_data)
+{
+	AppSection *self = user_data;
+	GVariant *state;
+
+	state = g_action_group_get_action_state (group, action_name);
+	if (state) {
+		self->priv->draws_attention |= action_draws_attention (state);
+		g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DRAWS_ATTENTION]);
+		g_variant_unref (state);
+	}
+}
+
+static void
+action_state_changed (GActionGroup *group,
+		      const gchar *action_name,
+		      GVariant *value,
+		      gpointer user_data)
+{
+	AppSection *self = user_data;
+
+	self->priv->draws_attention = any_action_draws_attention (group, NULL);
+	g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DRAWS_ATTENTION]);
+}
+
+static void
+action_removed (GActionGroup *group,
+		const gchar *action_name,
+		gpointer user_data)
+{
+	AppSection *self = user_data;
+
+	self->priv->draws_attention = any_action_draws_attention (group, action_name);
+	g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DRAWS_ATTENTION]);
+}
+
+gboolean
+app_section_get_uses_chat_status (AppSection *self)
+{
+	AppSectionPrivate * priv = self->priv;
+
+	return priv->uses_chat_status;
+}
+
+const gchar *
+app_section_get_status (AppSection *self)
+{
+	AppSectionPrivate * priv = self->priv;
+
+	return priv->chat_status;
+}
+
+void
+app_section_set_status (AppSection  *self,
+			const gchar *status)
+{
+	AppSectionPrivate * priv = self->priv;
+
+	g_free (priv->chat_status);
+	priv->chat_status = g_strdup (status);
+
+	g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_CHAT_STATUS]);
 }

=== renamed file 'src/app-menu-item.h' => 'src/app-section.h'
--- src/app-menu-item.h	2010-04-16 14:52:41 +0000
+++ src/app-section.h	2013-06-07 21:39:23 +0000
@@ -2,9 +2,10 @@
 An indicator to show information that is in messaging applications
 that the user is using.
 
-Copyright 2009 Canonical Ltd.
+Copyright 2012 Canonical Ltd.
 
 Authors:
+    Lars Uebernickel <lars.uebernickel@xxxxxxxxxxxxx>
     Ted Gould <ted@xxxxxxxxxxxxx>
 
 This program is free software: you can redistribute it and/or modify it 
@@ -19,54 +20,54 @@
 You should have received a copy of the GNU General Public License along 
 with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
-#ifndef __APP_MENU_ITEM_H__
-#define __APP_MENU_ITEM_H__
-
-#include <glib.h>
-#include <glib-object.h>
-
-#include <libdbusmenu-glib/menuitem.h>
-#include <libindicate/listener.h>
+#ifndef __APP_SECTION_H__
+#define __APP_SECTION_H__
+
+#include <gio/gio.h>
+#include <gio/gdesktopappinfo.h>
 
 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))
-
-#define APP_MENU_ITEM_SIGNAL_COUNT_CHANGED     "count-changed"
-#define APP_MENU_ITEM_SIGNAL_NAME_CHANGED      "name-changed"
-#define APP_MENU_ITEM_SIGNAL_SHORTCUT_ADDED    "shortcut-added"
-#define APP_MENU_ITEM_SIGNAL_SHORTCUT_REMOVED  "shortcut-removed"
-
-typedef struct _AppMenuItem      AppMenuItem;
-typedef struct _AppMenuItemClass AppMenuItemClass;
-
-struct _AppMenuItemClass {
-	DbusmenuMenuitemClass 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;
-};
-
-GType app_menu_item_get_type (void);
-AppMenuItem * app_menu_item_new (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);
+#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;
+typedef struct _AppSectionPrivate AppSectionPrivate;
+
+
+struct _AppSectionClass {
+	GObjectClass parent_class;
+};
+
+struct _AppSection {
+	GObject parent;
+	AppSectionPrivate *priv;
+};
+
+GType app_section_get_type (void);
+AppSection * app_section_new (GDesktopAppInfo *appinfo);
+const gchar * app_section_get_desktop (AppSection * appitem);
+GActionGroup * app_section_get_actions (AppSection *self);
+GMenuModel * app_section_get_menu (AppSection *appitem);
+GAppInfo * app_section_get_app_info (AppSection *appitem);
+gboolean app_section_get_draws_attention (AppSection *appitem);
+void app_section_clear_draws_attention (AppSection *appitem);
+void app_section_set_object_path (AppSection *self,
+				  GDBusConnection *bus,
+				  const gchar *bus_name,
+				  const gchar *object_path);
+void app_section_unset_object_path (AppSection *self);
+gboolean app_section_get_uses_chat_status (AppSection *self);
+const gchar * app_section_get_status (AppSection *self);
+void app_section_set_status (AppSection *self,
+			     const gchar *status);
 
 G_END_DECLS
 
-#endif /* __APP_MENU_ITEM_H__ */
+#endif /* __APP_SECTION_H__ */
 

=== modified file 'src/dbus-data.h'
--- src/dbus-data.h	2011-01-14 20:19:48 +0000
+++ src/dbus-data.h	2013-06-07 21:39:23 +0000
@@ -8,16 +8,4 @@
 #define INDICATOR_MESSAGES_DBUS_SERVICE_OBJECT     "/com/canonical/indicator/messages/service"
 #define INDICATOR_MESSAGES_DBUS_SERVICE_INTERFACE  "com.canonical.indicator.messages.service"
 
-#define APPLICATION_MENUITEM_TYPE        "application-item"
-#define APPLICATION_MENUITEM_PROP_NAME   "label"
-#define APPLICATION_MENUITEM_PROP_ICON   "icon-name"
-#define APPLICATION_MENUITEM_PROP_RUNNING "app-running"
-
-#define INDICATOR_MENUITEM_TYPE          "indicator-item"
-#define INDICATOR_MENUITEM_PROP_LABEL    "indicator-label"
-#define INDICATOR_MENUITEM_PROP_ICON     "indicator-icon"
-#define INDICATOR_MENUITEM_PROP_RIGHT    "right-side-text"
-
-#define MAX_NUMBER_OF_INDICATORS  7
-
 #endif /* __DBUS_DATA_H__ */

=== removed file 'src/default-applications.c'
--- src/default-applications.c	2011-07-22 16:49:14 +0000
+++ src/default-applications.c	1970-01-01 00:00:00 +0000
@@ -1,116 +0,0 @@
-/*
-Looking for the default applications.  A quick lookup.
-
-Copyright 2010 Canonical Ltd.
-
-Authors:
-    Ted Gould <ted@xxxxxxxxxxxxx>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <glib.h>
-#include <glib/gi18n.h>
-#include <gio/gio.h>
-#include <gio/gdesktopappinfo.h>
-#include "default-applications.h"
-
-struct default_db_t {
-	const gchar * desktop_file;
-	const gchar * uri_scheme;
-	const gchar * name;
-	const gchar * setupname;
-	const gchar * icon;
-};
-
-struct default_db_t default_db[] = {
-	{NULL,	              "mailto",   N_("Mail"),           N_("Set Up Mail..."),              "applications-email-panel"},
-	{"empathy.desktop",   NULL,       N_("Chat"),           N_("Set Up Chat..."),              "applications-chat-panel"},
-	{"gwibber.desktop",   NULL,       N_("Broadcast"),      N_("Set Up Broadcast Account..."), "applications-microblogging-panel"},
-};
-
-static struct default_db_t *
-get_default_helper (const gchar * desktop_path)
-{
-	g_return_val_if_fail(desktop_path != NULL, NULL);
-	gchar * basename = g_path_get_basename(desktop_path);
-	g_return_val_if_fail(basename != NULL, NULL);
-
-	gboolean found = FALSE;
-	gint i;
-	gint length = G_N_ELEMENTS(default_db);
-	for (i = 0; i < length && !found; i++) {
-		if (default_db[i].desktop_file) {
-			if (g_strcmp0(default_db[i].desktop_file, basename) == 0) {
-				found = TRUE;
-			}
-		} else if (default_db[i].uri_scheme) {
-			GAppInfo *info = g_app_info_get_default_for_uri_scheme(default_db[i].uri_scheme);
-			if (!info) {
-				continue;
-			}
-
-			const gchar * filename = g_desktop_app_info_get_filename(G_DESKTOP_APP_INFO(info));
-			if (!filename) {
-				g_object_unref(info);
-				continue;
-			}
-
-			gchar * default_basename = g_path_get_basename(filename);
-			g_object_unref(info);
-			if (g_strcmp0(default_basename, basename) == 0) {
-				found = TRUE;
-			}
-
-			g_free(default_basename);
-		}
-	}
-
-	g_free(basename);
-
-	if (found) {
-		return &default_db[i - 1];
-	}
-
-	return NULL;
-}
-
-const gchar *
-get_default_name (const gchar * desktop_path)
-{
-	struct default_db_t * db = get_default_helper(desktop_path);
-
-	if (db == NULL)
-		return NULL;
-	return db->name;
-}
-
-const gchar *
-get_default_setup (const gchar * desktop_path)
-{
-	struct default_db_t * db = get_default_helper(desktop_path);
-
-	if (db == NULL)
-		return NULL;
-	return db->setupname;
-}
-
-const gchar *
-get_default_icon (const gchar * desktop_path)
-{
-	struct default_db_t * db = get_default_helper(desktop_path);
-
-	if (db == NULL)
-		return NULL;
-	return db->icon;
-}

=== removed file 'src/default-applications.h'
--- src/default-applications.h	2011-04-06 16:20:08 +0000
+++ src/default-applications.h	1970-01-01 00:00:00 +0000
@@ -1,34 +0,0 @@
-/*
-Looking for the default applications.  A quick lookup.
-
-Copyright 2010 Canonical Ltd.
-
-Authors:
-    Ted Gould <ted@xxxxxxxxxxxxx>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef DEFAULT_APPLICATIONS_H__
-#define DEFAULT_APPLICATIONS_H__ 1
-
-/* Used for override icons in the normal case, but didn't
-   have a better place to put it. */
-#define ICON_KEY  "X-Ayatana-Messaging-Menu-Icon"
-
-const gchar * get_default_name  (const gchar * desktop_path);
-const gchar * get_default_setup (const gchar * desktop_path);
-const gchar * get_default_icon  (const gchar * desktop_path);
-
-#endif /* DEFAULT_APPLICATIONS_H__ */
-

=== removed file 'src/dirs.h'
--- src/dirs.h	2009-09-23 16:06:01 +0000
+++ src/dirs.h	1970-01-01 00:00:00 +0000
@@ -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"

=== added file 'src/gactionmuxer.c'
--- src/gactionmuxer.c	1970-01-01 00:00:00 +0000
+++ src/gactionmuxer.c	2013-06-07 21:39:23 +0000
@@ -0,0 +1,485 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *     Lars Uebernickel <lars.uebernickel@xxxxxxxxxxxxx>
+ *     Ryan Lortie <desrt@xxxxxxxx>
+ */
+
+#include "gactionmuxer.h"
+
+#include <string.h>
+
+/*
+ * 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 void     g_action_muxer_disconnect_group       (GActionMuxer *muxer,
+                                                       GActionGroup *subgroup);
+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;
+  GActionGroup *subgroup;
+
+  if (muxer->global_actions)
+    {
+      g_action_muxer_disconnect_group (muxer, muxer->global_actions);
+      g_clear_object (&muxer->global_actions);
+    }
+
+  g_hash_table_iter_init (&it, muxer->groups);
+  while (g_hash_table_iter_next (&it, NULL, (gpointer *) &subgroup))
+    g_action_muxer_disconnect_group (muxer, subgroup);
+
+  g_hash_table_remove_all (muxer->groups);
+  g_hash_table_remove_all (muxer->reverse);
+}
+
+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 void
+g_action_muxer_disconnect_group (GActionMuxer *muxer,
+                                 GActionGroup *subgroup)
+{
+  gchar **actions;
+  gchar **action;
+
+  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);
+}
+
+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);
+
+  if (muxer->global_actions)
+    {
+      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;
+
+  g_return_if_fail (action_name != NULL);
+
+  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;
+
+  g_return_if_fail (action_name != NULL);
+
+  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;
+
+  g_return_val_if_fail (action_name != NULL, FALSE);
+
+  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: (allow-none): a #GActionGroup, or NULL
+ *
+ * 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
+ * <varname>x</varname> in @group, there is an equivalent action
+ * @prefix<literal>.</literal><varname>x</varname> in @muxer.
+ *
+ * For example, if @prefix is "<literal>app</literal>" and @group contains an
+ * action called "<literal>quit</literal>", then @muxer will now contain an
+ * action called "<literal>app.quit</literal>".
+ *
+ * If @prefix is <literal>NULL</literal>, the actions in @group will be added
+ * to @muxer without prefix.
+ *
+ * If @group is <literal>NULL</literal>, this function has the same effect as
+ * calling g_action_muxer_remove() with @prefix.
+ *
+ * There may only be one group per prefix (including the
+ * <literal>NULL</literal>-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;
+
+  g_return_if_fail (G_IS_ACTION_MUXER (muxer));
+
+  subgroup = prefix ? g_hash_table_lookup (muxer->groups, prefix) : muxer->global_actions;
+  if (!subgroup)
+    return;
+
+  g_action_muxer_disconnect_group (muxer, subgroup);
+
+  if (prefix)
+    {
+      g_hash_table_remove (muxer->groups, prefix);
+      g_hash_table_remove (muxer->reverse, subgroup);
+    }
+  else
+    g_clear_object (&muxer->global_actions);
+}
+

=== added file 'src/gactionmuxer.h'
--- src/gactionmuxer.h	1970-01-01 00:00:00 +0000
+++ src/gactionmuxer.h	2013-06-07 21:39:23 +0000
@@ -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 <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *     Lars Uebernickel <lars.uebernickel@xxxxxxxxxxxxx>
+ *     Ryan Lortie <desrt@xxxxxxxx>
+ */
+
+#ifndef __G_ACTION_MUXER_H__
+#define __G_ACTION_MUXER_H__
+
+#include <gio/gio.h>
+
+#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
+

=== added file 'src/gmenuutils.c'
--- src/gmenuutils.c	1970-01-01 00:00:00 +0000
+++ src/gmenuutils.c	2013-06-07 21:39:23 +0000
@@ -0,0 +1,87 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *     Lars Uebernickel <lars.uebernickel@xxxxxxxxxxxxx>
+ */
+
+#include "gmenuutils.h"
+#include "dbus-data.h"
+
+/* g_menu_find_section:
+ * @menu: a #GMenu
+ * @section: the section to be found in @menu
+ *
+ * @Returns the index of the first menu item that is linked to #section, or -1
+ * if there's no such item.
+ */
+int
+g_menu_find_section (GMenu      *menu,
+                     GMenuModel *section)
+{
+  GMenuModel *model = G_MENU_MODEL (menu);
+  int n_items;
+  int i;
+
+  g_return_val_if_fail (G_IS_MENU_MODEL (section), -1);
+
+  n_items = g_menu_model_get_n_items (model);
+  for (i = 0; i < n_items; i++)
+    {
+      GMenuModel *link;
+      gboolean found;
+
+      link = g_menu_model_get_item_link (model, i, G_MENU_LINK_SECTION);
+      found = section == link;
+
+      g_object_unref (link);
+
+      if (found)
+        return i;
+    }
+
+  return -1;
+}
+
+
+void
+g_menu_append_with_icon (GMenu *menu,
+                         const gchar *label,
+                         GIcon *icon,
+                         const gchar *detailed_action)
+{
+  gchar *iconstr;
+
+  iconstr = g_icon_to_string (icon);
+  g_menu_append_with_icon_name (menu, label, iconstr, detailed_action);
+
+  g_free (iconstr);
+}
+
+void
+g_menu_append_with_icon_name (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, "x-canonical-icon", "s", icon_name);
+
+  g_menu_append_item (menu, item);
+
+  g_object_unref (item);
+}

=== added file 'src/gmenuutils.h'
--- src/gmenuutils.h	1970-01-01 00:00:00 +0000
+++ src/gmenuutils.h	2013-06-07 21:39:23 +0000
@@ -0,0 +1,38 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *     Lars Uebernickel <lars.uebernickel@xxxxxxxxxxxxx>
+ */
+
+#ifndef __G_MENU_UTILS_H__
+#define __G_MENU_UTILS_H__
+
+#include <gio/gio.h>
+
+int     g_menu_find_section             (GMenu *menu,
+                                         GMenuModel *section);
+
+void    g_menu_append_with_icon         (GMenu *menu,
+                                         const gchar *label,
+                                         GIcon *icon,
+                                         const gchar *detailed_action);
+
+void    g_menu_append_with_icon_name    (GMenu *menu,
+                                         const gchar *label,
+                                         const gchar *icon_name,
+                                         const gchar *detailed_action);
+
+#endif

=== added file 'src/gsettingsstrv.c'
--- src/gsettingsstrv.c	1970-01-01 00:00:00 +0000
+++ src/gsettingsstrv.c	2013-06-07 21:39:23 +0000
@@ -0,0 +1,106 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *     Lars Uebernickel <lars.uebernickel@xxxxxxxxxxxxx>
+ */
+
+#include "gsettingsstrv.h"
+
+/**
+ * g_settings_strv_append_unique:
+ * @settings: a #GSettings object
+ * @key: the key at which @settings contains a string array
+ * @item: the string to append
+ *
+ * Appends @item to the string array at @key if that string array doesn't
+ * contain @item yet.
+ *
+ * Returns: TRUE if @item was added to the list, FALSE if it already existed.
+ */
+gboolean
+g_settings_strv_append_unique (GSettings   *settings,
+                               const gchar *key,
+                               const gchar *item)
+{
+  gchar **strv;
+  gchar **it;
+  gboolean add = TRUE;
+
+  g_return_val_if_fail (G_IS_SETTINGS (settings), FALSE);
+  g_return_val_if_fail (key != NULL, FALSE);
+  g_return_val_if_fail (item != NULL, FALSE);
+
+  strv = g_settings_get_strv (settings, key);
+
+  for (it = strv; *it; it++)
+    {
+      if (g_str_equal (*it, item))
+        {
+          add = FALSE;
+          break;
+        }
+    }
+
+  if (add)
+    {
+      GVariantBuilder builder;
+
+      g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
+
+      for (it = strv; *it; it++)
+        g_variant_builder_add (&builder, "s", *it);
+      g_variant_builder_add (&builder, "s", item);
+
+      g_settings_set_value (settings, key, g_variant_builder_end (&builder));
+    }
+
+  g_strfreev (strv);
+  return add;
+}
+
+/**
+ * g_settings_strv_remove:
+ * @settings: a #GSettings object
+ * @key: the key at which @settings contains a string array
+ * @item: the string to remove
+ *
+ * Removes all occurences of @item in @key.
+ */
+void
+g_settings_strv_remove (GSettings   *settings,
+                        const gchar *key,
+                        const gchar *item)
+{
+  gchar **strv;
+  gchar **it;
+  GVariantBuilder builder;
+
+  g_return_if_fail (G_IS_SETTINGS (settings));
+  g_return_if_fail (key != NULL);
+  g_return_if_fail (item != NULL);
+
+  strv = g_settings_get_strv (settings, key);
+
+  g_variant_builder_init (&builder, (GVariantType *)"as");
+  for (it = strv; *it; it++)
+    {
+      if (!g_str_equal (*it, item))
+        g_variant_builder_add (&builder, "s", *it);
+    }
+  g_settings_set_value (settings, key, g_variant_builder_end (&builder));
+
+  g_strfreev (strv);
+}

=== added file 'src/gsettingsstrv.h'
--- src/gsettingsstrv.h	1970-01-01 00:00:00 +0000
+++ src/gsettingsstrv.h	2013-06-07 21:39:23 +0000
@@ -0,0 +1,33 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *     Lars Uebernickel <lars.uebernickel@xxxxxxxxxxxxx>
+ */
+
+#ifndef __G_SETTINGS_STRV_H__
+#define __G_SETTINGS_STRV_H__
+
+#include <gio/gio.h>
+
+gboolean        g_settings_strv_append_unique   (GSettings   *settings,
+                                                 const gchar *key,
+                                                 const gchar *item);
+
+void            g_settings_strv_remove          (GSettings   *settings,
+                                                 const gchar *key,
+                                                 const gchar *item);
+
+#endif

=== added file 'src/ido-detail-label.c'
--- src/ido-detail-label.c	1970-01-01 00:00:00 +0000
+++ src/ido-detail-label.c	2013-06-07 21:39:23 +0000
@@ -0,0 +1,396 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *     Lars Uebernickel <lars.uebernickel@xxxxxxxxxxxxx>
+ */
+
+#include "ido-detail-label.h"
+
+#include <math.h>
+
+G_DEFINE_TYPE (IdoDetailLabel, ido_detail_label, GTK_TYPE_WIDGET)
+
+struct _IdoDetailLabelPrivate
+{
+  gchar *text;
+  PangoLayout *layout;
+  gboolean draw_lozenge;
+};
+
+enum
+{
+  PROP_0,
+  PROP_TEXT,
+  NUM_PROPERTIES
+};
+
+static GParamSpec *properties[NUM_PROPERTIES];
+
+static void
+ido_detail_label_get_property (GObject    *object,
+                               guint       property_id,
+                               GValue     *value,
+                               GParamSpec *pspec)
+{
+  IdoDetailLabel *self = IDO_DETAIL_LABEL (object);
+
+  switch (property_id)
+    {
+    case PROP_TEXT:
+      g_value_set_string (value, self->priv->text);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+static void
+ido_detail_label_set_property (GObject      *object,
+                               guint         property_id,
+                               const GValue *value,
+                               GParamSpec   *pspec)
+{
+  IdoDetailLabel *self = IDO_DETAIL_LABEL (object);
+
+  switch (property_id)
+    {
+    case PROP_TEXT:
+      ido_detail_label_set_text (self, g_value_get_string (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+
+static void
+ido_detail_label_finalize (GObject *object)
+{
+  IdoDetailLabelPrivate *priv = IDO_DETAIL_LABEL (object)->priv;
+
+  g_free (priv->text);
+
+  G_OBJECT_CLASS (ido_detail_label_parent_class)->finalize (object);
+}
+
+static void
+ido_detail_label_dispose (GObject *object)
+{
+  IdoDetailLabelPrivate *priv = IDO_DETAIL_LABEL (object)->priv;
+
+  g_clear_object (&priv->layout);
+
+  G_OBJECT_CLASS (ido_detail_label_parent_class)->dispose (object);
+}
+
+static void
+ido_detail_label_ensure_layout (IdoDetailLabel *label)
+{
+  IdoDetailLabelPrivate *priv = label->priv;
+
+  if (priv->layout == NULL)
+    {
+      priv->layout = gtk_widget_create_pango_layout (GTK_WIDGET (label), priv->text);
+      pango_layout_set_alignment (priv->layout, PANGO_ALIGN_CENTER);
+      pango_layout_set_ellipsize (priv->layout, PANGO_ELLIPSIZE_END);
+      pango_layout_set_height (priv->layout, -1);
+
+      // TODO update layout on "style-updated" and "direction-changed"
+    }
+}
+
+static void
+cairo_lozenge (cairo_t *cr,
+               double   x,
+               double   y,
+               double   w,
+               double   h,
+               double   radius)
+{
+  double x1 = x + w - radius;
+  double x2 = x + radius;
+  double y1 = y + radius;
+  double y2 = y + h - radius;
+
+  cairo_move_to (cr, x + radius, y);
+  cairo_arc (cr, x1, y1, radius, G_PI * 1.5, G_PI * 2);
+  cairo_arc (cr, x1, y2, radius, 0,          G_PI * 0.5);
+  cairo_arc (cr, x2, y2, radius, G_PI * 0.5, G_PI);
+  cairo_arc (cr, x2, y1, radius, G_PI,       G_PI * 1.5);
+}
+
+static PangoFontMetrics *
+gtk_widget_get_font_metrics (GtkWidget    *widget,
+                             PangoContext *context)
+{
+  const PangoFontDescription *font;
+
+  font = gtk_style_context_get_font (gtk_widget_get_style_context (widget),
+                                     gtk_widget_get_state_flags (widget));
+
+  return pango_context_get_metrics (context,
+                                    font,
+                                    pango_context_get_language (context));
+}
+
+static gint
+ido_detail_label_get_minimum_text_width (IdoDetailLabel *label)
+{
+  IdoDetailLabelPrivate *priv = label->priv;
+  PangoContext *context;
+  PangoFontMetrics *metrics;
+  gint char_width;
+  gint w;
+
+  context = pango_layout_get_context (priv->layout);
+  metrics = gtk_widget_get_font_metrics (GTK_WIDGET (label), context);
+  char_width = pango_font_metrics_get_approximate_digit_width (metrics);
+
+  w = 2 * char_width / PANGO_SCALE;
+  pango_font_metrics_unref (metrics);
+  return w;
+}
+
+static gboolean
+ido_detail_label_draw (GtkWidget *widget,
+                       cairo_t   *cr)
+{
+  IdoDetailLabel *label = IDO_DETAIL_LABEL (widget);
+  IdoDetailLabelPrivate *priv = IDO_DETAIL_LABEL (widget)->priv;
+  PangoRectangle extents;
+  GtkAllocation allocation;
+  double x, w, h, radius;
+  GdkRGBA color;
+
+  if (!priv->text || !*priv->text)
+    return TRUE;
+
+  gtk_widget_get_allocation (widget, &allocation);
+
+  ido_detail_label_ensure_layout (IDO_DETAIL_LABEL (widget));
+
+  pango_layout_get_extents (priv->layout, NULL, &extents);
+  pango_extents_to_pixels (&extents, NULL);
+
+  h = MIN (allocation.height, extents.height);
+  radius = floor (h / 2.0);
+  w = MAX (ido_detail_label_get_minimum_text_width (label), extents.width) + 2.0 * radius;
+  x = allocation.width - w;
+
+  pango_layout_set_width (priv->layout, (allocation.width - 2 * radius) * PANGO_SCALE);
+  pango_layout_get_extents (priv->layout, NULL, &extents);
+  pango_extents_to_pixels (&extents, NULL);
+
+  gtk_style_context_get_color (gtk_widget_get_style_context (widget),
+                               gtk_widget_get_state_flags (widget),
+                               &color);
+  gdk_cairo_set_source_rgba (cr, &color);
+
+  cairo_set_line_width (cr, 1.0);
+  cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
+
+  if (priv->draw_lozenge)
+    cairo_lozenge (cr, x, 0.0, w, h, radius);
+
+  cairo_move_to (cr, x + radius, (allocation.height - extents.height) / 2.0);
+  pango_cairo_layout_path (cr, priv->layout);
+  cairo_fill (cr);
+
+  return TRUE;
+}
+
+static void
+ido_detail_label_get_preferred_width (GtkWidget *widget,
+                                      gint      *minimum,
+                                      gint      *natural)
+{
+  IdoDetailLabelPrivate *priv = IDO_DETAIL_LABEL (widget)->priv;
+  PangoRectangle extents;
+  double radius;
+
+  ido_detail_label_ensure_layout (IDO_DETAIL_LABEL (widget));
+
+  pango_layout_get_extents (priv->layout, NULL, &extents);
+  pango_extents_to_pixels (&extents, NULL);
+
+  radius = floor (extents.height / 2.0);
+
+  *minimum = ido_detail_label_get_minimum_text_width (IDO_DETAIL_LABEL (widget)) + 2.0 * radius;
+  *natural = MAX (*minimum, extents.width + 2.0 * radius);
+}
+
+static void
+ido_detail_label_get_preferred_height (GtkWidget *widget,
+                                       gint      *minimum,
+                                       gint      *natural)
+{
+  IdoDetailLabelPrivate *priv = IDO_DETAIL_LABEL (widget)->priv;
+  PangoContext *context;
+  PangoFontMetrics *metrics;
+  PangoRectangle extents;
+
+  ido_detail_label_ensure_layout (IDO_DETAIL_LABEL (widget));
+
+  pango_layout_get_extents (priv->layout, NULL, &extents);
+  pango_extents_to_pixels (&extents, NULL);
+  context = pango_layout_get_context (priv->layout);
+  metrics = gtk_widget_get_font_metrics (widget, context);
+
+  *minimum = *natural = (pango_font_metrics_get_ascent (metrics) +
+                         pango_font_metrics_get_descent (metrics)) / PANGO_SCALE;
+
+  pango_font_metrics_unref (metrics);
+}
+
+static void
+ido_detail_label_class_init (IdoDetailLabelClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->get_property = ido_detail_label_get_property;
+  object_class->set_property = ido_detail_label_set_property;
+  object_class->finalize = ido_detail_label_finalize;
+  object_class->dispose = ido_detail_label_dispose;
+
+  widget_class->draw = ido_detail_label_draw;
+  widget_class->get_preferred_width = ido_detail_label_get_preferred_width;
+  widget_class->get_preferred_height = ido_detail_label_get_preferred_height;
+
+  g_type_class_add_private (klass, sizeof (IdoDetailLabelPrivate));
+
+  properties[PROP_TEXT] = g_param_spec_string ("text",
+                                               "Text",
+                                               "The text of the label",
+                                               NULL,
+                                               G_PARAM_READWRITE |
+                                               G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
+}
+
+static void
+ido_detail_label_init (IdoDetailLabel *self)
+{
+  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+                                            IDO_TYPE_DETAIL_LABEL,
+                                            IdoDetailLabelPrivate);
+
+  gtk_widget_set_has_window (GTK_WIDGET (self), FALSE);
+}
+
+GtkWidget *
+ido_detail_label_new (const gchar *label)
+{
+  return g_object_new (IDO_TYPE_DETAIL_LABEL,
+                       "text", label,
+                       NULL);
+}
+
+const gchar *
+ido_detail_label_get_text (IdoDetailLabel *label)
+{
+  g_return_val_if_fail (IDO_IS_DETAIL_LABEL (label), NULL);
+  return label->priv->text;
+}
+
+/* collapse_whitespace:
+ * @str: the source string
+ *
+ * Collapses all occurences of consecutive whitespace charactes in @str
+ * into a single space.
+ *
+ * Returns: (transfer full): a newly-allocated string
+ */
+static gchar *
+collapse_whitespace (const gchar *str)
+{
+  GString *result;
+  gboolean in_space = FALSE;
+
+  if (str == NULL)
+    return NULL;
+
+  result = g_string_new ("");
+
+  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);
+}
+
+static void
+ido_detail_label_set_text_impl (IdoDetailLabel *label,
+                                const gchar    *text,
+                                gboolean        draw_lozenge)
+{
+  IdoDetailLabelPrivate * priv = label->priv;
+
+  g_clear_object (&priv->layout);
+  g_free (priv->text);
+
+  priv->text = g_strdup (text);
+  priv->draw_lozenge = draw_lozenge;
+
+  g_object_notify_by_pspec (G_OBJECT (label), properties[PROP_TEXT]);
+  gtk_widget_queue_resize (GTK_WIDGET (label));
+}
+
+void
+ido_detail_label_set_text (IdoDetailLabel *label,
+                           const gchar    *text)
+{
+  gchar *str;
+
+  g_return_if_fail (IDO_IS_DETAIL_LABEL (label));
+
+  str = collapse_whitespace (text);
+  ido_detail_label_set_text_impl (label, str, FALSE);
+  g_free (str);
+}
+
+void
+ido_detail_label_set_count (IdoDetailLabel *label,
+                            gint            count)
+{
+  gchar *text;
+
+  g_return_if_fail (IDO_IS_DETAIL_LABEL (label));
+
+  text = g_strdup_printf ("%d", count);
+  ido_detail_label_set_text_impl (label, text, TRUE);
+  g_free (text);
+}

=== added file 'src/ido-detail-label.h'
--- src/ido-detail-label.h	1970-01-01 00:00:00 +0000
+++ src/ido-detail-label.h	2013-06-07 21:39:23 +0000
@@ -0,0 +1,59 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *     Lars Uebernickel <lars.uebernickel@xxxxxxxxxxxxx>
+ */
+
+#ifndef __IDO_DETAIL_LABEL_H__
+#define __IDO_DETAIL_LABEL_H__
+
+#include <gtk/gtk.h>
+
+#define IDO_TYPE_DETAIL_LABEL            (ido_detail_label_get_type())
+#define IDO_DETAIL_LABEL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), IDO_TYPE_DETAIL_LABEL, IdoDetailLabel))
+#define IDO_DETAIL_LABEL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), IDO_TYPE_DETAIL_LABEL, IdoDetailLabelClass))
+#define IDO_IS_DETAIL_LABEL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IDO_TYPE_DETAIL_LABEL))
+#define IDO_IS_DETAIL_LABEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), IDO_TYPE_DETAIL_LABEL))
+#define IDO_DETAIL_LABEL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), IDO_TYPE_DETAIL_LABEL, IdoDetailLabelClass))
+
+typedef struct _IdoDetailLabel        IdoDetailLabel;
+typedef struct _IdoDetailLabelClass   IdoDetailLabelClass;
+typedef struct _IdoDetailLabelPrivate IdoDetailLabelPrivate;
+
+struct _IdoDetailLabel
+{
+  GtkWidget parent;
+  IdoDetailLabelPrivate *priv;
+};
+
+struct _IdoDetailLabelClass
+{
+  GtkWidgetClass parent_class;
+};
+
+GType         ido_detail_label_get_type  (void) G_GNUC_CONST;
+
+GtkWidget *   ido_detail_label_new       (const gchar *str);
+
+const gchar * ido_detail_label_get_text  (IdoDetailLabel *label);
+
+void          ido_detail_label_set_text  (IdoDetailLabel *label,
+                                          const gchar    *text);
+
+void          ido_detail_label_set_count (IdoDetailLabel *label,
+                                          gint            count);
+
+#endif

=== added file 'src/ido-menu-item.c'
--- src/ido-menu-item.c	1970-01-01 00:00:00 +0000
+++ src/ido-menu-item.c	2013-06-07 21:39:23 +0000
@@ -0,0 +1,425 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *     Lars Uebernickel <lars.uebernickel@xxxxxxxxxxxxx>
+ */
+
+#include "ido-menu-item.h"
+
+struct _IdoMenuItemPrivate
+{
+  GActionGroup *action_group;
+  gchar *action;
+  GVariant *target;
+
+  GtkWidget *icon;
+  GtkWidget *label;
+
+  gboolean has_indicator;
+  gboolean in_set_active;
+};
+
+enum
+{
+  PROP_0,
+  PROP_MENU_ITEM,
+  PROP_ACTION_GROUP,
+  NUM_PROPERTIES
+};
+
+static GParamSpec *properties[NUM_PROPERTIES];
+
+G_DEFINE_TYPE (IdoMenuItem, ido_menu_item, GTK_TYPE_CHECK_MENU_ITEM);
+
+static void
+ido_menu_item_constructed (GObject *object)
+{
+  IdoMenuItemPrivate *priv = IDO_MENU_ITEM (object)->priv;
+  GtkWidget *grid;
+
+  priv->icon = g_object_ref (gtk_image_new ());
+  gtk_widget_set_margin_right (priv->icon, 6);
+
+  priv->label = g_object_ref (gtk_label_new (""));
+
+  grid = gtk_grid_new ();
+  gtk_grid_attach (GTK_GRID (grid), priv->icon, 0, 0, 1, 1);
+  gtk_grid_attach (GTK_GRID (grid), priv->label, 1, 0, 1, 1);
+
+  gtk_container_add (GTK_CONTAINER (object), grid);
+  gtk_widget_show_all (grid);
+
+  G_OBJECT_CLASS (ido_menu_item_parent_class)->constructed (object);
+}
+
+static void
+ido_menu_item_set_active (IdoMenuItem *self,
+                          gboolean     active)
+{
+  /* HACK gtk_check_menu_item_set_active calls gtk_menu_item_activate.
+   * Make sure our activate handler doesn't toggle the action as a
+   * result of calling this function. */
+
+  self->priv->in_set_active = TRUE;
+  gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (self), active);
+  self->priv->in_set_active = FALSE;
+}
+
+static void
+ido_menu_item_set_has_indicator (IdoMenuItem *self,
+                                 gboolean     has_indicator)
+{
+  if (has_indicator == self->priv->has_indicator)
+    return;
+
+  self->priv->has_indicator = has_indicator;
+
+  gtk_widget_queue_resize (GTK_WIDGET (self));
+}
+
+static void
+ido_menu_item_set_state (IdoMenuItem *self,
+                         GVariant    *state)
+{
+  IdoMenuItemPrivate *priv = self->priv;
+
+  if (priv->target)
+    {
+      ido_menu_item_set_has_indicator (self, TRUE);
+      ido_menu_item_set_active (self, FALSE);
+      gtk_check_menu_item_set_draw_as_radio (GTK_CHECK_MENU_ITEM (self), TRUE);
+      gtk_check_menu_item_set_inconsistent (GTK_CHECK_MENU_ITEM (self), FALSE);
+
+      if (g_variant_is_of_type (state, G_VARIANT_TYPE_STRING))
+        {
+          ido_menu_item_set_active (self, g_variant_equal (priv->target, state));
+        }
+      else if (g_variant_is_of_type (state, G_VARIANT_TYPE ("as")) &&
+               g_variant_is_of_type (priv->target, G_VARIANT_TYPE_STRING))
+        {
+          const gchar *target_str;
+          const gchar **state_strs;
+          const gchar **it;
+
+          target_str = g_variant_get_string (priv->target, NULL);
+          state_strs = g_variant_get_strv (state, NULL);
+
+          it = state_strs;
+          while (*it != NULL && !g_str_equal (*it, target_str))
+            it++;
+
+          if (*it != NULL)
+            {
+              ido_menu_item_set_active (self, TRUE);
+              gtk_check_menu_item_set_inconsistent (GTK_CHECK_MENU_ITEM (self),
+                                                    g_strv_length ((gchar **)state_strs) > 1);
+            }
+
+          g_free (state_strs);
+        }
+    }
+  else if (g_variant_is_of_type (state, G_VARIANT_TYPE_BOOLEAN))
+    {
+      ido_menu_item_set_has_indicator (self, TRUE);
+      gtk_check_menu_item_set_draw_as_radio (GTK_CHECK_MENU_ITEM (self), FALSE);
+      ido_menu_item_set_active (self, g_variant_get_boolean (state));
+    }
+  else
+    {
+      ido_menu_item_set_has_indicator (self, FALSE);
+    }
+}
+
+static void
+ido_menu_item_set_action_name (IdoMenuItem *self,
+                               const gchar *action_name)
+{
+  IdoMenuItemPrivate *priv = self->priv;
+  gboolean enabled = FALSE;
+  GVariant *state;
+  const GVariantType *param_type;
+
+  if (priv->action != NULL)
+    g_free (priv->action);
+
+  priv->action = g_strdup (action_name);
+
+  if (priv->action_group != NULL && priv->action != NULL &&
+      g_action_group_query_action (priv->action_group, priv->action,
+                                   &enabled, &param_type, NULL, NULL, &state))
+    {
+      gtk_widget_set_sensitive (GTK_WIDGET (self), enabled);
+
+      if (state)
+        {
+          ido_menu_item_set_state (self, state);
+          g_variant_unref (state);
+        }
+    }
+  else
+    {
+      ido_menu_item_set_active (self, FALSE);
+      gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
+      ido_menu_item_set_has_indicator (self, FALSE);
+    }
+}
+
+static void
+ido_menu_item_action_added (GActionGroup *action_group,
+                            gchar        *action_name,
+                            gpointer      user_data)
+{
+  IdoMenuItem *self = user_data;
+
+  if (g_strcmp0 (self->priv->action, action_name) == 0)
+    ido_menu_item_set_action_name (self, action_name);
+}
+
+static void
+ido_menu_item_action_removed (GActionGroup *action_group,
+                              gchar        *action_name,
+                              gpointer      user_data)
+{
+  IdoMenuItem *self = user_data;
+
+  if (g_strcmp0 (self->priv->action, action_name) == 0)
+    {
+      gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
+    }
+}
+
+static void
+ido_menu_item_action_enabled_changed (GActionGroup *action_group,
+                                      gchar        *action_name,
+                                      gboolean      enabled,
+                                      gpointer      user_data)
+{
+  IdoMenuItem *self = user_data;
+
+  if (g_strcmp0 (self->priv->action, action_name) == 0)
+    gtk_widget_set_sensitive (GTK_WIDGET (self), enabled);
+}
+
+static void
+ido_menu_item_action_state_changed (GActionGroup *action_group,
+                                    gchar        *action_name,
+                                    GVariant     *value,
+                                    gpointer      user_data)
+{
+  IdoMenuItem *self = user_data;
+
+  if (g_strcmp0 (self->priv->action, action_name) == 0)
+    ido_menu_item_set_state (self, value);
+}
+
+static void
+ido_menu_set_property (GObject      *object,
+                       guint         property_id,
+                       const GValue *value,
+                       GParamSpec   *pspec)
+{
+  IdoMenuItem *self = IDO_MENU_ITEM (object);
+
+  switch (property_id)
+    {
+    case PROP_MENU_ITEM:
+      ido_menu_item_set_menu_item (self, G_MENU_ITEM (g_value_get_object (value)));
+      break;
+
+    case PROP_ACTION_GROUP:
+      ido_menu_item_set_action_group (self, G_ACTION_GROUP (g_value_get_object (value)));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+static void
+ido_menu_item_dispose (GObject *object)
+{
+  IdoMenuItem *self = IDO_MENU_ITEM (object);
+
+  if (self->priv->action_group)
+      ido_menu_item_set_action_group (self, NULL);
+
+  g_clear_object (&self->priv->icon);
+  g_clear_object (&self->priv->label);
+
+  if (self->priv->target)
+    {
+      g_variant_unref (self->priv->target);
+      self->priv->target = NULL;
+    }
+
+  G_OBJECT_CLASS (ido_menu_item_parent_class)->dispose (object);
+}
+
+static void
+ido_menu_item_finalize (GObject *object)
+{
+  IdoMenuItemPrivate *priv = IDO_MENU_ITEM (object)->priv;
+
+  g_free (priv->action);
+
+  G_OBJECT_CLASS (ido_menu_item_parent_class)->finalize (object);
+}
+
+static void
+ido_menu_item_activate (GtkMenuItem *item)
+{
+  IdoMenuItemPrivate *priv = IDO_MENU_ITEM (item)->priv;
+
+  /* see ido_menu_item_set_active */
+  if (!priv->in_set_active && priv->action && priv->action_group)
+    g_action_group_activate_action (priv->action_group, priv->action, priv->target);
+
+  if (priv->in_set_active)
+    GTK_MENU_ITEM_CLASS (ido_menu_item_parent_class)->activate (item);
+}
+
+static void
+ido_menu_item_draw_indicator (GtkCheckMenuItem *item,
+                              cairo_t          *cr)
+{
+  IdoMenuItem *self = IDO_MENU_ITEM (item);
+
+  if (self->priv->has_indicator)
+    GTK_CHECK_MENU_ITEM_CLASS (ido_menu_item_parent_class)
+      ->draw_indicator (item, cr);
+}
+
+static void
+ido_menu_item_class_init (IdoMenuItemClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkMenuItemClass *menu_item_class = GTK_MENU_ITEM_CLASS (klass);
+  GtkCheckMenuItemClass *check_class = GTK_CHECK_MENU_ITEM_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (IdoMenuItemPrivate));
+
+  object_class->constructed = ido_menu_item_constructed;
+  object_class->set_property = ido_menu_set_property;
+  object_class->dispose = ido_menu_item_dispose;
+  object_class->finalize = ido_menu_item_finalize;
+
+  menu_item_class->activate = ido_menu_item_activate;
+
+  check_class->draw_indicator = ido_menu_item_draw_indicator;
+
+  properties[PROP_MENU_ITEM] = g_param_spec_object ("menu-item",
+                                                    "Menu item",
+                                                    "The model GMenuItem for this menu item",
+                                                    G_TYPE_MENU_ITEM,
+                                                    G_PARAM_WRITABLE |
+                                                    G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_ACTION_GROUP] = g_param_spec_object ("action-group",
+                                                       "Action group",
+                                                       "The action group associated with this menu item",
+                                                       G_TYPE_ACTION_GROUP,
+                                                       G_PARAM_WRITABLE |
+                                                       G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
+}
+
+static void
+ido_menu_item_init (IdoMenuItem *self)
+{
+  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+                                            IDO_TYPE_MENU_ITEM,
+                                            IdoMenuItemPrivate);
+}
+
+void
+ido_menu_item_set_menu_item (IdoMenuItem *self,
+                             GMenuItem   *menuitem)
+{
+  gchar *iconstr = NULL;
+  GIcon *icon = NULL;
+  gchar *label = NULL;
+  gchar *action = NULL;
+
+  if (g_menu_item_get_attribute (menuitem, "x-canonical-icon", "s", &iconstr))
+    {
+      GError *error;
+
+      /* only indent the label if icon is set to "" */
+      if (iconstr[0] == '\0')
+        {
+          gint width;
+
+          gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &width, NULL);
+          gtk_widget_set_size_request (self->priv->icon, width, -1);
+        }
+      else
+        {
+          icon = g_icon_new_for_string (iconstr, &error);
+          if (icon == NULL)
+            {
+              g_warning ("unable to set icon: %s", error->message);
+              g_error_free (error);
+            }
+        }
+      g_free (iconstr);
+    }
+  gtk_image_set_from_gicon (GTK_IMAGE (self->priv->icon), icon, GTK_ICON_SIZE_MENU);
+
+  g_menu_item_get_attribute (menuitem, "label", "s", &label);
+  gtk_label_set_label (GTK_LABEL (self->priv->label), label ? label : "");
+
+  self->priv->target = g_menu_item_get_attribute_value (menuitem, "target", NULL);
+
+  g_menu_item_get_attribute (menuitem, "action", "s", &action);
+  ido_menu_item_set_action_name (self, action);
+
+  if (icon)
+    g_object_unref (icon);
+  g_free (label);
+  g_free (action);
+}
+
+void
+ido_menu_item_set_action_group (IdoMenuItem  *self,
+                                GActionGroup *action_group)
+{
+  IdoMenuItemPrivate *priv = self->priv;
+
+  if (priv->action_group != NULL)
+    {
+      g_signal_handlers_disconnect_by_func (priv->action_group, ido_menu_item_action_added, self);
+      g_signal_handlers_disconnect_by_func (priv->action_group, ido_menu_item_action_removed, self);
+      g_signal_handlers_disconnect_by_func (priv->action_group, ido_menu_item_action_enabled_changed, self);
+      g_signal_handlers_disconnect_by_func (priv->action_group, ido_menu_item_action_state_changed, self);
+
+      g_clear_object (&priv->action_group);
+    }
+
+  if (action_group != NULL)
+    {
+      priv->action_group = g_object_ref (action_group);
+
+      g_signal_connect (priv->action_group, "action-added",
+                        G_CALLBACK (ido_menu_item_action_added), self);
+      g_signal_connect (priv->action_group, "action-removed",
+                        G_CALLBACK (ido_menu_item_action_removed), self);
+      g_signal_connect (priv->action_group, "action-enabled-changed",
+                        G_CALLBACK (ido_menu_item_action_enabled_changed), self);
+      g_signal_connect (priv->action_group, "action-state-changed",
+                        G_CALLBACK (ido_menu_item_action_state_changed), self);
+    }
+}

=== added file 'src/ido-menu-item.h'
--- src/ido-menu-item.h	1970-01-01 00:00:00 +0000
+++ src/ido-menu-item.h	2013-06-07 21:39:23 +0000
@@ -0,0 +1,54 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *     Lars Uebernickel <lars.uebernickel@xxxxxxxxxxxxx>
+ */
+
+#ifndef __IDO_MENU_ITEM_H__
+#define __IDO_MENU_ITEM_H__
+
+#include <gtk/gtk.h>
+
+#define IDO_TYPE_MENU_ITEM            (ido_menu_item_get_type ())
+#define IDO_MENU_ITEM(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), IDO_TYPE_MENU_ITEM, IdoMenuItem))
+#define IDO_MENU_ITEM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), IDO_TYPE_MENU_ITEM, IdoMenuItemClass))
+#define IS_IDO_MENU_ITEM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IDO_TYPE_MENU_ITEM))
+#define IS_IDO_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), IDO_TYPE_MENU_ITEM))
+#define IDO_MENU_ITEM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), IDO_TYPE_MENU_ITEM, IdoMenuItemClass))
+
+typedef struct _IdoMenuItem        IdoMenuItem;
+typedef struct _IdoMenuItemClass   IdoMenuItemClass;
+typedef struct _IdoMenuItemPrivate IdoMenuItemPrivate;
+
+struct _IdoMenuItemClass
+{
+  GtkCheckMenuItemClass parent_class;
+};
+
+struct _IdoMenuItem
+{
+  GtkCheckMenuItem parent;
+  IdoMenuItemPrivate *priv;
+};
+
+GType           ido_menu_item_get_type           (void);
+
+void            ido_menu_item_set_menu_item      (IdoMenuItem *item,
+                                                  GMenuItem   *menuitem);
+void            ido_menu_item_set_action_group   (IdoMenuItem  *self,
+                                                  GActionGroup *action_group);
+
+#endif

=== added file 'src/im-app-menu-item.c'
--- src/im-app-menu-item.c	1970-01-01 00:00:00 +0000
+++ src/im-app-menu-item.c	2013-06-07 21:39:23 +0000
@@ -0,0 +1,351 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *     Lars Uebernickel <lars.uebernickel@xxxxxxxxxxxxx>
+ */
+
+#include "im-app-menu-item.h"
+
+struct _ImAppMenuItemPrivate
+{
+  GActionGroup *action_group;
+  gchar *action;
+  gboolean is_running;
+
+  GtkWidget *icon;
+  GtkWidget *label;
+};
+
+enum
+{
+  PROP_0,
+  PROP_MENU_ITEM,
+  PROP_ACTION_GROUP,
+  NUM_PROPERTIES
+};
+
+static GParamSpec *properties[NUM_PROPERTIES];
+
+G_DEFINE_TYPE (ImAppMenuItem, im_app_menu_item, GTK_TYPE_MENU_ITEM);
+
+static void
+im_app_menu_item_constructed (GObject *object)
+{
+  ImAppMenuItemPrivate *priv = IM_APP_MENU_ITEM (object)->priv;
+  GtkWidget *grid;
+
+  priv->icon = g_object_ref (gtk_image_new ());
+  gtk_widget_set_margin_right (priv->icon, 6);
+
+  priv->label = g_object_ref (gtk_label_new (""));
+
+  grid = gtk_grid_new ();
+  gtk_grid_attach (GTK_GRID (grid), priv->icon, 0, 0, 1, 1);
+  gtk_grid_attach (GTK_GRID (grid), priv->label, 1, 0, 1, 1);
+
+  gtk_container_add (GTK_CONTAINER (object), grid);
+  gtk_widget_show_all (grid);
+
+  G_OBJECT_CLASS (im_app_menu_item_parent_class)->constructed (object);
+}
+
+static void
+im_app_menu_item_set_action_name (ImAppMenuItem *self,
+                                  const gchar   *action_name)
+{
+  ImAppMenuItemPrivate *priv = self->priv;
+  gboolean enabled = FALSE;
+  GVariant *state;
+
+  if (priv->action != NULL)
+    g_free (priv->action);
+
+  priv->action = g_strdup (action_name);
+
+  priv->is_running = FALSE;
+
+  if (priv->action_group != NULL && priv->action != NULL &&
+      g_action_group_query_action (priv->action_group, priv->action,
+                                   &enabled, NULL, NULL, NULL, &state))
+    {
+      if (state && g_variant_is_of_type (state, G_VARIANT_TYPE ("b")))
+        priv->is_running = g_variant_get_boolean (state);
+      else
+        enabled = FALSE;
+
+      if (state)
+        g_variant_unref (state);
+    }
+
+  gtk_widget_set_sensitive (GTK_WIDGET (self), enabled);
+  gtk_widget_queue_draw (GTK_WIDGET (self));
+}
+
+static void
+im_app_menu_item_action_added (GActionGroup *action_group,
+                               gchar        *action_name,
+                               gpointer      user_data)
+{
+  ImAppMenuItem *self = user_data;
+
+  if (g_strcmp0 (self->priv->action, action_name) == 0)
+    im_app_menu_item_set_action_name (self, action_name);
+}
+
+static void
+im_app_menu_item_action_removed (GActionGroup *action_group,
+                                 gchar        *action_name,
+                                 gpointer      user_data)
+{
+  ImAppMenuItem *self = user_data;
+
+  if (g_strcmp0 (self->priv->action, action_name) == 0)
+    {
+      gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
+      self->priv->is_running = FALSE;
+      gtk_widget_queue_draw (GTK_WIDGET (self));
+    }
+}
+
+static void
+im_app_menu_item_action_enabled_changed (GActionGroup *action_group,
+                                         gchar        *action_name,
+                                         gboolean      enabled,
+                                         gpointer      user_data)
+{
+  ImAppMenuItem *self = user_data;
+
+  if (g_strcmp0 (self->priv->action, action_name) == 0)
+    gtk_widget_set_sensitive (GTK_WIDGET (self), enabled);
+}
+
+static void
+im_app_menu_item_action_state_changed (GActionGroup *action_group,
+                                       gchar        *action_name,
+                                       GVariant     *value,
+                                       gpointer      user_data)
+{
+  ImAppMenuItem *self = user_data;
+
+  if (g_strcmp0 (self->priv->action, action_name) == 0)
+    {
+      g_return_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("b")));
+
+      self->priv->is_running = g_variant_get_boolean (value);
+      gtk_widget_queue_draw (GTK_WIDGET (self));
+    }
+}
+
+static void
+im_app_menu_set_property (GObject      *object,
+                          guint         property_id,
+                          const GValue *value,
+                          GParamSpec   *pspec)
+{
+  ImAppMenuItem *self = IM_APP_MENU_ITEM (object);
+
+  switch (property_id)
+    {
+    case PROP_MENU_ITEM:
+      im_app_menu_item_set_menu_item (self, G_MENU_ITEM (g_value_get_object (value)));
+      break;
+
+    case PROP_ACTION_GROUP:
+      im_app_menu_item_set_action_group (self, G_ACTION_GROUP (g_value_get_object (value)));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+static void
+im_app_menu_item_dispose (GObject *object)
+{
+  ImAppMenuItem *self = IM_APP_MENU_ITEM (object);
+
+  if (self->priv->action_group)
+      im_app_menu_item_set_action_group (self, NULL);
+
+  g_clear_object (&self->priv->icon);
+  g_clear_object (&self->priv->label);
+
+  G_OBJECT_CLASS (im_app_menu_item_parent_class)->dispose (object);
+}
+
+static void
+im_app_menu_item_finalize (GObject *object)
+{
+  ImAppMenuItemPrivate *priv = IM_APP_MENU_ITEM (object)->priv;
+
+  g_free (priv->action);
+
+  G_OBJECT_CLASS (im_app_menu_item_parent_class)->finalize (object);
+}
+
+static gboolean
+im_app_menu_item_draw (GtkWidget *widget,
+                       cairo_t   *cr)
+{
+  ImAppMenuItemPrivate *priv = IM_APP_MENU_ITEM (widget)->priv;
+
+  GTK_WIDGET_CLASS (im_app_menu_item_parent_class)->draw (widget, cr);
+
+  if (priv->is_running)
+    {
+      const int arrow_width = 5;
+      const double half_arrow_height = 4.5;
+      GtkAllocation alloc;
+      GdkRGBA color;
+      double center;
+
+      gtk_widget_get_allocation (widget, &alloc);
+
+      gtk_style_context_get_color (gtk_widget_get_style_context (widget),
+                                   gtk_widget_get_state_flags (widget),
+                                   &color);
+      gdk_cairo_set_source_rgba (cr, &color);
+
+      center = alloc.height / 2 + 0.5;
+
+      cairo_move_to (cr, 0, center - half_arrow_height);
+      cairo_line_to (cr, 0, center + half_arrow_height);
+      cairo_line_to (cr, arrow_width, center);
+      cairo_close_path (cr);
+
+      cairo_fill (cr);
+    }
+
+  return FALSE;
+}
+
+static void
+im_app_menu_item_activate (GtkMenuItem *item)
+{
+  ImAppMenuItemPrivate *priv = IM_APP_MENU_ITEM (item)->priv;
+
+  if (priv->action && priv->action_group)
+    g_action_group_activate_action (priv->action_group, priv->action, NULL);
+}
+
+static void
+im_app_menu_item_class_init (ImAppMenuItemClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+  GtkMenuItemClass *menu_item_class = GTK_MENU_ITEM_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (ImAppMenuItemPrivate));
+
+  object_class->constructed = im_app_menu_item_constructed;
+  object_class->set_property = im_app_menu_set_property;
+  object_class->dispose = im_app_menu_item_dispose;
+  object_class->finalize = im_app_menu_item_finalize;
+
+  widget_class->draw = im_app_menu_item_draw;
+
+  menu_item_class->activate = im_app_menu_item_activate;
+
+  properties[PROP_MENU_ITEM] = g_param_spec_object ("menu-item",
+                                                    "Menu item",
+                                                    "The model GMenuItem for this menu item",
+                                                    G_TYPE_MENU_ITEM,
+                                                    G_PARAM_WRITABLE |
+                                                    G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_ACTION_GROUP] = g_param_spec_object ("action-group",
+                                                       "Action group",
+                                                       "The action group associated with this menu item",
+                                                       G_TYPE_ACTION_GROUP,
+                                                       G_PARAM_WRITABLE |
+                                                       G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
+}
+
+static void
+im_app_menu_item_init (ImAppMenuItem *self)
+{
+  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+                                            IM_TYPE_APP_MENU_ITEM,
+                                            ImAppMenuItemPrivate);
+}
+
+void
+im_app_menu_item_set_menu_item (ImAppMenuItem *self,
+                                GMenuItem     *menuitem)
+{
+  gchar *iconstr = NULL;
+  GIcon *icon = NULL;
+  gchar *label;
+  gchar *action = NULL;
+
+  if (g_menu_item_get_attribute (menuitem, "x-canonical-icon", "s", &iconstr))
+    {
+      GError *error;
+
+      icon = g_icon_new_for_string (iconstr, &error);
+      if (icon == NULL)
+        {
+          g_warning ("unable to set icon: %s", error->message);
+          g_error_free (error);
+        }
+      g_free (iconstr);
+    }
+  gtk_image_set_from_gicon (GTK_IMAGE (self->priv->icon), icon, GTK_ICON_SIZE_MENU);
+
+  g_menu_item_get_attribute (menuitem, "label", "s", &label);
+  gtk_label_set_label (GTK_LABEL (self->priv->label), label ? label : "");
+
+  g_menu_item_get_attribute (menuitem, "action", "s", &action);
+  im_app_menu_item_set_action_name (self, action);
+
+  if (icon)
+    g_object_unref (icon);
+  g_free (label);
+  g_free (action);
+}
+
+void
+im_app_menu_item_set_action_group (ImAppMenuItem *self,
+                                   GActionGroup  *action_group)
+{
+  ImAppMenuItemPrivate *priv = self->priv;
+
+  if (priv->action_group != NULL)
+    {
+      g_signal_handlers_disconnect_by_func (priv->action_group, im_app_menu_item_action_added, self);
+      g_signal_handlers_disconnect_by_func (priv->action_group, im_app_menu_item_action_removed, self);
+      g_signal_handlers_disconnect_by_func (priv->action_group, im_app_menu_item_action_enabled_changed, self);
+      g_signal_handlers_disconnect_by_func (priv->action_group, im_app_menu_item_action_state_changed, self);
+
+      g_clear_object (&priv->action_group);
+    }
+
+  if (action_group != NULL)
+    {
+      priv->action_group = g_object_ref (action_group);
+
+      g_signal_connect (priv->action_group, "action-added",
+                        G_CALLBACK (im_app_menu_item_action_added), self);
+      g_signal_connect (priv->action_group, "action-removed",
+                        G_CALLBACK (im_app_menu_item_action_removed), self);
+      g_signal_connect (priv->action_group, "action-enabled-changed",
+                        G_CALLBACK (im_app_menu_item_action_enabled_changed), self);
+      g_signal_connect (priv->action_group, "action-state-changed",
+                        G_CALLBACK (im_app_menu_item_action_state_changed), self);
+    }
+}

=== added file 'src/im-app-menu-item.h'
--- src/im-app-menu-item.h	1970-01-01 00:00:00 +0000
+++ src/im-app-menu-item.h	2013-06-07 21:39:23 +0000
@@ -0,0 +1,54 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *     Lars Uebernickel <lars.uebernickel@xxxxxxxxxxxxx>
+ */
+
+#ifndef __IM_APP_MENU_ITEM_H__
+#define __IM_APP_MENU_ITEM_H__
+
+#include <gtk/gtk.h>
+
+#define IM_TYPE_APP_MENU_ITEM            (im_app_menu_item_get_type ())
+#define IM_APP_MENU_ITEM(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), IM_TYPE_APP_MENU_ITEM, ImAppMenuItem))
+#define IM_APP_MENU_ITEM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), IM_TYPE_APP_MENU_ITEM, ImAppMenuItemClass))
+#define IS_IM_APP_MENU_ITEM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IM_TYPE_APP_MENU_ITEM))
+#define IS_IM_APP_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), IM_TYPE_APP_MENU_ITEM))
+#define IM_APP_MENU_ITEM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), IM_TYPE_APP_MENU_ITEM, ImAppMenuItemClass))
+
+typedef struct _ImAppMenuItem        ImAppMenuItem;
+typedef struct _ImAppMenuItemClass   ImAppMenuItemClass;
+typedef struct _ImAppMenuItemPrivate ImAppMenuItemPrivate;
+
+struct _ImAppMenuItemClass
+{
+  GtkMenuItemClass parent_class;
+};
+
+struct _ImAppMenuItem
+{
+  GtkMenuItem parent;
+  ImAppMenuItemPrivate *priv;
+};
+
+GType           im_app_menu_item_get_type           (void);
+
+void            im_app_menu_item_set_menu_item      (ImAppMenuItem *item,
+                                                     GMenuItem     *menuitem);
+void            im_app_menu_item_set_action_group   (ImAppMenuItem *self,
+                                                     GActionGroup  *action_group);
+
+#endif

=== removed file 'src/im-menu-item.c'
--- src/im-menu-item.c	2011-01-14 19:35:21 +0000
+++ src/im-menu-item.c	1970-01-01 00:00:00 +0000
@@ -1,538 +0,0 @@
-/*
-An indicator to show information that is in messaging applications
-that the user is using.
-
-Copyright 2009 Canonical Ltd.
-
-Authors:
-    Ted Gould <ted@xxxxxxxxxxxxx>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <glib/gi18n.h>
-#include <libdbusmenu-glib/client.h>
-#include <libindicate/indicator.h>
-#include <libindicate/indicator-messages.h>
-#include <libindicate/listener.h>
-#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(&current_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)
-{
-	dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(data), INDICATOR_MENUITEM_PROP_ICON, propertydata);
-	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(&current_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;
-}
-
-/* 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)
-{
-	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;
-	}
-
-	dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), INDICATOR_MENUITEM_PROP_LABEL, propertydata);
-
-	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);
-		}
-		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);
-
-	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;
-}

=== removed file 'src/im-menu-item.h'
--- src/im-menu-item.h	2009-09-04 22:31:29 +0000
+++ src/im-menu-item.h	1970-01-01 00:00:00 +0000
@@ -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 <ted@xxxxxxxxxxxxx>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-#ifndef __IM_MENU_ITEM_H__
-#define __IM_MENU_ITEM_H__
-
-#include <glib.h>
-#include <glib-object.h>
-
-#include <libdbusmenu-glib/menuitem.h>
-#include <libindicate/listener.h>
-
-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
-

=== added file 'src/im-source-menu-item.c'
--- src/im-source-menu-item.c	1970-01-01 00:00:00 +0000
+++ src/im-source-menu-item.c	2013-06-07 21:39:23 +0000
@@ -0,0 +1,407 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *     Lars Uebernickel <lars.uebernickel@xxxxxxxxxxxxx>
+ */
+
+#include "im-source-menu-item.h"
+
+#include <libintl.h>
+#include "ido-detail-label.h"
+
+struct _ImSourceMenuItemPrivate
+{
+  GActionGroup *action_group;
+  gchar *action;
+
+  GtkWidget *icon;
+  GtkWidget *label;
+  GtkWidget *detail;
+
+  gint64 time;
+  guint timer_id;
+};
+
+enum
+{
+  PROP_0,
+  PROP_MENU_ITEM,
+  PROP_ACTION_GROUP,
+  NUM_PROPERTIES
+};
+
+static GParamSpec *properties[NUM_PROPERTIES];
+
+G_DEFINE_TYPE (ImSourceMenuItem, im_source_menu_item, GTK_TYPE_MENU_ITEM);
+
+static void
+im_source_menu_item_constructed (GObject *object)
+{
+  ImSourceMenuItemPrivate *priv = IM_SOURCE_MENU_ITEM (object)->priv;
+  GtkWidget *grid;
+  gint icon_width;
+
+  gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &icon_width, NULL);
+
+  priv->icon = g_object_ref (gtk_image_new ());
+  gtk_widget_set_margin_left (priv->icon, icon_width + 6);
+
+  priv->label = g_object_ref (gtk_label_new (""));
+  gtk_label_set_max_width_chars (GTK_LABEL (priv->label), 40);
+  gtk_label_set_ellipsize (GTK_LABEL (priv->label), PANGO_ELLIPSIZE_END);
+  gtk_misc_set_alignment (GTK_MISC (priv->label), 0.0, 0.5);
+
+  priv->detail = g_object_ref (ido_detail_label_new (""));
+  gtk_widget_set_halign (priv->detail, GTK_ALIGN_END);
+  gtk_widget_set_hexpand (priv->detail, TRUE);
+  gtk_style_context_add_class (gtk_widget_get_style_context (priv->detail), "accelerator");
+
+  grid = gtk_grid_new ();
+  gtk_grid_attach (GTK_GRID (grid), priv->icon, 0, 0, 1, 1);
+  gtk_grid_attach (GTK_GRID (grid), priv->label, 1, 0, 1, 1);
+  gtk_grid_attach (GTK_GRID (grid), priv->detail, 2, 0, 1, 1);
+
+  gtk_container_add (GTK_CONTAINER (object), grid);
+  gtk_widget_show_all (grid);
+
+  G_OBJECT_CLASS (im_source_menu_item_parent_class)->constructed (object);
+}
+
+static gchar *
+im_source_menu_item_time_span_string (gint64 timestamp)
+{
+  gchar *str;
+  gint64 span;
+  gint hours;
+  gint minutes;
+
+  span = MAX (g_get_real_time () - timestamp, 0) / G_USEC_PER_SEC;
+  hours = span / 3600;
+  minutes = (span / 60) % 60;
+
+  if (hours == 0)
+    {
+      /* TRANSLATORS: number of minutes that have passed */
+      str = g_strdup_printf (ngettext ("%d m", "%d m", minutes), minutes);
+    }
+  else
+    {
+      /* TRANSLATORS: number of hours that have passed */
+      str = g_strdup_printf (ngettext ("%d h", "%d h", hours), hours);
+    }
+
+  return str;
+}
+
+static void
+im_source_menu_item_set_detail_time (ImSourceMenuItem *self,
+                                     gint64            time)
+{
+  ImSourceMenuItemPrivate *priv = self->priv;
+  gchar *str;
+
+  priv->time = time;
+
+  str = im_source_menu_item_time_span_string (priv->time);
+  ido_detail_label_set_text (IDO_DETAIL_LABEL (priv->detail), str);
+
+  g_free (str);
+}
+
+static gboolean
+im_source_menu_item_update_time (gpointer data)
+{
+  ImSourceMenuItem *self = data;
+
+  im_source_menu_item_set_detail_time (self, self->priv->time);
+
+  return TRUE;
+}
+
+static gboolean
+im_source_menu_item_set_state (ImSourceMenuItem *self,
+                               GVariant         *state)
+{
+  ImSourceMenuItemPrivate *priv = self->priv;
+  guint32 count;
+  gint64 time;
+  const gchar *str;
+
+  if (priv->timer_id != 0)
+    {
+      g_source_remove (priv->timer_id);
+      priv->timer_id = 0;
+    }
+
+  g_return_val_if_fail (g_variant_is_of_type (state, G_VARIANT_TYPE ("(uxsb)")), FALSE);
+
+  g_variant_get (state, "(ux&sb)", &count, &time, &str, NULL);
+
+  if (count != 0)
+    ido_detail_label_set_count (IDO_DETAIL_LABEL (priv->detail), count);
+  else if (time != 0)
+    {
+      im_source_menu_item_set_detail_time (self, time);
+      priv->timer_id = g_timeout_add_seconds (59, im_source_menu_item_update_time, self);
+    }
+  else if (str != NULL && *str)
+    ido_detail_label_set_text (IDO_DETAIL_LABEL (priv->detail), str);
+
+  return TRUE;
+}
+
+static void
+im_source_menu_item_set_action_name (ImSourceMenuItem *self,
+                                     const gchar      *action_name)
+{
+  ImSourceMenuItemPrivate *priv = self->priv;
+  gboolean enabled = FALSE;
+  GVariant *state;
+
+  if (priv->action != NULL)
+    g_free (priv->action);
+
+  priv->action = g_strdup (action_name);
+
+  if (priv->action_group != NULL && priv->action != NULL &&
+      g_action_group_query_action (priv->action_group, priv->action,
+                                   &enabled, NULL, NULL, NULL, &state))
+    {
+      if (!state || !im_source_menu_item_set_state (self, state))
+        enabled = FALSE;
+
+      if (state)
+        g_variant_unref (state);
+    }
+
+  gtk_widget_set_sensitive (GTK_WIDGET (self), enabled);
+}
+
+static void
+im_source_menu_item_action_added (GActionGroup *action_group,
+                                  gchar        *action_name,
+                                  gpointer      user_data)
+{
+  ImSourceMenuItem *self = user_data;
+
+  if (g_strcmp0 (self->priv->action, action_name) == 0)
+    im_source_menu_item_set_action_name (self, action_name);
+}
+
+static void
+im_source_menu_item_action_removed (GActionGroup *action_group,
+                                    gchar        *action_name,
+                                    gpointer      user_data)
+{
+  ImSourceMenuItem *self = user_data;
+
+  if (g_strcmp0 (self->priv->action, action_name) == 0)
+    {
+      gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
+    }
+}
+
+static void
+im_source_menu_item_action_enabled_changed (GActionGroup *action_group,
+                                            gchar        *action_name,
+                                            gboolean      enabled,
+                                            gpointer      user_data)
+{
+  ImSourceMenuItem *self = user_data;
+
+  if (g_strcmp0 (self->priv->action, action_name) == 0)
+    gtk_widget_set_sensitive (GTK_WIDGET (self), enabled);
+}
+
+static void
+im_source_menu_item_action_state_changed (GActionGroup *action_group,
+                                          gchar        *action_name,
+                                          GVariant     *value,
+                                          gpointer      user_data)
+{
+  ImSourceMenuItem *self = user_data;
+
+  if (g_strcmp0 (self->priv->action, action_name) == 0)
+    im_source_menu_item_set_state (self, value);
+}
+
+static void
+im_source_menu_set_property (GObject      *object,
+                             guint         property_id,
+                             const GValue *value,
+                             GParamSpec   *pspec)
+{
+  ImSourceMenuItem *self = IM_SOURCE_MENU_ITEM (object);
+
+  switch (property_id)
+    {
+    case PROP_MENU_ITEM:
+      im_source_menu_item_set_menu_item (self, G_MENU_ITEM (g_value_get_object (value)));
+      break;
+
+    case PROP_ACTION_GROUP:
+      im_source_menu_item_set_action_group (self, G_ACTION_GROUP (g_value_get_object (value)));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+static void
+im_source_menu_item_dispose (GObject *object)
+{
+  ImSourceMenuItem *self = IM_SOURCE_MENU_ITEM (object);
+
+  if (self->priv->timer_id != 0)
+    {
+      g_source_remove (self->priv->timer_id);
+      self->priv->timer_id = 0;
+    }
+
+  if (self->priv->action_group)
+      im_source_menu_item_set_action_group (self, NULL);
+
+  g_clear_object (&self->priv->icon);
+  g_clear_object (&self->priv->label);
+  g_clear_object (&self->priv->detail);
+
+  G_OBJECT_CLASS (im_source_menu_item_parent_class)->dispose (object);
+}
+
+static void
+im_source_menu_item_finalize (GObject *object)
+{
+  ImSourceMenuItemPrivate *priv = IM_SOURCE_MENU_ITEM (object)->priv;
+
+  g_free (priv->action);
+
+  G_OBJECT_CLASS (im_source_menu_item_parent_class)->finalize (object);
+}
+
+static void
+im_source_menu_item_activate (GtkMenuItem *item)
+{
+  ImSourceMenuItemPrivate *priv = IM_SOURCE_MENU_ITEM (item)->priv;
+
+  if (priv->action && priv->action_group)
+    g_action_group_activate_action (priv->action_group, priv->action, NULL);
+}
+
+static void
+im_source_menu_item_class_init (ImSourceMenuItemClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkMenuItemClass *menu_item_class = GTK_MENU_ITEM_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (ImSourceMenuItemPrivate));
+
+  object_class->constructed = im_source_menu_item_constructed;
+  object_class->set_property = im_source_menu_set_property;
+  object_class->dispose = im_source_menu_item_dispose;
+  object_class->finalize = im_source_menu_item_finalize;
+
+  menu_item_class->activate = im_source_menu_item_activate;
+
+  properties[PROP_MENU_ITEM] = g_param_spec_object ("menu-item",
+                                                    "Menu item",
+                                                    "The model GMenuItem for this menu item",
+                                                    G_TYPE_MENU_ITEM,
+                                                    G_PARAM_WRITABLE |
+                                                    G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_ACTION_GROUP] = g_param_spec_object ("action-group",
+                                                       "Action group",
+                                                       "The action group associated with this menu item",
+                                                       G_TYPE_ACTION_GROUP,
+                                                       G_PARAM_WRITABLE |
+                                                       G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
+}
+
+static void
+im_source_menu_item_init (ImSourceMenuItem *self)
+{
+  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+                                            IM_TYPE_SOURCE_MENU_ITEM,
+                                            ImSourceMenuItemPrivate);
+}
+
+void
+im_source_menu_item_set_menu_item (ImSourceMenuItem *self,
+                                   GMenuItem        *menuitem)
+{
+  gchar *iconstr = NULL;
+  GIcon *icon = NULL;
+  gchar *label;
+  gchar *action = NULL;
+
+  if (g_menu_item_get_attribute (menuitem, "x-canonical-icon", "s", &iconstr))
+    {
+      GError *error;
+      icon = g_icon_new_for_string (iconstr, &error);
+      if (icon == NULL)
+        {
+          g_warning ("unable to set icon: %s", error->message);
+          g_error_free (error);
+        }
+      g_free (iconstr);
+    }
+  gtk_image_set_from_gicon (GTK_IMAGE (self->priv->icon), icon, GTK_ICON_SIZE_MENU);
+
+  g_menu_item_get_attribute (menuitem, "label", "s", &label);
+  gtk_label_set_label (GTK_LABEL (self->priv->label), label ? label : "");
+
+  g_menu_item_get_attribute (menuitem, "action", "s", &action);
+  im_source_menu_item_set_action_name (self, action);
+
+  if (icon)
+    g_object_unref (icon);
+  g_free (label);
+  g_free (action);
+}
+
+void
+im_source_menu_item_set_action_group (ImSourceMenuItem *self,
+                                      GActionGroup     *action_group)
+{
+  ImSourceMenuItemPrivate *priv = self->priv;
+
+  if (priv->action_group != NULL)
+    {
+      g_signal_handlers_disconnect_by_func (priv->action_group, im_source_menu_item_action_added, self);
+      g_signal_handlers_disconnect_by_func (priv->action_group, im_source_menu_item_action_removed, self);
+      g_signal_handlers_disconnect_by_func (priv->action_group, im_source_menu_item_action_enabled_changed, self);
+      g_signal_handlers_disconnect_by_func (priv->action_group, im_source_menu_item_action_state_changed, self);
+
+      g_clear_object (&priv->action_group);
+    }
+
+  if (action_group != NULL)
+    {
+      priv->action_group = g_object_ref (action_group);
+
+      g_signal_connect (priv->action_group, "action-added",
+                        G_CALLBACK (im_source_menu_item_action_added), self);
+      g_signal_connect (priv->action_group, "action-removed",
+                        G_CALLBACK (im_source_menu_item_action_removed), self);
+      g_signal_connect (priv->action_group, "action-enabled-changed",
+                        G_CALLBACK (im_source_menu_item_action_enabled_changed), self);
+      g_signal_connect (priv->action_group, "action-state-changed",
+                        G_CALLBACK (im_source_menu_item_action_state_changed), self);
+    }
+}

=== added file 'src/im-source-menu-item.h'
--- src/im-source-menu-item.h	1970-01-01 00:00:00 +0000
+++ src/im-source-menu-item.h	2013-06-07 21:39:23 +0000
@@ -0,0 +1,54 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *     Lars Uebernickel <lars.uebernickel@xxxxxxxxxxxxx>
+ */
+
+#ifndef __IM_SOURCE_MENU_ITEM_H__
+#define __IM_SOURCE_MENU_ITEM_H__
+
+#include <gtk/gtk.h>
+
+#define IM_TYPE_SOURCE_MENU_ITEM            (im_source_menu_item_get_type ())
+#define IM_SOURCE_MENU_ITEM(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), IM_TYPE_SOURCE_MENU_ITEM, ImSourceMenuItem))
+#define IM_SOURCE_MENU_ITEM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), IM_TYPE_SOURCE_MENU_ITEM, ImSourceMenuItemClass))
+#define IS_IM_SOURCE_MENU_ITEM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IM_TYPE_SOURCE_MENU_ITEM))
+#define IS_IM_SOURCE_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), IM_TYPE_SOURCE_MENU_ITEM))
+#define IM_SOURCE_MENU_ITEM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), IM_TYPE_SOURCE_MENU_ITEM, ImSourceMenuItemClass))
+
+typedef struct _ImSourceMenuItem        ImSourceMenuItem;
+typedef struct _ImSourceMenuItemClass   ImSourceMenuItemClass;
+typedef struct _ImSourceMenuItemPrivate ImSourceMenuItemPrivate;
+
+struct _ImSourceMenuItemClass
+{
+  GtkMenuItemClass parent_class;
+};
+
+struct _ImSourceMenuItem
+{
+  GtkMenuItem parent;
+  ImSourceMenuItemPrivate *priv;
+};
+
+GType           im_source_menu_item_get_type           (void);
+
+void            im_source_menu_item_set_menu_item      (ImSourceMenuItem *item,
+                                                        GMenuItem     *menuitem);
+void            im_source_menu_item_set_action_group   (ImSourceMenuItem *self,
+                                                        GActionGroup  *action_group);
+
+#endif

=== removed file 'src/indicator-messages-status-provider-0.5.pc.in.in'
--- src/indicator-messages-status-provider-0.5.pc.in.in	2011-07-08 19:46:06 +0000
+++ src/indicator-messages-status-provider-0.5.pc.in.in	1970-01-01 00:00:00 +0000
@@ -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@

=== modified file 'src/indicator-messages.c'
--- src/indicator-messages.c	2011-09-21 20:14:17 +0000
+++ src/indicator-messages.c	2013-06-07 21:39:23 +0000
@@ -2,10 +2,11 @@
 An indicator to show information that is in messaging applications
 that the user is using.
 
-Copyright 2009 Canonical Ltd.
+Copyright 2012 Canonical Ltd.
 
 Authors:
     Ted Gould <ted@xxxxxxxxxxxxx>
+    Lars Uebernickel <lars.uebernickel@xxxxxxxxxxxxx>
 
 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 
@@ -20,27 +21,24 @@
 with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
+#include "config.h"
+
 #include <string.h>
+#include <math.h>
 #include <glib.h>
 #include <glib-object.h>
-#include <glib/gi18n.h>
+#include <glib/gi18n-lib.h>
 #include <gtk/gtk.h>
 
-#if GTK_CHECK_VERSION(3, 0, 0)
-#include <libdbusmenu-gtk3/menu.h>
-#include <libdbusmenu-gtk3/menuitem.h>
-#else
-#include <libdbusmenu-gtk/menu.h>
-#include <libdbusmenu-gtk/menuitem.h>
-#endif
-
 #include <libindicator/indicator.h>
 #include <libindicator/indicator-object.h>
-#include <libindicator/indicator-image-helper.h>
 #include <libindicator/indicator-service-manager.h>
 
 #include "dbus-data.h"
-#include "gen-messages-service.xml.h"
+
+#include "ido-menu-item.h"
+#include "im-app-menu-item.h"
+#include "im-source-menu-item.h"
 
 #define INDICATOR_MESSAGES_TYPE            (indicator_messages_get_type ())
 #define INDICATOR_MESSAGES(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_MESSAGES_TYPE, IndicatorMessages))
@@ -49,22 +47,21 @@
 #define IS_INDICATOR_MESSAGES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), INDICATOR_MESSAGES_TYPE))
 #define INDICATOR_MESSAGES_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), INDICATOR_MESSAGES_TYPE, IndicatorMessagesClass))
 
-#define M_PI 3.1415926535897932384626433832795028841971693993751
-
-#define RIGHT_LABEL_FONT_SIZE 12
-#define RIGHT_LABEL_RADIUS 20
-
 typedef struct _IndicatorMessages      IndicatorMessages;
 typedef struct _IndicatorMessagesClass IndicatorMessagesClass;
 
 struct _IndicatorMessagesClass {
 	IndicatorObjectClass parent_class;
-	void    (*update_a11y_desc) (IndicatorServiceManager * service, gpointer * user_data);
 };
 
 struct _IndicatorMessages {
 	IndicatorObject parent;
 	IndicatorServiceManager * service;
+	GActionGroup *actions;
+	GMenuModel *menu;
+	GtkWidget *image;
+	GtkWidget *gtkmenu;
+	gchar *accessible_desc;
 };
 
 GType indicator_messages_get_type (void);
@@ -73,53 +70,34 @@
 INDICATOR_SET_VERSION
 INDICATOR_SET_TYPE(INDICATOR_MESSAGES_TYPE)
 
-/* Globals */
-static GtkWidget * main_image = NULL;
-static GDBusProxy * icon_proxy = NULL;
-static GtkSizeGroup * indicator_right_group = NULL;
-static GDBusNodeInfo *            bus_node_info = NULL;
-static GDBusInterfaceInfo *       bus_interface_info = NULL;
-static const gchar *              accessible_desc = NULL;
-static IndicatorObject *          indicator = NULL;
-
 /* Prototypes */
 static void indicator_messages_class_init (IndicatorMessagesClass *klass);
 static void indicator_messages_init       (IndicatorMessages *self);
 static void indicator_messages_dispose    (GObject *object);
 static void indicator_messages_finalize   (GObject *object);
-static GtkImage * get_icon                (IndicatorObject * io);
+static void service_connection_changed    (IndicatorServiceManager *sm,
+					   gboolean connected,
+					   gpointer user_data);
+static GtkImage * get_image               (IndicatorObject * io);
 static GtkMenu * get_menu                 (IndicatorObject * io);
-static void indicator_messages_middle_click (IndicatorObject * io,
-                                             IndicatorObjectEntry * entry,
-                                             guint time, gpointer data);
 static const gchar * get_accessible_desc  (IndicatorObject * io);
-static void connection_change             (IndicatorServiceManager * sm,
-                                           gboolean connected,
-                                           gpointer user_data);
+static const gchar * get_name_hint        (IndicatorObject * io);
+static void menu_items_changed            (GMenuModel *menu,
+                                           gint        position,
+                                           gint        removed,
+                                           gint        added,
+                                           gpointer    user_data);
+static void messages_action_added         (GActionGroup *action_group,
+                                           gchar        *action_name,
+                                           gpointer      user_data);
+static void messages_state_changed        (GActionGroup *action_group,
+                                           gchar        *action_name,
+                                           GVariant     *value,
+                                           gpointer      user_data);
+static void indicator_messages_add_toplevel_menu (IndicatorMessages *self);
 
 G_DEFINE_TYPE (IndicatorMessages, indicator_messages, INDICATOR_OBJECT_TYPE);
 
-static void
-update_a11y_desc (void)
-{
-	g_return_if_fail(IS_INDICATOR_MESSAGES(indicator));
-
-	GList *entries = indicator_object_get_entries(indicator);
-	IndicatorObjectEntry * entry = (IndicatorObjectEntry *)entries->data;
-
-	entry->accessible_desc = get_accessible_desc(indicator);
-
-	g_signal_emit(G_OBJECT(indicator),
-	              INDICATOR_OBJECT_SIGNAL_ACCESSIBLE_DESC_UPDATE_ID,
-	              0,
-	              entry,
-	              TRUE);
-
-	g_list_free(entries);
-
-	return;
-}
-
 /* Initialize the one-timers */
 static void
 indicator_messages_class_init (IndicatorMessagesClass *klass)
@@ -131,46 +109,30 @@
 
 	IndicatorObjectClass * io_class = INDICATOR_OBJECT_CLASS(klass);
 
-	io_class->get_image = get_icon;
+	io_class->get_image = get_image;
 	io_class->get_menu = get_menu;
 	io_class->get_accessible_desc = get_accessible_desc;
-	io_class->secondary_activate = indicator_messages_middle_click;
-
-	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;
+	io_class->get_name_hint = get_name_hint;
 }
 
 /* Build up our per-instance variables */
 static void
 indicator_messages_init (IndicatorMessages *self)
 {
-	/* Default values */
-	self->service = NULL;
-
-	/* Complex stuff */
 	self->service = indicator_service_manager_new_version(INDICATOR_MESSAGES_DBUS_NAME, 1);
-	g_signal_connect(self->service, INDICATOR_SERVICE_MANAGER_SIGNAL_CONNECTION_CHANGE, G_CALLBACK(connection_change), self);
-
-	indicator = INDICATOR_OBJECT(self);
-
-	return;
+	g_signal_connect (self->service, "connection-change",
+			  G_CALLBACK (service_connection_changed), self);
+
+	self->gtkmenu = gtk_menu_new ();
+	g_object_ref_sink (self->gtkmenu);
+
+	self->image = g_object_ref_sink (gtk_image_new ());
+
+	/* make sure custom menu item types are registered (so that
+         * gtk_model_new_from_menu can pick them up */
+	ido_menu_item_get_type ();
+	im_app_menu_item_get_type ();
+	im_source_menu_item_get_type ();
 }
 
 /* Unref stuff */
@@ -180,10 +142,11 @@
 	IndicatorMessages * self = INDICATOR_MESSAGES(object);
 	g_return_if_fail(self != NULL);
 
-	if (self->service != NULL) {
-		g_object_unref(self->service);
-		self->service = NULL;
-	}
+	g_clear_object (&self->service);
+	g_clear_object (&self->actions);
+	g_clear_object (&self->menu);
+	g_clear_object (&self->gtkmenu);
+	g_clear_object (&self->image);
 
 	G_OBJECT_CLASS (indicator_messages_parent_class)->dispose (object);
 	return;
@@ -193,6 +156,9 @@
 static void
 indicator_messages_finalize (GObject *object)
 {
+	IndicatorMessages *self = INDICATOR_MESSAGES (object);
+
+	g_free (self->accessible_desc);
 
 	G_OBJECT_CLASS (indicator_messages_parent_class)->finalize (object);
 	return;
@@ -202,617 +168,215 @@
 
 /* Functions */
 
-/* Signal off of the proxy */
-static void
-proxy_signal (GDBusProxy * proxy, const gchar * sender, const gchar * signal, GVariant * params, gpointer user_data)
-{
-	gboolean prop = g_variant_get_boolean(g_variant_get_child_value(params, 0));
-
-	if (g_strcmp0("AttentionChanged", signal) == 0) {
-		if (prop) {
-			indicator_image_helper_update(GTK_IMAGE(main_image), "indicator-messages-new");
-			accessible_desc = _("New Messages");
-		} else {
-			indicator_image_helper_update(GTK_IMAGE(main_image), "indicator-messages");
-			accessible_desc = _("Messages");
-		}
-	} else if (g_strcmp0("IconChanged", signal) == 0) {
-		if (prop) {
-			gtk_widget_hide(main_image);
-		} else {
-			gtk_widget_show(main_image);
-		}
-	} else {
-		g_warning("Unknown signal %s", signal);
-	}
-
-	update_a11y_desc();
-
-	return;
-}
-
-/* Callback from getting the attention status from the service. */
-static void
-attention_cb (GObject * object, GAsyncResult * ares, gpointer user_data)
-{
-	GError * error = NULL;
-	GVariant * res = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), ares, &error);
-
-	if (error != NULL) {
-		g_warning("Unable to get attention status: %s", error->message);
-		g_error_free(error);
-		return;
-	}
-
-	gboolean prop = g_variant_get_boolean(g_variant_get_child_value(res, 0));
-
-	if (prop) {
-		indicator_image_helper_update(GTK_IMAGE(main_image), "indicator-messages-new");
-		accessible_desc = _("New Messages");
-	} else {
-		indicator_image_helper_update(GTK_IMAGE(main_image), "indicator-messages");
-		accessible_desc = _("Messages");
-	}
-
-	update_a11y_desc();
-
-	return;
-}
-
-/* Change from getting the icon visibility from the service */
-static void
-icon_cb (GObject * object, GAsyncResult * ares, gpointer user_data)
-{
-	GError * error = NULL;
-	GVariant * res = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), ares, &error);
-
-	if (error != NULL) {
-		g_warning("Unable to get icon visibility: %s", error->message);
-		g_error_free(error);
-		return;
-	}
-
-	gboolean prop = g_variant_get_boolean(g_variant_get_child_value(res, 0));
-	
-	if (prop) {
-		gtk_widget_hide(main_image);
-	} else {
-		gtk_widget_show(main_image);
-	}
-
-	return;
-}
-
-static guint connection_drop_timeout = 0;
-
-/* Resets the icon to not having messages if we can't get a good
-   answer on it from the service. */
-static gboolean
-connection_drop_cb (gpointer user_data)
-{
-	if (main_image != NULL) {
-		indicator_image_helper_update(GTK_IMAGE(main_image), "indicator-messages");
-	}
-	connection_drop_timeout = 0;
-	return FALSE;
-}
-
-/* Proxy is setup now.. whoo! */
-static void
-proxy_ready_cb (GObject * obj, GAsyncResult * res, gpointer user_data)
-{
-	GError * error = NULL;
-	GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish(res, &error);
-
-	if (error != NULL) {
-		g_warning("Unable to get proxy of service: %s", error->message);
-		g_error_free(error);
-		return;
-	}
-
-	icon_proxy = proxy;
-
-	g_signal_connect(G_OBJECT(proxy), "g-signal", G_CALLBACK(proxy_signal), user_data);
-
-	g_dbus_proxy_call(icon_proxy,
-	                  "AttentionRequested",
-	                  NULL, /* params */
-	                  G_DBUS_CALL_FLAGS_NONE,
-	                  -1, /* timeout */
-	                  NULL, /* cancel */
-	                  attention_cb,
-	                  user_data);
-	g_dbus_proxy_call(icon_proxy,
-	                  "IconShown",
-	                  NULL, /* params */
-	                  G_DBUS_CALL_FLAGS_NONE,
-	                  -1, /* timeout */
-	                  NULL, /* cancel */
-	                  icon_cb,
-	                  user_data);
-
-	return;
-}
-
-/* Sets up all the icon information in the proxy. */
-static void 
-connection_change (IndicatorServiceManager * sm, gboolean connected, gpointer user_data)
-{
-	if (connection_drop_timeout != 0) {
-		g_source_remove(connection_drop_timeout);
-		connection_drop_timeout = 0;
-	}
-
-	if (!connected) {
-		/* Ensure that we're not saying there are messages
-		   when we don't have a connection. */
-		connection_drop_timeout = g_timeout_add(400, connection_drop_cb, NULL);
-		return;
-	}
-
-	if (icon_proxy == NULL) {
-		g_dbus_proxy_new_for_bus(G_BUS_TYPE_SESSION,
-		                         G_DBUS_PROXY_FLAGS_NONE,
-		                         bus_interface_info,
-		                         INDICATOR_MESSAGES_DBUS_NAME,
-		                         INDICATOR_MESSAGES_DBUS_SERVICE_OBJECT,
-		                         INDICATOR_MESSAGES_DBUS_SERVICE_INTERFACE,
-		                         NULL, /* cancel */
-		                         proxy_ready_cb,
-		                         sm);
-	} else {
-		g_dbus_proxy_call(icon_proxy,
-		                  "AttentionRequested",
-		                  NULL, /* params */
-		                  G_DBUS_CALL_FLAGS_NONE,
-		                  -1, /* timeout */
-		                  NULL, /* cancel */
-		                  attention_cb,
-		                  sm);
-		g_dbus_proxy_call(icon_proxy,
-		                  "IconShown",
-		                  NULL, /* params */
-		                  G_DBUS_CALL_FLAGS_NONE,
-		                  -1, /* timeout */
-		                  NULL, /* cancel */
-		                  icon_cb,
-		                  sm);
-	}
-
-	return;
-}
-
-/* Sets the icon when it changes. */
-static void
-application_icon_change_cb (DbusmenuMenuitem * mi, gchar * prop, GVariant * value, gpointer user_data)
-{
-	if (!g_strcmp0(prop, APPLICATION_MENUITEM_PROP_ICON)) {
-		/* Set the main icon */
-		if (GTK_IS_IMAGE(user_data)) {
-			gtk_image_set_from_icon_name(GTK_IMAGE(user_data), g_variant_get_string(value, NULL), GTK_ICON_SIZE_MENU);
-		}
-	}
-
-	return;
-}
-
-/* Sets the label when it changes. */
-static void
-application_prop_change_cb (DbusmenuMenuitem * mi, gchar * prop, GVariant * value, gpointer user_data)
-{
-	if (!g_strcmp0(prop, APPLICATION_MENUITEM_PROP_NAME)) {
-		/* Set the main label */
-		if (GTK_IS_LABEL(user_data)) {
-			gtk_label_set_text(GTK_LABEL(user_data), g_variant_get_string(value, NULL));
-		}
-	}
-
-	if (!g_strcmp0(prop, APPLICATION_MENUITEM_PROP_RUNNING)) {
-		/* TODO: should hide/show the triangle live if the menu was open.
-		   In practice, this is rarely needed. */
-	}
-
-	return;
-}
-
-/* Draws a triangle on the left, using fg[STATE_TYPE] color. */
-#if GTK_CHECK_VERSION(3, 0, 0)
-static gboolean
-application_triangle_draw_cb (GtkWidget *widget, cairo_t *cr, gpointer data)
-{
-#else
-static gboolean
-application_triangle_draw_cb (GtkWidget *widget, GdkEventExpose *event, gpointer data)
-{
-	cairo_t *cr;
-#endif
-	GtkAllocation allocation;
-	GtkStyle *style;
-	int x, y, arrow_width, arrow_height;
-
-	if (!GTK_IS_WIDGET (widget)) return FALSE;
-	if (!DBUSMENU_IS_MENUITEM (data)) return FALSE;
-
-	/* render the triangle indicator only if the application is running */
-	if (! dbusmenu_menuitem_property_get_bool (DBUSMENU_MENUITEM(data), APPLICATION_MENUITEM_PROP_RUNNING))
-		return FALSE;;
-
-	/* get style */
-	style = gtk_widget_get_style (widget);
-
-	/* set arrow position / dimensions */
-	arrow_width = 5; /* the pixel-based reference triangle is 5x9 */
-	arrow_height = 9;
-	gtk_widget_get_allocation (widget, &allocation);
-#if GTK_CHECK_VERSION(3, 0, 0)
-	x = 0;
-	y = allocation.height/2.0 - (double)arrow_height/2.0;
-#else
-	x = allocation.x;
-	y = allocation.y + allocation.height/2.0 - (double)arrow_height/2.0;
-#endif
-
-#if GTK_CHECK_VERSION(3, 0, 0)
-	cairo_save (cr);
-#else
-	/* initialize cairo drawing area */
-	cr = (cairo_t*) gdk_cairo_create (gtk_widget_get_window (widget));
-#endif
-
-	/* set line width */
-	cairo_set_line_width (cr, 1.0);
-
-	/* cairo drawing code */
-	cairo_move_to (cr, x, y);
-	cairo_line_to (cr, x, y + arrow_height);
-	cairo_line_to (cr, x + arrow_width, y + (double)arrow_height/2.0);
-	cairo_close_path (cr);
-	cairo_set_source_rgb (cr, style->fg[gtk_widget_get_state(widget)].red/65535.0,
-	                          style->fg[gtk_widget_get_state(widget)].green/65535.0,
-	                          style->fg[gtk_widget_get_state(widget)].blue/65535.0);
-	cairo_fill (cr);
-
-#if GTK_CHECK_VERSION(3, 0, 0)
-	cairo_restore (cr);
-#else
-	/* remember to destroy cairo context to avoid leaks */
-	cairo_destroy (cr);
-#endif
-
-	return FALSE;
-}
-
-/* Custom function to draw rounded rectangle with max radius */
-static void
-custom_cairo_rounded_rectangle (cairo_t *cr,
-                                double x, double y, double w, double h)
-{
-	double radius = MIN (w/2.0, h/2.0);
-
-	cairo_move_to (cr, x+radius, y);
-	cairo_arc (cr, x+w-radius, y+radius, radius, M_PI*1.5, M_PI*2);
-	cairo_arc (cr, x+w-radius, y+h-radius, radius, 0, M_PI*0.5);
-	cairo_arc (cr, x+radius,   y+h-radius, radius, M_PI*0.5, M_PI);
-	cairo_arc (cr, x+radius,   y+radius,   radius, M_PI, M_PI*1.5);
-}
-
-/* Draws a rounded rectangle with text inside. */
-#if GTK_CHECK_VERSION(3, 0, 0)
-static gboolean
-numbers_draw_cb (GtkWidget *widget, cairo_t *cr, gpointer data)
-{
-#else
-static gboolean
-numbers_draw_cb (GtkWidget *widget, GdkEventExpose *event, gpointer data)
-{
-	cairo_t *cr;
-#endif
-	GtkAllocation allocation;
-	GtkStyle *style;
-	double x, y, w, h;
-	PangoLayout * layout;
-	gint font_size = RIGHT_LABEL_FONT_SIZE;
-
-	if (!GTK_IS_WIDGET (widget)) return FALSE;
-
-	/* get style */
-	style = gtk_widget_get_style (widget);
-
-	/* set arrow position / dimensions */
-	gtk_widget_get_allocation (widget, &allocation);
-#if GTK_CHECK_VERSION(3, 0, 0)
-	x = 0;
-	y = 0;
-#else
-	x = allocation.x;
-	y = allocation.y;
-#endif
-	w = allocation.width;
-	h = allocation.height;
-
-	layout = gtk_label_get_layout (GTK_LABEL(widget));
-
-	/* This does not work, don't ask me why but font_size is 0.
-	 * I wanted to use a dynamic font size to adjust the padding on left/right edges
-	 * of the rounded rectangle. Andrea Cimitan */
-	/* const PangoFontDescription * font_description = pango_layout_get_font_description (layout);
-	font_size = pango_font_description_get_size (font_description); */
-
-#if GTK_CHECK_VERSION(3, 0, 0)
-	cairo_save (cr);
-#else
-	/* initialize cairo drawing area */
-	cr = (cairo_t*) gdk_cairo_create (gtk_widget_get_window (widget));
-#endif
-
-	/* set line width */
-	cairo_set_line_width (cr, 1.0);
-
-	cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
-
-	/* cairo drawing code */
-	custom_cairo_rounded_rectangle (cr, x - font_size/2.0, y, w + font_size, h);
-
-	cairo_set_source_rgba (cr, style->fg[gtk_widget_get_state(widget)].red/65535.0,
-	                           style->fg[gtk_widget_get_state(widget)].green/65535.0,
-	                           style->fg[gtk_widget_get_state(widget)].blue/65535.0, 0.5);
-
-	cairo_move_to (cr, x, y);
-	pango_cairo_layout_path (cr, layout);
-	cairo_fill (cr);
-
-#if GTK_CHECK_VERSION(3, 0, 0)
-	cairo_restore (cr);
-#else
-	/* remember to destroy cairo context to avoid leaks */
-	cairo_destroy (cr);
-#endif
-
-	return TRUE;
-}
-
-/* Builds a menu item representing a running application in the
-   messaging menu */
-static gboolean
-new_application_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data)
-{
-	g_debug ("%s (\"%s\")", __func__, dbusmenu_menuitem_property_get(newitem, APPLICATION_MENUITEM_PROP_NAME));
-
-	GtkMenuItem * gmi = GTK_MENU_ITEM(gtk_image_menu_item_new());
-	gtk_image_menu_item_set_always_show_image(GTK_IMAGE_MENU_ITEM(gmi), TRUE);
-
-	/* Set the minimum size, we always want it to take space */
-	gint width, height;
-	gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height);
-
-	GtkWidget * icon = gtk_image_new_from_icon_name(dbusmenu_menuitem_property_get(newitem, APPLICATION_MENUITEM_PROP_ICON), GTK_ICON_SIZE_MENU);
-	gtk_widget_set_size_request(icon, width
-								+ 5 /* ref triangle is 5x9 pixels */
-								+ 2 /* padding */,
-								height);
-	gtk_misc_set_alignment(GTK_MISC(icon), 1.0 /* right aligned */, 0.5);
-	gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(gmi), icon);
-	gtk_widget_show(icon);
-
-	/* Application name in a label */
-	GtkWidget * label = gtk_label_new(dbusmenu_menuitem_property_get(newitem, APPLICATION_MENUITEM_PROP_NAME));
-	gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
-	gtk_widget_show(label);
-
-	/* Insert the hbox */
-	gtk_container_add(GTK_CONTAINER(gmi), label);
-
-	/* Attach some of the standard GTK stuff */
-	dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, gmi, parent);
-
-	/* Make sure we can handle the label changing */
-	g_signal_connect(G_OBJECT(newitem), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(application_prop_change_cb), label);
-	g_signal_connect(G_OBJECT(newitem), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(application_icon_change_cb), icon);
-#if GTK_CHECK_VERSION(3, 0, 0)
-	g_signal_connect_after(G_OBJECT (gmi), "draw", G_CALLBACK (application_triangle_draw_cb), newitem);
-#else
-	g_signal_connect_after(G_OBJECT (gmi), "expose_event", G_CALLBACK (application_triangle_draw_cb), newitem);
-#endif
-
-	return TRUE;
-}
-
-typedef struct _indicator_item_t indicator_item_t;
-struct _indicator_item_t {
-	GtkWidget * icon;
-	GtkWidget * label;
-	GtkWidget * right;
-};
-
-/* Whenever we have a property change on a DbusmenuMenuitem
-   we need to be responsive to that. */
-static void
-indicator_prop_change_cb (DbusmenuMenuitem * mi, gchar * prop, GVariant * value, indicator_item_t * mi_data)
-{
-	if (!g_strcmp0(prop, INDICATOR_MENUITEM_PROP_LABEL)) {
-		/* Set the main label */
-		gtk_label_set_text(GTK_LABEL(mi_data->label), g_variant_get_string(value, NULL));
-	} else if (!g_strcmp0(prop, INDICATOR_MENUITEM_PROP_RIGHT)) {
-		/* Set the right label */
-		gtk_label_set_text(GTK_LABEL(mi_data->right), g_variant_get_string(value, NULL));
-	} else if (!g_strcmp0(prop, INDICATOR_MENUITEM_PROP_ICON)) {
-		/* We don't use the value here, which is probably less efficient, 
-		   but it's easier to use the easy function.  And since th value
-		   is already cached, shouldn't be a big deal really.  */
-		GdkPixbuf * pixbuf = dbusmenu_menuitem_property_get_image(mi, INDICATOR_MENUITEM_PROP_ICON);
-		if (pixbuf != NULL) {
-			/* If we've got a pixbuf we need to make sure it's of a reasonable
-			   size to fit in the menu.  If not, rescale it. */
-			GdkPixbuf * resized_pixbuf;
-			gint width, height;
-			gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height);
-			if (gdk_pixbuf_get_width(pixbuf) > width ||
-					gdk_pixbuf_get_height(pixbuf) > height) {
-				g_debug("Resizing icon from %dx%d to %dx%d", gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf), width, height);
-				resized_pixbuf = gdk_pixbuf_scale_simple(pixbuf,
-				                                         width,
-				                                         height,
-				                                         GDK_INTERP_BILINEAR);
-				g_object_unref(pixbuf);
-			} else {
-				g_debug("Happy with icon sized %dx%d", gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf));
-				resized_pixbuf = pixbuf;
-			}
-	  
-			gtk_image_set_from_pixbuf(GTK_IMAGE(mi_data->icon), resized_pixbuf);
-
-			g_object_unref(resized_pixbuf);
-
-			gtk_widget_show(mi_data->icon);
-		} else {
-			gtk_widget_hide(mi_data->icon);
-		}
-	}
-
-	return;
-}
-
-/* We have a small little menuitem type that handles all
-   of the fun stuff for indicators.  Mostly this is the
-   shifting over and putting the icon in with some right
-   side text that'll be determined by the service.  */
-static gboolean
-new_indicator_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data)
-{
-	g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE);
-	g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE);
-	/* Note: not checking parent, it's reasonable for it to be NULL */
-
-	indicator_item_t * mi_data = g_new0(indicator_item_t, 1);
-
-	GtkMenuItem * gmi = GTK_MENU_ITEM(gtk_menu_item_new());
-
-	gint padding = 4;
-	gint font_size = RIGHT_LABEL_FONT_SIZE;
-	gtk_widget_style_get(GTK_WIDGET(gmi), "toggle-spacing", &padding, NULL);
-
-	GtkWidget * hbox = gtk_hbox_new(FALSE, padding);
-
-	/* Icon, probably someone's face or avatar on an IM */
-	mi_data->icon = gtk_image_new();
-
-	/* Set the minimum size, we always want it to take space */
-	gint width, height;
-	gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height);
-	gtk_widget_set_size_request(mi_data->icon, width, height);
-
-	GdkPixbuf * pixbuf = dbusmenu_menuitem_property_get_image(newitem, INDICATOR_MENUITEM_PROP_ICON);
-	if (pixbuf != NULL) {
-		/* If we've got a pixbuf we need to make sure it's of a reasonable
-		   size to fit in the menu.  If not, rescale it. */
-		GdkPixbuf * resized_pixbuf;
-		if (gdk_pixbuf_get_width(pixbuf) > width ||
-		        gdk_pixbuf_get_height(pixbuf) > height) {
-			g_debug("Resizing icon from %dx%d to %dx%d", gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf), width, height);
-			resized_pixbuf = gdk_pixbuf_scale_simple(pixbuf,
-			                                         width,
-			                                         height,
-			                                         GDK_INTERP_BILINEAR);
-			g_object_unref(pixbuf);
-		} else {
-			g_debug("Happy with icon sized %dx%d", gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf));
-			resized_pixbuf = pixbuf;
-		}
-  
-		gtk_image_set_from_pixbuf(GTK_IMAGE(mi_data->icon), resized_pixbuf);
-
-		g_object_unref(resized_pixbuf);
-	}
-	gtk_misc_set_alignment(GTK_MISC(mi_data->icon), 0.0, 0.5);
-	gtk_box_pack_start(GTK_BOX(hbox), mi_data->icon, FALSE, FALSE, 0);
-
-	if (pixbuf != NULL) {
-		gtk_widget_show(mi_data->icon);
-	}
-
-	/* Label, probably a username, chat room or mailbox name */
-	mi_data->label = gtk_label_new(dbusmenu_menuitem_property_get(newitem, INDICATOR_MENUITEM_PROP_LABEL));
-	gtk_misc_set_alignment(GTK_MISC(mi_data->label), 0.0, 0.5);
-	gtk_box_pack_start(GTK_BOX(hbox), mi_data->label, TRUE, TRUE, 0);
-	gtk_widget_show(mi_data->label);
-
-	/* Usually either the time or the count on the individual
-	   item. */
-	mi_data->right = gtk_label_new(dbusmenu_menuitem_property_get(newitem, INDICATOR_MENUITEM_PROP_RIGHT));
-	gtk_size_group_add_widget(indicator_right_group, mi_data->right);
-	/* install extra decoration overlay */
-#if GTK_CHECK_VERSION(3, 0, 0)
-	g_signal_connect (G_OBJECT (mi_data->right), "draw",
-	                  G_CALLBACK (numbers_draw_cb), NULL);
-#else
-	g_signal_connect (G_OBJECT (mi_data->right), "expose_event",
-	                  G_CALLBACK (numbers_draw_cb), NULL);
-#endif
-
-	gtk_misc_set_alignment(GTK_MISC(mi_data->right), 1.0, 0.5);
-	gtk_box_pack_start(GTK_BOX(hbox), mi_data->right, FALSE, FALSE, padding + font_size/2.0);
-	gtk_widget_show(mi_data->right);
-
-	gtk_container_add(GTK_CONTAINER(gmi), hbox);
-	gtk_widget_show(hbox);
-
-	dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, gmi, parent);
-
-	g_signal_connect(G_OBJECT(newitem), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(indicator_prop_change_cb), mi_data);
-	g_object_weak_ref(G_OBJECT(newitem), (GWeakNotify)g_free, mi_data);
-
-	return TRUE;
-}
-
-/* Builds the main image icon using the libindicator helper. */
+static void service_connection_changed (IndicatorServiceManager *sm,
+				        gboolean connected,
+				        gpointer user_data)
+{
+	IndicatorMessages *self = user_data;
+	GDBusConnection *bus;
+	GError *error = NULL;
+
+	if (self->actions != NULL) {
+		g_signal_handlers_disconnect_by_func (self->actions, messages_action_added, self);
+		g_signal_handlers_disconnect_by_func (self->actions, messages_state_changed, self);
+		g_clear_object (&self->actions);
+	}
+	if (self->menu != NULL) {
+		g_signal_handlers_disconnect_by_func (self->menu, menu_items_changed, self);
+		g_clear_object (&self->menu);
+	}
+	gtk_menu_shell_bind_model (GTK_MENU_SHELL (self->gtkmenu), NULL, NULL, FALSE);
+
+	if (connected == FALSE)
+		return;
+
+	bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
+	if (!bus) {
+		g_warning ("error connecting to the session bus: %s", error->message);
+		g_error_free (error);
+		return;
+	}
+
+	self->actions = G_ACTION_GROUP (g_dbus_action_group_get (bus,
+								 INDICATOR_MESSAGES_DBUS_NAME,
+								 INDICATOR_MESSAGES_DBUS_OBJECT));
+	gtk_widget_insert_action_group (self->gtkmenu, 
+					get_name_hint (INDICATOR_OBJECT (self)),
+					self->actions);
+	g_signal_connect (self->actions, "action-added::messages",
+			  G_CALLBACK (messages_action_added), self);
+	g_signal_connect (self->actions, "action-state-changed::messages",
+			  G_CALLBACK (messages_state_changed), self);
+
+	self->menu = G_MENU_MODEL (g_dbus_menu_model_get (bus,
+							  INDICATOR_MESSAGES_DBUS_NAME,
+							  INDICATOR_MESSAGES_DBUS_OBJECT));
+	g_signal_connect (self->menu, "items-changed", G_CALLBACK (menu_items_changed), self);
+
+	if (g_menu_model_get_n_items (self->menu) == 1)
+		indicator_messages_add_toplevel_menu (self);
+	else
+		indicator_object_set_visible (INDICATOR_OBJECT (self), FALSE);
+
+	g_object_unref (bus);
+}
+
 static GtkImage *
-get_icon (IndicatorObject * io)
+get_image (IndicatorObject * io)
 {
-	main_image = GTK_WIDGET(indicator_image_helper("indicator-messages"));
-	gtk_widget_show(main_image);
+	IndicatorMessages *self = INDICATOR_MESSAGES (io);
 
-	return GTK_IMAGE(main_image);
+	gtk_widget_show (self->image);
+	return GTK_IMAGE (self->image);
 }
 
-/* Builds the menu for the indicator */
 static GtkMenu *
 get_menu (IndicatorObject * io)
 {
-	indicator_right_group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
-
-	DbusmenuGtkMenu * menu = dbusmenu_gtkmenu_new(INDICATOR_MESSAGES_DBUS_NAME, INDICATOR_MESSAGES_DBUS_OBJECT);
-	DbusmenuGtkClient * client = dbusmenu_gtkmenu_get_client(menu);
-
-	dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), INDICATOR_MENUITEM_TYPE, new_indicator_item);
-	dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), APPLICATION_MENUITEM_TYPE, new_application_item);
-
-	return GTK_MENU(menu);
+	IndicatorMessages *self = INDICATOR_MESSAGES (io);
+
+	return GTK_MENU (self->gtkmenu);
 }
 
-/* Returns the accessible description of the indicator */
 static const gchar *
 get_accessible_desc (IndicatorObject * io)
 {
-	return accessible_desc;
-}
-
-/* Hide the notifications on middle-click over the indicator-messages */
-static void
-indicator_messages_middle_click (IndicatorObject * io, IndicatorObjectEntry * entry,
-                                 guint time, gpointer data)
-{
-	if (icon_proxy == NULL) {
-		return;
-	}
-
-	g_dbus_proxy_call(icon_proxy,
-	                  "ClearAttention",
-	                  NULL, /* params */
-	                  G_DBUS_CALL_FLAGS_NONE,
-	                  -1, /* timeout */
-	                  NULL, /* cancel */
-	                  NULL,
-	                  NULL);
-
-	return;
+	IndicatorMessages *self = INDICATOR_MESSAGES (io);
+	return self->accessible_desc;
+}
+
+static const gchar *
+get_name_hint (IndicatorObject *io)
+{
+  return PACKAGE;
+}
+
+static void
+indicator_messages_accessible_desc_updated (IndicatorMessages *self)
+{
+	GList *entries;
+
+	entries = indicator_object_get_entries (INDICATOR_OBJECT (self));
+	g_return_if_fail (entries != NULL);
+
+	g_signal_emit_by_name (self, INDICATOR_OBJECT_SIGNAL_ACCESSIBLE_DESC_UPDATE, entries->data);
+
+	g_list_free (entries);
+}
+
+static GIcon *
+g_menu_model_get_item_attribute_icon (GMenuModel  *menu,
+				      gint         index,
+				      const gchar *attribute)
+{
+	gchar *iconstr;
+	GIcon *icon = NULL;
+
+	if (g_menu_model_get_item_attribute (menu, index, attribute, "s", &iconstr)) {
+		GError *error;
+
+		icon = g_icon_new_for_string (iconstr, &error);
+		if (icon == NULL) {
+			g_warning ("unable to load icon: %s", error->message);
+			g_error_free (error);
+		}
+
+		g_free (iconstr);
+	}
+
+	return icon;
+}
+
+static void
+indicator_messages_add_toplevel_menu (IndicatorMessages *self)
+{
+	GIcon *icon;
+	GMenuModel *popup;
+
+	indicator_object_set_visible (INDICATOR_OBJECT (self), TRUE);
+
+	icon = g_menu_model_get_item_attribute_icon (self->menu, 0, "x-canonical-icon");
+	if (icon) {
+		gtk_image_set_from_gicon (GTK_IMAGE (self->image), icon, GTK_ICON_SIZE_LARGE_TOOLBAR);
+		g_object_unref (icon);
+	}
+
+	g_free (self->accessible_desc);
+	self->accessible_desc = NULL;
+	if (g_menu_model_get_item_attribute (self->menu, 0, "x-canonical-accessible-description",
+					     "s", &self->accessible_desc)) {
+		indicator_messages_accessible_desc_updated (self);
+	}
+
+	popup = g_menu_model_get_item_link (self->menu, 0, G_MENU_LINK_SUBMENU);
+	if (popup) {
+		gtk_menu_shell_bind_model (GTK_MENU_SHELL (self->gtkmenu),
+					   popup,
+					   get_name_hint (INDICATOR_OBJECT (self)),
+					   TRUE);
+
+		g_object_unref (popup);
+	}
+}
+
+static void
+menu_items_changed (GMenuModel *menu,
+                    gint        position,
+                    gint        removed,
+                    gint        added,
+                    gpointer    user_data)
+{
+	IndicatorMessages *self = user_data;
+
+	g_return_if_fail (position == 0);
+
+	if (added == 1)
+		indicator_messages_add_toplevel_menu (self);
+	else if (removed == 1)
+		indicator_object_set_visible (INDICATOR_OBJECT (self), FALSE);
+}
+
+static void
+indicator_messages_update_icon (IndicatorMessages *self,
+                                GVariant          *state)
+{
+	GIcon *icon;
+	GError *error = NULL;
+
+	g_return_if_fail (g_variant_is_of_type (state, G_VARIANT_TYPE_STRING));
+
+	icon = g_icon_new_for_string (g_variant_get_string (state, NULL), &error);
+	if (icon == NULL) {
+		g_warning ("unable to load icon: %s", error->message);
+		g_error_free (error);
+	}
+	else {
+		gtk_image_set_from_gicon (GTK_IMAGE (self->image), icon, GTK_ICON_SIZE_LARGE_TOOLBAR);
+		g_object_unref (icon);
+	}
+}
+
+static void
+messages_action_added (GActionGroup *action_group,
+                       gchar        *action_name,
+                       gpointer      user_data)
+{
+	IndicatorMessages *self = user_data;
+	GVariant *state;
+	
+	state = g_action_group_get_action_state (action_group, "messages");
+	indicator_messages_update_icon (self, state);
+
+	g_variant_unref (state);
+}
+
+static void
+messages_state_changed (GActionGroup *action_group,
+                        gchar        *action_name,
+                        GVariant     *value,
+                        gpointer      user_data)
+{
+	IndicatorMessages *self = user_data;
+
+	indicator_messages_update_icon (self, value);
 }

=== removed file 'src/launcher-menu-item.c'
--- src/launcher-menu-item.c	2011-04-06 16:20:08 +0000
+++ src/launcher-menu-item.c	1970-01-01 00:00:00 +0000
@@ -1,392 +0,0 @@
-/*
-An indicator to show information that is in messaging applications
-that the user is using.
-
-Copyright 2009 Canonical Ltd.
-
-Authors:
-    Ted Gould <ted@xxxxxxxxxxxxx>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gdk/gdk.h>
-#include <glib/gi18n.h>
-#include <gio/gdesktopappinfo.h>
-#include <libindicator/indicator-desktop-shortcuts.h>
-#include "launcher-menu-item.h"
-#include "dbus-data.h"
-#include "default-applications.h"
-#include "seen-db.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));
-
-	const gchar * default_name = NULL;
-	
-	if (seen_db_seen(desktop_file)) {
-		default_name = get_default_name(desktop_file);
-	} else {
-		default_name = get_default_setup(desktop_file);
-	}
-
-	if (default_name == NULL) {
-		dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), DBUSMENU_MENUITEM_PROP_LABEL, launcher_menu_item_get_name(self));
-	} else {
-		dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), DBUSMENU_MENUITEM_PROP_LABEL, _(default_name));
-	}
-
-	gchar * iconstr;
-	if (default_name == NULL) {
-		iconstr = launcher_menu_item_get_icon(self);
-	} else {
-		iconstr = g_strdup(get_default_icon(desktop_file));
-	}
-	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 */
-	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]);
-
-			dbusmenu_menuitem_property_set(mi, DBUSMENU_MENUITEM_PROP_LABEL, indicator_desktop_shortcuts_nick_get_name(priv->ids, nicks[i]));
-			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) {
-		const gchar * default_name = NULL;
-		
-		if (seen_db_seen(priv->desktop)) {
-			default_name = get_default_name(priv->desktop);
-		} else {
-			default_name = get_default_setup(priv->desktop);
-		}
-
-		if (default_name == NULL) {
-			dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(li), DBUSMENU_MENUITEM_PROP_LABEL, launcher_menu_item_get_name(li));
-		} else {
-			dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(li), DBUSMENU_MENUITEM_PROP_LABEL, _(default_name));
-		}
-	}
-
-	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;
-}

=== removed file 'src/launcher-menu-item.h'
--- src/launcher-menu-item.h	2010-02-18 17:23:29 +0000
+++ src/launcher-menu-item.h	1970-01-01 00:00:00 +0000
@@ -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 <ted@xxxxxxxxxxxxx>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef __LAUNCHER_MENU_ITEM_H__
-#define __LAUNCHER_MENU_ITEM_H__
-
-#include <glib.h>
-#include <glib-object.h>
-
-#include <libdbusmenu-glib/menuitem.h>
-
-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__ */
-

=== removed file 'src/messages-service-dbus.c'
--- src/messages-service-dbus.c	2011-07-21 21:25:58 +0000
+++ src/messages-service-dbus.c	1970-01-01 00:00:00 +0000
@@ -1,267 +0,0 @@
-/*
-An indicator to show information that is in messaging applications
-that the user is using.
-
-Copyright 2009 Canonical Ltd.
-
-Authors:
-    Ted Gould <ted@xxxxxxxxxxxxx>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gio/gio.h>
-#include "messages-service-dbus.h"
-#include "dbus-data.h"
-#include "gen-messages-service.xml.h"
-
-enum {
-	ATTENTION_CHANGED,
-	ICON_CHANGED,
-	LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-typedef struct _MessageServiceDbusPrivate MessageServiceDbusPrivate;
-
-struct _MessageServiceDbusPrivate
-{
-	GDBusConnection * connection;
-	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);
-
-	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
-message_service_dbus_init (MessageServiceDbus *self)
-{
-	g_bus_get(G_BUS_TYPE_SESSION, NULL, connection_cb, 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;
-	}
-
-	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 {
-		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);
-		}
-	}
-	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;
-}

=== removed file 'src/messages-service-dbus.h'
--- src/messages-service-dbus.h	2009-08-26 15:35:56 +0000
+++ src/messages-service-dbus.h	1970-01-01 00:00:00 +0000
@@ -1,62 +0,0 @@
-/*
-An indicator to show information that is in messaging applications
-that the user is using.
-
-Copyright 2009 Canonical Ltd.
-
-Authors:
-    Ted Gould <ted@xxxxxxxxxxxxx>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef __MESSAGE_SERVICE_DBUS_H__
-#define __MESSAGE_SERVICE_DBUS_H__
-
-#include <glib.h>
-#include <glib-object.h>
-
-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"
-
-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);
-
-G_END_DECLS
-
-#endif

=== modified file 'src/messages-service.c'
--- src/messages-service.c	2011-08-25 01:26:02 +0000
+++ src/messages-service.c	2013-06-07 21:39:23 +0000
@@ -2,10 +2,11 @@
 An indicator to show information that is in messaging applications
 that the user is using.
 
-Copyright 2009 Canonical Ltd.
+Copyright 2012 Canonical Ltd.
 
 Authors:
     Ted Gould <ted@xxxxxxxxxxxxx>
+    Lars Uebernickel <lars.uebernickel@xxxxxxxxxxxxx>
 
 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 
@@ -20,1370 +21,360 @@
 with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#include <string.h>
+#include <config.h>
 #include <locale.h>
-#include <libintl.h>
-#include <config.h>
-#include <pango/pango-utils.h>
-#include <libindicate/listener.h>
 #include <libindicator/indicator-service.h>
 #include <gio/gio.h>
+#include <gio/gdesktopappinfo.h>
 #include <glib/gi18n.h>
 
-#include <libdbusmenu-glib/client.h>
-#include <libdbusmenu-glib/server.h>
-
-#include "im-menu-item.h"
-#include "app-menu-item.h"
-#include "launcher-menu-item.h"
+#include "app-section.h"
 #include "dbus-data.h"
-#include "dirs.h"
-#include "messages-service-dbus.h"
-#include "seen-db.h"
-#include "status-items.h"
-
-static IndicatorService * service = NULL;
-static IndicateListener * listener = NULL;
-static GList * serverList = NULL;
-static GList * launcherList = NULL;
-
-static DbusmenuMenuitem * root_menuitem = NULL;
-static DbusmenuMenuitem * status_separator = NULL;
-static DbusmenuMenuitem * clear_attention = NULL;
-static GMainLoop * mainloop = NULL;
-
-static MessageServiceDbus * dbus_interface = NULL;
-
-#define DESKTOP_FILE_GROUP        "Messaging Menu"
-#define DESKTOP_FILE_KEY_DESKTOP  "DesktopFile"
-
-static void server_shortcut_added (AppMenuItem * appitem, DbusmenuMenuitem * mi, gpointer data);
-static void server_shortcut_removed (AppMenuItem * appitem, DbusmenuMenuitem * mi, gpointer data);
-static void server_count_changed (AppMenuItem * appitem, guint count, gpointer data);
-static void server_name_changed (AppMenuItem * appitem, gchar * name, gpointer data);
-static void im_time_changed (ImMenuItem * imitem, glong seconds, gpointer data);
-static void resort_menu (DbusmenuMenuitem * menushell);
-static void indicator_removed (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gpointer data);
-static void check_eclipses (AppMenuItem * ai);
-static void remove_eclipses (AppMenuItem * ai);
-static gboolean build_launcher (gpointer data);
-static gboolean build_launcher_keyfile (gpointer data);
-static void build_launcher_core (const gchar * desktop);
-static gboolean build_launchers (gpointer data);
-static gboolean blacklist_init (gpointer data);
-static gboolean blacklist_add (gpointer data);
-static gchar * desktop_file_from_keyfile (const gchar * definition_file);
-static gboolean blacklist_keyfile_add (gpointer udata);
-static void blacklist_add_core (gchar * desktop, gchar * definition);
-static gboolean blacklist_remove (gpointer data);
-static void blacklist_dir_changed (GFileMonitor * monitor, GFile * file, GFile * other_file, GFileMonitorEvent event_type, gpointer user_data);
-static void app_dir_changed (GFileMonitor * monitor, GFile * file, GFile * other_file, GFileMonitorEvent event_type, gpointer user_data);
-static gboolean destroy_launcher (gpointer data);
-static void check_hidden (void);
-
-
-/*
- * Server List
- */
-
-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 * pas = INDICATE_LISTENER_SERVER_DBUS_NAME(pa->server);
-	const gchar * pbs = INDICATE_LISTENER_SERVER_DBUS_NAME(pb->server);
-
-	return g_strcmp0(pas, pbs);
-}
-
-static gint
-serverList_sort (gconstpointer a, gconstpointer b)
-{
-	serverList_t * pa, * pb;
-
-	pa = (serverList_t *)a;
-	pb = (serverList_t *)b;
-
-	const gchar * pan = app_menu_item_get_name(pa->menuitem);
-	const gchar * pbn = app_menu_item_get_name(pb->menuitem);
-
-	return g_strcmp0(pan, pbn);
-}
-
-/*
- * Item List
- */
-
-typedef struct _imList_t imList_t;
-struct _imList_t {
-	IndicateListenerServer * server;
-	IndicateListenerIndicator * indicator;
-	DbusmenuMenuitem * menuitem;
-	gulong timechange_cb;
-	gulong attentionchange_cb;
-};
-
-static gboolean
-imList_equal (gconstpointer a, gconstpointer b)
-{
-	imList_t * pa, * pb;
-
-	pa = (imList_t *)a;
-	pb = (imList_t *)b;
-
-	const gchar * pas = INDICATE_LISTENER_SERVER_DBUS_NAME(pa->server);
-	const gchar * pbs = INDICATE_LISTENER_SERVER_DBUS_NAME(pb->server);
-
-	guint pai = INDICATE_LISTENER_INDICATOR_ID(pa->indicator);
-	guint pbi = INDICATE_LISTENER_INDICATOR_ID(pb->indicator);
-
-	g_debug("\tComparing (%s %d) to (%s %d)", pas, pai, pbs, pbi);
-
-	return !((!g_strcmp0(pas, pbs)) && (pai == pbi));
-}
-
-static gint
-imList_sort (gconstpointer a, gconstpointer b)
-{
-	imList_t * pa, * pb;
-
-	pa = (imList_t *)a;
-	pb = (imList_t *)b;
-
-	return (gint)(im_menu_item_get_seconds(IM_MENU_ITEM(pb->menuitem)) - im_menu_item_get_seconds(IM_MENU_ITEM(pa->menuitem)));
-}
-
-/*
- * Launcher List
- */
-
-typedef struct _launcherList_t launcherList_t;
-struct _launcherList_t {
-	LauncherMenuItem * menuitem;
-	DbusmenuMenuitem * separator;
-	GList * appdiritems;
-};
-
-static gint
-launcherList_sort (gconstpointer a, gconstpointer b)
-{
-	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;
-}
-
-/*
- * 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;
-}
-
-/* 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;
-	/* Dump the file */
-	gchar * desktop;
-	g_file_get_contents(definition_file, &desktop, NULL, NULL);
-	if (desktop == NULL) {
-		g_warning("Couldn't get data out of: %s", definition_file);
-		return FALSE;
-	}
-
-	/* Clean up the data */
-	gchar * trimdesktop = pango_trim_string(desktop);
-	g_free(desktop);
-
-	blacklist_add_core(trimdesktop, definition_file);
-	g_free(trimdesktop);
-
-	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)
-{
-	/* Check for conflicts */
-	gpointer data = g_hash_table_lookup(blacklist, desktop);
-	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);
-		}
-
-		return;
-	}
-
-	/* Actually blacklist this thing */
-	g_hash_table_insert(blacklist, g_strdup(desktop), 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;
-		if (!g_strcmp0(desktop, launcher_menu_item_get_desktop(item->menuitem))) {
-			launcher_menu_item_set_eclipsed(item->menuitem, TRUE);
-			dbusmenu_menuitem_property_set_bool(item->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
-		}
-	}
-
-	check_hidden();
-	/* Shouldn't need a resort here as hiding shouldn't cause things to
-	   move other than this item disappearing. */
-
-	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);
-
+#include "gactionmuxer.h"
+#include "gsettingsstrv.h"
+#include "gmenuutils.h"
+#include "indicator-messages-service.h"
+
+#define NUM_STATUSES 5
+
+static GHashTable *applications;
+
+static IndicatorMessagesService *messages_service;
+static GSimpleActionGroup *actions;
+static GActionMuxer *action_muxer;
+static GMenu *toplevel_menu;
+static GMenu *menu;
+static GMenuModel *chat_section;
+static GSettings *settings;
+static gboolean draws_attention;
+static const gchar *global_status[6]; /* max 5: available, away, busy, invisible, offline */
+
+static gchar *
+indicator_messages_get_icon_name ()
+{
+	GString *name;
+	GIcon *icon;
+	gchar *iconstr;
+
+	name = g_string_new ("indicator-messages");
+
+	if (global_status[0] != NULL)
+	{
+		if (global_status[1] != NULL)
+			g_string_append (name, "-mixed");
+		else
+			g_string_append_printf (name, "-%s", global_status[0]);
+	}
+
+	if (draws_attention)
+		g_string_append (name, "-new");
+
+	icon = g_themed_icon_new (name->str);
+	g_themed_icon_append_name (G_THEMED_ICON (icon),
+				   draws_attention ? "indicator-messages-new"
+						   : "indicator-messages");
+
+	iconstr = g_icon_to_string (icon);
+
+	g_object_unref (icon);
+	g_string_free (name, TRUE);
+
+	return iconstr;
+}
+
+static void
+indicator_messages_update_icon ()
+{
+	GSimpleAction *messages;
+	gchar *icon;
+
+	messages = G_SIMPLE_ACTION (g_simple_action_group_lookup (actions, "messages"));
+	g_return_if_fail (messages != NULL);
+
+	icon = indicator_messages_get_icon_name ();
+	g_simple_action_set_state (messages, g_variant_new_string (icon));
+
+	g_free (icon);
+}
+
+static gchar *
+g_app_info_get_simple_id (GAppInfo *appinfo)
+{
+	const gchar *id;
+
+	id = g_app_info_get_id (appinfo);
+	if (!id)
+		return NULL;
+
+	if (g_str_has_suffix (id, ".desktop"))
+		return g_strndup (id, strlen (id) - 8);
+	else
+		return g_strdup (id);
+}
+
+static void
+actions_changed (GObject *object,
+		 GParamSpec *pspec,
+		 gpointer user_data)
+{
+	AppSection *section = APP_SECTION (object);
+	gchar *id;
+	GActionGroup *actions;
+
+	id = g_app_info_get_simple_id (app_section_get_app_info (section));
+	actions = app_section_get_actions (section);
+
+	g_action_muxer_insert (action_muxer, id, actions);
+	g_free (id);
+}
+
+
+static gboolean
+app_section_draws_attention (gpointer key,
+			     gpointer value,
+			     gpointer user_data)
+{
+	AppSection *section = value;
+	return app_section_get_draws_attention (section);
+}
+
+static void
+draws_attention_changed (GObject *object,
+			 GParamSpec *pspec,
+			 gpointer user_data)
+{
+	GSimpleAction *clear;
+
+	clear = G_SIMPLE_ACTION (g_simple_action_group_lookup (actions, "clear"));
+	g_return_if_fail (clear != NULL);
+
+	draws_attention = g_hash_table_find (applications, app_section_draws_attention, NULL) != NULL;
+
+	g_simple_action_set_enabled (clear, draws_attention);
+
+	indicator_messages_update_icon ();
+}
+
+static gboolean
+app_section_uses_chat (gpointer key,
+		       gpointer value,
+		       gpointer user_data)
+{
+	AppSection *section = value;
+	return app_section_get_uses_chat_status (section);
+}
+
+static void
+update_chat_section ()
+{
+	gboolean show_chat;
+	GMenuModel *first_section;
+
+	show_chat = g_hash_table_find (applications, app_section_uses_chat, NULL) != NULL;
+
+	first_section = g_menu_model_get_item_link (G_MENU_MODEL (menu), 0, G_MENU_LINK_SECTION);
+	if (first_section == chat_section) {
+		if (!show_chat)
+			g_menu_remove (menu, 0);
+	}
+	else {
+		if (show_chat)
+			g_menu_insert_section (menu, 0, NULL, chat_section);
+	}
+
+	if (first_section != NULL)
+		g_object_unref (first_section);
+
+	indicator_messages_update_icon ();
+}
+
+static void
+uses_chat_status_changed (GObject *object,
+			  GParamSpec *pspec,
+			  gpointer user_data)
+{
+	update_chat_section ();
+}
+
+static gboolean
+strv_contains (const gchar **strv,
+	       const gchar  *needle)
+{
+	const gchar **it;
+
+	it = strv;
+	while (*it != NULL && !g_str_equal (*it, needle))
+		it++;
+
+	return *it != NULL;
+}
+
+static void
+update_chat_status ()
+{
 	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)
-{
-	g_debug("Checking blacklist for: %s", desktop_file);
-	if (blacklist == NULL) return FALSE;
-
-	if (g_hash_table_lookup(blacklist, desktop_file)) {
-		g_debug("\tFound!");
-		return TRUE;
-	}
-
-	return FALSE;
-}
-
-/* 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
- */
-
-/* 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;
-}
-
-/* A new server has been created on the indicate bus.
-   We need to check to see if we like it.  And build
-   structures for it if so. */
-static void 
-server_added (IndicateListener * listener, IndicateListenerServer * server, gchar * type, gpointer data)
-{
-	g_debug("Server Added '%s' of type '%s'.", INDICATE_LISTENER_SERVER_DBUS_NAME(server), type);
-	if (type == NULL) {
-		return;
-	}
-
-	if (type[0] == '\0') {
-		return;
-	}
-
-	if (strncmp(type, "message", strlen("message"))) {
-		g_debug("\tServer type '%s' is not a message based type.", type);
-		return;
-	}
-
-	DbusmenuMenuitem * menushell = DBUSMENU_MENUITEM(data);
-	if (menushell == NULL) {
-		g_error("\tData in callback is not a menushell");
-		return;
-	}
-
-	/* Build the Menu item */
-	AppMenuItem * menuitem = app_menu_item_new(listener, server);
-
-	/* Build a possible server structure */
-	serverList_t * sl_item = g_new0(serverList_t, 1);
-	sl_item->server = server;
-	sl_item->menuitem = menuitem;
-	sl_item->imList = NULL;
-	sl_item->attention = FALSE;
-	sl_item->count = 0;
-
-	/* Incase we got an indicator first */
-	GList * alreadythere = g_list_find_custom(serverList, sl_item, serverList_equal);
-	if (alreadythere != NULL) {
-		/* Use the one we already had */
-		g_free(sl_item);
-		sl_item = (serverList_t *)alreadythere->data;
-		sl_item->menuitem = menuitem;
-		serverList = g_list_sort(serverList, serverList_sort);
-	} else {
-		/* Insert the new one in the list */
-		serverList = g_list_insert_sorted(serverList, sl_item, serverList_sort);
-	}
-
-	/* Build a separator */
-	sl_item->separator = dbusmenu_menuitem_new();
-	dbusmenu_menuitem_property_set(sl_item->separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
-
-	/* Connect the signals up to the menu item */
-	g_signal_connect(G_OBJECT(menuitem), APP_MENU_ITEM_SIGNAL_COUNT_CHANGED, G_CALLBACK(server_count_changed), sl_item);
-	g_signal_connect(G_OBJECT(menuitem), APP_MENU_ITEM_SIGNAL_NAME_CHANGED,  G_CALLBACK(server_name_changed),  menushell);
-	g_signal_connect(G_OBJECT(menuitem), APP_MENU_ITEM_SIGNAL_SHORTCUT_ADDED,  G_CALLBACK(server_shortcut_added),  menushell);
-	g_signal_connect(G_OBJECT(menuitem), APP_MENU_ITEM_SIGNAL_SHORTCUT_REMOVED,  G_CALLBACK(server_shortcut_removed),  menushell);
-
-	/* Put our new menu item in, with the separator behind it.
-	   resort_menu will take care of whether it should be hidden
-	   or not. */
-	dbusmenu_menuitem_child_append(menushell, DBUSMENU_MENUITEM(menuitem));
-
-	GList * shortcuts = app_menu_item_get_items(sl_item->menuitem);
-	while (shortcuts != NULL) {
-		DbusmenuMenuitem * mi = DBUSMENU_MENUITEM(shortcuts->data);
-		g_debug("\tAdding shortcut: %s", dbusmenu_menuitem_property_get(mi, DBUSMENU_MENUITEM_PROP_LABEL));
-		dbusmenu_menuitem_child_append(menushell, mi);
-		shortcuts = g_list_next(shortcuts);
-	}
-
-	dbusmenu_menuitem_child_append(menushell, DBUSMENU_MENUITEM(sl_item->separator));
-
-	resort_menu(menushell);
-	check_hidden();
-
-	return;
-}
-
-/* Server shortcut has been added */
-static void
-server_shortcut_added (AppMenuItem * appitem, DbusmenuMenuitem * mi, gpointer data)
-{
-	g_debug("Application Shortcut added: %s", mi != NULL ? dbusmenu_menuitem_property_get(mi, DBUSMENU_MENUITEM_PROP_LABEL) : "none");
-	DbusmenuMenuitem * shell = DBUSMENU_MENUITEM(data);
-	if (mi != NULL) {
-		dbusmenu_menuitem_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);
-	check_eclipses(appitem);
-	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);
-
-	/* Remove launchers this could be eclipsing */
-	remove_eclipses(sltp->menuitem);
-
-	/* If there is a menu item, let's get rid of it. */
-	if (sltp->menuitem != NULL) {
-		/* If there are shortcuts remove them */
-		GList * shortcuts = app_menu_item_get_items(sltp->menuitem);
-		while (shortcuts != NULL) {
-			g_debug("\tRemoving shortcut: %s", dbusmenu_menuitem_property_get(DBUSMENU_MENUITEM(shortcuts->data), DBUSMENU_MENUITEM_PROP_LABEL));
-			dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(shortcuts->data), DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
-			dbusmenu_menuitem_child_delete(DBUSMENU_MENUITEM(data), DBUSMENU_MENUITEM(shortcuts->data));
-			shortcuts = g_list_next(shortcuts);
-		}
-
-		g_debug("\tRemoving item");
-		dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(sltp->menuitem), DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
-		dbusmenu_menuitem_child_delete(DBUSMENU_MENUITEM(data), DBUSMENU_MENUITEM(sltp->menuitem));
-		g_object_unref(G_OBJECT(sltp->menuitem));
-	} else {
-		g_debug("\tNo menuitem");
-	}
-	
-	/* If there is a separator, let's get rid of it. */
-	if (sltp->separator != NULL) {
-		g_debug("\tRemoving separator");
-		dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(sltp->separator), DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
-		dbusmenu_menuitem_child_delete(DBUSMENU_MENUITEM(data), DBUSMENU_MENUITEM(sltp->separator));
-		g_object_unref(G_OBJECT(sltp->separator));
-	} else {
-		g_debug("\tNo separator");
-	}
-
-	if (sltp->attention) {
-		/* Check to see if this was the server causing the menu item to
-		   be lit up. */
-		check_attention();
-	}
-
-	g_free(sltp);
-
-	check_hidden();
-
-	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)))) {
-		msl->found = TRUE;
-		/* Return a position at the end of our shortcuts */
-		msl->position += g_list_length(app_menu_item_get_items(appmenu));		
-	} else {
-		msl->position++;
-	}
-
-	return;
-}
-
-static void
-check_hidden (void)
-{
-	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
-   menu functions will handle the cases where they don't move so this
-   is a good way to ensure everything is right. */
-static void
-resort_menu (DbusmenuMenuitem * menushell)
-{
-	guint position = 0;
-	GList * serverentry;
-	GList * launcherentry = launcherList;
-
-	g_debug("Reordering Menu:");
-	
-	if (DBUSMENU_IS_MENUITEM(status_separator)) {
-		position = dbusmenu_menuitem_get_position(status_separator, root_menuitem) + 1;
-		g_debug("\tPriming with location of status separator: %d", position);
-	}
-
-	for (serverentry = serverList; serverentry != NULL; serverentry = serverentry->next) {
-		serverList_t * si = (serverList_t *)serverentry->data;
-		
-		/* Looking to see if there are any launchers we need to insert
-		   into the menu structure.  We put as many as we need to. */
-		if (launcherentry != NULL) {
-			launcherList_t * li = (launcherList_t *)launcherentry->data;
-			while (launcherentry != NULL && g_strcmp0(launcher_menu_item_get_name(li->menuitem), app_menu_item_get_name(si->menuitem)) < 0) {
-				/* Putting the launcher item in */
-				g_debug("\tMoving launcher '%s' to position %d", launcher_menu_item_get_name(li->menuitem), position);
-				dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(li->menuitem), position);
-				position++;
-
-				/* Inserting the shortcuts from the launcher */
-				GList * shortcuts = launcher_menu_item_get_items(li->menuitem);
-				while (shortcuts != NULL) {
-					g_debug("\t\tMoving shortcut to position %d", position);
-					dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(shortcuts->data), position);
-					position++;
-					shortcuts = g_list_next(shortcuts);
-				}
-
-				/* Putting the launcher separator in */
-				g_debug("\tMoving launcher separator to position %d", position);
-				dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(li->separator), position);
-				if (!launcher_menu_item_get_eclipsed(li->menuitem)) {
-					/* Only clear the visiblity if we're not eclipsed */
-					dbusmenu_menuitem_property_set_bool(li->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
-				}
-				position++;
-
-				launcherentry = launcherentry->next;
-				if (launcherentry != NULL) {
-					li = (launcherList_t *)launcherentry->data;
-				}
-			}
-		}
-
-		/* Putting the app menu item in */
-		if (si->menuitem != NULL) {
-			g_debug("\tMoving app %s to position %d", INDICATE_LISTENER_SERVER_DBUS_NAME(si->server), position);
-			dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(si->menuitem), position);
-			position++;
-
-			/* Inserting the shortcuts from the launcher */
-			GList * shortcuts = app_menu_item_get_items(si->menuitem);
-			while (shortcuts != NULL) {
-				g_debug("\t\tMoving shortcut to position %d", position);
-				dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(shortcuts->data), position);
-				position++;
-				shortcuts = g_list_next(shortcuts);
-			}
-		}
-
-		/* Putting all the indicators that are related to this application
-		   after it. */
-		GList * imentry;
-		for (imentry = si->imList; imentry != NULL; imentry = imentry->next) {
-			imList_t * imi = (imList_t *)imentry->data;
-
-			if (imi->menuitem != NULL) {
-				g_debug("\tMoving indicator on %s id %d to position %d", INDICATE_LISTENER_SERVER_DBUS_NAME(imi->server), INDICATE_LISTENER_INDICATOR_ID(imi->indicator), position);
-
-				if (si->menuitem == NULL || !dbusmenu_menuitem_property_get_bool(DBUSMENU_MENUITEM(si->menuitem), DBUSMENU_MENUITEM_PROP_VISIBLE)) {
-					dbusmenu_menuitem_property_set_bool(imi->menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
-				} else {
-					dbusmenu_menuitem_property_set_bool(imi->menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
-				}
-
-				dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(imi->menuitem), position);
-				position++;
-			}
-		}
-
-		/* Lastly putting the separator in */
-		if (si->separator != NULL) {
-			g_debug("\tMoving app %s separator to position %d", INDICATE_LISTENER_SERVER_DBUS_NAME(si->server), position);
-
-			if (si->menuitem == NULL || !dbusmenu_menuitem_property_get_bool(DBUSMENU_MENUITEM(si->menuitem), DBUSMENU_MENUITEM_PROP_VISIBLE)) {
-				dbusmenu_menuitem_property_set_bool(si->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
-				/* Note, this isn't the last if we can't see it */
-			} else {
-				dbusmenu_menuitem_property_set_bool(si->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
-			}
-
-			dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(si->separator), position);
-			position++;
-		}
-	}
-
-	/* Put any leftover launchers in at the end of the list. */
-	while (launcherentry != NULL) {
-		launcherList_t * li = (launcherList_t *)launcherentry->data;
-
-		/* Putting the launcher in */
-		g_debug("\tMoving launcher '%s' to position %d", launcher_menu_item_get_name(li->menuitem), position);
-		dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(li->menuitem), position);
-		position++;
-
-		/* Inserting the shortcuts from the launcher */
-		GList * shortcuts = launcher_menu_item_get_items(li->menuitem);
-		while (shortcuts != NULL) {
-			g_debug("\t\tMoving shortcut to position %d", position);
-			dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(shortcuts->data), position);
-			position++;
-			shortcuts = g_list_next(shortcuts);
-		}
-
-		/* Putting the launcher separator in */
-		g_debug("\tMoving launcher separator to position %d", position);
-		dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(li->separator), position);
-		if (!launcher_menu_item_get_eclipsed(li->menuitem)) {
-			/* Only clear the visiblity if we're not eclipsed */
-			dbusmenu_menuitem_property_set_bool(li->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
-		}
-		position++;
-
-		launcherentry = launcherentry->next;
-	}
-
-	if (clear_attention != NULL) {
-		dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), clear_attention, position);
-		position++; /* Not needed, but reduce bugs on code tacked on here, compiler will remove */
-	}
-
-	return;
-}
-
-/* Responding to a new indicator showing up on the bus.  We
-   need to create a menuitem for it and start populating the
-   internal structures to track it. */
-static void
-indicator_added (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gpointer data)
-{
-	DbusmenuMenuitem * menushell = DBUSMENU_MENUITEM(data);
-	if (menushell == NULL) {
-		g_error("Data in callback is not a menushell");
-		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));
-	}
-
-	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;
-}
-
-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 */
-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;
-
-	if (blacklist_check(aidesktop)) return;
-
-	GList * llitem;
-	for (llitem = launcherList; llitem != NULL; llitem = llitem->next) {
-		launcherList_t * ll = (launcherList_t *)llitem->data;
-		const gchar * lidesktop = launcher_menu_item_get_desktop(ll->menuitem);
-
-		if (!g_strcmp0(aidesktop, lidesktop)) {
-			launcher_menu_item_set_eclipsed(ll->menuitem, FALSE);
-			dbusmenu_menuitem_property_set_bool(ll->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
-			break;
-		}
-	}
-
-	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
+	AppSection *section;
+	int pos;
+	GAction *status;
+
+	for (pos = 0; pos < G_N_ELEMENTS (global_status); pos++)
+		global_status[pos] = NULL;
+
+	pos = 0;
+	g_hash_table_iter_init (&iter, applications);
+	while (g_hash_table_iter_next (&iter, NULL, (gpointer) &section) &&
+	       pos < G_N_ELEMENTS (global_status))
+	{
+		const gchar *status_str = NULL;
+
+		status_str = app_section_get_status (section);
+		if (status_str != NULL && !strv_contains (global_status, status_str))
+			global_status[pos++] = status_str;
+	}
+
+	if (pos == 0)
+		global_status[0] = "offline";
+
+	status = g_simple_action_group_lookup (actions, "status");
+	g_return_if_fail (status != NULL);
+
+	g_simple_action_set_state (G_SIMPLE_ACTION (status), g_variant_new_strv (global_status, -1));
+
+	indicator_messages_update_icon ();
+}
+
+static void
+chat_status_changed (GObject    *object,
+		     GParamSpec *pspec,
+		     gpointer    user_data)
+{
+	update_chat_status ();
+}
+
+static void
+remove_section (AppSection  *section,
+		const gchar *id)
+{
+	int pos = g_menu_find_section (menu, app_section_get_menu (section));
+	if (pos >= 0)
+		g_menu_remove (menu, pos);
+	g_action_muxer_remove (action_muxer, id);
+
+	g_signal_handlers_disconnect_by_func (section, actions_changed, NULL);
+	g_signal_handlers_disconnect_by_func (section, draws_attention_changed, NULL);
+	g_signal_handlers_disconnect_by_func (section, uses_chat_status_changed, NULL);
+	g_signal_handlers_disconnect_by_func (section, chat_status_changed, NULL);
+	g_signal_handlers_disconnect_by_func (section, remove_section, NULL);
+
+	g_hash_table_remove (applications, id);
+
+	if (g_hash_table_size (applications) == 0 &&
+	    g_menu_model_get_n_items (G_MENU_MODEL (toplevel_menu)) == 1) {
+		g_menu_remove (toplevel_menu, 0);
+	}
+
+	update_chat_status ();
+	update_chat_section ();
+}
+
+static AppSection *
+add_application (const gchar *desktop_id)
+{
+	GDesktopAppInfo *appinfo;
+	gchar *id;
+	AppSection *section;
+
+	appinfo = g_desktop_app_info_new (desktop_id);
+	if (!appinfo) {
+		g_warning ("could not add '%s', there's no desktop file with that id", desktop_id);
+		return NULL;
+	}
+
+	id = g_app_info_get_simple_id (G_APP_INFO (appinfo));
+	section = g_hash_table_lookup (applications, id);
+
+	if (!section) {
+		GMenuItem *menuitem;
+
+		section = app_section_new(appinfo);
+		g_hash_table_insert (applications, g_strdup (id), section);
+
+		g_action_muxer_insert (action_muxer, id, app_section_get_actions (section));
+		g_signal_connect (section, "notify::actions",
+				  G_CALLBACK (actions_changed), NULL);
+		g_signal_connect (section, "notify::draws-attention",
+				  G_CALLBACK (draws_attention_changed), NULL);
+		g_signal_connect (section, "notify::uses-chat-status",
+				  G_CALLBACK (uses_chat_status_changed), NULL);
+		g_signal_connect (section, "notify::chat-status",
+				  G_CALLBACK (chat_status_changed), NULL);
+		g_signal_connect_data (section, "destroy",
+				       G_CALLBACK (remove_section),
+				       g_strdup (id),
+				       (GClosureNotify) g_free,
+				       0);
+
+		/* TODO insert it at the right position (alphabetically by application name) */
+		menuitem = g_menu_item_new_section (NULL, app_section_get_menu (section));
+		g_menu_item_set_attribute (menuitem, "action-namespace", "s", id);
+		g_menu_insert_item (menu, g_menu_model_get_n_items (G_MENU_MODEL (menu)) -1, menuitem);
+		g_object_unref (menuitem);
+	}
+
+	if (g_menu_model_get_n_items (G_MENU_MODEL (toplevel_menu)) == 0) {
+		GMenuItem *header;
+
+		header = g_menu_item_new (NULL, "messages");
+		g_menu_item_set_submenu (header, G_MENU_MODEL (menu));
+		g_menu_item_set_attribute (header, "x-canonical-accessible-description", "s", _("Messages"));
+		g_menu_append_item (toplevel_menu, header);
+
+		g_object_unref (header);
+	}
+
+	g_free (id);
+	g_object_unref (appinfo);
+	return section;
+}
+
+static void
+remove_application (const char *desktop_id)
+{
+	GDesktopAppInfo *appinfo;
+	gchar *id;
+	AppSection *section;
+
+	appinfo = g_desktop_app_info_new (desktop_id);
+	if (!appinfo) {
+		g_warning ("could not remove '%s', there's no desktop file with that id", desktop_id);
+		return;
+	}
+
+	id = g_app_info_get_simple_id (G_APP_INFO (appinfo));
+
+	section = g_hash_table_lookup (applications, id);
+	if (section) {
+		remove_section (section, id);
+	}
+	else {
+		g_warning ("could not remove '%s', it's not registered", desktop_id);
+	}
+	
+	g_free (id);
+	g_object_unref (appinfo);
+}
+
+/* This function turns a specific desktop id 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);
-
-	if (desktop == NULL) {
-		return FALSE;
-	}
-
-	gchar * trimdesktop = pango_trim_string(desktop);
-	g_free(desktop);
-	g_debug("\tcontents: %s", trimdesktop);
-
-	build_launcher_core(trimdesktop);
-	g_free(trimdesktop);
-	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);
-	}
-	return FALSE;
-}
-
-/* The core action of dealing with a desktop file that should
-   be a launcher */
-static void
-build_launcher_core (const gchar * desktop)
-{
-	/* Check to see if we already have a launcher */
-	GList * listitem;
-	for (listitem = launcherList; listitem != NULL; listitem = listitem->next) {
-		launcherList_t * li = (launcherList_t *)listitem->data;
-		if (!g_strcmp0(launcher_menu_item_get_desktop(li->menuitem), desktop)) {
-			break;
-		}
-	}
-
-	if (listitem == NULL) {
-		/* If not */
-		/* Build the item */
-		launcherList_t * ll = g_new0(launcherList_t, 1);
-		ll->menuitem = launcher_menu_item_new(desktop);
-		ll->appdiritems = g_list_append(NULL, g_strdup(desktop));
-
-		/* Build a separator */
-		ll->separator = dbusmenu_menuitem_new();
-		dbusmenu_menuitem_property_set(ll->separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
-
-		/* Add it to the list */
-		launcherList = g_list_insert_sorted(launcherList, ll, launcherList_sort);
-
-		/* Add it to the menu */
-		dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(ll->menuitem), DBUSMENU_MENUITEM_PROP_TYPE, APPLICATION_MENUITEM_TYPE);
-		dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(ll->menuitem));
-		GList * shortcuts = launcher_menu_item_get_items(ll->menuitem);
-		while (shortcuts != NULL) {
-			dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(shortcuts->data));
-			shortcuts = g_list_next(shortcuts);
-		}
-		dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(ll->separator));
-
-		/* If we're in the black list or we've gotten eclipsed
-		   by something else, hide the item and the separator. */
-		if (blacklist_check(launcher_menu_item_get_desktop(ll->menuitem)) ||
-				launcher_menu_item_get_eclipsed(ll->menuitem)) {
-			launcher_menu_item_set_eclipsed(ll->menuitem, TRUE);
-			dbusmenu_menuitem_property_set_bool(ll->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
-		}
-
-		/* Check to see if any of the current applications should
-		   be eclipsing us. */
-		GList * server;
-		for (server = serverList; server != NULL; server = g_list_next(server)) {
-			serverList_t * slt = (serverList_t *)server->data;
-			check_eclipses(slt->menuitem);
-		}
-
-		resort_menu(root_menuitem);
-		check_hidden();
-	} else {
-		/* If so add ourselves */
-		launcherList_t * ll = (launcherList_t *)listitem->data;
-		ll->appdiritems = g_list_append(ll->appdiritems, g_strdup(desktop));
-	}
-
-	return;
+	gchar *desktop_id = data;
+
+	add_application (desktop_id);
+
+	g_free (desktop_id);
+	return FALSE;
 }
 
 /* This function goes through all the launchers that we're
@@ -1393,86 +384,272 @@
 static gboolean
 build_launchers (gpointer data)
 {
-	gchar * directory = (gchar *)data;
-
-	if (!g_file_test(directory, G_FILE_TEST_IS_DIR)) {
-		return FALSE;
-	}
-
-	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);
-	}
-
-	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);
-		}
-	}
-
-	g_dir_close(dir);
-	launcherList = g_list_sort(launcherList, launcherList_sort);
+	gchar **applications = g_settings_get_strv (settings, "applications");
+	gchar **app;
+
+	g_return_val_if_fail (applications != NULL, FALSE);
+
+	for (app = applications; *app; app++)
+	{
+		g_idle_add(build_launcher, g_strdup (*app));
+	}
+
+	g_strfreev (applications);
 	return FALSE;
 }
 
 static void 
 service_shutdown (IndicatorService * service, gpointer user_data)
 {
+	GMainLoop *mainloop = user_data;
+
 	g_warning("Shutting down service!");
 	g_main_loop_quit(mainloop);
-	return;
-}
-
-/* Respond to changing status by updating the icon that
-   is on the panel */
-static void
-status_update_callback (void)
-{
-	return;
-}
-
-/* The clear attention item has been clicked on, what to do? */
-static void
-clear_attention_activate (DbusmenuMenuitem * mi, guint timestamp, MessageServiceDbus * dbus)
-{
-	message_service_dbus_set_attention(dbus, FALSE);
-	return;
-}
-
-/* Handle an update of the active state to ensure that we're
-   only enabled when we could do something. */
-static void
-clear_attention_handler (MessageServiceDbus * msd, gboolean attention, DbusmenuMenuitem * clearitem)
-{
-	dbusmenu_menuitem_property_set_bool(clearitem, DBUSMENU_MENUITEM_PROP_ENABLED, attention);
-	return;
-}
-
-/* Oh, if you don't know what main() is for
-   we really shouldn't be talking. */
+}
+
+static void
+app_section_remove_attention (gpointer key,
+			      gpointer value,
+			      gpointer user_data)
+{
+	AppSection *section = value;
+	app_section_clear_draws_attention (section);
+}
+
+static void
+clear_action_activate (GSimpleAction *simple,
+		       GVariant *param,
+		       gpointer user_data)
+{
+	g_hash_table_foreach (applications, app_section_remove_attention, NULL);
+}
+
+static void
+status_action_activate (GSimpleAction *action,
+			GVariant *parameter,
+			gpointer user_data)
+{
+	const gchar *status;
+
+	status = g_variant_get_string (parameter, NULL);
+
+	indicator_messages_service_emit_status_changed (messages_service, status);
+}
+
+static void
+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 = 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 (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);
+}
+
+static void
+application_stopped_running (IndicatorMessagesService *service,
+			     GDBusMethodInvocation    *invocation,
+			     const gchar              *desktop_id,
+			     gpointer                  user_data)
+{
+	GDesktopAppInfo *appinfo;
+	gchar *id;
+	AppSection *section;
+
+	indicator_messages_service_complete_application_stopped_running (service, invocation);
+
+	if (!(appinfo = g_desktop_app_info_new (desktop_id)))
+		return;
+
+	id = g_app_info_get_simple_id (G_APP_INFO (appinfo));
+	section = g_hash_table_lookup (applications, id);
+	app_section_unset_object_path (section);
+
+	g_free (id);
+	g_object_unref (appinfo);
+}
+
+static void
+set_status (IndicatorMessagesService *service,
+	    GDBusMethodInvocation *invocation,
+	    const gchar *desktop_id,
+	    const gchar *status_str,
+	    gpointer user_data)
+{
+	GDesktopAppInfo *appinfo;
+	gchar *id;
+	AppSection *section;
+
+	g_return_if_fail (g_str_equal (status_str, "available") ||
+			  g_str_equal (status_str, "away")||
+			  g_str_equal (status_str, "busy") ||
+			  g_str_equal (status_str, "invisible") ||
+			  g_str_equal (status_str, "offline"));
+
+	appinfo = g_desktop_app_info_new (desktop_id);
+	if (!appinfo) {
+		g_warning ("could not set status for '%s', there's no desktop file with that id", desktop_id);
+		return;
+	}
+
+	id = g_app_info_get_simple_id (G_APP_INFO (appinfo));
+	section = g_hash_table_lookup (applications, id);
+	if (section != NULL)
+		app_section_set_status (section, status_str);
+
+	indicator_messages_service_complete_set_status (service, invocation);
+
+	g_free (id);
+	g_object_unref (appinfo);
+}
+
+static GSimpleActionGroup *
+create_action_group (void)
+{
+	GSimpleActionGroup *actions;
+	GSimpleAction *messages;
+	GSimpleAction *clear;
+	GSimpleAction *status;
+	const gchar *default_status[] = { "offline", NULL };
+	gchar *icon;
+
+	actions = g_simple_action_group_new ();
+
+	/* state of the messages action is its icon name */
+	icon = indicator_messages_get_icon_name ();
+	messages = g_simple_action_new_stateful ("messages", G_VARIANT_TYPE ("s"),
+						 g_variant_new_string (icon));
+
+	status = g_simple_action_new_stateful ("status", G_VARIANT_TYPE ("s"),
+					       g_variant_new_strv (default_status, -1));
+	g_signal_connect (status, "activate", G_CALLBACK (status_action_activate), NULL);
+
+	clear = g_simple_action_new ("clear", NULL);
+	g_simple_action_set_enabled (clear, FALSE);
+	g_signal_connect (clear, "activate", G_CALLBACK (clear_action_activate), NULL);
+
+	g_simple_action_group_insert (actions, G_ACTION (messages));
+	g_simple_action_group_insert (actions, G_ACTION (status));
+	g_simple_action_group_insert (actions, G_ACTION (clear));
+
+	g_free (icon);
+	return actions;
+}
+
+static GMenuModel *
+create_status_section (void)
+{
+	GMenu *menu;
+	GMenuItem *item;
+	struct status_item {
+		gchar *label;
+		gchar *action;
+		gchar *icon_name;
+	} status_items[] = {
+		{ _("Available"), "status::available", "user-available" },
+		{ _("Away"),      "status::away",      "user-away" },
+		{ _("Busy"),      "status::busy",      "user-busy" },
+		{ _("Invisible"), "status::invisible", "user-invisible" },
+		{ _("Offline"),   "status::offline",   "user-offline" }
+	};
+	int i;
+
+	menu = g_menu_new ();
+
+	item = g_menu_item_new (NULL, NULL);
+	g_menu_item_set_attribute (item, "x-canonical-type", "s", "IdoMenuItem");
+
+	for (i = 0; i < G_N_ELEMENTS (status_items); i++) {
+		g_menu_item_set_label (item, status_items[i].label);
+		g_menu_item_set_detailed_action (item, status_items[i].action);
+		g_menu_item_set_attribute (item, "x-canonical-icon", "s", status_items[i].icon_name);
+		g_menu_append_item (menu, item);
+	}
+
+	g_object_unref (item);
+	return G_MENU_MODEL (menu);
+}
+
+static void
+got_bus (GObject *object,
+	 GAsyncResult * res,
+	 gpointer user_data)
+{
+	GDBusConnection *bus;
+	GError *error = NULL;
+
+	bus = g_bus_get_finish (res, &error);
+	if (!bus) {
+		g_warning ("unable to connect to the session bus: %s", error->message);
+		g_error_free (error);
+		return;
+	}
+
+	g_dbus_connection_export_action_group (bus, INDICATOR_MESSAGES_DBUS_OBJECT,
+                                               G_ACTION_GROUP (action_muxer), &error);
+	if (error) {
+		g_warning ("unable to export action group on dbus: %s", error->message);
+		g_error_free (error);
+		return;
+	}
+
+	g_dbus_connection_export_menu_model (bus, INDICATOR_MESSAGES_DBUS_OBJECT,
+					     G_MENU_MODEL (toplevel_menu), &error);
+	if (error) {
+		g_warning ("unable to export menu on dbus: %s", error->message);
+		g_error_free (error);
+		return;
+	}
+
+	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);
+}
+
 int
 main (int argc, char ** argv)
 {
-	/* Glib init */
-	g_type_init();
+	GMainLoop * mainloop;
+	IndicatorService * service;
+
+	mainloop = g_main_loop_new (NULL, FALSE);
 
 	/* Create the Indicator Service interface */
 	service = indicator_service_new_version(INDICATOR_MESSAGES_DBUS_NAME, 1);
-	g_signal_connect(service, INDICATOR_SERVICE_SIGNAL_SHUTDOWN, G_CALLBACK(service_shutdown), NULL);
+	g_signal_connect(service, INDICATOR_SERVICE_SIGNAL_SHUTDOWN, G_CALLBACK(service_shutdown), mainloop);
 
 	/* Setting up i18n and gettext.  Apparently, we need
 	   all of these. */
@@ -1480,58 +657,43 @@
 	bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
 	textdomain (GETTEXT_PACKAGE);
 
-	/* Create the Seen DB */
-	seen_db_init();
-
 	/* Bring up the service DBus interface */
-	dbus_interface = message_service_dbus_new();
-
-	/* Build the base menu */
-	root_menuitem = dbusmenu_menuitem_new();
-	DbusmenuServer * server = dbusmenu_server_new(INDICATOR_MESSAGES_DBUS_OBJECT);
-	dbusmenu_server_set_root(server, root_menuitem);
-
-	/* Add status items */
-	GList * statusitems = status_items_build(&status_update_callback);
-	while (statusitems != NULL) {
-		dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(statusitems->data));
-		statusitems = g_list_next(statusitems);
-	}
-	status_separator = dbusmenu_menuitem_new();
-	dbusmenu_menuitem_property_set(status_separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
-	dbusmenu_menuitem_child_append(root_menuitem, status_separator);
-
-	/* Add in the clear attention item */
-	clear_attention = dbusmenu_menuitem_new();
-	dbusmenu_menuitem_property_set(clear_attention, DBUSMENU_MENUITEM_PROP_LABEL, _("Clear"));
-	dbusmenu_menuitem_child_append(root_menuitem, clear_attention);
-	g_signal_connect(G_OBJECT(dbus_interface), MESSAGE_SERVICE_DBUS_SIGNAL_ATTENTION_CHANGED, G_CALLBACK(clear_attention_handler), clear_attention);
-	g_signal_connect(G_OBJECT(clear_attention), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(clear_attention_activate), dbus_interface);
-
-	/* Start up the libindicate listener */
-	listener = indicate_listener_ref_default();
-	serverList = NULL;
-
-	g_signal_connect(listener, INDICATE_LISTENER_SIGNAL_INDICATOR_ADDED, G_CALLBACK(indicator_added), root_menuitem);
-	g_signal_connect(listener, INDICATE_LISTENER_SIGNAL_INDICATOR_REMOVED, G_CALLBACK(indicator_removed), root_menuitem);
-	g_signal_connect(listener, INDICATE_LISTENER_SIGNAL_SERVER_ADDED, G_CALLBACK(server_added), root_menuitem);
-	g_signal_connect(listener, INDICATE_LISTENER_SIGNAL_SERVER_REMOVED, G_CALLBACK(server_removed), root_menuitem);
-
-	/* Find launchers by looking through the config directories
-	   in the idle loop */
-	g_idle_add(blacklist_init, NULL);
-	g_idle_add(build_launchers, SYSTEM_APPS_DIR);
-	g_idle_add(build_launchers, SYSTEM_APPS_DIR_OLD);
-	gchar * userdir = g_build_filename(g_get_user_config_dir(), USER_APPS_DIR, NULL);
-	g_idle_add(build_launchers, userdir);
-
-	/* Let's run a mainloop */
-	mainloop = g_main_loop_new(NULL, FALSE);
+	messages_service = indicator_messages_service_skeleton_new ();
+
+	g_bus_get (G_BUS_TYPE_SESSION, NULL, got_bus, NULL);
+
+	actions = create_action_group ();
+
+	action_muxer = g_action_muxer_new ();
+	g_action_muxer_insert (action_muxer, NULL, G_ACTION_GROUP (actions));
+
+	g_signal_connect (messages_service, "handle-register-application",
+			  G_CALLBACK (register_application), NULL);
+	g_signal_connect (messages_service, "handle-unregister-application",
+			  G_CALLBACK (unregister_application), NULL);
+	g_signal_connect (messages_service, "handle-application-stopped-running",
+			  G_CALLBACK (application_stopped_running), NULL);
+	g_signal_connect (messages_service, "handle-set-status",
+			  G_CALLBACK (set_status), NULL);
+
+	menu = g_menu_new ();
+	chat_section = create_status_section ();
+	g_menu_append (menu, _("Clear"), "clear");
+
+	toplevel_menu = g_menu_new ();
+
+	settings = g_settings_new ("com.canonical.indicator.messages");
+
+	applications = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+
+	g_idle_add(build_launchers, NULL);
+
 	g_main_loop_run(mainloop);
 
 	/* Clean up */
-	status_items_cleanup();
-	g_free(userdir);
-
+	g_object_unref (messages_service);
+	g_object_unref (chat_section);
+	g_object_unref (settings);
+	g_hash_table_unref (applications);
 	return 0;
 }

=== modified file 'src/messages-service.xml'
--- src/messages-service.xml	2011-07-21 21:17:09 +0000
+++ src/messages-service.xml	2013-06-07 21:39:23 +0000
@@ -2,21 +2,26 @@
 <node name="/">
 	<interface name="com.canonical.indicator.messages.service">
 
-<!-- Methods -->
-		<method name="AttentionRequested">
-			<arg type="b" name="dot" direction="out" />
-		</method>
-		<method name="IconShown">
-			<arg type="b" name="hidden" direction="out" />
-		</method>
-		<method name="ClearAttention" />
-
-<!-- Signals -->
-		<signal name="AttentionChanged">
-			<arg type="b" name="dot" direction="out" />
-		</signal>
-		<signal name="IconChanged">
-			<arg type="b" name="hidden" direction="out" />
+		<method name="RegisterApplication">
+		    <arg type="s" name="desktop_id" direction="in" />
+		    <arg type="o" name="menu_path" direction="in" />
+		</method>
+
+		<method name="UnregisterApplication">
+		    <arg type="s" name="desktop_id" direction="in" />
+		</method>
+
+		<method name="ApplicationStoppedRunning">
+			<arg type="s" name="desktop_id" direction="in" />
+		</method>
+
+		<method name="SetStatus">
+			<arg type="s" name="desktop_id" direction="in" />
+			<arg type="s" name="status" direction="in" />
+		</method>
+
+		<signal name="StatusChanged">
+			<arg type="s" name="status" direction="in" />
 		</signal>
 
 	</interface>

=== removed file 'src/seen-db.c'
--- src/seen-db.c	2010-03-25 15:25:13 +0000
+++ src/seen-db.c	1970-01-01 00:00:00 +0000
@@ -1,177 +0,0 @@
-/*
-A small database of which desktop files we've seen.
-
-Copyright 2010 Canonical Ltd.
-
-Authors:
-    Ted Gould <ted@xxxxxxxxxxxxx>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-#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));
-}

=== removed file 'src/seen-db.h'
--- src/seen-db.h	2010-03-25 02:26:07 +0000
+++ src/seen-db.h	1970-01-01 00:00:00 +0000
@@ -1,31 +0,0 @@
-/*
-A small database of which desktop files we've seen.
-
-Copyright 2010 Canonical Ltd.
-
-Authors:
-    Ted Gould <ted@xxxxxxxxxxxxx>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef SEEN_DB_H__
-#define SEEN_DB_H__ 1
-
-#include <glib.h>
-
-void seen_db_init(void);
-void seen_db_add (const gchar * desktop);
-gboolean seen_db_seen (const gchar * desktop);
-
-#endif /* SEEN_DB_H__ */

=== removed file 'src/status-items.c'
--- src/status-items.c	2011-07-13 20:17:58 +0000
+++ src/status-items.c	1970-01-01 00:00:00 +0000
@@ -1,314 +0,0 @@
-/*
-Code to build and maintain the status adjustment menuitems.
-
-Copyright 2011 Canonical Ltd.
-
-Authors:
-    Ted Gould <ted@xxxxxxxxxxxxx>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <glib.h>
-#include <glib/gi18n.h>
-#include <gio/gio.h>
-#include <libdbusmenu-glib/dbusmenu-glib.h>
-
-#include "status-items.h"
-#include "status-provider.h"
-
-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 (DbusmenuMenuitem * item, guint timestamp, gpointer pstatus);
-
-/* Globals */
-static StatusProviderStatus current_status = STATUS_PROVIDER_STATUS_DISCONNECTED;
-static GList * menuitems = NULL;
-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)
-{
-	int i;
-	for (i = STATUS_PROVIDER_STATUS_ONLINE; i < STATUS_PROVIDER_STATUS_DISCONNECTED; i++) {
-		DbusmenuMenuitem * item = dbusmenu_menuitem_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]);
-
-		dbusmenu_menuitem_property_set_bool(item, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
-		dbusmenu_menuitem_property_set_bool(item, DBUSMENU_MENUITEM_PROP_ENABLED, FALSE);
-
-		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_signal_connect(G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(user_status_change), GINT_TO_POINTER(i));
-
-		menuitems = g_list_append(menuitems, 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);
-	} else {
-		g_idle_add(provider_directory_parse, (gpointer)status_providers_env);
-	}
-
-	return menuitems;
-}
-
-/* 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;
-
-	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);
-		}
-	}
-
-	return;
-}
-
-/* Handle the user requesting a status change */
-static void
-user_status_change (DbusmenuMenuitem * item, guint timestamp, gpointer pstatus)
-{
-	StatusProviderStatus status = GPOINTER_TO_INT(pstatus);
-	GList * provider;
-
-	/* 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 = (gchar *)dir;
-
-	if (!g_file_test(provider, G_FILE_TEST_EXISTS)) {
-		goto exit_final;
-	}
-
-	g_debug("Loading status provider: %s", provider);
-
-	GModule * module;
-
-	module = g_module_open(provider, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
-	if (module == NULL) {
-		g_warning("Unable to module for: %s", provider);
-		goto exit_module_fail;
-	}
-
-	/* Got it */
-	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);
-		goto exit_module_fail;
-	}
-
-	GType provider_type = type_func();
-	if (provider_type == 0) {
-		g_warning("Unable to create type from: %s", provider);
-		goto exit_module_fail;
-	}
-
-	StatusProvider * sprovider = STATUS_PROVIDER(g_object_new(provider_type, NULL));
-	if (sprovider == NULL) {
-		g_warning("Unable to build provider from: %s", provider);
-		goto exit_module_fail;
-	}
-
-	/* 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 close automatically. */
-	g_object_set_data_full(G_OBJECT(sprovider), "status-provider-module", module, module_destroy_in_idle);
-
-	status_providers = g_list_prepend(status_providers, sprovider);
-
-	/* Force and update every time just so we know we're
-	   in a consistent state*/
-	update_status();
-
-	goto exit_final;
-
-exit_module_fail:
-	g_module_close(module);
-
-exit_final:
-	g_free(provider);
-	return FALSE;
-}

=== removed file 'src/status-items.h'
--- src/status-items.h	2011-07-13 20:17:58 +0000
+++ src/status-items.h	1970-01-01 00:00:00 +0000
@@ -1,38 +0,0 @@
-/*
-Code to build and maintain the status adjustment menuitems.
-
-Copyright 2011 Canonical Ltd.
-
-Authors:
-    Ted Gould <ted@xxxxxxxxxxxxx>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef __STATUS_ITEMS_H__
-#define __STATUS_ITEMS_H__
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-typedef void (*StatusUpdateFunc) (void);
-
-GList * status_items_build (StatusUpdateFunc update_func);
-const gchar * status_current_panel_icon (gboolean alert);
-void status_items_cleanup (void);
-
-G_END_DECLS
-
-#endif /* __STATUS_ITEMS_H__ */
-

=== removed file 'src/status-provider-emesene.c'
--- src/status-provider-emesene.c	2011-07-29 12:25:03 +0000
+++ src/status-provider-emesene.c	1970-01-01 00:00:00 +0000
@@ -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 <stefano.candori@xxxxxxxxx>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "status-provider.h"
-#include "status-provider-emesene.h"
-
-#include <dbus/dbus-glib.h>
-
-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];
-}

=== removed file 'src/status-provider-emesene.h'
--- src/status-provider-emesene.h	2011-06-22 20:42:44 +0000
+++ src/status-provider-emesene.h	1970-01-01 00:00:00 +0000
@@ -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 <stefano.candori@xxxxxxxxx>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef __STATUS_PROVIDER_EMESENE_H__
-#define __STATUS_PROVIDER_EMESENE_H__
-
-#include <glib.h>
-#include <glib-object.h>
-
-#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

=== removed file 'src/status-provider-mc5.c'
--- src/status-provider-mc5.c	2011-07-02 12:15:22 +0000
+++ src/status-provider-mc5.c	1970-01-01 00:00:00 +0000
@@ -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 <ted@xxxxxxxxxxxxx>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <telepathy-glib/account-manager.h>
-
-#include "status-provider.h"
-#include "status-provider-mc5.h"
-#include "status-provider-mc5-marshal.h"
-
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-bindings.h>
-
-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_DISCONNECTED;
-	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_DISCONNECTED;
-		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_DISCONNECTED;
-	}
-
-	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;
-}
-

=== removed file 'src/status-provider-mc5.h'
--- src/status-provider-mc5.h	2011-06-22 20:42:44 +0000
+++ src/status-provider-mc5.h	1970-01-01 00:00:00 +0000
@@ -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 <ted@xxxxxxxxxxxxx>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef __STATUS_PROVIDER_MC5_H__
-#define __STATUS_PROVIDER_MC5_H__
-
-#include <glib.h>
-#include <glib-object.h>
-
-#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

=== removed file 'src/status-provider-mc5.list'
--- src/status-provider-mc5.list	2011-06-22 20:42:44 +0000
+++ src/status-provider-mc5.list	1970-01-01 00:00:00 +0000
@@ -1,1 +0,0 @@
-VOID:UINT,STRING

=== removed file 'src/status-provider-pidgin.c'
--- src/status-provider-pidgin.c	2011-07-02 12:15:22 +0000
+++ src/status-provider-pidgin.c	1970-01-01 00:00:00 +0000
@@ -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 <ted@xxxxxxxxxxxxx>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "status-provider.h"
-#include "status-provider-pidgin.h"
-#include "status-provider-pidgin-marshal.h"
-
-#include <dbus/dbus-glib.h>
-
-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];
-}

=== removed file 'src/status-provider-pidgin.h'
--- src/status-provider-pidgin.h	2011-06-22 20:42:44 +0000
+++ src/status-provider-pidgin.h	1970-01-01 00:00:00 +0000
@@ -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 <ted@xxxxxxxxxxxxx>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef __STATUS_PROVIDER_PIDGIN_H__
-#define __STATUS_PROVIDER_PIDGIN_H__
-
-#include <glib.h>
-#include <glib-object.h>
-
-#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

=== removed file 'src/status-provider-pidgin.list'
--- src/status-provider-pidgin.list	2011-06-22 20:42:44 +0000
+++ src/status-provider-pidgin.list	1970-01-01 00:00:00 +0000
@@ -1,1 +0,0 @@
-VOID:INT,INT

=== removed file 'src/status-provider-telepathy.c'
--- src/status-provider-telepathy.c	2011-07-02 12:15:22 +0000
+++ src/status-provider-telepathy.c	1970-01-01 00:00:00 +0000
@@ -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 <ted@xxxxxxxxxxxxx>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "status-provider.h"
-#include "status-provider-telepathy.h"
-#include "status-provider-telepathy-marshal.h"
-
-#include <dbus/dbus-glib.h>
-
-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, &priv->mc_status,
-	                        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;
-}

=== removed file 'src/status-provider-telepathy.h'
--- src/status-provider-telepathy.h	2011-06-22 20:42:44 +0000
+++ src/status-provider-telepathy.h	1970-01-01 00:00:00 +0000
@@ -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 <ted@xxxxxxxxxxxxx>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef __STATUS_PROVIDER_TELEPATHY_H__
-#define __STATUS_PROVIDER_TELEPATHY_H__
-
-#include <glib.h>
-#include <glib-object.h>
-
-#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

=== removed file 'src/status-provider-telepathy.list'
--- src/status-provider-telepathy.list	2011-06-22 20:42:44 +0000
+++ src/status-provider-telepathy.list	1970-01-01 00:00:00 +0000
@@ -1,1 +0,0 @@
-VOID:UINT,STRING

=== removed file 'src/status-provider.c'
--- src/status-provider.c	2011-06-22 20:42:44 +0000
+++ src/status-provider.c	1970-01-01 00:00:00 +0000
@@ -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 <ted@xxxxxxxxxxxxx>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-#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);
-}
-

=== removed file 'src/status-provider.h'
--- src/status-provider.h	2011-07-02 12:15:22 +0000
+++ src/status-provider.h	1970-01-01 00:00:00 +0000
@@ -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 <ted@xxxxxxxxxxxxx>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef __STATUS_PROVIDER_H__
-#define __STATUS_PROVIDER_H__
-
-#include <glib.h>
-#include <glib-object.h>
-
-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

=== added file 'test/Makefile.am'
--- test/Makefile.am	1970-01-01 00:00:00 +0000
+++ test/Makefile.am	2013-06-07 21:39:23 +0000
@@ -0,0 +1,78 @@
+
+check_LIBRARIES = libgtest.a
+check_PROGRAMS = test-gactionmuxer
+
+TESTS = $(check_PROGRAMS)
+
+AM_CPPFLAGS = $(GTEST_CPPFLAGS) \
+	-I${top_srcdir}/src
+
+nodist_libgtest_a_SOURCES = \
+	$(GTEST_SOURCE)/src/gtest-all.cc \
+	$(GTEST_SOURCE)/src/gtest_main.cc
+libgtest_a_CPPFLAGS = \
+	$(GTEST_CPPFLAGS) -w \
+	$(AM_CPPFLAGS)
+libgtest_a_CXXFLAGS = \
+	$(AM_CXXFLAGS)
+
+
+test_gactionmuxer_SOURCES = \
+	test-gactionmuxer.cpp
+
+test_gactionmuxer_CPPFLAGS = \
+	$(APPLET_CFLAGS) \
+	$(AM_CPPFLAGS)
+
+test_gactionmuxer_LDADD = \
+	$(APPLET_LIBS) \
+	libindicator-messages-service.la \
+	libgtest.a
+
+
+######################################
+# Lib containing code under test
+######################################
+
+noinst_LTLIBRARIES = \
+	libindicator-messages-service.la
+
+libindicator_messages_service_la_SOURCES = \
+	$(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 \
+	$(top_srcdir)/src/gactionmuxer.h
+	$(top_srcdir)/src/dbus-data.h
+
+libindicator_messages_service_ladir = \
+	$(includedir)/libindicator-messages-service/
+
+libindicator_messages_service_la_CFLAGS = \
+	$(APPLET_CFLAGS) \
+	$(COVERAGE_CFLAGS) \
+	-I$(top_builddir)/src \
+	-Wall \
+	-Wl,-Bsymbolic-functions \
+	-Wl,-z,defs \
+	-Wl,--as-needed \
+	-Werror \
+	-DG_LOG_DOMAIN=\"Indicator-Messages\"
+
+libindicator_messages_service_la_LIBADD = \
+	$(APPLET_LIBS)
+
+libindicator_messages_service_la_LDFLAGS = \
+	$(COVERAGE_LDFLAGS)
+
+######################################
+# Test client with dbusmock
+######################################
+
+TESTS_ENVIRONMENT = \
+	export LD_LIBRARY_PATH=$(top_builddir)/libmessaging-menu/.libs; \
+	export GI_TYPELIB_PATH=$(top_builddir)/libmessaging-menu; \
+	export XDG_DATA_DIRS=$(abs_srcdir);
+
+TESTS += test-client.py

=== added directory 'test/applications'
=== added file 'test/applications/test.desktop'
--- test/applications/test.desktop	1970-01-01 00:00:00 +0000
+++ test/applications/test.desktop	2013-06-07 21:39:23 +0000
@@ -0,0 +1,2 @@
+[Desktop Entry]
+Type=Application

=== modified file 'test/indicator-messages-service-activate.c'
--- test/indicator-messages-service-activate.c	2009-05-28 15:29:41 +0000
+++ test/indicator-messages-service-activate.c	2013-06-07 21:39:23 +0000
@@ -28,8 +28,6 @@
 int
 main (int argc, char ** argv)
 {
-	g_type_init();
-
 	guint returnval = 0;
 	GError * error = NULL;
 

=== added file 'test/test-client.py'
--- test/test-client.py	1970-01-01 00:00:00 +0000
+++ test/test-client.py	2013-06-07 21:39:23 +0000
@@ -0,0 +1,75 @@
+#!/usr/bin/env python3
+
+import unittest
+import dbus
+from dbus.mainloop.glib import DBusGMainLoop
+import dbusmock
+import subprocess
+from gi.repository import GLib, Gio, MessagingMenu
+
+DBusGMainLoop(set_as_default=True)
+
+class MessagingMenuTest(dbusmock.DBusTestCase):
+    @classmethod
+    def setUpClass(klass):
+        klass.start_session_bus()
+        klass.bus = klass.get_dbus(False)
+
+    def setUp(self):
+        name = 'com.canonical.indicator.messages'
+        obj_path = '/com/canonical/indicator/messages/service'
+        iface = 'com.canonical.indicator.messages.service