1 // -----------------------------------------------------------------------
2 // <copyright file="PreferencesViewModel.cs" company="GRNet">
3 // Copyright 2011 GRNET S.A. All rights reserved.
5 // Redistribution and use in source and binary forms, with or
6 // without modification, are permitted provided that the following
9 // 1. Redistributions of source code must retain the above
10 // copyright notice, this list of conditions and the following
13 // 2. Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following
15 // disclaimer in the documentation and/or other materials
16 // provided with the distribution.
18 // THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
19 // OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
22 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
25 // USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 // AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 // POSSIBILITY OF SUCH DAMAGE.
31 // The views and conclusions contained in the software and
32 // documentation are those of the authors and should not be
33 // interpreted as representing official policies, either expressed
34 // or implied, of GRNET S.A.
37 // -----------------------------------------------------------------------
39 using System.Collections.Concurrent;
40 using System.ComponentModel.Composition;
42 using System.Reflection;
44 using System.Windows.Forms;
46 using IWshRuntimeLibrary;
47 using Pithos.Client.WPF.Configuration;
48 using Pithos.Client.WPF.Preferences;
49 using Pithos.Client.WPF.SelectiveSynch;
51 using Pithos.Interfaces;
52 using File = System.IO.File;
53 using Screen = Caliburn.Micro.Screen;
55 namespace Pithos.Client.WPF
59 using System.Threading.Tasks;
62 /// TODO: Update summary.
65 public class PreferencesViewModel : Screen
67 private IEventAggregator _events;
70 private PithosSettings _settings;
71 public PithosSettings Settings
73 get { return _settings; }
77 NotifyOfPropertyChange(()=>Settings);
81 private ObservableConcurrentCollection<AccountSettings> _accounts;
82 public ObservableConcurrentCollection<AccountSettings> Accounts
84 get { return _accounts; }
88 NotifyOfPropertyChange(()=>Accounts);
92 public bool StartOnSystemStartup { get; set; }
94 private static void CreateShortcut(string shortcutPath)
96 var wshShell = new WshShellClass();
97 var shortcut = (IWshRuntimeLibrary.IWshShortcut) wshShell.CreateShortcut(
100 var exePath = Assembly.GetExecutingAssembly().Location;
101 shortcut.TargetPath = exePath;
102 shortcut.WorkingDirectory = Path.GetDirectoryName(exePath);
103 shortcut.Description = "Pithos";
107 public ShellViewModel Shell { get; set; }
108 //ShellExtensionController _extensionController=new ShellExtensionController();
110 public PreferencesViewModel(IWindowManager windowManager, IEventAggregator events, ShellViewModel shell, PithosSettings settings)
112 _windowManager = windowManager;
115 DisplayName = "Pithos Preferences";
119 Accounts = new ObservableConcurrentCollection<AccountSettings>();
120 if (settings.Accounts == null)
122 settings.Accounts=new AccountsCollection();
125 Accounts.AddFromEnumerable(settings.Accounts);
127 var startupPath = Environment.GetFolderPath(Environment.SpecialFolder.Startup);
128 _shortcutPath = Path.Combine(startupPath, "Pithos.lnk");
131 StartOnSystemStartup = File.Exists(_shortcutPath);
136 #region Preferences Properties
138 private bool _noProxy;
141 get { return _noProxy; }
145 NotifyOfPropertyChange(()=>NoProxy);
150 private bool _defaultProxy;
152 public bool DefaultProxy
154 get { return _defaultProxy; }
157 _defaultProxy = value;
158 NotifyOfPropertyChange(() => DefaultProxy);
163 private bool _manualProxy;
165 public bool ManualProxy
167 get { return _manualProxy; }
170 _manualProxy = value;
171 NotifyOfPropertyChange(() => ManualProxy);
179 public bool CanSelectiveSyncFolders
181 get { return CurrentAccount != null; }
184 public void SelectiveSyncFolders()
186 var monitor = Shell.Monitors[CurrentAccount.AccountName];
187 var folders=monitor.GetRootFolders();
189 var model = new SelectiveSynchViewModel(folders,_events,CurrentAccount);
190 if (_windowManager.ShowDialog(model) == true)
196 public void SaveChanges()
202 public void RejectChanges()
208 public void ApplyChanges()
213 private void DoSave()
219 foreach (var account in Settings.Accounts)
221 Shell.MonitorAccount(account);
224 NotifyOfPropertyChange(()=>Settings);
227 private void SetStartupMode()
229 if (StartOnSystemStartup && !File.Exists(_shortcutPath))
231 CreateShortcut(_shortcutPath);
233 else if (!StartOnSystemStartup && File.Exists(_shortcutPath))
235 if (File.Exists(_shortcutPath))
236 File.Delete(_shortcutPath);
240 /* public void ChangePithosFolder()
242 var browser = new FolderBrowserDialog();
243 browser.SelectedPath = Settings.PithosPath;
244 var result = browser.ShowDialog((IWin32Window)GetView());
245 if (result == DialogResult.OK)
247 var newPath = browser.SelectedPath;
248 var accountName = CurrentAccount.AccountName;
249 var monitor = Shell.Monitors[accountName];
252 Shell.Monitors.Remove(accountName);
254 Directory.Move(Settings.PithosPath, newPath);
255 Settings.PithosPath = newPath;
258 Shell.MonitorAccount(CurrentAccount);
260 NotifyOfPropertyChange(() => Settings);
264 public void AddAccount()
266 var wizard = new AddAccountViewModel();
267 if (_windowManager.ShowDialog(wizard) == true)
269 var newAccount = new AccountSettings
271 AccountName = wizard.AccountName,
272 ServerUrl=wizard.CurrentServer,
274 RootPath=wizard.AccountPath,
275 IsActive=wizard.IsAccountActive
277 Settings.Accounts.Add(newAccount);
278 (Accounts as IProducerConsumerCollection<AccountSettings>).TryAdd(newAccount);
279 CurrentAccount = newAccount;
280 NotifyOfPropertyChange(() => Accounts);
281 NotifyOfPropertyChange(() => Settings);
288 public async void AddPithosAccount()
290 var credentials=await PithosAccount.RetrieveCredentials(Settings.PithosLoginUrl);
291 var account = Settings.Accounts.FirstOrDefault(act => act.AccountName == credentials.UserName);
294 account=new AccountSettings{
295 AccountName=credentials.UserName,
296 ApiKey=credentials.Password
298 Settings.Accounts.Add(account);
299 (Accounts as IProducerConsumerCollection<AccountSettings>).TryAdd(account);
303 account.ApiKey=credentials.Password;
305 //SelectedAccountIndex= Settings.Accounts.IndexOf(account);
306 CurrentAccount = account;
307 NotifyOfPropertyChange(() => Accounts);
308 NotifyOfPropertyChange(()=>Settings);
311 public void RemoveAccount()
313 var accountName = CurrentAccount.AccountName;
314 Settings.Accounts.Remove(CurrentAccount);
316 Accounts.TryRemove(CurrentAccount);
319 CurrentAccount = null;
320 //Accounts = Settings.Accounts;
322 Shell.RemoveMonitor(accountName);
323 NotifyOfPropertyChange(() => Accounts);
324 NotifyOfPropertyChange(() => Settings);
326 //NotifyOfPropertyChange("Settings.Accounts");
329 public bool CanRemoveAccount
331 get { return (CurrentAccount != null); }
336 public bool ExtensionsActivated
338 get { return Settings.ExtensionsActivated; }
341 if (Settings.ExtensionsActivated == value)
344 Settings.ExtensionsActivated = value;
348 _extensionController.RegisterExtensions();
351 _extensionController.UnregisterExtensions();
354 NotifyOfPropertyChange(() => ExtensionsActivated);
361 /* private int _selectedAccountIndex;
362 public int SelectedAccountIndex
364 get { return _selectedAccountIndex; }
367 //var accountCount=Settings.Accounts.Count;
368 //if (accountCount == 0)
370 //if (0 <= value && value < accountCount)
371 // _selectedAccountIndex = value;
373 // _selectedAccountIndex = 0;
374 _selectedAccountIndex = value;
375 NotifyOfPropertyChange(() => CurrentAccount);
376 NotifyOfPropertyChange(() => CanRemoveAccount);
377 NotifyOfPropertyChange(()=>SelectedAccountIndex);
381 private AccountSettings _currentAccount;
382 private IWindowManager _windowManager;
383 private string _shortcutPath;
387 public AccountSettings CurrentAccount
389 get { return _currentAccount; }
392 _currentAccount = value;
393 NotifyOfPropertyChange(()=>CurrentAccount);
394 NotifyOfPropertyChange(() => CanRemoveAccount);
395 NotifyOfPropertyChange(() => CanSelectiveSyncFolders);
396 NotifyOfPropertyChange(() => CanMoveAccountFolder);
401 public AccountSettings CurrentAccount
404 if (0 <= SelectedAccountIndex && SelectedAccountIndex < Settings.Accounts.Count)
405 return Settings.Accounts[SelectedAccountIndex];
413 public bool CanMoveAccountFolder
415 get { return CurrentAccount != null; }
418 public void MoveAccountFolder()
421 using (var dlg = new FolderBrowserDialog())
423 var currentFolder = CurrentAccount.RootPath;
424 dlg.SelectedPath = currentFolder;
425 //Ask the user to select a folder
426 //Note: We need a parent window here, which we retrieve with GetView
427 var view = (Window)GetView();
428 if (DialogResult.OK != dlg.ShowDialog(new Wpf32Window(view)))
431 var newPath= dlg.SelectedPath;
432 //Find the account's monitor and stop it
433 PithosMonitor monitor;
434 if (Shell.Monitors.TryGetValue(CurrentAccount.AccountName, out monitor))
439 var oldPath = monitor.RootPath;
440 //The old directory may not exist eg. if we create an account for the first time
441 if (Directory.Exists(oldPath))
443 //If it does, do the move
445 //Now Create all of the directories
446 foreach (string dirPath in Directory.EnumerateDirectories(oldPath, "*",
447 SearchOption.AllDirectories))
448 Directory.CreateDirectory(dirPath.Replace(oldPath, newPath));
451 foreach (string newFilePath in Directory.EnumerateFiles(oldPath, "*.*",
452 SearchOption.AllDirectories))
453 File.Copy(newFilePath, newFilePath.Replace(oldPath, newPath));
455 Directory.Delete(oldPath, true);
457 //We also need to change the path of the existing file states
459 monitor.MoveFileStates(oldPath, newPath);
462 //Replace the old rootpath with the new
463 CurrentAccount.RootPath = newPath;
464 //TODO: This will save all settings changes. Too coarse grained, need to fix at a later date
466 //And start the monitor on the new RootPath
469 monitor.RootPath = newPath;
470 if (CurrentAccount.IsActive)
474 Shell.MonitorAccount(CurrentAccount);
475 //Finally, notify that the Settings, CurrentAccount have changed
476 NotifyOfPropertyChange(() => CurrentAccount);
477 NotifyOfPropertyChange(() => Settings);