Opkman: Begin implementing support for multiple repositories.

git-svn-id: trunk@53956 -
This commit is contained in:
balazs 2017-01-16 14:00:39 +00:00
parent 96ce75a353
commit 91877feb80
12 changed files with 593 additions and 46 deletions

2
.gitattributes vendored
View File

@ -3313,6 +3313,8 @@ components/onlinepackagemanager/opkman_packagelistfrm.lfm svneol=native#text/pla
components/onlinepackagemanager/opkman_packagelistfrm.pas svneol=native#text/pascal
components/onlinepackagemanager/opkman_progressfrm.lfm svneol=native#text/plain
components/onlinepackagemanager/opkman_progressfrm.pas svneol=native#text/pascal
components/onlinepackagemanager/opkman_repositories.lfm -text svneol=native#plain/text
components/onlinepackagemanager/opkman_repositories.pas svneol=native#text/pascal
components/onlinepackagemanager/opkman_serializablepackages.pas svneol=native#text/pascal
components/onlinepackagemanager/opkman_timer.pas svneol=native#text/pascal
components/onlinepackagemanager/opkman_updates.pas svneol=native#text/pascal

View File

@ -20,7 +20,7 @@
<Description Value="Online package manger"/>
<License Value="GPL"/>
<Version Major="1"/>
<Files Count="20">
<Files Count="21">
<Item1>
<Filename Value="onlinepackagemanagerintf.pas"/>
<HasRegisterProc Value="True"/>
@ -107,6 +107,10 @@
<Filename Value="opkman_uploader.pas"/>
<UnitName Value="opkman_uploader"/>
</Item20>
<Item21>
<Filename Value="opkman_repositories.pas"/>
<UnitName Value="opkman_repositories"/>
</Item21>
</Files>
<i18n>
<EnableI18N Value="True"/>

View File

@ -14,7 +14,7 @@ uses
opkman_installer, opkman_packagelistfrm, opkman_options,
opkman_createrepositorypackage, opkman_categoriesfrm,
opkman_packagedetailsfrm, opkman_updates, opkman_createjsonforupdates,
opkman_uploader, LazarusPackageIntf;
opkman_uploader, opkman_repositories, LazarusPackageIntf;
implementation

View File

@ -33,6 +33,7 @@ uses
const
cRemoteRepository = 'http://packages.lazarus-ide.org/';
cRemoteRepositoryTitle = 'Lazarus Central Repository';
cRemoteJSONFile = 'packagelist.json';
cLocalRepository = 'onlinepackagemanager';
cLocalRepositoryPackages = 'packages';
@ -55,6 +56,7 @@ const
cExtractDir = 'ExtractDir';
cSubmitURL_Zip = 'aHR0cDovL2xhemFydXNvcG0uMDAwd2ViaG9zdGFwcC5jb20vemlwLnBocA==';
cSubmitURL_JSON = 'aHR0cDovL2xhemFydXNvcG0uMDAwd2ViaG9zdGFwcC5jb20vanNvbi5waHA=';
cSep = '#@$%^';
resourcestring
//package manager
@ -348,13 +350,25 @@ resourcestring
rsCreateJSONForUpdatesFrm_Message4 = 'JSON for updates successfully created.';
rsCreateJSONForUpdatesFrm_Error1 = 'Cannot create JSON for updates! Error message:';
//categories form
rsCategoriesFrm_Caption = 'List with categories';
rsCategoriesFrm_lbMessage_Caption = 'Please select (check) one or more categories';
rsCategoriesFrm_bYes_Caption = 'OK';
rsCategoriesFrm_bCancel_Caption = 'Cancel';
//repositories
rsRepositories_Caption = 'Repositories';
rsRepositories_VST_HeaderColumn = 'Repository Address';
rsRepositories_bAdd_Caption = 'Add';
rsRepositories_bEdit_Caption = 'Edit';
rsRepositories_bDelete_Caption = 'Delete';
rsRepositories_bOk_Caption = 'OK';
rsRepositories_bCancel_Caption = 'Cancel';
rsRepositories_cbDefault_Caption = 'Set selected item as default repository';
rsRepositories_Confirmation0 = 'Delete selected repository "%s" ?';
rsRepositories_InputBox_Caption0 = 'Add repository';
rsRepositories_InputBox_Caption1 = 'Edit repository';
rsRepositories_InputBox_Text = 'Type the repository name:';
implementation

View File

@ -345,7 +345,7 @@ begin
if SerializablePackages.Items[I].IsDownloadable then
begin
Inc(FCnt);
FFrom := Options.RemoteRepository + SerializablePackages.Items[I].RepositoryFileName;
FFrom := Options.RemoteRepository[Options.ActiveRepositoryIndex] + SerializablePackages.Items[I].RepositoryFileName;
FTo := FDownloadTo + SerializablePackages.Items[I].RepositoryFileName;
FCurSize := SerializablePackages.Items[I].RepositoryFileSize;
DS := TDownloadStream.Create(TFileStream.Create(FTo, fmCreate));
@ -499,7 +499,7 @@ end;
procedure TThreadDownload.DownloadJSON(const ATimeOut: Integer = -1);
begin
FRemoteJSONFile := Options.RemoteRepository + cRemoteJSONFile;
FRemoteJSONFile := Options.RemoteRepository[Options.ActiveRepositoryIndex] + cRemoteJSONFile;
FDownloadType := dtJSON;
FTimer := TThreadTimer.Create;
FTimer.Interval := ATimeOut;

View File

@ -151,7 +151,7 @@ begin
VisualTree.OnChecked := @DoOnChecked;
SerializablePackages := TSerializablePackages.Create;
SerializablePackages.OnProcessJSON := @DoOnProcessJSON;
PackageDownloader := TPackageDownloader.Create(Options.RemoteRepository);
PackageDownloader := TPackageDownloader.Create(Options.RemoteRepository[Options.ActiveRepositoryIndex]);
PackageDownloader.OnJSONProgress := @DoOnJSONProgress;
PackageDownloader.OnJSONDownloadCompleted := @DoOnJSONDownloadCompleted;
Updates := TUpdates.Create(LocalRepositoryUpdatesFile);
@ -363,7 +363,7 @@ begin
OptionsFrm.SetupControls(AActivePageIndex);
if OptionsFrm.ShowModal = mrOk then
begin
tbRefresh.Enabled := Options.RemoteRepository <> '';
tbRefresh.Enabled := Trim(Options.RemoteRepository[Options.ActiveRepositoryIndex]) <> '';
GetPackageList;
end;
finally
@ -384,7 +384,7 @@ begin
VisualTree.VST.Enabled := (AEnable) and (SerializablePackages.Count > 0);
if edFilter.CanFocus then
edFilter.SetFocus;
tbRefresh.Enabled := (AEnable) and (Trim(Options.RemoteRepository) <> '');
tbRefresh.Enabled := (AEnable) and (Trim(Options.RemoteRepository[Options.ActiveRepositoryIndex]) <> '');
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);

View File

@ -47,7 +47,9 @@ type
FProxySettings: TProxySettings;
FXML: TXMLConfig;
FVersion: Integer;
FRemoteRepository: String;
FRemoteRepository: TStringList;
FRemoteRepositoryTmp: TStringList;
FActiveRepositoryIndex: Integer;
FForceDownloadAndExtract: Boolean;
FDeleteZipAfterInstall: Boolean;
FCheckForUpdates: Integer;
@ -67,7 +69,6 @@ type
FUserProfile: Integer;
FExcludedFiles: String;
FExcludedFolders: String;
procedure SetRemoteRepository(const ARemoteRepository: String);
public
constructor Create(const AFileName: String);
destructor Destroy; override;
@ -77,7 +78,9 @@ type
procedure CreateMissingPaths;
published
property Changed: Boolean read FChanged write FChanged;
property RemoteRepository: string read FRemoteRepository write SetRemoteRepository;
property RemoteRepository: TStringList read FRemoteRepository write FRemoteRepository;
property RemoteRepositoryTmp: TStringList read FRemoteRepositoryTmp write FRemoteRepositoryTmp;
property ActiveRepositoryIndex: Integer read FActiveRepositoryIndex write FActiveRepositoryIndex;
property ForceDownloadAndExtract: Boolean read FForceDownloadAndExtract write FForceDownloadAndExtract;
property DeleteZipAfterInstall: Boolean read FDeleteZipAfterInstall write FDeleteZipAfterInstall;
property CheckForUpdates: Integer read FCheckForUpdates write FCheckForUpdates;
@ -110,6 +113,8 @@ constructor TOptions.Create(const AFileName: String);
var
LocalRepo: String;
begin
FRemoteRepository := TStringList.Create;
FRemoteRepositoryTmp := TStringList.Create;
LocalRepo := AppendPathDelim(AppendPathDelim(LazarusIDE.GetPrimaryConfigPath) + cLocalRepository);
FLocalPackagesDefault := LocalRepo + AppendPathDelim(cLocalRepositoryPackages);
FLocalArchiveDefault := LocalRepo + AppendPathDelim(cLocalRepositoryArchive);
@ -139,6 +144,8 @@ destructor TOptions.Destroy;
begin
if FChanged then
Save;
FRemoteRepository.Free;
FRemoteRepositoryTmp.Free;
FXML.Free;
inherited Destroy;
end;
@ -147,9 +154,10 @@ procedure TOptions.Load;
begin
FVersion := FXML.GetValue('Version/Value', 0);
if FVersion = 0 then
FRemoteRepository := FXML.GetValue('RemoteRepository/Value', '')
FRemoteRepository.Text := FXML.GetValue('RemoteRepository/Value', '')
else
FRemoteRepository := FXML.GetValue('General/RemoteRepository/Value', '');
FRemoteRepository.Text := FXML.GetValue('General/RemoteRepository/Value', '');
FActiveRepositoryIndex := FXML.GetValue('General/ActiveRepositoryIndex/Value', 0);
FForceDownloadAndExtract := FXML.GetValue('General/ForceDownloadAndExtract/Value', True);
FDeleteZipAfterInstall := FXML.GetValue('General/DeleteZipAfterInstall/Value', True);
FLastDownloadDir := FXML.GetValue('General/LastDownloadDir/Value', '');
@ -176,7 +184,8 @@ end;
procedure TOptions.Save;
begin
FXML.SetDeleteValue('Version/Value', OpkVersion, 0);
FXML.SetDeleteValue('General/RemoteRepository/Value', FRemoteRepository, '');
FXML.SetDeleteValue('General/RemoteRepository/Value', FRemoteRepository.Text, '');
FXML.SetDeleteValue('General/ActiveRepositoryIndex/Value', FActiveRepositoryIndex, 0);
FXML.SetDeleteValue('General/ForceDownloadAndExtract/Value', FForceDownloadAndExtract, True);
FXML.SetDeleteValue('General/DeleteZipAfterInstall/Value', FDeleteZipAfterInstall, True);
FXML.SetDeleteValue('General/LastDownloadDir/Value', FLastDownloadDir, '');
@ -185,6 +194,7 @@ begin
FXML.SetDeleteValue('General/CheckForUpdates/Value', FCheckForUpdates, 0);
FXML.SetDeleteExtendedValue('General/LastUpdate/Value', FLastUpdate, 0.0);
FXML.SetDeleteValue('Proxy/Enabled/Value', FProxySettings.FEnabled, false);
FXML.SetDeleteValue('Proxy/Server/Value', FProxySettings.FServer, '');
FXML.SetDeleteValue('Proxy/Port/Value', FProxySettings.FPort, 0);
@ -205,7 +215,8 @@ end;
procedure TOptions.LoadDefault;
begin
FRemoteRepository := cRemoteRepository;
FRemoteRepository.Add(cRemoteRepository);
FActiveRepositoryIndex := 0;
FForceDownloadAndExtract := True;
FDeleteZipAfterInstall := True;
FCheckForUpdates := 0;
@ -237,15 +248,5 @@ begin
CreateDirUTF8(FLocalRepositoryUpdate);
end;
procedure TOptions.SetRemoteRepository(const ARemoteRepository: String);
begin
if FRemoteRepository <> ARemoteRepository then
begin
FRemoteRepository := Trim(ARemoteRepository);
if FRemoteRepository[Length(FRemoteRepository)] <> '/' then
FRemoteRepository := FRemoteRepository + '/';
end;
end;
end.

View File

@ -86,16 +86,6 @@ object OptionsFrm: TOptionsFrm
Caption = 'Remote repository:'
ParentColor = False
end
object edRemoteRepository: TEdit
Left = 15
Height = 23
Top = 32
Width = 483
Anchors = [akTop, akLeft, akRight]
OnKeyPress = edRemoteRepositoryKeyPress
TabOrder = 0
Text = 'http://localhost/packages/'
end
object cbForceDownloadExtract: TCheckBox
Left = 15
Height = 19
@ -104,7 +94,7 @@ object OptionsFrm: TOptionsFrm
Caption = ' Force download and extract of packages'
ParentShowHint = False
ShowHint = True
TabOrder = 1
TabOrder = 0
end
object cbDeleteZipAfterInstall: TCheckBox
Left = 15
@ -114,7 +104,7 @@ object OptionsFrm: TOptionsFrm
Caption = 'Delete downloaded zip files after installation/update'
ParentShowHint = False
ShowHint = True
TabOrder = 2
TabOrder = 1
end
object lbUpdates: TLabel
Left = 15
@ -140,7 +130,7 @@ object OptionsFrm: TOptionsFrm
'Never'
)
Style = csDropDownList
TabOrder = 3
TabOrder = 2
Text = 'Every few minutes'
end
object lbLastUpdate: TLabel
@ -151,6 +141,26 @@ object OptionsFrm: TOptionsFrm
Caption = 'Last update:'
ParentColor = False
end
object bOpen: TButton
Left = 476
Height = 25
Top = 31
Width = 27
Anchors = [akTop, akRight]
Caption = '...'
OnClick = bOpenClick
TabOrder = 3
end
object cbRemoteRepository: TComboBox
Left = 16
Height = 23
Top = 32
Width = 457
Anchors = [akTop, akLeft, akRight]
ItemHeight = 15
Style = csDropDownList
TabOrder = 4
end
end
end
object tsProxy: TTabSheet
@ -595,6 +605,6 @@ object OptionsFrm: TOptionsFrm
end
object SDD: TSelectDirectoryDialog
left = 448
top = 32
top = 112
end
end

View File

@ -47,18 +47,19 @@ type
bOk: TButton;
bRestore: TButton;
bFilesAdd: TButton;
bOpen: TButton;
cbProxy: TCheckBox;
cbForceDownloadExtract: TCheckBox;
cbDeleteZipAfterInstall: TCheckBox;
cbCheckForUpdates: TComboBox;
cbSelectProfile: TComboBox;
cbRemoteRepository: TComboBox;
edLocalRepositoryUpdate: TDirectoryEdit;
edLocalRepositoryPackages: TDirectoryEdit;
edLocalRepositoryArchive: TDirectoryEdit;
edProxyPassword: TEdit;
edProxyServer: TEdit;
edProxyUser: TEdit;
edRemoteRepository: TEdit;
gbProxySettings: TGroupBox;
lbFilterFiles: TLabel;
lbFilterDirs: TLabel;
@ -99,6 +100,7 @@ type
procedure bFilesDeleteClick(Sender: TObject);
procedure bFilesEditClick(Sender: TObject);
procedure bOkClick(Sender: TObject);
procedure bOpenClick(Sender: TObject);
procedure bRestoreClick(Sender: TObject);
procedure cbProxyChange(Sender: TObject);
procedure cbSelectProfileChange(Sender: TObject);
@ -115,7 +117,7 @@ var
OptionsFrm: TOptionsFrm;
implementation
uses opkman_options, opkman_common, opkman_const;
uses opkman_options, opkman_common, opkman_const, opkman_repositories;
{$R *.lfm}
{ TOptionsFrm }
@ -124,10 +126,10 @@ procedure TOptionsFrm.bOkClick(Sender: TObject);
var
I: Integer;
begin
if Trim(edRemoteRepository.Text) = '' then
if Trim(cbRemoteRepository.Text) = '' then
begin
MessageDlgEx(rsOptions_RemoteRepository_Information, mtInformation, [mbOk], Self);
edRemoteRepository.SetFocus;
cbRemoteRepository.SetFocus;
Exit;
end;
@ -165,7 +167,9 @@ begin
edLocalRepositoryUpdate.SetFocus;
Exit;
end;
Options.RemoteRepository := edRemoteRepository.Text;
if Options.RemoteRepositoryTmp.Count > 0 then
Options.RemoteRepository.Text := Options.RemoteRepositoryTmp.Text;
Options.ActiveRepositoryIndex := cbRemoteRepository.ItemIndex;
Options.ForceDownloadAndExtract := cbForceDownloadExtract.Checked;
Options.DeleteZipAfterInstall := cbDeleteZipAfterInstall.Checked;
Options.CheckForUpdates := cbCheckForUpdates.ItemIndex;
@ -200,6 +204,30 @@ begin
ModalResult := mrOk;
end;
procedure TOptionsFrm.bOpenClick(Sender: TObject);
var
I: Integer;
begin
RepositoriesFrm := TRepositoriesFrm.Create(Self);
try
if RepositoriesFrm.ShowModal = mrOk then
begin
cbRemoteRepository.Clear;
for I := 0 to Options.RemoteRepositoryTmp.Count - 1 do
cbRemoteRepository.Items.Add(Options.RemoteRepositoryTmp.Strings[I]);
if Options.ActiveRepositoryIndex <= cbRemoteRepository.Items.Count - 1 then
cbRemoteRepository.ItemIndex := Options.ActiveRepositoryIndex
else
begin
cbRemoteRepository.ItemIndex := 0;
Options.ActiveRepositoryIndex := 0;
end;
end;
finally
RepositoriesFrm.Free;
end;
end;
function TOptionsFrm.GetSelectedText(AListBox: TListBox; var AIndex: Integer): String;
var
I: Integer;
@ -338,13 +366,19 @@ begin
end;
procedure TOptionsFrm.SetupControls(const AActivePageIndex: Integer = 0);
var
I: Integer;
begin
Self.DoubleBuffered := True;
Caption := rsOptions_FrmCaption;
pgOptions.ActivePageIndex := AActivePageIndex;
tsGeneral.Caption := rsOptions_tsGeneral_Caption;
lbRemoteRepository.Caption := rsOptions_lbRemoteRepository_Caption;
edRemoteRepository.Text := Options.RemoteRepository;
Options.RemoteRepositoryTmp.Clear;
for I := 0 to Options.RemoteRepository.Count - 1 do
cbRemoteRepository.Items.Add(Options.RemoteRepository.Strings[I]);
cbRemoteRepository.ItemIndex := Options.ActiveRepositoryIndex;
cbForceDownloadExtract.Checked := Options.ForceDownloadAndExtract;
cbDeleteZipAfterInstall.Checked := Options.DeleteZipAfterInstall;
cbForceDownloadExtract.Caption := rsOptions_cbForceDownloadExtract_Caption;

View File

@ -0,0 +1,129 @@
object RepositoriesFrm: TRepositoriesFrm
Left = 530
Height = 367
Top = 293
Width = 561
BorderIcons = [biSystemMenu]
Caption = 'RepositoriesFrm'
ClientHeight = 367
ClientWidth = 561
OnCreate = FormCreate
OnDestroy = FormDestroy
PopupMode = pmExplicit
Position = poOwnerFormCenter
LCLVersion = '1.7'
object pnBottom: TPanel
Left = 460
Height = 332
Top = 0
Width = 101
Align = alRight
BevelOuter = bvNone
ClientHeight = 332
ClientWidth = 101
TabOrder = 0
object bAdd: TButton
Left = 4
Height = 25
Top = 5
Width = 88
Anchors = [akTop, akRight]
Caption = 'Add'
OnClick = bAddClick
TabOrder = 0
end
object bEdit: TButton
Tag = 1
Left = 4
Height = 25
Top = 34
Width = 88
Anchors = [akTop, akRight]
Caption = 'Edit'
OnClick = bAddClick
TabOrder = 1
end
object bDelete: TButton
Tag = 2
Left = 4
Height = 25
Top = 63
Width = 88
Anchors = [akTop, akRight]
Caption = 'Delete'
OnClick = bAddClick
TabOrder = 2
end
end
object pnBottom1: TPanel
Left = 0
Height = 35
Top = 332
Width = 561
Align = alBottom
BevelOuter = bvNone
ClientHeight = 35
ClientWidth = 561
TabOrder = 1
object bOk: TButton
Left = 373
Height = 25
Top = 4
Width = 88
Anchors = [akTop, akRight]
Caption = 'OK'
ModalResult = 1
OnClick = bOkClick
TabOrder = 0
end
object bCancel: TButton
Left = 465
Height = 25
Top = 4
Width = 88
Anchors = [akTop, akRight]
Caption = 'Cancel'
ModalResult = 2
TabOrder = 1
end
end
object imTree: TImageList
left = 16
top = 8
Bitmap = {
4C69010000001000000010000000A38D780095806C12B3A18B9FC5B49FFEC6B5
A0FFC6B5A0FFC6B5A0FFC6B5A1FFBEAD98E3A5917C4BFFFFFF00988674000000
0000000000000000000000000000FFEAD300AC9A886AD5C9BBF9E3D9CBFFE2D9
CAFFE2D9CAFFE2D9CAFFE3D9CAFFE0D6C8FFC3B4A4CB84715C189B8874000000
0000000000000000000000000000FFFFFF00AE9F8E87E5DBCEFFE7DDCFFFE8DE
D2FFE8DED2FFE8DED2FFE8DED2FFE8DED0FFD1C5B7E67563502492806B000000
0000000000000000000000000000FFFFFF00AC9C8B87DED2C2FFCBB69BFFC9B4
99FFC9B499FFC9B499FFC8B398FFD6C5B0FFCEC1B3E673614E24907D69000000
0000000000000000000000000000FFFFFF00AA9A8887DED3C4FFE0D3C4FFE1D5
C6FFE1D5C6FFE1D5C6FFE1D5C6FFE1D5C5FFCBBEAFE672604E248E7C68000000
0000000000000000000000000000FFFFFF00A8988687DACDBDFFCBB69CFFC9B4
9AFFCAB49AFFCAB49AFFC9B499FFD4C4AEFFC9BCADE6715F4C248D7B67000000
0000000000000000000000000000FFFFFF00A6958387D9CEBEFFDED2C2FFDFD3
C4FFDFD3C4FFDFD3C4FFDFD3C4FFDED2C2FFC7B8A7E574614D238E7A65000000
0000000000000000000000000000FFFFFF00A4938187D5C8B7FFCAB69BFFC9B4
99FFC9B599FFC9B599FFC8B499FFC9BBA6FFC0B6A8F3B2AA9E92BCB6AB7FBAB4
A87CB0AA9F489D968B09A39D9100FFFFFF00A2917E87D4C8B8FFDBD0C0FFDCD2
C2FFDCD1C2FFDDD3C3FFCCC1B2FFCFC6BBFFDDD5CBFFDFD6CCFFDED5CBFFDCD4
CAFFD1C9BEEFADA69B5FF1E8D900FFFFFF00A08F7C87D0C3B0FFCAB79CFFC9B5
9AFFCAB69BFFCEB79CFFBEB09DFFDBD4CCFFE9E2D9FFEAE3DBFFEAE3DBFFE9E2
D9FFDCD5CCFFA8A19686FFFFFF00FFFFFF009E8D7987CEC1AEFFCDBFA9FFCDBF
A9FFC7BDA6FF95B08AFFB5AE9CFFC4BCB3FFDAD1C8FFE8DED7FFE8DED8FFDBD2
CAFFC6BEB5FF9D968B84FFFFFF00FFFFFF009C8B7687CCC1ADFFD7CDBAFFD7CD
BAFFD6CCB9FFC8CAB2FFC5BCACFFC7BFB6FFD1C9C0FFDCD2CAFFDCD3CBFFD2CA
C2FFC8C1B8FC978F8570FFFFFF00FFFFFF009A887487CBBFABFFE0D7C6FFE1D8
C8FFE1D8C8FFE4DBCAFFC3BAACFFCCC5BCFFE1DAD2FFEAE2DAFFEAE2DBFFE2DB
D3FFCFC8BEFF9B918683FFFFFF00FFFFFF008C7B6773AD9E89ECB1A28EECB1A2
8DECB1A28DECB1A28DEBA69A8AF2C3BAB1FED9D0C7FFE7DDD5FFE9DED7FFDAD1
C9FFC4BCB3FF938A7E84FFFFFF00000000003830271A3F352A3C3D33283E3D33
283E3D33283E3B30263D5951485B948C82BAB0A69CE7BAAFA6EABBB0A7EAB0A7
9CE7958C82BB675F563EFFFFFF00000000000000000000000000000000000000
000000000000000000000000000625221D2638322C4336312A4636312A463832
2C4325211D26000000061F181300
}
end
end

View File

@ -0,0 +1,353 @@
unit opkman_repositories;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
StdCtrls, Menus, opkman_VirtualTrees;
type
{ TRepositoriesFrm }
TRepositoriesFrm = class(TForm)
bEdit: TButton;
bCancel: TButton;
bDelete: TButton;
bAdd: TButton;
bOk: TButton;
imTree: TImageList;
pnBottom: TPanel;
pnBottom1: TPanel;
procedure bAddClick(Sender: TObject);
procedure bOkClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
FVST: TVirtualStringTree;
FSortCol: Integer;
FSortDir: opkman_VirtualTrees.TSortDirection;
procedure VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; {%H-}TextType: TVSTTextType; var CellText: String);
procedure VSTGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode;
{%H-}Kind: TVTImageKind; Column: TColumnIndex; var {%H-}Ghosted: Boolean;
var ImageIndex: Integer);
procedure VSTCompareNodes(Sender: TBaseVirtualTree; Node1,
Node2: PVirtualNode; Column: TColumnIndex; var Result: Integer);
procedure VSTFocuseChanged(Sender: TBaseVirtualTree; {%H-}Node: PVirtualNode; {%H-}Column: TColumnIndex);
procedure VSTPaintText(Sender: TBaseVirtualTree; const TargetCanvas: TCanvas;
Node: PVirtualNode; {%H-}Column: TColumnIndex; {%H-}TextType: TVSTTextType);
procedure VSTHeaderClick(Sender: TVTHeader; Column: TColumnIndex;
Button: TMouseButton; {%H-}Shift: TShiftState; {%H-}X, {%H-}Y: Integer);
procedure VSTFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
procedure PopulateTree;
procedure EnableDisableButtons;
public
end;
var
RepositoriesFrm: TRepositoriesFrm;
implementation
uses opkman_const, opkman_common, opkman_options, opkman_optionsfrm;
{$R *.lfm}
type
PData = ^TData;
TData = record
FAddress: string;
FType: Integer;
FImageIndex: Integer;
end;
{ TRepositoriesFrm }
procedure TRepositoriesFrm.FormCreate(Sender: TObject);
begin
Caption := rsRepositories_Caption;
bAdd.Caption := rsRepositories_bAdd_Caption;
bEdit.Caption := rsRepositories_bEdit_Caption;
bDelete.Caption := rsRepositories_bDelete_Caption;
bOk.Caption := rsRepositories_bOk_Caption;
bCancel.Caption := rsRepositories_bCancel_Caption;
FVST := TVirtualStringTree.Create(nil);
with FVST do
begin
Parent := Self;
Align := alClient;
Anchors := [akLeft, akTop, akRight];
Color := clBtnFace;
DefaultNodeHeight := 22;
Indent := 0;
DefaultText := '';
Colors.BorderColor := clBlack;
BorderSpacing.Top := 5;
BorderSpacing.Left := 5;
BorderSpacing.Right := 0;
BorderSpacing.Bottom := 0;
Header.Height := 25;
Header.Options := [hoAutoResize, hoVisible, hoColumnResize, hoRestrictDrag, hoShowSortGlyphs, hoAutoSpring];
{$IFDEF LCLCarbon}
Header.Options := Header.Options - [hoShowSortGlyphs];
{$ENDIF}
Header.AutoSizeIndex := 1;
Header.Height := 25;
with Header.Columns.Add do
begin
Position := 1;
Width := 250;
Text := rsRepositories_VST_HeaderColumn;
end;
Header.SortColumn := 0;
TabOrder := 0;
TreeOptions.MiscOptions := [toFullRepaintOnResize, toInitOnSave, toToggleOnDblClick, toWheelPanning];
TreeOptions.PaintOptions := [toHideFocusRect, toPopupMode, toShowButtons, toShowDropmark, toThemeAware, toUseBlendedImages];
TreeOptions.SelectionOptions := [toFullRowSelect, toRightClickSelect];
TreeOptions.AutoOptions := [toAutoTristateTracking];
Images := imTree;
OnGetText := @VSTGetText;
OnGetImageIndex := @VSTGetImageIndex;
OnCompareNodes := @VSTCompareNodes;
OnFocusChanged := @VSTFocuseChanged;
OnPaintText := @VSTPaintText;
OnHeaderClick := @VSTHeaderClick;
OnFreeNode := @VSTFreeNode;
end;
FVST.NodeDataSize := SizeOf(TData);
PopulateTree;
end;
procedure TRepositoriesFrm.bAddClick(Sender: TObject);
var
PrevNode, Node: PVirtualNode;
Data: PData;
Value: String;
begin
case (Sender as TButton).Tag of
0: begin
Value := InputBox(rsRepositories_InputBox_Caption0, rsRepositories_InputBox_Text, '');
if Value <> '' then
begin
Node := FVST.AddChild(nil);
Data := FVST.GetNodeData(Node);
Data^.FAddress := Trim(Value);
Data^.FAddress := FixProtocol(Data^.FAddress);
if Data^.FAddress[Length(Data^.FAddress)] <> '/' then
Data^.FAddress := Data^.FAddress + '/';
Data^.FType := 1;
Data^.FImageIndex := 0;
FVST.Selected[Node] := True;
FVST.FocusedNode := Node;
FVST.SortTree(0, FSortDir);
end;
end;
1: begin
Node := FVST.GetFirstSelected;
if Node <> nil then
begin
Data := FVST.GetNodeData(Node);
Value := InputBox(rsRepositories_InputBox_Caption1, rsRepositories_InputBox_Text, Data^.FAddress);
if Value <> '' then
begin
Data^.FAddress := Trim(Value);
Data^.FAddress := FixProtocol(Data^.FAddress);
if Data^.FAddress[Length(Data^.FAddress)] <> '/' then
Data^.FAddress := Data^.FAddress + '/';
FVST.ReinitNode(Node, False);
FVST.RepaintNode(Node);
end;
FVST.SortTree(0, FSortDir);
end;
end;
2: begin
Node := FVST.GetFirstSelected;
if Node <> nil then
begin
Data := FVST.GetNodeData(Node);
if MessageDlgEx(Format(rsRepositories_Confirmation0, [Data^.FAddress]), mtConfirmation, [mbYes, mbNo], Self) = mrYes then
begin
PrevNode := FVST.GetPrevious(Node);
FVST.DeleteNode(Node);
if PrevNode <> nil then
begin
FVST.Selected[PrevNode] := True;
FVST.FocusedNode := PrevNode;
end;
end;
end;
end;
end;
end;
procedure TRepositoriesFrm.bOkClick(Sender: TObject);
var
Node: PVirtualNode;
Data: PData;
begin
Options.RemoteRepositoryTmp.Clear;
FVST.BeginUpdate;
FVST.SortTree(0, opkman_VirtualTrees.sdAscending);
Node := FVST.GetFirst;
while Assigned(Node) do
begin
Data := FVST.GetNodeData(Node);
Options.RemoteRepositoryTmp.Add(Data^.FAddress);
Node := FVST.GetNext(Node);
end;
end;
procedure TRepositoriesFrm.FormDestroy(Sender: TObject);
begin
FVST.Clear;
FVST.Free;
end;
procedure TRepositoriesFrm.VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; TextType: TVSTTextType; var CellText: String);
var
Data: PData;
begin
Data := FVST.GetNodeData(Node);
if Column = 0 then
CellText := Data^.FAddress;
end;
procedure TRepositoriesFrm.VSTGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode;
Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean;
var ImageIndex: Integer);
var
Data: PData;
begin
if Column <> 0 then
Exit;
Data := FVST.GetNodeData(Node);
ImageIndex := Data^.FImageIndex;
end;
procedure TRepositoriesFrm.VSTCompareNodes(Sender: TBaseVirtualTree; Node1,
Node2: PVirtualNode; Column: TColumnIndex; var Result: Integer);
var
Data1: PData;
Data2: PData;
begin
Data1 := Sender.GetNodeData(Node1);
Data2 := Sender.GetNodeData(Node2);
case Column of
0: if Data1^.FType > Data2^.FType then
Result := 1
else if Data1^.FType < Data2^.FType then
Result := 0
else if Data1^.FType = Data2^.FType then
Result := CompareText(Data1^.FAddress, Data2^.FAddress);
end;
end;
procedure TRepositoriesFrm.VSTFocuseChanged(Sender: TBaseVirtualTree;
Node: PVirtualNode; Column: TColumnIndex);
begin
EnableDisableButtons;
end;
procedure TRepositoriesFrm.VSTPaintText(Sender: TBaseVirtualTree;
const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
TextType: TVSTTextType);
var
Data: PData;
begin
Data := FVST.GetNodeData(Node);
if Data^.FType = 0 then
TargetCanvas.Font.Style := TargetCanvas.Font.Style + [fsBold]
else
TargetCanvas.Font.Style := TargetCanvas.Font.Style - [fsBold]
end;
procedure TRepositoriesFrm.VSTHeaderClick(Sender: TVTHeader;
Column: TColumnIndex; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if (Column <> 0) and (Column <> 1) and (Column <> 3) then
Exit;
if Button = mbLeft then
begin
with Sender, Treeview do
begin
if (SortColumn = NoColumn) or (SortColumn <> Column) then
begin
SortColumn := Column;
SortDirection := opkman_VirtualTrees.sdAscending;
end
else
begin
if SortDirection = opkman_VirtualTrees.sdAscending then
SortDirection := opkman_VirtualTrees.sdDescending
else
SortDirection := opkman_VirtualTrees.sdAscending;
FSortDir := SortDirection;
end;
SortTree(SortColumn, SortDirection, False);
FSortCol := Sender.SortColumn;
end;
end;
end;
procedure TRepositoriesFrm.VSTFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
var
Data: PData;
begin
Data := FVST.GetNodeData(Node);
Finalize(Data^);
end;
procedure TRepositoriesFrm.EnableDisableButtons;
var
SelNode: PVirtualNode;
SelData: PData;
begin
bEdit.Enabled := False;
bDelete.Enabled := False;
if FVST.RootNodeCount = 0 then
Exit;
SelNode := FVST.GetFirstSelected;
if SelNode = nil then
Exit;
SelData := FVST.GetNodeData(SelNode);
bEdit.Enabled := SelData^.FType > 0;
bDelete.Enabled := SelData^.FType > 0;
end;
procedure TRepositoriesFrm.PopulateTree;
var
I: Integer;
Node: PVirtualNode;
Data: PData;
begin
if Trim(Options.RemoteRepositoryTmp.Text) = '' then
Options.RemoteRepositoryTmp.Text := Options.RemoteRepository.Text;
for I := 0 to Options.RemoteRepositoryTmp.Count - 1 do
begin
if Trim(Options.RemoteRepositoryTmp.Strings[I]) <> '' then
begin
Node := FVST.AddChild(nil);
Data := FVST.GetNodeData(Node);
Data^.FAddress := Options.RemoteRepositoryTmp.Strings[I];
if I = 0 then
Data^.FType := 0
else
Data^.FType := 1;
Data^.FImageIndex := 0;
end;
end;
FVST.SortTree(0, opkman_VirtualTrees.sdAscending);
Node := FVST.GetFirst;
if Node <> nil then
begin
FVST.Selected[Node] := True;
FVST.FocusedNode := Node;
end;
EnableDisableButtons;
end;
end.

View File

@ -306,7 +306,7 @@ begin
//add repository(DataType = 0)
RootNode := FVST.AddChild(nil);
RootData := FVST.GetNodeData(RootNode);
RootData^.Repository := Options.RemoteRepository;
RootData^.Repository := Options.RemoteRepository[Options.ActiveRepositoryIndex];
RootData^.DataType := 0;
for I := 0 to SerializablePackages.Count - 1 do
begin