Skip to content

Commit

Permalink
Merge #4187 Label search fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
HebaruSan committed Sep 19, 2024
2 parents 5089e20 + 4cb17a8 commit f88747a
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 61 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ All notable changes to this project will be documented in this file.
- [Multiple] Refactor ZIP importing (#4153 by: HebaruSan)
- [GUI] Work around OpenFileDialog always showing all shortcuts despite filters (#4168 by: HebaruSan)
- [Core] Suppress exceptions for non-indexed mods (#4170 by: HebaruSan)
- [GUI] Label search fixes (#4187 by: HebaruSan)

### Internal

Expand Down
6 changes: 1 addition & 5 deletions GUI/Controls/EditModSearch.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Linq;
using System.Drawing;
using System.Windows.Forms;
#if NET5_0_OR_GREATER
Expand Down Expand Up @@ -139,10 +138,7 @@ private void ImmediateHandler(object? sender, EventArgs? e)
if (Main.Instance?.CurrentInstance != null)
{
// Sync the search boxes immediately
currentSearch = ModSearch.Parse(
FilterCombinedTextBox.Text,
ModuleLabelList.ModuleLabels.LabelsFor(Main.Instance.CurrentInstance.Name)
.ToList());
currentSearch = ModSearch.Parse(FilterCombinedTextBox.Text);
}
SearchToEditor();
}
Expand Down
14 changes: 2 additions & 12 deletions GUI/Controls/EditModSearchDetails.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
#if NET5_0_OR_GREATER
Expand Down Expand Up @@ -45,11 +44,6 @@ public void SetFocus()
}

public ModSearch CurrentSearch()
=> CurrentSearch(
ModuleLabelList.ModuleLabels.LabelsFor(Main.Instance?.CurrentInstance?.Name ?? "")
.ToList());

private ModSearch CurrentSearch(List<ModuleLabel>? knownLabels)
=> new ModSearch(
FilterByNameTextBox.Text,
FilterByAuthorTextBox.Text.Split(Array.Empty<char>(), StringSplitOptions.RemoveEmptyEntries).ToList(),
Expand All @@ -62,10 +56,7 @@ private ModSearch CurrentSearch(List<ModuleLabel>? knownLabels)
FilterByConflictsTextBox.Text.Split(Array.Empty<char>(), StringSplitOptions.RemoveEmptyEntries).ToList(),
FilterBySupportsTextBox.Text.Split(Array.Empty<char>(), StringSplitOptions.RemoveEmptyEntries).ToList(),
FilterByTagsTextBox.Text.Split(Array.Empty<char>(), StringSplitOptions.RemoveEmptyEntries).ToList(),
FilterByLabelsTextBox.Text.Split(Array.Empty<char>(), StringSplitOptions.RemoveEmptyEntries)
.Select(ln => knownLabels?.FirstOrDefault(lb => lb.Name == ln))
.OfType<ModuleLabel>()
.ToList(),
FilterByLabelsTextBox.Text.Split(Array.Empty<char>(), StringSplitOptions.RemoveEmptyEntries).ToList(),
CompatibleToggle.Value,
InstalledToggle.Value,
CachedToggle.Value,
Expand Down Expand Up @@ -97,8 +88,7 @@ public void PopulateSearch(ModSearch? search)
?? "";
FilterByTagsTextBox.Text = search?.TagNames.Aggregate("", CombinePieces)
?? "";
FilterByLabelsTextBox.Text = search?.Labels.Select(lb => lb.Name)
.Aggregate("", CombinePieces)
FilterByLabelsTextBox.Text = search?.LabelNames.Aggregate("", CombinePieces)
?? "";

CompatibleToggle.Value = search?.Compatible;
Expand Down
4 changes: 1 addition & 3 deletions GUI/Controls/ManageMods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -465,10 +465,8 @@ public void Filter(SavedSearch search, bool merge)
{
if (currentInstance != null)
{
var lbls = ModuleLabelList.ModuleLabels.LabelsFor(currentInstance.Name)
.ToList();
var searches = search.Values
.Select(s => ModSearch.Parse(s, lbls))
.Select(s => ModSearch.Parse(s))
.OfType<ModSearch>()
.ToList();

Expand Down
3 changes: 1 addition & 2 deletions GUI/Main/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -634,8 +634,7 @@ private void SetupDefaultSearch()
}
else
{
var labels = ModuleLabelList.ModuleLabels.LabelsFor(CurrentInstance.Name).ToList();
var searches = def.Select(s => ModSearch.Parse(s, labels))
var searches = def.Select(s => ModSearch.Parse(s))
.OfType<ModSearch>()
.ToList();
ManageMods.SetSearches(searches);
Expand Down
2 changes: 1 addition & 1 deletion GUI/Model/ModList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ private bool TagInSearches(ModuleTag tag)
=> activeSearches?.Any(s => s?.TagNames.Contains(tag.Name) ?? false) ?? false;

private bool LabelInSearches(ModuleLabel label)
=> activeSearches?.Any(s => s?.Labels.Contains(label) ?? false) ?? false;
=> activeSearches?.Any(s => s?.LabelNames.Contains(label.Name) ?? false) ?? false;

private bool HiddenByTagsOrLabels(GUIMod m, string instanceName, IGame game, Registry registry)
// "Hide" labels apply to all non-custom filters
Expand Down
74 changes: 36 additions & 38 deletions GUI/Model/ModSearch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public ModSearch(
List<string>? licenses, List<string>? localizations,
List<string>? depends, List<string>? recommends, List<string>? suggests, List<string>? conflicts,
List<string>? supports,
List<string>? tagNames, List<ModuleLabel>? labels,
List<string>? tagNames, List<string>? labelNames,
bool? compatible, bool? installed, bool? cached, bool? newlyCompatible,
bool? upgradeable, bool? replaceable,
string? combined = null)
Expand All @@ -53,11 +53,8 @@ public ModSearch(
initStringList(ConflictsWith, conflicts);
initStringList(Supports, supports);

initStringList(TagNames, tagNames);
if (labels?.Any() ?? false)
{
Labels.AddRange(labels);
}
initStringList(TagNames, tagNames);
initStringList(LabelNames, labelNames);

Compatible = compatible;
Installed = installed;
Expand Down Expand Up @@ -93,15 +90,15 @@ public ModSearch(GUIModFilter filter,
case GUIModFilter.Uncached: Cached = false; break;
case GUIModFilter.NewInRepository: NewlyCompatible = true; break;
case GUIModFilter.Tag:
if (tag?.Name is string n)
if (tag?.Name is string tn)
{
TagNames.Add(n);
TagNames.Add(tn);
}
break;
case GUIModFilter.CustomLabel:
if (label != null)
if (label?.Name is string ln)
{
Labels.Add(label);
LabelNames.Add(ln);
}
break;
default:
Expand Down Expand Up @@ -166,8 +163,8 @@ public ModSearch(GUIModFilter filter,
/// </summary>
public readonly string? Combined;

public readonly List<string> TagNames = new List<string>();
public readonly List<ModuleLabel> Labels = new List<ModuleLabel>();
public readonly List<string> TagNames = new List<string>();
public readonly List<string> LabelNames = new List<string>();

public readonly bool? Compatible;
public readonly bool? Installed;
Expand Down Expand Up @@ -209,7 +206,7 @@ public ModSearch MergedWith(ModSearch other)
ConflictsWith.Concat(other.ConflictsWith).Distinct().ToList(),
Supports.Concat(other.Supports).Distinct().ToList(),
TagNames.Concat(other.TagNames).Distinct().ToList(),
Labels.Concat(other.Labels).Distinct().ToList(),
LabelNames.Concat(other.LabelNames).Distinct().ToList(),
Compatible ?? other.Compatible,
Installed ?? other.Installed,
Cached ?? other.Cached,
Expand Down Expand Up @@ -271,9 +268,9 @@ public ModSearch MergedWith(ModSearch other)
{
pieces.Add(AddTermPrefix(Properties.Resources.ModSearchTagPrefix, tagName ?? ""));
}
foreach (var label in Labels)
foreach (var label in LabelNames)
{
pieces.Add($"{Properties.Resources.ModSearchLabelPrefix}{label.Name.Replace(" ", "")}");
pieces.Add($"{Properties.Resources.ModSearchLabelPrefix}{label.Replace(" ", "")}");
}
if (Compatible.HasValue)
{
Expand Down Expand Up @@ -321,7 +318,7 @@ private static string triStateString(bool val, string suffix)
/// <returns>
/// New search object, or null if no search terms defined
/// </returns>
public static ModSearch? Parse(string combined, List<ModuleLabel> knownLabels)
public static ModSearch? Parse(string combined)
{
if (string.IsNullOrWhiteSpace(combined))
{
Expand All @@ -339,8 +336,8 @@ private static string triStateString(bool val, string suffix)
var conflicts = new List<string>();
var supports = new List<string>();

List<string> tagNames = new List<string>();
List<ModuleLabel> labels = new List<ModuleLabel>();
List<string> tagNames = new List<string>();
List<string> labels = new List<string>();

bool? compatible = null;
bool? installed = null;
Expand Down Expand Up @@ -394,13 +391,7 @@ private static string triStateString(bool val, string suffix)
}
else if (TryPrefix(s, Properties.Resources.ModSearchLabelPrefix, out string labelName))
{
labels.AddRange(
// Label searches exclude spaces, but label names can include them
knownLabels.Where(lb => lb.Name.Replace(" ", "") == labelName)
// If label doesn't exist, maybe it will be created later or the user is still typing.
// Make an unofficial label object to accurately reflect the search.
.DefaultIfEmpty(new ModuleLabel(labelName))
);
labels.Add(labelName);
}
else if (TryPrefix(s, Properties.Resources.ModSearchYesPrefix, out string yesSuffix))
{
Expand Down Expand Up @@ -601,21 +592,28 @@ private static bool RelationshipMatch(List<RelationshipDescriptor>? rels, List<s
^ rels.Any(r => r.StartsWith(subRel))));

private bool MatchesTags(GUIMod mod)
{
var tagsInMod = mod.ToModule().Tags;
return TagNames.Count < 1
=> TagNames.Count < 1
|| TagNames.All(tn =>
ShouldNegateTerm(tn, out string subTag) ^ (
string.IsNullOrEmpty(subTag)
? tagsInMod == null
: tagsInMod?.Contains(subTag) ?? false));
}
ShouldNegateTerm(tn, out string subTag) ^ (
string.IsNullOrEmpty(subTag)
? mod.ToModule().Tags == null
: mod.ToModule().Tags?.Contains(subTag) ?? false));

private bool MatchesLabels(GUIMod mod)
// Every label in Labels must contain this mod
=> Main.Instance?.CurrentInstance != null
&& (Labels.Count < 1
|| Labels.All(lb => lb.ContainsModule(Main.Instance.CurrentInstance.game, mod.Identifier)));
=> LabelNames.Count < 1
|| (Main.Instance?.CurrentInstance is GameInstance inst
&& ModuleLabelList.ModuleLabels.LabelsFor(inst.Name)
.ToArray()
is ModuleLabel[] instanceLabels
&& LabelNames.All(ln =>
ShouldNegateTerm(ln, out string subLabel) ^ (
string.IsNullOrEmpty(subLabel)
? instanceLabels.All(lbl => !lbl.ContainsModule(inst.game, mod.Identifier))
: instanceLabels.Where(lbl => lbl.Name == subLabel)
.ToArray()
is ModuleLabel[] myLabels
&& myLabels.Length > 0
&& myLabels.All(lbl => lbl.ContainsModule(inst.game, mod.Identifier)))));

private bool MatchesCompatible(GUIMod mod)
=> !Compatible.HasValue || Compatible.Value == !mod.IsIncompatible;
Expand Down Expand Up @@ -654,7 +652,7 @@ public bool Equals(ModSearch? other)
&& ConflictsWith.SequenceEqual(other.ConflictsWith)
&& Supports.SequenceEqual(other.Supports)
&& TagNames.SequenceEqual(other.TagNames)
&& Labels.SequenceEqual(other.Labels);
&& LabelNames.SequenceEqual(other.LabelNames);

public override bool Equals(object? obj)
=> Equals(obj as ModSearch);
Expand Down

0 comments on commit f88747a

Please sign in to comment.