Change XMPP http connection set to a SoupSession.
[pidgin-git.git] / finch / gntstatus.c
blob772cc2a7a29162d189968ffcdd0f7165235c05fb
1 /*
2 * finch
4 * Finch is the legal property of its developers, whose names are too numerous
5 * to list here. Please refer to the COPYRIGHT file distributed with this
6 * source distribution.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
23 #include <internal.h>
25 #include <gnt.h>
26 #include <gntbox.h>
27 #include <gntbutton.h>
28 #include <gntcombobox.h>
29 #include <gntentry.h>
30 #include <gntlabel.h>
31 #include <gntline.h>
32 #include <gnttree.h>
33 #include <gntutils.h>
35 #include "finch.h"
37 #include <notify.h>
38 #include <request.h>
40 #include "gntstatus.h"
42 static struct
44 GntWidget *window;
45 GntWidget *tree;
46 } statuses;
48 typedef struct
50 PurpleSavedStatus *saved;
51 GntWidget *window;
52 GntWidget *title;
53 GntWidget *type;
54 GntWidget *message;
55 GntWidget *tree;
56 GHashTable *hash; /* list of windows for substatuses */
57 } EditStatus;
59 typedef struct
61 PurpleAccount *account;
62 const PurpleStatusType *type;
63 char *message;
64 } RowInfo;
66 typedef struct
68 GntWidget *window;
69 GntWidget *type;
70 GntWidget *message;
72 EditStatus *parent;
73 RowInfo *key;
74 } EditSubStatus;
76 static GList *edits; /* List of opened edit-status dialogs */
78 static void
79 reset_status_window(GntWidget *widget, gpointer null)
81 statuses.window = NULL;
82 statuses.tree = NULL;
85 static void
86 populate_statuses(GntTree *tree)
88 GList *list;
90 for (list = purple_savedstatuses_get_all(); list; list = list->next)
92 PurpleSavedStatus *saved = list->data;
93 const char *title, *type, *message;
95 if (purple_savedstatus_is_transient(saved))
96 continue;
98 title = purple_savedstatus_get_title(saved);
99 type = purple_primitive_get_name_from_type(purple_savedstatus_get_primitive_type(saved));
100 message = purple_savedstatus_get_message(saved); /* XXX: Strip possible markups */
102 gnt_tree_add_row_last(tree, saved,
103 gnt_tree_create_row(tree, title, type, message), NULL);
107 static void
108 really_delete_status(PurpleSavedStatus *saved)
110 GList *iter;
112 for (iter = edits; iter; iter = iter->next)
114 EditStatus *edit = iter->data;
115 if (edit->saved == saved)
117 gnt_widget_destroy(edit->window);
118 break;
122 if (statuses.tree)
123 gnt_tree_remove(GNT_TREE(statuses.tree), saved);
125 purple_savedstatus_delete(purple_savedstatus_get_title(saved));
128 static void
129 ask_before_delete(GntWidget *button, gpointer null)
131 char *ask;
132 PurpleSavedStatus *saved;
134 g_return_if_fail(statuses.tree != NULL);
136 saved = gnt_tree_get_selection_data(GNT_TREE(statuses.tree));
137 ask = g_strdup_printf(_("Are you sure you want to delete \"%s\""),
138 purple_savedstatus_get_title(saved));
140 purple_request_action(saved, _("Delete Status"), ask, NULL, 0,
141 NULL, saved, 2,
142 _("Delete"), really_delete_status,
143 _("Cancel"), NULL);
144 g_free(ask);
147 static void
148 use_savedstatus_cb(GntWidget *widget, gpointer null)
150 g_return_if_fail(statuses.tree != NULL);
152 purple_savedstatus_activate(gnt_tree_get_selection_data(GNT_TREE(statuses.tree)));
155 static void
156 edit_savedstatus_cb(GntWidget *widget, gpointer null)
158 g_return_if_fail(statuses.tree != NULL);
160 finch_savedstatus_edit(gnt_tree_get_selection_data(GNT_TREE(statuses.tree)));
163 void finch_savedstatus_show_all()
165 GntWidget *window, *tree, *box, *button;
166 int widths[] = {25, 12, 35};
167 if (statuses.window) {
168 gnt_window_present(statuses.window);
169 return;
172 statuses.window = window = gnt_vbox_new(FALSE);
173 gnt_box_set_toplevel(GNT_BOX(window), TRUE);
174 gnt_box_set_title(GNT_BOX(window), _("Saved Statuses"));
175 gnt_box_set_fill(GNT_BOX(window), FALSE);
176 gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
177 gnt_box_set_pad(GNT_BOX(window), 0);
179 /* XXX: Add some sorting function to sort alphabetically, perhaps */
180 statuses.tree = tree = gnt_tree_new_with_columns(3);
181 gnt_tree_set_column_titles(GNT_TREE(tree), _("Title"), _("Type"), _("Message"));
182 gnt_tree_set_show_title(GNT_TREE(tree), TRUE);
183 gnt_tree_set_column_width_ratio(GNT_TREE(tree), widths);
184 gnt_widget_set_size(tree, 72, 0);
185 gnt_box_add_widget(GNT_BOX(window), tree);
187 populate_statuses(GNT_TREE(tree));
189 box = gnt_hbox_new(FALSE);
190 gnt_box_add_widget(GNT_BOX(window), box);
192 button = gnt_button_new(_("Use"));
193 gnt_box_add_widget(GNT_BOX(box), button);
194 g_signal_connect(G_OBJECT(button), "activate",
195 G_CALLBACK(use_savedstatus_cb), NULL);
197 button = gnt_button_new(_("Add"));
198 gnt_box_add_widget(GNT_BOX(box), button);
199 gnt_util_set_trigger_widget(tree, GNT_KEY_INS, button);
200 g_signal_connect_swapped(G_OBJECT(button), "activate",
201 G_CALLBACK(finch_savedstatus_edit), NULL);
203 button = gnt_button_new(_("Edit"));
204 gnt_box_add_widget(GNT_BOX(box), button);
205 g_signal_connect(G_OBJECT(button), "activate",
206 G_CALLBACK(edit_savedstatus_cb), NULL);
208 button = gnt_button_new(_("Delete"));
209 gnt_box_add_widget(GNT_BOX(box), button);
210 gnt_util_set_trigger_widget(tree, GNT_KEY_DEL, button);
211 g_signal_connect(G_OBJECT(button), "activate",
212 G_CALLBACK(ask_before_delete), NULL);
214 button = gnt_button_new(_("Close"));
215 gnt_box_add_widget(GNT_BOX(box), button);
216 g_signal_connect_swapped(G_OBJECT(button), "activate",
217 G_CALLBACK(gnt_widget_destroy), window);
219 g_signal_connect(G_OBJECT(window), "destroy",
220 G_CALLBACK(reset_status_window), NULL);
221 gnt_widget_show(window);
224 static void
225 destroy_substatus_win(PurpleAccount *account, EditSubStatus *sub, gpointer null)
227 gnt_widget_destroy(sub->window); /* the "destroy" callback will remove entry from the hashtable */
230 static void
231 free_key(gpointer key, gpointer n)
233 RowInfo *row = key;
234 g_free(row->message);
235 g_free(key);
239 static void
240 update_edit_list(GntWidget *widget, EditStatus *edit)
242 edits = g_list_remove(edits, edit);
243 purple_notify_close_with_handle(edit);
244 g_hash_table_foreach(edit->hash, (GHFunc)destroy_substatus_win, NULL);
245 g_list_foreach((GList*)gnt_tree_get_rows(GNT_TREE(edit->tree)), free_key, NULL);
246 g_free(edit);
249 static void
250 set_substatuses(EditStatus *edit)
252 GList *iter;
253 for (iter = gnt_tree_get_rows(GNT_TREE(edit->tree)); iter; iter = iter->next) {
254 RowInfo *key = iter->data;
255 if (gnt_tree_get_choice(GNT_TREE(edit->tree), key)) {
256 purple_savedstatus_set_substatus(edit->saved, key->account, key->type, key->message);
262 static void
263 use_trans_status_cb(GntWidget *button, EditStatus *edit)
265 const char *message;
266 PurpleStatusPrimitive prim;
267 PurpleSavedStatus *saved;
269 message = gnt_entry_get_text(GNT_ENTRY(edit->message));
270 prim = GPOINTER_TO_INT(gnt_combo_box_get_selected_data(GNT_COMBO_BOX(edit->type)));
272 saved = purple_savedstatus_find_transient_by_type_and_message(prim, message);
273 if (saved == NULL) {
274 saved = purple_savedstatus_new(NULL, prim);
275 edit->saved = saved;
276 set_substatuses(edit);
278 purple_savedstatus_set_message(saved, message);
279 purple_savedstatus_activate(saved);
280 gnt_widget_destroy(edit->window);
283 static void
284 save_savedstatus_cb(GntWidget *button, EditStatus *edit)
286 const char *title, *message;
287 PurpleStatusPrimitive prim;
288 PurpleSavedStatus *find;
290 title = gnt_entry_get_text(GNT_ENTRY(edit->title));
291 message = gnt_entry_get_text(GNT_ENTRY(edit->message));
292 if (!message || !*message)
293 message = NULL;
295 prim = GPOINTER_TO_INT(gnt_combo_box_get_selected_data(GNT_COMBO_BOX(edit->type)));
297 if (!title || !*title)
299 purple_notify_error(edit, _("Error"), _("Invalid title"),
300 _("Please enter a non-empty title for the status."), NULL);
301 gnt_box_give_focus_to_child(GNT_BOX(edit->window), edit->title);
302 return;
305 find = purple_savedstatus_find(title);
306 if (find && find != edit->saved)
308 purple_notify_error(edit, _("Error"), _("Duplicate title"),
309 _("Please enter a different title for the status."), NULL);
310 gnt_box_give_focus_to_child(GNT_BOX(edit->window), edit->title);
311 return;
314 if (edit->saved == NULL)
316 edit->saved = purple_savedstatus_new(title, prim);
317 purple_savedstatus_set_message(edit->saved, message);
318 set_substatuses(edit);
319 if (statuses.tree)
320 gnt_tree_add_row_last(GNT_TREE(statuses.tree), edit->saved,
321 gnt_tree_create_row(GNT_TREE(statuses.tree), title,
322 purple_primitive_get_name_from_type(prim), message), NULL);
324 else
326 purple_savedstatus_set_title(edit->saved, title);
327 purple_savedstatus_set_primitive_type(edit->saved, prim);
328 purple_savedstatus_set_message(edit->saved, message);
329 if (statuses.tree)
331 gnt_tree_change_text(GNT_TREE(statuses.tree), edit->saved, 0, title);
332 gnt_tree_change_text(GNT_TREE(statuses.tree), edit->saved, 1,
333 purple_primitive_get_name_from_type(prim));
334 gnt_tree_change_text(GNT_TREE(statuses.tree), edit->saved, 2, message);
338 if (g_object_get_data(G_OBJECT(button), "use"))
339 purple_savedstatus_activate(edit->saved);
341 gnt_widget_destroy(edit->window);
344 static void
345 add_substatus(EditStatus *edit, PurpleAccount *account)
347 char *name;
348 const char *type = NULL, *message = NULL;
349 PurpleSavedStatusSub *sub = NULL;
350 RowInfo *key;
352 if (!edit || !edit->tree)
353 return;
355 if (edit->saved)
356 sub = purple_savedstatus_get_substatus(edit->saved, account);
358 key = g_new0(RowInfo, 1);
359 key->account = account;
361 if (sub)
363 key->type = purple_savedstatus_substatus_get_status_type(sub);
364 type = purple_status_type_get_name(key->type);
365 message = purple_savedstatus_substatus_get_message(sub);
366 key->message = g_strdup(message);
369 name = g_strdup_printf("%s (%s)", purple_account_get_username(account),
370 purple_account_get_protocol_name(account));
371 gnt_tree_add_choice(GNT_TREE(edit->tree), key,
372 gnt_tree_create_row(GNT_TREE(edit->tree),
373 name, type ? type : "", message ? message : ""), NULL, NULL);
375 if (sub)
376 gnt_tree_set_choice(GNT_TREE(edit->tree), key, TRUE);
377 g_free(name);
380 static void
381 substatus_window_destroy_cb(GntWidget *window, EditSubStatus *sub)
383 g_hash_table_remove(sub->parent->hash, sub->key->account);
384 g_free(sub);
387 static void
388 save_substatus_cb(GntWidget *widget, EditSubStatus *sub)
390 PurpleSavedStatus *saved = sub->parent->saved;
391 RowInfo *row = sub->key;
392 const char *message;
393 PurpleStatusType *type;
395 type = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(sub->type));
396 message = gnt_entry_get_text(GNT_ENTRY(sub->message));
398 row->type = type;
399 row->message = g_strdup(message);
401 if (saved) /* Save the substatus if the savedstatus actually exists. */
402 purple_savedstatus_set_substatus(saved, row->account, type, message);
404 gnt_tree_set_choice(GNT_TREE(sub->parent->tree), row, TRUE);
405 gnt_tree_change_text(GNT_TREE(sub->parent->tree), row, 1,
406 purple_status_type_get_name(type));
407 gnt_tree_change_text(GNT_TREE(sub->parent->tree), row, 2, message);
409 gnt_widget_destroy(sub->window);
412 static gboolean
413 popup_substatus(GntTree *tree, const char *key, EditStatus *edit)
415 if (key[0] == ' ' && key[1] == 0)
417 EditSubStatus *sub;
418 GntWidget *window, *combo, *entry, *box, *button, *l;
419 PurpleSavedStatusSub *substatus = NULL;
420 GList *iter;
421 char *name;
422 RowInfo *selected = gnt_tree_get_selection_data(tree);
423 PurpleAccount *account = selected->account;
425 if (gnt_tree_get_choice(tree, selected))
427 /* There was a savedstatus for this account. Now remove it. */
428 g_free(selected->message);
429 selected->type = NULL;
430 selected->message = NULL;
431 /* XXX: should we really be saving it right now? */
432 purple_savedstatus_unset_substatus(edit->saved, account);
433 gnt_tree_change_text(tree, account, 1, NULL);
434 gnt_tree_change_text(tree, account, 2, NULL);
435 return FALSE;
438 if (g_hash_table_lookup(edit->hash, account))
439 return TRUE;
441 if (edit->saved)
442 substatus = purple_savedstatus_get_substatus(edit->saved, account);
444 sub = g_new0(EditSubStatus, 1);
445 sub->parent = edit;
446 sub->key = selected;
448 sub->window = window = gnt_vbox_new(FALSE);
449 gnt_box_set_toplevel(GNT_BOX(window), TRUE);
450 gnt_box_set_title(GNT_BOX(window), _("Substatus")); /* XXX: a better title */
451 gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
453 box = gnt_hbox_new(FALSE);
454 gnt_box_add_widget(GNT_BOX(box), gnt_label_new(_("Account:")));
455 name = g_strdup_printf("%s (%s)", purple_account_get_username(account),
456 purple_account_get_protocol_name(account));
457 gnt_box_add_widget(GNT_BOX(box), gnt_label_new(name));
458 g_free(name);
459 gnt_box_add_widget(GNT_BOX(window), box);
461 box = gnt_hbox_new(FALSE);
462 gnt_box_add_widget(GNT_BOX(box), (l = gnt_label_new(_("Status:"))));
463 gnt_widget_set_size(l, 0, 1); /* I don't like having to do this */
464 sub->type = combo = gnt_combo_box_new();
465 gnt_box_add_widget(GNT_BOX(box), combo);
466 gnt_box_add_widget(GNT_BOX(window), box);
468 for (iter = purple_account_get_status_types(account); iter; iter = iter->next)
470 PurpleStatusType *type = iter->data;
471 if (!purple_status_type_is_user_settable(type))
472 continue;
473 gnt_combo_box_add_data(GNT_COMBO_BOX(combo), type, purple_status_type_get_name(type));
476 box = gnt_hbox_new(FALSE);
477 gnt_box_add_widget(GNT_BOX(box), gnt_label_new(_("Message:")));
478 sub->message = entry = gnt_entry_new(substatus ? purple_savedstatus_substatus_get_message(substatus) : NULL);
479 gnt_box_add_widget(GNT_BOX(box), entry);
480 gnt_box_add_widget(GNT_BOX(window), box);
482 box = gnt_hbox_new(FALSE);
483 button = gnt_button_new(_("Cancel"));
484 g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gnt_widget_destroy), window);
485 gnt_box_add_widget(GNT_BOX(box), button);
486 button = gnt_button_new(_("Save"));
487 g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(save_substatus_cb), sub);
488 gnt_box_add_widget(GNT_BOX(box), button);
489 gnt_box_add_widget(GNT_BOX(window), box);
491 gnt_widget_show(window);
493 g_hash_table_insert(edit->hash, account, sub);
495 g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(substatus_window_destroy_cb), sub);
497 return TRUE;
499 return FALSE;
502 void finch_savedstatus_edit(PurpleSavedStatus *saved)
504 EditStatus *edit;
505 GntWidget *window, *box, *button, *entry, *combo, *label, *tree;
506 PurpleStatusPrimitive prims[] = {PURPLE_STATUS_AVAILABLE, PURPLE_STATUS_AWAY,
507 PURPLE_STATUS_INVISIBLE, PURPLE_STATUS_OFFLINE, PURPLE_STATUS_UNSET}, current;
508 GList *iter;
509 int i;
511 if (saved)
513 GList *iter;
514 for (iter = edits; iter; iter = iter->next)
516 edit = iter->data;
517 if (edit->saved == saved)
518 return;
522 edit = g_new0(EditStatus, 1);
523 edit->saved = saved;
524 edit->window = window = gnt_vbox_new(FALSE);
525 gnt_box_set_toplevel(GNT_BOX(window), TRUE);
526 gnt_box_set_title(GNT_BOX(window), _("Edit Status"));
527 gnt_box_set_fill(GNT_BOX(window), TRUE);
528 gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
529 gnt_box_set_pad(GNT_BOX(window), 0);
531 edits = g_list_append(edits, edit);
533 /* Title */
534 box = gnt_hbox_new(FALSE);
535 gnt_box_set_alignment(GNT_BOX(box), GNT_ALIGN_LEFT);
536 gnt_box_add_widget(GNT_BOX(window), box);
537 gnt_box_add_widget(GNT_BOX(box), gnt_label_new(_("Title")));
539 edit->title = entry = gnt_entry_new(saved ? purple_savedstatus_get_title(saved) : NULL);
540 gnt_box_add_widget(GNT_BOX(box), entry);
542 /* Type */
543 box = gnt_hbox_new(FALSE);
544 gnt_box_add_widget(GNT_BOX(window), box);
545 gnt_box_add_widget(GNT_BOX(box), label = gnt_label_new(_("Status")));
546 gnt_widget_set_size(label, 0, 1);
548 edit->type = combo = gnt_combo_box_new();
549 gnt_box_add_widget(GNT_BOX(box), combo);
550 current = saved ? purple_savedstatus_get_primitive_type(saved) : PURPLE_STATUS_UNSET;
551 for (i = 0; prims[i] != PURPLE_STATUS_UNSET; i++)
553 gnt_combo_box_add_data(GNT_COMBO_BOX(combo), GINT_TO_POINTER(prims[i]),
554 purple_primitive_get_name_from_type(prims[i]));
555 if (prims[i] == current)
556 gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), GINT_TO_POINTER(current));
559 /* Message */
560 box = gnt_hbox_new(FALSE);
561 gnt_box_add_widget(GNT_BOX(window), box);
562 gnt_box_add_widget(GNT_BOX(box), gnt_label_new(_("Message")));
564 edit->message = entry = gnt_entry_new(saved ? purple_savedstatus_get_message(saved) : NULL);
565 gnt_box_add_widget(GNT_BOX(window), entry);
567 gnt_box_add_widget(GNT_BOX(window), gnt_hline_new());
568 gnt_box_add_widget(GNT_BOX(window), gnt_label_new(_("Use a different status for some accounts")));
570 edit->hash = g_hash_table_new(g_direct_hash, g_direct_equal);
571 edit->tree = tree = gnt_tree_new_with_columns(3);
572 gnt_box_add_widget(GNT_BOX(window), tree);
573 gnt_tree_set_show_title(GNT_TREE(tree), TRUE);
574 gnt_tree_set_column_titles(GNT_TREE(tree), _("Account"), _("Status"), _("Message"));
575 gnt_tree_set_col_width(GNT_TREE(tree), 0, 30);
576 gnt_tree_set_col_width(GNT_TREE(tree), 1, 10);
577 gnt_tree_set_col_width(GNT_TREE(tree), 2, 30);
579 for (iter = purple_accounts_get_all(); iter; iter = iter->next)
581 add_substatus(edit, iter->data);
584 g_signal_connect(G_OBJECT(tree), "key_pressed", G_CALLBACK(popup_substatus), edit);
586 /* The buttons */
587 box = gnt_hbox_new(FALSE);
588 gnt_box_add_widget(GNT_BOX(window), box);
590 /* Use */
591 button = gnt_button_new(_("Use"));
592 gnt_box_add_widget(GNT_BOX(box), button);
593 g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(use_trans_status_cb), edit);
595 /* Save */
596 button = gnt_button_new(_("Save"));
597 gnt_box_add_widget(GNT_BOX(box), button);
598 g_object_set_data(G_OBJECT(button), "use", NULL);
599 g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(save_savedstatus_cb), edit);
601 /* Save and Use */
602 button = gnt_button_new(_("Save and Use"));
603 gnt_box_add_widget(GNT_BOX(box), button);
604 g_object_set_data(G_OBJECT(button), "use", GINT_TO_POINTER(TRUE));
605 g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(save_savedstatus_cb), edit);
607 /* Cancel */
608 button = gnt_button_new(_("Cancel"));
609 gnt_box_add_widget(GNT_BOX(box), button);
610 g_signal_connect_swapped(G_OBJECT(button), "activate",
611 G_CALLBACK(gnt_widget_destroy), window);
613 g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(update_edit_list), edit);
615 gnt_widget_show(window);