chore(developer): move IDEOptions key responsibility into KeymanDeveloperOptions

First part of addressing #10161 is to refactor the existing usage of the
registry values into the common KeymanDeveloperOptions unit. This was
mostly straightforward except for the changes to KeymanSentryClient,
which happens to be the most important part of this particular fix.
This commit is contained in:
Marc Durdin 2023-12-11 13:48:43 +07:00
parent c945b203bd
commit 3a91c7d197
15 changed files with 145 additions and 129 deletions

View file

@ -18,7 +18,7 @@ uses
{$R *.res}
begin
TKeymanSentryClient.Start(TSentryClientVcl, kscpDesktop, '');
TKeymanSentryClient.Start(TSentryClientVcl, kscpDesktop, '', [kscfCaptureExceptions, kscfShowUI, kscfTerminate]);
try
Application.Initialize;
Application.MainFormOnTaskbar := True;

View file

@ -9,7 +9,8 @@ uses
type
TKeymanSentryClientProject = (kscpDesktop, kscpDeveloper);
TKeymanSentryClientFlags = set of (kscfCaptureExceptions, kscfShowUI, kscfTerminate);
TKeymanSentryClientFlags = set of (kscfCaptureExceptions, kscfShowUI, kscfTerminate,
kscfReportExceptions, kscfReportMessages);
TKeymanSentryClient = class
private
class var FInstance: TKeymanSentryClient;
@ -38,7 +39,7 @@ type
class procedure Breadcrumb(const BreadcrumbType, Message: string; const Category: string = ''; const Level: string = 'info');
class procedure Start(SentryClientClass: TSentryClientClass; AProject: TKeymanSentryClientProject; const ALogger: string; AFlags: TKeymanSentryClientFlags = [kscfCaptureExceptions, kscfShowUI, kscfTerminate]);
class procedure Start(SentryClientClass: TSentryClientClass; AProject: TKeymanSentryClientProject; const ALogger: string; AFlags: TKeymanSentryClientFlags);
class procedure Stop;
class property Client: TSentryClient read FClient;
class property Enabled: Boolean read GetEnabled;
@ -52,6 +53,7 @@ type
const S_Sentry_ViewEvent_URL = 'https://sentry.io/organizations/keyman/projects/%0:s/events/%1:s/'; // Do not localize
end;
function LoadKeymanDesktopSentryFlags(Default: TKeymanSEntryClientFlags = [kscfCaptureExceptions, kscfShowUI, kscfTerminate]): TKeymanSentryClientFlags;
implementation
@ -315,7 +317,7 @@ var
reg: TRegistry;
o: TSentryClientOptions;
f: TSentryClientFlags;
path, RegKey: string;
path: string;
begin
Assert(not Assigned(FInstance));
@ -350,29 +352,11 @@ begin
// Load the registry settings for privacy settings
if AProject = kscpDesktop
then RegKey := SRegKey_KeymanEngine_CU
else RegKey := SRegKey_IDEOptions_CU;
if kscfReportExceptions in FFlags
then Include(f, scfReportExceptions);
reg := TRegistry.Create;
try
if reg.OpenKeyReadOnly(RegKey) then
begin
if not reg.ValueExists(SRegValue_AutomaticallyReportErrors) or
reg.ReadBool(SRegValue_AutomaticallyReportErrors) then
Include(f, scfReportExceptions);
if not reg.ValueExists(SRegValue_AutomaticallyReportUsage) or
reg.ReadBool(SRegValue_AutomaticallyReportUsage) then
Include(f, scfReportMessages);
end
else
begin
Include(f, scfReportExceptions);
Include(f, scfReportMessages);
end;
finally
reg.Free;
end;
if kscfReportMessages in FFlags
then Include(f, scfReportMessages);
o.HandlerPath := ExtractFilePath(path) + 'crashpad_handler.exe';
o.DatabasePath := TKeymanPaths.ErrorLogPath + 'sentry-'+SENTRY_SDK_VERSION+'-db';
@ -467,5 +451,36 @@ begin
writeln(n); // We'll never get here, but this stops a compiler warning
end;
// These functions may be moved elsewhere in the future, but in order to remove
// the registry load from TKeymanSentryClient, we'll start by extracting them
// from the constructor
function LoadKeymanDesktopSentryFlags(Default: TKeymanSentryClientFlags): TKeymanSentryClientFlags;
var
reg: TRegistry;
begin
Result := Default;
reg := TRegistry.Create;
try
if reg.OpenKeyReadOnly(SRegKey_KeymanEngine_CU) then
begin
if not reg.ValueExists(SRegValue_AutomaticallyReportErrors) or
reg.ReadBool(SRegValue_AutomaticallyReportErrors) then
Include(Result, kscfReportExceptions);
if not reg.ValueExists(SRegValue_AutomaticallyReportUsage) or
reg.ReadBool(SRegValue_AutomaticallyReportUsage) then
Include(Result, kscfReportMessages);
end
else
begin
Include(Result, kscfReportExceptions);
Include(Result, kscfReportMessages);
end;
finally
reg.Free;
end;
end;
end.

View file

@ -300,7 +300,6 @@ const
SRegKey_IDE_CU = SRegKey_KeymanDeveloper_CU + '\IDE'; // CU
SRegKey_IDEDock_CU = SRegKey_IDE_CU + '\Dock'; // CU
SRegKey_IDEFiles_CU = SRegKey_IDE_CU + '\Files'; // CU
SRegKey_IDEOptions_CU = SRegKey_IDE_CU + '\Options'; // CU
SRegKey_IDECharacterMap_CU = SRegKey_IDE_CU + '\Character Map'; // CU
SRegKey_IDEColours_CU = SRegKey_IDE_CU + '\Colours'; // CU
SRegKey_IDEEditFonts_CU = SRegKey_IDE_CU + '\EditFonts'; // CU
@ -355,53 +354,6 @@ const
SRegValue_IDEVKbd_ExportBMPUnicode = 'export bmp unicode'; // CU
SRegValue_IDEVKbd_ExportBMPPixelWidth = 'export bmp pixel width'; // CU
{ SRegKey_IDEOptions values }
SRegValue_IDEOptLinkFontSizes = 'link font sizes'; // CU
SRegValue_IDEOptUseTabCharacter = 'use tab char'; // CU
SRegValue_IDEOptIndentSize = 'indent size'; // CU
SRegValue_IDEOptDocVirusCheck = 'warn if packaging doc files'; // CU
SRegValue_IDEOptUseSyntaxHighlighting = 'use syntax highlighting'; // CU
SRegValue_IDEOptToolbarVisible = 'toolbar visible'; // CU
SRegValue_IDEOptUseOldDebugger = 'use old debugger'; // CU
SRegValue_IDEOptEditorTheme = 'editor theme'; // CU
SRegValue_IDEOptDebuggerBreakWhenExitingLine = 'debugger break when exiting line'; // CU
SRegValue_IDEOptDebuggerSingleStepAfterBreak = 'debugger single step after break'; // CU
SRegValue_IDEOptDebuggerShowStoreOffset = 'debugger show store offset'; // CU
SRegValue_IDEOptDebuggerAutoRecompileWithDebugInfo = 'debugger recompile with debug info'; // CU
SRegValue_IDEOptDebuggerAutoResetBeforeCompiling = 'debugger auto reset before compilng'; // CU
SRegValue_IDEOptAutoSaveBeforeCompiling = 'auto save before compiling'; // CU
SRegValue_IDEOptOSKAutoSaveBeforeImporting = 'osk auto save before importing'; // CU
// Note: keeping 'web host port' reg value name to ensure settings maintained
// from version 14.0 and earlier of Keyman Developer. Other values are
// new with Keyman Developer 15.0
SRegValue_IDEOptServerPort = 'web host port'; // I4021
SRegValue_IDEOptServerKeepAlive = 'server keep alive';
SRegValue_IDEOptServerNgrokToken = 'server ngrok token';
SRegValue_IDEOptServerNgrokRegion = 'server ngrok region';
SRegValue_IDEOptServerUseLocalAddresses = 'server use local addresses';
SRegValue_IDEOptServerUseNgrok = 'server use ngrok';
SRegValue_IDEOptServerShowConsoleWindow = 'server show console window';
SRegValue_IDEOptCharMapDisableDatabaseLookups = 'char map disable database lookups'; // CU
SRegValue_IDEOptCharMapAutoLookup = 'char map auto lookup'; // CU
SRegValue_IDEOptOpenKeyboardFilesInSourceView = 'open keyboard files in source view'; // CU // I4751
SRegValue_IDEDisplayTheme = 'display theme'; // I4796
SRegValue_IDEOptExternalEditorPath = 'external editor path'; // CU
SRegValue_IDEOptSMTPServer = 'smtp server'; // CU // I4506
SRegValue_IDEOptTestEmailAddresses = 'test email addresses'; // CU // I4506
SRegValue_IDEOpt_WebLadderLength = 'web ladder length'; // CU
CRegValue_IDEOpt_WebLadderLength_Default = 100;
SRegValue_IDEOpt_DefaultProjectPath = 'default project path';
{-------------------------------------------------------------------------------
- Shared keys and values -

View file

@ -85,7 +85,9 @@ uses
KeymanPaths in '..\..\..\common\windows\delphi\general\KeymanPaths.pas',
Keyman.System.Standards.LangTagsRegistry in '..\..\..\common\windows\delphi\standards\Keyman.System.Standards.LangTagsRegistry.pas',
Keyman.Developer.System.Project.UrlRenderer in '..\TIKE\project\Keyman.Developer.System.Project.UrlRenderer.pas',
Keyman.System.LexicalModelUtils in '..\common\delphi\lexicalmodels\Keyman.System.LexicalModelUtils.pas';
Keyman.System.LexicalModelUtils in '..\common\delphi\lexicalmodels\Keyman.System.LexicalModelUtils.pas',
KeymanDeveloperOptions in '..\TIKE\main\KeymanDeveloperOptions.pas',
Keyman.Developer.System.KeymanDeveloperPaths in '..\tike\main\Keyman.Developer.System.KeymanDeveloperPaths.pas';
{$R icons.RES}
{$R version.res}
@ -94,7 +96,7 @@ uses
const
LOGGER_DEVELOPER_TOOLS_KMCONVERT = TKeymanSentryClient.LOGGER_DEVELOPER_TOOLS + '.kmconvert';
begin
TKeymanSentryClient.Start(TSentryClientConsole, kscpDeveloper, LOGGER_DEVELOPER_TOOLS_KMCONVERT);
TKeymanSentryClient.Start(TSentryClientConsole, kscpDeveloper, LOGGER_DEVELOPER_TOOLS_KMCONVERT, LoadKeymanDeveloperSentryFlags);
try
try
TKeymanSentryClient.Validate;

View file

@ -194,6 +194,8 @@
<DCCReference Include="..\..\..\common\windows\delphi\standards\Keyman.System.Standards.LangTagsRegistry.pas"/>
<DCCReference Include="..\TIKE\project\Keyman.Developer.System.Project.UrlRenderer.pas"/>
<DCCReference Include="..\common\delphi\lexicalmodels\Keyman.System.LexicalModelUtils.pas"/>
<DCCReference Include="..\TIKE\main\KeymanDeveloperOptions.pas"/>
<DCCReference Include="..\tike\main\Keyman.Developer.System.KeymanDeveloperPaths.pas"/>
<BuildConfiguration Include="Release">
<Key>Cfg_2</Key>
<CfgParent>Base</CfgParent>

View file

@ -12,6 +12,7 @@ uses
uCEFApplication,
uCEFTypes,
KeymanDeveloperOptions,
Keyman.Developer.System.TikeCommandLine,
Keyman.System.CEFManager,
Keyman.System.KeymanSentryClient,
@ -36,7 +37,7 @@ begin
Application.Initialize;
Application.Title := 'Keyman Developer';
TKeymanSentryClient.Start(TSentryClientVcl, kscpDeveloper, LOGGER_DEVELOPER_IDE_TIKE);
TKeymanSentryClient.Start(TSentryClientVcl, kscpDeveloper, LOGGER_DEVELOPER_IDE_TIKE, LoadKeymanDeveloperSentryFlags);
try
try
RunWithExceptionsHandled;

View file

@ -38,31 +38,17 @@ uses
Vcl.Dialogs,
Winapi.Windows,
ErrorControlledRegistry,
Keyman.Developer.System.LaunchProjects,
RegistryKeys,
KeymanDeveloperOptions,
utilexecute;
{ TTikeCommandLine }
constructor TTikeCommandLine.Create;
var
reg: TRegistryErrorControlled;
begin
inherited Create;
FStartupProjectPath := '';
reg := TRegistryErrorControlled.Create; // I2890
try
if reg.OpenKeyReadOnly(SRegKey_IDEOptions_CU) then
begin
if reg.ValueExists(SRegValue_ActiveProject) then
FStartupProjectPath := reg.ReadString(SRegValue_ActiveProject);
end;
finally
reg.Free;
end;
FStartupProjectPath := FKeymanDeveloperOptions.StartupProjectPath;
if (FStartupProjectPath <> '') and not FileExists(FStartupProjectPath) then
begin

View file

@ -33,7 +33,8 @@ uses
Winapi.Windows,
ErrorControlledRegistry,
RegistryKeys;
RegistryKeys,
Keyman.System.KeymanSentryClient;
type
TKeymanDeveloperOptions = class
@ -69,6 +70,8 @@ type
FServerNgrokToken: string;
FServerNgrokRegion: string;
FServerKeepAlive: Boolean;
FToolbarVisible: Boolean;
FStartupProjectPath: string;
procedure CloseRegistry;
procedure OpenRegistry;
function regReadString(const nm, def: string): string;
@ -123,9 +126,13 @@ type
property ExternalEditorPath: WideString read FExternalEditorPath write FExternalEditorPath;
property SMTPServer: string read FSMTPServer write FSMTPServer; // I4506
property TestEmailAddresses: string read FTestEmailAddresses write FTestEmailAddresses; // I4506
property ToolbarVisible: Boolean read FToolbarVisible write FToolbarVisible;
property StartupProjectPath: string read FStartupProjectPath write FStartupProjectPath;
end;
function FKeymanDeveloperOptions: TKeymanDeveloperOptions;
function LoadKeymanDeveloperSentryFlags: TKeymanSentryClientFlags;
//procedure CreateKeymanDeveloperOptions;
//procedure DestroyKeymanDeveloperOptions;
@ -150,6 +157,7 @@ uses
System.Classes,
System.JSON,
System.Math,
System.StrUtils,
Winapi.ShlObj,
JsonUtil,
@ -157,6 +165,57 @@ uses
utilsystem,
GetOSVersion;
const
{ SRegKey_IDEOptions values }
SRegKey_IDEOptions_CU = SRegKey_IDE_CU + '\Options'; // CU
SRegValue_IDEOptLinkFontSizes = 'link font sizes'; // CU
SRegValue_IDEOptUseTabCharacter = 'use tab char'; // CU
SRegValue_IDEOptIndentSize = 'indent size'; // CU
SRegValue_IDEOptDocVirusCheck = 'warn if packaging doc files'; // CU
SRegValue_IDEOptUseSyntaxHighlighting = 'use syntax highlighting'; // CU
SRegValue_IDEOptToolbarVisible = 'toolbar visible'; // CU
SRegValue_IDEOptUseOldDebugger = 'use old debugger'; // CU
SRegValue_IDEOptEditorTheme = 'editor theme'; // CU
SRegValue_IDEOptDebuggerBreakWhenExitingLine = 'debugger break when exiting line'; // CU
SRegValue_IDEOptDebuggerSingleStepAfterBreak = 'debugger single step after break'; // CU
SRegValue_IDEOptDebuggerShowStoreOffset = 'debugger show store offset'; // CU
SRegValue_IDEOptDebuggerAutoRecompileWithDebugInfo = 'debugger recompile with debug info'; // CU
SRegValue_IDEOptDebuggerAutoResetBeforeCompiling = 'debugger auto reset before compilng'; // CU
SRegValue_IDEOptAutoSaveBeforeCompiling = 'auto save before compiling'; // CU
SRegValue_IDEOptOSKAutoSaveBeforeImporting = 'osk auto save before importing'; // CU
// Note: keeping 'web host port' reg value name to ensure settings maintained
// from version 14.0 and earlier of Keyman Developer. Other values are
// new with Keyman Developer 15.0
SRegValue_IDEOptServerPort = 'web host port'; // I4021
SRegValue_IDEOptServerKeepAlive = 'server keep alive';
SRegValue_IDEOptServerNgrokToken = 'server ngrok token';
SRegValue_IDEOptServerNgrokRegion = 'server ngrok region';
SRegValue_IDEOptServerUseLocalAddresses = 'server use local addresses';
SRegValue_IDEOptServerUseNgrok = 'server use ngrok';
SRegValue_IDEOptServerShowConsoleWindow = 'server show console window';
SRegValue_IDEOptCharMapDisableDatabaseLookups = 'char map disable database lookups'; // CU
SRegValue_IDEOptCharMapAutoLookup = 'char map auto lookup'; // CU
SRegValue_IDEOptOpenKeyboardFilesInSourceView = 'open keyboard files in source view'; // CU // I4751
SRegValue_IDEDisplayTheme = 'display theme'; // I4796
SRegValue_IDEOptExternalEditorPath = 'external editor path'; // CU
SRegValue_IDEOptSMTPServer = 'smtp server'; // CU // I4506
SRegValue_IDEOptTestEmailAddresses = 'test email addresses'; // CU // I4506
SRegValue_IDEOpt_WebLadderLength = 'web ladder length'; // CU
CRegValue_IDEOpt_WebLadderLength_Default = 100;
SRegValue_IDEOpt_DefaultProjectPath = 'default project path';
var
AFKeymanDeveloperOptions: TKeymanDeveloperOptions = nil;
@ -247,6 +306,10 @@ begin
(reg.ReadInteger(SRegValue_AutomaticallyReportErrors) <> 0);
FReportUsage := not reg.ValueExists(SRegValue_AutomaticallyReportUsage) or
(reg.ReadInteger(SRegValue_AutomaticallyReportUsage) <> 0);
FToolbarVisible := regReadString(SRegValue_IDEOptToolbarVisible, '1') <> '0';
FStartupProjectPath := regReadString(SRegValue_ActiveProject, '');
finally
CloseRegistry;
end;
@ -301,6 +364,10 @@ begin
// to write integers as a REG_SZ type and that's far too messy to change now.
reg.WriteInteger(SRegValue_AutomaticallyReportErrors, IfThen(FReportErrors, 1, 0));
reg.WriteInteger(SRegValue_AutomaticallyReportUsage, IfThen(FReportUsage, 1, 0));
reg.WriteString(SRegValue_IDEOptToolbarVisible, IfThen(FToolbarVisible, '1', '0'));
reg.WriteString(SRegValue_ActiveProject, FStartupProjectPath);
finally
CloseRegistry;
end;
@ -400,6 +467,15 @@ begin
Result := DefaultEditorThemeItemIndex(s) >= 0;
end;
function LoadKeymanDeveloperSentryFlags: TKeymanSentryClientFlags;
begin
Result := [kscfCaptureExceptions, kscfShowUI, kscfTerminate];
if FKeymanDeveloperOptions.ReportErrors then
Include(Result, kscfReportExceptions);
if FKeymanDeveloperOptions.ReportUsage then
Include(Result, kscfReportMessages);
end;
initialization
finalization
DestroyKeymanDeveloperOptions;

View file

@ -574,17 +574,8 @@ begin
Application.HelpFile := GetHelpURL; // I4677 // I4841
mHHelp := TWebHookHelpSystem.Create(Application.HelpFile); // I4677 // I4841
with TRegistryErrorControlled.Create do // I2890
try
RootKey := HKEY_CURRENT_USER;
if OpenKeyReadOnly(SRegKey_IDEOptions_CU) then
begin
if ValueExists(SRegValue_IDEOptToolbarVisible) and (ReadString(SRegValue_IDEOptToolbarVisible) = '0') then
barTools.Visible := False;
end;
finally
Free;
end;
if not FKeymanDeveloperOptions.ToolbarVisible then
barTools.Visible := False;
RemoveOldestTikeEditFonts(False);
RemoveOldestTikeTestFonts(False);
@ -671,25 +662,16 @@ begin
FChildWindows[i].Release; // I2595, probably not necessary
end;
with TRegistryErrorControlled.Create do // I2890
try
RootKey := HKEY_CURRENT_USER;
if OpenKey(SRegKey_IDEOptions_CU, True) then
begin
if IsGlobalProjectUIReady then
begin
FGlobalProject.Save; // I4691
WriteString(SRegValue_ActiveProject, FGlobalProject.FileName);
end
else
begin
if ValueExists(SRegValue_ActiveProject) then
DeleteValue(SRegValue_ActiveProject);
end;
end;
finally
Free;
if IsGlobalProjectUIReady then
begin
FGlobalProject.Save; // I4691
FKeymanDeveloperOptions.StartupProjectPath := FGlobalProject.FileName;
end
else
begin
FKeymanDeveloperOptions.StartupProjectPath := '';
end;
FKeymanDeveloperOptions.Write;
FreeAndNil(frmCharacterMapDock);
FreeAndNil(frmCharacterIdentifier); // I4807

View file

@ -32,7 +32,7 @@ const
LOGGER_DESKTOP_KMBROWSERHOST = TKeymanSentryClient.LOGGER_DESKTOP + '.kmbrowserhost';
begin
TKeymanSentryClient.Start(TSentryClient, kscpDesktop,
LOGGER_DESKTOP_KMBROWSERHOST, [kscfCaptureExceptions, kscfTerminate]); // no ui wanted
LOGGER_DESKTOP_KMBROWSERHOST, LoadKeymanDesktopSentryFlags([kscfCaptureExceptions, kscfTerminate])); // no ui wanted
try
try
TKeymanSentryClient.Validate;

View file

@ -25,7 +25,7 @@ uses
const
LOGGER_DESKTOP_KMCONFIG = TKeymanSentryClient.LOGGER_DESKTOP + '.kmconfig';
begin
TKeymanSentryClient.Start(TSentryClientConsole, kscpDesktop, LOGGER_DESKTOP_KMCONFIG);
TKeymanSentryClient.Start(TSentryClientConsole, kscpDesktop, LOGGER_DESKTOP_KMCONFIG, LoadKeymanDesktopSentryFlags);
try
try
TKeymanSentryClient.Validate;

View file

@ -188,7 +188,7 @@ uses
const
LOGGER_DESKTOP_KMSHELL = TKeymanSentryClient.LOGGER_DESKTOP + '.kmshell';
begin
TKeymanSentryClient.Start(TSentryClientVcl, kscpDesktop, LOGGER_DESKTOP_KMSHELL);
TKeymanSentryClient.Start(TSentryClientVcl, kscpDesktop, LOGGER_DESKTOP_KMSHELL, LoadKeymanDesktopSentryFlags);
try
CoInitFlags := COINIT_APARTMENTTHREADED;
FInitializeCEF := TCEFManager.Create;

View file

@ -125,7 +125,7 @@ uses
const
LOGGER_DESKTOP_ENGINE_KEYMAN = TKeymanSentryClient.LOGGER_DESKTOP_ENGINE + '.keyman';
begin
TKeymanSentryClient.Start(TSentryClientVcl, kscpDesktop, LOGGER_DESKTOP_ENGINE_KEYMAN);
TKeymanSentryClient.Start(TSentryClientVcl, kscpDesktop, LOGGER_DESKTOP_ENGINE_KEYMAN, LoadKeymanDesktopSentryFlags);
try
Run;
finally

View file

@ -71,7 +71,7 @@ const
LOGGER_DESKTOP_ENGINE_TSYSINFO = TKeymanSentryClient.LOGGER_DESKTOP_ENGINE + '.tsysinfo';
begin
TKeymanSentryClient.Start(TSentryClientVcl, kscpDesktop, LOGGER_DESKTOP_ENGINE_TSYSINFO,
[kscfCaptureExceptions]); // no ui for exceptions, no termination
LoadKeymanDesktopSentryFlags([kscfCaptureExceptions])); // no ui for exceptions, no termination
try
if RunCrashReportHandler then
Exit;

View file

@ -25,7 +25,7 @@ uses
const
LOGGER_DESKTOP_ENGINE_TSYSINFOX64 = TKeymanSentryClient.LOGGER_DESKTOP_ENGINE + '.tsysinfox64';
begin
TKeymanSentryClient.Start(TSentryClient, kscpDesktop, LOGGER_DESKTOP_ENGINE_TSYSINFOX64);
TKeymanSentryClient.Start(TSentryClient, kscpDesktop, LOGGER_DESKTOP_ENGINE_TSYSINFOX64, LoadKeymanDesktopSentryFlags);
try
try
TKeymanSentryClient.Validate;