implemented broken dependencies dialog

git-svn-id: trunk@4052 -
This commit is contained in:
mattias 2003-04-13 13:45:04 +00:00
parent 1f7808ff3a
commit 51365b3a35
13 changed files with 486 additions and 86 deletions

View File

@ -35,6 +35,10 @@ unit IDEComp;
{ $DEFINE INTERBASE}
{$IFDEF INTERBASE}
{$linklib crypt}
{$ENDIF}
interface
uses

View File

@ -354,6 +354,8 @@ type
function DoInitProjectRun: TModalResult; virtual; abstract;
function DoOpenMacroFile(Sender: TObject;
const AFilename: string): TModalResult; virtual;
function DoCheckCreatingFile(const AFilename: string;
CheckReadable: boolean): TModalResult; virtual;
function DoCheckFilesOnDisk: TModalResult; virtual; abstract;
function DoCheckAmbigiousSources(const AFilename: string;
@ -1351,6 +1353,61 @@ begin
[ofOnlyIfExists,ofAddToRecent,ofRegularFile,ofConvertMacros]);
end;
{-------------------------------------------------------------------------------
function TMainIDEBar.DoCheckCreatingFile(const AFilename: string;
CheckReadable: boolean): TModalResult;
-------------------------------------------------------------------------------}
function TMainIDEBar.DoCheckCreatingFile(const AFilename: string;
CheckReadable: boolean): TModalResult;
var
fs: TFileStream;
c: char;
begin
// create if not yet done
if not FileExists(AFilename) then begin
try
fs:=TFileStream.Create(AFilename,fmCreate);
fs.Free;
except
Result:=MessageDlg('Unable to create file',
'Unable to create file "'+AFilename+'".',mtError,[mbCancel,mbAbort],0);
exit;
end;
end;
// check writable
try
if CheckReadable then
fs:=TFileStream.Create(AFilename,fmOpenWrite)
else
fs:=TFileStream.Create(AFilename,fmOpenReadWrite);
try
fs.Seek(0,soEnd);
fs.Write(' ',1);
finally
fs.Free;
end;
except
Result:=MessageDlg('Unable to write file',
'Unable to write file "'+AFilename+'".',mtError,[mbCancel,mbAbort],0);
exit;
end;
// check readable
try
fs:=TFileStream.Create(AFilename,fmOpenReadWrite);
try
fs.Seek(-1,soEnd);
fs.Read(c,1);
finally
fs.Free;
end;
except
Result:=MessageDlg('Unable to read file',
'Unable to read file "'+AFilename+'".',mtError,[mbCancel,mbAbort],0);
exit;
end;
Result:=mrOk;
end;
{-------------------------------------------------------------------------------
function TMainIDEBar.DoCheckAmbigiousSources(const AFilename: string
): TModalResult;

View File

@ -1207,7 +1207,21 @@ begin
if Result=mrAbort then exit;
end;
confPath:=SetDirSeparators(confPath);
xmlconfig := TXMLConfig.Create(confPath);
try
ClearFile(confPath,true);
xmlconfig := TXMLConfig.Create(confPath);
except
on E: Exception do begin
writeln('ERROR: ',E.Message);
MessageDlg('Write error',
'Unable to write the project info file'#13
+'"'+ProjectInfoFile+'".'#13
+'Error: '+E.Message
,mtError,[mbOk],0);
Result:=mrCancel;
exit;
end;
end;
UpdateUsageCounts;
repeat
@ -2282,6 +2296,9 @@ end.
{
$Log$
Revision 1.103 2003/04/13 13:45:04 mattias
implemented broken dependencies dialog
Revision 1.102 2003/04/07 23:49:03 mattias
implemented adding units to packages

View File

@ -215,6 +215,9 @@ type
property Item[const AIndex: Integer]: TListItem read GetItem write SetItem; default;
property Owner : TCustomListView read FOwner;
end;
{ TListColumn }
TWidth = 0..MaxInt;
@ -254,6 +257,9 @@ type
property Visible : Boolean read FVisible write SetVisible;
property Width: TWidth read GetWidth write SetWidth;
end;
{ TListColumns }
TListColumns = class(TCollection)
private
@ -270,6 +276,9 @@ type
read GetItem write SetItem; default;
procedure Assign(Source: TPersistent); override;
end;
{ TCustomListView }
TItemChange = (ctText, ctImage, ctState);
TViewStyle = (vsList,vsReport);
@ -374,8 +383,11 @@ type
procedure EndUpdate;
property Selected: TListItem read GetSelection write SetSelection;
end;
{ TListView }
TListView = class(TCustomListView)
TListView = class(TCustomListView)
published
property Align;
property Anchors;
@ -1742,6 +1754,9 @@ end.
{ =============================================================================
$Log$
Revision 1.71 2003/04/13 13:45:04 mattias
implemented broken dependencies dialog
Revision 1.70 2003/04/08 16:56:55 mattias
implemented saving package

View File

@ -41,22 +41,28 @@ uses
LMessages, Forms, Controls, GraphType, Graphics, Buttons, StdCtrls;
//type
// TDialogButtons = (mbYes, mbNo, mbOK, mbCancel, mbAbort, mbRetry,
// mbIgnore, mbAll, mbNoToAll, mbYesToAll, mbHelp);
// TDialogButtonsSet = set of TDialogButtons;
type
TMsgDlgType = (mtWarning, mtError, mtInformation, mtConfirmation,
mtCustom);
TMsgDlgBtn = (mbYes, mbNo, mbOK, mbCancel, mbAbort, mbRetry, mbIgnore,
mbAll, mbNoToAll, mbYesToAll, mbHelp);
TMsgDlgButtons = set of TMsgDlgBtn;
TMsgDlgType = (mtWarning, mtError, mtInformation, mtConfirmation,
mtCustom);
TMsgDlgBtn = (mbYes, mbNo, mbOK, mbCancel, mbAbort, mbRetry, mbIgnore,
mbAll, mbNoToAll, mbYesToAll, mbHelp, mbClose);
TMsgDlgButtons = set of TMsgDlgBtn;
const
mbYesNoCancel = [mbYes, mbNo, mbCancel];
mbOKCancel = [mbOK, mbCancel];
mbAbortRetryIgnore = [mbAbort, mbRetry, mbIgnore];
mbYesNoCancel = [mbYes, mbNo, mbCancel];
mbOKCancel = [mbOK, mbCancel];
mbAbortRetryIgnore = [mbAbort, mbRetry, mbIgnore];
MsgDlgBtnToBitBtnKind: array[TMsgDlgBtn] of TBitBtnKind = (
bkYes, bkNo, bkOK, bkCancel, bkAbort, bkRetry, bkIgnore,
bkAll, bkNoToAll, bkYesToAll, bkHelp, bkClose
);
BitBtnKindToMsgDlgBtn: array[TBitBtnKind] of TMsgDlgBtn = (
mbOk, mbOK, mbCancel, mbHelp, mbYes, mbNo,
mbClose, mbAbort, mbRetry, mbIgnore, mbAll, mbNoToALl, mbYesToAll
);
type
@ -340,6 +346,9 @@ end.
{ =============================================================================
$Log$
Revision 1.30 2003/04/13 13:45:04 mattias
implemented broken dependencies dialog
Revision 1.29 2003/04/08 09:04:07 mattias
fixed registration for fpc 1.0.x

View File

@ -102,7 +102,8 @@ const
ButtonIds : Array[TMsgDlgbtn] of Longint = (idButtonYes, idButtonNo,
idButtonOK, idButtonCancel, idButtonAbort, idButtonRetry, idButtonIgnore,
idButtonAll, idButtonNoToAll, idButtonYesToAll, idButtonHelp);
idButtonAll, idButtonNoToAll, idButtonYesToAll, idButtonHelp,
idButtonClose);
DialogResults : Array[idButtonOK..idButtonNoToAll] of TModalResult = (
mrOk, mrCancel, mrOk{CLOSE!!}, mrYes, mrNo, -1{HELP!!}, mrAbort, mrRetry,
@ -232,6 +233,9 @@ end;
{
$Log$
Revision 1.22 2003/04/13 13:45:04 mattias
implemented broken dependencies dialog
Revision 1.21 2002/10/25 14:59:11 lazarus
AJ: MessageDlgs -> PromptUser, better Cancel/Default order

View File

@ -48,7 +48,8 @@ uses
type
TPkgSaveFlag = (
psfSaveAs
psfSaveAs,
pfAskBeforeSaving
);
TPkgSaveFlags = set of TPkgSaveFlag;
@ -74,6 +75,9 @@ type
Flags: TPkgOpenFlags): TModalResult; virtual; abstract;
function DoSavePackage(APackage: TLazPackage;
Flags: TPkgSaveFlags): TModalResult; virtual; abstract;
function DoSaveAllPackages(Flags: TPkgSaveFlags): TModalResult; virtual; abstract;
function DoClosePackageEditor(APackage: TLazPackage): TModalResult; virtual; abstract;
function DoCloseAllPackageEditors: TModalResult; virtual; abstract;
end;
var

View File

@ -216,6 +216,7 @@ type
procedure Assign(Source: TPkgDependency);
procedure ConsistencyCheck;
function IsCompatible(Pkg: TLazPackageID): boolean;
procedure MakeCompatible(const PkgName: string; const Version: TPkgVersion);
function AsString: string;
function NextUsedByDependency: TPkgDependency;
function PrevUsedByDependency: TPkgDependency;
@ -290,7 +291,8 @@ type
// (for example because it is Installed or an Installed
// package requires this package)
lpfVisited, // Used by the PackageGraph to avoid double checking
lpfDestroying // set during destruction
lpfDestroying, // set during destruction
lpfSkipSaving
);
TLazPackageFlags = set of TLazPackageFlag;
@ -326,7 +328,6 @@ type
FIconFile: string;
FInstalled: TPackageInstallType;
FModifiedLock: integer;
FOnChangeName: TPkgChangeNameEvent;
FPackageEditor: TBasePackageEditor;
FPackageType: TLazPackageType;
FReadOnly: boolean;
@ -402,6 +403,7 @@ type
function Requires(APackage: TLazPackage): boolean;
procedure AddUsedByDependency(Dependency: TPkgDependency);
procedure RemoveUsedByDependency(Dependency: TPkgDependency);
procedure ChangeID(const NewName: string; NewVersion: TPkgVersion);
public
property AddDependCompilerOptions: TAdditionalCompilerOptions
read FAddDependCompilerOptions;
@ -430,7 +432,6 @@ type
property Installed: TPackageInstallType read FInstalled write SetInstalled;
property Registered: boolean read FRegistered write SetRegistered;
property Modified: boolean read GetModified write SetModified;
property OnChangeName: TPkgChangeNameEvent read FOnChangeName write FOnChangeName;
property PackageType: TLazPackageType
read FPackageType write SetPackageType;
property ReadOnly: boolean read FReadOnly write SetReadOnly;
@ -467,7 +468,7 @@ const
'RunTime', 'DesignTime', 'RunAndDesignTime');
LazPackageFlagNames: array[TLazPackageFlag] of string = (
'lpfAutoIncrementVersionOnBuild', 'lpfModified', 'lpfAutoUpdate',
'lpfNeeded', 'lpfVisited', 'lpfDestroying');
'lpfNeeded', 'lpfVisited', 'lpfDestroying', 'lpfSkipSaving');
var
// All TPkgDependency are added to this AVL tree (sorted for names, not version!)
@ -1002,6 +1003,14 @@ begin
Result:=IsCompatible(Pkg.Name,Pkg.Version);
end;
procedure TPkgDependency.MakeCompatible(const PkgName: string;
const Version: TPkgVersion);
begin
PackageName:=PkgName;
if MinVersion.Compare(Version)>0 then MinVersion.Assign(Version);
if MaxVersion.Compare(Version)<0 then MaxVersion.Assign(Version);
end;
function TPkgDependency.AsString: string;
begin
Result:=FPackageName;
@ -1309,16 +1318,13 @@ begin
Include(FFlags,lpfModified)
else
Exclude(FFlags,lpfModified);
Exclude(FFlags,lpfSkipSaving);
end;
procedure TLazPackage.SetName(const AValue: string);
var
OldName: String;
begin
if FName=AValue then exit;
OldName:=FName;
FName:=AValue;
if Assigned(OnChangeName) then OnChangeName(Self,OldName);
Modified:=true;
end;
@ -1836,6 +1842,12 @@ begin
Dependency.RemoveFromList(FFirstUsedByDependency,pdlUsedBy);
end;
procedure TLazPackage.ChangeID(const NewName: string; NewVersion: TPkgVersion);
begin
Version.Assign(NewVersion);
Name:=NewName;
end;
{ TPkgComponent }
procedure TPkgComponent.SetPkgFile(const AValue: TPkgFile);

View File

@ -49,7 +49,8 @@ type
TOnOpenPackage =
function(Sender: TObject; APackage: TLazPackage): TModalResult of object;
TOnSavePackage =
function(Sender: TObject; APackage: TLazPackage): TModalResult of object;
function(Sender: TObject; APackage: TLazPackage;
SaveAs: boolean): TModalResult of object;
TOnCreateNewPkgFile =
function(Sender: TObject;
const Params: TAddToPkgResult): TModalResult of object;
@ -109,6 +110,7 @@ type
ARect: TRect; State: TOwnerDrawState);
procedure RemoveBitBtnClick(Sender: TObject);
procedure SaveBitBtnClick(Sender: TObject);
procedure SaveAsClick(Sender: TObject);
procedure UseMaxVersionCheckBoxClick(Sender: TObject);
procedure UseMinVersionCheckBoxClick(Sender: TObject);
private
@ -133,7 +135,7 @@ type
public
constructor Create(TheOwner: TComponent); override;
destructor Destroy; override;
procedure DoSave;
procedure DoSave(SaveAs: boolean);
public
property LazPackage: TLazPackage read FLazPackage write SetLazPackage;
end;
@ -167,7 +169,7 @@ type
procedure DoFreeEditor(Pkg: TLazPackage);
function CreateNewFile(Sender: TObject;
const Params: TAddToPkgResult): TModalResult;
function SavePackage(APackage: TLazPackage): TModalResult;
function SavePackage(APackage: TLazPackage; SaveAs: boolean): TModalResult;
public
property Editors[Index: integer]: TPackageEditorForm read GetEditors;
property OnCreateNewFile: TOnCreateNewPkgFile read FOnCreateNewFile
@ -321,6 +323,7 @@ begin
AddPopupMenuItem('-',nil,true);
AddPopupMenuItem('Save',@SaveBitBtnClick,SaveBitBtn.Enabled);
AddPopupMenuItem('Save As',@SaveAsClick,not LazPackage.AutoCreated);
AddPopupMenuItem('Compile',@CompileBitBtnClick,CompileBitBtn.Enabled);
AddPopupMenuItem('Add',@AddBitBtnClick,AddBitBtn.Enabled);
AddPopupMenuItem('Remove',@RemoveBitBtnClick,RemoveBitBtn.Enabled);
@ -410,7 +413,7 @@ begin
+'Save package?',
mtConfirmation,[mbYes,mbNo,mbAbort],0);
if MsgResult=mrYes then begin
MsgResult:=PackageEditors.SavePackage(LazPackage);
MsgResult:=PackageEditors.SavePackage(LazPackage,false);
end;
if MsgResult=mrAbort then CanClose:=false;
end;
@ -505,7 +508,12 @@ end;
procedure TPackageEditorForm.SaveBitBtnClick(Sender: TObject);
begin
DoSave;
DoSave(false);
end;
procedure TPackageEditorForm.SaveAsClick(Sender: TObject);
begin
DoSave(true);
end;
procedure TPackageEditorForm.UseMaxVersionCheckBoxClick(Sender: TObject);
@ -830,7 +838,7 @@ begin
with CompilerOptionsBitBtn do begin
Name:='CompilerOptionsBitBtn';
Parent:=Self;
Caption:='Compiler Options';
Caption:='Comp. Opts.';
OnClick:=@CompilerOptionsBitBtnClick;
Hint:='Edit Options to compile package';
ShowHint:=true;
@ -1283,9 +1291,9 @@ begin
end;
end;
procedure TPackageEditorForm.DoSave;
procedure TPackageEditorForm.DoSave(SaveAs: boolean);
begin
PackageEditors.SavePackage(LazPackage);
PackageEditors.SavePackage(LazPackage,SaveAs);
UpdateButtons;
UpdateTitle;
UpdateStatusBar;
@ -1404,9 +1412,10 @@ begin
Result:=OnCreateNewFile(Sender,Params);
end;
function TPackageEditors.SavePackage(APackage: TLazPackage): TModalResult;
function TPackageEditors.SavePackage(APackage: TLazPackage;
SaveAs: boolean): TModalResult;
begin
if Assigned(OnSavePackage) then Result:=OnSavePackage(Self,APackage);
if Assigned(OnSavePackage) then Result:=OnSavePackage(Self,APackage,SaveAs);
end;
initialization

View File

@ -67,6 +67,7 @@ const
type
TPkgAddedEvent = procedure(APackage: TLazPackage) of object;
TPkgDeleteEvent = procedure(APackage: TLazPackage) of object;
TDependencyModifiedEvent = procedure(ADependency: TPkgDependency) of object;
TLazPackageGraph = class
private
@ -79,6 +80,7 @@ type
FOnBeginUpdate: TNotifyEvent;
FOnChangePackageName: TPkgChangeNameEvent;
FOnDeletePackage: TPkgDeleteEvent;
FOnDependencyModified: TDependencyModifiedEvent;
FOnEndUpdate: TNotifyEvent;
FRegistrationFile: TPkgFile;
FRegistrationPackage: TLazPackage;
@ -134,6 +136,11 @@ type
procedure ClosePackage(APackage: TLazPackage);
procedure MarkNeededPackages;
procedure CloseUnneededPackages;
procedure ChangePackageID(APackage: TLazPackage;
const NewName: string; NewVersion: TPkgVersion;
RenameDependencies: boolean);
function GetBrokenDependenciesWhenChangingPkgID(APackage: TLazPackage;
const NewName: string; NewVersion: TPkgVersion): TList;
function CheckIfPackageCanBeClosed(APackage: TLazPackage): boolean;
function PackageIsNeeded(APackage: TLazPackage): boolean;
procedure RegisterStaticPackages;
@ -157,7 +164,10 @@ type
property OnBeginUpdate: TNotifyEvent read FOnBeginUpdate write FOnBeginUpdate;
property OnChangePackageName: TPkgChangeNameEvent read FOnChangePackageName
write FOnChangePackageName;
property OnDeletePackage: TPkgDeleteEvent read FOnDeletePackage write FOnDeletePackage;
property OnDependencyModified: TDependencyModifiedEvent
read FOnDependencyModified write FOnDependencyModified;
property OnDeletePackage: TPkgDeleteEvent read FOnDeletePackage
write FOnDeletePackage;
property OnEndUpdate: TNotifyEvent read FOnEndUpdate write FOnEndUpdate;
property Packages[Index: integer]: TLazPackage read GetPackages; default;
property RegistrationFile: TPkgFile read FRegistrationFile;
@ -724,8 +734,7 @@ begin
BeginUpdate;
FTree.Add(APackage);
FItems.Add(APackage);
APackage.OnChangeName:=@PackageChangedName;
// open all dependencies
Dependency:=APackage.FirstRequiredDependency;
while Dependency<>nil do begin
@ -829,6 +838,83 @@ begin
EndUpdate;
end;
procedure TLazPackageGraph.ChangePackageID(APackage: TLazPackage;
const NewName: string; NewVersion: TPkgVersion; RenameDependencies: boolean);
var
Dependency, FirstUpdateDependency: TPkgDependency;
RequiredPackage: TLazPackage;
ANode: TAVLTreeNode;
NextDependency: TPkgDependency;
OldPkgName: String;
begin
OldPkgName:=APackage.Name;
if (AnsiCompareText(OldPkgName,NewName)=0)
and (APackage.Version.Compare(NewVersion)=0) then begin
// ID does not change
// -> just rename
APackage.Name:=NewName;
exit;
end;
// ID changed
// break or change all dependencies, that became incompatible
Dependency:=APackage.FirstUsedByDependency;
FirstUpdateDependency:=nil;
while Dependency<>nil do begin
NextDependency:=Dependency.NextUsedByDependency;
if not Dependency.IsCompatible(NewName,NewVersion) then begin
if RenameDependencies then begin
Dependency.MakeCompatible(NewName,NewVersion);
if Assigned(OnDependencyModified) then OnDependencyModified(Dependency);
end else begin
Dependency.RequiredPackage:=nil;
Dependency.AddToList(FirstUpdateDependency,pdlUsedBy);
end;
end;
Dependency:=NextDependency;
end;
// change ID
FTree.Remove(APackage);
APackage.ChangeID(NewName,NewVersion);
FTree.Add(APackage);
// update new broken dependencies
while FirstUpdateDependency<>nil do begin
Dependency.RemoveFromList(FirstUpdateDependency,pdlUsedBy);
OpenDependency(Dependency,RequiredPackage);
end;
// update old broken dependencies
ANode:=FindLowestPkgDependencyNodeWithName(NewName);
while ANode<>nil do begin
Dependency:=TPkgDependency(ANode.Data);
if (Dependency.LoadPackageResult<>lprSuccess)
and Dependency.IsCompatible(APackage) then
OpenDependency(Dependency,RequiredPackage);
ANode:=FindNextPkgDependecyNodeWithSameName(ANode);
end;
if Assigned(OnChangePackageName) then
OnChangePackageName(APackage,OldPkgName);
end;
function TLazPackageGraph.GetBrokenDependenciesWhenChangingPkgID(
APackage: TLazPackage; const NewName: string; NewVersion: TPkgVersion
): TList;
var
Dependency: TPkgDependency;
begin
Result:=TList.Create;
// find all dependencies, that will become incompatible
Dependency:=APackage.FirstUsedByDependency;
while Dependency<>nil do begin
if not Dependency.IsCompatible(NewName,NewVersion) then
Result.Add(Dependency);
Dependency:=Dependency.NextUsedByDependency;
end;
end;
function TLazPackageGraph.CheckIfPackageCanBeClosed(APackage: TLazPackage
): boolean;
begin

View File

@ -41,7 +41,7 @@ uses
Classes, SysUtils, LCLProc, LResources, Forms, Controls, Buttons, ComCtrls,
StdCtrls, ExtCtrls, Menus, Dialogs, Graphics, FileCtrl, AVL_Tree,
LazarusIDEStrConsts, IDEProcs, IDEOptionDefs, EnvironmentOpts,
Project, PackageDefs, PackageSystem, PackageEditor;
Project, BrokenDependenciesDlg, PackageDefs, PackageSystem, PackageEditor;
type
TPkgGraphExplorer = class(TForm)
@ -488,7 +488,6 @@ var
Dependency: TPkgDependency;
UsedByDep: TPkgDependency;
sl: TStringList;
DepOwner: TObject;
NewItem: String;
begin
GetDependency(PkgTreeView.Selected,Pkg,Dependency);
@ -498,19 +497,7 @@ begin
UsedByDep:=Pkg.FirstUsedByDependency;
sl:=TStringList.Create;
while UsedByDep<>nil do begin
DepOwner:=UsedByDep.Owner;
if (DepOwner<>nil) then begin
if DepOwner is TLazPackage then begin
NewItem:='Package: '+TLazPackage(DepOwner).IDAsString;
end else if DepOwner is TProject then begin
NewItem:='Project: '
+ExtractFileNameOnly(TProject(DepOwner).ProjectInfoFile);
end else begin
NewItem:=DepOwner.ClassName
end;
end else begin
NewItem:='Dependency without Owner: '+UsedByDep.AsString;
end;
NewItem:=GetDependencyOwnerAsString(UsedByDep);
sl.Add(NewItem);
UsedByDep:=UsedByDep.NextUsedByDependency;
end;

View File

@ -47,9 +47,9 @@ uses
Classes, SysUtils, LCLProc, Forms, Controls, FileCtrl,
Dialogs, Menus, CodeToolManager, CodeCache, Laz_XMLCfg, AVL_Tree,
LazarusIDEStrConsts, KeyMapping, EnvironmentOpts, IDEProcs, ProjectDefs,
InputHistory, IDEDefs, UComponentManMain, PackageEditor, AddToPackageDlg,
PackageDefs, PackageLinks, PackageSystem, ComponentReg, OpenInstalledPkgDlg,
PkgGraphExporer,
InputHistory, IDEDefs, UComponentManMain, Project, ComponentReg,
PackageEditor, AddToPackageDlg, PackageDefs, PackageLinks, PackageSystem,
OpenInstalledPkgDlg, PkgGraphExporer, BrokenDependenciesDlg,
BasePkgManager, MainBar;
type
@ -64,11 +64,12 @@ type
var HasRegisterProc: boolean);
function OnPackageEditorOpenPackage(Sender: TObject; APackage: TLazPackage
): TModalResult;
function OnPackageEditorSavePackage(Sender: TObject;
APackage: TLazPackage): TModalResult;
function OnPackageEditorSavePackage(Sender: TObject; APackage: TLazPackage;
SaveAs: boolean): TModalResult;
procedure PackageGraphChangePackageName(APackage: TLazPackage;
const OldName: string);
procedure PackageGraphDeletePackage(APackage: TLazPackage);
procedure PackageGraphDependencyModified(ADependency: TPkgDependency);
function PackageGraphExplorerOpenPackage(Sender: TObject;
APackage: TLazPackage): TModalResult;
procedure PkgManagerAddPackage(Pkg: TLazPackage);
@ -99,7 +100,10 @@ type
Flags: TPkgOpenFlags): TModalResult; override;
function DoSavePackage(APackage: TLazPackage;
Flags: TPkgSaveFlags): TModalResult; override;
function DoSaveAllPackages(Flags: TPkgSaveFlags): TModalResult; override;
function DoShowPackageGraph: TModalResult;
function DoClosePackageEditor(APackage: TLazPackage): TModalResult; override;
function DoCloseAllPackageEditors: TModalResult; override;
end;
implementation
@ -223,9 +227,12 @@ begin
end;
function TPkgManager.OnPackageEditorSavePackage(Sender: TObject;
APackage: TLazPackage): TModalResult;
APackage: TLazPackage; SaveAs: boolean): TModalResult;
begin
Result:=DoSavePackage(APackage,[]);
if SaveAs then
Result:=DoSavePackage(APackage,[psfSaveAs])
else
Result:=DoSavePackage(APackage,[]);
end;
procedure TPkgManager.PackageGraphChangePackageName(APackage: TLazPackage;
@ -243,6 +250,18 @@ begin
end;
end;
procedure TPkgManager.PackageGraphDependencyModified(ADependency: TPkgDependency
);
var
DepOwner: TObject;
begin
DepOwner:=ADependency.Owner;
if DepOwner is TLazPackage then
TLazPackage(DepOwner).Modified:=true
else if DepOwner is TProject then
TProject(DepOwner).Modified:=true;
end;
function TPkgManager.PackageGraphExplorerOpenPackage(Sender: TObject;
APackage: TLazPackage): TModalResult;
begin
@ -304,6 +323,8 @@ var
ConflictPkg: TLazPackage;
PkgFile: TPkgFile;
LowerFilename: String;
BrokenDependencies: TList;
RenameDependencies: Boolean;
begin
OldPkgFilename:=APackage.Filename;
@ -402,6 +423,22 @@ begin
continue; // try again
end;
// check for broken dependencies
BrokenDependencies:=PackageGraph.GetBrokenDependenciesWhenChangingPkgID(
APackage,NewPkgName,APackage.Version);
RenameDependencies:=false;
try
if BrokenDependencies.Count>0 then begin
Result:=ShowBrokenDependencies(BrokenDependencies,
DefaultBrokenDepButtons);
if Result=mrAbort then exit;
if Result=mrRetry then continue;
if Result=mrYes then RenameDependencies:=true;
end;
finally
BrokenDependencies.Free;
end;
// check existing file
if (CompareFilenames(NewFileName,OldPkgFilename)<>0)
and FileExists(NewFileName) then begin
@ -411,6 +448,10 @@ begin
if Result<>mrOk then exit;
end;
// check if new file is read/writable
Result:=MainIDE.DoCheckCreatingFile(NewFileName,true);
if Result=mrAbort then exit;
until Result<>mrRetry;
finally
InputHistories.StoreFileDialogSettings(SaveDialog);
@ -421,17 +462,9 @@ begin
APackage.Filename:=NewFilename;
// rename package
if NewPkgName<>APackage.Name then begin
if AnsiCompareText(NewPkgName,APackage.Name)=0 then begin
// just change the case
APackage.Name:=NewPkgName;
end else begin
// name change -> update package graph
APackage.Name:=NewPkgName;
// ToDo: update package graph
end;
end;
PackageGraph.ChangePackageID(APackage,NewPkgName,APackage.Version,
RenameDependencies);
// clean up old package file to reduce ambigiousities
if FileExists(OldPkgFilename)
and (CompareFilenames(OldPkgFilename,NewFilename)<>0) then begin
@ -444,8 +477,7 @@ begin
EnvironmentOptions.RecentPackageFiles);
end else begin
MessageDlg('Delete failed',
'Deleting of file "'+OldPkgFilename+'"'
+' failed.',mtError,[mbOk],0);
'Unable to delete file "'+OldPkgFilename+'".',mtError,[mbOk],0);
end;
end;
end;
@ -465,6 +497,7 @@ begin
PackageGraph.OnChangePackageName:=@PackageGraphChangePackageName;
PackageGraph.OnAddPackage:=@PkgManagerAddPackage;
PackageGraph.OnDeletePackage:=@PackageGraphDeletePackage;
PackageGraph.OnDependencyModified:=@PackageGraphDependencyModified;
PackageEditors:=TPackageEditors.Create;
PackageEditors.OnOpenFile:=@MainIDE.DoOpenMacroFile;
@ -579,6 +612,7 @@ begin
NewPackage:=PackageGraph.NewPackage('NewPackage');
NewPackage.AddRequiredDependency(
PackageGraph.FCLPackage.CreateDependencyForThisPkg);
NewPackage.Modified:=false;
// open a package editor
CurEditor:=PackageEditors.OpenEditor(NewPackage);
@ -670,18 +704,29 @@ begin
Result:=mrAbort;
exit;
end;
MainIDE.SaveSourceEditorChangesToCodeCache(-1);
if APackage.IsVirtual then Include(Flags,psfSaveAs);
// check if package needs saving
if (not (psfSaveAs in Flags)) and (not APackage.ReadOnly)
and (not APackage.Modified)
if (not (psfSaveAs in Flags))
and (not APackage.ReadOnly) and (not APackage.Modified)
and FileExists(APackage.Filename) then begin
Result:=mrOk;
exit;
end;
// ask user if package should be saved
if pfAskBeforeSaving in Flags then begin
Result:=MessageDlg('Save package?',
'Package "'+APackage.IDAsString+'" changed. Save?',
mtConfirmation,[mbYes,mbNo,mbAbort],0);
if (Result=mrNo) then Result:=mrIgnore;
if Result<>mrOk then exit;
end;
// save editor files to codetools
MainIDE.SaveSourceEditorChangesToCodeCache(-1);
// save package
if (psfSaveAs in Flags) then begin
Result:=DoShowSavePackageAsDialog(APackage);
@ -697,6 +742,7 @@ begin
// save
try
ClearFile(APackage.Filename,true);
XMLConfig:=TXMLConfig.Create(APackage.Filename);
try
XMLConfig.Clear;
@ -709,12 +755,13 @@ begin
on E: Exception do begin
Result:=MessageDlg('Error Writing Package',
'Unable to write package "'+APackage.IDAsString+'"'#13
+'to file "'+APackage.Filename+'".',
+'to file "'+APackage.Filename+'".'#13
+'Error: '+E.Message,
mtError,[mbAbort,mbCancel],0);
exit;
end;
end;
// success
APackage.Modified:=false;
// add to recent
@ -735,5 +782,58 @@ begin
Result:=mrOk;
end;
function TPkgManager.DoCloseAllPackageEditors: TModalResult;
var
APackage: TLazPackage;
begin
while PackageEditors.Count>0 do begin
APackage:=PackageEditors.Editors[PackageEditors.Count-1].LazPackage;
Result:=DoClosePackageEditor(APackage);
if Result<>mrOk then exit;
end;
Result:=mrOk;
end;
function TPkgManager.DoClosePackageEditor(APackage: TLazPackage): TModalResult;
begin
if APackage.Editor<>nil then begin
APackage.Editor.Free;
end;
Result:=mrOk;
end;
function TPkgManager.DoSaveAllPackages(Flags: TPkgSaveFlags): TModalResult;
var
AllSaved: Boolean;
i: Integer;
CurPackage: TLazPackage;
begin
try
repeat
AllSaved:=true;
i:=0;
while i<PackageGraph.Count do begin
CurPackage:=PackageGraph[i];
if CurPackage.Modified and (not CurPackage.ReadOnly)
and (not (lpfSkipSaving in CurPackage.Flags)) then begin
Result:=DoSavePackage(CurPackage,Flags);
if Result=mrIgnore then
CurPackage.Flags:=CurPackage.Flags+[lpfSkipSaving];
if Result<>mrOk then exit;
AllSaved:=false;
end;
inc(i);
end;
until AllSaved;
finally
// clear all lpfSkipSaving flags
for i:=0 to PackageGraph.Count-1 do begin
CurPackage:=PackageGraph[i];
CurPackage.Flags:=CurPackage.Flags-[lpfSkipSaving];
end;
end;
Result:=mrOk;
end;
end.

View File

@ -39,8 +39,8 @@ interface
uses
Classes, SysUtils, Forms, Controls, Buttons, LResources, ExtCtrls, StdCtrls,
Spin, Dialogs, PathEditorDlg, IDEProcs, IDEOptionDefs,
PackageDefs, PackageSystem;
Spin, Dialogs, PathEditorDlg, IDEProcs, IDEOptionDefs, LazarusIDEStrConsts,
BrokenDependenciesDlg, PackageDefs, PackageSystem;
type
TPackageOptionsDialog = class(TForm)
@ -89,6 +89,9 @@ type
procedure AddOptionsGroupBoxResize(Sender: TObject);
procedure AddPathsGroupBoxResize(Sender: TObject);
procedure DescriptionPageResize(Sender: TObject);
procedure OkButtonClick(Sender: TObject);
procedure PackageOptionsDialogClose(Sender: TObject;
var Action: TCloseAction);
procedure PackageOptionsDialogResize(Sender: TObject);
procedure PathEditBtnClick(Sender: TObject);
procedure PathEditBtnExecuted(Sender: TObject);
@ -104,6 +107,7 @@ type
procedure ReadOptionsFromPackage;
procedure ReadPkgTypeFromPackage;
function GetEditForPathButton(AButton: TPathEditorButton): TEdit;
procedure ShowMsgPackageTypeMustBeDesign;
public
constructor Create(TheOwner: TComponent); override;
destructor Destroy; override;
@ -196,12 +200,7 @@ begin
then begin
// user sets to runtime only
if (LazPackage.AutoInstall<>pitNope) then begin
MessageDlg('Invalid package type',
'The package "'+LazPackage.IDAsString+'" has the auto install flag.'#13
+'This means it will be installed in the IDE. Installation packages'#13
+'must be designtime Packages.',
mtError,[mbCancel],0);
ReadPkgTypeFromPackage;
ShowMsgPackageTypeMustBeDesign;
end;
end;
end;
@ -296,6 +295,89 @@ begin
SetBounds(x,y,w,90);
end;
procedure TPackageOptionsDialog.OkButtonClick(Sender: TObject);
var
NewPackageType: TLazPackageType;
NewVersion: TPkgVersion;
BrokenDependencies: TList;
RenameDependencies: Boolean;
MsgResult: TModalResult;
begin
if LazPackage.ReadOnly then exit;
// check changes
// package type
case PkgTypeRadioGroup.ItemIndex of
0: NewPackageType:=lptDesignTime;
1: NewPackageType:=lptRunTime;
else NewPackageType:=lptRunAndDesignTime;
end;
if NewPackageType<>LazPackage.PackageType then begin
if (NewPackageType=lptRunTime) and (LazPackage.AutoInstall<>pitNope) then
begin
ShowMsgPackageTypeMustBeDesign;
exit;
end;
end;
// version
NewVersion:=TPkgVersion.Create;
try
NewVersion.Major:=round(VersionMajorSpinEdit.Value);
NewVersion.Minor:=round(VersionMinorSpinEdit.Value);
NewVersion.Release:=round(VersionReleaseSpinEdit.Value);
NewVersion.Build:=round(VersionBuildSpinEdit.Value);
// check for broken dependencies
BrokenDependencies:=PackageGraph.GetBrokenDependenciesWhenChangingPkgID(
LazPackage,LazPackage.Name,NewVersion);
RenameDependencies:=false;
try
if BrokenDependencies.Count>0 then begin
MsgResult:=ShowBrokenDependencies(BrokenDependencies,
DefaultBrokenDepButtons);
if MsgResult=mrYes then
RenameDependencies:=true
else if MsgResult=mrNo then
RenameDependencies:=false
else
exit;
end;
finally
BrokenDependencies.Free;
end;
PackageGraph.ChangePackageID(LazPackage,LazPackage.Name,NewVersion,
RenameDependencies);
finally
NewVersion.Free;
end;
// Description page
LazPackage.Description:=DescriptionMemo.Text;
LazPackage.Author:=AuthorEdit.Text;
LazPackage.AutoIncrementVersionOnBuild:=AutoIncrementOnBuildCheckBox.Checked;
// Usage page
LazPackage.PackageType:=NewPackageType;
LazPackage.AutoUpdate:=(UpdateRadioGroup.ItemIndex=0);
with LazPackage.AddDependCompilerOptions do begin
UnitPath:=UnitPathEdit.Text;
IncludePath:=IncludePathEdit.Text;
ObjectPath:=ObjectPathEdit.Text;
LibraryPath:=LibraryPathEdit.Text;
LinkerOptions:=LinkerOptionsMemo.Text;
CustomOptions:=CustomOptionsMemo.Text;
end;
end;
procedure TPackageOptionsDialog.PackageOptionsDialogClose(Sender: TObject;
var Action: TCloseAction);
begin
IDEDialogLayoutList.SaveLayout(Self);
end;
procedure TPackageOptionsDialog.AddPathsGroupBoxResize(Sender: TObject);
var
LabelLeft: Integer;
@ -385,6 +467,7 @@ begin
Name:='OkButton';
Caption:='Ok';
Parent:=Self;
OnClick:=@OkButtonClick;
end;
CancelButton:=TButton.Create(Self);
@ -688,6 +771,8 @@ end;
procedure TPackageOptionsDialog.ReadOptionsFromPackage;
begin
if LazPackage=nil then exit;
OkButton.Enabled:=not LazPackage.ReadOnly;
// Description page
DescriptionMemo.Text:=LazPackage.Description;
@ -739,6 +824,16 @@ begin
Result:=nil;
end;
procedure TPackageOptionsDialog.ShowMsgPackageTypeMustBeDesign;
begin
MessageDlg('Invalid package type',
'The package "'+LazPackage.IDAsString+'" has the auto install flag.'#13
+'This means it will be installed in the IDE. Installation packages'#13
+'must be designtime Packages.',
mtError,[mbCancel],0);
ReadPkgTypeFromPackage;
end;
constructor TPackageOptionsDialog.Create(TheOwner: TComponent);
begin
inherited Create(TheOwner);
@ -749,6 +844,7 @@ begin
Position:=poScreenCenter;
IDEDialogLayoutList.ApplyLayout(Self,450,400);
OnResize(Self);
OnClose:=@PackageOptionsDialogClose;
end;
destructor TPackageOptionsDialog.Destroy;