2 /* -----------------------------------------------------------------------
3 * <copyright file="PreferencesViewModel.cs" company="GRNet">
5 * Copyright 2011-2012 GRNET S.A. All rights reserved.
7 * Redistribution and use in source and binary forms, with or
8 * without modification, are permitted provided that the following
11 * 1. Redistributions of source code must retain the above
12 * copyright notice, this list of conditions and the following
15 * 2. Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer in the documentation and/or other materials
18 * provided with the distribution.
21 * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
22 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
34 * The views and conclusions contained in the software and
35 * documentation are those of the authors and should not be
36 * interpreted as representing official policies, either expressed
37 * or implied, of GRNET S.A.
39 * -----------------------------------------------------------------------
44 // -----------------------------------------------------------------------
46 using System.Collections.Concurrent;
47 using System.ComponentModel.Composition;
50 using System.Threading.Tasks;
52 using System.Windows.Forms;
54 using Pithos.Client.WPF.Configuration;
55 using Pithos.Client.WPF.SelectiveSynch;
57 using Pithos.Interfaces;
60 using Screen = Caliburn.Micro.Screen;
62 namespace Pithos.Client.WPF.Preferences
65 /// TODO: Update summary.
68 public class PreferencesViewModel : Screen
70 private IEventAggregator _events;
73 private PithosSettings _settings;
74 public PithosSettings Settings
76 get { return _settings; }
80 NotifyOfPropertyChange(()=>Settings);
84 private ObservableConcurrentCollection<AccountSettings> _accounts;
85 public ObservableConcurrentCollection<AccountSettings> Accounts
87 get { return _accounts; }
91 NotifyOfPropertyChange(()=>Accounts);
95 public bool StartOnSystemStartup { get; set; }
97 public ShellViewModel Shell { get; set; }
98 //ShellExtensionController _extensionController=new ShellExtensionController();
100 public PreferencesViewModel(IWindowManager windowManager, IEventAggregator events, ShellViewModel shell, PithosSettings settings)
102 _windowManager = windowManager;
105 DisplayName = "Pithos Preferences";
109 Accounts = new ObservableConcurrentCollection<AccountSettings>();
110 if (settings.Accounts == null)
112 settings.Accounts=new AccountsCollection();
115 Accounts.AddFromEnumerable(settings.Accounts);
117 var startupPath = Environment.GetFolderPath(Environment.SpecialFolder.Startup);
118 _shortcutPath = Path.Combine(startupPath, "Pithos.lnk");
121 StartOnSystemStartup = File.Exists(_shortcutPath);
126 #region Preferences Properties
128 private bool _noProxy;
131 get { return _noProxy; }
135 NotifyOfPropertyChange(()=>NoProxy);
140 private bool _defaultProxy;
142 public bool DefaultProxy
144 get { return _defaultProxy; }
147 _defaultProxy = value;
148 NotifyOfPropertyChange(() => DefaultProxy);
153 private bool _manualProxy;
155 public bool ManualProxy
157 get { return _manualProxy; }
160 _manualProxy = value;
161 NotifyOfPropertyChange(() => ManualProxy);
167 public int StartupDelay
169 get { return (int) Settings.StartupDelay.TotalMinutes; }
173 throw new ArgumentOutOfRangeException("value","The Startup Delay must be greater or equal to 0");
174 Settings.StartupDelay = TimeSpan.FromMinutes(value);
175 NotifyOfPropertyChange(()=>StartupDelay);
181 public bool CanSelectiveSyncFolders
183 get { return CurrentAccount != null; }
186 public void SelectiveSyncFolders()
188 var monitor = Shell.Monitors[CurrentAccount.AccountName];
191 var model = new SelectiveSynchViewModel(monitor,_events,CurrentAccount);
192 if (_windowManager.ShowDialog(model) == true)
198 public async Task RefreshApiKey()
200 await Shell.TryAuthorize(CurrentAccount.AccountName, 3);
201 NotifyOfPropertyChange(()=>CurrentAccount);
204 public void SaveChanges()
210 public void RejectChanges()
216 public void ApplyChanges()
221 private void DoSave()
226 foreach (var account in Settings.Accounts)
228 Shell.MonitorAccount(account);
231 NotifyOfPropertyChange(()=>Settings);
234 /* public void ChangePithosFolder()
236 var browser = new FolderBrowserDialog();
237 browser.SelectedPath = Settings.PithosPath;
238 var result = browser.ShowDialog((IWin32Window)GetView());
239 if (result == DialogResult.OK)
241 var newPath = browser.SelectedPath;
242 var accountName = CurrentAccount.AccountName;
243 var monitor = Shell.Monitors[accountName];
246 Shell.Monitors.Remove(accountName);
248 Directory.Move(Settings.PithosPath, newPath);
249 Settings.PithosPath = newPath;
252 Shell.MonitorAccount(CurrentAccount);
254 NotifyOfPropertyChange(() => Settings);
261 public void AddAccount()
263 var wizard = new AddAccountViewModel();
264 if (_windowManager.ShowDialog(wizard) == true)
266 string selectedPath = wizard.AccountPath;
267 var initialRootPath = Path.Combine(selectedPath, "Okeanos");
268 var actualRootPath= initialRootPath;
270 while (Directory.Exists(actualRootPath) || File.Exists(actualRootPath))
272 actualRootPath = String.Format("{0} {1}", initialRootPath,attempt++);
275 var newAccount = new AccountSettings
277 AccountName = wizard.AccountName,
278 ServerUrl=wizard.CurrentServer,
280 RootPath = actualRootPath,
281 IsActive=wizard.IsAccountActive
283 Settings.Accounts.Add(newAccount);
284 (Accounts as IProducerConsumerCollection<AccountSettings>).TryAdd(newAccount);
285 CurrentAccount = newAccount;
286 NotifyOfPropertyChange(() => Accounts);
287 NotifyOfPropertyChange(() => Settings);
294 public async void AddPithosAccount()
296 var credentials=await PithosAccount.RetrieveCredentials(Settings.PithosLoginUrl);
297 var account = Settings.Accounts.FirstOrDefault(act => act.AccountName == credentials.UserName);
300 account=new AccountSettings{
301 AccountName=credentials.UserName,
302 ApiKey=credentials.Password
304 Settings.Accounts.Add(account);
305 (Accounts as IProducerConsumerCollection<AccountSettings>).TryAdd(account);
309 account.ApiKey=credentials.Password;
311 //SelectedAccountIndex= Settings.Accounts.IndexOf(account);
312 CurrentAccount = account;
313 NotifyOfPropertyChange(() => Accounts);
314 NotifyOfPropertyChange(()=>Settings);
317 public void RemoveAccount()
319 var accountName = CurrentAccount.AccountName;
320 Settings.Accounts.Remove(CurrentAccount);
322 Accounts.TryRemove(CurrentAccount);
325 CurrentAccount = null;
326 //Accounts = Settings.Accounts;
328 Shell.RemoveMonitor(accountName);
329 NotifyOfPropertyChange(() => Accounts);
330 NotifyOfPropertyChange(() => Settings);
332 //NotifyOfPropertyChange("Settings.Accounts");
335 public bool CanRemoveAccount
337 get { return (CurrentAccount != null); }
342 public bool ExtensionsActivated
344 get { return Settings.ExtensionsActivated; }
347 if (Settings.ExtensionsActivated == value)
350 Settings.ExtensionsActivated = value;
354 _extensionController.RegisterExtensions();
357 _extensionController.UnregisterExtensions();
360 NotifyOfPropertyChange(() => ExtensionsActivated);
367 /* private int _selectedAccountIndex;
368 public int SelectedAccountIndex
370 get { return _selectedAccountIndex; }
373 //var accountCount=Settings.Accounts.Count;
374 //if (accountCount == 0)
376 //if (0 <= value && value < accountCount)
377 // _selectedAccountIndex = value;
379 // _selectedAccountIndex = 0;
380 _selectedAccountIndex = value;
381 NotifyOfPropertyChange(() => CurrentAccount);
382 NotifyOfPropertyChange(() => CanRemoveAccount);
383 NotifyOfPropertyChange(()=>SelectedAccountIndex);
387 private AccountSettings _currentAccount;
388 private IWindowManager _windowManager;
389 private string _shortcutPath;
393 public AccountSettings CurrentAccount
395 get { return _currentAccount; }
398 _currentAccount = value;
399 NotifyOfPropertyChange(()=>CurrentAccount);
400 NotifyOfPropertyChange(() => CanRemoveAccount);
401 NotifyOfPropertyChange(() => CanSelectiveSyncFolders);
402 NotifyOfPropertyChange(() => CanMoveAccountFolder);
407 public AccountSettings CurrentAccount
410 if (0 <= SelectedAccountIndex && SelectedAccountIndex < Settings.Accounts.Count)
411 return Settings.Accounts[SelectedAccountIndex];
419 public bool CanMoveAccountFolder
421 get { return CurrentAccount != null; }
424 public void MoveAccountFolder()
427 using (var dlg = new FolderBrowserDialog())
429 var currentFolder = CurrentAccount.RootPath;
430 dlg.SelectedPath = currentFolder;
431 //Ask the user to select a folder
432 //Note: We need a parent window here, which we retrieve with GetView
433 var view = (Window)GetView();
434 if (DialogResult.OK != dlg.ShowDialog(new Wpf32Window(view)))
437 var newPath= dlg.SelectedPath;
438 //Find the account's monitor and stop it
439 PithosMonitor monitor;
440 if (Shell.Monitors.TryGetValue(CurrentAccount.AccountName, out monitor))
445 var oldPath = monitor.RootPath;
446 //The old directory may not exist eg. if we create an account for the first time
447 if (Directory.Exists(oldPath))
449 //If it does, do the move
451 //Now Create all of the directories
452 foreach (string dirPath in Directory.EnumerateDirectories(oldPath, "*",
453 SearchOption.AllDirectories))
454 Directory.CreateDirectory(dirPath.Replace(oldPath, newPath));
457 foreach (string newFilePath in Directory.EnumerateFiles(oldPath, "*.*",
458 SearchOption.AllDirectories))
459 File.Copy(newFilePath, newFilePath.Replace(oldPath, newPath));
461 Directory.Delete(oldPath, true);
463 //We also need to change the path of the existing file states
465 monitor.MoveFileStates(oldPath, newPath);
468 //Replace the old rootpath with the new
469 CurrentAccount.RootPath = newPath;
470 //TODO: This will save all settings changes. Too coarse grained, need to fix at a later date
472 //And start the monitor on the new RootPath
475 monitor.RootPath = newPath;
476 if (CurrentAccount.IsActive)
480 Shell.MonitorAccount(CurrentAccount);
481 //Finally, notify that the Settings, CurrentAccount have changed
482 NotifyOfPropertyChange(() => CurrentAccount);
483 NotifyOfPropertyChange(() => Settings);