Merge branch '1443_one_dir_copy_progress'
* 1443_one_dir_copy_progress: Change param name from 'Layout.progressbar_always_left2right' to 'Layout.classic_progressbar' Change progressbar dialog. Added ability to show progressbars (when copy files) from right to left. Added indication of total BPS and ETA for file operations. Widget library: added new widget WHLine. Show Count progress bar before copy/move of 1st file,Z not after. copy_file_file(): create file copy buffer in stack instead of heap. Type accuracy in file operation routines. Reimplemented some gotos in panel_operate(). Ticket #1443: show average copying velocity/ETA for whole operation.
Этот коммит содержится в:
Коммит
e2b2ea2bfa
12
lib/util.c
12
lib/util.c
@ -49,6 +49,7 @@
|
||||
#include "lib/vfs/mc-vfs/vfs.h"
|
||||
#include "lib/strutil.h"
|
||||
|
||||
#include "src/filegui.h"
|
||||
#include "src/file.h" /* copy_file_file() */
|
||||
#ifndef HAVE_CHARSET
|
||||
#include "src/main.h" /* eight_bit_clean */
|
||||
@ -539,15 +540,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, 1, &count, &bytes, 1);
|
||||
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 +1446,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;%llu\n", filename, line, column, offset) < 0)
|
||||
goto write_position_error;
|
||||
}
|
||||
|
||||
|
12
src/cmd.c
12
src/cmd.c
@ -345,7 +345,7 @@ void
|
||||
copy_cmd (void)
|
||||
{
|
||||
save_cwds_stat ();
|
||||
if (panel_operate (current_panel, OP_COPY, 0)) {
|
||||
if (panel_operate (current_panel, OP_COPY, FALSE)) {
|
||||
update_panels (UP_OPTIMIZE, UP_KEEPSEL);
|
||||
repaint_screen ();
|
||||
}
|
||||
@ -355,7 +355,7 @@ copy_cmd (void)
|
||||
void rename_cmd (void)
|
||||
{
|
||||
save_cwds_stat ();
|
||||
if (panel_operate (current_panel, OP_MOVE, 0)){
|
||||
if (panel_operate (current_panel, OP_MOVE, FALSE)) {
|
||||
update_panels (UP_OPTIMIZE, UP_KEEPSEL);
|
||||
repaint_screen ();
|
||||
}
|
||||
@ -365,7 +365,7 @@ void rename_cmd (void)
|
||||
void copy_cmd_local (void)
|
||||
{
|
||||
save_cwds_stat ();
|
||||
if (panel_operate (current_panel, OP_COPY, 1)){
|
||||
if (panel_operate (current_panel, OP_COPY, TRUE)) {
|
||||
update_panels (UP_OPTIMIZE, UP_KEEPSEL);
|
||||
repaint_screen ();
|
||||
}
|
||||
@ -375,7 +375,7 @@ void copy_cmd_local (void)
|
||||
void rename_cmd_local (void)
|
||||
{
|
||||
save_cwds_stat ();
|
||||
if (panel_operate (current_panel, OP_MOVE, 1)){
|
||||
if (panel_operate (current_panel, OP_MOVE, TRUE)) {
|
||||
update_panels (UP_OPTIMIZE, UP_KEEPSEL);
|
||||
repaint_screen ();
|
||||
}
|
||||
@ -422,7 +422,7 @@ void delete_cmd (void)
|
||||
{
|
||||
save_cwds_stat ();
|
||||
|
||||
if (panel_operate (current_panel, OP_DELETE, 0)){
|
||||
if (panel_operate (current_panel, OP_DELETE, FALSE)) {
|
||||
update_panels (UP_OPTIMIZE, UP_KEEPSEL);
|
||||
repaint_screen ();
|
||||
}
|
||||
@ -433,7 +433,7 @@ void delete_cmd_local (void)
|
||||
{
|
||||
save_cwds_stat ();
|
||||
|
||||
if (panel_operate (current_panel, OP_DELETE, 1)){
|
||||
if (panel_operate (current_panel, OP_DELETE, TRUE)) {
|
||||
update_panels (UP_OPTIMIZE, UP_KEEPSEL);
|
||||
repaint_screen ();
|
||||
}
|
||||
|
765
src/file.c
765
src/file.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
23
src/file.h
23
src/file.h
@ -7,6 +7,7 @@
|
||||
#define MC_FILE_H
|
||||
|
||||
#include <sys/types.h> /* off_t */
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "lib/global.h"
|
||||
#include "dialog.h" /* Dlg_head */
|
||||
@ -15,18 +16,18 @@
|
||||
|
||||
struct link;
|
||||
|
||||
FileProgressStatus copy_file_file (FileOpContext *ctx, const char *s, const char *d,
|
||||
int ask_overwrite, off_t *progress_count,
|
||||
double *progress_bytes, int 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, int toplevel,
|
||||
int move_over, int 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);
|
||||
|
||||
int panel_operate (void *source_panel, FileOperation op, int force_single);
|
||||
gboolean panel_operate (void *source_panel, FileOperation op, gboolean force_single);
|
||||
|
||||
extern int file_op_compute_totals;
|
||||
|
||||
|
509
src/filegui.c
509
src/filegui.c
@ -79,6 +79,7 @@
|
||||
#include "lib/global.h"
|
||||
|
||||
#include "lib/tty/key.h" /* tty_get_event */
|
||||
#include "lib/mcconfig.h"
|
||||
#include "lib/search.h"
|
||||
#include "lib/vfs/mc-vfs/vfs.h"
|
||||
#include "lib/strescape.h"
|
||||
@ -108,51 +109,8 @@ typedef enum {
|
||||
/* Hack: the vfs code should not rely on this */
|
||||
#define WITH_FULL_PATHS 1
|
||||
|
||||
/* This structure describes the UI and internal data required by a file
|
||||
* operation context.
|
||||
*/
|
||||
typedef struct {
|
||||
/* ETA and bps */
|
||||
|
||||
int showing_eta;
|
||||
int showing_bps;
|
||||
int eta_extra;
|
||||
|
||||
/* Dialog and widgets for the operation progress window */
|
||||
|
||||
Dlg_head *op_dlg;
|
||||
|
||||
WLabel *file_label[2];
|
||||
WLabel *file_string[2];
|
||||
WLabel *progress_label[3];
|
||||
WGauge *progress_gauge[3];
|
||||
WLabel *eta_label;
|
||||
WLabel *bps_label;
|
||||
WLabel *stalled_label;
|
||||
|
||||
/* Query replace dialog */
|
||||
|
||||
Dlg_head *replace_dlg;
|
||||
const char *replace_filename;
|
||||
int replace_result;
|
||||
struct stat *s_stat, *d_stat;
|
||||
} FileOpContextUI;
|
||||
|
||||
|
||||
/* Used to save the hint line */
|
||||
static int last_hint_line;
|
||||
|
||||
/* File operate window sizes */
|
||||
#define WX 62
|
||||
#define WY 10
|
||||
#define BY 10
|
||||
#define WX_ETA_EXTRA 12
|
||||
|
||||
#define FCOPY_GAUGE_X 14
|
||||
#define FCOPY_LABEL_X 5
|
||||
|
||||
/* Used for button result values */
|
||||
enum {
|
||||
typedef enum {
|
||||
REPLACE_YES = B_USER,
|
||||
REPLACE_NO,
|
||||
REPLACE_APPEND,
|
||||
@ -162,19 +120,57 @@ enum {
|
||||
REPLACE_ABORT,
|
||||
REPLACE_SIZE,
|
||||
REPLACE_REGET
|
||||
};
|
||||
} replace_action_t;
|
||||
|
||||
static int
|
||||
filegui__check_attrs_on_fs(const char *fs_path)
|
||||
/* This structure describes the UI and internal data required by a file
|
||||
* operation context.
|
||||
*/
|
||||
typedef struct {
|
||||
/* ETA and bps */
|
||||
gboolean showing_eta;
|
||||
gboolean showing_bps;
|
||||
|
||||
/* Dialog and widgets for the operation progress window */
|
||||
Dlg_head *op_dlg;
|
||||
WLabel *file_string[2];
|
||||
WLabel *file_label[2];
|
||||
WGauge *progress_file_gauge;
|
||||
WLabel *progress_file_label;
|
||||
|
||||
WGauge *progress_total_gauge;
|
||||
|
||||
WLabel *total_files_processed_label;
|
||||
WLabel *time_label;
|
||||
WLabel *total_bytes_label;
|
||||
|
||||
/* Query replace dialog */
|
||||
Dlg_head *replace_dlg;
|
||||
const char *replace_filename;
|
||||
replace_action_t replace_result;
|
||||
|
||||
struct stat *s_stat, *d_stat;
|
||||
} FileOpContextUI;
|
||||
|
||||
|
||||
/* Used to save the hint line */
|
||||
static int last_hint_line;
|
||||
|
||||
/* File operate window sizes */
|
||||
#define WX 58
|
||||
#define WY 11
|
||||
#define FCOPY_LABEL_X 3
|
||||
|
||||
static gboolean
|
||||
filegui__check_attrs_on_fs (const char *fs_path)
|
||||
{
|
||||
#ifdef STATFS
|
||||
STRUCT_STATFS stfs;
|
||||
|
||||
if (!setup_copymove_persistent_attr)
|
||||
return 0;
|
||||
return FALSE;
|
||||
|
||||
if (STATFS(fs_path, &stfs)!=0)
|
||||
return 1;
|
||||
if (STATFS (fs_path, &stfs) != 0)
|
||||
return TRUE;
|
||||
|
||||
# ifdef __linux__
|
||||
switch ((filegui_nonattrs_fs_t) stfs.f_type)
|
||||
@ -186,8 +182,7 @@ filegui__check_attrs_on_fs(const char *fs_path)
|
||||
case SMB_SUPER_MAGIC:
|
||||
case NCP_SUPER_MAGIC:
|
||||
case USBDEVICE_SUPER_MAGIC:
|
||||
return 0;
|
||||
break;
|
||||
return FALSE;
|
||||
}
|
||||
# elif defined(HAVE_STRUCT_STATFS_F_FSTYPENAME) \
|
||||
|| defined(HAVE_STRUCT_STATVFS_F_FSTYPENAME)
|
||||
@ -197,21 +192,21 @@ filegui__check_attrs_on_fs(const char *fs_path)
|
||||
|| !strcmp(stfs.f_fstypename, "procfs")
|
||||
|| !strcmp(stfs.f_fstypename, "smbfs")
|
||||
|| strstr(stfs.f_fstypename, "fusefs"))
|
||||
return 0;
|
||||
return FALSE;
|
||||
# elif defined(HAVE_STRUCT_STATVFS_F_BASETYPE)
|
||||
if (!strcmp(stfs.f_basetype, "pcfs")
|
||||
|| !strcmp(stfs.f_basetype, "ntfs")
|
||||
|| !strcmp(stfs.f_basetype, "proc")
|
||||
|| !strcmp(stfs.f_basetype, "smbfs")
|
||||
|| !strcmp(stfs.f_basetype, "fuse"))
|
||||
return 0;
|
||||
return FALSE;
|
||||
# endif
|
||||
#endif /* STATFS */
|
||||
|
||||
return 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static FileProgressStatus
|
||||
FileProgressStatus
|
||||
check_progress_buttons (FileOpContext *ctx)
|
||||
{
|
||||
int c;
|
||||
@ -236,11 +231,9 @@ check_progress_buttons (FileOpContext *ctx)
|
||||
switch (ui->op_dlg->ret_value) {
|
||||
case FILE_SKIP:
|
||||
return FILE_SKIP;
|
||||
break;
|
||||
case B_CANCEL:
|
||||
case FILE_ABORT:
|
||||
return FILE_ABORT;
|
||||
break;
|
||||
default:
|
||||
return FILE_CONT;
|
||||
}
|
||||
@ -249,38 +242,56 @@ check_progress_buttons (FileOpContext *ctx)
|
||||
/* {{{ File progress display routines */
|
||||
|
||||
void
|
||||
file_op_context_create_ui_without_init (FileOpContext *ctx, int with_eta)
|
||||
file_op_context_create_ui_without_init (FileOpContext *ctx, gboolean with_eta, filegui_dialog_type_t dialog_type)
|
||||
{
|
||||
FileOpContextUI *ui;
|
||||
int x_size;
|
||||
int minus;
|
||||
int eta_offset;
|
||||
const char *sixty;
|
||||
const char *fifteen;
|
||||
int minus, total_reserve=0;
|
||||
const char *abort_button_label = N_("&Abort");
|
||||
const char *skip_button_label = N_("&Skip");
|
||||
int abort_button_width, skip_button_width, buttons_width;
|
||||
int dlg_width;
|
||||
|
||||
g_return_if_fail (ctx != NULL);
|
||||
g_return_if_fail (ctx->ui == NULL);
|
||||
|
||||
#ifdef ENABLE_NLS
|
||||
abort_button_label = _(abort_button_label);
|
||||
skip_button_label = _(skip_button_label);
|
||||
#endif
|
||||
|
||||
abort_button_width = str_term_width1 (abort_button_label) + 3;
|
||||
skip_button_width = str_term_width1 (skip_button_label) + 3;
|
||||
buttons_width = abort_button_width + skip_button_width + 2;
|
||||
|
||||
dlg_width = max (WX, buttons_width + 6);
|
||||
|
||||
ui = g_new0 (FileOpContextUI, 1);
|
||||
ctx->ui = ui;
|
||||
|
||||
ctx->dialog_type = dialog_type;
|
||||
minus = verbose ? 0 : 3;
|
||||
eta_offset = with_eta ? (WX_ETA_EXTRA) / 2 : 0;
|
||||
|
||||
sixty = "";
|
||||
fifteen = "";
|
||||
switch (dialog_type) {
|
||||
case FILEGUI_DIALOG_ONE_ITEM:
|
||||
total_reserve = 0;
|
||||
break;
|
||||
case FILEGUI_DIALOG_MULTI_ITEM:
|
||||
total_reserve = 5;
|
||||
break;
|
||||
case FILEGUI_DIALOG_DELETE_ITEM:
|
||||
total_reserve = -5;
|
||||
break;
|
||||
}
|
||||
|
||||
ctx->recursive_result = 0;
|
||||
ctx->recursive_result = RECURSIVE_YES;
|
||||
|
||||
ui->replace_result = 0;
|
||||
ui->replace_result = REPLACE_YES;
|
||||
ui->showing_eta = with_eta;
|
||||
ui->showing_bps = with_eta;
|
||||
ui->eta_extra = with_eta ? WX_ETA_EXTRA : 0;
|
||||
x_size = (WX + 4) + ui->eta_extra;
|
||||
|
||||
ui->op_dlg =
|
||||
create_dlg (0, 0, WY - minus + 4, x_size, dialog_colors, NULL,
|
||||
NULL, op_names[ctx->operation],
|
||||
create_dlg (0, 0, WY - minus + 1 + total_reserve, dlg_width,
|
||||
dialog_colors, NULL, NULL, op_names[ctx->operation],
|
||||
DLG_CENTER | DLG_REVERSE);
|
||||
|
||||
last_hint_line = the_hint->widget.y;
|
||||
@ -288,49 +299,65 @@ file_op_context_create_ui_without_init (FileOpContext *ctx, int 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,
|
||||
NORMAL_BUTTON, _("&Abort"), 0));
|
||||
button_new (WY - minus - 2 + total_reserve,
|
||||
dlg_width/2 + 1, FILE_ABORT,
|
||||
NORMAL_BUTTON, abort_button_label, NULL));
|
||||
add_widget (ui->op_dlg,
|
||||
button_new (BY - minus, 14 + eta_offset, FILE_SKIP,
|
||||
NORMAL_BUTTON, _("&Skip"), 0));
|
||||
button_new (WY - minus - 2 + total_reserve,
|
||||
dlg_width/2 - 1 - skip_button_width, FILE_SKIP,
|
||||
NORMAL_BUTTON, skip_button_label, NULL));
|
||||
|
||||
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, ""));
|
||||
|
||||
add_widget (ui->op_dlg, ui->progress_gauge[1] =
|
||||
gauge_new (8, FCOPY_GAUGE_X, 0, 100, 0));
|
||||
add_widget (ui->op_dlg, ui->progress_label[1] =
|
||||
label_new (8, FCOPY_LABEL_X, fifteen));
|
||||
add_widget (ui->op_dlg, ui->stalled_label = label_new (8, WX, ""));
|
||||
if (dialog_type == FILEGUI_DIALOG_MULTI_ITEM) {
|
||||
add_widget (ui->op_dlg, hline_new (8, 1, dlg_width - 2));
|
||||
|
||||
add_widget (ui->op_dlg, ui->progress_gauge[0] =
|
||||
gauge_new (6, FCOPY_GAUGE_X, 0, 100, 0));
|
||||
add_widget (ui->op_dlg, ui->progress_label[0] =
|
||||
label_new (6, FCOPY_LABEL_X, fifteen));
|
||||
add_widget (ui->op_dlg, ui->eta_label = label_new (6, WX, ""));
|
||||
add_widget (ui->op_dlg, ui->total_bytes_label =
|
||||
label_new (8, FCOPY_LABEL_X + 15, ""));
|
||||
|
||||
add_widget (ui->op_dlg, ui->progress_total_gauge =
|
||||
gauge_new (9, FCOPY_LABEL_X + 3, 0, 100, 0));
|
||||
|
||||
add_widget (ui->op_dlg, ui->total_files_processed_label =
|
||||
label_new (11, FCOPY_LABEL_X, ""));
|
||||
|
||||
add_widget (ui->op_dlg, ui->time_label =
|
||||
label_new (12, FCOPY_LABEL_X, ""));
|
||||
}
|
||||
|
||||
add_widget (ui->op_dlg, ui->progress_file_label =
|
||||
label_new (7, FCOPY_LABEL_X, ""));
|
||||
|
||||
add_widget (ui->op_dlg, ui->progress_file_gauge =
|
||||
gauge_new (6, FCOPY_LABEL_X + 3, 0, 100, 0));
|
||||
|
||||
add_widget (ui->op_dlg, ui->file_string[1] =
|
||||
label_new (4, FCOPY_GAUGE_X, sixty));
|
||||
label_new (5, FCOPY_LABEL_X, ""));
|
||||
|
||||
add_widget (ui->op_dlg, ui->file_label[1] =
|
||||
label_new (4, FCOPY_LABEL_X, fifteen));
|
||||
label_new (4, FCOPY_LABEL_X, ""));
|
||||
add_widget (ui->op_dlg, ui->file_string[0] =
|
||||
label_new (3, FCOPY_GAUGE_X, sixty));
|
||||
label_new (3, FCOPY_LABEL_X, ""));
|
||||
add_widget (ui->op_dlg, ui->file_label[0] =
|
||||
label_new (3, FCOPY_LABEL_X, fifteen));
|
||||
label_new (2, FCOPY_LABEL_X, ""));
|
||||
|
||||
if ((right_panel == current_panel)
|
||||
&& !mc_config_get_bool (mc_main_config,"Layout",
|
||||
"classic_progressbar", TRUE)) {
|
||||
ui->progress_file_gauge->from_left_to_right = FALSE;
|
||||
if (dialog_type == FILEGUI_DIALOG_MULTI_ITEM)
|
||||
ui->progress_total_gauge->from_left_to_right = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
file_op_context_create_ui (FileOpContext *ctx, int with_eta)
|
||||
file_op_context_create_ui (FileOpContext *ctx, gboolean with_eta, filegui_dialog_type_t dialog_type)
|
||||
{
|
||||
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, dialog_type);
|
||||
ui = ctx->ui;
|
||||
|
||||
/* We will manage the dialog without any help, that's why
|
||||
@ -359,178 +386,170 @@ file_op_context_destroy_ui (FileOpContext *ctx)
|
||||
ctx->ui = NULL;
|
||||
}
|
||||
|
||||
static FileProgressStatus
|
||||
show_no_bar (FileOpContext *ctx, int n)
|
||||
{
|
||||
FileOpContextUI *ui;
|
||||
|
||||
if (ctx->ui == NULL)
|
||||
return FILE_CONT;
|
||||
|
||||
ui = ctx->ui;
|
||||
|
||||
if (n >= 0) {
|
||||
label_set_text (ui->progress_label[n], "");
|
||||
gauge_show (ui->progress_gauge[n], 0);
|
||||
}
|
||||
return check_progress_buttons (ctx);
|
||||
}
|
||||
|
||||
static FileProgressStatus
|
||||
show_bar (FileOpContext *ctx, int n, double done, double total)
|
||||
{
|
||||
FileOpContextUI *ui;
|
||||
|
||||
if (ctx->ui == NULL)
|
||||
return FILE_CONT;
|
||||
|
||||
ui = ctx->ui;
|
||||
|
||||
/*
|
||||
* Gauge needs integers, so give it with integers between 0 and 1023.
|
||||
* This precision should be quite reasonable.
|
||||
*/
|
||||
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;
|
||||
char eta_buffer[BUF_TINY];
|
||||
FileOpContextUI *ui;
|
||||
|
||||
if (ctx->ui == NULL)
|
||||
return;
|
||||
|
||||
ui = ctx->ui;
|
||||
|
||||
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;
|
||||
|
||||
label_set_text (ui->eta_label, eta_buffer);
|
||||
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_bps_show (FileOpContext *ctx)
|
||||
file_eta_prepare_for_show (char *buffer, double eta_secs, gboolean always_show)
|
||||
{
|
||||
char bps_buffer[BUF_TINY];
|
||||
FileOpContextUI *ui;
|
||||
|
||||
if (ctx->ui == NULL)
|
||||
char _fmt_buff[BUF_TINY];
|
||||
if (eta_secs <= 0.5 && !always_show) {
|
||||
*buffer = '\0';
|
||||
return;
|
||||
|
||||
ui = ctx->ui;
|
||||
|
||||
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;
|
||||
|
||||
label_set_text (ui->bps_label, bps_buffer);
|
||||
}
|
||||
if (eta_secs <= 0.5)
|
||||
eta_secs = 1;
|
||||
file_frmt_time (_fmt_buff, eta_secs);
|
||||
g_snprintf (buffer, BUF_TINY, _("ETA %s"), _fmt_buff);
|
||||
}
|
||||
|
||||
FileProgressStatus
|
||||
file_progress_show (FileOpContext *ctx, off_t done, off_t total)
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
show progressbar for file
|
||||
*/
|
||||
void
|
||||
file_progress_show (FileOpContext *ctx, off_t done, off_t total,
|
||||
const char *stalled_msg, gboolean force_update)
|
||||
{
|
||||
FileOpContextUI *ui;
|
||||
char buffer[BUF_TINY];
|
||||
char buffer2[BUF_TINY];
|
||||
char buffer3[BUF_TINY];
|
||||
|
||||
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);
|
||||
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);
|
||||
} else
|
||||
return show_no_bar (ctx, 0);
|
||||
return;
|
||||
|
||||
if (total == 0) {
|
||||
gauge_show (ui->progress_file_gauge, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
gauge_set_value (ui->progress_file_gauge, 1024, (int) (1024 * done / total));
|
||||
gauge_show (ui->progress_file_gauge, 1);
|
||||
|
||||
if (!force_update)
|
||||
return;
|
||||
|
||||
if (ui->showing_eta && ctx->eta_secs > 0.5) {
|
||||
file_eta_prepare_for_show (buffer2, ctx->eta_secs, FALSE);
|
||||
file_bps_prepare_for_show (buffer3, ctx->bps);
|
||||
g_snprintf (buffer, BUF_TINY, "%s (%s) %s", buffer2, buffer3, stalled_msg);
|
||||
} else {
|
||||
g_snprintf (buffer, BUF_TINY, "%s",stalled_msg);
|
||||
}
|
||||
|
||||
label_set_text (ui->progress_file_label, buffer);
|
||||
}
|
||||
|
||||
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->dialog_type != FILEGUI_DIALOG_MULTI_ITEM || 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
|
||||
file_progress_show_bytes (FileOpContext *ctx, double done, double total)
|
||||
void
|
||||
file_progress_show_total (FileOpTotalContext *tctx, FileOpContext *ctx, double copyed_bytes,
|
||||
gboolean need_show_total_summary)
|
||||
{
|
||||
char buffer[BUF_TINY];
|
||||
char buffer2[BUF_TINY];
|
||||
char buffer3[BUF_TINY];
|
||||
char buffer4[BUF_TINY];
|
||||
struct timeval tv_current;
|
||||
FileOpContextUI *ui;
|
||||
|
||||
g_return_val_if_fail (ctx != NULL, FILE_CONT);
|
||||
|
||||
if (ctx->ui == NULL)
|
||||
return FILE_CONT;
|
||||
if (ctx->dialog_type != FILEGUI_DIALOG_MULTI_ITEM || ctx->ui == NULL)
|
||||
return;
|
||||
|
||||
ui = ctx->ui;
|
||||
|
||||
if (!verbose)
|
||||
return check_progress_buttons (ctx);
|
||||
if (total > 0) {
|
||||
label_set_text (ui->progress_label[2], _("Bytes"));
|
||||
return show_bar (ctx, 2, done, total);
|
||||
if (ctx->progress_bytes > 0 ){
|
||||
gauge_set_value (ui->progress_total_gauge, 1024, (int) (1024 * copyed_bytes/ ctx->progress_bytes));
|
||||
gauge_show (ui->progress_total_gauge, 1);
|
||||
} else
|
||||
return show_no_bar (ctx, 2);
|
||||
gauge_show (ui->progress_total_gauge, 0);
|
||||
|
||||
|
||||
if (!need_show_total_summary && tctx->bps == 0)
|
||||
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);
|
||||
file_bps_prepare_for_show (buffer4, (long) tctx->bps);
|
||||
|
||||
|
||||
|
||||
g_snprintf (buffer, BUF_TINY, _("Time: %s %s (%s)"), buffer2, buffer3, buffer4);
|
||||
label_set_text (ui->time_label, buffer);
|
||||
|
||||
size_trunc_len (buffer2, 5, tctx->copyed_bytes, 0);
|
||||
size_trunc_len (buffer3, 5, ctx->progress_bytes, 0);
|
||||
|
||||
g_snprintf (buffer, BUF_TINY, _(" Total: %s of %s "), buffer2, buffer3);
|
||||
|
||||
label_set_text (ui->total_bytes_label, buffer);
|
||||
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
#define truncFileString(ui, s) str_trunc (s, ui->eta_extra + 47)
|
||||
#define truncFileStringSecure(ui, s) path_trunc (s, ui->eta_extra + 47)
|
||||
#define truncFileString(ui, s) str_trunc (s, 52)
|
||||
#define truncFileStringSecure(ui, s) path_trunc (s, 52)
|
||||
|
||||
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;
|
||||
|
||||
@ -547,52 +566,46 @@ 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);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -600,9 +613,7 @@ file_progress_show_deleting (FileOpContext *ctx, const char *s)
|
||||
* but actually I'm not familiar with it and have not much time :(
|
||||
* alex
|
||||
*/
|
||||
|
||||
|
||||
static int
|
||||
static replace_action_t
|
||||
overwrite_query_dialog (FileOpContext *ctx, enum OperationMode mode)
|
||||
{
|
||||
#define ADD_RD_BUTTON(i)\
|
||||
@ -767,23 +778,11 @@ overwrite_query_dialog (FileOpContext *ctx, enum OperationMode mode)
|
||||
|
||||
g_free (widgets_len);
|
||||
|
||||
return result;
|
||||
return (result == B_CANCEL) ? REPLACE_ABORT : (replace_action_t) result;
|
||||
#undef ADD_RD_LABEL
|
||||
#undef ADD_RD_BUTTON
|
||||
}
|
||||
|
||||
void
|
||||
file_progress_set_stalled_label (FileOpContext *ctx, const char *stalled_msg)
|
||||
{
|
||||
FileOpContextUI *ui;
|
||||
|
||||
g_return_if_fail (ctx != NULL);
|
||||
g_return_if_fail (ctx->ui != NULL);
|
||||
|
||||
ui = ctx->ui;
|
||||
label_set_text (ui->stalled_label, stalled_msg);
|
||||
}
|
||||
|
||||
FileProgressStatus
|
||||
file_progress_real_query_replace (FileOpContext *ctx,
|
||||
enum OperationMode mode, const char *destname,
|
||||
@ -802,8 +801,6 @@ file_progress_real_query_replace (FileOpContext *ctx,
|
||||
ui->s_stat = _s_stat;
|
||||
ui->d_stat = _d_stat;
|
||||
ui->replace_result = overwrite_query_dialog (ctx, mode);
|
||||
if (ui->replace_result == B_CANCEL)
|
||||
ui->replace_result = REPLACE_ABORT;
|
||||
}
|
||||
|
||||
switch (ui->replace_result) {
|
||||
@ -826,7 +823,7 @@ file_progress_real_query_replace (FileOpContext *ctx,
|
||||
ctx->do_reget = _d_stat->st_size;
|
||||
|
||||
case REPLACE_APPEND:
|
||||
ctx->do_append = 1;
|
||||
ctx->do_append = TRUE;
|
||||
|
||||
case REPLACE_YES:
|
||||
case REPLACE_ALWAYS:
|
||||
@ -992,7 +989,7 @@ file_mask_dialog (FileOpContext *ctx, FileOperation operation,
|
||||
/* destination */
|
||||
fmd_widgets[7 - OFFSET].u.input.text = def_text_secure;
|
||||
|
||||
ctx->stable_symlinks = 0;
|
||||
ctx->stable_symlinks = FALSE;
|
||||
*do_background = FALSE;
|
||||
|
||||
{
|
||||
@ -1018,18 +1015,18 @@ file_mask_dialog (FileOpContext *ctx, FileOperation operation,
|
||||
ctx->stat_func = mc_lstat;
|
||||
|
||||
if (ctx->op_preserve) {
|
||||
ctx->preserve = 1;
|
||||
ctx->preserve = TRUE;
|
||||
ctx->umask_kill = 0777777;
|
||||
ctx->preserve_uidgid = (geteuid () == 0) ? 1 : 0;
|
||||
ctx->preserve_uidgid = (geteuid () == 0);
|
||||
} else {
|
||||
int i2;
|
||||
ctx->preserve = ctx->preserve_uidgid = 0;
|
||||
ctx->preserve = ctx->preserve_uidgid = FALSE;
|
||||
i2 = umask (0);
|
||||
umask (i2);
|
||||
ctx->umask_kill = i2 ^ 0777777;
|
||||
}
|
||||
|
||||
if (!dest_dir || !*dest_dir) {
|
||||
if ((dest_dir == NULL) || (*dest_dir == '\0')) {
|
||||
g_free (def_text_secure);
|
||||
g_free (source_mask);
|
||||
return dest_dir;
|
||||
|
@ -9,9 +9,31 @@
|
||||
#include "lib/global.h"
|
||||
#include "fileopctx.h"
|
||||
|
||||
typedef enum {
|
||||
FILEGUI_DIALOG_ONE_ITEM,
|
||||
FILEGUI_DIALOG_MULTI_ITEM,
|
||||
FILEGUI_DIALOG_DELETE_ITEM
|
||||
} filegui_dialog_type_t;
|
||||
|
||||
void file_op_context_create_ui (FileOpContext *ctx, gboolean with_eta, filegui_dialog_type_t dialog_type);
|
||||
void file_op_context_create_ui_without_init (FileOpContext *ctx, gboolean with_eta, filegui_dialog_type_t dialog_type);
|
||||
void file_op_context_destroy_ui (FileOpContext *ctx);
|
||||
|
||||
|
||||
char *file_mask_dialog (FileOpContext *ctx, FileOperation operation,
|
||||
gboolean only_one,
|
||||
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,
|
||||
const char *stalled_msg, gboolean force_update);
|
||||
void file_progress_show_count (FileOpContext *ctx, off_t done, off_t total);
|
||||
void file_progress_show_total (FileOpTotalContext *tctx, FileOpContext *ctx,
|
||||
double copyed_bytes, gboolean need_show_total_summary);
|
||||
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 */
|
||||
|
@ -55,10 +55,10 @@ file_op_context_new (FileOperation op)
|
||||
ctx->eta_secs = 0.0;
|
||||
ctx->progress_bytes = 0.0;
|
||||
ctx->op_preserve = TRUE;
|
||||
ctx->do_reget = TRUE;
|
||||
ctx->do_reget = 1;
|
||||
ctx->stat_func = mc_lstat;
|
||||
ctx->preserve = TRUE;
|
||||
ctx->preserve_uidgid = (geteuid () == 0) ? TRUE : FALSE;
|
||||
ctx->preserve_uidgid = (geteuid () == 0);
|
||||
ctx->umask_kill = 0777777;
|
||||
ctx->erase_at_end = TRUE;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
@ -17,14 +17,26 @@
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "lib/global.h"
|
||||
|
||||
struct mc_search_struct;
|
||||
|
||||
typedef enum {
|
||||
OP_COPY,
|
||||
OP_MOVE,
|
||||
OP_DELETE
|
||||
OP_COPY = 0,
|
||||
OP_MOVE = 1,
|
||||
OP_DELETE = 2
|
||||
} FileOperation;
|
||||
|
||||
typedef enum {
|
||||
RECURSIVE_YES = 0,
|
||||
RECURSIVE_NO = 1,
|
||||
RECURSIVE_ALWAYS = 2,
|
||||
RECURSIVE_NEVER = 3,
|
||||
RECURSIVE_ABORT = 4
|
||||
} FileCopyMode;
|
||||
|
||||
typedef int (*mc_stat_fn) (const char *filename, struct stat *buf);
|
||||
|
||||
/* This structure describes a context for file operations. It is used to update
|
||||
@ -44,7 +56,8 @@ typedef struct FileOpContext {
|
||||
long bps_time;
|
||||
|
||||
/* Whether the panel total has been computed */
|
||||
int progress_totals_computed;
|
||||
gboolean progress_totals_computed;
|
||||
int dialog_type;
|
||||
|
||||
/* Counters for progress indicators */
|
||||
off_t progress_count;
|
||||
@ -55,25 +68,25 @@ typedef struct FileOpContext {
|
||||
* to preserve file attributs when moving files across filesystem boundaries
|
||||
* (we want to keep the value of the checkbox between copy operations).
|
||||
*/
|
||||
int op_preserve;
|
||||
gboolean op_preserve;
|
||||
|
||||
/* Result from the recursive query */
|
||||
int recursive_result;
|
||||
FileCopyMode recursive_result;
|
||||
|
||||
/* Whether to do a reget */
|
||||
off_t do_reget;
|
||||
|
||||
/* Controls appending to files */
|
||||
int do_append;
|
||||
gboolean do_append;
|
||||
|
||||
/* Whether to stat or lstat */
|
||||
int follow_links;
|
||||
gboolean follow_links;
|
||||
|
||||
/* Pointer to the stat function we will use */
|
||||
mc_stat_fn stat_func;
|
||||
|
||||
/* Whether to recompute symlinks */
|
||||
int stable_symlinks;
|
||||
gboolean stable_symlinks;
|
||||
|
||||
/* Preserve the original files' owner, group, permissions, and
|
||||
* timestamps (owner, group only as root).
|
||||
@ -83,7 +96,7 @@ typedef struct FileOpContext {
|
||||
/* If running as root, preserve the original uid/gid (we don't want to
|
||||
* try chown for non root) preserve_uidgid = preserve && uid == 0
|
||||
*/
|
||||
int preserve_uidgid;
|
||||
gboolean preserve_uidgid;
|
||||
|
||||
/* The bits to preserve in created files' modes on file copy */
|
||||
int umask_kill;
|
||||
@ -91,7 +104,9 @@ typedef struct FileOpContext {
|
||||
/* The mask of files to actually operate on */
|
||||
char *dest_mask;
|
||||
|
||||
struct mc_search_struct *search_handle;
|
||||
/* search handler */
|
||||
struct mc_search_struct *search_handle;
|
||||
|
||||
/* Whether to dive into subdirectories for recursive operations */
|
||||
int dive_into_subdirs;
|
||||
|
||||
@ -99,24 +114,40 @@ typedef struct FileOpContext {
|
||||
* successfully copied files when all files below the directory and its
|
||||
* subdirectories were processed.
|
||||
*
|
||||
* If erase_at_end is zero files will be deleted immediately after their
|
||||
* If erase_at_end is FALSE files will be deleted immediately after their
|
||||
* successful copy (Note: this behavior is not tested and at the moment
|
||||
* it can't be changed at runtime).
|
||||
*/
|
||||
int erase_at_end;
|
||||
gboolean erase_at_end;
|
||||
|
||||
/* PID of the child for background operations */
|
||||
pid_t pid;
|
||||
|
||||
/* User interface data goes here */
|
||||
|
||||
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];
|
||||
|
||||
@ -127,14 +158,6 @@ typedef enum {
|
||||
FILE_ABORT = 3
|
||||
} FileProgressStatus;
|
||||
|
||||
typedef enum {
|
||||
RECURSIVE_YES,
|
||||
RECURSIVE_NO,
|
||||
RECURSIVE_ALWAYS,
|
||||
RECURSIVE_NEVER,
|
||||
RECURSIVE_ABORT
|
||||
} FileCopyMode;
|
||||
|
||||
/* First argument passed to real functions */
|
||||
enum OperationMode {
|
||||
Foreground,
|
||||
@ -143,19 +166,6 @@ enum OperationMode {
|
||||
|
||||
/* The following functions are implemented separately by each port */
|
||||
|
||||
void file_op_context_create_ui (FileOpContext *ctx, int with_eta);
|
||||
void file_op_context_create_ui_without_init (FileOpContext *ctx, int with_eta);
|
||||
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,
|
||||
enum OperationMode mode,
|
||||
const char *destname,
|
||||
|
37
src/tree.c
37
src/tree.c
@ -66,6 +66,7 @@
|
||||
#include "keybind.h"
|
||||
#include "history.h"
|
||||
#include "tree.h"
|
||||
#include "filegui.h"
|
||||
|
||||
const global_keymap_t *tree_map;
|
||||
|
||||
@ -634,21 +635,26 @@ 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;
|
||||
|
||||
g_snprintf (msg, sizeof (msg), _("Copy \"%s\" directory to:"),
|
||||
str_trunc (tree->selected_ptr->name, 50));
|
||||
dest = input_expand_dialog (Q_("DialogTitle|Copy"), msg, MC_HISTORY_FM_TREE_COPY, default_dest);
|
||||
dest = input_expand_dialog (Q_("DialogTitle|Copy"),
|
||||
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, 1, 0, 0, 0, &count, &bytes);
|
||||
tctx = file_op_total_context_new ();
|
||||
file_op_context_create_ui (ctx, FALSE, FILEGUI_DIALOG_MULTI_ITEM);
|
||||
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);
|
||||
}
|
||||
|
||||
@ -661,9 +667,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;
|
||||
@ -692,8 +697,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, FILEGUI_DIALOG_ONE_ITEM);
|
||||
move_dir_dir (tctx, ctx, tree->selected_ptr->name, dest);
|
||||
file_op_total_context_destroy (tctx);
|
||||
file_op_context_destroy (ctx);
|
||||
|
||||
g_free (dest);
|
||||
@ -723,9 +730,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;
|
||||
@ -745,9 +751,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, FILEGUI_DIALOG_ONE_ITEM);
|
||||
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);
|
||||
}
|
||||
|
||||
|
78
src/widget.c
78
src/widget.c
@ -785,6 +785,66 @@ label_new (int y, int x, const char *text)
|
||||
return l;
|
||||
}
|
||||
|
||||
static cb_ret_t
|
||||
hline_callback (Widget *w, widget_msg_t msg, int parm)
|
||||
{
|
||||
WHLine *l = (WHLine *) w;
|
||||
Dlg_head *h = l->widget.parent;
|
||||
|
||||
switch (msg) {
|
||||
case WIDGET_INIT:
|
||||
case WIDGET_RESIZED:
|
||||
if (l->auto_adjust_cols) {
|
||||
if (((w->parent->flags & DLG_COMPACT) != 0)) {
|
||||
w->x = w->parent->x;
|
||||
w->cols = w->parent->cols;
|
||||
} else {
|
||||
w->x = w->parent->x + 1;
|
||||
w->cols = w->parent->cols - 2;
|
||||
}
|
||||
}
|
||||
|
||||
case WIDGET_FOCUS:
|
||||
/* We don't want to get the focus */
|
||||
return MSG_NOT_HANDLED;
|
||||
|
||||
case WIDGET_DRAW:
|
||||
if (l->transparent)
|
||||
tty_setcolor (DEFAULT_COLOR);
|
||||
else
|
||||
tty_setcolor (DLG_NORMALC (h));
|
||||
|
||||
tty_draw_hline (w->y, w->x + 1, ACS_HLINE, w->cols - 2);
|
||||
|
||||
if (l->auto_adjust_cols) {
|
||||
widget_move (w, 0, 0);
|
||||
tty_print_alt_char (ACS_LTEE);
|
||||
widget_move (w, 0, w->cols - 1);
|
||||
tty_print_alt_char (ACS_RTEE);
|
||||
}
|
||||
return MSG_HANDLED;
|
||||
|
||||
default:
|
||||
return default_proc (msg, parm);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WHLine *
|
||||
hline_new (int y, int x, int width)
|
||||
{
|
||||
WHLine *l;
|
||||
int cols = width;
|
||||
int lines = 1;
|
||||
|
||||
l = g_new (WHLine, 1);
|
||||
init_widget (&l->widget, y, x, lines, cols, hline_callback, NULL);
|
||||
l->auto_adjust_cols = (width < 0);
|
||||
l->transparent = FALSE;
|
||||
widget_want_cursor (l->widget, 0);
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
/* Gauge widget (progress indicator) */
|
||||
/* Currently width is hardcoded here for text mode */
|
||||
@ -825,10 +885,19 @@ gauge_callback (Widget *w, widget_msg_t msg, int parm)
|
||||
percentage = (200 * done / total + 1) / 2;
|
||||
columns = (2 * (gauge_len - 7) * done / total + 1) / 2;
|
||||
tty_print_char ('[');
|
||||
tty_setcolor (GAUGE_COLOR);
|
||||
tty_printf ("%*s", (int) columns, "");
|
||||
tty_setcolor (DLG_NORMALC (h));
|
||||
tty_printf ("%*s] %3d%%", (int)(gauge_len - 7 - columns), "", (int) percentage);
|
||||
if (g->from_left_to_right) {
|
||||
tty_setcolor (GAUGE_COLOR);
|
||||
tty_printf ("%*s", (int) columns, "");
|
||||
tty_setcolor (DLG_NORMALC (h));
|
||||
tty_printf ("%*s] %3d%%", (int)(gauge_len - 7 - columns), "", (int) percentage);
|
||||
} else {
|
||||
tty_setcolor (DLG_NORMALC (h));
|
||||
tty_printf ("%*s", gauge_len - columns - 7, "");
|
||||
tty_setcolor (GAUGE_COLOR);
|
||||
tty_printf ("%*s", columns, "");
|
||||
tty_setcolor (DLG_NORMALC (h));
|
||||
tty_printf ("] %3d%%", 100 * columns / (gauge_len - 7), percentage);
|
||||
}
|
||||
}
|
||||
return MSG_HANDLED;
|
||||
}
|
||||
@ -869,6 +938,7 @@ gauge_new (int y, int x, int shown, int max, int current)
|
||||
max = 1; /* I do not like division by zero :) */
|
||||
g->max = max;
|
||||
g->current = current;
|
||||
g->from_left_to_right = TRUE;
|
||||
widget_want_cursor (g->widget, 0);
|
||||
return g;
|
||||
}
|
||||
|
@ -89,6 +89,7 @@ typedef struct WGauge {
|
||||
int shown;
|
||||
int max;
|
||||
int current;
|
||||
gboolean from_left_to_right;
|
||||
} WGauge;
|
||||
|
||||
GList *history_get (const char *input_name);
|
||||
@ -128,6 +129,12 @@ typedef struct {
|
||||
int transparent; /* Paint in the default color fg/bg */
|
||||
} WLabel;
|
||||
|
||||
typedef struct {
|
||||
Widget widget;
|
||||
gboolean auto_adjust_cols; /* Compute widget.cols from parent width? */
|
||||
gboolean transparent; /* Paint in the default color fg/bg */
|
||||
} WHLine;
|
||||
|
||||
typedef struct WLEntry {
|
||||
char *text; /* Text to display */
|
||||
int hotkey;
|
||||
@ -187,6 +194,8 @@ WRadio *radio_new (int y, int x, int count, const char **text);
|
||||
WCheck *check_new (int y, int x, int state, const char *text);
|
||||
WInput *input_new (int y, int x, int color, int len, const char *text, const char *histname, INPUT_COMPLETE_FLAGS completion_flags);
|
||||
WLabel *label_new (int y, int x, const char *text);
|
||||
WHLine *hline_new (int y, int x, int width);
|
||||
|
||||
WGauge *gauge_new (int y, int x, int shown, int max, int current);
|
||||
WListbox *listbox_new (int y, int x, int height, int width, gboolean deletable, lcback callback);
|
||||
WButtonBar *buttonbar_new (gboolean visible);
|
||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user