From 437dfcfda43db982425a5effa773361c5ecf948f Mon Sep 17 00:00:00 2001 From: Salvador Cipolla Date: Tue, 21 Jan 2025 20:27:21 -0300 Subject: [PATCH] Tool Rework -Updated UI and changed the buttons -Added create a desktop shortcut -Add wine support for tools on linux -Add quicklaunch function for tools (needed for the shortcuts) -Bonus add mod shortcut on mod settings "Create shortcuts" only works on windows, this may be changed at some point later --- Knossos.NET/AppStyles.axaml | 6 ++ Knossos.NET/Classes/KnUtils.cs | 31 +++++++ Knossos.NET/Classes/Knossos.cs | 31 +++++++ Knossos.NET/Classes/Tool.cs | 81 ++++++++++++++---- Knossos.NET/Classes/Wine.cs | 73 +++++++++++++++- Knossos.NET/Knossos.NET.csproj | 1 + Knossos.NET/Program.cs | 2 +- Knossos.NET/ViewModels/TaskViewModel.cs | 4 +- .../Templates/DevModEditorViewModel.cs | 4 +- .../Templates/DevToolManagerViewModel.cs | 83 ++++++++++++++++--- .../Windows/ModSettingsViewModel.cs | 18 ++++ .../Views/Templates/DevToolManagerView.axaml | 50 +++++++++-- 12 files changed, 342 insertions(+), 42 deletions(-) diff --git a/Knossos.NET/AppStyles.axaml b/Knossos.NET/AppStyles.axaml index 758a8213..232270d9 100644 --- a/Knossos.NET/AppStyles.axaml +++ b/Knossos.NET/AppStyles.axaml @@ -73,6 +73,12 @@ M2 4.5C2 4.22386 2.22386 4 2.5 4H17.5C17.7761 4 18 4.22386 18 4.5C18 4.77614 17.7761 5 17.5 5H2.5C2.22386 5 2 4.77614 2 4.5Z M2 9.5C2 9.22386 2.22386 9 2.5 9H17.5C17.7761 9 18 9.22386 18 9.5C18 9.77614 17.7761 10 17.5 10H2.5C2.22386 10 2 9.77614 2 9.5Z M2.5 14C2.22386 14 2 14.2239 2 14.5C2 14.7761 2.22386 15 2.5 15H17.5C17.7761 15 18 14.7761 18 14.5C18 14.2239 17.7761 14 17.5 14H2.5Z + M14.4373398,3.10348696 C14.6345524,3.20081719 14.7941799,3.36044472 14.8915102,3.55765732 L17.8153782,9.48206111 L24.353346,10.4320834 C24.8998908,10.511501 25.2785723,11.0189439 25.1991547,11.5654888 C25.1675302,11.7831258 25.065043,11.9842682 24.9075593,12.1377768 L20.1766414,16.749282 L21.2934597,23.2608319 C21.3868207,23.8051684 21.0212328,24.3221243 20.4768964,24.4154853 C20.2601388,24.4526621 20.0371707,24.4173475 19.8425102,24.3150084 L13.9947741,21.2406716 L8.14703796,24.3150084 C7.65819337,24.5720092 7.05356621,24.3840627 6.79656541,23.8952181 C6.69422634,23.7005576 6.65891166,23.4775895 6.69608851,23.2608319 L7.81290673,16.749282 L3.08198882,12.1377768 C2.68650524,11.7522756 2.67841294,11.1191623 3.06391415,10.7236788 C3.21742275,10.5661951 3.41856517,10.4637079 3.6362022,10.4320834 L10.1741699,9.48206111 L13.098038,3.55765732 C13.3424603,3.06240366 13.9420861,2.85906466 14.4373398,3.10348696 Z M11.1702682,10.8530728 L4.85448108,11.7708103 L9.42462758,16.2256022 L8.34576234,22.5158692 L13.9947741,19.546008 L19.6437858,22.5158692 L18.5649206,16.2256022 L23.1350671,11.7708103 L16.81928,10.8530728 L13.9947741,5.12999876 L11.1702682,10.8530728 Z + M7.25008054,4.49999913 L10.7494682,4.49999913 C11.1636818,4.49999913 11.4994682,4.83578644 11.4994682,5.25 C11.4994682,5.62969577 11.2173143,5.94349023 10.8512388,5.99315253 L10.7494682,5.99999913 L7.24972349,5.99999913 C6.07077742,5.99943864 5.10347879,6.90639393 5.00784424,8.06094921 L5.00026803,8.21986131 L5.00310465,16.7504962 C5.00341779,17.9413602 5.92883567,18.9158978 7.09964605,18.9947542 L7.25369622,18.9999045 L15.751762,18.9882338 C16.9414684,18.9865998 17.9144722,18.0618298 17.9934904,16.8921377 L17.9986716,16.738236 L17.9986716,13.2319436 C17.9986716,12.81773 18.334458,12.4819436 18.7486716,12.4819436 C19.1283674,12.4819436 19.4421626,12.7640975 19.491825,13.130173 L19.4986716,13.2319436 L19.4986716,16.738236 C19.4986716,18.7405488 17.9292489,20.3767194 15.9527826,20.4827708 L15.7538222,20.4882324 L7.25825518,20.499901 L7.05493071,20.4947588 C5.14237343,20.3951844 3.60893529,18.8625525 3.50835508,16.9500479 L3.5031047,16.7508907 L3.50087004,8.2525319 L3.50527942,8.05003289 C3.60537339,6.13731798 5.13865446,4.60431851 7.05094826,4.50510482 L7.25008054,4.49999913 L10.7494682,4.49999913 L7.25008054,4.49999913 Z M13.748109,3.00129623 L20.3017795,3.0018036 L20.4013609,3.01557712 L20.4013609,3.01557712 L20.5021655,3.04376069 L20.5021655,3.04376069 L20.5589882,3.06786568 L20.5589882,3.06786568 C20.6122302,3.09104804 20.6633548,3.12146211 20.7110467,3.15867802 L20.7803898,3.22139044 L20.7803898,3.22139044 L20.8641342,3.31997258 L20.8641342,3.31997258 L20.9183108,3.41008637 L20.9183108,3.41008637 L20.9570021,3.50039784 L20.9570021,3.50039784 L20.9762122,3.56459327 L20.9762122,3.56459327 L20.9897783,3.62845344 L20.9897783,3.62845344 L20.9991402,3.72265407 L20.9991402,3.72265407 L20.9996358,10.2551867 C20.9996358,10.6694002 20.6638494,11.0051867 20.2496358,11.0051867 C19.86994,11.0051867 19.5561448,10.7230328 19.5064824,10.3569572 L19.4996358,10.2551867 L19.49887,5.56129623 L12.2796385,12.7845179 C12.0134324,13.0508449 11.5967743,13.0751456 11.3031133,12.8573578 L11.2189784,12.7847587 C10.9526514,12.5185526 10.9283507,12.1018944 11.1461385,11.8082335 L11.2187376,11.7240986 L18.43687,4.50129623 L13.748109,4.50129623 C13.3684132,4.50129623 13.054618,4.21914235 13.0049556,3.85306678 L12.998109,3.75129623 C12.998109,3.37160046 13.2802629,3.05780527 13.6463384,3.00814284 L13.748109,3.00129623 Z + M24,7.25 C27.1017853,7.25 29.629937,9.70601719 29.7458479,12.7794443 L29.75,13 L37,13 C37.6903559,13 38.25,13.5596441 38.25,14.25 C38.25,14.8972087 37.7581253,15.4295339 37.1278052,15.4935464 L37,15.5 L35.909,15.5 L34.2058308,38.0698451 C34.0385226,40.2866784 32.1910211,42 29.9678833,42 L18.0321167,42 C15.8089789,42 13.9614774,40.2866784 13.7941692,38.0698451 L12.09,15.5 L11,15.5 C10.3527913,15.5 9.8204661,15.0081253 9.75645361,14.3778052 L9.75,14.25 C9.75,13.6027913 10.2418747,13.0704661 10.8721948,13.0064536 L11,13 L18.25,13 C18.25,9.82436269 20.8243627,7.25 24,7.25 Z M33.4021054,15.5 L14.5978946,15.5 L16.2870795,37.8817009 C16.3559711,38.7945146 17.116707,39.5 18.0321167,39.5 L29.9678833,39.5 C30.883293,39.5 31.6440289,38.7945146 31.7129205,37.8817009 L33.4021054,15.5 Z M27.25,20.75 C27.8972087,20.75 28.4295339,21.2418747 28.4935464,21.8721948 L28.5,22 L28.5,33 C28.5,33.6903559 27.9403559,34.25 27.25,34.25 C26.6027913,34.25 26.0704661,33.7581253 26.0064536,33.1278052 L26,33 L26,22 C26,21.3096441 26.5596441,20.75 27.25,20.75 Z M20.75,20.75 C21.3972087,20.75 21.9295339,21.2418747 21.9935464,21.8721948 L22,22 L22,33 C22,33.6903559 21.4403559,34.25 20.75,34.25 C20.1027913,34.25 19.5704661,33.7581253 19.5064536,33.1278052 L19.5,33 L19.5,22 C19.5,21.3096441 20.0596441,20.75 20.75,20.75 Z M24,9.75 C22.2669685,9.75 20.8507541,11.1064548 20.7551448,12.8155761 L20.75,13 L27.25,13 C27.25,11.2050746 25.7949254,9.75 24,9.75 Z + M12.25,39.5 L35.75,39.5 C36.4403559,39.5 37,40.0596441 37,40.75 C37,41.3972087 36.5081253,41.9295339 35.8778052,41.9935464 L35.75,42 L12.25,42 C11.5596441,42 11,41.4403559 11,40.75 C11,40.1027913 11.4918747,39.5704661 12.1221948,39.5064536 L12.25,39.5 L35.75,39.5 L12.25,39.5 Z M23.6221948,6.00645361 L23.75,6 C24.3972087,6 24.9295339,6.49187466 24.9935464,7.12219476 L25,7.25 L25,31.54 L30.6466793,25.8942911 C31.1348346,25.4061358 31.9262909,25.4061358 32.4144462,25.8942911 C32.9026016,26.3824465 32.9026016,27.1739027 32.4144462,27.6620581 L24.6362716,35.4402327 C24.1481163,35.928388 23.35666,35.928388 22.8685047,35.4402327 L15.0903301,27.6620581 C14.6021747,27.1739027 14.6021747,26.3824465 15.0903301,25.8942911 C15.5784855,25.4061358 16.3699417,25.4061358 16.858097,25.8942911 L22.5,31.536 L22.5,7.25 C22.5,6.60279131 22.9918747,6.0704661 23.6221948,6.00645361 L23.75,6 L23.6221948,6.00645361 Z + M4.21157,12.7326 C3.9244,13.0312 3.93361,13.5059 4.23213,13.7931 C4.53064,14.0803 5.00543,14.0711 5.29259,13.7725 L13.2521,5.49831 L13.2521,24.2511 C13.2521,24.6653 13.5879,25.0011 14.0021,25.0011 C14.4163,25.0011 14.7521,24.6653 14.7521,24.2511 L14.7521,5.4993 L22.7106,13.7725 C22.9978,14.0711 23.4726,14.0803 23.7711,13.7931 C24.0696,13.5059 24.0788,13.0312 23.7916,12.7326 L14.7223,3.30466 C14.3289,2.89568 13.6743,2.89568 13.2809,3.30466 L4.21157,12.7326 Z + M10.5 8.25C10.5 7.2835 11.2835 6.5 12.25 6.5H24V15.25C24 17.3211 25.6789 19 27.75 19H37.5V39.75C37.5 40.7165 36.7165 41.5 35.75 41.5H24.2608C23.7353 42.4086 23.1029 43.2476 22.3809 44H35.75C38.0972 44 40 42.0972 40 39.75V18.4142C40 17.8175 39.7629 17.2452 39.341 16.8232L27.1768 4.65901C26.7548 4.23705 26.1825 4 25.5858 4H12.25C9.90279 4 8 5.90279 8 8.25V22.9963C8.79632 22.6642 9.63275 22.4091 10.5 22.2402V8.25ZM35.4822 16.5H27.75C27.0596 16.5 26.5 15.9404 26.5 15.25V7.51777L35.4822 16.5Z M24 35C24 41.0751 19.0751 46 13 46C6.92487 46 2 41.0751 2 35C2 28.9249 6.92487 24 13 24C19.0751 24 24 28.9249 24 35ZM11.7071 29.2929C11.3166 28.9024 10.6834 28.9024 10.2929 29.2929L5.29289 34.2929C4.90237 34.6834 4.90237 35.3166 5.29289 35.7071L10.2929 40.7071C10.6834 41.0976 11.3166 41.0976 11.7071 40.7071C12.0976 40.3166 12.0976 39.6834 11.7071 39.2929L8.41421 36H20C20.5523 36 21 35.5523 21 35C21 34.4477 20.5523 34 20 34H8.41421L11.7071 30.7071C12.0976 30.3166 12.0976 29.6834 11.7071 29.2929Z diff --git a/Knossos.NET/Classes/KnUtils.cs b/Knossos.NET/Classes/KnUtils.cs index 369c181f..f8cb0146 100644 --- a/Knossos.NET/Classes/KnUtils.cs +++ b/Knossos.NET/Classes/KnUtils.cs @@ -23,6 +23,7 @@ using Avalonia.Media; using Avalonia.Threading; using Microsoft.Win32; +using WindowsShortcutFactory; namespace Knossos.NET { @@ -1034,5 +1035,35 @@ public static void DeleteFileSafe(string filePath) Log.Add(Log.LogSeverity.Error, "KnUtils.DeleteFileSafe()", ex); } } + + /// + /// Creates a shortcut into the user desktop + /// optional diferent icon path, if null is passed the destfilepath icon will be used + /// Only Windows + /// + /// + /// + /// + public static void CreateDesktopShortcut(string shortcutName, string destFileFullPath, string arguments = "", string? iconFilePath = null) + { + try + { + if (IsWindows) + { + using var shortcut = new WindowsShortcut + { + Path = @destFileFullPath, + Description = "KnossosNET quicklaunch to " + shortcutName, + IconLocation = iconFilePath == null ? destFileFullPath : iconFilePath, + Arguments = arguments + }; + + shortcut.Save(@Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + Path.DirectorySeparatorChar + shortcutName + ".lnk"); + } + }catch(Exception ex) + { + Log.Add(Log.LogSeverity.Error, "KnUtils.CreateDesktopShortcut()", ex); + } + } } } diff --git a/Knossos.NET/Classes/Knossos.cs b/Knossos.NET/Classes/Knossos.cs index c989812e..e001bfd0 100644 --- a/Knossos.NET/Classes/Knossos.cs +++ b/Knossos.NET/Classes/Knossos.cs @@ -191,13 +191,20 @@ private static async Task QuickLaunch() string modid = string.Empty; string modver = string.Empty; string modExecType = string.Empty; + string toolName = string.Empty; bool saveID = false; bool saveVer = false; bool saveExecType = false; + bool toolID = false; foreach (var arg in args) { Log.Add(Log.LogSeverity.Information, "Knossos.StartUp", "Knet Cmdline Arg: " + arg); + if (toolID) + { + toolID = false; + toolName = arg; + } if (saveID) { saveID = false; @@ -217,6 +224,10 @@ private static async Task QuickLaunch() { saveID = true; } + if (arg.ToLower() == "-tool") + { + toolID = true; + } if (arg.ToLower() == "-version") { saveVer = true; @@ -227,6 +238,26 @@ private static async Task QuickLaunch() } } + if (toolName != string.Empty) + { + var tool = GetTools().FirstOrDefault(x=> x.name.ToLower() == toolName.ToLower()); + try + { + if (tool != null) + { + _ = tool.Open(); + } + else + { + Log.Add(Log.LogSeverity.Error, "Knossos.QuickLaunch", "Quick launch was used but the tool was not found. Used tool name: " + toolName); + } + } + catch(Exception ex) + { + Log.Add(Log.LogSeverity.Error, "Knossos.QuickLaunch", ex); + } + } + if(modid != string.Empty) { var execType = FsoExecType.Release; diff --git a/Knossos.NET/Classes/Tool.cs b/Knossos.NET/Classes/Tool.cs index 6402625b..1ceb8b16 100644 --- a/Knossos.NET/Classes/Tool.cs +++ b/Knossos.NET/Classes/Tool.cs @@ -6,6 +6,7 @@ using System.Text.Json; using System.Text.Json.Serialization; using System.IO; +using System.Threading.Tasks; namespace Knossos.NET.Classes { @@ -70,25 +71,39 @@ public Tool(string folderpath) /// /// /// true or false depending if the process start was successfull - public bool Open(string? workingFolder = null) + public async Task Open(string? workingFolder = null) { - var best = GetBestPackage(); - if (folderpath != string.Empty && best != null) + var bestPkg = GetBestPackage(); + var path = GetExecutableFullPath(bestPkg); + if (path != null) { try { if (!KnUtils.IsWindows) - KnUtils.Chmod(Path.Combine(folderpath, best.executablePath)); - using (var process = new Process()) + KnUtils.Chmod(path); + + if(bestPkg != null && bestPkg.wineSupport && bestPkg.os.ToLower() == "windows" && KnUtils.IsLinux) { - process.StartInfo.FileName = Path.Combine(folderpath, best.executablePath); - if(cmdline != string.Empty) - process.StartInfo.Arguments = cmdline; - if(workingFolder != null) - process.StartInfo.WorkingDirectory = workingFolder; - process.StartInfo.UseShellExecute = true; - process.Start(); - return true; + Log.Add(Log.LogSeverity.Information, "Tool.Open()", "Executing Wine to run this tool: " + path); + //Wine + var res = await Wine.RunTool(path,cmdline, workingFolder, bestPkg.cpuArch); + return res.IsSuccess; + } + else + { + Log.Add(Log.LogSeverity.Information, "Tool.Open()", "Running tool: " + path); + //Normal + using (var process = new Process()) + { + process.StartInfo.FileName = path; + if (cmdline != string.Empty) + process.StartInfo.Arguments = cmdline; + if (workingFolder != null) + process.StartInfo.WorkingDirectory = workingFolder; + process.StartInfo.UseShellExecute = true; + process.Start(); + return true; + } } } catch (Exception ex) @@ -96,11 +111,25 @@ public bool Open(string? workingFolder = null) Log.Add(Log.LogSeverity.Error, "Tool.Open()", ex); } } + return false; + } + + /// + /// Gets full path to the best executable for this tool on this platform + /// + /// fullpath string or null + public string? GetExecutableFullPath(ToolPackage? toolPackage = null) + { + var best = toolPackage == null ? GetBestPackage() : toolPackage; + if (folderpath != string.Empty && best != null) + { + return Path.Combine(folderpath, best.executablePath); + } else { - Log.Add(Log.LogSeverity.Error, "Tool.Open()", "Invalid platform or folderpath is empty. Tool: " + name); + Log.Add(Log.LogSeverity.Error, "Tool.GetExecutableFullPath()", "Invalid platform or folderpath is empty. Tool: " + name); } - return false; + return null; } /// @@ -257,6 +286,26 @@ private void SetPkgScores() } } } + else + { + //Wine + if(pkg.wineSupport && pkg.os.ToLower() == "windows" && KnUtils.IsLinux) + { + foreach (var arch in archs) + { + if (arch == "x64" && KnUtils.CpuArch == "X64" || + arch == "x86" && KnUtils.CpuArch == "X86" || + arch == "arm64" && KnUtils.CpuArch == "Arm64" || + arch == "arm32" && KnUtils.CpuArch != "Arm64" && (KnUtils.CpuArch == "Arm" || KnUtils.CpuArch == "Armv6") || + arch == "riscv64" && KnUtils.CpuArch == "RiscV64" || + arch == "riscv32" && KnUtils.CpuArch == "RiscV32") + { + pkg.score = 5; + continue; + } + } + } + } } scoresSet = true; } @@ -276,5 +325,7 @@ public class ToolPackage public string executablePath { get; set; } = string.Empty; [JsonIgnore] public int score { get; set; } = 0; + [JsonPropertyName("wine_support")] + public bool wineSupport { get; set; } = false; } } diff --git a/Knossos.NET/Classes/Wine.cs b/Knossos.NET/Classes/Wine.cs index 23283deb..5233e532 100644 --- a/Knossos.NET/Classes/Wine.cs +++ b/Knossos.NET/Classes/Wine.cs @@ -30,6 +30,55 @@ public WineResult(bool isSuccess) /// public static class Wine { + public static async Task RunTool(string exePath, string exeCmdLine, string? workingFolder, string arch) + { + try + { + var wineArch = GetWineArch(arch.ToLower()); + if (wineArch == null) + { + return new WineResult(false, "Unsupported WINEARCH: " + arch); + } + + var prefixResult = await SetWinePrefixFred2(wineArch); //use the same settings for fred2 + if (!prefixResult.IsSuccess) + { + return prefixResult; + } + + var winePrefix = GetWinePrefixPath(); + Log.Add(Log.LogSeverity.Information, "Wine.RunTool()", "Executing wine with the following cmdline: WINEPREFIX=" + winePrefix + + " WINEARCH=" + wineArch + " wine " + exePath + " " + exeCmdLine); + + using (var wine = new Process()) + { + wine.StartInfo.FileName = "wine"; + wine.StartInfo.Arguments = exePath + " " + exeCmdLine; + if (workingFolder != null) + { + wine.StartInfo.WorkingDirectory = workingFolder; + } + wine.StartInfo.EnvironmentVariables["WINEPREFIX"] = winePrefix; + wine.StartInfo.EnvironmentVariables["WINEARCH"] = wineArch; + wine.StartInfo.UseShellExecute = false; + wine.Start(); + await wine.WaitForExitAsync(); + } + + return new WineResult(true); + } + catch (Win32Exception ex) + { + Log.Add(Log.LogSeverity.Error, "Wine.RunTool()", "Wine not found or another error ocurred: " + ex.Message); + return new WineResult(false, "Wine not found or another error ocurred: " + ex.Message); + } + catch (Exception ex) + { + Log.Add(Log.LogSeverity.Error, "Wine.RunTool()", ex.ToString()); + return new WineResult(false, ex.ToString()); + } + } + public static async Task RunFred2(string exePath, string exeCmdLine, string? workingFolder, FsoExecArch fsoArch) { try @@ -47,7 +96,7 @@ public static async Task RunFred2(string exePath, string exeCmdLine, } var winePrefix = GetWinePrefixPath(); - Log.Add(Log.LogSeverity.Information, "Wine.SetWinePrefixFred2()", "Executing wine with the following cmdline: WINEPREFIX=" + winePrefix + + Log.Add(Log.LogSeverity.Information, "Wine.RunFred2()", "Executing wine with the following cmdline: WINEPREFIX=" + winePrefix + " WINEARCH=" + wineArch + " wine " + exePath + " " + exeCmdLine); using (var wine = new Process()) @@ -69,7 +118,7 @@ public static async Task RunFred2(string exePath, string exeCmdLine, } catch (Win32Exception ex) { - Log.Add(Log.LogSeverity.Error, "Wine.SetWinePrefixFred2()", "Wine not found or another error ocurred: " + ex.Message); + Log.Add(Log.LogSeverity.Error, "Wine.RunFred2()", "Wine not found or another error ocurred: " + ex.Message); return new WineResult(false, "Wine not found or another error ocurred: " + ex.Message); } catch (Exception ex) @@ -161,6 +210,26 @@ private static async Task SetWinePrefixFred2(string wineArch) } } + /// + /// Determine WINEARCH from Arch string (tools) + /// + /// + /// WineArch compatible string or null + private static string? GetWineArch(string archString) + { + switch (archString) + { + case "x86": + return "win32"; + case "x64": + case "arm64": + case "riscv64": + return "win64"; + default: + return null; + } + } + /// /// Get the WinePrefix directory, a "wine" directory inside Knet data folder /// diff --git a/Knossos.NET/Knossos.NET.csproj b/Knossos.NET/Knossos.NET.csproj index 1c3ebf66..022dd763 100644 --- a/Knossos.NET/Knossos.NET.csproj +++ b/Knossos.NET/Knossos.NET.csproj @@ -83,6 +83,7 @@ + diff --git a/Knossos.NET/Program.cs b/Knossos.NET/Program.cs index e321a365..00edf8a1 100644 --- a/Knossos.NET/Program.cs +++ b/Knossos.NET/Program.cs @@ -22,7 +22,7 @@ public static void Main(string[] args) { softwareRendering = true; } - if (arg.ToLower() == "-playmod") + if (arg.ToLower() == "-playmod" || arg.ToLower() == "-tool") { isQuickLaunch = true; } diff --git a/Knossos.NET/ViewModels/TaskViewModel.cs b/Knossos.NET/ViewModels/TaskViewModel.cs index c8c73880..5fe7f51e 100644 --- a/Knossos.NET/ViewModels/TaskViewModel.cs +++ b/Knossos.NET/ViewModels/TaskViewModel.cs @@ -423,7 +423,7 @@ public async void UploadModVersion(Mod mod, bool isNewMod, bool metadataonly = f /// /// /// - public async void DownloadTool(Tool tool, Tool? updateFrom, Action finishedCallback) + public async Task DownloadTool(Tool tool, Tool? updateFrom, Action finishedCallback) { using (var cancelSource = new CancellationTokenSource()) { @@ -433,7 +433,7 @@ public async void DownloadTool(Tool tool, Tool? updateFrom, Action finishe TaskList.Add(newTask); taskQueue.Enqueue(newTask); }); - await newTask.InstallTool(tool, updateFrom, finishedCallback, cancelSource).ConfigureAwait(false); + return await newTask.InstallTool(tool, updateFrom, finishedCallback, cancelSource).ConfigureAwait(false); } } } diff --git a/Knossos.NET/ViewModels/Templates/DevModEditorViewModel.cs b/Knossos.NET/ViewModels/Templates/DevModEditorViewModel.cs index ae3b98f2..46e7884c 100644 --- a/Knossos.NET/ViewModels/Templates/DevModEditorViewModel.cs +++ b/Knossos.NET/ViewModels/Templates/DevModEditorViewModel.cs @@ -248,7 +248,7 @@ internal void PlayMod(object type) } } - internal void OpenTool() + internal async void OpenTool() { try { @@ -260,7 +260,7 @@ internal void OpenTool() var tool = selected.DataContext as Tool; if (tool != null) { - tool.Open(ActiveVersion.fullPath); + await tool.Open(ActiveVersion.fullPath); } } } diff --git a/Knossos.NET/ViewModels/Templates/DevToolManagerViewModel.cs b/Knossos.NET/ViewModels/Templates/DevToolManagerViewModel.cs index 8db27985..60ae4c60 100644 --- a/Knossos.NET/ViewModels/Templates/DevToolManagerViewModel.cs +++ b/Knossos.NET/ViewModels/Templates/DevToolManagerViewModel.cs @@ -16,6 +16,10 @@ public partial class DevToolManagerViewModel : ViewModelBase /**/ public partial class ToolItem : ObservableObject { + [ObservableProperty] + internal bool wine = false; + [ObservableProperty] + internal bool shortcutEnabled = KnUtils.IsWindows; [ObservableProperty] internal IBrush favoriteColor = Brushes.White; [ObservableProperty] @@ -27,18 +31,25 @@ public partial class ToolItem : ObservableObject [ObservableProperty] internal string updateTooltip = ""; [ObservableProperty] - internal string toolTip = ""; + internal string description = ""; [ObservableProperty] public Tool tool; public Tool? repo; + private DevToolManagerViewModel? toolMgr; - public ToolItem(Tool tool) + public ToolItem(Tool tool, DevToolManagerViewModel? toolMgr) { this.tool = tool; - ToolTip = tool.description + "\n\n\nLast Updated: " + tool.lastUpdate; + Description = tool.description + "\n\n\nLast Updated: " + tool.lastUpdate; IsInstalled = tool.isInstalled; if (Tool.isFavorite) FavoriteColor = Brushes.Yellow; + this.toolMgr = toolMgr; + if(KnUtils.IsLinux) + { + var checkStatus = tool.GetBestPackage()?.wineSupport; + Wine = checkStatus.HasValue ? checkStatus.Value : false; + } } internal void ToggleFavorite() @@ -64,11 +75,11 @@ public void AddRepoVersion(Tool repo) } } - internal void Update() + internal async void Update() { DisableButtons = true; if(repo != null) - TaskViewModel.Instance!.DownloadTool(repo, Tool, Callback); + await TaskViewModel.Instance!.DownloadTool(repo, Tool, Callback); } internal void Delete() @@ -85,19 +96,35 @@ internal void Delete() IsInstalled = Tool.isInstalled; } IsInstalled = false; + toolMgr?.SortTools(); } catch { } } - internal void Install() + internal async void Install() { DisableButtons = true; - TaskViewModel.Instance!.DownloadTool(Tool,null,Callback); + await TaskViewModel.Instance!.DownloadTool(Tool,null,Callback); + toolMgr?.SortTools(); + } + + internal void Shortcut() + { + var execPath = Tool.GetExecutableFullPath(); + var knPath = System.Diagnostics.Process.GetCurrentProcess().MainModule!.FileName; + if (execPath != null && knPath != null) + { + if (KnUtils.IsAppImage) + { + knPath = KnUtils.AppImagePath; + } + KnUtils.CreateDesktopShortcut(Tool.name, knPath, "-tool "+ "\"" + Tool.name + "\"", execPath); + } } internal void Open() { - Tool.Open(); + _= Tool.Open(); } internal void Callback(bool _) @@ -112,6 +139,22 @@ internal void Callback(bool _) } IsInstalled = Tool.isInstalled; } + + /// + /// To use with List .Sort() + /// + public static int CompareTools(ToolItem t1, ToolItem t2) + { + if (t1.IsInstalled && !t2.IsInstalled) + { + return -1; + } + if (!t1.IsInstalled && t2.IsInstalled) + { + return 1; + } + return string.Compare(t1.Tool.name, t2.Tool.name); + } } /**/ @@ -137,6 +180,19 @@ public async void LoadTools() } } + internal void SortTools() + { + Dispatcher.UIThread.Invoke(new Action(() => { + var list = Tools.ToList(); + list.Sort((x, y) => ToolItem.CompareTools(x,y)); + Tools.Clear(); + foreach (var item in list) + { + Tools.Add(item); + } + })); + } + private async Task LoadToolRepo() { try @@ -176,16 +232,19 @@ private void InsertInOrder(Tool tool) int i; for (i = 0; i < Tools.Count; i++) { - if(Tools[i].Tool.isFavorite == tool.isFavorite && String.Compare(Tools[i].Tool.name, tool.name) > 0) + if (!Tools[i].Tool.isInstalled && tool.isInstalled) { break; } - if (!Tools[i].Tool.isFavorite && tool.isFavorite) + if (Tools[i].Tool.isInstalled == tool.isInstalled) { - break; + if (String.Compare(Tools[i].Tool.name, tool.name) > 0) + { + break; + } } } - Tools.Insert(i, new ToolItem(tool)); + Tools.Insert(i, new ToolItem(tool, this)); } } } diff --git a/Knossos.NET/ViewModels/Windows/ModSettingsViewModel.cs b/Knossos.NET/ViewModels/Windows/ModSettingsViewModel.cs index 7b591b0c..780562a1 100644 --- a/Knossos.NET/ViewModels/Windows/ModSettingsViewModel.cs +++ b/Knossos.NET/ViewModels/Windows/ModSettingsViewModel.cs @@ -25,6 +25,8 @@ public partial class ModSettingsViewModel : ViewModelBase /* UI Variables with ObervableProperty*/ [ObservableProperty] + internal bool shortcutEnabled = KnUtils.IsWindows; + [ObservableProperty] internal bool configureBuildOpen = false; [ObservableProperty] internal string title = string.Empty; @@ -133,6 +135,22 @@ public ModSettingsViewModel(Mod modJson, ModCardViewModel? modCard=null) Task.Factory.StartNew(() => UpdateModSize()); } + /// + /// Generate mod shortcut on windows + /// + internal void Shortcut() + { + var knPath = System.Diagnostics.Process.GetCurrentProcess().MainModule!.FileName; + if (knPath != null) + { + if (KnUtils.IsAppImage) + { + knPath = KnUtils.AppImagePath; + } + KnUtils.CreateDesktopShortcut(modJson!.title, knPath, "-playmod " + modJson.id + " -version " + modJson.version + " -exec Default"); + } + } + /// /// Update Mod Folder size value on UI /// diff --git a/Knossos.NET/Views/Templates/DevToolManagerView.axaml b/Knossos.NET/Views/Templates/DevToolManagerView.axaml index 87c28e78..a2f5926f 100644 --- a/Knossos.NET/Views/Templates/DevToolManagerView.axaml +++ b/Knossos.NET/Views/Templates/DevToolManagerView.axaml @@ -12,20 +12,54 @@ - + - - - + + + + + - - - - + + + + + + + + + + +