mirror of
https://github.com/terrymacdonald/DisplayMagician.git
synced 2024-08-30 18:32:20 +00:00
If a shortcut has Autoname turned on, and if the user changes the name of the profile, then the shortcut will be renamed to keep pace with the new profile name. If autoname is NOT turned on, then the shortcut name will be kept as is, and the user will need to make any changes. Please note that HeliosPlus will not make any changes to any desktop shortcuts saved to the PC. It will only change the name of the shortcut in the shortcut library within the App.
469 lines
16 KiB
C#
469 lines
16 KiB
C#
using HeliosPlus.Shared;
|
|
using Newtonsoft.Json;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing.IconLib;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
|
|
namespace HeliosPlus
|
|
{
|
|
|
|
class ShortcutRepository
|
|
{
|
|
#region Class Variables
|
|
// Common items to the class
|
|
private static List<ShortcutItem> _allShortcuts = null;
|
|
public static Version Version = new Version(1, 0, 0);
|
|
// Other constants that are useful
|
|
private static string _shortcutStorageJsonPath = Path.Combine(Program.AppDataPath, $"Shortcuts");
|
|
private static string _shortcutStorageJsonFileName = Path.Combine(_shortcutStorageJsonPath, $"Shortcuts_{Version.ToString(2)}.json");
|
|
private static uint _lastShortcutId;
|
|
#endregion
|
|
|
|
#region Instance Variables
|
|
// Individual items per class instance
|
|
#endregion
|
|
|
|
|
|
#region Class Constructors
|
|
public ShortcutRepository()
|
|
{
|
|
// Load the Shortcuts from storage
|
|
LoadShortcuts();
|
|
/* if (LoadShortcuts() && ShortcutCount > 0)
|
|
{
|
|
// Work out the starting NextShortcutId value
|
|
long max = _allShortcuts.Max<ShortcutItem>(item => item.Id);
|
|
_lastShortcutId = Convert.ToUInt32(max);
|
|
} else
|
|
_lastShortcutId = 0;
|
|
*/ }
|
|
|
|
public ShortcutRepository(ShortcutItem shortcut) : this()
|
|
{
|
|
if (shortcut is ShortcutItem)
|
|
AddShortcut(shortcut);
|
|
}
|
|
#endregion
|
|
|
|
#region Class Properties
|
|
public static List<ShortcutItem> AllShortcuts
|
|
{
|
|
get
|
|
{
|
|
if (_allShortcuts == null)
|
|
// Load the Shortcuts from storage
|
|
LoadShortcuts();
|
|
/* if (LoadShortcuts() && ShortcutCount > 0)
|
|
{
|
|
// Work out the starting NextShortcutId value
|
|
long max = _allShortcuts.Max<ShortcutItem>(item => item.Id);
|
|
_lastShortcutId = Convert.ToUInt32(max);
|
|
}
|
|
else
|
|
_lastShortcutId = 0;
|
|
*/
|
|
return _allShortcuts;
|
|
}
|
|
}
|
|
|
|
|
|
public static int ShortcutCount
|
|
{
|
|
get
|
|
{
|
|
return _allShortcuts.Count;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Class Methods
|
|
public static bool AddShortcut(ShortcutItem shortcut)
|
|
{
|
|
if (!(shortcut is ShortcutItem))
|
|
return false;
|
|
|
|
// Doublecheck if it already exists
|
|
// Because then we just update the one that already exists
|
|
if (ContainsShortcut(shortcut))
|
|
{
|
|
// We update the existing Shortcut with the data over
|
|
ShortcutItem shortcutToUpdate = GetShortcut(shortcut.UUID);
|
|
shortcut.CopyTo(shortcutToUpdate);
|
|
}
|
|
else
|
|
{
|
|
// Add the shortcut to the list of shortcuts
|
|
_allShortcuts.Add(shortcut);
|
|
}
|
|
|
|
//Doublecheck it's been added
|
|
if (ContainsShortcut(shortcut))
|
|
{
|
|
// Generate the Shortcut Icon ready to be used
|
|
SaveShortcutIconToCache(shortcut);
|
|
|
|
// Save the shortcuts JSON as it's different
|
|
SaveShortcuts();
|
|
|
|
return true;
|
|
}
|
|
else
|
|
return false;
|
|
|
|
}
|
|
|
|
public static bool RemoveShortcut(ShortcutItem shortcut)
|
|
{
|
|
if (!(shortcut is ShortcutItem))
|
|
return false;
|
|
|
|
// Remove the Shortcut Icons from the Cache
|
|
List<ShortcutItem> shortcutsToRemove = _allShortcuts.FindAll(item => item.UUID.Equals(shortcut.UUID));
|
|
foreach (ShortcutItem shortcutToRemove in shortcutsToRemove)
|
|
{
|
|
try
|
|
{
|
|
File.Delete(shortcutToRemove.SavedShortcutIconCacheFilename);
|
|
}
|
|
catch
|
|
{
|
|
// TODO check and report
|
|
}
|
|
}
|
|
|
|
// Remove the shortcut from the list.
|
|
int numRemoved = _allShortcuts.RemoveAll(item => item.UUID.Equals(shortcut.UUID));
|
|
|
|
if (numRemoved == 1)
|
|
{
|
|
SaveShortcuts();
|
|
return true;
|
|
}
|
|
else if (numRemoved == 0)
|
|
return false;
|
|
else
|
|
throw new ShortcutRepositoryException();
|
|
}
|
|
|
|
|
|
public static bool RemoveShortcut(string shortcutNameOrUuid)
|
|
{
|
|
if (String.IsNullOrWhiteSpace(shortcutNameOrUuid))
|
|
return false;
|
|
|
|
List<ShortcutItem> shortcutsToRemove;
|
|
int numRemoved;
|
|
|
|
string uuidV4Regex = @"/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i";
|
|
Match match = Regex.Match(shortcutNameOrUuid, uuidV4Regex, RegexOptions.IgnoreCase);
|
|
if (match.Success)
|
|
{
|
|
shortcutsToRemove = _allShortcuts.FindAll(item => item.UUID.Equals(shortcutNameOrUuid));
|
|
numRemoved = _allShortcuts.RemoveAll(item => item.UUID.Equals(shortcutNameOrUuid));
|
|
}
|
|
else
|
|
{
|
|
shortcutsToRemove = _allShortcuts.FindAll(item => item.Name.Equals(shortcutNameOrUuid));
|
|
numRemoved = _allShortcuts.RemoveAll(item => item.Name.Equals(shortcutNameOrUuid));
|
|
}
|
|
// Remove the Shortcut Icons from the Cache
|
|
foreach (ShortcutItem shortcutToRemove in shortcutsToRemove)
|
|
{
|
|
try
|
|
{
|
|
File.Delete(shortcutToRemove.SavedShortcutIconCacheFilename);
|
|
}
|
|
catch
|
|
{
|
|
// TODO check and report
|
|
}
|
|
}
|
|
|
|
if (numRemoved == 1)
|
|
{
|
|
SaveShortcuts();
|
|
return true;
|
|
}
|
|
else if (numRemoved == 0)
|
|
return false;
|
|
else
|
|
throw new ShortcutRepositoryException();
|
|
|
|
}
|
|
|
|
|
|
public static bool ContainsShortcut(ShortcutItem shortcut)
|
|
{
|
|
if (!(shortcut is ShortcutItem))
|
|
return false;
|
|
|
|
foreach (ShortcutItem testShortcut in _allShortcuts)
|
|
{
|
|
if (testShortcut.UUID.Equals(shortcut.UUID))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public static bool ContainsShortcut(string shortcutNameOrUuid)
|
|
{
|
|
if (String.IsNullOrWhiteSpace(shortcutNameOrUuid))
|
|
return false;
|
|
|
|
|
|
string uuidV4Regex = @"/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i";
|
|
Match match = Regex.Match(shortcutNameOrUuid, uuidV4Regex, RegexOptions.IgnoreCase);
|
|
if (match.Success)
|
|
{
|
|
foreach (ShortcutItem testShortcut in _allShortcuts)
|
|
{
|
|
if (testShortcut.UUID.Equals(shortcutNameOrUuid))
|
|
return true;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
foreach (ShortcutItem testShortcut in _allShortcuts)
|
|
{
|
|
if (testShortcut.Name.Equals(shortcutNameOrUuid))
|
|
return true;
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
public static ShortcutItem GetShortcut(string shortcutNameOrUuid)
|
|
{
|
|
if (String.IsNullOrWhiteSpace(shortcutNameOrUuid))
|
|
return null;
|
|
|
|
string uuidV4Regex = @"/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i";
|
|
Match match = Regex.Match(shortcutNameOrUuid, uuidV4Regex, RegexOptions.IgnoreCase);
|
|
if (match.Success)
|
|
{
|
|
foreach (ShortcutItem testShortcut in _allShortcuts)
|
|
{
|
|
if (testShortcut.UUID.Equals(shortcutNameOrUuid))
|
|
return testShortcut;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
foreach (ShortcutItem testShortcut in _allShortcuts)
|
|
{
|
|
if (testShortcut.Name.Equals(shortcutNameOrUuid))
|
|
return testShortcut;
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
public static bool RenameShortcutProfile(ProfileItem newProfile)
|
|
{
|
|
if (!(newProfile is ProfileItem))
|
|
return false;
|
|
|
|
foreach (ShortcutItem testShortcut in ShortcutRepository.AllShortcuts)
|
|
{
|
|
if (testShortcut.ProfileUUID.Equals(newProfile.UUID) && testShortcut.AutoName)
|
|
{
|
|
testShortcut.ProfileToUse = newProfile;
|
|
testShortcut.AutoSuggestShortcutName();
|
|
}
|
|
}
|
|
|
|
SaveShortcuts();
|
|
|
|
return true;
|
|
}
|
|
|
|
/* public static uint GetNextAvailableShortcutId()
|
|
{
|
|
return ++_lastShortcutId;
|
|
}*/
|
|
|
|
|
|
|
|
|
|
|
|
private static bool LoadShortcuts()
|
|
{
|
|
|
|
if (File.Exists(_shortcutStorageJsonFileName))
|
|
{
|
|
var json = File.ReadAllText(_shortcutStorageJsonFileName, Encoding.Unicode);
|
|
|
|
if (!string.IsNullOrWhiteSpace(json))
|
|
{
|
|
List<ShortcutItem> shortcuts = new List<ShortcutItem>();
|
|
try
|
|
{
|
|
_allShortcuts = JsonConvert.DeserializeObject<List<ShortcutItem>>(json, new JsonSerializerSettings
|
|
{
|
|
MissingMemberHandling = MissingMemberHandling.Ignore,
|
|
NullValueHandling = NullValueHandling.Ignore,
|
|
DefaultValueHandling = DefaultValueHandling.Include,
|
|
TypeNameHandling = TypeNameHandling.Auto
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// ignored
|
|
Console.WriteLine($"Unable to load Shortcuts from JSON file {_shortcutStorageJsonFileName}: " + ex.Message);
|
|
}
|
|
|
|
// Lookup all the Profile Names in the Saved Profiles
|
|
foreach (ShortcutItem updatedShortcut in _allShortcuts)
|
|
{
|
|
foreach (ProfileItem profile in ProfileRepository.AllProfiles)
|
|
{
|
|
|
|
if (profile.Equals(updatedShortcut.ProfileToUse))
|
|
{
|
|
// And assign the matching Profile if we find it.
|
|
updatedShortcut.ProfileToUse = profile;
|
|
updatedShortcut.IsPossible = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private static bool SaveShortcuts()
|
|
{
|
|
|
|
if (!Directory.Exists(_shortcutStorageJsonPath))
|
|
{
|
|
try
|
|
{
|
|
Directory.CreateDirectory(_shortcutStorageJsonPath);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"Unable to create Shortcut folder {_shortcutStorageJsonPath}: " + ex.Message);
|
|
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
var json = JsonConvert.SerializeObject(_allShortcuts, Formatting.Indented, new JsonSerializerSettings
|
|
{
|
|
NullValueHandling = NullValueHandling.Include,
|
|
DefaultValueHandling = DefaultValueHandling.Populate,
|
|
TypeNameHandling = TypeNameHandling.Auto
|
|
|
|
});
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(json))
|
|
{
|
|
File.WriteAllText(_shortcutStorageJsonFileName, json, Encoding.Unicode);
|
|
return true;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"Unable to save Shortcut JSON file {_shortcutStorageJsonFileName}: " + ex.Message);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private static void SaveShortcutIconToCache(ShortcutItem shortcut)
|
|
{
|
|
|
|
// Only add the rest of the options if the permanence is temporary
|
|
if (shortcut.Permanence == ShortcutPermanence.Temporary)
|
|
{
|
|
// Only add this set of options if the shortcut is to an standalone application
|
|
if (shortcut.Category == ShortcutCategory.Application)
|
|
{
|
|
// Work out the name of the shortcut we'll save.
|
|
shortcut.SavedShortcutIconCacheFilename = Path.Combine(_shortcutStorageJsonPath, String.Concat(@"executable-", shortcut.ProfileToUse.UUID, "-", Path.GetFileNameWithoutExtension(shortcut.ExecutableNameAndPath), @".ico"));
|
|
|
|
}
|
|
// Only add the rest of the options if the temporary switch radio button is set
|
|
// and if the game launching radio button is set
|
|
else if (shortcut.Permanence == ShortcutPermanence.Temporary)
|
|
{
|
|
// TODO need to make this work so at least one game library is installed
|
|
// i.e. if (!SteamGame.SteamInstalled && !UplayGame.UplayInstalled )
|
|
if (shortcut.GameLibrary == SupportedGameLibrary.Steam)
|
|
{
|
|
// Work out the name of the shortcut we'll save.
|
|
shortcut.SavedShortcutIconCacheFilename = Path.Combine(_shortcutStorageJsonPath, String.Concat(@"steam-", shortcut.ProfileToUse.UUID, "-", shortcut.GameAppId.ToString(), @".ico"));
|
|
|
|
}
|
|
else if (shortcut.GameLibrary == SupportedGameLibrary.Uplay)
|
|
{
|
|
// Work out the name of the shortcut we'll save.
|
|
shortcut.SavedShortcutIconCacheFilename = Path.Combine(_shortcutStorageJsonPath, String.Concat(@"uplay-", shortcut.ProfileToUse.UUID, "-", shortcut.GameAppId.ToString(), @".ico"));
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
// Only add the rest of the options if the shortcut is permanent
|
|
else
|
|
{
|
|
// Work out the name of the shortcut we'll save.
|
|
shortcut.SavedShortcutIconCacheFilename = Path.Combine(_shortcutStorageJsonPath, String.Concat(@"permanent-", shortcut.ProfileToUse.UUID, @".ico"));
|
|
}
|
|
|
|
MultiIcon shortcutIcon;
|
|
try
|
|
{
|
|
//shortcutIcon = new ProfileIcon(shortcut.ProfileToUse).ToIconOverlay(shortcut.OriginalIconPath);
|
|
shortcutIcon = shortcut.ToIconOverlay();
|
|
shortcutIcon.Save(shortcut.SavedShortcutIconCacheFilename, MultiIconFormat.ICO);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// If we fail to create an icon based on the original executable or game
|
|
// Then we use the standard HeliosPlus profile one.
|
|
shortcutIcon = shortcut.ProfileToUse.ProfileIcon.ToIcon();
|
|
shortcutIcon.Save(shortcut.SavedShortcutIconCacheFilename, MultiIconFormat.ICO);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
|
|
[global::System.Serializable]
|
|
public class ShortcutRepositoryException : Exception
|
|
{
|
|
public ShortcutRepositoryException() { }
|
|
public ShortcutRepositoryException(string message) : base(message) { }
|
|
public ShortcutRepositoryException(string message, Exception inner) : base(message, inner) { }
|
|
protected ShortcutRepositoryException(
|
|
System.Runtime.Serialization.SerializationInfo info,
|
|
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
|
|
}
|
|
|
|
|
|
}
|