Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix very slow response to checkbox changes #2354

Merged
merged 1 commit into from
Mar 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cmdline/Action/Import.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public int RunCommand(CKAN.KSP ksp, object options)
log.InfoFormat("Importing {0} files", toImport.Count);
List<string> toInstall = new List<string>();
ModuleInstaller inst = ModuleInstaller.GetInstance(ksp, user);
inst.ImportFiles(toImport, user, id => toInstall.Add(id), !opts.Headless);
inst.ImportFiles(toImport, user, mod => toInstall.Add(mod.identifier), !opts.Headless);
if (toInstall.Count > 0)
{
inst.InstallList(
Expand Down
103 changes: 41 additions & 62 deletions ConsoleUI/DependencyScreen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ public DependencyScreen(KSPManager mgr, ChangePlan cp, HashSet<string> rej, bool
new ConsoleListBoxColumn<Dependency>() {
Header = "Install",
Width = 7,
Renderer = (Dependency d) => StatusSymbol(d.identifier),
Renderer = (Dependency d) => StatusSymbol(d.module)
},
new ConsoleListBoxColumn<Dependency>() {
Header = "Name",
Width = 24,
Renderer = (Dependency d) => d.identifier,
Width = 36,
Renderer = (Dependency d) => d.module.ToString()
},
new ConsoleListBoxColumn<Dependency>() {
Header = "Sources",
Expand All @@ -56,7 +56,7 @@ public DependencyScreen(KSPManager mgr, ChangePlan cp, HashSet<string> rej, bool
);
dependencyList.AddTip("+", "Toggle");
dependencyList.AddBinding(Keys.Plus, (object sender) => {
ChangePlan.toggleContains(accepted, dependencyList.Selection.identifier);
ChangePlan.toggleContains(accepted, dependencyList.Selection.module);
return true;
});

Expand All @@ -81,7 +81,7 @@ public DependencyScreen(KSPManager mgr, ChangePlan cp, HashSet<string> rej, bool
if (dependencyList.Selection != null) {
LaunchSubScreen(new ModInfoScreen(
manager, plan,
registry.LatestAvailable(dependencyList.Selection.identifier, manager.CurrentInstance.VersionCriteria()),
dependencyList.Selection.module,
debug
));
}
Expand All @@ -94,20 +94,20 @@ public DependencyScreen(KSPManager mgr, ChangePlan cp, HashSet<string> rej, bool
AddBinding(Keys.Escape, (object sender) => {
// Add everything to rejected
foreach (var kvp in dependencies) {
rejected.Add(kvp.Key);
rejected.Add(kvp.Key.identifier);
}
return false;
});

AddTip("F9", "Accept");
AddBinding(Keys.F9, (object sender) => {
foreach (string name in accepted) {
plan.Install.Add(name);
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);
rejected.Add(kvp.Key.identifier);
}
}
return false;
Expand All @@ -126,94 +126,73 @@ public bool HaveOptions()
return dependencies.Count > 0;
}

private void generateList(HashSet<string> inst)
private void generateList(HashSet<CkanModule> inst)
{
foreach (string mod in inst) {
CkanModule m = registry.LatestAvailable(mod, manager.CurrentInstance.VersionCriteria());
if (m != null) {
AddDependencies(inst, mod, m.recommends, true);
AddDependencies(inst, mod, m.suggests, false);
}
foreach (CkanModule mod in inst) {
AddDependencies(inst, mod, mod.recommends, true);
AddDependencies(inst, mod, mod.suggests, false);
}
}

private void AddDependencies(HashSet<string> alreadyInstalling, string identifier, List<RelationshipDescriptor> source, bool installByDefault)
private void AddDependencies(HashSet<CkanModule> alreadyInstalling, CkanModule dependent, List<RelationshipDescriptor> source, bool installByDefault)
{
if (source != null) {
foreach (RelationshipDescriptor dependency in source) {
if (!rejected.Contains(dependency.name)) {
try {
if (registry.LatestAvailable(
dependency.name,
manager.CurrentInstance.VersionCriteria(),
dependency
) != null
&& !registry.IsInstalled(dependency.name)
&& !alreadyInstalling.Contains(dependency.name)) {

AddDep(dependency.name, installByDefault, identifier);
}
} catch (ModuleNotFoundKraken) {
// LatestAvailable throws if you recommend a "provides" name,
// so ask the registry again for provides-based choices
List<CkanModule> opts = registry.LatestAvailableWithProvides(
dependency.name,
manager.CurrentInstance.VersionCriteria(),
dependency
);
foreach (CkanModule provider in opts) {
if (!registry.IsInstalled(provider.identifier)
&& !alreadyInstalling.Contains(provider.identifier)) {

// Default to not installing because these probably conflict with each other
AddDep(provider.identifier, false, identifier);
}
List<CkanModule> opts = registry.LatestAvailableWithProvides(
dependency.name,
manager.CurrentInstance.VersionCriteria(),
dependency
);
foreach (CkanModule provider in opts) {
if (!registry.IsInstalled(provider.identifier)
&& !alreadyInstalling.Contains(provider)) {

// Only default to installing if there's only one
AddDep(provider, installByDefault && opts.Count == 1, dependent);
}
} catch (Kraken) {
// GUI/MainInstall.cs::AddMod just ignores all exceptions,
// so that's baked into the infrastructure
}
}
}
}
}

private void AddDep(string identifier, bool defaultInstall, string dependent)
private void AddDep(CkanModule mod, bool defaultInstall, CkanModule dependent)
{
if (dependencies.ContainsKey(identifier)) {
dependencies[identifier].defaultInstall |= defaultInstall;
dependencies[identifier].dependents.Add(dependent);
if (dependencies.ContainsKey(mod)) {
dependencies[mod].defaultInstall |= defaultInstall;
dependencies[mod].dependents.Add(dependent);
} else {
dependencies.Add(identifier, new Dependency() {
identifier = identifier,
dependencies.Add(mod, new Dependency() {
module = mod,
defaultInstall = defaultInstall,
dependents = new List<string>() {dependent}
dependents = new List<CkanModule>() { dependent }
});
}
if (defaultInstall) {
accepted.Add(identifier);
accepted.Add(mod);
}
}

private string StatusSymbol(string identifier)
private string StatusSymbol(CkanModule mod)
{
if (accepted.Contains(identifier)) {
if (accepted.Contains(mod)) {
return installing;
} else {
return notinstalled;
}
}

private HashSet<string> accepted = new HashSet<string>();
private HashSet<CkanModule> accepted = new HashSet<CkanModule>();
private HashSet<string> rejected;

private IRegistryQuerier registry;
private KSPManager manager;
private ChangePlan plan;
private bool debug;

private Dictionary<string, Dependency> dependencies = new Dictionary<string, Dependency>();
private ConsoleListBox<Dependency> dependencyList;
private Dictionary<CkanModule, Dependency> dependencies = new Dictionary<CkanModule, Dependency>();
private ConsoleListBox<Dependency> dependencyList;

private static readonly string notinstalled = " ";
private static readonly string installing = "+";
Expand All @@ -227,17 +206,17 @@ public class Dependency {
/// <summary>
/// Identifier of mod
/// </summary>
public string identifier;
public CkanModule module;

/// <summary>
/// True if we default to installing, false otherwise
/// </summary>
public bool defaultInstall;
public bool defaultInstall;

/// <summary>
/// List of mods that recommended or suggested this mod
/// </summary>
public List<string> dependents = new List<string>();
public List<CkanModule> dependents = new List<CkanModule>();
}

}
2 changes: 1 addition & 1 deletion ConsoleUI/DownloadImportDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public static void ImportDownloads(KSP gameInst, ChangePlan cp)
ProgressScreen ps = new ProgressScreen("Importing Downloads", "Calculating...");
ModuleInstaller inst = ModuleInstaller.GetInstance(gameInst, ps);
ps.Run(() => inst.ImportFiles(files, ps,
(string identifier) => cp.Install.Add(identifier)));
(CkanModule mod) => cp.Install.Add(mod)));
// Don't let the installer re-use old screen references
inst.User = null;
}
Expand Down
16 changes: 6 additions & 10 deletions ConsoleUI/InstallScreen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public override void Run(Action process = null)
plan.Upgrade.Clear();
}
if (plan.Install.Count > 0) {
List<string> iList = new List<string>(plan.Install);
List<CkanModule> iList = new List<CkanModule>(plan.Install);
inst.InstallList(iList, resolvOpts, dl);
plan.Install.Clear();
}
Expand Down Expand Up @@ -109,19 +109,15 @@ public override void Run(Action process = null)
RaiseError(ex.InconsistenciesPretty);
} catch (TooManyModsProvideKraken ex) {

List<string> opts = new List<string>();
foreach (CkanModule opt in ex.modules) {
opts.Add(opt.identifier);
}
ConsoleChoiceDialog<string> ch = new ConsoleChoiceDialog<string>(
ConsoleChoiceDialog<CkanModule> ch = new ConsoleChoiceDialog<CkanModule>(
$"Module {ex.requested} is provided by multiple modules. Which would you like to install?",
"Name",
opts,
(string s) => s
ex.modules,
(CkanModule mod) => mod.ToString()
);
string chosen = ch.Run();
CkanModule chosen = ch.Run();
DrawBackground();
if (!string.IsNullOrEmpty(chosen)) {
if (chosen != null) {
// Use chosen to continue installing
plan.Install.Add(chosen);
retry = true;
Expand Down
71 changes: 45 additions & 26 deletions ConsoleUI/ModListScreen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,10 @@ public ModListScreen(KSPManager mgr, bool dbg)
moduleList.AddBinding(Keys.Plus, (object sender) => {
if (moduleList.Selection != null) {
if (!registry.IsInstalled(moduleList.Selection.identifier, false)) {
plan.ToggleInstall(moduleList.Selection.identifier);
plan.ToggleInstall(moduleList.Selection);
} else if (registry.IsInstalled(moduleList.Selection.identifier, false)
&& registry.HasUpdate(moduleList.Selection.identifier, manager.CurrentInstance.VersionCriteria())) {
plan.ToggleUpgrade(moduleList.Selection.identifier);
plan.ToggleUpgrade(moduleList.Selection);
}
}
return true;
Expand All @@ -189,7 +189,7 @@ public ModListScreen(KSPManager mgr, bool dbg)
);
moduleList.AddBinding(Keys.Minus, (object sender) => {
if (moduleList.Selection != null && registry.IsInstalled(moduleList.Selection.identifier, false)) {
plan.ToggleRemove(moduleList.Selection.identifier);
plan.ToggleRemove(moduleList.Selection);
}
return true;
});
Expand Down Expand Up @@ -325,7 +325,7 @@ private bool ViewSuggestions()
// Only check mods that are still available
try {
if (registry.LatestAvailable(im.identifier, manager.CurrentInstance.VersionCriteria()) != null) {
reinstall.Install.Add(im.identifier);
reinstall.Install.Add(im.Module);
}
} catch {
// The registry object badly needs an IsAvailable check
Expand All @@ -337,8 +337,8 @@ private bool ViewSuggestions()
LaunchSubScreen(ds);
bool needRefresh = false;
// Copy the right ones into our real plan
foreach (string mod in reinstall.Install) {
if (!registry.IsInstalled(mod, false)) {
foreach (CkanModule mod in reinstall.Install) {
if (!registry.IsInstalled(mod.identifier, false)) {
plan.Install.Add(mod);
needRefresh = true;
}
Expand Down Expand Up @@ -582,34 +582,34 @@ public ChangePlan() { }
/// <summary>
/// Add or remove a mod from the remove list
/// </summary>
/// <param name="identifier">The mod to add or remove</param>
public void ToggleRemove(string identifier)
/// <param name="mod">The mod to add or remove</param>
public void ToggleRemove(CkanModule mod)
{
Install.Remove(identifier);
Upgrade.Remove(identifier);
toggleContains(Remove, identifier);
Install.Remove(mod);
Upgrade.Remove(mod.identifier);
toggleContains(Remove, mod.identifier);
}

/// <summary>
/// Add or remove a mod from the install list
/// </summary>
/// <param name="identifier">The mod to add or remove</param>
public void ToggleInstall(string identifier)
/// <param name="mod">The mod to add or remove</param>
public void ToggleInstall(CkanModule mod)
{
Upgrade.Remove(identifier);
Remove.Remove(identifier);
toggleContains(Install, identifier);
Upgrade.Remove(mod.identifier);
Remove.Remove(mod.identifier);
toggleContains(Install, mod);
}

/// <summary>
/// Add or remove a mod from the upgrade list
/// </summary>
/// <param name="identifier">The mod to add or remove</param>
public void ToggleUpgrade(string identifier)
/// <param name="mod">The mod to add or remove</param>
public void ToggleUpgrade(CkanModule mod)
{
Install.Remove(identifier);
Remove.Remove(identifier);
toggleContains(Upgrade, identifier);
Install.Remove(mod);
Remove.Remove(mod.identifier);
toggleContains(Upgrade, mod.identifier);
}

/// <summary>
Expand Down Expand Up @@ -659,11 +659,14 @@ public InstallStatus GetModStatus(KSPManager manager, IRegistryQuerier registry,
return InstallStatus.Installed;
}
} else {
if (Install.Contains(identifier)) {
return InstallStatus.Installing;
} else {
return InstallStatus.NotInstalled;
foreach (CkanModule m in Install)
{
if (m.identifier == identifier)
{
return InstallStatus.Installing;
}
}
return InstallStatus.NotInstalled;
}
}

Expand Down Expand Up @@ -701,10 +704,26 @@ public static void toggleContains(HashSet<string> list, string identifier)
}
}

/// <summary>
/// Add or remove a value from a HashSet
/// </summary>
/// <param name="list">HashSet to manipulate</param>
/// <param name="mod">The value</param>
public static void toggleContains(HashSet<CkanModule> list, CkanModule mod)
{
if (list != null && mod != null) {
if (list.Contains(mod)) {
list.Remove(mod);
} else {
list.Add(mod);
}
}
}

/// <summary>
/// Mods we're planning to install
/// </summary>
public readonly HashSet<string> Install = new HashSet<string>();
public readonly HashSet<CkanModule> Install = new HashSet<CkanModule>();

/// <summary>
/// Mods we're planning to upgrade
Expand Down
Loading