Merged pidgin/main into default
[pidgin-git.git] / finch / gntroomlist.c
blob147c2c8851da030325ce92f51f98eed0c211340d
1 /* finch
3 * Finch is the legal property of its developers, whose names are too numerous
4 * to list here. Please refer to the COPYRIGHT file distributed with this
5 * source distribution.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
22 #include "finch.h"
23 #include <internal.h>
25 #include "gntrequest.h"
26 #include "gntroomlist.h"
28 #include "gntbox.h"
29 #include "gntbutton.h"
30 #include "gntcombobox.h"
31 #include "gnttextview.h"
32 #include "gnttree.h"
33 #include "gntwindow.h"
35 #include "debug.h"
37 #define PREF_ROOT "/finch/roomlist"
40 /* Yes, just one roomlist at a time. Let's not get greedy. Aight? */
41 struct _FinchRoomlist
43 GntWidget *window;
45 GntWidget *accounts;
46 GntWidget *tree;
47 GntWidget *details;
49 GntWidget *getlist;
50 GntWidget *add;
51 GntWidget *join;
52 GntWidget *stop;
53 GntWidget *close;
55 PurpleAccount *account;
56 PurpleRoomlist *roomlist;
57 } froomlist;
59 typedef struct _FinchRoomlist FinchRoomlist;
61 static void
62 unset_roomlist(gpointer null)
64 froomlist.window = NULL;
65 if (froomlist.roomlist) {
66 g_object_unref(froomlist.roomlist);
67 froomlist.roomlist = NULL;
69 froomlist.account = NULL;
70 froomlist.tree = NULL;
73 static void
74 update_roomlist(PurpleRoomlist *list)
76 if (froomlist.roomlist == list)
77 return;
79 if (froomlist.roomlist)
80 g_object_unref(froomlist.roomlist);
82 if ((froomlist.roomlist = list) != NULL)
83 g_object_ref(list);
86 static void fl_stop(GntWidget *button, gpointer null)
88 if (froomlist.roomlist &&
89 purple_roomlist_get_in_progress(froomlist.roomlist))
90 purple_roomlist_cancel_get_list(froomlist.roomlist);
93 static void fl_get_list(GntWidget *button, gpointer null)
95 PurpleAccount *account = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(froomlist.accounts));
96 PurpleConnection *gc = purple_account_get_connection(account);
98 if (!gc)
99 return;
101 update_roomlist(NULL);
102 froomlist.roomlist = purple_roomlist_get_list(gc);
103 gnt_box_give_focus_to_child(GNT_BOX(froomlist.window), froomlist.tree);
106 static void fl_add_chat(GntWidget *button, gpointer null)
108 char *name;
109 PurpleRoomlistRoom *room = gnt_tree_get_selection_data(GNT_TREE(froomlist.tree));
110 PurpleConnection *gc = purple_account_get_connection(froomlist.account);
111 PurpleProtocol *protocol = NULL;
113 if (gc == NULL || room == NULL)
114 return;
116 protocol = purple_connection_get_protocol(gc);
118 if(protocol != NULL && PURPLE_PROTOCOL_IMPLEMENTS(protocol, ROOMLIST_IFACE, room_serialize))
119 name = purple_protocol_roomlist_iface_room_serialize(protocol, room);
120 else
121 name = g_strdup(purple_roomlist_room_get_name(room));
123 purple_blist_request_add_chat(froomlist.account, NULL, NULL, name);
125 g_free(name);
128 static void fl_close(GntWidget *button, gpointer null)
130 gnt_widget_destroy(froomlist.window);
133 static void
134 roomlist_activated(GntWidget *widget)
136 PurpleRoomlistRoom *room = gnt_tree_get_selection_data(GNT_TREE(widget));
137 if (!room)
138 return;
140 switch (purple_roomlist_room_get_room_type(room)) {
141 case PURPLE_ROOMLIST_ROOMTYPE_ROOM:
142 purple_roomlist_room_join(froomlist.roomlist, room);
143 break;
144 case PURPLE_ROOMLIST_ROOMTYPE_CATEGORY:
145 if (!purple_roomlist_room_get_expanded_once(room)) {
146 purple_roomlist_expand_category(froomlist.roomlist, room);
147 purple_roomlist_room_set_expanded_once(room, TRUE);
149 break;
151 gnt_tree_set_expanded(GNT_TREE(widget), room, TRUE);
154 static void
155 roomlist_selection_changed(GntWidget *widget, gpointer old, gpointer current, gpointer null)
157 GList *iter, *field;
158 PurpleRoomlistRoom *room = current;
159 GntTextView *tv = GNT_TEXT_VIEW(froomlist.details);
160 gboolean first = TRUE;
162 gnt_text_view_clear(tv);
164 if (!room)
165 return;
167 for (iter = purple_roomlist_room_get_fields(room),
168 field = purple_roomlist_get_fields(froomlist.roomlist);
169 iter && field;
170 iter = iter->next, field = field->next) {
171 PurpleRoomlistField *f = field->data;
172 char *label = NULL;
174 if (purple_roomlist_field_get_hidden(f)) {
175 continue;
178 if (!first)
179 gnt_text_view_append_text_with_flags(tv, "\n", GNT_TEXT_FLAG_NORMAL);
181 gnt_text_view_append_text_with_flags(tv,
182 purple_roomlist_field_get_label(f), GNT_TEXT_FLAG_BOLD);
183 gnt_text_view_append_text_with_flags(tv, ": ", GNT_TEXT_FLAG_BOLD);
185 switch (purple_roomlist_field_get_field_type(f)) {
186 case PURPLE_ROOMLIST_FIELD_BOOL:
187 label = g_strdup(iter->data ? "True" : "False");
188 break;
189 case PURPLE_ROOMLIST_FIELD_INT:
190 label = g_strdup_printf("%d", GPOINTER_TO_INT(iter->data));
191 break;
192 case PURPLE_ROOMLIST_FIELD_STRING:
193 label = g_strdup(iter->data);
194 break;
196 gnt_text_view_append_text_with_flags(tv, label, GNT_TEXT_FLAG_NORMAL);
197 g_free(label);
198 first = FALSE;
201 if (purple_roomlist_room_get_room_type(room) == PURPLE_ROOMLIST_ROOMTYPE_CATEGORY) {
202 if (!first)
203 gnt_text_view_append_text_with_flags(tv, "\n", GNT_TEXT_FLAG_NORMAL);
204 gnt_text_view_append_text_with_flags(tv,
205 _("Hit 'Enter' to find more rooms of this category."),
206 GNT_TEXT_FLAG_NORMAL);
210 static void
211 roomlist_account_changed(GntWidget *widget, gpointer old, gpointer current, gpointer null)
213 if (froomlist.account == current) {
214 return;
217 froomlist.account = current;
218 if (froomlist.roomlist) {
219 if (purple_roomlist_get_in_progress(froomlist.roomlist))
220 purple_roomlist_cancel_get_list(froomlist.roomlist);
221 update_roomlist(NULL);
224 gnt_tree_remove_all(GNT_TREE(froomlist.tree));
225 gnt_widget_draw(froomlist.tree);
228 static void
229 reset_account_list(PurpleAccount *account)
231 GList *list;
232 GntComboBox *accounts = GNT_COMBO_BOX(froomlist.accounts);
233 gnt_combo_box_remove_all(accounts);
234 for (list = purple_connections_get_all(); list; list = list->next) {
235 PurpleProtocol *protocol = NULL;
236 PurpleConnection *gc = list->data;
238 protocol = purple_connection_get_protocol(gc);
239 if (PURPLE_CONNECTION_IS_CONNECTED(gc) &&
240 PURPLE_PROTOCOL_IMPLEMENTS(protocol, ROOMLIST_IFACE, get_list)) {
241 PurpleAccount *account = purple_connection_get_account(gc);
242 char *text = g_strdup_printf("%s (%s)",
243 purple_account_get_username(account),
244 purple_account_get_protocol_name(account));
245 gnt_combo_box_add_data(accounts, account, text);
246 g_free(text);
251 static void
252 size_changed_cb(GntWidget *widget, int oldw, int oldh)
254 int w, h;
255 gnt_widget_get_size(widget, &w, &h);
256 purple_prefs_set_int(PREF_ROOT "/size/width", w);
257 purple_prefs_set_int(PREF_ROOT "/size/height", h);
260 static void
261 setup_roomlist(PurpleAccount *account)
263 GntWidget *window, *tree, *hbox, *accounts;
264 int iter;
265 struct {
266 const char *label;
267 GCallback callback;
268 GntWidget **widget;
269 } buttons[] = {
270 {_("Stop"), G_CALLBACK(fl_stop), &froomlist.stop},
271 {_("Get"), G_CALLBACK(fl_get_list), &froomlist.getlist},
272 {_("Add"), G_CALLBACK(fl_add_chat), &froomlist.add},
273 {_("Close"), G_CALLBACK(fl_close), &froomlist.close},
274 {NULL, NULL, NULL}
277 if (froomlist.window)
278 return;
280 froomlist.window = window = gnt_window_new();
281 g_object_set(G_OBJECT(window), "vertical", TRUE, NULL);
282 gnt_box_set_pad(GNT_BOX(window), 0);
283 gnt_box_set_title(GNT_BOX(window), _("Room List"));
284 gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
286 froomlist.accounts = accounts = gnt_combo_box_new();
287 reset_account_list(account);
288 gnt_box_add_widget(GNT_BOX(window), accounts);
289 g_signal_connect(G_OBJECT(accounts), "selection-changed",
290 G_CALLBACK(roomlist_account_changed), NULL);
291 froomlist.account = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(accounts));
293 froomlist.tree = tree = gnt_tree_new_with_columns(2);
294 gnt_tree_set_show_title(GNT_TREE(tree), TRUE);
295 g_signal_connect(G_OBJECT(tree), "activate", G_CALLBACK(roomlist_activated), NULL);
296 gnt_tree_set_column_titles(GNT_TREE(tree), _("Name"), "");
297 gnt_tree_set_show_separator(GNT_TREE(tree), FALSE);
298 gnt_tree_set_col_width(GNT_TREE(tree), 1, 1);
299 gnt_tree_set_column_resizable(GNT_TREE(tree), 1, FALSE);
300 gnt_tree_set_search_column(GNT_TREE(tree), 0);
302 gnt_box_add_widget(GNT_BOX(window), tree);
304 froomlist.details = gnt_text_view_new();
305 gnt_text_view_set_flag(GNT_TEXT_VIEW(froomlist.details), GNT_TEXT_VIEW_TOP_ALIGN);
306 gnt_box_add_widget(GNT_BOX(window), froomlist.details);
307 gnt_widget_set_size(froomlist.details, -1, 8);
309 hbox = gnt_hbox_new(FALSE);
310 gnt_box_add_widget(GNT_BOX(window), hbox);
312 for (iter = 0; buttons[iter].label; iter++) {
313 GntWidget *button = gnt_button_new(buttons[iter].label);
314 gnt_box_add_widget(GNT_BOX(hbox), button);
315 g_signal_connect(G_OBJECT(button), "activate", buttons[iter].callback, NULL);
316 *buttons[iter].widget = button;
317 gnt_text_view_attach_scroll_widget(GNT_TEXT_VIEW(froomlist.details), button);
320 g_signal_connect(G_OBJECT(tree), "selection-changed", G_CALLBACK(roomlist_selection_changed), NULL);
322 g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(unset_roomlist), NULL);
325 static void
326 fl_show_with_account(PurpleAccount *account)
328 setup_roomlist(account);
329 g_signal_handlers_disconnect_matched(G_OBJECT(froomlist.window), G_SIGNAL_MATCH_FUNC,
330 0, 0, NULL, G_CALLBACK(size_changed_cb), NULL);
331 gnt_widget_show(froomlist.window);
332 gnt_screen_resize_widget(froomlist.window,
333 purple_prefs_get_int(PREF_ROOT "/size/width"),
334 purple_prefs_get_int(PREF_ROOT "/size/height"));
335 g_signal_connect(G_OBJECT(froomlist.window), "size_changed", G_CALLBACK(size_changed_cb), NULL);
336 gnt_window_present(froomlist.window);
339 static void
340 fl_create(PurpleRoomlist *list)
342 purple_roomlist_set_ui_data(list, &froomlist);
343 setup_roomlist(NULL);
344 update_roomlist(list);
347 static void
348 fl_set_fields(PurpleRoomlist *list, GList *fields)
352 static void
353 fl_add_room(PurpleRoomlist *roomlist, PurpleRoomlistRoom *room)
355 gboolean category;
356 if (froomlist.roomlist != roomlist)
357 return;
359 category = (purple_roomlist_room_get_room_type(room) == PURPLE_ROOMLIST_ROOMTYPE_CATEGORY);
360 gnt_tree_remove(GNT_TREE(froomlist.tree), room);
361 gnt_tree_add_row_after(GNT_TREE(froomlist.tree), room,
362 gnt_tree_create_row(GNT_TREE(froomlist.tree),
363 purple_roomlist_room_get_name(room),
364 category ? "<" : ""),
365 purple_roomlist_room_get_parent(room), NULL);
366 gnt_tree_set_expanded(GNT_TREE(froomlist.tree), room, !category);
369 static void
370 fl_destroy(PurpleRoomlist *list)
372 if (!froomlist.window)
373 return;
375 if (froomlist.roomlist == list) {
376 froomlist.roomlist = NULL;
377 gnt_tree_remove_all(GNT_TREE(froomlist.tree));
378 gnt_widget_draw(froomlist.tree);
382 static PurpleRoomlistUiOps ui_ops =
384 fl_show_with_account, /* void (*show_with_account)(PurpleAccount *account); **< Force the ui to pop up a dialog and get the list */
385 fl_create, /* void (*create)(PurpleRoomlist *list); **< A new list was created. */
386 fl_set_fields, /* void (*set_fields)(PurpleRoomlist *list, GList *fields); **< Sets the columns. */
387 fl_add_room, /* void (*add_room)(PurpleRoomlist *list, PurpleRoomlistRoom *room); **< Add a room to the list. */
388 NULL, /* void (*in_progress)(PurpleRoomlist *list, gboolean flag); **< Are we fetching stuff still? */
389 fl_destroy, /* void (*destroy)(PurpleRoomlist *list); **< We're destroying list. */
391 NULL, /* void (*_purple_reserved1)(void); */
392 NULL, /* void (*_purple_reserved2)(void); */
393 NULL, /* void (*_purple_reserved3)(void); */
394 NULL /* void (*_purple_reserved4)(void); */
397 PurpleRoomlistUiOps *finch_roomlist_get_ui_ops(void)
399 return &ui_ops;
402 void finch_roomlist_show_all(void)
404 purple_roomlist_show_with_account(NULL);
407 void finch_roomlist_init(void)
409 purple_prefs_add_none(PREF_ROOT);
410 purple_prefs_add_none(PREF_ROOT "/size");
411 purple_prefs_add_int(PREF_ROOT "/size/width", 60);
412 purple_prefs_add_int(PREF_ROOT "/size/height", 15);
415 void finch_roomlist_uninit(void)