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