← Back to team overview

ayatana-commits team mailing list archive

[Merge] lp:~ted/indicator-application/ordering-id into lp:indicator-application

 

Ted Gould has proposed merging lp:~ted/indicator-application/ordering-id into lp:indicator-application with lp:~ted/indicator-application/x-label-branch as a prerequisite.

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


Adds a way for the applications to suggest ordering.  And makes the ordering fixed upon a category and ID.  It also allows for override files to set the values absolutely.
-- 
https://code.launchpad.net/~ted/indicator-application/ordering-id/+merge/32383
Your team ayatana-commits is subscribed to branch lp:indicator-application.
=== modified file '.bzrignore'
--- .bzrignore	2010-08-03 18:15:49 +0000
+++ .bzrignore	2010-08-11 20:58:44 +0000
@@ -113,3 +113,5 @@
 tests/test-approver-tester
 bindings/mono/policy.0.0.appindicator-sharp.config
 bindings/mono/policy.0.0.appindicator-sharp.dll
+src/libapplication_la-generate-id.lo
+src/libappindicator_la-generate-id.lo

=== modified file 'data/Makefile.am'
--- data/Makefile.am	2009-11-25 03:52:40 +0000
+++ data/Makefile.am	2010-08-11 20:58:44 +0000
@@ -5,7 +5,13 @@
 %.service: %.service.in
 	sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
 
-EXTRA_DIST = indicator-application.service.in
-
-CLEANFILES = indicator-application.service
+overridedir = $(pkgdatadir)
+override_DATA = ordering-override.keyfile
+
+EXTRA_DIST = \
+	indicator-application.service.in \
+	ordering-override.keyfile
+
+CLEANFILES = \
+	indicator-application.service
 

=== added file 'data/ordering-override.keyfile'
--- data/ordering-override.keyfile	1970-01-01 00:00:00 +0000
+++ data/ordering-override.keyfile	2010-08-11 20:58:44 +0000
@@ -0,0 +1,2 @@
+[Ordering Index Overrides]
+gnome-power-manager=1

=== modified file 'docs/reference/Makefile.am'
--- docs/reference/Makefile.am	2010-05-21 01:22:24 +0000
+++ docs/reference/Makefile.am	2010-08-11 20:58:44 +0000
@@ -66,6 +66,7 @@
 	dbus-properties-client.h \
 	dbus-properties-server.h \
 	dbus-shared.h \
+	generate-id.h \
 	notification-item-client.h \
 	notification-item-server.h \
 	notification-watcher-client.h \

=== modified file 'docs/reference/libappindicator-sections.txt'
--- docs/reference/libappindicator-sections.txt	2010-08-05 21:35:25 +0000
+++ docs/reference/libappindicator-sections.txt	2010-08-11 20:58:44 +0000
@@ -27,6 +27,7 @@
 app_indicator_set_icon
 app_indicator_set_icon_theme_path
 app_indicator_set_label
+app_indicator_set_ordering_index
 app_indicator_get_id
 app_indicator_get_category
 app_indicator_get_status
@@ -36,5 +37,6 @@
 app_indicator_get_menu
 app_indicator_get_label
 app_indicator_get_label_guide
+app_indicator_get_ordering_index
 </SECTION>
 

=== modified file 'src/Makefile.am'
--- src/Makefile.am	2010-08-05 22:09:56 +0000
+++ src/Makefile.am	2010-08-11 20:58:44 +0000
@@ -44,17 +44,20 @@
 	application-service.c \
 	application-service-appstore.h \
 	application-service-appstore.c \
-	application-service-lru-file.h \
-	application-service-lru-file.c \
 	application-service-marshal.c \
 	application-service-watcher.h \
 	application-service-watcher.c \
 	app-indicator-enum-types.c \
-	dbus-shared.h
+	dbus-shared.h \
+	generate-id.h \
+	generate-id.c
+
 indicator_application_service_CFLAGS = \
 	$(INDICATOR_CFLAGS) \
+	-DDATADIR="\"$(pkgdatadir)\"" \
 	-Wall -Werror \
 	-DG_LOG_DOMAIN=\"indicator-application-service\"
+
 indicator_application_service_LDADD = \
 	$(INDICATOR_LIBS) \
 	libappindicator.la
@@ -95,7 +98,9 @@
 	$(libappindicator_headers) \
 	app-indicator-enum-types.c \
 	app-indicator.c \
-	application-service-marshal.c
+	application-service-marshal.c \
+	generate-id.h \
+	generate-id.c
 
 libappindicator_la_LDFLAGS = \
 	-version-info 1:0:0 \

=== modified file 'src/app-indicator.c'
--- src/app-indicator.c	2010-08-11 20:58:43 +0000
+++ src/app-indicator.c	2010-08-11 20:58:44 +0000
@@ -43,6 +43,7 @@
 #include "notification-watcher-client.h"
 
 #include "dbus-shared.h"
+#include "generate-id.h"
 
 #define PANEL_ICON_SUFFIX  "panel"
 
@@ -73,6 +74,7 @@
 	gchar                *icon_theme_path;
 	DbusmenuServer       *menuservice;
 	GtkWidget            *menu;
+	guint32               ordering_index;
 	gchar *               label;
 	gchar *               label_guide;
 	guint                 label_change_idle;
@@ -115,7 +117,9 @@
 	PROP_LABEL,
 	PROP_LABEL_GUIDE,
 	PROP_X_LABEL,
-	PROP_X_LABEL_GUIDE
+	PROP_X_LABEL_GUIDE,
+	PROP_ORDERING_INDEX,
+	PROP_X_ORDERING_INDEX
 };
 
 /* The strings so that they can be slowly looked up. */
@@ -129,8 +133,10 @@
 #define PROP_CONNECTED_S             "connected"
 #define PROP_LABEL_S                 "label"
 #define PROP_LABEL_GUIDE_S           "label-guide"
-#define PROP_X_LABEL_S               "x-ayatana-label"
-#define PROP_X_LABEL_GUIDE_S         "x-ayatana-label-guide"
+#define PROP_X_LABEL_S               ("x-ayatana-" PROP_LABEL_S)
+#define PROP_X_LABEL_GUIDE_S         ("x-ayatana-" PROP_LABEL_GUIDE_S)
+#define PROP_ORDERING_INDEX_S        "ordering-index"
+#define PROP_X_ORDERING_INDEX_S      ("x-ayatana-" PROP_ORDERING_INDEX_S)
 
 /* Private macro, shhhh! */
 #define APP_INDICATOR_GET_PRIVATE(o) \
@@ -338,6 +344,39 @@
 	                                                     "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));
+	/**
+		AppIndicator:ordering-index:
+
+		The ordering index is an odd parameter, and if you think you don't need
+		it you're probably right.  In general, the application indicator try
+		to place the applications in a recreatable place taking into account
+		which category they're in to try and group them.  But, there are some
+		cases where you'd want to ensure indicators are next to each other.
+		To do that you can override the generated ordering index and replace it
+		with a new one.  Again, you probably don't want to be doing this, but
+		in case you do, this is the way.
+	*/
+	g_object_class_install_property(object_class,
+	                                PROP_ORDERING_INDEX,
+	                                g_param_spec_uint (PROP_ORDERING_INDEX_S,
+	                                                   "The location that this app indicator should be in the list.",
+	                                                   "A way to override the default ordering of the applications by providing a very specific idea of where this entry should be placed.",
+	                                                   0, G_MAXUINT32, 0,
+	                                                   G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+	/**
+		AppIndicator:x-ayatana-ordering-index:
+
+		A wrapper for #AppIndicator:ordering-index so that it can match the
+		dbus interface currently.  It will hopefully be retired, please don't
+		use it anywhere.
+	*/
+	g_object_class_install_property(object_class,
+	                                PROP_X_ORDERING_INDEX,
+	                                g_param_spec_uint (PROP_X_ORDERING_INDEX_S,
+	                                                   "A wrapper, please don't use.",
+	                                                   "A wrapper, please don't use.",
+	                                                   0, G_MAXUINT32, 0,
+	                                                   G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
 	/**
 		AppIndicator:x-ayatana-label:
@@ -497,6 +536,7 @@
 	priv->icon_theme_path = NULL;
 	priv->menu = NULL;
 	priv->menuservice = NULL;
+	priv->ordering_index = 0;
 	priv->label = NULL;
 	priv->label_guide = NULL;
 	priv->label_change_idle = 0;
@@ -747,6 +787,10 @@
 		  }
 		  break;
 		}
+		case PROP_X_ORDERING_INDEX:
+		case PROP_ORDERING_INDEX:
+		  priv->ordering_index = g_value_get_uint(value);
+		  break;
 
         default:
           G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -815,6 +859,11 @@
           g_value_set_string (value, priv->label_guide);
           break;
 
+		case PROP_X_ORDERING_INDEX:
+		case PROP_ORDERING_INDEX:
+		  g_value_set_uint(value, priv->ordering_index);
+		  break;
+
         default:
           G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
           break;
@@ -1844,6 +1893,27 @@
 }
 
 /**
+	app_indicator_set_ordering_index:
+	@self: The #AppIndicator
+	@ordering_index: A value for the ordering of this app indicator
+
+	Sets the ordering index for the app indicator which effects the
+	placement of it on the panel.  For almost all app indicator
+	this is not the function you're looking for.
+
+	Wrapper function for property #AppIndicator:ordering-index.
+**/
+void
+app_indicator_set_ordering_index (AppIndicator *self, guint32 ordering_index)
+{
+	g_return_if_fail (IS_APP_INDICATOR (self));
+
+	self->priv->ordering_index = ordering_index;
+
+	return;
+}
+
+/**
 	app_indicator_get_id:
 	@self: The #AppIndicator object to use
 
@@ -1992,3 +2062,23 @@
   return self->priv->label_guide;
 }
 
+/**
+	app_indicator_get_ordering_index:
+	@self: The #AppIndicator object to use
+
+	Wrapper function for property #AppIndicator:ordering-index.
+
+	Return value: The current ordering index.
+*/
+guint32
+app_indicator_get_ordering_index (AppIndicator *self)
+{
+	g_return_val_if_fail (IS_APP_INDICATOR (self), 0);
+
+	if (self->priv->ordering_index == 0) {
+		return generate_id(self->priv->category, self->priv->id);
+	} else {
+		return self->priv->ordering_index;
+	}
+}
+

=== modified file 'src/app-indicator.h'
--- src/app-indicator.h	2010-08-05 22:14:38 +0000
+++ src/app-indicator.h	2010-08-11 20:58:44 +0000
@@ -265,6 +265,8 @@
                                                                   const gchar        *guide);
 void                            app_indicator_set_icon_theme_path(AppIndicator       *self,
                                                                   const gchar        *icon_theme_path);
+void                            app_indicator_set_ordering_index (AppIndicator       *self,
+                                                                  guint32             ordering_index);
 
 /* Get properties */
 const gchar *                   app_indicator_get_id             (AppIndicator *self);
@@ -276,6 +278,7 @@
 GtkMenu *                       app_indicator_get_menu           (AppIndicator *self);
 const gchar *                   app_indicator_get_label          (AppIndicator *self);
 const gchar *                   app_indicator_get_label_guide    (AppIndicator *self);
+guint32                         app_indicator_get_ordering_index (AppIndicator *self);
 
 G_END_DECLS
 

=== modified file 'src/application-service-appstore.c'
--- src/application-service-appstore.c	2010-08-11 20:58:43 +0000
+++ src/application-service-appstore.c	2010-08-11 20:58:44 +0000
@@ -32,21 +32,23 @@
 #include "dbus-properties-client.h"
 #include "dbus-shared.h"
 #include "notification-approver-client.h"
+#include "generate-id.h"
 
 /* DBus Prototypes */
 static gboolean _application_service_server_get_applications (ApplicationServiceAppstore * appstore, GPtrArray ** apps, GError ** error);
 
 #include "application-service-server.h"
 
-#define NOTIFICATION_ITEM_PROP_ID               "Id"
-#define NOTIFICATION_ITEM_PROP_CATEGORY         "Category"
-#define NOTIFICATION_ITEM_PROP_STATUS           "Status"
-#define NOTIFICATION_ITEM_PROP_ICON_NAME        "IconName"
-#define NOTIFICATION_ITEM_PROP_AICON_NAME       "AttentionIconName"
-#define NOTIFICATION_ITEM_PROP_ICON_THEME_PATH  "IconThemePath"
-#define NOTIFICATION_ITEM_PROP_MENU             "Menu"
-#define NOTIFICATION_ITEM_PROP_LABEL            "XAyatanaLabel"
-#define NOTIFICATION_ITEM_PROP_LABEL_GUIDE      "XAyatanaLabelGuide"
+#define NOTIFICATION_ITEM_PROP_ID                    "Id"
+#define NOTIFICATION_ITEM_PROP_CATEGORY              "Category"
+#define NOTIFICATION_ITEM_PROP_STATUS                "Status"
+#define NOTIFICATION_ITEM_PROP_ICON_NAME             "IconName"
+#define NOTIFICATION_ITEM_PROP_AICON_NAME            "AttentionIconName"
+#define NOTIFICATION_ITEM_PROP_ICON_THEME_PATH       "IconThemePath"
+#define NOTIFICATION_ITEM_PROP_MENU                  "Menu"
+#define NOTIFICATION_ITEM_PROP_LABEL                 "XAyatanaLabel"
+#define NOTIFICATION_ITEM_PROP_LABEL_GUIDE           "XAyatanaLabelGuide"
+#define NOTIFICATION_ITEM_PROP_ORDERING_INDEX        "XAyatanaOrderingIndex"
 
 #define NOTIFICATION_ITEM_SIG_NEW_ICON               "NewIcon"
 #define NOTIFICATION_ITEM_SIG_NEW_AICON              "NewAttentionIcon"
@@ -54,12 +56,15 @@
 #define NOTIFICATION_ITEM_SIG_NEW_LABEL              "XAyatanaNewLabel"
 #define NOTIFICATION_ITEM_SIG_NEW_ICON_THEME_PATH    "NewIconThemePath"
 
+#define OVERRIDE_GROUP_NAME                          "Ordering Index Overrides"
+#define OVERRIDE_FILE_NAME                           "ordering-override.keyfile"
+
 /* Private Stuff */
 struct _ApplicationServiceAppstorePrivate {
 	DBusGConnection * bus;
 	GList * applications;
 	GList * approvers;
-	AppLruFile * lrufile;
+	GHashTable * ordering_overrides;
 };
 
 typedef struct _Approver Approver;
@@ -85,6 +90,7 @@
 	gchar * label;
 	gchar * guide;
 	gboolean currently_free;
+	guint ordering_index;
 };
 
 #define APPLICATION_SERVICE_APPSTORE_GET_PRIVATE(o) \
@@ -107,7 +113,9 @@
 static void application_service_appstore_init       (ApplicationServiceAppstore *self);
 static void application_service_appstore_dispose    (GObject *object);
 static void application_service_appstore_finalize   (GObject *object);
+static void load_override_file (GHashTable * hash, const gchar * filename);
 static AppIndicatorStatus string_to_status(const gchar * status_string);
+static AppIndicatorCategory string_to_cat(const gchar * cat_string);
 static void apply_status (Application * app, AppIndicatorStatus status);
 static void approver_free (gpointer papprover, gpointer user_data);
 static void check_with_new_approver (gpointer papp, gpointer papprove);
@@ -181,7 +189,13 @@
 
 	priv->applications = NULL;
 	priv->approvers = NULL;
-	priv->lrufile = NULL;
+
+	priv->ordering_overrides = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
+
+	load_override_file(priv->ordering_overrides, DATADIR "/" OVERRIDE_FILE_NAME);
+	gchar * userfile = g_build_filename(g_get_user_data_dir(), "indicators", "application", OVERRIDE_FILE_NAME, NULL);
+	load_override_file(priv->ordering_overrides, userfile);
+	g_free(userfile);
 	
 	GError * error = NULL;
 	priv->bus = dbus_g_bus_get(DBUS_BUS_STARTER, &error);
@@ -224,11 +238,71 @@
 static void
 application_service_appstore_finalize (GObject *object)
 {
+	ApplicationServiceAppstorePrivate * priv = APPLICATION_SERVICE_APPSTORE(object)->priv;
+
+	if (priv->ordering_overrides != NULL) {
+		g_hash_table_destroy(priv->ordering_overrides);
+		priv->ordering_overrides = NULL;
+	}
 
 	G_OBJECT_CLASS (application_service_appstore_parent_class)->finalize (object);
 	return;
 }
 
+/* Loads the file and adds the override entries to the table
+   of overrides */
+static void
+load_override_file (GHashTable * hash, const gchar * filename)
+{
+	g_return_if_fail(hash != NULL);
+	g_return_if_fail(filename != NULL);
+
+	if (!g_file_test(filename, G_FILE_TEST_EXISTS)) {
+		return;
+	}
+
+	g_debug("Loading overrides from: '%s'", filename);
+
+	GError * error = NULL;
+	GKeyFile * keyfile = g_key_file_new();
+	g_key_file_load_from_file(keyfile, filename, G_KEY_FILE_NONE, &error);
+
+	if (error != NULL) {
+		g_warning("Unable to load keyfile '%s' because: %s", filename, error->message);
+		g_error_free(error);
+		g_key_file_free(keyfile);
+		return;
+	}
+
+	gchar ** keys = g_key_file_get_keys(keyfile, OVERRIDE_GROUP_NAME, NULL, &error);
+	if (error != NULL) {
+		g_warning("Unable to get keys from keyfile '%s' because: %s", filename, error->message);
+		g_error_free(error);
+		g_key_file_free(keyfile);
+		return;
+	}
+
+	gchar * key = keys[0];
+	gint i;
+
+	for (i = 0; (key = keys[i]) != NULL; i++) {
+		GError * valerror = NULL;
+		gint val = g_key_file_get_integer(keyfile, OVERRIDE_GROUP_NAME, key, &valerror);
+
+		if (valerror != NULL) {
+			g_warning("Unable to get key '%s' out of file '%s' because: %s", key, filename, valerror->message);
+			g_error_free(valerror);
+			continue;
+		}
+		g_debug("%s: override '%s' with value '%d'", filename, key, val);
+
+		g_hash_table_insert(hash, g_strdup(key), GINT_TO_POINTER(val));
+	}
+	g_key_file_free(keyfile);
+
+	return;
+}
+
 /* Return from getting the properties from the item.  We're looking at those
    and making sure we have everythign that we need.  If we do, then we'll
    move on up to sending this onto the indicator. */
@@ -257,7 +331,6 @@
 	app->id = g_value_dup_string(g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_ID));
 	app->category = g_value_dup_string(g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_CATEGORY));
 	ApplicationServiceAppstorePrivate * priv = app->appstore->priv;
-	app_lru_file_touch(priv->lrufile, app->id, app->category);
 
 	app->icon = g_value_dup_string(g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_ICON_NAME));
 
@@ -281,6 +354,19 @@
 		app->icon_theme_path = g_strdup("");
 	}
 
+	gpointer ordering_index_over = g_hash_table_lookup(priv->ordering_overrides, app->id);
+	if (ordering_index_over == NULL) {
+		gpointer ordering_index_data = g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_ORDERING_INDEX);
+		if (ordering_index_data == NULL || g_value_get_uint(ordering_index_data) == 0) {
+			app->ordering_index = generate_id(string_to_cat(app->category), app->id);
+		} else {
+			app->ordering_index = g_value_get_uint(ordering_index_data);
+		}
+	} else {
+		app->ordering_index = GPOINTER_TO_UINT(ordering_index_over);
+	}
+	g_debug("'%s' ordering index is '%X'", app->id, app->ordering_index);
+
 	gpointer label_data = g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_LABEL);
 	if (label_data != NULL) {
 		app->label = g_value_dup_string((GValue *)label_data);
@@ -333,6 +419,28 @@
 	return retval;
 }
 
+/* Simple translation function -- could be optimized */
+static AppIndicatorCategory
+string_to_cat(const gchar * cat_string)
+{
+	GEnumClass * klass = G_ENUM_CLASS(g_type_class_ref(APP_INDICATOR_TYPE_INDICATOR_CATEGORY));
+	g_return_val_if_fail(klass != NULL, APP_INDICATOR_CATEGORY_OTHER);
+
+	AppIndicatorCategory retval = APP_INDICATOR_CATEGORY_OTHER;
+
+	GEnumValue * val = g_enum_get_value_by_nick(klass, cat_string);
+	if (val == NULL) {
+		g_warning("Unrecognized status '%s' assuming other.", cat_string);
+	} else {
+		retval = (AppIndicatorCategory)val->value;
+	}
+
+	g_type_class_unref(klass);
+
+	return retval;
+}
+
+
 /* A small helper function to get the position of an application
    in the app list. */
 static gint 
@@ -440,15 +548,13 @@
 }
 
 /* This function takes two Application structure
-   pointers and uses the lrufile to compare them. */
+   pointers and uses their ordering index to compare them. */
 static gint
 app_sort_func (gconstpointer a, gconstpointer b, gpointer userdata)
 {
 	Application * appa = (Application *)a;
 	Application * appb = (Application *)b;
-	AppLruFile * lrufile = (AppLruFile *)userdata;
-
-	return app_lru_file_sort(lrufile, appa->id, appb->id);
+	return (appb->ordering_index/2) - (appa->ordering_index/2);
 }
 
 /* Change the status of the application.  If we're going passive
@@ -485,7 +591,7 @@
 		if (app->status == APP_INDICATOR_STATUS_PASSIVE) {
                         if (can_add_application (priv->applications, app)) {
                                 /* Put on panel */
-                                priv->applications = g_list_insert_sorted_with_data (priv->applications, app, app_sort_func, priv->lrufile);
+                                priv->applications = g_list_insert_sorted_with_data (priv->applications, app, app_sort_func, NULL);
 
                                 g_signal_emit(G_OBJECT(app->appstore),
                                               signals[APPLICATION_ADDED], 0,
@@ -734,6 +840,7 @@
 	app->label = NULL;
 	app->guide = NULL;
 	app->currently_free = FALSE;
+	app->ordering_index = 0;
 
 	/* Get the DBus proxy for the NotificationItem interface */
 	GError * error = NULL;
@@ -853,12 +960,9 @@
 /* Creates a basic appstore object and attaches the
    LRU file object to it. */
 ApplicationServiceAppstore *
-application_service_appstore_new (AppLruFile * lrufile)
+application_service_appstore_new (void)
 {
-	g_return_val_if_fail(IS_APP_LRU_FILE(lrufile), NULL);
 	ApplicationServiceAppstore * appstore = APPLICATION_SERVICE_APPSTORE(g_object_new(APPLICATION_SERVICE_APPSTORE_TYPE, NULL));
-	ApplicationServiceAppstorePrivate * priv = appstore->priv;
-	priv->lrufile = lrufile;
 	return appstore;
 }
 

=== modified file 'src/application-service-appstore.h'
--- src/application-service-appstore.h	2010-08-05 21:54:12 +0000
+++ src/application-service-appstore.h	2010-08-11 20:58:44 +0000
@@ -25,7 +25,6 @@
 
 #include <glib.h>
 #include <glib-object.h>
-#include "application-service-lru-file.h"
 
 G_BEGIN_DECLS
 
@@ -56,7 +55,7 @@
 	ApplicationServiceAppstorePrivate * priv;
 };
 
-ApplicationServiceAppstore * application_service_appstore_new (AppLruFile * lrufile);
+ApplicationServiceAppstore * application_service_appstore_new (void);
 GType application_service_appstore_get_type               (void);
 void  application_service_appstore_application_add        (ApplicationServiceAppstore *   appstore,
                                                            const gchar *             dbus_name,

=== removed file 'src/application-service-lru-file.c'
--- src/application-service-lru-file.c	2010-01-20 22:41:38 +0000
+++ src/application-service-lru-file.c	1970-01-01 00:00:00 +0000
@@ -1,473 +0,0 @@
-/*
-This object manages the database of when the entires were touched
-and loved.  And writes that out to disk occationally as well.
-
-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/>.
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-#include <gio/gio.h>
-#include <json-glib/json-glib.h>
-#include "application-service-lru-file.h"
-
-#define ENTRY_CATEGORY   "category"
-#define ENTRY_FIRST_TIME "first-time"
-#define ENTRY_LAST_TIME  "last-time"
-#define ENTRY_VERSION    "version"
-
-#define CONFIG_DIR       ("indicators" G_DIR_SEPARATOR_S "application")
-#define CONFIG_FILE      "lru-file.json"
-
-typedef struct _AppLruFilePrivate AppLruFilePrivate;
-struct _AppLruFilePrivate {
-	GHashTable * apps;
-	gboolean dirty;
-	guint timer;
-	gchar * filename;
-};
-
-typedef struct _AppData AppData;
-struct _AppData {
-	gchar * category;
-	GTimeVal last_touched;
-	GTimeVal first_touched;
-};
-
-#define APP_LRU_FILE_GET_PRIVATE(o) \
-		(G_TYPE_INSTANCE_GET_PRIVATE ((o), APP_LRU_FILE_TYPE, AppLruFilePrivate))
-
-static void app_lru_file_class_init (AppLruFileClass *klass);
-static void app_lru_file_init       (AppLruFile *self);
-static void app_lru_file_dispose    (GObject *object);
-static void app_lru_file_finalize   (GObject *object);
-static void app_data_free           (gpointer data);
-static void get_dirty (AppLruFile * lrufile);
-static gboolean load_from_file      (gpointer data);
-static void load_file_object_cb (JsonObject * obj, const gchar * key, JsonNode * value, gpointer data);
-static void clean_off_hash_cb (gpointer key, gpointer value, gpointer data);
-static void clean_off_write_end_cb (GObject * obj, GAsyncResult * res, gpointer data);
-
-G_DEFINE_TYPE (AppLruFile, app_lru_file, G_TYPE_OBJECT);
-
-/* Set up the class variable stuff */
-static void
-app_lru_file_class_init (AppLruFileClass *klass)
-{
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
-	g_type_class_add_private (klass, sizeof (AppLruFilePrivate));
-
-	object_class->dispose = app_lru_file_dispose;
-	object_class->finalize = app_lru_file_finalize;
-
-	return;
-}
-
-/* Set all the data of the per-instance variables */
-static void
-app_lru_file_init (AppLruFile *self)
-{
-	AppLruFilePrivate * priv = APP_LRU_FILE_GET_PRIVATE(self);
-
-	/* Default values */
-	priv->apps = NULL;
-	priv->dirty = FALSE;
-	priv->timer = 0;
-	priv->filename = NULL;
-
-	/* Now let's build some stuff */
-	priv->apps = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, app_data_free);
-	priv->filename = g_build_filename(g_get_user_config_dir(), CONFIG_DIR, CONFIG_FILE, NULL);
-
-	/* No reason to delay other stuff for this, we'll
-	   merge any values that get touched. */
-	g_idle_add(load_from_file, self);
-
-	return;
-}
-
-/* Get rid of objects and other big things */
-static void
-app_lru_file_dispose (GObject *object)
-{
-	AppLruFilePrivate * priv = APP_LRU_FILE_GET_PRIVATE(object);
-
-	if (priv->timer != 0) {
-		g_source_remove(priv->timer);
-		priv->timer = 0;
-	}
-
-	if (priv->apps != NULL) {
-		/* Cleans up the keys and entries itself */
-		g_hash_table_destroy(priv->apps);
-		priv->apps = NULL;
-	}
-
-	G_OBJECT_CLASS (app_lru_file_parent_class)->dispose (object);
-	return;
-}
-
-/* Deallocate memory */
-static void
-app_lru_file_finalize (GObject *object)
-{
-	AppLruFilePrivate * priv = APP_LRU_FILE_GET_PRIVATE(object);
-	
-	if (priv->filename != NULL) {
-		g_free(priv->filename);
-		priv->filename = NULL;
-	}
-
-	G_OBJECT_CLASS (app_lru_file_parent_class)->finalize (object);
-	return;
-}
-
-/* Takes an AppData structure and free's the
-   memory from it. */
-static void
-app_data_free (gpointer data)
-{
-	AppData * appdata = (AppData *)data;
-
-	if (appdata->category != NULL) {
-		g_free(appdata->category);
-	}
-
-	g_free(appdata);
-
-	return;
-}
-
-/* Loads all of the data out of a json file */
-static gboolean
-load_from_file (gpointer data)
-{
-	AppLruFile * lrufile = (AppLruFile *)data;
-	AppLruFilePrivate * priv = APP_LRU_FILE_GET_PRIVATE(lrufile);
-
-	if (!g_file_test(priv->filename, G_FILE_TEST_EXISTS)) {
-		return FALSE;
-	}
-
-	JsonParser * parser = json_parser_new();
-
-	if (!json_parser_load_from_file(parser, priv->filename, NULL)) {
-		g_warning("Unable to parse JSON file '%s'", priv->filename);
-		g_object_unref(parser);
-		return FALSE;
-	}
-
-	JsonNode * root = json_parser_get_root(parser);
-	JsonObject * rootobj = json_node_get_object(root);
-	if (rootobj == NULL) {
-		g_warning("Malformed LRU file.  The root node is not an object.");
-		g_object_unref(parser);
-		return FALSE;
-	}
-
-	json_object_foreach_member(rootobj, load_file_object_cb, lrufile);
-
-	g_object_unref(parser);
-	return FALSE;
-}
-
-/* Looks at the various things that we need on a node, makes
-   sure that we have them, and then copies them into the
-   application hash table of love. */
-static void
-load_file_object_cb (JsonObject * rootobj, const gchar * key, JsonNode * value, gpointer data)
-{
-	AppLruFile * lrufile = (AppLruFile *)data;
-	AppLruFilePrivate * priv = APP_LRU_FILE_GET_PRIVATE(lrufile);
-
-	/* We're not looking at this today. */
-	if (!g_strcmp0(key, ENTRY_VERSION)) {
-		return;
-	}
-
-	JsonObject * obj = json_node_get_object(value);
-	if (obj == NULL) {
-		g_warning("Data for node '%s' is not an object.", key);
-		return;
-	}
-
-	const gchar * obj_category = json_object_get_string_member(obj, ENTRY_CATEGORY);
-	const gchar * obj_first    = json_object_get_string_member(obj, ENTRY_FIRST_TIME);
-	const gchar * obj_last     = json_object_get_string_member(obj, ENTRY_LAST_TIME);
-
-	if (obj_category == NULL || obj_first == NULL || obj_last == NULL) {
-		g_warning("Node '%s' is missing data.  Got: ('%s', '%s', '%s')", key, obj_category, obj_first, obj_last);
-		get_dirty(lrufile);
-		return;
-	}
-
-	/* Check to see how old this entry is.  If it hasn't been
-	   used in the last year, we remove the cruft. */
-	GTimeVal currenttime;
-	g_get_current_time(&currenttime);
-	GDate * currentdate = g_date_new();
-	g_date_set_time_val(currentdate, &currenttime);
-
-	GTimeVal lasttouch;
-	g_time_val_from_iso8601(obj_last, &lasttouch);
-	GDate * lastdate = g_date_new();
-	g_date_set_time_val(lastdate, &lasttouch);
-
-	gint spread = g_date_days_between(lastdate, currentdate);
-
-	g_date_free(currentdate);
-	g_date_free(lastdate);
-
-	if (spread > 365) {
-		g_debug("Removing node '%s' as it's %d days old.", key, spread);
-		get_dirty(lrufile);
-		return;
-	}
-
-	/* See if we already have one of these.  It's a little bit
-	   unlikely, but since we're async, we need to check */
-	gpointer datapntr = g_hash_table_lookup(priv->apps, key);
-	if (datapntr == NULL) {
-		/* Build a new node */
-		AppData * appdata = g_new0(AppData, 1);
-		appdata->category = g_strdup(obj_category);
-		g_time_val_from_iso8601(obj_first, &appdata->first_touched);
-		g_time_val_from_iso8601(obj_last, &appdata->last_touched);
-
-		g_hash_table_insert(priv->apps, g_strdup(key), appdata);
-	} else {
-		/* Merge nodes */
-		AppData * appdata = (AppData *)datapntr;
-		GTimeVal temptime;
-		g_time_val_from_iso8601(obj_first, &temptime);
-
-		if (temptime.tv_sec < appdata->first_touched.tv_sec) {
-			g_time_val_from_iso8601(obj_first, &appdata->first_touched);
-		}
-	}
-
-	return;
-}
-
-/* Write out our cache to a file so that we can unmark the dirty
-   bit and be happy. */
-static gboolean
-clean_off (gpointer data)
-{
-	AppLruFile * lrufile = (AppLruFile *)data;
-	AppLruFilePrivate * priv = APP_LRU_FILE_GET_PRIVATE(lrufile);
-	priv->timer = 0;
-
-	GError * error = NULL;
-	
-	/* Check to see if our directory exists.  Build it if not. */
-	gchar * dirname = g_build_filename(g_get_user_config_dir(), CONFIG_DIR, NULL);
-	if (!g_file_test(dirname, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
-		GFile * dirfile = g_file_new_for_path(dirname);
-		g_file_make_directory_with_parents(dirfile, NULL, NULL);
-		g_object_unref(dirfile);
-	}
-	g_free(dirname);
-
-	GFile * file = g_file_new_for_path(priv->filename);
-	GFileOutputStream * ostream = g_file_replace(file,
-	                                             NULL, /* etag */
-	                                             TRUE, /* backup */
-	                                             G_FILE_CREATE_NONE, /* flags */
-	                                             NULL, /* cancelable */
-	                                             &error);
-	if (error != NULL) {
-		g_warning("Unable to open a file to store LRU file: %s", error->message);
-		return FALSE;
-	}
-
-	/* This is how the file will start */
-	GString * filestring = g_string_new("{\n  \"" ENTRY_VERSION "\": 1");
-
-	/* Put the middle in. */
-	g_hash_table_foreach (priv->apps, clean_off_hash_cb, filestring);
-
-	/* And then tack on the end. */
-	g_string_append(filestring, "\n}\n");
-	gchar * filedata = g_string_free(filestring, FALSE);
-	g_output_stream_write_async(G_OUTPUT_STREAM(ostream),
-	                            filedata,
-	                            strlen(filedata),
-	                            G_PRIORITY_DEFAULT_IDLE,
-	                            NULL,
-	                            clean_off_write_end_cb,
-	                            filedata);
-
-	return FALSE; /* drop the timer */
-}
-
-/* Looks at every value in the applications hash table and
-   turns it into a string for writing out. */
-static void
-clean_off_hash_cb (gpointer key, gpointer value, gpointer data)
-{
-	/* Mega-cast */
-	gchar * id = (gchar *)key;
-	AppData * appdata = (AppData *)value;
-	GString * string = (GString *)data;
-
-	gchar * firsttime = g_time_val_to_iso8601(&appdata->first_touched);
-	gchar * lasttime = g_time_val_to_iso8601(&appdata->last_touched);
-
-	g_string_append_printf(string, ",\n  \"%s\": { \"" ENTRY_FIRST_TIME "\": \"%s\", \"" ENTRY_LAST_TIME "\": \"%s\", \"" ENTRY_CATEGORY "\": \"%s\"}", id, firsttime, lasttime, appdata->category);
-
-	g_free(lasttime);
-	g_free(firsttime);
-
-	return;
-}
-
-/* Very much like clean_off_write_cb except that it is the
-   last actor on this Output Stream so it closes it. */
-static void
-clean_off_write_end_cb (GObject * obj, GAsyncResult * res, gpointer data)
-{
-	g_free(data);
-
-	GError * error = NULL;
-	g_output_stream_close(G_OUTPUT_STREAM(obj), NULL, &error);
-
-	if (error != NULL) {
-		g_warning("Unable to close LRU File: %s", error->message);
-		g_error_free(error);
-	}
-
-	return;
-}
-
-/* Sets the dirty bit if not already set and makes sure that
-   we have a timer to fix that at some point. */
-static void
-get_dirty (AppLruFile * lrufile)
-{
-	AppLruFilePrivate * priv = APP_LRU_FILE_GET_PRIVATE(lrufile);
-
-	priv->dirty = TRUE;
-
-	if (priv->timer == 0) {
-		priv->timer = g_timeout_add_seconds(60, clean_off, lrufile);
-	}
-
-	return;
-}
-
-/* API */
-
-/* Simple helper to create a new object */
-AppLruFile *
-app_lru_file_new (void)
-{
-	return APP_LRU_FILE(g_object_new(APP_LRU_FILE_TYPE, NULL));
-}
-
-/* This updates the timestamp for a particular
-   entry in the database.  It also queues up a 
-   write out of the database.  But that'll happen
-   later. */
-void
-app_lru_file_touch (AppLruFile * lrufile, const gchar * id, const gchar * category)
-{
-	g_return_if_fail(IS_APP_LRU_FILE(lrufile));
-	g_return_if_fail(id != NULL && id[0] != '\0');
-	g_return_if_fail(category != NULL && category[0] != '\0');
-
-	AppData * appdata = NULL;
-	AppLruFilePrivate * priv = APP_LRU_FILE_GET_PRIVATE(lrufile);
-	gpointer data = g_hash_table_lookup(priv->apps, id);
-
-	if (data == NULL) {
-		/* Oh, we don't have one, let's build it and put it
-		   into the hash table ourselves */
-		appdata = g_new0(AppData, 1);
-
-		appdata->category = g_strdup(category);
-		g_get_current_time(&(appdata->first_touched));
-		/* NOTE: last touched set below */
-
-		g_hash_table_insert(priv->apps, g_strdup(id), appdata);
-	} else {
-		/* Boring, we've got this one already */
-		appdata = (AppData *)data;
-	}
-
-	/* Touch it and mark the DB as dirty */
-	g_get_current_time(&(appdata->last_touched));
-	get_dirty(lrufile);
-	return;
-}
-
-/* Used to sort or compare different applications. */
-gint
-app_lru_file_sort (AppLruFile * lrufile, const gchar * id_a, const gchar * id_b)
-{
-	g_return_val_if_fail(IS_APP_LRU_FILE(lrufile), -1);
-
-	/* Let's first look to see if the IDs are the same, this
-	   really shouldn't happen, but it'll be confusing if we
-	   don't get it out of the way to start. */
-	if (g_strcmp0(id_a, id_b) == 0) {
-		return 0;
-	}
-
-	AppLruFilePrivate * priv = APP_LRU_FILE_GET_PRIVATE(lrufile);
-
-	/* Now make sure we have app data for both of these.  If
-	   not we'll assume that the one without is newer? */
-	gpointer data_a = g_hash_table_lookup(priv->apps, id_a);
-	if (data_a == NULL) {
-		return -1;
-	}
-
-	gpointer data_b = g_hash_table_lookup(priv->apps, id_b);
-	if (data_b == NULL) {
-		return 1;
-	}
-
-	/* Ugly casting */
-	AppData * appdata_a = (AppData *)data_a;
-	AppData * appdata_b = (AppData *)data_b;
-
-	/* Look at categories, we'll put the categories in alpha
-	   order if they're not the same. */
-	gint catcompare = g_strcmp0(appdata_a->category, appdata_b->category);
-	if (catcompare != 0) {
-		return catcompare;
-	}
-
-	/* Now we're looking at the first time that these two were
-	   seen in this account.  Only using seconds.  I mean, seriously. */
-	if (appdata_a->first_touched.tv_sec < appdata_b->first_touched.tv_sec) {
-		return -1;
-	}
-	if (appdata_b->first_touched.tv_sec < appdata_a->first_touched.tv_sec) {
-		return 1;
-	}
-
-	/* Eh, this seems roughly impossible.  But if we have to choose,
-	   I like A better. */
-	return 1;
-}

=== removed file 'src/application-service-lru-file.h'
--- src/application-service-lru-file.h	2010-01-20 22:28:13 +0000
+++ src/application-service-lru-file.h	1970-01-01 00:00:00 +0000
@@ -1,59 +0,0 @@
-/*
-This object manages the database of when the entires were touched
-and loved.  And writes that out to disk occationally as well.
-
-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 __APP_LRU_FILE_H__
-#define __APP_LRU_FILE_H__
-
-#include <glib.h>
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-
-#define APP_LRU_FILE_TYPE            (app_lru_file_get_type ())
-#define APP_LRU_FILE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), APP_LRU_FILE_TYPE, AppLruFile))
-#define APP_LRU_FILE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), APP_LRU_FILE_TYPE, AppLruFileClass))
-#define IS_APP_LRU_FILE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), APP_LRU_FILE_TYPE))
-#define IS_APP_LRU_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), APP_LRU_FILE_TYPE))
-#define APP_LRU_FILE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), APP_LRU_FILE_TYPE, AppLruFileClass))
-
-typedef struct _AppLruFile      AppLruFile;
-typedef struct _AppLruFileClass AppLruFileClass;
-
-struct _AppLruFileClass {
-	GObjectClass parent_class;
-
-};
-
-struct _AppLruFile {
-	GObject parent;
-
-};
-
-GType app_lru_file_get_type (void);
-
-AppLruFile * app_lru_file_new (void);
-void app_lru_file_touch (AppLruFile * lrufile, const gchar * id, const gchar * category);
-gint app_lru_file_sort  (AppLruFile * lrufile, const gchar * id_a, const gchar * id_b);
-
-G_END_DECLS
-
-#endif

=== modified file 'src/application-service.c'
--- src/application-service.c	2010-01-19 23:20:21 +0000
+++ src/application-service.c	2010-08-11 20:58:44 +0000
@@ -25,7 +25,6 @@
 #include "notification-item-client.h"
 #include "application-service-appstore.h"
 #include "application-service-watcher.h"
-#include "application-service-lru-file.h"
 #include "dbus-shared.h"
 
 /* The base main loop */
@@ -36,8 +35,6 @@
 static ApplicationServiceWatcher * watcher = NULL;
 /* The service management interface */
 static IndicatorService * service = NULL;
-/* The LRU file interface */
-static AppLruFile * lrufile = NULL;
 
 /* Recieves the disonnection signal from the service
    object and closes the mainloop. */
@@ -62,11 +59,8 @@
 	service = indicator_service_new(INDICATOR_APPLICATION_DBUS_ADDR);
 	g_signal_connect(G_OBJECT(service), INDICATOR_SERVICE_SIGNAL_SHUTDOWN, G_CALLBACK(service_disconnected), NULL);
 
-	/* Start up the LRU file reading */
-	lrufile = app_lru_file_new();
-
 	/* Building our app store */
-	appstore = application_service_appstore_new(lrufile);
+	appstore = application_service_appstore_new();
 
 	/* Adding a watcher for the Apps coming up */
 	watcher = application_service_watcher_new(appstore);
@@ -79,7 +73,6 @@
 	g_object_unref(G_OBJECT(watcher));
 	g_object_unref(G_OBJECT(appstore));
 	g_object_unref(G_OBJECT(service));
-	g_object_unref(G_OBJECT(lrufile));
 
 	return 0;
 }

=== added file 'src/generate-id.c'
--- src/generate-id.c	1970-01-01 00:00:00 +0000
+++ src/generate-id.c	2010-08-11 20:58:44 +0000
@@ -0,0 +1,69 @@
+/*
+Quick litte lack to generate the ordering ID.
+
+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 "generate-id.h"
+
+#define MULTIPLIER 32
+
+guint32
+generate_id (const AppIndicatorCategory catenum, const gchar * id)
+{
+	guchar category = 0;
+	guchar first = 0;
+	guchar second = 0;
+	guchar third = 0;
+
+	switch (catenum) {
+	case APP_INDICATOR_CATEGORY_OTHER:
+		category = MULTIPLIER * 5;
+		break;
+	case APP_INDICATOR_CATEGORY_APPLICATION_STATUS:
+		category = MULTIPLIER * 4;
+		break;
+	case APP_INDICATOR_CATEGORY_COMMUNICATIONS:
+		category = MULTIPLIER * 3;
+		break;
+	case APP_INDICATOR_CATEGORY_SYSTEM_SERVICES:
+		category = MULTIPLIER * 2;
+		break;
+	case APP_INDICATOR_CATEGORY_HARDWARE:
+		category = MULTIPLIER * 1;
+		break;
+	default:
+		g_warning("Got an undefined category: %d", category);
+		category = 0;
+		break;
+	}
+	
+	if (id != NULL) {
+		if (id[0] != '\0') {
+			first = id[0];
+			if (id[1] != '\0') {
+				second = id[1];
+				if (id[2] != '\0') {
+					third = id[2];
+				}
+			}
+		}
+	}
+
+	return (((((category * 256) + first) * 256) + second) * 256) + third;
+}

=== added file 'src/generate-id.h'
--- src/generate-id.h	1970-01-01 00:00:00 +0000
+++ src/generate-id.h	2010-08-11 20:58:44 +0000
@@ -0,0 +1,30 @@
+/*
+Quick litte lack to generate the ordering ID.
+
+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 __GENERATE_ID_H__
+#define __GENERATE_ID_H__
+
+#include <glib.h>
+#include "app-indicator.h"
+
+guint32 generate_id (const AppIndicatorCategory category, const gchar * id);
+
+#endif /* __GENERATE_ID_H__ */

=== modified file 'src/notification-item.xml'
--- src/notification-item.xml	2010-08-11 20:58:43 +0000
+++ src/notification-item.xml	2010-08-11 20:58:44 +0000
@@ -14,6 +14,7 @@
 		<property name="Menu" type="o" access="read" />
 		<property name="XAyatanaLabel" type="s" access="read" />
 		<property name="XAyatanaLabelGuide" type="s" access="read" />
+		<property name="XAyatanaOrderingIndex" type="u" access="read" />
 
 <!-- Methods -->
 		<!-- None currently -->


Follow ups