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, string currentTab)
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);
123 SelectedTab = currentTab;
126 private string _selectedTab="General";
127 public string SelectedTab
129 get { return _selectedTab; }
132 _selectedTab = value??"General";
133 NotifyOfPropertyChange(()=>SelectedTab);
134 NotifyOfPropertyChange(() => AccountTabSelected);
139 public bool AccountTabSelected
141 get { return _selectedTab == "AccountTab"; }
143 #region Preferences Properties
145 private bool _noProxy;
148 get { return _noProxy; }
152 NotifyOfPropertyChange(()=>NoProxy);
157 private bool _defaultProxy;
159 public bool DefaultProxy
161 get { return _defaultProxy; }
164 _defaultProxy = value;
165 NotifyOfPropertyChange(() => DefaultProxy);
170 private bool _manualProxy;
172 public bool ManualProxy
174 get { return _manualProxy; }
177 _manualProxy = value;
178 NotifyOfPropertyChange(() => ManualProxy);
184 public int StartupDelay
186 get { return (int) Settings.StartupDelay.TotalMinutes; }
190 throw new ArgumentOutOfRangeException("value","The Startup Delay must be greater or equal to 0");
191 Settings.StartupDelay = TimeSpan.FromMinutes(value);
192 NotifyOfPropertyChange(()=>StartupDelay);
198 public bool CanSelectiveSyncFolders
200 get { return CurrentAccount != null; }
203 public void SelectiveSyncFolders()
205 var monitor = Shell.Monitors[CurrentAccount.AccountName];
208 var model = new SelectiveSynchViewModel(monitor,_events,CurrentAccount);
209 if (_windowManager.ShowDialog(model) == true)
215 public async Task RefreshApiKey()
217 await Shell.TryAuthorize(CurrentAccount.AccountName, 3);
218 NotifyOfPropertyChange(()=>CurrentAccount);
221 public void SaveChanges()
227 public void RejectChanges()
233 public void ApplyChanges()
238 private void DoSave()
243 foreach (var account in Settings.Accounts)
245 Shell.MonitorAccount(account);
248 NotifyOfPropertyChange(()=>Settings);
251 /* public void ChangePithosFolder()
253 var browser = new FolderBrowserDialog();
254 browser.SelectedPath = Settings.PithosPath;
255 var result = browser.ShowDialog((IWin32Window)GetView());
256 if (result == DialogResult.OK)
258 var newPath = browser.SelectedPath;
259 var accountName = CurrentAccount.AccountName;
260 var monitor = Shell.Monitors[accountName];
263 Shell.Monitors.Remove(accountName);
265 Directory.Move(Settings.PithosPath, newPath);
266 Settings.PithosPath = newPath;
269 Shell.MonitorAccount(CurrentAccount);
271 NotifyOfPropertyChange(() => Settings);
278 public void AddAccount()
280 var wizard = new AddAccountViewModel();
281 if (_windowManager.ShowDialog(wizard) == true)
283 string selectedPath = wizard.AccountPath;
284 var initialRootPath = Path.Combine(selectedPath, "Okeanos");
285 var actualRootPath= initialRootPath;
287 while (Directory.Exists(actualRootPath) || File.Exists(actualRootPath))
289 actualRootPath = String.Format("{0} {1}", initialRootPath,attempt++);
292 var newAccount = new AccountSettings
294 AccountName = wizard.AccountName,
295 ServerUrl=wizard.CurrentServer,
297 RootPath = actualRootPath,
298 IsActive=wizard.IsAccountActive
300 Settings.Accounts.Add(newAccount);
301 (Accounts as IProducerConsumerCollection<AccountSettings>).TryAdd(newAccount);
302 CurrentAccount = newAccount;
303 NotifyOfPropertyChange(() => Accounts);
304 NotifyOfPropertyChange(() => Settings);
311 public async void AddPithosAccount()
313 var credentials=await PithosAccount.RetrieveCredentials(Settings.PithosLoginUrl);
314 var account = Settings.Accounts.FirstOrDefault(act => act.AccountName == credentials.UserName);
317 account=new AccountSettings{
318 AccountName=credentials.UserName,
319 ApiKey=credentials.Password
321 Settings.Accounts.Add(account);
322 (Accounts as IProducerConsumerCollection<AccountSettings>).TryAdd(account);
326 account.ApiKey=credentials.Password;
328 //SelectedAccountIndex= Settings.Accounts.IndexOf(account);
329 CurrentAccount = account;
330 NotifyOfPropertyChange(() => Accounts);
331 NotifyOfPropertyChange(()=>Settings);
334 public void RemoveAccount()
336 var accountName = CurrentAccount.AccountName;
337 Settings.Accounts.Remove(CurrentAccount);
339 Accounts.TryRemove(CurrentAccount);
342 CurrentAccount = null;
343 //Accounts = Settings.Accounts;
345 Shell.RemoveMonitor(accountName);
346 NotifyOfPropertyChange(() => Accounts);
347 NotifyOfPropertyChange(() => Settings);
349 //NotifyOfPropertyChange("Settings.Accounts");
352 public bool CanRemoveAccount
354 get { return (CurrentAccount != null); }
359 public bool ExtensionsActivated
361 get { return Settings.ExtensionsActivated; }
364 if (Settings.ExtensionsActivated == value)
367 Settings.ExtensionsActivated = value;
371 _extensionController.RegisterExtensions();
374 _extensionController.UnregisterExtensions();
377 NotifyOfPropertyChange(() => ExtensionsActivated);
384 /* private int _selectedAccountIndex;
385 public int SelectedAccountIndex
387 get { return _selectedAccountIndex; }
390 //var accountCount=Settings.Accounts.Count;
391 //if (accountCount == 0)
393 //if (0 <= value && value < accountCount)
394 // _selectedAccountIndex = value;
396 // _selectedAccountIndex = 0;
397 _selectedAccountIndex = value;
398 NotifyOfPropertyChange(() => CurrentAccount);
399 NotifyOfPropertyChange(() => CanRemoveAccount);
400 NotifyOfPropertyChange(()=>SelectedAccountIndex);
404 private AccountSettings _currentAccount;
405 private IWindowManager _windowManager;
406 private string _shortcutPath;
410 public AccountSettings CurrentAccount
412 get { return _currentAccount; }
415 _currentAccount = value;
416 NotifyOfPropertyChange(()=>CurrentAccount);
417 NotifyOfPropertyChange(() => CanRemoveAccount);
418 NotifyOfPropertyChange(() => CanSelectiveSyncFolders);
419 NotifyOfPropertyChange(() => CanMoveAccountFolder);
424 public AccountSettings CurrentAccount
427 if (0 <= SelectedAccountIndex && SelectedAccountIndex < Settings.Accounts.Count)
428 return Settings.Accounts[SelectedAccountIndex];
436 public bool CanMoveAccountFolder
438 get { return CurrentAccount != null; }
441 public void MoveAccountFolder()
444 using (var dlg = new FolderBrowserDialog())
446 var currentFolder = CurrentAccount.RootPath;
447 dlg.SelectedPath = currentFolder;
448 //Ask the user to select a folder
449 //Note: We need a parent window here, which we retrieve with GetView
450 var view = (Window)GetView();
451 if (DialogResult.OK != dlg.ShowDialog(new Wpf32Window(view)))
454 var newPath= dlg.SelectedPath;
455 //Find the account's monitor and stop it
456 PithosMonitor monitor;
457 if (Shell.Monitors.TryGetValue(CurrentAccount.AccountName, out monitor))
462 var oldPath = monitor.RootPath;
463 //The old directory may not exist eg. if we create an account for the first time
464 if (Directory.Exists(oldPath))
466 //If it does, do the move
468 //Now Create all of the directories
469 foreach (string dirPath in Directory.EnumerateDirectories(oldPath, "*",
470 SearchOption.AllDirectories))
471 Directory.CreateDirectory(dirPath.Replace(oldPath, newPath));
474 foreach (string newFilePath in Directory.EnumerateFiles(oldPath, "*.*",
475 SearchOption.AllDirectories))
476 File.Copy(newFilePath, newFilePath.Replace(oldPath, newPath));
478 Directory.Delete(oldPath, true);
480 //We also need to change the path of the existing file states
482 monitor.MoveFileStates(oldPath, newPath);
485 //Replace the old rootpath with the new
486 CurrentAccount.RootPath = newPath;
487 //TODO: This will save all settings changes. Too coarse grained, need to fix at a later date
489 //And start the monitor on the new RootPath
492 monitor.RootPath = newPath;
493 if (CurrentAccount.IsActive)
497 Shell.MonitorAccount(CurrentAccount);
498 //Finally, notify that the Settings, CurrentAccount have changed
499 NotifyOfPropertyChange(() => CurrentAccount);
500 NotifyOfPropertyChange(() => Settings);