2018-07-16 00:48:31 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
2017-05-16 23:27:43 +00:00
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
using System.Drawing;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Linq;
|
2018-07-16 00:48:31 +00:00
|
|
|
|
using System.Threading.Tasks;
|
2017-05-16 23:27:43 +00:00
|
|
|
|
using System.Windows.Forms;
|
2018-07-16 00:48:31 +00:00
|
|
|
|
using PKHeX.Core;
|
|
|
|
|
using PKHeX.WinForms.Properties;
|
2018-04-07 04:23:09 +00:00
|
|
|
|
using static PKHeX.Core.MessageStrings;
|
2017-05-16 23:27:43 +00:00
|
|
|
|
|
|
|
|
|
namespace PKHeX.WinForms
|
|
|
|
|
{
|
|
|
|
|
public partial class SAV_FolderList : Form
|
|
|
|
|
{
|
2018-07-16 00:48:31 +00:00
|
|
|
|
private readonly Action<SaveFile> OpenSaveFile;
|
|
|
|
|
private readonly List<CustomFolderPath> Paths;
|
|
|
|
|
private readonly SortableBindingList<SavePreview> Recent;
|
|
|
|
|
private readonly SortableBindingList<SavePreview> Backup;
|
|
|
|
|
|
|
|
|
|
public SAV_FolderList(Action<SaveFile> openSaveFile)
|
2017-05-16 23:27:43 +00:00
|
|
|
|
{
|
|
|
|
|
InitializeComponent();
|
2018-07-16 00:48:31 +00:00
|
|
|
|
OpenSaveFile = openSaveFile;
|
2017-05-16 23:27:43 +00:00
|
|
|
|
|
|
|
|
|
// Preprogrammed folders
|
|
|
|
|
var locs = new List<CustomFolderPath>
|
|
|
|
|
{
|
2018-05-22 01:20:08 +00:00
|
|
|
|
new CustomFolderPath(Main.BackupPath, "PKHeX Backups")
|
2017-05-16 23:27:43 +00:00
|
|
|
|
};
|
2017-06-18 01:37:19 +00:00
|
|
|
|
locs.AddRange(GetUserPaths());
|
|
|
|
|
locs.AddRange(Get3DSPaths());
|
2018-05-22 01:20:08 +00:00
|
|
|
|
locs.AddRange(GetSwitchPaths());
|
|
|
|
|
addIfExists(CyberGadgetUtil.GetCacheFolder(), "CGSE Cache");
|
|
|
|
|
addIfExists(CyberGadgetUtil.GetTempFolder(), "CGSE Temp");
|
2018-05-12 15:13:39 +00:00
|
|
|
|
|
2018-07-16 00:48:31 +00:00
|
|
|
|
Paths = locs.GroupBy(z => z.Path).Select(z => z.First())
|
|
|
|
|
.OrderByDescending(z => Directory.Exists(z.Path)).ToList();
|
|
|
|
|
foreach (var loc in Paths)
|
2017-10-05 23:01:16 +00:00
|
|
|
|
AddButton(loc.DisplayText, loc.Path);
|
2017-05-16 23:27:43 +00:00
|
|
|
|
|
2018-07-16 00:48:31 +00:00
|
|
|
|
var recent = PathUtilWindows.GetSaveFiles(Paths.Select(z => z.Path).Where(z => z != Main.BackupPath));
|
|
|
|
|
Recent = PopulateData(dgDataRecent, recent);
|
|
|
|
|
var backup = PathUtilWindows.GetSaveFiles(Main.BackupPath);
|
|
|
|
|
Backup = PopulateData(dgDataBackup, backup);
|
|
|
|
|
|
|
|
|
|
dgDataRecent.ContextMenuStrip = GetContextMenu(dgDataRecent);
|
|
|
|
|
dgDataBackup.ContextMenuStrip = GetContextMenu(dgDataBackup);
|
|
|
|
|
|
|
|
|
|
dgDataRecent.DoubleBuffered(true);
|
|
|
|
|
dgDataBackup.DoubleBuffered(true);
|
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
WinFormsUtil.TranslateInterface(this, Main.CurrentLanguage);
|
2018-07-16 00:48:31 +00:00
|
|
|
|
CenterToParent();
|
2018-05-22 01:20:08 +00:00
|
|
|
|
|
|
|
|
|
void addIfExists(string path, string text)
|
|
|
|
|
{
|
|
|
|
|
if (Directory.Exists(path))
|
|
|
|
|
locs.Add(new CustomFolderPath(path, text));
|
|
|
|
|
}
|
2017-05-16 23:27:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
private void AddButton(string name, string path)
|
2017-05-16 23:27:43 +00:00
|
|
|
|
{
|
|
|
|
|
var button = new Button
|
|
|
|
|
{
|
|
|
|
|
Size = new Size { Height = 30, Width = 130 },
|
|
|
|
|
Text = name,
|
2017-09-30 05:58:25 +00:00
|
|
|
|
Name = $"B_{name}",
|
2017-05-16 23:27:43 +00:00
|
|
|
|
Enabled = new DirectoryInfo(path).Exists,
|
|
|
|
|
};
|
|
|
|
|
button.Click += (s, e) =>
|
|
|
|
|
{
|
|
|
|
|
if (Directory.Exists(path))
|
2017-05-18 01:25:48 +00:00
|
|
|
|
{
|
2017-05-16 23:27:43 +00:00
|
|
|
|
Process.Start("explorer.exe", path);
|
2017-05-18 01:25:48 +00:00
|
|
|
|
Close();
|
|
|
|
|
}
|
2017-05-16 23:27:43 +00:00
|
|
|
|
else
|
2018-04-07 04:23:09 +00:00
|
|
|
|
WinFormsUtil.Alert(MsgFolderNotFound, path);
|
2017-05-16 23:27:43 +00:00
|
|
|
|
};
|
|
|
|
|
FLP_Buttons.Controls.Add(button);
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
private static IEnumerable<CustomFolderPath> GetUserPaths()
|
2017-05-16 23:27:43 +00:00
|
|
|
|
{
|
2017-05-18 03:39:06 +00:00
|
|
|
|
string loc = Path.Combine(Main.WorkingDirectory, "savpaths.txt");
|
2017-05-16 23:27:43 +00:00
|
|
|
|
|
|
|
|
|
if (!File.Exists(loc))
|
2018-05-22 01:20:08 +00:00
|
|
|
|
return Enumerable.Empty<CustomFolderPath>();
|
2017-05-16 23:27:43 +00:00
|
|
|
|
|
2018-02-20 07:34:07 +00:00
|
|
|
|
var lines = File.ReadLines(loc);
|
2018-05-22 01:20:08 +00:00
|
|
|
|
return lines.Select(z => z.Split('\t'))
|
|
|
|
|
.Where(a => a.Length == 2)
|
|
|
|
|
.Select(x => new CustomFolderPath(x));
|
2017-05-17 04:44:02 +00:00
|
|
|
|
}
|
2017-06-18 01:37:19 +00:00
|
|
|
|
private static IEnumerable<CustomFolderPath> Get3DSPaths()
|
2017-05-17 04:44:02 +00:00
|
|
|
|
{
|
2018-05-22 01:20:08 +00:00
|
|
|
|
var path3DS = PathUtilWindows.GetSwitchLocation();
|
|
|
|
|
if (path3DS == null || !Directory.Exists(path3DS))
|
|
|
|
|
return Enumerable.Empty<CustomFolderPath>();
|
|
|
|
|
var root = Path.GetPathRoot(path3DS);
|
|
|
|
|
var paths = PathUtilWindows.GetSwitchBackupPaths(root);
|
|
|
|
|
return paths.Select(z => new CustomFolderPath(z));
|
|
|
|
|
}
|
|
|
|
|
private static IEnumerable<CustomFolderPath> GetSwitchPaths()
|
|
|
|
|
{
|
|
|
|
|
var pathNX = PathUtilWindows.GetSwitchLocation();
|
|
|
|
|
if (pathNX == null || !Directory.Exists(pathNX))
|
|
|
|
|
return Enumerable.Empty<CustomFolderPath>();
|
|
|
|
|
var root = Path.GetPathRoot(pathNX);
|
|
|
|
|
var paths = PathUtilWindows.GetSwitchBackupPaths(root);
|
|
|
|
|
return paths.Select(z => new CustomFolderPath(z));
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-16 00:48:31 +00:00
|
|
|
|
private class CustomFolderPath
|
2018-05-22 01:20:08 +00:00
|
|
|
|
{
|
|
|
|
|
public readonly string Path;
|
|
|
|
|
public readonly string DisplayText;
|
|
|
|
|
|
|
|
|
|
public CustomFolderPath(string z)
|
2017-05-16 23:27:43 +00:00
|
|
|
|
{
|
2017-05-17 04:44:02 +00:00
|
|
|
|
var di = new DirectoryInfo(z);
|
|
|
|
|
var root = di.Root.Name;
|
|
|
|
|
var folder = di.Parent.Name;
|
|
|
|
|
if (root == folder)
|
|
|
|
|
folder = di.Name;
|
2018-05-22 01:20:08 +00:00
|
|
|
|
|
|
|
|
|
Path = z;
|
|
|
|
|
DisplayText = folder;
|
2017-05-16 23:27:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-05-22 01:20:08 +00:00
|
|
|
|
public CustomFolderPath(IReadOnlyList<string> arr)
|
|
|
|
|
{
|
|
|
|
|
Path = arr[1];
|
|
|
|
|
DisplayText = arr[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public CustomFolderPath(string path, string display)
|
|
|
|
|
{
|
|
|
|
|
Path = path;
|
|
|
|
|
DisplayText = display;
|
|
|
|
|
}
|
2017-05-16 23:27:43 +00:00
|
|
|
|
}
|
2018-07-16 00:48:31 +00:00
|
|
|
|
|
|
|
|
|
private string GetParentFolderName(SaveFile first)
|
|
|
|
|
{
|
2018-07-17 04:00:43 +00:00
|
|
|
|
var parent = Paths.Find(z => first.FileFolder.StartsWith(z.Path));
|
2018-07-16 00:48:31 +00:00
|
|
|
|
return parent?.DisplayText ?? "???";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private sealed class SaveList<T> : SortableBindingList<T> { }
|
|
|
|
|
private sealed class SavePreview
|
|
|
|
|
{
|
|
|
|
|
public readonly SaveFile Save;
|
|
|
|
|
|
|
|
|
|
public SavePreview(SaveFile sav, string parent)
|
|
|
|
|
{
|
|
|
|
|
Save = sav;
|
|
|
|
|
Folder = parent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string OT => Save.OT;
|
|
|
|
|
public int G => Save.Generation;
|
|
|
|
|
public GameVersion Game => Save.Version;
|
|
|
|
|
|
|
|
|
|
public string Played => Save.PlayTimeString.PadLeft(9, '0');
|
|
|
|
|
public string FileTime => new FileInfo(Save.FilePath).LastWriteTime.ToString("yyyy.MM.dd:hh:mm:ss");
|
|
|
|
|
|
|
|
|
|
public int TID => Save.Generation >= 7 ? Save.TrainerID7 : Save.TID;
|
|
|
|
|
public int SID => Save.Generation >= 7 ? Save.TrainerSID7 : Save.SID;
|
|
|
|
|
|
|
|
|
|
// ReSharper disable once MemberCanBePrivate.Local
|
|
|
|
|
// ReSharper disable once UnusedAutoPropertyAccessor.Local
|
|
|
|
|
public string Folder { get; }
|
2018-07-16 04:28:27 +00:00
|
|
|
|
|
|
|
|
|
public string Name => Path.GetFileName(Save.FilePath);
|
2018-07-16 00:48:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private ContextMenuStrip GetContextMenu(DataGridView dgv)
|
|
|
|
|
{
|
|
|
|
|
var mnuOpen = new ToolStripMenuItem
|
|
|
|
|
{
|
|
|
|
|
Name = "mnuOpen",
|
|
|
|
|
Text = "Open",
|
|
|
|
|
Image = Resources.open,
|
|
|
|
|
};
|
|
|
|
|
mnuOpen.Click += (sender, e) => ClickOpenFile(dgv);
|
|
|
|
|
|
|
|
|
|
var mnuBrowseAt = new ToolStripMenuItem
|
|
|
|
|
{
|
|
|
|
|
Name = "mnuBrowseAt",
|
|
|
|
|
Text = "Browse...",
|
|
|
|
|
Image = Resources.folder,
|
|
|
|
|
};
|
|
|
|
|
mnuBrowseAt.Click += (sender, e) => ClickOpenFolder(dgv);
|
|
|
|
|
|
|
|
|
|
ContextMenuStrip mnu = new ContextMenuStrip();
|
|
|
|
|
mnu.Items.Add(mnuOpen);
|
|
|
|
|
mnu.Items.Add(mnuBrowseAt);
|
|
|
|
|
return mnu;
|
|
|
|
|
}
|
|
|
|
|
private void ClickOpenFile(DataGridView dgv)
|
|
|
|
|
{
|
|
|
|
|
var sav = GetSaveFile(dgv);
|
|
|
|
|
if (sav == null)
|
|
|
|
|
{
|
|
|
|
|
WinFormsUtil.Alert(MsgFileLoadFail);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OpenSaveFile(sav.Save);
|
|
|
|
|
}
|
|
|
|
|
private void ClickOpenFolder(DataGridView dgv)
|
|
|
|
|
{
|
|
|
|
|
var sav = GetSaveFile(dgv);
|
|
|
|
|
if (sav == null)
|
|
|
|
|
{
|
|
|
|
|
WinFormsUtil.Alert(MsgFileLoadFail);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var path = sav.Save.FilePath;
|
|
|
|
|
Process.Start("explorer.exe", $"/select, \"{path}\"");
|
|
|
|
|
}
|
|
|
|
|
private SavePreview GetSaveFile(DataGridView dgData)
|
|
|
|
|
{
|
|
|
|
|
var c = dgData.SelectedCells;
|
|
|
|
|
if (c.Count != 1)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
var item = c[0].RowIndex;
|
|
|
|
|
var parent = dgData == dgDataRecent ? Recent : Backup;
|
|
|
|
|
return parent[item];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void DataGridCellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (e.ColumnIndex == -1 || e.RowIndex == -1 || e.Button != MouseButtons.Right)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
var c = ((DataGridView) sender)[e.ColumnIndex, e.RowIndex];
|
|
|
|
|
c.DataGridView.ClearSelection();
|
|
|
|
|
c.DataGridView.CurrentCell = c;
|
|
|
|
|
c.Selected = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private SaveList<SavePreview> PopulateData(DataGridView dgData, IEnumerable<SaveFile> saves)
|
|
|
|
|
{
|
|
|
|
|
var list = new SaveList<SavePreview>();
|
|
|
|
|
|
|
|
|
|
var enumerator = saves.GetEnumerator();
|
|
|
|
|
while (enumerator.Current == null)
|
|
|
|
|
{
|
|
|
|
|
if (!enumerator.MoveNext())
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var first = enumerator.Current;
|
|
|
|
|
var sav1 = new SavePreview(first, GetParentFolderName(first));
|
|
|
|
|
LoadEntryInitial(dgData, list, sav1);
|
|
|
|
|
Task.Run(async () => // load the rest async
|
|
|
|
|
{
|
2018-07-16 22:31:23 +00:00
|
|
|
|
while (!dgData.IsHandleCreated)
|
|
|
|
|
await Task.Delay(15).ConfigureAwait(false);
|
2018-07-16 00:48:31 +00:00
|
|
|
|
while (enumerator.MoveNext())
|
|
|
|
|
{
|
|
|
|
|
var next = enumerator.Current;
|
|
|
|
|
if (next == null)
|
|
|
|
|
continue;
|
|
|
|
|
var sav = new SavePreview(next, GetParentFolderName(next));
|
|
|
|
|
dgData.Invoke(new Action(() => LoadEntry(dgData, list, sav)));
|
|
|
|
|
}
|
|
|
|
|
enumerator.Dispose();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void LoadEntryInitial(DataGridView dgData, SaveList<SavePreview> list, SavePreview sav)
|
|
|
|
|
{
|
|
|
|
|
list.Add(sav);
|
|
|
|
|
dgData.DataSource = list;
|
|
|
|
|
dgData.AutoGenerateColumns = true;
|
|
|
|
|
for (int i = 0; i < dgData.Columns.Count; i++)
|
|
|
|
|
dgData.Columns[i].SortMode = DataGridViewColumnSortMode.Automatic;
|
|
|
|
|
dgData.AutoResizeColumns(); // Trigger Resizing
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void LoadEntry(DataGridView dgData, ICollection<SavePreview> list, SavePreview sav)
|
|
|
|
|
{
|
|
|
|
|
dgData.SuspendLayout();
|
|
|
|
|
list.Add(sav);
|
|
|
|
|
dgData.AutoResizeColumns();
|
|
|
|
|
dgData.ResumeLayout();
|
|
|
|
|
}
|
2017-05-16 23:27:43 +00:00
|
|
|
|
}
|
|
|
|
|
}
|