Mercurial > pidgin
comparison finch/gntft.c @ 15817:0e3a8505ebbe
renamed gaim-text to finch
author | Sean Egan <seanegan@gmail.com> |
---|---|
date | Sun, 18 Mar 2007 19:38:15 +0000 |
parents | |
children | 32c366eeeb99 |
comparison
equal
deleted
inserted
replaced
15816:317e7613e581 | 15817:0e3a8505ebbe |
---|---|
1 /** | |
2 * @file gntft.c GNT File Transfer UI | |
3 * @ingroup gntui | |
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 <gnt.h> | |
26 #include <gntbox.h> | |
27 #include <gntbutton.h> | |
28 #include <gntcheckbox.h> | |
29 #include <gntlabel.h> | |
30 #include <gnttree.h> | |
31 #include "internal.h" | |
32 | |
33 #include "debug.h" | |
34 #include "notify.h" | |
35 #include "ft.h" | |
36 #include "prpl.h" | |
37 #include "util.h" | |
38 | |
39 #include "gntft.h" | |
40 #include "prefs.h" | |
41 | |
42 #define GAIM_GNTXFER(xfer) \ | |
43 (GaimGntXferUiData *)(xfer)->ui_data | |
44 | |
45 typedef struct | |
46 { | |
47 gboolean keep_open; | |
48 gboolean auto_clear; | |
49 gint num_transfers; | |
50 | |
51 GntWidget *window; | |
52 GntWidget *tree; | |
53 | |
54 GntWidget *remove_button; | |
55 GntWidget *stop_button; | |
56 GntWidget *close_button; | |
57 } GaimGntXferDialog; | |
58 | |
59 static GaimGntXferDialog *xfer_dialog = NULL; | |
60 | |
61 typedef struct | |
62 { | |
63 time_t last_updated_time; | |
64 gboolean in_list; | |
65 | |
66 char *name; | |
67 | |
68 } GaimGntXferUiData; | |
69 | |
70 enum | |
71 { | |
72 COLUMN_PROGRESS = 0, | |
73 COLUMN_FILENAME, | |
74 COLUMN_SIZE, | |
75 COLUMN_SPEED, | |
76 COLUMN_REMAINING, | |
77 COLUMN_STATUS, | |
78 NUM_COLUMNS | |
79 }; | |
80 | |
81 | |
82 /************************************************************************** | |
83 * Utility Functions | |
84 **************************************************************************/ | |
85 | |
86 static void | |
87 update_title_progress() | |
88 { | |
89 const GList *list; | |
90 int num_active_xfers = 0; | |
91 guint64 total_bytes_xferred = 0; | |
92 guint64 total_file_size = 0; | |
93 | |
94 if (xfer_dialog == NULL || xfer_dialog->window == NULL) | |
95 return; | |
96 | |
97 /* Find all active transfers */ | |
98 for (list = gnt_tree_get_rows(GNT_TREE(xfer_dialog->tree)); list; list = list->next) { | |
99 GaimXfer *xfer = (GaimXfer *)list->data; | |
100 | |
101 if (gaim_xfer_get_status(xfer) == GAIM_XFER_STATUS_STARTED) { | |
102 num_active_xfers++; | |
103 total_bytes_xferred += gaim_xfer_get_bytes_sent(xfer); | |
104 total_file_size += gaim_xfer_get_size(xfer); | |
105 } | |
106 } | |
107 | |
108 /* Update the title */ | |
109 if (num_active_xfers > 0) { | |
110 gchar *title; | |
111 int total_pct = 0; | |
112 | |
113 if (total_file_size > 0) { | |
114 total_pct = 100 * total_bytes_xferred / total_file_size; | |
115 } | |
116 | |
117 title = g_strdup_printf(_("File Transfers - %d%% of %d files"), | |
118 total_pct, num_active_xfers); | |
119 gnt_screen_rename_widget((xfer_dialog->window), title); | |
120 g_free(title); | |
121 } else { | |
122 gnt_screen_rename_widget((xfer_dialog->window), _("File Transfers")); | |
123 } | |
124 } | |
125 | |
126 | |
127 /************************************************************************** | |
128 * Callbacks | |
129 **************************************************************************/ | |
130 static void | |
131 toggle_keep_open_cb(GntWidget *w) | |
132 { | |
133 xfer_dialog->keep_open = !xfer_dialog->keep_open; | |
134 gaim_prefs_set_bool("/gaim/gnt/filetransfer/keep_open", | |
135 xfer_dialog->keep_open); | |
136 } | |
137 | |
138 static void | |
139 toggle_clear_finished_cb(GntWidget *w) | |
140 { | |
141 xfer_dialog->auto_clear = !xfer_dialog->auto_clear; | |
142 gaim_prefs_set_bool("/gaim/gnt/filetransfer/clear_finished", | |
143 xfer_dialog->auto_clear); | |
144 } | |
145 | |
146 static void | |
147 remove_button_cb(GntButton *button) | |
148 { | |
149 GaimXfer *selected_xfer = gnt_tree_get_selection_data(GNT_TREE(xfer_dialog->tree)); | |
150 if (selected_xfer && (selected_xfer->status == GAIM_XFER_STATUS_CANCEL_LOCAL || | |
151 selected_xfer->status == GAIM_XFER_STATUS_CANCEL_REMOTE || | |
152 selected_xfer->status == GAIM_XFER_STATUS_DONE)) { | |
153 finch_xfer_dialog_remove_xfer(selected_xfer); | |
154 } | |
155 } | |
156 | |
157 static void | |
158 stop_button_cb(GntButton *button) | |
159 { | |
160 GaimXfer *selected_xfer = gnt_tree_get_selection_data(GNT_TREE(xfer_dialog->tree)); | |
161 if (selected_xfer && selected_xfer->status == GAIM_XFER_STATUS_STARTED) | |
162 gaim_xfer_cancel_local(selected_xfer); | |
163 } | |
164 | |
165 #if 0 | |
166 static void | |
167 tree_selection_changed_cb(GntTree *tree, GntTreeRow *old, GntTreeRow *current, gpointer n) | |
168 { | |
169 xfer_dialog->selected_xfer = (GaimXfer *)gnt_tree_get_selection_data(tree); | |
170 } | |
171 #endif | |
172 | |
173 /************************************************************************** | |
174 * Dialog Building Functions | |
175 **************************************************************************/ | |
176 | |
177 | |
178 void | |
179 finch_xfer_dialog_new(void) | |
180 { | |
181 const GList *iter; | |
182 GntWidget *window; | |
183 GntWidget *bbox; | |
184 GntWidget *button; | |
185 GntWidget *checkbox; | |
186 GntWidget *tree; | |
187 | |
188 if (!xfer_dialog) | |
189 xfer_dialog = g_new0(GaimGntXferDialog, 1); | |
190 | |
191 xfer_dialog->keep_open = | |
192 gaim_prefs_get_bool("/gaim/gnt/filetransfer/keep_open"); | |
193 xfer_dialog->auto_clear = | |
194 gaim_prefs_get_bool("/gaim/gnt/filetransfer/clear_finished"); | |
195 | |
196 /* Create the window. */ | |
197 xfer_dialog->window = window = gnt_vbox_new(FALSE); | |
198 g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(finch_xfer_dialog_destroy), NULL); | |
199 gnt_box_set_toplevel(GNT_BOX(window), TRUE); | |
200 gnt_box_set_title(GNT_BOX(window), _("File Transfers")); | |
201 | |
202 xfer_dialog->tree = tree = gnt_tree_new_with_columns(NUM_COLUMNS); | |
203 gnt_tree_set_column_titles(GNT_TREE(tree), _("Progress"), _("Filename"), _("Size"), _("Speed"), _("Remaining"), _("Status")); | |
204 gnt_tree_set_col_width(GNT_TREE(tree), COLUMN_PROGRESS, 8); | |
205 gnt_tree_set_col_width(GNT_TREE(tree), COLUMN_FILENAME, 8); | |
206 gnt_tree_set_col_width(GNT_TREE(tree), COLUMN_SIZE, 10); | |
207 gnt_tree_set_col_width(GNT_TREE(tree), COLUMN_SPEED, 10); | |
208 gnt_tree_set_col_width(GNT_TREE(tree), COLUMN_REMAINING, 10); | |
209 gnt_tree_set_col_width(GNT_TREE(tree), COLUMN_STATUS, 10); | |
210 gnt_tree_set_show_title(GNT_TREE(tree), TRUE); | |
211 gnt_box_add_widget(GNT_BOX(window), tree); | |
212 /*g_signal_connect(G_OBJECT(tree), "selection-changed",*/ | |
213 /*G_CALLBACK(tree_selection_changed_cb), NULL);*/ | |
214 checkbox = gnt_check_box_new( _("Close this window when all transfers finish")); | |
215 gnt_check_box_set_checked(GNT_CHECK_BOX(checkbox), | |
216 !xfer_dialog->keep_open); | |
217 g_signal_connect(G_OBJECT(checkbox), "toggled", | |
218 G_CALLBACK(toggle_keep_open_cb), NULL); | |
219 gnt_box_add_widget(GNT_BOX(window), checkbox); | |
220 | |
221 checkbox = gnt_check_box_new(_("Clear finished transfers")); | |
222 gnt_check_box_set_checked(GNT_CHECK_BOX(checkbox), | |
223 xfer_dialog->auto_clear); | |
224 g_signal_connect(G_OBJECT(checkbox), "toggled", | |
225 G_CALLBACK(toggle_clear_finished_cb), NULL); | |
226 gnt_box_add_widget(GNT_BOX(window), checkbox); | |
227 | |
228 bbox = gnt_hbox_new(TRUE); | |
229 | |
230 xfer_dialog->remove_button = button = gnt_button_new(_("Remove")); | |
231 g_signal_connect(G_OBJECT(button), "activate", | |
232 G_CALLBACK(remove_button_cb), NULL); | |
233 gnt_box_add_widget(GNT_BOX(bbox), button); | |
234 | |
235 xfer_dialog->stop_button = button = gnt_button_new(_("Stop")); | |
236 g_signal_connect(G_OBJECT(button), "activate", | |
237 G_CALLBACK(stop_button_cb), NULL); | |
238 gnt_box_add_widget(GNT_BOX(bbox), button); | |
239 | |
240 xfer_dialog->close_button = button = gnt_button_new(_("Close")); | |
241 g_signal_connect(G_OBJECT(button), "activate", | |
242 G_CALLBACK(finch_xfer_dialog_destroy), NULL); | |
243 gnt_box_add_widget(GNT_BOX(bbox), button); | |
244 | |
245 gnt_box_add_widget(GNT_BOX(window), bbox); | |
246 | |
247 for (iter = gaim_xfers_get_all(); iter; iter = iter->next) { | |
248 GaimXfer *xfer = (GaimXfer *)iter->data; | |
249 GaimGntXferUiData *data = GAIM_GNTXFER(xfer); | |
250 if (data->in_list) { | |
251 finch_xfer_dialog_add_xfer(xfer); | |
252 finch_xfer_dialog_update_xfer(xfer); | |
253 gnt_tree_set_selected(GNT_TREE(tree), xfer); | |
254 } | |
255 } | |
256 gnt_widget_show(xfer_dialog->window); | |
257 } | |
258 | |
259 void | |
260 finch_xfer_dialog_destroy() | |
261 { | |
262 gnt_widget_destroy(xfer_dialog->window); | |
263 g_free(xfer_dialog); | |
264 xfer_dialog = NULL; | |
265 } | |
266 | |
267 void | |
268 finch_xfer_dialog_show() | |
269 { | |
270 if (xfer_dialog == NULL) | |
271 finch_xfer_dialog_new(); | |
272 } | |
273 | |
274 void | |
275 finch_xfer_dialog_add_xfer(GaimXfer *xfer) | |
276 { | |
277 GaimGntXferUiData *data; | |
278 GaimXferType type; | |
279 char *size_str, *remaining_str; | |
280 char *lfilename, *utf8; | |
281 | |
282 g_return_if_fail(xfer_dialog != NULL); | |
283 g_return_if_fail(xfer != NULL); | |
284 | |
285 gaim_xfer_ref(xfer); | |
286 | |
287 data = GAIM_GNTXFER(xfer); | |
288 data->in_list = TRUE; | |
289 | |
290 finch_xfer_dialog_show(); | |
291 | |
292 data->last_updated_time = 0; | |
293 | |
294 type = gaim_xfer_get_type(xfer); | |
295 | |
296 size_str = gaim_str_size_to_units(gaim_xfer_get_size(xfer)); | |
297 remaining_str = gaim_str_size_to_units(gaim_xfer_get_bytes_remaining(xfer)); | |
298 | |
299 lfilename = g_path_get_basename(gaim_xfer_get_local_filename(xfer)); | |
300 utf8 = g_filename_to_utf8(lfilename, -1, NULL, NULL, NULL); | |
301 g_free(lfilename); | |
302 lfilename = utf8; | |
303 gnt_tree_add_row_last(GNT_TREE(xfer_dialog->tree), xfer, | |
304 gnt_tree_create_row(GNT_TREE(xfer_dialog->tree), | |
305 "0.0", (type == GAIM_XFER_RECEIVE) ? gaim_xfer_get_filename(xfer) : lfilename, | |
306 size_str, "0.0", "",_("Waiting for transfer to begin")), NULL); | |
307 g_free(lfilename); | |
308 | |
309 g_free(size_str); | |
310 g_free(remaining_str); | |
311 | |
312 xfer_dialog->num_transfers++; | |
313 | |
314 update_title_progress(); | |
315 } | |
316 | |
317 void | |
318 finch_xfer_dialog_remove_xfer(GaimXfer *xfer) | |
319 { | |
320 GaimGntXferUiData *data; | |
321 | |
322 g_return_if_fail(xfer_dialog != NULL); | |
323 g_return_if_fail(xfer != NULL); | |
324 | |
325 data = GAIM_GNTXFER(xfer); | |
326 | |
327 if (data == NULL) | |
328 return; | |
329 | |
330 if (!data->in_list) | |
331 return; | |
332 | |
333 data->in_list = FALSE; | |
334 | |
335 gnt_tree_remove(GNT_TREE(xfer_dialog->tree), xfer); | |
336 | |
337 xfer_dialog->num_transfers--; | |
338 | |
339 if (xfer_dialog->num_transfers == 0 && !xfer_dialog->keep_open) | |
340 finch_xfer_dialog_destroy(); | |
341 else | |
342 update_title_progress(); | |
343 gaim_xfer_unref(xfer); | |
344 } | |
345 | |
346 void | |
347 finch_xfer_dialog_cancel_xfer(GaimXfer *xfer) | |
348 { | |
349 GaimGntXferUiData *data; | |
350 const gchar *status; | |
351 | |
352 g_return_if_fail(xfer_dialog != NULL); | |
353 g_return_if_fail(xfer != NULL); | |
354 | |
355 data = GAIM_GNTXFER(xfer); | |
356 | |
357 if (data == NULL) | |
358 return; | |
359 | |
360 if (!data->in_list) | |
361 return; | |
362 | |
363 if ((gaim_xfer_get_status(xfer) == GAIM_XFER_STATUS_CANCEL_LOCAL) && (xfer_dialog->auto_clear)) { | |
364 finch_xfer_dialog_remove_xfer(xfer); | |
365 return; | |
366 } | |
367 | |
368 data = GAIM_GNTXFER(xfer); | |
369 | |
370 update_title_progress(); | |
371 | |
372 if (gaim_xfer_is_canceled(xfer)) | |
373 status = _("Canceled"); | |
374 else | |
375 status = _("Failed"); | |
376 | |
377 gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_STATUS, status); | |
378 } | |
379 | |
380 void | |
381 finch_xfer_dialog_update_xfer(GaimXfer *xfer) | |
382 { | |
383 GaimGntXferUiData *data; | |
384 char *size_str, *remaining_str; | |
385 time_t current_time; | |
386 char prog_str[5]; | |
387 double kb_sent, kb_rem; | |
388 double kbps = 0.0; | |
389 time_t elapsed, now; | |
390 char *kbsec; | |
391 | |
392 if (xfer->end_time != 0) | |
393 now = xfer->end_time; | |
394 else | |
395 now = time(NULL); | |
396 | |
397 kb_sent = gaim_xfer_get_bytes_sent(xfer) / 1024.0; | |
398 kb_rem = gaim_xfer_get_bytes_remaining(xfer) / 1024.0; | |
399 elapsed = (xfer->start_time > 0 ? now - xfer->start_time : 0); | |
400 kbps = (elapsed > 0 ? (kb_sent / elapsed) : 0); | |
401 | |
402 kbsec = g_strdup_printf(_("%.2f KB/s"), kbps); | |
403 | |
404 g_return_if_fail(xfer_dialog != NULL); | |
405 g_return_if_fail(xfer != NULL); | |
406 | |
407 if ((data = GAIM_GNTXFER(xfer)) == NULL) | |
408 return; | |
409 | |
410 if (data->in_list == FALSE) | |
411 return; | |
412 | |
413 current_time = time(NULL); | |
414 if (((current_time - data->last_updated_time) == 0) && | |
415 (!gaim_xfer_is_completed(xfer))) { | |
416 /* Don't update the window more than once per second */ | |
417 return; | |
418 } | |
419 data->last_updated_time = current_time; | |
420 | |
421 size_str = gaim_str_size_to_units(gaim_xfer_get_size(xfer)); | |
422 remaining_str = gaim_str_size_to_units(gaim_xfer_get_bytes_remaining(xfer)); | |
423 | |
424 gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_PROGRESS, | |
425 g_ascii_dtostr(prog_str, sizeof(prog_str), gaim_xfer_get_progress(xfer) * 100.)); | |
426 gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_SIZE, size_str); | |
427 gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_REMAINING, remaining_str); | |
428 gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_SPEED, kbsec); | |
429 g_free(size_str); | |
430 g_free(remaining_str); | |
431 if (gaim_xfer_is_completed(xfer)) { | |
432 gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_STATUS, _("Finished")); | |
433 } else { | |
434 gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_STATUS, _("Transferring")); | |
435 } | |
436 | |
437 update_title_progress(); | |
438 | |
439 if (gaim_xfer_is_completed(xfer) && xfer_dialog->auto_clear) | |
440 finch_xfer_dialog_remove_xfer(xfer); | |
441 } | |
442 | |
443 /************************************************************************** | |
444 * File Transfer UI Ops | |
445 **************************************************************************/ | |
446 static void | |
447 finch_xfer_new_xfer(GaimXfer *xfer) | |
448 { | |
449 GaimGntXferUiData *data; | |
450 | |
451 /* This is where we're setting xfer->ui_data for the first time. */ | |
452 data = g_new0(GaimGntXferUiData, 1); | |
453 xfer->ui_data = data; | |
454 } | |
455 | |
456 static void | |
457 finch_xfer_destroy(GaimXfer *xfer) | |
458 { | |
459 GaimGntXferUiData *data; | |
460 | |
461 data = GAIM_GNTXFER(xfer); | |
462 if (data) { | |
463 g_free(data->name); | |
464 g_free(data); | |
465 xfer->ui_data = NULL; | |
466 } | |
467 } | |
468 | |
469 static void | |
470 finch_xfer_add_xfer(GaimXfer *xfer) | |
471 { | |
472 if (!xfer_dialog) | |
473 finch_xfer_dialog_new(); | |
474 | |
475 finch_xfer_dialog_add_xfer(xfer); | |
476 gnt_tree_set_selected(GNT_TREE(xfer_dialog->tree), xfer); | |
477 } | |
478 | |
479 static void | |
480 finch_xfer_update_progress(GaimXfer *xfer, double percent) | |
481 { | |
482 if (xfer_dialog) | |
483 finch_xfer_dialog_update_xfer(xfer); | |
484 } | |
485 | |
486 static void | |
487 finch_xfer_cancel_local(GaimXfer *xfer) | |
488 { | |
489 if (xfer_dialog) | |
490 finch_xfer_dialog_cancel_xfer(xfer); | |
491 } | |
492 | |
493 static void | |
494 finch_xfer_cancel_remote(GaimXfer *xfer) | |
495 { | |
496 if (xfer_dialog) | |
497 finch_xfer_dialog_cancel_xfer(xfer); | |
498 } | |
499 | |
500 static GaimXferUiOps ops = | |
501 { | |
502 finch_xfer_new_xfer, | |
503 finch_xfer_destroy, | |
504 finch_xfer_add_xfer, | |
505 finch_xfer_update_progress, | |
506 finch_xfer_cancel_local, | |
507 finch_xfer_cancel_remote | |
508 }; | |
509 | |
510 /************************************************************************** | |
511 * GNT File Transfer API | |
512 **************************************************************************/ | |
513 void | |
514 finch_xfers_init(void) | |
515 { | |
516 gaim_prefs_add_none("/gaim/gnt/filetransfer"); | |
517 gaim_prefs_add_bool("/gaim/gnt/filetransfer/clear_finished", TRUE); | |
518 gaim_prefs_add_bool("/gaim/gnt/filetransfer/keep_open", FALSE); | |
519 } | |
520 | |
521 void | |
522 finch_xfers_uninit(void) | |
523 { | |
524 if (xfer_dialog != NULL) | |
525 finch_xfer_dialog_destroy(); | |
526 } | |
527 | |
528 GaimXferUiOps * | |
529 finch_xfers_get_ui_ops(void) | |
530 { | |
531 return &ops; | |
532 } |