From 9dbecc48ee6a9b1f01b7fb37a8ce369c68a2cf13 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Mon, 24 Sep 2007 13:53:43 +0000 Subject: [PATCH] Implemented SD2-1371: Use recycle bin to delete files. Fixed bug introduced in last revision that caused the unit tests to fail. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2690 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../LineManager/DefaultLineManager.cs | 2 +- .../Resources/LoadSaveOptionPanel.xfrm | 35 +++++++--- .../OptionPanels/IDEOptions/LoadSavePanel.cs | 5 +- .../Project/Src/Services/File/FileService.cs | 19 +++++- .../Base/Project/Src/Util/NativeMethods.cs | 68 +++++++++++++++++++ .../ProjectContent/DefaultProjectContent.cs | 2 +- .../ReflectionProjectContent.cs | 5 +- 7 files changed, 122 insertions(+), 14 deletions(-) diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/LineManager/DefaultLineManager.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/LineManager/DefaultLineManager.cs index e5d6681e2f..293f633422 100644 --- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/LineManager/DefaultLineManager.cs +++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/LineManager/DefaultLineManager.cs @@ -77,7 +77,7 @@ namespace ICSharpCode.TextEditor.Document public void Replace(int offset, int length, string text) { - Console.WriteLine("Replace offset="+offset+" length="+length+" text.Length="+text.Length); +// Console.WriteLine("Replace offset="+offset+" length="+length+" text.Length="+text.Length); int lineStart = GetLineNumberForOffset(offset); int oldNumberOfLines = this.TotalNumberOfLines; RemoveInternal(offset, length); diff --git a/src/Main/Base/Project/Resources/LoadSaveOptionPanel.xfrm b/src/Main/Base/Project/Resources/LoadSaveOptionPanel.xfrm index ee8d1b74aa..112d62b6e9 100644 --- a/src/Main/Base/Project/Resources/LoadSaveOptionPanel.xfrm +++ b/src/Main/Base/Project/Resources/LoadSaveOptionPanel.xfrm @@ -1,31 +1,50 @@ - + + + + + + + + + + + + + + + + + + + + - + - - + + - - + + @@ -42,8 +61,8 @@ - + @@ -76,4 +95,4 @@ - + \ No newline at end of file diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/IDEOptions/LoadSavePanel.cs b/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/IDEOptions/LoadSavePanel.cs index 4a787b5dbe..f9acc73726 100644 --- a/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/IDEOptions/LoadSavePanel.cs +++ b/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/IDEOptions/LoadSavePanel.cs @@ -27,7 +27,7 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels const string createBackupCopyCheckBox = "createBackupCopyCheckBox"; const string lineTerminatorStyleComboBox = "lineTerminatorStyleComboBox"; - CheckBox autoLoadExternalChangesCheckBox, detectExternalChangesCheckBox; + CheckBox autoLoadExternalChangesCheckBox, detectExternalChangesCheckBox, useRecycleBinCheckBox; public override void LoadPanelContents() { @@ -44,6 +44,7 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels autoLoadExternalChangesCheckBox = Get("autoLoadExternalChanges"); detectExternalChangesCheckBox = Get("detectExternalChanges"); + useRecycleBinCheckBox = Get("useRecycleBin"); detectExternalChangesCheckBox.CheckedChanged += delegate { autoLoadExternalChangesCheckBox.Enabled = detectExternalChangesCheckBox.Checked; @@ -52,6 +53,7 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels detectExternalChangesCheckBox.Checked = FileChangeWatcher.DetectExternalChangesOption; autoLoadExternalChangesCheckBox.Checked = FileChangeWatcher.AutoLoadExternalChangesOption; + useRecycleBinCheckBox.Checked = FileService.DeleteToRecycleBin; } public override bool StorePanelContents() @@ -62,6 +64,7 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels FileChangeWatcher.DetectExternalChangesOption = detectExternalChangesCheckBox.Checked; FileChangeWatcher.AutoLoadExternalChangesOption = autoLoadExternalChangesCheckBox.Checked; + FileService.DeleteToRecycleBin = useRecycleBinCheckBox.Checked; return true; } diff --git a/src/Main/Base/Project/Src/Services/File/FileService.cs b/src/Main/Base/Project/Src/Services/File/FileService.cs index 27aa3b0b95..b2391c9d83 100644 --- a/src/Main/Base/Project/Src/Services/File/FileService.cs +++ b/src/Main/Base/Project/Src/Services/File/FileService.cs @@ -294,6 +294,15 @@ namespace ICSharpCode.SharpDevelop return null; } + public static bool DeleteToRecycleBin { + get { + return PropertyService.Get("SharpDevelop.DeleteToRecycleBin", true); + } + set { + PropertyService.Set("SharpDevelop.DeleteToRecycleBin", value); + } + } + /// /// Removes a file, raising the appropriate events. This method may show message boxes. /// @@ -307,7 +316,10 @@ namespace ICSharpCode.SharpDevelop if (isDirectory) { try { if (Directory.Exists(fileName)) { - Directory.Delete(fileName, true); + if (DeleteToRecycleBin) + NativeMethods.DeleteToRecycleBin(fileName); + else + Directory.Delete(fileName, true); } } catch (Exception e) { MessageService.ShowError(e, "Can't remove directory " + fileName); @@ -316,7 +328,10 @@ namespace ICSharpCode.SharpDevelop } else { try { if (File.Exists(fileName)) { - File.Delete(fileName); + if (DeleteToRecycleBin) + NativeMethods.DeleteToRecycleBin(fileName); + else + File.Delete(fileName); } } catch (Exception e) { MessageService.ShowError(e, "Can't remove file " + fileName); diff --git a/src/Main/Base/Project/Src/Util/NativeMethods.cs b/src/Main/Base/Project/Src/Util/NativeMethods.cs index b206a108af..a8ffc0f759 100644 --- a/src/Main/Base/Project/Src/Util/NativeMethods.cs +++ b/src/Main/Base/Project/Src/Util/NativeMethods.cs @@ -6,6 +6,7 @@ // using System; +using System.IO; using System.Security; using System.Runtime.InteropServices; using System.Windows.Forms; @@ -41,5 +42,72 @@ namespace ICSharpCode.SharpDevelop { return GetKeyState((int)key) < 0; } + + #region SHFileOperation + enum FO_FUNC : uint + { + FO_MOVE = 0x0001, + FO_COPY = 0x0002, + FO_DELETE = 0x0003, + FO_RENAME = 0x0004, + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] + struct SHFILEOPSTRUCT + { + public IntPtr hwnd; + public FO_FUNC wFunc; + [MarshalAs(UnmanagedType.LPWStr)] + public string pFrom; + [MarshalAs(UnmanagedType.LPWStr)] + public string pTo; + public FILEOP_FLAGS fFlags; + public bool fAnyOperationsAborted; + public IntPtr hNameMappings; + [MarshalAs(UnmanagedType.LPWStr)] + public string lpszProgressTitle; + } + + [Flags] + private enum FILEOP_FLAGS : ushort + { + None = 0, + FOF_MULTIDESTFILES = 0x0001, + FOF_CONFIRMMOUSE = 0x0002, + FOF_SILENT = 0x0004, // don't create progress/report + FOF_RENAMEONCOLLISION = 0x0008, + FOF_NOCONFIRMATION = 0x0010, // Don't prompt the user. + FOF_WANTMAPPINGHANDLE = 0x0020, // Fill in SHFILEOPSTRUCT.hNameMappings + // Must be freed using SHFreeNameMappings + FOF_ALLOWUNDO = 0x0040, + FOF_FILESONLY = 0x0080, // on *.*, do only files + FOF_SIMPLEPROGRESS = 0x0100, // means don't show names of files + FOF_NOCONFIRMMKDIR = 0x0200, // don't confirm making any needed dirs + FOF_NOERRORUI = 0x0400, // don't put up error UI + FOF_NOCOPYSECURITYATTRIBS = 0x0800, // dont copy NT file Security Attributes + FOF_NORECURSION = 0x1000, // don't recurse into directories. + FOF_NO_CONNECTED_ELEMENTS = 0x2000, // don't operate on connected elements. + FOF_WANTNUKEWARNING = 0x4000, // during delete operation, warn if nuking instead of recycling (partially overrides FOF_NOCONFIRMATION) + FOF_NORECURSEREPARSE = 0x8000, // treat reparse points as objects, not containers + } + + [DllImport("shell32.dll", CharSet = CharSet.Unicode)] + static extern int SHFileOperation([In] ref SHFILEOPSTRUCT lpFileOp); + + public static void DeleteToRecycleBin(string fileName) + { + if (!File.Exists(fileName)) + throw new FileNotFoundException("File not found.", fileName); + SHFILEOPSTRUCT info = new SHFILEOPSTRUCT(); + info.hwnd = Gui.WorkbenchSingleton.MainForm.Handle; + info.wFunc = FO_FUNC.FO_DELETE; + info.fFlags = FILEOP_FLAGS.FOF_ALLOWUNDO | FILEOP_FLAGS.FOF_NOCONFIRMATION; + info.lpszProgressTitle = "Delete " + Path.GetFileName(fileName); + info.pFrom = fileName + "\0"; // pFrom is double-null-terminated + int result = SHFileOperation(ref info); + if (result != 0) + throw new IOException("Could not delete file " + fileName + ". Error " + result); + } + #endregion } } diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/DefaultProjectContent.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/DefaultProjectContent.cs index 79f79f64dc..2f2790dea8 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/DefaultProjectContent.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/DefaultProjectContent.cs @@ -512,7 +512,7 @@ namespace ICSharpCode.SharpDevelop.Dom } } - void RemoveClass(IClass @class) + protected void RemoveClass(IClass @class) { string fullyQualifiedName = @class.FullyQualifiedName; int typeParameterCount = @class.TypeParameters.Count; diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/ReflectionProjectContent.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/ReflectionProjectContent.cs index 1ccd1fc364..bf3230de45 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/ReflectionProjectContent.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/ReflectionProjectContent.cs @@ -130,7 +130,10 @@ namespace ICSharpCode.SharpDevelop.Dom public void InitializeSpecialClasses() { - if (GetClassInternal(VoidClass.VoidName, 0, Language) != null) { + // Replace the class representing System.Void with VoidClass.Instance + IClass voidClass = GetClassInternal(VoidClass.VoidName, 0, Language); + if (voidClass != null) { + RemoveClass(voidClass); AddClassToNamespaceList(VoidClass.Instance); } }