Statistics
| Branch: | Revision:

root / trunk / Pithos.Client.WPF / Preferences / PreferencesViewModel.cs @ 2f5fcd2f

History | View | Annotate | Download (29.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
            if (Accounts.Count > 0)
164
                CurrentAccount = Accounts.First();
165

    
166
        }
167

    
168
        private string _selectedTab = "General";
169

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

    
181

    
182
        public bool AccountTabSelected
183
        {
184
            get { return _selectedTab == "AccountTab"; }
185
        }
186

    
187
        #region Preferences Properties
188

    
189
        private bool _noProxy;
190

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

    
201

    
202
        private bool _defaultProxy;
203

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

    
214

    
215
        private bool _manualProxy;
216

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

    
227
        #endregion
228

    
229

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

    
244
        #region Commands
245

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

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

    
255

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

    
260
            }
261
        }
262

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

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

    
282
                var name = CurrentAccount.AccountName;
283

    
284
                var loginUri = PithosAccount.GetLoginUri(CurrentAccount.ServerUrl);
285
                var credentials = PithosAccount.RetrieveCredentials(loginUri.ToString(), name);
286
                if (credentials == null)
287
                    return;
288
                //The server will return credentials for a different account, not just the current account
289
                //We need to find the correct account first
290
                AccountViewModel account=null;
291
                Guid token;
292
                if (Guid.TryParse(name, out token))
293
                {
294
                    account =
295
                        Accounts.First(
296
                            act => act.AccountName == credentials.UserName && act.ServerUrl == CurrentAccount.ServerUrl);
297
                }
298
                else
299
                {
300
                    account =
301
                        Accounts.First(
302
                            act => act.AccountName == name && act.ServerUrl == CurrentAccount.ServerUrl);
303
                    account.AccountName = credentials.UserName;
304
                    account.DisplayName = name;
305
                    Shell.RemoveMonitor(account.ServerUrl,name);
306
                    CurrentAccount.AccountName = credentials.UserName;
307
                    CurrentAccount.DisplayName = name;
308
                    Shell.MonitorAccount(account.Account);
309
                }
310
                account.ApiKey = credentials.Password;
311
                account.IsExpired = false;
312
                Settings.Save();
313
                TaskEx.Delay(10000).ContinueWith(_ => Shell.MonitorAccount(account.Account));
314
                NotifyOfPropertyChange(() => Accounts);
315
            }
316
            catch (AggregateException exc)
317
            {
318
                string message = String.Format("API Key retrieval failed");
319
                Log.Error(message, exc.InnerException);
320
                _events.Publish(new Notification
321
                                    {Title = "Authorization failed", Message = message, Level = TraceLevel.Error});
322
            }
323
            catch (Exception exc)
324
            {
325
                string message = String.Format("API Key retrieval failed");
326
                Log.Error(message, exc);
327
                _events.Publish(new Notification
328
                                    {Title = "Authorization failed", Message = message, Level = TraceLevel.Error});
329
            }
330

    
331
        }
332

    
333
        public bool CanWipeAccount
334
        {
335
            get { return CurrentAccount != null 
336
                && Shell.Monitors.ContainsKey(CurrentAccount.AccountKey)
337
                && Shell.Monitors[CurrentAccount.AccountKey].CloudClient!=null;
338
            }
339
        }
340

    
341
        public async void WipeAccount()
342
        {
343
            PithosMonitor aMonitor;
344
            if (Shell.Monitors.TryGetValue(CurrentAccount.AccountKey, out aMonitor))
345
            {
346
                if (aMonitor.CloudClient == null)
347
                {
348
                    Log.ErrorFormat("Tried to wipe account [{0}] before authenticating",CurrentAccount.AccountKey);
349
                    return;
350
                }
351
                var message = String.Format("You are about to wipe all data in the {0} account at {1}. Are you sure?",
352
                                            CurrentAccount.AccountName, CurrentAccount.ServerUrl);
353
                if (MessageBoxResult.Yes !=
354
                    MessageBox.Show(message, "Warning! Account data will be wiped", MessageBoxButton.YesNo,
355
                                    MessageBoxImage.Hand, MessageBoxResult.No))
356
                    return;      
357
                          
358
                await aMonitor.CloudClient.WipeContainer("", new Uri("pithos", UriKind.Relative));
359
                aMonitor.Stop();
360
                await aMonitor.Start();
361
                MessageBox.Show("Account wiped");
362
            }
363
        }
364

    
365

    
366
        public void OpenLogPath()
367
        {
368
            Shell.OpenLogPath();
369
        }
370

    
371
        public void OpenLogConsole()
372
        {
373
            var logView = IoC.Get<LogConsole.LogConsoleViewModel>();
374
            _windowManager.ShowWindow(logView);
375
        }
376

    
377
        public void SaveChanges()
378
        {
379
            DoSave();
380
            TryClose( /*true*/);
381
        }
382

    
383
        public void RejectChanges()
384
        {
385
            Settings.Reload();
386
            TryClose( /*false*/);
387
        }
388

    
389
        public void ApplyChanges()
390
        {
391
            DoSave();
392
        }
393

    
394
        private void DoSave()
395
        {
396
            //SetStartupMode();            
397

    
398
            //Ensure we save the settings changes first
399
            foreach (var account in _accountsToRemove)
400
            {
401
                Settings.Accounts.Remove(account);
402
            }
403

    
404
            foreach (var account in _accountsToAdd)
405
            {
406
                Settings.Accounts.Add(account);
407
            }
408

    
409
            Settings.Save();
410

    
411

    
412
            try
413
            {
414
                foreach (var account in _accountsToRemove)
415
                {
416
                    Shell.RemoveMonitor(account.ServerUrl, account.AccountName);
417
                    Shell.RemoveAccountFromDatabase(account);
418
                }
419

    
420
                foreach (var account in Settings.Accounts)
421
                {
422
                    Shell.MonitorAccount(account);
423
                }
424

    
425
                var poller = IoC.Get<PollAgent>();
426
                poller.SynchNow();
427
            }
428
            finally
429
            {
430
                _accountsToRemove.Clear();
431
                _accountsToAdd.Clear();
432
            }
433

    
434
            NotifyOfPropertyChange(() => Settings);
435

    
436
            if (IgnoreCertificateErrors)
437
                ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;
438
            else
439
            {
440
                ServicePointManager.ServerCertificateValidationCallback = null;
441
            }
442
        }
443

    
444
        /*   public void ChangePithosFolder()
445
        {
446
            var browser = new FolderBrowserDialog();
447
            browser.SelectedPath = Settings.PithosPath;
448
            var result = browser.ShowDialog((IWin32Window)GetView());
449
            if (result == DialogResult.OK)
450
            {
451
                var newPath = browser.SelectedPath;
452
                var accountName = CurrentAccount.AccountName;
453
                var monitor = Shell.Monitors[accountName];
454
                monitor.Stop();
455
                
456
                Shell.Monitors.Remove(accountName);
457

    
458
                Directory.Move(Settings.PithosPath, newPath);
459
                Settings.PithosPath = newPath;
460
                Settings.Save();
461

    
462
                Shell.MonitorAccount(CurrentAccount);
463

    
464
                NotifyOfPropertyChange(() => Settings);                
465
            }
466
        }
467
*/
468

    
469

    
470
        private readonly List<AccountSettings> _accountsToAdd = new List<AccountSettings>();
471

    
472
        public async void AddAccount()
473
        {
474
            var wizard = new AddAccountViewModel();
475
            if (_windowManager.ShowDialog(wizard) == true)
476
            {
477
                try
478
                {
479
                    string selectedPath = wizard.AccountPath;
480
                    var initialRootPath = wizard.ShouldCreateOkeanosFolder
481
                                              ? Path.Combine(selectedPath, "okeanos")
482
                                              : selectedPath;
483
                    var actualRootPath = initialRootPath;
484
                    if (wizard.ShouldCreateOkeanosFolder)
485
                    {
486
                        int attempt = 1;
487
                        while (Directory.Exists(actualRootPath) || File.Exists(actualRootPath))
488
                        {
489
                            actualRootPath = String.Format("{0} {1}", initialRootPath, attempt++);
490
                        }
491
                        Directory.CreateDirectory(actualRootPath);
492
                    }
493

    
494

    
495

    
496
                    var account =
497
                        Accounts.FirstOrDefault(
498
                            act => act.AccountName == wizard.AccountName && act.ServerUrl == wizard.CurrentServer);
499
                    if (account != null)
500
                    {
501
                        if (
502
                            MessageBox.Show("The account you specified already exists. Do you want to update it?",
503
                                            "The account exists") == MessageBoxResult.Yes)
504
                        {
505
                            account.ApiKey = wizard.Token;
506
                            account.IsExpired = false;
507
                            CurrentAccount = account;
508
                        }
509
                    }
510
                    else
511
                    {
512
                        var newAccount = new AccountSettings
513
                                             {
514
                                                 AccountName = wizard.AccountName,
515
                                                 ServerUrl = wizard.CurrentServer,
516
                                                 ApiKey = wizard.Token,
517
                                                 RootPath = actualRootPath,
518
                                                 IsActive = wizard.IsAccountActive,
519
                                             };
520

    
521
                        
522
                        var client = new CloudFilesClient(newAccount.AccountName, newAccount.ApiKey)
523
                                         {
524
                                             AuthenticationUrl = newAccount.ServerUrl,
525
                                             UsePithos = true
526
                                         };
527
                        await client.Authenticate().ConfigureAwait(false);
528

    
529
                        Guid token;
530
                        if (Guid.TryParse(wizard.AccountName, out token))
531
                        {
532
                            newAccount.AccountToken = token;
533
                            newAccount.DisplayName = await client.ResolveName(token).ConfigureAwait(false);    
534
                        }
535

    
536
                        
537
                        await InitializeSelectiveFolders(newAccount, client);
538

    
539

    
540
                        //TODO:Add the "pithos" container as a default selection                   
541

    
542
                        _accountsToAdd.Add(newAccount);
543
                        var accountVm = new AccountViewModel(newAccount);
544
                        (Accounts as IProducerConsumerCollection<AccountViewModel>).TryAdd(accountVm);
545
                        CurrentAccount = accountVm;
546
                    }
547
                    NotifyOfPropertyChange(() => Accounts);
548
                    NotifyOfPropertyChange(() => Settings);
549
                }
550
                catch (WebException exc)
551
                {
552
                    Log.ErrorFormat("[Add Account] Connectivity Error: {0}", exc);
553
                    MessageBox.Show("Unable to connect to Pithos. Please try again later", "Connectivity Error",
554
                                    MessageBoxButton.OK, MessageBoxImage.Exclamation);
555
                }
556
            }
557

    
558

    
559

    
560
        }
561

    
562
        private async Task InitializeSelectiveFolders(AccountSettings newAccount, CloudFilesClient client,
563
                                                      int retries = 3)
564
        {
565
            while (true)
566
            {
567
                try
568
                {
569
                    
570

    
571
                    var containers = await client.ListContainers(newAccount.AccountName).ConfigureAwait(false);
572
                    var containerUris = from container in containers
573
                                        select String.Format(@"{0}/v1/{1}/{2}",
574
                                                             newAccount.ServerUrl, newAccount.AccountName,
575
                                                             container.Name);
576
                    lock (newAccount.SelectiveFolders)
577
                    {
578
                        newAccount.SelectiveFolders.AddRange(containerUris.ToArray());
579
                    }
580

    
581
                    var objectInfos = (from container in containers
582
                                       from dir in client.ListObjects(newAccount.AccountName, container.Name)
583
                                       where container.Name.ToString() != "trash"
584
                                       select dir).ToList();
585
                    var tree = objectInfos.ToTree();
586

    
587
                    var selected = (from root in tree
588
                                    from child in root
589
                                    select child.Uri.ToString()).ToArray();
590
                    lock (newAccount.SelectiveFolders)
591
                    {
592
                        newAccount.SelectiveFolders.AddRange(selected);
593
                    }
594
                    return;
595
                }
596
                catch (WebException)
597
                {
598
                    if (retries > 0)
599
                        retries--;
600
                    else
601
                        throw;
602
                }
603
            }
604
        }
605

    
606
/*
607
        public void AddPithosAccount()
608
       {
609
            var credentials=PithosAccount.RetrieveCredentials(null);
610
            if (credentials == null)
611
                return;
612
            var account = Settings.Accounts.FirstOrDefault(act => act.AccountName == credentials.UserName);
613
            var accountVM = new AccountViewModel(account);
614
            if (account == null)
615
            {
616
                account=new AccountSettings{
617
                    AccountName=credentials.UserName,
618
                    ApiKey=credentials.Password
619
                };
620
                Settings.Accounts.Add(account);
621
                accountVM = new AccountViewModel(account);
622
                (Accounts as IProducerConsumerCollection<AccountViewModel>).TryAdd(accountVM);
623
            }
624
            else
625
            {
626
                account.ApiKey=credentials.Password;
627
            }
628
            //SelectedAccountIndex= Settings.Accounts.IndexOf(account);
629
            CurrentAccount = accountVM;
630
            NotifyOfPropertyChange(() => Accounts);
631
            NotifyOfPropertyChange(()=>Settings);                       
632
       }
633
*/
634

    
635

    
636
        private readonly List<AccountSettings> _accountsToRemove = new List<AccountSettings>();
637

    
638
        public void RemoveAccount()
639
        {
640
            Accounts.TryRemove(CurrentAccount);
641
            _accountsToRemove.Add(CurrentAccount.Account);
642

    
643
            CurrentAccount = null;
644
            NotifyOfPropertyChange(() => Accounts);
645

    
646

    
647
            //NotifyOfPropertyChange("Settings.Accounts");
648
        }
649

    
650
        public bool CanRemoveAccount
651
        {
652
            get { return (CurrentAccount != null); }
653
        }
654

    
655
        public bool CanClearAccountCache
656
        {
657
            get { return (CurrentAccount != null); }
658
        }
659

    
660
        public void ClearAccountCache()
661
        {
662
            if (MessageBoxResult.Yes ==
663
                MessageBox.Show("You are about to delete all partially downloaded files from the account's cache.\n" +
664
                                " You will have to download all partially downloaded data again\n" +
665
                                "This change can not be undone\n\n" +
666
                                "Do you wish to delete all partially downloaded data?",
667
                                "Warning! Clearing account cache",
668
                                MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No))
669
            {
670

    
671
                var cachePath = Path.Combine(CurrentAccount.RootPath, FolderConstants.CacheFolder);
672
                var dir = new DirectoryInfo(cachePath);
673
                //The file may not exist if we just created the account
674
                if (!dir.Exists)
675
                    return;
676
                dir.EnumerateFiles().Apply(file => file.Delete());
677
                dir.EnumerateDirectories().Apply(folder => folder.Delete(true));
678
            }
679
        }
680

    
681

    
682
        public bool ExtensionsActivated
683
        {
684
            get { return Settings.ExtensionsActivated; }
685
            set
686
            {
687
                if (Settings.ExtensionsActivated == value)
688
                    return;
689

    
690
                Settings.ExtensionsActivated = value;
691

    
692
/*
693
                if (value)
694
                    _extensionController.RegisterExtensions();
695
                else
696
                {
697
                    _extensionController.UnregisterExtensions();
698
                }
699
*/
700
                NotifyOfPropertyChange(() => ExtensionsActivated);
701
            }
702
        }
703

    
704
        public bool DebugLoggingEnabled
705
        {
706
            get { return Settings.DebugLoggingEnabled; }
707
            set
708
            {
709
                Settings.DebugLoggingEnabled = value;
710
                NotifyOfPropertyChange(() => DebugLoggingEnabled);
711
            }
712
        }
713

    
714
        public bool IgnoreCertificateErrors
715
        {
716
            get { return Settings.IgnoreCertificateErrors; }
717
            set
718
            {
719
                Settings.IgnoreCertificateErrors = value;
720
                NotifyOfPropertyChange(() => IgnoreCertificateErrors);
721
            }
722
        }
723

    
724
        #endregion
725

    
726
        /* private int _selectedAccountIndex;
727
        public int SelectedAccountIndex
728
        {
729
            get { return _selectedAccountIndex; }
730
            set
731
            {
732
                //var accountCount=Settings.Accounts.Count;
733
                //if (accountCount == 0)
734
                //    return;
735
                //if (0 <= value && value < accountCount)
736
                //    _selectedAccountIndex = value;
737
                //else
738
                //    _selectedAccountIndex = 0;
739
                _selectedAccountIndex = value;
740
                NotifyOfPropertyChange(() => CurrentAccount);
741
                NotifyOfPropertyChange(() => CanRemoveAccount);
742
                NotifyOfPropertyChange(()=>SelectedAccountIndex);
743
            }
744
        }*/
745

    
746
        private AccountViewModel _currentAccount;
747
        private readonly IWindowManager _windowManager;
748
        private readonly string _shortcutPath;
749

    
750

    
751

    
752
        public AccountViewModel CurrentAccount
753
        {
754
            get { return _currentAccount; }
755
            set
756
            {
757
                _currentAccount = value;
758

    
759
                if (_currentAccount != null)
760
                    _currentAccount.PropertyChanged += (o, e) => NotifyOfPropertyChange(() => CanSelectiveSyncFolders);
761

    
762
                NotifyOfPropertyChange(() => CurrentAccount);
763
                NotifyOfPropertyChange(() => CanRemoveAccount);
764
                NotifyOfPropertyChange(() => CanSelectiveSyncFolders);
765
                NotifyOfPropertyChange(() => CanMoveAccountFolder);
766
                NotifyOfPropertyChange(() => CanClearAccountCache);
767
                NotifyOfPropertyChange(() => CanWipeAccount);
768
            }
769
        }
770

    
771
/*
772
        public AccountSettings CurrentAccount
773
        {
774
            get {
775
                if (0 <= SelectedAccountIndex && SelectedAccountIndex < Settings.Accounts.Count)                    
776
                    return Settings.Accounts[SelectedAccountIndex];
777
                return null;
778
            }
779

    
780
        }
781
*/
782

    
783

    
784
        public bool CanMoveAccountFolder
785
        {
786
            get { return CurrentAccount != null; }
787
        }
788

    
789
        public void MoveAccountFolder()
790
        {
791

    
792
            using (var dlg = new FolderBrowserDialog())
793
            {
794
                var currentFolder = CurrentAccount.RootPath;
795
                dlg.SelectedPath = currentFolder;
796
                //Ask the user to select a folder
797
                //Note: We need a parent window here, which we retrieve with GetView            
798
                var view = (Window) GetView();
799
                if (DialogResult.OK != dlg.ShowDialog(new Wpf32Window(view)))
800
                    return;
801

    
802
                var newPath = dlg.SelectedPath;
803
                //Find the account's monitor and stop it
804
                PithosMonitor monitor;
805
                if (Shell.Monitors.TryGetValue(CurrentAccount.AccountKey, out monitor))
806
                {
807
                    //Problem: Doesn't stop the poll agent
808
                    monitor.Stop();
809

    
810
                    monitor.MoveRootFolder(newPath);
811

    
812
                   
813
                }
814
                //Replace the old rootpath with the new
815
                CurrentAccount.RootPath = newPath;
816
                //TODO: This will save all settings changes. Too coarse grained, need to fix at a later date
817
                Settings.Save();
818
                //And start the monitor on the new RootPath            
819
                if (monitor != null)
820
                {
821
                    monitor.RootPath = newPath;
822
                    if (CurrentAccount.IsActive)
823
                        Shell.StartMonitor(monitor);
824
                        
825
                }
826
                else
827
                    Shell.MonitorAccount(CurrentAccount.Account);
828
                //Finally, notify that the Settings, CurrentAccount have changed
829
                NotifyOfPropertyChange(() => CurrentAccount);
830
                NotifyOfPropertyChange(() => Settings);
831

    
832
            }
833
        }
834

    
835
    }
836
}