Messaging indicator article



An introduction to the message indicator

The messaging indicator, also known as the indicator-applet[1], is a central place to keep track of messages that you might need to be concerned about.  The focus is on human-to-human messaging, for example; instant messaging, e-mail, social networking, etc.  By tracking these in a single applet, instead of displaying separate icons in the noticiation area or on the panel, we save a considerable amount of realestate and cut down on the clutter.  We also get the benefit of a single place in the panel to find messages waiting review.  For more information on the rationale, check out the specification [2].

Current applications that take advantage of the messaging indicator include:
 * pidgin, with patches to pidgin-libnotify
 * evolution, with evolution-indicator
 * gajim, with patches already excepted upstream
 * gwibber

To effectively use the messaging indicator with your application, you should keep two things in mind:
 * Hide your applications icon from the notification area if it is using the indicator
 * Rely on the indicator for raising/hiding your application as well as quick access to incoming messages

Lets walk through some examples.  The library used to interact with the the messaging indicator is called libindicate, in C.  There are also python bindings to libindicate, called python-indicate.  At this time the python-bindings only handle application side, not the listener.  

Using it is actually pretty simple, you just need to have your application advertise it's indicators using libindicate.  The server object handles all of the DBus interactions so all you have to do is tell it about your indicators.  The server registers itself with the indicator, which displays an item in the messaging menu for the application.  When selecting the entry in the message menu, it calls the signal on the indicator.  This is very useful for access to the application itself, like raising the buddy list in pidgin, etc.  Examples included below in python and you can find examples at the end of the article in C as well.


First we create the server object
<code>
    server = indicate.indicate_server_ref_default()
</code>

Set the message type and subtype, valid types include 
 * "message" -- a user level message.  This includes e-mail, IM and SMS messages.
 * "system" -- a software update or other notification about the system state.
 * "media" -- a notification related media the user is listening to in the background

message.instant, message.micro, and message.im
<code>
    server.set_type("message.im")
</code>

We can get some descriptive information to display in the messaging menu from a desktop file provided by the application
<code>
    server.set_desktop_file("/usr/share/applications/pidgin.desktop")
</code>

Now that all the setup work is done, we just need to connect it to the indicator.  The second argument to this method call is the name of the method to call when selecting the entry in the messaging menu.  The show method shows the indicator after connecting.
<code>
    server.connect("server-display", server_display)
    server.show()
</code>

The client tells the server there is a message waiting, and when the message is selected in the the messaging menu it calls the display method for the client.

Setup the message object
<code>
    indicator = indicate.IndicatorMessage()
</code>
Then we need to set some properties for the message, available properties are:
 * "subject" -- "message" (optional) -- This is the subject line of an e-mail or message.
 * "sender" -- "message" (required) -- The person who sent the message
 * "body" -- "message" (required) -- The body of the message sent to the user
<code>
    indicator.set_property("subtype", "instant")
    indicator.set_property("sender", "Test message")
    indicator.set_property("body", "Test message body")
    indicator.set_property_time("time", time())
</code>

The only things left to do is show the message and connect it to a method.  The second argument in the connect method is the method to call when the message is selected.
<code>
    indicator.show()
    indicator.connect("user-display", display)
</code>

Here is a complete python example:
<code>
#!/usr/bin/env python

import indicate
import gobject
import gtk
from time import time
import os

curdir = os.getcwd()
desktop_file = os.path.join(curdir, "example-indicator.desktop")

def timeout_cb(indicator):
    print "Modifying properties"
    indicator.set_property_time("time", time())
    return True

def display(indicator):
    print "Ah, my indicator has been displayed"
    indicator.hide()

def server_display(server):
    print "Ah, my server has been displayed"


if __name__ == "__main__":
    # Setup the server
    server = indicate.indicate_server_ref_default()
    server.set_type("message.im")
    server.set_desktop_file(desktop_file)
    server.connect("server-display", server_display)
    server.show()

    # Setup the message
    indicator = indicate.IndicatorMessage()
    indicator.set_property("subtype", "im")
    indicator.set_property("sender", "Test message")
    indicator.set_property("body", "Test message body")
    indicator.set_property_time("time", time())
    indicator.show()
    indicator.connect("user-display", display)

    # Loop
    gobject.timeout_add_seconds(5, timeout_cb, indicator)
    gtk.main()

</code>

C example:
<code>
#include <glib.h>
#include "libindicate/server.h"
#include "libindicate/indicator-message.h"

static gboolean
timeout_cb (gpointer data)
{
	g_debug("Modifying properties");

	IndicateIndicator * indicator = INDICATE_INDICATOR(data);

	GTimeVal time;
	g_get_current_time(&time);
	indicate_indicator_set_property_time(INDICATE_INDICATOR(indicator), "time", &time);

	return TRUE;
}

static void
display (IndicateIndicator * indicator, gpointer data)
{
	g_debug("Ah, my indicator has been displayed");
	indicate_indicator_hide(indicator);
}

static void
server_display (IndicateServer * server, gpointer data)
{
	g_debug("Ah, my server has been displayed");
}

int
main (int argc, char ** argv)
{
	g_type_init();

	IndicateServer * server = indicate_server_ref_default();
	indicate_server_set_type(server, "message.im");
	gchar * path = g_build_filename(g_get_current_dir(), "example-indicator.desktop", NULL);
	indicate_server_set_desktop_file(server, path);
	g_free(path);
	g_signal_connect(G_OBJECT(server), INDICATE_SERVER_SIGNAL_SERVER_DISPLAY, G_CALLBACK(server_display), NULL);

	IndicateIndicatorMessage * indicator;

	indicator = indicate_indicator_message_new();
	indicate_indicator_set_property(INDICATE_INDICATOR(indicator), "subtype", "instant");
	indicate_indicator_set_property(INDICATE_INDICATOR(indicator), "sender", "IM Client Test");
	GTimeVal time; g_get_current_time(&time);
	indicate_indicator_set_property_time(INDICATE_INDICATOR(indicator), "time", &time);
	indicate_indicator_show(INDICATE_INDICATOR(indicator));

	g_get_current_time(&time);
	indicate_indicator_set_property_time(INDICATE_INDICATOR(indicator), "time", &time);

	g_signal_connect(G_OBJECT(indicator), INDICATE_INDICATOR_SIGNAL_DISPLAY, G_CALLBACK(display), NULL);

	g_timeout_add_seconds(5, timeout_cb, indicator);

	g_main_loop_run(g_main_loop_new(NULL, FALSE));

	return 0;
}
</code>

Example desktop file example-indicator.desktop:
<code>
[Desktop Entry]
Version=1.0
Name=Example Indicator
Type=Application
</code>


CONCLUSION
Lets clean up the notication area!  To do this, we all really need your help.  If you maintain an application that could utilize the message indicator, please update it to support the indicator.  If you aren't a maintainer, but have an application you use regularly that could use the indicator and have the skills to create a patch, please do.  Maintainers are usualy happy to receive patches, so patch something you care about and submit the patch.  Let me also add, if you find bugs (or have suggestions for improvement) in the indicator APIs or the indicator itself, please file bugs in launchpad[1].

[1] http://launchpad.net/indicator-applet
[2] https://wiki.ubuntu.com/MessagingMenu


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]