Add wxMoveToTrash function

Implement it for Windows, macOS and GTK.

Closes #26256.
This commit is contained in:
Blake-Madden
2026-02-28 09:43:53 -05:00
committed by Vadim Zeitlin
parent d9018cdb44
commit 400780a33f
7 changed files with 116 additions and 0 deletions

View File

@@ -204,6 +204,9 @@ Currently the following symbols exist:
@itemdef{wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG, Defined if the <code>long
long</code> and <code>long</code> types are different. This can be useful
to decide whether some function should be overloaded for both types or not.}
@itemdef{wxHAS_MOVE_TO_TRASH, Defined if wxMoveToTrash() is supported on the
current platform. This is currently the case for MSW, macOS, and GTK.
This constant is available since wxWidgets 3.3.3}
@itemdef{wxHAS_MULTIPLE_FILEDLG_FILTERS, Defined if wxFileDialog supports multiple ('|'-separated) filters.}
@itemdef{wxHAS_NATIVE_ANIMATIONCTRL, Defined if native wxAnimationCtrl class is being used (this symbol only exists in wxWidgets 3.1.4 and later).}
@itemdef{wxHAS_NATIVE_DATAVIEWCTRL, Defined if native wxDataViewCtrl class is being used (this symbol only exists in wxWidgets 3.1.4 and later).}

View File

@@ -435,6 +435,13 @@ WXDLLIMPEXP_BASE bool wxCopyFile(const wxString& src, const wxString& dest,
// Remove file
WXDLLIMPEXP_BASE bool wxRemoveFile(const wxString& file);
// Move file or directory to trash/recycle bin
#if defined(__WINDOWS__) || defined(__WXDARWIN_OSX__) || defined(__WXGTK__)
#define wxHAS_MOVE_TO_TRASH
#endif
WXDLLIMPEXP_BASE bool wxMoveToTrash(const wxString& path);
// Rename file
WXDLLIMPEXP_BASE bool wxRenameFile(const wxString& oldpath, const wxString& newpath, bool overwrite = true);

View File

@@ -348,6 +348,32 @@ bool wxConcatFiles(const wxString& src1,
*/
bool wxRemoveFile(const wxString& file);
/**
Moves @a path to the system trash or recycle bin.
This works for both files and directories. The item is not permanently
deleted and can be restored by the user from the platform's trash
facility.
Preprocessor symbol @c wxHAS_MOVE_TO_TRASH is defined if this function is
supported on the current platform. If it is not defined, the function still
exists but always returns @false without doing anything else.
Implementation details:
- Under Windows, this uses @c SHFileOperation with @c FOF_ALLOWUNDO.
- Under macOS, this uses @c NSFileManager's @c trashItemAtURL method.
- Under Unix systems (including Linux and BSD), this uses @c g_file_trash.
@returns @true on success or @false if the operation failed in which case
an error message will have been logged using wxLogError() and the file
or directory at @a path is left in place.
@since 3.3.3
@header{wx/filefn.h}
*/
bool wxMoveToTrash(const wxString& path);
/**
File permission bit names.

View File

@@ -641,6 +641,15 @@ bool wxRemoveFile(const wxString& file)
return res == 0;
}
#ifndef wxHAS_MOVE_TO_TRASH
bool wxMoveToTrash(const wxString& WXUNUSED(path))
{
return false;
}
#endif // !wxHAS_MOVE_TO_TRASH
bool wxMkdir(const wxString& dir, int perm)
{
#if defined(__WXMAC__) && !defined(__UNIX__)

View File

@@ -26,6 +26,10 @@
#include "wx/gtk/private/wrapgdk.h"
#include "wx/gtk/private/backend.h"
#include "wx/gtk/private/error.h"
#include "wx/gtk/private/object.h"
#include <gio/gio.h>
#if wxDEBUG_LEVEL
#include "wx/gtk/assertdlg_gtk.h"
@@ -335,3 +339,18 @@ bool wxGUIAppTraits::ShowAssertDialog(const wxString& msg)
}
#endif // __UNIX__
bool wxMoveToTrash(const wxString& path)
{
wxGtkError err;
wxGtkObject<GFile> file(g_file_new_for_path(path.utf8_str()));
bool ok = g_file_trash(file, nullptr, err.Out());
if ( !ok )
{
wxLogError(_("'%s' couldn't be moved to trash: %s"),
path, err ? err.GetMessage() : _("unknown error"));
}
return ok;
}

View File

@@ -1715,6 +1715,35 @@ wxCreateHiddenWindow(LPCTSTR *pclassname, LPCTSTR classname, WNDPROC wndproc)
return hwnd;
}
bool wxMoveToTrash(const wxString& path)
{
// SHFileOperation needs double null termination string
// but without separator at the end of the path
wxString pathStr(path);
if ( pathStr.Last() == wxFILE_SEP_PATH )
pathStr.RemoveLast();
pathStr += wxT('\0');
SHFILEOPSTRUCT fileop;
wxZeroMemory(fileop);
fileop.wFunc = FO_DELETE;
fileop.pFrom = pathStr.t_str();
fileop.fFlags = FOF_ALLOWUNDO | FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI;
const int ret = SHFileOperation(&fileop);
if ( ret != 0 || fileop.fAnyOperationsAborted )
{
// Note that the return value from SHFileOperation() is not a standard
// Win32 error code, so we can't use wxLogSysError() here.
wxLogError(_("'%s' couldn't be moved to trash: error 0x%08x"),
path,
ret);
return false;
}
return true;
}
int wxCMPFUNC_CONV wxCmpNatural(const wxString& s1, const wxString& s2)
{
return StrCmpLogicalW(s1.wc_str(), s2.wc_str());

View File

@@ -388,4 +388,27 @@ bool wxMacInitCocoa()
return cocoaLoaded;
}
// Move file or directory to macOS Trash using NSFileManager.
bool wxMoveToTrash(const wxString& path)
{
wxCFStringRef cfPath(path);
NSURL *fileURL = [NSURL fileURLWithPath:cfPath.AsNSString()];
if ( fileURL == nil )
return false;
NSError *error = nil;
BOOL ok = [[NSFileManager defaultManager] trashItemAtURL:fileURL
resultingItemURL:nil
error:&error];
if ( !ok )
{
wxLogError(_("'%s' couldn't be moved to trash: %s"),
path,
error ? wxCFStringRef::AsString([error localizedDescription])
: _("unknown error"));
}
return ok;
}
#endif // __WXDARWIN_OSX__