Properties.cpp 25 KB

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