Mercurial > pidgin
annotate finch/gntft.c @ 15923:f8c16848b76d
Allow selecting multiple files from the file-select dialog.
You need to tag the files by pressing 't' to select the files. It is possible
to tag files from different locations, ie. when you change the directory, the
tags are remembered. You can untag a selection by pressing 't' again. To untag
all selections, press 'c'.
author | Sadrul Habib Chowdhury <imadil@gmail.com> |
---|---|
date | Mon, 26 Mar 2007 01:19:59 +0000 |
parents | 66dff3dfdea6 |
children | ee397e53d9ce |
rev | line source |
---|---|
15817 | 1 /** |
2 * @file gntft.c GNT File Transfer UI | |
3 * @ingroup gntui | |
4 * | |
15870
66dff3dfdea6
Re-sed the copyright notices so they don't all talk about Purple.
Richard Laager <rlaager@wiktel.com>
parents:
15822
diff
changeset
|
5 * finch |
15817 | 6 * |
15870
66dff3dfdea6
Re-sed the copyright notices so they don't all talk about Purple.
Richard Laager <rlaager@wiktel.com>
parents:
15822
diff
changeset
|
7 * Finch is the legal property of its developers, whose names are too numerous |
15817 | 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 | |
15822 | 42 #define FINCHXFER(xfer) \ |
43 (PurpleGntXferUiData *)(xfer)->ui_data | |
15817 | 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; | |
15822 | 57 } PurpleGntXferDialog; |
15817 | 58 |
15822 | 59 static PurpleGntXferDialog *xfer_dialog = NULL; |
15817 | 60 |
61 typedef struct | |
62 { | |
63 time_t last_updated_time; | |
64 gboolean in_list; | |
65 | |
66 char *name; | |
67 | |
15822 | 68 } PurpleGntXferUiData; |
15817 | 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) { | |
15822 | 99 PurpleXfer *xfer = (PurpleXfer *)list->data; |
15817 | 100 |
15822 | 101 if (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_STARTED) { |
15817 | 102 num_active_xfers++; |
15822 | 103 total_bytes_xferred += purple_xfer_get_bytes_sent(xfer); |
104 total_file_size += purple_xfer_get_size(xfer); | |
15817 | 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; | |
15822 | 134 purple_prefs_set_bool("/purple/gnt/filetransfer/keep_open", |
15817 | 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; | |
15822 | 142 purple_prefs_set_bool("/purple/gnt/filetransfer/clear_finished", |
15817 | 143 xfer_dialog->auto_clear); |
144 } | |
145 | |
146 static void | |
147 remove_button_cb(GntButton *button) | |
148 { | |
15822 | 149 PurpleXfer *selected_xfer = gnt_tree_get_selection_data(GNT_TREE(xfer_dialog->tree)); |
150 if (selected_xfer && (selected_xfer->status == PURPLE_XFER_STATUS_CANCEL_LOCAL || | |
151 selected_xfer->status == PURPLE_XFER_STATUS_CANCEL_REMOTE || | |
152 selected_xfer->status == PURPLE_XFER_STATUS_DONE)) { | |
15817 | 153 finch_xfer_dialog_remove_xfer(selected_xfer); |
154 } | |
155 } | |
156 | |
157 static void | |
158 stop_button_cb(GntButton *button) | |
159 { | |
15822 | 160 PurpleXfer *selected_xfer = gnt_tree_get_selection_data(GNT_TREE(xfer_dialog->tree)); |
161 if (selected_xfer && selected_xfer->status == PURPLE_XFER_STATUS_STARTED) | |
162 purple_xfer_cancel_local(selected_xfer); | |
15817 | 163 } |
164 | |
165 #if 0 | |
166 static void | |
167 tree_selection_changed_cb(GntTree *tree, GntTreeRow *old, GntTreeRow *current, gpointer n) | |
168 { | |
15822 | 169 xfer_dialog->selected_xfer = (PurpleXfer *)gnt_tree_get_selection_data(tree); |
15817 | 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) | |
15822 | 189 xfer_dialog = g_new0(PurpleGntXferDialog, 1); |
15817 | 190 |
191 xfer_dialog->keep_open = | |
15822 | 192 purple_prefs_get_bool("/purple/gnt/filetransfer/keep_open"); |
15817 | 193 xfer_dialog->auto_clear = |
15822 | 194 purple_prefs_get_bool("/purple/gnt/filetransfer/clear_finished"); |
15817 | 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 | |
15822 | 247 for (iter = purple_xfers_get_all(); iter; iter = iter->next) { |
248 PurpleXfer *xfer = (PurpleXfer *)iter->data; | |
249 PurpleGntXferUiData *data = FINCHXFER(xfer); | |
15817 | 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 | |
15822 | 275 finch_xfer_dialog_add_xfer(PurpleXfer *xfer) |
15817 | 276 { |
15822 | 277 PurpleGntXferUiData *data; |
278 PurpleXferType type; | |
15817 | 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 | |
15822 | 285 purple_xfer_ref(xfer); |
15817 | 286 |
15822 | 287 data = FINCHXFER(xfer); |
15817 | 288 data->in_list = TRUE; |
289 | |
290 finch_xfer_dialog_show(); | |
291 | |
292 data->last_updated_time = 0; | |
293 | |
15822 | 294 type = purple_xfer_get_type(xfer); |
15817 | 295 |
15822 | 296 size_str = purple_str_size_to_units(purple_xfer_get_size(xfer)); |
297 remaining_str = purple_str_size_to_units(purple_xfer_get_bytes_remaining(xfer)); | |
15817 | 298 |
15822 | 299 lfilename = g_path_get_basename(purple_xfer_get_local_filename(xfer)); |
15817 | 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), | |
15822 | 305 "0.0", (type == PURPLE_XFER_RECEIVE) ? purple_xfer_get_filename(xfer) : lfilename, |
15817 | 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 | |
15822 | 318 finch_xfer_dialog_remove_xfer(PurpleXfer *xfer) |
15817 | 319 { |
15822 | 320 PurpleGntXferUiData *data; |
15817 | 321 |
322 g_return_if_fail(xfer_dialog != NULL); | |
323 g_return_if_fail(xfer != NULL); | |
324 | |
15822 | 325 data = FINCHXFER(xfer); |
15817 | 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(); | |
15822 | 343 purple_xfer_unref(xfer); |
15817 | 344 } |
345 | |
346 void | |
15822 | 347 finch_xfer_dialog_cancel_xfer(PurpleXfer *xfer) |
15817 | 348 { |
15822 | 349 PurpleGntXferUiData *data; |
15817 | 350 const gchar *status; |
351 | |
352 g_return_if_fail(xfer_dialog != NULL); | |
353 g_return_if_fail(xfer != NULL); | |
354 | |
15822 | 355 data = FINCHXFER(xfer); |
15817 | 356 |
357 if (data == NULL) | |
358 return; | |
359 | |
360 if (!data->in_list) | |
361 return; | |
362 | |
15822 | 363 if ((purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL) && (xfer_dialog->auto_clear)) { |
15817 | 364 finch_xfer_dialog_remove_xfer(xfer); |
365 return; | |
366 } | |
367 | |
15822 | 368 data = FINCHXFER(xfer); |
15817 | 369 |
370 update_title_progress(); | |
371 | |
15822 | 372 if (purple_xfer_is_canceled(xfer)) |
15817 | 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 | |
15822 | 381 finch_xfer_dialog_update_xfer(PurpleXfer *xfer) |
15817 | 382 { |
15822 | 383 PurpleGntXferUiData *data; |
15817 | 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 | |
15822 | 397 kb_sent = purple_xfer_get_bytes_sent(xfer) / 1024.0; |
398 kb_rem = purple_xfer_get_bytes_remaining(xfer) / 1024.0; | |
15817 | 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 | |
15822 | 407 if ((data = FINCHXFER(xfer)) == NULL) |
15817 | 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) && | |
15822 | 415 (!purple_xfer_is_completed(xfer))) { |
15817 | 416 /* Don't update the window more than once per second */ |
417 return; | |
418 } | |
419 data->last_updated_time = current_time; | |
420 | |
15822 | 421 size_str = purple_str_size_to_units(purple_xfer_get_size(xfer)); |
422 remaining_str = purple_str_size_to_units(purple_xfer_get_bytes_remaining(xfer)); | |
15817 | 423 |
424 gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_PROGRESS, | |
15822 | 425 g_ascii_dtostr(prog_str, sizeof(prog_str), purple_xfer_get_progress(xfer) * 100.)); |
15817 | 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); | |
15822 | 431 if (purple_xfer_is_completed(xfer)) { |
15817 | 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 | |
15822 | 439 if (purple_xfer_is_completed(xfer) && xfer_dialog->auto_clear) |
15817 | 440 finch_xfer_dialog_remove_xfer(xfer); |
441 } | |
442 | |
443 /************************************************************************** | |
444 * File Transfer UI Ops | |
445 **************************************************************************/ | |
446 static void | |
15822 | 447 finch_xfer_new_xfer(PurpleXfer *xfer) |
15817 | 448 { |
15822 | 449 PurpleGntXferUiData *data; |
15817 | 450 |
451 /* This is where we're setting xfer->ui_data for the first time. */ | |
15822 | 452 data = g_new0(PurpleGntXferUiData, 1); |
15817 | 453 xfer->ui_data = data; |
454 } | |
455 | |
456 static void | |
15822 | 457 finch_xfer_destroy(PurpleXfer *xfer) |
15817 | 458 { |
15822 | 459 PurpleGntXferUiData *data; |
15817 | 460 |
15822 | 461 data = FINCHXFER(xfer); |
15817 | 462 if (data) { |
463 g_free(data->name); | |
464 g_free(data); | |
465 xfer->ui_data = NULL; | |
466 } | |
467 } | |
468 | |
469 static void | |
15822 | 470 finch_xfer_add_xfer(PurpleXfer *xfer) |
15817 | 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 | |
15822 | 480 finch_xfer_update_progress(PurpleXfer *xfer, double percent) |
15817 | 481 { |
482 if (xfer_dialog) | |
483 finch_xfer_dialog_update_xfer(xfer); | |
484 } | |
485 | |
486 static void | |
15822 | 487 finch_xfer_cancel_local(PurpleXfer *xfer) |
15817 | 488 { |
489 if (xfer_dialog) | |
490 finch_xfer_dialog_cancel_xfer(xfer); | |
491 } | |
492 | |
493 static void | |
15822 | 494 finch_xfer_cancel_remote(PurpleXfer *xfer) |
15817 | 495 { |
496 if (xfer_dialog) | |
497 finch_xfer_dialog_cancel_xfer(xfer); | |
498 } | |
499 | |
15822 | 500 static PurpleXferUiOps ops = |
15817 | 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 { | |
15822 | 516 purple_prefs_add_none("/purple/gnt/filetransfer"); |
517 purple_prefs_add_bool("/purple/gnt/filetransfer/clear_finished", TRUE); | |
518 purple_prefs_add_bool("/purple/gnt/filetransfer/keep_open", FALSE); | |
15817 | 519 } |
520 | |
521 void | |
522 finch_xfers_uninit(void) | |
523 { | |
524 if (xfer_dialog != NULL) | |
525 finch_xfer_dialog_destroy(); | |
526 } | |
527 | |
15822 | 528 PurpleXferUiOps * |
15817 | 529 finch_xfers_get_ui_ops(void) |
530 { | |
531 return &ops; | |
532 } |