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..f8d1d6815f
--- /dev/null
+++ b/Ryujinx/Ui/GameTableContextMenu.cs
@@ -0,0 +1,75 @@
+using Gtk;
+using Ryujinx.HLE.FileSystem;
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Reflection;
+
+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))
+ {
+ MessageDialog messageDialog = new MessageDialog(null, DialogFlags.Modal, MessageType.Question, ButtonsType.YesNo, null)
+ {
+ Title = "Ryujinx",
+ Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png"),
+ Text = $"Could not find save directory for {titleName} [{titleId}]",
+ SecondaryText = "Would you like to create the directory?",
+ WindowPosition = WindowPosition.Center
+ };
+
+ if (messageDialog.Run() == (int)ResponseType.Yes)
+ {
+ Directory.CreateDirectory(saveDir);
+ }
+ else
+ {
+ messageDialog.Dispose();
+
+ return;
+ }
+
+ messageDialog.Dispose();
+ }
+
+ 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..dc3315e979 100644
--- a/Ryujinx/Ui/MainWindow.cs
+++ b/Ryujinx/Ui/MainWindow.cs
@@ -38,16 +38,6 @@ namespace Ryujinx.Ui
private static bool _gameLoaded;
private static bool _ending;
- private static TreeViewColumn _favColumn;
- private static TreeViewColumn _appColumn;
- private static TreeViewColumn _devColumn;
- private static TreeViewColumn _versionColumn;
- private static TreeViewColumn _timePlayedColumn;
- private static TreeViewColumn _lastPlayedColumn;
- private static TreeViewColumn _fileExtColumn;
- private static TreeViewColumn _fileSizeColumn;
- private static TreeViewColumn _pathColumn;
-
private static TreeView _treeView;
#pragma warning disable CS0649
@@ -66,6 +56,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 +72,8 @@ namespace Ryujinx.Ui
ApplicationLibrary.ApplicationAdded += Application_Added;
+ _gameTable.ButtonReleaseEvent += Row_Clicked;
+
_renderer = new OglRenderer();
_audioOut = InitializeAudioEngine();
@@ -173,26 +166,16 @@ namespace Ryujinx.Ui
foreach (TreeViewColumn column in _gameTable.Columns)
{
- if (column.Title == "Fav") _favColumn = column;
- else if (column.Title == "Application") _appColumn = column;
- else if (column.Title == "Developer") _devColumn = column;
- else if (column.Title == "Version") _versionColumn = column;
- else if (column.Title == "Time Played") _timePlayedColumn = column;
- else if (column.Title == "Last Played") _lastPlayedColumn = column;
- else if (column.Title == "File Ext") _fileExtColumn = column;
- else if (column.Title == "File Size") _fileSizeColumn = column;
- else if (column.Title == "Path") _pathColumn = column;
+ if (column.Title == "Fav" && ConfigurationState.Instance.Ui.GuiColumns.FavColumn) column.SortColumnId = 0;
+ else if (column.Title == "Application" && ConfigurationState.Instance.Ui.GuiColumns.AppColumn) column.SortColumnId = 2;
+ else if (column.Title == "Developer" && ConfigurationState.Instance.Ui.GuiColumns.DevColumn) column.SortColumnId = 3;
+ else if (column.Title == "Version" && ConfigurationState.Instance.Ui.GuiColumns.VersionColumn) column.SortColumnId = 4;
+ else if (column.Title == "Time Played" && ConfigurationState.Instance.Ui.GuiColumns.TimePlayedColumn) column.SortColumnId = 5;
+ else if (column.Title == "Last Played" && ConfigurationState.Instance.Ui.GuiColumns.LastPlayedColumn) column.SortColumnId = 6;
+ else if (column.Title == "File Ext" && ConfigurationState.Instance.Ui.GuiColumns.FileExtColumn) column.SortColumnId = 7;
+ else if (column.Title == "File Size" && ConfigurationState.Instance.Ui.GuiColumns.FileSizeColumn) column.SortColumnId = 8;
+ else if (column.Title == "Path" && ConfigurationState.Instance.Ui.GuiColumns.PathColumn) column.SortColumnId = 9;
}
-
- if (ConfigurationState.Instance.Ui.GuiColumns.FavColumn) _favColumn.SortColumnId = 0;
- if (ConfigurationState.Instance.Ui.GuiColumns.AppColumn) _appColumn.SortColumnId = 2;
- if (ConfigurationState.Instance.Ui.GuiColumns.DevColumn) _devColumn.SortColumnId = 3;
- if (ConfigurationState.Instance.Ui.GuiColumns.VersionColumn) _versionColumn.SortColumnId = 4;
- if (ConfigurationState.Instance.Ui.GuiColumns.TimePlayedColumn) _timePlayedColumn.SortColumnId = 5;
- if (ConfigurationState.Instance.Ui.GuiColumns.LastPlayedColumn) _lastPlayedColumn.SortColumnId = 6;
- if (ConfigurationState.Instance.Ui.GuiColumns.FileExtColumn) _fileExtColumn.SortColumnId = 7;
- if (ConfigurationState.Instance.Ui.GuiColumns.FileSizeColumn) _fileSizeColumn.SortColumnId = 8;
- if (ConfigurationState.Instance.Ui.GuiColumns.PathColumn) _pathColumn.SortColumnId = 9;
}
private HLE.Switch InitializeSwitchInstance()
@@ -421,24 +404,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 +460,25 @@ 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);
+
+ if (treeIter.UserData == IntPtr.Zero) return;
+
+ 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
-
+