/ src / settings-ui / Settings.UI / ViewModels / PowerAccentViewModel.cs
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  }