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 @@ + + + + + + True + False + + + True + False + Open the folder where saves for the application is loaded + Open Save Directory + True + + + + 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 - +