/ide/compatibilityrestrictions.pas

http://github.com/graemeg/lazarus · Pascal · 387 lines · 283 code · 69 blank · 35 comment · 30 complexity · 15f2f0c734bcf42c72f959b16a874b87 MD5 · raw file

  1. { /***************************************************************************
  2. CompatibilityRestrictions.pas - Lazarus IDE unit
  3. --------------------------------------------------
  4. ***************************************************************************/
  5. ***************************************************************************
  6. * *
  7. * This source is free software; you can redistribute it and/or modify *
  8. * it under the terms of the GNU General Public License as published by *
  9. * the Free Software Foundation; either version 2 of the License, or *
  10. * (at your option) any later version. *
  11. * *
  12. * This code is distributed in the hope that it will be useful, but *
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of *
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
  15. * General Public License for more details. *
  16. * *
  17. * A copy of the GNU General Public License is available on the World *
  18. * Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
  19. * obtain it by writing to the Free Software Foundation, *
  20. * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  21. * *
  22. ***************************************************************************
  23. Abstract:
  24. Compatiblity restrictions utilities
  25. }
  26. unit CompatibilityRestrictions;
  27. {$mode objfpc}{$H+}
  28. interface
  29. uses
  30. Classes, SysUtils, Forms, LCLProc, InterfaceBase, StringHashList,
  31. Laz2_DOM, Laz2_XMLRead, Laz2_XMLWrite,
  32. ObjectInspector, OIFavoriteProperties, PackageIntf,
  33. PackageSystem, PackageDefs, ComponentReg, LazConf;
  34. type
  35. TReadRestrictedEvent = procedure (const RestrictedName, WidgetSetName: String) of object;
  36. TReadRestrictedContentEvent = procedure (const Short, Description: String) of object;
  37. PRestriction = ^TRestriction;
  38. TRestriction = record
  39. Name: String;
  40. Short: String;
  41. Description: String;
  42. WidgetSet: TLCLPlatform;
  43. end;
  44. { TClassHashList }
  45. TClassHashList = class
  46. private
  47. FHashList: TStringHashList;
  48. public
  49. constructor Create;
  50. destructor Destroy; override;
  51. procedure Add(const AClass: TPersistentClass);
  52. procedure AddComponent(const AClass: TComponentClass);
  53. function Find(const AClassName: String): TPersistentClass;
  54. end;
  55. TRestrictedList = array of TRestriction;
  56. { TRestrictedManager }
  57. TRestrictedManager = class
  58. private
  59. FRestrictedProperties: TOIRestrictedProperties;
  60. FRestrictedList: TRestrictedList;
  61. FRestrictedFiles: TStringList;
  62. FClassList: TClassHashList;
  63. procedure AddPackage(APackage: TLazPackageID);
  64. procedure AddRestricted(const RestrictedName, WidgetSetName: String);
  65. procedure AddRestrictedContent(const Short, Description: String);
  66. procedure AddRestrictedProperty(const RestrictedName, WidgetSetName: String);
  67. procedure GatherRestrictedFiles;
  68. procedure ReadRestrictions(const Filename: String;
  69. OnReadRestricted: TReadRestrictedEvent;
  70. OnReadRestrictedContent: TReadRestrictedContentEvent);
  71. public
  72. constructor Create;
  73. destructor Destroy; override;
  74. function GetRestrictedProperties: TOIRestrictedProperties;
  75. function GetRestrictedList: TRestrictedList;
  76. end;
  77. function GetRestrictedProperties: TOIRestrictedProperties;
  78. function GetRestrictedList: TRestrictedList;
  79. implementation
  80. var
  81. RestrictedManager: TRestrictedManager = nil;
  82. { TClassHashList }
  83. constructor TClassHashList.Create;
  84. begin
  85. inherited;
  86. FHashList := TStringHashList.Create(False);
  87. end;
  88. destructor TClassHashList.Destroy;
  89. begin
  90. FHashList.Free;
  91. inherited;
  92. end;
  93. procedure TClassHashList.Add(const AClass: TPersistentClass);
  94. var
  95. C: TClass;
  96. begin
  97. C := AClass;
  98. while (C <> nil) and (FHashList.Find(C.ClassName) < 0) do
  99. begin
  100. FHashList.Add(C.ClassName, Pointer(C));
  101. if (C = TPersistent) then Break;
  102. C := C.ClassParent;
  103. end;
  104. end;
  105. procedure TClassHashList.AddComponent(const AClass: TComponentClass);
  106. begin
  107. Add(AClass);
  108. end;
  109. function TClassHashList.Find(const AClassName: String): TPersistentClass;
  110. begin
  111. Result := TPersistentClass(FHashList.Data[AClassName]);
  112. end;
  113. function GetRestrictedProperties: TOIRestrictedProperties;
  114. begin
  115. if RestrictedManager = nil then
  116. RestrictedManager := TRestrictedManager.Create;
  117. Result := RestrictedManager.GetRestrictedProperties;
  118. end;
  119. function GetRestrictedList: TRestrictedList;
  120. begin
  121. if RestrictedManager = nil then
  122. RestrictedManager := TRestrictedManager.Create;
  123. Result := RestrictedManager.GetRestrictedList;
  124. end;
  125. { TRestrictedManager }
  126. function TRestrictedManager.GetRestrictedProperties: TOIRestrictedProperties;
  127. var
  128. I: Integer;
  129. begin
  130. Result := nil;
  131. FreeAndNil(FRestrictedProperties);
  132. FRestrictedProperties := TOIRestrictedProperties.Create;
  133. FClassList := TClassHashList.Create;
  134. try
  135. IDEComponentPalette.IterateRegisteredClasses(@(FClassList.AddComponent));
  136. FClassList.Add(TForm);
  137. FClassList.Add(TDataModule);
  138. for I := 0 to FRestrictedFiles.Count - 1 do
  139. ReadRestrictions(FRestrictedFiles[I], @AddRestrictedProperty, nil);
  140. Result := FRestrictedProperties;
  141. finally
  142. FreeAndNil(FClassList);
  143. end;
  144. end;
  145. function TRestrictedManager.GetRestrictedList: TRestrictedList;
  146. var
  147. I: Integer;
  148. begin
  149. SetLength(FRestrictedList, 0);
  150. for I := 0 to FRestrictedFiles.Count - 1 do
  151. ReadRestrictions(FRestrictedFiles[I], @AddRestricted, @AddRestrictedContent);
  152. Result := FRestrictedList;
  153. end;
  154. procedure TRestrictedManager.AddPackage(APackage: TLazPackageID);
  155. var
  156. ALazPackage: TLazPackage;
  157. I: Integer;
  158. begin
  159. if APackage = nil then Exit;
  160. ALazPackage := PackageGraph.FindPackageWithID(APackage);
  161. if ALazPackage = nil then Exit;
  162. for I := 0 to ALazPackage.FileCount - 1 do
  163. if ALazPackage.Files[I].FileType = pftIssues then
  164. FRestrictedFiles.Add(ALazPackage.Files[I].GetFullFilename);
  165. end;
  166. procedure TRestrictedManager.AddRestricted(const RestrictedName, WidgetSetName: String);
  167. begin
  168. SetLength(FRestrictedList, Succ(Length(FRestrictedList)));
  169. FRestrictedList[High(FRestrictedList)].Name := RestrictedName;
  170. FRestrictedList[High(FRestrictedList)].WidgetSet := DirNameToLCLPlatform(WidgetSetName);
  171. FRestrictedList[High(FRestrictedList)].Short := '';
  172. FRestrictedList[High(FRestrictedList)].Description := '';
  173. end;
  174. procedure TRestrictedManager.AddRestrictedContent(const Short, Description: String);
  175. begin
  176. if Length(FRestrictedList) = 0 then Exit;
  177. FRestrictedList[High(FRestrictedList)].Short := Short;
  178. FRestrictedList[High(FRestrictedList)].Description := Description;
  179. end;
  180. procedure TRestrictedManager.AddRestrictedProperty(const RestrictedName, WidgetSetName: String);
  181. var
  182. Issue: TOIRestrictedProperty;
  183. AClass: TPersistentClass;
  184. AProperty: String;
  185. P: Integer;
  186. begin
  187. if RestrictedName = '' then Exit;
  188. P := Pos('.', RestrictedName);
  189. if P = 0 then
  190. begin
  191. AClass := FClassList.Find(RestrictedName);
  192. AProperty := '';
  193. end
  194. else
  195. begin
  196. AClass := FClassList.Find(Copy(RestrictedName, 0, P - 1));
  197. AProperty := Copy(RestrictedName, P + 1, MaxInt);
  198. end;
  199. if AClass = nil then
  200. begin
  201. // add as generic widgetset issue
  202. FRestrictedProperties.WidgetSetRestrictions[DirNameToLCLPlatform(WidgetSetName)] := FRestrictedProperties.WidgetSetRestrictions[DirNameToLCLPlatform(WidgetSetName)] + 1;
  203. Exit;
  204. end;
  205. Issue := TOIRestrictedProperty.Create(AClass, AProperty, True);
  206. Issue.WidgetSets := [DirNameToLCLPlatform(WidgetSetName)];
  207. FRestrictedProperties.Add(Issue);
  208. end;
  209. procedure TRestrictedManager.GatherRestrictedFiles;
  210. begin
  211. FRestrictedFiles.Clear;
  212. PackageGraph.IteratePackages([fpfSearchInInstalledPckgs], @AddPackage);
  213. end;
  214. procedure TRestrictedManager.ReadRestrictions(const Filename: String;
  215. OnReadRestricted: TReadRestrictedEvent;
  216. OnReadRestrictedContent: TReadRestrictedContentEvent);
  217. var
  218. IssueFile: TXMLDocument;
  219. R, N: TDOMNode;
  220. function ReadContent(ANode: TDOMNode): String;
  221. var
  222. S: TStringStream;
  223. N: TDOMNode;
  224. begin
  225. Result := '';
  226. S := TStringStream.Create('');
  227. try
  228. N := ANode.FirstChild;
  229. while N <> nil do
  230. begin
  231. WriteXML(N, S);
  232. N := N.NextSibling;
  233. end;
  234. Result := S.DataString;
  235. finally
  236. S.Free;
  237. end;
  238. end;
  239. procedure ParseWidgetSet(ANode: TDOMNode);
  240. var
  241. WidgetSetName, IssueName, Short, Description: String;
  242. IssueNode, AttrNode, IssueContentNode: TDOMNode;
  243. begin
  244. AttrNode := ANode.Attributes.GetNamedItem('name');
  245. if AttrNode <> nil then WidgetSetName := AttrNode.NodeValue
  246. else WidgetSetName := 'win32';
  247. IssueNode := ANode.FirstChild;
  248. while IssueNode <> nil do
  249. begin
  250. if IssueNode.NodeName = 'issue' then
  251. begin
  252. AttrNode := IssueNode.Attributes.GetNamedItem('name');
  253. if AttrNode <> nil then IssueName := AttrNode.NodeValue
  254. else IssueName := 'win32';
  255. if Assigned(OnReadRestricted) then
  256. OnReadRestricted(IssueName, WidgetSetName);
  257. if Assigned(OnReadRestrictedContent) then
  258. begin
  259. Short := '';
  260. Description := '';
  261. IssueContentNode := IssueNode.FirstChild;
  262. while IssueContentNode <> nil do
  263. begin
  264. if IssueContentNode.NodeName = 'short' then
  265. Short := ReadContent(IssueContentNode)
  266. else
  267. if IssueContentNode.NodeName = 'descr' then
  268. Description := ReadContent(IssueContentNode);
  269. IssueContentNode := IssueContentNode.NextSibling;
  270. end;
  271. OnReadRestrictedContent(Short, Description);
  272. end;
  273. end;
  274. IssueNode := IssueNode.NextSibling;
  275. end;
  276. end;
  277. begin
  278. try
  279. ReadXMLFile(IssueFile, Filename);
  280. except
  281. on E: Exception do
  282. DebugLn('TIssueManager.ReadFileIssues failed: ' + E.Message);
  283. end;
  284. try
  285. if IssueFile = nil then Exit;
  286. R := IssueFile.FindNode('package');
  287. if R = nil then Exit;
  288. N := R.FirstChild;
  289. while N <> nil do
  290. begin
  291. if N.NodeName = 'widgetset' then
  292. ParseWidgetSet(N);
  293. N := N.NextSibling;
  294. end;
  295. finally
  296. IssueFile.Free;
  297. end;
  298. end;
  299. constructor TRestrictedManager.Create;
  300. begin
  301. inherited;
  302. FRestrictedFiles := TStringList.Create;
  303. FRestrictedProperties := nil;
  304. GatherRestrictedFiles;
  305. end;
  306. destructor TRestrictedManager.Destroy;
  307. begin
  308. FreeAndNil(FRestrictedFiles);
  309. FreeAndNil(FRestrictedProperties);
  310. inherited Destroy;
  311. end;
  312. finalization
  313. FreeAndNil(RestrictedManager);
  314. end.