Mercurial > pidgin
comparison src/gtksavedstatuses.c @ 10418:bed2c96bc1fb
[gaim-migrate @ 11669]
I split the status-saving code into it's own little API, because it
really is separate from the other status.c
savedstatuses.c sits on top of the rest of the status API.
And you can delete saved statuses now.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Sun, 26 Dec 2004 00:46:26 +0000 |
parents | |
children | c9b1f3fac753 |
comparison
equal
deleted
inserted
replaced
10417:823ad21cd95a | 10418:bed2c96bc1fb |
---|---|
1 /** | |
2 * @file gtksavedstatus.c GTK+ Saved Status Editor UI | |
3 * @ingroup gtkui | |
4 * | |
5 * gaim | |
6 * | |
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. | |
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 "account.h" | |
27 #include "internal.h" | |
28 #include "request.h" | |
29 #include "savedstatuses.h" | |
30 #include "status.h" | |
31 #include "util.h" | |
32 | |
33 #include "gtkblist.h" | |
34 #include "gtkgaim.h" | |
35 #include "gtkgaim-disclosure.h" | |
36 #include "gtkimhtml.h" | |
37 #include "gtkimhtmltoolbar.h" | |
38 #include "gtksavedstatuses.h" | |
39 #include "gtkstock.h" | |
40 #include "gtkutils.h" | |
41 | |
42 enum | |
43 { | |
44 STATUS_EDITOR_COLUMN_CUSTOM_STATUS, | |
45 STATUS_EDITOR_COLUMN_ICON, | |
46 STATUS_EDITOR_COLUMN_SCREENNAME, | |
47 STATUS_EDITOR_NUM_COLUMNS | |
48 }; | |
49 | |
50 enum | |
51 { | |
52 STATUS_WINDOW_COLUMN_TITLE, | |
53 STATUS_WINDOW_COLUMN_MESSAGE, | |
54 STATUS_WINDOW_NUM_COLUMNS | |
55 }; | |
56 | |
57 typedef struct | |
58 { | |
59 GtkWidget *window; | |
60 GtkListStore *model; | |
61 GtkWidget *treeview; | |
62 } StatusEditor; | |
63 | |
64 typedef struct | |
65 { | |
66 GtkWidget *window; | |
67 GtkListStore *model; | |
68 GtkWidget *treeview; | |
69 GtkWidget *modify_button; | |
70 GtkWidget *delete_button; | |
71 } StatusWindow; | |
72 | |
73 static StatusWindow *status_window = NULL; | |
74 | |
75 static gboolean | |
76 status_editor_destroy_cb(GtkWidget *widget, GdkEvent *event, gpointer user_data) | |
77 { | |
78 StatusWindow *dialog = user_data; | |
79 | |
80 g_free(dialog); | |
81 | |
82 return FALSE; | |
83 } | |
84 | |
85 static void | |
86 status_editor_cancel_cb(GtkButton *button, gpointer user_data) | |
87 { | |
88 StatusWindow *dialog = user_data; | |
89 | |
90 gtk_widget_destroy(dialog->window); | |
91 | |
92 g_free(dialog); | |
93 } | |
94 | |
95 static void | |
96 status_editor_save_cb(GtkButton *button, gpointer user_data) | |
97 { | |
98 /* TODO: Save the status */ | |
99 } | |
100 | |
101 /* TODO: Can this menu be created more automatically? */ | |
102 static GtkWidget * | |
103 create_status_type_menu() | |
104 { | |
105 GtkWidget *dropdown; | |
106 GtkWidget *menu; | |
107 GtkWidget *item; | |
108 | |
109 dropdown = gtk_option_menu_new(); | |
110 menu = gtk_menu_new(); | |
111 | |
112 /* GAIM_STATUS_AVAILABLE */ | |
113 item = gtk_menu_item_new_with_label(_("Available")); | |
114 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); | |
115 gtk_widget_show(item); | |
116 | |
117 /* GAIM_STATUS_UNAVAILABLE */ | |
118 item = gtk_menu_item_new_with_label(_("Unavailable")); | |
119 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); | |
120 gtk_widget_show(item); | |
121 | |
122 /* GAIM_STATUS_HIDDEN */ | |
123 item = gtk_menu_item_new_with_label(_("Hidden")); | |
124 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); | |
125 gtk_widget_show(item); | |
126 | |
127 /* GAIM_STATUS_AWAY */ | |
128 item = gtk_menu_item_new_with_label(_("Away")); | |
129 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); | |
130 gtk_widget_show(item); | |
131 | |
132 /* GAIM_STATUS_EXTENDED_AWAY */ | |
133 item = gtk_menu_item_new_with_label(_("Extended Away")); | |
134 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); | |
135 gtk_widget_show(item); | |
136 | |
137 gtk_option_menu_set_menu(GTK_OPTION_MENU(dropdown), menu); | |
138 gtk_widget_show(menu); | |
139 | |
140 return dropdown; | |
141 } | |
142 | |
143 static void | |
144 status_editor_custom_status_cb(GtkCellRendererToggle *renderer, gchar *path_str, gpointer data) | |
145 { | |
146 /* StatusEditor *dialog = (StatusEditor *)data; */ | |
147 | |
148 /* TODO: Need to allow user to set a custom status for the highlighted account, somehow */ | |
149 } | |
150 | |
151 static void | |
152 status_editor_add_columns(StatusEditor *dialog) | |
153 { | |
154 GtkCellRenderer *renderer; | |
155 GtkTreeViewColumn *column; | |
156 | |
157 /* Custom status column */ | |
158 renderer = gtk_cell_renderer_toggle_new(); | |
159 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(dialog->treeview), | |
160 -1, _("Custom status"), | |
161 renderer, | |
162 "active", STATUS_EDITOR_COLUMN_CUSTOM_STATUS, | |
163 NULL); | |
164 column = gtk_tree_view_get_column(GTK_TREE_VIEW(dialog->treeview), 1); | |
165 g_signal_connect(G_OBJECT(renderer), "toggled", | |
166 G_CALLBACK(status_editor_custom_status_cb), dialog); | |
167 | |
168 /* Screen Name column */ | |
169 column = gtk_tree_view_column_new(); | |
170 gtk_tree_view_column_set_resizable(column, TRUE); | |
171 gtk_tree_view_column_set_title(column, _("Screen Name")); | |
172 gtk_tree_view_insert_column(GTK_TREE_VIEW(dialog->treeview), column, -1); | |
173 gtk_tree_view_column_set_resizable(column, TRUE); | |
174 | |
175 /* Icon */ | |
176 renderer = gtk_cell_renderer_pixbuf_new(); | |
177 gtk_tree_view_column_pack_start(column, renderer, FALSE); | |
178 gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", | |
179 STATUS_EDITOR_COLUMN_ICON); | |
180 | |
181 /* Screen Name */ | |
182 renderer = gtk_cell_renderer_text_new(); | |
183 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
184 gtk_tree_view_column_add_attribute(column, renderer, "text", | |
185 STATUS_EDITOR_COLUMN_SCREENNAME); | |
186 } | |
187 | |
188 static void | |
189 status_editor_set_account(GtkListStore *store, GaimAccount *account, GtkTreeIter *iter) | |
190 { | |
191 GdkPixbuf *pixbuf; | |
192 GdkPixbuf *scale; | |
193 | |
194 scale = NULL; | |
195 | |
196 pixbuf = create_prpl_icon(account); | |
197 | |
198 if (pixbuf != NULL) | |
199 { | |
200 scale = gdk_pixbuf_scale_simple(pixbuf, 16, 16, GDK_INTERP_BILINEAR); | |
201 | |
202 if (!gaim_account_is_connected(account)) | |
203 gdk_pixbuf_saturate_and_pixelate(scale, scale, 0.0, FALSE); | |
204 } | |
205 | |
206 gtk_list_store_set(store, iter, | |
207 STATUS_EDITOR_COLUMN_ICON, scale, | |
208 STATUS_EDITOR_COLUMN_SCREENNAME, gaim_account_get_username(account), | |
209 -1); | |
210 | |
211 if (pixbuf != NULL) g_object_unref(G_OBJECT(pixbuf)); | |
212 if (scale != NULL) g_object_unref(G_OBJECT(scale)); | |
213 } | |
214 | |
215 static void | |
216 status_editor_add_account(StatusEditor *dialog, GaimAccount *account) | |
217 { | |
218 GtkTreeIter iter; | |
219 | |
220 gtk_list_store_append(dialog->model, &iter); | |
221 | |
222 status_editor_set_account(dialog->model, account, &iter); | |
223 } | |
224 | |
225 static void | |
226 status_editor_populate_list(StatusEditor *dialog) | |
227 { | |
228 GList *l; | |
229 | |
230 gtk_list_store_clear(dialog->model); | |
231 | |
232 for (l = gaim_accounts_get_all(); l != NULL; l = l->next) | |
233 status_editor_add_account(dialog, (GaimAccount *)l->data); | |
234 } | |
235 | |
236 void | |
237 gaim_gtk_status_editor_show(void) | |
238 { | |
239 StatusEditor *dialog; | |
240 GtkSizeGroup *sg; | |
241 GtkWidget *bbox; | |
242 GtkWidget *button; | |
243 GtkWidget *dbox; | |
244 GtkWidget *disclosure; | |
245 GtkWidget *dropdown; | |
246 GtkWidget *entry; | |
247 GtkWidget *frame; | |
248 GtkWidget *hbox; | |
249 GtkWidget *label; | |
250 GtkWidget *sep; | |
251 GtkWidget *sw; | |
252 GtkWidget *text; | |
253 GtkWidget *toolbar; | |
254 GtkWidget *vbox; | |
255 GtkWidget *win; | |
256 | |
257 dialog = g_new0(StatusEditor, 1); | |
258 | |
259 dialog->window = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); | |
260 gtk_window_set_role(GTK_WINDOW(win), "status"); | |
261 gtk_window_set_title(GTK_WINDOW(win), _("Status")); | |
262 gtk_window_set_resizable(GTK_WINDOW(win), FALSE); | |
263 gtk_container_set_border_width(GTK_CONTAINER(win), 12); | |
264 | |
265 g_signal_connect(G_OBJECT(win), "delete_event", | |
266 G_CALLBACK(status_editor_destroy_cb), dialog); | |
267 | |
268 /* Setup the vbox */ | |
269 vbox = gtk_vbox_new(FALSE, 12); | |
270 gtk_container_add(GTK_CONTAINER(win), vbox); | |
271 gtk_widget_show(vbox); | |
272 | |
273 sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); | |
274 | |
275 /* Title */ | |
276 hbox = gtk_hbox_new(FALSE, 6); | |
277 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); | |
278 gtk_widget_show(hbox); | |
279 | |
280 label = gtk_label_new_with_mnemonic(_("_Title:")); | |
281 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
282 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); | |
283 gtk_widget_show(label); | |
284 gtk_size_group_add_widget(sg, label); | |
285 | |
286 entry = gtk_entry_new(); | |
287 gtk_entry_set_text(GTK_ENTRY(entry), _("Out of the office")); | |
288 gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0); | |
289 gtk_widget_show(entry); | |
290 | |
291 /* Status type */ | |
292 hbox = gtk_hbox_new(FALSE, 6); | |
293 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); | |
294 gtk_widget_show(hbox); | |
295 | |
296 label = gtk_label_new_with_mnemonic(_("_Status:")); | |
297 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
298 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); | |
299 gtk_widget_show(label); | |
300 gtk_size_group_add_widget(sg, label); | |
301 | |
302 dropdown = create_status_type_menu(); | |
303 gtk_box_pack_start(GTK_BOX(hbox), dropdown, TRUE, TRUE, 0); | |
304 gtk_widget_show(dropdown); | |
305 | |
306 /* Status message */ | |
307 hbox = gtk_hbox_new(FALSE, 6); | |
308 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); | |
309 gtk_widget_show(hbox); | |
310 | |
311 label = gtk_label_new_with_mnemonic(_("_Message:")); | |
312 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
313 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); | |
314 gtk_widget_show(label); | |
315 gtk_size_group_add_widget(sg, label); | |
316 | |
317 frame = gaim_gtk_create_imhtml(TRUE, &text, &toolbar); | |
318 gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0); | |
319 gtk_widget_show(frame); | |
320 | |
321 /* Custom status message disclosure */ | |
322 disclosure = gaim_disclosure_new(_("Use a different status for some accounts"), | |
323 _("Use a different status for some accounts")); | |
324 gtk_box_pack_start(GTK_BOX(vbox), disclosure, FALSE, FALSE, 0); | |
325 gtk_widget_show(disclosure); | |
326 | |
327 /* Setup the box that the disclosure will cover */ | |
328 dbox = gtk_vbox_new(FALSE, 18); | |
329 gtk_box_pack_start(GTK_BOX(vbox), dbox, FALSE, FALSE, 0); | |
330 gaim_disclosure_set_container(GAIM_DISCLOSURE(disclosure), dbox); | |
331 | |
332 /* Custom status message treeview */ | |
333 sw = gtk_scrolled_window_new(NULL, NULL); | |
334 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), | |
335 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); | |
336 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), | |
337 GTK_SHADOW_IN); | |
338 gtk_box_pack_start(GTK_BOX(dbox), sw, TRUE, TRUE, 0); | |
339 gtk_widget_show(sw); | |
340 | |
341 /* Create the list model */ | |
342 dialog->model = gtk_list_store_new(STATUS_EDITOR_NUM_COLUMNS, | |
343 G_TYPE_BOOLEAN, | |
344 GDK_TYPE_PIXBUF, G_TYPE_STRING); | |
345 | |
346 /* Create the treeview */ | |
347 dialog->treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(dialog->model)); | |
348 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(dialog->treeview), TRUE); | |
349 gtk_widget_set_size_request(dialog->treeview, 400, 250); | |
350 gtk_container_add(GTK_CONTAINER(sw), dialog->treeview); | |
351 gtk_widget_show(dialog->treeview); | |
352 | |
353 /* Add columns */ | |
354 status_editor_add_columns(dialog); | |
355 | |
356 /* Populate list */ | |
357 status_editor_populate_list(dialog); | |
358 | |
359 /* Separator */ | |
360 sep = gtk_hseparator_new(); | |
361 gtk_box_pack_start(GTK_BOX(vbox), sep, FALSE, FALSE, 0); | |
362 gtk_widget_show(sep); | |
363 | |
364 /* Button box */ | |
365 bbox = gtk_hbutton_box_new(); | |
366 gtk_box_set_spacing(GTK_BOX(bbox), 6); | |
367 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); | |
368 gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, TRUE, 0); | |
369 gtk_widget_show(bbox); | |
370 | |
371 /* Cancel button */ | |
372 button = gtk_button_new_from_stock(GTK_STOCK_CANCEL); | |
373 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); | |
374 gtk_widget_show(button); | |
375 | |
376 g_signal_connect(G_OBJECT(button), "clicked", | |
377 G_CALLBACK(status_editor_cancel_cb), dialog); | |
378 | |
379 /* Save button */ | |
380 /* TODO: This button needs to be made sensitive when the title box contains text */ | |
381 button = gtk_button_new_from_stock(GTK_STOCK_SAVE); | |
382 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); | |
383 gtk_widget_set_sensitive(button, FALSE); | |
384 gtk_widget_show(button); | |
385 | |
386 g_signal_connect(G_OBJECT(button), "clicked", | |
387 G_CALLBACK(status_editor_save_cb), dialog); | |
388 | |
389 gtk_widget_show(win); | |
390 } | |
391 | |
392 static gboolean | |
393 status_window_find_savedstatus(GtkTreeIter *iter, const char *title) | |
394 { | |
395 GtkTreeModel *model = GTK_TREE_MODEL(status_window->model); | |
396 const char *cur; | |
397 | |
398 if (!gtk_tree_model_get_iter_first(model, iter)) | |
399 return FALSE; | |
400 | |
401 gtk_tree_model_get(model, iter, STATUS_WINDOW_COLUMN_TITLE, &cur, -1); | |
402 if (!strcmp(title, cur)) | |
403 return TRUE; | |
404 | |
405 while (gtk_tree_model_iter_next(model, iter)) | |
406 { | |
407 gtk_tree_model_get(model, iter, STATUS_WINDOW_COLUMN_TITLE, &cur, -1); | |
408 if (!strcmp(title, cur)) | |
409 return TRUE; | |
410 } | |
411 | |
412 return FALSE; | |
413 } | |
414 | |
415 static gboolean | |
416 status_window_destroy_cb(GtkWidget *widget, GdkEvent *event, gpointer user_data) | |
417 { | |
418 StatusWindow *dialog = user_data; | |
419 | |
420 dialog->window = NULL; | |
421 gaim_gtk_status_window_hide(); | |
422 | |
423 return FALSE; | |
424 } | |
425 | |
426 static void | |
427 status_window_add_cb(GtkButton *button, gpointer user_data) | |
428 { | |
429 gaim_gtk_status_editor_show(); | |
430 } | |
431 | |
432 static void | |
433 status_window_modify_foreach(GtkTreeModel *model, GtkTreePath *path, | |
434 GtkTreeIter *iter, gpointer user_data) | |
435 { | |
436 const char *title; | |
437 GaimStatusSaved *status; | |
438 | |
439 gtk_tree_model_get(model, iter, STATUS_WINDOW_COLUMN_TITLE, &title, -1); | |
440 | |
441 status = gaim_savedstatuses_find(title); | |
442 /* TODO: Need to show a status editor pre-populated with this status */ | |
443 } | |
444 | |
445 static void | |
446 status_window_modify_cb(GtkButton *button, gpointer user_data) | |
447 { | |
448 StatusWindow *dialog = user_data; | |
449 GtkTreeSelection *selection; | |
450 | |
451 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->treeview)); | |
452 | |
453 gtk_tree_selection_selected_foreach(selection, status_window_modify_foreach, user_data); | |
454 } | |
455 | |
456 static void | |
457 status_window_delete_confirm_cb(char *title) | |
458 { | |
459 GtkTreeIter iter; | |
460 | |
461 if (status_window_find_savedstatus(&iter, title)) | |
462 gtk_list_store_remove(status_window->model, &iter); | |
463 | |
464 gaim_savedstatuses_delete(title); | |
465 | |
466 g_free(title); | |
467 } | |
468 | |
469 static void | |
470 status_window_delete_foreach(GtkTreeModel *model, GtkTreePath *path, | |
471 GtkTreeIter *iter, gpointer user_data) | |
472 { | |
473 const char *title; | |
474 char *buf; | |
475 | |
476 gtk_tree_model_get(model, iter, STATUS_WINDOW_COLUMN_TITLE, &title, -1); | |
477 | |
478 buf = g_strdup_printf(_("Are you sure you want to delete %s?"), title); | |
479 gaim_request_action(NULL, NULL, buf, NULL, 0, g_strdup(title), 2, | |
480 _("Delete"), status_window_delete_confirm_cb, | |
481 _("Cancel"), g_free); | |
482 g_free(buf); | |
483 } | |
484 | |
485 static void | |
486 status_window_delete_cb(GtkButton *button, gpointer user_data) | |
487 { | |
488 StatusWindow *dialog = user_data; | |
489 GtkTreeSelection *selection; | |
490 | |
491 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->treeview)); | |
492 | |
493 gtk_tree_selection_selected_foreach(selection, status_window_delete_foreach, user_data); | |
494 } | |
495 | |
496 static void | |
497 status_window_close_cb(GtkButton *button, gpointer user_data) | |
498 { | |
499 gaim_gtk_status_window_hide(); | |
500 } | |
501 | |
502 static void | |
503 status_selected_cb(GtkTreeSelection *sel, gpointer user_data) | |
504 { | |
505 StatusWindow *dialog = user_data; | |
506 gboolean selected = FALSE; | |
507 | |
508 #if GTK_CHECK_VERSION(2,2,0) | |
509 selected = (gtk_tree_selection_count_selected_rows(sel) > 0); | |
510 #else | |
511 gtk_tree_selection_selected_foreach(sel, get_selected_helper, &selected); | |
512 #endif | |
513 | |
514 gtk_widget_set_sensitive(dialog->modify_button, selected); | |
515 gtk_widget_set_sensitive(dialog->delete_button, selected); | |
516 } | |
517 | |
518 static void | |
519 populate_saved_status_list(StatusWindow *dialog) | |
520 { | |
521 GtkTreeIter iter; | |
522 const GList *saved_statuses; | |
523 GaimStatusSaved *saved_status; | |
524 char *message; | |
525 | |
526 gtk_list_store_clear(dialog->model); | |
527 | |
528 for (saved_statuses = gaim_savedstatuses_get_all(); saved_statuses != NULL; | |
529 saved_statuses = g_list_next(saved_statuses)) | |
530 { | |
531 saved_status = (GaimStatusSaved *)saved_statuses->data; | |
532 message = gaim_markup_strip_html(gaim_savedstatuses_get_message(saved_status)); | |
533 if (strlen(message) > 70) | |
534 strcpy(&message[68], "..."); | |
535 | |
536 gtk_list_store_append(dialog->model, &iter); | |
537 gtk_list_store_set(dialog->model, &iter, | |
538 STATUS_WINDOW_COLUMN_TITLE, gaim_savedstatuses_get_title(saved_status), | |
539 STATUS_WINDOW_COLUMN_MESSAGE, message, | |
540 -1); | |
541 free(message); | |
542 } | |
543 } | |
544 | |
545 static GtkWidget * | |
546 create_saved_status_list(StatusWindow *dialog) | |
547 { | |
548 GtkWidget *sw; | |
549 GtkWidget *treeview; | |
550 GtkTreeSelection *sel; | |
551 GtkTreeViewColumn *column; | |
552 GtkCellRenderer *renderer; | |
553 | |
554 /* Create the scrolled window */ | |
555 sw = gtk_scrolled_window_new(0, 0); | |
556 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), | |
557 GTK_POLICY_AUTOMATIC, | |
558 GTK_POLICY_ALWAYS); | |
559 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), | |
560 GTK_SHADOW_IN); | |
561 gtk_widget_show(sw); | |
562 | |
563 /* Create the list model */ | |
564 dialog->model = gtk_list_store_new(STATUS_WINDOW_NUM_COLUMNS, | |
565 G_TYPE_STRING, | |
566 G_TYPE_STRING); | |
567 | |
568 /* Create the treeview */ | |
569 treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(dialog->model)); | |
570 dialog->treeview = treeview; | |
571 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE); | |
572 | |
573 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); | |
574 gtk_tree_selection_set_mode(sel, GTK_SELECTION_MULTIPLE); | |
575 g_signal_connect(G_OBJECT(sel), "changed", | |
576 G_CALLBACK(status_selected_cb), dialog); | |
577 | |
578 gtk_container_add(GTK_CONTAINER(sw), treeview); | |
579 gtk_widget_show(treeview); | |
580 | |
581 | |
582 /* Add columns */ | |
583 column = gtk_tree_view_column_new(); | |
584 gtk_tree_view_column_set_title(column, _("Title")); | |
585 gtk_tree_view_column_set_resizable(column, TRUE); | |
586 gtk_tree_view_column_set_sort_column_id(column, | |
587 STATUS_WINDOW_COLUMN_TITLE); | |
588 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); | |
589 renderer = gtk_cell_renderer_text_new(); | |
590 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
591 gtk_tree_view_column_add_attribute(column, renderer, "text", | |
592 STATUS_WINDOW_COLUMN_TITLE); | |
593 | |
594 column = gtk_tree_view_column_new(); | |
595 gtk_tree_view_column_set_title(column, _("Message")); | |
596 gtk_tree_view_column_set_resizable(column, TRUE); | |
597 gtk_tree_view_column_set_sort_column_id(column, | |
598 STATUS_WINDOW_COLUMN_MESSAGE); | |
599 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); | |
600 renderer = gtk_cell_renderer_text_new(); | |
601 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
602 gtk_tree_view_column_add_attribute(column, renderer, "text", | |
603 STATUS_WINDOW_COLUMN_MESSAGE); | |
604 | |
605 /* Populate list */ | |
606 populate_saved_status_list(dialog); | |
607 | |
608 return sw; | |
609 } | |
610 | |
611 static gboolean | |
612 configure_cb(GtkWidget *widget, GdkEventConfigure *event, StatusWindow *dialog) | |
613 { | |
614 if (GTK_WIDGET_VISIBLE(widget)) { | |
615 gaim_prefs_set_int("/gaim/gtk/status/dialog/width", event->width); | |
616 gaim_prefs_set_int("/gaim/gtk/status/dialog/height", event->height); | |
617 } | |
618 | |
619 return FALSE; | |
620 } | |
621 | |
622 void | |
623 gaim_gtk_status_window_show(void) | |
624 { | |
625 StatusWindow *dialog; | |
626 GtkWidget *bbox; | |
627 GtkWidget *button; | |
628 GtkWidget *list; | |
629 GtkWidget *sep; | |
630 GtkWidget *vbox; | |
631 GtkWidget *win; | |
632 int width, height; | |
633 | |
634 if (status_window != NULL) { | |
635 gtk_window_present(GTK_WINDOW(status_window->window)); | |
636 return; | |
637 } | |
638 | |
639 status_window = dialog = g_new0(StatusWindow, 1); | |
640 | |
641 width = gaim_prefs_get_int("/gaim/gtk/status/dialog/width"); | |
642 height = gaim_prefs_get_int("/gaim/gtk/status/dialog/height"); | |
643 | |
644 dialog->window = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); | |
645 gtk_window_set_default_size(GTK_WINDOW(win), width, height); | |
646 gtk_window_set_role(GTK_WINDOW(win), "statuses"); | |
647 gtk_window_set_title(GTK_WINDOW(win), _("Saved Statuses")); | |
648 gtk_container_set_border_width(GTK_CONTAINER(win), 12); | |
649 | |
650 g_signal_connect(G_OBJECT(win), "delete_event", | |
651 G_CALLBACK(status_window_destroy_cb), dialog); | |
652 g_signal_connect(G_OBJECT(win), "configure_event", | |
653 G_CALLBACK(configure_cb), dialog); | |
654 | |
655 /* Setup the vbox */ | |
656 vbox = gtk_vbox_new(FALSE, 12); | |
657 gtk_container_add(GTK_CONTAINER(win), vbox); | |
658 gtk_widget_show(vbox); | |
659 | |
660 /* List of saved status states */ | |
661 list = create_saved_status_list(dialog); | |
662 gtk_box_pack_start(GTK_BOX(vbox), list, TRUE, TRUE, 0); | |
663 | |
664 /* Separator... */ | |
665 sep = gtk_hseparator_new(); | |
666 gtk_box_pack_start(GTK_BOX(vbox), sep, FALSE, FALSE, 0); | |
667 gtk_widget_show(sep); | |
668 | |
669 /* Button box. */ | |
670 bbox = gtk_hbutton_box_new(); | |
671 gtk_box_set_spacing(GTK_BOX(bbox), 6); | |
672 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); | |
673 gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, TRUE, 0); | |
674 gtk_widget_show(bbox); | |
675 | |
676 /* Add button */ | |
677 button = gtk_button_new_from_stock(GTK_STOCK_ADD); | |
678 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); | |
679 gtk_widget_show(button); | |
680 | |
681 g_signal_connect(G_OBJECT(button), "clicked", | |
682 G_CALLBACK(status_window_add_cb), dialog); | |
683 | |
684 /* Modify button */ | |
685 button = gtk_button_new_from_stock(GAIM_STOCK_MODIFY); | |
686 dialog->modify_button = button; | |
687 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); | |
688 gtk_widget_set_sensitive(button, FALSE); | |
689 gtk_widget_show(button); | |
690 | |
691 g_signal_connect(G_OBJECT(button), "clicked", | |
692 G_CALLBACK(status_window_modify_cb), dialog); | |
693 | |
694 /* Delete button */ | |
695 button = gtk_button_new_from_stock(GTK_STOCK_DELETE); | |
696 dialog->delete_button = button; | |
697 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); | |
698 gtk_widget_set_sensitive(button, FALSE); | |
699 gtk_widget_show(button); | |
700 | |
701 g_signal_connect(G_OBJECT(button), "clicked", | |
702 G_CALLBACK(status_window_delete_cb), dialog); | |
703 | |
704 /* Close button */ | |
705 button = gtk_button_new_from_stock(GTK_STOCK_CLOSE); | |
706 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); | |
707 gtk_widget_show(button); | |
708 | |
709 g_signal_connect(G_OBJECT(button), "clicked", | |
710 G_CALLBACK(status_window_close_cb), dialog); | |
711 | |
712 gtk_widget_show(win); | |
713 } | |
714 | |
715 void | |
716 gaim_gtk_status_window_hide(void) | |
717 { | |
718 if (status_window == NULL) | |
719 return; | |
720 | |
721 if (status_window->window != NULL) | |
722 gtk_widget_destroy(status_window->window); | |
723 | |
724 g_free(status_window); | |
725 status_window = NULL; | |
726 } | |
727 | |
728 void * | |
729 gaim_gtk_status_get_handle() | |
730 { | |
731 static int handle; | |
732 | |
733 return &handle; | |
734 } | |
735 | |
736 void | |
737 gaim_gtk_status_init(void) | |
738 { | |
739 gaim_prefs_add_none("/gaim/gtk/status"); | |
740 gaim_prefs_add_none("/gaim/gtk/status/dialog"); | |
741 gaim_prefs_add_int("/gaim/gtk/status/dialog/width", 550); | |
742 gaim_prefs_add_int("/gaim/gtk/status/dialog/height", 250); | |
743 } | |
744 | |
745 void | |
746 gaim_gtk_status_uninit(void) | |
747 { | |
748 gaim_gtk_status_window_hide(); | |
749 } |