Properties.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783
  1. //---------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include "WinInterface.h"
  5. #include "Properties.h"
  6. #include <VCLCommon.h>
  7. #include <Common.h>
  8. #include <Terminal.h>
  9. #include <TextsWin.h>
  10. #include <GUITools.h>
  11. #include <CoreMain.h>
  12. #include <Tools.h>
  13. #include <BaseUtils.hpp>
  14. //---------------------------------------------------------------------
  15. #pragma link "PathLabel"
  16. #pragma link "Rights"
  17. #pragma link "RightsExt"
  18. #ifndef NO_RESOURCES
  19. #pragma resource "*.dfm"
  20. #endif
  21. //---------------------------------------------------------------------
  22. bool __fastcall DoPropertiesDialog(TStrings * FileList,
  23. const UnicodeString Directory, const TRemoteTokenList * GroupList,
  24. const TRemoteTokenList * UserList, TStrings * ChecksumAlgs,
  25. TRemoteProperties * Properties,
  26. int AllowedChanges, bool UserGroupByID, TCalculateSizeEvent OnCalculateSize,
  27. TCalculateChecksumEvent OnCalculateChecksum)
  28. {
  29. bool Result;
  30. TPropertiesDialog * PropertiesDialog = new TPropertiesDialog(Application,
  31. FileList, Directory, GroupList, UserList, ChecksumAlgs, AllowedChanges, UserGroupByID,
  32. OnCalculateSize, OnCalculateChecksum);
  33. try
  34. {
  35. Result = PropertiesDialog->Execute(*Properties);
  36. }
  37. __finally
  38. {
  39. delete PropertiesDialog;
  40. }
  41. return Result;
  42. }
  43. //---------------------------------------------------------------------
  44. __fastcall TPropertiesDialog::TPropertiesDialog(TComponent* AOwner,
  45. TStrings * FileList, const UnicodeString Directory,
  46. const TRemoteTokenList * GroupList, const TRemoteTokenList * UserList,
  47. TStrings * ChecksumAlgs,
  48. int AllowedChanges, bool UserGroupByID, TCalculateSizeEvent OnCalculateSize,
  49. TCalculateChecksumEvent OnCalculateChecksum)
  50. : TForm(AOwner)
  51. {
  52. FOnCalculateSize = OnCalculateSize;
  53. FOnCalculateChecksum = OnCalculateChecksum;
  54. RightsFrame->OnChange = ControlChange;
  55. FFileList = new TStringList();
  56. FFileList->Assign(FileList);
  57. FAllowedChanges = AllowedChanges;
  58. FUserGroupByID = UserGroupByID;
  59. FAllowCalculateStats = false;
  60. FStatsNotCalculated = false;
  61. FChecksumLoaded = false;
  62. FMultipleChecksum = false;
  63. LocationLabel->Caption = Directory;
  64. FGroupList = GroupList;
  65. FUserList = UserList;
  66. FChecksumAlgs = ChecksumAlgs;
  67. LoadInfo();
  68. UseSystemSettings(this);
  69. }
  70. //---------------------------------------------------------------------------
  71. __fastcall TPropertiesDialog::~TPropertiesDialog()
  72. {
  73. delete FFileList;
  74. FFileList = NULL;
  75. }
  76. //---------------------------------------------------------------------
  77. bool __fastcall TPropertiesDialog::Execute(TRemoteProperties & Properties)
  78. {
  79. SetFileProperties(Properties);
  80. PageControl->ActivePage = CommonSheet;
  81. if (FAllowedChanges & cpGroup) ActiveControl = GroupComboBox;
  82. else
  83. if (FAllowedChanges & cpOwner) ActiveControl = OwnerComboBox;
  84. else
  85. if (FAllowedChanges & cpMode) ActiveControl = RightsFrame;
  86. else ActiveControl = CancelButton;
  87. if (DebugAlwaysTrue(FChecksumAlgs != NULL))
  88. {
  89. ChecksumAlgEdit->Items->Assign(FChecksumAlgs);
  90. int ChecksumIndex = FChecksumAlgs->IndexOf(GUIConfiguration->ChecksumAlg);
  91. if (ChecksumIndex < 0)
  92. {
  93. ChecksumIndex = 0;
  94. }
  95. ChecksumAlgEdit->ItemIndex = ChecksumIndex;
  96. }
  97. ResetChecksum();
  98. UpdateControls();
  99. bool Result = (ShowModal() == DefaultResult());
  100. if (Result)
  101. {
  102. Properties = GetFileProperties();
  103. }
  104. return Result;
  105. }
  106. //---------------------------------------------------------------------------
  107. TModalResult __fastcall TPropertiesDialog::DefaultResult()
  108. {
  109. // Fallback when ChecksumButton is default
  110. return ::DefaultResult(this, OkButton);
  111. }
  112. //---------------------------------------------------------------------------
  113. UnicodeString __fastcall TPropertiesDialog::LoadRemoteToken(
  114. const TRemoteToken & Token)
  115. {
  116. UnicodeString Result;
  117. if (FUserGroupByID)
  118. {
  119. if (Token.IDValid)
  120. {
  121. if (Token.NameValid)
  122. {
  123. Result = FORMAT(L"%s [%d]", (Token.Name, int(Token.ID)));
  124. }
  125. else
  126. {
  127. Result = FORMAT(L"[%d]", (int(Token.ID)));
  128. }
  129. }
  130. else
  131. {
  132. // be it valid or not
  133. Result = Token.Name;
  134. }
  135. }
  136. else
  137. {
  138. // what if name is not filled in?
  139. Result = Token.Name;
  140. }
  141. return Result;
  142. }
  143. //---------------------------------------------------------------------------
  144. void __fastcall TPropertiesDialog::LoadRemoteToken(
  145. TComboBox * ComboBox, bool Valid, const TRemoteToken & Token)
  146. {
  147. if (Valid)
  148. {
  149. ComboBox->Text = LoadRemoteToken(Token);
  150. }
  151. else
  152. {
  153. ComboBox->Text = L"";
  154. }
  155. }
  156. //---------------------------------------------------------------------------
  157. void __fastcall TPropertiesDialog::LoadRemoteTokens(TComboBox * ComboBox,
  158. const TRemoteTokenList * List)
  159. {
  160. TStrings * Items = ComboBox->Items;
  161. Items->BeginUpdate();
  162. try
  163. {
  164. Items->Clear();
  165. if (List != NULL)
  166. {
  167. int Count = List->Count();
  168. for (int Index = 0; Index < Count; Index++)
  169. {
  170. Items->Add(LoadRemoteToken(*List->Token(Index)));
  171. }
  172. }
  173. }
  174. __finally
  175. {
  176. Items->EndUpdate();
  177. }
  178. }
  179. //---------------------------------------------------------------------------
  180. void __fastcall TPropertiesDialog::LoadInfo()
  181. {
  182. DebugAssert(FFileList->Count > 0);
  183. FMultiple = FFileList->Count > 1;
  184. FMultipleChecksum = FMultiple;
  185. FAllowCalculateStats = false;
  186. FStatsNotCalculated = false;
  187. __int64 FilesSize = 0;
  188. TCalculateSizeStats Stats;
  189. for (int Index = 0; Index < FFileList->Count; Index++)
  190. {
  191. TRemoteFile * File = (TRemoteFile *)(FFileList->Objects[Index]);
  192. if (File->IsDirectory)
  193. {
  194. Stats.Directories++;
  195. // we should use TTerminal::CanRecurseToDirectory instead
  196. if (!File->IsSymLink)
  197. {
  198. FAllowCalculateStats = true;
  199. FStatsNotCalculated = true;
  200. FMultipleChecksum = true;
  201. }
  202. }
  203. else
  204. {
  205. Stats.Files++;
  206. }
  207. if (File->IsSymLink)
  208. {
  209. Stats.SymLinks++;
  210. }
  211. FilesSize += File->Size;
  212. }
  213. LoadRemoteTokens(GroupComboBox, FGroupList);
  214. LoadRemoteTokens(OwnerComboBox, FUserList);
  215. RightsFrame->AllowAddXToDirectories = (Stats.Directories > 0);
  216. RecursiveCheck->Visible = (Stats.Directories > 0);
  217. RecursiveBevel->Visible = (Stats.Directories > 0);
  218. LoadStats(FilesSize, Stats);
  219. RightsFrame->AllowUndef = FMultiple;
  220. if (!FMultiple)
  221. {
  222. TRemoteFile * File = (TRemoteFile *)(FFileList->Objects[0]);
  223. DebugAssert(File);
  224. UpdateFileImage();
  225. LinksToLabelLabel->Visible = File->IsSymLink;
  226. LinksToLabel->Visible = File->IsSymLink;
  227. if (File->IsSymLink)
  228. {
  229. LinksToLabel->Caption = File->LinkTo;
  230. }
  231. RightsFrame->AllowAddXToDirectories = File->IsDirectory;
  232. Caption = FMTLOAD(PROPERTIES_FILE_CAPTION, (File->FileName));
  233. RecursiveCheck->Visible = File->IsDirectory;
  234. RecursiveBevel->Visible = File->IsDirectory;
  235. }
  236. else
  237. {
  238. Caption = FMTLOAD(PROPERTIES_FILES_CAPTION, (FFileList->Strings[0]));
  239. LinksToLabelLabel->Hide();
  240. LinksToLabel->Hide();
  241. LoadDialogImage(FileIconImage, L"Multiple Files");
  242. }
  243. ChecksumGroup->Visible = !FMultipleChecksum;
  244. ChecksumView->Visible = FMultipleChecksum;
  245. }
  246. //---------------------------------------------------------------------------
  247. void __fastcall TPropertiesDialog::UpdateFileImage()
  248. {
  249. TImageList * ImageList = ShellImageListForControl(this, ilsLarge);
  250. FileIconImage->Picture->Bitmap = NULL;
  251. TRemoteFile * File = (TRemoteFile *)(FFileList->Objects[0]);
  252. // shell image list does not have fixed large icon size
  253. // (it is probably 32x32 min, but can be larger, on xp it is 48x48 if
  254. // large icons are enabled, on vista can be even larger).
  255. // so we stretch (shrink) the icon to 32x32 here to be sure.
  256. Graphics::TBitmap * Bitmap = new Graphics::TBitmap;
  257. try
  258. {
  259. ImageList->GetBitmap(File->IconIndex, Bitmap);
  260. int Size = DialogImageSize(this);
  261. // Use exact DPI-scaled size, not approximate scaling by font size.
  262. // Otherwise we stretch icons unnecessarily because the canvas
  263. // is one or two pixels off the icon size
  264. FileIconImage->Width = Size;
  265. FileIconImage->Height = Size;
  266. FileIconImage->Picture->Bitmap->Width = Size;
  267. FileIconImage->Picture->Bitmap->Height = Size;
  268. FileIconImage->Picture->Bitmap->Canvas->StretchDraw(
  269. TRect(0, 0, Size, Size),
  270. Bitmap);
  271. }
  272. __finally
  273. {
  274. delete Bitmap;
  275. }
  276. }
  277. //---------------------------------------------------------------------------
  278. void __fastcall TPropertiesDialog::LoadStats(__int64 FilesSize,
  279. const TCalculateSizeStats & Stats)
  280. {
  281. UnicodeString SizeStr;
  282. UnicodeString FilesStr;
  283. if (FStatsNotCalculated)
  284. {
  285. SizeStr = LoadStr(PROPERTIES_UNKNOWN_SIZE);
  286. }
  287. else
  288. {
  289. SizeStr = FormatBytes(FilesSize);
  290. UnicodeString SizeUnorderedStr = FormatBytes(FilesSize, fbNone);
  291. if (SizeStr != SizeUnorderedStr)
  292. {
  293. SizeStr = FORMAT(L"%s (%s)", (SizeStr, SizeUnorderedStr));
  294. }
  295. }
  296. if (((Stats.Files + Stats.Directories) == 0) && !FMultiple)
  297. {
  298. TRemoteFile * File = (TRemoteFile *)(FFileList->Objects[0]);
  299. DebugAssert(File != NULL);
  300. FilesStr = File->FileName;
  301. }
  302. else
  303. {
  304. if (Stats.Files > 0)
  305. {
  306. FilesStr = (Stats.Files == 1) ? FMTLOAD(PROPERTIES_FILE, (Stats.Files)) :
  307. FMTLOAD(PROPERTIES_FILES, (Stats.Files));
  308. if (Stats.Directories > 0)
  309. {
  310. FilesStr = FORMAT(L"%s, ", (FilesStr));
  311. }
  312. }
  313. if (Stats.Directories > 0)
  314. {
  315. FilesStr += (Stats.Directories == 1) ? FMTLOAD(PROPERTIES_DIRECTORY, (Stats.Directories)) :
  316. FMTLOAD(PROPERTIES_DIRECTORIES, (Stats.Directories));
  317. }
  318. if (Stats.SymLinks > 0)
  319. {
  320. UnicodeString SymLinksStr;
  321. SymLinksStr = (Stats.SymLinks == 1) ? FMTLOAD(PROPERTIES_SYMLINK, (Stats.SymLinks)) :
  322. FMTLOAD(PROPERTIES_SYMLINKS, (Stats.SymLinks));
  323. FilesStr = FORMAT(L"%s (%s)", (FilesStr, SymLinksStr));
  324. }
  325. }
  326. SizeLabel->Caption = SizeStr;
  327. FileLabel->Caption = FilesStr;
  328. }
  329. //---------------------------------------------------------------------------
  330. void __fastcall TPropertiesDialog::SetFileProperties(const TRemoteProperties & value)
  331. {
  332. TValidProperties Valid;
  333. if (value.Valid.Contains(vpRights) && FAllowedChanges & cpMode) Valid << vpRights;
  334. if (value.Valid.Contains(vpOwner) && FAllowedChanges & cpOwner) Valid << vpOwner;
  335. if (value.Valid.Contains(vpGroup) && FAllowedChanges & cpGroup) Valid << vpGroup;
  336. FOrigProperties = value;
  337. FOrigProperties.Valid = Valid;
  338. FOrigProperties.Recursive = false;
  339. if (value.Valid.Contains(vpRights))
  340. {
  341. RightsFrame->Rights = value.Rights;
  342. RightsFrame->AddXToDirectories = value.AddXToDirectories;
  343. }
  344. else
  345. {
  346. RightsFrame->Rights = TRights();
  347. RightsFrame->AddXToDirectories = false;
  348. }
  349. LoadRemoteToken(GroupComboBox, value.Valid.Contains(vpGroup), value.Group);
  350. LoadRemoteToken(OwnerComboBox, value.Valid.Contains(vpOwner), value.Owner);
  351. RecursiveCheck->Checked = value.Recursive;
  352. UpdateControls();
  353. }
  354. //---------------------------------------------------------------------------
  355. void __fastcall TPropertiesDialog::StoreRemoteToken(unsigned int ID,
  356. const UnicodeString & Text, const TRemoteTokenList * List, TRemoteToken & Result)
  357. {
  358. DebugAssert(List != NULL);
  359. const TRemoteToken * Token = List->Find(ID);
  360. if (Token == NULL)
  361. {
  362. Result.ID = ID;
  363. Result.Name = Text;
  364. }
  365. else
  366. {
  367. Result = *Token;
  368. }
  369. }
  370. //---------------------------------------------------------------------------
  371. TRemoteToken __fastcall TPropertiesDialog::StoreRemoteToken(const TRemoteToken & Orig,
  372. UnicodeString Text, int Message, const TRemoteTokenList * List)
  373. {
  374. TRemoteToken Result;
  375. Text = Text.Trim();
  376. if (!Text.IsEmpty())
  377. {
  378. if (FUserGroupByID)
  379. {
  380. DebugAssert(List != NULL);
  381. int IDStart = Text.LastDelimiter(L"[");
  382. if (!Text.IsEmpty() && (IDStart >= 0) && (Text[Text.Length()] == L']'))
  383. {
  384. int ID;
  385. UnicodeString IDStr = Text.SubString(IDStart + 1, Text.Length() - IDStart - 1);
  386. if (!TryStrToInt(IDStr, ID))
  387. {
  388. throw Exception(Message);
  389. }
  390. else
  391. {
  392. StoreRemoteToken(ID, Text.SubString(1, IDStart - 1).Trim(), List, Result);
  393. }
  394. }
  395. else
  396. {
  397. const TRemoteToken * Token = List->Find(Text);
  398. if (Token == NULL)
  399. {
  400. int ID;
  401. if (TryStrToInt(Text, ID))
  402. {
  403. StoreRemoteToken(ID, Text, List, Result);
  404. }
  405. else
  406. {
  407. throw Exception(MainInstructions(FMTLOAD(PROPERTIES_UNKNOWN_TOKEN, (Text))));
  408. }
  409. }
  410. else
  411. {
  412. Result = *Token;
  413. }
  414. }
  415. }
  416. else
  417. {
  418. Result.Name = Text;
  419. }
  420. }
  421. if (LoadRemoteToken(Result) == LoadRemoteToken(Orig))
  422. {
  423. Result = Orig;
  424. }
  425. return Result;
  426. }
  427. //---------------------------------------------------------------------------
  428. void __fastcall TPropertiesDialog::StoreRemoteToken(TComboBox * ComboBox,
  429. int ChangeFlag, TValidProperty PropertyFlag, const TRemoteToken & Orig,
  430. TRemoteToken & Token, int Message, const TRemoteTokenList * List,
  431. TRemoteProperties & Properties)
  432. {
  433. UnicodeString Text = ComboBox->Text.Trim();
  434. if (FLAGSET(FAllowedChanges, ChangeFlag))
  435. {
  436. Token = StoreRemoteToken(Orig, Text, Message, List);
  437. if (Token.IsSet)
  438. {
  439. Properties.Valid << PropertyFlag;
  440. }
  441. }
  442. }
  443. //---------------------------------------------------------------------------
  444. TRemoteProperties __fastcall TPropertiesDialog::GetFileProperties()
  445. {
  446. TRemoteProperties Result;
  447. if (FAllowedChanges & cpMode)
  448. {
  449. Result.Valid << vpRights;
  450. Result.Rights = RightsFrame->Rights;
  451. Result.AddXToDirectories = RightsFrame->AddXToDirectories;
  452. }
  453. StoreRemoteToken(GroupComboBox, cpGroup, vpGroup, FOrigProperties.Group,
  454. Result.Group, PROPERTIES_INVALID_GROUP, FGroupList, Result);
  455. StoreRemoteToken(OwnerComboBox, cpOwner, vpOwner, FOrigProperties.Owner,
  456. Result.Owner, PROPERTIES_INVALID_OWNER, FUserList, Result);
  457. Result.Recursive = RecursiveCheck->Checked;
  458. return Result;
  459. }
  460. //---------------------------------------------------------------------------
  461. void __fastcall TPropertiesDialog::ControlChange(TObject * /*Sender*/)
  462. {
  463. if (Visible)
  464. {
  465. UpdateControls();
  466. }
  467. }
  468. //---------------------------------------------------------------------------
  469. void __fastcall TPropertiesDialog::UpdateControls()
  470. {
  471. // No point enabling recursive check if there's no change allowed (supported),
  472. // i.e. with WebDAV.
  473. EnableControl(RecursiveCheck, ((FAllowedChanges & (cpGroup | cpOwner | cpMode)) != 0));
  474. bool Allow;
  475. try
  476. {
  477. Allow =
  478. !TRemoteProperties::ChangedProperties(FOrigProperties, GetFileProperties()).Valid.Empty() ||
  479. (RecursiveCheck->Enabled && RecursiveCheck->Checked);
  480. }
  481. catch(...)
  482. {
  483. // when properties are invalid allow submitting the form,
  484. // because that reveals the cause to the user, otherwise he/she
  485. // may not be able to tell what is wrong
  486. Allow = true;
  487. }
  488. EnableControl(OkButton, Allow);
  489. EnableControl(GroupComboBox, FAllowedChanges & cpGroup);
  490. EnableControl(OwnerComboBox, FAllowedChanges & cpOwner);
  491. EnableControl(RightsFrame, FAllowedChanges & cpMode);
  492. CalculateSizeButton->Visible = FAllowCalculateStats;
  493. if (!FMultiple)
  494. {
  495. // when setting properties for one file only, allow undef state
  496. // only when the input right explicitly requires it or
  497. // when "recursive" is on (possible for directory only).
  498. bool AllowUndef =
  499. (FOrigProperties.Valid.Contains(vpRights) &&
  500. FOrigProperties.Rights.AllowUndef) ||
  501. (RecursiveCheck->Checked);
  502. if (!AllowUndef)
  503. {
  504. // when disallowing undef state, make sure, all undef are turned into unset
  505. RightsFrame->Rights = TRights(RightsFrame->Rights.NumberSet);
  506. }
  507. RightsFrame->AllowUndef = AllowUndef;
  508. }
  509. EnableControl(ChecksumSheet, ChecksumSupported());
  510. EnableControl(ChecksumButton, ChecksumSheet->Enabled &&
  511. !ChecksumAlgEdit->Text.IsEmpty());
  512. // hide checksum edit at least if it is disabled to get rid of ugly
  513. // visage on XP
  514. ChecksumEdit->Visible = ChecksumEdit->Enabled;
  515. DefaultButton(ChecksumButton, ChecksumAlgEdit->Focused());
  516. DefaultButton(OkButton, !ChecksumAlgEdit->Focused());
  517. }
  518. //---------------------------------------------------------------------------
  519. void __fastcall TPropertiesDialog::FormCloseQuery(TObject * /*Sender*/,
  520. bool & /*CanClose*/)
  521. {
  522. if (ModalResult == DefaultResult())
  523. {
  524. ExitActiveControl(this);
  525. }
  526. }
  527. //---------------------------------------------------------------------------
  528. void __fastcall TPropertiesDialog::CalculateSizeButtonClick(
  529. TObject * /*Sender*/)
  530. {
  531. DebugAssert(FOnCalculateSize != NULL);
  532. bool DoClose = false;
  533. Enabled = false;
  534. try
  535. {
  536. __int64 Size;
  537. TCalculateSizeStats Stats;
  538. FOnCalculateSize(FFileList, Size, Stats, DoClose);
  539. FStatsNotCalculated = false;
  540. LoadStats(Size, Stats);
  541. }
  542. __finally
  543. {
  544. Enabled = true;
  545. if (DoClose)
  546. {
  547. Close();
  548. }
  549. }
  550. }
  551. //---------------------------------------------------------------------------
  552. void __fastcall TPropertiesDialog::HelpButtonClick(TObject * /*Sender*/)
  553. {
  554. FormHelp(this);
  555. }
  556. //---------------------------------------------------------------------------
  557. void __fastcall TPropertiesDialog::ResetChecksum()
  558. {
  559. ChecksumView->Items->Clear();
  560. ChecksumEdit->Text = LoadStr(PROPERTIES_CHECKSUM_UNKNOWN);
  561. AutoSizeListColumnsWidth(ChecksumView);
  562. }
  563. //---------------------------------------------------------------------------
  564. void __fastcall TPropertiesDialog::CalculateChecksum()
  565. {
  566. DebugAssert(FOnCalculateChecksum != NULL);
  567. ResetChecksum();
  568. FChecksumLoaded = true;
  569. FAlgUsed = UnicodeString();
  570. bool DoClose = false;
  571. try
  572. {
  573. FOnCalculateChecksum(ChecksumAlgEdit->Text, FFileList, CalculatedChecksum, DoClose);
  574. }
  575. __finally
  576. {
  577. if (DoClose)
  578. {
  579. Close();
  580. }
  581. }
  582. // If we successfully used the selected checksum, remember it (in normalized form)
  583. if (!FAlgUsed.IsEmpty())
  584. {
  585. GUIConfiguration->ChecksumAlg = FAlgUsed;
  586. }
  587. AutoSizeListColumnsWidth(ChecksumView);
  588. }
  589. //---------------------------------------------------------------------------
  590. void __fastcall TPropertiesDialog::CalculatedChecksum(
  591. const UnicodeString & FileName, const UnicodeString & Alg,
  592. const UnicodeString & Hash)
  593. {
  594. if (FMultipleChecksum)
  595. {
  596. TListItem * Item = ChecksumView->Items->Add();
  597. Item->Caption = FileName;
  598. Item->SubItems->Add(Hash);
  599. // optimization
  600. int TopIndex = ListView_GetTopIndex(ChecksumView->Handle);
  601. int Index = Item->Index;
  602. if ((TopIndex <= Index) &&
  603. (Index <= TopIndex + ChecksumView->VisibleRowCount))
  604. {
  605. AutoSizeListColumnsWidth(ChecksumView);
  606. }
  607. }
  608. else
  609. {
  610. ChecksumEdit->Text = Hash;
  611. }
  612. FAlgUsed = Alg;
  613. }
  614. //---------------------------------------------------------------------------
  615. void __fastcall TPropertiesDialog::NeedChecksum()
  616. {
  617. if (!FChecksumLoaded && ChecksumSupported())
  618. {
  619. CalculateChecksum();
  620. }
  621. }
  622. //---------------------------------------------------------------------------
  623. bool __fastcall TPropertiesDialog::ChecksumSupported()
  624. {
  625. return (FOnCalculateChecksum != NULL);
  626. }
  627. //---------------------------------------------------------------------------
  628. void __fastcall TPropertiesDialog::ChecksumButtonClick(TObject * /*Sender*/)
  629. {
  630. CalculateChecksum();
  631. }
  632. //---------------------------------------------------------------------------
  633. void __fastcall TPropertiesDialog::PageControlChange(TObject * /*Sender*/)
  634. {
  635. if (PageControl->ActivePage == ChecksumSheet)
  636. {
  637. NeedChecksum();
  638. }
  639. }
  640. //---------------------------------------------------------------------------
  641. void __fastcall TPropertiesDialog::ChecksumAlgEditChange(TObject * /*Sender*/)
  642. {
  643. ResetChecksum();
  644. UpdateControls();
  645. }
  646. //---------------------------------------------------------------------------
  647. void __fastcall TPropertiesDialog::CopyClick(TObject * Sender)
  648. {
  649. TInstantOperationVisualizer Visualizer;
  650. TListView * ListView = dynamic_cast<TListView *>(GetPopupComponent(Sender));
  651. DebugAssert(ListView != NULL);
  652. int Count = 0;
  653. UnicodeString SingleText;
  654. UnicodeString Text;
  655. TListItem * Item = ListView->GetNextItem(NULL, sdAll, TItemStates() << isSelected);
  656. while (Item != NULL)
  657. {
  658. DebugAssert(Item->Selected);
  659. SingleText = Item->SubItems->Strings[0];
  660. Text += FORMAT(L"%s = %s\r\n", (Item->Caption, Item->SubItems->Strings[0]));
  661. Count++;
  662. Item = ListView->GetNextItem(Item, sdAll, TItemStates() << isSelected);
  663. }
  664. CopyToClipboard(Count == 1 ? SingleText : Text);
  665. }
  666. //---------------------------------------------------------------------------
  667. void __fastcall TPropertiesDialog::ChecksumViewContextPopup(
  668. TObject * Sender, TPoint & MousePos, bool & Handled)
  669. {
  670. MenuPopup(Sender, MousePos, Handled);
  671. }
  672. //---------------------------------------------------------------------------
  673. void __fastcall TPropertiesDialog::ResolveRemoteToken(
  674. const TRemoteToken & Orig, int Message, TComboBox * ComboBox,
  675. const TRemoteTokenList * List)
  676. {
  677. try
  678. {
  679. ComboBox->Text =
  680. LoadRemoteToken(StoreRemoteToken(Orig, ComboBox->Text, Message, List));
  681. }
  682. catch(...)
  683. {
  684. ComboBox->SetFocus();
  685. throw;
  686. }
  687. }
  688. //---------------------------------------------------------------------------
  689. void __fastcall TPropertiesDialog::GroupComboBoxExit(TObject * Sender)
  690. {
  691. ResolveRemoteToken(FOrigProperties.Group, PROPERTIES_INVALID_GROUP,
  692. dynamic_cast<TComboBox *>(Sender), FGroupList);
  693. }
  694. //---------------------------------------------------------------------------
  695. void __fastcall TPropertiesDialog::OwnerComboBoxExit(TObject * Sender)
  696. {
  697. ResolveRemoteToken(FOrigProperties.Owner, PROPERTIES_INVALID_OWNER,
  698. dynamic_cast<TComboBox *>(Sender), FUserList);
  699. }
  700. //---------------------------------------------------------------------------
  701. void __fastcall TPropertiesDialog::FormShow(TObject * /*Sender*/)
  702. {
  703. UpdateControls();
  704. }
  705. //---------------------------------------------------------------------------
  706. void __fastcall TPropertiesDialog::CMDpiChanged(TMessage & Message)
  707. {
  708. TForm::Dispatch(&Message);
  709. if (!FMultiple)
  710. {
  711. UpdateFileImage();
  712. }
  713. }
  714. //---------------------------------------------------------------------------
  715. void __fastcall TPropertiesDialog::Dispatch(void * Message)
  716. {
  717. TMessage * M = reinterpret_cast<TMessage*>(Message);
  718. if (M->Msg == CM_DPICHANGED)
  719. {
  720. CMDpiChanged(*M);
  721. }
  722. else
  723. {
  724. TForm::Dispatch(Message);
  725. }
  726. }
  727. //---------------------------------------------------------------------------