IDE: clean up package dependencies dialog: show transitivities

git-svn-id: trunk@40766 -
This commit is contained in:
mattias 2013-04-09 18:37:13 +00:00
parent 541e7293b1
commit be39fcdf63
3 changed files with 164 additions and 18 deletions

View File

@ -741,6 +741,7 @@
<Filename Value="../packager/cleanpkgdeps.pas"/> <Filename Value="../packager/cleanpkgdeps.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<ComponentName Value="CleanPkgDepsDlg"/> <ComponentName Value="CleanPkgDepsDlg"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/> <ResourceBaseClass Value="Form"/>
<UnitName Value="CleanPkgDeps"/> <UnitName Value="CleanPkgDeps"/>
</Unit98> </Unit98>
@ -753,7 +754,7 @@
</Target> </Target>
<SearchPaths> <SearchPaths>
<IncludeFiles Value="include"/> <IncludeFiles Value="include"/>
<OtherUnitFiles Value="frames;../converter;../debugger;../debugger/frames;../packager;../designer;../packager/frames;../ide;../packager"/> <OtherUnitFiles Value="frames;../converter;../debugger;../debugger/frames;../packager;../designer;../packager/frames;../ide"/>
<UnitOutputDirectory Value="$(LazarusDir)/units/$(TargetCPU)-$(TargetOS)/$(LCLWidgetType)"/> <UnitOutputDirectory Value="$(LazarusDir)/units/$(TargetCPU)-$(TargetOS)/$(LCLWidgetType)"/>
</SearchPaths> </SearchPaths>
<Other> <Other>

View File

@ -7,12 +7,13 @@ object CleanPkgDepsDlg: TCleanPkgDepsDlg
ClientHeight = 380 ClientHeight = 380
ClientWidth = 522 ClientWidth = 522
OnCreate = FormCreate OnCreate = FormCreate
OnDestroy = FormDestroy
Position = poScreenCenter Position = poScreenCenter
LCLVersion = '1.1' LCLVersion = '1.1'
object ButtonPanel1: TButtonPanel object ButtonPanel1: TButtonPanel
Left = 6 Left = 6
Height = 30 Height = 36
Top = 344 Top = 338
Width = 510 Width = 510
OKButton.Name = 'OKButton' OKButton.Name = 'OKButton'
OKButton.DefaultCaption = True OKButton.DefaultCaption = True
@ -27,28 +28,28 @@ object CleanPkgDepsDlg: TCleanPkgDepsDlg
end end
object TransitivityGroupBox: TGroupBox object TransitivityGroupBox: TGroupBox
Left = 0 Left = 0
Height = 338 Height = 332
Top = 0 Top = 0
Width = 522 Width = 522
Align = alClient Align = alClient
Caption = 'TransitivityGroupBox' Caption = 'TransitivityGroupBox'
ClientHeight = 316 ClientHeight = 315
ClientWidth = 514 ClientWidth = 518
TabOrder = 1 TabOrder = 1
object TransitivityTreeView: TTreeView object TransitivityTreeView: TTreeView
Left = 0 Left = 0
Height = 300 Height = 300
Top = 16 Top = 15
Width = 514 Width = 518
Align = alClient Align = alClient
DefaultItemHeight = 18 DefaultItemHeight = 18
TabOrder = 0 TabOrder = 0
end end
object TransitivityLabel: TLabel object TransitivityLabel: TLabel
Left = 0 Left = 0
Height = 16 Height = 15
Top = 0 Top = 0
Width = 514 Width = 518
Align = alTop Align = alTop
Caption = 'TransitivityLabel' Caption = 'TransitivityLabel'
ParentColor = False ParentColor = False

View File

@ -1,3 +1,25 @@
{
***************************************************************************
* *
* 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
}
unit CleanPkgDeps; unit CleanPkgDeps;
{$mode objfpc}{$H+} {$mode objfpc}{$H+}
@ -5,12 +27,20 @@ unit CleanPkgDeps;
interface interface
uses uses
Classes, SysUtils, FileUtil, LvlGraphCtrl, Forms, Controls, Graphics, Dialogs, Classes, SysUtils, FileUtil, AvgLvlTree, LazLogger, LvlGraphCtrl, Forms,
ButtonPanel, ComCtrls, ExtCtrls, StdCtrls, LazarusIDEStrConsts, Project, Controls, Graphics, Dialogs, ButtonPanel, ComCtrls, ExtCtrls, StdCtrls,
PackageDefs; LazarusIDEStrConsts, Project, PackageDefs, IDEImagesIntf;
const
CPDProjectName = '-Project-';
type type
TCPDNodeInfo = class
public
Owner: string; // CPDProjectName or package name
Dependency: string; // required package name
end;
{ TCleanPkgDepsDlg } { TCleanPkgDepsDlg }
TCleanPkgDepsDlg = class(TForm) TCleanPkgDepsDlg = class(TForm)
@ -18,15 +48,21 @@ type
TransitivityGroupBox: TGroupBox; TransitivityGroupBox: TGroupBox;
TransitivityLabel: TLabel; TransitivityLabel: TLabel;
TransitivityTreeView: TTreeView; TransitivityTreeView: TTreeView;
procedure ButtonPanel1OKButtonClick(Sender: TObject);
procedure FormCreate(Sender: TObject); procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private private
FOwners: TFPList; FOwners: TFPList;
ImgIndexProject: integer;
ImgIndexPackage: integer;
procedure SetOwners(AValue: TFPList); procedure SetOwners(AValue: TFPList);
procedure ClearTreeData;
procedure UpdateTransitivityTree; procedure UpdateTransitivityTree;
procedure UpdateButtons; procedure UpdateButtons;
function IsTVNodeChecked(TVNode: TTreeNode): boolean; function IsTVNodeChecked(TVNode: TTreeNode): boolean;
procedure AddTransitivities(NodeCaption: string; procedure AddTransitivities(NodeCaption: string; ImgIndex: integer;
FirstDependency: TPkgDependency); FirstDependency: TPkgDependency);
function FindAlternativeRoute(Dependency, StartDependency: TPkgDependency): TFPList;
public public
property Owners: TFPList read FOwners write SetOwners; property Owners: TFPList read FOwners write SetOwners;
end; end;
@ -79,10 +115,26 @@ end;
procedure TCleanPkgDepsDlg.FormCreate(Sender: TObject); procedure TCleanPkgDepsDlg.FormCreate(Sender: TObject);
begin begin
ImgIndexProject := IDEImages.LoadImage(16, 'item_project');
ImgIndexPackage := IDEImages.LoadImage(16, 'item_package');
Caption:='Clean up package dependencies'; Caption:='Clean up package dependencies';
TransitivityGroupBox.Caption:='Transitivity'; TransitivityGroupBox.Caption:='Transitivity';
TransitivityLabel.Caption:='The following dependencies are not needed, because of the automatic transitivity between package dependencies.'; TransitivityLabel.Caption:='The following dependencies are not needed, because of the automatic transitivity between package dependencies.';
TransitivityTreeView.Images:=IDEImages.Images_16;
ButtonPanel1.OKButton.Caption:='Delete dependencies'; ButtonPanel1.OKButton.Caption:='Delete dependencies';
ButtonPanel1.OKButton.OnClick:=@ButtonPanel1OKButtonClick;
end;
procedure TCleanPkgDepsDlg.FormDestroy(Sender: TObject);
begin
ClearTreeData;
end;
procedure TCleanPkgDepsDlg.ButtonPanel1OKButtonClick(Sender: TObject);
begin
ShowMessage('Not implemented yet');
ModalResult:=mrNone;
end; end;
procedure TCleanPkgDepsDlg.SetOwners(AValue: TFPList); procedure TCleanPkgDepsDlg.SetOwners(AValue: TFPList);
@ -93,6 +145,20 @@ begin
UpdateButtons; UpdateButtons;
end; end;
procedure TCleanPkgDepsDlg.ClearTreeData;
var
i: Integer;
TVNode: TTreeNode;
begin
for i:=0 to TransitivityTreeView.Items.Count-1 do begin
TVNode:=TransitivityTreeView.Items[i];
if TVNode.Data<>nil then begin
TObject(TVNode.Data).Free;
TVNode.Data:=nil;
end;
end;
end;
procedure TCleanPkgDepsDlg.UpdateTransitivityTree; procedure TCleanPkgDepsDlg.UpdateTransitivityTree;
var var
i: Integer; i: Integer;
@ -101,15 +167,16 @@ var
APackage: TLazPackage; APackage: TLazPackage;
begin begin
TransitivityTreeView.BeginUpdate; TransitivityTreeView.BeginUpdate;
ClearTreeData;
TransitivityTreeView.Items.Clear; TransitivityTreeView.Items.Clear;
for i:=0 to Owners.Count-1 do begin for i:=0 to Owners.Count-1 do begin
CurOwner:=TObject(Owners[i]); CurOwner:=TObject(Owners[i]);
if CurOwner is TProject then begin if CurOwner is TProject then begin
AProject:=TProject(CurOwner); AProject:=TProject(CurOwner);
AddTransitivities('-Project-',AProject.FirstRequiredDependency); AddTransitivities(CPDProjectName,ImgIndexProject,AProject.FirstRequiredDependency);
end else if CurOwner is TLazPackage then begin end else if CurOwner is TLazPackage then begin
APackage:=TLazPackage(CurOwner); APackage:=TLazPackage(CurOwner);
AddTransitivities(APackage.IDAsString,APackage.FirstRequiredDependency); AddTransitivities(APackage.IDAsString,ImgIndexPackage,APackage.FirstRequiredDependency);
end; end;
end; end;
TransitivityTreeView.EndUpdate; TransitivityTreeView.EndUpdate;
@ -136,16 +203,93 @@ begin
end; end;
procedure TCleanPkgDepsDlg.AddTransitivities(NodeCaption: string; procedure TCleanPkgDepsDlg.AddTransitivities(NodeCaption: string;
FirstDependency: TPkgDependency); ImgIndex: integer; FirstDependency: TPkgDependency);
var var
Dependency: TPkgDependency; Dependency: TPkgDependency;
AltRoute: TFPList;
MainTVNode: TTreeNode;
TVNode: TTreeNode;
Info: TCPDNodeInfo;
s: String;
i: Integer;
begin begin
MainTVNode:=nil;
Dependency:=FirstDependency; Dependency:=FirstDependency;
while Dependency<>nil do begin while Dependency<>nil do begin
AltRoute:=FindAlternativeRoute(Dependency,FirstDependency);
if AltRoute<>nil then begin
if MainTVNode=nil then begin
MainTVNode:=TransitivityTreeView.Items.Add(nil,NodeCaption);
MainTVNode.ImageIndex:=ImgIndex;
end;
s:=Dependency.AsString+' = ';
for i:=0 to AltRoute.Count-1 do begin
if i>0 then
s+='-';
s+=TLazPackage(AltRoute[i]).Name;
end;
TVNode:=TransitivityTreeView.Items.AddChild(MainTVNode,s);
TVNode.ImageIndex:=ImgIndexPackage;
Info:=TCPDNodeInfo.Create;
TVNode.Data:=Info;
Info.Owner:=NodeCaption;
Info.Dependency:=Dependency.RequiredPackage.Name;
MainTVNode.Expand(true);
AltRoute.Free;
end;
Dependency:=Dependency.NextRequiresDependency; Dependency:=Dependency.NextRequiresDependency;
end; end;
end; end;
function TCleanPkgDepsDlg.FindAlternativeRoute(Dependency,
StartDependency: TPkgDependency): TFPList;
var
Visited: TAvgLvlTree;
function Search(Pkg: TLazPackage; Level: integer; var AltRoute: TFPList): boolean;
var
CurDependency: TPkgDependency;
begin
Result:=false;
if Pkg=nil then exit;
if Pkg=Dependency.Owner then exit; // cycle detected
if (Level>0) and (Pkg=Dependency.RequiredPackage) then begin
// alternative route found
AltRoute:=TFPList.Create;
AltRoute.Add(Pkg);
exit(true);
end;
if Visited.Find(Pkg)<>nil then exit;
Visited.Add(Pkg);
CurDependency:=Pkg.FirstRequiredDependency;
while CurDependency<>nil do begin
if Search(CurDependency.RequiredPackage,Level+1,AltRoute) then begin
AltRoute.Insert(0,Pkg);
exit(true);
end;
CurDependency:=CurDependency.NextRequiresDependency;
end;
end;
var
CurDependency: TPkgDependency;
begin
Result:=nil;
if Dependency=nil then exit;
if Dependency.RequiredPackage=nil then exit;
Visited:=TAvgLvlTree.Create;
try
CurDependency:=StartDependency;
while CurDependency<>nil do begin
if CurDependency<>Dependency then
if Search(CurDependency.RequiredPackage,0,Result) then exit;
CurDependency:=CurDependency.NextRequiresDependency;
end;
finally
Visited.Free;
end;
end;
end. end.