SynchronizeChecklist.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824
  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 <CustomWinConfiguration.h>
  13. //---------------------------------------------------------------------
  14. #pragma link "IEListView"
  15. #pragma link "NortonLikeListView"
  16. #ifndef NO_RESOURCES
  17. #pragma resource "*.dfm"
  18. #endif
  19. //---------------------------------------------------------------------
  20. bool __fastcall DoSynchronizeChecklistDialog(TSynchronizeChecklist * Checklist,
  21. TSynchronizeMode Mode, int Params, const AnsiString LocalDirectory,
  22. const AnsiString RemoteDirectory, TCustomCommandMenuEvent OnCustomCommandMenu)
  23. {
  24. bool Result;
  25. TSynchronizeChecklistDialog * Dialog = new TSynchronizeChecklistDialog(
  26. Application, Mode, Params, LocalDirectory, RemoteDirectory, OnCustomCommandMenu);
  27. try
  28. {
  29. Result = Dialog->Execute(Checklist);
  30. }
  31. __finally
  32. {
  33. delete Dialog;
  34. }
  35. return Result;
  36. }
  37. //---------------------------------------------------------------------
  38. __fastcall TSynchronizeChecklistDialog::TSynchronizeChecklistDialog(
  39. TComponent * AOwner, TSynchronizeMode Mode, int Params,
  40. const AnsiString LocalDirectory, const AnsiString RemoteDirectory,
  41. TCustomCommandMenuEvent OnCustomCommandMenu)
  42. : TForm(AOwner)
  43. {
  44. FFormRestored = false;
  45. FMode = Mode;
  46. FParams = Params;
  47. FLocalDirectory = ExcludeTrailingBackslash(LocalDirectory);
  48. FRemoteDirectory = UnixExcludeTrailingBackslash(RemoteDirectory);
  49. FOnCustomCommandMenu = OnCustomCommandMenu;
  50. UseSystemSettings(this);
  51. FChecklist = NULL;
  52. FChangingItem = NULL;
  53. FChangingItemIgnore = false;
  54. FChangingItemMass = false;
  55. FGeneralHint = StatusBar->Hint;
  56. FOrigListViewWindowProc = ListView->WindowProc;
  57. ListView->WindowProc = ListViewWindowProc;
  58. FSystemImageList = SharedSystemImageList(false);
  59. ListView->SmallImages = FSystemImageList;
  60. // header images mut be assigned after the small images, so it cannot
  61. // be done via DFM
  62. ListView->HeaderImages = ArrowImages;
  63. CustomCommandsButton->Visible = (FOnCustomCommandMenu != NULL);
  64. }
  65. //---------------------------------------------------------------------
  66. __fastcall TSynchronizeChecklistDialog::~TSynchronizeChecklistDialog()
  67. {
  68. delete FSystemImageList;
  69. ListView->WindowProc = FOrigListViewWindowProc;
  70. }
  71. //---------------------------------------------------------------------
  72. bool __fastcall TSynchronizeChecklistDialog::Execute(TSynchronizeChecklist * Checklist)
  73. {
  74. FChecklist = Checklist;
  75. bool Result = (ShowModal() != mrCancel);
  76. if (Result)
  77. {
  78. for (int Index = 0; Index < ListView->Items->Count; Index++)
  79. {
  80. TListItem * Item = ListView->Items->Item[Index];
  81. // const violation !
  82. TSynchronizeChecklist::TItem * ChecklistItem =
  83. static_cast<TSynchronizeChecklist::TItem *>(Item->Data);
  84. ChecklistItem->Checked = Item->Checked;
  85. }
  86. TSynchronizeChecklistConfiguration FormConfiguration =
  87. CustomWinConfiguration->SynchronizeChecklist;
  88. FormConfiguration.ListParams = ListView->ColProperties->ParamsStr;
  89. AnsiString WindowParams = FormConfiguration.WindowParams;
  90. // if there is no main window, keep previous "custom pos" indication,
  91. bool CustomPos = (StrToIntDef(::CutToChar(WindowParams, ';', true), 0) != 0);
  92. if (Application->MainForm != NULL)
  93. {
  94. CustomPos = (Application->MainForm->BoundsRect != BoundsRect);
  95. }
  96. FormConfiguration.WindowParams =
  97. FORMAT("%d;%s", ((CustomPos ? 1 : 0), StoreForm(this)));
  98. CustomWinConfiguration->SynchronizeChecklist = FormConfiguration;
  99. }
  100. return Result;
  101. }
  102. //---------------------------------------------------------------------
  103. void __fastcall TSynchronizeChecklistDialog::UpdateControls()
  104. {
  105. StatusBar->Invalidate();
  106. bool AllChecked = true;
  107. bool AllUnchecked = true;
  108. bool AnyBoth = false;
  109. bool AnyNonBoth = false;
  110. TListItem * Item = ListView->Selected;
  111. while (Item != NULL)
  112. {
  113. const TSynchronizeChecklist::TItem * ChecklistItem =
  114. static_cast<const TSynchronizeChecklist::TItem *>(Item->Data);
  115. if ((ChecklistItem->Action == TSynchronizeChecklist::saUploadUpdate) ||
  116. (ChecklistItem->Action == TSynchronizeChecklist::saDownloadUpdate))
  117. {
  118. AnyBoth = true;
  119. }
  120. else
  121. {
  122. AnyNonBoth = true;
  123. }
  124. if (Item->Checked)
  125. {
  126. AllUnchecked = false;
  127. }
  128. else
  129. {
  130. AllChecked = false;
  131. }
  132. Item = ListView->GetNextItem(Item, sdAll, TItemStates() << isSelected);
  133. }
  134. EnableControl(OkButton, (FChecked[0] > 0));
  135. EnableControl(CheckButton, !AllChecked);
  136. EnableControl(UncheckButton, !AllUnchecked);
  137. EnableControl(CheckAllButton, (FChecked[0] < FTotals[0]));
  138. EnableControl(UncheckAllButton, (FChecked[0] > 0));
  139. EnableControl(UncheckAllButton, (FChecked[0] > 0));
  140. EnableControl(CustomCommandsButton, AnyBoth && !AnyNonBoth);
  141. CheckItem->Enabled = CheckButton->Enabled;
  142. UncheckItem->Enabled = UncheckButton->Enabled;
  143. SelectAllItem->Enabled = (ListView->SelCount < ListView->Items->Count);
  144. }
  145. //---------------------------------------------------------------------------
  146. void __fastcall TSynchronizeChecklistDialog::CreateParams(TCreateParams & Params)
  147. {
  148. if (!FFormRestored)
  149. {
  150. FFormRestored = True;
  151. AnsiString WindowParams = CustomWinConfiguration->SynchronizeChecklist.WindowParams;
  152. bool CustomPos = (StrToIntDef(::CutToChar(WindowParams, ';', true), 0) != 0);
  153. if (!CustomPos && (Application->MainForm != NULL))
  154. {
  155. BoundsRect = Application->MainForm->BoundsRect;
  156. }
  157. else
  158. {
  159. RestoreForm(WindowParams, this);
  160. }
  161. }
  162. TForm::CreateParams(Params);
  163. }
  164. //---------------------------------------------------------------------------
  165. void __fastcall TSynchronizeChecklistDialog::HelpButtonClick(TObject * /*Sender*/)
  166. {
  167. FormHelp(this);
  168. }
  169. //---------------------------------------------------------------------------
  170. void __fastcall TSynchronizeChecklistDialog::LoadItem(TListItem * Item)
  171. {
  172. AnsiString S;
  173. const TSynchronizeChecklist::TItem * ChecklistItem = FChecklist->Item[Item->Index];
  174. Item->Data = const_cast<TSynchronizeChecklist::TItem *>(ChecklistItem);
  175. Item->Checked = ChecklistItem->Checked;
  176. if (ChecklistItem->ImageIndex >= 0)
  177. {
  178. Item->ImageIndex = ChecklistItem->ImageIndex;
  179. }
  180. else
  181. {
  182. Item->ImageIndex = FakeFileImageIndex(ChecklistItem->GetFileName(),
  183. FLAGMASK(ChecklistItem->IsDirectory, FILE_ATTRIBUTE_DIRECTORY));
  184. }
  185. S = ChecklistItem->GetFileName();
  186. if (ChecklistItem->IsDirectory)
  187. {
  188. S = IncludeTrailingBackslash(S);
  189. }
  190. Item->Caption = S;
  191. if (ChecklistItem->Action == TSynchronizeChecklist::saDeleteRemote)
  192. {
  193. Item->SubItems->Add("");
  194. Item->SubItems->Add("");
  195. Item->SubItems->Add("");
  196. }
  197. else
  198. {
  199. S = ChecklistItem->Local.Directory;
  200. if (AnsiSameText(FLocalDirectory, S.SubString(1, FLocalDirectory.Length())))
  201. {
  202. S[1] = '.';
  203. S.Delete(2, FLocalDirectory.Length() - 1);
  204. }
  205. else
  206. {
  207. assert(false);
  208. }
  209. Item->SubItems->Add(S);
  210. if (ChecklistItem->Action == TSynchronizeChecklist::saDownloadNew)
  211. {
  212. Item->SubItems->Add("");
  213. Item->SubItems->Add("");
  214. }
  215. else
  216. {
  217. if (ChecklistItem->IsDirectory)
  218. {
  219. Item->SubItems->Add("");
  220. }
  221. else
  222. {
  223. Item->SubItems->Add(FormatFloat("#,##0", ChecklistItem->Local.Size));
  224. }
  225. Item->SubItems->Add(UserModificationStr(ChecklistItem->Local.Modification,
  226. ChecklistItem->Local.ModificationFmt));
  227. }
  228. }
  229. Item->SubItems->Add("");
  230. if (ChecklistItem->Action == TSynchronizeChecklist::saDeleteLocal)
  231. {
  232. Item->SubItems->Add("");
  233. Item->SubItems->Add("");
  234. Item->SubItems->Add("");
  235. }
  236. else
  237. {
  238. S = ChecklistItem->Remote.Directory;
  239. if (AnsiSameText(FRemoteDirectory, S.SubString(1, FRemoteDirectory.Length())))
  240. {
  241. S[1] = '.';
  242. S.Delete(2, FRemoteDirectory.Length() - 1);
  243. }
  244. else
  245. {
  246. assert(false);
  247. }
  248. Item->SubItems->Add(S);
  249. if (ChecklistItem->Action == TSynchronizeChecklist::saUploadNew)
  250. {
  251. Item->SubItems->Add("");
  252. Item->SubItems->Add("");
  253. }
  254. else
  255. {
  256. if (ChecklistItem->IsDirectory)
  257. {
  258. Item->SubItems->Add("");
  259. }
  260. else
  261. {
  262. Item->SubItems->Add(FormatFloat("#,##0", ChecklistItem->Remote.Size));
  263. }
  264. Item->SubItems->Add(UserModificationStr(ChecklistItem->Remote.Modification,
  265. ChecklistItem->Remote.ModificationFmt));
  266. }
  267. }
  268. }
  269. //---------------------------------------------------------------------------
  270. void __fastcall TSynchronizeChecklistDialog::LoadList()
  271. {
  272. memset(&FTotals, 0, sizeof(FTotals));
  273. memset(&FChecked, 0, sizeof(FChecked));
  274. FTotals[0] = FChecklist->Count;
  275. FChecked[0] = 0;
  276. ListView->Items->BeginUpdate();
  277. try
  278. {
  279. ListView->Items->Clear();
  280. for (int Index = 0; Index < FChecklist->Count; Index++)
  281. {
  282. const TSynchronizeChecklist::TItem * ChecklistItem =
  283. FChecklist->Item[ListView->Items->Count];
  284. FChangingItemIgnore = true;
  285. try
  286. {
  287. LoadItem(ListView->Items->Add());
  288. }
  289. __finally
  290. {
  291. FChangingItemIgnore = false;
  292. }
  293. FTotals[int(ChecklistItem->Action)]++;
  294. if (ChecklistItem->Checked)
  295. {
  296. FChecked[int(ChecklistItem->Action)]++;
  297. FChecked[0]++;
  298. }
  299. }
  300. }
  301. __finally
  302. {
  303. ListView->Items->EndUpdate();
  304. }
  305. ListView->AlphaSort();
  306. UpdateControls();
  307. }
  308. //---------------------------------------------------------------------------
  309. void __fastcall TSynchronizeChecklistDialog::FormShow(TObject * /*Sender*/)
  310. {
  311. ListView->ColProperties->ParamsStr = CustomWinConfiguration->SynchronizeChecklist.ListParams;
  312. LoadList();
  313. }
  314. //---------------------------------------------------------------------------
  315. void __fastcall TSynchronizeChecklistDialog::ListViewWindowProc(TMessage & Message)
  316. {
  317. if (Message.Msg == CN_NOTIFY)
  318. {
  319. TWMNotify & NotifyMessage = reinterpret_cast<TWMNotify &>(Message);
  320. if (NotifyMessage.NMHdr->code == NM_CUSTOMDRAW)
  321. {
  322. // Due to a bug in VCL, OnAdvancedCustomDrawSubItem is not called for any
  323. // other stage except for cdPrePaint. So we must call it ourselves.
  324. TNMLVCustomDraw * CustomDraw =
  325. reinterpret_cast<TNMLVCustomDraw *>(NotifyMessage.NMHdr);
  326. if (FLAGSET(CustomDraw->nmcd.dwDrawStage, CDDS_ITEM) &&
  327. FLAGSET(CustomDraw->nmcd.dwDrawStage, CDDS_SUBITEM) &&
  328. FLAGSET(CustomDraw->nmcd.dwDrawStage, CDDS_ITEMPOSTPAINT))
  329. {
  330. TListItem * Item = ListView->Items->Item[CustomDraw->nmcd.dwItemSpec];
  331. bool DefaultDraw = true; // not used
  332. // do not know how to convert CustomDraw->nmcd.uItemState to TCustomDrawState
  333. ListViewAdvancedCustomDrawSubItem(ListView, Item, CustomDraw->iSubItem,
  334. TCustomDrawState(), cdPostPaint, DefaultDraw);
  335. }
  336. }
  337. }
  338. FOrigListViewWindowProc(Message);
  339. }
  340. //---------------------------------------------------------------------------
  341. void __fastcall TSynchronizeChecklistDialog::ListViewAdvancedCustomDrawSubItem(
  342. TCustomListView * /*Sender*/, TListItem * Item, int SubItem,
  343. TCustomDrawState /*State*/, TCustomDrawStage Stage, bool & /*DefaultDraw*/)
  344. {
  345. if ((SubItem == 4) && (Stage == cdPostPaint))
  346. {
  347. if (ActionImages->Width <= ListView->Columns->Items[SubItem]->Width)
  348. {
  349. const TSynchronizeChecklist::TItem * ChecklistItem =
  350. static_cast<const TSynchronizeChecklist::TItem *>(Item->Data);
  351. TRect R = Item->DisplayRect(drBounds);
  352. for (int Index = 0; Index < SubItem; Index++)
  353. {
  354. R.Left += ListView->Columns->Items[Index]->Width;
  355. }
  356. R.Left +=
  357. (ListView->Columns->Items[SubItem]->Width - ActionImages->Width) / 2;
  358. ImageList_Draw(reinterpret_cast<HIMAGELIST>(ActionImages->Handle),
  359. int(ChecklistItem->Action), ListView->Canvas->Handle,
  360. R.Left, R.Top, ILD_TRANSPARENT);
  361. }
  362. }
  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. AnsiString PanelText;
  408. if (Possible)
  409. {
  410. PanelText = FORMAT(LoadStrPart(SYNCHRONIZE_SELECTED_ACTIONS, 1),
  411. (FormatFloat("#,##0", FChecked[Panel->Index]),
  412. FormatFloat("#,##0", 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. AnsiString 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("%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 = CompareText(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 = CompareText(ChecklistItem1->Local.Directory, ChecklistItem2->Local.Directory);
  687. }
  688. else
  689. {
  690. assert(!ChecklistItem1->Remote.Directory.IsEmpty());
  691. Compare = CompareText(ChecklistItem1->Remote.Directory, ChecklistItem2->Remote.Directory);
  692. }
  693. if (Compare == 0)
  694. {
  695. Compare = CompareText(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. AnsiString LocalPath =
  743. IncludeTrailingBackslash(ChecklistItem->Local.Directory) +
  744. ChecklistItem->Local.FileName;
  745. LocalFileList->Add(LocalPath);
  746. AnsiString 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. //---------------------------------------------------------------------------