* @file gntft.c GNT File Transfer UI * Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA #define FINCHXFER(xfer) \ (PurpleGntXferUiData *)FINCH_GET_DATA(xfer) GntWidget *remove_button; static PurpleGntXferDialog *xfer_dialog = NULL; time_t last_updated_time; gboolean notified; /* Has the completion of the transfer been notified? */ /************************************************************************** **************************************************************************/ update_title_progress(void) int num_active_xfers = 0; guint64 total_bytes_xferred = 0; guint64 total_file_size = 0; if (xfer_dialog == NULL || xfer_dialog->window == NULL) /* Find all active transfers */ for (list = gnt_tree_get_rows(GNT_TREE(xfer_dialog->tree)); list; list = list->next) { PurpleXfer *xfer = (PurpleXfer *)list->data; if (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_STARTED) { total_bytes_xferred += purple_xfer_get_bytes_sent(xfer); total_file_size += purple_xfer_get_size(xfer); if (num_active_xfers > 0) { if (total_file_size > 0) { total_pct = 100 * total_bytes_xferred / total_file_size; title = g_strdup_printf(ngettext("File Transfers - %d%% of %d file", "File Transfers - %d%% of %d files", total_pct, num_active_xfers); gnt_screen_rename_widget((xfer_dialog->window), title); gnt_screen_rename_widget((xfer_dialog->window), _("File Transfers")); /************************************************************************** **************************************************************************/ toggle_keep_open_cb(GntWidget *w) xfer_dialog->keep_open = !xfer_dialog->keep_open; purple_prefs_set_bool("/finch/filetransfer/keep_open", toggle_clear_finished_cb(GntWidget *w) xfer_dialog->auto_clear = !xfer_dialog->auto_clear; purple_prefs_set_bool("/finch/filetransfer/clear_finished", xfer_dialog->auto_clear); if (xfer_dialog->auto_clear) { GList *iter = purple_xfers_get_all(); PurpleXfer *xfer = iter->data; if (purple_xfer_is_completed(xfer) || purple_xfer_is_canceled(xfer)) finch_xfer_dialog_remove_xfer(xfer); remove_button_cb(GntButton *button) PurpleXfer *selected_xfer = gnt_tree_get_selection_data(GNT_TREE(xfer_dialog->tree)); if (selected_xfer && (purple_xfer_is_completed(selected_xfer) || purple_xfer_is_canceled(selected_xfer))) { finch_xfer_dialog_remove_xfer(selected_xfer); stop_button_cb(GntButton *button) PurpleXfer *selected_xfer = gnt_tree_get_selection_data(GNT_TREE(xfer_dialog->tree)); PurpleXferStatusType status; status = purple_xfer_get_status(selected_xfer); if (status != PURPLE_XFER_STATUS_CANCEL_LOCAL && status != PURPLE_XFER_STATUS_CANCEL_REMOTE && status != PURPLE_XFER_STATUS_DONE) purple_xfer_cancel_local(selected_xfer); /************************************************************************** * Dialog Building Functions **************************************************************************/ finch_xfer_dialog_new(void) int widths[] = {8, 12, 8, 8, 8, 8, -1}; xfer_dialog = g_new0(PurpleGntXferDialog, 1); purple_prefs_get_bool("/finch/filetransfer/keep_open"); xfer_dialog->auto_clear = purple_prefs_get_bool("/finch/filetransfer/clear_finished"); xfer_dialog->window = window = gnt_vbox_new(FALSE); g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(finch_xfer_dialog_destroy), NULL); gnt_box_set_toplevel(GNT_BOX(window), TRUE); gnt_box_set_title(GNT_BOX(window), _("File Transfers")); gnt_box_set_fill(GNT_BOX(window), TRUE); gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID); xfer_dialog->tree = tree = gnt_tree_new_with_columns(NUM_COLUMNS); gnt_tree_set_column_titles(GNT_TREE(tree), _("Progress"), _("Filename"), _("Size"), _("Speed"), _("Remaining"), _("Status")); gnt_tree_set_column_width_ratio(GNT_TREE(tree), widths); gnt_tree_set_column_resizable(GNT_TREE(tree), COLUMN_PROGRESS, FALSE); gnt_tree_set_column_resizable(GNT_TREE(tree), COLUMN_SIZE, FALSE); gnt_tree_set_column_resizable(GNT_TREE(tree), COLUMN_SPEED, FALSE); gnt_tree_set_column_resizable(GNT_TREE(tree), COLUMN_REMAINING, FALSE); gnt_widget_set_size(tree, 70, -1); gnt_tree_set_show_title(GNT_TREE(tree), TRUE); gnt_box_add_widget(GNT_BOX(window), tree); checkbox = gnt_check_box_new( _("Close this window when all transfers finish")); gnt_check_box_set_checked(GNT_CHECK_BOX(checkbox), !xfer_dialog->keep_open); g_signal_connect(G_OBJECT(checkbox), "toggled", G_CALLBACK(toggle_keep_open_cb), NULL); gnt_box_add_widget(GNT_BOX(window), checkbox); checkbox = gnt_check_box_new(_("Clear finished transfers")); gnt_check_box_set_checked(GNT_CHECK_BOX(checkbox), xfer_dialog->auto_clear); g_signal_connect(G_OBJECT(checkbox), "toggled", G_CALLBACK(toggle_clear_finished_cb), NULL); gnt_box_add_widget(GNT_BOX(window), checkbox); bbox = gnt_hbox_new(FALSE); xfer_dialog->remove_button = button = gnt_button_new(_("Remove")); g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(remove_button_cb), NULL); gnt_box_add_widget(GNT_BOX(bbox), button); xfer_dialog->stop_button = button = gnt_button_new(_("Stop")); g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(stop_button_cb), NULL); gnt_box_add_widget(GNT_BOX(bbox), button); xfer_dialog->close_button = button = gnt_button_new(_("Close")); g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(finch_xfer_dialog_destroy), NULL); gnt_box_add_widget(GNT_BOX(bbox), button); gnt_box_add_widget(GNT_BOX(window), bbox); for (iter = purple_xfers_get_all(); iter; iter = iter->next) { PurpleXfer *xfer = (PurpleXfer *)iter->data; PurpleGntXferUiData *data = FINCHXFER(xfer); finch_xfer_dialog_add_xfer(xfer); finch_xfer_dialog_update_xfer(xfer); gnt_tree_set_selected(GNT_TREE(tree), xfer); gnt_widget_show(xfer_dialog->window); finch_xfer_dialog_destroy() gnt_widget_destroy(xfer_dialog->window); gnt_window_present(xfer_dialog->window); finch_xfer_dialog_add_xfer(PurpleXfer *xfer) PurpleGntXferUiData *data; char *size_str, *remaining_str; g_return_if_fail(xfer_dialog != NULL); g_return_if_fail(xfer != NULL); finch_xfer_dialog_show(); data->last_updated_time = 0; type = purple_xfer_get_type(xfer); size_str = purple_str_size_to_units(purple_xfer_get_size(xfer)); remaining_str = purple_str_size_to_units(purple_xfer_get_bytes_remaining(xfer)); lfilename = g_path_get_basename(purple_xfer_get_local_filename(xfer)); utf8 = g_filename_to_utf8(lfilename, -1, NULL, NULL, NULL); gnt_tree_add_row_last(GNT_TREE(xfer_dialog->tree), xfer, gnt_tree_create_row(GNT_TREE(xfer_dialog->tree), "0.0", (type == PURPLE_XFER_RECEIVE) ? purple_xfer_get_filename(xfer) : lfilename, size_str, "0.0", "",_("Waiting for transfer to begin")), NULL); xfer_dialog->num_transfers++; finch_xfer_dialog_remove_xfer(PurpleXfer *xfer) PurpleGntXferUiData *data; g_return_if_fail(xfer_dialog != NULL); g_return_if_fail(xfer != NULL); gnt_tree_remove(GNT_TREE(xfer_dialog->tree), xfer); xfer_dialog->num_transfers--; if (xfer_dialog->num_transfers == 0 && !xfer_dialog->keep_open) finch_xfer_dialog_destroy(); finch_xfer_dialog_cancel_xfer(PurpleXfer *xfer) PurpleGntXferUiData *data; g_return_if_fail(xfer_dialog != NULL); g_return_if_fail(xfer != NULL); if ((purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL) && (xfer_dialog->auto_clear)) { finch_xfer_dialog_remove_xfer(xfer); if (purple_xfer_is_canceled(xfer)) gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_STATUS, status); finch_xfer_dialog_update_xfer(PurpleXfer *xfer) PurpleGntXferUiData *data; char *size_str, *remaining_str; if ((now = purple_xfer_get_end_time(xfer)) == 0) kb_sent = purple_xfer_get_bytes_sent(xfer) / 1024.0; elapsed = (purple_xfer_get_start_time(xfer) > 0 ? now - purple_xfer_get_start_time(xfer) : 0); kbps = (elapsed > 0 ? (kb_sent / elapsed) : 0); g_return_if_fail(xfer_dialog != NULL); g_return_if_fail(xfer != NULL); if ((data = FINCHXFER(xfer)) == NULL) if (data->in_list == FALSE || data->notified) current_time = time(NULL); if (((current_time - data->last_updated_time) == 0) && (!purple_xfer_is_completed(xfer))) { /* Don't update the window more than once per second */ data->last_updated_time = current_time; send = (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND); size_str = purple_str_size_to_units(purple_xfer_get_size(xfer)); remaining_str = purple_str_size_to_units(purple_xfer_get_bytes_remaining(xfer)); kbsec = g_strdup_printf(_("%.2f KiB/s"), kbps); gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_PROGRESS, g_ascii_dtostr(prog_str, sizeof(prog_str), purple_xfer_get_progress(xfer) * 100.)); gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_SIZE, size_str); gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_REMAINING, remaining_str); gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_SPEED, kbsec); if (purple_xfer_is_completed(xfer)) { gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_STATUS, send ? _("Sent") : _("Received")); gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_REMAINING, _("Finished")); char *msg = g_strdup_printf(_("The file was saved as %s."), purple_xfer_get_local_filename(xfer)); purple_xfer_conversation_write(xfer, msg, FALSE); gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_STATUS, send ? _("Sending") : _("Receiving")); if (purple_xfer_is_completed(xfer) && xfer_dialog->auto_clear) finch_xfer_dialog_remove_xfer(xfer); /************************************************************************** **************************************************************************/ finch_xfer_new_xfer(PurpleXfer *xfer) PurpleGntXferUiData *data; /* This is where we're setting xfer->ui_data for the first time. */ data = g_new0(PurpleGntXferUiData, 1); FINCH_SET_DATA(xfer, data); finch_xfer_destroy(PurpleXfer *xfer) PurpleGntXferUiData *data; FINCH_SET_DATA(xfer, NULL); finch_xfer_add_xfer(PurpleXfer *xfer) finch_xfer_dialog_add_xfer(xfer); gnt_tree_set_selected(GNT_TREE(xfer_dialog->tree), xfer); finch_xfer_update_progress(PurpleXfer *xfer, double percent) finch_xfer_dialog_update_xfer(xfer); finch_xfer_cancel_local(PurpleXfer *xfer) finch_xfer_dialog_cancel_xfer(xfer); finch_xfer_cancel_remote(PurpleXfer *xfer) finch_xfer_dialog_cancel_xfer(xfer); static PurpleXferUiOps ops = finch_xfer_update_progress, finch_xfer_cancel_remote, /************************************************************************** **************************************************************************/ purple_prefs_add_none("/finch/filetransfer"); purple_prefs_add_bool("/finch/filetransfer/clear_finished", TRUE); purple_prefs_add_bool("/finch/filetransfer/keep_open", FALSE); finch_xfer_dialog_destroy(); finch_xfers_get_ui_ops(void)