sexta-feira, 27 de novembro de 2009

Notificações do Gnome - Usando LibNotify no Python

De alguns tempos para cá, o Gnome vem utilizando um sistema centralizado de notificações, chamado Galago Project. Este sistema é um conjunto de APIs, UIs e um mecanismo que permite que aplicativos, serviços, plugins ou qualquer outro processo possam notificar o usuário sobre alguma coisa que valha a pena ser notificada.

O sistema consiste de um daemon de notificação, API chamada LibNotify, um cliente que implementa essa API na forma de um executável, um sistema baseado no DBus, para juntar tudo, e finalmente bindings para várias linguagens (até o momento, sei de bindings para Python, Ruby e C/C++).

A maneira mais simples de fazer uma notificação é utilizando o comando notify-send (que pode ser instalado no Ubuntu com o comando sudo aptitude install libnotify-bin), como mostra a imagem abaixo:

Esta é realmente a forma mais simples de se criar uma notificação, mas infelismente é bastante limitada e não tão interessante.

Se você quiser realmente usar a biblioteca sem precisar destes artifícios, o melhor caminho é usar a API.



Libnotify no Python

Usar essa biblioteca no Python não é nada difícil. Na realidade, é tão simples que nem valeria um post, se realmente o recurso de notificação não fosse tão interessante e procurado. Segue um exemplo de notificação básica:

import pynotify
if pynotify.init("Nome da Aplicação"):
    n = pynotify.Notification("Título", "Sua mensagem")
    n.show()
else:
    print "Oops, problemas com a inicialização do módulo pynotify"

Como eu disse, não é nada complexo. No entanto, a biblioteca dispõe de outros recursos interessantes também. Entre eles, a possibilidade de definir o nível de urgência de uma mensagem:

n.set_urgency(pynotify.URGENCY_LOW)
n.set_urgency(pynotify.URGENCY_NORMAL)
n.set_urgency(pynotify.URGENCY_CRITICAL)

Outra opção é a de se usar ícones nas notificações, que podem ser feitas de três maneiras diferentes:

1: Com o path do ícone, no formato URI ("file://path/icone.png")
2: Usando um ícone padrão do Gnome, a partir de seu nome ("gnome-terminal")
3: Usando um pixbuf

Para os dois primeiros métodos, simplesmente informe o nome ou a URI do ícone em um terceiro parâmetro no método Notification():

n = pynotify.Notification("Título", "Sua mensagem", "gnome-terminal")

Caso queira utilizar um pixbuf em memória, você pode usar o método set_icon_from_pixbuf(), passando o pixbuf como parâmetro:

n.set_icon_from_pixbuf(pixbuf)



Você ainda pode setar o tempo que a mensagem ficará no ar, em segundos:

n.set_timeout(10)

Posicionar a mensagem próximo de algum widget:

n.attach_to_widget(widget) # 'self' funciona aki

Pode também, se quiser, expecificar diretamente a posição da notificação na tela:

n.set_hint("x", 250)
n.set_hint("y", 300)

Outra função interessante é a de poder fechar a notificação antes que seu tempo tenha expirado, para o caso em que vc já leu a mensagem e a mesma não se faz mais necessária:

n.close()

E muitos outros recursos a mais. É possível desde colocar botões na janela de notificação até setar funções de callback que retornam informações como cliques ou outros eventos notificáveis.

Caso esteja interessado em saber mais, o pacote pynotify têm vários exemplos de uso mais avançado da biblioteca.

Só para constar, coloco também um exemplo em C, só pra vcs não ficarem tristinhos. Realmente em C as coisas não são tão simples e práticas quanto no Python, como vc pode ver abaixo:

#include 

int main(int argc, char **argv) {
    // inicializando o GTK
    gtk_init(&argc,&argv);

    char nome[60] = “Exemplo de Notificação”;

    // iniciando a biblioteca
    notify_init(nome);

    // criando uma nova notificação
    NotifyNotification *exemplo;
    exemplo = notify_notification_new(nome, “Hello World!”, NULL, NULL);

    // criando um ícone para a notificação
    GtkStatusIcon *icone = gtk_status_icon_new_from_stock(GTK_STOCK_YES);
    gtk_status_icon_set_visible(icone, TRUE);
    notify_notification_attach_to_status_icon(exemplo, icone);

    // configurando a duração da notificação para 10 segundos
    notify_notification_set_timeout(exemplo, 10000);

    // configurando a categoria da notificação
    char categoria[40] = “Notificações de Teste”;
    notify_notification_set_category(exemplo, categoria);

    // configurando o nível de urgência da notificação
    notify_notification_set_urgency(exemplo, NOTIFY_URGENCY_CRITICAL);

    GError *error = NULL;

    notify_notification_show(exemplo, &error);

    return 0;
}

Só lembrando de, na hora de compilar, fazer a ligação com a biblioteca:

$ gcc `pkg-config –cflags –libs gtk+-2.0` notify.c -o notify -l notify

No geral é isso pessoal. Minha intenção foi mostrar o uso desse recurso que muito ajuda (e irrita, no caso do Pidgin e do Empathy) principalmente para vc saber quando uma determinada atividade que você disparou já terminou ou que chegou algo pra vc. Uma das utilidades é pro pessoal que escreve scripts em shellscript. Acho que essa oportunidade de notificação era uma boa coisa a ser explorada.

Entre os projetos que estou em mente é alterar meu Simplex Python Terminal Chat para passar a usar essa biblioteca.

Abração, e até mais.

Fontes:
man notify-send
Galago Projetc