Mercurial > pidgin.yaz
annotate src/gtkstatusbox.c @ 11638:3a05b53a589e
[gaim-migrate @ 13914]
Some bits'n'pieces:
A bunch of memory leak fixes
Fix newly created accounts to connect in the currently active global
status
Fix the modify account dialog to only show relevant user options etc.
Update sametime to use some more of the new status stuff, it still
needs more love though.
Some s/online/available/ for consistency across prpls
Fix a racyness in disconnecting connections that want to die (fixes
the Yahoo crash when signing on somewhere else)
Sorry if I caused any conflicts!
committer: Tailor Script <tailor@pidgin.im>
author | Stu Tomlinson <stu@nosnilmot.com> |
---|---|
date | Mon, 10 Oct 2005 17:59:48 +0000 |
parents | 5dbefebb20cb |
children | bf6ba37db13b |
rev | line source |
---|---|
10643 | 1 /* |
2 * @file gtkstatusbox.c GTK+ Status Selection Widget | |
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 | |
11627 | 26 #include "account.h" |
10643 | 27 #include "internal.h" |
11627 | 28 #include "savedstatuses.h" |
10643 | 29 #include "status.h" |
11627 | 30 |
10643 | 31 #include "gtkgaim.h" |
32 #include "gtkstock.h" | |
33 #include "gtkstatusbox.h" | |
34 | |
35 static void imhtml_changed_cb(GtkTextBuffer *buffer, void *data); | |
11562 | 36 static void remove_typing_cb(GtkGaimStatusBox *box); |
10643 | 37 |
38 static void gtk_gaim_status_box_changed(GtkComboBox *box); | |
39 static void gtk_gaim_status_box_size_request (GtkWidget *widget, GtkRequisition *requisition); | |
40 static void gtk_gaim_status_box_size_allocate (GtkWidget *widget, GtkAllocation *allocation); | |
41 static gboolean gtk_gaim_status_box_expose_event (GtkWidget *widget, GdkEventExpose *event); | |
42 static void gtk_gaim_status_box_forall (GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data); | |
43 | |
44 static void (*combo_box_size_request)(GtkWidget *widget, GtkRequisition *requisition); | |
45 static void (*combo_box_size_allocate)(GtkWidget *widget, GtkAllocation *allocation); | |
46 static gboolean (*combo_box_expose_event)(GtkWidget *widget, GdkEventExpose *event); | |
47 static void (*combo_box_forall) (GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data); | |
48 enum { | |
49 ICON_COLUMN, | |
50 TEXT_COLUMN, | |
51 TITLE_COLUMN, | |
52 DESC_COLUMN, | |
53 TYPE_COLUMN, | |
54 NUM_COLUMNS | |
55 }; | |
56 | |
11499 | 57 enum { |
58 PROP_0, | |
59 PROP_ACCOUNT | |
60 }; | |
61 | |
10643 | 62 static void gtk_gaim_status_box_class_init (GtkGaimStatusBoxClass *klass); |
63 static void gtk_gaim_status_box_init (GtkGaimStatusBox *status_box); | |
64 | |
65 GType | |
66 gtk_gaim_status_box_get_type (void) | |
67 { | |
10861 | 68 static GType status_box_type = 0; |
10643 | 69 |
10861 | 70 if (!status_box_type) |
71 { | |
72 static const GTypeInfo status_box_info = | |
73 { | |
74 sizeof (GtkGaimStatusBoxClass), | |
75 NULL, /* base_init */ | |
76 NULL, /* base_finalize */ | |
77 (GClassInitFunc) gtk_gaim_status_box_class_init, | |
78 NULL, /* class_finalize */ | |
79 NULL, /* class_data */ | |
80 sizeof (GtkGaimStatusBox), | |
81 0, | |
82 (GInstanceInitFunc) gtk_gaim_status_box_init | |
83 }; | |
10643 | 84 |
10861 | 85 status_box_type = g_type_register_static(GTK_TYPE_COMBO_BOX, |
86 "GtkGaimStatusBox", | |
87 &status_box_info, | |
88 0); | |
89 } | |
10643 | 90 |
10861 | 91 return status_box_type; |
10643 | 92 } |
93 | |
94 static void | |
11499 | 95 gtk_gaim_status_box_get_property(GObject *object, guint param_id, |
96 GValue *value, GParamSpec *psec) | |
97 { | |
98 GtkGaimStatusBox *statusbox = GTK_GAIM_STATUS_BOX(object); | |
99 | |
100 switch (param_id) { | |
101 case PROP_ACCOUNT: | |
102 g_value_set_pointer(value, statusbox->account); | |
103 break; | |
104 default: | |
105 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, psec); | |
106 break; | |
107 } | |
108 } | |
109 | |
110 static void | |
111 gtk_gaim_status_box_set_property(GObject *object, guint param_id, | |
112 const GValue *value, GParamSpec *pspec) | |
113 { | |
114 GtkGaimStatusBox *statusbox = GTK_GAIM_STATUS_BOX(object); | |
115 | |
116 switch (param_id) { | |
117 case PROP_ACCOUNT: | |
118 statusbox->account = g_value_get_pointer(value); | |
119 break; | |
120 default: | |
121 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); | |
122 break; | |
123 } | |
124 } | |
125 | |
126 | |
127 static void | |
10643 | 128 gtk_gaim_status_box_class_init (GtkGaimStatusBoxClass *klass) |
129 { | |
10861 | 130 GObjectClass *object_class; |
131 GtkWidgetClass *widget_class; | |
132 GtkComboBoxClass *parent_class = (GtkComboBoxClass*)klass; | |
133 GtkContainerClass *container_class = (GtkContainerClass*)klass; | |
10643 | 134 |
10861 | 135 parent_class->changed = gtk_gaim_status_box_changed; |
136 widget_class = (GtkWidgetClass*)klass; | |
137 combo_box_size_request = widget_class->size_request; | |
138 widget_class->size_request = gtk_gaim_status_box_size_request; | |
139 combo_box_size_allocate = widget_class->size_allocate; | |
140 widget_class->size_allocate = gtk_gaim_status_box_size_allocate; | |
141 combo_box_expose_event = widget_class->expose_event; | |
142 widget_class->expose_event = gtk_gaim_status_box_expose_event; | |
10643 | 143 |
10861 | 144 combo_box_forall = container_class->forall; |
145 container_class->forall = gtk_gaim_status_box_forall; | |
146 | |
147 object_class = (GObjectClass *)klass; | |
11499 | 148 |
149 object_class->get_property = gtk_gaim_status_box_get_property; | |
150 object_class->set_property = gtk_gaim_status_box_set_property; | |
151 | |
152 g_object_class_install_property(object_class, | |
153 PROP_ACCOUNT, | |
154 g_param_spec_pointer("account", | |
155 "Account", | |
156 "The account, or NULL for all accounts", | |
157 G_PARAM_READWRITE | |
158 ) | |
159 ); | |
10643 | 160 } |
161 | |
162 static void | |
163 gtk_gaim_status_box_refresh(GtkGaimStatusBox *status_box) | |
164 { | |
10672
0925c898b73c
[gaim-migrate @ 12212]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10661
diff
changeset
|
165 char *text, *title; |
10643 | 166 char aa_color[8]; |
167 GdkPixbuf *pixbuf; | |
10702 | 168 GtkTreePath *path; |
10643 | 169 |
170 GtkStyle *style = gtk_widget_get_style(GTK_WIDGET(status_box)); | |
171 snprintf(aa_color, sizeof(aa_color), "#%02x%02x%02x", | |
172 style->text_aa[GTK_STATE_NORMAL].red >> 8, | |
173 style->text_aa[GTK_STATE_NORMAL].green >> 8, | |
174 style->text_aa[GTK_STATE_NORMAL].blue >> 8); | |
10672
0925c898b73c
[gaim-migrate @ 12212]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10661
diff
changeset
|
175 |
0925c898b73c
[gaim-migrate @ 12212]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10661
diff
changeset
|
176 title = status_box->title; |
0925c898b73c
[gaim-migrate @ 12212]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10661
diff
changeset
|
177 if (!title) |
0925c898b73c
[gaim-migrate @ 12212]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10661
diff
changeset
|
178 title = ""; |
0925c898b73c
[gaim-migrate @ 12212]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10661
diff
changeset
|
179 |
10643 | 180 if (status_box->error) { |
11499 | 181 text = g_strdup_printf("%s\n<span size=\"smaller\" weight=\"bold\" color=\"red\">%s</span>", |
10861 | 182 title, status_box->error); |
10643 | 183 } else if (status_box->typing) { |
10861 | 184 text = g_strdup_printf("%s\n<span size=\"smaller\" color=\"%s\">%s</span>", |
185 title, aa_color, _("Typing")); | |
10643 | 186 } else if (status_box->connecting) { |
10861 | 187 text = g_strdup_printf("%s\n<span size=\"smaller\" color=\"%s\">%s</span>", |
188 title, aa_color, _("Connecting")); | |
189 } else if (status_box->desc) { | |
190 text = g_strdup_printf("%s\n<span size=\"smaller\" color=\"%s\">%s</span>", | |
191 title, aa_color, status_box->desc); | |
10643 | 192 } else { |
10672
0925c898b73c
[gaim-migrate @ 12212]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10661
diff
changeset
|
193 text = g_strdup_printf("%s", title); |
10643 | 194 } |
10861 | 195 |
11523 | 196 if (status_box->connecting) |
197 pixbuf = status_box->connecting_pixbufs[status_box->connecting_index]; | |
198 else if (status_box->error) | |
10643 | 199 pixbuf = status_box->error_pixbuf; |
200 else if (status_box->typing) | |
201 pixbuf = status_box->typing_pixbufs[status_box->typing_index]; | |
202 else | |
203 pixbuf = status_box->pixbuf; | |
204 | |
205 gtk_list_store_set(status_box->store, &(status_box->iter), | |
206 ICON_COLUMN, pixbuf, | |
10861 | 207 TEXT_COLUMN, text, |
10672
0925c898b73c
[gaim-migrate @ 12212]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10661
diff
changeset
|
208 TITLE_COLUMN, title, |
10861 | 209 DESC_COLUMN, status_box->desc, |
10643 | 210 TYPE_COLUMN, NULL, -1); |
10702 | 211 path = gtk_tree_path_new_from_string("0"); |
212 gtk_cell_view_set_displayed_row(GTK_CELL_VIEW(status_box->cell_view), path); | |
213 gtk_tree_path_free(path); | |
10643 | 214 |
215 g_free(text); | |
216 } | |
217 | |
218 static void | |
219 gtk_gaim_status_box_init (GtkGaimStatusBox *status_box) | |
220 { | |
11400 | 221 GtkCellRenderer *text_rend; |
222 GtkCellRenderer *icon_rend; | |
10643 | 223 GtkTextBuffer *buffer; |
224 GdkPixbuf *pixbuf, *pixbuf2, *pixbuf3, *pixbuf4; | |
11400 | 225 GtkIconSize icon_size; |
11593
4b7fb30b8926
[gaim-migrate @ 13863]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11562
diff
changeset
|
226 GtkTreePath *path; |
11627 | 227 const GList *list = NULL; |
11400 | 228 |
229 text_rend = gtk_cell_renderer_text_new(); | |
230 icon_rend = gtk_cell_renderer_pixbuf_new(); | |
231 icon_size = gtk_icon_size_from_name(GAIM_ICON_SIZE_STATUS); | |
10643 | 232 |
233 status_box->imhtml_visible = FALSE; | |
234 status_box->error_pixbuf = gtk_widget_render_icon (GTK_WIDGET(status_box), GAIM_STOCK_STATUS_OFFLINE, | |
235 icon_size, "GtkGaimStatusBox"); | |
236 status_box->connecting_index = 0; | |
10861 | 237 status_box->connecting_pixbufs[0] = gtk_widget_render_icon (GTK_WIDGET(status_box), GAIM_STOCK_STATUS_CONNECT0, |
10643 | 238 icon_size, "GtkGaimStatusBox"); |
10861 | 239 status_box->connecting_pixbufs[1] = gtk_widget_render_icon (GTK_WIDGET(status_box), GAIM_STOCK_STATUS_CONNECT1, |
10643 | 240 icon_size, "GtkGaimStatusBox"); |
10861 | 241 status_box->connecting_pixbufs[2] = gtk_widget_render_icon (GTK_WIDGET(status_box), GAIM_STOCK_STATUS_CONNECT2, |
10643 | 242 icon_size, "GtkGaimStatusBox"); |
10861 | 243 status_box->connecting_pixbufs[3] = gtk_widget_render_icon (GTK_WIDGET(status_box), GAIM_STOCK_STATUS_CONNECT3, |
10643 | 244 icon_size, "GtkGaimStatusBox"); |
245 | |
246 status_box->typing_index = 0; | |
247 status_box->typing_pixbufs[0] = gtk_widget_render_icon (GTK_WIDGET(status_box), GAIM_STOCK_STATUS_TYPING0, | |
248 icon_size, "GtkGaimStatusBox"); | |
249 status_box->typing_pixbufs[1] = gtk_widget_render_icon (GTK_WIDGET(status_box), GAIM_STOCK_STATUS_TYPING1, | |
250 icon_size, "GtkGaimStatusBox"); | |
251 status_box->typing_pixbufs[2] = gtk_widget_render_icon (GTK_WIDGET(status_box), GAIM_STOCK_STATUS_TYPING2, | |
252 icon_size, "GtkGaimStatusBox"); | |
253 status_box->typing_pixbufs[3] = gtk_widget_render_icon (GTK_WIDGET(status_box), GAIM_STOCK_STATUS_TYPING3, | |
254 icon_size, "GtkGaimStatusBox"); | |
255 status_box->connecting = FALSE; | |
256 status_box->typing = FALSE; | |
257 status_box->title = NULL; | |
10861 | 258 status_box->pixbuf = NULL; |
10643 | 259 status_box->cell_view = gtk_cell_view_new(); |
260 gtk_widget_show (status_box->cell_view); | |
10861 | 261 |
10643 | 262 status_box->store = gtk_list_store_new(NUM_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); |
263 status_box->dropdown_store = gtk_list_store_new(NUM_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); | |
264 gtk_combo_box_set_model(GTK_COMBO_BOX(status_box), GTK_TREE_MODEL(status_box->dropdown_store)); | |
265 gtk_cell_view_set_model(GTK_CELL_VIEW(status_box->cell_view), GTK_TREE_MODEL(status_box->store)); | |
266 gtk_combo_box_set_wrap_width(GTK_COMBO_BOX(status_box), 0); | |
267 gtk_list_store_append(status_box->store, &(status_box->iter)); | |
268 gtk_gaim_status_box_refresh(status_box); | |
11593
4b7fb30b8926
[gaim-migrate @ 13863]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11562
diff
changeset
|
269 path = gtk_tree_path_new_from_string("0"); |
4b7fb30b8926
[gaim-migrate @ 13863]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11562
diff
changeset
|
270 gtk_cell_view_set_displayed_row(GTK_CELL_VIEW(status_box->cell_view), path); |
4b7fb30b8926
[gaim-migrate @ 13863]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11562
diff
changeset
|
271 gtk_tree_path_free(path); |
10643 | 272 gtk_container_add(GTK_CONTAINER(status_box), status_box->cell_view); |
10861 | 273 |
10643 | 274 status_box->icon_rend = gtk_cell_renderer_pixbuf_new(); |
275 status_box->text_rend = gtk_cell_renderer_text_new(); | |
276 | |
277 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(status_box), icon_rend, FALSE); | |
10861 | 278 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(status_box), text_rend, TRUE); |
10643 | 279 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(status_box), icon_rend, "pixbuf", ICON_COLUMN, NULL); |
280 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(status_box), text_rend, "markup", TEXT_COLUMN, NULL); | |
281 | |
282 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(status_box->cell_view), status_box->icon_rend, FALSE); | |
11499 | 283 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(status_box->cell_view), status_box->text_rend, TRUE); |
10643 | 284 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(status_box->cell_view), status_box->icon_rend, "pixbuf", ICON_COLUMN, NULL); |
285 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(status_box->cell_view), status_box->text_rend, "markup", TEXT_COLUMN, NULL); | |
286 | |
287 status_box->vbox = gtk_vbox_new(0, FALSE); | |
288 status_box->imhtml = gtk_imhtml_new(NULL, NULL); | |
289 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(status_box->imhtml)); | |
290 g_signal_connect(G_OBJECT(buffer), "changed", G_CALLBACK(imhtml_changed_cb), status_box); | |
11562 | 291 g_signal_connect_swapped(G_OBJECT(status_box->imhtml), "message_send", G_CALLBACK(remove_typing_cb), status_box); |
10643 | 292 gtk_imhtml_set_editable(GTK_IMHTML(status_box->imhtml), TRUE); |
293 gtk_widget_set_parent(status_box->vbox, GTK_WIDGET(status_box)); | |
294 status_box->sw = gtk_scrolled_window_new(NULL, NULL); | |
295 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(status_box->sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); | |
296 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(status_box->sw), GTK_SHADOW_IN); | |
297 gtk_container_add(GTK_CONTAINER(status_box->sw), status_box->imhtml); | |
298 gtk_box_pack_start(GTK_BOX(status_box->vbox), status_box->sw, TRUE, TRUE, 0); | |
299 pixbuf = gtk_widget_render_icon (GTK_WIDGET(status_box), GAIM_STOCK_STATUS_ONLINE, | |
300 icon_size, "GtkGaimStatusBox"); | |
301 pixbuf2 = gtk_widget_render_icon (GTK_WIDGET(status_box), GAIM_STOCK_STATUS_AWAY, | |
302 icon_size, "GtkGaimStatusBox"); | |
303 pixbuf3 = gtk_widget_render_icon (GTK_WIDGET(status_box), GAIM_STOCK_STATUS_OFFLINE, | |
304 icon_size, "GtkGaimStatusBox"); | |
305 pixbuf4 = gtk_widget_render_icon (GTK_WIDGET(status_box), GAIM_STOCK_STATUS_INVISIBLE, | |
306 icon_size, "GtkGaimStatusBox"); | |
307 /* hacks */ | |
308 gtk_gaim_status_box_add(GTK_GAIM_STATUS_BOX(status_box), pixbuf, _("Available"), NULL, "available"); | |
309 gtk_gaim_status_box_add(GTK_GAIM_STATUS_BOX(status_box), pixbuf2, _("Away"), NULL, "away"); | |
310 gtk_gaim_status_box_add(GTK_GAIM_STATUS_BOX(status_box), pixbuf4, _("Invisible"), NULL, "invisible"); | |
311 gtk_gaim_status_box_add(GTK_GAIM_STATUS_BOX(status_box), pixbuf3, _("Offline"), NULL, "offline"); | |
11306 | 312 /* |
313 * TODO: This triggers a callback of gaim_gtk_status_box_changed(). | |
314 * That's bad. We should at least try not figure out what | |
315 * status the user's accounts are set to instead of always | |
316 * using "Available." | |
317 */ | |
11347 | 318 /* gtk_combo_box_set_active(GTK_COMBO_BOX(status_box), 0); */ |
10643 | 319 |
11627 | 320 |
321 for (list = gaim_savedstatuses_get_all(); list; list = list->next) { | |
322 GaimSavedStatus *status = list->data; | |
323 | |
324 gtk_gaim_status_box_add(GTK_GAIM_STATUS_BOX(status_box), pixbuf2, | |
325 gaim_savedstatus_get_title(status), NULL, "saved"); | |
326 } | |
327 | |
10643 | 328 } |
329 | |
330 | |
331 static void | |
10861 | 332 gtk_gaim_status_box_size_request(GtkWidget *widget, |
333 GtkRequisition *requisition) | |
10643 | 334 { |
335 GtkRequisition box_req; | |
336 combo_box_size_request(widget, requisition); | |
10861 | 337 |
10643 | 338 gtk_widget_size_request(GTK_GAIM_STATUS_BOX(widget)->vbox, &box_req); |
339 if (box_req.height > 1) | |
340 requisition->height = requisition->height + box_req.height + 6; | |
10861 | 341 |
10643 | 342 requisition->width = 1; |
343 | |
344 } | |
345 | |
346 static void | |
10861 | 347 gtk_gaim_status_box_size_allocate(GtkWidget *widget, |
348 GtkAllocation *allocation) | |
10643 | 349 { |
350 GtkRequisition req = {0,0}; | |
11400 | 351 GtkAllocation parent_alc, box_alc; |
352 | |
353 parent_alc = *allocation; | |
354 box_alc = *allocation; | |
10643 | 355 combo_box_size_request(widget, &req); |
10861 | 356 |
10643 | 357 /* EVIL XXX */ |
10861 | 358 box_alc.height = 80; |
359 /* box_alc.height = MAX(1,box_alc.height - req.height - 6); */ | |
360 | |
10643 | 361 box_alc.y = box_alc.y + req.height + 6; |
362 gtk_widget_size_allocate((GTK_GAIM_STATUS_BOX(widget))->vbox, &box_alc); | |
10861 | 363 |
10643 | 364 parent_alc.height = MAX(1,req.height); |
365 combo_box_size_allocate(widget, &parent_alc); | |
366 widget->allocation = *allocation; | |
367 } | |
368 | |
369 | |
370 static gboolean | |
10861 | 371 gtk_gaim_status_box_expose_event(GtkWidget *widget, |
372 GdkEventExpose *event) | |
10643 | 373 { |
10861 | 374 GtkGaimStatusBox *status_box = GTK_GAIM_STATUS_BOX(widget); |
375 combo_box_expose_event(widget, event); | |
10643 | 376 |
10861 | 377 gtk_container_propagate_expose(GTK_CONTAINER(widget), |
378 status_box->vbox, event); | |
379 return FALSE; | |
10643 | 380 } |
381 | |
382 static void | |
10861 | 383 gtk_gaim_status_box_forall(GtkContainer *container, |
384 gboolean include_internals, | |
385 GtkCallback callback, | |
386 gpointer callback_data) | |
10643 | 387 { |
10861 | 388 GtkGaimStatusBox *status_box = GTK_GAIM_STATUS_BOX (container); |
10643 | 389 |
10861 | 390 if (include_internals) |
391 { | |
392 (* callback) (status_box->vbox, callback_data); | |
393 } | |
10643 | 394 |
10861 | 395 combo_box_forall(container, include_internals, callback, callback_data); |
10643 | 396 } |
397 | |
398 GtkWidget * | |
399 gtk_gaim_status_box_new() | |
400 { | |
401 return g_object_new(GTK_GAIM_TYPE_STATUS_BOX, NULL); | |
402 } | |
403 | |
11499 | 404 GtkWidget * |
405 gtk_gaim_status_box_new_with_account(GaimAccount *account) | |
406 { | |
407 return g_object_new(GTK_GAIM_TYPE_STATUS_BOX, "account", account, NULL); | |
408 } | |
10643 | 409 |
410 void | |
411 gtk_gaim_status_box_add(GtkGaimStatusBox *status_box, GdkPixbuf *pixbuf, const char *text, const char *sec_text, char *edit) | |
412 { | |
413 GtkTreeIter iter; | |
414 char *t; | |
10861 | 415 |
10643 | 416 if (sec_text) { |
417 char aa_color[8]; | |
418 GtkStyle *style = gtk_widget_get_style(GTK_WIDGET(status_box)); | |
419 snprintf(aa_color, sizeof(aa_color), "#%02x%02x%02x", | |
420 style->text_aa[GTK_STATE_NORMAL].red >> 8, | |
421 style->text_aa[GTK_STATE_NORMAL].green >> 8, | |
10861 | 422 style->text_aa[GTK_STATE_NORMAL].blue >> 8); |
10643 | 423 t = g_strdup_printf("%s\n<span color=\"%s\">%s</span>", text, aa_color, sec_text); |
424 } else { | |
425 t = g_strdup(text); | |
426 } | |
10861 | 427 |
10643 | 428 gtk_list_store_append(status_box->dropdown_store, &iter); |
429 gtk_list_store_set(status_box->dropdown_store, &iter, | |
430 ICON_COLUMN, pixbuf, | |
10861 | 431 TEXT_COLUMN, t, |
10643 | 432 TITLE_COLUMN, text, |
10861 | 433 DESC_COLUMN, sec_text, |
10643 | 434 TYPE_COLUMN, edit, -1); |
11638 | 435 g_free(t); |
10643 | 436 } |
437 | |
438 void | |
439 gtk_gaim_status_box_set_error(GtkGaimStatusBox *status_box, const gchar *error) | |
440 { | |
11523 | 441 if (status_box->error) |
442 g_free(status_box->error); | |
10643 | 443 status_box->error = g_strdup(error); |
444 gtk_gaim_status_box_refresh(status_box); | |
445 } | |
446 | |
447 void | |
448 gtk_gaim_status_box_set_connecting(GtkGaimStatusBox *status_box, gboolean connecting) | |
449 { | |
450 if (!status_box) | |
451 return; | |
452 status_box->connecting = connecting; | |
453 gtk_gaim_status_box_refresh(status_box); | |
454 } | |
455 | |
456 void | |
457 gtk_gaim_status_box_pulse_connecting(GtkGaimStatusBox *status_box) | |
458 { | |
459 if (!status_box) | |
460 return; | |
461 if (status_box->connecting_index == 3) | |
462 status_box->connecting_index = 0; | |
10861 | 463 else |
10643 | 464 status_box->connecting_index++; |
465 gtk_gaim_status_box_refresh(status_box); | |
466 } | |
467 | |
468 void | |
469 gtk_gaim_status_box_pulse_typing(GtkGaimStatusBox *status_box) | |
470 { | |
471 if (status_box->typing_index == 3) | |
472 status_box->typing_index = 0; | |
10861 | 473 else |
10643 | 474 status_box->typing_index++; |
475 gtk_gaim_status_box_refresh(status_box); | |
476 } | |
477 | |
478 static void remove_typing_cb(GtkGaimStatusBox *box) | |
479 { | |
11638 | 480 gchar *status_type_id, *title; |
10643 | 481 GList *l; |
482 GtkTreeIter iter; | |
483 | |
484 gtk_combo_box_get_active_iter(GTK_COMBO_BOX(box), &iter); | |
11638 | 485 gtk_tree_model_get(GTK_TREE_MODEL(box->dropdown_store), &iter, |
486 TYPE_COLUMN, &status_type_id, | |
487 TITLE_COLUMN, &title, -1); | |
10643 | 488 for (l = gaim_accounts_get_all(); l != NULL; l = l->next) { |
489 GaimAccount *account = (GaimAccount*)l->data; | |
490 GaimStatusType *status_type; | |
11638 | 491 gchar *msg; |
10861 | 492 |
10643 | 493 if (!gaim_account_get_enabled(account, GAIM_GTK_UI)) |
494 continue; | |
495 | |
11627 | 496 /* I am not very comfortable with this, but can't think of a better way. */ |
11638 | 497 /* XXX: this is definitely wrong - the specific account's saved status should |
498 * be looked for */ | |
11627 | 499 if (!strcmp(status_type_id, "saved")) |
500 { | |
501 GaimSavedStatus *saved = NULL; | |
502 GaimStatusPrimitive type; | |
503 | |
504 saved = gaim_savedstatus_find(title); | |
505 type = gaim_savedstatus_get_type(saved); | |
11638 | 506 g_free(status_type_id); |
507 status_type_id = g_strdup(gaim_primitive_get_id_from_type(type)); | |
11627 | 508 } |
509 | |
10643 | 510 status_type = gaim_account_get_status_type(account, status_type_id); |
511 | |
512 if (status_type == NULL) | |
513 continue; | |
11638 | 514 |
515 msg = gtk_imhtml_get_markup(GTK_IMHTML(box->imhtml)); | |
10861 | 516 gaim_account_set_status(account, status_type_id, TRUE, |
11638 | 517 "message", msg, NULL); |
518 g_free(msg); | |
10643 | 519 } |
520 g_source_remove(box->typing); | |
521 box->typing = 0; | |
522 gtk_gaim_status_box_refresh(box); | |
11627 | 523 |
524 /* How about saving the status here.. where title = first X characters of the message. | |
525 * The user can alway edit the title later from Tools->Statuses if necessary | |
526 */ | |
11638 | 527 g_free(status_type_id); |
528 g_free(title); | |
10643 | 529 } |
530 | |
531 static void gtk_gaim_status_box_changed(GtkComboBox *box) | |
532 { | |
11400 | 533 GtkGaimStatusBox *status_box; |
10643 | 534 GtkTreeIter iter; |
535 char *text, *sec_text; | |
536 GdkPixbuf *pixbuf; | |
537 gchar *status_type_id; | |
538 GList *l; | |
539 | |
11400 | 540 status_box = GTK_GAIM_STATUS_BOX(box); |
541 | |
10643 | 542 gtk_combo_box_get_active_iter(GTK_COMBO_BOX(status_box), &iter); |
543 gtk_tree_model_get(GTK_TREE_MODEL(status_box->dropdown_store), &iter, TITLE_COLUMN, &text, | |
10861 | 544 DESC_COLUMN, &sec_text, ICON_COLUMN, &pixbuf, |
10643 | 545 TYPE_COLUMN, &status_type_id, -1); |
546 if (status_box->title) | |
547 g_free(status_box->title); | |
11638 | 548 status_box->title = text; |
10643 | 549 if (status_box->desc && sec_text) |
11638 | 550 g_free(status_box->desc); |
551 status_box->desc = sec_text; | |
10643 | 552 if (status_box->pixbuf) |
553 g_object_unref(status_box->pixbuf); | |
554 status_box->pixbuf = pixbuf; | |
11638 | 555 if (status_box->typing) |
556 g_source_remove(status_box->typing); | |
557 status_box->typing = 0; | |
10861 | 558 |
11627 | 559 if (!strcmp(status_type_id, "away") || !strcmp(status_type_id, "saved")) { |
10643 | 560 gtk_widget_show_all(status_box->vbox); |
561 status_box->typing = g_timeout_add(3000, (GSourceFunc)remove_typing_cb, status_box); | |
562 gtk_imhtml_clear(GTK_IMHTML(status_box->imhtml)); | |
563 gtk_widget_grab_focus(status_box->imhtml); | |
11627 | 564 |
565 /* If it's one of the saved statuses, then set the away message to that. */ | |
566 if (!strcmp(status_type_id, "saved")) { | |
567 GaimSavedStatus *status = NULL; | |
568 status = gaim_savedstatus_find(text); | |
569 gtk_imhtml_append_text(GTK_IMHTML(status_box->imhtml), gaim_savedstatus_get_message(status), 0); | |
570 } | |
10643 | 571 } else { |
572 gtk_widget_hide_all(status_box->vbox); | |
573 for (l = gaim_accounts_get_all(); l != NULL; l = l->next) { | |
574 GaimAccount *account = (GaimAccount*)l->data; | |
575 GaimStatusType *status_type; | |
576 | |
577 if (!gaim_account_get_enabled(account, GAIM_GTK_UI)) | |
578 continue; | |
579 | |
580 status_type = gaim_account_get_status_type(account, status_type_id); | |
581 | |
582 if (status_type == NULL) | |
583 continue; | |
584 gaim_account_set_status(account, status_type_id, TRUE, NULL); | |
585 } | |
586 } | |
11638 | 587 g_free(status_type_id); |
10643 | 588 gtk_gaim_status_box_refresh(status_box); |
589 } | |
590 | |
591 static void imhtml_changed_cb(GtkTextBuffer *buffer, void *data) | |
592 { | |
593 GtkGaimStatusBox *box = (GtkGaimStatusBox*)data; | |
594 if (box->typing) { | |
595 gtk_gaim_status_box_pulse_typing(box); | |
596 g_source_remove(box->typing); | |
10861 | 597 } |
10643 | 598 box->typing = g_timeout_add(3000, (GSourceFunc)remove_typing_cb, box); |
599 gtk_gaim_status_box_refresh(box); | |
600 } | |
10649 | 601 |
11638 | 602 char *gtk_gaim_status_box_get_active_type(GtkGaimStatusBox *status_box) |
10649 | 603 { |
604 GtkTreeIter iter; | |
605 char *type; | |
606 gtk_combo_box_get_active_iter(GTK_COMBO_BOX(status_box), &iter); | |
10861 | 607 gtk_tree_model_get(GTK_TREE_MODEL(status_box->dropdown_store), &iter, |
10649 | 608 TYPE_COLUMN, &type, -1); |
609 return type; | |
610 } | |
611 | |
11638 | 612 char *gtk_gaim_status_box_get_message(GtkGaimStatusBox *status_box) |
10649 | 613 { |
614 if (status_box->imhtml_visible) | |
615 return gtk_imhtml_get_markup(GTK_IMHTML(status_box->imhtml)); | |
616 else | |
617 return NULL; | |
618 } |