Mercurial > pidgin
annotate src/gtksavedstatuses.c @ 11261:b53606580f68
[gaim-migrate @ 13439]
Patch #1226486 from Levi Bard
Fixes bug #1224178
If you change the topic in a chat room and that topic change is rejected, the
topic field is wrong -- it shows the new topic even thought it didn't get set.
This patch resets the GUI's topic immediately when you hit enter. Then, if the
topic change is successful, the server will echo the topic change back to us
and we'll update the GUI to the new topic.
The only question is, does the server always echo the topic back to us? From the
core's point of view, I'm ready to assume yes. It's the case for both IRC and
Jabber*. If someone could test changing a topic in SILC or Zephyr, that'd be
great. If servers using those protocols do not echo the topic back, the prpl
will have to fake it as appropriate.
* I didn't actually test on Jabber, but Nathan said the server will echo the
topic change back. If it's broken, let me know.
committer: Tailor Script <tailor@pidgin.im>
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Sun, 14 Aug 2005 06:55:57 +0000 |
parents | ad9a61894d9b |
children | 30ad548e8537 |
rev | line source |
---|---|
10418 | 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" | |
10420 | 28 #include "notify.h" |
10418 | 29 #include "request.h" |
30 #include "savedstatuses.h" | |
31 #include "status.h" | |
32 #include "util.h" | |
33 | |
34 #include "gtkblist.h" | |
35 #include "gtkgaim.h" | |
36 #include "gtkgaim-disclosure.h" | |
37 #include "gtkimhtml.h" | |
38 #include "gtkimhtmltoolbar.h" | |
39 #include "gtksavedstatuses.h" | |
40 #include "gtkstock.h" | |
41 #include "gtkutils.h" | |
42 | |
43 enum | |
44 { | |
10421 | 45 STATUS_WINDOW_COLUMN_TITLE, |
46 STATUS_WINDOW_COLUMN_TYPE, | |
47 STATUS_WINDOW_COLUMN_MESSAGE, | |
48 STATUS_WINDOW_NUM_COLUMNS | |
49 }; | |
50 | |
51 enum | |
52 { | |
10418 | 53 STATUS_EDITOR_COLUMN_CUSTOM_STATUS, |
54 STATUS_EDITOR_COLUMN_ICON, | |
55 STATUS_EDITOR_COLUMN_SCREENNAME, | |
56 STATUS_EDITOR_NUM_COLUMNS | |
57 }; | |
58 | |
10421 | 59 typedef struct |
10418 | 60 { |
10421 | 61 GtkWidget *window; |
62 GtkListStore *model; | |
63 GtkWidget *treeview; | |
64 GtkWidget *modify_button; | |
65 GtkWidget *delete_button; | |
66 } StatusWindow; | |
10418 | 67 |
68 typedef struct | |
69 { | |
70 GtkWidget *window; | |
71 GtkListStore *model; | |
72 GtkWidget *treeview; | |
10420 | 73 GtkWidget *save_button; |
74 | |
75 gchar *original_title; | |
76 GtkEntry *title; | |
77 GtkOptionMenu *type; | |
78 GtkIMHtml *message; | |
10418 | 79 } StatusEditor; |
80 | |
81 static StatusWindow *status_window = NULL; | |
82 | |
10421 | 83 |
84 /************************************************************************** | |
85 * Status window | |
86 **************************************************************************/ | |
87 | |
88 static gboolean | |
89 status_window_find_savedstatus(GtkTreeIter *iter, const char *title) | |
90 { | |
91 GtkTreeModel *model = GTK_TREE_MODEL(status_window->model); | |
10439 | 92 char *cur; |
10421 | 93 |
94 if (!gtk_tree_model_get_iter_first(model, iter)) | |
95 return FALSE; | |
96 | |
97 gtk_tree_model_get(model, iter, STATUS_WINDOW_COLUMN_TITLE, &cur, -1); | |
98 if (!strcmp(title, cur)) | |
10439 | 99 { |
100 g_free(cur); | |
10421 | 101 return TRUE; |
10439 | 102 } |
103 g_free(cur); | |
10421 | 104 |
105 while (gtk_tree_model_iter_next(model, iter)) | |
106 { | |
107 gtk_tree_model_get(model, iter, STATUS_WINDOW_COLUMN_TITLE, &cur, -1); | |
108 if (!strcmp(title, cur)) | |
10439 | 109 { |
110 g_free(cur); | |
10421 | 111 return TRUE; |
10439 | 112 } |
113 g_free(cur); | |
10421 | 114 } |
115 | |
116 return FALSE; | |
117 } | |
118 | |
119 static gboolean | |
120 status_window_destroy_cb(GtkWidget *widget, GdkEvent *event, gpointer user_data) | |
121 { | |
122 StatusWindow *dialog = user_data; | |
123 | |
124 dialog->window = NULL; | |
125 gaim_gtk_status_window_hide(); | |
126 | |
127 return FALSE; | |
128 } | |
129 | |
130 static void | |
131 status_window_add_cb(GtkButton *button, gpointer user_data) | |
132 { | |
133 gaim_gtk_status_editor_show(NULL); | |
134 } | |
135 | |
136 static void | |
137 status_window_modify_foreach(GtkTreeModel *model, GtkTreePath *path, | |
138 GtkTreeIter *iter, gpointer user_data) | |
139 { | |
10439 | 140 char *title; |
10421 | 141 GaimSavedStatus *status; |
142 | |
143 gtk_tree_model_get(model, iter, STATUS_WINDOW_COLUMN_TITLE, &title, -1); | |
144 | |
145 status = gaim_savedstatus_find(title); | |
10439 | 146 g_free(title); |
10421 | 147 gaim_gtk_status_editor_show(status); |
148 } | |
149 | |
150 static void | |
151 status_window_modify_cb(GtkButton *button, gpointer user_data) | |
152 { | |
153 StatusWindow *dialog = user_data; | |
154 GtkTreeSelection *selection; | |
155 | |
156 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->treeview)); | |
157 | |
158 gtk_tree_selection_selected_foreach(selection, status_window_modify_foreach, user_data); | |
159 } | |
160 | |
161 static void | |
162 status_window_delete_confirm_cb(char *title) | |
163 { | |
164 GtkTreeIter iter; | |
165 | |
166 if (status_window_find_savedstatus(&iter, title)) | |
167 gtk_list_store_remove(status_window->model, &iter); | |
168 | |
169 gaim_savedstatus_delete(title); | |
170 | |
171 g_free(title); | |
172 } | |
173 | |
174 static void | |
175 status_window_delete_foreach(GtkTreeModel *model, GtkTreePath *path, | |
176 GtkTreeIter *iter, gpointer user_data) | |
177 { | |
10439 | 178 char *title; |
10435 | 179 char *title_escaped, *buf; |
10421 | 180 |
181 gtk_tree_model_get(model, iter, STATUS_WINDOW_COLUMN_TITLE, &title, -1); | |
182 | |
10732
c4cb90065e1d
[gaim-migrate @ 12334]
Luke Schierer <lschiere@pidgin.im>
parents:
10591
diff
changeset
|
183 title_escaped = g_markup_escape_text(title, -1); |
10435 | 184 buf = g_strdup_printf(_("Are you sure you want to delete %s?"), title_escaped); |
185 free(title_escaped); | |
10439 | 186 gaim_request_action(NULL, NULL, buf, NULL, 0, title, 2, |
10421 | 187 _("Delete"), status_window_delete_confirm_cb, |
188 _("Cancel"), g_free); | |
189 g_free(buf); | |
190 } | |
191 | |
192 static void | |
193 status_window_delete_cb(GtkButton *button, gpointer user_data) | |
194 { | |
195 StatusWindow *dialog = user_data; | |
196 GtkTreeSelection *selection; | |
197 | |
198 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->treeview)); | |
199 | |
200 gtk_tree_selection_selected_foreach(selection, status_window_delete_foreach, user_data); | |
201 } | |
202 | |
203 static void | |
204 status_window_close_cb(GtkButton *button, gpointer user_data) | |
205 { | |
206 gaim_gtk_status_window_hide(); | |
207 } | |
208 | |
209 static void | |
210 status_selected_cb(GtkTreeSelection *sel, gpointer user_data) | |
211 { | |
212 StatusWindow *dialog = user_data; | |
213 gboolean selected = FALSE; | |
214 | |
215 #if GTK_CHECK_VERSION(2,2,0) | |
216 selected = (gtk_tree_selection_count_selected_rows(sel) > 0); | |
217 #else | |
218 gtk_tree_selection_selected_foreach(sel, get_selected_helper, &selected); | |
219 #endif | |
220 | |
221 gtk_widget_set_sensitive(dialog->modify_button, selected); | |
222 gtk_widget_set_sensitive(dialog->delete_button, selected); | |
223 } | |
224 | |
225 static void | |
226 add_status_to_saved_status_list(GtkListStore *model, GaimSavedStatus *saved_status) | |
227 { | |
228 GtkTreeIter iter; | |
229 const char *title; | |
230 const char *type; | |
231 char *message; | |
232 | |
233 title = gaim_savedstatus_get_title(saved_status); | |
234 type = gaim_primitive_get_name_from_type(gaim_savedstatus_get_type(saved_status)); | |
235 message = gaim_markup_strip_html(gaim_savedstatus_get_message(saved_status)); | |
236 | |
237 gtk_list_store_append(model, &iter); | |
238 gtk_list_store_set(model, &iter, | |
239 STATUS_WINDOW_COLUMN_TITLE, title, | |
240 STATUS_WINDOW_COLUMN_TYPE, type, | |
241 STATUS_WINDOW_COLUMN_MESSAGE, message, | |
242 -1); | |
243 free(message); | |
244 } | |
245 | |
246 static void | |
247 populate_saved_status_list(StatusWindow *dialog) | |
248 { | |
249 const GList *saved_statuses; | |
250 | |
251 gtk_list_store_clear(dialog->model); | |
252 | |
253 for (saved_statuses = gaim_savedstatuses_get_all(); saved_statuses != NULL; | |
254 saved_statuses = g_list_next(saved_statuses)) | |
255 { | |
256 add_status_to_saved_status_list(dialog->model, saved_statuses->data); | |
257 } | |
258 } | |
259 | |
10435 | 260 static gboolean |
261 search_func(GtkTreeModel *model, gint column, const gchar *key, GtkTreeIter *iter, gpointer search_data) | |
262 { | |
10439 | 263 gboolean result; |
264 char *haystack; | |
10435 | 265 |
266 gtk_tree_model_get(model, iter, column, &haystack, -1); | |
267 | |
10439 | 268 result = (gaim_strcasestr(haystack, key) == NULL); |
269 | |
270 g_free(haystack); | |
271 | |
272 return result; | |
10435 | 273 } |
274 | |
10421 | 275 static GtkWidget * |
276 create_saved_status_list(StatusWindow *dialog) | |
277 { | |
278 GtkWidget *sw; | |
279 GtkWidget *treeview; | |
280 GtkTreeSelection *sel; | |
281 GtkTreeViewColumn *column; | |
282 GtkCellRenderer *renderer; | |
283 | |
284 /* Create the scrolled window */ | |
285 sw = gtk_scrolled_window_new(0, 0); | |
286 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), | |
287 GTK_POLICY_AUTOMATIC, | |
288 GTK_POLICY_ALWAYS); | |
289 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), | |
290 GTK_SHADOW_IN); | |
291 gtk_widget_show(sw); | |
292 | |
293 /* Create the list model */ | |
294 dialog->model = gtk_list_store_new(STATUS_WINDOW_NUM_COLUMNS, | |
295 G_TYPE_STRING, | |
296 G_TYPE_STRING, | |
297 G_TYPE_STRING); | |
298 | |
299 /* Create the treeview */ | |
300 treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(dialog->model)); | |
301 dialog->treeview = treeview; | |
302 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE); | |
303 | |
304 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); | |
305 gtk_tree_selection_set_mode(sel, GTK_SELECTION_MULTIPLE); | |
306 g_signal_connect(G_OBJECT(sel), "changed", | |
307 G_CALLBACK(status_selected_cb), dialog); | |
308 | |
309 gtk_container_add(GTK_CONTAINER(sw), treeview); | |
310 gtk_widget_show(treeview); | |
311 | |
312 /* Add columns */ | |
313 column = gtk_tree_view_column_new(); | |
314 gtk_tree_view_column_set_title(column, _("Title")); | |
315 gtk_tree_view_column_set_resizable(column, TRUE); | |
316 gtk_tree_view_column_set_sort_column_id(column, | |
317 STATUS_WINDOW_COLUMN_TITLE); | |
318 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); | |
319 renderer = gtk_cell_renderer_text_new(); | |
320 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
321 gtk_tree_view_column_add_attribute(column, renderer, "text", | |
322 STATUS_WINDOW_COLUMN_TITLE); | |
323 | |
324 column = gtk_tree_view_column_new(); | |
325 gtk_tree_view_column_set_title(column, _("Type")); | |
326 gtk_tree_view_column_set_resizable(column, TRUE); | |
327 gtk_tree_view_column_set_sort_column_id(column, | |
328 STATUS_WINDOW_COLUMN_TYPE); | |
329 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); | |
330 renderer = gtk_cell_renderer_text_new(); | |
331 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
332 gtk_tree_view_column_add_attribute(column, renderer, "text", | |
333 STATUS_WINDOW_COLUMN_TYPE); | |
334 | |
335 column = gtk_tree_view_column_new(); | |
336 gtk_tree_view_column_set_title(column, _("Message")); | |
337 gtk_tree_view_column_set_resizable(column, TRUE); | |
338 gtk_tree_view_column_set_sort_column_id(column, | |
339 STATUS_WINDOW_COLUMN_MESSAGE); | |
340 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); | |
341 renderer = gtk_cell_renderer_text_new(); | |
342 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
343 gtk_tree_view_column_add_attribute(column, renderer, "text", | |
344 STATUS_WINDOW_COLUMN_MESSAGE); | |
10435 | 345 #if GTK_CHECK_VERSION(2,6,0) |
10502 | 346 g_object_set(renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL); |
10435 | 347 #endif |
348 | |
349 /* Enable CTRL+F searching */ | |
350 gtk_tree_view_set_search_column(GTK_TREE_VIEW(treeview), STATUS_WINDOW_COLUMN_TITLE); | |
351 gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(treeview), search_func, NULL, NULL); | |
10421 | 352 |
10422 | 353 /* Sort the title column by default */ |
354 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(dialog->model), | |
355 STATUS_WINDOW_COLUMN_TITLE, | |
356 GTK_SORT_ASCENDING); | |
357 | |
10421 | 358 /* Populate list */ |
359 populate_saved_status_list(dialog); | |
360 | |
361 return sw; | |
362 } | |
363 | |
364 static gboolean | |
365 configure_cb(GtkWidget *widget, GdkEventConfigure *event, StatusWindow *dialog) | |
366 { | |
367 if (GTK_WIDGET_VISIBLE(widget)) { | |
368 gaim_prefs_set_int("/gaim/gtk/status/dialog/width", event->width); | |
369 gaim_prefs_set_int("/gaim/gtk/status/dialog/height", event->height); | |
370 } | |
371 | |
372 return FALSE; | |
373 } | |
374 | |
375 void | |
376 gaim_gtk_status_window_show(void) | |
377 { | |
378 StatusWindow *dialog; | |
379 GtkWidget *bbox; | |
380 GtkWidget *button; | |
381 GtkWidget *list; | |
382 GtkWidget *vbox; | |
383 GtkWidget *win; | |
384 int width, height; | |
385 | |
386 if (status_window != NULL) { | |
387 gtk_window_present(GTK_WINDOW(status_window->window)); | |
388 return; | |
389 } | |
390 | |
391 status_window = dialog = g_new0(StatusWindow, 1); | |
392 | |
393 width = gaim_prefs_get_int("/gaim/gtk/status/dialog/width"); | |
394 height = gaim_prefs_get_int("/gaim/gtk/status/dialog/height"); | |
395 | |
396 dialog->window = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); | |
397 gtk_window_set_default_size(GTK_WINDOW(win), width, height); | |
398 gtk_window_set_role(GTK_WINDOW(win), "statuses"); | |
399 gtk_window_set_title(GTK_WINDOW(win), _("Saved Statuses")); | |
11243 | 400 gtk_container_set_border_width(GTK_CONTAINER(win), GAIM_HIG_BORDER); |
10421 | 401 |
402 g_signal_connect(G_OBJECT(win), "delete_event", | |
403 G_CALLBACK(status_window_destroy_cb), dialog); | |
404 g_signal_connect(G_OBJECT(win), "configure_event", | |
405 G_CALLBACK(configure_cb), dialog); | |
406 | |
407 /* Setup the vbox */ | |
11243 | 408 vbox = gtk_vbox_new(FALSE, GAIM_HIG_BORDER); |
10421 | 409 gtk_container_add(GTK_CONTAINER(win), vbox); |
410 gtk_widget_show(vbox); | |
411 | |
412 /* List of saved status states */ | |
413 list = create_saved_status_list(dialog); | |
414 gtk_box_pack_start(GTK_BOX(vbox), list, TRUE, TRUE, 0); | |
415 | |
416 /* Button box. */ | |
417 bbox = gtk_hbutton_box_new(); | |
11243 | 418 gtk_box_set_spacing(GTK_BOX(bbox), GAIM_HIG_BOX_SPACE); |
10421 | 419 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); |
420 gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, TRUE, 0); | |
421 gtk_widget_show(bbox); | |
422 | |
423 /* Add button */ | |
424 button = gtk_button_new_from_stock(GTK_STOCK_ADD); | |
425 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); | |
426 gtk_widget_show(button); | |
427 | |
428 g_signal_connect(G_OBJECT(button), "clicked", | |
429 G_CALLBACK(status_window_add_cb), dialog); | |
430 | |
431 /* Modify button */ | |
432 button = gtk_button_new_from_stock(GAIM_STOCK_MODIFY); | |
433 dialog->modify_button = button; | |
434 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); | |
435 gtk_widget_set_sensitive(button, FALSE); | |
436 gtk_widget_show(button); | |
437 | |
438 g_signal_connect(G_OBJECT(button), "clicked", | |
439 G_CALLBACK(status_window_modify_cb), dialog); | |
440 | |
441 /* Delete button */ | |
442 button = gtk_button_new_from_stock(GTK_STOCK_DELETE); | |
443 dialog->delete_button = button; | |
444 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); | |
445 gtk_widget_set_sensitive(button, FALSE); | |
446 gtk_widget_show(button); | |
447 | |
448 g_signal_connect(G_OBJECT(button), "clicked", | |
449 G_CALLBACK(status_window_delete_cb), dialog); | |
450 | |
451 /* Close button */ | |
452 button = gtk_button_new_from_stock(GTK_STOCK_CLOSE); | |
453 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); | |
454 gtk_widget_show(button); | |
455 | |
456 g_signal_connect(G_OBJECT(button), "clicked", | |
457 G_CALLBACK(status_window_close_cb), dialog); | |
458 | |
459 gtk_widget_show(win); | |
460 } | |
461 | |
462 void | |
463 gaim_gtk_status_window_hide(void) | |
464 { | |
465 if (status_window == NULL) | |
466 return; | |
467 | |
468 if (status_window->window != NULL) | |
469 gtk_widget_destroy(status_window->window); | |
470 | |
471 g_free(status_window); | |
472 status_window = NULL; | |
473 } | |
474 | |
475 | |
476 /************************************************************************** | |
477 * Status editor | |
478 **************************************************************************/ | |
10420 | 479 |
10418 | 480 static gboolean |
481 status_editor_destroy_cb(GtkWidget *widget, GdkEvent *event, gpointer user_data) | |
482 { | |
10574 | 483 StatusEditor *dialog = user_data; |
10418 | 484 |
10574 | 485 g_free(dialog->original_title); |
10418 | 486 g_free(dialog); |
487 | |
488 return FALSE; | |
489 } | |
490 | |
491 static void | |
492 status_editor_cancel_cb(GtkButton *button, gpointer user_data) | |
493 { | |
10574 | 494 StatusEditor *dialog = user_data; |
10418 | 495 |
496 gtk_widget_destroy(dialog->window); | |
497 | |
10574 | 498 g_free(dialog->original_title); |
10418 | 499 g_free(dialog); |
500 } | |
501 | |
502 static void | |
503 status_editor_save_cb(GtkButton *button, gpointer user_data) | |
504 { | |
10420 | 505 StatusEditor *dialog = user_data; |
506 const char *title; | |
507 GaimStatusPrimitive type; | |
508 char *message, *unformatted; | |
509 GaimSavedStatus *status; | |
510 | |
511 title = gtk_entry_get_text(dialog->title); | |
512 | |
513 /* | |
514 * If the title is already taken then show an error dialog and | |
515 * don't do anything. | |
516 */ | |
517 if ((gaim_savedstatus_find(title) != NULL) && | |
518 ((dialog->original_title == NULL) || (strcmp(title, dialog->original_title)))) | |
519 { | |
520 gaim_notify_error(NULL, NULL, _("Title already in use. You must " | |
521 "choose a unique title."), NULL); | |
522 return; | |
523 } | |
524 | |
525 type = gtk_option_menu_get_history(dialog->type); | |
526 message = gtk_imhtml_get_markup(dialog->message); | |
527 unformatted = gaim_markup_strip_html(message); | |
528 | |
529 /* | |
530 * If we're editing an existing status, remove the old one to | |
531 * make way for the modified one. | |
532 */ | |
533 if (dialog->original_title != NULL) | |
534 { | |
535 GtkTreeIter iter; | |
536 | |
537 gaim_savedstatus_delete(dialog->original_title); | |
538 | |
539 if (status_window_find_savedstatus(&iter, dialog->original_title)) | |
540 { | |
541 gtk_list_store_remove(status_window->model, &iter); | |
542 } | |
543 } | |
544 | |
545 status = gaim_savedstatus_new(title, type); | |
546 if (*unformatted != '\0') | |
547 gaim_savedstatus_set_message(status, message); | |
548 g_free(message); | |
549 g_free(unformatted); | |
550 | |
551 gtk_widget_destroy(dialog->window); | |
10574 | 552 g_free(dialog->original_title); |
10420 | 553 g_free(dialog); |
554 | |
555 add_status_to_saved_status_list(status_window->model, status); | |
556 } | |
557 | |
558 static void | |
559 status_editor_custom_status_cb(GtkCellRendererToggle *renderer, gchar *path_str, gpointer data) | |
560 { | |
561 /* StatusEditor *dialog = (StatusEditor *)data; */ | |
562 | |
563 /* TODO: Need to allow user to set a custom status for the highlighted account, somehow */ | |
564 } | |
565 | |
566 static void | |
567 editor_title_changed_cb(GtkWidget *widget, gpointer user_data) | |
568 { | |
569 StatusEditor *dialog = user_data; | |
570 const gchar *text; | |
571 | |
572 text = gtk_entry_get_text(dialog->title); | |
573 | |
574 gtk_widget_set_sensitive(dialog->save_button, (*text != '\0')); | |
10418 | 575 } |
576 | |
577 static GtkWidget * | |
10419 | 578 create_status_type_menu(GaimStatusPrimitive type) |
10418 | 579 { |
10419 | 580 int i; |
10418 | 581 GtkWidget *dropdown; |
582 GtkWidget *menu; | |
583 GtkWidget *item; | |
584 | |
585 dropdown = gtk_option_menu_new(); | |
586 menu = gtk_menu_new(); | |
587 | |
10419 | 588 for (i = 0; i < GAIM_STATUS_NUM_PRIMITIVES; i++) |
589 { | |
590 item = gtk_menu_item_new_with_label(gaim_primitive_get_name_from_type(i)); | |
591 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); | |
592 gtk_widget_show(item); | |
593 } | |
10418 | 594 |
10419 | 595 gtk_menu_set_active(GTK_MENU(menu), type); |
10418 | 596 gtk_option_menu_set_menu(GTK_OPTION_MENU(dropdown), menu); |
597 gtk_widget_show(menu); | |
598 | |
599 return dropdown; | |
600 } | |
601 | |
602 static void | |
603 status_editor_add_columns(StatusEditor *dialog) | |
604 { | |
605 GtkCellRenderer *renderer; | |
606 GtkTreeViewColumn *column; | |
607 | |
608 /* Custom status column */ | |
609 renderer = gtk_cell_renderer_toggle_new(); | |
610 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(dialog->treeview), | |
611 -1, _("Custom status"), | |
612 renderer, | |
613 "active", STATUS_EDITOR_COLUMN_CUSTOM_STATUS, | |
614 NULL); | |
615 column = gtk_tree_view_get_column(GTK_TREE_VIEW(dialog->treeview), 1); | |
616 g_signal_connect(G_OBJECT(renderer), "toggled", | |
617 G_CALLBACK(status_editor_custom_status_cb), dialog); | |
618 | |
619 /* Screen Name column */ | |
620 column = gtk_tree_view_column_new(); | |
621 gtk_tree_view_column_set_resizable(column, TRUE); | |
622 gtk_tree_view_column_set_title(column, _("Screen Name")); | |
623 gtk_tree_view_insert_column(GTK_TREE_VIEW(dialog->treeview), column, -1); | |
624 gtk_tree_view_column_set_resizable(column, TRUE); | |
625 | |
626 /* Icon */ | |
627 renderer = gtk_cell_renderer_pixbuf_new(); | |
628 gtk_tree_view_column_pack_start(column, renderer, FALSE); | |
629 gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", | |
630 STATUS_EDITOR_COLUMN_ICON); | |
631 | |
632 /* Screen Name */ | |
633 renderer = gtk_cell_renderer_text_new(); | |
634 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
635 gtk_tree_view_column_add_attribute(column, renderer, "text", | |
636 STATUS_EDITOR_COLUMN_SCREENNAME); | |
637 } | |
638 | |
639 static void | |
640 status_editor_set_account(GtkListStore *store, GaimAccount *account, GtkTreeIter *iter) | |
641 { | |
642 GdkPixbuf *pixbuf; | |
643 GdkPixbuf *scale; | |
644 | |
645 scale = NULL; | |
646 | |
10884 | 647 pixbuf = gaim_gtk_create_prpl_icon(account); |
10418 | 648 |
649 if (pixbuf != NULL) | |
650 { | |
651 scale = gdk_pixbuf_scale_simple(pixbuf, 16, 16, GDK_INTERP_BILINEAR); | |
652 | |
11251 | 653 if (gaim_account_is_disconnected(account)) |
10418 | 654 gdk_pixbuf_saturate_and_pixelate(scale, scale, 0.0, FALSE); |
655 } | |
656 | |
657 gtk_list_store_set(store, iter, | |
658 STATUS_EDITOR_COLUMN_ICON, scale, | |
659 STATUS_EDITOR_COLUMN_SCREENNAME, gaim_account_get_username(account), | |
660 -1); | |
661 | |
662 if (pixbuf != NULL) g_object_unref(G_OBJECT(pixbuf)); | |
663 if (scale != NULL) g_object_unref(G_OBJECT(scale)); | |
664 } | |
665 | |
666 static void | |
667 status_editor_add_account(StatusEditor *dialog, GaimAccount *account) | |
668 { | |
669 GtkTreeIter iter; | |
670 | |
671 gtk_list_store_append(dialog->model, &iter); | |
672 | |
673 status_editor_set_account(dialog->model, account, &iter); | |
674 } | |
675 | |
676 static void | |
677 status_editor_populate_list(StatusEditor *dialog) | |
678 { | |
679 GList *l; | |
680 | |
681 gtk_list_store_clear(dialog->model); | |
682 | |
683 for (l = gaim_accounts_get_all(); l != NULL; l = l->next) | |
684 status_editor_add_account(dialog, (GaimAccount *)l->data); | |
685 } | |
686 | |
687 void | |
10419 | 688 gaim_gtk_status_editor_show(GaimSavedStatus *status) |
10418 | 689 { |
690 StatusEditor *dialog; | |
691 GtkSizeGroup *sg; | |
692 GtkWidget *bbox; | |
693 GtkWidget *button; | |
694 GtkWidget *dbox; | |
695 GtkWidget *disclosure; | |
696 GtkWidget *dropdown; | |
697 GtkWidget *entry; | |
698 GtkWidget *frame; | |
699 GtkWidget *hbox; | |
700 GtkWidget *label; | |
701 GtkWidget *sw; | |
702 GtkWidget *text; | |
703 GtkWidget *toolbar; | |
704 GtkWidget *vbox; | |
705 GtkWidget *win; | |
706 | |
707 dialog = g_new0(StatusEditor, 1); | |
708 | |
10420 | 709 if (status != NULL) |
710 dialog->original_title = g_strdup(gaim_savedstatus_get_title(status)); | |
711 | |
10418 | 712 dialog->window = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); |
713 gtk_window_set_role(GTK_WINDOW(win), "status"); | |
714 gtk_window_set_title(GTK_WINDOW(win), _("Status")); | |
715 gtk_window_set_resizable(GTK_WINDOW(win), FALSE); | |
11243 | 716 gtk_container_set_border_width(GTK_CONTAINER(win), GAIM_HIG_BORDER); |
10418 | 717 |
718 g_signal_connect(G_OBJECT(win), "delete_event", | |
719 G_CALLBACK(status_editor_destroy_cb), dialog); | |
720 | |
721 /* Setup the vbox */ | |
11243 | 722 vbox = gtk_vbox_new(FALSE, GAIM_HIG_BORDER); |
10418 | 723 gtk_container_add(GTK_CONTAINER(win), vbox); |
724 gtk_widget_show(vbox); | |
725 | |
726 sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); | |
727 | |
728 /* Title */ | |
11243 | 729 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BOX_SPACE); |
10418 | 730 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); |
731 gtk_widget_show(hbox); | |
732 | |
733 label = gtk_label_new_with_mnemonic(_("_Title:")); | |
734 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
735 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); | |
736 gtk_widget_show(label); | |
737 gtk_size_group_add_widget(sg, label); | |
738 | |
739 entry = gtk_entry_new(); | |
10420 | 740 dialog->title = GTK_ENTRY(entry); |
10419 | 741 if (status != NULL) |
10420 | 742 gtk_entry_set_text(GTK_ENTRY(entry), dialog->original_title); |
10419 | 743 else |
744 gtk_entry_set_text(GTK_ENTRY(entry), _("Out of the office")); | |
10418 | 745 gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0); |
746 gtk_widget_show(entry); | |
10420 | 747 g_signal_connect(G_OBJECT(entry), "changed", |
748 G_CALLBACK(editor_title_changed_cb), dialog); | |
10418 | 749 |
750 /* Status type */ | |
11243 | 751 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BOX_SPACE); |
10418 | 752 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); |
753 gtk_widget_show(hbox); | |
754 | |
755 label = gtk_label_new_with_mnemonic(_("_Status:")); | |
756 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
757 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); | |
758 gtk_widget_show(label); | |
759 gtk_size_group_add_widget(sg, label); | |
760 | |
10419 | 761 if (status != NULL) |
762 dropdown = create_status_type_menu(gaim_savedstatus_get_type(status)); | |
763 else | |
764 dropdown = create_status_type_menu(GAIM_STATUS_AWAY); | |
10420 | 765 dialog->type = GTK_OPTION_MENU(dropdown); |
10418 | 766 gtk_box_pack_start(GTK_BOX(hbox), dropdown, TRUE, TRUE, 0); |
767 gtk_widget_show(dropdown); | |
768 | |
769 /* Status message */ | |
11243 | 770 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BOX_SPACE); |
10418 | 771 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); |
772 gtk_widget_show(hbox); | |
773 | |
774 label = gtk_label_new_with_mnemonic(_("_Message:")); | |
775 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
776 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); | |
777 gtk_widget_show(label); | |
778 gtk_size_group_add_widget(sg, label); | |
779 | |
780 frame = gaim_gtk_create_imhtml(TRUE, &text, &toolbar); | |
10420 | 781 dialog->message = GTK_IMHTML(text); |
10418 | 782 gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0); |
783 gtk_widget_show(frame); | |
784 | |
10574 | 785 if ((status != NULL) && (gaim_savedstatus_get_message(status) != NULL)) |
10419 | 786 gtk_imhtml_append_text(GTK_IMHTML(text), |
787 gaim_savedstatus_get_message(status), 0); | |
788 | |
10418 | 789 /* Custom status message disclosure */ |
790 disclosure = gaim_disclosure_new(_("Use a different status for some accounts"), | |
791 _("Use a different status for some accounts")); | |
792 gtk_box_pack_start(GTK_BOX(vbox), disclosure, FALSE, FALSE, 0); | |
793 gtk_widget_show(disclosure); | |
794 | |
795 /* Setup the box that the disclosure will cover */ | |
11243 | 796 dbox = gtk_vbox_new(FALSE, GAIM_HIG_CAT_SPACE); |
10418 | 797 gtk_box_pack_start(GTK_BOX(vbox), dbox, FALSE, FALSE, 0); |
798 gaim_disclosure_set_container(GAIM_DISCLOSURE(disclosure), dbox); | |
799 | |
800 /* Custom status message treeview */ | |
801 sw = gtk_scrolled_window_new(NULL, NULL); | |
802 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), | |
803 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); | |
804 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), | |
805 GTK_SHADOW_IN); | |
806 gtk_box_pack_start(GTK_BOX(dbox), sw, TRUE, TRUE, 0); | |
807 gtk_widget_show(sw); | |
808 | |
809 /* Create the list model */ | |
810 dialog->model = gtk_list_store_new(STATUS_EDITOR_NUM_COLUMNS, | |
811 G_TYPE_BOOLEAN, | |
812 GDK_TYPE_PIXBUF, G_TYPE_STRING); | |
813 | |
814 /* Create the treeview */ | |
815 dialog->treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(dialog->model)); | |
816 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(dialog->treeview), TRUE); | |
817 gtk_widget_set_size_request(dialog->treeview, 400, 250); | |
818 gtk_container_add(GTK_CONTAINER(sw), dialog->treeview); | |
819 gtk_widget_show(dialog->treeview); | |
820 | |
821 /* Add columns */ | |
822 status_editor_add_columns(dialog); | |
823 | |
824 /* Populate list */ | |
825 status_editor_populate_list(dialog); | |
826 | |
827 /* Button box */ | |
828 bbox = gtk_hbutton_box_new(); | |
11243 | 829 gtk_box_set_spacing(GTK_BOX(bbox), GAIM_HIG_BOX_SPACE); |
10418 | 830 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); |
831 gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, TRUE, 0); | |
832 gtk_widget_show(bbox); | |
833 | |
834 /* Cancel button */ | |
835 button = gtk_button_new_from_stock(GTK_STOCK_CANCEL); | |
836 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); | |
837 gtk_widget_show(button); | |
838 | |
839 g_signal_connect(G_OBJECT(button), "clicked", | |
840 G_CALLBACK(status_editor_cancel_cb), dialog); | |
841 | |
842 /* Save button */ | |
843 button = gtk_button_new_from_stock(GTK_STOCK_SAVE); | |
10420 | 844 dialog->save_button = button; |
10418 | 845 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); |
846 gtk_widget_show(button); | |
847 | |
848 g_signal_connect(G_OBJECT(button), "clicked", | |
849 G_CALLBACK(status_editor_save_cb), dialog); | |
850 | |
851 gtk_widget_show(win); | |
852 } | |
853 | |
854 | |
10421 | 855 /************************************************************************** |
10814
364a2ef907ae
[gaim-migrate @ 12468]
Luke Schierer <lschiere@pidgin.im>
parents:
10732
diff
changeset
|
856 * GTK+ saved status glue |
10421 | 857 **************************************************************************/ |
10418 | 858 |
859 void * | |
860 gaim_gtk_status_get_handle() | |
861 { | |
862 static int handle; | |
863 | |
864 return &handle; | |
865 } | |
866 | |
867 void | |
868 gaim_gtk_status_init(void) | |
869 { | |
870 gaim_prefs_add_none("/gaim/gtk/status"); | |
871 gaim_prefs_add_none("/gaim/gtk/status/dialog"); | |
872 gaim_prefs_add_int("/gaim/gtk/status/dialog/width", 550); | |
873 gaim_prefs_add_int("/gaim/gtk/status/dialog/height", 250); | |
874 } | |
875 | |
876 void | |
877 gaim_gtk_status_uninit(void) | |
878 { | |
879 gaim_gtk_status_window_hide(); | |
880 } |