Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Work around OpenFileDialog always showing all shortcuts despite filters #4168

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Core/CkanTransaction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public static TransactionScope CreateTransactionScope()
}

// System.ArgumentOutOfRangeException : Time-out interval must be less than 2^32-2. (Parameter 'dueTime')
private const double timeoutMs = Int32.MaxValue;
private const double timeoutMs = int.MaxValue;
private static readonly TimeSpan maxCoretimeout = TimeSpan.FromMilliseconds(timeoutMs);

private static readonly TransactionOptions transOpts = new TransactionOptions()
Expand Down
2 changes: 1 addition & 1 deletion Core/Configuration/JsonConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public JsonConfiguration(string newConfig = null)
// If you have multiple instances of CKAN running at the same time, each will
// believe that their copy of the config file in memory is authoritative, so
// changes made by one copy will not be respected by the other.
private string configFile = defaultConfigFile;
private readonly string configFile = defaultConfigFile;
private Config config = null;

public string DownloadCacheDir
Expand Down
115 changes: 71 additions & 44 deletions GUI/Dialogs/ManageGameInstancesDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,42 +18,24 @@ namespace CKAN.GUI
#endif
public partial class ManageGameInstancesDialog : Form
{
private static GameInstanceManager manager => Main.Instance.Manager;
private readonly IUser _user;
private RenameInstanceDialog _renameInstanceDialog;
private readonly OpenFileDialog _instanceDialog = new OpenFileDialog()
{
AddExtension = false,
CheckFileExists = false,
CheckPathExists = false,
InitialDirectory = Environment.CurrentDirectory,
Filter = GameFolderFilter(manager),
Multiselect = false
};

/// <summary>
/// Generate filter string for OpenFileDialog
/// </summary>
/// <param name="mgr">Game instance manager that can tell us about the build ID files</param>
/// <returns>
/// "Build metadata files (buildID.txt;buildID64.txt)|buildID.txt;buildID64.txt"
/// </returns>
public static string GameFolderFilter(GameInstanceManager mgr)
=> Properties.Resources.GameProgramFileDescription
+ "|" + string.Join(";", mgr.AllInstanceAnchorFiles);

public bool HasSelections => GameInstancesListView.SelectedItems.Count > 0;

/// <summary>
/// Initialize the game instance selection window
/// </summary>
/// <param name="mgr">Game instance manager object to provide our game instances</param>
/// <param name="centerScreen">true to center the window on the screen, false to center it on the parent</param>
public ManageGameInstancesDialog(bool centerScreen, IUser user)
/// <param name="user">IUser object reference for raising dialogs</param>
public ManageGameInstancesDialog(GameInstanceManager mgr,
bool centerScreen,
IUser user)
{
_user = user;
manager = mgr;
this.user = user;
InitializeComponent();
DialogResult = DialogResult.Cancel;

instanceDialog.Filter = GameFolderFilter(manager);
instanceDialog.FileOk += InstanceFileOK;

if (centerScreen)
{
StartPosition = FormStartPosition.CenterScreen;
Expand Down Expand Up @@ -101,6 +83,19 @@ public void UpdateInstancesList()
GameInstancesListView.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
}

/// <summary>
/// Generate filter string for OpenFileDialog
/// </summary>
/// <param name="mgr">Game instance manager that can tell us about the build ID files</param>
/// <returns>
/// "Build metadata files (buildID.txt;buildID64.txt)|buildID.txt;buildID64.txt"
/// </returns>
public static string GameFolderFilter(GameInstanceManager mgr)
=> Properties.Resources.GameProgramFileDescription
+ "|" + string.Join(";", mgr.AllInstanceAnchorFiles);

public bool HasSelections => GameInstancesListView.SelectedItems.Count > 0;

private void AddOrRemoveColumn(ListView listView, ColumnHeader column, bool condition, int index)
{
if (condition && !listView.Columns.Contains(column))
Expand Down Expand Up @@ -157,22 +152,20 @@ protected override void OnHelpButtonClicked(CancelEventArgs evt)
}

private static string FormatVersion(GameVersion v)
{
return v == null
=> v == null
? Properties.Resources.CompatibleGameVersionsDialogNone
// The BUILD component is not useful visually
: new GameVersion(v.Major, v.Minor, v.Patch).ToString();
}

private void AddToCKANMenuItem_Click(object sender, EventArgs e)
{
if (_instanceDialog.ShowDialog(this) != DialogResult.OK
|| !File.Exists(_instanceDialog.FileName))
if (instanceDialog.ShowDialog(this) != DialogResult.OK
|| !File.Exists(instanceDialog.FileName))
{
return;
}

var path = Path.GetDirectoryName(_instanceDialog.FileName);
var path = Path.GetDirectoryName(instanceDialog.FileName);
try
{
var instanceName = Path.GetFileName(path);
Expand All @@ -181,17 +174,17 @@ private void AddToCKANMenuItem_Click(object sender, EventArgs e)
instanceName = path;
}
instanceName = manager.GetNextValidInstanceName(instanceName);
manager.AddInstance(path, instanceName, _user);
manager.AddInstance(path, instanceName, user);
UpdateInstancesList();
}
catch (NotKSPDirKraken k)
{
_user.RaiseError(Properties.Resources.ManageGameInstancesNotValid,
user.RaiseError(Properties.Resources.ManageGameInstancesNotValid,
new object[] { k.path });
}
catch (Exception exc)
{
_user.RaiseError(exc.Message);
user.RaiseError(exc.Message);
}
}

Expand All @@ -213,7 +206,7 @@ private void CloneGameInstanceMenuItem_Click(object sender, EventArgs e)
{
var old_instance = manager.CurrentInstance;

var result = new CloneGameInstanceDialog(manager, _user, (string)GameInstancesListView.SelectedItems[0].Tag).ShowDialog(this);
var result = new CloneGameInstanceDialog(manager, user, (string)GameInstancesListView.SelectedItems[0].Tag).ShowDialog(this);
if (result == DialogResult.OK && !Equals(old_instance, manager.CurrentInstance))
{
DialogResult = DialogResult.OK;
Expand Down Expand Up @@ -246,7 +239,7 @@ private void UseSelectedInstance()
}
catch (NotKSPDirKraken k)
{
_user.RaiseError(Properties.Resources.ManageGameInstancesNotValid, k.path);
user.RaiseError(Properties.Resources.ManageGameInstancesNotValid, k.path);
}
}
}
Expand All @@ -270,7 +263,7 @@ private void SetAsDefaultCheckbox_Click(object sender, EventArgs e)
}
catch (NotKSPDirKraken k)
{
_user.RaiseError(Properties.Resources.ManageGameInstancesNotValid, k.path);
user.RaiseError(Properties.Resources.ManageGameInstancesNotValid, k.path);
}
}
}
Expand Down Expand Up @@ -321,7 +314,7 @@ private void OpenDirectoryMenuItem_Click(object sender, EventArgs e)

if (!Directory.Exists(path))
{
_user.RaiseError(Properties.Resources.ManageGameInstancesDirectoryDeleted, path);
user.RaiseError(Properties.Resources.ManageGameInstancesDirectoryDeleted, path);
return;
}

Expand All @@ -333,14 +326,14 @@ private void RenameButton_Click(object sender, EventArgs e)
var instance = (string)GameInstancesListView.SelectedItems[0].Tag;

// show the dialog, and only continue if the user selected "OK"
_renameInstanceDialog = new RenameInstanceDialog();
if (_renameInstanceDialog.ShowRenameInstanceDialog(instance) != DialogResult.OK)
var renameInstanceDialog = new RenameInstanceDialog();
if (renameInstanceDialog.ShowRenameInstanceDialog(instance) != DialogResult.OK)
{
return;
}

// proceed with instance rename
manager.RenameInstance(instance, _renameInstanceDialog.GetResult());
manager.RenameInstance(instance, renameInstanceDialog.GetResult());
UpdateInstancesList();
}

Expand All @@ -359,5 +352,39 @@ private void UpdateButtonState()
ForgetButton.Enabled = HasSelections && (string)GameInstancesListView.SelectedItems[0].Tag != manager.CurrentInstance?.Name;
ImportFromSteamMenuItem.Enabled = manager.SteamLibrary.Games.Length > 0;
}

private readonly GameInstanceManager manager;

private readonly IUser user;

private readonly OpenFileDialog instanceDialog = new OpenFileDialog()
{
AddExtension = false,
CheckFileExists = false,
CheckPathExists = false,
DereferenceLinks = false,
InitialDirectory = Environment.CurrentDirectory,
Multiselect = false,
};

private void InstanceFileOK(object sender, CancelEventArgs e)
{
if (sender is OpenFileDialog dlg)
{
// OpenFileDialog always shows shortcuts (!!!!!),
// so we have to re-enforce the filter ourselves
var chosen = Path.GetFileName(dlg.FileName);
var allowed = manager.AllInstanceAnchorFiles;
if (!allowed.Contains(chosen))
{
e.Cancel = true;
user.RaiseError(Properties.Resources.ManageGameInstancesInvalidFileSelected,
chosen,
string.Join(Environment.NewLine,
allowed.OrderBy(f => f)
.Select(f => $" - {f}")));
}
}
}
}
}
4 changes: 2 additions & 2 deletions GUI/Main/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ private bool InstancePromptAtStart()
bool gotInstance = false;
Util.Invoke(this, () =>
{
var result = new ManageGameInstancesDialog(!actuallyVisible, currentUser).ShowDialog(this);
var result = new ManageGameInstancesDialog(Manager, !actuallyVisible, currentUser).ShowDialog(this);
gotInstance = result == DialogResult.OK;
});
return gotInstance;
Expand All @@ -335,7 +335,7 @@ private bool InstancePromptAtStart()
private void manageGameInstancesMenuItem_Click(object sender, EventArgs e)
{
var old_instance = CurrentInstance;
var result = new ManageGameInstancesDialog(!actuallyVisible, currentUser).ShowDialog(this);
var result = new ManageGameInstancesDialog(Manager, !actuallyVisible, currentUser).ShowDialog(this);
if (result == DialogResult.OK && !Equals(old_instance, CurrentInstance))
{
for (bool done = false; !done;)
Expand Down
4 changes: 2 additions & 2 deletions GUI/Model/ModList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ public Tuple<IEnumerable<ModChange>, Dictionary<CkanModule, string>, List<string
}

foreach (var im in registry.FindRemovableAutoInstalled(
InstalledAfterChanges(registry, changeSet, version).ToList(), version))
InstalledAfterChanges(registry, changeSet).ToList(), version))
{
changeSet.Add(new ModChange(im.Module, GUIModChangeType.Remove, new SelectionReason.NoLongerUsed()));
modules_to_remove.Add(im.Module);
Expand Down Expand Up @@ -228,7 +228,7 @@ public Tuple<IEnumerable<ModChange>, Dictionary<CkanModule, string>, List<string
/// <param name="crit">Compatible versions of current instance</param>
/// <returns>Sequence of InstalledModules after the changes are applied, not including dependencies</returns>
private IEnumerable<InstalledModule> InstalledAfterChanges(
IRegistryQuerier registry, HashSet<ModChange> changeSet, GameVersionCriteria crit)
IRegistryQuerier registry, HashSet<ModChange> changeSet)
{
var removingIdents = changeSet
.Where(ch => ch.ChangeType != GUIModChangeType.Install)
Expand Down
7 changes: 7 additions & 0 deletions GUI/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,13 @@ You can refresh the mod list manually with the Refresh button at the top, and yo
<data name="ManageGameInstancesDirectoryDeleted" xml:space="preserve"><value>Directory "{0}" doesn't exist.</value></data>
<data name="ManageGameInstancesNameColumnInvalid" xml:space="preserve"><value>{0} (INVALID)</value></data>
<data name="ManageGameInstancesNameColumnLocked" xml:space="preserve"><value>{0} (LOCKED)</value></data>
<data name="ManageGameInstancesInvalidFileSelected" xml:space="preserve"><value>Not a valid game instance file: "{0}"

If you selected a shortcut, don't do that; Windows won't let us hide them from this dialog even though they're invalid.

Find the folder where your game is installed and choose one of these files:

{1}</value></data>
<data name="NewRepoDialogFailed" xml:space="preserve"><value>Failed to fetch master list.</value></data>
<data name="PluginsDialogFilter" xml:space="preserve"><value>CKAN Plugins (*.dll)|*.dll</value></data>
<data name="SettingsDialogSummmary" xml:space="preserve"><value>{0} files, {1}, {2} free</value></data>
Expand Down
1 change: 0 additions & 1 deletion Netkan/Transformers/InternalCkanTransformer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System.Collections.Generic;
using log4net;

using CKAN.Versioning;
using CKAN.NetKAN.Extensions;
using CKAN.NetKAN.Model;
using CKAN.NetKAN.Services;
Expand Down
1 change: 0 additions & 1 deletion Netkan/Transformers/MetaNetkanTransformer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using log4net;
using Newtonsoft.Json.Linq;

using CKAN.Versioning;
using CKAN.NetKAN.Extensions;
using CKAN.NetKAN.Model;
using CKAN.NetKAN.Services;
Expand Down