← Back to team overview

ayatana-commits team mailing list archive

[Merge] lp:~ted/indicator-application/label-in-the-lib into lp:indicator-application

 

Ted Gould has proposed merging lp:~ted/indicator-application/label-in-the-lib into lp:indicator-application.

Requested reviews:
  Indicator Applet Developers (indicator-applet-developers)


Label support for libappindicator.
-- 
https://code.launchpad.net/~ted/indicator-application/label-in-the-lib/+merge/31886
Your team ayatana-commits is subscribed to branch lp:indicator-application.
=== modified file '.bzrignore'
--- .bzrignore	2010-07-12 18:58:37 +0000
+++ .bzrignore	2010-08-05 20:31:14 +0000
@@ -111,3 +111,5 @@
 src/notification-approver-server.h
 tests/test-approver
 tests/test-approver-tester
+bindings/mono/policy.0.0.appindicator-sharp.config
+bindings/mono/policy.0.0.appindicator-sharp.dll

=== modified file 'docs/reference/libappindicator-sections.txt'
--- docs/reference/libappindicator-sections.txt	2010-01-13 22:23:08 +0000
+++ docs/reference/libappindicator-sections.txt	2010-08-05 20:31:14 +0000
@@ -9,6 +9,7 @@
 APP_INDICATOR_SIGNAL_NEW_ICON
 APP_INDICATOR_SIGNAL_NEW_ATTENTION_ICON
 APP_INDICATOR_SIGNAL_NEW_STATUS
+APP_INDICATOR_SIGNAL_NEW_LABEL
 APP_INDICATOR_SIGNAL_CONNECTION_CHANGED
 AppIndicatorCategory
 AppIndicatorStatus
@@ -23,11 +24,14 @@
 app_indicator_set_attention_icon
 app_indicator_set_menu
 app_indicator_set_icon
+app_indicator_set_label
 app_indicator_get_id
 app_indicator_get_category
 app_indicator_get_status
 app_indicator_get_icon
 app_indicator_get_attention_icon
 app_indicator_get_menu
+app_indicator_get_label
+app_indicator_get_label_guide
 </SECTION>
 

=== modified file 'example/simple-client.c'
--- example/simple-client.c	2010-04-29 16:31:36 +0000
+++ example/simple-client.c	2010-08-05 20:31:14 +0000
@@ -26,6 +26,21 @@
 
 GMainLoop * mainloop = NULL;
 static gboolean active = TRUE;
+static gboolean can_haz_label = TRUE;
+
+static void
+label_toggle_cb (GtkWidget * widget, gpointer data)
+{
+	can_haz_label = !can_haz_label;
+
+	if (can_haz_label) {
+		gtk_menu_item_set_label(GTK_MENU_ITEM(widget), "Hide label");
+	} else {
+		gtk_menu_item_set_label(GTK_MENU_ITEM(widget), "Show label");
+	}
+
+	return;
+}
 
 static void
 activate_clicked_cb (GtkWidget *widget, gpointer data)
@@ -97,6 +112,22 @@
   gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), menu);
 }
 
+guint percentage = 0;
+
+static gboolean
+percent_change (gpointer user_data)
+{
+	percentage = (percentage + 1) % 100;
+	if (can_haz_label) {
+		gchar * percentstr = g_strdup_printf("%d%%", percentage + 1);
+		app_indicator_set_label (APP_INDICATOR(user_data), percentstr, "100%");
+		g_free(percentstr);
+	} else {
+		app_indicator_set_label (APP_INDICATOR(user_data), NULL, NULL);
+	}
+	return TRUE;
+}
+
 int
 main (int argc, char ** argv)
 {
@@ -114,6 +145,9 @@
 
 	app_indicator_set_status (ci, APP_INDICATOR_STATUS_ACTIVE);
 	app_indicator_set_attention_icon(ci, "indicator-messages-new");
+	app_indicator_set_label (ci, "1%", "100%");
+
+	g_timeout_add_seconds(1, percent_change, ci);
 
         menu = gtk_menu_new ();
         GtkWidget *item = gtk_check_menu_item_new_with_label ("1");
@@ -151,6 +185,13 @@
         gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
 		gtk_widget_show(item);
 
+        item = gtk_menu_item_new_with_label ("Show label");
+		label_toggle_cb(item, ci);
+        g_signal_connect (item, "activate",
+                          G_CALLBACK (label_toggle_cb), ci);
+        gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+		gtk_widget_show(item);
+
         app_indicator_set_menu (ci, GTK_MENU (menu));
 
 	mainloop = g_main_loop_new(NULL, FALSE);

=== modified file 'src/Makefile.am'
--- src/Makefile.am	2010-06-25 19:34:03 +0000
+++ src/Makefile.am	2010-08-05 20:31:14 +0000
@@ -94,7 +94,8 @@
 libappindicator_la_SOURCES = \
 	$(libappindicator_headers) \
 	app-indicator-enum-types.c \
-	app-indicator.c
+	app-indicator.c \
+	application-service-marshal.c
 
 libappindicator_la_LDFLAGS = \
 	-version-info 0:0:0 \

=== modified file 'src/app-indicator.c'
--- src/app-indicator.c	2010-07-07 19:17:31 +0000
+++ src/app-indicator.c	2010-08-05 20:31:14 +0000
@@ -37,6 +37,7 @@
 
 #include "app-indicator.h"
 #include "app-indicator-enum-types.h"
+#include "application-service-marshal.h"
 
 #include "notification-item-server.h"
 #include "notification-watcher-client.h"
@@ -72,6 +73,9 @@
 	gchar *               icon_path;
 	DbusmenuServer       *menuservice;
 	GtkWidget            *menu;
+	gchar *               label;
+	gchar *               label_guide;
+	guint                 label_change_idle;
 
 	GtkStatusIcon *       status_icon;
 	gint                  fallback_timer;
@@ -87,6 +91,7 @@
 	NEW_ICON,
 	NEW_ATTENTION_ICON,
 	NEW_STATUS,
+	NEW_LABEL,
 	CONNECTION_CHANGED,
 	LAST_SIGNAL
 };
@@ -104,7 +109,9 @@
 	PROP_ATTENTION_ICON_NAME,
 	PROP_ICON_THEME_PATH,
 	PROP_MENU,
-	PROP_CONNECTED
+	PROP_CONNECTED,
+	PROP_LABEL,
+	PROP_LABEL_GUIDE
 };
 
 /* The strings so that they can be slowly looked up. */
@@ -116,6 +123,8 @@
 #define PROP_ICON_THEME_PATH_S       "icon-theme-path"
 #define PROP_MENU_S                  "menu"
 #define PROP_CONNECTED_S             "connected"
+#define PROP_LABEL_S                 "label"
+#define PROP_LABEL_GUIDE_S           "label-guide"
 
 /* Private macro, shhhh! */
 #define APP_INDICATOR_GET_PRIVATE(o) \
@@ -136,6 +145,7 @@
 static void app_indicator_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec);
 static void app_indicator_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec);
 /* Other stuff */
+static void signal_label_change (AppIndicator * self);
 static void check_connect (AppIndicator * self);
 static void register_service_cb (DBusGProxy * proxy, GError * error, gpointer data);
 static void start_fallback_timer (AppIndicator * self, gboolean disable_timeout);
@@ -284,6 +294,41 @@
                                                                "Pretty simple, true if we have a reasonable expectation of being displayed through this object.  You should hide your TrayIcon if so.",
                                                                FALSE,
                                                                G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+	/**
+		AppIndicator:label:
+		
+		A label that can be shown next to the string in the application
+		indicator.  The label will not be shown unless there is an icon
+		as well.  The label is useful for numerical and other frequently
+		updated information.  In general, it shouldn't be shown unless a
+		user requests it as it can take up a significant amount of space
+		on the user's panel.  This may not be shown in all visualizations.
+	*/
+	g_object_class_install_property(object_class,
+	                                PROP_LABEL,
+	                                g_param_spec_string (PROP_LABEL_S,
+	                                                     "A label next to the icon",
+	                                                     "A label to provide dynamic information.",
+	                                                     NULL,
+	                                                     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+	/**
+		AppIndicator:label-guide:
+		
+		An optional string to provide guidance to the panel on how big
+		the #AppIndicator:label string could get.  If this is set correctly
+		then the panel should never 'jiggle' as the string adjusts through
+		out the range of options.  For instance, if you were providing a
+		percentage like "54% thrust" in #AppIndicator:label you'd want to
+		set this string to "100% thrust" to ensure space when Scotty can
+		get you enough power.
+	*/
+	g_object_class_install_property(object_class,
+	                                PROP_LABEL_GUIDE,
+	                                g_param_spec_string (PROP_LABEL_GUIDE_S,
+	                                                     "A string to size the space available for the label.",
+	                                                     "To ensure that the label does not cause the panel to 'jiggle' this string should provide information on how much space it could take.",
+	                                                     NULL,
+	                                                     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
 
 	/* Signals */
@@ -333,6 +378,23 @@
                                             G_TYPE_STRING);
 
 	/**
+		AppIndicator::new-label:
+		@arg0: The #AppIndicator object
+		@arg1: The string for the label
+		@arg1: The string for the guide
+
+		Emitted when either #AppIndicator:label or #AppIndicator:label-guide are
+		changed.
+	*/
+	signals[NEW_LABEL] = g_signal_new (APP_INDICATOR_SIGNAL_NEW_LABEL,
+	                                    G_TYPE_FROM_CLASS(klass),
+	                                    G_SIGNAL_RUN_LAST,
+	                                    G_STRUCT_OFFSET (AppIndicatorClass, new_label),
+	                                    NULL, NULL,
+	                                    _application_service_marshal_VOID__STRING_STRING,
+	                                    G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING);
+
+	/**
 		AppIndicator::connection-changed:
 		@arg0: The #AppIndicator object
 		@arg1: Whether we're connected or not
@@ -368,6 +430,9 @@
 	priv->icon_path = NULL;
 	priv->menu = NULL;
 	priv->menuservice = NULL;
+	priv->label = NULL;
+	priv->label_guide = NULL;
+	priv->label_change_idle = 0;
 
 	priv->watcher_proxy = NULL;
 	priv->connection = NULL;
@@ -419,6 +484,11 @@
 		priv->fallback_timer = 0;
 	}
 
+	if (priv->label_change_idle != 0) {
+		g_source_remove(priv->label_change_idle);
+		priv->label_change_idle = 0;
+	}
+
 	if (priv->menu != NULL) {
                 g_signal_handlers_disconnect_by_func (G_OBJECT (priv->menu),
                                                       client_menu_changed,
@@ -491,6 +561,16 @@
 		g_free(priv->icon_path);
 		priv->icon_path = NULL;
 	}
+	
+	if (priv->label != NULL) {
+		g_free(priv->label);
+		priv->label = NULL;
+	}
+
+	if (priv->label_guide != NULL) {
+		g_free(priv->label_guide);
+		priv->label_guide = NULL;
+	}
 
 	G_OBJECT_CLASS (app_indicator_parent_class)->finalize (object);
 	return;
@@ -563,6 +643,43 @@
           priv->icon_path = g_value_dup_string(value);
           break;
 
+		case PROP_LABEL: {
+		  gchar * oldlabel = priv->label;
+		  priv->label = g_value_dup_string(value);
+
+		  if (g_strcmp0(oldlabel, priv->label) != 0) {
+		    signal_label_change(APP_INDICATOR(object));
+		  }
+
+		  if (priv->label != NULL && priv->label[0] == '\0') {
+		  	g_free(priv->label);
+			priv->label = NULL;
+		  }
+
+		  if (oldlabel != NULL) {
+		  	g_free(oldlabel);
+		  }
+		  break;
+		}
+		case PROP_LABEL_GUIDE: {
+		  gchar * oldguide = priv->label_guide;
+		  priv->label_guide = g_value_dup_string(value);
+
+		  if (g_strcmp0(oldguide, priv->label_guide) != 0) {
+		    signal_label_change(APP_INDICATOR(object));
+		  }
+
+		  if (priv->label_guide != NULL && priv->label_guide[0] == '\0') {
+		  	g_free(priv->label_guide);
+			priv->label_guide = NULL;
+		  }
+
+		  if (oldguide != NULL) {
+		  	g_free(oldguide);
+		  }
+		  break;
+		}
+
         default:
           G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
           break;
@@ -620,6 +737,14 @@
           g_value_set_boolean (value, priv->watcher_proxy != NULL ? TRUE : FALSE);
           break;
 
+        case PROP_LABEL:
+          g_value_set_string (value, priv->label);
+          break;
+
+        case PROP_LABEL_GUIDE:
+          g_value_set_string (value, priv->label_guide);
+          break;
+
         default:
           G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
           break;
@@ -628,6 +753,39 @@
 	return;
 }
 
+/* Sends the label changed signal and resets the source ID */
+static gboolean
+signal_label_change_idle (gpointer user_data)
+{
+	AppIndicator * self = (AppIndicator *)user_data;
+	AppIndicatorPrivate *priv = self->priv;
+
+	g_signal_emit(G_OBJECT(self), signals[NEW_LABEL], 0,
+	              priv->label != NULL ? priv->label : "",
+	              priv->label_guide != NULL ? priv->label_guide : "",
+	              TRUE);
+
+	priv->label_change_idle = 0;
+
+	return FALSE;
+}
+
+/* Sets up an idle function to send the label changed signal
+   so that we don't send it too many times. */
+static void
+signal_label_change (AppIndicator * self)
+{
+	AppIndicatorPrivate *priv = self->priv;
+
+	/* don't set it twice */
+	if (priv->label_change_idle != 0) {
+		return;
+	}
+
+	priv->label_change_idle = g_idle_add(signal_label_change_idle, self);
+	return;
+}
+
 /* This function is used to see if we have enough information to
    connect to things.  If we do, and we're not connected, it
    connects for us. */
@@ -1134,6 +1292,31 @@
   return;
 }
 
+/**
+	app_indicator_set_label:
+	@self: The #AppIndicator object to use
+	@label: The label to show next to the icon.
+	@guide: A guide to size the label correctly.
+
+	This is a wrapper function for the #AppIndicator:label and
+	#AppIndicator:guide properties.  This function can take #NULL
+	as either @label or @guide and will clear the entries.
+*/
+void
+app_indicator_set_label (AppIndicator *self, const gchar * label, const gchar * guide)
+{
+	g_return_if_fail (IS_APP_INDICATOR (self));
+	/* Note: The label can be NULL, it's okay */
+	/* Note: The guide can be NULL, it's okay */
+
+	g_object_set(G_OBJECT(self),
+	             PROP_LABEL_S,       label == NULL ? "" : label,
+	             PROP_LABEL_GUIDE_S, guide == NULL ? "" : guide,
+	             NULL);
+
+	return;
+}
+
 static void
 activate_menuitem (DbusmenuMenuitem *mi, guint timestamp, gpointer user_data)
 {
@@ -1661,3 +1844,36 @@
 
 	return GTK_MENU(priv->menu);
 }
+
+/**
+	app_indicator_get_label:
+	@self: The #AppIndicator object to use
+
+	Wrapper function for property #AppIndicator:label.
+
+	Return value: The current label.
+*/
+const gchar *
+app_indicator_get_label (AppIndicator *self)
+{
+  g_return_val_if_fail (IS_APP_INDICATOR (self), NULL);
+
+  return self->priv->label;
+}
+
+/**
+	app_indicator_get_label_guide:
+	@self: The #AppIndicator object to use
+
+	Wrapper function for property #AppIndicator:label-guide.
+
+	Return value: The current label guide.
+*/
+const gchar *
+app_indicator_get_label_guide (AppIndicator *self)
+{
+  g_return_val_if_fail (IS_APP_INDICATOR (self), NULL);
+
+  return self->priv->label_guide;
+}
+

=== modified file 'src/app-indicator.h'
--- src/app-indicator.h	2010-05-23 10:44:53 +0000
+++ src/app-indicator.h	2010-08-05 20:31:14 +0000
@@ -92,6 +92,11 @@
 	String identifier for the #AppIndicator::new-status signal.
 */
 /**
+	APP_INDICATOR_SIGNAL_NEW_LABEL:
+
+	String identifier for the #AppIndicator::new-label signal.
+*/
+/**
 	APP_INDICATOR_SIGNAL_CONNECTION_CHANGED:
 
 	String identifier for the #AppIndicator::connection-changed signal.
@@ -99,6 +104,7 @@
 #define APP_INDICATOR_SIGNAL_NEW_ICON            "new-icon"
 #define APP_INDICATOR_SIGNAL_NEW_ATTENTION_ICON  "new-attention-icon"
 #define APP_INDICATOR_SIGNAL_NEW_STATUS          "new-status"
+#define APP_INDICATOR_SIGNAL_NEW_LABEL           "new-label"
 #define APP_INDICATOR_SIGNAL_CONNECTION_CHANGED  "connection-changed"
 
 /**
@@ -152,8 +158,8 @@
 		there is no Application Indicator area available.
 	@unfallback: The function that gets called if an Application
 		Indicator area appears after the fallback has been created.
+	@new_label: Slot for #AppIndicator::new-label.
 	@app_indicator_reserved_1: Reserved for future use.
-	@app_indicator_reserved_2: Reserved for future use.
 
 	The signals and external functions that make up the #AppIndicator
 	class object.
@@ -181,9 +187,14 @@
 	void (*unfallback)              (AppIndicator * indicator,
 	                                 GtkStatusIcon * status_icon);
 
+	/* Another DBus Signal */
+	void (* new_label)              (AppIndicator       *indicator,
+	                                 const gchar        *label,
+	                                 const gchar        *guide,
+	                                 gpointer            user_data);
+
 	/* Reserved */
 	void (*app_indicator_reserved_1)(void);
-	void (*app_indicator_reserved_2)(void);
 };
 
 /**
@@ -226,6 +237,9 @@
                                                                   GtkMenu            *menu);
 void                            app_indicator_set_icon           (AppIndicator       *self,
                                                                   const gchar        *icon_name);
+void                            app_indicator_set_label          (AppIndicator       *self,
+                                                                  const gchar        *label,
+                                                                  const gchar        *guide);
 
 /* Get properties */
 const gchar *                   app_indicator_get_id             (AppIndicator *self);
@@ -234,6 +248,8 @@
 const gchar *                   app_indicator_get_icon           (AppIndicator *self);
 const gchar *                   app_indicator_get_attention_icon (AppIndicator *self);
 GtkMenu *                       app_indicator_get_menu           (AppIndicator *self);
+const gchar *                   app_indicator_get_label          (AppIndicator *self);
+const gchar *                   app_indicator_get_label_guide    (AppIndicator *self);
 
 G_END_DECLS
 

=== modified file 'src/application-service-marshal.list'
--- src/application-service-marshal.list	2010-01-07 23:06:38 +0000
+++ src/application-service-marshal.list	2010-08-05 20:31:14 +0000
@@ -18,3 +18,4 @@
 # with this program.  If not, see <http://www.gnu.org/licenses/>.
 VOID: STRING, INT, STRING, STRING, STRING
 VOID: INT, STRING
+VOID: STRING, STRING

=== removed file 'src/dbus-properties-client.h'
--- src/dbus-properties-client.h	2010-01-08 02:53:46 +0000
+++ src/dbus-properties-client.h	1970-01-01 00:00:00 +0000
@@ -1,139 +0,0 @@
-/* Generated by dbus-binding-tool; do not edit! */
-
-#include <glib.h>
-#include <dbus/dbus-glib.h>
-
-G_BEGIN_DECLS
-
-#ifndef _DBUS_GLIB_ASYNC_DATA_FREE
-#define _DBUS_GLIB_ASYNC_DATA_FREE
-static
-#ifdef G_HAVE_INLINE
-inline
-#endif
-void
-_dbus_glib_async_data_free (gpointer stuff)
-{
-	g_slice_free (DBusGAsyncData, stuff);
-}
-#endif
-
-#ifndef DBUS_GLIB_CLIENT_WRAPPERS_org_freedesktop_DBus_Properties
-#define DBUS_GLIB_CLIENT_WRAPPERS_org_freedesktop_DBus_Properties
-
-static
-#ifdef G_HAVE_INLINE
-inline
-#endif
-gboolean
-org_freedesktop_DBus_Properties_get (DBusGProxy *proxy, const char * IN_Interface_Name, const char * IN_Property_Name, GValue* OUT_Value, GError **error)
-
-{
-  return dbus_g_proxy_call (proxy, "Get", error, G_TYPE_STRING, IN_Interface_Name, G_TYPE_STRING, IN_Property_Name, G_TYPE_INVALID, G_TYPE_VALUE, OUT_Value, G_TYPE_INVALID);
-}
-
-typedef void (*org_freedesktop_DBus_Properties_get_reply) (DBusGProxy *proxy, GValue OUT_Value, GError *error, gpointer userdata);
-
-static void
-org_freedesktop_DBus_Properties_get_async_callback (DBusGProxy *proxy, DBusGProxyCall *call, void *user_data)
-{
-  DBusGAsyncData *data = (DBusGAsyncData*) user_data;
-  GError *error = NULL;
-  GValue OUT_Value = {0};
-  dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_VALUE, &OUT_Value, G_TYPE_INVALID);
-  (*(org_freedesktop_DBus_Properties_get_reply)data->cb) (proxy, OUT_Value, error, data->userdata);
-  return;
-}
-
-static
-#ifdef G_HAVE_INLINE
-inline
-#endif
-DBusGProxyCall*
-org_freedesktop_DBus_Properties_get_async (DBusGProxy *proxy, const char * IN_Interface_Name, const char * IN_Property_Name, org_freedesktop_DBus_Properties_get_reply callback, gpointer userdata)
-
-{
-  DBusGAsyncData *stuff;
-  stuff = g_slice_new (DBusGAsyncData);
-  stuff->cb = G_CALLBACK (callback);
-  stuff->userdata = userdata;
-  return dbus_g_proxy_begin_call (proxy, "Get", org_freedesktop_DBus_Properties_get_async_callback, stuff, _dbus_glib_async_data_free, G_TYPE_STRING, IN_Interface_Name, G_TYPE_STRING, IN_Property_Name, G_TYPE_INVALID);
-}
-static
-#ifdef G_HAVE_INLINE
-inline
-#endif
-gboolean
-org_freedesktop_DBus_Properties_set (DBusGProxy *proxy, const char * IN_Interface_Name, const char * IN_Property_Name, const GValue* IN_Value, GError **error)
-
-{
-  return dbus_g_proxy_call (proxy, "Set", error, G_TYPE_STRING, IN_Interface_Name, G_TYPE_STRING, IN_Property_Name, G_TYPE_VALUE, IN_Value, G_TYPE_INVALID, G_TYPE_INVALID);
-}
-
-typedef void (*org_freedesktop_DBus_Properties_set_reply) (DBusGProxy *proxy, GError *error, gpointer userdata);
-
-static void
-org_freedesktop_DBus_Properties_set_async_callback (DBusGProxy *proxy, DBusGProxyCall *call, void *user_data)
-{
-  DBusGAsyncData *data = (DBusGAsyncData*) user_data;
-  GError *error = NULL;
-  dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID);
-  (*(org_freedesktop_DBus_Properties_set_reply)data->cb) (proxy, error, data->userdata);
-  return;
-}
-
-static
-#ifdef G_HAVE_INLINE
-inline
-#endif
-DBusGProxyCall*
-org_freedesktop_DBus_Properties_set_async (DBusGProxy *proxy, const char * IN_Interface_Name, const char * IN_Property_Name, const GValue* IN_Value, org_freedesktop_DBus_Properties_set_reply callback, gpointer userdata)
-
-{
-  DBusGAsyncData *stuff;
-  stuff = g_slice_new (DBusGAsyncData);
-  stuff->cb = G_CALLBACK (callback);
-  stuff->userdata = userdata;
-  return dbus_g_proxy_begin_call (proxy, "Set", org_freedesktop_DBus_Properties_set_async_callback, stuff, _dbus_glib_async_data_free, G_TYPE_STRING, IN_Interface_Name, G_TYPE_STRING, IN_Property_Name, G_TYPE_VALUE, IN_Value, G_TYPE_INVALID);
-}
-static
-#ifdef G_HAVE_INLINE
-inline
-#endif
-gboolean
-org_freedesktop_DBus_Properties_get_all (DBusGProxy *proxy, const char * IN_Interface_Name, GHashTable** OUT_Properties, GError **error)
-
-{
-  return dbus_g_proxy_call (proxy, "GetAll", error, G_TYPE_STRING, IN_Interface_Name, G_TYPE_INVALID, dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), OUT_Properties, G_TYPE_INVALID);
-}
-
-typedef void (*org_freedesktop_DBus_Properties_get_all_reply) (DBusGProxy *proxy, GHashTable *OUT_Properties, GError *error, gpointer userdata);
-
-static void
-org_freedesktop_DBus_Properties_get_all_async_callback (DBusGProxy *proxy, DBusGProxyCall *call, void *user_data)
-{
-  DBusGAsyncData *data = (DBusGAsyncData*) user_data;
-  GError *error = NULL;
-  GHashTable* OUT_Properties;
-  dbus_g_proxy_end_call (proxy, call, &error, dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), &OUT_Properties, G_TYPE_INVALID);
-  (*(org_freedesktop_DBus_Properties_get_all_reply)data->cb) (proxy, OUT_Properties, error, data->userdata);
-  return;
-}
-
-static
-#ifdef G_HAVE_INLINE
-inline
-#endif
-DBusGProxyCall*
-org_freedesktop_DBus_Properties_get_all_async (DBusGProxy *proxy, const char * IN_Interface_Name, org_freedesktop_DBus_Properties_get_all_reply callback, gpointer userdata)
-
-{
-  DBusGAsyncData *stuff;
-  stuff = g_slice_new (DBusGAsyncData);
-  stuff->cb = G_CALLBACK (callback);
-  stuff->userdata = userdata;
-  return dbus_g_proxy_begin_call (proxy, "GetAll", org_freedesktop_DBus_Properties_get_all_async_callback, stuff, _dbus_glib_async_data_free, G_TYPE_STRING, IN_Interface_Name, G_TYPE_INVALID);
-}
-#endif /* defined DBUS_GLIB_CLIENT_WRAPPERS_org_freedesktop_DBus_Properties */
-
-G_END_DECLS

=== modified file 'src/notification-item.xml'
--- src/notification-item.xml	2010-03-15 17:10:43 +0000
+++ src/notification-item.xml	2010-08-05 20:31:14 +0000
@@ -12,6 +12,8 @@
 		     to find the icons specified above. -->
 		<property name="IconThemePath" type="s" access="read" />
 		<property name="Menu" type="o" access="read" />
+		<property name="Label" type="s" access="read" />
+		<property name="LabelGuide" type="s" access="read" />
 
 <!-- Methods -->
 		<!-- None currently -->
@@ -24,6 +26,10 @@
 		<signal name="NewStatus">
 			<arg type="s" name="status" direction="out" />
 		</signal>
+		<signal name="NewLabel">
+			<arg type="s" name="label" direction="out" />
+			<arg type="s" name="guide" direction="out" />
+		</signal>
 
 	</interface>
 </node>

=== modified file 'tests/test-libappindicator.c'
--- tests/test-libappindicator.c	2010-04-29 16:31:36 +0000
+++ tests/test-libappindicator.c	2010-08-05 20:31:14 +0000
@@ -163,12 +163,145 @@
 }
 
 void
+test_libappindicator_set_label (void)
+{
+	AppIndicator * ci = app_indicator_new ("my-id",
+	                                       "my-name",
+	                                       APP_INDICATOR_CATEGORY_APPLICATION_STATUS);
+
+	g_assert(ci != NULL);
+	g_assert(app_indicator_get_label(ci) == NULL);
+	g_assert(app_indicator_get_label_guide(ci) == NULL);
+
+	/* First check all the clearing modes, this is important as
+	   we're going to use them later, we need them to work. */
+	app_indicator_set_label(ci, NULL, NULL);
+
+	g_assert(app_indicator_get_label(ci) == NULL);
+	g_assert(app_indicator_get_label_guide(ci) == NULL);
+
+	app_indicator_set_label(ci, "", NULL);
+
+	g_assert(app_indicator_get_label(ci) == NULL);
+	g_assert(app_indicator_get_label_guide(ci) == NULL);
+
+	app_indicator_set_label(ci, NULL, "");
+
+	g_assert(app_indicator_get_label(ci) == NULL);
+	g_assert(app_indicator_get_label_guide(ci) == NULL);
+
+	app_indicator_set_label(ci, "", "");
+
+	g_assert(app_indicator_get_label(ci) == NULL);
+	g_assert(app_indicator_get_label_guide(ci) == NULL);
+
+	app_indicator_set_label(ci, "label", "");
+
+	g_assert(g_strcmp0(app_indicator_get_label(ci), "label") == 0);
+	g_assert(app_indicator_get_label_guide(ci) == NULL);
+
+	app_indicator_set_label(ci, NULL, NULL);
+
+	g_assert(app_indicator_get_label(ci) == NULL);
+	g_assert(app_indicator_get_label_guide(ci) == NULL);
+
+	app_indicator_set_label(ci, "label", "guide");
+
+	g_assert(g_strcmp0(app_indicator_get_label(ci), "label") == 0);
+	g_assert(g_strcmp0(app_indicator_get_label_guide(ci), "guide") == 0);
+
+	app_indicator_set_label(ci, "label2", "guide");
+
+	g_assert(g_strcmp0(app_indicator_get_label(ci), "label2") == 0);
+	g_assert(g_strcmp0(app_indicator_get_label_guide(ci), "guide") == 0);
+
+	app_indicator_set_label(ci, "trick-label", "trick-guide");
+
+	g_assert(g_strcmp0(app_indicator_get_label(ci), "trick-label") == 0);
+	g_assert(g_strcmp0(app_indicator_get_label_guide(ci), "trick-guide") == 0);
+
+	g_object_unref(G_OBJECT(ci));
+	return;
+}
+
+void
+label_signals_cb (AppIndicator * appindicator, gchar * label, gchar * guide, gpointer user_data)
+{
+	gint * label_signals_count = (gint *)user_data;
+	(*label_signals_count)++;
+	return;
+}
+
+void
+label_signals_check (void)
+{
+	while (g_main_context_pending(NULL)) {
+		g_main_context_iteration(NULL, TRUE);
+	}
+
+	return;
+}
+
+void
+test_libappindicator_label_signals (void)
+{
+	gint label_signals_count = 0;
+	AppIndicator * ci = app_indicator_new ("my-id",
+	                                       "my-name",
+	                                       APP_INDICATOR_CATEGORY_APPLICATION_STATUS);
+
+	g_assert(ci != NULL);
+	g_assert(app_indicator_get_label(ci) == NULL);
+	g_assert(app_indicator_get_label_guide(ci) == NULL);
+
+	g_signal_connect(G_OBJECT(ci), APP_INDICATOR_SIGNAL_NEW_LABEL, G_CALLBACK(label_signals_cb), &label_signals_count);
+
+	/* Shouldn't be a signal as it should be stuck in idle */
+	app_indicator_set_label(ci, "label", "guide");
+	g_assert(label_signals_count == 0);
+
+	/* Should show up after idle processing */
+	label_signals_check();
+	g_assert(label_signals_count == 1);
+
+	/* Shouldn't signal with no change */
+	label_signals_count = 0;
+	app_indicator_set_label(ci, "label", "guide");
+	label_signals_check();
+	g_assert(label_signals_count == 0);
+
+	/* Change one, we should get one signal */
+	app_indicator_set_label(ci, "label2", "guide");
+	label_signals_check();
+	g_assert(label_signals_count == 1);
+
+	/* Change several times, one signal */
+	label_signals_count = 0;
+	app_indicator_set_label(ci, "label1", "guide0");
+	app_indicator_set_label(ci, "label1", "guide1");
+	app_indicator_set_label(ci, "label2", "guide2");
+	app_indicator_set_label(ci, "label3", "guide3");
+	label_signals_check();
+	g_assert(label_signals_count == 1);
+
+	/* Clear should signal too */
+	label_signals_count = 0;
+	app_indicator_set_label(ci, NULL, NULL);
+	label_signals_check();
+	g_assert(label_signals_count == 1);
+
+	return;
+}
+
+void
 test_libappindicator_props_suite (void)
 {
 	g_test_add_func ("/indicator-application/libappindicator/init",            test_libappindicator_init);
 	g_test_add_func ("/indicator-application/libappindicator/init_props",      test_libappindicator_init_with_props);
 	g_test_add_func ("/indicator-application/libappindicator/init_set_props",  test_libappindicator_init_set_props);
 	g_test_add_func ("/indicator-application/libappindicator/prop_signals",    test_libappindicator_prop_signals);
+	g_test_add_func ("/indicator-application/libappindicator/set_label",       test_libappindicator_set_label);
+	g_test_add_func ("/indicator-application/libappindicator/label_signals",   test_libappindicator_label_signals);
 
 	return;
 }


Follow ups