Skip to content

Commit

Permalink
Merge #2354 Improve response to checkbox changes
Browse files Browse the repository at this point in the history
  • Loading branch information
politas committed Mar 18, 2018
2 parents b8e62e7 + 6fe078c commit b198ce5
Show file tree
Hide file tree
Showing 16 changed files with 450 additions and 470 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ All notable changes to this project will be documented in this file.
- [Netkan] Invalidate stale cached files from GitHub in Netkan (#2337 by: HebaruSan; reviewed: politas)
- [Build] Allow building CKAN.app on macOS (#2356 by: phardy; reviewed: HebaruSan)
- [GUI] Always switch to progress tab when starting a [re/un]install (#2351 by: HebaruSan; reviewed: Olympic1)
- [Core] Support CC-BY-ND licences in code (#2369 by: HebaruSan; no review)
- [GUI] Improve response to checkbox changes (#2354 by: HebaruSan; reviewed: politas)

### Internal

Expand Down
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
Loading

0 comments on commit b198ce5

Please sign in to comment.