FileFind.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741
  1. //---------------------------------------------------------------------------
  2. #include <FormsPCH.h>
  3. #pragma hdrstop
  4. #include <Terminal.h>
  5. #include "FileFind.h"
  6. //---------------------------------------------------------------------------
  7. #pragma link "HistoryComboBox"
  8. #pragma link "IEListView"
  9. #pragma link "NortonLikeListView"
  10. #pragma resource "*.dfm"
  11. //---------------------------------------------------------------------------
  12. static TFileFindDialog * FileFindDialog = NULL;
  13. static const int NoSort = 1;
  14. //---------------------------------------------------------------------------
  15. void __fastcall ShowFileFindDialog(
  16. TTerminal * Terminal, UnicodeString Directory, TFindEvent OnFind, TFocusFileEvent OnFocusFile,
  17. TFileListOperationEvent OnDeleteFiles, TFileListOperationEvent OnDownloadFiles, TFileListOperationEvent OnEditFiles)
  18. {
  19. if (FileFindDialog == NULL)
  20. {
  21. FileFindDialog = new TFileFindDialog(Application);
  22. }
  23. FileFindDialog->Init(Terminal, Directory, OnFind, OnFocusFile, OnDeleteFiles, OnDownloadFiles, OnEditFiles);
  24. FileFindDialog->Show();
  25. }
  26. //---------------------------------------------------------------------------
  27. void __fastcall HideFileFindDialog()
  28. {
  29. if (FileFindDialog != NULL)
  30. {
  31. delete FileFindDialog;
  32. }
  33. }
  34. //---------------------------------------------------------------------------
  35. __fastcall TFileFindDialog::TFileFindDialog(TComponent * Owner)
  36. : TForm(Owner)
  37. {
  38. UseSystemSettings(this);
  39. FState = ffInit;
  40. FixComboBoxResizeBug(MaskEdit);
  41. FixComboBoxResizeBug(RemoteDirectoryEdit);
  42. HintLabel(MaskHintText,
  43. FORMAT(L"%s\n \n%s\n \n%s\n \n%s\n \n%s\n \n%s", (LoadStr(MASK_HINT2),
  44. LoadStr(FILE_MASK_EX_HINT), LoadStr(COMBINING_MASKS_HINT),
  45. LoadStr(PATH_MASK_HINT2), LoadStr(DIRECTORY_MASK_HINT),
  46. LoadStr(MASK_HELP))));
  47. UpdateImages();
  48. UseDesktopFont(FileView2);
  49. UseDesktopFont(StatusBar);
  50. FFrameAnimation.Init(AnimationPaintBox, L"Find");
  51. FixFormIcons(this);
  52. }
  53. //---------------------------------------------------------------------------
  54. __fastcall TFileFindDialog::~TFileFindDialog()
  55. {
  56. TFindFileConfiguration FormConfiguration = CustomWinConfiguration->FindFile;
  57. // | is there to make TCustomListViewColProperties.SetParamsStr stop there
  58. // (and it allows adding new parameters to the col properties in the future)
  59. FormConfiguration.ListParams = FORMAT(L"%s|/%d", (FileView2->ColProperties->ParamsStr, 1));
  60. UnicodeString WindowParams = StoreFormSize(this);
  61. // this is particularly to prevent saving the form state
  62. // for the first time, keeping default positioning by a system
  63. if (!FWindowParams.IsEmpty() && (FWindowParams != WindowParams))
  64. {
  65. FormConfiguration.WindowParams = WindowParams;
  66. }
  67. CustomWinConfiguration->FindFile = FormConfiguration;
  68. Clear();
  69. DebugAssert(FileFindDialog == this);
  70. FileFindDialog = NULL;
  71. }
  72. //---------------------------------------------------------------------------
  73. void __fastcall TFileFindDialog::UpdateImages()
  74. {
  75. FileView2->SmallImages = ShellImageListForControl(this, ilsSmall);
  76. }
  77. //---------------------------------------------------------------------------
  78. bool __fastcall TFileFindDialog::IsFinding()
  79. {
  80. return (FState == ffFinding) || (FState == ffAborting);
  81. }
  82. //---------------------------------------------------------------------------
  83. void __fastcall TFileFindDialog::UpdateControls()
  84. {
  85. bool Finding = IsFinding();
  86. Caption = LoadStr(Finding ? FIND_FILE_FINDING : FIND_FILE_TITLE) + TitleSeparator + FTerminalName;
  87. UnicodeString StartStopCaption;
  88. if (Finding)
  89. {
  90. EnableControl(StartStopButton, true);
  91. StartStopCaption = LoadStr(FIND_FILE_STOP);
  92. }
  93. else
  94. {
  95. EnableControl(StartStopButton, !RemoteDirectoryEdit->Text.IsEmpty());
  96. StartStopCaption = LoadStr(FIND_FILE_START);
  97. }
  98. StartStopButton->Caption = StartStopCaption;
  99. EnableControl(FilterGroup, !Finding);
  100. FocusAction->Enabled = (FileView2->ItemFocused != NULL);
  101. bool EnableFileOperations = !Finding && (FileView2->SelCount > 0);
  102. DeleteAction->Enabled = EnableFileOperations;
  103. DownloadAction->Enabled = EnableFileOperations;
  104. EditAction->Enabled = EnableFileOperations;
  105. CopyAction->Enabled = (FileView2->Items->Count > 0);
  106. SelectAllAction->Enabled = (FileView2->SelCount < FileView2->Items->Count);
  107. switch (FState)
  108. {
  109. case ffInit:
  110. StatusBar->SimpleText = L"";
  111. break;
  112. case ffFinding:
  113. case ffAborting:
  114. if (!FFindingInDirectory.IsEmpty())
  115. {
  116. StatusBar->SimpleText = FMTLOAD(FIND_FILE_IN_DIRECTORY, (FFindingInDirectory));
  117. }
  118. else
  119. {
  120. StatusBar->SimpleText = L"";
  121. }
  122. break;
  123. case ffAborted:
  124. StatusBar->SimpleText = LoadStr(FIND_FILE_ABORTED);
  125. break;
  126. case ffDone:
  127. StatusBar->SimpleText = LoadStr(FIND_FILE_DONE);
  128. break;
  129. default:
  130. DebugFail();
  131. break;
  132. }
  133. FocusButton->Default = FileView2->Focused() && (FState != ffInit);
  134. StartStopButton->Default = !FocusButton->Default;
  135. }
  136. //---------------------------------------------------------------------------
  137. void __fastcall TFileFindDialog::ControlChange(TObject * /*Sender*/)
  138. {
  139. UpdateControls();
  140. }
  141. //---------------------------------------------------------------------------
  142. void __fastcall TFileFindDialog::Init(
  143. TTerminal * Terminal, UnicodeString Directory, TFindEvent OnFind, TFocusFileEvent OnFocusFile,
  144. TFileListOperationEvent OnDeleteFiles, TFileListOperationEvent OnDownloadFiles, TFileListOperationEvent OnEditFiles)
  145. {
  146. if (FTerminal != Terminal)
  147. {
  148. FTerminal = Terminal;
  149. FTerminalName = Terminal->SessionData->SessionName;
  150. Clear();
  151. FState = ffInit;
  152. ActiveControl = MaskEdit;
  153. }
  154. FOnFind = OnFind;
  155. FOnFocusFile = OnFocusFile;
  156. FOnDeleteFiles = OnDeleteFiles;
  157. FOnDownloadFiles = OnDownloadFiles;
  158. FOnEditFiles = OnEditFiles;
  159. MaskEdit->Text = WinConfiguration->SelectMask;
  160. RemoteDirectoryEdit->Text = UnixExcludeTrailingBackslash(Directory);
  161. UpdateControls();
  162. }
  163. //---------------------------------------------------------------------------
  164. void __fastcall TFileFindDialog::CreateParams(TCreateParams & Params)
  165. {
  166. TForm::CreateParams(Params);
  167. Params.WndParent = GetDesktopWindow();
  168. }
  169. //---------------------------------------------------------------------------
  170. void __fastcall TFileFindDialog::ClearItem(TListItem * Item)
  171. {
  172. TRemoteFile * File = static_cast<TRemoteFile *>(Item->Data);
  173. Item->Data = NULL;
  174. delete File;
  175. }
  176. //---------------------------------------------------------------------------
  177. void __fastcall TFileFindDialog::Clear()
  178. {
  179. for (int Index = 0; Index < FileView2->Items->Count; Index++)
  180. {
  181. ClearItem(FileView2->Items->Item[Index]);
  182. }
  183. FileView2->Items->Clear();
  184. }
  185. //---------------------------------------------------------------------------
  186. void __fastcall TFileFindDialog::Start()
  187. {
  188. if (MaskEdit->Focused())
  189. {
  190. MaskEditExit(NULL);
  191. }
  192. RemoteDirectoryEdit->SaveToHistory();
  193. CustomWinConfiguration->History[L"RemoteDirectory"] = RemoteDirectoryEdit->Items;
  194. MaskEdit->SaveToHistory();
  195. WinConfiguration->History[L"Mask"] = MaskEdit->Items;
  196. WinConfiguration->SelectMask = MaskEdit->Text;
  197. DebugAssert(FState != ffFinding);
  198. FState = ffFinding;
  199. FClosePending = false;
  200. try
  201. {
  202. FFrameAnimation.Start();
  203. UpdateControls();
  204. Repaint();
  205. TOperationVisualizer Visualizer;
  206. DebugAssert(FOnFind != NULL);
  207. UnicodeString Directory = UnixExcludeTrailingBackslash(RemoteDirectoryEdit->Text);
  208. FDirectory = Directory;
  209. if (FDirectory == ROOTDIRECTORY)
  210. {
  211. FDirectory = UnicodeString();
  212. }
  213. FOnFind(FTerminal, Directory, MaskEdit->Text, FileFound, FindingFile);
  214. }
  215. __finally
  216. {
  217. FFindingInDirectory = L"";
  218. if (FState == ffFinding)
  219. {
  220. FState = ffDone;
  221. }
  222. if (FState == ffAborting)
  223. {
  224. FState = ffAborted;
  225. }
  226. FFrameAnimation.Stop();
  227. if (WindowState == wsMinimized)
  228. {
  229. ShowNotification(
  230. NULL, MainInstructions(LoadStr(BALLOON_OPERATION_COMPLETE)),
  231. qtInformation);
  232. }
  233. if (!FFocusPath.IsEmpty())
  234. {
  235. UnicodeString FocusPath = FFocusPath;
  236. FFocusPath = L"";
  237. DoFocusFile(FocusPath);
  238. }
  239. UpdateControls();
  240. }
  241. if (FClosePending)
  242. {
  243. FClosePending = false;
  244. Close();
  245. }
  246. }
  247. //---------------------------------------------------------------------------
  248. void __fastcall TFileFindDialog::FileFound(TTerminal * /*Terminal*/,
  249. const UnicodeString DebugUsedArg(FileName), const TRemoteFile * AFile, bool & Cancel)
  250. {
  251. TListItem * Item;
  252. int Count = FileView2->Items->Count;
  253. if ((GetColProperties()->SortColumn == NoSort) || (Count == 0))
  254. {
  255. Item = FileView2->Items->Add();
  256. }
  257. else
  258. {
  259. TRemoteFile * FirstFile = static_cast<TRemoteFile *>(FileView2->Items->Item[0]->Data);
  260. TRemoteFile * LastFile = static_cast<TRemoteFile *>(FileView2->Items->Item[Count - 1]->Data);
  261. if (FilesCompare(AFile, FirstFile) < 0)
  262. {
  263. Item = FileView2->Items->Insert(0);
  264. }
  265. else if (FilesCompare(LastFile, AFile) < 0)
  266. {
  267. Item = FileView2->Items->Add();
  268. }
  269. else
  270. {
  271. int Start = 0;
  272. int End = Count;
  273. while (Start < End - 1)
  274. {
  275. int Index = (Start + End) / 2;
  276. DebugAssert((Index >= 0) && (Index < End));
  277. TRemoteFile * FileAtIndex = static_cast<TRemoteFile *>(FileView2->Items->Item[Index]->Data);
  278. int Compare = FilesCompare(AFile, FileAtIndex);
  279. if (Compare <= 0)
  280. {
  281. End = Index;
  282. }
  283. else
  284. {
  285. Start = Index;
  286. }
  287. }
  288. Item = FileView2->Items->Insert(Start + 1);
  289. }
  290. }
  291. TRemoteFile * File = AFile->Duplicate(true);
  292. Item->Data = File;
  293. Item->ImageIndex = File->IconIndex;
  294. UnicodeString Caption = File->FileName;
  295. if (File->IsDirectory)
  296. {
  297. Caption = UnixIncludeTrailingBackslash(Caption);
  298. }
  299. Item->Caption = Caption;
  300. UnicodeString Directory = UnixExtractFilePath(File->FullFileName);
  301. if (AnsiSameText(FDirectory, Directory.SubString(1, FDirectory.Length())))
  302. {
  303. Directory = L"." + Directory.SubString(FDirectory.Length() + 1, Directory.Length() - FDirectory.Length());
  304. }
  305. else
  306. {
  307. DebugFail();
  308. }
  309. Item->SubItems->Add(Directory);
  310. if (File->IsDirectory)
  311. {
  312. Item->SubItems->Add(L"");
  313. }
  314. else
  315. {
  316. Item->SubItems->Add(
  317. FormatPanelBytes(File->Size, WinConfiguration->FormatSizeBytes));
  318. }
  319. Item->SubItems->Add(UserModificationStr(File->Modification, File->ModificationFmt));
  320. UpdateControls();
  321. Cancel = (FState == ffAborting);
  322. Application->ProcessMessages();
  323. }
  324. //---------------------------------------------------------------------------
  325. void __fastcall TFileFindDialog::FindingFile(TTerminal * /*Terminal*/,
  326. const UnicodeString Directory, bool & Cancel)
  327. {
  328. if (!Directory.IsEmpty() && (FFindingInDirectory != Directory))
  329. {
  330. FFindingInDirectory = Directory;
  331. UpdateControls();
  332. }
  333. Cancel = (FState == ffAborting);
  334. Application->ProcessMessages();
  335. }
  336. //---------------------------------------------------------------------------
  337. void __fastcall TFileFindDialog::StartStopButtonClick(TObject * /*Sender*/)
  338. {
  339. if (IsFinding())
  340. {
  341. Stop();
  342. }
  343. else
  344. {
  345. Clear();
  346. if (ActiveControl->Parent == FilterGroup)
  347. {
  348. FileView2->SetFocus();
  349. }
  350. Start();
  351. }
  352. }
  353. //---------------------------------------------------------------------------
  354. void __fastcall TFileFindDialog::StopButtonClick(TObject * /*Sender*/)
  355. {
  356. Stop();
  357. }
  358. //---------------------------------------------------------------------------
  359. void __fastcall TFileFindDialog::Stop()
  360. {
  361. FState = ffAborting;
  362. UpdateControls();
  363. }
  364. //---------------------------------------------------------------------------
  365. void __fastcall TFileFindDialog::FormShow(TObject * /*Sender*/)
  366. {
  367. InstallPathWordBreakProc(MaskEdit);
  368. InstallPathWordBreakProc(RemoteDirectoryEdit);
  369. // have to set history after value, to prevent autocompletition
  370. MaskEdit->Items = WinConfiguration->History[L"Mask"];
  371. RemoteDirectoryEdit->Items = CustomWinConfiguration->History[L"RemoteDirectory"];
  372. UpdateFormPosition(this, poOwnerFormCenter);
  373. RestoreFormSize(CustomWinConfiguration->FindFile.WindowParams, this);
  374. UnicodeString S = CustomWinConfiguration->FindFile.ListParams;
  375. UnicodeString ParamsStr = CutToChar(S, L'/', true);
  376. FileView2->ColProperties->ParamsStr = ParamsStr;
  377. UnicodeString V = CutToChar(S, L'/', true);
  378. if (StrToIntDef(V, 0) == 0)
  379. {
  380. // Old versions had non-sense (while unused) default to sorting by "Changed", ignore it.
  381. GetColProperties()->SortColumn = NoSort;
  382. }
  383. DebugAssert(FWindowParams.IsEmpty());
  384. if (FWindowParams.IsEmpty())
  385. {
  386. FWindowParams = StoreFormSize(this);
  387. }
  388. UpdateControls();
  389. }
  390. //---------------------------------------------------------------------------
  391. bool __fastcall TFileFindDialog::StopIfFinding()
  392. {
  393. bool Result = IsFinding();
  394. if (Result)
  395. {
  396. Stop();
  397. }
  398. return Result;
  399. }
  400. //---------------------------------------------------------------------------
  401. void __fastcall TFileFindDialog::FormCloseQuery(TObject * /*Sender*/,
  402. bool & CanClose)
  403. {
  404. if (StopIfFinding())
  405. {
  406. FClosePending = true;
  407. CanClose = false;
  408. }
  409. }
  410. //---------------------------------------------------------------------------
  411. void __fastcall TFileFindDialog::HelpButtonClick(TObject * /*Sender*/)
  412. {
  413. FormHelp(this);
  414. }
  415. //---------------------------------------------------------------------------
  416. void __fastcall TFileFindDialog::Dispatch(void * Message)
  417. {
  418. TMessage * M = reinterpret_cast<TMessage*>(Message);
  419. if (M->Msg == CM_DIALOGKEY)
  420. {
  421. CMDialogKey(*((TWMKeyDown *)Message));
  422. }
  423. else
  424. {
  425. TForm::Dispatch(Message);
  426. }
  427. }
  428. //---------------------------------------------------------------------------
  429. void __fastcall TFileFindDialog::FormAfterMonitorDpiChanged(TObject *, int OldDPI, int NewDPI)
  430. {
  431. DebugUsedParam2(OldDPI, NewDPI);
  432. UpdateImages();
  433. }
  434. //---------------------------------------------------------------------------
  435. void __fastcall TFileFindDialog::CMDialogKey(TWMKeyDown & Message)
  436. {
  437. // Handling VK_ESCAPE in FormKeyDown causes a beep when any "edit" has focus.
  438. // Moreover FormKeyDown is called when the the "esc" is pressed while drop down list is unrolled.
  439. if (Message.CharCode == VK_ESCAPE)
  440. {
  441. if (!StopIfFinding())
  442. {
  443. Close();
  444. }
  445. Message.Result = 1;
  446. return;
  447. }
  448. TForm::Dispatch(&Message);
  449. }
  450. //---------------------------------------------------------------------------
  451. void __fastcall TFileFindDialog::FormKeyDown(TObject * /*Sender*/, WORD & Key,
  452. TShiftState Shift)
  453. {
  454. if ((Key == L'C') && Shift.Contains(ssCtrl) &&
  455. (dynamic_cast<TCustomCombo *>(ActiveControl) == NULL))
  456. {
  457. CopyToClipboard();
  458. Key = 0;
  459. }
  460. else if ((Key == VK_F10) && Shift.Empty())
  461. {
  462. Key = 0;
  463. StopIfFinding();
  464. Close();
  465. }
  466. }
  467. //---------------------------------------------------------------------------
  468. void __fastcall TFileFindDialog::MaskEditExit(TObject * /*Sender*/)
  469. {
  470. ValidateMaskEdit(MaskEdit);
  471. }
  472. //---------------------------------------------------------------------------
  473. void __fastcall TFileFindDialog::DoFocusFile(const UnicodeString & Path)
  474. {
  475. FOnFocusFile(FTerminal, Path);
  476. }
  477. //---------------------------------------------------------------------------
  478. void __fastcall TFileFindDialog::FocusFile()
  479. {
  480. UnicodeString Path = static_cast<TRemoteFile *>(FileView2->ItemFocused->Data)->FullFileName;
  481. // To make focussing directories work,
  482. // otherwise it would try to focus "empty-named file" in the Path
  483. Path = UnixExcludeTrailingBackslash(Path);
  484. if (StopIfFinding())
  485. {
  486. FFocusPath = Path;
  487. }
  488. else
  489. {
  490. DoFocusFile(Path);
  491. }
  492. }
  493. //---------------------------------------------------------------------------
  494. void __fastcall TFileFindDialog::FileView2DblClick(TObject * /*Sender*/)
  495. {
  496. if (FileView2->ItemFocused != NULL)
  497. {
  498. FocusFile();
  499. }
  500. }
  501. //---------------------------------------------------------------------------
  502. void __fastcall TFileFindDialog::FocusActionExecute(TObject * /*Sender*/)
  503. {
  504. FocusFile();
  505. }
  506. //---------------------------------------------------------------------------
  507. void __fastcall TFileFindDialog::FileView2SelectItem(TObject * /*Sender*/,
  508. TListItem * /*Item*/, bool /*Selected*/)
  509. {
  510. UpdateControls();
  511. }
  512. //---------------------------------------------------------------------------
  513. void __fastcall TFileFindDialog::MaskButtonClick(TObject * /*Sender*/)
  514. {
  515. TFileMasks Masks = MaskEdit->Text;
  516. if (DoEditMaskDialog(Masks))
  517. {
  518. MaskEdit->Text = Masks.Masks;
  519. }
  520. }
  521. //---------------------------------------------------------------------------
  522. void __fastcall TFileFindDialog::CopyToClipboard()
  523. {
  524. TInstantOperationVisualizer Visualizer;
  525. std::unique_ptr<TStrings> Strings(new TStringList());
  526. for (int Index = 0; Index < FileView2->Items->Count; Index++)
  527. {
  528. TListItem * Item = FileView2->Items->Item[Index];
  529. TRemoteFile * File = static_cast<TRemoteFile *>(Item->Data);
  530. Strings->Add(File->FullFileName);
  531. }
  532. ::CopyToClipboard(Strings.get());
  533. }
  534. //---------------------------------------------------------------------------
  535. void __fastcall TFileFindDialog::CopyActionExecute(TObject * /*Sender*/)
  536. {
  537. CopyToClipboard();
  538. }
  539. //---------------------------------------------------------------------------
  540. void __fastcall TFileFindDialog::FormClose(TObject * /*Sender*/, TCloseAction & Action)
  541. {
  542. StopIfFinding();
  543. Action = caFree;
  544. }
  545. //---------------------------------------------------------------------------
  546. void __fastcall TFileFindDialog::FileView2ContextPopup(TObject * Sender, TPoint & MousePos, bool & Handled)
  547. {
  548. // to update source popup menu before TBX menu is created
  549. UpdateControls();
  550. MenuPopup(Sender, MousePos, Handled);
  551. }
  552. //---------------------------------------------------------------------------
  553. TListItem * __fastcall TFileFindDialog::FileOperationFinished(const UnicodeString & FileName)
  554. {
  555. TFileItemMap::iterator I = FFileItemMap.find(FileName);
  556. TListItem * Result = NULL;
  557. if (DebugAlwaysTrue(I != FFileItemMap.end()))
  558. {
  559. Result = I->second;
  560. FileView2->MakeProgressVisible(Result);
  561. FFileItemMap.erase(I);
  562. }
  563. return Result;
  564. }
  565. //---------------------------------------------------------------------------
  566. void __fastcall TFileFindDialog::FileDeleteFinished(
  567. TOperationSide, const UnicodeString & FileName, bool Success, bool NotCancelled)
  568. {
  569. DebugUsedParam(NotCancelled);
  570. if (FileName.IsEmpty())
  571. {
  572. DebugAssert(Success && NotCancelled);
  573. FileView2->SelectAll(smNone);
  574. }
  575. else
  576. {
  577. TListItem * Item = FileOperationFinished(FileName);
  578. if (DebugAlwaysTrue(Item != NULL) && Success)
  579. {
  580. ClearItem(Item);
  581. Item->Delete();
  582. }
  583. }
  584. }
  585. //---------------------------------------------------------------------------
  586. void __fastcall TFileFindDialog::FileDownloadFinished(
  587. TOperationSide, const UnicodeString & FileName, bool Success, bool NotCancelled)
  588. {
  589. if (FileName.IsEmpty())
  590. {
  591. DebugAssert(Success && NotCancelled);
  592. // Moved to queue, see call in TCustomScpExplorerForm::CopyParamDialog
  593. FileView2->SelectAll(smNone);
  594. }
  595. else
  596. {
  597. TListItem * Item = FileOperationFinished(FileName);
  598. if (DebugAlwaysTrue(Item != NULL) && Success && NotCancelled)
  599. {
  600. Item->Selected = false;
  601. }
  602. }
  603. }
  604. //---------------------------------------------------------------------------
  605. void __fastcall TFileFindDialog::FileListOperation(
  606. TFileListOperationEvent Operation, TFileOperationFinishedEvent OnFileOperationFinished)
  607. {
  608. std::unique_ptr<TStrings> FileList(new TStringList());
  609. DebugAssert(FFileItemMap.empty());
  610. TListItem * Item = FileView2->Selected;
  611. while (Item != NULL)
  612. {
  613. TRemoteFile * File = static_cast<TRemoteFile *>(Item->Data);
  614. FileList->AddObject(File->FullFileName, File);
  615. FFileItemMap.insert(std::make_pair(File->FullFileName, Item));
  616. Item = FileView2->GetNextItem(Item, sdAll, TItemStates() << isSelected);
  617. }
  618. try
  619. {
  620. Operation(FTerminal, FileList.get(), OnFileOperationFinished);
  621. }
  622. __finally
  623. {
  624. // can be non-empty only when not all files were processed
  625. FFileItemMap.clear();
  626. }
  627. UpdateControls();
  628. }
  629. //---------------------------------------------------------------------------
  630. void __fastcall TFileFindDialog::DeleteActionExecute(TObject * /*Sender*/)
  631. {
  632. FileListOperation(FOnDeleteFiles, FileDeleteFinished);
  633. }
  634. //---------------------------------------------------------------------------
  635. void __fastcall TFileFindDialog::SelectAllActionExecute(TObject * /*Sender*/)
  636. {
  637. FileView2->SelectAll(smAll);
  638. }
  639. //---------------------------------------------------------------------------
  640. void __fastcall TFileFindDialog::DownloadActionExecute(TObject * /*Sender*/)
  641. {
  642. FileListOperation(FOnDownloadFiles, FileDownloadFinished);
  643. }
  644. //---------------------------------------------------------------------------
  645. void __fastcall TFileFindDialog::EditActionExecute(TObject * /*Sender*/)
  646. {
  647. FileListOperation(FOnEditFiles, FileDownloadFinished);
  648. }
  649. //---------------------------------------------------------------------------
  650. TIEListViewColProperties * TFileFindDialog::GetColProperties()
  651. {
  652. return dynamic_cast<TIEListViewColProperties *>(FileView2->ColProperties);
  653. }
  654. //---------------------------------------------------------------------------
  655. int TFileFindDialog::FilesCompare(const TRemoteFile * File1, const TRemoteFile * File2)
  656. {
  657. int Result = 0;
  658. switch (GetColProperties()->SortColumn)
  659. {
  660. case 0: // name
  661. Result = CompareText(File1->FileName, File2->FileName);
  662. break;
  663. case NoSort: // directories
  664. Result = 0; // default sort
  665. break;
  666. case 2: // size
  667. Result = CompareNumber(File1->Size, File2->Size);
  668. break;
  669. case 3: // changed
  670. Result = CompareFileTime(File1->Modification, File2->Modification);
  671. break;
  672. }
  673. if (Result == 0)
  674. {
  675. Result = CompareText(UnixExtractFilePath(File1->FullFileName), UnixExtractFilePath(File2->FullFileName));
  676. if (Result == 0)
  677. {
  678. Result = CompareText(File1->FileName, File2->FileName);
  679. }
  680. }
  681. if (!GetColProperties()->SortAscending)
  682. {
  683. Result = -Result;
  684. }
  685. return Result;
  686. }
  687. //---------------------------------------------------------------------------
  688. void __fastcall TFileFindDialog::FileView2Compare(TObject *, TListItem * Item1, TListItem * Item2, int DebugUsedArg(Data), int & Compare)
  689. {
  690. TRemoteFile * File1 = static_cast<TRemoteFile *>(Item1->Data);
  691. TRemoteFile * File2 = static_cast<TRemoteFile *>(Item2->Data);
  692. Compare = FilesCompare(File1, File2);
  693. }
  694. //---------------------------------------------------------------------------