Properties.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  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. //---------------------------------------------------------------------
  13. #pragma link "PathLabel"
  14. #pragma link "Rights"
  15. #pragma link "RightsExt"
  16. #pragma resource "*.dfm"
  17. //---------------------------------------------------------------------
  18. bool __fastcall DoPropertiesDialog(TStrings * FileList,
  19. const AnsiString Directory, TStrings * GroupList, TStrings * UserList,
  20. TRemoteProperties * Properties, int AllowedChanges,
  21. TCalculateSizeEvent OnCalculateSize,
  22. TCalculateChecksumEvent OnCalculateChecksum)
  23. {
  24. bool Result;
  25. TPropertiesDialog * PropertiesDialog = new TPropertiesDialog(Application,
  26. OnCalculateSize, OnCalculateChecksum);
  27. try
  28. {
  29. PropertiesDialog->AllowedChanges = AllowedChanges;
  30. PropertiesDialog->Directory = Directory;
  31. PropertiesDialog->FileList = FileList;
  32. PropertiesDialog->GroupList = GroupList;
  33. PropertiesDialog->UserList = UserList;
  34. PropertiesDialog->FileProperties = *Properties;
  35. Result = PropertiesDialog->Execute();
  36. if (Result)
  37. {
  38. *Properties = PropertiesDialog->FileProperties;
  39. }
  40. }
  41. __finally
  42. {
  43. delete PropertiesDialog;
  44. }
  45. return Result;
  46. }
  47. //---------------------------------------------------------------------
  48. __fastcall TPropertiesDialog::TPropertiesDialog(TComponent* AOwner,
  49. TCalculateSizeEvent OnCalculateSize,
  50. TCalculateChecksumEvent OnCalculateChecksum)
  51. : TForm(AOwner)
  52. {
  53. FOnCalculateSize = OnCalculateSize;
  54. FOnCalculateChecksum = OnCalculateChecksum;
  55. RightsFrame->OnChange = ControlChange;
  56. FGroupsSet = False;
  57. TSHFileInfo FileInfo;
  58. FShellImageList = new TImageList(this);
  59. FShellImageList->Handle = SHGetFileInfo("", 0, &FileInfo, sizeof(FileInfo),
  60. SHGFI_SYSICONINDEX | SHGFI_LARGEICON);
  61. FShellImageList->ShareImages = True;
  62. FFileList = new TStringList();
  63. FAllowCalculateStats = false;
  64. FStatsNotCalculated = false;
  65. FChecksumLoaded = false;
  66. FMultipleChecksum = false;
  67. UseSystemSettings(this);
  68. }
  69. //---------------------------------------------------------------------------
  70. __fastcall TPropertiesDialog::~TPropertiesDialog()
  71. {
  72. delete FFileList;
  73. FFileList = NULL;
  74. delete FShellImageList;
  75. FShellImageList = NULL;
  76. }
  77. //---------------------------------------------------------------------
  78. bool __fastcall TPropertiesDialog::Execute()
  79. {
  80. PageControl->ActivePage = CommonSheet;
  81. if (AllowedChanges & cpGroup) ActiveControl = GroupComboBox;
  82. else
  83. if (AllowedChanges & cpOwner) ActiveControl = OwnerComboBox;
  84. else
  85. if (AllowedChanges & cpMode) ActiveControl = RightsFrame;
  86. else ActiveControl = CancelButton;
  87. ChecksumAlgEdit->Text = GUIConfiguration->ChecksumAlg;
  88. ResetChecksum();
  89. UpdateControls();
  90. bool Result = (ShowModal() == mrOk);
  91. GUIConfiguration->ChecksumAlg = ChecksumAlgEdit->Text;
  92. return Result;
  93. }
  94. //---------------------------------------------------------------------------
  95. void __fastcall TPropertiesDialog::SetFileList(TStrings * value)
  96. {
  97. if (FFileList != value)
  98. {
  99. FFileList->Assign(value);
  100. LoadInfo();
  101. FGroupsSet = false;
  102. FUsersSet = false;
  103. }
  104. }
  105. //---------------------------------------------------------------------------
  106. void __fastcall TPropertiesDialog::LoadInfo()
  107. {
  108. if (FFileList)
  109. {
  110. assert(FFileList->Count > 0);
  111. FAllowCalculateStats = false;
  112. FStatsNotCalculated = false;
  113. FileIconImage->Picture->Bitmap = NULL;
  114. __int64 FilesSize;
  115. TCalculateSizeStats Stats;
  116. RightsFrame->AllowUndef = Multiple;
  117. FMultipleChecksum = Multiple;
  118. if (!Multiple)
  119. {
  120. TRemoteFile * File = (TRemoteFile *)(FFileList->Objects[0]);
  121. assert(File && FShellImageList);
  122. FShellImageList->GetIcon(File->IconIndex, FileIconImage->Picture->Icon);
  123. if (!FUsersSet)
  124. {
  125. OwnerComboBox->Items->Text = File->Owner;
  126. }
  127. if (!FGroupsSet)
  128. {
  129. GroupComboBox->Items->Text = File->Group;
  130. }
  131. FilesSize = File->Size;
  132. LinksToLabelLabel->Visible = File->IsSymLink;
  133. LinksToLabel->Visible = File->IsSymLink;
  134. if (File->IsSymLink)
  135. {
  136. LinksToLabel->Caption = File->LinkTo;
  137. }
  138. if (File->IsDirectory && !File->IsSymLink)
  139. {
  140. FAllowCalculateStats = true;
  141. FStatsNotCalculated = true;
  142. FMultipleChecksum = true;
  143. }
  144. RightsFrame->AllowAddXToDirectories = File->IsDirectory;
  145. Caption = FMTLOAD(PROPERTIES_FILE_CAPTION, (File->FileName));
  146. RecursiveCheck->Visible = File->IsDirectory;
  147. RecursiveBevel->Visible = File->IsDirectory;
  148. }
  149. else
  150. {
  151. Caption = FFileList->Count ?
  152. FMTLOAD(PROPERTIES_FILES_CAPTION, (FFileList->Strings[0])) : AnsiString();
  153. LinksToLabelLabel->Hide();
  154. LinksToLabel->Hide();
  155. TStrings *GroupList = new TStringList();
  156. ((TStringList*)GroupList)->Duplicates = dupIgnore;
  157. ((TStringList*)GroupList)->Sorted = True;
  158. TStrings *OwnerList = new TStringList();
  159. ((TStringList*)OwnerList)->Duplicates = dupIgnore;
  160. ((TStringList*)OwnerList)->Sorted = True;
  161. try
  162. {
  163. FilesSize = 0;
  164. for (int Index = 0; Index < FFileList->Count; Index++)
  165. {
  166. TRemoteFile * File = (TRemoteFile *)(FFileList->Objects[Index]);
  167. assert(File);
  168. if (!File->Group.IsEmpty())
  169. {
  170. GroupList->Add(File->Group);
  171. }
  172. if (!File->Owner.IsEmpty())
  173. {
  174. OwnerList->Add(File->Owner);
  175. }
  176. if (File->IsDirectory)
  177. {
  178. Stats.Directories++;
  179. if (!File->IsSymLink)
  180. {
  181. FAllowCalculateStats = true;
  182. FStatsNotCalculated = true;
  183. }
  184. }
  185. else
  186. {
  187. Stats.Files++;
  188. }
  189. if (File->IsSymLink)
  190. {
  191. Stats.SymLinks++;
  192. }
  193. FilesSize += File->Size;
  194. }
  195. if (!FUsersSet)
  196. {
  197. OwnerComboBox->Items = OwnerList;
  198. }
  199. if (!FGroupsSet)
  200. {
  201. GroupComboBox->Items = GroupList;
  202. }
  203. RightsFrame->AllowAddXToDirectories = (Stats.Directories > 0);
  204. RecursiveCheck->Visible = (Stats.Directories > 0);
  205. RecursiveBevel->Visible = (Stats.Directories > 0);
  206. }
  207. __finally
  208. {
  209. delete GroupList;
  210. delete OwnerList;
  211. }
  212. }
  213. LoadStats(FilesSize, Stats);
  214. FilesIconImage->Visible = Multiple;
  215. FileIconImage->Visible = !Multiple;
  216. ChecksumGroup->Visible = !FMultipleChecksum;
  217. ChecksumView->Visible = FMultipleChecksum;
  218. }
  219. }
  220. //---------------------------------------------------------------------------
  221. void __fastcall TPropertiesDialog::LoadStats(__int64 FilesSize,
  222. const TCalculateSizeStats & Stats)
  223. {
  224. AnsiString SizeStr;
  225. AnsiString FilesStr;
  226. if (FStatsNotCalculated)
  227. {
  228. SizeStr = LoadStr(PROPERTIES_UNKNOWN_SIZE);
  229. }
  230. else
  231. {
  232. SizeStr = FormatBytes(FilesSize);
  233. AnsiString SizeUnorderedStr = FormatBytes(FilesSize, false);
  234. if (SizeStr != SizeUnorderedStr)
  235. {
  236. SizeStr = FORMAT("%s (%s)", (SizeStr, SizeUnorderedStr));
  237. }
  238. }
  239. if (((Stats.Files + Stats.Directories) == 0) && !Multiple)
  240. {
  241. TRemoteFile * File = (TRemoteFile *)(FFileList->Objects[0]);
  242. assert(File != NULL);
  243. FilesStr = File->FileName;
  244. }
  245. else
  246. {
  247. if (Stats.Files > 0)
  248. {
  249. FilesStr = (Stats.Files == 1) ? FMTLOAD(PROPERTIES_FILE, (Stats.Files)) :
  250. FMTLOAD(PROPERTIES_FILES, (Stats.Files));
  251. if (Stats.Directories > 0)
  252. {
  253. FilesStr = FORMAT("%s, ", (FilesStr));
  254. }
  255. }
  256. if (Stats.Directories > 0)
  257. {
  258. FilesStr += (Stats.Directories == 1) ? FMTLOAD(PROPERTIES_DIRECTORY, (Stats.Directories)) :
  259. FMTLOAD(PROPERTIES_DIRECTORIES, (Stats.Directories));
  260. }
  261. if (Stats.SymLinks > 0)
  262. {
  263. AnsiString SymLinksStr;
  264. SymLinksStr = (Stats.SymLinks == 1) ? FMTLOAD(PROPERTIES_SYMLINK, (Stats.SymLinks)) :
  265. FMTLOAD(PROPERTIES_SYMLINKS, (Stats.SymLinks));
  266. FilesStr = FORMAT("%s (%s)", (FilesStr, SymLinksStr));
  267. }
  268. }
  269. SizeLabel->Caption = SizeStr;
  270. FileLabel->Caption = FilesStr;
  271. }
  272. //---------------------------------------------------------------------------
  273. void __fastcall TPropertiesDialog::SetDirectory(AnsiString value)
  274. {
  275. LocationLabel->Caption = value;
  276. }
  277. //---------------------------------------------------------------------------
  278. AnsiString __fastcall TPropertiesDialog::GetDirectory()
  279. {
  280. return LocationLabel->Caption;
  281. }
  282. //---------------------------------------------------------------------------
  283. void __fastcall TPropertiesDialog::SetFileProperties(TRemoteProperties value)
  284. {
  285. TValidProperties Valid;
  286. if (value.Valid.Contains(vpRights) && FAllowedChanges & cpMode) Valid << vpRights;
  287. if (value.Valid.Contains(vpOwner) && FAllowedChanges & cpOwner) Valid << vpOwner;
  288. if (value.Valid.Contains(vpGroup) && FAllowedChanges & cpGroup) Valid << vpGroup;
  289. FOrigProperties = value;
  290. FOrigProperties.Valid = Valid;
  291. FOrigProperties.Recursive = false;
  292. if (value.Valid.Contains(vpRights))
  293. {
  294. RightsFrame->Rights = value.Rights;
  295. RightsFrame->AddXToDirectories = value.AddXToDirectories;
  296. }
  297. else
  298. {
  299. RightsFrame->Rights = TRights();
  300. RightsFrame->AddXToDirectories = false;
  301. }
  302. GroupComboBox->Text = value.Valid.Contains(vpGroup) ? value.Group : AnsiString();
  303. OwnerComboBox->Text = value.Valid.Contains(vpOwner) ? value.Owner : AnsiString();
  304. RecursiveCheck->Checked = value.Recursive;
  305. UpdateControls();
  306. }
  307. //---------------------------------------------------------------------------
  308. TRemoteProperties __fastcall TPropertiesDialog::GetFileProperties()
  309. {
  310. TRemoteProperties Result;
  311. if (AllowedChanges & cpMode)
  312. {
  313. Result.Valid << vpRights;
  314. Result.Rights = RightsFrame->Rights;
  315. Result.AddXToDirectories = RightsFrame->AddXToDirectories;
  316. }
  317. #define STORE_NAME(PROPERTY) \
  318. if (!PROPERTY ## ComboBox->Text.Trim().IsEmpty() && \
  319. AllowedChanges & cp ## PROPERTY) \
  320. { \
  321. Result.Valid << vp ## PROPERTY; \
  322. Result.PROPERTY = PROPERTY ## ComboBox->Text.Trim(); \
  323. }
  324. STORE_NAME(Group);
  325. STORE_NAME(Owner);
  326. #undef STORE_NAME
  327. Result.Recursive = RecursiveCheck->Checked;
  328. return Result;
  329. }
  330. //---------------------------------------------------------------------------
  331. void __fastcall TPropertiesDialog::ControlChange(TObject * /*Sender*/)
  332. {
  333. UpdateControls();
  334. }
  335. //---------------------------------------------------------------------------
  336. void __fastcall TPropertiesDialog::UpdateControls()
  337. {
  338. EnableControl(OkButton,
  339. // group name is specified or we set multiple-file properties and
  340. // no valid group was specified (there are at least two different groups)
  341. (!GroupComboBox->Text.Trim().IsEmpty() ||
  342. (Multiple && !FOrigProperties.Valid.Contains(vpGroup)) ||
  343. (FOrigProperties.Group == GroupComboBox->Text)) &&
  344. // same but with owner
  345. (!OwnerComboBox->Text.Trim().IsEmpty() ||
  346. (Multiple && !FOrigProperties.Valid.Contains(vpOwner)) ||
  347. (FOrigProperties.Owner == OwnerComboBox->Text)) &&
  348. ((FileProperties != FOrigProperties) || RecursiveCheck->Checked)
  349. );
  350. EnableControl(GroupComboBox, FAllowedChanges & cpGroup);
  351. EnableControl(OwnerComboBox, FAllowedChanges & cpOwner);
  352. EnableControl(RightsFrame, FAllowedChanges & cpMode);
  353. CalculateSizeButton->Visible = FAllowCalculateStats;
  354. if (!Multiple)
  355. {
  356. // when setting properties for one file only, allow undef state
  357. // only when the input right explicitly requires it or
  358. // when "recursive" is on (possible for directory only).
  359. bool AllowUndef =
  360. (FOrigProperties.Valid.Contains(vpRights) &&
  361. FOrigProperties.Rights.AllowUndef) ||
  362. (RecursiveCheck->Checked);
  363. if (!AllowUndef)
  364. {
  365. // when disallowing undef state, make sure, all undef are turned into unset
  366. RightsFrame->Rights = TRights(RightsFrame->Rights.NumberSet);
  367. }
  368. RightsFrame->AllowUndef = AllowUndef;
  369. }
  370. EnableControl(ChecksumSheet, ChecksumSupported());
  371. EnableControl(ChecksumButton, ChecksumSheet->Enabled &&
  372. !ChecksumAlgEdit->Text.IsEmpty());
  373. // hide checksum edit at least if it is disabled to get rid of ugly
  374. // visage on XP
  375. ChecksumEdit->Visible = ChecksumEdit->Enabled;
  376. }
  377. //---------------------------------------------------------------------------
  378. bool __fastcall TPropertiesDialog::GetMultiple()
  379. {
  380. return (FFileList->Count != 1);
  381. }
  382. //---------------------------------------------------------------------------
  383. void __fastcall TPropertiesDialog::SetGroupList(TStrings * value)
  384. {
  385. if (FGroupsSet || ((value != NULL) && (value->Count > 0)))
  386. {
  387. GroupComboBox->Items = value;
  388. FGroupsSet = true;
  389. }
  390. }
  391. //---------------------------------------------------------------------------
  392. TStrings * __fastcall TPropertiesDialog::GetGroupList()
  393. {
  394. return GroupComboBox->Items;
  395. }
  396. //---------------------------------------------------------------------------
  397. void __fastcall TPropertiesDialog::SetUserList(TStrings * value)
  398. {
  399. if (FUsersSet || ((value != NULL) && (value->Count > 0)))
  400. {
  401. OwnerComboBox->Items = value;
  402. FUsersSet = true;
  403. }
  404. }
  405. //---------------------------------------------------------------------------
  406. TStrings * __fastcall TPropertiesDialog::GetUserList()
  407. {
  408. return OwnerComboBox->Items;
  409. }
  410. //---------------------------------------------------------------------------
  411. void __fastcall TPropertiesDialog::FormCloseQuery(TObject * /*Sender*/,
  412. bool & /*CanClose*/)
  413. {
  414. if (ModalResult == mrOk)
  415. {
  416. #define CHECK_VALID_NAME(Property, Message) \
  417. if (FOrigProperties.Valid.Contains(vp ## Property) && Property ## ComboBox->Text.Trim().IsEmpty()) { \
  418. Property ## ComboBox->SetFocus(); throw Exception(Message); }
  419. CHECK_VALID_NAME(Group, PROPERTIES_INVALID_GROUP);
  420. CHECK_VALID_NAME(Owner, PROPERTIES_INVALID_OWNER);
  421. #undef CHECK_VALID_NAME
  422. }
  423. }
  424. //---------------------------------------------------------------------------
  425. void __fastcall TPropertiesDialog::SetAllowedChanges(int value)
  426. {
  427. if (FAllowedChanges != value)
  428. {
  429. FAllowedChanges = value;
  430. UpdateControls();
  431. }
  432. }
  433. //---------------------------------------------------------------------------
  434. void __fastcall TPropertiesDialog::CalculateSizeButtonClick(
  435. TObject * /*Sender*/)
  436. {
  437. assert(FOnCalculateSize != NULL);
  438. bool DoClose = false;
  439. try
  440. {
  441. __int64 Size;
  442. TCalculateSizeStats Stats;
  443. FOnCalculateSize(FileList, Size, Stats, DoClose);
  444. FStatsNotCalculated = false;
  445. LoadStats(Size, Stats);
  446. }
  447. __finally
  448. {
  449. if (DoClose)
  450. {
  451. Close();
  452. }
  453. }
  454. }
  455. //---------------------------------------------------------------------------
  456. void __fastcall TPropertiesDialog::HelpButtonClick(TObject * /*Sender*/)
  457. {
  458. FormHelp(this);
  459. }
  460. //---------------------------------------------------------------------------
  461. void __fastcall TPropertiesDialog::ResetChecksum()
  462. {
  463. ChecksumView->Items->Clear();
  464. ChecksumEdit->Text = LoadStr(PROPERTIES_CHECKSUM_UNKNOWN);
  465. }
  466. //---------------------------------------------------------------------------
  467. void __fastcall TPropertiesDialog::CalculateChecksum()
  468. {
  469. assert(FOnCalculateChecksum != NULL);
  470. ResetChecksum();
  471. FChecksumLoaded = true;
  472. bool DoClose = false;
  473. try
  474. {
  475. FOnCalculateChecksum(ChecksumAlgEdit->Text, FFileList, CalculatedChecksum, DoClose);
  476. }
  477. __finally
  478. {
  479. if (DoClose)
  480. {
  481. Close();
  482. }
  483. }
  484. }
  485. //---------------------------------------------------------------------------
  486. void __fastcall TPropertiesDialog::CalculatedChecksum(
  487. const AnsiString & FileName, const AnsiString & /*Alg*/,
  488. const AnsiString & Hash)
  489. {
  490. if (FMultipleChecksum)
  491. {
  492. TListItem * Item = ChecksumView->Items->Add();
  493. Item->Caption = FileName;
  494. Item->SubItems->Add(Hash);
  495. }
  496. else
  497. {
  498. ChecksumEdit->Text = Hash;
  499. }
  500. }
  501. //---------------------------------------------------------------------------
  502. void __fastcall TPropertiesDialog::NeedChecksum()
  503. {
  504. if (!FChecksumLoaded && ChecksumSupported())
  505. {
  506. CalculateChecksum();
  507. }
  508. }
  509. //---------------------------------------------------------------------------
  510. bool __fastcall TPropertiesDialog::ChecksumSupported()
  511. {
  512. return (FOnCalculateChecksum != NULL);
  513. }
  514. //---------------------------------------------------------------------------
  515. void __fastcall TPropertiesDialog::ChecksumButtonClick(TObject * /*Sender*/)
  516. {
  517. CalculateChecksum();
  518. }
  519. //---------------------------------------------------------------------------
  520. void __fastcall TPropertiesDialog::PageControlChange(TObject * /*Sender*/)
  521. {
  522. if (PageControl->ActivePage == ChecksumSheet)
  523. {
  524. NeedChecksum();
  525. }
  526. }
  527. //---------------------------------------------------------------------------
  528. void __fastcall TPropertiesDialog::ChecksumAlgEditChange(TObject * /*Sender*/)
  529. {
  530. ResetChecksum();
  531. UpdateControls();
  532. }
  533. //---------------------------------------------------------------------------
  534. void __fastcall TPropertiesDialog::CopyClick(TObject * /*Sender*/)
  535. {
  536. TListView * ListView = dynamic_cast<TListView *>(ListViewMenu->PopupComponent);
  537. assert(ListView != NULL);
  538. int Count = 0;
  539. AnsiString SingleText;
  540. AnsiString Text;
  541. TListItem * Item = ListView->GetNextItem(NULL, sdAll, TItemStates() << isSelected);
  542. while (Item != NULL)
  543. {
  544. assert(Item->Selected);
  545. SingleText = Item->SubItems->Strings[0];
  546. Text += FORMAT("%s = %s\r\n", (Item->Caption, Item->SubItems->Strings[0]));
  547. Count++;
  548. Item = ListView->GetNextItem(Item, sdAll, TItemStates() << isSelected);
  549. }
  550. CopyToClipboard(Count == 1 ? SingleText : Text);
  551. }
  552. //---------------------------------------------------------------------------
  553. void __fastcall TPropertiesDialog::ChecksumViewContextPopup(
  554. TObject * Sender, TPoint & MousePos, bool & Handled)
  555. {
  556. MenuPopup(Sender, MousePos, Handled);
  557. }
  558. //---------------------------------------------------------------------------