/// <summary> /// Initialize the Screen /// </summary> /// <param name="mgr">KSP manager containing instances</param> /// <param name="cp">Plan of mods to install or remove</param> /// <param name="dbg">True if debug options should be available, false otherwise</param> public InstallScreen(KSPManager mgr, ChangePlan cp, bool dbg) : base( "Installing, Updating, and Removing Mods", "Calculating..." ) { debug = dbg; manager = mgr; plan = cp; }
private bool UpdateRegistry(ConsoleTheme theme, bool showNewModsPrompt = true) { ProgressScreen ps = new ProgressScreen("Updating Registry", "Checking for updates"); LaunchSubScreen(theme, ps, (ConsoleTheme th) => { HashSet <string> availBefore = new HashSet <string>( Array.ConvertAll <CkanModule, string>( registry.CompatibleModules( manager.CurrentInstance.VersionCriteria() ).ToArray(), (l => l.identifier) ) ); recent.Clear(); try { Repo.UpdateAllRepositories( RegistryManager.Instance(manager.CurrentInstance), manager.CurrentInstance, manager.Cache, ps ); } catch (ReinstallModuleKraken rmk) { ChangePlan reinstPlan = new ChangePlan(); foreach (CkanModule m in rmk.Modules) { reinstPlan.ToggleUpgrade(m); } LaunchSubScreen(theme, new InstallScreen(manager, reinstPlan, debug)); } catch (Exception ex) { // There can be errors while you re-install mods with changed metadata ps.RaiseError(ex.Message + ex.StackTrace); } // Update recent with mods that were updated in this pass foreach (CkanModule mod in registry.CompatibleModules( manager.CurrentInstance.VersionCriteria() )) { if (!availBefore.Contains(mod.identifier)) { recent.Add(mod.identifier); } } }); if (showNewModsPrompt && recent.Count > 0 && RaiseYesNoDialog(newModPrompt(recent.Count))) { searchBox.Clear(); moduleList.FilterString = searchBox.Value = "~n"; } RefreshList(theme); return(true); }
private bool ViewSuggestions(ConsoleTheme theme) { ChangePlan reinstall = new ChangePlan(); foreach (InstalledModule im in registry.InstalledModules) { // Only check mods that are still available try { if (registry.LatestAvailable(im.identifier, manager.CurrentInstance.VersionCriteria()) != null) { reinstall.Install.Add(im.Module); } } catch { // The registry object badly needs an IsAvailable check } } try { DependencyScreen ds = new DependencyScreen(manager, reinstall, new HashSet <string>(), debug); if (ds.HaveOptions()) { LaunchSubScreen(theme, ds); bool needRefresh = false; // Copy the right ones into our real plan foreach (CkanModule mod in reinstall.Install) { if (!registry.IsInstalled(mod.identifier, false)) { plan.Install.Add(mod); needRefresh = true; } } if (needRefresh) { RefreshList(); } } else { RaiseError("Installed mods have no unsatisfied recommendations or suggestions."); } } catch (ModuleNotFoundKraken k) { RaiseError($"{k.module} {k.version}: {k.Message}"); } return(true); }
/// <summary> /// Let the user choose some zip files, then import them to the mod cache. /// </summary> /// <param name="gameInst">Game instance to import into</param> /// <param name="cp">Change plan object for marking things to be installed</param> public static void ImportDownloads(KSP gameInst, ChangePlan cp) { ConsoleFileMultiSelectDialog cfmsd = new ConsoleFileMultiSelectDialog( "Import Downloads", FindDownloadsPath(gameInst), "*.zip", "Import" ); HashSet<FileInfo> files = cfmsd.Run(); if (files.Count > 0) { ProgressScreen ps = new ProgressScreen("Importing Downloads", "Calculating..."); ModuleInstaller inst = ModuleInstaller.GetInstance(gameInst, ps); ps.Run(() => inst.ImportFiles(files, ps, (CkanModule mod) => cp.Install.Add(mod))); // Don't let the installer re-use old screen references inst.User = null; } }
/// <summary> /// Initialize the screen /// </summary> /// <param name="mgr">KSP manager containing instances</param> /// <param name="cp">Plan of mods to add and remove</param> /// <param name="rej">Mods that the user saw and did not select, in this pass or a previous pass</param> /// <param name="dbg">True if debug options should be available, false otherwise</param> public DependencyScreen(KSPManager mgr, ChangePlan cp, HashSet <string> rej, bool dbg) : base() { debug = dbg; manager = mgr; plan = cp; registry = RegistryManager.Instance(manager.CurrentInstance).registry; rejected = rej; AddObject(new ConsoleLabel( 1, 2, -1, () => "Additional mods are recommended or suggested:" )); generateList(plan.Install); generateList(new HashSet <CkanModule>( ReplacementIdentifiers(plan.Replace) .Select(id => registry.InstalledModule(id).Module) )); dependencyList = new ConsoleListBox <Dependency>( 1, 4, -1, -2, new List <Dependency>(dependencies.Values), new List <ConsoleListBoxColumn <Dependency> >() { new ConsoleListBoxColumn <Dependency>() { Header = "Install", Width = 7, Renderer = (Dependency d) => StatusSymbol(d.module) }, new ConsoleListBoxColumn <Dependency>() { Header = "Name", Width = 36, Renderer = (Dependency d) => d.module.ToString() }, new ConsoleListBoxColumn <Dependency>() { Header = "Sources", Width = 42, Renderer = (Dependency d) => string.Join(", ", d.dependents) } }, 1, 0, ListSortDirection.Descending ); dependencyList.AddTip("+", "Toggle"); dependencyList.AddBinding(Keys.Plus, (object sender) => { ChangePlan.toggleContains(accepted, dependencyList.Selection.module); return(true); }); dependencyList.AddTip("Ctrl+A", "Select all"); dependencyList.AddBinding(Keys.CtrlA, (object sender) => { foreach (var kvp in dependencies) { if (!accepted.Contains(kvp.Key)) { ChangePlan.toggleContains(accepted, kvp.Key); } } return(true); }); dependencyList.AddTip("Ctrl+D", "Deselect all", () => accepted.Count > 0); dependencyList.AddBinding(Keys.CtrlD, (object sender) => { accepted.Clear(); return(true); }); dependencyList.AddTip("Enter", "Details"); dependencyList.AddBinding(Keys.Enter, (object sender) => { if (dependencyList.Selection != null) { LaunchSubScreen(new ModInfoScreen( manager, plan, dependencyList.Selection.module, debug )); } return(true); }); AddObject(dependencyList); AddTip("Esc", "Cancel"); AddBinding(Keys.Escape, (object sender) => { // Add everything to rejected foreach (var kvp in dependencies) { rejected.Add(kvp.Key.identifier); } return(false); }); AddTip("F9", "Accept"); AddBinding(Keys.F9, (object sender) => { foreach (CkanModule mod in accepted) { plan.Install.Add(mod); } // Add the rest to rejected foreach (var kvp in dependencies) { if (!accepted.Contains(kvp.Key)) { rejected.Add(kvp.Key.identifier); } } return(false); }); }
private int addVersionDisplay() { int boxLeft = Console.WindowWidth / 2 + 1, boxTop = 3; const int boxRight = -1, boxH = 5; if (ChangePlan.IsAnyAvailable(registry, mod.identifier)) { List <CkanModule> avail = registry.AllAvailable(mod.identifier); CkanModule inst = registry.GetInstalledVersion(mod.identifier); CkanModule latest = registry.LatestAvailable(mod.identifier, null); bool installed = registry.IsInstalled(mod.identifier, false); bool latestIsInstalled = inst?.Equals(latest) ?? false; List <CkanModule> others = avail; others.Remove(inst); others.Remove(latest); if (installed) { DateTime?instTime = InstalledOn(mod.identifier); if (latestIsInstalled) { addVersionBox( boxLeft, boxTop, boxRight, boxTop + boxH - 1, () => $"Latest/Installed {instTime?.ToString("d") ?? "manually"}", () => ConsoleTheme.Current.ActiveFrameFg, true, new List <CkanModule>() { inst } ); boxTop += boxH; } else { addVersionBox( boxLeft, boxTop, boxRight, boxTop + boxH - 1, () => "Latest Version", () => ConsoleTheme.Current.AlertFrameFg, false, new List <CkanModule>() { latest } ); boxTop += boxH; addVersionBox( boxLeft, boxTop, boxRight, boxTop + boxH - 1, () => $"Installed {instTime?.ToString("d") ?? "manually"}", () => ConsoleTheme.Current.ActiveFrameFg, true, new List <CkanModule>() { inst } ); boxTop += boxH; } } else { addVersionBox( boxLeft, boxTop, boxRight, boxTop + boxH - 1, () => "Latest Version", () => ConsoleTheme.Current.NormalFrameFg, false, new List <CkanModule>() { latest } ); boxTop += boxH; } if (others.Count > 0) { addVersionBox( boxLeft, boxTop, boxRight, boxTop + boxH - 1, () => "Other Versions", () => ConsoleTheme.Current.NormalFrameFg, false, others ); boxTop += boxH; } } else { DateTime?instTime = InstalledOn(mod.identifier); // Mod is no longer indexed, but we can generate a display // of the old info about it from when we installed it addVersionBox( boxLeft, boxTop, boxRight, boxTop + boxH - 1, () => $"UNAVAILABLE/Installed {instTime?.ToString("d") ?? "manually"}", () => ConsoleTheme.Current.AlertFrameFg, true, new List <CkanModule>() { mod } ); boxTop += boxH; } return(boxTop - 1); }
/// <summary> /// Initialize the Screen /// </summary> /// <param name="mgr">KSP manager containing game instances</param> /// <param name="cp">Plan of other mods to be added or removed</param> /// <param name="m">The module to display</param> /// <param name="dbg">True if debug options should be available, false otherwise</param> public ModInfoScreen(KSPManager mgr, ChangePlan cp, CkanModule m, bool dbg) { debug = dbg; mod = m; manager = mgr; plan = cp; registry = RegistryManager.Instance(manager.CurrentInstance).registry; int midL = Console.WindowWidth / 2 - 1; AddObject(new ConsoleLabel( 1, 1, -1, () => mod.name == mod.identifier ? mod.name : $"{mod.name} ({mod.identifier})", null, () => ConsoleTheme.Current.ActiveFrameFg )); AddObject(new ConsoleLabel( 1, 2, -1, () => $"By {string.Join(", ", mod.author)}" )); AddObject(new ConsoleFrame( 1, 3, midL, 7, () => "", () => ConsoleTheme.Current.NormalFrameFg, false )); AddObject(new ConsoleLabel( 3, 4, 11, () => "License:", null, () => ConsoleTheme.Current.DimLabelFg )); AddObject(new ConsoleLabel( 13, 4, midL - 2, () => string.Join(", ", Array.ConvertAll <License, string>( mod.license.ToArray(), (l => l.ToString()))) )); AddObject(new ConsoleLabel( 3, 5, 12, () => "Download:", null, () => ConsoleTheme.Current.DimLabelFg )); AddObject(new ConsoleLabel( 13, 5, midL - 2, () => CkanModule.FmtSize(mod.download_size) )); AddObject(new ConsoleLabel( 3, 6, midL - 2, HostedOn )); int depsBot = addDependencies(); int versBot = addVersionDisplay(); AddObject(new ConsoleFrame( 1, Math.Max(depsBot, versBot) + 1, -1, -1, () => "Description", () => ConsoleTheme.Current.NormalFrameFg, false )); ConsoleTextBox tb = new ConsoleTextBox( 3, Math.Max(depsBot, versBot) + 2, -3, -2, false, TextAlign.Left, () => ConsoleTheme.Current.MainBg, () => ConsoleTheme.Current.LabelFg ); tb.AddLine(mod.@abstract); if (!string.IsNullOrEmpty(mod.description) && mod.description != mod.@abstract) { tb.AddLine(mod.description); } AddObject(tb); if (!ChangePlan.IsAnyAvailable(registry, mod.identifier)) { tb.AddLine("\r\nNOTE: This mod is installed but no longer available."); tb.AddLine("If you uninstall it, CKAN will not be able to re-install it."); } tb.AddScrollBindings(this); AddTip("Esc", "Back"); AddBinding(Keys.Escape, (object sender) => false); AddTip("Ctrl+D", "Download", () => !manager.Cache.IsMaybeCachedZip(mod) ); AddBinding(Keys.CtrlD, (object sender) => { Download(); return(true); }); if (mod.resources != null) { List <ConsoleMenuOption> opts = new List <ConsoleMenuOption>(); if (mod.resources.homepage != null) { opts.Add(new ConsoleMenuOption( "Home page", "", "Open the home page URL in a browser", true, () => LaunchURL(mod.resources.homepage) )); } if (mod.resources.repository != null) { opts.Add(new ConsoleMenuOption( "Repository", "", "Open the repository URL in a browser", true, () => LaunchURL(mod.resources.repository) )); } if (mod.resources.bugtracker != null) { opts.Add(new ConsoleMenuOption( "Bugtracker", "", "Open the bug tracker URL in a browser", true, () => LaunchURL(mod.resources.bugtracker) )); } if (mod.resources.spacedock != null) { opts.Add(new ConsoleMenuOption( "SpaceDock", "", "Open the SpaceDock URL in a browser", true, () => LaunchURL(mod.resources.spacedock) )); } if (mod.resources.curse != null) { opts.Add(new ConsoleMenuOption( "Curse", "", "Open the Curse URL in a browser", true, () => LaunchURL(mod.resources.curse) )); } if (debug) { opts.Add(null); opts.Add(new ConsoleMenuOption( "DEBUG: View metadata", "", "Display the full registry data for this mod", true, ViewMetadata )); } if (opts.Count > 0) { mainMenu = new ConsolePopupMenu(opts); } } }
/// <summary> /// Let the user choose some zip files, then import them to the mod cache. /// </summary> /// <param name="theme">The visual theme to use to draw the dialog</param> /// <param name="gameInst">Game instance to import into</param> /// <param name="cache">Cache object to import into</param> /// <param name="cp">Change plan object for marking things to be installed</param> public static void ImportDownloads(ConsoleTheme theme, GameInstance gameInst, NetModuleCache cache, ChangePlan cp) { ConsoleFileMultiSelectDialog cfmsd = new ConsoleFileMultiSelectDialog( "Import Downloads", FindDownloadsPath(gameInst), "*.zip", "Import" ); HashSet <FileInfo> files = cfmsd.Run(theme); if (files.Count > 0) { ProgressScreen ps = new ProgressScreen("Importing Downloads", "Calculating..."); ModuleInstaller inst = new ModuleInstaller(gameInst, cache, ps); ps.Run(theme, (ConsoleTheme th) => inst.ImportFiles(files, ps, (CkanModule mod) => cp.Install.Add(mod), RegistryManager.Instance(gameInst).registry)); // Don't let the installer re-use old screen references inst.User = null; } }