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

Show reverse relationships #3638

Merged
merged 4 commits into from
Aug 23, 2022
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
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
2 changes: 2 additions & 0 deletions GUI/Controls/Changeset.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ public void LoadChangeset(List<ModChange> changes, List<ModuleLabel> AlertLabels
.Where(ch => ch.ChangeType != GUIModChangeType.None)
.Select(makeItem)
.ToArray());
ChangesListView.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
ChangesListView.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
}
}

Expand Down
46 changes: 40 additions & 6 deletions GUI/Controls/ModInfo.Designer.cs

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

Loading