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