diff --git a/GUI/CKAN-GUI.csproj b/GUI/CKAN-GUI.csproj
index d98a8332e1..1d8c7cf4c6 100644
--- a/GUI/CKAN-GUI.csproj
+++ b/GUI/CKAN-GUI.csproj
@@ -224,6 +224,18 @@
ModInfo.cs
+
+ UserControl
+
+
+ EditModSearch.cs
+
+
+ UserControl
+
+
+ ManageMods.cs
+
@@ -235,6 +247,8 @@
+
+
@@ -265,9 +279,6 @@
Form
-
- Form
-
Form
@@ -472,6 +483,24 @@
ModInfo.cs
+
+ ManageMods.cs
+
+
+ ..\..\Controls\ManageMods.cs
+
+
+ ..\..\Controls\ManageMods.cs
+
+
+ EditModSearch.cs
+
+
+ ..\..\Controls\EditModSearch.cs
+
+
+ ..\..\Controls\EditModSearch.cs
+
..\..\Controls\ModInfo.cs
diff --git a/GUI/Controls/EditModSearch.Designer.cs b/GUI/Controls/EditModSearch.Designer.cs
new file mode 100644
index 0000000000..60658a5cd5
--- /dev/null
+++ b/GUI/Controls/EditModSearch.Designer.cs
@@ -0,0 +1,342 @@
+namespace CKAN
+{
+ partial class EditModSearch
+ {
+ ///
+ /// 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(EditModSearch));
+ this.ToolTip = new System.Windows.Forms.ToolTip();
+ this.FilterByNameLabel = new System.Windows.Forms.Label();
+ this.FilterByNameTextBox = new CKAN.HintTextBox();
+ this.FilterByAuthorLabel = new System.Windows.Forms.Label();
+ this.FilterByAuthorTextBox = new CKAN.HintTextBox();
+ this.FilterByDescriptionLabel = new System.Windows.Forms.Label();
+ this.FilterByDescriptionTextBox = new CKAN.HintTextBox();
+ this.FilterByLanguageLabel = new System.Windows.Forms.Label();
+ this.FilterByLanguageTextBox = new CKAN.HintTextBox();
+ this.FilterByDependsLabel = new System.Windows.Forms.Label();
+ this.FilterByDependsTextBox = new CKAN.HintTextBox();
+ this.FilterByRecommendsLabel = new System.Windows.Forms.Label();
+ this.FilterByRecommendsTextBox = new CKAN.HintTextBox();
+ this.FilterBySuggestsLabel = new System.Windows.Forms.Label();
+ this.FilterBySuggestsTextBox = new CKAN.HintTextBox();
+ this.FilterByConflictsLabel = new System.Windows.Forms.Label();
+ this.FilterByConflictsTextBox = new CKAN.HintTextBox();
+ this.FilterCombinedLabel = new System.Windows.Forms.Label();
+ this.FilterCombinedTextBox = new CKAN.HintTextBox();
+ this.ExpandButton = new System.Windows.Forms.CheckBox();
+ this.SuspendLayout();
+ //
+ // ToolTip
+ //
+ this.ToolTip.AutoPopDelay = 10000;
+ this.ToolTip.InitialDelay = 250;
+ this.ToolTip.ReshowDelay = 250;
+ this.ToolTip.ShowAlways = true;
+ //
+ // FilterByNameLabel
+ //
+ this.FilterByNameLabel.AutoSize = true;
+ this.FilterByNameLabel.BackColor = System.Drawing.Color.Transparent;
+ this.FilterByNameLabel.Location = new System.Drawing.Point(6, 9);
+ this.FilterByNameLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.FilterByNameLabel.Name = "FilterByNameLabel";
+ this.FilterByNameLabel.Size = new System.Drawing.Size(147, 20);
+ this.FilterByNameLabel.TabIndex = 0;
+ this.FilterByNameLabel.Visible = false;
+ resources.ApplyResources(this.FilterByNameLabel, "FilterByNameLabel");
+ //
+ // FilterByNameTextBox
+ //
+ this.FilterByNameTextBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+ this.FilterByNameTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
+ this.FilterByNameTextBox.Name = "FilterByNameTextBox";
+ this.FilterByNameTextBox.Size = new System.Drawing.Size(170, 26);
+ this.FilterByNameTextBox.TabIndex = 1;
+ this.FilterByNameTextBox.TextChanged += new System.EventHandler(this.FilterTextBox_TextChanged);
+ this.FilterByNameTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.FilterTextBox_KeyDown);
+ this.FilterByNameTextBox.Visible = false;
+ resources.ApplyResources(this.FilterByNameTextBox, "FilterByNameTextBox");
+ //
+ // FilterByAuthorLabel
+ //
+ this.FilterByAuthorLabel.AutoSize = true;
+ this.FilterByAuthorLabel.BackColor = System.Drawing.Color.Transparent;
+ this.FilterByAuthorLabel.Location = new System.Drawing.Point(372, 9);
+ this.FilterByAuthorLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.FilterByAuthorLabel.Name = "FilterByAuthorLabel";
+ this.FilterByAuthorLabel.Size = new System.Drawing.Size(162, 20);
+ this.FilterByAuthorLabel.TabIndex = 2;
+ this.FilterByAuthorLabel.Visible = false;
+ resources.ApplyResources(this.FilterByAuthorLabel, "FilterByAuthorLabel");
+ //
+ // FilterByAuthorTextBox
+ //
+ this.FilterByAuthorTextBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+ this.FilterByAuthorTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
+ this.FilterByAuthorTextBox.Name = "FilterByAuthorTextBox";
+ this.FilterByAuthorTextBox.Size = new System.Drawing.Size(170, 26);
+ this.FilterByAuthorTextBox.TabIndex = 3;
+ this.FilterByAuthorTextBox.Visible = false;
+ this.FilterByAuthorTextBox.TextChanged += new System.EventHandler(this.FilterTextBox_TextChanged);
+ this.FilterByAuthorTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.FilterTextBox_KeyDown);
+ resources.ApplyResources(this.FilterByAuthorTextBox, "FilterByAuthorTextBox");
+ //
+ // FilterByDescriptionLabel
+ //
+ this.FilterByDescriptionLabel.AutoSize = true;
+ this.FilterByDescriptionLabel.BackColor = System.Drawing.Color.Transparent;
+ this.FilterByDescriptionLabel.Location = new System.Drawing.Point(754, 9);
+ this.FilterByDescriptionLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.FilterByDescriptionLabel.Name = "FilterByDescriptionLabel";
+ this.FilterByDescriptionLabel.Size = new System.Drawing.Size(149, 20);
+ this.FilterByDescriptionLabel.TabIndex = 4;
+ this.FilterByDescriptionLabel.Visible = false;
+ resources.ApplyResources(this.FilterByDescriptionLabel, "FilterByDescriptionLabel");
+ //
+ // FilterByDescriptionTextBox
+ //
+ this.FilterByDescriptionTextBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+ this.FilterByDescriptionTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
+ this.FilterByDescriptionTextBox.Name = "FilterByDescriptionTextBox";
+ this.FilterByDescriptionTextBox.Size = new System.Drawing.Size(170, 26);
+ this.FilterByDescriptionTextBox.TabIndex = 5;
+ this.FilterByDescriptionTextBox.Visible = false;
+ this.FilterByDescriptionTextBox.TextChanged += new System.EventHandler(this.FilterTextBox_TextChanged);
+ this.FilterByDescriptionTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.FilterTextBox_KeyDown);
+ resources.ApplyResources(this.FilterByDescriptionTextBox, "FilterByDescriptionTextBox");
+ //
+ // FilterByLanguageLabel
+ //
+ this.FilterByLanguageLabel.AutoSize = true;
+ this.FilterByLanguageLabel.BackColor = System.Drawing.Color.Transparent;
+ this.FilterByLanguageLabel.Location = new System.Drawing.Point(754, 9);
+ this.FilterByLanguageLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.FilterByLanguageLabel.Name = "FilterByLanguageLabel";
+ this.FilterByLanguageLabel.Size = new System.Drawing.Size(149, 20);
+ this.FilterByLanguageLabel.TabIndex = 6;
+ this.FilterByLanguageLabel.Visible = false;
+ resources.ApplyResources(this.FilterByLanguageLabel, "FilterByLanguageLabel");
+ //
+ // FilterByLanguageTextBox
+ //
+ this.FilterByLanguageTextBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+ this.FilterByLanguageTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
+ this.FilterByLanguageTextBox.Name = "FilterByLanguageTextBox";
+ this.FilterByLanguageTextBox.Size = new System.Drawing.Size(170, 26);
+ this.FilterByLanguageTextBox.TabIndex = 7;
+ this.FilterByLanguageTextBox.Visible = false;
+ this.FilterByLanguageTextBox.TextChanged += new System.EventHandler(this.FilterTextBox_TextChanged);
+ this.FilterByLanguageTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.FilterTextBox_KeyDown);
+ resources.ApplyResources(this.FilterByLanguageTextBox, "FilterByLanguageTextBox");
+ //
+ // FilterByDependsLabel
+ //
+ this.FilterByDependsLabel.AutoSize = true;
+ this.FilterByDependsLabel.BackColor = System.Drawing.Color.Transparent;
+ this.FilterByDependsLabel.Location = new System.Drawing.Point(754, 9);
+ this.FilterByDependsLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.FilterByDependsLabel.Name = "FilterByDependsLabel";
+ this.FilterByDependsLabel.Size = new System.Drawing.Size(149, 20);
+ this.FilterByDependsLabel.TabIndex = 8;
+ this.FilterByDependsLabel.Visible = false;
+ resources.ApplyResources(this.FilterByDependsLabel, "FilterByDependsLabel");
+ //
+ // FilterByDependsTextBox
+ //
+ this.FilterByDependsTextBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+ this.FilterByDependsTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
+ this.FilterByDependsTextBox.Name = "FilterByDependsTextBox";
+ this.FilterByDependsTextBox.Size = new System.Drawing.Size(170, 26);
+ this.FilterByDependsTextBox.TabIndex = 9;
+ this.FilterByDependsTextBox.Visible = false;
+ this.FilterByDependsTextBox.TextChanged += new System.EventHandler(this.FilterTextBox_TextChanged);
+ this.FilterByDependsTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.FilterTextBox_KeyDown);
+ resources.ApplyResources(this.FilterByDependsTextBox, "FilterByDependsTextBox");
+ //
+ // FilterByRecommendsLabel
+ //
+ this.FilterByRecommendsLabel.AutoSize = true;
+ this.FilterByRecommendsLabel.BackColor = System.Drawing.Color.Transparent;
+ this.FilterByRecommendsLabel.Location = new System.Drawing.Point(754, 9);
+ this.FilterByRecommendsLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.FilterByRecommendsLabel.Name = "FilterByRecommendsLabel";
+ this.FilterByRecommendsLabel.Size = new System.Drawing.Size(149, 20);
+ this.FilterByRecommendsLabel.TabIndex = 10;
+ this.FilterByRecommendsLabel.Visible = false;
+ resources.ApplyResources(this.FilterByRecommendsLabel, "FilterByRecommendsLabel");
+ //
+ // FilterByRecommendsTextBox
+ //
+ this.FilterByRecommendsTextBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+ this.FilterByRecommendsTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
+ this.FilterByRecommendsTextBox.Name = "FilterByRecommendsTextBox";
+ this.FilterByRecommendsTextBox.Size = new System.Drawing.Size(170, 26);
+ this.FilterByRecommendsTextBox.TabIndex = 11;
+ this.FilterByRecommendsTextBox.Visible = false;
+ this.FilterByRecommendsTextBox.TextChanged += new System.EventHandler(this.FilterTextBox_TextChanged);
+ this.FilterByRecommendsTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.FilterTextBox_KeyDown);
+ resources.ApplyResources(this.FilterByRecommendsTextBox, "FilterByRecommendsTextBox");
+ //
+ // FilterBySuggestsLabel
+ //
+ this.FilterBySuggestsLabel.AutoSize = true;
+ this.FilterBySuggestsLabel.BackColor = System.Drawing.Color.Transparent;
+ this.FilterBySuggestsLabel.Location = new System.Drawing.Point(754, 9);
+ this.FilterBySuggestsLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.FilterBySuggestsLabel.Name = "FilterBySuggestsLabel";
+ this.FilterBySuggestsLabel.Size = new System.Drawing.Size(149, 20);
+ this.FilterBySuggestsLabel.TabIndex = 12;
+ this.FilterBySuggestsLabel.Visible = false;
+ resources.ApplyResources(this.FilterBySuggestsLabel, "FilterBySuggestsLabel");
+ //
+ // FilterBySuggestsTextBox
+ //
+ this.FilterBySuggestsTextBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+ this.FilterBySuggestsTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
+ this.FilterBySuggestsTextBox.Name = "FilterBySuggestsTextBox";
+ this.FilterBySuggestsTextBox.Size = new System.Drawing.Size(170, 26);
+ this.FilterBySuggestsTextBox.TabIndex = 13;
+ this.FilterBySuggestsTextBox.Visible = false;
+ this.FilterBySuggestsTextBox.TextChanged += new System.EventHandler(this.FilterTextBox_TextChanged);
+ this.FilterBySuggestsTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.FilterTextBox_KeyDown);
+ resources.ApplyResources(this.FilterBySuggestsTextBox, "FilterBySuggestsTextBox");
+ //
+ // FilterByConflictsLabel
+ //
+ this.FilterByConflictsLabel.AutoSize = true;
+ this.FilterByConflictsLabel.BackColor = System.Drawing.Color.Transparent;
+ this.FilterByConflictsLabel.Location = new System.Drawing.Point(754, 9);
+ this.FilterByConflictsLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.FilterByConflictsLabel.Name = "FilterByConflictsLabel";
+ this.FilterByConflictsLabel.Size = new System.Drawing.Size(149, 20);
+ this.FilterByConflictsLabel.TabIndex = 14;
+ this.FilterByConflictsLabel.Visible = false;
+ resources.ApplyResources(this.FilterByConflictsLabel, "FilterByConflictsLabel");
+ //
+ // FilterByConflictsTextBox
+ //
+ this.FilterByConflictsTextBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+ this.FilterByConflictsTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
+ this.FilterByConflictsTextBox.Name = "FilterByConflictsTextBox";
+ this.FilterByConflictsTextBox.Size = new System.Drawing.Size(170, 26);
+ this.FilterByConflictsTextBox.TabIndex = 15;
+ this.FilterByConflictsTextBox.Visible = false;
+ this.FilterByConflictsTextBox.TextChanged += new System.EventHandler(this.FilterTextBox_TextChanged);
+ this.FilterByConflictsTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.FilterTextBox_KeyDown);
+ resources.ApplyResources(this.FilterByConflictsTextBox, "FilterByConflictsTextBox");
+ //
+ // FilterCombinedLabel
+ //
+ this.FilterCombinedLabel.AutoSize = true;
+ this.FilterCombinedLabel.BackColor = System.Drawing.Color.Transparent;
+ this.FilterCombinedLabel.Location = new System.Drawing.Point(6, 9);
+ this.FilterCombinedLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.FilterCombinedLabel.Name = "FilterCombinedLabel";
+ this.FilterCombinedLabel.Size = new System.Drawing.Size(147, 20);
+ this.FilterCombinedLabel.TabIndex = 16;
+ resources.ApplyResources(this.FilterCombinedLabel, "FilterCombinedLabel");
+ //
+ // FilterCombinedTextBox
+ //
+ this.FilterCombinedTextBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+ this.FilterCombinedTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
+ this.FilterCombinedTextBox.Name = "FilterCombinedTextBox";
+ this.FilterCombinedTextBox.Size = new System.Drawing.Size(340, 26);
+ this.FilterCombinedTextBox.TabIndex = 17;
+ this.FilterCombinedTextBox.TextChanged += new System.EventHandler(this.FilterCombinedTextBox_TextChanged);
+ this.FilterCombinedTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.FilterTextBox_KeyDown);
+ resources.ApplyResources(this.FilterCombinedTextBox, "FilterCombinedTextBox");
+ //
+ // ExpandButton
+ //
+ this.ExpandButton.Appearance = System.Windows.Forms.Appearance.Button;
+ this.ExpandButton.Location = new System.Drawing.Point(330, 5);
+ this.ExpandButton.Name = "ExpandButton";
+ this.ExpandButton.Size = new System.Drawing.Size(20, 26);
+ this.ExpandButton.TabIndex = 18;
+ this.ExpandButton.Text = "▴";
+ this.ExpandButton.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+ this.ExpandButton.UseVisualStyleBackColor = true;
+ this.ExpandButton.CheckedChanged += new System.EventHandler(this.ExpandButton_CheckedChanged);
+ resources.ApplyResources(this.ExpandButton, "ExpandButton");
+ //
+ // EditModSearch
+ //
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
+ this.Controls.Add(this.FilterCombinedLabel);
+ this.Controls.Add(this.FilterCombinedTextBox);
+ this.Controls.Add(this.ExpandButton);
+ this.Controls.Add(this.FilterByAuthorTextBox);
+ this.Controls.Add(this.FilterByAuthorLabel);
+ this.Controls.Add(this.FilterByNameLabel);
+ this.Controls.Add(this.FilterByNameTextBox);
+ this.Controls.Add(this.FilterByDescriptionLabel);
+ this.Controls.Add(this.FilterByDescriptionTextBox);
+ this.Controls.Add(this.FilterByLanguageLabel);
+ this.Controls.Add(this.FilterByLanguageTextBox);
+ this.Controls.Add(this.FilterByDependsLabel);
+ this.Controls.Add(this.FilterByDependsTextBox);
+ this.Controls.Add(this.FilterByRecommendsLabel);
+ this.Controls.Add(this.FilterByRecommendsTextBox);
+ this.Controls.Add(this.FilterBySuggestsLabel);
+ this.Controls.Add(this.FilterBySuggestsTextBox);
+ this.Controls.Add(this.FilterByConflictsLabel);
+ this.Controls.Add(this.FilterByConflictsTextBox);
+ this.Name = "EditModSearch";
+ this.Size = new System.Drawing.Size(500, 26);
+ resources.ApplyResources(this, "$this");
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.ToolTip ToolTip;
+ private System.Windows.Forms.Label FilterByNameLabel;
+ private CKAN.HintTextBox FilterByNameTextBox;
+ private System.Windows.Forms.Label FilterByAuthorLabel;
+ private CKAN.HintTextBox FilterByAuthorTextBox;
+ private System.Windows.Forms.Label FilterByDescriptionLabel;
+ private CKAN.HintTextBox FilterByDescriptionTextBox;
+ private System.Windows.Forms.Label FilterByLanguageLabel;
+ private CKAN.HintTextBox FilterByLanguageTextBox;
+ private System.Windows.Forms.Label FilterByDependsLabel;
+ private CKAN.HintTextBox FilterByDependsTextBox;
+ private System.Windows.Forms.Label FilterByRecommendsLabel;
+ private CKAN.HintTextBox FilterByRecommendsTextBox;
+ private System.Windows.Forms.Label FilterBySuggestsLabel;
+ private CKAN.HintTextBox FilterBySuggestsTextBox;
+ private System.Windows.Forms.Label FilterByConflictsLabel;
+ private CKAN.HintTextBox FilterByConflictsTextBox;
+ private System.Windows.Forms.Label FilterCombinedLabel;
+ private CKAN.HintTextBox FilterCombinedTextBox;
+ private System.Windows.Forms.CheckBox ExpandButton;
+ }
+}
diff --git a/GUI/Controls/EditModSearch.cs b/GUI/Controls/EditModSearch.cs
new file mode 100644
index 0000000000..6ddfb3fb17
--- /dev/null
+++ b/GUI/Controls/EditModSearch.cs
@@ -0,0 +1,258 @@
+using System;
+using System.Linq;
+using System.Drawing;
+using System.Windows.Forms;
+using Timer = System.Windows.Forms.Timer;
+using log4net;
+
+namespace CKAN
+{
+ ///
+ /// A control for displaying and editing a search of mods.
+ /// Contains several separate fields for searching different properties,
+ /// plus a combined field that represents them all in a special syntax.
+ ///
+ public partial class EditModSearch : UserControl
+ {
+ ///
+ /// Initialize a mod search editing control
+ ///
+ public EditModSearch()
+ {
+ InitializeComponent();
+
+ this.ToolTip.SetToolTip(ExpandButton, Properties.Resources.EditModSearchTooltipExpandButton);
+
+ labels = new Label[]
+ {
+ FilterByNameLabel,
+ FilterByAuthorLabel,
+ FilterByDescriptionLabel,
+ FilterByLanguageLabel,
+ FilterByDependsLabel,
+ FilterByRecommendsLabel,
+ FilterBySuggestsLabel,
+ FilterByConflictsLabel,
+ FilterCombinedLabel,
+ };
+ textboxes = new TextBox[]
+ {
+ FilterByNameTextBox,
+ FilterByAuthorTextBox,
+ FilterByDescriptionTextBox,
+ FilterByLanguageTextBox,
+ FilterByDependsTextBox,
+ FilterByRecommendsTextBox,
+ FilterBySuggestsTextBox,
+ FilterByConflictsTextBox,
+ FilterCombinedTextBox,
+ };
+ rowCount = labels.Length;
+ maxLabelWidth = labels.Select(l => l.Width).Max();
+ DoLayout(ExpandButton.Checked);
+ }
+
+ ///
+ /// Clear the input fields
+ ///
+ public void Clear()
+ {
+ FilterCombinedTextBox.Text = "";
+ }
+
+ ///
+ /// Toggle whether the detailed controls are shown or hidden.
+ ///
+ public void ExpandCollapse()
+ {
+ ExpandButton.Checked = !ExpandButton.Checked;
+ }
+
+ ///
+ /// Event fired when a search needs to be executed.
+ ///
+ public event Action ApplySearch;
+
+ ///
+ /// Event fired when user wants to switch focus away from this control.
+ ///
+ public event Action SurrenderFocus;
+
+ private static readonly ILog log = LogManager.GetLogger(typeof(EditModSearch));
+ private Label[] labels;
+ private TextBox[] textboxes;
+ private readonly int rowCount;
+ private const int rowHeight = 26;
+ private const int padding = 4;
+ private readonly int maxLabelWidth;
+ private Timer filterTimer;
+ private bool suppressSearch = false;
+ private ModSearch currentSearch = null;
+
+ private void ExpandButton_CheckedChanged(object sender, EventArgs e)
+ {
+ ExpandButton.Text = ExpandButton.Checked ? "▾" : "▴";
+ DoLayout(ExpandButton.Checked);
+ }
+
+ private void DoLayout(bool expanded)
+ {
+ if (expanded)
+ {
+ for (int row = 0; row < rowCount; ++row)
+ {
+ labels[row].Visible = true;
+ labels[row].Left = padding;
+ labels[row].Top = padding + row * (rowHeight + padding);
+ textboxes[row].Visible = true;
+ textboxes[row].Left = maxLabelWidth + 2 * padding;
+ textboxes[row].Top = padding + row * (rowHeight + padding);
+ }
+ Height = rowCount * (rowHeight + padding);
+ }
+ else
+ {
+ Height = rowHeight + padding;
+ for (int row = 0; row < labels.Length; ++row)
+ {
+ if (row < labels.Length - 1)
+ {
+ labels[row].Visible = false;
+ textboxes[row].Visible = false;
+ }
+ else
+ {
+ labels[row].Top = padding;
+ labels[row].Left = padding;
+ textboxes[row].Top = padding;
+ textboxes[row].Left = maxLabelWidth + 2 * padding;
+ }
+ }
+ }
+ var botTB = textboxes[rowCount - 1];
+ ExpandButton.Left = botTB.Left + botTB.Width;
+ ExpandButton.Top = botTB.Top;
+ ExpandButton.Height = botTB.Height;
+ ExpandButton.Width = botTB.Height;
+ }
+
+ private void FilterCombinedTextBox_TextChanged(object sender, EventArgs e)
+ {
+ if (suppressSearch)
+ return;
+
+ try
+ {
+ currentSearch = ModSearch.Parse(FilterCombinedTextBox.Text);
+ suppressSearch = true;
+ FilterByNameTextBox.Text = currentSearch?.Name ?? "";
+ FilterByAuthorTextBox.Text = currentSearch?.Author ?? "";
+ FilterByDescriptionTextBox.Text = currentSearch?.Description ?? "";
+ FilterByLanguageTextBox.Text = currentSearch?.Localization ?? "";
+ FilterByDependsTextBox.Text = currentSearch?.DependsOn ?? "";
+ FilterByRecommendsTextBox.Text = currentSearch?.Recommends ?? "";
+ FilterBySuggestsTextBox.Text = currentSearch?.Suggests ?? "";
+ FilterByConflictsTextBox.Text = currentSearch?.ConflictsWith ?? "";
+ suppressSearch = false;
+ TriggerSearchOrTimer();
+ }
+ catch (Kraken k)
+ {
+ Main.Instance.AddStatusMessage(k.Message);
+ }
+ }
+
+ private void FilterTextBox_TextChanged(object sender, EventArgs e)
+ {
+ if (suppressSearch)
+ return;
+
+ currentSearch = new ModSearch(
+ FilterByNameTextBox.Text,
+ FilterByAuthorTextBox.Text,
+ FilterByDescriptionTextBox.Text,
+ FilterByLanguageTextBox.Text,
+ FilterByDependsTextBox.Text,
+ FilterByRecommendsTextBox.Text,
+ FilterBySuggestsTextBox.Text,
+ FilterByConflictsTextBox.Text
+ );
+ suppressSearch = true;
+ FilterCombinedTextBox.Text = currentSearch?.Combined ?? "";
+ suppressSearch = false;
+ TriggerSearchOrTimer();
+ }
+
+ private void FilterTextBox_KeyDown(object sender, KeyEventArgs e)
+ {
+ // Switch focus from filters to mod list on enter, down, or pgdn
+ switch (e.KeyCode)
+ {
+ case Keys.Enter:
+ case Keys.Up:
+ case Keys.Down:
+ case Keys.PageUp:
+ case Keys.PageDown:
+ if (SurrenderFocus != null)
+ {
+ SurrenderFocus();
+ }
+ e.Handled = true;
+ break;
+ }
+ }
+
+ private void TriggerSearchOrTimer()
+ {
+ if (Platform.IsMac)
+ {
+ // Delay updating to improve typing performance on OS X.
+ RunFilterUpdateTimer();
+ }
+ else
+ {
+ TriggerSearch();
+ }
+ }
+
+ ///
+ /// Start or restart a timer to update the filter after an interval since the last keypress.
+ /// On Mac OS X, this prevents the search field from locking up due to DataGridViews being
+ /// slow and key strokes being interpreted incorrectly when slowed down:
+ /// http://mono.1490590.n4.nabble.com/Incorrect-missing-and-duplicate-keypress-events-td4658863.html
+ ///
+ private void RunFilterUpdateTimer()
+ {
+ if (filterTimer == null)
+ {
+ filterTimer = new Timer();
+ filterTimer.Tick += OnFilterUpdateTimer;
+ filterTimer.Interval = 700;
+ filterTimer.Start();
+ }
+ else
+ {
+ filterTimer.Stop();
+ filterTimer.Start();
+ }
+ }
+
+ ///
+ /// Updates the filter after an interval of time has passed since the last keypress.
+ ///
+ private void OnFilterUpdateTimer(object source, EventArgs e)
+ {
+ TriggerSearch();
+ filterTimer.Stop();
+ }
+
+ private void TriggerSearch()
+ {
+ if (ApplySearch != null)
+ {
+ ApplySearch(currentSearch);
+ }
+ }
+
+ }
+}
diff --git a/GUI/Controls/EditModSearch.resx b/GUI/Controls/EditModSearch.resx
new file mode 100644
index 0000000000..5ed37254f8
--- /dev/null
+++ b/GUI/Controls/EditModSearch.resx
@@ -0,0 +1,199 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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
+
+
+ 236, 17
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ 351, 17
+
+
+ True
+
+
+ (Default)
+
+ Launch KSP
+ Refresh
+ Add available updates
+ Apply changes
+ Filter (Compatible)
+ Compatible
+ Installed
+ Installed (update available)
+ Replaceable
+ Cached
+ Uncached
+ Newly compatible
+ Not installed
+ Incompatible
+ All
+ Tags
+ Labels
+ Previous selected mod...
+ Next selected mod...
+ Inst
+ Auto-installed
+ Update
+ Replace
+ Name
+ Author
+ Installed version
+ Latest version
+ Max KSP version
+ Download
+ Install date
+ Downloads
+ Description
+ Reinstall
+ Download Contents
+ Purge Contents
+ Search:
+ Name:
+ Author:
+ Description:
+ Language:
+ Depends on:
+ Recommends:
+ Suggests:
+ Conflicts with:
+ Labels
+ Edit labels...
+
diff --git a/GUI/Controls/ManageMods.Designer.cs b/GUI/Controls/ManageMods.Designer.cs
new file mode 100644
index 0000000000..60d3a5666b
--- /dev/null
+++ b/GUI/Controls/ManageMods.Designer.cs
@@ -0,0 +1,569 @@
+namespace CKAN
+{
+ partial class ManageMods
+ {
+ ///
+ /// 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(ManageMods));
+ this.menuStrip2 = new System.Windows.Forms.MenuStrip();
+ this.launchKSPToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.RefreshToolButton = new System.Windows.Forms.ToolStripMenuItem();
+ this.UpdateAllToolButton = new System.Windows.Forms.ToolStripMenuItem();
+ this.ApplyToolButton = new System.Windows.Forms.ToolStripMenuItem();
+ this.FilterToolButton = new System.Windows.Forms.ToolStripMenuItem();
+ this.FilterCompatibleButton = new System.Windows.Forms.ToolStripMenuItem();
+ this.FilterInstalledButton = new System.Windows.Forms.ToolStripMenuItem();
+ this.FilterInstalledUpdateButton = new System.Windows.Forms.ToolStripMenuItem();
+ this.FilterReplaceableButton = new System.Windows.Forms.ToolStripMenuItem();
+ this.FilterCachedButton = new System.Windows.Forms.ToolStripMenuItem();
+ this.FilterUncachedButton = new System.Windows.Forms.ToolStripMenuItem();
+ this.FilterNewButton = new System.Windows.Forms.ToolStripMenuItem();
+ this.FilterNotInstalledButton = new System.Windows.Forms.ToolStripMenuItem();
+ this.FilterIncompatibleButton = new System.Windows.Forms.ToolStripMenuItem();
+ this.FilterAllButton = new System.Windows.Forms.ToolStripMenuItem();
+ this.FilterLabelsToolButton = new System.Windows.Forms.ToolStripMenuItem();
+ this.FilterTagsToolButton = new System.Windows.Forms.ToolStripMenuItem();
+ this.NavBackwardToolButton = new System.Windows.Forms.ToolStripMenuItem();
+ this.NavForwardToolButton = new System.Windows.Forms.ToolStripMenuItem();
+ this.EditModSearch = new CKAN.EditModSearch();
+ this.ModGrid = new System.Windows.Forms.DataGridView();
+ this.InstallAllCheckbox = new System.Windows.Forms.CheckBox();
+ this.Installed = new System.Windows.Forms.DataGridViewCheckBoxColumn();
+ this.AutoInstalled = new System.Windows.Forms.DataGridViewCheckBoxColumn();
+ this.UpdateCol = new System.Windows.Forms.DataGridViewCheckBoxColumn();
+ this.ReplaceCol = new System.Windows.Forms.DataGridViewCheckBoxColumn();
+ this.ModName = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.Author = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.InstalledVersion = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.LatestVersion = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.KSPCompatibility = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.SizeCol = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.InstallDate = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.DownloadCount = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.Description = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.ModListContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this.LabelsContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this.ModListHeaderContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this.modListToolStripSeparator = new System.Windows.Forms.ToolStripSeparator();
+ this.tagFilterToolStripSeparator = new System.Windows.Forms.ToolStripSeparator();
+ this.untaggedFilterToolStripSeparator = new System.Windows.Forms.ToolStripSeparator();
+ this.labelsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.labelToolStripSeparator = new System.Windows.Forms.ToolStripSeparator();
+ this.editLabelsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.reinstallToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.downloadContentsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.purgeContentsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.menuStrip2.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.ModGrid)).BeginInit();
+ this.ModListContextMenuStrip.SuspendLayout();
+ this.ModListHeaderContextMenuStrip.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // menuStrip2
+ //
+ this.menuStrip2.AutoSize = false;
+ this.menuStrip2.Dock = System.Windows.Forms.DockStyle.Top;
+ this.menuStrip2.ImageScalingSize = new System.Drawing.Size(24, 24);
+ this.menuStrip2.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.launchKSPToolStripMenuItem,
+ this.RefreshToolButton,
+ this.UpdateAllToolButton,
+ this.ApplyToolButton,
+ this.FilterToolButton,
+ this.NavBackwardToolButton,
+ this.NavForwardToolButton});
+ this.menuStrip2.Location = new System.Drawing.Point(0, 0);
+ this.menuStrip2.Name = "menuStrip2";
+ this.menuStrip2.Size = new System.Drawing.Size(5876, 48);
+ this.menuStrip2.TabIndex = 4;
+ this.menuStrip2.Text = "menuStrip2";
+ //
+ // launchKSPToolStripMenuItem
+ //
+ this.launchKSPToolStripMenuItem.Image = global::CKAN.Properties.Resources.ksp;
+ this.launchKSPToolStripMenuItem.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
+ this.launchKSPToolStripMenuItem.Name = "launchKSPToolStripMenuItem";
+ this.launchKSPToolStripMenuItem.Size = new System.Drawing.Size(146, 56);
+ this.launchKSPToolStripMenuItem.Click += new System.EventHandler(this.launchKSPToolStripMenuItem_Click);
+ resources.ApplyResources(this.launchKSPToolStripMenuItem, "launchKSPToolStripMenuItem");
+ //
+ // RefreshToolButton
+ //
+ this.RefreshToolButton.Image = global::CKAN.Properties.Resources.refresh;
+ this.RefreshToolButton.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
+ this.RefreshToolButton.Name = "RefreshToolButton";
+ this.RefreshToolButton.Size = new System.Drawing.Size(114, 56);
+ this.RefreshToolButton.Click += new System.EventHandler(this.RefreshToolButton_Click);
+ resources.ApplyResources(this.RefreshToolButton, "RefreshToolButton");
+ //
+ // UpdateAllToolButton
+ //
+ this.UpdateAllToolButton.Image = global::CKAN.Properties.Resources.update;
+ this.UpdateAllToolButton.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
+ this.UpdateAllToolButton.Name = "UpdateAllToolButton";
+ this.UpdateAllToolButton.Size = new System.Drawing.Size(232, 56);
+ this.UpdateAllToolButton.Click += new System.EventHandler(this.MarkAllUpdatesToolButton_Click);
+ resources.ApplyResources(this.UpdateAllToolButton, "UpdateAllToolButton");
+ //
+ // ApplyToolButton
+ //
+ this.ApplyToolButton.Image = global::CKAN.Properties.Resources.apply;
+ this.ApplyToolButton.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
+ this.ApplyToolButton.Name = "ApplyToolButton";
+ this.ApplyToolButton.Size = new System.Drawing.Size(173, 56);
+ this.ApplyToolButton.Click += new System.EventHandler(this.ApplyToolButton_Click);
+ resources.ApplyResources(this.ApplyToolButton, "ApplyToolButton");
+ //
+ // FilterToolButton
+ //
+ this.FilterToolButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.FilterCompatibleButton,
+ this.FilterInstalledButton,
+ this.FilterInstalledUpdateButton,
+ this.FilterReplaceableButton,
+ this.FilterCachedButton,
+ this.FilterUncachedButton,
+ this.FilterNewButton,
+ this.FilterNotInstalledButton,
+ this.FilterIncompatibleButton,
+ this.FilterAllButton,
+ this.tagFilterToolStripSeparator,
+ this.FilterTagsToolButton,
+ this.FilterLabelsToolButton});
+ this.FilterToolButton.DropDown.Opening += new System.ComponentModel.CancelEventHandler(FilterToolButton_DropDown_Opening);
+ this.FilterToolButton.Image = global::CKAN.Properties.Resources.filter;
+ this.FilterToolButton.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
+ this.FilterToolButton.Name = "FilterToolButton";
+ this.FilterToolButton.Size = new System.Drawing.Size(201, 56);
+ resources.ApplyResources(this.FilterToolButton, "FilterToolButton");
+ //
+ // FilterCompatibleButton
+ //
+ this.FilterCompatibleButton.Name = "FilterCompatibleButton";
+ this.FilterCompatibleButton.Size = new System.Drawing.Size(307, 30);
+ this.FilterCompatibleButton.Click += new System.EventHandler(this.FilterCompatibleButton_Click);
+ resources.ApplyResources(this.FilterCompatibleButton, "FilterCompatibleButton");
+ //
+ // FilterInstalledButton
+ //
+ this.FilterInstalledButton.Name = "FilterInstalledButton";
+ this.FilterInstalledButton.Size = new System.Drawing.Size(307, 30);
+ this.FilterInstalledButton.Click += new System.EventHandler(this.FilterInstalledButton_Click);
+ resources.ApplyResources(this.FilterInstalledButton, "FilterInstalledButton");
+ //
+ // FilterInstalledUpdateButton
+ //
+ this.FilterInstalledUpdateButton.Name = "FilterInstalledUpdateButton";
+ this.FilterInstalledUpdateButton.Size = new System.Drawing.Size(307, 30);
+ this.FilterInstalledUpdateButton.Click += new System.EventHandler(this.FilterInstalledUpdateButton_Click);
+ resources.ApplyResources(this.FilterInstalledUpdateButton, "FilterInstalledUpdateButton");
+ //
+ // FilterReplaceableButton
+ //
+ this.FilterReplaceableButton.Name = "FilterReplaceableButton";
+ this.FilterReplaceableButton.Size = new System.Drawing.Size(307, 30);
+ this.FilterReplaceableButton.Click += new System.EventHandler(this.FilterReplaceableButton_Click);
+ resources.ApplyResources(this.FilterReplaceableButton, "FilterReplaceableButton");
+ //
+ // FilterCachedButton
+ //
+ this.FilterCachedButton.Name = "FilterCachedButton";
+ this.FilterCachedButton.Size = new System.Drawing.Size(307, 30);
+ this.FilterCachedButton.Click += new System.EventHandler(this.FilterCachedButton_Click);
+ resources.ApplyResources(this.FilterCachedButton, "FilterCachedButton");
+ //
+ // FilterUncachedButton
+ //
+ this.FilterUncachedButton.Name = "FilterUncachedButton";
+ this.FilterUncachedButton.Size = new System.Drawing.Size(307, 30);
+ this.FilterUncachedButton.Click += new System.EventHandler(this.FilterUncachedButton_Click);
+ resources.ApplyResources(this.FilterUncachedButton, "FilterUncachedButton");
+ //
+ // FilterNewButton
+ //
+ this.FilterNewButton.Name = "FilterNewButton";
+ this.FilterNewButton.Size = new System.Drawing.Size(307, 30);
+ this.FilterNewButton.Click += new System.EventHandler(this.FilterNewButton_Click);
+ resources.ApplyResources(this.FilterNewButton, "FilterNewButton");
+ //
+ // FilterNotInstalledButton
+ //
+ this.FilterNotInstalledButton.Name = "FilterNotInstalledButton";
+ this.FilterNotInstalledButton.Size = new System.Drawing.Size(307, 30);
+ this.FilterNotInstalledButton.Click += new System.EventHandler(this.FilterNotInstalledButton_Click);
+ resources.ApplyResources(this.FilterNotInstalledButton, "FilterNotInstalledButton");
+ //
+ // FilterIncompatibleButton
+ //
+ this.FilterIncompatibleButton.Name = "FilterIncompatibleButton";
+ this.FilterIncompatibleButton.Size = new System.Drawing.Size(307, 30);
+ this.FilterIncompatibleButton.Click += new System.EventHandler(this.FilterIncompatibleButton_Click);
+ resources.ApplyResources(this.FilterIncompatibleButton, "FilterIncompatibleButton");
+ //
+ // FilterAllButton
+ //
+ this.FilterAllButton.Name = "FilterAllButton";
+ this.FilterAllButton.Size = new System.Drawing.Size(307, 30);
+ this.FilterAllButton.Click += new System.EventHandler(this.FilterAllButton_Click);
+ resources.ApplyResources(this.FilterAllButton, "FilterAllButton");
+ //
+ // FilterTagsToolButton
+ //
+ this.FilterTagsToolButton.Name = "FilterTagsToolButton";
+ this.FilterTagsToolButton.Size = new System.Drawing.Size(179, 22);
+ resources.ApplyResources(this.FilterTagsToolButton, "FilterTagsToolButton");
+ this.FilterTagsToolButton.DropDown.Opening += new System.ComponentModel.CancelEventHandler(FilterTagsToolButton_DropDown_Opening);
+ //
+ // FilterLabelsToolButton
+ //
+ this.FilterLabelsToolButton.Name = "FilterLabelsToolButton";
+ this.FilterLabelsToolButton.Size = new System.Drawing.Size(179, 22);
+ resources.ApplyResources(this.FilterLabelsToolButton, "FilterLabelsToolButton");
+ this.FilterLabelsToolButton.DropDown.Opening += new System.ComponentModel.CancelEventHandler(FilterLabelsToolButton_DropDown_Opening);
+ //
+ // NavBackwardToolButton
+ //
+ this.NavBackwardToolButton.Image = global::CKAN.Properties.Resources.backward;
+ this.NavBackwardToolButton.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
+ this.NavBackwardToolButton.Name = "NavBackwardToolButton";
+ this.NavBackwardToolButton.Size = new System.Drawing.Size(44, 56);
+ this.NavBackwardToolButton.Click += new System.EventHandler(this.NavBackwardToolButton_Click);
+ resources.ApplyResources(this.NavBackwardToolButton, "NavBackwardToolButton");
+ //
+ // NavForwardToolButton
+ //
+ this.NavForwardToolButton.Image = global::CKAN.Properties.Resources.forward;
+ this.NavForwardToolButton.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
+ this.NavForwardToolButton.Name = "NavForwardToolButton";
+ this.NavForwardToolButton.Size = new System.Drawing.Size(44, 56);
+ this.NavForwardToolButton.Click += new System.EventHandler(this.NavForwardToolButton_Click);
+ resources.ApplyResources(this.NavForwardToolButton, "NavForwardToolButton");
+ //
+ // EditModSearch
+ //
+ this.EditModSearch.Dock = System.Windows.Forms.DockStyle.Bottom;
+ this.EditModSearch.ApplySearch += EditModSearch_ApplySearch;
+ this.EditModSearch.SurrenderFocus += EditModSearch_SurrenderFocus;
+ //
+ // ModGrid
+ //
+ this.ModGrid.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.ModGrid.AllowUserToAddRows = false;
+ this.ModGrid.AllowUserToDeleteRows = false;
+ this.ModGrid.AllowUserToResizeRows = false;
+ this.ModGrid.BackgroundColor = System.Drawing.SystemColors.Window;
+ this.ModGrid.EnableHeadersVisualStyles = false;
+ this.ModGrid.ColumnHeadersDefaultCellStyle.BackColor = System.Drawing.SystemColors.Control;
+ this.ModGrid.ColumnHeadersDefaultCellStyle.ForeColor = System.Drawing.SystemColors.ControlText;
+ this.ModGrid.DefaultCellStyle.ForeColor = System.Drawing.SystemColors.WindowText;
+ this.ModGrid.CellBorderStyle = System.Windows.Forms.DataGridViewCellBorderStyle.None;
+ this.ModGrid.ColumnHeadersBorderStyle = System.Windows.Forms.DataGridViewHeaderBorderStyle.None;
+ this.ModGrid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
+ this.ModGrid.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
+ this.Installed,
+ this.AutoInstalled,
+ this.UpdateCol,
+ this.ReplaceCol,
+ this.ModName,
+ this.Author,
+ this.InstalledVersion,
+ this.LatestVersion,
+ this.KSPCompatibility,
+ this.SizeCol,
+ this.InstallDate,
+ this.DownloadCount,
+ this.Description});
+ this.ModGrid.Location = new System.Drawing.Point(0, 111);
+ this.ModGrid.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
+ this.ModGrid.MultiSelect = false;
+ this.ModGrid.Name = "ModGrid";
+ this.ModGrid.RowHeadersVisible = false;
+ this.ModGrid.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
+ this.ModGrid.Size = new System.Drawing.Size(1536, 837);
+ this.ModGrid.StandardTab = true;
+ this.ModGrid.TabIndex = 12;
+ this.ModGrid.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.ModList_CellContentClick);
+ this.ModGrid.CellMouseDoubleClick += new System.Windows.Forms.DataGridViewCellMouseEventHandler(this.ModList_CellMouseDoubleClick);
+ this.ModGrid.ColumnHeaderMouseClick += new System.Windows.Forms.DataGridViewCellMouseEventHandler(this.ModList_HeaderMouseClick);
+ this.ModGrid.SelectionChanged += new System.EventHandler(this.ModList_SelectedIndexChanged);
+ this.ModGrid.KeyDown += new System.Windows.Forms.KeyEventHandler(this.ModList_KeyDown);
+ this.ModGrid.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.ModList_KeyPress);
+ this.ModGrid.MouseDown += new System.Windows.Forms.MouseEventHandler(this.ModList_MouseDown);
+ this.ModGrid.GotFocus += new System.EventHandler(this.ModList_GotFocus);
+ this.ModGrid.LostFocus += new System.EventHandler(this.ModList_LostFocus);
+ this.ModGrid.CurrentCellDirtyStateChanged += new System.EventHandler(this.ModList_CurrentCellDirtyStateChanged);
+ this.ModGrid.CellValueChanged += new System.Windows.Forms.DataGridViewCellEventHandler(this.ModList_CellValueChanged);
+ //
+ // Installed
+ //
+ this.Installed.Name = "Installed";
+ this.Installed.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
+ this.Installed.DefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter;
+ this.Installed.Width = 50;
+ resources.ApplyResources(this.Installed, "Installed");
+ //
+ // AutoInstalled
+ //
+ this.AutoInstalled.Name = "AutoInstalled";
+ this.AutoInstalled.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
+ this.AutoInstalled.DefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter;
+ this.AutoInstalled.Width = 50;
+ resources.ApplyResources(this.AutoInstalled, "AutoInstalled");
+ //
+ // UpdateCol
+ //
+ this.UpdateCol.Name = "UpdateCol";
+ this.UpdateCol.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
+ this.UpdateCol.DefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter;
+ this.UpdateCol.Width = 46;
+ resources.ApplyResources(this.UpdateCol, "UpdateCol");
+ //
+ // ReplaceCol
+ //
+ this.ReplaceCol.Name = "ReplaceCol";
+ this.ReplaceCol.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
+ this.ReplaceCol.DefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter;
+ this.ReplaceCol.Width = 46;
+ resources.ApplyResources(this.ReplaceCol, "ReplaceCol");
+ //
+ // ModName
+ //
+ this.ModName.Name = "ModName";
+ this.ModName.ReadOnly = true;
+ this.ModName.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
+ this.ModName.Width = 250;
+ resources.ApplyResources(this.ModName, "ModName");
+ //
+ // Author
+ //
+ this.Author.Name = "Author";
+ this.Author.ReadOnly = true;
+ this.Author.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
+ this.Author.Width = 120;
+ resources.ApplyResources(this.Author, "Author");
+ //
+ // InstalledVersion
+ //
+ this.InstalledVersion.Name = "InstalledVersion";
+ this.InstalledVersion.ReadOnly = true;
+ this.InstalledVersion.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
+ this.InstalledVersion.Width = 70;
+ resources.ApplyResources(this.InstalledVersion, "InstalledVersion");
+ //
+ // LatestVersion
+ //
+ this.LatestVersion.Name = "LatestVersion";
+ this.LatestVersion.ReadOnly = true;
+ this.LatestVersion.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
+ this.LatestVersion.Width = 70;
+ resources.ApplyResources(this.LatestVersion, "LatestVersion");
+ //
+ // KSPCompatibility
+ //
+ this.KSPCompatibility.Name = "KSPCompatibility";
+ this.KSPCompatibility.ReadOnly = true;
+ this.KSPCompatibility.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
+ this.KSPCompatibility.Width = 78;
+ resources.ApplyResources(this.KSPCompatibility, "KSPCompatibility");
+ //
+ // SizeCol
+ //
+ this.SizeCol.Name = "SizeCol";
+ this.SizeCol.ReadOnly = true;
+ this.SizeCol.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
+ this.SizeCol.DefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleRight;
+ resources.ApplyResources(this.SizeCol, "SizeCol");
+ //
+ // InstallDate
+ //
+ this.InstallDate.Name = "InstallDate";
+ this.InstallDate.ReadOnly = true;
+ this.InstallDate.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
+ this.InstallDate.Width = 140;
+ resources.ApplyResources(this.InstallDate, "InstallDate");
+ //
+ // DownloadCount
+ //
+ this.DownloadCount.Name = "DownloadCount";
+ this.DownloadCount.ReadOnly = true;
+ this.DownloadCount.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
+ this.DownloadCount.DefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleRight;
+ this.DownloadCount.Width = 70;
+ resources.ApplyResources(this.DownloadCount, "DownloadCount");
+ //
+ // Description
+ //
+ this.Description.Name = "Description";
+ this.Description.ReadOnly = true;
+ this.Description.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
+ this.Description.Width = 821;
+ resources.ApplyResources(this.Description, "Description");
+ //
+ // ModListContextMenuStrip
+ //
+ this.ModListContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.labelsToolStripMenuItem,
+ this.modListToolStripSeparator,
+ this.reinstallToolStripMenuItem,
+ this.downloadContentsToolStripMenuItem,
+ this.purgeContentsToolStripMenuItem});
+ this.ModListContextMenuStrip.Name = "ModListContextMenuStrip";
+ this.ModListContextMenuStrip.Size = new System.Drawing.Size(180, 70);
+ //
+ // labelsToolStripMenuItem
+ //
+ this.labelsToolStripMenuItem.Name = "labelsToolStripMenuItem";
+ this.labelsToolStripMenuItem.Size = new System.Drawing.Size(179, 22);
+ this.labelsToolStripMenuItem.DropDown = this.LabelsContextMenuStrip;
+ resources.ApplyResources(this.labelsToolStripMenuItem, "labelsToolStripMenuItem");
+ //
+ // reinstallToolStripMenuItem
+ //
+ this.reinstallToolStripMenuItem.Name = "reinstallToolStripMenuItem";
+ this.reinstallToolStripMenuItem.Size = new System.Drawing.Size(179, 22);
+ this.reinstallToolStripMenuItem.Click += new System.EventHandler(this.reinstallToolStripMenuItem_Click);
+ resources.ApplyResources(this.reinstallToolStripMenuItem, "reinstallToolStripMenuItem");
+ //
+ // downloadContentsToolStripMenuItem
+ //
+ this.downloadContentsToolStripMenuItem.Name = "downloadContentsToolStripMenuItem";
+ this.downloadContentsToolStripMenuItem.Size = new System.Drawing.Size(179, 22);
+ this.downloadContentsToolStripMenuItem.Click += new System.EventHandler(this.downloadContentsToolStripMenuItem_Click);
+ resources.ApplyResources(this.downloadContentsToolStripMenuItem, "downloadContentsToolStripMenuItem");
+ //
+ // purgeContentsToolStripMenuItem
+ //
+ this.purgeContentsToolStripMenuItem.Name = "purgeContentsToolStripMenuItem";
+ this.purgeContentsToolStripMenuItem.Size = new System.Drawing.Size(179, 22);
+ this.purgeContentsToolStripMenuItem.Click += new System.EventHandler(this.purgeContentsToolStripMenuItem_Click);
+ resources.ApplyResources(this.purgeContentsToolStripMenuItem, "purgeContentsToolStripMenuItem");
+ //
+ // LabelsContextMenuStrip
+ //
+ this.LabelsContextMenuStrip.Name = "LabelsContextMenuStrip";
+ this.LabelsContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.editLabelsToolStripMenuItem});
+ this.LabelsContextMenuStrip.Size = new System.Drawing.Size(180, 70);
+ this.LabelsContextMenuStrip.Opening += new System.ComponentModel.CancelEventHandler(LabelsContextMenuStrip_Opening);
+ //
+ // editLabelsToolStripMenuItem
+ //
+ this.editLabelsToolStripMenuItem.Name = "editLabelsToolStripMenuItem";
+ this.editLabelsToolStripMenuItem.Size = new System.Drawing.Size(179, 22);
+ this.editLabelsToolStripMenuItem.Click += new System.EventHandler(this.editLabelsToolStripMenuItem_Click);
+ resources.ApplyResources(this.editLabelsToolStripMenuItem, "editLabelsToolStripMenuItem");
+ //
+ // ModListHeaderContextMenuStrip
+ //
+ this.ModListHeaderContextMenuStrip.Name = "ModListHeaderContextMenuStrip";
+ this.ModListHeaderContextMenuStrip.AutoSize = true;
+ this.ModListHeaderContextMenuStrip.ShowCheckMargin = true;
+ this.ModListHeaderContextMenuStrip.ItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(ModListHeaderContextMenuStrip_ItemClicked);
+ //
+ // InstallAllCheckbox
+ //
+ this.InstallAllCheckbox.Location = new System.Drawing.Point(2, 50);
+ this.InstallAllCheckbox.Size = new System.Drawing.Size(20, 20);
+ this.InstallAllCheckbox.Checked = true;
+ this.InstallAllCheckbox.CheckedChanged += new System.EventHandler(this.InstallAllCheckbox_CheckChanged);
+ this.InstallAllCheckbox.TabIndex = 11;
+ this.InstallAllCheckbox.TabStop = false;
+ //
+ // ManageMods
+ //
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
+ this.Controls.Add(this.InstallAllCheckbox);
+ this.Controls.Add(this.ModGrid);
+ this.Controls.Add(this.menuStrip2);
+ this.Controls.Add(this.EditModSearch);
+ this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
+ this.Name = "ManageMods";
+ this.Size = new System.Drawing.Size(1544, 948);
+ resources.ApplyResources(this, "$this");
+ this.menuStrip2.ResumeLayout(false);
+ this.menuStrip2.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.ModGrid)).EndInit();
+ this.ModListContextMenuStrip.ResumeLayout(false);
+ this.ModListHeaderContextMenuStrip.ResumeLayout(false);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.MenuStrip menuStrip2;
+ private System.Windows.Forms.ToolStripMenuItem launchKSPToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem RefreshToolButton;
+ private System.Windows.Forms.ToolStripMenuItem UpdateAllToolButton;
+ private System.Windows.Forms.ToolStripMenuItem ApplyToolButton;
+ private System.Windows.Forms.ToolStripMenuItem FilterToolButton;
+ private System.Windows.Forms.ToolStripMenuItem FilterCompatibleButton;
+ private System.Windows.Forms.ToolStripMenuItem FilterInstalledButton;
+ private System.Windows.Forms.ToolStripMenuItem FilterInstalledUpdateButton;
+ private System.Windows.Forms.ToolStripMenuItem FilterReplaceableButton;
+ private System.Windows.Forms.ToolStripMenuItem FilterCachedButton;
+ private System.Windows.Forms.ToolStripMenuItem FilterUncachedButton;
+ private System.Windows.Forms.ToolStripMenuItem FilterNewButton;
+ private System.Windows.Forms.ToolStripMenuItem FilterNotInstalledButton;
+ private System.Windows.Forms.ToolStripMenuItem FilterIncompatibleButton;
+ private System.Windows.Forms.ToolStripMenuItem FilterAllButton;
+ private System.Windows.Forms.ToolStripMenuItem FilterLabelsToolButton;
+ private System.Windows.Forms.ToolStripMenuItem FilterTagsToolButton;
+ private System.Windows.Forms.ToolStripMenuItem NavBackwardToolButton;
+ private System.Windows.Forms.ToolStripMenuItem NavForwardToolButton;
+ public System.Windows.Forms.DataGridView ModGrid;
+ private System.Windows.Forms.CheckBox InstallAllCheckbox;
+ private System.Windows.Forms.DataGridViewCheckBoxColumn Installed;
+ private System.Windows.Forms.DataGridViewCheckBoxColumn AutoInstalled;
+ private System.Windows.Forms.DataGridViewCheckBoxColumn UpdateCol;
+ private System.Windows.Forms.DataGridViewCheckBoxColumn ReplaceCol;
+ private System.Windows.Forms.DataGridViewTextBoxColumn ModName;
+ private System.Windows.Forms.DataGridViewTextBoxColumn Author;
+ private System.Windows.Forms.DataGridViewTextBoxColumn InstalledVersion;
+ private System.Windows.Forms.DataGridViewTextBoxColumn LatestVersion;
+ private System.Windows.Forms.DataGridViewTextBoxColumn KSPCompatibility;
+ private System.Windows.Forms.DataGridViewTextBoxColumn SizeCol;
+ private System.Windows.Forms.DataGridViewTextBoxColumn InstallDate;
+ private System.Windows.Forms.DataGridViewTextBoxColumn DownloadCount;
+ private System.Windows.Forms.DataGridViewTextBoxColumn Description;
+ private System.Windows.Forms.ContextMenuStrip ModListContextMenuStrip;
+ private System.Windows.Forms.ToolStripSeparator modListToolStripSeparator;
+ private System.Windows.Forms.ToolStripSeparator tagFilterToolStripSeparator;
+ private System.Windows.Forms.ToolStripSeparator untaggedFilterToolStripSeparator;
+ private System.Windows.Forms.ContextMenuStrip LabelsContextMenuStrip;
+ private System.Windows.Forms.ContextMenuStrip ModListHeaderContextMenuStrip;
+ private System.Windows.Forms.ToolStripMenuItem labelsToolStripMenuItem;
+ private System.Windows.Forms.ToolStripSeparator labelToolStripSeparator;
+ private System.Windows.Forms.ToolStripMenuItem editLabelsToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem reinstallToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem downloadContentsToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem purgeContentsToolStripMenuItem;
+ private CKAN.EditModSearch EditModSearch;
+ }
+}
diff --git a/GUI/Controls/ManageMods.cs b/GUI/Controls/ManageMods.cs
new file mode 100644
index 0000000000..6744773fe4
--- /dev/null
+++ b/GUI/Controls/ManageMods.cs
@@ -0,0 +1,1424 @@
+using System;
+using System.IO;
+using System.Linq;
+using System.Drawing;
+using System.Diagnostics;
+using System.Collections.ObjectModel;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using Timer = System.Windows.Forms.Timer;
+using log4net;
+using CKAN.Versioning;
+
+namespace CKAN
+{
+ public partial class ManageMods : UserControl
+ {
+ public ManageMods()
+ {
+ InitializeComponent();
+
+ mainModList = new ModList(source => UpdateFilters());
+ FilterToolButton.MouseHover += (sender, args) => FilterToolButton.ShowDropDown();
+ launchKSPToolStripMenuItem.MouseHover += (sender, args) => launchKSPToolStripMenuItem.ShowDropDown();
+ ApplyToolButton.MouseHover += (sender, args) => ApplyToolButton.ShowDropDown();
+ ApplyToolButton.Enabled = false;
+
+ // History is read-only until the UI is started. We switch
+ // out of it at the end of OnLoad() when we call NavInit().
+ navHistory = new NavigationHistory { IsReadOnly = true };
+
+ // Initialize navigation. This should be called as late as
+ // possible, once the UI is "settled" from its initial load.
+ NavInit();
+
+ if (Platform.IsMono)
+ {
+ menuStrip2.Renderer = new FlatToolStripRenderer();
+ FilterToolButton.DropDown.Renderer = new FlatToolStripRenderer();
+ FilterTagsToolButton.DropDown.Renderer = new FlatToolStripRenderer();
+ FilterLabelsToolButton.DropDown.Renderer = new FlatToolStripRenderer();
+ ModListContextMenuStrip.Renderer = new FlatToolStripRenderer();
+ ModListHeaderContextMenuStrip.Renderer = new FlatToolStripRenderer();
+ LabelsContextMenuStrip.Renderer = new FlatToolStripRenderer();
+ }
+ }
+
+ private static readonly ILog log = LogManager.GetLogger(typeof(ManageMods));
+ private DateTime lastSearchTime;
+ private string lastSearchKey;
+ private NavigationHistory navHistory;
+
+ private IEnumerable currentChangeSet;
+ private Dictionary conflicts;
+
+ public readonly ModList mainModList;
+
+ public event Action OnSelectedModuleChanged;
+ public event Action> OnChangeSetChanged;
+ public event Action OnRegistryChanged;
+
+ public event Action> StartChangeSet;
+ public event Action OpenProgressTab;
+ public event Action CloseProgressTab;
+ public event Action> LabelsAfterUpdate;
+
+ private IEnumerable ChangeSet
+ {
+ get { return currentChangeSet; }
+ set
+ {
+ var orig = currentChangeSet;
+ currentChangeSet = value;
+ if (!ReferenceEquals(orig, value))
+ ChangeSetUpdated();
+ }
+ }
+
+ private void ChangeSetUpdated()
+ {
+ if (ChangeSet != null && ChangeSet.Any())
+ {
+ ApplyToolButton.Enabled = true;
+ }
+ else
+ {
+ ApplyToolButton.Enabled = false;
+ InstallAllCheckbox.Checked = true;
+ }
+ if (OnChangeSetChanged != null)
+ {
+ OnChangeSetChanged(ChangeSet);
+ }
+ }
+
+ private Dictionary Conflicts
+ {
+ get { return conflicts; }
+ set
+ {
+ var orig = conflicts;
+ conflicts = value;
+ if (orig != value)
+ ConflictsUpdated(orig);
+ }
+ }
+
+ private void ConflictsUpdated(Dictionary prevConflicts)
+ {
+ if (Conflicts == null)
+ {
+ // Clear status bar if no conflicts
+ Main.Instance.AddStatusMessage("");
+ }
+
+ if (prevConflicts != null)
+ {
+ // Mark old conflicts as non-conflicted
+ // (rows that are _still_ conflicted will be marked as such in the next loop)
+ foreach (GUIMod guiMod in prevConflicts.Keys)
+ {
+ DataGridViewRow row = mainModList.full_list_of_mod_rows[guiMod.Identifier];
+
+ foreach (DataGridViewCell cell in row.Cells)
+ {
+ cell.ToolTipText = null;
+ }
+ mainModList.ReapplyLabels(guiMod, false, Main.Instance.CurrentInstance.Name);
+ if (row.Visible)
+ {
+ ModGrid.InvalidateRow(row.Index);
+ }
+ }
+ }
+ if (Conflicts != null)
+ {
+ // Mark current conflicts as conflicted
+ foreach (var kvp in Conflicts)
+ {
+ GUIMod guiMod = kvp.Key;
+ DataGridViewRow row = mainModList.full_list_of_mod_rows[guiMod.Identifier];
+ string conflict_text = kvp.Value;
+
+ foreach (DataGridViewCell cell in row.Cells)
+ {
+ cell.ToolTipText = conflict_text;
+ }
+ row.DefaultCellStyle.BackColor = mainModList.GetRowBackground(guiMod, true, Main.Instance.CurrentInstance.Name);
+ if (row.Visible)
+ {
+ ModGrid.InvalidateRow(row.Index);
+ }
+ }
+ }
+ }
+
+ private void RefreshToolButton_Click(object sender, EventArgs e)
+ {
+ Main.Instance.UpdateRepo();
+ }
+
+ private void FilterToolButton_DropDown_Opening(object sender, System.ComponentModel.CancelEventArgs e)
+ {
+ // The menu items' dropdowns can't be accessed if they're empty
+ FilterTagsToolButton_DropDown_Opening(null, null);
+ FilterLabelsToolButton_DropDown_Opening(null, null);
+ }
+
+ private void FilterCompatibleButton_Click(object sender, EventArgs e)
+ {
+ Filter(GUIModFilter.Compatible);
+ }
+
+ private void FilterInstalledButton_Click(object sender, EventArgs e)
+ {
+ Filter(GUIModFilter.Installed);
+ }
+
+ private void FilterInstalledUpdateButton_Click(object sender, EventArgs e)
+ {
+ Filter(GUIModFilter.InstalledUpdateAvailable);
+ }
+
+ private void FilterReplaceableButton_Click(object sender, EventArgs e)
+ {
+ Filter(GUIModFilter.Replaceable);
+ }
+
+ private void FilterCachedButton_Click(object sender, EventArgs e)
+ {
+ Filter(GUIModFilter.Cached);
+ }
+
+ private void FilterUncachedButton_Click(object sender, EventArgs e)
+ {
+ Filter(GUIModFilter.Uncached);
+ }
+
+ private void FilterNewButton_Click(object sender, EventArgs e)
+ {
+ Filter(GUIModFilter.NewInRepository);
+ }
+
+ private void FilterNotInstalledButton_Click(object sender, EventArgs e)
+ {
+ Filter(GUIModFilter.NotInstalled);
+ }
+
+ private void FilterIncompatibleButton_Click(object sender, EventArgs e)
+ {
+ Filter(GUIModFilter.Incompatible);
+ }
+
+ private void FilterAllButton_Click(object sender, EventArgs e)
+ {
+ Filter(GUIModFilter.All);
+ }
+
+ ///
+ /// Called when the ModGrid filter (all, compatible, incompatible...) is changed.
+ ///
+ /// Filter.
+ public void Filter(GUIModFilter filter, ModuleTag tag = null, ModuleLabel label = null)
+ {
+ // Triggers mainModList.ModFiltersUpdated()
+ mainModList.TagFilter = tag;
+ mainModList.CustomLabelFilter = label;
+ mainModList.ModFilter = filter;
+
+ // Save new filter to the configuration.
+ Main.Instance.configuration.ActiveFilter = (int)mainModList.ModFilter;
+ Main.Instance.configuration.CustomLabelFilter = label?.Name;
+ Main.Instance.configuration.TagFilter = tag?.Name;
+ Main.Instance.configuration.Save();
+
+ // Ask the configuration which columns to show.
+ foreach (DataGridViewColumn col in ModGrid.Columns)
+ {
+ // Some columns are always shown, and others are handled by UpdateModsList()
+ if (col.Name != "Installed" && col.Name != "UpdateCol" && col.Name != "ReplaceCol")
+ {
+ col.Visible = !Main.Instance.configuration.HiddenColumnNames.Contains(col.Name);
+ }
+ }
+
+ switch (filter)
+ {
+ // Some columns really do / don't make sense to be visible on certain filter settings.
+ // Hide / Show them, without writing to config, so once the user changes tab again,
+ // they are shown / hidden again, as before.
+ case GUIModFilter.All: FilterToolButton.Text = Properties.Resources.MainFilterAll; break;
+ case GUIModFilter.Incompatible: FilterToolButton.Text = Properties.Resources.MainFilterIncompatible; break;
+ case GUIModFilter.Installed: FilterToolButton.Text = Properties.Resources.MainFilterInstalled; break;
+ case GUIModFilter.InstalledUpdateAvailable: FilterToolButton.Text = Properties.Resources.MainFilterUpgradeable; break;
+ case GUIModFilter.Replaceable: FilterToolButton.Text = Properties.Resources.MainFilterReplaceable; break;
+ case GUIModFilter.Cached: FilterToolButton.Text = Properties.Resources.MainFilterCached; break;
+ case GUIModFilter.Uncached: FilterToolButton.Text = Properties.Resources.MainFilterUncached; break;
+ case GUIModFilter.NewInRepository: FilterToolButton.Text = Properties.Resources.MainFilterNew; break;
+ case GUIModFilter.NotInstalled: ModGrid.Columns["InstalledVersion"].Visible = false;
+ ModGrid.Columns["InstallDate"].Visible = false;
+ ModGrid.Columns["AutoInstalled"].Visible = false;
+ FilterToolButton.Text = Properties.Resources.MainFilterNotInstalled; break;
+ case GUIModFilter.CustomLabel: FilterToolButton.Text = string.Format(Properties.Resources.MainFilterLabel, label?.Name ?? "CUSTOM"); break;
+ case GUIModFilter.Tag:
+ FilterToolButton.Text = tag == null
+ ? Properties.Resources.MainFilterUntagged
+ : string.Format(Properties.Resources.MainFilterTag, tag.Name);
+ break;
+ default: FilterToolButton.Text = Properties.Resources.MainFilterCompatible; break;
+ }
+ }
+
+ public void MarkAllUpdates()
+ {
+ foreach (DataGridViewRow row in ModGrid.Rows)
+ {
+ var mod = (GUIMod)row.Tag;
+ if (mod.HasUpdate)
+ {
+ MarkModForUpdate(mod.Identifier, true);
+ }
+ }
+
+ // only sort by Update column if checkbox in settings checked
+ if (Main.Instance.configuration.AutoSortByUpdate)
+ {
+ // set new sort column
+ var new_sort_column = ModGrid.Columns[UpdateCol.Index];
+ var current_sort_column = ModGrid.Columns[Main.Instance.configuration.SortByColumnIndex];
+
+ // Reset the glyph.
+ current_sort_column.HeaderCell.SortGlyphDirection = SortOrder.None;
+ Main.Instance.configuration.SortByColumnIndex = new_sort_column.Index;
+ UpdateFilters();
+
+ // Select the top row and scroll the list to it.
+ ModGrid.CurrentCell = ModGrid.Rows[0].Cells[SelectableColumnIndex()];
+ }
+
+ ModGrid.Refresh();
+ }
+
+ private void MarkAllUpdatesToolButton_Click(object sender, EventArgs e)
+ {
+ MarkAllUpdates();
+ }
+
+ private void ApplyToolButton_Click(object sender, EventArgs e)
+ {
+ Main.Instance.tabController.ShowTab("ChangesetTabPage", 1);
+ }
+
+ public void MarkModForUpdate(string identifier, bool value)
+ {
+ Util.Invoke(this, () => _MarkModForUpdate(identifier, value));
+ }
+
+ private void _MarkModForUpdate(string identifier, bool value)
+ {
+ DataGridViewRow row = mainModList.full_list_of_mod_rows[identifier];
+ var mod = (GUIMod)row.Tag;
+ mod.SetUpgradeChecked(row, UpdateCol, value);
+ }
+
+ private void launchKSPToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ Main.Instance.LaunchKSP();
+ }
+
+ private void FilterTagsToolButton_DropDown_Opening(object sender, System.ComponentModel.CancelEventArgs e)
+ {
+ FilterTagsToolButton.DropDownItems.Clear();
+ foreach (var kvp in mainModList.ModuleTags.Tags.OrderBy(kvp => kvp.Key))
+ {
+ FilterTagsToolButton.DropDownItems.Add(new ToolStripMenuItem(
+ $"{kvp.Key} ({kvp.Value.ModuleIdentifiers.Count})",
+ null, tagFilterButton_Click
+ )
+ {
+ Tag = kvp.Value
+ });
+ }
+ FilterTagsToolButton.DropDownItems.Add(untaggedFilterToolStripSeparator);
+ FilterTagsToolButton.DropDownItems.Add(new ToolStripMenuItem(
+ string.Format(Properties.Resources.MainLabelsUntagged, mainModList.ModuleTags.Untagged.Count),
+ null, tagFilterButton_Click
+ )
+ {
+ Tag = null
+ });
+ }
+
+ private void FilterLabelsToolButton_DropDown_Opening(object sender, System.ComponentModel.CancelEventArgs e)
+ {
+ FilterLabelsToolButton.DropDownItems.Clear();
+ foreach (ModuleLabel mlbl in mainModList.ModuleLabels.LabelsFor(Main.Instance.CurrentInstance.Name))
+ {
+ FilterLabelsToolButton.DropDownItems.Add(new ToolStripMenuItem(
+ $"{mlbl.Name} ({mlbl.ModuleIdentifiers.Count})",
+ null, customFilterButton_Click
+ )
+ {
+ Tag = mlbl
+ });
+ }
+ }
+
+ private void NavBackwardToolButton_Click(object sender, EventArgs e)
+ {
+ NavGoBackward();
+ }
+
+ private void NavForwardToolButton_Click(object sender, EventArgs e)
+ {
+ NavGoForward();
+ }
+
+ private void ModList_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ // Skip if already disposed (i.e. after the form has been closed).
+ // Needed for TransparentTextBoxes
+ if (IsDisposed)
+ {
+ return;
+ }
+
+ var module = SelectedModule;
+ if (OnSelectedModuleChanged != null)
+ {
+ OnSelectedModuleChanged(module);
+ }
+ if (module != null)
+ {
+ NavSelectMod(module);
+ }
+ }
+
+ ///
+ /// Called when there's a click on the ModGrid header row.
+ /// Handles sorting and the header right click context menu.
+ ///
+ private void ModList_HeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
+ {
+ // Left click -> sort by new column / change sorting direction.
+ if (e.Button == MouseButtons.Left)
+ {
+ var new_sort_column = ModGrid.Columns [e.ColumnIndex];
+ var current_sort_column = ModGrid.Columns [Main.Instance.configuration.SortByColumnIndex];
+
+ // Reverse the sort order if the current sorting column is clicked again.
+ Main.Instance.configuration.SortDescending = new_sort_column == current_sort_column && !Main.Instance.configuration.SortDescending;
+
+ // Reset the glyph.
+ current_sort_column.HeaderCell.SortGlyphDirection = SortOrder.None;
+ Main.Instance.configuration.SortByColumnIndex = new_sort_column.Index;
+ UpdateFilters();
+ }
+ // Right click -> Bring up context menu to change visibility of columns.
+ else if (e.Button == MouseButtons.Right)
+ {
+ // Start from scrap: clear the entire item list, then add all options again.
+ ModListHeaderContextMenuStrip.Items.Clear();
+
+ // Add columns
+ ModListHeaderContextMenuStrip.Items.AddRange(
+ ModGrid.Columns.Cast()
+ .Where(col => col.Name != "Installed" && col.Name != "UpdateCol" && col.Name != "ReplaceCol")
+ .Select(col => new ToolStripMenuItem()
+ {
+ Name = col.Name,
+ Text = col.HeaderText,
+ Checked = col.Visible,
+ Tag = col
+ })
+ .ToArray()
+ );
+
+ // Separator
+ ModListHeaderContextMenuStrip.Items.Add(new ToolStripSeparator());
+
+ // Add tags
+ ModListHeaderContextMenuStrip.Items.AddRange(
+ mainModList.ModuleTags.Tags.OrderBy(kvp => kvp.Key)
+ .Select(kvp => new ToolStripMenuItem()
+ {
+ Name = kvp.Key,
+ Text = kvp.Key,
+ Checked = kvp.Value.Visible,
+ Tag = kvp.Value,
+ })
+ .ToArray()
+ );
+
+ // Show the context menu on cursor position.
+ ModListHeaderContextMenuStrip.Show(Cursor.Position);
+ }
+ }
+
+ ///
+ /// Called if a ToolStripButton of the header context menu is pressed.
+ ///
+ private void ModListHeaderContextMenuStrip_ItemClicked(object sender, System.Windows.Forms.ToolStripItemClickedEventArgs e)
+ {
+ // ClickedItem is of type ToolStripItem, we need ToolStripButton.
+ ToolStripMenuItem clickedItem = e.ClickedItem as ToolStripMenuItem;
+ DataGridViewColumn col = clickedItem?.Tag as DataGridViewColumn;
+ ModuleTag tag = clickedItem?.Tag as ModuleTag;
+
+ if (col != null)
+ {
+ col.Visible = !clickedItem.Checked;
+ Main.Instance.configuration.SetColumnVisibility(col.Name, !clickedItem.Checked);
+ if (col.Index == 0)
+ {
+ InstallAllCheckbox.Visible = col.Visible;
+ }
+ }
+ else if (tag != null)
+ {
+ tag.Visible = !clickedItem.Checked;
+ if (tag.Visible)
+ {
+ mainModList.ModuleTags.HiddenTags.Remove(tag.Name);
+ }
+ else
+ {
+ mainModList.ModuleTags.HiddenTags.Add(tag.Name);
+ }
+ mainModList.ModuleTags.Save(ModuleTagList.DefaultPath);
+ UpdateFilters();
+ }
+ }
+
+ ///
+ /// Called on key down when the mod list is focused.
+ /// Makes the Home/End keys go to the top/bottom of the list respectively.
+ ///
+ private void ModList_KeyDown(object sender, KeyEventArgs e)
+ {
+ switch (e.KeyCode)
+ {
+ case Keys.Home:
+ // First row.
+ ModGrid.CurrentCell = ModGrid.Rows[0].Cells[SelectableColumnIndex()];
+ e.Handled = true;
+ break;
+
+ case Keys.End:
+ // Last row.
+ ModGrid.CurrentCell = ModGrid.Rows[ModGrid.Rows.Count - 1].Cells[SelectableColumnIndex()];
+ e.Handled = true;
+ break;
+
+ case Keys.Space:
+ // If they've focused one of the checkbox columns, don't intercept
+ if (ModGrid.CurrentCell.ColumnIndex > 3)
+ {
+ DataGridViewRow row = ModGrid.CurrentRow;
+ // Toggle Update column if enabled, otherwise Install
+ for (int colIndex = 2; colIndex >= 0; --colIndex)
+ {
+ if (row?.Cells[colIndex] is DataGridViewCheckBoxCell)
+ {
+ // Need to change the state here, because the user hasn't clicked on a checkbox
+ row.Cells[colIndex].Value = !(bool)row.Cells[colIndex].Value;
+ ModGrid.CommitEdit(DataGridViewDataErrorContexts.Commit);
+ e.Handled = true;
+ break;
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ ///
+ /// Called on key press when the mod is focused. Scrolls to the first mod with name
+ /// beginning with the key pressed. If more than one unique keys are pressed in under
+ /// a second, it searches for the combination of the keys pressed. If the same key is
+ /// being pressed repeatedly, it cycles through mods names beginning with that key.
+ /// If space is pressed, the checkbox at the current row is toggled.
+ ///
+ private void ModList_KeyPress(object sender, KeyPressEventArgs e)
+ {
+ // Don't search for spaces or newlines
+ if (e.KeyChar == (char)Keys.Space || e.KeyChar == (char)Keys.Enter)
+ {
+ return;
+ }
+
+ var key = e.KeyChar.ToString();
+ // Determine time passed since last key press.
+ TimeSpan interval = DateTime.Now - lastSearchTime;
+ if (interval.TotalSeconds < 1)
+ {
+ // Last keypress was < 1 sec ago, so combine the last and current keys.
+ key = lastSearchKey + key;
+ }
+
+ // Remember the current time and key.
+ lastSearchTime = DateTime.Now;
+ lastSearchKey = key;
+
+ if (key.Distinct().Count() == 1)
+ {
+ // Treat repeating and single keypresses the same.
+ key = key.Substring(0, 1);
+ }
+
+ FocusMod(key, false);
+ e.Handled = true;
+ }
+
+ ///
+ /// I'm pretty sure this is what gets called when the user clicks on a ticky in the mod list.
+ ///
+ private void ModList_CellContentClick(object sender, DataGridViewCellEventArgs e)
+ {
+ ModGrid.CommitEdit(DataGridViewDataErrorContexts.Commit);
+ }
+
+ private void ModList_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
+ {
+ if (e.Button != MouseButtons.Left)
+ return;
+
+ if (e.RowIndex < 0)
+ return;
+
+ DataGridViewRow row = ModGrid.Rows[e.RowIndex];
+ if (!(row.Cells[0] is DataGridViewCheckBoxCell))
+ return;
+
+ // Need to change the state here, because the user hasn't clicked on a checkbox.
+ row.Cells[0].Value = !(bool)row.Cells[0].Value;
+ ModGrid.CommitEdit(DataGridViewDataErrorContexts.Commit);
+ }
+
+ private async void ModList_CellValueChanged(object sender, DataGridViewCellEventArgs e)
+ {
+ int row_index = e.RowIndex;
+ int column_index = e.ColumnIndex;
+
+ if (row_index < 0 || column_index < 0)
+ return;
+
+ DataGridView grid = sender as DataGridView;
+ DataGridViewRow row = grid?.Rows[row_index];
+ DataGridViewCell gridCell = row?.Cells[column_index];
+
+ if (gridCell is DataGridViewLinkCell)
+ {
+ // Launch URLs if found in grid
+ DataGridViewLinkCell cell = gridCell as DataGridViewLinkCell;
+ string cmd = cell?.Value.ToString();
+ if (!string.IsNullOrEmpty(cmd))
+ Utilities.ProcessStartURL(cmd);
+ }
+ else
+ {
+ GUIMod gui_mod = row?.Tag as GUIMod;
+ if (gui_mod != null)
+ {
+ switch (ModGrid.Columns[column_index].Name)
+ {
+ case "Installed":
+ gui_mod.SetInstallChecked(row, Installed);
+ // The above will call UpdateChangeSetAndConflicts, so we don't need to.
+ return;
+ case "AutoInstalled":
+ gui_mod.SetAutoInstallChecked(row, AutoInstalled);
+ if (OnRegistryChanged != null)
+ {
+ OnRegistryChanged();
+ }
+ break;
+ case "UpdateCol":
+ gui_mod.SetUpgradeChecked(row, UpdateCol);
+ break;
+ case "ReplaceCol":
+ gui_mod.SetReplaceChecked(row, ReplaceCol);
+ break;
+ }
+ await UpdateChangeSetAndConflicts(
+ Main.Instance.CurrentInstance,
+ RegistryManager.Instance(Main.Instance.CurrentInstance).registry
+ );
+ }
+ }
+ }
+
+ private void ModList_GotFocus(object sender, EventArgs e)
+ {
+ Util.Invoke(this, () =>
+ {
+ // Give the selected row the standard highlight color
+ ModGrid.RowsDefaultCellStyle.SelectionBackColor = SystemColors.Highlight;
+ ModGrid.RowsDefaultCellStyle.SelectionForeColor = SystemColors.HighlightText;
+ });
+ }
+
+ private void ModList_LostFocus(object sender, EventArgs e)
+ {
+ Util.Invoke(this, () =>
+ {
+ // Gray out the selected row so you can tell the mod list is not focused
+ ModGrid.RowsDefaultCellStyle.SelectionBackColor = SystemColors.Control;
+ ModGrid.RowsDefaultCellStyle.SelectionForeColor = SystemColors.ControlText;
+ });
+ }
+
+ private void InstallAllCheckbox_CheckChanged(object sender, EventArgs e)
+ {
+ if (InstallAllCheckbox.Checked)
+ {
+ // Reset changeset
+ ClearChangeSet();
+ }
+ else
+ {
+ // Uninstall all
+ foreach (DataGridViewRow row in mainModList.full_list_of_mod_rows.Values)
+ {
+ GUIMod mod = row.Tag as GUIMod;
+ if (mod.IsInstallChecked)
+ {
+ mod.SetInstallChecked(row, Installed, false);
+ }
+ }
+ }
+ }
+
+ public void ClearChangeSet()
+ {
+ foreach (DataGridViewRow row in mainModList.full_list_of_mod_rows.Values)
+ {
+ GUIMod mod = row.Tag as GUIMod;
+ if (mod.IsInstallChecked != mod.IsInstalled)
+ {
+ mod.SetInstallChecked(row, Installed, mod.IsInstalled);
+ }
+ mod.SetUpgradeChecked(row, UpdateCol, false);
+ mod.SetReplaceChecked(row, ReplaceCol, false);
+ }
+ }
+
+ private void tagFilterButton_Click(object sender, EventArgs e)
+ {
+ var clicked = sender as ToolStripMenuItem;
+ Filter(GUIModFilter.Tag, clicked.Tag as ModuleTag, null);
+ }
+
+ private void customFilterButton_Click(object sender, EventArgs e)
+ {
+ var clicked = sender as ToolStripMenuItem;
+ Filter(GUIModFilter.CustomLabel, null, clicked.Tag as ModuleLabel);
+ }
+
+ ///
+ /// Find a column of the grid that can contain the CurrentCell.
+ /// Can't be hidden or an exception is thrown.
+ /// Shouldn't be a checkbox because we don't want the space bar to toggle.
+ ///
+ ///
+ /// Index of the column to use.
+ ///
+ private int SelectableColumnIndex()
+ {
+ // First try the currently active cell's column
+ return ModGrid.CurrentCell?.ColumnIndex
+ // If there's no currently active cell, use the first visible non-checkbox column
+ ?? ModGrid.Columns.Cast()
+ .FirstOrDefault(c => c is DataGridViewTextBoxColumn && c.Visible)?.Index
+ // Otherwise use the Installed checkbox column since it can't be hidden
+ ?? Installed.Index;
+ }
+
+ public void FocusMod(string key, bool exactMatch, bool showAsFirst = false)
+ {
+ DataGridViewRow current_row = ModGrid.CurrentRow;
+ int currentIndex = current_row?.Index ?? 0;
+ DataGridViewRow first_match = null;
+
+ var does_name_begin_with_key = new Func(row =>
+ {
+ GUIMod mod = row.Tag as GUIMod;
+ bool row_match;
+ if (exactMatch)
+ row_match = mod.Name == key || mod.Identifier == key;
+ else
+ row_match = mod.Name.StartsWith(key, StringComparison.OrdinalIgnoreCase) ||
+ mod.Abbrevation.StartsWith(key, StringComparison.OrdinalIgnoreCase) ||
+ mod.Identifier.StartsWith(key, StringComparison.OrdinalIgnoreCase);
+
+ if (row_match && first_match == null)
+ {
+ // Remember the first match to allow cycling back to it if necessary.
+ first_match = row;
+ }
+
+ if (key.Length == 1 && row_match && row.Index <= currentIndex)
+ {
+ // Keep going forward if it's a single key match and not ahead of the current row.
+ return false;
+ }
+
+ return row_match;
+ });
+
+ ModGrid.ClearSelection();
+ var rows = ModGrid.Rows.Cast().Where(row => row.Visible);
+ DataGridViewRow match = rows.FirstOrDefault(does_name_begin_with_key);
+ if (match == null && first_match != null)
+ {
+ // If there were no matches after the first match, cycle over to the beginning.
+ match = first_match;
+ }
+
+ if (match != null)
+ {
+ match.Selected = true;
+
+ ModGrid.CurrentCell = match.Cells[SelectableColumnIndex()];
+ if (showAsFirst)
+ ModGrid.FirstDisplayedScrollingRowIndex = match.Index;
+ }
+ else
+ {
+ Main.Instance.AddStatusMessage(Properties.Resources.MainNotFound);
+ }
+ }
+
+ private void ModList_MouseDown(object sender, MouseEventArgs e)
+ {
+ var rowIndex = ModGrid.HitTest(e.X, e.Y).RowIndex;
+
+ // Ignore header column to prevent errors.
+ if (rowIndex != -1 && e.Button == MouseButtons.Right)
+ {
+ // Detect the clicked cell and select the row.
+ ModGrid.ClearSelection();
+ ModGrid.Rows[rowIndex].Selected = true;
+
+ // Show the context menu.
+ ModListContextMenuStrip.Show(ModGrid, new Point(e.X, e.Y));
+
+ // Set the menu options.
+ var guiMod = (GUIMod)ModGrid.Rows[rowIndex].Tag;
+
+ downloadContentsToolStripMenuItem.Enabled = !guiMod.IsCached;
+ purgeContentsToolStripMenuItem.Enabled = guiMod.IsCached;
+ reinstallToolStripMenuItem.Enabled = guiMod.IsInstalled && !guiMod.IsAutodetected;
+ }
+ }
+
+ private void reinstallToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ GUIMod module = SelectedModule;
+ if (module == null || !module.IsCKAN)
+ return;
+
+ YesNoDialog reinstallDialog = new YesNoDialog();
+ string confirmationText = string.Format(Properties.Resources.MainReinstallConfirm, module.Name);
+ if (reinstallDialog.ShowYesNoDialog(Main.Instance, confirmationText) == DialogResult.No)
+ return;
+
+ IRegistryQuerier registry = RegistryManager.Instance(Main.Instance.CurrentInstance).registry;
+
+ // Build the list of changes, first the mod to remove:
+ List toReinstall = new List()
+ {
+ new ModChange(module.ToModule(), GUIModChangeType.Remove, null)
+ };
+ // Then everything we need to re-install:
+ var revdep = registry.FindReverseDependencies(new List() { module.Identifier });
+ var goners = revdep.Union(
+ registry.FindRemovableAutoInstalled(
+ registry.InstalledModules.Where(im => !revdep.Contains(im.identifier))
+ ).Select(im => im.Module.identifier)
+ );
+ foreach (string id in goners)
+ {
+ toReinstall.Add(new ModChange(
+ (mainModList.full_list_of_mod_rows[id]?.Tag as GUIMod).ToModule(),
+ GUIModChangeType.Install,
+ null
+ ));
+ }
+ if (StartChangeSet != null)
+ {
+ StartChangeSet(toReinstall);
+ }
+ }
+
+ private void purgeContentsToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ // Purge other versions as well since the user is likely to want that
+ // and has no other way to achieve it
+ var selected = SelectedModule;
+ if (selected != null)
+ {
+ IRegistryQuerier registry = RegistryManager.Instance(Main.Instance.CurrentInstance).registry;
+ var allAvail = registry.AvailableByIdentifier(selected.Identifier);
+ foreach (CkanModule mod in allAvail)
+ {
+ Main.Instance.Manager.Cache.Purge(mod);
+ }
+ selected.UpdateIsCached();
+ Main.Instance.UpdateModContentsTree(selected.ToCkanModule(), true);
+ }
+ }
+
+ private void downloadContentsToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ Main.Instance.StartDownload(SelectedModule);
+ }
+
+ private void EditModSearch_ApplySearch(ModSearch search)
+ {
+ mainModList.SetSearch(search);
+ }
+
+ private void EditModSearch_SurrenderFocus()
+ {
+ Util.Invoke(this, () => ModGrid.Focus());
+ }
+
+ private void LabelsContextMenuStrip_Opening(object sender, System.ComponentModel.CancelEventArgs e)
+ {
+ LabelsContextMenuStrip.Items.Clear();
+
+ var module = SelectedModule;
+ foreach (ModuleLabel mlbl in mainModList.ModuleLabels.LabelsFor(Main.Instance.CurrentInstance.Name))
+ {
+ LabelsContextMenuStrip.Items.Add(
+ new ToolStripMenuItem(mlbl.Name, null, labelMenuItem_Click)
+ {
+ Checked = mlbl.ModuleIdentifiers.Contains(module.Identifier),
+ CheckOnClick = true,
+ Tag = mlbl,
+ }
+ );
+ }
+ LabelsContextMenuStrip.Items.Add(labelToolStripSeparator);
+ LabelsContextMenuStrip.Items.Add(editLabelsToolStripMenuItem);
+ e.Cancel = false;
+ }
+
+ private void editLabelsToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ EditLabelsDialog eld = new EditLabelsDialog(Main.Instance.currentUser, Main.Instance.Manager, mainModList.ModuleLabels);
+ eld.ShowDialog(this);
+ eld.Dispose();
+ mainModList.ModuleLabels.Save(ModuleLabelList.DefaultPath);
+ foreach (GUIMod module in mainModList.Modules)
+ {
+ mainModList.ReapplyLabels(module, Conflicts?.ContainsKey(module) ?? false, Main.Instance.CurrentInstance.Name);
+ }
+ }
+
+ private void labelMenuItem_Click(object sender, EventArgs e)
+ {
+ var item = sender as ToolStripMenuItem;
+ var mlbl = item.Tag as ModuleLabel;
+ var module = SelectedModule;
+ if (item.Checked)
+ {
+ mlbl.Add(module.Identifier);
+ }
+ else
+ {
+ mlbl.Remove(module.Identifier);
+ }
+ mainModList.ReapplyLabels(module, Conflicts?.ContainsKey(module) ?? false, Main.Instance.CurrentInstance.Name);
+ mainModList.ModuleLabels.Save(ModuleLabelList.DefaultPath);
+ }
+
+ private void UpdateFilters()
+ {
+ Util.Invoke(this, _UpdateFilters);
+ }
+
+ private void _UpdateFilters()
+ {
+ if (ModGrid == null || mainModList?.full_list_of_mod_rows == null)
+ return;
+
+ // Each time a row in DataGridViewRow is changed, DataGridViewRow updates the view. Which is slow.
+ // To make the filtering process faster, Copy the list of rows. Filter out the hidden and replace the
+ // rows in DataGridView.
+
+ var rows = new DataGridViewRow[mainModList.full_list_of_mod_rows.Count];
+ mainModList.full_list_of_mod_rows.Values.CopyTo(rows, 0);
+ // Try to remember the current scroll position and selected mod
+ var scroll_col = Math.Max(0, ModGrid.FirstDisplayedScrollingColumnIndex);
+ GUIMod selected_mod = null;
+ if (ModGrid.CurrentRow != null)
+ {
+ selected_mod = (GUIMod) ModGrid.CurrentRow.Tag;
+ }
+
+ ModGrid.Rows.Clear();
+ foreach (var row in rows)
+ {
+ var mod = ((GUIMod) row.Tag);
+ row.Visible = mainModList.IsVisible(mod, Main.Instance.CurrentInstance.Name);
+ }
+
+ var sorted = this._SortRowsByColumn(rows.Where(row => row.Visible));
+
+ ModGrid.Rows.AddRange(sorted.ToArray());
+
+ // Find and select the previously selected row
+ if (selected_mod != null)
+ {
+ var selected_row = ModGrid.Rows.Cast()
+ .FirstOrDefault(row => selected_mod.Identifier.Equals(((GUIMod)row.Tag).Identifier));
+ if (selected_row != null)
+ {
+ ModGrid.CurrentCell = selected_row.Cells[scroll_col];
+ }
+ }
+ }
+
+ public async void UpdateModsList(Dictionary old_modules = null)
+ {
+ // Run the update in the background so the UI thread can appear alive
+ // Await it so potential (fatal) errors are thrown, not swallowed.
+ // Need to be on the GUI thread to get the translated strings
+ Main.Instance.tabController.RenameTab("WaitTabPage", Properties.Resources.MainModListWaitTitle);
+ await Task.Factory.StartNew(() =>
+ _UpdateModsList(old_modules)
+ );
+ }
+
+ private void _UpdateModsList(Dictionary old_modules = null)
+ {
+ log.Info("Updating the mod list");
+
+ if (OpenProgressTab != null)
+ {
+ OpenProgressTab();
+ }
+
+ Main.Instance.Wait.AddLogMessage(Properties.Resources.MainModListLoadingRegistry);
+ KspVersionCriteria versionCriteria = Main.Instance.CurrentInstance.VersionCriteria();
+ IRegistryQuerier registry = RegistryManager.Instance(Main.Instance.CurrentInstance).registry;
+
+ Main.Instance.Wait.AddLogMessage(Properties.Resources.MainModListLoadingInstalled);
+ var gui_mods = new HashSet();
+ gui_mods.UnionWith(
+ registry.InstalledModules
+ .Where(instMod => !instMod.Module.IsDLC)
+ .Select(instMod => new GUIMod(instMod, registry, versionCriteria))
+ );
+ Main.Instance.Wait.AddLogMessage(Properties.Resources.MainModListLoadingAvailable);
+ gui_mods.UnionWith(
+ registry.CompatibleModules(versionCriteria)
+ .Where(m => !m.IsDLC)
+ .Select(m => new GUIMod(m, registry, versionCriteria))
+ );
+ 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))
+ );
+
+ Main.Instance.Wait.AddLogMessage(Properties.Resources.MainModListPreservingNew);
+ var toNotify = new HashSet();
+ if (old_modules != null)
+ {
+ foreach (GUIMod gm in gui_mods)
+ {
+ if (old_modules.TryGetValue(gm.Identifier, out bool oldIncompat))
+ {
+ // Found it; check if newly compatible
+ if (!gm.IsIncompatible && oldIncompat)
+ {
+ gm.IsNew = true;
+ toNotify.Add(gm);
+ }
+ }
+ else
+ {
+ // Newly indexed, show regardless of compatibility
+ gm.IsNew = true;
+ }
+ }
+ }
+ else
+ {
+ // Copy the new mod flag from the old list.
+ var old_new_mods = new HashSet(
+ mainModList.Modules.Where(m => m.IsNew));
+ foreach (var gui_mod in gui_mods.Where(m => old_new_mods.Contains(m)))
+ {
+ gui_mod.IsNew = true;
+ }
+ }
+ if (LabelsAfterUpdate != null)
+ {
+ LabelsAfterUpdate(toNotify);
+ }
+
+ 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.Modules = new ReadOnlyCollection(
+ mainModList.full_list_of_mod_rows.Values.Select(row => row.Tag as GUIMod).ToList());
+
+ UpdateChangeSetAndConflicts(Main.Instance.CurrentInstance, registry);
+
+ Main.Instance.Wait.AddLogMessage(Properties.Resources.MainModListUpdatingFilters);
+
+ var has_any_updates = gui_mods.Any(mod => mod.HasUpdate);
+ var has_any_installed = gui_mods.Any(mod => mod.IsInstalled);
+ var has_any_replacements = gui_mods.Any(mod => mod.IsInstalled && mod.HasReplacement);
+
+ Util.Invoke(menuStrip2, () =>
+ {
+ FilterCompatibleButton.Text = String.Format(Properties.Resources.MainModListCompatible,
+ mainModList.CountModsByFilter(GUIModFilter.Compatible));
+ FilterInstalledButton.Text = String.Format(Properties.Resources.MainModListInstalled,
+ mainModList.CountModsByFilter(GUIModFilter.Installed));
+ FilterInstalledUpdateButton.Text = String.Format(Properties.Resources.MainModListUpgradeable,
+ mainModList.CountModsByFilter(GUIModFilter.InstalledUpdateAvailable));
+ FilterReplaceableButton.Text = String.Format(Properties.Resources.MainModListReplaceable,
+ mainModList.CountModsByFilter(GUIModFilter.Replaceable));
+ FilterCachedButton.Text = String.Format(Properties.Resources.MainModListCached,
+ mainModList.CountModsByFilter(GUIModFilter.Cached));
+ FilterUncachedButton.Text = String.Format(Properties.Resources.MainModListUncached,
+ mainModList.CountModsByFilter(GUIModFilter.Uncached));
+ FilterNewButton.Text = String.Format(Properties.Resources.MainModListNewlyCompatible,
+ mainModList.CountModsByFilter(GUIModFilter.NewInRepository));
+ FilterNotInstalledButton.Text = String.Format(Properties.Resources.MainModListNotInstalled,
+ mainModList.CountModsByFilter(GUIModFilter.NotInstalled));
+ FilterIncompatibleButton.Text = String.Format(Properties.Resources.MainModListIncompatible,
+ mainModList.CountModsByFilter(GUIModFilter.Incompatible));
+ FilterAllButton.Text = String.Format(Properties.Resources.MainModListAll,
+ mainModList.CountModsByFilter(GUIModFilter.All));
+
+ UpdateAllToolButton.Enabled = has_any_updates;
+ });
+
+ (registry as Registry)?.BuildTagIndex(mainModList.ModuleTags);
+
+ UpdateFilters();
+
+ // Hide update and replacement columns if not needed.
+ // Write it to the configuration, else they are hidden again after a filter change.
+ // After the update / replacement, they are hidden again.
+ Util.Invoke(ModGrid, () =>
+ {
+ ModGrid.Columns["UpdateCol"].Visible = has_any_updates;
+ ModGrid.Columns["AutoInstalled"].Visible = has_any_installed && !Main.Instance.configuration.HiddenColumnNames.Contains("AutoInstalled");
+ ModGrid.Columns["ReplaceCol"].Visible = has_any_replacements;
+ });
+
+ Main.Instance.Wait.AddLogMessage(Properties.Resources.MainModListUpdatingTray);
+
+ if (CloseProgressTab != null)
+ {
+ CloseProgressTab();
+ }
+ Util.Invoke(this, () => ModGrid.Focus());
+ }
+
+ public void MarkModForInstall(string identifier, bool uncheck = false)
+ {
+ Util.Invoke(this, () => _MarkModForInstall(identifier, uncheck));
+ }
+
+ private void _MarkModForInstall(string identifier, bool uninstall)
+ {
+ DataGridViewRow row = mainModList?.full_list_of_mod_rows?[identifier];
+ var mod = (GUIMod)row?.Tag;
+ if (mod?.Identifier == identifier)
+ {
+ mod.SetInstallChecked(row, Installed, !uninstall);
+ }
+ }
+
+ private void ModList_CurrentCellDirtyStateChanged(object sender, EventArgs e)
+ {
+ ModList_CellContentClick(sender, null);
+ }
+
+ private IEnumerable _SortRowsByColumn(IEnumerable rows)
+ {
+ switch (Main.Instance.configuration.SortByColumnIndex)
+ {
+ // XXX: There should be a better way to identify checkbox columns than hardcoding their indices here
+ case 0: case 1:
+ case 2: case 3: return Sort(rows, CheckboxSorter);
+ case 9: return Sort(rows, DownloadSizeSorter);
+ case 10: return Sort(rows, InstallDateSorter);
+ case 11: return Sort(rows, r => (r.Tag as GUIMod)?.DownloadCount ?? 0);
+ }
+ return Sort(rows, DefaultSorter);
+ }
+
+ private IEnumerable Sort(IEnumerable rows, Func sortFunction)
+ {
+ var get_row_mod_name = new Func(row => ((GUIMod)row.Tag).Name);
+ DataGridViewColumnHeaderCell header =
+ this.ModGrid.Columns[Main.Instance.configuration.SortByColumnIndex].HeaderCell;
+
+ // The columns will be sorted by mod name in addition to whatever the current sorting column is
+ if (Main.Instance.configuration.SortDescending)
+ {
+ header.SortGlyphDirection = SortOrder.Descending;
+ return rows.OrderByDescending(sortFunction).ThenBy(get_row_mod_name);
+ }
+
+ header.SortGlyphDirection = SortOrder.Ascending;
+ return rows.OrderBy(sortFunction).ThenBy(get_row_mod_name);
+ }
+
+ ///
+ /// Transforms a DataGridViewRow's into a generic value suitable for sorting.
+ /// Uses this.m_Configuration.SortByColumnIndex to determine which
+ /// field to sort on.
+ ///
+ private string DefaultSorter(DataGridViewRow row)
+ {
+ // changed so that it never returns null
+ var cellVal = row.Cells[Main.Instance.configuration.SortByColumnIndex].Value as string;
+ return string.IsNullOrWhiteSpace(cellVal) ? string.Empty : cellVal;
+ }
+
+ ///
+ /// Transforms a DataGridViewRow's checkbox status into a value suitable for sorting.
+ /// Uses this.m_Configuration.SortByColumnIndex to determine which
+ /// field to sort on.
+ ///
+ private string CheckboxSorter(DataGridViewRow row)
+ {
+ var cell = row.Cells[Main.Instance.configuration.SortByColumnIndex];
+ if (cell.ValueType == typeof(bool))
+ {
+ return (bool)cell.Value ? "a" : "c";
+ }
+ else
+ {
+ // If it's a "-" cell, let it be ordered last
+ // Otherwise put it after the checked boxes
+ return (string)cell.Value == "-" ? "d" : "b";
+ }
+ }
+
+ ///
+ /// Transforms a DataGridViewRow into a long representing the download size,
+ /// suitable for sorting.
+ ///
+ private long DownloadSizeSorter(DataGridViewRow row)
+ {
+ return (row.Tag as GUIMod)?.ToCkanModule()?.download_size ?? 0;
+ }
+
+ ///
+ /// Transforms a DataGridViewRow into a long representing the install date,
+ /// suitable for sorting.
+ /// The grid's default on first click is ascending, and sorting uninstalled mods to
+ /// the top is kind of useless, so we'll make this negative so ascending is useful.
+ ///
+ private long InstallDateSorter(DataGridViewRow row)
+ {
+ return -(row.Tag as GUIMod)?.InstallDate?.Ticks ?? 0;
+ }
+
+ public void ResetFilterAndSelectModOnList(string key)
+ {
+ EditModSearch.Clear();
+ FocusMod(key, true);
+ }
+
+ public GUIMod SelectedModule
+ {
+ get
+ {
+ return ModGrid.SelectedRows.Count == 0
+ ? null
+ : ModGrid.SelectedRows[0]?.Tag as GUIMod;
+ }
+ }
+
+ #region Navigation History
+
+ private void NavInit()
+ {
+ navHistory.OnHistoryChange += NavOnHistoryChange;
+ navHistory.IsReadOnly = false;
+ var currentMod = SelectedModule;
+ if (currentMod != null)
+ navHistory.AddToHistory(currentMod);
+ }
+
+ private void NavUpdateUI()
+ {
+ NavBackwardToolButton.Enabled = navHistory.CanNavigateBackward;
+ NavForwardToolButton.Enabled = navHistory.CanNavigateForward;
+ }
+
+ private void NavSelectMod(GUIMod module)
+ {
+ navHistory.AddToHistory(module);
+ }
+
+ private void NavGoBackward()
+ {
+ if (navHistory.CanNavigateBackward)
+ NavGoToMod(navHistory.NavigateBackward());
+ }
+
+ private void NavGoForward()
+ {
+ if (navHistory.CanNavigateForward)
+ NavGoToMod(navHistory.NavigateForward());
+ }
+
+ private void NavGoToMod(GUIMod module)
+ {
+ // Focussing on a mod also causes navigation, but we don't want
+ // this to affect the history. so we switch to read-only mode.
+ navHistory.IsReadOnly = true;
+ FocusMod(module.Name, true);
+ navHistory.IsReadOnly = false;
+ }
+
+ private void NavOnHistoryChange()
+ {
+ NavUpdateUI();
+ }
+
+ #endregion
+
+ protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
+ {
+ switch (keyData)
+ {
+ case Keys.Control | Keys.F:
+ ActiveControl = EditModSearch;
+ return true;
+
+ case Keys.Control | Keys.Shift | Keys.F:
+ EditModSearch.ExpandCollapse();
+ ActiveControl = EditModSearch;
+ return true;
+
+ case Keys.Control | Keys.S:
+ if (ChangeSet != null && ChangeSet.Any())
+ ApplyToolButton_Click(null, null);
+
+ return true;
+ }
+
+ return base.ProcessCmdKey(ref msg, keyData);
+ }
+
+ public bool AllowClose()
+ {
+ if (Conflicts != null)
+ {
+ if (Conflicts.Any())
+ {
+ // Ask if they want to resolve conflicts
+ string confDescrip = Conflicts
+ .Select(kvp => kvp.Value)
+ .Aggregate((a, b) => $"{a}, {b}");
+ if (!Main.Instance.YesNoDialog(string.Format(Properties.Resources.MainQuitWithConflicts, confDescrip),
+ Properties.Resources.MainQuit,
+ Properties.Resources.MainGoBack))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ // The Conflicts dictionary is empty even when there are unmet dependencies.
+ if (!Main.Instance.YesNoDialog(Properties.Resources.MainQuitWithUnmetDeps,
+ Properties.Resources.MainQuit,
+ Properties.Resources.MainGoBack))
+ {
+ return false;
+ }
+ }
+ }
+ else if (ChangeSet?.Any() ?? false)
+ {
+ // Ask if they want to discard the change set
+ string changeDescrip = ChangeSet
+ .GroupBy(ch => ch.ChangeType, ch => ch.Mod.name)
+ .Select(grp => $"{grp.Key}: "
+ + grp.Aggregate((a, b) => $"{a}, {b}"))
+ .Aggregate((a, b) => $"{a}\r\n{b}");
+ if (!Main.Instance.YesNoDialog(string.Format(Properties.Resources.MainQuitWIthUnappliedChanges, changeDescrip),
+ Properties.Resources.MainQuit,
+ Properties.Resources.MainGoBack))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public void InstanceUpdated(KSP ksp)
+ {
+ ChangeSet = null;
+ Conflicts = null;
+ }
+
+ public async Task UpdateChangeSetAndConflicts(KSP ksp, IRegistryQuerier registry)
+ {
+ IEnumerable full_change_set = null;
+ Dictionary new_conflicts = null;
+
+ bool too_many_provides_thrown = false;
+ var user_change_set = mainModList.ComputeUserChangeSet(registry);
+ try
+ {
+ var module_installer = ModuleInstaller.GetInstance(ksp, Main.Instance.Manager.Cache, Main.Instance.currentUser);
+ full_change_set = mainModList.ComputeChangeSetFromModList(registry, user_change_set, module_installer, ksp.VersionCriteria());
+ }
+ catch (InconsistentKraken k)
+ {
+ // Need to be recomputed due to ComputeChangeSetFromModList possibly changing it with too many provides handling.
+ Main.Instance.AddStatusMessage(k.ShortDescription);
+ user_change_set = mainModList.ComputeUserChangeSet(registry);
+ new_conflicts = ModList.ComputeConflictsFromModList(registry, user_change_set, ksp.VersionCriteria());
+ full_change_set = null;
+ }
+ catch (TooManyModsProvideKraken)
+ {
+ // Can be thrown by ComputeChangeSetFromModList if the user cancels out of it.
+ // We can just rerun it as the ModInfo has been removed.
+ too_many_provides_thrown = true;
+ }
+ catch (DependencyNotSatisfiedKraken k)
+ {
+ Main.Instance.currentUser.RaiseError(
+ Properties.Resources.MainDepNotSatisfied,
+ k.parent,
+ k.module
+ );
+
+ // Uncheck the box
+ MarkModForInstall(k.parent.identifier, true);
+ }
+
+ if (too_many_provides_thrown)
+ {
+ await UpdateChangeSetAndConflicts(ksp, registry);
+ new_conflicts = Conflicts;
+ full_change_set = ChangeSet;
+ }
+
+ Conflicts = new_conflicts;
+ ChangeSet = full_change_set;
+ }
+
+ }
+}
diff --git a/GUI/Controls/ManageMods.resx b/GUI/Controls/ManageMods.resx
new file mode 100644
index 0000000000..52a70e78f9
--- /dev/null
+++ b/GUI/Controls/ManageMods.resx
@@ -0,0 +1,199 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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
+
+
+ 236, 17
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ 351, 17
+
+
+ True
+
+
+ (Default)
+
+ Launch KSP
+ Refresh
+ Add available updates
+ Apply changes
+ Filter (Compatible)
+ Compatible
+ Installed
+ Installed (update available)
+ Replaceable
+ Cached
+ Uncached
+ Newly compatible
+ Not installed
+ Incompatible
+ All
+ Tags
+ Labels
+ Previous selected mod...
+ Next selected mod...
+ Inst
+ Auto-installed
+ Update
+ Replace
+ Name
+ Author
+ Installed version
+ Latest version
+ Max KSP version
+ Download
+ Install date
+ Downloads
+ Description
+ Reinstall
+ Download Contents
+ Purge Contents
+ Filter by author name:
+ 543, 74
+ 170, 26
+ Filter by mod name:
+ 160, 74
+ 170, 26
+ Filter by description:
+ 912, 74
+ 170, 26
+ Labels
+ Edit labels...
+
diff --git a/GUI/Controls/ModInfo.cs b/GUI/Controls/ModInfo.cs
index 27d01e1cb4..55a3f15bb6 100644
--- a/GUI/Controls/ModInfo.cs
+++ b/GUI/Controls/ModInfo.cs
@@ -90,7 +90,7 @@ private KSPManager manager
private void DependsGraphTree_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
{
- Main.Instance.ResetFilterAndSelectModOnList(e.Node.Name);
+ Main.Instance.ManageMods.ResetFilterAndSelectModOnList(e.Node.Name);
}
private void ContentsPreviewTree_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
@@ -213,7 +213,7 @@ private ModuleLabelList ModuleLabels
{
get
{
- return Main.Instance.mainModList.ModuleLabels;
+ return Main.Instance.ManageMods.mainModList.ModuleLabels;
}
}
@@ -221,7 +221,7 @@ private ModuleTagList ModuleTags
{
get
{
- return Main.Instance.mainModList.ModuleTags;
+ return Main.Instance.ManageMods.mainModList.ModuleTags;
}
}
diff --git a/GUI/Dialogs/SettingsDialog.cs b/GUI/Dialogs/SettingsDialog.cs
index 86a96931bb..8e62aa6ea2 100644
--- a/GUI/Dialogs/SettingsDialog.cs
+++ b/GUI/Dialogs/SettingsDialog.cs
@@ -204,7 +204,7 @@ private void PurgeAllMenuItem_Click(object sender, EventArgs e)
Main.Instance.Manager.Cache.RemoveAll();
// forcibly tell all mod rows to re-check cache state
- foreach (DataGridViewRow row in Main.Instance.ModList.Rows)
+ foreach (DataGridViewRow row in Main.Instance.ManageMods.ModGrid.Rows)
{
var mod = row.Tag as GUIMod;
mod?.UpdateIsCached();
diff --git a/GUI/Localization/de-DE/EditModSearch.de-DE.resx b/GUI/Localization/de-DE/EditModSearch.de-DE.resx
new file mode 100644
index 0000000000..2392f0902a
--- /dev/null
+++ b/GUI/Localization/de-DE/EditModSearch.de-DE.resx
@@ -0,0 +1,156 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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
+
+
+ 236, 17
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ 351, 17
+
+
+ True
+
+
+ (Default)
+
+ Nach Autorenname filtern:
+ Nach Modname filtern:
+ Nach Beschreibung filtern:
+
diff --git a/GUI/Localization/de-DE/Main.de-DE.resx b/GUI/Localization/de-DE/Main.de-DE.resx
index 461508c29d..3696bda2da 100644
--- a/GUI/Localization/de-DE/Main.de-DE.resx
+++ b/GUI/Localization/de-DE/Main.de-DE.resx
@@ -181,47 +181,7 @@
Fehler mit dem CKAN Client melden
Fehler mit Mod-Metadaten melden
Über
- KSP starten
- Aktualisieren
- Verfügbare Updates auswählen
- Annehmen
- Filter (Kompatibel)
- Kompatibel
- Installiert
- Aktualisierbar
- Ersetzbar
- Im Cache
- Nicht im Cache
- Neu kompatibel
- Nicht installiert
- Inkompatibel
- Alle
- Kategorien
- Zuvor ausgewählte Mod...
- Danach ausgewählte mod...
- Auto-installiert
- Ersetzen
- Autor
- Installierte Version
- Neueste Version
- Max. KSP Version
- Downloadgröße
- Installationsdatum
- Downloadanzahl
- Kurzbeschreibung
- Neu installieren
- Inhalt herunterladen
- Inhalt löschen
Mods verwalten
- Nach Autorenname filtern:
- 570, 74
- 170, 26
- Nach Modname filtern:
- 180, 74
- 170, 26
- Nach Beschreibung filtern:
- 955, 74
- 170, 26
Änderungen
Statuslog
Wähle Mods
@@ -235,5 +195,4 @@
KSP-Verzeichnis öffnen
CKAN Einstellungen
Beenden
- Labels bearbeiten...
diff --git a/GUI/Localization/de-DE/ManageMods.de-DE.resx b/GUI/Localization/de-DE/ManageMods.de-DE.resx
new file mode 100644
index 0000000000..64a15cac65
--- /dev/null
+++ b/GUI/Localization/de-DE/ManageMods.de-DE.resx
@@ -0,0 +1,185 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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
+
+
+ 236, 17
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ 351, 17
+
+
+ True
+
+
+ (Default)
+
+ KSP starten
+ Aktualisieren
+ Verfügbare Updates auswählen
+ Annehmen
+ Filter (Kompatibel)
+ Kompatibel
+ Installiert
+ Aktualisierbar
+ Ersetzbar
+ Im Cache
+ Nicht im Cache
+ Neu kompatibel
+ Nicht installiert
+ Inkompatibel
+ Alle
+ Kategorien
+ Zuvor ausgewählte Mod...
+ Danach ausgewählte mod...
+ Auto-installiert
+ Ersetzen
+ Autor
+ Installierte Version
+ Neueste Version
+ Max. KSP Version
+ Downloadgröße
+ Installationsdatum
+ Downloadanzahl
+ Kurzbeschreibung
+ Neu installieren
+ Inhalt herunterladen
+ Inhalt löschen
+ Labels bearbeiten...
+
diff --git a/GUI/Localization/zh-CN/EditModSearch.zh-CN.resx b/GUI/Localization/zh-CN/EditModSearch.zh-CN.resx
new file mode 100644
index 0000000000..67095f8396
--- /dev/null
+++ b/GUI/Localization/zh-CN/EditModSearch.zh-CN.resx
@@ -0,0 +1,156 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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
+
+
+ 236, 17
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ 351, 17
+
+
+ True
+
+
+ (Default)
+
+ 按作者名筛选:
+ 按Mod名称筛选:
+ 按描述筛选:
+
diff --git a/GUI/Localization/zh-CN/Main.zh-CN.resx b/GUI/Localization/zh-CN/Main.zh-CN.resx
index fadb9d3b6c..4a8f49d93d 100644
--- a/GUI/Localization/zh-CN/Main.zh-CN.resx
+++ b/GUI/Localization/zh-CN/Main.zh-CN.resx
@@ -183,51 +183,7 @@
报告CKAN客户端的问题
报告Mod元数据的问题
关于
- 启动KSP
- 刷新
- 添加可用更新
- 应用更改
- 筛选 (兼容)
- 兼容
- 已安装
- 已安装 (更新可用)
- 可替换
- 已缓存
- 未缓存
- 新兼容
- 未安装
- 不兼容
- 所有
- 分类
- 标签
- 上一个选中Mod...
- 下一个选中Mod...
- 安装
- 自动安装
- 更新
- 替换
- 名称
- 作者
- 已安装版本
- 最新版本
- 最高KSP版本
- 下载大小
- 安装日期
- 下载量
- 描述
- 重新安装
- 下载内容
- 清除内容
管理模组
- 按作者名筛选:
- 543, 74
- 170, 26
- 按Mod名称筛选:
- 160, 74
- 170, 26
- 按描述筛选:
- 912, 74
- 170, 26
更改列表
状态日志
选择Mod
@@ -243,6 +199,4 @@
打开KSP目录
CKAN设置
退出
- 标签
- 编辑标签...
diff --git a/GUI/Localization/zh-CN/ManageMods.zh-CN.resx b/GUI/Localization/zh-CN/ManageMods.zh-CN.resx
new file mode 100644
index 0000000000..7f51c55087
--- /dev/null
+++ b/GUI/Localization/zh-CN/ManageMods.zh-CN.resx
@@ -0,0 +1,190 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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
+
+
+ 236, 17
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ 351, 17
+
+
+ True
+
+
+ (Default)
+
+ 启动KSP
+ 刷新
+ 添加可用更新
+ 应用更改
+ 筛选 (兼容)
+ 兼容
+ 已安装
+ 已安装 (更新可用)
+ 可替换
+ 已缓存
+ 未缓存
+ 新兼容
+ 未安装
+ 不兼容
+ 所有
+ 分类
+ 标签
+ 上一个选中Mod...
+ 下一个选中Mod...
+ 安装
+ 自动安装
+ 更新
+ 替换
+ 名称
+ 作者
+ 已安装版本
+ 最新版本
+ 最高KSP版本
+ 下载大小
+ 安装日期
+ 下载量
+ 描述
+ 重新安装
+ 下载内容
+ 清除内容
+ 标签
+ 编辑标签...
+
diff --git a/GUI/Main/Main.Designer.cs b/GUI/Main/Main.Designer.cs
index bd93ac68c7..e09b7bdd4b 100644
--- a/GUI/Main/Main.Designer.cs
+++ b/GUI/Main/Main.Designer.cs
@@ -53,66 +53,20 @@ private void InitializeComponent()
this.reportMetadataIssueToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
- this.menuStrip2 = new System.Windows.Forms.MenuStrip();
- this.launchKSPToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.RefreshToolButton = new System.Windows.Forms.ToolStripMenuItem();
- this.UpdateAllToolButton = new System.Windows.Forms.ToolStripMenuItem();
- this.ApplyToolButton = new System.Windows.Forms.ToolStripMenuItem();
- this.FilterToolButton = new System.Windows.Forms.ToolStripMenuItem();
- this.FilterCompatibleButton = new System.Windows.Forms.ToolStripMenuItem();
- this.FilterInstalledButton = new System.Windows.Forms.ToolStripMenuItem();
- this.FilterInstalledUpdateButton = new System.Windows.Forms.ToolStripMenuItem();
- this.FilterReplaceableButton = new System.Windows.Forms.ToolStripMenuItem();
- this.FilterCachedButton = new System.Windows.Forms.ToolStripMenuItem();
- this.FilterUncachedButton = new System.Windows.Forms.ToolStripMenuItem();
- this.FilterNewButton = new System.Windows.Forms.ToolStripMenuItem();
- this.FilterNotInstalledButton = new System.Windows.Forms.ToolStripMenuItem();
- this.FilterIncompatibleButton = new System.Windows.Forms.ToolStripMenuItem();
- this.FilterAllButton = new System.Windows.Forms.ToolStripMenuItem();
- this.FilterLabelsToolButton = new System.Windows.Forms.ToolStripMenuItem();
- this.FilterTagsToolButton = new System.Windows.Forms.ToolStripMenuItem();
- this.NavBackwardToolButton = new System.Windows.Forms.ToolStripMenuItem();
- this.NavForwardToolButton = new System.Windows.Forms.ToolStripMenuItem();
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
- this.ModList = new CKAN.MainModListGUI();
- this.InstallAllCheckbox = new System.Windows.Forms.CheckBox();
- this.Installed = new System.Windows.Forms.DataGridViewCheckBoxColumn();
- this.AutoInstalled = new System.Windows.Forms.DataGridViewCheckBoxColumn();
- this.UpdateCol = new System.Windows.Forms.DataGridViewCheckBoxColumn();
- this.ReplaceCol = new System.Windows.Forms.DataGridViewCheckBoxColumn();
- this.ModName = new System.Windows.Forms.DataGridViewTextBoxColumn();
- this.Author = new System.Windows.Forms.DataGridViewTextBoxColumn();
- this.InstalledVersion = new System.Windows.Forms.DataGridViewTextBoxColumn();
- this.LatestVersion = new System.Windows.Forms.DataGridViewTextBoxColumn();
- this.KSPCompatibility = new System.Windows.Forms.DataGridViewTextBoxColumn();
- this.SizeCol = new System.Windows.Forms.DataGridViewTextBoxColumn();
- this.InstallDate = new System.Windows.Forms.DataGridViewTextBoxColumn();
- this.DownloadCount = new System.Windows.Forms.DataGridViewTextBoxColumn();
- this.Description = new System.Windows.Forms.DataGridViewTextBoxColumn();
- this.ModListContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
this.LabelsContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
- this.ModListHeaderContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
this.modListToolStripSeparator = new System.Windows.Forms.ToolStripSeparator();
this.tagFilterToolStripSeparator = new System.Windows.Forms.ToolStripSeparator();
this.untaggedFilterToolStripSeparator = new System.Windows.Forms.ToolStripSeparator();
- this.labelsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.labelToolStripSeparator = new System.Windows.Forms.ToolStripSeparator();
this.editLabelsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.reinstallToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.downloadContentsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.purgeContentsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ModInfo = new CKAN.ModInfo();
this.StatusLabel = new System.Windows.Forms.ToolStripStatusLabel();
this.StatusInstanceLabel = new System.Windows.Forms.ToolStripStatusLabel();
this.StatusProgress = new System.Windows.Forms.ToolStripProgressBar();
this.MainTabControl = new CKAN.MainTabControl();
this.ManageModsTabPage = new System.Windows.Forms.TabPage();
- this.FilterByAuthorTextBox = new CKAN.HintTextBox();
- this.FilterByAuthorLabel = new System.Windows.Forms.Label();
- this.FilterByNameLabel = new System.Windows.Forms.Label();
- this.FilterByNameTextBox = new CKAN.HintTextBox();
- this.FilterByDescriptionLabel = new System.Windows.Forms.Label();
- this.FilterByDescriptionTextBox = new CKAN.HintTextBox();
+ this.ManageMods = new CKAN.ManageMods();
this.ChangesetTabPage = new System.Windows.Forms.TabPage();
this.Changeset = new CKAN.Changeset();
this.WaitTabPage = new System.Windows.Forms.TabPage();
@@ -140,14 +94,10 @@ private void InitializeComponent()
this.EditModpackTabPage = new System.Windows.Forms.TabPage();
this.EditModpack = new CKAN.EditModpack();
this.menuStrip1.SuspendLayout();
- this.menuStrip2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
this.splitContainer1.Panel1.SuspendLayout();
this.splitContainer1.Panel2.SuspendLayout();
this.splitContainer1.SuspendLayout();
- ((System.ComponentModel.ISupportInitialize)(this.ModList)).BeginInit();
- this.ModListContextMenuStrip.SuspendLayout();
- this.ModListHeaderContextMenuStrip.SuspendLayout();
this.statusStrip1.SuspendLayout();
this.MainTabControl.SuspendLayout();
this.ManageModsTabPage.SuspendLayout();
@@ -356,189 +306,6 @@ private void InitializeComponent()
this.StatusProgress,
});
//
- // menuStrip2
- //
- this.menuStrip2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
- | System.Windows.Forms.AnchorStyles.Right)));
- this.menuStrip2.AutoSize = false;
- this.menuStrip2.Dock = System.Windows.Forms.DockStyle.None;
- this.menuStrip2.ImageScalingSize = new System.Drawing.Size(24, 24);
- this.menuStrip2.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.launchKSPToolStripMenuItem,
- this.RefreshToolButton,
- this.UpdateAllToolButton,
- this.ApplyToolButton,
- this.FilterToolButton,
- this.NavBackwardToolButton,
- this.NavForwardToolButton});
- this.menuStrip2.Location = new System.Drawing.Point(0, 5);
- this.menuStrip2.Name = "menuStrip2";
- this.menuStrip2.Padding = new System.Windows.Forms.Padding(9, 3, 0, 3);
- this.menuStrip2.Size = new System.Drawing.Size(5876, 62);
- this.menuStrip2.TabIndex = 4;
- this.menuStrip2.Text = "menuStrip2";
- //
- // launchKSPToolStripMenuItem
- //
- this.launchKSPToolStripMenuItem.Image = global::CKAN.Properties.Resources.ksp;
- this.launchKSPToolStripMenuItem.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
- this.launchKSPToolStripMenuItem.Name = "launchKSPToolStripMenuItem";
- this.launchKSPToolStripMenuItem.Size = new System.Drawing.Size(146, 56);
- this.launchKSPToolStripMenuItem.Click += new System.EventHandler(this.launchKSPToolStripMenuItem_Click);
- resources.ApplyResources(this.launchKSPToolStripMenuItem, "launchKSPToolStripMenuItem");
- //
- // RefreshToolButton
- //
- this.RefreshToolButton.Image = global::CKAN.Properties.Resources.refresh;
- this.RefreshToolButton.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
- this.RefreshToolButton.Name = "RefreshToolButton";
- this.RefreshToolButton.Size = new System.Drawing.Size(114, 56);
- this.RefreshToolButton.Click += new System.EventHandler(this.RefreshToolButton_Click);
- resources.ApplyResources(this.RefreshToolButton, "RefreshToolButton");
- //
- // UpdateAllToolButton
- //
- this.UpdateAllToolButton.Image = global::CKAN.Properties.Resources.update;
- this.UpdateAllToolButton.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
- this.UpdateAllToolButton.Name = "UpdateAllToolButton";
- this.UpdateAllToolButton.Size = new System.Drawing.Size(232, 56);
- this.UpdateAllToolButton.Click += new System.EventHandler(this.MarkAllUpdatesToolButton_Click);
- resources.ApplyResources(this.UpdateAllToolButton, "UpdateAllToolButton");
- //
- // ApplyToolButton
- //
- this.ApplyToolButton.Image = global::CKAN.Properties.Resources.apply;
- this.ApplyToolButton.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
- this.ApplyToolButton.Name = "ApplyToolButton";
- this.ApplyToolButton.Size = new System.Drawing.Size(173, 56);
- this.ApplyToolButton.Click += new System.EventHandler(this.ApplyToolButton_Click);
- resources.ApplyResources(this.ApplyToolButton, "ApplyToolButton");
- //
- // FilterToolButton
- //
- this.FilterToolButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.FilterCompatibleButton,
- this.FilterInstalledButton,
- this.FilterInstalledUpdateButton,
- this.FilterReplaceableButton,
- this.FilterCachedButton,
- this.FilterUncachedButton,
- this.FilterNewButton,
- this.FilterNotInstalledButton,
- this.FilterIncompatibleButton,
- this.FilterAllButton,
- this.tagFilterToolStripSeparator,
- this.FilterTagsToolButton,
- this.FilterLabelsToolButton});
- this.FilterToolButton.DropDown.Opening += new System.ComponentModel.CancelEventHandler(FilterToolButton_DropDown_Opening);
- this.FilterToolButton.Image = global::CKAN.Properties.Resources.filter;
- this.FilterToolButton.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
- this.FilterToolButton.Name = "FilterToolButton";
- this.FilterToolButton.Size = new System.Drawing.Size(201, 56);
- resources.ApplyResources(this.FilterToolButton, "FilterToolButton");
- //
- // FilterCompatibleButton
- //
- this.FilterCompatibleButton.Name = "FilterCompatibleButton";
- this.FilterCompatibleButton.Size = new System.Drawing.Size(307, 30);
- this.FilterCompatibleButton.Click += new System.EventHandler(this.FilterCompatibleButton_Click);
- resources.ApplyResources(this.FilterCompatibleButton, "FilterCompatibleButton");
- //
- // FilterInstalledButton
- //
- this.FilterInstalledButton.Name = "FilterInstalledButton";
- this.FilterInstalledButton.Size = new System.Drawing.Size(307, 30);
- this.FilterInstalledButton.Click += new System.EventHandler(this.FilterInstalledButton_Click);
- resources.ApplyResources(this.FilterInstalledButton, "FilterInstalledButton");
- //
- // FilterInstalledUpdateButton
- //
- this.FilterInstalledUpdateButton.Name = "FilterInstalledUpdateButton";
- this.FilterInstalledUpdateButton.Size = new System.Drawing.Size(307, 30);
- this.FilterInstalledUpdateButton.Click += new System.EventHandler(this.FilterInstalledUpdateButton_Click);
- resources.ApplyResources(this.FilterInstalledUpdateButton, "FilterInstalledUpdateButton");
- //
- // FilterReplaceableButton
- //
- this.FilterReplaceableButton.Name = "FilterReplaceableButton";
- this.FilterReplaceableButton.Size = new System.Drawing.Size(307, 30);
- this.FilterReplaceableButton.Click += new System.EventHandler(this.FilterReplaceableButton_Click);
- resources.ApplyResources(this.FilterReplaceableButton, "FilterReplaceableButton");
- //
- // FilterCachedButton
- //
- this.FilterCachedButton.Name = "FilterCachedButton";
- this.FilterCachedButton.Size = new System.Drawing.Size(307, 30);
- this.FilterCachedButton.Click += new System.EventHandler(this.FilterCachedButton_Click);
- resources.ApplyResources(this.FilterCachedButton, "FilterCachedButton");
- //
- // FilterUncachedButton
- //
- this.FilterUncachedButton.Name = "FilterUncachedButton";
- this.FilterUncachedButton.Size = new System.Drawing.Size(307, 30);
- this.FilterUncachedButton.Click += new System.EventHandler(this.FilterUncachedButton_Click);
- resources.ApplyResources(this.FilterUncachedButton, "FilterUncachedButton");
- //
- // FilterNewButton
- //
- this.FilterNewButton.Name = "FilterNewButton";
- this.FilterNewButton.Size = new System.Drawing.Size(307, 30);
- this.FilterNewButton.Click += new System.EventHandler(this.FilterNewButton_Click);
- resources.ApplyResources(this.FilterNewButton, "FilterNewButton");
- //
- // FilterNotInstalledButton
- //
- this.FilterNotInstalledButton.Name = "FilterNotInstalledButton";
- this.FilterNotInstalledButton.Size = new System.Drawing.Size(307, 30);
- this.FilterNotInstalledButton.Click += new System.EventHandler(this.FilterNotInstalledButton_Click);
- resources.ApplyResources(this.FilterNotInstalledButton, "FilterNotInstalledButton");
- //
- // FilterIncompatibleButton
- //
- this.FilterIncompatibleButton.Name = "FilterIncompatibleButton";
- this.FilterIncompatibleButton.Size = new System.Drawing.Size(307, 30);
- this.FilterIncompatibleButton.Click += new System.EventHandler(this.FilterIncompatibleButton_Click);
- resources.ApplyResources(this.FilterIncompatibleButton, "FilterIncompatibleButton");
- //
- // FilterAllButton
- //
- this.FilterAllButton.Name = "FilterAllButton";
- this.FilterAllButton.Size = new System.Drawing.Size(307, 30);
- this.FilterAllButton.Click += new System.EventHandler(this.FilterAllButton_Click);
- resources.ApplyResources(this.FilterAllButton, "FilterAllButton");
- //
- // FilterTagsToolButton
- //
- this.FilterTagsToolButton.Name = "FilterTagsToolButton";
- this.FilterTagsToolButton.Size = new System.Drawing.Size(179, 22);
- resources.ApplyResources(this.FilterTagsToolButton, "FilterTagsToolButton");
- this.FilterTagsToolButton.DropDown.Opening += new System.ComponentModel.CancelEventHandler(FilterTagsToolButton_DropDown_Opening);
- //
- // FilterLabelsToolButton
- //
- this.FilterLabelsToolButton.Name = "FilterLabelsToolButton";
- this.FilterLabelsToolButton.Size = new System.Drawing.Size(179, 22);
- resources.ApplyResources(this.FilterLabelsToolButton, "FilterLabelsToolButton");
- this.FilterLabelsToolButton.DropDown.Opening += new System.ComponentModel.CancelEventHandler(FilterLabelsToolButton_DropDown_Opening);
- //
- // NavBackwardToolButton
- //
- this.NavBackwardToolButton.Image = global::CKAN.Properties.Resources.backward;
- this.NavBackwardToolButton.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
- this.NavBackwardToolButton.Name = "NavBackwardToolButton";
- this.NavBackwardToolButton.Size = new System.Drawing.Size(44, 56);
- this.NavBackwardToolButton.Click += new System.EventHandler(this.NavBackwardToolButton_Click);
- resources.ApplyResources(this.NavBackwardToolButton, "NavBackwardToolButton");
- //
- // NavForwardToolButton
- //
- this.NavForwardToolButton.Image = global::CKAN.Properties.Resources.forward;
- this.NavForwardToolButton.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
- this.NavForwardToolButton.Name = "NavForwardToolButton";
- this.NavForwardToolButton.Size = new System.Drawing.Size(44, 56);
- this.NavForwardToolButton.Click += new System.EventHandler(this.NavForwardToolButton_Click);
- resources.ApplyResources(this.NavForwardToolButton, "NavForwardToolButton");
- //
// splitContainer1
//
this.splitContainer1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
@@ -564,221 +331,6 @@ private void InitializeComponent()
this.splitContainer1.SplitterWidth = 10;
this.splitContainer1.TabIndex = 1;
//
- // ModList
- //
- this.ModList.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
- | System.Windows.Forms.AnchorStyles.Left)
- | System.Windows.Forms.AnchorStyles.Right)));
- this.ModList.AllowUserToAddRows = false;
- this.ModList.AllowUserToDeleteRows = false;
- this.ModList.AllowUserToResizeRows = false;
- this.ModList.BackgroundColor = System.Drawing.SystemColors.Window;
- this.ModList.EnableHeadersVisualStyles = false;
- this.ModList.ColumnHeadersDefaultCellStyle.BackColor = System.Drawing.SystemColors.Control;
- this.ModList.ColumnHeadersDefaultCellStyle.ForeColor = System.Drawing.SystemColors.ControlText;
- this.ModList.DefaultCellStyle.ForeColor = System.Drawing.SystemColors.WindowText;
- this.ModList.CellBorderStyle = System.Windows.Forms.DataGridViewCellBorderStyle.None;
- this.ModList.ColumnHeadersBorderStyle = System.Windows.Forms.DataGridViewHeaderBorderStyle.None;
- this.ModList.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
- this.ModList.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
- this.Installed,
- this.AutoInstalled,
- this.UpdateCol,
- this.ReplaceCol,
- this.ModName,
- this.Author,
- this.InstalledVersion,
- this.LatestVersion,
- this.KSPCompatibility,
- this.SizeCol,
- this.InstallDate,
- this.DownloadCount,
- this.Description});
- this.ModList.Location = new System.Drawing.Point(0, 111);
- this.ModList.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
- this.ModList.MultiSelect = false;
- this.ModList.Name = "ModList";
- this.ModList.RowHeadersVisible = false;
- this.ModList.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
- this.ModList.Size = new System.Drawing.Size(1536, 837);
- this.ModList.StandardTab = true;
- this.ModList.TabIndex = 12;
- this.ModList.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.ModList_CellContentClick);
- this.ModList.CellMouseDoubleClick += new System.Windows.Forms.DataGridViewCellMouseEventHandler(this.ModList_CellMouseDoubleClick);
- this.ModList.ColumnHeaderMouseClick += new System.Windows.Forms.DataGridViewCellMouseEventHandler(this.ModList_HeaderMouseClick);
- this.ModList.SelectionChanged += new System.EventHandler(this.ModList_SelectedIndexChanged);
- this.ModList.KeyDown += new System.Windows.Forms.KeyEventHandler(this.ModList_KeyDown);
- this.ModList.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.ModList_KeyPress);
- this.ModList.MouseDown += new System.Windows.Forms.MouseEventHandler(this.ModList_MouseDown);
- this.ModList.GotFocus += new System.EventHandler(this.ModList_GotFocus);
- this.ModList.LostFocus += new System.EventHandler(this.ModList_LostFocus);
- //
- // Installed
- //
- this.Installed.Name = "Installed";
- this.Installed.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
- this.Installed.DefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter;
- this.Installed.Width = 50;
- resources.ApplyResources(this.Installed, "Installed");
- //
- // AutoInstalled
- //
- this.AutoInstalled.Name = "AutoInstalled";
- this.AutoInstalled.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
- this.AutoInstalled.DefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter;
- this.AutoInstalled.Width = 50;
- resources.ApplyResources(this.AutoInstalled, "AutoInstalled");
- //
- // UpdateCol
- //
- this.UpdateCol.Name = "UpdateCol";
- this.UpdateCol.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
- this.UpdateCol.DefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter;
- this.UpdateCol.Width = 46;
- resources.ApplyResources(this.UpdateCol, "UpdateCol");
- //
- // ReplaceCol
- //
- this.ReplaceCol.Name = "ReplaceCol";
- this.ReplaceCol.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
- this.ReplaceCol.DefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter;
- this.ReplaceCol.Width = 46;
- resources.ApplyResources(this.ReplaceCol, "ReplaceCol");
- //
- // ModName
- //
- this.ModName.Name = "ModName";
- this.ModName.ReadOnly = true;
- this.ModName.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
- this.ModName.Width = 250;
- resources.ApplyResources(this.ModName, "ModName");
- //
- // Author
- //
- this.Author.Name = "Author";
- this.Author.ReadOnly = true;
- this.Author.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
- this.Author.Width = 120;
- resources.ApplyResources(this.Author, "Author");
- //
- // InstalledVersion
- //
- this.InstalledVersion.Name = "InstalledVersion";
- this.InstalledVersion.ReadOnly = true;
- this.InstalledVersion.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
- this.InstalledVersion.Width = 70;
- resources.ApplyResources(this.InstalledVersion, "InstalledVersion");
- //
- // LatestVersion
- //
- this.LatestVersion.Name = "LatestVersion";
- this.LatestVersion.ReadOnly = true;
- this.LatestVersion.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
- this.LatestVersion.Width = 70;
- resources.ApplyResources(this.LatestVersion, "LatestVersion");
- //
- // KSPCompatibility
- //
- this.KSPCompatibility.Name = "KSPCompatibility";
- this.KSPCompatibility.ReadOnly = true;
- this.KSPCompatibility.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
- this.KSPCompatibility.Width = 78;
- resources.ApplyResources(this.KSPCompatibility, "KSPCompatibility");
- //
- // SizeCol
- //
- this.SizeCol.Name = "SizeCol";
- this.SizeCol.ReadOnly = true;
- this.SizeCol.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
- this.SizeCol.DefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleRight;
- resources.ApplyResources(this.SizeCol, "SizeCol");
- //
- // InstallDate
- //
- this.InstallDate.Name = "InstallDate";
- this.InstallDate.ReadOnly = true;
- this.InstallDate.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
- this.InstallDate.Width = 140;
- resources.ApplyResources(this.InstallDate, "InstallDate");
- //
- // DownloadCount
- //
- this.DownloadCount.Name = "DownloadCount";
- this.DownloadCount.ReadOnly = true;
- this.DownloadCount.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
- this.DownloadCount.DefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleRight;
- this.DownloadCount.Width = 70;
- resources.ApplyResources(this.DownloadCount, "DownloadCount");
- //
- // Description
- //
- this.Description.Name = "Description";
- this.Description.ReadOnly = true;
- this.Description.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
- this.Description.Width = 821;
- resources.ApplyResources(this.Description, "Description");
- //
- // ModListContextMenuStrip
- //
- this.ModListContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.labelsToolStripMenuItem,
- this.modListToolStripSeparator,
- this.reinstallToolStripMenuItem,
- this.downloadContentsToolStripMenuItem,
- this.purgeContentsToolStripMenuItem});
- this.ModListContextMenuStrip.Name = "ModListContextMenuStrip";
- this.ModListContextMenuStrip.Size = new System.Drawing.Size(180, 70);
- //
- // labelsToolStripMenuItem
- //
- this.labelsToolStripMenuItem.Name = "labelsToolStripMenuItem";
- this.labelsToolStripMenuItem.Size = new System.Drawing.Size(179, 22);
- this.labelsToolStripMenuItem.DropDown = this.LabelsContextMenuStrip;
- resources.ApplyResources(this.labelsToolStripMenuItem, "labelsToolStripMenuItem");
- //
- // reinstallToolStripMenuItem
- //
- this.reinstallToolStripMenuItem.Name = "reinstallToolStripMenuItem";
- this.reinstallToolStripMenuItem.Size = new System.Drawing.Size(179, 22);
- this.reinstallToolStripMenuItem.Click += new System.EventHandler(this.reinstallToolStripMenuItem_Click);
- resources.ApplyResources(this.reinstallToolStripMenuItem, "reinstallToolStripMenuItem");
- //
- // downloadContentsToolStripMenuItem
- //
- this.downloadContentsToolStripMenuItem.Name = "downloadContentsToolStripMenuItem";
- this.downloadContentsToolStripMenuItem.Size = new System.Drawing.Size(179, 22);
- this.downloadContentsToolStripMenuItem.Click += new System.EventHandler(this.downloadContentsToolStripMenuItem_Click);
- resources.ApplyResources(this.downloadContentsToolStripMenuItem, "downloadContentsToolStripMenuItem");
- //
- // purgeContentsToolStripMenuItem
- //
- this.purgeContentsToolStripMenuItem.Name = "purgeContentsToolStripMenuItem";
- this.purgeContentsToolStripMenuItem.Size = new System.Drawing.Size(179, 22);
- this.purgeContentsToolStripMenuItem.Click += new System.EventHandler(this.purgeContentsToolStripMenuItem_Click);
- resources.ApplyResources(this.purgeContentsToolStripMenuItem, "purgeContentsToolStripMenuItem");
- //
- // LabelsContextMenuStrip
- //
- this.LabelsContextMenuStrip.Name = "LabelsContextMenuStrip";
- this.LabelsContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.editLabelsToolStripMenuItem});
- this.LabelsContextMenuStrip.Size = new System.Drawing.Size(180, 70);
- this.LabelsContextMenuStrip.Opening += new System.ComponentModel.CancelEventHandler(LabelsContextMenuStrip_Opening);
- //
- // editLabelsToolStripMenuItem
- //
- this.editLabelsToolStripMenuItem.Name = "editLabelsToolStripMenuItem";
- this.editLabelsToolStripMenuItem.Size = new System.Drawing.Size(179, 22);
- this.editLabelsToolStripMenuItem.Click += new System.EventHandler(this.editLabelsToolStripMenuItem_Click);
- resources.ApplyResources(this.editLabelsToolStripMenuItem, "editLabelsToolStripMenuItem");
- //
- // ModListHeaderContextMenuStrip
- //
- this.ModListHeaderContextMenuStrip.Name = "ModListHeaderContextMenuStrip";
- this.ModListHeaderContextMenuStrip.AutoSize = true;
- this.ModListHeaderContextMenuStrip.ShowCheckMargin = true;
- this.ModListHeaderContextMenuStrip.ItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(ModListHeaderContextMenuStrip_ItemClicked);
- //
// ModInfo
//
this.ModInfo.Dock = System.Windows.Forms.DockStyle.Fill;
@@ -841,15 +393,7 @@ private void InitializeComponent()
// ManageModsTabPage
//
this.ManageModsTabPage.BackColor = System.Drawing.SystemColors.Control;
- this.ManageModsTabPage.Controls.Add(this.InstallAllCheckbox);
- this.ManageModsTabPage.Controls.Add(this.FilterByAuthorTextBox);
- this.ManageModsTabPage.Controls.Add(this.FilterByAuthorLabel);
- this.ManageModsTabPage.Controls.Add(this.FilterByNameLabel);
- this.ManageModsTabPage.Controls.Add(this.FilterByNameTextBox);
- this.ManageModsTabPage.Controls.Add(this.FilterByDescriptionLabel);
- this.ManageModsTabPage.Controls.Add(this.FilterByDescriptionTextBox);
- this.ManageModsTabPage.Controls.Add(this.menuStrip2);
- this.ManageModsTabPage.Controls.Add(this.ModList);
+ this.ManageModsTabPage.Controls.Add(this.ManageMods);
this.ManageModsTabPage.Location = new System.Drawing.Point(4, 29);
this.ManageModsTabPage.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.ManageModsTabPage.Name = "ManageModsTabPage";
@@ -857,78 +401,22 @@ private void InitializeComponent()
this.ManageModsTabPage.Size = new System.Drawing.Size(1536, 948);
this.ManageModsTabPage.TabIndex = 3;
resources.ApplyResources(this.ManageModsTabPage, "ManageModsTabPage");
- //
- // InstallAllCheckbox
- //
- this.InstallAllCheckbox.Location = new System.Drawing.Point(4, 118);
- this.InstallAllCheckbox.Size = new System.Drawing.Size(20, 20);
- this.InstallAllCheckbox.Checked = true;
- this.InstallAllCheckbox.CheckedChanged += new System.EventHandler(this.InstallAllCheckbox_CheckChanged);
- this.InstallAllCheckbox.TabIndex = 11;
- this.InstallAllCheckbox.TabStop = false;
- //
- // FilterByAuthorTextBox
- //
- this.FilterByAuthorTextBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
- this.FilterByAuthorTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
- this.FilterByAuthorTextBox.Name = "FilterByAuthorTextBox";
- this.FilterByAuthorTextBox.TabIndex = 8;
- this.FilterByAuthorTextBox.TextChanged += new System.EventHandler(this.FilterByAuthorTextBox_TextChanged);
- this.FilterByAuthorTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.FilterTextBox_KeyDown);
- resources.ApplyResources(this.FilterByAuthorTextBox, "FilterByAuthorTextBox");
- //
- // FilterByAuthorLabel
- //
- this.FilterByAuthorLabel.AutoSize = true;
- this.FilterByAuthorLabel.BackColor = System.Drawing.Color.Transparent;
- this.FilterByAuthorLabel.Location = new System.Drawing.Point(372, 77);
- this.FilterByAuthorLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
- this.FilterByAuthorLabel.Name = "FilterByAuthorLabel";
- this.FilterByAuthorLabel.Size = new System.Drawing.Size(162, 20);
- this.FilterByAuthorLabel.TabIndex = 7;
- resources.ApplyResources(this.FilterByAuthorLabel, "FilterByAuthorLabel");
- //
- // FilterByNameLabel
- //
- this.FilterByNameLabel.AutoSize = true;
- this.FilterByNameLabel.BackColor = System.Drawing.Color.Transparent;
- this.FilterByNameLabel.Location = new System.Drawing.Point(6, 77);
- this.FilterByNameLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
- this.FilterByNameLabel.Name = "FilterByNameLabel";
- this.FilterByNameLabel.Size = new System.Drawing.Size(147, 20);
- this.FilterByNameLabel.TabIndex = 5;
- resources.ApplyResources(this.FilterByNameLabel, "FilterByNameLabel");
- //
- // FilterByNameTextBox
- //
- this.FilterByNameTextBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
- this.FilterByNameTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
- this.FilterByNameTextBox.Name = "FilterByNameTextBox";
- this.FilterByNameTextBox.TabIndex = 6;
- this.FilterByNameTextBox.TextChanged += new System.EventHandler(this.FilterByNameTextBox_TextChanged);
- this.FilterByNameTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.FilterTextBox_KeyDown);
- resources.ApplyResources(this.FilterByNameTextBox, "FilterByNameTextBox");
- //
- // FilterByDescriptionLabel
- //
- this.FilterByDescriptionLabel.AutoSize = true;
- this.FilterByDescriptionLabel.BackColor = System.Drawing.Color.Transparent;
- this.FilterByDescriptionLabel.Location = new System.Drawing.Point(754, 77);
- this.FilterByDescriptionLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
- this.FilterByDescriptionLabel.Name = "FilterByDescriptionLabel";
- this.FilterByDescriptionLabel.Size = new System.Drawing.Size(149, 20);
- this.FilterByDescriptionLabel.TabIndex = 9;
- resources.ApplyResources(this.FilterByDescriptionLabel, "FilterByDescriptionLabel");
- //
- // FilterByDescriptionTextBox
- //
- this.FilterByDescriptionTextBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
- this.FilterByDescriptionTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
- this.FilterByDescriptionTextBox.Name = "FilterByDescriptionTextBox";
- this.FilterByDescriptionTextBox.TabIndex = 10;
- this.FilterByDescriptionTextBox.TextChanged += new System.EventHandler(this.FilterByDescriptionTextBox_TextChanged);
- this.FilterByDescriptionTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.FilterTextBox_KeyDown);
- resources.ApplyResources(this.FilterByDescriptionTextBox, "FilterByDescriptionTextBox");
+ //
+ // ManageMods
+ //
+ this.ManageMods.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.ManageMods.Location = new System.Drawing.Point(0, 0);
+ this.ManageMods.Margin = new System.Windows.Forms.Padding(0,0,0,0);
+ this.ManageMods.Padding = new System.Windows.Forms.Padding(0,0,0,0);
+ this.ManageMods.Name = "ManageMods";
+ this.ManageMods.Size = new System.Drawing.Size(500, 500);
+ this.ManageMods.TabIndex = 4;
+ this.ManageMods.OnSelectedModuleChanged += ManageMods_OnSelectedModuleChanged;
+ this.ManageMods.OnChangeSetChanged += ManageMods_OnChangeSetChanged;
+ this.ManageMods.OnRegistryChanged += ManageMods_OnRegistryChanged;
+ this.ManageMods.OpenProgressTab += ManageMods_OpenProgressTab;
+ this.ManageMods.CloseProgressTab += ManageMods_CloseProgressTab;
+ this.ManageMods.LabelsAfterUpdate += ManageMods_LabelsAfterUpdate;
//
// ChangesetTabPage
//
@@ -1135,12 +623,11 @@ private void InitializeComponent()
this.openCKANToolStripMenuItem.Click += new System.EventHandler(this.openCKANToolStripMenuItem_Click);
resources.ApplyResources(this.openCKANToolStripMenuItem, "openCKANToolStripMenuItem");
//
- //
// openKSPToolStripMenuItem
//
this.openKSPToolStripMenuItem.Name = "launchKSPToolStripMenuItem";
this.openKSPToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
- this.openKSPToolStripMenuItem.Click += new System.EventHandler(this.launchKSPToolStripMenuItem_Click);
+ this.openKSPToolStripMenuItem.Click += new System.EventHandler(this.openKSPToolStripMenuItem_Click);
resources.ApplyResources(this.openKSPToolStripMenuItem, "openKSPToolStripMenuItem");
//
// openKSPDirectoryToolStripMenuItem1
@@ -1187,15 +674,10 @@ private void InitializeComponent()
resources.ApplyResources(this, "$this");
this.menuStrip1.ResumeLayout(false);
this.menuStrip1.PerformLayout();
- this.menuStrip2.ResumeLayout(false);
- this.menuStrip2.PerformLayout();
this.splitContainer1.Panel1.ResumeLayout(false);
this.splitContainer1.Panel2.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
this.splitContainer1.ResumeLayout(false);
- ((System.ComponentModel.ISupportInitialize)(this.ModList)).EndInit();
- this.ModListContextMenuStrip.ResumeLayout(false);
- this.ModListHeaderContextMenuStrip.ResumeLayout(false);
this.statusStrip1.ResumeLayout(false);
this.statusStrip1.PerformLayout();
this.MainTabControl.ResumeLayout(false);
@@ -1245,70 +727,24 @@ private void InitializeComponent()
private System.Windows.Forms.ToolStripMenuItem reportMetadataIssueToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem;
private System.Windows.Forms.StatusStrip statusStrip1;
- private System.Windows.Forms.MenuStrip menuStrip2;
- private System.Windows.Forms.ToolStripMenuItem launchKSPToolStripMenuItem;
- private System.Windows.Forms.ToolStripMenuItem RefreshToolButton;
- private System.Windows.Forms.ToolStripMenuItem UpdateAllToolButton;
- private System.Windows.Forms.ToolStripMenuItem ApplyToolButton;
- private System.Windows.Forms.ToolStripMenuItem FilterToolButton;
- private System.Windows.Forms.ToolStripMenuItem FilterCompatibleButton;
- private System.Windows.Forms.ToolStripMenuItem FilterInstalledButton;
- private System.Windows.Forms.ToolStripMenuItem FilterInstalledUpdateButton;
- private System.Windows.Forms.ToolStripMenuItem FilterReplaceableButton;
- private System.Windows.Forms.ToolStripMenuItem FilterCachedButton;
- private System.Windows.Forms.ToolStripMenuItem FilterUncachedButton;
- private System.Windows.Forms.ToolStripMenuItem FilterNewButton;
- private System.Windows.Forms.ToolStripMenuItem FilterNotInstalledButton;
- private System.Windows.Forms.ToolStripMenuItem FilterIncompatibleButton;
- private System.Windows.Forms.ToolStripMenuItem FilterAllButton;
- private System.Windows.Forms.ToolStripMenuItem FilterLabelsToolButton;
- private System.Windows.Forms.ToolStripMenuItem FilterTagsToolButton;
- private System.Windows.Forms.ToolStripMenuItem NavBackwardToolButton;
- private System.Windows.Forms.ToolStripMenuItem NavForwardToolButton;
private System.Windows.Forms.SplitContainer splitContainer1;
- public CKAN.MainModListGUI ModList;
- private System.Windows.Forms.CheckBox InstallAllCheckbox;
- private System.Windows.Forms.DataGridViewCheckBoxColumn Installed;
- private System.Windows.Forms.DataGridViewCheckBoxColumn AutoInstalled;
- private System.Windows.Forms.DataGridViewCheckBoxColumn UpdateCol;
- private System.Windows.Forms.DataGridViewCheckBoxColumn ReplaceCol;
- private System.Windows.Forms.DataGridViewTextBoxColumn ModName;
- private System.Windows.Forms.DataGridViewTextBoxColumn Author;
- private System.Windows.Forms.DataGridViewTextBoxColumn InstalledVersion;
- private System.Windows.Forms.DataGridViewTextBoxColumn LatestVersion;
- private System.Windows.Forms.DataGridViewTextBoxColumn KSPCompatibility;
- private System.Windows.Forms.DataGridViewTextBoxColumn SizeCol;
- private System.Windows.Forms.DataGridViewTextBoxColumn InstallDate;
- private System.Windows.Forms.DataGridViewTextBoxColumn DownloadCount;
- private System.Windows.Forms.DataGridViewTextBoxColumn Description;
- private System.Windows.Forms.ContextMenuStrip ModListContextMenuStrip;
private System.Windows.Forms.ToolStripSeparator modListToolStripSeparator;
private System.Windows.Forms.ToolStripSeparator tagFilterToolStripSeparator;
private System.Windows.Forms.ToolStripSeparator untaggedFilterToolStripSeparator;
private System.Windows.Forms.ContextMenuStrip LabelsContextMenuStrip;
- private System.Windows.Forms.ContextMenuStrip ModListHeaderContextMenuStrip;
- private System.Windows.Forms.ToolStripMenuItem labelsToolStripMenuItem;
private System.Windows.Forms.ToolStripSeparator labelToolStripSeparator;
private System.Windows.Forms.ToolStripMenuItem editLabelsToolStripMenuItem;
- private System.Windows.Forms.ToolStripMenuItem reinstallToolStripMenuItem;
- private System.Windows.Forms.ToolStripMenuItem downloadContentsToolStripMenuItem;
- private System.Windows.Forms.ToolStripMenuItem purgeContentsToolStripMenuItem;
private CKAN.ModInfo ModInfo;
private System.Windows.Forms.ToolStripStatusLabel StatusLabel;
private System.Windows.Forms.ToolStripStatusLabel StatusInstanceLabel;
private System.Windows.Forms.ToolStripProgressBar StatusProgress;
private CKAN.MainTabControl MainTabControl;
private System.Windows.Forms.TabPage ManageModsTabPage;
- private CKAN.HintTextBox FilterByAuthorTextBox;
- private System.Windows.Forms.Label FilterByAuthorLabel;
- private System.Windows.Forms.Label FilterByNameLabel;
- private CKAN.HintTextBox FilterByNameTextBox;
- private System.Windows.Forms.Label FilterByDescriptionLabel;
- private CKAN.HintTextBox FilterByDescriptionTextBox;
+ public CKAN.ManageMods ManageMods;
private System.Windows.Forms.TabPage ChangesetTabPage;
private CKAN.Changeset Changeset;
private System.Windows.Forms.TabPage WaitTabPage;
- private CKAN.Wait Wait;
+ public CKAN.Wait Wait;
private System.Windows.Forms.TabPage ChooseRecommendedModsTabPage;
private CKAN.ChooseRecommendedMods ChooseRecommendedMods;
private System.Windows.Forms.TabPage ChooseProvidedModsTabPage;
diff --git a/GUI/Main/Main.cs b/GUI/Main/Main.cs
index fc1bc546ef..7d09994666 100644
--- a/GUI/Main/Main.cs
+++ b/GUI/Main/Main.cs
@@ -49,117 +49,13 @@ public KSPManager Manager
private bool needRegistrySave = false;
- public MainModList mainModList { get; }
-
- public NavigationHistory navHistory;
-
public string[] commandLineArgs;
public GUIUser currentUser;
- private Timer filterTimer;
-
private bool enableTrayIcon;
private bool minimizeToTray;
- private DateTime lastSearchTime;
- private string lastSearchKey;
-
- private IEnumerable currentChangeSet;
- private Dictionary conflicts;
-
- private IEnumerable ChangeSet
- {
- get { return currentChangeSet; }
- set
- {
- var orig = currentChangeSet;
- currentChangeSet = value;
- if (!ReferenceEquals(orig, value))
- ChangeSetUpdated();
- }
- }
-
- private Dictionary Conflicts
- {
- get { return conflicts; }
- set
- {
- var orig = conflicts;
- conflicts = value;
- if (orig != value)
- ConflictsUpdated(orig);
- }
- }
-
- private void ConflictsUpdated(Dictionary prevConflicts)
- {
- if (Conflicts == null)
- {
- // Clear status bar if no conflicts
- AddStatusMessage("");
- }
-
- if (prevConflicts != null)
- {
- // Mark old conflicts as non-conflicted
- // (rows that are _still_ conflicted will be marked as such in the next loop)
- foreach (GUIMod guiMod in prevConflicts.Keys)
- {
- DataGridViewRow row = mainModList.full_list_of_mod_rows[guiMod.Identifier];
-
- foreach (DataGridViewCell cell in row.Cells)
- {
- cell.ToolTipText = null;
- }
- mainModList.ReapplyLabels(guiMod, false, CurrentInstance.Name);
- if (row.Visible)
- {
- ModList.InvalidateRow(row.Index);
- }
- }
- }
- if (Conflicts != null)
- {
- // Mark current conflicts as conflicted
- foreach (var kvp in Conflicts)
- {
- GUIMod guiMod = kvp.Key;
- DataGridViewRow row = mainModList.full_list_of_mod_rows[guiMod.Identifier];
- string conflict_text = kvp.Value;
-
- foreach (DataGridViewCell cell in row.Cells)
- {
- cell.ToolTipText = conflict_text;
- }
- row.DefaultCellStyle.BackColor = mainModList.GetRowBackground(guiMod, true, CurrentInstance.Name);
- if (row.Visible)
- {
- ModList.InvalidateRow(row.Index);
- }
- }
- }
- }
-
- private void ChangeSetUpdated()
- {
- if (ChangeSet != null && ChangeSet.Any())
- {
- tabController.ShowTab("ChangesetTabPage", 1, false);
- UpdateChangesDialog(ChangeSet.ToList());
- ApplyToolButton.Enabled = true;
- auditRecommendationsMenuItem.Enabled = false;
- }
- else
- {
- tabController.HideTab("ChangesetTabPage");
- ApplyToolButton.Enabled = false;
- Wait.RetryEnabled = false;
- auditRecommendationsMenuItem.Enabled = true;
- InstallAllCheckbox.Checked = true;
- }
- }
-
public Main(string[] cmdlineArgs, KSPManager mgr, bool showConsole)
{
log.Info("Starting the GUI");
@@ -189,30 +85,18 @@ public Main(string[] cmdlineArgs, KSPManager mgr, bool showConsole)
manager = mgr ?? new KSPManager(currentUser);
controlFactory = new ControlFactory();
- mainModList = new MainModList(source => UpdateFilters(this), currentUser);
-
- // History is read-only until the UI is started. We switch
- // out of it at the end of OnLoad() when we call NavInit().
- navHistory = new NavigationHistory { IsReadOnly = true };
// React when the user clicks a tag or filter link in mod info
- ModInfo.OnChangeFilter += Filter;
+ ModInfo.OnChangeFilter += ManageMods.Filter;
// Replace mono's broken, ugly toolstrip renderer
if (Platform.IsMono)
{
menuStrip1.Renderer = new FlatToolStripRenderer();
- menuStrip2.Renderer = new FlatToolStripRenderer();
fileToolStripMenuItem.DropDown.Renderer = new FlatToolStripRenderer();
settingsToolStripMenuItem.DropDown.Renderer = new FlatToolStripRenderer();
helpToolStripMenuItem.DropDown.Renderer = new FlatToolStripRenderer();
- FilterToolButton.DropDown.Renderer = new FlatToolStripRenderer();
- FilterTagsToolButton.DropDown.Renderer = new FlatToolStripRenderer();
- FilterLabelsToolButton.DropDown.Renderer = new FlatToolStripRenderer();
minimizedContextMenuStrip.Renderer = new FlatToolStripRenderer();
- ModListContextMenuStrip.Renderer = new FlatToolStripRenderer();
- ModListHeaderContextMenuStrip.Renderer = new FlatToolStripRenderer();
- LabelsContextMenuStrip.Renderer = new FlatToolStripRenderer();
}
// Initialize all user interaction dialogs.
@@ -251,13 +135,6 @@ public Main(string[] cmdlineArgs, KSPManager mgr, bool showConsole)
return;
}
- FilterToolButton.MouseHover += (sender, args) => FilterToolButton.ShowDropDown();
- launchKSPToolStripMenuItem.MouseHover += (sender, args) => launchKSPToolStripMenuItem.ShowDropDown();
- ApplyToolButton.MouseHover += (sender, args) => ApplyToolButton.ShowDropDown();
-
- ModList.CurrentCellDirtyStateChanged += ModList_CurrentCellDirtyStateChanged;
- ModList.CellValueChanged += ModList_CellValueChanged;
-
tabController = new TabController(MainTabControl);
tabController.ShowTab("ManageModsTabPage");
@@ -290,29 +167,6 @@ public Main(string[] cmdlineArgs, KSPManager mgr, bool showConsole)
registry?.Dispose();
}
- private void ModList_CurrentCellDirtyStateChanged(object sender, EventArgs e)
- {
- ModList_CellContentClick(sender, null);
- }
-
- protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
- {
- switch (keyData)
- {
- case Keys.Control | Keys.F:
- ActiveControl = FilterByNameTextBox;
- return true;
-
- case Keys.Control | Keys.S:
- if (ChangeSet != null && ChangeSet.Any())
- ApplyToolButton_Click(null, null);
-
- return true;
- }
-
- return base.ProcessCmdKey(ref msg, keyData);
- }
-
public static Main Instance { get; private set; }
///
@@ -435,8 +289,6 @@ protected override void OnLoad(EventArgs e)
URLHandlers.RegisterURLHandler(configuration, currentUser);
- ApplyToolButton.Enabled = false;
-
CurrentInstanceUpdated(!autoUpdating);
if (commandLineArgs.Length >= 2)
@@ -451,8 +303,8 @@ protected override void OnLoad(EventArgs e)
identifier = identifier.Substring(0, identifier.Length - 1);
log.Debug("Attempting to select mod from startup parameters");
- FocusMod(identifier, true, true);
- ModList.Refresh();
+ ManageMods.FocusMod(identifier, true, true);
+ ManageMods.ModGrid.Refresh();
log.Debug("Failed to select mod from startup parameters");
}
@@ -464,10 +316,6 @@ protected override void OnLoad(EventArgs e)
CurrentInstance.RebuildKSPSubDir();
- // Initialize navigation. This should be called as late as
- // possible, once the UI is "settled" from its initial load.
- NavInit();
-
log.Info("GUI started");
base.OnLoad(e);
}
@@ -481,49 +329,10 @@ protected override void OnFormClosing(FormClosingEventArgs e)
return;
}
- if (Conflicts != null)
- {
- if (Conflicts.Any())
- {
- // Ask if they want to resolve conflicts
- string confDescrip = Conflicts
- .Select(kvp => kvp.Value)
- .Aggregate((a, b) => $"{a}, {b}");
- if (!YesNoDialog(string.Format(Properties.Resources.MainQuitWithConflicts, confDescrip),
- Properties.Resources.MainQuit,
- Properties.Resources.MainGoBack))
- {
- e.Cancel = true;
- return;
- }
- }
- else
- {
- // The Conflicts dictionary is empty even when there are unmet dependencies.
- if (!YesNoDialog(Properties.Resources.MainQuitWithUnmetDeps,
- Properties.Resources.MainQuit,
- Properties.Resources.MainGoBack))
- {
- e.Cancel = true;
- return;
- }
- }
- }
- else if (ChangeSet?.Any() ?? false)
+ if (!ManageMods.AllowClose())
{
- // Ask if they want to discard the change set
- string changeDescrip = ChangeSet
- .GroupBy(ch => ch.ChangeType, ch => ch.Mod.name)
- .Select(grp => $"{grp.Key}: "
- + grp.Aggregate((a, b) => $"{a}, {b}"))
- .Aggregate((a, b) => $"{a}\r\n{b}");
- if (!YesNoDialog(string.Format(Properties.Resources.MainQuitWIthUnappliedChanges, changeDescrip),
- Properties.Resources.MainQuit,
- Properties.Resources.MainGoBack))
- {
- e.Cancel = true;
- return;
- }
+ e.Cancel = true;
+ return;
}
// Copy window location to app settings
@@ -542,8 +351,8 @@ protected override void OnFormClosing(FormClosingEventArgs e)
configuration.ModInfoPosition = ModInfo.ModMetaSplitPosition;
// Save the active filter
- configuration.ActiveFilter = (int)mainModList.ModFilter;
- configuration.CustomLabelFilter = mainModList.CustomLabelFilter?.Name;
+ configuration.ActiveFilter = (int)ManageMods.mainModList.ModFilter;
+ configuration.CustomLabelFilter = ManageMods.mainModList.CustomLabelFilter?.Name;
// Save settings.
configuration.Save();
@@ -584,7 +393,7 @@ private void CurrentInstanceUpdated(bool allowRepoUpdate)
}
(RegistryManager.Instance(CurrentInstance).registry as Registry)
- ?.BuildTagIndex(mainModList.ModuleTags);
+ ?.BuildTagIndex(ManageMods.mainModList.ModuleTags);
bool repoUpdateNeeded = configuration.RefreshOnStartup
|| !RegistryManager.Instance(CurrentInstance).registry.HasAnyAvailable();
@@ -595,10 +404,10 @@ private void CurrentInstanceUpdated(bool allowRepoUpdate)
// Remove it again after it ran, else it stays there and is added again and again.
void filterUpdate(object sender, RunWorkerCompletedEventArgs e)
{
- Filter(
+ ManageMods.Filter(
(GUIModFilter)configuration.ActiveFilter,
- mainModList.ModuleTags.Tags.GetOrDefault(configuration.TagFilter),
- mainModList.ModuleLabels.LabelsFor(CurrentInstance.Name)
+ ManageMods.mainModList.ModuleTags.Tags.GetOrDefault(configuration.TagFilter),
+ ManageMods.mainModList.ModuleLabels.LabelsFor(CurrentInstance.Name)
.FirstOrDefault(l => l.Name == configuration.CustomLabelFilter)
);
m_UpdateRepoWorker.RunWorkerCompleted -= filterUpdate;
@@ -606,22 +415,20 @@ void filterUpdate(object sender, RunWorkerCompletedEventArgs e)
m_UpdateRepoWorker.RunWorkerCompleted += filterUpdate;
- ModList.Rows.Clear();
+ ManageMods.ModGrid.Rows.Clear();
UpdateRepo();
}
else
{
- UpdateModsList();
- Filter(
+ ManageMods.UpdateModsList();
+ ManageMods.Filter(
(GUIModFilter)configuration.ActiveFilter,
- mainModList.ModuleTags.Tags.GetOrDefault(configuration.TagFilter),
- mainModList.ModuleLabels.LabelsFor(CurrentInstance.Name)
+ ManageMods.mainModList.ModuleTags.Tags.GetOrDefault(configuration.TagFilter),
+ ManageMods.mainModList.ModuleLabels.LabelsFor(CurrentInstance.Name)
.FirstOrDefault(l => l.Name == configuration.CustomLabelFilter)
);
}
-
- ChangeSet = null;
- Conflicts = null;
+ ManageMods.InstanceUpdated(CurrentInstance);
}
public void UpdateCKAN()
@@ -639,373 +446,16 @@ public void UpdateCKAN()
updateWorker.RunWorkerAsync();
}
- private void RefreshToolButton_Click(object sender, EventArgs e)
- {
- UpdateRepo();
- }
-
- private void MarkAllUpdatesToolButton_Click(object sender, EventArgs e)
- {
- foreach (DataGridViewRow row in ModList.Rows)
- {
- var mod = (GUIMod)row.Tag;
- if (mod.HasUpdate)
- {
- MarkModForUpdate(mod.Identifier, true);
- }
- }
-
- // only sort by Update column if checkbox in settings checked
- if (Main.Instance.configuration.AutoSortByUpdate)
- {
- // set new sort column
- var new_sort_column = ModList.Columns[UpdateCol.Index];
- var current_sort_column = ModList.Columns[configuration.SortByColumnIndex];
-
- // Reset the glyph.
- current_sort_column.HeaderCell.SortGlyphDirection = SortOrder.None;
- configuration.SortByColumnIndex = new_sort_column.Index;
- UpdateFilters(this);
-
- // Select the top row and scroll the list to it.
- ModList.CurrentCell = ModList.Rows[0].Cells[SelectableColumnIndex()];
- }
-
- ModList.Refresh();
- }
-
public void UpdateModContentsTree(CkanModule module, bool force = false)
{
ModInfo.UpdateModContentsTree(module, force);
}
- private void ApplyToolButton_Click(object sender, EventArgs e)
- {
- tabController.ShowTab("ChangesetTabPage", 1);
- }
-
private void ExitToolButton_Click(object sender, EventArgs e)
{
Close();
}
- private void FilterByNameTextBox_TextChanged(object sender, EventArgs e)
- {
- if (Platform.IsMac)
- {
- // Delay updating to improve typing performance on OS X.
- RunFilterUpdateTimer();
- }
- else
- mainModList.ModNameFilter = FilterByNameTextBox.Text;
- }
-
- private void FilterByAuthorTextBox_TextChanged(object sender, EventArgs e)
- {
- if (Platform.IsMac)
- {
- // Delay updating to improve typing performance on OS X.
- RunFilterUpdateTimer();
- }
- else
- mainModList.ModAuthorFilter = FilterByAuthorTextBox.Text;
- }
-
- private void FilterByDescriptionTextBox_TextChanged(object sender, EventArgs e)
- {
- if (Platform.IsMac)
- {
- // Delay updating to improve typing performance on OS X.
- RunFilterUpdateTimer();
- }
- else
- mainModList.ModDescriptionFilter = FilterByDescriptionTextBox.Text;
- }
-
- private void FilterTextBox_KeyDown(object sender, KeyEventArgs e)
- {
- // Switch focus from filters to mod list on enter, down, or pgdn
- switch (e.KeyCode)
- {
- case Keys.Enter:
- case Keys.Down:
- case Keys.PageDown:
- Util.Invoke(this, () => ModList.Focus());
- e.Handled = true;
- break;
- }
- }
-
- ///
- /// Start or restart a timer to update the filter after an interval since the last keypress.
- /// On Mac OS X, this prevents the search field from locking up due to DataGridViews being
- /// slow and key strokes being interpreted incorrectly when slowed down:
- /// http://mono.1490590.n4.nabble.com/Incorrect-missing-and-duplicate-keypress-events-td4658863.html
- ///
- private void RunFilterUpdateTimer()
- {
- if (filterTimer == null)
- {
- filterTimer = new Timer();
- filterTimer.Tick += OnFilterUpdateTimer;
- filterTimer.Interval = 700;
- filterTimer.Start();
- }
- else
- {
- filterTimer.Stop();
- filterTimer.Start();
- }
- }
-
- ///
- /// Updates the filter after an interval of time has passed since the last keypress.
- ///
- private void OnFilterUpdateTimer(object source, EventArgs e)
- {
- mainModList.ModNameFilter = FilterByNameTextBox.Text;
- mainModList.ModAuthorFilter = FilterByAuthorTextBox.Text;
- mainModList.ModDescriptionFilter = FilterByDescriptionTextBox.Text;
- filterTimer.Stop();
- }
-
- public async Task UpdateChangeSetAndConflicts(IRegistryQuerier registry)
- {
- IEnumerable full_change_set = null;
- Dictionary new_conflicts = null;
-
- bool too_many_provides_thrown = false;
- var user_change_set = mainModList.ComputeUserChangeSet(registry);
- try
- {
- var module_installer = ModuleInstaller.GetInstance(CurrentInstance, Manager.Cache, currentUser);
- full_change_set = mainModList.ComputeChangeSetFromModList(registry, user_change_set, module_installer, CurrentInstance.VersionCriteria());
- }
- catch (InconsistentKraken k)
- {
- // Need to be recomputed due to ComputeChangeSetFromModList possibly changing it with too many provides handling.
- AddStatusMessage(k.ShortDescription);
- user_change_set = mainModList.ComputeUserChangeSet(registry);
- new_conflicts = MainModList.ComputeConflictsFromModList(registry, user_change_set, CurrentInstance.VersionCriteria());
- full_change_set = null;
- }
- catch (TooManyModsProvideKraken)
- {
- // Can be thrown by ComputeChangeSetFromModList if the user cancels out of it.
- // We can just rerun it as the ModInfo has been removed.
- too_many_provides_thrown = true;
- }
- catch (DependencyNotSatisfiedKraken k)
- {
- currentUser.RaiseError(
- Properties.Resources.MainDepNotSatisfied,
- k.parent,
- k.module
- );
-
- // Uncheck the box
- MarkModForInstall(k.parent.identifier, true);
- }
-
- if (too_many_provides_thrown)
- {
- await UpdateChangeSetAndConflicts(registry);
- new_conflicts = Conflicts;
- full_change_set = ChangeSet;
- }
-
- Conflicts = new_conflicts;
- ChangeSet = full_change_set;
- }
-
- private void FilterCompatibleButton_Click(object sender, EventArgs e)
- {
- Filter(GUIModFilter.Compatible);
- }
-
- private void FilterInstalledButton_Click(object sender, EventArgs e)
- {
- Filter(GUIModFilter.Installed);
- }
-
- private void FilterInstalledUpdateButton_Click(object sender, EventArgs e)
- {
- Filter(GUIModFilter.InstalledUpdateAvailable);
- }
-
- private void FilterReplaceableButton_Click(object sender, EventArgs e)
- {
- Filter(GUIModFilter.Replaceable);
- }
-
- private void FilterCachedButton_Click(object sender, EventArgs e)
- {
- Filter(GUIModFilter.Cached);
- }
-
- private void FilterUncachedButton_Click(object sender, EventArgs e)
- {
- Filter(GUIModFilter.Uncached);
- }
-
- private void FilterNewButton_Click(object sender, EventArgs e)
- {
- Filter(GUIModFilter.NewInRepository);
- }
-
- private void FilterNotInstalledButton_Click(object sender, EventArgs e)
- {
- Filter(GUIModFilter.NotInstalled);
- }
-
- private void FilterIncompatibleButton_Click(object sender, EventArgs e)
- {
- Filter(GUIModFilter.Incompatible);
- }
-
- private void FilterAllButton_Click(object sender, EventArgs e)
- {
- Filter(GUIModFilter.All);
- }
-
- ///
- /// Called when the modlist filter (all, compatible, incompatible...) is changed.
- ///
- /// Filter.
- private void Filter(GUIModFilter filter, ModuleTag tag = null, ModuleLabel label = null)
- {
- // Triggers mainModList.ModFiltersUpdated()
- mainModList.TagFilter = tag;
- mainModList.CustomLabelFilter = label;
- mainModList.ModFilter = filter;
-
- // Save new filter to the configuration.
- configuration.ActiveFilter = (int)mainModList.ModFilter;
- configuration.CustomLabelFilter = label?.Name;
- configuration.TagFilter = tag?.Name;
- configuration.Save();
-
- // Ask the configuration which columns to show.
- foreach (DataGridViewColumn col in ModList.Columns)
- {
- // Some columns are always shown, and others are handled by UpdateModsList()
- if (col.Name != "Installed" && col.Name != "UpdateCol" && col.Name != "ReplaceCol")
- {
- col.Visible = !configuration.HiddenColumnNames.Contains(col.Name);
- }
- }
-
- switch (filter)
- {
- // Some columns really do / don't make sense to be visible on certain filter settings.
- // Hide / Show them, without writing to config, so once the user changes tab again,
- // they are shown / hidden again, as before.
- case GUIModFilter.All: FilterToolButton.Text = Properties.Resources.MainFilterAll; break;
- case GUIModFilter.Incompatible: FilterToolButton.Text = Properties.Resources.MainFilterIncompatible; break;
- case GUIModFilter.Installed: FilterToolButton.Text = Properties.Resources.MainFilterInstalled; break;
- case GUIModFilter.InstalledUpdateAvailable: FilterToolButton.Text = Properties.Resources.MainFilterUpgradeable; break;
- case GUIModFilter.Replaceable: FilterToolButton.Text = Properties.Resources.MainFilterReplaceable; break;
- case GUIModFilter.Cached: FilterToolButton.Text = Properties.Resources.MainFilterCached; break;
- case GUIModFilter.Uncached: FilterToolButton.Text = Properties.Resources.MainFilterUncached; break;
- case GUIModFilter.NewInRepository: FilterToolButton.Text = Properties.Resources.MainFilterNew; break;
- case GUIModFilter.NotInstalled: ModList.Columns["InstalledVersion"].Visible = false;
- ModList.Columns["InstallDate"].Visible = false;
- ModList.Columns["AutoInstalled"].Visible = false;
- FilterToolButton.Text = Properties.Resources.MainFilterNotInstalled; break;
- case GUIModFilter.CustomLabel: FilterToolButton.Text = string.Format(Properties.Resources.MainFilterLabel, label?.Name ?? "CUSTOM"); break;
- case GUIModFilter.Tag:
- FilterToolButton.Text = tag == null
- ? Properties.Resources.MainFilterUntagged
- : string.Format(Properties.Resources.MainFilterTag, tag.Name);
- break;
- default: FilterToolButton.Text = Properties.Resources.MainFilterCompatible; break;
- }
- }
-
- private GUIMod GetSelectedModule()
- {
- if (ModList.SelectedRows.Count == 0)
- return null;
-
- DataGridViewRow selected_item = ModList.SelectedRows[0];
-
- var module = (GUIMod)selected_item?.Tag;
- return module;
- }
-
- private void launchKSPToolStripMenuItem_Click(object sender, EventArgs e)
- {
- var split = configuration.CommandLineArguments.Split(' ');
- if (split.Length == 0)
- return;
-
- var registry = RegistryManager.Instance(CurrentInstance).registry;
- var incomp = registry.IncompatibleInstalled(CurrentInstance.VersionCriteria());
- if (incomp.Any())
- {
- // Warn that it might not be safe to run KSP with incompatible modules installed
- string incompatDescrip = incomp
- .Select(m => $"{m.Module} ({registry.CompatibleGameVersions(m.Module)})")
- .Aggregate((a, b) => $"{a}, {b}");
- if (!YesNoDialog(string.Format(Properties.Resources.MainLaunchWithIncompatible, incompatDescrip),
- Properties.Resources.MainLaunch,
- Properties.Resources.MainGoBack))
- {
- return;
- }
- }
-
- // -single-instance crashes KSP 1.8 to KSP 1.9 on Linux
- // https://issuetracker.unity3d.com/issues/linux-segmentation-fault-when-running-a-built-project-with-single-instance-argument
- if (Platform.IsUnix)
- {
- var brokenVersionRange = new KspVersionRange(
- new KspVersion(1, 8),
- new KspVersion(1, 9)
- );
- split = filterCmdLineArgs(split, brokenVersionRange, "-single-instance");
- }
-
- var binary = split[0];
- var args = string.Join(" ", split.Skip(1));
-
- try
- {
- Directory.SetCurrentDirectory(CurrentInstance.GameDir());
- Process.Start(binary, args);
- }
- catch (Exception exception)
- {
- currentUser.RaiseError(Properties.Resources.MainLaunchFailed, exception.Message);
- }
- }
-
- ///
- /// If the installed game version is in the given range,
- /// return the given array without the given parameter,
- /// otherwise return the array as-is.
- ///
- /// Command line parameters to check
- /// Game versions that should not use this parameter
- /// The parameter to remove on version match
- ///
- /// args or args minus parameter
- ///
- private string[] filterCmdLineArgs(string[] args, KspVersionRange crashyKspRange, string parameter)
- {
- var installedRange = CurrentInstance.Version().ToVersionRange();
- if (crashyKspRange.IntersectWith(installedRange) != null
- && args.Contains(parameter))
- {
- log.DebugFormat(
- "Parameter {0} found on incompatible KSP version {1}, pruning",
- parameter,
- CurrentInstance.Version().ToString());
- return args.Where(s => s != parameter).ToArray();
- }
- return args;
- }
-
private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
{
new AboutDialog().ShowDialog();
@@ -1101,16 +551,11 @@ private void manageKspInstancesMenuItem_Click(object sender, EventArgs e)
var result = new ManageKspInstancesDialog(!actuallyVisible, currentUser).ShowDialog();
if (result == DialogResult.OK && !Equals(old_instance, Instance.CurrentInstance))
{
- ModList.ClearSelection();
+ ManageMods.ModGrid.ClearSelection();
CurrentInstanceUpdated(true);
}
}
- private void openKspDirectoryToolStripMenuItem_Click(object sender, EventArgs e)
- {
- Utilities.ProcessStartURL(Instance.manager.CurrentInstance.GameDir());
- }
-
private void CompatibleKspVersionsToolStripMenuItem_Click(object sender, EventArgs e)
{
CompatibleKspVersionsDialog dialog = new CompatibleKspVersionsDialog(
@@ -1120,70 +565,13 @@ private void CompatibleKspVersionsToolStripMenuItem_Click(object sender, EventAr
if (dialog.ShowDialog() != DialogResult.Cancel)
{
// This takes a while, so don't do it if they cancel out
- UpdateModsList();
+ ManageMods.UpdateModsList();
}
}
- public void ResetFilterAndSelectModOnList(string key)
+ private void ManageMods_OnSelectedModuleChanged(GUIMod m)
{
- FilterByNameTextBox.Text = string.Empty;
- mainModList.ModNameFilter = string.Empty;
- FocusMod(key, true);
- }
-
- private void FocusMod(string key, bool exactMatch, bool showAsFirst = false)
- {
- DataGridViewRow current_row = ModList.CurrentRow;
- int currentIndex = current_row?.Index ?? 0;
- DataGridViewRow first_match = null;
-
- var does_name_begin_with_key = new Func(row =>
- {
- GUIMod mod = row.Tag as GUIMod;
- bool row_match;
- if (exactMatch)
- row_match = mod.Name == key || mod.Identifier == key;
- else
- row_match = mod.Name.StartsWith(key, StringComparison.OrdinalIgnoreCase) ||
- mod.Abbrevation.StartsWith(key, StringComparison.OrdinalIgnoreCase) ||
- mod.Identifier.StartsWith(key, StringComparison.OrdinalIgnoreCase);
-
- if (row_match && first_match == null)
- {
- // Remember the first match to allow cycling back to it if necessary.
- first_match = row;
- }
-
- if (key.Length == 1 && row_match && row.Index <= currentIndex)
- {
- // Keep going forward if it's a single key match and not ahead of the current row.
- return false;
- }
-
- return row_match;
- });
-
- ModList.ClearSelection();
- var rows = ModList.Rows.Cast().Where(row => row.Visible);
- DataGridViewRow match = rows.FirstOrDefault(does_name_begin_with_key);
- if (match == null && first_match != null)
- {
- // If there were no matches after the first match, cycle over to the beginning.
- match = first_match;
- }
-
- if (match != null)
- {
- match.Selected = true;
-
- ModList.CurrentCell = match.Cells[SelectableColumnIndex()];
- if (showAsFirst)
- ModList.FirstDisplayedScrollingRowIndex = match.Index;
- }
- else
- {
- AddStatusMessage(Properties.Resources.MainNotFound);
- }
+ ActiveModInfo = m;
}
private GUIMod ActiveModInfo
@@ -1215,12 +603,34 @@ private void ShowSelectionModInfo(ListView.SelectedListViewItemCollection select
);
}
+ private void ManageMods_OnChangeSetChanged(IEnumerable changeset)
+ {
+ if (changeset != null && changeset.Any())
+ {
+ tabController.ShowTab("ChangesetTabPage", 1, false);
+ UpdateChangesDialog(changeset.ToList());
+ auditRecommendationsMenuItem.Enabled = false;
+ }
+ else
+ {
+ tabController.HideTab("ChangesetTabPage");
+ Wait.RetryEnabled = false;
+ auditRecommendationsMenuItem.Enabled = true;
+ }
+ }
+
+ private void ManageMods_OnRegistryChanged()
+ {
+ needRegistrySave = true;
+ }
+
private void MainTabControl_OnSelectedIndexChanged(object sender, EventArgs e)
{
switch (MainTabControl.SelectedTab?.Name)
{
case "ManageModsTabPage":
- ModList_SelectedIndexChanged(sender, e);
+ // TODO: Call public func on ManageMods
+ //ModList_SelectedIndexChanged(sender, e);
break;
case "ChangesetTabPage":
@@ -1251,151 +661,123 @@ private void reportMetadataIssueToolStripMenuItem_Click(object sender, EventArgs
Utilities.ProcessStartURL("https://github.com/KSP-CKAN/NetKAN/issues/new/choose");
}
- private void ModList_MouseDown(object sender, MouseEventArgs e)
+ private void Main_Resize(object sender, EventArgs e)
{
- var rowIndex = ModList.HitTest(e.X, e.Y).RowIndex;
-
- // Ignore header column to prevent errors.
- if (rowIndex != -1 && e.Button == MouseButtons.Right)
- {
- // Detect the clicked cell and select the row.
- ModList.ClearSelection();
- ModList.Rows[rowIndex].Selected = true;
-
- // Show the context menu.
- ModListContextMenuStrip.Show(ModList, new Point(e.X, e.Y));
-
- // Set the menu options.
- var guiMod = (GUIMod)ModList.Rows[rowIndex].Tag;
-
- downloadContentsToolStripMenuItem.Enabled = !guiMod.IsCached;
- purgeContentsToolStripMenuItem.Enabled = guiMod.IsCached;
- reinstallToolStripMenuItem.Enabled = guiMod.IsInstalled && !guiMod.IsAutodetected;
- }
+ UpdateTrayState();
}
- private void reinstallToolStripMenuItem_Click(object sender, EventArgs e)
+ private void openKspDirectoryToolStripMenuItem_Click(object sender, EventArgs e)
{
- GUIMod module = ModInfo.SelectedModule;
- if (module == null || !module.IsCKAN)
- return;
-
- YesNoDialog reinstallDialog = new YesNoDialog();
- string confirmationText = string.Format(Properties.Resources.MainReinstallConfirm, module.Name);
- if (reinstallDialog.ShowYesNoDialog(this, confirmationText) == DialogResult.No)
- return;
-
- IRegistryQuerier registry = RegistryManager.Instance(CurrentInstance).registry;
+ Utilities.ProcessStartURL(Instance.manager.CurrentInstance.GameDir());
+ }
- // Build the list of changes, first the mod to remove:
- List toReinstall = new List()
- {
- new ModChange(module.ToModule(), GUIModChangeType.Remove, null)
- };
- // Then everything we need to re-install:
- var revdep = registry.FindReverseDependencies(new List() { module.Identifier });
- var goners = revdep.Union(
- registry.FindRemovableAutoInstalled(
- registry.InstalledModules.Where(im => !revdep.Contains(im.identifier))
- ).Select(im => im.Module.identifier)
- );
- foreach (string id in goners)
- {
- toReinstall.Add(new ModChange(
- (mainModList.full_list_of_mod_rows[id]?.Tag as GUIMod).ToModule(),
- GUIModChangeType.Install,
- null
- ));
- }
- // Hand off to centralized [un]installer code
- installWorker.RunWorkerAsync(
- new KeyValuePair, RelationshipResolverOptions>(
- toReinstall,
- RelationshipResolver.DependsOnlyOpts()
- )
- );
+ private void openKSPToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ LaunchKSP();
}
- private void purgeContentsToolStripMenuItem_Click(object sender, EventArgs e)
+ public void LaunchKSP()
{
- // Purge other versions as well since the user is likely to want that
- // and has no other way to achieve it
- if (ModInfo.SelectedModule != null)
+ var split = configuration.CommandLineArguments.Split(' ');
+ if (split.Length == 0)
+ return;
+
+ var registry = RegistryManager.Instance(CurrentInstance).registry;
+ var incomp = registry.IncompatibleInstalled(CurrentInstance.VersionCriteria());
+ if (incomp.Any())
{
- IRegistryQuerier registry = RegistryManager.Instance(CurrentInstance).registry;
- var allAvail = registry.AvailableByIdentifier(ModInfo.SelectedModule.Identifier);
- foreach (CkanModule mod in allAvail)
+ // Warn that it might not be safe to run KSP with incompatible modules installed
+ string incompatDescrip = incomp
+ .Select(m => $"{m.Module} ({registry.CompatibleGameVersions(m.Module)})")
+ .Aggregate((a, b) => $"{a}, {b}");
+ if (!YesNoDialog(string.Format(Properties.Resources.MainLaunchWithIncompatible, incompatDescrip),
+ Properties.Resources.MainLaunch,
+ Properties.Resources.MainGoBack))
{
- Manager.Cache.Purge(mod);
+ return;
}
- ModInfo.SelectedModule.UpdateIsCached();
- UpdateModContentsTree(ModInfo.SelectedModule.ToCkanModule(), true);
}
- }
- private void Main_Resize(object sender, EventArgs e)
- {
- UpdateTrayState();
- }
-
- #region Navigation History
-
- private void NavInit()
- {
- navHistory.OnHistoryChange += NavOnHistoryChange;
- navHistory.IsReadOnly = false;
- var currentMod = GetSelectedModule();
- if (currentMod != null)
- navHistory.AddToHistory(currentMod);
- }
-
- private void NavUpdateUI()
- {
- NavBackwardToolButton.Enabled = navHistory.CanNavigateBackward;
- NavForwardToolButton.Enabled = navHistory.CanNavigateForward;
- }
-
- private void NavSelectMod(GUIMod module)
- {
- navHistory.AddToHistory(module);
- }
+ // -single-instance crashes KSP 1.8 to KSP 1.9 on Linux
+ // https://issuetracker.unity3d.com/issues/linux-segmentation-fault-when-running-a-built-project-with-single-instance-argument
+ if (Platform.IsUnix)
+ {
+ var brokenVersionRange = new KspVersionRange(
+ new KspVersion(1, 8),
+ new KspVersion(1, 9)
+ );
+ split = filterCmdLineArgs(split, brokenVersionRange, "-single-instance");
+ }
- private void NavGoBackward()
- {
- if (navHistory.CanNavigateBackward)
- NavGoToMod(navHistory.NavigateBackward());
- }
+ var binary = split[0];
+ var args = string.Join(" ", split.Skip(1));
- private void NavGoForward()
- {
- if (navHistory.CanNavigateForward)
- NavGoToMod(navHistory.NavigateForward());
+ try
+ {
+ Directory.SetCurrentDirectory(CurrentInstance.GameDir());
+ Process.Start(binary, args);
+ }
+ catch (Exception exception)
+ {
+ currentUser.RaiseError(Properties.Resources.MainLaunchFailed, exception.Message);
+ }
}
- private void NavGoToMod(GUIMod module)
+ ///
+ /// If the installed game version is in the given range,
+ /// return the given array without the given parameter,
+ /// otherwise return the array as-is.
+ ///
+ /// Command line parameters to check
+ /// Game versions that should not use this parameter
+ /// The parameter to remove on version match
+ ///
+ /// args or args minus parameter
+ ///
+ private string[] filterCmdLineArgs(string[] args, KspVersionRange crashyKspRange, string parameter)
{
- // Focussing on a mod also causes navigation, but we don't want
- // this to affect the history. so we switch to read-only mode.
- navHistory.IsReadOnly = true;
- FocusMod(module.Name, true);
- navHistory.IsReadOnly = false;
+ var installedRange = Main.Instance.CurrentInstance.Version().ToVersionRange();
+ if (crashyKspRange.IntersectWith(installedRange) != null
+ && args.Contains(parameter))
+ {
+ log.DebugFormat(
+ "Parameter {0} found on incompatible KSP version {1}, pruning",
+ parameter,
+ Main.Instance.CurrentInstance.Version().ToString());
+ return args.Where(s => s != parameter).ToArray();
+ }
+ return args;
}
- private void NavOnHistoryChange()
+ private void ManageMods_StartChangeSet(List changeset)
{
- NavUpdateUI();
+ // Hand off to centralized [un]installer code
+ installWorker.RunWorkerAsync(
+ new KeyValuePair, RelationshipResolverOptions>(
+ changeset,
+ RelationshipResolver.DependsOnlyOpts()
+ )
+ );
}
- private void NavBackwardToolButton_Click(object sender, EventArgs e)
+ private void ManageMods_OpenProgressTab()
{
- NavGoBackward();
+ ResetProgress();
+ ShowWaitDialog(false);
+ tabController.SetTabLock(true);
+ Util.Invoke(this, SwitchEnabledState);
+ Wait.ClearLog();
}
- private void NavForwardToolButton_Click(object sender, EventArgs e)
+ private void ManageMods_CloseProgressTab()
{
- NavGoForward();
+ Util.Invoke(this, UpdateTrayInfo);
+ HideWaitDialog(true);
+ tabController.HideTab("WaitTabPage");
+ tabController.SetTabLock(false);
+ tabController.ShowTab("ManageModsTabPage");
+ Util.Invoke(this, SwitchEnabledState);
}
- #endregion
}
}
diff --git a/GUI/Main/Main.resx b/GUI/Main/Main.resx
index 951dd76b90..e2f4db738e 100644
--- a/GUI/Main/Main.resx
+++ b/GUI/Main/Main.resx
@@ -123,33 +123,6 @@
126, 17
-
- 236, 17
-
-
- True
-
-
- True
-
-
- True
-
-
- True
-
-
- True
-
-
- True
-
-
- True
-
-
- 351, 17
-
546, 17
@@ -183,51 +156,7 @@
Report an issue with the CKAN client
Report an issue with mod metadata
About
- Launch KSP
- Refresh
- Add available updates
- Apply changes
- Filter (Compatible)
- Compatible
- Installed
- Installed (update available)
- Replaceable
- Cached
- Uncached
- Newly compatible
- Not installed
- Incompatible
- All
- Tags
- Labels
- Previous selected mod...
- Next selected mod...
- Inst
- Auto-installed
- Update
- Replace
- Name
- Author
- Installed version
- Latest version
- Max KSP version
- Download
- Install date
- Downloads
- Description
- Reinstall
- Download Contents
- Purge Contents
Manage mods
- Filter by author name:
- 543, 74
- 170, 26
- Filter by mod name:
- 160, 74
- 170, 26
- Filter by description:
- 912, 74
- 170, 26
Changeset
Status log
Choose mods
@@ -243,6 +172,4 @@
Open KSP Directory
CKAN Settings
Quit
- Labels
- Edit labels...
diff --git a/GUI/Main/MainChangeset.cs b/GUI/Main/MainChangeset.cs
index ff5ba1012b..006ade9eab 100644
--- a/GUI/Main/MainChangeset.cs
+++ b/GUI/Main/MainChangeset.cs
@@ -10,7 +10,7 @@ public void UpdateChangesDialog(List changeset)
{
Changeset.LoadChangeset(
changeset,
- mainModList.ModuleLabels.LabelsFor(CurrentInstance.Name)
+ ManageMods.mainModList.ModuleLabels.LabelsFor(CurrentInstance.Name)
.Where(l => l.AlertOnInstall)
.ToList());
}
@@ -22,7 +22,7 @@ private void Changeset_OnSelectedItemsChanged(ListView.SelectedListViewItemColle
private void Changeset_OnCancelChanges()
{
- ClearChangeSet();
+ ManageMods.ClearChangeSet();
UpdateChangesDialog(null);
tabController.ShowTab("ManageModsTabPage");
}
@@ -36,24 +36,11 @@ private void Changeset_OnConfirmChanges()
// TODO Work out why this is.
installWorker.RunWorkerAsync(
new KeyValuePair, RelationshipResolverOptions>(
- mainModList.ComputeUserChangeSet(RegistryManager.Instance(Main.Instance.CurrentInstance).registry).ToList(),
+ ManageMods.mainModList.ComputeUserChangeSet(RegistryManager.Instance(Main.Instance.CurrentInstance).registry).ToList(),
RelationshipResolver.DependsOnlyOpts()
)
);
}
- private void ClearChangeSet()
- {
- foreach (DataGridViewRow row in mainModList.full_list_of_mod_rows.Values)
- {
- GUIMod mod = row.Tag as GUIMod;
- if (mod.IsInstallChecked != mod.IsInstalled)
- {
- mod.SetInstallChecked(row, Installed, mod.IsInstalled);
- }
- mod.SetUpgradeChecked(row, UpdateCol, false);
- mod.SetReplaceChecked(row, ReplaceCol, false);
- }
- }
}
}
diff --git a/GUI/Main/MainDownload.cs b/GUI/Main/MainDownload.cs
index 39138c2315..f3c8499fe9 100644
--- a/GUI/Main/MainDownload.cs
+++ b/GUI/Main/MainDownload.cs
@@ -10,11 +10,6 @@ public partial class Main
private BackgroundWorker cacheWorker;
private NetAsyncModulesDownloader downloader;
- private void downloadContentsToolStripMenuItem_Click(object sender, EventArgs e)
- {
- StartDownload(ModInfo.SelectedModule);
- }
-
private void ModInfo_OnDownloadClick(GUIMod gmod)
{
StartDownload(gmod);
diff --git a/GUI/Main/MainExport.cs b/GUI/Main/MainExport.cs
index 720876edf8..5f7ffa7b2e 100644
--- a/GUI/Main/MainExport.cs
+++ b/GUI/Main/MainExport.cs
@@ -38,7 +38,7 @@ private void EditModpack_OnSelectedItemsChanged(ListView.SelectedListViewItemCol
{
var first = items.Cast().FirstOrDefault()?.Tag as ModuleRelationshipDescriptor;
var ident = first?.name;
- if (!string.IsNullOrEmpty(ident) && mainModList.full_list_of_mod_rows.TryGetValue(ident, out DataGridViewRow row))
+ if (!string.IsNullOrEmpty(ident) && ManageMods.mainModList.full_list_of_mod_rows.TryGetValue(ident, out DataGridViewRow row))
{
ActiveModInfo = row.Tag as GUIMod;
}
diff --git a/GUI/Main/MainImport.cs b/GUI/Main/MainImport.cs
index 4d6322baf9..97c60d32ea 100644
--- a/GUI/Main/MainImport.cs
+++ b/GUI/Main/MainImport.cs
@@ -39,7 +39,7 @@ private void ImportModules()
ModuleInstaller.GetInstance(CurrentInstance, Manager.Cache, currentUser).ImportFiles(
GetFiles(dlg.FileNames),
currentUser,
- (CkanModule mod) => MarkModForInstall(mod.identifier, false),
+ (CkanModule mod) => ManageMods.MarkModForInstall(mod.identifier, false),
RegistryManager.Instance(CurrentInstance).registry
);
}
diff --git a/GUI/Main/MainInstall.cs b/GUI/Main/MainInstall.cs
index b7224ab1ae..f6a2a6c197 100644
--- a/GUI/Main/MainInstall.cs
+++ b/GUI/Main/MainInstall.cs
@@ -59,10 +59,6 @@ public void InstallModuleDriver(IRegistryQuerier registry, CkanModule module)
HideWaitDialog(false);
menuStrip1.Enabled = true;
}
- finally
- {
- ChangeSet = null;
- }
}
// this probably needs to be refactored
@@ -238,103 +234,6 @@ out Dictionary> supporters
return;
}
}
- catch (DependencyNotSatisfiedKraken ex)
- {
- currentUser.RaiseMessage(Properties.Resources.MainInstallDepNotSatisfied, ex.parent, ex.module);
- return;
- }
- catch (ModuleNotFoundKraken ex)
- {
- currentUser.RaiseMessage(Properties.Resources.MainInstallNotFound, ex.module);
- return;
- }
- catch (BadMetadataKraken ex)
- {
- currentUser.RaiseMessage(Properties.Resources.MainInstallBadMetadata, ex.module, ex.Message);
- return;
- }
- catch (FileExistsKraken ex)
- {
- if (ex.owningModule != null)
- {
- currentUser.RaiseMessage(
- Properties.Resources.MainInstallFileExists,
- ex.filename, ex.installingModule, ex.owningModule,
- Meta.GetVersion()
- );
- }
- else
- {
- currentUser.RaiseMessage(
- Properties.Resources.MainInstallUnownedFileExists,
- ex.installingModule, ex.filename
- );
- }
- currentUser.RaiseMessage(Properties.Resources.MainInstallGameDataReverted);
- return;
- }
- catch (InconsistentKraken ex)
- {
- // The prettiest Kraken formats itself for us.
- currentUser.RaiseMessage(ex.InconsistenciesPretty);
- return;
- }
- catch (CancelledActionKraken)
- {
- return;
- }
- catch (MissingCertificateKraken kraken)
- {
- // Another very pretty kraken.
- currentUser.RaiseMessage(kraken.ToString());
- return;
- }
- catch (DownloadThrottledKraken kraken)
- {
- string msg = kraken.ToString();
- currentUser.RaiseMessage(msg);
- if (YesNoDialog(string.Format(Properties.Resources.MainInstallOpenSettingsPrompt, msg),
- Properties.Resources.MainInstallOpenSettings,
- Properties.Resources.MainInstallNo))
- {
- // Launch the URL describing this host's throttling practices, if any
- if (kraken.infoUrl != null)
- {
- Utilities.ProcessStartURL(kraken.infoUrl.ToString());
- }
- // Now pretend they clicked the menu option for the settings
- Enabled = false;
- new SettingsDialog(currentUser).ShowDialog();
- Enabled = true;
- }
- return;
- }
- catch (ModuleDownloadErrorsKraken kraken)
- {
- currentUser.RaiseMessage(kraken.ToString());
- currentUser.RaiseError(kraken.ToString());
- return;
- }
- catch (DirectoryNotFoundKraken kraken)
- {
- currentUser.RaiseMessage("\r\n{0}", kraken.Message);
- return;
- }
- catch (DllNotFoundException)
- {
- if (currentUser.RaiseYesNoDialog(Properties.Resources.MainInstallLibCurlMissing))
- {
- Utilities.ProcessStartURL("https://github.com/KSP-CKAN/CKAN/wiki/libcurl");
- }
- throw;
- }
- catch (ModuleIsDLCKraken kraken)
- {
- string msg = string.Format(Properties.Resources.MainInstallCantInstallDLC, kraken.module.name);
- currentUser.RaiseMessage(msg);
- currentUser.RaiseError(msg);
- return;
- }
}
}
@@ -386,67 +285,157 @@ private void OnModInstalled(CkanModule mod)
private void PostInstallMods(object sender, RunWorkerCompletedEventArgs e)
{
- KeyValuePair result = (KeyValuePair) e.Result;
-
tabController.SetTabLock(false);
- if (result.Key && !installCanceled)
+ switch (e.Error)
{
- // Rebuilds the list of GUIMods
- UpdateModsList(null);
+ case DependencyNotSatisfiedKraken exc:
+ currentUser.RaiseMessage(Properties.Resources.MainInstallDepNotSatisfied, exc.parent, exc.module);
+ break;
- if (modChangedCallback != null)
- {
- foreach (var mod in result.Value)
+ case ModuleNotFoundKraken exc:
+ currentUser.RaiseMessage(Properties.Resources.MainInstallNotFound, exc.module);
+ break;
+
+ case BadMetadataKraken exc:
+ currentUser.RaiseMessage(Properties.Resources.MainInstallBadMetadata, exc.module, exc.Message);
+ break;
+
+ case FileExistsKraken exc:
+ if (exc.owningModule != null)
+ {
+ currentUser.RaiseMessage(
+ Properties.Resources.MainInstallFileExists,
+ exc.filename, exc.installingModule, exc.owningModule,
+ Meta.GetVersion()
+ );
+ }
+ else
{
- modChangedCallback(mod.Mod, mod.ChangeType);
+ currentUser.RaiseMessage(
+ Properties.Resources.MainInstallUnownedFileExists,
+ exc.installingModule, exc.filename
+ );
}
- }
+ currentUser.RaiseMessage(Properties.Resources.MainInstallGameDataReverted);
+ break;
- // install successful
- AddStatusMessage(Properties.Resources.MainInstallSuccess);
- HideWaitDialog(true);
- }
- else if (installCanceled)
- {
- // User cancelled the installation
- // Rebuilds the list of GUIMods
- UpdateModsList(ChangeSet);
- if (result.Key) {
- FailWaitDialog(
- Properties.Resources.MainInstallCancelTooLate,
- Properties.Resources.MainInstallCancelAfterInstall,
- Properties.Resources.MainInstallProcessComplete,
- result.Key
- );
- } else {
+ case InconsistentKraken exc:
+ currentUser.RaiseMessage(exc.InconsistenciesPretty);
+ break;
+
+ case CancelledActionKraken exc:
+ // No message needed, the user knows they cancelled
+ break;
+
+ case MissingCertificateKraken exc:
+ currentUser.RaiseMessage(exc.ToString());
+ break;
+
+ case DownloadThrottledKraken exc:
+ string msg = exc.ToString();
+ currentUser.RaiseMessage(msg);
+ if (YesNoDialog(string.Format(Properties.Resources.MainInstallOpenSettingsPrompt, msg),
+ Properties.Resources.MainInstallOpenSettings,
+ Properties.Resources.MainInstallNo))
+ {
+ // Launch the URL describing this host's throttling practices, if any
+ if (exc.infoUrl != null)
+ {
+ Utilities.ProcessStartURL(exc.infoUrl.ToString());
+ }
+ // Now pretend they clicked the menu option for the settings
+ Enabled = false;
+ new SettingsDialog(currentUser).ShowDialog();
+ Enabled = true;
+ }
+ break;
+
+ case ModuleDownloadErrorsKraken exc:
+ currentUser.RaiseMessage(exc.ToString());
+ currentUser.RaiseError(exc.ToString());
+ break;
+
+ case DirectoryNotFoundKraken exc:
+ currentUser.RaiseMessage("\r\n{0}", exc.Message);
+ break;
+
+ case DllNotFoundException exc:
+ if (currentUser.RaiseYesNoDialog(Properties.Resources.MainInstallLibCurlMissing))
+ {
+ Utilities.ProcessStartURL("https://github.com/KSP-CKAN/CKAN/wiki/libcurl");
+ }
+ break;
+
+ case ModuleIsDLCKraken exc:
+ string dlcMsg = string.Format(Properties.Resources.MainInstallCantInstallDLC, exc.module.name);
+ currentUser.RaiseMessage(dlcMsg);
+ currentUser.RaiseError(dlcMsg);
+ break;
+
+ case null:
+ // No error
+ KeyValuePair result = (KeyValuePair) e.Result;
+
+ if (result.Key && !installCanceled)
+ {
+ // Rebuilds the list of GUIMods
+ ManageMods.UpdateModsList(null);
+
+ if (modChangedCallback != null)
+ {
+ foreach (var mod in result.Value)
+ {
+ modChangedCallback(mod.Mod, mod.ChangeType);
+ }
+ }
+
+ // install successful
+ AddStatusMessage(Properties.Resources.MainInstallSuccess);
+ HideWaitDialog(true);
+ }
+ else if (installCanceled)
+ {
+ // User cancelled the installation
+ // Rebuilds the list of GUIMods
+ ManageMods.UpdateModsList();
+ if (result.Key) {
+ FailWaitDialog(
+ Properties.Resources.MainInstallCancelTooLate,
+ Properties.Resources.MainInstallCancelAfterInstall,
+ Properties.Resources.MainInstallProcessComplete,
+ result.Key
+ );
+ } else {
+ FailWaitDialog(
+ Properties.Resources.MainInstallProcessCanceled,
+ Properties.Resources.MainInstallCanceledManually,
+ Properties.Resources.MainInstallInstallCanceled,
+ result.Key
+ );
+ }
+ }
+ else
+ {
+ // The install was unsuccessful, but no exception was thrown
+ FailWaitDialog(
+ Properties.Resources.MainInstallErrorInstalling,
+ Properties.Resources.MainInstallKnownError,
+ Properties.Resources.MainInstallFailed,
+ result.Key
+ );
+ }
+ break;
+
+ default:
+ // An unknown error was thrown
FailWaitDialog(
- Properties.Resources.MainInstallProcessCanceled,
- Properties.Resources.MainInstallCanceledManually,
- Properties.Resources.MainInstallInstallCanceled,
- result.Key
+ Properties.Resources.MainInstallErrorInstalling,
+ Properties.Resources.MainInstallUnknownError,
+ Properties.Resources.MainInstallFailed,
+ false
);
- }
- }
- else if (e.Error == null)
- {
- // The install was unsuccessful, but we did catch the exception.
- FailWaitDialog(
- Properties.Resources.MainInstallErrorInstalling,
- Properties.Resources.MainInstallKnownError,
- Properties.Resources.MainInstallFailed,
- result.Key
- );
- }
- else
- {
- // An unknown error was thrown which we didn't catch.
- FailWaitDialog(
- Properties.Resources.MainInstallErrorInstalling,
- Properties.Resources.MainInstallUnknownError,
- Properties.Resources.MainInstallFailed,
- result.Key
- );
+ break;
}
Util.Invoke(this, () => Enabled = true);
diff --git a/GUI/Main/MainLabels.cs b/GUI/Main/MainLabels.cs
index 1614b256ea..442d15551e 100644
--- a/GUI/Main/MainLabels.cs
+++ b/GUI/Main/MainLabels.cs
@@ -10,127 +10,20 @@ public partial class Main
{
#region Filter dropdown
- private void FilterToolButton_DropDown_Opening(object sender, System.ComponentModel.CancelEventArgs e)
- {
- // The menu items' dropdowns can't be accessed if they're empty
- FilterTagsToolButton_DropDown_Opening(null, null);
- FilterLabelsToolButton_DropDown_Opening(null, null);
- }
-
- private void FilterTagsToolButton_DropDown_Opening(object sender, System.ComponentModel.CancelEventArgs e)
- {
- FilterTagsToolButton.DropDownItems.Clear();
- foreach (var kvp in mainModList.ModuleTags.Tags.OrderBy(kvp => kvp.Key))
- {
- FilterTagsToolButton.DropDownItems.Add(new ToolStripMenuItem(
- $"{kvp.Key} ({kvp.Value.ModuleIdentifiers.Count})",
- null, tagFilterButton_Click
- )
- {
- Tag = kvp.Value
- });
- }
- FilterTagsToolButton.DropDownItems.Add(untaggedFilterToolStripSeparator);
- FilterTagsToolButton.DropDownItems.Add(new ToolStripMenuItem(
- string.Format(Properties.Resources.MainLabelsUntagged, mainModList.ModuleTags.Untagged.Count),
- null, tagFilterButton_Click
- )
- {
- Tag = null
- });
- }
-
- private void FilterLabelsToolButton_DropDown_Opening(object sender, System.ComponentModel.CancelEventArgs e)
- {
- FilterLabelsToolButton.DropDownItems.Clear();
- foreach (ModuleLabel mlbl in mainModList.ModuleLabels.LabelsFor(CurrentInstance.Name))
- {
- FilterLabelsToolButton.DropDownItems.Add(new ToolStripMenuItem(
- $"{mlbl.Name} ({mlbl.ModuleIdentifiers.Count})",
- null, customFilterButton_Click
- )
- {
- Tag = mlbl
- });
- }
- }
-
- private void tagFilterButton_Click(object sender, EventArgs e)
- {
- var clicked = sender as ToolStripMenuItem;
- Filter(GUIModFilter.Tag, clicked.Tag as ModuleTag, null);
- }
-
- private void customFilterButton_Click(object sender, EventArgs e)
- {
- var clicked = sender as ToolStripMenuItem;
- Filter(GUIModFilter.CustomLabel, null, clicked.Tag as ModuleLabel);
- }
-
#endregion
#region Right click menu
- private void LabelsContextMenuStrip_Opening(object sender, System.ComponentModel.CancelEventArgs e)
- {
- LabelsContextMenuStrip.Items.Clear();
-
- var module = GetSelectedModule();
- foreach (ModuleLabel mlbl in mainModList.ModuleLabels.LabelsFor(CurrentInstance.Name))
- {
- LabelsContextMenuStrip.Items.Add(
- new ToolStripMenuItem(mlbl.Name, null, labelMenuItem_Click)
- {
- Checked = mlbl.ModuleIdentifiers.Contains(module.Identifier),
- CheckOnClick = true,
- Tag = mlbl,
- }
- );
- }
- LabelsContextMenuStrip.Items.Add(labelToolStripSeparator);
- LabelsContextMenuStrip.Items.Add(editLabelsToolStripMenuItem);
- e.Cancel = false;
- }
-
- private void labelMenuItem_Click(object sender, EventArgs e)
- {
- var item = sender as ToolStripMenuItem;
- var mlbl = item.Tag as ModuleLabel;
- var module = GetSelectedModule();
- if (item.Checked)
- {
- mlbl.Add(module.Identifier);
- }
- else
- {
- mlbl.Remove(module.Identifier);
- }
- mainModList.ReapplyLabels(module, Conflicts?.ContainsKey(module) ?? false, CurrentInstance.Name);
- mainModList.ModuleLabels.Save(ModuleLabelList.DefaultPath);
- }
-
- private void editLabelsToolStripMenuItem_Click(object sender, EventArgs e)
- {
- EditLabelsDialog eld = new EditLabelsDialog(currentUser, Manager, mainModList.ModuleLabels);
- eld.ShowDialog(this);
- eld.Dispose();
- mainModList.ModuleLabels.Save(ModuleLabelList.DefaultPath);
- foreach (GUIMod module in mainModList.Modules)
- {
- mainModList.ReapplyLabels(module, Conflicts?.ContainsKey(module) ?? false, CurrentInstance.Name);
- }
- }
-
#endregion
#region Notifications
- private void LabelsAfterUpdate(IEnumerable mods)
+ private void ManageMods_LabelsAfterUpdate(IEnumerable mods)
{
Util.Invoke(Main.Instance, () =>
{
mods = mods.Memoize();
- var notifLabs = mainModList.ModuleLabels.LabelsFor(CurrentInstance.Name)
+ var notifLabs = ManageMods.mainModList.ModuleLabels.LabelsFor(CurrentInstance.Name)
.Where(l => l.NotifyOnChange)
.Memoize();
var toNotif = mods
@@ -153,7 +46,7 @@ private void LabelsAfterUpdate(IEnumerable mods)
foreach (GUIMod mod in mods)
{
- foreach (ModuleLabel l in mainModList.ModuleLabels.LabelsFor(CurrentInstance.Name)
+ foreach (ModuleLabel l in ManageMods.mainModList.ModuleLabels.LabelsFor(CurrentInstance.Name)
.Where(l => l.RemoveOnChange
&& l.ModuleIdentifiers.Contains(mod.Identifier)))
{
@@ -165,7 +58,7 @@ private void LabelsAfterUpdate(IEnumerable mods)
private void LabelsAfterInstall(CkanModule mod)
{
- foreach (ModuleLabel l in mainModList.ModuleLabels.LabelsFor(CurrentInstance.Name)
+ foreach (ModuleLabel l in ManageMods.mainModList.ModuleLabels.LabelsFor(CurrentInstance.Name)
.Where(l => l.RemoveOnInstall && l.ModuleIdentifiers.Contains(mod.identifier)))
{
l.Remove(mod.identifier);
diff --git a/GUI/Main/MainModList.cs b/GUI/Main/MainModList.cs
deleted file mode 100644
index daca76793f..0000000000
--- a/GUI/Main/MainModList.cs
+++ /dev/null
@@ -1,1234 +0,0 @@
-using System;
-using System.Drawing;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Linq;
-using System.Threading.Tasks;
-using System.Reflection;
-using System.Text.RegularExpressions;
-using System.Windows.Forms;
-using CKAN.Versioning;
-
-namespace CKAN
-{
- public enum GUIModFilter
- {
- Compatible = 0,
- Installed = 1,
- InstalledUpdateAvailable = 2,
- NewInRepository = 3,
- NotInstalled = 4,
- Incompatible = 5,
- All = 6,
- Cached = 7,
- Replaceable = 8,
- Uncached = 9,
- CustomLabel = 10,
- Tag = 11,
- }
-
- public partial class Main
- {
- private IEnumerable _SortRowsByColumn(IEnumerable rows)
- {
- switch (this.configuration.SortByColumnIndex)
- {
- // XXX: There should be a better way to identify checkbox columns than hardcoding their indices here
- case 0: case 1:
- case 2: case 3: return Sort(rows, CheckboxSorter);
- case 9: return Sort(rows, DownloadSizeSorter);
- case 10: return Sort(rows, InstallDateSorter);
- case 11: return Sort(rows, r => (r.Tag as GUIMod)?.DownloadCount ?? 0);
- }
- return Sort(rows, DefaultSorter);
- }
-
- private IEnumerable Sort(IEnumerable rows, Func sortFunction)
- {
- var get_row_mod_name = new Func(row => ((GUIMod)row.Tag).Name);
- DataGridViewColumnHeaderCell header =
- this.ModList.Columns[this.configuration.SortByColumnIndex].HeaderCell;
-
- // The columns will be sorted by mod name in addition to whatever the current sorting column is
- if (this.configuration.SortDescending)
- {
- header.SortGlyphDirection = SortOrder.Descending;
- return rows.OrderByDescending(sortFunction).ThenBy(get_row_mod_name);
- }
-
- header.SortGlyphDirection = SortOrder.Ascending;
- return rows.OrderBy(sortFunction).ThenBy(get_row_mod_name);
- }
-
- ///
- /// Transforms a DataGridViewRow's into a generic value suitable for sorting.
- /// Uses this.m_Configuration.SortByColumnIndex to determine which
- /// field to sort on.
- ///
- private string DefaultSorter(DataGridViewRow row)
- {
- // changed so that it never returns null
- var cellVal = row.Cells[configuration.SortByColumnIndex].Value as string;
- return string.IsNullOrWhiteSpace(cellVal) ? string.Empty : cellVal;
- }
-
- ///
- /// Transforms a DataGridViewRow's checkbox status into a value suitable for sorting.
- /// Uses this.m_Configuration.SortByColumnIndex to determine which
- /// field to sort on.
- ///
- private string CheckboxSorter(DataGridViewRow row)
- {
- var cell = row.Cells[this.configuration.SortByColumnIndex];
- if (cell.ValueType == typeof(bool))
- {
- return (bool)cell.Value ? "a" : "c";
- }
- else
- {
- // If it's a "-" cell, let it be ordered last
- // Otherwise put it after the checked boxes
- return (string)cell.Value == "-" ? "d" : "b";
- }
- }
-
- ///
- /// Transforms a DataGridViewRow into a long representing the download size,
- /// suitable for sorting.
- ///
- private long DownloadSizeSorter(DataGridViewRow row)
- {
- return (row.Tag as GUIMod)?.ToCkanModule()?.download_size ?? 0;
- }
-
- ///
- /// Transforms a DataGridViewRow into a long representing the install date,
- /// suitable for sorting.
- /// The grid's default on first click is ascending, and sorting uninstalled mods to
- /// the top is kind of useless, so we'll make this negative so ascending is useful.
- ///
- private long InstallDateSorter(DataGridViewRow row)
- {
- return -(row.Tag as GUIMod)?.InstallDate?.Ticks ?? 0;
- }
-
- private void UpdateFilters(Main control)
- {
- Util.Invoke(control, _UpdateFilters);
- }
-
- private void _UpdateFilters()
- {
- if (ModList == null || mainModList?.full_list_of_mod_rows == null)
- return;
-
- // Each time a row in DataGridViewRow is changed, DataGridViewRow updates the view. Which is slow.
- // To make the filtering process faster, Copy the list of rows. Filter out the hidden and replace the
- // rows in DataGridView.
-
- var rows = new DataGridViewRow[mainModList.full_list_of_mod_rows.Count];
- mainModList.full_list_of_mod_rows.Values.CopyTo(rows, 0);
- // Try to remember the current scroll position and selected mod
- var scroll_col = Math.Max(0, ModList.FirstDisplayedScrollingColumnIndex);
- GUIMod selected_mod = null;
- if (ModList.CurrentRow != null)
- {
- selected_mod = (GUIMod) ModList.CurrentRow.Tag;
- }
-
- ModList.Rows.Clear();
- foreach (var row in rows)
- {
- var mod = ((GUIMod) row.Tag);
- row.Visible = mainModList.IsVisible(mod, CurrentInstance.Name);
- }
-
- var sorted = this._SortRowsByColumn(rows.Where(row => row.Visible));
-
- ModList.Rows.AddRange(sorted.ToArray());
-
- // Find and select the previously selected row
- if (selected_mod != null)
- {
- var selected_row = ModList.Rows.Cast()
- .FirstOrDefault(row => selected_mod.Identifier.Equals(((GUIMod)row.Tag).Identifier));
- if (selected_row != null)
- {
- ModList.CurrentCell = selected_row.Cells[scroll_col];
- }
- }
- }
-
- public async void UpdateModsList(IEnumerable mc = null, Dictionary old_modules = null)
- {
- // Run the update in the background so the UI thread can appear alive
- // Await it so potential (fatal) errors are thrown, not swallowed.
- // Need to be on the GUI thread to get the translated strings
- tabController.RenameTab("WaitTabPage", Properties.Resources.MainModListWaitTitle);
- await Task.Factory.StartNew(() =>
- _UpdateModsList(mc ?? new List(), old_modules)
- );
- }
-
- private void _UpdateModsList(IEnumerable mc, Dictionary old_modules = null)
- {
- log.Info("Updating the mod list");
-
- ResetProgress();
- ShowWaitDialog(false);
- tabController.SetTabLock(true);
- Util.Invoke(this, SwitchEnabledState);
- Wait.ClearLog();
-
- Wait.AddLogMessage(Properties.Resources.MainModListLoadingRegistry);
- KspVersionCriteria versionCriteria = CurrentInstance.VersionCriteria();
- IRegistryQuerier registry = RegistryManager.Instance(CurrentInstance).registry;
-
- Wait.AddLogMessage(Properties.Resources.MainModListLoadingInstalled);
- var gui_mods = new HashSet();
- gui_mods.UnionWith(
- registry.InstalledModules
- .Where(instMod => !instMod.Module.IsDLC)
- .Select(instMod => new GUIMod(instMod, registry, versionCriteria))
- );
- Wait.AddLogMessage(Properties.Resources.MainModListLoadingAvailable);
- gui_mods.UnionWith(
- registry.CompatibleModules(versionCriteria)
- .Where(m => !m.IsDLC)
- .Select(m => new GUIMod(m, registry, versionCriteria))
- );
- Wait.AddLogMessage(Properties.Resources.MainModListLoadingIncompatible);
- gui_mods.UnionWith(
- registry.IncompatibleModules(versionCriteria)
- .Where(m => !m.IsDLC)
- .Select(m => new GUIMod(m, registry, versionCriteria, true))
- );
-
- Wait.AddLogMessage(Properties.Resources.MainModListPreservingNew);
- var toNotify = new HashSet();
- if (old_modules != null)
- {
- foreach (GUIMod gm in gui_mods)
- {
- if (old_modules.TryGetValue(gm.Identifier, out bool oldIncompat))
- {
- // Found it; check if newly compatible
- if (!gm.IsIncompatible && oldIncompat)
- {
- gm.IsNew = true;
- toNotify.Add(gm);
- }
- }
- else
- {
- // Newly indexed, show regardless of compatibility
- gm.IsNew = true;
- }
- }
- }
- else
- {
- // Copy the new mod flag from the old list.
- var old_new_mods = new HashSet(
- mainModList.Modules.Where(m => m.IsNew));
- foreach (var gui_mod in gui_mods.Where(m => old_new_mods.Contains(m)))
- {
- gui_mod.IsNew = true;
- }
- }
- LabelsAfterUpdate(toNotify);
-
- Wait.AddLogMessage(Properties.Resources.MainModListPopulatingList);
- // Update our mod listing
- mainModList.ConstructModList(gui_mods.ToList(), CurrentInstance.Name, mc, configuration.HideEpochs, configuration.HideV);
- mainModList.Modules = new ReadOnlyCollection(
- mainModList.full_list_of_mod_rows.Values.Select(row => row.Tag as GUIMod).ToList());
-
- UpdateChangeSetAndConflicts(registry);
-
- Wait.AddLogMessage(Properties.Resources.MainModListUpdatingFilters);
-
- var has_any_updates = gui_mods.Any(mod => mod.HasUpdate);
- var has_any_installed = gui_mods.Any(mod => mod.IsInstalled);
- var has_any_replacements = gui_mods.Any(mod => mod.IsInstalled && mod.HasReplacement);
-
- Util.Invoke(menuStrip2, () =>
- {
- FilterCompatibleButton.Text = String.Format(Properties.Resources.MainModListCompatible,
- mainModList.CountModsByFilter(GUIModFilter.Compatible));
- FilterInstalledButton.Text = String.Format(Properties.Resources.MainModListInstalled,
- mainModList.CountModsByFilter(GUIModFilter.Installed));
- FilterInstalledUpdateButton.Text = String.Format(Properties.Resources.MainModListUpgradeable,
- mainModList.CountModsByFilter(GUIModFilter.InstalledUpdateAvailable));
- FilterReplaceableButton.Text = String.Format(Properties.Resources.MainModListReplaceable,
- mainModList.CountModsByFilter(GUIModFilter.Replaceable));
- FilterCachedButton.Text = String.Format(Properties.Resources.MainModListCached,
- mainModList.CountModsByFilter(GUIModFilter.Cached));
- FilterUncachedButton.Text = String.Format(Properties.Resources.MainModListUncached,
- mainModList.CountModsByFilter(GUIModFilter.Uncached));
- FilterNewButton.Text = String.Format(Properties.Resources.MainModListNewlyCompatible,
- mainModList.CountModsByFilter(GUIModFilter.NewInRepository));
- FilterNotInstalledButton.Text = String.Format(Properties.Resources.MainModListNotInstalled,
- mainModList.CountModsByFilter(GUIModFilter.NotInstalled));
- FilterIncompatibleButton.Text = String.Format(Properties.Resources.MainModListIncompatible,
- mainModList.CountModsByFilter(GUIModFilter.Incompatible));
- FilterAllButton.Text = String.Format(Properties.Resources.MainModListAll,
- mainModList.CountModsByFilter(GUIModFilter.All));
-
- UpdateAllToolButton.Enabled = has_any_updates;
- });
-
- (registry as Registry)?.BuildTagIndex(mainModList.ModuleTags);
-
- UpdateFilters(this);
-
- // Hide update and replacement columns if not needed.
- // Write it to the configuration, else they are hidden again after a filter change.
- // After the update / replacement, they are hidden again.
- Util.Invoke(ModList, () =>
- {
- ModList.Columns["UpdateCol"].Visible = has_any_updates;
- ModList.Columns["AutoInstalled"].Visible = has_any_installed && !configuration.HiddenColumnNames.Contains("AutoInstalled");
- ModList.Columns["ReplaceCol"].Visible = has_any_replacements;
- });
-
- Wait.AddLogMessage(Properties.Resources.MainModListUpdatingTray);
- Util.Invoke(this, UpdateTrayInfo);
-
- HideWaitDialog(true);
- tabController.HideTab("WaitTabPage");
- tabController.SetTabLock(false);
- tabController.ShowTab("ManageModsTabPage");
- Util.Invoke(this, SwitchEnabledState);
- Util.Invoke(this, () => Main.Instance.ModList.Focus());
- }
-
- public void MarkModForInstall(string identifier, bool uncheck = false)
- {
- Util.Invoke(this, () => _MarkModForInstall(identifier, uncheck));
- }
-
- private void _MarkModForInstall(string identifier, bool uninstall)
- {
- DataGridViewRow row = mainModList?.full_list_of_mod_rows?[identifier];
- var mod = (GUIMod)row?.Tag;
- if (mod?.Identifier == identifier)
- {
- mod.SetInstallChecked(row, Installed, !uninstall);
- }
- }
-
- public void MarkModForUpdate(string identifier, bool value)
- {
- Util.Invoke(this, () => _MarkModForUpdate(identifier, value));
- }
-
- public void _MarkModForUpdate(string identifier, bool value)
- {
- DataGridViewRow row = mainModList.full_list_of_mod_rows[identifier];
- var mod = (GUIMod)row.Tag;
- mod.SetUpgradeChecked(row, UpdateCol, value);
- }
-
- private void ModList_SelectedIndexChanged(object sender, EventArgs e)
- {
- // Skip if already disposed (i.e. after the form has been closed).
- // Needed for TransparentTextBoxes
- if (ModInfo.IsDisposed)
- {
- return;
- }
-
- var module = GetSelectedModule();
-
- ActiveModInfo = module;
- if (module == null)
- return;
-
- NavSelectMod(module);
- }
-
- ///
- /// Called when there's a click on the modlist header row.
- /// Handles sorting and the header right click context menu.
- ///
- private void ModList_HeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
- {
- // Left click -> sort by new column / change sorting direction.
- if (e.Button == MouseButtons.Left)
- {
- var new_sort_column = ModList.Columns [e.ColumnIndex];
- var current_sort_column = ModList.Columns [configuration.SortByColumnIndex];
-
- // Reverse the sort order if the current sorting column is clicked again.
- configuration.SortDescending = new_sort_column == current_sort_column && !configuration.SortDescending;
-
- // Reset the glyph.
- current_sort_column.HeaderCell.SortGlyphDirection = SortOrder.None;
- configuration.SortByColumnIndex = new_sort_column.Index;
- UpdateFilters(this);
- }
- // Right click -> Bring up context menu to change visibility of columns.
- else if (e.Button == MouseButtons.Right)
- {
- // Start from scrap: clear the entire item list, then add all options again.
- ModListHeaderContextMenuStrip.Items.Clear();
-
- // Add columns
- ModListHeaderContextMenuStrip.Items.AddRange(
- ModList.Columns.Cast()
- .Where(col => col.Name != "Installed" && col.Name != "UpdateCol" && col.Name != "ReplaceCol")
- .Select(col => new ToolStripMenuItem()
- {
- Name = col.Name,
- Text = col.HeaderText,
- Checked = col.Visible,
- Tag = col
- })
- .ToArray()
- );
-
- // Separator
- ModListHeaderContextMenuStrip.Items.Add(new ToolStripSeparator());
-
- // Add tags
- ModListHeaderContextMenuStrip.Items.AddRange(
- mainModList.ModuleTags.Tags.OrderBy(kvp => kvp.Key)
- .Select(kvp => new ToolStripMenuItem()
- {
- Name = kvp.Key,
- Text = kvp.Key,
- Checked = kvp.Value.Visible,
- Tag = kvp.Value,
- })
- .ToArray()
- );
-
- // Show the context menu on cursor position.
- ModListHeaderContextMenuStrip.Show(Cursor.Position);
- }
- }
-
- ///
- /// Called if a ToolStripButton of the header context menu is pressed.
- ///
- private void ModListHeaderContextMenuStrip_ItemClicked(object sender, System.Windows.Forms.ToolStripItemClickedEventArgs e)
- {
- // ClickedItem is of type ToolStripItem, we need ToolStripButton.
- ToolStripMenuItem clickedItem = e.ClickedItem as ToolStripMenuItem;
- DataGridViewColumn col = clickedItem?.Tag as DataGridViewColumn;
- ModuleTag tag = clickedItem?.Tag as ModuleTag;
-
- if (col != null)
- {
- col.Visible = !clickedItem.Checked;
- configuration.SetColumnVisibility(col.Name, !clickedItem.Checked);
- if (col.Index == 0)
- {
- InstallAllCheckbox.Visible = col.Visible;
- }
- }
- else if (tag != null)
- {
- tag.Visible = !clickedItem.Checked;
- if (tag.Visible)
- {
- mainModList.ModuleTags.HiddenTags.Remove(tag.Name);
- }
- else
- {
- mainModList.ModuleTags.HiddenTags.Add(tag.Name);
- }
- mainModList.ModuleTags.Save(ModuleTagList.DefaultPath);
- UpdateFilters(this);
- }
- }
-
- ///
- /// Called on key down when the mod list is focused.
- /// Makes the Home/End keys go to the top/bottom of the list respectively.
- ///
- private void ModList_KeyDown(object sender, KeyEventArgs e)
- {
- switch (e.KeyCode)
- {
- case Keys.Home:
- // First row.
- ModList.CurrentCell = ModList.Rows[0].Cells[SelectableColumnIndex()];
- e.Handled = true;
- break;
-
- case Keys.End:
- // Last row.
- ModList.CurrentCell = ModList.Rows[ModList.Rows.Count - 1].Cells[SelectableColumnIndex()];
- e.Handled = true;
- break;
-
- case Keys.Space:
- // If they've focused one of the checkbox columns, don't intercept
- if (ModList.CurrentCell.ColumnIndex > 3)
- {
- DataGridViewRow row = ModList.CurrentRow;
- // Toggle Update column if enabled, otherwise Install
- for (int colIndex = 2; colIndex >= 0; --colIndex)
- {
- if (row?.Cells[colIndex] is DataGridViewCheckBoxCell)
- {
- // Need to change the state here, because the user hasn't clicked on a checkbox
- row.Cells[colIndex].Value = !(bool)row.Cells[colIndex].Value;
- ModList.CommitEdit(DataGridViewDataErrorContexts.Commit);
- e.Handled = true;
- break;
- }
- }
- }
- break;
- }
- }
-
- ///
- /// Find a column of the grid that can contain the CurrentCell.
- /// Can't be hidden or an exception is thrown.
- /// Shouldn't be a checkbox because we don't want the space bar to toggle.
- ///
- ///
- /// Index of the column to use.
- ///
- private int SelectableColumnIndex()
- {
- // First try the currently active cell's column
- return ModList.CurrentCell?.ColumnIndex
- // If there's no currently active cell, use the first visible non-checkbox column
- ?? ModList.Columns.Cast()
- .FirstOrDefault(c => c is DataGridViewTextBoxColumn && c.Visible)?.Index
- // Otherwise use the Installed checkbox column since it can't be hidden
- ?? Installed.Index;
- }
-
- ///
- /// Called on key press when the mod is focused. Scrolls to the first mod with name
- /// beginning with the key pressed. If more than one unique keys are pressed in under
- /// a second, it searches for the combination of the keys pressed. If the same key is
- /// being pressed repeatedly, it cycles through mods names beginning with that key.
- /// If space is pressed, the checkbox at the current row is toggled.
- ///
- private void ModList_KeyPress(object sender, KeyPressEventArgs e)
- {
- // Don't search for spaces or newlines
- if (e.KeyChar == (char)Keys.Space || e.KeyChar == (char)Keys.Enter)
- {
- return;
- }
-
- var key = e.KeyChar.ToString();
- // Determine time passed since last key press.
- TimeSpan interval = DateTime.Now - lastSearchTime;
- if (interval.TotalSeconds < 1)
- {
- // Last keypress was < 1 sec ago, so combine the last and current keys.
- key = lastSearchKey + key;
- }
-
- // Remember the current time and key.
- lastSearchTime = DateTime.Now;
- lastSearchKey = key;
-
- if (key.Distinct().Count() == 1)
- {
- // Treat repeating and single keypresses the same.
- key = key.Substring(0, 1);
- }
-
- FocusMod(key, false);
- e.Handled = true;
- }
-
- ///
- /// I'm pretty sure this is what gets called when the user clicks on a ticky in the mod list.
- ///
- private void ModList_CellContentClick(object sender, DataGridViewCellEventArgs e)
- {
- ModList.CommitEdit(DataGridViewDataErrorContexts.Commit);
- }
-
- private void ModList_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
- {
- if (e.Button != MouseButtons.Left)
- return;
-
- if (e.RowIndex < 0)
- return;
-
- DataGridViewRow row = ModList.Rows[e.RowIndex];
- if (!(row.Cells[0] is DataGridViewCheckBoxCell))
- return;
-
- // Need to change the state here, because the user hasn't clicked on a checkbox.
- row.Cells[0].Value = !(bool)row.Cells[0].Value;
- ModList.CommitEdit(DataGridViewDataErrorContexts.Commit);
- }
-
- private async void ModList_CellValueChanged(object sender, DataGridViewCellEventArgs e)
- {
- int row_index = e.RowIndex;
- int column_index = e.ColumnIndex;
-
- if (row_index < 0 || column_index < 0)
- return;
-
- DataGridView grid = sender as DataGridView;
- DataGridViewRow row = grid?.Rows[row_index];
- DataGridViewCell gridCell = row?.Cells[column_index];
-
- if (gridCell is DataGridViewLinkCell)
- {
- // Launch URLs if found in grid
- DataGridViewLinkCell cell = gridCell as DataGridViewLinkCell;
- string cmd = cell?.Value.ToString();
- if (!string.IsNullOrEmpty(cmd))
- Utilities.ProcessStartURL(cmd);
- }
- else
- {
- GUIMod gui_mod = row?.Tag as GUIMod;
- if (gui_mod != null)
- {
- switch (ModList.Columns[column_index].Name)
- {
- case "Installed":
- gui_mod.SetInstallChecked(row, Installed);
- // The above will call UpdateChangeSetAndConflicts, so we don't need to.
- return;
- case "AutoInstalled":
- gui_mod.SetAutoInstallChecked(row, AutoInstalled);
- needRegistrySave = true;
- break;
- case "UpdateCol":
- gui_mod.SetUpgradeChecked(row, UpdateCol);
- break;
- case "ReplaceCol":
- gui_mod.SetReplaceChecked(row, ReplaceCol);
- break;
- }
- await UpdateChangeSetAndConflicts(
- RegistryManager.Instance(CurrentInstance).registry
- );
- }
- }
- }
-
- private void ModList_GotFocus(object sender, EventArgs e)
- {
- Util.Invoke(this, () =>
- {
- // Give the selected row the standard highlight color
- ModList.RowsDefaultCellStyle.SelectionBackColor = SystemColors.Highlight;
- ModList.RowsDefaultCellStyle.SelectionForeColor = SystemColors.HighlightText;
- });
- }
-
- private void ModList_LostFocus(object sender, EventArgs e)
- {
- Util.Invoke(this, () =>
- {
- // Gray out the selected row so you can tell the mod list is not focused
- ModList.RowsDefaultCellStyle.SelectionBackColor = SystemColors.Control;
- ModList.RowsDefaultCellStyle.SelectionForeColor = SystemColors.ControlText;
- });
- }
-
- private void InstallAllCheckbox_CheckChanged(object sender, EventArgs e)
- {
- if (InstallAllCheckbox.Checked)
- {
- // Reset changeset
- ClearChangeSet();
- }
- else
- {
- // Uninstall all
- foreach (DataGridViewRow row in mainModList.full_list_of_mod_rows.Values)
- {
- GUIMod mod = row.Tag as GUIMod;
- if (mod.IsInstallChecked)
- {
- mod.SetInstallChecked(row, Installed, false);
- }
- }
- }
- }
- }
-
- ///
- /// The main list of mods. Currently used to work around mono issues.
- ///
- public class MainModListGUI : DataGridView
- {
- protected override void OnPaint(PaintEventArgs e)
- {
- try
- {
- // Hacky workaround for https://bugzilla.xamarin.com/show_bug.cgi?id=24372
- if (Platform.IsMono && !Platform.IsMonoFourOrLater)
- {
- var first_row_index = typeof (MainModListGUI).BaseType
- .GetField("first_row_index", BindingFlags.NonPublic | BindingFlags.Instance);
- var value = (int) first_row_index.GetValue(this);
- if (value < 0 || value >= Rows.Count)
- {
- first_row_index.SetValue(this, 0);
- }
- }
- }
- catch
- {
- // Never throw exceptions in OnPaint, or WinForms might decide to replace our control with a big red X
- // https://blogs.msdn.microsoft.com/shawnhar/2010/11/22/winforms-and-the-big-red-x-of-doom/
- }
- base.OnPaint(e);
- }
-
- //Hacky workaround for https://bugzilla.xamarin.com/show_bug.cgi?id=24372
- protected override void SetSelectedRowCore(int rowIndex, bool selected)
- {
- if (rowIndex < 0 || rowIndex >= Rows.Count)
- return;
- base.SetSelectedRowCore(rowIndex, selected);
- }
-
- //ImageList for Update/Changes Column
- public System.Windows.Forms.ImageList ModChangesImageList { get; set; }
-
- }
-
- public class MainModList
- {
- //identifier, row
- internal Dictionary full_list_of_mod_rows;
-
- public MainModList(ModFiltersUpdatedEvent onModFiltersUpdated,
- IUser user = null)
- {
- this.user = user ?? new NullUser();
- Modules = new ReadOnlyCollection(new List());
- ModFiltersUpdated += onModFiltersUpdated ?? (source => { });
- ModFiltersUpdated(this);
- }
-
- public delegate void ModFiltersUpdatedEvent(MainModList source);
-
- //TODO Move to relationship resolver and have it use this.
- public delegate Task HandleTooManyProvides(TooManyModsProvideKraken kraken);
-
- public event ModFiltersUpdatedEvent ModFiltersUpdated;
- public ReadOnlyCollection Modules { get; set; }
-
- public GUIModFilter ModFilter
- {
- get { return _modFilter; }
- set
- {
- var old = _modFilter;
- _modFilter = value;
- if (!old.Equals(value)) ModFiltersUpdated(this);
- }
- }
-
- public readonly ModuleLabelList ModuleLabels = ModuleLabelList.Load(ModuleLabelList.DefaultPath)
- ?? ModuleLabelList.GetDefaultLabels();
-
- public readonly ModuleTagList ModuleTags = ModuleTagList.Load(ModuleTagList.DefaultPath)
- ?? new ModuleTagList();
-
- private ModuleTag _tagFilter;
- public ModuleTag TagFilter
- {
- get { return _tagFilter; }
- set
- {
- var old = _tagFilter;
- _tagFilter = value;
- if (!old?.Equals(value) ?? !value?.Equals(old) ?? false)
- {
- ModFiltersUpdated(this);
- }
- }
- }
-
- private ModuleLabel _customLabelFilter;
- public ModuleLabel CustomLabelFilter
- {
- get { return _customLabelFilter; }
- set
- {
- var old = _customLabelFilter;
- _customLabelFilter = value;
- if (!old?.Equals(value) ?? !value?.Equals(old) ?? false)
- {
- ModFiltersUpdated(this);
- }
- }
- }
-
- public string ModNameFilter
- {
- get { return _modNameFilter; }
- set
- {
- var old = _modNameFilter;
- _modNameFilter = value;
- if (!old.Equals(value)) ModFiltersUpdated(this);
- }
- }
-
- public string ModAuthorFilter
- {
- get { return _modAuthorFilter; }
- set
- {
- var old = _modAuthorFilter;
- _modAuthorFilter = value;
- if (!old.Equals(value)) ModFiltersUpdated(this);
- }
- }
-
- public string ModDescriptionFilter
- {
- get { return _modDescriptionFilter; }
- set
- {
- var old = _modDescriptionFilter;
- _modDescriptionFilter = value;
- if (!old.Equals(value)) ModFiltersUpdated(this);
- }
- }
-
- private GUIModFilter _modFilter = GUIModFilter.Compatible;
- private string _modNameFilter = String.Empty;
- private string _modAuthorFilter = String.Empty;
- private string _modDescriptionFilter = String.Empty;
- private IUser user;
-
- ///
- /// This function returns a changeset based on the selections of the user.
- /// Currently returns null if a conflict is detected.
- ///
- ///
- ///
- /// A module installer for the current KSP install
- /// The version of the current KSP install
- public IEnumerable ComputeChangeSetFromModList(
- IRegistryQuerier registry, HashSet changeSet, ModuleInstaller installer,
- KspVersionCriteria version)
- {
- var modules_to_install = new HashSet();
- var modules_to_remove = new HashSet();
-
- foreach (var change in changeSet)
- {
- switch (change.ChangeType)
- {
- case GUIModChangeType.None:
- break;
- case GUIModChangeType.Update:
- case GUIModChangeType.Install:
- modules_to_install.Add(change.Mod);
- break;
- case GUIModChangeType.Remove:
- modules_to_remove.Add(change.Mod);
- break;
- case GUIModChangeType.Replace:
- ModuleReplacement repl = registry.GetReplacement(change.Mod, version);
- if (repl != null)
- {
- modules_to_remove.Add(repl.ToReplace);
- modules_to_install.Add(repl.ReplaceWith);
- }
- break;
- default:
- throw new ArgumentOutOfRangeException();
- }
- }
-
- var installed_modules =
- registry.InstalledModules.Select(imod => imod.Module).ToDictionary(mod => mod.identifier, mod => mod);
-
- foreach (var dependent in registry.FindReverseDependencies(
- modules_to_remove
- .Select(mod => mod.identifier)
- .Except(modules_to_install.Select(m => m.identifier)),
- modules_to_install
- ))
- {
- //TODO This would be a good place to have an event that alters the row's graphics to show it will be removed
- CkanModule depMod;
- if (installed_modules.TryGetValue(dependent, out depMod))
- {
- CkanModule module_by_version = registry.GetModuleByVersion(depMod.identifier,
- depMod.version)
- ?? registry.InstalledModule(dependent).Module;
- changeSet.Add(new ModChange(module_by_version, GUIModChangeType.Remove, null));
- modules_to_remove.Add(module_by_version);
- }
- }
- foreach (var im in registry.FindRemovableAutoInstalled(
- registry.InstalledModules.Where(im => !modules_to_remove.Any(m => m.identifier == im.identifier) || modules_to_install.Any(m => m.identifier == im.identifier))
- ))
- {
- changeSet.Add(new ModChange(im.Module, GUIModChangeType.Remove, new SelectionReason.NoLongerUsed()));
- modules_to_remove.Add(im.Module);
- }
-
- // Get as many dependencies as we can, but leave decisions and prompts for installation time
- RelationshipResolverOptions opts = RelationshipResolver.DependsOnlyOpts();
- opts.without_toomanyprovides_kraken = true;
- opts.without_enforce_consistency = true;
-
- var resolver = new RelationshipResolver(
- modules_to_install,
- modules_to_remove,
- opts, registry, version);
- changeSet.UnionWith(
- resolver.ModList()
- .Select(m => new ModChange(m, GUIModChangeType.Install, resolver.ReasonFor(m))));
-
- return changeSet;
- }
-
- public bool IsVisible(GUIMod mod, string instanceName)
- {
- return IsNameInNameFilter(mod)
- && IsAuthorInAuthorFilter(mod)
- && IsAbstractInDescriptionFilter(mod)
- && IsModInFilter(ModFilter, TagFilter, CustomLabelFilter, mod)
- && !HiddenByTagsOrLabels(ModFilter, TagFilter, CustomLabelFilter, mod, instanceName);
- }
-
- private bool HiddenByTagsOrLabels(GUIModFilter filter, ModuleTag tag, ModuleLabel label, GUIMod m, string instanceName)
- {
- if (filter != GUIModFilter.CustomLabel)
- {
- // "Hide" labels apply to all non-custom filters
- if (ModuleLabels?.LabelsFor(instanceName)
- .Where(l => l != label && l.Hide)
- .Any(l => l.ModuleIdentifiers.Contains(m.Identifier))
- ?? false)
- {
- return true;
- }
- if (ModuleTags?.Tags?.Values
- .Where(t => t != tag && t.Visible == false)
- .Any(t => t.ModuleIdentifiers.Contains(m.Identifier))
- ?? false)
- {
- return true;
- }
- }
- return false;
- }
-
- public int CountModsByFilter(GUIModFilter filter)
- {
- if (filter == GUIModFilter.All)
- {
- // Don't check each one
- return Modules.Count;
- }
- // Tags and Labels are not counted here
- return Modules.Count(m => IsModInFilter(filter, null, null, m));
- }
-
- ///
- /// Constructs the mod list suitable for display to the user.
- /// Manipulates full_list_of_mod_rows.
- ///
- /// 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)
- {
- List changes = mc?.ToList();
- full_list_of_mod_rows = modules.ToDictionary(
- gm => gm.Identifier,
- gm => MakeRow(gm, changes, instanceName, hideEpochs, hideV)
- );
- return full_list_of_mod_rows.Values;
- }
-
- private DataGridViewRow MakeRow(GUIMod mod, List changes, string instanceName, bool hideEpochs = false, bool hideV = false)
- {
- DataGridViewRow item = new DataGridViewRow() {Tag = mod};
-
- Color? myColor = ModuleLabels.LabelsFor(instanceName)
- .FirstOrDefault(l => l.ModuleIdentifiers.Contains(mod.Identifier))
- ?.Color;
- if (myColor.HasValue)
- {
- item.DefaultCellStyle.BackColor = myColor.Value;
- }
-
- ModChange myChange = changes?.FindLast((ModChange ch) => ch.Mod.Equals(mod));
-
- var selecting = mod.IsInstallable()
- ? (DataGridViewCell) new DataGridViewCheckBoxCell()
- {
- Value = myChange == null ? mod.IsInstalled
- : myChange.ChangeType == GUIModChangeType.Install ? true
- : myChange.ChangeType == GUIModChangeType.Remove ? false
- : mod.IsInstalled
- }
- : new DataGridViewTextBoxCell()
- {
- Value = mod.IsAutodetected ? Properties.Resources.MainModListAutoDetected : "-"
- };
-
- var autoInstalled = mod.IsInstalled && !mod.IsAutodetected
- ? (DataGridViewCell) new DataGridViewCheckBoxCell()
- {
- Value = mod.IsAutoInstalled
- }
- : new DataGridViewTextBoxCell()
- {
- Value = "-"
- };
-
- var updating = mod.IsInstallable() && mod.HasUpdate
- ? (DataGridViewCell) new DataGridViewCheckBoxCell()
- {
- Value = myChange == null ? false
- : myChange.ChangeType == GUIModChangeType.Update ? true
- : false
- }
- : new DataGridViewTextBoxCell()
- {
- Value = "-"
- };
-
- var replacing = IsModInFilter(GUIModFilter.Replaceable, null, null, mod)
- ? (DataGridViewCell) new DataGridViewCheckBoxCell()
- {
- Value = myChange == null ? false
- : myChange.ChangeType == GUIModChangeType.Replace ? true
- : false
- }
- : new DataGridViewTextBoxCell()
- {
- Value = "-"
- };
-
- var name = new DataGridViewTextBoxCell() {Value = mod.Name};
- var author = new DataGridViewTextBoxCell() {Value = mod.Authors};
-
- var installVersion = new DataGridViewTextBoxCell()
- {
- Value = hideEpochs
- ? (hideV
- ? ModuleInstaller.StripEpoch(ModuleInstaller.StripV(mod.InstalledVersion ?? ""))
- : ModuleInstaller.StripEpoch(mod.InstalledVersion ?? ""))
- : (hideV
- ? ModuleInstaller.StripV(mod.InstalledVersion ?? "")
- : 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)
- };
-
- var downloadCount = new DataGridViewTextBoxCell() { Value = String.Format("{0:N0}", mod.DownloadCount) };
- var compat = new DataGridViewTextBoxCell() { Value = mod.KSPCompatibility };
- var size = new DataGridViewTextBoxCell() { Value = mod.DownloadSize };
- var installDate = new DataGridViewTextBoxCell() { Value = mod.InstallDate };
- var desc = new DataGridViewTextBoxCell() { Value = mod.Abstract };
-
- item.Cells.AddRange(selecting, autoInstalled, updating, replacing, name, author, installVersion, latestVersion, compat, size, installDate, downloadCount, desc);
-
- selecting.ReadOnly = selecting is DataGridViewTextBoxCell;
- autoInstalled.ReadOnly = autoInstalled is DataGridViewTextBoxCell;
- updating.ReadOnly = updating is DataGridViewTextBoxCell;
-
- return item;
- }
-
- public Color GetRowBackground(GUIMod mod, bool conflicted, string instanceName)
- {
- if (conflicted)
- {
- return Color.LightCoral;
- }
- DataGridViewRow row;
- if (full_list_of_mod_rows.TryGetValue(mod.Identifier, out row))
- {
- Color? myColor = ModuleLabels.LabelsFor(instanceName)
- .FirstOrDefault(l => l.ModuleIdentifiers.Contains(mod.Identifier))
- ?.Color;
- if (myColor.HasValue)
- {
- return myColor.Value;
- }
- }
- return Color.Empty;
- }
-
- ///
- /// Update the color and visible state of the given row
- /// after it has been added to or removed from a label group
- ///
- /// The mod that needs an update
- public void ReapplyLabels(GUIMod mod, bool conflicted, string instanceName)
- {
- DataGridViewRow row;
- if (full_list_of_mod_rows.TryGetValue(mod.Identifier, out row))
- {
- row.DefaultCellStyle.BackColor = GetRowBackground(mod, conflicted, instanceName);
- row.Visible = IsVisible(mod, instanceName);
- }
- }
-
- ///
- /// Returns a version string shorn of any leading epoch as delimited by a single colon
- ///
- public string StripEpoch(string version)
- {
- // If our version number starts with a string of digits, followed by
- // a colon, and then has no more colons, we're probably safe to assume
- // the first string of digits is an epoch
- //return Regex.IsMatch(version, @"^[0-9][0-9]*:[^:]+$") ? Regex.Replace(version, @"^([^:]+):([^:]+)$", @"$2") : version;
- return ContainsEpoch.IsMatch(version) ? RemoveEpoch.Replace(version, @"$2") : version;
- }
-
- private static readonly Regex ContainsEpoch = new Regex(@"^[0-9][0-9]*:[^:]+$", RegexOptions.Compiled);
- private static readonly Regex RemoveEpoch = new Regex(@"^([^:]+):([^:]+)$", RegexOptions.Compiled);
-
-
- private bool IsNameInNameFilter(GUIMod mod)
- {
- string sanitisedModNameFilter = CkanModule.nonAlphaNums.Replace(ModNameFilter, "");
-
- return mod.Abbrevation.IndexOf(ModNameFilter, StringComparison.InvariantCultureIgnoreCase) != -1
- || mod.SearchableName.IndexOf(sanitisedModNameFilter, StringComparison.InvariantCultureIgnoreCase) != -1
- || mod.SearchableIdentifier.IndexOf(sanitisedModNameFilter, StringComparison.InvariantCultureIgnoreCase) != -1;
- }
-
- private bool IsAuthorInAuthorFilter(GUIMod mod)
- {
- string sanitisedModAuthorFilter = CkanModule.nonAlphaNums.Replace(ModAuthorFilter, "");
-
- return mod.SearchableAuthors.Any((author) => author.IndexOf(sanitisedModAuthorFilter, StringComparison.InvariantCultureIgnoreCase) != -1);
- }
-
- private bool IsAbstractInDescriptionFilter(GUIMod mod)
- {
- string sanitisedModDescriptionFilter = CkanModule.nonAlphaNums.Replace(ModDescriptionFilter, "");
-
- return mod.SearchableAbstract.IndexOf(sanitisedModDescriptionFilter, StringComparison.InvariantCultureIgnoreCase) != -1
- || mod.SearchableDescription.IndexOf(sanitisedModDescriptionFilter, StringComparison.InvariantCultureIgnoreCase) != -1;
- }
-
- private bool IsModInFilter(GUIModFilter filter, ModuleTag tag, ModuleLabel label, GUIMod m)
- {
- switch (filter)
- {
- case GUIModFilter.Compatible: return !m.IsIncompatible;
- case GUIModFilter.Installed: return m.IsInstalled;
- case GUIModFilter.InstalledUpdateAvailable: return m.IsInstalled && m.HasUpdate;
- case GUIModFilter.Cached: return m.IsCached;
- case GUIModFilter.Uncached: return !m.IsCached;
- case GUIModFilter.NewInRepository: return m.IsNew;
- case GUIModFilter.NotInstalled: return !m.IsInstalled;
- case GUIModFilter.Incompatible: return m.IsIncompatible;
- case GUIModFilter.Replaceable: return m.IsInstalled && m.HasReplacement;
- case GUIModFilter.All: return true;
- case GUIModFilter.Tag: return tag?.ModuleIdentifiers.Contains(m.Identifier)
- ?? ModuleTags.Untagged.Contains(m.Identifier);
- case GUIModFilter.CustomLabel: return label?.ModuleIdentifiers?.Contains(m.Identifier) ?? false;
- default: throw new Kraken(string.Format(Properties.Resources.MainModListUnknownFilter, filter));
- }
- }
-
- public static Dictionary ComputeConflictsFromModList(IRegistryQuerier registry,
- IEnumerable change_set, KspVersionCriteria ksp_version)
- {
- var modules_to_install = new HashSet();
- var modules_to_remove = new HashSet();
- var options = new RelationshipResolverOptions
- {
- without_toomanyprovides_kraken = true,
- proceed_with_inconsistencies = true,
- without_enforce_consistency = true,
- with_recommends = false
- };
-
- foreach (var change in change_set)
- {
- switch (change.ChangeType)
- {
- case GUIModChangeType.None:
- break;
- case GUIModChangeType.Install:
- modules_to_install.Add(change.Mod.identifier);
- break;
- case GUIModChangeType.Remove:
- modules_to_remove.Add(change.Mod.identifier);
- break;
- case GUIModChangeType.Update:
- break;
- case GUIModChangeType.Replace:
- ModuleReplacement repl = registry.GetReplacement(change.Mod, ksp_version);
- if (repl != null)
- {
- modules_to_remove.Add(repl.ToReplace.identifier);
- modules_to_install.Add(repl.ReplaceWith.identifier);
- }
- break;
- default:
- throw new ArgumentOutOfRangeException();
- }
- }
-
- // Only check mods that would exist after the changes are made.
- IEnumerable installed = registry.InstalledModules.Where(
- im => !modules_to_remove.Contains(im.Module.identifier)
- ).Select(im => im.Module);
-
- // Convert ONLY modules_to_install with CkanModule.FromIDandVersion,
- // because it may not find already-installed modules.
- IEnumerable mods_to_check = installed.Union(
- modules_to_install.Except(modules_to_remove).Select(
- name => CkanModule.FromIDandVersion(registry, name, ksp_version)
- )
- );
- var resolver = new RelationshipResolver(
- mods_to_check,
- change_set.Where(ch => ch.ChangeType == GUIModChangeType.Remove)
- .Select(ch => ch.Mod),
- options, registry, ksp_version
- );
- return resolver.ConflictList.ToDictionary(item => new GUIMod(item.Key, registry, ksp_version),
- item => item.Value);
- }
-
- public HashSet ComputeUserChangeSet(IRegistryQuerier registry)
- {
- var removableAuto = registry?.FindRemovableAutoInstalled(registry?.InstalledModules)
- ?? new InstalledModule[] {};
- return new HashSet(
- Modules
- .SelectMany(mod => mod.GetModChanges())
- .Union(removableAuto.Select(im => new ModChange(
- im.Module,
- GUIModChangeType.Remove,
- new SelectionReason.NoLongerUsed())))
- );
- }
- }
-}
diff --git a/GUI/Main/MainRepo.cs b/GUI/Main/MainRepo.cs
index d3f9518469..805b6ff51b 100644
--- a/GUI/Main/MainRepo.cs
+++ b/GUI/Main/MainRepo.cs
@@ -115,9 +115,9 @@ private void PostUpdateRepo(object sender, RunWorkerCompletedEventArgs e)
AddStatusMessage(Properties.Resources.MainRepoUpToDate);
HideWaitDialog(true);
// Load rows if grid empty, otherwise keep current
- if (ModList.Rows.Count < 1)
+ if (ManageMods.ModGrid.Rows.Count < 1)
{
- UpdateModsList(ChangeSet);
+ ManageMods.UpdateModsList();
}
break;
@@ -127,7 +127,7 @@ private void PostUpdateRepo(object sender, RunWorkerCompletedEventArgs e)
case RepoUpdateResult.Updated:
default:
- UpdateModsList(ChangeSet, oldModules);
+ ManageMods.UpdateModsList(oldModules);
AddStatusMessage(Properties.Resources.MainRepoSuccess);
ShowRefreshQuestion();
HideWaitDialog(true);
@@ -137,7 +137,7 @@ private void PostUpdateRepo(object sender, RunWorkerCompletedEventArgs e)
Util.Invoke(this, SwitchEnabledState);
Util.Invoke(this, RecreateDialogs);
- Util.Invoke(this, ModList.Select);
+ Util.Invoke(this, ManageMods.ModGrid.Select);
}
private void ShowRefreshQuestion()
@@ -182,7 +182,7 @@ public void UpdateRefreshTimer()
private void OnRefreshTimer(object sender, ElapsedEventArgs e)
{
- if (!configuration.RefreshPaused)
+ if (menuStrip1.Enabled && !configuration.RefreshPaused)
{
// Just a safety check
UpdateRepo();
@@ -191,7 +191,7 @@ private void OnRefreshTimer(object sender, ElapsedEventArgs e)
private void UpgradeNotification()
{
- int numUpgradeable = mainModList.Modules.Count(mod => mod.HasUpdate);
+ int numUpgradeable = ManageMods.mainModList.Modules.Count(mod => mod.HasUpdate);
if (numUpgradeable > 0)
{
Util.Invoke(this, () =>
@@ -212,12 +212,12 @@ private void minimizeNotifyIcon_BalloonTipClicked(object sender, EventArgs e)
OpenWindow();
// Check all the upgrade checkboxes
- MarkAllUpdatesToolButton_Click(null, null);
+ ManageMods.MarkAllUpdates();
// Install
installWorker.RunWorkerAsync(
new KeyValuePair, RelationshipResolverOptions>(
- mainModList.ComputeUserChangeSet(RegistryManager.Instance(Main.Instance.CurrentInstance).registry).ToList(),
+ ManageMods.mainModList.ComputeUserChangeSet(RegistryManager.Instance(Main.Instance.CurrentInstance).registry).ToList(),
RelationshipResolver.DependsOnlyOpts()
)
);
diff --git a/GUI/Main/MainTabControl.cs b/GUI/Main/MainTabControl.cs
index 95d57ae238..d839949479 100644
--- a/GUI/Main/MainTabControl.cs
+++ b/GUI/Main/MainTabControl.cs
@@ -11,7 +11,7 @@ protected override void OnSelectedIndexChanged(EventArgs e)
{
case "ManageModsTabPage":
// Focus the grid
- Main.Instance.ModList.Focus();
+ Main.Instance.ManageMods.ModGrid.Focus();
break;
}
}
diff --git a/GUI/Main/MainTrayIcon.cs b/GUI/Main/MainTrayIcon.cs
index b06071474f..9118e765a4 100644
--- a/GUI/Main/MainTrayIcon.cs
+++ b/GUI/Main/MainTrayIcon.cs
@@ -50,7 +50,7 @@ private void UpdateTrayState()
private void UpdateTrayInfo()
{
- var count = mainModList.CountModsByFilter(GUIModFilter.InstalledUpdateAvailable);
+ var count = ManageMods.mainModList.CountModsByFilter(GUIModFilter.InstalledUpdateAvailable);
if (count == 0)
{
@@ -81,7 +81,7 @@ private void minimizeNotifyIcon_MouseDoubleClick(object sender, MouseEventArgs e
private void updatesToolStripMenuItem_Click(object sender, EventArgs e)
{
OpenWindow();
- MarkAllUpdatesToolButton_Click(sender, e);
+ ManageMods.MarkAllUpdates();
}
private void refreshToolStripMenuItem_Click(object sender, EventArgs e)
diff --git a/GUI/Model/GUIMod.cs b/GUI/Model/GUIMod.cs
index ea551177cc..8405d549cf 100644
--- a/GUI/Model/GUIMod.cs
+++ b/GUI/Model/GUIMod.cs
@@ -27,7 +27,6 @@ public CkanModule SelectedMod
if (!(selectedMod?.Equals(value) ?? value?.Equals(selectedMod) ?? true))
{
selectedMod = value;
- var row = Main.Instance?.mainModList?.full_list_of_mod_rows?[Identifier];
if (IsInstalled && HasUpdate)
{
@@ -35,13 +34,14 @@ public CkanModule SelectedMod
if (IsUpgradeChecked ^ isLatest)
{
// Try upgrading if they pick the latest
- Main.Instance.MarkModForUpdate(Identifier, isLatest);
+ Main.Instance.ManageMods.MarkModForUpdate(Identifier, isLatest);
}
}
- Main.Instance.MarkModForInstall(Identifier, selectedMod == null);
+ Main.Instance.ManageMods.MarkModForInstall(Identifier, selectedMod == null);
- Main.Instance.UpdateChangeSetAndConflicts(
+ Main.Instance.ManageMods.UpdateChangeSetAndConflicts(
+ Main.Instance.Manager.CurrentInstance,
RegistryManager.Instance(Main.Instance.Manager.CurrentInstance).registry
);
diff --git a/GUI/Model/ModList.cs b/GUI/Model/ModList.cs
new file mode 100644
index 0000000000..b46471e21c
--- /dev/null
+++ b/GUI/Model/ModList.cs
@@ -0,0 +1,501 @@
+using System;
+using System.Drawing;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Reflection;
+using System.Text.RegularExpressions;
+using System.Windows.Forms;
+using CKAN.Versioning;
+
+namespace CKAN
+{
+ public enum GUIModFilter
+ {
+ Compatible = 0,
+ Installed = 1,
+ InstalledUpdateAvailable = 2,
+ NewInRepository = 3,
+ NotInstalled = 4,
+ Incompatible = 5,
+ All = 6,
+ Cached = 7,
+ Replaceable = 8,
+ Uncached = 9,
+ CustomLabel = 10,
+ Tag = 11,
+ }
+
+ public class ModList
+ {
+ //identifier, row
+ internal Dictionary full_list_of_mod_rows;
+
+ public ModList(ModFiltersUpdatedEvent onModFiltersUpdated)
+ {
+ Modules = new ReadOnlyCollection(new List());
+ ModFiltersUpdated += onModFiltersUpdated ?? (source => { });
+ ModFiltersUpdated(this);
+ }
+
+ public delegate void ModFiltersUpdatedEvent(ModList source);
+
+ //TODO Move to relationship resolver and have it use this.
+ public delegate Task HandleTooManyProvides(TooManyModsProvideKraken kraken);
+
+ public event ModFiltersUpdatedEvent ModFiltersUpdated;
+ public ReadOnlyCollection Modules { get; set; }
+
+ public GUIModFilter ModFilter
+ {
+ get { return _modFilter; }
+ set
+ {
+ var old = _modFilter;
+ _modFilter = value;
+ if (!old.Equals(value)) ModFiltersUpdated(this);
+ }
+ }
+
+ public readonly ModuleLabelList ModuleLabels = ModuleLabelList.Load(ModuleLabelList.DefaultPath)
+ ?? ModuleLabelList.GetDefaultLabels();
+
+ public readonly ModuleTagList ModuleTags = ModuleTagList.Load(ModuleTagList.DefaultPath)
+ ?? new ModuleTagList();
+
+ private ModuleTag _tagFilter;
+ public ModuleTag TagFilter
+ {
+ get { return _tagFilter; }
+ set
+ {
+ var old = _tagFilter;
+ _tagFilter = value;
+ if (!old?.Equals(value) ?? !value?.Equals(old) ?? false)
+ {
+ ModFiltersUpdated(this);
+ }
+ }
+ }
+
+ private ModuleLabel _customLabelFilter;
+ public ModuleLabel CustomLabelFilter
+ {
+ get { return _customLabelFilter; }
+ set
+ {
+ var old = _customLabelFilter;
+ _customLabelFilter = value;
+ if (!old?.Equals(value) ?? !value?.Equals(old) ?? false)
+ {
+ ModFiltersUpdated(this);
+ }
+ }
+ }
+
+ private GUIModFilter _modFilter = GUIModFilter.Compatible;
+ private ModSearch activeSearch = null;
+
+ public void SetSearch(ModSearch newSearch)
+ {
+ activeSearch = newSearch;
+ ModFiltersUpdated(this);
+ }
+
+ ///
+ /// This function returns a changeset based on the selections of the user.
+ /// Currently returns null if a conflict is detected.
+ ///
+ ///
+ ///
+ /// A module installer for the current KSP install
+ /// The version of the current KSP install
+ public IEnumerable ComputeChangeSetFromModList(
+ IRegistryQuerier registry, HashSet changeSet, ModuleInstaller installer,
+ KspVersionCriteria version)
+ {
+ var modules_to_install = new HashSet();
+ var modules_to_remove = new HashSet();
+
+ foreach (var change in changeSet)
+ {
+ switch (change.ChangeType)
+ {
+ case GUIModChangeType.None:
+ break;
+ case GUIModChangeType.Update:
+ case GUIModChangeType.Install:
+ modules_to_install.Add(change.Mod);
+ break;
+ case GUIModChangeType.Remove:
+ modules_to_remove.Add(change.Mod);
+ break;
+ case GUIModChangeType.Replace:
+ ModuleReplacement repl = registry.GetReplacement(change.Mod, version);
+ if (repl != null)
+ {
+ modules_to_remove.Add(repl.ToReplace);
+ modules_to_install.Add(repl.ReplaceWith);
+ }
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ var installed_modules =
+ registry.InstalledModules.Select(imod => imod.Module).ToDictionary(mod => mod.identifier, mod => mod);
+
+ foreach (var dependent in registry.FindReverseDependencies(
+ modules_to_remove
+ .Select(mod => mod.identifier)
+ .Except(modules_to_install.Select(m => m.identifier)),
+ modules_to_install
+ ))
+ {
+ //TODO This would be a good place to have an event that alters the row's graphics to show it will be removed
+ CkanModule depMod;
+ if (installed_modules.TryGetValue(dependent, out depMod))
+ {
+ CkanModule module_by_version = registry.GetModuleByVersion(depMod.identifier,
+ depMod.version)
+ ?? registry.InstalledModule(dependent).Module;
+ changeSet.Add(new ModChange(module_by_version, GUIModChangeType.Remove, null));
+ modules_to_remove.Add(module_by_version);
+ }
+ }
+ foreach (var im in registry.FindRemovableAutoInstalled(
+ registry.InstalledModules.Where(im => !modules_to_remove.Any(m => m.identifier == im.identifier) || modules_to_install.Any(m => m.identifier == im.identifier))
+ ))
+ {
+ changeSet.Add(new ModChange(im.Module, GUIModChangeType.Remove, new SelectionReason.NoLongerUsed()));
+ modules_to_remove.Add(im.Module);
+ }
+
+ // Get as many dependencies as we can, but leave decisions and prompts for installation time
+ RelationshipResolverOptions opts = RelationshipResolver.DependsOnlyOpts();
+ opts.without_toomanyprovides_kraken = true;
+ opts.without_enforce_consistency = true;
+
+ var resolver = new RelationshipResolver(
+ modules_to_install,
+ modules_to_remove,
+ opts, registry, version);
+ changeSet.UnionWith(
+ resolver.ModList()
+ .Select(m => new ModChange(m, GUIModChangeType.Install, resolver.ReasonFor(m))));
+
+ return changeSet;
+ }
+
+ public bool IsVisible(GUIMod mod, string instanceName)
+ {
+ return (activeSearch?.Matches(mod) ?? true)
+ && IsModInFilter(ModFilter, TagFilter, CustomLabelFilter, mod)
+ && !HiddenByTagsOrLabels(ModFilter, TagFilter, CustomLabelFilter, mod, instanceName);
+ }
+
+ private bool HiddenByTagsOrLabels(GUIModFilter filter, ModuleTag tag, ModuleLabel label, GUIMod m, string instanceName)
+ {
+ if (filter != GUIModFilter.CustomLabel)
+ {
+ // "Hide" labels apply to all non-custom filters
+ if (ModuleLabels?.LabelsFor(instanceName)
+ .Where(l => l != label && l.Hide)
+ .Any(l => l.ModuleIdentifiers.Contains(m.Identifier))
+ ?? false)
+ {
+ return true;
+ }
+ if (ModuleTags?.Tags?.Values
+ .Where(t => t != tag && t.Visible == false)
+ .Any(t => t.ModuleIdentifiers.Contains(m.Identifier))
+ ?? false)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public int CountModsByFilter(GUIModFilter filter)
+ {
+ if (filter == GUIModFilter.All)
+ {
+ // Don't check each one
+ return Modules.Count;
+ }
+ // Tags and Labels are not counted here
+ return Modules.Count(m => IsModInFilter(filter, null, null, m));
+ }
+
+ ///
+ /// Constructs the mod list suitable for display to the user.
+ /// Manipulates full_list_of_mod_rows.
+ ///
+ /// 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)
+ {
+ List changes = mc?.ToList();
+ full_list_of_mod_rows = modules.ToDictionary(
+ gm => gm.Identifier,
+ gm => MakeRow(gm, changes, instanceName, hideEpochs, hideV)
+ );
+ return full_list_of_mod_rows.Values;
+ }
+
+ private DataGridViewRow MakeRow(GUIMod mod, List changes, string instanceName, bool hideEpochs = false, bool hideV = false)
+ {
+ DataGridViewRow item = new DataGridViewRow() {Tag = mod};
+
+ Color? myColor = ModuleLabels.LabelsFor(instanceName)
+ .FirstOrDefault(l => l.ModuleIdentifiers.Contains(mod.Identifier))
+ ?.Color;
+ if (myColor.HasValue)
+ {
+ item.DefaultCellStyle.BackColor = myColor.Value;
+ }
+
+ ModChange myChange = changes?.FindLast((ModChange ch) => ch.Mod.Equals(mod));
+
+ var selecting = mod.IsInstallable()
+ ? (DataGridViewCell) new DataGridViewCheckBoxCell()
+ {
+ Value = myChange == null ? mod.IsInstalled
+ : myChange.ChangeType == GUIModChangeType.Install ? true
+ : myChange.ChangeType == GUIModChangeType.Remove ? false
+ : mod.IsInstalled
+ }
+ : new DataGridViewTextBoxCell()
+ {
+ Value = mod.IsAutodetected ? Properties.Resources.MainModListAutoDetected : "-"
+ };
+
+ var autoInstalled = mod.IsInstalled && !mod.IsAutodetected
+ ? (DataGridViewCell) new DataGridViewCheckBoxCell()
+ {
+ Value = mod.IsAutoInstalled
+ }
+ : new DataGridViewTextBoxCell()
+ {
+ Value = "-"
+ };
+
+ var updating = mod.IsInstallable() && mod.HasUpdate
+ ? (DataGridViewCell) new DataGridViewCheckBoxCell()
+ {
+ Value = myChange == null ? false
+ : myChange.ChangeType == GUIModChangeType.Update ? true
+ : false
+ }
+ : new DataGridViewTextBoxCell()
+ {
+ Value = "-"
+ };
+
+ var replacing = IsModInFilter(GUIModFilter.Replaceable, null, null, mod)
+ ? (DataGridViewCell) new DataGridViewCheckBoxCell()
+ {
+ Value = myChange == null ? false
+ : myChange.ChangeType == GUIModChangeType.Replace ? true
+ : false
+ }
+ : new DataGridViewTextBoxCell()
+ {
+ Value = "-"
+ };
+
+ var name = new DataGridViewTextBoxCell() {Value = mod.Name};
+ var author = new DataGridViewTextBoxCell() {Value = mod.Authors};
+
+ var installVersion = new DataGridViewTextBoxCell()
+ {
+ Value = hideEpochs
+ ? (hideV
+ ? ModuleInstaller.StripEpoch(ModuleInstaller.StripV(mod.InstalledVersion ?? ""))
+ : ModuleInstaller.StripEpoch(mod.InstalledVersion ?? ""))
+ : (hideV
+ ? ModuleInstaller.StripV(mod.InstalledVersion ?? "")
+ : 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)
+ };
+
+ var downloadCount = new DataGridViewTextBoxCell() { Value = String.Format("{0:N0}", mod.DownloadCount) };
+ var compat = new DataGridViewTextBoxCell() { Value = mod.KSPCompatibility };
+ var size = new DataGridViewTextBoxCell() { Value = mod.DownloadSize };
+ var installDate = new DataGridViewTextBoxCell() { Value = mod.InstallDate };
+ var desc = new DataGridViewTextBoxCell() { Value = mod.Abstract };
+
+ item.Cells.AddRange(selecting, autoInstalled, updating, replacing, name, author, installVersion, latestVersion, compat, size, installDate, downloadCount, desc);
+
+ selecting.ReadOnly = selecting is DataGridViewTextBoxCell;
+ autoInstalled.ReadOnly = autoInstalled is DataGridViewTextBoxCell;
+ updating.ReadOnly = updating is DataGridViewTextBoxCell;
+
+ return item;
+ }
+
+ public Color GetRowBackground(GUIMod mod, bool conflicted, string instanceName)
+ {
+ if (conflicted)
+ {
+ return Color.LightCoral;
+ }
+ DataGridViewRow row;
+ if (full_list_of_mod_rows.TryGetValue(mod.Identifier, out row))
+ {
+ Color? myColor = ModuleLabels.LabelsFor(instanceName)
+ .FirstOrDefault(l => l.ModuleIdentifiers.Contains(mod.Identifier))
+ ?.Color;
+ if (myColor.HasValue)
+ {
+ return myColor.Value;
+ }
+ }
+ return Color.Empty;
+ }
+
+ ///
+ /// Update the color and visible state of the given row
+ /// after it has been added to or removed from a label group
+ ///
+ /// The mod that needs an update
+ public void ReapplyLabels(GUIMod mod, bool conflicted, string instanceName)
+ {
+ DataGridViewRow row;
+ if (full_list_of_mod_rows.TryGetValue(mod.Identifier, out row))
+ {
+ row.DefaultCellStyle.BackColor = GetRowBackground(mod, conflicted, instanceName);
+ row.Visible = IsVisible(mod, instanceName);
+ }
+ }
+
+ ///
+ /// Returns a version string shorn of any leading epoch as delimited by a single colon
+ ///
+ public string StripEpoch(string version)
+ {
+ // If our version number starts with a string of digits, followed by
+ // a colon, and then has no more colons, we're probably safe to assume
+ // the first string of digits is an epoch
+ //return Regex.IsMatch(version, @"^[0-9][0-9]*:[^:]+$") ? Regex.Replace(version, @"^([^:]+):([^:]+)$", @"$2") : version;
+ return ContainsEpoch.IsMatch(version) ? RemoveEpoch.Replace(version, @"$2") : version;
+ }
+
+ private static readonly Regex ContainsEpoch = new Regex(@"^[0-9][0-9]*:[^:]+$", RegexOptions.Compiled);
+ private static readonly Regex RemoveEpoch = new Regex(@"^([^:]+):([^:]+)$", RegexOptions.Compiled);
+
+ private bool IsModInFilter(GUIModFilter filter, ModuleTag tag, ModuleLabel label, GUIMod m)
+ {
+ switch (filter)
+ {
+ case GUIModFilter.Compatible: return !m.IsIncompatible;
+ case GUIModFilter.Installed: return m.IsInstalled;
+ case GUIModFilter.InstalledUpdateAvailable: return m.IsInstalled && m.HasUpdate;
+ case GUIModFilter.Cached: return m.IsCached;
+ case GUIModFilter.Uncached: return !m.IsCached;
+ case GUIModFilter.NewInRepository: return m.IsNew;
+ case GUIModFilter.NotInstalled: return !m.IsInstalled;
+ case GUIModFilter.Incompatible: return m.IsIncompatible;
+ case GUIModFilter.Replaceable: return m.IsInstalled && m.HasReplacement;
+ case GUIModFilter.All: return true;
+ case GUIModFilter.Tag: return tag?.ModuleIdentifiers.Contains(m.Identifier)
+ ?? ModuleTags.Untagged.Contains(m.Identifier);
+ case GUIModFilter.CustomLabel: return label?.ModuleIdentifiers?.Contains(m.Identifier) ?? false;
+ default: throw new Kraken(string.Format(Properties.Resources.MainModListUnknownFilter, filter));
+ }
+ }
+
+ public static Dictionary ComputeConflictsFromModList(IRegistryQuerier registry,
+ IEnumerable change_set, KspVersionCriteria ksp_version)
+ {
+ var modules_to_install = new HashSet();
+ var modules_to_remove = new HashSet();
+ var options = new RelationshipResolverOptions
+ {
+ without_toomanyprovides_kraken = true,
+ proceed_with_inconsistencies = true,
+ without_enforce_consistency = true,
+ with_recommends = false
+ };
+
+ foreach (var change in change_set)
+ {
+ switch (change.ChangeType)
+ {
+ case GUIModChangeType.None:
+ break;
+ case GUIModChangeType.Install:
+ modules_to_install.Add(change.Mod.identifier);
+ break;
+ case GUIModChangeType.Remove:
+ modules_to_remove.Add(change.Mod.identifier);
+ break;
+ case GUIModChangeType.Update:
+ break;
+ case GUIModChangeType.Replace:
+ ModuleReplacement repl = registry.GetReplacement(change.Mod, ksp_version);
+ if (repl != null)
+ {
+ modules_to_remove.Add(repl.ToReplace.identifier);
+ modules_to_install.Add(repl.ReplaceWith.identifier);
+ }
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ // Only check mods that would exist after the changes are made.
+ IEnumerable installed = registry.InstalledModules.Where(
+ im => !modules_to_remove.Contains(im.Module.identifier)
+ ).Select(im => im.Module);
+
+ // Convert ONLY modules_to_install with CkanModule.FromIDandVersion,
+ // because it may not find already-installed modules.
+ IEnumerable mods_to_check = installed.Union(
+ modules_to_install.Except(modules_to_remove).Select(
+ name => CkanModule.FromIDandVersion(registry, name, ksp_version)
+ )
+ );
+ var resolver = new RelationshipResolver(
+ mods_to_check,
+ change_set.Where(ch => ch.ChangeType == GUIModChangeType.Remove)
+ .Select(ch => ch.Mod),
+ options, registry, ksp_version
+ );
+ return resolver.ConflictList.ToDictionary(item => new GUIMod(item.Key, registry, ksp_version),
+ item => item.Value);
+ }
+
+ public HashSet ComputeUserChangeSet(IRegistryQuerier registry)
+ {
+ var removableAuto = registry?.FindRemovableAutoInstalled(registry?.InstalledModules)
+ ?? new InstalledModule[] {};
+ return new HashSet(
+ Modules
+ .SelectMany(mod => mod.GetModChanges())
+ .Union(removableAuto.Select(im => new ModChange(
+ im.Module,
+ GUIModChangeType.Remove,
+ new SelectionReason.NoLongerUsed())))
+ );
+ }
+ }
+}
diff --git a/GUI/Model/ModSearch.cs b/GUI/Model/ModSearch.cs
new file mode 100644
index 0000000000..c341418599
--- /dev/null
+++ b/GUI/Model/ModSearch.cs
@@ -0,0 +1,302 @@
+using System;
+using System.Linq;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+
+namespace CKAN
+{
+ ///
+ /// An object representing a search to be performed of the mod list.
+ /// Create one with the constructor or Parse(), and use it with Matches().
+ ///
+ public sealed class ModSearch
+ {
+ ///
+ /// Initialize a mod search object.
+ /// Null or empty parameters are treated as matching everything.
+ ///
+ /// String to search for in mod names, identifiers, and abbreviations
+ /// String to search for in author names
+ /// String to search for in mod descriptions
+ /// Language to search for in mod localizations
+ /// Identifier prefix to find in mod depends relationships
+ /// Identifier prefix to find in mod recommends relationships
+ /// Identifier prefix to find in mod suggests relationships
+ /// Identifier prefix to find in mod conflicts relationships
+ /// Full formatted search string if known, will be auto generated otherwise
+ public ModSearch(
+ string byName, string byAuthor, string byDescription, string localization,
+ string depends, string recommends, string suggests, string conflicts,
+ string combined = null)
+ {
+ Name = CkanModule.nonAlphaNums.Replace(byName, "");
+ Author = CkanModule.nonAlphaNums.Replace(byAuthor, "");
+ Description = CkanModule.nonAlphaNums.Replace(byDescription, "");
+ Localization = localization;
+
+ DependsOn = depends;
+ Recommends = recommends;
+ Suggests = suggests;
+ ConflictsWith = conflicts;
+
+ Combined = combined ?? getCombined();
+ }
+
+ ///
+ /// String to search for in mod names, identifiers, and abbreviations
+ ///
+ public readonly string Name;
+
+ ///
+ /// String to search for in author names
+ ///
+ public readonly string Author;
+
+ ///
+ /// String to search for in mod descriptions
+ ///
+ public readonly string Description;
+
+ ///
+ /// Language to search for in mod localizations
+ ///
+ public readonly string Localization;
+
+ ///
+ /// Identifier prefix to find in mod depends relationships
+ ///
+ public readonly string DependsOn;
+
+ ///
+ /// Identifier prefix to find in mod recommends relationships
+ ///
+ public readonly string Recommends;
+
+ ///
+ /// Identifier prefix to find in mod suggests relationships
+ ///
+ public readonly string Suggests;
+
+ ///
+ /// Identifier prefix to find in mod conflicts relationships
+ ///
+ public readonly string ConflictsWith;
+
+ ///
+ /// Full formatted search string
+ ///
+ public readonly string Combined;
+
+ ///
+ /// Generate a full formatted search string from the parameters.
+ /// MUST be the inverse of Parse!
+ ///
+ ///
+ ///
+ ///
+ private string getCombined()
+ {
+ var pieces = new List();
+ if (!string.IsNullOrWhiteSpace(Name))
+ {
+ pieces.Add(Name);
+ }
+ if (!string.IsNullOrWhiteSpace(Author))
+ {
+ pieces.Add($"@{Author}");
+ }
+ if (!string.IsNullOrWhiteSpace(Description))
+ {
+ pieces.Add($"{Properties.Resources.ModSearchDescriptionPrefix}{Description}");
+ }
+ if (!string.IsNullOrWhiteSpace(Localization))
+ {
+ pieces.Add($"{Properties.Resources.ModSearchLanguagePrefix}{Localization}");
+ }
+ if (!string.IsNullOrWhiteSpace(DependsOn))
+ {
+ pieces.Add($"{Properties.Resources.ModSearchDependsPrefix}{DependsOn}");
+ }
+ if (!string.IsNullOrWhiteSpace(Recommends))
+ {
+ pieces.Add($"{Properties.Resources.ModSearchRecommendsPrefix}{Recommends}");
+ }
+ if (!string.IsNullOrWhiteSpace(Suggests))
+ {
+ pieces.Add($"{Properties.Resources.ModSearchSuggestsPrefix}{Suggests}");
+ }
+ if (!string.IsNullOrWhiteSpace(ConflictsWith))
+ {
+ pieces.Add($"{Properties.Resources.ModSearchConflictsPrefix}{ConflictsWith}");
+ }
+ return pieces.Count == 0
+ ? null
+ : string.Join(" ", pieces);
+ }
+
+ ///
+ /// Parse a full formatted search string into its component parts.
+ /// May throw a Kraken if the syntax is bad.
+ /// MUST be the inverse of getCombined!
+ ///
+ /// Full formatted search string
+ ///
+ /// New search object, or null if no search terms defined
+ ///
+ public static ModSearch Parse(string combined)
+ {
+ if (string.IsNullOrWhiteSpace(combined))
+ {
+ return null;
+ }
+ string byName = "";
+ string byAuthor = "";
+ string byDescription = "";
+ string byLocalization = "";
+
+ string depends = "";
+ string recommends = "";
+ string suggests = "";
+ string conflicts = "";
+
+ var pieces = combined.Split(' ');
+ foreach (string s in pieces)
+ {
+ if (TryPrefix(s, "@", out string auth))
+ {
+ if (string.IsNullOrEmpty(byAuthor))
+ {
+ byAuthor = CkanModule.nonAlphaNums.Replace(auth, "");
+ }
+ else
+ {
+ throw new Kraken("Can't search multiple authors!");
+ }
+ }
+ else if (TryPrefix(s, Properties.Resources.ModSearchDescriptionPrefix, out string desc))
+ {
+ byDescription += CkanModule.nonAlphaNums.Replace(desc, "");
+ }
+ else if (TryPrefix(s, Properties.Resources.ModSearchLanguagePrefix, out string lang))
+ {
+ byLocalization += lang;
+ }
+ else if (TryPrefix(s, Properties.Resources.ModSearchDependsPrefix, out string dep))
+ {
+ depends += dep;
+ }
+ else if (TryPrefix(s, Properties.Resources.ModSearchRecommendsPrefix, out string rec))
+ {
+ recommends += rec;
+ }
+ else if (TryPrefix(s, Properties.Resources.ModSearchSuggestsPrefix, out string sug))
+ {
+ suggests += sug;
+ }
+ else if (TryPrefix(s, Properties.Resources.ModSearchConflictsPrefix, out string conf))
+ {
+ conflicts += conf;
+ }
+ else
+ {
+ // No special format = search names and identifiers
+ byName += CkanModule.nonAlphaNums.Replace(s, "");
+ }
+ }
+ return new ModSearch(
+ byName, byAuthor, byDescription, byLocalization,
+ depends, recommends, suggests, conflicts,
+ combined
+ );
+ }
+
+ private static bool TryPrefix(string container, string prefix, out string remainder)
+ {
+ if (container.StartsWith(prefix))
+ {
+ remainder = container.Substring(prefix.Length);
+ return true;
+ }
+ else
+ {
+ remainder = "";
+ return false;
+ }
+ }
+
+ ///
+ /// Check whether our filters match the given mod.
+ ///
+ /// Mod to check
+ ///
+ /// true if mod matches filters, false otherwise
+ ///
+ public bool Matches(GUIMod mod)
+ {
+ return MatchesName(mod)
+ && MatchesAuthor(mod)
+ && MatchesDescription(mod)
+ && MatchesLocalization(mod)
+ && MatchesDepends(mod)
+ && MatchesRecommends(mod)
+ && MatchesSuggests(mod)
+ && MatchesConflicts(mod);
+ }
+
+ private bool MatchesName(GUIMod mod)
+ {
+ return string.IsNullOrWhiteSpace(Name)
+ || mod.Abbrevation.IndexOf(Name, StringComparison.InvariantCultureIgnoreCase) != -1
+ || mod.SearchableName.IndexOf(Name, StringComparison.InvariantCultureIgnoreCase) != -1
+ || mod.SearchableIdentifier.IndexOf(Name, StringComparison.InvariantCultureIgnoreCase) != -1;
+ }
+
+ private bool MatchesAuthor(GUIMod mod)
+ {
+ return string.IsNullOrWhiteSpace(Author)
+ || mod.SearchableAuthors.Any(author =>
+ author.IndexOf(Author, StringComparison.InvariantCultureIgnoreCase) != -1);
+ }
+
+ private bool MatchesDescription(GUIMod mod)
+ {
+ return string.IsNullOrWhiteSpace(Description)
+ || mod.SearchableAbstract.IndexOf(Description, StringComparison.InvariantCultureIgnoreCase) != -1
+ || mod.SearchableDescription.IndexOf(Description, StringComparison.InvariantCultureIgnoreCase) != -1;
+ }
+
+ private bool MatchesLocalization(GUIMod mod)
+ {
+ var ckm = mod.ToModule();
+ return string.IsNullOrWhiteSpace(Localization)
+ || (
+ ckm.localizations != null
+ && ckm.localizations.Any(loc =>
+ loc.IndexOf(Localization, StringComparison.InvariantCultureIgnoreCase) != -1)
+ );
+ }
+
+ private bool MatchesDepends(GUIMod mod)
+ {
+ return RelationshipMatch(mod.ToModule().depends, DependsOn);
+ }
+ private bool MatchesRecommends(GUIMod mod)
+ {
+ return RelationshipMatch(mod.ToModule().recommends, Recommends);
+ }
+ private bool MatchesSuggests(GUIMod mod)
+ {
+ return RelationshipMatch(mod.ToModule().suggests, Suggests);
+ }
+ private bool MatchesConflicts(GUIMod mod)
+ {
+ return RelationshipMatch(mod.ToModule().conflicts, ConflictsWith);
+ }
+ private bool RelationshipMatch(List rels, string toFind)
+ {
+ return string.IsNullOrWhiteSpace(toFind)
+ || (rels != null && rels.Any(r => r.StartsWith(toFind)));
+ }
+
+ }
+}
diff --git a/GUI/Properties/Resources.Designer.cs b/GUI/Properties/Resources.Designer.cs
index f1305f8d22..3844af437b 100644
--- a/GUI/Properties/Resources.Designer.cs
+++ b/GUI/Properties/Resources.Designer.cs
@@ -920,5 +920,27 @@ internal static string EditModpackTooltipCancel {
internal static string EditModpackTooltipExport {
get { return (string)(ResourceManager.GetObject("EditModpackTooltipExport", resourceCulture)); }
}
+
+ internal static string ModSearchDescriptionPrefix {
+ get { return (string)(ResourceManager.GetObject("ModSearchDescriptionPrefix", resourceCulture)); }
+ }
+ internal static string ModSearchLanguagePrefix {
+ get { return (string)(ResourceManager.GetObject("ModSearchLanguagePrefix", resourceCulture)); }
+ }
+ internal static string ModSearchDependsPrefix {
+ get { return (string)(ResourceManager.GetObject("ModSearchDependsPrefix", resourceCulture)); }
+ }
+ internal static string ModSearchRecommendsPrefix {
+ get { return (string)(ResourceManager.GetObject("ModSearchRecommendsPrefix", resourceCulture)); }
+ }
+ internal static string ModSearchSuggestsPrefix {
+ get { return (string)(ResourceManager.GetObject("ModSearchSuggestsPrefix", resourceCulture)); }
+ }
+ internal static string ModSearchConflictsPrefix {
+ get { return (string)(ResourceManager.GetObject("ModSearchConflictsPrefix", resourceCulture)); }
+ }
+ internal static string EditModSearchTooltipExpandButton {
+ get { return (string)(ResourceManager.GetObject("EditModSearchTooltipExpandButton", resourceCulture)); }
+ }
}
}
diff --git a/GUI/Properties/Resources.resx b/GUI/Properties/Resources.resx
index c3e71b05af..0291c59923 100644
--- a/GUI/Properties/Resources.resx
+++ b/GUI/Properties/Resources.resx
@@ -395,4 +395,11 @@ Do you want to allow CKAN to do this? If you click no you won't see this message
Move selected mods to the Ignored group. These mods won't be included in the modpack.
Abort modpack creation
Choose a filename and save the modpack
+ desc:
+ lang:
+ dep:
+ rec:
+ sug:
+ conf:
+ Expand or collapse the detailed search fields (Ctrl-Shift-F)
diff --git a/Tests/GUI/GH1866.cs b/Tests/GUI/GH1866.cs
index 74df15048f..53fbf88180 100644
--- a/Tests/GUI/GH1866.cs
+++ b/Tests/GUI/GH1866.cs
@@ -22,8 +22,8 @@ public class GH1866
private KSPManager _manager;
private RegistryManager _registryManager;
private Registry _registry;
- private MainModList _modList;
- private MainModListGUI _listGui;
+ private ModList _modList;
+ private DataGridView _listGui;
/*
* an exception would be thrown at the bottom of this
@@ -79,8 +79,8 @@ public void Up()
_registry.AddAvailable(TestData.kOS_014_module());
// test object
- _modList = new MainModList(null, _manager.User);
- _listGui = new MainModListGUI();
+ _modList = new ModList(null);
+ _listGui = new DataGridView();
// todo: refactor the column header code to allow mocking of the GUI without creating columns
_listGui.Columns.Add(new DataGridViewCheckBoxColumn());
diff --git a/Tests/GUI/MainModList.cs b/Tests/GUI/ModList.cs
similarity index 79%
rename from Tests/GUI/MainModList.cs
rename to Tests/GUI/ModList.cs
index 2d13fed72f..838b535e7a 100644
--- a/Tests/GUI/MainModList.cs
+++ b/Tests/GUI/ModList.cs
@@ -13,32 +13,20 @@
namespace Tests.GUI
{
[TestFixture]
- public class MainModListTests
+ public class ModListTests
{
[Test]
public void OnCreation_HasDefaultFilters()
{
- var item = new MainModList(delegate { });
+ var item = new ModList(delegate { });
Assert.AreEqual(GUIModFilter.Compatible, item.ModFilter, "ModFilter");
- Assert.AreEqual(String.Empty, item.ModNameFilter, "ModNameFilter");
}
- [Test]
- public void OnModTextFilterChanges_CallsEventHandler()
- {
- var called_n = 0;
- var item = new MainModList(delegate { called_n++; });
- Assert.That(called_n == 1);
- item.ModNameFilter = "randomString";
- Assert.That(called_n == 2);
- item.ModNameFilter = "randomString";
- Assert.That(called_n == 2);
- }
[Test]
public void OnModTypeFilterChanges_CallsEventHandler()
{
var called_n = 0;
- var item = new MainModList(delegate { called_n++; });
+ var item = new ModList(delegate { called_n++; });
Assert.That(called_n == 1);
item.ModFilter = GUIModFilter.Installed;
Assert.That(called_n == 2);
@@ -49,7 +37,7 @@ public void OnModTypeFilterChanges_CallsEventHandler()
[Test]
public void ComputeChangeSetFromModList_WithEmptyList_HasEmptyChangeSet()
{
- var item = new MainModList(delegate { });
+ var item = new ModList(delegate { });
Assert.That(item.ComputeUserChangeSet(null), Is.Empty);
}
@@ -68,7 +56,7 @@ public void IsVisible_WithAllAndNoNameFilter_ReturnsTrueForCompatible()
var ckan_mod = TestData.FireSpitterModule();
var registry = Registry.Empty();
registry.AddAvailable(ckan_mod);
- var item = new MainModList(delegate { });
+ var item = new ModList(delegate { });
Assert.That(item.IsVisible(
new GUIMod(ckan_mod, registry, manager.CurrentInstance.VersionCriteria()),
manager.CurrentInstance.Name
@@ -81,7 +69,7 @@ public void IsVisible_WithAllAndNoNameFilter_ReturnsTrueForCompatible()
[Test]
public void CountModsByFilter_EmptyModList_ReturnsZeroForAllFilters()
{
- var item = new MainModList(delegate { });
+ var item = new ModList(delegate { });
foreach (GUIModFilter filter in Enum.GetValues(typeof(GUIModFilter)))
{
Assert.That(item.CountModsByFilter(filter), Is.EqualTo(0));
@@ -104,7 +92,7 @@ public void ConstructModList_NumberOfRows_IsEqualToNumberOfMods()
var registry = Registry.Empty();
registry.AddAvailable(TestData.FireSpitterModule());
registry.AddAvailable(TestData.kOS_014_module());
- var main_mod_list = new MainModList(null);
+ var main_mod_list = new ModList(null);
var mod_list = main_mod_list.ConstructModList(
new List
{