Skip to content

Commit

Permalink
Merge #4148 Search by licenses
Browse files Browse the repository at this point in the history
  • Loading branch information
HebaruSan committed Aug 6, 2024
2 parents 81ec4c2 + 4e2cda6 commit 5a7a2f7
Show file tree
Hide file tree
Showing 7 changed files with 246 additions and 54 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ All notable changes to this project will be documented in this file.
- [Multiple] Visually indicate to users that they should click Refresh (#4133 by: HebaruSan)
- [Multiple] Option to clone smaller instances with junction points (Windows) or symbolic links (Unix) (#4129, #4144 by: HebaruSan)
- [Multiple] Recommendation suppression for modpacks (#4147 by: HebaruSan; reviewed: JonnyOThan)
- [GUI] Search by licenses (#4148 by: HebaruSan)

### Bugfixes

Expand Down
133 changes: 82 additions & 51 deletions GUI/Controls/EditModSearchDetails.Designer.cs

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions GUI/Controls/EditModSearchDetails.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ private ModSearch CurrentSearch(List<ModuleLabel> knownLabels)
FilterByNameTextBox.Text,
FilterByAuthorTextBox.Text.Split(Array.Empty<char>(), StringSplitOptions.RemoveEmptyEntries).ToList(),
FilterByDescriptionTextBox.Text,
FilterByLicenseTextBox.Text.Split(Array.Empty<char>(), StringSplitOptions.RemoveEmptyEntries).ToList(),
FilterByLanguageTextBox.Text.Split(Array.Empty<char>(), StringSplitOptions.RemoveEmptyEntries).ToList(),
FilterByDependsTextBox.Text.Split(Array.Empty<char>(), StringSplitOptions.RemoveEmptyEntries).ToList(),
FilterByRecommendsTextBox.Text.Split(Array.Empty<char>(), StringSplitOptions.RemoveEmptyEntries).ToList(),
Expand All @@ -82,6 +83,8 @@ public void PopulateSearch(ModSearch search)
?? "";
FilterByDescriptionTextBox.Text = search?.Description
?? "";
FilterByLicenseTextBox.Text = search?.Licenses.Aggregate("", CombinePieces)
?? "";
FilterByLanguageTextBox.Text = search?.Localizations.Aggregate("", CombinePieces)
?? "";
FilterByDependsTextBox.Text = search?.DependsOn.Aggregate("", CombinePieces)
Expand Down
1 change: 1 addition & 0 deletions GUI/Controls/EditModSearchDetails.resx
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@
<data name="FilterByNameLabel.Text" xml:space="preserve"><value>Name:</value></data>
<data name="FilterByAuthorLabel.Text" xml:space="preserve"><value>Author:</value></data>
<data name="FilterByDescriptionLabel.Text" xml:space="preserve"><value>Description:</value></data>
<data name="FilterByLicenseLabel.Text" xml:space="preserve"><value>Licence:</value></data>
<data name="FilterByLanguageLabel.Text" xml:space="preserve"><value>Language:</value></data>
<data name="FilterByDependsLabel.Text" xml:space="preserve"><value>Depends on:</value></data>
<data name="FilterByRecommendsLabel.Text" xml:space="preserve"><value>Recommends:</value></data>
Expand Down
121 changes: 121 additions & 0 deletions GUI/Localization/en-US/EditModSearchDetails.en-US.resx
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="FilterByLicenseLabel.Text" xml:space="preserve"><value>License:</value></data>
</root>
40 changes: 37 additions & 3 deletions GUI/Model/ModSearch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ public sealed class ModSearch : IEquatable<ModSearch>
/// <param name="conflicts">Identifier prefix to find in mod conflicts relationships</param>
/// <param name="combined">Full formatted search string if known, will be auto generated otherwise</param>
public ModSearch(
string byName, List<string> byAuthors, string byDescription, List<string> localizations,
string byName, List<string> byAuthors, string byDescription,
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,
Expand All @@ -44,6 +45,7 @@ public ModSearch(
Description = (ShouldNegateTerm(byDescription, out string subDesc) ? "-" : "")
+ CkanModule.nonAlphaNums.Replace(subDesc, "");
initStringList(Localizations, localizations);
initStringList(Licenses, licenses);

initStringList(DependsOn, depends);
initStringList(Recommends, recommends);
Expand Down Expand Up @@ -116,6 +118,11 @@ public ModSearch(GUIModFilter filter, ModuleTag tag = null, ModuleLabel label =
/// </summary>
public readonly string Description;

/// <summary>
/// License substring to search for in mod licenses
/// </summary>
public readonly List<string> Licenses = new List<string>();

/// <summary>
/// Language to search for in mod localizations
/// </summary>
Expand Down Expand Up @@ -169,7 +176,8 @@ public ModSearch(GUIModFilter filter, ModuleTag tag = null, ModuleLabel label =
public static ModSearch FromAuthors(IEnumerable<string> authors)
=> new ModSearch(
// Can't search for spaces, so massage them like SearchableAuthors
"", authors.Select(a => CkanModule.nonAlphaNums.Replace(a, "")).ToList(), "", null,
"", authors.Select(a => CkanModule.nonAlphaNums.Replace(a, "")).ToList(), "",
null, null,
null, null, null, null, null,
null, null,
null, null, null, null,
Expand All @@ -185,6 +193,7 @@ public ModSearch MergedWith(ModSearch other)
Name + other.Name,
Authors.Concat(other.Authors).Distinct().ToList(),
Description + other.Description,
Licenses.Concat(other.Licenses).Distinct().ToList(),
Localizations.Concat(other.Localizations).Distinct().ToList(),
DependsOn.Concat(other.DependsOn).Distinct().ToList(),
Recommends.Concat(other.Recommends).Distinct().ToList(),
Expand Down Expand Up @@ -222,6 +231,10 @@ private string getCombined()
{
pieces.Add(AddTermPrefix(Properties.Resources.ModSearchDescriptionPrefix, Description));
}
foreach (var license in Licenses.Where(lic => !string.IsNullOrEmpty(lic)))
{
pieces.Add(AddTermPrefix(Properties.Resources.ModSearchLicensePrefix, license));
}
foreach (var localization in Localizations.Where(lang => !string.IsNullOrEmpty(lang)))
{
pieces.Add(AddTermPrefix(Properties.Resources.ModSearchLanguagePrefix, localization));
Expand Down Expand Up @@ -309,6 +322,7 @@ public static ModSearch Parse(string combined, List<ModuleLabel> knownLabels)
string byName = "";
var byAuthors = new List<string>();
string byDescription = "";
var byLicenses = new List<string>();
var byLocalizations = new List<string>();

var depends = new List<string>();
Expand Down Expand Up @@ -338,6 +352,10 @@ public static ModSearch Parse(string combined, List<ModuleLabel> knownLabels)
{
byDescription += (ShouldNegateTerm(desc, out string subDesc) ? "-" : "") + CkanModule.nonAlphaNums.Replace(subDesc, "");
}
else if (TryPrefix(s, Properties.Resources.ModSearchLicensePrefix, out string lic))
{
byLicenses.Add(lic);
}
else if (TryPrefix(s, Properties.Resources.ModSearchLanguagePrefix, out string lang))
{
byLocalizations.Add(lang);
Expand Down Expand Up @@ -437,7 +455,8 @@ public static ModSearch Parse(string combined, List<ModuleLabel> knownLabels)
}
}
return new ModSearch(
byName, byAuthors, byDescription, byLocalizations,
byName, byAuthors, byDescription,
byLicenses, byLocalizations,
depends, recommends, suggests, conflicts, supports,
tagNames, labels,
compatible, installed, cached, newlyCompatible,
Expand Down Expand Up @@ -495,6 +514,7 @@ public bool Matches(GUIMod mod)
=> MatchesName(mod)
&& MatchesAuthors(mod)
&& MatchesDescription(mod)
&& MatchesLicenses(mod)
&& MatchesLocalizations(mod)
&& MatchesDepends(mod)
&& MatchesRecommends(mod)
Expand Down Expand Up @@ -530,6 +550,19 @@ private bool MatchesDescription(GUIMod mod)
mod.SearchableAbstract.IndexOf(subDesc, StringComparison.InvariantCultureIgnoreCase) != -1
|| mod.SearchableDescription.IndexOf(subDesc, StringComparison.InvariantCultureIgnoreCase) != -1);

private bool MatchesLicenses(GUIMod mod)
{
var ckm = mod.ToModule();
return Licenses.Count < 1
|| (
ckm.license != null
&& Licenses.All(searchLic =>
ShouldNegateTerm(searchLic, out string subLic)
^ ckm.license.Any(modLic =>
modLic.ToString().StartsWith(subLic, StringComparison.InvariantCultureIgnoreCase)))
);
}

private bool MatchesLocalizations(GUIMod mod)
{
var ckm = mod.ToModule();
Expand Down Expand Up @@ -604,6 +637,7 @@ public bool Equals(ModSearch other)
&& Upgradeable == other.Upgradeable
&& Replaceable == other.Replaceable
&& Authors.SequenceEqual(other.Authors)
&& Licenses.SequenceEqual(other.Licenses)
&& Localizations.SequenceEqual(other.Localizations)
&& DependsOn.SequenceEqual(other.DependsOn)
&& Recommends.SequenceEqual(other.Recommends)
Expand Down
1 change: 1 addition & 0 deletions GUI/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,7 @@ If unchecked, only mods in the pack will be installed.</value></data>
<data name="TriStateToggleBothTooltip" xml:space="preserve"><value>Yes or No</value></data>
<data name="TriStateToggleNoTooltip" xml:space="preserve"><value>No</value></data>
<data name="ModSearchDescriptionPrefix" xml:space="preserve"><value>desc:</value></data>
<data name="ModSearchLicensePrefix" xml:space="preserve"><value>lic:</value></data>
<data name="ModSearchLanguagePrefix" xml:space="preserve"><value>lang:</value></data>
<data name="ModSearchDependsPrefix" xml:space="preserve"><value>dep:</value></data>
<data name="ModSearchRecommendsPrefix" xml:space="preserve"><value>rec:</value></data>
Expand Down

0 comments on commit 5a7a2f7

Please sign in to comment.