Properties.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  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. //---------------------------------------------------------------------
  12. #pragma link "PathLabel"
  13. #pragma link "Rights"
  14. #pragma link "RightsExt"
  15. #pragma resource "*.dfm"
  16. //---------------------------------------------------------------------
  17. bool __fastcall DoPropertiesDialog(TStrings * FileList,
  18. const AnsiString Directory, TStrings * GroupList, TStrings * UserList,
  19. TRemoteProperties * Properties, int AllowedChanges,
  20. TTerminal * Terminal)
  21. {
  22. bool Result;
  23. TPropertiesDialog * PropertiesDialog = new TPropertiesDialog(Application);
  24. try
  25. {
  26. PropertiesDialog->AllowedChanges = AllowedChanges;
  27. PropertiesDialog->Directory = Directory;
  28. PropertiesDialog->FileList = FileList;
  29. PropertiesDialog->GroupList = GroupList;
  30. PropertiesDialog->UserList = UserList;
  31. PropertiesDialog->FileProperties = *Properties;
  32. PropertiesDialog->Terminal = Terminal;
  33. Result = PropertiesDialog->Execute();
  34. if (Result)
  35. {
  36. *Properties = PropertiesDialog->FileProperties;
  37. }
  38. }
  39. __finally
  40. {
  41. delete PropertiesDialog;
  42. }
  43. return Result;
  44. }
  45. //---------------------------------------------------------------------
  46. __fastcall TPropertiesDialog::TPropertiesDialog(TComponent* AOwner)
  47. : TForm(AOwner)
  48. {
  49. RightsFrame->OnChange = ControlChange;
  50. FGroupsSet = False;
  51. TSHFileInfo FileInfo;
  52. FShellImageList = new TImageList(this);
  53. FShellImageList->Handle = SHGetFileInfo("", 0, &FileInfo, sizeof(FileInfo),
  54. SHGFI_SYSICONINDEX | SHGFI_LARGEICON);
  55. FShellImageList->ShareImages = True;
  56. FFileList = new TStringList();
  57. FAllowCalculateStats = false;
  58. FStatsNotCalculated = false;
  59. UseSystemSettings(this);
  60. }
  61. //---------------------------------------------------------------------------
  62. __fastcall TPropertiesDialog::~TPropertiesDialog()
  63. {
  64. delete FFileList;
  65. FFileList = NULL;
  66. delete FShellImageList;
  67. FShellImageList = NULL;
  68. }
  69. //---------------------------------------------------------------------
  70. bool __fastcall TPropertiesDialog::Execute()
  71. {
  72. bool Result;
  73. FPrevTerminalClose = NULL;;
  74. if (FTerminal)
  75. {
  76. FPrevTerminalClose = FTerminal->OnClose;
  77. // used instead of previous TTerminalManager::OnChangeTerminal
  78. FTerminal->OnClose = TerminalClose;
  79. }
  80. try
  81. {
  82. if (AllowedChanges & cpGroup) ActiveControl = GroupComboBox;
  83. else
  84. if (AllowedChanges & cpOwner) ActiveControl = OwnerComboBox;
  85. else
  86. if (AllowedChanges & cpMode) ActiveControl = RightsFrame;
  87. else ActiveControl = OkButton;
  88. UpdateControls();
  89. Result = (ShowModal() == mrOk);
  90. }
  91. __finally
  92. {
  93. if (FTerminal)
  94. {
  95. assert(FTerminal->OnClose == TerminalClose);
  96. FTerminal->OnClose = FPrevTerminalClose;
  97. }
  98. }
  99. return Result;
  100. }
  101. //---------------------------------------------------------------------------
  102. void __fastcall TPropertiesDialog::TerminalClose(TObject * Sender)
  103. {
  104. Close();
  105. Terminal = NULL;
  106. if (FPrevTerminalClose)
  107. {
  108. FPrevTerminalClose(Sender);
  109. }
  110. }
  111. //---------------------------------------------------------------------------
  112. void __fastcall TPropertiesDialog::SetFileList(TStrings * value)
  113. {
  114. if (FFileList != value)
  115. {
  116. FFileList->Assign(value);
  117. LoadInfo();
  118. FGroupsSet = false;
  119. FUsersSet = false;
  120. }
  121. }
  122. //---------------------------------------------------------------------------
  123. void __fastcall TPropertiesDialog::LoadInfo()
  124. {
  125. if (FFileList)
  126. {
  127. assert(FFileList->Count > 0);
  128. FAllowCalculateStats = false;
  129. FStatsNotCalculated = false;
  130. FileIconImage->Picture->Bitmap = NULL;
  131. __int64 FilesSize;
  132. TCalculateSizeStats Stats;
  133. RightsFrame->AllowUndef = Multiple;
  134. if (!Multiple)
  135. {
  136. TRemoteFile * File = (TRemoteFile *)(FFileList->Objects[0]);
  137. assert(File && FShellImageList);
  138. FShellImageList->GetIcon(File->IconIndex, FileIconImage->Picture->Icon);
  139. if (!FUsersSet)
  140. {
  141. OwnerComboBox->Items->Text = File->Owner;
  142. }
  143. if (!FGroupsSet)
  144. {
  145. GroupComboBox->Items->Text = File->Group;
  146. }
  147. FilesSize = File->Size;
  148. LinksToLabelLabel->Visible = File->IsSymLink;
  149. LinksToLabel->Visible = File->IsSymLink;
  150. if (File->IsSymLink)
  151. {
  152. LinksToLabel->Caption = File->LinkTo;
  153. }
  154. if (File->IsDirectory && !File->IsSymLink)
  155. {
  156. FAllowCalculateStats = true;
  157. FStatsNotCalculated = true;
  158. }
  159. RightsFrame->AllowAddXToDirectories = File->IsDirectory;
  160. Caption = FMTLOAD(PROPERTIES_FILE_CAPTION, (File->FileName));
  161. RecursiveCheck->Visible = File->IsDirectory;
  162. RecursiveBevel->Visible = File->IsDirectory;
  163. }
  164. else
  165. {
  166. Caption = FFileList->Count ?
  167. FMTLOAD(PROPERTIES_FILES_CAPTION, (FFileList->Strings[0])) : AnsiString();
  168. LinksToLabelLabel->Hide();
  169. LinksToLabel->Hide();
  170. TStrings *GroupList = new TStringList();
  171. ((TStringList*)GroupList)->Duplicates = dupIgnore;
  172. ((TStringList*)GroupList)->Sorted = True;
  173. TStrings *OwnerList = new TStringList();
  174. ((TStringList*)OwnerList)->Duplicates = dupIgnore;
  175. ((TStringList*)OwnerList)->Sorted = True;
  176. try
  177. {
  178. FilesSize = 0;
  179. for (int Index = 0; Index < FFileList->Count; Index++)
  180. {
  181. TRemoteFile * File = (TRemoteFile *)(FFileList->Objects[Index]);
  182. assert(File);
  183. if (!File->Group.IsEmpty())
  184. {
  185. GroupList->Add(File->Group);
  186. }
  187. if (!File->Owner.IsEmpty())
  188. {
  189. OwnerList->Add(File->Owner);
  190. }
  191. if (File->IsDirectory)
  192. {
  193. Stats.Directories++;
  194. if (!File->IsSymLink)
  195. {
  196. FAllowCalculateStats = true;
  197. FStatsNotCalculated = true;
  198. }
  199. }
  200. else
  201. {
  202. Stats.Files++;
  203. }
  204. if (File->IsSymLink)
  205. {
  206. Stats.SymLinks++;
  207. }
  208. FilesSize += File->Size;
  209. }
  210. if (!FUsersSet)
  211. {
  212. OwnerComboBox->Items = OwnerList;
  213. }
  214. if (!FGroupsSet)
  215. {
  216. GroupComboBox->Items = GroupList;
  217. }
  218. RightsFrame->AllowAddXToDirectories = (Stats.Directories > 0);
  219. RecursiveCheck->Visible = (Stats.Directories > 0);
  220. RecursiveBevel->Visible = (Stats.Directories > 0);
  221. }
  222. __finally
  223. {
  224. delete GroupList;
  225. delete OwnerList;
  226. }
  227. }
  228. LoadStats(FilesSize, Stats);
  229. FilesIconImage->Visible = Multiple;
  230. FileIconImage->Visible = !Multiple;
  231. }
  232. }
  233. //---------------------------------------------------------------------------
  234. void __fastcall TPropertiesDialog::LoadStats(__int64 FilesSize,
  235. const TCalculateSizeStats & Stats)
  236. {
  237. AnsiString SizeStr;
  238. AnsiString FilesStr;
  239. if (FStatsNotCalculated)
  240. {
  241. SizeStr = LoadStr(PROPERTIES_UNKNOWN_SIZE);
  242. }
  243. else
  244. {
  245. SizeStr = FormatBytes(FilesSize);
  246. AnsiString SizeUnorderedStr = FormatBytes(FilesSize, false);
  247. if (SizeStr != SizeUnorderedStr)
  248. {
  249. SizeStr = FORMAT("%s (%s)", (SizeStr, SizeUnorderedStr));
  250. }
  251. }
  252. if (((Stats.Files + Stats.Directories) == 0) && !Multiple)
  253. {
  254. TRemoteFile * File = (TRemoteFile *)(FFileList->Objects[0]);
  255. assert(File != NULL);
  256. FilesStr = File->FileName;
  257. }
  258. else
  259. {
  260. if (Stats.Files > 0)
  261. {
  262. FilesStr = (Stats.Files == 1) ? FMTLOAD(PROPERTIES_FILE, (Stats.Files)) :
  263. FMTLOAD(PROPERTIES_FILES, (Stats.Files));
  264. if (Stats.Directories > 0)
  265. {
  266. FilesStr = FORMAT("%s, ", (FilesStr));
  267. }
  268. }
  269. if (Stats.Directories > 0)
  270. {
  271. FilesStr += (Stats.Directories == 1) ? FMTLOAD(PROPERTIES_DIRECTORY, (Stats.Directories)) :
  272. FMTLOAD(PROPERTIES_DIRECTORIES, (Stats.Directories));
  273. }
  274. if (Stats.SymLinks > 0)
  275. {
  276. AnsiString SymLinksStr;
  277. SymLinksStr = (Stats.SymLinks == 1) ? FMTLOAD(PROPERTIES_SYMLINK, (Stats.SymLinks)) :
  278. FMTLOAD(PROPERTIES_SYMLINKS, (Stats.SymLinks));
  279. FilesStr = FORMAT("%s (%s)", (FilesStr, SymLinksStr));
  280. }
  281. }
  282. SizeLabel->Caption = SizeStr;
  283. FileLabel->Caption = FilesStr;
  284. }
  285. //---------------------------------------------------------------------------
  286. void __fastcall TPropertiesDialog::SetDirectory(AnsiString value)
  287. {
  288. LocationLabel->Caption = value;
  289. }
  290. //---------------------------------------------------------------------------
  291. AnsiString __fastcall TPropertiesDialog::GetDirectory()
  292. {
  293. return LocationLabel->Caption;
  294. }
  295. //---------------------------------------------------------------------------
  296. void __fastcall TPropertiesDialog::SetFileProperties(TRemoteProperties value)
  297. {
  298. TValidProperties Valid;
  299. if (value.Valid.Contains(vpRights) && FAllowedChanges & cpMode) Valid << vpRights;
  300. if (value.Valid.Contains(vpOwner) && FAllowedChanges & cpOwner) Valid << vpOwner;
  301. if (value.Valid.Contains(vpGroup) && FAllowedChanges & cpGroup) Valid << vpGroup;
  302. FOrigProperties = value;
  303. FOrigProperties.Valid = Valid;
  304. FOrigProperties.Recursive = false;
  305. if (value.Valid.Contains(vpRights))
  306. {
  307. RightsFrame->Rights = value.Rights;
  308. RightsFrame->AddXToDirectories = value.AddXToDirectories;
  309. }
  310. else
  311. {
  312. RightsFrame->Rights = TRights();
  313. RightsFrame->AddXToDirectories = false;
  314. }
  315. GroupComboBox->Text = value.Valid.Contains(vpGroup) ? value.Group : AnsiString();
  316. OwnerComboBox->Text = value.Valid.Contains(vpOwner) ? value.Owner : AnsiString();
  317. RecursiveCheck->Checked = value.Recursive;
  318. UpdateControls();
  319. }
  320. //---------------------------------------------------------------------------
  321. TRemoteProperties __fastcall TPropertiesDialog::GetFileProperties()
  322. {
  323. TRemoteProperties Result;
  324. if (AllowedChanges & cpMode)
  325. {
  326. Result.Valid << vpRights;
  327. Result.Rights = RightsFrame->Rights;
  328. Result.AddXToDirectories = RightsFrame->AddXToDirectories;
  329. }
  330. #define STORE_NAME(PROPERTY) \
  331. if (!PROPERTY ## ComboBox->Text.Trim().IsEmpty() && \
  332. AllowedChanges & cp ## PROPERTY) \
  333. { \
  334. Result.Valid << vp ## PROPERTY; \
  335. Result.PROPERTY = PROPERTY ## ComboBox->Text.Trim(); \
  336. }
  337. STORE_NAME(Group);
  338. STORE_NAME(Owner);
  339. #undef STORE_NAME
  340. Result.Recursive = RecursiveCheck->Checked;
  341. return Result;
  342. }
  343. //---------------------------------------------------------------------------
  344. void __fastcall TPropertiesDialog::ControlChange(TObject * /*Sender*/)
  345. {
  346. UpdateControls();
  347. }
  348. //---------------------------------------------------------------------------
  349. void __fastcall TPropertiesDialog::UpdateControls()
  350. {
  351. EnableControl(OkButton,
  352. // group name is specified or we set multiple-file properties and
  353. // no valid group was specified (there are at least two different groups)
  354. (!GroupComboBox->Text.Trim().IsEmpty() ||
  355. (Multiple && !FOrigProperties.Valid.Contains(vpGroup)) ||
  356. (FOrigProperties.Group == GroupComboBox->Text)) &&
  357. // same but with owner
  358. (!OwnerComboBox->Text.Trim().IsEmpty() ||
  359. (Multiple && !FOrigProperties.Valid.Contains(vpOwner)) ||
  360. (FOrigProperties.Owner == OwnerComboBox->Text)) &&
  361. ((FileProperties != FOrigProperties) || RecursiveCheck->Checked)
  362. );
  363. EnableControl(GroupComboBox, FAllowedChanges & cpGroup);
  364. EnableControl(OwnerComboBox, FAllowedChanges & cpOwner);
  365. EnableControl(RightsFrame, FAllowedChanges & cpMode);
  366. CalculateSizeButton->Visible = Terminal && FAllowCalculateStats;
  367. if (!Multiple)
  368. {
  369. // when setting properties for one file only, allow undef state
  370. // only when the input right explicitly requires it or
  371. // when "recursive" is on (possible for directory only).
  372. bool AllowUndef =
  373. (FOrigProperties.Valid.Contains(vpRights) &&
  374. FOrigProperties.Rights.AllowUndef) ||
  375. (RecursiveCheck->Checked);
  376. if (!AllowUndef)
  377. {
  378. // when disallowing undef state, make sure, all undef are turned into unset
  379. RightsFrame->Rights = TRights(RightsFrame->Rights.NumberSet);
  380. }
  381. RightsFrame->AllowUndef = AllowUndef;
  382. }
  383. }
  384. //---------------------------------------------------------------------------
  385. bool __fastcall TPropertiesDialog::GetMultiple()
  386. {
  387. return (FFileList->Count != 1);
  388. }
  389. //---------------------------------------------------------------------------
  390. void __fastcall TPropertiesDialog::SetGroupList(TStrings * value)
  391. {
  392. if (FGroupsSet || ((value != NULL) && (value->Count > 0)))
  393. {
  394. GroupComboBox->Items = value;
  395. FGroupsSet = true;
  396. }
  397. }
  398. //---------------------------------------------------------------------------
  399. TStrings * __fastcall TPropertiesDialog::GetGroupList()
  400. {
  401. return GroupComboBox->Items;
  402. }
  403. //---------------------------------------------------------------------------
  404. void __fastcall TPropertiesDialog::SetUserList(TStrings * value)
  405. {
  406. if (FUsersSet || ((value != NULL) && (value->Count > 0)))
  407. {
  408. OwnerComboBox->Items = value;
  409. FUsersSet = true;
  410. }
  411. }
  412. //---------------------------------------------------------------------------
  413. TStrings * __fastcall TPropertiesDialog::GetUserList()
  414. {
  415. return OwnerComboBox->Items;
  416. }
  417. //---------------------------------------------------------------------------
  418. void __fastcall TPropertiesDialog::FormCloseQuery(TObject * /*Sender*/,
  419. bool & /*CanClose*/)
  420. {
  421. if (ModalResult == mrOk)
  422. {
  423. #define CHECK_VALID_NAME(Property, Message) \
  424. if (FOrigProperties.Valid.Contains(vp ## Property) && Property ## ComboBox->Text.Trim().IsEmpty()) { \
  425. Property ## ComboBox->SetFocus(); throw Exception(Message); }
  426. CHECK_VALID_NAME(Group, PROPERTIES_INVALID_GROUP);
  427. CHECK_VALID_NAME(Owner, PROPERTIES_INVALID_OWNER);
  428. #undef CHECK_VALID_NAME
  429. }
  430. }
  431. //---------------------------------------------------------------------------
  432. void __fastcall TPropertiesDialog::SetAllowedChanges(int value)
  433. {
  434. if (FAllowedChanges != value)
  435. {
  436. FAllowedChanges = value;
  437. UpdateControls();
  438. }
  439. }
  440. //---------------------------------------------------------------------------
  441. void __fastcall TPropertiesDialog::CalculateSizeButtonClick(
  442. TObject * /*Sender*/)
  443. {
  444. assert(Terminal);
  445. __int64 Size;
  446. TCalculateSizeStats Stats;
  447. Terminal->CalculateFilesSize(FileList, Size, 0, NULL, &Stats);
  448. FStatsNotCalculated = false;
  449. LoadStats(Size, Stats);
  450. }
  451. //---------------------------------------------------------------------------
  452. void __fastcall TPropertiesDialog::HelpButtonClick(TObject * /*Sender*/)
  453. {
  454. FormHelp(this);
  455. }
  456. //---------------------------------------------------------------------------