aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Gould <ted@gould.cx>2010-01-07 16:27:18 -0600
committerTed Gould <ted@gould.cx>2010-01-07 16:27:18 -0600
commit45e742eba4c7cae1c732c83acae43033f5c39e90 (patch)
treee2ea202c99647d7b1a230890362f0823a6d77545
parent16fb78b663704da483de14c54fbcc4088a754c0e (diff)
downloadlibayatana-appindicator-45e742eba4c7cae1c732c83acae43033f5c39e90.tar.gz
libayatana-appindicator-45e742eba4c7cae1c732c83acae43033f5c39e90.tar.bz2
libayatana-appindicator-45e742eba4c7cae1c732c83acae43033f5c39e90.zip
Moving the list of applications management into the state change function. This makes it so that we can handle it appearing and disappearing all in one special place.
-rw-r--r--src/application-service-appstore.c136
1 files changed, 111 insertions, 25 deletions
diff --git a/src/application-service-appstore.c b/src/application-service-appstore.c
index 128139b..385bd16 100644
--- a/src/application-service-appstore.c
+++ b/src/application-service-appstore.c
@@ -53,6 +53,10 @@ struct _ApplicationServiceAppstorePrivate {
GList * applications;
};
+#define APP_STATUS_PASSIVE_STR "passive"
+#define APP_STATUS_ACTIVE_STR "active"
+#define APP_STATUS_ATTENTION_STR "attention"
+
typedef enum _ApplicationStatus ApplicationStatus;
enum _ApplicationStatus {
APP_STATUS_PASSIVE,
@@ -69,6 +73,9 @@ struct _Application {
DBusGProxy * prop_proxy;
gboolean validated; /* Whether we've gotten all the parameters and they look good. */
ApplicationStatus status;
+ gchar * icon;
+ gchar * aicon;
+ gchar * menu;
};
#define APPLICATION_SERVICE_APPSTORE_GET_PRIVATE(o) \
@@ -89,6 +96,8 @@ static void application_service_appstore_class_init (ApplicationServiceAppstoreC
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 ApplicationStatus string_to_status(const gchar * status_string);
+static void apply_status (Application * app, ApplicationStatus status);
G_DEFINE_TYPE (ApplicationServiceAppstore, application_service_appstore, G_TYPE_OBJECT);
@@ -190,6 +199,7 @@ get_all_properties_cb (DBusGProxy * proxy, GHashTable * properties, GError * err
Application * app = (Application *)data;
if (g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_MENU) == NULL ||
+ g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_STATUS) == NULL ||
g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_ICON_NAME) == NULL) {
g_warning("Notification Item on object %s of %s doesn't have enough properties.", app->dbus_object, app->dbus_name);
g_free(app); // Need to do more than this, but it gives the idea of the flow we're going for.
@@ -198,24 +208,28 @@ get_all_properties_cb (DBusGProxy * proxy, GHashTable * properties, GError * err
app->validated = TRUE;
- ApplicationServiceAppstorePrivate * priv = APPLICATION_SERVICE_APPSTORE_GET_PRIVATE(app->appstore);
- priv->applications = g_list_prepend(priv->applications, app);
-
- /* TODO: We need to have the position determined better. This
- would involve looking at the name and category and sorting
- it with the other entries. */
-
- g_signal_emit(G_OBJECT(app->appstore),
- signals[APPLICATION_ADDED], 0,
- g_value_get_string(g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_ICON_NAME)),
- 0, /* Position */
- app->dbus_name,
- g_value_get_string(g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_MENU)),
- TRUE);
+ app->icon = g_value_dup_string(g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_ICON_NAME));
+ app->menu = g_value_dup_string(g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_MENU));
+ if (g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_AICON_NAME) != NULL) {
+ app->aicon = g_value_dup_string(g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_ICON_NAME));
+ }
+
+ apply_status(app, string_to_status(g_value_get_string(g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_STATUS))));
return;
}
+/* Simple translation function -- could be optimized */
+static ApplicationStatus
+string_to_status(const gchar * status_string)
+{
+ if (!g_strcmp0(status_string, APP_STATUS_ACTIVE_STR))
+ return APP_STATUS_ACTIVE;
+ if (!g_strcmp0(status_string, APP_STATUS_ATTENTION_STR))
+ return APP_STATUS_ATTENTION;
+ return APP_STATUS_PASSIVE;
+}
+
/* A simple global function for dealing with freeing the information
in an Application structure */
static void
@@ -229,6 +243,15 @@ application_free (Application * app)
if (app->dbus_object != NULL) {
g_free(app->dbus_object);
}
+ if (app->icon != NULL) {
+ g_free(app->icon);
+ }
+ if (app->aicon != NULL) {
+ g_free(app->aicon);
+ }
+ if (app->menu != NULL) {
+ g_free(app->menu);
+ }
g_free(app);
return;
@@ -240,24 +263,84 @@ static void
application_removed_cb (DBusGProxy * proxy, gpointer userdata)
{
Application * app = (Application *)userdata;
- ApplicationServiceAppstore * appstore = app->appstore;
- ApplicationServiceAppstorePrivate * priv = APPLICATION_SERVICE_APPSTORE_GET_PRIVATE(appstore);
- GList * applistitem = g_list_find(priv->applications, app);
- if (applistitem == NULL) {
- g_warning("Removing an application that isn't in the application list?");
+ /* Remove from the panel */
+ apply_status(app, APP_STATUS_PASSIVE);
+
+ /* Destroy the data */
+ application_free(app);
+ return;
+}
+
+/* Change the status of the application. If we're going passive
+ it removes it from the panel. If we're coming online, then
+ it add it to the panel. Otherwise it changes the icon. */
+static void
+apply_status (Application * app, ApplicationStatus status)
+{
+ if (app->status == status) {
return;
}
- gint position = g_list_position(priv->applications, applistitem);
+ ApplicationServiceAppstore * appstore = app->appstore;
+ ApplicationServiceAppstorePrivate * priv = APPLICATION_SERVICE_APPSTORE_GET_PRIVATE(appstore);
- g_signal_emit(G_OBJECT(appstore),
- signals[APPLICATION_REMOVED], 0,
- position, TRUE);
+ /* This means we're going off line */
+ if (status == APP_STATUS_PASSIVE) {
+ GList * applistitem = g_list_find(priv->applications, app);
+ if (applistitem == NULL) {
+ g_warning("Removing an application that isn't in the application list?");
+ return;
+ }
+
+ gint position = g_list_position(priv->applications, applistitem);
+
+ g_signal_emit(G_OBJECT(appstore),
+ signals[APPLICATION_REMOVED], 0,
+ position, TRUE);
+
+ priv->applications = g_list_remove(priv->applications, app);
+ } else {
+ /* Figure out which icon we should be using */
+ gchar * newicon = app->icon;
+ if (status == APP_STATUS_ATTENTION && app->aicon != NULL) {
+ newicon = app->aicon;
+ }
+
+ /* Determine whether we're already shown or not */
+ if (app->status == APP_STATUS_PASSIVE) {
+ /* Put on panel */
+ priv->applications = g_list_prepend(priv->applications, app);
+
+ /* TODO: We need to have the position determined better. This
+ would involve looking at the name and category and sorting
+ it with the other entries. */
+
+ g_signal_emit(G_OBJECT(app->appstore),
+ signals[APPLICATION_ADDED], 0,
+ newicon,
+ 0, /* Position */
+ app->dbus_name,
+ app->menu,
+ TRUE);
+ } else {
+ /* Icon update */
+ GList * applistitem = g_list_find(priv->applications, app);
+ if (applistitem == NULL) {
+ g_warning("Change the icon of an application that isn't in the application list?");
+ return;
+ }
+
+ gint position = g_list_position(priv->applications, applistitem);
+
+ g_signal_emit(G_OBJECT(appstore),
+ signals[APPLICATION_ICON_CHANGED], 0,
+ position, newicon, TRUE);
+ }
+ }
- priv->applications = g_list_remove(priv->applications, app);
+ app->status = status;
- application_free(app);
return;
}
@@ -317,6 +400,9 @@ application_service_appstore_application_add (ApplicationServiceAppstore * appst
app->dbus_object = g_strdup(dbus_object);
app->appstore = appstore;
app->status = APP_STATUS_PASSIVE;
+ app->icon = NULL;
+ app->aicon = NULL;
+ app->menu = NULL;
/* Get the DBus proxy for the NotificationItem interface */
GError * error = NULL;