Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (27.9 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 =
86
            log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
87

    
88
        private PithosSettings _settings;
89

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

    
100
        private ObservableConcurrentCollection<AccountViewModel> _accounts;
101

    
102
        public ObservableConcurrentCollection<AccountViewModel> Accounts
103
        {
104
            get { return _accounts; }
105
            set
106
            {
107
                _accounts = value;
108
                NotifyOfPropertyChange(() => Accounts);
109
            }
110
        }
111

    
112
        public bool StartOnSystemStartup { get; set; }
113

    
114
        public ShellViewModel Shell { get; set; }
115
        //ShellExtensionController _extensionController=new ShellExtensionController();
116

    
117
        [ImportingConstructor]
118
        public PreferencesViewModel(IWindowManager windowManager, IEventAggregator events, ShellViewModel shell,
119
                                    PithosSettings settings)
120
        {
121
            this.DisplayName = "Pithos+ Preferences";
122

    
123
            // ReSharper disable DoNotCallOverridableMethodsInConstructor
124
            //Caliburn.Micro uses DisplayName for the view's title
125
            DisplayName = "Pithos+ Preferences";
126
            // ReSharper restore DoNotCallOverridableMethodsInConstructor
127

    
128
            _windowManager = windowManager;
129
            _events = events;
130

    
131
            Shell = shell;
132

    
133
            Settings = settings;
134
            Accounts = new ObservableConcurrentCollection<AccountViewModel>();
135

    
136

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

    
140

    
141
            StartOnSystemStartup = File.Exists(_shortcutPath);
142

    
143
            //SelectedTab = currentTab;
144
        }
145

    
146
        protected override void OnViewLoaded(object view)
147
        {
148
            base.OnViewLoaded(view);
149

    
150
            Settings.Reload();
151

    
152
            Accounts.Clear();
153

    
154
            if (Settings.Accounts == null)
155
            {
156
                Settings.Accounts = new AccountsCollection();
157
                Settings.Save();
158
            }
159
            var accountVMs = from account in Settings.Accounts
160
                             select new AccountViewModel(account);
161

    
162
            Accounts.AddFromEnumerable(accountVMs);
163

    
164
        }
165

    
166
        private string _selectedTab = "General";
167

    
168
        public string SelectedTab
169
        {
170
            get { return _selectedTab; }
171
            set
172
            {
173
                _selectedTab = value ?? "GeneralTab";
174
                NotifyOfPropertyChange(() => SelectedTab);
175
                NotifyOfPropertyChange(() => AccountTabSelected);
176
            }
177
        }
178

    
179

    
180
        public bool AccountTabSelected
181
        {
182
            get { return _selectedTab == "AccountTab"; }
183
        }
184

    
185
        #region Preferences Properties
186

    
187
        private bool _noProxy;
188

    
189
        public bool NoProxy
190
        {
191
            get { return _noProxy; }
192
            set
193
            {
194
                _noProxy = value;
195
                NotifyOfPropertyChange(() => NoProxy);
196
            }
197
        }
198

    
199

    
200
        private bool _defaultProxy;
201

    
202
        public bool DefaultProxy
203
        {
204
            get { return _defaultProxy; }
205
            set
206
            {
207
                _defaultProxy = value;
208
                NotifyOfPropertyChange(() => DefaultProxy);
209
            }
210
        }
211

    
212

    
213
        private bool _manualProxy;
214

    
215
        public bool ManualProxy
216
        {
217
            get { return _manualProxy; }
218
            set
219
            {
220
                _manualProxy = value;
221
                NotifyOfPropertyChange(() => ManualProxy);
222
            }
223
        }
224

    
225
        #endregion
226

    
227

    
228
        public int StartupDelay
229
        {
230
            get { return (int) Settings.StartupDelay.TotalMinutes; }
231
            set
232
            {
233
                if (value < 0)
234
                    throw new ArgumentOutOfRangeException("value",
235
                                                          Resources.
236
                                                              PreferencesViewModel_StartupDelay_Greater_or_equal_to_0);
237
                Settings.StartupDelay = TimeSpan.FromMinutes(value);
238
                NotifyOfPropertyChange(() => StartupDelay);
239
            }
240
        }
241

    
242
        #region Commands
243

    
244
        public bool CanSelectiveSyncFolders
245
        {
246
            get { return CurrentAccount != null && CurrentAccount.SelectiveSyncEnabled; }
247
        }
248

    
249
        public void SelectiveSyncFolders()
250
        {
251
            //var monitor = Shell.Monitors[CurrentAccount.AccountKey];
252

    
253

    
254
            var model = new SelectiveSynchViewModel(_events, CurrentAccount.Account, CurrentAccount.ApiKey, false);
255
            if (_windowManager.ShowDialog(model) == true)
256
            {
257

    
258
            }
259
        }
260

    
261
        /* private bool _networkTracing;
262
        public bool NetworkTracing
263
        {
264
            get { return _networkTracing; }
265
            set
266
            {
267
                _networkTracing = value;
268
                
269
            }
270
        }*/
271

    
272
        public void RefreshApiKey()
273
        {
274
            //_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 });
275
            if (CurrentAccount == null)
276
                return;
277
            try
278
            {
279

    
280
                var name = CurrentAccount.AccountName;
281

    
282
                var loginUri = new Uri(CurrentAccount.ServerUrl).Combine("login");
283
                var credentials = PithosAccount.RetrieveCredentials(loginUri.ToString(), name);
284
                if (credentials == null)
285
                    return;
286
                //The server will return credentials for a different account, not just the current account
287
                //We need to find the correct account first
288
                var account =
289
                    Accounts.First(
290
                        act => act.AccountName == credentials.UserName && act.ServerUrl == CurrentAccount.ServerUrl);
291
                account.ApiKey = credentials.Password;
292
                account.IsExpired = false;
293
                Settings.Save();
294
                TaskEx.Delay(10000).ContinueWith(_ => Shell.MonitorAccount(account.Account));
295
                NotifyOfPropertyChange(() => Accounts);
296
            }
297
            catch (AggregateException exc)
298
            {
299
                string message = String.Format("API Key retrieval failed");
300
                Log.Error(message, exc.InnerException);
301
                _events.Publish(new Notification
302
                                    {Title = "Authorization failed", Message = message, Level = TraceLevel.Error});
303
            }
304
            catch (Exception exc)
305
            {
306
                string message = String.Format("API Key retrieval failed");
307
                Log.Error(message, exc);
308
                _events.Publish(new Notification
309
                                    {Title = "Authorization failed", Message = message, Level = TraceLevel.Error});
310
            }
311

    
312
        }
313

    
314
        public bool CanWipeAccount
315
        {
316
            get { return CurrentAccount != null; }
317
        }
318

    
319
        public async void WipeAccount()
320
        {
321
            PithosMonitor amonitor;
322
            if (Shell.Monitors.TryGetValue(CurrentAccount.AccountKey, out amonitor))
323
            {
324
                var message = String.Format("You are about to wipe all data in the {0} account at {1}. Are you sure?",
325
                                            amonitor.Account.UserName, amonitor.Account.SiteUri);
326
                if (MessageBoxResult.Yes !=
327
                    MessageBox.Show(message, "Warning! Account data will be wiped", MessageBoxButton.YesNo,
328
                                    MessageBoxImage.Hand, MessageBoxResult.No))
329
                    return;
330
                await amonitor.CloudClient.WipeContainer("", new Uri("pithos", UriKind.Relative));
331
                MessageBox.Show("Account wiped");
332
            }
333
        }
334

    
335

    
336
        public void OpenLogPath()
337
        {
338
            Shell.OpenLogPath();
339
        }
340

    
341
        public void OpenLogConsole()
342
        {
343
            var logView = IoC.Get<LogConsole.LogConsoleViewModel>();
344
            _windowManager.ShowWindow(logView);
345
        }
346

    
347
        public void SaveChanges()
348
        {
349
            DoSave();
350
            TryClose( /*true*/);
351
        }
352

    
353
        public void RejectChanges()
354
        {
355
            Settings.Reload();
356
            TryClose( /*false*/);
357
        }
358

    
359
        public void ApplyChanges()
360
        {
361
            DoSave();
362
        }
363

    
364
        private void DoSave()
365
        {
366
            //SetStartupMode();            
367

    
368
            //Ensure we save the settings changes first
369
            foreach (var account in _accountsToRemove)
370
            {
371
                Settings.Accounts.Remove(account);
372
            }
373

    
374
            foreach (var account in _accountsToAdd)
375
            {
376
                Settings.Accounts.Add(account);
377
            }
378

    
379
            Settings.Save();
380

    
381

    
382
            try
383
            {
384
                foreach (var account in _accountsToRemove)
385
                {
386
                    Shell.RemoveMonitor(account.ServerUrl, account.AccountName);
387
                    Shell.RemoveAccountFromDatabase(account);
388
                }
389

    
390
                foreach (var account in Settings.Accounts)
391
                {
392
                    Shell.MonitorAccount(account);
393
                }
394

    
395
                var poller = IoC.Get<PollAgent>();
396
                poller.SynchNow();
397
            }
398
            finally
399
            {
400
                _accountsToRemove.Clear();
401
                _accountsToAdd.Clear();
402
            }
403

    
404
            NotifyOfPropertyChange(() => Settings);
405

    
406
            if (IgnoreCertificateErrors)
407
                ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;
408
            else
409
            {
410
                ServicePointManager.ServerCertificateValidationCallback = null;
411
            }
412
        }
413

    
414
        /*   public void ChangePithosFolder()
415
        {
416
            var browser = new FolderBrowserDialog();
417
            browser.SelectedPath = Settings.PithosPath;
418
            var result = browser.ShowDialog((IWin32Window)GetView());
419
            if (result == DialogResult.OK)
420
            {
421
                var newPath = browser.SelectedPath;
422
                var accountName = CurrentAccount.AccountName;
423
                var monitor = Shell.Monitors[accountName];
424
                monitor.Stop();
425
                
426
                Shell.Monitors.Remove(accountName);
427

    
428
                Directory.Move(Settings.PithosPath, newPath);
429
                Settings.PithosPath = newPath;
430
                Settings.Save();
431

    
432
                Shell.MonitorAccount(CurrentAccount);
433

    
434
                NotifyOfPropertyChange(() => Settings);                
435
            }
436
        }
437
*/
438

    
439

    
440
        private readonly List<AccountSettings> _accountsToAdd = new List<AccountSettings>();
441

    
442
        public async void AddAccount()
443
        {
444
            var wizard = new AddAccountViewModel();
445
            if (_windowManager.ShowDialog(wizard) == true)
446
            {
447
                try
448
                {
449
                    string selectedPath = wizard.AccountPath;
450
                    var initialRootPath = wizard.ShouldCreateOkeanosFolder
451
                                              ? Path.Combine(selectedPath, "Okeanos")
452
                                              : selectedPath;
453
                    var actualRootPath = initialRootPath;
454
                    if (wizard.ShouldCreateOkeanosFolder)
455
                    {
456
                        int attempt = 1;
457
                        while (Directory.Exists(actualRootPath) || File.Exists(actualRootPath))
458
                        {
459
                            actualRootPath = String.Format("{0} {1}", initialRootPath, attempt++);
460
                        }
461
                    }
462

    
463

    
464

    
465
                    var account =
466
                        Accounts.FirstOrDefault(
467
                            act => act.AccountName == wizard.AccountName && act.ServerUrl == wizard.CurrentServer);
468
                    if (account != null)
469
                    {
470
                        if (
471
                            MessageBox.Show("The account you specified already exists. Do you want to update it?",
472
                                            "The account exists") == MessageBoxResult.Yes)
473
                        {
474
                            account.ApiKey = wizard.Token;
475
                            account.IsExpired = false;
476
                            CurrentAccount = account;
477
                        }
478
                    }
479
                    else
480
                    {
481
                        var newAccount = new AccountSettings
482
                                             {
483
                                                 AccountName = wizard.AccountName,
484
                                                 ServerUrl = wizard.CurrentServer,
485
                                                 ApiKey = wizard.Token,
486
                                                 RootPath = actualRootPath,
487
                                                 IsActive = wizard.IsAccountActive,
488
                                             };
489

    
490

    
491
                        var client = new CloudFilesClient(newAccount.AccountName, newAccount.ApiKey)
492
                                         {
493
                                             AuthenticationUrl = newAccount.ServerUrl,
494
                                             UsePithos = true
495
                                         };
496

    
497
                        await InitializeSelectiveFolders(newAccount, client);
498

    
499

    
500
                        //TODO:Add the "pithos" container as a default selection                   
501

    
502
                        _accountsToAdd.Add(newAccount);
503
                        var accountVm = new AccountViewModel(newAccount);
504
                        (Accounts as IProducerConsumerCollection<AccountViewModel>).TryAdd(accountVm);
505
                        CurrentAccount = accountVm;
506
                    }
507
                    NotifyOfPropertyChange(() => Accounts);
508
                    NotifyOfPropertyChange(() => Settings);
509
                }
510
                catch (WebException exc)
511
                {
512
                    Log.ErrorFormat("[Add Account] Connectivity Error: {0}", exc);
513
                    MessageBox.Show("Unable to connect to Pithos. Please try again later", "Connectivity Error",
514
                                    MessageBoxButton.OK, MessageBoxImage.Exclamation);
515
                }
516
            }
517

    
518

    
519

    
520
        }
521

    
522
        private async Task InitializeSelectiveFolders(AccountSettings newAccount, CloudFilesClient client,
523
                                                      int retries = 3)
524
        {
525
            while (true)
526
            {
527
                try
528
                {
529
                    await client.Authenticate().ConfigureAwait(false);
530

    
531
                    var containers = await client.ListContainers(newAccount.AccountName).ConfigureAwait(false);
532
                    var containerUris = from container in containers
533
                                        select String.Format(@"{0}/v1/{1}/{2}",
534
                                                             newAccount.ServerUrl, newAccount.AccountName,
535
                                                             container.Name);
536

    
537
                    newAccount.SelectiveFolders.AddRange(containerUris.ToArray());
538

    
539
                    var objectInfos = (from container in containers
540
                                       from dir in client.ListObjects(newAccount.AccountName, container.Name)
541
                                       where container.Name.ToString() != "trash"
542
                                       select dir).ToList();
543
                    var tree = objectInfos.ToTree();
544

    
545
                    var selected = (from root in tree
546
                                    from child in root
547
                                    select child.Uri.ToString()).ToArray();
548
                    newAccount.SelectiveFolders.AddRange(selected);
549
                    return;
550
                }
551
                catch (WebException)
552
                {
553
                    if (retries > 0)
554
                        retries--;
555
                    else
556
                        throw;
557
                }
558
            }
559
        }
560

    
561
/*
562
        public void AddPithosAccount()
563
       {
564
            var credentials=PithosAccount.RetrieveCredentials(null);
565
            if (credentials == null)
566
                return;
567
            var account = Settings.Accounts.FirstOrDefault(act => act.AccountName == credentials.UserName);
568
            var accountVM = new AccountViewModel(account);
569
            if (account == null)
570
            {
571
                account=new AccountSettings{
572
                    AccountName=credentials.UserName,
573
                    ApiKey=credentials.Password
574
                };
575
                Settings.Accounts.Add(account);
576
                accountVM = new AccountViewModel(account);
577
                (Accounts as IProducerConsumerCollection<AccountViewModel>).TryAdd(accountVM);
578
            }
579
            else
580
            {
581
                account.ApiKey=credentials.Password;
582
            }
583
            //SelectedAccountIndex= Settings.Accounts.IndexOf(account);
584
            CurrentAccount = accountVM;
585
            NotifyOfPropertyChange(() => Accounts);
586
            NotifyOfPropertyChange(()=>Settings);                       
587
       }
588
*/
589

    
590

    
591
        private readonly List<AccountSettings> _accountsToRemove = new List<AccountSettings>();
592

    
593
        public void RemoveAccount()
594
        {
595
            Accounts.TryRemove(CurrentAccount);
596
            _accountsToRemove.Add(CurrentAccount.Account);
597

    
598
            CurrentAccount = null;
599
            NotifyOfPropertyChange(() => Accounts);
600

    
601

    
602
            //NotifyOfPropertyChange("Settings.Accounts");
603
        }
604

    
605
        public bool CanRemoveAccount
606
        {
607
            get { return (CurrentAccount != null); }
608
        }
609

    
610
        public bool CanClearAccountCache
611
        {
612
            get { return (CurrentAccount != null); }
613
        }
614

    
615
        public void ClearAccountCache()
616
        {
617
            if (MessageBoxResult.Yes ==
618
                MessageBox.Show("You are about to delete all partially downloaded files from the account's cache.\n" +
619
                                " You will have to download all partially downloaded data again\n" +
620
                                "This change can not be undone\n\n" +
621
                                "Do you wish to delete all partially downloaded data?",
622
                                "Warning! Clearing account cache",
623
                                MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No))
624
            {
625

    
626
                var cachePath = Path.Combine(CurrentAccount.RootPath, FolderConstants.CacheFolder);
627
                var dir = new DirectoryInfo(cachePath);
628
                //The file may not exist if we just created the account
629
                if (!dir.Exists)
630
                    return;
631
                dir.EnumerateFiles().Apply(file => file.Delete());
632
                dir.EnumerateDirectories().Apply(folder => folder.Delete(true));
633
            }
634
        }
635

    
636

    
637
        public bool ExtensionsActivated
638
        {
639
            get { return Settings.ExtensionsActivated; }
640
            set
641
            {
642
                if (Settings.ExtensionsActivated == value)
643
                    return;
644

    
645
                Settings.ExtensionsActivated = value;
646

    
647
/*
648
                if (value)
649
                    _extensionController.RegisterExtensions();
650
                else
651
                {
652
                    _extensionController.UnregisterExtensions();
653
                }
654
*/
655
                NotifyOfPropertyChange(() => ExtensionsActivated);
656
            }
657
        }
658

    
659
        public bool DebugLoggingEnabled
660
        {
661
            get { return Settings.DebugLoggingEnabled; }
662
            set
663
            {
664
                Settings.DebugLoggingEnabled = value;
665
                NotifyOfPropertyChange(() => DebugLoggingEnabled);
666
            }
667
        }
668

    
669
        public bool IgnoreCertificateErrors
670
        {
671
            get { return Settings.IgnoreCertificateErrors; }
672
            set
673
            {
674
                Settings.IgnoreCertificateErrors = value;
675
                NotifyOfPropertyChange(() => IgnoreCertificateErrors);
676
            }
677
        }
678

    
679
        #endregion
680

    
681
        /* private int _selectedAccountIndex;
682
        public int SelectedAccountIndex
683
        {
684
            get { return _selectedAccountIndex; }
685
            set
686
            {
687
                //var accountCount=Settings.Accounts.Count;
688
                //if (accountCount == 0)
689
                //    return;
690
                //if (0 <= value && value < accountCount)
691
                //    _selectedAccountIndex = value;
692
                //else
693
                //    _selectedAccountIndex = 0;
694
                _selectedAccountIndex = value;
695
                NotifyOfPropertyChange(() => CurrentAccount);
696
                NotifyOfPropertyChange(() => CanRemoveAccount);
697
                NotifyOfPropertyChange(()=>SelectedAccountIndex);
698
            }
699
        }*/
700

    
701
        private AccountViewModel _currentAccount;
702
        private readonly IWindowManager _windowManager;
703
        private readonly string _shortcutPath;
704

    
705

    
706

    
707
        public AccountViewModel CurrentAccount
708
        {
709
            get { return _currentAccount; }
710
            set
711
            {
712
                _currentAccount = value;
713

    
714
                if (_currentAccount != null)
715
                    _currentAccount.PropertyChanged += (o, e) => NotifyOfPropertyChange(() => CanSelectiveSyncFolders);
716

    
717
                NotifyOfPropertyChange(() => CurrentAccount);
718
                NotifyOfPropertyChange(() => CanRemoveAccount);
719
                NotifyOfPropertyChange(() => CanSelectiveSyncFolders);
720
                NotifyOfPropertyChange(() => CanMoveAccountFolder);
721
                NotifyOfPropertyChange(() => CanClearAccountCache);
722
                NotifyOfPropertyChange(() => CanWipeAccount);
723
            }
724
        }
725

    
726
/*
727
        public AccountSettings CurrentAccount
728
        {
729
            get {
730
                if (0 <= SelectedAccountIndex && SelectedAccountIndex < Settings.Accounts.Count)                    
731
                    return Settings.Accounts[SelectedAccountIndex];
732
                return null;
733
            }
734

    
735
        }
736
*/
737

    
738

    
739
        public bool CanMoveAccountFolder
740
        {
741
            get { return CurrentAccount != null; }
742
        }
743

    
744
        public void MoveAccountFolder()
745
        {
746

    
747
            using (var dlg = new FolderBrowserDialog())
748
            {
749
                var currentFolder = CurrentAccount.RootPath;
750
                dlg.SelectedPath = currentFolder;
751
                //Ask the user to select a folder
752
                //Note: We need a parent window here, which we retrieve with GetView            
753
                var view = (Window) GetView();
754
                if (DialogResult.OK != dlg.ShowDialog(new Wpf32Window(view)))
755
                    return;
756

    
757
                var newPath = dlg.SelectedPath;
758
                //Find the account's monitor and stop it
759
                PithosMonitor monitor;
760
                if (Shell.Monitors.TryGetValue(CurrentAccount.AccountKey, out monitor))
761
                {
762
                    //Problem: Doesn't stop the poll agent
763
                    monitor.Stop();
764

    
765
                    monitor.MoveRootFolder(newPath);
766

    
767
                   
768
                }
769
                //Replace the old rootpath with the new
770
                CurrentAccount.RootPath = newPath;
771
                //TODO: This will save all settings changes. Too coarse grained, need to fix at a later date
772
                Settings.Save();
773
                //And start the monitor on the new RootPath            
774
                if (monitor != null)
775
                {
776
                    monitor.RootPath = newPath;
777
                    if (CurrentAccount.IsActive)
778
                        Shell.StartMonitor(monitor);
779
                        
780
                }
781
                else
782
                    Shell.MonitorAccount(CurrentAccount.Account);
783
                //Finally, notify that the Settings, CurrentAccount have changed
784
                NotifyOfPropertyChange(() => CurrentAccount);
785
                NotifyOfPropertyChange(() => Settings);
786

    
787
            }
788
        }
789

    
790
    }
791
}