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