Mercurial > pidgin
annotate src/gtkblist.c @ 11635:e95c37720766
[gaim-migrate @ 13911]
If someone in your buddy list is idle, but not away, and you sign
on with your Yahoo! account, previosly the person would remain
offline. They should now correctly appear online and idle.
No wukkaz.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Mon, 10 Oct 2005 05:12:55 +0000 |
parents | c7305c2d650b |
children | 2f7558b0c01b |
rev | line source |
---|---|
5228 | 1 /* |
10297
ec140184437b
[gaim-migrate @ 11480]
Luke Schierer <lschiere@pidgin.im>
parents:
10288
diff
changeset
|
2 * @file gtkblist.c GTK+ BuddyList API |
ec140184437b
[gaim-migrate @ 11480]
Luke Schierer <lschiere@pidgin.im>
parents:
10288
diff
changeset
|
3 * @ingroup gtkui |
ec140184437b
[gaim-migrate @ 11480]
Luke Schierer <lschiere@pidgin.im>
parents:
10288
diff
changeset
|
4 * |
5228 | 5 * gaim |
6 * | |
8046 | 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. | |
5228 | 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 */ | |
9791 | 26 #include "internal.h" |
27 #include "gtkgaim.h" | |
7620 | 28 |
29 #include "account.h" | |
9015 | 30 #include "connection.h" |
7620 | 31 #include "core.h" |
32 #include "debug.h" | |
33 #include "notify.h" | |
34 #include "prpl.h" | |
35 #include "prefs.h" | |
8986 | 36 #include "plugin.h" |
7620 | 37 #include "request.h" |
38 #include "signals.h" | |
10297
ec140184437b
[gaim-migrate @ 11480]
Luke Schierer <lschiere@pidgin.im>
parents:
10288
diff
changeset
|
39 #include "gtkstock.h" |
7620 | 40 #include "util.h" |
41 | |
42 #include "gtkaccount.h" | |
43 #include "gtkblist.h" | |
44 #include "gtkconv.h" | |
45 #include "gtkdebug.h" | |
9709 | 46 #include "gtkdialogs.h" |
7620 | 47 #include "gtkft.h" |
48 #include "gtklog.h" | |
49 #include "gtkpounce.h" | |
50 #include "gtkprefs.h" | |
51 #include "gtkprivacy.h" | |
8113 | 52 #include "gtkroomlist.h" |
10418 | 53 #include "gtksavedstatuses.h" |
10643 | 54 #include "gtkstatusbox.h" |
7620 | 55 #include "gtkutils.h" |
56 | |
5228 | 57 #include <gdk/gdkkeysyms.h> |
58 #include <gtk/gtk.h> | |
7620 | 59 #include <gdk/gdk.h> |
60 | |
10968
e0d5038fbb7e
[gaim-migrate @ 12789]
Christopher O'Brien <siege@pidgin.im>
parents:
10924
diff
changeset
|
61 /* if someone explicitly asked for drop shadows, we also need to make |
e0d5038fbb7e
[gaim-migrate @ 12789]
Christopher O'Brien <siege@pidgin.im>
parents:
10924
diff
changeset
|
62 sure that their environment can support it. If not, tough */ |
e0d5038fbb7e
[gaim-migrate @ 12789]
Christopher O'Brien <siege@pidgin.im>
parents:
10924
diff
changeset
|
63 #ifdef WANT_DROP_SHADOW |
e0d5038fbb7e
[gaim-migrate @ 12789]
Christopher O'Brien <siege@pidgin.im>
parents:
10924
diff
changeset
|
64 # if !GTK_CHECK_VERSION(2,2,0) || (defined(__APPLE__) && defined(__MACH__)) |
e0d5038fbb7e
[gaim-migrate @ 12789]
Christopher O'Brien <siege@pidgin.im>
parents:
10924
diff
changeset
|
65 # undef WANT_DROP_SHADOW |
e0d5038fbb7e
[gaim-migrate @ 12789]
Christopher O'Brien <siege@pidgin.im>
parents:
10924
diff
changeset
|
66 # endif |
7662 | 67 #endif |
68 | |
7620 | 69 typedef struct |
70 { | |
71 GaimAccount *account; | |
72 | |
73 GtkWidget *window; | |
74 GtkWidget *combo; | |
75 GtkWidget *entry; | |
76 GtkWidget *entry_for_alias; | |
77 GtkWidget *account_box; | |
78 | |
79 } GaimGtkAddBuddyData; | |
80 | |
81 typedef struct | |
82 { | |
9811 | 83 GaimAccount *account; |
9812 | 84 gchar *default_chat_name; |
9811 | 85 |
86 GtkWidget *window; | |
7620 | 87 GtkWidget *account_menu; |
88 GtkWidget *alias_entry; | |
89 GtkWidget *group_combo; | |
90 GtkWidget *entries_box; | |
91 GtkSizeGroup *sg; | |
92 | |
93 GList *entries; | |
94 | |
95 } GaimGtkAddChatData; | |
96 | |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
97 typedef struct |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
98 { |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
99 GaimAccount *account; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
100 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
101 GtkWidget *window; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
102 GtkWidget *account_menu; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
103 GtkWidget *entries_box; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
104 GtkSizeGroup *sg; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
105 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
106 GList *entries; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
107 } GaimGtkJoinChatData; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
108 |
7620 | 109 |
9949 | 110 static GtkWidget *protomenu = NULL; |
111 static GtkWidget *pluginmenu = NULL; | |
5228 | 112 |
5422 | 113 GSList *gaim_gtk_blist_sort_methods = NULL; |
114 static struct gaim_gtk_blist_sort_method *current_sort_method = NULL; | |
7620 | 115 static GtkTreeIter sort_method_none(GaimBlistNode *node, GaimBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur); |
116 | |
117 /* The functions we use for sorting aren't available in gtk 2.0.x, and | |
118 * segfault in 2.2.0. 2.2.1 is known to work, so I'll require that */ | |
119 #if GTK_CHECK_VERSION(2,2,1) | |
120 static GtkTreeIter sort_method_alphabetical(GaimBlistNode *node, GaimBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur); | |
121 static GtkTreeIter sort_method_status(GaimBlistNode *node, GaimBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur); | |
122 static GtkTreeIter sort_method_log(GaimBlistNode *node, GaimBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur); | |
123 #endif | |
124 static GaimGtkBuddyList *gtkblist = NULL; | |
5228 | 125 |
126 /* part of the best damn Docklet code this side of Tahiti */ | |
127 static gboolean gaim_gtk_blist_obscured = FALSE; | |
128 | |
129 static void gaim_gtk_blist_selection_changed(GtkTreeSelection *selection, gpointer data); | |
7620 | 130 static void gaim_gtk_blist_update(GaimBuddyList *list, GaimBlistNode *node); |
5234 | 131 static char *gaim_get_tooltip_text(GaimBlistNode *node); |
5228 | 132 static char *item_factory_translate_func (const char *path, gpointer func_data); |
5273 | 133 static gboolean get_iter_from_node(GaimBlistNode *node, GtkTreeIter *iter); |
7620 | 134 static void redo_buddy_list(GaimBuddyList *list, gboolean remove); |
135 static void gaim_gtk_blist_collapse_contact_cb(GtkWidget *w, GaimBlistNode *node); | |
136 | |
11059
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
137 static void gaim_gtk_blist_tooltip_destroy(); |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
138 |
5256 | 139 struct _gaim_gtk_blist_node { |
140 GtkTreeRowReference *row; | |
7620 | 141 gboolean contact_expanded; |
5256 | 142 }; |
143 | |
10968
e0d5038fbb7e
[gaim-migrate @ 12789]
Christopher O'Brien <siege@pidgin.im>
parents:
10924
diff
changeset
|
144 |
7662 | 145 #ifdef WANT_DROP_SHADOW |
7620 | 146 /**************************** Weird drop shadow stuff *******************/ |
11494 | 147 /* This is based on a patch for drop shadows in GTK+ menus available at |
10311 | 148 * http://www.xfce.org/gtkmenu-shadow/ |
149 */ | |
7620 | 150 |
151 enum side { | |
152 EAST_SIDE, | |
153 SOUTH_SIDE | |
154 }; | |
155 | |
10850 | 156 static const double shadow_strip_l[5] = { |
7620 | 157 .937, .831, .670, .478, .180 |
158 }; | |
159 | |
10850 | 160 static const double bottom_left_corner[25] = { |
7620 | 161 1.00, .682, .423, .333, .258, |
8470
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
162 1.00, .898, .800, .682, .584, |
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
163 1.00, .937, .874, .800, .737, |
7620 | 164 1.00, .968, .937, .898, .866, |
165 1.00, .988, .976, .960, .945 | |
166 }; | |
167 | |
10850 | 168 static const double bottom_right_corner[25] = { |
7620 | 169 .258, .584, .737, .866, .945, |
170 .584, .682, .800, .898, .960, | |
171 .737, .800, .874, .937, .976, | |
172 .866, .898, .937, .968, .988, | |
8470
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
173 .945, .960, .976, .988, .996 |
7620 | 174 }; |
175 | |
10850 | 176 static const double top_right_corner[25] = { |
8470
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
177 1.00, 1.00, 1.00, 1.00, 1.00, |
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
178 .686, .898, .937, .968, .988, |
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
179 .423, .803, .874, .937, .976, |
7620 | 180 .333, .686, .800, .898, .960, |
181 .258, .584, .737, .866, .945 | |
182 }; | |
183 | |
10850 | 184 static const double top_left_corner[25] = { |
7620 | 185 .988, .968, .937, .898, .498, |
8470
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
186 .976, .937, .874, .803, .423, |
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
187 .960, .898, .800, .686, .333, |
7620 | 188 .945, .866, .737, .584, .258, |
189 .941, .847, .698, .521, .215 | |
8470
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
190 }; |
7620 | 191 |
192 | |
10015 | 193 static gboolean xcomposite_is_present() |
194 { | |
10018
bae1cd16e854
[gaim-migrate @ 10938]
Luke Schierer <lschiere@pidgin.im>
parents:
10017
diff
changeset
|
195 static gboolean result = FALSE; |
bae1cd16e854
[gaim-migrate @ 10938]
Luke Schierer <lschiere@pidgin.im>
parents:
10017
diff
changeset
|
196 #ifndef _WIN32 |
bae1cd16e854
[gaim-migrate @ 10938]
Luke Schierer <lschiere@pidgin.im>
parents:
10017
diff
changeset
|
197 static gboolean known = FALSE; |
10015 | 198 int i, j, k; |
199 | |
200 if (!known) { | |
201 /* I don't actually care about versions/etc. */ | |
202 if (XQueryExtension(GDK_DISPLAY(), "Composite", &i, &j, &k) == True) | |
203 result = TRUE; | |
10017 | 204 known = TRUE; |
10015 | 205 } |
10018
bae1cd16e854
[gaim-migrate @ 10938]
Luke Schierer <lschiere@pidgin.im>
parents:
10017
diff
changeset
|
206 #endif |
10015 | 207 |
208 return result; | |
209 } | |
210 | |
7620 | 211 static GdkPixbuf * |
9811 | 212 get_pixbuf(GtkWidget *menu, int x, int y, int width, int height) |
7620 | 213 { |
9811 | 214 GdkPixbuf *dest, *src; |
215 GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET(menu)); | |
216 GdkWindow *root = gdk_screen_get_root_window (screen); | |
217 gint screen_height = gdk_screen_get_height (screen); | |
218 gint screen_width = gdk_screen_get_width (screen); | |
219 gint original_width = width; | |
220 gint original_height = height; | |
7620 | 221 |
9811 | 222 if (x < 0) { |
223 width += x; | |
224 x = 0; | |
225 } | |
226 | |
227 if (y < 0) { | |
228 height += y; | |
229 y = 0; | |
230 } | |
231 | |
232 if (x + width > screen_width) { | |
233 width = screen_width - x; | |
234 } | |
235 | |
236 if (y + height > screen_height) { | |
237 height = screen_height - y; | |
238 } | |
239 | |
240 if (width <= 0 || height <= 0) | |
241 return NULL; | |
242 | |
243 dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, | |
244 original_width, original_height); | |
245 src = gdk_pixbuf_get_from_drawable(NULL, root, NULL, x, y, 0, 0, | |
246 width, height); | |
247 gdk_pixbuf_copy_area (src, 0, 0, width, height, dest, 0, 0); | |
248 | |
249 g_object_unref (G_OBJECT (src)); | |
250 | |
251 return dest; | |
7620 | 252 } |
253 | |
254 static void | |
255 shadow_paint(GaimGtkBuddyList *blist, GdkRectangle *area, enum side shadow) | |
256 { | |
9811 | 257 gint width, height; |
258 GdkGC *gc = gtkblist->tipwindow->style->black_gc; | |
259 | |
260 switch (shadow) { | |
261 case EAST_SIDE: | |
262 if (gtkblist->east != NULL) { | |
263 if (area) | |
264 gdk_gc_set_clip_rectangle (gc, area); | |
265 | |
266 width = gdk_pixbuf_get_width (gtkblist->east); | |
267 height = gdk_pixbuf_get_height (gtkblist->east); | |
268 | |
269 gdk_draw_pixbuf(GDK_DRAWABLE(gtkblist->east_shadow), gc, | |
270 gtkblist->east, 0, 0, 0, 0, width, height, | |
271 GDK_RGB_DITHER_NONE, 0, 0); | |
272 | |
273 if (area) | |
274 gdk_gc_set_clip_rectangle (gc, NULL); | |
275 } | |
276 break; | |
277 | |
278 case SOUTH_SIDE: | |
279 if (blist->south != NULL) { | |
280 if (area) | |
281 gdk_gc_set_clip_rectangle (gc, area); | |
282 | |
283 width = gdk_pixbuf_get_width (gtkblist->south); | |
284 height = gdk_pixbuf_get_height (gtkblist->south); | |
285 | |
286 gdk_draw_pixbuf(GDK_DRAWABLE(gtkblist->south_shadow), gc, | |
287 gtkblist->south, 0, 0, 0, 0, width, height, | |
288 GDK_RGB_DITHER_NONE, 0, 0); | |
289 | |
290 if (area) | |
291 gdk_gc_set_clip_rectangle (gc, NULL); | |
292 } | |
293 break; | |
294 } | |
7620 | 295 } |
296 | |
297 static void | |
9811 | 298 pixbuf_add_shadow (GdkPixbuf *pb, enum side shadow) |
7620 | 299 { |
9811 | 300 gint width, rowstride, height; |
301 gint i; | |
302 guchar *pixels, *p; | |
303 | |
304 width = gdk_pixbuf_get_width (pb); | |
305 height = gdk_pixbuf_get_height (pb); | |
306 rowstride = gdk_pixbuf_get_rowstride (pb); | |
307 pixels = gdk_pixbuf_get_pixels (pb); | |
308 | |
309 switch (shadow) { | |
310 case EAST_SIDE: | |
311 if (height > 5) { | |
312 for (i = 0; i < width; i++) { | |
313 gint j, k; | |
314 | |
315 p = pixels + (i * rowstride); | |
316 for (j = 0, k = 0; j < 3 * width; j += 3, k++) { | |
317 p[j] = (guchar) (p[j] * top_right_corner [i * width + k]); | |
318 p[j + 1] = (guchar) (p[j + 1] * top_right_corner [i * width + k]); | |
319 p[j + 2] = (guchar) (p[j + 2] * top_right_corner [i * width + k]); | |
320 } | |
321 } | |
322 | |
323 i = 5; | |
324 } else { | |
325 i = 0; | |
326 } | |
327 | |
328 for (; i < height; i++) { | |
329 gint j, k; | |
330 | |
331 p = pixels + (i * rowstride); | |
332 for (j = 0, k = 0; j < 3 * width; j += 3, k++) { | |
333 p[j] = (guchar) (p[j] * shadow_strip_l[width - 1 - k]); | |
334 p[j + 1] = (guchar) (p[j + 1] * shadow_strip_l[width - 1 - k]); | |
335 p[j + 2] = (guchar) (p[j + 2] * shadow_strip_l[width - 1 - k]); | |
336 } | |
337 } | |
338 break; | |
339 | |
340 case SOUTH_SIDE: | |
341 for (i = 0; i < height; i++) { | |
342 gint j, k; | |
343 | |
344 p = pixels + (i * rowstride); | |
345 for (j = 0, k = 0; j < 3 * height; j += 3, k++) { | |
346 p[j] = (guchar) (p[j] * bottom_left_corner[i * height + k]); | |
347 p[j + 1] = (guchar) (p[j + 1] * bottom_left_corner[i * height + k]); | |
348 p[j + 2] = (guchar) (p[j + 2] * bottom_left_corner[i * height + k]); | |
349 } | |
350 | |
351 p = pixels + (i * rowstride) + 3 * height; | |
352 for (j = 0, k = 0; j < (width * 3) - (6 * height); j += 3, k++) { | |
353 p[j] = (guchar) (p[j] * bottom_right_corner [i * height]); | |
354 p[j + 1] = (guchar) (p[j + 1] * bottom_right_corner [i * height]); | |
355 p[j + 2] = (guchar) (p[j + 2] * bottom_right_corner [i * height]); | |
356 } | |
357 | |
358 p = pixels + (i * rowstride) + ((width * 3) - (3 * height)); | |
359 for (j = 0, k = 0; j < 3 * height; j += 3, k++) { | |
360 p[j] = (guchar) (p[j] * bottom_right_corner[i * height + k]); | |
361 p[j + 1] = (guchar) (p[j + 1] * bottom_right_corner[i * height + k]); | |
362 p[j + 2] = (guchar) (p[j + 2] * bottom_right_corner[i * height + k]); | |
363 } | |
364 } | |
365 break; | |
366 } | |
7620 | 367 } |
368 | |
369 static gboolean | |
370 map_shadow_windows (gpointer data) | |
371 { | |
372 GaimGtkBuddyList *blist = (GaimGtkBuddyList*)data; | |
373 GtkWidget *widget = blist->tipwindow; | |
374 GdkPixbuf *pixbuf; | |
375 int x, y; | |
376 | |
377 gtk_window_get_position(GTK_WINDOW(widget), &x, &y); | |
9811 | 378 pixbuf = get_pixbuf(widget, |
379 x + widget->allocation.width, y, | |
380 5, widget->allocation.height + 5); | |
7620 | 381 if (pixbuf != NULL) |
382 { | |
383 pixbuf_add_shadow (pixbuf, EAST_SIDE); | |
384 if (blist->east != NULL) | |
385 { | |
386 g_object_unref (G_OBJECT (blist->east)); | |
387 } | |
388 blist->east = pixbuf; | |
389 } | |
390 | |
391 pixbuf = get_pixbuf (widget, | |
392 x, y + widget->allocation.height, | |
393 widget->allocation.width + 5, 5); | |
8470
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
394 if (pixbuf != NULL) |
7620 | 395 { |
396 pixbuf_add_shadow (pixbuf, SOUTH_SIDE); | |
8470
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
397 if (blist->south != NULL) |
7620 | 398 { |
399 g_object_unref (G_OBJECT (blist->south)); | |
400 } | |
401 blist->south = pixbuf; | |
402 } | |
403 | |
9686 | 404 gdk_window_move_resize (blist->east_shadow, |
405 x + widget->allocation.width, MAX(0,y), | |
406 5, MIN(widget->allocation.height, gdk_screen_height())); | |
10382
9f28196ed769
[gaim-migrate @ 11608]
Luke Schierer <lschiere@pidgin.im>
parents:
10357
diff
changeset
|
407 |
9686 | 408 gdk_window_move_resize (blist->south_shadow, |
409 MAX(0,x), y + widget->allocation.height, | |
410 MIN(widget->allocation.width + 5, gdk_screen_width()), 5); | |
411 | |
412 gdk_window_show (blist->east_shadow); | |
413 gdk_window_show (blist->south_shadow); | |
414 shadow_paint(blist, NULL, EAST_SIDE); | |
415 shadow_paint(blist, NULL, SOUTH_SIDE); | |
416 | |
417 return FALSE; | |
7620 | 418 } |
419 | |
420 /**************** END WEIRD DROP SHADOW STUFF ***********************************/ | |
10968
e0d5038fbb7e
[gaim-migrate @ 12789]
Christopher O'Brien <siege@pidgin.im>
parents:
10924
diff
changeset
|
421 #endif /* ifdef WANT_DROP_SHADOW */ |
e0d5038fbb7e
[gaim-migrate @ 12789]
Christopher O'Brien <siege@pidgin.im>
parents:
10924
diff
changeset
|
422 |
8254 | 423 |
10118 | 424 static char dim_grey_string[8] = ""; |
10144 | 425 static char *dim_grey() |
10118 | 426 { |
427 if (!gtkblist) | |
428 return "dim grey"; | |
429 if (!dim_grey_string[0]) { | |
430 GtkStyle *style = gtk_widget_get_style(gtkblist->treeview); | |
431 snprintf(dim_grey_string, sizeof(dim_grey_string), "#%02x%02x%02x", | |
432 style->text_aa[GTK_STATE_NORMAL].red >> 8, | |
433 style->text_aa[GTK_STATE_NORMAL].green >> 8, | |
434 style->text_aa[GTK_STATE_NORMAL].blue >> 8); | |
435 } | |
436 return dim_grey_string; | |
437 } | |
10144 | 438 |
5228 | 439 /*************************************************** |
440 * Callbacks * | |
441 ***************************************************/ | |
442 | |
443 static gboolean gtk_blist_delete_cb(GtkWidget *w, GdkEventAny *event, gpointer data) | |
444 { | |
445 if (docklet_count) | |
446 gaim_blist_set_visible(FALSE); | |
447 else | |
7620 | 448 gaim_core_quit(); |
5228 | 449 |
450 /* we handle everything, event should not propogate further */ | |
451 return TRUE; | |
452 } | |
453 | |
454 static gboolean gtk_blist_configure_cb(GtkWidget *w, GdkEventConfigure *event, gpointer data) | |
455 { | |
456 /* unfortunately GdkEventConfigure ignores the window gravity, but * | |
457 * the only way we have of setting the position doesn't. we have to * | |
7620 | 458 * call get_position because it does pay attention to the gravity. * |
459 * this is inefficient and I agree it sucks, but it's more likely * | |
460 * to work correctly. - Robot101 */ | |
5228 | 461 gint x, y; |
462 | |
463 /* check for visibility because when we aren't visible, this will * | |
464 * give us bogus (0,0) coordinates. - xOr */ | |
7620 | 465 if (GTK_WIDGET_VISIBLE(w)) |
5228 | 466 gtk_window_get_position(GTK_WINDOW(w), &x, &y); |
7620 | 467 else |
468 return FALSE; /* carry on normally */ | |
469 | |
470 /* don't save if nothing changed */ | |
471 if (x == gaim_prefs_get_int("/gaim/gtk/blist/x") && | |
472 y == gaim_prefs_get_int("/gaim/gtk/blist/y") && | |
473 event->width == gaim_prefs_get_int("/gaim/gtk/blist/width") && | |
474 event->height == gaim_prefs_get_int("/gaim/gtk/blist/height")) { | |
475 | |
476 return FALSE; /* carry on normally */ | |
5228 | 477 } |
478 | |
7620 | 479 /* don't save off-screen positioning */ |
480 if (x + event->width < 0 || | |
9811 | 481 y + event->height < 0 || |
482 x > gdk_screen_width() || | |
483 y > gdk_screen_height()) { | |
7620 | 484 |
485 return FALSE; /* carry on normally */ | |
486 } | |
487 | |
488 /* store the position */ | |
489 gaim_prefs_set_int("/gaim/gtk/blist/x", x); | |
490 gaim_prefs_set_int("/gaim/gtk/blist/y", y); | |
491 gaim_prefs_set_int("/gaim/gtk/blist/width", event->width); | |
492 gaim_prefs_set_int("/gaim/gtk/blist/height", event->height); | |
493 | |
5228 | 494 /* continue to handle event normally */ |
495 return FALSE; | |
496 } | |
497 | |
498 static gboolean gtk_blist_visibility_cb(GtkWidget *w, GdkEventVisibility *event, gpointer data) | |
499 { | |
500 if (event->state == GDK_VISIBILITY_FULLY_OBSCURED) | |
501 gaim_gtk_blist_obscured = TRUE; | |
502 else | |
503 gaim_gtk_blist_obscured = FALSE; | |
504 | |
505 /* continue to handle event normally */ | |
506 return FALSE; | |
507 } | |
508 | |
7620 | 509 static void gtk_blist_menu_info_cb(GtkWidget *w, GaimBuddy *b) |
5228 | 510 { |
511 serv_get_info(b->account->gc, b->name); | |
512 } | |
513 | |
7620 | 514 static void gtk_blist_menu_im_cb(GtkWidget *w, GaimBuddy *b) |
5228 | 515 { |
9728 | 516 gaim_gtkdialogs_im_with_user(b->account, b->name); |
5228 | 517 } |
518 | |
9466 | 519 static void gtk_blist_menu_send_file_cb(GtkWidget *w, GaimBuddy *b) |
520 { | |
521 serv_send_file(b->account->gc, b->name, NULL); | |
522 } | |
523 | |
7620 | 524 static void gtk_blist_menu_autojoin_cb(GtkWidget *w, GaimChat *chat) |
525 { | |
7693 | 526 gaim_blist_node_set_bool((GaimBlistNode*)chat, "gtk-autojoin", |
527 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))); | |
7620 | 528 } |
529 | |
530 static void gtk_blist_menu_join_cb(GtkWidget *w, GaimChat *chat) | |
5228 | 531 { |
5234 | 532 serv_join_chat(chat->account->gc, chat->components); |
533 } | |
534 | |
11016 | 535 static void gtk_blist_renderer_edited_cb(GtkCellRendererText *text_rend, char *arg1, |
536 char *arg2, gpointer nada) | |
537 { | |
538 GtkTreeIter iter; | |
539 GtkTreePath *path; | |
540 GValue val = {0,}; | |
541 GaimBlistNode *node; | |
542 | |
543 path = gtk_tree_path_new_from_string (arg1); | |
544 gtk_tree_model_get_iter (GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); | |
545 gtk_tree_path_free (path); | |
546 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val); | |
547 node = g_value_get_pointer(&val); | |
548 gtk_tree_view_set_enable_search (GTK_TREE_VIEW(gtkblist->treeview), TRUE); | |
549 g_object_set(G_OBJECT(gtkblist->text_rend), "editable", FALSE, NULL); | |
550 switch (node->type){ | |
551 case GAIM_BLIST_CONTACT_NODE: | |
552 gaim_blist_alias_buddy(gaim_contact_get_priority_buddy((GaimContact*)node), arg2); | |
553 break; | |
554 case GAIM_BLIST_BUDDY_NODE: | |
555 gaim_blist_alias_buddy((GaimBuddy*)node, arg2); | |
556 break; | |
557 case GAIM_BLIST_GROUP_NODE: | |
558 gaim_blist_rename_group((GaimGroup*)node, arg2); | |
559 break; | |
560 case GAIM_BLIST_CHAT_NODE: | |
561 gaim_blist_alias_chat((GaimChat*)node, arg2); | |
562 break; | |
563 default: | |
564 break; | |
565 } | |
566 } | |
567 | |
5234 | 568 static void gtk_blist_menu_alias_cb(GtkWidget *w, GaimBlistNode *node) |
569 { | |
11016 | 570 GtkTreeIter iter; |
571 GtkTreePath *path; | |
11258 | 572 const char *text = NULL; |
11494 | 573 |
11258 | 574 if (!(get_iter_from_node(node, &iter))) { |
11016 | 575 /* This is either a bug, or the buddy is in a collapsed contact */ |
576 node = node->parent; | |
577 if (!get_iter_from_node(node, &iter)) | |
578 /* Now it's definitely a bug */ | |
579 return; | |
580 } | |
11258 | 581 |
582 switch (node->type) { | |
583 case GAIM_BLIST_BUDDY_NODE: | |
584 text = gaim_buddy_get_alias((GaimBuddy *)node); | |
585 break; | |
586 case GAIM_BLIST_CONTACT_NODE: | |
587 text = gaim_buddy_get_alias(gaim_contact_get_priority_buddy((GaimContact *)node)); | |
588 break; | |
589 case GAIM_BLIST_GROUP_NODE: | |
590 text = ((GaimGroup *)node)->name; | |
591 break; | |
592 case GAIM_BLIST_CHAT_NODE: | |
593 text = gaim_chat_get_name((GaimChat *)node); | |
594 break; | |
595 default: | |
596 g_return_if_reached(); | |
597 } | |
598 | |
599 gtk_tree_store_set(gtkblist->treemodel, &iter, NAME_COLUMN, text, -1); | |
600 | |
11016 | 601 path = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &iter); |
602 g_object_set(G_OBJECT(gtkblist->text_rend), "editable", TRUE, NULL); | |
603 gtk_tree_view_set_enable_search (GTK_TREE_VIEW(gtkblist->treeview), FALSE); | |
604 gtk_widget_grab_focus(gtkblist->treeview); | |
605 gtk_tree_view_set_cursor(GTK_TREE_VIEW(gtkblist->treeview), path, gtkblist->text_column, TRUE); | |
606 gtk_tree_path_free(path); | |
5228 | 607 } |
608 | |
7620 | 609 static void gtk_blist_menu_bp_cb(GtkWidget *w, GaimBuddy *b) |
5228 | 610 { |
7620 | 611 gaim_gtkpounce_dialog_show(b->account, b->name, NULL); |
5228 | 612 } |
613 | |
9917 | 614 static void gtk_blist_menu_showlog_cb(GtkWidget *w, GaimBlistNode *node) |
5228 | 615 { |
9917 | 616 GaimLogType type; |
617 GaimAccount *account; | |
618 char *name = NULL; | |
10663 | 619 |
9917 | 620 if (GAIM_BLIST_NODE_IS_BUDDY(node)) { |
621 GaimBuddy *b = (GaimBuddy*) node; | |
622 type = GAIM_LOG_IM; | |
623 name = g_strdup(b->name); | |
624 account = b->account; | |
625 } else if (GAIM_BLIST_NODE_IS_CHAT(node)) { | |
626 GaimChat *c = (GaimChat*) node; | |
627 GaimPluginProtocolInfo *prpl_info = NULL; | |
628 type = GAIM_LOG_CHAT; | |
629 account = c->account; | |
630 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gaim_find_prpl(gaim_account_get_protocol_id(account))); | |
631 if (prpl_info && prpl_info->get_chat_name) { | |
632 name = prpl_info->get_chat_name(c->components); | |
633 } | |
10663 | 634 } else if (GAIM_BLIST_NODE_IS_CONTACT(node)) { |
635 gaim_gtk_log_show_contact((GaimContact *)node); | |
636 return; | |
9917 | 637 } else |
638 return; | |
639 | |
640 if (name && account) { | |
641 gaim_gtk_log_show(type, name, account); | |
642 g_free(name); | |
643 } | |
7620 | 644 } |
645 | |
5228 | 646 static void gtk_blist_show_systemlog_cb() |
647 { | |
8573 | 648 gaim_gtk_syslog_show(); |
5228 | 649 } |
650 | |
651 static void gtk_blist_show_onlinehelp_cb() | |
652 { | |
10240
95ca0db2d01d
[gaim-migrate @ 11377]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
10229
diff
changeset
|
653 gaim_notify_uri(NULL, GAIM_WEBSITE "documentation.php"); |
5228 | 654 } |
655 | |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
656 static void |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
657 do_join_chat(GaimGtkJoinChatData *data) |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
658 { |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
659 if (data) |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
660 { |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
661 GHashTable *components = |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
662 g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
663 GList *tmp; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
664 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
665 for (tmp = data->entries; tmp != NULL; tmp = tmp->next) |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
666 { |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
667 if (g_object_get_data(tmp->data, "is_spin")) |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
668 { |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
669 g_hash_table_replace(components, |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
670 g_strdup(g_object_get_data(tmp->data, "identifier")), |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
671 g_strdup_printf("%d", |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
672 gtk_spin_button_get_value_as_int(tmp->data))); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
673 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
674 else |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
675 { |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
676 g_hash_table_replace(components, |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
677 g_strdup(g_object_get_data(tmp->data, "identifier")), |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
678 g_strdup(gtk_entry_get_text(tmp->data))); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
679 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
680 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
681 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
682 serv_join_chat(gaim_account_get_connection(data->account), components); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
683 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
684 g_hash_table_destroy(components); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
685 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
686 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
687 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
688 static void |
8940 | 689 do_joinchat(GtkWidget *dialog, int id, GaimGtkJoinChatData *info) |
690 { | |
691 switch(id) | |
692 { | |
693 case GTK_RESPONSE_OK: | |
694 do_join_chat(info); | |
695 | |
696 break; | |
697 } | |
698 | |
699 gtk_widget_destroy(GTK_WIDGET(dialog)); | |
700 g_list_free(info->entries); | |
701 g_free(info); | |
702 } | |
703 | |
10475 | 704 /* |
705 * Check the values of all the text entry boxes. If any required input | |
706 * strings are empty then don't allow the user to click on "OK." | |
707 */ | |
708 static void | |
709 joinchat_set_sensitive_if_input_cb(GtkWidget *entry, gpointer user_data) | |
710 { | |
711 GaimGtkJoinChatData *data; | |
712 GList *tmp; | |
713 const char *text; | |
714 gboolean required; | |
715 gboolean sensitive = TRUE; | |
716 | |
717 data = user_data; | |
718 | |
719 for (tmp = data->entries; tmp != NULL; tmp = tmp->next) | |
720 { | |
721 if (!g_object_get_data(tmp->data, "is_spin")) | |
722 { | |
723 required = GPOINTER_TO_INT(g_object_get_data(tmp->data, "required")); | |
724 text = gtk_entry_get_text(tmp->data); | |
725 if (required && (*text == '\0')) | |
726 sensitive = FALSE; | |
727 } | |
728 } | |
729 | |
730 gtk_dialog_set_response_sensitive(GTK_DIALOG(data->window), GTK_RESPONSE_OK, sensitive); | |
731 } | |
732 | |
8940 | 733 static void |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
734 rebuild_joinchat_entries(GaimGtkJoinChatData *data) |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
735 { |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
736 GaimConnection *gc; |
9959 | 737 GList *list = NULL, *tmp = NULL; |
9770 | 738 GHashTable *defaults = NULL; |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
739 struct proto_chat_entry *pce; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
740 gboolean focus = TRUE; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
741 |
10127 | 742 g_return_if_fail(data->account != NULL); |
743 | |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
744 gc = gaim_account_get_connection(data->account); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
745 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
746 while (GTK_BOX(data->entries_box)->children) |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
747 { |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
748 gtk_container_remove(GTK_CONTAINER(data->entries_box), |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
749 ((GtkBoxChild *)GTK_BOX(data->entries_box)->children->data)->widget); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
750 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
751 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
752 if (data->entries != NULL) |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
753 g_list_free(data->entries); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
754 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
755 data->entries = NULL; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
756 |
9987 | 757 if (GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info != NULL) |
9959 | 758 list = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info(gc); |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
759 |
9770 | 760 if (GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults != NULL) |
761 defaults = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, NULL); | |
762 | |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
763 for (tmp = list; tmp; tmp = tmp->next) |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
764 { |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
765 GtkWidget *label; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
766 GtkWidget *rowbox; |
10475 | 767 GtkWidget *input; |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
768 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
769 pce = tmp->data; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
770 |
11243 | 771 rowbox = gtk_hbox_new(FALSE, GAIM_HIG_BORDER); |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
772 gtk_box_pack_start(GTK_BOX(data->entries_box), rowbox, FALSE, FALSE, 0); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
773 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
774 label = gtk_label_new_with_mnemonic(pce->label); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
775 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
776 gtk_size_group_add_widget(data->sg, label); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
777 gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
778 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
779 if (pce->is_int) |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
780 { |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
781 GtkObject *adjust; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
782 adjust = gtk_adjustment_new(pce->min, pce->min, pce->max, |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
783 1, 10, 10); |
10475 | 784 input = gtk_spin_button_new(GTK_ADJUSTMENT(adjust), 1, 0); |
785 gtk_widget_set_size_request(input, 50, -1); | |
786 gtk_box_pack_end(GTK_BOX(rowbox), input, FALSE, FALSE, 0); | |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
787 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
788 else |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
789 { |
9770 | 790 char *value; |
10475 | 791 input = gtk_entry_new(); |
792 gtk_entry_set_activates_default(GTK_ENTRY(input), TRUE); | |
9770 | 793 value = g_hash_table_lookup(defaults, pce->identifier); |
794 if (value != NULL) | |
10475 | 795 gtk_entry_set_text(GTK_ENTRY(input), value); |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
796 if (pce->secret) |
10475 | 797 gtk_entry_set_visibility(GTK_ENTRY(input), FALSE); |
798 gtk_box_pack_end(GTK_BOX(rowbox), input, TRUE, TRUE, 0); | |
799 g_signal_connect(G_OBJECT(input), "changed", | |
800 G_CALLBACK(joinchat_set_sensitive_if_input_cb), data); | |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
801 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
802 |
10475 | 803 /* Do the following for any type of input widget */ |
804 if (focus) | |
805 { | |
806 gtk_widget_grab_focus(input); | |
807 focus = FALSE; | |
808 } | |
809 gtk_label_set_mnemonic_widget(GTK_LABEL(label), input); | |
810 gaim_set_accessible_label(input, label); | |
811 g_object_set_data(G_OBJECT(input), "identifier", pce->identifier); | |
812 g_object_set_data(G_OBJECT(input), "is_spin", GINT_TO_POINTER(pce->is_int)); | |
813 g_object_set_data(G_OBJECT(input), "required", GINT_TO_POINTER(pce->required)); | |
814 data->entries = g_list_append(data->entries, input); | |
815 | |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
816 g_free(pce); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
817 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
818 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
819 g_list_free(list); |
10475 | 820 g_hash_table_destroy(defaults); |
821 | |
822 /* Set whether the "OK" button should be clickable initially */ | |
823 joinchat_set_sensitive_if_input_cb(NULL, data); | |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
824 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
825 gtk_widget_show_all(data->entries_box); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
826 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
827 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
828 static void |
8940 | 829 joinchat_select_account_cb(GObject *w, GaimAccount *account, |
10475 | 830 GaimGtkJoinChatData *data) |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
831 { |
9460 | 832 if (strcmp(gaim_account_get_protocol_id(data->account), |
10475 | 833 gaim_account_get_protocol_id(account)) == 0) |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
834 { |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
835 data->account = account; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
836 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
837 else |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
838 { |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
839 data->account = account; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
840 rebuild_joinchat_entries(data); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
841 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
842 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
843 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
844 static gboolean |
9987 | 845 chat_account_filter_func(GaimAccount *account) |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
846 { |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
847 GaimConnection *gc = gaim_account_get_connection(account); |
8940 | 848 GaimPluginProtocolInfo *prpl_info = NULL; |
849 | |
850 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl); | |
851 | |
852 return (prpl_info->chat_info != NULL); | |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
853 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
854 |
8940 | 855 gboolean |
856 gaim_gtk_blist_joinchat_is_showable() | |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
857 { |
8940 | 858 GList *c; |
859 GaimConnection *gc; | |
860 | |
861 for (c = gaim_connections_get_all(); c != NULL; c = c->next) { | |
862 gc = c->data; | |
863 | |
9987 | 864 if (chat_account_filter_func(gaim_connection_get_account(gc))) |
8940 | 865 return TRUE; |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
866 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
867 |
8940 | 868 return FALSE; |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
869 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
870 |
8305
57bdd25752c1
[gaim-migrate @ 9029]
Christian Hammond <chipx86@chipx86.com>
parents:
8303
diff
changeset
|
871 void |
8940 | 872 gaim_gtk_blist_joinchat_show(void) |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
873 { |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
874 GtkWidget *hbox, *vbox; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
875 GtkWidget *rowbox; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
876 GtkWidget *label; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
877 GaimGtkBuddyList *gtkblist; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
878 GtkWidget *img = NULL; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
879 GaimGtkJoinChatData *data = NULL; |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
880 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
881 gtkblist = GAIM_GTK_BLIST(gaim_get_blist()); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
882 img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_QUESTION, |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
883 GTK_ICON_SIZE_DIALOG); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
884 data = g_new0(GaimGtkJoinChatData, 1); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
885 |
8975 | 886 data->window = gtk_dialog_new_with_buttons(_("Join a Chat"), |
887 NULL, GTK_DIALOG_NO_SEPARATOR, | |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
888 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, |
8308 | 889 GAIM_STOCK_CHAT, GTK_RESPONSE_OK, NULL); |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
890 gtk_dialog_set_default_response(GTK_DIALOG(data->window), GTK_RESPONSE_OK); |
11243 | 891 gtk_container_set_border_width(GTK_CONTAINER(data->window), GAIM_HIG_BOX_SPACE); |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
892 gtk_window_set_resizable(GTK_WINDOW(data->window), FALSE); |
11243 | 893 gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(data->window)->vbox), GAIM_HIG_BORDER); |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
894 gtk_container_set_border_width( |
11243 | 895 GTK_CONTAINER(GTK_DIALOG(data->window)->vbox), GAIM_HIG_BOX_SPACE); |
8975 | 896 gtk_window_set_role(GTK_WINDOW(data->window), "join_chat"); |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
897 |
11243 | 898 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BORDER); |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
899 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(data->window)->vbox), hbox); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
900 gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
901 gtk_misc_set_alignment(GTK_MISC(img), 0, 0); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
902 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
903 vbox = gtk_vbox_new(FALSE, 5); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
904 gtk_container_set_border_width(GTK_CONTAINER(vbox), 0); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
905 gtk_container_add(GTK_CONTAINER(hbox), vbox); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
906 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
907 label = gtk_label_new(_("Please enter the appropriate information " |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
908 "about the chat you would like to join.\n")); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
909 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
910 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
911 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
912 |
11243 | 913 rowbox = gtk_hbox_new(FALSE, GAIM_HIG_BORDER); |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
914 gtk_box_pack_start(GTK_BOX(vbox), rowbox, TRUE, TRUE, 0); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
915 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
916 data->sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
917 |
8940 | 918 label = gtk_label_new_with_mnemonic(_("_Account:")); |
919 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
920 gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0); | |
921 gtk_size_group_add_widget(data->sg, label); | |
922 | |
923 data->account_menu = gaim_gtk_account_option_menu_new(NULL, FALSE, | |
924 G_CALLBACK(joinchat_select_account_cb), | |
9987 | 925 chat_account_filter_func, data); |
8940 | 926 gtk_box_pack_start(GTK_BOX(rowbox), data->account_menu, TRUE, TRUE, 0); |
927 gtk_label_set_mnemonic_widget(GTK_LABEL(label), | |
928 GTK_WIDGET(data->account_menu)); | |
929 gaim_set_accessible_label (data->account_menu, label); | |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
930 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
931 data->entries_box = gtk_vbox_new(FALSE, 5); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
932 gtk_container_add(GTK_CONTAINER(vbox), data->entries_box); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
933 gtk_container_set_border_width(GTK_CONTAINER(data->entries_box), 0); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
934 |
8940 | 935 data->account = gaim_gtk_account_option_menu_get_selected(data->account_menu); |
936 | |
8303
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
937 rebuild_joinchat_entries(data); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
938 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
939 g_signal_connect(G_OBJECT(data->window), "response", |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
940 G_CALLBACK(do_joinchat), data); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
941 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
942 g_object_unref(data->sg); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
943 |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
944 gtk_widget_show_all(data->window); |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
945 } |
4eb4b2a6c604
[gaim-migrate @ 9027]
Christian Hammond <chipx86@chipx86.com>
parents:
8302
diff
changeset
|
946 |
5228 | 947 static void gtk_blist_row_expanded_cb(GtkTreeView *tv, GtkTreeIter *iter, GtkTreePath *path, gpointer user_data) { |
948 GaimBlistNode *node; | |
949 GValue val = {0,}; | |
950 | |
951 gtk_tree_model_get_value(GTK_TREE_MODEL(gtkblist->treemodel), iter, NODE_COLUMN, &val); | |
952 | |
953 node = g_value_get_pointer(&val); | |
954 | |
955 if (GAIM_BLIST_NODE_IS_GROUP(node)) { | |
7693 | 956 gaim_blist_node_set_bool(node, "collapsed", FALSE); |
5228 | 957 } |
958 } | |
959 | |
960 static void gtk_blist_row_collapsed_cb(GtkTreeView *tv, GtkTreeIter *iter, GtkTreePath *path, gpointer user_data) { | |
961 GaimBlistNode *node; | |
962 GValue val = {0,}; | |
963 | |
964 gtk_tree_model_get_value(GTK_TREE_MODEL(gtkblist->treemodel), iter, NODE_COLUMN, &val); | |
965 | |
966 node = g_value_get_pointer(&val); | |
967 | |
968 if (GAIM_BLIST_NODE_IS_GROUP(node)) { | |
7693 | 969 gaim_blist_node_set_bool(node, "collapsed", TRUE); |
7620 | 970 } else if(GAIM_BLIST_NODE_IS_CONTACT(node)) { |
971 gaim_gtk_blist_collapse_contact_cb(NULL, node); | |
5228 | 972 } |
973 } | |
974 | |
975 static void gtk_blist_row_activated_cb(GtkTreeView *tv, GtkTreePath *path, GtkTreeViewColumn *col, gpointer data) { | |
976 GaimBlistNode *node; | |
977 GtkTreeIter iter; | |
978 GValue val = { 0, }; | |
979 | |
980 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); | |
981 | |
982 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val); | |
983 node = g_value_get_pointer(&val); | |
984 | |
7620 | 985 if(GAIM_BLIST_NODE_IS_CONTACT(node) || GAIM_BLIST_NODE_IS_BUDDY(node)) { |
986 GaimBuddy *buddy; | |
987 | |
988 if(GAIM_BLIST_NODE_IS_CONTACT(node)) | |
989 buddy = gaim_contact_get_priority_buddy((GaimContact*)node); | |
990 else | |
991 buddy = (GaimBuddy*)node; | |
992 | |
9728 | 993 gaim_gtkdialogs_im_with_user(buddy->account, buddy->name); |
5234 | 994 } else if (GAIM_BLIST_NODE_IS_CHAT(node)) { |
7620 | 995 serv_join_chat(((GaimChat *)node)->account->gc, ((GaimChat *)node)->components); |
5228 | 996 } else if (GAIM_BLIST_NODE_IS_GROUP(node)) { |
997 if (gtk_tree_view_row_expanded(tv, path)) | |
998 gtk_tree_view_collapse_row(tv, path); | |
999 else | |
1000 gtk_tree_view_expand_row(tv,path,FALSE); | |
1001 } | |
1002 } | |
1003 | |
5234 | 1004 static void gaim_gtk_blist_add_chat_cb() |
1005 { | |
1006 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gtkblist->treeview)); | |
1007 GtkTreeIter iter; | |
1008 GaimBlistNode *node; | |
1009 | |
1010 if(gtk_tree_selection_get_selected(sel, NULL, &iter)){ | |
1011 gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &node, -1); | |
7620 | 1012 if (GAIM_BLIST_NODE_IS_BUDDY(node)) |
9754 | 1013 gaim_blist_request_add_chat(NULL, (GaimGroup*)node->parent->parent, NULL, NULL); |
7620 | 1014 if (GAIM_BLIST_NODE_IS_CONTACT(node) || GAIM_BLIST_NODE_IS_CHAT(node)) |
9754 | 1015 gaim_blist_request_add_chat(NULL, (GaimGroup*)node->parent, NULL, NULL); |
5234 | 1016 else if (GAIM_BLIST_NODE_IS_GROUP(node)) |
9754 | 1017 gaim_blist_request_add_chat(NULL, (GaimGroup*)node, NULL, NULL); |
5234 | 1018 } |
1019 else { | |
9754 | 1020 gaim_blist_request_add_chat(NULL, NULL, NULL, NULL); |
5234 | 1021 } |
1022 } | |
1023 | |
5228 | 1024 static void gaim_gtk_blist_add_buddy_cb() |
1025 { | |
1026 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gtkblist->treeview)); | |
1027 GtkTreeIter iter; | |
1028 GaimBlistNode *node; | |
1029 | |
1030 if(gtk_tree_selection_get_selected(sel, NULL, &iter)){ | |
1031 gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &node, -1); | |
7620 | 1032 if (GAIM_BLIST_NODE_IS_BUDDY(node)) { |
1033 gaim_blist_request_add_buddy(NULL, NULL, ((GaimGroup*)node->parent->parent)->name, | |
1034 NULL); | |
1035 } else if (GAIM_BLIST_NODE_IS_CONTACT(node) | |
1036 || GAIM_BLIST_NODE_IS_CHAT(node)) { | |
1037 gaim_blist_request_add_buddy(NULL, NULL, ((GaimGroup*)node->parent)->name, NULL); | |
1038 } else if (GAIM_BLIST_NODE_IS_GROUP(node)) { | |
1039 gaim_blist_request_add_buddy(NULL, NULL, ((GaimGroup*)node)->name, NULL); | |
1040 } | |
5228 | 1041 } |
1042 else { | |
7620 | 1043 gaim_blist_request_add_buddy(NULL, NULL, NULL, NULL); |
1044 } | |
1045 } | |
1046 | |
1047 static void | |
1048 gaim_gtk_blist_remove_cb (GtkWidget *w, GaimBlistNode *node) | |
1049 { | |
1050 if (GAIM_BLIST_NODE_IS_BUDDY(node)) { | |
9730 | 1051 gaim_gtkdialogs_remove_buddy((GaimBuddy*)node); |
7620 | 1052 } else if (GAIM_BLIST_NODE_IS_CHAT(node)) { |
9730 | 1053 gaim_gtkdialogs_remove_chat((GaimChat*)node); |
7620 | 1054 } else if (GAIM_BLIST_NODE_IS_GROUP(node)) { |
9730 | 1055 gaim_gtkdialogs_remove_group((GaimGroup*)node); |
7620 | 1056 } else if (GAIM_BLIST_NODE_IS_CONTACT(node)) { |
9730 | 1057 gaim_gtkdialogs_remove_contact((GaimContact*)node); |
5228 | 1058 } |
1059 } | |
1060 | |
1061 static void | |
7620 | 1062 gaim_gtk_blist_expand_contact_cb(GtkWidget *w, GaimBlistNode *node) |
5228 | 1063 { |
7620 | 1064 struct _gaim_gtk_blist_node *gtknode; |
9632 | 1065 GtkTreeIter iter, parent; |
7620 | 1066 GaimBlistNode *bnode; |
10325 | 1067 GtkTreePath *path; |
7620 | 1068 |
1069 if(!GAIM_BLIST_NODE_IS_CONTACT(node)) | |
1070 return; | |
1071 | |
1072 gtknode = (struct _gaim_gtk_blist_node *)node->ui_data; | |
1073 | |
1074 gtknode->contact_expanded = TRUE; | |
1075 | |
1076 for(bnode = node->child; bnode; bnode = bnode->next) { | |
1077 gaim_gtk_blist_update(NULL, bnode); | |
1078 } | |
10353 | 1079 |
9632 | 1080 /* This ensures that the bottom buddy is visible, i.e. not scrolled off the alignment */ |
1081 get_iter_from_node(node, &parent); | |
10353 | 1082 gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(gtkblist->treemodel), &iter, &parent, |
9811 | 1083 gtk_tree_model_iter_n_children(GTK_TREE_MODEL(gtkblist->treemodel), &parent) -1); |
9632 | 1084 path = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &iter); |
1085 /* Let the treeview draw so it knows where to scroll */ | |
1086 while (gtk_events_pending()) | |
1087 gtk_main_iteration(); | |
10353 | 1088 gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW(gtkblist->treeview), path, NULL, FALSE, 0, 0); |
1089 | |
9632 | 1090 |
7620 | 1091 gaim_gtk_blist_update(NULL, node); |
9632 | 1092 gtk_tree_path_free(path); |
7620 | 1093 } |
1094 | |
1095 static void | |
1096 gaim_gtk_blist_collapse_contact_cb(GtkWidget *w, GaimBlistNode *node) | |
1097 { | |
1098 GaimBlistNode *bnode; | |
1099 struct _gaim_gtk_blist_node *gtknode; | |
1100 | |
1101 if(!GAIM_BLIST_NODE_IS_CONTACT(node)) | |
1102 return; | |
1103 | |
1104 gtknode = (struct _gaim_gtk_blist_node *)node->ui_data; | |
1105 | |
1106 gtknode->contact_expanded = FALSE; | |
1107 | |
1108 for(bnode = node->child; bnode; bnode = bnode->next) { | |
1109 gaim_gtk_blist_update(NULL, bnode); | |
5228 | 1110 } |
1111 } | |
1112 | |
9030 | 1113 |
1114 static void | |
1115 blist_node_menu_cb(GtkMenuItem *item, GaimBlistNode *node) | |
1116 { | |
1117 GaimBlistNodeAction *act; | |
1118 act = (GaimBlistNodeAction *) g_object_get_data(G_OBJECT(item), | |
1119 "gaimcallback"); | |
1120 if(act->callback) | |
1121 act->callback(node, act->data); | |
1122 } | |
1123 | |
1124 | |
1125 static void | |
10662
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
1126 append_blist_node_action(GtkWidget *menu, GaimBlistNodeAction *act, |
9030 | 1127 GaimBlistNode *node, gboolean *dup_separator) |
5228 | 1128 { |
9030 | 1129 if(act == NULL) { |
1130 if(! *dup_separator) { | |
1131 gaim_separator(menu); | |
1132 *dup_separator = TRUE; | |
1133 } | |
1134 } else { | |
1135 GtkWidget *menuitem; | |
1136 | |
10662
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
1137 if (act->children == NULL) { |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
1138 *dup_separator = FALSE; |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
1139 |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
1140 menuitem = gtk_menu_item_new_with_mnemonic(act->label); |
11038
aedd557f46dd
[gaim-migrate @ 12935]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
1141 if (act->callback != NULL) { |
aedd557f46dd
[gaim-migrate @ 12935]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
1142 g_object_set_data(G_OBJECT(menuitem), "gaimcallback", |
aedd557f46dd
[gaim-migrate @ 12935]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
1143 act); |
aedd557f46dd
[gaim-migrate @ 12935]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
1144 g_signal_connect(G_OBJECT(menuitem), "activate", |
aedd557f46dd
[gaim-migrate @ 12935]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
1145 G_CALLBACK(blist_node_menu_cb), node); |
aedd557f46dd
[gaim-migrate @ 12935]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
1146 } else { |
aedd557f46dd
[gaim-migrate @ 12935]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
1147 gtk_widget_set_sensitive(menuitem, FALSE); |
aedd557f46dd
[gaim-migrate @ 12935]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
1148 } |
10662
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
1149 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
1150 } else { |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
1151 GtkWidget *submenu = NULL; |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
1152 GList *l = NULL; |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
1153 |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
1154 menuitem = gtk_menu_item_new_with_mnemonic(act->label); |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
1155 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
1156 |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
1157 submenu = gtk_menu_new(); |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
1158 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
1159 |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
1160 for (l = act->children; l; l = l->next) { |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
1161 GaimBlistNodeAction *act = (GaimBlistNodeAction *) l->data; |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
1162 |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
1163 append_blist_node_action(submenu, act, node, dup_separator); |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
1164 |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
1165 g_list_free(act->children); |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
1166 act->children = NULL; |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
1167 } |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
1168 } |
9030 | 1169 } |
5228 | 1170 } |
1171 | |
9030 | 1172 |
9051 | 1173 void |
10662
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
1174 gaim_gtk_append_blist_node_proto_menu(GtkWidget *menu, GaimConnection *gc, |
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10643
diff
changeset
|
1175 GaimBlistNode *node) |
9030 | 1176 { |
1177 GList *l, *ll; | |
1178 gboolean dup_separator = FALSE; | |
1179 GaimPluginProtocolInfo *prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl); | |
1180 | |
1181 if(!prpl_info || !prpl_info->blist_node_menu) | |
1182 return; | |
1183 | |
1184 for(l = ll = prpl_info->blist_node_menu(node); l; l = l->next) { | |
1185 GaimBlistNodeAction *act = (GaimBlistNodeAction *) l->data; | |
1186 append_blist_node_action(menu, act, node, &dup_separator); | |
1187 } | |
1188 g_list_free(ll); | |
1189 } | |
1190 | |
1191 | |
9051 | 1192 void |
1193 gaim_gtk_append_blist_node_extended_menu (GtkWidget *menu, GaimBlistNode *node) | |
9030 | 1194 { |
1195 GList *l, *ll; | |
1196 gboolean dup_separator = FALSE; | |
1197 | |
1198 for(l = ll = gaim_blist_node_get_extended_menu(node); l; l = l->next) { | |
1199 GaimBlistNodeAction *act = (GaimBlistNodeAction *) l->data; | |
1200 append_blist_node_action(menu, act, node, &dup_separator); | |
1201 } | |
1202 g_list_free(ll); | |
1203 } | |
1204 | |
1205 | |
9774 | 1206 void |
10484 | 1207 gaim_gtk_blist_make_buddy_menu(GtkWidget *menu, GaimBuddy *buddy, gboolean sub) { |
9774 | 1208 GaimPluginProtocolInfo *prpl_info; |
10663 | 1209 GaimContact *contact; |
1210 gboolean contact_expanded = FALSE; | |
9774 | 1211 |
1212 g_return_if_fail(menu); | |
1213 g_return_if_fail(buddy); | |
1214 | |
1215 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(buddy->account->gc->prpl); | |
1216 | |
10663 | 1217 contact = gaim_buddy_get_contact(buddy); |
1218 if (contact) { | |
1219 contact_expanded = ((struct _gaim_gtk_blist_node *)(((GaimBlistNode*)contact)->ui_data))->contact_expanded; | |
1220 } | |
1221 | |
7620 | 1222 if (prpl_info && prpl_info->get_info) { |
8137 | 1223 gaim_new_item_from_stock(menu, _("Get _Info"), GAIM_STOCK_INFO, |
9774 | 1224 G_CALLBACK(gtk_blist_menu_info_cb), buddy, 0, 0, NULL); |
7620 | 1225 } |
8137 | 1226 gaim_new_item_from_stock(menu, _("I_M"), GAIM_STOCK_IM, |
9774 | 1227 G_CALLBACK(gtk_blist_menu_im_cb), buddy, 0, 0, NULL); |
9466 | 1228 if (prpl_info && prpl_info->send_file) { |
9774 | 1229 if (!prpl_info->can_receive_file || |
1230 prpl_info->can_receive_file(buddy->account->gc, buddy->name)) | |
1231 { | |
1232 gaim_new_item_from_stock(menu, _("_Send File"), | |
1233 GAIM_STOCK_FILE_TRANSFER, | |
1234 G_CALLBACK(gtk_blist_menu_send_file_cb), | |
1235 buddy, 0, 0, NULL); | |
9466 | 1236 } |
1237 } | |
7620 | 1238 gaim_new_item_from_stock(menu, _("Add Buddy _Pounce"), NULL, |
9774 | 1239 G_CALLBACK(gtk_blist_menu_bp_cb), buddy, 0, 0, NULL); |
10663 | 1240 |
1241 if(((GaimBlistNode*)buddy)->parent->child->next && !sub && !contact_expanded) { | |
1242 gaim_new_item_from_stock(menu, _("View _Log"), NULL, | |
1243 G_CALLBACK(gtk_blist_menu_showlog_cb), | |
1244 contact, 0, 0, NULL); | |
1245 } else if (!sub) { | |
1246 gaim_new_item_from_stock(menu, _("View _Log"), NULL, | |
1247 G_CALLBACK(gtk_blist_menu_showlog_cb), buddy, 0, 0, NULL); | |
1248 } | |
9774 | 1249 |
1250 gaim_gtk_append_blist_node_proto_menu(menu, buddy->account->gc, | |
1251 (GaimBlistNode *)buddy); | |
1252 gaim_gtk_append_blist_node_extended_menu(menu, (GaimBlistNode *)buddy); | |
7620 | 1253 |
1254 gaim_separator(menu); | |
9030 | 1255 |
10663 | 1256 if(((GaimBlistNode*)buddy)->parent->child->next && !sub && !contact_expanded) { |
9925 | 1257 gaim_new_item_from_stock(menu, _("_Alias Buddy..."), GAIM_STOCK_ALIAS, |
1258 G_CALLBACK(gtk_blist_menu_alias_cb), buddy, 0, 0, NULL); | |
1259 gaim_new_item_from_stock(menu, _("_Remove Buddy"), GTK_STOCK_REMOVE, | |
1260 G_CALLBACK(gaim_gtk_blist_remove_cb), buddy, 0, 0, NULL); | |
1261 gaim_new_item_from_stock(menu, _("Alias Contact..."), GAIM_STOCK_ALIAS, | |
1262 G_CALLBACK(gtk_blist_menu_alias_cb), | |
10663 | 1263 contact, 0, 0, NULL); |
9925 | 1264 gaim_new_item_from_stock(menu, _("Remove Contact"), GTK_STOCK_REMOVE, |
1265 G_CALLBACK(gaim_gtk_blist_remove_cb), | |
10663 | 1266 contact, 0, 0, NULL); |
9925 | 1267 } else { |
1268 gaim_new_item_from_stock(menu, _("_Alias..."), GAIM_STOCK_ALIAS, | |
1269 G_CALLBACK(gtk_blist_menu_alias_cb), buddy, 0, 0, NULL); | |
1270 gaim_new_item_from_stock(menu, _("_Remove"), GTK_STOCK_REMOVE, | |
1271 G_CALLBACK(gaim_gtk_blist_remove_cb), buddy, | |
1272 0, 0, NULL); | |
1273 } | |
7620 | 1274 } |
1275 | |
9774 | 1276 static gboolean |
1277 gtk_blist_key_press_cb(GtkWidget *tv, GdkEventKey *event, gpointer data) { | |
7620 | 1278 GaimBlistNode *node; |
1279 GValue val = { 0, }; | |
1280 GtkTreeIter iter; | |
1281 GtkTreeSelection *sel; | |
1282 | |
1283 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv)); | |
1284 if(!gtk_tree_selection_get_selected(sel, NULL, &iter)) | |
1285 return FALSE; | |
1286 | |
1287 gtk_tree_model_get_value(GTK_TREE_MODEL(gtkblist->treemodel), &iter, | |
1288 NODE_COLUMN, &val); | |
1289 node = g_value_get_pointer(&val); | |
1290 | |
1291 if(event->state & GDK_CONTROL_MASK && | |
1292 (event->keyval == 'o' || event->keyval == 'O')) { | |
1293 GaimBuddy *buddy; | |
1294 | |
1295 if(GAIM_BLIST_NODE_IS_CONTACT(node)) { | |
1296 buddy = gaim_contact_get_priority_buddy((GaimContact*)node); | |
1297 } else if(GAIM_BLIST_NODE_IS_BUDDY(node)) { | |
1298 buddy = (GaimBuddy*)node; | |
1299 } else { | |
1300 return FALSE; | |
1301 } | |
1302 if(buddy) | |
1303 serv_get_info(buddy->account->gc, buddy->name); | |
1304 } | |
1305 | |
1306 return FALSE; | |
1307 } | |
1308 | |
9013 | 1309 |
8143 | 1310 static GtkWidget * |
8952 | 1311 create_group_menu (GaimBlistNode *node, GaimGroup *g) |
8143 | 1312 { |
1313 GtkWidget *menu; | |
1314 | |
1315 menu = gtk_menu_new(); | |
1316 gaim_new_item_from_stock(menu, _("Add a _Buddy"), GTK_STOCK_ADD, | |
1317 G_CALLBACK(gaim_gtk_blist_add_buddy_cb), node, 0, 0, NULL); | |
1318 gaim_new_item_from_stock(menu, _("Add a C_hat"), GTK_STOCK_ADD, | |
1319 G_CALLBACK(gaim_gtk_blist_add_chat_cb), node, 0, 0, NULL); | |
1320 gaim_new_item_from_stock(menu, _("_Delete Group"), GTK_STOCK_REMOVE, | |
1321 G_CALLBACK(gaim_gtk_blist_remove_cb), node, 0, 0, NULL); | |
1322 gaim_new_item_from_stock(menu, _("_Rename"), NULL, | |
11016 | 1323 G_CALLBACK(gtk_blist_menu_alias_cb), node, 0, 0, NULL); |
8952 | 1324 |
9051 | 1325 gaim_gtk_append_blist_node_extended_menu(menu, node); |
8952 | 1326 |
8143 | 1327 return menu; |
1328 } | |
1329 | |
8586 | 1330 |
8143 | 1331 static GtkWidget * |
9774 | 1332 create_chat_menu(GaimBlistNode *node, GaimChat *c) { |
8143 | 1333 GtkWidget *menu; |
9030 | 1334 gboolean autojoin; |
8143 | 1335 |
1336 menu = gtk_menu_new(); | |
9030 | 1337 autojoin = (gaim_blist_node_get_bool(node, "gtk-autojoin") || |
1338 (gaim_blist_node_get_string(node, "gtk-autojoin") != NULL)); | |
1339 | |
8143 | 1340 gaim_new_item_from_stock(menu, _("_Join"), GAIM_STOCK_CHAT, |
9030 | 1341 G_CALLBACK(gtk_blist_menu_join_cb), node, 0, 0, NULL); |
8143 | 1342 gaim_new_check_item(menu, _("Auto-Join"), |
9030 | 1343 G_CALLBACK(gtk_blist_menu_autojoin_cb), node, autojoin); |
9917 | 1344 gaim_new_item_from_stock(menu, _("View _Log"), NULL, |
1345 G_CALLBACK(gtk_blist_menu_showlog_cb), node, 0, 0, NULL); | |
9030 | 1346 |
9051 | 1347 gaim_gtk_append_blist_node_proto_menu(menu, c->account->gc, node); |
1348 gaim_gtk_append_blist_node_extended_menu(menu, node); | |
8586 | 1349 |
1350 gaim_separator(menu); | |
9030 | 1351 |
8302
462ead6fc1a0
[gaim-migrate @ 9026]
Christian Hammond <chipx86@chipx86.com>
parents:
8259
diff
changeset
|
1352 gaim_new_item_from_stock(menu, _("_Alias..."), GAIM_STOCK_ALIAS, |
8143 | 1353 G_CALLBACK(gtk_blist_menu_alias_cb), node, 0, 0, NULL); |
1354 gaim_new_item_from_stock(menu, _("_Remove"), GTK_STOCK_REMOVE, | |
1355 G_CALLBACK(gaim_gtk_blist_remove_cb), node, 0, 0, NULL); | |
8586 | 1356 |
8143 | 1357 return menu; |
1358 } | |
1359 | |
1360 static GtkWidget * | |
1361 create_contact_menu (GaimBlistNode *node) | |
1362 { | |
1363 GtkWidget *menu; | |
1364 | |
1365 menu = gtk_menu_new(); | |
10663 | 1366 |
1367 gaim_new_item_from_stock(menu, _("View _Log"), NULL, | |
1368 G_CALLBACK(gtk_blist_menu_showlog_cb), | |
1369 node, 0, 0, NULL); | |
1370 | |
1371 gaim_separator(menu); | |
1372 | |
8302
462ead6fc1a0
[gaim-migrate @ 9026]
Christian Hammond <chipx86@chipx86.com>
parents:
8259
diff
changeset
|
1373 gaim_new_item_from_stock(menu, _("_Alias..."), GAIM_STOCK_ALIAS, |
8143 | 1374 G_CALLBACK(gtk_blist_menu_alias_cb), node, 0, 0, NULL); |
10663 | 1375 gaim_new_item_from_stock(menu, _("_Remove"), GTK_STOCK_REMOVE, |
1376 G_CALLBACK(gaim_gtk_blist_remove_cb), node, 0, 0, NULL); | |
1377 | |
1378 gaim_separator(menu); | |
1379 | |
8143 | 1380 gaim_new_item_from_stock(menu, _("_Collapse"), GTK_STOCK_ZOOM_OUT, |
1381 G_CALLBACK(gaim_gtk_blist_collapse_contact_cb), | |
1382 node, 0, 0, NULL); | |
9051 | 1383 |
1384 gaim_gtk_append_blist_node_extended_menu(menu, node); | |
1385 | |
8143 | 1386 return menu; |
1387 } | |
1388 | |
1389 static GtkWidget * | |
9774 | 1390 create_buddy_menu(GaimBlistNode *node, GaimBuddy *b) { |
8143 | 1391 struct _gaim_gtk_blist_node *gtknode = (struct _gaim_gtk_blist_node *)node->ui_data; |
1392 GtkWidget *menu; | |
1393 GtkWidget *menuitem; | |
1394 gboolean show_offline = gaim_prefs_get_bool("/gaim/gtk/blist/show_offline_buddies"); | |
8470
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
1395 |
8143 | 1396 menu = gtk_menu_new(); |
10484 | 1397 gaim_gtk_blist_make_buddy_menu(menu, b, FALSE); |
8143 | 1398 |
1399 if(GAIM_BLIST_NODE_IS_CONTACT(node)) { | |
1400 gaim_separator(menu); | |
8470
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
1401 |
8143 | 1402 if(gtknode->contact_expanded) { |
1403 gaim_new_item_from_stock(menu, _("_Collapse"), | |
1404 GTK_STOCK_ZOOM_OUT, | |
1405 G_CALLBACK(gaim_gtk_blist_collapse_contact_cb), | |
1406 node, 0, 0, NULL); | |
1407 } else { | |
1408 gaim_new_item_from_stock(menu, _("_Expand"), | |
1409 GTK_STOCK_ZOOM_IN, | |
1410 G_CALLBACK(gaim_gtk_blist_expand_contact_cb), node, | |
1411 0, 0, NULL); | |
1412 } | |
1413 if(node->child->next) { | |
1414 GaimBlistNode *bnode; | |
1415 | |
1416 for(bnode = node->child; bnode; bnode = bnode->next) { | |
1417 GaimBuddy *buddy = (GaimBuddy*)bnode; | |
9340 | 1418 GdkPixbuf *buf; |
8143 | 1419 GtkWidget *submenu; |
1420 GtkWidget *image; | |
1421 | |
1422 if(buddy == b) | |
1423 continue; | |
1424 if(!buddy->account->gc) | |
1425 continue; | |
1426 if(!show_offline && !GAIM_BUDDY_IS_ONLINE(buddy)) | |
1427 continue; | |
1428 | |
1429 menuitem = gtk_image_menu_item_new_with_label(buddy->name); | |
9340 | 1430 buf = gaim_gtk_blist_get_status_icon(bnode, |
1431 GAIM_STATUS_ICON_SMALL); | |
1432 image = gtk_image_new_from_pixbuf(buf); | |
1433 g_object_unref(G_OBJECT(buf)); | |
8143 | 1434 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), |
9811 | 1435 image); |
8143 | 1436 gtk_widget_show(image); |
1437 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); | |
1438 gtk_widget_show(menuitem); | |
1439 | |
1440 submenu = gtk_menu_new(); | |
1441 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); | |
1442 gtk_widget_show(submenu); | |
1443 | |
10484 | 1444 gaim_gtk_blist_make_buddy_menu(submenu, buddy, TRUE); |
8143 | 1445 } |
1446 } | |
1447 } | |
1448 return menu; | |
1449 } | |
1450 | |
1451 static gboolean | |
1452 gaim_gtk_blist_show_context_menu(GaimBlistNode *node, | |
1453 GtkMenuPositionFunc func, | |
1454 GtkWidget *tv, | |
1455 guint button, | |
1456 guint32 time) | |
1457 { | |
1458 struct _gaim_gtk_blist_node *gtknode; | |
1459 GtkWidget *menu = NULL; | |
1460 gboolean handled = FALSE; | |
1461 | |
1462 gtknode = (struct _gaim_gtk_blist_node *)node->ui_data; | |
1463 | |
1464 /* Create a menu based on the thing we right-clicked on */ | |
1465 if (GAIM_BLIST_NODE_IS_GROUP(node)) { | |
8952 | 1466 GaimGroup *g = (GaimGroup *)node; |
9774 | 1467 |
8952 | 1468 menu = create_group_menu(node, g); |
8143 | 1469 } else if (GAIM_BLIST_NODE_IS_CHAT(node)) { |
8586 | 1470 GaimChat *c = (GaimChat *)node; |
9774 | 1471 |
1472 menu = create_chat_menu(node, c); | |
8143 | 1473 } else if ((GAIM_BLIST_NODE_IS_CONTACT(node)) && (gtknode->contact_expanded)) { |
1474 menu = create_contact_menu(node); | |
1475 } else if (GAIM_BLIST_NODE_IS_CONTACT(node) || GAIM_BLIST_NODE_IS_BUDDY(node)) { | |
1476 GaimBuddy *b; | |
1477 | |
1478 if (GAIM_BLIST_NODE_IS_CONTACT(node)) | |
1479 b = gaim_contact_get_priority_buddy((GaimContact*)node); | |
1480 else | |
1481 b = (GaimBuddy *)node; | |
1482 | |
9774 | 1483 menu = create_buddy_menu(node, b); |
8143 | 1484 } |
1485 | |
11059
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1486 #ifdef _WIN32 |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1487 /* Unhook the tooltip-timeout since we don't want a tooltip |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1488 * to appear and obscure the context menu we are about to show |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1489 This is a workaround for GTK+ bug 107320. */ |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1490 if (gtkblist->timeout) { |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1491 g_source_remove(gtkblist->timeout); |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1492 gtkblist->timeout = 0; |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1493 } |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1494 #endif |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1495 |
8143 | 1496 /* Now display the menu */ |
1497 if (menu != NULL) { | |
1498 gtk_widget_show_all(menu); | |
1499 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, func, tv, button, time); | |
1500 handled = TRUE; | |
1501 } | |
1502 | |
1503 return handled; | |
1504 } | |
1505 | |
1506 static gboolean gtk_blist_button_press_cb(GtkWidget *tv, GdkEventButton *event, gpointer user_data) | |
5228 | 1507 { |
1508 GtkTreePath *path; | |
1509 GaimBlistNode *node; | |
1510 GValue val = { 0, }; | |
1511 GtkTreeIter iter; | |
1512 GtkTreeSelection *sel; | |
1513 GaimPlugin *prpl = NULL; | |
1514 GaimPluginProtocolInfo *prpl_info = NULL; | |
7620 | 1515 struct _gaim_gtk_blist_node *gtknode; |
1516 gboolean handled = FALSE; | |
5228 | 1517 |
1518 /* Here we figure out which node was clicked */ | |
1519 if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), event->x, event->y, &path, NULL, NULL, NULL)) | |
1520 return FALSE; | |
1521 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); | |
8143 | 1522 gtk_tree_model_get_value(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val); |
5228 | 1523 node = g_value_get_pointer(&val); |
7620 | 1524 gtknode = (struct _gaim_gtk_blist_node *)node->ui_data; |
1525 | |
8143 | 1526 /* Right click draws a context menu */ |
1527 if ((event->button == 3) && (event->type == GDK_BUTTON_PRESS)) { | |
1528 handled = gaim_gtk_blist_show_context_menu(node, NULL, tv, 3, event->time); | |
1529 | |
1530 /* CTRL+middle click expands or collapse a contact */ | |
1531 } else if ((event->button == 2) && (event->type == GDK_BUTTON_PRESS) && | |
1532 (event->state & GDK_CONTROL_MASK) && (GAIM_BLIST_NODE_IS_CONTACT(node))) { | |
1533 if (gtknode->contact_expanded) | |
7620 | 1534 gaim_gtk_blist_collapse_contact_cb(NULL, node); |
1535 else | |
1536 gaim_gtk_blist_expand_contact_cb(NULL, node); | |
1537 handled = TRUE; | |
8143 | 1538 |
1539 /* Double middle click gets info */ | |
1540 } else if ((event->button == 2) && (event->type == GDK_2BUTTON_PRESS) && | |
1541 ((GAIM_BLIST_NODE_IS_CONTACT(node)) || (GAIM_BLIST_NODE_IS_BUDDY(node)))) { | |
7620 | 1542 GaimBuddy *b; |
1543 if(GAIM_BLIST_NODE_IS_CONTACT(node)) | |
1544 b = gaim_contact_get_priority_buddy((GaimContact*)node); | |
1545 else | |
1546 b = (GaimBuddy *)node; | |
1547 | |
7956 | 1548 prpl = gaim_find_prpl(gaim_account_get_protocol_id(b->account)); |
5228 | 1549 if (prpl != NULL) |
1550 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl); | |
1551 | |
8143 | 1552 if (prpl && prpl_info->get_info) |
1553 serv_get_info(b->account->gc, b->name); | |
1554 handled = TRUE; | |
5228 | 1555 } |
1556 | |
8143 | 1557 #if (1) |
1558 /* | |
10814
364a2ef907ae
[gaim-migrate @ 12468]
Luke Schierer <lschiere@pidgin.im>
parents:
10780
diff
changeset
|
1559 * This code only exists because GTK+ doesn't work. If we return |
8143 | 1560 * FALSE here, as would be normal the event propoagates down and |
1561 * somehow gets interpreted as the start of a drag event. | |
1562 * | |
1563 * Um, isn't it _normal_ to return TRUE here? Since the event | |
1564 * was handled? --Mark | |
1565 */ | |
7620 | 1566 if(handled) { |
1567 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv)); | |
1568 gtk_tree_selection_select_path(sel, path); | |
1569 gtk_tree_path_free(path); | |
1570 return TRUE; | |
1571 } | |
5228 | 1572 #endif |
7753 | 1573 gtk_tree_path_free(path); |
8143 | 1574 |
7620 | 1575 return FALSE; |
5228 | 1576 } |
1577 | |
8143 | 1578 static gboolean |
1579 gaim_gtk_blist_popup_menu_cb(GtkWidget *tv, void *user_data) | |
1580 { | |
1581 GaimBlistNode *node; | |
1582 GValue val = { 0, }; | |
1583 GtkTreeIter iter; | |
1584 GtkTreeSelection *sel; | |
1585 gboolean handled = FALSE; | |
1586 | |
1587 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv)); | |
1588 if (!gtk_tree_selection_get_selected(sel, NULL, &iter)) | |
1589 return FALSE; | |
1590 | |
1591 gtk_tree_model_get_value(GTK_TREE_MODEL(gtkblist->treemodel), | |
1592 &iter, NODE_COLUMN, &val); | |
1593 node = g_value_get_pointer(&val); | |
1594 | |
1595 /* Shift+F10 draws a context menu */ | |
1596 handled = gaim_gtk_blist_show_context_menu(node, gaim_gtk_treeview_popup_menu_position_func, tv, 0, GDK_CURRENT_TIME); | |
1597 | |
1598 return handled; | |
1599 } | |
1600 | |
5228 | 1601 static void gaim_gtk_blist_show_empty_groups_cb(gpointer data, guint action, GtkWidget *item) |
1602 { | |
7620 | 1603 gaim_prefs_set_bool("/gaim/gtk/blist/show_empty_groups", |
1604 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item))); | |
5228 | 1605 } |
1606 | |
1607 static void gaim_gtk_blist_edit_mode_cb(gpointer callback_data, guint callback_action, | |
1608 GtkWidget *checkitem) { | |
1609 if(gtkblist->window->window) { | |
1610 GdkCursor *cursor = gdk_cursor_new(GDK_WATCH); | |
1611 gdk_window_set_cursor(gtkblist->window->window, cursor); | |
1612 while (gtk_events_pending()) | |
1613 gtk_main_iteration(); | |
1614 gdk_cursor_unref(cursor); | |
1615 } | |
1616 | |
7620 | 1617 gaim_prefs_set_bool("/gaim/gtk/blist/show_offline_buddies", |
1618 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(checkitem))); | |
5228 | 1619 |
1620 if(gtkblist->window->window) { | |
1621 GdkCursor *cursor = gdk_cursor_new(GDK_LEFT_PTR); | |
1622 gdk_window_set_cursor(gtkblist->window->window, cursor); | |
1623 gdk_cursor_unref(cursor); | |
1624 } | |
1625 } | |
1626 | |
10074 | 1627 static void gaim_gtk_blist_mute_sounds_cb(gpointer data, guint action, GtkWidget *item) |
1628 { | |
1629 gaim_prefs_set_bool("/gaim/gtk/sound/mute", GTK_CHECK_MENU_ITEM(item)->active); | |
1630 } | |
1631 | |
1632 static void gaim_gtk_blist_mute_pref_cb(const char *name, GaimPrefType type, gpointer value, gpointer data) | |
1633 { | |
1634 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item(gtkblist->ift, | |
1635 N_("/Tools/Mute Sounds"))), (gboolean)GPOINTER_TO_INT(value)); | |
1636 } | |
1637 | |
1638 static void gaim_gtk_blist_sound_method_pref_cb(const char *name, GaimPrefType type, gpointer value, gpointer data) | |
1639 { | |
1640 gboolean sensitive = TRUE; | |
1641 | |
1642 if(!strcmp(value, "none")) | |
1643 sensitive = FALSE; | |
1644 | |
1645 gtk_widget_set_sensitive(gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Mute Sounds")), sensitive); | |
1646 } | |
1647 | |
8089 | 1648 static void |
1649 add_buddies_from_vcard(const char *prpl_id, GaimGroup *group, GList *list, | |
1650 const char *alias) | |
1651 { | |
1652 GList *l; | |
1653 GaimAccount *account = NULL; | |
1654 GaimConnection *gc; | |
1655 | |
1656 if (list == NULL) | |
1657 return; | |
1658 | |
1659 for (l = gaim_connections_get_all(); l != NULL; l = l->next) | |
1660 { | |
1661 gc = (GaimConnection *)l->data; | |
1662 account = gaim_connection_get_account(gc); | |
1663 | |
1664 if (!strcmp(gaim_account_get_protocol_id(account), prpl_id)) | |
1665 break; | |
1666 | |
1667 account = NULL; | |
1668 } | |
1669 | |
1670 if (account != NULL) | |
1671 { | |
1672 for (l = list; l != NULL; l = l->next) | |
1673 { | |
1674 gaim_blist_request_add_buddy(account, l->data, | |
1675 (group ? group->name : NULL), | |
1676 alias); | |
1677 } | |
1678 } | |
1679 | |
1680 g_list_foreach(list, (GFunc)g_free, NULL); | |
1681 g_list_free(list); | |
1682 } | |
1683 | |
1684 static gboolean | |
1685 parse_vcard(const char *vcard, GaimGroup *group) | |
1686 { | |
1687 char *temp_vcard; | |
1688 char *s, *c; | |
1689 char *alias = NULL; | |
1690 GList *aims = NULL; | |
1691 GList *icqs = NULL; | |
1692 GList *yahoos = NULL; | |
1693 GList *msns = NULL; | |
1694 GList *jabbers = NULL; | |
1695 | |
1696 s = temp_vcard = g_strdup(vcard); | |
1697 | |
1698 while (*s != '\0' && strncmp(s, "END:vCard", strlen("END:vCard"))) | |
1699 { | |
1700 char *field, *value; | |
1701 | |
1702 field = s; | |
1703 | |
1704 /* Grab the field */ | |
1705 while (*s != '\r' && *s != '\n' && *s != '\0' && *s != ':') | |
1706 s++; | |
1707 | |
1708 if (*s == '\r') s++; | |
1709 if (*s == '\n') | |
1710 { | |
1711 s++; | |
1712 continue; | |
1713 } | |
1714 | |
1715 if (*s != '\0') *s++ = '\0'; | |
1716 | |
1717 if ((c = strchr(field, ';')) != NULL) | |
1718 *c = '\0'; | |
1719 | |
1720 /* Proceed to the end of the line */ | |
1721 value = s; | |
1722 | |
1723 while (*s != '\r' && *s != '\n' && *s != '\0') | |
1724 s++; | |
1725 | |
1726 if (*s == '\r') *s++ = '\0'; | |
1727 if (*s == '\n') *s++ = '\0'; | |
1728 | |
1729 /* We only want to worry about a few fields here. */ | |
1730 if (!strcmp(field, "FN")) | |
1731 alias = g_strdup(value); | |
1732 else if (!strcmp(field, "X-AIM") || !strcmp(field, "X-ICQ") || | |
1733 !strcmp(field, "X-YAHOO") || !strcmp(field, "X-MSN") || | |
1734 !strcmp(field, "X-JABBER")) | |
1735 { | |
1736 char **values = g_strsplit(value, ":", 0); | |
1737 char **im; | |
1738 | |
1739 for (im = values; *im != NULL; im++) | |
1740 { | |
1741 if (!strcmp(field, "X-AIM")) | |
1742 aims = g_list_append(aims, g_strdup(*im)); | |
1743 else if (!strcmp(field, "X-ICQ")) | |
1744 icqs = g_list_append(icqs, g_strdup(*im)); | |
1745 else if (!strcmp(field, "X-YAHOO")) | |
1746 yahoos = g_list_append(yahoos, g_strdup(*im)); | |
1747 else if (!strcmp(field, "X-MSN")) | |
1748 msns = g_list_append(msns, g_strdup(*im)); | |
1749 else if (!strcmp(field, "X-JABBER")) | |
1750 jabbers = g_list_append(jabbers, g_strdup(*im)); | |
1751 } | |
1752 | |
1753 g_strfreev(values); | |
1754 } | |
1755 } | |
1756 | |
1757 g_free(temp_vcard); | |
1758 | |
1759 if (aims == NULL && icqs == NULL && yahoos == NULL && | |
1760 msns == NULL && jabbers == NULL) | |
1761 { | |
1762 if (alias != NULL) | |
1763 g_free(alias); | |
1764 | |
1765 return FALSE; | |
1766 } | |
1767 | |
1768 add_buddies_from_vcard("prpl-oscar", group, aims, alias); | |
1769 add_buddies_from_vcard("prpl-oscar", group, icqs, alias); | |
1770 add_buddies_from_vcard("prpl-yahoo", group, yahoos, alias); | |
1771 add_buddies_from_vcard("prpl-msn", group, msns, alias); | |
1772 add_buddies_from_vcard("prpl-jabber", group, jabbers, alias); | |
1773 | |
1774 if (alias != NULL) | |
1775 g_free(alias); | |
1776 | |
1777 return TRUE; | |
1778 } | |
1779 | |
11059
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1780 #ifdef _WIN32 |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1781 static void gaim_gtk_blist_drag_begin(GtkWidget *widget, |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1782 GdkDragContext *drag_context, gpointer user_data) |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1783 { |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1784 gaim_gtk_blist_tooltip_destroy(); |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1785 |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1786 |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1787 /* Unhook the tooltip-timeout since we don't want a tooltip |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1788 * to appear and obscure the dragging operation. |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1789 * This is a workaround for GTK+ bug 107320. */ |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1790 if (gtkblist->timeout) { |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1791 g_source_remove(gtkblist->timeout); |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1792 gtkblist->timeout = 0; |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1793 } |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1794 } |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1795 #endif |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1796 |
9811 | 1797 static void gaim_gtk_blist_drag_data_get_cb(GtkWidget *widget, |
1798 GdkDragContext *dc, | |
1799 GtkSelectionData *data, | |
1800 guint info, | |
1801 guint time, | |
11059
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1802 gpointer null) |
5228 | 1803 { |
11059
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
1804 |
8089 | 1805 if (data->target == gdk_atom_intern("GAIM_BLIST_NODE", FALSE)) |
1806 { | |
5228 | 1807 GtkTreeRowReference *ref = g_object_get_data(G_OBJECT(dc), "gtk-tree-view-source-row"); |
1808 GtkTreePath *sourcerow = gtk_tree_row_reference_get_path(ref); | |
1809 GtkTreeIter iter; | |
1810 GaimBlistNode *node = NULL; | |
1811 GValue val = {0}; | |
5273 | 1812 if(!sourcerow) |
1813 return; | |
5228 | 1814 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, sourcerow); |
1815 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val); | |
1816 node = g_value_get_pointer(&val); | |
1817 gtk_selection_data_set (data, | |
1818 gdk_atom_intern ("GAIM_BLIST_NODE", FALSE), | |
1819 8, /* bits */ | |
1820 (void*)&node, | |
1821 sizeof (node)); | |
5273 | 1822 |
5228 | 1823 gtk_tree_path_free(sourcerow); |
1824 } | |
8089 | 1825 else if (data->target == gdk_atom_intern("application/x-im-contact", FALSE)) |
1826 { | |
7706 | 1827 GtkTreeRowReference *ref; |
1828 GtkTreePath *sourcerow; | |
1829 GtkTreeIter iter; | |
1830 GaimBlistNode *node = NULL; | |
1831 GaimBuddy *buddy; | |
1832 GaimConnection *gc; | |
1833 GValue val = {0}; | |
1834 GString *str; | |
1835 const char *protocol; | |
1836 char *mime_str; | |
1837 | |
1838 ref = g_object_get_data(G_OBJECT(dc), "gtk-tree-view-source-row"); | |
1839 sourcerow = gtk_tree_row_reference_get_path(ref); | |
1840 | |
1841 if (!sourcerow) | |
1842 return; | |
1843 | |
1844 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, | |
1845 sourcerow); | |
1846 gtk_tree_model_get_value(GTK_TREE_MODEL(gtkblist->treemodel), &iter, | |
1847 NODE_COLUMN, &val); | |
1848 | |
1849 node = g_value_get_pointer(&val); | |
1850 | |
1851 if (GAIM_BLIST_NODE_IS_CONTACT(node)) | |
1852 { | |
1853 buddy = gaim_contact_get_priority_buddy((GaimContact *)node); | |
1854 } | |
1855 else if (!GAIM_BLIST_NODE_IS_BUDDY(node)) | |
1856 { | |
1857 gtk_tree_path_free(sourcerow); | |
1858 return; | |
1859 } | |
1860 else | |
1861 { | |
1862 buddy = (GaimBuddy *)node; | |
1863 } | |
1864 | |
1865 gc = gaim_account_get_connection(buddy->account); | |
1866 | |
1867 if (gc == NULL) | |
1868 { | |
1869 gtk_tree_path_free(sourcerow); | |
1870 return; | |
1871 } | |
1872 | |
1873 protocol = | |
1874 GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->list_icon(buddy->account, | |
1875 buddy); | |
1876 | |
1877 str = g_string_new(NULL); | |
1878 g_string_printf(str, | |
1879 "MIME-Version: 1.0\r\n" | |
1880 "Content-Type: application/x-im-contact\r\n" | |
1881 "X-IM-Protocol: %s\r\n" | |
1882 "X-IM-Username: %s\r\n", | |
1883 protocol, | |
1884 buddy->name); | |
1885 | |
1886 if (buddy->alias != NULL) | |
1887 { | |
1888 g_string_append_printf(str, | |
1889 "X-IM-Alias: %s\r\n", | |
1890 buddy->alias); | |
1891 } | |
1892 | |
1893 str = g_string_append(str, "\r\n"); | |
1894 | |
1895 mime_str = g_string_free(str, FALSE); | |
1896 | |
1897 gtk_selection_data_set(data, | |
1898 gdk_atom_intern("application/x-im-contact", FALSE), | |
1899 8, /* bits */ | |
11137 | 1900 (const guchar *)mime_str, |
7706 | 1901 strlen(mime_str) + 1); |
1902 | |
1903 g_free(mime_str); | |
1904 gtk_tree_path_free(sourcerow); | |
1905 } | |
5228 | 1906 } |
1907 | |
1908 static void gaim_gtk_blist_drag_data_rcv_cb(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, | |
1909 GtkSelectionData *sd, guint info, guint t) | |
7620 | 1910 { |
5228 | 1911 if (sd->target == gdk_atom_intern("GAIM_BLIST_NODE", FALSE) && sd->data) { |
1912 GaimBlistNode *n = NULL; | |
1913 GtkTreePath *path = NULL; | |
1914 GtkTreeViewDropPosition position; | |
1915 memcpy(&n, sd->data, sizeof(n)); | |
1916 if(gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(widget), x, y, &path, &position)) { | |
8470
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
1917 /* if we're here, I think it means the drop is ok */ |
7642 | 1918 GtkTreeIter iter; |
5228 | 1919 GaimBlistNode *node; |
1920 GValue val = {0}; | |
7620 | 1921 struct _gaim_gtk_blist_node *gtknode; |
1922 | |
1923 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), | |
1924 &iter, path); | |
1925 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), | |
1926 &iter, NODE_COLUMN, &val); | |
5228 | 1927 node = g_value_get_pointer(&val); |
7620 | 1928 gtknode = node->ui_data; |
1929 | |
1930 if (GAIM_BLIST_NODE_IS_CONTACT(n)) { | |
1931 GaimContact *c = (GaimContact*)n; | |
1932 if (GAIM_BLIST_NODE_IS_CONTACT(node) && gtknode->contact_expanded) { | |
1933 gaim_blist_merge_contact(c, node); | |
1934 } else if (GAIM_BLIST_NODE_IS_CONTACT(node) || | |
5234 | 1935 GAIM_BLIST_NODE_IS_CHAT(node)) { |
5228 | 1936 switch(position) { |
1937 case GTK_TREE_VIEW_DROP_AFTER: | |
1938 case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: | |
7620 | 1939 gaim_blist_add_contact(c, (GaimGroup*)node->parent, |
1940 node); | |
1941 break; | |
1942 case GTK_TREE_VIEW_DROP_BEFORE: | |
1943 case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE: | |
1944 gaim_blist_add_contact(c, (GaimGroup*)node->parent, | |
1945 node->prev); | |
1946 break; | |
1947 } | |
1948 } else if(GAIM_BLIST_NODE_IS_GROUP(node)) { | |
1949 gaim_blist_add_contact(c, (GaimGroup*)node, NULL); | |
1950 } else if(GAIM_BLIST_NODE_IS_BUDDY(node)) { | |
1951 gaim_blist_merge_contact(c, node); | |
1952 } | |
1953 } else if (GAIM_BLIST_NODE_IS_BUDDY(n)) { | |
1954 GaimBuddy *b = (GaimBuddy*)n; | |
1955 if (GAIM_BLIST_NODE_IS_BUDDY(node)) { | |
1956 switch(position) { | |
1957 case GTK_TREE_VIEW_DROP_AFTER: | |
1958 case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: | |
1959 gaim_blist_add_buddy(b, (GaimContact*)node->parent, | |
1960 (GaimGroup*)node->parent->parent, node); | |
5228 | 1961 break; |
1962 case GTK_TREE_VIEW_DROP_BEFORE: | |
1963 case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE: | |
7620 | 1964 gaim_blist_add_buddy(b, (GaimContact*)node->parent, |
1965 (GaimGroup*)node->parent->parent, | |
1966 node->prev); | |
5228 | 1967 break; |
1968 } | |
7620 | 1969 } else if(GAIM_BLIST_NODE_IS_CHAT(node)) { |
1970 gaim_blist_add_buddy(b, NULL, (GaimGroup*)node->parent, | |
1971 NULL); | |
5228 | 1972 } else if (GAIM_BLIST_NODE_IS_GROUP(node)) { |
7620 | 1973 gaim_blist_add_buddy(b, NULL, (GaimGroup*)node, NULL); |
1974 } else if (GAIM_BLIST_NODE_IS_CONTACT(node)) { | |
1975 if(gtknode->contact_expanded) { | |
1976 switch(position) { | |
1977 case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: | |
1978 case GTK_TREE_VIEW_DROP_AFTER: | |
1979 case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE: | |
1980 gaim_blist_add_buddy(b, (GaimContact*)node, | |
1981 (GaimGroup*)node->parent, NULL); | |
1982 break; | |
1983 case GTK_TREE_VIEW_DROP_BEFORE: | |
1984 gaim_blist_add_buddy(b, NULL, | |
1985 (GaimGroup*)node->parent, node->prev); | |
1986 break; | |
1987 } | |
1988 } else { | |
1989 switch(position) { | |
1990 case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: | |
1991 case GTK_TREE_VIEW_DROP_AFTER: | |
1992 gaim_blist_add_buddy(b, NULL, | |
1993 (GaimGroup*)node->parent, NULL); | |
1994 break; | |
1995 case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE: | |
1996 case GTK_TREE_VIEW_DROP_BEFORE: | |
1997 gaim_blist_add_buddy(b, NULL, | |
1998 (GaimGroup*)node->parent, node->prev); | |
1999 break; | |
2000 } | |
2001 } | |
5228 | 2002 } |
5234 | 2003 } else if (GAIM_BLIST_NODE_IS_CHAT(n)) { |
7620 | 2004 GaimChat *chat = (GaimChat *)n; |
2005 if (GAIM_BLIST_NODE_IS_BUDDY(node)) { | |
2006 switch(position) { | |
2007 case GTK_TREE_VIEW_DROP_AFTER: | |
2008 case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: | |
2009 gaim_blist_add_chat(chat, | |
2010 (GaimGroup*)node->parent->parent, node); | |
2011 break; | |
2012 case GTK_TREE_VIEW_DROP_BEFORE: | |
2013 case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE: | |
2014 gaim_blist_add_chat(chat, | |
2015 (GaimGroup*)node->parent->parent, | |
2016 node->prev); | |
2017 break; | |
2018 } | |
2019 } else if(GAIM_BLIST_NODE_IS_CONTACT(node) || | |
5234 | 2020 GAIM_BLIST_NODE_IS_CHAT(node)) { |
2021 switch(position) { | |
2022 case GTK_TREE_VIEW_DROP_AFTER: | |
2023 case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: | |
7620 | 2024 gaim_blist_add_chat(chat, (GaimGroup*)node->parent, node); |
5234 | 2025 break; |
2026 case GTK_TREE_VIEW_DROP_BEFORE: | |
2027 case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE: | |
7620 | 2028 gaim_blist_add_chat(chat, (GaimGroup*)node->parent, node->prev); |
5234 | 2029 break; |
2030 } | |
2031 } else if (GAIM_BLIST_NODE_IS_GROUP(node)) { | |
7620 | 2032 gaim_blist_add_chat(chat, (GaimGroup*)node, NULL); |
5234 | 2033 } |
5228 | 2034 } else if (GAIM_BLIST_NODE_IS_GROUP(n)) { |
7620 | 2035 GaimGroup *g = (GaimGroup*)n; |
5228 | 2036 if (GAIM_BLIST_NODE_IS_GROUP(node)) { |
2037 switch (position) { | |
2038 case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: | |
2039 case GTK_TREE_VIEW_DROP_AFTER: | |
2040 gaim_blist_add_group(g, node); | |
2041 break; | |
2042 case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE: | |
2043 case GTK_TREE_VIEW_DROP_BEFORE: | |
2044 gaim_blist_add_group(g, node->prev); | |
2045 break; | |
2046 } | |
7620 | 2047 } else if(GAIM_BLIST_NODE_IS_BUDDY(node)) { |
2048 gaim_blist_add_group(g, node->parent->parent); | |
2049 } else if(GAIM_BLIST_NODE_IS_CONTACT(node) || | |
5234 | 2050 GAIM_BLIST_NODE_IS_CHAT(node)) { |
5228 | 2051 gaim_blist_add_group(g, node->parent); |
2052 } | |
2053 } | |
2054 | |
2055 gtk_tree_path_free(path); | |
7620 | 2056 gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t); |
5228 | 2057 } |
2058 } | |
7706 | 2059 else if (sd->target == gdk_atom_intern("application/x-im-contact", |
2060 FALSE) && sd->data) | |
2061 { | |
2062 GaimGroup *group = NULL; | |
2063 GtkTreePath *path = NULL; | |
2064 GtkTreeViewDropPosition position; | |
7712
2823111061ba
[gaim-migrate @ 8357]
Christian Hammond <chipx86@chipx86.com>
parents:
7706
diff
changeset
|
2065 GaimAccount *account; |
7706 | 2066 char *protocol = NULL; |
2067 char *username = NULL; | |
2068 char *alias = NULL; | |
2069 | |
2070 if (gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(widget), | |
2071 x, y, &path, &position)) | |
2072 { | |
2073 GtkTreeIter iter; | |
2074 GaimBlistNode *node; | |
2075 GValue val = {0}; | |
2076 | |
2077 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), | |
2078 &iter, path); | |
2079 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), | |
2080 &iter, NODE_COLUMN, &val); | |
2081 node = g_value_get_pointer(&val); | |
2082 | |
2083 if (GAIM_BLIST_NODE_IS_BUDDY(node)) | |
2084 { | |
2085 group = (GaimGroup *)node->parent->parent; | |
2086 } | |
2087 else if (GAIM_BLIST_NODE_IS_CHAT(node) || | |
2088 GAIM_BLIST_NODE_IS_CONTACT(node)) | |
2089 { | |
2090 group = (GaimGroup *)node->parent; | |
2091 } | |
2092 else if (GAIM_BLIST_NODE_IS_GROUP(node)) | |
2093 { | |
2094 group = (GaimGroup *)node; | |
2095 } | |
2096 } | |
2097 | |
11137 | 2098 if (gaim_gtk_parse_x_im_contact((const char *)sd->data, FALSE, &account, |
7712
2823111061ba
[gaim-migrate @ 8357]
Christian Hammond <chipx86@chipx86.com>
parents:
7706
diff
changeset
|
2099 &protocol, &username, &alias)) |
7706 | 2100 { |
2101 if (account == NULL) | |
2102 { | |
2103 gaim_notify_error(NULL, NULL, | |
2104 _("You are not currently signed on with an account that " | |
2105 "can add that buddy."), NULL); | |
2106 } | |
2107 else | |
2108 { | |
2109 gaim_blist_request_add_buddy(account, username, | |
2110 (group ? group->name : NULL), | |
2111 alias); | |
2112 } | |
2113 } | |
2114 | |
2115 if (username != NULL) g_free(username); | |
2116 if (protocol != NULL) g_free(protocol); | |
2117 if (alias != NULL) g_free(alias); | |
2118 | |
2119 if (path != NULL) | |
2120 gtk_tree_path_free(path); | |
2121 | |
2122 gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t); | |
2123 } | |
8089 | 2124 else if (sd->target == gdk_atom_intern("text/x-vcard", FALSE) && sd->data) |
2125 { | |
2126 gboolean result; | |
2127 GaimGroup *group = NULL; | |
2128 GtkTreePath *path = NULL; | |
2129 GtkTreeViewDropPosition position; | |
2130 | |
2131 if (gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(widget), | |
2132 x, y, &path, &position)) | |
2133 { | |
2134 GtkTreeIter iter; | |
2135 GaimBlistNode *node; | |
2136 GValue val = {0}; | |
2137 | |
2138 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), | |
2139 &iter, path); | |
2140 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), | |
2141 &iter, NODE_COLUMN, &val); | |
2142 node = g_value_get_pointer(&val); | |
2143 | |
2144 if (GAIM_BLIST_NODE_IS_BUDDY(node)) | |
2145 { | |
2146 group = (GaimGroup *)node->parent->parent; | |
2147 } | |
2148 else if (GAIM_BLIST_NODE_IS_CHAT(node) || | |
2149 GAIM_BLIST_NODE_IS_CONTACT(node)) | |
2150 { | |
2151 group = (GaimGroup *)node->parent; | |
2152 } | |
2153 else if (GAIM_BLIST_NODE_IS_GROUP(node)) | |
2154 { | |
2155 group = (GaimGroup *)node; | |
2156 } | |
2157 } | |
2158 | |
11137 | 2159 result = parse_vcard((const gchar *)sd->data, group); |
8089 | 2160 |
2161 gtk_drag_finish(dc, result, (dc->action == GDK_ACTION_MOVE), t); | |
9525 | 2162 } else if (sd->target == gdk_atom_intern("text/uri-list", FALSE) && sd->data) { |
9495 | 2163 GtkTreePath *path = NULL; |
2164 GtkTreeViewDropPosition position; | |
2165 | |
2166 if (gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(widget), | |
9811 | 2167 x, y, &path, &position)) |
9495 | 2168 { |
2169 GtkTreeIter iter; | |
2170 GaimBlistNode *node; | |
2171 GValue val = {0}; | |
10382
9f28196ed769
[gaim-migrate @ 11608]
Luke Schierer <lschiere@pidgin.im>
parents:
10357
diff
changeset
|
2172 |
9495 | 2173 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), |
2174 &iter, path); | |
2175 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), | |
2176 &iter, NODE_COLUMN, &val); | |
2177 node = g_value_get_pointer(&val); | |
10382
9f28196ed769
[gaim-migrate @ 11608]
Luke Schierer <lschiere@pidgin.im>
parents:
10357
diff
changeset
|
2178 |
9495 | 2179 if (GAIM_BLIST_NODE_IS_BUDDY(node) || GAIM_BLIST_NODE_IS_CONTACT(node)) { |
2180 GaimBuddy *b = GAIM_BLIST_NODE_IS_BUDDY(node) ? (GaimBuddy*)node : gaim_contact_get_priority_buddy((GaimContact*)node); | |
10229 | 2181 gaim_dnd_file_manage(sd, b->account, b->name); |
2182 gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t); | |
2183 } else { | |
2184 gtk_drag_finish(dc, FALSE, FALSE, t); | |
9495 | 2185 } |
10382
9f28196ed769
[gaim-migrate @ 11608]
Luke Schierer <lschiere@pidgin.im>
parents:
10357
diff
changeset
|
2186 } |
8089 | 2187 } |
5228 | 2188 } |
2189 | |
10482 | 2190 static GdkPixbuf *gaim_gtk_blist_get_buddy_icon(GaimBlistNode *node, |
2191 gboolean scaled, gboolean greyed) | |
2192 { | |
10483 | 2193 GdkPixbuf *buf, *ret = NULL; |
10482 | 2194 GdkPixbufLoader *loader; |
2195 GaimBuddyIcon *icon; | |
11137 | 2196 const guchar *data; |
2197 gsize len; | |
10482 | 2198 GaimBuddy *buddy = (GaimBuddy *)node; |
2199 | |
2200 if(GAIM_BLIST_NODE_IS_CONTACT(node)) { | |
2201 buddy = gaim_contact_get_priority_buddy((GaimContact*)node); | |
2202 } else if(GAIM_BLIST_NODE_IS_BUDDY(node)) { | |
2203 buddy = (GaimBuddy*)node; | |
2204 } else { | |
2205 return NULL; | |
2206 } | |
2207 | |
2208 #if 0 | |
2209 if (!gaim_prefs_get_bool("/gaim/gtk/blist/show_buddy_icons")) | |
2210 return NULL; | |
2211 #endif | |
2212 | |
2213 if (!(icon = gaim_buddy_get_icon(buddy))) | |
2214 if (!(icon = gaim_buddy_icons_find(buddy->account, buddy->name))) /* Not sure I like this...*/ | |
2215 return NULL; | |
2216 | |
2217 loader = gdk_pixbuf_loader_new(); | |
2218 data = gaim_buddy_icon_get_data(icon, &len); | |
2219 gdk_pixbuf_loader_write(loader, data, len, NULL); | |
2220 buf = gdk_pixbuf_loader_get_pixbuf(loader); | |
2221 if (buf) | |
2222 g_object_ref(G_OBJECT(buf)); | |
2223 gdk_pixbuf_loader_close(loader, NULL); | |
2224 g_object_unref(G_OBJECT(loader)); | |
2225 | |
2226 if (buf) { | |
10544 | 2227 GaimAccount *account = gaim_buddy_get_account(buddy); |
2228 GaimPluginProtocolInfo *prpl_info = NULL; | |
2229 int orig_width, orig_height; | |
2230 int scale_width, scale_height; | |
2231 | |
2232 if(account && account->gc) | |
2233 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(account->gc->prpl); | |
2234 | |
10482 | 2235 if (greyed) { |
2236 GaimPresence *presence = gaim_buddy_get_presence(buddy); | |
2237 if (!GAIM_BUDDY_IS_ONLINE(buddy)) | |
2238 gdk_pixbuf_saturate_and_pixelate(buf, buf, 0.0, FALSE); | |
2239 if (gaim_presence_is_idle(presence)) | |
2240 gdk_pixbuf_saturate_and_pixelate(buf, buf, 0.25, FALSE); | |
2241 } | |
2242 | |
10544 | 2243 /* i'd use the gaim_gtk_buddy_icon_get_scale_size() thing, |
2244 * but it won't tell me the original size, which I need for scaling | |
2245 * purposes */ | |
2246 scale_width = orig_width = gdk_pixbuf_get_width(buf); | |
2247 scale_height = orig_height = gdk_pixbuf_get_height(buf); | |
2248 | |
2249 gaim_buddy_icon_get_scale_size(prpl_info ? &prpl_info->icon_spec : NULL, &scale_width, &scale_height); | |
2250 | |
10482 | 2251 if (scaled) { |
10544 | 2252 if(scale_height > scale_width) { |
2253 scale_width = 30.0 * (double)scale_width / (double)scale_height; | |
2254 scale_height = 30; | |
2255 } else { | |
2256 scale_height = 30.0 * (double)scale_height / (double)scale_width; | |
2257 scale_width = 30; | |
2258 } | |
2259 | |
2260 ret = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 30, 30); | |
2261 gdk_pixbuf_fill(ret, 0x00000000); | |
2262 gdk_pixbuf_scale(buf, ret, (30-scale_width)/2, (30-scale_height)/2, scale_width, scale_height, (30-scale_width)/2, (30-scale_height)/2, (double)scale_width/(double)orig_width, (double)scale_height/(double)orig_height, GDK_INTERP_BILINEAR); | |
10483 | 2263 } else { |
2264 ret = gdk_pixbuf_scale_simple(buf,scale_width,scale_height, GDK_INTERP_BILINEAR); | |
2265 } | |
10544 | 2266 g_object_unref(G_OBJECT(buf)); |
10482 | 2267 } |
2268 | |
10483 | 2269 return ret; |
10482 | 2270 } |
2271 | |
5234 | 2272 static void gaim_gtk_blist_paint_tip(GtkWidget *widget, GdkEventExpose *event, GaimBlistNode *node) |
5228 | 2273 { |
2274 GtkStyle *style; | |
5234 | 2275 GdkPixbuf *pixbuf = gaim_gtk_blist_get_status_icon(node, GAIM_STATUS_ICON_LARGE); |
5228 | 2276 PangoLayout *layout; |
5234 | 2277 char *tooltiptext = gaim_get_tooltip_text(node); |
10482 | 2278 GdkPixbuf *avatar = NULL; |
2279 int layout_width, layout_height; | |
5228 | 2280 |
7620 | 2281 if(!tooltiptext) |
2282 return; | |
2283 | |
10482 | 2284 avatar = gaim_gtk_blist_get_buddy_icon(node, FALSE, FALSE); |
2285 | |
5228 | 2286 layout = gtk_widget_create_pango_layout (gtkblist->tipwindow, NULL); |
2287 pango_layout_set_markup(layout, tooltiptext, strlen(tooltiptext)); | |
2288 pango_layout_set_wrap(layout, PANGO_WRAP_WORD); | |
2289 pango_layout_set_width(layout, 300000); | |
10482 | 2290 { |
2291 int w, h; | |
2292 pango_layout_get_size (layout, &w, &h); | |
2293 layout_width = PANGO_PIXELS(w) + 8; | |
2294 layout_height = PANGO_PIXELS(h) + 8; | |
2295 } | |
5228 | 2296 style = gtkblist->tipwindow->style; |
2297 | |
9811 | 2298 gtk_paint_flat_box(style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, GTK_SHADOW_OUT, |
2299 NULL, gtkblist->tipwindow, "tooltip", 0, 0, -1, -1); | |
5228 | 2300 |
2301 #if GTK_CHECK_VERSION(2,2,0) | |
2302 gdk_draw_pixbuf(GDK_DRAWABLE(gtkblist->tipwindow->window), NULL, pixbuf, | |
2303 0, 0, 4, 4, -1 , -1, GDK_RGB_DITHER_NONE, 0, 0); | |
10482 | 2304 if(avatar) |
2305 gdk_draw_pixbuf(GDK_DRAWABLE(gtkblist->tipwindow->window), NULL, | |
2306 avatar, 0, 0, layout_width + 38 + 4, 4, -1 , -1, GDK_RGB_DITHER_NONE, 0, 0); | |
5228 | 2307 #else |
2308 gdk_pixbuf_render_to_drawable(pixbuf, GDK_DRAWABLE(gtkblist->tipwindow->window), NULL, 0, 0, 4, 4, -1, -1, GDK_RGB_DITHER_NONE, 0, 0); | |
10482 | 2309 if(avatar) |
2310 gdk_pixbuf_render_to_drawable(avatar, | |
2311 GDK_DRAWABLE(gtkblist->tipwindow->window), NULL, 0, 0, layout_width + 38 + 4, | |
2312 4, -1, -1, GDK_RGB_DITHER_NONE, 0, 0); | |
5228 | 2313 #endif |
2314 | |
10778 | 2315 gtk_paint_layout (style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, FALSE, |
10482 | 2316 NULL, gtkblist->tipwindow, "tooltip", 38 + 4, 4, layout); |
2317 | |
2318 if(avatar) | |
2319 g_object_unref (avatar); | |
5228 | 2320 |
2321 g_object_unref (pixbuf); | |
2322 g_object_unref (layout); | |
2323 g_free(tooltiptext); | |
7620 | 2324 |
7662 | 2325 #ifdef WANT_DROP_SHADOW |
10015 | 2326 if (!xcomposite_is_present()) { |
2327 shadow_paint(gtkblist, NULL, EAST_SIDE); | |
2328 shadow_paint(gtkblist, NULL, SOUTH_SIDE); | |
2329 } | |
7620 | 2330 #endif |
2331 | |
5228 | 2332 return; |
2333 } | |
2334 | |
8254 | 2335 static void gaim_gtk_blist_tooltip_destroy() |
2336 { | |
2337 if (gtkblist->tipwindow == NULL) | |
2338 return; | |
2339 | |
2340 gtk_widget_destroy(gtkblist->tipwindow); | |
2341 gtkblist->tipwindow = NULL; | |
2342 #ifdef WANT_DROP_SHADOW | |
10015 | 2343 if (!xcomposite_is_present()) { |
2344 gdk_window_set_user_data (gtkblist->east_shadow, NULL); | |
2345 gdk_window_destroy (gtkblist->east_shadow); | |
2346 gtkblist->east_shadow = NULL; | |
2347 | |
2348 gdk_window_set_user_data (gtkblist->south_shadow, NULL); | |
2349 gdk_window_destroy (gtkblist->south_shadow); | |
2350 gtkblist->south_shadow = NULL; | |
2351 } | |
8254 | 2352 #endif |
2353 } | |
2354 | |
10354 | 2355 |
2356 static gboolean gaim_gtk_blist_expand_timeout(GtkWidget *tv) | |
2357 { | |
2358 GtkTreePath *path; | |
2359 GtkTreeIter iter; | |
2360 GaimBlistNode *node; | |
2361 GValue val = {0}; | |
2362 struct _gaim_gtk_blist_node *gtknode; | |
2363 | |
2364 if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), gtkblist->tip_rect.x, gtkblist->tip_rect.y, &path, NULL, NULL, NULL)) | |
2365 return FALSE; | |
2366 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); | |
2367 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val); | |
2368 node = g_value_get_pointer(&val); | |
2369 | |
10504 | 2370 if(!GAIM_BLIST_NODE_IS_CONTACT(node)) { |
2371 gtk_tree_path_free(path); | |
10354 | 2372 return FALSE; |
10504 | 2373 } |
10354 | 2374 |
2375 gtknode = node->ui_data; | |
2376 | |
2377 if (!gtknode->contact_expanded) { | |
2378 GtkTreeIter i; | |
10382
9f28196ed769
[gaim-migrate @ 11608]
Luke Schierer <lschiere@pidgin.im>
parents:
10357
diff
changeset
|
2379 |
10354 | 2380 gaim_gtk_blist_expand_contact_cb(NULL, node); |
10382
9f28196ed769
[gaim-migrate @ 11608]
Luke Schierer <lschiere@pidgin.im>
parents:
10357
diff
changeset
|
2381 |
10354 | 2382 gtk_tree_view_get_cell_area(GTK_TREE_VIEW(tv), path, NULL, >kblist->contact_rect); |
2383 gdk_drawable_get_size(GDK_DRAWABLE(tv->window), &(gtkblist->contact_rect.width), NULL); | |
2384 gtkblist->mouseover_contact = node; | |
2385 gtk_tree_path_down (path); | |
2386 while (gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &i, path)) { | |
2387 GdkRectangle rect; | |
2388 gtk_tree_view_get_cell_area(GTK_TREE_VIEW(tv), path, NULL, &rect); | |
2389 gtkblist->contact_rect.height += rect.height; | |
2390 gtk_tree_path_next(path); | |
2391 } | |
2392 } | |
2393 gtk_tree_path_free(path); | |
2394 return FALSE; | |
2395 } | |
2396 | |
5228 | 2397 static gboolean gaim_gtk_blist_tooltip_timeout(GtkWidget *tv) |
2398 { | |
2399 GtkTreePath *path; | |
2400 GtkTreeIter iter; | |
2401 GaimBlistNode *node; | |
2402 GValue val = {0}; | |
9869 | 2403 int scr_w, scr_h, w, h, x, y; |
2404 #if GTK_CHECK_VERSION(2,2,0) | |
2405 int mon_num; | |
2406 GdkScreen *screen = NULL; | |
2407 #endif | |
5234 | 2408 PangoLayout *layout; |
7636 | 2409 gboolean tooltip_top = FALSE; |
5234 | 2410 char *tooltiptext = NULL; |
7636 | 2411 struct _gaim_gtk_blist_node *gtknode; |
9773 | 2412 GdkRectangle mon_size; |
7662 | 2413 #ifdef WANT_DROP_SHADOW |
7620 | 2414 GdkWindowAttr attr; |
2415 #endif | |
5228 | 2416 |
7636 | 2417 if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), gtkblist->tip_rect.x, gtkblist->tip_rect.y, &path, NULL, NULL, NULL)) |
5228 | 2418 return FALSE; |
2419 gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); | |
2420 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val); | |
2421 node = g_value_get_pointer(&val); | |
7620 | 2422 |
10504 | 2423 gtk_tree_path_free(path); |
2424 | |
7620 | 2425 if(!GAIM_BLIST_NODE_IS_CONTACT(node) && !GAIM_BLIST_NODE_IS_BUDDY(node) |
2426 && !GAIM_BLIST_NODE_IS_CHAT(node)) | |
5234 | 2427 return FALSE; |
5228 | 2428 |
7636 | 2429 gtknode = node->ui_data; |
2430 | |
5234 | 2431 tooltiptext = gaim_get_tooltip_text(node); |
7620 | 2432 |
2433 if(!tooltiptext) | |
2434 return FALSE; | |
2435 | |
7837 | 2436 if(gtkblist->tipwindow) |
2437 gtk_widget_destroy(gtkblist->tipwindow); | |
5234 | 2438 gtkblist->tipwindow = gtk_window_new(GTK_WINDOW_POPUP); |
2439 gtk_widget_set_app_paintable(gtkblist->tipwindow, TRUE); | |
2440 gtk_window_set_resizable(GTK_WINDOW(gtkblist->tipwindow), FALSE); | |
2441 gtk_widget_set_name(gtkblist->tipwindow, "gtk-tooltips"); | |
2442 g_signal_connect(G_OBJECT(gtkblist->tipwindow), "expose_event", | |
2443 G_CALLBACK(gaim_gtk_blist_paint_tip), node); | |
2444 gtk_widget_ensure_style (gtkblist->tipwindow); | |
7837 | 2445 |
7662 | 2446 #ifdef WANT_DROP_SHADOW |
10015 | 2447 if (!xcomposite_is_present()) { |
2448 attr.window_type = GDK_WINDOW_TEMP; | |
2449 attr.override_redirect = TRUE; | |
2450 attr.x = gtkblist->tipwindow->allocation.x; | |
2451 attr.y = gtkblist->tipwindow->allocation.y; | |
2452 attr.width = gtkblist->tipwindow->allocation.width; | |
2453 attr.height = gtkblist->tipwindow->allocation.height; | |
2454 attr.wclass = GDK_INPUT_OUTPUT; | |
2455 attr.visual = gtk_widget_get_visual (gtkblist->window); | |
2456 attr.colormap = gtk_widget_get_colormap (gtkblist->window); | |
2457 | |
2458 attr.event_mask = gtk_widget_get_events (gtkblist->tipwindow); | |
2459 | |
2460 attr.event_mask |= (GDK_EXPOSURE_MASK | GDK_KEY_PRESS_MASK | | |
2461 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK ); | |
2462 if(gtkblist->east_shadow) { | |
2463 gdk_window_set_user_data (gtkblist->east_shadow, NULL); | |
2464 gdk_window_destroy (gtkblist->east_shadow); | |
2465 } | |
2466 gtkblist->east_shadow = gdk_window_new(gtk_widget_get_root_window(gtkblist->tipwindow), &attr, | |
2467 GDK_WA_NOREDIR | GDK_WA_VISUAL | GDK_WA_COLORMAP); | |
2468 gdk_window_set_user_data (gtkblist->east_shadow, gtkblist->tipwindow); | |
2469 gdk_window_set_back_pixmap (gtkblist->east_shadow, NULL, FALSE); | |
2470 | |
2471 if(gtkblist->south_shadow) { | |
2472 gdk_window_set_user_data (gtkblist->south_shadow, NULL); | |
2473 gdk_window_destroy (gtkblist->south_shadow); | |
2474 } | |
2475 gtkblist->south_shadow = gdk_window_new(gtk_widget_get_root_window(gtkblist->tipwindow), &attr, | |
2476 GDK_WA_NOREDIR | GDK_WA_VISUAL | GDK_WA_COLORMAP); | |
2477 gdk_window_set_user_data (gtkblist->south_shadow, gtkblist->tipwindow); | |
2478 gdk_window_set_back_pixmap (gtkblist->south_shadow, NULL, FALSE); | |
7897 | 2479 } |
10968
e0d5038fbb7e
[gaim-migrate @ 12789]
Christopher O'Brien <siege@pidgin.im>
parents:
10924
diff
changeset
|
2480 #endif /* ifdef WANT_DROP_SHADOW */ |
8470
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
2481 |
5234 | 2482 layout = gtk_widget_create_pango_layout (gtkblist->tipwindow, NULL); |
2483 pango_layout_set_wrap(layout, PANGO_WRAP_WORD); | |
2484 pango_layout_set_width(layout, 300000); | |
2485 pango_layout_set_markup(layout, tooltiptext, strlen(tooltiptext)); | |
2486 pango_layout_get_size (layout, &w, &h); | |
9773 | 2487 |
9869 | 2488 #if GTK_CHECK_VERSION(2,2,0) |
9773 | 2489 gdk_display_get_pointer(gdk_display_get_default(), &screen, &x, &y, NULL); |
2490 mon_num = gdk_screen_get_monitor_at_point(screen, x, y); | |
2491 gdk_screen_get_monitor_geometry(screen, mon_num, &mon_size); | |
2492 | |
2493 scr_w = mon_size.width + mon_size.x; | |
2494 scr_h = mon_size.height + mon_size.y; | |
9869 | 2495 #else |
2496 scr_w = gdk_screen_width(); | |
2497 scr_h = gdk_screen_height(); | |
2498 gdk_window_get_pointer(NULL, &x, &y, NULL); | |
2499 mon_size.x = 0; | |
2500 mon_size.y = 0; | |
2501 #endif | |
9773 | 2502 |
5234 | 2503 w = PANGO_PIXELS(w) + 8; |
2504 h = PANGO_PIXELS(h) + 8; | |
5228 | 2505 |
5234 | 2506 /* 38 is the size of a large status icon plus 4 pixels padding on each side. |
2507 * I should #define this or something */ | |
2508 w = w + 38; | |
2509 h = MAX(h, 38); | |
2510 | |
10482 | 2511 /* Now the size of the buddy icon */ |
2512 { | |
2513 GdkPixbuf *avatar = NULL; | |
2514 | |
2515 if ((avatar = gaim_gtk_blist_get_buddy_icon(node, FALSE, FALSE))) { | |
2516 w += gdk_pixbuf_get_width(avatar) + 8; | |
2517 h = MAX(h, gdk_pixbuf_get_height(avatar) + 8); | |
2518 g_object_unref(avatar); | |
2519 } | |
2520 } | |
2521 | |
9869 | 2522 #if GTK_CHECK_VERSION(2,2,0) |
10046 | 2523 if (w > mon_size.width) |
9773 | 2524 w = mon_size.width - 10; |
2525 | |
10046 | 2526 if (h > mon_size.height) |
9773 | 2527 h = mon_size.height - 10; |
9869 | 2528 #endif |
9773 | 2529 |
5234 | 2530 if (GTK_WIDGET_NO_WINDOW(gtkblist->window)) |
2531 y+=gtkblist->window->allocation.y; | |
2532 | |
2533 x -= ((w >> 1) + 4); | |
5228 | 2534 |
7636 | 2535 if ((y + h + 4) > scr_h || tooltip_top) |
7620 | 2536 y = y - h - 5; |
5234 | 2537 else |
2538 y = y + 6; | |
7620 | 2539 |
9773 | 2540 if (y < mon_size.y) |
2541 y = mon_size.y; | |
2542 | |
2543 if (y != mon_size.y) { | |
7719 | 2544 if ((x + w) > scr_w) |
2545 x -= (x + w + 5) - scr_w; | |
9773 | 2546 else if (x < mon_size.x) |
2547 x = mon_size.x; | |
7719 | 2548 } else { |
2549 x -= (w / 2 + 10); | |
9773 | 2550 if (x < mon_size.x) |
2551 x = mon_size.x; | |
7719 | 2552 } |
2553 | |
5234 | 2554 g_object_unref (layout); |
2555 g_free(tooltiptext); | |
2556 gtk_widget_set_size_request(gtkblist->tipwindow, w, h); | |
2557 gtk_window_move(GTK_WINDOW(gtkblist->tipwindow), x, y); | |
2558 gtk_widget_show(gtkblist->tipwindow); | |
5228 | 2559 |
7662 | 2560 #ifdef WANT_DROP_SHADOW |
10015 | 2561 if (!xcomposite_is_present()) { |
2562 map_shadow_windows(gtkblist); | |
2563 } | |
7620 | 2564 #endif |
2565 | |
5228 | 2566 return FALSE; |
2567 } | |
2568 | |
10354 | 2569 static gboolean gaim_gtk_blist_drag_motion_cb(GtkWidget *tv, GdkDragContext *drag_context, |
2570 gint x, gint y, guint time, gpointer user_data) | |
2571 { | |
2572 GtkTreePath *path; | |
2573 int delay; | |
2574 | |
2575 delay = 500; | |
2576 | |
2577 if (gtkblist->drag_timeout) { | |
2578 if ((y > gtkblist->tip_rect.y) && ((y - gtkblist->tip_rect.height) < gtkblist->tip_rect.y)) | |
2579 return FALSE; | |
2580 /* We've left the cell. Remove the timeout and create a new one below */ | |
2581 g_source_remove(gtkblist->drag_timeout); | |
2582 } | |
2583 | |
2584 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), x, y, &path, NULL, NULL, NULL); | |
2585 gtk_tree_view_get_cell_area(GTK_TREE_VIEW(tv), path, NULL, >kblist->tip_rect); | |
2586 | |
2587 if (path) | |
2588 gtk_tree_path_free(path); | |
2589 gtkblist->drag_timeout = g_timeout_add(delay, (GSourceFunc)gaim_gtk_blist_expand_timeout, tv); | |
2590 | |
2591 if (gtkblist->mouseover_contact) { | |
2592 if ((y < gtkblist->contact_rect.y) || ((y - gtkblist->contact_rect.height) > gtkblist->contact_rect.y)) { | |
2593 gaim_gtk_blist_collapse_contact_cb(NULL, gtkblist->mouseover_contact); | |
2594 gtkblist->mouseover_contact = NULL; | |
2595 } | |
2596 } | |
2597 | |
2598 return FALSE; | |
2599 } | |
2600 | |
5228 | 2601 static gboolean gaim_gtk_blist_motion_cb (GtkWidget *tv, GdkEventMotion *event, gpointer null) |
2602 { | |
2603 GtkTreePath *path; | |
8470
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
2604 int delay; |
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
2605 |
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
2606 delay = gaim_prefs_get_int("/gaim/gtk/blist/tooltip_delay"); |
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
2607 |
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
2608 if (delay == 0) |
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
2609 return FALSE; |
8083 | 2610 |
5228 | 2611 if (gtkblist->timeout) { |
7636 | 2612 if ((event->y > gtkblist->tip_rect.y) && ((event->y - gtkblist->tip_rect.height) < gtkblist->tip_rect.y)) |
5228 | 2613 return FALSE; |
2614 /* We've left the cell. Remove the timeout and create a new one below */ | |
8254 | 2615 gaim_gtk_blist_tooltip_destroy(); |
5228 | 2616 g_source_remove(gtkblist->timeout); |
2617 } | |
8470
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
2618 |
5228 | 2619 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), event->x, event->y, &path, NULL, NULL, NULL); |
7636 | 2620 gtk_tree_view_get_cell_area(GTK_TREE_VIEW(tv), path, NULL, >kblist->tip_rect); |
8470
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
2621 |
5228 | 2622 if (path) |
2623 gtk_tree_path_free(path); | |
8470
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
2624 gtkblist->timeout = g_timeout_add(delay, (GSourceFunc)gaim_gtk_blist_tooltip_timeout, tv); |
7636 | 2625 |
2626 if (gtkblist->mouseover_contact) { | |
2627 if ((event->y < gtkblist->contact_rect.y) || ((event->y - gtkblist->contact_rect.height) > gtkblist->contact_rect.y)) { | |
2628 gaim_gtk_blist_collapse_contact_cb(NULL, gtkblist->mouseover_contact); | |
2629 gtkblist->mouseover_contact = NULL; | |
2630 } | |
2631 } | |
8470
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
2632 |
5228 | 2633 return FALSE; |
2634 } | |
2635 | |
2636 static void gaim_gtk_blist_leave_cb (GtkWidget *w, GdkEventCrossing *e, gpointer n) | |
2637 { | |
8083 | 2638 |
5228 | 2639 if (gtkblist->timeout) { |
2640 g_source_remove(gtkblist->timeout); | |
2641 gtkblist->timeout = 0; | |
2642 } | |
10382
9f28196ed769
[gaim-migrate @ 11608]
Luke Schierer <lschiere@pidgin.im>
parents:
10357
diff
changeset
|
2643 |
10354 | 2644 if (gtkblist->drag_timeout) { |
2645 g_source_remove(gtkblist->drag_timeout); | |
2646 gtkblist->drag_timeout = 0; | |
2647 } | |
2648 | |
8254 | 2649 gaim_gtk_blist_tooltip_destroy(); |
7720 | 2650 |
8470
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
2651 if (gtkblist->mouseover_contact && |
9811 | 2652 !((e->x > gtkblist->contact_rect.x) && (e->x < (gtkblist->contact_rect.x + gtkblist->contact_rect.width)) && |
2653 (e->y > gtkblist->contact_rect.y) && (e->y < (gtkblist->contact_rect.y + gtkblist->contact_rect.height)))) { | |
2654 gaim_gtk_blist_collapse_contact_cb(NULL, gtkblist->mouseover_contact); | |
7636 | 2655 gtkblist->mouseover_contact = NULL; |
2656 } | |
5228 | 2657 } |
2658 | |
2659 static void | |
2660 toggle_debug(void) | |
2661 { | |
7620 | 2662 gaim_prefs_set_bool("/gaim/gtk/debug/enabled", |
2663 !gaim_prefs_get_bool("/gaim/gtk/debug/enabled")); | |
5228 | 2664 } |
2665 | |
2666 | |
2667 /*************************************************** | |
2668 * Crap * | |
2669 ***************************************************/ | |
2670 static GtkItemFactoryEntry blist_menu[] = | |
2671 { | |
2672 /* Buddies menu */ | |
2673 { N_("/_Buddies"), NULL, NULL, 0, "<Branch>" }, | |
9714 | 2674 { N_("/Buddies/New Instant _Message..."), "<CTL>M", gaim_gtkdialogs_im, 0, "<StockItem>", GAIM_STOCK_IM }, |
8940 | 2675 { N_("/Buddies/Join a _Chat..."), "<CTL>C", gaim_gtk_blist_joinchat_show, 0, "<StockItem>", GAIM_STOCK_CHAT }, |
9714 | 2676 { N_("/Buddies/Get User _Info..."), "<CTL>I", gaim_gtkdialogs_info, 0, "<StockItem>", GAIM_STOCK_INFO }, |
2677 { N_("/Buddies/View User _Log..."), "<CTL>L", gaim_gtkdialogs_log, 0, NULL }, | |
5228 | 2678 { "/Buddies/sep1", NULL, NULL, 0, "<Separator>" }, |
11025 | 2679 { N_("/Buddies/Show _Offline Buddies"), NULL, gaim_gtk_blist_edit_mode_cb, 1, "<CheckItem>"}, |
2680 { N_("/Buddies/Show _Empty Groups"), NULL, gaim_gtk_blist_show_empty_groups_cb, 1, "<CheckItem>"}, | |
7853 | 2681 { N_("/Buddies/_Add Buddy..."), "<CTL>B", gaim_gtk_blist_add_buddy_cb, 0, "<StockItem>", GTK_STOCK_ADD }, |
2682 { N_("/Buddies/Add C_hat..."), NULL, gaim_gtk_blist_add_chat_cb, 0, "<StockItem>", GTK_STOCK_ADD }, | |
2683 { N_("/Buddies/Add _Group..."), NULL, gaim_blist_request_add_group, 0, "<StockItem>", GTK_STOCK_ADD }, | |
5228 | 2684 { "/Buddies/sep2", NULL, NULL, 0, "<Separator>" }, |
7620 | 2685 { N_("/Buddies/_Quit"), "<CTL>Q", gaim_core_quit, 0, "<StockItem>", GTK_STOCK_QUIT }, |
5228 | 2686 |
8470
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
2687 /* Tools */ |
5228 | 2688 { N_("/_Tools"), NULL, NULL, 0, "<Branch>" }, |
2689 { N_("/Tools/Buddy _Pounce"), NULL, NULL, 0, "<Branch>" }, | |
8845 | 2690 { N_("/Tools/Account Ac_tions"), NULL, NULL, 0, "<Branch>" }, |
8986 | 2691 { N_("/Tools/Pl_ugin Actions"), NULL, NULL, 0, "<Branch>" }, |
5228 | 2692 { "/Tools/sep1", NULL, NULL, 0, "<Separator>" }, |
10325 | 2693 { N_("/Tools/_Statuses"), NULL, gaim_gtk_status_window_show, 0, "<StockItem>", GAIM_STOCK_ICON_AWAY }, |
7620 | 2694 { N_("/Tools/A_ccounts"), "<CTL>A", gaim_gtk_accounts_window_show, 0, "<StockItem>", GAIM_STOCK_ACCOUNTS }, |
10325 | 2695 { N_("/Tools/Pr_eferences"), "<CTL>P", gaim_gtk_prefs_show, 0, "<StockItem>", GTK_STOCK_PREFERENCES }, |
10694 | 2696 { N_("/Tools/Pr_ivacy"), NULL, gaim_gtk_privacy_dialog_show, 0, "<StockItem>", GTK_STOCK_DIALOG_ERROR }, |
10019
8cc6f0bfa215
[gaim-migrate @ 10943]
Luke Schierer <lschiere@pidgin.im>
parents:
10018
diff
changeset
|
2697 { N_("/Tools/_File Transfers"), "<CTL>T", gaim_show_xfer_dialog, 0, "<StockItem>", GAIM_STOCK_FILE_TRANSFER }, |
10694 | 2698 { N_("/Tools/R_oom List"), NULL, gaim_gtk_roomlist_dialog_show, 0, "<StockItem>", GTK_STOCK_INDEX }, |
10325 | 2699 { "/Tools/sep2", NULL, NULL, 0, "<Separator>" }, |
10074 | 2700 { N_("/Tools/Mute _Sounds"), "<CTL>S", gaim_gtk_blist_mute_sounds_cb, 0, "<CheckItem>"}, |
7620 | 2701 { N_("/Tools/View System _Log"), NULL, gtk_blist_show_systemlog_cb, 0, NULL }, |
5228 | 2702 |
2703 /* Help */ | |
2704 { N_("/_Help"), NULL, NULL, 0, "<Branch>" }, | |
2705 { N_("/Help/Online _Help"), "F1", gtk_blist_show_onlinehelp_cb, 0, "<StockItem>", GTK_STOCK_HELP }, | |
7620 | 2706 { N_("/Help/_Debug Window"), NULL, toggle_debug, 0, NULL }, |
9753 | 2707 { N_("/Help/_About"), NULL, gaim_gtkdialogs_about, 0, "<StockItem>", GAIM_STOCK_ABOUT }, |
5228 | 2708 }; |
2709 | |
2710 /********************************************************* | |
2711 * Private Utility functions * | |
2712 *********************************************************/ | |
2713 | |
5234 | 2714 static char *gaim_get_tooltip_text(GaimBlistNode *node) |
5228 | 2715 { |
10475 | 2716 GString *str = g_string_new(""); |
5237 | 2717 GaimPlugin *prpl; |
2718 GaimPluginProtocolInfo *prpl_info = NULL; | |
10475 | 2719 char *tmp; |
2720 | |
2721 if (GAIM_BLIST_NODE_IS_CHAT(node)) | |
2722 { | |
2723 GaimChat *chat; | |
2724 GList *cur; | |
5274 | 2725 struct proto_chat_entry *pce; |
10475 | 2726 char *name, *value; |
2727 | |
2728 chat = (GaimChat *)node; | |
7956 | 2729 prpl = gaim_find_prpl(gaim_account_get_protocol_id(chat->account)); |
5274 | 2730 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl); |
2731 | |
10475 | 2732 tmp = g_markup_escape_text(gaim_chat_get_name(chat), -1); |
2733 g_string_append_printf(str, "<span size='larger' weight='bold'>%s</span>", tmp); | |
2734 g_free(tmp); | |
2735 | |
2736 if (g_list_length(gaim_connections_get_all()) > 1) | |
2737 { | |
2738 tmp = g_markup_escape_text(chat->account->username, -1); | |
2739 g_string_append_printf(str, _("\n<b>Account:</b> %s"), tmp); | |
2740 g_free(tmp); | |
2741 } | |
2742 | |
9959 | 2743 if (prpl_info->chat_info != NULL) |
10475 | 2744 cur = prpl_info->chat_info(chat->account->gc); |
2745 else | |
2746 cur = NULL; | |
2747 | |
2748 while (cur != NULL) | |
2749 { | |
2750 pce = cur->data; | |
2751 | |
2752 if (!pce->secret && (!pce->required && | |
2753 g_hash_table_lookup(chat->components, pce->identifier) == NULL)) | |
2754 { | |
2755 tmp = gaim_text_strip_mnemonic(pce->label); | |
2756 name = g_markup_escape_text(tmp, -1); | |
2757 g_free(tmp); | |
2758 value = g_markup_escape_text(g_hash_table_lookup( | |
2759 chat->components, pce->identifier), -1); | |
10924
7a82d86ab44a
[gaim-migrate @ 12695]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10918
diff
changeset
|
2760 g_string_append_printf(str, "\n<b>%s</b> %s", |
7a82d86ab44a
[gaim-migrate @ 12695]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10918
diff
changeset
|
2761 name ? name : "", |
7a82d86ab44a
[gaim-migrate @ 12695]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10918
diff
changeset
|
2762 value ? value : ""); |
10475 | 2763 g_free(name); |
8020 | 2764 g_free(value); |
2765 } | |
10475 | 2766 |
5274 | 2767 g_free(pce); |
10475 | 2768 cur = g_list_remove(cur, pce); |
5274 | 2769 } |
10475 | 2770 } |
2771 else if (GAIM_BLIST_NODE_IS_CONTACT(node) || GAIM_BLIST_NODE_IS_BUDDY(node)) | |
2772 { | |
2773 GaimContact *c; | |
7620 | 2774 GaimBuddy *b; |
9944 | 2775 GaimPresence *presence; |
10475 | 2776 char *tmp; |
9944 | 2777 gboolean idle; |
10567 | 2778 time_t idle_secs, signon; |
10475 | 2779 |
2780 if (GAIM_BLIST_NODE_IS_CONTACT(node)) | |
2781 { | |
2782 c = (GaimContact *)node; | |
2783 b = gaim_contact_get_priority_buddy(c); | |
2784 } | |
2785 else | |
2786 { | |
7620 | 2787 b = (GaimBuddy *)node; |
10475 | 2788 c = gaim_buddy_get_contact(b); |
7620 | 2789 } |
2790 | |
7956 | 2791 prpl = gaim_find_prpl(gaim_account_get_protocol_id(b->account)); |
5234 | 2792 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl); |
2793 | |
10475 | 2794 presence = gaim_buddy_get_presence(b); |
2795 | |
2796 /* Buddy Name */ | |
2797 tmp = g_markup_escape_text(gaim_buddy_get_name(b), -1); | |
2798 g_string_append_printf(str, "<span size='larger' weight='bold'>%s</span>", tmp); | |
2799 g_free(tmp); | |
2800 | |
2801 /* Account */ | |
2802 if (g_list_length(gaim_connections_get_all()) > 1) | |
2803 { | |
2804 tmp = g_markup_escape_text(gaim_account_get_username( | |
2805 gaim_buddy_get_account(b)), -1); | |
2806 g_string_append_printf(str, _("\n<b>Account:</b> %s"), tmp); | |
2807 g_free(tmp); | |
2808 } | |
2809 | |
2810 /* Contact Alias */ | |
2811 if (GAIM_BLIST_NODE_IS_CONTACT(node) && | |
10499 | 2812 (c->alias != NULL)) |
10475 | 2813 { |
10499 | 2814 tmp = g_markup_escape_text(c->alias, -1); |
10475 | 2815 g_string_append_printf(str, _("\n<b>Contact Alias:</b> %s"), tmp); |
2816 g_free(tmp); | |
2817 } | |
2818 | |
2819 /* Alias */ | |
2820 if ((b->alias != NULL) && (b->alias[0] != '\0')) | |
2821 { | |
2822 tmp = g_markup_escape_text(b->alias, -1); | |
2823 g_string_append_printf(str, _("\n<b>Alias:</b> %s"), tmp); | |
2824 g_free(tmp); | |
2825 } | |
2826 | |
2827 /* Nickname/Server Alias */ | |
2828 if (b->server_alias != NULL) | |
2829 { | |
2830 tmp = g_markup_escape_text(b->server_alias, -1); | |
2831 g_string_append_printf(str, _("\n<b>Nickname:</b> %s"), tmp); | |
2832 g_free(tmp); | |
2833 } | |
2834 | |
2835 /* Logged In */ | |
10567 | 2836 signon = gaim_presence_get_login_time(presence); |
10992
2bda44d66641
[gaim-migrate @ 12830]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10968
diff
changeset
|
2837 if (GAIM_BUDDY_IS_ONLINE(b) && signon > 0) |
10475 | 2838 { |
10567 | 2839 tmp = gaim_str_seconds_to_string(time(NULL) - signon); |
10475 | 2840 g_string_append_printf(str, _("\n<b>Logged In:</b> %s"), tmp); |
2841 g_free(tmp); | |
2842 } | |
2843 | |
2844 /* Idle */ | |
2845 idle = gaim_presence_is_idle(presence); | |
2846 if (idle) | |
2847 { | |
2848 idle_secs = gaim_presence_get_idle_time(presence); | |
2849 if (idle_secs > 0) | |
2850 { | |
2851 tmp = gaim_str_seconds_to_string(time(NULL) - idle_secs); | |
2852 g_string_append_printf(str, _("\n<b>Idle:</b> %s"), tmp); | |
2853 g_free(tmp); | |
2854 } | |
2855 } | |
2856 | |
2857 /* Last Seen */ | |
11437
1c20849fc716
[gaim-migrate @ 13674]
Richard Laager <rlaager@wiktel.com>
parents:
11436
diff
changeset
|
2858 if ((!GAIM_BUDDY_IS_ONLINE(b) && b->present != GAIM_BUDDY_SIGNING_OFF) || |
1c20849fc716
[gaim-migrate @ 13674]
Richard Laager <rlaager@wiktel.com>
parents:
11436
diff
changeset
|
2859 b->present == GAIM_BUDDY_SIGNING_ON) |
10475 | 2860 { |
11023 | 2861 struct _gaim_gtk_blist_node *gtknode = ((GaimBlistNode *)c)->ui_data; |
2862 GaimBlistNode *bnode; | |
2863 int lastseen = 0; | |
2864 | |
2865 if (!gtknode->contact_expanded || GAIM_BLIST_NODE_IS_CONTACT(node)) | |
2866 { | |
11437
1c20849fc716
[gaim-migrate @ 13674]
Richard Laager <rlaager@wiktel.com>
parents:
11436
diff
changeset
|
2867 /* We're either looking at a buddy for a collapsed contact or |
11438
5451fe2d89c0
[gaim-migrate @ 13675]
Richard Laager <rlaager@wiktel.com>
parents:
11437
diff
changeset
|
2868 * an expanded contact itself so we show the most recent |
11023 | 2869 * (largest) last_seen time for any of the buddies under |
2870 * the contact. */ | |
2871 for (bnode = ((GaimBlistNode *)c)->child ; bnode != NULL ; bnode = bnode->next) | |
2872 { | |
2873 int value = gaim_blist_node_get_int(bnode, "last_seen"); | |
2874 if (value > lastseen) | |
2875 lastseen = value; | |
2876 } | |
2877 } | |
2878 else | |
2879 { | |
2880 /* We're dealing with a buddy under an expanded contact, | |
2881 * so we show the last_seen time for the buddy. */ | |
2882 lastseen = gaim_blist_node_get_int(&b->node, "last_seen"); | |
2883 } | |
2884 | |
10475 | 2885 if (lastseen > 0) |
2886 { | |
2887 tmp = gaim_str_seconds_to_string(time(NULL) - lastseen); | |
2888 g_string_append_printf(str, _("\n<b>Last Seen:</b> %s ago"), tmp); | |
2889 g_free(tmp); | |
5234 | 2890 } |
2891 } | |
2892 | |
10475 | 2893 |
2894 /* Offline? */ | |
2895 if (!GAIM_BUDDY_IS_ONLINE(b)) { | |
2896 g_string_append_printf(str, _("\n<b>Status:</b> Offline")); | |
2897 } | |
10992
2bda44d66641
[gaim-migrate @ 12830]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10968
diff
changeset
|
2898 |
2bda44d66641
[gaim-migrate @ 12830]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10968
diff
changeset
|
2899 if (prpl_info && prpl_info->tooltip_text) |
10475 | 2900 { |
2901 /* Additional text from the PRPL */ | |
2902 const char *end; | |
2903 tmp = prpl_info->tooltip_text(b); | |
2904 | |
2905 if (tmp && !g_utf8_validate(tmp, -1, &end)) | |
2906 { | |
2907 char *new = g_strndup(tmp, g_utf8_pointer_to_offset(tmp, end)); | |
2908 g_free(tmp); | |
2909 tmp = new; | |
2910 } | |
2911 | |
11634 | 2912 if (tmp != NULL) |
2913 g_string_append(str, tmp); | |
10476 | 2914 g_free(tmp); |
10475 | 2915 } |
2916 | |
2917 /* These are Easter Eggs. Patches to remove them will be rejected. */ | |
2918 if (!g_ascii_strcasecmp(b->name, "robflynn")) | |
2919 g_string_append(str, _("\n<b>Description:</b> Spooky")); | |
2920 if (!g_ascii_strcasecmp(b->name, "seanegn")) | |
2921 g_string_append(str, _("\n<b>Status:</b> Awesome")); | |
2922 if (!g_ascii_strcasecmp(b->name, "chipx86")) | |
2923 g_string_append(str, _("\n<b>Status:</b> Rockin'")); | |
5234 | 2924 } |
10475 | 2925 |
8824 | 2926 gaim_signal_emit(gaim_gtk_blist_get_handle(), |
10477 | 2927 "drawing-tooltip", node, str); |
10475 | 2928 |
2929 return g_string_free(str, FALSE); | |
5228 | 2930 } |
2931 | |
7620 | 2932 struct _emblem_data { |
9954 | 2933 const char *filename; |
7620 | 2934 int x; |
2935 int y; | |
2936 }; | |
2937 | |
9944 | 2938 GdkPixbuf * |
2939 gaim_gtk_blist_get_status_icon(GaimBlistNode *node, GaimStatusIconSize size) | |
5228 | 2940 { |
7620 | 2941 GdkPixbuf *scale, *status = NULL; |
2942 int i, scalesize = 30; | |
2943 char *filename; | |
5228 | 2944 const char *protoname = NULL; |
7620 | 2945 struct _gaim_gtk_blist_node *gtknode = node->ui_data; |
2946 struct _emblem_data emblems[4] = {{NULL, 15, 15}, {NULL, 0, 15}, | |
2947 {NULL, 0, 0}, {NULL, 15, 0}}; | |
9944 | 2948 GaimPresence *presence = NULL; |
7620 | 2949 GaimBuddy *buddy = NULL; |
2950 GaimChat *chat = NULL; | |
2951 | |
2952 if(GAIM_BLIST_NODE_IS_CONTACT(node)) { | |
2953 if(!gtknode->contact_expanded) | |
2954 buddy = gaim_contact_get_priority_buddy((GaimContact*)node); | |
2955 } else if(GAIM_BLIST_NODE_IS_BUDDY(node)) { | |
2956 buddy = (GaimBuddy*)node; | |
2957 } else if(GAIM_BLIST_NODE_IS_CHAT(node)) { | |
2958 chat = (GaimChat*)node; | |
2959 } else { | |
5228 | 2960 return NULL; |
5234 | 2961 } |
2962 | |
7620 | 2963 if(buddy || chat) { |
2964 GaimAccount *account; | |
2965 GaimPlugin *prpl; | |
2966 GaimPluginProtocolInfo *prpl_info; | |
2967 | |
2968 if(buddy) | |
2969 account = buddy->account; | |
2970 else | |
2971 account = chat->account; | |
2972 | |
7956 | 2973 prpl = gaim_find_prpl(gaim_account_get_protocol_id(account)); |
7620 | 2974 if(!prpl) |
2975 return NULL; | |
2976 | |
2977 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl); | |
2978 | |
2979 if(prpl_info && prpl_info->list_icon) { | |
2980 protoname = prpl_info->list_icon(account, buddy); | |
2981 } | |
2982 if(prpl_info && prpl_info->list_emblems && buddy) { | |
2983 if(buddy->present != GAIM_BUDDY_SIGNING_OFF) | |
2984 prpl_info->list_emblems(buddy, &emblems[0].filename, | |
2985 &emblems[1].filename, &emblems[2].filename, | |
2986 &emblems[3].filename); | |
2987 } | |
5234 | 2988 } |
5228 | 2989 |
7620 | 2990 if(size == GAIM_STATUS_ICON_SMALL) { |
5228 | 2991 scalesize = 15; |
7620 | 2992 /* So that only the se icon will composite */ |
2993 emblems[1].filename = emblems[2].filename = emblems[3].filename = NULL; | |
5228 | 2994 } |
2995 | |
7620 | 2996 if(buddy && buddy->present == GAIM_BUDDY_SIGNING_ON) { |
2997 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "login.png", NULL); | |
2998 } else if(buddy && buddy->present == GAIM_BUDDY_SIGNING_OFF) { | |
2999 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "logout.png", NULL); | |
3000 } else if(buddy || chat) { | |
5228 | 3001 char *image = g_strdup_printf("%s.png", protoname); |
3002 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", image, NULL); | |
3003 g_free(image); | |
7620 | 3004 } else { |
3005 /* gaim dude */ | |
3006 filename = g_build_filename(DATADIR, "pixmaps", "gaim.png", NULL); | |
5228 | 3007 } |
7620 | 3008 |
3009 status = gdk_pixbuf_new_from_file(filename, NULL); | |
3010 g_free(filename); | |
3011 | |
3012 if(!status) | |
3013 return NULL; | |
3014 | |
3015 scale = gdk_pixbuf_scale_simple(status, scalesize, scalesize, | |
3016 GDK_INTERP_BILINEAR); | |
3017 g_object_unref(status); | |
3018 | |
3019 for(i=0; i<4; i++) { | |
3020 if(emblems[i].filename) { | |
3021 GdkPixbuf *emblem; | |
3022 char *image = g_strdup_printf("%s.png", emblems[i].filename); | |
3023 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", image, NULL); | |
3024 g_free(image); | |
3025 emblem = gdk_pixbuf_new_from_file(filename, NULL); | |
3026 g_free(filename); | |
3027 if(emblem) { | |
3028 if(i == 0 && size == GAIM_STATUS_ICON_SMALL) { | |
3029 gdk_pixbuf_composite(emblem, | |
3030 scale, 5, 5, | |
3031 10, 10, | |
3032 5, 5, | |
3033 .6, .6, | |
3034 GDK_INTERP_BILINEAR, | |
3035 255); | |
3036 } else { | |
3037 gdk_pixbuf_composite(emblem, | |
3038 scale, emblems[i].x, emblems[i].y, | |
3039 15, 15, | |
3040 emblems[i].x, emblems[i].y, | |
3041 1, 1, | |
3042 GDK_INTERP_BILINEAR, | |
3043 255); | |
3044 } | |
3045 g_object_unref(emblem); | |
3046 } | |
5228 | 3047 } |
3048 } | |
7620 | 3049 |
3050 if(buddy) { | |
9944 | 3051 presence = gaim_buddy_get_presence(buddy); |
3052 | |
3053 if (!GAIM_BUDDY_IS_ONLINE(buddy)) | |
7620 | 3054 gdk_pixbuf_saturate_and_pixelate(scale, scale, 0.0, FALSE); |
10118 | 3055 else if (gaim_presence_is_idle(presence)) |
9944 | 3056 { |
7620 | 3057 gdk_pixbuf_saturate_and_pixelate(scale, scale, 0.25, FALSE); |
9944 | 3058 } |
11111
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
3059 |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
3060 if (!gaim_privacy_check(buddy->account, gaim_buddy_get_name(buddy))) |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
3061 { |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
3062 GdkPixbuf *emblem; |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
3063 char *filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "blocked.png", NULL); |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
3064 |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
3065 emblem = gdk_pixbuf_new_from_file(filename, NULL); |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
3066 g_free(filename); |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
3067 |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
3068 if (emblem) |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
3069 { |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
3070 gdk_pixbuf_composite(emblem, scale, |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
3071 0, 0, scalesize, scalesize, |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
3072 0, 0, |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
3073 (double)scalesize / gdk_pixbuf_get_width(emblem), |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
3074 (double)scalesize / gdk_pixbuf_get_height(emblem), |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
3075 GDK_INTERP_BILINEAR, |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
3076 224); |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
3077 g_object_unref(emblem); |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
3078 } |
f03dce7ea408
[gaim-migrate @ 13163]
Richard Laager <rlaager@wiktel.com>
parents:
11059
diff
changeset
|
3079 } |
5228 | 3080 } |
7620 | 3081 |
5228 | 3082 return scale; |
3083 } | |
3084 | |
7620 | 3085 static gchar *gaim_gtk_blist_get_name_markup(GaimBuddy *b, gboolean selected) |
5228 | 3086 { |
7620 | 3087 const char *name; |
3088 char *esc, *text = NULL; | |
5228 | 3089 GaimPlugin *prpl; |
3090 GaimPluginProtocolInfo *prpl_info = NULL; | |
7620 | 3091 GaimContact *contact; |
9944 | 3092 GaimPresence *presence; |
7620 | 3093 struct _gaim_gtk_blist_node *gtkcontactnode = NULL; |
11257 | 3094 char *idletime = NULL, *statustext = NULL; |
5228 | 3095 time_t t; |
7620 | 3096 /* XXX Clean up this crap */ |
3097 | |
3098 contact = (GaimContact*)((GaimBlistNode*)b)->parent; | |
3099 if(contact) | |
3100 gtkcontactnode = ((GaimBlistNode*)contact)->ui_data; | |
3101 | |
3102 if(gtkcontactnode && !gtkcontactnode->contact_expanded && contact->alias) | |
3103 name = contact->alias; | |
3104 else | |
9620 | 3105 name = gaim_buddy_get_alias(b); |
7620 | 3106 esc = g_markup_escape_text(name, strlen(name)); |
3107 | |
7956 | 3108 prpl = gaim_find_prpl(gaim_account_get_protocol_id(b->account)); |
5228 | 3109 |
3110 if (prpl != NULL) | |
3111 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl); | |
3112 | |
9944 | 3113 presence = gaim_buddy_get_presence(b); |
3114 | |
7620 | 3115 if (!gaim_prefs_get_bool("/gaim/gtk/blist/show_buddy_icons")) { |
9944 | 3116 |
10118 | 3117 if ((gaim_presence_is_idle(presence) || !GAIM_BUDDY_IS_ONLINE(b)) && !selected) |
9944 | 3118 { |
10118 | 3119 text = g_strdup_printf("<span color='%s'>%s</span>", |
3120 dim_grey(), esc); | |
5228 | 3121 g_free(esc); |
3122 return text; | |
7620 | 3123 } |
9944 | 3124 else |
5228 | 3125 return esc; |
3126 } | |
3127 | |
8122
36674144c510
[gaim-migrate @ 8826]
Christian Hammond <chipx86@chipx86.com>
parents:
8113
diff
changeset
|
3128 if (prpl_info && prpl_info->status_text && b->account->gc) { |
5228 | 3129 char *tmp = prpl_info->status_text(b); |
3130 const char *end; | |
3131 | |
3132 if(tmp && !g_utf8_validate(tmp, -1, &end)) { | |
3133 char *new = g_strndup(tmp, | |
3134 g_utf8_pointer_to_offset(tmp, end)); | |
3135 g_free(tmp); | |
3136 tmp = new; | |
3137 } | |
3138 | |
10288 | 3139 #if !GTK_CHECK_VERSION(2,6,0) |
5228 | 3140 if(tmp) { |
3141 char buf[32]; | |
3142 char *c = tmp; | |
3143 int length = 0, vis=0; | |
3144 gboolean inside = FALSE; | |
3145 g_strdelimit(tmp, "\n", ' '); | |
7620 | 3146 gaim_str_strip_cr(tmp); |
5228 | 3147 |
3148 while(*c && vis < 20) { | |
3149 if(*c == '&') | |
3150 inside = TRUE; | |
3151 else if(*c == ';') | |
3152 inside = FALSE; | |
3153 if(!inside) | |
3154 vis++; | |
7620 | 3155 c = g_utf8_next_char(c); /* this is fun */ |
5228 | 3156 } |
3157 | |
7620 | 3158 length = c - tmp; |
3159 | |
5228 | 3160 if(vis == 20) |
3161 g_snprintf(buf, sizeof(buf), "%%.%ds...", length); | |
3162 else | |
3163 g_snprintf(buf, sizeof(buf), "%%s "); | |
3164 | |
3165 statustext = g_strdup_printf(buf, tmp); | |
3166 | |
3167 g_free(tmp); | |
3168 } | |
10288 | 3169 #else |
3170 statustext = tmp; | |
3171 #endif | |
5228 | 3172 } |
3173 | |
10351 | 3174 if (gaim_presence_is_idle(presence)) { |
9944 | 3175 time_t idle_secs = gaim_presence_get_idle_time(presence); |
3176 | |
10351 | 3177 if (idle_secs > 0) { |
9944 | 3178 int ihrs, imin; |
3179 | |
3180 time(&t); | |
3181 ihrs = (t - idle_secs) / 3600; | |
3182 imin = ((t - idle_secs) / 60) % 60; | |
3183 | |
3184 if (ihrs) | |
11134
f78e7e982cf4
[gaim-migrate @ 13195]
Richard Laager <rlaager@wiktel.com>
parents:
11111
diff
changeset
|
3185 idletime = g_strdup_printf(_("Idle (%dh %02dm) "), ihrs, imin); |
9944 | 3186 else |
3187 idletime = g_strdup_printf(_("Idle (%dm) "), imin); | |
3188 } | |
5228 | 3189 else |
9944 | 3190 idletime = g_strdup(_("Idle ")); |
5228 | 3191 } |
3192 | |
3193 if(!GAIM_BUDDY_IS_ONLINE(b) && !statustext) | |
7620 | 3194 statustext = g_strdup(_("Offline ")); |
3195 | |
10118 | 3196 if (gaim_presence_is_idle(presence) && !selected) { |
3197 text = g_strdup_printf("<span color='%s'>%s</span>\n" | |
11257 | 3198 "<span color='%s' size='smaller'>%s%s%s</span>", |
10118 | 3199 dim_grey(), esc, dim_grey(), |
5228 | 3200 statustext != NULL ? statustext : "", |
11134
f78e7e982cf4
[gaim-migrate @ 13195]
Richard Laager <rlaager@wiktel.com>
parents:
11111
diff
changeset
|
3201 (idletime != NULL && statustext != NULL) ? " - " : "", |
11257 | 3202 idletime != NULL ? idletime : ""); |
3203 } else if (statustext == NULL && idletime == NULL && GAIM_BUDDY_IS_ONLINE(b)) { | |
5228 | 3204 text = g_strdup(esc); |
3205 } else { | |
10118 | 3206 if (selected) |
3207 text = g_strdup_printf("%s\n" | |
11257 | 3208 "<span size='smaller'>%s%s%s</span>", esc, |
10118 | 3209 statustext != NULL ? statustext : "", |
11134
f78e7e982cf4
[gaim-migrate @ 13195]
Richard Laager <rlaager@wiktel.com>
parents:
11111
diff
changeset
|
3210 (idletime != NULL && statustext != NULL) ? " - " : "", |
11257 | 3211 idletime != NULL ? idletime : ""); |
10118 | 3212 else |
3213 text = g_strdup_printf("%s\n" | |
11257 | 3214 "<span color='%s' size='smaller'>%s%s%s</span>", esc, |
10144 | 3215 dim_grey(), |
10118 | 3216 statustext != NULL ? statustext : "", |
11134
f78e7e982cf4
[gaim-migrate @ 13195]
Richard Laager <rlaager@wiktel.com>
parents:
11111
diff
changeset
|
3217 (idletime != NULL && statustext != NULL) ? " - " : "", |
11257 | 3218 idletime != NULL ? idletime : ""); |
5228 | 3219 } |
3220 if (idletime) | |
3221 g_free(idletime); | |
3222 if (statustext) | |
3223 g_free(statustext); | |
3224 if (esc) | |
3225 g_free(esc); | |
3226 | |
3227 return text; | |
3228 } | |
3229 | |
3230 static void gaim_gtk_blist_restore_position() | |
3231 { | |
7620 | 3232 int blist_x, blist_y, blist_width, blist_height; |
3233 | |
3234 blist_width = gaim_prefs_get_int("/gaim/gtk/blist/width"); | |
3235 | |
3236 /* if the window exists, is hidden, we're saving positions, and the | |
3237 * position is sane... */ | |
3238 if (gtkblist && gtkblist->window && | |
3239 !GTK_WIDGET_VISIBLE(gtkblist->window) && blist_width != 0) { | |
3240 | |
3241 blist_x = gaim_prefs_get_int("/gaim/gtk/blist/x"); | |
3242 blist_y = gaim_prefs_get_int("/gaim/gtk/blist/y"); | |
3243 blist_height = gaim_prefs_get_int("/gaim/gtk/blist/height"); | |
3244 | |
5228 | 3245 /* ...check position is on screen... */ |
7620 | 3246 if (blist_x >= gdk_screen_width()) |
3247 blist_x = gdk_screen_width() - 100; | |
3248 else if (blist_x + blist_width < 0) | |
3249 blist_x = 100; | |
3250 | |
3251 if (blist_y >= gdk_screen_height()) | |
3252 blist_y = gdk_screen_height() - 100; | |
3253 else if (blist_y + blist_height < 0) | |
3254 blist_y = 100; | |
3255 | |
5228 | 3256 /* ...and move it back. */ |
7620 | 3257 gtk_window_move(GTK_WINDOW(gtkblist->window), blist_x, blist_y); |
3258 gtk_window_resize(GTK_WINDOW(gtkblist->window), blist_width, blist_height); | |
5228 | 3259 } |
3260 } | |
3261 | |
7620 | 3262 static gboolean gaim_gtk_blist_refresh_timer(GaimBuddyList *list) |
5228 | 3263 { |
7620 | 3264 GaimBlistNode *gnode, *cnode; |
3265 | |
3266 for(gnode = list->root; gnode; gnode = gnode->next) { | |
3267 if(!GAIM_BLIST_NODE_IS_GROUP(gnode)) | |
5234 | 3268 continue; |
7620 | 3269 for(cnode = gnode->child; cnode; cnode = cnode->next) { |
3270 if(GAIM_BLIST_NODE_IS_CONTACT(cnode)) { | |
9944 | 3271 GaimBuddy *buddy; |
3272 | |
3273 buddy = gaim_contact_get_priority_buddy((GaimContact*)cnode); | |
10012 | 3274 |
3275 if (buddy && | |
3276 gaim_presence_is_idle(gaim_buddy_get_presence(buddy))) | |
9944 | 3277 gaim_gtk_blist_update(list, cnode); |
7620 | 3278 } |
5228 | 3279 } |
3280 } | |
3281 | |
3282 /* keep on going */ | |
3283 return TRUE; | |
3284 } | |
3285 | |
7620 | 3286 static void gaim_gtk_blist_hide_node(GaimBuddyList *list, GaimBlistNode *node) |
5260 | 3287 { |
3288 struct _gaim_gtk_blist_node *gtknode = (struct _gaim_gtk_blist_node *)node->ui_data; | |
3289 GtkTreeIter iter; | |
3290 | |
3291 if (!gtknode || !gtknode->row || !gtkblist) | |
3292 return; | |
3293 | |
3294 if(gtkblist->selected_node == node) | |
3295 gtkblist->selected_node = NULL; | |
3296 | |
3297 if (get_iter_from_node(node, &iter)) { | |
3298 gtk_tree_store_remove(gtkblist->treemodel, &iter); | |
7620 | 3299 if(GAIM_BLIST_NODE_IS_CONTACT(node) || GAIM_BLIST_NODE_IS_BUDDY(node) |
3300 || GAIM_BLIST_NODE_IS_CHAT(node)) { | |
5260 | 3301 gaim_gtk_blist_update(list, node->parent); |
3302 } | |
3303 } | |
3304 gtk_tree_row_reference_free(gtknode->row); | |
3305 gtknode->row = NULL; | |
3306 } | |
3307 | |
10352 | 3308 static const char *require_connection[] = |
7620 | 3309 { |
10352 | 3310 N_("/Buddies/New Instant Message..."), |
3311 N_("/Buddies/Join a Chat..."), | |
3312 N_("/Buddies/Get User Info..."), | |
3313 N_("/Buddies/Add Buddy..."), | |
3314 N_("/Buddies/Add Chat..."), | |
3315 N_("/Buddies/Add Group..."), | |
3316 }; | |
3317 | |
10357 | 3318 static const int require_connection_size = sizeof(require_connection) |
3319 / sizeof(*require_connection); | |
10352 | 3320 |
3321 /** | |
3322 * Rebuild dynamic menus and make menu items sensitive/insensitive | |
3323 * where appropriate. | |
3324 */ | |
3325 static void | |
3326 update_menu_bar(GaimGtkBuddyList *gtkblist) | |
3327 { | |
8937 | 3328 GtkWidget *widget; |
10352 | 3329 gboolean sensitive; |
3330 int i; | |
3331 | |
3332 g_return_if_fail(gtkblist != NULL); | |
8259
4f9f68ab8770
[gaim-migrate @ 8982]
Christian Hammond <chipx86@chipx86.com>
parents:
8254
diff
changeset
|
3333 |
7620 | 3334 gaim_gtk_blist_update_protocol_actions(); |
8235 | 3335 gaim_gtkpounce_menu_build(gtkblist->bpmenu); |
8937 | 3336 |
10352 | 3337 sensitive = (gaim_connections_get_all() != NULL); |
3338 | |
10357 | 3339 for (i = 0; i < require_connection_size; i++) |
10352 | 3340 { |
3341 widget = gtk_item_factory_get_widget(gtkblist->ift, require_connection[i]); | |
3342 gtk_widget_set_sensitive(widget, sensitive); | |
3343 } | |
3344 | |
8940 | 3345 widget = gtk_item_factory_get_widget(gtkblist->ift, N_("/Buddies/Join a Chat...")); |
3346 gtk_widget_set_sensitive(widget, gaim_gtk_blist_joinchat_is_showable()); | |
3347 | |
8937 | 3348 widget = gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Room List")); |
8939 | 3349 gtk_widget_set_sensitive(widget, gaim_gtk_roomlist_is_showable()); |
8938 | 3350 |
3351 widget = gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Privacy")); | |
3352 gtk_widget_set_sensitive(widget, gaim_gtk_privacy_is_showable()); | |
7620 | 3353 } |
3354 | |
10352 | 3355 static void |
3356 sign_on_off_cb(GaimConnection *gc, GaimBuddyList *blist) | |
3357 { | |
3358 GaimGtkBuddyList *gtkblist = GAIM_GTK_BLIST(blist); | |
3359 | |
3360 update_menu_bar(gtkblist); | |
3361 } | |
8986 | 3362 |
3363 static void | |
3364 plugin_changed_cb(GaimPlugin *p, gpointer *data) | |
3365 { | |
3366 gaim_gtk_blist_update_plugin_actions(); | |
3367 } | |
3368 | |
5228 | 3369 /********************************************************************************** |
3370 * Public API Functions * | |
3371 **********************************************************************************/ | |
9774 | 3372 |
7620 | 3373 static void gaim_gtk_blist_new_list(GaimBuddyList *blist) |
5228 | 3374 { |
7620 | 3375 GaimGtkBuddyList *gtkblist; |
3376 | |
3377 gtkblist = g_new0(GaimGtkBuddyList, 1); | |
3378 blist->ui_data = gtkblist; | |
5228 | 3379 } |
3380 | |
5256 | 3381 static void gaim_gtk_blist_new_node(GaimBlistNode *node) |
3382 { | |
3383 node->ui_data = g_new0(struct _gaim_gtk_blist_node, 1); | |
3384 } | |
3385 | |
11018 | 3386 gboolean gaim_gtk_blist_node_is_contact_expanded(GaimBlistNode *node) |
3387 { | |
3388 if GAIM_BLIST_NODE_IS_BUDDY(node) | |
3389 node = node->parent; | |
3390 | |
3391 g_return_val_if_fail(GAIM_BLIST_NODE_IS_CONTACT(node), FALSE); | |
3392 | |
3393 return ((struct _gaim_gtk_blist_node *)node->ui_data)->contact_expanded; | |
3394 } | |
3395 | |
5228 | 3396 void gaim_gtk_blist_update_columns() |
3397 { | |
3398 if(!gtkblist) | |
3399 return; | |
3400 | |
7620 | 3401 if (gaim_prefs_get_bool("/gaim/gtk/blist/show_buddy_icons")) { |
5228 | 3402 gtk_tree_view_column_set_visible(gtkblist->buddy_icon_column, TRUE); |
3403 gtk_tree_view_column_set_visible(gtkblist->idle_column, FALSE); | |
3404 } else { | |
10351 | 3405 gtk_tree_view_column_set_visible(gtkblist->idle_column, TRUE); |
5228 | 3406 gtk_tree_view_column_set_visible(gtkblist->buddy_icon_column, FALSE); |
3407 } | |
3408 } | |
3409 | |
10433 | 3410 enum { |
3411 DRAG_BUDDY, | |
3412 DRAG_ROW, | |
3413 DRAG_VCARD, | |
3414 DRAG_TEXT, | |
3415 DRAG_URI, | |
3416 NUM_TARGETS | |
3417 }; | |
5228 | 3418 |
3419 static char * | |
3420 item_factory_translate_func (const char *path, gpointer func_data) | |
3421 { | |
7620 | 3422 return _((char *)path); |
5228 | 3423 } |
3424 | |
5422 | 3425 void gaim_gtk_blist_setup_sort_methods() |
3426 { | |
7620 | 3427 gaim_gtk_blist_sort_method_reg("none", _("None"), sort_method_none); |
3428 #if GTK_CHECK_VERSION(2,2,1) | |
3429 gaim_gtk_blist_sort_method_reg("alphabetical", _("Alphabetical"), sort_method_alphabetical); | |
3430 gaim_gtk_blist_sort_method_reg("status", _("By status"), sort_method_status); | |
3431 gaim_gtk_blist_sort_method_reg("log_size", _("By log size"), sort_method_log); | |
3432 #endif | |
3433 gaim_gtk_blist_sort_method_set(gaim_prefs_get_string("/gaim/gtk/blist/sort_type")); | |
3434 } | |
3435 | |
10433 | 3436 static void _prefs_change_redo_list() |
3437 { | |
7620 | 3438 redo_buddy_list(gaim_get_blist(), TRUE); |
3439 } | |
3440 | |
3441 static void _prefs_change_sort_method(const char *pref_name, GaimPrefType type, | |
10433 | 3442 gpointer val, gpointer data) |
3443 { | |
7620 | 3444 if(!strcmp(pref_name, "/gaim/gtk/blist/sort_type")) |
3445 gaim_gtk_blist_sort_method_set(val); | |
3446 } | |
3447 | |
10433 | 3448 /* |
3449 * "This is so dead sexy." | |
3450 * "Two thumbs up." | |
3451 * "Best movie of the year." | |
3452 * | |
3453 * This is the function that handles CTRL+F searching in the buddy list. | |
3454 * It finds the top-most buddy/group/chat/whatever containing the | |
3455 * entered string. | |
3456 * | |
3457 * It's somewhat ineffecient, because we strip all the HTML from the | |
3458 * "name" column of the buddy list (because the GtkTreeModel does not | |
3459 * contain the screen name in a non-markedup format). But the alternative | |
3460 * is to add an extra column to the GtkTreeModel. And this function is | |
3461 * used rarely, so it shouldn't matter TOO much. | |
3462 */ | |
3463 static gboolean | |
3464 _search_func(GtkTreeModel *model, gint column, const gchar *key, GtkTreeIter *iter, gpointer search_data) | |
3465 { | |
10435 | 3466 gboolean result; |
10433 | 3467 gchar *enteredstring; |
10439 | 3468 gchar *withmarkup; |
10433 | 3469 gchar *nomarkup; |
11490 | 3470 gchar *normalized; |
10435 | 3471 |
3472 gtk_tree_model_get(model, iter, column, &withmarkup, -1); | |
10433 | 3473 |
11490 | 3474 enteredstring = g_utf8_casefold(gaim_normalize(NULL, key), -1); |
10433 | 3475 nomarkup = gaim_markup_strip_html(withmarkup); |
11490 | 3476 normalized = g_utf8_casefold(gaim_normalize(NULL, nomarkup), -1); |
10433 | 3477 |
3478 result = (g_strstr_len(normalized, strlen(normalized), enteredstring) == NULL); | |
3479 | |
10439 | 3480 g_free(withmarkup); |
10433 | 3481 g_free(enteredstring); |
3482 g_free(nomarkup); | |
11490 | 3483 g_free(normalized); |
10433 | 3484 |
3485 return result; | |
3486 } | |
3487 | |
7620 | 3488 static void gaim_gtk_blist_show(GaimBuddyList *list) |
5228 | 3489 { |
10087 | 3490 void *handle; |
5228 | 3491 GtkCellRenderer *rend; |
3492 GtkTreeViewColumn *column; | |
10178
96a850ab30c8
[gaim-migrate @ 11293]
Christian Hammond <chipx86@chipx86.com>
parents:
10144
diff
changeset
|
3493 GtkWidget *menu; |
5228 | 3494 GtkWidget *sw; |
3495 GtkAccelGroup *accel_group; | |
3496 GtkTreeSelection *selection; | |
9556 | 3497 GtkTargetEntry dte[] = {{"GAIM_BLIST_NODE", GTK_TARGET_SAME_APP, DRAG_ROW}, |
8089 | 3498 {"application/x-im-contact", 0, DRAG_BUDDY}, |
9495 | 3499 {"text/x-vcard", 0, DRAG_VCARD }, |
9525 | 3500 {"text/uri-list", 0, DRAG_URI}, |
3501 {"text/plain", 0, DRAG_TEXT}}; | |
9556 | 3502 GtkTargetEntry ste[] = {{"GAIM_BLIST_NODE", GTK_TARGET_SAME_APP, DRAG_ROW}, |
3503 {"application/x-im-contact", 0, DRAG_BUDDY}, | |
3504 {"text/x-vcard", 0, DRAG_VCARD }}; | |
5228 | 3505 if (gtkblist && gtkblist->window) { |
10282 | 3506 if (gaim_prefs_get_bool("/gaim/gtk/blist/list_visible") || docklet_count == 0) |
3507 gtk_widget_show(gtkblist->window); | |
5228 | 3508 return; |
3509 } | |
3510 | |
3511 gtkblist = GAIM_GTK_BLIST(list); | |
3512 | |
3513 gtkblist->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | |
3514 gtk_window_set_role(GTK_WINDOW(gtkblist->window), "buddy_list"); | |
9746 | 3515 gtk_window_set_title(GTK_WINDOW(gtkblist->window), _("Buddy List")); |
5228 | 3516 |
3517 gtkblist->vbox = gtk_vbox_new(FALSE, 0); | |
10178
96a850ab30c8
[gaim-migrate @ 11293]
Christian Hammond <chipx86@chipx86.com>
parents:
10144
diff
changeset
|
3518 gtk_widget_show(gtkblist->vbox); |
5228 | 3519 gtk_container_add(GTK_CONTAINER(gtkblist->window), gtkblist->vbox); |
3520 | |
3521 g_signal_connect(G_OBJECT(gtkblist->window), "delete_event", G_CALLBACK(gtk_blist_delete_cb), NULL); | |
3522 g_signal_connect(G_OBJECT(gtkblist->window), "configure_event", G_CALLBACK(gtk_blist_configure_cb), NULL); | |
3523 g_signal_connect(G_OBJECT(gtkblist->window), "visibility_notify_event", G_CALLBACK(gtk_blist_visibility_cb), NULL); | |
3524 gtk_widget_add_events(gtkblist->window, GDK_VISIBILITY_NOTIFY_MASK); | |
3525 | |
3526 /******************************* Menu bar *************************************/ | |
3527 accel_group = gtk_accel_group_new(); | |
3528 gtk_window_add_accel_group(GTK_WINDOW (gtkblist->window), accel_group); | |
3529 g_object_unref(accel_group); | |
5427 | 3530 gtkblist->ift = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<GaimMain>", accel_group); |
9811 | 3531 gtk_item_factory_set_translate_func(gtkblist->ift, |
3532 item_factory_translate_func, | |
3533 NULL, NULL); | |
5427 | 3534 gtk_item_factory_create_items(gtkblist->ift, sizeof(blist_menu) / sizeof(*blist_menu), |
9811 | 3535 blist_menu, NULL); |
7620 | 3536 gaim_gtk_load_accels(); |
3537 g_signal_connect(G_OBJECT(accel_group), "accel-changed", | |
3538 G_CALLBACK(gaim_gtk_save_accels_cb), NULL); | |
10178
96a850ab30c8
[gaim-migrate @ 11293]
Christian Hammond <chipx86@chipx86.com>
parents:
10144
diff
changeset
|
3539 menu = gtk_item_factory_get_widget(gtkblist->ift, "<GaimMain>"); |
96a850ab30c8
[gaim-migrate @ 11293]
Christian Hammond <chipx86@chipx86.com>
parents:
10144
diff
changeset
|
3540 gtk_widget_show(menu); |
96a850ab30c8
[gaim-migrate @ 11293]
Christian Hammond <chipx86@chipx86.com>
parents:
10144
diff
changeset
|
3541 gtk_box_pack_start(GTK_BOX(gtkblist->vbox), menu, FALSE, FALSE, 0); |
5228 | 3542 |
5427 | 3543 gtkblist->bpmenu = gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Buddy Pounce")); |
8844 | 3544 protomenu = gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Account Actions")); |
8986 | 3545 pluginmenu = gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Plugin Actions")); |
10352 | 3546 |
5228 | 3547 /****************************** GtkTreeView **********************************/ |
3548 sw = gtk_scrolled_window_new(NULL,NULL); | |
10178
96a850ab30c8
[gaim-migrate @ 11293]
Christian Hammond <chipx86@chipx86.com>
parents:
10144
diff
changeset
|
3549 gtk_widget_show(sw); |
5228 | 3550 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_IN); |
3551 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); | |
3552 | |
7620 | 3553 gtkblist->treemodel = gtk_tree_store_new(BLIST_COLUMNS, |
11494 | 3554 GDK_TYPE_PIXBUF, G_TYPE_BOOLEAN, |
11257 | 3555 G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_POINTER); |
5228 | 3556 |
3557 gtkblist->treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(gtkblist->treemodel)); | |
10178
96a850ab30c8
[gaim-migrate @ 11293]
Christian Hammond <chipx86@chipx86.com>
parents:
10144
diff
changeset
|
3558 gtk_widget_show(gtkblist->treeview); |
9176 | 3559 gtk_widget_set_name(gtkblist->treeview, "gaim_gtkblist_treeview"); |
5228 | 3560 |
3561 /* Set up selection stuff */ | |
3562 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(gtkblist->treeview)); | |
3563 g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(gaim_gtk_blist_selection_changed), NULL); | |
3564 | |
3565 /* Set up dnd */ | |
7650 | 3566 gtk_tree_view_enable_model_drag_source(GTK_TREE_VIEW(gtkblist->treeview), |
9811 | 3567 GDK_BUTTON1_MASK, ste, 3, |
3568 GDK_ACTION_COPY); | |
7650 | 3569 gtk_tree_view_enable_model_drag_dest(GTK_TREE_VIEW(gtkblist->treeview), |
9811 | 3570 dte, 5, |
3571 GDK_ACTION_COPY | GDK_ACTION_MOVE); | |
7636 | 3572 |
10544 | 3573 g_signal_connect(G_OBJECT(gtkblist->treeview), "drag-data-received", G_CALLBACK(gaim_gtk_blist_drag_data_rcv_cb), NULL); |
5228 | 3574 g_signal_connect(G_OBJECT(gtkblist->treeview), "drag-data-get", G_CALLBACK(gaim_gtk_blist_drag_data_get_cb), NULL); |
11059
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
3575 #ifdef _WIN32 |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
3576 g_signal_connect(G_OBJECT(gtkblist->treeview), "drag-begin", G_CALLBACK(gaim_gtk_blist_drag_begin), NULL); |
c86d423df757
[gaim-migrate @ 13012]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11038
diff
changeset
|
3577 #endif |
10433 | 3578 |
10354 | 3579 g_signal_connect(G_OBJECT(gtkblist->treeview), "drag-motion", G_CALLBACK(gaim_gtk_blist_drag_motion_cb), NULL); |
5228 | 3580 |
3581 /* Tooltips */ | |
3582 g_signal_connect(G_OBJECT(gtkblist->treeview), "motion-notify-event", G_CALLBACK(gaim_gtk_blist_motion_cb), NULL); | |
3583 g_signal_connect(G_OBJECT(gtkblist->treeview), "leave-notify-event", G_CALLBACK(gaim_gtk_blist_leave_cb), NULL); | |
3584 | |
3585 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(gtkblist->treeview), FALSE); | |
3586 | |
11016 | 3587 gtkblist->text_column = column = gtk_tree_view_column_new (); |
5228 | 3588 |
3589 rend = gtk_cell_renderer_pixbuf_new(); | |
9811 | 3590 gtk_tree_view_column_pack_start(column, rend, FALSE); |
3591 gtk_tree_view_column_set_attributes(column, rend, | |
3592 "pixbuf", STATUS_ICON_COLUMN, | |
3593 "visible", STATUS_ICON_VISIBLE_COLUMN, | |
3594 NULL); | |
5228 | 3595 g_object_set(rend, "xalign", 0.0, "ypad", 0, NULL); |
3596 | |
11016 | 3597 gtkblist->text_rend = rend = gtk_cell_renderer_text_new(); |
5228 | 3598 gtk_tree_view_column_pack_start (column, rend, TRUE); |
9811 | 3599 gtk_tree_view_column_set_attributes(column, rend, |
3600 "markup", NAME_COLUMN, | |
3601 NULL); | |
11016 | 3602 g_signal_connect(G_OBJECT(rend), "edited", G_CALLBACK(gtk_blist_renderer_edited_cb), NULL); |
5228 | 3603 g_object_set(rend, "ypad", 0, "yalign", 0.5, NULL); |
10285 | 3604 #if GTK_CHECK_VERSION(2,6,0) |
3605 gtk_tree_view_column_set_expand (column, TRUE); | |
10501 | 3606 g_object_set(rend, "ellipsize", PANGO_ELLIPSIZE_END, NULL); |
10285 | 3607 #endif |
5228 | 3608 gtk_tree_view_append_column(GTK_TREE_VIEW(gtkblist->treeview), column); |
3609 | |
3610 rend = gtk_cell_renderer_text_new(); | |
10351 | 3611 gtkblist->idle_column = gtk_tree_view_column_new_with_attributes("Idle", rend, "markup", IDLE_COLUMN, NULL); |
3612 gtk_tree_view_append_column(GTK_TREE_VIEW(gtkblist->treeview), gtkblist->idle_column); | |
5228 | 3613 g_object_set(rend, "xalign", 1.0, "ypad", 0, NULL); |
3614 | |
3615 rend = gtk_cell_renderer_pixbuf_new(); | |
3616 gtkblist->buddy_icon_column = gtk_tree_view_column_new_with_attributes("Buddy Icon", rend, "pixbuf", BUDDY_ICON_COLUMN, NULL); | |
3617 g_object_set(rend, "xalign", 1.0, "ypad", 0, NULL); | |
3618 gtk_tree_view_append_column(GTK_TREE_VIEW(gtkblist->treeview), gtkblist->buddy_icon_column); | |
3619 | |
3620 g_signal_connect(G_OBJECT(gtkblist->treeview), "row-activated", G_CALLBACK(gtk_blist_row_activated_cb), NULL); | |
3621 g_signal_connect(G_OBJECT(gtkblist->treeview), "row-expanded", G_CALLBACK(gtk_blist_row_expanded_cb), NULL); | |
3622 g_signal_connect(G_OBJECT(gtkblist->treeview), "row-collapsed", G_CALLBACK(gtk_blist_row_collapsed_cb), NULL); | |
3623 g_signal_connect(G_OBJECT(gtkblist->treeview), "button-press-event", G_CALLBACK(gtk_blist_button_press_cb), NULL); | |
7620 | 3624 g_signal_connect(G_OBJECT(gtkblist->treeview), "key-press-event", G_CALLBACK(gtk_blist_key_press_cb), NULL); |
8143 | 3625 g_signal_connect(G_OBJECT(gtkblist->treeview), "popup-menu", G_CALLBACK(gaim_gtk_blist_popup_menu_cb), NULL); |
5228 | 3626 |
5419 | 3627 /* Enable CTRL+F searching */ |
3628 gtk_tree_view_set_search_column(GTK_TREE_VIEW(gtkblist->treeview), NAME_COLUMN); | |
10433 | 3629 gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(gtkblist->treeview), _search_func, NULL, NULL); |
5419 | 3630 |
5228 | 3631 gtk_box_pack_start(GTK_BOX(gtkblist->vbox), sw, TRUE, TRUE, 0); |
3632 gtk_container_add(GTK_CONTAINER(sw), gtkblist->treeview); | |
3633 gaim_gtk_blist_update_columns(); | |
3634 | |
10643 | 3635 gtkblist->statusbox = gtk_gaim_status_box_new(); |
3636 | |
3637 gtk_widget_show(gtkblist->statusbox); | |
3638 gtk_box_pack_start(GTK_BOX(gtkblist->vbox), gtkblist->statusbox, FALSE, TRUE, 0); | |
10178
96a850ab30c8
[gaim-migrate @ 11293]
Christian Hammond <chipx86@chipx86.com>
parents:
10144
diff
changeset
|
3639 |
5228 | 3640 /* set the Show Offline Buddies option. must be done |
3641 * after the treeview or faceprint gets mad. -Robot101 | |
3642 */ | |
5427 | 3643 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Buddies/Show Offline Buddies"))), |
7620 | 3644 gaim_prefs_get_bool("/gaim/gtk/blist/show_offline_buddies")); |
5427 | 3645 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Buddies/Show Empty Groups"))), |
7620 | 3646 gaim_prefs_get_bool("/gaim/gtk/blist/show_empty_groups")); |
10074 | 3647 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Tools/Mute Sounds"))), |
3648 gaim_prefs_get_bool("/gaim/gtk/sound/mute")); | |
3649 if(!strcmp(gaim_prefs_get_string("/gaim/gtk/sound/method"), "none")) | |
11494 | 3650 gtk_widget_set_sensitive(gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Mute Sounds")), FALSE); |
5228 | 3651 |
10353 | 3652 /* Update some dynamic things */ |
3653 update_menu_bar(gtkblist); | |
3654 gaim_gtk_blist_update_plugin_actions(); | |
3655 | |
5228 | 3656 /* OK... let's show this bad boy. */ |
10282 | 3657 if (gaim_prefs_get_bool("/gaim/gtk/blist/list_visible") || docklet_count == 0) { |
3658 gaim_gtk_blist_refresh(list); | |
3659 gaim_gtk_blist_restore_position(); | |
3660 gtk_widget_show(gtkblist->window); | |
3661 } | |
5228 | 3662 |
3663 /* start the refresh timer */ | |
10351 | 3664 gtkblist->refresh_timer = g_timeout_add(30000, (GSourceFunc)gaim_gtk_blist_refresh_timer, list); |
10353 | 3665 |
10087 | 3666 handle = gaim_gtk_blist_get_handle(); |
3667 | |
7620 | 3668 /* things that affect how buddies are displayed */ |
10087 | 3669 gaim_prefs_connect_callback(handle, "/gaim/gtk/blist/show_buddy_icons", |
3670 _prefs_change_redo_list, NULL); | |
3671 gaim_prefs_connect_callback(handle, "/gaim/gtk/blist/show_empty_groups", | |
3672 _prefs_change_redo_list, NULL); | |
3673 gaim_prefs_connect_callback(handle, "/gaim/gtk/blist/show_offline_buddies", | |
3674 _prefs_change_redo_list, NULL); | |
7620 | 3675 |
3676 /* sorting */ | |
10087 | 3677 gaim_prefs_connect_callback(handle, "/gaim/gtk/blist/sort_type", |
3678 _prefs_change_sort_method, NULL); | |
7620 | 3679 |
3680 /* things that affect what columns are displayed */ | |
10087 | 3681 gaim_prefs_connect_callback(handle, "/gaim/gtk/blist/show_buddy_icons", |
3682 gaim_gtk_blist_update_columns, NULL); | |
8259
4f9f68ab8770
[gaim-migrate @ 8982]
Christian Hammond <chipx86@chipx86.com>
parents:
8254
diff
changeset
|
3683 |
10074 | 3684 /* menus */ |
10087 | 3685 gaim_prefs_connect_callback(handle, "/gaim/gtk/sound/mute", |
3686 gaim_gtk_blist_mute_pref_cb, NULL); | |
3687 gaim_prefs_connect_callback(handle, "/gaim/gtk/sound/method", | |
3688 gaim_gtk_blist_sound_method_pref_cb, NULL); | |
10074 | 3689 |
8259
4f9f68ab8770
[gaim-migrate @ 8982]
Christian Hammond <chipx86@chipx86.com>
parents:
8254
diff
changeset
|
3690 /* Setup some gaim signal handlers. */ |
8937 | 3691 gaim_signal_connect(gaim_connections_get_handle(), "signed-on", |
3692 gtkblist, GAIM_CALLBACK(sign_on_off_cb), list); | |
3693 gaim_signal_connect(gaim_connections_get_handle(), "signed-off", | |
3694 gtkblist, GAIM_CALLBACK(sign_on_off_cb), list); | |
8815 | 3695 |
8986 | 3696 gaim_signal_connect(gaim_plugins_get_handle(), "plugin-load", |
3697 gtkblist, GAIM_CALLBACK(plugin_changed_cb), NULL); | |
3698 gaim_signal_connect(gaim_plugins_get_handle(), "plugin-unload", | |
3699 gtkblist, GAIM_CALLBACK(plugin_changed_cb), NULL); | |
3700 | |
8815 | 3701 /* emit our created signal */ |
10087 | 3702 gaim_signal_emit(handle, "gtkblist-created", list); |
5228 | 3703 } |
3704 | |
7620 | 3705 /* XXX: does this need fixing? */ |
3706 static void redo_buddy_list(GaimBuddyList *list, gboolean remove) | |
5228 | 3707 { |
7620 | 3708 GaimBlistNode *gnode, *cnode, *bnode; |
3709 | |
3710 for(gnode = list->root; gnode; gnode = gnode->next) { | |
3711 if(!GAIM_BLIST_NODE_IS_GROUP(gnode)) | |
5234 | 3712 continue; |
7620 | 3713 for(cnode = gnode->child; cnode; cnode = cnode->next) { |
3714 if(GAIM_BLIST_NODE_IS_CONTACT(cnode)) { | |
3715 if(remove) | |
3716 gaim_gtk_blist_hide_node(list, cnode); | |
3717 | |
3718 for(bnode = cnode->child; bnode; bnode = bnode->next) { | |
3719 if(!GAIM_BLIST_NODE_IS_BUDDY(bnode)) | |
3720 continue; | |
3721 if(remove) | |
3722 gaim_gtk_blist_hide_node(list, bnode); | |
3723 gaim_gtk_blist_update(list, bnode); | |
3724 } | |
3725 | |
3726 gaim_gtk_blist_update(list, cnode); | |
3727 } else if(GAIM_BLIST_NODE_IS_CHAT(cnode)) { | |
3728 if(remove) | |
3729 gaim_gtk_blist_hide_node(list, cnode); | |
3730 | |
3731 gaim_gtk_blist_update(list, cnode); | |
3732 } | |
5228 | 3733 } |
7620 | 3734 gaim_gtk_blist_update(list, gnode); |
5228 | 3735 } |
3736 } | |
3737 | |
7620 | 3738 void gaim_gtk_blist_refresh(GaimBuddyList *list) |
5422 | 3739 { |
3740 redo_buddy_list(list, FALSE); | |
3741 } | |
3742 | |
5297 | 3743 void |
3744 gaim_gtk_blist_update_refresh_timeout() | |
3745 { | |
7620 | 3746 GaimBuddyList *blist; |
3747 GaimGtkBuddyList *gtkblist; | |
5297 | 3748 |
3749 blist = gaim_get_blist(); | |
3750 gtkblist = GAIM_GTK_BLIST(gaim_get_blist()); | |
3751 | |
10351 | 3752 gtkblist->refresh_timer = g_timeout_add(30000,(GSourceFunc)gaim_gtk_blist_refresh_timer, blist); |
5297 | 3753 } |
3754 | |
5256 | 3755 static gboolean get_iter_from_node(GaimBlistNode *node, GtkTreeIter *iter) { |
3756 struct _gaim_gtk_blist_node *gtknode = (struct _gaim_gtk_blist_node *)node->ui_data; | |
3757 GtkTreePath *path; | |
5228 | 3758 |
5263 | 3759 if (!gtknode) { |
3760 return FALSE; | |
3761 } | |
3762 | |
3763 if (!gtkblist) { | |
10006 | 3764 gaim_debug_error("gtkblist", "get_iter_from_node was called, but we don't seem to have a blist\n"); |
5263 | 3765 return FALSE; |
3766 } | |
3767 | |
3768 if (!gtknode->row) | |
5228 | 3769 return FALSE; |
11494 | 3770 |
5228 | 3771 |
5256 | 3772 if ((path = gtk_tree_row_reference_get_path(gtknode->row)) == NULL) |
5228 | 3773 return FALSE; |
11016 | 3774 |
5256 | 3775 if (!gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), iter, path)) { |
3776 gtk_tree_path_free(path); | |
3777 return FALSE; | |
3778 } | |
3779 gtk_tree_path_free(path); | |
3780 return TRUE; | |
5228 | 3781 } |
3782 | |
7620 | 3783 static void gaim_gtk_blist_remove(GaimBuddyList *list, GaimBlistNode *node) |
5228 | 3784 { |
10222 | 3785 gaim_request_close_with_handle(node); |
3786 | |
5260 | 3787 gaim_gtk_blist_hide_node(list, node); |
5228 | 3788 |
7620 | 3789 if(node->parent) |
3790 gaim_gtk_blist_update(list, node->parent); | |
3791 | |
10504 | 3792 /* There's something I don't understand here - Ethan */ |
3793 /* Ethan said that back in 2003, but this g_free has been left commented | |
3794 * out ever since. I can't find any reason at all why this is bad and | |
3795 * valgrind found several reasons why it's good. If this causes problems | |
3796 * comment it out again. Stu */ | |
10510 | 3797 /* Of course it still causes problems - this breaks dragging buddies into |
10515 | 3798 * contacts, the dragged buddy mysteriously 'disappears'. Stu. */ |
3799 /* I think it's fixed now. Stu. */ | |
10504 | 3800 g_free(node->ui_data); |
10515 | 3801 node->ui_data = NULL; |
5228 | 3802 } |
3803 | |
3804 static gboolean do_selection_changed(GaimBlistNode *new_selection) | |
3805 { | |
5254 | 3806 GaimBlistNode *old_selection = NULL; |
5228 | 3807 |
5254 | 3808 /* test for gtkblist because crazy timeout means we can be called after the blist is gone */ |
3809 if (gtkblist && new_selection != gtkblist->selected_node) { | |
3810 old_selection = gtkblist->selected_node; | |
5228 | 3811 gtkblist->selected_node = new_selection; |
3812 if(new_selection) | |
3813 gaim_gtk_blist_update(NULL, new_selection); | |
3814 if(old_selection) | |
3815 gaim_gtk_blist_update(NULL, old_selection); | |
3816 } | |
3817 | |
3818 return FALSE; | |
3819 } | |
3820 | |
3821 static void gaim_gtk_blist_selection_changed(GtkTreeSelection *selection, gpointer data) | |
3822 { | |
3823 GaimBlistNode *new_selection = NULL; | |
3824 GtkTreeIter iter; | |
3825 | |
3826 if(gtk_tree_selection_get_selected(selection, NULL, &iter)){ | |
3827 gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, | |
3828 NODE_COLUMN, &new_selection, -1); | |
3829 } | |
5254 | 3830 |
5228 | 3831 /* we set this up as a timeout, otherwise the blist flickers */ |
3832 g_timeout_add(0, (GSourceFunc)do_selection_changed, new_selection); | |
3833 } | |
3834 | |
8252 | 3835 static gboolean insert_node(GaimBuddyList *list, GaimBlistNode *node, GtkTreeIter *iter) |
7620 | 3836 { |
3837 GtkTreeIter parent_iter, cur, *curptr = NULL; | |
3838 struct _gaim_gtk_blist_node *gtknode = node->ui_data; | |
5256 | 3839 GtkTreePath *newpath; |
7620 | 3840 |
10515 | 3841 if(!iter) |
8252 | 3842 return FALSE; |
7620 | 3843 |
3844 if(node->parent && !get_iter_from_node(node->parent, &parent_iter)) | |
8252 | 3845 return FALSE; |
7620 | 3846 |
3847 if(get_iter_from_node(node, &cur)) | |
3848 curptr = &cur; | |
3849 | |
3850 if(GAIM_BLIST_NODE_IS_CONTACT(node) || GAIM_BLIST_NODE_IS_CHAT(node)) { | |
3851 *iter = current_sort_method->func(node, list, parent_iter, curptr); | |
3852 } else { | |
3853 *iter = sort_method_none(node, list, parent_iter, curptr); | |
5228 | 3854 } |
3855 | |
10515 | 3856 if(gtknode != NULL) { |
3857 gtk_tree_row_reference_free(gtknode->row); | |
3858 } else { | |
3859 gaim_gtk_blist_new_node(node); | |
3860 gtknode = (struct _gaim_gtk_blist_node *)node->ui_data; | |
3861 } | |
3862 | |
7620 | 3863 newpath = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), |
3864 iter); | |
3865 gtknode->row = | |
3866 gtk_tree_row_reference_new(GTK_TREE_MODEL(gtkblist->treemodel), | |
3867 newpath); | |
11494 | 3868 |
5256 | 3869 gtk_tree_path_free(newpath); |
3870 | |
5228 | 3871 gtk_tree_store_set(gtkblist->treemodel, iter, |
3872 NODE_COLUMN, node, | |
3873 -1); | |
7620 | 3874 |
3875 if(node->parent) { | |
3876 GtkTreePath *expand = NULL; | |
3877 struct _gaim_gtk_blist_node *gtkparentnode = node->parent->ui_data; | |
3878 | |
3879 if(GAIM_BLIST_NODE_IS_GROUP(node->parent)) { | |
7693 | 3880 if(!gaim_blist_node_get_bool(node->parent, "collapsed")) |
7620 | 3881 expand = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &parent_iter); |
3882 } else if(GAIM_BLIST_NODE_IS_CONTACT(node->parent) && | |
3883 gtkparentnode->contact_expanded) { | |
3884 expand = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &parent_iter); | |
3885 } | |
3886 if(expand) { | |
7693 | 3887 gtk_tree_view_expand_row(GTK_TREE_VIEW(gtkblist->treeview), expand, FALSE); |
7620 | 3888 gtk_tree_path_free(expand); |
3889 } | |
3890 } | |
3891 | |
8252 | 3892 return TRUE; |
5228 | 3893 } |
3894 | |
7620 | 3895 static void gaim_gtk_blist_update_group(GaimBuddyList *list, GaimBlistNode *node) |
3896 { | |
3897 GaimGroup *group; | |
8203 | 3898 int count; |
7620 | 3899 |
3900 g_return_if_fail(GAIM_BLIST_NODE_IS_GROUP(node)); | |
3901 | |
3902 group = (GaimGroup*)node; | |
3903 | |
8203 | 3904 if(gaim_prefs_get_bool("/gaim/gtk/blist/show_offline_buddies")) |
3905 count = gaim_blist_get_group_size(group, FALSE); | |
3906 else | |
3907 count = gaim_blist_get_group_online_count(group); | |
3908 if(gaim_prefs_get_bool("/gaim/gtk/blist/show_empty_groups") || count > 0) { | |
7620 | 3909 char *mark, *esc; |
3910 GtkTreeIter iter; | |
3911 | |
8252 | 3912 if(!insert_node(list, node, &iter)) |
3913 return; | |
7620 | 3914 |
3915 esc = g_markup_escape_text(group->name, -1); | |
8945 | 3916 mark = g_strdup_printf("<span weight='bold'>%s</span> (%d/%d)", |
3917 esc, gaim_blist_get_group_online_count(group), | |
3918 gaim_blist_get_group_size(group, FALSE)); | |
7620 | 3919 g_free(esc); |
3920 | |
3921 gtk_tree_store_set(gtkblist->treemodel, &iter, | |
3922 STATUS_ICON_COLUMN, NULL, | |
3923 STATUS_ICON_VISIBLE_COLUMN, FALSE, | |
3924 NAME_COLUMN, mark, | |
3925 NODE_COLUMN, node, | |
3926 -1); | |
3927 g_free(mark); | |
3928 } else { | |
3929 gaim_gtk_blist_hide_node(list, node); | |
3930 } | |
3931 } | |
3932 | |
3933 static void buddy_node(GaimBuddy *buddy, GtkTreeIter *iter, GaimBlistNode *node) | |
5228 | 3934 { |
9944 | 3935 GaimPresence *presence; |
7620 | 3936 GdkPixbuf *status, *avatar; |
3937 char *mark; | |
11257 | 3938 char *idle = NULL; |
7620 | 3939 gboolean selected = (gtkblist->selected_node == node); |
3940 | |
9944 | 3941 presence = gaim_buddy_get_presence(buddy); |
3942 | |
7620 | 3943 status = gaim_gtk_blist_get_status_icon((GaimBlistNode*)buddy, |
3944 (gaim_prefs_get_bool("/gaim/gtk/blist/show_buddy_icons") | |
3945 ? GAIM_STATUS_ICON_LARGE : GAIM_STATUS_ICON_SMALL)); | |
3946 | |
10482 | 3947 avatar = gaim_gtk_blist_get_buddy_icon((GaimBlistNode *)buddy, TRUE, TRUE); |
7620 | 3948 mark = gaim_gtk_blist_get_name_markup(buddy, selected); |
3949 | |
9944 | 3950 if (gaim_presence_is_idle(presence)) |
3951 { | |
3952 time_t idle_secs = gaim_presence_get_idle_time(presence); | |
3953 | |
3954 if (idle_secs > 0) | |
3955 { | |
3956 time_t t; | |
3957 int ihrs, imin; | |
3958 time(&t); | |
3959 ihrs = (t - idle_secs) / 3600; | |
3960 imin = ((t - idle_secs) / 60) % 60; | |
3961 | |
3962 if (ihrs > 0) | |
3963 idle = g_strdup_printf("(%d:%02d)", ihrs, imin); | |
3964 else | |
3965 idle = g_strdup_printf("(%d)", imin); | |
3966 } | |
7620 | 3967 } |
3968 | |
10118 | 3969 if (gaim_presence_is_idle(presence)) |
9944 | 3970 { |
3971 if (idle && !selected) { | |
10118 | 3972 char *i2 = g_strdup_printf("<span color='%s'>%s</span>", |
3973 dim_grey(), idle); | |
7620 | 3974 g_free(idle); |
3975 idle = i2; | |
5228 | 3976 } |
7620 | 3977 } |
3978 | |
3979 gtk_tree_store_set(gtkblist->treemodel, iter, | |
3980 STATUS_ICON_COLUMN, status, | |
3981 STATUS_ICON_VISIBLE_COLUMN, TRUE, | |
3982 NAME_COLUMN, mark, | |
3983 IDLE_COLUMN, idle, | |
3984 BUDDY_ICON_COLUMN, avatar, | |
3985 -1); | |
3986 | |
3987 g_free(mark); | |
3988 if(idle) | |
3989 g_free(idle); | |
3990 if(status) | |
3991 g_object_unref(status); | |
3992 if(avatar) | |
3993 g_object_unref(avatar); | |
3994 } | |
3995 | |
3996 static void gaim_gtk_blist_update_contact(GaimBuddyList *list, GaimBlistNode *node) | |
3997 { | |
3998 GaimContact *contact; | |
3999 GaimBuddy *buddy; | |
4000 struct _gaim_gtk_blist_node *gtknode; | |
4001 | |
4002 g_return_if_fail(GAIM_BLIST_NODE_IS_CONTACT(node)); | |
4003 | |
4004 /* First things first, update the group */ | |
4005 gaim_gtk_blist_update_group(list, node->parent); | |
4006 | |
4007 contact = (GaimContact*)node; | |
4008 buddy = gaim_contact_get_priority_buddy(contact); | |
4009 | |
11577 | 4010 if (buddy && gaim_account_is_connected(buddy->account) && |
4011 (gaim_presence_is_online(buddy->presence) || | |
11434
f191b5bc199b
[gaim-migrate @ 13671]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11338
diff
changeset
|
4012 buddy->present == GAIM_BUDDY_SIGNING_OFF || |
11577 | 4013 gaim_prefs_get_bool("/gaim/gtk/blist/show_offline_buddies") || |
10006 | 4014 gaim_blist_node_get_bool(node, "show_offline"))) |
4015 { | |
7620 | 4016 GtkTreeIter iter; |
4017 | |
8252 | 4018 if(!insert_node(list, node, &iter)) |
4019 return; | |
7620 | 4020 |
10515 | 4021 gtknode = (struct _gaim_gtk_blist_node *)node->ui_data; |
4022 | |
7620 | 4023 if(gtknode->contact_expanded) { |
4024 GdkPixbuf *status; | |
5228 | 4025 char *mark; |
4026 | |
7620 | 4027 status = gaim_gtk_blist_get_status_icon(node, |
4028 (gaim_prefs_get_bool("/gaim/gtk/blist/show_buddy_icons") ? | |
4029 GAIM_STATUS_ICON_LARGE : GAIM_STATUS_ICON_SMALL)); | |
4030 | |
4031 mark = g_markup_escape_text(gaim_contact_get_alias(contact), -1); | |
4032 | |
5228 | 4033 gtk_tree_store_set(gtkblist->treemodel, &iter, |
7620 | 4034 STATUS_ICON_COLUMN, status, |
4035 STATUS_ICON_VISIBLE_COLUMN, TRUE, | |
5228 | 4036 NAME_COLUMN, mark, |
7620 | 4037 IDLE_COLUMN, NULL, |
4038 BUDDY_ICON_COLUMN, NULL, | |
5228 | 4039 -1); |
4040 g_free(mark); | |
7620 | 4041 if(status) |
4042 g_object_unref(status); | |
4043 } else { | |
4044 buddy_node(buddy, &iter, node); | |
5228 | 4045 } |
7620 | 4046 } else { |
4047 gaim_gtk_blist_hide_node(list, node); | |
5228 | 4048 } |
7620 | 4049 } |
4050 | |
4051 static void gaim_gtk_blist_update_buddy(GaimBuddyList *list, GaimBlistNode *node) | |
4052 { | |
4053 GaimContact *contact; | |
4054 GaimBuddy *buddy; | |
4055 struct _gaim_gtk_blist_node *gtkparentnode; | |
4056 | |
4057 g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node)); | |
4058 | |
4059 buddy = (GaimBuddy*)node; | |
4060 contact = (GaimContact*)node->parent; | |
4061 | |
11624 | 4062 if (contact == NULL) |
4063 return; | |
4064 | |
7620 | 4065 /* First things first, update the contact */ |
4066 gaim_gtk_blist_update_contact(list, node->parent); | |
4067 | |
10918 | 4068 gtkparentnode = (struct _gaim_gtk_blist_node *)node->parent->ui_data; |
4069 | |
10006 | 4070 if (gtkparentnode->contact_expanded && |
4071 (gaim_presence_is_online(buddy->presence) || | |
11434
f191b5bc199b
[gaim-migrate @ 13671]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11338
diff
changeset
|
4072 buddy->present == GAIM_BUDDY_SIGNING_OFF || |
7620 | 4073 (gaim_account_is_connected(buddy->account) && |
10006 | 4074 gaim_prefs_get_bool("/gaim/gtk/blist/show_offline_buddies")) || |
4075 gaim_blist_node_get_bool(node->parent, "show_offline"))) | |
4076 { | |
7620 | 4077 GtkTreeIter iter; |
4078 | |
10006 | 4079 if (!insert_node(list, node, &iter)) |
8252 | 4080 return; |
4081 | |
7620 | 4082 buddy_node(buddy, &iter, node); |
4083 | |
4084 } else { | |
4085 gaim_gtk_blist_hide_node(list, node); | |
4086 } | |
4087 | |
4088 } | |
4089 | |
4090 static void gaim_gtk_blist_update_chat(GaimBuddyList *list, GaimBlistNode *node) | |
4091 { | |
4092 GaimChat *chat; | |
4093 | |
4094 g_return_if_fail(GAIM_BLIST_NODE_IS_CHAT(node)); | |
4095 | |
4096 /* First things first, update the group */ | |
4097 gaim_gtk_blist_update_group(list, node->parent); | |
4098 | |
4099 chat = (GaimChat*)node; | |
4100 | |
4101 if(gaim_account_is_connected(chat->account)) { | |
4102 GtkTreeIter iter; | |
5234 | 4103 GdkPixbuf *status; |
7620 | 4104 char *mark; |
4105 | |
8252 | 4106 if(!insert_node(list, node, &iter)) |
4107 return; | |
5234 | 4108 |
4109 status = gaim_gtk_blist_get_status_icon(node, | |
7620 | 4110 (gaim_prefs_get_bool("/gaim/gtk/blist/show_buddy_icons") ? |
4111 GAIM_STATUS_ICON_LARGE : GAIM_STATUS_ICON_SMALL)); | |
4112 | |
4113 mark = g_markup_escape_text(gaim_chat_get_name(chat), -1); | |
5234 | 4114 |
4115 gtk_tree_store_set(gtkblist->treemodel, &iter, | |
7620 | 4116 STATUS_ICON_COLUMN, status, |
4117 STATUS_ICON_VISIBLE_COLUMN, TRUE, | |
4118 NAME_COLUMN, mark, | |
4119 -1); | |
5228 | 4120 |
4121 g_free(mark); | |
7620 | 4122 if(status) |
5228 | 4123 g_object_unref(status); |
7620 | 4124 } else { |
5260 | 4125 gaim_gtk_blist_hide_node(list, node); |
5228 | 4126 } |
7620 | 4127 } |
4128 | |
4129 static void gaim_gtk_blist_update(GaimBuddyList *list, GaimBlistNode *node) | |
4130 { | |
4131 if(!gtkblist) | |
4132 return; | |
4133 | |
4134 switch(node->type) { | |
4135 case GAIM_BLIST_GROUP_NODE: | |
4136 gaim_gtk_blist_update_group(list, node); | |
4137 break; | |
4138 case GAIM_BLIST_CONTACT_NODE: | |
4139 gaim_gtk_blist_update_contact(list, node); | |
4140 break; | |
4141 case GAIM_BLIST_BUDDY_NODE: | |
4142 gaim_gtk_blist_update_buddy(list, node); | |
4143 break; | |
4144 case GAIM_BLIST_CHAT_NODE: | |
4145 gaim_gtk_blist_update_chat(list, node); | |
4146 break; | |
4147 case GAIM_BLIST_OTHER_NODE: | |
4148 return; | |
4149 } | |
5234 | 4150 |
5228 | 4151 gtk_tree_view_columns_autosize(GTK_TREE_VIEW(gtkblist->treeview)); |
4152 } | |
4153 | |
7620 | 4154 |
4155 static void gaim_gtk_blist_destroy(GaimBuddyList *list) | |
5228 | 4156 { |
4157 if (!gtkblist) | |
4158 return; | |
4159 | |
8937 | 4160 gaim_signal_disconnect(gaim_connections_get_handle(), "signed-on", |
4161 gtkblist, GAIM_CALLBACK(sign_on_off_cb)); | |
4162 gaim_signal_disconnect(gaim_connections_get_handle(), "signed-off", | |
4163 gtkblist, GAIM_CALLBACK(sign_on_off_cb)); | |
8259
4f9f68ab8770
[gaim-migrate @ 8982]
Christian Hammond <chipx86@chipx86.com>
parents:
8254
diff
changeset
|
4164 |
5228 | 4165 gtk_widget_destroy(gtkblist->window); |
7620 | 4166 |
8254 | 4167 gaim_gtk_blist_tooltip_destroy(); |
7620 | 4168 |
5228 | 4169 if (gtkblist->refresh_timer) |
4170 g_source_remove(gtkblist->refresh_timer); | |
4171 if (gtkblist->timeout) | |
4172 g_source_remove(gtkblist->timeout); | |
10354 | 4173 if (gtkblist->drag_timeout) |
4174 g_source_remove(gtkblist->drag_timeout); | |
5228 | 4175 |
4176 gtkblist->refresh_timer = 0; | |
4177 gtkblist->timeout = 0; | |
10354 | 4178 gtkblist->drag_timeout = 0; |
5228 | 4179 gtkblist->window = gtkblist->vbox = gtkblist->treeview = NULL; |
4180 gtkblist->treemodel = NULL; | |
4181 gtkblist->idle_column = NULL; | |
11257 | 4182 gtkblist->buddy_icon_column = NULL; |
5427 | 4183 g_object_unref(G_OBJECT(gtkblist->ift)); |
5228 | 4184 protomenu = NULL; |
8986 | 4185 pluginmenu = NULL; |
5228 | 4186 gtkblist = NULL; |
7620 | 4187 |
10087 | 4188 gaim_prefs_disconnect_by_handle(gaim_gtk_blist_get_handle()); |
5228 | 4189 } |
4190 | |
7620 | 4191 static void gaim_gtk_blist_set_visible(GaimBuddyList *list, gboolean show) |
5228 | 4192 { |
4193 if (!(gtkblist && gtkblist->window)) | |
4194 return; | |
10325 | 4195 |
10282 | 4196 gaim_prefs_set_bool("/gaim/gtk/blist/list_visible", show); |
10325 | 4197 |
5228 | 4198 if (show) { |
4199 gaim_gtk_blist_restore_position(); | |
4200 gtk_window_present(GTK_WINDOW(gtkblist->window)); | |
4201 } else { | |
7620 | 4202 if (!gaim_connections_get_all() || docklet_count) { |
5228 | 4203 #ifdef _WIN32 |
4204 wgaim_systray_minimize(gtkblist->window); | |
4205 #endif | |
4206 gtk_widget_hide(gtkblist->window); | |
4207 } else { | |
4208 gtk_window_iconify(GTK_WINDOW(gtkblist->window)); | |
4209 } | |
4210 } | |
4211 } | |
4212 | |
7620 | 4213 static GList * |
4214 groups_tree(void) | |
4215 { | |
4216 GList *tmp = NULL; | |
4217 char *tmp2; | |
4218 GaimGroup *g; | |
4219 GaimBlistNode *gnode; | |
4220 | |
4221 if (gaim_get_blist()->root == NULL) | |
4222 { | |
4223 tmp2 = g_strdup(_("Buddies")); | |
4224 tmp = g_list_append(tmp, tmp2); | |
4225 } | |
4226 else | |
4227 { | |
4228 for (gnode = gaim_get_blist()->root; | |
4229 gnode != NULL; | |
4230 gnode = gnode->next) | |
4231 { | |
4232 if (GAIM_BLIST_NODE_IS_GROUP(gnode)) | |
4233 { | |
4234 g = (GaimGroup *)gnode; | |
4235 tmp2 = g->name; | |
4236 tmp = g_list_append(tmp, tmp2); | |
4237 } | |
4238 } | |
4239 } | |
4240 | |
4241 return tmp; | |
4242 } | |
4243 | |
4244 static void | |
4245 add_buddy_select_account_cb(GObject *w, GaimAccount *account, | |
4246 GaimGtkAddBuddyData *data) | |
4247 { | |
4248 /* Save our account */ | |
4249 data->account = account; | |
4250 } | |
4251 | |
4252 static void | |
4253 destroy_add_buddy_dialog_cb(GtkWidget *win, GaimGtkAddBuddyData *data) | |
4254 { | |
4255 g_free(data); | |
4256 } | |
4257 | |
4258 static void | |
4259 add_buddy_cb(GtkWidget *w, int resp, GaimGtkAddBuddyData *data) | |
4260 { | |
4261 const char *grp, *who, *whoalias; | |
4262 GaimConversation *c; | |
4263 GaimBuddy *b; | |
4264 GaimGroup *g; | |
4265 | |
4266 if (resp == GTK_RESPONSE_OK) | |
4267 { | |
4268 who = gtk_entry_get_text(GTK_ENTRY(data->entry)); | |
4269 grp = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(data->combo)->entry)); | |
4270 whoalias = gtk_entry_get_text(GTK_ENTRY(data->entry_for_alias)); | |
9658 | 4271 if (*whoalias == '\0') |
4272 whoalias = NULL; | |
7620 | 4273 |
4274 if ((g = gaim_find_group(grp)) == NULL) | |
4275 { | |
4276 g = gaim_group_new(grp); | |
4277 gaim_blist_add_group(g, NULL); | |
4278 } | |
4279 | |
4280 b = gaim_buddy_new(data->account, who, whoalias); | |
4281 gaim_blist_add_buddy(b, NULL, g, NULL); | |
9285 | 4282 serv_add_buddy(gaim_account_get_connection(data->account), b); |
7620 | 4283 |
7887 | 4284 /* |
9285 | 4285 * XXX |
8470
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
4286 * It really seems like it would be better if the call to serv_add_buddy() |
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
4287 * and gaim_conversation_update() were done in blist.c, possibly in the |
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
4288 * gaim_blist_add_buddy() function. Maybe serv_add_buddy() should be |
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
4289 * renamed to gaim_blist_add_new_buddy() or something, and have it call |
7887 | 4290 * gaim_blist_add_buddy() after it creates it. --Mark |
9285 | 4291 * |
4292 * No that's not good. blist.c should only deal with adding nodes to the | |
4293 * local list. We need a new, non-gtk file that calls both serv_add_buddy | |
4294 * and gaim_blist_add_buddy(). Or something. --Mark | |
7887 | 4295 */ |
4296 | |
11338 | 4297 c = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, who, data->account); |
7620 | 4298 if (c != NULL) { |
4299 gaim_buddy_icon_update(gaim_conv_im_get_icon(GAIM_CONV_IM(c))); | |
4300 gaim_conversation_update(c, GAIM_CONV_UPDATE_ADD); | |
4301 } | |
4302 } | |
4303 | |
4304 gtk_widget_destroy(data->window); | |
4305 } | |
4306 | |
4307 static void | |
4308 gaim_gtk_blist_request_add_buddy(GaimAccount *account, const char *username, | |
4309 const char *group, const char *alias) | |
4310 { | |
4311 GtkWidget *table; | |
4312 GtkWidget *label; | |
4313 GtkWidget *hbox; | |
4314 GtkWidget *vbox; | |
4315 GtkWidget *img; | |
4316 GaimGtkBuddyList *gtkblist; | |
4317 GaimGtkAddBuddyData *data = g_new0(GaimGtkAddBuddyData, 1); | |
4318 | |
4319 data->account = | |
4320 (account != NULL | |
4321 ? account | |
4322 : gaim_connection_get_account(gaim_connections_get_all()->data)); | |
4323 | |
4324 img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_QUESTION, | |
4325 GTK_ICON_SIZE_DIALOG); | |
4326 | |
4327 gtkblist = GAIM_GTK_BLIST(gaim_get_blist()); | |
4328 | |
4329 data->window = gtk_dialog_new_with_buttons(_("Add Buddy"), | |
8975 | 4330 NULL, GTK_DIALOG_NO_SEPARATOR, |
7620 | 4331 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, |
4332 GTK_STOCK_ADD, GTK_RESPONSE_OK, | |
4333 NULL); | |
4334 | |
4335 gtk_dialog_set_default_response(GTK_DIALOG(data->window), GTK_RESPONSE_OK); | |
11243 | 4336 gtk_container_set_border_width(GTK_CONTAINER(data->window), GAIM_HIG_BOX_SPACE); |
7620 | 4337 gtk_window_set_resizable(GTK_WINDOW(data->window), FALSE); |
11243 | 4338 gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(data->window)->vbox), GAIM_HIG_BORDER); |
4339 gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(data->window)->vbox), GAIM_HIG_BOX_SPACE); | |
7620 | 4340 gtk_window_set_role(GTK_WINDOW(data->window), "add_buddy"); |
8975 | 4341 gtk_window_set_type_hint(GTK_WINDOW(data->window), |
9811 | 4342 GDK_WINDOW_TYPE_HINT_DIALOG); |
7620 | 4343 |
11243 | 4344 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BORDER); |
7620 | 4345 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(data->window)->vbox), hbox); |
4346 gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); | |
4347 gtk_misc_set_alignment(GTK_MISC(img), 0, 0); | |
4348 | |
4349 vbox = gtk_vbox_new(FALSE, 0); | |
4350 gtk_container_add(GTK_CONTAINER(hbox), vbox); | |
4351 | |
4352 label = gtk_label_new( | |
4353 _("Please enter the screen name of the person you would like " | |
4354 "to add to your buddy list. You may optionally enter an alias, " | |
4355 "or nickname, for the buddy. The alias will be displayed in " | |
4356 "place of the screen name whenever possible.\n")); | |
4357 | |
4358 gtk_widget_set_size_request(GTK_WIDGET(label), 400, -1); | |
4359 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); | |
4360 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); | |
4361 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); | |
4362 | |
11243 | 4363 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BOX_SPACE); |
7620 | 4364 gtk_container_add(GTK_CONTAINER(vbox), hbox); |
4365 | |
4366 g_signal_connect(G_OBJECT(data->window), "destroy", | |
4367 G_CALLBACK(destroy_add_buddy_dialog_cb), data); | |
4368 | |
4369 table = gtk_table_new(4, 2, FALSE); | |
4370 gtk_table_set_row_spacings(GTK_TABLE(table), 5); | |
4371 gtk_table_set_col_spacings(GTK_TABLE(table), 5); | |
4372 gtk_container_set_border_width(GTK_CONTAINER(table), 0); | |
4373 gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0); | |
4374 | |
4375 label = gtk_label_new(_("Screen Name:")); | |
4376 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
4377 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1); | |
4378 | |
4379 data->entry = gtk_entry_new(); | |
4380 gtk_table_attach_defaults(GTK_TABLE(table), data->entry, 1, 2, 0, 1); | |
4381 gtk_widget_grab_focus(data->entry); | |
4382 | |
4383 if (username != NULL) | |
4384 gtk_entry_set_text(GTK_ENTRY(data->entry), username); | |
4385 | |
4386 gtk_entry_set_activates_default (GTK_ENTRY(data->entry), TRUE); | |
8137 | 4387 gaim_set_accessible_label (data->entry, label); |
7620 | 4388 |
4389 label = gtk_label_new(_("Alias:")); | |
4390 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
4391 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2); | |
4392 | |
4393 data->entry_for_alias = gtk_entry_new(); | |
4394 gtk_table_attach_defaults(GTK_TABLE(table), | |
4395 data->entry_for_alias, 1, 2, 1, 2); | |
4396 | |
4397 if (alias != NULL) | |
4398 gtk_entry_set_text(GTK_ENTRY(data->entry_for_alias), alias); | |
4399 | |
10734
8b2c81d9b271
[gaim-migrate @ 12336]
Luke Schierer <lschiere@pidgin.im>
parents:
10694
diff
changeset
|
4400 if (username != NULL) |
8b2c81d9b271
[gaim-migrate @ 12336]
Luke Schierer <lschiere@pidgin.im>
parents:
10694
diff
changeset
|
4401 gtk_widget_grab_focus(GTK_WIDGET(data->entry_for_alias)); |
8b2c81d9b271
[gaim-migrate @ 12336]
Luke Schierer <lschiere@pidgin.im>
parents:
10694
diff
changeset
|
4402 |
7620 | 4403 gtk_entry_set_activates_default (GTK_ENTRY(data->entry_for_alias), TRUE); |
8137 | 4404 gaim_set_accessible_label (data->entry_for_alias, label); |
7620 | 4405 |
4406 label = gtk_label_new(_("Group:")); | |
4407 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
4408 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3); | |
4409 | |
4410 data->combo = gtk_combo_new(); | |
4411 gtk_combo_set_popdown_strings(GTK_COMBO(data->combo), groups_tree()); | |
4412 gtk_table_attach_defaults(GTK_TABLE(table), data->combo, 1, 2, 2, 3); | |
8137 | 4413 gaim_set_accessible_label (data->combo, label); |
7620 | 4414 |
4415 /* Set up stuff for the account box */ | |
4416 label = gtk_label_new(_("Account:")); | |
4417 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
4418 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 3, 4); | |
4419 | |
4420 data->account_box = gaim_gtk_account_option_menu_new(account, FALSE, | |
4421 G_CALLBACK(add_buddy_select_account_cb), NULL, data); | |
4422 | |
4423 gtk_table_attach_defaults(GTK_TABLE(table), data->account_box, 1, 2, 3, 4); | |
8137 | 4424 gaim_set_accessible_label (data->account_box, label); |
7620 | 4425 /* End of account box */ |
4426 | |
4427 g_signal_connect(G_OBJECT(data->window), "response", | |
4428 G_CALLBACK(add_buddy_cb), data); | |
4429 | |
4430 gtk_widget_show_all(data->window); | |
4431 | |
4432 if (group != NULL) | |
4433 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(data->combo)->entry), group); | |
4434 } | |
4435 | |
4436 static void | |
4437 add_chat_cb(GtkWidget *w, GaimGtkAddChatData *data) | |
4438 { | |
4439 GHashTable *components; | |
4440 GList *tmp; | |
4441 GaimChat *chat; | |
4442 GaimGroup *group; | |
4443 const char *group_name; | |
9918 | 4444 char *chat_name = NULL; |
4445 GaimConversation *conv = NULL; | |
10475 | 4446 const char *value; |
7620 | 4447 |
4448 components = g_hash_table_new_full(g_str_hash, g_str_equal, | |
4449 g_free, g_free); | |
4450 | |
4451 for (tmp = data->entries; tmp; tmp = tmp->next) | |
4452 { | |
4453 if (g_object_get_data(tmp->data, "is_spin")) | |
4454 { | |
4455 g_hash_table_replace(components, | |
4456 g_strdup(g_object_get_data(tmp->data, "identifier")), | |
4457 g_strdup_printf("%d", | |
4458 gtk_spin_button_get_value_as_int(tmp->data))); | |
4459 } | |
4460 else | |
4461 { | |
10475 | 4462 value = gtk_entry_get_text(tmp->data); |
4463 if (*value != '\0') | |
4464 g_hash_table_replace(components, | |
4465 g_strdup(g_object_get_data(tmp->data, "identifier")), | |
4466 g_strdup(value)); | |
7620 | 4467 } |
4468 } | |
4469 | |
4470 chat = gaim_chat_new(data->account, | |
4471 gtk_entry_get_text(GTK_ENTRY(data->alias_entry)), | |
4472 components); | |
4473 | |
4474 group_name = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(data->group_combo)->entry)); | |
4475 | |
4476 if ((group = gaim_find_group(group_name)) == NULL) | |
4477 { | |
4478 group = gaim_group_new(group_name); | |
4479 gaim_blist_add_group(group, NULL); | |
4480 } | |
4481 | |
4482 if (chat != NULL) | |
4483 { | |
4484 gaim_blist_add_chat(chat, group, NULL); | |
9918 | 4485 |
4486 if (GAIM_PLUGIN_PROTOCOL_INFO(data->account->gc->prpl)->get_chat_name != NULL) | |
4487 chat_name = GAIM_PLUGIN_PROTOCOL_INFO( | |
4488 data->account->gc->prpl)->get_chat_name(chat->components); | |
10246 | 4489 |
9918 | 4490 if (chat_name != NULL) { |
11338 | 4491 conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT, |
10246 | 4492 chat_name, |
4493 data->account); | |
9918 | 4494 g_free(chat_name); |
4495 } | |
4496 | |
4497 if (conv != NULL) | |
4498 gaim_conversation_update(conv, GAIM_CONV_UPDATE_ADD); | |
7620 | 4499 } |
4500 | |
4501 gtk_widget_destroy(data->window); | |
9812 | 4502 g_free(data->default_chat_name); |
7620 | 4503 g_list_free(data->entries); |
4504 g_free(data); | |
4505 } | |
4506 | |
4507 static void | |
4508 add_chat_resp_cb(GtkWidget *w, int resp, GaimGtkAddChatData *data) | |
4509 { | |
4510 if (resp == GTK_RESPONSE_OK) | |
4511 { | |
4512 add_chat_cb(NULL, data); | |
4513 } | |
4514 else | |
4515 { | |
4516 gtk_widget_destroy(data->window); | |
9812 | 4517 g_free(data->default_chat_name); |
7620 | 4518 g_list_free(data->entries); |
4519 g_free(data); | |
4520 } | |
4521 } | |
4522 | |
10475 | 4523 /* |
4524 * Check the values of all the text entry boxes. If any required input | |
4525 * strings are empty then don't allow the user to click on "OK." | |
4526 */ | |
4527 static void | |
4528 addchat_set_sensitive_if_input_cb(GtkWidget *entry, gpointer user_data) | |
4529 { | |
4530 GaimGtkAddChatData *data; | |
4531 GList *tmp; | |
4532 const char *text; | |
4533 gboolean required; | |
4534 gboolean sensitive = TRUE; | |
4535 | |
4536 data = user_data; | |
4537 | |
4538 for (tmp = data->entries; tmp != NULL; tmp = tmp->next) | |
4539 { | |
4540 if (!g_object_get_data(tmp->data, "is_spin")) | |
4541 { | |
4542 required = GPOINTER_TO_INT(g_object_get_data(tmp->data, "required")); | |
4543 text = gtk_entry_get_text(tmp->data); | |
4544 if (required && (*text == '\0')) | |
4545 sensitive = FALSE; | |
4546 } | |
4547 } | |
4548 | |
4549 gtk_dialog_set_response_sensitive(GTK_DIALOG(data->window), GTK_RESPONSE_OK, sensitive); | |
4550 } | |
4551 | |
7620 | 4552 static void |
4553 rebuild_addchat_entries(GaimGtkAddChatData *data) | |
4554 { | |
4555 GaimConnection *gc; | |
9959 | 4556 GList *list = NULL, *tmp = NULL; |
9754 | 4557 GHashTable *defaults = NULL; |
7620 | 4558 struct proto_chat_entry *pce; |
4559 gboolean focus = TRUE; | |
4560 | |
10127 | 4561 g_return_if_fail(data->account != NULL); |
4562 | |
7620 | 4563 gc = gaim_account_get_connection(data->account); |
4564 | |
4565 while (GTK_BOX(data->entries_box)->children) | |
4566 { | |
4567 gtk_container_remove(GTK_CONTAINER(data->entries_box), | |
10475 | 4568 ((GtkBoxChild *)GTK_BOX(data->entries_box)->children->data)->widget); |
7620 | 4569 } |
4570 | |
4571 if (data->entries != NULL) | |
4572 g_list_free(data->entries); | |
4573 | |
4574 data->entries = NULL; | |
4575 | |
9959 | 4576 if (GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info != NULL) |
4577 list = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info(gc); | |
7620 | 4578 |
9754 | 4579 if (GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults != NULL) |
10475 | 4580 defaults = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, data->default_chat_name); |
9754 | 4581 |
7620 | 4582 for (tmp = list; tmp; tmp = tmp->next) |
4583 { | |
4584 GtkWidget *label; | |
4585 GtkWidget *rowbox; | |
10475 | 4586 GtkWidget *input; |
7620 | 4587 |
4588 pce = tmp->data; | |
4589 | |
4590 rowbox = gtk_hbox_new(FALSE, 5); | |
4591 gtk_box_pack_start(GTK_BOX(data->entries_box), rowbox, FALSE, FALSE, 0); | |
4592 | |
7889 | 4593 label = gtk_label_new_with_mnemonic(pce->label); |
7620 | 4594 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); |
4595 gtk_size_group_add_widget(data->sg, label); | |
4596 gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0); | |
4597 | |
4598 if (pce->is_int) | |
4599 { | |
4600 GtkObject *adjust; | |
4601 adjust = gtk_adjustment_new(pce->min, pce->min, pce->max, | |
4602 1, 10, 10); | |
10475 | 4603 input = gtk_spin_button_new(GTK_ADJUSTMENT(adjust), 1, 0); |
4604 gtk_widget_set_size_request(input, 50, -1); | |
4605 gtk_box_pack_end(GTK_BOX(rowbox), input, FALSE, FALSE, 0); | |
7620 | 4606 } |
4607 else | |
4608 { | |
9754 | 4609 char *value; |
10475 | 4610 input = gtk_entry_new(); |
4611 gtk_entry_set_activates_default(GTK_ENTRY(input), TRUE); | |
9754 | 4612 value = g_hash_table_lookup(defaults, pce->identifier); |
4613 if (value != NULL) | |
10475 | 4614 gtk_entry_set_text(GTK_ENTRY(input), value); |
7620 | 4615 if (pce->secret) |
10475 | 4616 gtk_entry_set_visibility(GTK_ENTRY(input), FALSE); |
4617 gtk_box_pack_end(GTK_BOX(rowbox), input, TRUE, TRUE, 0); | |
4618 g_signal_connect(G_OBJECT(input), "changed", | |
4619 G_CALLBACK(addchat_set_sensitive_if_input_cb), data); | |
7620 | 4620 } |
4621 | |
10475 | 4622 /* Do the following for any type of input widget */ |
4623 if (focus) | |
4624 { | |
4625 gtk_widget_grab_focus(input); | |
4626 focus = FALSE; | |
4627 } | |
4628 gtk_label_set_mnemonic_widget(GTK_LABEL(label), input); | |
4629 gaim_set_accessible_label(input, label); | |
4630 g_object_set_data(G_OBJECT(input), "identifier", pce->identifier); | |
4631 g_object_set_data(G_OBJECT(input), "is_spin", GINT_TO_POINTER(pce->is_int)); | |
4632 g_object_set_data(G_OBJECT(input), "required", GINT_TO_POINTER(pce->required)); | |
4633 data->entries = g_list_append(data->entries, input); | |
4634 | |
7620 | 4635 g_free(pce); |
4636 } | |
4637 | |
4638 g_list_free(list); | |
9754 | 4639 g_hash_table_destroy(defaults); |
7620 | 4640 |
10475 | 4641 /* Set whether the "OK" button should be clickable initially */ |
4642 addchat_set_sensitive_if_input_cb(NULL, data); | |
4643 | |
7620 | 4644 gtk_widget_show_all(data->entries_box); |
4645 } | |
4646 | |
4647 static void | |
10475 | 4648 addchat_select_account_cb(GObject *w, GaimAccount *account, |
7620 | 4649 GaimGtkAddChatData *data) |
4650 { | |
9460 | 4651 if (strcmp(gaim_account_get_protocol_id(data->account), |
4652 gaim_account_get_protocol_id(account)) == 0) | |
7620 | 4653 { |
4654 data->account = account; | |
4655 } | |
4656 else | |
4657 { | |
4658 data->account = account; | |
4659 rebuild_addchat_entries(data); | |
4660 } | |
4661 } | |
4662 | |
4663 void | |
7859 | 4664 gaim_gtk_blist_request_add_chat(GaimAccount *account, GaimGroup *group, |
9754 | 4665 const char *alias, const char *name) |
7620 | 4666 { |
4667 GaimGtkAddChatData *data; | |
8975 | 4668 GaimGtkBuddyList *gtkblist; |
4669 GList *l; | |
4670 GaimConnection *gc; | |
7620 | 4671 GtkWidget *label; |
4672 GtkWidget *rowbox; | |
4673 GtkWidget *hbox; | |
4674 GtkWidget *vbox; | |
4675 GtkWidget *img; | |
4676 | |
9812 | 4677 if (account != NULL) { |
4678 gc = gaim_account_get_connection(account); | |
4679 | |
4680 if (GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->join_chat == NULL) { | |
4681 gaim_notify_error(gc, NULL, _("This protocol does not support chat rooms."), NULL); | |
4682 return; | |
4683 } | |
4684 } else { | |
4685 /* Find an account with chat capabilities */ | |
4686 for (l = gaim_connections_get_all(); l != NULL; l = l->next) { | |
4687 gc = (GaimConnection *)l->data; | |
4688 | |
4689 if (GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->join_chat != NULL) { | |
4690 account = gaim_connection_get_account(gc); | |
4691 break; | |
4692 } | |
4693 } | |
4694 | |
4695 if (account == NULL) { | |
4696 gaim_notify_error(NULL, NULL, | |
4697 _("You are not currently signed on with any " | |
4698 "protocols that have the ability to chat."), NULL); | |
4699 return; | |
4700 } | |
4701 } | |
4702 | |
7620 | 4703 data = g_new0(GaimGtkAddChatData, 1); |
9812 | 4704 data->account = account; |
4705 data->default_chat_name = g_strdup(name); | |
7620 | 4706 |
4707 img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_QUESTION, | |
4708 GTK_ICON_SIZE_DIALOG); | |
4709 | |
8975 | 4710 gtkblist = GAIM_GTK_BLIST(gaim_get_blist()); |
4711 | |
7620 | 4712 data->sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); |
4713 | |
8975 | 4714 data->window = gtk_dialog_new_with_buttons(_("Add Chat"), |
4715 NULL, GTK_DIALOG_NO_SEPARATOR, | |
4716 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, | |
4717 GTK_STOCK_ADD, GTK_RESPONSE_OK, | |
4718 NULL); | |
4719 | |
4720 gtk_dialog_set_default_response(GTK_DIALOG(data->window), GTK_RESPONSE_OK); | |
11243 | 4721 gtk_container_set_border_width(GTK_CONTAINER(data->window), GAIM_HIG_BOX_SPACE); |
8975 | 4722 gtk_window_set_resizable(GTK_WINDOW(data->window), FALSE); |
11243 | 4723 gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(data->window)->vbox), GAIM_HIG_BORDER); |
4724 gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(data->window)->vbox), GAIM_HIG_BOX_SPACE); | |
7620 | 4725 gtk_window_set_role(GTK_WINDOW(data->window), "add_chat"); |
8975 | 4726 gtk_window_set_type_hint(GTK_WINDOW(data->window), |
9811 | 4727 GDK_WINDOW_TYPE_HINT_DIALOG); |
7620 | 4728 |
11243 | 4729 hbox = gtk_hbox_new(FALSE, GAIM_HIG_BORDER); |
7620 | 4730 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(data->window)->vbox), hbox); |
4731 gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); | |
4732 gtk_misc_set_alignment(GTK_MISC(img), 0, 0); | |
4733 | |
4734 vbox = gtk_vbox_new(FALSE, 5); | |
4735 gtk_container_add(GTK_CONTAINER(hbox), vbox); | |
4736 | |
4737 label = gtk_label_new( | |
4738 _("Please enter an alias, and the appropriate information " | |
4739 "about the chat you would like to add to your buddy list.\n")); | |
4740 gtk_widget_set_size_request(label, 400, -1); | |
4741 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); | |
4742 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); | |
4743 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); | |
4744 | |
4745 rowbox = gtk_hbox_new(FALSE, 5); | |
4746 gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0); | |
4747 | |
4748 label = gtk_label_new(_("Account:")); | |
4749 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
4750 gtk_size_group_add_widget(data->sg, label); | |
4751 gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0); | |
4752 | |
4753 data->account_menu = gaim_gtk_account_option_menu_new(account, FALSE, | |
10475 | 4754 G_CALLBACK(addchat_select_account_cb), |
9987 | 4755 chat_account_filter_func, data); |
7620 | 4756 gtk_box_pack_start(GTK_BOX(rowbox), data->account_menu, TRUE, TRUE, 0); |
8137 | 4757 gaim_set_accessible_label (data->account_menu, label); |
7620 | 4758 |
4759 data->entries_box = gtk_vbox_new(FALSE, 5); | |
9811 | 4760 gtk_container_set_border_width(GTK_CONTAINER(data->entries_box), 0); |
7620 | 4761 gtk_box_pack_start(GTK_BOX(vbox), data->entries_box, TRUE, TRUE, 0); |
4762 | |
4763 rebuild_addchat_entries(data); | |
4764 | |
4765 rowbox = gtk_hbox_new(FALSE, 5); | |
4766 gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0); | |
4767 | |
4768 label = gtk_label_new(_("Alias:")); | |
4769 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
4770 gtk_size_group_add_widget(data->sg, label); | |
4771 gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0); | |
4772 | |
4773 data->alias_entry = gtk_entry_new(); | |
7859 | 4774 if (alias != NULL) |
4775 gtk_entry_set_text(GTK_ENTRY(data->alias_entry), alias); | |
7620 | 4776 gtk_box_pack_end(GTK_BOX(rowbox), data->alias_entry, TRUE, TRUE, 0); |
10311 | 4777 gtk_entry_set_activates_default(GTK_ENTRY(data->alias_entry), TRUE); |
8137 | 4778 gaim_set_accessible_label (data->alias_entry, label); |
7620 | 4779 |
4780 rowbox = gtk_hbox_new(FALSE, 5); | |
4781 gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0); | |
4782 | |
9811 | 4783 label = gtk_label_new(_("Group:")); |
7620 | 4784 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); |
4785 gtk_size_group_add_widget(data->sg, label); | |
4786 gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0); | |
4787 | |
9811 | 4788 data->group_combo = gtk_combo_new(); |
4789 gtk_combo_set_popdown_strings(GTK_COMBO(data->group_combo), groups_tree()); | |
7620 | 4790 gtk_box_pack_end(GTK_BOX(rowbox), data->group_combo, TRUE, TRUE, 0); |
4791 | |
4792 if (group) | |
4793 { | |
4794 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(data->group_combo)->entry), | |
4795 group->name); | |
4796 } | |
8137 | 4797 gaim_set_accessible_label (data->group_combo, label); |
7620 | 4798 |
4799 g_signal_connect(G_OBJECT(data->window), "response", | |
4800 G_CALLBACK(add_chat_resp_cb), data); | |
4801 | |
4802 gtk_widget_show_all(data->window); | |
4803 } | |
4804 | |
4805 static void | |
4806 add_group_cb(GaimConnection *gc, const char *group_name) | |
4807 { | |
9285 | 4808 GaimGroup *group; |
4809 | |
4810 group = gaim_group_new(group_name); | |
4811 gaim_blist_add_group(group, NULL); | |
7620 | 4812 } |
4813 | |
4814 void | |
4815 gaim_gtk_blist_request_add_group(void) | |
4816 { | |
7853 | 4817 gaim_request_input(NULL, _("Add Group"), NULL, |
7620 | 4818 _("Please enter the name of the group to be added."), |
8697 | 4819 NULL, FALSE, FALSE, NULL, |
7620 | 4820 _("Add"), G_CALLBACK(add_group_cb), |
4821 _("Cancel"), NULL, NULL); | |
4822 } | |
4823 | |
5228 | 4824 void gaim_gtk_blist_docklet_toggle() { |
4825 /* Useful for the docklet plugin and also for the win32 tray icon*/ | |
8470
9949b752d1ab
[gaim-migrate @ 9203]
Christian Hammond <chipx86@chipx86.com>
parents:
8444
diff
changeset
|
4826 /* This is called when one of those is clicked--it will show/hide the |
5228 | 4827 buddy list/login window--depending on which is active */ |
10315 | 4828 if (gtkblist && gtkblist->window) { |
4829 if (GTK_WIDGET_VISIBLE(gtkblist->window)) { | |
4830 gaim_blist_set_visible(GAIM_WINDOW_ICONIFIED(gtkblist->window) || gaim_gtk_blist_obscured); | |
5228 | 4831 } else { |
4832 #if _WIN32 | |
10315 | 4833 wgaim_systray_maximize(gtkblist->window); |
5228 | 4834 #endif |
10315 | 4835 gaim_blist_set_visible(TRUE); |
5228 | 4836 } |
4837 } else { | |
10315 | 4838 /* we're logging in or something... do nothing */ |
4839 /* or should I make the blist? */ | |
4840 gaim_debug_warning("gtkblist", | |
4841 "docklet_toggle called with gaim_connections_get_all() " | |
4842 "but no blist!\n"); | |
5228 | 4843 } |
4844 } | |
4845 | |
4846 void gaim_gtk_blist_docklet_add() | |
4847 { | |
4848 docklet_count++; | |
4849 } | |
4850 | |
4851 void gaim_gtk_blist_docklet_remove() | |
4852 { | |
4853 docklet_count--; | |
4854 if (!docklet_count) { | |
4855 gaim_blist_set_visible(TRUE); | |
4856 } | |
4857 } | |
4858 | |
7620 | 4859 static GaimBlistUiOps blist_ui_ops = |
5228 | 4860 { |
4861 gaim_gtk_blist_new_list, | |
5256 | 4862 gaim_gtk_blist_new_node, |
5228 | 4863 gaim_gtk_blist_show, |
4864 gaim_gtk_blist_update, | |
4865 gaim_gtk_blist_remove, | |
4866 gaim_gtk_blist_destroy, | |
7620 | 4867 gaim_gtk_blist_set_visible, |
4868 gaim_gtk_blist_request_add_buddy, | |
4869 gaim_gtk_blist_request_add_chat, | |
10012 | 4870 gaim_gtk_blist_request_add_group |
5228 | 4871 }; |
4872 | |
4873 | |
7620 | 4874 GaimBlistUiOps * |
4875 gaim_gtk_blist_get_ui_ops(void) | |
5228 | 4876 { |
4877 return &blist_ui_ops; | |
4878 } | |
4879 | |
10643 | 4880 GaimGtkBuddyList *gaim_gtk_blist_get_default_gtk_blist() |
4881 { | |
4882 return gtkblist; | |
4883 } | |
4884 | |
7620 | 4885 static void account_signon_cb(GaimConnection *gc, gpointer z) |
4886 { | |
4887 GaimAccount *account = gaim_connection_get_account(gc); | |
4888 GaimBlistNode *gnode, *cnode; | |
4889 for(gnode = gaim_get_blist()->root; gnode; gnode = gnode->next) | |
4890 { | |
4891 if(!GAIM_BLIST_NODE_IS_GROUP(gnode)) | |
4892 continue; | |
4893 for(cnode = gnode->child; cnode; cnode = cnode->next) | |
4894 { | |
4895 GaimChat *chat; | |
4896 | |
4897 if(!GAIM_BLIST_NODE_IS_CHAT(cnode)) | |
4898 continue; | |
4899 | |
4900 chat = (GaimChat *)cnode; | |
4901 | |
4902 if(chat->account != account) | |
4903 continue; | |
4904 | |
8197 | 4905 if(gaim_blist_node_get_bool((GaimBlistNode*)chat, "gtk-autojoin") || |
8198 | 4906 (gaim_blist_node_get_string((GaimBlistNode*)chat, |
4907 "gtk-autojoin") != NULL)) | |
7620 | 4908 serv_join_chat(gc, chat->components); |
4909 } | |
4910 } | |
4911 } | |
4912 | |
8815 | 4913 void * |
4914 gaim_gtk_blist_get_handle() { | |
4915 static int handle; | |
4916 | |
4917 return &handle; | |
4918 } | |
4919 | |
7620 | 4920 void gaim_gtk_blist_init(void) |
4921 { | |
8815 | 4922 void *gtk_blist_handle = gaim_gtk_blist_get_handle(); |
7620 | 4923 |
4924 gaim_signal_connect(gaim_connections_get_handle(), "signed-on", | |
8815 | 4925 gtk_blist_handle, GAIM_CALLBACK(account_signon_cb), |
7620 | 4926 NULL); |
7731 | 4927 |
4928 /* Initialize prefs */ | |
8819 | 4929 gaim_prefs_add_none("/gaim/gtk/blist"); |
4930 gaim_prefs_add_bool("/gaim/gtk/blist/show_buddy_icons", TRUE); | |
4931 gaim_prefs_add_bool("/gaim/gtk/blist/show_empty_groups", FALSE); | |
4932 gaim_prefs_add_bool("/gaim/gtk/blist/show_offline_buddies", FALSE); | |
10282 | 4933 gaim_prefs_add_bool("/gaim/gtk/blist/list_visible", TRUE); |
9711 | 4934 gaim_prefs_add_string("/gaim/gtk/blist/sort_type", "alphabetical"); |
8819 | 4935 gaim_prefs_add_int("/gaim/gtk/blist/x", 0); |
4936 gaim_prefs_add_int("/gaim/gtk/blist/y", 0); | |
9778 | 4937 gaim_prefs_add_int("/gaim/gtk/blist/width", 309); /* Golden ratio, baby */ |
4938 gaim_prefs_add_int("/gaim/gtk/blist/height", 500); /* Golden ratio, baby */ | |
8819 | 4939 gaim_prefs_add_int("/gaim/gtk/blist/tooltip_delay", 500); |
7731 | 4940 |
8815 | 4941 /* Register our signals */ |
4942 gaim_signal_register(gtk_blist_handle, "gtkblist-created", | |
9811 | 4943 gaim_marshal_VOID__POINTER, NULL, 1, |
4944 gaim_value_new(GAIM_TYPE_SUBTYPE, | |
4945 GAIM_SUBTYPE_BLIST)); | |
8819 | 4946 |
4947 gaim_signal_register(gtk_blist_handle, "drawing-tooltip", | |
9811 | 4948 gaim_marshal_VOID__POINTER_POINTER, NULL, 2, |
4949 gaim_value_new(GAIM_TYPE_SUBTYPE, GAIM_SUBTYPE_BLIST_NODE), | |
10477 | 4950 gaim_value_new_outgoing(GAIM_TYPE_BOXED, "GString *")); |
7620 | 4951 } |
4952 | |
8815 | 4953 void |
4954 gaim_gtk_blist_uninit(void) { | |
4955 gaim_signals_unregister_by_instance(gaim_gtk_blist_get_handle()); | |
4956 } | |
5228 | 4957 |
4958 /********************************************************************* | |
4959 * Public utility functions * | |
4960 *********************************************************************/ | |
4961 | |
4962 GdkPixbuf * | |
10884 | 4963 gaim_gtk_create_prpl_icon(GaimAccount *account) |
5228 | 4964 { |
4965 GaimPlugin *prpl; | |
4966 GaimPluginProtocolInfo *prpl_info = NULL; | |
4967 GdkPixbuf *status = NULL; | |
4968 char *filename = NULL; | |
4969 const char *protoname = NULL; | |
4970 char buf[256]; | |
4971 | |
10046 | 4972 g_return_val_if_fail(account != NULL, NULL); |
4973 | |
7956 | 4974 prpl = gaim_find_prpl(gaim_account_get_protocol_id(account)); |
5228 | 4975 |
4976 if (prpl != NULL) { | |
4977 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl); | |
4978 | |
4979 if (prpl_info->list_icon != NULL) | |
4980 protoname = prpl_info->list_icon(account, NULL); | |
4981 } | |
4982 | |
4983 if (protoname == NULL) | |
4984 return NULL; | |
4985 | |
4986 /* | |
4987 * Status icons will be themeable too, and then it will look up | |
4988 * protoname from the theme | |
4989 */ | |
4990 g_snprintf(buf, sizeof(buf), "%s.png", protoname); | |
4991 | |
4992 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", | |
4993 "default", buf, NULL); | |
4994 status = gdk_pixbuf_new_from_file(filename, NULL); | |
4995 g_free(filename); | |
4996 | |
4997 return status; | |
4998 } | |
4999 | |
5422 | 5000 |
5001 /********************************************************************* | |
9811 | 5002 * Buddy List sorting functions * |
5422 | 5003 *********************************************************************/ |
5004 | |
7620 | 5005 void gaim_gtk_blist_sort_method_reg(const char *id, const char *name, gaim_gtk_blist_sort_function func) |
5422 | 5006 { |
5007 struct gaim_gtk_blist_sort_method *method = g_new0(struct gaim_gtk_blist_sort_method, 1); | |
7620 | 5008 method->id = g_strdup(id); |
5422 | 5009 method->name = g_strdup(name); |
9775 | 5010 method->func = func; |
5422 | 5011 gaim_gtk_blist_sort_methods = g_slist_append(gaim_gtk_blist_sort_methods, method); |
5012 } | |
5013 | |
7620 | 5014 void gaim_gtk_blist_sort_method_unreg(const char *id){ |
5015 GSList *l = gaim_gtk_blist_sort_methods; | |
5016 | |
5017 while(l) { | |
5018 struct gaim_gtk_blist_sort_method *method = l->data; | |
5019 if(!strcmp(method->id, id)) { | |
5020 gaim_gtk_blist_sort_methods = g_slist_remove(gaim_gtk_blist_sort_methods, method); | |
5021 g_free(method->id); | |
5022 g_free(method->name); | |
5023 g_free(method); | |
5024 break; | |
5025 } | |
5026 } | |
5422 | 5027 } |
5028 | |
7620 | 5029 void gaim_gtk_blist_sort_method_set(const char *id){ |
5422 | 5030 GSList *l = gaim_gtk_blist_sort_methods; |
7620 | 5031 |
5032 if(!id) | |
5033 id = "none"; | |
5034 | |
5035 while (l && strcmp(((struct gaim_gtk_blist_sort_method*)l->data)->id, id)) | |
5422 | 5036 l = l->next; |
7620 | 5037 |
5422 | 5038 if (l) { |
5039 current_sort_method = l->data; | |
5040 } else if (!current_sort_method) { | |
7620 | 5041 gaim_gtk_blist_sort_method_set("none"); |
5422 | 5042 return; |
5043 } | |
5044 redo_buddy_list(gaim_get_blist(), TRUE); | |
5045 | |
5046 } | |
5047 | |
5048 /****************************************** | |
5049 ** Sort Methods | |
5050 ******************************************/ | |
5051 | |
7620 | 5052 static GtkTreeIter sort_method_none(GaimBlistNode *node, GaimBuddyList *blist, GtkTreeIter parent_iter, GtkTreeIter *cur) |
5422 | 5053 { |
7620 | 5054 GtkTreeIter iter; |
5055 GaimBlistNode *sibling = node->prev; | |
5056 GtkTreeIter sibling_iter; | |
5057 | |
5058 if(cur) | |
5422 | 5059 return *cur; |
7620 | 5060 |
5061 while (sibling && !get_iter_from_node(sibling, &sibling_iter)) { | |
5062 sibling = sibling->prev; | |
5422 | 5063 } |
7620 | 5064 |
5065 gtk_tree_store_insert_after(gtkblist->treemodel, &iter, | |
5066 node->parent ? &parent_iter : NULL, | |
5067 sibling ? &sibling_iter : NULL); | |
5068 | |
5422 | 5069 return iter; |
5070 } | |
5071 | |
7620 | 5072 #if GTK_CHECK_VERSION(2,2,1) |
5073 | |
5074 static GtkTreeIter sort_method_alphabetical(GaimBlistNode *node, GaimBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur) | |
5422 | 5075 { |
5076 GtkTreeIter more_z, iter; | |
5077 GaimBlistNode *n; | |
5078 GValue val = {0,}; | |
7620 | 5079 |
5080 const char *my_name; | |
5081 | |
5082 if(GAIM_BLIST_NODE_IS_CONTACT(node)) { | |
5083 my_name = gaim_contact_get_alias((GaimContact*)node); | |
5084 } else if(GAIM_BLIST_NODE_IS_CHAT(node)) { | |
5085 my_name = gaim_chat_get_name((GaimChat*)node); | |
5086 } else { | |
5087 return sort_method_none(node, blist, groupiter, cur); | |
5088 } | |
5089 | |
5422 | 5090 |
5091 if (!gtk_tree_model_iter_children(GTK_TREE_MODEL(gtkblist->treemodel), &more_z, &groupiter)) { | |
5092 gtk_tree_store_insert(gtkblist->treemodel, &iter, &groupiter, 0); | |
7620 | 5093 return iter; |
5094 } | |
5095 | |
5096 do { | |
5097 const char *this_name; | |
5098 int cmp; | |
5099 | |
5100 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &more_z, NODE_COLUMN, &val); | |
5101 n = g_value_get_pointer(&val); | |
5102 | |
5103 if(GAIM_BLIST_NODE_IS_CONTACT(n)) { | |
5104 this_name = gaim_contact_get_alias((GaimContact*)n); | |
5105 } else if(GAIM_BLIST_NODE_IS_CHAT(n)) { | |
5106 this_name = gaim_chat_get_name((GaimChat*)n); | |
5107 } else { | |
5108 this_name = NULL; | |
5109 } | |
5110 | |
5111 cmp = gaim_utf8_strcasecmp(my_name, this_name); | |
5112 | |
5113 if(this_name && (cmp < 0 || (cmp == 0 && node < n))) { | |
5114 if(cur) { | |
5115 gtk_tree_store_move_before(gtkblist->treemodel, cur, &more_z); | |
5116 return *cur; | |
5117 } else { | |
5118 gtk_tree_store_insert_before(gtkblist->treemodel, &iter, | |
5119 &groupiter, &more_z); | |
5120 return iter; | |
5121 } | |
5122 } | |
5123 g_value_unset(&val); | |
5124 } while (gtk_tree_model_iter_next (GTK_TREE_MODEL(gtkblist->treemodel), &more_z)); | |
5125 | |
5126 if(cur) { | |
5127 gtk_tree_store_move_before(gtkblist->treemodel, cur, NULL); | |
5128 return *cur; | |
5129 } else { | |
5130 gtk_tree_store_append(gtkblist->treemodel, &iter, &groupiter); | |
5131 return iter; | |
5132 } | |
5133 } | |
5134 | |
5135 static GtkTreeIter sort_method_status(GaimBlistNode *node, GaimBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur) | |
5136 { | |
5137 GtkTreeIter more_z, iter; | |
5138 GaimBlistNode *n; | |
5139 GValue val = {0,}; | |
5140 | |
5141 GaimBuddy *my_buddy, *this_buddy; | |
5142 | |
5143 if(GAIM_BLIST_NODE_IS_CONTACT(node)) { | |
5144 my_buddy = gaim_contact_get_priority_buddy((GaimContact*)node); | |
5145 } else if(GAIM_BLIST_NODE_IS_CHAT(node)) { | |
5146 if(cur) | |
5147 return *cur; | |
5148 | |
5149 gtk_tree_store_append(gtkblist->treemodel, &iter, &groupiter); | |
5150 return iter; | |
5151 } else { | |
5152 return sort_method_none(node, blist, groupiter, cur); | |
5153 } | |
5154 | |
5155 | |
5156 if (!gtk_tree_model_iter_children(GTK_TREE_MODEL(gtkblist->treemodel), &more_z, &groupiter)) { | |
5157 gtk_tree_store_insert(gtkblist->treemodel, &iter, &groupiter, 0); | |
5422 | 5158 return iter; |
5159 } | |
5160 | |
5161 do { | |
9944 | 5162 gint name_cmp; |
5163 gint presence_cmp; | |
7620 | 5164 |
5422 | 5165 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &more_z, NODE_COLUMN, &val); |
5166 n = g_value_get_pointer(&val); | |
7620 | 5167 |
5168 if(GAIM_BLIST_NODE_IS_CONTACT(n)) { | |
5169 this_buddy = gaim_contact_get_priority_buddy((GaimContact*)n); | |
5170 } else { | |
5171 this_buddy = NULL; | |
5172 } | |
5173 | |
9944 | 5174 name_cmp = gaim_utf8_strcasecmp( |
5175 (my_buddy | |
5176 ? gaim_contact_get_alias(gaim_buddy_get_contact(my_buddy)) | |
5177 : NULL), | |
5178 (this_buddy | |
5179 ? gaim_contact_get_alias(gaim_buddy_get_contact(this_buddy)) | |
5180 : NULL)); | |
5181 | |
5182 presence_cmp = gaim_presence_compare( | |
5183 gaim_buddy_get_presence(my_buddy), | |
5184 gaim_buddy_get_presence(this_buddy)); | |
5185 | |
5186 if (this_buddy == NULL || | |
10860 | 5187 (presence_cmp < 0 || |
9944 | 5188 (presence_cmp == 0 && |
5189 (name_cmp < 0 || (name_cmp == 0 && node < n))))) | |
5190 { | |
5191 if (cur != NULL) | |
5192 { | |
7620 | 5193 gtk_tree_store_move_before(gtkblist->treemodel, cur, &more_z); |
5194 return *cur; | |
9944 | 5195 } |
5196 else | |
5197 { | |
7620 | 5198 gtk_tree_store_insert_before(gtkblist->treemodel, &iter, |
9944 | 5199 &groupiter, &more_z); |
7620 | 5200 return iter; |
5201 } | |
5422 | 5202 } |
9944 | 5203 |
5422 | 5204 g_value_unset(&val); |
9944 | 5205 } |
5206 while (gtk_tree_model_iter_next(GTK_TREE_MODEL(gtkblist->treemodel), | |
5207 &more_z)); | |
7620 | 5208 |
5209 if(cur) { | |
5210 gtk_tree_store_move_before(gtkblist->treemodel, cur, NULL); | |
5211 return *cur; | |
5212 } else { | |
5213 gtk_tree_store_append(gtkblist->treemodel, &iter, &groupiter); | |
5214 return iter; | |
5215 } | |
5422 | 5216 } |
5217 | |
7620 | 5218 static GtkTreeIter sort_method_log(GaimBlistNode *node, GaimBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur) |
5422 | 5219 { |
5220 GtkTreeIter more_z, iter; | |
7620 | 5221 GaimBlistNode *n = NULL, *n2; |
5422 | 5222 GValue val = {0,}; |
7620 | 5223 |
5224 int log_size = 0, this_log_size = 0; | |
5225 const char *buddy_name, *this_buddy_name; | |
5226 | |
5227 if(cur && (gtk_tree_model_iter_n_children(GTK_TREE_MODEL(gtkblist->treemodel), &groupiter) == 1)) | |
5228 return *cur; | |
5229 | |
5230 if(GAIM_BLIST_NODE_IS_CONTACT(node)) { | |
5231 for (n = node->child; n; n = n->next) | |
8898 | 5232 log_size += gaim_log_get_total_size(GAIM_LOG_IM, ((GaimBuddy*)(n))->name, ((GaimBuddy*)(n))->account); |
7620 | 5233 buddy_name = gaim_contact_get_alias((GaimContact*)node); |
5234 } else if(GAIM_BLIST_NODE_IS_CHAT(node)) { | |
5235 /* we don't have a reliable way of getting the log filename | |
5236 * from the chat info in the blist, yet */ | |
5237 if(cur) | |
5238 return *cur; | |
5239 | |
5240 gtk_tree_store_append(gtkblist->treemodel, &iter, &groupiter); | |
5241 return iter; | |
5242 } else { | |
5243 return sort_method_none(node, blist, groupiter, cur); | |
5244 } | |
5245 | |
5246 | |
5422 | 5247 if (!gtk_tree_model_iter_children(GTK_TREE_MODEL(gtkblist->treemodel), &more_z, &groupiter)) { |
5248 gtk_tree_store_insert(gtkblist->treemodel, &iter, &groupiter, 0); | |
5249 return iter; | |
5250 } | |
5251 | |
5252 do { | |
7620 | 5253 int cmp; |
5254 | |
5422 | 5255 gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &more_z, NODE_COLUMN, &val); |
5256 n = g_value_get_pointer(&val); | |
7620 | 5257 this_log_size = 0; |
5258 | |
5259 if(GAIM_BLIST_NODE_IS_CONTACT(n)) { | |
5260 for (n2 = n->child; n2; n2 = n2->next) | |
8898 | 5261 this_log_size += gaim_log_get_total_size(GAIM_LOG_IM, ((GaimBuddy*)(n2))->name, ((GaimBuddy*)(n2))->account); |
7620 | 5262 this_buddy_name = gaim_contact_get_alias((GaimContact*)n); |
5263 } else { | |
5264 this_buddy_name = NULL; | |
5422 | 5265 } |
7620 | 5266 |
5267 cmp = gaim_utf8_strcasecmp(buddy_name, this_buddy_name); | |
5268 | |
5269 if (!GAIM_BLIST_NODE_IS_CONTACT(n) || log_size > this_log_size || | |
5270 ((log_size == this_log_size) && | |
5271 (cmp < 0 || (cmp == 0 && node < n)))) { | |
5272 if(cur) { | |
5273 gtk_tree_store_move_before(gtkblist->treemodel, cur, &more_z); | |
5274 return *cur; | |
5275 } else { | |
5276 gtk_tree_store_insert_before(gtkblist->treemodel, &iter, | |
5277 &groupiter, &more_z); | |
5278 return iter; | |
5279 } | |
5422 | 5280 } |
5281 g_value_unset(&val); | |
5282 } while (gtk_tree_model_iter_next (GTK_TREE_MODEL(gtkblist->treemodel), &more_z)); | |
7620 | 5283 |
5284 if(cur) { | |
5285 gtk_tree_store_move_before(gtkblist->treemodel, cur, NULL); | |
5286 return *cur; | |
5287 } else { | |
5288 gtk_tree_store_append(gtkblist->treemodel, &iter, &groupiter); | |
5289 return iter; | |
5290 } | |
5291 } | |
5292 | |
5293 #endif | |
5294 | |
5295 static void | |
9015 | 5296 plugin_act(GtkObject *obk, GaimPluginAction *pam) |
7620 | 5297 { |
10352 | 5298 if (pam->callback) |
5299 pam->callback(pam); | |
5422 | 5300 } |
7620 | 5301 |
8986 | 5302 static void |
9015 | 5303 build_plugin_actions(GtkWidget *menu, GaimPlugin *plugin, gpointer context) |
8986 | 5304 { |
9015 | 5305 GtkWidget *menuitem = NULL; |
5306 GaimPluginAction *action = NULL; | |
5307 GList *l, *ll; | |
5308 | |
5309 for (l = ll = GAIM_PLUGIN_ACTIONS(plugin, context); l; l = l->next) { | |
5310 if (l->data) { | |
5311 action = (GaimPluginAction *) l->data; | |
5312 action->plugin = plugin; | |
5313 action->context = context; | |
5314 | |
5315 menuitem = gtk_menu_item_new_with_label(action->label); | |
5316 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); | |
5317 g_signal_connect(G_OBJECT(menuitem), "activate", | |
5318 G_CALLBACK(plugin_act), action); | |
5319 g_object_set_data(G_OBJECT(menuitem), "plugin_action", action); | |
5320 gtk_widget_show(menuitem); | |
5321 } | |
5322 else | |
5323 gaim_separator(menu); | |
5324 } | |
5325 | |
5326 g_list_free(ll); | |
8986 | 5327 } |
5328 | |
5329 | |
7620 | 5330 void |
5331 gaim_gtk_blist_update_protocol_actions(void) | |
5332 { | |
9015 | 5333 GtkWidget *menuitem, *submenu; |
7620 | 5334 GList *l; |
5335 GaimConnection *gc = NULL; | |
9015 | 5336 GaimPlugin *plugin = NULL; |
7620 | 5337 int count = 0; |
9015 | 5338 |
9019 | 5339 if (protomenu == NULL) |
7620 | 5340 return; |
5341 | |
9019 | 5342 /* Clear the old Account Actions menu */ |
9015 | 5343 for (l = gtk_container_get_children(GTK_CONTAINER(protomenu)); l; l = l->next) { |
5344 GaimPluginAction *action; | |
9987 | 5345 |
7620 | 5346 menuitem = l->data; |
9015 | 5347 action = (GaimPluginAction *) g_object_get_data(G_OBJECT(menuitem), |
5348 "plugin_action"); | |
5349 g_free(action); | |
7620 | 5350 |
5351 gtk_container_remove(GTK_CONTAINER(protomenu), GTK_WIDGET(menuitem)); | |
5352 } | |
5353 | |
9019 | 5354 /* Count the number of accounts with actions */ |
9015 | 5355 for (l = gaim_connections_get_all(); l; l = l->next) { |
5356 gc = l->data; | |
5357 plugin = gc->prpl; | |
5358 | |
9019 | 5359 if (GAIM_CONNECTION_IS_CONNECTED(gc) && GAIM_PLUGIN_HAS_ACTIONS(plugin)) |
5360 count++; | |
5361 | |
9015 | 5362 /* no need to count past 2, so don't */ |
9019 | 5363 if (count > 1) |
9015 | 5364 break; |
7620 | 5365 } |
5366 | |
9015 | 5367 if (count == 0) { |
5368 menuitem = gtk_menu_item_new_with_label(_("No actions available")); | |
7620 | 5369 gtk_menu_shell_append(GTK_MENU_SHELL(protomenu), menuitem); |
9015 | 5370 gtk_widget_set_sensitive(menuitem, FALSE); |
7620 | 5371 gtk_widget_show(menuitem); |
5372 } | |
9019 | 5373 |
5374 else if (count == 1) { | |
5375 /* Find the one account that has actions */ | |
5376 for (l = gaim_connections_get_all(); l; l = l->next) { | |
5377 gc = l->data; | |
5378 plugin = gc->prpl; | |
5379 | |
5380 if (GAIM_CONNECTION_IS_CONNECTED(gc) && GAIM_PLUGIN_HAS_ACTIONS(plugin)) | |
5381 break; | |
5382 } | |
5383 | |
9015 | 5384 build_plugin_actions(protomenu, plugin, gc); |
7620 | 5385 } |
9019 | 5386 |
7620 | 5387 else { |
9015 | 5388 for (l = gaim_connections_get_all(); l; l = l->next) { |
7620 | 5389 GaimAccount *account; |
5390 GdkPixbuf *pixbuf, *scale; | |
5391 GtkWidget *image; | |
9015 | 5392 char *buf; |
5393 | |
5394 gc = l->data; | |
5395 plugin = gc->prpl; | |
5396 | |
9019 | 5397 if (!GAIM_CONNECTION_IS_CONNECTED(gc) || !GAIM_PLUGIN_HAS_ACTIONS(plugin)) |
7620 | 5398 continue; |
5399 | |
5400 account = gaim_connection_get_account(gc); | |
9015 | 5401 buf = g_strconcat(gaim_account_get_username(account), " (", |
5402 plugin->info->name, ")", NULL); | |
7620 | 5403 menuitem = gtk_image_menu_item_new_with_label(buf); |
9015 | 5404 g_free(buf); |
5405 | |
10884 | 5406 pixbuf = gaim_gtk_create_prpl_icon(account); |
9019 | 5407 if (pixbuf) { |
7620 | 5408 scale = gdk_pixbuf_scale_simple(pixbuf, 16, 16, |
5409 GDK_INTERP_BILINEAR); | |
5410 image = gtk_image_new_from_pixbuf(scale); | |
5411 g_object_unref(G_OBJECT(pixbuf)); | |
5412 g_object_unref(G_OBJECT(scale)); | |
5413 gtk_widget_show(image); | |
9015 | 5414 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image); |
7620 | 5415 } |
5416 | |
5417 gtk_menu_shell_append(GTK_MENU_SHELL(protomenu), menuitem); | |
5418 gtk_widget_show(menuitem); | |
5419 | |
5420 submenu = gtk_menu_new(); | |
5421 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); | |
5422 gtk_widget_show(submenu); | |
5423 | |
9015 | 5424 build_plugin_actions(submenu, plugin, gc); |
7620 | 5425 } |
5426 } | |
5427 } | |
8986 | 5428 |
5429 void | |
5430 gaim_gtk_blist_update_plugin_actions(void) | |
5431 { | |
9015 | 5432 GtkWidget *menuitem, *submenu; |
5433 GaimPlugin *plugin = NULL; | |
8986 | 5434 GList *l; |
5435 int count = 0; | |
5436 | |
9019 | 5437 if (pluginmenu == NULL) |
8986 | 5438 return; |
5439 | |
9019 | 5440 /* Clear the old Account Actions menu */ |
9015 | 5441 for (l = gtk_container_get_children(GTK_CONTAINER(pluginmenu)); l; l = l->next) { |
5442 GaimPluginAction *action; | |
8986 | 5443 |
5444 menuitem = l->data; | |
9015 | 5445 action = g_object_get_data(G_OBJECT(menuitem), "plugin_action"); |
5446 g_free(action); | |
8986 | 5447 |
5448 gtk_container_remove(GTK_CONTAINER(pluginmenu), GTK_WIDGET(menuitem)); | |
5449 } | |
5450 | |
9019 | 5451 /* Count the number of plugins with actions */ |
9015 | 5452 for (l = gaim_plugins_get_loaded(); l; l = l->next) { |
5453 plugin = (GaimPlugin *) l->data; | |
5454 | |
9019 | 5455 if (!GAIM_IS_PROTOCOL_PLUGIN(plugin) && GAIM_PLUGIN_HAS_ACTIONS(plugin)) |
5456 count++; | |
5457 | |
5458 /* no need to count past 2, so don't */ | |
5459 if (count > 1) | |
9015 | 5460 break; |
8986 | 5461 } |
5462 | |
5463 if (count == 0) { | |
5464 menuitem = gtk_menu_item_new_with_label(_("No actions available")); | |
5465 gtk_menu_shell_append(GTK_MENU_SHELL(pluginmenu), menuitem); | |
9015 | 5466 gtk_widget_set_sensitive(menuitem, FALSE); |
8986 | 5467 gtk_widget_show(menuitem); |
5468 } | |
9019 | 5469 |
5470 else if (count == 1) { | |
5471 /* Find the one plugin that has actions */ | |
5472 for (l = gaim_plugins_get_loaded(); l; l = l->next) { | |
5473 plugin = (GaimPlugin *) l->data; | |
5474 | |
5475 if (!GAIM_IS_PROTOCOL_PLUGIN(plugin) && GAIM_PLUGIN_HAS_ACTIONS(plugin)) | |
5476 break; | |
5477 } | |
5478 | |
9015 | 5479 build_plugin_actions(pluginmenu, plugin, NULL); |
8986 | 5480 } |
9019 | 5481 |
8986 | 5482 else { |
9015 | 5483 for (l = gaim_plugins_get_loaded(); l; l = l->next) { |
5484 plugin = (GaimPlugin *) l->data; | |
5485 | |
5486 if (GAIM_IS_PROTOCOL_PLUGIN(plugin)) | |
8986 | 5487 continue; |
5488 | |
9019 | 5489 if (!GAIM_PLUGIN_HAS_ACTIONS(plugin)) |
9015 | 5490 continue; |
5491 | |
5492 menuitem = gtk_image_menu_item_new_with_label(plugin->info->name); | |
8986 | 5493 gtk_menu_shell_append(GTK_MENU_SHELL(pluginmenu), menuitem); |
5494 gtk_widget_show(menuitem); | |
5495 | |
5496 submenu = gtk_menu_new(); | |
5497 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); | |
5498 gtk_widget_show(submenu); | |
5499 | |
9015 | 5500 build_plugin_actions(submenu, plugin, NULL); |
8986 | 5501 } |
5502 } | |
5503 } |