From f1fb60eaa0bf4802884cab8416b1652460983970 Mon Sep 17 00:00:00 2001 From: Paul Hebble Date: Mon, 1 Jul 2019 00:43:05 +0000 Subject: [PATCH] Queue module version changes in change set --- Core/ModuleInstaller.cs | 17 ++++- GUI/GUIMod.cs | 107 ++++++++++++++++++++++------ GUI/Main.cs | 11 +-- GUI/MainAllModVersions.Designer.cs | 5 +- GUI/MainAllModVersions.cs | 92 +++++++++++++++++++----- GUI/MainChangeset.cs | 12 ++-- GUI/MainInstall.cs | 16 ++--- GUI/MainModInfo.cs | 8 +-- GUI/MainModList.cs | 74 ++++++++----------- GUI/MainRecommendations.cs | 2 +- GUI/ModChange.cs | 6 +- GUI/Properties/Resources.de-DE.resx | 4 +- GUI/Properties/Resources.resx | 4 +- Tests/GUI/GH1866.cs | 2 +- 14 files changed, 245 insertions(+), 115 deletions(-) diff --git a/Core/ModuleInstaller.cs b/Core/ModuleInstaller.cs index 25a8548ad2..a2b55e41a6 100644 --- a/Core/ModuleInstaller.cs +++ b/Core/ModuleInstaller.cs @@ -210,7 +210,8 @@ public void InstallList(ICollection modules, RelationshipResolverOpt { for (int i = 0; i < modsToInstall.Count; i++) { - int percent_complete = (i * 100) / modsToInstall.Count; + // The post-install steps start at 70%, so count up to 60% for installation + int percent_complete = (i * 60) / modsToInstall.Count; User.RaiseProgress(String.Format("Installing mod \"{0}\"", modsToInstall[i]), percent_complete); @@ -984,20 +985,29 @@ public void AddRemove(IEnumerable add = null, IEnumerable im.Module.identifier == module.identifier); + int percent_complete = (step++ * 70) / totSteps; + User.RaiseProgress($"Installing \"{module}\"", percent_complete); Install(module, previous?.AutoInstalled ?? false); } + User.RaiseProgress("Updating registry", 80); registry_manager.Save(enforceConsistency); + User.RaiseProgress("Committing filesystem changes", 90); tx.Complete(); EnforceCacheSizeLimit(); @@ -1022,6 +1032,8 @@ public void Upgrade(IEnumerable identifiers, IDownloader netAsyncDownloa /// public void Upgrade(IEnumerable modules, IDownloader netAsyncDownloader, bool enforceConsistency = true) { + User.RaiseMessage("About to upgrade...\r\n"); + // Start by making sure we've downloaded everything. DownloadModules(modules, netAsyncDownloader); @@ -1073,6 +1085,7 @@ public void Upgrade(IEnumerable modules, IDownloader netAsyncDownloa to_remove, enforceConsistency ); + User.RaiseProgress("Done!", 100); } /// diff --git a/GUI/GUIMod.cs b/GUI/GUIMod.cs index 733479b882..28b39fa667 100644 --- a/GUI/GUIMod.cs +++ b/GUI/GUIMod.cs @@ -2,14 +2,64 @@ using System.Collections.Generic; using System.Windows.Forms; using System.Linq; +using System.ComponentModel; +using System.Runtime.CompilerServices; using CKAN.Versioning; namespace CKAN { - public sealed class GUIMod + public sealed class GUIMod : INotifyPropertyChanged { - private CkanModule Mod { get; set; } - private InstalledModule InstalledMod { get; set; } + private CkanModule Mod { get; set; } + private CkanModule LatestCompatibleMod { get; set; } + private InstalledModule InstalledMod { get; set; } + + /// + /// The module of the checkbox that is checked in the MainAllModVersions list if any, + /// null otherwise. + /// Used for generating this mod's part of the change set. + /// + public CkanModule SelectedMod + { + get { return selectedMod; } + set + { + if (!(selectedMod?.Equals(value) ?? value?.Equals(selectedMod) ?? true)) + { + selectedMod = value; + var row = Main.Instance?.mainModList?.full_list_of_mod_rows?[Identifier]; + + if (IsInstalled && HasUpdate) + { + var isLatest = (LatestCompatibleMod?.Equals(selectedMod) ?? false); + if (IsUpgradeChecked ^ isLatest) + { + // Try upgrading if they pick the latest + Main.Instance.MarkModForUpdate(Identifier, isLatest); + } + + } + Main.Instance.MarkModForInstall(Identifier, selectedMod == null); + + Main.Instance.UpdateChangeSetAndConflicts( + RegistryManager.Instance(Main.Instance.Manager.CurrentInstance).registry + ); + + OnPropertyChanged(); + } + } + } + private CkanModule selectedMod = null; + + /// + /// Notify listeners when certain properties change. + /// Currently used to tell MainAllModVersions to update its checkboxes. + /// + public event PropertyChangedEventHandler PropertyChanged; + protected void OnPropertyChanged([CallerMemberName] string name = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); + } public string Name { get; private set; } public bool IsInstalled { get; private set; } @@ -85,6 +135,7 @@ public GUIMod(InstalledModule instMod, IRegistryQuerier registry, KspVersionCrit IsInstalled = true; IsInstallChecked = true; InstalledMod = instMod; + SelectedMod = instMod.Module; IsAutoInstalled = instMod.AutoInstalled; InstallDate = instMod.InstallTime; InstalledVersion = instMod.Module.version.ToString(); @@ -157,7 +208,8 @@ public GUIMod(string identifier, IRegistryQuerier registry, KspVersionCriteria c ModuleVersion latest_version = null; try { - latest_version = registry.LatestAvailable(identifier, current_ksp_version)?.version; + LatestCompatibleMod = registry.LatestAvailable(identifier, current_ksp_version); + latest_version = LatestCompatibleMod?.version; } catch (ModuleNotFoundKraken) { @@ -234,22 +286,32 @@ public CkanModule ToModule() return Mod; } - public KeyValuePair? GetRequestedChange() + public IEnumerable> GetRequestedChanges() { - if (IsInstalled ^ IsInstallChecked) + if (IsInstalled && !IsInstallChecked) + { + // Uninstall the version we have installed + yield return new KeyValuePair(InstalledMod.Module, GUIModChangeType.Remove); + } + else if (!IsInstalled && IsInstallChecked) + { + yield return new KeyValuePair(SelectedMod ?? Mod, GUIModChangeType.Install); + } + else if (IsInstalled && (IsInstallChecked && HasUpdate && IsUpgradeChecked)) { - var change_type = IsInstalled ? GUIModChangeType.Remove : GUIModChangeType.Install; - return new KeyValuePair(this, change_type); + yield return new KeyValuePair(Mod, GUIModChangeType.Update); } - if (IsInstalled && (IsInstallChecked && HasUpdate && IsUpgradeChecked)) + else if (IsReplaceChecked) { - return new KeyValuePair(this, GUIModChangeType.Update); + yield return new KeyValuePair(Mod, GUIModChangeType.Replace); } - if (IsReplaceChecked) + else if (IsInstalled + && SelectedMod != null + && !InstalledMod.Module.Equals(SelectedMod)) { - return new KeyValuePair(this, GUIModChangeType.Replace); + yield return new KeyValuePair(InstalledMod.Module, GUIModChangeType.Remove); + yield return new KeyValuePair(SelectedMod, GUIModChangeType.Install); } - return null; } /// @@ -282,14 +344,9 @@ public void SetRequestedChange(GUIModChangeType change) } } - public static implicit operator CkanModule(GUIMod mod) - { - return mod.ToModule(); - } - public void SetUpgradeChecked(DataGridViewRow row, DataGridViewColumn col, bool? set_value_to = null) { - var update_cell = row.Cells[col.Index] as DataGridViewCheckBoxCell; + var update_cell = row?.Cells[col.Index] as DataGridViewCheckBoxCell; if (update_cell != null) { var old_value = (bool) update_cell.Value; @@ -297,13 +354,22 @@ public void SetUpgradeChecked(DataGridViewRow row, DataGridViewColumn col, bool? bool value = set_value_to ?? old_value; IsUpgradeChecked = value; if (old_value != value) + { update_cell.Value = value; + SelectedMod = value ? LatestCompatibleMod : (SelectedMod ?? InstalledMod?.Module); + } + else if (!set_value_to.HasValue) + { + var isLatest = (LatestCompatibleMod?.Equals(selectedMod) ?? false); + SelectedMod = value ? LatestCompatibleMod + : isLatest ? InstalledMod?.Module : SelectedMod; + } } } public void SetInstallChecked(DataGridViewRow row, DataGridViewColumn col, bool? set_value_to = null) { - var install_cell = row.Cells[col.Index] as DataGridViewCheckBoxCell; + var install_cell = row?.Cells[col.Index] as DataGridViewCheckBoxCell; if (install_cell != null) { bool changeTo = set_value_to ?? (bool)install_cell.Value; @@ -311,6 +377,7 @@ public void SetInstallChecked(DataGridViewRow row, DataGridViewColumn col, bool? { IsInstallChecked = changeTo; } + SelectedMod = changeTo ? (SelectedMod ?? Mod) : null; // Setting this property causes ModList_CellValueChanged to be called, // which calls SetInstallChecked again. Treat it conservatively. if ((bool)install_cell.Value != IsInstallChecked) diff --git a/GUI/Main.cs b/GUI/Main.cs index beb0c43255..ea6c3278fe 100644 --- a/GUI/Main.cs +++ b/GUI/Main.cs @@ -150,6 +150,7 @@ private void ChangeSetUpdated() tabController.HideTab("ChangesetTabPage"); ApplyToolButton.Enabled = false; auditRecommendationsMenuItem.Enabled = true; + InstallAllCheckbox.Checked = true; } } @@ -483,7 +484,7 @@ protected override void OnFormClosing(FormClosingEventArgs e) { // Ask if they want to discard the change set string changeDescrip = ChangeSet - .GroupBy(ch => ch.ChangeType, ch => ch.Mod.Name) + .GroupBy(ch => ch.ChangeType, ch => ch.Mod.name) .Select(grp => $"{grp.Key}: " + grp.Aggregate((a, b) => $"{a}, {b}")) .Aggregate((a, b) => $"{a}\r\n{b}"); @@ -595,7 +596,7 @@ private void MarkAllUpdatesToolButton_Click(object sender, EventArgs e) var mod = (GUIMod)row.Tag; if (mod.HasUpdate) { - MarkModForUpdate(mod.Identifier); + MarkModForUpdate(mod.Identifier, true); } } @@ -713,7 +714,7 @@ private void OnFilterUpdateTimer(object source, EventArgs e) filterTimer.Stop(); } - private async Task UpdateChangeSetAndConflicts(IRegistryQuerier registry) + public async Task UpdateChangeSetAndConflicts(IRegistryQuerier registry) { IEnumerable full_change_set = null; Dictionary new_conflicts = null; @@ -1230,7 +1231,7 @@ private void reinstallToolStripMenuItem_Click(object sender, EventArgs e) // Build the list of changes, first the mod to remove: List toReinstall = new List() { - new ModChange(module, GUIModChangeType.Remove, null) + new ModChange(module.ToModule(), GUIModChangeType.Remove, null) }; // Then everything we need to re-install: var revdep = registry.FindReverseDependencies(new List() { module.Identifier }); @@ -1242,7 +1243,7 @@ private void reinstallToolStripMenuItem_Click(object sender, EventArgs e) foreach (string id in goners) { toReinstall.Add(new ModChange( - mainModList.full_list_of_mod_rows[id]?.Tag as GUIMod, + (mainModList.full_list_of_mod_rows[id]?.Tag as GUIMod).ToModule(), GUIModChangeType.Install, null )); diff --git a/GUI/MainAllModVersions.Designer.cs b/GUI/MainAllModVersions.Designer.cs index 0d633811ee..575dde85fe 100644 --- a/GUI/MainAllModVersions.Designer.cs +++ b/GUI/MainAllModVersions.Designer.cs @@ -57,7 +57,7 @@ private void InitializeComponent() // // ModVersion // - this.ModVersion.Width = 73; + this.ModVersion.Width = 98; resources.ApplyResources(this.ModVersion, "ModVersion"); // // CompatibleKSPVersion @@ -73,6 +73,7 @@ private void InitializeComponent() this.VersionsListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { this.ModVersion, this.CompatibleKSPVersion}); + this.VersionsListView.CheckBoxes = true; this.VersionsListView.FullRowSelect = true; this.VersionsListView.Items.AddRange(new System.Windows.Forms.ListViewItem[] { listViewItem4}); @@ -82,7 +83,7 @@ private void InitializeComponent() this.VersionsListView.TabIndex = 1; this.VersionsListView.UseCompatibleStateImageBehavior = false; this.VersionsListView.View = System.Windows.Forms.View.Details; - this.VersionsListView.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.VersionsListView_DoubleClick); + this.VersionsListView.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.VersionsListView_ItemCheck); // // label2 // diff --git a/GUI/MainAllModVersions.cs b/GUI/MainAllModVersions.cs index 99b5fbffec..03822e2233 100644 --- a/GUI/MainAllModVersions.cs +++ b/GUI/MainAllModVersions.cs @@ -1,3 +1,4 @@ +using System.ComponentModel; using System.Collections.Generic; using System.Drawing; using System.Data; @@ -14,30 +15,70 @@ public MainAllModVersions() InitializeComponent(); } - /// - /// React to double click of a version by prompting to install - /// - /// The version list view - /// The mouse click event - public void VersionsListView_DoubleClick(object sender, MouseEventArgs e) + private GUIMod visibleGuiModule = null; + private bool ignoreItemCheck = false; + + private async void VersionsListView_ItemCheck(object sender, ItemCheckEventArgs e) { - ListViewHitTestInfo info = ((ListView)sender).HitTest(e.X, e.Y); - ListViewItem item = info.Item; - CkanModule module = item.Tag as CkanModule; + if (ignoreItemCheck || e.CurrentValue == e.NewValue) + { + return; + } + ListViewItem item = VersionsListView.Items[e.Index]; + CkanModule module = item.Tag as CkanModule; + switch (e.NewValue) + { + case CheckState.Checked: + if (allowInstall(module)) + { + // Add this version to the change set + visibleGuiModule.SelectedMod = module; + } + else + { + // Abort! Abort! + e.NewValue = CheckState.Unchecked; + } + break; + + case CheckState.Unchecked: + // Remove or cancel installation + visibleGuiModule.SelectedMod = null; + break; + } + } - if (module.IsCompatibleKSP(Main.Instance.Manager.CurrentInstance.VersionCriteria()) - && Main.Instance.YesNoDialog( + private bool allowInstall(CkanModule module) + { + return module.IsCompatibleKSP(Main.Instance.Manager.CurrentInstance.VersionCriteria()) + || Main.Instance.YesNoDialog( string.Format(Properties.Resources.MainAllModVersionsInstallPrompt, module.ToString()), Properties.Resources.MainAllModVersionsInstallYes, - Properties.Resources.MainAllModVersionsInstallNo)) + Properties.Resources.MainAllModVersionsInstallNo); + } + + private void visibleGuiModule_PropertyChanged(object sender, PropertyChangedEventArgs e) + { + switch (e.PropertyName) { - Main.Instance.InstallModuleDriver( - RegistryManager.Instance(Main.Instance.Manager.CurrentInstance).registry, - module - ); + case "SelectedMod": + UpdateSelection(); + break; } } + private void UpdateSelection() + { + bool prevIgnore = ignoreItemCheck; + ignoreItemCheck = true; + foreach (ListViewItem item in VersionsListView.Items) + { + CkanModule module = item.Tag as CkanModule; + item.Checked = module.Equals(visibleGuiModule.SelectedMod); + } + ignoreItemCheck = prevIgnore; + } + /// /// Make the ListView redraw itself. /// Works around a problem where the headers aren't drawn when this tab activates. @@ -51,6 +92,20 @@ public GUIMod SelectedModule { set { + ignoreItemCheck = true; + if (!(visibleGuiModule?.Equals(value) ?? value?.Equals(visibleGuiModule) ?? true)) + { + // Listen for property changes (we only care about GUIMod.SelectedMod) + if (visibleGuiModule != null) + { + visibleGuiModule.PropertyChanged -= visibleGuiModule_PropertyChanged; + } + visibleGuiModule = value; + if (visibleGuiModule != null) + { + visibleGuiModule.PropertyChanged += visibleGuiModule_PropertyChanged; + } + } VersionsListView.Items.Clear(); KSP currentInstance = Main.Instance.Manager.CurrentInstance; @@ -105,8 +160,13 @@ public GUIMod SelectedModule { toRet.Font = new Font(toRet.Font, FontStyle.Bold); } + if (module.Equals(value.SelectedMod)) + { + toRet.Checked = true; + } return toRet; }).ToArray()); + ignoreItemCheck = false; } } } diff --git a/GUI/MainChangeset.cs b/GUI/MainChangeset.cs index 4723a24d5d..498874bb53 100644 --- a/GUI/MainChangeset.cs +++ b/GUI/MainChangeset.cs @@ -46,7 +46,7 @@ public void UpdateChangesDialog(List changeset, BackgroundWorker inst continue; } - CkanModule m = change.Mod.ToModule(); + CkanModule m = change.Mod; ListViewItem item = new ListViewItem() { Text = m.IsMetapackage @@ -55,7 +55,7 @@ public void UpdateChangesDialog(List changeset, BackgroundWorker inst ? string.Format(Properties.Resources.MainChangesetCached, m.name, m.version) : string.Format(Properties.Resources.MainChangesetHostSize, m.name, m.version, m.download.Host ?? "", CkanModule.FmtSize(m.download_size)), - Tag = change.Mod.ToModule() + Tag = change.Mod }; var sub_change_type = new ListViewItem.ListViewSubItem {Text = change.ChangeType.ToString()}; @@ -65,7 +65,7 @@ public void UpdateChangesDialog(List changeset, BackgroundWorker inst if (change.ChangeType == GUIModChangeType.Update) { - description.Text = String.Format(Properties.Resources.MainChangesetUpdateSelected, change.Mod.LatestVersion); + description.Text = String.Format(Properties.Resources.MainChangesetUpdateSelected, change.Mod.version); } if (change.ChangeType == GUIModChangeType.Install && change.Reason is SelectionReason.UserRequested) @@ -100,7 +100,7 @@ private void ClearChangeSet() /// So we get for example "ModuleRCSFX" directly after "USI Exploration Pack" /// /// It is very likely that this is forward-compatible with new ChangeTypes's, - /// like a a "reconfigure" changetype, but only the future will tell + /// like a "reconfigure" changetype, but only the future will tell /// /// Every leftover ModChange that should be sorted /// @@ -108,11 +108,11 @@ private void CreateSortedModList(IEnumerable changes, ModChange paren { foreach (ModChange change in changes) { - bool goDeeper = parent == null || change.Reason.Parent.identifier == parent.Mod.Identifier; + bool goDeeper = parent == null || change.Reason.Parent.identifier == parent.Mod.identifier; if (goDeeper) { - if (!changeSet.Any(c => c.Mod.Identifier == change.Mod.Identifier)) + if (!changeSet.Any(c => c.Mod.identifier == change.Mod.identifier && c.ChangeType != GUIModChangeType.Remove)) changeSet.Add(change); CreateSortedModList(changes.Where(c => !(c.Reason is SelectionReason.UserRequested)), change); } diff --git a/GUI/MainInstall.cs b/GUI/MainInstall.cs index a82d35e170..726e5b873a 100644 --- a/GUI/MainInstall.cs +++ b/GUI/MainInstall.cs @@ -34,14 +34,14 @@ public async void InstallModuleDriver(IRegistryQuerier registry, CkanModule modu { // Already installed, remove it first userChangeSet.Add(new ModChange( - new GUIMod(installed.Module, registry, CurrentInstance.VersionCriteria()), + installed.Module, GUIModChangeType.Remove, null )); } // Install the selected mod userChangeSet.Add(new ModChange( - new GUIMod(module, registry, CurrentInstance.VersionCriteria()), + module, GUIModChangeType.Install, null )); @@ -64,7 +64,7 @@ public async void InstallModuleDriver(IRegistryQuerier registry, CkanModule modu } finally { - changeSet = null; + ChangeSet = null; } } @@ -94,16 +94,16 @@ private void InstallMods(object sender, DoWorkEventArgs e) switch (change.ChangeType) { case GUIModChangeType.Remove: - toUninstall.Add(change.Mod.Identifier); + toUninstall.Add(change.Mod.identifier); break; case GUIModChangeType.Update: - toUpgrade.Add(change.Mod.Identifier); + toUpgrade.Add(change.Mod.identifier); break; case GUIModChangeType.Install: - toInstall.Add(change.Mod.ToModule()); + toInstall.Add(change.Mod); break; case GUIModChangeType.Replace: - ModuleReplacement repl = registry.GetReplacement(change.Mod.ToModule(), CurrentInstance.VersionCriteria()); + ModuleReplacement repl = registry.GetReplacement(change.Mod, CurrentInstance.VersionCriteria()); if (repl != null) { toUninstall.Add(repl.ToReplace.identifier); @@ -116,7 +116,7 @@ private void InstallMods(object sender, DoWorkEventArgs e) // Prompt for recommendations and suggestions, if any var recRows = getRecSugRows( opts.Key.Where(ch => ch.ChangeType == GUIModChangeType.Install) - .Select(ch => ch.Mod.ToModule()), + .Select(ch => ch.Mod), registry, toInstall ); if (recRows.Any()) diff --git a/GUI/MainModInfo.cs b/GUI/MainModInfo.cs index dc737e7386..3b990ed4f7 100644 --- a/GUI/MainModInfo.cs +++ b/GUI/MainModInfo.cs @@ -46,14 +46,14 @@ public GUIMod SelectedModule } else { - var module = value; + var module = value.ToModule(); ModInfoTabControl.Enabled = module != null; if (module == null) return; - UpdateModInfo(module); + UpdateModInfo(value); UpdateModDependencyGraph(module); UpdateModContentsTree(module); - AllModVersions.SelectedModule = module; + AllModVersions.SelectedModule = value; } } get @@ -124,7 +124,7 @@ private void ContentsDownloadButton_Click(object sender, EventArgs e) private void ContentsOpenButton_Click(object sender, EventArgs e) { - Process.Start(manager.Cache.GetCachedFilename(SelectedModule)); + Process.Start(manager.Cache.GetCachedFilename(SelectedModule.ToModule())); } private void LinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) diff --git a/GUI/MainModList.cs b/GUI/MainModList.cs index 8b7bc8d23b..dc55a7ccd1 100644 --- a/GUI/MainModList.cs +++ b/GUI/MainModList.cs @@ -199,18 +199,6 @@ private void _UpdateModsList(IEnumerable mc, Dictionary .Select(m => new GUIMod(m, registry, versionCriteria, true)) ); - if (mc != null) - { - AddLogMessage(Properties.Resources.MainModListRestoringChangeset); - foreach (ModChange change in mc) - { - // Propagate IsInstallChecked and IsUpgradeChecked to the next generation - gui_mods.FirstOrDefault( - mod => mod.Identifier == change.Mod.Identifier - )?.SetRequestedChange(change.ChangeType); - } - } - AddLogMessage(Properties.Resources.MainModListPreservingNew); if (old_modules != null) { @@ -309,29 +297,24 @@ public void MarkModForInstall(string identifier, bool uncheck = false) private void _MarkModForInstall(string identifier, bool uninstall) { - if (!mainModList.full_list_of_mod_rows.ContainsKey(identifier)) - { - return; - } - DataGridViewRow row = mainModList.full_list_of_mod_rows[identifier]; - - var mod = (GUIMod)row.Tag; - if (mod.Identifier == identifier) + DataGridViewRow row = mainModList?.full_list_of_mod_rows?[identifier]; + var mod = (GUIMod)row?.Tag; + if (mod?.Identifier == identifier) { mod.SetInstallChecked(row, Installed, !uninstall); } } - public void MarkModForUpdate(string identifier) + public void MarkModForUpdate(string identifier, bool value) { - Util.Invoke(this, () => _MarkModForUpdate(identifier)); + Util.Invoke(this, () => _MarkModForUpdate(identifier, value)); } - public void _MarkModForUpdate(string identifier) + public void _MarkModForUpdate(string identifier, bool value) { DataGridViewRow row = mainModList.full_list_of_mod_rows[identifier]; var mod = (GUIMod)row.Tag; - mod.SetUpgradeChecked(row, UpdateCol, true); + mod.SetUpgradeChecked(row, UpdateCol, value); } private void ModList_SelectedIndexChanged(object sender, EventArgs e) @@ -772,15 +755,13 @@ public async Task> ComputeChangeSetFromModList( break; case GUIModChangeType.Update: case GUIModChangeType.Install: - //TODO: Fix - //This will give us a mod with a wrong version! - modules_to_install.Add(change.Mod.ToCkanModule()); + modules_to_install.Add(change.Mod); break; case GUIModChangeType.Remove: modules_to_remove.Add(change.Mod); break; case GUIModChangeType.Replace: - ModuleReplacement repl = registry.GetReplacement(change.Mod.ToModule(), version); + ModuleReplacement repl = registry.GetReplacement(change.Mod, version); if (repl != null) { modules_to_remove.Add(repl.ToReplace); @@ -800,17 +781,22 @@ public async Task> ComputeChangeSetFromModList( .Except(modules_to_install.Select(m => m.identifier)) )) { - //TODO This would be a good place to have a event that alters the row's graphics to show it will be removed - CkanModule module_by_version = registry.GetModuleByVersion(installed_modules[dependency].identifier, - installed_modules[dependency].version) ?? registry.InstalledModule(dependency).Module; - changeSet.Add(new ModChange(new GUIMod(module_by_version, registry, version), GUIModChangeType.Remove, null)); - modules_to_remove.Add(module_by_version); + //TODO This would be a good place to have an event that alters the row's graphics to show it will be removed + CkanModule depMod; + if (installed_modules.TryGetValue(dependency, out depMod)) + { + CkanModule module_by_version = registry.GetModuleByVersion(depMod.identifier, + depMod.version) + ?? registry.InstalledModule(dependency).Module; + changeSet.Add(new ModChange(module_by_version, GUIModChangeType.Remove, null)); + modules_to_remove.Add(module_by_version); + } } foreach (var im in registry.FindRemovableAutoInstalled( - registry.InstalledModules.Where(im => !modules_to_remove.Any(m => m.identifier == im.identifier)) + registry.InstalledModules.Where(im => !modules_to_remove.Any(m => m.identifier == im.identifier) || modules_to_install.Any(m => m.identifier == im.identifier)) )) { - changeSet.Add(new ModChange(new GUIMod(im.Module, registry, version), GUIModChangeType.Remove, new SelectionReason.NoLongerUsed())); + changeSet.Add(new ModChange(im.Module, GUIModChangeType.Remove, new SelectionReason.NoLongerUsed())); modules_to_remove.Add(im.Module); } @@ -825,7 +811,7 @@ public async Task> ComputeChangeSetFromModList( opts, registry, version); changeSet.UnionWith( resolver.ModList() - .Select(m => new ModChange(new GUIMod(m, registry, version), GUIModChangeType.Install, resolver.ReasonFor(m)))); + .Select(m => new ModChange(m, GUIModChangeType.Install, resolver.ReasonFor(m)))); return changeSet; } @@ -875,7 +861,7 @@ private DataGridViewRow MakeRow(GUIMod mod, List changes, bool hideEp { DataGridViewRow item = new DataGridViewRow() {Tag = mod}; - ModChange myChange = changes?.FindLast((ModChange ch) => ch.Mod.Identifier == mod.Identifier); + ModChange myChange = changes?.FindLast((ModChange ch) => ch.Mod.Equals(mod)); var selecting = mod.IsInstallable() ? (DataGridViewCell) new DataGridViewCheckBoxCell() @@ -1040,15 +1026,15 @@ public static Dictionary ComputeConflictsFromModList(IRegistryQu case GUIModChangeType.None: break; case GUIModChangeType.Install: - modules_to_install.Add(change.Mod.Identifier); + modules_to_install.Add(change.Mod.identifier); break; case GUIModChangeType.Remove: - modules_to_remove.Add(change.Mod.Identifier); + modules_to_remove.Add(change.Mod.identifier); break; case GUIModChangeType.Update: break; case GUIModChangeType.Replace: - ModuleReplacement repl = registry.GetReplacement(change.Mod.ToModule(), ksp_version); + ModuleReplacement repl = registry.GetReplacement(change.Mod, ksp_version); if (repl != null) { modules_to_remove.Add(repl.ToReplace.identifier); @@ -1075,7 +1061,7 @@ public static Dictionary ComputeConflictsFromModList(IRegistryQu var resolver = new RelationshipResolver( mods_to_check, change_set.Where(ch => ch.ChangeType == GUIModChangeType.Remove) - .Select(ch => ch.Mod.ToModule()), + .Select(ch => ch.Mod), options, registry, ksp_version ); return resolver.ConflictList.ToDictionary(item => new GUIMod(item.Key, registry, ksp_version), @@ -1089,12 +1075,10 @@ public HashSet ComputeUserChangeSet(IRegistryQuerier registry) return new HashSet( Modules .Where(mod => mod.IsInstallable()) - .Select(mod => mod.GetRequestedChange()) - .Where(change => change.HasValue) - .Select(change => change.Value) + .SelectMany(mod => mod.GetRequestedChanges()) .Select(change => new ModChange(change.Key, change.Value, null)) .Union(removableAuto.Select(im => new ModChange( - new GUIMod(im, registry, Main.Instance.CurrentInstance.VersionCriteria()), + im.Module, GUIModChangeType.Remove, new SelectionReason.NoLongerUsed()))) ); diff --git a/GUI/MainRecommendations.cs b/GUI/MainRecommendations.cs index b6d8052406..57fb41106a 100644 --- a/GUI/MainRecommendations.cs +++ b/GUI/MainRecommendations.cs @@ -314,7 +314,7 @@ private void AuditRecommendations(IRegistryQuerier registry, KspVersionCriteria installWorker.RunWorkerAsync( new KeyValuePair, RelationshipResolverOptions>( toInstall.Select(mod => new ModChange( - new GUIMod(mod, registry, versionCriteria), + mod, GUIModChangeType.Install, null )).ToList(), diff --git a/GUI/ModChange.cs b/GUI/ModChange.cs index 6bbe22aa56..b25b50d801 100644 --- a/GUI/ModChange.cs +++ b/GUI/ModChange.cs @@ -16,11 +16,11 @@ public enum GUIModChangeType /// public class ModChange { - public GUIMod Mod { get; private set; } + public CkanModule Mod { get; private set; } public GUIModChangeType ChangeType { get; private set; } public SelectionReason Reason { get; private set; } - public ModChange(GUIMod mod, GUIModChangeType changeType, SelectionReason reason) + public ModChange(CkanModule mod, GUIModChangeType changeType, SelectionReason reason) { Mod = mod; ChangeType = changeType; @@ -39,7 +39,7 @@ public override bool Equals(object obj) if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; if (obj.GetType() != this.GetType()) return false; - return (obj as ModChange).Mod.Identifier == Mod.Identifier; + return (obj as ModChange).Mod.Equals(Mod); } public override int GetHashCode() diff --git a/GUI/Properties/Resources.de-DE.resx b/GUI/Properties/Resources.de-DE.resx index 6b99999016..280d950905 100644 --- a/GUI/Properties/Resources.de-DE.resx +++ b/GUI/Properties/Resources.de-DE.resx @@ -177,7 +177,9 @@ Klartext (*.txt) Nicht gefunden. Möchtest du {0} neu installieren? - {0} installieren? + {0} wird von Ihrer aktuellen Spielversion nicht unterstützt und funktioniert möglicherweise überhaupt nicht. Wenn Sie Probleme damit haben, sollten Sie die Betreuer NICHT um Hilfe bitten. + +Möchten Sie es wirklich installieren? Installieren Abbrechen {0} {1} (Metapacket) diff --git a/GUI/Properties/Resources.resx b/GUI/Properties/Resources.resx index 89e4ffbc65..a3ca9c673b 100644 --- a/GUI/Properties/Resources.resx +++ b/GUI/Properties/Resources.resx @@ -7006,7 +7006,9 @@ Tab-separated values (*.tsv) Not found. Do you want to reinstall {0}? - Install {0}? + {0} is not supported on your current game version and may not work at all. If you have any problems with it, you should NOT ask its maintainers for help. + +Do you really want to install it? Install Cancel {0} {1} (metapackage) diff --git a/Tests/GUI/GH1866.cs b/Tests/GUI/GH1866.cs index 6709e45135..8021bc5717 100644 --- a/Tests/GUI/GH1866.cs +++ b/Tests/GUI/GH1866.cs @@ -137,7 +137,7 @@ public void TestSimple() { // perform the install of the "other" module - now we need to sort ModuleInstaller.GetInstance(_instance.KSP, _manager.Cache, _manager.User).InstallList( - _modList.ComputeUserChangeSet(null).Select(change => change.Mod.ToCkanModule()).ToList(), + _modList.ComputeUserChangeSet(null).Select(change => change.Mod).ToList(), new RelationshipResolverOptions(), new NetAsyncModulesDownloader(_manager.User, _manager.Cache) );