/* ЗАМЕТКА РАЗРАБОТЧИКУ * * В данном файле размещаются функции для работы с файлами и каталогами. * Данные функции запускаются в отдельных от UI потоках из кода * файла MainWindow-Actions.cs . Всякая функция должна иметь * префикс Do, означающий её чисто утилитарную принадлежность. * * Вызовы пользовательского интерфейса (XWT) должны производиться через * вызывалку Xwt.Application.Invoke(new Action(delegate { КОД ПОТОКА ИНТЕРФЕЙСА })); * в противном случае возможны глюки (вылеты WPF, зависания и лаги GTK). */ /// <summary> /// Background file copier /// </summary> /// <param name='SourceFS'>Source FS.</param> /// <param name='DestinationFS'>Destination FS.</param> /// <param name='SourceURL'>Source file URL.</param> /// <param name='DestinationURL'>Destination URL.</param> /// <param name="Feedback">If at the destination URL a file exists, a ReplaceQuestionDialog will be shown. This argument is the place, where the user's last choose should be saved.</param> /// <param name="AC">The instance of AsyncCopy class that should be used to copy the file.</param> private void DoCp(IFSPlugin SourceFS, IFSPlugin DestinationFS, string SourceURL, string DestinationURL, ref ReplaceQuestionDialog.ClickedButton Feedback, AsyncCopy AC) { if (SourceURL == DestinationURL){ string itself = Localizator.GetString("CantCopySelf"); string toshow = string.Format(Localizator.GetString("CantCopy"), SourceFS.GetMetadata(SourceURL).Name, itself); Xwt.Application.Invoke(delegate { Xwt.MessageDialog.ShowWarning(toshow); }); //calling the msgbox in non-main threads causes some UI bugs, so push this call into main thread return; } if(DestinationFS.FileExists (DestinationURL)){ ReplaceQuestionDialog rpd = null; bool ready = false; Xwt.Application.Invoke( delegate { rpd = new ReplaceQuestionDialog(DestinationFS.GetMetadata(DestinationURL).Name); ready = true; } ); do { } while (!ready); ready = false; var ClickedButton = ReplaceQuestionDialog.ClickedButton.Skip; Xwt.Application.Invoke( delegate { ClickedButton = rpd.Run(); ready = true; } ); do {} while (!ready); switch(ClickedButton){ case ReplaceQuestionDialog.ClickedButton.Replace: //continue execution Feedback = rpd.ChoosedButton; break; case ReplaceQuestionDialog.ClickedButton.ReplaceAll: //continue execution Feedback = rpd.ChoosedButton; break; case ReplaceQuestionDialog.ClickedButton.ReplaceOld: Feedback = rpd.ChoosedButton; if(SourceFS.GetMetadata(SourceURL).LastWriteTimeUTC < DestinationFS.GetMetadata(DestinationURL).LastWriteTimeUTC) {/*continue execution*/} else {return;} break; case ReplaceQuestionDialog.ClickedButton.Skip: Feedback = rpd.ChoosedButton; return; case ReplaceQuestionDialog.ClickedButton.SkipAll: Feedback = rpd.ChoosedButton; return; } } try { pluginner.FSEntryMetadata md = SourceFS.GetMetadata(SourceURL); md.FullURL = DestinationURL; System.IO.Stream SrcStream = SourceFS.GetFileStream(SourceURL); DestinationFS.Touch(md); System.IO.Stream DestStream = DestinationFS.GetFileStream(DestinationURL,true); if(AC == null) AC = new AsyncCopy(); bool CpComplete = false; AC.OnComplete += result => CpComplete = true; //warning: due to some GTK# bugs, buffer sizes lesser than 128KB may cause //an StackOverflowException at UI update code AC.CopyFile(SrcStream, DestStream, 131072); //buffer is 1/8 megabyte or 128KB do{ } while(!CpComplete); //don't stop this thread until the copy is finished } catch (Exception ex) { if (ex.GetType() != typeof(System.Threading.ThreadAbortException)) { Utilities.ShowMessage(string.Format(Localizator.GetString("CantCopy"),SourceURL,ex.Message)); Console.WriteLine("Cannot copy because of {0}({1}) at \n{2}.", ex.GetType(), ex.Message, ex.StackTrace); } } }
/// <summary> /// Background file copier /// </summary> /// <param name='SourceFS'> /// Source FS. /// </param> /// <param name='DestinationFS'> /// Destination FS. /// </param> /// <param name='SourceFile'> /// Source file. /// </param> /// <param name='DestinationURL'> /// Destination URL. /// </param> /// <param name='SkipAll'> /// The referenced variable will be set to TRUE if user chooses "Skip all" /// </param> /// <param name='ReplaceAll'> /// The referenced variable will be set to TRUE if user chooses "Replace all" /// </param> void DoCp(pluginner.IFSPlugin SourceFS, pluginner.IFSPlugin DestinationFS, pluginner.File SourceFile, string DestinationURL, ref ReplaceQuestionDialog.ClickedButton Feedback, AsyncCopy AC) { pluginner.File NewFile = SourceFile; NewFile.Path = DestinationURL; if (SourceFile.Path == DestinationURL) { string itself = Locale.GetString("CantCopySelf"); string toshow = string.Format(Locale.GetString("CantCopy"), SourceFile.Name, itself); Xwt.Application.Invoke(new Action(delegate { Xwt.MessageDialog.ShowWarning(toshow); })); //calling the msgbox in non-main threads causes some UI bugs, so push this call into main thread return; } if (DestinationFS.FileExists(DestinationURL)) { ReplaceQuestionDialog rpd = null; bool ready = false; Xwt.Application.Invoke( new Action( delegate { rpd = new ReplaceQuestionDialog(DestinationFS.GetFile(DestinationURL, new double()).Name); ready = true; } ) ); do { } while (!ready); ready = false; var ClickedButton = ReplaceQuestionDialog.ClickedButton.Skip; Xwt.Application.Invoke( new Action( delegate { ClickedButton = rpd.Run(); ready = true; } ) ); do { } while (!ready); switch (ClickedButton) { case ReplaceQuestionDialog.ClickedButton.Replace: //continue execution Feedback = rpd.ChoosedButton; break; case ReplaceQuestionDialog.ClickedButton.ReplaceAll: //continue execution Feedback = rpd.ChoosedButton; break; case ReplaceQuestionDialog.ClickedButton.ReplaceOld: Feedback = rpd.ChoosedButton; if (SourceFS.GetMetadata(SourceFile.Path).LastWriteTimeUTC < DestinationFS.GetFile(DestinationURL, new double()).Metadata.LastWriteTimeUTC) { /*continue execution*/ } else { return; } break; case ReplaceQuestionDialog.ClickedButton.Skip: Feedback = rpd.ChoosedButton; return; case ReplaceQuestionDialog.ClickedButton.SkipAll: Feedback = rpd.ChoosedButton; return; } } try { pluginner.FSEntryMetadata md = SourceFS.GetMetadata(SourceFile.Path); md.FullURL = NewFile.Path; System.IO.Stream SrcStream = SourceFS.GetStream(SourceFile.Path); DestinationFS.Touch(md); System.IO.Stream DestStream = DestinationFS.GetStream(DestinationURL, true); if (AC == null) { AC = new AsyncCopy(); } bool CpComplete = false; AC.OnComplete += (rezultat) => { CpComplete = true; }; //warning: due to some GTK# bugs, buffer sizes lesser than 128KB may cause //an StackOverflowException at UI update code AC.CopyFile(SrcStream, DestStream, 131072); //buffer is 1/8 megabyte do /*nothing*/ } { while(!CpComplete); //don't stop this thread until the copy is finished return; }