Statistics
| Branch: | Revision:

root / trunk / Pithos.Client.WPF / Shell / ShellViewModel.cs @ 133f83c2

History | View | Annotate | Download (21.4 kB)

1 c53aa229 Panagiotis Kanavos
using System.Collections.Concurrent;
2 c53aa229 Panagiotis Kanavos
using System.Diagnostics;
3 c28a075a Panagiotis Kanavos
using System.Diagnostics.Contracts;
4 c53aa229 Panagiotis Kanavos
using System.IO;
5 c28a075a Panagiotis Kanavos
using System.Net;
6 d17258c2 Panagiotis Kanavos
using System.Reflection;
7 c53aa229 Panagiotis Kanavos
using System.Runtime.InteropServices;
8 c53aa229 Panagiotis Kanavos
using System.ServiceModel;
9 c53aa229 Panagiotis Kanavos
using System.Threading.Tasks;
10 c53aa229 Panagiotis Kanavos
using System.Windows;
11 9bae55d1 Panagiotis Kanavos
using Caliburn.Micro;
12 c53aa229 Panagiotis Kanavos
using Hardcodet.Wpf.TaskbarNotification;
13 c53aa229 Panagiotis Kanavos
using Pithos.Client.WPF.Configuration;
14 42800be8 Panagiotis Kanavos
using Pithos.Client.WPF.FileProperties;
15 d3a13891 Panagiotis Kanavos
using Pithos.Client.WPF.SelectiveSynch;
16 42800be8 Panagiotis Kanavos
using Pithos.Client.WPF.Services;
17 5cb9d74f Panagiotis Kanavos
using Pithos.Client.WPF.Shell;
18 c53aa229 Panagiotis Kanavos
using Pithos.Core;
19 c53aa229 Panagiotis Kanavos
using Pithos.Interfaces;
20 c53aa229 Panagiotis Kanavos
using System;
21 c53aa229 Panagiotis Kanavos
using System.Collections.Generic;
22 c53aa229 Panagiotis Kanavos
using System.Linq;
23 0bd56b7c Panagiotis Kanavos
using Pithos.Network;
24 c53aa229 Panagiotis Kanavos
using StatusService = Pithos.Client.WPF.Services.StatusService;
25 9bae55d1 Panagiotis Kanavos
26 9bae55d1 Panagiotis Kanavos
namespace Pithos.Client.WPF {
27 4ec636f6 Panagiotis Kanavos
	using System.ComponentModel.Composition;
28 9bae55d1 Panagiotis Kanavos
29 4ec636f6 Panagiotis Kanavos
	
30 cf761c0d Panagiotis Kanavos
	///<summary>
31 cf761c0d Panagiotis Kanavos
	/// The "shell" of the Pithos application displays the taskbar  icon, menu and notifications.
32 cf761c0d Panagiotis Kanavos
	/// The shell also hosts the status service called by shell extensions to retrieve file info
33 cf761c0d Panagiotis Kanavos
	///</summary>
34 cf761c0d Panagiotis Kanavos
	///<remarks>
35 cf761c0d Panagiotis Kanavos
	/// It is a strange "shell" as its main visible element is an icon instead of a window
36 cf761c0d Panagiotis Kanavos
	/// The shell subscribes to the following events:
37 cf761c0d Panagiotis Kanavos
	/// * Notification:  Raised by components that want to notify the user. Usually displayed in a balloon
38 cf761c0d Panagiotis Kanavos
	/// * SelectiveSynchChanges: Notifies that the user made changes to the selective synch folders for an account. Raised by the Selective Synch dialog. Located here because the monitors are here
39 cf761c0d Panagiotis Kanavos
	/// * ShowFilePropertiesEvent: Raised when a shell command requests the display of the file/container properties dialog
40 cf761c0d Panagiotis Kanavos
	///</remarks>		
41 cf761c0d Panagiotis Kanavos
	//TODO: CODE SMELL Why does the shell handle the SelectiveSynchChanges?
42 4ec636f6 Panagiotis Kanavos
	[Export(typeof(IShell))]
43 4ec636f6 Panagiotis Kanavos
	public class ShellViewModel : Screen, IStatusNotification, IShell,
44 4ec636f6 Panagiotis Kanavos
		IHandle<Notification>, IHandle<SelectiveSynchChanges>, IHandle<ShowFilePropertiesEvent>
45 4ec636f6 Panagiotis Kanavos
	{
46 cf761c0d Panagiotis Kanavos
		//The Status Checker provides the current synch state
47 cf761c0d Panagiotis Kanavos
		//TODO: Could we remove the status checker and use events in its place?
48 4f6d51d4 Panagiotis Kanavos
		private readonly IStatusChecker _statusChecker;
49 4f6d51d4 Panagiotis Kanavos
		private readonly IEventAggregator _events;
50 c53aa229 Panagiotis Kanavos
51 4ec636f6 Panagiotis Kanavos
		public PithosSettings Settings { get; private set; }
52 c53aa229 Panagiotis Kanavos
53 4ec636f6 Panagiotis Kanavos
54 4f6d51d4 Panagiotis Kanavos
        private readonly ConcurrentDictionary<string, PithosMonitor> _monitors = new ConcurrentDictionary<string, PithosMonitor>();
55 cf761c0d Panagiotis Kanavos
		///<summary>
56 cf761c0d Panagiotis Kanavos
		/// Dictionary of account monitors, keyed by account
57 cf761c0d Panagiotis Kanavos
		///</summary>
58 cf761c0d Panagiotis Kanavos
		///<remarks>
59 cf761c0d Panagiotis Kanavos
		/// One monitor class is created for each account. The Shell needs access to the monitors to execute start/stop/pause commands,
60 cf761c0d Panagiotis Kanavos
		/// retrieve account and boject info		
61 cf761c0d Panagiotis Kanavos
		///</remarks>
62 cf761c0d Panagiotis Kanavos
		// TODO: Does the Shell REALLY need access to the monitors? Could we achieve the same results with a better design?
63 cf761c0d Panagiotis Kanavos
		// TODO: The monitors should be internal to Pithos.Core, even though exposing them makes coding of the Object and Container windows easier
64 4ec636f6 Panagiotis Kanavos
        public ConcurrentDictionary<string, PithosMonitor> Monitors
65 4ec636f6 Panagiotis Kanavos
		{
66 4ec636f6 Panagiotis Kanavos
			get { return _monitors; }
67 4ec636f6 Panagiotis Kanavos
		}
68 c53aa229 Panagiotis Kanavos
69 cf761c0d Panagiotis Kanavos
70 4f6d51d4 Panagiotis Kanavos
	    ///<summary>
71 4f6d51d4 Panagiotis Kanavos
	    /// The status service is used by Shell extensions to retrieve file status information
72 4f6d51d4 Panagiotis Kanavos
	    ///</summary>
73 4f6d51d4 Panagiotis Kanavos
	    //TODO: CODE SMELL! This is the shell! While hosting in the shell makes executing start/stop commands easier, it is still a smell
74 4f6d51d4 Panagiotis Kanavos
	    private ServiceHost _statusService;
75 c53aa229 Panagiotis Kanavos
76 cf761c0d Panagiotis Kanavos
		//Logging in the Pithos client is provided by log4net
77 4ec636f6 Panagiotis Kanavos
		private static readonly log4net.ILog Log = log4net.LogManager.GetLogger("Pithos");
78 c53aa229 Panagiotis Kanavos
79 cf761c0d Panagiotis Kanavos
		///<summary>
80 cf761c0d Panagiotis Kanavos
		/// The Shell depends on MEF to provide implementations for windowManager, events, the status checker service and the settings
81 cf761c0d Panagiotis Kanavos
		///</summary>
82 cf761c0d Panagiotis Kanavos
		///<remarks>
83 cf761c0d Panagiotis Kanavos
		/// The PithosSettings class encapsulates the app's settings to abstract their storage mechanism (App settings, a database or registry)
84 cf761c0d Panagiotis Kanavos
		///</remarks>
85 4ec636f6 Panagiotis Kanavos
		[ImportingConstructor]		
86 4ec636f6 Panagiotis Kanavos
		public ShellViewModel(IWindowManager windowManager, IEventAggregator events, IStatusChecker statusChecker, PithosSettings settings)
87 4ec636f6 Panagiotis Kanavos
		{
88 4ec636f6 Panagiotis Kanavos
			try
89 4ec636f6 Panagiotis Kanavos
			{
90 d3a13891 Panagiotis Kanavos
91 4ec636f6 Panagiotis Kanavos
				_windowManager = windowManager;
92 cf761c0d Panagiotis Kanavos
				//CHECK: Caliburn doesn't need explicit command construction
93 4ec636f6 Panagiotis Kanavos
				//OpenPithosFolderCommand = new PithosCommand(OpenPithosFolder);
94 4ec636f6 Panagiotis Kanavos
				_statusChecker = statusChecker;
95 cf761c0d Panagiotis Kanavos
				//The event subst
96 4ec636f6 Panagiotis Kanavos
				_events = events;
97 4ec636f6 Panagiotis Kanavos
				_events.Subscribe(this);
98 c53aa229 Panagiotis Kanavos
99 4ec636f6 Panagiotis Kanavos
				Settings = settings;
100 c53aa229 Panagiotis Kanavos
101 4ec636f6 Panagiotis Kanavos
				StatusMessage = "In Synch";
102 7e26c075 Panagiotis Kanavos
103 4ec636f6 Panagiotis Kanavos
				_accounts.CollectionChanged += (sender, e) =>
104 4ec636f6 Panagiotis Kanavos
												   {
105 4ec636f6 Panagiotis Kanavos
													   NotifyOfPropertyChange(() => OpenFolderCaption);
106 4ec636f6 Panagiotis Kanavos
													   NotifyOfPropertyChange(() => HasAccounts);
107 4ec636f6 Panagiotis Kanavos
												   };
108 6aa29f4f Panagiotis Kanavos
109 4ec636f6 Panagiotis Kanavos
			}
110 4ec636f6 Panagiotis Kanavos
			catch (Exception exc)
111 4ec636f6 Panagiotis Kanavos
			{
112 4ec636f6 Panagiotis Kanavos
				Log.Error("Error while starting the ShellViewModel",exc);
113 4ec636f6 Panagiotis Kanavos
				throw;
114 4ec636f6 Panagiotis Kanavos
			}
115 4ec636f6 Panagiotis Kanavos
		}
116 c53aa229 Panagiotis Kanavos
117 6aa29f4f Panagiotis Kanavos
118 4ec636f6 Panagiotis Kanavos
		protected override void OnActivate()
119 4ec636f6 Panagiotis Kanavos
		{
120 4ec636f6 Panagiotis Kanavos
			base.OnActivate();
121 42800be8 Panagiotis Kanavos
122 4ec636f6 Panagiotis Kanavos
			StartMonitoring();                    
123 4ec636f6 Panagiotis Kanavos
		}
124 7b0a5fec Panagiotis Kanavos
125 42800be8 Panagiotis Kanavos
126 4f6d51d4 Panagiotis Kanavos
		private async void StartMonitoring()
127 4ec636f6 Panagiotis Kanavos
		{
128 4ec636f6 Panagiotis Kanavos
			try
129 4ec636f6 Panagiotis Kanavos
			{
130 4ec636f6 Panagiotis Kanavos
				var accounts = Settings.Accounts.Select(MonitorAccount);
131 4ec636f6 Panagiotis Kanavos
				await TaskEx.WhenAll(accounts);
132 4ec636f6 Panagiotis Kanavos
				_statusService = StatusService.Start();
133 692ec33b Panagiotis Kanavos
134 692ec33b Panagiotis Kanavos
/*
135 4ec636f6 Panagiotis Kanavos
				foreach (var account in Settings.Accounts)
136 4ec636f6 Panagiotis Kanavos
				{
137 4ec636f6 Panagiotis Kanavos
					await MonitorAccount(account);
138 4ec636f6 Panagiotis Kanavos
				}
139 692ec33b Panagiotis Kanavos
*/
140 4ec636f6 Panagiotis Kanavos
				
141 4ec636f6 Panagiotis Kanavos
			}
142 4ec636f6 Panagiotis Kanavos
			catch (AggregateException exc)
143 4ec636f6 Panagiotis Kanavos
			{
144 4ec636f6 Panagiotis Kanavos
				exc.Handle(e =>
145 4ec636f6 Panagiotis Kanavos
				{
146 4ec636f6 Panagiotis Kanavos
					Log.Error("Error while starting monitoring", e);
147 4ec636f6 Panagiotis Kanavos
					return true;
148 4ec636f6 Panagiotis Kanavos
				});
149 4ec636f6 Panagiotis Kanavos
				throw;
150 4ec636f6 Panagiotis Kanavos
			}
151 4ec636f6 Panagiotis Kanavos
		}
152 4ec636f6 Panagiotis Kanavos
153 4ec636f6 Panagiotis Kanavos
		protected override void OnDeactivate(bool close)
154 4ec636f6 Panagiotis Kanavos
		{
155 4ec636f6 Panagiotis Kanavos
			base.OnDeactivate(close);
156 4ec636f6 Panagiotis Kanavos
			if (close)
157 4ec636f6 Panagiotis Kanavos
			{
158 4ec636f6 Panagiotis Kanavos
				StatusService.Stop(_statusService);
159 4ec636f6 Panagiotis Kanavos
				_statusService = null;
160 4ec636f6 Panagiotis Kanavos
			}
161 4ec636f6 Panagiotis Kanavos
		}
162 4ec636f6 Panagiotis Kanavos
163 4ec636f6 Panagiotis Kanavos
		public Task MonitorAccount(AccountSettings account)
164 4ec636f6 Panagiotis Kanavos
		{
165 4ec636f6 Panagiotis Kanavos
			return Task.Factory.StartNew(() =>
166 4ec636f6 Panagiotis Kanavos
			{                                                
167 4f6d51d4 Panagiotis Kanavos
				PithosMonitor monitor;
168 4ec636f6 Panagiotis Kanavos
				var accountName = account.AccountName;
169 4ec636f6 Panagiotis Kanavos
170 4ec636f6 Panagiotis Kanavos
				if (_monitors.TryGetValue(accountName, out monitor))
171 4ec636f6 Panagiotis Kanavos
				{
172 4ec636f6 Panagiotis Kanavos
					//If the account is active
173 4ec636f6 Panagiotis Kanavos
					if (account.IsActive)
174 4ec636f6 Panagiotis Kanavos
						//Start the monitor. It's OK to start an already started monitor,
175 4ec636f6 Panagiotis Kanavos
						//it will just ignore the call                        
176 4ec636f6 Panagiotis Kanavos
						StartMonitor(monitor).Wait();                        
177 4ec636f6 Panagiotis Kanavos
					else
178 4ec636f6 Panagiotis Kanavos
					{
179 4ec636f6 Panagiotis Kanavos
						//If the account is inactive
180 4ec636f6 Panagiotis Kanavos
						//Stop and remove the monitor
181 4ec636f6 Panagiotis Kanavos
						RemoveMonitor(accountName);
182 4ec636f6 Panagiotis Kanavos
					}
183 4ec636f6 Panagiotis Kanavos
					return;
184 4ec636f6 Panagiotis Kanavos
				}
185 4ec636f6 Panagiotis Kanavos
186 4ec636f6 Panagiotis Kanavos
				//Create a new monitor/ Can't use MEF here, it would return a single instance for all monitors
187 4ec636f6 Panagiotis Kanavos
				monitor = new PithosMonitor
188 4ec636f6 Panagiotis Kanavos
							  {
189 4ec636f6 Panagiotis Kanavos
								  UserName = accountName,
190 4ec636f6 Panagiotis Kanavos
								  ApiKey = account.ApiKey,                                  
191 4ec636f6 Panagiotis Kanavos
								  StatusNotification = this,
192 4ec636f6 Panagiotis Kanavos
								  RootPath = account.RootPath
193 4ec636f6 Panagiotis Kanavos
							  };
194 4ec636f6 Panagiotis Kanavos
				//PithosMonitor uses MEF so we need to resolve it
195 4ec636f6 Panagiotis Kanavos
				IoC.BuildUp(monitor);
196 4ec636f6 Panagiotis Kanavos
197 4f6d51d4 Panagiotis Kanavos
			    monitor.AuthenticationUrl = account.ServerUrl;
198 4ec636f6 Panagiotis Kanavos
199 4ec636f6 Panagiotis Kanavos
				_monitors[accountName] = monitor;
200 4ec636f6 Panagiotis Kanavos
201 4ec636f6 Panagiotis Kanavos
				if (account.IsActive)
202 4ec636f6 Panagiotis Kanavos
				{
203 4ec636f6 Panagiotis Kanavos
					//Don't start a monitor if it doesn't have an account and ApiKey
204 4ec636f6 Panagiotis Kanavos
					if (String.IsNullOrWhiteSpace(monitor.UserName) ||
205 4ec636f6 Panagiotis Kanavos
						String.IsNullOrWhiteSpace(monitor.ApiKey))
206 4ec636f6 Panagiotis Kanavos
						return;
207 4ec636f6 Panagiotis Kanavos
					StartMonitor(monitor);
208 4ec636f6 Panagiotis Kanavos
				}
209 4ec636f6 Panagiotis Kanavos
			});
210 4ec636f6 Panagiotis Kanavos
		}
211 4ec636f6 Panagiotis Kanavos
212 4ec636f6 Panagiotis Kanavos
213 4ec636f6 Panagiotis Kanavos
		protected override void OnViewLoaded(object view)
214 4ec636f6 Panagiotis Kanavos
		{
215 4ec636f6 Panagiotis Kanavos
			UpdateStatus();
216 4ec636f6 Panagiotis Kanavos
			var window = (Window)view;            
217 4ec636f6 Panagiotis Kanavos
			TaskEx.Delay(1000).ContinueWith(t => Execute.OnUIThread(window.Hide));
218 4ec636f6 Panagiotis Kanavos
			base.OnViewLoaded(view);
219 4ec636f6 Panagiotis Kanavos
		}
220 4ec636f6 Panagiotis Kanavos
221 4ec636f6 Panagiotis Kanavos
222 4ec636f6 Panagiotis Kanavos
		#region Status Properties
223 4ec636f6 Panagiotis Kanavos
224 4ec636f6 Panagiotis Kanavos
		private string _statusMessage;
225 4ec636f6 Panagiotis Kanavos
		public string StatusMessage
226 4ec636f6 Panagiotis Kanavos
		{
227 4ec636f6 Panagiotis Kanavos
			get { return _statusMessage; }
228 4ec636f6 Panagiotis Kanavos
			set
229 4ec636f6 Panagiotis Kanavos
			{
230 4ec636f6 Panagiotis Kanavos
				_statusMessage = value;
231 4ec636f6 Panagiotis Kanavos
				NotifyOfPropertyChange(() => StatusMessage);
232 4ec636f6 Panagiotis Kanavos
			}
233 4ec636f6 Panagiotis Kanavos
		}
234 4ec636f6 Panagiotis Kanavos
235 4ec636f6 Panagiotis Kanavos
		private readonly ObservableConcurrentCollection<AccountInfo> _accounts = new ObservableConcurrentCollection<AccountInfo>();
236 4ec636f6 Panagiotis Kanavos
		public ObservableConcurrentCollection<AccountInfo> Accounts
237 4ec636f6 Panagiotis Kanavos
		{
238 4ec636f6 Panagiotis Kanavos
			get { return _accounts; }
239 4ec636f6 Panagiotis Kanavos
		}
240 4ec636f6 Panagiotis Kanavos
241 4ec636f6 Panagiotis Kanavos
		public bool HasAccounts
242 4ec636f6 Panagiotis Kanavos
		{
243 4ec636f6 Panagiotis Kanavos
			get { return _accounts.Count > 0; }
244 4ec636f6 Panagiotis Kanavos
		}
245 4ec636f6 Panagiotis Kanavos
246 4ec636f6 Panagiotis Kanavos
247 4ec636f6 Panagiotis Kanavos
		public string OpenFolderCaption
248 4ec636f6 Panagiotis Kanavos
		{
249 4ec636f6 Panagiotis Kanavos
			get
250 4ec636f6 Panagiotis Kanavos
			{
251 4ec636f6 Panagiotis Kanavos
				return (_accounts.Count == 0)
252 4ec636f6 Panagiotis Kanavos
						? "No Accounts Defined"
253 4ec636f6 Panagiotis Kanavos
						: "Open Pithos Folder";
254 4ec636f6 Panagiotis Kanavos
			}
255 4ec636f6 Panagiotis Kanavos
		}
256 4ec636f6 Panagiotis Kanavos
257 4ec636f6 Panagiotis Kanavos
		private string _pauseSyncCaption="Pause Synching";
258 4ec636f6 Panagiotis Kanavos
		public string PauseSyncCaption
259 4ec636f6 Panagiotis Kanavos
		{
260 4ec636f6 Panagiotis Kanavos
			get { return _pauseSyncCaption; }
261 4ec636f6 Panagiotis Kanavos
			set
262 4ec636f6 Panagiotis Kanavos
			{
263 4ec636f6 Panagiotis Kanavos
				_pauseSyncCaption = value;
264 4ec636f6 Panagiotis Kanavos
				NotifyOfPropertyChange(() => PauseSyncCaption);
265 4ec636f6 Panagiotis Kanavos
			}
266 4ec636f6 Panagiotis Kanavos
		}
267 4ec636f6 Panagiotis Kanavos
268 4ec636f6 Panagiotis Kanavos
		private readonly ObservableConcurrentCollection<FileEntry> _recentFiles = new ObservableConcurrentCollection<FileEntry>();
269 4ec636f6 Panagiotis Kanavos
		public ObservableConcurrentCollection<FileEntry> RecentFiles
270 4ec636f6 Panagiotis Kanavos
		{
271 4ec636f6 Panagiotis Kanavos
			get { return _recentFiles; }
272 4ec636f6 Panagiotis Kanavos
		}
273 4ec636f6 Panagiotis Kanavos
274 4ec636f6 Panagiotis Kanavos
275 4ec636f6 Panagiotis Kanavos
		private string _statusIcon="../Images/Pithos.ico";
276 4ec636f6 Panagiotis Kanavos
		public string StatusIcon
277 4ec636f6 Panagiotis Kanavos
		{
278 4ec636f6 Panagiotis Kanavos
			get { return _statusIcon; }
279 4ec636f6 Panagiotis Kanavos
			set
280 4ec636f6 Panagiotis Kanavos
			{
281 4f6d51d4 Panagiotis Kanavos
                //TODO: Ensure all status icons use the Pithos logo
282 4f6d51d4 Panagiotis Kanavos
				_statusIcon = value;
283 4ec636f6 Panagiotis Kanavos
				NotifyOfPropertyChange(() => StatusIcon);
284 4ec636f6 Panagiotis Kanavos
			}
285 4ec636f6 Panagiotis Kanavos
		}
286 4ec636f6 Panagiotis Kanavos
287 4ec636f6 Panagiotis Kanavos
		#endregion
288 4ec636f6 Panagiotis Kanavos
289 4ec636f6 Panagiotis Kanavos
		#region Commands
290 4ec636f6 Panagiotis Kanavos
291 4ec636f6 Panagiotis Kanavos
		public void ShowPreferences()
292 4ec636f6 Panagiotis Kanavos
		{
293 4ec636f6 Panagiotis Kanavos
			Settings.Reload();
294 4ec636f6 Panagiotis Kanavos
			var preferences = new PreferencesViewModel(_windowManager,_events, this,Settings);            
295 4ec636f6 Panagiotis Kanavos
			_windowManager.ShowDialog(preferences);
296 4ec636f6 Panagiotis Kanavos
			
297 4ec636f6 Panagiotis Kanavos
		}
298 4ec636f6 Panagiotis Kanavos
299 4ec636f6 Panagiotis Kanavos
		public void AboutPithos()
300 4ec636f6 Panagiotis Kanavos
		{
301 4ec636f6 Panagiotis Kanavos
			var about = new AboutViewModel();
302 4ec636f6 Panagiotis Kanavos
			_windowManager.ShowWindow(about);
303 4ec636f6 Panagiotis Kanavos
		}
304 4ec636f6 Panagiotis Kanavos
305 4ec636f6 Panagiotis Kanavos
		public void SendFeedback()
306 4ec636f6 Panagiotis Kanavos
		{
307 4ec636f6 Panagiotis Kanavos
			var feedBack =  IoC.Get<FeedbackViewModel>();
308 4ec636f6 Panagiotis Kanavos
			_windowManager.ShowWindow(feedBack);
309 4ec636f6 Panagiotis Kanavos
		}
310 4ec636f6 Panagiotis Kanavos
311 4ec636f6 Panagiotis Kanavos
		//public PithosCommand OpenPithosFolderCommand { get; private set; }
312 4ec636f6 Panagiotis Kanavos
313 4ec636f6 Panagiotis Kanavos
		public void OpenPithosFolder()
314 4ec636f6 Panagiotis Kanavos
		{
315 4ec636f6 Panagiotis Kanavos
			var account = Settings.Accounts.FirstOrDefault(acc => acc.IsActive);
316 4ec636f6 Panagiotis Kanavos
			if (account == null)
317 4ec636f6 Panagiotis Kanavos
				return;
318 4ec636f6 Panagiotis Kanavos
			Process.Start(account.RootPath);
319 4ec636f6 Panagiotis Kanavos
		}
320 4ec636f6 Panagiotis Kanavos
321 4ec636f6 Panagiotis Kanavos
		public void OpenPithosFolder(AccountInfo account)
322 4ec636f6 Panagiotis Kanavos
		{
323 4ec636f6 Panagiotis Kanavos
			Process.Start(account.AccountPath);
324 4ec636f6 Panagiotis Kanavos
		}
325 4ec636f6 Panagiotis Kanavos
326 4ec636f6 Panagiotis Kanavos
		
327 f734ab5b Panagiotis Kanavos
/*
328 4ec636f6 Panagiotis Kanavos
		public void GoToSite()
329 4ec636f6 Panagiotis Kanavos
		{            
330 4ec636f6 Panagiotis Kanavos
			var site = Properties.Settings.Default.PithosSite;
331 4ec636f6 Panagiotis Kanavos
			Process.Start(site);            
332 4ec636f6 Panagiotis Kanavos
		}
333 f734ab5b Panagiotis Kanavos
*/
334 6aa29f4f Panagiotis Kanavos
335 4ec636f6 Panagiotis Kanavos
		public void GoToSite(AccountInfo account)
336 4ec636f6 Panagiotis Kanavos
		{
337 4ec636f6 Panagiotis Kanavos
			/*var site = String.Format("{0}/ui/?token={1}&user={2}",
338 4ec636f6 Panagiotis Kanavos
				account.SiteUri,account.Token,
339 4ec636f6 Panagiotis Kanavos
				account.UserName);*/
340 4ec636f6 Panagiotis Kanavos
			Process.Start(account.SiteUri);
341 4ec636f6 Panagiotis Kanavos
		}
342 4ec636f6 Panagiotis Kanavos
343 4ec636f6 Panagiotis Kanavos
		public void ShowFileProperties()
344 4ec636f6 Panagiotis Kanavos
		{
345 4ec636f6 Panagiotis Kanavos
			var account = Settings.Accounts.First(acc => acc.IsActive);            
346 4ec636f6 Panagiotis Kanavos
			var dir = new DirectoryInfo(account.RootPath + @"\pithos");
347 4ec636f6 Panagiotis Kanavos
			var files=dir.GetFiles();
348 4ec636f6 Panagiotis Kanavos
			var r=new Random();
349 4ec636f6 Panagiotis Kanavos
			var idx=r.Next(0, files.Length);
350 4ec636f6 Panagiotis Kanavos
			ShowFileProperties(files[idx].FullName);            
351 4ec636f6 Panagiotis Kanavos
		}
352 4ec636f6 Panagiotis Kanavos
353 4ec636f6 Panagiotis Kanavos
		public void ShowFileProperties(string filePath)
354 4ec636f6 Panagiotis Kanavos
		{
355 4ec636f6 Panagiotis Kanavos
			if (String.IsNullOrWhiteSpace(filePath))
356 4ec636f6 Panagiotis Kanavos
				throw new ArgumentNullException("filePath");
357 4f6d51d4 Panagiotis Kanavos
			if (!File.Exists(filePath) && !Directory.Exists(filePath))
358 4ec636f6 Panagiotis Kanavos
				throw new ArgumentException(String.Format("Non existent file {0}",filePath),"filePath");
359 4ec636f6 Panagiotis Kanavos
			Contract.EndContractBlock();
360 4ec636f6 Panagiotis Kanavos
361 4ec636f6 Panagiotis Kanavos
			var pair=(from monitor in  Monitors
362 4ec636f6 Panagiotis Kanavos
							   where filePath.StartsWith(monitor.Value.RootPath, StringComparison.InvariantCultureIgnoreCase)
363 4ec636f6 Panagiotis Kanavos
								   select monitor).FirstOrDefault();
364 4f6d51d4 Panagiotis Kanavos
		    var accountMonitor = pair.Value;
365 4ec636f6 Panagiotis Kanavos
366 4ec636f6 Panagiotis Kanavos
			if (accountMonitor == null)
367 4ec636f6 Panagiotis Kanavos
				return;
368 4ec636f6 Panagiotis Kanavos
369 4ec636f6 Panagiotis Kanavos
			var infoTask=Task.Factory.StartNew(()=>accountMonitor.GetObjectInfo(filePath));
370 4ec636f6 Panagiotis Kanavos
371 4ec636f6 Panagiotis Kanavos
			
372 4ec636f6 Panagiotis Kanavos
373 4ec636f6 Panagiotis Kanavos
			var fileProperties = new FilePropertiesViewModel(this, infoTask,filePath);
374 4ec636f6 Panagiotis Kanavos
			_windowManager.ShowWindow(fileProperties);
375 4ec636f6 Panagiotis Kanavos
		} 
376 4ec636f6 Panagiotis Kanavos
		
377 4ec636f6 Panagiotis Kanavos
		public void ShowContainerProperties()
378 4ec636f6 Panagiotis Kanavos
		{
379 4ec636f6 Panagiotis Kanavos
			var account = Settings.Accounts.First(acc => acc.IsActive);            
380 4ec636f6 Panagiotis Kanavos
			var dir = new DirectoryInfo(account.RootPath);
381 4ec636f6 Panagiotis Kanavos
			var fullName = (from folder in dir.EnumerateDirectories()
382 4ec636f6 Panagiotis Kanavos
							where (folder.Attributes & FileAttributes.Hidden) == 0
383 4ec636f6 Panagiotis Kanavos
							select folder.FullName).First();
384 4ec636f6 Panagiotis Kanavos
			ShowContainerProperties(fullName);            
385 4ec636f6 Panagiotis Kanavos
		}
386 4ec636f6 Panagiotis Kanavos
387 4ec636f6 Panagiotis Kanavos
		public void ShowContainerProperties(string filePath)
388 4ec636f6 Panagiotis Kanavos
		{
389 4ec636f6 Panagiotis Kanavos
			if (String.IsNullOrWhiteSpace(filePath))
390 4ec636f6 Panagiotis Kanavos
				throw new ArgumentNullException("filePath");
391 4ec636f6 Panagiotis Kanavos
			if (!Directory.Exists(filePath))
392 4ec636f6 Panagiotis Kanavos
				throw new ArgumentException(String.Format("Non existent file {0}",filePath),"filePath");
393 4ec636f6 Panagiotis Kanavos
			Contract.EndContractBlock();
394 4ec636f6 Panagiotis Kanavos
395 4ec636f6 Panagiotis Kanavos
			var pair=(from monitor in  Monitors
396 4ec636f6 Panagiotis Kanavos
							   where filePath.StartsWith(monitor.Value.RootPath, StringComparison.InvariantCultureIgnoreCase)
397 4ec636f6 Panagiotis Kanavos
								   select monitor).FirstOrDefault();
398 4f6d51d4 Panagiotis Kanavos
		    var accountMonitor = pair.Value;            
399 4ec636f6 Panagiotis Kanavos
			var info = accountMonitor.GetContainerInfo(filePath);
400 4ec636f6 Panagiotis Kanavos
401 4ec636f6 Panagiotis Kanavos
			
402 4ec636f6 Panagiotis Kanavos
403 4ec636f6 Panagiotis Kanavos
			var containerProperties = new ContainerPropertiesViewModel(this, info,filePath);
404 4ec636f6 Panagiotis Kanavos
			_windowManager.ShowWindow(containerProperties);
405 4ec636f6 Panagiotis Kanavos
		}
406 4ec636f6 Panagiotis Kanavos
407 133f83c2 Panagiotis Kanavos
        public void SynchNow()
408 133f83c2 Panagiotis Kanavos
        {}
409 133f83c2 Panagiotis Kanavos
410 4ec636f6 Panagiotis Kanavos
		public ObjectInfo RefreshObjectInfo(ObjectInfo currentInfo)
411 4ec636f6 Panagiotis Kanavos
		{
412 4ec636f6 Panagiotis Kanavos
			if (currentInfo==null)
413 4ec636f6 Panagiotis Kanavos
				throw new ArgumentNullException("currentInfo");
414 4ec636f6 Panagiotis Kanavos
			Contract.EndContractBlock();
415 4ec636f6 Panagiotis Kanavos
416 4ec636f6 Panagiotis Kanavos
			var monitor = Monitors[currentInfo.Account];
417 4ec636f6 Panagiotis Kanavos
			var newInfo=monitor.CloudClient.GetObjectInfo(currentInfo.Account, currentInfo.Container, currentInfo.Name);
418 4ec636f6 Panagiotis Kanavos
			return newInfo;
419 4ec636f6 Panagiotis Kanavos
		}
420 4ec636f6 Panagiotis Kanavos
421 4ec636f6 Panagiotis Kanavos
		public ContainerInfo RefreshContainerInfo(ContainerInfo container)
422 4ec636f6 Panagiotis Kanavos
		{
423 4ec636f6 Panagiotis Kanavos
			if (container == null)
424 4ec636f6 Panagiotis Kanavos
				throw new ArgumentNullException("container");
425 4ec636f6 Panagiotis Kanavos
			Contract.EndContractBlock();
426 4ec636f6 Panagiotis Kanavos
427 4ec636f6 Panagiotis Kanavos
			var monitor = Monitors[container.Account];
428 4ec636f6 Panagiotis Kanavos
			var newInfo = monitor.CloudClient.GetContainerInfo(container.Account, container.Name);
429 4ec636f6 Panagiotis Kanavos
			return newInfo;
430 4ec636f6 Panagiotis Kanavos
		}
431 4ec636f6 Panagiotis Kanavos
432 4ec636f6 Panagiotis Kanavos
433 4ec636f6 Panagiotis Kanavos
		public void ToggleSynching()
434 4ec636f6 Panagiotis Kanavos
		{
435 4ec636f6 Panagiotis Kanavos
			bool isPaused=false;
436 4ec636f6 Panagiotis Kanavos
			foreach (var pair in Monitors)
437 4ec636f6 Panagiotis Kanavos
			{
438 4ec636f6 Panagiotis Kanavos
				var monitor = pair.Value;
439 4ec636f6 Panagiotis Kanavos
				monitor.Pause = !monitor.Pause;
440 4ec636f6 Panagiotis Kanavos
				isPaused = monitor.Pause;
441 4ec636f6 Panagiotis Kanavos
			}
442 4ec636f6 Panagiotis Kanavos
443 4ec636f6 Panagiotis Kanavos
			PauseSyncCaption = isPaused ? "Resume syncing" : "Pause syncing";
444 4ec636f6 Panagiotis Kanavos
			var iconKey = isPaused? "TraySyncPaused" : "TrayInSynch";
445 4ec636f6 Panagiotis Kanavos
			StatusIcon = String.Format(@"../Images/{0}.ico", iconKey);
446 4ec636f6 Panagiotis Kanavos
		}
447 4ec636f6 Panagiotis Kanavos
448 4ec636f6 Panagiotis Kanavos
		public void ExitPithos()
449 4ec636f6 Panagiotis Kanavos
		{
450 4ec636f6 Panagiotis Kanavos
			foreach (var pair in Monitors)
451 4ec636f6 Panagiotis Kanavos
			{
452 4ec636f6 Panagiotis Kanavos
				var monitor = pair.Value;
453 4ec636f6 Panagiotis Kanavos
				monitor.Stop();
454 4ec636f6 Panagiotis Kanavos
			}
455 4ec636f6 Panagiotis Kanavos
456 4ec636f6 Panagiotis Kanavos
			((Window)GetView()).Close();
457 4ec636f6 Panagiotis Kanavos
		}
458 4ec636f6 Panagiotis Kanavos
		#endregion
459 4ec636f6 Panagiotis Kanavos
460 4ec636f6 Panagiotis Kanavos
461 4f6d51d4 Panagiotis Kanavos
		private readonly Dictionary<PithosStatus, StatusInfo> _iconNames = new List<StatusInfo>
462 4ec636f6 Panagiotis Kanavos
			{
463 4ec636f6 Panagiotis Kanavos
				new StatusInfo(PithosStatus.InSynch, "All files up to date", "TrayInSynch"),
464 4ec636f6 Panagiotis Kanavos
				new StatusInfo(PithosStatus.Syncing, "Syncing Files", "TraySynching"),
465 4ec636f6 Panagiotis Kanavos
				new StatusInfo(PithosStatus.SyncPaused, "Sync Paused", "TraySyncPaused")
466 4ec636f6 Panagiotis Kanavos
			}.ToDictionary(s => s.Status);
467 4ec636f6 Panagiotis Kanavos
468 4ec636f6 Panagiotis Kanavos
		readonly IWindowManager _windowManager;
469 c53aa229 Panagiotis Kanavos
470 c53aa229 Panagiotis Kanavos
471 cf761c0d Panagiotis Kanavos
		///<summary>
472 cf761c0d Panagiotis Kanavos
		/// Updates the visual status indicators of the application depending on status changes, e.g. icon, stat		
473 cf761c0d Panagiotis Kanavos
		///</summary>
474 4ec636f6 Panagiotis Kanavos
		public void UpdateStatus()
475 4ec636f6 Panagiotis Kanavos
		{
476 4ec636f6 Panagiotis Kanavos
			var pithosStatus = _statusChecker.GetPithosStatus();
477 4ec636f6 Panagiotis Kanavos
478 4f6d51d4 Panagiotis Kanavos
			if (_iconNames.ContainsKey(pithosStatus))
479 4ec636f6 Panagiotis Kanavos
			{
480 4f6d51d4 Panagiotis Kanavos
				var info = _iconNames[pithosStatus];
481 4ec636f6 Panagiotis Kanavos
				StatusIcon = String.Format(@"../Images/{0}.ico", info.IconName);
482 4ec636f6 Panagiotis Kanavos
483 4ec636f6 Panagiotis Kanavos
				Assembly assembly = Assembly.GetExecutingAssembly();                               
484 4ec636f6 Panagiotis Kanavos
				var fileVersion = FileVersionInfo.GetVersionInfo(assembly.Location);
485 4ec636f6 Panagiotis Kanavos
486 4ec636f6 Panagiotis Kanavos
487 4ec636f6 Panagiotis Kanavos
				StatusMessage = String.Format("Pithos {0}\r\n{1}", fileVersion.FileVersion,info.StatusText);
488 4ec636f6 Panagiotis Kanavos
			}
489 4ec636f6 Panagiotis Kanavos
			
490 4ec636f6 Panagiotis Kanavos
			_events.Publish(new Notification { Title = "Start", Message = "Start Monitoring", Level = TraceLevel.Info});
491 4ec636f6 Panagiotis Kanavos
		}
492 4ec636f6 Panagiotis Kanavos
493 4ec636f6 Panagiotis Kanavos
494 4ec636f6 Panagiotis Kanavos
	   
495 4ec636f6 Panagiotis Kanavos
		private Task StartMonitor(PithosMonitor monitor,int retries=0)
496 4ec636f6 Panagiotis Kanavos
		{
497 4ec636f6 Panagiotis Kanavos
			return Task.Factory.StartNew(() =>
498 4ec636f6 Panagiotis Kanavos
			{
499 4ec636f6 Panagiotis Kanavos
				using (log4net.ThreadContext.Stacks["Monitor"].Push("Start"))
500 4ec636f6 Panagiotis Kanavos
				{
501 4ec636f6 Panagiotis Kanavos
					try
502 4ec636f6 Panagiotis Kanavos
					{
503 4ec636f6 Panagiotis Kanavos
						Log.InfoFormat("Start Monitoring {0}", monitor.UserName);
504 4ec636f6 Panagiotis Kanavos
505 4ec636f6 Panagiotis Kanavos
						monitor.Start();
506 4ec636f6 Panagiotis Kanavos
					}
507 4ec636f6 Panagiotis Kanavos
					catch (WebException exc)
508 4ec636f6 Panagiotis Kanavos
					{
509 4ec636f6 Panagiotis Kanavos
						if (AbandonRetry(monitor, retries))
510 4ec636f6 Panagiotis Kanavos
							return;
511 4ec636f6 Panagiotis Kanavos
512 4ec636f6 Panagiotis Kanavos
						if (IsUnauthorized(exc))
513 4ec636f6 Panagiotis Kanavos
						{
514 4ec636f6 Panagiotis Kanavos
							var message = String.Format("API Key Expired for {0}. Starting Renewal",monitor.UserName);                            
515 4ec636f6 Panagiotis Kanavos
							Log.Error(message,exc);
516 4ec636f6 Panagiotis Kanavos
							TryAuthorize(monitor,retries).Wait();
517 4ec636f6 Panagiotis Kanavos
						}
518 4ec636f6 Panagiotis Kanavos
						else
519 4ec636f6 Panagiotis Kanavos
						{
520 4ec636f6 Panagiotis Kanavos
							TryLater(monitor, exc,retries);
521 4ec636f6 Panagiotis Kanavos
						}
522 4ec636f6 Panagiotis Kanavos
					}
523 4ec636f6 Panagiotis Kanavos
					catch (Exception exc)
524 4ec636f6 Panagiotis Kanavos
					{
525 4ec636f6 Panagiotis Kanavos
						if (AbandonRetry(monitor, retries)) 
526 4ec636f6 Panagiotis Kanavos
							return;
527 4ec636f6 Panagiotis Kanavos
528 4ec636f6 Panagiotis Kanavos
						TryLater(monitor,exc,retries);
529 4ec636f6 Panagiotis Kanavos
					}
530 4ec636f6 Panagiotis Kanavos
				}
531 4ec636f6 Panagiotis Kanavos
			});
532 4ec636f6 Panagiotis Kanavos
		}
533 4ec636f6 Panagiotis Kanavos
534 4ec636f6 Panagiotis Kanavos
		private bool AbandonRetry(PithosMonitor monitor, int retries)
535 4ec636f6 Panagiotis Kanavos
		{
536 4ec636f6 Panagiotis Kanavos
			if (retries > 1)
537 4ec636f6 Panagiotis Kanavos
			{
538 4ec636f6 Panagiotis Kanavos
				var message = String.Format("Monitoring of account {0} has failed too many times. Will not retry",
539 4ec636f6 Panagiotis Kanavos
											monitor.UserName);
540 4ec636f6 Panagiotis Kanavos
				_events.Publish(new Notification
541 4ec636f6 Panagiotis Kanavos
									{Title = "Account monitoring failed", Message = message, Level = TraceLevel.Error});
542 4ec636f6 Panagiotis Kanavos
				return true;
543 4ec636f6 Panagiotis Kanavos
			}
544 4ec636f6 Panagiotis Kanavos
			return false;
545 4ec636f6 Panagiotis Kanavos
		}
546 4ec636f6 Panagiotis Kanavos
547 4ec636f6 Panagiotis Kanavos
548 4ec636f6 Panagiotis Kanavos
		private async Task TryAuthorize(PithosMonitor monitor,int retries)
549 4ec636f6 Panagiotis Kanavos
		{
550 4ec636f6 Panagiotis Kanavos
			_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 });
551 4ec636f6 Panagiotis Kanavos
552 4ec636f6 Panagiotis Kanavos
			try
553 4ec636f6 Panagiotis Kanavos
			{
554 4ec636f6 Panagiotis Kanavos
555 4ec636f6 Panagiotis Kanavos
				var credentials = await PithosAccount.RetrieveCredentials(Settings.PithosLoginUrl);
556 4ec636f6 Panagiotis Kanavos
557 4f6d51d4 Panagiotis Kanavos
				var account = Settings.Accounts.First(act => act.AccountName == credentials.UserName);
558 4ec636f6 Panagiotis Kanavos
				account.ApiKey = credentials.Password;
559 4ec636f6 Panagiotis Kanavos
				monitor.ApiKey = credentials.Password;
560 4ec636f6 Panagiotis Kanavos
				Settings.Save();
561 4ec636f6 Panagiotis Kanavos
				await TaskEx.Delay(10000);
562 4ec636f6 Panagiotis Kanavos
				StartMonitor(monitor, retries + 1);
563 4ec636f6 Panagiotis Kanavos
				NotifyOfPropertyChange(()=>Accounts);
564 4ec636f6 Panagiotis Kanavos
			}
565 4ec636f6 Panagiotis Kanavos
			catch (AggregateException exc)
566 4ec636f6 Panagiotis Kanavos
			{
567 4ec636f6 Panagiotis Kanavos
				string message = String.Format("API Key retrieval for {0} failed", monitor.UserName);
568 4ec636f6 Panagiotis Kanavos
				Log.Error(message, exc.InnerException);
569 4ec636f6 Panagiotis Kanavos
				_events.Publish(new Notification { Title = "Authorization failed", Message = message, Level = TraceLevel.Error });
570 4ec636f6 Panagiotis Kanavos
			}
571 4ec636f6 Panagiotis Kanavos
			catch (Exception exc)
572 4ec636f6 Panagiotis Kanavos
			{
573 4ec636f6 Panagiotis Kanavos
				string message = String.Format("API Key retrieval for {0} failed", monitor.UserName);
574 4ec636f6 Panagiotis Kanavos
				Log.Error(message, exc);
575 4ec636f6 Panagiotis Kanavos
				_events.Publish(new Notification { Title = "Authorization failed", Message = message, Level = TraceLevel.Error });
576 4ec636f6 Panagiotis Kanavos
			}
577 4ec636f6 Panagiotis Kanavos
578 4ec636f6 Panagiotis Kanavos
		}
579 4ec636f6 Panagiotis Kanavos
580 4ec636f6 Panagiotis Kanavos
		private static bool IsUnauthorized(WebException exc)
581 4ec636f6 Panagiotis Kanavos
		{
582 4ec636f6 Panagiotis Kanavos
			if (exc==null)
583 4ec636f6 Panagiotis Kanavos
				throw new ArgumentNullException("exc");
584 4ec636f6 Panagiotis Kanavos
			Contract.EndContractBlock();
585 4ec636f6 Panagiotis Kanavos
586 4ec636f6 Panagiotis Kanavos
			var response = exc.Response as HttpWebResponse;
587 4ec636f6 Panagiotis Kanavos
			if (response == null)
588 4ec636f6 Panagiotis Kanavos
				return false;
589 4ec636f6 Panagiotis Kanavos
			return (response.StatusCode == HttpStatusCode.Unauthorized);
590 4ec636f6 Panagiotis Kanavos
		}
591 4ec636f6 Panagiotis Kanavos
592 4ec636f6 Panagiotis Kanavos
		private void TryLater(PithosMonitor monitor, Exception exc,int retries)
593 4ec636f6 Panagiotis Kanavos
		{
594 4ec636f6 Panagiotis Kanavos
			var message = String.Format("An exception occured. Can't start monitoring\nWill retry in 10 seconds");
595 4ec636f6 Panagiotis Kanavos
			Task.Factory.StartNewDelayed(10000, () => StartMonitor(monitor,retries+1));
596 4ec636f6 Panagiotis Kanavos
			_events.Publish(new Notification
597 4ec636f6 Panagiotis Kanavos
								{Title = "Error", Message = message, Level = TraceLevel.Error});
598 4ec636f6 Panagiotis Kanavos
			Log.Error(message, exc);
599 4ec636f6 Panagiotis Kanavos
		}
600 4ec636f6 Panagiotis Kanavos
601 4ec636f6 Panagiotis Kanavos
602 4ec636f6 Panagiotis Kanavos
		public void NotifyChange(string status, TraceLevel level=TraceLevel.Info)
603 4ec636f6 Panagiotis Kanavos
		{
604 4f6d51d4 Panagiotis Kanavos
			StatusMessage = status;
605 4ec636f6 Panagiotis Kanavos
			
606 4ec636f6 Panagiotis Kanavos
			_events.Publish(new Notification { Title = "Pithos", Message = status, Level = level });
607 4ec636f6 Panagiotis Kanavos
		}
608 4ec636f6 Panagiotis Kanavos
609 4ec636f6 Panagiotis Kanavos
		public void NotifyChangedFile(string filePath)
610 4ec636f6 Panagiotis Kanavos
		{
611 4ec636f6 Panagiotis Kanavos
			var entry = new FileEntry {FullPath=filePath};
612 4f6d51d4 Panagiotis Kanavos
			IProducerConsumerCollection<FileEntry> files=RecentFiles;
613 4ec636f6 Panagiotis Kanavos
			FileEntry popped;
614 4ec636f6 Panagiotis Kanavos
			while (files.Count > 5)
615 4ec636f6 Panagiotis Kanavos
				files.TryTake(out popped);
616 4ec636f6 Panagiotis Kanavos
			files.TryAdd(entry);
617 4ec636f6 Panagiotis Kanavos
		}
618 4ec636f6 Panagiotis Kanavos
619 4ec636f6 Panagiotis Kanavos
		public void NotifyAccount(AccountInfo account)
620 4ec636f6 Panagiotis Kanavos
		{
621 4ec636f6 Panagiotis Kanavos
			if (account== null)
622 4ec636f6 Panagiotis Kanavos
				return;
623 4ec636f6 Panagiotis Kanavos
			//TODO: What happens to an existing account whose Token has changed?
624 4ec636f6 Panagiotis Kanavos
			account.SiteUri= String.Format("{0}/ui/?token={1}&user={2}",
625 f7ccec15 Panagiotis Kanavos
				account.SiteUri, Uri.EscapeUriString(account.Token),
626 f7ccec15 Panagiotis Kanavos
				Uri.EscapeUriString(account.UserName));
627 4ec636f6 Panagiotis Kanavos
628 4ec636f6 Panagiotis Kanavos
			if (Accounts.All(item => item.UserName != account.UserName))
629 4ec636f6 Panagiotis Kanavos
				Accounts.TryAdd(account);
630 4ec636f6 Panagiotis Kanavos
631 4ec636f6 Panagiotis Kanavos
		}
632 4ec636f6 Panagiotis Kanavos
633 4ec636f6 Panagiotis Kanavos
634 4ec636f6 Panagiotis Kanavos
		public void RemoveMonitor(string accountName)
635 4ec636f6 Panagiotis Kanavos
		{
636 4ec636f6 Panagiotis Kanavos
			if (String.IsNullOrWhiteSpace(accountName))
637 4ec636f6 Panagiotis Kanavos
				return;
638 4ec636f6 Panagiotis Kanavos
639 4ec636f6 Panagiotis Kanavos
			var accountInfo=_accounts.FirstOrDefault(account => account.UserName == accountName);
640 4ec636f6 Panagiotis Kanavos
			_accounts.TryRemove(accountInfo);
641 4ec636f6 Panagiotis Kanavos
642 4ec636f6 Panagiotis Kanavos
			PithosMonitor monitor;
643 4ec636f6 Panagiotis Kanavos
			if (Monitors.TryRemove(accountName, out monitor))
644 4ec636f6 Panagiotis Kanavos
			{
645 4ec636f6 Panagiotis Kanavos
				monitor.Stop();
646 4ec636f6 Panagiotis Kanavos
			}
647 4ec636f6 Panagiotis Kanavos
		}
648 4ec636f6 Panagiotis Kanavos
649 4ec636f6 Panagiotis Kanavos
		public void RefreshOverlays()
650 4ec636f6 Panagiotis Kanavos
		{
651 4ec636f6 Panagiotis Kanavos
			foreach (var pair in Monitors)
652 4ec636f6 Panagiotis Kanavos
			{
653 4ec636f6 Panagiotis Kanavos
				var monitor = pair.Value;
654 4ec636f6 Panagiotis Kanavos
655 4ec636f6 Panagiotis Kanavos
				var path = monitor.RootPath;
656 4ec636f6 Panagiotis Kanavos
657 4ec636f6 Panagiotis Kanavos
				if (String.IsNullOrWhiteSpace(path))
658 4ec636f6 Panagiotis Kanavos
					continue;
659 4ec636f6 Panagiotis Kanavos
660 4ec636f6 Panagiotis Kanavos
				if (!Directory.Exists(path) && !File.Exists(path))
661 4ec636f6 Panagiotis Kanavos
					continue;
662 4ec636f6 Panagiotis Kanavos
663 4ec636f6 Panagiotis Kanavos
				IntPtr pathPointer = Marshal.StringToCoTaskMemAuto(path);
664 4ec636f6 Panagiotis Kanavos
665 4ec636f6 Panagiotis Kanavos
				try
666 4ec636f6 Panagiotis Kanavos
				{
667 4ec636f6 Panagiotis Kanavos
					NativeMethods.SHChangeNotify(HChangeNotifyEventID.SHCNE_UPDATEITEM,
668 4ec636f6 Panagiotis Kanavos
												 HChangeNotifyFlags.SHCNF_PATHW | HChangeNotifyFlags.SHCNF_FLUSHNOWAIT,
669 4ec636f6 Panagiotis Kanavos
												 pathPointer, IntPtr.Zero);
670 4ec636f6 Panagiotis Kanavos
				}
671 4ec636f6 Panagiotis Kanavos
				finally
672 4ec636f6 Panagiotis Kanavos
				{
673 4ec636f6 Panagiotis Kanavos
					Marshal.FreeHGlobal(pathPointer);
674 4ec636f6 Panagiotis Kanavos
				}
675 4ec636f6 Panagiotis Kanavos
			}
676 4ec636f6 Panagiotis Kanavos
		}
677 4ec636f6 Panagiotis Kanavos
678 4ec636f6 Panagiotis Kanavos
		#region Event Handlers
679 4ec636f6 Panagiotis Kanavos
		
680 4ec636f6 Panagiotis Kanavos
		public void Handle(SelectiveSynchChanges message)
681 4ec636f6 Panagiotis Kanavos
		{
682 4ec636f6 Panagiotis Kanavos
			var accountName = message.Account.AccountName;
683 4ec636f6 Panagiotis Kanavos
			PithosMonitor monitor;
684 4ec636f6 Panagiotis Kanavos
			if (_monitors.TryGetValue(accountName, out monitor))
685 4ec636f6 Panagiotis Kanavos
			{
686 4ec636f6 Panagiotis Kanavos
				monitor.AddSelectivePaths(message.Added);
687 4ec636f6 Panagiotis Kanavos
				monitor.RemoveSelectivePaths(message.Removed);
688 4ec636f6 Panagiotis Kanavos
689 4ec636f6 Panagiotis Kanavos
			}
690 4ec636f6 Panagiotis Kanavos
			
691 4ec636f6 Panagiotis Kanavos
		}
692 4ec636f6 Panagiotis Kanavos
693 4ec636f6 Panagiotis Kanavos
694 4ec636f6 Panagiotis Kanavos
		public void Handle(Notification notification)
695 4ec636f6 Panagiotis Kanavos
		{
696 4ec636f6 Panagiotis Kanavos
			if (!Settings.ShowDesktopNotifications)
697 4ec636f6 Panagiotis Kanavos
				return;
698 4f6d51d4 Panagiotis Kanavos
			BalloonIcon icon;
699 4ec636f6 Panagiotis Kanavos
			switch (notification.Level)
700 4ec636f6 Panagiotis Kanavos
			{
701 4ec636f6 Panagiotis Kanavos
				case TraceLevel.Error:
702 4ec636f6 Panagiotis Kanavos
					icon = BalloonIcon.Error;
703 4ec636f6 Panagiotis Kanavos
					break;
704 4ec636f6 Panagiotis Kanavos
				case TraceLevel.Info:
705 4ec636f6 Panagiotis Kanavos
				case TraceLevel.Verbose:
706 4ec636f6 Panagiotis Kanavos
					icon = BalloonIcon.Info;
707 4ec636f6 Panagiotis Kanavos
					break;
708 4ec636f6 Panagiotis Kanavos
				case TraceLevel.Warning:
709 4ec636f6 Panagiotis Kanavos
					icon = BalloonIcon.Warning;
710 4ec636f6 Panagiotis Kanavos
					break;
711 4ec636f6 Panagiotis Kanavos
				default:
712 4ec636f6 Panagiotis Kanavos
					icon = BalloonIcon.None;
713 4ec636f6 Panagiotis Kanavos
					break;
714 4ec636f6 Panagiotis Kanavos
			}
715 4ec636f6 Panagiotis Kanavos
716 4ec636f6 Panagiotis Kanavos
			if (Settings.ShowDesktopNotifications)
717 4ec636f6 Panagiotis Kanavos
			{
718 4f6d51d4 Panagiotis Kanavos
				var tv = (ShellView) GetView();
719 4ec636f6 Panagiotis Kanavos
				tv.TaskbarView.ShowBalloonTip(notification.Title, notification.Message, icon);
720 4ec636f6 Panagiotis Kanavos
			}
721 4ec636f6 Panagiotis Kanavos
		}
722 4ec636f6 Panagiotis Kanavos
		#endregion
723 4ec636f6 Panagiotis Kanavos
724 4ec636f6 Panagiotis Kanavos
		public void Handle(ShowFilePropertiesEvent message)
725 4ec636f6 Panagiotis Kanavos
		{
726 4ec636f6 Panagiotis Kanavos
			if (message == null)
727 4ec636f6 Panagiotis Kanavos
				throw new ArgumentNullException("message");
728 4ec636f6 Panagiotis Kanavos
			if (String.IsNullOrWhiteSpace(message.FileName) )
729 4ec636f6 Panagiotis Kanavos
				throw new ArgumentException("message");
730 4ec636f6 Panagiotis Kanavos
			Contract.EndContractBlock();
731 4ec636f6 Panagiotis Kanavos
732 4ec636f6 Panagiotis Kanavos
			var fileName = message.FileName;
733 4f6d51d4 Panagiotis Kanavos
            //TODO: Display file properties for non-container folders
734 4ec636f6 Panagiotis Kanavos
			if (File.Exists(fileName))
735 4f6d51d4 Panagiotis Kanavos
                //Retrieve the full name with exact casing. Pithos names are case sensitive				
736 f3d080df Panagiotis Kanavos
                ShowFileProperties(FileInfoExtensions.GetProperFilePathCapitalization(fileName));
737 4ec636f6 Panagiotis Kanavos
			else if (Directory.Exists(fileName))
738 4f6d51d4 Panagiotis Kanavos
                //Retrieve the full name with exact casing. Pithos names are case sensitive
739 4f6d51d4 Panagiotis Kanavos
			{
740 f3d080df Panagiotis Kanavos
                var path = FileInfoExtensions.GetProperDirectoryCapitalization(fileName);
741 4f6d51d4 Panagiotis Kanavos
                if (IsContainer(path))
742 4f6d51d4 Panagiotis Kanavos
			        ShowContainerProperties(path);
743 4f6d51d4 Panagiotis Kanavos
                else
744 4f6d51d4 Panagiotis Kanavos
                    ShowFileProperties(path);
745 4f6d51d4 Panagiotis Kanavos
			}
746 4ec636f6 Panagiotis Kanavos
		}
747 4f6d51d4 Panagiotis Kanavos
748 4f6d51d4 Panagiotis Kanavos
	    private bool IsContainer(string path)
749 4f6d51d4 Panagiotis Kanavos
	    {
750 4f6d51d4 Panagiotis Kanavos
	        var matchingFolders = from account in _accounts
751 4f6d51d4 Panagiotis Kanavos
	                              from rootFolder in Directory.GetDirectories(account.AccountPath)
752 4f6d51d4 Panagiotis Kanavos
	                              where rootFolder.Equals(path, StringComparison.InvariantCultureIgnoreCase)
753 4f6d51d4 Panagiotis Kanavos
	                              select rootFolder;
754 4f6d51d4 Panagiotis Kanavos
	        return matchingFolders.Any();
755 4f6d51d4 Panagiotis Kanavos
	    }
756 4f6d51d4 Panagiotis Kanavos
757 4ec636f6 Panagiotis Kanavos
	}
758 9bae55d1 Panagiotis Kanavos
}