diff --git a/Ryujinx/Ryujinx.csproj b/Ryujinx/Ryujinx.csproj
index b231ddb8d2..e610e8277e 100644
--- a/Ryujinx/Ryujinx.csproj
+++ b/Ryujinx/Ryujinx.csproj
@@ -43,6 +43,7 @@
+
@@ -63,6 +64,7 @@
+
diff --git a/Ryujinx/Ui/GameTableContextMenu.cs b/Ryujinx/Ui/GameTableContextMenu.cs
new file mode 100644
index 0000000000..7346f40eb9
--- /dev/null
+++ b/Ryujinx/Ui/GameTableContextMenu.cs
@@ -0,0 +1,56 @@
+using Gtk;
+using Ryujinx.HLE.FileSystem;
+using System;
+using System.Diagnostics;
+using System.IO;
+
+using GUI = Gtk.Builder.ObjectAttribute;
+
+namespace Ryujinx.Ui
+{
+ public class GameTableContextMenu : Menu
+ {
+ private static ListStore _gameTableStore;
+ private static TreeIter _rowIter;
+
+#pragma warning disable CS0649
+#pragma warning disable IDE0044
+ [GUI] MenuItem _openSaveDir;
+#pragma warning restore CS0649
+#pragma warning restore IDE0044
+
+ public GameTableContextMenu(ListStore gameTableStore, TreeIter rowIter) : this(new Builder("Ryujinx.Ui.GameTableContextMenu.glade"), gameTableStore, rowIter) { }
+
+ private GameTableContextMenu(Builder builder, ListStore gameTableStore, TreeIter rowIter) : base(builder.GetObject("_contextMenu").Handle)
+ {
+ builder.Autoconnect(this);
+
+ _openSaveDir.Activated += OpenSaveDir_Clicked;
+
+ _gameTableStore = gameTableStore;
+ _rowIter = rowIter;
+ }
+
+ //Events
+ private void OpenSaveDir_Clicked(object sender, EventArgs args)
+ {
+ string titleName = _gameTableStore.GetValue(_rowIter, 2).ToString().Split("\n")[0];
+ string titleId = _gameTableStore.GetValue(_rowIter, 2).ToString().Split("\n")[1].ToLower();
+ string saveDir = System.IO.Path.Combine(new VirtualFileSystem().GetNandPath(), "user", "save", "0000000000000000", "00000000000000000000000000000001", titleId, "0");
+
+ if (!Directory.Exists(saveDir))
+ {
+ GtkDialog.CreateErrorDialog($"Could not find save location for {titleName} [{titleId}]");
+ }
+ else
+ {
+ Process.Start(new ProcessStartInfo()
+ {
+ FileName = saveDir,
+ UseShellExecute = true,
+ Verb = "open"
+ });
+ }
+ }
+ }
+}
diff --git a/Ryujinx/Ui/GameTableContextMenu.glade b/Ryujinx/Ui/GameTableContextMenu.glade
new file mode 100644
index 0000000000..2c9e097292
--- /dev/null
+++ b/Ryujinx/Ui/GameTableContextMenu.glade
@@ -0,0 +1,18 @@
+
+
+
+
+
+
diff --git a/Ryujinx/Ui/MainWindow.cs b/Ryujinx/Ui/MainWindow.cs
index e0bd849479..ce06086b2f 100644
--- a/Ryujinx/Ui/MainWindow.cs
+++ b/Ryujinx/Ui/MainWindow.cs
@@ -66,6 +66,7 @@ namespace Ryujinx.Ui
[GUI] CheckMenuItem _fileSizeToggle;
[GUI] CheckMenuItem _pathToggle;
[GUI] TreeView _gameTable;
+ [GUI] TreeSelection _gameTableSelection;
[GUI] Label _progressLabel;
[GUI] LevelBar _progressBar;
#pragma warning restore CS0649
@@ -81,6 +82,8 @@ namespace Ryujinx.Ui
ApplicationLibrary.ApplicationAdded += Application_Added;
+ _gameTable.ButtonReleaseEvent += Row_Clicked;
+
_renderer = new OglRenderer();
_audioOut = InitializeAudioEngine();
@@ -421,24 +424,24 @@ namespace Ryujinx.Ui
}
//Events
- private void Application_Added(object sender, ApplicationAddedEventArgs e)
+ private void Application_Added(object sender, ApplicationAddedEventArgs args)
{
Application.Invoke(delegate
{
_tableStore.AppendValues(
- e.AppData.Favorite,
- new Gdk.Pixbuf(e.AppData.Icon, 75, 75),
- $"{e.AppData.TitleName}\n{e.AppData.TitleId.ToUpper()}",
- e.AppData.Developer,
- e.AppData.Version,
- e.AppData.TimePlayed,
- e.AppData.LastPlayed,
- e.AppData.FileExtension,
- e.AppData.FileSize,
- e.AppData.Path);
+ args.AppData.Favorite,
+ new Gdk.Pixbuf(args.AppData.Icon, 75, 75),
+ $"{args.AppData.TitleName}\n{args.AppData.TitleId.ToUpper()}",
+ args.AppData.Developer,
+ args.AppData.Version,
+ args.AppData.TimePlayed,
+ args.AppData.LastPlayed,
+ args.AppData.FileExtension,
+ args.AppData.FileSize,
+ args.AppData.Path);
- _progressLabel.Text = $"{e.NumAppsLoaded}/{e.NumAppsFound} Games Loaded";
- _progressBar.Value = (float)e.NumAppsLoaded / e.NumAppsFound;
+ _progressLabel.Text = $"{args.NumAppsLoaded}/{args.NumAppsFound} Games Loaded";
+ _progressBar.Value = (float)args.NumAppsLoaded / args.NumAppsFound;
});
}
@@ -477,12 +480,23 @@ namespace Ryujinx.Ui
private void Row_Activated(object sender, RowActivatedArgs args)
{
- _tableStore.GetIter(out TreeIter treeIter, new TreePath(args.Path.ToString()));
+ _gameTableSelection.GetSelected(out TreeIter treeIter);
string path = (string)_tableStore.GetValue(treeIter, 9);
LoadApplication(path);
}
+ private void Row_Clicked(object sender, ButtonReleaseEventArgs args)
+ {
+ if (args.Event.Button != 3) return;
+
+ _gameTableSelection.GetSelected(out TreeIter treeIter);
+
+ GameTableContextMenu contextMenu = new GameTableContextMenu(_tableStore, treeIter);
+ contextMenu.ShowAll();
+ contextMenu.PopupAtPointer(null);
+ }
+
private void Load_Application_File(object sender, EventArgs args)
{
FileChooserDialog fileChooser = new FileChooserDialog("Choose the file to open", this, FileChooserAction.Open, "Cancel", ResponseType.Cancel, "Open", ResponseType.Accept);
diff --git a/Ryujinx/Ui/MainWindow.glade b/Ryujinx/Ui/MainWindow.glade
index 6d66dc2007..fcf91bc4c5 100644
--- a/Ryujinx/Ui/MainWindow.glade
+++ b/Ryujinx/Ui/MainWindow.glade
@@ -330,7 +330,7 @@
True
-
+