diff --git a/CreamInstaller/Forms/SelectDialogForm.cs b/CreamInstaller/Forms/SelectDialogForm.cs index 7802397..4675b09 100644 --- a/CreamInstaller/Forms/SelectDialogForm.cs +++ b/CreamInstaller/Forms/SelectDialogForm.cs @@ -12,16 +12,17 @@ internal sealed partial class SelectDialogForm : CustomForm private readonly List<(Platform platform, string id, string name)> selected = new(); internal SelectDialogForm(IWin32Window owner) : base(owner) => InitializeComponent(); - internal List<(Platform platform, string id, string name)> QueryUser(string groupBoxText, - List<(Platform platform, string id, string name, bool alreadySelected)> choices) + internal DialogResult QueryUser(string groupBoxText, List<(Platform platform, string id, string name, bool alreadySelected)> potentialChoices, + out List<(Platform platform, string id, string name)> choices) { - if (!choices.Any()) - return null; + choices = null; + if (!potentialChoices.Any()) + return DialogResult.Cancel; groupBox.Text = groupBoxText; allCheckBox.Enabled = false; acceptButton.Enabled = false; selectionTreeView.AfterCheck += OnTreeNodeChecked; - foreach ((Platform platform, string id, string name, bool alreadySelected) in choices) + foreach ((Platform platform, string id, string name, bool alreadySelected) in potentialChoices) { TreeNode node = new() { Tag = platform, Name = id, Text = name, Checked = alreadySelected }; OnTreeNodeChecked(node); @@ -38,7 +39,8 @@ internal sealed partial class SelectDialogForm : CustomForm loadButton.Enabled = ProgramData.ReadProgramChoices() is not null; OnResize(null, null); Resize += OnResize; - return ShowDialog() == DialogResult.OK ? selected : null; + choices = selected; + return ShowDialog(); } private void OnTreeNodeChecked(object sender, TreeViewEventArgs e) diff --git a/CreamInstaller/Forms/SelectForm.cs b/CreamInstaller/Forms/SelectForm.cs index 1cdd6f4..cda417b 100644 --- a/CreamInstaller/Forms/SelectForm.cs +++ b/CreamInstaller/Forms/SelectForm.cs @@ -100,7 +100,7 @@ internal sealed partial class SelectForm : CustomForm }); } - private async Task GetApplicablePrograms(IProgress progress) + private async Task GetApplicablePrograms(IProgress progress, bool uninstallAll = false) { if (programsToScan is null || !programsToScan.Any()) return; @@ -128,25 +128,37 @@ internal sealed partial class SelectForm : CustomForm List dllDirectories = await ParadoxLauncher.InstallPath.GetDllDirectoriesFromGameDirectory(Platform.Paradox, this); if (dllDirectories is not null) { - ProgramSelection selection = ProgramSelection.FromPlatformId(Platform.Paradox, "PL"); - selection ??= new(); - if (allCheckBox.Checked) - selection.Enabled = true; - if (koaloaderAllCheckBox.Checked) - selection.Koaloader = true; - selection.Id = "PL"; - selection.Name = "Paradox Launcher"; - selection.RootDirectory = ParadoxLauncher.InstallPath; - selection.ExecutableDirectories = await ParadoxLauncher.GetExecutableDirectories(selection.RootDirectory); - selection.DllDirectories = dllDirectories; - selection.Platform = Platform.Paradox; - TreeNode programNode = treeNodes.Find(s => s.Tag is Platform.Paradox && s.Name == selection.Id) ?? new TreeNode(); - programNode.Tag = selection.Platform; - programNode.Name = selection.Id; - programNode.Text = selection.Name; - programNode.Checked = selection.Enabled; - if (programNode.TreeView is null) - _ = selectionTreeView.Nodes.Add(programNode); + if (uninstallAll) + { + ProgramSelection bareSelection = ProgramSelection.FromPlatformId(Platform.Paradox, "PL") ?? new(); + bareSelection.Id = "PL"; + bareSelection.Name = "Paradox Launcher"; + bareSelection.RootDirectory = ParadoxLauncher.InstallPath; + bareSelection.ExecutableDirectories = await ParadoxLauncher.GetExecutableDirectories(bareSelection.RootDirectory); + bareSelection.DllDirectories = dllDirectories; + bareSelection.Platform = Platform.Paradox; + } + else + { + ProgramSelection selection = ProgramSelection.FromPlatformId(Platform.Paradox, "PL") ?? new(); + if (allCheckBox.Checked) + selection.Enabled = true; + if (koaloaderAllCheckBox.Checked) + selection.Koaloader = true; + selection.Id = "PL"; + selection.Name = "Paradox Launcher"; + selection.RootDirectory = ParadoxLauncher.InstallPath; + selection.ExecutableDirectories = await ParadoxLauncher.GetExecutableDirectories(selection.RootDirectory); + selection.DllDirectories = dllDirectories; + selection.Platform = Platform.Paradox; + TreeNode programNode = treeNodes.Find(s => s.Tag is Platform.Paradox && s.Name == selection.Id) ?? new TreeNode(); + programNode.Tag = selection.Platform; + programNode.Name = selection.Id; + programNode.Text = selection.Name; + programNode.Checked = selection.Enabled; + if (programNode.TreeView is null) + _ = selectionTreeView.Nodes.Add(programNode); + } } } int steamGamesToCheck; @@ -158,7 +170,7 @@ internal sealed partial class SelectForm : CustomForm { if (Program.Canceled) return; - if (Program.IsGameBlocked(name, gameDirectory) || !programsToScan.Any(c => c.platform is Platform.Steam && c.id == appId)) + if (!uninstallAll && (Program.IsGameBlocked(name, gameDirectory) || !programsToScan.Any(c => c.platform is Platform.Steam && c.id == appId))) { Interlocked.Decrement(ref steamGamesToCheck); continue; @@ -175,6 +187,20 @@ internal sealed partial class SelectForm : CustomForm RemoveFromRemainingGames(name); return; } + if (uninstallAll) + { + ProgramSelection bareSelection = ProgramSelection.FromPlatformId(Platform.Steam, appId) ?? new ProgramSelection(); + bareSelection.Enabled = true; + bareSelection.Id = appId; + bareSelection.Name = name; + bareSelection.RootDirectory = gameDirectory; + bareSelection.ExecutableDirectories = await SteamLibrary.GetExecutableDirectories(bareSelection.RootDirectory); + bareSelection.DllDirectories = dllDirectories; + bareSelection.Platform = Platform.Steam; + return; + } + if (Program.Canceled) + return; AppData appData = await SteamStore.QueryStoreAPI(appId); Interlocked.Decrement(ref steamGamesToCheck); VProperty appInfo = await SteamCMD.GetAppInfo(appId, branch, buildId); @@ -316,12 +342,10 @@ internal sealed partial class SelectForm : CustomForm programNode.Checked = selection.Enabled; if (programNode.TreeView is null) _ = selectionTreeView.Nodes.Add(programNode); - foreach (KeyValuePair pair in dlc) + foreach ((string appId, (DlcType type, string name, string icon) dlcApp) in dlc) { if (Program.Canceled) return; - string appId = pair.Key; - (DlcType type, string name, string icon) dlcApp = pair.Value; selection.AllDlc[appId] = dlcApp; if (allCheckBox.Checked && dlcApp.name != "Unknown") selection.SelectedDlc[appId] = dlcApp; @@ -351,7 +375,7 @@ internal sealed partial class SelectForm : CustomForm string directory = manifest.InstallLocation; if (Program.Canceled) return; - if (Program.IsGameBlocked(name, directory) || !programsToScan.Any(c => c.platform is Platform.Epic && c.id == @namespace)) + if (!uninstallAll && (Program.IsGameBlocked(name, directory) || !programsToScan.Any(c => c.platform is Platform.Epic && c.id == @namespace))) continue; AddToRemainingGames(name); Task task = Task.Run(async () => @@ -364,6 +388,18 @@ internal sealed partial class SelectForm : CustomForm RemoveFromRemainingGames(name); return; } + if (uninstallAll) + { + ProgramSelection bareSelection = ProgramSelection.FromPlatformId(Platform.Epic, @namespace) ?? new ProgramSelection(); + bareSelection.Enabled = true; + bareSelection.Id = @namespace; + bareSelection.Name = name; + bareSelection.RootDirectory = directory; + bareSelection.ExecutableDirectories = await EpicLibrary.GetExecutableDirectories(bareSelection.RootDirectory); + bareSelection.DllDirectories = dllDirectories; + bareSelection.Platform = Platform.Epic; + return; + } if (Program.Canceled) return; ConcurrentDictionary entitlements = new(); @@ -443,10 +479,9 @@ internal sealed partial class SelectForm : CustomForm entitlementsNode.Checked = selection.SelectedDlc.Any(pair => pair.Value.type == DlcType.Entitlement); if (entitlementsNode.Parent is null) programNode.Nodes.Add(entitlementsNode);*/ - foreach (KeyValuePair pair in entitlements) + foreach ((string dlcId, (string name, string product, string icon, string developer) value) in entitlements) { - string dlcId = pair.Key; - (DlcType type, string name, string icon) dlcApp = (DlcType.EpicEntitlement, pair.Value.name, pair.Value.icon); + (DlcType type, string name, string icon) dlcApp = (DlcType.EpicEntitlement, value.name, value.icon); selection.AllDlc[dlcId] = dlcApp; if (allCheckBox.Checked) selection.SelectedDlc[dlcId] = dlcApp; @@ -486,6 +521,18 @@ internal sealed partial class SelectForm : CustomForm RemoveFromRemainingGames(name); return; } + if (uninstallAll) + { + ProgramSelection bareSelection = ProgramSelection.FromPlatformId(Platform.Ubisoft, gameId) ?? new ProgramSelection(); + bareSelection.Enabled = true; + bareSelection.Id = gameId; + bareSelection.Name = name; + bareSelection.RootDirectory = gameDirectory; + bareSelection.ExecutableDirectories = await UbisoftLibrary.GetExecutableDirectories(bareSelection.RootDirectory); + bareSelection.DllDirectories = dllDirectories; + bareSelection.Platform = Platform.Ubisoft; + return; + } if (Program.Canceled) return; ProgramSelection selection = ProgramSelection.FromPlatformId(Platform.Ubisoft, gameId) ?? new ProgramSelection(); @@ -571,16 +618,29 @@ internal sealed partial class SelectForm : CustomForm if (gameChoices.Any()) { using SelectDialogForm form = new(this); - List<(Platform platform, string id, string name)> choices = form.QueryUser("Choose which programs and/or games to scan for DLC:", gameChoices); - scan = choices is not null && choices.Any(); - const string retry = "\n\nPress the \"Rescan\" button to re-choose."; - if (scan) + DialogResult selectResult = form.QueryUser("Choose which programs and/or games to scan:", gameChoices, + out List<(Platform platform, string id, string name)> choices); + if (selectResult == DialogResult.Abort) // will be an uninstall all button { + choices = new(); + foreach ((Platform platform, string id, string name, bool alreadySelected) in gameChoices) + choices.Add((platform, id, name)); programsToScan = choices; - noneFoundLabel.Text = "None of the chosen programs nor games were applicable!" + retry; + await GetApplicablePrograms(new Progress(), true); + OnUninstall(null, null); } else - noneFoundLabel.Text = "You didn't choose any programs nor games!" + retry; + { + scan = selectResult == DialogResult.OK && choices is not null && choices.Any(); + const string retry = "\n\nPress the \"Rescan\" button to re-choose."; + if (scan) + { + programsToScan = choices; + noneFoundLabel.Text = "None of the chosen programs nor games were applicable!" + retry; + } + else + noneFoundLabel.Text = "You didn't choose any programs nor games!" + retry; + } } else noneFoundLabel.Text = "No applicable programs nor games were found on your computer!"; diff --git a/CreamInstaller/ProgramSelection.cs b/CreamInstaller/ProgramSelection.cs index 832a7c9..942b0ce 100644 --- a/CreamInstaller/ProgramSelection.cs +++ b/CreamInstaller/ProgramSelection.cs @@ -114,10 +114,8 @@ internal sealed class ProgramSelection internal void ToggleDlc(string dlcId, bool enabled) { - foreach (KeyValuePair pair in AllDlc) + foreach ((string appId, (DlcType type, string name, string icon) dlcApp) in AllDlc) { - string appId = pair.Key; - (DlcType type, string name, string icon) dlcApp = pair.Value; if (appId != dlcId) continue; Toggle(appId, dlcApp, enabled);