aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bzrignore1
-rw-r--r--src/Makefile.am12
-rw-r--r--src/app-indicator.c80
-rw-r--r--src/app-indicator.h3
-rw-r--r--src/application-service-appstore.c45
-rw-r--r--src/application-service-appstore.h3
-rw-r--r--src/application-service-lru-file.c473
-rw-r--r--src/application-service-lru-file.h59
-rw-r--r--src/application-service.c9
-rw-r--r--src/generate-id.c60
-rw-r--r--src/generate-id.h29
-rw-r--r--src/notification-item.xml1
12 files changed, 207 insertions, 568 deletions
diff --git a/.bzrignore b/.bzrignore
index 94155ae..6183694 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -113,3 +113,4 @@ tests/test-approver
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
diff --git a/src/Makefile.am b/src/Makefile.am
index 0e84749..a7cfc0b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -44,17 +44,19 @@ indicator_application_service_SOURCES = \
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) \
-Wall -Werror \
-DG_LOG_DOMAIN=\"indicator-application-service\"
+
indicator_application_service_LDADD = \
$(INDICATOR_LIBS) \
libappindicator.la
@@ -95,7 +97,9 @@ libappindicator_la_SOURCES = \
$(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 \
diff --git a/src/app-indicator.c b/src/app-indicator.c
index 22b9c03..e4138d4 100644
--- a/src/app-indicator.c
+++ b/src/app-indicator.c
@@ -43,6 +43,7 @@ License version 3 and version 2.1 along with this program. If not, see
#include "notification-watcher-client.h"
#include "dbus-shared.h"
+#include "generate-id.h"
#define PANEL_ICON_SUFFIX "panel"
@@ -73,6 +74,7 @@ struct _AppIndicatorPrivate {
gchar *icon_theme_path;
DbusmenuServer *menuservice;
GtkWidget *menu;
+ guint32 ordering_index;
gchar * label;
gchar * label_guide;
guint label_change_idle;
@@ -112,7 +114,8 @@ enum {
PROP_MENU,
PROP_CONNECTED,
PROP_LABEL,
- PROP_LABEL_GUIDE
+ PROP_LABEL_GUIDE,
+ PROP_ORDERING_INDEX
};
/* The strings so that they can be slowly looked up. */
@@ -126,6 +129,7 @@ enum {
#define PROP_CONNECTED_S "connected"
#define PROP_LABEL_S "label"
#define PROP_LABEL_GUIDE_S "label-guide"
+#define PROP_ORDERING_INDEX_S "ordering-index"
/* Private macro, shhhh! */
#define APP_INDICATOR_GET_PRIVATE(o) \
@@ -330,6 +334,25 @@ app_indicator_class_init (AppIndicatorClass *klass)
"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));
/* Signals */
@@ -446,6 +469,7 @@ app_indicator_init (AppIndicator *self)
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;
@@ -694,6 +718,9 @@ app_indicator_set_property (GObject * object, guint prop_id, const GValue * valu
}
break;
}
+ case PROP_ORDERING_INDEX:
+ priv->ordering_index = g_value_get_uint(value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -760,6 +787,14 @@ app_indicator_get_property (GObject * object, guint prop_id, GValue * value, GPa
g_value_set_string (value, priv->label_guide);
break;
+ case PROP_ORDERING_INDEX:
+ if (priv->ordering_index == 0) {
+ g_value_set_uint(value, generate_id(priv->category, priv->id));
+ } else {
+ g_value_set_uint(value, priv->ordering_index);
+ }
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1785,6 +1820,27 @@ app_indicator_set_menu (AppIndicator *self, GtkMenu *menu)
}
/**
+ 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
@@ -1933,3 +1989,25 @@ app_indicator_get_label_guide (AppIndicator *self)
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);
+
+ guint ordering_index = 0;
+
+ g_object_get(G_OBJECT(self),
+ PROP_ORDERING_INDEX_S, &ordering_index,
+ NULL);
+
+ return ordering_index;
+}
+
diff --git a/src/app-indicator.h b/src/app-indicator.h
index a9e1c38..ce152bb 100644
--- a/src/app-indicator.h
+++ b/src/app-indicator.h
@@ -265,6 +265,8 @@ void app_indicator_set_label (AppIndicator
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 @@ const gchar * app_indicator_get_attention_icon (AppIndicator *
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
diff --git a/src/application-service-appstore.c b/src/application-service-appstore.c
index 55906ff..5fc4f9b 100644
--- a/src/application-service-appstore.c
+++ b/src/application-service-appstore.c
@@ -32,21 +32,23 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#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 "Label"
-#define NOTIFICATION_ITEM_PROP_LABEL_GUIDE "LabelGuide"
+#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 "Label"
+#define NOTIFICATION_ITEM_PROP_LABEL_GUIDE "LabelGuide"
+#define NOTIFICATION_ITEM_PROP_ORDERING_INDEX "OrderingIndex"
#define NOTIFICATION_ITEM_SIG_NEW_ICON "NewIcon"
#define NOTIFICATION_ITEM_SIG_NEW_AICON "NewAttentionIcon"
@@ -59,7 +61,6 @@ struct _ApplicationServiceAppstorePrivate {
DBusGConnection * bus;
GList * applications;
GList * approvers;
- AppLruFile * lrufile;
};
typedef struct _Approver Approver;
@@ -85,6 +86,7 @@ struct _Application {
gchar * label;
gchar * guide;
gboolean currently_free;
+ guint ordering_index;
};
#define APPLICATION_SERVICE_APPSTORE_GET_PRIVATE(o) \
@@ -181,7 +183,6 @@ application_service_appstore_init (ApplicationServiceAppstore *self)
priv->applications = NULL;
priv->approvers = NULL;
- priv->lrufile = NULL;
GError * error = NULL;
priv->bus = dbus_g_bus_get(DBUS_BUS_STARTER, &error);
@@ -257,7 +258,6 @@ get_all_properties_cb (DBusGProxy * proxy, GHashTable * properties, GError * err
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 +281,13 @@ get_all_properties_cb (DBusGProxy * proxy, GHashTable * properties, GError * err
app->icon_theme_path = g_strdup("");
}
+ 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_status(app->category), app->id);
+ } else {
+ app->ordering_index = g_value_get_uint(ordering_index_data);
+ }
+
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);
@@ -440,15 +447,13 @@ can_add_application (GList *applications, Application *app)
}
/* 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 appa->ordering_index - appb->ordering_index;
}
/* Change the status of the application. If we're going passive
@@ -485,7 +490,7 @@ apply_status (Application * app, AppIndicatorStatus status)
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 +739,7 @@ application_service_appstore_application_add (ApplicationServiceAppstore * appst
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 +859,9 @@ application_service_appstore_application_remove (ApplicationServiceAppstore * ap
/* 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;
}
diff --git a/src/application-service-appstore.h b/src/application-service-appstore.h
index 9ae2874..73f6a9d 100644
--- a/src/application-service-appstore.h
+++ b/src/application-service-appstore.h
@@ -25,7 +25,6 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <glib.h>
#include <glib-object.h>
-#include "application-service-lru-file.h"
G_BEGIN_DECLS
@@ -56,7 +55,7 @@ struct _ApplicationServiceAppstore {
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,
diff --git a/src/application-service-lru-file.c b/src/application-service-lru-file.c
deleted file mode 100644
index c69a20f..0000000
--- a/src/application-service-lru-file.c
+++ /dev/null
@@ -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@canonical.com>
-
-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;
-}
diff --git a/src/application-service-lru-file.h b/src/application-service-lru-file.h
deleted file mode 100644
index 7c92c82..0000000
--- a/src/application-service-lru-file.h
+++ /dev/null
@@ -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@canonical.com>
-
-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
diff --git a/src/application-service.c b/src/application-service.c
index ffd042e..94e7d2e 100644
--- a/src/application-service.c
+++ b/src/application-service.c
@@ -25,7 +25,6 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#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 ApplicationServiceAppstore * appstore = NULL;
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 @@ main (int argc, char ** argv)
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 @@ main (int argc, char ** argv)
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;
}
diff --git a/src/generate-id.c b/src/generate-id.c
new file mode 100644
index 0000000..6855b39
--- /dev/null
+++ b/src/generate-id.c
@@ -0,0 +1,60 @@
+/*
+Quick litte lack to generate the ordering ID.
+
+Copyright 2010 Canonical Ltd.
+
+Authors:
+ Ted Gould <ted@canonical.com>
+
+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"
+
+struct ordering_id_struct {
+ gchar category;
+ gchar first;
+ gchar second;
+ gchar third;
+};
+
+union ordering_id_union_t {
+ guint32 id;
+ struct ordering_id_struct str;
+};
+
+guint32
+generate_id (const gchar category, const gchar * id)
+{
+ union ordering_id_union_t u;
+
+ u.str.category = category;
+
+ u.str.first = 0;
+ u.str.second = 0;
+ u.str.third = 0;
+
+ if (id != NULL) {
+ if (id[0] != '\0') {
+ u.str.first = id[0];
+ if (id[1] != '\0') {
+ u.str.second = id[1];
+ if (id[2] != '\0') {
+ u.str.third = id[2];
+ }
+ }
+ }
+ }
+
+ return u.id;
+}
diff --git a/src/generate-id.h b/src/generate-id.h
new file mode 100644
index 0000000..3713158
--- /dev/null
+++ b/src/generate-id.h
@@ -0,0 +1,29 @@
+/*
+Quick litte lack to generate the ordering ID.
+
+Copyright 2010 Canonical Ltd.
+
+Authors:
+ Ted Gould <ted@canonical.com>
+
+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>
+
+guint32 generate_id (const gchar category, const gchar * id);
+
+#endif /* __GENERATE_ID_H__ */
diff --git a/src/notification-item.xml b/src/notification-item.xml
index 01261b5..ffd59d1 100644
--- a/src/notification-item.xml
+++ b/src/notification-item.xml
@@ -14,6 +14,7 @@
<property name="Menu" type="o" access="read" />
<property name="Label" type="s" access="read" />
<property name="LabelGuide" type="s" access="read" />
+ <property name="OrderingIndex" type="u" access="read" />
<!-- Methods -->
<!-- None currently -->