ScpCommander.cpp 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include "ScpCommander.h"
  5. #include <Common.h>
  6. #include <Net.h>
  7. #include <ScpMain.h>
  8. #include <Interface.h>
  9. #include <TextsWin.h>
  10. #include <VCLCommon.h>
  11. #include <GUITools.h>
  12. #include <DragDrop.hpp>
  13. #include "NonVisual.h"
  14. #include "Tools.h"
  15. #include "WinConfiguration.h"
  16. #include "TerminalManager.h"
  17. //---------------------------------------------------------------------------
  18. #pragma package(smart_init)
  19. #pragma link "AssociatedStatusBar"
  20. #pragma link "CustomDirView"
  21. #pragma link "CustomScpExplorer"
  22. #pragma link "CustomUnixDirView"
  23. #pragma link "IEListView"
  24. #pragma link "NortonLikeListView"
  25. #pragma link "UnixDirView"
  26. #pragma link "DirView"
  27. #pragma link "CustomPathComboBox"
  28. #pragma link "IEComboBox"
  29. #pragma link "IEPathComboBox"
  30. #pragma link "PathLabel"
  31. #pragma link "UnixPathComboBox"
  32. #pragma link "ToolbarPanel"
  33. #pragma link "HistoryComboBox"
  34. #pragma resource "*.dfm"
  35. //---------------------------------------------------------------------------
  36. __fastcall TScpCommanderForm::TScpCommanderForm(TComponent* Owner)
  37. : TCustomScpExplorerForm(Owner)
  38. {
  39. FLastDirView = LocalDirView;
  40. FLastLocalPanelWidth = LocalPanelWidth;
  41. FSynchronization = ssStopped;
  42. FSynchronizeDialog = NULL;
  43. FSynchronisingBrowse = false;
  44. FFirstTerminal = true;
  45. FInternalDDDownloadList = new TStringList();
  46. LocalBackButton->DropdownMenu = LocalDirView->BackMenu;
  47. LocalForwardButton->DropdownMenu = LocalDirView->ForwardMenu;
  48. RemoteBackButton->DropdownMenu = RemoteDirView->BackMenu;
  49. RemoteForwardButton->DropdownMenu = RemoteDirView->ForwardMenu;
  50. SavedSessionsButton->OnClick = DropDownButtonMenu;
  51. TopCoolBar->PopupMenu = NonVisualDataModule->CommanderBarPopup;
  52. ToolbarPanel->PopupMenu = TopCoolBar->PopupMenu;
  53. StatusBar->PopupMenu = TopCoolBar->PopupMenu;
  54. LocalCoolBar->PopupMenu = NonVisualDataModule->LocalPanelPopup;
  55. LocalPathLabel->PopupMenu = LocalCoolBar->PopupMenu;
  56. LocalStatusBar->PopupMenu = LocalCoolBar->PopupMenu;
  57. RemoteCoolBar->PopupMenu = NonVisualDataModule->RemotePanelPopup;
  58. RemotePathLabel->PopupMenu = RemoteCoolBar->PopupMenu;
  59. RemoteStatusBar->PopupMenu = RemoteCoolBar->PopupMenu;
  60. // set common norton shorcuts to our actions
  61. NonVisualDataModule->CommanderShortcuts();
  62. Splitter->ShowHint = True;
  63. ((TLabel*)Splitter)->OnDblClick = SplitterDblClick;
  64. RemotePathComboBox->TabStop = False;
  65. CommandLineLabel->FocusControl = CommandLineCombo;
  66. CommandLineCombo->Text = "";
  67. FCommandLineComboPopulated = false;
  68. LocalDirView->Font = Screen->IconFont;
  69. }
  70. //---------------------------------------------------------------------------
  71. __fastcall TScpCommanderForm::~TScpCommanderForm()
  72. {
  73. delete FInternalDDDownloadList;
  74. }
  75. //---------------------------------------------------------------------------
  76. void __fastcall TScpCommanderForm::RestoreFormParams()
  77. {
  78. assert(WinConfiguration);
  79. TCustomScpExplorerForm::RestoreFormParams();
  80. WinConfiguration->RestoreForm(WinConfiguration->ScpCommander.WindowParams, this);
  81. }
  82. //---------------------------------------------------------------------------
  83. void __fastcall TScpCommanderForm::RestoreParams()
  84. {
  85. assert(Configuration);
  86. // called later once again after menu font is updated (see FormShow)
  87. SetCoolBandsMinWidth(TopCoolBar);
  88. SetCoolBandsMinWidth(LocalCoolBar);
  89. SetCoolBandsMinWidth(RemoteCoolBar);
  90. // IDE often looses this link
  91. LocalDirView->HeaderImages = NonVisualDataModule->ArrowImages;
  92. TCustomScpExplorerForm::RestoreParams();
  93. LocalPanelWidth = WinConfiguration->ScpCommander.LocalPanelWidth;
  94. LoadCoolbarLayoutStr(TopCoolBar, WinConfiguration->ScpCommander.CoolBarLayout);
  95. StatusBar->Visible = WinConfiguration->ScpCommander.StatusBar;
  96. ToolbarPanel->Visible = WinConfiguration->ScpCommander.ToolBar;
  97. CommandLinePanel->Visible = WinConfiguration->ScpCommander.CommandLine;
  98. FDirViewToSelect = (WinConfiguration->ScpCommander.CurrentPanel == osLocal ?
  99. (TCustomDirView *)LocalDirView : (TCustomDirView *)RemoteDirView);
  100. #define RESTORE_PANEL_PARAMS(PANEL) \
  101. PANEL ## DirView->ColProperties->ParamsStr = WinConfiguration->ScpCommander.PANEL ## Panel.DirViewParams; \
  102. PANEL ## StatusBar->Visible = WinConfiguration->ScpCommander.PANEL ## Panel.StatusBar; \
  103. LoadCoolbarLayoutStr(PANEL ## CoolBar, WinConfiguration->ScpCommander.PANEL ## Panel.CoolBarLayout)
  104. RESTORE_PANEL_PARAMS(Local);
  105. RESTORE_PANEL_PARAMS(Remote);
  106. #undef RESTORE_PANEL_PARAMS
  107. NonVisualDataModule->SynchronizeBrowsingAction->Checked = WinConfiguration->ScpCommander.SynchronizeBrowsing;
  108. }
  109. //---------------------------------------------------------------------------
  110. void __fastcall TScpCommanderForm::StoreParams()
  111. {
  112. assert(WinConfiguration);
  113. WinConfiguration->BeginUpdate();
  114. try
  115. {
  116. WinConfiguration->ScpCommander.CoolBarLayout = GetCoolbarLayoutStr(TopCoolBar);
  117. WinConfiguration->ScpCommander.LocalPanelWidth = LocalPanelWidth;
  118. WinConfiguration->ScpCommander.StatusBar = StatusBar->Visible;
  119. WinConfiguration->ScpCommander.ToolBar = ToolbarPanel->Visible;
  120. WinConfiguration->ScpCommander.CommandLine = CommandLinePanel->Visible;
  121. SaveCommandLine();
  122. WinConfiguration->ScpCommander.CurrentPanel =
  123. ((FLastDirView == LocalDirView) ? osLocal : osRemote);
  124. #define STORE_PANEL_PARAMS(PANEL) \
  125. WinConfiguration->ScpCommander.PANEL ## Panel.DirViewParams = PANEL ## DirView->ColProperties->ParamsStr; \
  126. WinConfiguration->ScpCommander.PANEL ## Panel.StatusBar = PANEL ## StatusBar->Visible; \
  127. WinConfiguration->ScpCommander.PANEL ## Panel.CoolBarLayout = GetCoolbarLayoutStr(PANEL ## CoolBar)
  128. STORE_PANEL_PARAMS(Local);
  129. STORE_PANEL_PARAMS(Remote);
  130. #undef RESTORE_PANEL_PARAMS
  131. WinConfiguration->ScpCommander.WindowParams = WinConfiguration->StoreForm(this);;
  132. WinConfiguration->ScpCommander.SynchronizeBrowsing = NonVisualDataModule->SynchronizeBrowsingAction->Checked;
  133. TCustomScpExplorerForm::StoreParams();
  134. }
  135. __finally
  136. {
  137. WinConfiguration->EndUpdate();
  138. }
  139. }
  140. //---------------------------------------------------------------------------
  141. void __fastcall TScpCommanderForm::UpdateSessionData(TSessionData * Data)
  142. {
  143. assert(Terminal && Terminal->SessionData);
  144. if (!Data)
  145. {
  146. Data = Terminal->SessionData;
  147. }
  148. TCustomScpExplorerForm::UpdateSessionData(Data);
  149. assert(LocalDirView);
  150. Data->LocalDirectory = LocalDirView->PathName;
  151. }
  152. //---------------------------------------------------------------------------
  153. bool __fastcall TScpCommanderForm::InternalDDDownload(AnsiString & TargetDirectory)
  154. {
  155. bool Result = false;
  156. if (LocalDirView->DropTarget)
  157. {
  158. // when drop target is not directory, it is probably file type, which have
  159. // associated drop handler (such as ZIP file in WinXP). in this case we
  160. // must leave drop handling to destination application.
  161. // ! this check is duplicated in LocalDirViewDDTargetHasDropHandler()
  162. // for shellex downloads
  163. if (LocalDirView->ItemIsDirectory(LocalDirView->DropTarget))
  164. {
  165. TargetDirectory = LocalDirView->ItemFullFileName(LocalDirView->DropTarget);
  166. Result = true;
  167. }
  168. }
  169. else
  170. {
  171. TargetDirectory = IncludeTrailingBackslash(LocalDirView->Path);
  172. Result = true;
  173. }
  174. return Result;
  175. }
  176. //---------------------------------------------------------------------------
  177. bool __fastcall TScpCommanderForm::CopyParamDialog(TTransferDirection Direction,
  178. TTransferType Type, bool DragDrop, TStrings * FileList, AnsiString & TargetDirectory,
  179. TCopyParamType & CopyParam, bool Confirm)
  180. {
  181. bool Result = false;
  182. if (DragDrop && (Direction == tdToLocal) && (FDDTargetDirView == LocalDirView))
  183. {
  184. Result = InternalDDDownload(TargetDirectory);
  185. if (Result)
  186. {
  187. assert(FileList->Count > 0);
  188. FInternalDDDownloadList->Assign(FileList);
  189. }
  190. }
  191. else if (!DragDrop && TargetDirectory.IsEmpty())
  192. {
  193. if (Direction == tdToLocal)
  194. {
  195. TargetDirectory = IncludeTrailingBackslash(LocalDirView->Path);
  196. }
  197. else
  198. {
  199. TargetDirectory = UnixIncludeTrailingBackslash(RemoteDirView->Path);
  200. }
  201. }
  202. if (!Result)
  203. {
  204. Result = TCustomScpExplorerForm::CopyParamDialog(Direction, Type, DragDrop,
  205. FileList, TargetDirectory, CopyParam, Confirm);
  206. }
  207. return Result;
  208. }
  209. //---------------------------------------------------------------------------
  210. void __fastcall TScpCommanderForm::FormShow(TObject */*Sender*/)
  211. {
  212. assert(FDirViewToSelect);
  213. FDirViewToSelect->SetFocus();
  214. // called for second time after menu font was updated (see also RestoreParams)
  215. SetCoolBandsMinWidth(TopCoolBar);
  216. SetCoolBandsMinWidth(LocalCoolBar);
  217. SetCoolBandsMinWidth(RemoteCoolBar);
  218. UpdateControls();
  219. }
  220. //---------------------------------------------------------------------------
  221. Boolean __fastcall TScpCommanderForm::AllowedAction(TAction * Action, TActionAllowed Allowed)
  222. {
  223. #define FLAG ((TActionFlag)(Action->Tag))
  224. return
  225. // always require Commander flag
  226. (FLAG & afCommander) &&
  227. // if action is execution or update, we don't require any other flag
  228. // if we check for shortcut, we require proper dirview to be selected
  229. ((Allowed != aaShortCut) ||
  230. ((FLAG & afLocal) && (FLastDirView == LocalDirView)) ||
  231. ((FLAG & afRemote) && (FLastDirView == RemoteDirView))
  232. );
  233. #undef FLAG
  234. }
  235. //---------------------------------------------------------------------------
  236. TCustomDirView * __fastcall TScpCommanderForm::DirView(TOperationSide Side)
  237. {
  238. switch (Side) {
  239. case osCurrent: return FLastDirView;
  240. case osLocal: return LocalDirView;
  241. case osRemote: return RemoteDirView;
  242. default: assert(false); return NULL;
  243. }
  244. }
  245. //---------------------------------------------------------------------------
  246. TOperationSide __fastcall TScpCommanderForm::GetSide(TOperationSide Side)
  247. {
  248. if (Side == osCurrent)
  249. {
  250. if (FLastDirView == RemoteDirView)
  251. {
  252. Side = osRemote;
  253. }
  254. else
  255. {
  256. assert(FLastDirView);
  257. Side = osLocal;
  258. }
  259. }
  260. return TCustomScpExplorerForm::GetSide(Side);
  261. }
  262. //---------------------------------------------------------------------------
  263. void __fastcall TScpCommanderForm::TerminalChanged()
  264. {
  265. if (Terminal)
  266. {
  267. bool WasSynchronisingBrowsing = NonVisualDataModule->SynchronizeBrowsingAction->Checked;
  268. NonVisualDataModule->SynchronizeBrowsingAction->Checked = false;
  269. TCustomScpExplorerForm::TerminalChanged();
  270. if (FFirstTerminal || !WinConfiguration->ScpCommander.PreserveLocalDirectory)
  271. {
  272. AnsiString LocalDirectory = Terminal->SessionData->LocalDirectory;
  273. bool DocumentsDir = LocalDirectory.IsEmpty();
  274. if (!DocumentsDir)
  275. {
  276. try
  277. {
  278. LocalDirView->Path = LocalDirectory;
  279. }
  280. catch(Exception & E)
  281. {
  282. DocumentsDir = true;
  283. ShowExtendedException(&E, this);
  284. }
  285. }
  286. if (DocumentsDir)
  287. {
  288. try
  289. {
  290. LocalDirView->HomeDirectory = "";
  291. LocalDirView->ExecuteHomeDirectory();
  292. }
  293. catch(Exception & E)
  294. {
  295. ShowExtendedException(&E, this);
  296. LocalDirView->Path = ExtractFilePath(Application->ExeName);
  297. }
  298. }
  299. if (Configuration->DefaultDirIsHome &&
  300. !Terminal->SessionData->UpdateDirectories)
  301. {
  302. LocalDirView->HomeDirectory = LocalDirectory;
  303. }
  304. }
  305. FFirstTerminal = false;
  306. if (WasSynchronisingBrowsing &&
  307. SameText(ExtractFileName(LocalDirView->PathName),
  308. UnixExtractFileName(RemoteDirView->PathName)))
  309. {
  310. NonVisualDataModule->SynchronizeBrowsingAction->Checked = true;
  311. }
  312. }
  313. else
  314. {
  315. TCustomScpExplorerForm::TerminalChanged();
  316. }
  317. }
  318. //---------------------------------------------------------------------------
  319. void __fastcall TScpCommanderForm::ConfigurationChanged()
  320. {
  321. TCustomScpExplorerForm::ConfigurationChanged();
  322. if (Configuration->DefaultDirIsHome && Terminal)
  323. {
  324. LocalDirView->HomeDirectory = Terminal->SessionData->LocalDirectory;
  325. }
  326. else
  327. {
  328. LocalDirView->HomeDirectory = "";
  329. }
  330. LocalDirView->DimmHiddenFiles = WinConfiguration->DimmHiddenFiles;
  331. LocalDirView->ShowHiddenFiles = WinConfiguration->ShowHiddenFiles;
  332. LocalDirView->NortonLike = !WinConfiguration->ScpCommander.ExplorerStyleSelection;
  333. RemoteDirView->NortonLike = !WinConfiguration->ScpCommander.ExplorerStyleSelection;
  334. LocalDirView->DragDropFilesEx->ShellExtensions->DropHandler =
  335. !WinConfiguration->DDExtEnabled;
  336. }
  337. //---------------------------------------------------------------------------
  338. void __fastcall TScpCommanderForm::SetLocalPanelWidth(float value)
  339. {
  340. float Total = LocalPanel->Width + RemotePanel->Width;
  341. FLocalPanelWidth = value;
  342. if (value * Total != LocalPanel->Width)
  343. {
  344. LocalPanel->Width = value * Total;
  345. UpdateControls();
  346. }
  347. }
  348. //---------------------------------------------------------------------------
  349. float __fastcall TScpCommanderForm::GetLocalPanelWidth()
  350. {
  351. return FLocalPanelWidth;
  352. }
  353. //---------------------------------------------------------------------------
  354. void __fastcall TScpCommanderForm::SplitterMoved(TObject * /*Sender*/)
  355. {
  356. float Local = LocalPanel->Width;
  357. float Total = LocalPanel->Width + RemotePanel->Width;
  358. FLocalPanelWidth = Local / Total;
  359. FLastLocalPanelWidth = LocalPanelWidth;
  360. UpdateControls();
  361. }
  362. //---------------------------------------------------------------------------
  363. void __fastcall TScpCommanderForm::SplitterCanResize(TObject * /*Sender*/,
  364. int &NewSize, bool & /*Accept*/)
  365. {
  366. // When splitter is drag so far to right, that width contraint of remote panel would
  367. // be violated, it doesn't stop, but extend form width.
  368. // Following prevents this behaviour.
  369. if (ClientWidth - NewSize - Splitter->Width < RemotePanel->Constraints->MinWidth)
  370. NewSize = (ClientWidth - RemotePanel->Constraints->MinWidth - Splitter->Width);
  371. }
  372. //---------------------------------------------------------------------------
  373. void __fastcall TScpCommanderForm::SplitterDblClick(TObject * /*Sender*/)
  374. {
  375. LocalPanelWidth = 0.5;
  376. }
  377. //---------------------------------------------------------------------------
  378. void __fastcall TScpCommanderForm::UpdateControls()
  379. {
  380. Splitter->Hint = FormatFloat("0%|X", LocalPanelWidth*100);
  381. if (FLastDirView != NULL)
  382. {
  383. CommandLineLabel->UnixPath = (FLastDirView == RemoteDirView);
  384. CommandLineLabel->Caption = FLastDirView->PathName;
  385. CommandLinePromptLabel->Caption =
  386. (FLastDirView == RemoteDirView) ? "$" : ">";
  387. EnableControl(CommandLineCombo,
  388. (FLastDirView == LocalDirView) || Terminal->IsCapable[fcAnyCommand]);
  389. }
  390. }
  391. //---------------------------------------------------------------------------
  392. void __fastcall TScpCommanderForm::ChangePath(TOperationSide Side)
  393. {
  394. assert((Side == osLocal) || (Side == osRemote));
  395. TCustomPathComboBox * PathComboBox;
  396. if (Side == osLocal) PathComboBox = LocalPathComboBox;
  397. else PathComboBox = RemotePathComboBox;
  398. assert(PathComboBox);
  399. PathComboBox->SetFocus();
  400. PathComboBox->DroppedDown = True;
  401. }
  402. //---------------------------------------------------------------------------
  403. void __fastcall TScpCommanderForm::PathComboBoxCloseUp(TObject * /*Sender*/,
  404. bool /*Canceled*/)
  405. {
  406. assert(FLastDirView);
  407. FLastDirView->SetFocus();
  408. }
  409. //---------------------------------------------------------------------------
  410. void __fastcall TScpCommanderForm::SessionComboCloseUp(TObject *Sender)
  411. {
  412. PathComboBoxCloseUp(Sender, false);
  413. }
  414. //---------------------------------------------------------------------------
  415. void __fastcall TScpCommanderForm::FormResize(TObject * /*Sender*/)
  416. {
  417. LocalPanelWidth = FLastLocalPanelWidth;
  418. UpdateControls();
  419. }
  420. //---------------------------------------------------------------------------
  421. TControl * __fastcall TScpCommanderForm::GetComponent(Byte Component)
  422. {
  423. switch (Component) {
  424. case fcToolBar: return ToolbarPanel;
  425. case fcStatusBar: return StatusBar;
  426. case fcLocalCoolBar: return LocalCoolBar;
  427. case fcLocalStatusBar: return LocalStatusBar;
  428. case fcRemoteCoolBar: return RemoteCoolBar;
  429. case fcRemoteStatusBar: return RemoteStatusBar;
  430. case fcSessionCombo: return SessionCombo;
  431. case fcMenuToolBar: return MenuToolBar;
  432. case fcCommandLinePanel: return CommandLinePanel;
  433. default: return TCustomScpExplorerForm::GetComponent(Component);
  434. }
  435. }
  436. //---------------------------------------------------------------------------
  437. void __fastcall TScpCommanderForm::SetComponentVisible(Word Component, Boolean value)
  438. {
  439. TCustomScpExplorerForm::SetComponentVisible(Component, value);
  440. if ((StatusBar->Top < ToolbarPanel->Top) && ToolbarPanel->Visible)
  441. {
  442. StatusBar->Top = ToolbarPanel->Top + ToolbarPanel->Height;
  443. }
  444. if ((ToolbarPanel->Top < CommandLinePanel->Top) && CommandLinePanel->Visible)
  445. {
  446. ToolbarPanel->Top = CommandLinePanel->Top + CommandLinePanel->Height;
  447. }
  448. if (LocalDirView->ItemFocused != NULL)
  449. {
  450. LocalDirView->ItemFocused->MakeVisible(false);
  451. }
  452. }
  453. //---------------------------------------------------------------------------
  454. bool __fastcall TScpCommanderForm::GetHasDirView(TOperationSide Side)
  455. {
  456. return TCustomScpExplorerForm::GetHasDirView(Side) || (Side == osLocal);
  457. }
  458. //---------------------------------------------------------------------------
  459. void __fastcall TScpCommanderForm::CompareDirectories()
  460. {
  461. LocalDirView->CompareFiles(RemoteDirView, false,
  462. WinConfiguration->ScpCommander.CompareCriterias());
  463. RemoteDirView->CompareFiles(LocalDirView, false,
  464. WinConfiguration->ScpCommander.CompareCriterias());
  465. if (LocalDirView->SelCount + RemoteDirView->SelCount == 0)
  466. {
  467. MessageDialog(LoadStr(COMPARE_NO_DIFFERENCES), qtInformation, qaOK, 0);
  468. }
  469. }
  470. //---------------------------------------------------------------------------
  471. void __fastcall TScpCommanderForm::SynchronizeDirectories()
  472. {
  473. TSynchronizeParamType Params;
  474. Params.CopyParams.Assign(Configuration->CopyParam);
  475. Params.AllowTransferMode = Terminal->IsCapable[fcTextMode];
  476. if (!Params.AllowTransferMode)
  477. {
  478. Params.CopyParams.TransferMode = tmBinary;
  479. }
  480. Params.LocalDirectory = LocalDirView->PathName;
  481. Params.RemoteDirectory = RemoteDirView->PathName;
  482. DoSynchronizeDialog(Params, SynchronizeStartStop);
  483. }
  484. //---------------------------------------------------------------------------
  485. void __fastcall TScpCommanderForm::SynchronizeStartStop(System::TObject* Sender,
  486. bool Start, TSynchronizeParamType Params)
  487. {
  488. FSynchronization = (Start ? ssWaiting : ssStopped);
  489. if (Start)
  490. {
  491. FSynchronizeDialog = (TSynchronizeDialog *)Sender;
  492. FSynchronizeParams = Params;
  493. SynchronizeNow();
  494. }
  495. else
  496. {
  497. FSynchronizeDialog = NULL;
  498. }
  499. }
  500. //---------------------------------------------------------------------------
  501. void __fastcall TScpCommanderForm::FullSynchronizeDirectories()
  502. {
  503. AnsiString LocalDirectory = LocalDirView->PathName;
  504. AnsiString RemoteDirectory = RemoteDirView->PathName;
  505. TSynchronizeMode Mode = (FLastDirView == LocalDirView) ? smRemote : smLocal;
  506. DoFullSynchronizeDirectories(LocalDirectory, RemoteDirectory, Mode);
  507. }
  508. //---------------------------------------------------------------------------
  509. void __fastcall TScpCommanderForm::LocalDirViewChangeDetected(
  510. TObject * /*Sender*/)
  511. {
  512. switch (FSynchronization) {
  513. case ssWaiting: SynchronizeNow(); break;
  514. case ssSynchronizing: FSynchronization = ssSynchronize; break;
  515. }
  516. }
  517. //---------------------------------------------------------------------------
  518. void __fastcall TScpCommanderForm::SynchronizeNow()
  519. {
  520. try
  521. {
  522. TStrings * ChangedFiles;
  523. FSynchronization = ssSynchronize;
  524. try
  525. {
  526. // repeat until there is any change pending (see ::LocalDirViewChangeDetected)
  527. while (FSynchronization == ssSynchronize)
  528. {
  529. FSynchronization = ssSynchronizing;
  530. assert(FSynchronizeDialog);
  531. ChangedFiles = LocalDirView->CreateChangedFileList(
  532. RemoteDirView, true, FSynchronizeDialog->ExistingOnly,
  533. WinConfiguration->ScpCommander.CompareCriterias());
  534. Terminal->ExceptionOnFail = true;
  535. try
  536. {
  537. if (ChangedFiles->Count > 0)
  538. {
  539. Terminal->CopyToRemote(ChangedFiles, FSynchronizeParams.RemoteDirectory,
  540. &FSynchronizeParams.CopyParams, 0);
  541. }
  542. }
  543. __finally
  544. {
  545. delete ChangedFiles;
  546. Terminal->ExceptionOnFail = false;
  547. }
  548. }
  549. }
  550. __finally
  551. {
  552. FSynchronization = ssWaiting;
  553. }
  554. }
  555. catch (EFatal & E)
  556. {
  557. throw;
  558. }
  559. catch(Exception & E)
  560. {
  561. assert(FSynchronizeDialog);
  562. FSynchronizeDialog->Stop();
  563. ShowExtendedException(&E);
  564. }
  565. }
  566. //---------------------------------------------------------------------------
  567. void __fastcall TScpCommanderForm::DoOperationFinished(
  568. ::TFileOperation Operation, TOperationSide Side,
  569. bool DragDrop, const AnsiString FileName, bool Success,
  570. bool & DisconnectWhenFinished)
  571. {
  572. if (FSynchronization == ssStopped)
  573. {
  574. TCustomScpExplorerForm::DoOperationFinished(Operation, Side, DragDrop,
  575. FileName, Success, DisconnectWhenFinished);
  576. }
  577. }
  578. //---------------------------------------------------------------------------
  579. void __fastcall TScpCommanderForm::ExploreLocalDirectory()
  580. {
  581. if ((int)ShellExecute(Application->Handle, "explore",
  582. (char*)LocalDirView->Path.data(), NULL, NULL, SW_SHOWNORMAL) <= 32)
  583. {
  584. throw Exception(FORMAT(EXPLORE_LOCAL_DIR_ERROR, (LocalDirView->Path)));
  585. }
  586. }
  587. //---------------------------------------------------------------------------
  588. void __fastcall TScpCommanderForm::LocalDirViewExecFile(TObject *Sender,
  589. TListItem *Item, bool &AllowExec)
  590. {
  591. assert(Item);
  592. if ((UpperCase(PFileRec(Item->Data)->FileExt) == "LNK") &&
  593. DirectoryExists(ResolveFileShortCut(LocalDirView->ItemFullFileName(Item), true)))
  594. {
  595. AllowExec = true;
  596. }
  597. else
  598. {
  599. DoDirViewExecFile(Sender, Item, AllowExec);
  600. }
  601. }
  602. //---------------------------------------------------------------------------
  603. void __fastcall TScpCommanderForm::LocalDirViewDDDragEnter(TObject *Sender,
  604. IDataObject *DataObj, int grfKeyState, TPoint &Point, int &dwEffect,
  605. bool &Accept)
  606. {
  607. // LocalDirViewDDDragEnter is duplication of
  608. // TCustomScpExplorerForm::DirViewDDDragEnter, but it differs in
  609. // literal type of 'DataObj' parameter.Actual type is however same
  610. DirViewDDDragEnter(Sender, DataObj, grfKeyState, Point, dwEffect, Accept);
  611. }
  612. //---------------------------------------------------------------------------
  613. void __fastcall TScpCommanderForm::FileOperationProgress(
  614. TFileOperationProgressType & ProgressData, TCancelStatus & Cancel)
  615. {
  616. // Heuristic: When operation finishes and DD targed is local dir view,
  617. // we suppose that drag&drop download finished, so local dir view should be
  618. // reloaded
  619. if (!ProgressData.InProgress && FProgressForm &&
  620. (FDDTargetDirView == LocalDirView))
  621. {
  622. LocalDirView->ReloadDirectory();
  623. }
  624. TCustomScpExplorerForm::FileOperationProgress(ProgressData, Cancel);
  625. }
  626. //---------------------------------------------------------------------------
  627. void __fastcall TScpCommanderForm::DirViewLoaded(TObject *Sender)
  628. {
  629. UpdateControls();
  630. try
  631. {
  632. TCustomDirView * ADirView = dynamic_cast<TCustomDirView *>(Sender);
  633. assert(ADirView);
  634. AnsiString PrevPath = FPrevPath[ADirView == LocalDirView];
  635. FPrevPath[ADirView == LocalDirView] = ADirView->Path;
  636. if (!FSynchronisingBrowse && NonVisualDataModule->SynchronizeBrowsingAction->Checked &&
  637. !PrevPath.IsEmpty() && PrevPath != ADirView->Path)
  638. {
  639. FSynchronisingBrowse = true;
  640. if (ADirView == LocalDirView)
  641. {
  642. Terminal->ExceptionOnFail = true;
  643. try
  644. {
  645. if (PrevPath == ExcludeTrailingBackslash(ExtractFilePath(LocalDirView->Path)))
  646. {
  647. RemoteDirView->Path = RemoteDirView->Path + ExtractFileName(LocalDirView->Path);
  648. }
  649. else if (ExcludeTrailingBackslash(ExtractFilePath(PrevPath)) ==
  650. ExcludeTrailingBackslash(LocalDirView->PathName))
  651. {
  652. if (RemoteDirView->IsRoot)
  653. {
  654. Abort();
  655. }
  656. RemoteDirView->Path = UnixExtractFilePath(RemoteDirView->PathName);
  657. }
  658. else
  659. {
  660. Abort();
  661. }
  662. }
  663. __finally
  664. {
  665. Terminal->ExceptionOnFail = false;
  666. }
  667. }
  668. else
  669. {
  670. if (PrevPath == UnixExtractFilePath(RemoteDirView->PathName))
  671. {
  672. LocalDirView->Path = IncludeTrailingBackslash(LocalDirView->Path) +
  673. UnixExtractFileName(RemoteDirView->PathName);
  674. }
  675. else if (UnixExtractFilePath(UnixExcludeTrailingBackslash(PrevPath)) == RemoteDirView->Path)
  676. {
  677. if (LocalDirView->IsRoot)
  678. {
  679. Abort();
  680. }
  681. LocalDirView->Path = ExtractFilePath(LocalDirView->Path);
  682. }
  683. else
  684. {
  685. Abort();
  686. }
  687. }
  688. FSynchronisingBrowse = false;
  689. }
  690. }
  691. catch(Exception & E)
  692. {
  693. FSynchronisingBrowse = false;
  694. NonVisualDataModule->SynchronizeBrowsingAction->Checked = false;
  695. if (!Application->Terminated)
  696. {
  697. ShowExtendedException(&E);
  698. MessageDialog(LoadStr(SYNC_DIR_BROWSE_ERROR), qtInformation, qaOK, 0);
  699. }
  700. else
  701. {
  702. throw;
  703. }
  704. }
  705. }
  706. //---------------------------------------------------------------------------
  707. void __fastcall TScpCommanderForm::AddEditLink()
  708. {
  709. if (FLastDirView == LocalDirView)
  710. {
  711. bool Edit = false;
  712. AnsiString FileName;
  713. AnsiString PointTo;
  714. bool SymbolicLink = true;
  715. if (LocalDirView->ItemFocused)
  716. {
  717. assert(LocalDirView->ItemFocused->Data);
  718. PFileRec FileRec = (PFileRec)LocalDirView->ItemFocused->Data;
  719. Edit = UpperCase(FileRec->FileExt) == "LNK";
  720. if (Edit)
  721. {
  722. AnsiString FullName = LocalDirView->ItemFullFileName(LocalDirView->ItemFocused);
  723. FileName = FullName;//FileRec->FileName;
  724. PointTo = ResolveFileShortCut(FullName, false);
  725. if (PointTo.IsEmpty())
  726. {
  727. throw Exception(FMTLOAD(RESOLVE_SHORTCUT_ERROR, (FullName)));
  728. }
  729. }
  730. else
  731. {
  732. PointTo = FileRec->FileName;
  733. }
  734. }
  735. if (DoSymlinkDialog(FileName, PointTo, osLocal, SymbolicLink, Edit, false))
  736. {
  737. assert(SymbolicLink);
  738. assert(!FileName.IsEmpty());
  739. assert(!PointTo.IsEmpty());
  740. if (ExtractFileDrive(FileName) == "" && FileName[1] != '\\')
  741. {
  742. FileName = IncludeTrailingBackslash(LocalDirView->PathName) + FileName;
  743. }
  744. if (ExtractFileDrive(PointTo) == "" && PointTo[1] != '\\')
  745. {
  746. PointTo = IncludeTrailingBackslash(LocalDirView->PathName) + PointTo;
  747. }
  748. if (ExtractFileExt(FileName) == "")
  749. {
  750. FileName = FileName + ".lnk";
  751. }
  752. if (Edit && !DeleteFile(FileName))
  753. {
  754. throw Exception(FMTLOAD(DELETE_LOCAL_FILE_ERROR, (FileName)));
  755. }
  756. if (!CreateFileShortCut(PointTo, FileName, ""))
  757. {
  758. throw Exception(CREATE_SHORTCUT_ERROR);
  759. }
  760. }
  761. }
  762. else
  763. {
  764. TCustomScpExplorerForm::AddEditLink();
  765. }
  766. }
  767. //---------------------------------------------------------------------------
  768. void __fastcall TScpCommanderForm::DoOpenDirectoryDialog(TOpenDirectoryMode Mode,
  769. TOperationSide Side)
  770. {
  771. if (WinConfiguration->UseLocationProfiles)
  772. {
  773. TStrings * RemoteDirectories = CreateVisitedDirectories(osRemote);
  774. try
  775. {
  776. AnsiString Local = LocalDirView->PathName;
  777. AnsiString Remote = RemoteDirView->PathName;
  778. if (LocationProfilesDialog(Mode, Side, Local, Remote, RemoteDirectories, Terminal))
  779. {
  780. if (!Local.IsEmpty())
  781. {
  782. LocalDirView->Path = Local;
  783. }
  784. if (!Remote.IsEmpty())
  785. {
  786. RemoteDirView->Path = Remote;
  787. }
  788. }
  789. }
  790. __finally
  791. {
  792. delete RemoteDirectories;
  793. }
  794. }
  795. else
  796. {
  797. TCustomScpExplorerForm::DoOpenDirectoryDialog(Mode, Side);
  798. }
  799. }
  800. //---------------------------------------------------------------------------
  801. void __fastcall TScpCommanderForm::LocalDirViewDDTargetHasDropHandler(
  802. TObject * /*Sender*/, TListItem * Item, int & /*Effect*/, bool & DropHandler)
  803. {
  804. // when drop target is not directory, it is probably file type, which have
  805. // associated drop handler (such as ZIP file in WinXP). in this case we
  806. // cannot allow downloading when using shellex.
  807. // ! this check is duplicated in InternalDDDownload() for non-shellex downloads
  808. if ((FDDExtMapFile != NULL) &&
  809. !LocalDirView->ItemIsDirectory(Item))
  810. {
  811. DropHandler = false;
  812. }
  813. }
  814. //---------------------------------------------------------------------------
  815. void __fastcall TScpCommanderForm::LocalDirViewDDDragOver(TObject * /*Sender*/,
  816. int grfKeyState, TPoint & /*Point*/, int & dwEffect)
  817. {
  818. if ((grfKeyState & (MK_CONTROL | MK_SHIFT)) == 0)
  819. {
  820. if (DropSourceControl == RemoteDirView)
  821. {
  822. dwEffect = DROPEFFECT_Copy;
  823. }
  824. }
  825. }
  826. //---------------------------------------------------------------------------
  827. void __fastcall TScpCommanderForm::DDGetTarget(AnsiString & Directory)
  828. {
  829. if (!FDDExtTarget.IsEmpty())
  830. {
  831. Directory = FDDExtTarget;
  832. FDDExtTarget = "";
  833. }
  834. else
  835. {
  836. TCustomScpExplorerForm::DDGetTarget(Directory);
  837. }
  838. }
  839. //---------------------------------------------------------------------------
  840. void __fastcall TScpCommanderForm::DDExtInitDrag(TFileList * FileList,
  841. bool & Created)
  842. {
  843. FDDExtTarget = "";
  844. TCustomScpExplorerForm::DDExtInitDrag(FileList, Created);
  845. }
  846. //---------------------------------------------------------------------------
  847. void __fastcall TScpCommanderForm::LocalDirViewDDFileOperation(
  848. TObject * /*Sender*/, int dwEffect, AnsiString SourcePath,
  849. AnsiString TargetPath, bool & DoOperation)
  850. {
  851. if (DropSourceControl == RemoteDirView)
  852. {
  853. AnsiString TargetDirectory;
  854. if (InternalDDDownload(TargetDirectory))
  855. {
  856. if (FDDExtMapFile != NULL)
  857. {
  858. FDDExtTarget = TargetDirectory;
  859. }
  860. else
  861. {
  862. assert(FInternalDDDownloadList->Count > 0);
  863. assert(dwEffect == DROPEFFECT_Copy || dwEffect == DROPEFFECT_Move);
  864. TCopyParamType CopyParams = Configuration->CopyParam;
  865. if (CopyParamDialog(tdToLocal, dwEffect == DROPEFFECT_Copy ? ttCopy : ttMove,
  866. false, FInternalDDDownloadList, TargetDirectory, CopyParams,
  867. WinConfiguration->DDTransferConfirmation))
  868. {
  869. Terminal->CopyToLocal(FInternalDDDownloadList, TargetDirectory, &CopyParams,
  870. (dwEffect == DROPEFFECT_Move ? cpDelete : 0));
  871. FInternalDDDownloadList->Clear();
  872. }
  873. }
  874. DoOperation = false;
  875. }
  876. }
  877. }
  878. //---------------------------------------------------------------------------
  879. void __fastcall TScpCommanderForm::RemoteDirViewDDFileOperationExecuted(
  880. TObject * /*Sender*/, int dwEffect, AnsiString /*SourcePath*/,
  881. AnsiString /*TargetPath*/)
  882. {
  883. if ((dwEffect == DROPEFFECT_Move) && (DropSourceControl == LocalDirView))
  884. {
  885. LocalDirView->Reload(true);
  886. }
  887. }
  888. //---------------------------------------------------------------------------
  889. void __fastcall TScpCommanderForm::DoDirViewEnter(TCustomDirView * DirView)
  890. {
  891. if (FLastDirView != DirView)
  892. {
  893. CommandLineCombo->Items->Clear();
  894. FCommandLineComboPopulated = false;
  895. }
  896. TCustomScpExplorerForm::DoDirViewEnter(DirView);
  897. UpdateControls();
  898. }
  899. //---------------------------------------------------------------------------
  900. void __fastcall TScpCommanderForm::OpenConsole(AnsiString Command)
  901. {
  902. SaveCommandLine();
  903. try
  904. {
  905. TCustomScpExplorerForm::OpenConsole(Command);
  906. }
  907. __finally
  908. {
  909. FCommandLineComboPopulated = false;
  910. }
  911. }
  912. //---------------------------------------------------------------------------
  913. void __fastcall TScpCommanderForm::CommandLineComboKeyDown(TObject * /*Sender*/,
  914. WORD & Key, TShiftState /*Shift*/)
  915. {
  916. if (Key == VK_RETURN)
  917. {
  918. Key = 0;
  919. ExecuteCommandLine();
  920. }
  921. else if ((Key == VK_ESCAPE) && !CommandLineCombo->DroppedDown)
  922. {
  923. Key = 0;
  924. CommandLineCombo->Text = "";
  925. }
  926. else if ((Key == VK_UP) || (Key == VK_DOWN))
  927. {
  928. CommandLinePopulate();
  929. }
  930. }
  931. //---------------------------------------------------------------------------
  932. void __fastcall TScpCommanderForm::SaveCommandLine()
  933. {
  934. if (FCommandLineComboPopulated)
  935. {
  936. CustomWinConfiguration->History[
  937. FLastDirView == RemoteDirView ? "Commands" : "LocalCommands"] =
  938. CommandLineCombo->Items;
  939. }
  940. }
  941. //---------------------------------------------------------------------------
  942. void __fastcall TScpCommanderForm::ExecuteCommandLine()
  943. {
  944. if (!CommandLineCombo->Text.Trim().IsEmpty())
  945. {
  946. CommandLinePopulate();
  947. CommandLineCombo->SaveToHistory();
  948. AnsiString Command = CommandLineCombo->Text;
  949. CommandLineCombo->Text = "";
  950. if (FLastDirView == RemoteDirView)
  951. {
  952. OpenConsole(Command);
  953. }
  954. else
  955. {
  956. AnsiString Program, Params, Dir;
  957. SplitCommand(Command, Program, Params, Dir);
  958. if (!ExecuteShell(Program, Params))
  959. {
  960. throw Exception(FMTLOAD(EXECUTE_APP_ERROR, (Program)));
  961. }
  962. }
  963. }
  964. }
  965. //---------------------------------------------------------------------------
  966. void __fastcall TScpCommanderForm::CommandLineComboDropDown(
  967. TObject * /*Sender*/)
  968. {
  969. CommandLinePopulate();
  970. }
  971. //---------------------------------------------------------------------------
  972. void __fastcall TScpCommanderForm::CommandLinePopulate()
  973. {
  974. if (!FCommandLineComboPopulated)
  975. {
  976. TStrings * CommandsHistory;
  977. CommandsHistory = CustomWinConfiguration->History[
  978. FLastDirView == RemoteDirView ? "Commands" : "LocalCommands"];
  979. if ((CommandsHistory != NULL) && (CommandsHistory->Count > 0))
  980. {
  981. CommandLineCombo->Items = CommandsHistory;
  982. }
  983. else
  984. {
  985. CommandLineCombo->Items->Clear();
  986. }
  987. FCommandLineComboPopulated = true;
  988. }
  989. }
  990. //---------------------------------------------------------------------------
  991. void __fastcall TScpCommanderForm::GoToCommandLine()
  992. {
  993. ComponentVisible[fcCommandLinePanel] = true;
  994. if (CommandLineCombo->Enabled)
  995. {
  996. CommandLineCombo->SetFocus();
  997. }
  998. }
  999. //---------------------------------------------------------------------------
  1000. void __fastcall TScpCommanderForm::CommandLineComboEnter(TObject * /*Sender*/)
  1001. {
  1002. KeyPreview = false;
  1003. TPanel * LastPanel = FLastDirView == LocalDirView ? LocalPanel : RemotePanel;
  1004. if (CommandLinePanel->TabOrder > LastPanel->TabOrder)
  1005. {
  1006. CommandLinePanel->TabOrder = LastPanel->TabOrder;
  1007. }
  1008. else if (CommandLinePanel->TabOrder < LastPanel->TabOrder - 1)
  1009. {
  1010. CommandLinePanel->TabOrder = static_cast<TTabOrder>(LastPanel->TabOrder - 1);
  1011. }
  1012. }
  1013. //---------------------------------------------------------------------------
  1014. void __fastcall TScpCommanderForm::CommandLineComboExit(TObject * /*Sender*/)
  1015. {
  1016. KeyPreview = true;
  1017. }
  1018. //---------------------------------------------------------------------------
  1019. void __fastcall TScpCommanderForm::PanelExportStore(TOperationSide Side,
  1020. TPanelExport Export, TPanelExportDestination Destination,
  1021. TStringList * ExportData)
  1022. {
  1023. if (Destination == pedCommandLine)
  1024. {
  1025. ComponentVisible[fcCommandLinePanel] = true;
  1026. AnsiString Buf;
  1027. for (int Index = 0; Index < ExportData->Count; Index++)
  1028. {
  1029. Buf += ExportData->Strings[Index] + " ";
  1030. }
  1031. if (CommandLineCombo->Focused())
  1032. {
  1033. CommandLineCombo->SelText = Buf;
  1034. }
  1035. else
  1036. {
  1037. CommandLineCombo->Text = CommandLineCombo->Text + Buf;
  1038. }
  1039. }
  1040. else
  1041. {
  1042. TCustomScpExplorerForm::PanelExportStore(Side, Export, Destination, ExportData);
  1043. }
  1044. }
  1045. //---------------------------------------------------------------------------