PageRenderTime 29ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/Main/Source/Schedulr/ViewModels/ConfigurationEditorViewModel.cs

#
C# | 247 lines | 187 code | 38 blank | 22 comment | 16 complexity | 47cb415c00cf50f0e59d44110b6e21b5 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.ObjectModel;
  4. using System.Diagnostics;
  5. using System.Globalization;
  6. using System.IO;
  7. using System.Linq;
  8. using System.Windows;
  9. using System.Windows.Input;
  10. using JelleDruyts.Windows;
  11. using JelleDruyts.Windows.ObjectModel;
  12. using Microsoft.Win32;
  13. using Schedulr.Extensibility;
  14. using Schedulr.Infrastructure;
  15. using Schedulr.Messages;
  16. using Schedulr.Models;
  17. using Schedulr.Providers;
  18. using Schedulr.Views.Dialogs;
  19. namespace Schedulr.ViewModels
  20. {
  21. public class ConfigurationEditorViewModel : ViewModel
  22. {
  23. #region Properties
  24. /// <summary>
  25. /// Gets the commands that are available for the selected account.
  26. /// </summary>
  27. public IEnumerable<ICommand> SelectedAccountCommands { get; private set; }
  28. /// <summary>
  29. /// Gets the action commands that are available.
  30. /// </summary>
  31. public IEnumerable<ICommand> ActionsCommands { get; private set; }
  32. /// <summary>
  33. /// Gets the dialog commands that are available.
  34. /// </summary>
  35. public IEnumerable<ICommand> DialogCommands { get; private set; }
  36. /// <summary>
  37. /// Gets the input bindings for the commands.
  38. /// </summary>
  39. public IEnumerable<InputBinding> InputBindings { get; private set; }
  40. #endregion
  41. #region Observable Properties
  42. /// <summary>
  43. /// Gets or sets the accounts.
  44. /// </summary>
  45. public ObservableCollection<Account> Accounts
  46. {
  47. get { return this.GetValue(AccountsProperty); }
  48. set { this.SetValue(AccountsProperty, value); }
  49. }
  50. public static ObservableProperty<ObservableCollection<Account>> AccountsProperty = new ObservableProperty<ObservableCollection<Account>, ConfigurationEditorViewModel>(o => o.Accounts);
  51. /// <summary>
  52. /// Gets or sets the selected account.
  53. /// </summary>
  54. public Account SelectedAccount
  55. {
  56. get { return this.GetValue(SelectedAccountProperty); }
  57. set { this.SetValue(SelectedAccountProperty, value); }
  58. }
  59. public static ObservableProperty<Account> SelectedAccountProperty = new ObservableProperty<Account, ConfigurationEditorViewModel>(o => o.SelectedAccount);
  60. #endregion
  61. #region Constructors
  62. /// <summary>
  63. /// Initializes a new instance of the <see cref="ConfigurationEditorViewModel"/> class.
  64. /// </summary>
  65. public ConfigurationEditorViewModel()
  66. {
  67. this.SelectedAccountCommands = new ICommand[]
  68. {
  69. new RelayCommand(RemoveAccount, CanRemoveAccount, "_Remove", "Removes the selected account [DEL]", new KeyGesture(Key.Delete)),
  70. new RelayCommand(SetDefaultAccount, CanSetDefaultAccount, "Set _Default", "Makes the selected account show by default when starting the application [ENTER]", new KeyGesture(Key.Enter)),
  71. new RelayCommand(ImportPictures, CanImportPictures, "_Import Pictures", "Imports the queued pictures from the configuration file of a previous version of the application [CTRL-M]", new KeyGesture(Key.M, ModifierKeys.Control))
  72. };
  73. this.ActionsCommands = new ICommand[]
  74. {
  75. new RelayCommand(AddAccount, CanAddAccount, "_Add Account...", "Adds a new account [INS]", new KeyGesture(Key.Insert)),
  76. App.Instance.SaveChangesCommand,
  77. App.Instance.UndoChangesCommand,
  78. App.Instance.ExportConfigurationCommand,
  79. App.Instance.ImportConfigurationCommand,
  80. App.Instance.OpenLogFileCommand
  81. };
  82. this.DialogCommands = new ICommand[]
  83. {
  84. new RelayCommand(Close, CanClose, "_Close", "Closes this dialog [ESC]", new KeyGesture(Key.Escape))
  85. };
  86. this.InputBindings = this.SelectedAccountCommands.Union(this.ActionsCommands).Union(this.DialogCommands).OfType<RelayCommand>().SelectMany(r => r.InputGestures.Select(g => new InputBinding(r, g)));
  87. Messenger.Register<ConfigurationChangedMessage>(OnConfigurationChanged);
  88. }
  89. #endregion
  90. #region Message Handlers
  91. private void OnConfigurationChanged(ConfigurationChangedMessage message)
  92. {
  93. Logger.Log("ConfigurationWindowViewModel - Setting accounts", TraceEventType.Verbose);
  94. this.Accounts = message.Configuration.Accounts;
  95. }
  96. #endregion
  97. #region Selected Account Commands
  98. private bool CanImportPictures(object parameter)
  99. {
  100. return (this.SelectedAccount != null);
  101. }
  102. private void ImportPictures(object parameter)
  103. {
  104. var openFileDialog = new OpenFileDialog();
  105. openFileDialog.Title = "Please select the configuration file from a previous version of the application from which to import the queued pictures";
  106. openFileDialog.Filter = "XML files|*.xml|All files|*.*";
  107. if (openFileDialog.ShowDialog() == true)
  108. {
  109. try
  110. {
  111. var fileName = openFileDialog.FileName;
  112. var count = SchedulrConfigurationProvider.ImportFromLegacyConfiguration(this.SelectedAccount, fileName);
  113. Messenger.Send<StatusMessage>(new StatusMessage(string.Format(CultureInfo.CurrentCulture, "{0} queued pictures imported from \"{1}\"", count, Path.GetFileName(fileName))));
  114. }
  115. catch (Exception)
  116. {
  117. MessageBox.Show(App.Current.MainWindow, string.Format(CultureInfo.CurrentCulture, "The queued pictures from the specified configuration file could not be imported.{0}{0}Note that this is only intended to import queued pictures from a previous version of the application. Export the configuration from the previous version and import it back into the selected account here.{0}{0}Please see the log file for more details.", Environment.NewLine), "Error importing pictures", MessageBoxButton.OK, MessageBoxImage.Warning);
  118. }
  119. }
  120. }
  121. private bool CanSetDefaultAccount(object parameter)
  122. {
  123. return (this.SelectedAccount != null && !this.SelectedAccount.IsDefaultAccount);
  124. }
  125. private void SetDefaultAccount(object parameter)
  126. {
  127. foreach (var account in this.Accounts)
  128. {
  129. account.IsDefaultAccount = false;
  130. }
  131. this.SelectedAccount.IsDefaultAccount = true;
  132. }
  133. private bool CanRemoveAccount(object parameter)
  134. {
  135. return (this.SelectedAccount != null);
  136. }
  137. private void RemoveAccount(object parameter)
  138. {
  139. var account = this.SelectedAccount;
  140. PluginManager.OnGeneralAccountEvent(new GeneralAccountEventArgs(GeneralAccountEventType.Removing, App.Info, account));
  141. Messenger.Send<AccountActionMessage>(new AccountActionMessage(account, ListAction.Removed));
  142. PluginManager.OnGeneralAccountEvent(new GeneralAccountEventArgs(GeneralAccountEventType.Removed, App.Info, account));
  143. }
  144. #endregion
  145. #region Actions Commands
  146. private bool CanAddAccount(object parameter)
  147. {
  148. return FlickrClient.IsOnline();
  149. }
  150. private void AddAccount(object parameter)
  151. {
  152. PluginManager.OnGeneralAccountEvent(new GeneralAccountEventArgs(GeneralAccountEventType.Adding, App.Info, null));
  153. var addingAccountTask = new ApplicationTask("Adding account");
  154. Messenger.Send(new TaskStatusMessage(addingAccountTask));
  155. string accountName = null;
  156. try
  157. {
  158. var flickr = new FlickrClient();
  159. var authenticationUrl = flickr.BeginAuthentication();
  160. var authenticationDialog = new AuthenticationDialog(authenticationUrl);
  161. var result = authenticationDialog.ShowDialog();
  162. if (result.HasValue && result.Value)
  163. {
  164. var token = flickr.EndAuthentication(authenticationDialog.Verifier);
  165. var userInfo = flickr.GetUserInfo();
  166. var isDefaultAccount = (this.Accounts != null && this.Accounts.Count == 0);
  167. // Check if an account with the same Id or Name already exists.
  168. var accountExists = this.Accounts.Any(a => string.Equals(a.Id, userInfo.UserId, StringComparison.OrdinalIgnoreCase) || string.Equals(a.Name, userInfo.UserName, StringComparison.OrdinalIgnoreCase));
  169. if (accountExists)
  170. {
  171. var message = "This account is already configured; you cannot add the same account twice.";
  172. addingAccountTask.Status = message;
  173. MessageBox.Show(message, "Duplicate Account", MessageBoxButton.OK, MessageBoxImage.Information);
  174. }
  175. else
  176. {
  177. var account = new Account { AuthenticationToken = token.Token, AuthenticationTokenSecret = token.TokenSecret, IsDefaultAccount = isDefaultAccount, Id = userInfo.UserId, Name = userInfo.UserName, UserInfo = userInfo };
  178. SchedulrConfigurationProvider.AddPluginToRetrieveMetadata(account);
  179. accountName = account.Name;
  180. Messenger.Send<AccountActionMessage>(new AccountActionMessage(account, ListAction.Added));
  181. PluginManager.OnGeneralAccountEvent(new GeneralAccountEventArgs(GeneralAccountEventType.Added, App.Info, account));
  182. }
  183. }
  184. }
  185. catch (Exception exc)
  186. {
  187. var errorMessage = "An error occurred while adding the account";
  188. Logger.Log(errorMessage, exc);
  189. addingAccountTask.SetError(errorMessage, exc);
  190. }
  191. finally
  192. {
  193. var message = (accountName == null ? "No account was added" : string.Format(CultureInfo.CurrentCulture, "\"{0}\" added", accountName));
  194. addingAccountTask.SetComplete(message);
  195. }
  196. }
  197. #endregion
  198. #region Dialog Commands
  199. private bool CanClose(object parameter)
  200. {
  201. return (this.Accounts != null && this.Accounts.Count > 0);
  202. }
  203. private void Close(object parameter)
  204. {
  205. Messenger.Send<DialogCloseRequestedMessage>(new DialogCloseRequestedMessage(Dialog.ConfigurationEditor));
  206. }
  207. #endregion
  208. }
  209. }