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