IDE: Improve InstallPkgSetDialog, disable "Uninstall" when it can't be used, support drag/drop for import. Issue #40496, patch by n7800.

This commit is contained in:
Juha 2023-09-26 12:49:56 +03:00
parent 8563725a77
commit c76cc9ce62
3 changed files with 119 additions and 35 deletions

View File

@ -129,8 +129,8 @@ resourcestring
// *** Rest of the resource strings ***
lisImportPackageListXml = 'Import package list (*.xml)';
lisExportPackageListXml = 'Export package list (*.xml)';
lisImportPackageListXml = 'Import package list';
lisExportPackageListXml = 'Export package list';
lrsRescanLplFiles = 'Rescan lpl files';
lisRenameShowResult = 'Show list of renamed Identifiers';
lisResourceNameMustBeUnique = 'Resource name must be unique.';
@ -5210,15 +5210,15 @@ resourcestring
lisErrorMovingComponent2 = 'Error moving component %s:%s';
lisInstallUninstallPackages = 'Install/Uninstall Packages';
lisMenuEditInstallPkgs = 'Install/Uninstall Packages ...';
lisExportList = 'Export list';
lisExportList = 'Export...';
lisAvailableForInstallation = 'Available for installation';
lisPkgsInstalled = 'Installed';
lisImportList = 'Import list';
lisImportList = 'Import...';
lisUninstallSelection = 'Uninstall selection';
lisInstallSelection = 'Install selection';
lisPackageInfo = 'Package info';
lisSaveAndRebuildIDE = 'Save and rebuild IDE';
lisSaveAndExitDialog = 'Save and exit dialog';
lisSaveAndRebuildIDE = 'Rebuild IDE';
lisSaveAndExitDialog = 'Only Save';
lisAlignment = 'Alignment';
lisHorizontal = 'Horizontal';
lisNoChange = 'No change';

View File

@ -4,6 +4,7 @@ object InstallPkgSetDialog: TInstallPkgSetDialog
Top = 219
Width = 607
ActiveControl = AvailableFilterEdit
AllowDropFiles = True
BorderStyle = bsSizeToolWin
Caption = 'InstallPkgSetDialog'
ClientHeight = 638
@ -14,6 +15,7 @@ object InstallPkgSetDialog: TInstallPkgSetDialog
OnClose = FormClose
OnCreate = InstallPkgSetDialogCreate
OnDestroy = InstallPkgSetDialogDestroy
OnDropFiles = FormDropFiles
OnKeyDown = FormKeyDown
OnResize = InstallPkgSetDialogResize
OnShow = InstallPkgSetDialogShow
@ -324,6 +326,7 @@ object InstallPkgSetDialog: TInstallPkgSetDialog
ParentFont = False
Spacing = 2
TabOrder = 0
OnKeyDown = InstallTreeViewKeyDown
FilteredTreeview = InstallTreeView
OnGetImageIndex = FilterEditGetImageIndex
end
@ -453,6 +456,7 @@ object InstallPkgSetDialog: TInstallPkgSetDialog
ParentFont = False
Spacing = 2
TabOrder = 0
OnKeyDown = AvailableTreeViewKeyDown
FilteredTreeview = AvailableTreeView
OnGetImageIndex = FilterEditGetImageIndex
end

View File

@ -90,6 +90,7 @@ type
function FilterEditGetImageIndex({%H-}Str: String; {%H-}Data: TObject;
var {%H-}AIsEnabled: Boolean): Integer;
procedure FormClose(Sender: TObject; var {%H-}CloseAction: TCloseAction);
procedure FormDropFiles(Sender: TObject; const FileNames: array of string);
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure InstallTreeViewKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
@ -155,6 +156,8 @@ type
procedure PkgInfosChanged;
procedure ChangePkgVersion(PkgInfo: TLPKInfo; NewVersion: TPkgVersion);
function FindOnlinePackageLink(const AName: String): TPackageLink;
function IsBasePkg(aPkgID: TLazPackageID): boolean;
function IsBasePkg(aPkgName: string): boolean;
public
function GetNewInstalledPackages: TObjectList;
property OldInstalledPackages: TPkgDependency read FOldInstalledPackages
@ -283,9 +286,11 @@ end;
procedure TInstallPkgSetDialog.SaveAndRebuildButtonClick(Sender: TObject);
begin
if not CheckSelection then exit;
RebuildIDE:=true;
ModalResult:=mrOk;
if SaveAndRebuildButton.Enabled and CheckSelection then
begin
RebuildIDE := true;
ModalResult := mrOk;
end;
end;
procedure TInstallPkgSetDialog.AvailableTreeViewSelectionChanged(Sender: TObject);
@ -304,6 +309,7 @@ begin
InputHistories.ApplyFileDialogSettings(SaveDialog);
SaveDialog.InitialDir:=GetPrimaryConfigPath;
SaveDialog.Title:=lisExportPackageListXml;
SaveDialog.Filter:='XML-files|*.xml|Plain text|*.txt|All files|*.*';
SaveDialog.Options:=SaveDialog.Options+[ofPathMustExist];
if SaveDialog.Execute then begin
AFilename:=CleanAndExpandFilename(SaveDialog.Filename);
@ -332,6 +338,7 @@ begin
InputHistories.ApplyFileDialogSettings(OpenDialog);
OpenDialog.InitialDir:=GetPrimaryConfigPath;
OpenDialog.Title:=lisImportPackageListXml;
OpenDialog.Filter:='Package list files|*.xml;*.txt|All files|*.*';
OpenDialog.Options:=OpenDialog.Options+[ofPathMustExist,ofFileMustExist];
if OpenDialog.Execute then begin
AFilename:=CleanAndExpandFilename(OpenDialog.Filename);
@ -362,9 +369,28 @@ end;
procedure TInstallPkgSetDialog.FormClose(Sender: TObject;
var CloseAction: TCloseAction);
begin
// don't close until parsing is complete
if LPKParsingTimer.Enabled then
begin
CloseAction := caNone;
exit;
end;
IDEDialogLayoutList.SaveLayout(Self);
end;
procedure TInstallPkgSetDialog.FormDropFiles(Sender: TObject;
const FileNames: array of string);
var
lFilename: String;
begin
if length(FileNames) = 1 then // only one file
begin
lFilename := CleanAndExpandFilename(FileNames[0]);
LoadPackageListFromFile(lFilename);
end;
end;
procedure TInstallPkgSetDialog.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
@ -372,7 +398,48 @@ begin
begin
Close;
Key := 0;
end;
end
else if (Key = VK_RETURN) and (Shift = [ssCtrl]) then
begin
SaveAndRebuildButtonClick(Sender);
Key := 0;
end
else if (Key = VK_S) and (Shift = [ssCtrl]) then
begin
SaveAndExitButtonClick(Sender);
Key := 0;
end
// import and export
else if (Key = VK_E) and (Shift = [ssCtrl]) then
begin
ExportButtonClick(Sender);
Key := 0;
end
else if (Key = VK_I) and (Shift = [ssCtrl]) then
begin
ImportButtonClick(Sender);
Key := 0;
end
// scroll description
else if (Key = VK_DOWN) and (Shift = [ssCtrl]) then
begin
PkgInfoMemo.VertScrollBar.Position := PkgInfoMemo.VertScrollBar.Position + 1;
Key := 0;
end
else if (Key = VK_UP) and (Shift = [ssCtrl]) then
begin
PkgInfoMemo.VertScrollBar.Position := PkgInfoMemo.VertScrollBar.Position - 1;
Key := 0;
end
// switch focus
else if (Key = VK_TAB) and (Shift = [ssCtrl]) then
begin
if AvailableFilterEdit.Focused then
InstalledFilterEdit.SetFocus
else
AvailableFilterEdit.SetFocus;
Key := 0;
end
end;
procedure TInstallPkgSetDialog.InstallTreeViewKeyDown(Sender: TObject;
@ -487,9 +554,11 @@ end;
procedure TInstallPkgSetDialog.SaveAndExitButtonClick(Sender: TObject);
begin
if not CheckSelection then exit;
RebuildIDE:=false;
ModalResult:=mrOk;
if SaveAndExitButton.Enabled and CheckSelection then
begin
RebuildIDE := false;
ModalResult := mrOk;
end;
end;
procedure TInstallPkgSetDialog.SetOldInstalledPackages(const AValue: TPkgDependency);
@ -593,6 +662,29 @@ begin
Result := PackageLink;
end;
// returns false on error or if the package is not base
function TInstallPkgSetDialog.IsBasePkg(aPkgID: TLazPackageID): boolean;
var
lPkg: TLazPackage;
begin
lPkg := PackageGraph.FindPackageWithID(aPkgID); // no need to free
result := (lPkg <> nil) and PackageGraph.IsCompiledInBasePackage(lPkg.Name);
end;
// returns false on error or if the package is not base
function TInstallPkgSetDialog.IsBasePkg(aPkgName: string): boolean;
var
lPkgID: TLazPackageID;
begin
result := false;
lPkgID := TLazPackageID.Create;
try
result := lPkgID.StringToID(aPkgName) and IsBasePkg(lPkgID);
finally
lPkgID.Free;
end;
end;
procedure TInstallPkgSetDialog.UpdateAvailablePackages(Immediately: boolean);
var
ANode: TAvlTreeNode;
@ -785,7 +877,8 @@ procedure TInstallPkgSetDialog.UpdateButtonStates;
begin
SaveAndRebuildButton.Enabled := ChangesFound;
SaveAndExitButton .Enabled := SaveAndRebuildButton.Enabled;
UninstallButton .Enabled := InstallTreeView.Selected <> nil;
UninstallButton .Enabled := (InstallTreeView.Selected <> nil) and
not IsBasePkg(InstallTreeView.Selected.Text);
AddToInstallButton .Enabled := AvailableTreeView.Selected <> nil;
end;
@ -1183,24 +1276,6 @@ begin
end;
procedure TInstallPkgSetDialog.AddToUninstall(Sender: TObject);
function SelectionOk(aPackageID: TLazPackageID): Boolean;
var
APackage: TLazPackage;
begin
APackage:=PackageGraph.FindPackageWithID(aPackageID);
if APackage<>nil then begin
// check if package is a base package
if PackageGraph.IsCompiledInBasePackage(APackage.Name) then begin
MessageDlg(lisUninstallImpossible,
Format(lisThePackageCanNotBeUninstalledBecauseItIsNeededByTh, [
APackage.Name]), mtError, [mbCancel], 0);
exit(false);
end;
end;
Result:=true;
end;
var
i, j: Integer;
NewSelectedIndex, LastNonSelectedIndex: Integer;
@ -1228,12 +1303,17 @@ begin
NewSelectedIndex:=i+1; // Will have the next index after the selected one.
PkgName:=TVNode.Text;
if not DelPackageID.StringToID(PkgName) then begin
TVNode.Selected:=false;
debugln('TInstallPkgSetDialog.AddToUninstall invalid ID: ', PkgName);
continue;
end;
if not SelectionOk(DelPackageID) then begin
TVNode.Selected:=false;
if IsBasePkg(DelPackageID) then begin
MessageDlg(
lisUninstallImpossible,
Format(lisThePackageCanNotBeUninstalledBecauseItIsNeededByTh, [PkgName]),
mtError,
[mbCancel],
0
);
exit;
end;
// ok => add to deletions