aboutsummaryrefslogtreecommitdiff
path: root/src/im-menu-item.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/im-menu-item.c')
-rw-r--r--src/im-menu-item.c586
1 files changed, 0 insertions, 586 deletions
diff --git a/src/im-menu-item.c b/src/im-menu-item.c
deleted file mode 100644
index 7466d3e..0000000
--- a/src/im-menu-item.c
+++ /dev/null
@@ -1,586 +0,0 @@
-/*
-An indicator to show information that is in messaging applications
-that the user is using.
-
-Copyright 2009 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 <glib/gi18n.h>
-#include <libdbusmenu-glib/client.h>
-#include <libindicate/indicator.h>
-#include <libindicate/indicator-messages.h>
-#include <libindicate/listener.h>
-#include "im-menu-item.h"
-#include "dbus-data.h"
-
-enum {
- TIME_CHANGED,
- ATTENTION_CHANGED,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-typedef struct _ImMenuItemPrivate ImMenuItemPrivate;
-
-struct _ImMenuItemPrivate
-{
- IndicateListener * listener;
- IndicateListenerServer * server;
- IndicateListenerIndicator * indicator;
-
- glong creation_seconds;
- glong seconds;
- gchar * count;
- gulong indicator_changed;
- gboolean attention;
- gboolean show;
-
- guint time_update_min;
-};
-
-#define IM_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), IM_MENU_ITEM_TYPE, ImMenuItemPrivate))
-
-/* Prototypes */
-static void im_menu_item_class_init (ImMenuItemClass *klass);
-static void im_menu_item_init (ImMenuItem *self);
-static void im_menu_item_dispose (GObject *object);
-static void im_menu_item_finalize (GObject *object);
-static void sender_cb (IndicateListener * listener,
- IndicateListenerServer * server,
- IndicateListenerIndicator * indicator,
- gchar * property,
- const gchar * propertydata,
- gpointer data);
-static void time_cb (IndicateListener * listener,
- IndicateListenerServer * server,
- IndicateListenerIndicator * indicator,
- gchar * property,
- const GTimeVal * propertydata,
- gpointer data);
-static void icon_cb (IndicateListener * listener,
- IndicateListenerServer * server,
- IndicateListenerIndicator * indicator,
- gchar * property,
- const gchar * propertydata,
- gpointer data);
-static void activate_cb (ImMenuItem * self,
- guint timestamp,
- gpointer data);
-static void indicator_modified_cb (IndicateListener * listener,
- IndicateListenerServer * server,
- IndicateListenerIndicator * indicator,
- gchar * property,
- ImMenuItem * self);
-
-G_DEFINE_TYPE (ImMenuItem, im_menu_item, DBUSMENU_TYPE_MENUITEM);
-
-static void
-im_menu_item_class_init (ImMenuItemClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- g_type_class_add_private (klass, sizeof (ImMenuItemPrivate));
-
- object_class->dispose = im_menu_item_dispose;
- object_class->finalize = im_menu_item_finalize;
-
- signals[TIME_CHANGED] = g_signal_new(IM_MENU_ITEM_SIGNAL_TIME_CHANGED,
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ImMenuItemClass, time_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__LONG,
- G_TYPE_NONE, 1, G_TYPE_LONG);
- signals[ATTENTION_CHANGED] = g_signal_new(IM_MENU_ITEM_SIGNAL_ATTENTION_CHANGED,
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ImMenuItemClass, attention_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__BOOLEAN,
- G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
-
- return;
-}
-
-static void
-im_menu_item_init (ImMenuItem *self)
-{
- g_debug("Building new IM Menu Item");
- ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self);
-
- /* Set the variables to NULL, but they should be
- configured further down the line. */
- priv->listener = NULL;
- priv->server = NULL;
- priv->indicator = NULL;
-
- /* A sane default, but look below */
- priv->creation_seconds = 0;
- priv->seconds = 0;
-
- /* Set the seconds to be the time when the item was
- created incase we're not given a better time. */
- GTimeVal current_time;
- g_get_current_time(&current_time);
- priv->creation_seconds = current_time.tv_sec;
-
- return;
-}
-
-static void
-im_menu_item_dispose (GObject *object)
-{
- G_OBJECT_CLASS (im_menu_item_parent_class)->dispose (object);
-
- ImMenuItem * self = IM_MENU_ITEM(object);
- ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self);
-
- if (priv->time_update_min != 0) {
- g_source_remove(priv->time_update_min);
- }
-
- g_signal_handler_disconnect(priv->listener, priv->indicator_changed);
- priv->indicator_changed = 0;
-
- return;
-}
-
-static void
-im_menu_item_finalize (GObject *object)
-{
- G_OBJECT_CLASS (im_menu_item_parent_class)->finalize (object);
-}
-
-/* Call back for getting icon data. It just passes it along
- to the indicator so that it can visualize it. Not our problem. */
-static void
-icon_cb (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * property, const gchar * propertydata, gpointer data)
-{
- gsize len;
- guchar *icon;
- icon = g_base64_decode (propertydata, &len);
- dbusmenu_menuitem_property_set_byte_array(DBUSMENU_MENUITEM(data), INDICATOR_MENUITEM_PROP_ICON, icon, len);
- g_free (icon);
- return;
-}
-
-/* This function takes the time and turns it into the appropriate
- string to put on the right side of the menu item. Of course it
- doesn't do that if there is a count set. If there's a count then
- it gets that space. */
-static void
-update_time (ImMenuItem * self)
-{
- ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self);
-
- /* Count has been set, so it takes priority. */
- if (priv->count != NULL) {
- return;
- }
-
- /* Seconds hasn't been set, so we just want to keep the time
- area blank. */
- if (priv->seconds == 0) {
- dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), INDICATOR_MENUITEM_PROP_RIGHT, "");
- return;
- }
-
- gchar * timestring = NULL;
-
- GTimeVal current_time;
- g_get_current_time(&current_time);
-
- guint elapsed_seconds = current_time.tv_sec - priv->seconds;
- guint elapsed_minutes = elapsed_seconds / 60;
-
- if (elapsed_seconds % 60 > 55) {
- /* We're using fuzzy timers, so we need fuzzy comparisons */
- elapsed_minutes += 1;
- }
-
- if (elapsed_minutes < 60) {
- /* TRANSLATORS: This string is used to represent the number of minutes
- since an IM has occured. It is in the right column
- of a menu so being brief is desirable, but one character
- is not a requirement. */
- timestring = g_strdup_printf(ngettext("%d m", "%d m", elapsed_minutes), elapsed_minutes);
- } else {
- guint elapsed_hours = elapsed_minutes / 60;
-
- if (elapsed_minutes % 60 > 55) {
- /* We're using fuzzy timers, so we need fuzzy comparisons */
- elapsed_hours += 1;
- }
-
- /* TRANSLATORS: This string is used to represent the number of hours
- since an IM has occured. It is in the right column
- of a menu so being brief is desirable, but one character
- is not a requirement. */
- timestring = g_strdup_printf(ngettext("%d h", "%d h", elapsed_hours), elapsed_hours);
- }
-
- if (timestring != NULL) {
- dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), INDICATOR_MENUITEM_PROP_RIGHT, timestring);
- g_free(timestring);
- }
-
- return;
-}
-
-/* This is a wrapper around update_time that matches the prototype
- needed to make this a timer callback. Silly. */
-static gboolean
-time_update_cb (gpointer data)
-{
- ImMenuItem * self = IM_MENU_ITEM(data);
-
- update_time(self);
-
- return TRUE;
-}
-
-/* Yet another time function. This one takes the time as formated as
- we get it from libindicate and turns it into the seconds that we're
- looking for. It should only be called once at the init with a new
- indicator and again when the value changes. */
-static void
-time_cb (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * property, const GTimeVal * propertydata, gpointer data)
-{
- g_debug("Got Time info");
- ImMenuItem * self = IM_MENU_ITEM(data);
- if (self == NULL) {
- g_error("Menu Item callback called without a menu item");
- return;
- }
-
- if (property == NULL || g_strcmp0(property, "time")) {
- g_warning("Time callback called without being sent the time.");
- return;
- }
-
- ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self);
-
- priv->seconds = propertydata->tv_sec;
-
- update_time(self);
-
- if (priv->time_update_min == 0) {
- priv->time_update_min = g_timeout_add_seconds(60, time_update_cb, self);
- }
-
- g_signal_emit(G_OBJECT(self), signals[TIME_CHANGED], 0, priv->seconds, TRUE);
-
- return;
-}
-
-/* Returns a newly allocated string which is 'str' with all occurences of
- * consecutive whitespace collapsed into single space character. */
-static gchar *
-collapse_whitespace (const gchar *str)
-{
- GString *result;
- gboolean in_space = FALSE;
-
- if (!str)
- return NULL;
-
- result = g_string_sized_new (strlen (str));
-
- while (*str) {
- gunichar c = g_utf8_get_char_validated (str, -1);
-
- if (c < 0)
- break;
-
- if (!g_unichar_isspace (c)) {
- g_string_append_unichar (result, c);
- in_space = FALSE;
- }
- else if (!in_space) {
- g_string_append_c (result, ' ');
- in_space = TRUE;
- }
-
- str = g_utf8_next_char (str);
- }
-
- return g_string_free (result, FALSE);
-}
-
-/* Callback from libindicate that is for getting the sender information
- on a particular indicator. */
-static void
-sender_cb (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * property, const gchar * propertydata, gpointer data)
-{
- gchar *label;
-
- g_debug("Got Sender Information: %s", propertydata);
- ImMenuItem * self = IM_MENU_ITEM(data);
-
- /* Our data should be right */
- g_return_if_fail(self != NULL);
- /* We should have a property name */
- g_return_if_fail(property != NULL);
- /* The Property should be sender or name */
- g_return_if_fail(!g_strcmp0(property, "sender") || !g_strcmp0(property, INDICATE_INDICATOR_MESSAGES_PROP_NAME));
-
- /* We might get the sender variable returning a
- null string as it doesn't exist on newer clients
- but we don't want to listen to that. */
- if (!g_strcmp0(property, "sender") && propertydata[0] == '\0') {
- return;
- }
-
- label = collapse_whitespace (propertydata);
- dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), INDICATOR_MENUITEM_PROP_LABEL, label);
- g_free (label);
-
- return;
-}
-
-/* Callback saying that the count is updated, we need to either put
- that on the menu item or just remove it if the count is gone. If
- that's the case we can update time. */
-static void
-count_cb (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * property, const gchar * propertydata, gpointer data)
-{
- g_debug("Got Count Information");
- ImMenuItem * self = IM_MENU_ITEM(data);
-
- /* Our data should be right */
- g_return_if_fail(self != NULL);
- /* We should have a property name */
- g_return_if_fail(property != NULL);
- /* The Property should be count */
- g_return_if_fail(!g_strcmp0(property, INDICATE_INDICATOR_MESSAGES_PROP_COUNT));
-
- ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self);
-
- if (propertydata == NULL || propertydata[0] == '\0') {
- /* The count is either being unset or it was never
- set in the first place. */
- if (priv->count != NULL) {
- g_free(priv->count);
- priv->count = NULL;
- update_time(self);
- dbusmenu_menuitem_property_set_bool (DBUSMENU_MENUITEM (self),
- INDICATOR_MENUITEM_PROP_RIGHT_IS_LOZENGE,
- FALSE);
- }
- return;
- }
-
- if (priv->count != NULL) {
- g_free(priv->count);
- }
-
- priv->count = g_strdup_printf("%s", propertydata);
- dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), INDICATOR_MENUITEM_PROP_RIGHT, priv->count);
- dbusmenu_menuitem_property_set_bool (DBUSMENU_MENUITEM (self),
- INDICATOR_MENUITEM_PROP_RIGHT_IS_LOZENGE,
- TRUE);
-
- return;
-}
-
-/* This is getting the attention variable that's looking at whether
- this indicator should be calling for attention or not. If we are,
- we need to signal that. */
-static void
-attention_cb (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * property, GVariant * propertydata, gpointer data)
-{
- g_debug("Got Attention Information");
- ImMenuItem * self = IM_MENU_ITEM(data);
-
- /* Our data should be right */
- g_return_if_fail(self != NULL);
- /* We should have a property name */
- g_return_if_fail(property != NULL);
- /* The Property should be count */
- g_return_if_fail(!g_strcmp0(property, INDICATE_INDICATOR_MESSAGES_PROP_ATTENTION));
-
- ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self);
-
- gboolean wantit;
- if (g_variant_is_of_type(propertydata, G_VARIANT_TYPE_BOOLEAN)) {
- wantit = g_variant_get_boolean(propertydata);
- } else if (g_variant_is_of_type(propertydata, G_VARIANT_TYPE_STRING)) {
- const gchar * propstring = g_variant_get_string(propertydata, NULL);
-
- if (propstring == NULL || propstring[0] == '\0' || !g_strcmp0(propstring, "false")) {
- wantit = FALSE;
- } else {
- wantit = TRUE;
- }
- } else {
- g_warning("Got property '%s' of an unknown type.", property);
- return;
- }
-
- if (priv->attention != wantit) {
- priv->attention = wantit;
- g_signal_emit(G_OBJECT(self), signals[ATTENTION_CHANGED], 0, wantit, TRUE);
- }
-
- return;
-}
-
-/* Callback when the item gets clicked on from the Messaging Menu */
-static void
-activate_cb (ImMenuItem * self, guint timestamp, gpointer data)
-{
- ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self);
-
- indicate_listener_display(priv->listener, priv->server, priv->indicator, timestamp);
-}
-
-/* Callback when a property gets modified. It figures out which one
- got modified and notifies the appropriate person. */
-void
-indicator_modified_cb (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * property, ImMenuItem * self)
-{
- ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self);
-
- /* Not meant for us */
- if (INDICATE_LISTENER_INDICATOR_ID(indicator) != INDICATE_LISTENER_INDICATOR_ID(priv->indicator)) return;
- if (server != priv->server) return;
-
- /* Determine which property has been changed and request the
- value go to the appropriate callback. */
- if (!g_strcmp0(property, INDICATE_INDICATOR_MESSAGES_PROP_NAME)) {
- indicate_listener_get_property(listener, server, indicator, INDICATE_INDICATOR_MESSAGES_PROP_NAME, sender_cb, self);
- } else if (!g_strcmp0(property, INDICATE_INDICATOR_MESSAGES_PROP_TIME)) {
- indicate_listener_get_property_time(listener, server, indicator, INDICATE_INDICATOR_MESSAGES_PROP_TIME, time_cb, self);
- } else if (!g_strcmp0(property, INDICATE_INDICATOR_MESSAGES_PROP_ICON)) {
- indicate_listener_get_property(listener, server, indicator, INDICATE_INDICATOR_MESSAGES_PROP_ICON, icon_cb, self);
- } else if (!g_strcmp0(property, INDICATE_INDICATOR_MESSAGES_PROP_COUNT)) {
- indicate_listener_get_property(listener, server, indicator, INDICATE_INDICATOR_MESSAGES_PROP_COUNT, count_cb, self);
- } else if (!g_strcmp0(property, INDICATE_INDICATOR_MESSAGES_PROP_ATTENTION)) {
- indicate_listener_get_property_variant(listener, server, indicator, INDICATE_INDICATOR_MESSAGES_PROP_ATTENTION, attention_cb, self);
- } else if (!g_strcmp0(property, "sender")) {
- /* This is a compatibility string with v1 and should be removed */
- g_debug("Indicator is using 'sender' property which is a v1 string.");
- indicate_listener_get_property(listener, server, indicator, "sender", sender_cb, self);
- }
-
- return;
-}
-
-ImMenuItem *
-im_menu_item_new (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator)
-{
- ImMenuItem * self = g_object_new(IM_MENU_ITEM_TYPE, NULL);
-
- ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self);
-
- priv->listener = listener;
- priv->server = server;
- priv->indicator = indicator;
- priv->count = NULL;
- priv->time_update_min = 0;
- priv->attention = FALSE;
- priv->show = TRUE;
-
- dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), DBUSMENU_MENUITEM_PROP_TYPE, INDICATOR_MENUITEM_TYPE);
-
- indicate_listener_displayed(listener, server, indicator, TRUE);
-
- indicate_listener_get_property(listener, server, indicator, INDICATE_INDICATOR_MESSAGES_PROP_NAME, sender_cb, self);
- indicate_listener_get_property_time(listener, server, indicator, INDICATE_INDICATOR_MESSAGES_PROP_TIME, time_cb, self);
- indicate_listener_get_property(listener, server, indicator, INDICATE_INDICATOR_MESSAGES_PROP_ICON, icon_cb, self);
- indicate_listener_get_property(listener, server, indicator, INDICATE_INDICATOR_MESSAGES_PROP_COUNT, count_cb, self);
- indicate_listener_get_property_variant(listener, server, indicator, INDICATE_INDICATOR_MESSAGES_PROP_ATTENTION, attention_cb, self);
- indicate_listener_get_property(listener, server, indicator, "sender", sender_cb, self);
-
- g_signal_connect(G_OBJECT(self), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(activate_cb), NULL);
- priv->indicator_changed = g_signal_connect(G_OBJECT(listener), INDICATE_LISTENER_SIGNAL_INDICATOR_MODIFIED, G_CALLBACK(indicator_modified_cb), self);
-
- return self;
-}
-
-/* Gets the number of seconds for the creator
- of this item. */
-glong
-im_menu_item_get_seconds (ImMenuItem * menuitem)
-{
- g_return_val_if_fail(IS_IM_MENU_ITEM(menuitem), 0);
-
- ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(menuitem);
-
- if (priv->seconds == 0) {
- return priv->creation_seconds;
- } else {
- return priv->seconds;
- }
-}
-
-/* Gets whether or not this indicator item is
- asking for attention or not. */
-gboolean
-im_menu_item_get_attention (ImMenuItem * menuitem)
-{
- g_return_val_if_fail(IS_IM_MENU_ITEM(menuitem), FALSE);
-
- ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(menuitem);
- return priv->attention;
-}
-
-/* This takes care of items that need to be hidden, this is
- usually because they go over the count of allowed indicators.
- Which is more than a little bit silly. We shouldn't do that.
- But we need to enforce it to save users against bad apps. */
-void
-im_menu_item_show (ImMenuItem * menuitem, gboolean show)
-{
- g_return_if_fail(IS_IM_MENU_ITEM(menuitem));
-
- ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(menuitem);
-
- if (priv->show == show) {
- return;
- }
-
- priv->show = show;
- /* Tell the app what we're doing to it. If it's being
- punished it needs to know about it. */
- indicate_listener_displayed(priv->listener, priv->server, priv->indicator, priv->show);
- if (priv->attention) {
- /* If we were asking for attention we can ask for it
- again if we're being shown, otherwise no. */
- g_signal_emit(G_OBJECT(menuitem), signals[ATTENTION_CHANGED], 0, priv->show, TRUE);
- }
- dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(menuitem), DBUSMENU_MENUITEM_PROP_VISIBLE, priv->show ? "true" : "false");
-
- return;
-}
-
-/* Check to see if this item is shown. Accessor for the
- internal variable. */
-gboolean
-im_menu_item_shown (ImMenuItem * menuitem)
-{
- g_return_val_if_fail(IS_IM_MENU_ITEM(menuitem), FALSE);
-
- ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(menuitem);
-
- return priv->show;
-}