Properties.cpp 23 KB

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