comparison src/gtkstatusbox.c @ 13050:fb607b2d4ff2

[gaim-migrate @ 15411] Some fixes and documentation. I'm not sure if we were escaping everything correctly after my changes last night, but it's definitely working correctly now. Selecting a saved status with a message will not show the imhtml. Instead it'll show the title and the first part of the message directly on the status box. That seemed like a good idea to me. Selecting one of the 4 basic transient statuses (available, away, invisible, offline) with no substatuses will make the status box show the primtive and open the imhtml. committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Fri, 27 Jan 2006 06:40:38 +0000
parents 704dc95d0198
children 1ef760c65174
comparison
equal deleted inserted replaced
13049:97fa7332b034 13050:fb607b2d4ff2
396 */ 396 */
397 static void 397 static void
398 update_to_reflect_current_status(GtkGaimStatusBox *status_box) 398 update_to_reflect_current_status(GtkGaimStatusBox *status_box)
399 { 399 {
400 GaimSavedStatus *saved_status; 400 GaimSavedStatus *saved_status;
401 GaimStatusPrimitive primitive;
401 gint index; 402 gint index;
402 const char *message; 403 const char *message;
403 GList *list; 404 GList *list;
404 405
405 /* this function is inappropriate for ones with accounts */ 406 /* this function is inappropriate for ones with accounts */
412 * Suppress the "changed" signal because the status 413 * Suppress the "changed" signal because the status
413 * was changed programmatically. 414 * was changed programmatically.
414 */ 415 */
415 gtk_widget_set_sensitive(GTK_WIDGET(status_box), FALSE); 416 gtk_widget_set_sensitive(GTK_WIDGET(status_box), FALSE);
416 417
417 list = gaim_savedstatuses_get_popular(6); 418 /*
418 if ((index = g_list_index(list, saved_status)) > -1) 419 * If the saved_status is transient, is Available, Away, Invisible
419 index += 5; 420 * or Offline, and it does not have an substatuses, then select
421 * the primitive in the dropdown menu. Otherwise select the
422 * popular status in the dropdown menu.
423 */
424 primitive = gaim_savedstatus_get_type(saved_status);
425 if (gaim_savedstatus_is_transient(saved_status) &&
426 ((primitive == GAIM_STATUS_AVAILABLE) || (primitive == GAIM_STATUS_AWAY) ||
427 (primitive == GAIM_STATUS_INVISIBLE) || (primitive == GAIM_STATUS_OFFLINE)) &&
428 (!gaim_savedstatus_has_substatuses(saved_status)))
429 {
430 index = get_statusbox_index(status_box, saved_status);
431 }
420 else 432 else
421 { 433 {
422 if (gaim_savedstatus_has_substatuses(saved_status)) 434 /*
423 index = GTK_LIST_STORE(status_box->dropdown_store)->length - 2; 435 * TODO: This code is really bad. We need to look at the DATA
436 * column of the saved statuses, instead.
437 */
438 list = gaim_savedstatuses_get_popular(6);
439 if ((index = g_list_index(list, saved_status)) > -1)
440 index += 5; /* Skip over the primitives and a spacer that may or may not exist! (Fix this) */
424 else 441 else
425 { 442 index = 0; /* TODO: Need to do something better here */
426 index = get_statusbox_index(status_box, saved_status); 443 g_list_free(list);
427 } 444 }
428 } 445
429 g_list_free(list);
430 gtk_combo_box_set_active(GTK_COMBO_BOX(status_box), index); 446 gtk_combo_box_set_active(GTK_COMBO_BOX(status_box), index);
431 447
432 message = gaim_savedstatus_get_message(saved_status); 448 message = gaim_savedstatus_get_message(saved_status);
433 if (!message || !*message) 449 if (!gaim_savedstatus_is_transient(saved_status) || !message || !*message)
434 { 450 {
435 status_box->imhtml_visible = FALSE; 451 status_box->imhtml_visible = FALSE;
436 gtk_widget_hide_all(status_box->vbox); 452 gtk_widget_hide_all(status_box->vbox);
437 } 453 }
438 else 454 else
461 static void 477 static void
462 add_popular_statuses(GtkGaimStatusBox *statusbox) 478 add_popular_statuses(GtkGaimStatusBox *statusbox)
463 { 479 {
464 GList *list, *cur; 480 GList *list, *cur;
465 GtkIconSize icon_size; 481 GtkIconSize icon_size;
466 GdkPixbuf *away_pix, *avl_pix, *pixbuf; 482 GdkPixbuf *pixbuf, *emblem, *scale;
467 483
468 list = gaim_savedstatuses_get_popular(6); 484 list = gaim_savedstatuses_get_popular(6);
469 if (list == NULL) 485 if (list == NULL)
470 /* Odd... oh well, nothing we can do about it. */ 486 /* Odd... oh well, nothing we can do about it. */
471 return; 487 return;
473 if (gaim_prefs_get_bool("/gaim/gtk/blist/show_buddy_icons")) 489 if (gaim_prefs_get_bool("/gaim/gtk/blist/show_buddy_icons"))
474 icon_size = gtk_icon_size_from_name(GAIM_ICON_SIZE_STATUS); 490 icon_size = gtk_icon_size_from_name(GAIM_ICON_SIZE_STATUS);
475 else 491 else
476 icon_size = gtk_icon_size_from_name(GAIM_ICON_SIZE_STATUS_SMALL); 492 icon_size = gtk_icon_size_from_name(GAIM_ICON_SIZE_STATUS_SMALL);
477 493
478 away_pix = gtk_widget_render_icon(GTK_WIDGET(statusbox->vbox), GAIM_STOCK_STATUS_AWAY, 494 /* Create the icon to use for non-transient saved-statuses */
479 icon_size, "GtkGaimStatusBox"); 495 pixbuf = gtk_widget_render_icon(GTK_WIDGET(statusbox->vbox),
480 avl_pix = gtk_widget_render_icon(GTK_WIDGET(statusbox->vbox), GAIM_STOCK_STATUS_ONLINE, 496 GAIM_STOCK_STATUS_ONLINE, icon_size, "GtkGaimStatusBox");
481 icon_size, "GtkGaimStatusBox"); 497 scale = gdk_pixbuf_scale_simple(pixbuf, 32, 32, GDK_INTERP_BILINEAR);
498 g_object_unref(G_OBJECT(pixbuf));
499 pixbuf = scale;
500
501 emblem = gtk_widget_render_icon(GTK_WIDGET(statusbox->vbox),
502 GTK_STOCK_SAVE, icon_size, "GtkGaimStatusBox");
503 scale = gdk_pixbuf_scale_simple(emblem, 15, 15, GDK_INTERP_BILINEAR);
504 g_object_unref(G_OBJECT(emblem));
505 emblem = scale;
506
507 gdk_pixbuf_composite(emblem, pixbuf, 32-15, 32-15, 15, 15, 17, 17, 1, 1,
508 GDK_INTERP_BILINEAR, 255);
509 g_object_unref(G_OBJECT(emblem));
482 510
483 gtk_gaim_status_box_add_separator(statusbox); 511 gtk_gaim_status_box_add_separator(statusbox);
484 512
485 for (cur = list; cur != NULL; cur = cur->next) 513 for (cur = list; cur != NULL; cur = cur->next)
486 { 514 {
487 GaimSavedStatus *saved = cur->data; 515 GaimSavedStatus *saved = cur->data;
488 516 const gchar *message;
489 switch (gaim_savedstatus_get_type(saved)) 517 gchar *stripped;
490 { 518
491 case GAIM_STATUS_AVAILABLE: 519 /* TODO: For transient saved-statuses, make a new icon showing the primitive */
492 pixbuf = avl_pix; 520
493 break; 521 if (gaim_savedstatus_is_transient(saved))
494 default: 522 {
495 pixbuf = away_pix; 523 /*
496 break; 524 * Transient statuses do not have a title, so the savedstatus
525 * API returns the message when gaim_savedstatus_get_title() is
526 * called, so we don't need to get the message a second time.
527 */
528 stripped = NULL;
529 }
530 else
531 {
532 message = gaim_savedstatus_get_message(saved);
533 stripped = gaim_markup_strip_html(message);
534 gaim_util_chrreplace(stripped, '\n', ' ');
497 } 535 }
498 gtk_gaim_status_box_add(statusbox, GTK_GAIM_STATUS_BOX_TYPE_POPULAR, 536 gtk_gaim_status_box_add(statusbox, GTK_GAIM_STATUS_BOX_TYPE_POPULAR,
499 pixbuf, gaim_savedstatus_get_title(saved), NULL, 537 pixbuf, gaim_savedstatus_get_title(saved), stripped,
500 GINT_TO_POINTER(gaim_savedstatus_get_creation_time(saved))); 538 GINT_TO_POINTER(gaim_savedstatus_get_creation_time(saved)));
539 g_free(stripped);
501 } 540 }
502 541
503 g_list_free(list); 542 g_list_free(list);
504 } 543 }
505 544
937 gtk_gaim_status_box_new_with_account(GaimAccount *account) 976 gtk_gaim_status_box_new_with_account(GaimAccount *account)
938 { 977 {
939 return g_object_new(GTK_GAIM_TYPE_STATUS_BOX, "account", account, NULL); 978 return g_object_new(GTK_GAIM_TYPE_STATUS_BOX, "account", account, NULL);
940 } 979 }
941 980
981 /**
982 * Add a row to the dropdown menu.
983 *
984 * @param status_box The status box itself.
985 * @param type A GtkGaimStatusBoxItemType.
986 * @param pixbuf The icon to associate with this row in the menu.
987 * @param title The title of this item. For the primitive entries,
988 * this is something like "Available" or "Away." For
989 * the saved statuses, this is something like
990 * "My favorite away message!" This should be
991 * plaintext (non-markedup) (this function escapes it).
992 * @param desc The secondary text for this item. This will be
993 * placed on the row below the title, in a dimmer
994 * font (generally gray). This text should be plaintext
995 * (non-markedup) (this function escapes it).
996 * @param data Data to be associated with this row in the dropdown
997 * menu. For primitives this is the value of the
998 * GaimStatusPrimitive. For saved statuses this is the
999 * creation timestamp.
1000 */
942 void 1001 void
943 gtk_gaim_status_box_add(GtkGaimStatusBox *status_box, GtkGaimStatusBoxItemType type, GdkPixbuf *pixbuf, const char *text, const char *sec_text, gpointer data) 1002 gtk_gaim_status_box_add(GtkGaimStatusBox *status_box, GtkGaimStatusBoxItemType type, GdkPixbuf *pixbuf, const char *title, const char *desc, gpointer data)
944 { 1003 {
945 GtkTreeIter iter; 1004 GtkTreeIter iter;
946 char *t; 1005 char *text;
947 1006
948 if (sec_text) { 1007 if (desc == NULL)
1008 {
1009 text = g_markup_escape_text(title, -1);
1010 }
1011 else
1012 {
949 char aa_color[8]; 1013 char aa_color[8];
950 gchar *escaped; 1014 gchar *escaped_title, *escaped_desc;
951 GtkStyle *style = gtk_widget_get_style(GTK_WIDGET(status_box)); 1015 GtkStyle *style;
1016
1017 style = gtk_widget_get_style(GTK_WIDGET(status_box));
952 snprintf(aa_color, sizeof(aa_color), "#%02x%02x%02x", 1018 snprintf(aa_color, sizeof(aa_color), "#%02x%02x%02x",
953 style->text_aa[GTK_STATE_NORMAL].red >> 8, 1019 style->text_aa[GTK_STATE_NORMAL].red >> 8,
954 style->text_aa[GTK_STATE_NORMAL].green >> 8, 1020 style->text_aa[GTK_STATE_NORMAL].green >> 8,
955 style->text_aa[GTK_STATE_NORMAL].blue >> 8); 1021 style->text_aa[GTK_STATE_NORMAL].blue >> 8);
956 escaped = g_markup_escape_text(sec_text, -1); 1022
957 t = g_strdup_printf("%s\n<span color=\"%s\">%s</span>", text, aa_color, escaped); 1023 escaped_title = g_markup_escape_text(title, -1);
958 g_free(escaped); 1024 escaped_desc = g_markup_escape_text(desc, -1);
959 } else { 1025 text = g_strdup_printf("%s\n<span color=\"%s\" size=\"smaller\">%s</span>",
960 t = g_markup_escape_text(text, -1); 1026 escaped_title, aa_color, escaped_desc);
1027 g_free(escaped_title);
1028 g_free(escaped_desc);
961 } 1029 }
962 1030
963 gtk_list_store_append(status_box->dropdown_store, &iter); 1031 gtk_list_store_append(status_box->dropdown_store, &iter);
964 gtk_list_store_set(status_box->dropdown_store, &iter, 1032 gtk_list_store_set(status_box->dropdown_store, &iter,
965 TYPE_COLUMN, type, 1033 TYPE_COLUMN, type,
966 ICON_COLUMN, pixbuf, 1034 ICON_COLUMN, pixbuf,
967 TEXT_COLUMN, t, 1035 TEXT_COLUMN, text,
968 TITLE_COLUMN, text, 1036 TITLE_COLUMN, title,
969 DESC_COLUMN, sec_text, 1037 DESC_COLUMN, desc,
970 DATA_COLUMN, data, 1038 DATA_COLUMN, data,
971 -1); 1039 -1);
972 g_free(t); 1040 g_free(text);
973 } 1041 }
974 1042
975 void 1043 void
976 gtk_gaim_status_box_add_separator(GtkGaimStatusBox *status_box) 1044 gtk_gaim_status_box_add_separator(GtkGaimStatusBox *status_box)
977 { 1045 {
1029 else 1097 else
1030 status_box->typing_index++; 1098 status_box->typing_index++;
1031 gtk_gaim_status_box_refresh(status_box); 1099 gtk_gaim_status_box_refresh(status_box);
1032 } 1100 }
1033 1101
1034 static GaimStatusType 1102 static GaimStatusType *
1035 *find_status_type_by_index(const GaimAccount *account, gint active) 1103 find_status_type_by_index(const GaimAccount *account, gint active)
1036 { 1104 {
1037 const GList *l = gaim_account_get_status_types(account); 1105 const GList *l = gaim_account_get_status_types(account);
1038 gint i; 1106 gint i;
1039 1107
1040 for (i = 0; l; l = l->next) { 1108 for (i = 0; l; l = l->next) {
1230 static void gtk_gaim_status_box_changed(GtkComboBox *box) 1298 static void gtk_gaim_status_box_changed(GtkComboBox *box)
1231 { 1299 {
1232 GtkGaimStatusBox *status_box; 1300 GtkGaimStatusBox *status_box;
1233 GtkTreeIter iter; 1301 GtkTreeIter iter;
1234 GtkGaimStatusBoxItemType type; 1302 GtkGaimStatusBoxItemType type;
1235 char *text, *sec_text; 1303 char *text, *desc;
1236 GdkPixbuf *pixbuf; 1304 GdkPixbuf *pixbuf;
1237 gpointer data; 1305 gpointer data;
1238 GList *accounts = NULL, *node; 1306 GList *accounts = NULL, *node;
1239 1307
1240 status_box = GTK_GAIM_STATUS_BOX(box); 1308 status_box = GTK_GAIM_STATUS_BOX(box);
1242 if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(status_box), &iter)) 1310 if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(status_box), &iter))
1243 return; 1311 return;
1244 gtk_tree_model_get(GTK_TREE_MODEL(status_box->dropdown_store), &iter, 1312 gtk_tree_model_get(GTK_TREE_MODEL(status_box->dropdown_store), &iter,
1245 TYPE_COLUMN, &type, 1313 TYPE_COLUMN, &type,
1246 TITLE_COLUMN, &text, 1314 TITLE_COLUMN, &text,
1247 DESC_COLUMN, &sec_text, 1315 DESC_COLUMN, &desc,
1248 ICON_COLUMN, &pixbuf, 1316 ICON_COLUMN, &pixbuf,
1249 DATA_COLUMN, &data, 1317 DATA_COLUMN, &data,
1250 -1); 1318 -1);
1251 if (status_box->title) 1319 if (status_box->title)
1252 g_free(status_box->title); 1320 g_free(status_box->title);
1253 status_box->title = text; 1321 status_box->title = text;
1254 if (status_box->desc && sec_text) 1322 if (status_box->desc && desc)
1255 g_free(status_box->desc); 1323 g_free(status_box->desc);
1256 status_box->desc = sec_text; 1324 status_box->desc = desc;
1257 if (status_box->pixbuf) 1325 if (status_box->pixbuf)
1258 g_object_unref(status_box->pixbuf); 1326 g_object_unref(status_box->pixbuf);
1259 status_box->pixbuf = pixbuf; 1327 status_box->pixbuf = pixbuf;
1260 if (status_box->typing) 1328 if (status_box->typing)
1261 g_source_remove(status_box->typing); 1329 g_source_remove(status_box->typing);
1358 break; 1426 break;
1359 case GAIM_STATUS_OFFLINE: 1427 case GAIM_STATUS_OFFLINE:
1360 index = 3; 1428 index = 3;
1361 break; 1429 break;
1362 default: 1430 default:
1363 index = GTK_LIST_STORE(box->dropdown_store)->length - 2; 1431 /*
1432 * TODO: This is very bad! I believe it's causing the infinite
1433 * windows bug. Need to do something better here.
1434 */
1435 /* index = GTK_LIST_STORE(box->dropdown_store)->length - 2; */
1436 index = 0;
1364 break; 1437 break;
1365 } 1438 }
1366 1439
1367 return index; 1440 return index;
1368 } 1441 }