Mercurial > pidgin
annotate plugins/chatlist.c @ 4359:5fb47ec9bfe4
[gaim-migrate @ 4625]
Wow, okay, where to begin with this one ;)
I rewrote the whole conversation backend. It is now core/UI split. Here's
how it works..
Every conversation is represented by a gaim_conversation structure. This
branches out into gaim_im and gaim_chat structures. Every conversation
lives in (well, normally, but it doesn't have to) a gaim_window structure.
This is a _CORE_ representation of a window. There can be multiple
gaim_window structures around.
The gaim_window and gaim_conversation structures have UI-specific operation
structures associated with them. At the moment, the only UI is GTK+, and
this will be for some time. Don't start thinking you can write a QT UI now.
It's just not going to happen.
Everything that is done on a conversation is done through the core API.
This API does core processing and then calls the UI operations for the
rendering and anything else.
Now, what does this give the user?
- Multiple windows.
- Multiple tabs per window.
- Draggable tabs.
- Send As menu is moved to the menubar.
- Menubar for chats.
- Some very cool stuff in the future, like replacing, say, IRC chat windows
with an X-Chat interface, or whatever.
- Later on, customizable window/conversation positioning.
For developers:
- Fully documented API
- Core/UI split
- Variable checking and mostly sane handling of incorrect variables.
- Logical structure to conversations, both core and UI.
- Some very cool stuff in the future, like replacing, say, IRC chat windows
with an X-Chat interface, or whatever.
- Later on, customizable window/conversation positioning.
- Oh yeah, and the beginning of a stock icon system.
Now, there are things that aren't there yet. You will see tabs even if you
have them turned off. This will be fixed in time. Also, the preferences
will change to work with the new structure. I'm starting school in 2 days,
so it may not be done immediately, but hopefully in the next week.
Enjoy!
committer: Tailor Script <tailor@pidgin.im>
| author | Christian Hammond <chipx86@chipx86.com> |
|---|---|
| date | Mon, 20 Jan 2003 09:10:23 +0000 |
| parents | da5e1b57adb0 |
| children | 2427d847e39c |
| rev | line source |
|---|---|
|
4202
59751fe608c5
[gaim-migrate @ 4438]
Christian Hammond <chipx86@chipx86.com>
parents:
4165
diff
changeset
|
1 #include "config.h" |
|
59751fe608c5
[gaim-migrate @ 4438]
Christian Hammond <chipx86@chipx86.com>
parents:
4165
diff
changeset
|
2 |
|
59751fe608c5
[gaim-migrate @ 4438]
Christian Hammond <chipx86@chipx86.com>
parents:
4165
diff
changeset
|
3 #ifndef GAIM_PLUGINS |
| 2241 | 4 #define GAIM_PLUGINS |
|
4202
59751fe608c5
[gaim-migrate @ 4438]
Christian Hammond <chipx86@chipx86.com>
parents:
4165
diff
changeset
|
5 #endif |
| 2241 | 6 |
| 7 #include "pixmaps/refresh.xpm" | |
| 8 #include "pixmaps/gnome_add.xpm" | |
| 9 #include "pixmaps/gnome_remove.xpm" | |
| 10 | |
| 11 #include "proxy.h" | |
| 12 #include "gaim.h" | |
| 13 | |
| 14 #include <stdlib.h> | |
|
2272
4ecc9a9a75d8
[gaim-migrate @ 2282]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2241
diff
changeset
|
15 #include <string.h> |
| 3630 | 16 #ifdef _WIN32 |
| 17 #include "win32dep.h" | |
| 18 #endif | |
| 2241 | 19 |
| 2993 | 20 #define AOL_SRCHSTR "aim:GoChat?RoomName=" |
|
2417
5473c8c5378d
[gaim-migrate @ 2430]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2356
diff
changeset
|
21 |
| 2241 | 22 struct chat_page { |
| 23 GtkWidget *list1; | |
| 24 GtkWidget *list2; | |
| 25 }; | |
| 26 | |
| 27 struct chat_room { | |
| 28 char name[80]; | |
| 29 int exchange; | |
| 30 }; | |
| 31 | |
| 32 static GtkWidget *item = NULL; /* this is the parent tree */ | |
| 33 static GList *chat_rooms = NULL; | |
| 34 | |
| 35 static struct chat_page *cp = NULL; | |
| 36 | |
| 37 static void des_item() | |
| 38 { | |
| 39 if (item) | |
| 40 gtk_widget_destroy(item); | |
| 41 item = NULL; | |
| 42 } | |
| 43 | |
| 44 static void handle_click_chat(GtkWidget *widget, GdkEventButton * event, struct chat_room *cr) | |
| 45 { | |
| 46 if (event->type == GDK_2BUTTON_PRESS && event->button == 1) { | |
| 47 GList *m = g_list_append(NULL, cr->name); | |
| 48 int *x = g_new0(int, 1); | |
| 49 *x = cr->exchange; | |
| 50 m = g_list_append(m, x); | |
| 51 serv_join_chat(connections->data, m); | |
| 52 g_free(x); | |
| 53 g_list_free(m); | |
| 54 } | |
| 55 } | |
| 56 | |
| 57 static void setup_buddy_chats() | |
| 58 { | |
| 59 GList *crs = chat_rooms; | |
| 60 GtkWidget *tree; | |
| 61 | |
| 62 if (!blist) | |
| 63 return; | |
| 64 | |
| 65 if (item) | |
| 66 gtk_tree_remove_item(GTK_TREE(buddies), item); | |
| 67 item = NULL; | |
| 68 | |
| 69 if (!chat_rooms) | |
| 70 return; | |
| 71 | |
| 72 item = gtk_tree_item_new_with_label(_("Buddy Chat")); | |
|
4165
07a3d1fae88f
[gaim-migrate @ 4394]
Christian Hammond <chipx86@chipx86.com>
parents:
4164
diff
changeset
|
73 g_signal_connect(GTK_OBJECT(item), "destroy", G_CALLBACK(des_item), NULL); |
| 2241 | 74 gtk_tree_append(GTK_TREE(buddies), item); |
| 75 gtk_tree_item_expand(GTK_TREE_ITEM(item)); | |
| 76 gtk_widget_show(item); | |
| 77 | |
| 78 tree = gtk_tree_new(); | |
| 79 gtk_tree_item_set_subtree(GTK_TREE_ITEM(item), tree); | |
| 80 gtk_widget_show(tree); | |
| 81 | |
| 82 while (crs) { | |
| 83 struct chat_room *cr = (struct chat_room *)crs->data; | |
| 84 GtkWidget *titem = gtk_tree_item_new_with_label(cr->name); | |
| 85 gtk_object_set_user_data(GTK_OBJECT(titem), cr); | |
| 86 gtk_tree_append(GTK_TREE(tree), titem); | |
| 87 gtk_widget_show(titem); | |
|
4165
07a3d1fae88f
[gaim-migrate @ 4394]
Christian Hammond <chipx86@chipx86.com>
parents:
4164
diff
changeset
|
88 g_signal_connect(GTK_OBJECT(titem), "button_press_event", |
|
07a3d1fae88f
[gaim-migrate @ 4394]
Christian Hammond <chipx86@chipx86.com>
parents:
4164
diff
changeset
|
89 G_CALLBACK(handle_click_chat), cr); |
| 2241 | 90 crs = crs->next; |
| 91 } | |
|
2900
aaaca46b507b
[gaim-migrate @ 2913]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2892
diff
changeset
|
92 |
|
aaaca46b507b
[gaim-migrate @ 2913]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2892
diff
changeset
|
93 gtk_tree_item_expand(GTK_TREE_ITEM(item)); |
| 2241 | 94 } |
| 95 | |
| 96 static void save_chat_prefs() | |
| 97 { | |
| 98 FILE *f; | |
| 99 char path[1024]; | |
| 100 char *x = gaim_user_dir(); | |
| 101 GList *crs = chat_rooms; | |
| 102 | |
| 103 g_snprintf(path, sizeof(path), "%s/%s", x, "chats"); | |
| 104 f = fopen(path, "w"); | |
| 3930 | 105 if (!f) |
| 2241 | 106 return; |
| 107 while (crs) { | |
| 108 struct chat_room *cr = crs->data; | |
| 109 crs = crs->next; | |
| 110 fprintf(f, "%s\n%d\n", cr->name, cr->exchange); | |
| 111 } | |
| 112 fclose(f); | |
| 113 } | |
| 114 | |
| 115 static void restore_chat_prefs() | |
| 116 { | |
| 117 FILE *f; | |
| 118 char path[1024]; | |
| 119 char *x = gaim_user_dir(); | |
| 120 char buf[1024]; | |
| 121 | |
| 122 g_snprintf(path, sizeof(path), "%s/%s", x, "chats"); | |
| 123 f = fopen(path, "r"); | |
| 3930 | 124 if (!f) |
| 2241 | 125 return; |
| 126 while (fgets(buf, 1024, f)) { | |
| 127 struct chat_room *cr = g_new0(struct chat_room, 1); | |
|
2356
ddf404cd9757
[gaim-migrate @ 2369]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2272
diff
changeset
|
128 g_snprintf(cr->name, sizeof(cr->name), "%s", g_strchomp(buf)); |
| 2241 | 129 if (!fgets(buf, 1024, f)) { |
| 130 g_free(cr); | |
| 131 break; | |
| 132 } | |
| 133 cr->exchange = atoi(buf); | |
| 134 chat_rooms = g_list_append(chat_rooms, cr); | |
| 135 } | |
| 136 fclose(f); | |
| 137 setup_buddy_chats(); | |
| 138 } | |
| 139 | |
| 4327 | 140 static void ref_list_callback(gpointer data, char *text, unsigned long len) |
| 2241 | 141 { |
| 142 char *c; | |
| 143 GtkWidget *item; | |
| 144 GList *items = GTK_LIST(cp->list1)->children; | |
| 145 struct chat_room *cr; | |
| 146 c = text; | |
| 147 | |
| 148 if (!text) | |
| 149 return; | |
| 150 | |
| 151 while (items) { | |
| 152 g_free(gtk_object_get_user_data(GTK_OBJECT(items->data))); | |
| 153 items = items->next; | |
| 154 } | |
| 155 | |
| 156 items = NULL; | |
| 157 | |
| 158 gtk_list_clear_items(GTK_LIST(cp->list1), 0, -1); | |
| 159 | |
| 160 item = gtk_list_item_new_with_label(_("Gaim Chat")); | |
| 161 cr = g_new0(struct chat_room, 1); | |
| 162 strcpy(cr->name, _("Gaim Chat")); | |
| 163 cr->exchange = 4; | |
| 164 gtk_object_set_user_data(GTK_OBJECT(item), cr); | |
| 165 gtk_widget_show(item); | |
| 166 | |
| 167 items = g_list_append(NULL, item); | |
| 168 | |
| 169 while (c) { | |
| 170 if (c - text > len - 30) | |
| 171 break; /* assume no chat rooms 30 from end, padding */ | |
| 172 if (!g_strncasecmp(AOL_SRCHSTR, c, strlen(AOL_SRCHSTR))) { | |
| 173 char *t; | |
| 174 int len = 0; | |
| 3000 | 175 int exchange = 5; |
| 2241 | 176 char *name = NULL; |
| 177 | |
| 178 c += strlen(AOL_SRCHSTR); | |
| 179 t = c; | |
| 180 while (t) { | |
| 181 len++; | |
| 182 name = g_realloc(name, len); | |
| 183 if (*t == '+') | |
| 184 name[len - 1] = ' '; | |
| 185 else if (*t == '&') { | |
| 186 name[len - 1] = 0; | |
| 3000 | 187 sscanf(t, "&Exchange=%d", &exchange); |
| 188 c = t + strlen("&Exchange=x"); | |
| 2241 | 189 break; |
| 190 } else | |
| 191 name[len - 1] = *t; | |
| 192 t++; | |
| 193 } | |
| 194 cr = g_new0(struct chat_room, 1); | |
| 195 strcpy(cr->name, name); | |
| 196 cr->exchange = exchange; | |
|
4164
a55c2a0ddcd4
[gaim-migrate @ 4393]
Christian Hammond <chipx86@chipx86.com>
parents:
3930
diff
changeset
|
197 printf("Adding '%s'\n", name); |
| 2241 | 198 item = gtk_list_item_new_with_label(name); |
| 199 gtk_widget_show(item); | |
| 200 items = g_list_append(items, item); | |
| 201 gtk_object_set_user_data(GTK_OBJECT(item), cr); | |
| 202 g_free(name); | |
| 203 } | |
| 204 c++; | |
| 205 } | |
| 206 gtk_list_append_items(GTK_LIST(cp->list1), items); | |
| 207 } | |
| 208 | |
| 209 static void refresh_list(GtkWidget *w, gpointer *m) | |
| 210 { | |
|
2872
30828b83143d
[gaim-migrate @ 2885]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2692
diff
changeset
|
211 grab_url("http://www.aim.com/community/chats.adp", FALSE, ref_list_callback, NULL); |
| 2241 | 212 } |
| 213 | |
| 214 static void add_chat(GtkWidget *w, gpointer *m) | |
| 215 { | |
| 216 GList *sel = GTK_LIST(cp->list1)->selection; | |
| 217 struct chat_room *cr, *cr2; | |
| 218 GList *crs = chat_rooms; | |
| 219 GtkWidget *item; | |
| 220 | |
| 221 if (sel) { | |
| 222 cr = (struct chat_room *)gtk_object_get_user_data(GTK_OBJECT(sel->data)); | |
| 223 } else | |
| 224 return; | |
| 225 | |
| 226 while (crs) { | |
| 227 cr2 = (struct chat_room *)crs->data; | |
| 228 if (!g_strcasecmp(cr->name, cr2->name)) | |
| 229 return; | |
| 230 crs = crs->next; | |
| 231 } | |
| 232 item = gtk_list_item_new_with_label(cr->name); | |
| 233 cr2 = g_new0(struct chat_room, 1); | |
| 234 strcpy(cr2->name, cr->name); | |
| 235 cr2->exchange = cr->exchange; | |
| 236 gtk_object_set_user_data(GTK_OBJECT(item), cr2); | |
| 237 gtk_widget_show(item); | |
| 238 sel = g_list_append(NULL, item); | |
| 239 gtk_list_append_items(GTK_LIST(cp->list2), sel); | |
| 240 chat_rooms = g_list_append(chat_rooms, cr2); | |
| 241 | |
| 242 setup_buddy_chats(); | |
| 243 save_chat_prefs(); | |
| 244 } | |
| 245 | |
| 246 static void remove_chat(GtkWidget *w, gpointer *m) | |
| 247 { | |
| 248 GList *sel = GTK_LIST(cp->list2)->selection; | |
| 249 struct chat_room *cr; | |
| 250 GList *crs; | |
| 251 GtkWidget *item; | |
| 252 | |
| 253 if (sel) { | |
| 254 item = (GtkWidget *)sel->data; | |
| 255 cr = (struct chat_room *)gtk_object_get_user_data(GTK_OBJECT(item)); | |
| 256 } else | |
| 257 return; | |
| 258 | |
| 259 chat_rooms = g_list_remove(chat_rooms, cr); | |
| 260 | |
| 261 | |
| 262 gtk_list_clear_items(GTK_LIST(cp->list2), 0, -1); | |
| 263 | |
| 264 if (g_list_length(chat_rooms) == 0) | |
| 265 chat_rooms = NULL; | |
| 266 | |
| 267 crs = chat_rooms; | |
| 268 | |
| 269 while (crs) { | |
| 270 cr = (struct chat_room *)crs->data; | |
| 271 item = gtk_list_item_new_with_label(cr->name); | |
| 272 gtk_object_set_user_data(GTK_OBJECT(item), cr); | |
| 273 gtk_widget_show(item); | |
| 274 gtk_list_append_items(GTK_LIST(cp->list2), g_list_append(NULL, item)); | |
| 275 | |
| 276 | |
| 277 crs = crs->next; | |
| 278 } | |
| 279 | |
| 280 setup_buddy_chats(); | |
| 281 save_chat_prefs(); | |
| 282 } | |
| 283 | |
| 3630 | 284 G_MODULE_EXPORT GtkWidget *gaim_plugin_config_gtk() |
| 2241 | 285 { |
| 3565 | 286 GtkWidget *ret, *vbox; |
| 2241 | 287 GtkWidget *list1, *list2; |
| 288 GtkWidget *sw1, *sw2; | |
| 3565 | 289 GtkWidget *ref_button, *add_button, *rem_button; |
| 290 GtkWidget *table, *label; | |
| 291 struct chat_room *cr = NULL; | |
| 2241 | 292 GList *items = NULL; |
| 3565 | 293 GList *crs = chat_rooms; |
| 294 | |
| 2241 | 295 if (cp) |
| 3565 | 296 g_free(cp); |
| 297 cp = g_new0(struct chat_page, 1); | |
| 2241 | 298 |
| 299 | |
| 3565 | 300 ret = gtk_vbox_new(FALSE, 18); |
| 301 gtk_container_set_border_width (GTK_CONTAINER (ret), 12); | |
| 2241 | 302 |
| 3565 | 303 vbox = make_frame(ret, _("Chat Rooms")); |
| 2241 | 304 |
| 305 table = gtk_table_new(4, 2, FALSE); | |
| 306 gtk_widget_show(table); | |
| 307 | |
| 3565 | 308 gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, TRUE, 0); |
| 2241 | 309 |
| 310 list1 = gtk_list_new(); | |
| 311 list2 = gtk_list_new(); | |
| 312 sw1 = gtk_scrolled_window_new(NULL, NULL); | |
| 313 sw2 = gtk_scrolled_window_new(NULL, NULL); | |
| 314 | |
| 3565 | 315 ref_button = picture_button(prefs, _("Refresh"), refresh_xpm); |
| 316 add_button = picture_button(prefs, _("Add"), gnome_add_xpm); | |
| 317 rem_button = picture_button(prefs, _("Remove"), gnome_remove_xpm); | |
| 2241 | 318 gtk_widget_show(list1); |
| 319 gtk_widget_show(sw1); | |
| 320 gtk_widget_show(list2); | |
| 321 gtk_widget_show(sw2); | |
| 322 | |
| 323 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw1), list1); | |
| 324 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw2), list2); | |
| 325 | |
| 326 cp->list1 = list1; | |
| 327 cp->list2 = list2; | |
| 328 | |
|
4165
07a3d1fae88f
[gaim-migrate @ 4394]
Christian Hammond <chipx86@chipx86.com>
parents:
4164
diff
changeset
|
329 g_signal_connect(GTK_OBJECT(ref_button), "clicked", G_CALLBACK(refresh_list), cp); |
|
07a3d1fae88f
[gaim-migrate @ 4394]
Christian Hammond <chipx86@chipx86.com>
parents:
4164
diff
changeset
|
330 g_signal_connect(GTK_OBJECT(rem_button), "clicked", G_CALLBACK(remove_chat), cp); |
|
07a3d1fae88f
[gaim-migrate @ 4394]
Christian Hammond <chipx86@chipx86.com>
parents:
4164
diff
changeset
|
331 g_signal_connect(GTK_OBJECT(add_button), "clicked", G_CALLBACK(add_chat), cp); |
| 2241 | 332 |
| 333 label = gtk_label_new(_("List of available chats")); | |
| 334 gtk_widget_show(label); | |
| 335 | |
| 336 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); | |
| 337 gtk_table_attach(GTK_TABLE(table), ref_button, 0, 1, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); | |
| 338 gtk_table_attach(GTK_TABLE(table), sw1, 0, 1, 2, 3, | |
| 339 GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 5, 5); | |
| 340 gtk_table_attach(GTK_TABLE(table), add_button, 0, 1, 3, 4, GTK_SHRINK, GTK_SHRINK, 0, 0); | |
| 341 | |
| 342 | |
| 343 label = gtk_label_new(_("List of subscribed chats")); | |
| 344 gtk_widget_show(label); | |
| 345 | |
| 346 gtk_table_attach(GTK_TABLE(table), label, 1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); | |
| 347 gtk_table_attach(GTK_TABLE(table), sw2, 1, 2, 2, 3, | |
| 348 GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 5, 5); | |
| 349 gtk_table_attach(GTK_TABLE(table), rem_button, 1, 2, 3, 4, GTK_SHRINK, GTK_SHRINK, 0, 0); | |
| 350 | |
| 351 | |
| 352 item = gtk_list_item_new_with_label(_("Gaim Chat")); | |
| 353 cr = g_new0(struct chat_room, 1); | |
| 354 strcpy(cr->name, _("Gaim Chat")); | |
| 355 cr->exchange = 4; | |
| 356 gtk_object_set_user_data(GTK_OBJECT(item), cr); | |
| 357 gtk_widget_show(item); | |
| 358 gtk_list_append_items(GTK_LIST(list1), g_list_append(NULL, item)); | |
| 359 | |
| 360 | |
| 361 while (crs) { | |
| 362 cr = (struct chat_room *)crs->data; | |
| 363 item = gtk_list_item_new_with_label(cr->name); | |
| 364 gtk_object_set_user_data(GTK_OBJECT(item), cr); | |
| 365 gtk_widget_show(item); | |
| 366 items = g_list_append(items, item); | |
| 367 | |
| 368 crs = crs->next; | |
| 369 } | |
| 370 | |
| 371 gtk_list_append_items(GTK_LIST(list2), items); | |
| 3565 | 372 gtk_widget_show_all(ret); |
| 373 return ret; | |
| 2241 | 374 } |
| 375 | |
| 376 static void handle_signon(struct gaim_connection *gc) | |
| 377 { | |
| 378 setup_buddy_chats(); | |
| 379 } | |
| 380 | |
| 3630 | 381 G_MODULE_EXPORT char *gaim_plugin_init(GModule *m) |
| 2241 | 382 { |
| 383 restore_chat_prefs(); | |
| 384 gaim_signal_connect(m, event_signon, handle_signon, NULL); | |
| 385 return NULL; | |
| 386 } | |
| 387 | |
| 3630 | 388 G_MODULE_EXPORT void gaim_plugin_remove() |
| 2241 | 389 { |
| 390 if (item) | |
| 391 gtk_tree_remove_item(GTK_TREE(buddies), item); | |
| 392 item = NULL; | |
| 393 | |
| 394 while (chat_rooms) { | |
| 395 g_free(chat_rooms->data); | |
| 396 chat_rooms = g_list_remove(chat_rooms, chat_rooms->data); | |
| 397 } | |
| 398 | |
| 399 if (cp) | |
| 400 g_free(cp); | |
| 401 cp = NULL; | |
| 402 } | |
| 403 | |
| 3551 | 404 struct gaim_plugin_description desc; |
| 405 struct gaim_plugin_description *gaim_plugin_desc() { | |
| 406 desc.api_version = PLUGIN_API_VERSION; | |
| 407 desc.name = g_strdup("Chat List"); | |
| 408 desc.version = g_strdup(VERSION); | |
| 409 desc.description = g_strdup("Allows you to add chat rooms to your buddy list."); | |
| 410 desc.authors = g_strdup("Eric Warmenhoven <eric@warmenhoven.org>"); | |
| 411 desc.url = g_strdup(WEBSITE); | |
| 412 return &desc; | |
| 413 } | |
| 414 | |
| 3630 | 415 G_MODULE_EXPORT char *name() |
| 2241 | 416 { |
| 417 return "Chat List"; | |
| 418 } | |
| 419 | |
| 3630 | 420 G_MODULE_EXPORT char *description() |
| 2241 | 421 { |
| 422 return "Allows you to add chat rooms to your buddy list. Click the configure button to choose" | |
| 423 " which rooms."; | |
| 424 } |
