IDE: when opening a form with missing design time package: show option to install those packages

git-svn-id: trunk@28080 -
This commit is contained in:
mattias 2010-11-05 00:19:24 +00:00
parent e8b131614c
commit 2bf7963f78
4 changed files with 192 additions and 158 deletions

View File

@ -3539,14 +3539,11 @@ resourcestring
+'old package %s?'; +'old package %s?';
lisPkgMangNewPackage = 'NewPackage'; lisPkgMangNewPackage = 'NewPackage';
lisProbablyYouNeedToInstallSomePackagesForBeforeConti = 'Probably you need ' lisProbablyYouNeedToInstallSomePackagesForBeforeConti = 'Probably you need '
+'to install some packages for before continuing.%s%sWarning:%sThe ' +'to install some packages before continuing.%s%sWarning:%sThe '
+'following units belong to packages ' +'project uses the following design time packages, which might be needed '
+'which are not yet installed in the IDE. If you try to open a form in ' +'to open the form in the designer. If you continue, you might get errors '
+'the IDE, that uses such components, you will get errors about missing ' +'about missing components and the form loading will probably create very '
+'components and the form loading will probably create very unpleasant ' +'unpleasant results.%s%sIt is recommended to cancel and install these packages first.%s%s';
+'results.%s%sThis has no impact on opening the project or any of its '
+'sources.%s%sIt only means: It is a bad idea to open the forms for '
+'designing, before installing the missing packages.%s%s';
lisPackageNeedsInstallation = 'Package needs installation'; lisPackageNeedsInstallation = 'Package needs installation';
lisUnitInPackage = '%s unit %s in package %s%s'; lisUnitInPackage = '%s unit %s in package %s%s';
lisPkgMangSkipThisPackage = 'Skip this package'; lisPkgMangSkipThisPackage = 'Skip this package';

View File

@ -981,12 +981,13 @@ function QuestionDlg(const aCaption, aMsg: string; DlgType: TMsgDlgType;
a caption. The default captions will be used. a caption. The default captions will be used.
Examples for Buttons: Examples for Buttons:
[mrOk,mrCancel,'Cancel now',mrIgnore,300,'Do it'] [mrOk,mrCancel,'Cancel now',mrIgnore,300,'Do it','IsDefault']
This will result in 4 buttons: This will result in 4 buttons:
'Ok' returning mrOk 'Ok' returning mrOk
'Cancel now' returning mrCancel 'Cancel now' returning mrCancel
'Ignore' returning mrIgnore 'Ignore' returning mrIgnore
'Do it' returning 300 'Do it' returning 300. This will be the default button (focused)
} }
var var
QuestionDialog: TQuestionDlg; QuestionDialog: TQuestionDlg;

View File

@ -46,7 +46,7 @@ uses
type type
TOnCheckInstallPackageList = TOnCheckInstallPackageList =
procedure(PkgIDs: TFPList; var Ok: boolean) of object; procedure(PkgIDs: TFPList; out Ok: boolean) of object;
{ TInstallPkgSetDialog } { TInstallPkgSetDialog }
@ -472,7 +472,6 @@ end;
function TInstallPkgSetDialog.CheckSelection: boolean; function TInstallPkgSetDialog.CheckSelection: boolean;
begin begin
Result := False;
OnCheckInstallPackageList(FNewInstalledPackages,Result); OnCheckInstallPackageList(FNewInstalledPackages,Result);
end; end;

View File

@ -157,7 +157,7 @@ type
procedure GetWritablePkgOutputDirectory(APackage: TLazPackage; procedure GetWritablePkgOutputDirectory(APackage: TLazPackage;
var AnOutDirectory: string); var AnOutDirectory: string);
procedure PackageFileLoaded(Sender: TObject); procedure PackageFileLoaded(Sender: TObject);
procedure OnCheckInstallPackageList(PkgIDList: TFPList; var Ok: boolean); procedure OnCheckInstallPackageList(PkgIDList: TFPList; out Ok: boolean);
function LoadDependencyList(FirstDependency: TPkgDependency): TModalResult; function LoadDependencyList(FirstDependency: TPkgDependency): TModalResult;
procedure CreateIDEWindow(Sender: TObject; aFormName: string; procedure CreateIDEWindow(Sender: TObject; aFormName: string;
var AForm: TCustomForm; DoDisableAutoSizing: boolean); var AForm: TCustomForm; DoDisableAutoSizing: boolean);
@ -301,6 +301,8 @@ type
function DoInstallPackage(APackage: TLazPackage): TModalResult; function DoInstallPackage(APackage: TLazPackage): TModalResult;
function DoUninstallPackage(APackage: TLazPackage; function DoUninstallPackage(APackage: TLazPackage;
Flags: TPkgUninstallFlags; ShowAbort: boolean): TModalResult; Flags: TPkgUninstallFlags; ShowAbort: boolean): TModalResult;
function DoInstallPackages(PkgIdList: TFPList; RebuildIDE, Quiet: boolean;
CheckList: boolean = true): TModalResult;
procedure DoTranslatePackage(APackage: TLazPackage); procedure DoTranslatePackage(APackage: TLazPackage);
function DoOpenPackageSource(APackage: TLazPackage): TModalResult; function DoOpenPackageSource(APackage: TLazPackage): TModalResult;
function DoCompileAutoInstallPackages(Flags: TPkgCompileFlags function DoCompileAutoInstallPackages(Flags: TPkgCompileFlags
@ -402,155 +404,20 @@ begin
end; end;
procedure TPkgManager.MainIDEitmPkgEditInstallPkgsClick(Sender: TObject); procedure TPkgManager.MainIDEitmPkgEditInstallPkgsClick(Sender: TObject);
procedure CreateChangeReport(
OldDependencyList, NewDependencyList: TPkgDependency; Report: TStrings);
var
CurDependency: TPkgDependency;
OldDependency: TPkgDependency;
NewDependency: TPkgDependency;
s: String;
begin
// list all packages, that will be installed
CurDependency:=NewDependencyList;
while CurDependency<>nil do begin
s:=CurDependency.AsString;
OldDependency:=FindDependencyByNameInList(OldDependencyList,pdlRequires,
CurDependency.PackageName);
if OldDependency=nil then begin
// newly installed
s:=s+'|'+lisNew;
Report.Add(s);
end;
CurDependency:=CurDependency.NextRequiresDependency;
end;
// list all packages, that will be removed
CurDependency:=OldDependencyList;
while CurDependency<>nil do begin
NewDependency:=FindDependencyByNameInList(NewDependencyList,pdlRequires,
CurDependency.PackageName);
if NewDependency=nil then
// this package will be removed
Report.Add('|'+lisRemove+'|'+CurDependency.AsString);
CurDependency:=CurDependency.NextRequiresDependency;
end;
// list all packages, that are kept
CurDependency:=NewDependencyList;
while CurDependency<>nil do begin
s:=CurDependency.AsString;
OldDependency:=FindDependencyByNameInList(OldDependencyList,pdlRequires,
CurDependency.PackageName);
if OldDependency<>nil then begin
// stay installed
if CurDependency.AsString<>OldDependency.AsString then
s:=s+'|'+lisKeep+'|'+OldDependency.AsString;
Report.Add(s);
end;
CurDependency:=CurDependency.NextRequiresDependency;
end;
end;
var var
RebuildIDE: Boolean; RebuildIDE: Boolean;
PkgIDList: TFPList; PkgIDList: TFPList;
NewFirstAutoInstallDependency: TPkgDependency;
BuildIDEFlags: TBuildLazarusFlags;
ok: boolean;
Report: TStringList;
PkgList: TFPList;
RequiredPackage: TLazPackage;
i: Integer;
CurDependency: TPkgDependency;
begin begin
RebuildIDE:=false; RebuildIDE:=false;
PkgIDList:=nil; PkgIDList:=nil;
NewFirstAutoInstallDependency:=nil;
PkgList:=nil;
try try
if ShowEditInstallPkgsDialog(PackageGraph.FirstAutoInstallDependency, if ShowEditInstallPkgsDialog(PackageGraph.FirstAutoInstallDependency,
@OnCheckInstallPackageList,PkgIDList,RebuildIDE)<>mrOk @OnCheckInstallPackageList,PkgIDList,RebuildIDE)<>mrOk
then exit; then exit;
OnCheckInstallPackageList(PkgIDList,ok); DoInstallPackages(PkgIDList,RebuildIDE,false,true);
if not ok then exit;
// create new auto install dependency PkgIDList
ListPkgIDToDependencyList(PkgIDList,NewFirstAutoInstallDependency,
pdlRequires,Self,true);
PackageGraph.SortDependencyListTopologically(NewFirstAutoInstallDependency,
false);
// tell the user, which packages will stay, which will be removed and
// which will be newly installed
try
Report:=TStringList.Create;
CreateChangeReport(
PackageGraph.FirstAutoInstallDependency,NewFirstAutoInstallDependency,
Report);
if not ConfirmPackageList(Report) then exit;
finally
Report.Free;
end;
// try to commit changes -> replace install list
PackageGraph.BeginUpdate(true);
try
// get all required packages
//debugln('TPkgManager.MainIDEitmPkgEditInstallPkgsClick GetAllRequiredPackages for ',DependencyListAsString(NewFirstAutoInstallDependency,pdlRequires));
if LoadDependencyList(NewFirstAutoInstallDependency)<>mrOk then exit;
PackageGraph.GetAllRequiredPackages(NewFirstAutoInstallDependency,PkgList);
// mark packages for installation
//debugln('TPkgManager.MainIDEitmPkgEditInstallPkgsClick mark packages for installation');
for i:=0 to PkgList.Count-1 do begin
RequiredPackage:=TLazPackage(PkgList[i]);
if RequiredPackage.AutoInstall=pitNope then begin
RequiredPackage.AutoInstall:=pitStatic;
end;
end;
// mark packages for uninstall
//debugln('TPkgManager.MainIDEitmPkgEditInstallPkgsClick mark packages for uninstall');
CurDependency:=PackageGraph.FirstAutoInstallDependency;
while CurDependency<>nil do begin
if (CurDependency.RequiredPackage<>nil)
and (not CurDependency.RequiredPackage.AutoCreated)
and (not PackageGraph.IsStaticBasePackage(CurDependency.PackageName)) then
CurDependency.RequiredPackage.AutoInstall:=pitNope;
CurDependency:=CurDependency.NextRequiresDependency;
end;
// replace install list
//debugln('TPkgManager.MainIDEitmPkgEditInstallPkgsClick replace install list');
FreeDependencyList(PackageGraph.FirstAutoInstallDependency,pdlRequires);
PackageGraph.FirstAutoInstallDependency:=NewFirstAutoInstallDependency;
NewFirstAutoInstallDependency:=nil;
finally
PackageGraph.EndUpdate;
end;
// save package list
//debugln('TPkgManager.MainIDEitmPkgEditInstallPkgsClick save package list');
PackageGraph.SortAutoInstallDependencies;
SaveAutoInstallDependencies(true);
// save IDE build configs, so user can build IDE on command line
BuildIDEFlags:=[blfWithStaticPackages,blfDontClean,blfOnlyIDE,
blfWithoutCompilingIDE];
if MainIDE.DoSaveBuildIDEConfigs(BuildIDEFlags)<>mrOk then exit;
if RebuildIDE then begin
// rebuild Lazarus
if MainIDE.DoBuildLazarus(BuildIDEFlags)<>mrOk then exit;
end;
finally finally
if PkgIDList<>nil then FreeListObjects(PkgIDList,true); if PkgIDList<>nil then FreeListObjects(PkgIDList,true);
FreeDependencyList(NewFirstAutoInstallDependency,pdlRequires);
PkgList.Free;
end; end;
end; end;
@ -631,7 +498,7 @@ begin
end; end;
procedure TPkgManager.OnCheckInstallPackageList(PkgIDList: TFPList; procedure TPkgManager.OnCheckInstallPackageList(PkgIDList: TFPList;
var Ok: boolean); out Ok: boolean);
var var
NewFirstAutoInstallDependency: TPkgDependency; NewFirstAutoInstallDependency: TPkgDependency;
PkgList: TFPList; PkgList: TFPList;
@ -2160,6 +2027,7 @@ var
i: Integer; i: Integer;
PkgFile: TPkgFile; PkgFile: TPkgFile;
Msg: String; Msg: String;
PkgList: TFPList;
begin begin
Result:=mrOk; Result:=mrOk;
MissingUnits:=PackageGraph.FindNotInstalledRegisterUnits(nil, MissingUnits:=PackageGraph.FindNotInstalledRegisterUnits(nil,
@ -2168,15 +2036,31 @@ begin
if Interactive then begin if Interactive then begin
Msg:=Format(lisProbablyYouNeedToInstallSomePackagesForBeforeConti, [#13, Msg:=Format(lisProbablyYouNeedToInstallSomePackagesForBeforeConti, [#13,
#13, #13, #13, #13, #13, #13, #13, #13]); #13, #13, #13, #13, #13, #13, #13, #13]);
PkgList:=TFPList.Create;
try
for i:=0 to MissingUnits.Count-1 do begin for i:=0 to MissingUnits.Count-1 do begin
PkgFile:=TPkgFile(MissingUnits[i]); PkgFile:=TPkgFile(MissingUnits[i]);
if PkgList.IndexOf(PkgFile.LazPackage)<0 then
PkgList.Add(PkgFile.LazPackage);
Msg:=Format(lisUnitInPackage, [Msg, PkgFile.Unit_Name, Msg:=Format(lisUnitInPackage, [Msg, PkgFile.Unit_Name,
PkgFile.LazPackage.IDAsString, #13]); PkgFile.LazPackage.IDAsString, #13]);
end; end;
Result:=IDEMessageDialog(lisPackageNeedsInstallation, Result:=IDEQuestionDialog(lisPackageNeedsInstallation,
Msg,mtWarning,[mbIgnore,mbCancel]); Msg,mtWarning,[mrIgnore,'Continue without install',mrYes,'Install these packages',mrCancel,'Cancel','IsDefault']);
if Result<>mrIgnore then if Result=mrIgnore then begin
// continue
end else if Result=mrYes then
begin
// install
DoInstallPackages(PkgList,true,false);
Result:=mrAbort;
end else begin
// do not warn again
AProject.AutoOpenDesignerFormsDisabled:=true; AProject.AutoOpenDesignerFormsDisabled:=true;
end;
finally
PkgList.Free;
end;
end else end else
Result:=mrCancel; Result:=mrCancel;
MissingUnits.Free; MissingUnits.Free;
@ -3843,6 +3727,159 @@ begin
Result:=mrOk; Result:=mrOk;
end; end;
function TPkgManager.DoInstallPackages(PkgIdList: TFPList; RebuildIDE,
Quiet: boolean; CheckList: boolean): TModalResult;
procedure CreateChangeReport(
OldDependencyList, NewDependencyList: TPkgDependency; Report: TStrings);
var
CurDependency: TPkgDependency;
OldDependency: TPkgDependency;
NewDependency: TPkgDependency;
s: String;
begin
// list all packages, that will be installed
CurDependency:=NewDependencyList;
while CurDependency<>nil do begin
s:=CurDependency.AsString;
OldDependency:=FindDependencyByNameInList(OldDependencyList,pdlRequires,
CurDependency.PackageName);
if OldDependency=nil then begin
// newly installed
s:=s+'|'+lisNew;
Report.Add(s);
end;
CurDependency:=CurDependency.NextRequiresDependency;
end;
// list all packages, that will be removed
CurDependency:=OldDependencyList;
while CurDependency<>nil do begin
NewDependency:=FindDependencyByNameInList(NewDependencyList,pdlRequires,
CurDependency.PackageName);
if NewDependency=nil then
// this package will be removed
Report.Add('|'+lisRemove+'|'+CurDependency.AsString);
CurDependency:=CurDependency.NextRequiresDependency;
end;
// list all packages, that are kept
CurDependency:=NewDependencyList;
while CurDependency<>nil do begin
s:=CurDependency.AsString;
OldDependency:=FindDependencyByNameInList(OldDependencyList,pdlRequires,
CurDependency.PackageName);
if OldDependency<>nil then begin
// stay installed
if CurDependency.AsString<>OldDependency.AsString then
s:=s+'|'+lisKeep+'|'+OldDependency.AsString;
Report.Add(s);
end;
CurDependency:=CurDependency.NextRequiresDependency;
end;
end;
var
NewFirstAutoInstallDependency: TPkgDependency;
BuildIDEFlags: TBuildLazarusFlags;
ok: boolean;
Report: TStringList;
PkgList: TFPList;
RequiredPackage: TLazPackage;
i: Integer;
CurDependency: TPkgDependency;
begin
Result:=mrCancel;
NewFirstAutoInstallDependency:=nil;
PkgList:=nil;
try
if CheckList then
begin
OnCheckInstallPackageList(PkgIDList,ok);
if not ok then exit(mrCancel);
end;
// create new auto install dependency PkgIDList
ListPkgIDToDependencyList(PkgIDList,NewFirstAutoInstallDependency,
pdlRequires,Self,true);
PackageGraph.SortDependencyListTopologically(NewFirstAutoInstallDependency,
false);
if not Quiet then
begin
// tell the user, which packages will stay, which will be removed and
// which will be newly installed
try
Report:=TStringList.Create;
CreateChangeReport(
PackageGraph.FirstAutoInstallDependency,NewFirstAutoInstallDependency,
Report);
if not ConfirmPackageList(Report) then exit(mrCancel);
finally
Report.Free;
end;
end;
// try to commit changes -> replace install list
PackageGraph.BeginUpdate(true);
try
// get all required packages
//debugln('TPkgManager.MainIDEitmPkgEditInstallPkgsClick GetAllRequiredPackages for ',DependencyListAsString(NewFirstAutoInstallDependency,pdlRequires));
if LoadDependencyList(NewFirstAutoInstallDependency)<>mrOk then exit(mrCancel);
PackageGraph.GetAllRequiredPackages(NewFirstAutoInstallDependency,PkgList);
// mark packages for installation
//debugln('TPkgManager.MainIDEitmPkgEditInstallPkgsClick mark packages for installation');
for i:=0 to PkgList.Count-1 do begin
RequiredPackage:=TLazPackage(PkgList[i]);
if RequiredPackage.AutoInstall=pitNope then begin
RequiredPackage.AutoInstall:=pitStatic;
end;
end;
// mark packages for uninstall
//debugln('TPkgManager.MainIDEitmPkgEditInstallPkgsClick mark packages for uninstall');
CurDependency:=PackageGraph.FirstAutoInstallDependency;
while CurDependency<>nil do begin
if (CurDependency.RequiredPackage<>nil)
and (not CurDependency.RequiredPackage.AutoCreated)
and (not PackageGraph.IsStaticBasePackage(CurDependency.PackageName)) then
CurDependency.RequiredPackage.AutoInstall:=pitNope;
CurDependency:=CurDependency.NextRequiresDependency;
end;
// replace install list
//debugln('TPkgManager.MainIDEitmPkgEditInstallPkgsClick replace install list');
FreeDependencyList(PackageGraph.FirstAutoInstallDependency,pdlRequires);
PackageGraph.FirstAutoInstallDependency:=NewFirstAutoInstallDependency;
NewFirstAutoInstallDependency:=nil;
finally
PackageGraph.EndUpdate;
end;
// save package list
//debugln('TPkgManager.MainIDEitmPkgEditInstallPkgsClick save package list');
PackageGraph.SortAutoInstallDependencies;
SaveAutoInstallDependencies(true);
// save IDE build configs, so user can build IDE on command line
BuildIDEFlags:=[blfWithStaticPackages,blfDontClean,blfOnlyIDE,
blfWithoutCompilingIDE];
if MainIDE.DoSaveBuildIDEConfigs(BuildIDEFlags)<>mrOk then exit(mrCancel);
if RebuildIDE then begin
// rebuild Lazarus
if MainIDE.DoBuildLazarus(BuildIDEFlags)<>mrOk then exit(mrCancel);
end;
finally
FreeDependencyList(NewFirstAutoInstallDependency,pdlRequires);
PkgList.Free;
end;
Result:=mrOk;
end;
function TPkgManager.DoOpenPackageSource(APackage: TLazPackage): TModalResult; function TPkgManager.DoOpenPackageSource(APackage: TLazPackage): TModalResult;
var var
Filename: String; Filename: String;