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