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