Mercurial > pidgin.yaz
comparison src/gtksavedstatuses.c @ 10420:854c972ea863
[gaim-migrate @ 11671]
The ability to add, modify and _save_ new statuses. This hopefully
brings our functionality slightly past where it is in oldstatus.
This could use a bit of testing, but I think it's pretty good.
We still can't edit substatuses.
Primitive types like "unset" should be hidden from the status selector
dropdown. "Online" and "offline" should maybe be hidden... but someone
in #gaim mentioned that it might be a good way to choose which accounts
are offline for a given status. Eh.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Sun, 26 Dec 2004 05:23:51 +0000 |
parents | c9b1f3fac753 |
children | ee56a3e54fbd |
comparison
equal
deleted
inserted
replaced
10419:c9b1f3fac753 | 10420:854c972ea863 |
---|---|
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
24 */ | 24 */ |
25 | 25 |
26 #include "account.h" | 26 #include "account.h" |
27 #include "internal.h" | 27 #include "internal.h" |
28 #include "notify.h" | |
28 #include "request.h" | 29 #include "request.h" |
29 #include "savedstatuses.h" | 30 #include "savedstatuses.h" |
30 #include "status.h" | 31 #include "status.h" |
31 #include "util.h" | 32 #include "util.h" |
32 | 33 |
48 }; | 49 }; |
49 | 50 |
50 enum | 51 enum |
51 { | 52 { |
52 STATUS_WINDOW_COLUMN_TITLE, | 53 STATUS_WINDOW_COLUMN_TITLE, |
54 STATUS_WINDOW_COLUMN_TYPE, | |
53 STATUS_WINDOW_COLUMN_MESSAGE, | 55 STATUS_WINDOW_COLUMN_MESSAGE, |
54 STATUS_WINDOW_NUM_COLUMNS | 56 STATUS_WINDOW_NUM_COLUMNS |
55 }; | 57 }; |
56 | 58 |
57 typedef struct | 59 typedef struct |
58 { | 60 { |
59 GtkWidget *window; | 61 GtkWidget *window; |
60 GtkListStore *model; | 62 GtkListStore *model; |
61 GtkWidget *treeview; | 63 GtkWidget *treeview; |
64 GtkWidget *save_button; | |
65 | |
66 gchar *original_title; | |
67 GtkEntry *title; | |
68 GtkOptionMenu *type; | |
69 GtkIMHtml *message; | |
62 } StatusEditor; | 70 } StatusEditor; |
63 | 71 |
64 typedef struct | 72 typedef struct |
65 { | 73 { |
66 GtkWidget *window; | 74 GtkWidget *window; |
70 GtkWidget *delete_button; | 78 GtkWidget *delete_button; |
71 } StatusWindow; | 79 } StatusWindow; |
72 | 80 |
73 static StatusWindow *status_window = NULL; | 81 static StatusWindow *status_window = NULL; |
74 | 82 |
83 static void add_status_to_saved_status_list(GtkListStore *model, GaimSavedStatus *saved_status); | |
84 static gboolean status_window_find_savedstatus(GtkTreeIter *iter, const char *title); | |
85 | |
75 static gboolean | 86 static gboolean |
76 status_editor_destroy_cb(GtkWidget *widget, GdkEvent *event, gpointer user_data) | 87 status_editor_destroy_cb(GtkWidget *widget, GdkEvent *event, gpointer user_data) |
77 { | 88 { |
78 StatusWindow *dialog = user_data; | 89 StatusWindow *dialog = user_data; |
79 | 90 |
93 } | 104 } |
94 | 105 |
95 static void | 106 static void |
96 status_editor_save_cb(GtkButton *button, gpointer user_data) | 107 status_editor_save_cb(GtkButton *button, gpointer user_data) |
97 { | 108 { |
98 /* TODO: Save the status */ | 109 StatusEditor *dialog = user_data; |
110 const char *title; | |
111 GaimStatusPrimitive type; | |
112 char *message, *unformatted; | |
113 GaimSavedStatus *status; | |
114 | |
115 title = gtk_entry_get_text(dialog->title); | |
116 | |
117 /* | |
118 * If the title is already taken then show an error dialog and | |
119 * don't do anything. | |
120 */ | |
121 if ((gaim_savedstatus_find(title) != NULL) && | |
122 ((dialog->original_title == NULL) || (strcmp(title, dialog->original_title)))) | |
123 { | |
124 gaim_notify_error(NULL, NULL, _("Title already in use. You must " | |
125 "choose a unique title."), NULL); | |
126 return; | |
127 } | |
128 | |
129 type = gtk_option_menu_get_history(dialog->type); | |
130 message = gtk_imhtml_get_markup(dialog->message); | |
131 unformatted = gaim_markup_strip_html(message); | |
132 | |
133 /* | |
134 * If we're editing an existing status, remove the old one to | |
135 * make way for the modified one. | |
136 */ | |
137 if (dialog->original_title != NULL) | |
138 { | |
139 GtkTreeIter iter; | |
140 | |
141 gaim_savedstatus_delete(dialog->original_title); | |
142 | |
143 if (status_window_find_savedstatus(&iter, dialog->original_title)) | |
144 { | |
145 gtk_list_store_remove(status_window->model, &iter); | |
146 } | |
147 | |
148 g_free(dialog->original_title); | |
149 } | |
150 | |
151 status = gaim_savedstatus_new(title, type); | |
152 if (*unformatted != '\0') | |
153 gaim_savedstatus_set_message(status, message); | |
154 g_free(message); | |
155 g_free(unformatted); | |
156 | |
157 gtk_widget_destroy(dialog->window); | |
158 g_free(dialog); | |
159 | |
160 add_status_to_saved_status_list(status_window->model, status); | |
161 } | |
162 | |
163 static void | |
164 status_editor_custom_status_cb(GtkCellRendererToggle *renderer, gchar *path_str, gpointer data) | |
165 { | |
166 /* StatusEditor *dialog = (StatusEditor *)data; */ | |
167 | |
168 /* TODO: Need to allow user to set a custom status for the highlighted account, somehow */ | |
169 } | |
170 | |
171 static void | |
172 editor_title_changed_cb(GtkWidget *widget, gpointer user_data) | |
173 { | |
174 StatusEditor *dialog = user_data; | |
175 const gchar *text; | |
176 | |
177 text = gtk_entry_get_text(dialog->title); | |
178 | |
179 gtk_widget_set_sensitive(dialog->save_button, (*text != '\0')); | |
99 } | 180 } |
100 | 181 |
101 static GtkWidget * | 182 static GtkWidget * |
102 create_status_type_menu(GaimStatusPrimitive type) | 183 create_status_type_menu(GaimStatusPrimitive type) |
103 { | 184 { |
119 gtk_menu_set_active(GTK_MENU(menu), type); | 200 gtk_menu_set_active(GTK_MENU(menu), type); |
120 gtk_option_menu_set_menu(GTK_OPTION_MENU(dropdown), menu); | 201 gtk_option_menu_set_menu(GTK_OPTION_MENU(dropdown), menu); |
121 gtk_widget_show(menu); | 202 gtk_widget_show(menu); |
122 | 203 |
123 return dropdown; | 204 return dropdown; |
124 } | |
125 | |
126 static void | |
127 status_editor_custom_status_cb(GtkCellRendererToggle *renderer, gchar *path_str, gpointer data) | |
128 { | |
129 /* StatusEditor *dialog = (StatusEditor *)data; */ | |
130 | |
131 /* TODO: Need to allow user to set a custom status for the highlighted account, somehow */ | |
132 } | 205 } |
133 | 206 |
134 static void | 207 static void |
135 status_editor_add_columns(StatusEditor *dialog) | 208 status_editor_add_columns(StatusEditor *dialog) |
136 { | 209 { |
237 GtkWidget *vbox; | 310 GtkWidget *vbox; |
238 GtkWidget *win; | 311 GtkWidget *win; |
239 | 312 |
240 dialog = g_new0(StatusEditor, 1); | 313 dialog = g_new0(StatusEditor, 1); |
241 | 314 |
315 if (status != NULL) | |
316 dialog->original_title = g_strdup(gaim_savedstatus_get_title(status)); | |
317 | |
242 dialog->window = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); | 318 dialog->window = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); |
243 gtk_window_set_role(GTK_WINDOW(win), "status"); | 319 gtk_window_set_role(GTK_WINDOW(win), "status"); |
244 gtk_window_set_title(GTK_WINDOW(win), _("Status")); | 320 gtk_window_set_title(GTK_WINDOW(win), _("Status")); |
245 gtk_window_set_resizable(GTK_WINDOW(win), FALSE); | 321 gtk_window_set_resizable(GTK_WINDOW(win), FALSE); |
246 gtk_container_set_border_width(GTK_CONTAINER(win), 12); | 322 gtk_container_set_border_width(GTK_CONTAINER(win), 12); |
265 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); | 341 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); |
266 gtk_widget_show(label); | 342 gtk_widget_show(label); |
267 gtk_size_group_add_widget(sg, label); | 343 gtk_size_group_add_widget(sg, label); |
268 | 344 |
269 entry = gtk_entry_new(); | 345 entry = gtk_entry_new(); |
346 dialog->title = GTK_ENTRY(entry); | |
270 if (status != NULL) | 347 if (status != NULL) |
271 gtk_entry_set_text(GTK_ENTRY(entry), gaim_savedstatus_get_title(status)); | 348 gtk_entry_set_text(GTK_ENTRY(entry), dialog->original_title); |
272 else | 349 else |
273 gtk_entry_set_text(GTK_ENTRY(entry), _("Out of the office")); | 350 gtk_entry_set_text(GTK_ENTRY(entry), _("Out of the office")); |
274 gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0); | 351 gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0); |
275 gtk_widget_show(entry); | 352 gtk_widget_show(entry); |
353 g_signal_connect(G_OBJECT(entry), "changed", | |
354 G_CALLBACK(editor_title_changed_cb), dialog); | |
276 | 355 |
277 /* Status type */ | 356 /* Status type */ |
278 hbox = gtk_hbox_new(FALSE, 6); | 357 hbox = gtk_hbox_new(FALSE, 6); |
279 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); | 358 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); |
280 gtk_widget_show(hbox); | 359 gtk_widget_show(hbox); |
287 | 366 |
288 if (status != NULL) | 367 if (status != NULL) |
289 dropdown = create_status_type_menu(gaim_savedstatus_get_type(status)); | 368 dropdown = create_status_type_menu(gaim_savedstatus_get_type(status)); |
290 else | 369 else |
291 dropdown = create_status_type_menu(GAIM_STATUS_AWAY); | 370 dropdown = create_status_type_menu(GAIM_STATUS_AWAY); |
371 dialog->type = GTK_OPTION_MENU(dropdown); | |
292 gtk_box_pack_start(GTK_BOX(hbox), dropdown, TRUE, TRUE, 0); | 372 gtk_box_pack_start(GTK_BOX(hbox), dropdown, TRUE, TRUE, 0); |
293 gtk_widget_show(dropdown); | 373 gtk_widget_show(dropdown); |
294 | 374 |
295 /* Status message */ | 375 /* Status message */ |
296 hbox = gtk_hbox_new(FALSE, 6); | 376 hbox = gtk_hbox_new(FALSE, 6); |
302 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); | 382 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); |
303 gtk_widget_show(label); | 383 gtk_widget_show(label); |
304 gtk_size_group_add_widget(sg, label); | 384 gtk_size_group_add_widget(sg, label); |
305 | 385 |
306 frame = gaim_gtk_create_imhtml(TRUE, &text, &toolbar); | 386 frame = gaim_gtk_create_imhtml(TRUE, &text, &toolbar); |
387 dialog->message = GTK_IMHTML(text); | |
307 gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0); | 388 gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0); |
308 gtk_widget_show(frame); | 389 gtk_widget_show(frame); |
309 | 390 |
310 if (status != NULL) | 391 if (status != NULL) |
311 gtk_imhtml_append_text(GTK_IMHTML(text), | 392 gtk_imhtml_append_text(GTK_IMHTML(text), |
368 | 449 |
369 g_signal_connect(G_OBJECT(button), "clicked", | 450 g_signal_connect(G_OBJECT(button), "clicked", |
370 G_CALLBACK(status_editor_cancel_cb), dialog); | 451 G_CALLBACK(status_editor_cancel_cb), dialog); |
371 | 452 |
372 /* Save button */ | 453 /* Save button */ |
373 /* TODO: This button needs to be made sensitive when the title box contains text */ | |
374 button = gtk_button_new_from_stock(GTK_STOCK_SAVE); | 454 button = gtk_button_new_from_stock(GTK_STOCK_SAVE); |
455 dialog->save_button = button; | |
375 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); | 456 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); |
376 gtk_widget_set_sensitive(button, FALSE); | |
377 gtk_widget_show(button); | 457 gtk_widget_show(button); |
378 | 458 |
379 g_signal_connect(G_OBJECT(button), "clicked", | 459 g_signal_connect(G_OBJECT(button), "clicked", |
380 G_CALLBACK(status_editor_save_cb), dialog); | 460 G_CALLBACK(status_editor_save_cb), dialog); |
381 | 461 |
507 gtk_widget_set_sensitive(dialog->modify_button, selected); | 587 gtk_widget_set_sensitive(dialog->modify_button, selected); |
508 gtk_widget_set_sensitive(dialog->delete_button, selected); | 588 gtk_widget_set_sensitive(dialog->delete_button, selected); |
509 } | 589 } |
510 | 590 |
511 static void | 591 static void |
592 add_status_to_saved_status_list(GtkListStore *model, GaimSavedStatus *saved_status) | |
593 { | |
594 GtkTreeIter iter; | |
595 const char *title; | |
596 const char *type; | |
597 char *message; | |
598 | |
599 title = gaim_savedstatus_get_title(saved_status); | |
600 type = gaim_primitive_get_name_from_type(gaim_savedstatus_get_type(saved_status)); | |
601 message = gaim_markup_strip_html(gaim_savedstatus_get_message(saved_status)); | |
602 if (strlen(message) > 70) | |
603 strcpy(&message[68], "..."); | |
604 | |
605 gtk_list_store_append(model, &iter); | |
606 gtk_list_store_set(model, &iter, | |
607 STATUS_WINDOW_COLUMN_TITLE, title, | |
608 STATUS_WINDOW_COLUMN_TYPE, type, | |
609 STATUS_WINDOW_COLUMN_MESSAGE, message, | |
610 -1); | |
611 free(message); | |
612 } | |
613 | |
614 static void | |
512 populate_saved_status_list(StatusWindow *dialog) | 615 populate_saved_status_list(StatusWindow *dialog) |
513 { | 616 { |
514 GtkTreeIter iter; | |
515 const GList *saved_statuses; | 617 const GList *saved_statuses; |
516 GaimSavedStatus *saved_status; | |
517 char *message; | |
518 | 618 |
519 gtk_list_store_clear(dialog->model); | 619 gtk_list_store_clear(dialog->model); |
520 | 620 |
521 for (saved_statuses = gaim_savedstatuses_get_all(); saved_statuses != NULL; | 621 for (saved_statuses = gaim_savedstatuses_get_all(); saved_statuses != NULL; |
522 saved_statuses = g_list_next(saved_statuses)) | 622 saved_statuses = g_list_next(saved_statuses)) |
523 { | 623 { |
524 saved_status = (GaimSavedStatus *)saved_statuses->data; | 624 add_status_to_saved_status_list(dialog->model, saved_statuses->data); |
525 message = gaim_markup_strip_html(gaim_savedstatus_get_message(saved_status)); | |
526 if (strlen(message) > 70) | |
527 strcpy(&message[68], "..."); | |
528 | |
529 gtk_list_store_append(dialog->model, &iter); | |
530 gtk_list_store_set(dialog->model, &iter, | |
531 STATUS_WINDOW_COLUMN_TITLE, gaim_savedstatus_get_title(saved_status), | |
532 STATUS_WINDOW_COLUMN_MESSAGE, message, | |
533 -1); | |
534 free(message); | |
535 } | 625 } |
536 } | 626 } |
537 | 627 |
538 static GtkWidget * | 628 static GtkWidget * |
539 create_saved_status_list(StatusWindow *dialog) | 629 create_saved_status_list(StatusWindow *dialog) |
553 GTK_SHADOW_IN); | 643 GTK_SHADOW_IN); |
554 gtk_widget_show(sw); | 644 gtk_widget_show(sw); |
555 | 645 |
556 /* Create the list model */ | 646 /* Create the list model */ |
557 dialog->model = gtk_list_store_new(STATUS_WINDOW_NUM_COLUMNS, | 647 dialog->model = gtk_list_store_new(STATUS_WINDOW_NUM_COLUMNS, |
648 G_TYPE_STRING, | |
558 G_TYPE_STRING, | 649 G_TYPE_STRING, |
559 G_TYPE_STRING); | 650 G_TYPE_STRING); |
560 | 651 |
561 /* Create the treeview */ | 652 /* Create the treeview */ |
562 treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(dialog->model)); | 653 treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(dialog->model)); |
583 gtk_tree_view_column_pack_start(column, renderer, TRUE); | 674 gtk_tree_view_column_pack_start(column, renderer, TRUE); |
584 gtk_tree_view_column_add_attribute(column, renderer, "text", | 675 gtk_tree_view_column_add_attribute(column, renderer, "text", |
585 STATUS_WINDOW_COLUMN_TITLE); | 676 STATUS_WINDOW_COLUMN_TITLE); |
586 | 677 |
587 column = gtk_tree_view_column_new(); | 678 column = gtk_tree_view_column_new(); |
679 gtk_tree_view_column_set_title(column, _("Type")); | |
680 gtk_tree_view_column_set_resizable(column, TRUE); | |
681 gtk_tree_view_column_set_sort_column_id(column, | |
682 STATUS_WINDOW_COLUMN_TYPE); | |
683 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); | |
684 renderer = gtk_cell_renderer_text_new(); | |
685 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
686 gtk_tree_view_column_add_attribute(column, renderer, "text", | |
687 STATUS_WINDOW_COLUMN_TYPE); | |
688 | |
689 column = gtk_tree_view_column_new(); | |
588 gtk_tree_view_column_set_title(column, _("Message")); | 690 gtk_tree_view_column_set_title(column, _("Message")); |
589 gtk_tree_view_column_set_resizable(column, TRUE); | 691 gtk_tree_view_column_set_resizable(column, TRUE); |
590 gtk_tree_view_column_set_sort_column_id(column, | 692 gtk_tree_view_column_set_sort_column_id(column, |
591 STATUS_WINDOW_COLUMN_MESSAGE); | 693 STATUS_WINDOW_COLUMN_MESSAGE); |
592 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); | 694 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); |