Count the files to be deleted before deleting

This commit is contained in:
Pierre Pronchery 2017-10-16 19:43:00 +02:00
parent 807f25dbe1
commit a88f6c6140

View File

@ -68,22 +68,37 @@ typedef int Prefs;
typedef struct _DeleteDir DeleteDir;
typedef enum _DeleteMode
{
DM_COUNT = 0,
DM_DELETE
} DeleteMode;
typedef struct _Delete
{
DeleteMode mode;
Prefs * prefs;
unsigned int filec;
char ** filev;
unsigned int file_cur;
size_t count_cnt;
size_t count_cur;
struct timeval count_tv;
struct dirent * de;
DeleteDir ** dirv;
size_t dirv_cnt;
/* widgets */
guint source;
guint idle;
guint timeout;
GtkWidget * window;
GtkWidget * label;
GtkWidget * hbox;
GtkWidget * entry;
GtkWidget * progress;
} Delete;
@ -98,14 +113,16 @@ static int _delete_error(Delete * delete, char const * message, int ret);
static int _delete_filename_error(Delete * delete, char const * filename,
int ret);
static void _delete_refresh(Delete * delete, char const * filename);
/* functions */
/* delete */
static void _delete_refresh(Delete * delete, char const * filename);
/* callbacks */
static void _delete_on_cancel(gpointer data);
static gboolean _delete_on_closex(gpointer data);
static gboolean _delete_idle(gpointer data);
static gboolean _delete_timeout(gpointer data);
static int _delete(Prefs * prefs, unsigned int filec, char * filev[])
{
@ -117,10 +134,13 @@ static int _delete(Prefs * prefs, unsigned int filec, char * filev[])
if(filec < 1 || filev == NULL)
return 1;
delete.mode = DM_COUNT;
delete.prefs = prefs;
delete.filec = filec;
delete.filev = filev;
delete.file_cur = 0;
delete.count_cnt = 0;
delete.count_cur = 0;
delete.de = NULL;
delete.dirv = NULL;
delete.dirv_cnt = 0;
@ -135,13 +155,23 @@ static int _delete(Prefs * prefs, unsigned int filec, char * filev[])
#else
vbox = gtk_vbox_new(FALSE, 4);
#endif
/* counter */
delete.label = gtk_label_new(_("Counting files..."));
#if GTK_CHECK_VERSION(3, 0, 0)
g_object_set(delete.label, "halign", GTK_ALIGN_START, NULL);
#else
gtk_misc_set_alignment(GTK_MISC(delete.label), 0.0, 0.5);
#endif
gtk_box_pack_start(GTK_BOX(vbox), delete.label, FALSE, TRUE, 0);
/* current argument */
#if GTK_CHECK_VERSION(3, 0, 0)
hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
delete.hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
#else
hbox = gtk_hbox_new(FALSE, 4);
delete.hbox = gtk_hbox_new(FALSE, 4);
#endif
widget = gtk_label_new(_("Deleting: "));
hbox = delete.hbox;
gtk_widget_set_no_show_all(hbox, TRUE);
widget = gtk_label_new(_("File: "));
bold = pango_font_description_new();
pango_font_description_set_weight(bold, PANGO_WEIGHT_BOLD);
#if GTK_CHECK_VERSION(3, 0, 0)
@ -150,18 +180,12 @@ static int _delete(Prefs * prefs, unsigned int filec, char * filev[])
gtk_widget_modify_font(widget, bold);
#endif
pango_font_description_free(bold);
gtk_widget_show(widget);
gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, TRUE, 0);
delete.label = gtk_label_new("");
#if GTK_CHECK_VERSION(2, 6, 0)
gtk_label_set_ellipsize(GTK_LABEL(delete.label), PANGO_ELLIPSIZE_END);
gtk_label_set_width_chars(GTK_LABEL(delete.label), 25);
#endif
#if GTK_CHECK_VERSION(3, 0, 0)
g_object_set(delete.label, "halign", GTK_ALIGN_START, NULL);
#else
gtk_misc_set_alignment(GTK_MISC(delete.label), 0.0, 0.5);
#endif
gtk_box_pack_start(GTK_BOX(hbox), delete.label, TRUE, TRUE, 0);
delete.entry = gtk_entry_new();
gtk_editable_set_editable(GTK_EDITABLE(delete.entry), FALSE);
gtk_widget_show(delete.entry);
gtk_box_pack_start(GTK_BOX(hbox), delete.entry, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
/* progress bar */
delete.progress = gtk_progress_bar_new();
@ -180,34 +204,16 @@ static int _delete(Prefs * prefs, unsigned int filec, char * filev[])
gtk_container_set_border_width(GTK_CONTAINER(delete.window), 4);
gtk_container_add(GTK_CONTAINER(delete.window), vbox);
#ifdef DEBUG
delete.source = g_timeout_add(10, _delete_idle, &delete);
delete.idle = g_timeout_add(10, _delete_idle, &delete);
#else
delete.source = g_idle_add(_delete_idle, &delete);
delete.idle = g_idle_add(_delete_idle, &delete);
#endif
delete.timeout = g_timeout_add(500, _delete_timeout, &delete);
_delete_refresh(&delete, "");
gtk_widget_show_all(delete.window);
return 0;
}
static void _delete_refresh(Delete * delete, char const * filename)
{
char * p;
char buf[64];
double fraction;
if((p = g_filename_to_utf8(filename, -1, NULL, NULL, NULL)) != NULL)
filename = p;
gtk_label_set_text(GTK_LABEL(delete->label), filename);
free(p);
snprintf(buf, sizeof(buf), _("File %u of %u"), delete->file_cur + 1,
delete->filec);
fraction = delete->file_cur;
fraction /= delete->filec;
gtk_progress_bar_set_text(GTK_PROGRESS_BAR(delete->progress), buf);
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(delete->progress),
fraction);
}
static void _delete_on_cancel(gpointer data)
{
Delete * delete = data;
@ -222,8 +228,10 @@ static void _delete_on_cancel(gpointer data)
free(delete->dirv[i - 1]);
}
free(delete->dirv);
if(delete->source != 0)
g_source_remove(delete->source);
if(delete->idle != 0)
g_source_remove(delete->idle);
if(delete->timeout != 0)
g_source_remove(delete->timeout);
gtk_main_quit();
}
@ -235,20 +243,47 @@ static gboolean _delete_on_closex(gpointer data)
return FALSE;
}
static gboolean _idle_count(Delete * delete);
static gboolean _idle_delete(Delete * delete);
static int _idle_do(Delete * delete);
static gboolean _delete_idle(gpointer data)
{
gboolean ret = FALSE;
Delete * delete = data;
_idle_do(delete);
switch(delete->mode)
{
case DM_COUNT:
ret = _idle_count(delete);
break;
case DM_DELETE:
ret = _idle_delete(delete);
break;
}
if(ret == FALSE)
gtk_main_quit();
return ret;
}
static gboolean _idle_count(Delete * delete)
{
if(delete->file_cur == delete->filec)
{
gtk_main_quit();
return FALSE;
delete->mode = DM_DELETE;
delete->file_cur = 0;
gtk_label_set_text(GTK_LABEL(delete->label),
_("Deleting files..."));
gtk_widget_show(delete->hbox);
}
return TRUE;
}
static gboolean _idle_delete(Delete * delete)
{
return (delete->file_cur == delete->filec) ? FALSE : TRUE;
}
static int _idle_do_file(Delete * delete, char const * filename);
static int _idle_do_readdir(Delete * delete);
static int _idle_do_closedir(Delete * delete);
@ -272,6 +307,8 @@ static int _idle_do(Delete * delete)
return ret;
}
static int _idle_do_file_count(Delete * delete);
static int _idle_do_file_delete(Delete * delete, char const * filename);
static int _idle_do_file(Delete * delete, char const * filename)
{
struct stat st;
@ -297,7 +334,27 @@ static int _idle_do_file(Delete * delete, char const * filename)
|| _idle_ask_recursive(delete, filename) == 0)
return _idle_do_opendir(delete, filename);
}
else if((*(delete->prefs) & PREFS_f)
else
switch(delete->mode)
{
case DM_COUNT:
return _idle_do_file_count(delete);
case DM_DELETE:
return _idle_do_file_delete(delete, filename);
}
return 0;
}
static int _idle_do_file_count(Delete * delete)
{
delete->count_cnt++;
return 0;
}
static int _idle_do_file_delete(Delete * delete, char const * filename)
{
delete->count_cur++;
if((*(delete->prefs) & PREFS_f)
|| _idle_ask(delete, filename) == 0)
#ifdef DEBUG
fprintf(stderr, "DEBUG: unlink(\"%s\")\n", filename);
@ -334,17 +391,23 @@ static int _idle_do_readdir(Delete * delete)
return ret;
}
static int _idle_do_closedir_count(Delete * delete);
static int _idle_do_closedir_delete(Delete * delete, DeleteDir * dd);
static int _idle_do_closedir(Delete * delete)
{
int ret = 0;
DeleteDir * dd = delete->dirv[delete->dirv_cnt - 1];
closedir(dd->dir);
#ifdef DEBUG
fprintf(stderr, "DEBUG: rmdir(\"%s\")\n", dd->filename);
#else
if(rmdir(dd->filename) != 0)
_delete_filename_error(delete, dd->filename, 1);
#endif
switch(delete->mode)
{
case DM_COUNT:
ret = _idle_do_closedir_count(delete);
break;
case DM_DELETE:
ret = _idle_do_closedir_delete(delete, dd);
break;
}
free(dd->filename);
free(dd);
if(--delete->dirv_cnt == 0)
@ -353,6 +416,24 @@ static int _idle_do_closedir(Delete * delete)
delete->dirv = NULL;
delete->file_cur++;
}
return ret;
}
static int _idle_do_closedir_count(Delete * delete)
{
delete->count_cnt++;
return 0;
}
static int _idle_do_closedir_delete(Delete * delete, DeleteDir * dd)
{
delete->count_cur++;
#ifdef DEBUG
fprintf(stderr, "DEBUG: rmdir(\"%s\")\n", dd->filename);
#else
if(rmdir(dd->filename) != 0)
_delete_filename_error(delete, dd->filename, 1);
#endif
return 0;
}
@ -362,6 +443,13 @@ static int _idle_ask_recursive(Delete * delete, char const * filename)
GtkWidget * dialog;
int res;
switch(delete->mode)
{
case DM_COUNT:
return 0;
case DM_DELETE:
break;
}
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, filename);
#endif
@ -454,6 +542,23 @@ static int _idle_do_opendir(Delete * delete, char const * filename)
return 0;
}
static gboolean _delete_timeout(gpointer data)
{
Delete * delete = data;
switch(delete->mode)
{
case DM_COUNT:
gtk_progress_bar_pulse(GTK_PROGRESS_BAR(
delete->progress));
return TRUE;
case DM_DELETE:
break;
}
delete->timeout = 0;
return FALSE;
}
/* delete_error */
static int _error_text(char const * message, int ret);
@ -504,6 +609,44 @@ static int _delete_filename_error(Delete * delete, char const * filename,
}
/* delete_refresh */
static void _refresh_delete(Delete * delete, char const * filename);
static void _delete_refresh(Delete * delete, char const * filename)
{
switch(delete->mode)
{
case DM_COUNT:
break;
case DM_DELETE:
_refresh_delete(delete, filename);
break;
}
}
static void _refresh_delete(Delete * delete, char const * filename)
{
char * p;
char buf[64];
double fraction;
if((p = g_filename_to_utf8(filename, -1, NULL, NULL, NULL)) != NULL)
filename = p;
gtk_entry_set_text(GTK_ENTRY(delete->entry), filename);
free(p);
snprintf(buf, sizeof(buf), _("File %u of %u"), delete->file_cur + 1,
delete->filec);
fraction = MIN(delete->count_cur, delete->count_cnt);
fraction /= MAX(delete->count_cnt, 1);
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s() %f\n", __func__, fraction);
#endif
gtk_progress_bar_set_text(GTK_PROGRESS_BAR(delete->progress), buf);
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(delete->progress),
fraction);
}
/* usage */
static int _usage(void)
{