lazarus/packager/installpkgsetdlg.pas
2012-04-06 21:34:21 +00:00

900 lines
29 KiB
ObjectPascal

{ $Id$ }
{
/***************************************************************************
installpkgsetdlg.pas
--------------------
***************************************************************************/
***************************************************************************
* *
* This source is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This code is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* General Public License for more details. *
* *
* A copy of the GNU General Public License is available on the World *
* Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
* obtain it by writing to the Free Software Foundation, *
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
***************************************************************************
Author: Mattias Gaertner
Abstract:
Dialog to edit the package set installed in the IDE.
}
unit InstallPkgSetDlg;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, contnrs, LCLProc, Forms, Controls, Graphics, Dialogs,
KeywordFuncLists, StdCtrls, Buttons, FileUtil, ExtCtrls, ComCtrls, EditBtn,
LCLType, AVL_Tree, Laz2_XMLCfg, TreeFilterEdit, PackageIntf, IDEImagesIntf,
IDEHelpIntf, IDEDialogs, LazarusIDEStrConsts, EnvironmentOpts, InputHistory,
LazConf, IDEProcs, PackageDefs, PackageSystem, PackageLinks,
IDEContextHelpEdit;
type
TOnCheckInstallPackageList =
procedure(PkgIDs: TObjectList; RemoveConflicts: boolean; out Ok: boolean) of object;
{ TInstallPkgSetDialog }
TInstallPkgSetDialog = class(TForm)
AddToInstallButton: TBitBtn;
AvailableTreeView: TTreeView;
AvailablePkgGroupBox: TGroupBox;
HelpButton: TBitBtn;
CancelButton: TBitBtn;
ExportButton: TButton;
BtnPanel: TPanel;
InstallTreeView: TTreeView;
lblMiddle: TLabel;
AvailableFilterEdit: TTreeFilterEdit;
NoteLabel: TLabel;
PkgInfoMemo: TMemo;
PkgInfoGroupBox: TGroupBox;
ImportButton: TButton;
SaveAndExitButton: TBitBtn;
InstallPkgGroupBox: TGroupBox;
SaveAndRebuildButton: TBitBtn;
UninstallButton: TBitBtn;
procedure AddToInstallButtonClick(Sender: TObject);
procedure AvailableTreeViewDblClick(Sender: TObject);
procedure AvailableTreeViewKeyPress(Sender: TObject; var Key: char);
procedure AvailableTreeViewSelectionChanged(Sender: TObject);
procedure ExportButtonClick(Sender: TObject);
procedure HelpButtonClick(Sender: TObject);
procedure ImportButtonClick(Sender: TObject);
procedure InstallButtonClick(Sender: TObject);
procedure InstallTreeViewDblClick(Sender: TObject);
procedure InstallPkgSetDialogCreate(Sender: TObject);
procedure InstallPkgSetDialogDestroy(Sender: TObject);
procedure InstallPkgSetDialogResize(Sender: TObject);
procedure InstallTreeViewSelectionChanged(Sender: TObject);
procedure SaveAndExitButtonClick(Sender: TObject);
procedure UninstallButtonClick(Sender: TObject);
private
FNewInstalledPackages: TObjectList; // list of TLazPackageID (not TLazPackage)
FOldInstalledPackages: TPkgDependency;
FOnCheckInstallPackageList: TOnCheckInstallPackageList;
fAvailablePackages: TAVLTree;// tree of TLazPackageID (all available packages and links)
FRebuildIDE: boolean;
FSelectedPkg: TLazPackage;
ImgIndexPackage: integer;
ImgIndexInstallPackage: integer;
ImgIndexInstalledPackage: integer;
ImgIndexUninstallPackage: integer;
ImgIndexCirclePackage: integer;
ImgIndexMissingPackage: integer;
procedure SetOldInstalledPackages(const AValue: TPkgDependency);
procedure AssignOldInstalledPackagesToList;
function PackageInInstallList(PkgName: string): boolean;
function GetPkgImgIndex(APackage: TLazPackage; InInstallList: boolean): integer;
function GetAvailablePkgImageIndex(Str: String; Data: TObject; var AIsEnabled: Boolean): Integer;
procedure UpdateAvailablePackages(Immediately: boolean = false);
procedure UpdateNewInstalledPackages;
procedure OnIteratePackages(APackageID: TLazPackageID);
function DependencyToStr(Dependency: TPkgDependency): string;
procedure ClearNewInstalledPackages;
function CheckSelection: boolean;
procedure UpdateButtonStates;
procedure UpdatePackageInfo(Tree: TTreeView);
function NewInstalledPackagesContains(APackageID: TLazPackageID): boolean;
function IndexOfNewInstalledPackageID(APackageID: TLazPackageID): integer;
function IndexOfNewInstalledPkgByName(const APackageName: string): integer;
procedure SavePackageListToFile(const AFilename: string);
procedure LoadPackageListFromFile(const AFilename: string);
function ExtractNameFromPkgID(ID: string): string;
procedure AddToInstall;
procedure AddToUninstall;
public
function GetNewInstalledPackages: TObjectList;
property OldInstalledPackages: TPkgDependency read FOldInstalledPackages
write SetOldInstalledPackages;
property NewInstalledPackages: TObjectList read FNewInstalledPackages;
property RebuildIDE: boolean read FRebuildIDE write FRebuildIDE;
property OnCheckInstallPackageList: TOnCheckInstallPackageList
read FOnCheckInstallPackageList write FOnCheckInstallPackageList;
end;
function ShowEditInstallPkgsDialog(OldInstalledPackages: TPkgDependency;
CheckInstallPackageList: TOnCheckInstallPackageList;
var NewInstalledPackages: TObjectList; // list of TLazPackageID (must be freed)
var RebuildIDE: boolean): TModalResult;
implementation
{$R *.lfm}
function ShowEditInstallPkgsDialog(OldInstalledPackages: TPkgDependency;
CheckInstallPackageList: TOnCheckInstallPackageList;
var NewInstalledPackages: TObjectList; // list of TLazPackageID
var RebuildIDE: boolean): TModalResult;
var
InstallPkgSetDialog: TInstallPkgSetDialog;
begin
NewInstalledPackages:=nil;
InstallPkgSetDialog:=TInstallPkgSetDialog.Create(nil);
try
InstallPkgSetDialog.OldInstalledPackages:=OldInstalledPackages;
// InstallPkgSetDialog.UpdateAvailablePackages;
InstallPkgSetDialog.UpdateButtonStates;
InstallPkgSetDialog.OnCheckInstallPackageList:=CheckInstallPackageList;
Result:=InstallPkgSetDialog.ShowModal;
NewInstalledPackages:=InstallPkgSetDialog.GetNewInstalledPackages;
RebuildIDE:=InstallPkgSetDialog.RebuildIDE;
finally
InstallPkgSetDialog.Free;
end;
end;
{ TInstallPkgSetDialog }
procedure TInstallPkgSetDialog.InstallPkgSetDialogCreate(Sender: TObject);
begin
InstallTreeView.Images := IDEImages.Images_16;
AvailableTreeView.Images := IDEImages.Images_16;
ImgIndexPackage := IDEImages.LoadImage(16, 'item_package');
ImgIndexInstalledPackage := IDEImages.LoadImage(16, 'pkg_installed');
ImgIndexInstallPackage := IDEImages.LoadImage(16, 'pkg_package_autoinstall');
ImgIndexUninstallPackage := IDEImages.LoadImage(16, 'pkg_package_uninstall');
ImgIndexCirclePackage := IDEImages.LoadImage(16, 'pkg_package_circle');
ImgIndexMissingPackage := IDEImages.LoadImage(16, 'pkg_conflict');
Caption:=lisInstallUninstallPackages;
NoteLabel.Caption:=lisToInstallYouMustCompileAndRestartTheIDE;
AvailablePkgGroupBox.Caption:=lisDoNotInstall;
AvailableFilterEdit.OnGetImageIndex:=@GetAvailablePkgImageIndex;
ExportButton.Caption:=lisExportList;
ImportButton.Caption:=lisImportList;
UninstallButton.Caption:=lisUninstallSelection;
UninstallButton.LoadGlyphFromLazarusResource('arrow_right');
InstallPkgGroupBox.Caption:=lisPckEditInstall;
AddToInstallButton.Caption:=lisInstallSelection;
AddToInstallButton.LoadGlyphFromLazarusResource('arrow_left');
PkgInfoGroupBox.Caption := lisPackageInfo;
SaveAndRebuildButton.Caption:=lisSaveAndRebuildIDE;
SaveAndExitButton.Caption:=lisSaveAndExitDialog;
HelpButton.Caption:=lisMenuHelp;
CancelButton.Caption:=lisCancel;
fAvailablePackages:=TAVLTree.Create(@CompareLazPackageIDNames);
FNewInstalledPackages:=TObjectList.Create(true);
ActiveControl:=AvailableFilterEdit;
PkgInfoMemo.Clear;
end;
procedure TInstallPkgSetDialog.InstallButtonClick(Sender: TObject);
begin
if not CheckSelection then exit;
RebuildIDE:=true;
ModalResult:=mrOk;
end;
procedure TInstallPkgSetDialog.InstallTreeViewDblClick(Sender: TObject);
begin
AddToUninstall;
end;
procedure TInstallPkgSetDialog.AvailableTreeViewSelectionChanged(Sender: TObject);
begin
UpdateButtonStates;
UpdatePackageInfo(AvailableTreeView);
end;
procedure TInstallPkgSetDialog.ExportButtonClick(Sender: TObject);
var
SaveDialog: TSaveDialog;
AFilename: string;
begin
SaveDialog:=TSaveDialog.Create(nil);
try
InputHistories.ApplyFileDialogSettings(SaveDialog);
SaveDialog.InitialDir:=GetPrimaryConfigPath;
SaveDialog.Title:=lisExportPackageListXml;
SaveDialog.Options:=SaveDialog.Options+[ofPathMustExist];
if SaveDialog.Execute then begin
AFilename:=CleanAndExpandFilename(SaveDialog.Filename);
if ExtractFileExt(AFilename)='' then
AFilename:=AFilename+'.xml';
SavePackageListToFile(AFilename);
end;
InputHistories.StoreFileDialogSettings(SaveDialog);
finally
SaveDialog.Free;
end;
end;
procedure TInstallPkgSetDialog.HelpButtonClick(Sender: TObject);
begin
LazarusHelp.ShowHelpForIDEControl(Self);
end;
procedure TInstallPkgSetDialog.ImportButtonClick(Sender: TObject);
var
OpenDialog: TOpenDialog;
AFilename: string;
begin
OpenDialog:=TOpenDialog.Create(nil);
try
InputHistories.ApplyFileDialogSettings(OpenDialog);
OpenDialog.InitialDir:=GetPrimaryConfigPath;
OpenDialog.Title:=lisImportPackageListXml;
OpenDialog.Options:=OpenDialog.Options+[ofPathMustExist,ofFileMustExist];
if OpenDialog.Execute then begin
AFilename:=CleanAndExpandFilename(OpenDialog.Filename);
LoadPackageListFromFile(AFilename);
end;
InputHistories.StoreFileDialogSettings(OpenDialog);
finally
OpenDialog.Free;
end;
end;
procedure TInstallPkgSetDialog.AddToInstallButtonClick(Sender: TObject);
begin
AddToInstall;
end;
procedure TInstallPkgSetDialog.AvailableTreeViewDblClick(Sender: TObject);
begin
AddToInstall;
end;
procedure TInstallPkgSetDialog.AvailableTreeViewKeyPress(Sender: TObject; var Key: char);
begin
if Key = char(VK_RETURN) then
AddToInstall;
end;
procedure TInstallPkgSetDialog.InstallPkgSetDialogDestroy(Sender: TObject);
begin
ClearNewInstalledPackages;
FNewInstalledPackages.Free;
fAvailablePackages.Free;
end;
procedure TInstallPkgSetDialog.InstallPkgSetDialogResize(Sender: TObject);
var
w: Integer;
begin
w:=ClientWidth div 2-InstallPkgGroupBox.BorderSpacing.Left*3;
if w<1 then w:=1;
InstallPkgGroupBox.Width:=w;
end;
procedure TInstallPkgSetDialog.InstallTreeViewSelectionChanged(Sender: TObject);
begin
UpdateButtonStates;
UpdatePackageInfo(InstallTreeView);
end;
procedure TInstallPkgSetDialog.SaveAndExitButtonClick(Sender: TObject);
begin
if not CheckSelection then exit;
RebuildIDE:=false;
ModalResult:=mrOk;
end;
procedure TInstallPkgSetDialog.UninstallButtonClick(Sender: TObject);
begin
AddToUninstall;
end;
procedure TInstallPkgSetDialog.SetOldInstalledPackages(const AValue: TPkgDependency);
begin
if FOldInstalledPackages=AValue then exit;
FOldInstalledPackages:=AValue;
AssignOldInstalledPackagesToList;
end;
procedure TInstallPkgSetDialog.AssignOldInstalledPackagesToList;
var
Dependency: TPkgDependency;
Cnt: Integer;
NewPackageID: TLazPackageID;
begin
ClearNewInstalledPackages;
Cnt:=0;
Dependency:=OldInstalledPackages;
while Dependency<>nil do begin
NewPackageID:=TLazPackageID.Create;
if (Dependency.LoadPackageResult=lprSuccess)
and (Dependency.RequiredPackage<>nil) then begin
// packages can be freed while the dialog runs => use packageid instead
NewPackageID.AssignID(Dependency.RequiredPackage);
end else begin
NewPackageID.Name:=Dependency.PackageName;
end;
FNewInstalledPackages.Add(NewPackageID);
Dependency:=Dependency.NextRequiresDependency;
inc(Cnt);
end;
UpdateNewInstalledPackages;
end;
function TInstallPkgSetDialog.PackageInInstallList(PkgName: string): boolean;
var
i: Integer;
begin
//for i:=0 to InstallTreeView.Items.TopLvlCount-1 do
//debugln(['TInstallPkgSetDialog.PackageInInstallList ',i,' ',ExtractNameFromPkgID(InstallTreeView.Items.TopLvlItems[i].Text),' ',PkgName]);
for i:=0 to InstallTreeView.Items.TopLvlCount-1 do
if SysUtils.CompareText(
ExtractNameFromPkgID(InstallTreeView.Items.TopLvlItems[i].Text),PkgName)=0
then
exit(true);
Result:=false;
end;
function TInstallPkgSetDialog.GetPkgImgIndex(APackage: TLazPackage;
InInstallList: boolean): integer;
begin
if APackage.Installed<>pitNope then begin
// is not currently installed
if InInstallList then begin
// is installed and will be installed
Result:=ImgIndexPackage;
end
else begin
// is installed and will be uninstalled
Result:=ImgIndexUninstallPackage;
end;
end else begin
// is currently installed
if InInstallList then begin
// is not installed and will be installed
Result:=ImgIndexInstallPackage;
end
else begin
// is not installed and will be not be installed
Result:=ImgIndexPackage;
end;
end;
end;
function TInstallPkgSetDialog.GetAvailablePkgImageIndex(Str: String; Data: TObject;
var AIsEnabled: Boolean): Integer;
begin
Result:=ImgIndexPackage;
if (Data is TLazPackage) then
Result:=GetPkgImgIndex(TLazPackage(Data),false);
end;
procedure TInstallPkgSetDialog.UpdateAvailablePackages(Immediately: boolean);
var
ANode: TAVLTreeNode;
Pkg: TLazPackageID;
PkgName: String;
DuplCheck: TStringList; // Add pkg names also here to filter out duplicates.
FilteredBranch: TTreeFilterBranch;
begin
DuplCheck:=TStringList.Create;
try
if fAvailablePackages.Count=0 then
PackageGraph.IteratePackages(fpfSearchAllExisting,@OnIteratePackages);
FilteredBranch := AvailableFilterEdit.GetBranch(Nil); // All items are top level.
ANode:=fAvailablePackages.FindLowest;
while ANode<>nil do begin
Pkg:=TLazPackageID(ANode.Data);
if (not (Pkg is TLazPackage))
or (TLazPackage(Pkg).PackageType in [lptDesignTime,lptRunAndDesignTime])
then begin
if (not PackageInInstallList(Pkg.Name)) then begin
PkgName:=Pkg.IDAsString;
if (DuplCheck.IndexOf(PkgName)<0) then begin
DuplCheck.Add(PkgName);
FilteredBranch.AddNodeData(PkgName, Pkg);
end;
end;
end;
ANode:=fAvailablePackages.FindSuccessor(ANode);
end;
AvailableFilterEdit.InvalidateFilter;
finally
DuplCheck.Free;
end;
end;
procedure TInstallPkgSetDialog.UpdateNewInstalledPackages;
var
s: String;
NewPackageID: TLazPackageID;
i: Integer;
sl: TStringList;
TVNode: TTreeNode;
APackage: TLazPackage;
ImgIndex: LongInt;
begin
sl:=TStringList.Create;
for i:=0 to FNewInstalledPackages.Count-1 do begin
NewPackageID:=TLazPackageID(FNewInstalledPackages[i]);
APackage:=PackageGraph.FindPackageWithName(NewPackageID.Name,nil);
if APackage<>nil then
NewPackageID:=APackage;
s:=NewPackageID.IDAsString;
sl.AddObject(s,NewPackageID);
end;
sl.Sort;
InstallTreeView.BeginUpdate;
InstallTreeView.Items.Clear;
for i:=0 to sl.Count-1 do begin
TVNode:=InstallTreeView.Items.Add(nil,sl[i]);
NewPackageID:=TLazPackageID(sl.Objects[i]);
ImgIndex:=ImgIndexInstallPackage;
if NewPackageID is TLazPackage then begin
APackage:=TLazPackage(NewPackageID);
ImgIndex:=GetPkgImgIndex(APackage,true);
end;
TVNode.ImageIndex:=ImgIndex;
TVNode.SelectedIndex:=ImgIndex;
end;
InstallTreeView.EndUpdate;
sl.Free;
UpdateAvailablePackages;
end;
procedure TInstallPkgSetDialog.OnIteratePackages(APackageID: TLazPackageID);
begin
//debugln('TInstallPkgSetDialog.OnIteratePackages ',APackageID.IDAsString);
if (fAvailablePackages.Find(APackageID)=nil) then
fAvailablePackages.Add(APackageID);
end;
function TInstallPkgSetDialog.DependencyToStr(Dependency: TPkgDependency): string;
begin
Result:='';
if Dependency=nil then exit;
if (Dependency.LoadPackageResult=lprSuccess)
and (Dependency.RequiredPackage<>nil) then
Result:=Dependency.RequiredPackage.IDAsString
else
Result:=Dependency.PackageName;
end;
procedure TInstallPkgSetDialog.ClearNewInstalledPackages;
begin
FNewInstalledPackages.Clear;
end;
function TInstallPkgSetDialog.CheckSelection: boolean;
begin
OnCheckInstallPackageList(FNewInstalledPackages,true,Result);
end;
procedure TInstallPkgSetDialog.UpdateButtonStates;
var
Cnt: Integer;
Dependency: TPkgDependency;
s: String;
ListChanged: Boolean;
begin
UninstallButton.Enabled:=InstallTreeView.Selected<>nil;
AddToInstallButton.Enabled:=AvailableTreeView.Selected<>nil;
// check for changes
ListChanged:=false;
Cnt:=0;
Dependency:=OldInstalledPackages;
while Dependency<>nil do begin
s:=Dependency.PackageName;
if not PackageInInstallList(s) then begin
ListChanged:=true;
break;
end;
Dependency:=Dependency.NextRequiresDependency;
inc(Cnt);
end;
if InstallTreeView.Items.TopLvlCount<>Cnt then
ListChanged:=true;
SaveAndExitButton.Enabled:=ListChanged;
SaveAndRebuildButton.Enabled:=ListChanged;
end;
procedure TInstallPkgSetDialog.UpdatePackageInfo(Tree: TTreeView);
var
InfoStr: string;
procedure AddState(const NewState: string);
begin
if (InfoStr<>'') and (InfoStr[length(InfoStr)]<>' ') then
InfoStr:=InfoStr+', ';
InfoStr:=InfoStr+NewState;
end;
var
PkgName: String;
PkgID: TLazPackageID;
Author: String;
Description: String;
PkgLink: TPackageLink;
XMLConfig: TXMLConfig;
begin
if Tree = nil then Exit;
PkgName := '';
if Tree.Selected <> nil then
PkgName := Tree.Selected.Text;
if PkgName = '' then Exit;
if Assigned(FSelectedPkg) and (PkgName = FSelectedPkg.IDAsString) then Exit;
PkgInfoMemo.Clear;
PkgID := TLazPackageID.Create;
try
PkgID.StringToID(PkgName);
FSelectedPkg := PackageGraph.FindPackageWithID(PkgID);
Author:='';
Description:='';
if FSelectedPkg <> nil then begin
Author:=FSelectedPkg.Author;
Description:=FSelectedPkg.Description;
end else begin
// package not loaded -> read values from .lpk
PkgLink:=PkgLinks.FindLinkWithPackageID(PkgID);
if (PkgLink<>nil) and FileExistsCached(PkgLink.GetEffectiveFilename) then begin
// load the package file
try
XMLConfig:=TXMLConfig.Create(PkgLink.GetEffectiveFilename);
try
Author:=XMLConfig.GetValue('Package/Author/Value','');
Description:=XMLConfig.GetValue('Package/Description/Value','');
finally
XMLConfig.Free;
end;
except
on E: Exception do begin
DebugLn('TInstallPkgSetDialog.UpdatePackageInfo ERROR: ',E.Message);
end;
end;
end;
end;
if Author<>'' then
PkgInfoMemo.Lines.Add(lisPckOptsAuthor + ': ' + Author);
if Description<>'' then
PkgInfoMemo.Lines.Add(lisPckOptsDescriptionAbstract
+ ': ' + Description);
if FSelectedPkg<>nil then
begin
PkgInfoMemo.Lines.Add(Format(lisOIPFilename, [FSelectedPkg.Filename]));
InfoStr:=lisCurrentState;
if FSelectedPkg.Installed<>pitNope then
AddState(lisInstalled)
else
AddState(lisNotInstalled);
if FSelectedPkg.AutoCreated then
AddState(lisPckExplAutoCreated);
PkgInfoMemo.Lines.Add(InfoStr);
end;
finally
PkgId.Free;
end;
end;
function TInstallPkgSetDialog.NewInstalledPackagesContains(
APackageID: TLazPackageID): boolean;
begin
Result:=IndexOfNewInstalledPackageID(APackageID)>=0;
end;
function TInstallPkgSetDialog.IndexOfNewInstalledPackageID(
APackageID: TLazPackageID): integer;
begin
Result:=FNewInstalledPackages.Count-1;
while (Result>=0)
and (TLazPackageID(FNewInstalledPackages[Result]).Compare(APackageID)<>0) do
dec(Result);
end;
function TInstallPkgSetDialog.IndexOfNewInstalledPkgByName(
const APackageName: string): integer;
begin
Result:=FNewInstalledPackages.Count-1;
while (Result>=0)
and (CompareText(TLazPackageID(FNewInstalledPackages[Result]).Name,
APackageName)<>0)
do
dec(Result);
end;
procedure TInstallPkgSetDialog.SavePackageListToFile(const AFilename: string);
var
XMLConfig: TXMLConfig;
i: Integer;
LazPackageID: TLazPackageID;
begin
try
XMLConfig:=TXMLConfig.CreateClean(AFilename);
try
XMLConfig.SetDeleteValue('Packages/Count',FNewInstalledPackages.Count,0);
for i:=0 to FNewInstalledPackages.Count-1 do begin
LazPackageID:=TLazPackageID(FNewInstalledPackages[i]);
XMLConfig.SetDeleteValue('Packages/Item'+IntToStr(i)+'/ID',
LazPackageID.IDAsString,'');
end;
InvalidateFileStateCache;
XMLConfig.Flush;
finally
XMLConfig.Free;
end;
except
on E: Exception do begin
MessageDlg(lisCodeToolsDefsWriteError,
Format(lisErrorWritingPackageListToFile, [#13, AFilename, #13, E.Message
]), mtError, [mbCancel], 0);
end;
end;
end;
procedure TInstallPkgSetDialog.LoadPackageListFromFile(const AFilename: string);
function PkgNameExists(List: TObjectList; ID: TLazPackageID): boolean;
var
i: Integer;
LazPackageID: TLazPackageID;
begin
if List<>nil then
for i:=0 to List.Count-1 do begin
LazPackageID:=TLazPackageID(List[i]);
if CompareText(LazPackageID.Name,ID.Name)=0 then begin
Result:=true;
exit;
end;
end;
Result:=false;
end;
var
XMLConfig: TXMLConfig;
i: Integer;
LazPackageID: TLazPackageID;
NewCount: LongInt;
NewList: TObjectList;
ID: String;
begin
NewList:=nil;
LazPackageID:=nil;
try
XMLConfig:=TXMLConfig.Create(AFilename);
try
NewCount:=XMLConfig.GetValue('Packages/Count',0);
LazPackageID:=TLazPackageID.Create;
for i:=0 to NewCount-1 do begin
// get ID
ID:=XMLConfig.GetValue('Packages/Item'+IntToStr(i)+'/ID','');
if ID='' then continue;
// parse ID
if not LazPackageID.StringToID(ID) then continue;
// ignore doubles
if PkgNameExists(NewList,LazPackageID) then continue;
// add
if NewList=nil then NewList:=TObjectList.Create(true);
NewList.Add(LazPackageID);
LazPackageID:=TLazPackageID.Create;
end;
// clean up old list
ClearNewInstalledPackages;
FNewInstalledPackages.Free;
// assign new list
FNewInstalledPackages:=NewList;
NewList:=nil;
UpdateNewInstalledPackages;
UpdateButtonStates;
finally
XMLConfig.Free;
LazPackageID.Free;
NewList.Free;
end;
except
on E: Exception do begin
MessageDlg(lisCodeToolsDefsReadError,
Format(lisErrorReadingPackageListFromFile, [#13, AFilename, #13,
E.Message]), mtError, [mbCancel], 0);
end;
end;
end;
function TInstallPkgSetDialog.ExtractNameFromPkgID(ID: string): string;
var
p: Integer;
begin
p:=1;
while (p<=length(ID)) and IsIdentChar[ID[p]] do inc(p);
Result:=copy(ID,1,p-1);
end;
procedure TInstallPkgSetDialog.AddToInstall;
var
i: Integer;
NewPackageID: TLazPackageID;
j: LongInt;
APackage: TLazPackage;
Additions: TObjectList;
TVNode: TTreeNode;
PkgName: String;
ConflictDep: TPkgDependency;
begin
Additions:=TObjectList.Create(false);
NewPackageID:=TLazPackageID.Create;
try
for i:=0 to AvailableTreeView.Items.TopLvlCount-1 do begin
TVNode:=AvailableTreeView.Items.TopLvlItems[i];
if not TVNode.MultiSelected then continue;
PkgName:=TVNode.Text;
// check string
if not NewPackageID.StringToID(PkgName) then begin
TVNode.Selected:=false;
debugln('TInstallPkgSetDialog.AddToInstallButtonClick invalid ID: ',
PkgName);
continue;
end;
// check if already in list
if NewInstalledPackagesContains(NewPackageID) then begin
MessageDlg(lisDuplicate,
Format(lisThePackageIsAlreadyInTheList, [NewPackageID.Name]), mtError,
[mbCancel],0);
TVNode.Selected:=false;
exit;
end;
// check if a package with same name is already in the list
j:=IndexOfNewInstalledPkgByName(NewPackageID.Name);
if j>=0 then begin
MessageDlg(lisConflict,
Format(lisThereIsAlreadyAPackageInTheList, [NewPackageID.Name]),
mtError,[mbCancel],0);
TVNode.Selected:=false;
exit;
end;
// check if package is loaded and has some attributes that prevents
// installation in the IDE
APackage:=PackageGraph.FindPackageWithID(NewPackageID);
if APackage<>nil then begin
if APackage.PackageType in [lptRunTime,lptRunTimeOnly] then begin
IDEMessageDialog(lisNotADesigntimePackage,
Format(lisThePackageIsNotADesignTimePackageItCanNotBeInstall, [
APackage.IDAsString]), mtError,
[mbCancel]);
TVNode.Selected:=false;
exit;
end;
ConflictDep:=PackageGraph.FindRuntimePkgOnlyRecursively(
APackage.FirstRequiredDependency);
if ConflictDep<>nil then begin
IDEMessageDialog(lisNotADesigntimePackage,
Format(lisThePackageCanNotBeInstalledBecauseItRequiresWhichI, [
APackage.Name, ConflictDep.AsString]),
mtError,[mbCancel]);
TVNode.Selected:=false;
exit;
end;
end;
// ok => add to list
Additions.Add(NewPackageID);
NewPackageID:=TLazPackageID.Create;
end;
// all ok => add to list
for i:=0 to Additions.Count-1 do
FNewInstalledPackages.Add(Additions[i]);
Additions.Clear;
UpdateNewInstalledPackages;
UpdateButtonStates;
finally
// clean up
NewPackageID.Free;
for i:=0 to Additions.Count-1 do
TObject(Additions[i]).Free;
Additions.Free;
end;
end;
procedure TInstallPkgSetDialog.AddToUninstall;
var
i: Integer;
OldPackageID: TLazPackageID;
APackage: TLazPackage;
Deletions: TObjectList;
DelPackageID: TLazPackageID;
j: LongInt;
TVNode: TTreeNode;
PkgName: String;
begin
OldPackageID := nil;
Deletions:=TObjectList.Create(true);
try
for i:=0 to InstallTreeView.Items.TopLvlCount-1 do begin
TVNode:=InstallTreeView.Items.TopLvlItems[i];
if not TVNode.MultiSelected then continue;
if OldPackageID = nil then
OldPackageID:=TLazPackageID.Create;
PkgName:=TVNode.Text;
if not OldPackageID.StringToID(PkgName) then begin
TVNode.Selected:=false;
debugln('TInstallPkgSetDialog.AddToUninstallButtonClick invalid ID: ',
PkgName);
continue;
end;
// ok => add to deletions
Deletions.Add(OldPackageID);
DelPackageID:=OldPackageID;
OldPackageID := nil;
// get package
APackage:=PackageGraph.FindPackageWithID(DelPackageID);
if APackage<>nil then begin
// check if package is a base package
if APackage.AutoCreated
or PackageGraph.IsStaticBasePackage(APackage.Name) then begin
TVNode.Selected:=false;
MessageDlg(lisUninstallImpossible,
Format(lisThePackageCanNotBeUninstalledBecauseItIsNeededByTh, [
APackage.Name]), mtError, [mbCancel], 0);
exit;
end;
end;
end;
// ok => remove from list
InstallTreeView.Selected:=nil;
for i:=0 to Deletions.Count-1 do begin
DelPackageID:=TLazPackageID(Deletions[i]);
j:=IndexOfNewInstalledPackageID(DelPackageID);
FNewInstalledPackages.Delete(j);
end;
UpdateNewInstalledPackages;
UpdateButtonStates;
finally
OldPackageID.Free;
Deletions.Free;
end;
end;
function TInstallPkgSetDialog.GetNewInstalledPackages: TObjectList;
var
i: Integer;
NewPackageID: TLazPackageID;
begin
Result:=TObjectList.Create(true);
for i:=0 to FNewInstalledPackages.Count-1 do begin
NewPackageID:=TLazPackageID.Create;
NewPackageID.AssignID(TLazPackageID(FNewInstalledPackages[i]));
Result.Add(NewPackageID);
end;
end;
end.