فهرست منبع

GUI: Implement context menu for the game table (#840)

* Add context menu to the game table

* Minor bugfix and cleanup

* add ability to create directory if it doesn't exist

* nit

* dont show menu when right-clicking nothing
Xpl0itR 6 سال پیش
والد
کامیت
bd010869a5
5فایلهای تغییر یافته به همراه136 افزوده شده و 45 حذف شده
  1. 2 0
      Ryujinx/Ryujinx.csproj
  2. 75 0
      Ryujinx/Ui/GameTableContextMenu.cs
  3. 18 0
      Ryujinx/Ui/GameTableContextMenu.glade
  4. 40 44
      Ryujinx/Ui/MainWindow.cs
  5. 1 1
      Ryujinx/Ui/MainWindow.glade

+ 2 - 0
Ryujinx/Ryujinx.csproj

@@ -43,6 +43,7 @@
     <None Remove="Ui\assets\PatreonLogo.png" />
     <None Remove="Ui\assets\Icon.png" />
     <None Remove="Ui\assets\TwitterLogo.png" />
+    <None Remove="Ui\GameTableContextMenu.glade" />
     <None Remove="Ui\MainWindow.glade" />
     <None Remove="Ui\SwitchSettings.glade" />
   </ItemGroup>
@@ -63,6 +64,7 @@
     <EmbeddedResource Include="Ui\assets\PatreonLogo.png" />
     <EmbeddedResource Include="Ui\assets\Icon.png" />
     <EmbeddedResource Include="Ui\assets\TwitterLogo.png" />
+    <EmbeddedResource Include="Ui\GameTableContextMenu.glade" />
     <EmbeddedResource Include="Ui\MainWindow.glade" />
     <EmbeddedResource Include="Ui\SwitchSettings.glade" />
   </ItemGroup>

+ 75 - 0
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"
+            });
+        }
+    }
+}

+ 18 - 0
Ryujinx/Ui/GameTableContextMenu.glade

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface>
+  <requires lib="gtk+" version="3.20"/>
+  <object class="GtkMenu" id="_contextMenu">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <child>
+      <object class="GtkMenuItem" id="_openSaveDir">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="tooltip_text" translatable="yes">Open the folder where saves for the application is loaded</property>
+        <property name="label" translatable="yes">Open Save Directory</property>
+        <property name="use_underline">True</property>
+      </object>
+    </child>
+  </object>
+</interface>

+ 40 - 44
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);
-
-                _progressLabel.Text = $"{e.NumAppsLoaded}/{e.NumAppsFound} Games Loaded";
-                _progressBar.Value  = (float)e.NumAppsLoaded / e.NumAppsFound;
+                    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 = $"{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);

+ 1 - 1
Ryujinx/Ui/MainWindow.glade

@@ -330,7 +330,7 @@
                     <property name="hover_selection">True</property>
                     <signal name="row-activated" handler="Row_Activated" swapped="no"/>
                     <child internal-child="selection">
-                      <object class="GtkTreeSelection"/>
+                      <object class="GtkTreeSelection" id="_gameTableSelection"/>
                     </child>
                   </object>
                 </child>