Statistics
| Branch: | Revision:

root / trunk / Pithos.Client.WPF / Preferences / PreferencesViewModel.cs @ c945b450

History | View | Annotate | Download (25.6 kB)

1
#region
2
/* -----------------------------------------------------------------------
3
 * <copyright file="PreferencesViewModel.cs" company="GRNet">
4
 * 
5
 * Copyright 2011-2012 GRNET S.A. All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or
8
 * without modification, are permitted provided that the following
9
 * conditions are met:
10
 *
11
 *   1. Redistributions of source code must retain the above
12
 *      copyright notice, this list of conditions and the following
13
 *      disclaimer.
14
 *
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.
19
 *
20
 *
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.
33
 *
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.
38
 * </copyright>
39
 * -----------------------------------------------------------------------
40
 */
41
#endregion
42

    
43

    
44
using System.Collections.Concurrent;
45
using System.Collections.Generic;
46
using System.Collections.Specialized;
47
using System.ComponentModel.Composition;
48
using System.Diagnostics;
49
using System.IO;
50
using System.Net;
51
using System.Reflection;
52
using System.Threading.Tasks;
53
using System.Windows;
54
using System.Windows.Forms;
55
using Caliburn.Micro;
56
using Pithos.Client.WPF.Configuration;
57
using Pithos.Client.WPF.Properties;
58
using Pithos.Client.WPF.SelectiveSynch;
59
using Pithos.Client.WPF.Utils;
60
using Pithos.Core;
61
using Pithos.Core.Agents;
62
using Pithos.Interfaces;
63
using System;
64
using System.Linq;
65
using Pithos.Network;
66
using MessageBox = System.Windows.MessageBox;
67
using Screen = Caliburn.Micro.Screen;
68

    
69
namespace Pithos.Client.WPF.Preferences
70
{
71
    /// <summary>
72
    /// The preferences screen displays user and account settings and updates the PithosMonitor
73
    /// classes when account settings change.
74
    /// </summary>
75
    /// <remarks>
76
    /// The class is a single ViewModel for all Preferences tabs. It can be broken in separate
77
    /// ViewModels, one for each tab.
78
    /// </remarks>
79
    [Export, PartCreationPolicy(CreationPolicy.Shared)]
80
    public class PreferencesViewModel : Screen
81
    {
82
        private readonly IEventAggregator _events;
83

    
84
        //Logging in the Pithos client is provided by log4net
85
        private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
86

    
87
        private PithosSettings _settings;
88
        public PithosSettings Settings
89
        {
90
            get { return _settings; }
91
            set
92
            {
93
                _settings = value;
94
                NotifyOfPropertyChange(()=>Settings);
95
            }
96
        }
97

    
98
        private ObservableConcurrentCollection<AccountViewModel> _accounts;
99
        public ObservableConcurrentCollection<AccountViewModel> Accounts
100
        {
101
            get { return _accounts; }
102
            set 
103
            { 
104
                _accounts = value;
105
                NotifyOfPropertyChange(()=>Accounts);
106
            }
107
        }
108
        
109
        public bool StartOnSystemStartup { get; set; }
110

    
111
        public ShellViewModel Shell { get;  set; }
112
        //ShellExtensionController _extensionController=new ShellExtensionController();
113

    
114
        public PreferencesViewModel(IWindowManager windowManager, IEventAggregator events, ShellViewModel shell, PithosSettings settings, string currentTab)
115
        {
116
            // ReSharper disable DoNotCallOverridableMethodsInConstructor
117
            //Caliburn.Micro uses DisplayName for the view's title
118
            DisplayName = "Pithos+ Preferences";
119
            // ReSharper restore DoNotCallOverridableMethodsInConstructor
120

    
121
            _windowManager = windowManager;
122
            _events = events;
123

    
124
            Shell = shell;
125
            
126
            Settings=settings;
127
            Accounts = new ObservableConcurrentCollection<AccountViewModel>();
128
            if (settings.Accounts == null)
129
            {
130
                settings.Accounts=new AccountsCollection();
131
                settings.Save();
132
            }
133
            var accountVMs = from account in settings.Accounts
134
                             select new AccountViewModel(account);
135

    
136
            Accounts.AddFromEnumerable(accountVMs);
137
            
138
            var startupPath = Environment.GetFolderPath(Environment.SpecialFolder.Startup);
139
            _shortcutPath = Path.Combine(startupPath, "Pithos.lnk");
140

    
141

    
142
            StartOnSystemStartup = File.Exists(_shortcutPath);
143

    
144
            SelectedTab = currentTab;
145
        }
146

    
147
        private string _selectedTab="General";
148
        public string SelectedTab
149
        {
150
            get { return _selectedTab; }
151
            set
152
            {
153
                _selectedTab = value??"General";
154
                NotifyOfPropertyChange(()=>SelectedTab);
155
                NotifyOfPropertyChange(() => AccountTabSelected);
156
            }
157
        }
158

    
159

    
160
        public bool AccountTabSelected
161
        {
162
            get { return _selectedTab == "AccountTab"; }
163
        }
164
        #region Preferences Properties
165

    
166
        private bool _noProxy;
167
        public bool NoProxy
168
        {
169
            get { return _noProxy; }
170
            set
171
            {
172
                _noProxy = value;
173
                NotifyOfPropertyChange(()=>NoProxy);
174
            }
175
        }
176

    
177

    
178
        private bool _defaultProxy;
179

    
180
        public bool DefaultProxy
181
        {
182
            get { return _defaultProxy; }
183
            set
184
            {
185
                _defaultProxy = value;
186
                NotifyOfPropertyChange(() => DefaultProxy);
187
            }
188
        }
189

    
190

    
191
        private bool _manualProxy;
192

    
193
        public bool ManualProxy
194
        {
195
            get { return _manualProxy; }
196
            set
197
            {
198
                _manualProxy = value;
199
                NotifyOfPropertyChange(() => ManualProxy);
200
            }
201
        }
202
        #endregion
203

    
204

    
205
        public int StartupDelay
206
        {
207
            get { return (int) Settings.StartupDelay.TotalMinutes; }
208
            set
209
            {
210
                if (value<0)
211
                    throw new ArgumentOutOfRangeException("value",Resources.PreferencesViewModel_StartupDelay_Greater_or_equal_to_0);
212
                Settings.StartupDelay = TimeSpan.FromMinutes(value);
213
                NotifyOfPropertyChange(()=>StartupDelay);
214
            }
215
        }
216
       
217
        #region Commands
218
        
219
        public bool CanSelectiveSyncFolders
220
        {
221
            get { return CurrentAccount != null && CurrentAccount.SelectiveSyncEnabled; }
222
        }
223

    
224
        public void SelectiveSyncFolders()
225
        {
226
            //var monitor = Shell.Monitors[CurrentAccount.AccountKey];
227
            
228

    
229
            var model = new SelectiveSynchViewModel(_events,CurrentAccount.Account,CurrentAccount.ApiKey);            
230
            if (_windowManager.ShowDialog(model) == true)
231
            {
232
                
233
            }
234
        }
235

    
236
       /* private bool _networkTracing;
237
        public bool NetworkTracing
238
        {
239
            get { return _networkTracing; }
240
            set
241
            {
242
                _networkTracing = value;
243
                
244
            }
245
        }*/
246

    
247
        public void RefreshApiKey()
248
        {
249
            //_events.Publish(new Notification { Title = "Authorization failed", Message = "Your API Key has probably expired. You will be directed to a page where you can renew it", Level = TraceLevel.Error });
250
            if (CurrentAccount == null)
251
                return;
252
            try
253
            {
254

    
255
                var name = CurrentAccount.AccountName;
256

    
257
                var loginUri = new Uri(new Uri(CurrentAccount.ServerUrl), "login");
258
                var credentials = PithosAccount.RetrieveCredentials(loginUri.ToString(),name);
259
                if (credentials==null)
260
                    return;
261
                //The server will return credentials for a different account, not just the current account
262
                //We need to find the correct account first
263
                var account = Accounts.First(act => act.AccountName == credentials.UserName && act.ServerUrl == CurrentAccount.ServerUrl);
264
                account.ApiKey = credentials.Password;                
265
                account.IsExpired = false;
266
                Settings.Save();
267
                TaskEx.Delay(10000).ContinueWith(_ =>Shell.MonitorAccount(account.Account));
268
                NotifyOfPropertyChange(() => Accounts);
269
            }
270
            catch (AggregateException exc)
271
            {
272
                string message = String.Format("API Key retrieval failed");
273
                Log.Error(message, exc.InnerException);
274
                _events.Publish(new Notification { Title = "Authorization failed", Message = message, Level = TraceLevel.Error });
275
            }
276
            catch (Exception exc)
277
            {
278
                string message = String.Format("API Key retrieval failed");
279
                Log.Error(message, exc);
280
                _events.Publish(new Notification { Title = "Authorization failed", Message = message, Level = TraceLevel.Error });
281
            }
282

    
283
        }
284

    
285
    
286
        public void OpenLogPath()
287
        {
288
            Shell.OpenLogPath();
289
        }
290

    
291
        public void OpenLogConsole()
292
        {
293
            var logView=IoC.Get<LogConsole.LogConsoleViewModel>();            
294
            _windowManager.ShowWindow(logView);
295
        }
296

    
297
        public void SaveChanges()
298
        {
299
            DoSave();
300
            TryClose(true);
301
        }
302

    
303
        public void RejectChanges()
304
        {
305
            Settings.Reload();
306
            TryClose(false);
307
        }
308

    
309
        public void ApplyChanges()
310
        {
311
            DoSave();
312
        }
313

    
314
        private void DoSave()
315
        {
316
            //SetStartupMode();            
317

    
318
            //Ensure we save the settings changes first
319
            foreach (var account in _accountsToRemove)
320
            {
321
                Settings.Accounts.Remove(account);
322
            }
323

    
324
            foreach (var account in _accountsToAdd)
325
            {
326
                Settings.Accounts.Add(account);    
327
            }
328

    
329
            Settings.Save();
330

    
331

    
332
            try
333
            {
334
                foreach (var account in _accountsToRemove)
335
                {
336
                    Shell.RemoveMonitor(account.ServerUrl, account.AccountName);
337
                    Shell.RemoveAccountFromDatabase(account);
338
                }
339

    
340
                foreach (var account in Settings.Accounts)
341
                {
342
                    Shell.MonitorAccount(account);
343
                }
344

    
345
                var poller=IoC.Get<PollAgent>();
346
                poller.SynchNow();
347
            }                
348
            finally
349
            {
350
                _accountsToRemove.Clear();
351
                _accountsToAdd.Clear();
352
            }
353

    
354
            NotifyOfPropertyChange(()=>Settings);
355

    
356
            if (IgnoreCertificateErrors)
357
                ServicePointManager.ServerCertificateValidationCallback= (sender,certificate,chain,errors)=> true;
358
            else
359
            {
360
                ServicePointManager.ServerCertificateValidationCallback = null;
361
            }
362
        }
363

    
364
     /*   public void ChangePithosFolder()
365
        {
366
            var browser = new FolderBrowserDialog();
367
            browser.SelectedPath = Settings.PithosPath;
368
            var result = browser.ShowDialog((IWin32Window)GetView());
369
            if (result == DialogResult.OK)
370
            {
371
                var newPath = browser.SelectedPath;
372
                var accountName = CurrentAccount.AccountName;
373
                var monitor = Shell.Monitors[accountName];
374
                monitor.Stop();
375
                
376
                Shell.Monitors.Remove(accountName);
377

    
378
                Directory.Move(Settings.PithosPath, newPath);
379
                Settings.PithosPath = newPath;
380
                Settings.Save();
381

    
382
                Shell.MonitorAccount(CurrentAccount);
383

    
384
                NotifyOfPropertyChange(() => Settings);                
385
            }
386
        }
387
*/
388

    
389

    
390
        readonly List<AccountSettings> _accountsToAdd=new List<AccountSettings>();
391
       public void AddAccount()
392
       {
393
           var wizard = new AddAccountViewModel();
394
           if (_windowManager.ShowDialog(wizard) == true)
395
           {
396
               string selectedPath = wizard.AccountPath;
397
               var initialRootPath = wizard.ShouldCreateOkeanosFolder?
398
                   Path.Combine(selectedPath, "Okeanos")
399
                   :selectedPath;
400
               var actualRootPath= initialRootPath;
401
               if (wizard.ShouldCreateOkeanosFolder)
402
               {
403
                   int attempt = 1;
404
                   while (Directory.Exists(actualRootPath) || File.Exists(actualRootPath))
405
                   {
406
                       actualRootPath = String.Format("{0} {1}", initialRootPath, attempt++);
407
                   }
408
               }
409

    
410

    
411

    
412
               var account = Accounts.FirstOrDefault(act => act.AccountName == wizard.AccountName && act.ServerUrl == wizard.CurrentServer);
413
               if (account != null)
414
               {
415
                   if (MessageBox.Show("The account you specified already exists. Do you want to update it?", "The account exists") == MessageBoxResult.Yes)
416
                   {
417
                       account.ApiKey = wizard.Token;
418
                       account.IsExpired = false;
419
                       CurrentAccount = account;
420
                   }
421
               }
422
               else
423
               {
424
                   var newAccount = new AccountSettings
425
                                        {
426
                                            AccountName = wizard.AccountName,
427
                                            ServerUrl = wizard.CurrentServer,
428
                                            ApiKey = wizard.Token,
429
                                            RootPath = actualRootPath,
430
                                            IsActive = wizard.IsAccountActive,
431
                                        };
432

    
433

    
434
                   var client = new CloudFilesClient(newAccount.AccountName, newAccount.ApiKey)
435
                                    {
436
                                        AuthenticationUrl = newAccount.ServerUrl, UsePithos = true
437
                                    };
438
                   client.Authenticate();
439

    
440

    
441
                   var containers = client.ListContainers(newAccount.AccountName);
442
                   var containerUris = from container in containers
443
                                       select String.Format(@"{0}/v1/{1}/{2}",
444
                                            newAccount.ServerUrl, newAccount.AccountName, container.Name);
445
                   
446
                   newAccount.SelectiveFolders.AddRange(containerUris.ToArray());
447

    
448
                   var objectInfos = (from container in containers
449
                                      from dir in client.ListObjects(newAccount.AccountName, container.Name)
450
                                      where container.Name != "trash"
451
                                      select dir).ToList();
452
                   var tree = objectInfos.ToTree();
453

    
454
                   var selected = (from root in tree 
455
                                   from child in root 
456
                                   select child.Uri.ToString()).ToArray();
457
                   newAccount.SelectiveFolders.AddRange(selected);
458

    
459
                   
460
                   //TODO:Add the "pithos" container as a default selection                   
461

    
462
                   _accountsToAdd.Add(newAccount);
463
                   var accountVm = new AccountViewModel(newAccount);
464
                   (Accounts as IProducerConsumerCollection<AccountViewModel>).TryAdd(accountVm);
465
                   CurrentAccount = accountVm;
466
               }
467
               NotifyOfPropertyChange(() => Accounts);
468
               NotifyOfPropertyChange(() => Settings);   
469
           }
470

    
471

    
472
            
473
       }
474

    
475
/*
476
        public void AddPithosAccount()
477
       {
478
            var credentials=PithosAccount.RetrieveCredentials(null);
479
            if (credentials == null)
480
                return;
481
            var account = Settings.Accounts.FirstOrDefault(act => act.AccountName == credentials.UserName);
482
            var accountVM = new AccountViewModel(account);
483
            if (account == null)
484
            {
485
                account=new AccountSettings{
486
                    AccountName=credentials.UserName,
487
                    ApiKey=credentials.Password
488
                };
489
                Settings.Accounts.Add(account);
490
                accountVM = new AccountViewModel(account);
491
                (Accounts as IProducerConsumerCollection<AccountViewModel>).TryAdd(accountVM);
492
            }
493
            else
494
            {
495
                account.ApiKey=credentials.Password;
496
            }
497
            //SelectedAccountIndex= Settings.Accounts.IndexOf(account);
498
            CurrentAccount = accountVM;
499
            NotifyOfPropertyChange(() => Accounts);
500
            NotifyOfPropertyChange(()=>Settings);                       
501
       }
502
*/
503

    
504

    
505
        readonly List<AccountSettings> _accountsToRemove = new List<AccountSettings>();
506
        public void RemoveAccount()
507
        {
508
            Accounts.TryRemove(CurrentAccount);
509
            _accountsToRemove.Add(CurrentAccount.Account);
510

    
511
            CurrentAccount = null;
512
            NotifyOfPropertyChange(() => Accounts);
513

    
514
            
515
            //NotifyOfPropertyChange("Settings.Accounts");
516
        }
517

    
518
        public bool CanRemoveAccount
519
        {
520
            get { return (CurrentAccount != null); }
521
        }
522

    
523
        public bool CanClearAccountCache
524
        {
525
            get { return (CurrentAccount != null); }
526
        }
527

    
528
        public void ClearAccountCache()
529
        {
530
            if (MessageBoxResult.Yes == MessageBox.Show("You are about to delete all partially downloaded files from the account's cache.\n" +
531
                            " You will have to download all partially downloaded data again\n" +
532
                            "This change can not be undone\n\n" +
533
            "Do you wish to delete all partially downloaded data?", "Warning! Clearing account cache",
534
                            MessageBoxButton.YesNo,MessageBoxImage.Question,MessageBoxResult.No))
535
            {
536

    
537
                var cachePath = Path.Combine(CurrentAccount.RootPath, FolderConstants.CacheFolder);
538
                var dir = new DirectoryInfo(cachePath);
539
                //The file may not exist if we just created the account
540
                if (!dir.Exists)
541
                    return;
542
                dir.EnumerateFiles().Apply(file=>file.Delete());
543
                dir.EnumerateDirectories().Apply(folder => folder.Delete(true));
544
            }
545
        }
546

    
547

    
548
        public bool ExtensionsActivated
549
        {
550
            get { return Settings.ExtensionsActivated; }
551
            set
552
            {
553
                if (Settings.ExtensionsActivated == value)
554
                    return;
555

    
556
                Settings.ExtensionsActivated = value;
557

    
558
/*
559
                if (value)
560
                    _extensionController.RegisterExtensions();
561
                else
562
                {
563
                    _extensionController.UnregisterExtensions();
564
                }
565
*/
566
                NotifyOfPropertyChange(() => ExtensionsActivated);
567
            }
568
        }
569

    
570
        public bool DebugLoggingEnabled
571
        {
572
            get { return Settings.DebugLoggingEnabled; }
573
            set { 
574
                Settings.DebugLoggingEnabled = value;
575
                NotifyOfPropertyChange(()=>DebugLoggingEnabled);
576
            }
577
        }
578

    
579
        public bool IgnoreCertificateErrors
580
        {
581
            get { return Settings.IgnoreCertificateErrors; }
582
            set {
583
                Settings.IgnoreCertificateErrors = value;
584
                NotifyOfPropertyChange(() => IgnoreCertificateErrors);
585
            }
586
        }
587
       
588
        #endregion
589

    
590
       /* private int _selectedAccountIndex;
591
        public int SelectedAccountIndex
592
        {
593
            get { return _selectedAccountIndex; }
594
            set
595
            {
596
                //var accountCount=Settings.Accounts.Count;
597
                //if (accountCount == 0)
598
                //    return;
599
                //if (0 <= value && value < accountCount)
600
                //    _selectedAccountIndex = value;
601
                //else
602
                //    _selectedAccountIndex = 0;
603
                _selectedAccountIndex = value;
604
                NotifyOfPropertyChange(() => CurrentAccount);
605
                NotifyOfPropertyChange(() => CanRemoveAccount);
606
                NotifyOfPropertyChange(()=>SelectedAccountIndex);
607
            }
608
        }*/
609

    
610
        private AccountViewModel _currentAccount;
611
        private readonly IWindowManager _windowManager;
612
        private readonly string _shortcutPath;
613

    
614

    
615
        
616
        public AccountViewModel CurrentAccount
617
        {
618
            get { return _currentAccount; }
619
            set
620
            {
621
                _currentAccount = value;
622

    
623
                if (_currentAccount!=null)
624
                    _currentAccount.PropertyChanged += (o, e) => NotifyOfPropertyChange(() => CanSelectiveSyncFolders);
625

    
626
                NotifyOfPropertyChange(() => CurrentAccount);
627
                NotifyOfPropertyChange(() => CanRemoveAccount);
628
                NotifyOfPropertyChange(() => CanSelectiveSyncFolders);
629
                NotifyOfPropertyChange(() => CanMoveAccountFolder);
630
                NotifyOfPropertyChange(() => CanClearAccountCache);
631
            }
632
        }
633

    
634
/*
635
        public AccountSettings CurrentAccount
636
        {
637
            get {
638
                if (0 <= SelectedAccountIndex && SelectedAccountIndex < Settings.Accounts.Count)                    
639
                    return Settings.Accounts[SelectedAccountIndex];
640
                return null;
641
            }
642

    
643
        }
644
*/
645

    
646

    
647
        public bool CanMoveAccountFolder
648
        {
649
            get { return CurrentAccount != null; }
650
        }
651

    
652
    public void MoveAccountFolder()
653
    {
654

    
655
        using (var dlg = new FolderBrowserDialog())
656
        {
657
            var currentFolder = CurrentAccount.RootPath;
658
            dlg.SelectedPath = currentFolder;
659
            //Ask the user to select a folder
660
            //Note: We need a parent window here, which we retrieve with GetView            
661
            var view = (Window)GetView();            
662
            if (DialogResult.OK != dlg.ShowDialog(new Wpf32Window(view)))
663
                return;            
664

    
665
            var newPath= dlg.SelectedPath;                
666
            //Find the account's monitor and stop it
667
            PithosMonitor monitor;
668
            if (Shell.Monitors.TryGetValue(CurrentAccount.AccountKey, out monitor))
669
            {
670
                monitor.Stop();
671

    
672

    
673
                var oldPath = monitor.RootPath;
674
                //The old directory may not exist eg. if we create an account for the first time
675
                if (Directory.Exists(oldPath))
676
                {
677
                    //If it does, do the move
678

    
679
                    //Now Create all of the directories
680
                    foreach (string dirPath in Directory.EnumerateDirectories(oldPath, "*",
681
                                                           SearchOption.AllDirectories))
682
                        Directory.CreateDirectory(dirPath.Replace(oldPath, newPath));
683

    
684
                    //Copy all the files
685
                    foreach (string newFilePath in Directory.EnumerateFiles(oldPath, "*.*",
686
                                                                            SearchOption.AllDirectories))
687
                        File.Copy(newFilePath, newFilePath.Replace(oldPath, newPath));
688

    
689
                    Log.InfoFormat("Deleting account folder {0}",oldPath);
690
                    Directory.Delete(oldPath, true);
691

    
692
                    //We also need to change the path of the existing file states
693
                    monitor.MoveFileStates(oldPath, newPath);
694
                }
695
            }
696
            //Replace the old rootpath with the new
697
            CurrentAccount.RootPath = newPath;
698
            //TODO: This will save all settings changes. Too coarse grained, need to fix at a later date
699
            Settings.Save();            
700
            //And start the monitor on the new RootPath            
701
            if (monitor != null)
702
            {
703
                monitor.RootPath = newPath;
704
                if (CurrentAccount.IsActive)
705
                    monitor.Start();
706
            }
707
            else
708
                Shell.MonitorAccount(CurrentAccount.Account);
709
            //Finally, notify that the Settings, CurrentAccount have changed
710
            NotifyOfPropertyChange(() => CurrentAccount);
711
            NotifyOfPropertyChange(() => Settings);
712

    
713
        }
714
    }
715
    }
716
}