Statistics
| Branch: | Revision:

root / trunk / Pithos.Client.WPF / Preferences / PreferencesViewModel.cs @ 31c97141

History | View | Annotate | Download (18.2 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
// </copyright>
44
// -----------------------------------------------------------------------
45

    
46
using System.Collections.Concurrent;
47
using System.ComponentModel.Composition;
48
using System.Diagnostics;
49
using System.IO;
50
using System.Net;
51
using System.Threading.Tasks;
52
using System.Windows;
53
using System.Windows.Forms;
54
using Caliburn.Micro;
55
using Pithos.Client.WPF.Configuration;
56
using Pithos.Client.WPF.SelectiveSynch;
57
using Pithos.Core;
58
using Pithos.Interfaces;
59
using System;
60
using System.Linq;
61
using Screen = Caliburn.Micro.Screen;
62

    
63
namespace Pithos.Client.WPF.Preferences
64
{
65
    /// <summary>
66
    /// TODO: Update summary.
67
    /// </summary>
68
    [Export]
69
    public class PreferencesViewModel : Screen
70
    {
71
        private IEventAggregator _events;
72

    
73
        //Logging in the Pithos client is provided by log4net
74
        private static readonly log4net.ILog Log = log4net.LogManager.GetLogger("Pithos");
75

    
76
        private PithosSettings _settings;
77
        public PithosSettings Settings
78
        {
79
            get { return _settings; }
80
            set
81
            {
82
                _settings = value;
83
                NotifyOfPropertyChange(()=>Settings);
84
            }
85
        }
86

    
87
        private ObservableConcurrentCollection<AccountViewModel> _accounts;
88
        public ObservableConcurrentCollection<AccountViewModel> Accounts
89
        {
90
            get { return _accounts; }
91
            set 
92
            { 
93
                _accounts = value;
94
                NotifyOfPropertyChange(()=>Accounts);
95
            }
96
        }
97
        
98
        public bool StartOnSystemStartup { get; set; }
99

    
100
        public ShellViewModel Shell { get;  set; }
101
        //ShellExtensionController _extensionController=new ShellExtensionController();
102

    
103
        public PreferencesViewModel(IWindowManager windowManager, IEventAggregator events, ShellViewModel shell, PithosSettings settings, string currentTab)
104
        {
105
            _windowManager = windowManager;
106
            _events = events;
107

    
108
            DisplayName = "Pithos Preferences";
109
            Shell = shell;
110
            
111
            Settings=settings;
112
            Accounts = new ObservableConcurrentCollection<AccountViewModel>();
113
            if (settings.Accounts == null)
114
            {
115
                settings.Accounts=new AccountsCollection();
116
                settings.Save();
117
            }
118
            var accountVMs = from account in settings.Accounts
119
                             select new AccountViewModel(account);
120

    
121
            Accounts.AddFromEnumerable(accountVMs);
122
            
123
            var startupPath = Environment.GetFolderPath(Environment.SpecialFolder.Startup);
124
            _shortcutPath = Path.Combine(startupPath, "Pithos.lnk");
125

    
126

    
127
            StartOnSystemStartup = File.Exists(_shortcutPath);
128

    
129
            SelectedTab = currentTab;
130
        }
131

    
132
        private string _selectedTab="General";
133
        public string SelectedTab
134
        {
135
            get { return _selectedTab; }
136
            set
137
            {
138
                _selectedTab = value??"General";
139
                NotifyOfPropertyChange(()=>SelectedTab);
140
                NotifyOfPropertyChange(() => AccountTabSelected);
141
            }
142
        }
143

    
144

    
145
        public bool AccountTabSelected
146
        {
147
            get { return _selectedTab == "AccountTab"; }
148
        }
149
        #region Preferences Properties
150

    
151
        private bool _noProxy;
152
        public bool NoProxy
153
        {
154
            get { return _noProxy; }
155
            set
156
            {
157
                _noProxy = value;
158
                NotifyOfPropertyChange(()=>NoProxy);
159
            }
160
        }
161

    
162

    
163
        private bool _defaultProxy;
164

    
165
        public bool DefaultProxy
166
        {
167
            get { return _defaultProxy; }
168
            set
169
            {
170
                _defaultProxy = value;
171
                NotifyOfPropertyChange(() => DefaultProxy);
172
            }
173
        }
174

    
175

    
176
        private bool _manualProxy;
177

    
178
        public bool ManualProxy
179
        {
180
            get { return _manualProxy; }
181
            set
182
            {
183
                _manualProxy = value;
184
                NotifyOfPropertyChange(() => ManualProxy);
185
            }
186
        }
187
        #endregion
188

    
189

    
190
        public int StartupDelay
191
        {
192
            get { return (int) Settings.StartupDelay.TotalMinutes; }
193
            set
194
            {
195
                if (value<0)
196
                    throw new ArgumentOutOfRangeException("value","The Startup Delay must be greater or equal to 0");
197
                Settings.StartupDelay = TimeSpan.FromMinutes(value);
198
                NotifyOfPropertyChange(()=>StartupDelay);
199
            }
200
        }
201
       
202
        #region Commands
203
        
204
        public bool CanSelectiveSyncFolders
205
        {
206
            get { return CurrentAccount != null; }
207
        }
208

    
209
        public void SelectiveSyncFolders()
210
        {
211
            var monitor = Shell.Monitors[CurrentAccount.AccountName];
212
            
213

    
214
            var model = new SelectiveSynchViewModel(monitor,_events,CurrentAccount.Account);
215
            if (_windowManager.ShowDialog(model) == true)
216
            {
217
                
218
            }
219
        }
220

    
221
        public async Task RefreshApiKey()
222
        {
223
            _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 });
224

    
225
            //var userName = CurrentAccount.AccountName;
226
            try
227
            {
228

    
229
                var credentials = await PithosAccount.RetrieveCredentials(Settings.PithosLoginUrl);
230

    
231
                var account = Accounts.First(act => act.AccountName == credentials.UserName);
232
                //The server may return credentials for a different account
233
                var monitor =  Shell.Monitors[account.AccountName];
234
                account.ApiKey = credentials.Password;
235
                monitor.ApiKey = credentials.Password;
236
                account.IsExpired = false;
237
                Settings.Save();
238
                TaskEx.Delay(10000).ContinueWith(_ =>Shell.MonitorAccount(account.Account));
239
                NotifyOfPropertyChange(() => Accounts);
240
            }
241
            catch (AggregateException exc)
242
            {
243
                string message = String.Format("API Key retrieval failed");
244
                Log.Error(message, exc.InnerException);
245
                _events.Publish(new Notification { Title = "Authorization failed", Message = message, Level = TraceLevel.Error });
246
            }
247
            catch (Exception exc)
248
            {
249
                string message = String.Format("API Key retrieval failed");
250
                Log.Error(message, exc);
251
                _events.Publish(new Notification { Title = "Authorization failed", Message = message, Level = TraceLevel.Error });
252
            }
253

    
254
        }
255

    
256
    
257
        public void SaveChanges()
258
        {
259
            DoSave();
260
            TryClose(true);
261
        }
262

    
263
        public void RejectChanges()
264
        {
265
            Settings.Reload();
266
            TryClose(false);
267
        }
268

    
269
        public void ApplyChanges()
270
        {
271
            DoSave();
272
        }
273

    
274
        private void DoSave()
275
        {
276
            Settings.Save();
277
            //SetStartupMode();            
278

    
279
            foreach (var account in Settings.Accounts)
280
            {                                
281
                Shell.MonitorAccount(account);
282
            }
283

    
284
            NotifyOfPropertyChange(()=>Settings);
285
        }
286

    
287
     /*   public void ChangePithosFolder()
288
        {
289
            var browser = new FolderBrowserDialog();
290
            browser.SelectedPath = Settings.PithosPath;
291
            var result = browser.ShowDialog((IWin32Window)GetView());
292
            if (result == DialogResult.OK)
293
            {
294
                var newPath = browser.SelectedPath;
295
                var accountName = CurrentAccount.AccountName;
296
                var monitor = Shell.Monitors[accountName];
297
                monitor.Stop();
298
                
299
                Shell.Monitors.Remove(accountName);
300

    
301
                Directory.Move(Settings.PithosPath, newPath);
302
                Settings.PithosPath = newPath;
303
                Settings.Save();
304

    
305
                Shell.MonitorAccount(CurrentAccount);
306

    
307
                NotifyOfPropertyChange(() => Settings);                
308
            }
309
        }
310
*/
311

    
312
        
313

    
314
       public void AddAccount()
315
       {
316
           var wizard = new AddAccountViewModel();
317
           if (_windowManager.ShowDialog(wizard) == true)
318
           {
319
               string selectedPath = wizard.AccountPath;
320
               var initialRootPath = Path.Combine(selectedPath, "Okeanos");
321
               var actualRootPath= initialRootPath;
322
               int attempt = 1;
323
               while (Directory.Exists(actualRootPath) || File.Exists(actualRootPath))
324
               {
325
                   actualRootPath = String.Format("{0} {1}", initialRootPath,attempt++);
326
               }
327

    
328
               var newAccount = new AccountSettings
329
                                    {
330
                                        AccountName = wizard.AccountName,
331
                                        ServerUrl=wizard.CurrentServer,
332
                                        ApiKey=wizard.Token,
333
                                        RootPath = actualRootPath,
334
                                        IsActive=wizard.IsAccountActive
335
                                    };
336
               Settings.Accounts.Add(newAccount);
337
               var accountVM = new AccountViewModel(newAccount);
338
               (Accounts as IProducerConsumerCollection<AccountViewModel>).TryAdd(accountVM);
339
               CurrentAccount = accountVM;
340
               NotifyOfPropertyChange(() => Accounts);
341
               NotifyOfPropertyChange(() => Settings);   
342
           }
343

    
344

    
345
            
346
       }
347

    
348
        public async void AddPithosAccount()
349
       {
350
            var credentials=await PithosAccount.RetrieveCredentials(Settings.PithosLoginUrl);
351
            var account = Settings.Accounts.FirstOrDefault(act => act.AccountName == credentials.UserName);
352
            var accountVM = new AccountViewModel(account);
353
            if (account == null)
354
            {
355
                account=new AccountSettings{
356
                    AccountName=credentials.UserName,
357
                    ApiKey=credentials.Password
358
                };
359
                Settings.Accounts.Add(account);
360
                accountVM = new AccountViewModel(account);
361
                (Accounts as IProducerConsumerCollection<AccountViewModel>).TryAdd(accountVM);
362
            }
363
            else
364
            {
365
                account.ApiKey=credentials.Password;
366
            }
367
            //SelectedAccountIndex= Settings.Accounts.IndexOf(account);
368
            CurrentAccount = accountVM;
369
            NotifyOfPropertyChange(() => Accounts);
370
            NotifyOfPropertyChange(()=>Settings);                       
371
       }
372

    
373
        public void RemoveAccount()
374
        {
375
            var accountName = CurrentAccount.AccountName;
376
            Settings.Accounts.Remove(CurrentAccount.Account);
377

    
378
            Accounts.TryRemove(CurrentAccount);
379
            
380
            
381
            CurrentAccount = null;
382
            //Accounts = Settings.Accounts;
383
            //Settings.Save();            
384
            Shell.RemoveMonitor(accountName);
385
            NotifyOfPropertyChange(() => Accounts);
386
            NotifyOfPropertyChange(() => Settings);                       
387
            
388
            //NotifyOfPropertyChange("Settings.Accounts");
389
        }
390

    
391
        public bool CanRemoveAccount
392
        {
393
            get { return (CurrentAccount != null); }
394
        }
395

    
396

    
397

    
398
        public bool ExtensionsActivated
399
        {
400
            get { return Settings.ExtensionsActivated; }
401
            set
402
            {
403
                if (Settings.ExtensionsActivated == value)
404
                    return;
405

    
406
                Settings.ExtensionsActivated = value;
407

    
408
/*
409
                if (value)
410
                    _extensionController.RegisterExtensions();
411
                else
412
                {
413
                    _extensionController.UnregisterExtensions();
414
                }
415
*/
416
                NotifyOfPropertyChange(() => ExtensionsActivated);
417
            }
418
        }
419

    
420
       
421
        #endregion
422

    
423
       /* private int _selectedAccountIndex;
424
        public int SelectedAccountIndex
425
        {
426
            get { return _selectedAccountIndex; }
427
            set
428
            {
429
                //var accountCount=Settings.Accounts.Count;
430
                //if (accountCount == 0)
431
                //    return;
432
                //if (0 <= value && value < accountCount)
433
                //    _selectedAccountIndex = value;
434
                //else
435
                //    _selectedAccountIndex = 0;
436
                _selectedAccountIndex = value;
437
                NotifyOfPropertyChange(() => CurrentAccount);
438
                NotifyOfPropertyChange(() => CanRemoveAccount);
439
                NotifyOfPropertyChange(()=>SelectedAccountIndex);
440
            }
441
        }*/
442

    
443
        private AccountViewModel _currentAccount;
444
        private IWindowManager _windowManager;
445
        private string _shortcutPath;
446

    
447

    
448
        
449
        public AccountViewModel CurrentAccount
450
        {
451
            get { return _currentAccount; }
452
            set
453
            {
454
                _currentAccount = value;
455
                NotifyOfPropertyChange(()=>CurrentAccount);
456
                NotifyOfPropertyChange(() => CanRemoveAccount);
457
                NotifyOfPropertyChange(() => CanSelectiveSyncFolders);
458
                NotifyOfPropertyChange(() => CanMoveAccountFolder);
459
            }
460
        }
461

    
462
/*
463
        public AccountSettings CurrentAccount
464
        {
465
            get {
466
                if (0 <= SelectedAccountIndex && SelectedAccountIndex < Settings.Accounts.Count)                    
467
                    return Settings.Accounts[SelectedAccountIndex];
468
                return null;
469
            }
470

    
471
        }
472
*/
473

    
474

    
475
        public bool CanMoveAccountFolder
476
        {
477
            get { return CurrentAccount != null; }
478
        }
479

    
480
    public void MoveAccountFolder()
481
    {
482

    
483
        using (var dlg = new FolderBrowserDialog())
484
        {
485
            var currentFolder = CurrentAccount.RootPath;
486
            dlg.SelectedPath = currentFolder;
487
            //Ask the user to select a folder
488
            //Note: We need a parent window here, which we retrieve with GetView            
489
            var view = (Window)GetView();            
490
            if (DialogResult.OK != dlg.ShowDialog(new Wpf32Window(view)))
491
                return;            
492

    
493
            var newPath= dlg.SelectedPath;                
494
            //Find the account's monitor and stop it
495
            PithosMonitor monitor;
496
            if (Shell.Monitors.TryGetValue(CurrentAccount.AccountName, out monitor))
497
            {
498
                monitor.Stop();
499

    
500

    
501
                var oldPath = monitor.RootPath;
502
                //The old directory may not exist eg. if we create an account for the first time
503
                if (Directory.Exists(oldPath))
504
                {
505
                    //If it does, do the move
506

    
507
                    //Now Create all of the directories
508
                    foreach (string dirPath in Directory.EnumerateDirectories(oldPath, "*",
509
                                                           SearchOption.AllDirectories))
510
                        Directory.CreateDirectory(dirPath.Replace(oldPath, newPath));
511

    
512
                    //Copy all the files
513
                    foreach (string newFilePath in Directory.EnumerateFiles(oldPath, "*.*",
514
                                                                            SearchOption.AllDirectories))
515
                        File.Copy(newFilePath, newFilePath.Replace(oldPath, newPath));
516

    
517
                    Directory.Delete(oldPath, true);
518

    
519
                    //We also need to change the path of the existing file states
520
                    if (monitor != null)
521
                        monitor.MoveFileStates(oldPath, newPath);
522
                }
523
            }
524
            //Replace the old rootpath with the new
525
            CurrentAccount.RootPath = newPath;
526
            //TODO: This will save all settings changes. Too coarse grained, need to fix at a later date
527
            Settings.Save();            
528
            //And start the monitor on the new RootPath            
529
            if (monitor != null)
530
            {
531
                monitor.RootPath = newPath;
532
                if (CurrentAccount.IsActive)
533
                    monitor.Start();
534
            }
535
            else
536
                Shell.MonitorAccount(CurrentAccount.Account);
537
            //Finally, notify that the Settings, CurrentAccount have changed
538
            NotifyOfPropertyChange(() => CurrentAccount);
539
            NotifyOfPropertyChange(() => Settings);
540

    
541
        }
542
    }
543
    }
544
}