[gnome-commander] Rewrite of many methods for transering files and folders via GIO
- From: Uwe Scholz <uwescholz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-commander] Rewrite of many methods for transering files and folders via GIO
- Date: Fri, 27 Aug 2021 18:14:07 +0000 (UTC)
commit a0a6b876ef1907a62409f08b1902ce7827d71513
Author: Uwe Scholz <u scholz83 gmx de>
Date: Fri Aug 27 20:10:48 2021 +0200
Rewrite of many methods for transering files and folders via GIO
There is still a lot to do
src/cap.cc | 14 +-
src/dialogs/gnome-cmd-make-copy-dialog.cc | 8 +-
src/dialogs/gnome-cmd-prepare-copy-dialog.cc | 13 +-
src/dialogs/gnome-cmd-prepare-xfer-dialog.cc | 11 +-
src/dialogs/gnome-cmd-prepare-xfer-dialog.h | 1 +
src/gnome-cmd-file-list.cc | 120 ++-
src/gnome-cmd-file-list.h | 15 +-
src/gnome-cmd-file.cc | 8 +-
src/gnome-cmd-xfer.cc | 1244 +++++++++++++++++++++++---
src/gnome-cmd-xfer.h | 112 ++-
10 files changed, 1318 insertions(+), 228 deletions(-)
---
diff --git a/src/cap.cc b/src/cap.cc
index eb8def1d..10b252fe 100644
--- a/src/cap.cc
+++ b/src/cap.cc
@@ -1,4 +1,4 @@
-/**
+/**
* @file cap.cc
* @copyright (C) 2001-2006 Marcus Bjurman\n
* @copyright (C) 2007-2012 Piotr Eljasiak\n
@@ -57,12 +57,12 @@ inline void update_refs (GnomeCmdFileList *fl, GList *files)
inline void cut_and_paste (GnomeCmdDir *to)
{
- gnome_cmd_xfer_start (_files,
+ gnome_cmd_move_start (_files,
gnome_cmd_dir_ref (to),
_fl,
NULL,
- GNOME_VFS_XFER_REMOVESOURCE,
- GNOME_VFS_XFER_OVERWRITE_MODE_QUERY,
+ G_FILE_COPY_NONE,
+ true,
GTK_SIGNAL_FUNC (on_xfer_done), _files);
_files = NULL;
_fl = NULL;
@@ -72,12 +72,12 @@ inline void cut_and_paste (GnomeCmdDir *to)
inline void copy_and_paste (GnomeCmdDir *to)
{
- gnome_cmd_xfer_start (_files,
+ gnome_cmd_copy_start (_files,
gnome_cmd_dir_ref (to),
_fl,
NULL,
- GNOME_VFS_XFER_RECURSIVE,
- GNOME_VFS_XFER_OVERWRITE_MODE_QUERY,
+ G_FILE_COPY_NONE,
+ true,
GTK_SIGNAL_FUNC (on_xfer_done), _files);
_files = NULL;
_fl = NULL;
diff --git a/src/dialogs/gnome-cmd-make-copy-dialog.cc b/src/dialogs/gnome-cmd-make-copy-dialog.cc
index f0e9e1b9..a4039860 100644
--- a/src/dialogs/gnome-cmd-make-copy-dialog.cc
+++ b/src/dialogs/gnome-cmd-make-copy-dialog.cc
@@ -1,4 +1,4 @@
-/**
+/**
* @file gnome-cmd-make-copy-dialog.cc
* @copyright (C) 2001-2006 Marcus Bjurman\n
* @copyright (C) 2007-2012 Piotr Eljasiak\n
@@ -43,12 +43,12 @@ inline void copy_file (GnomeCmdFile *f, GnomeCmdDir *dir, const gchar *filename)
{
GList *src_files = g_list_append (NULL, f);
- gnome_cmd_xfer_start (src_files,
+ gnome_cmd_copy_start (src_files,
dir,
NULL,
g_strdup (filename),
- GNOME_VFS_XFER_RECURSIVE,
- GNOME_VFS_XFER_OVERWRITE_MODE_QUERY,
+ G_FILE_COPY_NONE,
+ true,
NULL,
NULL);
}
diff --git a/src/dialogs/gnome-cmd-prepare-copy-dialog.cc b/src/dialogs/gnome-cmd-prepare-copy-dialog.cc
index 5a9b6a0a..0a394364 100644
--- a/src/dialogs/gnome-cmd-prepare-copy-dialog.cc
+++ b/src/dialogs/gnome-cmd-prepare-copy-dialog.cc
@@ -51,8 +51,13 @@ static void on_ok (GtkButton *button, gpointer user_data)
PrepareCopyData *data = (PrepareCopyData *) user_data;
GnomeCmdPrepareXferDialog *dlg = data->dialog;
+ guint gFileCopyFlags = 0;
+
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->silent)))
+ {
dlg->xferOverwriteMode = GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE;
+ gFileCopyFlags |= G_FILE_COPY_OVERWRITE;
+ }
else
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->query)))
dlg->xferOverwriteMode = GNOME_VFS_XFER_OVERWRITE_MODE_QUERY;
@@ -62,9 +67,15 @@ static void on_ok (GtkButton *button, gpointer user_data)
guint xferOptions = GNOME_VFS_XFER_RECURSIVE;
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->follow_links)))
+ {
xferOptions |= GNOME_VFS_XFER_FOLLOW_LINKS;
-
+ }
+ else
+ {
+ gFileCopyFlags |= G_FILE_COPY_NOFOLLOW_SYMLINKS;
+ }
dlg->xferOptions = (GnomeVFSXferOptions) xferOptions;
+ dlg->gFileCopyFlags = (GFileCopyFlags) gFileCopyFlags;
}
diff --git a/src/dialogs/gnome-cmd-prepare-xfer-dialog.cc b/src/dialogs/gnome-cmd-prepare-xfer-dialog.cc
index ba55517a..01bfc0ca 100644
--- a/src/dialogs/gnome-cmd-prepare-xfer-dialog.cc
+++ b/src/dialogs/gnome-cmd-prepare-xfer-dialog.cc
@@ -225,13 +225,20 @@ static void on_ok (GtkButton *button, GnomeCmdPrepareXferDialog *dialog)
gnome_cmd_dir_ref (dest_dir);
- gnome_cmd_xfer_start (dialog->src_files,
+ gnome_cmd_copy_start (dialog->src_files,
dest_dir,
dialog->src_fs->file_list(),
dest_fn,
- dialog->xferOptions,
+ dialog->gFileCopyFlags,
dialog->xferOverwriteMode,
NULL, NULL);
+// gnome_cmd_move_start (dialog->src_files,
+// dest_dir,
+// dialog->src_fs->file_list(),
+// dest_fn,
+// dialog->gFileCopyFlags,
+// dialog->xferOverwriteMode,
+// NULL, NULL);
bailout:
g_free (dest_path);
diff --git a/src/dialogs/gnome-cmd-prepare-xfer-dialog.h b/src/dialogs/gnome-cmd-prepare-xfer-dialog.h
index 5a34d0c6..b5887d3f 100644
--- a/src/dialogs/gnome-cmd-prepare-xfer-dialog.h
+++ b/src/dialogs/gnome-cmd-prepare-xfer-dialog.h
@@ -44,6 +44,7 @@ struct GnomeCmdPrepareXferDialog
GtkWidget *ok_button;
GtkWidget *cancel_button;
+ GFileCopyFlags gFileCopyFlags;
GnomeVFSXferOptions xferOptions;
GnomeVFSXferOverwriteMode xferOverwriteMode;
diff --git a/src/gnome-cmd-file-list.cc b/src/gnome-cmd-file-list.cc
index 50bb7348..d6ed0e1e 100644
--- a/src/gnome-cmd-file-list.cc
+++ b/src/gnome-cmd-file-list.cc
@@ -185,7 +185,9 @@ struct GnomeCmdFileList::Private
static gchar *translate_menu(const gchar *path, gpointer);
- static void on_dnd_popup_menu(GnomeCmdFileList *fl, GnomeVFSXferOptions xferOptions, GtkWidget *widget);
+ static void on_dnd_popup_menu_copy(GnomeCmdFileList *fl, GFileCopyFlags gFileCopyFlags, GtkWidget
*widget);
+ static void on_dnd_popup_menu_move(GnomeCmdFileList *fl, GFileCopyFlags gFileCopyFlags, GtkWidget
*widget);
+ static void on_dnd_popup_menu_link(GnomeCmdFileList *fl, GFileCopyFlags gFileCopyFlags, GtkWidget
*widget);
};
@@ -221,11 +223,11 @@ GnomeCmdFileList::Private::Private(GnomeCmdFileList *fl)
gtk_clist_set_column_resizeable (*fl, i, TRUE);
static GtkItemFactoryEntry items[] = {
- {(gchar*) N_("/_Copy here"), (gchar*) "<control>",
(GtkItemFactoryCallback) on_dnd_popup_menu, GNOME_VFS_XFER_RECURSIVE, (gchar*) "<StockItem>", GTK_STOCK_COPY},
- {(gchar*) N_("/_Move here"), (gchar*) "<shift>",
(GtkItemFactoryCallback) on_dnd_popup_menu, GNOME_VFS_XFER_REMOVESOURCE, (gchar*) "<StockItem>",
GTK_STOCK_COPY},
- {(gchar*) N_("/_Link here"), (gchar*) "<control><shift>",
(GtkItemFactoryCallback) on_dnd_popup_menu,GNOME_VFS_XFER_LINK_ITEMS, (gchar*) "<StockItem>",
GTK_STOCK_CONVERT},
+ {(gchar*) N_("/_Copy here"), (gchar*) "<control>",
(GtkItemFactoryCallback) on_dnd_popup_menu_copy, G_FILE_COPY_NONE, (gchar*) "<StockItem>", GTK_STOCK_COPY},
+ {(gchar*) N_("/_Move here"), (gchar*) "<shift>",
(GtkItemFactoryCallback) on_dnd_popup_menu_move, G_FILE_COPY_NONE, (gchar*) "<StockItem>", GTK_STOCK_COPY},
+ {(gchar*) N_("/_Link here"), (gchar*) "<control><shift>",
(GtkItemFactoryCallback) on_dnd_popup_menu_link,G_FILE_COPY_NONE, (gchar*) "<StockItem>", GTK_STOCK_CONVERT},
{(gchar*) "/", nullptr, nullptr, 0, (gchar*) "<Separator>"},
- {(gchar*) N_("/C_ancel"), (gchar*) "Esc",
(GtkItemFactoryCallback) on_dnd_popup_menu, 0, (gchar*) "<StockItem>", GTK_STOCK_CANCEL}
+ {(gchar*) N_("/C_ancel"), (gchar*) "Esc", nullptr, 1, (gchar*)
"<StockItem>", GTK_STOCK_CANCEL}
};
ifac = gtk_item_factory_new (GTK_TYPE_MENU, (const gchar*) "<main>", nullptr);
@@ -246,19 +248,40 @@ gchar *GnomeCmdFileList::Private::translate_menu(const gchar *path, gpointer unu
}
-void GnomeCmdFileList::Private::on_dnd_popup_menu(GnomeCmdFileList *fl, GnomeVFSXferOptions xferOptions,
GtkWidget *widget)
+void GnomeCmdFileList::Private::on_dnd_popup_menu_copy(GnomeCmdFileList *fl, GFileCopyFlags gFileCopyFlags,
GtkWidget *widget)
+{
+ g_return_if_fail (GNOME_CMD_IS_FILE_LIST (fl));
+
+ auto data = (gpointer *) gtk_item_factory_popup_data_from_widget (widget);
+ auto gFileGlist = (GList *) data[0];
+ auto to = static_cast<GnomeCmdDir*> (data[1]);
+
+ data[0] = nullptr;
+ fl->drop_files(GnomeCmdFileList::DndMode::COPY, gFileCopyFlags, gFileGlist, to);
+}
+
+void GnomeCmdFileList::Private::on_dnd_popup_menu_move(GnomeCmdFileList *fl, GFileCopyFlags gFileCopyFlags,
GtkWidget *widget)
{
g_return_if_fail (GNOME_CMD_IS_FILE_LIST (fl));
gpointer *data = (gpointer *) gtk_item_factory_popup_data_from_widget (widget);
- GList *uri_list = (GList *) data[0];
+ GList *gFileGlist = (GList *) data[0];
auto to = static_cast<GnomeCmdDir*> (data[1]);
- if (xferOptions)
- {
- data[0] = nullptr;
- fl->drop_files(xferOptions,uri_list,to);
- }
+ data[0] = nullptr;
+ fl->drop_files(GnomeCmdFileList::DndMode::MOVE, gFileCopyFlags, gFileGlist, to);
+}
+
+void GnomeCmdFileList::Private::on_dnd_popup_menu_link(GnomeCmdFileList *fl, GFileCopyFlags gFileCopyFlags,
GtkWidget *widget)
+{
+ g_return_if_fail (GNOME_CMD_IS_FILE_LIST (fl));
+
+ gpointer *data = (gpointer *) gtk_item_factory_popup_data_from_widget (widget);
+ GList *gFileGlist = (GList *) data[0];
+ auto to = static_cast<GnomeCmdDir*> (data[1]);
+
+ data[0] = nullptr;
+ fl->drop_files(GnomeCmdFileList::DndMode::LINK, gFileCopyFlags, gFileGlist, to);
}
@@ -1252,7 +1275,7 @@ static void on_tmp_download_response (GtkWidget *w, gint id, TmpDlData *dldata)
GnomeCmdPlainPath path(path_str);
auto destGFile = gnome_cmd_con_create_gfile (get_home_con (), &path);
- gnome_cmd_xfer_tmp_download (sourceGFile,
+ gnome_cmd_tmp_download (sourceGFile,
destGFile,
G_FILE_COPY_OVERWRITE,
GTK_SIGNAL_FUNC (do_mime_exec_single),
@@ -2212,6 +2235,8 @@ void GnomeCmdFileList::toggle_and_step()
void GnomeCmdFileList::focus_file(const gchar *file_to_focus, gboolean scroll_to_file)
{
+ g_return_if_fail(file_to_focus != nullptr);
+
for (auto i = get_visible_files(); i; i = i->next)
{
auto f = static_cast<GnomeCmdFile*> (i->data);
@@ -2223,7 +2248,7 @@ void GnomeCmdFileList::focus_file(const gchar *file_to_focus, gboolean scroll_to
return;
auto basename = g_file_get_basename(f->gFile);
- if (strcmp (basename, file_to_focus) == 0)
+ if (basename && strcmp (basename, file_to_focus) == 0)
{
g_free(basename);
priv->cur_file = row;
@@ -3087,8 +3112,8 @@ static void free_dnd_popup_data (gpointer *data)
{
if (data)
{
- GList *uri_list = (GList *) data[0];
- unref_uri_list (uri_list);
+ GList *gFileGlist = (GList *) data[0];
+ unref_gfile_list (gFileGlist);
}
g_free (data);
@@ -3124,7 +3149,7 @@ static void drag_data_received (GtkWidget *widget, GdkDragContext *context, gint
{
gpointer *arr = g_new (gpointer, 2);
- arr[0] = uri_list;
+ arr[0] = gFileGlist;
arr[1] = to;
gtk_item_factory_popup_with_data (fl->priv->ifac, arr, (GDestroyNotify) free_dnd_popup_data, x, y,
0, time);
@@ -3132,8 +3157,6 @@ static void drag_data_received (GtkWidget *widget, GdkDragContext *context, gint
return;
}
- GnomeVFSXferOptions xferOptions;
-
// find out what operation to perform
#if defined (__GNUC__)
#pragma GCC diagnostic push
@@ -3142,15 +3165,15 @@ static void drag_data_received (GtkWidget *widget, GdkDragContext *context, gint
switch (context->action)
{
case GDK_ACTION_MOVE:
- xferOptions = GNOME_VFS_XFER_REMOVESOURCE;
+ fl->drop_files(GnomeCmdFileList::DndMode::MOVE, G_FILE_COPY_NONE, gFileGlist, to);
break;
case GDK_ACTION_COPY:
- xferOptions = GNOME_VFS_XFER_RECURSIVE;
+ fl->drop_files(GnomeCmdFileList::DndMode::COPY, G_FILE_COPY_NONE, gFileGlist, to);
break;
case GDK_ACTION_LINK:
- xferOptions = GNOME_VFS_XFER_LINK_ITEMS;
+ fl->drop_files(GnomeCmdFileList::DndMode::LINK, G_FILE_COPY_NONE, gFileGlist, to);
break;
default:
@@ -3160,8 +3183,6 @@ static void drag_data_received (GtkWidget *widget, GdkDragContext *context, gint
#if defined (__GNUC__)
#pragma GCC diagnostic pop
#endif
-
- fl->drop_files(xferOptions,uri_list,to);
}
@@ -3242,19 +3263,46 @@ void GnomeCmdFileList::init_dnd()
g_signal_connect (this, "drag-data-received", G_CALLBACK (drag_data_received), this);
}
-
-void GnomeCmdFileList::drop_files(GnomeVFSXferOptions xferOptions, GList *uri_list, GnomeCmdDir *dir)
+void GnomeCmdFileList::drop_files(DndMode dndMode, GFileCopyFlags gFileCopyFlags, GList *gFileGlist,
GnomeCmdDir *dir)
{
g_return_if_fail (GNOME_CMD_IS_DIR (dir));
- // start the xfer
- gnome_cmd_xfer_gfiles_start (uri_list,
- gnome_cmd_dir_ref (dir),
- nullptr,
- nullptr,
- g_list_length (uri_list) == 1 ? gnome_vfs_unescape_string
(gnome_vfs_uri_extract_short_name ((GnomeVFSURI *) uri_list->data), 0) : nullptr,
- xferOptions,
- GNOME_VFS_XFER_OVERWRITE_MODE_QUERY,
- GTK_SIGNAL_FUNC (unref_uri_list),
- uri_list);
+ switch (dndMode)
+ {
+ case COPY:
+ gnome_cmd_copy_gfiles_start (gFileGlist,
+ gnome_cmd_dir_ref (dir),
+ nullptr,
+ nullptr,
+ g_list_length (gFileGlist) == 1 ? g_file_get_basename ((GFile *)
gFileGlist->data) : nullptr,
+ gFileCopyFlags,
+ true,
+ nullptr,
+ nullptr);
+ break;
+ case MOVE:
+ gnome_cmd_move_gfiles_start (gFileGlist,
+ gnome_cmd_dir_ref (dir),
+ nullptr,
+ nullptr,
+ g_list_length (gFileGlist) == 1 ? g_file_get_basename ((GFile *)
gFileGlist->data) : nullptr,
+ gFileCopyFlags,
+ true,
+ nullptr,
+ nullptr);
+ break;
+ case LINK:
+ gnome_cmd_link_gfiles_start (gFileGlist,
+ gnome_cmd_dir_ref (dir),
+ nullptr,
+ nullptr,
+ g_list_length (gFileGlist) == 1 ? g_file_get_basename ((GFile *)
gFileGlist->data) : nullptr,
+ gFileCopyFlags,
+ true,
+ nullptr,
+ nullptr);
+ break;
+ default:
+ return;
+ }
}
diff --git a/src/gnome-cmd-file-list.h b/src/gnome-cmd-file-list.h
index 1d9b38a5..a521bac3 100644
--- a/src/gnome-cmd-file-list.h
+++ b/src/gnome-cmd-file-list.h
@@ -151,7 +151,7 @@ struct GnomeCmdFileList
* Returns a list with all files shown in the file list. The list is
* the same as that in the file list it self so make a copy and ref
* the files if needed
- */
+ */
GList *get_visible_files();
/**
@@ -160,13 +160,13 @@ struct GnomeCmdFileList
* list is however not refed before returning
*/
GList *get_selected_files();
-
+
/**
* Returns a collection of all selected files.
* A marked file is a file that has been selected with ins etc. The file that is currently focused is
not marked.
*/
GnomeCmd::Collection<GnomeCmdFile *> &get_marked_files();
-
+
/**
* Returns the currently focused file if any. The returned file is
* not reffed. The ".." file is returned if focused
@@ -215,8 +215,15 @@ struct GnomeCmdFileList
gboolean key_pressed(GdkEventKey *event);
+ enum DndMode
+ {
+ COPY,
+ MOVE,
+ LINK
+ };
+
void init_dnd();
- void drop_files(GnomeVFSXferOptions xferOptions, GList *uri_list, GnomeCmdDir *dir);
+ void drop_files(DndMode dndMode, GFileCopyFlags gFileCopyFlags, GList *uri_list, GnomeCmdDir *dir);
};
diff --git a/src/gnome-cmd-file.cc b/src/gnome-cmd-file.cc
index 99a8e874..edf84457 100644
--- a/src/gnome-cmd-file.cc
+++ b/src/gnome-cmd-file.cc
@@ -443,6 +443,9 @@ gchar *GnomeCmdFile::get_path()
auto filename = g_file_info_get_name (this->gFileInfo);
+ if (!filename)
+ return nullptr;
+
if (strcmp (filename, G_DIR_SEPARATOR_S) == 0)
return g_strdup(filename);
@@ -593,8 +596,9 @@ GFile *GnomeCmdFile::get_gfile(const gchar *name)
g_assert ("Non directory file without owning directory");
}
auto filename = g_file_get_basename(gFile);
- return gnome_cmd_dir_get_child_gfile (::get_parent_dir (this), name ? name : filename);
+ auto childGFile = gnome_cmd_dir_get_child_gfile (::get_parent_dir (this), name ? name : filename);
g_free(filename);
+ return childGFile;
}
@@ -882,7 +886,7 @@ void gnome_cmd_file_view (GnomeCmdFile *f, gint internal_viewer)
g_printerr ("Copying to: %s\n", path_str);
g_free (path_str);
- gnome_cmd_xfer_tmp_download (srcGFile,
+ gnome_cmd_tmp_download (srcGFile,
destGFile,
G_FILE_COPY_OVERWRITE,
GTK_SIGNAL_FUNC (on_file_downloaded_for_view),
diff --git a/src/gnome-cmd-xfer.cc b/src/gnome-cmd-xfer.cc
index eb7cc00d..02f255a3 100644
--- a/src/gnome-cmd-xfer.cc
+++ b/src/gnome-cmd-xfer.cc
@@ -23,6 +23,8 @@
#include <unistd.h>
#include "gnome-cmd-includes.h"
+#include "gnome-cmd-con-list.h"
+#include "gnome-cmd-plain-path.h"
#include "gnome-cmd-xfer.h"
#include "gnome-cmd-file-selector.h"
#include "gnome-cmd-file-list.h"
@@ -30,17 +32,10 @@
#include "gnome-cmd-main-win.h"
#include "gnome-cmd-data.h"
#include "utils.h"
+#include "src/dialogs/gnome-cmd-delete-dialog.h"
using namespace std;
-
-#define XFER_PRIORITY GNOME_VFS_PRIORITY_DEFAULT
-
-#define XFER_ERROR_ACTION_DEFAULT -1
-#define XFER_ERROR_ACTION_ABORT 0
-#define XFER_ERROR_ACTION_RETRY 1
-#define XFER_ERROR_ACTION_SKIP 2
-
inline void free_xfer_data (XferData *xferData)
{
// free the list with target uris
@@ -73,49 +68,30 @@ create_xfer_data (GFileCopyFlags copyFlags, GList *srcGFileList, GList *destGFil
xferData->copyFlags = copyFlags;
xferData->srcGFileList = srcGFileList;
xferData->destGFileList = destGFileList;
- xferData->to_dir = to_dir;
+ xferData->destGnomeCmdDir = to_dir;
xferData->src_fl = src_fl;
xferData->src_files = src_files;
xferData->win = nullptr;
xferData->cur_file_name = nullptr;
- xferData->cur_file = -1;
- xferData->prev_file = -1;
- xferData->files_total = 0;
- xferData->prev_totalprog = (gfloat) 0.00;
+ xferData->curFileNumber = 0;
+ xferData->filesTotal = 0;
xferData->first_time = TRUE;
xferData->on_completed_func = on_completed_func;
xferData->on_completed_data = on_completed_data;
xferData->done = FALSE;
xferData->aborted = FALSE;
xferData->problem = FALSE;
- xferData->problem_action = -1;
- xferData->problem_file_name = nullptr;
+ xferData->problem_action = COPY_ERROR_ACTION_NO_ACTION_YET;
xferData->thread = nullptr;
xferData->error = nullptr;
- //ToDo: Fix this to complete migration from gnome-vfs to gvfs
- // If this is a move-operation, determine totals
- // The async_xfer_callback-results for file and byte totals are not reliable
- //if (xferOptions == GNOME_VFS_XFER_REMOVESOURCE) {
- // GList *uris;
- // xferData->bytes_total = 0;
- // xferData->files_total = 0;
- // for (uris = xferData->srcGFileList; uris != nullptr; uris = uris->next) {
- // GnomeVFSURI *uri;
- // uri = (GnomeVFSURI*)uris->xferData;
- // xferData->bytes_total += calc_tree_size(uri,&(xferData->files_total));
- // g_object_unref(gFile);
- // }
- //}
-
return xferData;
}
-inline gchar *file_details(const gchar *text_uri)
+inline gchar *get_file_details_string(GFile *gFile)
{
- auto gFileTmp = g_file_new_for_uri(text_uri);
- auto gFileInfoTmp = g_file_query_info(gFileTmp,
+ auto gFileInfoTmp = g_file_query_info(gFile,
G_FILE_ATTRIBUTE_STANDARD_SIZE "," G_FILE_ATTRIBUTE_TIME_MODIFIED,
G_FILE_QUERY_INFO_NONE, nullptr, nullptr);
gchar *size = create_nice_size_str (g_file_info_get_attribute_uint64(gFileInfoTmp,
G_FILE_ATTRIBUTE_STANDARD_SIZE));
@@ -133,22 +109,370 @@ inline gchar *file_details(const gchar *text_uri)
}
-static gint async_xfer_callback (GnomeVFSAsyncHandle *handle, GnomeVFSXferProgressInfo *info, XferData *data)
+static void run_simple_error_dialog(const char *msg, XferData *xferData)
+{
+ gdk_threads_enter ();
+ gint guiResponse = run_simple_dialog (
+ *main_win, TRUE, GTK_MESSAGE_ERROR, msg, _("Transfer problem"),
+ -1, _("Abort"), _("Retry"), _("Skip"), NULL);
+ gdk_threads_leave ();
+
+ switch (guiResponse)
+ {
+ case 0:
+ xferData->problem_action = COPY_ERROR_ACTION_ABORT;
+ break;
+ case 1:
+ xferData->problem_action = COPY_ERROR_ACTION_RETRY;
+ break;
+ case 2:
+ xferData->problem_action = COPY_ERROR_ACTION_SKIP;
+ break;
+ default:
+ xferData->problem_action = COPY_ERROR_ACTION_RETRY;
+ break;
+ }
+}
+
+static void update_transfer_gui_error_copy (XferData *xferData)
+{
+ gint guiResponse = -1;
+
+ gchar *msg = g_strdup_printf (_("Error while transferring “%s”\n\n%s"),
+ g_file_peek_path(xferData->problemSrcGFile),
+ xferData->error->message);
+
+ if(!g_error_matches(xferData->error, G_IO_ERROR, G_IO_ERROR_EXISTS))
+ {
+ run_simple_error_dialog(msg, xferData);
+ }
+ else
+ {
+ if (xferData->currentFileType == G_FILE_TYPE_DIRECTORY)
+ {
+ gdk_threads_enter ();
+ g_list_length(xferData->srcGFileList) > 1
+ ? guiResponse = run_simple_dialog (
+ *main_win, TRUE, GTK_MESSAGE_ERROR, msg, _("Copy problem"),
+ -1, _("Abort"), _("Retry"), _("Copy into"), _("Rename"), _("Rename all"), _("Skip"), _("Skip
all"), NULL)
+ : guiResponse = run_simple_dialog (
+ *main_win, TRUE, GTK_MESSAGE_ERROR, msg, _("Copy problem"),
+ -1, _("Abort"), _("Retry"), _("Copy into"), _("Rename"), NULL);
+ gdk_threads_leave ();
+ switch (guiResponse)
+ {
+ case 0:
+ xferData->problem_action = COPY_ERROR_ACTION_ABORT;
+ break;
+ case 1:
+ xferData->problem_action = COPY_ERROR_ACTION_RETRY;
+ break;
+ case 2:
+ xferData->problem_action = COPY_ERROR_ACTION_COPY_INTO;
+ break;
+ case 3:
+ xferData->problem_action = COPY_ERROR_ACTION_RENAME;
+ break;
+ case 4:
+ xferData->problem_action = COPY_ERROR_ACTION_RENAME_ALL;
+ break;
+ case 5:
+ xferData->problem_action = COPY_ERROR_ACTION_SKIP;
+ break;
+ case 6:
+ xferData->problem_action = COPY_ERROR_ACTION_SKIP_ALL;
+ break;
+ default:
+ xferData->problem_action = COPY_ERROR_ACTION_RETRY;
+ break;
+ }
+ }
+ if (xferData->currentFileType == G_FILE_TYPE_REGULAR)
+ {
+ auto problemSrcBasename = get_gfile_attribute_string(xferData->problemSrcGFile,
+ G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME);
+ auto problemDestBasename = get_gfile_attribute_string(xferData->problemDestGFile,
+ G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME);
+ auto sourceDetails = get_file_details_string (xferData->problemSrcGFile);
+ auto targetDetails = get_file_details_string (xferData->problemDestGFile);
+ g_free(msg);
+ msg = g_strdup_printf (_("Overwrite file:\n\n<b>%s</b>\n<span color='dimgray'
size='smaller'>%s</span>\n\nWith:\n\n<b>%s</b>\n<span color='dimgray' size='smaller'>%s</span>"),
+ problemDestBasename,
+ targetDetails,
+ problemSrcBasename,
+ sourceDetails);
+ g_free (problemSrcBasename);
+ g_free (problemDestBasename);
+ g_free (sourceDetails);
+ g_free (targetDetails);
+ gdk_threads_enter ();
+ xferData->filesTotal > 1
+ ? guiResponse = run_simple_dialog (
+ *main_win, TRUE, GTK_MESSAGE_ERROR, msg, _("Copy problem"),
+ -1, _("Abort"), _("Retry"), _("Replace"), _("Rename"), _("Skip"), _("Replace all"),
_("Rename all"), _("Skip all"), NULL)
+ : guiResponse = run_simple_dialog (
+ *main_win, TRUE, GTK_MESSAGE_ERROR, msg, _("Copy problem"),
+ -1, _("Abort"), _("Retry"), _("Replace"), _("Rename"), NULL);
+ gdk_threads_leave ();
+ switch (guiResponse)
+ {
+ case 0:
+ xferData->problem_action = COPY_ERROR_ACTION_ABORT;
+ break;
+ case 1:
+ xferData->problem_action = COPY_ERROR_ACTION_RETRY;
+ break;
+ case 2:
+ xferData->problem_action = COPY_ERROR_ACTION_REPLACE;
+ break;
+ case 3:
+ xferData->problem_action = COPY_ERROR_ACTION_RENAME;
+ break;
+ case 4:
+ xferData->problem_action = COPY_ERROR_ACTION_SKIP;
+ break;
+ case 5:
+ xferData->problem_action = COPY_ERROR_ACTION_REPLACE_ALL;
+ break;
+ case 6:
+ xferData->problem_action = COPY_ERROR_ACTION_RENAME_ALL;
+ break;
+ case 7:
+ xferData->problem_action = COPY_ERROR_ACTION_SKIP_ALL;
+ break;
+ default:
+ xferData->problem_action = COPY_ERROR_ACTION_RETRY;
+ break;
+ }
+ }
+ }
+ g_free (msg);
+}
+
+static void update_transfer_gui_error_move (XferData *xferData)
+{
+ gint guiResponse = -1;
+
+ gchar *msg = g_strdup_printf (_("Error while transferring “%s”\n\n%s"),
+ g_file_peek_path(xferData->problemSrcGFile),
+ xferData->error->message);
+
+ if(!g_error_matches(xferData->error, G_IO_ERROR, G_IO_ERROR_EXISTS))
+ {
+ run_simple_error_dialog(msg, xferData);
+ }
+ else
+ {
+ if (xferData->currentFileType == G_FILE_TYPE_DIRECTORY)
+ {
+ gdk_threads_enter ();
+ g_list_length(xferData->srcGFileList) > 1
+ ? guiResponse = run_simple_dialog (
+ *main_win, TRUE, GTK_MESSAGE_ERROR, msg, _("Move problem"),
+ -1, _("Abort"), _("Retry"), _("Copy into"), _("Rename"), _("Rename all"), _("Skip"), _("Skip
all"), NULL)
+ : guiResponse = run_simple_dialog (
+ *main_win, TRUE, GTK_MESSAGE_ERROR, msg, _("Move problem"),
+ -1, _("Abort"), _("Retry"), _("Copy into"), _("Rename"), NULL);
+ gdk_threads_leave ();
+ switch (guiResponse)
+ {
+ case 0:
+ xferData->problem_action = COPY_ERROR_ACTION_ABORT;
+ break;
+ case 1:
+ xferData->problem_action = COPY_ERROR_ACTION_RETRY;
+ break;
+ case 2:
+ xferData->problem_action = COPY_ERROR_ACTION_COPY_INTO;
+ break;
+ case 3:
+ xferData->problem_action = COPY_ERROR_ACTION_RENAME;
+ break;
+ case 4:
+ xferData->problem_action = COPY_ERROR_ACTION_RENAME_ALL;
+ break;
+ case 5:
+ xferData->problem_action = COPY_ERROR_ACTION_SKIP;
+ break;
+ case 6:
+ xferData->problem_action = COPY_ERROR_ACTION_SKIP_ALL;
+ break;
+ default:
+ xferData->problem_action = COPY_ERROR_ACTION_RETRY;
+ break;
+ }
+ }
+ if (xferData->currentFileType == G_FILE_TYPE_REGULAR)
+ {
+ auto problemSrcBasename = get_gfile_attribute_string(xferData->problemSrcGFile,
+ G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME);
+ auto problemDestBasename = get_gfile_attribute_string(xferData->problemDestGFile,
+ G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME);
+ auto sourceDetails = get_file_details_string (xferData->problemSrcGFile);
+ auto targetDetails = get_file_details_string (xferData->problemDestGFile);
+ g_free(msg);
+ msg = g_strdup_printf (_("Overwrite file:\n\n<b>%s</b>\n<span color='dimgray'
size='smaller'>%s</span>\n\nWith:\n\n<b>%s</b>\n<span color='dimgray' size='smaller'>%s</span>"),
+ problemDestBasename,
+ targetDetails,
+ problemSrcBasename,
+ sourceDetails);
+ g_free (problemSrcBasename);
+ g_free (problemDestBasename);
+ g_free (sourceDetails);
+ g_free (targetDetails);
+ gdk_threads_enter ();
+ xferData->filesTotal > 1
+ ? guiResponse = run_simple_dialog (
+ *main_win, TRUE, GTK_MESSAGE_ERROR, msg, _("Copy problem"),
+ -1, _("Abort"), _("Retry"), _("Replace"), _("Rename"), _("Skip"), _("Replace all"),
_("Rename all"), _("Skip all"), NULL)
+ : guiResponse = run_simple_dialog (
+ *main_win, TRUE, GTK_MESSAGE_ERROR, msg, _("Copy problem"),
+ -1, _("Abort"), _("Retry"), _("Replace"), _("Rename"), NULL);
+ gdk_threads_leave ();
+ switch (guiResponse)
+ {
+ case 0:
+ xferData->problem_action = COPY_ERROR_ACTION_ABORT;
+ break;
+ case 1:
+ xferData->problem_action = COPY_ERROR_ACTION_RETRY;
+ break;
+ case 2:
+ xferData->problem_action = COPY_ERROR_ACTION_REPLACE;
+ break;
+ case 3:
+ xferData->problem_action = COPY_ERROR_ACTION_RENAME;
+ break;
+ case 4:
+ xferData->problem_action = COPY_ERROR_ACTION_SKIP;
+ break;
+ case 5:
+ xferData->problem_action = COPY_ERROR_ACTION_REPLACE_ALL;
+ break;
+ case 6:
+ xferData->problem_action = COPY_ERROR_ACTION_RENAME_ALL;
+ break;
+ case 7:
+ xferData->problem_action = COPY_ERROR_ACTION_SKIP_ALL;
+ break;
+ default:
+ xferData->problem_action = COPY_ERROR_ACTION_RETRY;
+ break;
+ }
+ }
+ }
+ g_free (msg);
+}
+
+static gboolean update_transfer_gui (XferData *xferData)
+{
+ g_mutex_lock (&xferData->mutex);
+
+ if (xferData->problem && xferData->error)
+ {
+ switch (xferData->transferType)
+ {
+ case COPY:
+ update_transfer_gui_error_copy(xferData);
+ break;
+ case MOVE:
+ update_transfer_gui_error_move(xferData);
+ break;
+ case LINK:
+ break;
+ }
+
+ xferData->problem = FALSE;
+ }
+
+ if (xferData->win && xferData->win->cancel_pressed)
+ {
+ xferData->aborted = TRUE;
+
+ if (xferData->on_completed_func)
+ xferData->on_completed_func (xferData->on_completed_data, nullptr);
+
+ gtk_widget_destroy (GTK_WIDGET (xferData->win));
+ free_xfer_data (xferData);
+ return FALSE;
+ }
+
+ if (xferData->done)
+ {
+ // Only update the files if needed
+ if (xferData->destGnomeCmdDir)
+ {
+ gnome_cmd_dir_relist_files (xferData->destGnomeCmdDir, FALSE);
+ main_win->focus_file_lists();
+ gnome_cmd_dir_unref (xferData->destGnomeCmdDir);
+ xferData->destGnomeCmdDir = nullptr;
+ }
+
+ if (xferData->win)
+ {
+ gtk_widget_destroy (GTK_WIDGET (xferData->win));
+ xferData->win = nullptr;
+ }
+
+ // ToDo: If more than one file should be transferred and one file could not be
+ // transferred successsfully, we have to check for this error here
+ if (xferData->problem_action == COPY_ERROR_ACTION_NO_ACTION_YET
+ && xferData->on_completed_func)
+ {
+ xferData->on_completed_func (xferData->on_completed_data, nullptr);
+ }
+
+ free_xfer_data (xferData);
+
+ return FALSE;
+ }
+
+ if (xferData->bytesTotalTransferred == 0)
+ gnome_cmd_xfer_progress_win_set_action (xferData->win, _("copying…"));
+
+ if (xferData->curFileNumber)
+ {
+ gchar *msg = g_strdup_printf (_("[file %ld of %ld] “%s”"), xferData->curFileNumber,
+ xferData->filesTotal, xferData->curSrcFileName);
+
+ gnome_cmd_xfer_progress_win_set_msg (xferData->win, msg);
+
+ g_free (msg);
+ }
+
+ if (xferData->bytesTotal > 0)
+ {
+ gfloat totalProgress =
+ (gfloat)((gdouble)(xferData->bytesTotalTransferred + xferData->bytesCopiedFile)
+ / (gdouble)xferData->bytesTotal);
+
+ if ((totalProgress >= 0.0 && totalProgress <= 1.0) || xferData->first_time)
+ {
+ xferData->first_time = FALSE;
+ gnome_cmd_xfer_progress_win_set_total_progress (xferData->win, xferData->bytesCopiedFile,
+ xferData->fileSize,
+ xferData->bytesTotalTransferred +
xferData->bytesCopiedFile,
+ xferData->bytesTotal);
+ while (gtk_events_pending ())
+ gtk_main_iteration_do (FALSE);
+ }
+ }
+ g_mutex_unlock (&xferData->mutex);
+ return TRUE;
+}
-static gboolean update_xfer_gui (XferData *xferData)
+static gboolean update_tmp_download_gui (XferData *xferData)
{
g_mutex_lock (&xferData->mutex);
if (xferData->problem && xferData->error)
{
gchar *msg = g_strdup_printf (_("Error while transferring “%s”\n\n%s"),
- xferData->problem_file_name,
+ g_file_peek_path(xferData->problemSrcGFile),
xferData->error->message);
- xferData->problem_action = run_simple_dialog (
- *main_win, TRUE, GTK_MESSAGE_ERROR, msg, _("Transfer problem"),
- -1, _("Abort"), _("Retry"), _("Skip"), NULL);
+ run_simple_error_dialog(msg, xferData);
g_free (msg);
@@ -170,12 +494,12 @@ static gboolean update_xfer_gui (XferData *xferData)
if (xferData->done)
{
// Only update the files if needed
- if (xferData->to_dir)
+ if (xferData->destGnomeCmdDir)
{
- gnome_cmd_dir_relist_files (xferData->to_dir, FALSE);
+ gnome_cmd_dir_relist_files (xferData->destGnomeCmdDir, FALSE);
main_win->focus_file_lists();
- gnome_cmd_dir_unref (xferData->to_dir);
- xferData->to_dir = nullptr;
+ gnome_cmd_dir_unref (xferData->destGnomeCmdDir);
+ xferData->destGnomeCmdDir = nullptr;
}
if (xferData->win)
@@ -184,9 +508,7 @@ static gboolean update_xfer_gui (XferData *xferData)
xferData->win = nullptr;
}
- // ToDo: If more than one file should be transfered and one file could not be
- // transfered successsfully, we have to check for this error here
- if (xferData->problem_action == XFER_ERROR_ACTION_DEFAULT
+ if (xferData->problem_action == COPY_ERROR_ACTION_NO_ACTION_YET
&& xferData->on_completed_func)
{
xferData->on_completed_func (xferData->on_completed_data, nullptr);
@@ -197,43 +519,6 @@ static gboolean update_xfer_gui (XferData *xferData)
return FALSE;
}
-// if (xferData->cur_phase == GNOME_VFS_XFER_PHASE_COPYING)
-// {
-// if (xferData->prev_phase != GNOME_VFS_XFER_PHASE_COPYING)
-// {
- gnome_cmd_xfer_progress_win_set_action (xferData->win, _("copying…"));
-// xferData->prev_file = -1;
-// }
-//
-// if (xferData->prev_file != xferData->cur_file)
-// {
-// gchar *t = str_uri_basename (xferData->cur_file_name);
-// gchar *fn = get_utf8 (t);
-// gchar *msg = g_strdup_printf (_("[file %ld of %ld] “%s”"), xferData->cur_file,
xferData->files_total, fn);
-//
-// gnome_cmd_xfer_progress_win_set_msg (xferData->win, msg);
-//
-// xferData->prev_file = xferData->cur_file;
-//
-// g_free (msg);
-// g_free (fn);
-// g_free (t);
-// }
-//
-// if (xferData->bytes_total > 0)
-// {
-// gfloat total_prog = (gfloat)((gdouble)xferData->total_bytes_copied /
(gdouble)xferData->bytes_total);
-// gfloat total_diff = total_prog - xferData->prev_totalprog;
-//
-// if ((total_diff > (gfloat)0.01 && total_prog >= 0.0 && total_prog <= 1.0) ||
xferData->first_time)
-// {
-// xferData->first_time = FALSE;
-// gnome_cmd_xfer_progress_win_set_total_progress (xferData->win, xferData->bytes_copied,
xferData->file_size, xferData->total_bytes_copied, xferData->bytes_total);
-// while (gtk_events_pending ())
-// gtk_main_iteration_do (FALSE);
-// }
-// }
-// }
g_mutex_unlock (&xferData->mutex);
return TRUE;
@@ -254,7 +539,7 @@ inline gboolean gfile_is_parent_to_dir_or_equal (GFile *gFile, GnomeCmdDir *dir)
}
-inline gchar *remove_basename (gchar *in)
+inline gchar *remove_basename (const gchar *in)
{
gchar *out = g_strdup (in);
@@ -269,56 +554,291 @@ inline gchar *remove_basename (gchar *in)
}
-inline gboolean file_is_already_in_dir (GnomeVFSURI *uri, GnomeCmdDir *dir)
+inline gboolean file_is_already_in_dir (GFile *gFile, GnomeCmdDir *dir)
{
- gchar *tmp = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_PASSWORD);
- gchar *uri_str = remove_basename (tmp);
+ gchar *uri_str = remove_basename (g_file_get_uri(gFile));
+
+ if (!uri_str)
+ return false;
+
gchar *dir_uri_str = GNOME_CMD_FILE (dir)->get_uri_str();
gboolean ret = (strcmp (uri_str, dir_uri_str) == 0);
g_free (uri_str);
g_free (dir_uri_str);
- g_free (tmp);
return ret;
}
+static void
+set_files_total(XferData *xferData)
+{
+ for(auto gFileSrcListItem = xferData->srcGFileList; gFileSrcListItem; gFileSrcListItem =
gFileSrcListItem->next)
+ {
+ guint64 diskUsage = 0;
+ guint64 numFiles = 0;
+ auto gFile = (GFile *) gFileSrcListItem->data;
+ g_return_if_fail(G_IS_FILE(gFile));
+
+ g_file_measure_disk_usage (gFile,
+ G_FILE_MEASURE_NONE,
+ nullptr, nullptr, nullptr,
+ &diskUsage,
+ nullptr,
+ &numFiles,
+ nullptr);
+ xferData->bytesTotal = diskUsage;
+ xferData->filesTotal += numFiles;
+ }
+}
+
void
-gnome_cmd_xfer_gfiles_start (GList *srcGFileGList,
- GnomeCmdDir *to_dir,
- GnomeCmdFileList *src_fl,
- GList *src_files,
- gchar *dest_fn,
- GnomeVFSXferOptions xferOptions,
- GnomeVFSXferOverwriteMode xferOverwriteMode,
- GtkSignalFunc on_completed_func,
- gpointer on_completed_data)
+gnome_cmd_copy_gfiles_start (GList *srcGFileGList,
+ GnomeCmdDir *destGnomeCmdDir,
+ GnomeCmdFileList *srcGnomeCmdFileList,
+ GList *srcFilesGList,
+ gchar *destFileName,
+ GFileCopyFlags copyFlags,
+ gboolean skipAsk,
+ GtkSignalFunc on_completed_func,
+ gpointer on_completed_data)
{
- g_return_if_fail (src_uri_list != nullptr);
- g_return_if_fail (GNOME_CMD_IS_DIR (to_dir));
+ g_return_if_fail (srcGFileGList != nullptr);
+ g_return_if_fail (GNOME_CMD_IS_DIR (destGnomeCmdDir));
- GnomeVFSURI *src_uri, *dest_uri;
+ GFile *srcGFile, *destGFile;
// Sanity check
- for (GList *i = src_uri_list; i; i = i->next)
+ for (GList *i = srcGFileGList; i; i = i->next)
{
- src_uri = (GnomeVFSURI *) i->data;
- if (uri_is_parent_to_dir_or_equal (src_uri, to_dir))
+ srcGFile = (GFile *) i->data;
+ if (gfile_is_parent_to_dir_or_equal (srcGFile, destGnomeCmdDir))
{
gnome_cmd_show_message (*main_win, _("Copying a directory into itself is a bad idea."), _("The
whole operation was cancelled."));
return;
}
- if (file_is_already_in_dir (src_uri, to_dir))
- if (dest_fn && strcmp (dest_fn, gnome_vfs_uri_extract_short_name (src_uri)) == 0)
+ if (file_is_already_in_dir (srcGFile, destGnomeCmdDir))
+ {
+ auto srcFilename = g_file_get_basename(srcGFile);
+ if (destFileName && strcmp (destFileName, srcFilename) == 0)
{
+ g_free(srcFilename);
DEBUG ('x', "Copying a file to the same directory as it's already in, is not permitted\n");
return;
}
+ g_free(srcFilename);
+ }
+ }
+
+ XferData *xferData = create_xfer_data (copyFlags, srcGFileGList, nullptr,
+ destGnomeCmdDir, srcGnomeCmdFileList, srcFilesGList,
+ (GFunc) on_completed_func, on_completed_data);
+ xferData->transferType = COPY;
+
+ if (g_list_length (srcGFileGList) == 1 && destFileName != nullptr)
+ {
+ destGFile = gnome_cmd_dir_get_child_gfile (destGnomeCmdDir, destFileName);
+
+ xferData->destGFileList = g_list_append (xferData->destGFileList, destGFile);
+ }
+ else
+ {
+ for (auto srcGFileGListItem = srcGFileGList; srcGFileGListItem; srcGFileGListItem =
srcGFileGListItem->next)
+ {
+ srcGFile = (GFile *) srcGFileGListItem->data;
+ auto basename = g_file_get_basename(srcGFile);
+
+ destGFile = gnome_cmd_dir_get_child_gfile (destGnomeCmdDir, basename);
+ g_free (basename);
+
+ xferData->destGFileList = g_list_append (xferData->destGFileList, destGFile);
+ }
+ }
+
+ g_free (destFileName);
+
+ set_files_total(xferData);
+
+ xferData->win = GNOME_CMD_XFER_PROGRESS_WIN (gnome_cmd_xfer_progress_win_new (xferData->filesTotal));
+ gtk_widget_ref (GTK_WIDGET (xferData->win));
+ gtk_window_set_title (GTK_WINDOW (xferData->win), _("preparing…"));
+ gtk_widget_show (GTK_WIDGET (xferData->win));
+
+ g_mutex_init(&xferData->mutex);
+
+ // start the transfer
+ xferData->thread = g_thread_new (NULL, (GThreadFunc) gnome_cmd_transfer_gfiles, xferData);
+ g_timeout_add (gnome_cmd_data.gui_update_rate, (GSourceFunc) update_transfer_gui, xferData);
+ g_mutex_clear(&xferData->mutex);
+}
+
+void
+gnome_cmd_move_gfiles_start (GList *srcGFileGList,
+ GnomeCmdDir *destGnomeCmdDir,
+ GnomeCmdFileList *srcGnomeCmdFileList,
+ GList *srcGnomeCmdFileGList,
+ gchar *destFileName,
+ GFileCopyFlags copyFlags,
+ gboolean skipAsk,
+ GtkSignalFunc on_completed_func,
+ gpointer on_completed_data)
+{
+ g_return_if_fail (srcGFileGList != nullptr);
+ g_return_if_fail (GNOME_CMD_IS_DIR (destGnomeCmdDir));
+
+ GFile *srcGFile, *destGFile;
+
+ // Sanity check
+ for (GList *i = srcGFileGList; i; i = i->next)
+ {
+ srcGFile = (GFile *) i->data;
+ if (gfile_is_parent_to_dir_or_equal (srcGFile, destGnomeCmdDir))
+ {
+ gnome_cmd_show_message (*main_win, _("Moving a directory into itself is a bad idea."), _("The
whole operation was cancelled."));
+ return;
+ }
+ if (file_is_already_in_dir (srcGFile, destGnomeCmdDir))
+ {
+ auto srcFilename = g_file_get_basename(srcGFile);
+ if (destFileName && strcmp (destFileName, srcFilename) == 0)
+ {
+ g_free(srcFilename);
+ DEBUG ('x', "Moving a file to the same directory as it's already in, is not permitted\n");
+ return;
+ }
+ g_free(srcFilename);
+ }
+ }
+
+ XferData *xferData = create_xfer_data (copyFlags, srcGFileGList, nullptr,
+ destGnomeCmdDir, srcGnomeCmdFileList, srcGnomeCmdFileGList,
+ (GFunc) on_completed_func, on_completed_data);
+ xferData->transferType = MOVE;
+
+ if (g_list_length (srcGFileGList) == 1 && destFileName != nullptr)
+ {
+ destGFile = gnome_cmd_dir_get_child_gfile (destGnomeCmdDir, destFileName);
+
+ xferData->destGFileList = g_list_append (xferData->destGFileList, destGFile);
+ }
+ else
+ {
+ for (auto srcGFileGListItem = srcGFileGList; srcGFileGListItem; srcGFileGListItem =
srcGFileGListItem->next)
+ {
+ srcGFile = (GFile *) srcGFileGListItem->data;
+ auto basename = g_file_get_basename(srcGFile);
+
+ destGFile = gnome_cmd_dir_get_child_gfile (destGnomeCmdDir, basename);
+ g_free (basename);
+
+ xferData->destGFileList = g_list_append (xferData->destGFileList, destGFile);
+ }
+ }
+
+ g_free (destFileName);
+
+ set_files_total(xferData);
+
+ xferData->win = GNOME_CMD_XFER_PROGRESS_WIN (gnome_cmd_xfer_progress_win_new (xferData->filesTotal));
+ gtk_widget_ref (GTK_WIDGET (xferData->win));
+ gtk_window_set_title (GTK_WINDOW (xferData->win), _("preparing…"));
+ gtk_widget_show (GTK_WIDGET (xferData->win));
+
+ g_mutex_init(&xferData->mutex);
+
+ // start the transfer
+ xferData->thread = g_thread_new (NULL, (GThreadFunc) gnome_cmd_transfer_gfiles, xferData);
+ g_timeout_add (gnome_cmd_data.gui_update_rate, (GSourceFunc) update_transfer_gui, xferData);
+ g_mutex_clear(&xferData->mutex);
+}
+
+
+void
+gnome_cmd_link_gfiles_start (GList *srcGFileGList,
+ GnomeCmdDir *destGnomeCmdDir,
+ GnomeCmdFileList *srcGnomeCmdFileList,
+ GList *srcGnomeCmdFileGList,
+ gchar *destFileName,
+ GFileCopyFlags copyFlags,
+ gboolean skipAsk,
+ GtkSignalFunc on_completed_func,
+ gpointer on_completed_data)
+{
+ g_return_if_fail (srcGFileGList != nullptr);
+ g_return_if_fail (GNOME_CMD_IS_DIR (destGnomeCmdDir));
+
+ GFile *srcGFile, *destGFile;
+
+ // Sanity check
+ for (GList *i = srcGFileGList; i; i = i->next)
+ {
+ srcGFile = (GFile *) i->data;
+ if (gfile_is_parent_to_dir_or_equal (srcGFile, destGnomeCmdDir))
+ {
+ gnome_cmd_show_message (*main_win, _("Moving a directory into itself is a bad idea."), _("The
whole operation was cancelled."));
+ return;
+ }
+ if (file_is_already_in_dir (srcGFile, destGnomeCmdDir))
+ {
+ auto srcFilename = g_file_get_basename(srcGFile);
+ if (destFileName && strcmp (destFileName, srcFilename) == 0)
+ {
+ g_free(srcFilename);
+ DEBUG ('x', "Moving a file to the same directory as it's already in, is not permitted\n");
+ return;
+ }
+ g_free(srcFilename);
+ }
}
+
+ XferData *xferData = create_xfer_data (copyFlags, srcGFileGList, nullptr,
+ destGnomeCmdDir, srcGnomeCmdFileList, srcGnomeCmdFileGList,
+ (GFunc) on_completed_func, on_completed_data);
+ xferData->transferType = LINK;
+
+ if (g_list_length (srcGFileGList) == 1 && destFileName != nullptr)
+ {
+ destGFile = gnome_cmd_dir_get_child_gfile (destGnomeCmdDir, destFileName);
+
+ xferData->destGFileList = g_list_append (xferData->destGFileList, destGFile);
+ }
+ else
+ {
+ for (auto srcGFileGListItem = srcGFileGList; srcGFileGListItem; srcGFileGListItem =
srcGFileGListItem->next)
+ {
+ srcGFile = (GFile *) srcGFileGListItem->data;
+ auto basename = g_file_get_basename(srcGFile);
+
+ destGFile = gnome_cmd_dir_get_child_gfile (destGnomeCmdDir, basename);
+ g_free (basename);
+
+ xferData->destGFileList = g_list_append (xferData->destGFileList, destGFile);
+ }
+ }
+
+ g_free (destFileName);
+
+ set_files_total(xferData);
+
+ //xferData->win = GNOME_CMD_XFER_PROGRESS_WIN (gnome_cmd_xfer_progress_win_new (xferData->filesTotal));
+ //gtk_widget_ref (GTK_WIDGET (xferData->win));
+ //gtk_window_set_title (GTK_WINDOW (xferData->win), _("preparing…"));
+ //gtk_widget_show (GTK_WIDGET (xferData->win));
+
+ //g_mutex_init(&xferData->mutex);
+
+ // start the transfer
+ gnome_cmd_transfer_gfiles(xferData);
+ //xferData->thread = g_thread_new (NULL, (GThreadFunc) gnome_cmd_transfer_gfiles, xferData);
+ //g_timeout_add (gnome_cmd_data.gui_update_rate, (GSourceFunc) update_transfer_gui, xferData);
+ //g_mutex_clear(&xferData->mutex);
+}
+
+
void
-gnome_cmd_xfer_tmp_download (GFile *srcGFile,
+gnome_cmd_tmp_download (GFile *srcGFile,
GFile *destGFile,
GFileCopyFlags copyFlags,
GtkSignalFunc on_completed_func,
@@ -333,23 +853,23 @@ gnome_cmd_xfer_tmp_download (GFile *srcGFile,
auto xferData = create_xfer_data (copyFlags, srcGFileList, destGFileList,
nullptr, nullptr, nullptr,
(GFunc) on_completed_func, on_completed_data);
+ xferData->transferType = COPY;
g_mutex_init(&xferData->mutex);
- // ToDo: This must be extracted in an own method
xferData->win = GNOME_CMD_XFER_PROGRESS_WIN (gnome_cmd_xfer_progress_win_new (g_list_length
(xferData->srcGFileList)));
gtk_window_set_title (GTK_WINDOW (xferData->win), _("downloading to /tmp"));
- g_object_ref(xferData->win);
+ gtk_widget_ref (GTK_WIDGET (xferData->win));
gtk_widget_show (GTK_WIDGET (xferData->win));
- xferData->thread = g_thread_new (NULL, (GThreadFunc) gnome_cmd_xfer_tmp_download_multiple, xferData);
- g_timeout_add (gnome_cmd_data.gui_update_rate, (GSourceFunc) update_xfer_gui, xferData);
+ xferData->thread = g_thread_new (NULL, (GThreadFunc) gnome_cmd_transfer_gfiles, xferData);
+ g_timeout_add (gnome_cmd_data.gui_update_rate, (GSourceFunc) update_tmp_download_gui, xferData);
g_mutex_clear(&xferData->mutex);
}
void
-gnome_cmd_xfer_tmp_download_multiple (XferData *xferData)
+gnome_cmd_transfer_gfiles (XferData *xferData)
{
g_return_if_fail (xferData->srcGFileList != nullptr);
g_return_if_fail (xferData->destGFileList != nullptr);
@@ -357,35 +877,71 @@ gnome_cmd_xfer_tmp_download_multiple (XferData *xferData)
if (g_list_length(xferData->srcGFileList) != g_list_length(xferData->destGFileList))
return;
+ GError *error = nullptr;
+
auto gFileDestListItem = xferData->destGFileList;
- for (auto gFileSrcListItem = xferData->srcGFileList; gFileSrcListItem; gFileSrcListItem =
gFileSrcListItem->next)
+ for (auto gFileSrcListItem = xferData->srcGFileList; gFileSrcListItem; gFileSrcListItem =
gFileSrcListItem->next,
+ gFileDestListItem =
gFileDestListItem->next)
{
auto srcGFile = (GFile *) gFileSrcListItem->data;
auto destGFile = (GFile *) gFileDestListItem->data;
- gnome_cmd_xfer_tmp_download(srcGFile, destGFile, xferData->copyFlags, xferData);
-
- if (xferData->problem_action == XFER_ERROR_ACTION_ABORT)
- break;
-
- gFileDestListItem = xferData->destGFileList->next;
+ switch (xferData->transferType)
+ {
+ case COPY:
+ gnome_cmd_copy_gfile_recursive(srcGFile, destGFile, xferData->copyFlags, xferData);
+ break;
+ case MOVE:
+ gnome_cmd_move_gfile_recursive(srcGFile, destGFile, xferData->copyFlags, xferData);
+ break;
+ case LINK:
+ auto symlinkSrcPath = g_file_get_path(srcGFile);
+
+ g_file_make_symbolic_link (destGFile,
+ symlinkSrcPath,
+ nullptr,
+ &error);
+
+ g_free(symlinkSrcPath);
+
+ if (error)
+ {
+ gchar *msg = g_strdup_printf (_("Error while creating symlink “%s”\n\n%s"),
+ g_file_peek_path(destGFile),
+ error->message);
+
+ run_simple_dialog (
+ *main_win, TRUE, GTK_MESSAGE_ERROR, msg, _("Symlink creation problem"),
+ -1, _("Ignore"), NULL);
+ g_free(msg);
+ g_error_free(error);
+ error = nullptr;
+ }
+ break;
+ }
}
+ main_win->focus_file_lists();
xferData->done = TRUE;
}
+
static void
-update_copied_xfer_data (goffset current_num_bytes,
- goffset total_num_bytes,
+update_transferred_data (goffset currentNumBytes,
+ goffset totalNumBytes,
gpointer xferDataPointer)
{
auto xferData = (XferData *) xferDataPointer;
- xferData->total_bytes_copied = current_num_bytes;
- xferData->bytes_total = total_num_bytes;
+ xferData->bytesCopiedFile = currentNumBytes;
+ xferData->fileSize = totalNumBytes;
}
+/**
+ * This function forces the thread for copying files and folders to wait until
+ * the user clicked something on the popup gui which makes problem_action becomes != -1.
+ */
static void xfer_progress_update (XferData *xferData)
{
g_mutex_lock (&xferData->mutex);
@@ -398,7 +954,8 @@ static void xfer_progress_update (XferData *xferData)
while (xferData->problem_action == -1)
g_thread_yield ();
g_mutex_lock (&xferData->mutex);
- xferData->problem_file_name = nullptr;
+ g_object_unref(xferData->problemSrcGFile);
+ g_object_unref(xferData->problemDestGFile);
g_clear_error (&(xferData->error));
}
@@ -406,46 +963,415 @@ static void xfer_progress_update (XferData *xferData)
}
-void
-gnome_cmd_xfer_tmp_download (GFile *srcGFile,
- GFile *destGFile,
- GFileCopyFlags copyFlags,
- gpointer xferDataPointer)
+static void
+do_the_copy(GFile *srcGFile, GFile *destGFile, GFileCopyFlags copyFlags, gpointer xferDataPointer)
{
- GError *tmpError = nullptr;
+ g_return_if_fail(xferDataPointer != nullptr);
+ g_return_if_fail(srcGFile != nullptr);
+ g_return_if_fail(destGFile != nullptr);
- g_return_if_fail(G_IS_FILE(srcGFile));
- g_return_if_fail(G_IS_FILE(destGFile));
+ GError *tmpError = nullptr;
auto xferData = (XferData *) xferDataPointer;
- // Start the transfer
- if (!g_file_copy (srcGFile, destGFile, copyFlags, nullptr, update_copied_xfer_data, xferDataPointer,
&tmpError))
+ g_free(xferData->curSrcFileName);
+ xferData->curSrcFileName = get_gfile_attribute_string(srcGFile, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME);
+ if(!g_file_copy(srcGFile, destGFile, copyFlags, nullptr, update_transferred_data, xferDataPointer,
&tmpError))
{
- g_warning("g_file_copy: File could not be copied: %s\n", tmpError->message);
g_propagate_error(&(xferData->error), tmpError);
- xferData->problem_file_name = g_file_peek_path(srcGFile);
+ xferData->problemSrcGFile = g_file_dup(srcGFile);
+ xferData->problemDestGFile = g_file_dup(destGFile);
xfer_progress_update(xferData);
}
else
{
- // Set back to default value because transfering the file might work only after the first try
- xferData->problem_action = XFER_ERROR_ACTION_DEFAULT;
+ xferData->curFileNumber++;
+ xferData->bytesTotalTransferred += xferData->fileSize;
+ if (xferData->problem_action == COPY_ERROR_ACTION_RETRY)
+ xferData->problem_action = COPY_ERROR_ACTION_NO_ACTION_YET;
+ }
+}
+
+static GFile*
+get_new_dest_gfile(GFile *srcGFile, GFile *destGFile, const char *copyString, guint increment)
+{
+ auto destGFileParent = g_file_get_parent(destGFile);
+ auto srcBasename = g_file_get_basename(srcGFile);
+ auto newDestGFilePath = g_strdup_printf("%s%s%s (%s %d)",
+ g_file_peek_path(destGFileParent),
+ G_DIR_SEPARATOR_S,
+ srcBasename,
+ copyString,
+ increment);
+ auto newDestGFile = g_file_new_for_path(newDestGFilePath);
+ g_free(newDestGFilePath);
+ g_free(srcBasename);
+ g_object_unref(destGFileParent);
+
+ return newDestGFile;
+}
+
+static void
+set_new_nonexisting_dest_gfile(GFile *srcGFile, GFile **destGFile, XferData *xferData)
+{
+ // Translators: Translate 'Copy' as a noun here
+ auto copyString = C_("Filename suffix", "Copy");
+ guint increment = 1;
+
+ auto newDestGFile = get_new_dest_gfile(srcGFile, *destGFile, copyString, increment);
+
+ while (g_file_query_exists(newDestGFile, nullptr))
+ {
+ g_object_unref(newDestGFile);
+ increment++;
+ newDestGFile = get_new_dest_gfile(srcGFile, *destGFile, copyString, increment);
+ }
+
+ // If destGFile is an item of the user-provided list of items
+ // to be transferred, we have to update this list-item also
+ auto oldDestItem = g_list_find(xferData->destGFileList, *destGFile);
+ if (oldDestItem)
+ {
+ oldDestItem->data = newDestGFile;
+ }
+
+ g_object_unref(*destGFile);
+
+ *destGFile = newDestGFile;
+}
+
+/**
+ * This function moves directories and files from srcGFile to destGFile.
+ * ...
+ */
+gboolean
+gnome_cmd_move_gfile_recursive (GFile *srcGFile,
+ GFile *destGFile,
+ GFileCopyFlags copyFlags,
+ gpointer xferDataPointer)
+{
+ auto xferData = (XferData *) xferDataPointer;
+ if (xferData->error)
+ {
+ return false;
+ }
+
+ g_return_val_if_fail(G_IS_FILE(srcGFile), false);
+ g_return_val_if_fail(G_IS_FILE(destGFile), false);
+
+ GError *tmpError = nullptr;
+
+ g_free(xferData->curSrcFileName);
+ xferData->curSrcFileName = get_gfile_attribute_string(srcGFile, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME);
+ if(!g_file_move(srcGFile, destGFile, copyFlags, nullptr, update_transferred_data, xferDataPointer,
&tmpError))
+ {
+ if(g_file_query_file_type(srcGFile, G_FILE_QUERY_INFO_NONE, nullptr) == G_FILE_TYPE_DIRECTORY
+ && g_error_matches(tmpError, G_IO_ERROR, G_IO_ERROR_WOULD_RECURSE))
+ {
+ g_message("Folder could not be copied natively, trying a copy-delete...");
+ g_error_free(tmpError);
+ tmpError = nullptr;
+ if (gnome_cmd_copy_gfile_recursive(srcGFile, destGFile, xferData->copyFlags, xferData))
+ {
+ auto gFileInfo = g_file_query_info(srcGFile, "*", G_FILE_QUERY_INFO_NONE, nullptr,
&tmpError);
+ if (!gFileInfo || tmpError)
+ {
+ g_propagate_error(&(xferData->error), tmpError);
+ xferData->problemSrcGFile = g_file_dup(srcGFile);
+ xferData->problemDestGFile = g_file_dup(destGFile);
+ xfer_progress_update(xferData);
+ g_object_unref (gFileInfo);
+ //ToDo: Decide what to do here!
+ return false;
+ }
+
+ auto srcGFileParent = g_file_get_parent(srcGFile);
+ if (!srcGFileParent)
+ {
+ g_object_unref(gFileInfo);
+ return false;
+ }
+ auto gFileParentPath = g_file_get_path(srcGFileParent);
+ auto gnomeCmdDirParent = gnome_cmd_dir_new (get_home_con(), new
GnomeCmdPlainPath(gFileParentPath));
+ auto gnomeCmdDir = gnome_cmd_dir_new_from_gfileinfo(gFileInfo, gnomeCmdDirParent);
+
+ auto deleteData = g_new0 (DeleteData, 1);
+ deleteData->gnomeCmdFiles = g_list_append(nullptr, gnomeCmdDir);
+ do_delete (deleteData, false); // false -> do not show progress window
+
+ g_free(gFileParentPath);
+ g_object_unref(srcGFileParent);
+ }
+ }
+ else
+ {
+ g_propagate_error(&(xferData->error), tmpError);
+ xferData->problemSrcGFile = g_file_dup(srcGFile);
+ xferData->problemDestGFile = g_file_dup(destGFile);
+ xfer_progress_update(xferData);
+ }
+ }
+ else
+ {
+ xferData->curFileNumber++;
+ xferData->bytesTotalTransferred += xferData->fileSize;
+ if (xferData->problem_action == COPY_ERROR_ACTION_RETRY)
+ xferData->problem_action = COPY_ERROR_ACTION_NO_ACTION_YET;
}
- if(xferData->problem_action == XFER_ERROR_ACTION_RETRY)
+ return true;
+}
+
+/**
+ * This function recursively copies directories and files from srcGFile to destGFile.
+ * As the function can call itself multiple times, some logic is build into it to handle the
+ * case when the destination is already existing and the user decides up on that.
+ *
+ * The function does return when it copied a regular file or when something went wrong
+ * unexpectedly. It calls itself if a directory should be copied or if a rename should happen
+ * as the original destination exists already.
+ */
+gboolean
+gnome_cmd_copy_gfile_recursive (GFile *srcGFile,
+ GFile *destGFile,
+ GFileCopyFlags copyFlags,
+ gpointer xferDataPointer)
+{
+ auto xferData = (XferData *) xferDataPointer;
+ if (xferData->error)
{
- xferData->problem_action = XFER_ERROR_ACTION_DEFAULT;
- gnome_cmd_xfer_tmp_download(srcGFile, destGFile, copyFlags, xferData);
+ return false;
}
+
+ g_return_val_if_fail(G_IS_FILE(srcGFile), false);
+ g_return_val_if_fail(G_IS_FILE(destGFile), false);
+
+ GError *tmpError = nullptr;
+
+ switch (g_file_query_file_type(srcGFile, G_FILE_QUERY_INFO_NONE, nullptr))
+ {
+ case G_FILE_TYPE_DIRECTORY:
+ {
+ xferData->currentFileType = G_FILE_TYPE_DIRECTORY;
+ switch (xferData->problem_action)
+ {
+ case COPY_ERROR_ACTION_NO_ACTION_YET:
+ // Try to create the dest directory
+ if (!g_file_make_directory (destGFile, nullptr, &tmpError))
+ {
+ g_warning("g_file_make_directory error: %s\n", tmpError->message);
+ g_propagate_error(&(xferData->error), tmpError);
+ xferData->problemSrcGFile = g_file_dup(srcGFile);
+ xferData->problemDestGFile = g_file_dup(destGFile);
+ xfer_progress_update(xferData);
+ return gnome_cmd_copy_gfile_recursive(srcGFile, destGFile, copyFlags, xferData);
+ }
+ break;
+ case COPY_ERROR_ACTION_RENAME:
+ xferData->problem_action = COPY_ERROR_ACTION_NO_ACTION_YET;
+ set_new_nonexisting_dest_gfile(srcGFile, &destGFile, xferData);
+ if (!g_file_make_directory (destGFile, nullptr, &tmpError))
+ {
+ g_warning("g_file_make_directory error: %s\n", tmpError->message);
+ g_propagate_error(&(xferData->error), tmpError);
+ xferData->problemSrcGFile = g_file_dup(srcGFile);
+ xferData->problemDestGFile = g_file_dup(destGFile);
+ xfer_progress_update(xferData);
+ return false;
+ }
+ break;
+ case COPY_ERROR_ACTION_COPY_INTO:
+ xferData->problem_action = COPY_ERROR_ACTION_NO_ACTION_YET;
+ break;
+ case COPY_ERROR_ACTION_RENAME_ALL:
+ set_new_nonexisting_dest_gfile(srcGFile, &destGFile, xferData);
+ if (!g_file_make_directory (destGFile, nullptr, &tmpError))
+ {
+ g_warning("g_file_make_directory error: %s\n", tmpError->message);
+ g_propagate_error(&(xferData->error), tmpError);
+ xferData->problemSrcGFile = g_file_dup(srcGFile);
+ xferData->problemDestGFile = g_file_dup(destGFile);
+ xfer_progress_update(xferData);
+ return false;
+ }
+ break;
+ case COPY_ERROR_ACTION_SKIP:
+ xferData->problem_action = COPY_ERROR_ACTION_NO_ACTION_YET;
+ return true;
+ case COPY_ERROR_ACTION_SKIP_ALL:
+ return true;
+ case COPY_ERROR_ACTION_RETRY:
+ xferData->problem_action = COPY_ERROR_ACTION_NO_ACTION_YET;
+ return gnome_cmd_copy_gfile_recursive(srcGFile, destGFile, copyFlags, xferData);
+ case COPY_ERROR_ACTION_ABORT:
+ return false;
+ case COPY_ERROR_ACTION_REPLACE: // This is not handled for directories when copying
+ case COPY_ERROR_ACTION_REPLACE_ALL: // This is not handled for directories when copying
+ default:
+ return false;
+ }
+
+ auto enumerator = g_file_enumerate_children(srcGFile, "*", G_FILE_QUERY_INFO_NONE, NULL,
&tmpError);
+ if (tmpError)
+ {
+ g_warning("g_file_enumerate_children error: %s\n", tmpError->message);
+ g_propagate_error(&(xferData->error), tmpError);
+ xferData->problemSrcGFile = g_file_dup(srcGFile);
+ xferData->problemDestGFile = g_file_dup(destGFile);
+ xfer_progress_update(xferData);
+ return false;
+ }
+
+ // Loop through the items of the directory.
+ // Probably this can be extracted into an own function.
+ auto gFileInfoChildFile = g_file_enumerator_next_file(enumerator, nullptr, &tmpError);
+ while(gFileInfoChildFile != nullptr && !tmpError)
+ {
+ if(g_file_info_get_file_type(gFileInfoChildFile) == G_FILE_TYPE_DIRECTORY)
+ {
+ auto dirNameChildGFile = g_file_info_get_name(gFileInfoChildFile);
+ auto sourceChildGFile = g_file_get_child(g_file_enumerator_get_container(enumerator),
dirNameChildGFile);
+ auto targetPath = g_strdup_printf("%s%s%s", g_file_peek_path(destGFile),
G_DIR_SEPARATOR_S, dirNameChildGFile);
+ auto targetGFile = g_file_new_for_path(targetPath);
+
+ gnome_cmd_copy_gfile_recursive(sourceChildGFile, targetGFile, copyFlags, xferData);
+
+ g_object_unref(sourceChildGFile);
+ g_object_unref(targetGFile);
+ g_free(targetPath);
+ }
+ else if(g_file_info_get_file_type(gFileInfoChildFile) == G_FILE_TYPE_REGULAR)
+ {
+ xferData->currentFileType = G_FILE_TYPE_REGULAR;
+ auto fileNameChildGFile = g_file_info_get_name(gFileInfoChildFile);
+ auto srcChildGFile = g_file_get_child(g_file_enumerator_get_container(enumerator),
fileNameChildGFile);
+ auto targetPath = g_strdup_printf("%s%s%s", g_file_peek_path(destGFile),
G_DIR_SEPARATOR_S, fileNameChildGFile);
+ auto targetGFile = g_file_new_for_path(targetPath);
+
+ do_the_copy(srcChildGFile, targetGFile, copyFlags, xferDataPointer);
+ switch (xferData->problem_action)
+ {
+ case COPY_ERROR_ACTION_RETRY:
+ xferData->problem_action = COPY_ERROR_ACTION_NO_ACTION_YET;
+ return gnome_cmd_copy_gfile_recursive(srcChildGFile, targetGFile, copyFlags,
xferData);
+ case COPY_ERROR_ACTION_REPLACE:
+ xferData->problem_action = COPY_ERROR_ACTION_NO_ACTION_YET;
+ gnome_cmd_copy_gfile_recursive(srcChildGFile, targetGFile,
G_FILE_COPY_OVERWRITE, xferData);
+ break;
+ case COPY_ERROR_ACTION_RENAME:
+ xferData->problem_action = COPY_ERROR_ACTION_NO_ACTION_YET;
+ set_new_nonexisting_dest_gfile(srcChildGFile, &targetGFile, xferData);
+ gnome_cmd_copy_gfile_recursive(srcChildGFile, targetGFile, copyFlags, xferData);
+ break;
+ case COPY_ERROR_ACTION_SKIP:
+ xferData->problem_action = COPY_ERROR_ACTION_NO_ACTION_YET;
+ break;
+ case COPY_ERROR_ACTION_REPLACE_ALL:
+ gnome_cmd_copy_gfile_recursive(srcChildGFile, targetGFile,
G_FILE_COPY_OVERWRITE, xferData);
+ break;
+ case COPY_ERROR_ACTION_SKIP_ALL:
+ g_object_unref(srcChildGFile);
+ g_object_unref(targetGFile);
+ g_free(targetPath);
+ g_object_unref(gFileInfoChildFile);
+ g_file_enumerator_close (enumerator, nullptr, nullptr);
+ return true;
+ case COPY_ERROR_ACTION_RENAME_ALL:
+ set_new_nonexisting_dest_gfile(srcChildGFile, &targetGFile, xferData);
+ gnome_cmd_copy_gfile_recursive(srcChildGFile, targetGFile,
G_FILE_COPY_OVERWRITE, xferData);
+ break;
+ case COPY_ERROR_ACTION_ABORT:
+ case COPY_ERROR_ACTION_COPY_INTO:
+ g_object_unref(srcChildGFile);
+ g_object_unref(targetGFile);
+ g_free(targetPath);
+ g_object_unref(gFileInfoChildFile);
+ g_file_enumerator_close (enumerator, nullptr, nullptr);
+ return false;
+ case COPY_ERROR_ACTION_NO_ACTION_YET:
+ default:
+ break;
+ }
+ g_object_unref(srcChildGFile);
+ g_object_unref(targetGFile);
+ g_free(targetPath);
+ }
+ g_object_unref(gFileInfoChildFile);
+ gFileInfoChildFile = g_file_enumerator_next_file(enumerator, NULL, &tmpError);
+ }
+ if (tmpError)
+ {
+ printf("g_file_enumerator_next_file: %s\n", tmpError->message);
+ g_propagate_error(&(xferData->error), tmpError);
+ xfer_progress_update(xferData);
+ }
+
+ g_file_enumerator_close (enumerator, nullptr, nullptr);
+ break;
+ }
+ case G_FILE_TYPE_REGULAR:
+ {
+ xferData->currentFileType = G_FILE_TYPE_REGULAR;
+ do_the_copy(srcGFile, destGFile, copyFlags, xferDataPointer);
+ switch (xferData->problem_action)
+ {
+ case COPY_ERROR_ACTION_RETRY:
+ xferData->problem_action = COPY_ERROR_ACTION_NO_ACTION_YET;
+ return gnome_cmd_copy_gfile_recursive(srcGFile, destGFile, copyFlags, xferData);
+ case COPY_ERROR_ACTION_REPLACE:
+ xferData->problem_action = COPY_ERROR_ACTION_NO_ACTION_YET;
+ gnome_cmd_copy_gfile_recursive(srcGFile, destGFile, G_FILE_COPY_OVERWRITE, xferData);
+ break;
+ case COPY_ERROR_ACTION_RENAME:
+ xferData->problem_action = COPY_ERROR_ACTION_NO_ACTION_YET;
+ set_new_nonexisting_dest_gfile(srcGFile, &destGFile, xferData);
+ gnome_cmd_copy_gfile_recursive(srcGFile, destGFile, copyFlags, xferData);
+ break;
+ case COPY_ERROR_ACTION_SKIP:
+ xferData->problem_action = COPY_ERROR_ACTION_NO_ACTION_YET;
+ break;
+ case COPY_ERROR_ACTION_REPLACE_ALL:
+ gnome_cmd_copy_gfile_recursive(srcGFile, destGFile, G_FILE_COPY_OVERWRITE, xferData);
+ break;
+ case COPY_ERROR_ACTION_SKIP_ALL:
+ return true;
+ case COPY_ERROR_ACTION_RENAME_ALL:
+ set_new_nonexisting_dest_gfile(srcGFile, &destGFile, xferData);
+ gnome_cmd_copy_gfile_recursive(srcGFile, destGFile, copyFlags, xferData);
+ break;
+ case COPY_ERROR_ACTION_COPY_INTO: // This is not handled for files when copying
+ case COPY_ERROR_ACTION_ABORT:
+ return false;
+ case COPY_ERROR_ACTION_NO_ACTION_YET:
+ default:
+ break;
+ }
+ }
+
+ case G_FILE_TYPE_MOUNTABLE:
+ case G_FILE_TYPE_UNKNOWN:
+ case G_FILE_TYPE_SHORTCUT:
+ case G_FILE_TYPE_SPECIAL:
+ case G_FILE_TYPE_SYMBOLIC_LINK:
+ default:
+ break;
+ }
+
+ if(xferData->problem_action == COPY_ERROR_ACTION_RETRY)
+ {
+ xferData->problem_action = COPY_ERROR_ACTION_NO_ACTION_YET;
+ gnome_cmd_copy_gfile_recursive(srcGFile, destGFile, copyFlags, xferData);
+ }
+
+ return true;
}
void
-gnome_cmd_xfer_start (GList *srcGnomeCmdFileGList,
+gnome_cmd_copy_start (GList *srcGnomeCmdFileGList,
GnomeCmdDir *toGnomeCmdDir,
GnomeCmdFileList *srcGnomeCmdFileList,
gchar *destFileName,
- GnomeVFSXferOptions xferOptions,
- GnomeVFSXferOverwriteMode xferOverwriteMode,
+ GFileCopyFlags copyFlags,
+ gboolean skipAsk,
GtkSignalFunc on_completed_func,
gpointer on_completed_data)
{
@@ -454,13 +1380,39 @@ gnome_cmd_xfer_start (GList *srcGnomeCmdFileGList,
GList *srcGFileList = gnome_cmd_file_list_to_gfile_list (srcGnomeCmdFileGList);
- gnome_cmd_xfer_gfiles_start (srcGFileList,
+ gnome_cmd_copy_gfiles_start (srcGFileList,
toGnomeCmdDir,
srcGnomeCmdFileList,
srcGnomeCmdFileGList,
destFileName,
- xferOptions,
- xferOverwriteMode,
+ copyFlags,
+ skipAsk,
on_completed_func,
on_completed_data);
}
+
+void
+gnome_cmd_move_start (GList *srcGnomeCmdFileGList,
+ GnomeCmdDir *toGnomeCmdDir,
+ GnomeCmdFileList *srcGnomeCmdFileList,
+ gchar *destFileName,
+ GFileCopyFlags copyFlags,
+ gboolean skipAsk,
+ GtkSignalFunc on_completed_func,
+ gpointer on_completed_data)
+{
+ g_return_if_fail (srcGnomeCmdFileGList != nullptr);
+ g_return_if_fail (GNOME_CMD_IS_DIR (toGnomeCmdDir));
+
+ GList *srcGFileList = gnome_cmd_file_list_to_gfile_list (srcGnomeCmdFileGList);
+
+ gnome_cmd_move_gfiles_start (srcGFileList,
+ toGnomeCmdDir,
+ srcGnomeCmdFileList,
+ srcGnomeCmdFileGList,
+ destFileName,
+ copyFlags,
+ skipAsk,
+ on_completed_func,
+ on_completed_data);
+}
diff --git a/src/gnome-cmd-xfer.h b/src/gnome-cmd-xfer.h
index 5e60fa45..355048e7 100644
--- a/src/gnome-cmd-xfer.h
+++ b/src/gnome-cmd-xfer.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file gnome-cmd-xfer.h
* @copyright (C) 2001-2006 Marcus Bjurman\n
* @copyright (C) 2007-2012 Piotr Eljasiak\n
@@ -25,33 +25,54 @@
#include "gnome-cmd-file-list.h"
#include "gnome-cmd-xfer-progress-win.h"
+enum COPY_ERROR_ACTION
+{
+ COPY_ERROR_ACTION_NO_ACTION_YET = -1, // No error yet, so no action to take
+ COPY_ERROR_ACTION_ABORT,
+ COPY_ERROR_ACTION_RETRY,
+ COPY_ERROR_ACTION_COPY_INTO,
+ COPY_ERROR_ACTION_SKIP,
+ COPY_ERROR_ACTION_RENAME,
+ COPY_ERROR_ACTION_SKIP_ALL,
+ COPY_ERROR_ACTION_RENAME_ALL,
+ COPY_ERROR_ACTION_REPLACE,
+ COPY_ERROR_ACTION_REPLACE_ALL
+};
+
+enum TRANSFER_TYPE
+{
+ COPY,
+ MOVE,
+ LINK
+};
+
struct XferData
{
GFileCopyFlags copyFlags;
GnomeVFSXferOptions xferOptions;
GnomeVFSAsyncHandle *handle;
+ TRANSFER_TYPE transferType{COPY};
// Source and target GFile's. The first srcGFile should be transfered to the first destGFile and so on...
GList *srcGFileList;
GList *destGFileList;
- GnomeCmdDir *to_dir;
+ GnomeCmdDir *destGnomeCmdDir;
GnomeCmdFileList *src_fl;
GList *src_files;
// Used for showing the progress
GnomeCmdXferProgressWin *win;
- gulong cur_file;
- gulong prev_file;
- gulong files_total;
- gfloat prev_totalprog;
+ gulong curFileNumber;
+ gchar *curSrcFileName;
+ gulong filesTotal;
gboolean first_time;
gchar *cur_file_name;
- GnomeVFSFileSize file_size;
- GnomeVFSFileSize bytes_copied;
- GnomeVFSFileSize bytes_total;
- GnomeVFSFileSize total_bytes_copied;
+ guint64 fileSize;
+ guint64 bytesCopiedFile;
+ guint64 bytesTotal;
+ guint64 bytesTotalTransferred{0};
GFunc on_completed_func;
gpointer on_completed_data;
@@ -60,47 +81,86 @@ struct XferData
gboolean aborted;
gboolean problem{FALSE}; // signals to the main thread that the work thread is waiting
for an answer on what to do
- gint problem_action{-1}; // where the answer is delivered
- const gchar *problem_file_name{nullptr}; // the filename of the file that can't be deleted
+ COPY_ERROR_ACTION problem_action; // action to take when an error occurs
+ GFile *problemSrcGFile;
+ GFile *problemDestGFile;
GThread *thread{nullptr}; // the work thread
GMutex mutex{nullptr}; // used to sync the main and worker thread
GError *error{nullptr}; // the cause that the file cant be deleted
+ GType currentFileType; // the file type of the file which is currently copied
};
void
-gnome_cmd_xfer_start (GList *src_files,
+gnome_cmd_copy_start (GList *src_files,
GnomeCmdDir *to,
GnomeCmdFileList *src_fl,
gchar *dest_fn,
- GnomeVFSXferOptions xferOptions,
- GnomeVFSXferOverwriteMode xferOverwriteMode,
+ GFileCopyFlags copyFlags,
+ gboolean skipAsk,
GtkSignalFunc on_completed_func,
gpointer on_completed_data);
+void
+gnome_cmd_move_start (GList *src_files,
+ GnomeCmdDir *to,
+ GnomeCmdFileList *src_fl,
+ gchar *dest_fn,
+ GFileCopyFlags copyFlags,
+ gboolean skipAsk,
+ GtkSignalFunc on_completed_func,
+ gpointer on_completed_data);
+
+void
+gnome_cmd_copy_gfiles_start (GList *src_uri_list,
+ GnomeCmdDir *to,
+ GnomeCmdFileList *src_fl,
+ GList *src_files,
+ gchar *dest_fn,
+ GFileCopyFlags copyFlags,
+ gboolean skipAsk,
+ GtkSignalFunc on_completed_func,
+ gpointer on_completed_data);
+
+void
+gnome_cmd_move_gfiles_start (GList *src_uri_list,
+ GnomeCmdDir *to,
+ GnomeCmdFileList *src_fl,
+ GList *src_files,
+ gchar *dest_fn,
+ GFileCopyFlags copyFlags,
+ gboolean skipAsk,
+ GtkSignalFunc on_completed_func,
+ gpointer on_completed_data);
void
-gnome_cmd_xfer_gfiles_start (GList *src_uri_list,
+gnome_cmd_link_gfiles_start (GList *src_uri_list,
GnomeCmdDir *to,
GnomeCmdFileList *src_fl,
GList *src_files,
gchar *dest_fn,
- GnomeVFSXferOptions xferOptions,
- GnomeVFSXferOverwriteMode xferOverwriteMode,
+ GFileCopyFlags copyFlags,
+ gboolean skipAsk,
GtkSignalFunc on_completed_func,
gpointer on_completed_data);
void
-gnome_cmd_xfer_tmp_download (GFile *srcGFile,
+gnome_cmd_tmp_download (GFile *srcGFile,
GFile *destGFile,
GFileCopyFlags copyFlags,
GtkSignalFunc on_completed_func,
gpointer on_completed_data);
void
-gnome_cmd_xfer_tmp_download_multiple (XferData *xferData);
-
-void
-gnome_cmd_xfer_tmp_download (GFile *srcGFile,
- GFile *destGFile,
- GFileCopyFlags copyFlags,
- gpointer on_completed_data);
+gnome_cmd_transfer_gfiles (XferData *xferData);
+
+gboolean
+gnome_cmd_copy_gfile_recursive (GFile *srcGFile,
+ GFile *destGFile,
+ GFileCopyFlags copyFlags,
+ gpointer on_completed_data);
+
+gboolean
+gnome_cmd_move_gfile_recursive (GFile *srcGFile,
+ GFile *destGFile,
+ GFileCopyFlags copyFlags,
+ gpointer on_completed_data);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]