SynchronizeChecklist.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819
  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 UnicodeString LocalDirectory,
  22. const UnicodeString 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 UnicodeString LocalDirectory, const UnicodeString 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. UnicodeString WindowParams = FormConfiguration.WindowParams;
  90. // if there is no main window, keep previous "custom pos" indication,
  91. bool CustomPos = (StrToIntDef(::CutToChar(WindowParams, L';', true), 0) != 0);
  92. if (Application->MainForm != NULL)
  93. {
  94. CustomPos = (Application->MainForm->BoundsRect != BoundsRect);
  95. }
  96. FormConfiguration.WindowParams =
  97. FORMAT(L"%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. UnicodeString WindowParams = CustomWinConfiguration->SynchronizeChecklist.WindowParams;
  152. bool CustomPos = (StrToIntDef(::CutToChar(WindowParams, L';', 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. UnicodeString 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(L"");
  194. Item->SubItems->Add(L"");
  195. Item->SubItems->Add(L"");
  196. }
  197. else
  198. {
  199. S = ChecklistItem->Local.Directory;
  200. if (AnsiSameText(FLocalDirectory, S.SubString(1, FLocalDirectory.Length())))
  201. {
  202. S[1] = L'.';
  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(L"");
  213. Item->SubItems->Add(L"");
  214. }
  215. else
  216. {
  217. if (ChecklistItem->IsDirectory)
  218. {
  219. Item->SubItems->Add(L"");
  220. }
  221. else
  222. {
  223. Item->SubItems->Add(FormatFloat(L"#,##0", ChecklistItem->Local.Size));
  224. }
  225. Item->SubItems->Add(UserModificationStr(ChecklistItem->Local.Modification,
  226. ChecklistItem->Local.ModificationFmt));
  227. }
  228. }
  229. Item->SubItems->Add(L"");
  230. if (ChecklistItem->Action == TSynchronizeChecklist::saDeleteLocal)
  231. {
  232. Item->SubItems->Add(L"");
  233. Item->SubItems->Add(L"");
  234. Item->SubItems->Add(L"");
  235. }
  236. else
  237. {
  238. S = ChecklistItem->Remote.Directory;
  239. if (AnsiSameText(FRemoteDirectory, S.SubString(1, FRemoteDirectory.Length())))
  240. {
  241. S[1] = L'.';
  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(L"");
  252. Item->SubItems->Add(L"");
  253. }
  254. else
  255. {
  256. if (ChecklistItem->IsDirectory)
  257. {
  258. Item->SubItems->Add(L"");
  259. }
  260. else
  261. {
  262. Item->SubItems->Add(FormatFloat(L"#,##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. (CustomDraw->iSubItem == 4) &&
  330. (ActionImages->Width <= ListView->Columns->Items[CustomDraw->iSubItem]->Width))
  331. {
  332. TListItem * Item = ListView->Items->Item[CustomDraw->nmcd.dwItemSpec];
  333. const TSynchronizeChecklist::TItem * ChecklistItem =
  334. static_cast<const TSynchronizeChecklist::TItem *>(Item->Data);
  335. TRect R = Item->DisplayRect(drBounds);
  336. for (int Index = 0; Index < CustomDraw->iSubItem; Index++)
  337. {
  338. R.Left += ListView->Columns->Items[Index]->Width;
  339. }
  340. R.Left +=
  341. (ListView->Columns->Items[CustomDraw->iSubItem]->Width - ActionImages->Width) / 2;
  342. // doing this from ListViewAdvancedCustomDraw corrupts list view on Windows 7
  343. ImageList_Draw(reinterpret_cast<HIMAGELIST>(ActionImages->Handle),
  344. int(ChecklistItem->Action), CustomDraw->nmcd.hdc,
  345. R.Left, R.Top, ILD_TRANSPARENT);
  346. }
  347. }
  348. }
  349. FOrigListViewWindowProc(Message);
  350. }
  351. //---------------------------------------------------------------------------
  352. void __fastcall TSynchronizeChecklistDialog::ListViewAdvancedCustomDrawSubItem(
  353. TCustomListView * /*Sender*/, TListItem * /*Item*/, int /*SubItem*/,
  354. TCustomDrawState /*State*/, TCustomDrawStage /*Stage*/, bool & /*DefaultDraw*/)
  355. {
  356. // this is just fake handler that makes the list view request custom draw notification above
  357. }
  358. //---------------------------------------------------------------------------
  359. void __fastcall TSynchronizeChecklistDialog::StatusBarDrawPanel(
  360. TStatusBar * StatusBar, TStatusPanel * Panel, const TRect & Rect)
  361. {
  362. bool Possible;
  363. TSynchronizeChecklist::TAction Action = TSynchronizeChecklist::TAction(Panel->Index);
  364. switch (Action)
  365. {
  366. case TSynchronizeChecklist::saNone:
  367. Possible = true;
  368. break;
  369. case TSynchronizeChecklist::saUploadNew:
  370. Possible = ((FMode == smRemote) || (FMode == smBoth)) &&
  371. FLAGCLEAR(FParams, spTimestamp);
  372. break;
  373. case TSynchronizeChecklist::saDownloadNew:
  374. Possible = ((FMode == smLocal) || (FMode == smBoth)) &&
  375. FLAGCLEAR(FParams, spTimestamp);
  376. break;
  377. case TSynchronizeChecklist::saUploadUpdate:
  378. Possible =
  379. ((FMode == smRemote) || (FMode == smBoth)) &&
  380. (FLAGCLEAR(FParams, spNotByTime) || FLAGSET(FParams, spBySize));
  381. break;
  382. case TSynchronizeChecklist::saDownloadUpdate:
  383. Possible =
  384. ((FMode == smLocal) || (FMode == smBoth)) &&
  385. (FLAGCLEAR(FParams, spNotByTime) || FLAGSET(FParams, spBySize));
  386. break;
  387. case TSynchronizeChecklist::saDeleteRemote:
  388. Possible = (FMode == smRemote) &&
  389. FLAGCLEAR(FParams, spTimestamp);
  390. break;
  391. case TSynchronizeChecklist::saDeleteLocal:
  392. Possible = (FMode == smLocal) &&
  393. FLAGCLEAR(FParams, spTimestamp);
  394. break;
  395. default:
  396. assert(false);
  397. Possible = false;
  398. break;
  399. }
  400. int ImageIndex = Panel->Index;
  401. UnicodeString PanelText;
  402. if (Possible)
  403. {
  404. PanelText = FORMAT(LoadStrPart(SYNCHRONIZE_SELECTED_ACTIONS, 1),
  405. (FormatFloat(L"#,##0", FChecked[Panel->Index]),
  406. FormatFloat(L"#,##0", FTotals[Panel->Index])));
  407. }
  408. else
  409. {
  410. PanelText = LoadStrPart(SYNCHRONIZE_SELECTED_ACTIONS, 2);
  411. }
  412. StatusBar->Canvas->TextRect(Rect, Rect.left + 18, Rect.top + 1, PanelText);
  413. ActionImages->Draw(StatusBar->Canvas,
  414. Rect.Left + 1, Rect.Top, ImageIndex, Possible);
  415. }
  416. //---------------------------------------------------------------------------
  417. int __fastcall TSynchronizeChecklistDialog::PanelAt(int X)
  418. {
  419. int Result = 0;
  420. while ((X > StatusBar->Panels->Items[Result]->Width) &&
  421. (Result < StatusBar->Panels->Count - 1))
  422. {
  423. X -= StatusBar->Panels->Items[Result]->Width;
  424. Result++;
  425. }
  426. return ((Result < StatusBar->Panels->Count - 1) ? Result : -1);
  427. }
  428. //---------------------------------------------------------------------------
  429. void __fastcall TSynchronizeChecklistDialog::StatusBarMouseMove(
  430. TObject * /*Sender*/, TShiftState /*Shift*/, int X, int /*Y*/)
  431. {
  432. UnicodeString Hint;
  433. int IPanel = PanelAt(X);
  434. if (IPanel >= 0)
  435. {
  436. Hint = StatusBar->Panels->Items[IPanel]->Text;
  437. if (IPanel > 0)
  438. {
  439. Hint = FORMAT(L"%s\n%s", (Hint, FGeneralHint));
  440. }
  441. }
  442. if (Hint != StatusBar->Hint)
  443. {
  444. Application->CancelHint();
  445. StatusBar->Hint = Hint;
  446. }
  447. }
  448. //---------------------------------------------------------------------------
  449. void __fastcall TSynchronizeChecklistDialog::ListViewChange(
  450. TObject * /*Sender*/, TListItem * Item, TItemChange Change)
  451. {
  452. if ((Change == ctState) && (FChangingItem == Item) && (FChangingItem != NULL))
  453. {
  454. if (!FChangingItemIgnore)
  455. {
  456. assert(Item->Data != NULL);
  457. if ((FChangingItemChecked != Item->Checked) && (Item->Data != NULL))
  458. {
  459. const TSynchronizeChecklist::TItem * ChecklistItem =
  460. static_cast<const TSynchronizeChecklist::TItem *>(Item->Data);
  461. if (Item->Checked)
  462. {
  463. FChecked[int(ChecklistItem->Action)]++;
  464. FChecked[0]++;
  465. }
  466. else
  467. {
  468. FChecked[int(ChecklistItem->Action)]--;
  469. FChecked[0]--;
  470. }
  471. if (!FChangingItemMass)
  472. {
  473. UpdateControls();
  474. }
  475. }
  476. }
  477. FChangingItem = NULL;
  478. }
  479. }
  480. //---------------------------------------------------------------------------
  481. void __fastcall TSynchronizeChecklistDialog::ListViewChanging(
  482. TObject * /*Sender*/, TListItem * Item, TItemChange Change,
  483. bool & /*AllowChange*/)
  484. {
  485. if (Change == ctState)
  486. {
  487. FChangingItem = Item;
  488. FChangingItemChecked = Item->Checked;
  489. }
  490. else
  491. {
  492. assert(FChangingItem == NULL);
  493. FChangingItem = NULL;
  494. }
  495. }
  496. //---------------------------------------------------------------------------
  497. void __fastcall TSynchronizeChecklistDialog::CheckAll(bool Check)
  498. {
  499. FChangingItemMass = true;
  500. try
  501. {
  502. for (int Index = 0; Index < ListView->Items->Count; Index++)
  503. {
  504. ListView->Items->Item[Index]->Checked = Check;
  505. }
  506. }
  507. __finally
  508. {
  509. FChangingItemMass = false;
  510. }
  511. UpdateControls();
  512. }
  513. //---------------------------------------------------------------------------
  514. void __fastcall TSynchronizeChecklistDialog::CheckAllButtonClick(TObject * Sender)
  515. {
  516. CheckAll(Sender == CheckAllButton);
  517. }
  518. //---------------------------------------------------------------------------
  519. void __fastcall TSynchronizeChecklistDialog::CheckButtonClick(
  520. TObject * Sender)
  521. {
  522. FChangingItemMass = true;
  523. try
  524. {
  525. TListItem * Item = ListView->Selected;
  526. while (Item != NULL)
  527. {
  528. TComponent * Component = dynamic_cast<TComponent *>(Sender);
  529. assert(Component != NULL);
  530. Item->Checked = (Component->Tag != 0);
  531. Item = ListView->GetNextItem(Item, sdAll, TItemStates() << isSelected);
  532. }
  533. }
  534. __finally
  535. {
  536. FChangingItemMass = false;
  537. }
  538. UpdateControls();
  539. }
  540. //---------------------------------------------------------------------------
  541. void __fastcall TSynchronizeChecklistDialog::ListViewSelectItem(
  542. TObject * /*Sender*/, TListItem * /*Item*/, bool /*Selected*/)
  543. {
  544. // Delayed update of button status in case many items are being selected at once
  545. // Also change of selection causes buttons to flash, as for short period of time,
  546. // no item is selected
  547. UpdateTimer->Enabled = true;
  548. }
  549. //---------------------------------------------------------------------------
  550. void __fastcall TSynchronizeChecklistDialog::StatusBarResize(
  551. TObject * Sender)
  552. {
  553. RepaintStatusBar(dynamic_cast<TCustomStatusBar *>(Sender));
  554. }
  555. //---------------------------------------------------------------------------
  556. void __fastcall TSynchronizeChecklistDialog::UpdateTimerTimer(
  557. TObject * /*Sender*/)
  558. {
  559. UpdateTimer->Enabled = false;
  560. UpdateControls();
  561. }
  562. //---------------------------------------------------------------------------
  563. TListItem * __fastcall TSynchronizeChecklistDialog::SelectAll(bool Select, int Action,
  564. bool OnlyTheAction)
  565. {
  566. TListItem * Result = NULL;
  567. for (int Index = 0; Index < ListView->Items->Count; Index++)
  568. {
  569. TListItem * Item = ListView->Items->Item[Index];
  570. if (Action == 0)
  571. {
  572. Item->Selected = Select;
  573. if (Result == NULL)
  574. {
  575. Result = Item;
  576. }
  577. }
  578. else
  579. {
  580. const TSynchronizeChecklist::TItem * ChecklistItem =
  581. static_cast<const TSynchronizeChecklist::TItem *>(Item->Data);
  582. bool WantedAction = (int(ChecklistItem->Action) == Action);
  583. if (WantedAction || !OnlyTheAction)
  584. {
  585. Item->Selected = Select && WantedAction;
  586. if (WantedAction && (Result == NULL))
  587. {
  588. Result = Item;
  589. }
  590. }
  591. }
  592. }
  593. return Result;
  594. }
  595. //---------------------------------------------------------------------------
  596. void __fastcall TSynchronizeChecklistDialog::SelectAllItemClick(
  597. TObject * /*Sender*/)
  598. {
  599. SelectAll(true);
  600. }
  601. //---------------------------------------------------------------------------
  602. void __fastcall TSynchronizeChecklistDialog::StatusBarMouseDown(
  603. TObject * /*Sender*/, TMouseButton /*Button*/, TShiftState Shift, int X,
  604. int /*Y*/)
  605. {
  606. int IPanel = PanelAt(X);
  607. if (IPanel >= 0)
  608. {
  609. TListItem * Item = SelectAll(true, IPanel, Shift.Contains(ssCtrl));
  610. if (Item != NULL)
  611. {
  612. Item->MakeVisible(false);
  613. Item->Focused = true;
  614. ListView->SetFocus();
  615. }
  616. }
  617. }
  618. //---------------------------------------------------------------------------
  619. int __fastcall TSynchronizeChecklistDialog::CompareNumber(__int64 Value1,
  620. __int64 Value2)
  621. {
  622. int Result;
  623. if (Value1 < Value2)
  624. {
  625. Result = -1;
  626. }
  627. else if (Value1 == Value2)
  628. {
  629. Result = 0;
  630. }
  631. else
  632. {
  633. Result = 1;
  634. }
  635. return Result;
  636. }
  637. //---------------------------------------------------------------------------
  638. void __fastcall TSynchronizeChecklistDialog::ListViewCompare(
  639. TObject * /*Sender*/, TListItem * Item1, TListItem * Item2, int /*Data*/,
  640. int & Compare)
  641. {
  642. const TSynchronizeChecklist::TItem * ChecklistItem1 =
  643. static_cast<const TSynchronizeChecklist::TItem *>(Item1->Data);
  644. const TSynchronizeChecklist::TItem * ChecklistItem2 =
  645. static_cast<const TSynchronizeChecklist::TItem *>(Item2->Data);
  646. TIEListViewColProperties * ColProperties =
  647. dynamic_cast<TIEListViewColProperties *>(ListView->ColProperties);
  648. switch (ColProperties->SortColumn)
  649. {
  650. case 0: // name
  651. Compare = AnsiCompareText(ChecklistItem1->GetFileName(), ChecklistItem2->GetFileName());
  652. break;
  653. // sorting by local and remote dir is the same
  654. case 1: // local dir
  655. case 5: // remote dir
  656. Compare = 0; // default sorting
  657. break;
  658. case 2: // local size
  659. Compare = CompareNumber(ChecklistItem1->Local.Size, ChecklistItem2->Local.Size);
  660. break;
  661. case 3: // local changed
  662. Compare = CompareFileTime(ChecklistItem1->Local.Modification,
  663. ChecklistItem2->Local.Modification);
  664. break;
  665. case 4: // action
  666. Compare = CompareNumber(ChecklistItem1->Action, ChecklistItem2->Action);
  667. break;
  668. case 6: // remote size
  669. Compare = CompareNumber(ChecklistItem1->Remote.Size, ChecklistItem2->Remote.Size);
  670. break;
  671. case 7: // remote changed
  672. Compare = CompareFileTime(ChecklistItem1->Remote.Modification,
  673. ChecklistItem2->Remote.Modification);
  674. break;
  675. }
  676. if (Compare == 0)
  677. {
  678. if (!ChecklistItem1->Local.Directory.IsEmpty())
  679. {
  680. Compare = AnsiCompareText(ChecklistItem1->Local.Directory, ChecklistItem2->Local.Directory);
  681. }
  682. else
  683. {
  684. assert(!ChecklistItem1->Remote.Directory.IsEmpty());
  685. Compare = AnsiCompareText(ChecklistItem1->Remote.Directory, ChecklistItem2->Remote.Directory);
  686. }
  687. if (Compare == 0)
  688. {
  689. Compare = AnsiCompareText(ChecklistItem1->GetFileName(), ChecklistItem2->GetFileName());
  690. }
  691. }
  692. if (!ColProperties->SortAscending)
  693. {
  694. Compare = -Compare;
  695. }
  696. }
  697. //---------------------------------------------------------------------------
  698. void __fastcall TSynchronizeChecklistDialog::ListViewSecondaryColumnHeader(
  699. TCustomIEListView * /*Sender*/, int Index, int & SecondaryColumn)
  700. {
  701. // "remote dir" column is sorting alias for "local dir" column
  702. if (Index == 5)
  703. {
  704. SecondaryColumn = 1;
  705. }
  706. else
  707. {
  708. SecondaryColumn = -1;
  709. }
  710. }
  711. //---------------------------------------------------------------------------
  712. void __fastcall TSynchronizeChecklistDialog::ListViewContextPopup(
  713. TObject * Sender, TPoint & MousePos, bool & Handled)
  714. {
  715. // to update source popup menu before TBX menu is created
  716. UpdateControls();
  717. MenuPopup(Sender, MousePos, Handled);
  718. }
  719. //---------------------------------------------------------------------------
  720. void __fastcall TSynchronizeChecklistDialog::CustomCommandsButtonClick(
  721. TObject * /*Sender*/)
  722. {
  723. TStrings * LocalFileList = new TStringList();
  724. TStrings * RemoteFileList = new TStringList();
  725. try
  726. {
  727. TListItem * Item = ListView->Selected;
  728. assert(Item != NULL);
  729. while (Item != NULL)
  730. {
  731. const TSynchronizeChecklist::TItem * ChecklistItem =
  732. static_cast<const TSynchronizeChecklist::TItem *>(Item->Data);
  733. assert((ChecklistItem->Action == TSynchronizeChecklist::saUploadUpdate) ||
  734. (ChecklistItem->Action == TSynchronizeChecklist::saDownloadUpdate));
  735. assert(ChecklistItem->RemoteFile != NULL);
  736. UnicodeString LocalPath =
  737. IncludeTrailingBackslash(ChecklistItem->Local.Directory) +
  738. ChecklistItem->Local.FileName;
  739. LocalFileList->Add(LocalPath);
  740. UnicodeString RemotePath =
  741. UnixIncludeTrailingBackslash(ChecklistItem->Remote.Directory) +
  742. ChecklistItem->Remote.FileName;
  743. RemoteFileList->AddObject(RemotePath, ChecklistItem->RemoteFile);
  744. Item = ListView->GetNextItem(Item, sdAll, TItemStates() << isSelected);
  745. }
  746. }
  747. catch(...)
  748. {
  749. delete LocalFileList;
  750. delete RemoteFileList;
  751. throw;
  752. }
  753. assert(FOnCustomCommandMenu != NULL);
  754. FOnCustomCommandMenu(CustomCommandsButton,
  755. CustomCommandsButton->ClientToScreen(TPoint(0, CustomCommandsButton->Height)),
  756. LocalFileList, RemoteFileList);
  757. }
  758. //---------------------------------------------------------------------------