Mercurial > pidgin.yaz
annotate src/gtkroomlist.c @ 9067:1f2bbb359adb
[gaim-migrate @ 9843]
This fixes a bug where the account was always null until you actually
clicked on the account selector, instead of being the first selected
account. The only time this wouldn't happen was when the roomlist was
invoked with /list.
committer: Tailor Script <tailor@pidgin.im>
author | Tim Ringenbach <marv@pidgin.im> |
---|---|
date | Wed, 26 May 2004 01:13:10 +0000 |
parents | b875f5d57b81 |
children | 31be05742be9 |
rev | line source |
---|---|
8113 | 1 /** |
8939 | 2 * @file gtkroomlist.c GTK+ Room List UI |
8113 | 3 * @ingroup gtkui |
4 * | |
5 * gaim | |
6 * | |
8146 | 7 * Gaim is the legal property of its developers, whose names are too numerous |
8 * to list here. Please refer to the COPYRIGHT file distributed with this | |
9 * source distribution. | |
8113 | 10 * |
11 * This program is free software; you can redistribute it and/or modify | |
12 * it under the terms of the GNU General Public License as published by | |
13 * the Free Software Foundation; either version 2 of the License, or | |
14 * (at your option) any later version. | |
15 * | |
16 * This program is distributed in the hope that it will be useful, | |
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 * GNU General Public License for more details. | |
20 * | |
21 * You should have received a copy of the GNU General Public License | |
22 * along with this program; if not, write to the Free Software | |
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
24 */ | |
25 | |
26 #include "gtkinternal.h" | |
27 #include "gtkutils.h" | |
28 #include "stock.h" | |
29 #include "debug.h" | |
30 #include "account.h" | |
31 #include "connection.h" | |
32 #include "notify.h" | |
33 | |
34 #include "gtkroomlist.h" | |
35 | |
36 typedef struct _GaimGtkRoomlist { | |
37 GaimGtkRoomlistDialog *dialog; | |
38 GtkTreeStore *model; | |
39 GtkWidget *tree; | |
40 GHashTable *cats; /**< Meow. */ | |
41 gint num_rooms, total_rooms; | |
42 } GaimGtkRoomlist; | |
43 | |
44 struct _GaimGtkRoomlistDialog { | |
45 GtkWidget *window; | |
46 GtkWidget *account_widget; | |
47 GtkWidget *progress; | |
48 GtkWidget *sw; | |
49 | |
8199 | 50 GtkWidget *stop_button; |
8113 | 51 GtkWidget *list_button; |
8199 | 52 GtkWidget *join_button; |
8113 | 53 GtkWidget *close_button; |
54 | |
55 GaimAccount *account; | |
56 GaimRoomlist *roomlist; | |
8230 | 57 |
58 gboolean pg_needs_pulse; | |
59 gboolean pg_to_active; | |
60 guint pg_update_to; | |
8113 | 61 }; |
62 | |
63 enum { | |
64 NAME_COLUMN = 0, | |
65 ROOM_COLUMN, | |
66 NUM_OF_COLUMNS, | |
67 }; | |
68 | |
69 static GList *roomlists = NULL; | |
70 | |
71 static gint delete_win_cb(GtkWidget *w, GdkEventAny *e, gpointer d) | |
72 { | |
73 GaimGtkRoomlistDialog *dialog; | |
74 | |
75 dialog = (GaimGtkRoomlistDialog *) d; | |
76 | |
8199 | 77 if (dialog->roomlist && gaim_roomlist_get_in_progress(dialog->roomlist)) |
78 gaim_roomlist_cancel_get_list(dialog->roomlist); | |
79 | |
8230 | 80 if (dialog->roomlist) { |
81 if (dialog->pg_to_active) { | |
8287
ef881489396e
[gaim-migrate @ 9011]
Christian Hammond <chipx86@chipx86.com>
parents:
8230
diff
changeset
|
82 gaim_timeout_remove(dialog->pg_update_to); |
8230 | 83 dialog->pg_to_active = FALSE; |
84 /* yes, that's right, unref it twice. */ | |
85 gaim_roomlist_unref(dialog->roomlist); | |
86 } | |
87 } | |
88 | |
8113 | 89 /* free stuff here */ |
90 if (dialog->roomlist) | |
91 gaim_roomlist_unref(dialog->roomlist); | |
92 g_free(dialog); | |
93 | |
94 return FALSE; | |
95 } | |
96 | |
97 static void dialog_select_account_cb(GObject *w, GaimAccount *account, | |
98 GaimGtkRoomlistDialog *dialog) | |
99 { | |
100 dialog->account = account; | |
101 } | |
102 | |
103 static void list_button_cb(GtkButton *button, GaimGtkRoomlistDialog *dialog) | |
104 { | |
105 GaimConnection *gc; | |
106 GaimGtkRoomlist *rl; | |
107 | |
108 gc = gaim_account_get_connection(dialog->account); | |
109 if (!gc) | |
110 return; | |
111 | |
8199 | 112 if (dialog->roomlist != NULL) { |
113 rl = dialog->roomlist->ui_data; | |
114 gtk_widget_destroy(rl->tree); | |
115 gaim_roomlist_unref(dialog->roomlist); | |
116 } | |
117 | |
8113 | 118 dialog->roomlist = gaim_roomlist_get_list(gc); |
119 gaim_roomlist_ref(dialog->roomlist); | |
120 rl = dialog->roomlist->ui_data; | |
121 rl->dialog = dialog; | |
8199 | 122 |
8113 | 123 if (dialog->account_widget) |
124 gtk_widget_set_sensitive(dialog->account_widget, FALSE); | |
8199 | 125 |
126 gtk_container_add(GTK_CONTAINER(dialog->sw), rl->tree); | |
127 | |
128 gtk_widget_set_sensitive(dialog->stop_button, TRUE); | |
8113 | 129 gtk_widget_set_sensitive(dialog->list_button, FALSE); |
8199 | 130 gtk_widget_set_sensitive(dialog->join_button, FALSE); |
8113 | 131 } |
132 | |
133 static void stop_button_cb(GtkButton *button, GaimGtkRoomlistDialog *dialog) | |
134 { | |
135 gaim_roomlist_cancel_get_list(dialog->roomlist); | |
8199 | 136 |
137 if (dialog->account_widget) | |
138 gtk_widget_set_sensitive(dialog->account_widget, TRUE); | |
139 | |
140 gtk_widget_set_sensitive(dialog->stop_button, FALSE); | |
141 gtk_widget_set_sensitive(dialog->list_button, TRUE); | |
142 gtk_widget_set_sensitive(dialog->join_button, FALSE); | |
8113 | 143 } |
144 | |
145 static void close_button_cb(GtkButton *button, GaimGtkRoomlistDialog *dialog) | |
146 { | |
147 GtkWidget *window = dialog->window; | |
148 | |
149 delete_win_cb(NULL, NULL, dialog); | |
150 gtk_widget_destroy(window); | |
151 } | |
152 | |
153 struct _menu_cb_info { | |
154 GaimRoomlist *list; | |
155 GaimRoomlistRoom *room; | |
156 }; | |
157 | |
8199 | 158 static void |
8377 | 159 join_button_data_change_cb(gpointer data) { |
160 g_free(data); | |
161 } | |
162 | |
163 static void | |
8199 | 164 selection_changed_cb(GtkTreeSelection *selection, GaimGtkRoomlist *grl) { |
165 GtkTreeIter iter; | |
166 GValue val = { 0, }; | |
167 GaimRoomlistRoom *room; | |
168 static struct _menu_cb_info *info; | |
169 GaimGtkRoomlistDialog *dialog; | |
170 | |
171 dialog = grl->dialog; | |
172 | |
173 if (gtk_tree_selection_get_selected(selection, NULL, &iter)) { | |
174 gtk_tree_model_get_value(GTK_TREE_MODEL(grl->model), &iter, ROOM_COLUMN, &val); | |
175 room = g_value_get_pointer(&val); | |
176 if (!room || !(room->type & GAIM_ROOMLIST_ROOMTYPE_ROOM)) { | |
177 gtk_widget_set_sensitive(dialog->join_button, FALSE); | |
178 return; | |
179 } | |
180 | |
181 info = g_new0(struct _menu_cb_info, 1); | |
182 info->list = dialog->roomlist; | |
183 info->room = room; | |
184 | |
8377 | 185 g_object_set_data_full(G_OBJECT(dialog->join_button), "room-info", |
186 info, join_button_data_change_cb); | |
8199 | 187 |
188 gtk_widget_set_sensitive(dialog->join_button, TRUE); | |
189 } else { | |
190 gtk_widget_set_sensitive(dialog->join_button, FALSE); | |
191 } | |
192 } | |
193 | |
8113 | 194 static void do_join_cb(GtkWidget *w, struct _menu_cb_info *info) |
195 { | |
8199 | 196 gaim_roomlist_room_join(info->list, info->room); |
197 } | |
8113 | 198 |
8199 | 199 static void join_button_cb(GtkButton *button, GaimGtkRoomlistDialog *dialog) |
200 { | |
201 GaimRoomlist *rl = dialog->roomlist; | |
202 GaimGtkRoomlist *grl = rl->ui_data; | |
203 struct _menu_cb_info *info; | |
204 | |
205 info = (struct _menu_cb_info*)g_object_get_data(G_OBJECT(button), "room-info"); | |
206 | |
8377 | 207 if(info != NULL) |
208 do_join_cb(grl->tree, info); | |
8113 | 209 } |
210 | |
211 static void row_activated_cb(GtkTreeView *tv, GtkTreePath *path, GtkTreeViewColumn *arg2, | |
212 GaimRoomlist *list) | |
213 { | |
214 GaimGtkRoomlist *grl = list->ui_data; | |
215 GtkTreeIter iter; | |
216 GaimRoomlistRoom *room; | |
217 GValue val = { 0, }; | |
218 struct _menu_cb_info info; | |
219 | |
220 gtk_tree_model_get_iter(GTK_TREE_MODEL(grl->model), &iter, path); | |
221 gtk_tree_model_get_value(GTK_TREE_MODEL(grl->model), &iter, ROOM_COLUMN, &val); | |
222 room = g_value_get_pointer(&val); | |
223 if (!room || !(room->type & GAIM_ROOMLIST_ROOMTYPE_ROOM)) | |
224 return; | |
225 | |
226 info.list = list; | |
227 info.room = room; | |
228 | |
229 do_join_cb(GTK_WIDGET(tv), &info); | |
230 } | |
231 | |
232 static gboolean room_click_cb(GtkWidget *tv, GdkEventButton *event, GaimRoomlist *list) | |
233 { | |
234 GtkTreePath *path; | |
235 GaimGtkRoomlist *grl = list->ui_data; | |
236 GValue val = { 0, }; | |
237 GaimRoomlistRoom *room; | |
238 GtkTreeIter iter; | |
239 GtkWidget *menu; | |
240 static struct _menu_cb_info info; /* XXX? */ | |
241 | |
242 if (event->button != 3 || event->type != GDK_BUTTON_PRESS) | |
243 return FALSE; | |
244 | |
245 /* Here we figure out which room was clicked */ | |
246 if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), event->x, event->y, &path, NULL, NULL, NULL)) | |
247 return FALSE; | |
248 gtk_tree_model_get_iter(GTK_TREE_MODEL(grl->model), &iter, path); | |
249 gtk_tree_path_free(path); | |
250 gtk_tree_model_get_value (GTK_TREE_MODEL(grl->model), &iter, ROOM_COLUMN, &val); | |
251 room = g_value_get_pointer(&val); | |
252 | |
253 if (!room || !(room->type & GAIM_ROOMLIST_ROOMTYPE_ROOM)) | |
254 return FALSE; | |
255 | |
256 info.list = list; | |
257 info.room = room; | |
258 | |
259 | |
260 menu = gtk_menu_new(); | |
261 gaim_new_item_from_stock(menu, _("_Join"), GAIM_STOCK_CHAT, | |
262 G_CALLBACK(do_join_cb), &info, 0, 0, NULL); | |
263 | |
264 | |
265 gtk_widget_show_all(menu); | |
266 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3, event->time); | |
267 | |
268 return FALSE; | |
269 } | |
270 | |
271 static void row_expanded_cb(GtkTreeView *treeview, GtkTreeIter *arg1, GtkTreePath *arg2, gpointer user_data) | |
272 { | |
273 GaimRoomlist *list = user_data; | |
8584 | 274 GaimRoomlistRoom *category; |
8113 | 275 GValue val = { 0, }; |
276 | |
277 gtk_tree_model_get_value(gtk_tree_view_get_model(treeview), arg1, ROOM_COLUMN, &val); | |
8584 | 278 category = g_value_get_pointer(&val); |
8113 | 279 |
8584 | 280 if (!category->expanded_once) { |
281 gaim_roomlist_expand_category(list, category); | |
282 category->expanded_once = TRUE; | |
8113 | 283 } |
284 } | |
285 | |
8939 | 286 static gboolean account_filter_func(GaimAccount *account) |
8113 | 287 { |
8939 | 288 GaimConnection *gc = gaim_account_get_connection(account); |
289 GaimPluginProtocolInfo *prpl_info = NULL; | |
290 | |
291 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl); | |
292 | |
293 return (prpl_info->roomlist_get_list != NULL); | |
294 } | |
295 | |
296 gboolean | |
297 gaim_gtk_roomlist_is_showable() | |
298 { | |
299 GList *c; | |
8113 | 300 GaimConnection *gc; |
301 | |
8939 | 302 for (c = gaim_connections_get_all(); c != NULL; c = c->next) { |
303 gc = c->data; | |
304 | |
305 if (account_filter_func(gaim_connection_get_account(gc))) | |
306 return TRUE; | |
307 } | |
308 | |
309 return FALSE; | |
8113 | 310 } |
311 | |
312 GaimGtkRoomlistDialog *gaim_gtk_roomlist_dialog_new_with_account(GaimAccount *account) | |
313 { | |
314 GaimGtkRoomlistDialog *dialog; | |
315 GtkWidget *window; | |
8199 | 316 GtkWidget *vbox; |
317 GtkWidget *vbox2; | |
8113 | 318 GtkWidget *account_hbox; |
319 GtkWidget *bbox; | |
320 GtkWidget *label; | |
321 | |
322 dialog = g_new0(GaimGtkRoomlistDialog, 1); | |
8937 | 323 dialog->account = account; |
8113 | 324 |
325 /* Create the window. */ | |
326 dialog->window = window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | |
327 gtk_window_set_role(GTK_WINDOW(window), "room list"); | |
328 gtk_window_set_title(GTK_WINDOW(window), _("Room List")); | |
329 | |
330 gtk_container_set_border_width(GTK_CONTAINER(window), 12); | |
331 gtk_widget_realize(window); | |
332 | |
333 g_signal_connect(G_OBJECT(window), "delete_event", | |
334 G_CALLBACK(delete_win_cb), dialog); | |
335 | |
336 /* Create the parent vbox for everything. */ | |
8199 | 337 vbox = gtk_vbox_new(FALSE, 12); |
338 gtk_container_add(GTK_CONTAINER(window), vbox); | |
339 gtk_widget_show(vbox); | |
8113 | 340 |
8199 | 341 vbox2 = gtk_vbox_new(FALSE, 12); |
342 gtk_container_add(GTK_CONTAINER(vbox), vbox2); | |
8113 | 343 gtk_widget_show(vbox2); |
344 | |
8352 | 345 /* accounts dropdown list */ |
8425
6d8ec773a485
[gaim-migrate @ 9155]
Christian Hammond <chipx86@chipx86.com>
parents:
8377
diff
changeset
|
346 account_hbox = gtk_hbox_new(FALSE, 6); |
8352 | 347 gtk_box_pack_start(GTK_BOX(vbox2), account_hbox, FALSE, FALSE, 0); |
348 gtk_widget_show(account_hbox); | |
8113 | 349 |
8352 | 350 label = gtk_label_new(NULL); |
8425
6d8ec773a485
[gaim-migrate @ 9155]
Christian Hammond <chipx86@chipx86.com>
parents:
8377
diff
changeset
|
351 gtk_box_pack_start(GTK_BOX(account_hbox), label, FALSE, FALSE, 0); |
8352 | 352 gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), _("_Account:")); |
8425
6d8ec773a485
[gaim-migrate @ 9155]
Christian Hammond <chipx86@chipx86.com>
parents:
8377
diff
changeset
|
353 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); |
8352 | 354 gtk_widget_show(label); |
8113 | 355 |
8352 | 356 dialog->account_widget = gaim_gtk_account_option_menu_new(dialog->account, FALSE, |
8939 | 357 G_CALLBACK(dialog_select_account_cb), account_filter_func, dialog); |
8199 | 358 |
9067 | 359 if (!dialog->account) /* this is normally null, and we normally don't care what the first selected item is */ |
360 dialog->account = gaim_gtk_account_option_menu_get_selected(dialog->account_widget); | |
361 | |
8352 | 362 gtk_box_pack_start(GTK_BOX(account_hbox), dialog->account_widget, TRUE, TRUE, 0); |
363 gtk_label_set_mnemonic_widget(GTK_LABEL(label), GTK_WIDGET(dialog->account_widget)); | |
364 gtk_widget_show(dialog->account_widget); | |
8113 | 365 |
8199 | 366 /* scrolled window */ |
8113 | 367 dialog->sw = gtk_scrolled_window_new(NULL, NULL); |
368 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(dialog->sw), | |
369 GTK_SHADOW_IN); | |
370 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(dialog->sw), | |
371 GTK_POLICY_AUTOMATIC, | |
372 GTK_POLICY_AUTOMATIC); | |
8199 | 373 gtk_box_pack_start(GTK_BOX(vbox2), dialog->sw, TRUE, TRUE, 0); |
374 gtk_widget_set_size_request(dialog->sw, -1, 250); | |
8113 | 375 gtk_widget_show(dialog->sw); |
376 | |
8199 | 377 /* progress bar */ |
378 dialog->progress = gtk_progress_bar_new(); | |
379 gtk_progress_bar_set_pulse_step(GTK_PROGRESS_BAR(dialog->progress), 0.1); | |
380 gtk_box_pack_start(GTK_BOX(vbox2), dialog->progress, FALSE, FALSE, 0); | |
381 gtk_widget_show(dialog->progress); | |
382 | |
383 | |
384 /* button box */ | |
385 bbox = gtk_hbutton_box_new(); | |
386 gtk_box_set_spacing(GTK_BOX(bbox), 6); | |
387 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); | |
388 gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, TRUE, 0); | |
389 gtk_widget_show(bbox); | |
390 | |
391 /* stop button */ | |
392 dialog->stop_button = gtk_button_new_from_stock(GTK_STOCK_STOP); | |
393 gtk_box_pack_start(GTK_BOX(bbox), dialog->stop_button, FALSE, FALSE, 0); | |
394 g_signal_connect(G_OBJECT(dialog->stop_button), "clicked", | |
395 G_CALLBACK(stop_button_cb), dialog); | |
396 gtk_widget_set_sensitive(dialog->stop_button, FALSE); | |
397 gtk_widget_show(dialog->stop_button); | |
398 | |
399 /* list button */ | |
400 dialog->list_button = gtk_button_new_with_mnemonic(_("_Get List")); | |
401 gtk_box_pack_start(GTK_BOX(bbox), dialog->list_button, FALSE, FALSE, 0); | |
402 g_signal_connect(G_OBJECT(dialog->list_button), "clicked", | |
403 G_CALLBACK(list_button_cb), dialog); | |
404 gtk_widget_show(dialog->list_button); | |
405 | |
406 /* join button */ | |
407 dialog->join_button = gaim_pixbuf_button_from_stock(_("_Join"), GAIM_STOCK_CHAT, | |
408 GAIM_BUTTON_HORIZONTAL); | |
409 gtk_box_pack_start(GTK_BOX(bbox), dialog->join_button, FALSE, FALSE, 0); | |
410 g_signal_connect(G_OBJECT(dialog->join_button), "clicked", | |
411 G_CALLBACK(join_button_cb), dialog); | |
412 gtk_widget_set_sensitive(dialog->join_button, FALSE); | |
413 gtk_widget_show(dialog->join_button); | |
414 | |
415 /* close button */ | |
416 dialog->close_button = gtk_button_new_from_stock(GTK_STOCK_CLOSE); | |
417 gtk_box_pack_start(GTK_BOX(bbox), dialog->close_button, FALSE, FALSE, 0); | |
418 g_signal_connect(G_OBJECT(dialog->close_button), "clicked", | |
419 G_CALLBACK(close_button_cb), dialog); | |
420 gtk_widget_show(dialog->close_button); | |
421 | |
422 /* show the dialog window and return the dialog */ | |
423 gtk_widget_show(dialog->window); | |
424 | |
8113 | 425 return dialog; |
426 } | |
427 | |
428 GaimGtkRoomlistDialog *gaim_gtk_roomlist_dialog_new(void) | |
429 { | |
430 return gaim_gtk_roomlist_dialog_new_with_account(NULL); | |
431 } | |
432 | |
8352 | 433 static void gaim_gtk_roomlist_dialog_show_with_account(GaimAccount *account) |
434 { | |
435 GaimGtkRoomlistDialog *dialog; | |
436 | |
437 dialog = gaim_gtk_roomlist_dialog_new_with_account(account); | |
438 if (!dialog) | |
439 return; | |
440 | |
441 list_button_cb(GTK_BUTTON(dialog->list_button), dialog); | |
442 } | |
443 | |
8113 | 444 void gaim_gtk_roomlist_dialog_show(void) |
445 { | |
446 gaim_gtk_roomlist_dialog_new(); | |
447 } | |
448 | |
449 static void gaim_gtk_roomlist_new(GaimRoomlist *list) | |
450 { | |
451 GaimGtkRoomlist *rl; | |
452 | |
453 rl = g_new0(GaimGtkRoomlist, 1); | |
454 | |
455 list->ui_data = rl; | |
456 | |
457 rl->cats = g_hash_table_new_full(NULL, NULL, NULL, (GDestroyNotify)gtk_tree_row_reference_free); | |
458 | |
459 roomlists = g_list_append(roomlists, list); | |
460 } | |
461 | |
462 static void int_cell_data_func(GtkTreeViewColumn *col, GtkCellRenderer *renderer, | |
463 GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data) | |
464 { | |
465 gchar buf[16]; | |
466 int myint; | |
467 | |
468 gtk_tree_model_get(model, iter, GPOINTER_TO_INT(user_data), &myint, -1); | |
469 | |
470 if (myint) | |
471 g_snprintf(buf, sizeof(buf), "%d", myint); | |
472 else | |
473 buf[0] = '\0'; | |
474 | |
475 g_object_set(renderer, "text", buf, NULL); | |
476 } | |
477 | |
478 /* this sorts backwards on purpose, so that clicking name sorts a-z, while clicking users sorts | |
479 infinity-0. you can still click again to reverse it on any of them. */ | |
480 static gint int_sort_func(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data) | |
481 { | |
482 int c, d; | |
483 | |
484 c = d = 0; | |
485 | |
486 gtk_tree_model_get(model, a, GPOINTER_TO_INT(user_data), &c, -1); | |
487 gtk_tree_model_get(model, b, GPOINTER_TO_INT(user_data), &d, -1); | |
488 | |
489 if (c == d) | |
490 return 0; | |
491 else if (c > d) | |
492 return -1; | |
493 else | |
494 return 1; | |
495 } | |
496 | |
497 static void gaim_gtk_roomlist_set_fields(GaimRoomlist *list, GList *fields) | |
498 { | |
499 GaimGtkRoomlist *grl = list->ui_data; | |
500 gint columns = NUM_OF_COLUMNS; | |
501 int j; | |
502 GtkTreeStore *model; | |
503 GtkWidget *tree; | |
504 GtkCellRenderer *renderer; | |
505 GtkTreeViewColumn *column; | |
8199 | 506 GtkTreeSelection *selection; |
8113 | 507 GList *l; |
508 GType *types; | |
509 | |
510 g_return_if_fail(grl != NULL); | |
511 | |
512 columns += g_list_length(fields); | |
513 types = g_new(GType, columns); | |
514 | |
515 types[NAME_COLUMN] = G_TYPE_STRING; | |
516 types[ROOM_COLUMN] = G_TYPE_POINTER; | |
517 | |
518 for (j = NUM_OF_COLUMNS, l = fields; l; l = l->next, j++) { | |
519 GaimRoomlistField *f = l->data; | |
520 | |
521 switch (f->type) { | |
522 case GAIM_ROOMLIST_FIELD_BOOL: | |
523 types[j] = G_TYPE_BOOLEAN; | |
524 break; | |
525 case GAIM_ROOMLIST_FIELD_INT: | |
526 types[j] = G_TYPE_INT; | |
527 break; | |
528 case GAIM_ROOMLIST_FIELD_STRING: | |
529 types[j] = G_TYPE_STRING; | |
530 break; | |
531 } | |
532 } | |
533 | |
534 model = gtk_tree_store_newv(columns, types); | |
535 g_free(types); | |
536 | |
537 tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model)); | |
538 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(tree), TRUE); | |
539 | |
8199 | 540 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree)); |
541 g_signal_connect(G_OBJECT(selection), "changed", | |
542 G_CALLBACK(selection_changed_cb), grl); | |
543 | |
8113 | 544 g_object_unref(model); |
545 | |
546 grl->model = model; | |
547 grl->tree = tree; | |
548 gtk_widget_show(grl->tree); | |
549 | |
550 renderer = gtk_cell_renderer_text_new(); | |
551 column = gtk_tree_view_column_new_with_attributes(_("Name"), renderer, | |
552 "text", NAME_COLUMN, NULL); | |
553 gtk_tree_view_column_set_sizing(GTK_TREE_VIEW_COLUMN(column), | |
554 GTK_TREE_VIEW_COLUMN_GROW_ONLY); | |
555 gtk_tree_view_column_set_resizable(GTK_TREE_VIEW_COLUMN(column), TRUE); | |
556 gtk_tree_view_column_set_sort_column_id(GTK_TREE_VIEW_COLUMN(column), NAME_COLUMN); | |
557 gtk_tree_view_column_set_reorderable(GTK_TREE_VIEW_COLUMN(column), TRUE); | |
558 gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); | |
559 | |
560 for (j = NUM_OF_COLUMNS, l = fields; l; l = l->next, j++) { | |
561 GaimRoomlistField *f = l->data; | |
562 | |
563 if (f->hidden) | |
564 continue; | |
565 | |
566 renderer = gtk_cell_renderer_text_new(); | |
567 column = gtk_tree_view_column_new_with_attributes(f->label, renderer, | |
568 "text", j, NULL); | |
569 gtk_tree_view_column_set_sizing(GTK_TREE_VIEW_COLUMN(column), | |
570 GTK_TREE_VIEW_COLUMN_GROW_ONLY); | |
571 gtk_tree_view_column_set_resizable(GTK_TREE_VIEW_COLUMN(column), TRUE); | |
572 gtk_tree_view_column_set_sort_column_id(GTK_TREE_VIEW_COLUMN(column), j); | |
573 gtk_tree_view_column_set_reorderable(GTK_TREE_VIEW_COLUMN(column), TRUE); | |
574 if (f->type == GAIM_ROOMLIST_FIELD_INT) { | |
575 gtk_tree_view_column_set_cell_data_func(column, renderer, int_cell_data_func, | |
576 GINT_TO_POINTER(j), NULL); | |
577 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(model), j, int_sort_func, | |
578 GINT_TO_POINTER(j), NULL); | |
579 } | |
580 gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); | |
581 } | |
582 | |
583 g_signal_connect(G_OBJECT(tree), "button-press-event", G_CALLBACK(room_click_cb), list); | |
584 g_signal_connect(G_OBJECT(tree), "row-expanded", G_CALLBACK(row_expanded_cb), list); | |
585 g_signal_connect(G_OBJECT(tree), "row-activated", G_CALLBACK(row_activated_cb), list); | |
586 } | |
587 | |
8230 | 588 static gboolean gaim_gtk_progress_bar_pulse(gpointer data) |
589 { | |
590 GaimRoomlist *list = data; | |
591 GaimGtkRoomlist *rl = list->ui_data; | |
592 | |
593 if (!rl || !rl->dialog || !rl->dialog->pg_needs_pulse) { | |
594 rl->dialog->pg_to_active = FALSE; | |
595 gaim_roomlist_unref(list); | |
596 return FALSE; | |
597 } | |
598 | |
599 gtk_progress_bar_pulse(GTK_PROGRESS_BAR(rl->dialog->progress)); | |
600 rl->dialog->pg_needs_pulse = FALSE; | |
601 return TRUE; | |
602 } | |
603 | |
8113 | 604 static void gaim_gtk_roomlist_add_room(GaimRoomlist *list, GaimRoomlistRoom *room) |
605 { | |
606 GaimGtkRoomlist *rl= list->ui_data; | |
607 GtkTreeRowReference *rr, *parentrr = NULL; | |
608 GtkTreePath *path; | |
609 GtkTreeIter iter, parent, child; | |
610 GList *l, *k; | |
611 int j; | |
612 gboolean append = TRUE; | |
613 | |
614 rl->total_rooms++; | |
615 if (room->type == GAIM_ROOMLIST_ROOMTYPE_ROOM) | |
616 rl->num_rooms++; | |
617 | |
618 if (rl->dialog) { | |
8230 | 619 if (!rl->dialog->pg_to_active) { |
620 rl->dialog->pg_to_active = TRUE; | |
621 gaim_roomlist_ref(list); | |
622 rl->dialog->pg_update_to = g_timeout_add(100, gaim_gtk_progress_bar_pulse, list); | |
623 gtk_progress_bar_pulse(GTK_PROGRESS_BAR(rl->dialog->progress)); | |
624 } else { | |
625 rl->dialog->pg_needs_pulse = TRUE; | |
626 } | |
8113 | 627 } |
628 if (room->parent) { | |
629 parentrr = g_hash_table_lookup(rl->cats, room->parent); | |
630 path = gtk_tree_row_reference_get_path(parentrr); | |
631 if (path) { | |
632 GaimRoomlistRoom *tmproom = NULL; | |
633 | |
634 gtk_tree_model_get_iter(GTK_TREE_MODEL(rl->model), &parent, path); | |
635 gtk_tree_path_free(path); | |
636 | |
637 if (gtk_tree_model_iter_children(GTK_TREE_MODEL(rl->model), &child, &parent)) { | |
638 gtk_tree_model_get(GTK_TREE_MODEL(rl->model), &child, ROOM_COLUMN, &tmproom, -1); | |
639 if (!tmproom) | |
640 append = FALSE; | |
641 } | |
642 } | |
643 } | |
644 | |
645 if (append) | |
646 gtk_tree_store_append(rl->model, &iter, (parentrr ? &parent : NULL)); | |
647 else | |
648 iter = child; | |
649 | |
8584 | 650 if (room->type & GAIM_ROOMLIST_ROOMTYPE_CATEGORY) |
8113 | 651 gtk_tree_store_append(rl->model, &child, &iter); |
652 | |
653 path = gtk_tree_model_get_path(GTK_TREE_MODEL(rl->model), &iter); | |
654 | |
8584 | 655 if (room->type & GAIM_ROOMLIST_ROOMTYPE_CATEGORY) { |
8113 | 656 rr = gtk_tree_row_reference_new(GTK_TREE_MODEL(rl->model), path); |
657 g_hash_table_insert(rl->cats, room, rr); | |
658 } | |
659 | |
660 gtk_tree_path_free(path); | |
661 | |
662 gtk_tree_store_set(rl->model, &iter, NAME_COLUMN, room->name, -1); | |
663 gtk_tree_store_set(rl->model, &iter, ROOM_COLUMN, room, -1); | |
664 | |
665 for (j = NUM_OF_COLUMNS, l = room->fields, k = list->fields; l && k; j++, l = l->next, k = k->next) { | |
666 GaimRoomlistField *f = k->data; | |
667 if (f->hidden) | |
668 continue; | |
669 gtk_tree_store_set(rl->model, &iter, j, l->data, -1); | |
670 } | |
671 } | |
672 | |
673 static void gaim_gtk_roomlist_in_progress(GaimRoomlist *list, gboolean flag) | |
674 { | |
675 GaimGtkRoomlist *rl = list->ui_data; | |
676 | |
677 if (!rl || !rl->dialog) | |
678 return; | |
679 | |
680 if (flag) { | |
8199 | 681 if (rl->dialog->account_widget) |
682 gtk_widget_set_sensitive(rl->dialog->account_widget, FALSE); | |
683 gtk_widget_set_sensitive(rl->dialog->stop_button, TRUE); | |
684 gtk_widget_set_sensitive(rl->dialog->list_button, FALSE); | |
8113 | 685 } else { |
8230 | 686 rl->dialog->pg_needs_pulse = FALSE; |
8113 | 687 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(rl->dialog->progress), 0.0); |
8199 | 688 if (rl->dialog->account_widget) |
689 gtk_widget_set_sensitive(rl->dialog->account_widget, TRUE); | |
690 gtk_widget_set_sensitive(rl->dialog->stop_button, FALSE); | |
691 gtk_widget_set_sensitive(rl->dialog->list_button, TRUE); | |
8113 | 692 } |
693 } | |
694 | |
695 static void gaim_gtk_roomlist_destroy(GaimRoomlist *list) | |
696 { | |
697 GaimGtkRoomlist *rl; | |
698 | |
699 roomlists = g_list_remove(roomlists, list); | |
700 | |
701 rl = list->ui_data; | |
702 | |
703 g_return_if_fail(rl != NULL); | |
704 | |
705 g_hash_table_destroy(rl->cats); | |
706 g_free(rl); | |
707 list->ui_data = NULL; | |
708 } | |
709 | |
710 static GaimRoomlistUiOps ops = { | |
8352 | 711 gaim_gtk_roomlist_dialog_show_with_account, |
8113 | 712 gaim_gtk_roomlist_new, |
713 gaim_gtk_roomlist_set_fields, | |
714 gaim_gtk_roomlist_add_room, | |
715 gaim_gtk_roomlist_in_progress, | |
716 gaim_gtk_roomlist_destroy | |
717 }; | |
718 | |
719 | |
720 void gaim_gtk_roomlist_init(void) | |
721 { | |
722 gaim_roomlist_set_ui_ops(&ops); | |
723 } |