PowerAccentViewModel.cs
1 // Copyright (c) Microsoft Corporation 2 // The Microsoft Corporation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System; 6 using System.Collections.Generic; 7 using System.Linq; 8 using System.Runtime.CompilerServices; 9 using global::PowerToys.GPOWrapper; 10 using Microsoft.PowerToys.Settings.UI.Helpers; 11 using Microsoft.PowerToys.Settings.UI.Library; 12 using Microsoft.PowerToys.Settings.UI.Library.Enumerations; 13 using Microsoft.PowerToys.Settings.UI.Library.Helpers; 14 using Microsoft.PowerToys.Settings.UI.Library.Interfaces; 15 16 namespace Microsoft.PowerToys.Settings.UI.ViewModels 17 { 18 public partial class PowerAccentViewModel : Observable 19 { 20 private GeneralSettings GeneralSettingsConfig { get; set; } 21 22 private readonly PowerAccentSettings _powerAccentSettings; 23 24 private readonly SettingsUtils _settingsUtils; 25 26 private const string SpecialGroup = "QuickAccent_Group_Special"; 27 private const string LanguageGroup = "QuickAccent_Group_Language"; 28 29 public List<PowerAccentLanguageModel> Languages { get; } = [ 30 new PowerAccentLanguageModel("SPECIAL", "QuickAccent_SelectedLanguage_Special", SpecialGroup), 31 new PowerAccentLanguageModel("BG", "QuickAccent_SelectedLanguage_Bulgarian", LanguageGroup), 32 new PowerAccentLanguageModel("CA", "QuickAccent_SelectedLanguage_Catalan", LanguageGroup), 33 new PowerAccentLanguageModel("CRH", "QuickAccent_SelectedLanguage_Crimean", LanguageGroup), 34 new PowerAccentLanguageModel("CUR", "QuickAccent_SelectedLanguage_Currency", SpecialGroup), 35 new PowerAccentLanguageModel("HR", "QuickAccent_SelectedLanguage_Croatian", LanguageGroup), 36 new PowerAccentLanguageModel("CZ", "QuickAccent_SelectedLanguage_Czech", LanguageGroup), 37 new PowerAccentLanguageModel("DK", "QuickAccent_SelectedLanguage_Danish", LanguageGroup), 38 new PowerAccentLanguageModel("GA", "QuickAccent_SelectedLanguage_Gaeilge", LanguageGroup), 39 new PowerAccentLanguageModel("GD", "QuickAccent_SelectedLanguage_Gaidhlig", LanguageGroup), 40 new PowerAccentLanguageModel("NL", "QuickAccent_SelectedLanguage_Dutch", LanguageGroup), 41 new PowerAccentLanguageModel("EL", "QuickAccent_SelectedLanguage_Greek", LanguageGroup), 42 new PowerAccentLanguageModel("EST", "QuickAccent_SelectedLanguage_Estonian", LanguageGroup), 43 new PowerAccentLanguageModel("EPO", "QuickAccent_SelectedLanguage_Esperanto", LanguageGroup), 44 new PowerAccentLanguageModel("FI", "QuickAccent_SelectedLanguage_Finnish", LanguageGroup), 45 new PowerAccentLanguageModel("FR", "QuickAccent_SelectedLanguage_French", LanguageGroup), 46 new PowerAccentLanguageModel("DE", "QuickAccent_SelectedLanguage_German", LanguageGroup), 47 new PowerAccentLanguageModel("HE", "QuickAccent_SelectedLanguage_Hebrew", LanguageGroup), 48 new PowerAccentLanguageModel("HU", "QuickAccent_SelectedLanguage_Hungarian", LanguageGroup), 49 new PowerAccentLanguageModel("IS", "QuickAccent_SelectedLanguage_Icelandic", LanguageGroup), 50 new PowerAccentLanguageModel("IPA", "QuickAccent_SelectedLanguage_IPA", SpecialGroup), 51 new PowerAccentLanguageModel("IT", "QuickAccent_SelectedLanguage_Italian", LanguageGroup), 52 new PowerAccentLanguageModel("KU", "QuickAccent_SelectedLanguage_Kurdish", LanguageGroup), 53 new PowerAccentLanguageModel("LT", "QuickAccent_SelectedLanguage_Lithuanian", LanguageGroup), 54 new PowerAccentLanguageModel("MK", "QuickAccent_SelectedLanguage_Macedonian", LanguageGroup), 55 new PowerAccentLanguageModel("MT", "QuickAccent_SelectedLanguage_Maltese", LanguageGroup), 56 new PowerAccentLanguageModel("MI", "QuickAccent_SelectedLanguage_Maori", LanguageGroup), 57 new PowerAccentLanguageModel("NO", "QuickAccent_SelectedLanguage_Norwegian", LanguageGroup), 58 new PowerAccentLanguageModel("PI", "QuickAccent_SelectedLanguage_Pinyin", LanguageGroup), 59 new PowerAccentLanguageModel("PIE", "QuickAccent_SelectedLanguage_Proto_Indo_European", LanguageGroup), 60 new PowerAccentLanguageModel("PL", "QuickAccent_SelectedLanguage_Polish", LanguageGroup), 61 new PowerAccentLanguageModel("PT", "QuickAccent_SelectedLanguage_Portuguese", LanguageGroup), 62 new PowerAccentLanguageModel("RO", "QuickAccent_SelectedLanguage_Romanian", LanguageGroup), 63 new PowerAccentLanguageModel("ROM", "QuickAccent_SelectedLanguage_Romanization", SpecialGroup), 64 new PowerAccentLanguageModel("SK", "QuickAccent_SelectedLanguage_Slovak", LanguageGroup), 65 new PowerAccentLanguageModel("SL", "QuickAccent_SelectedLanguage_Slovenian", LanguageGroup), 66 new PowerAccentLanguageModel("SP", "QuickAccent_SelectedLanguage_Spanish", LanguageGroup), 67 new PowerAccentLanguageModel("SR", "QuickAccent_SelectedLanguage_Serbian", LanguageGroup), 68 new PowerAccentLanguageModel("SR_CYRL", "QuickAccent_SelectedLanguage_Serbian_Cyrillic", LanguageGroup), 69 new PowerAccentLanguageModel("SV", "QuickAccent_SelectedLanguage_Swedish", LanguageGroup), 70 new PowerAccentLanguageModel("TK", "QuickAccent_SelectedLanguage_Turkish", LanguageGroup), 71 new PowerAccentLanguageModel("VI", "QuickAccent_SelectedLanguage_Vietnamese", LanguageGroup), 72 new PowerAccentLanguageModel("CY", "QuickAccent_SelectedLanguage_Welsh", LanguageGroup), 73 ]; 74 75 public PowerAccentLanguageGroupModel[] LanguageGroups { get; private set; } 76 77 private readonly string[] _toolbarOptions = 78 { 79 "Top center", 80 "Bottom center", 81 "Left", 82 "Right", 83 "Top right corner", 84 "Top left corner", 85 "Bottom right corner", 86 "Bottom left corner", 87 "Center", 88 }; 89 90 private Func<string, int> SendConfigMSG { get; } 91 92 public PowerAccentViewModel(SettingsUtils settingsUtils, ISettingsRepository<GeneralSettings> settingsRepository, Func<string, int> ipcMSGCallBackFunc) 93 { 94 // To obtain the general settings configurations of PowerToys Settings. 95 ArgumentNullException.ThrowIfNull(settingsRepository); 96 97 _settingsUtils = settingsUtils ?? throw new ArgumentNullException(nameof(settingsUtils)); 98 GeneralSettingsConfig = settingsRepository.SettingsConfig; 99 100 InitializeEnabledValue(); 101 InitializeLanguages(); 102 103 if (_settingsUtils.SettingsExists(PowerAccentSettings.ModuleName)) 104 { 105 _powerAccentSettings = _settingsUtils.GetSettingsOrDefault<PowerAccentSettings>(PowerAccentSettings.ModuleName); 106 } 107 else 108 { 109 _powerAccentSettings = new PowerAccentSettings(); 110 } 111 112 _inputTimeMs = _powerAccentSettings.Properties.InputTime.Value; 113 114 _excludedApps = _powerAccentSettings.Properties.ExcludedApps.Value; 115 116 if (!string.IsNullOrWhiteSpace(_powerAccentSettings.Properties.SelectedLang.Value) && !_powerAccentSettings.Properties.SelectedLang.Value.Contains("ALL")) 117 { 118 SelectedLanguageOptions = _powerAccentSettings.Properties.SelectedLang.Value.Split(',') 119 .Select(l => Languages.Find(lang => lang.LanguageCode == l)) 120 .Where(l => l != null) // Wrongly typed languages will appear as null after find. We want to remove those to avoid crashes. 121 .ToArray(); 122 } 123 else if (_powerAccentSettings.Properties.SelectedLang.Value.Contains("ALL")) 124 { 125 SelectedLanguageOptions = Languages.ToArray(); 126 } 127 else 128 { 129 SelectedLanguageOptions = Array.Empty<PowerAccentLanguageModel>(); 130 } 131 132 _toolbarPositionIndex = Array.IndexOf(_toolbarOptions, _powerAccentSettings.Properties.ToolbarPosition.Value); 133 134 // set the callback functions value to handle outgoing IPC message. 135 SendConfigMSG = ipcMSGCallBackFunc; 136 } 137 138 private void InitializeEnabledValue() 139 { 140 _enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredQuickAccentEnabledValue(); 141 if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled) 142 { 143 // Get the enabled state from GPO. 144 _enabledStateIsGPOConfigured = true; 145 _isEnabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled; 146 } 147 else 148 { 149 _isEnabled = GeneralSettingsConfig.Enabled.PowerAccent; 150 } 151 } 152 153 /// <summary> 154 /// Adds Localized Language Name, sorts by it and splits languages into two groups. 155 /// </summary> 156 private void InitializeLanguages() 157 { 158 foreach (var item in Languages) 159 { 160 item.Language = ResourceLoaderInstance.ResourceLoader.GetString(item.LanguageResourceID); 161 } 162 163 Languages.Sort((x, y) => string.Compare(x.Language, y.Language, StringComparison.Ordinal)); 164 LanguageGroups = Languages 165 .GroupBy(language => language.GroupResourceID) 166 .Select(grp => new PowerAccentLanguageGroupModel(grp.ToList(), ResourceLoaderInstance.ResourceLoader.GetString(grp.Key))) 167 .ToArray(); 168 } 169 170 public bool IsEnabled 171 { 172 get => _isEnabled; 173 set 174 { 175 if (_enabledStateIsGPOConfigured) 176 { 177 // If it's GPO configured, shouldn't be able to change this state. 178 return; 179 } 180 181 if (_isEnabled != value) 182 { 183 _isEnabled = value; 184 185 GeneralSettingsConfig.Enabled.PowerAccent = value; 186 OnPropertyChanged(nameof(IsEnabled)); 187 OutGoingGeneralSettings outgoing = new OutGoingGeneralSettings(GeneralSettingsConfig); 188 SendConfigMSG(outgoing.ToString()); 189 } 190 } 191 } 192 193 public bool IsEnabledGpoConfigured 194 { 195 get => _enabledStateIsGPOConfigured; 196 } 197 198 public int ActivationKey 199 { 200 get 201 { 202 return (int)_powerAccentSettings.Properties.ActivationKey; 203 } 204 205 set 206 { 207 if (value != (int)_powerAccentSettings.Properties.ActivationKey) 208 { 209 _powerAccentSettings.Properties.ActivationKey = (PowerAccentActivationKey)value; 210 OnPropertyChanged(nameof(ActivationKey)); 211 RaisePropertyChanged(); 212 } 213 } 214 } 215 216 public bool DoNotActivateOnGameMode 217 { 218 get 219 { 220 return _powerAccentSettings.Properties.DoNotActivateOnGameMode; 221 } 222 223 set 224 { 225 if (value != _powerAccentSettings.Properties.DoNotActivateOnGameMode) 226 { 227 _powerAccentSettings.Properties.DoNotActivateOnGameMode = value; 228 OnPropertyChanged(nameof(DoNotActivateOnGameMode)); 229 RaisePropertyChanged(); 230 } 231 } 232 } 233 234 private int _inputTimeMs = PowerAccentSettings.DefaultInputTimeMs; 235 236 public int InputTimeMs 237 { 238 get 239 { 240 return _inputTimeMs; 241 } 242 243 set 244 { 245 if (value != _inputTimeMs) 246 { 247 _inputTimeMs = value; 248 _powerAccentSettings.Properties.InputTime.Value = value; 249 OnPropertyChanged(nameof(InputTimeMs)); 250 RaisePropertyChanged(); 251 } 252 } 253 } 254 255 private string _excludedApps; 256 257 public string ExcludedApps 258 { 259 get 260 { 261 return _excludedApps; 262 } 263 264 set 265 { 266 if (value != _excludedApps) 267 { 268 _excludedApps = value; 269 _powerAccentSettings.Properties.ExcludedApps.Value = value; 270 OnPropertyChanged(nameof(ExcludedApps)); 271 RaisePropertyChanged(); 272 } 273 } 274 } 275 276 private int _toolbarPositionIndex; 277 278 public int ToolbarPositionIndex 279 { 280 get 281 { 282 return _toolbarPositionIndex; 283 } 284 285 set 286 { 287 if (_toolbarPositionIndex != value) 288 { 289 _toolbarPositionIndex = value; 290 _powerAccentSettings.Properties.ToolbarPosition.Value = _toolbarOptions[value]; 291 RaisePropertyChanged(nameof(ToolbarPositionIndex)); 292 } 293 } 294 } 295 296 public bool AllSelected => _selectedLanguageOptions.Length == Languages.Count; 297 298 private PowerAccentLanguageModel[] _selectedLanguageOptions; 299 300 public PowerAccentLanguageModel[] SelectedLanguageOptions 301 { 302 get => _selectedLanguageOptions; 303 set 304 { 305 _selectedLanguageOptions = value; 306 _powerAccentSettings.Properties.SelectedLang.Value = string.Join(',', _selectedLanguageOptions.Select(l => l.LanguageCode)); 307 RaisePropertyChanged(nameof(SelectedLanguageOptions)); 308 } 309 } 310 311 public bool ShowUnicodeDescription 312 { 313 get 314 { 315 return _powerAccentSettings.Properties.ShowUnicodeDescription; 316 } 317 318 set 319 { 320 if (value != _powerAccentSettings.Properties.ShowUnicodeDescription) 321 { 322 _powerAccentSettings.Properties.ShowUnicodeDescription = value; 323 OnPropertyChanged(nameof(ShowUnicodeDescription)); 324 RaisePropertyChanged(); 325 } 326 } 327 } 328 329 public bool SortByUsageFrequency 330 { 331 get 332 { 333 return _powerAccentSettings.Properties.SortByUsageFrequency; 334 } 335 336 set 337 { 338 if (value != _powerAccentSettings.Properties.SortByUsageFrequency) 339 { 340 _powerAccentSettings.Properties.SortByUsageFrequency = value; 341 OnPropertyChanged(nameof(SortByUsageFrequency)); 342 RaisePropertyChanged(); 343 } 344 } 345 } 346 347 public bool StartSelectionFromTheLeft 348 { 349 get 350 { 351 return _powerAccentSettings.Properties.StartSelectionFromTheLeft; 352 } 353 354 set 355 { 356 if (value != _powerAccentSettings.Properties.StartSelectionFromTheLeft) 357 { 358 _powerAccentSettings.Properties.StartSelectionFromTheLeft = value; 359 OnPropertyChanged(nameof(StartSelectionFromTheLeft)); 360 RaisePropertyChanged(); 361 } 362 } 363 } 364 365 private void RaisePropertyChanged([CallerMemberName] string propertyName = null) 366 { 367 // Notify UI of property change 368 OnPropertyChanged(propertyName); 369 370 if (SendConfigMSG != null) 371 { 372 SndPowerAccentSettings snd = new SndPowerAccentSettings(_powerAccentSettings); 373 SndModuleSettings<SndPowerAccentSettings> ipcMessage = new SndModuleSettings<SndPowerAccentSettings>(snd); 374 SendConfigMSG(ipcMessage.ToJsonString()); 375 } 376 } 377 378 public void RefreshEnabledState() 379 { 380 InitializeEnabledValue(); 381 OnPropertyChanged(nameof(IsEnabled)); 382 } 383 384 private GpoRuleConfigured _enabledGpoRuleConfiguration; 385 private bool _enabledStateIsGPOConfigured; 386 private bool _isEnabled; 387 } 388 }