UnixDirView.cpp 33 KB

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