Sun, 20 Apr 2003 20:56:14 +0000
[gaim-migrate @ 5550]
don't infinite loop on unload
| 3391 | 1 | /* GTK - The GIMP Toolkit |
| 2 | * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald | |
| 3 | * | |
| 4 | * This library is free software; you can redistribute it and/or | |
| 5 | * modify it under the terms of the GNU Library General Public | |
| 6 | * License as published by the Free Software Foundation; either | |
| 7 | * version 2 of the License, or (at your option) any later version. | |
| 8 | * | |
| 9 | * This library is distributed in the hope that it will be useful, | |
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 12 | * Library General Public License for more details. | |
| 13 | * | |
| 14 | * You should have received a copy of the GNU Library General Public | |
| 15 | * License along with this library; if not, write to the | |
| 16 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
| 17 | * Boston, MA 02111-1307, USA. | |
| 18 | */ | |
| 19 | ||
| 20 | /* | |
| 21 | * ticker.c -- Syd Logan, Summer 2000 | |
| 22 | * pluginized- Sean Egan, Summer 2002 | |
| 23 | */ | |
| 24 | ||
| 25 | ||
| 26 | #include <gtk/gtk.h> | |
| 27 | #include "gtkticker.h" | |
| 28 | #include <string.h> | |
| 29 | #include <stdlib.h> | |
| 30 | #include "gaim.h" | |
| 5170 | 31 | #include "list.h" |
| 32 | #include "gtklist.h" | |
| 3630 | 33 | #ifdef _WIN32 |
| 34 | #include "win32dep.h" | |
| 35 | #endif | |
| 3391 | 36 | |
| 3867 | 37 | #ifndef GAIM_PLUGINS |
| 38 | #define GAIM_PLUGINS | |
| 39 | #endif | |
| 40 | ||
| 3391 | 41 | static GtkWidget *tickerwindow = NULL; |
| 42 | static GtkWidget *ticker; | |
| 43 | static GModule *handle; | |
| 44 | ||
| 45 | typedef struct { | |
| 5170 | 46 | struct buddy *buddy; |
| 3391 | 47 | GtkWidget *ebox; |
| 48 | GtkWidget *label; | |
| 5170 | 49 | GtkWidget *icon; |
| 3391 | 50 | } TickerData; |
| 51 | ||
| 5170 | 52 | GList *tickerbuds = NULL; |
| 3391 | 53 | |
| 3630 | 54 | /* for win32 compatability */ |
| 55 | G_MODULE_IMPORT GSList *connections; | |
| 56 | ||
| 5172 | 57 | static gboolean buddy_ticker_destroy_window(GtkWidget *window, |
| 58 | GdkEventAny *event, gpointer data) { | |
| 59 | if(window) | |
| 60 | gtk_widget_hide(window); | |
| 61 | ||
| 62 | return TRUE; /* don't actually destroy the window */ | |
| 3391 | 63 | } |
| 64 | ||
| 5170 | 65 | static void buddy_ticker_create_window() { |
| 66 | if(tickerwindow) { | |
| 67 | gtk_widget_show(tickerwindow); | |
| 68 | return; | |
| 69 | } | |
| 3391 | 70 | |
| 5170 | 71 | tickerwindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); |
| 5172 | 72 | g_signal_connect(G_OBJECT(tickerwindow), "delete_event", |
| 5170 | 73 | G_CALLBACK (buddy_ticker_destroy_window), NULL); |
| 74 | gtk_window_set_title (GTK_WINDOW(tickerwindow), _("Buddy Ticker")); | |
|
4850
ca9d06f1bb54
[gaim-migrate @ 5175]
Mark Doliner <markdoliner@pidgin.im>
parents:
4770
diff
changeset
|
75 | gtk_window_set_role (GTK_WINDOW(tickerwindow), "ticker"); |
| 3391 | 76 | |
|
4850
ca9d06f1bb54
[gaim-migrate @ 5175]
Mark Doliner <markdoliner@pidgin.im>
parents:
4770
diff
changeset
|
77 | ticker = gtk_ticker_new(); |
| 5170 | 78 | gtk_ticker_set_spacing(GTK_TICKER(ticker), 20); |
| 79 | gtk_container_add(GTK_CONTAINER(tickerwindow), ticker); | |
| 80 | gtk_ticker_set_interval(GTK_TICKER(ticker), 500); | |
| 81 | gtk_ticker_set_scootch(GTK_TICKER(ticker), 10); | |
| 82 | gtk_ticker_start_scroll(GTK_TICKER(ticker)); | |
| 83 | gtk_widget_set_size_request(ticker, 500, -1); | |
| 3391 | 84 | |
| 5170 | 85 | gtk_widget_show_all(tickerwindow); |
| 3391 | 86 | } |
| 87 | ||
| 5170 | 88 | static gboolean buddy_click_cb(GtkWidget *widget, GdkEventButton *event, gpointer user_data) { |
| 89 | struct buddy *b = user_data; | |
|
4850
ca9d06f1bb54
[gaim-migrate @ 5175]
Mark Doliner <markdoliner@pidgin.im>
parents:
4770
diff
changeset
|
90 | |
| 5170 | 91 | gaim_conversation_new(GAIM_CONV_IM, b->account, b->name); |
| 3391 | 92 | return TRUE; |
| 93 | } | |
| 94 | ||
| 5170 | 95 | static TickerData *buddy_ticker_find_buddy(struct buddy *b) { |
| 96 | GList *tb; | |
| 97 | for(tb = tickerbuds; tb; tb = tb->next) { | |
| 98 | TickerData *td = tb->data; | |
| 99 | if(td->buddy == b) | |
| 100 | return td; | |
| 101 | } | |
| 102 | return NULL; | |
| 103 | } | |
| 104 | ||
| 105 | static void buddy_ticker_set_pixmap(struct buddy *b) { | |
| 106 | TickerData *td = buddy_ticker_find_buddy(b); | |
| 107 | GdkPixbuf *pixbuf; | |
| 3391 | 108 | |
| 5170 | 109 | if(!td) |
| 3391 | 110 | return; |
| 5170 | 111 | |
| 112 | if(!td->icon) | |
| 113 | td->icon = gtk_image_new(); | |
| 3391 | 114 | |
| 5170 | 115 | pixbuf = gaim_gtk_blist_get_status_icon(b, GAIM_STATUS_ICON_SMALL); |
| 116 | gtk_image_set_from_pixbuf(GTK_IMAGE(td->icon), pixbuf); | |
| 117 | g_object_unref(G_OBJECT(pixbuf)); | |
| 118 | } | |
| 119 | ||
| 120 | static void buddy_ticker_add_buddy(struct buddy *b) { | |
| 121 | GtkWidget *hbox; | |
| 122 | TickerData *td; | |
| 123 | ||
| 124 | buddy_ticker_create_window(); | |
| 5172 | 125 | |
| 3391 | 126 | if (!ticker) |
| 127 | return; | |
| 128 | ||
| 5170 | 129 | if(buddy_ticker_find_buddy(b)) |
| 3391 | 130 | return; |
| 131 | ||
| 5170 | 132 | td = g_new0(TickerData, 1); |
| 133 | td->buddy = b; | |
| 134 | tickerbuds = g_list_append(tickerbuds, td); | |
| 3391 | 135 | |
| 5170 | 136 | td->ebox = gtk_event_box_new(); |
| 137 | gtk_ticker_add(GTK_TICKER(ticker), td->ebox); | |
| 138 | hbox = gtk_hbox_new(FALSE, 0); | |
| 139 | gtk_container_add(GTK_CONTAINER(td->ebox), hbox); | |
| 140 | buddy_ticker_set_pixmap(b); | |
| 141 | gtk_box_pack_start(GTK_BOX(hbox), td->icon, FALSE, FALSE, 5); | |
| 3391 | 142 | |
| 5170 | 143 | g_signal_connect(G_OBJECT(td->ebox), "button-press-event", |
| 144 | G_CALLBACK(buddy_click_cb), b); | |
| 3391 | 145 | |
| 5170 | 146 | td->label = gtk_label_new(gaim_get_buddy_alias(b)); |
| 147 | gtk_box_pack_start(GTK_BOX(hbox), td->label, FALSE, FALSE, 5); | |
| 148 | ||
| 149 | gtk_widget_show_all(td->ebox); | |
| 150 | gtk_widget_show(tickerwindow); | |
| 3391 | 151 | } |
| 152 | ||
| 5170 | 153 | static void buddy_ticker_remove_buddy(struct buddy *b) { |
| 154 | TickerData *td = buddy_ticker_find_buddy(b); | |
| 3391 | 155 | |
| 5170 | 156 | if (!td) |
| 157 | return; | |
| 3391 | 158 | |
| 5172 | 159 | /* pop up the ticker window again */ |
| 160 | buddy_ticker_create_window(); | |
| 161 | ||
| 5170 | 162 | gtk_ticker_remove(GTK_TICKER(ticker), td->ebox); |
| 163 | tickerbuds = g_list_remove(tickerbuds, td); | |
| 164 | g_free(td); | |
| 3391 | 165 | } |
| 166 | ||
| 5170 | 167 | static void buddy_ticker_show() |
| 3391 | 168 | { |
| 5170 | 169 | struct gaim_buddy_list *list = gaim_get_blist(); |
| 170 | GaimBlistNode *gnode, *bnode; | |
| 171 | struct buddy *b; | |
| 3391 | 172 | |
| 5170 | 173 | if(!list) |
| 174 | return; | |
| 3391 | 175 | |
| 5170 | 176 | for(gnode = list->root; gnode; gnode = gnode->next) { |
| 177 | if(!GAIM_BLIST_NODE_IS_GROUP(gnode)) | |
| 178 | continue; | |
| 179 | for(bnode = gnode->child; bnode; bnode = bnode->next) { | |
| 180 | if(!GAIM_BLIST_NODE_IS_BUDDY(bnode)) | |
| 181 | continue; | |
| 182 | b = (struct buddy *)bnode; | |
| 183 | if(GAIM_BUDDY_IS_ONLINE(b)) | |
| 184 | buddy_ticker_add_buddy(b); | |
| 3391 | 185 | } |
| 186 | } | |
| 187 | } | |
| 188 | ||
| 189 | void signon_cb(struct gaim_connection *gc, char *who) { | |
|
4850
ca9d06f1bb54
[gaim-migrate @ 5175]
Mark Doliner <markdoliner@pidgin.im>
parents:
4770
diff
changeset
|
190 | struct buddy *b = gaim_find_buddy(gc->account, who); |
| 5170 | 191 | if(buddy_ticker_find_buddy(b)) |
| 192 | buddy_ticker_set_pixmap(b); | |
| 193 | else | |
| 194 | buddy_ticker_add_buddy(b); | |
| 3391 | 195 | } |
| 196 | ||
| 197 | void signoff_cb(struct gaim_connection *gc) { | |
| 5170 | 198 | if (!connections) { |
| 5185 | 199 | while(tickerbuds) { |
| 200 | g_free(tickerbuds->data); | |
| 201 | tickerbuds = g_list_delete_link(tickerbuds, tickerbuds); | |
| 202 | } | |
| 3391 | 203 | gtk_widget_destroy(tickerwindow); |
| 204 | tickerwindow = NULL; | |
| 205 | ticker = NULL; | |
| 5185 | 206 | } else { |
| 207 | GList *t = tickerbuds; | |
| 208 | while(t) { | |
| 209 | TickerData *td = t->data; | |
| 210 | t = t->next; | |
| 211 | if(td->buddy->account == gc->account) { | |
| 212 | g_free(td); | |
| 213 | tickerbuds = g_list_remove(tickerbuds, td); | |
| 214 | } | |
| 215 | } | |
| 3391 | 216 | } |
| 217 | } | |
| 218 | ||
| 219 | void buddy_signoff_cb(struct gaim_connection *gc, char *who) { | |
| 5170 | 220 | struct buddy *b = gaim_find_buddy(gc->account, who); |
| 221 | ||
| 222 | buddy_ticker_remove_buddy(b); | |
| 5185 | 223 | if(!tickerbuds) |
| 224 | gtk_widget_hide(tickerwindow); | |
| 3391 | 225 | } |
| 226 | ||
| 227 | void away_cb(struct gaim_connection *gc, char *who) { | |
|
4850
ca9d06f1bb54
[gaim-migrate @ 5175]
Mark Doliner <markdoliner@pidgin.im>
parents:
4770
diff
changeset
|
228 | struct buddy *b = gaim_find_buddy(gc->account, who); |
| 5170 | 229 | if(buddy_ticker_find_buddy(b)) |
| 230 | buddy_ticker_set_pixmap(b); | |
| 231 | else | |
| 232 | buddy_ticker_add_buddy(b); | |
| 3391 | 233 | } |
| 234 | ||
| 3630 | 235 | /* |
| 236 | * EXPORTED FUNCTIONS | |
| 237 | */ | |
| 238 | ||
| 239 | G_MODULE_EXPORT char *name() { | |
| 4585 | 240 | return _("Buddy Ticker"); |
| 3630 | 241 | } |
| 242 | ||
| 243 | G_MODULE_EXPORT char *description() { | |
| 4606 | 244 | return _("A horizontal scrolling version of the buddy list."); |
| 3630 | 245 | } |
| 246 | ||
| 247 | G_MODULE_EXPORT char *gaim_plugin_init(GModule *h) { | |
| 3391 | 248 | handle = h; |
| 5170 | 249 | |
| 3391 | 250 | gaim_signal_connect(h, event_buddy_signon, signon_cb, NULL); |
| 251 | gaim_signal_connect(h, event_signoff, signoff_cb, NULL); | |
| 252 | gaim_signal_connect(h, event_buddy_signoff, buddy_signoff_cb, NULL); | |
| 253 | gaim_signal_connect(h, event_buddy_away, away_cb, NULL); | |
| 5170 | 254 | gaim_signal_connect(h, event_buddy_back, away_cb, NULL); |
| 3391 | 255 | |
| 256 | if (connections) | |
| 5170 | 257 | buddy_ticker_show(); |
| 3391 | 258 | return NULL; |
| 259 | } | |
| 260 | ||
| 3630 | 261 | G_MODULE_EXPORT void gaim_plugin_remove() { |
| 5185 | 262 | while(tickerbuds) { |
| 263 | g_free(tickerbuds->data); | |
| 5186 | 264 | tickerbuds = g_list_delete_link(tickerbuds, tickerbuds); |
| 5185 | 265 | } |
| 5181 | 266 | gtk_widget_destroy(tickerwindow); |
| 3391 | 267 | } |
| 5170 | 268 | |
| 269 | struct gaim_plugin_description desc; | |
| 3630 | 270 | G_MODULE_EXPORT struct gaim_plugin_description *gaim_plugin_desc() { |
| 3551 | 271 | desc.api_version = PLUGIN_API_VERSION; |
| 4585 | 272 | desc.name = g_strdup(_("Buddy Ticker")); |
| 3551 | 273 | desc.version = g_strdup(VERSION); |
| 4585 | 274 | desc.description = g_strdup(_("A horizontal scrolling version of the buddy list.")); |
| 3551 | 275 | desc.authors = g_strdup("Syd Logan"); |
| 276 | desc.url = g_strdup(WEBSITE); | |
| 277 | return &desc; | |
| 278 | } |