CnTransEditor.pas 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990
  1. {******************************************************************************}
  2. { CnPack For Delphi/C++Builder }
  3. { 中国人自己的开放源码第三方开发包 }
  4. { (C)Copyright 2001-2016 CnPack 开发组 }
  5. { ------------------------------------ }
  6. { }
  7. { 本开发包是开源的自由软件,您可以遵照 CnPack 的发布协议来修 }
  8. { 改和重新发布这一程序。 }
  9. { }
  10. { 发布这一开发包的目的是希望它有用,但没有任何担保。甚至没有 }
  11. { 适合特定目的而隐含的担保。更详细的情况请参阅 CnPack 发布协议。 }
  12. { }
  13. { 您应该已经和开发包一起收到一份 CnPack 发布协议的副本。如果 }
  14. { 还没有,可访问我们的网站: }
  15. { }
  16. { 网站地址:http://www.cnpack.org }
  17. { 电子邮件:master@cnpack.org }
  18. { }
  19. {******************************************************************************}
  20. unit CnTransEditor;
  21. {* |<PRE>
  22. ================================================================================
  23. * 软件名称:CnPack 多语包
  24. * 单元名称:多语包 IDE 翻译编辑单元
  25. * 单元作者:CnPack开发组 刘啸 (liuxiao@cnpack.org)
  26. * 备 注:该单元实现了多语包的 IDE 翻译编辑功能
  27. * 开发平台:PWin2000 + Delphi 5.0
  28. * 兼容测试:PWin9X/2000/XP + Delphi 5/6/7
  29. * 本 地 化:该单元中的字符串均符合本地化处理方式
  30. * 单元标识:$Id$
  31. * 修改记录:2012.11.06 V1.5
  32. * 修正未处理环境变量导致输出路径中出现$(Platform)的问题
  33. * 2008.10.13 V1.4
  34. * 修正由 Filter 引起的更新时忽略了新属性的问题
  35. * 2008.05.30 V1.3
  36. * 不处理只读的 string 属性
  37. * 2004.03.05 V1.2
  38. * 修正对 TFrame 处理不当的问题
  39. * 2003.12.10 V1.1
  40. * 增加对字体的额外处理
  41. * 2003.08.20 V1.0
  42. * 创建单元,实现功能
  43. ================================================================================
  44. |</PRE>}
  45. interface
  46. {$I CnPack.inc}
  47. uses
  48. {$IFDEF COMPILER6_UP}
  49. DesignIntf, DesignEditors, Variants,
  50. {$ELSE}
  51. Dsgnintf,
  52. {$ENDIF}
  53. SysUtils, Classes, Forms, Windows, Messages, Dialogs, Graphics, Menus, Grids,
  54. ComCtrls, Controls, ExtCtrls, ToolWin, ActnList, ImgList, TypInfo, StdCtrls,
  55. FileCtrl,
  56. CnLangConsts, CnLangTranslator, CnLangMgr, CnLangCollection, CnLangStorage,
  57. CnIniLangFileStorage, CnIniStrUtils, CnCommon, ToolsApi, ComObj, CnOTAUtils,
  58. CnClasses, CnTransFilter, CnLangUtils;
  59. type
  60. {$IFNDEF COMPILER6_UP}
  61. IDesigner = IFormDesigner;
  62. {$ENDIF}
  63. TCnTranslatorEditor = class(TComponentEditor)
  64. private
  65. FExtractor: TCnLangStringExtractor;
  66. protected
  67. procedure ExecFormTranslationManager;
  68. {* 显示翻译管理器 }
  69. public
  70. constructor Create(AComponent: TComponent; ADesigner: IDesigner); override;
  71. destructor Destroy; override;
  72. procedure Edit; override;
  73. {* 双击的过程 }
  74. procedure ExecuteVerb(Index: Integer); override;
  75. {* 执行右键菜单的过程 }
  76. function GetVerb(Index: Integer): string; override;
  77. {* 返回右键菜单条目 }
  78. function GetVerbCount: Integer; override;
  79. {* 返回右键菜单条目数 }
  80. property Extractor: TCnLangStringExtractor read FExtractor;
  81. end;
  82. type
  83. TFrmTransEditor = class(TForm)
  84. statTrans: TStatusBar;
  85. tvStorages: TTreeView;
  86. tlbMain: TToolBar;
  87. splTrans: TSplitter;
  88. pnlTrans: TPanel;
  89. clbrTrans: TCoolBar;
  90. pnlTitle: TPanel;
  91. StringGrid: TStringGrid;
  92. lblLangName: TLabel;
  93. lblLangID: TLabel;
  94. lblIndex: TLabel;
  95. lblLangNameValue: TLabel;
  96. lblLangIDValue: TLabel;
  97. lblLangIndexValue: TLabel;
  98. actlstTrans: TActionList;
  99. actGenStrs: TAction;
  100. ToolButton1: TToolButton;
  101. actCopyStrs: TAction;
  102. ToolButton2: TToolButton;
  103. actUpdateStrs: TAction;
  104. actSaveCurItem: TAction;
  105. actAddLine: TAction;
  106. ToolButton3: TToolButton;
  107. ToolButton4: TToolButton;
  108. ToolButton5: TToolButton;
  109. actDelLine: TAction;
  110. ToolButton6: TToolButton;
  111. ilStorage: TImageList;
  112. ilImages: TImageList;
  113. lbl1: TLabel;
  114. lblFileName: TLabel;
  115. actClear: TAction;
  116. btn1: TToolButton;
  117. btn2: TToolButton;
  118. actCollectForm: TAction;
  119. ToolButton7: TToolButton;
  120. ToolButton8: TToolButton;
  121. actClose: TAction;
  122. ToolButton9: TToolButton;
  123. ToolButton10: TToolButton;
  124. actDelBlank: TAction;
  125. ToolButton11: TToolButton;
  126. btnFilter: TToolButton;
  127. actFilter: TAction;
  128. procedure tvStoragesChange(Sender: TObject; Node: TTreeNode);
  129. procedure FormCreate(Sender: TObject);
  130. procedure StringGridDrawCell(Sender: TObject; ACol, ARow: Integer;
  131. Rect: TRect; State: TGridDrawState);
  132. procedure actGenStrsExecute(Sender: TObject);
  133. procedure StringGridSelectCell(Sender: TObject; ACol, ARow: Integer;
  134. var CanSelect: Boolean);
  135. procedure actCopyStrsExecute(Sender: TObject);
  136. procedure actUpdateStrsExecute(Sender: TObject);
  137. procedure actAddLineExecute(Sender: TObject);
  138. procedure actSaveCurItemExecute(Sender: TObject);
  139. procedure tvStoragesCustomDrawItem(Sender: TCustomTreeView;
  140. Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
  141. procedure actDelLineExecute(Sender: TObject);
  142. procedure pnlTransResize(Sender: TObject);
  143. procedure actClearExecute(Sender: TObject);
  144. procedure actCollectFormExecute(Sender: TObject);
  145. procedure actCloseExecute(Sender: TObject);
  146. procedure actDelBlankExecute(Sender: TObject);
  147. procedure actFilterExecute(Sender: TObject);
  148. private
  149. FFormFilterOptions: TLangTransFilterSet;
  150. FTransEditor: TCnTranslatorEditor;
  151. FContainer: TWinControl;
  152. { Private declarations }
  153. public
  154. { Public declarations }
  155. procedure WriteNameValueStringsToGrid(List: TStrings; Item: TCnLanguageItem);
  156. procedure LoadStorageFromList(List: TList);
  157. procedure SetBasicInfo(List: TStrings; Item: TCnLanguageItem);
  158. procedure UpdateLangDisplay(Storage: TCnCustomLangStorage; Item: TCnLanguageItem);
  159. property TransEditor: TCnTranslatorEditor read FTransEditor write FTransEditor;
  160. property Container: TWinControl read FContainer write FContainer;
  161. end;
  162. implementation
  163. {$R *.dfm}
  164. procedure SetDesignPathFile(Storage: TCnCustomLangFileStorage);
  165. var
  166. aPath, aFile: string;
  167. begin
  168. if Storage = nil then Exit;
  169. aPath := CnOtaReplaceToActualPath(CnOtaGetOutputDir);
  170. if aPath = '' then
  171. aPath := _CnExtractFilePath(CnOtaGetFileNameOfCurrentModule);
  172. (Storage as TCnCustomLangFileStorage).SetDesignLangPath(aPath);
  173. aFile := _CnChangeFileExt(CnOtaGetCurrentProjectFileName, '');
  174. (Storage as TCnCustomLangFileStorage).SetDesignLangFile(_CnExtractFileName(aFile));
  175. end;
  176. constructor TCnTranslatorEditor.Create(AComponent: TComponent;
  177. ADesigner: IDesigner);
  178. begin
  179. inherited;
  180. FExtractor := TCnLangStringExtractor.Create;
  181. end;
  182. destructor TCnTranslatorEditor.Destroy;
  183. begin
  184. FExtractor.Free;
  185. inherited;
  186. end;
  187. procedure TCnTranslatorEditor.Edit;
  188. begin
  189. ExecFormTranslationManager;
  190. end;
  191. procedure TCnTranslatorEditor.ExecFormTranslationManager;
  192. var
  193. ATranslator: TCnLangTranslator;
  194. Container: TComponent;
  195. i: Integer;
  196. List: TList;
  197. begin
  198. if CnLanguageManager = nil then
  199. begin
  200. MessageBox(0, PChar(SCnErrorNoLangManager), PChar(SCnErrorCaption),
  201. MB_OK or MB_ICONWARNING);
  202. Exit;
  203. end;
  204. ATranslator := TCnLangTranslator(Self.Component);
  205. Container := ATranslator.Owner;
  206. List := TList.Create;
  207. for i := 0 to Container.ComponentCount - 1 do
  208. if Container.Components[i] is TCnCustomLangStorage then
  209. begin
  210. List.Add(Container.Components[i]);
  211. if Container.Components[i] is TCnCustomLangFileStorage then
  212. SetDesignPathFile(Container.Components[i] as TCnCustomLangFileStorage);
  213. end;
  214. if CnLanguageManager.LanguageStorage <> nil then
  215. if List.IndexOf(CnLanguageManager.LanguageStorage) < 0 then
  216. begin
  217. List.Add(CnLanguageManager.LanguageStorage);
  218. if CnLanguageManager.LanguageStorage is TCnCustomLangFileStorage then
  219. SetDesignPathFile(CnLanguageManager.LanguageStorage as TCnCustomLangFileStorage);
  220. end;
  221. if List.Count = 0 then
  222. begin
  223. MessageBox(0, PChar(SCnErrorNoStorage), PChar(SCnErrorCaption),
  224. MB_OK or MB_ICONWARNING);
  225. Exit;
  226. end;
  227. with TFrmTransEditor.Create(nil) do
  228. begin
  229. TransEditor := Self;
  230. LoadStorageFromList(List);
  231. ShowModal;
  232. Free;
  233. end;
  234. List.Free;
  235. end;
  236. procedure TCnTranslatorEditor.ExecuteVerb(Index: Integer);
  237. begin
  238. case Index of
  239. 0: ExecFormTranslationManager;
  240. end;
  241. end;
  242. function TCnTranslatorEditor.GetVerb(Index: Integer): string;
  243. begin
  244. case Index of
  245. 0: Result := SCnFormTranslationManager;
  246. end;
  247. end;
  248. function TCnTranslatorEditor.GetVerbCount: Integer;
  249. begin
  250. Result := 1;
  251. end;
  252. { TFrmTransEditor }
  253. procedure TFrmTransEditor.LoadStorageFromList(List: TList);
  254. var
  255. i, j: Integer;
  256. ANode: TTreeNode;
  257. begin
  258. Self.tvStorages.Items.Clear;
  259. for i := 0 to List.Count - 1 do
  260. begin
  261. ANode := Self.tvStorages.Items.AddObject(nil,
  262. TCnCustomLangStorage(List[i]).Name, List[i]);
  263. for j := 0 to TCnCustomLangStorage(List[i]).LanguageCount - 1 do
  264. Self.tvStorages.Items.AddChildObject(ANode,
  265. InttoStr(TCnCustomLangStorage(List[i]).Languages[j].LanguageID) + ' - ' +
  266. TCnCustomLangStorage(List[i]).Languages[j].LanguageName,
  267. TCnCustomLangStorage(List[i]).Languages[j]);
  268. end;
  269. for i := 0 to Self.tvStorages.Items.Count - 1 do
  270. begin
  271. Self.tvStorages.Items[i].ImageIndex := Self.tvStorages.Items[i].Level;
  272. Self.tvStorages.Items[i].SelectedIndex := Self.tvStorages.Items[i].Level;
  273. if Self.tvStorages.Items[i].Level = 0 then
  274. Self.tvStorages.Items[i].Expand(True);
  275. end;
  276. end;
  277. procedure TFrmTransEditor.tvStoragesChange(Sender: TObject;
  278. Node: TTreeNode);
  279. begin
  280. if Node.Level = 1 then
  281. begin
  282. Self.UpdateLangDisplay(TCnCustomLangStorage(Node.Parent.Data),
  283. TCnLanguageItem(Node.Data));
  284. Self.pnlTrans.Enabled := True;
  285. end
  286. else
  287. Self.pnlTrans.Enabled := False;
  288. end;
  289. procedure TFrmTransEditor.UpdateLangDisplay(Storage: TCnCustomLangStorage;
  290. Item: TCnLanguageItem);
  291. function IsLangComment(const CommentString: string): Boolean;
  292. begin
  293. Result := (CommentString[1] = SCnCommentChar1) or
  294. (CommentString[1] = SCnCommentChar2) or
  295. ((CommentString[1] = SCnCommentChar3) and
  296. (CommentString[2] = SCnCommentChar3));
  297. end;
  298. var
  299. List: TStringList;
  300. i: Integer;
  301. S: WideString;
  302. bPrompted: Boolean;
  303. begin
  304. Self.lblLangNameValue.Caption := Item.LanguageName;
  305. Self.lblLangIDValue.Caption := InttoStr(Item.LanguageID);
  306. Self.lblLangIndexValue.Caption := InttoStr(Item.Index);
  307. if Storage is TCnCustomLangFileStorage then
  308. begin
  309. if DirectoryExists((Storage as TCnCustomLangFileStorage).LanguagePath) then
  310. ForceDirectories((Storage as TCnCustomLangFileStorage).LanguagePath);
  311. if (Storage as TCnCustomLangFileStorage).StorageMode = smByFile then
  312. Self.lblFileName.Caption := Item.LanguageFileName +
  313. (Storage as TCnCustomLangFileStorage).GetLanguageFileExt
  314. else
  315. Self.lblFileName.Caption := '.\' + Item.LanguageDirName + '\'
  316. + (Storage as TCnCustomLangFileStorage).DesignLangFile
  317. + (Storage as TCnCustomLangFileStorage).GetLanguageFileExt;
  318. end;
  319. if Self.Container = nil then
  320. if (Self.TransEditor = nil) then
  321. Exit
  322. else
  323. Self.Container := TWinControl(TCnLangTranslator(Self.TransEditor.Component).Owner);
  324. Storage.CurrentLanguageIndex := Item.Index;
  325. List := TStringList.Create;
  326. Storage.GetNamesList(List);
  327. Self.StringGrid.RowCount := 2;
  328. Self.StringGrid.FixedRows := 1;
  329. if List.Count > 0 then
  330. begin
  331. //清除空行和注释
  332. bPrompted := False;
  333. for i := List.Count - 1 downto 0 do
  334. begin
  335. if (List[i] = '') or IsLangComment(List[i]) then
  336. begin
  337. if not bPrompted then
  338. begin
  339. WarningDlg(SCnLangInvalidLine);
  340. bPrompted := True;
  341. end;
  342. List.Delete(i);
  343. end;
  344. end;
  345. Self.StringGrid.RowCount := List.Count + 1;
  346. for i := 1 to Self.StringGrid.RowCount - 1 do
  347. Self.StringGrid.Cells[0, i] := InttoStr(i);
  348. for i := 0 to List.Count - 1 do
  349. begin
  350. Self.StringGrid.Cells[1, i + 1] := List[i];
  351. S := List[i];
  352. if S[1] <> SystemNamePrefix then // 正常字符获取其原文值
  353. begin
  354. S := GetValueByTransName(Self.Container, S);
  355. Self.StringGrid.Cells[2, i + 1] := S
  356. end;
  357. // 显示其翻译后的值
  358. if Storage.GetString(List[i], S) then
  359. Self.StringGrid.Cells[3, i + 1] := S;
  360. end;
  361. end
  362. else
  363. begin
  364. Self.StringGrid.Rows[1].Text := '';
  365. Self.StringGrid.Cells[0, 1] := '1';
  366. end;
  367. end;
  368. procedure TFrmTransEditor.FormCreate(Sender: TObject);
  369. begin
  370. Self.StringGrid.ColWidths[0] := 30;
  371. Self.StringGrid.ColWidths[1] := 141;
  372. Self.StringGrid.ColWidths[2] := 194;
  373. Self.StringGrid.ColWidths[3] := 194;
  374. // Localize UI
  375. actAddLine.Caption := SCnactAddLineCaption;
  376. actAddLine.Hint := SCnactAddLineHint;
  377. actClear.Caption := SCnactClearCaption;
  378. actClear.Hint := SCnactClearHint;
  379. actClose.Caption := SCnactCloseCaption;
  380. actCollectForm.Caption := SCnactCollectFormCaption;
  381. actCollectForm.Hint := SCnactCollectFormHint;
  382. actCopyStrs.Caption := SCnactCopyStrsCaption;
  383. actCopyStrs.Hint := SCnactCopyStrsHint;
  384. actDelBlank.Caption := SCnactDelBlankCaption;
  385. actDelBlank.Hint := SCnactDelBlankHint;
  386. actDelLine.Caption := SCnactDelLineCaption;
  387. actDelLine.Hint := SCnactDelLineHint;
  388. actFilter.Caption := SCnactFilterCaption;
  389. actFilter.Hint := SCnactFilterHint;
  390. actGenStrs.Caption := SCnactGenStrsCaption;
  391. actGenStrs.Hint := SCnactGenStrsHint;
  392. actSaveCurItem.Caption := SCnactSaveCurItemCaption;
  393. actSaveCurItem.Hint := SCnactSaveCurItemHint;
  394. actUpdateStrs.Caption := SCnactUpdateStrsCaption;
  395. actUpdateStrs.Hint := SCnactUpdateStrsHint;
  396. Caption := SCnCaption;
  397. lbl1.Caption := SCnlbl1Caption;
  398. lblIndex.Caption := SCnlblIndexCaption;
  399. lblLangID.Caption := SCnlblLangIDCaption;
  400. lblLangName.Caption := SCnlblLangNameCaption;
  401. StringGrid.Hint := SCnStringGridHint;
  402. tvStorages.Hint := SCntvStoragesHint;
  403. Self.StringGrid.Cells[1, 0] := SCnStringGridCells10;
  404. Self.StringGrid.Cells[2, 0] := SCnStringGridCells20;
  405. Self.StringGrid.Cells[3, 0] := SCnStringGridCells30;
  406. FFormFilterOptions := [];
  407. end;
  408. procedure TFrmTransEditor.StringGridDrawCell(Sender: TObject; ACol,
  409. ARow: Integer; Rect: TRect; State: TGridDrawState);
  410. var
  411. OutStr: string;
  412. begin
  413. if (gdFixed in State)then
  414. with Sender as TStringGrid do
  415. begin
  416. OutStr := Cells[ACol, ARow];
  417. Canvas.Brush.Style := bsSolid;
  418. Canvas.FillRect(Rect);
  419. Canvas.TextOut(Rect.Left + ((Rect.Right - Rect.Left -
  420. Canvas.TextWidth(OutStr)) shr 1), Rect.Top + ((Rect.Bottom - Rect.top
  421. - Canvas.TextHeight(OutStr)) shr 1), OutStr);
  422. end;
  423. if ACol = 0 then
  424. begin
  425. Canvas.Brush.Style := bsSolid;
  426. Canvas.FillRect(Rect);
  427. Canvas.TextOut(Rect.Left + 3, Rect.Top + 2, InttoStr(ARow));
  428. end;
  429. end;
  430. procedure TFrmTransEditor.actGenStrsExecute(Sender: TObject);
  431. var
  432. List: TStringList;
  433. Item: TCnLanguageItem;
  434. begin
  435. if (tvStorages.Selected = nil) or (tvStorages.Selected.Level <> 1) then
  436. Exit;
  437. if Self.Container = nil then
  438. if (Self.TransEditor = nil) then
  439. Exit
  440. else
  441. Self.Container := TWinControl(TCnLangTranslator(Self.TransEditor.Component).Owner);
  442. List := TStringList.Create;
  443. Item := TCnLanguageItem(tvStorages.Selected.Data);
  444. TransEditor.Extractor.SetFilterOptions(FFormFilterOptions);
  445. Self.TransEditor.Extractor.GetFormStrings(Self.Container, List);
  446. WriteNameValueStringsToGrid(List, Item);
  447. end;
  448. procedure TFrmTransEditor.StringGridSelectCell(Sender: TObject; ACol,
  449. ARow: Integer; var CanSelect: Boolean);
  450. begin
  451. if ACol in [1, 3] then
  452. Self.StringGrid.Options := Self.StringGrid.Options + [goEditing]
  453. else
  454. Self.StringGrid.Options := Self.StringGrid.Options - [goEditing];
  455. end;
  456. procedure TFrmTransEditor.actCopyStrsExecute(Sender: TObject);
  457. var
  458. i: Integer;
  459. begin
  460. for i := 1 to Self.StringGrid.RowCount do
  461. if Self.StringGrid.Cells[3, i] = '' then
  462. Self.StringGrid.Cells[3, i] := Self.StringGrid.Cells[2, i];
  463. end;
  464. procedure TFrmTransEditor.actUpdateStrsExecute(Sender: TObject);
  465. var
  466. List: TStringList;
  467. DestList: array[1..3] of TStringList;
  468. i, Index: Integer;
  469. Item: TCnLanguageItem;
  470. begin
  471. { DONE : 获得所有字串列表,对于已经有翻译的,对应移动翻译字串。否则添加。 }
  472. if (tvStorages.Selected = nil) or (tvStorages.Selected.Level <> 1) then
  473. Exit;
  474. Item := TCnLanguageItem(Self.tvStorages.Selected.Data);
  475. if Self.Container = nil then
  476. if (Self.TransEditor = nil) then
  477. Exit
  478. else
  479. Self.Container := TWinControl(TCnLangTranslator(Self.TransEditor.Component).Owner);
  480. List := nil;
  481. for i := Low(DestList) to High(DestList) do
  482. DestList[i] := nil;
  483. TransEditor.Extractor.SetFilterOptions(FFormFilterOptions);
  484. try
  485. List := TStringList.Create;
  486. Self.TransEditor.Extractor.GetFormStrings(Self.Container, List);
  487. for i := Low(DestList) to High(DestList) do
  488. DestList[i] := TStringList.Create;
  489. for i := 1 to Self.StringGrid.RowCount - 1 do
  490. begin
  491. if Self.StringGrid.Cells[1, i] <> '' then
  492. begin
  493. DestList[1].Add(Self.StringGrid.Cells[1, i]);
  494. DestList[2].Add(Self.StringGrid.Cells[2, i]);
  495. DestList[3].Add(Self.StringGrid.Cells[3, i]);
  496. end;
  497. end;
  498. Index := DestList[1].IndexOf(SystemNamePrefix + SCnLanguageID);
  499. if Index > 0 then DestList[3][Index] := InttoStr(Item.LanguageID);
  500. Index := DestList[1].IndexOf(SystemNamePrefix + SCnLanguageName);
  501. if Index > 0 then DestList[3][Index] := Item.LanguageName;
  502. Index := DestList[1].IndexOf(SystemNamePrefix + SCnAuthor);
  503. if Index > 0 then DestList[3][Index] := Item.Author;
  504. Index := DestList[1].IndexOf(SystemNamePrefix + SCnAuthorEmail);
  505. if Index > 0 then DestList[3][Index] := Item.AuthorEmail;
  506. Index := DestList[1].IndexOf(SystemNamePrefix + SCnDefaultFont);
  507. if Index > 0 then DestList[3][Index] := Item.DefaultFontStr;
  508. for i := 0 to List.Count - 1 do
  509. begin
  510. Index := DestList[1].IndexOf(List.Names[i]);
  511. if Index > 0 then
  512. begin
  513. DestList[2][Index] := List.Values[List.Names[i]];
  514. end
  515. else
  516. begin
  517. DestList[1].Add(List.Names[i]);
  518. DestList[2].Add(List.Values[List.Names[i]]);
  519. DestList[3].Add('');
  520. end;
  521. end;
  522. Self.StringGrid.RowCount := DestList[1].Count + 1;
  523. for i := 0 to DestList[1].Count - 1 do
  524. begin
  525. Self.StringGrid.Cells[0, i + 1] := InttoStr(i + 1);
  526. Self.StringGrid.Cells[1, i + 1] := DestList[1][i];
  527. Self.StringGrid.Cells[2, i + 1] := DestList[2][i];
  528. Self.StringGrid.Cells[3, i + 1] := DestList[3][i];
  529. end;
  530. finally
  531. for i := Low(DestList) to High(DestList) do
  532. DestList[i].Free;
  533. List.Free;
  534. end;
  535. end;
  536. procedure TFrmTransEditor.actAddLineExecute(Sender: TObject);
  537. var
  538. R: TGridRect;
  539. begin
  540. if (tvStorages.Selected = nil) or (tvStorages.Selected.Level <> 1) then
  541. Exit;
  542. with Self.StringGrid do
  543. begin
  544. RowCount := RowCount + 1;
  545. Rows[RowCount - 1].Text := '';
  546. Cells[0, RowCount - 1] := InttoStr(RowCount - 1);
  547. R.Left := 1; R.Top := RowCount - 1;
  548. R.Right := 1; R.Bottom := RowCount - 1;
  549. Selection := R;
  550. SetFocus;
  551. end;
  552. end;
  553. procedure TFrmTransEditor.actSaveCurItemExecute(Sender: TObject);
  554. var
  555. Storage: TCnCustomLangStorage;
  556. i: Integer;
  557. begin
  558. if (tvStorages.Selected = nil) or (tvStorages.Selected.Level <> 1) then
  559. Exit;
  560. Storage := TCnCustomLangStorage(tvStorages.Selected.Parent.Data);
  561. if Storage is TCnCustomLangFileStorage then
  562. SetDesignPathFile(Storage as TCnCustomLangFileStorage);
  563. Storage.ClearCurrentLanguage;
  564. for i := 1 to Self.StringGrid.RowCount - 1 do
  565. if StringGrid.Cells[1, i] <> '' then
  566. Storage.SetString(StringGrid.Cells[1, i], StringGrid.Cells[3, i]);
  567. Storage.SaveCurrentLanguage;
  568. end;
  569. procedure TFrmTransEditor.SetBasicInfo(List: TStrings; Item: TCnLanguageItem);
  570. begin
  571. if (List <> nil) and (Item <> nil) then
  572. begin
  573. List.Values[SystemNamePrefix + SCnLanguageID] := InttoStr(Item.LanguageID);
  574. List.Values[SystemNamePrefix + SCnLanguageName] := Item.LanguageName;
  575. List.Values[SystemNamePrefix + SCnAuthor] := Item.Author;
  576. List.Values[SystemNamePrefix + SCnAuthorEmail] := Item.AuthorEmail;
  577. end;
  578. end;
  579. procedure TFrmTransEditor.tvStoragesCustomDrawItem(Sender: TCustomTreeView;
  580. Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
  581. begin
  582. if Node.Level = 0 then // 多语管理器的存储组件用粗体显示
  583. begin
  584. if CnLanguageManager <> nil then
  585. if CnLanguageManager.LanguageStorage = TCnCustomLangStorage(Node.Data) then
  586. Sender.Canvas.Font.Style := [fsBold];
  587. end
  588. else if Node.Level = 1 then // 多语管理器的当前语言条目也用粗体显示
  589. begin
  590. if CnLanguageManager <> nil then
  591. if CnLanguageManager.LanguageStorage = TCnCustomLangStorage(Node.Parent.Data) then
  592. if CnLanguageManager.CurrentLanguageIndex = Node.Parent.IndexOf(Node) then
  593. Sender.Canvas.Font.Style := [fsBold];
  594. end;
  595. DefaultDraw := True;
  596. end;
  597. procedure TFrmTransEditor.actDelLineExecute(Sender: TObject);
  598. var
  599. i: Integer;
  600. begin
  601. { DONE : 删除一行。 }
  602. with Self.StringGrid do
  603. if RowCount > 2 then
  604. begin
  605. for i := Row to RowCount - 2 do
  606. begin
  607. Rows[i].Text := Rows[i + 1].Text;
  608. Cells[0, i] := InttoStr(i);
  609. end;
  610. RowCount := RowCount - 1;
  611. end
  612. else if RowCount = 2 then
  613. Rows[1].Text := '1';
  614. end;
  615. procedure TFrmTransEditor.pnlTransResize(Sender: TObject);
  616. begin
  617. { DONE : 处理Resize事件,改变Grid列宽。 }
  618. Self.StringGrid.ColWidths[1] := (Self.StringGrid.Width - 30 - 24) * 7 div 27 + 1;
  619. Self.StringGrid.ColWidths[2] := (Self.StringGrid.Width - 30 - 24) * 10 div 27;
  620. Self.StringGrid.ColWidths[3] := (Self.StringGrid.Width - 30 - 24) * 10 div 27;
  621. end;
  622. procedure TFrmTransEditor.actClearExecute(Sender: TObject);
  623. begin
  624. if (tvStorages.Selected = nil) or (tvStorages.Selected.Level <> 1) then
  625. Exit;
  626. Self.StringGrid.RowCount := 2;
  627. Self.StringGrid.Rows[1].Text := '';
  628. Self.StringGrid.Cells[0, 1] := '1';
  629. end;
  630. procedure TFrmTransEditor.actCollectFormExecute(Sender: TObject);
  631. var
  632. List: TStringList;
  633. Item: TCnLanguageItem;
  634. i: Integer;
  635. Project: IOTAProject;
  636. ModuleInfo: IOTAModuleInfo;
  637. FormEditor: IOTAFormEditor;
  638. AModule: IOTAModule;
  639. Opened: Boolean;
  640. function CnOtaGetProjectGroup: IOTAProjectGroup;
  641. var
  642. IModuleServices: IOTAModuleServices;
  643. IModule: IOTAModule;
  644. i: Integer;
  645. begin
  646. Result := nil;
  647. Supports(BorlandIDEServices, IOTAModuleServices, IModuleServices);
  648. if IModuleServices <> nil then
  649. for i := 0 to IModuleServices.ModuleCount - 1 do
  650. begin
  651. IModule := IModuleServices.Modules[i];
  652. if Supports(IModule, IOTAProjectGroup, Result) then
  653. Break;
  654. end;
  655. end;
  656. function CnOtaGetCurrentProject: IOTAProject;
  657. var
  658. IProjectGroup: IOTAProjectGroup;
  659. begin
  660. Result := nil;
  661. IProjectGroup := CnOtaGetProjectGroup;
  662. if not Assigned(IProjectGroup) then
  663. Exit;
  664. try
  665. // This raises exceptions in D5 with .bat projects active
  666. Result := IProjectGroup.ActiveProject;
  667. except
  668. Result := nil;
  669. end;
  670. end;
  671. function ExtractUpperFileExt(const FileName: string): string;
  672. begin
  673. Result := UpperCase(_CnExtractFileExt(FileName));
  674. end;
  675. function IsCpp(const FileName: string): Boolean;
  676. var
  677. FileExt: string;
  678. begin
  679. FileExt := ExtractUpperFileExt(FileName);
  680. Result := (FileExt = '.CPP');
  681. end;
  682. function CnOtaGetFileEditorForModule(Module: IOTAModule; Index: Integer): IOTAEditor;
  683. begin
  684. Result := nil;
  685. if not Assigned(Module) then Exit;
  686. try
  687. // BCB 5 下为一个简单的单元调用 GetModuleFileEditor(1) 会出错
  688. {$IFDEF BCB5}
  689. if IsCpp(Module.FileName) and (Module.GetModuleFileCount = 2) and (Index = 1) then
  690. Index := 2;
  691. {$ENDIF}
  692. Result := Module.GetModuleFileEditor(Index);
  693. except
  694. Result := nil; // 在 IDE 释放时,可能会有异常发生
  695. end;
  696. end;
  697. function CnOtaGetFormEditorFromModule(const Module: IOTAModule): IOTAFormEditor;
  698. var
  699. i: Integer;
  700. Editor: IOTAEditor;
  701. FormEditor: IOTAFormEditor;
  702. begin
  703. Result := nil;
  704. if not Assigned(Module) then
  705. Exit;
  706. for i := 0 to Module.GetModuleFileCount - 1 do
  707. begin
  708. Editor := CnOtaGetFileEditorForModule(Module, i);
  709. if Supports(Editor, IOTAFormEditor, FormEditor) then
  710. begin
  711. Result := FormEditor;
  712. Exit;
  713. end;
  714. end;
  715. end;
  716. function CnOtaGetRootComponentFromEditor(Editor: IOTAFormEditor): TComponent;
  717. var
  718. Component: IOTAComponent;
  719. NTAComponent: INTAComponent;
  720. begin
  721. Result := nil;
  722. if not Assigned(Editor) then Exit;
  723. try
  724. Component := Editor.GetRootComponent;
  725. except
  726. // 打开某些文件时会出错(Delphi5)
  727. Exit;
  728. end;
  729. if Assigned(Component) and Supports(Component, INTAComponent,
  730. NTAComponent) then
  731. begin
  732. Result := NTAComponent.GetComponent;
  733. Exit;
  734. end;
  735. end;
  736. begin
  737. if (tvStorages.Selected = nil) or (tvStorages.Selected.Level <> 1) then
  738. Exit;
  739. Item := TCnLanguageItem(tvStorages.Selected.Data);
  740. List := TStringList.Create;
  741. Project := CnOtaGetCurrentProject;
  742. if Project = nil then
  743. Exit;
  744. Screen.Cursor := crHourGlass;
  745. try
  746. for i := 0 to Project.GetModuleCount - 1 do
  747. begin
  748. ModuleInfo := Project.GetModule(i);
  749. Opened := CnOtaIsFileOpen(ModuleInfo.FileName);
  750. if ModuleInfo.FormName = '' then Continue;
  751. try
  752. AModule := ModuleInfo.OpenModule;
  753. FormEditor := CnOtaGetFormEditorFromModule(AModule);
  754. except
  755. FormEditor := nil;
  756. AModule := nil;
  757. end;
  758. if FormEditor <> nil then
  759. begin
  760. TransEditor.Extractor.SetFilterOptions(FFormFilterOptions);
  761. Self.TransEditor.Extractor.GetFormStrings(CnOtaGetRootComponentFromEditor(FormEditor), List);
  762. if not Opened and (AModule <> nil) then
  763. begin
  764. try
  765. AModule.CloseModule(True);
  766. except
  767. ;
  768. end;
  769. AModule := nil;
  770. end;
  771. end;
  772. end;
  773. Application.ProcessMessages;
  774. WriteNameValueStringsToGrid(List, Item);
  775. finally
  776. Screen.Cursor := crDefault;
  777. end;
  778. end;
  779. procedure TFrmTransEditor.WriteNameValueStringsToGrid(List: TStrings;
  780. Item: TCnLanguageItem);
  781. var
  782. i, EquPos: Integer;
  783. S: string;
  784. begin
  785. if (List = nil) or (Item = nil) then
  786. Exit;
  787. Self.StringGrid.RowCount := List.Count + 6;
  788. Self.StringGrid.Cells[1, 1] := SystemNamePrefix + SCnLanguageID;
  789. Self.StringGrid.Cells[3, 1] := InttoStr(Item.LanguageID);
  790. Self.StringGrid.Cells[1, 2] := SystemNamePrefix + SCnLanguageName;
  791. Self.StringGrid.Cells[3, 2] := Item.LanguageName;
  792. Self.StringGrid.Cells[1, 3] := SystemNamePrefix + SCnAuthor;
  793. Self.StringGrid.Cells[3, 3] := Item.Author;
  794. Self.StringGrid.Cells[1, 4] := SystemNamePrefix + SCnAuthorEmail;
  795. Self.StringGrid.Cells[3, 4] := Item.AuthorEmail;
  796. Self.StringGrid.Cells[1, 5] := SystemNamePrefix + SCnDefaultFont;
  797. Self.StringGrid.Cells[3, 5] := Item.DefaultFontStr;
  798. for i := 1 to 5 do
  799. begin
  800. Self.StringGrid.Cells[0, i] := InttoStr(i);
  801. Self.StringGrid.Cells[2, i] := '';
  802. end;
  803. for i := 0 to List.Count - 1 do
  804. begin
  805. Self.StringGrid.Cells[0, i + 6] := InttoStr(i + 6);
  806. S := List[I];
  807. EquPos := Pos('=', S);
  808. if EquPos > 0 then
  809. begin
  810. Self.StringGrid.Cells[1, i + 6] := Copy(S, 1, EquPos - 1);
  811. Self.StringGrid.Cells[2, i + 6] := Copy(S, EquPos + 1, MaxInt);
  812. end
  813. else // 无等号
  814. begin
  815. Self.StringGrid.Cells[1, i + 6] := S;
  816. Self.StringGrid.Cells[2, i + 6] := '';
  817. end;
  818. Self.StringGrid.Cells[3, i + 6] := '';
  819. end;
  820. Self.StringGrid.Cells[0, 0] := '';
  821. end;
  822. procedure TFrmTransEditor.actCloseExecute(Sender: TObject);
  823. begin
  824. Self.Close;
  825. end;
  826. procedure TFrmTransEditor.actDelBlankExecute(Sender: TObject);
  827. var
  828. I, BlankRow: Integer;
  829. function IsBlankText(AText: string): Boolean;
  830. var
  831. I: Integer;
  832. begin
  833. Result := True;
  834. for I := 1 to Length(AText) do
  835. if not CharInSet(AText[I], [' '..'@', '['..'_', '{'..'~']) then
  836. begin
  837. Result := False;
  838. Exit;
  839. end;
  840. end;
  841. begin
  842. Screen.Cursor := crHourGlass;
  843. BlankRow := -1; // BlankRow 始终记录第一个空行或无效行
  844. try
  845. for I := 5 to Self.StringGrid.RowCount - 1 do
  846. begin
  847. if (StringGrid.Cells[1, I][1] <> '!') and IsBlankText(StringGrid.Cells[2, I])
  848. and IsBlankText(StringGrid.Cells[3, I]) then // 如果碰到空行
  849. begin
  850. if BlankRow = -1 then // 如以前无空行,
  851. BlankRow := I; // 则记录此空行位置
  852. end
  853. else // 如果当前行不空
  854. begin
  855. if BlankRow >= 0 then // 以前有空行
  856. begin
  857. // 当前行内容移动到空行去
  858. StringGrid.Cells[0, BlankRow] := IntToStr(BlankRow);
  859. StringGrid.Cells[1, BlankRow] := StringGrid.Cells[1, I];
  860. StringGrid.Cells[2, BlankRow] := StringGrid.Cells[2, I];
  861. StringGrid.Cells[3, BlankRow] := StringGrid.Cells[3, I];
  862. // BlankRow 指向下一个行,可能非空但已无用了
  863. Inc(BlankRow);
  864. end;
  865. end;
  866. end;
  867. if BlankRow >= 0 then
  868. Self.StringGrid.RowCount := BlankRow;
  869. finally
  870. Screen.Cursor := crDefault;
  871. end;
  872. end;
  873. procedure TFrmTransEditor.actFilterExecute(Sender: TObject);
  874. begin
  875. with TFrmTransFilter.Create(Self) do
  876. begin
  877. try
  878. Open(FFormFilterOptions);
  879. finally
  880. Free;
  881. end;
  882. end;
  883. end;
  884. end.