Mercurial > pidgin.yaz
comparison pidgin/gtkft.c @ 15374:5fe8042783c1
Rename gtk/ and libgaim/ to pidgin/ and libpurple/
author | Sean Egan <seanegan@gmail.com> |
---|---|
date | Sat, 20 Jan 2007 02:32:10 +0000 |
parents | |
children | d75099d2567e |
comparison
equal
deleted
inserted
replaced
15373:f79e0f4df793 | 15374:5fe8042783c1 |
---|---|
1 /** | |
2 * @file gtkft.c GTK+ File Transfer UI | |
3 * @ingroup gtkui | |
4 * | |
5 * gaim | |
6 * | |
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. | |
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 #include "internal.h" | |
26 #include "gtkgaim.h" | |
27 | |
28 #include "debug.h" | |
29 #include "notify.h" | |
30 #include "ft.h" | |
31 #include "prpl.h" | |
32 #include "util.h" | |
33 | |
34 #include "gtkcellrendererprogress.h" | |
35 #include "gtkft.h" | |
36 #include "prefs.h" | |
37 #include "gtkexpander.h" | |
38 #include "gaimstock.h" | |
39 #include "gtkutils.h" | |
40 | |
41 #define GAIM_GTKXFER(xfer) \ | |
42 (GaimGtkXferUiData *)(xfer)->ui_data | |
43 | |
44 struct _GaimGtkXferDialog | |
45 { | |
46 gboolean keep_open; | |
47 gboolean auto_clear; | |
48 | |
49 gint num_transfers; | |
50 | |
51 GaimXfer *selected_xfer; | |
52 | |
53 GtkWidget *window; | |
54 GtkWidget *tree; | |
55 GtkListStore *model; | |
56 | |
57 GtkWidget *expander; | |
58 | |
59 GtkWidget *table; | |
60 | |
61 GtkWidget *local_user_desc_label; | |
62 GtkWidget *local_user_label; | |
63 GtkWidget *remote_user_desc_label; | |
64 GtkWidget *remote_user_label; | |
65 GtkWidget *protocol_label; | |
66 GtkWidget *filename_label; | |
67 GtkWidget *localfile_label; | |
68 GtkWidget *status_label; | |
69 GtkWidget *speed_label; | |
70 GtkWidget *time_elapsed_label; | |
71 GtkWidget *time_remaining_label; | |
72 | |
73 GtkWidget *progress; | |
74 | |
75 /* Buttons */ | |
76 GtkWidget *open_button; | |
77 GtkWidget *pause_button; | |
78 GtkWidget *resume_button; | |
79 GtkWidget *remove_button; | |
80 GtkWidget *stop_button; | |
81 GtkWidget *close_button; | |
82 }; | |
83 | |
84 typedef struct | |
85 { | |
86 GtkTreeIter iter; | |
87 time_t last_updated_time; | |
88 gboolean in_list; | |
89 | |
90 char *name; | |
91 | |
92 } GaimGtkXferUiData; | |
93 | |
94 static GaimGtkXferDialog *xfer_dialog = NULL; | |
95 | |
96 enum | |
97 { | |
98 COLUMN_STATUS = 0, | |
99 COLUMN_PROGRESS, | |
100 COLUMN_FILENAME, | |
101 COLUMN_SIZE, | |
102 COLUMN_REMAINING, | |
103 COLUMN_DATA, | |
104 NUM_COLUMNS | |
105 }; | |
106 | |
107 | |
108 /************************************************************************** | |
109 * Utility Functions | |
110 **************************************************************************/ | |
111 static void | |
112 get_xfer_info_strings(GaimXfer *xfer, char **kbsec, char **time_elapsed, | |
113 char **time_remaining) | |
114 { | |
115 GaimGtkXferUiData *data; | |
116 double kb_sent, kb_rem; | |
117 double kbps = 0.0; | |
118 time_t elapsed, now; | |
119 | |
120 data = GAIM_GTKXFER(xfer); | |
121 | |
122 if (xfer->end_time != 0) | |
123 now = xfer->end_time; | |
124 else | |
125 now = time(NULL); | |
126 | |
127 kb_sent = gaim_xfer_get_bytes_sent(xfer) / 1024.0; | |
128 kb_rem = gaim_xfer_get_bytes_remaining(xfer) / 1024.0; | |
129 elapsed = (xfer->start_time > 0 ? now - xfer->start_time : 0); | |
130 kbps = (elapsed > 0 ? (kb_sent / elapsed) : 0); | |
131 | |
132 if (kbsec != NULL) { | |
133 *kbsec = g_strdup_printf(_("%.2f KB/s"), kbps); | |
134 } | |
135 | |
136 if (time_elapsed != NULL) | |
137 { | |
138 int h, m, s; | |
139 int secs_elapsed; | |
140 | |
141 if (xfer->start_time > 0) | |
142 { | |
143 secs_elapsed = now - xfer->start_time; | |
144 | |
145 h = secs_elapsed / 3600; | |
146 m = (secs_elapsed % 3600) / 60; | |
147 s = secs_elapsed % 60; | |
148 | |
149 *time_elapsed = g_strdup_printf("%d:%02d:%02d", h, m, s); | |
150 } | |
151 else | |
152 { | |
153 *time_elapsed = g_strdup(_("Not started")); | |
154 } | |
155 } | |
156 | |
157 if (time_remaining != NULL) { | |
158 if (gaim_xfer_get_size(xfer) == 0) { | |
159 *time_remaining = g_strdup(_("Unknown")); | |
160 } | |
161 else if (gaim_xfer_is_completed(xfer)) { | |
162 *time_remaining = g_strdup(_("Finished")); | |
163 } | |
164 else if (gaim_xfer_is_canceled(xfer)) { | |
165 *time_remaining = g_strdup(_("Canceled")); | |
166 } | |
167 else if (kb_sent <= 0) { | |
168 *time_remaining = g_strdup(_("Waiting for transfer to begin")); | |
169 } | |
170 else { | |
171 int h, m, s; | |
172 int secs_remaining; | |
173 | |
174 secs_remaining = (int)(kb_rem / kbps); | |
175 | |
176 h = secs_remaining / 3600; | |
177 m = (secs_remaining % 3600) / 60; | |
178 s = secs_remaining % 60; | |
179 | |
180 *time_remaining = g_strdup_printf("%d:%02d:%02d", h, m, s); | |
181 } | |
182 } | |
183 } | |
184 | |
185 static void | |
186 update_title_progress(GaimGtkXferDialog *dialog) | |
187 { | |
188 gboolean valid; | |
189 GtkTreeIter iter; | |
190 int num_active_xfers = 0; | |
191 guint64 total_bytes_xferred = 0; | |
192 guint64 total_file_size = 0; | |
193 | |
194 if (dialog->window == NULL) | |
195 return; | |
196 | |
197 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(dialog->model), &iter); | |
198 | |
199 /* Find all active transfers */ | |
200 while (valid) { | |
201 GValue val; | |
202 GaimXfer *xfer = NULL; | |
203 | |
204 val.g_type = 0; | |
205 gtk_tree_model_get_value(GTK_TREE_MODEL(dialog->model), | |
206 &iter, COLUMN_DATA, &val); | |
207 | |
208 xfer = g_value_get_pointer(&val); | |
209 if (gaim_xfer_get_status(xfer) == GAIM_XFER_STATUS_STARTED) { | |
210 num_active_xfers++; | |
211 total_bytes_xferred += gaim_xfer_get_bytes_sent(xfer); | |
212 total_file_size += gaim_xfer_get_size(xfer); | |
213 } | |
214 | |
215 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(dialog->model), &iter); | |
216 } | |
217 | |
218 /* Update the title */ | |
219 if (num_active_xfers > 0) | |
220 { | |
221 gchar *title; | |
222 int total_pct = 0; | |
223 | |
224 if (total_file_size > 0) { | |
225 total_pct = 100 * total_bytes_xferred / total_file_size; | |
226 } | |
227 | |
228 title = g_strdup_printf(_("File Transfers - %d%% of %d files"), | |
229 total_pct, num_active_xfers); | |
230 gtk_window_set_title(GTK_WINDOW(dialog->window), title); | |
231 g_free(title); | |
232 } else { | |
233 gtk_window_set_title(GTK_WINDOW(dialog->window), _("File Transfers")); | |
234 } | |
235 } | |
236 | |
237 static void | |
238 update_detailed_info(GaimGtkXferDialog *dialog, GaimXfer *xfer) | |
239 { | |
240 GaimGtkXferUiData *data; | |
241 char *kbsec, *time_elapsed, *time_remaining; | |
242 char *status, *utf8; | |
243 | |
244 if (dialog == NULL || xfer == NULL) | |
245 return; | |
246 | |
247 data = GAIM_GTKXFER(xfer); | |
248 | |
249 get_xfer_info_strings(xfer, &kbsec, &time_elapsed, &time_remaining); | |
250 | |
251 status = g_strdup_printf("%ld%% (%ld of %ld bytes)", | |
252 (unsigned long)(gaim_xfer_get_progress(xfer)*100), | |
253 (unsigned long)gaim_xfer_get_bytes_sent(xfer), | |
254 (unsigned long)gaim_xfer_get_size(xfer)); | |
255 | |
256 if (gaim_xfer_is_completed(xfer)) { | |
257 | |
258 GdkPixbuf *pixbuf = NULL; | |
259 | |
260 pixbuf = gtk_widget_render_icon(xfer_dialog->window, | |
261 GAIM_STOCK_FILE_DONE, | |
262 GTK_ICON_SIZE_MENU, NULL); | |
263 | |
264 gtk_list_store_set(GTK_LIST_STORE(xfer_dialog->model), &data->iter, | |
265 COLUMN_STATUS, pixbuf, | |
266 -1); | |
267 | |
268 g_object_unref(pixbuf); | |
269 } | |
270 | |
271 if (gaim_xfer_get_type(xfer) == GAIM_XFER_RECEIVE) { | |
272 gtk_label_set_markup(GTK_LABEL(dialog->local_user_desc_label), | |
273 _("<b>Receiving As:</b>")); | |
274 gtk_label_set_markup(GTK_LABEL(dialog->remote_user_desc_label), | |
275 _("<b>Receiving From:</b>")); | |
276 } | |
277 else { | |
278 gtk_label_set_markup(GTK_LABEL(dialog->remote_user_desc_label), | |
279 _("<b>Sending To:</b>")); | |
280 gtk_label_set_markup(GTK_LABEL(dialog->local_user_desc_label), | |
281 _("<b>Sending As:</b>")); | |
282 } | |
283 | |
284 gtk_label_set_text(GTK_LABEL(dialog->local_user_label), | |
285 gaim_account_get_username(xfer->account)); | |
286 gtk_label_set_text(GTK_LABEL(dialog->remote_user_label), xfer->who); | |
287 gtk_label_set_text(GTK_LABEL(dialog->protocol_label), | |
288 gaim_account_get_protocol_name(xfer->account)); | |
289 | |
290 if (gaim_xfer_get_type(xfer) == GAIM_XFER_RECEIVE) { | |
291 gtk_label_set_text(GTK_LABEL(dialog->filename_label), | |
292 gaim_xfer_get_filename(xfer)); | |
293 } else { | |
294 char *tmp; | |
295 | |
296 tmp = g_path_get_basename(gaim_xfer_get_local_filename(xfer)); | |
297 utf8 = g_filename_to_utf8(tmp, -1, NULL, NULL, NULL); | |
298 g_free(tmp); | |
299 | |
300 gtk_label_set_text(GTK_LABEL(dialog->filename_label), utf8); | |
301 g_free(utf8); | |
302 } | |
303 | |
304 utf8 = g_filename_to_utf8((gaim_xfer_get_local_filename(xfer)), -1, NULL, NULL, NULL); | |
305 gtk_label_set_text(GTK_LABEL(dialog->localfile_label), utf8); | |
306 g_free(utf8); | |
307 | |
308 gtk_label_set_text(GTK_LABEL(dialog->status_label), status); | |
309 | |
310 gtk_label_set_text(GTK_LABEL(dialog->speed_label), kbsec); | |
311 gtk_label_set_text(GTK_LABEL(dialog->time_elapsed_label), time_elapsed); | |
312 gtk_label_set_text(GTK_LABEL(dialog->time_remaining_label), | |
313 time_remaining); | |
314 | |
315 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(dialog->progress), | |
316 gaim_xfer_get_progress(xfer)); | |
317 | |
318 g_free(kbsec); | |
319 g_free(time_elapsed); | |
320 g_free(time_remaining); | |
321 g_free(status); | |
322 } | |
323 | |
324 static void | |
325 update_buttons(GaimGtkXferDialog *dialog, GaimXfer *xfer) | |
326 { | |
327 if (dialog->selected_xfer == NULL) { | |
328 gtk_widget_set_sensitive(dialog->expander, FALSE); | |
329 gtk_widget_set_sensitive(dialog->open_button, FALSE); | |
330 gtk_widget_set_sensitive(dialog->pause_button, FALSE); | |
331 gtk_widget_set_sensitive(dialog->resume_button, FALSE); | |
332 gtk_widget_set_sensitive(dialog->stop_button, FALSE); | |
333 | |
334 gtk_widget_show(dialog->stop_button); | |
335 gtk_widget_hide(dialog->remove_button); | |
336 | |
337 return; | |
338 } | |
339 | |
340 if (dialog->selected_xfer != xfer) | |
341 return; | |
342 | |
343 if (gaim_xfer_is_completed(xfer)) { | |
344 gtk_widget_hide(dialog->stop_button); | |
345 gtk_widget_show(dialog->remove_button); | |
346 | |
347 #ifdef _WIN32 | |
348 /* If using Win32... */ | |
349 if (gaim_xfer_get_type(xfer) == GAIM_XFER_RECEIVE) { | |
350 gtk_widget_set_sensitive(dialog->open_button, TRUE); | |
351 } else { | |
352 gtk_widget_set_sensitive(dialog->open_button, FALSE); | |
353 } | |
354 #else | |
355 if (gaim_xfer_get_type(xfer) == GAIM_XFER_RECEIVE) { | |
356 gtk_widget_set_sensitive(dialog->open_button, TRUE); | |
357 } else { | |
358 gtk_widget_set_sensitive (dialog->open_button, FALSE); | |
359 } | |
360 #endif | |
361 gtk_widget_set_sensitive(dialog->pause_button, FALSE); | |
362 gtk_widget_set_sensitive(dialog->resume_button, FALSE); | |
363 | |
364 gtk_widget_set_sensitive(dialog->remove_button, TRUE); | |
365 } else if (gaim_xfer_is_canceled(xfer)) { | |
366 gtk_widget_hide(dialog->stop_button); | |
367 gtk_widget_show(dialog->remove_button); | |
368 | |
369 gtk_widget_set_sensitive(dialog->open_button, FALSE); | |
370 gtk_widget_set_sensitive(dialog->pause_button, FALSE); | |
371 gtk_widget_set_sensitive(dialog->resume_button, FALSE); | |
372 | |
373 gtk_widget_set_sensitive(dialog->remove_button, TRUE); | |
374 } else { | |
375 gtk_widget_show(dialog->stop_button); | |
376 gtk_widget_hide(dialog->remove_button); | |
377 | |
378 gtk_widget_set_sensitive(dialog->open_button, FALSE); | |
379 | |
380 /* TODO: If the transfer can pause, blah blah */ | |
381 gtk_widget_set_sensitive(dialog->pause_button, FALSE); | |
382 gtk_widget_set_sensitive(dialog->resume_button, FALSE); | |
383 gtk_widget_set_sensitive(dialog->stop_button, TRUE); | |
384 } | |
385 } | |
386 | |
387 static void | |
388 ensure_row_selected(GaimGtkXferDialog *dialog) | |
389 { | |
390 GtkTreeIter iter; | |
391 GtkTreeSelection *selection; | |
392 | |
393 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->tree)); | |
394 | |
395 if (gtk_tree_selection_get_selected(selection, NULL, &iter)) | |
396 return; | |
397 | |
398 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(dialog->model), &iter)) | |
399 gtk_tree_selection_select_iter(selection, &iter); | |
400 } | |
401 | |
402 /************************************************************************** | |
403 * Callbacks | |
404 **************************************************************************/ | |
405 static gint | |
406 delete_win_cb(GtkWidget *w, GdkEventAny *e, gpointer d) | |
407 { | |
408 GaimGtkXferDialog *dialog; | |
409 | |
410 dialog = (GaimGtkXferDialog *)d; | |
411 | |
412 gaim_gtkxfer_dialog_hide(dialog); | |
413 | |
414 return TRUE; | |
415 } | |
416 | |
417 static void | |
418 toggle_keep_open_cb(GtkWidget *w, GaimGtkXferDialog *dialog) | |
419 { | |
420 dialog->keep_open = !dialog->keep_open; | |
421 gaim_prefs_set_bool("/gaim/gtk/filetransfer/keep_open", | |
422 dialog->keep_open); | |
423 } | |
424 | |
425 static void | |
426 toggle_clear_finished_cb(GtkWidget *w, GaimGtkXferDialog *dialog) | |
427 { | |
428 dialog->auto_clear = !dialog->auto_clear; | |
429 gaim_prefs_set_bool("/gaim/gtk/filetransfer/clear_finished", | |
430 dialog->auto_clear); | |
431 } | |
432 | |
433 static void | |
434 selection_changed_cb(GtkTreeSelection *selection, GaimGtkXferDialog *dialog) | |
435 { | |
436 GtkTreeIter iter; | |
437 GaimXfer *xfer = NULL; | |
438 | |
439 if (gtk_tree_selection_get_selected(selection, NULL, &iter)) { | |
440 GValue val; | |
441 | |
442 gtk_widget_set_sensitive(dialog->expander, TRUE); | |
443 | |
444 val.g_type = 0; | |
445 gtk_tree_model_get_value(GTK_TREE_MODEL(dialog->model), | |
446 &iter, COLUMN_DATA, &val); | |
447 | |
448 xfer = g_value_get_pointer(&val); | |
449 | |
450 update_detailed_info(dialog, xfer); | |
451 | |
452 dialog->selected_xfer = xfer; | |
453 } | |
454 else { | |
455 gtk_expander_set_expanded(GTK_EXPANDER(dialog->expander), | |
456 FALSE); | |
457 | |
458 gtk_widget_set_sensitive(dialog->expander, FALSE); | |
459 | |
460 dialog->selected_xfer = NULL; | |
461 } | |
462 | |
463 update_buttons(dialog, xfer); | |
464 } | |
465 | |
466 static void | |
467 open_button_cb(GtkButton *button, GaimGtkXferDialog *dialog) | |
468 { | |
469 #ifdef _WIN32 | |
470 /* If using Win32... */ | |
471 int code; | |
472 if (G_WIN32_HAVE_WIDECHAR_API ()) { | |
473 wchar_t *wc_filename = g_utf8_to_utf16( | |
474 gaim_xfer_get_local_filename( | |
475 dialog->selected_xfer), | |
476 -1, NULL, NULL, NULL); | |
477 | |
478 code = (int) ShellExecuteW(NULL, NULL, wc_filename, NULL, NULL, | |
479 SW_SHOW); | |
480 | |
481 g_free(wc_filename); | |
482 } else { | |
483 char *l_filename = g_locale_from_utf8( | |
484 gaim_xfer_get_local_filename( | |
485 dialog->selected_xfer), | |
486 -1, NULL, NULL, NULL); | |
487 | |
488 code = (int) ShellExecuteA(NULL, NULL, l_filename, NULL, NULL, | |
489 SW_SHOW); | |
490 | |
491 g_free(l_filename); | |
492 } | |
493 | |
494 if (code == SE_ERR_ASSOCINCOMPLETE || code == SE_ERR_NOASSOC) | |
495 { | |
496 gaim_notify_error(dialog, NULL, | |
497 _("There is no application configured to open this type of file."), NULL); | |
498 } | |
499 else if (code < 32) | |
500 { | |
501 gaim_notify_error(dialog, NULL, | |
502 _("An error occurred while opening the file."), NULL); | |
503 gaim_debug_warning("ft", "filename: %s; code: %d\n", | |
504 gaim_xfer_get_local_filename(dialog->selected_xfer), code); | |
505 } | |
506 #else | |
507 const char *filename = gaim_xfer_get_local_filename(dialog->selected_xfer); | |
508 char *command = NULL; | |
509 char *tmp = NULL; | |
510 GError *error = NULL; | |
511 | |
512 if (gaim_running_gnome()) | |
513 { | |
514 char *escaped = g_shell_quote(filename); | |
515 command = g_strdup_printf("gnome-open %s", escaped); | |
516 g_free(escaped); | |
517 } | |
518 else if (gaim_running_kde()) | |
519 { | |
520 char *escaped = g_shell_quote(filename); | |
521 | |
522 if (gaim_str_has_suffix(filename, ".desktop")) | |
523 command = g_strdup_printf("kfmclient openURL %s 'text/plain'", escaped); | |
524 else | |
525 command = g_strdup_printf("kfmclient openURL %s", escaped); | |
526 g_free(escaped); | |
527 } | |
528 else | |
529 { | |
530 gaim_notify_uri(NULL, filename); | |
531 return; | |
532 } | |
533 | |
534 if (gaim_program_is_valid(command)) | |
535 { | |
536 gint exit_status; | |
537 if (!g_spawn_command_line_sync(command, NULL, NULL, &exit_status, &error)) | |
538 { | |
539 tmp = g_strdup_printf(_("Error launching %s: %s"), | |
540 gaim_xfer_get_local_filename(dialog->selected_xfer), | |
541 error->message); | |
542 gaim_notify_error(dialog, NULL, _("Unable to open file."), tmp); | |
543 g_free(tmp); | |
544 g_error_free(error); | |
545 } | |
546 if (exit_status != 0) | |
547 { | |
548 char *primary = g_strdup_printf(_("Error running %s"), command); | |
549 char *secondary = g_strdup_printf(_("Process returned error code %d"), | |
550 exit_status); | |
551 gaim_notify_error(dialog, NULL, primary, secondary); | |
552 g_free(tmp); | |
553 } | |
554 } | |
555 #endif | |
556 } | |
557 | |
558 static void | |
559 pause_button_cb(GtkButton *button, GaimGtkXferDialog *dialog) | |
560 { | |
561 } | |
562 | |
563 static void | |
564 resume_button_cb(GtkButton *button, GaimGtkXferDialog *dialog) | |
565 { | |
566 } | |
567 | |
568 static void | |
569 remove_button_cb(GtkButton *button, GaimGtkXferDialog *dialog) | |
570 { | |
571 gaim_gtkxfer_dialog_remove_xfer(dialog, dialog->selected_xfer); | |
572 } | |
573 | |
574 static void | |
575 stop_button_cb(GtkButton *button, GaimGtkXferDialog *dialog) | |
576 { | |
577 gaim_xfer_cancel_local(dialog->selected_xfer); | |
578 } | |
579 | |
580 static void | |
581 close_button_cb(GtkButton *button, GaimGtkXferDialog *dialog) | |
582 { | |
583 gaim_gtkxfer_dialog_hide(dialog); | |
584 } | |
585 | |
586 | |
587 /************************************************************************** | |
588 * Dialog Building Functions | |
589 **************************************************************************/ | |
590 static GtkWidget * | |
591 setup_tree(GaimGtkXferDialog *dialog) | |
592 { | |
593 GtkWidget *sw; | |
594 GtkWidget *tree; | |
595 GtkListStore *model; | |
596 GtkCellRenderer *renderer; | |
597 GtkTreeViewColumn *column; | |
598 GtkTreeSelection *selection; | |
599 | |
600 /* Create the scrolled window. */ | |
601 sw = gtk_scrolled_window_new(0, 0); | |
602 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), | |
603 GTK_SHADOW_IN); | |
604 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), | |
605 GTK_POLICY_AUTOMATIC, | |
606 GTK_POLICY_AUTOMATIC); | |
607 gtk_widget_show(sw); | |
608 | |
609 /* Build the tree model */ | |
610 /* Transfer type, Progress Bar, Filename, Size, Remaining */ | |
611 model = gtk_list_store_new(NUM_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_DOUBLE, | |
612 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, | |
613 G_TYPE_POINTER); | |
614 dialog->model = model; | |
615 | |
616 /* Create the treeview */ | |
617 dialog->tree = tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model)); | |
618 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(tree), TRUE); | |
619 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree)); | |
620 /* gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE); */ | |
621 | |
622 gtk_widget_show(tree); | |
623 | |
624 g_signal_connect(G_OBJECT(selection), "changed", | |
625 G_CALLBACK(selection_changed_cb), dialog); | |
626 | |
627 g_object_unref(G_OBJECT(model)); | |
628 | |
629 | |
630 /* Columns */ | |
631 | |
632 /* Transfer Type column */ | |
633 renderer = gtk_cell_renderer_pixbuf_new(); | |
634 column = gtk_tree_view_column_new_with_attributes(NULL, renderer, | |
635 "pixbuf", COLUMN_STATUS, NULL); | |
636 gtk_tree_view_column_set_sizing(GTK_TREE_VIEW_COLUMN(column), | |
637 GTK_TREE_VIEW_COLUMN_FIXED); | |
638 gtk_tree_view_column_set_fixed_width(GTK_TREE_VIEW_COLUMN(column), 25); | |
639 gtk_tree_view_column_set_resizable(GTK_TREE_VIEW_COLUMN(column), TRUE); | |
640 gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); | |
641 | |
642 /* Progress bar column */ | |
643 renderer = gaim_gtk_cell_renderer_progress_new(); | |
644 column = gtk_tree_view_column_new_with_attributes(_("Progress"), renderer, | |
645 "percentage", COLUMN_PROGRESS, NULL); | |
646 gtk_tree_view_column_set_resizable(GTK_TREE_VIEW_COLUMN(column), TRUE); | |
647 gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); | |
648 | |
649 /* Filename column */ | |
650 renderer = gtk_cell_renderer_text_new(); | |
651 column = gtk_tree_view_column_new_with_attributes(_("Filename"), renderer, | |
652 "text", COLUMN_FILENAME, NULL); | |
653 gtk_tree_view_column_set_resizable(GTK_TREE_VIEW_COLUMN(column), TRUE); | |
654 gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); | |
655 | |
656 /* File Size column */ | |
657 renderer = gtk_cell_renderer_text_new(); | |
658 column = gtk_tree_view_column_new_with_attributes(_("Size"), renderer, | |
659 "text", COLUMN_SIZE, NULL); | |
660 gtk_tree_view_column_set_resizable(GTK_TREE_VIEW_COLUMN(column), TRUE); | |
661 gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); | |
662 | |
663 /* Bytes Remaining column */ | |
664 renderer = gtk_cell_renderer_text_new(); | |
665 column = gtk_tree_view_column_new_with_attributes(_("Remaining"), | |
666 renderer, "text", COLUMN_REMAINING, NULL); | |
667 gtk_tree_view_column_set_resizable(GTK_TREE_VIEW_COLUMN(column), TRUE); | |
668 gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); | |
669 | |
670 gtk_tree_view_columns_autosize(GTK_TREE_VIEW(tree)); | |
671 | |
672 gtk_container_add(GTK_CONTAINER(sw), tree); | |
673 gtk_widget_show(tree); | |
674 | |
675 return sw; | |
676 } | |
677 | |
678 static GtkWidget * | |
679 make_info_table(GaimGtkXferDialog *dialog) | |
680 { | |
681 GtkWidget *table; | |
682 GtkWidget *label; | |
683 int i; | |
684 | |
685 struct | |
686 { | |
687 GtkWidget **desc_label; | |
688 GtkWidget **val_label; | |
689 const char *desc; | |
690 | |
691 } labels[] = | |
692 { | |
693 { &dialog->local_user_desc_label, &dialog->local_user_label, NULL }, | |
694 { &dialog->remote_user_desc_label, &dialog->remote_user_label, NULL }, | |
695 { &label, &dialog->protocol_label, _("Protocol:") }, | |
696 { &label, &dialog->filename_label, _("Filename:") }, | |
697 { &label, &dialog->localfile_label, _("Local File:") }, | |
698 { &label, &dialog->status_label, _("Status:") }, | |
699 { &label, &dialog->speed_label, _("Speed:") }, | |
700 { &label, &dialog->time_elapsed_label, _("Time Elapsed:") }, | |
701 { &label, &dialog->time_remaining_label, _("Time Remaining:") } | |
702 }; | |
703 | |
704 /* Setup the initial table */ | |
705 dialog->table = table = gtk_table_new(9, 2, FALSE); | |
706 gtk_table_set_row_spacings(GTK_TABLE(table), GAIM_HIG_BOX_SPACE); | |
707 gtk_table_set_col_spacings(GTK_TABLE(table), GAIM_HIG_BOX_SPACE); | |
708 | |
709 /* Setup the labels */ | |
710 for (i = 0; i < sizeof(labels) / sizeof(*labels); i++) { | |
711 GtkWidget *label; | |
712 char buf[256]; | |
713 | |
714 g_snprintf(buf, sizeof(buf), "<b>%s</b>", | |
715 labels[i].desc != NULL ? labels[i].desc : ""); | |
716 | |
717 *labels[i].desc_label = label = gtk_label_new(NULL); | |
718 gtk_label_set_markup(GTK_LABEL(label), buf); | |
719 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT); | |
720 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
721 gtk_table_attach(GTK_TABLE(table), label, 0, 1, i, i + 1, | |
722 GTK_FILL, 0, 0, 0); | |
723 gtk_widget_show(label); | |
724 | |
725 *labels[i].val_label = label = gtk_label_new(NULL); | |
726 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | |
727 gtk_table_attach(GTK_TABLE(table), label, 1, 2, i, i + 1, | |
728 GTK_FILL | GTK_EXPAND, 0, 0, 0); | |
729 gtk_widget_show(label); | |
730 } | |
731 | |
732 /* Setup the progress bar */ | |
733 dialog->progress = gtk_progress_bar_new(); | |
734 gtk_table_attach(GTK_TABLE(table), dialog->progress, 0, 2, 8, 9, | |
735 GTK_FILL, GTK_FILL, 0, 0); | |
736 gtk_widget_show(dialog->progress); | |
737 | |
738 return table; | |
739 } | |
740 | |
741 GaimGtkXferDialog * | |
742 gaim_gtkxfer_dialog_new(void) | |
743 { | |
744 GaimGtkXferDialog *dialog; | |
745 GtkWidget *window; | |
746 GtkWidget *vbox1, *vbox2; | |
747 GtkWidget *bbox; | |
748 GtkWidget *sw; | |
749 GtkWidget *button; | |
750 GtkWidget *expander; | |
751 GtkWidget *table; | |
752 GtkWidget *checkbox; | |
753 | |
754 dialog = g_new0(GaimGtkXferDialog, 1); | |
755 dialog->keep_open = | |
756 gaim_prefs_get_bool("/gaim/gtk/filetransfer/keep_open"); | |
757 dialog->auto_clear = | |
758 gaim_prefs_get_bool("/gaim/gtk/filetransfer/clear_finished"); | |
759 | |
760 /* Create the window. */ | |
761 dialog->window = window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | |
762 gtk_window_set_role(GTK_WINDOW(window), "file transfer"); | |
763 gtk_window_set_title(GTK_WINDOW(window), _("File Transfers")); | |
764 gtk_container_set_border_width(GTK_CONTAINER(window), GAIM_HIG_BORDER); | |
765 | |
766 g_signal_connect(G_OBJECT(window), "delete_event", | |
767 G_CALLBACK(delete_win_cb), dialog); | |
768 | |
769 /* Create the parent vbox for everything. */ | |
770 vbox1 = gtk_vbox_new(FALSE, GAIM_HIG_BORDER); | |
771 gtk_container_add(GTK_CONTAINER(window), vbox1); | |
772 gtk_widget_show(vbox1); | |
773 | |
774 /* Create the main vbox for top half of the window. */ | |
775 vbox2 = gtk_vbox_new(FALSE, GAIM_HIG_BOX_SPACE); | |
776 gtk_box_pack_start(GTK_BOX(vbox1), vbox2, TRUE, TRUE, 0); | |
777 gtk_widget_show(vbox2); | |
778 | |
779 /* Setup the listbox */ | |
780 sw = setup_tree(dialog); | |
781 gtk_box_pack_start(GTK_BOX(vbox2), sw, TRUE, TRUE, 0); | |
782 gtk_widget_set_size_request(sw,-1, 140); | |
783 | |
784 /* "Close this window when all transfers finish" */ | |
785 checkbox = gtk_check_button_new_with_mnemonic( | |
786 _("Close this window when all transfers _finish")); | |
787 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbox), | |
788 !dialog->keep_open); | |
789 g_signal_connect(G_OBJECT(checkbox), "toggled", | |
790 G_CALLBACK(toggle_keep_open_cb), dialog); | |
791 gtk_box_pack_start(GTK_BOX(vbox2), checkbox, FALSE, FALSE, 0); | |
792 gtk_widget_show(checkbox); | |
793 | |
794 /* "Clear finished transfers" */ | |
795 checkbox = gtk_check_button_new_with_mnemonic( | |
796 _("C_lear finished transfers")); | |
797 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbox), | |
798 dialog->auto_clear); | |
799 g_signal_connect(G_OBJECT(checkbox), "toggled", | |
800 G_CALLBACK(toggle_clear_finished_cb), dialog); | |
801 gtk_box_pack_start(GTK_BOX(vbox2), checkbox, FALSE, FALSE, 0); | |
802 gtk_widget_show(checkbox); | |
803 | |
804 /* "Download Details" arrow */ | |
805 expander = gtk_expander_new_with_mnemonic(_("File transfer _details")); | |
806 dialog->expander = expander; | |
807 gtk_box_pack_start(GTK_BOX(vbox2), expander, FALSE, FALSE, 0); | |
808 gtk_widget_show(expander); | |
809 | |
810 gtk_widget_set_sensitive(expander, FALSE); | |
811 | |
812 /* The table of information. */ | |
813 table = make_info_table(dialog); | |
814 gtk_container_add(GTK_CONTAINER(expander), table); | |
815 gtk_widget_show(table); | |
816 | |
817 /* Now the button box for the buttons */ | |
818 bbox = gtk_hbutton_box_new(); | |
819 gtk_box_set_spacing(GTK_BOX(bbox), GAIM_HIG_BOX_SPACE); | |
820 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); | |
821 gtk_box_pack_end(GTK_BOX(vbox1), bbox, FALSE, TRUE, 0); | |
822 gtk_widget_show(bbox); | |
823 | |
824 /* Open button */ | |
825 button = gtk_button_new_from_stock(GTK_STOCK_OPEN); | |
826 gtk_widget_set_sensitive(button, FALSE); | |
827 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); | |
828 gtk_widget_show(button); | |
829 dialog->open_button = button; | |
830 | |
831 g_signal_connect(G_OBJECT(button), "clicked", | |
832 G_CALLBACK(open_button_cb), dialog); | |
833 | |
834 /* Pause button */ | |
835 button = gtk_button_new_with_mnemonic(_("_Pause")); | |
836 gtk_widget_set_sensitive(button, FALSE); | |
837 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); | |
838 gtk_widget_show(button); | |
839 dialog->pause_button = button; | |
840 | |
841 g_signal_connect(G_OBJECT(button), "clicked", | |
842 G_CALLBACK(pause_button_cb), dialog); | |
843 | |
844 /* Resume button */ | |
845 button = gtk_button_new_with_mnemonic(_("_Resume")); | |
846 gtk_widget_set_sensitive(button, FALSE); | |
847 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); | |
848 gtk_widget_show(button); | |
849 dialog->resume_button = button; | |
850 | |
851 g_signal_connect(G_OBJECT(button), "clicked", | |
852 G_CALLBACK(resume_button_cb), dialog); | |
853 | |
854 /* Remove button */ | |
855 button = gtk_button_new_from_stock(GTK_STOCK_REMOVE); | |
856 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); | |
857 gtk_widget_hide(button); | |
858 dialog->remove_button = button; | |
859 | |
860 g_signal_connect(G_OBJECT(button), "clicked", | |
861 G_CALLBACK(remove_button_cb), dialog); | |
862 | |
863 /* Stop button */ | |
864 button = gtk_button_new_from_stock(GTK_STOCK_STOP); | |
865 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); | |
866 gtk_widget_show(button); | |
867 gtk_widget_set_sensitive(button, FALSE); | |
868 dialog->stop_button = button; | |
869 | |
870 g_signal_connect(G_OBJECT(button), "clicked", | |
871 G_CALLBACK(stop_button_cb), dialog); | |
872 | |
873 /* Close button */ | |
874 button = gtk_button_new_from_stock(GTK_STOCK_CLOSE); | |
875 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); | |
876 gtk_widget_show(button); | |
877 dialog->close_button = button; | |
878 | |
879 g_signal_connect(G_OBJECT(button), "clicked", | |
880 G_CALLBACK(close_button_cb), dialog); | |
881 | |
882 #ifdef _WIN32 | |
883 g_signal_connect(G_OBJECT(dialog->window), "show", | |
884 G_CALLBACK(gtkwgaim_ensure_onscreen), dialog->window); | |
885 #endif | |
886 | |
887 return dialog; | |
888 } | |
889 | |
890 void | |
891 gaim_gtkxfer_dialog_destroy(GaimGtkXferDialog *dialog) | |
892 { | |
893 g_return_if_fail(dialog != NULL); | |
894 | |
895 gaim_notify_close_with_handle(dialog); | |
896 | |
897 gtk_widget_destroy(dialog->window); | |
898 | |
899 g_free(dialog); | |
900 } | |
901 | |
902 void | |
903 gaim_gtkxfer_dialog_show(GaimGtkXferDialog *dialog) | |
904 { | |
905 GaimGtkXferDialog *tmp; | |
906 | |
907 if (dialog == NULL) { | |
908 tmp = gaim_get_gtkxfer_dialog(); | |
909 | |
910 if (tmp == NULL) { | |
911 tmp = gaim_gtkxfer_dialog_new(); | |
912 gaim_set_gtkxfer_dialog(tmp); | |
913 } | |
914 | |
915 gtk_widget_show(tmp->window); | |
916 } else { | |
917 gtk_widget_show(dialog->window); | |
918 } | |
919 } | |
920 | |
921 void | |
922 gaim_gtkxfer_dialog_hide(GaimGtkXferDialog *dialog) | |
923 { | |
924 g_return_if_fail(dialog != NULL); | |
925 | |
926 gaim_notify_close_with_handle(dialog); | |
927 | |
928 gtk_widget_hide(dialog->window); | |
929 } | |
930 | |
931 void | |
932 gaim_gtkxfer_dialog_add_xfer(GaimGtkXferDialog *dialog, GaimXfer *xfer) | |
933 { | |
934 GaimGtkXferUiData *data; | |
935 GaimXferType type; | |
936 GdkPixbuf *pixbuf; | |
937 char *size_str, *remaining_str; | |
938 char *lfilename, *utf8; | |
939 | |
940 g_return_if_fail(dialog != NULL); | |
941 g_return_if_fail(xfer != NULL); | |
942 | |
943 gaim_xfer_ref(xfer); | |
944 | |
945 data = GAIM_GTKXFER(xfer); | |
946 data->in_list = TRUE; | |
947 | |
948 gaim_gtkxfer_dialog_show(dialog); | |
949 | |
950 data->last_updated_time = 0; | |
951 | |
952 type = gaim_xfer_get_type(xfer); | |
953 | |
954 size_str = gaim_str_size_to_units(gaim_xfer_get_size(xfer)); | |
955 remaining_str = gaim_str_size_to_units(gaim_xfer_get_bytes_remaining(xfer)); | |
956 | |
957 pixbuf = gtk_widget_render_icon(dialog->window, | |
958 (type == GAIM_XFER_RECEIVE | |
959 ? GAIM_STOCK_DOWNLOAD | |
960 : GAIM_STOCK_UPLOAD), | |
961 GTK_ICON_SIZE_MENU, NULL); | |
962 | |
963 gtk_list_store_append(dialog->model, &data->iter); | |
964 lfilename = g_path_get_basename(gaim_xfer_get_local_filename(xfer)); | |
965 utf8 = g_filename_to_utf8(lfilename, -1, NULL, NULL, NULL); | |
966 g_free(lfilename); | |
967 lfilename = utf8; | |
968 gtk_list_store_set(dialog->model, &data->iter, | |
969 COLUMN_STATUS, pixbuf, | |
970 COLUMN_PROGRESS, 0.0, | |
971 COLUMN_FILENAME, (type == GAIM_XFER_RECEIVE) | |
972 ? gaim_xfer_get_filename(xfer) | |
973 : lfilename, | |
974 COLUMN_SIZE, size_str, | |
975 COLUMN_REMAINING, _("Waiting for transfer to begin"), | |
976 COLUMN_DATA, xfer, | |
977 -1); | |
978 g_free(lfilename); | |
979 | |
980 gtk_tree_view_columns_autosize(GTK_TREE_VIEW(dialog->tree)); | |
981 | |
982 g_object_unref(pixbuf); | |
983 | |
984 g_free(size_str); | |
985 g_free(remaining_str); | |
986 | |
987 dialog->num_transfers++; | |
988 | |
989 ensure_row_selected(dialog); | |
990 update_title_progress(dialog); | |
991 } | |
992 | |
993 void | |
994 gaim_gtkxfer_dialog_remove_xfer(GaimGtkXferDialog *dialog, | |
995 GaimXfer *xfer) | |
996 { | |
997 GaimGtkXferUiData *data; | |
998 | |
999 g_return_if_fail(dialog != NULL); | |
1000 g_return_if_fail(xfer != NULL); | |
1001 | |
1002 data = GAIM_GTKXFER(xfer); | |
1003 | |
1004 if (data == NULL) | |
1005 return; | |
1006 | |
1007 if (!data->in_list) | |
1008 return; | |
1009 | |
1010 data->in_list = FALSE; | |
1011 | |
1012 gtk_list_store_remove(GTK_LIST_STORE(dialog->model), &data->iter); | |
1013 | |
1014 dialog->num_transfers--; | |
1015 | |
1016 ensure_row_selected(dialog); | |
1017 | |
1018 update_title_progress(dialog); | |
1019 gaim_xfer_unref(xfer); | |
1020 } | |
1021 | |
1022 void | |
1023 gaim_gtkxfer_dialog_cancel_xfer(GaimGtkXferDialog *dialog, | |
1024 GaimXfer *xfer) | |
1025 { | |
1026 GaimGtkXferUiData *data; | |
1027 GdkPixbuf *pixbuf; | |
1028 const gchar *status; | |
1029 | |
1030 g_return_if_fail(dialog != NULL); | |
1031 g_return_if_fail(xfer != NULL); | |
1032 | |
1033 data = GAIM_GTKXFER(xfer); | |
1034 | |
1035 if (data == NULL) | |
1036 return; | |
1037 | |
1038 if (!data->in_list) | |
1039 return; | |
1040 | |
1041 if ((gaim_xfer_get_status(xfer) == GAIM_XFER_STATUS_CANCEL_LOCAL) && (dialog->auto_clear)) { | |
1042 gaim_gtkxfer_dialog_remove_xfer(dialog, xfer); | |
1043 return; | |
1044 } | |
1045 | |
1046 data = GAIM_GTKXFER(xfer); | |
1047 | |
1048 update_detailed_info(dialog, xfer); | |
1049 update_title_progress(dialog); | |
1050 | |
1051 pixbuf = gtk_widget_render_icon(dialog->window, | |
1052 GAIM_STOCK_FILE_CANCELED, | |
1053 GTK_ICON_SIZE_MENU, NULL); | |
1054 | |
1055 if (gaim_xfer_is_canceled(xfer)) | |
1056 status = _("Canceled"); | |
1057 else | |
1058 status = _("Failed"); | |
1059 | |
1060 gtk_list_store_set(dialog->model, &data->iter, | |
1061 COLUMN_STATUS, pixbuf, | |
1062 COLUMN_REMAINING, status, | |
1063 -1); | |
1064 | |
1065 g_object_unref(pixbuf); | |
1066 | |
1067 update_buttons(dialog, xfer); | |
1068 } | |
1069 | |
1070 void | |
1071 gaim_gtkxfer_dialog_update_xfer(GaimGtkXferDialog *dialog, | |
1072 GaimXfer *xfer) | |
1073 { | |
1074 GaimGtkXferUiData *data; | |
1075 char *size_str, *remaining_str; | |
1076 GtkTreeSelection *selection; | |
1077 time_t current_time; | |
1078 GtkTreeIter iter; | |
1079 gboolean valid; | |
1080 | |
1081 g_return_if_fail(dialog != NULL); | |
1082 g_return_if_fail(xfer != NULL); | |
1083 | |
1084 if ((data = GAIM_GTKXFER(xfer)) == NULL) | |
1085 return; | |
1086 | |
1087 if (data->in_list == FALSE) | |
1088 return; | |
1089 | |
1090 current_time = time(NULL); | |
1091 if (((current_time - data->last_updated_time) == 0) && | |
1092 (!gaim_xfer_is_completed(xfer))) | |
1093 { | |
1094 /* Don't update the window more than once per second */ | |
1095 return; | |
1096 } | |
1097 data->last_updated_time = current_time; | |
1098 | |
1099 size_str = gaim_str_size_to_units(gaim_xfer_get_size(xfer)); | |
1100 remaining_str = gaim_str_size_to_units(gaim_xfer_get_bytes_remaining(xfer)); | |
1101 | |
1102 gtk_list_store_set(xfer_dialog->model, &data->iter, | |
1103 COLUMN_PROGRESS, gaim_xfer_get_progress(xfer), | |
1104 COLUMN_SIZE, size_str, | |
1105 COLUMN_REMAINING, remaining_str, | |
1106 -1); | |
1107 | |
1108 if (gaim_xfer_is_completed(xfer)) | |
1109 { | |
1110 GdkPixbuf *pixbuf; | |
1111 | |
1112 pixbuf = gtk_widget_render_icon(dialog->window, | |
1113 GAIM_STOCK_FILE_DONE, | |
1114 GTK_ICON_SIZE_MENU, NULL); | |
1115 | |
1116 gtk_list_store_set(GTK_LIST_STORE(xfer_dialog->model), &data->iter, | |
1117 COLUMN_STATUS, pixbuf, | |
1118 COLUMN_REMAINING, _("Finished"), | |
1119 -1); | |
1120 | |
1121 g_object_unref(pixbuf); | |
1122 } | |
1123 | |
1124 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(xfer_dialog->tree)); | |
1125 | |
1126 update_title_progress(dialog); | |
1127 if (xfer == dialog->selected_xfer) | |
1128 update_detailed_info(xfer_dialog, xfer); | |
1129 | |
1130 if (gaim_xfer_is_completed(xfer) && dialog->auto_clear) | |
1131 gaim_gtkxfer_dialog_remove_xfer(dialog, xfer); | |
1132 else | |
1133 update_buttons(dialog, xfer); | |
1134 | |
1135 /* | |
1136 * If all transfers are finished, and the pref is set, then | |
1137 * close the dialog. Otherwise just exit this function. | |
1138 */ | |
1139 if (dialog->keep_open) | |
1140 return; | |
1141 | |
1142 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(dialog->model), &iter); | |
1143 while (valid) | |
1144 { | |
1145 GValue val; | |
1146 GaimXfer *next; | |
1147 | |
1148 val.g_type = 0; | |
1149 gtk_tree_model_get_value(GTK_TREE_MODEL(dialog->model), | |
1150 &iter, COLUMN_DATA, &val); | |
1151 | |
1152 next = g_value_get_pointer(&val); | |
1153 if (!gaim_xfer_is_completed(next)) | |
1154 return; | |
1155 | |
1156 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(dialog->model), &iter); | |
1157 } | |
1158 | |
1159 /* If we got to this point then we know everything is finished */ | |
1160 gaim_gtkxfer_dialog_hide(dialog); | |
1161 } | |
1162 | |
1163 /************************************************************************** | |
1164 * File Transfer UI Ops | |
1165 **************************************************************************/ | |
1166 static void | |
1167 gaim_gtkxfer_new_xfer(GaimXfer *xfer) | |
1168 { | |
1169 GaimGtkXferUiData *data; | |
1170 | |
1171 /* This is where we're setting xfer->ui_data for the first time. */ | |
1172 data = g_new0(GaimGtkXferUiData, 1); | |
1173 xfer->ui_data = data; | |
1174 } | |
1175 | |
1176 static void | |
1177 gaim_gtkxfer_destroy(GaimXfer *xfer) | |
1178 { | |
1179 GaimGtkXferUiData *data; | |
1180 | |
1181 data = GAIM_GTKXFER(xfer); | |
1182 if (data) { | |
1183 g_free(data->name); | |
1184 g_free(data); | |
1185 xfer->ui_data = NULL; | |
1186 } | |
1187 } | |
1188 | |
1189 static void | |
1190 gaim_gtkxfer_add_xfer(GaimXfer *xfer) | |
1191 { | |
1192 if (xfer_dialog == NULL) | |
1193 xfer_dialog = gaim_gtkxfer_dialog_new(); | |
1194 | |
1195 gaim_gtkxfer_dialog_add_xfer(xfer_dialog, xfer); | |
1196 } | |
1197 | |
1198 static void | |
1199 gaim_gtkxfer_update_progress(GaimXfer *xfer, double percent) | |
1200 { | |
1201 gaim_gtkxfer_dialog_update_xfer(xfer_dialog, xfer); | |
1202 } | |
1203 | |
1204 static void | |
1205 gaim_gtkxfer_cancel_local(GaimXfer *xfer) | |
1206 { | |
1207 if (xfer_dialog) | |
1208 gaim_gtkxfer_dialog_cancel_xfer(xfer_dialog, xfer); | |
1209 } | |
1210 | |
1211 static void | |
1212 gaim_gtkxfer_cancel_remote(GaimXfer *xfer) | |
1213 { | |
1214 if (xfer_dialog) | |
1215 gaim_gtkxfer_dialog_cancel_xfer(xfer_dialog, xfer); | |
1216 } | |
1217 | |
1218 static GaimXferUiOps ops = | |
1219 { | |
1220 gaim_gtkxfer_new_xfer, | |
1221 gaim_gtkxfer_destroy, | |
1222 gaim_gtkxfer_add_xfer, | |
1223 gaim_gtkxfer_update_progress, | |
1224 gaim_gtkxfer_cancel_local, | |
1225 gaim_gtkxfer_cancel_remote | |
1226 }; | |
1227 | |
1228 /************************************************************************** | |
1229 * GTK+ File Transfer API | |
1230 **************************************************************************/ | |
1231 void | |
1232 gaim_gtk_xfers_init(void) | |
1233 { | |
1234 gaim_prefs_add_none("/gaim/gtk/filetransfer"); | |
1235 gaim_prefs_add_bool("/gaim/gtk/filetransfer/clear_finished", TRUE); | |
1236 gaim_prefs_add_bool("/gaim/gtk/filetransfer/keep_open", FALSE); | |
1237 } | |
1238 | |
1239 void | |
1240 gaim_gtk_xfers_uninit(void) | |
1241 { | |
1242 if (xfer_dialog != NULL) | |
1243 gaim_gtkxfer_dialog_destroy(xfer_dialog); | |
1244 } | |
1245 | |
1246 void | |
1247 gaim_set_gtkxfer_dialog(GaimGtkXferDialog *dialog) | |
1248 { | |
1249 xfer_dialog = dialog; | |
1250 } | |
1251 | |
1252 GaimGtkXferDialog * | |
1253 gaim_get_gtkxfer_dialog(void) | |
1254 { | |
1255 return xfer_dialog; | |
1256 } | |
1257 | |
1258 GaimXferUiOps * | |
1259 gaim_gtk_xfers_get_ui_ops(void) | |
1260 { | |
1261 return &ops; | |
1262 } |