| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646 | //---------------------------------------------------------------------------#include <vcl.h>#pragma hdrstop#include <Common.h>#include <WinInterface.h>#include <VCLCommon.h>#include <TextsWin.h>#include <WinConfiguration.h>#include <CoreMain.h>#include <Tools.h>#include <BaseUtils.hpp>#include <Terminal.h>#include "FileFind.h"//---------------------------------------------------------------------------#pragma package(smart_init)#pragma link "HistoryComboBox"#pragma link "IEListView"#pragma link "NortonLikeListView"#pragma link "PngImageList"#ifndef NO_RESOURCES#pragma resource "*.dfm"#endif//---------------------------------------------------------------------------TFileFindDialog * FileFindDialog = NULL;//---------------------------------------------------------------------------void __fastcall ShowFileFindDialog(  TTerminal * Terminal, UnicodeString Directory, TFindEvent OnFind, TFocusFileEvent OnFocusFile,  TFileListOperationEvent OnDeleteFiles, TFileListOperationEvent OnDownloadFiles, TFileListOperationEvent OnEditFiles){  if (FileFindDialog == NULL)  {    FileFindDialog = new TFileFindDialog(Application);  }  FileFindDialog->Init(Terminal, Directory, OnFind, OnFocusFile, OnDeleteFiles, OnDownloadFiles, OnEditFiles);  FileFindDialog->Show();}//---------------------------------------------------------------------------void __fastcall HideFileFindDialog(){  if (FileFindDialog != NULL)  {    delete FileFindDialog;  }}//---------------------------------------------------------------------------__fastcall TFileFindDialog::TFileFindDialog(TComponent * Owner)  : TForm(Owner){  UseSystemSettings(this);  FState = ffInit;  FixComboBoxResizeBug(MaskEdit);  FixComboBoxResizeBug(RemoteDirectoryEdit);  HintLabel(MaskHintText,    FORMAT(L"%s\n \n%s\n \n%s\n \n%s\n \n%s\n \n%s", (LoadStr(MASK_HINT2),      LoadStr(FILE_MASK_EX_HINT), LoadStr(COMBINING_MASKS_HINT),      LoadStr(PATH_MASK_HINT2), LoadStr(DIRECTORY_MASK_HINT),      LoadStr(MASK_HELP))));  UpdateImages();  FileView->ShowColumnIcon = false;  UseDesktopFont(FileView);  UseDesktopFont(StatusBar);  FFrameAnimation.Init(AnimationPaintBox, L"Find");  FixFormIcons(this);}//---------------------------------------------------------------------------__fastcall TFileFindDialog::~TFileFindDialog(){  TFindFileConfiguration FormConfiguration = CustomWinConfiguration->FindFile;  FormConfiguration.ListParams = FileView->ColProperties->ParamsStr;  UnicodeString WindowParams = StoreFormSize(this);  // this is particularly to prevent saving the form state  // for the first time, keeping default positioning by a system  if (!FWindowParams.IsEmpty() && (FWindowParams != WindowParams))  {    FormConfiguration.WindowParams = WindowParams;  }  CustomWinConfiguration->FindFile = FormConfiguration;  Clear();  DebugAssert(FileFindDialog == this);  FileFindDialog = NULL;}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::UpdateImages(){  FileView->SmallImages = ShellImageListForControl(this, ilsSmall);}//---------------------------------------------------------------------------bool __fastcall TFileFindDialog::IsFinding(){  return (FState == ffFinding) || (FState == ffAborting);}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::UpdateControls(){  bool Finding = IsFinding();  Caption = FORMAT("%s - %s", (LoadStr(Finding ? FIND_FILE_FINDING : FIND_FILE_TITLE), FTerminalName));  UnicodeString StartStopCaption;  if (Finding)  {    EnableControl(StartStopButton, true);    StartStopCaption = LoadStr(FIND_FILE_STOP);  }  else  {    EnableControl(StartStopButton, !RemoteDirectoryEdit->Text.IsEmpty());    StartStopCaption = LoadStr(FIND_FILE_START);  }  StartStopButton->Caption = StartStopCaption;  EnableControl(FilterGroup, !Finding);  FocusAction->Enabled = (FileView->ItemFocused != NULL);  bool EnableFileOperations = !Finding && (FileView->SelCount > 0);  DeleteAction->Enabled = EnableFileOperations;  DownloadAction->Enabled = EnableFileOperations;  EditAction->Enabled = EnableFileOperations;  CopyAction->Enabled = (FileView->Items->Count > 0);  SelectAllAction->Enabled = (FileView->SelCount < FileView->Items->Count);  switch (FState)  {    case ffInit:      StatusBar->SimpleText = L"";      break;    case ffFinding:    case ffAborting:      if (!FFindingInDirectory.IsEmpty())      {        StatusBar->SimpleText = FMTLOAD(FIND_FILE_IN_DIRECTORY, (FFindingInDirectory));      }      else      {        StatusBar->SimpleText = L"";      }      break;    case ffAborted:      StatusBar->SimpleText = LoadStr(FIND_FILE_ABORTED);      break;    case ffDone:      StatusBar->SimpleText = LoadStr(FIND_FILE_DONE);      break;    default:      DebugFail();      break;  }  FocusButton->Default = FileView->Focused() && (FState != ffInit);  StartStopButton->Default = !FocusButton->Default;}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::ControlChange(TObject * /*Sender*/){  UpdateControls();}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::Init(  TTerminal * Terminal, UnicodeString Directory, TFindEvent OnFind, TFocusFileEvent OnFocusFile,  TFileListOperationEvent OnDeleteFiles, TFileListOperationEvent OnDownloadFiles, TFileListOperationEvent OnEditFiles){  if (FTerminal != Terminal)  {    FTerminal = Terminal;    FTerminalName = Terminal->SessionData->SessionName;    Clear();    FState = ffInit;    ActiveControl = MaskEdit;  }  FOnFind = OnFind;  FOnFocusFile = OnFocusFile;  FOnDeleteFiles = OnDeleteFiles;  FOnDownloadFiles = OnDownloadFiles;  FOnEditFiles = OnEditFiles;  MaskEdit->Text = WinConfiguration->SelectMask;  RemoteDirectoryEdit->Text = UnixExcludeTrailingBackslash(Directory);  UpdateControls();}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::CreateParams(TCreateParams & Params){  TForm::CreateParams(Params);  Params.WndParent = GetDesktopWindow();}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::ClearItem(TListItem * Item){  TRemoteFile * File = static_cast<TRemoteFile *>(Item->Data);  Item->Data = NULL;  delete File;}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::Clear(){  for (int Index = 0; Index < FileView->Items->Count; Index++)  {    ClearItem(FileView->Items->Item[Index]);  }  FileView->Items->Clear();}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::Start(){  if (MaskEdit->Focused())  {    MaskEditExit(NULL);  }  RemoteDirectoryEdit->SaveToHistory();  CustomWinConfiguration->History[L"RemoteDirectory"] = RemoteDirectoryEdit->Items;  MaskEdit->SaveToHistory();  WinConfiguration->History[L"Mask"] = MaskEdit->Items;  WinConfiguration->SelectMask = MaskEdit->Text;  DebugAssert(FState != ffFinding);  FState = ffFinding;  FClosePending = false;  try  {    FFrameAnimation.Start();    UpdateControls();    Repaint();    TOperationVisualizer Visualizer;    DebugAssert(FOnFind != NULL);    UnicodeString Directory = UnixExcludeTrailingBackslash(RemoteDirectoryEdit->Text);    FDirectory = Directory;    if (FDirectory == ROOTDIRECTORY)    {      FDirectory = UnicodeString();    }    FOnFind(FTerminal, Directory, MaskEdit->Text, FileFound, FindingFile);  }  __finally  {    FFindingInDirectory = L"";    if (FState == ffFinding)    {      FState = ffDone;    }    if (FState == ffAborting)    {      FState = ffAborted;    }    FFrameAnimation.Stop();    if (WindowState == wsMinimized)    {      ShowNotification(        NULL, MainInstructions(LoadStr(BALLOON_OPERATION_COMPLETE)),        qtInformation);    }    if (!FFocusPath.IsEmpty())    {      UnicodeString FocusPath = FFocusPath;      FFocusPath = L"";      DoFocusFile(FocusPath);    }    UpdateControls();  }  if (FClosePending)  {    FClosePending = false;    Close();  }}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::FileFound(TTerminal * /*Terminal*/,  const UnicodeString FileName, const TRemoteFile * AFile, bool & Cancel){  TListItem * Item = FileView->Items->Add();  TRemoteFile * File = AFile->Duplicate(true);  Item->Data = File;  Item->ImageIndex = File->IconIndex;  UnicodeString Caption = File->FileName;  if (File->IsDirectory)  {    Caption = UnixIncludeTrailingBackslash(Caption);  }  Item->Caption = Caption;  UnicodeString Directory = UnixExtractFilePath(File->FullFileName);  if (AnsiSameText(FDirectory, Directory.SubString(1, FDirectory.Length())))  {    Directory = L"." + Directory.SubString(FDirectory.Length() + 1, Directory.Length() - FDirectory.Length());  }  else  {    DebugFail();  }  Item->SubItems->Add(Directory);  if (File->IsDirectory)  {    Item->SubItems->Add(L"");  }  else  {    Item->SubItems->Add(      FormatPanelBytes(File->Size, WinConfiguration->FormatSizeBytes));  }  Item->SubItems->Add(UserModificationStr(File->Modification, File->ModificationFmt));  UpdateControls();  Cancel = (FState == ffAborting);  Application->ProcessMessages();}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::FindingFile(TTerminal * /*Terminal*/,  const UnicodeString Directory, bool & Cancel){  if (!Directory.IsEmpty() && (FFindingInDirectory != Directory))  {    FFindingInDirectory = Directory;    UpdateControls();  }  Cancel = (FState == ffAborting);  Application->ProcessMessages();}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::StartStopButtonClick(TObject * /*Sender*/){  if (IsFinding())  {    Stop();  }  else  {    Clear();    if (ActiveControl->Parent == FilterGroup)    {      FileView->SetFocus();    }    Start();  }}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::StopButtonClick(TObject * /*Sender*/){  Stop();}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::Stop(){  FState = ffAborting;  UpdateControls();}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::FormShow(TObject * /*Sender*/){  InstallPathWordBreakProc(MaskEdit);  InstallPathWordBreakProc(RemoteDirectoryEdit);  // have to set history after value, to prevent autocompletition  MaskEdit->Items = WinConfiguration->History[L"Mask"];  RemoteDirectoryEdit->Items = CustomWinConfiguration->History[L"RemoteDirectory"];  UpdateFormPosition(this, poOwnerFormCenter);  RestoreFormSize(CustomWinConfiguration->FindFile.WindowParams, this);  FileView->ColProperties->ParamsStr = CustomWinConfiguration->FindFile.ListParams;  DebugAssert(FWindowParams.IsEmpty());  if (FWindowParams.IsEmpty())  {    FWindowParams = StoreFormSize(this);  }  UpdateControls();}//---------------------------------------------------------------------------bool __fastcall TFileFindDialog::StopIfFinding(){  bool Result = IsFinding();  if (Result)  {    Stop();  }  return Result;}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::FormCloseQuery(TObject * /*Sender*/,  bool & CanClose){  if (StopIfFinding())  {    FClosePending = true;    CanClose = false;  }}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::HelpButtonClick(TObject * /*Sender*/){  FormHelp(this);}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::Dispatch(void * Message){  TMessage * M = reinterpret_cast<TMessage*>(Message);  if (M->Msg == CM_DIALOGKEY)  {    CMDialogKey(*((TWMKeyDown *)Message));  }  else if (M->Msg == CM_DPICHANGED)  {    CMDpiChanged(*M);  }  else  {    TForm::Dispatch(Message);  }}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::CMDpiChanged(TMessage & Message){  TForm::Dispatch(&Message);  UpdateImages();}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::CMDialogKey(TWMKeyDown & Message){  // Handling VK_ESCAPE in FormKeyDown causes a beep when any "edit" has focus.  // Moreover FormKeyDown is called when the the "esc" is pressed while drop down list is unrolled.  if (Message.CharCode == VK_ESCAPE)  {    if (!StopIfFinding())    {      Close();    }    Message.Result = 1;    return;  }  TForm::Dispatch(&Message);}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::FormKeyDown(TObject * /*Sender*/, WORD & Key,  TShiftState Shift){  if ((Key == L'C') && Shift.Contains(ssCtrl) &&      (dynamic_cast<TCustomCombo *>(ActiveControl) == NULL))  {    CopyToClipboard();    Key = 0;  }  else if ((Key == VK_F10) && Shift.Empty())  {    Key = 0;    StopIfFinding();    Close();  }}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::MaskEditExit(TObject * /*Sender*/){  ValidateMaskEdit(MaskEdit);}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::DoFocusFile(const UnicodeString & Path){  FOnFocusFile(FTerminal, Path);}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::FocusFile(){  UnicodeString Path = static_cast<TRemoteFile *>(FileView->ItemFocused->Data)->FullFileName;  // To make focussing directories work,  // otherwise it would try to focus "empty-named file" in the Path  Path = UnixExcludeTrailingBackslash(Path);  if (StopIfFinding())  {    FFocusPath = Path;  }  else  {    DoFocusFile(Path);  }}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::FileViewDblClick(TObject * /*Sender*/){  if (FileView->ItemFocused != NULL)  {    FocusFile();  }}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::FocusActionExecute(TObject * /*Sender*/){  FocusFile();}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::FileViewSelectItem(TObject * /*Sender*/,  TListItem * /*Item*/, bool /*Selected*/){  UpdateControls();}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::MaskButtonClick(TObject * /*Sender*/){  TFileMasks Masks = MaskEdit->Text;  if (DoEditMaskDialog(Masks))  {    MaskEdit->Text = Masks.Masks;  }}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::CopyToClipboard(){  TInstantOperationVisualizer Visualizer;  std::unique_ptr<TStrings> Strings(new TStringList());  for (int Index = 0; Index < FileView->Items->Count; Index++)  {    TListItem * Item = FileView->Items->Item[Index];    TRemoteFile * File = static_cast<TRemoteFile *>(Item->Data);    Strings->Add(File->FullFileName);  }  ::CopyToClipboard(Strings.get());}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::CopyActionExecute(TObject * /*Sender*/){  CopyToClipboard();}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::FormClose(TObject * /*Sender*/, TCloseAction & Action){  StopIfFinding();  Action = caFree;}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::FileViewContextPopup(TObject * Sender, TPoint & MousePos, bool & Handled){  // to update source popup menu before TBX menu is created  UpdateControls();  MenuPopup(Sender, MousePos, Handled);}//---------------------------------------------------------------------------TListItem * __fastcall TFileFindDialog::FileOperationFinished(const UnicodeString & FileName){  TFileItemMap::iterator I = FFileItemMap.find(FileName);  TListItem * Result = NULL;  if (DebugAlwaysTrue(I != FFileItemMap.end()))  {    Result = I->second;    FileView->MakeProgressVisible(Result);    FFileItemMap.erase(I);  }  return Result;}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::FileDeleteFinished(const UnicodeString & FileName, bool Success){  // Delete in queue not supported  DebugAssert(!FileName.IsEmpty());  TListItem * Item = FileOperationFinished(FileName);  if (DebugAlwaysTrue(Item != NULL) && Success)  {    ClearItem(Item);    Item->Delete();  }}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::FileDownloadFinished(const UnicodeString & FileName, bool Success){  if (FileName.IsEmpty())  {    DebugAssert(Success);    // Moved to queue, see call in TCustomScpExplorerForm::CopyParamDialog    FileView->SelectAll(smNone);  }  else  {    TListItem * Item = FileOperationFinished(FileName);    if (DebugAlwaysTrue(Item != NULL) && Success)    {      Item->Selected = false;    }  }}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::FileListOperation(  TFileListOperationEvent Operation, TFileOperationFinishedEvent OnFileOperationFinished){  std::unique_ptr<TStrings> FileList(new TStringList());  DebugAssert(FFileItemMap.empty());  TListItem * Item = FileView->Selected;  while (Item != NULL)  {    TRemoteFile * File = static_cast<TRemoteFile *>(Item->Data);    FileList->AddObject(File->FullFileName, File);    FFileItemMap.insert(std::make_pair(File->FullFileName, Item));    Item = FileView->GetNextItem(Item, sdAll, TItemStates() << isSelected);  }  try  {    Operation(FTerminal, FileList.get(), OnFileOperationFinished);  }  __finally  {    // can be non-empty only when not all files were processed    FFileItemMap.clear();  }  UpdateControls();}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::DeleteActionExecute(TObject * /*Sender*/){  FileListOperation(FOnDeleteFiles, FileDeleteFinished);}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::SelectAllActionExecute(TObject * /*Sender*/){  FileView->SelectAll(smAll);}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::DownloadActionExecute(TObject * /*Sender*/){  FileListOperation(FOnDownloadFiles, FileDownloadFinished);}//---------------------------------------------------------------------------void __fastcall TFileFindDialog::EditActionExecute(TObject * /*Sender*/){  FileListOperation(FOnEditFiles, FileDownloadFinished);}//---------------------------------------------------------------------------
 |