UnixDirView.cpp 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include "UnixDirView.h"
  5. #include <FileCtrl.hpp>
  6. #ifndef DESIGN_ONLY
  7. #include <Interface.h>
  8. #include <ScpMain.h>
  9. #endif
  10. #include <Common.h>
  11. #pragma package(smart_init)
  12. #ifndef DESIGN_ONLY
  13. #define ITEMFILE ((TRemoteFile *)(Item->Data))
  14. #define ASSERT_VALID_ITEM assert(Item && Item->Data && Terminal); assert(Terminal->Files->IndexOf(ITEMFILE) >= 0)
  15. #endif
  16. //---------------------------------------------------------------------------
  17. static inline void ValidCtrCheck(TUnixDirView *)
  18. {
  19. new TUnixDirView(NULL);
  20. }
  21. //---------------------------------------------------------------------------
  22. namespace Unixdirview
  23. {
  24. void __fastcall PACKAGE Register()
  25. {
  26. TComponentClass classes[1] = {__classid(TUnixDirView)};
  27. RegisterComponents("Scp", classes, 0);
  28. }
  29. }
  30. //---------------------------------------------------------------------------
  31. #ifndef DESIGN_ONLY
  32. #define RFILE(N) ((TRemoteFile *)(Item ## N->Data))
  33. int __stdcall CompareDirectories(TListItem *Item1, TListItem *Item2, TUnixDirView *DirView)
  34. {
  35. // Because CompareDirectories is called from each other compare functions
  36. // it's sufficient to check pointers only here (see below)
  37. assert(DirView && Item1 && RFILE(1) && Item2 && RFILE(2));
  38. if (RFILE(1)->IsParentDirectory && !RFILE(2)->IsParentDirectory) return -1;
  39. else
  40. if (!RFILE(1)->IsParentDirectory && RFILE(2)->IsParentDirectory) return 1;
  41. else
  42. if (DirView->DirsOnTop &&
  43. RFILE(1)->IsDirectory && !RFILE(2)->IsDirectory) return -1;
  44. else
  45. if (DirView->DirsOnTop &&
  46. !RFILE(1)->IsDirectory && RFILE(2)->IsDirectory) return 1;
  47. else
  48. return 0;
  49. }
  50. //---------------------------------------------------------------------------
  51. #define DEFINE_COMPARE_FUNC(Property, CompareFunc) \
  52. int __stdcall Compare ## Property(TListItem *Item1, TListItem *Item2, TUnixDirView *DirView) \
  53. { int Result = CompareDirectories(Item1, Item2, DirView); \
  54. if (!Result) { Result = CompareFunc(RFILE(1)->Property, RFILE(2)->Property); \
  55. if (!DirView->UnixColProperties->SortAscending) Result = -Result; }\
  56. return Result; }
  57. #define COMPARE_NUMBER(Num1, Num2) ( Num1 < Num2 ? -1 : ( Num1 > Num2 ? 1 : 0) )
  58. //---------------------------------------------------------------------------
  59. DEFINE_COMPARE_FUNC(FileName, AnsiCompareText);
  60. DEFINE_COMPARE_FUNC(Size, COMPARE_NUMBER);
  61. DEFINE_COMPARE_FUNC(Modification, COMPARE_NUMBER);
  62. DEFINE_COMPARE_FUNC(RightsStr, AnsiCompareText);
  63. DEFINE_COMPARE_FUNC(Owner, AnsiCompareText);
  64. DEFINE_COMPARE_FUNC(Group, AnsiCompareText);
  65. DEFINE_COMPARE_FUNC(Extension, AnsiCompareText);
  66. //---------------------------------------------------------------------------
  67. #undef DEFINE_COMPARE_FUNC
  68. #undef COMPARE_NUMBER
  69. #undef RFILE
  70. #endif
  71. //---------------------------------------------------------------------------
  72. AnsiString __fastcall UniqTempDir(const AnsiString BaseDir)
  73. {
  74. AnsiString TempDir;
  75. #ifndef DESIGN_ONLY
  76. if (BaseDir.IsEmpty()) TempDir = SystemTemporaryDirectory();
  77. else
  78. #endif
  79. TempDir = BaseDir;
  80. TempDir = IncludeTrailingBackslash(IncludeTrailingBackslash(TempDir) + "scp" +
  81. FormatDateTime("nnzzz", Now()));
  82. return TempDir;
  83. }
  84. //---------------------------------------------------------------------------
  85. __fastcall TUnixDirView::TUnixDirView(TComponent* Owner)
  86. : TCustomUnixDirView(Owner)
  87. {
  88. #ifndef DESIGN_ONLY
  89. FTerminal = NULL;
  90. #endif
  91. FUniqTempDir = "";
  92. FDDDeleteDelay = DefaultDDDeleteDelay;
  93. FCaseSensitive = true;
  94. DDAllowMove = false;
  95. FShowInaccesibleDirectories = true;
  96. FOnWarnLackOfTempSpace = NULL;
  97. FDDTotalSize = -1;
  98. FOnDDTargetDrop = NULL;
  99. FDelayedDeletionTimer = NULL;
  100. FFullLoad = false;
  101. FDDFileList = NULL;
  102. FDelayedDeletionList = new TStringList();
  103. }
  104. //---------------------------------------------------------------------------
  105. __fastcall TUnixDirView::~TUnixDirView()
  106. {
  107. #ifndef DESIGN_ONLY
  108. Terminal = NULL;
  109. #endif
  110. if (FDelayedDeletionTimer)
  111. {
  112. DoDelayedDeletion(NULL);
  113. delete FDelayedDeletionTimer;
  114. }
  115. delete FDelayedDeletionList;
  116. }
  117. //---------------------------------------------------------------------------
  118. void __fastcall TUnixDirView::DisplayContextMenu(const TPoint &Where)
  119. {
  120. bool Handled = false;
  121. if (OnContextPopup) OnContextPopup(this, ScreenToClient(Where), Handled);
  122. if (!Handled)
  123. {
  124. if (PopupMenu && !PopupMenu->AutoPopup)
  125. PopupMenu->Popup(Where.x, Where.y);
  126. }
  127. }
  128. //---------------------------------------------------------------------------
  129. void __fastcall TUnixDirView::AddDelayedDirectoryDeletion(
  130. const AnsiString TempDir, int SecDelay)
  131. {
  132. TDateTime Alarm = Now() + (double)SecDelay*(double(1)/24/60/60);
  133. AnsiString xx = Alarm.TimeString();
  134. FDelayedDeletionList->AddObject(TempDir, (TObject*)Alarm.FileDate());
  135. if (!FDelayedDeletionTimer)
  136. {
  137. assert(HandleAllocated());
  138. FDelayedDeletionTimer = new TTimer(this);
  139. FDelayedDeletionTimer->Interval = 10000;
  140. FDelayedDeletionTimer->Enabled = true;
  141. FDelayedDeletionTimer->OnTimer = DoDelayedDeletion;
  142. }
  143. }
  144. //---------------------------------------------------------------------------
  145. bool DeleteCurrentFile(const AnsiString FileName)
  146. {
  147. if (FileName == "." || FileName == "..")
  148. {
  149. return true;
  150. }
  151. else
  152. {
  153. return DeleteFile(FileName);
  154. }
  155. }
  156. //---------------------------------------------------------------------------
  157. bool DeleteDirectory(const AnsiString DirName)
  158. {
  159. TSearchRec sr;
  160. bool retval = true;
  161. if (FindFirst(DirName + "\\*", faAnyFile, sr) == 0) // VCL Function
  162. {
  163. if (sr.Attr == faDirectory)
  164. {
  165. if (sr.Name != "." && sr.Name != "..")
  166. retval = DeleteDirectory(DirName + "\\" + sr.Name);
  167. }
  168. else
  169. {
  170. retval = DeleteCurrentFile(DirName + "\\" + sr.Name);
  171. }
  172. if (retval)
  173. {
  174. while (FindNext(sr) == 0)
  175. { // VCL Function
  176. if (sr.Attr == faDirectory)
  177. {
  178. if (sr.Name != "." && sr.Name != "..")
  179. retval = DeleteDirectory(DirName + "\\" + sr.Name);
  180. }
  181. else
  182. {
  183. retval = DeleteCurrentFile(DirName + "\\" + sr.Name);
  184. }
  185. if (!retval) break;
  186. }
  187. }
  188. }
  189. FindClose(sr);
  190. if (retval) retval = RemoveDir(DirName); // VCL function
  191. return retval;
  192. }
  193. //---------------------------------------------------------------------------
  194. void __fastcall TUnixDirView::DoDelayedDeletion(TObject * Sender)
  195. {
  196. assert(FDelayedDeletionList);
  197. TDateTime N = Now();
  198. TDateTime Alert;
  199. AnsiString Directory;
  200. for (int Index = FDelayedDeletionList->Count-1; Index >= 0; Index--)
  201. {
  202. Alert = FileDateToDateTime((int)FDelayedDeletionList->Objects[Index]);
  203. if (N >= Alert || !Sender)
  204. {
  205. Directory = FDelayedDeletionList->Strings[Index];
  206. if (DeleteDirectory(ExcludeTrailingBackslash(Directory)))
  207. {
  208. FDelayedDeletionList->Delete(Index);
  209. }
  210. }
  211. }
  212. if (FDelayedDeletionList->Count == 0)
  213. {
  214. FDelayedDeletionTimer->Enabled = false;
  215. }
  216. }
  217. //---------------------------------------------------------------------------
  218. void __fastcall TUnixDirView::DisplayPropertiesMenu()
  219. {
  220. if (OnDisplayProperties) OnDisplayProperties(this);
  221. }
  222. //---------------------------------------------------------------------------
  223. void __fastcall TUnixDirView::ExecuteFile(TListItem * Item)
  224. {
  225. #ifndef DESIGN_ONLY
  226. ASSERT_VALID_ITEM;
  227. if (ITEMFILE->IsDirectory)
  228. {
  229. FLastPath = PathName;
  230. ChangeDirectory(ITEMFILE->FileName);
  231. }
  232. else
  233. {
  234. if (ItemFocused != Item) ItemFocused = Item;
  235. DisplayPropertiesMenu();
  236. }
  237. #endif
  238. }
  239. //---------------------------------------------------------------------------
  240. void __fastcall TUnixDirView::ExecuteParentDirectory()
  241. {
  242. // We need to remember this to select directory being leaved in parent directory
  243. FLastPath = PathName;
  244. #ifndef DESIGN_ONLY
  245. ChangeDirectory(PARENTDIRECTORY);
  246. #endif
  247. }
  248. //---------------------------------------------------------------------------
  249. void __fastcall TUnixDirView::ExecuteHomeDirectory()
  250. {
  251. #ifndef DESIGN_ONLY
  252. // don't select any directory
  253. FLastPath = "";
  254. AnsiString APath = Terminal->SessionData->RemoteDirectory;
  255. if (Configuration->DefaultDirIsHome && !APath.IsEmpty() &&
  256. !Terminal->SessionData->UpdateDirectories)
  257. {
  258. if (APath[1] != '/')
  259. {
  260. Terminal->BeginTransaction();
  261. try
  262. {
  263. ChangeDirectory(HOMEDIRECTORY);
  264. ChangeDirectory(APath);
  265. }
  266. __finally
  267. {
  268. Terminal->EndTransaction();
  269. }
  270. }
  271. else
  272. {
  273. ChangeDirectory(APath);
  274. }
  275. }
  276. else
  277. {
  278. ChangeDirectory(HOMEDIRECTORY);
  279. }
  280. #endif
  281. }
  282. //---------------------------------------------------------------------------
  283. void __fastcall TUnixDirView::ReloadDirectory()
  284. {
  285. #ifndef DESIGN_ONLY
  286. FLastPath = "";
  287. DoAnimation(true);
  288. Terminal->ReloadDirectory();
  289. #endif
  290. }
  291. //---------------------------------------------------------------------------
  292. void __fastcall TUnixDirView::ExecuteRootDirectory()
  293. {
  294. #ifndef DESIGN_ONLY
  295. // We set LastPath to top directory, so it will be selected
  296. // after entering root directory
  297. // DISABLED: see PathChanged(): back moves to top directory, not to current
  298. FLastPath = PathName;
  299. ChangeDirectory(ROOTDIRECTORY);
  300. #endif
  301. }
  302. //---------------------------------------------------------------------------
  303. bool __fastcall TUnixDirView::ItemIsDirectory(TListItem * Item)
  304. {
  305. #ifndef DESIGN_ONLY
  306. ASSERT_VALID_ITEM;
  307. return ITEMFILE->IsDirectory;
  308. #else
  309. return false;
  310. #endif
  311. }
  312. //---------------------------------------------------------------------------
  313. bool __fastcall TUnixDirView::ItemIsFile(TListItem * Item)
  314. {
  315. #ifndef DESIGN_ONLY
  316. ASSERT_VALID_ITEM;
  317. return !(ITEMFILE->IsParentDirectory);
  318. #else
  319. return false;
  320. #endif
  321. }
  322. //---------------------------------------------------------------------------
  323. bool __fastcall TUnixDirView::ItemIsParentDirectory(TListItem * Item)
  324. {
  325. #ifndef DESIGN_ONLY
  326. ASSERT_VALID_ITEM;
  327. return ITEMFILE->IsParentDirectory;
  328. #else
  329. return false;
  330. #endif
  331. }
  332. //---------------------------------------------------------------------------
  333. AnsiString __fastcall TUnixDirView::ItemFileName(TListItem * Item)
  334. {
  335. #ifndef DESIGN_ONLY
  336. ASSERT_VALID_ITEM;
  337. return ITEMFILE->FileName;
  338. #else
  339. return AnsiString();
  340. #endif
  341. }
  342. //---------------------------------------------------------------------------
  343. __int64 __fastcall TUnixDirView::ItemFileSize(TListItem * Item)
  344. {
  345. #ifndef DESIGN_ONLY
  346. ASSERT_VALID_ITEM;
  347. return ITEMFILE->IsDirectory ? 0 : ITEMFILE->Size;
  348. #else
  349. return 0;
  350. #endif
  351. }
  352. //---------------------------------------------------------------------------
  353. AnsiString __fastcall TUnixDirView::ItemDragFileName(TListItem * Item)
  354. {
  355. #ifndef DESIGN_ONLY
  356. assert(Item && Item->Data && Terminal && (Terminal->Files->IndexOf(ITEMFILE) >= 0) && !FUniqTempDir.IsEmpty());
  357. return FUniqTempDir + Configuration->CopyParam.ValidLocalFileName(ITEMFILE->FileName);
  358. #else
  359. return 0;
  360. #endif
  361. }
  362. //---------------------------------------------------------------------------
  363. AnsiString __fastcall TUnixDirView::ItemFullFileName(TListItem * Item)
  364. {
  365. #ifndef DESIGN_ONLY
  366. ASSERT_VALID_ITEM;
  367. return ITEMFILE->FullFileName;
  368. #else
  369. return AnsiString();
  370. #endif
  371. }
  372. //---------------------------------------------------------------------------
  373. int __fastcall TUnixDirView::ItemImageIndex(TListItem * Item, bool /*Cache*/)
  374. {
  375. #ifndef DESIGN_ONLY
  376. ASSERT_VALID_ITEM;
  377. // TCustomDirView::ItemImageIndex is used for icon caching
  378. // so we don't need it here. But it's implemented anyway.
  379. return ITEMFILE->IconIndex;
  380. #else
  381. return 0;
  382. #endif
  383. }
  384. //---------------------------------------------------------------------------
  385. bool __fastcall TUnixDirView::ItemMatchesFilter(TListItem * Item,
  386. const TFileFilter &Filter)
  387. {
  388. #ifndef DESIGN_ONLY
  389. ASSERT_VALID_ITEM;
  390. TRemoteFile *File = ITEMFILE;
  391. int Attr = File->Attr;
  392. return
  393. ((Attr & Filter.IncludeAttr) == Filter.IncludeAttr) &&
  394. ((Attr & Filter.ExcludeAttr) == 0) &&
  395. ((!File->IsDirectory) || Filter.Directories) &&
  396. ((Filter.FileSizeFrom == 0) || (File->Size >= Filter.FileSizeFrom)) &&
  397. ((Filter.FileSizeTo == 0) || (File->Size <= Filter.FileSizeTo)) &&
  398. ((!(int)Filter.ModificationFrom) || (File->Modification >= Filter.ModificationFrom)) &&
  399. ((!(int)Filter.ModificationTo) || (File->Modification <= Filter.ModificationTo)) &&
  400. ((Filter.Masks.IsEmpty()) ||
  401. FileNameMatchesMasks(File->FileName, Filter.Masks));
  402. #else
  403. return false;
  404. #endif
  405. }
  406. //---------------------------------------------------------------------------
  407. Word __fastcall TUnixDirView::ItemOverlayIndexes(TListItem * Item)
  408. {
  409. #ifndef DESIGN_ONLY
  410. ASSERT_VALID_ITEM;
  411. Word Result = oiNoOverlay;
  412. if (ITEMFILE->IsParentDirectory)
  413. {
  414. Result |= oiDirUp;
  415. }
  416. if (ITEMFILE->IsSymLink)
  417. {
  418. Result |= ITEMFILE->BrokenLink ? oiBrokenLink : oiLink;
  419. }
  420. return Result;
  421. #else
  422. return 0;
  423. #endif
  424. }
  425. //---------------------------------------------------------------------------
  426. void __fastcall TUnixDirView::LoadFiles()
  427. {
  428. #ifndef DESIGN_ONLY
  429. assert(Terminal);
  430. if (DirOK)
  431. {
  432. // it's enough if we reach this point, we don't require that loading files into
  433. // list succeeded. FDirLoadedAfterChangeDir == false tells only that
  434. // loding file list from server failed, not loading into listview
  435. FDirLoadedAfterChangeDir = true;
  436. FFilesSize = 0;
  437. FHasParentDir = false;
  438. int VisibleFiles = 0;
  439. for (int Index = 0; Index < Terminal->Files->Count; Index++)
  440. {
  441. TRemoteFile *File = Terminal->Files->Files[Index];
  442. assert(File);
  443. TListItem *Item;
  444. if ((ShowHiddenFiles || !File->IsHidden) &&
  445. (ShowInaccesibleDirectories || !File->IsInaccesibleDirectory))
  446. {
  447. VisibleFiles++;
  448. if (!File->IsDirectory) FFilesSize += File->Size;
  449. if (File->IsParentDirectory) FHasParentDir = true;
  450. Item = Items->Add();
  451. Item->Data = File;
  452. Item->Caption = File->FileName;
  453. if (FFullLoad)
  454. {
  455. Item->ImageIndex = File->IconIndex;
  456. Item->SubItems->Add((!File->IsDirectory ? FormatFloat("#,##0", File->Size) : AnsiString()));
  457. Item->SubItems->Add(File->UserModificationStr);
  458. Item->SubItems->Add(File->RightsStr);
  459. Item->SubItems->Add(File->Owner);
  460. Item->SubItems->Add(File->Group);
  461. Item->SubItems->Add(File->Extension);
  462. }
  463. }
  464. }
  465. if (OwnerData)
  466. {
  467. Items->Count = VisibleFiles;
  468. }
  469. }
  470. #endif
  471. }
  472. //---------------------------------------------------------------------------
  473. void __fastcall TUnixDirView::GetDisplayInfo(TListItem * Item, tagLVITEMA &DispInfo)
  474. {
  475. if (!FFullLoad)
  476. {
  477. #ifndef DESIGN_ONLY
  478. TRemoteFile * File = ITEMFILE;
  479. if (DispInfo.mask & LVIF_TEXT)
  480. {
  481. AnsiString Value;
  482. switch (DispInfo.iSubItem) {
  483. case uvName: Value = File->FileName; break;
  484. case uvSize: Value = (!File->IsDirectory ? FormatFloat("#,##0", File->Size) : AnsiString()); break;
  485. case uvChanged: Value = File->UserModificationStr; break;
  486. case uvRights: Value = File->RightsStr; break;
  487. case uvOwner: Value = File->Owner; break;
  488. case uvGroup: Value = File->Group; break;
  489. case uvExt: Value = File->Extension; break;
  490. default: assert(false);
  491. }
  492. StrPLCopy(DispInfo.pszText, Value, DispInfo.cchTextMax);
  493. }
  494. if (DispInfo.iSubItem == 0 && DispInfo.mask & LVIF_IMAGE)
  495. {
  496. DispInfo.iImage = File->IconIndex;
  497. DispInfo.mask |= LVIF_DI_SETITEM;
  498. }
  499. #endif
  500. }
  501. }
  502. //---------------------------------------------------------------------------
  503. void __fastcall TUnixDirView::PerformItemDragDropOperation(TListItem * Item, int Effect)
  504. {
  505. #ifndef DESIGN_ONLY
  506. assert(DragDropFilesEx);
  507. TTransferType Type;
  508. TCopyParamType CopyParams = Configuration->CopyParam;
  509. TStrings *FileList = NULL;
  510. AnsiString Directory;
  511. switch (Effect) {
  512. case DROPEFFECT_COPY: Type = ttCopy; break;
  513. case DROPEFFECT_MOVE: Type = ttMove; break;
  514. // occures on WinXP (reported by user)
  515. default: Type = ttCopy; //assert(false);
  516. };
  517. FileList = new TStringList();
  518. try
  519. {
  520. AnsiString SourceDirectory;
  521. for (int Index = 0; Index < DragDropFilesEx->FileList->Count; Index++)
  522. {
  523. AnsiString FileName = DragDropFilesEx->FileList->Items[Index]->Name;
  524. if (SourceDirectory.IsEmpty())
  525. {
  526. SourceDirectory = ExtractFilePath(FileName);
  527. }
  528. FileList->Add(FileName);
  529. }
  530. if (Item)
  531. {
  532. assert(ITEMFILE->IsDirectory && (Terminal->Files->IndexOf(ITEMFILE) >= 0));
  533. Directory = ITEMFILE->FullFileName;
  534. }
  535. else
  536. {
  537. Directory = Path;
  538. }
  539. bool DoFileOperation = true;
  540. if (OnDDFileOperation != NULL)
  541. {
  542. OnDDFileOperation(this, Effect, SourceDirectory, Directory,
  543. DoFileOperation);
  544. }
  545. if (DoFileOperation)
  546. {
  547. if (OnGetCopyParam)
  548. {
  549. OnGetCopyParam(this, tdToRemote, Type, Directory, FileList, CopyParams);
  550. }
  551. assert(Terminal);
  552. int Params = cpDragDrop;
  553. if (Type == ttMove) Params |= cpDelete;
  554. Terminal->CopyToRemote(FileList, Directory, &CopyParams, Params);
  555. if (OnDDFileOperationExecuted)
  556. {
  557. OnDDFileOperationExecuted(this, Effect, SourceDirectory, Directory);
  558. }
  559. // If target is current directory, we try to focus first dropped file
  560. if (!Item)
  561. {
  562. int RemoteIndex, DragIndex;
  563. for (RemoteIndex = 0; RemoteIndex < Items->Count; RemoteIndex++)
  564. {
  565. for (DragIndex = 0; DragIndex < FileList->Count; DragIndex++)
  566. {
  567. if (ItemFileName(Items->Item[RemoteIndex]) ==
  568. ExtractFileName(FileList->Strings[DragIndex]))
  569. {
  570. ItemFocused = Items->Item[RemoteIndex];
  571. // We need to break both FOR cycles
  572. RemoteIndex = Items->Count-1;
  573. break;
  574. }
  575. }
  576. }
  577. }
  578. }
  579. }
  580. __finally
  581. {
  582. delete FileList;
  583. }
  584. #endif
  585. }
  586. //---------------------------------------------------------------------------
  587. void __fastcall TUnixDirView::SetItemImageIndex(TListItem * /* Item */, int /* Index */)
  588. {
  589. // TCustomDirView::SetItemImageIndex is used for icon caching
  590. // so we don't need it here.
  591. }
  592. //---------------------------------------------------------------------------
  593. void __fastcall TUnixDirView::DDMenuDone(TObject* /* Sender */, HMENU /* AMenu */)
  594. {
  595. // TODO: Why I need to duplicate this method? (see TCustomDirView::DDMenuDone)
  596. }
  597. //---------------------------------------------------------------------------
  598. #ifndef DESIGN_ONLY
  599. void __fastcall TUnixDirView::SetTerminal(TTerminal *value)
  600. {
  601. if (FTerminal != value)
  602. {
  603. if (FTerminal)
  604. {
  605. assert(FTerminal->OnReadDirectory == DoReadDirectory);
  606. Terminal->OnReadDirectory = NULL;
  607. assert(FTerminal->OnChangeDirectory == DoChangeDirectory);
  608. FTerminal->OnChangeDirectory = NULL;
  609. if (!value || !value->Files->Loaded)
  610. {
  611. ClearItems();
  612. }
  613. }
  614. FTerminal = value;
  615. if (FTerminal)
  616. {
  617. FTerminal->OnReadDirectory = DoReadDirectory;
  618. FTerminal->OnChangeDirectory = DoChangeDirectory;
  619. FTerminal->Files->IncludeParentDirectory = AddParentDir;
  620. if (FTerminal->Files->Loaded)
  621. {
  622. DoChangeDirectory(FTerminal);
  623. DoReadDirectory(FTerminal, false);
  624. }
  625. }
  626. }
  627. }
  628. #endif
  629. //---------------------------------------------------------------------------
  630. void __fastcall TUnixDirView::DoReadDirectory(TObject * /*Sender*/, bool ReloadOnly)
  631. {
  632. #ifndef DESIGN_ONLY
  633. if (Terminal->Active)
  634. {
  635. if (ReloadOnly)
  636. {
  637. Reload(false);
  638. }
  639. else
  640. {
  641. Load();
  642. PathChanged();
  643. }
  644. }
  645. #endif
  646. }
  647. //---------------------------------------------------------------------------
  648. void __fastcall TUnixDirView::DoChangeDirectory(TObject * /*Sender*/)
  649. {
  650. #ifndef DESIGN_ONLY
  651. // Reload(false);
  652. #endif
  653. }
  654. //---------------------------------------------------------------------------
  655. bool __fastcall TUnixDirView::GetDirOK()
  656. {
  657. #ifndef DESIGN_ONLY
  658. return (Active && Terminal->Files->Loaded);
  659. #else
  660. return false;
  661. #endif
  662. }
  663. //---------------------------------------------------------------------------
  664. AnsiString __fastcall TUnixDirView::GetPathName()
  665. {
  666. #ifndef DESIGN_ONLY
  667. if (DirOK) return Terminal->CurrentDirectory;
  668. else
  669. #endif
  670. return "";
  671. }
  672. //---------------------------------------------------------------------------
  673. AnsiString __fastcall TUnixDirView::GetPath()
  674. {
  675. #ifndef DESIGN_ONLY
  676. if (DirOK) return UnixIncludeTrailingBackslash(Terminal->CurrentDirectory);
  677. else
  678. #endif
  679. return "";
  680. }
  681. //---------------------------------------------------------------------------
  682. void __fastcall TUnixDirView::SetPath(AnsiString Value)
  683. {
  684. #ifndef DESIGN_ONLY
  685. Value = UnixExcludeTrailingBackslash(
  686. StringReplace(Value, '\\', '/', TReplaceFlags() << rfReplaceAll));
  687. if (Active && (Terminal->CurrentDirectory != Value))
  688. {
  689. FLastPath = PathName;
  690. Terminal->CurrentDirectory = Value;
  691. }
  692. #endif
  693. }
  694. //---------------------------------------------------------------------------
  695. void __fastcall TUnixDirView::SortItems()
  696. {
  697. #ifndef DESIGN_ONLY
  698. assert(Terminal);
  699. if (HandleAllocated())
  700. {
  701. PFNLVCOMPARE SortProc;
  702. switch (SortColumn) {
  703. case uvName: SortProc = (PFNLVCOMPARE)CompareFileName; break;
  704. case uvSize: SortProc = (PFNLVCOMPARE)CompareSize; break;
  705. case uvChanged: SortProc = (PFNLVCOMPARE)CompareModification; break;
  706. case uvRights: SortProc = (PFNLVCOMPARE)CompareRightsStr; break;
  707. case uvOwner: SortProc = (PFNLVCOMPARE)CompareOwner; break;
  708. case uvGroup: SortProc = (PFNLVCOMPARE)CompareGroup; break;
  709. case uvExt: SortProc = (PFNLVCOMPARE)CompareExtension; break;
  710. default: assert(false);
  711. }
  712. CustomSortItems(SortProc);
  713. }
  714. #endif
  715. }
  716. //---------------------------------------------------------------------------
  717. bool __fastcall TUnixDirView::GetActive()
  718. {
  719. #ifndef DESIGN_ONLY
  720. return ((Terminal != NULL) && Terminal->Active);
  721. #else
  722. return false;
  723. #endif
  724. }
  725. //---------------------------------------------------------------------------
  726. AnsiString __fastcall TUnixDirView::GetUniqTempDir()
  727. {
  728. return UniqTempDir(DDTemporaryDirectory);
  729. }
  730. //---------------------------------------------------------------------------
  731. void __fastcall TUnixDirView::DDDragDetect(int grfKeyState,
  732. const TPoint &DetectStart, const TPoint &Point, TDragDetectStatus DragStatus)
  733. {
  734. if ((DragStatus == ddsDrag) && (!Loading) && (MarkedCount > 0))
  735. {
  736. assert(FDragDropSshTerminate.IsEmpty());
  737. FDragDropSshTerminate = "";
  738. assert(!FDDFileList);
  739. FDDFileList = NULL;
  740. try
  741. {
  742. FDDFileList = new TStringList();
  743. FUniqTempDir = GetUniqTempDir();
  744. TCustomUnixDirView::DDDragDetect(grfKeyState, DetectStart, Point, DragStatus);
  745. #ifndef DESIGN_ONLY
  746. if (!FDragDropSshTerminate.IsEmpty())
  747. {
  748. throw ESshTerminate(NULL, FDragDropSshTerminate);
  749. }
  750. #endif
  751. }
  752. __finally
  753. {
  754. FDragDropSshTerminate = "";
  755. SAFE_DESTROY(FDDFileList);
  756. }
  757. }
  758. }
  759. //---------------------------------------------------------------------------
  760. void __fastcall TUnixDirView::SetAddParentDir(bool Value)
  761. {
  762. if (Value != AddParentDir)
  763. {
  764. #ifndef DESIGN_ONLY
  765. if (Terminal) Terminal->Files->IncludeParentDirectory = Value;
  766. #endif
  767. TCustomUnixDirView::SetAddParentDir(Value);
  768. }
  769. }
  770. //---------------------------------------------------------------------------
  771. void __fastcall TUnixDirView::SetDDDeleteDelay(int value)
  772. {
  773. if (value < 0) value = -1;
  774. if (FDDDeleteDelay != value)
  775. {
  776. FDDDeleteDelay = value;
  777. }
  778. }
  779. //---------------------------------------------------------------------------
  780. bool __fastcall TUnixDirView::TargetHasDropHandler(TListItem * /* Item */, int /* Effect */)
  781. {
  782. return false;
  783. }
  784. //---------------------------------------------------------------------------
  785. void __fastcall TUnixDirView::DDGiveFeedback(int dwEffect, HRESULT & Result)
  786. {
  787. // Remember drop effect so we know (when user dropes files), if we copy or move
  788. FLastDropEffect = dwEffect;
  789. TCustomUnixDirView::DDGiveFeedback(dwEffect, Result);
  790. }
  791. //---------------------------------------------------------------------------
  792. void __fastcall TUnixDirView::DDChooseEffect(int grfKeyState, int &dwEffect)
  793. {
  794. if (DDOwnerIsSource)
  795. {
  796. dwEffect = (DropTarget != NULL) ? DROPEFFECT_Move : DROPEFFECT_None;
  797. }
  798. else if ((grfKeyState & (MK_CONTROL | MK_SHIFT)) == 0)
  799. {
  800. dwEffect = DROPEFFECT_Copy;
  801. }
  802. }
  803. //---------------------------------------------------------------------------
  804. void __fastcall TUnixDirView::DDQueryContinueDrag(BOOL FEscapePressed,
  805. int grfKeyState, HRESULT & Result)
  806. {
  807. #ifndef DESIGN_ONLY
  808. TCustomUnixDirView::DDQueryContinueDrag(FEscapePressed, grfKeyState, Result);
  809. if (Result == DRAGDROP_S_DROP)
  810. {
  811. try
  812. {
  813. GlobalDragImageList->HideDragImage();
  814. DDTargetDrop();
  815. }
  816. catch (Exception &E)
  817. {
  818. // If downloading fails we need to cancel drag&drop, othwerwise
  819. // Explorer shows error
  820. // But by the way exception probably never reach this point as
  821. // it's catched on way
  822. Result = DRAGDROP_S_CANCEL;
  823. ShowExtendedException(&E);
  824. }
  825. }
  826. #endif
  827. }
  828. //---------------------------------------------------------------------------
  829. void __fastcall TUnixDirView::DDTargetDrop()
  830. {
  831. #ifndef DESIGN_ONLY
  832. bool Continue = true;
  833. if (OnDDTargetDrop)
  834. {
  835. OnDDTargetDrop(this, FLastDropEffect, Continue);
  836. }
  837. if (Continue)
  838. {
  839. assert(!FUniqTempDir.IsEmpty());
  840. TTransferType Type;
  841. AnsiString TempDir = FUniqTempDir;
  842. // We clear FUniqTempDir before calling
  843. // just in case it fail (raises exception)
  844. FUniqTempDir = "";
  845. Type = (FLastDropEffect & DROPEFFECT_MOVE ? ttMove : Type = ttCopy);
  846. try
  847. {
  848. TStrings * FileList = new TStringList();
  849. try
  850. {
  851. assert(DragDropFilesEx);
  852. assert(FDDFileList);
  853. TRemoteFile * File;
  854. int FileIndex;
  855. for (int Index = 0; Index < DragDropFilesEx->FileList->Count; Index++)
  856. {
  857. FileIndex = FDDFileList->IndexOf(DragDropFilesEx->FileList->Items[Index]->Name);
  858. assert(FileIndex >= 0);
  859. File = dynamic_cast<TRemoteFile *>(FDDFileList->Objects[FileIndex]);
  860. assert(File);
  861. FileList->AddObject(File->FileName, File);
  862. }
  863. TCopyParamType CopyParams = Configuration->CopyParam;
  864. AnsiString TargetDir = "";
  865. if (OnGetCopyParam)
  866. {
  867. OnGetCopyParam(this, tdToLocal, Type,
  868. TargetDir /* empty directory parameter means temp directory -> don't display it! */,
  869. FileList, CopyParams);
  870. }
  871. bool TemporaryDownload = TargetDir.IsEmpty();
  872. bool Continue = true;
  873. if (TemporaryDownload)
  874. {
  875. DoWarnLackOfTempSpace(TempDir, FDDTotalSize, Continue);
  876. TargetDir = TempDir;
  877. }
  878. if (Continue)
  879. {
  880. if (TemporaryDownload)
  881. {
  882. if (ForceDirectories(TargetDir))
  883. {
  884. assert(Terminal && !TargetDir.IsEmpty());
  885. try
  886. {
  887. Terminal->CopyToLocal(FileList, TargetDir, &CopyParams,
  888. cpDragDrop | (Type == ttMove ? cpDelete : 0));
  889. }
  890. __finally
  891. {
  892. AddDelayedDirectoryDeletion(TargetDir, DDDeleteDelay);
  893. }
  894. }
  895. else
  896. {
  897. DragDropDirException(TargetDir);
  898. }
  899. }
  900. }
  901. else
  902. {
  903. Abort();
  904. }
  905. }
  906. __finally
  907. {
  908. delete FileList;
  909. }
  910. }
  911. catch(ESshTerminate & E)
  912. {
  913. assert(!E.MoreMessages); // not supported
  914. assert(!E.Message.IsEmpty());
  915. FDragDropSshTerminate = E.Message;
  916. }
  917. }
  918. #endif
  919. }
  920. //---------------------------------------------------------------------------
  921. void __fastcall TUnixDirView::SetDDAllowMove(bool value)
  922. {
  923. if (DDAllowMove != value)
  924. {
  925. assert(DragDropFilesEx);
  926. FDDAllowMove = value;
  927. DragDropFilesEx->SourceEffects = DragSourceEffects;
  928. }
  929. }
  930. //---------------------------------------------------------------------------
  931. TDropEffectSet __fastcall TUnixDirView::GetDragSourceEffects()
  932. {
  933. TDropEffectSet Result;
  934. Result << deCopy;
  935. if (DDAllowMove) Result << deMove;
  936. return Result;
  937. }
  938. //---------------------------------------------------------------------------
  939. void __fastcall TUnixDirView::ChangeDirectory(AnsiString Path)
  940. {
  941. AnsiString LastFile = "";
  942. if (ItemFocused) LastFile = ItemFileName(ItemFocused);
  943. ClearItems();
  944. DoAnimation(true);
  945. #ifndef DESIGN_ONLY
  946. try
  947. {
  948. FDirLoadedAfterChangeDir = false;
  949. if (Path == HOMEDIRECTORY)
  950. {
  951. Terminal->HomeDirectory();
  952. }
  953. else
  954. // this works even with LockInHome
  955. if (Path == ROOTDIRECTORY)
  956. {
  957. Terminal->CurrentDirectory = ROOTDIRECTORY;
  958. }
  959. else
  960. {
  961. Terminal->ChangeDirectory(Path);
  962. }
  963. }
  964. __finally
  965. {
  966. // changing directory failed, so we load again old directory
  967. if (!FDirLoadedAfterChangeDir)
  968. {
  969. FSelectFile = LastFile;
  970. Reload(false);
  971. };
  972. }
  973. #endif
  974. }
  975. //---------------------------------------------------------------------------
  976. bool __fastcall TUnixDirView::CanEdit(TListItem* Item)
  977. {
  978. #ifndef DESIGN_ONLY
  979. assert(Terminal);
  980. return TCustomUnixDirView::CanEdit(Item) && Terminal->IsCapable[fcRename];
  981. #else
  982. return false;
  983. #endif
  984. }
  985. //---------------------------------------------------------------------------
  986. void __fastcall TUnixDirView::InternalEdit(const tagLVITEMA & HItem)
  987. {
  988. #ifndef DESIGN_ONLY
  989. TListItem *Item = GetItemFromHItem(HItem);
  990. ASSERT_VALID_ITEM;
  991. FSelectFile = HItem.pszText;
  992. Terminal->RenameFile(ITEMFILE, HItem.pszText, true);
  993. #endif
  994. }
  995. //---------------------------------------------------------------------------
  996. void __fastcall TUnixDirView::CreateDirectory(AnsiString DirName)
  997. {
  998. #ifndef DESIGN_ONLY
  999. assert(Terminal);
  1000. // if file would be created in current directory, select it after reload
  1001. if (UnixExtractFileName(DirName) == DirName)
  1002. {
  1003. FSelectFile = DirName;
  1004. }
  1005. Terminal->CreateDirectory(DirName);
  1006. #endif
  1007. }
  1008. //---------------------------------------------------------------------------
  1009. AnsiString __fastcall TUnixDirView::MinimizePath(AnsiString Path, int Length)
  1010. {
  1011. return StringReplace(MinimizeName(
  1012. StringReplace(Path, '/', '\\', TReplaceFlags() << rfReplaceAll),
  1013. Canvas, Length), '\\', '/', TReplaceFlags() << rfReplaceAll);
  1014. }
  1015. //---------------------------------------------------------------------------
  1016. bool __fastcall TUnixDirView::GetIsRoot()
  1017. {
  1018. #ifndef DESIGN_ONLY
  1019. return (PathName == ROOTDIRECTORY);
  1020. #else
  1021. return false;
  1022. #endif
  1023. }
  1024. //---------------------------------------------------------------------------
  1025. TColor __fastcall TUnixDirView::ItemColor(TListItem * Item)
  1026. {
  1027. assert(Item);
  1028. #ifndef DESIGN_ONLY
  1029. if (DimmHiddenFiles && !Item->Selected && ITEMFILE->IsHidden)
  1030. {
  1031. return clGrayText;
  1032. }
  1033. else
  1034. #endif
  1035. {
  1036. return (TColor)clDefaultItemColor;
  1037. }
  1038. }
  1039. //---------------------------------------------------------------------------
  1040. TDateTime __fastcall TUnixDirView::ItemFileTime(TListItem * Item)
  1041. {
  1042. assert(Item);
  1043. #ifndef DESIGN_ONLY
  1044. return ITEMFILE->Modification;
  1045. #else
  1046. return Now();
  1047. #endif
  1048. }
  1049. //---------------------------------------------------------------------------
  1050. void __fastcall TUnixDirView::SetShowInaccesibleDirectories(bool value)
  1051. {
  1052. if (FShowInaccesibleDirectories != value)
  1053. {
  1054. FShowInaccesibleDirectories = value;
  1055. if (DirOK) Reload(false);
  1056. }
  1057. }
  1058. //---------------------------------------------------------------------------
  1059. void __fastcall TUnixDirView::DoWarnLackOfTempSpace(const AnsiString Path,
  1060. __int64 RequiredSpace, bool & Continue)
  1061. {
  1062. if (FOnWarnLackOfTempSpace)
  1063. {
  1064. FOnWarnLackOfTempSpace(this, Path, RequiredSpace, Continue);
  1065. }
  1066. }
  1067. //---------------------------------------------------------------------------
  1068. void __fastcall TUnixDirView::AddToDragFileList(TFileList* FileList, TListItem* Item)
  1069. {
  1070. #ifndef DESIGN_ONLY
  1071. if (FileList->Count == 0) FDDTotalSize = 0;
  1072. if (FDDTotalSize >= 0)
  1073. {
  1074. if (ItemIsDirectory(Item))
  1075. {
  1076. FDDTotalSize = -1;
  1077. }
  1078. else
  1079. {
  1080. FDDTotalSize += ItemFileSize(Item);
  1081. }
  1082. }
  1083. FDDFileList->AddObject(ItemDragFileName(Item), ITEMFILE);
  1084. TCustomUnixDirView::AddToDragFileList(FileList, Item);
  1085. #endif
  1086. }