Skip to content

Commit 057b416

Browse files
committed
Add start-up code to determine if What's New dialogue is required.
Some additional version information code was added to enable testing if a version number falls within a desired range.
1 parent 1657455 commit 057b416

File tree

3 files changed

+96
-7
lines changed

3 files changed

+96
-7
lines changed

Src/FirstRun.UConfigFile.pas

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@
1616
interface
1717

1818

19+
uses
20+
// Project
21+
UVersionInfo;
22+
23+
1924
type
2025
/// <summary>Class that manages the updating of older config files to the
2126
/// current format. Missing files will also be created.</summary>
@@ -60,6 +65,9 @@ TConfigFileUpdater = class abstract(TObject)
6065
/// <summary>Checks if program version in config file is same as current
6166
/// program version.</summary>
6267
function IsCurrentProgramVer: Boolean; overload;
68+
class function PreviousProgramVer(const CfgFileName: string):
69+
TVersionNumber; overload;
70+
function PreviousProgramVer: TVersionNumber; overload;
6371
/// <summary>Stamps config file with current file version.</summary>
6472
procedure Stamp; virtual;
6573
end;
@@ -234,10 +242,25 @@ class function TConfigFileUpdater.IsCurrentProgramVer(
234242
var
235243
CfgProgVer: string; // program version from config file
236244
begin
237-
CfgProgVer := GetIniString('IniFile', 'ProgramVersion', '', CfgFileName);
245+
CfgProgVer := PreviousProgramVer(CfgFileName);
238246
Result := CfgProgVer = TAppInfo.ProgramReleaseVersion;
239247
end;
240248

249+
function TConfigFileUpdater.PreviousProgramVer: TVersionNumber;
250+
begin
251+
Result := PreviousProgramVer(fCfgFileName);
252+
end;
253+
254+
class function TConfigFileUpdater.PreviousProgramVer(
255+
const CfgFileName: string): TVersionNumber;
256+
begin
257+
if not TVersionNumber.TryStrToVersionNumber(
258+
GetIniString('IniFile', 'ProgramVersion', '', CfgFileName),
259+
Result
260+
) then
261+
Exit(TVersionNumber.Nul);
262+
end;
263+
241264
procedure TConfigFileUpdater.Stamp;
242265
begin
243266
if not TFile.Exists(fCfgFileName, False) then

Src/FirstRun.UMain.pas

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ interface
1919

2020
uses
2121
// Project
22-
FirstRun.UConfigFile, FirstRun.UDatabase, FirstRun.UInstallInfo;
22+
FirstRun.UConfigFile, FirstRun.UDatabase, FirstRun.UInstallInfo, UVersionInfo;
2323

2424

2525
type
@@ -79,8 +79,17 @@ TFirstRun = class(TObject)
7979
/// <summary>Creates a new, empty, Unicode encoded per-user config file for
8080
/// current installation.</summary>
8181
procedure CreateEmptyUserCfgFile;
82-
/// <summary>
82+
/// <summary>Checks if the program has been updated since the last run.
83+
/// </summary>
84+
/// <remarks>Compares the version number stored in the brought forward
85+
/// config file against the current program version number from resources.
86+
/// </remarks>
8387
function IsProgramUpdated: Boolean;
88+
/// <summary>Checks if the previous program's version number, as specified
89+
/// in the user config file, is contained in the range Lo..Hi with range
90+
/// endpoints determined by IntervalEndPoints.</summary>
91+
function IsPreviousProgramVerInRange(const Lo, Hi: TVersionNumber;
92+
const IntervalEndPoints: TVersionNumber.TIntervalEndPoints): Boolean;
8493
end;
8594

8695
type
@@ -108,7 +117,8 @@ TFirstRunMgr = class(TObject)
108117
class function IsProgramUpdated: Boolean;
109118
public
110119
/// <summary>Runs start-up checks to detect if program has been run before
111-
/// and performs any required user config and user database updates.
120+
/// and performs any required user config and user database updates. In
121+
/// some circumstances a "what's new" dialogue box may be displayed.
112122
/// </summary>
113123
class procedure Execute;
114124
end;
@@ -119,9 +129,10 @@ implementation
119129

120130
uses
121131
// Delphi
122-
SysUtils, IOUtils, Forms
123-
{$IFNDEF PORTABLE}
132+
SysUtils, IOUtils, Forms,
124133
// Project
134+
FirstRun.FmWhatsNew
135+
{$IFNDEF PORTABLE}
125136
,
126137
FirstRun.FmV4ConfigDlg;
127138
{$ELSE}
@@ -187,6 +198,15 @@ function TFirstRun.HaveOldUserDB: Boolean;
187198
Result := TFile.Exists(fInstallInfo.PreviousUserDatabaseFileName, False);
188199
end;
189200

201+
function TFirstRun.IsPreviousProgramVerInRange(const Lo, Hi: TVersionNumber;
202+
const IntervalEndPoints: TVersionNumber.TIntervalEndPoints): Boolean;
203+
var
204+
PrevProgVer: TVersionNumber;
205+
begin
206+
PrevProgVer := fUserConfigFile.PreviousProgramVer;
207+
Result := PrevProgVer.IsInRange(Lo, Hi, IntervalEndPoints);
208+
end;
209+
190210
function TFirstRun.IsProgramUpdated: Boolean;
191211
begin
192212
Result := fUserConfigFile.IsCurrentProgramVer;
@@ -270,6 +290,12 @@ procedure TFirstRun.UpdateUserCfgFile(out Changes: TFirstRunCfgChangeSet);
270290
{ TFirstRunMgr }
271291

272292
class procedure TFirstRunMgr.Execute;
293+
const
294+
// Version numbers specifying a range in which previous program version must
295+
// lie in order to display "What's New" dialogue box.
296+
// Range is [NeedWhatsNewLoVerIncl, NeedWhatsNewHiVerExcl)
297+
NeedWhatsNewLoVerIncl: TVersionNumber = (V1: 4; V2: 0; V3: 0; V4: 0);
298+
NeedWhatsNewHiVerExcl: TVersionNumber = (V1: 4; V2: 16; V3: 0; V4: 0);
273299
var
274300
FR: TFirstRun;
275301
Changes: TFirstRunCfgChangeSet;
@@ -295,7 +321,15 @@ class procedure TFirstRunMgr.Execute;
295321
begin
296322
FR := TFirstRun.Create;
297323
try
298-
FR.UpdateUserCfgFile(Changes);
324+
// We display "What's New" dialogue box if previous program version number
325+
// is in the given range
326+
if FR.IsPreviousProgramVerInRange(
327+
NeedWhatsNewLoVerIncl,
328+
NeedWhatsNewHiVerExcl,
329+
TVersionNumber.TIntervalEndPoints.iepHalfOpenHi
330+
) then
331+
TWhatsNewDlg.Execute(Application);
332+
FR.UpdateUserCfgFile(Changes); // we ignore Changes [out] param value
299333
finally
300334
FR.Free;
301335
end;

Src/UVersionInfo.pas

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,17 @@ TVersionNumber = record
3333
strict private
3434
/// <summary>Converts version number to a string.</summary>
3535
function ToString: string;
36+
public
37+
type
38+
/// <summary>Enumeration that specifies whether intervals used in range
39+
/// checks are open, closed or half-open.</summary>
40+
/// <remarks>
41+
/// <para><c>iepOpen</c> - open interval (x,y)</para>
42+
/// <para><c>iepHalfOpenLo</c> - half open interval (x,y]</para>
43+
/// <para><c>iepHalfOpenHi</c> - half open interval [x,y)</para>
44+
/// <para><c>iepClosed</c> - closed interval [x,y]</para>
45+
/// </remarks>
46+
TIntervalEndPoints = (iepOpen, iepHalfOpenLo, iepHalfOpenHi, iepClosed);
3647
public
3748
V1: Word; // Major version number
3849
V2: Word; // Minor version number
@@ -45,6 +56,13 @@ TVersionNumber = record
4556
{Creates a nul version number with all fields set to zero.
4657
@return Required nul record.
4758
}
59+
/// <summary>Checks if the current version number is contained in the range
60+
/// Lo..Hi with range endpoints determined by EndPoints.</summary>
61+
/// <remarks>Note that when Lo=Hi the intervals (Lo,Hi), (Lo,Hi] and
62+
/// [Lo,Hi) represent the empty set, while [Lo,Hi] = {Lo}. When Lo &gt; Hi
63+
/// all interval types represent the empty set.</remarks>
64+
function IsInRange(const Lo, Hi: TVersionNumber;
65+
const EndPoints: TIntervalEndPoints): Boolean;
4866
/// <summary>Attempts to convert a string to a version number.</summary>
4967
/// <param name="S">string [in] String to convert.</param>
5068
/// <param name="V">Word [out] Converted version number.</param>
@@ -170,6 +188,7 @@ implementation
170188
// Delphi
171189
SysUtils,
172190
// Project
191+
UExceptions,
173192
UIStringList,
174193
UUtils;
175194

@@ -318,6 +337,19 @@ class function TVersionInfo.SpecialBuildStr: string;
318337
raise EConvertError.CreateFmt(sError, [Str]);
319338
end;
320339

340+
function TVersionNumber.IsInRange(const Lo, Hi: TVersionNumber;
341+
const EndPoints: TIntervalEndPoints): Boolean;
342+
begin
343+
case EndPoints of
344+
iepOpen: Result := (Lo < Self) and (Self < Hi);
345+
iepHalfOpenLo: Result := (Lo < Self) and (Self <= Hi);
346+
iepHalfOpenHi: Result := (Lo <= Self) and (Self < Hi);
347+
iepClosed: Result := (Lo <= Self) and (Self <= Hi);
348+
else
349+
raise EBug.Create('TVersionNumber.IsInRange: invalid Kind parameter');
350+
end;
351+
end;
352+
321353
function TVersionNumber.IsNull: Boolean;
322354
begin
323355
Result := Self = TVersionNumber.Nul;

0 commit comments

Comments
 (0)