[file-roller: 61/123] use a byte based progress bar if the archive supports it
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [file-roller: 61/123] use a byte based progress bar if the archive supports it
- Date: Mon, 6 Aug 2012 13:45:59 +0000 (UTC)
commit 7a13b88467f0e795cbd13f869795b040a9aeee1e
Author: Paolo Bacchilega <paobac src gnome org>
Date: Tue Jul 24 09:23:23 2012 +0200
use a byte based progress bar if the archive supports it
with libarchive we can have a byte based progress indicator, instead of
file based.
src/fr-archive-libarchive.c | 9 ++-
src/fr-archive.c | 169 +++++++++++++++++++++++++++++++++++++++++--
src/fr-archive.h | 24 ++++--
src/fr-command-7z.c | 8 +-
src/fr-command-rar.c | 10 ++--
src/fr-command-tar.c | 5 +-
src/fr-command-unarchiver.c | 6 +-
src/fr-command-zip.c | 6 +-
src/fr-command.c | 23 +++---
src/fr-window.c | 27 +++++--
10 files changed, 229 insertions(+), 58 deletions(-)
---
diff --git a/src/fr-archive-libarchive.c b/src/fr-archive-libarchive.c
index 0d4db84..02c06fa 100644
--- a/src/fr-archive-libarchive.c
+++ b/src/fr-archive-libarchive.c
@@ -26,8 +26,10 @@
#include <archive.h>
#include <archive_entry.h>
#include "file-data.h"
+#include "fr-error.h"
#include "fr-archive-libarchive.h"
#include "glib-utils.h"
+#include "typedefs.h"
G_DEFINE_TYPE (FrArchiveLibarchive, fr_archive_libarchive, FR_TYPE_ARCHIVE)
@@ -172,6 +174,7 @@ load_archive_thread (GSimpleAsyncResult *result,
LoadData *load_data;
struct archive *a;
struct archive_entry *entry;
+ int r;
load_data = g_simple_async_result_get_op_res_gpointer (result);
@@ -179,7 +182,7 @@ load_archive_thread (GSimpleAsyncResult *result,
archive_read_support_filter_all (a);
archive_read_support_format_all (a);
archive_read_open (a, load_data, load_data_open, load_data_read, load_data_close);
- while (archive_read_next_header (a, &entry) == ARCHIVE_OK) {
+ while ((r = archive_read_next_header (a, &entry)) == ARCHIVE_OK) {
FileData *file_data;
const char *pathname;
@@ -228,12 +231,12 @@ load_archive_thread (GSimpleAsyncResult *result,
}
archive_read_free (a);
+ if ((load_data->error == NULL) && (r != ARCHIVE_EOF))
+ load_data->error = g_error_new_literal (FR_ERROR, FR_ERROR_COMMAND_ERROR, archive_error_string (a));
if (load_data->error == NULL)
g_cancellable_set_error_if_cancelled (cancellable, &load_data->error);
-
if (load_data->error != NULL)
g_simple_async_result_set_from_error (result, load_data->error);
- g_simple_async_result_complete_in_idle (result);
load_data_free (load_data);
}
diff --git a/src/fr-archive.c b/src/fr-archive.c
index 430b15b..b1155c8 100644
--- a/src/fr-archive.c
+++ b/src/fr-archive.c
@@ -45,6 +45,7 @@
#define FILE_ARRAY_INITIAL_SIZE 256
+#define PROGRESS_DELAY 100
char *action_names[] = { "NONE",
@@ -74,7 +75,16 @@ struct _FrArchivePrivate {
GFile *file;
FrArchiveCaps capabilities;
- /* internal */
+ /* progress data */
+
+ int total_files;
+ int completed_files;
+ gsize total_bytes;
+ gsize completed_bytes;
+ GMutex progress_mutex;
+ gulong progress_event;
+
+ /* others */
gboolean creating_archive;
char *extraction_destination;
@@ -222,6 +232,13 @@ fr_archive_finalize (GObject *object)
archive = FR_ARCHIVE (object);
_fr_archive_set_uri (archive, NULL);
+ if (archive->priv->progress_event != 0) {
+ g_source_remove (archive->priv->progress_event);
+ archive->priv->progress_event = 0;
+ }
+ g_mutex_clear (&archive->priv->progress_mutex);
+ g_hash_table_unref (archive->files_hash);
+ _g_ptr_array_free_full (archive->files, (GFunc) file_data_free, NULL);
/* Chain up */
@@ -404,6 +421,7 @@ fr_archive_init (FrArchive *self)
self->mime_type = NULL;
self->files = g_ptr_array_sized_new (FILE_ARRAY_INITIAL_SIZE);
+ self->files_hash = g_hash_table_new (g_str_hash, g_str_equal);
self->n_regular_files = 0;
self->password = NULL;
self->encrypt_header = FALSE;
@@ -412,8 +430,6 @@ fr_archive_init (FrArchive *self)
self->volume_size = 0;
self->read_only = FALSE;
self->extract_here = FALSE;
- self->n_file = 0;
- self->n_files = 0;
self->propAddCanUpdate = FALSE;
self->propAddCanReplace = FALSE;
@@ -432,6 +448,11 @@ fr_archive_init (FrArchive *self)
self->priv->creating_archive = FALSE;
self->priv->extraction_destination = NULL;
self->priv->have_write_permissions = FALSE;
+ self->priv->completed_files = 0;
+ self->priv->total_files = 0;
+ self->priv->completed_bytes = 0;
+ self->priv->total_bytes = 0;
+ g_mutex_init (&self->priv->progress_mutex);
}
@@ -861,6 +882,7 @@ fr_archive_load (FrArchive *archive,
g_return_if_fail (archive != NULL);
if (archive->files != NULL) {
+ g_hash_table_remove_all (archive->files_hash);
_g_ptr_array_free_full (archive->files, (GFunc) file_data_free, NULL);
archive->files = g_ptr_array_sized_new (FILE_ARRAY_INITIAL_SIZE);
}
@@ -874,7 +896,44 @@ fr_archive_operation_finish (FrArchive *archive,
GAsyncResult *result,
GError **error)
{
- return ! g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error);
+ gboolean success;
+
+ if (archive->priv->progress_event != 0) {
+ g_source_remove (archive->priv->progress_event);
+ archive->priv->progress_event = 0;
+ }
+
+ success = ! g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error);
+
+ if (success && (g_simple_async_result_get_source_tag (G_SIMPLE_ASYNC_RESULT (result)) == fr_archive_load)) {
+ int i;
+
+ /* order the list by name to speed up search */
+ g_ptr_array_sort (archive->files, file_data_compare_by_path);
+
+ /* update the file_data hash */
+ g_hash_table_remove_all (archive->files_hash);
+ for (i = 0; i < archive->files->len; i++) {
+ FileData *file_data = g_ptr_array_index (archive->files, i);
+ g_hash_table_insert (archive->files_hash, file_data->original_path, file_data);
+ }
+ }
+
+ if (! success && (error != NULL) && g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ g_error_free (*error);
+ *error = g_error_new_literal (FR_ERROR, FR_ERROR_STOPPED, "");
+ }
+
+ return success;
+}
+
+
+static gboolean
+_fr_archive_update_progress_cb (gpointer user_data)
+{
+ FrArchive *archive = user_data;
+ fr_archive_progress (archive, fr_archive_progress_get_fraction (archive));
+ return TRUE;
}
@@ -896,6 +955,7 @@ fr_archive_add_files (FrArchive *archive,
g_return_if_fail (! archive->read_only);
fr_archive_action_started (archive, FR_ACTION_ADDING_FILES);
+ archive->priv->progress_event = g_timeout_add (PROGRESS_DELAY, _fr_archive_update_progress_cb, archive);
FR_ARCHIVE_GET_CLASS (archive)->add_files (archive,
file_list,
@@ -1214,6 +1274,8 @@ fr_archive_remove (FrArchive *archive,
{
g_return_if_fail (! archive->read_only);
+ archive->priv->progress_event = g_timeout_add (PROGRESS_DELAY, _fr_archive_update_progress_cb, archive);
+
FR_ARCHIVE_GET_CLASS (archive)->remove_files (archive,
file_list,
compression,
@@ -1239,6 +1301,8 @@ fr_archive_extract (FrArchive *self,
g_free (self->priv->extraction_destination);
self->priv->extraction_destination = g_strdup (destination);
+ self->priv->progress_event = g_timeout_add (PROGRESS_DELAY, _fr_archive_update_progress_cb, self);
+
FR_ARCHIVE_GET_CLASS (self)->extract_files (self,
file_list,
destination,
@@ -1680,11 +1744,100 @@ fr_archive_working_archive (FrArchive *self,
void
-fr_archive_set_n_files (FrArchive *self,
- int n_files)
+fr_archive_progress_set_total_files (FrArchive *self,
+ int n_files)
+{
+ g_mutex_lock (&self->priv->progress_mutex);
+ self->priv->total_files = n_files;
+ self->priv->completed_files = 0;
+ g_mutex_unlock (&self->priv->progress_mutex);
+}
+
+
+int
+fr_archive_progress_get_total_files (FrArchive *self)
+{
+ int result;
+
+ g_mutex_lock (&self->priv->progress_mutex);
+ result = self->priv->total_files;
+ g_mutex_unlock (&self->priv->progress_mutex);
+
+ return result;
+}
+
+
+int
+fr_archive_progress_get_completed_files (FrArchive *self)
+{
+ int result;
+
+ g_mutex_lock (&self->priv->progress_mutex);
+ result = self->priv->completed_files;
+ g_mutex_unlock (&self->priv->progress_mutex);
+
+ return result;
+}
+
+
+double
+fr_archive_progress_inc_completed_files (FrArchive *self,
+ int new_completed)
+{
+ double fraction;
+
+ g_mutex_lock (&self->priv->progress_mutex);
+ self->priv->completed_files += new_completed;
+ fraction = (double) self->priv->completed_files / (self->priv->total_files + 1);
+ g_mutex_unlock (&self->priv->progress_mutex);
+
+ return fraction;
+
+}
+
+
+void
+fr_archive_progress_set_total_bytes (FrArchive *self,
+ gsize total)
+{
+ g_mutex_lock (&self->priv->progress_mutex);
+ self->priv->total_bytes = total;
+ self->priv->completed_bytes = 0;
+ g_mutex_unlock (&self->priv->progress_mutex);
+}
+
+
+double
+fr_archive_progress_inc_completed_bytes (FrArchive *self,
+ gsize new_completed)
+{
+ double fraction;
+
+ g_mutex_lock (&self->priv->progress_mutex);
+ self->priv->completed_bytes += new_completed;
+ fraction = (double) self->priv->completed_bytes / (self->priv->total_bytes + 1);
+ /*g_print ("%" G_GSIZE_FORMAT " / %" G_GSIZE_FORMAT " : %f\n", self->priv->completed_bytes, self->priv->total_bytes + 1, fraction);*/
+ g_mutex_unlock (&self->priv->progress_mutex);
+
+ return fraction;
+}
+
+
+double
+fr_archive_progress_get_fraction (FrArchive *self)
{
- self->n_files = n_files;
- self->n_file = 0;
+ double fraction;
+
+ g_mutex_lock (&self->priv->progress_mutex);
+ if ((self->priv->total_bytes > 0) && (self->priv->completed_bytes > 0))
+ fraction = (double) self->priv->completed_bytes / (self->priv->total_bytes + 1);
+ else if ((self->priv->total_files > 0) && (self->priv->completed_files > 0))
+ fraction = (double) self->priv->completed_files / (self->priv->total_files + 1);
+ else
+ fraction = 0.0;
+ g_mutex_unlock (&self->priv->progress_mutex);
+
+ return fraction;
}
diff --git a/src/fr-archive.h b/src/fr-archive.h
index 9e8a103..4d646ab 100644
--- a/src/fr-archive.h
+++ b/src/fr-archive.h
@@ -73,7 +73,8 @@ struct _FrArchive {
/*<public, read only>*/
const char *mime_type;
- GPtrArray *files; /* Array of FileData* */
+ GPtrArray *files; /* Array of FileData */
+ GHashTable *files_hash; /* Hash of FileData with original_path as key */
int n_regular_files;
/*<public>*/
@@ -91,11 +92,6 @@ struct _FrArchive {
gboolean extract_here;
- /* progress data */
-
- int n_file;
- int n_files;
-
/* features. */
/* propAddCanReplace:
@@ -498,8 +494,20 @@ void fr_archive_message (FrArchive *archive,
const char *msg);
void fr_archive_working_archive (FrArchive *archive,
const char *archive_name);
-void fr_archive_set_n_files (FrArchive *archive,
- int n_files);
+void fr_archive_progress_set_total_files(FrArchive *archive,
+ int total);
+int fr_archive_progress_get_total_files(FrArchive *archive);
+int fr_archive_progress_get_completed_files
+ (FrArchive *archive);
+double fr_archive_progress_inc_completed_files
+ (FrArchive *archive,
+ int new_completed);
+void fr_archive_progress_set_total_bytes (FrArchive *archive,
+ gsize total);
+double fr_archive_progress_inc_completed_bytes
+ (FrArchive *archive,
+ gsize new_completed);
+double fr_archive_progress_get_fraction (FrArchive *archive);
void fr_archive_add_file (FrArchive *archive,
FileData *file_data);
diff --git a/src/fr-command-7z.c b/src/fr-command-7z.c
index e4c4814..f407d89 100644
--- a/src/fr-command-7z.c
+++ b/src/fr-command-7z.c
@@ -257,8 +257,8 @@ parse_progress_line (FrArchive *archive,
prefix_len = strlen (prefix);
if (strncmp (line, prefix, prefix_len) == 0) {
- if (archive->n_files > 1) {
- fr_archive_progress (archive, (double) ++archive->n_file / (archive->n_files + 1));
+ if (fr_archive_progress_get_total_files (archive) > 1) {
+ fr_archive_progress (archive, fr_archive_progress_inc_completed_files (archive, 1));
}
else {
char filename[4196];
@@ -293,7 +293,7 @@ process_line__add (char *line,
g_free (volume_filename);
}
- if (archive->n_files != 0)
+ if (fr_archive_progress_get_total_files (archive) > 0)
parse_progress_line (archive, "Compressing ", _("Adding \"%s\""), line);
}
@@ -415,7 +415,7 @@ process_line__extract (char *line,
{
FrArchive *archive = FR_ARCHIVE (data);
- if (archive->n_files != 0)
+ if (fr_archive_progress_get_total_files (archive) > 0)
parse_progress_line (archive, "Extracting ", _("Extracting \"%s\""), line);
}
diff --git a/src/fr-command-rar.c b/src/fr-command-rar.c
index 328f322..e098427 100644
--- a/src/fr-command-rar.c
+++ b/src/fr-command-rar.c
@@ -258,8 +258,8 @@ parse_progress_line (FrCommand *comm,
prefix_len = strlen (prefix);
if (strncmp (line, prefix, prefix_len) == 0) {
- if (archive->n_files > 1) {
- fr_archive_progress (archive, (double) ++archive->n_file / (archive->n_files + 1));
+ if (fr_archive_progress_get_total_files (archive) > 1) {
+ fr_archive_progress (archive, fr_archive_progress_inc_completed_files (archive, 1));
}
else {
char filename[4096];
@@ -321,7 +321,7 @@ process_line__add (char *line,
return;
}
- if (archive->n_files != 0)
+ if (fr_archive_progress_get_total_files (archive) > 0)
parse_progress_line (comm, "Adding ", _("Adding \"%s\""), line);
}
@@ -399,7 +399,7 @@ process_line__delete (char *line,
return;
}
- if (FR_ARCHIVE (comm)->n_files != 0)
+ if (fr_archive_progress_get_total_files (FR_ARCHIVE (comm)) > 0)
parse_progress_line (comm, "Deleting ", _("Removing \"%s\""), line);
}
@@ -448,7 +448,7 @@ process_line__extract (char *line,
return;
}
- if (FR_ARCHIVE (comm)->n_files != 0)
+ if (fr_archive_progress_get_total_files (FR_ARCHIVE (comm)) > 0)
parse_progress_line (comm, "Extracting ", _("Extracting \"%s\""), line);
}
diff --git a/src/fr-command-tar.c b/src/fr-command-tar.c
index 28d1afd..471f5d8 100644
--- a/src/fr-command-tar.c
+++ b/src/fr-command-tar.c
@@ -286,9 +286,8 @@ process_line__generic (char *line,
if (line[strlen (line) - 1] == '/') /* ignore directories */
return;
- if (archive->n_files > 1) {
- double fraction = (double) ++archive->n_file / (archive->n_files + 1);
- fr_archive_progress (archive, fraction);
+ if (fr_archive_progress_get_total_files (archive) > 1) {
+ fr_archive_progress (archive, fr_archive_progress_inc_completed_files (archive, 1));
}
else {
char *msg = g_strdup_printf (message_format, _g_path_get_file_name (line), NULL);
diff --git a/src/fr-command-unarchiver.c b/src/fr-command-unarchiver.c
index bd67ac4..c88685e 100644
--- a/src/fr-command-unarchiver.c
+++ b/src/fr-command-unarchiver.c
@@ -160,10 +160,8 @@ process_line__extract (char *line,
if (unar_comm->n_line == 1)
return;
- if (archive->n_files > 1) {
- double fraction = (double) ++archive->n_file / (archive->n_files + 1);
- fr_archive_progress (archive, CLAMP (fraction, 0.0, 1.0));
- }
+ if (fr_archive_progress_get_total_files (archive) > 1)
+ fr_archive_progress (archive, fr_archive_progress_inc_completed_files (archive, 1));
else
fr_archive_message (archive, line);
}
diff --git a/src/fr-command-zip.c b/src/fr-command-zip.c
index 4994662..8d5707f 100644
--- a/src/fr-command-zip.c
+++ b/src/fr-command-zip.c
@@ -200,10 +200,8 @@ process_line__common (char *line,
if (line == NULL)
return;
- if (archive->n_files > 1) {
- double fraction = (double) ++archive->n_file / (archive->n_files + 1);
- fr_archive_progress (archive, fraction);
- }
+ if (fr_archive_progress_get_total_files (archive) > 1)
+ fr_archive_progress (archive, fr_archive_progress_inc_completed_files (archive, 1));
else
fr_archive_message (archive, line);
}
diff --git a/src/fr-command.c b/src/fr-command.c
index 7f4dc0c..d67185c 100644
--- a/src/fr-command.c
+++ b/src/fr-command.c
@@ -720,9 +720,6 @@ _fr_command_load_complete (LoadData *load_data)
archive = load_data->archive;
- /* order the list by name to speed up search */
- g_ptr_array_sort (archive->files, file_data_compare_by_path);
-
/* the name of the volumes are different from the
* original name */
if (archive->multi_volume)
@@ -1099,6 +1096,7 @@ _fr_command_add (FrCommand *self,
char *archive_filename = NULL;
char *tmp_archive_filename = NULL;
gboolean error_occurred = FALSE;
+ int new_file_list_length;
if (file_list == NULL)
return FALSE;
@@ -1226,9 +1224,10 @@ _fr_command_add (FrCommand *self,
/* add now. */
- fr_archive_set_n_files (archive, g_list_length (new_file_list));
+ new_file_list_length = g_list_length (new_file_list);
+ fr_archive_progress_set_total_files (archive, new_file_list_length);
- if (archive->propListFromFile && (archive->n_files > LIST_LENGTH_TO_USE_FILE)) {
+ if (archive->propListFromFile && (new_file_list_length > LIST_LENGTH_TO_USE_FILE)) {
char *list_dir;
char *list_filename;
@@ -1677,6 +1676,7 @@ delete_from_archive (FrCommand *self,
GList *tmp_file_list = NULL;
gboolean tmp_file_list_created = FALSE;
GList *scan;
+ int tmp_file_list_length;
/* file_list == NULL means delete all the files in the archive. */
@@ -1724,9 +1724,10 @@ delete_from_archive (FrCommand *self,
if (file_list_created)
g_list_free (file_list);
- fr_archive_set_n_files (archive, g_list_length (tmp_file_list));
+ tmp_file_list_length = g_list_length (tmp_file_list);
+ fr_archive_progress_set_total_files (archive, tmp_file_list_length);
- if (archive->propListFromFile && (archive->n_files > LIST_LENGTH_TO_USE_FILE)) {
+ if (archive->propListFromFile && (tmp_file_list_length > LIST_LENGTH_TO_USE_FILE)) {
char *list_dir;
char *list_filename;
@@ -2112,7 +2113,7 @@ extract_from_archive (FrCommand *self,
}
-static char*
+static char *
compute_base_path (const char *base_dir,
const char *path,
gboolean junk_paths,
@@ -2299,9 +2300,9 @@ _fr_command_extract (FrCommand *self,
}
if (extract_all && (file_list == NULL))
- fr_archive_set_n_files (archive, archive->files->len);
+ fr_archive_progress_set_total_files (archive, archive->files->len);
else
- fr_archive_set_n_files (archive, g_list_length (file_list));
+ fr_archive_progress_set_total_files (archive, g_list_length (file_list));
if (all_options_supported) {
gboolean created_filtered_list = FALSE;
@@ -2635,7 +2636,7 @@ fr_command_test_integrity (FrArchive *archive,
"filename", self->priv->local_copy,
"password", password,
NULL);
- fr_archive_set_n_files (archive, 0);
+ fr_archive_progress_set_total_files (archive, 0);
fr_process_clear (self->process);
fr_command_test (self);
diff --git a/src/fr-window.c b/src/fr-window.c
index d401a53..f1d6633 100644
--- a/src/fr-window.c
+++ b/src/fr-window.c
@@ -2691,17 +2691,13 @@ fr_archive_progress_cb (FrArchive *archive,
gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (window->priv->pd_progress_bar), fraction);
gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (window->priv->progress_bar), fraction);
- if ((archive != NULL) && (archive->n_files > 1)) {
+ if ((archive != NULL) && (fr_archive_progress_get_total_files (archive) > 1)) {
char *message = NULL;
int remaining_files;
- remaining_files = archive->n_files - archive->n_file + 1;
+ remaining_files = fr_archive_progress_get_total_files (archive) - fr_archive_progress_get_completed_files (archive) + 1;
switch (window->priv->action) {
- /* case FR_ACTION_CREATING_ARCHIVE:
- case FR_ACTION_RENAMING_FILES:
- case FR_ACTION_PASTING_FILES:
- case FR_ACTION_UPDATING_FILES: FIXME */
case FR_ACTION_ADDING_FILES:
case FR_ACTION_EXTRACTING_FILES:
case FR_ACTION_DELETING_FILES:
@@ -3089,7 +3085,7 @@ _archive_operation_completed (FrWindow *window,
if (opens_dialog)
return;
- operation_canceled = ((error != NULL) && (error->code == FR_ERROR_STOPPED));
+ operation_canceled = g_error_matches (error, FR_ERROR, FR_ERROR_STOPPED);
switch (action) {
case FR_ACTION_CREATING_NEW_ARCHIVE:
@@ -6706,8 +6702,23 @@ static void
_fr_window_archive_extract_from_edata (FrWindow *window,
ExtractData *edata)
{
- _archive_operation_started (window, FR_ACTION_EXTRACTING_FILES);
+ GList *scan;
+ gsize total_size;
+
+ total_size = 0;
+ for (scan = edata->file_list; scan; scan = scan->next) {
+ char *filename = scan->data;
+ FileData *file_data;
+
+ file_data = g_hash_table_lookup (window->archive->files_hash, filename);
+ if (file_data == NULL)
+ continue;
+
+ total_size += file_data->size;
+ }
+ fr_archive_progress_set_total_bytes (window->archive, total_size);
+ _archive_operation_started (window, FR_ACTION_EXTRACTING_FILES);
window->priv->ask_to_open_destination_after_extraction = edata->ask_to_open_destination;
fr_archive_extract (window->archive,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]