diff options
Diffstat (limited to 'src/app-menu-item.c')
-rw-r--r-- | src/app-menu-item.c | 140 |
1 files changed, 139 insertions, 1 deletions
diff --git a/src/app-menu-item.c b/src/app-menu-item.c index 2622010..4fe3298 100644 --- a/src/app-menu-item.c +++ b/src/app-menu-item.c @@ -29,6 +29,14 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #include <gio/gdesktopappinfo.h> #include "app-menu-item.h" +enum { + COUNT_CHANGED, + NAME_CHANGED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + typedef struct _AppMenuItemPrivate AppMenuItemPrivate; struct _AppMenuItemPrivate @@ -38,6 +46,8 @@ struct _AppMenuItemPrivate gchar * type; GAppInfo * appinfo; + guint unreadcount; + gboolean count_on_label; GtkWidget * name; }; @@ -52,6 +62,9 @@ static void app_menu_item_finalize (GObject *object); static void activate_cb (AppMenuItem * self, gpointer data); static void type_cb (IndicateListener * listener, IndicateListenerServer * server, gchar * value, gpointer data); static void desktop_cb (IndicateListener * listener, IndicateListenerServer * server, gchar * value, gpointer data); +static void indicator_added_cb (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * type, gpointer data); +static void indicator_removed_cb (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * type, gpointer data); +static void update_label (AppMenuItem * self); @@ -66,6 +79,23 @@ app_menu_item_class_init (AppMenuItemClass *klass) object_class->dispose = app_menu_item_dispose; object_class->finalize = app_menu_item_finalize; + + signals[COUNT_CHANGED] = g_signal_new(APP_MENU_ITEM_SIGNAL_COUNT_CHANGED, + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (AppMenuItemClass, count_changed), + NULL, NULL, + g_cclosure_marshal_VOID__UINT, + G_TYPE_NONE, 1, G_TYPE_UINT); + signals[NAME_CHANGED] = g_signal_new(APP_MENU_ITEM_SIGNAL_NAME_CHANGED, + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (AppMenuItemClass, name_changed), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); + + return; } static void @@ -79,6 +109,8 @@ app_menu_item_init (AppMenuItem *self) priv->name = NULL; priv->type = NULL; priv->appinfo = NULL; + priv->unreadcount = 0; + priv->count_on_label = FALSE; return; @@ -94,6 +126,14 @@ static void app_menu_item_finalize (GObject *object) { G_OBJECT_CLASS (app_menu_item_parent_class)->finalize (object); + + AppMenuItem * self = APP_MENU_ITEM(object); + AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self); + + g_signal_handlers_disconnect_by_func(G_OBJECT(priv->listener), G_CALLBACK(indicator_added_cb), self); + g_signal_handlers_disconnect_by_func(G_OBJECT(priv->listener), G_CALLBACK(indicator_removed_cb), self); + + return; } AppMenuItem * @@ -106,6 +146,9 @@ app_menu_item_new (IndicateListener * listener, IndicateListenerServer * server) priv->listener = listener; priv->server = server; + g_signal_connect(G_OBJECT(listener), INDICATE_LISTENER_SIGNAL_INDICATOR_ADDED, G_CALLBACK(indicator_added_cb), self); + g_signal_connect(G_OBJECT(listener), INDICATE_LISTENER_SIGNAL_INDICATOR_REMOVED, G_CALLBACK(indicator_removed_cb), self); + priv->name = gtk_label_new(INDICATE_LISTENER_SERVER_DBUS_NAME(server)); gtk_misc_set_alignment(GTK_MISC(priv->name), 0.0, 0.5); gtk_widget_show(GTK_WIDGET(priv->name)); @@ -132,6 +175,30 @@ type_cb (IndicateListener * listener, IndicateListenerServer * server, gchar * v priv->type = g_strdup(value); + if (!(!g_strcmp0(priv->type, "message.instant") || !g_strcmp0(priv->type, "message.micro") || !g_strcmp0(priv->type, "message.im"))) { + /* For IM and Microblogging we want the individual items, not a count */ + priv->count_on_label = TRUE; + update_label(self); + } + + return; +} + +static void +update_label (AppMenuItem * self) +{ + AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self); + + if (priv->count_on_label && !priv->unreadcount < 1) { + /* TRANSLATORS: This is the name of the program and the number of indicators. So it + would read something like "Mail Client (5)" */ + gchar * label = g_strdup_printf(_("%s (%d)"), g_app_info_get_name(priv->appinfo), priv->unreadcount); + gtk_label_set_text(GTK_LABEL(priv->name), label); + g_free(label); + } else { + gtk_label_set_text(GTK_LABEL(priv->name), g_app_info_get_name(priv->appinfo)); + } + return; } @@ -144,11 +211,16 @@ desktop_cb (IndicateListener * listener, IndicateListenerServer * server, gchar if (priv->appinfo != NULL) { g_object_unref(G_OBJECT(priv->appinfo)); } + + if (value == NULL || value[0] == '\0') { + return; + } priv->appinfo = G_APP_INFO(g_desktop_app_info_new_from_filename(value)); g_return_if_fail(priv->appinfo != NULL); - gtk_label_set_text(GTK_LABEL(priv->name), g_app_info_get_name(priv->appinfo)); + update_label(self); + g_signal_emit(G_OBJECT(self), signals[NAME_CHANGED], 0, g_app_info_get_name(priv->appinfo), TRUE); return; } @@ -162,3 +234,69 @@ activate_cb (AppMenuItem * self, gpointer data) return; } + +static void +indicator_added_cb (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * type, gpointer data) +{ + AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(data); + + if (g_strcmp0(INDICATE_LISTENER_SERVER_DBUS_NAME(server), INDICATE_LISTENER_SERVER_DBUS_NAME(priv->server))) { + /* Not us */ + return; + } + + priv->unreadcount++; + + update_label(APP_MENU_ITEM(data)); + g_signal_emit(G_OBJECT(data), signals[COUNT_CHANGED], 0, priv->unreadcount, TRUE); + + return; +} + +static void +indicator_removed_cb (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * type, gpointer data) +{ + AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(data); + + if (g_strcmp0(INDICATE_LISTENER_SERVER_DBUS_NAME(server), INDICATE_LISTENER_SERVER_DBUS_NAME(priv->server))) { + /* Not us */ + return; + } + + /* Should never happen, but let's have some protection on that */ + if (priv->unreadcount > 0) { + priv->unreadcount--; + } + + update_label(APP_MENU_ITEM(data)); + g_signal_emit(G_OBJECT(data), signals[COUNT_CHANGED], 0, priv->unreadcount, TRUE); + + return; +} + +guint +app_menu_item_get_count (AppMenuItem * appitem) +{ + AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(appitem); + + return priv->unreadcount; +} + +IndicateListenerServer * +app_menu_item_get_server (AppMenuItem * appitem) { + AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(appitem); + + return priv->server; +} + +const gchar * +app_menu_item_get_name (AppMenuItem * appitem) +{ + AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(appitem); + + if (priv->appinfo == NULL) { + return INDICATE_LISTENER_SERVER_DBUS_NAME(priv->server); + } else { + return g_app_info_get_name(priv->appinfo); + } +} |