diff --git a/shared/shell/src/fsop.c b/shared/shell/src/fsop.c index 0b62483..8a1437c 100644 --- a/shared/shell/src/fsop.c +++ b/shared/shell/src/fsop.c @@ -205,9 +205,22 @@ static void wintc_sh_fs_operation_constructed( { WinTCShFSOperation* fs_operation = WINTC_SH_FS_OPERATION(object); - // Check things are set + // There must always be files to work on // - if (!(fs_operation->list_files) || !(fs_operation->dest)) + if (!(fs_operation->list_files)) + { + fs_operation->operation_kind = WINTC_SH_FS_OPERATION_INVALID; + } + + // Copying/moving requires a destination + // + if ( + !(fs_operation->dest) && + ( + fs_operation->operation_kind == WINTC_SH_FS_OPERATION_COPY || + fs_operation->operation_kind == WINTC_SH_FS_OPERATION_MOVE + ) + ) { fs_operation->operation_kind = WINTC_SH_FS_OPERATION_INVALID; } @@ -234,7 +247,15 @@ static void wintc_sh_fs_operation_constructed( ) { fs_operation->operation_kind = WINTC_SH_FS_OPERATION_TRASH; + + g_clear_pointer( + &(fs_operation->dest), + (GDestroyNotify) g_free + ); } + + (G_OBJECT_CLASS(wintc_sh_fs_operation_parent_class)) + ->constructed(object); } static void wintc_sh_fs_operation_dispose( @@ -319,9 +340,15 @@ static void wintc_sh_fs_operation_set_property( case PROP_DESTINATION: fs_operation->dest = g_value_dup_string(value); - fs_operation->dest_file = get_g_file_for_target( - fs_operation->dest - ); + + if (fs_operation->dest) + { + fs_operation->dest_file = + get_g_file_for_target( + fs_operation->dest + ); + } + break; case PROP_OPERATION: @@ -418,8 +445,12 @@ static void wintc_sh_fs_operation_step( const gchar* src_path = (gchar*) fs_operation->iter_op->data; GFile* src_file = get_g_file_for_target(src_path); - g_object_ref(dest_file); + gboolean dest_file_is_temp = FALSE; + // If the target of a copy or move is a directory, then we must create a + // temporary GFile object to hold the destination file path within that + // directory + // if ( ( fs_operation->operation_kind == WINTC_SH_FS_OPERATION_COPY || @@ -431,7 +462,7 @@ static void wintc_sh_fs_operation_step( ) ) { - g_object_unref(dest_file); + dest_file_is_temp = TRUE; dest_file = get_g_file_for_copymove( @@ -493,7 +524,7 @@ static void wintc_sh_fs_operation_step( g_file_trash_async( src_file, G_PRIORITY_DEFAULT, - NULL, // FIXME: Cancellable, should use this! + fs_operation->cancellable, (GAsyncReadyCallback) cb_async_file_op, fs_operation ); @@ -505,7 +536,10 @@ static void wintc_sh_fs_operation_step( break; } - g_object_unref(dest_file); + if (dest_file_is_temp) + { + g_object_unref(dest_file); + } } static void wintc_sh_fs_operation_update_progress_text( diff --git a/shared/shell/src/res/menufslf.ui b/shared/shell/src/res/menufslf.ui index 4ca4546..9f4fdf0 100644 --- a/shared/shell/src/res/menufslf.ui +++ b/shared/shell/src/res/menufslf.ui @@ -34,8 +34,9 @@ Create Shortcut - control.no-op + control.view-op Delete + 9 control.no-op diff --git a/shared/shell/src/res/menufsvw.ui b/shared/shell/src/res/menufsvw.ui index b85fbbc..b99ba21 100644 --- a/shared/shell/src/res/menufsvw.ui +++ b/shared/shell/src/res/menufsvw.ui @@ -44,8 +44,9 @@ Create Shortcut - control.no-op + control.view-op Delete + 9 control.no-op diff --git a/shared/shell/src/vwfs.c b/shared/shell/src/vwfs.c index 45c62c7..49df9d4 100644 --- a/shared/shell/src/vwfs.c +++ b/shared/shell/src/vwfs.c @@ -9,6 +9,7 @@ #include #include "../public/fsclipbd.h" +#include "../public/fsop.h" #include "../public/vwfs.h" // @@ -127,6 +128,14 @@ static gboolean real_activate_item( GError** error ); +static gchar* wintc_sh_view_fs_build_path_for_view_item( + WinTCShViewFS* view_fs, + WinTCShextViewItem* item +); +static GList* wintc_sh_view_fs_convert_list_hashes( + WinTCShViewFS* view_fs, + GList* list_items +); static WinTCShextViewItem* wintc_sh_view_fs_get_view_item( WinTCShViewFS* view_fs, guint item_hash @@ -135,6 +144,12 @@ static void wintc_sh_view_fs_update_new_templates( WinTCShViewFS* view_fs ); +static gboolean shopr_delete( + WinTCIShextView* view, + WinTCShextOperation* operation, + GtkWindow* wnd, + GError** error +); static gboolean shopr_new( WinTCIShextView* view, WinTCShextOperation* operation, @@ -161,6 +176,10 @@ static void on_file_monitor_changed( GFileMonitorEvent event_type, gpointer user_data ); +static void on_fs_operation_done( + WinTCShFSOperation* self, + WINTC_UNUSED(gpointer user_data) +); // // GLIB OOP/CLASS INSTANCE DEFINITIONS @@ -756,12 +775,14 @@ static void wintc_sh_view_fs_refresh_items( } static WinTCShextOperation* wintc_sh_view_fs_spawn_operation( - WINTC_UNUSED(WinTCIShextView* view), - gint operation_id, - GList* targets, + WinTCIShextView* view, + gint operation_id, + GList* targets, WINTC_UNUSED(GError** error) ) { + WinTCShViewFS* view_fs = WINTC_SH_VIEW_FS(view); + // Spawn op // WinTCShextOperation* ret = g_new(WinTCShextOperation, 1); @@ -777,6 +798,14 @@ static WinTCShextOperation* wintc_sh_view_fs_spawn_operation( ret->func = shopr_paste; break; + case WINTC_SHEXT_KNOWN_OP_DELETE: + ret->func = shopr_delete; + ret->priv = wintc_sh_view_fs_convert_list_hashes( + view_fs, + g_steal_pointer(&targets) + ); + break; + default: // Could be a NEW operation... // @@ -911,14 +940,15 @@ static gboolean real_activate_item( // If the target is a dir or has a shell extension then set that as // the target path // - gchar* next_path = g_build_path( - G_DIR_SEPARATOR_S, - view_fs->path, - item->display_name, - NULL - ); + gchar* next_path; gchar* target_path = NULL; + next_path = + wintc_sh_view_fs_build_path_for_view_item( + view_fs, + item + ); + if (!(item->is_leaf)) { target_path = g_strdup_printf("file://%s", next_path); @@ -969,6 +999,42 @@ static gboolean real_activate_item( return success; } +static gchar* wintc_sh_view_fs_build_path_for_view_item( + WinTCShViewFS* view_fs, + WinTCShextViewItem* item +) +{ + return g_build_path( + G_DIR_SEPARATOR_S, + view_fs->path, + item->display_name, + NULL + ); +} + +static GList* wintc_sh_view_fs_convert_list_hashes( + WinTCShViewFS* view_fs, + GList* list_items +) +{ + for (GList* iter = list_items; iter; iter = iter->next) + { + WinTCShextViewItem* item = + wintc_sh_view_fs_get_view_item( + view_fs, + GPOINTER_TO_UINT(iter->data) + ); + + iter->data = + wintc_sh_view_fs_build_path_for_view_item( + view_fs, + item + ); + } + + return list_items; +} + static WinTCShextViewItem* wintc_sh_view_fs_get_view_item( WinTCShViewFS* view_fs, guint item_hash @@ -1123,6 +1189,32 @@ static void wintc_sh_view_fs_update_new_templates( // // CALLBACKS // +static gboolean shopr_delete( + WINTC_UNUSED(WinTCIShextView* view), + WinTCShextOperation* operation, + GtkWindow* wnd, + WINTC_UNUSED(GError** error) +) +{ + WinTCShFSOperation* op = + wintc_sh_fs_operation_new( + (GList*) operation->priv, + NULL, + WINTC_SH_FS_OPERATION_TRASH + ); + + g_signal_connect( + op, + "done", + G_CALLBACK(on_fs_operation_done), + operation->priv + ); + + wintc_sh_fs_operation_do(op, wnd); + + return TRUE; +} + static gboolean shopr_new( WinTCIShextView* view, WinTCShextOperation* operation, @@ -1423,3 +1515,12 @@ static void on_file_monitor_changed( g_list_free(data); g_free(file_path); } + +static void on_fs_operation_done( + WinTCShFSOperation* self, + gpointer user_data +) +{ + g_list_free_full((GList*) user_data, g_free); + g_object_unref(self); +}