Version
[pithos-ms-client] / trunk / Pithos.Client.WPF / Shell / ShellViewModel.cs
index da44496..f86f46e 100644 (file)
@@ -97,7 +97,7 @@ namespace Pithos.Client.WPF {
                public PithosSettings Settings { get; private set; }
 
 
-               private readonly ConcurrentDictionary<string, PithosMonitor> _monitors = new ConcurrentDictionary<string, PithosMonitor>();
+               private readonly ConcurrentDictionary<Uri, PithosMonitor> _monitors = new ConcurrentDictionary<Uri, PithosMonitor>();
                ///<summary>
                /// Dictionary of account monitors, keyed by account
                ///</summary>
@@ -107,7 +107,7 @@ namespace Pithos.Client.WPF {
                ///</remarks>
                // TODO: Does the Shell REALLY need access to the monitors? Could we achieve the same results with a better design?
                // TODO: The monitors should be internal to Pithos.Core, even though exposing them makes coding of the Object and Container windows easier
-               public ConcurrentDictionary<string, PithosMonitor> Monitors
+               public ConcurrentDictionary<Uri, PithosMonitor> Monitors
                {
                        get { return _monitors; }
                }
@@ -123,7 +123,10 @@ namespace Pithos.Client.WPF {
         private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
 
            private readonly PollAgent _pollAgent;
+           private readonly NetworkAgent _networkAgent;
 
+           [Import]
+           public Selectives Selectives { get; set; }
 
            private MiniStatusViewModel _miniStatus;
 
@@ -150,7 +153,7 @@ namespace Pithos.Client.WPF {
                /// The PithosSettings class encapsulates the app's settings to abstract their storage mechanism (App settings, a database or registry)
                ///</remarks>
                [ImportingConstructor]          
-               public ShellViewModel(IWindowManager windowManager, IEventAggregator events, IStatusChecker statusChecker, PithosSettings settings,PollAgent pollAgent)
+               public ShellViewModel(IWindowManager windowManager, IEventAggregator events, IStatusChecker statusChecker, PithosSettings settings,PollAgent pollAgent,NetworkAgent networkAgent)
                {
                        try
                        {
@@ -164,6 +167,7 @@ namespace Pithos.Client.WPF {
                                _events.Subscribe(this);
 
                            _pollAgent = pollAgent;
+                           _networkAgent = networkAgent;
                                Settings = settings;
 
                                Proxy.SetFromSettings(settings);
@@ -195,13 +199,27 @@ namespace Pithos.Client.WPF {
                VersionMessage = String.Format("Pithos+ {0}", fileVersion.FileVersion);
            }
 
-        public void OnStatusAction()
+        public void CurrentSyncStatus()
         {
-            if (Accounts.Count==0)
+            if (Accounts.Count == 0)
             {
                 ShowPreferences("AccountTab");
             }
+            else
+            {
+                if (!_statusVisible)
+                    _windowManager.ShowWindow(MiniStatus);
+                else
+                {
+                    if (MiniStatus.IsActive)
+                        MiniStatus.TryClose();
+                }
+                _statusVisible = !_statusVisible;
+
+                NotifyOfPropertyChange(() => MiniStatusCaption);
+            }
         }
+
            protected override void OnActivate()
                {
                        base.OnActivate();
@@ -262,17 +280,15 @@ namespace Pithos.Client.WPF {
                {
                        try
                        {
+                if (Settings.IgnoreCertificateErrors)
+                {
+                    ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;
+                }
+                    
                                var accounts = Settings.Accounts.Select(MonitorAccount);
                                await TaskEx.WhenAll(accounts);
                                _statusService = StatusService.Start();
 
-/*
-                               foreach (var account in Settings.Accounts)
-                               {
-                                       await MonitorAccount(account);
-                               }
-*/
-                               
                        }
                        catch (AggregateException exc)
                        {
@@ -302,7 +318,11 @@ namespace Pithos.Client.WPF {
                                PithosMonitor monitor;
                                var accountName = account.AccountName;
 
-                               if (_monitors.TryGetValue(accountName, out monitor))
+                           MigrateFolders(account);
+
+                           Selectives.SetIsSelectiveEnabled(account.AccountKey, account.SelectiveSyncEnabled);
+
+                               if (Monitors.TryGetValue(account.AccountKey, out monitor))
                                {
                                        //If the account is active
                     if (account.IsActive)
@@ -319,7 +339,7 @@ namespace Pithos.Client.WPF {
                     {
                         //If the account is inactive
                         //Stop and remove the monitor
-                        RemoveMonitor(accountName);
+                        RemoveMonitor(account.ServerUrl,accountName);
                     }
                                        return;
                                }
@@ -338,7 +358,7 @@ namespace Pithos.Client.WPF {
 
                                monitor.AuthenticationUrl = account.ServerUrl;
 
-                               _monitors[accountName] = monitor;
+                               Monitors[account.AccountKey] = monitor;
 
                                if (account.IsActive)
                                {
@@ -351,8 +371,21 @@ namespace Pithos.Client.WPF {
                        });
                }
 
+           private void MigrateFolders(AccountSettings account)
+           {
+               var oldOthersFolder=Path.Combine(account.RootPath, FolderConstants.OldOthersFolder);
+               var newOthersFolder = Path.Combine(account.RootPath, FolderConstants.OthersFolder);
+               var oldFolder = new DirectoryInfo(oldOthersFolder);
+               var newFolder = new DirectoryInfo(newOthersFolder);
+
+            if (oldFolder.Exists && !newFolder.Exists)
+            {
+                oldFolder.MoveTo(newOthersFolder);
+            }
+           }
 
-               protected override void OnViewLoaded(object view)
+
+           protected override void OnViewLoaded(object view)
                {
                        UpdateStatus();
                        var window = (Window)view;            
@@ -377,7 +410,6 @@ namespace Pithos.Client.WPF {
 
         public string VersionMessage { get; set; }
 
-           private string _tooltipMessage;
            public string TooltipMessage
            {
                get
@@ -386,6 +418,22 @@ namespace Pithos.Client.WPF {
                }
            }
 
+        public string TooltipMiniStatus
+        {
+            get
+            {
+                return String.Format("{0}\r\n{1}", "Status Window", "Enable / Disable the status window");
+            }
+        }
+
+        public string ToggleStatusWindowMessage
+        {
+            get
+            {
+                return String.Format("{0}" + Environment.NewLine + "{1} Toggle Mini Status");
+            }
+        }
+
            private readonly ObservableConcurrentCollection<AccountInfo> _accounts = new ObservableConcurrentCollection<AccountInfo>();
                public ObservableConcurrentCollection<AccountInfo> Accounts
                {
@@ -442,6 +490,11 @@ namespace Pithos.Client.WPF {
 
                #region Commands
 
+        public void CancelCurrentOperation()
+        {
+            _networkAgent.CancelCurrentOperation();
+        }
+
         public void ShowPreferences()
         {
             ShowPreferences(null);
@@ -450,6 +503,7 @@ namespace Pithos.Client.WPF {
                public void ShowPreferences(string currentTab)
                {
                        //Settings.Reload();
+            
                    var preferences = new PreferencesViewModel(_windowManager, _events, this, Settings,currentTab);
                    _windowManager.ShowDialog(preferences);
                        
@@ -508,18 +562,13 @@ namespace Pithos.Client.WPF {
                }
            }
 
-           public void ShowMiniStatus()
-        {            
-            if (!_statusVisible)
-                _windowManager.ShowWindow(MiniStatus);
-            else
-            {           
-                if (MiniStatus.IsActive)
-                    MiniStatus.TryClose();
-            }
-            _statusVisible=!_statusVisible;
-
-               NotifyOfPropertyChange(()=>MiniStatusCaption);
+           public bool HasConflicts
+           {
+            get { return true; }
+           }
+        public void ShowConflicts()
+        {
+            _windowManager.ShowWindow(IoC.Get<ConflictsViewModel>());            
         }
 
            /// <summary>
@@ -615,9 +664,8 @@ namespace Pithos.Client.WPF {
                {
                        if (currentInfo==null)
                                throw new ArgumentNullException("currentInfo");
-                       Contract.EndContractBlock();
-
-                       var monitor = Monitors[currentInfo.Account];
+                       Contract.EndContractBlock();                
+            var monitor = Monitors[currentInfo.AccountKey];
                        var newInfo=monitor.CloudClient.GetObjectInfo(currentInfo.Account, currentInfo.Container, currentInfo.Name);
                        return newInfo;
                }
@@ -628,39 +676,64 @@ namespace Pithos.Client.WPF {
                                throw new ArgumentNullException("container");
                        Contract.EndContractBlock();
 
-                       var monitor = Monitors[container.Account];
+                       var monitor = Monitors[container.AccountKey];
                        var newInfo = monitor.CloudClient.GetContainerInfo(container.Account, container.Name);
                        return newInfo;
                }
 
+           private bool _isPaused;
+           public bool IsPaused
+           {
+               get { return _isPaused; }
+               set
+               {
+                   _isPaused = value;
+                PauseSyncCaption = IsPaused ? "Resume syncing" : "Pause syncing";
+                var iconKey = IsPaused ? "TraySyncPaused" : "TrayInSynch";
+                StatusIcon = String.Format(@"../Images/{0}.ico", iconKey);
+
+                NotifyOfPropertyChange(() => IsPaused);
+               }
+           }
 
-               public void ToggleSynching()
+           public void ToggleSynching()
                {
-                       bool isPaused=false;
-                       foreach (var pair in Monitors)
+                       IsPaused=!IsPaused;
+                       foreach (var monitor in Monitors.Values)
                        {
-                               var monitor = pair.Value;
-                               monitor.Pause = !monitor.Pause;
-                               isPaused = monitor.Pause;
+                           monitor.Pause = IsPaused ;
                        }
-                        
+            _pollAgent.Pause = IsPaused;
+            _networkAgent.Pause = IsPaused;
+
 
-                       PauseSyncCaption = isPaused ? "Resume syncing" : "Pause syncing";
-                       var iconKey = isPaused? "TraySyncPaused" : "TrayInSynch";
-                       StatusIcon = String.Format(@"../Images/{0}.ico", iconKey);
                }
 
-               public void ExitPithos()
-               {
-                       foreach (var pair in Monitors)
-                       {
-                               var monitor = pair.Value;
-                               monitor.Stop();
-                       }
+        public void ExitPithos()
+        {
+            try
+            {
 
-                       ((Window)GetView()).Close();
-               }
-               #endregion
+                foreach (var monitor in Monitors.Select(pair => pair.Value))
+                {
+                    monitor.Stop();
+                }
+
+                var view = GetView() as Window;
+                if (view != null)
+                    view.Close();
+            }
+            catch (Exception exc)
+            {
+                Log.Info("Exception while exiting", exc);                
+            }
+            finally
+            {
+                Application.Current.Shutdown();
+            }
+        }
+
+           #endregion
 
 
                private readonly Dictionary<PithosStatus, StatusInfo> _iconNames = new List<StatusInfo>
@@ -697,9 +770,20 @@ namespace Pithos.Client.WPF {
             SetPithosStatus(status);
         }
 
+         /*  public Notifier GetNotifier(Notification startNotification, Notification endNotification)
+           {
+               return new Notifier(this, startNotification, endNotification);
+           }*/
 
+           public Notifier GetNotifier(string startMessage, string endMessage, params object[] args)
+           {
+               return new Notifier(this, 
+                new StatusNotification(String.Format(startMessage,args)), 
+                new StatusNotification(String.Format(endMessage,args)));
+           }
 
-               ///<summary>
+
+           ///<summary>
                /// Updates the visual status indicators of the application depending on status changes, e.g. icon, stat                
                ///</summary>
                public void UpdateStatus()
@@ -745,7 +829,7 @@ namespace Pithos.Client.WPF {
                                                                var message = String.Format("API Key Expired for {0}. Starting Renewal",
                                                                                                                        monitor.UserName);
                                                                Log.Error(message, exc);
-                                                       var account = Settings.Accounts.Find(acc => acc.AccountName == monitor.UserName);                                
+                                var account = Settings.Accounts.Find(acc => acc.AccountKey == new Uri(new Uri(monitor.AuthenticationUrl), monitor.UserName));                                
                                                        account.IsExpired = true;
                                 Notify(new ExpirationNotification(account));
                                                                //TryAuthorize(monitor.UserName, retries).Wait();
@@ -835,7 +919,7 @@ namespace Pithos.Client.WPF {
                                account.SiteUri, Uri.EscapeDataString(account.Token),
                                Uri.EscapeDataString(account.UserName));
 
-                       if (Accounts.All(item => item.UserName != account.UserName))
+                       if (!Accounts.Any(item => item.UserName == account.UserName && item.SiteUri == account.SiteUri))
                                Accounts.TryAdd(account);
 
                }
@@ -873,20 +957,21 @@ namespace Pithos.Client.WPF {
                }
 
 
-               public void RemoveMonitor(string accountName)
+               public void RemoveMonitor(string serverUrl,string accountName)
                {
                        if (String.IsNullOrWhiteSpace(accountName))
                                return;
 
-                       var accountInfo=_accounts.FirstOrDefault(account => account.UserName == accountName);
+                       var accountInfo=_accounts.FirstOrDefault(account => account.UserName == accountName && account.StorageUri.ToString().StartsWith(serverUrl));
             if (accountInfo != null)
             {
                 _accounts.TryRemove(accountInfo);
                 _pollAgent.RemoveAccount(accountInfo);
             }
 
+            var accountKey = new Uri(new Uri(serverUrl),accountName);
                    PithosMonitor monitor;
-                       if (Monitors.TryRemove(accountName, out monitor))
+                       if (Monitors.TryRemove(accountKey, out monitor))
                        {
                                monitor.Stop();
                 //TODO: Also remove any pending actions for this account
@@ -927,14 +1012,22 @@ namespace Pithos.Client.WPF {
                
                public void Handle(SelectiveSynchChanges message)
                {
-                       var accountName = message.Account.AccountName;
-                       PithosMonitor monitor;
-                       if (_monitors.TryGetValue(accountName, out monitor))
-                       {
-                               monitor.SetSelectivePaths(message.Uris,message.Added,message.Removed);
+                   TaskEx.Run(() =>
+                   {
+                       PithosMonitor monitor;
+                       if (Monitors.TryGetValue(message.Account.AccountKey, out monitor))
+                       {
+                    Selectives.SetIsSelectiveEnabled(message.Account.AccountKey, message.Enabled);
+                           monitor.SetSelectivePaths(message.Uris, message.Added, message.Removed);
+                       }
+
+                       var account = Accounts.FirstOrDefault(acc => acc.AccountKey == message.Account.AccountKey);
+                       if (account != null)
+                       {
+                           this._pollAgent.SetSelectivePaths(account, message.Added, message.Removed);
+                       }
+                   });
 
-                       }
-                       
                }