SynchronizeChecklist.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825
  1. //---------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include <Common.h>
  5. #include "WinInterface.h"
  6. #include "SynchronizeChecklist.h"
  7. #include <Terminal.h>
  8. #include <TextsWin.h>
  9. #include <CoreMain.h>
  10. #include <VCLCommon.h>
  11. #include <Tools.h>
  12. #include <BaseUtils.hpp>
  13. #include <WinConfiguration.h>
  14. //---------------------------------------------------------------------
  15. #pragma link "IEListView"
  16. #pragma link "NortonLikeListView"
  17. #pragma link "PngImageList"
  18. #ifndef NO_RESOURCES
  19. #pragma resource "*.dfm"
  20. #endif
  21. //---------------------------------------------------------------------
  22. bool __fastcall DoSynchronizeChecklistDialog(TSynchronizeChecklist * Checklist,
  23. TSynchronizeMode Mode, int Params, const UnicodeString LocalDirectory,
  24. const UnicodeString RemoteDirectory, TCustomCommandMenuEvent OnCustomCommandMenu)
  25. {
  26. bool Result;
  27. TSynchronizeChecklistDialog * Dialog = new TSynchronizeChecklistDialog(
  28. Application, Mode, Params, LocalDirectory, RemoteDirectory, OnCustomCommandMenu);
  29. try
  30. {
  31. Result = Dialog->Execute(Checklist);
  32. }
  33. __finally
  34. {
  35. delete Dialog;
  36. }
  37. return Result;
  38. }
  39. //---------------------------------------------------------------------
  40. __fastcall TSynchronizeChecklistDialog::TSynchronizeChecklistDialog(
  41. TComponent * AOwner, TSynchronizeMode Mode, int Params,
  42. const UnicodeString LocalDirectory, const UnicodeString RemoteDirectory,
  43. TCustomCommandMenuEvent OnCustomCommandMenu)
  44. : TForm(AOwner)
  45. {
  46. FFormRestored = false;
  47. FMode = Mode;
  48. FParams = Params;
  49. FLocalDirectory = ExcludeTrailingBackslash(LocalDirectory);
  50. FRemoteDirectory = UnixExcludeTrailingBackslash(RemoteDirectory);
  51. FOnCustomCommandMenu = OnCustomCommandMenu;
  52. UseSystemSettings(this);
  53. FChecklist = NULL;
  54. FChangingItem = NULL;
  55. FChangingItemIgnore = false;
  56. FChangingItemMass = false;
  57. FGeneralHint = StatusBar->Hint;
  58. FOrigListViewWindowProc = ListView->WindowProc;
  59. ListView->WindowProc = ListViewWindowProc;
  60. FSystemImageList = SharedSystemImageList(false);
  61. ListView->SmallImages = FSystemImageList;
  62. // header images mut be assigned after the small images, so it cannot
  63. // be done via DFM
  64. ListView->HeaderImages = ArrowImages;
  65. CustomCommandsButton->Visible = (FOnCustomCommandMenu != NULL);
  66. }
  67. //---------------------------------------------------------------------
  68. __fastcall TSynchronizeChecklistDialog::~TSynchronizeChecklistDialog()
  69. {
  70. delete FSystemImageList;
  71. ListView->WindowProc = FOrigListViewWindowProc;
  72. }
  73. //---------------------------------------------------------------------
  74. bool __fastcall TSynchronizeChecklistDialog::Execute(TSynchronizeChecklist * Checklist)
  75. {
  76. FChecklist = Checklist;
  77. bool Result = (ShowModal() != mrCancel);
  78. if (Result)
  79. {
  80. for (int Index = 0; Index < ListView->Items->Count; Index++)
  81. {
  82. TListItem * Item = ListView->Items->Item[Index];
  83. // const violation !
  84. TSynchronizeChecklist::TItem * ChecklistItem =
  85. static_cast<TSynchronizeChecklist::TItem *>(Item->Data);
  86. ChecklistItem->Checked = Item->Checked;
  87. }
  88. TSynchronizeChecklistConfiguration FormConfiguration =
  89. CustomWinConfiguration->SynchronizeChecklist;
  90. FormConfiguration.ListParams = ListView->ColProperties->ParamsStr;
  91. UnicodeString WindowParams = FormConfiguration.WindowParams;
  92. // if there is no main window, keep previous "custom pos" indication,
  93. bool CustomPos = (StrToIntDef(::CutToChar(WindowParams, L';', true), 0) != 0);
  94. if (Application->MainForm != NULL)
  95. {
  96. CustomPos = (Application->MainForm->BoundsRect != BoundsRect);
  97. }
  98. FormConfiguration.WindowParams =
  99. FORMAT(L"%d;%s", ((CustomPos ? 1 : 0), StoreForm(this)));
  100. CustomWinConfiguration->SynchronizeChecklist = FormConfiguration;
  101. }
  102. return Result;
  103. }
  104. //---------------------------------------------------------------------
  105. void __fastcall TSynchronizeChecklistDialog::UpdateControls()
  106. {
  107. StatusBar->Invalidate();
  108. bool AllChecked = true;
  109. bool AllUnchecked = true;
  110. bool AnyBoth = false;
  111. bool AnyNonBoth = false;
  112. TListItem * Item = ListView->Selected;
  113. while (Item != NULL)
  114. {
  115. const TSynchronizeChecklist::TItem * ChecklistItem =
  116. static_cast<const TSynchronizeChecklist::TItem *>(Item->Data);
  117. if ((ChecklistItem->Action == TSynchronizeChecklist::saUploadUpdate) ||
  118. (ChecklistItem->Action == TSynchronizeChecklist::saDownloadUpdate))
  119. {
  120. AnyBoth = true;
  121. }
  122. else
  123. {
  124. AnyNonBoth = true;
  125. }
  126. if (Item->Checked)
  127. {
  128. AllUnchecked = false;
  129. }
  130. else
  131. {
  132. AllChecked = false;
  133. }
  134. Item = ListView->GetNextItem(Item, sdAll, TItemStates() << isSelected);
  135. }
  136. EnableControl(OkButton, (FChecked[0] > 0));
  137. EnableControl(CheckButton, !AllChecked);
  138. EnableControl(UncheckButton, !AllUnchecked);
  139. EnableControl(CheckAllButton, (FChecked[0] < FTotals[0]));
  140. EnableControl(UncheckAllButton, (FChecked[0] > 0));
  141. EnableControl(UncheckAllButton, (FChecked[0] > 0));
  142. EnableControl(CustomCommandsButton, AnyBoth && !AnyNonBoth);
  143. CheckItem->Enabled = CheckButton->Enabled;
  144. UncheckItem->Enabled = UncheckButton->Enabled;
  145. SelectAllItem->Enabled = (ListView->SelCount < ListView->Items->Count);
  146. }
  147. //---------------------------------------------------------------------------
  148. void __fastcall TSynchronizeChecklistDialog::CreateParams(TCreateParams & Params)
  149. {
  150. if (!FFormRestored)
  151. {
  152. FFormRestored = True;
  153. UnicodeString WindowParams = CustomWinConfiguration->SynchronizeChecklist.WindowParams;
  154. bool CustomPos = (StrToIntDef(::CutToChar(WindowParams, L';', true), 0) != 0);
  155. if (!CustomPos && (Application->MainForm != NULL))
  156. {
  157. BoundsRect = Application->MainForm->BoundsRect;
  158. }
  159. else
  160. {
  161. RestoreForm(WindowParams, this);
  162. }
  163. }
  164. TForm::CreateParams(Params);
  165. }
  166. //---------------------------------------------------------------------------
  167. void __fastcall TSynchronizeChecklistDialog::HelpButtonClick(TObject * /*Sender*/)
  168. {
  169. FormHelp(this);
  170. }
  171. //---------------------------------------------------------------------------
  172. void __fastcall TSynchronizeChecklistDialog::LoadItem(TListItem * Item)
  173. {
  174. UnicodeString S;
  175. const TSynchronizeChecklist::TItem * ChecklistItem = FChecklist->Item[Item->Index];
  176. Item->Data = const_cast<TSynchronizeChecklist::TItem *>(ChecklistItem);
  177. Item->Checked = ChecklistItem->Checked;
  178. if (ChecklistItem->ImageIndex >= 0)
  179. {
  180. Item->ImageIndex = ChecklistItem->ImageIndex;
  181. }
  182. else
  183. {
  184. Item->ImageIndex = FakeFileImageIndex(ChecklistItem->GetFileName(),
  185. FLAGMASK(ChecklistItem->IsDirectory, FILE_ATTRIBUTE_DIRECTORY));
  186. }
  187. S = ChecklistItem->GetFileName();
  188. if (ChecklistItem->IsDirectory)
  189. {
  190. S = IncludeTrailingBackslash(S);
  191. }
  192. Item->Caption = S;
  193. if (ChecklistItem->Action == TSynchronizeChecklist::saDeleteRemote)
  194. {
  195. Item->SubItems->Add(L"");
  196. Item->SubItems->Add(L"");
  197. Item->SubItems->Add(L"");
  198. }
  199. else
  200. {
  201. S = ChecklistItem->Local.Directory;
  202. if (AnsiSameText(FLocalDirectory, S.SubString(1, FLocalDirectory.Length())))
  203. {
  204. S[1] = L'.';
  205. S.Delete(2, FLocalDirectory.Length() - 1);
  206. }
  207. else
  208. {
  209. assert(false);
  210. }
  211. Item->SubItems->Add(S);
  212. if (ChecklistItem->Action == TSynchronizeChecklist::saDownloadNew)
  213. {
  214. Item->SubItems->Add(L"");
  215. Item->SubItems->Add(L"");
  216. }
  217. else
  218. {
  219. if (ChecklistItem->IsDirectory)
  220. {
  221. Item->SubItems->Add(L"");
  222. }
  223. else
  224. {
  225. Item->SubItems->Add(
  226. FormatBytes(ChecklistItem->Local.Size,
  227. WinConfiguration->FormatSizeBytes, WinConfiguration->FormatSizeBytes));
  228. }
  229. Item->SubItems->Add(UserModificationStr(ChecklistItem->Local.Modification,
  230. ChecklistItem->Local.ModificationFmt));
  231. }
  232. }
  233. Item->SubItems->Add(L"");
  234. if (ChecklistItem->Action == TSynchronizeChecklist::saDeleteLocal)
  235. {
  236. Item->SubItems->Add(L"");
  237. Item->SubItems->Add(L"");
  238. Item->SubItems->Add(L"");
  239. }
  240. else
  241. {
  242. S = ChecklistItem->Remote.Directory;
  243. if (AnsiSameText(FRemoteDirectory, S.SubString(1, FRemoteDirectory.Length())))
  244. {
  245. S[1] = L'.';
  246. S.Delete(2, FRemoteDirectory.Length() - 1);
  247. }
  248. else
  249. {
  250. assert(false);
  251. }
  252. Item->SubItems->Add(S);
  253. if (ChecklistItem->Action == TSynchronizeChecklist::saUploadNew)
  254. {
  255. Item->SubItems->Add(L"");
  256. Item->SubItems->Add(L"");
  257. }
  258. else
  259. {
  260. if (ChecklistItem->IsDirectory)
  261. {
  262. Item->SubItems->Add(L"");
  263. }
  264. else
  265. {
  266. Item->SubItems->Add(
  267. FormatBytes(ChecklistItem->Remote.Size,
  268. WinConfiguration->FormatSizeBytes, WinConfiguration->FormatSizeBytes));
  269. }
  270. Item->SubItems->Add(UserModificationStr(ChecklistItem->Remote.Modification,
  271. ChecklistItem->Remote.ModificationFmt));
  272. }
  273. }
  274. }
  275. //---------------------------------------------------------------------------
  276. void __fastcall TSynchronizeChecklistDialog::LoadList()
  277. {
  278. memset(&FTotals, 0, sizeof(FTotals));
  279. memset(&FChecked, 0, sizeof(FChecked));
  280. FTotals[0] = FChecklist->Count;
  281. FChecked[0] = 0;
  282. ListView->Items->BeginUpdate();
  283. try
  284. {
  285. ListView->Items->Clear();
  286. for (int Index = 0; Index < FChecklist->Count; Index++)
  287. {
  288. const TSynchronizeChecklist::TItem * ChecklistItem =
  289. FChecklist->Item[ListView->Items->Count];
  290. FChangingItemIgnore = true;
  291. try
  292. {
  293. LoadItem(ListView->Items->Add());
  294. }
  295. __finally
  296. {
  297. FChangingItemIgnore = false;
  298. }
  299. FTotals[int(ChecklistItem->Action)]++;
  300. if (ChecklistItem->Checked)
  301. {
  302. FChecked[int(ChecklistItem->Action)]++;
  303. FChecked[0]++;
  304. }
  305. }
  306. }
  307. __finally
  308. {
  309. ListView->Items->EndUpdate();
  310. }
  311. ListView->AlphaSort();
  312. UpdateControls();
  313. }
  314. //---------------------------------------------------------------------------
  315. void __fastcall TSynchronizeChecklistDialog::FormShow(TObject * /*Sender*/)
  316. {
  317. ListView->ColProperties->ParamsStr = CustomWinConfiguration->SynchronizeChecklist.ListParams;
  318. LoadList();
  319. }
  320. //---------------------------------------------------------------------------
  321. void __fastcall TSynchronizeChecklistDialog::ListViewWindowProc(TMessage & Message)
  322. {
  323. if (Message.Msg == CN_NOTIFY)
  324. {
  325. TWMNotify & NotifyMessage = reinterpret_cast<TWMNotify &>(Message);
  326. if (NotifyMessage.NMHdr->code == NM_CUSTOMDRAW)
  327. {
  328. // Due to a bug in VCL, OnAdvancedCustomDrawSubItem is not called for any
  329. // other stage except for cdPrePaint. So we must call it ourselves.
  330. TNMLVCustomDraw * CustomDraw =
  331. reinterpret_cast<TNMLVCustomDraw *>(NotifyMessage.NMHdr);
  332. if (FLAGSET(CustomDraw->nmcd.dwDrawStage, CDDS_ITEM) &&
  333. FLAGSET(CustomDraw->nmcd.dwDrawStage, CDDS_SUBITEM) &&
  334. FLAGSET(CustomDraw->nmcd.dwDrawStage, CDDS_ITEMPOSTPAINT) &&
  335. (CustomDraw->iSubItem == 4) &&
  336. (ActionImages->Width <= ListView->Columns->Items[CustomDraw->iSubItem]->Width))
  337. {
  338. TListItem * Item = ListView->Items->Item[CustomDraw->nmcd.dwItemSpec];
  339. const TSynchronizeChecklist::TItem * ChecklistItem =
  340. static_cast<const TSynchronizeChecklist::TItem *>(Item->Data);
  341. TRect R = Item->DisplayRect(drBounds);
  342. for (int Index = 0; Index < CustomDraw->iSubItem; Index++)
  343. {
  344. R.Left += ListView->Columns->Items[Index]->Width;
  345. }
  346. R.Left +=
  347. (ListView->Columns->Items[CustomDraw->iSubItem]->Width - ActionImages->Width) / 2;
  348. // doing this from ListViewAdvancedCustomDraw corrupts list view on Windows 7
  349. ImageList_Draw(reinterpret_cast<HIMAGELIST>(ActionImages->Handle),
  350. int(ChecklistItem->Action), CustomDraw->nmcd.hdc,
  351. R.Left, R.Top, ILD_TRANSPARENT);
  352. }
  353. }
  354. }
  355. FOrigListViewWindowProc(Message);
  356. }
  357. //---------------------------------------------------------------------------
  358. void __fastcall TSynchronizeChecklistDialog::ListViewAdvancedCustomDrawSubItem(
  359. TCustomListView * /*Sender*/, TListItem * /*Item*/, int /*SubItem*/,
  360. TCustomDrawState /*State*/, TCustomDrawStage /*Stage*/, bool & /*DefaultDraw*/)
  361. {
  362. // this is just fake handler that makes the list view request custom draw notification above
  363. }
  364. //---------------------------------------------------------------------------
  365. void __fastcall TSynchronizeChecklistDialog::StatusBarDrawPanel(
  366. TStatusBar * StatusBar, TStatusPanel * Panel, const TRect & Rect)
  367. {
  368. bool Possible;
  369. TSynchronizeChecklist::TAction Action = TSynchronizeChecklist::TAction(Panel->Index);
  370. switch (Action)
  371. {
  372. case TSynchronizeChecklist::saNone:
  373. Possible = true;
  374. break;
  375. case TSynchronizeChecklist::saUploadNew:
  376. Possible = ((FMode == smRemote) || (FMode == smBoth)) &&
  377. FLAGCLEAR(FParams, spTimestamp);
  378. break;
  379. case TSynchronizeChecklist::saDownloadNew:
  380. Possible = ((FMode == smLocal) || (FMode == smBoth)) &&
  381. FLAGCLEAR(FParams, spTimestamp);
  382. break;
  383. case TSynchronizeChecklist::saUploadUpdate:
  384. Possible =
  385. ((FMode == smRemote) || (FMode == smBoth)) &&
  386. (FLAGCLEAR(FParams, spNotByTime) || FLAGSET(FParams, spBySize));
  387. break;
  388. case TSynchronizeChecklist::saDownloadUpdate:
  389. Possible =
  390. ((FMode == smLocal) || (FMode == smBoth)) &&
  391. (FLAGCLEAR(FParams, spNotByTime) || FLAGSET(FParams, spBySize));
  392. break;
  393. case TSynchronizeChecklist::saDeleteRemote:
  394. Possible = (FMode == smRemote) &&
  395. FLAGCLEAR(FParams, spTimestamp);
  396. break;
  397. case TSynchronizeChecklist::saDeleteLocal:
  398. Possible = (FMode == smLocal) &&
  399. FLAGCLEAR(FParams, spTimestamp);
  400. break;
  401. default:
  402. assert(false);
  403. Possible = false;
  404. break;
  405. }
  406. int ImageIndex = Panel->Index;
  407. UnicodeString PanelText;
  408. if (Possible)
  409. {
  410. PanelText = FORMAT(LoadStrPart(SYNCHRONIZE_SELECTED_ACTIONS, 1),
  411. (FormatNumber(FChecked[Panel->Index]),
  412. FormatNumber(FTotals[Panel->Index])));
  413. }
  414. else
  415. {
  416. PanelText = LoadStrPart(SYNCHRONIZE_SELECTED_ACTIONS, 2);
  417. }
  418. StatusBar->Canvas->TextRect(Rect, Rect.left + 18, Rect.top + 1, PanelText);
  419. ActionImages->Draw(StatusBar->Canvas,
  420. Rect.Left + 1, Rect.Top, ImageIndex, Possible);
  421. }
  422. //---------------------------------------------------------------------------
  423. int __fastcall TSynchronizeChecklistDialog::PanelAt(int X)
  424. {
  425. int Result = 0;
  426. while ((X > StatusBar->Panels->Items[Result]->Width) &&
  427. (Result < StatusBar->Panels->Count - 1))
  428. {
  429. X -= StatusBar->Panels->Items[Result]->Width;
  430. Result++;
  431. }
  432. return ((Result < StatusBar->Panels->Count - 1) ? Result : -1);
  433. }
  434. //---------------------------------------------------------------------------
  435. void __fastcall TSynchronizeChecklistDialog::StatusBarMouseMove(
  436. TObject * /*Sender*/, TShiftState /*Shift*/, int X, int /*Y*/)
  437. {
  438. UnicodeString Hint;
  439. int IPanel = PanelAt(X);
  440. if (IPanel >= 0)
  441. {
  442. Hint = StatusBar->Panels->Items[IPanel]->Text;
  443. if (IPanel > 0)
  444. {
  445. Hint = FORMAT(L"%s\n%s", (Hint, FGeneralHint));
  446. }
  447. }
  448. if (Hint != StatusBar->Hint)
  449. {
  450. Application->CancelHint();
  451. StatusBar->Hint = Hint;
  452. }
  453. }
  454. //---------------------------------------------------------------------------
  455. void __fastcall TSynchronizeChecklistDialog::ListViewChange(
  456. TObject * /*Sender*/, TListItem * Item, TItemChange Change)
  457. {
  458. if ((Change == ctState) && (FChangingItem == Item) && (FChangingItem != NULL))
  459. {
  460. if (!FChangingItemIgnore)
  461. {
  462. assert(Item->Data != NULL);
  463. if ((FChangingItemChecked != Item->Checked) && (Item->Data != NULL))
  464. {
  465. const TSynchronizeChecklist::TItem * ChecklistItem =
  466. static_cast<const TSynchronizeChecklist::TItem *>(Item->Data);
  467. if (Item->Checked)
  468. {
  469. FChecked[int(ChecklistItem->Action)]++;
  470. FChecked[0]++;
  471. }
  472. else
  473. {
  474. FChecked[int(ChecklistItem->Action)]--;
  475. FChecked[0]--;
  476. }
  477. if (!FChangingItemMass)
  478. {
  479. UpdateControls();
  480. }
  481. }
  482. }
  483. FChangingItem = NULL;
  484. }
  485. }
  486. //---------------------------------------------------------------------------
  487. void __fastcall TSynchronizeChecklistDialog::ListViewChanging(
  488. TObject * /*Sender*/, TListItem * Item, TItemChange Change,
  489. bool & /*AllowChange*/)
  490. {
  491. if (Change == ctState)
  492. {
  493. FChangingItem = Item;
  494. FChangingItemChecked = Item->Checked;
  495. }
  496. else
  497. {
  498. assert(FChangingItem == NULL);
  499. FChangingItem = NULL;
  500. }
  501. }
  502. //---------------------------------------------------------------------------
  503. void __fastcall TSynchronizeChecklistDialog::CheckAll(bool Check)
  504. {
  505. FChangingItemMass = true;
  506. try
  507. {
  508. for (int Index = 0; Index < ListView->Items->Count; Index++)
  509. {
  510. ListView->Items->Item[Index]->Checked = Check;
  511. }
  512. }
  513. __finally
  514. {
  515. FChangingItemMass = false;
  516. }
  517. UpdateControls();
  518. }
  519. //---------------------------------------------------------------------------
  520. void __fastcall TSynchronizeChecklistDialog::CheckAllButtonClick(TObject * Sender)
  521. {
  522. CheckAll(Sender == CheckAllButton);
  523. }
  524. //---------------------------------------------------------------------------
  525. void __fastcall TSynchronizeChecklistDialog::CheckButtonClick(
  526. TObject * Sender)
  527. {
  528. FChangingItemMass = true;
  529. try
  530. {
  531. TListItem * Item = ListView->Selected;
  532. while (Item != NULL)
  533. {
  534. TComponent * Component = dynamic_cast<TComponent *>(Sender);
  535. assert(Component != NULL);
  536. Item->Checked = (Component->Tag != 0);
  537. Item = ListView->GetNextItem(Item, sdAll, TItemStates() << isSelected);
  538. }
  539. }
  540. __finally
  541. {
  542. FChangingItemMass = false;
  543. }
  544. UpdateControls();
  545. }
  546. //---------------------------------------------------------------------------
  547. void __fastcall TSynchronizeChecklistDialog::ListViewSelectItem(
  548. TObject * /*Sender*/, TListItem * /*Item*/, bool /*Selected*/)
  549. {
  550. // Delayed update of button status in case many items are being selected at once
  551. // Also change of selection causes buttons to flash, as for short period of time,
  552. // no item is selected
  553. UpdateTimer->Enabled = true;
  554. }
  555. //---------------------------------------------------------------------------
  556. void __fastcall TSynchronizeChecklistDialog::StatusBarResize(
  557. TObject * Sender)
  558. {
  559. RepaintStatusBar(dynamic_cast<TCustomStatusBar *>(Sender));
  560. }
  561. //---------------------------------------------------------------------------
  562. void __fastcall TSynchronizeChecklistDialog::UpdateTimerTimer(
  563. TObject * /*Sender*/)
  564. {
  565. UpdateTimer->Enabled = false;
  566. UpdateControls();
  567. }
  568. //---------------------------------------------------------------------------
  569. TListItem * __fastcall TSynchronizeChecklistDialog::SelectAll(bool Select, int Action,
  570. bool OnlyTheAction)
  571. {
  572. TListItem * Result = NULL;
  573. for (int Index = 0; Index < ListView->Items->Count; Index++)
  574. {
  575. TListItem * Item = ListView->Items->Item[Index];
  576. if (Action == 0)
  577. {
  578. Item->Selected = Select;
  579. if (Result == NULL)
  580. {
  581. Result = Item;
  582. }
  583. }
  584. else
  585. {
  586. const TSynchronizeChecklist::TItem * ChecklistItem =
  587. static_cast<const TSynchronizeChecklist::TItem *>(Item->Data);
  588. bool WantedAction = (int(ChecklistItem->Action) == Action);
  589. if (WantedAction || !OnlyTheAction)
  590. {
  591. Item->Selected = Select && WantedAction;
  592. if (WantedAction && (Result == NULL))
  593. {
  594. Result = Item;
  595. }
  596. }
  597. }
  598. }
  599. return Result;
  600. }
  601. //---------------------------------------------------------------------------
  602. void __fastcall TSynchronizeChecklistDialog::SelectAllItemClick(
  603. TObject * /*Sender*/)
  604. {
  605. SelectAll(true);
  606. }
  607. //---------------------------------------------------------------------------
  608. void __fastcall TSynchronizeChecklistDialog::StatusBarMouseDown(
  609. TObject * /*Sender*/, TMouseButton /*Button*/, TShiftState Shift, int X,
  610. int /*Y*/)
  611. {
  612. int IPanel = PanelAt(X);
  613. if (IPanel >= 0)
  614. {
  615. TListItem * Item = SelectAll(true, IPanel, Shift.Contains(ssCtrl));
  616. if (Item != NULL)
  617. {
  618. Item->MakeVisible(false);
  619. Item->Focused = true;
  620. ListView->SetFocus();
  621. }
  622. }
  623. }
  624. //---------------------------------------------------------------------------
  625. int __fastcall TSynchronizeChecklistDialog::CompareNumber(__int64 Value1,
  626. __int64 Value2)
  627. {
  628. int Result;
  629. if (Value1 < Value2)
  630. {
  631. Result = -1;
  632. }
  633. else if (Value1 == Value2)
  634. {
  635. Result = 0;
  636. }
  637. else
  638. {
  639. Result = 1;
  640. }
  641. return Result;
  642. }
  643. //---------------------------------------------------------------------------
  644. void __fastcall TSynchronizeChecklistDialog::ListViewCompare(
  645. TObject * /*Sender*/, TListItem * Item1, TListItem * Item2, int /*Data*/,
  646. int & Compare)
  647. {
  648. const TSynchronizeChecklist::TItem * ChecklistItem1 =
  649. static_cast<const TSynchronizeChecklist::TItem *>(Item1->Data);
  650. const TSynchronizeChecklist::TItem * ChecklistItem2 =
  651. static_cast<const TSynchronizeChecklist::TItem *>(Item2->Data);
  652. TIEListViewColProperties * ColProperties =
  653. dynamic_cast<TIEListViewColProperties *>(ListView->ColProperties);
  654. switch (ColProperties->SortColumn)
  655. {
  656. case 0: // name
  657. Compare = AnsiCompareText(ChecklistItem1->GetFileName(), ChecklistItem2->GetFileName());
  658. break;
  659. // sorting by local and remote dir is the same
  660. case 1: // local dir
  661. case 5: // remote dir
  662. Compare = 0; // default sorting
  663. break;
  664. case 2: // local size
  665. Compare = CompareNumber(ChecklistItem1->Local.Size, ChecklistItem2->Local.Size);
  666. break;
  667. case 3: // local changed
  668. Compare = CompareFileTime(ChecklistItem1->Local.Modification,
  669. ChecklistItem2->Local.Modification);
  670. break;
  671. case 4: // action
  672. Compare = CompareNumber(ChecklistItem1->Action, ChecklistItem2->Action);
  673. break;
  674. case 6: // remote size
  675. Compare = CompareNumber(ChecklistItem1->Remote.Size, ChecklistItem2->Remote.Size);
  676. break;
  677. case 7: // remote changed
  678. Compare = CompareFileTime(ChecklistItem1->Remote.Modification,
  679. ChecklistItem2->Remote.Modification);
  680. break;
  681. }
  682. if (Compare == 0)
  683. {
  684. if (!ChecklistItem1->Local.Directory.IsEmpty())
  685. {
  686. Compare = AnsiCompareText(ChecklistItem1->Local.Directory, ChecklistItem2->Local.Directory);
  687. }
  688. else
  689. {
  690. assert(!ChecklistItem1->Remote.Directory.IsEmpty());
  691. Compare = AnsiCompareText(ChecklistItem1->Remote.Directory, ChecklistItem2->Remote.Directory);
  692. }
  693. if (Compare == 0)
  694. {
  695. Compare = AnsiCompareText(ChecklistItem1->GetFileName(), ChecklistItem2->GetFileName());
  696. }
  697. }
  698. if (!ColProperties->SortAscending)
  699. {
  700. Compare = -Compare;
  701. }
  702. }
  703. //---------------------------------------------------------------------------
  704. void __fastcall TSynchronizeChecklistDialog::ListViewSecondaryColumnHeader(
  705. TCustomIEListView * /*Sender*/, int Index, int & SecondaryColumn)
  706. {
  707. // "remote dir" column is sorting alias for "local dir" column
  708. if (Index == 5)
  709. {
  710. SecondaryColumn = 1;
  711. }
  712. else
  713. {
  714. SecondaryColumn = -1;
  715. }
  716. }
  717. //---------------------------------------------------------------------------
  718. void __fastcall TSynchronizeChecklistDialog::ListViewContextPopup(
  719. TObject * Sender, TPoint & MousePos, bool & Handled)
  720. {
  721. // to update source popup menu before TBX menu is created
  722. UpdateControls();
  723. MenuPopup(Sender, MousePos, Handled);
  724. }
  725. //---------------------------------------------------------------------------
  726. void __fastcall TSynchronizeChecklistDialog::CustomCommandsButtonClick(
  727. TObject * /*Sender*/)
  728. {
  729. TStrings * LocalFileList = new TStringList();
  730. TStrings * RemoteFileList = new TStringList();
  731. try
  732. {
  733. TListItem * Item = ListView->Selected;
  734. assert(Item != NULL);
  735. while (Item != NULL)
  736. {
  737. const TSynchronizeChecklist::TItem * ChecklistItem =
  738. static_cast<const TSynchronizeChecklist::TItem *>(Item->Data);
  739. assert((ChecklistItem->Action == TSynchronizeChecklist::saUploadUpdate) ||
  740. (ChecklistItem->Action == TSynchronizeChecklist::saDownloadUpdate));
  741. assert(ChecklistItem->RemoteFile != NULL);
  742. UnicodeString LocalPath =
  743. IncludeTrailingBackslash(ChecklistItem->Local.Directory) +
  744. ChecklistItem->Local.FileName;
  745. LocalFileList->Add(LocalPath);
  746. UnicodeString RemotePath =
  747. UnixIncludeTrailingBackslash(ChecklistItem->Remote.Directory) +
  748. ChecklistItem->Remote.FileName;
  749. RemoteFileList->AddObject(RemotePath, ChecklistItem->RemoteFile);
  750. Item = ListView->GetNextItem(Item, sdAll, TItemStates() << isSelected);
  751. }
  752. }
  753. catch(...)
  754. {
  755. delete LocalFileList;
  756. delete RemoteFileList;
  757. throw;
  758. }
  759. assert(FOnCustomCommandMenu != NULL);
  760. FOnCustomCommandMenu(CustomCommandsButton,
  761. CustomCommandsButton->ClientToScreen(TPoint(0, CustomCommandsButton->Height)),
  762. LocalFileList, RemoteFileList);
  763. }
  764. //---------------------------------------------------------------------------