Properties.cpp 23 KB

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