Mercurial > pidgin
annotate src/gtkstatusselector.c @ 10197:7369bf2bf593
[gaim-migrate @ 11314]
More status fixes. Oscar kind of works... you can set yourself away,
invisible and available, but you can't choose the message for away,
can't choose an available message, and invisible only seems to work
the first time.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Wed, 17 Nov 2004 01:32:06 +0000 |
parents | 0f86175b41a4 |
children | 76e296e16def |
rev | line source |
---|---|
10178 | 1 /** |
2 * @file gtkstatusselector.c Status selector 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 #include "internal.h" | |
26 #include "gtkgaim.h" | |
27 #include "gtkimhtml.h" | |
28 #include "gtkstatusselector.h" | |
29 #include "gtkutils.h" | |
30 | |
31 #include "account.h" | |
32 #include "debug.h" | |
33 #include "prefs.h" | |
34 | |
35 struct _GaimGtkStatusSelectorPrivate | |
36 { | |
37 GtkWidget *combo; | |
38 GtkWidget *entry; | |
10191 | 39 GtkWidget *frame; |
10178 | 40 |
41 #if GTK_CHECK_VERSION(2,4,0) | |
42 GtkListStore *model; | |
43 #endif | |
44 }; | |
45 | |
46 #if GTK_CHECK_VERSION(2,4,0) | |
47 enum | |
48 { | |
49 COLUMN_STATUS_TYPE_ID, | |
50 COLUMN_ICON, | |
51 COLUMN_NAME, | |
52 NUM_COLUMNS | |
53 }; | |
54 #endif /* GTK >= 2.4.0 */ | |
55 | |
56 static void gaim_gtk_status_selector_class_init(GaimGtkStatusSelectorClass *klass); | |
57 static void gaim_gtk_status_selector_init(GaimGtkStatusSelector *selector); | |
58 static void gaim_gtk_status_selector_finalize(GObject *obj); | |
59 static void gaim_gtk_status_selector_destroy(GtkObject *obj); | |
60 static void status_switched_cb(GtkWidget *combo, GaimGtkStatusSelector *selector); | |
61 static void signed_on_off_cb(GaimConnection *gc, GaimGtkStatusSelector *selector); | |
62 static void rebuild_list(GaimGtkStatusSelector *selector); | |
63 | |
64 static GtkVBox *parent_class = NULL; | |
65 | |
66 GType | |
67 gaim_gtk_status_selector_get_type(void) | |
68 { | |
69 static GType type = 0; | |
70 | |
71 if (!type) | |
72 { | |
73 static const GTypeInfo info = | |
74 { | |
75 sizeof(GaimGtkStatusSelectorClass), | |
76 NULL, | |
77 NULL, | |
78 (GClassInitFunc)gaim_gtk_status_selector_class_init, | |
79 NULL, | |
80 NULL, | |
81 sizeof(GaimGtkStatusSelector), | |
82 0, | |
83 (GInstanceInitFunc)gaim_gtk_status_selector_init | |
84 }; | |
85 | |
86 type = g_type_register_static(GTK_TYPE_VBOX, | |
87 "GaimGtkStatusSelector", &info, 0); | |
88 } | |
89 | |
90 return type; | |
91 } | |
92 | |
93 static void | |
94 gaim_gtk_status_selector_class_init(GaimGtkStatusSelectorClass *klass) | |
95 { | |
96 GObjectClass *gobject_class; | |
97 GtkObjectClass *object_class; | |
98 | |
99 parent_class = g_type_class_peek_parent(klass); | |
100 | |
101 gobject_class = G_OBJECT_CLASS(klass); | |
102 object_class = GTK_OBJECT_CLASS(klass); | |
103 | |
104 gobject_class->finalize = gaim_gtk_status_selector_finalize; | |
105 | |
106 object_class->destroy = gaim_gtk_status_selector_destroy; | |
107 } | |
108 | |
109 static void | |
110 gaim_gtk_status_selector_init(GaimGtkStatusSelector *selector) | |
111 { | |
112 GtkWidget *combo; | |
113 GtkWidget *entry; | |
10191 | 114 GtkWidget *toolbar; |
115 GtkWidget *frame; | |
10178 | 116 #if GTK_CHECK_VERSION(2,4,0) |
117 GtkCellRenderer *renderer; | |
118 #endif | |
119 | |
120 selector->priv = g_new0(GaimGtkStatusSelectorPrivate, 1); | |
121 | |
122 #if GTK_CHECK_VERSION(2,4,0) | |
123 selector->priv->model = gtk_list_store_new(NUM_COLUMNS, G_TYPE_POINTER, | |
124 GDK_TYPE_PIXBUF, G_TYPE_STRING); | |
125 | |
126 combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(selector->priv->model)); | |
127 selector->priv->combo = combo; | |
128 | |
129 g_object_unref(G_OBJECT(selector->priv->model)); | |
130 | |
131 renderer = gtk_cell_renderer_pixbuf_new(); | |
132 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), renderer, FALSE); | |
133 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), renderer, | |
134 "pixbuf", COLUMN_ICON, | |
135 NULL); | |
136 | |
137 renderer = gtk_cell_renderer_text_new(); | |
138 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), renderer, TRUE); | |
139 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), renderer, | |
140 "text", COLUMN_NAME, | |
141 NULL); | |
142 | |
143 g_signal_connect(G_OBJECT(combo), "changed", | |
144 G_CALLBACK(status_switched_cb), selector); | |
145 #else /* GTK < 2.4.0 */ | |
146 | |
147 /* TODO */ | |
148 | |
149 #endif /* GTK < 2.4.0 */ | |
150 | |
151 gtk_widget_show(combo); | |
152 gtk_box_pack_start(GTK_BOX(selector), combo, FALSE, FALSE, 0); | |
153 | |
10191 | 154 frame = gaim_gtk_create_imhtml(TRUE, &entry, &toolbar); |
155 selector->priv->entry = entry; | |
156 selector->priv->frame = frame; | |
157 gtk_widget_set_name(entry, "gaim_gtkstatusselector_imhtml"); | |
158 gtk_box_pack_start(GTK_BOX(selector), frame, TRUE, TRUE, 0); | |
159 gtk_widget_hide(toolbar); | |
10178 | 160 |
161 gaim_signal_connect(gaim_connections_get_handle(), "signed-on", | |
162 selector, GAIM_CALLBACK(signed_on_off_cb), | |
163 selector); | |
164 gaim_signal_connect(gaim_connections_get_handle(), "signed-off", | |
165 selector, GAIM_CALLBACK(signed_on_off_cb), | |
166 selector); | |
167 | |
168 rebuild_list(selector); | |
169 } | |
170 | |
171 static void | |
172 gaim_gtk_status_selector_finalize(GObject *obj) | |
173 { | |
174 GaimGtkStatusSelector *selector; | |
175 | |
176 g_return_if_fail(obj != NULL); | |
177 g_return_if_fail(GAIM_GTK_IS_STATUS_SELECTOR(obj)); | |
178 | |
179 selector = GAIM_GTK_STATUS_SELECTOR(obj); | |
180 | |
181 g_free(selector->priv); | |
182 | |
183 if (G_OBJECT_CLASS(parent_class)->finalize) | |
184 G_OBJECT_CLASS(parent_class)->finalize(obj); | |
185 } | |
186 | |
187 static void | |
188 gaim_gtk_status_selector_destroy(GtkObject *obj) | |
189 { | |
190 GaimGtkStatusSelector *selector; | |
191 | |
192 g_return_if_fail(obj != NULL); | |
193 g_return_if_fail(GAIM_GTK_IS_STATUS_SELECTOR(obj)); | |
194 | |
195 selector = GAIM_GTK_STATUS_SELECTOR(obj); | |
196 | |
10187 | 197 gaim_signals_disconnect_by_handle(selector); |
198 | |
10178 | 199 if (GTK_OBJECT_CLASS(parent_class)->destroy) |
200 GTK_OBJECT_CLASS(parent_class)->destroy(obj); | |
201 } | |
202 | |
203 static void | |
204 status_switched_cb(GtkWidget *combo, GaimGtkStatusSelector *selector) | |
205 { | |
206 GtkTreeIter iter; | |
10188 | 207 const char *status_type_id; |
10191 | 208 const char *text; |
10188 | 209 GList *l; |
10178 | 210 |
10188 | 211 if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(selector->priv->combo), |
10178 | 212 &iter)) |
213 { | |
10188 | 214 return; |
215 } | |
216 | |
217 gtk_tree_model_get(GTK_TREE_MODEL(selector->priv->model), &iter, | |
218 COLUMN_NAME, &text, | |
219 COLUMN_STATUS_TYPE_ID, &status_type_id, | |
220 -1); | |
10178 | 221 |
10191 | 222 if (status_type_id == NULL) |
223 { | |
224 if (!strcmp(text, _("New Status"))) | |
225 { | |
226 /* TODO */ | |
227 } | |
228 } | |
10197 | 229 else |
10188 | 230 { |
10197 | 231 const char *message = text; |
10188 | 232 GtkTextBuffer *buffer; |
233 gboolean allow_message = FALSE; | |
10178 | 234 |
10188 | 235 buffer = |
236 gtk_text_view_get_buffer(GTK_TEXT_VIEW(selector->priv->entry)); | |
237 | |
238 gtk_text_buffer_set_text(buffer, message, -1); | |
239 | |
240 for (l = gaim_connections_get_all(); l != NULL; l = l->next) | |
10178 | 241 { |
10188 | 242 GaimConnection *gc = (GaimConnection *)l->data; |
243 GaimAccount *account = gaim_connection_get_account(gc); | |
244 GaimStatusType *status_type; | |
10178 | 245 |
10188 | 246 status_type = gaim_account_get_status_type(account, |
247 status_type_id); | |
10178 | 248 |
10188 | 249 if (status_type == NULL) |
250 continue; | |
10178 | 251 |
10188 | 252 if (gaim_status_type_get_attr(status_type, "message") != NULL) |
10178 | 253 { |
10188 | 254 gaim_account_set_status(account, |
10197 | 255 status_type_id, TRUE, |
10188 | 256 "message", message, |
257 NULL); | |
10178 | 258 |
10188 | 259 allow_message = TRUE; |
260 } | |
261 else | |
262 { | |
263 gaim_account_set_status(account, | |
10197 | 264 status_type_id, TRUE, |
10188 | 265 NULL); |
266 } | |
267 } | |
10178 | 268 |
10188 | 269 if (allow_message) |
10191 | 270 gtk_widget_show(selector->priv->frame); |
10188 | 271 else |
10191 | 272 gtk_widget_hide(selector->priv->frame); |
10178 | 273 } |
274 } | |
275 | |
276 static void | |
277 signed_on_off_cb(GaimConnection *gc, GaimGtkStatusSelector *selector) | |
278 { | |
279 rebuild_list(selector); | |
280 } | |
281 | |
282 static GdkPixbuf * | |
283 load_icon(const char *basename) | |
284 { | |
285 char *filename; | |
286 GdkPixbuf *pixbuf, *scale = NULL; | |
287 | |
288 if (!strcmp(basename, "available.png")) | |
289 basename = "online.png"; | |
290 else if (!strcmp(basename, "hidden.png")) | |
291 basename = "invisible.png"; | |
292 | |
293 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "icons", | |
294 basename, NULL); | |
295 pixbuf = gdk_pixbuf_new_from_file(filename, NULL); | |
296 g_free(filename); | |
297 | |
298 if (pixbuf != NULL) | |
299 { | |
300 scale = gdk_pixbuf_scale_simple(pixbuf, 16, 16, | |
301 GDK_INTERP_BILINEAR); | |
302 | |
303 g_object_unref(G_OBJECT(pixbuf)); | |
304 } | |
305 else | |
306 { | |
307 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", | |
308 "default", basename, NULL); | |
309 scale = gdk_pixbuf_new_from_file(filename, NULL); | |
310 g_free(filename); | |
311 } | |
312 | |
313 return scale; | |
314 } | |
315 | |
316 static void | |
317 add_item(GaimGtkStatusSelector *selector, const char *status_type_id, | |
318 const char *text, GdkPixbuf *pixbuf) | |
319 { | |
320 GtkTreeIter iter; | |
321 | |
322 gtk_list_store_append(selector->priv->model, &iter); | |
323 gtk_list_store_set(selector->priv->model, &iter, | |
324 COLUMN_STATUS_TYPE_ID, status_type_id, | |
325 COLUMN_ICON, pixbuf, | |
326 COLUMN_NAME, text, | |
327 -1); | |
328 | |
329 if (pixbuf != NULL) | |
330 g_object_unref(G_OBJECT(pixbuf)); | |
331 } | |
332 | |
333 static void | |
334 rebuild_list(GaimGtkStatusSelector *selector) | |
335 { | |
336 gboolean single_prpl = TRUE; | |
337 GaimAccount *first_account = NULL; | |
338 const char *first_prpl_type = NULL; | |
339 GList *l; | |
340 | |
341 g_return_if_fail(selector != NULL); | |
342 g_return_if_fail(GAIM_GTK_IS_STATUS_SELECTOR(selector)); | |
343 | |
344 gtk_list_store_clear(selector->priv->model); | |
345 | |
346 /* | |
347 * If the user only has one IM account or one type of IM account | |
348 * connected, they'll see all their statuses. This is ideal for those | |
349 * who use only one account, or one single protocol. Everyone else | |
350 * gets Available and Away and a list of saved statuses. | |
351 */ | |
352 for (l = gaim_connections_get_all(); l != NULL && single_prpl; l = l->next) | |
353 { | |
354 GaimConnection *gc = (GaimConnection *)l->data; | |
355 GaimAccount *account = gaim_connection_get_account(gc); | |
356 GaimPluginProtocolInfo *prpl_info; | |
357 const char *basename; | |
358 | |
359 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl); | |
360 basename = prpl_info->list_icon(account, NULL); | |
361 | |
362 if (first_prpl_type == NULL) | |
363 { | |
364 first_prpl_type = basename; | |
365 first_account = account; | |
366 } | |
10179
97ee3bf7bcf7
[gaim-migrate @ 11294]
Christian Hammond <chipx86@chipx86.com>
parents:
10178
diff
changeset
|
367 else if (strcmp(first_prpl_type, basename)) |
10178 | 368 single_prpl = FALSE; |
369 } | |
370 | |
371 if (single_prpl) | |
372 { | |
373 const GList *l; | |
374 | |
375 for (l = gaim_account_get_status_types(first_account); | |
376 l != NULL; | |
377 l = l->next) | |
378 { | |
379 GaimStatusType *status_type = (GaimStatusType *)l->data; | |
380 char filename[BUFSIZ]; | |
381 | |
382 if (!gaim_status_type_is_user_settable(status_type)) | |
383 continue; | |
384 | |
385 g_snprintf(filename, sizeof(filename), "%s.png", | |
386 gaim_status_type_get_id(status_type)); | |
387 | |
388 add_item(selector, | |
389 gaim_status_type_get_id(status_type), | |
390 gaim_status_type_get_name(status_type), | |
391 load_icon(filename)); | |
392 } | |
393 } | |
394 else | |
395 { | |
396 add_item(selector, "available", _("Available"), | |
397 load_icon("online.png")); | |
398 add_item(selector, "away", _("Away"), load_icon("away.png")); | |
399 } | |
400 | |
10191 | 401 /* TODO: Add saved statuses here? */ |
402 | |
10178 | 403 add_item(selector, NULL, _("New Status"), |
404 gtk_widget_render_icon(GTK_WIDGET(selector), GTK_STOCK_NEW, | |
405 GTK_ICON_SIZE_MENU, NULL)); | |
406 } | |
407 | |
408 GtkWidget * | |
409 gaim_gtk_status_selector_new(void) | |
410 { | |
411 GaimGtkStatusSelector *selector; | |
412 | |
413 selector = g_object_new(GAIM_GTK_TYPE_STATUS_SELECTOR, NULL); | |
414 | |
415 return GTK_WIDGET(selector); | |
416 } |