Mercurial > pidgin.yaz
diff pidgin/plugins/ticker/ticker.c @ 15374:5fe8042783c1
Rename gtk/ and libgaim/ to pidgin/ and libpurple/
author | Sean Egan <seanegan@gmail.com> |
---|---|
date | Sat, 20 Jan 2007 02:32:10 +0000 |
parents | |
children | d75099d2567e |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/plugins/ticker/ticker.c Sat Jan 20 02:32:10 2007 +0000 @@ -0,0 +1,379 @@ +/* + * Gaim Ticker Plugin + * The line below doesn't apply at all, does it? It should be Syd, Sean, and + * maybe Nathan, I believe. + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * ticker.c -- Syd Logan, Summer 2000 + * pluginized- Sean Egan, Summer 2002 + */ +#include "internal.h" +#include "gtkgaim.h" + +#include "blist.h" +#include "conversation.h" +#include "debug.h" +#include "prpl.h" +#include "signals.h" +#include "version.h" + +#include "gtkblist.h" +#include "gtkplugin.h" + +#include "gtkticker.h" + +#define TICKER_PLUGIN_ID "gtk-ticker" + +static GtkWidget *tickerwindow = NULL; +static GtkWidget *ticker; + +typedef struct { + GaimContact *contact; + GtkWidget *ebox; + GtkWidget *label; + GtkWidget *icon; + guint timeout; +} TickerData; + +GList *tickerbuds = NULL; + +static void buddy_ticker_update_contact(GaimContact *contact); + +static gboolean buddy_ticker_destroy_window(GtkWidget *window, + GdkEventAny *event, gpointer data) { + if(window) + gtk_widget_hide(window); + + return TRUE; /* don't actually destroy the window */ +} + +static void buddy_ticker_create_window() { + if(tickerwindow) { + gtk_widget_show(tickerwindow); + return; + } + + tickerwindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_default_size(GTK_WINDOW(tickerwindow), 500, -1); + g_signal_connect(G_OBJECT(tickerwindow), "delete_event", + G_CALLBACK (buddy_ticker_destroy_window), NULL); + gtk_window_set_title (GTK_WINDOW(tickerwindow), _("Buddy Ticker")); + gtk_window_set_role (GTK_WINDOW(tickerwindow), "ticker"); + + ticker = gtk_ticker_new(); + gtk_ticker_set_spacing(GTK_TICKER(ticker), 20); + gtk_container_add(GTK_CONTAINER(tickerwindow), ticker); + gtk_ticker_set_interval(GTK_TICKER(ticker), 500); + gtk_ticker_set_scootch(GTK_TICKER(ticker), 10); + gtk_ticker_start_scroll(GTK_TICKER(ticker)); + gtk_widget_set_size_request(ticker, 1, -1); + + gtk_widget_show_all(tickerwindow); +} + +static gboolean buddy_click_cb(GtkWidget *widget, GdkEventButton *event, gpointer user_data) { + GaimContact *contact = user_data; + GaimBuddy *b = gaim_contact_get_priority_buddy(contact); + + gaim_conversation_new(GAIM_CONV_TYPE_IM, b->account, b->name); + return TRUE; +} + +static TickerData *buddy_ticker_find_contact(GaimContact *c) { + GList *tb; + for(tb = tickerbuds; tb; tb = tb->next) { + TickerData *td = tb->data; + if(td->contact == c) + return td; + } + return NULL; +} + +static void buddy_ticker_set_pixmap(GaimContact *c) { + TickerData *td = buddy_ticker_find_contact(c); + GdkPixbuf *pixbuf; + + if(!td) + return; + + if(!td->icon) + td->icon = gtk_image_new(); + + pixbuf = gaim_gtk_blist_get_status_icon((GaimBlistNode*)c, + GAIM_STATUS_ICON_SMALL); + gtk_image_set_from_pixbuf(GTK_IMAGE(td->icon), pixbuf); + g_object_unref(G_OBJECT(pixbuf)); +} + +static gboolean buddy_ticker_set_pixmap_cb(gpointer data) { + TickerData *td = data; + + buddy_ticker_update_contact(td->contact); + td->timeout = 0; + + return FALSE; +} + +static void buddy_ticker_add_buddy(GaimBuddy *b) { + GtkWidget *hbox; + TickerData *td; + GaimContact *contact; + + contact = gaim_buddy_get_contact(b); + + buddy_ticker_create_window(); + + if (!ticker) + return; + + if (buddy_ticker_find_contact(contact)) + { + buddy_ticker_update_contact(contact); + return; + } + + td = g_new0(TickerData, 1); + td->contact = contact; + tickerbuds = g_list_append(tickerbuds, td); + + td->ebox = gtk_event_box_new(); + gtk_ticker_add(GTK_TICKER(ticker), td->ebox); + hbox = gtk_hbox_new(FALSE, 0); + gtk_container_add(GTK_CONTAINER(td->ebox), hbox); + buddy_ticker_set_pixmap(contact); + gtk_box_pack_start(GTK_BOX(hbox), td->icon, FALSE, FALSE, 0); + + g_signal_connect(G_OBJECT(td->ebox), "button-press-event", + G_CALLBACK(buddy_click_cb), contact); + + td->label = gtk_label_new(gaim_contact_get_alias(contact)); + gtk_box_pack_start(GTK_BOX(hbox), td->label, FALSE, FALSE, 2); + + gtk_widget_show_all(td->ebox); + gtk_widget_show(tickerwindow); + + /* + * Update the icon in a few seconds (after the open door icon has + * changed). This is somewhat ugly. + */ + td->timeout = g_timeout_add(11000, buddy_ticker_set_pixmap_cb, td); +} + +static void buddy_ticker_remove(TickerData *td) { + gtk_ticker_remove(GTK_TICKER(ticker), td->ebox); + tickerbuds = g_list_remove(tickerbuds, td); + if (td->timeout != 0) + g_source_remove(td->timeout); + g_free(td); +} + +static void buddy_ticker_update_contact(GaimContact *contact) { + TickerData *td = buddy_ticker_find_contact(contact); + + if (!td) + return; + + /* pop up the ticker window again */ + buddy_ticker_create_window(); + if (gaim_contact_get_priority_buddy(contact) == NULL) + buddy_ticker_remove(td); + else { + buddy_ticker_set_pixmap(contact); + gtk_label_set_text(GTK_LABEL(td->label), gaim_contact_get_alias(contact)); + } +} + +static void buddy_ticker_remove_buddy(GaimBuddy *b) { + GaimContact *c = gaim_buddy_get_contact(b); + TickerData *td = buddy_ticker_find_contact(c); + + if (!td) + return; + + gaim_contact_invalidate_priority_buddy(c); + + /* pop up the ticker window again */ + buddy_ticker_create_window(); + buddy_ticker_update_contact(c); +} + +static void buddy_ticker_show() +{ + GaimBuddyList *list = gaim_get_blist(); + GaimBlistNode *gnode, *cnode, *bnode; + GaimBuddy *b; + + if(!list) + return; + + for(gnode = list->root; gnode; gnode = gnode->next) { + if(!GAIM_BLIST_NODE_IS_GROUP(gnode)) + continue; + for(cnode = gnode->child; cnode; cnode = cnode->next) { + if(!GAIM_BLIST_NODE_IS_CONTACT(cnode)) + continue; + for(bnode = cnode->child; bnode; bnode = bnode->next) { + if(!GAIM_BLIST_NODE_IS_BUDDY(bnode)) + continue; + b = (GaimBuddy *)bnode; + if(GAIM_BUDDY_IS_ONLINE(b)) + buddy_ticker_add_buddy(b); + } + } + } +} + +static void +buddy_signon_cb(GaimBuddy *b) +{ + GaimContact *c = gaim_buddy_get_contact(b); + gaim_contact_invalidate_priority_buddy(c); + if(buddy_ticker_find_contact(c)) + buddy_ticker_update_contact(c); + else + buddy_ticker_add_buddy(b); +} + +static void +buddy_signoff_cb(GaimBuddy *b) +{ + buddy_ticker_remove_buddy(b); + if(!tickerbuds) + gtk_widget_hide(tickerwindow); +} + +static void +status_changed_cb(GaimBuddy *b, GaimStatus *os, GaimStatus *s) +{ + GaimContact *c = gaim_buddy_get_contact(b); + if(buddy_ticker_find_contact(c)) + buddy_ticker_set_pixmap(c); + else + buddy_ticker_add_buddy(b); +} + +static void +signoff_cb(GaimConnection *gc) +{ + TickerData *td; + if (!gaim_connections_get_all()) { + while (tickerbuds) { + td = tickerbuds->data; + tickerbuds = g_list_delete_link(tickerbuds, tickerbuds); + if (td->timeout != 0) + g_source_remove(td->timeout); + g_free(td); + } + gtk_widget_destroy(tickerwindow); + tickerwindow = NULL; + ticker = NULL; + } else { + GList *t = tickerbuds; + while (t) { + td = t->data; + t = t->next; + buddy_ticker_update_contact(td->contact); + } + } +} + + +/* + * EXPORTED FUNCTIONS + */ + +static gboolean +plugin_load(GaimPlugin *plugin) +{ + void *blist_handle = gaim_blist_get_handle(); + + gaim_signal_connect(gaim_connections_get_handle(), "signed-off", + plugin, GAIM_CALLBACK(signoff_cb), NULL); + gaim_signal_connect(blist_handle, "buddy-signed-on", + plugin, GAIM_CALLBACK(buddy_signon_cb), NULL); + gaim_signal_connect(blist_handle, "buddy-signed-off", + plugin, GAIM_CALLBACK(buddy_signoff_cb), NULL); + gaim_signal_connect(blist_handle, "buddy-status-changed", + plugin, GAIM_CALLBACK(status_changed_cb), NULL); + + if (gaim_connections_get_all()) + buddy_ticker_show(); + + return TRUE; +} + +static gboolean +plugin_unload(GaimPlugin *plugin) +{ + TickerData *td; + + while (tickerbuds) { + td = tickerbuds->data; + tickerbuds = g_list_delete_link(tickerbuds, tickerbuds); + if (td->timeout != 0) + g_source_remove(td->timeout); + g_free(td); + } + + if (tickerwindow != NULL) { + gtk_widget_destroy(tickerwindow); + tickerwindow = NULL; + } + + return TRUE; +} + +static GaimPluginInfo info = +{ + GAIM_PLUGIN_MAGIC, + GAIM_MAJOR_VERSION, + GAIM_MINOR_VERSION, + GAIM_PLUGIN_STANDARD, /**< type */ + GAIM_GTK_PLUGIN_TYPE, /**< ui_requirement */ + 0, /**< flags */ + NULL, /**< dependencies */ + GAIM_PRIORITY_DEFAULT, /**< priority */ + + TICKER_PLUGIN_ID, /**< id */ + N_("Buddy Ticker"), /**< name */ + VERSION, /**< version */ + /** summary */ + N_("A horizontal scrolling version of the buddy list."), + /** description */ + N_("A horizontal scrolling version of the buddy list."), + "Syd Logan", /**< author */ + GAIM_WEBSITE, /**< homepage */ + + plugin_load, /**< load */ + plugin_unload, /**< unload */ + NULL, /**< destroy */ + + NULL, /**< ui_info */ + NULL, /**< extra_info */ + NULL, + NULL +}; + +static void +init_plugin(GaimPlugin *plugin) +{ +} + +GAIM_INIT_PLUGIN(ticker, init_plugin, info)