/// <summary> /// Tries to get every mod in the Dictionary, which can be installed /// It also transforms the Recommender list to a string /// </summary> /// <param name="mods"></param> /// <returns></returns> private Dictionary <CkanModule, string> GetShowableMods(Dictionary <string, List <string> > mods) { Dictionary <CkanModule, string> modules = new Dictionary <CkanModule, string>(); var opts = new RelationshipResolverOptions { with_all_suggests = false, with_recommends = false, with_suggests = false, without_enforce_consistency = false, without_toomanyprovides_kraken = true }; foreach (var pair in mods) { CkanModule module; try { var resolver = new RelationshipResolver(new List <string> { pair.Key }, opts, RegistryManager.Instance(manager.CurrentInstance).registry, CurrentInstance.VersionCriteria()); if (!resolver.ModList().Any()) { continue; } module = RegistryManager.Instance(manager.CurrentInstance) .registry.LatestAvailable(pair.Key, CurrentInstance.VersionCriteria()); } catch { continue; } if (module == null) { continue; } modules.Add(module, String.Join(",", pair.Value.ToArray())); } return(modules); }
private void _UpdateModsList(IEnumerable <ModChange> mc, Dictionary <string, bool> old_modules = null) { log.Info("Updating the mod list"); ResetProgress(); tabController.RenameTab("WaitTabPage", "Loading modules"); ShowWaitDialog(false); tabController.SetTabLock(true); Util.Invoke(this, SwitchEnabledState); ClearLog(); AddLogMessage("Loading registry..."); KspVersionCriteria versionCriteria = CurrentInstance.VersionCriteria(); IRegistryQuerier registry = RegistryManager.Instance(CurrentInstance).registry; AddLogMessage("Loading installed modules..."); var gui_mods = new HashSet <GUIMod>(); gui_mods.UnionWith( registry.InstalledModules .Select(instMod => new GUIMod(instMod, registry, versionCriteria)) ); AddLogMessage("Loading available modules..."); gui_mods.UnionWith( registry.Available(versionCriteria) .Select(m => new GUIMod(m, registry, versionCriteria)) ); AddLogMessage("Loading incompatible modules..."); gui_mods.UnionWith( registry.Incompatible(versionCriteria) .Select(m => new GUIMod(m, registry, versionCriteria, true)) ); if (mc != null) { AddLogMessage("Restoring change set..."); 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("Preserving new flags..."); if (old_modules != null) { foreach (GUIMod gm in gui_mods) { bool oldIncompat; if (old_modules.TryGetValue(gm.Identifier, out oldIncompat)) { // Found it; check if newly compatible if (!gm.IsIncompatible && oldIncompat) { gm.IsNew = true; } } else { // Newly indexed, show regardless of compatibility gm.IsNew = true; } } } else { // Copy the new mod flag from the old list. var old_new_mods = new HashSet <GUIMod>( mainModList.Modules.Where(m => m.IsNew)); foreach (var gui_mod in gui_mods.Where(m => old_new_mods.Contains(m))) { gui_mod.IsNew = true; } } AddLogMessage("Populating mod list..."); // Update our mod listing mainModList.ConstructModList(gui_mods.ToList(), mc, configuration.HideEpochs, configuration.HideV); mainModList.Modules = new ReadOnlyCollection <GUIMod>( mainModList.full_list_of_mod_rows.Values.Select(row => row.Tag as GUIMod).ToList()); AddLogMessage("Updating filters..."); var has_any_updates = gui_mods.Any(mod => mod.HasUpdate); var has_any_installed = gui_mods.Any(mod => mod.IsInstalled); var has_any_replacements = gui_mods.Any(mod => mod.IsInstalled && mod.HasReplacement); //TODO Consider using smart enumeration pattern so stuff like this is easier Util.Invoke(menuStrip2, () => { FilterToolButton.DropDownItems[0].Text = String.Format("Compatible ({0})", mainModList.CountModsByFilter(GUIModFilter.Compatible)); FilterToolButton.DropDownItems[1].Text = String.Format("Installed ({0})", mainModList.CountModsByFilter(GUIModFilter.Installed)); FilterToolButton.DropDownItems[2].Text = String.Format("Upgradeable ({0})", mainModList.CountModsByFilter(GUIModFilter.InstalledUpdateAvailable)); FilterToolButton.DropDownItems[3].Text = String.Format("Replaceable ({0})", mainModList.CountModsByFilter(GUIModFilter.Replaceable)); FilterToolButton.DropDownItems[4].Text = String.Format("Cached ({0})", mainModList.CountModsByFilter(GUIModFilter.Cached)); FilterToolButton.DropDownItems[5].Text = String.Format("Newly compatible ({0})", mainModList.CountModsByFilter(GUIModFilter.NewInRepository)); FilterToolButton.DropDownItems[6].Text = String.Format("Not installed ({0})", mainModList.CountModsByFilter(GUIModFilter.NotInstalled)); FilterToolButton.DropDownItems[7].Text = String.Format("Incompatible ({0})", mainModList.CountModsByFilter(GUIModFilter.Incompatible)); FilterToolButton.DropDownItems[8].Text = String.Format("All ({0})", mainModList.CountModsByFilter(GUIModFilter.All)); UpdateAllToolButton.Enabled = has_any_updates; }); UpdateFilters(this); // Hide update and replacement columns if not needed. // Write it to the configuration, else they are hidden agian after a filter change. // After the update / replacement, they are hidden again. ModList.Columns["UpdateCol"].Visible = has_any_updates; ModList.Columns["AutoInstalled"].Visible = has_any_installed && !configuration.HiddenColumnNames.Contains("AutoInstalled"); ModList.Columns["ReplaceCol"].Visible = has_any_replacements; AddLogMessage("Updating tray..."); UpdateTrayInfo(); HideWaitDialog(true); tabController.HideTab("WaitTabPage"); tabController.SetTabLock(false); Util.Invoke(this, SwitchEnabledState); Util.Invoke(this, () => Main.Instance.ModList.Focus()); }
// this probably needs to be refactored private void InstallMods(object sender, DoWorkEventArgs e) { installCanceled = false; Wait.ClearLog(); var opts = (KeyValuePair <ModChanges, RelationshipResolverOptions>)e.Argument; RegistryManager registry_manager = RegistryManager.Instance(manager.CurrentInstance); Registry registry = registry_manager.registry; ModuleInstaller installer = ModuleInstaller.GetInstance(CurrentInstance, Manager.Cache, currentUser); // Avoid accumulating multiple event handlers installer.onReportModInstalled -= OnModInstalled; installer.onReportModInstalled += OnModInstalled; // setup progress callback // this will be the final list of mods we want to install HashSet <CkanModule> toInstall = new HashSet <CkanModule>(); var toUninstall = new HashSet <CkanModule>(); var toUpgrade = new HashSet <CkanModule>(); // First compose sets of what the user wants installed, upgraded, and removed. foreach (ModChange change in opts.Key) { switch (change.ChangeType) { case GUIModChangeType.Remove: toUninstall.Add(change.Mod); break; case GUIModChangeType.Update: toUpgrade.Add(change is ModUpgrade mu ? mu.targetMod : change.Mod); break; case GUIModChangeType.Install: toInstall.Add(change.Mod); break; case GUIModChangeType.Replace: ModuleReplacement repl = registry.GetReplacement(change.Mod, CurrentInstance.VersionCriteria()); if (repl != null) { toUninstall.Add(repl.ToReplace); toInstall.Add(repl.ReplaceWith); } break; } } // Prompt for recommendations and suggestions, if any if (installer.FindRecommendations( opts.Key.Where(ch => ch.ChangeType == GUIModChangeType.Install) .Select(ch => ch.Mod) .ToHashSet(), toInstall, registry, out Dictionary <CkanModule, Tuple <bool, List <string> > > recommendations, out Dictionary <CkanModule, List <string> > suggestions, out Dictionary <CkanModule, HashSet <string> > supporters )) { tabController.ShowTab("ChooseRecommendedModsTabPage", 3); ChooseRecommendedMods.LoadRecommendations( registry, toInstall, toUninstall, CurrentInstance.VersionCriteria(), Manager.Cache, recommendations, suggestions, supporters); tabController.SetTabLock(true); var result = ChooseRecommendedMods.Wait(); if (result == null) { installCanceled = true; } else { toInstall.UnionWith(result); } tabController.SetTabLock(false); tabController.HideTab("ChooseRecommendedModsTabPage"); } if (installCanceled) { tabController.ShowTab("ManageModsTabPage"); e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key); return; } // Now let's make all our changes. Util.Invoke(this, () => { // Need to be on the GUI thread to get the translated string tabController.RenameTab("WaitTabPage", Properties.Resources.MainInstallWaitTitle); }); ShowWaitDialog(); tabController.SetTabLock(true); IDownloader downloader = new NetAsyncModulesDownloader(currentUser, Manager.Cache); downloader.Progress += Wait.SetModuleProgress; downloader.AllComplete += Wait.DownloadsComplete; cancelCallback = () => { downloader.CancelDownload(); installCanceled = true; }; HashSet <string> possibleConfigOnlyDirs = null; // checks if all actions were successfull bool processSuccessful = false; bool resolvedAllProvidedMods = false; // uninstall/installs/upgrades until every list is empty // if the queue is NOT empty, resolvedAllProvidedMods is set to false until the action is done while (!resolvedAllProvidedMods) { try { e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key); if (toUninstall.Count > 0) { processSuccessful = false; if (!installCanceled) { installer.UninstallList(toUninstall.Select(m => m.identifier), ref possibleConfigOnlyDirs, registry_manager, false, toInstall); processSuccessful = true; } } if (toUpgrade.Count > 0) { processSuccessful = false; if (!installCanceled) { installer.Upgrade(toUpgrade, downloader, ref possibleConfigOnlyDirs, registry_manager, true, true, false); processSuccessful = true; } } if (toInstall.Count > 0) { processSuccessful = false; if (!installCanceled) { installer.InstallList(toInstall, opts.Value, registry_manager, ref possibleConfigOnlyDirs, downloader, false); processSuccessful = true; } } HandlePossibleConfigOnlyDirs(registry, possibleConfigOnlyDirs); e.Result = new KeyValuePair <bool, ModChanges>(processSuccessful, opts.Key); if (installCanceled) { return; } resolvedAllProvidedMods = true; } catch (TooManyModsProvideKraken k) { // Prompt user to choose which mod to use tabController.ShowTab("ChooseProvidedModsTabPage", 3); ChooseProvidedMods.LoadProviders(k.requested, k.modules, Manager.Cache); tabController.SetTabLock(true); CkanModule chosen = ChooseProvidedMods.Wait(); // Close the selection prompt tabController.SetTabLock(false); tabController.HideTab("ChooseProvidedModsTabPage"); if (chosen != null) { // User picked a mod, queue it up for installation toInstall.Add(chosen); // DON'T return so we can loop around and try the above InstallList call again tabController.ShowTab("WaitTabPage"); } else { // User cancelled, get out tabController.ShowTab("ManageModsTabPage"); e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key); return; } } } }
// this probably needs to be refactored private void InstallMods(object sender, DoWorkEventArgs e) { installCanceled = false; ClearLog(); var opts = (KeyValuePair <ModChanges, RelationshipResolverOptions>)e.Argument; IRegistryQuerier registry = RegistryManager.Instance(manager.CurrentInstance).registry; ModuleInstaller installer = ModuleInstaller.GetInstance(CurrentInstance, Manager.Cache, GUI.user); // Avoid accumulating multiple event handlers installer.onReportModInstalled -= OnModInstalled; installer.onReportModInstalled += OnModInstalled; // setup progress callback // this will be the final list of mods we want to install HashSet <CkanModule> toInstall = new HashSet <CkanModule>(); var toUninstall = new HashSet <string>(); var toUpgrade = new HashSet <string>(); // First compose sets of what the user wants installed, upgraded, and removed. foreach (ModChange change in opts.Key) { switch (change.ChangeType) { case GUIModChangeType.Remove: toUninstall.Add(change.Mod.identifier); break; case GUIModChangeType.Update: toUpgrade.Add(change.Mod.identifier); break; case GUIModChangeType.Install: toInstall.Add(change.Mod); break; case GUIModChangeType.Replace: ModuleReplacement repl = registry.GetReplacement(change.Mod, CurrentInstance.VersionCriteria()); if (repl != null) { toUninstall.Add(repl.ToReplace.identifier); toInstall.Add(repl.ReplaceWith); } break; } } // Prompt for recommendations and suggestions, if any var recRows = getRecSugRows( opts.Key.Where(ch => ch.ChangeType == GUIModChangeType.Install) .Select(ch => ch.Mod), registry, toInstall ); if (recRows.Any()) { ShowRecSugDialog(recRows, toInstall); } tabController.HideTab("ChooseRecommendedModsTabPage"); if (installCanceled) { tabController.ShowTab("ManageModsTabPage"); e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key); return; } // Now let's make all our changes. tabController.RenameTab("WaitTabPage", Properties.Resources.MainInstallWaitTitle); ShowWaitDialog(); tabController.SetTabLock(true); IDownloader downloader = new NetAsyncModulesDownloader(GUI.user, Manager.Cache); cancelCallback = () => { downloader.CancelDownload(); installCanceled = true; }; // checks if all actions were successfull bool processSuccessful = false; bool resolvedAllProvidedMods = false; // uninstall/installs/upgrades until every list is empty // if the queue is NOT empty, resolvedAllProvidedMods is set to false until the action is done while (!resolvedAllProvidedMods) { try { e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key); if (toUninstall.Count > 0) { processSuccessful = false; if (!installCanceled) { installer.UninstallList(toUninstall, false, toInstall.Select(m => m.identifier)); processSuccessful = true; } } if (toUpgrade.Count > 0) { processSuccessful = false; if (!installCanceled) { installer.Upgrade(toUpgrade, downloader); processSuccessful = true; } } if (toInstall.Count > 0) { processSuccessful = false; if (!installCanceled) { installer.InstallList(toInstall, opts.Value, downloader, false); processSuccessful = true; } } e.Result = new KeyValuePair <bool, ModChanges>(processSuccessful, opts.Key); if (installCanceled) { return; } resolvedAllProvidedMods = true; } catch (TooManyModsProvideKraken k) { // Prompt user to choose which mod to use CkanModule chosen = TooManyModsProvideCore(k).Result; // Close the selection prompt Util.Invoke(this, () => { tabController.ShowTab("WaitTabPage"); tabController.HideTab("ChooseProvidedModsTabPage"); }); if (chosen != null) { // User picked a mod, queue it up for installation toInstall.Add(chosen); // DON'T return so we can loop around and try the above InstallList call again } else { // User cancelled, get out tabController.ShowTab("ManageModsTabPage"); e.Result = new KeyValuePair <bool, ModChanges>(false, opts.Key); return; } } catch (DependencyNotSatisfiedKraken ex) { GUI.user.RaiseMessage(Properties.Resources.MainInstallDepNotSatisfied, ex.parent, ex.module); return; } catch (ModuleNotFoundKraken ex) { GUI.user.RaiseMessage(Properties.Resources.MainInstallNotFound, ex.module); return; } catch (BadMetadataKraken ex) { GUI.user.RaiseMessage(Properties.Resources.MainInstallBadMetadata, ex.module, ex.Message); return; } catch (FileExistsKraken ex) { if (ex.owningModule != null) { GUI.user.RaiseMessage( Properties.Resources.MainInstallFileExists, ex.filename, ex.installingModule, ex.owningModule, Meta.GetVersion() ); } else { GUI.user.RaiseMessage( Properties.Resources.MainInstallUnownedFileExists, ex.installingModule, ex.filename ); } GUI.user.RaiseMessage(Properties.Resources.MainInstallGameDataReverted); return; } catch (InconsistentKraken ex) { // The prettiest Kraken formats itself for us. GUI.user.RaiseMessage(ex.InconsistenciesPretty); return; } catch (CancelledActionKraken) { return; } catch (MissingCertificateKraken kraken) { // Another very pretty kraken. GUI.user.RaiseMessage(kraken.ToString()); return; } catch (DownloadThrottledKraken kraken) { string msg = kraken.ToString(); GUI.user.RaiseMessage(msg); if (YesNoDialog(string.Format(Properties.Resources.MainInstallOpenSettingsPrompt, msg), Properties.Resources.MainInstallOpenSettings, Properties.Resources.MainInstallNo)) { // Launch the URL describing this host's throttling practices, if any if (kraken.infoUrl != null) { Process.Start(new ProcessStartInfo() { UseShellExecute = true, FileName = kraken.infoUrl.ToString() }); } // Now pretend they clicked the menu option for the settings Enabled = false; settingsDialog.ShowDialog(); Enabled = true; } return; } catch (ModuleDownloadErrorsKraken kraken) { GUI.user.RaiseMessage(kraken.ToString()); GUI.user.RaiseError(kraken.ToString()); return; } catch (DirectoryNotFoundKraken kraken) { GUI.user.RaiseMessage("\r\n{0}", kraken.Message); return; } catch (DllNotFoundException) { if (GUI.user.RaiseYesNoDialog(Properties.Resources.MainInstallLibCurlMissing)) { Process.Start(new ProcessStartInfo() { UseShellExecute = true, FileName = "https://github.com/KSP-CKAN/CKAN/wiki/libcurl" }); } throw; } } }
private void _UpdateModsList(bool repo_updated, List <ModChange> mc) { log.Info("Updating the mod list"); KspVersionCriteria versionCriteria = CurrentInstance.VersionCriteria(); IRegistryQuerier registry = RegistryManager.Instance(CurrentInstance).registry; var gui_mods = new HashSet <GUIMod>(); gui_mods.UnionWith( registry.InstalledModules .Select(instMod => new GUIMod(instMod, registry, versionCriteria)) ); gui_mods.UnionWith( registry.Available(versionCriteria) .Select(m => new GUIMod(m, registry, versionCriteria)) ); gui_mods.UnionWith( registry.Incompatible(versionCriteria) .Select(m => new GUIMod(m, registry, versionCriteria, true)) ); var old_modules = mainModList.Modules.ToDictionary(m => m, m => m.IsIncompatible); if (repo_updated) { foreach (GUIMod gm in gui_mods) { bool oldIncompat; if (old_modules.TryGetValue(gm, out oldIncompat)) { // Found it; check if newly compatible if (!gm.IsIncompatible && oldIncompat) { gm.IsNew = true; } } else { // Newly indexed, show regardless of compatibility gm.IsNew = true; } } } else { //Copy the new mod flag from the old list. var old_new_mods = new HashSet <GUIMod>(old_modules.Keys.Where(m => m.IsNew)); foreach (var gui_mod in gui_mods.Where(m => old_new_mods.Contains(m))) { gui_mod.IsNew = true; } } // Update our mod listing. If we're doing a repo update, then we don't refresh // all (in case the user has selected changes they wish to apply). mainModList.ConstructModList(gui_mods.ToList(), mc, !repo_updated, configuration.HideEpochs, configuration.HideV); mainModList.Modules = new ReadOnlyCollection <GUIMod>( mainModList.full_list_of_mod_rows.Values.Select(row => row.Tag as GUIMod).ToList()); //TODO Consider using smart enumeration pattern so stuff like this is easier FilterToolButton.DropDownItems[0].Text = String.Format("Compatible ({0})", mainModList.CountModsByFilter(GUIModFilter.Compatible)); FilterToolButton.DropDownItems[1].Text = String.Format("Installed ({0})", mainModList.CountModsByFilter(GUIModFilter.Installed)); FilterToolButton.DropDownItems[2].Text = String.Format("Upgradeable ({0})", mainModList.CountModsByFilter(GUIModFilter.InstalledUpdateAvailable)); FilterToolButton.DropDownItems[3].Text = String.Format("Cached ({0})", mainModList.CountModsByFilter(GUIModFilter.Cached)); FilterToolButton.DropDownItems[4].Text = String.Format("Newly compatible ({0})", mainModList.CountModsByFilter(GUIModFilter.NewInRepository)); FilterToolButton.DropDownItems[5].Text = String.Format("Not installed ({0})", mainModList.CountModsByFilter(GUIModFilter.NotInstalled)); FilterToolButton.DropDownItems[6].Text = String.Format("Incompatible ({0})", mainModList.CountModsByFilter(GUIModFilter.Incompatible)); FilterToolButton.DropDownItems[7].Text = String.Format("All ({0})", mainModList.CountModsByFilter(GUIModFilter.All)); var has_any_updates = gui_mods.Any(mod => mod.HasUpdate); UpdateAllToolButton.Enabled = has_any_updates; UpdateFilters(this); }