Skip to content

Commit

Permalink
Show reverse relationships
Browse files Browse the repository at this point in the history
  • Loading branch information
HebaruSan committed Aug 20, 2022
1 parent 2f3d817 commit 5b82eed
Show file tree
Hide file tree
Showing 11 changed files with 402 additions and 197 deletions.
8 changes: 5 additions & 3 deletions Core/ModuleInstaller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -246,17 +246,19 @@ public IEnumerable<string> GetModuleContentsList(CkanModule module)

if (filename == null)
{
return null;
return Enumerable.Empty<string>();
}

try
{
return FindInstallableFiles(module, filename, ksp)
.Select(x => ksp.ToRelativeGameDir(x.destination));
// Skip folders
.Where(f => !f.source.IsDirectory)
.Select(f => ksp.ToRelativeGameDir(f.destination));
}
catch (ZipException)
{
return null;
return Enumerable.Empty<string>();
}
}

Expand Down
179 changes: 109 additions & 70 deletions GUI/Controls/AllModVersions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Threading.Tasks;

using CKAN.Versioning;

Expand Down Expand Up @@ -122,96 +123,134 @@ public GUIMod SelectedModule
visibleGuiModule.PropertyChanged += visibleGuiModule_PropertyChanged;
}
}
VersionsListView.Items.Clear();
if (value == null)
{
return;
}
Refresh(value);
}
}

private List<CkanModule> getVersions(GUIMod gmod)
{
GameInstance currentInstance = Main.Instance.Manager.CurrentInstance;
IRegistryQuerier registry = RegistryManager.Instance(currentInstance).registry;

// Can't be functional because AvailableByIdentifier throws exceptions
var versions = new List<CkanModule>();
try
{
versions = registry.AvailableByIdentifier(gmod.Identifier).ToList();
}
catch (ModuleNotFoundKraken)
{
// Identifier unknown to registry, maybe installed from local .ckan
}

// Take the module associated with GUIMod, if any, and append it to the list if it's not already there.
var installedModule = gmod.InstalledMod?.Module;
if (installedModule != null && !versions.Contains(installedModule))
{
versions.Add(installedModule);
}

// Get all the data; can put this in bg if slow
GameInstance currentInstance = Main.Instance.Manager.CurrentInstance;
IRegistryQuerier registry = RegistryManager.Instance(currentInstance).registry;
var installer = new ModuleInstaller(
currentInstance,
Main.Instance.Manager.Cache,
Main.Instance.currentUser);
Dictionary<CkanModule, bool> allAvailableVersions = null;
try
return versions;
}

private ListViewItem[] getItems(GUIMod gmod, List<CkanModule> versions)
{
GameInstance currentInstance = Main.Instance.Manager.CurrentInstance;
IRegistryQuerier registry = RegistryManager.Instance(currentInstance).registry;
ModuleVersion installedVersion = registry.InstalledVersion(gmod.Identifier);

var items = versions.OrderByDescending(module => module.version)
.Select(module =>
{
Registry.GetMinMaxVersions(
new List<CkanModule>() {module},
out ModuleVersion minMod, out ModuleVersion maxMod,
out GameVersion minKsp, out GameVersion maxKsp);
ListViewItem toRet = new ListViewItem(new string[]
{
allAvailableVersions = registry.AvailableByIdentifier(value.Identifier)
.ToDictionary(m => m,
m => installable(installer, m, registry));
}
catch (ModuleNotFoundKraken)
module.version.ToString(),
GameVersionRange.VersionSpan(currentInstance.game, minKsp, maxKsp),
module.release_date?.ToString("g") ?? ""
})
{
// Identifier unknown to registry, maybe installed from local .ckan
allAvailableVersions = new Dictionary<CkanModule, bool>();
}

// Take the module associated with GUIMod, if any, and append it to the list if it's not already there.
var installedModule = value.InstalledMod?.Module;
if (installedModule != null && !allAvailableVersions.ContainsKey(installedModule))
Tag = module
};
if (installedVersion != null && installedVersion.IsEqualTo(module.version))
{
allAvailableVersions.Add(installedModule, installable(installer, installedModule, registry));
toRet.Font = new Font(toRet.Font, FontStyle.Bold);
}

if (!allAvailableVersions.Any())
if (module.Equals(gmod.SelectedMod))
{
return;
toRet.Checked = true;
}
return toRet;
}).ToArray();

ModuleVersion installedVersion = registry.InstalledVersion(value.Identifier);

// Update UI; must be in fg
ignoreItemCheck = true;
bool latestCompatibleVersionAlreadyFound = false;

// Only show checkboxes for non-DLC modules
VersionsListView.CheckBoxes = !value.ToModule().IsDLC;
return items;
}

VersionsListView.Items.AddRange(allAvailableVersions
.OrderByDescending(kvp => kvp.Key.version)
.Select(kvp =>
private void checkInstallable(ListViewItem[] items)
{
GameInstance currentInstance = Main.Instance.Manager.CurrentInstance;
IRegistryQuerier registry = RegistryManager.Instance(currentInstance).registry;
bool latestCompatibleVersionAlreadyFound = false;
var installer = new ModuleInstaller(
currentInstance,
Main.Instance.Manager.Cache,
Main.Instance.currentUser);
foreach (ListViewItem item in items)
{
if (item.ListView == null)
{
CkanModule module = kvp.Key;
ModuleVersion minMod = null, maxMod = null;
GameVersion minKsp = null, maxKsp = null;
Registry.GetMinMaxVersions(new List<CkanModule>() {module}, out minMod, out maxMod, out minKsp, out maxKsp);
ListViewItem toRet = new ListViewItem(new string[]
{
module.version.ToString(),
GameVersionRange.VersionSpan(currentInstance.game, minKsp, maxKsp),
module.release_date?.ToString("g") ?? ""
})
{
Tag = module
};

if (kvp.Value)
// User switched to another mod, quit
break;
}
if (installable(installer, item.Tag as CkanModule, registry))
{
if (!latestCompatibleVersionAlreadyFound)
{
if (!latestCompatibleVersionAlreadyFound)
{
latestCompatibleVersionAlreadyFound = true;
toRet.BackColor = Color.Green;
toRet.ForeColor = Color.White;
}
else
latestCompatibleVersionAlreadyFound = true;
Util.Invoke(this, () =>
{
toRet.BackColor = Color.LightGreen;
}
item.BackColor = Color.Green;
item.ForeColor = Color.White;
});
}

if (installedVersion != null && installedVersion.IsEqualTo(module.version))
{
toRet.Font = new Font(toRet.Font, FontStyle.Bold);
}
if (module.Equals(value.SelectedMod))
else
{
toRet.Checked = true;
Util.Invoke(this, () =>
{
item.BackColor = Color.LightGreen;
});
}
return toRet;
}).ToArray());
}
}
Util.Invoke(this, () =>
{
UseWaitCursor = false;
});
}

private void Refresh(GUIMod gmod)
{
Util.Invoke(this, () => VersionsListView.Items.Clear());
var startingModule = gmod;
var items = getItems(gmod, getVersions(gmod));
// Make sure user hasn't switched to another mod while we were loading
if (startingModule.Equals(visibleGuiModule))
{
// Only show checkboxes for non-DLC modules
VersionsListView.CheckBoxes = !gmod.ToModule().IsDLC;
ignoreItemCheck = true;
VersionsListView.Items.AddRange(items);
ignoreItemCheck = false;
// Check installability in the background because it's slow
UseWaitCursor = true;
Task.Factory.StartNew(() => checkInstallable(items));
}
}
}
Expand Down
34 changes: 29 additions & 5 deletions GUI/Controls/ModInfo.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 5b82eed

Please sign in to comment.