From 5cd47724049c9d3b51a861f4e7cb47c1523b4a35 Mon Sep 17 00:00:00 2001 From: balazs Date: Wed, 23 Nov 2016 13:12:52 +0000 Subject: [PATCH] Extended options dialog. From now on the local repository path is configurable. git-svn-id: trunk@53424 - --- .../opkman_createrepositorypackagefr.pas | 12 +- .../onlinepackagemanager/opkman_common.pas | 28 +- .../onlinepackagemanager/opkman_const.pas | 23 +- .../opkman_downloader.pas | 24 +- .../onlinepackagemanager/opkman_mainfrm.pas | 34 +- .../onlinepackagemanager/opkman_options.pas | 124 +++-- .../opkman_optionsfrm.lfm | 457 +++++++++++++----- .../opkman_optionsfrm.pas | 136 +++++- .../opkman_serializablepackages.pas | 18 +- .../opkman_visualtree.pas | 2 +- 10 files changed, 598 insertions(+), 260 deletions(-) diff --git a/components/onlinepackagemanager/frames/opkman_createrepositorypackagefr.pas b/components/onlinepackagemanager/frames/opkman_createrepositorypackagefr.pas index f34e2428c6..ea837ae676 100644 --- a/components/onlinepackagemanager/frames/opkman_createrepositorypackagefr.pas +++ b/components/onlinepackagemanager/frames/opkman_createrepositorypackagefr.pas @@ -356,15 +356,15 @@ var begin CanGo := False; SDD.Title := rsCreateRepositorySDDTitleSrc; - SDD.InitialDir := PackageOptions.LastPackagedirSrc; + SDD.InitialDir := Options.LastPackagedirSrc; if SDD.Execute then begin ShowHideControls(1); Application.ProcessMessages; try FPackageDir := AppendPathDelim(SDD.FileName); - PackageOptions.LastPackageDirSrc := FPackageDir; - PackageOptions.Changed := True; + Options.LastPackageDirSrc := FPackageDir; + Options.Changed := True; edPackageDir.Text := FPackageDir; PackageList := TStringList.Create; try @@ -496,15 +496,15 @@ begin end; SDD.Title := rsCreateRepositorySDDTitleDst; - SDD.InitialDir := PackageOptions.LastPackagedirDst; + SDD.InitialDir := Options.LastPackagedirDst; if SDD.Execute then begin fPackageZipper := TPackageZipper.Create; fPackageZipper.OnZipError := @DoOnZippError; fPackageZipper.OnZipCompleted := @DoOnZipCompleted; FDestDir := AppendPathDelim(SDD.FileName); - PackageOptions.LastPackagedirDst := FDestDir; - PackageOptions.Changed := True; + Options.LastPackagedirDst := FDestDir; + Options.Changed := True; FPackageName := StringReplace(FPackageName, ' ', '', [rfReplaceAll]); FPackageFile := FDestDir + FPackageName + '.zip'; pnMessage.Caption := rsCreateRepositoryPackageMessage4; diff --git a/components/onlinepackagemanager/opkman_common.pas b/components/onlinepackagemanager/opkman_common.pas index c0552bb11d..cfd10a7ad3 100644 --- a/components/onlinepackagemanager/opkman_common.pas +++ b/components/onlinepackagemanager/opkman_common.pas @@ -42,13 +42,7 @@ type end; var - LocalRepository: String; - LocalRepositoryArchive: String; - LocalRepositoryPackages: String; - LocalRepositoryConfig: String; - LocalRepositoryUpdate: String; LocalRepositoryConfigFile: String; - ConfigFile: String; PackageAction: TPackageAction; ForceDownload: Boolean = True; ForceExtract: Boolean = True; @@ -56,7 +50,7 @@ var function MessageDlgEx(const AMsg: String; ADlgType: TMsgDlgType; AButtons: TMsgDlgButtons; AParent: TForm): TModalResult; -function InitLocalRepository: Boolean; +procedure InitLocalRepository; function SecToHourAndMin(const ASec: LongInt): String; function FormatSize(Size: Int64): String; function FormatSpeed(Speed: LongInt): String; @@ -84,28 +78,18 @@ begin end; end; -function InitLocalRepository: Boolean; +procedure InitLocalRepository; +var + LocalRepository, LocalRepositoryConfig: String; begin LocalRepository := AppendPathDelim(AppendPathDelim(LazarusIDE.GetPrimaryConfigPath) + cLocalRepository); if not DirectoryExistsUTF8(LocalRepository) then CreateDirUTF8(LocalRepository); - LocalRepositoryArchive := AppendPathDelim(LocalRepository + AppendPathDelim(cLocalRepositoryArchive)); - if not DirectoryExistsUTF8(LocalRepositoryArchive) then - CreateDirUTF8(LocalRepositoryArchive); - LocalRepositoryUpdate := AppendPathDelim(LocalRepository + AppendPathDelim(cLocalRepositoryUpdate)); - if not DirectoryExists(LocalRepositoryUpdate) then - CreateDir(LocalRepositoryUpdate); - LocalRepositoryPackages := AppendPathDelim(LocalRepository + AppendPathDelim(cLocalRepositoryPackages)); - if not DirectoryExists(LocalRepositoryPackages) then - CreateDir(LocalRepositoryPackages); - LocalRepositoryConfig := AppendPathDelim(LocalRepository + AppendPathDelim(cLocalRepositoryConfig)); + + LocalRepositoryConfig := AppendPathDelim(LocalRepository + cLocalRepositoryConfig); if not DirectoryExists(LocalRepositoryConfig) then CreateDir(LocalRepositoryConfig); LocalRepositoryConfigFile := LocalRepositoryConfig + cLocalRepositoryConfigFile; - Result := DirectoryExistsUTF8(LocalRepository) and - DirectoryExistsUTF8(LocalRepositoryArchive) and - DirectoryExistsUTF8(LocalRepositoryConfig) and - DirectoryExistsUTF8(LocalRepositoryPackages); end; function SecToHourAndMin(const ASec: LongInt): String; diff --git a/components/onlinepackagemanager/opkman_const.pas b/components/onlinepackagemanager/opkman_const.pas index 6fc4a29e8f..e8167d3407 100644 --- a/components/onlinepackagemanager/opkman_const.pas +++ b/components/onlinepackagemanager/opkman_const.pas @@ -161,10 +161,25 @@ resourcestring rsProgressFrmInfo4 = 'Canceling. Please wait...'; //options form - rsOptionsFrmCaption = 'Options'; - rsOptionedRemoteRepository = 'Please enter the remote repository address!'; - rsOptionedProxyServer = 'Please enter the proxy server address!'; - rsOptionedProxyPort = 'Please enter the proxy server port!'; + rsOptions_FrmCaption = 'Options'; + rsOptions_lbRemoteRepository_Caption = 'Remote repository'; + rsOptions_cbProxy_Caption = 'Use proxy'; + rsOptions_gbProxySettings_Caption = 'Proxy settings'; + rsOptions_lbServer_Caption = 'Server'; + rsOptions_lbPort_Caption = 'Port'; + rsOptions_lbUsername_Caption = 'Username'; + rsOptions_lbPassword_Caption = 'Password'; + rsOptions_lbLocalRepositoryPackages_Caption = 'Local repository'; + rsOptions_edLocalRepositoryPackages_Hint = 'The folder where the repository packages are extracted/installed'; + rsOptions_lbLocalRepositoryArchive_Caption = 'Archive directory'; + rsOptions_edLocalRepositoryArchive_Hint = 'The folder where the zip files are downloaded from the remote repository'; + rsOptions_lbLocalRepositoryUpdate_Caption = 'Update directory'; + rsOptions_edLocalRepositoryUpdate_Hint = 'The folder where the zip files are downloaded from the package maintainer webpage'; + rsOptions_RemoteRepository_Information = 'Please enter the remote repository address!'; + rsOptions_ProxyServer_Information = 'Please enter the proxy server address!'; + rsOptions_ProxyPort_Information = 'Please enter the proxy server port!'; + rsOptions_InvalidDirectory_Information = 'Please enter a valid directory'; + rsOptions_RestoreDefaults_Confirmation = 'This will restore the default settings. Continue?'; //packagelist form rsPackageListFrmCaption0 = 'Installed package list'; diff --git a/components/onlinepackagemanager/opkman_downloader.pas b/components/onlinepackagemanager/opkman_downloader.pas index 5873a0516d..0fd93a722c 100644 --- a/components/onlinepackagemanager/opkman_downloader.pas +++ b/components/onlinepackagemanager/opkman_downloader.pas @@ -348,7 +348,7 @@ begin if SerializablePackages.Items[I].IsDownloadable then begin Inc(FCnt); - FFrom := PackageOptions.RemoteRepository + SerializablePackages.Items[I].RepositoryFileName; + FFrom := Options.RemoteRepository + SerializablePackages.Items[I].RepositoryFileName; FTo := FDownloadTo + SerializablePackages.Items[I].RepositoryFileName; FCurSize := SerializablePackages.Items[I].RepositoryFileSize; DS := TDownloadStream.Create(TFileStream.Create(FTo, fmCreate)); @@ -479,12 +479,12 @@ begin FTimer := nil; FMS := TMemoryStream.Create; FHTTPClient := TFPHTTPClient.Create(nil); - if PackageOptions.ProxyEnabled then + if Options.ProxyEnabled then begin - FHTTPClient.Proxy.Host:= PackageOptions.ProxyServer; - FHTTPClient.Proxy.Port:= PackageOptions.ProxyPort; - FHTTPClient.Proxy.UserName:= PackageOptions.ProxyUser; - FHTTPClient.Proxy.Password:= PackageOptions.ProxyPassword; + FHTTPClient.Proxy.Host:= Options.ProxyServer; + FHTTPClient.Proxy.Port:= Options.ProxyPort; + FHTTPClient.Proxy.UserName:= Options.ProxyUser; + FHTTPClient.Proxy.Password:= Options.ProxyPassword; end; end; @@ -500,7 +500,7 @@ end; procedure TThreadDownload.DownloadJSON(const ATimeOut: Integer = -1); begin - FRemoteJSONFile := PackageOptions.RemoteRepository + cRemoteJSONFile; + FRemoteJSONFile := Options.RemoteRepository + cRemoteJSONFile; FDownloadType := dtJSON; FTimer := TThreadTimer.Create; FTimer.Interval := ATimeOut; @@ -557,12 +557,12 @@ begin try URL := FixProtocol(AURL); HttpClient := TFPHTTPClient.Create(nil); - if PackageOptions.ProxyEnabled then + if Options.ProxyEnabled then begin - HTTPClient.Proxy.Host:= PackageOptions.ProxyServer; - HTTPClient.Proxy.Port:= PackageOptions.ProxyPort; - HTTPClient.Proxy.UserName:= PackageOptions.ProxyUser; - HTTPClient.Proxy.Password:= PackageOptions.ProxyPassword; + HTTPClient.Proxy.Host:= Options.ProxyServer; + HTTPClient.Proxy.Port:= Options.ProxyPort; + HTTPClient.Proxy.UserName:= Options.ProxyUser; + HTTPClient.Proxy.Password:= Options.ProxyPassword; end; try diff --git a/components/onlinepackagemanager/opkman_mainfrm.pas b/components/onlinepackagemanager/opkman_mainfrm.pas index 4e036d4382..dfed2e6d3e 100644 --- a/components/onlinepackagemanager/opkman_mainfrm.pas +++ b/components/onlinepackagemanager/opkman_mainfrm.pas @@ -132,12 +132,12 @@ uses opkman_serializablepackages, opkman_visualtree, opkman_const, opkman_common procedure TMainFrm.FormCreate(Sender: TObject); begin InitLocalRepository; - PackageOptions := TPackageOptions.Create(LocalRepositoryConfigFile); + Options := TOptions.Create(LocalRepositoryConfigFile); VisualTree := TVisualTree.Create(pnMain, imTree, pmTree); VisualTree.OnChecking := @DoOnChecking; VisualTree.OnChecked := @DoOnChecked; SerializablePackages := TSerializablePackages.Create; - PackageDownloader := TPackageDownloader.Create(PackageOptions.RemoteRepository); + PackageDownloader := TPackageDownloader.Create(Options.RemoteRepository); PackageDownloader.OnJSONProgress := @DoOnJSONProgress; PackageDownloader.OnJSONDownloadCompleted := @DoOnJSONDownloadCompleted; InstallPackageList := TObjectList.Create(True); @@ -150,7 +150,7 @@ begin PackageDownloader.Free; SerializablePackages.Free; VisualTree.Free; - PackageOptions.Free; + Options.Free; InstallPackageList.Free; Application.HintHidePause := FHintTimeOut; end; @@ -312,18 +312,10 @@ procedure TMainFrm.ShowOptions; begin OptionsFrm := TOptionsFrm.Create(MainFrm); try - OptionsFrm.Caption := rsOptionsFrmCaption; - OptionsFrm.edRemoteRepository.Text := PackageOptions.RemoteRepository; - OptionsFrm.cbProxy.Checked := PackageOptions.ProxyEnabled; - OptionsFrm.gbProxySettings.Enabled := PackageOptions.ProxyEnabled; - OptionsFrm.edProxyServer.Text := PackageOptions.ProxyServer; - OptionsFrm.seProxyPort.Value := PackageOptions.ProxyPort; - OptionsFrm.edProxyUser.Text := PackageOptions.ProxyUser; - OptionsFrm.edProxyPassword.Text := PackageOptions.ProxyPassword; - + OptionsFrm.SetupControls; if OptionsFrm.ShowModal = mrOk then begin - tbRefresh.Enabled := PackageOptions.RemoteRepository <> ''; + tbRefresh.Enabled := Options.RemoteRepository <> ''; GetPackageList; end; finally @@ -344,7 +336,7 @@ begin VisualTree.VST.Enabled := (AEnable) and (SerializablePackages.Count > 0); if edFilter.CanFocus then edFilter.SetFocus; - tbRefresh.Enabled := (AEnable) and (Trim(PackageOptions.RemoteRepository) <> ''); + tbRefresh.Enabled := (AEnable) and (Trim(Options.RemoteRepository) <> ''); tbDownload.Enabled := (AEnable) and (SerializablePackages.Count > 0) and (VisualTree.VST.CheckedCount > 0); tbInstall.Enabled := (AEnable) and (SerializablePackages.Count > 0) and (VisualTree.VST.CheckedCount > 0); tbUpdate.Enabled := (AEnable) and (SerializablePackages.Count > 0) and (VisualTree.VST.CheckedCount > 0); @@ -517,7 +509,7 @@ begin if not IsSomethingChecked then Exit; - SDD.InitialDir := PackageOptions.LastDownloadDir; + SDD.InitialDir := Options.LastDownloadDir; if SDD.Execute then begin CanGo := True; @@ -540,8 +532,8 @@ begin if CanGo then begin - PackageOptions.LastDownloadDir := DstDir; - PackageOptions.Changed := True; + Options.LastDownloadDir := DstDir; + Options.Changed := True; PackageAction := paDownloadTo; DoExtract := False; if Download(DstDir, DoExtract) = mrOK then @@ -597,7 +589,7 @@ begin if SerializablePackages.DownloadCount > 0 then begin DoExtract := True; - CanGo := UpdateP(LocalRepositoryUpdate, DoExtract) = mrOK; + CanGo := UpdateP(Options.LocalRepositoryUpdate, DoExtract) = mrOK; VisualTree.UpdatePackageStates; end; @@ -606,7 +598,7 @@ begin if SerializablePackages.ExtractCount > 0 then begin DoOpen := False; - CanGo := Extract(LocalRepositoryUpdate, LocalRepositoryPackages, DoOpen, True) = mrOk; + CanGo := Extract(Options.LocalRepositoryUpdate, Options.LocalRepositoryPackages, DoOpen, True) = mrOk; VisualTree.UpdatePackageStates; end; @@ -669,7 +661,7 @@ begin if SerializablePackages.DownloadCount > 0 then begin DoExtract := True; - CanGo := Download(LocalRepositoryArchive, DoExtract) = mrOK; + CanGo := Download(Options.LocalRepositoryArchive, DoExtract) = mrOK; VisualTree.UpdatePackageStates; end; @@ -678,7 +670,7 @@ begin if SerializablePackages.ExtractCount > 0 then begin DoOpen := False; - CanGo := Extract(LocalRepositoryArchive, LocalRepositoryPackages, DoOpen) = mrOk; + CanGo := Extract(Options.LocalRepositoryArchive, Options.LocalRepositoryPackages, DoOpen) = mrOk; VisualTree.UpdatePackageStates; end; diff --git a/components/onlinepackagemanager/opkman_options.pas b/components/onlinepackagemanager/opkman_options.pas index 0906237cce..dd746be80d 100644 --- a/components/onlinepackagemanager/opkman_options.pas +++ b/components/onlinepackagemanager/opkman_options.pas @@ -27,28 +27,32 @@ interface Author: Balázs Székely } uses - Classes, SysUtils, Laz2_XMLCfg, LazFileUtils; + Classes, SysUtils, LazIDEIntf, Laz2_XMLCfg, LazFileUtils; type - { TPackageOptions } - RProxySettings = record - Enabled: boolean; - Server: string; - Port: Word; - User: string; - Password: string; + { TOptions } + TProxySettings = record + FEnabled: boolean; + FServer: string; + FPort: Word; + FUser: string; + FPassword: string; end; - TPackageOptions = class + TOptions = class private - FProxySettings: RProxySettings; + FProxySettings: TProxySettings; FXML: TXMLConfig; FRemoteRepository: String; FChanged: Boolean; FLastDownloadDir: String; FLastPackageDirSrc: String; FLastPackageDirDst: String; - procedure LoadDefault; + FRestrictedExtensions: String; + FRestrictedDirectories: String; + FLocalRepositoryPackages: String; + FLocalRepositoryArchive: String; + FLocalRepositoryUpdate: String; procedure SetRemoteRepository(const ARemoteRepository: String); public constructor Create(const AFileName: String); @@ -56,27 +60,34 @@ type public procedure Save; procedure Load; + procedure LoadDefault; published property Changed: Boolean read FChanged write FChanged; property LastDownloadDir: String read FLastDownloadDir write FLastDownloadDir; property LastPackagedirSrc: String read FLastPackageDirSrc write FLastPackageDirSrc; property LastPackagedirDst: String read FLastPackageDirDst write FLastPackageDirDst; property RemoteRepository: string read FRemoteRepository write SetRemoteRepository; - property ProxyEnabled: Boolean read FProxySettings.Enabled write FProxySettings.Enabled; - property ProxyServer: String read FProxySettings.Server write FProxySettings.Server; - property ProxyPort: Word read FProxySettings.Port write FProxySettings.Port; - property ProxyUser: String read FProxySettings.User write FProxySettings.User; - property ProxyPassword: String read FProxySettings.Password write FProxySettings.Password; + property ProxyEnabled: Boolean read FProxySettings.FEnabled write FProxySettings.FEnabled; + property ProxyServer: String read FProxySettings.FServer write FProxySettings.FServer; + property ProxyPort: Word read FProxySettings.FPort write FProxySettings.FPort; + property ProxyUser: String read FProxySettings.FUser write FProxySettings.FUser; + property ProxyPassword: String read FProxySettings.FPassword write FProxySettings.FPassword; + property RestrictedExtension: String read FRestrictedExtensions write FRestrictedExtensions; + property RestrictedDirectories: String read FRestrictedDirectories write FRestrictedDirectories; + property LocalRepositoryPackages: String read FLocalRepositoryPackages write FLocalRepositoryPackages; + property LocalRepositoryArchive: String read FLocalRepositoryArchive write FLocalRepositoryArchive; + property LocalRepositoryUpdate: String read FLocalRepositoryUpdate write FLocalRepositoryUpdate; end; var - PackageOptions: TPackageOptions = nil; + Options: TOptions = nil; implementation +uses opkman_const; -{ TPackageOptions } +{ TOptions } -constructor TPackageOptions.Create(const AFileName: String); +constructor TOptions.Create(const AFileName: String); begin FXML := TXMLConfig.Create(AFileName); if FileExists(AFileName) then @@ -85,7 +96,7 @@ begin LoadDefault; end; -destructor TPackageOptions.Destroy; +destructor TOptions.Destroy; begin if FChanged then Save; @@ -93,43 +104,74 @@ begin inherited Destroy; end; -procedure TPackageOptions.Load; +procedure TOptions.Load; begin - FRemoteRepository := FXML.GetValue('RemoteRepository/Value', ''); - FLastDownloadDir := FXML.GetValue('LastDownloadDir/Value', ''); - FLastPackageDirSrc := FXML.GetValue('LastPackageDirSrc/Value', ''); - FLastPackageDirDst := FXML.GetValue('LastPackageDirDst/Value', ''); - FProxySettings.Enabled := FXML.GetValue('Proxy/Enabled/Value', false); - FProxySettings.Server := FXML.GetValue('Proxy/Server/Value', ''); - FProxySettings.Port := FXML.GetValue('Proxy/Port/Value', 0); - FProxySettings.User := FXML.GetValue('Proxy/User/Value', ''); - FProxySettings.Password := FXML.GetValue('Proxy/Password/Value', ''); + FRemoteRepository := FXML.GetValue('General/RemoteRepository/Value', ''); + FLastDownloadDir := FXML.GetValue('General/LastDownloadDir/Value', ''); + FLastPackageDirSrc := FXML.GetValue('General/LastPackageDirSrc/Value', ''); + FLastPackageDirDst := FXML.GetValue('GeneralLastPackageDirDst/Value', ''); + + FProxySettings.FEnabled := FXML.GetValue('Proxy/Enabled/Value', False); + FProxySettings.FServer := FXML.GetValue('Proxy/Server/Value', ''); + FProxySettings.FPort := FXML.GetValue('Proxy/Port/Value', 0); + FProxySettings.FUser := FXML.GetValue('Proxy/User/Value', ''); + FProxySettings.FPassword := FXML.GetValue('Proxy/Password/Value', ''); + + FLocalRepositoryPackages := FXML.GetValue('Folders/LocalRepositoryPackages/Value', ''); + FLocalRepositoryArchive := FXML.GetValue('Folders/LocalRepositoryArchive/Value', ''); + FLocalRepositoryUpdate := FXML.GetValue('Folders/LocalRepositoryUpdate/Value', ''); end; -procedure TPackageOptions.Save; +procedure TOptions.Save; begin - FXML.SetDeleteValue('RemoteRepository/Value', FRemoteRepository, ''); - FXML.SetDeleteValue('LastDownloadDir/Value', FLastDownloadDir, ''); - FXML.SetDeleteValue('LastPackageDirSrc/Value', FLastPackageDirSrc, ''); + FXML.SetDeleteValue('General/RemoteRepository/Value', FRemoteRepository, ''); + FXML.SetDeleteValue('General/LastDownloadDir/Value', FLastDownloadDir, ''); + FXML.SetDeleteValue('General/LastPackageDirSrc/Value', FLastPackageDirSrc, ''); FXML.SetDeleteValue('LastPackageDirDst/Value', FLastPackageDirDst, ''); - FXML.SetDeleteValue('Proxy/Enabled/Value', FProxySettings.Enabled, false); - FXML.SetDeleteValue('Proxy/Server/Value', FProxySettings.Server, ''); - FXML.SetDeleteValue('Proxy/Port/Value', FProxySettings.Port, 0); - FXML.SetDeleteValue('Proxy/User/Value', FProxySettings.User, ''); - FXML.SetDeleteValue('Proxy/Password/Value', FProxySettings.Password, ''); + FXML.SetDeleteValue('Proxy/Enabled/Value', FProxySettings.FEnabled, false); + FXML.SetDeleteValue('Proxy/Server/Value', FProxySettings.FServer, ''); + FXML.SetDeleteValue('Proxy/Port/Value', FProxySettings.FPort, 0); + FXML.SetDeleteValue('Proxy/User/Value', FProxySettings.FUser, ''); + FXML.SetDeleteValue('Proxy/Password/Value', FProxySettings.FPassword, ''); + + FXML.SetDeleteValue('Folders/LocalRepositoryPackages/Value', FLocalRepositoryPackages, ''); + FXML.SetDeleteValue('Folders/LocalRepositoryArchive/Value', FLocalRepositoryArchive, ''); + FXML.SetDeleteValue('Folders/LocalRepositoryUpdate/Value', FLocalRepositoryUpdate, ''); FXML.Flush; FChanged := False; end; -procedure TPackageOptions.LoadDefault; +procedure TOptions.LoadDefault; +var + LocalRepository: String; begin FRemoteRepository := 'http://packages.lazarus-ide.org/'; + + FProxySettings.FEnabled := False; + FProxySettings.FServer := ''; + FProxySettings.FPort := 0; + FProxySettings.FUser := ''; + FProxySettings.FPassword := ''; + + LocalRepository := AppendPathDelim(AppendPathDelim(LazarusIDE.GetPrimaryConfigPath) + cLocalRepository); + FLocalRepositoryPackages := LocalRepository + AppendPathDelim(cLocalRepositoryPackages); + if not DirectoryExists(FLocalRepositoryPackages) then + CreateDir(FLocalRepositoryPackages); + FLocalRepositoryArchive := LocalRepository + AppendPathDelim(cLocalRepositoryArchive); + if not DirectoryExistsUTF8(FLocalRepositoryArchive) then + CreateDirUTF8(FLocalRepositoryArchive); + FLocalRepositoryUpdate := LocalRepository + AppendPathDelim(cLocalRepositoryUpdate); + if not DirectoryExists(FLocalRepositoryUpdate) then + CreateDir(FLocalRepositoryUpdate); + + FRestrictedExtensions := '*.a,*.o,*.ppu,*.compiled,*.bak,*.or,*.rsj,*.~ '; + FRestrictedDirectories := 'lib,backup'; Save; end; -procedure TPackageOptions.SetRemoteRepository(const ARemoteRepository: String); +procedure TOptions.SetRemoteRepository(const ARemoteRepository: String); begin if FRemoteRepository <> ARemoteRepository then begin diff --git a/components/onlinepackagemanager/opkman_optionsfrm.lfm b/components/onlinepackagemanager/opkman_optionsfrm.lfm index 8290147139..abd957e217 100644 --- a/components/onlinepackagemanager/opkman_optionsfrm.lfm +++ b/components/onlinepackagemanager/opkman_optionsfrm.lfm @@ -1,48 +1,32 @@ object OptionsFrm: TOptionsFrm Left = 611 - Height = 296 + Height = 300 Top = 304 - Width = 493 - ActiveControl = edRemoteRepository + Width = 450 BorderIcons = [biSystemMenu] - BorderStyle = bsSingle Caption = 'Options' - ClientHeight = 296 - ClientWidth = 493 + ClientHeight = 300 + ClientWidth = 450 + Color = clBtnFace + Constraints.MinHeight = 300 + Constraints.MinWidth = 450 PopupMode = pmExplicit Position = poOwnerFormCenter - Visible = False - object Label1: TLabel - Left = 16 - Height = 15 - Top = 16 - Width = 100 - Caption = 'Remote repository:' - ParentColor = False - end - object edRemoteRepository: TEdit - Left = 16 - Height = 23 - Top = 33 - Width = 452 - OnKeyPress = edRemoteRepositoryKeyPress - TabOrder = 0 - Text = 'http://localhost/packages/' - end + LCLVersion = '1.7' object pnBottom: TPanel Left = 0 Height = 39 - Top = 257 - Width = 493 + Top = 261 + Width = 450 Align = alBottom BevelOuter = bvNone ClientHeight = 39 - ClientWidth = 493 - TabOrder = 1 + ClientWidth = 450 + TabOrder = 0 object bOk: TButton - Left = 300 + Left = 257 Height = 25 - Top = 9 + Top = 8 Width = 88 Anchors = [akTop, akRight] Caption = 'OK' @@ -50,7 +34,7 @@ object OptionsFrm: TOptionsFrm TabOrder = 0 end object bCancel: TButton - Left = 393 + Left = 350 Height = 25 Top = 8 Width = 88 @@ -59,102 +43,327 @@ object OptionsFrm: TOptionsFrm ModalResult = 2 TabOrder = 1 end - object bSettings: TButton - Left = -299 - Height = 25 - Top = 10 - Width = 152 - Anchors = [akTop, akRight] - Caption = 'Settings' - TabOrder = 2 - end - end - object cbProxy: TCheckBox - Left = 16 - Height = 19 - Top = 80 - Width = 71 - Caption = 'Use Proxy' - OnChange = cbProxyChange - TabOrder = 2 - end - object gbProxySettings: TGroupBox - Left = 16 - Height = 127 - Top = 112 - Width = 416 - Caption = 'Proxy Settings' - ClientHeight = 107 - ClientWidth = 412 - TabOrder = 3 - object edProxyServer: TEdit + object bRestore: TButton Left = 8 - Height = 23 - Top = 17 - Width = 184 - OnKeyPress = edRemoteRepositoryKeyPress - TabOrder = 0 - Text = 'http://localhost/packages/' - end - object Label2: TLabel - Left = 12 - Height = 15 - Top = 0 - Width = 32 - Caption = 'Server' - ParentColor = False - end - object Label3: TLabel - Left = 12 - Height = 15 - Top = 48 - Width = 53 - Caption = 'Username' - ParentColor = False - end - object edProxyUser: TEdit - Left = 12 - Height = 23 - Top = 65 - Width = 184 - OnKeyPress = edRemoteRepositoryKeyPress - TabOrder = 1 - Text = 'username' - end - object Label4: TLabel - Left = 212 - Height = 15 - Top = 0 - Width = 22 - Caption = 'Port' - ParentColor = False - end - object Label5: TLabel - Left = 212 - Height = 15 - Top = 48 - Width = 50 - Caption = 'Password' - ParentColor = False - end - object edProxyPassword: TEdit - Left = 208 - Height = 23 - Top = 65 - Width = 184 - EchoMode = emPassword - OnKeyPress = edRemoteRepositoryKeyPress - PasswordChar = '*' + Height = 25 + Top = 8 + Width = 100 + Caption = 'Restore defaults' + OnClick = bRestoreClick TabOrder = 2 - Text = 'password' end - object seProxyPort: TSpinEdit - Left = 212 - Height = 23 - Top = 17 - Width = 76 - MaxValue = 65535 - TabOrder = 3 + end + object pgOptions: TPageControl + Left = 0 + Height = 261 + Top = 0 + Width = 450 + ActivePage = tsGeneral + Align = alClient + TabIndex = 0 + TabOrder = 1 + object tsGeneral: TTabSheet + Caption = 'General' + ClientHeight = 233 + ClientWidth = 442 + object pnGeneral: TPanel + Left = 0 + Height = 233 + Top = 0 + Width = 442 + Align = alClient + BevelOuter = bvNone + ClientHeight = 233 + ClientWidth = 442 + Color = clBtnFace + ParentColor = False + TabOrder = 0 + object lbRemoteRepository: TLabel + Left = 15 + Height = 15 + Top = 15 + Width = 100 + Caption = 'Remote repository:' + ParentColor = False + end + object edRemoteRepository: TEdit + Left = 15 + Height = 23 + Top = 32 + Width = 408 + Anchors = [akTop, akLeft, akRight] + OnKeyPress = edRemoteRepositoryKeyPress + TabOrder = 0 + Text = 'http://localhost/packages/' + end + end end + object tsProxy: TTabSheet + Caption = 'Proxy' + ClientHeight = 233 + ClientWidth = 442 + object pnProxy: TPanel + Left = 0 + Height = 233 + Top = 0 + Width = 442 + Align = alClient + BevelOuter = bvNone + ClientHeight = 233 + ClientWidth = 442 + Color = clBtnFace + ParentColor = False + TabOrder = 0 + object cbProxy: TCheckBox + Left = 15 + Height = 19 + Top = 15 + Width = 71 + Caption = 'Use Proxy' + OnChange = cbProxyChange + TabOrder = 0 + end + object gbProxySettings: TGroupBox + Left = 15 + Height = 130 + Top = 48 + Width = 411 + Caption = 'Proxy Settings' + ClientHeight = 110 + ClientWidth = 407 + TabOrder = 1 + object edProxyServer: TEdit + Left = 8 + Height = 23 + Top = 17 + Width = 296 + OnKeyPress = edRemoteRepositoryKeyPress + TabOrder = 0 + Text = 'http://localhost/packages/' + end + object lbServer: TLabel + Left = 8 + Height = 15 + Top = 0 + Width = 32 + Caption = 'Server' + ParentColor = False + end + object lbUserName: TLabel + Left = 8 + Height = 15 + Top = 48 + Width = 53 + Caption = 'Username' + ParentColor = False + end + object edProxyUser: TEdit + Left = 8 + Height = 23 + Top = 65 + Width = 186 + OnKeyPress = edRemoteRepositoryKeyPress + TabOrder = 1 + Text = 'username' + end + object lbPort: TLabel + Left = 318 + Height = 15 + Top = 0 + Width = 22 + Caption = 'Port' + ParentColor = False + end + object lbPassword: TLabel + Left = 208 + Height = 15 + Top = 48 + Width = 50 + Caption = 'Password' + ParentColor = False + end + object edProxyPassword: TEdit + Left = 208 + Height = 23 + Top = 64 + Width = 186 + EchoMode = emPassword + OnKeyPress = edRemoteRepositoryKeyPress + PasswordChar = '*' + TabOrder = 2 + Text = 'password' + end + object seProxyPort: TSpinEdit + Left = 318 + Height = 23 + Top = 16 + Width = 76 + MaxValue = 65535 + TabOrder = 3 + end + end + end + end + object tsFolders: TTabSheet + Caption = 'Folders' + ClientHeight = 233 + ClientWidth = 442 + object pnFolders: TPanel + Left = 0 + Height = 233 + Top = 0 + Width = 442 + Align = alClient + BevelOuter = bvNone + ClientHeight = 233 + ClientWidth = 442 + Color = clBtnFace + ParentColor = False + TabOrder = 0 + object pnLocalRepositoryPackages: TPanel + Left = 15 + Height = 23 + Top = 32 + Width = 413 + Anchors = [akTop, akLeft, akRight] + AutoSize = True + BevelOuter = bvNone + ClientHeight = 23 + ClientWidth = 413 + TabOrder = 0 + object edLocalRepositoryPackages: TEdit + Left = 0 + Height = 23 + Top = 0 + Width = 383 + Align = alClient + ParentShowHint = False + ShowHint = True + TabOrder = 0 + end + object bLocalRepositoryPackages: TSpeedButton + Left = 383 + Height = 23 + Top = 0 + Width = 30 + Align = alRight + Caption = '...' + OnClick = bLocalRepositoryPackagesClick + end + end + object lbLocalRepositoryPackages: TLabel + Left = 15 + Height = 15 + Top = 15 + Width = 84 + Caption = 'Local repository' + ParentColor = False + ParentShowHint = False + end + object pnLocalRepositoryArchive: TPanel + Left = 15 + Height = 23 + Top = 87 + Width = 413 + Anchors = [akTop, akLeft, akRight] + AutoSize = True + BevelOuter = bvNone + ClientHeight = 23 + ClientWidth = 413 + TabOrder = 1 + object edLocalRepositoryArchive: TEdit + Left = 0 + Height = 23 + Top = 0 + Width = 383 + Align = alClient + ParentShowHint = False + ShowHint = True + TabOrder = 0 + end + object bLocalRepositoryArchive: TSpeedButton + Tag = 1 + Left = 383 + Height = 23 + Top = 0 + Width = 30 + Align = alRight + Caption = '...' + OnClick = bLocalRepositoryPackagesClick + end + end + object lbLocalRepositoryArchive: TLabel + Left = 15 + Height = 15 + Top = 69 + Width = 125 + Caption = 'Local repository archive' + ParentColor = False + ParentShowHint = False + end + object pnLocalRepositoryUpdate: TPanel + Left = 15 + Height = 23 + Top = 145 + Width = 413 + Anchors = [akTop, akLeft, akRight] + AutoSize = True + BevelOuter = bvNone + ClientHeight = 23 + ClientWidth = 413 + TabOrder = 2 + object edLocalRepositoryUpdate: TEdit + Left = 0 + Height = 23 + Top = 0 + Width = 383 + Align = alClient + ParentShowHint = False + ShowHint = True + TabOrder = 0 + end + object bLocalRepositoryUpdate: TSpeedButton + Tag = 2 + Left = 383 + Height = 23 + Top = 0 + Width = 30 + Align = alRight + Caption = '...' + OnClick = bLocalRepositoryPackagesClick + end + end + object lbLocalRepositoryUpdate: TLabel + Left = 15 + Height = 15 + Top = 128 + Width = 124 + Caption = 'Local repository update' + ParentColor = False + ParentShowHint = False + end + end + end + object tsExtensions: TTabSheet + Caption = 'Extensions' + ClientHeight = 233 + ClientWidth = 442 + TabVisible = False + object pnExtensions: TPanel + Left = 0 + Height = 233 + Top = 0 + Width = 442 + Align = alClient + BevelOuter = bvNone + Color = clBtnFace + ParentColor = False + TabOrder = 0 + end + end + end + object SDD: TSelectDirectoryDialog + left = 200 + top = 80 end end diff --git a/components/onlinepackagemanager/opkman_optionsfrm.pas b/components/onlinepackagemanager/opkman_optionsfrm.pas index 48d543280e..5aa45409f5 100644 --- a/components/onlinepackagemanager/opkman_optionsfrm.pas +++ b/components/onlinepackagemanager/opkman_optionsfrm.pas @@ -31,7 +31,7 @@ interface uses Classes, SysUtils, FileUtil, opkman_VirtualTrees, Forms, Controls, Graphics, Dialogs, - StdCtrls, ExtCtrls, Spin; + StdCtrls, ExtCtrls, Spin, ComCtrls, Buttons, LazFileUtils; type @@ -39,28 +39,51 @@ type TOptionsFrm = class(TForm) bCancel: TButton; + bLocalRepositoryArchive: TSpeedButton; + bLocalRepositoryUpdate: TSpeedButton; bOk: TButton; - bSettings: TButton; + bLocalRepositoryPackages: TSpeedButton; + bRestore: TButton; cbProxy: TCheckBox; + edLocalRepositoryPackages: TEdit; + edLocalRepositoryArchive: TEdit; + edLocalRepositoryUpdate: TEdit; + edProxyPassword: TEdit; edProxyServer: TEdit; edProxyUser: TEdit; - edProxyPassword: TEdit; edRemoteRepository: TEdit; gbProxySettings: TGroupBox; - Label1: TLabel; - Label2: TLabel; - Label3: TLabel; - Label4: TLabel; - Label5: TLabel; + lbLocalRepositoryArchive: TLabel; + lbLocalRepositoryUpdate: TLabel; + lbRemoteRepository: TLabel; + lbServer: TLabel; + lbLocalRepositoryPackages: TLabel; + lbUserName: TLabel; + lbPort: TLabel; + lbPassword: TLabel; + pnExtensions: TPanel; + pnFolders: TPanel; + pnLocalRepositoryPackages: TPanel; + pnLocalRepositoryArchive: TPanel; + pnLocalRepositoryUpdate: TPanel; + pnProxy: TPanel; + pnGeneral: TPanel; + pgOptions: TPageControl; pnBottom: TPanel; + SDD: TSelectDirectoryDialog; seProxyPort: TSpinEdit; + tsFolders: TTabSheet; + tsExtensions: TTabSheet; + tsGeneral: TTabSheet; + tsProxy: TTabSheet; + procedure bLocalRepositoryPackagesClick(Sender: TObject); procedure bOkClick(Sender: TObject); + procedure bRestoreClick(Sender: TObject); procedure cbProxyChange(Sender: TObject); procedure edRemoteRepositoryKeyPress(Sender: TObject; var Key: char); private - public - + procedure SetupControls; end; var @@ -76,7 +99,7 @@ procedure TOptionsFrm.bOkClick(Sender: TObject); begin if Trim(edRemoteRepository.Text) = '' then begin - MessageDlgEx(rsOptionedRemoteRepository, mtInformation, [mbOk], Self); + MessageDlgEx(rsOptions_RemoteRepository_Information, mtInformation, [mbOk], Self); edRemoteRepository.SetFocus; Exit; end; @@ -85,38 +108,111 @@ begin begin if Trim(edProxyServer.Text) = '' then begin - MessageDlgEx(rsOptionedProxyServer, mtInformation, [mbOk], Self); + MessageDlgEx(rsOptions_ProxyServer_Information, mtInformation, [mbOk], Self); edProxyServer.SetFocus; Exit; end; if seProxyPort.Value = 0 then begin - MessageDlgEx(rsOptionedProxyPort, mtInformation, [mbOk], Self); + MessageDlgEx(rsOptions_ProxyPort_Information, mtInformation, [mbOk], Self); seProxyPort.SetFocus; Exit; end; end; - PackageOptions.RemoteRepository := edRemoteRepository.Text; - PackageOptions.ProxyEnabled := cbProxy.Checked; - PackageOptions.ProxyServer := edProxyServer.Text; - PackageOptions.ProxyPort := seProxyPort.Value; - PackageOptions.ProxyUser := edProxyUser.Text; - PackageOptions.ProxyPassword := edProxyPassword.Text; - PackageOptions.Save; + if Trim(edLocalRepositoryPackages.Text) = '' then + begin + MessageDlgEx(rsOptions_InvalidDirectory_Information, mtInformation, [mbOk], Self); + edLocalRepositoryPackages.SetFocus; + Exit; + end; + if Trim(edLocalRepositoryArchive.Text) = '' then + begin + MessageDlgEx(rsOptions_InvalidDirectory_Information, mtInformation, [mbOk], Self); + edLocalRepositoryArchive.SetFocus; + Exit; + end; + if Trim(edLocalRepositoryUpdate.Text) = '' then + begin + MessageDlgEx(rsOptions_InvalidDirectory_Information, mtInformation, [mbOk], Self); + edLocalRepositoryUpdate.SetFocus; + Exit; + end; + Options.RemoteRepository := edRemoteRepository.Text; + Options.ProxyEnabled := cbProxy.Checked; + Options.ProxyServer := edProxyServer.Text; + Options.ProxyPort := seProxyPort.Value; + Options.ProxyUser := edProxyUser.Text; + Options.ProxyPassword := edProxyPassword.Text; + Options.LocalRepositoryPackages := AppendPathDelim(edLocalRepositoryPackages.Text); + Options.LocalRepositoryArchive := AppendPathDelim(edLocalRepositoryArchive.Text); + Options.LocalRepositoryUpdate := AppendPathDelim(edLocalRepositoryUpdate.Text); + + Options.Save; ModalResult := mrOk; end; +procedure TOptionsFrm.bRestoreClick(Sender: TObject); +begin + if MessageDlgEx(rsOptions_RestoreDefaults_Confirmation, mtInformation, [mbYes, mbNo], Self) = mrYes then + begin + Options.LoadDefault; + SetupControls; + end; +end; + procedure TOptionsFrm.cbProxyChange(Sender: TObject); begin gbProxySettings.Enabled:= cbProxy.Checked; end; +procedure TOptionsFrm.bLocalRepositoryPackagesClick(Sender: TObject); +begin + if SDD.Execute then + case (Sender as TSpeedButton).Tag of + 0: edLocalRepositoryPackages.Text := SDD.FileName; + 1: edLocalRepositoryArchive.Text := SDD.FileName; + 2: edLocalRepositoryUpdate.Text := SDD.FileName; + end; +end; + procedure TOptionsFrm.edRemoteRepositoryKeyPress(Sender: TObject; var Key: char); begin if Key = #13 then bOkClick(bOk); end; +procedure TOptionsFrm.SetupControls; +begin + pgOptions.ActivePageIndex := 0; + Caption := rsOptions_FrmCaption; + + lbRemoteRepository.Caption := rsOptions_lbRemoteRepository_Caption; + edRemoteRepository.Text := Options.RemoteRepository; + + cbProxy.Caption := rsOptions_cbProxy_Caption; + gbProxySettings.Caption := rsOptions_gbProxySettings_Caption; + lbServer.Caption := rsOptions_lbServer_Caption; + lbPort.Caption := rsOptions_lbPort_Caption; + lbUserName.Caption := rsOptions_lbUsername_Caption; + lbPassword.Caption := rsOptions_lbPassword_Caption; + cbProxy.Checked := Options.ProxyEnabled; + gbProxySettings.Enabled := Options.ProxyEnabled; + edProxyServer.Text := Options.ProxyServer; + seProxyPort.Value := Options.ProxyPort; + edProxyUser.Text := Options.ProxyUser; + edProxyPassword.Text := Options.ProxyPassword; + + lbLocalRepositoryPackages.Caption := rsOptions_lbLocalRepositoryPackages_Caption; + edLocalRepositoryPackages.Hint := rsOptions_edLocalRepositoryPackages_Hint; + lbLocalRepositoryArchive.Caption := rsOptions_lbLocalRepositoryArchive_Caption; + edLocalRepositoryArchive.Hint := rsOptions_edLocalRepositoryArchive_Hint; + lbLocalRepositoryUpdate.Caption := rsOptions_lbLocalRepositoryUpdate_Caption; + edLocalRepositoryUpdate.Hint := rsOptions_edLocalRepositoryUpdate_Hint; + edLocalRepositoryPackages.Text := Options.LocalRepositoryPackages; + edLocalRepositoryArchive.Text := Options.LocalRepositoryArchive; + edLocalRepositoryUpdate.Text := Options.LocalRepositoryUpdate; +end; + end. diff --git a/components/onlinepackagemanager/opkman_serializablepackages.pas b/components/onlinepackagemanager/opkman_serializablepackages.pas index 888d9fc431..62bf1f017c 100644 --- a/components/onlinepackagemanager/opkman_serializablepackages.pas +++ b/components/onlinepackagemanager/opkman_serializablepackages.pas @@ -285,7 +285,7 @@ var implementation -uses opkman_common, opkman_const; +uses opkman_common, opkman_const, opkman_options; { TPackageVersion } @@ -986,7 +986,7 @@ function TSerializablePackages.IsPackageDownloaded(const APackage: TPackage): Bo var FileName: String; begin - FileName := LocalRepositoryArchive + APackage.RepositoryFileName; + FileName := Options.LocalRepositoryArchive + APackage.RepositoryFileName; Result := (FileExists(FileName)) and (MD5Print(MD5File(FileName)) = APackage.RepositoryFileHash) and (FileUtil.FileSize(FileName) = APackage.RepositoryFileSize); @@ -1001,7 +1001,7 @@ begin for I := 0 to APackage.FPackageFiles.Count - 1 do begin PackageFile := TPackageFile(APackage.FPackageFiles.Items[I]); - PackageFile.FPackageAbsolutePath := LocalRepositoryPackages + APackage.PackageBaseDir + PackageFile.FPackageRelativePath + PackageFile.Name; + PackageFile.FPackageAbsolutePath := Options.LocalRepositoryPackages + APackage.PackageBaseDir + PackageFile.FPackageRelativePath + PackageFile.Name; if not FileExists(PackageFile.FPackageAbsolutePath) then begin Result := False; @@ -1046,10 +1046,10 @@ begin begin FileName := StringReplace(APackageFile.Name, '.lpk', '.opkman', [rfIgnoreCase]); Result := (psExtracted in APackageFile.PackageStates) and - FileExists(LocalRepositoryPackages + APackageBaseDir + APackageFile.PackageRelativePath + FileName); + FileExists(Options.LocalRepositoryPackages + APackageBaseDir + APackageFile.PackageRelativePath + FileName); if Result then begin - APackageFile.InstalledFileName := LocalRepositoryPackages + APackageFile.FPackageRelativePath + APackageFile.Name; + APackageFile.InstalledFileName := Options.LocalRepositoryPackages + APackageFile.FPackageRelativePath + APackageFile.Name; APackageFile.InstalledFileVersion := APackageFile.VersionAsString; Result := True; end @@ -1237,7 +1237,7 @@ begin (PackageFile.PackageType in [ptRunTime, ptRunTimeOnly]) then begin FileName := StringReplace(PackageFile.Name, '.lpk', '.opkman', [rfIgnoreCase]); - FileCreate(LocalRepositoryPackages + Items[I].PackageBaseDir + PackageFile.PackageRelativePath + FileName); + FileCreate(Options.LocalRepositoryPackages + Items[I].PackageBaseDir + PackageFile.PackageRelativePath + FileName); end; end; end; @@ -1270,12 +1270,12 @@ begin begin if IsPackageDownloaded(Items[I]) then begin - if DeleteFile(LocalRepositoryArchive + Items[I].RepositoryFileName) then + if DeleteFile(Options.LocalRepositoryArchive + Items[I].RepositoryFileName) then Inc(Result); end; if IsPackageExtracted(Items[I]) then - if DirectoryExists(LocalRepositoryPackages + Items[I].PackageBaseDir) then - DeleteDirectory(LocalRepositoryPackages + Items[I].PackageBaseDir, False); + if DirectoryExists(Options.LocalRepositoryPackages + Items[I].PackageBaseDir) then + DeleteDirectory(Options.LocalRepositoryPackages + Items[I].PackageBaseDir, False); end; end; end; diff --git a/components/onlinepackagemanager/opkman_visualtree.pas b/components/onlinepackagemanager/opkman_visualtree.pas index cd37c6b2fa..bddca795ec 100644 --- a/components/onlinepackagemanager/opkman_visualtree.pas +++ b/components/onlinepackagemanager/opkman_visualtree.pas @@ -219,7 +219,7 @@ begin //add repository(DataType = 0) RootNode := FVST.AddChild(nil); RootData := FVST.GetNodeData(RootNode); - RootData^.Repository := PackageOptions.RemoteRepository; + RootData^.Repository := Options.RemoteRepository; RootData^.DataType := 0; for I := 0 to SerializablePackages.Count - 1 do begin