Mercurial > pidgin
annotate src/gtkstatusselector.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 | 364a2ef907ae |
children |
rev | line source |
---|---|
10178 | 1 /** |
10297
ec140184437b
[gaim-migrate @ 11480]
Luke Schierer <lschiere@pidgin.im>
parents:
10249
diff
changeset
|
2 * @file gtkstatusselector.c GTK+ Status selector widget |
10178 | 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 #include "internal.h" | |
26 #include "gtkgaim.h" | |
27 #include "gtkimhtml.h" | |
10447 | 28 #include "gtksavedstatuses.h" |
10178 | 29 #include "gtkstatusselector.h" |
30 #include "gtkutils.h" | |
31 | |
32 #include "account.h" | |
33 #include "debug.h" | |
34 #include "prefs.h" | |
35 | |
36 struct _GaimGtkStatusSelectorPrivate | |
37 { | |
38 GtkWidget *combo; | |
39 GtkWidget *entry; | |
10191 | 40 GtkWidget *frame; |
10178 | 41 |
10347 | 42 GtkWidget *optmenu; |
43 GtkWidget *menu; | |
44 GtkSizeGroup *sg; | |
45 | |
10178 | 46 GtkListStore *model; |
10199 | 47 |
48 guint entry_timer; | |
10178 | 49 }; |
50 | |
51 enum | |
52 { | |
53 COLUMN_STATUS_TYPE_ID, | |
54 COLUMN_ICON, | |
55 COLUMN_NAME, | |
56 NUM_COLUMNS | |
57 }; | |
58 | |
10347 | 59 #define GAIM_SELECTOR_TEXT "gaim-text" |
60 #define GAIM_SELECTOR_STATUS_TYPE_ID "gaim-status-type-id" | |
61 | |
10178 | 62 static void gaim_gtk_status_selector_class_init(GaimGtkStatusSelectorClass *klass); |
63 static void gaim_gtk_status_selector_init(GaimGtkStatusSelector *selector); | |
64 static void gaim_gtk_status_selector_finalize(GObject *obj); | |
65 static void gaim_gtk_status_selector_destroy(GtkObject *obj); | |
66 static void status_switched_cb(GtkWidget *combo, GaimGtkStatusSelector *selector); | |
10199 | 67 static gboolean key_press_cb(GtkWidget *entry, GdkEventKey *event, gpointer user_data); |
10178 | 68 static void signed_on_off_cb(GaimConnection *gc, GaimGtkStatusSelector *selector); |
69 static void rebuild_list(GaimGtkStatusSelector *selector); | |
70 | |
71 static GtkVBox *parent_class = NULL; | |
72 | |
73 GType | |
74 gaim_gtk_status_selector_get_type(void) | |
75 { | |
76 static GType type = 0; | |
77 | |
78 if (!type) | |
79 { | |
80 static const GTypeInfo info = | |
81 { | |
82 sizeof(GaimGtkStatusSelectorClass), | |
83 NULL, | |
84 NULL, | |
85 (GClassInitFunc)gaim_gtk_status_selector_class_init, | |
86 NULL, | |
87 NULL, | |
88 sizeof(GaimGtkStatusSelector), | |
89 0, | |
90 (GInstanceInitFunc)gaim_gtk_status_selector_init | |
91 }; | |
92 | |
93 type = g_type_register_static(GTK_TYPE_VBOX, | |
94 "GaimGtkStatusSelector", &info, 0); | |
95 } | |
96 | |
97 return type; | |
98 } | |
99 | |
100 static void | |
101 gaim_gtk_status_selector_class_init(GaimGtkStatusSelectorClass *klass) | |
102 { | |
103 GObjectClass *gobject_class; | |
104 GtkObjectClass *object_class; | |
105 | |
106 parent_class = g_type_class_peek_parent(klass); | |
107 | |
108 gobject_class = G_OBJECT_CLASS(klass); | |
109 object_class = GTK_OBJECT_CLASS(klass); | |
110 | |
111 gobject_class->finalize = gaim_gtk_status_selector_finalize; | |
112 | |
113 object_class->destroy = gaim_gtk_status_selector_destroy; | |
114 } | |
115 | |
116 static void | |
117 gaim_gtk_status_selector_init(GaimGtkStatusSelector *selector) | |
118 { | |
10225 | 119 #if GTK_CHECK_VERSION(2,4,0) |
10178 | 120 GtkWidget *combo; |
10347 | 121 GtkCellRenderer *renderer; |
122 #else | |
123 GtkWidget *optmenu; | |
124 #endif | |
10178 | 125 GtkWidget *entry; |
10191 | 126 GtkWidget *toolbar; |
127 GtkWidget *frame; | |
10178 | 128 |
129 selector->priv = g_new0(GaimGtkStatusSelectorPrivate, 1); | |
130 | |
131 #if GTK_CHECK_VERSION(2,4,0) | |
132 selector->priv->model = gtk_list_store_new(NUM_COLUMNS, G_TYPE_POINTER, | |
10347 | 133 GDK_TYPE_PIXBUF, G_TYPE_STRING); |
10178 | 134 |
135 combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(selector->priv->model)); | |
136 selector->priv->combo = combo; | |
137 | |
138 g_object_unref(G_OBJECT(selector->priv->model)); | |
139 | |
140 renderer = gtk_cell_renderer_pixbuf_new(); | |
141 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), renderer, FALSE); | |
142 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), renderer, | |
143 "pixbuf", COLUMN_ICON, | |
144 NULL); | |
145 | |
146 renderer = gtk_cell_renderer_text_new(); | |
147 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), renderer, TRUE); | |
148 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), renderer, | |
149 "text", COLUMN_NAME, | |
150 NULL); | |
151 | |
152 g_signal_connect(G_OBJECT(combo), "changed", | |
153 G_CALLBACK(status_switched_cb), selector); | |
154 | |
155 /* TODO */ | |
156 | |
157 | |
158 gtk_widget_show(combo); | |
159 gtk_box_pack_start(GTK_BOX(selector), combo, FALSE, FALSE, 0); | |
160 | |
10347 | 161 |
10814
364a2ef907ae
[gaim-migrate @ 12468]
Luke Schierer <lschiere@pidgin.im>
parents:
10504
diff
changeset
|
162 #else /* GTK+ < 2.4.0 */ |
10347 | 163 selector->priv->optmenu = optmenu = gtk_option_menu_new(); |
164 gtk_widget_show(optmenu); | |
165 | |
166 selector->priv->menu = gtk_menu_new(); | |
167 gtk_widget_show(selector->priv->menu); | |
168 gtk_option_menu_set_menu(GTK_OPTION_MENU(optmenu), selector->priv->menu); | |
169 | |
170 selector->priv->sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); | |
171 | |
172 g_signal_connect(G_OBJECT(optmenu), "changed", | |
173 G_CALLBACK(status_switched_cb), selector); | |
174 | |
175 gtk_box_pack_start(GTK_BOX(selector), optmenu, FALSE, FALSE, 0); | |
176 #endif | |
177 | |
10191 | 178 frame = gaim_gtk_create_imhtml(TRUE, &entry, &toolbar); |
179 selector->priv->entry = entry; | |
180 selector->priv->frame = frame; | |
181 gtk_widget_set_name(entry, "gaim_gtkstatusselector_imhtml"); | |
182 gtk_box_pack_start(GTK_BOX(selector), frame, TRUE, TRUE, 0); | |
183 gtk_widget_hide(toolbar); | |
10178 | 184 |
10199 | 185 g_signal_connect(G_OBJECT(entry), "key_press_event", |
10347 | 186 G_CALLBACK(key_press_cb), selector); |
10178 | 187 gaim_signal_connect(gaim_connections_get_handle(), "signed-on", |
10347 | 188 selector, GAIM_CALLBACK(signed_on_off_cb), |
189 selector); | |
10178 | 190 gaim_signal_connect(gaim_connections_get_handle(), "signed-off", |
10347 | 191 selector, GAIM_CALLBACK(signed_on_off_cb), |
192 selector); | |
10404 | 193 |
10178 | 194 rebuild_list(selector); |
195 } | |
196 | |
197 static void | |
198 gaim_gtk_status_selector_finalize(GObject *obj) | |
199 { | |
200 GaimGtkStatusSelector *selector; | |
201 | |
202 g_return_if_fail(obj != NULL); | |
203 g_return_if_fail(GAIM_GTK_IS_STATUS_SELECTOR(obj)); | |
204 | |
205 selector = GAIM_GTK_STATUS_SELECTOR(obj); | |
206 | |
10347 | 207 if (selector->priv->sg) { |
208 g_object_unref(selector->priv->sg); | |
209 selector->priv->sg = NULL; | |
210 } | |
211 | |
10178 | 212 g_free(selector->priv); |
213 | |
214 if (G_OBJECT_CLASS(parent_class)->finalize) | |
215 G_OBJECT_CLASS(parent_class)->finalize(obj); | |
216 } | |
217 | |
218 static void | |
219 gaim_gtk_status_selector_destroy(GtkObject *obj) | |
220 { | |
221 GaimGtkStatusSelector *selector; | |
222 | |
223 g_return_if_fail(obj != NULL); | |
224 g_return_if_fail(GAIM_GTK_IS_STATUS_SELECTOR(obj)); | |
225 | |
226 selector = GAIM_GTK_STATUS_SELECTOR(obj); | |
227 | |
10187 | 228 gaim_signals_disconnect_by_handle(selector); |
10249 | 229 if (selector->priv->entry_timer != 0) |
230 gaim_timeout_remove(selector->priv->entry_timer); | |
10187 | 231 |
10178 | 232 if (GTK_OBJECT_CLASS(parent_class)->destroy) |
233 GTK_OBJECT_CLASS(parent_class)->destroy(obj); | |
234 } | |
235 | |
10347 | 236 static gboolean |
10504 | 237 get_selected_data(GaimGtkStatusSelector *selector, char **text, const char **status_type_id) |
10347 | 238 { |
10225 | 239 #if GTK_CHECK_VERSION(2,4,0) |
10347 | 240 GtkTreeIter iter; |
241 | |
242 if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(selector->priv->combo), | |
243 &iter)) | |
244 return FALSE; | |
245 | |
246 gtk_tree_model_get(GTK_TREE_MODEL(selector->priv->model), &iter, | |
247 COLUMN_NAME, text, | |
248 COLUMN_STATUS_TYPE_ID, status_type_id, | |
249 -1); | |
250 return TRUE; | |
251 #else | |
252 GtkWidget *item; | |
253 int i; | |
254 GList *l; | |
255 | |
256 i = gtk_option_menu_get_history(GTK_OPTION_MENU(selector->priv->optmenu)); | |
257 l = GTK_MENU_SHELL(selector->priv->menu)->children; | |
258 item = g_list_nth_data(l, i); | |
10504 | 259 *text = g_strdup(g_object_get_data(G_OBJECT(item), GAIM_SELECTOR_TEXT)); |
10347 | 260 *status_type_id = g_object_get_data(G_OBJECT(item), GAIM_SELECTOR_STATUS_TYPE_ID); |
261 return TRUE; | |
262 #endif | |
263 } | |
264 | |
10447 | 265 /* |
10455 | 266 * TODO: Is it possible to remove of the duplication in this |
267 * function and insert_text_timeout_cb()? | |
10447 | 268 */ |
10178 | 269 static void |
270 status_switched_cb(GtkWidget *combo, GaimGtkStatusSelector *selector) | |
271 { | |
10347 | 272 const char *status_type_id = NULL; |
10504 | 273 char *text = NULL; |
10178 | 274 |
10455 | 275 /* Reset the status selector */ |
276 if (selector->priv->entry_timer != 0) | |
277 gaim_timeout_remove(selector->priv->entry_timer); | |
278 gtk_widget_hide(selector->priv->frame); | |
279 gtk_widget_set_sensitive(selector->priv->frame, FALSE); | |
280 | |
10347 | 281 if (!get_selected_data(selector, &text, &status_type_id)) |
10188 | 282 return; |
10178 | 283 |
10191 | 284 if (status_type_id == NULL) |
285 { | |
286 if (!strcmp(text, _("New Status"))) | |
287 { | |
10447 | 288 gaim_gtk_status_editor_show(NULL); |
10191 | 289 } |
290 } | |
10197 | 291 else |
10188 | 292 { |
10199 | 293 /* |
294 * If the chosen status does not require a message, then set the | |
295 * status immediately. Otherwise just register a timeout and the | |
296 * status will be set whenever the user stops typing the message. | |
297 */ | |
298 GList *l; | |
10188 | 299 GtkTextBuffer *buffer; |
10455 | 300 gboolean has_message = FALSE; |
10178 | 301 |
10188 | 302 buffer = |
303 gtk_text_view_get_buffer(GTK_TEXT_VIEW(selector->priv->entry)); | |
304 | |
10199 | 305 gtk_text_buffer_set_text(buffer, text, -1); |
306 | |
10400 | 307 for (l = gaim_accounts_get_all(); l != NULL; l = l->next) |
10199 | 308 { |
10400 | 309 GaimAccount *account = (GaimAccount*)l->data; |
10199 | 310 GaimStatusType *status_type; |
10404 | 311 |
10400 | 312 if (!gaim_account_get_enabled(account, GAIM_GTK_UI)) |
313 continue; | |
10199 | 314 |
10455 | 315 status_type = gaim_account_get_status_type(account, status_type_id); |
10199 | 316 |
317 if (status_type == NULL) | |
318 continue; | |
319 | |
320 if (gaim_status_type_get_attr(status_type, "message") != NULL) | |
321 { | |
10455 | 322 has_message = TRUE; |
10199 | 323 } |
324 else | |
325 { | |
10455 | 326 gaim_account_set_status(account, status_type_id, TRUE, NULL); |
10199 | 327 } |
328 } | |
329 | |
10455 | 330 if (has_message) |
10199 | 331 { |
332 gtk_widget_show(selector->priv->frame); | |
10455 | 333 gtk_widget_set_sensitive(selector->priv->frame, TRUE); |
10199 | 334 key_press_cb(NULL, NULL, selector); |
335 } | |
336 } | |
10504 | 337 g_free(text); |
10199 | 338 } |
339 | |
10455 | 340 /** |
341 * This is used to set the message of the selected status. It | |
342 * is triggered after the user has stopped typing in the little box. | |
343 * It just goes through and, if the selected status type for any | |
344 * given online/enabled account requires a message, then it sets | |
345 * that status with the entered message. | |
346 */ | |
10199 | 347 static gboolean |
348 insert_text_timeout_cb(gpointer data) | |
349 { | |
350 GaimGtkStatusSelector *selector = (GaimGtkStatusSelector *)data; | |
351 const char *status_type_id; | |
10504 | 352 char *text; |
10455 | 353 gchar *message; |
354 GList *l; | |
355 | |
356 gtk_widget_set_sensitive(selector->priv->frame, FALSE); | |
10199 | 357 |
10347 | 358 if (!get_selected_data(selector, &text, &status_type_id)) |
10199 | 359 return FALSE; |
360 | |
361 if (status_type_id == NULL) | |
10504 | 362 { |
363 g_free(text); | |
10455 | 364 return FALSE; |
10504 | 365 } |
10455 | 366 |
367 message = gtk_imhtml_get_markup(GTK_IMHTML(selector->priv->entry)); | |
368 | |
369 for (l = gaim_accounts_get_all(); l != NULL; l = l->next) | |
10199 | 370 { |
10455 | 371 GaimAccount *account = (GaimAccount*)l->data; |
372 GaimStatusType *status_type; | |
373 | |
374 if (!gaim_account_get_enabled(account, GAIM_GTK_UI)) | |
375 continue; | |
10199 | 376 |
10455 | 377 status_type = gaim_account_get_status_type(account, |
378 status_type_id); | |
10188 | 379 |
10455 | 380 if (status_type == NULL) |
381 continue; | |
382 | |
383 if (gaim_status_type_get_attr(status_type, "message") != NULL) | |
10178 | 384 { |
10455 | 385 gaim_account_set_status(account, |
386 status_type_id, TRUE, | |
387 "message", message, | |
388 NULL); | |
10188 | 389 } |
10199 | 390 } |
10178 | 391 |
10504 | 392 g_free(text); |
393 g_free(message); | |
394 | |
10199 | 395 return FALSE; |
396 } | |
397 | |
398 /** | |
399 * The user typed in the IMHTML entry widget. If the user is finished | |
400 * typing then we want to set the appropriate status message. So let's | |
401 * wait 3 seconds, and if they haven't typed anything else then set the | |
402 * status message. | |
403 */ | |
404 static gboolean | |
405 key_press_cb(GtkWidget *entry, GdkEventKey *event, gpointer user_data) | |
406 { | |
407 GaimGtkStatusSelector *selector = (GaimGtkStatusSelector *)user_data; | |
408 | |
409 if (selector->priv->entry_timer != 0) { | |
410 gaim_timeout_remove(selector->priv->entry_timer); | |
10178 | 411 } |
10199 | 412 |
10455 | 413 selector->priv->entry_timer = gaim_timeout_add(3000, |
414 insert_text_timeout_cb, | |
415 selector); | |
10199 | 416 |
417 return FALSE; | |
10178 | 418 } |
419 | |
420 static void | |
421 signed_on_off_cb(GaimConnection *gc, GaimGtkStatusSelector *selector) | |
422 { | |
423 rebuild_list(selector); | |
424 } | |
425 | |
426 static GdkPixbuf * | |
427 load_icon(const char *basename) | |
428 { | |
429 char *filename; | |
430 GdkPixbuf *pixbuf, *scale = NULL; | |
431 | |
432 if (!strcmp(basename, "available.png")) | |
433 basename = "online.png"; | |
434 else if (!strcmp(basename, "hidden.png")) | |
435 basename = "invisible.png"; | |
436 | |
437 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "icons", | |
438 basename, NULL); | |
439 pixbuf = gdk_pixbuf_new_from_file(filename, NULL); | |
440 g_free(filename); | |
441 | |
442 if (pixbuf != NULL) | |
443 { | |
444 scale = gdk_pixbuf_scale_simple(pixbuf, 16, 16, | |
445 GDK_INTERP_BILINEAR); | |
446 | |
447 g_object_unref(G_OBJECT(pixbuf)); | |
448 } | |
449 else | |
450 { | |
451 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", | |
452 "default", basename, NULL); | |
453 scale = gdk_pixbuf_new_from_file(filename, NULL); | |
454 g_free(filename); | |
455 } | |
456 | |
457 return scale; | |
458 } | |
459 | |
460 static void | |
461 add_item(GaimGtkStatusSelector *selector, const char *status_type_id, | |
462 const char *text, GdkPixbuf *pixbuf) | |
463 { | |
10347 | 464 #if GTK_CHECK_VERSION(2,4,0) |
10178 | 465 GtkTreeIter iter; |
466 | |
467 gtk_list_store_append(selector->priv->model, &iter); | |
468 gtk_list_store_set(selector->priv->model, &iter, | |
469 COLUMN_STATUS_TYPE_ID, status_type_id, | |
470 COLUMN_ICON, pixbuf, | |
471 COLUMN_NAME, text, | |
472 -1); | |
10347 | 473 #else |
474 GtkWidget *image = gtk_image_new_from_pixbuf(pixbuf); | |
475 GtkWidget *item, *hbox, *label; | |
476 | |
477 /* Create the item. */ | |
478 item = gtk_menu_item_new(); | |
479 | |
480 /* Create the hbox. */ | |
481 hbox = gtk_hbox_new(FALSE, 4); | |
482 gtk_container_add(GTK_CONTAINER(item), hbox); | |
483 gtk_widget_show(hbox); | |
484 | |
485 gtk_size_group_add_widget(selector->priv->sg, image); | |
486 | |
487 gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0); | |
488 gtk_widget_show(image); | |
489 | |
490 /* Create the label. */ | |
491 label = gtk_label_new(text); | |
492 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT); | |
493 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
494 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0); | |
495 gtk_widget_show(label); | |
496 | |
497 g_object_set_data_full(G_OBJECT(item), GAIM_SELECTOR_TEXT, g_strdup(text), g_free); | |
498 g_object_set_data_full(G_OBJECT(item), GAIM_SELECTOR_STATUS_TYPE_ID, g_strdup(status_type_id), g_free); | |
499 | |
500 gtk_menu_shell_append(GTK_MENU_SHELL(selector->priv->menu), item); | |
501 gtk_widget_show(item); | |
502 gaim_set_accessible_label(item, label); | |
503 #endif | |
10178 | 504 |
505 if (pixbuf != NULL) | |
506 g_object_unref(G_OBJECT(pixbuf)); | |
507 } | |
508 | |
10347 | 509 |
10178 | 510 static void |
511 rebuild_list(GaimGtkStatusSelector *selector) | |
512 { | |
513 gboolean single_prpl = TRUE; | |
10400 | 514 GList *accounts; |
515 gboolean enabled = FALSE; | |
10178 | 516 GaimAccount *first_account = NULL; |
517 const char *first_prpl_type = NULL; | |
10485 | 518 const GList *l; |
10178 | 519 |
520 g_return_if_fail(selector != NULL); | |
521 g_return_if_fail(GAIM_GTK_IS_STATUS_SELECTOR(selector)); | |
522 | |
10347 | 523 #if GTK_CHECK_VERSION(2,4,0) |
10178 | 524 gtk_list_store_clear(selector->priv->model); |
10347 | 525 #else |
526 gtk_option_menu_remove_menu(GTK_OPTION_MENU(selector->priv->optmenu)); | |
527 /* XXX this automaticly destroys the menu, right? */ | |
528 selector->priv->menu = gtk_menu_new(); | |
529 gtk_widget_show(selector->priv->menu); | |
530 #endif | |
10178 | 531 |
532 /* | |
10400 | 533 * If no accounts are enabled then gray ourself out and get |
10352 | 534 * outta hee. |
535 */ | |
10447 | 536 for (accounts = gaim_accounts_get_all(); accounts != NULL; |
537 accounts = accounts->next) | |
538 { | |
10400 | 539 GaimAccount *a = accounts->data; |
10447 | 540 if (gaim_account_get_enabled(a, GAIM_GTK_UI)) |
541 { | |
10400 | 542 enabled = TRUE; |
543 break; | |
544 } | |
545 } | |
10447 | 546 |
10400 | 547 if (enabled == FALSE) |
10352 | 548 { |
549 gtk_widget_set_sensitive(GTK_WIDGET(selector), FALSE); | |
550 return; | |
551 } | |
552 gtk_widget_set_sensitive(GTK_WIDGET(selector), TRUE); | |
553 | |
554 /* | |
10178 | 555 * If the user only has one IM account or one type of IM account |
556 * connected, they'll see all their statuses. This is ideal for those | |
557 * who use only one account, or one single protocol. Everyone else | |
558 * gets Available and Away and a list of saved statuses. | |
559 */ | |
10400 | 560 for (l = gaim_accounts_get_all(); l != NULL && single_prpl; l = l->next) |
10178 | 561 { |
10400 | 562 GaimAccount *account = l->data; |
10178 | 563 GaimPluginProtocolInfo *prpl_info; |
10400 | 564 GaimPlugin *plugin; |
10178 | 565 const char *basename; |
566 | |
10400 | 567 if (!gaim_account_get_enabled(account, GAIM_GTK_UI)) |
568 continue; | |
569 | |
570 plugin = gaim_find_prpl(account->protocol_id); | |
571 if (!plugin) | |
572 continue; | |
573 | |
574 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(plugin); | |
10178 | 575 basename = prpl_info->list_icon(account, NULL); |
576 | |
577 if (first_prpl_type == NULL) | |
578 { | |
579 first_prpl_type = basename; | |
580 first_account = account; | |
581 } | |
10179
97ee3bf7bcf7
[gaim-migrate @ 11294]
Christian Hammond <chipx86@chipx86.com>
parents:
10178
diff
changeset
|
582 else if (strcmp(first_prpl_type, basename)) |
10178 | 583 single_prpl = FALSE; |
584 } | |
585 | |
586 if (single_prpl) | |
587 { | |
588 for (l = gaim_account_get_status_types(first_account); | |
589 l != NULL; | |
590 l = l->next) | |
591 { | |
592 GaimStatusType *status_type = (GaimStatusType *)l->data; | |
593 char filename[BUFSIZ]; | |
594 | |
595 if (!gaim_status_type_is_user_settable(status_type)) | |
596 continue; | |
597 | |
10207 | 598 /* |
10447 | 599 * TODO: Find a way to fallback to the GaimStatusPrimitive |
10207 | 600 * if an icon for this id does not exist. |
601 */ | |
10178 | 602 g_snprintf(filename, sizeof(filename), "%s.png", |
603 gaim_status_type_get_id(status_type)); | |
604 | |
605 add_item(selector, | |
606 gaim_status_type_get_id(status_type), | |
607 gaim_status_type_get_name(status_type), | |
608 load_icon(filename)); | |
609 } | |
610 } | |
611 else | |
612 { | |
10485 | 613 /* what follows is either really ugly, or brilliant depending on |
614 * how you look at it, and how much you've had to drink */ | |
615 int i; | |
616 int num_accounts = 0; | |
617 int options[GAIM_STATUS_NUM_PRIMITIVES]; | |
618 GaimAccount *acct_options[GAIM_STATUS_NUM_PRIMITIVES]; | |
619 | |
620 for(i=0; i<GAIM_STATUS_NUM_PRIMITIVES; i++) { | |
621 options[i] = 0; | |
622 acct_options[i] = NULL; | |
623 } | |
624 | |
625 for(accounts = gaim_accounts_get_all(); accounts != NULL; accounts = accounts->next) { | |
626 GaimAccount *account = accounts->data; | |
627 | |
628 if (!gaim_account_get_enabled(account, GAIM_GTK_UI)) | |
629 continue; | |
630 | |
631 num_accounts++; | |
632 | |
633 for(l = gaim_account_get_status_types(account); l != NULL; l = l->next) { | |
634 GaimStatusType *status_type = l->data; | |
635 | |
636 if (!gaim_status_type_is_user_settable(status_type)) | |
637 continue; | |
638 | |
639 acct_options[gaim_status_type_get_primitive(status_type)] = account; | |
640 } | |
641 | |
642 for(i=0; i<GAIM_STATUS_NUM_PRIMITIVES; i++) { | |
643 if(acct_options[i] == account) | |
644 options[i]++; | |
645 } | |
646 } | |
647 | |
648 for(i=0; i<GAIM_STATUS_NUM_PRIMITIVES; i++) { | |
649 if(options[i] == num_accounts) { | |
650 char *filename = g_strdup_printf("%s.png", gaim_primitive_get_id_from_type(i)); | |
651 add_item(selector, gaim_primitive_get_id_from_type(i), gaim_primitive_get_name_from_type(i), load_icon(filename)); | |
652 g_free(filename); | |
653 } | |
654 } | |
10178 | 655 } |
656 | |
10191 | 657 /* TODO: Add saved statuses here? */ |
658 | |
10178 | 659 add_item(selector, NULL, _("New Status"), |
10347 | 660 gtk_widget_render_icon(GTK_WIDGET(selector), GTK_STOCK_NEW, |
661 GTK_ICON_SIZE_MENU, NULL)); | |
662 #if !GTK_CHECK_VERSION(2,4,0) | |
663 gtk_option_menu_set_menu(GTK_OPTION_MENU(selector->priv->optmenu), selector->priv->menu); | |
664 #endif | |
10178 | 665 } |
666 | |
667 GtkWidget * | |
668 gaim_gtk_status_selector_new(void) | |
669 { | |
670 GaimGtkStatusSelector *selector; | |
671 | |
672 selector = g_object_new(GAIM_GTK_TYPE_STATUS_SELECTOR, NULL); | |
673 | |
674 return GTK_WIDGET(selector); | |
675 } |