Skip to content

Commit 6c12cd7

Browse files
authored
Html export style selection persistence (#41)
1 parent cb89956 commit 6c12cd7

9 files changed

Lines changed: 106 additions & 28 deletions

File tree

‎src/O2/ViewModels/uHTMLExportModel.pas‎

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ interface
2222
uAppFiles, uUtils;
2323

2424
type
25+
TStyleRec = record
26+
Name: string;
27+
Style: string;
28+
end;
29+
2530
THTMLExportModel = class(TInterfacedObject, IHTMLExport)
2631
private
2732
FTitle: string;
@@ -36,7 +41,7 @@ THTMLExportModel = class(TInterfacedObject, IHTMLExport)
3641
FIncludeRelations: Boolean;
3742
FIncludePasswords: Boolean;
3843
FStyleIndex: Integer;
39-
FStyles: TList<string>;
44+
FStyles: TList<TStyleRec>;
4045
FBuilder: TStringBuilder;
4146
function GetIncludeIndex: Boolean;
4247
function GetIncludeTags: Boolean;
@@ -64,7 +69,7 @@ THTMLExportModel = class(TInterfacedObject, IHTMLExport)
6469
procedure StoreSettings;
6570

6671
function TryGetStyleFileName(Index: Integer; out FileName: string): Boolean;
67-
function AddStyle(const Style: string): Integer;
72+
function AddStyle(const Name, Style: string): Integer;
6873

6974
function ExportToHTML(Preview: Boolean): string; overload;
7075
procedure ExportToHTML(const FileName: string); overload;
@@ -106,7 +111,7 @@ constructor THTMLExportModel.Create(const O2File: TO2File;
106111
FIncludeRelations := FStorage.ReadBoolean(IdHTMLExportIncludeRelations, True);
107112
FIncludePasswords := FStorage.ReadBoolean(IdHTMLExportIncludePasswords, True);
108113
FStyleIndex := 0;
109-
FStyles := TList<string>.Create;
114+
FStyles := TList<TStyleRec>.Create;
110115
FBuilder := TStringBuilder.Create;
111116
end;
112117

@@ -154,6 +159,9 @@ procedure THTMLExportModel.StoreSettings;
154159
FStorage.WriteBoolean(IdHTMLExportIncludeNotes, FIncludeNotes);
155160
FStorage.WriteBoolean(IdHTMLExportIncludeRelations, FIncludeRelations);
156161
FStorage.WriteBoolean(IdHTMLExportIncludePasswords, FIncludePasswords);
162+
163+
if FStyles.Count > 0 then
164+
FStorage.WriteString(IdHTMLExportStyle, FStyles[FStyleIndex].Name);
157165
end;
158166

159167
function THTMLExportModel.TryGetStyleFileName(Index: Integer;
@@ -166,9 +174,16 @@ function THTMLExportModel.TryGetStyleFileName(Index: Integer;
166174
if Result then FileName := FAppFiles.FullPaths[Id];
167175
end;
168176

169-
function THTMLExportModel.AddStyle(const Style: string): Integer;
177+
function THTMLExportModel.AddStyle(const Name, Style: string): Integer;
178+
var
179+
StyleRec: TStyleRec;
170180
begin
171-
Result := FStyles.Add(Style);
181+
StyleRec.Name := Name;
182+
StyleRec.Style := Style;
183+
Result := FStyles.Add(StyleRec);
184+
185+
if FStorage.ReadString(IdHTMLExportStyle) = Name then
186+
FStyleIndex := Result;
172187
end;
173188

174189
function THTMLExportModel.ExportToHTML(Preview: Boolean): string;
@@ -189,7 +204,7 @@ function THTMLExportModel.ExportToHTML(Preview: Boolean): string;
189204
[FO2File.Description])
190205
.AppendFormat('<meta name="author" content="%s" />', [FO2File.Author])
191206
.AppendLine('<style>')
192-
.AppendLine(FStyles[FStyleIndex])
207+
.AppendLine(FStyles[FStyleIndex].Style)
193208
.AppendLine('</style>')
194209
.Append('<title>').AppendHTML(FTitle).AppendLine('</title>')
195210
.AppendLine('</head>')

‎src/O2/o2.dproj‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@
8787
<PropertyGroup Condition="'$(Cfg_1_Win32)'!=''">
8888
<DCC_DependencyCheckOutputName>o2.exe</DCC_DependencyCheckOutputName>
8989
<SanitizedProjectName>o2</SanitizedProjectName>
90-
<VerInfo_Build>566</VerInfo_Build>
91-
<VerInfo_Keys>CompanyName=The O2 Project;FileDescription=O2;FileVersion=3.2.0.566;InternalName=O2;LegalCopyright=(C) 2004-2026 Maurizio Basaglia. All rights reserved.;LegalTrademarks=;OriginalFilename=o2.exe;ProductName=O2;ProductVersion=3.2;Comments=A safe storage for your personal data.;Homepage=https://maurizuki.github.io/O2</VerInfo_Keys>
90+
<VerInfo_Build>567</VerInfo_Build>
91+
<VerInfo_Keys>CompanyName=The O2 Project;FileDescription=O2;FileVersion=3.2.0.567;InternalName=O2;LegalCopyright=(C) 2004-2026 Maurizio Basaglia. All rights reserved.;LegalTrademarks=;OriginalFilename=o2.exe;ProductName=O2;ProductVersion=3.2;Comments=A safe storage for your personal data.;Homepage=https://maurizuki.github.io/O2</VerInfo_Keys>
9292
<BT_BuildType>Debug</BT_BuildType>
9393
</PropertyGroup>
9494
<PropertyGroup Condition="'$(Cfg_2)'!=''">

‎src/O2/o2.res‎

0 Bytes
Binary file not shown.

‎src/O2/uGlobal.pas‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ interface
114114
IdHTMLExportIncludeNotes = 'ExportToHTML.Include.Notes';
115115
IdHTMLExportIncludeRelations = 'ExportToHTML.Include.Relations';
116116
IdHTMLExportIncludePasswords = 'ExportToHTML.Include.Passwords';
117+
IdHTMLExportStyle = 'ExportToHTML.Style';
117118
IdPrintIncludeTags = 'Print.Include.Tags';
118119
IdPrintIncludeNotes = 'Print.Include.Notes';
119120
IdPrintIncludeRelations = 'Print.Include.Relations';

‎src/O2/uHTMLExport.dfm‎

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ object HTMLExport: THTMLExport
2727
Align = alClient
2828
TabOrder = 0
2929
OnCreateWebViewCompleted = WebBrowserCreateWebViewCompleted
30-
ExplicitWidth = 410
31-
ExplicitHeight = 242
3230
end
3331
object ToolBar: TToolBar
3432
Left = 0
@@ -51,7 +49,6 @@ object HTMLExport: THTMLExport
5149
TabOrder = 1
5250
Transparent = True
5351
Wrapable = False
54-
ExplicitWidth = 418
5552
object ToolButton1: TToolButton
5653
Left = 0
5754
Top = 0
@@ -91,35 +88,35 @@ object HTMLExport: THTMLExport
9188
OnUpdate = ActionUpdate
9289
end
9390
object IncludeIndex: TAction
94-
Category = 'Options'
91+
Category = 'Options.Item'
9592
Caption = 'Include index'
9693
Hint = 'Include index'
9794
OnExecute = IncludeIndexExecute
9895
OnUpdate = IncludeIndexUpdate
9996
end
10097
object IncludeTags: TAction
101-
Category = 'Options'
98+
Category = 'Options.Item'
10299
Caption = 'Include tags'
103100
Hint = 'Include tags'
104101
OnExecute = IncludeTagsExecute
105102
OnUpdate = IncludeTagsUpdate
106103
end
107104
object IncludeNotes: TAction
108-
Category = 'Options'
105+
Category = 'Options.Item'
109106
Caption = 'Include notes'
110107
Hint = 'Include notes'
111108
OnExecute = IncludeNotesExecute
112109
OnUpdate = IncludeNotesUpdate
113110
end
114111
object IncludeRelations: TAction
115-
Category = 'Options'
112+
Category = 'Options.Item'
116113
Caption = 'Include relations'
117114
Hint = 'Include relations'
118115
OnExecute = IncludeRelationsExecute
119116
OnUpdate = IncludeRelationsUpdate
120117
end
121118
object IncludePasswords: TAction
122-
Category = 'Options'
119+
Category = 'Options.Item'
123120
Caption = 'Include passwords'
124121
Hint = 'Include passwords'
125122
OnExecute = IncludePasswordsExecute
@@ -133,31 +130,31 @@ object HTMLExport: THTMLExport
133130
OnUpdate = ActionUpdate
134131
end
135132
object BlueWaterStyle: TAction
136-
Category = 'Style'
133+
Category = 'Style.Item'
137134
Caption = 'Blue Water'
138135
GroupIndex = 1
139136
OnExecute = StyleExecute
140137
OnUpdate = StyleUpdate
141138
end
142139
object MatchaStyle: TAction
143140
Tag = 1
144-
Category = 'Style'
141+
Category = 'Style.Item'
145142
Caption = 'Matcha'
146143
GroupIndex = 1
147144
OnExecute = StyleExecute
148145
OnUpdate = StyleUpdate
149146
end
150147
object SakuraStyle: TAction
151148
Tag = 2
152-
Category = 'Style'
149+
Category = 'Style.Item'
153150
Caption = 'Sakura'
154151
GroupIndex = 1
155152
OnExecute = StyleExecute
156153
OnUpdate = StyleUpdate
157154
end
158155
object DarkStyle: TAction
159156
Tag = 3
160-
Category = 'Style'
157+
Category = 'Style.Item'
161158
Caption = 'Call of the Night'
162159
GroupIndex = 1
163160
OnExecute = StyleExecute

‎src/O2/uHTMLExport.pas‎

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -130,34 +130,36 @@ procedure THTMLExport.SetModel(Value: IHTMLExport);
130130
DefaultStyle.MacroByName('link-color').Value := '#0d6efd';
131131
DefaultStyle.MacroByName('border-color').Value := '#9ec5fe';
132132
DefaultStyle.MacroByName('alt-bg-color').Value := '#f4f8ff';
133-
BlueWaterStyle.Tag := FModel.AddStyle(DefaultStyle.ExpandMacros);
133+
BlueWaterStyle.Tag := FModel.AddStyle('BlueWater',
134+
DefaultStyle.ExpandMacros);
134135

135136
DefaultStyle.MacroByName('color').Value := '#000';
136137
DefaultStyle.MacroByName('background-color').Value := '#fff';
137138
DefaultStyle.MacroByName('link-color').Value := '#a1952e';
138139
DefaultStyle.MacroByName('border-color').Value := '#d5e3c0';
139140
DefaultStyle.MacroByName('alt-bg-color').Value := '#f1f6ea';
140-
MatchaStyle.Tag := FModel.AddStyle(DefaultStyle.ExpandMacros);
141+
MatchaStyle.Tag := FModel.AddStyle('Matcha', DefaultStyle.ExpandMacros);
141142

142143
DefaultStyle.MacroByName('color').Value := '#000';
143144
DefaultStyle.MacroByName('background-color').Value := '#fff';
144145
DefaultStyle.MacroByName('link-color').Value := '#c3829e';
145146
DefaultStyle.MacroByName('border-color').Value := '#fcc9b9';
146147
DefaultStyle.MacroByName('alt-bg-color').Value := '#fff5f2';
147-
SakuraStyle.Tag := FModel.AddStyle(DefaultStyle.ExpandMacros);
148+
SakuraStyle.Tag := FModel.AddStyle('Sakura', DefaultStyle.ExpandMacros);
148149

149150
DefaultStyle.MacroByName('color').Value := '#f0f6fc';
150151
DefaultStyle.MacroByName('background-color').Value := '#0d1117';
151152
DefaultStyle.MacroByName('link-color').Value := '#aaeeff';
152153
DefaultStyle.MacroByName('border-color').Value := '#3d444d';
153154
DefaultStyle.MacroByName('alt-bg-color').Value := '#151b23';
154-
DarkStyle.Tag := FModel.AddStyle(DefaultStyle.ExpandMacros);
155+
DarkStyle.Tag := FModel.AddStyle('Dark', DefaultStyle.ExpandMacros);
155156

156157
I := 0;
157158
while FModel.TryGetStyleFileName(I, FileName) do
158159
begin
159160
AAction := TAction.Create(Self);
160161
AAction.Caption := ChangeFileExt(ExtractFileName(FileName), '');
162+
AAction.Category := BlueWaterStyle.Category;
161163
AAction.GroupIndex := BlueWaterStyle.GroupIndex;
162164
AAction.OnExecute := StyleExecute;
163165
AAction.OnUpdate := StyleUpdate;
@@ -167,12 +169,19 @@ procedure THTMLExport.SetModel(Value: IHTMLExport);
167169
AMenuItem.Action := AAction;
168170
StyleMenu.Items.Add(AMenuItem);
169171

170-
AAction.Tag := FModel.AddStyle(TFile.ReadAllText(FileName));
172+
AAction.Tag := FModel.AddStyle(ExtractFileName(FileName),
173+
TFile.ReadAllText(FileName));
171174

172175
Inc(I);
173176
end;
174177

175-
BlueWaterStyle.Execute;
178+
if not ActionList.EnumByCategory(
179+
procedure(const Action: TContainedAction; var Done: boolean)
180+
begin
181+
Done := Action.Tag = FModel.StyleIndex;
182+
if Done then Action.Execute;
183+
end, BlueWaterStyle.Category, False) then
184+
BlueWaterStyle.Execute;
176185
end;
177186
end;
178187

‎src/O2/uServices.pas‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ interface
371371
procedure StoreSettings;
372372

373373
function TryGetStyleFileName(Index: Integer; out FileName: string): Boolean;
374-
function AddStyle(const Style: string): Integer;
374+
function AddStyle(const Name, Style: string): Integer;
375375

376376
function ExportToHTML(Preview: Boolean): string; overload;
377377
procedure ExportToHTML(const FileName: string); overload;

‎src/Tests/Testing.HTMLExportModel.pas‎

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ THTMLExportModelTests = class
4343
[TestCase('True' , 'True')]
4444
procedure LoadIncludePasswords(Value: Boolean);
4545

46+
[Test]
47+
[TestCase('First' , 'First,0')]
48+
[TestCase('Second', 'Second,1')]
49+
[TestCase('Third' , 'Third,2')]
50+
procedure LoadStyle(Value: string; StyleIndex: Integer);
51+
4652
[Test]
4753
[TestCase('False', 'False')]
4854
[TestCase('True' , 'True')]
@@ -67,6 +73,12 @@ THTMLExportModelTests = class
6773
[TestCase('False', 'False')]
6874
[TestCase('True' , 'True')]
6975
procedure SaveIncludePasswords(Value: Boolean);
76+
77+
[Test]
78+
[TestCase('First' , '0,First')]
79+
[TestCase('Second', '1,Second')]
80+
[TestCase('Third' , '2,Third')]
81+
procedure SaveStyle(StyleIndex: Integer; Value: string);
7082
end;
7183

7284
implementation
@@ -156,6 +168,24 @@ procedure THTMLExportModelTests.LoadIncludePasswords(Value: Boolean);
156168
Assert.AreEqual(Value, Model.IncludePasswords);
157169
end;
158170

171+
procedure THTMLExportModelTests.LoadStyle(Value: string; StyleIndex: Integer);
172+
var
173+
Storage: IStorage;
174+
Model: IHTMLExport;
175+
begin
176+
Storage := TXmlStorage.Create;
177+
Storage.WriteString('ExportToHTML.Style', Value);
178+
179+
Model := THTMLExportModel.Create(FO2File, FO2File.Objects.ToEnumerable,
180+
FAppVersionInfo, TAppFiles.Create, Storage);
181+
182+
Model.AddStyle('First', '');
183+
Model.AddStyle('Second', '');
184+
Model.AddStyle('Third', '');
185+
186+
Assert.AreEqual(StyleIndex, Model.StyleIndex);
187+
end;
188+
159189
procedure THTMLExportModelTests.SaveIncludeIndex(Value: Boolean);
160190
var
161191
Storage: IStorage;
@@ -236,4 +266,24 @@ procedure THTMLExportModelTests.SaveIncludePasswords(Value: Boolean);
236266
Assert.AreEqual(Value, Storage.ReadBoolean('ExportToHTML.Include.Passwords'));
237267
end;
238268

269+
procedure THTMLExportModelTests.SaveStyle(StyleIndex: Integer; Value: string);
270+
var
271+
Storage: IStorage;
272+
Model: IHTMLExport;
273+
begin
274+
Storage := TXmlStorage.Create;
275+
276+
Model := THTMLExportModel.Create(FO2File, FO2File.Objects.ToEnumerable,
277+
FAppVersionInfo, TAppFiles.Create, Storage);
278+
279+
Model.AddStyle('First', '');
280+
Model.AddStyle('Second', '');
281+
Model.AddStyle('Third', '');
282+
283+
Model.StyleIndex := StyleIndex;
284+
Model.StoreSettings;
285+
286+
Assert.AreEqual(Value, Storage.ReadString('ExportToHTML.Style'));
287+
end;
288+
239289
end.

‎test-results.md‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Total |Failures |Errors |Ignored |Date
44
---------|---------|---------|---------|-----------------------------
5-
819 |0 |0 |0 |2025-12-17T11:52:54.552+01:00
5+
825 |0 |0 |0 |2025-12-30T10:21:43.739+01:00
66

77
## Namespace Testing
88

@@ -361,6 +361,9 @@ LoadIncludeRelations.False|Pass|✔
361361
LoadIncludeRelations.True|Pass|✔
362362
LoadIncludeTags.False|Pass|✔
363363
LoadIncludeTags.True|Pass|✔
364+
LoadStyle.First|Pass|✔
365+
LoadStyle.Second|Pass|✔
366+
LoadStyle.Third|Pass|✔
364367
SaveIncludeIndex.False|Pass|✔
365368
SaveIncludeIndex.True|Pass|✔
366369
SaveIncludeNotes.False|Pass|✔
@@ -371,6 +374,9 @@ SaveIncludeRelations.False|Pass|✔
371374
SaveIncludeRelations.True|Pass|✔
372375
SaveIncludeTags.False|Pass|✔
373376
SaveIncludeTags.True|Pass|✔
377+
SaveStyle.First|Pass|✔
378+
SaveStyle.Second|Pass|✔
379+
SaveStyle.Third|Pass|✔
374380

375381
## Namespace ObjectModels
376382

0 commit comments

Comments
 (0)