From 804ca8e7b0d23937ca578659b1840f88e60fe931 Mon Sep 17 00:00:00 2001 From: Slava Zanko Date: Fri, 19 Feb 2010 15:05:56 +0200 Subject: [PATCH] Added indication of total BPS and ETA for file operations. * Optimized functions calls (changed return type of all file_progress_show*() functions) * Reworked for use global structure FileOpTotalContext * Moved declarations of file_progress_show*() functions from fileopctx.h to filegui.h * Code for calculate progressbar's variables was moved into function copy_file_file_display_progress() * Progressbar for little files now shows always 100% (for visible effect) * Added i18n string '< 1 sec' * Rework of progress copy dialog Signed-off-by: Slava Zanko Signed-off-by: Andrew Borodin --- lib/util.c | 11 +- src/file.c | 348 +++++++++++++++++++++++++----------------------- src/file.h | 22 +-- src/filegui.c | 234 ++++++++++++++++++++------------ src/filegui.h | 10 ++ src/fileopctx.c | 17 +++ src/fileopctx.h | 30 +++-- src/tree.c | 34 +++-- 8 files changed, 419 insertions(+), 287 deletions(-) diff --git a/lib/util.c b/lib/util.c index a6e99e419..e94167925 100644 --- a/lib/util.c +++ b/lib/util.c @@ -539,15 +539,16 @@ check_for_default (const char *default_file, const char *file) { if (!exist_file (file)) { FileOpContext *ctx; - off_t count = 0; - double bytes = 0.0; + FileOpTotalContext *tctx; if (!exist_file (default_file)) return -1; ctx = file_op_context_new (OP_COPY); - file_op_context_create_ui (ctx, 0); - copy_file_file (ctx, default_file, file, TRUE, &count, &bytes, TRUE); + tctx = file_op_total_context_new (); + file_op_context_create_ui (ctx, 0, FALSE); + copy_file_file (tctx, ctx, default_file, file); + file_op_total_context_destroy (tctx); file_op_context_destroy (ctx); } @@ -1444,7 +1445,7 @@ save_file_position (const char *filename, long line, long column, off_t offset) /* put the new record */ if (line != 1 || column != 0) { - if (fprintf (f, "%s %ld;%ld;%lli\n", filename, line, column, offset) < 0) + if (fprintf (f, "%s %ld;%ld;%li\n", filename, line, column, offset) < 0) goto write_position_error; } diff --git a/src/file.c b/src/file.c index 24f762efc..1341f01a5 100644 --- a/src/file.c +++ b/src/file.c @@ -54,7 +54,6 @@ #include #include #include -#include #include "lib/global.h" #include "lib/tty/tty.h" @@ -138,9 +137,8 @@ static FileProgressStatus query_replace (FileOpContext * ctx, const char *destna static FileProgressStatus query_recursive (FileOpContext * ctx, const char *s); static FileProgressStatus do_file_error (const char *str); static FileProgressStatus erase_dir_iff_empty (FileOpContext *ctx, const char *s); -static FileProgressStatus erase_file (FileOpContext *ctx, const char *s, - off_t *progress_count, double *progress_bytes, - gboolean is_toplevel_file); +static FileProgressStatus erase_file (FileOpTotalContext *tctx, FileOpContext *ctx, + const char *s, gboolean is_toplevel_file); static FileProgressStatus files_error (const char *format, const char *file1, const char *file2); @@ -346,26 +344,20 @@ make_symlink (FileOpContext *ctx, const char *src_path, const char *dst_path) return return_status; } -static int -progress_update_one (FileOpContext *ctx, - off_t *progress_count, double *progress_bytes, - off_t add, gboolean is_toplevel_file) +static FileProgressStatus +progress_update_one (FileOpTotalContext *tctx, FileOpContext *ctx, off_t add, gboolean is_toplevel_file) { - int ret; if (is_toplevel_file || ctx->progress_totals_computed) { - (*progress_count)++; - (*progress_bytes) += add; + tctx->progress_count++; + tctx->progress_bytes += add; } /* Apply some heuristic here to not call the update stuff very often */ - ret = file_progress_show_count (ctx, *progress_count, - ctx->progress_count); - if (ret == FILE_CONT) - ret = file_progress_show_bytes (ctx, *progress_bytes, - ctx->progress_bytes); + file_progress_show_count (ctx, tctx->progress_count, ctx->progress_count); + file_progress_show_bytes (ctx, tctx->progress_bytes, ctx->progress_bytes); - return ret; + return check_progress_buttons (ctx); } /* Status of the destination file */ @@ -422,10 +414,59 @@ warn_same_file (const char *fmt, const char *a, const char *b) } #endif +#define FILEOP_UPDATE_INTERVAL 2 +#define FILEOP_STALLING_INTERVAL 4 +static void +copy_file_file_display_progress (FileOpTotalContext *tctx, FileOpContext *ctx, + struct timeval tv_current, struct timeval tv_transfer_start, + off_t file_size, off_t n_read_total) +{ + long dt; + + /* 1. Update rotating dash after some time */ + rotate_dash (); + + /* 3. Compute ETA */ + dt = (tv_current.tv_sec - tv_transfer_start.tv_sec); + + if (n_read_total) { + ctx->eta_secs = ((dt / (double) n_read_total) * file_size) - dt; + ctx->bps = n_read_total / ((dt < 1) ? 1 : dt); + } else + ctx->eta_secs = 0.0; + + /* 4. Compute BPS rate */ + ctx->bps_time = (tv_current.tv_sec - tv_transfer_start.tv_sec); + if (ctx->bps_time < 1) + ctx->bps_time = 1; + ctx->bps = n_read_total / ctx->bps_time; + + /* 5. Compute total ETA and BPS*/ + if (ctx->progress_bytes != 0) { + double remain_bytes; + tctx->copyed_bytes = tctx->progress_bytes + n_read_total + ctx->do_reget; + remain_bytes = ctx->progress_bytes - tctx->copyed_bytes; +#if 1 + { + int total_secs = tv_current.tv_sec - tctx->transfer_start.tv_sec; + + if (total_secs < 1) + total_secs = 1; + tctx->bps = tctx->copyed_bytes / total_secs; + tctx->eta_secs = remain_bytes / tctx->bps; + } +#else + /* broken on lot of little files */ + tctx->bps_count++; + tctx->bps = ( tctx->bps * (tctx->bps_count - 1) + ctx->bps) / tctx->bps_count; + tctx->eta_secs = remain_bytes / tctx->bps; +#endif + } +} + FileProgressStatus -copy_file_file (FileOpContext *ctx, const char *src_path, const char *dst_path, - gboolean ask_overwrite, off_t *progress_count, - double *progress_bytes, gboolean is_toplevel_file) +copy_file_file (FileOpTotalContext *tctx, FileOpContext *ctx, + const char *src_path, const char *dst_path) { uid_t src_uid = (uid_t) -1; gid_t src_gid = (gid_t) -1; @@ -441,13 +482,15 @@ copy_file_file (FileOpContext *ctx, const char *src_path, const char *dst_path, struct timeval tv_transfer_start; dest_status_t dst_status = DEST_NONE; int open_flags; + gboolean is_first_time=TRUE; /* FIXME: We should not be using global variables! */ ctx->do_reget = 0; return_status = FILE_RETRY; - if (file_progress_show_source (ctx, src_path) == FILE_ABORT || - file_progress_show_target (ctx, dst_path) == FILE_ABORT) + file_progress_show_source (ctx, src_path); + file_progress_show_target (ctx, dst_path); + if (check_progress_buttons (ctx) == FILE_ABORT) return FILE_ABORT; mc_refresh (); @@ -479,7 +522,7 @@ copy_file_file (FileOpContext *ctx, const char *src_path, const char *dst_path, return warn_same_file (_(" `%s' \n and \n `%s' \n are the same file "), src_path, dst_path); /* Should we replace destination? */ - if (ask_overwrite) { + if (tctx->ask_overwrite) { ctx->do_reget = 0; return_status = query_replace (ctx, dst_path, &sb, &sb2); if (return_status != FILE_CONT) @@ -604,8 +647,12 @@ copy_file_file (FileOpContext *ctx, const char *src_path, const char *dst_path, ctx->eta_secs = 0.0; ctx->bps = 0; - return_status = file_progress_show (ctx, 0, file_size); - + if (tctx->bps == 0 || (file_size/(tctx->bps)) > FILEOP_UPDATE_INTERVAL) { + file_progress_show (ctx, 0, file_size); + } else { + file_progress_show (ctx, 1, 1); + } + return_status = check_progress_buttons (ctx); mc_refresh (); if (return_status != FILE_CONT) @@ -614,8 +661,7 @@ copy_file_file (FileOpContext *ctx, const char *src_path, const char *dst_path, { struct timeval tv_current, tv_last_update, tv_last_input; int secs, update_secs; - long dt; - const char *stalled_msg; + const char *stalled_msg=""; tv_last_update = tv_transfer_start; @@ -665,59 +711,43 @@ copy_file_file (FileOpContext *ctx, const char *src_path, const char *dst_path, goto ret; } } - - /* 1. Update rotating dash after some time (hardcoded to 2 seconds) */ secs = (tv_current.tv_sec - tv_last_update.tv_sec); - if (secs > 2) { - rotate_dash (); + update_secs = (tv_current.tv_sec - tv_last_input.tv_sec); + + if (is_first_time || secs > FILEOP_UPDATE_INTERVAL ) + { + copy_file_file_display_progress(tctx, ctx, + tv_current, + tv_transfer_start, + file_size, + n_read_total); tv_last_update = tv_current; } + is_first_time = FALSE; - /* 2. Check for a stalled condition */ - update_secs = (tv_current.tv_sec - tv_last_input.tv_sec); - stalled_msg = ""; - if (update_secs > 4) { - stalled_msg = _("(stalled)"); - } + if (update_secs > FILEOP_STALLING_INTERVAL) { + stalled_msg = _("(stalled)"); + } - /* 3. Compute ETA */ - if (secs > 2) { - dt = (tv_current.tv_sec - tv_transfer_start.tv_sec); - if (n_read_total) { - ctx->eta_secs = - ((dt / (double) n_read_total) * file_size) - dt; - ctx->bps = n_read_total / ((dt < 1) ? 1 : dt); - } else - ctx->eta_secs = 0.0; - } + file_progress_set_stalled_label (ctx, stalled_msg); + file_progress_show_count (ctx, tctx->progress_count, ctx->progress_count); + file_progress_show_bytes (ctx, tctx->progress_bytes + n_read_total + ctx->do_reget, + ctx->progress_bytes); - /* 4. Compute BPS rate */ - if (secs > 2) { - ctx->bps_time = - (tv_current.tv_sec - tv_transfer_start.tv_sec); - if (ctx->bps_time < 1) - ctx->bps_time = 1; - ctx->bps = n_read_total / ctx->bps_time; - } + if ((ctx->progress_bytes != 0) && (tv_current.tv_sec - tctx->transfer_start.tv_sec) > FILEOP_UPDATE_INTERVAL) { + file_progress_show_total (tctx, ctx); + } - file_progress_set_stalled_label (ctx, stalled_msg); + file_progress_show (ctx, n_read_total + ctx->do_reget, file_size); + mc_refresh (); - return_status = - file_progress_show_count (ctx, *progress_count, - ctx->progress_count); - if (return_status == FILE_CONT) - return_status = - file_progress_show_bytes (ctx, *progress_bytes + - n_read_total + ctx->do_reget, - ctx->progress_bytes); - if (return_status == FILE_CONT) - return_status = - file_progress_show (ctx, n_read_total + ctx->do_reget, file_size); + return_status = check_progress_buttons (ctx); - mc_refresh (); - if (return_status != FILE_CONT) + if (return_status != FILE_CONT) { + mc_refresh (); goto ret; + } } } @@ -785,13 +815,11 @@ copy_file_file (FileOpContext *ctx, const char *src_path, const char *dst_path, } if (return_status == FILE_CONT) - return_status = - progress_update_one (ctx, progress_count, progress_bytes, - file_size, is_toplevel_file); + return_status = progress_update_one (tctx, ctx, file_size, tctx->is_toplevel_file); return return_status; } - +#undef FILEOP_UPDATE_INTERVAL /* * I think these copy_*_* functions should have a return type. * anyway, this function *must* have two directories as arguments. @@ -799,10 +827,9 @@ copy_file_file (FileOpContext *ctx, const char *src_path, const char *dst_path, /* FIXME: This function needs to check the return values of the function calls */ FileProgressStatus -copy_dir_dir (FileOpContext *ctx, const char *s, const char *_d, +copy_dir_dir (FileOpTotalContext *tctx, FileOpContext *ctx, const char *s, const char *_d, gboolean toplevel, gboolean move_over, gboolean do_delete, - struct link *parent_dirs, - off_t *progress_count, double *progress_bytes) + struct link *parent_dirs) { struct dirent *next; struct stat buf, cbuf; @@ -957,15 +984,13 @@ copy_dir_dir (FileOpContext *ctx, const char *s, const char *_d, * dir already exists. So, we give the recursive call the flag 0 * meaning no toplevel. */ - return_status = copy_dir_dir (ctx, path, mdpath, FALSE, FALSE, do_delete, - parent_dirs, progress_count, progress_bytes); + return_status = copy_dir_dir (tctx, ctx, path, mdpath, FALSE, FALSE, do_delete, parent_dirs); g_free (mdpath); } else { char *dest_file; dest_file = concat_dir_and_file (dest_dir, x_basename (path)); - return_status = copy_file_file (ctx, path, dest_file, TRUE, - progress_count, progress_bytes, FALSE); + return_status = copy_file_file (tctx, ctx, path, dest_file); g_free (dest_file); } if (do_delete && return_status == FILE_CONT) { @@ -985,7 +1010,7 @@ copy_dir_dir (FileOpContext *ctx, const char *s, const char *_d, if (S_ISDIR (buf.st_mode)) { return_status = erase_dir_iff_empty (ctx, path); } else - return_status = erase_file (ctx, path, 0, 0, FALSE); + return_status = erase_file (tctx, ctx, path, FALSE); } } g_free (path); @@ -1017,15 +1042,15 @@ copy_dir_dir (FileOpContext *ctx, const char *s, const char *_d, /* {{{ Move routines */ static FileProgressStatus -move_file_file (FileOpContext *ctx, const char *s, const char *d, - off_t *progress_count, double *progress_bytes) +move_file_file (FileOpTotalContext *tctx, FileOpContext *ctx, const char *s, const char *d) { struct stat src_stats, dst_stats; FileProgressStatus return_status = FILE_CONT; gboolean copy_done = FALSE; - if (file_progress_show_source (ctx, s) == FILE_ABORT - || file_progress_show_target (ctx, d) == FILE_ABORT) + file_progress_show_source (ctx, s); + file_progress_show_target (ctx, d); + if (check_progress_buttons (ctx) == FILE_ABORT) return FILE_ABORT; mc_refresh (); @@ -1067,9 +1092,7 @@ move_file_file (FileOpContext *ctx, const char *s, const char *d, } if (mc_rename (s, d) == 0) { - return progress_update_one (ctx, progress_count, - progress_bytes, - src_stats.st_size, TRUE); + return progress_update_one (tctx, ctx, src_stats.st_size, TRUE); } } #if 0 @@ -1091,16 +1114,17 @@ move_file_file (FileOpContext *ctx, const char *s, const char *d, #endif /* Failed because filesystem boundary -> copy the file instead */ - return_status = - copy_file_file (ctx, s, d, FALSE, progress_count, progress_bytes, TRUE); + return_status = copy_file_file (tctx, ctx, s, d); if (return_status != FILE_CONT) return return_status; copy_done = TRUE; - if ((return_status = - file_progress_show_source (ctx, NULL)) != FILE_CONT - || (return_status = file_progress_show (ctx, 0, 0)) != FILE_CONT) + file_progress_show_source (ctx, NULL); + file_progress_show (ctx, 0, 0); + + return_status = check_progress_buttons (ctx); + if (return_status != FILE_CONT) return return_status; mc_refresh (); @@ -1115,18 +1139,14 @@ move_file_file (FileOpContext *ctx, const char *s, const char *d, } if (!copy_done) { - return_status = progress_update_one (ctx, - progress_count, - progress_bytes, - src_stats.st_size, TRUE); + return_status = progress_update_one (tctx, ctx, src_stats.st_size, TRUE); } return return_status; } FileProgressStatus -move_dir_dir (FileOpContext *ctx, const char *s, const char *d, - off_t *progress_count, double *progress_bytes) +move_dir_dir (FileOpTotalContext *tctx, FileOpContext *ctx, const char *s, const char *d) { struct stat sbuf, dbuf, destbuf; struct link *lp; @@ -1135,8 +1155,9 @@ move_dir_dir (FileOpContext *ctx, const char *s, const char *d, gboolean move_over = FALSE; gboolean dstat_ok; - if (file_progress_show_source (ctx, s) == FILE_ABORT || - file_progress_show_target (ctx, d) == FILE_ABORT) + file_progress_show_source (ctx, s); + file_progress_show_target (ctx, d); + if (check_progress_buttons (ctx) == FILE_ABORT) return FILE_ABORT; mc_refresh (); @@ -1159,8 +1180,7 @@ move_dir_dir (FileOpContext *ctx, const char *s, const char *d, retry_dst_stat: if (!mc_stat (destdir, &destbuf)) { if (move_over) { - return_status = copy_dir_dir (ctx, s, destdir, FALSE, TRUE, TRUE, - NULL, progress_count, progress_bytes); + return_status = copy_dir_dir (tctx, ctx, s, destdir, FALSE, TRUE, TRUE, NULL); if (return_status != FILE_CONT) goto ret; @@ -1199,15 +1219,16 @@ move_dir_dir (FileOpContext *ctx, const char *s, const char *d, } /* Failed because of filesystem boundary -> copy dir instead */ return_status = - copy_dir_dir (ctx, s, destdir, FALSE, FALSE, TRUE, - NULL, progress_count, progress_bytes); + copy_dir_dir (tctx, ctx, s, destdir, FALSE, FALSE, TRUE, NULL); if (return_status != FILE_CONT) goto ret; oktoret: - if ((return_status = - file_progress_show_source (ctx, NULL)) != FILE_CONT - || (return_status = file_progress_show (ctx, 0, 0)) != FILE_CONT) + file_progress_show_source (ctx, NULL); + file_progress_show (ctx, 0, 0); + + return_status = check_progress_buttons (ctx); + if (return_status != FILE_CONT) goto ret; mc_refresh (); @@ -1218,7 +1239,7 @@ move_dir_dir (FileOpContext *ctx, const char *s, const char *d, erase_dir_iff_empty (ctx, erase_list->name); } else return_status = - erase_file (ctx, erase_list->name, 0, 0, FALSE); + erase_file (tctx, ctx, erase_list->name, FALSE); lp = erase_list; erase_list = erase_list->next; g_free (lp); @@ -1241,17 +1262,17 @@ move_dir_dir (FileOpContext *ctx, const char *s, const char *d, /* {{{ Erase routines */ /* Don't update progress status if progress_count==NULL */ static FileProgressStatus -erase_file (FileOpContext *ctx, const char *s, off_t *progress_count, - double *progress_bytes, gboolean is_toplevel_file) +erase_file (FileOpTotalContext *tctx, FileOpContext *ctx, const char *s, gboolean is_toplevel_file) { int return_status; struct stat buf; - if (file_progress_show_deleting (ctx, s) == FILE_ABORT) + file_progress_show_deleting (ctx, s); + if (check_progress_buttons (ctx) == FILE_ABORT) return FILE_ABORT; mc_refresh (); - if (progress_count && mc_lstat (s, &buf)) { + if (tctx->progress_count && mc_lstat (s, &buf)) { /* ignore, most likely the mc_unlink fails, too */ buf.st_size = 0; } @@ -1263,16 +1284,14 @@ erase_file (FileOpContext *ctx, const char *s, off_t *progress_count, return return_status; } - if (progress_count) - return progress_update_one (ctx, progress_count, progress_bytes, - buf.st_size, is_toplevel_file); + if (tctx->progress_count) + return progress_update_one (tctx, ctx, buf.st_size, is_toplevel_file); else return FILE_CONT; } static FileProgressStatus -recursive_erase (FileOpContext *ctx, const char *s, off_t *progress_count, - double *progress_bytes) +recursive_erase (FileOpTotalContext *tctx, FileOpContext *ctx, const char *s) { struct dirent *next; struct stat buf; @@ -1301,18 +1320,17 @@ recursive_erase (FileOpContext *ctx, const char *s, off_t *progress_count, } if (S_ISDIR (buf.st_mode)) return_status = - (recursive_erase - (ctx, path, progress_count, progress_bytes) - != FILE_CONT) ? FILE_RETRY : FILE_CONT; + (recursive_erase (tctx, ctx, path) != FILE_CONT) ? FILE_RETRY : FILE_CONT; else return_status = - erase_file (ctx, path, progress_count, progress_bytes, 0); + erase_file (tctx, ctx, path, 0); g_free (path); } mc_closedir (reading); if (return_status != FILE_CONT) return return_status; - if (file_progress_show_deleting (ctx, s) == FILE_ABORT) + file_progress_show_deleting (ctx, s); + if (check_progress_buttons (ctx) == FILE_ABORT) return FILE_ABORT; mc_refresh (); @@ -1353,8 +1371,7 @@ check_dir_is_empty (const char *path) } FileProgressStatus -erase_dir (FileOpContext *ctx, const char *s, off_t *progress_count, - double *progress_bytes) +erase_dir (FileOpTotalContext *tctx, FileOpContext *ctx, const char *s) { FileProgressStatus error; @@ -1364,7 +1381,8 @@ erase_dir (FileOpContext *ctx, const char *s, off_t *progress_count, if (strcmp (s, ".") == 0) return FILE_SKIP; - if (file_progress_show_deleting (ctx, s) == FILE_ABORT) + file_progress_show_deleting (ctx, s); + if (check_progress_buttons (ctx) == FILE_ABORT) return FILE_ABORT; mc_refresh (); @@ -1379,8 +1397,7 @@ erase_dir (FileOpContext *ctx, const char *s, off_t *progress_count, if (error == 0) { /* not empty */ error = query_recursive (ctx, s); if (error == FILE_CONT) - return recursive_erase (ctx, s, progress_count, - progress_bytes); + return recursive_erase (tctx, ctx, s); else return error; } @@ -1406,7 +1423,8 @@ erase_dir_iff_empty (FileOpContext *ctx, const char *s) if (strcmp (s, ".") == 0) return FILE_SKIP; - if (file_progress_show_deleting (ctx, s) == FILE_ABORT) + file_progress_show_deleting (ctx, s); + if (check_progress_buttons (ctx) == FILE_ABORT) return FILE_ABORT; mc_refresh (); @@ -1869,9 +1887,7 @@ panel_operate (void *source_panel, FileOperation operation, gboolean force_singl int i; FileProgressStatus value; FileOpContext *ctx; - - off_t count = 0; - double bytes = 0; + FileOpTotalContext *tctx; gboolean do_bg = FALSE; /* do background operation? */ @@ -1908,6 +1924,8 @@ panel_operate (void *source_panel, FileOperation operation, gboolean force_singl } ctx = file_op_context_new (operation); + tctx = file_op_total_context_new (); + gettimeofday (&(tctx->transfer_start), (struct timezone *) NULL); /* Show confirmation dialog */ if (operation != OP_DELETE) { @@ -1937,6 +1955,7 @@ panel_operate (void *source_panel, FileOperation operation, gboolean force_singl dest_dir_ = g_strdup (dest_dir); } if (dest_dir_ == NULL) { + file_op_total_context_destroy (tctx); file_op_context_destroy (ctx); return FALSE; } @@ -1954,6 +1973,7 @@ panel_operate (void *source_panel, FileOperation operation, gboolean force_singl g_free (dest_dir_); if (dest == NULL || dest[0] == '\0') { + file_op_total_context_destroy (tctx); file_op_context_destroy (ctx); g_free (dest); return FALSE; @@ -1984,16 +2004,23 @@ panel_operate (void *source_panel, FileOperation operation, gboolean force_singl _("&Yes"), _("&No")); if (i != 0) { + file_op_total_context_destroy (tctx); file_op_context_destroy (ctx); return FALSE; } } + { + gboolean show_total = !((operation != OP_COPY) || (single_entry) || (force_single)); + + if ((single_entry) && (operation == OP_COPY) && S_ISDIR (selection (panel)->st.st_mode)) + show_total = TRUE; /* Background also need ctx->ui, but not full */ if (do_bg) - file_op_context_create_ui_without_init (ctx, 1); + file_op_context_create_ui_without_init (ctx, 1, show_total); else - file_op_context_create_ui (ctx, 1); + file_op_context_create_ui (ctx, 1, show_total); + } #ifdef WITH_BACKGROUND /* Did the user select to do a background operation? */ @@ -2049,9 +2076,9 @@ panel_operate (void *source_panel, FileOperation operation, gboolean force_singl source_with_path, ctx) == FILE_CONT) { if (operation == OP_DELETE) { if (S_ISDIR (src_stat.st_mode)) - value = erase_dir (ctx, source_with_path, &count, &bytes); + value = erase_dir (tctx, ctx, source_with_path); else - value = erase_file (ctx, source_with_path, &count, &bytes, 1); + value = erase_file (tctx, ctx, source_with_path, 1); } else { temp = transform_source (ctx, source_with_path); if (temp == NULL) @@ -2072,21 +2099,17 @@ panel_operate (void *source_panel, FileOperation operation, gboolean force_singl ctx->stat_func (source_with_path, &src_stat); if (S_ISDIR (src_stat.st_mode)) - value = copy_dir_dir (ctx, source_with_path, dest, - TRUE, FALSE, FALSE, - NULL, &count, &bytes); + value = copy_dir_dir (tctx, ctx, source_with_path, dest, + TRUE, FALSE, FALSE, NULL); else - value = copy_file_file (ctx, source_with_path, dest, TRUE, - &count, &bytes, TRUE); + value = copy_file_file (tctx, ctx, source_with_path, dest); break; case OP_MOVE: if (S_ISDIR (src_stat.st_mode)) - value = move_dir_dir (ctx, source_with_path, dest, - &count, &bytes); + value = move_dir_dir (tctx, ctx, source_with_path, dest); else - value = move_file_file (ctx, source_with_path, dest, - &count, &bytes); + value = move_file_file (tctx, ctx, source_with_path, dest); break; default: @@ -2133,9 +2156,9 @@ panel_operate (void *source_panel, FileOperation operation, gboolean force_singl if (operation == OP_DELETE) { if (S_ISDIR (src_stat.st_mode)) - value = erase_dir (ctx, source_with_path, &count, &bytes); + value = erase_dir (tctx, ctx, source_with_path); else - value = erase_file (ctx, source_with_path, &count, &bytes, 1); + value = erase_file (tctx, ctx, source_with_path, 1); } else { temp = transform_source (ctx, source_with_path); @@ -2160,22 +2183,18 @@ panel_operate (void *source_panel, FileOperation operation, gboolean force_singl /* we use file_mask_op_follow_links only with OP_COPY */ ctx->stat_func (source_with_path, &src_stat); if (S_ISDIR (src_stat.st_mode)) - value = copy_dir_dir (ctx, source_with_path, temp2, - TRUE, FALSE, FALSE, - NULL, &count, &bytes); + value = copy_dir_dir (tctx, ctx, source_with_path, temp2, + TRUE, FALSE, FALSE, NULL); else - value = copy_file_file (ctx, source_with_path, temp2, - TRUE, &count, &bytes, TRUE); + value = copy_file_file (tctx, ctx, source_with_path, temp2); free_linklist (&dest_dirs); break; case OP_MOVE: if (S_ISDIR (src_stat.st_mode)) - value = move_dir_dir (ctx, source_with_path, temp2, - &count, &bytes); + value = move_dir_dir (tctx, ctx, source_with_path, temp2); else - value = move_file_file (ctx, source_with_path, - temp2, &count, &bytes); + value = move_file_file (tctx, ctx, source_with_path, temp2); break; default: @@ -2193,20 +2212,19 @@ panel_operate (void *source_panel, FileOperation operation, gboolean force_singl if (value == FILE_CONT) do_file_mark (panel, i, 0); - if (file_progress_show_count (ctx, count, - ctx->progress_count) == FILE_ABORT) - break; + file_progress_show_count (ctx, tctx->progress_count, ctx->progress_count); + if (verbose) { - if (file_progress_show_bytes (ctx, bytes, - ctx->progress_bytes) == FILE_ABORT) - break; + file_progress_show_bytes (ctx, tctx->progress_bytes, ctx->progress_bytes); - if ((operation != OP_DELETE) - && (file_progress_show (ctx, 0, 0) == FILE_ABORT)) - break; + if (operation != OP_DELETE) + file_progress_show (ctx, 0, 0); } + if (check_progress_buttons (ctx) == FILE_ABORT) + break; + mc_refresh (); } /* Loop for every file */ } diff --git a/src/file.h b/src/file.h index 5105ba870..86b1c8f66 100644 --- a/src/file.h +++ b/src/file.h @@ -7,6 +7,7 @@ #define MC_FILE_H #include /* off_t */ +#include #include "lib/global.h" #include "dialog.h" /* Dlg_head */ @@ -15,17 +16,16 @@ struct link; -FileProgressStatus copy_file_file (FileOpContext *ctx, const char *s, const char *d, - gboolean ask_overwrite, off_t *progress_count, - double *progress_bytes, gboolean is_toplevel_file); -FileProgressStatus move_dir_dir (FileOpContext *ctx, const char *s, const char *d, - off_t *progress_count, double *progress_bytes); -FileProgressStatus copy_dir_dir (FileOpContext *ctx, const char *s, const char *d, - gboolean toplevel, gboolean move_over, - gboolean do_delete, struct link *parent_dirs, - off_t *progress_count, double *progress_bytes); -FileProgressStatus erase_dir (FileOpContext *ctx, const char *s, off_t *progress_count, - double *progress_bytes); +FileProgressStatus copy_file_file (FileOpTotalContext *tctx, FileOpContext *ctx, + const char *src_path, const char *dst_path); +FileProgressStatus move_dir_dir (FileOpTotalContext *tctx, FileOpContext *ctx, + const char *s, const char *d); +FileProgressStatus copy_dir_dir (FileOpTotalContext *tctx, FileOpContext *ctx, + const char *s, const char *d, + gboolean toplevel, gboolean move_over, gboolean do_delete, + struct link *parent_dirs); +FileProgressStatus erase_dir (FileOpTotalContext *tctx, FileOpContext *ctx, + const char *s); gboolean panel_operate (void *source_panel, FileOperation op, gboolean force_single); diff --git a/src/filegui.c b/src/filegui.c index cf0dd0040..271c5f92b 100644 --- a/src/filegui.c +++ b/src/filegui.c @@ -134,12 +134,16 @@ typedef struct { Dlg_head *op_dlg; WLabel *file_label[2]; WLabel *file_string[2]; - WLabel *progress_label[3]; - WGauge *progress_gauge[3]; + WLabel *progress_label[2]; + WGauge *progress_gauge[2]; WLabel *eta_label; WLabel *bps_label; WLabel *stalled_label; + WLabel *total_files_processed_label; + WLabel *time_label; + WLabel *total_bytes_label; + /* Query replace dialog */ Dlg_head *replace_dlg; const char *replace_filename; @@ -154,8 +158,8 @@ static int last_hint_line; /* File operate window sizes */ #define WX 62 -#define WY 10 -#define BY 10 +#define WY 12 +#define BY 12 #define WX_ETA_EXTRA 12 #define FCOPY_GAUGE_X 14 @@ -207,7 +211,7 @@ filegui__check_attrs_on_fs (const char *fs_path) return TRUE; } -static FileProgressStatus +FileProgressStatus check_progress_buttons (FileOpContext *ctx) { int c; @@ -243,11 +247,11 @@ check_progress_buttons (FileOpContext *ctx) /* {{{ File progress display routines */ void -file_op_context_create_ui_without_init (FileOpContext *ctx, gboolean with_eta) +file_op_context_create_ui_without_init (FileOpContext *ctx, gboolean with_eta, gboolean show_total) { FileOpContextUI *ui; int x_size; - int minus; + int minus, total_reserve=0; int eta_offset; const char *sixty; const char *fifteen; @@ -258,9 +262,13 @@ file_op_context_create_ui_without_init (FileOpContext *ctx, gboolean with_eta) ui = g_new0 (FileOpContextUI, 1); ctx->ui = ui; + ctx->show_total = show_total; minus = verbose ? 0 : 3; eta_offset = with_eta ? (WX_ETA_EXTRA) / 2 : 0; + if (show_total) + total_reserve = 3; + sixty = ""; fifteen = ""; @@ -273,7 +281,7 @@ file_op_context_create_ui_without_init (FileOpContext *ctx, gboolean with_eta) x_size = (WX + 4) + ui->eta_extra; ui->op_dlg = - create_dlg (0, 0, WY - minus + 4, x_size, dialog_colors, NULL, + create_dlg (0, 0, WY - minus + 1 + total_reserve, x_size, dialog_colors, NULL, NULL, op_names[ctx->operation], DLG_CENTER | DLG_REVERSE); @@ -282,22 +290,32 @@ file_op_context_create_ui_without_init (FileOpContext *ctx, gboolean with_eta) the_hint->widget.y = ui->op_dlg->y + ui->op_dlg->lines + 1; add_widget (ui->op_dlg, - button_new (BY - minus, WX - 19 + eta_offset, FILE_ABORT, + button_new (BY - minus - 2 + total_reserve, WX - 19 + eta_offset, FILE_ABORT, NORMAL_BUTTON, _("&Abort"), 0)); add_widget (ui->op_dlg, - button_new (BY - minus, 14 + eta_offset, FILE_SKIP, + button_new (BY - minus - 2 + total_reserve, 14 + eta_offset, FILE_SKIP, NORMAL_BUTTON, _("&Skip"), 0)); - add_widget (ui->op_dlg, ui->progress_gauge[2] = - gauge_new (7, FCOPY_GAUGE_X, 0, 100, 0)); - add_widget (ui->op_dlg, ui->progress_label[2] = - label_new (7, FCOPY_LABEL_X, fifteen)); - add_widget (ui->op_dlg, ui->bps_label = label_new (7, WX, "")); + if (show_total) { + add_widget (ui->op_dlg, ui->total_files_processed_label = + label_new (9, FCOPY_LABEL_X, "")); + + add_widget (ui->op_dlg, ui->total_bytes_label = + label_new (10, FCOPY_LABEL_X, "")); + + add_widget (ui->op_dlg, ui->time_label = + label_new (11, FCOPY_LABEL_X, "")); + + add_widget (ui->op_dlg, hline_new (8, 0, -1)); + } add_widget (ui->op_dlg, ui->progress_gauge[1] = - gauge_new (8, FCOPY_GAUGE_X, 0, 100, 0)); + gauge_new (7, FCOPY_GAUGE_X, 0, 100, 0)); add_widget (ui->op_dlg, ui->progress_label[1] = - label_new (8, FCOPY_LABEL_X, fifteen)); + label_new (7, FCOPY_LABEL_X, fifteen)); + + add_widget (ui->op_dlg, ui->bps_label = label_new (7, WX, "")); + add_widget (ui->op_dlg, ui->stalled_label = label_new (8, WX, "")); add_widget (ui->op_dlg, ui->progress_gauge[0] = @@ -317,14 +335,14 @@ file_op_context_create_ui_without_init (FileOpContext *ctx, gboolean with_eta) } void -file_op_context_create_ui (FileOpContext *ctx, gboolean with_eta) +file_op_context_create_ui (FileOpContext *ctx, gboolean with_eta, gboolean show_total) { FileOpContextUI *ui; g_return_if_fail (ctx != NULL); g_return_if_fail (ctx->ui == NULL); - file_op_context_create_ui_without_init (ctx, with_eta); + file_op_context_create_ui_without_init (ctx, with_eta, show_total); ui = ctx->ui; /* We will manage the dialog without any help, that's why @@ -353,13 +371,13 @@ file_op_context_destroy_ui (FileOpContext *ctx) ctx->ui = NULL; } -static FileProgressStatus +static void show_no_bar (FileOpContext *ctx, int n) { FileOpContextUI *ui; if (ctx->ui == NULL) - return FILE_CONT; + return; ui = ctx->ui; @@ -367,16 +385,15 @@ show_no_bar (FileOpContext *ctx, int n) label_set_text (ui->progress_label[n], ""); gauge_show (ui->progress_gauge[n], 0); } - return check_progress_buttons (ctx); } -static FileProgressStatus +static void show_bar (FileOpContext *ctx, int n, double done, double total) { FileOpContextUI *ui; if (ctx->ui == NULL) - return FILE_CONT; + return; ui = ctx->ui; @@ -387,13 +404,34 @@ show_bar (FileOpContext *ctx, int n, double done, double total) gauge_set_value (ui->progress_gauge[n], 1024, (int) (1024 * done / total)); gauge_show (ui->progress_gauge[n], 1); - return check_progress_buttons (ctx); } static void -file_eta_show (FileOpContext *ctx) +file_frmt_time (char *buffer, double eta_secs) { int eta_hours, eta_mins, eta_s; + eta_hours = eta_secs / (60 * 60); + eta_mins = (eta_secs - (eta_hours * 60 * 60)) / 60; + eta_s = eta_secs - (eta_hours * 60 * 60 + eta_mins * 60); + g_snprintf (buffer, BUF_TINY, _("%d:%02d.%02d"), eta_hours, eta_mins, eta_s); +} + +static void +file_eta_prepare_for_show (char *buffer, double eta_secs, gboolean always_show) +{ + char _fmt_buff[BUF_TINY]; + if (eta_secs <= 0.5 && !always_show) { + *buffer = '\0'; + return; + } + if (eta_secs <= 0.5) + eta_secs = 1; + file_frmt_time (_fmt_buff, eta_secs); + g_snprintf (buffer, BUF_TINY, _("ETA %s"), _fmt_buff); +} +static void +file_eta_show (FileOpContext *ctx) +{ char eta_buffer[BUF_TINY]; FileOpContextUI *ui; @@ -405,18 +443,26 @@ file_eta_show (FileOpContext *ctx) if (!ui->showing_eta) return; - if (ctx->eta_secs > 0.5) { - eta_hours = ctx->eta_secs / (60 * 60); - eta_mins = (ctx->eta_secs - (eta_hours * 60 * 60)) / 60; - eta_s = ctx->eta_secs - (eta_hours * 60 * 60 + eta_mins * 60); - g_snprintf (eta_buffer, sizeof (eta_buffer), _("ETA %d:%02d.%02d"), - eta_hours, eta_mins, eta_s); - } else - *eta_buffer = 0; - + file_eta_prepare_for_show (eta_buffer, ctx->eta_secs, FALSE); label_set_text (ui->eta_label, eta_buffer); } +static void +file_bps_prepare_for_show (char *buffer, long bps) +{ + if (bps > 1024 * 1024) { + g_snprintf (buffer, BUF_TINY, _("%.2f MB/s"), + bps / (1024 * 1024.0)); + } else if (bps > 1024) { + g_snprintf (buffer, BUF_TINY, _("%.2f KB/s"), + bps / 1024.0); + } else if (bps > 1) { + g_snprintf (buffer, BUF_TINY, _("%ld B/s"), + bps); + } else + *buffer = 0; +} + static void file_bps_show (FileOpContext *ctx) { @@ -431,84 +477,111 @@ file_bps_show (FileOpContext *ctx) if (!ui->showing_bps) return; - if (ctx->bps > 1024 * 1024) { - g_snprintf (bps_buffer, sizeof (bps_buffer), _("%.2f MB/s"), - ctx->bps / (1024 * 1024.0)); - } else if (ctx->bps > 1024) { - g_snprintf (bps_buffer, sizeof (bps_buffer), _("%.2f KB/s"), - ctx->bps / 1024.0); - } else if (ctx->bps > 1) { - g_snprintf (bps_buffer, sizeof (bps_buffer), _("%ld B/s"), - ctx->bps); - } else - *bps_buffer = 0; + file_bps_prepare_for_show (bps_buffer, ctx->bps); label_set_text (ui->bps_label, bps_buffer); } -FileProgressStatus +void file_progress_show (FileOpContext *ctx, off_t done, off_t total) { FileOpContextUI *ui; - g_return_val_if_fail (ctx != NULL, FILE_CONT); + g_return_if_fail (ctx != NULL); if (ctx->ui == NULL) - return FILE_CONT; + return; ui = ctx->ui; if (!verbose) - return check_progress_buttons (ctx); + return; + if (total > 0) { label_set_text (ui->progress_label[0], _("File")); file_eta_show (ctx); file_bps_show (ctx); - return show_bar (ctx, 0, done, total); + show_bar (ctx, 0, done, total); } else - return show_no_bar (ctx, 0); + show_no_bar (ctx, 0); } -FileProgressStatus +void file_progress_show_count (FileOpContext *ctx, off_t done, off_t total) { + char buffer[BUF_TINY]; FileOpContextUI *ui; - g_return_val_if_fail (ctx != NULL, FILE_CONT); + g_return_if_fail (ctx != NULL); - if (ctx->ui == NULL) - return FILE_CONT; + if (!ctx->show_total || ctx->ui == NULL) + return; ui = ctx->ui; if (!verbose) - return check_progress_buttons (ctx); - if (total > 0) { - label_set_text (ui->progress_label[1], _("Count")); - return show_bar (ctx, 1, done, total); - } else - return show_no_bar (ctx, 1); + return; + + g_snprintf (buffer, BUF_TINY, _("Files processed: %llu of %llu"), done, total); + + label_set_text (ui->total_files_processed_label, buffer); } -FileProgressStatus +void file_progress_show_bytes (FileOpContext *ctx, double done, double total) { FileOpContextUI *ui; - g_return_val_if_fail (ctx != NULL, FILE_CONT); + g_return_if_fail (ctx != NULL); if (ctx->ui == NULL) - return FILE_CONT; + return; ui = ctx->ui; if (!verbose) - return check_progress_buttons (ctx); + return; + if (total > 0) { - label_set_text (ui->progress_label[2], _("Bytes")); - return show_bar (ctx, 2, done, total); + label_set_text (ui->progress_label[1], _("Bytes")); + show_bar (ctx, 1, done, total); } else - return show_no_bar (ctx, 2); + show_no_bar (ctx, 1); +} + +void +file_progress_show_total (FileOpTotalContext *tctx, FileOpContext *ctx) +{ + char buffer[BUF_TINY]; + char buffer2[BUF_TINY]; + char buffer3[BUF_TINY]; + char buffer4[BUF_TINY]; + struct timeval tv_current; + FileOpContextUI *ui; + + if (!ctx->show_total || ctx->ui == NULL || tctx->bps == 0) + return; + + ui = ctx->ui; + + if (!verbose) + return; + + + gettimeofday (&tv_current, NULL); + file_frmt_time (buffer2, tv_current.tv_sec - tctx->transfer_start.tv_sec); + file_eta_prepare_for_show (buffer3, tctx->eta_secs, TRUE); + + g_snprintf (buffer, BUF_TINY, _("Time: %s ; %s"), buffer2, buffer3); + label_set_text (ui->time_label, buffer); + + file_bps_prepare_for_show (buffer2, (long) tctx->bps); + size_trunc_len (buffer3, 5, tctx->copyed_bytes, 0); + size_trunc_len (buffer4, 5, ctx->progress_bytes, 0); + + g_snprintf (buffer, BUF_TINY, _("Total: %s of %s (%s)"), buffer3, buffer4, buffer2); + + label_set_text (ui->total_bytes_label, buffer); } /* }}} */ @@ -516,15 +589,15 @@ file_progress_show_bytes (FileOpContext *ctx, double done, double total) #define truncFileString(ui, s) str_trunc (s, ui->eta_extra + 47) #define truncFileStringSecure(ui, s) path_trunc (s, ui->eta_extra + 47) -FileProgressStatus +void file_progress_show_source (FileOpContext *ctx, const char *s) { FileOpContextUI *ui; - g_return_val_if_fail (ctx != NULL, FILE_CONT); + g_return_if_fail (ctx != NULL); if (ctx->ui == NULL) - return FILE_CONT; + return; ui = ctx->ui; @@ -541,52 +614,47 @@ file_progress_show_source (FileOpContext *ctx, const char *s) label_set_text (ui->file_label[0], _("Source")); label_set_text (ui->file_string[0], truncFileString (ui, s)); - return check_progress_buttons (ctx); } else { label_set_text (ui->file_label[0], ""); label_set_text (ui->file_string[0], ""); - return check_progress_buttons (ctx); } } -FileProgressStatus +void file_progress_show_target (FileOpContext *ctx, const char *s) { FileOpContextUI *ui; - g_return_val_if_fail (ctx != NULL, FILE_CONT); + g_return_if_fail (ctx != NULL); if (ctx->ui == NULL) - return FILE_CONT; + return; ui = ctx->ui; if (s != NULL) { label_set_text (ui->file_label[1], _("Target")); label_set_text (ui->file_string[1], truncFileStringSecure (ui, s)); - return check_progress_buttons (ctx); } else { label_set_text (ui->file_label[1], ""); label_set_text (ui->file_string[1], ""); - return check_progress_buttons (ctx); } } -FileProgressStatus +void file_progress_show_deleting (FileOpContext *ctx, const char *s) { FileOpContextUI *ui; - g_return_val_if_fail (ctx != NULL, FILE_CONT); + g_return_if_fail (ctx != NULL); if (ctx->ui == NULL) - return FILE_CONT; + return; ui = ctx->ui; label_set_text (ui->file_label[0], _("Deleting")); label_set_text (ui->file_label[0], truncFileStringSecure (ui, s)); - return check_progress_buttons (ctx); } /* diff --git a/src/filegui.h b/src/filegui.h index f61fb88b3..da952f2d3 100644 --- a/src/filegui.h +++ b/src/filegui.h @@ -14,4 +14,14 @@ char *file_mask_dialog (FileOpContext *ctx, FileOperation operation, const char *format, const void *text, const char *def_text, gboolean *do_background); +FileProgressStatus check_progress_buttons (FileOpContext *ctx); + +void file_progress_show (FileOpContext *ctx, off_t done, off_t total); +void file_progress_show_count (FileOpContext *ctx, off_t done, off_t total); +void file_progress_show_bytes (FileOpContext *ctx, double done, double total); +void file_progress_show_total (FileOpTotalContext *tctx, FileOpContext *ctx); +void file_progress_show_source (FileOpContext *ctx, const char *path); +void file_progress_show_target (FileOpContext *ctx, const char *path); +void file_progress_show_deleting (FileOpContext *ctx, const char *path); + #endif /* MC_FILEGUI_H */ diff --git a/src/fileopctx.c b/src/fileopctx.c index 36b806602..604796150 100644 --- a/src/fileopctx.c +++ b/src/fileopctx.c @@ -87,3 +87,20 @@ file_op_context_destroy (FileOpContext *ctx) g_free (ctx); } + +FileOpTotalContext * +file_op_total_context_new (void) +{ + FileOpTotalContext *tctx; + tctx = g_new0 (FileOpTotalContext, 1); + tctx->ask_overwrite = TRUE; + tctx->is_toplevel_file = TRUE; + return tctx; +} + +void +file_op_total_context_destroy (FileOpTotalContext *tctx) +{ + g_return_if_fail (tctx != NULL); + g_free (tctx); +} diff --git a/src/fileopctx.h b/src/fileopctx.h index 07ad3807f..27288e2b1 100644 --- a/src/fileopctx.h +++ b/src/fileopctx.h @@ -17,6 +17,7 @@ #include #include +#include #include "lib/global.h" @@ -56,6 +57,7 @@ typedef struct FileOpContext { /* Whether the panel total has been computed */ gboolean progress_totals_computed; + gboolean show_total; /* Counters for progress indicators */ off_t progress_count; @@ -125,10 +127,27 @@ typedef struct FileOpContext { void *ui; } FileOpContext; +typedef struct { + off_t progress_count; + double progress_bytes; + double copyed_bytes; + size_t bps; + size_t bps_count; + struct timeval transfer_start; + double eta_secs; + + gboolean ask_overwrite; + gboolean is_toplevel_file; + +} FileOpTotalContext; + FileOpContext *file_op_context_new (FileOperation op); void file_op_context_destroy (FileOpContext *ctx); +FileOpTotalContext *file_op_total_context_new (void); +void file_op_total_context_destroy (FileOpTotalContext *tctx); + extern const char *op_names [3]; @@ -147,17 +166,10 @@ enum OperationMode { /* The following functions are implemented separately by each port */ -void file_op_context_create_ui (FileOpContext *ctx, gboolean with_eta); -void file_op_context_create_ui_without_init (FileOpContext *ctx, gboolean with_eta); +void file_op_context_create_ui (FileOpContext *ctx, gboolean with_eta, gboolean show_total); +void file_op_context_create_ui_without_init (FileOpContext *ctx, gboolean with_eta, gboolean show_total); void file_op_context_destroy_ui (FileOpContext *ctx); -FileProgressStatus file_progress_show (FileOpContext *ctx, off_t done, off_t total); -FileProgressStatus file_progress_show_count (FileOpContext *ctx, off_t done, off_t total); -FileProgressStatus file_progress_show_bytes (FileOpContext *ctx, double done, double total); -FileProgressStatus file_progress_show_source (FileOpContext *ctx, const char *path); -FileProgressStatus file_progress_show_target (FileOpContext *ctx, const char *path); -FileProgressStatus file_progress_show_deleting (FileOpContext *ctx, const char *path); - void file_progress_set_stalled_label (FileOpContext *ctx, const char *stalled_msg); FileProgressStatus file_progress_real_query_replace (FileOpContext *ctx, diff --git a/src/tree.c b/src/tree.c index 163eed551..ade307172 100644 --- a/src/tree.c +++ b/src/tree.c @@ -634,9 +634,6 @@ tree_copy (WTree *tree, const char *default_dest) { char msg [BUF_MEDIUM]; char *dest; - off_t count = 0; - double bytes = 0; - FileOpContext *ctx; if (tree->selected_ptr == NULL) return; @@ -647,10 +644,16 @@ tree_copy (WTree *tree, const char *default_dest) msg, MC_HISTORY_FM_TREE_COPY, default_dest); if (dest != NULL && *dest != '\0') { + FileOpContext *ctx; + FileOpTotalContext *tctx; + ctx = file_op_context_new (OP_COPY); - file_op_context_create_ui (ctx, FALSE); - copy_dir_dir (ctx, tree->selected_ptr->name, dest, - TRUE, FALSE, FALSE, NULL, &count, &bytes); + tctx = file_op_total_context_new (); + file_op_context_create_ui (ctx, FALSE, TRUE); + tctx->ask_overwrite = FALSE; + tctx->is_toplevel_file = FALSE; + copy_dir_dir (tctx, ctx, tree->selected_ptr->name, dest, TRUE, FALSE, FALSE, NULL); + file_op_total_context_destroy (tctx); file_op_context_destroy (ctx); } @@ -663,9 +666,8 @@ tree_move (WTree *tree, const char *default_dest) char msg [BUF_MEDIUM]; char *dest; struct stat buf; - double bytes = 0; - off_t count = 0; FileOpContext *ctx; + FileOpTotalContext *tctx; if (tree->selected_ptr == NULL) return; @@ -694,8 +696,10 @@ tree_move (WTree *tree, const char *default_dest) } ctx = file_op_context_new (OP_MOVE); - file_op_context_create_ui (ctx, FALSE); - move_dir_dir (ctx, tree->selected_ptr->name, dest, &count, &bytes); + tctx = file_op_total_context_new (); + file_op_context_create_ui (ctx, FALSE, FALSE); + move_dir_dir (tctx, ctx, tree->selected_ptr->name, dest); + file_op_total_context_destroy (tctx); file_op_context_destroy (ctx); g_free (dest); @@ -725,9 +729,8 @@ static void tree_rmdir (void *data) { WTree *tree = data; - off_t count = 0; - double bytes = 0; FileOpContext *ctx; + FileOpTotalContext *tctx; if (!tree->selected_ptr) return; @@ -747,9 +750,12 @@ tree_rmdir (void *data) } ctx = file_op_context_new (OP_DELETE); - file_op_context_create_ui (ctx, FALSE); - if (erase_dir (ctx, tree->selected_ptr->name, &count, &bytes) == FILE_CONT) + tctx = file_op_total_context_new (); + + file_op_context_create_ui (ctx, FALSE, FALSE); + if (erase_dir (tctx, ctx, tree->selected_ptr->name) == FILE_CONT) tree_forget (tree); + file_op_total_context_destroy (tctx); file_op_context_destroy (ctx); }