diff --git a/Core/GameInstance.cs b/Core/GameInstance.cs index bf316c7d79..b5f3e68566 100644 --- a/Core/GameInstance.cs +++ b/Core/GameInstance.cs @@ -122,20 +122,6 @@ private void SetupCkanDirectories(bool scan = true) User.RaiseMessage(Properties.Resources.GameInstanceCreatingDir, InstallHistoryDir()); txFileMgr.CreateDirectory(InstallHistoryDir()); } - - // Clear any temporary files we find. If the directory - // doesn't exist, then no sweat; FilesystemTransaction - // will auto-create it as needed. - // Create our temporary directories, or clear them if they - // already exist. - if (Directory.Exists(TempDir())) - { - var directory = new DirectoryInfo(TempDir()); - foreach (FileInfo file in directory.GetFiles()) - txFileMgr.Delete(file.FullName); - foreach (DirectoryInfo subDirectory in directory.GetDirectories()) - txFileMgr.DeleteDirectory(subDirectory.FullName); - } log.InfoFormat("Initialised {0}", CkanDir()); } @@ -334,8 +320,10 @@ public string DownloadCacheDir() public string InstallHistoryDir() => CKANPathUtils.NormalizePath(Path.Combine(CkanDir(), "history")); - public string TempDir() - => CKANPathUtils.NormalizePath(Path.Combine(CkanDir(), "temp")); + public IOrderedEnumerable InstallHistoryFiles() + => Directory.EnumerateFiles(InstallHistoryDir(), "*.ckan") + .Select(f => new FileInfo(f)) + .OrderByDescending(fi => fi.CreationTime); public GameVersion Version() { diff --git a/Core/HelpURLs.cs b/Core/HelpURLs.cs index be179ccb34..787bc95034 100644 --- a/Core/HelpURLs.cs +++ b/Core/HelpURLs.cs @@ -18,6 +18,8 @@ public static class HelpURLs public const string Labels = "https://github.com/KSP-CKAN/CKAN/pull/2936"; public const string PlayTime = "https://github.com/KSP-CKAN/CKAN/pull/3543"; public const string DownloadsFailed = "https://github.com/KSP-CKAN/CKAN/pull/3635"; + public const string UnmanagedFiles = "https://github.com/KSP-CKAN/CKAN/pull/3833"; + public const string InstallationHistory = "https://github.com/KSP-CKAN/CKAN/pull/3834"; public const string Discord = "https://discord.gg/Mb4nXQD"; } diff --git a/Core/Versioning/ModuleVersion.cs b/Core/Versioning/ModuleVersion.cs index c51e702226..7c5ac2883b 100644 --- a/Core/Versioning/ModuleVersion.cs +++ b/Core/Versioning/ModuleVersion.cs @@ -86,9 +86,16 @@ public ModuleVersion IncrementEpoch() /// The return value should not be considered safe for use in file paths. /// public override string ToString() - { - return _string; - } + => _string; + + public string ToString(bool hideEpoch, bool hideV) + => hideEpoch + ? hideV + ? ModuleInstaller.StripEpoch(ModuleInstaller.StripV(_string)) + : ModuleInstaller.StripEpoch(_string) + : hideV + ? ModuleInstaller.StripV(_string) + : _string; } public partial class ModuleVersion : IEquatable diff --git a/GUI/CKAN-GUI.csproj b/GUI/CKAN-GUI.csproj index 82a63f21d1..5aeb0486bb 100644 --- a/GUI/CKAN-GUI.csproj +++ b/GUI/CKAN-GUI.csproj @@ -237,6 +237,12 @@ UnmanagedFiles.cs + + UserControl + + + InstallationHistory.cs + UserControl @@ -340,6 +346,9 @@ Form + + Form + Form @@ -880,6 +889,9 @@ UnmanagedFiles.cs + + InstallationHistory.cs + PlayTime.cs diff --git a/GUI/Controls/InstallationHistory.Designer.cs b/GUI/Controls/InstallationHistory.Designer.cs new file mode 100644 index 0000000000..77a177e069 --- /dev/null +++ b/GUI/Controls/InstallationHistory.Designer.cs @@ -0,0 +1,238 @@ +namespace CKAN.GUI +{ + partial class InstallationHistory + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new SingleAssemblyComponentResourceManager(typeof(InstallationHistory)); + this.ToolTip = new System.Windows.Forms.ToolTip(); + this.Toolbar = new System.Windows.Forms.MenuStrip(); + this.InstallButton = new System.Windows.Forms.ToolStripMenuItem(); + this.Splitter = new System.Windows.Forms.SplitContainer(); + this.HistoryListView = new ThemedListView(); + this.TimestampColumn = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.ModsListView = new ThemedListView(); + this.NotInstalledGroup = new System.Windows.Forms.ListViewGroup(); + this.InstalledGroup = new System.Windows.Forms.ListViewGroup(); + this.NameColumn = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.VersionColumn = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.AuthorColumn = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.DescriptionColumn = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.SelectInstallMessage = new System.Windows.Forms.ListViewItem(); + this.NoModsMessage = new System.Windows.Forms.ListViewItem(); + this.BottomButtonPanel = new LeftRightRowPanel(); + this.OKButton = new System.Windows.Forms.Button(); + this.BottomButtonPanel.SuspendLayout(); + this.SuspendLayout(); + // + // Toolbar + // + this.Toolbar.AutoSize = false; + this.Toolbar.Dock = System.Windows.Forms.DockStyle.Top; + this.Toolbar.ImageScalingSize = new System.Drawing.Size(24, 24); + this.Toolbar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.InstallButton}); + this.Toolbar.CanOverflow = true; + this.Toolbar.Location = new System.Drawing.Point(0, 0); + this.Toolbar.Name = "Toolbar"; + this.Toolbar.ShowItemToolTips = true; + this.Toolbar.Size = new System.Drawing.Size(5876, 48); + this.Toolbar.TabStop = true; + this.Toolbar.TabIndex = 0; + this.Toolbar.Text = "Toolbar"; + // + // InstallButton + // + //this.InstallButton.Image = global::CKAN.GUI.Properties.Resources.install; + this.InstallButton.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None; + this.InstallButton.Name = "InstallButton"; + this.InstallButton.Size = new System.Drawing.Size(114, 56); + this.InstallButton.Overflow = System.Windows.Forms.ToolStripItemOverflow.AsNeeded; + this.InstallButton.Click += new System.EventHandler(this.InstallButton_Click); + resources.ApplyResources(this.InstallButton, "InstallButton"); + // + // Splitter + // + this.Splitter.Dock = System.Windows.Forms.DockStyle.Fill; + this.Splitter.FixedPanel = System.Windows.Forms.FixedPanel.Panel1; + this.Splitter.IsSplitterFixed = true; + this.Splitter.Location = new System.Drawing.Point(5, 70); + this.Splitter.Margin = new System.Windows.Forms.Padding(0,0,0,0); + this.Splitter.Name = "Splitter"; + this.Splitter.Size = new System.Drawing.Size(490, 385); + this.Splitter.SplitterDistance = 100; + this.Splitter.SplitterWidth = 10; + this.Splitter.TabIndex = 1; + // + // Splitter.Panel1 + // + this.Splitter.Panel1.Controls.Add(this.HistoryListView); + this.Splitter.Panel1MinSize = 100; + // + // Splitter.Panel2 + // + this.Splitter.Panel2.Controls.Add(this.ModsListView); + this.Splitter.Panel2MinSize = 400; + // + // HistoryListView + // + this.HistoryListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.TimestampColumn}); + this.HistoryListView.CheckBoxes = false; + this.HistoryListView.FullRowSelect = true; + this.HistoryListView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None; + this.HistoryListView.HideSelection = false; + this.HistoryListView.Location = new System.Drawing.Point(0, 0); + this.HistoryListView.MultiSelect = false; + this.HistoryListView.Name = "HistoryListView"; + this.HistoryListView.Size = new System.Drawing.Size(230, 455); + this.HistoryListView.TabIndex = 2; + this.HistoryListView.UseCompatibleStateImageBehavior = false; + this.HistoryListView.View = System.Windows.Forms.View.Details; + this.HistoryListView.Dock = System.Windows.Forms.DockStyle.Fill; + this.HistoryListView.ItemSelectionChanged += new System.Windows.Forms.ListViewItemSelectionChangedEventHandler(HistoryListView_ItemSelectionChanged); + // + // TimestampColumn + // + this.TimestampColumn.Width = -1; + resources.ApplyResources(this.TimestampColumn, "TimestampColumn"); + // + // ModsListView + // + this.ModsListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.NameColumn, + this.VersionColumn, + this.AuthorColumn, + this.DescriptionColumn}); + this.ModsListView.CheckBoxes = false; + this.ModsListView.FullRowSelect = true; + this.ModsListView.HideSelection = false; + this.ModsListView.Groups.Add(this.NotInstalledGroup); + this.ModsListView.Groups.Add(this.InstalledGroup); + this.ModsListView.Location = new System.Drawing.Point(0, 0); + this.ModsListView.MultiSelect = false; + this.ModsListView.Name = "ModsListView"; + this.ModsListView.Size = new System.Drawing.Size(230, 455); + this.ModsListView.TabIndex = 2; + this.ModsListView.UseCompatibleStateImageBehavior = false; + this.ModsListView.View = System.Windows.Forms.View.Details; + this.ModsListView.Dock = System.Windows.Forms.DockStyle.Fill; + this.ModsListView.ItemSelectionChanged += new System.Windows.Forms.ListViewItemSelectionChangedEventHandler(ModsListView_ItemSelectionChanged); + // + // NotInstalledGroup + // + this.NotInstalledGroup.Name = "NotInstalledGroup"; + this.NotInstalledGroup.HeaderAlignment = System.Windows.Forms.HorizontalAlignment.Left; + resources.ApplyResources(this.NotInstalledGroup, "NotInstalledGroup"); + // + // InstalledGroup + // + this.InstalledGroup.Name = "InstalledGroup"; + this.InstalledGroup.HeaderAlignment = System.Windows.Forms.HorizontalAlignment.Left; + resources.ApplyResources(this.InstalledGroup, "InstalledGroup"); + // + // NameColumn + // + this.NameColumn.Width = -1; + resources.ApplyResources(this.NameColumn, "NameColumn"); + // + // VersionColumn + // + this.VersionColumn.Width = 70; + resources.ApplyResources(this.VersionColumn, "VersionColumn"); + // + // AuthorColumn + // + this.AuthorColumn.Width = 120; + resources.ApplyResources(this.AuthorColumn, "AuthorColumn"); + // + // DescriptionColumn + // + this.DescriptionColumn.Width = -1; + resources.ApplyResources(this.DescriptionColumn, "DescriptionColumn"); + // + // SelectInstallMessage + // + resources.ApplyResources(this.SelectInstallMessage, "SelectInstallMessage"); + // + // NoModsMessage + // + resources.ApplyResources(this.NoModsMessage, "NoModsMessage"); + // + // BottomButtonPanel + // + this.BottomButtonPanel.RightControls.Add(this.OKButton); + this.BottomButtonPanel.Dock = System.Windows.Forms.DockStyle.Bottom; + this.BottomButtonPanel.Name = "BottomButtonPanel"; + // + // OKButton + // + this.OKButton.AutoSize = true; + this.OKButton.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowOnly; + this.OKButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.OKButton.Name = "OKButton"; + this.OKButton.Size = new System.Drawing.Size(112, 30); + this.OKButton.TabIndex = 2; + this.OKButton.Click += new System.EventHandler(this.OKButton_Click); + resources.ApplyResources(this.OKButton, "OKButton"); + // + // InstallationHistory + // + this.Controls.Add(this.Splitter); + this.Controls.Add(this.Toolbar); + this.Controls.Add(this.BottomButtonPanel); + this.Name = "InstallationHistory"; + this.Size = new System.Drawing.Size(500, 500); + resources.ApplyResources(this, "$this"); + this.BottomButtonPanel.ResumeLayout(false); + this.BottomButtonPanel.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + } + + #endregion + + private System.Windows.Forms.ToolTip ToolTip; + private System.Windows.Forms.MenuStrip Toolbar; + private System.Windows.Forms.ToolStripMenuItem InstallButton; + private System.Windows.Forms.SplitContainer Splitter; + private System.Windows.Forms.ListView HistoryListView; + private System.Windows.Forms.ColumnHeader TimestampColumn; + private System.Windows.Forms.ListView ModsListView; + private System.Windows.Forms.ListViewGroup NotInstalledGroup; + private System.Windows.Forms.ListViewGroup InstalledGroup; + private System.Windows.Forms.ColumnHeader NameColumn; + private System.Windows.Forms.ColumnHeader VersionColumn; + private System.Windows.Forms.ColumnHeader AuthorColumn; + private System.Windows.Forms.ColumnHeader DescriptionColumn; + private System.Windows.Forms.ListViewItem SelectInstallMessage; + private System.Windows.Forms.ListViewItem NoModsMessage; + private LeftRightRowPanel BottomButtonPanel; + private System.Windows.Forms.Button OKButton; + } +} diff --git a/GUI/Controls/InstallationHistory.cs b/GUI/Controls/InstallationHistory.cs new file mode 100644 index 0000000000..5e940396b0 --- /dev/null +++ b/GUI/Controls/InstallationHistory.cs @@ -0,0 +1,231 @@ +using System; +using System.Linq; +using System.Collections; +using System.Collections.Generic; +using System.Drawing; +using System.Windows.Forms; +using System.IO; +using System.Threading.Tasks; + +using CKAN.Games; + +namespace CKAN.GUI +{ + public partial class InstallationHistory : UserControl + { + public InstallationHistory() + { + InitializeComponent(); + } + + public void LoadHistory(GameInstance inst, GUIConfiguration config) + { + this.inst = inst; + this.registry = RegistryManager.Instance(inst).registry; + this.config = config; + Util.Invoke(this, () => + { + UseWaitCursor = true; + Task.Factory.StartNew(() => + { + var items = inst.InstallHistoryFiles() + .Select(fi => new ListViewItem(fi.CreationTime.ToString("g")) + { + Tag = fi + }) + .ToArray(); + Util.Invoke(this, () => + { + HistoryListView.BeginUpdate(); + HistoryListView.Items.Clear(); + HistoryListView.Items.AddRange(items); + HistoryListView.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent); + Splitter.Panel1MinSize = Splitter.SplitterDistance = + TimestampColumn.Width + + SystemInformation.VerticalScrollBarWidth + + 4 * SystemInformation.BorderSize.Width; + HistoryListView.EndUpdate(); + HistoryListView_ItemSelectionChanged(null, null); + UseWaitCursor = false; + }); + }); + }); + } + + /// + /// Invoked when the user selects a module + /// + public event Action OnSelectedModuleChanged; + + /// + /// Invoked when the user clicks the Install toolbar button + /// + public event Action Install; + + /// + /// Invoked when the user clicks OK + /// + public event Action Done; + + /// + /// Open the user guide when the user presses F1 + /// + protected override void OnHelpRequested(HelpEventArgs evt) + { + evt.Handled = Util.TryOpenWebPage(HelpURLs.InstallationHistory); + } + + private void HistoryListView_ItemSelectionChanged(Object sender, ListViewItemSelectionChangedEventArgs e) + { + UseWaitCursor = true; + Task.Factory.StartNew(() => + { + try + { + var path = HistoryListView.SelectedItems + .Cast() + .Select(lvi => lvi.Tag as FileInfo) + .First(); + var modRows = CkanModule.FromFile(path.FullName) + .depends + .Select(rel => rel as ModuleRelationshipDescriptor) + .Where(rel => rel != null) + .Select(ItemFromRelationship) + .Where(row => row != null) + .ToArray(); + Util.Invoke(this, () => + { + ModsListView.BeginUpdate(); + ModsListView.Items.Clear(); + if (modRows.Length > 0) + { + if (!ModsListView.ShowGroups) + { + // Work around first group header not showing up on first click + ModsListView.EndUpdate(); + ModsListView.ShowGroups = true; + ModsListView.HeaderStyle = ColumnHeaderStyle.Clickable; + ModsListView.BeginUpdate(); + } + ModsListView.Items.AddRange(modRows); + } + else + { + ModsListView.ShowGroups = false; + ModsListView.HeaderStyle = ColumnHeaderStyle.None; + ModsListView.Items.Add(NoModsMessage); + } + // Don't auto-resize version or author columns + ModsListView.AutoResizeColumn(NameColumn.Index, ColumnHeaderAutoResizeStyle.ColumnContent); + ModsListView.AutoResizeColumn(DescriptionColumn.Index, ColumnHeaderAutoResizeStyle.ColumnContent); + ModsListView.EndUpdate(); + OnSelectedModuleChanged?.Invoke(null); + UseWaitCursor = false; + }); + } + catch + { + Util.Invoke(this, () => + { + ModsListView.BeginUpdate(); + ModsListView.Items.Clear(); + ModsListView.ShowGroups = false; + ModsListView.HeaderStyle = ColumnHeaderStyle.None; + ModsListView.Items.Add(SelectInstallMessage); + ModsListView.AutoResizeColumn(NameColumn.Index, ColumnHeaderAutoResizeStyle.ColumnContent); + ModsListView.EndUpdate(); + UseWaitCursor = false; + }); + } + }); + } + + private ListViewItem ItemFromRelationship(ModuleRelationshipDescriptor rel) + { + var mod = registry.GetModuleByVersion(rel.name, rel.version) + ?? SaneLatestAvail(rel.name); + return mod == null + ? new ListViewItem(new string[] + { + rel.name, + rel.version.ToString(config.HideEpochs, config.HideV), + "???", + "???" + }) + { + Tag = rel, + Group = registry.IsInstalled(rel.name, false) + ? InstalledGroup + : NotInstalledGroup + } + : mod.IsDLC + // Never show DLC + ? null + : new ListViewItem(new string[] + { + mod.name, + mod.version.ToString(config.HideEpochs, config.HideV), + string.Join(", ", mod.author), + mod.@abstract + }) + { + Tag = mod, + Group = registry.IsInstalled(mod.identifier, false) + ? InstalledGroup + : NotInstalledGroup + }; + } + + // Registry.LatestAvailable without exceptions + private CkanModule SaneLatestAvail(string identifier) + { + try + { + return registry.LatestAvailable(identifier, inst.VersionCriteria()); + } + catch + { + try + { + return registry.LatestAvailable(identifier, null); + } + catch + { + return null; + } + } + } + + private void ModsListView_ItemSelectionChanged(Object sender, ListViewItemSelectionChangedEventArgs e) + { + var mod = ModsListView.SelectedItems + .Cast() + .Select(lvi => lvi.Tag as CkanModule) + .FirstOrDefault(); + if (mod != null) + { + OnSelectedModuleChanged?.Invoke(new GUIMod( + mod, registry, inst.VersionCriteria())); + } + } + + private void InstallButton_Click(object sender, EventArgs e) + { + Install?.Invoke(ModsListView.Items + .Cast() + .Where(lvi => lvi.Group == NotInstalledGroup) + .Select(lvi => lvi.Tag as CkanModule) + .Where(mod => mod != null) + .ToArray()); + } + + private void OKButton_Click(object sender, EventArgs e) + { + Done?.Invoke(); + } + + private GameInstance inst; + private Registry registry; + private GUIConfiguration config; + } +} diff --git a/GUI/Controls/InstallationHistory.resx b/GUI/Controls/InstallationHistory.resx new file mode 100644 index 0000000000..66e56a174b --- /dev/null +++ b/GUI/Controls/InstallationHistory.resx @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Timestamp + Not currently installed + Currently installed + Name + Version + Authors + Description + Click a timestamp at the left to see which mods were installed + No mods were installed + Install + OK + diff --git a/GUI/Controls/ManageMods.cs b/GUI/Controls/ManageMods.cs index aab0d4e0c3..92fb35d980 100644 --- a/GUI/Controls/ManageMods.cs +++ b/GUI/Controls/ManageMods.cs @@ -1133,20 +1133,20 @@ private void _UpdateModsList(Dictionary old_modules = null) gui_mods.UnionWith( registry.InstalledModules .Where(instMod => !instMod.Module.IsDLC) - .Select(instMod => new GUIMod(instMod, registry, versionCriteria)) - ); + .Select(instMod => new GUIMod(instMod, registry, versionCriteria, null, + Main.Instance.configuration.HideEpochs, Main.Instance.configuration.HideV))); Main.Instance.Wait.AddLogMessage(Properties.Resources.MainModListLoadingAvailable); gui_mods.UnionWith( registry.CompatibleModules(versionCriteria) .Where(m => !m.IsDLC) - .Select(m => new GUIMod(m, registry, versionCriteria)) - ); + .Select(m => new GUIMod(m, registry, versionCriteria, null, + Main.Instance.configuration.HideEpochs, Main.Instance.configuration.HideV))); Main.Instance.Wait.AddLogMessage(Properties.Resources.MainModListLoadingIncompatible); gui_mods.UnionWith( registry.IncompatibleModules(versionCriteria) .Where(m => !m.IsDLC) - .Select(m => new GUIMod(m, registry, versionCriteria, true)) - ); + .Select(m => new GUIMod(m, registry, versionCriteria, true, + Main.Instance.configuration.HideEpochs, Main.Instance.configuration.HideV))); Main.Instance.Wait.AddLogMessage(Properties.Resources.MainModListPreservingNew); var toNotify = new HashSet(); @@ -1187,7 +1187,7 @@ private void _UpdateModsList(Dictionary old_modules = null) Main.Instance.Wait.AddLogMessage(Properties.Resources.MainModListPopulatingList); // Update our mod listing - mainModList.ConstructModList(gui_mods.ToList(), Main.Instance.CurrentInstance.Name, ChangeSet, Main.Instance.configuration.HideEpochs, Main.Instance.configuration.HideV); + mainModList.ConstructModList(gui_mods.ToList(), Main.Instance.CurrentInstance.Name, ChangeSet); mainModList.Modules = new ReadOnlyCollection( mainModList.full_list_of_mod_rows.Values.Select(row => row.Tag as GUIMod).ToList()); @@ -1641,8 +1641,7 @@ public async Task UpdateChangeSetAndConflicts(GameInstance inst, IRegistryQuerie try { var gameVersion = inst.VersionCriteria(); - var module_installer = new ModuleInstaller(inst, Main.Instance.Manager.Cache, Main.Instance.currentUser); - var tuple = mainModList.ComputeFullChangeSetFromUserChangeSet(registry, user_change_set, module_installer, gameVersion); + var tuple = mainModList.ComputeFullChangeSetFromUserChangeSet(registry, user_change_set, gameVersion); full_change_set = tuple.Item1.ToList(); new_conflicts = tuple.Item2.ToDictionary( item => new GUIMod(item.Key, registry, gameVersion), diff --git a/GUI/Controls/UnmanagedFiles.cs b/GUI/Controls/UnmanagedFiles.cs index bea989cfab..1dedbf7f64 100644 --- a/GUI/Controls/UnmanagedFiles.cs +++ b/GUI/Controls/UnmanagedFiles.cs @@ -7,6 +7,8 @@ using System.IO; using System.Threading.Tasks; +using CKAN.Games; + namespace CKAN.GUI { public partial class UnmanagedFiles : UserControl @@ -17,9 +19,11 @@ public UnmanagedFiles() GameFolderTree.TreeViewNodeSorter = new DirsFirstSorter(); } - public void Refresh() + public void LoadFiles(GameInstance inst) { - Util.Invoke(GameFolderTree, _UpdateGameFolderTree); + this.inst = inst; + this.registry = RegistryManager.Instance(inst).registry; + Util.Invoke(this, _UpdateGameFolderTree); } /// @@ -27,7 +31,13 @@ public void Refresh() /// public event Action Done; - private GameInstanceManager manager => Main.Instance.Manager; + /// + /// Open the user guide when the user presses F1 + /// + protected override void OnHelpRequested(HelpEventArgs evt) + { + evt.Handled = Util.TryOpenWebPage(HelpURLs.UnmanagedFiles); + } private void _UpdateGameFolderTree() { @@ -37,14 +47,13 @@ private void _UpdateGameFolderTree() GameFolderTree.Nodes.Clear(); var rootNode = GameFolderTree.Nodes.Add( "", - manager.CurrentInstance.GameDir().Replace('/', Path.DirectorySeparatorChar), + inst.GameDir().Replace('/', Path.DirectorySeparatorChar), "folder", "folder"); UseWaitCursor = true; Task.Factory.StartNew(() => { - var registry = RegistryManager.Instance(manager.CurrentInstance).registry; - var paths = manager.CurrentInstance?.UnmanagedFiles(registry).ToArray() + var paths = inst?.UnmanagedFiles(registry).ToArray() ?? new string[] { }; Util.Invoke(this, () => { @@ -55,7 +64,7 @@ private void _UpdateGameFolderTree() } rootNode.Expand(); rootNode.EnsureVisible(); - ExpandDefaultModDir(); + ExpandDefaultModDir(inst.game); // The nodes don't have children at first, so the sort needs to be re-applied after they're added GameFolderTree.Sort(); GameFolderTree.EndUpdate(); @@ -68,9 +77,9 @@ private IEnumerable ParentPaths(string[] pathPieces) => Enumerable.Range(1, pathPieces.Length) .Select(numPieces => string.Join("/", pathPieces.Take(numPieces))); - private void ExpandDefaultModDir() + private void ExpandDefaultModDir(IGame game) { - foreach (string path in ParentPaths(manager.CurrentInstance.game.PrimaryModDirectoryRelative.Split(new char[] {'/'}))) + foreach (string path in ParentPaths(game.PrimaryModDirectoryRelative.Split(new char[] {'/'}))) { foreach (var node in GameFolderTree.Nodes.Find(path, true)) { @@ -126,7 +135,7 @@ private void ResetCollapseButton_Click(object sender, EventArgs e) GameFolderTree.BeginUpdate(); GameFolderTree.CollapseAll(); GameFolderTree.Nodes[0].Expand(); - ExpandDefaultModDir(); + ExpandDefaultModDir(inst.game); GameFolderTree.Nodes[0].EnsureVisible(); GameFolderTree.EndUpdate(); GameFolderTree.Focus(); @@ -141,9 +150,8 @@ private void ShowInFolderButton_Click(object sender, EventArgs e) private void DeleteButton_Click(object sender, EventArgs e) { var relPath = GameFolderTree.SelectedNode?.Name; - var registry = RegistryManager.Instance(manager.CurrentInstance).registry; - var absPath = manager.CurrentInstance.ToAbsoluteGameDir(relPath); - if (manager.CurrentInstance.HasManagedFiles(registry, absPath)) + var absPath = inst.ToAbsoluteGameDir(relPath); + if (inst.HasManagedFiles(registry, absPath)) { Main.Instance.ErrorDialog(Properties.Resources.FolderContainsManagedFiles, relPath); } @@ -184,7 +192,7 @@ private void OpenFileBrowser(TreeNode node) { if (node != null) { - string location = manager.CurrentInstance.ToAbsoluteGameDir(node.Name); + string location = inst.ToAbsoluteGameDir(node.Name); if (File.Exists(location)) { @@ -203,6 +211,9 @@ private void OpenFileBrowser(TreeNode node) Utilities.ProcessStartURL(location); } } + + private GameInstance inst; + private Registry registry; } internal class DirsFirstSorter : IComparer, IComparer diff --git a/GUI/Main/Main.Designer.cs b/GUI/Main/Main.Designer.cs index 7b64caf578..ad9784fe62 100644 --- a/GUI/Main/Main.Designer.cs +++ b/GUI/Main/Main.Designer.cs @@ -80,6 +80,8 @@ private void InitializeComponent() this.PlayTime = new CKAN.GUI.PlayTime(); this.UnmanagedFilesTabPage = new System.Windows.Forms.TabPage(); this.UnmanagedFiles = new CKAN.GUI.UnmanagedFiles(); + this.InstallationHistoryTabPage = new System.Windows.Forms.TabPage(); + this.InstallationHistory = new CKAN.GUI.InstallationHistory(); this.ChooseProvidedModsTabPage = new System.Windows.Forms.TabPage(); this.ChooseProvidedMods = new CKAN.GUI.ChooseProvidedMods(); this.minimizeNotifyIcon = new System.Windows.Forms.NotifyIcon(this.components); @@ -99,6 +101,7 @@ private void InitializeComponent() this.quitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.viewPlayTimeStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.viewUnmanagedFilesStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.installationHistoryStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.DeleteDirectoriesTabPage = new System.Windows.Forms.TabPage(); this.DeleteDirectories = new CKAN.GUI.DeleteDirectories(); this.EditModpackTabPage = new System.Windows.Forms.TabPage(); @@ -119,6 +122,8 @@ private void InitializeComponent() this.PlayTime.SuspendLayout(); this.UnmanagedFilesTabPage.SuspendLayout(); this.UnmanagedFiles.SuspendLayout(); + this.InstallationHistoryTabPage.SuspendLayout(); + this.InstallationHistory.SuspendLayout(); this.minimizedContextMenuStrip.SuspendLayout(); this.DeleteDirectoriesTabPage.SuspendLayout(); this.EditModpackTabPage.SuspendLayout(); @@ -144,6 +149,7 @@ private void InitializeComponent() this.manageGameInstancesMenuItem, this.openGameDirectoryToolStripMenuItem, this.toolStripSeparator1, + this.installationHistoryStripMenuItem, this.installFromckanToolStripMenuItem, this.importDownloadsToolStripMenuItem, this.toolStripSeparator2, @@ -426,6 +432,7 @@ private void InitializeComponent() this.MainTabControl.Controls.Add(this.ChooseRecommendedModsTabPage); this.MainTabControl.Controls.Add(this.PlayTimeTabPage); this.MainTabControl.Controls.Add(this.UnmanagedFilesTabPage); + this.MainTabControl.Controls.Add(this.InstallationHistoryTabPage); this.MainTabControl.Controls.Add(this.ChooseProvidedModsTabPage); this.MainTabControl.Controls.Add(this.DeleteDirectoriesTabPage); this.MainTabControl.Controls.Add(this.EditModpackTabPage); @@ -584,6 +591,31 @@ private void InitializeComponent() this.UnmanagedFiles.TabIndex = 32; this.UnmanagedFiles.Done += UnmanagedFiles_Done; // + // InstallationHistoryTabPage + // + this.InstallationHistoryTabPage.BackColor = System.Drawing.SystemColors.Control; + this.InstallationHistoryTabPage.Controls.Add(this.InstallationHistory); + this.InstallationHistoryTabPage.Location = new System.Drawing.Point(4, 29); + this.InstallationHistoryTabPage.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.InstallationHistoryTabPage.Name = "InstallationHistoryTabPage"; + this.InstallationHistoryTabPage.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.InstallationHistoryTabPage.Size = new System.Drawing.Size(1536, 948); + this.InstallationHistoryTabPage.TabIndex = 24; + resources.ApplyResources(this.InstallationHistoryTabPage, "InstallationHistoryTabPage"); + // + // InstallationHistory + // + this.InstallationHistory.Dock = System.Windows.Forms.DockStyle.Fill; + this.InstallationHistory.Location = new System.Drawing.Point(0, 0); + this.InstallationHistory.Margin = new System.Windows.Forms.Padding(0,0,0,0); + this.InstallationHistory.Padding = new System.Windows.Forms.Padding(0,0,0,0); + this.InstallationHistory.Name = "InstallationHistory"; + this.InstallationHistory.Size = new System.Drawing.Size(500, 500); + this.InstallationHistory.TabIndex = 32; + this.InstallationHistory.OnSelectedModuleChanged += InstallationHistory_OnSelectedModuleChanged; + this.InstallationHistory.Install += InstallationHistory_Install; + this.InstallationHistory.Done += InstallationHistory_Done; + // // ChooseProvidedModsTabPage // this.ChooseProvidedModsTabPage.BackColor = System.Drawing.SystemColors.Control; @@ -763,6 +795,13 @@ private void InitializeComponent() this.viewUnmanagedFilesStripMenuItem.Click += new System.EventHandler(this.viewUnmanagedFilesStripMenuItem_Click); resources.ApplyResources(this.viewUnmanagedFilesStripMenuItem, "viewUnmanagedFilesStripMenuItem"); // + // installationHistoryStripMenuItem + // + this.installationHistoryStripMenuItem.Name = "installationHistoryStripMenuItem"; + this.installationHistoryStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.installationHistoryStripMenuItem.Click += new System.EventHandler(this.installationHistoryStripMenuItem_Click); + resources.ApplyResources(this.installationHistoryStripMenuItem, "installationHistoryStripMenuItem"); + // // Main // this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); @@ -807,6 +846,10 @@ private void InitializeComponent() this.UnmanagedFilesTabPage.PerformLayout(); this.UnmanagedFiles.ResumeLayout(false); this.UnmanagedFiles.PerformLayout(); + this.InstallationHistoryTabPage.ResumeLayout(false); + this.InstallationHistoryTabPage.PerformLayout(); + this.InstallationHistory.ResumeLayout(false); + this.InstallationHistory.PerformLayout(); this.DeleteDirectoriesTabPage.ResumeLayout(false); this.DeleteDirectoriesTabPage.PerformLayout(); this.EditModpackTabPage.ResumeLayout(false); @@ -869,6 +912,8 @@ private void InitializeComponent() private CKAN.GUI.PlayTime PlayTime; private System.Windows.Forms.TabPage UnmanagedFilesTabPage; private CKAN.GUI.UnmanagedFiles UnmanagedFiles; + private System.Windows.Forms.TabPage InstallationHistoryTabPage; + private CKAN.GUI.InstallationHistory InstallationHistory; private System.Windows.Forms.TabPage ChooseProvidedModsTabPage; private CKAN.GUI.ChooseProvidedMods ChooseProvidedMods; private System.Windows.Forms.TabPage DeleteDirectoriesTabPage; @@ -892,5 +937,6 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripMenuItem quitToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem viewPlayTimeStripMenuItem; private System.Windows.Forms.ToolStripMenuItem viewUnmanagedFilesStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem installationHistoryStripMenuItem; } } diff --git a/GUI/Main/Main.cs b/GUI/Main/Main.cs index c97002ea6d..7fa3f099df 100644 --- a/GUI/Main/Main.cs +++ b/GUI/Main/Main.cs @@ -595,73 +595,77 @@ private void installFromckanToolStripMenuItem_Click(object sender, EventArgs e) if (open_file_dialog.ShowDialog(this) == DialogResult.OK) { - // We'll need to make some registry changes to do this. - RegistryManager registry_manager = RegistryManager.Instance(CurrentInstance); - var crit = CurrentInstance.VersionCriteria(); - - var installed = registry_manager.registry.InstalledModules.Select(inst => inst.Module).ToList(); - var toInstall = new List(); + InstallFromCkanFiles(open_file_dialog.FileNames); + } + } - foreach (string path in open_file_dialog.FileNames) - { - CkanModule module; + private void InstallFromCkanFiles(string[] files) + { + // We'll need to make some registry changes to do this. + RegistryManager registry_manager = RegistryManager.Instance(CurrentInstance); + var crit = CurrentInstance.VersionCriteria(); - try - { - module = CkanModule.FromFile(path); - if (module.IsMetapackage && module.depends != null) - { - // Add metapackage dependencies to the changeset so we can skip compat checks for them - toInstall.AddRange(module.depends - .Where(rel => !rel.MatchesAny(installed, null, null)) - .Select(rel => - // If there's a compatible match, return it - // Metapackages aren't intending to prompt users to choose providing mods - rel.ExactMatch(registry_manager.registry, crit, installed, toInstall) - // Otherwise look for incompatible - ?? rel.ExactMatch(registry_manager.registry, null, installed, toInstall)) - .Where(mod => mod != null)); - } - toInstall.Add(module); - } - catch (Kraken kraken) - { - currentUser.RaiseError(kraken.InnerException == null - ? kraken.Message - : $"{kraken.Message}: {kraken.InnerException.Message}"); + var installed = registry_manager.registry.InstalledModules.Select(inst => inst.Module).ToList(); + var toInstall = new List(); + foreach (string path in files) + { + CkanModule module; - continue; - } - catch (Exception ex) + try + { + module = CkanModule.FromFile(path); + if (module.IsMetapackage && module.depends != null) { - currentUser.RaiseError(ex.Message); - continue; + // Add metapackage dependencies to the changeset so we can skip compat checks for them + toInstall.AddRange(module.depends + .Where(rel => !rel.MatchesAny(installed, null, null)) + .Select(rel => + // If there's a compatible match, return it + // Metapackages aren't intending to prompt users to choose providing mods + rel.ExactMatch(registry_manager.registry, crit, installed, toInstall) + // Otherwise look for incompatible + ?? rel.ExactMatch(registry_manager.registry, null, installed, toInstall)) + .Where(mod => mod != null)); } + toInstall.Add(module); + } + catch (Kraken kraken) + { + currentUser.RaiseError(kraken.InnerException == null + ? kraken.Message + : $"{kraken.Message}: {kraken.InnerException.Message}"); - if (module.IsDLC) - { - currentUser.RaiseError(Properties.Resources.MainCantInstallDLC, module); - continue; - } + continue; } - // Get all recursively incompatible module identifiers (quickly) - var allIncompat = registry_manager.registry.IncompatibleModules(crit) - .Select(mod => mod.identifier) - .ToHashSet(); - // Get incompatible mods we're installing - var myIncompat = toInstall.Where(mod => allIncompat.Contains(mod.identifier)).ToList(); - if (!myIncompat.Any() - // Confirm installation of incompatible like the Versions tab does - || Main.Instance.YesNoDialog( - string.Format(Properties.Resources.ModpackInstallIncompatiblePrompt, - string.Join(Environment.NewLine, myIncompat), - crit.ToSummaryString(CurrentInstance.game)), - Properties.Resources.AllModVersionsInstallYes, - Properties.Resources.AllModVersionsInstallNo)) + catch (Exception ex) { - InstallModuleDriver(registry_manager.registry, toInstall); + currentUser.RaiseError(ex.Message); + continue; + } + + if (module.IsDLC) + { + currentUser.RaiseError(Properties.Resources.MainCantInstallDLC, module); + continue; } } + // Get all recursively incompatible module identifiers (quickly) + var allIncompat = registry_manager.registry.IncompatibleModules(crit) + .Select(mod => mod.identifier) + .ToHashSet(); + // Get incompatible mods we're installing + var myIncompat = toInstall.Where(mod => allIncompat.Contains(mod.identifier)).ToList(); + if (!myIncompat.Any() + // Confirm installation of incompatible like the Versions tab does + || Main.Instance.YesNoDialog( + string.Format(Properties.Resources.ModpackInstallIncompatiblePrompt, + string.Join(Environment.NewLine, myIncompat), + crit.ToSummaryString(CurrentInstance.game)), + Properties.Resources.AllModVersionsInstallYes, + Properties.Resources.AllModVersionsInstallNo)) + { + InstallModuleDriver(registry_manager.registry, toInstall); + } } private void CompatibleGameVersionsToolStripMenuItem_Click(object sender, EventArgs e) @@ -731,8 +735,9 @@ private void ShowSelectionModInfo(ListView.SelectedListViewItemCollection select ActiveModInfo = module == null ? null : new GUIMod( module, RegistryManager.Instance(CurrentInstance).registry, - CurrentInstance.VersionCriteria() - ); + CurrentInstance.VersionCriteria(), + configuration.HideEpochs, + configuration.HideV); } private void ManageMods_OnChangeSetChanged(List changeset, Dictionary conflicts) diff --git a/GUI/Main/Main.resx b/GUI/Main/Main.resx index 67a5397b7f..9a8d9c15f4 100644 --- a/GUI/Main/Main.resx +++ b/GUI/Main/Main.resx @@ -153,6 +153,7 @@ Delete Directories Edit Modpack Unmanaged Files + Installation History CKAN N available updates Refresh @@ -164,5 +165,6 @@ Quit Play &time... &Unmanaged files... + Installation &history... CKAN diff --git a/GUI/Main/MainHistory.cs b/GUI/Main/MainHistory.cs new file mode 100644 index 0000000000..63230612f6 --- /dev/null +++ b/GUI/Main/MainHistory.cs @@ -0,0 +1,48 @@ +using System; +using System.IO; +using System.Linq; +using System.Collections.Generic; + +using CKAN.Extensions; + +// Don't warn if we use our own obsolete properties +#pragma warning disable 0618 + +namespace CKAN.GUI +{ + public partial class Main + { + private void installationHistoryStripMenuItem_Click(object sender, EventArgs e) + { + InstallationHistory.LoadHistory(manager.CurrentInstance, configuration); + tabController.ShowTab("InstallationHistoryTabPage", 2); + DisableMainWindow(); + } + + private void InstallationHistory_Install(CkanModule[] modules) + { + InstallationHistory_Done(); + var tuple = ManageMods.mainModList.ComputeFullChangeSetFromUserChangeSet( + RegistryManager.Instance(CurrentInstance).registry, + modules.Select(mod => new ModChange(mod, GUIModChangeType.Install)) + .ToHashSet(), + CurrentInstance.VersionCriteria()); + UpdateChangesDialog(tuple.Item1.ToList(), tuple.Item2); + tabController.ShowTab("ChangesetTabPage", 1); + } + + private void InstallationHistory_Done() + { + UpdateStatusBar(); + tabController.ShowTab("ManageModsTabPage"); + tabController.HideTab("InstallationHistoryTabPage"); + EnableMainWindow(); + } + + private void InstallationHistory_OnSelectedModuleChanged(GUIMod m) + { + ActiveModInfo = m; + } + + } +} diff --git a/GUI/Main/MainUnmanaged.cs b/GUI/Main/MainUnmanaged.cs index dc9f94e4ef..83bade6509 100644 --- a/GUI/Main/MainUnmanaged.cs +++ b/GUI/Main/MainUnmanaged.cs @@ -9,7 +9,7 @@ public partial class Main { private void viewUnmanagedFilesStripMenuItem_Click(object sender, EventArgs e) { - UnmanagedFiles.Refresh(); + UnmanagedFiles.LoadFiles(manager.CurrentInstance); tabController.ShowTab("UnmanagedFilesTabPage", 2); DisableMainWindow(); } diff --git a/GUI/Model/GUIMod.cs b/GUI/Model/GUIMod.cs index d12b35cd99..f844a7f841 100644 --- a/GUI/Model/GUIMod.cs +++ b/GUI/Model/GUIMod.cs @@ -112,15 +112,11 @@ private void OnPropertyChanged([CallerMemberName] string name = null) /// otherwise false. /// public bool IsInstallable() - { - // Compatible mods are installable, but so are mods that are already installed - return !IsIncompatible || IsInstalled; - } + // Compatible mods are installable, but so are mods that are already installed + => !IsIncompatible || IsInstalled; public string Version - { - get { return IsInstalled ? InstalledVersion : LatestVersion; } - } + => IsInstalled ? InstalledVersion : LatestVersion; /// /// Initialize a GUIMod based on an InstalledModule @@ -129,8 +125,8 @@ public string Version /// CKAN registry object for current game instance /// Current game version /// If true, mark this module as incompatible - public GUIMod(InstalledModule instMod, IRegistryQuerier registry, GameVersionCriteria current_game_version, bool? incompatible = null) - : this(instMod.Module, registry, current_game_version, incompatible) + public GUIMod(InstalledModule instMod, IRegistryQuerier registry, GameVersionCriteria current_game_version, bool? incompatible = null, bool hideEpochs = false, bool hideV = false) + : this(instMod.Module, registry, current_game_version, incompatible, hideEpochs, hideV) { IsInstalled = true; IsInstallChecked = true; @@ -139,7 +135,8 @@ public GUIMod(InstalledModule instMod, IRegistryQuerier registry, GameVersionCri ?? instMod.Module; IsAutoInstalled = instMod.AutoInstalled; InstallDate = instMod.InstallTime; - InstalledVersion = instMod.Module.version.ToString(); + + InstalledVersion = instMod.Module.version.ToString(hideEpochs, hideV); if (LatestVersion == null || LatestVersion.Equals("-")) { LatestVersion = InstalledVersion; @@ -155,8 +152,8 @@ public GUIMod(InstalledModule instMod, IRegistryQuerier registry, GameVersionCri /// CKAN registry object for current game instance /// Current game version /// If true, mark this module as incompatible - public GUIMod(CkanModule mod, IRegistryQuerier registry, GameVersionCriteria current_game_version, bool? incompatible = null) - : this(mod.identifier, registry, current_game_version, incompatible) + public GUIMod(CkanModule mod, IRegistryQuerier registry, GameVersionCriteria current_game_version, bool? incompatible = null, bool hideEpochs = false, bool hideV = false) + : this(mod.identifier, registry, current_game_version, incompatible, hideEpochs, hideV) { Mod = mod; IsCKAN = mod is CkanModule; @@ -200,7 +197,7 @@ public GUIMod(CkanModule mod, IRegistryQuerier registry, GameVersionCriteria cur /// CKAN registry object for current game instance /// Current game version /// If true, mark this module as incompatible - public GUIMod(string identifier, IRegistryQuerier registry, GameVersionCriteria current_game_version, bool? incompatible = null) + public GUIMod(string identifier, IRegistryQuerier registry, GameVersionCriteria current_game_version, bool? incompatible = null, bool hideEpochs = false, bool hideV = false) { Identifier = identifier; IsAutodetected = registry.IsAutodetected(identifier); @@ -246,11 +243,11 @@ public GUIMod(string identifier, IRegistryQuerier registry, GameVersionCriteria if (latest_version != null) { - LatestVersion = latest_version.ToString(); + LatestVersion = latest_version.ToString(hideEpochs, hideV); } else if (latest_available_for_any_ksp != null) { - LatestVersion = latest_available_for_any_ksp.version.ToString(); + LatestVersion = latest_available_for_any_ksp.version.ToString(hideEpochs, hideV); } else { diff --git a/GUI/Model/ModList.cs b/GUI/Model/ModList.cs index d95618bd7b..3c2c18f97b 100644 --- a/GUI/Model/ModList.cs +++ b/GUI/Model/ModList.cs @@ -125,11 +125,9 @@ public static SavedSearch FilterToSavedSearch(GUIModFilter filter, ModuleTag tag /// /// /// - /// A module installer for the current game instance /// The version of the current game instance public Tuple, Dictionary> ComputeFullChangeSetFromUserChangeSet( - IRegistryQuerier registry, HashSet changeSet, ModuleInstaller installer, - GameVersionCriteria version) + IRegistryQuerier registry, HashSet changeSet, GameVersionCriteria version) { var modules_to_install = new List(); var modules_to_remove = new HashSet(); @@ -292,22 +290,19 @@ public int CountModsByFilter(GUIModFilter filter) /// /// A list of modules that may require updating /// Changes the user has made - /// If true, remove epochs from the displayed versions - /// If true, strip 'v' prefix from versions /// The mod list public IEnumerable ConstructModList( - IEnumerable modules, string instanceName, IEnumerable mc = null, - bool hideEpochs = false, bool hideV = false) + IEnumerable modules, string instanceName, IEnumerable mc = null) { List changes = mc?.ToList(); full_list_of_mod_rows = modules.ToDictionary( gm => gm.Identifier, - gm => MakeRow(gm, changes, instanceName, hideEpochs, hideV) + gm => MakeRow(gm, changes, instanceName) ); return full_list_of_mod_rows.Values; } - private DataGridViewRow MakeRow(GUIMod mod, List changes, string instanceName, bool hideEpochs = false, bool hideV = false) + private DataGridViewRow MakeRow(GUIMod mod, List changes, string instanceName) { DataGridViewRow item = new DataGridViewRow() {Tag = mod}; @@ -378,23 +373,12 @@ private DataGridViewRow MakeRow(GUIMod mod, List changes, string inst var installVersion = new DataGridViewTextBoxCell() { - Value = hideEpochs - ? (hideV - ? ModuleInstaller.StripEpoch(ModuleInstaller.StripV(mod.InstalledVersion ?? "")) - : ModuleInstaller.StripEpoch(mod.InstalledVersion ?? "")) - : (hideV - ? ModuleInstaller.StripV(mod.InstalledVersion ?? "") - : mod.InstalledVersion ?? "") + Value = mod.InstalledVersion }; var latestVersion = new DataGridViewTextBoxCell() { - Value = - hideEpochs ? - (hideV ? ModuleInstaller.StripEpoch(ModuleInstaller.StripV(mod.LatestVersion)) - : ModuleInstaller.StripEpoch(mod.LatestVersion)) - : (hideV ? ModuleInstaller.StripV(mod.LatestVersion) - : mod.LatestVersion) + Value = mod.LatestVersion }; var downloadCount = new DataGridViewTextBoxCell { Value = $"{mod.DownloadCount:N0}" };