SynchronizeChecklist.cpp 25 KB

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