comparison src/gtkstatusbox.c @ 13044:18fc2a679e38

[gaim-migrate @ 15403] Two things: * Escape text displayed in the status box and the status box drop down * Add and improve some gtkstatusbox documentation. committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Thu, 26 Jan 2006 05:23:49 +0000
parents 7d39e6c73dc3
children 704dc95d0198
comparison
equal deleted inserted replaced
13043:fa99be331f2f 13044:18fc2a679e38
21 * You should have received a copy of the GNU General Public License 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 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 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */ 24 */
25 25
26 /*
27 * The status box is made up of two main pieces:
28 * - The box that displays the current status, which is made
29 * of a GtkListStore ("status_box->store") and GtkCellView
30 * ("status_box->cell_view"). There is always exactly 1 row
31 * in this list store. Only the TYPE_ICON and TYPE_TEXT
32 * columns are used in this list store.
33 * - The dropdown menu that lets users select a status, which
34 * is made of a GtkComboBox ("status_box") and GtkListStore
35 * ("status_box->dropdown_store"). This dropdown is shown
36 * when the user clicks on the box that displays the current
37 * status. This list store contains one row for Available,
38 * one row for Away, etc., a few rows for popular statuses,
39 * and the "New..." and "Saved..." options.
40 */
41
26 #include <gdk/gdkkeysyms.h> 42 #include <gdk/gdkkeysyms.h>
27 43
28 #include "account.h" 44 #include "account.h"
29 #include "internal.h" 45 #include "internal.h"
30 #include "savedstatuses.h" 46 #include "savedstatuses.h"
64 static void (*combo_box_size_request)(GtkWidget *widget, GtkRequisition *requisition); 80 static void (*combo_box_size_request)(GtkWidget *widget, GtkRequisition *requisition);
65 static void (*combo_box_size_allocate)(GtkWidget *widget, GtkAllocation *allocation); 81 static void (*combo_box_size_allocate)(GtkWidget *widget, GtkAllocation *allocation);
66 static void (*combo_box_forall) (GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data); 82 static void (*combo_box_forall) (GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data);
67 83
68 enum { 84 enum {
69 TYPE_COLUMN, /* A GtkGaimStatusBoxItemType */ 85 /** A GtkGaimStatusBoxItemType */
70 ICON_COLUMN, /* This is a GdkPixbuf (the other columns are strings) */ 86 TYPE_COLUMN,
71 TEXT_COLUMN, /* A string */ 87
72 TITLE_COLUMN, /* The plain-English title of this item */ 88 /**
73 DESC_COLUMN, /* A plain-English description of this item */ 89 * This is a GdkPixbuf (the other columns are strings).
74 DATA_COLUMN, /* Keep track of the creation time of popular 90 * This column is visible.
75 statuses, and also the GaimStatusPrimitive */ 91 */
92 ICON_COLUMN,
93
94 /** The text displayed on the status box. This column is visible. */
95 TEXT_COLUMN,
96
97 /** The plain-English title of this item */
98 TITLE_COLUMN,
99
100 /** A plain-English description of this item */
101 DESC_COLUMN,
102
103 /*
104 * This value depends on TYPE_COLUMN. For POPULAR types,
105 * this is the creation time. For PRIMITIVE types,
106 * this is the GaimStatusPrimitive.
107 */
108 DATA_COLUMN,
109
76 NUM_COLUMNS 110 NUM_COLUMNS
77 }; 111 };
78 112
79 enum { 113 enum {
80 PROP_0, 114 PROP_0,
266 G_PARAM_READWRITE 300 G_PARAM_READWRITE
267 ) 301 )
268 ); 302 );
269 } 303 }
270 304
305 /**
306 * This updates the text displayed on the status box so that it shows
307 * the current status.
308 */
271 static void 309 static void
272 gtk_gaim_status_box_refresh(GtkGaimStatusBox *status_box) 310 gtk_gaim_status_box_refresh(GtkGaimStatusBox *status_box)
273 { 311 {
274 char *text = NULL, *title; 312 char *text = NULL, *title;
275 char aa_color[8]; 313 char aa_color[8];
281 snprintf(aa_color, sizeof(aa_color), "#%02x%02x%02x", 319 snprintf(aa_color, sizeof(aa_color), "#%02x%02x%02x",
282 style->text_aa[GTK_STATE_NORMAL].red >> 8, 320 style->text_aa[GTK_STATE_NORMAL].red >> 8,
283 style->text_aa[GTK_STATE_NORMAL].green >> 8, 321 style->text_aa[GTK_STATE_NORMAL].green >> 8,
284 style->text_aa[GTK_STATE_NORMAL].blue >> 8); 322 style->text_aa[GTK_STATE_NORMAL].blue >> 8);
285 323
286 title = status_box->title; 324 if (status_box->title != NULL)
287 if (!title) 325 title = g_markup_escape_text(status_box->title, -1);
288 title = ""; 326 else
327 title = g_strdup("");
289 328
290 if (status_box->error) { 329 if (status_box->error) {
330 gchar *tmp = g_markup_escape_text(status_box->error, -1);
291 text = g_strdup_printf("<span size=\"smaller\" weight=\"bold\" color=\"red\">%s</span>", 331 text = g_strdup_printf("<span size=\"smaller\" weight=\"bold\" color=\"red\">%s</span>",
292 status_box->error); 332 tmp);
333 g_free(tmp);
293 } else if (status_box->typing) { 334 } else if (status_box->typing) {
294 text = g_strdup_printf("<span size=\"smaller\" color=\"%s\">%s</span>", 335 text = g_strdup_printf("<span size=\"smaller\" color=\"%s\">%s</span>",
295 aa_color, _("Typing")); 336 aa_color, _("Typing"));
296 } else if (status_box->connecting) { 337 } else if (status_box->connecting) {
297 text = g_strdup_printf("<span size=\"smaller\" color=\"%s\">%s</span>", 338 text = g_strdup_printf("<span size=\"smaller\" color=\"%s\">%s</span>",
298 aa_color, _("Connecting")); 339 aa_color, _("Connecting"));
299 } else if (status_box->desc) { 340 } else if (status_box->desc) {
341 gchar *tmp = g_markup_escape_text(status_box->desc, -1);
300 text = g_strdup_printf("<span size=\"smaller\" color=\"%s\">%s</span>", 342 text = g_strdup_printf("<span size=\"smaller\" color=\"%s\">%s</span>",
301 aa_color, status_box->desc); 343 aa_color, tmp);
344 g_free(tmp);
302 } 345 }
303 346
304 if (status_box->account) { 347 if (status_box->account) {
305 char *text2 = g_strdup_printf("%s\n<span size=\"smaller\">%s</span>", 348 char *text2 = g_strdup_printf("%s\n<span size=\"smaller\">%s</span>",
306 gaim_account_get_username(status_box->account), 349 gaim_account_get_username(status_box->account),
312 g_free(text); 355 g_free(text);
313 text = text2; 356 text = text2;
314 } else { 357 } else {
315 text = g_strdup(title); 358 text = g_strdup(title);
316 } 359 }
360 g_free(title);
317 361
318 if (status_box->connecting) 362 if (status_box->connecting)
319 pixbuf = status_box->connecting_pixbufs[status_box->connecting_index]; 363 pixbuf = status_box->connecting_pixbufs[status_box->connecting_index];
320 else if (status_box->error) 364 else if (status_box->error)
321 pixbuf = status_box->error_pixbuf; 365 pixbuf = status_box->error_pixbuf;
322 else if (status_box->typing) 366 else if (status_box->typing)
323 pixbuf = status_box->typing_pixbufs[status_box->typing_index]; 367 pixbuf = status_box->typing_pixbufs[status_box->typing_index];
324 else 368 else
325 pixbuf = status_box->pixbuf; 369 pixbuf = status_box->pixbuf;
326 370
371 /*
372 * Only two columns are used in this list store (does it
373 * really need to be a list store?)
374 */
327 gtk_list_store_set(status_box->store, &(status_box->iter), 375 gtk_list_store_set(status_box->store, &(status_box->iter),
328 TYPE_COLUMN, -1, /* This field is not used in this list store */
329 ICON_COLUMN, pixbuf, 376 ICON_COLUMN, pixbuf,
330 TEXT_COLUMN, text, 377 TEXT_COLUMN, text,
331 TITLE_COLUMN, title,
332 DESC_COLUMN, status_box->desc,
333 DATA_COLUMN, -1, /* This field is not used in this list store */
334 -1); 378 -1);
335 path = gtk_tree_path_new_from_string("0"); 379 path = gtk_tree_path_new_from_string("0");
336 gtk_cell_view_set_displayed_row(GTK_CELL_VIEW(status_box->cell_view), path); 380 gtk_cell_view_set_displayed_row(GTK_CELL_VIEW(status_box->cell_view), path);
337 gtk_tree_path_free(path); 381 gtk_tree_path_free(path);
338 382
709 gtk_gaim_status_box_init (GtkGaimStatusBox *status_box) 753 gtk_gaim_status_box_init (GtkGaimStatusBox *status_box)
710 { 754 {
711 GtkCellRenderer *text_rend; 755 GtkCellRenderer *text_rend;
712 GtkCellRenderer *icon_rend; 756 GtkCellRenderer *icon_rend;
713 GtkTextBuffer *buffer; 757 GtkTextBuffer *buffer;
714 GtkTreePath *path;
715
716 text_rend = gtk_cell_renderer_text_new();
717 icon_rend = gtk_cell_renderer_pixbuf_new();
718 758
719 status_box->imhtml_visible = FALSE; 759 status_box->imhtml_visible = FALSE;
720 status_box->connecting = FALSE; 760 status_box->connecting = FALSE;
721 status_box->typing = FALSE; 761 status_box->typing = FALSE;
722 status_box->title = NULL; 762 status_box->title = NULL;
732 gtk_combo_box_set_model(GTK_COMBO_BOX(status_box), GTK_TREE_MODEL(status_box->dropdown_store)); 772 gtk_combo_box_set_model(GTK_COMBO_BOX(status_box), GTK_TREE_MODEL(status_box->dropdown_store));
733 gtk_cell_view_set_model(GTK_CELL_VIEW(status_box->cell_view), GTK_TREE_MODEL(status_box->store)); 773 gtk_cell_view_set_model(GTK_CELL_VIEW(status_box->cell_view), GTK_TREE_MODEL(status_box->store));
734 gtk_combo_box_set_wrap_width(GTK_COMBO_BOX(status_box), 0); 774 gtk_combo_box_set_wrap_width(GTK_COMBO_BOX(status_box), 0);
735 gtk_list_store_append(status_box->store, &(status_box->iter)); 775 gtk_list_store_append(status_box->store, &(status_box->iter));
736 gtk_gaim_status_box_refresh(status_box); 776 gtk_gaim_status_box_refresh(status_box);
737 path = gtk_tree_path_new_from_string("0");
738 gtk_cell_view_set_displayed_row(GTK_CELL_VIEW(status_box->cell_view), path);
739 gtk_tree_path_free(path);
740 777
741 gtk_container_add(GTK_CONTAINER(status_box->toggle_button), status_box->hbox); 778 gtk_container_add(GTK_CONTAINER(status_box->toggle_button), status_box->hbox);
742 gtk_box_pack_start(GTK_BOX(status_box->hbox), status_box->cell_view, TRUE, TRUE, 0); 779 gtk_box_pack_start(GTK_BOX(status_box->hbox), status_box->cell_view, TRUE, TRUE, 0);
743 gtk_box_pack_start(GTK_BOX(status_box->hbox), status_box->vsep, FALSE, FALSE, 0); 780 gtk_box_pack_start(GTK_BOX(status_box->hbox), status_box->vsep, FALSE, FALSE, 0);
744 gtk_box_pack_start(GTK_BOX(status_box->hbox), status_box->arrow, FALSE, FALSE, 0); 781 gtk_box_pack_start(GTK_BOX(status_box->hbox), status_box->arrow, FALSE, FALSE, 0);
745 gtk_widget_show_all(status_box->toggle_button); 782 gtk_widget_show_all(status_box->toggle_button);
746 #if GTK_CHECK_VERSION(2,4,0) 783 #if GTK_CHECK_VERSION(2,4,0)
747 gtk_button_set_focus_on_click(GTK_BUTTON(status_box->toggle_button), FALSE); 784 gtk_button_set_focus_on_click(GTK_BUTTON(status_box->toggle_button), FALSE);
748 #endif 785 #endif
749 status_box->icon_rend = gtk_cell_renderer_pixbuf_new(); 786
750 status_box->text_rend = gtk_cell_renderer_text_new(); 787 text_rend = gtk_cell_renderer_text_new();
751 788 icon_rend = gtk_cell_renderer_pixbuf_new();
752 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(status_box), icon_rend, FALSE); 789 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(status_box), icon_rend, FALSE);
753 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(status_box), text_rend, TRUE); 790 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(status_box), text_rend, TRUE);
754 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(status_box), icon_rend, "pixbuf", ICON_COLUMN, NULL); 791 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(status_box), icon_rend, "pixbuf", ICON_COLUMN, NULL);
755 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(status_box), text_rend, "markup", TEXT_COLUMN, NULL); 792 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(status_box), text_rend, "markup", TEXT_COLUMN, NULL);
756 793
794 status_box->icon_rend = gtk_cell_renderer_pixbuf_new();
795 status_box->text_rend = gtk_cell_renderer_text_new();
757 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(status_box->cell_view), status_box->icon_rend, FALSE); 796 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(status_box->cell_view), status_box->icon_rend, FALSE);
758 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(status_box->cell_view), status_box->text_rend, TRUE); 797 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(status_box->cell_view), status_box->text_rend, TRUE);
759 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(status_box->cell_view), status_box->icon_rend, "pixbuf", ICON_COLUMN, NULL); 798 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(status_box->cell_view), status_box->icon_rend, "pixbuf", ICON_COLUMN, NULL);
760 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(status_box->cell_view), status_box->text_rend, "markup", TEXT_COLUMN, NULL); 799 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(status_box->cell_view), status_box->text_rend, "markup", TEXT_COLUMN, NULL);
761 800
900 GtkTreeIter iter; 939 GtkTreeIter iter;
901 char *t; 940 char *t;
902 941
903 if (sec_text) { 942 if (sec_text) {
904 char aa_color[8]; 943 char aa_color[8];
944 gchar *escaped;
905 GtkStyle *style = gtk_widget_get_style(GTK_WIDGET(status_box)); 945 GtkStyle *style = gtk_widget_get_style(GTK_WIDGET(status_box));
906 snprintf(aa_color, sizeof(aa_color), "#%02x%02x%02x", 946 snprintf(aa_color, sizeof(aa_color), "#%02x%02x%02x",
907 style->text_aa[GTK_STATE_NORMAL].red >> 8, 947 style->text_aa[GTK_STATE_NORMAL].red >> 8,
908 style->text_aa[GTK_STATE_NORMAL].green >> 8, 948 style->text_aa[GTK_STATE_NORMAL].green >> 8,
909 style->text_aa[GTK_STATE_NORMAL].blue >> 8); 949 style->text_aa[GTK_STATE_NORMAL].blue >> 8);
910 t = g_strdup_printf("%s\n<span color=\"%s\">%s</span>", text, aa_color, sec_text); 950 escaped = g_markup_escape_text(sec_text, -1);
951 t = g_strdup_printf("%s\n<span color=\"%s\">%s</span>", text, aa_color, escaped);
952 g_free(escaped);
911 } else { 953 } else {
912 t = g_strdup(text); 954 t = g_markup_escape_text(text, -1);
913 } 955 }
914 956
915 gtk_list_store_append(status_box->dropdown_store, &iter); 957 gtk_list_store_append(status_box->dropdown_store, &iter);
916 gtk_list_store_set(status_box->dropdown_store, &iter, 958 gtk_list_store_set(status_box->dropdown_store, &iter,
917 TYPE_COLUMN, type, 959 TYPE_COLUMN, type,