Mercurial > pidgin
annotate src/gtksavedstatuses.c @ 12174:c7652a910308
[gaim-migrate @ 14476]
KingAnt said:
"And if double-clicking loads a plugin, then double-clicking
again must unload the plugin. However, I think it's better
if double-clicking either opens the preferences or does nothing."
I disagree that double-clicking again must undo what happened from the first time, and in this case, that would totally defeat the goal. Given that this is possibly confusing no matter how we do it, let's take the safest route and not enable the plugin if it's not already. This still accomplishes my main goal of being able to double-click on a plugin I'm using to see its prefs.
committer: Tailor Script <tailor@pidgin.im>
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Sun, 20 Nov 2005 22:09:24 +0000 |
parents | 81c63578aa39 |
children | d040123d2b69 |
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" | |
11735 | 35 #include "gtkexpander.h" |
10418 | 36 #include "gtkgaim.h" |
37 #include "gtkimhtml.h" | |
38 #include "gtkimhtmltoolbar.h" | |
39 #include "gtksavedstatuses.h" | |
40 #include "gtkstock.h" | |
41 #include "gtkutils.h" | |
42 | |
12080 | 43 /* |
44 * TODO: Should attach to the account-deleted and account-added signals | |
45 * and update the GtkListStores in any StatusEditor windows that | |
46 * may be open. | |
47 */ | |
48 | |
49 /** | |
50 * These are used for the GtkTreeView when you're scrolling through | |
51 * all your saved statuses. | |
52 */ | |
10418 | 53 enum |
54 { | |
10421 | 55 STATUS_WINDOW_COLUMN_TITLE, |
56 STATUS_WINDOW_COLUMN_TYPE, | |
57 STATUS_WINDOW_COLUMN_MESSAGE, | |
58 STATUS_WINDOW_NUM_COLUMNS | |
59 }; | |
60 | |
12080 | 61 /** |
62 * These is used for the GtkTreeView containing the list of accounts | |
63 * at the bottom of the window when you're editing a particular | |
64 * saved status. | |
65 */ | |
10421 | 66 enum |
67 { | |
12080 | 68 /** A hidden column containing a pointer to the GaimAccount */ |
69 STATUS_EDITOR_COLUMN_ACCOUNT, | |
70 STATUS_EDITOR_COLUMN_ENABLE_SUBSTATUS, | |
10418 | 71 STATUS_EDITOR_COLUMN_ICON, |
72 STATUS_EDITOR_COLUMN_SCREENNAME, | |
12080 | 73 /** A hidden column containing the ID of this GaimStatusType. */ |
74 STATUS_EDITOR_COLUMN_STATUS_ID, | |
75 STATUS_EDITOR_COLUMN_STATUS_NAME, | |
76 STATUS_EDITOR_COLUMN_STATUS_MESSAGE, | |
10418 | 77 STATUS_EDITOR_NUM_COLUMNS |
78 }; | |
79 | |
12080 | 80 /** |
81 * These are used in the GtkComboBox to select the specific | |
82 * GaimStatusType when setting a substatus for a particular saved | |
83 * status. | |
84 */ | |
85 enum | |
86 { | |
87 /** A hidden column containing a pointer to the GaimAccount. */ | |
88 SUBSTATUS_COLUMN_ACCOUNT, | |
89 SUBSTATUS_COLUMN_ICON, | |
90 /** A hidden column containing the ID of this GaimStatusType. */ | |
91 SUBSTATUS_COLUMN_STATUS_ID, | |
92 SUBSTATUS_COLUMN_STATUS_NAME, | |
93 SUBSTATUS_NUM_COLUMNS | |
94 }; | |
95 | |
10421 | 96 typedef struct |
10418 | 97 { |
10421 | 98 GtkWidget *window; |
99 GtkListStore *model; | |
100 GtkWidget *treeview; | |
11811 | 101 GtkWidget *use_button; |
10421 | 102 GtkWidget *modify_button; |
103 GtkWidget *delete_button; | |
104 } StatusWindow; | |
10418 | 105 |
106 typedef struct | |
107 { | |
108 GtkWidget *window; | |
109 GtkListStore *model; | |
110 GtkWidget *treeview; | |
10420 | 111 GtkWidget *save_button; |
112 | |
113 gchar *original_title; | |
114 GtkEntry *title; | |
115 GtkOptionMenu *type; | |
116 GtkIMHtml *message; | |
10418 | 117 } StatusEditor; |
118 | |
12080 | 119 typedef struct |
120 { | |
121 StatusEditor *status_editor; | |
122 GaimAccount *account; | |
123 | |
124 GtkWidget *window; | |
125 GtkListStore *model; | |
126 GtkComboBox *box; | |
127 GtkIMHtml *message; | |
128 GtkIMHtmlToolbar *toolbar; | |
129 } SubStatusEditor; | |
130 | |
10418 | 131 static StatusWindow *status_window = NULL; |
132 | |
10421 | 133 |
134 /************************************************************************** | |
135 * Status window | |
136 **************************************************************************/ | |
137 | |
138 static gboolean | |
139 status_window_find_savedstatus(GtkTreeIter *iter, const char *title) | |
140 { | |
141 GtkTreeModel *model = GTK_TREE_MODEL(status_window->model); | |
10439 | 142 char *cur; |
10421 | 143 |
144 if (!gtk_tree_model_get_iter_first(model, iter)) | |
145 return FALSE; | |
146 | |
147 gtk_tree_model_get(model, iter, STATUS_WINDOW_COLUMN_TITLE, &cur, -1); | |
148 if (!strcmp(title, cur)) | |
10439 | 149 { |
150 g_free(cur); | |
10421 | 151 return TRUE; |
10439 | 152 } |
153 g_free(cur); | |
10421 | 154 |
155 while (gtk_tree_model_iter_next(model, iter)) | |
156 { | |
157 gtk_tree_model_get(model, iter, STATUS_WINDOW_COLUMN_TITLE, &cur, -1); | |
158 if (!strcmp(title, cur)) | |
10439 | 159 { |
160 g_free(cur); | |
10421 | 161 return TRUE; |
10439 | 162 } |
163 g_free(cur); | |
10421 | 164 } |
165 | |
166 return FALSE; | |
167 } | |
168 | |
169 static gboolean | |
170 status_window_destroy_cb(GtkWidget *widget, GdkEvent *event, gpointer user_data) | |
171 { | |
172 StatusWindow *dialog = user_data; | |
173 | |
174 dialog->window = NULL; | |
175 gaim_gtk_status_window_hide(); | |
176 | |
177 return FALSE; | |
178 } | |
179 | |
11888 | 180 #if !GTK_CHECK_VERSION(2,2,0) |
181 static void | |
182 count_selected_helper(GtkTreeModel *model, GtkTreePath *path, | |
183 GtkTreeIter *iter, gpointer user_data) | |
184 { | |
185 (*(gint *)user_data)++; | |
186 } | |
187 | |
188 static void | |
189 list_selected_helper(GtkTreeModel *model, GtkTreePath *path, | |
190 GtkTreeIter *iter, gpointer user_data) | |
191 { | |
11889 | 192 GList **list = (GList **)user_data; |
193 *list = g_list_append(*list, gtk_tree_path_copy(path)); | |
11888 | 194 } |
195 #endif | |
196 | |
10421 | 197 static void |
11811 | 198 status_window_use_cb(GtkButton *button, StatusWindow *dialog) |
199 { | |
200 GtkTreeSelection *selection; | |
201 GtkTreeIter iter; | |
11889 | 202 GList *list = NULL; |
11888 | 203 int num_selected = 0; |
11811 | 204 |
205 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->treeview)); | |
206 | |
11888 | 207 #if GTK_CHECK_VERSION(2,2,0) |
208 num_selected = gtk_tree_selection_count_selected_rows(selection); | |
209 #else | |
210 gtk_tree_selection_selected_foreach(selection, count_selected_helper, &num_selected); | |
211 #endif | |
212 if (num_selected != 1) | |
11811 | 213 /* |
214 * This shouldn't happen because the "Use" button should have | |
215 * been grayed out. Oh well. | |
216 */ | |
217 return; | |
218 | |
11888 | 219 #if GTK_CHECK_VERSION(2,2,0) |
11811 | 220 list = gtk_tree_selection_get_selected_rows(selection, NULL); |
11888 | 221 #else |
222 gtk_tree_selection_selected_foreach(selection, list_selected_helper, &list); | |
223 #endif | |
11811 | 224 |
225 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(dialog->model), | |
226 &iter, list->data)) | |
227 { | |
12080 | 228 gchar *title; |
229 GaimSavedStatus *saved_status; | |
11811 | 230 gtk_tree_model_get(GTK_TREE_MODEL(dialog->model), &iter, |
12080 | 231 STATUS_WINDOW_COLUMN_TITLE, &title, |
11811 | 232 -1); |
12080 | 233 saved_status = gaim_savedstatus_find(title); |
234 g_free(title); | |
11811 | 235 gaim_savedstatus_activate(saved_status); |
236 } | |
237 | |
238 g_list_foreach(list, (GFunc)gtk_tree_path_free, NULL); | |
239 g_list_free(list); | |
240 } | |
241 | |
242 static void | |
10421 | 243 status_window_add_cb(GtkButton *button, gpointer user_data) |
244 { | |
245 gaim_gtk_status_editor_show(NULL); | |
246 } | |
247 | |
248 static void | |
249 status_window_modify_foreach(GtkTreeModel *model, GtkTreePath *path, | |
250 GtkTreeIter *iter, gpointer user_data) | |
251 { | |
12080 | 252 gchar *title; |
253 GaimSavedStatus *saved_status; | |
10421 | 254 |
12080 | 255 gtk_tree_model_get(model, iter, STATUS_WINDOW_COLUMN_TITLE, &title, -1); |
256 saved_status = gaim_savedstatus_find(title); | |
257 g_free(title); | |
258 gaim_gtk_status_editor_show(saved_status); | |
10421 | 259 } |
260 | |
261 static void | |
262 status_window_modify_cb(GtkButton *button, gpointer user_data) | |
263 { | |
264 StatusWindow *dialog = user_data; | |
265 GtkTreeSelection *selection; | |
266 | |
267 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->treeview)); | |
268 | |
269 gtk_tree_selection_selected_foreach(selection, status_window_modify_foreach, user_data); | |
270 } | |
271 | |
272 static void | |
273 status_window_delete_confirm_cb(char *title) | |
274 { | |
275 GtkTreeIter iter; | |
276 | |
277 if (status_window_find_savedstatus(&iter, title)) | |
278 gtk_list_store_remove(status_window->model, &iter); | |
279 | |
280 gaim_savedstatus_delete(title); | |
281 | |
282 g_free(title); | |
283 } | |
284 | |
285 static void | |
286 status_window_delete_foreach(GtkTreeModel *model, GtkTreePath *path, | |
287 GtkTreeIter *iter, gpointer user_data) | |
288 { | |
10439 | 289 char *title; |
10435 | 290 char *title_escaped, *buf; |
10421 | 291 |
292 gtk_tree_model_get(model, iter, STATUS_WINDOW_COLUMN_TITLE, &title, -1); | |
293 | |
10732
c4cb90065e1d
[gaim-migrate @ 12334]
Luke Schierer <lschiere@pidgin.im>
parents:
10591
diff
changeset
|
294 title_escaped = g_markup_escape_text(title, -1); |
10435 | 295 buf = g_strdup_printf(_("Are you sure you want to delete %s?"), title_escaped); |
296 free(title_escaped); | |
10439 | 297 gaim_request_action(NULL, NULL, buf, NULL, 0, title, 2, |
10421 | 298 _("Delete"), status_window_delete_confirm_cb, |
299 _("Cancel"), g_free); | |
300 g_free(buf); | |
301 } | |
302 | |
303 static void | |
304 status_window_delete_cb(GtkButton *button, gpointer user_data) | |
305 { | |
306 StatusWindow *dialog = user_data; | |
307 GtkTreeSelection *selection; | |
308 | |
309 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->treeview)); | |
310 | |
311 gtk_tree_selection_selected_foreach(selection, status_window_delete_foreach, user_data); | |
312 } | |
313 | |
314 static void | |
315 status_window_close_cb(GtkButton *button, gpointer user_data) | |
316 { | |
317 gaim_gtk_status_window_hide(); | |
318 } | |
319 | |
320 static void | |
321 status_selected_cb(GtkTreeSelection *sel, gpointer user_data) | |
322 { | |
323 StatusWindow *dialog = user_data; | |
11888 | 324 int num_selected = 0; |
10421 | 325 |
326 #if GTK_CHECK_VERSION(2,2,0) | |
11811 | 327 num_selected = gtk_tree_selection_count_selected_rows(sel); |
10421 | 328 #else |
11888 | 329 gtk_tree_selection_selected_foreach(sel, count_selected_helper, &num_selected); |
10421 | 330 #endif |
331 | |
11811 | 332 gtk_widget_set_sensitive(dialog->use_button, (num_selected == 1)); |
333 gtk_widget_set_sensitive(dialog->modify_button, (num_selected > 0)); | |
334 gtk_widget_set_sensitive(dialog->delete_button, (num_selected > 0)); | |
10421 | 335 } |
336 | |
337 static void | |
338 add_status_to_saved_status_list(GtkListStore *model, GaimSavedStatus *saved_status) | |
339 { | |
340 GtkTreeIter iter; | |
341 const char *title; | |
342 const char *type; | |
343 char *message; | |
344 | |
11651 | 345 if (gaim_savedstatus_is_transient(saved_status)) |
346 return; | |
347 | |
10421 | 348 title = gaim_savedstatus_get_title(saved_status); |
349 type = gaim_primitive_get_name_from_type(gaim_savedstatus_get_type(saved_status)); | |
350 message = gaim_markup_strip_html(gaim_savedstatus_get_message(saved_status)); | |
351 | |
352 gtk_list_store_append(model, &iter); | |
353 gtk_list_store_set(model, &iter, | |
354 STATUS_WINDOW_COLUMN_TITLE, title, | |
355 STATUS_WINDOW_COLUMN_TYPE, type, | |
356 STATUS_WINDOW_COLUMN_MESSAGE, message, | |
357 -1); | |
358 free(message); | |
359 } | |
360 | |
361 static void | |
362 populate_saved_status_list(StatusWindow *dialog) | |
363 { | |
364 const GList *saved_statuses; | |
365 | |
366 gtk_list_store_clear(dialog->model); | |
367 | |
368 for (saved_statuses = gaim_savedstatuses_get_all(); saved_statuses != NULL; | |
369 saved_statuses = g_list_next(saved_statuses)) | |
370 { | |
371 add_status_to_saved_status_list(dialog->model, saved_statuses->data); | |
372 } | |
373 } | |
374 | |
10435 | 375 static gboolean |
376 search_func(GtkTreeModel *model, gint column, const gchar *key, GtkTreeIter *iter, gpointer search_data) | |
377 { | |
10439 | 378 gboolean result; |
379 char *haystack; | |
10435 | 380 |
381 gtk_tree_model_get(model, iter, column, &haystack, -1); | |
382 | |
10439 | 383 result = (gaim_strcasestr(haystack, key) == NULL); |
384 | |
385 g_free(haystack); | |
386 | |
387 return result; | |
10435 | 388 } |
389 | |
12162
5e24b8e49522
[gaim-migrate @ 14463]
Richard Laager <rlaager@wiktel.com>
parents:
12080
diff
changeset
|
390 static void |
12173
81c63578aa39
[gaim-migrate @ 14475]
Richard Laager <rlaager@wiktel.com>
parents:
12162
diff
changeset
|
391 savedstatus_activated_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *column, StatusWindow *dialog) |
12162
5e24b8e49522
[gaim-migrate @ 14463]
Richard Laager <rlaager@wiktel.com>
parents:
12080
diff
changeset
|
392 { |
12173
81c63578aa39
[gaim-migrate @ 14475]
Richard Laager <rlaager@wiktel.com>
parents:
12162
diff
changeset
|
393 status_window_modify_cb(NULL, dialog); |
12162
5e24b8e49522
[gaim-migrate @ 14463]
Richard Laager <rlaager@wiktel.com>
parents:
12080
diff
changeset
|
394 } |
5e24b8e49522
[gaim-migrate @ 14463]
Richard Laager <rlaager@wiktel.com>
parents:
12080
diff
changeset
|
395 |
10421 | 396 static GtkWidget * |
397 create_saved_status_list(StatusWindow *dialog) | |
398 { | |
399 GtkWidget *sw; | |
400 GtkWidget *treeview; | |
401 GtkTreeSelection *sel; | |
402 GtkTreeViewColumn *column; | |
403 GtkCellRenderer *renderer; | |
404 | |
405 /* Create the scrolled window */ | |
406 sw = gtk_scrolled_window_new(0, 0); | |
407 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), | |
408 GTK_POLICY_AUTOMATIC, | |
409 GTK_POLICY_ALWAYS); | |
410 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), | |
411 GTK_SHADOW_IN); | |
412 gtk_widget_show(sw); | |
413 | |
414 /* Create the list model */ | |
415 dialog->model = gtk_list_store_new(STATUS_WINDOW_NUM_COLUMNS, | |
416 G_TYPE_STRING, | |
417 G_TYPE_STRING, | |
418 G_TYPE_STRING); | |
419 | |
420 /* Create the treeview */ | |
421 treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(dialog->model)); | |
422 dialog->treeview = treeview; | |
423 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE); | |
12162
5e24b8e49522
[gaim-migrate @ 14463]
Richard Laager <rlaager@wiktel.com>
parents:
12080
diff
changeset
|
424 g_signal_connect(G_OBJECT(treeview), "row-activated", |
12173
81c63578aa39
[gaim-migrate @ 14475]
Richard Laager <rlaager@wiktel.com>
parents:
12162
diff
changeset
|
425 G_CALLBACK(savedstatus_activated_cb), dialog); |
10421 | 426 |
427 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); | |
428 gtk_tree_selection_set_mode(sel, GTK_SELECTION_MULTIPLE); | |
429 g_signal_connect(G_OBJECT(sel), "changed", | |
430 G_CALLBACK(status_selected_cb), dialog); | |
431 | |
432 gtk_container_add(GTK_CONTAINER(sw), treeview); | |
433 gtk_widget_show(treeview); | |
434 | |
435 /* Add columns */ | |
436 column = gtk_tree_view_column_new(); | |
437 gtk_tree_view_column_set_title(column, _("Title")); | |
438 gtk_tree_view_column_set_resizable(column, TRUE); | |
11548 | 439 gtk_tree_view_column_set_min_width(column, 100); |
10421 | 440 gtk_tree_view_column_set_sort_column_id(column, |
441 STATUS_WINDOW_COLUMN_TITLE); | |
442 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); | |
443 renderer = gtk_cell_renderer_text_new(); | |
444 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
445 gtk_tree_view_column_add_attribute(column, renderer, "text", | |
446 STATUS_WINDOW_COLUMN_TITLE); | |
11548 | 447 #if GTK_CHECK_VERSION(2,6,0) |
448 g_object_set(renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL); | |
449 #endif | |
10421 | 450 |
451 column = gtk_tree_view_column_new(); | |
452 gtk_tree_view_column_set_title(column, _("Type")); | |
453 gtk_tree_view_column_set_resizable(column, TRUE); | |
454 gtk_tree_view_column_set_sort_column_id(column, | |
455 STATUS_WINDOW_COLUMN_TYPE); | |
456 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); | |
457 renderer = gtk_cell_renderer_text_new(); | |
458 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
459 gtk_tree_view_column_add_attribute(column, renderer, "text", | |
460 STATUS_WINDOW_COLUMN_TYPE); | |
461 | |
462 column = gtk_tree_view_column_new(); | |
463 gtk_tree_view_column_set_title(column, _("Message")); | |
464 gtk_tree_view_column_set_resizable(column, TRUE); | |
465 gtk_tree_view_column_set_sort_column_id(column, | |
466 STATUS_WINDOW_COLUMN_MESSAGE); | |
467 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); | |
468 renderer = gtk_cell_renderer_text_new(); | |
469 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
470 gtk_tree_view_column_add_attribute(column, renderer, "text", | |
471 STATUS_WINDOW_COLUMN_MESSAGE); | |
10435 | 472 #if GTK_CHECK_VERSION(2,6,0) |
10502 | 473 g_object_set(renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL); |
10435 | 474 #endif |
475 | |
476 /* Enable CTRL+F searching */ | |
477 gtk_tree_view_set_search_column(GTK_TREE_VIEW(treeview), STATUS_WINDOW_COLUMN_TITLE); | |
478 gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(treeview), search_func, NULL, NULL); | |
10421 | 479 |
10422 | 480 /* Sort the title column by default */ |
481 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(dialog->model), | |
482 STATUS_WINDOW_COLUMN_TITLE, | |
483 GTK_SORT_ASCENDING); | |
484 | |
10421 | 485 /* Populate list */ |
486 populate_saved_status_list(dialog); | |
487 | |
488 return sw; | |
489 } | |
490 | |
491 static gboolean | |
492 configure_cb(GtkWidget *widget, GdkEventConfigure *event, StatusWindow *dialog) | |
493 { | |
494 if (GTK_WIDGET_VISIBLE(widget)) { | |
495 gaim_prefs_set_int("/gaim/gtk/status/dialog/width", event->width); | |
496 gaim_prefs_set_int("/gaim/gtk/status/dialog/height", event->height); | |
497 } | |
498 | |
499 return FALSE; | |
500 } | |
501 | |
502 void | |
503 gaim_gtk_status_window_show(void) | |
504 { | |
505 StatusWindow *dialog; | |
506 GtkWidget *bbox; | |
507 GtkWidget *button; | |
508 GtkWidget *list; | |
509 GtkWidget *vbox; | |
510 GtkWidget *win; | |
511 int width, height; | |
512 | |
513 if (status_window != NULL) { | |
514 gtk_window_present(GTK_WINDOW(status_window->window)); | |
515 return; | |
516 } | |
517 | |
518 status_window = dialog = g_new0(StatusWindow, 1); | |
519 | |
520 width = gaim_prefs_get_int("/gaim/gtk/status/dialog/width"); | |
521 height = gaim_prefs_get_int("/gaim/gtk/status/dialog/height"); | |
522 | |
523 dialog->window = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); | |
524 gtk_window_set_default_size(GTK_WINDOW(win), width, height); | |
525 gtk_window_set_role(GTK_WINDOW(win), "statuses"); | |
526 gtk_window_set_title(GTK_WINDOW(win), _("Saved Statuses")); | |
11243 | 527 gtk_container_set_border_width(GTK_CONTAINER(win), GAIM_HIG_BORDER); |
10421 | 528 |
529 g_signal_connect(G_OBJECT(win), "delete_event", | |
530 G_CALLBACK(status_window_destroy_cb), dialog); | |
531 g_signal_connect(G_OBJECT(win), "configure_event", | |
532 G_CALLBACK(configure_cb), dialog); | |
533 | |
534 /* Setup the vbox */ | |
11243 | 535 vbox = gtk_vbox_new(FALSE, GAIM_HIG_BORDER); |
10421 | 536 gtk_container_add(GTK_CONTAINER(win), vbox); |
537 gtk_widget_show(vbox); | |
538 | |
539 /* List of saved status states */ | |
540 list = create_saved_status_list(dialog); | |
541 gtk_box_pack_start(GTK_BOX(vbox), list, TRUE, TRUE, 0); | |
542 | |
543 /* Button box. */ | |
544 bbox = gtk_hbutton_box_new(); | |
11243 | 545 gtk_box_set_spacing(GTK_BOX(bbox), GAIM_HIG_BOX_SPACE); |
10421 | 546 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); |
547 gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, TRUE, 0); | |
548 gtk_widget_show(bbox); | |
549 | |
11811 | 550 /* Use button */ |
11832 | 551 button = gaim_pixbuf_button_from_stock(_("_Use"), GTK_STOCK_EXECUTE, |
552 GAIM_BUTTON_HORIZONTAL); | |
11811 | 553 dialog->use_button = button; |
554 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); | |
555 gtk_widget_set_sensitive(button, FALSE); | |
556 gtk_widget_show(button); | |
557 | |
558 g_signal_connect(G_OBJECT(button), "clicked", | |
559 G_CALLBACK(status_window_use_cb), dialog); | |
560 | |
10421 | 561 /* Add button */ |
562 button = gtk_button_new_from_stock(GTK_STOCK_ADD); | |
563 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); | |
564 gtk_widget_show(button); | |
565 | |
566 g_signal_connect(G_OBJECT(button), "clicked", | |
567 G_CALLBACK(status_window_add_cb), dialog); | |
568 | |
569 /* Modify button */ | |
570 button = gtk_button_new_from_stock(GAIM_STOCK_MODIFY); | |
571 dialog->modify_button = button; | |
572 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); | |
573 gtk_widget_set_sensitive(button, FALSE); | |
574 gtk_widget_show(button); | |
575 | |
576 g_signal_connect(G_OBJECT(button), "clicked", | |
577 G_CALLBACK(status_window_modify_cb), dialog); | |
578 | |
579 /* Delete button */ | |
580 button = gtk_button_new_from_stock(GTK_STOCK_DELETE); | |
581 dialog->delete_button = button; | |
582 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); | |
583 gtk_widget_set_sensitive(button, FALSE); | |
584 gtk_widget_show(button); | |
585 | |
586 g_signal_connect(G_OBJECT(button), "clicked", | |
587 G_CALLBACK(status_window_delete_cb), dialog); | |
588 | |
589 /* Close button */ | |
590 button = gtk_button_new_from_stock(GTK_STOCK_CLOSE); | |
591 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); | |
592 gtk_widget_show(button); | |
593 | |
594 g_signal_connect(G_OBJECT(button), "clicked", | |
595 G_CALLBACK(status_window_close_cb), dialog); | |
596 | |
597 gtk_widget_show(win); | |
598 } | |
599 | |
600 void | |
601 gaim_gtk_status_window_hide(void) | |
602 { | |
603 if (status_window == NULL) | |
604 return; | |
605 | |
606 if (status_window->window != NULL) | |
607 gtk_widget_destroy(status_window->window); | |
608 | |
609 g_free(status_window); | |
610 status_window = NULL; | |
611 } | |
612 | |
613 | |
614 /************************************************************************** | |
615 * Status editor | |
616 **************************************************************************/ | |
10420 | 617 |
10418 | 618 static gboolean |
619 status_editor_destroy_cb(GtkWidget *widget, GdkEvent *event, gpointer user_data) | |
620 { | |
10574 | 621 StatusEditor *dialog = user_data; |
10418 | 622 |
10574 | 623 g_free(dialog->original_title); |
10418 | 624 g_free(dialog); |
625 | |
626 return FALSE; | |
627 } | |
628 | |
629 static void | |
630 status_editor_cancel_cb(GtkButton *button, gpointer user_data) | |
631 { | |
10574 | 632 StatusEditor *dialog = user_data; |
10418 | 633 |
634 gtk_widget_destroy(dialog->window); | |
635 | |
10574 | 636 g_free(dialog->original_title); |
10418 | 637 g_free(dialog); |
638 } | |
639 | |
640 static void | |
641 status_editor_save_cb(GtkButton *button, gpointer user_data) | |
642 { | |
10420 | 643 StatusEditor *dialog = user_data; |
644 const char *title; | |
645 GaimStatusPrimitive type; | |
646 char *message, *unformatted; | |
12080 | 647 GaimSavedStatus *saved_status = NULL; |
648 GtkTreeModel *model; | |
649 GtkTreeIter iter; | |
10420 | 650 |
651 title = gtk_entry_get_text(dialog->title); | |
652 | |
653 /* | |
654 * If the title is already taken then show an error dialog and | |
655 * don't do anything. | |
656 */ | |
657 if ((gaim_savedstatus_find(title) != NULL) && | |
658 ((dialog->original_title == NULL) || (strcmp(title, dialog->original_title)))) | |
659 { | |
660 gaim_notify_error(NULL, NULL, _("Title already in use. You must " | |
661 "choose a unique title."), NULL); | |
662 return; | |
663 } | |
664 | |
665 type = gtk_option_menu_get_history(dialog->type); | |
666 message = gtk_imhtml_get_markup(dialog->message); | |
667 unformatted = gaim_markup_strip_html(message); | |
668 | |
669 /* | |
12080 | 670 * If we're editing an old status, then lookup the old status (it's |
671 * possible that it has been deleted or renamed or something, and | |
672 * no longer exists). | |
10420 | 673 */ |
674 if (dialog->original_title != NULL) | |
675 { | |
676 GtkTreeIter iter; | |
677 | |
12080 | 678 saved_status = gaim_savedstatus_find(dialog->original_title); |
10420 | 679 |
680 if (status_window_find_savedstatus(&iter, dialog->original_title)) | |
681 { | |
682 gtk_list_store_remove(status_window->model, &iter); | |
683 } | |
684 } | |
685 | |
12080 | 686 if (saved_status == NULL) |
687 { | |
688 /* This is a new status */ | |
689 saved_status = gaim_savedstatus_new(title, type); | |
690 } | |
691 else | |
692 { | |
693 /* Modify the old status */ | |
694 if (strcmp(title, dialog->original_title)) | |
695 gaim_savedstatus_set_title(saved_status, title); | |
696 gaim_savedstatus_set_type(saved_status, type); | |
697 } | |
698 | |
10420 | 699 if (*unformatted != '\0') |
12080 | 700 gaim_savedstatus_set_message(saved_status, message); |
701 | |
702 /* Set any substatuses */ | |
703 model = GTK_TREE_MODEL(dialog->model); | |
704 if (gtk_tree_model_get_iter_first(model, &iter)) | |
705 { | |
706 GaimAccount *account; | |
707 gboolean enabled; | |
708 char *id; | |
709 char *message; | |
710 GaimStatusType *type; | |
711 | |
712 gtk_tree_model_get(model, &iter, | |
713 STATUS_EDITOR_COLUMN_ACCOUNT, &account, | |
714 STATUS_EDITOR_COLUMN_ENABLE_SUBSTATUS, &enabled, | |
715 STATUS_EDITOR_COLUMN_STATUS_ID, &id, | |
716 STATUS_EDITOR_COLUMN_STATUS_MESSAGE, &message, | |
717 -1); | |
718 if (enabled) | |
719 { | |
720 type = gaim_account_get_status_type(account, id); | |
721 gaim_savedstatus_set_substatus(saved_status, account, type, message); | |
722 } | |
723 g_free(id); | |
724 g_free(message); | |
725 | |
726 while (gtk_tree_model_iter_next(model, &iter)) | |
727 { | |
728 gtk_tree_model_get(model, &iter, | |
729 STATUS_EDITOR_COLUMN_ACCOUNT, &account, | |
730 STATUS_EDITOR_COLUMN_ENABLE_SUBSTATUS, &enabled, | |
731 STATUS_EDITOR_COLUMN_STATUS_ID, &id, | |
732 STATUS_EDITOR_COLUMN_STATUS_MESSAGE, &message, | |
733 -1); | |
734 if (enabled) | |
735 { | |
736 type = gaim_account_get_status_type(account, id); | |
737 gaim_savedstatus_set_substatus(saved_status, account, type, message); | |
738 } | |
739 g_free(id); | |
740 g_free(message); | |
741 } | |
742 } | |
743 | |
10420 | 744 g_free(message); |
745 g_free(unformatted); | |
746 | |
747 gtk_widget_destroy(dialog->window); | |
10574 | 748 g_free(dialog->original_title); |
10420 | 749 g_free(dialog); |
750 | |
12080 | 751 if (status_window != NULL) |
752 add_status_to_saved_status_list(status_window->model, saved_status); | |
10420 | 753 } |
754 | |
755 static void | |
756 editor_title_changed_cb(GtkWidget *widget, gpointer user_data) | |
757 { | |
758 StatusEditor *dialog = user_data; | |
759 const gchar *text; | |
760 | |
761 text = gtk_entry_get_text(dialog->title); | |
762 | |
763 gtk_widget_set_sensitive(dialog->save_button, (*text != '\0')); | |
10418 | 764 } |
765 | |
766 static GtkWidget * | |
10419 | 767 create_status_type_menu(GaimStatusPrimitive type) |
10418 | 768 { |
10419 | 769 int i; |
10418 | 770 GtkWidget *dropdown; |
771 GtkWidget *menu; | |
772 GtkWidget *item; | |
773 | |
774 dropdown = gtk_option_menu_new(); | |
775 menu = gtk_menu_new(); | |
776 | |
10419 | 777 for (i = 0; i < GAIM_STATUS_NUM_PRIMITIVES; i++) |
778 { | |
779 item = gtk_menu_item_new_with_label(gaim_primitive_get_name_from_type(i)); | |
780 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); | |
781 gtk_widget_show(item); | |
782 } | |
10418 | 783 |
10419 | 784 gtk_menu_set_active(GTK_MENU(menu), type); |
10418 | 785 gtk_option_menu_set_menu(GTK_OPTION_MENU(dropdown), menu); |
786 gtk_widget_show(menu); | |
787 | |
788 return dropdown; | |
789 } | |
790 | |
12080 | 791 static void edit_substatus(StatusEditor *status_editor, GaimAccount *account); |
792 | |
793 static void | |
794 edit_substatus_cb(GtkTreeView *tv, GtkTreePath *path, GtkTreeViewColumn *col, gpointer user_data) | |
795 { | |
796 StatusEditor *dialog = user_data; | |
797 GtkTreeIter iter; | |
798 GaimAccount *account; | |
799 | |
800 gtk_tree_model_get_iter(GTK_TREE_MODEL(dialog->model), &iter, path); | |
801 gtk_tree_model_get(GTK_TREE_MODEL(dialog->model), &iter, | |
802 STATUS_EDITOR_COLUMN_ACCOUNT, &account, | |
803 -1); | |
804 | |
805 edit_substatus(dialog, account); | |
806 } | |
807 | |
808 static void | |
809 status_editor_substatus_cb(GtkCellRendererToggle *renderer, gchar *path_str, gpointer data) | |
810 { | |
811 StatusEditor *dialog = (StatusEditor *)data; | |
812 GtkTreeIter iter; | |
813 gboolean enabled; | |
814 GaimAccount *account; | |
815 | |
816 gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(dialog->model), &iter, path_str); | |
817 gtk_tree_model_get(GTK_TREE_MODEL(dialog->model), &iter, | |
818 STATUS_EDITOR_COLUMN_ACCOUNT, &account, | |
819 STATUS_EDITOR_COLUMN_ENABLE_SUBSTATUS, &enabled, | |
820 -1); | |
821 | |
822 enabled = !enabled; | |
823 | |
824 if (enabled) | |
825 { | |
826 edit_substatus(dialog, account); | |
827 } | |
828 else | |
829 { | |
830 GaimSavedStatus *saved_status; | |
831 | |
832 /* Remove the substatus */ | |
833 saved_status = gaim_savedstatus_find(dialog->original_title); | |
834 gaim_savedstatus_unset_substatus(saved_status, account); | |
835 gtk_list_store_set(dialog->model, &iter, | |
836 STATUS_EDITOR_COLUMN_ENABLE_SUBSTATUS, enabled, | |
837 STATUS_EDITOR_COLUMN_STATUS_ID, NULL, | |
838 STATUS_EDITOR_COLUMN_STATUS_NAME, NULL, | |
839 STATUS_EDITOR_COLUMN_STATUS_MESSAGE, NULL, | |
840 -1); | |
841 } | |
842 } | |
843 | |
10418 | 844 static void |
845 status_editor_add_columns(StatusEditor *dialog) | |
846 { | |
847 GtkCellRenderer *renderer; | |
848 GtkTreeViewColumn *column; | |
849 | |
12080 | 850 /* Enable Different status column */ |
10418 | 851 renderer = gtk_cell_renderer_toggle_new(); |
852 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(dialog->treeview), | |
12080 | 853 -1, _("Different"), |
10418 | 854 renderer, |
12080 | 855 "active", STATUS_EDITOR_COLUMN_ENABLE_SUBSTATUS, |
10418 | 856 NULL); |
857 column = gtk_tree_view_get_column(GTK_TREE_VIEW(dialog->treeview), 1); | |
858 g_signal_connect(G_OBJECT(renderer), "toggled", | |
12080 | 859 G_CALLBACK(status_editor_substatus_cb), dialog); |
10418 | 860 |
861 /* Screen Name column */ | |
862 column = gtk_tree_view_column_new(); | |
863 gtk_tree_view_column_set_resizable(column, TRUE); | |
864 gtk_tree_view_column_set_title(column, _("Screen Name")); | |
865 gtk_tree_view_insert_column(GTK_TREE_VIEW(dialog->treeview), column, -1); | |
866 gtk_tree_view_column_set_resizable(column, TRUE); | |
867 | |
868 /* Icon */ | |
869 renderer = gtk_cell_renderer_pixbuf_new(); | |
870 gtk_tree_view_column_pack_start(column, renderer, FALSE); | |
871 gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", | |
872 STATUS_EDITOR_COLUMN_ICON); | |
873 | |
874 /* Screen Name */ | |
875 renderer = gtk_cell_renderer_text_new(); | |
876 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
877 gtk_tree_view_column_add_attribute(column, renderer, "text", | |
878 STATUS_EDITOR_COLUMN_SCREENNAME); | |
12080 | 879 |
880 /* Status column */ | |
881 column = gtk_tree_view_column_new(); | |
882 gtk_tree_view_column_set_resizable(column, TRUE); | |
883 gtk_tree_view_column_set_title(column, _("Status")); | |
884 gtk_tree_view_insert_column(GTK_TREE_VIEW(dialog->treeview), column, -1); | |
885 gtk_tree_view_column_set_resizable(column, TRUE); | |
886 renderer = gtk_cell_renderer_text_new(); | |
887 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
888 gtk_tree_view_column_add_attribute(column, renderer, "text", | |
889 STATUS_EDITOR_COLUMN_STATUS_NAME); | |
890 | |
891 /* Message column */ | |
892 column = gtk_tree_view_column_new(); | |
893 gtk_tree_view_column_set_resizable(column, TRUE); | |
894 gtk_tree_view_column_set_title(column, _("Message")); | |
895 gtk_tree_view_insert_column(GTK_TREE_VIEW(dialog->treeview), column, -1); | |
896 gtk_tree_view_column_set_resizable(column, TRUE); | |
897 renderer = gtk_cell_renderer_text_new(); | |
898 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
899 gtk_tree_view_column_add_attribute(column, renderer, "text", | |
900 STATUS_EDITOR_COLUMN_STATUS_MESSAGE); | |
901 | |
902 g_signal_connect(G_OBJECT(dialog->treeview), "row-activated", | |
903 G_CALLBACK(edit_substatus_cb), dialog); | |
10418 | 904 } |
905 | |
906 static void | |
12080 | 907 status_editor_set_account(GtkListStore *store, GaimAccount *account, |
908 GtkTreeIter *iter, GaimSavedStatusSub *substatus) | |
10418 | 909 { |
910 GdkPixbuf *pixbuf; | |
911 GdkPixbuf *scale; | |
12080 | 912 const char *id = NULL, *name = NULL, *message = NULL; |
10418 | 913 |
914 scale = NULL; | |
915 | |
10884 | 916 pixbuf = gaim_gtk_create_prpl_icon(account); |
10418 | 917 |
918 if (pixbuf != NULL) | |
919 { | |
920 scale = gdk_pixbuf_scale_simple(pixbuf, 16, 16, GDK_INTERP_BILINEAR); | |
921 | |
11251 | 922 if (gaim_account_is_disconnected(account)) |
10418 | 923 gdk_pixbuf_saturate_and_pixelate(scale, scale, 0.0, FALSE); |
924 } | |
925 | |
12080 | 926 if (substatus != NULL) |
927 { | |
928 const GaimStatusType *type; | |
929 | |
930 type = gaim_savedstatus_substatus_get_type(substatus); | |
931 id = gaim_status_type_get_id(type); | |
932 name = gaim_status_type_get_name(type); | |
933 if (gaim_status_type_get_attr(type, "message")) | |
934 message = gaim_savedstatus_substatus_get_message(substatus); | |
935 } | |
936 | |
10418 | 937 gtk_list_store_set(store, iter, |
12080 | 938 STATUS_EDITOR_COLUMN_ACCOUNT, account, |
939 STATUS_EDITOR_COLUMN_ENABLE_SUBSTATUS, (substatus != NULL), | |
10418 | 940 STATUS_EDITOR_COLUMN_ICON, scale, |
941 STATUS_EDITOR_COLUMN_SCREENNAME, gaim_account_get_username(account), | |
12080 | 942 STATUS_EDITOR_COLUMN_STATUS_ID, id, |
943 STATUS_EDITOR_COLUMN_STATUS_NAME, name, | |
944 STATUS_EDITOR_COLUMN_STATUS_MESSAGE, message, | |
10418 | 945 -1); |
946 | |
947 if (pixbuf != NULL) g_object_unref(G_OBJECT(pixbuf)); | |
948 if (scale != NULL) g_object_unref(G_OBJECT(scale)); | |
949 } | |
950 | |
951 static void | |
12080 | 952 status_editor_add_account(StatusEditor *dialog, GaimAccount *account, |
953 GaimSavedStatusSub *substatus) | |
10418 | 954 { |
955 GtkTreeIter iter; | |
956 | |
957 gtk_list_store_append(dialog->model, &iter); | |
958 | |
12080 | 959 status_editor_set_account(dialog->model, account, &iter, substatus); |
10418 | 960 } |
961 | |
962 static void | |
12080 | 963 status_editor_populate_list(StatusEditor *dialog, GaimSavedStatus *saved_status) |
10418 | 964 { |
12080 | 965 GList *iter; |
966 GaimSavedStatusSub *substatus; | |
10418 | 967 |
968 gtk_list_store_clear(dialog->model); | |
969 | |
12080 | 970 for (iter = gaim_accounts_get_all(); iter != NULL; iter = iter->next) |
971 { | |
972 GaimAccount *account = (GaimAccount *)iter->data; | |
973 | |
974 if (saved_status != NULL) | |
975 substatus = gaim_savedstatus_get_substatus(saved_status, account); | |
976 else | |
977 substatus = NULL; | |
978 | |
979 status_editor_add_account(dialog, account, substatus); | |
980 } | |
10418 | 981 } |
982 | |
983 void | |
12080 | 984 gaim_gtk_status_editor_show(GaimSavedStatus *saved_status) |
10418 | 985 { |
986 StatusEditor *dialog; | |
987 GtkSizeGroup *sg; | |
988 GtkWidget *bbox; | |
989 GtkWidget *button; | |
990 GtkWidget *dbox; | |
11735 | 991 GtkWidget *expander; |
10418 | 992 GtkWidget *dropdown; |
993 GtkWidget *entry; | |
994 GtkWidget *frame; | |
995 GtkWidget *hbox; | |
996 GtkWidget *label; | |
997 GtkWidget *sw; | |
998 GtkWidget *text; | |
999 GtkWidget *toolbar; | |
1000 GtkWidget *vbox; | |
1001 GtkWidget *win; | |
1002 | |
1003 dialog = g_new0(StatusEditor, 1); | |
1004 | |
12080 | 1005 if (saved_status != NULL) |
1006 dialog->original_title = g_strdup(gaim_savedstatus_get_title(saved_status)); | |
10420 | 1007 |
10418 | 1008 dialog->window = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); |
1009 gtk_window_set_role(GTK_WINDOW(win), "status"); | |
1010 gtk_window_set_title(GTK_WINDOW(win), _("Status")); | |
1011 gtk_window_set_resizable(GTK_WINDOW(win), FALSE); | |
11243 | 1012 gtk_container_set_border_width(GTK_CONTAINER(win), GAIM_HIG_BORDER); |
10418 | 1013 |
1014 g_signal_connect(G_OBJECT(win), "delete_event", | |
1015 G_CALLBACK(status_editor_destroy_cb), dialog); | |
1016 | |
1017 /* Setup the vbox */ | |
11243 | 1018 vbox = gtk_vbox_new(FALSE, GAIM_HIG_BORDER); |
10418 | 1019 gtk_container_add(GTK_CONTAINER(win), vbox); |
1020 gtk_widget_show(vbox); | |
1021 | |
1022 sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); | |
1023 | |
1024 /* Title */ | |
11243 | 1025 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BOX_SPACE); |
10418 | 1026 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); |
1027 gtk_widget_show(hbox); | |
1028 | |
1029 label = gtk_label_new_with_mnemonic(_("_Title:")); | |
1030 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
1031 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); | |
1032 gtk_widget_show(label); | |
1033 gtk_size_group_add_widget(sg, label); | |
1034 | |
1035 entry = gtk_entry_new(); | |
10420 | 1036 dialog->title = GTK_ENTRY(entry); |
12080 | 1037 if (dialog->original_title != NULL) |
10420 | 1038 gtk_entry_set_text(GTK_ENTRY(entry), dialog->original_title); |
10418 | 1039 gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0); |
1040 gtk_widget_show(entry); | |
10420 | 1041 g_signal_connect(G_OBJECT(entry), "changed", |
1042 G_CALLBACK(editor_title_changed_cb), dialog); | |
10418 | 1043 |
1044 /* Status type */ | |
11243 | 1045 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BOX_SPACE); |
10418 | 1046 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); |
1047 gtk_widget_show(hbox); | |
1048 | |
1049 label = gtk_label_new_with_mnemonic(_("_Status:")); | |
1050 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
1051 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); | |
1052 gtk_widget_show(label); | |
1053 gtk_size_group_add_widget(sg, label); | |
1054 | |
12080 | 1055 if (saved_status != NULL) |
1056 dropdown = create_status_type_menu(gaim_savedstatus_get_type(saved_status)); | |
10419 | 1057 else |
1058 dropdown = create_status_type_menu(GAIM_STATUS_AWAY); | |
10420 | 1059 dialog->type = GTK_OPTION_MENU(dropdown); |
10418 | 1060 gtk_box_pack_start(GTK_BOX(hbox), dropdown, TRUE, TRUE, 0); |
1061 gtk_widget_show(dropdown); | |
1062 | |
1063 /* Status message */ | |
11243 | 1064 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BOX_SPACE); |
10418 | 1065 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); |
1066 gtk_widget_show(hbox); | |
1067 | |
1068 label = gtk_label_new_with_mnemonic(_("_Message:")); | |
1069 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
1070 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); | |
1071 gtk_widget_show(label); | |
1072 gtk_size_group_add_widget(sg, label); | |
1073 | |
1074 frame = gaim_gtk_create_imhtml(TRUE, &text, &toolbar); | |
10420 | 1075 dialog->message = GTK_IMHTML(text); |
10418 | 1076 gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0); |
1077 gtk_widget_show(frame); | |
1078 | |
12080 | 1079 if ((saved_status != NULL) && (gaim_savedstatus_get_message(saved_status) != NULL)) |
10419 | 1080 gtk_imhtml_append_text(GTK_IMHTML(text), |
12080 | 1081 gaim_savedstatus_get_message(saved_status), 0); |
10419 | 1082 |
12080 | 1083 /* Different status message expander */ |
11735 | 1084 expander = gtk_expander_new_with_mnemonic(_("Use a _different status for some accounts")); |
1085 gtk_box_pack_start(GTK_BOX(vbox), expander, FALSE, FALSE, 0); | |
1086 gtk_widget_show(expander); | |
10418 | 1087 |
11735 | 1088 /* Setup the box that the expander will cover */ |
11243 | 1089 dbox = gtk_vbox_new(FALSE, GAIM_HIG_CAT_SPACE); |
11735 | 1090 gtk_container_add(GTK_CONTAINER(expander), dbox); |
1091 gtk_widget_show(dbox); | |
10418 | 1092 |
12080 | 1093 /* Different status message treeview */ |
10418 | 1094 sw = gtk_scrolled_window_new(NULL, NULL); |
1095 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), | |
1096 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); | |
1097 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), | |
1098 GTK_SHADOW_IN); | |
1099 gtk_box_pack_start(GTK_BOX(dbox), sw, TRUE, TRUE, 0); | |
1100 gtk_widget_show(sw); | |
1101 | |
1102 /* Create the list model */ | |
1103 dialog->model = gtk_list_store_new(STATUS_EDITOR_NUM_COLUMNS, | |
12080 | 1104 G_TYPE_POINTER, |
10418 | 1105 G_TYPE_BOOLEAN, |
12080 | 1106 GDK_TYPE_PIXBUF, |
1107 G_TYPE_STRING, | |
1108 G_TYPE_STRING, | |
1109 G_TYPE_STRING, | |
1110 G_TYPE_STRING); | |
10418 | 1111 |
1112 /* Create the treeview */ | |
1113 dialog->treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(dialog->model)); | |
1114 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(dialog->treeview), TRUE); | |
1115 gtk_widget_set_size_request(dialog->treeview, 400, 250); | |
1116 gtk_container_add(GTK_CONTAINER(sw), dialog->treeview); | |
1117 gtk_widget_show(dialog->treeview); | |
1118 | |
1119 /* Add columns */ | |
1120 status_editor_add_columns(dialog); | |
1121 | |
1122 /* Populate list */ | |
12080 | 1123 status_editor_populate_list(dialog, saved_status); |
10418 | 1124 |
1125 /* Button box */ | |
1126 bbox = gtk_hbutton_box_new(); | |
11243 | 1127 gtk_box_set_spacing(GTK_BOX(bbox), GAIM_HIG_BOX_SPACE); |
10418 | 1128 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); |
1129 gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, TRUE, 0); | |
1130 gtk_widget_show(bbox); | |
1131 | |
1132 /* Cancel button */ | |
1133 button = gtk_button_new_from_stock(GTK_STOCK_CANCEL); | |
1134 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); | |
1135 gtk_widget_show(button); | |
1136 | |
1137 g_signal_connect(G_OBJECT(button), "clicked", | |
1138 G_CALLBACK(status_editor_cancel_cb), dialog); | |
1139 | |
1140 /* Save button */ | |
1141 button = gtk_button_new_from_stock(GTK_STOCK_SAVE); | |
10420 | 1142 dialog->save_button = button; |
10418 | 1143 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); |
12080 | 1144 if (dialog->title == NULL) |
1145 gtk_widget_set_sensitive(button, FALSE); | |
10418 | 1146 gtk_widget_show(button); |
1147 | |
1148 g_signal_connect(G_OBJECT(button), "clicked", | |
1149 G_CALLBACK(status_editor_save_cb), dialog); | |
1150 | |
1151 gtk_widget_show(win); | |
1152 } | |
1153 | |
1154 | |
10421 | 1155 /************************************************************************** |
12080 | 1156 * SubStatus editor |
1157 **************************************************************************/ | |
1158 | |
1159 static void | |
1160 substatus_selection_changed_cb(GtkComboBox *box, gpointer user_data) | |
1161 { | |
1162 SubStatusEditor *select = user_data; | |
1163 GtkTreeIter iter; | |
1164 GaimAccount *account; | |
1165 char *id; | |
1166 GaimStatusType *type; | |
1167 | |
1168 if (!gtk_combo_box_get_active_iter(box, &iter)) | |
1169 return; | |
1170 gtk_tree_model_get(GTK_TREE_MODEL(select->model), &iter, | |
1171 SUBSTATUS_COLUMN_ACCOUNT, &account, | |
1172 SUBSTATUS_COLUMN_STATUS_ID, &id, | |
1173 -1); | |
1174 type = gaim_account_get_status_type(account, id); | |
1175 g_free(id); | |
1176 | |
1177 if (gaim_status_type_get_attr(type, "message") == NULL) | |
1178 { | |
1179 gtk_widget_set_sensitive(GTK_WIDGET(select->message), FALSE); | |
1180 gtk_widget_set_sensitive(GTK_WIDGET(select->toolbar), FALSE); | |
1181 } | |
1182 else | |
1183 { | |
1184 gtk_widget_set_sensitive(GTK_WIDGET(select->message), TRUE); | |
1185 gtk_widget_set_sensitive(GTK_WIDGET(select->toolbar), TRUE); | |
1186 } | |
1187 } | |
1188 | |
1189 static gboolean | |
1190 substatus_editor_destroy_cb(GtkWidget *widget, GdkEvent *event, gpointer user_data) | |
1191 { | |
1192 SubStatusEditor *dialog = user_data; | |
1193 | |
1194 g_free(dialog); | |
1195 | |
1196 return FALSE; | |
1197 } | |
1198 | |
1199 void | |
1200 substatus_editor_cancel_cb(GtkButton *button, gpointer user_data) | |
1201 { | |
1202 SubStatusEditor *dialog = user_data; | |
1203 | |
1204 gtk_widget_destroy(dialog->window); | |
1205 | |
1206 g_free(dialog); | |
1207 } | |
1208 | |
1209 static gboolean | |
1210 status_editor_find_account_in_treemodel(GtkTreeIter *iter, | |
1211 StatusEditor *status_editor, | |
1212 GaimAccount *account) | |
1213 { | |
1214 GtkTreeModel *model; | |
1215 GaimAccount *cur; | |
1216 | |
1217 g_return_val_if_fail(status_editor != NULL, FALSE); | |
1218 g_return_val_if_fail(account != NULL, FALSE); | |
1219 | |
1220 model = GTK_TREE_MODEL(status_editor->model); | |
1221 | |
1222 if (!gtk_tree_model_get_iter_first(model, iter)) | |
1223 return FALSE; | |
1224 | |
1225 gtk_tree_model_get(model, iter, STATUS_EDITOR_COLUMN_ACCOUNT, &cur, -1); | |
1226 if (cur == account) | |
1227 return TRUE; | |
1228 | |
1229 while (gtk_tree_model_iter_next(model, iter)) | |
1230 { | |
1231 gtk_tree_model_get(model, iter, STATUS_EDITOR_COLUMN_ACCOUNT, &cur, -1); | |
1232 if (cur == account) | |
1233 return TRUE; | |
1234 } | |
1235 | |
1236 return FALSE; | |
1237 } | |
1238 | |
1239 void | |
1240 substatus_editor_ok_cb(GtkButton *button, gpointer user_data) | |
1241 { | |
1242 SubStatusEditor *dialog = user_data; | |
1243 StatusEditor *status_editor; | |
1244 GtkTreeIter iter; | |
1245 GaimAccount *account; | |
1246 GaimStatusType *type; | |
1247 char *id = NULL; | |
1248 char *message = NULL; | |
1249 const char *name = NULL; | |
1250 | |
1251 gtk_combo_box_get_active_iter(dialog->box, &iter); | |
1252 gtk_tree_model_get(GTK_TREE_MODEL(dialog->model), &iter, | |
1253 SUBSTATUS_COLUMN_ACCOUNT, &account, | |
1254 SUBSTATUS_COLUMN_STATUS_ID, &id, | |
1255 -1); | |
1256 type = gaim_account_get_status_type(account, id); | |
1257 if (gaim_status_type_get_attr(type, "message") != NULL) | |
1258 message = gtk_imhtml_get_text(GTK_IMHTML(dialog->message), NULL, NULL); | |
1259 name = gaim_status_type_get_name(type); | |
1260 | |
1261 status_editor = dialog->status_editor; | |
1262 | |
1263 if (status_editor_find_account_in_treemodel(&iter, status_editor, account)) | |
1264 { | |
1265 gtk_list_store_set(status_editor->model, &iter, | |
1266 STATUS_EDITOR_COLUMN_ENABLE_SUBSTATUS, TRUE, | |
1267 STATUS_EDITOR_COLUMN_STATUS_ID, id, | |
1268 STATUS_EDITOR_COLUMN_STATUS_NAME, name, | |
1269 STATUS_EDITOR_COLUMN_STATUS_MESSAGE, message, | |
1270 -1); | |
1271 } | |
1272 | |
1273 gtk_widget_destroy(dialog->window); | |
1274 g_free(id); | |
1275 g_free(message); | |
1276 g_free(dialog); | |
1277 } | |
1278 | |
1279 static void | |
1280 edit_substatus(StatusEditor *status_editor, GaimAccount *account) | |
1281 { | |
1282 char *tmp; | |
1283 SubStatusEditor *dialog; | |
1284 GtkSizeGroup *sg; | |
1285 GtkWidget *bbox; | |
1286 GtkWidget *button; | |
1287 GtkWidget *combo; | |
1288 GtkWidget *hbox; | |
1289 GtkWidget *frame; | |
1290 GtkWidget *label; | |
1291 GtkWidget *text; | |
1292 GtkWidget *toolbar; | |
1293 GtkWidget *vbox; | |
1294 GtkWidget *win; | |
1295 GtkTreeIter iter; | |
1296 GtkCellRenderer *rend; | |
1297 const char *id = NULL; | |
1298 const GList *list; | |
1299 gboolean select = FALSE; | |
1300 | |
1301 g_return_if_fail(status_editor != NULL); | |
1302 g_return_if_fail(account != NULL); | |
1303 | |
1304 dialog = g_new0(SubStatusEditor, 1); | |
1305 dialog->status_editor = status_editor; | |
1306 | |
1307 dialog->window = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); | |
1308 gtk_window_set_role(GTK_WINDOW(win), "substatus"); | |
1309 tmp = g_strdup_printf(_("Status for %s"), gaim_account_get_username(account)); | |
1310 gtk_window_set_title(GTK_WINDOW(win), tmp); | |
1311 g_free(tmp); | |
1312 gtk_window_set_resizable(GTK_WINDOW(win), FALSE); | |
1313 gtk_container_set_border_width(GTK_CONTAINER(win), GAIM_HIG_BORDER); | |
1314 | |
1315 g_signal_connect(G_OBJECT(win), "delete_event", | |
1316 G_CALLBACK(substatus_editor_destroy_cb), dialog); | |
1317 | |
1318 /* Setup the vbox */ | |
1319 vbox = gtk_vbox_new(FALSE, GAIM_HIG_BORDER); | |
1320 gtk_container_add(GTK_CONTAINER(win), vbox); | |
1321 gtk_widget_show(vbox); | |
1322 | |
1323 sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); | |
1324 | |
1325 /* Status type */ | |
1326 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BOX_SPACE); | |
1327 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); | |
1328 gtk_widget_show(hbox); | |
1329 | |
1330 label = gtk_label_new_with_mnemonic(_("_Status:")); | |
1331 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
1332 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); | |
1333 gtk_widget_show(label); | |
1334 gtk_size_group_add_widget(sg, label); | |
1335 | |
1336 dialog->model = gtk_list_store_new(SUBSTATUS_NUM_COLUMNS, | |
1337 G_TYPE_POINTER, | |
1338 GDK_TYPE_PIXBUF, | |
1339 G_TYPE_STRING, | |
1340 G_TYPE_STRING); | |
1341 combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(dialog->model)); | |
1342 dialog->box = GTK_COMBO_BOX(combo); | |
1343 | |
1344 rend = GTK_CELL_RENDERER(gtk_cell_renderer_pixbuf_new()); | |
1345 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), rend, FALSE); | |
1346 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), rend, | |
1347 "pixbuf", SUBSTATUS_COLUMN_ICON, NULL); | |
1348 | |
1349 rend = GTK_CELL_RENDERER(gtk_cell_renderer_text_new()); | |
1350 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), rend, TRUE); | |
1351 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), rend, | |
1352 "text", SUBSTATUS_COLUMN_STATUS_NAME, NULL); | |
1353 | |
1354 g_signal_connect(G_OBJECT(combo), "changed", | |
1355 G_CALLBACK(substatus_selection_changed_cb), dialog); | |
1356 | |
1357 gtk_box_pack_start(GTK_BOX(hbox), combo, FALSE, FALSE, 0); | |
1358 gtk_widget_show(combo); | |
1359 | |
1360 /* Status mesage */ | |
1361 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BOX_SPACE); | |
1362 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); | |
1363 gtk_widget_show(hbox); | |
1364 | |
1365 label = gtk_label_new_with_mnemonic(_("_Message:")); | |
1366 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
1367 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); | |
1368 gtk_widget_show(label); | |
1369 gtk_size_group_add_widget(sg, label); | |
1370 | |
1371 frame = gaim_gtk_create_imhtml(TRUE, &text, &toolbar); | |
1372 dialog->message = GTK_IMHTML(text); | |
1373 dialog->toolbar = GTK_IMHTMLTOOLBAR(toolbar); | |
1374 gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0); | |
1375 gtk_widget_show(frame); | |
1376 | |
1377 /* Button box */ | |
1378 bbox = gtk_hbutton_box_new(); | |
1379 gtk_box_set_spacing(GTK_BOX(bbox), GAIM_HIG_BOX_SPACE); | |
1380 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); | |
1381 gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, TRUE, 0); | |
1382 gtk_widget_show(bbox); | |
1383 | |
1384 /* Cancel button */ | |
1385 button = gtk_button_new_from_stock(GTK_STOCK_CANCEL); | |
1386 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); | |
1387 gtk_widget_show(button); | |
1388 | |
1389 g_signal_connect(G_OBJECT(button), "clicked", | |
1390 G_CALLBACK(substatus_editor_cancel_cb), dialog); | |
1391 | |
1392 /* OK button */ | |
1393 button = gtk_button_new_from_stock(GTK_STOCK_OK); | |
1394 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); | |
1395 gtk_widget_show(button); | |
1396 | |
1397 g_signal_connect(G_OBJECT(button), "clicked", | |
1398 G_CALLBACK(substatus_editor_ok_cb), dialog); | |
1399 | |
1400 /* Seed the input widgets with the current values */ | |
1401 /* TODO: Get the current values from our parent's list store, not the saved_status! */ | |
1402 if (status_editor->original_title != NULL) | |
1403 { | |
1404 GaimSavedStatus *saved_status = NULL; | |
1405 GaimSavedStatusSub *substatus = NULL; | |
1406 | |
1407 saved_status = gaim_savedstatus_find(status_editor->original_title); | |
1408 if (saved_status != NULL) | |
1409 substatus = gaim_savedstatus_get_substatus(saved_status, account); | |
1410 | |
1411 if (substatus != NULL) | |
1412 { | |
1413 gtk_imhtml_append_text(dialog->message, | |
1414 gaim_savedstatus_substatus_get_message(substatus), | |
1415 0); | |
1416 id = gaim_status_type_get_id(gaim_savedstatus_substatus_get_type(substatus)); | |
1417 } | |
1418 } | |
1419 | |
1420 for (list = gaim_account_get_status_types(account); list; list = list->next) | |
1421 { | |
1422 GaimStatusType *status_type; | |
1423 GdkPixbuf *pixbuf, *scale = NULL; | |
1424 const char *id, *name; | |
1425 | |
1426 status_type = list->data; | |
1427 id = gaim_status_type_get_id(status_type); | |
1428 pixbuf = gaim_gtk_create_prpl_icon_with_status(account, status_type); | |
1429 if (pixbuf != NULL) | |
1430 scale = gdk_pixbuf_scale_simple(pixbuf, 16, 16, GDK_INTERP_BILINEAR); | |
1431 name = gaim_status_type_get_name(status_type); | |
1432 | |
1433 gtk_list_store_append(dialog->model, &iter); | |
1434 gtk_list_store_set(dialog->model, &iter, | |
1435 SUBSTATUS_COLUMN_ACCOUNT, account, | |
1436 SUBSTATUS_COLUMN_ICON, scale, | |
1437 SUBSTATUS_COLUMN_STATUS_ID, id, | |
1438 SUBSTATUS_COLUMN_STATUS_NAME, name, | |
1439 -1); | |
1440 if (id && !strcmp(id, gaim_status_type_get_id(status_type))) | |
1441 { | |
1442 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(combo), &iter); | |
1443 select = TRUE; | |
1444 } | |
1445 } | |
1446 | |
1447 if (!select) | |
1448 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0); | |
1449 | |
1450 gtk_widget_show(win); | |
1451 } | |
1452 | |
1453 | |
1454 /************************************************************************** | |
10814
364a2ef907ae
[gaim-migrate @ 12468]
Luke Schierer <lschiere@pidgin.im>
parents:
10732
diff
changeset
|
1455 * GTK+ saved status glue |
10421 | 1456 **************************************************************************/ |
10418 | 1457 |
1458 void * | |
1459 gaim_gtk_status_get_handle() | |
1460 { | |
1461 static int handle; | |
1462 | |
1463 return &handle; | |
1464 } | |
1465 | |
1466 void | |
1467 gaim_gtk_status_init(void) | |
1468 { | |
1469 gaim_prefs_add_none("/gaim/gtk/status"); | |
1470 gaim_prefs_add_none("/gaim/gtk/status/dialog"); | |
1471 gaim_prefs_add_int("/gaim/gtk/status/dialog/width", 550); | |
1472 gaim_prefs_add_int("/gaim/gtk/status/dialog/height", 250); | |
1473 } | |
1474 | |
1475 void | |
1476 gaim_gtk_status_uninit(void) | |
1477 { | |
1478 gaim_gtk_status_window_hide(); | |
1479 } |