mirror of
https://github.com/MidnightCommander/mc
synced 2024-12-23 04:46:55 +03:00
Interruptable computing of directory size.
file.h: new type and functions for status dialog of directory computing size. Added required includes. (compute_dir_size): changed return value. Added new parameters to handle status dialig. Fixed comments. file.c: new functions for status dialog of directory computing size. (compute_dir_size): interruptable dir size computing. Changed return value. Added new parameters to handle status dialig. (panel_compute_totals): likewise. (panel_operate): likewise. cmd.c (single_dirsize_cmd): interruptable dir size computing. (dirsizes_cmd): likewise.
This commit is contained in:
parent
f021c090f9
commit
11bc00bea9
40
src/cmd.c
40
src/cmd.c
@ -37,7 +37,7 @@
|
||||
#include "global.h"
|
||||
#include "cmd.h" /* Our definitions */
|
||||
#include "fileopctx.h" /* file_op_context_new() */
|
||||
#include "file.h" /* copy_file_file() */
|
||||
#include "file.h" /* file operation routines */
|
||||
#include "find.h" /* do_find() */
|
||||
#include "hotlist.h" /* hotlist_cmd() */
|
||||
#include "tree.h" /* tree_chdir() */
|
||||
@ -1197,13 +1197,21 @@ single_dirsize_cmd (void)
|
||||
file_entry *entry;
|
||||
off_t marked;
|
||||
double total;
|
||||
ComputeDirSizeUI *ui;
|
||||
|
||||
ui = compute_dir_size_create_ui ();
|
||||
|
||||
entry = &(panel->dir.list[panel->selected]);
|
||||
if (S_ISDIR (entry->st.st_mode) && strcmp(entry->fname, "..") != 0) {
|
||||
total = 0.0;
|
||||
compute_dir_size (entry->fname, &marked, &total);
|
||||
entry->st.st_size = (off_t) total;
|
||||
entry->f.dir_size_computed = 1;
|
||||
|
||||
if (compute_dir_size (entry->fname, ui, compute_dir_size_update_ui,
|
||||
&marked, &total) == FILE_CONT) {
|
||||
entry->st.st_size = (off_t) total;
|
||||
entry->f.dir_size_computed = 1;
|
||||
}
|
||||
|
||||
compute_dir_size_destroy_ui (ui);
|
||||
}
|
||||
|
||||
if (mark_moves_down)
|
||||
@ -1213,25 +1221,35 @@ single_dirsize_cmd (void)
|
||||
panel->dirty = 1;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
dirsizes_cmd (void)
|
||||
{
|
||||
WPanel *panel = current_panel;
|
||||
int i;
|
||||
off_t marked;
|
||||
double total;
|
||||
ComputeDirSizeUI *ui;
|
||||
|
||||
ui = compute_dir_size_create_ui ();
|
||||
|
||||
for (i = 0; i < panel->count; i++)
|
||||
if (S_ISDIR (panel->dir.list [i].st.st_mode) &&
|
||||
((panel->dirs_marked && panel->dir.list [i].f.marked) ||
|
||||
!panel->dirs_marked) &&
|
||||
strcmp (panel->dir.list [i].fname, "..") != 0) {
|
||||
if (S_ISDIR (panel->dir.list [i].st.st_mode)
|
||||
&& ((panel->dirs_marked && panel->dir.list [i].f.marked)
|
||||
|| !panel->dirs_marked)
|
||||
&& strcmp (panel->dir.list [i].fname, "..") != 0) {
|
||||
total = 0.0l;
|
||||
compute_dir_size (panel->dir.list [i].fname, &marked, &total);
|
||||
|
||||
if (compute_dir_size (panel->dir.list [i].fname,
|
||||
ui, compute_dir_size_update_ui,
|
||||
&marked, &total) != FILE_CONT)
|
||||
break;
|
||||
|
||||
panel->dir.list [i].st.st_size = (off_t) total;
|
||||
panel->dir.list [i].f.dir_size_computed = 1;
|
||||
}
|
||||
|
||||
|
||||
compute_dir_size_destroy_ui (ui);
|
||||
|
||||
recalculate_panel_summary (panel);
|
||||
panel_re_sort (panel);
|
||||
panel->dirty = 1;
|
||||
|
142
src/file.c
142
src/file.c
@ -1474,26 +1474,113 @@ panel_get_file (WPanel *panel, struct stat *stat_buf)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
ComputeDirSizeUI *
|
||||
compute_dir_size_create_ui (void)
|
||||
{
|
||||
ComputeDirSizeUI *ui;
|
||||
|
||||
char *b_name = N_("&Abort");
|
||||
|
||||
#ifdef ENABLE_NLS
|
||||
b_name = _(b_name);
|
||||
#endif
|
||||
|
||||
ui = g_new (ComputeDirSizeUI, 1);
|
||||
|
||||
ui->dlg = create_dlg (0, 0, 8, COLS/2, dialog_colors, NULL,
|
||||
NULL, _("Directory size"), DLG_CENTER | DLG_TRYUP);
|
||||
ui->dirname = label_new (3, 3, "");
|
||||
add_widget (ui->dlg, ui->dirname);
|
||||
|
||||
add_widget (ui->dlg,
|
||||
button_new (5, (ui->dlg->cols - strlen (b_name))/2,
|
||||
FILE_ABORT, NORMAL_BUTTON, b_name, NULL));
|
||||
|
||||
/* We will manage the dialog without any help,
|
||||
that's why we have to call init_dlg */
|
||||
init_dlg (ui->dlg);
|
||||
|
||||
return ui;
|
||||
}
|
||||
|
||||
void
|
||||
compute_dir_size_destroy_ui (ComputeDirSizeUI *ui)
|
||||
{
|
||||
if (ui != NULL) {
|
||||
/* schedule to update passive panel */
|
||||
other_panel->dirty = 1;
|
||||
|
||||
/* close and destroy dialog */
|
||||
dlg_run_done (ui->dlg);
|
||||
destroy_dlg (ui->dlg);
|
||||
g_free (ui);
|
||||
}
|
||||
}
|
||||
|
||||
FileProgressStatus
|
||||
compute_dir_size_update_ui (const void *ui, const char *dirname)
|
||||
{
|
||||
const ComputeDirSizeUI *this = (const ComputeDirSizeUI *) ui;
|
||||
char *msg;
|
||||
int c;
|
||||
Gpm_Event event;
|
||||
|
||||
if (ui == NULL)
|
||||
return FILE_CONT;
|
||||
|
||||
msg = g_strdup_printf (_("Scanning: %s"), dirname);
|
||||
label_set_text (this->dirname, name_trunc (msg, this->dlg->cols - 6));
|
||||
g_free (msg);
|
||||
|
||||
event.x = -1; /* Don't show the GPM cursor */
|
||||
c = get_event (&event, 0, 0);
|
||||
if (c == EV_NONE)
|
||||
return FILE_CONT;
|
||||
|
||||
/* Reinitialize to avoid old values after events other than
|
||||
selecting a button */
|
||||
this->dlg->ret_value = FILE_CONT;
|
||||
|
||||
dlg_process_event (this->dlg, c, &event);
|
||||
|
||||
switch (this->dlg->ret_value) {
|
||||
case B_CANCEL:
|
||||
case FILE_ABORT:
|
||||
return FILE_ABORT;
|
||||
default:
|
||||
return FILE_CONT;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* compute_dir_size:
|
||||
*
|
||||
* Computes the number of bytes used by the files in a directory
|
||||
*/
|
||||
void
|
||||
compute_dir_size (const char *dirname, off_t *ret_marked, double *ret_total)
|
||||
FileProgressStatus
|
||||
compute_dir_size (const char *dirname, const void *ui,
|
||||
compute_dir_size_callback cback,
|
||||
off_t *ret_marked, double *ret_total)
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *dirent;
|
||||
FileProgressStatus ret = FILE_CONT;
|
||||
|
||||
dir = mc_opendir (dirname);
|
||||
|
||||
if (!dir)
|
||||
return;
|
||||
if (dir == NULL)
|
||||
return ret;
|
||||
|
||||
while ((dirent = mc_readdir (dir)) != NULL) {
|
||||
struct stat s;
|
||||
char *fullname;
|
||||
int res;
|
||||
struct stat s;
|
||||
|
||||
ret = (cback != NULL) ? cback (ui, dirname) : FILE_CONT;
|
||||
|
||||
if (ret != FILE_CONT)
|
||||
break;
|
||||
|
||||
if (strcmp (dirent->d_name, ".") == 0)
|
||||
continue;
|
||||
@ -1501,19 +1588,23 @@ compute_dir_size (const char *dirname, off_t *ret_marked, double *ret_total)
|
||||
continue;
|
||||
|
||||
fullname = concat_dir_and_file (dirname, dirent->d_name);
|
||||
|
||||
res = mc_lstat (fullname, &s);
|
||||
|
||||
if (res != 0) {
|
||||
g_free (fullname);
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
if (S_ISDIR (s.st_mode)) {
|
||||
off_t subdir_count = 0;
|
||||
double subdir_bytes = 0;
|
||||
|
||||
compute_dir_size (fullname, &subdir_count, &subdir_bytes);
|
||||
ret = compute_dir_size (fullname, ui, cback, &subdir_count, &subdir_bytes);
|
||||
|
||||
if (ret != FILE_CONT) {
|
||||
g_free (fullname);
|
||||
break;
|
||||
}
|
||||
|
||||
*ret_marked += subdir_count;
|
||||
*ret_total += subdir_bytes;
|
||||
@ -1521,10 +1612,13 @@ compute_dir_size (const char *dirname, off_t *ret_marked, double *ret_total)
|
||||
(*ret_marked)++;
|
||||
*ret_total += s.st_size;
|
||||
}
|
||||
|
||||
g_free (fullname);
|
||||
}
|
||||
|
||||
mc_closedir (dir);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1535,8 +1629,10 @@ compute_dir_size (const char *dirname, off_t *ret_marked, double *ret_total)
|
||||
* as required. In addition, it checks to see if it will
|
||||
* overwrite any files by doing the copy.
|
||||
*/
|
||||
static void
|
||||
panel_compute_totals (WPanel *panel, off_t *ret_marked, double *ret_total)
|
||||
static FileProgressStatus
|
||||
panel_compute_totals (WPanel *panel, const void *ui,
|
||||
compute_dir_size_callback cback,
|
||||
off_t *ret_marked, double *ret_total)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -1555,19 +1651,27 @@ panel_compute_totals (WPanel *panel, off_t *ret_marked, double *ret_total)
|
||||
char *dir_name;
|
||||
off_t subdir_count = 0;
|
||||
double subdir_bytes = 0;
|
||||
FileProgressStatus status;
|
||||
|
||||
dir_name =
|
||||
concat_dir_and_file (panel->cwd, panel->dir.list[i].fname);
|
||||
compute_dir_size (dir_name, &subdir_count, &subdir_bytes);
|
||||
|
||||
status = compute_dir_size (dir_name, ui, cback,
|
||||
&subdir_count, &subdir_bytes);
|
||||
g_free (dir_name);
|
||||
|
||||
if (status != FILE_CONT)
|
||||
return FILE_ABORT;
|
||||
|
||||
*ret_marked += subdir_count;
|
||||
*ret_total += subdir_bytes;
|
||||
g_free (dir_name);
|
||||
} else {
|
||||
(*ret_marked)++;
|
||||
*ret_total += s->st_size;
|
||||
}
|
||||
}
|
||||
|
||||
return FILE_CONT;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1940,8 +2044,18 @@ panel_operate (void *source_panel, FileOperation operation,
|
||||
|
||||
/* Initialize variables for progress bars */
|
||||
if (operation != OP_MOVE && verbose && file_op_compute_totals) {
|
||||
panel_compute_totals (panel, &ctx->progress_count,
|
||||
&ctx->progress_bytes);
|
||||
ComputeDirSizeUI *ui;
|
||||
FileProgressStatus status;
|
||||
|
||||
ui = compute_dir_size_create_ui ();
|
||||
status = panel_compute_totals (panel,
|
||||
ui, compute_dir_size_update_ui,
|
||||
&ctx->progress_count, &ctx->progress_bytes);
|
||||
compute_dir_size_destroy_ui (ui);
|
||||
|
||||
if (status != FILE_CONT)
|
||||
goto clean_up;
|
||||
|
||||
ctx->progress_totals_computed = 1;
|
||||
} else {
|
||||
ctx->progress_totals_computed = 0;
|
||||
|
28
src/file.h
28
src/file.h
@ -1,7 +1,12 @@
|
||||
/* File and directory operation routines for Midnight Commander */
|
||||
|
||||
#ifndef MC_FILE_H
|
||||
#define MC_FILE_H
|
||||
|
||||
#include "global.h"
|
||||
#include "fileopctx.h"
|
||||
#include "dialog.h" /* Dlg_head */
|
||||
#include "widget.h" /* WLabel */
|
||||
|
||||
struct link;
|
||||
|
||||
@ -25,9 +30,24 @@ extern int file_op_compute_totals;
|
||||
/* Report error with one file */
|
||||
FileProgressStatus file_error (const char *format, const char *file);
|
||||
|
||||
/* Query routines */
|
||||
/* Compute directory size */
|
||||
/* callback to update status dialog */
|
||||
typedef FileProgressStatus (*compute_dir_size_callback)(const void *ui, const char *dirname);
|
||||
|
||||
void compute_dir_size (const char *dirname, off_t *ret_marked,
|
||||
double *ret_total);
|
||||
/* return value is FILE_CONT or FILE_ABORT */
|
||||
FileProgressStatus compute_dir_size (const char *dirname, const void *ui,
|
||||
compute_dir_size_callback cback,
|
||||
off_t *ret_marked, double *ret_total);
|
||||
|
||||
#endif
|
||||
/* status dialog of durectory size computing */
|
||||
typedef struct {
|
||||
Dlg_head *dlg;
|
||||
WLabel *dirname;
|
||||
} ComputeDirSizeUI;
|
||||
|
||||
ComputeDirSizeUI *compute_dir_size_create_ui (void);
|
||||
void compute_dir_size_destroy_ui (ComputeDirSizeUI *ui);
|
||||
FileProgressStatus compute_dir_size_update_ui (const void *ui, const char *dirname);
|
||||
|
||||
|
||||
#endif /* MC_FILE_H */
|
||||
|
Loading…
Reference in New Issue
Block a user