Statistics
| Branch: | Revision:

root / trunk / Pithos.Client.WPF / Shell / ShellViewModel.cs @ ee950288

History | View | Annotate | Download (36.5 kB)

1 255f5f86 Panagiotis Kanavos
#region
2 255f5f86 Panagiotis Kanavos
/* -----------------------------------------------------------------------
3 255f5f86 Panagiotis Kanavos
 * <copyright file="ShellViewModel.cs" company="GRNet">
4 255f5f86 Panagiotis Kanavos
 * 
5 255f5f86 Panagiotis Kanavos
 * Copyright 2011-2012 GRNET S.A. All rights reserved.
6 255f5f86 Panagiotis Kanavos
 *
7 255f5f86 Panagiotis Kanavos
 * Redistribution and use in source and binary forms, with or
8 255f5f86 Panagiotis Kanavos
 * without modification, are permitted provided that the following
9 255f5f86 Panagiotis Kanavos
 * conditions are met:
10 255f5f86 Panagiotis Kanavos
 *
11 255f5f86 Panagiotis Kanavos
 *   1. Redistributions of source code must retain the above
12 255f5f86 Panagiotis Kanavos
 *      copyright notice, this list of conditions and the following
13 255f5f86 Panagiotis Kanavos
 *      disclaimer.
14 255f5f86 Panagiotis Kanavos
 *
15 255f5f86 Panagiotis Kanavos
 *   2. Redistributions in binary form must reproduce the above
16 255f5f86 Panagiotis Kanavos
 *      copyright notice, this list of conditions and the following
17 255f5f86 Panagiotis Kanavos
 *      disclaimer in the documentation and/or other materials
18 255f5f86 Panagiotis Kanavos
 *      provided with the distribution.
19 255f5f86 Panagiotis Kanavos
 *
20 255f5f86 Panagiotis Kanavos
 *
21 255f5f86 Panagiotis Kanavos
 * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
22 255f5f86 Panagiotis Kanavos
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 255f5f86 Panagiotis Kanavos
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 255f5f86 Panagiotis Kanavos
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
25 255f5f86 Panagiotis Kanavos
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 255f5f86 Panagiotis Kanavos
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 255f5f86 Panagiotis Kanavos
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28 255f5f86 Panagiotis Kanavos
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 255f5f86 Panagiotis Kanavos
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 255f5f86 Panagiotis Kanavos
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 255f5f86 Panagiotis Kanavos
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 255f5f86 Panagiotis Kanavos
 * POSSIBILITY OF SUCH DAMAGE.
33 255f5f86 Panagiotis Kanavos
 *
34 255f5f86 Panagiotis Kanavos
 * The views and conclusions contained in the software and
35 255f5f86 Panagiotis Kanavos
 * documentation are those of the authors and should not be
36 255f5f86 Panagiotis Kanavos
 * interpreted as representing official policies, either expressed
37 255f5f86 Panagiotis Kanavos
 * or implied, of GRNET S.A.
38 255f5f86 Panagiotis Kanavos
 * </copyright>
39 255f5f86 Panagiotis Kanavos
 * -----------------------------------------------------------------------
40 255f5f86 Panagiotis Kanavos
 */
41 255f5f86 Panagiotis Kanavos
#endregion
42 255f5f86 Panagiotis Kanavos
using System.Collections.Concurrent;
43 c53aa229 Panagiotis Kanavos
using System.Diagnostics;
44 c28a075a Panagiotis Kanavos
using System.Diagnostics.Contracts;
45 c53aa229 Panagiotis Kanavos
using System.IO;
46 c28a075a Panagiotis Kanavos
using System.Net;
47 d17258c2 Panagiotis Kanavos
using System.Reflection;
48 c53aa229 Panagiotis Kanavos
using System.Runtime.InteropServices;
49 c53aa229 Panagiotis Kanavos
using System.ServiceModel;
50 c53aa229 Panagiotis Kanavos
using System.Threading.Tasks;
51 c53aa229 Panagiotis Kanavos
using System.Windows;
52 fb9d6e00 Panagiotis Kanavos
using System.Windows.Controls.Primitives;
53 049333d2 Panagiotis Kanavos
using AppLimit.NetSparkle;
54 9bae55d1 Panagiotis Kanavos
using Caliburn.Micro;
55 c53aa229 Panagiotis Kanavos
using Hardcodet.Wpf.TaskbarNotification;
56 c53aa229 Panagiotis Kanavos
using Pithos.Client.WPF.Configuration;
57 42800be8 Panagiotis Kanavos
using Pithos.Client.WPF.FileProperties;
58 65282d58 Panagiotis Kanavos
using Pithos.Client.WPF.Preferences;
59 d3a13891 Panagiotis Kanavos
using Pithos.Client.WPF.SelectiveSynch;
60 42800be8 Panagiotis Kanavos
using Pithos.Client.WPF.Services;
61 5cb9d74f Panagiotis Kanavos
using Pithos.Client.WPF.Shell;
62 c53aa229 Panagiotis Kanavos
using Pithos.Core;
63 29a6b387 Panagiotis Kanavos
using Pithos.Core.Agents;
64 c53aa229 Panagiotis Kanavos
using Pithos.Interfaces;
65 c53aa229 Panagiotis Kanavos
using System;
66 c53aa229 Panagiotis Kanavos
using System.Collections.Generic;
67 c53aa229 Panagiotis Kanavos
using System.Linq;
68 0bd56b7c Panagiotis Kanavos
using Pithos.Network;
69 c53aa229 Panagiotis Kanavos
using StatusService = Pithos.Client.WPF.Services.StatusService;
70 9bae55d1 Panagiotis Kanavos
71 9bae55d1 Panagiotis Kanavos
namespace Pithos.Client.WPF {
72 4ec636f6 Panagiotis Kanavos
	using System.ComponentModel.Composition;
73 9bae55d1 Panagiotis Kanavos
74 4ec636f6 Panagiotis Kanavos
	
75 cf761c0d Panagiotis Kanavos
	///<summary>
76 cf761c0d Panagiotis Kanavos
	/// The "shell" of the Pithos application displays the taskbar  icon, menu and notifications.
77 cf761c0d Panagiotis Kanavos
	/// The shell also hosts the status service called by shell extensions to retrieve file info
78 cf761c0d Panagiotis Kanavos
	///</summary>
79 cf761c0d Panagiotis Kanavos
	///<remarks>
80 cf761c0d Panagiotis Kanavos
	/// It is a strange "shell" as its main visible element is an icon instead of a window
81 cf761c0d Panagiotis Kanavos
	/// The shell subscribes to the following events:
82 cf761c0d Panagiotis Kanavos
	/// * Notification:  Raised by components that want to notify the user. Usually displayed in a balloon
83 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
84 cf761c0d Panagiotis Kanavos
	/// * ShowFilePropertiesEvent: Raised when a shell command requests the display of the file/container properties dialog
85 cf761c0d Panagiotis Kanavos
	///</remarks>		
86 cf761c0d Panagiotis Kanavos
	//TODO: CODE SMELL Why does the shell handle the SelectiveSynchChanges?
87 dcca46c3 pkanavos
    [Export(typeof(IShell)), Export(typeof(ShellViewModel))]
88 4ec636f6 Panagiotis Kanavos
	public class ShellViewModel : Screen, IStatusNotification, IShell,
89 4ec636f6 Panagiotis Kanavos
		IHandle<Notification>, IHandle<SelectiveSynchChanges>, IHandle<ShowFilePropertiesEvent>
90 4ec636f6 Panagiotis Kanavos
	{
91 6bcdd8e2 Panagiotis Kanavos
92 cf761c0d Panagiotis Kanavos
		//The Status Checker provides the current synch state
93 cf761c0d Panagiotis Kanavos
		//TODO: Could we remove the status checker and use events in its place?
94 4f6d51d4 Panagiotis Kanavos
		private readonly IStatusChecker _statusChecker;
95 4f6d51d4 Panagiotis Kanavos
		private readonly IEventAggregator _events;
96 c53aa229 Panagiotis Kanavos
97 4ec636f6 Panagiotis Kanavos
		public PithosSettings Settings { get; private set; }
98 c53aa229 Panagiotis Kanavos
99 4ec636f6 Panagiotis Kanavos
100 ebc37b0d pkanavos
		private readonly ConcurrentDictionary<Uri, PithosMonitor> _monitors = new ConcurrentDictionary<Uri, PithosMonitor>();
101 cf761c0d Panagiotis Kanavos
		///<summary>
102 cf761c0d Panagiotis Kanavos
		/// Dictionary of account monitors, keyed by account
103 cf761c0d Panagiotis Kanavos
		///</summary>
104 cf761c0d Panagiotis Kanavos
		///<remarks>
105 cf761c0d Panagiotis Kanavos
		/// One monitor class is created for each account. The Shell needs access to the monitors to execute start/stop/pause commands,
106 cf761c0d Panagiotis Kanavos
		/// retrieve account and boject info		
107 cf761c0d Panagiotis Kanavos
		///</remarks>
108 cf761c0d Panagiotis Kanavos
		// TODO: Does the Shell REALLY need access to the monitors? Could we achieve the same results with a better design?
109 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
110 ebc37b0d pkanavos
		public ConcurrentDictionary<Uri, PithosMonitor> Monitors
111 4ec636f6 Panagiotis Kanavos
		{
112 4ec636f6 Panagiotis Kanavos
			get { return _monitors; }
113 4ec636f6 Panagiotis Kanavos
		}
114 c53aa229 Panagiotis Kanavos
115 cf761c0d Panagiotis Kanavos
116 255f5f86 Panagiotis Kanavos
		///<summary>
117 255f5f86 Panagiotis Kanavos
		/// The status service is used by Shell extensions to retrieve file status information
118 255f5f86 Panagiotis Kanavos
		///</summary>
119 255f5f86 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
120 255f5f86 Panagiotis Kanavos
		private ServiceHost _statusService;
121 c53aa229 Panagiotis Kanavos
122 cf761c0d Panagiotis Kanavos
		//Logging in the Pithos client is provided by log4net
123 db8a9589 Panagiotis Kanavos
        private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
124 c53aa229 Panagiotis Kanavos
125 7f5882da Panagiotis Kanavos
	    private readonly PollAgent _pollAgent;
126 2341c603 pkanavos
	    private readonly NetworkAgent _networkAgent;
127 31c97141 Panagiotis Kanavos
128 43dd02a8 pkanavos
	    [Import]
129 43dd02a8 pkanavos
	    public Selectives Selectives { get; set; }
130 72eeda84 Panagiotis Kanavos
131 72eeda84 Panagiotis Kanavos
	    private MiniStatusViewModel _miniStatus;
132 72eeda84 Panagiotis Kanavos
133 72eeda84 Panagiotis Kanavos
	    [Import]
134 72eeda84 Panagiotis Kanavos
        public MiniStatusViewModel MiniStatus
135 72eeda84 Panagiotis Kanavos
	    {
136 72eeda84 Panagiotis Kanavos
	        get { return _miniStatus; }
137 72eeda84 Panagiotis Kanavos
	        set
138 72eeda84 Panagiotis Kanavos
	        {
139 72eeda84 Panagiotis Kanavos
	            _miniStatus = value;
140 72eeda84 Panagiotis Kanavos
	            _miniStatus.Shell = this;
141 6b0de454 Panagiotis Kanavos
	            _miniStatus.Deactivated += (sender, arg) =>
142 6b0de454 Panagiotis Kanavos
	                                           {
143 6b0de454 Panagiotis Kanavos
	                                               _statusVisible = false;
144 6b0de454 Panagiotis Kanavos
                                                   NotifyOfPropertyChange(()=>MiniStatusCaption);
145 6b0de454 Panagiotis Kanavos
	                                           };
146 72eeda84 Panagiotis Kanavos
	        }
147 72eeda84 Panagiotis Kanavos
	    }
148 72eeda84 Panagiotis Kanavos
149 72eeda84 Panagiotis Kanavos
	    ///<summary>
150 cf761c0d Panagiotis Kanavos
		/// The Shell depends on MEF to provide implementations for windowManager, events, the status checker service and the settings
151 cf761c0d Panagiotis Kanavos
		///</summary>
152 cf761c0d Panagiotis Kanavos
		///<remarks>
153 cf761c0d Panagiotis Kanavos
		/// The PithosSettings class encapsulates the app's settings to abstract their storage mechanism (App settings, a database or registry)
154 cf761c0d Panagiotis Kanavos
		///</remarks>
155 4ec636f6 Panagiotis Kanavos
		[ImportingConstructor]		
156 2341c603 pkanavos
		public ShellViewModel(IWindowManager windowManager, IEventAggregator events, IStatusChecker statusChecker, PithosSettings settings,PollAgent pollAgent,NetworkAgent networkAgent)
157 4ec636f6 Panagiotis Kanavos
		{
158 4ec636f6 Panagiotis Kanavos
			try
159 4ec636f6 Panagiotis Kanavos
			{
160 d3a13891 Panagiotis Kanavos
161 4ec636f6 Panagiotis Kanavos
				_windowManager = windowManager;
162 cf761c0d Panagiotis Kanavos
				//CHECK: Caliburn doesn't need explicit command construction
163 4ec636f6 Panagiotis Kanavos
				//OpenPithosFolderCommand = new PithosCommand(OpenPithosFolder);
164 4ec636f6 Panagiotis Kanavos
				_statusChecker = statusChecker;
165 cf761c0d Panagiotis Kanavos
				//The event subst
166 4ec636f6 Panagiotis Kanavos
				_events = events;
167 4ec636f6 Panagiotis Kanavos
				_events.Subscribe(this);
168 c53aa229 Panagiotis Kanavos
169 31c97141 Panagiotis Kanavos
			    _pollAgent = pollAgent;
170 2341c603 pkanavos
			    _networkAgent = networkAgent;
171 4ec636f6 Panagiotis Kanavos
				Settings = settings;
172 c53aa229 Panagiotis Kanavos
173 255f5f86 Panagiotis Kanavos
				Proxy.SetFromSettings(settings);
174 34bdb91d Panagiotis Kanavos
175 adfa4645 Panagiotis Kanavos
                StatusMessage = Settings.Accounts.Count==0 
176 81c5c310 pkanavos
                    ? "No Accounts added\r\nPlease add an account" 
177 adfa4645 Panagiotis Kanavos
                    : "Starting";
178 7e26c075 Panagiotis Kanavos
179 4ec636f6 Panagiotis Kanavos
				_accounts.CollectionChanged += (sender, e) =>
180 4ec636f6 Panagiotis Kanavos
												   {
181 4ec636f6 Panagiotis Kanavos
													   NotifyOfPropertyChange(() => OpenFolderCaption);
182 4ec636f6 Panagiotis Kanavos
													   NotifyOfPropertyChange(() => HasAccounts);
183 4ec636f6 Panagiotis Kanavos
												   };
184 6aa29f4f Panagiotis Kanavos
185 81c5c310 pkanavos
                SetVersionMessage();
186 4ec636f6 Panagiotis Kanavos
			}
187 4ec636f6 Panagiotis Kanavos
			catch (Exception exc)
188 4ec636f6 Panagiotis Kanavos
			{
189 4ec636f6 Panagiotis Kanavos
				Log.Error("Error while starting the ShellViewModel",exc);
190 4ec636f6 Panagiotis Kanavos
				throw;
191 4ec636f6 Panagiotis Kanavos
			}
192 6bcdd8e2 Panagiotis Kanavos
193 4ec636f6 Panagiotis Kanavos
		}
194 c53aa229 Panagiotis Kanavos
195 81c5c310 pkanavos
	    private void SetVersionMessage()
196 81c5c310 pkanavos
	    {
197 81c5c310 pkanavos
	        Assembly assembly = Assembly.GetExecutingAssembly();
198 81c5c310 pkanavos
	        var fileVersion = FileVersionInfo.GetVersionInfo(assembly.Location);
199 81c5c310 pkanavos
	        VersionMessage = String.Format("Pithos+ {0}", fileVersion.FileVersion);
200 81c5c310 pkanavos
	    }
201 6aa29f4f Panagiotis Kanavos
202 c3f2e9dc George Pantazis
        public void CurrentSyncStatus()
203 81c5c310 pkanavos
        {
204 c3f2e9dc George Pantazis
            if (Accounts.Count == 0)
205 81c5c310 pkanavos
            {
206 81c5c310 pkanavos
                ShowPreferences("AccountTab");
207 81c5c310 pkanavos
            }
208 c3f2e9dc George Pantazis
            else
209 c3f2e9dc George Pantazis
            {
210 c3f2e9dc George Pantazis
                if (!_statusVisible)
211 c3f2e9dc George Pantazis
                    _windowManager.ShowWindow(MiniStatus);
212 c3f2e9dc George Pantazis
                else
213 c3f2e9dc George Pantazis
                {
214 c3f2e9dc George Pantazis
                    if (MiniStatus.IsActive)
215 c3f2e9dc George Pantazis
                        MiniStatus.TryClose();
216 c3f2e9dc George Pantazis
                }
217 c3f2e9dc George Pantazis
                _statusVisible = !_statusVisible;
218 c3f2e9dc George Pantazis
219 c3f2e9dc George Pantazis
                NotifyOfPropertyChange(() => MiniStatusCaption);
220 c3f2e9dc George Pantazis
            }
221 81c5c310 pkanavos
        }
222 c3f2e9dc George Pantazis
223 81c5c310 pkanavos
	    protected override void OnActivate()
224 4ec636f6 Panagiotis Kanavos
		{
225 4ec636f6 Panagiotis Kanavos
			base.OnActivate();
226 42800be8 Panagiotis Kanavos
227 81c5c310 pkanavos
            InitializeSparkle();
228 049333d2 Panagiotis Kanavos
229 81c5c310 pkanavos
	        //Must delay opening the upgrade window
230 049333d2 Panagiotis Kanavos
            //to avoid Windows Messages sent by the TaskbarIcon
231 049333d2 Panagiotis Kanavos
            TaskEx.Delay(5000).ContinueWith(_=>
232 5d7b20e8 Panagiotis Kanavos
                Execute.OnUIThread(()=> _sparkle.StartLoop(true,Settings.UpdateForceCheck,Settings.UpdateCheckInterval)));
233 049333d2 Panagiotis Kanavos
234 34bdb91d Panagiotis Kanavos
235 4ec636f6 Panagiotis Kanavos
			StartMonitoring();                    
236 4ec636f6 Panagiotis Kanavos
		}
237 7b0a5fec Panagiotis Kanavos
238 81c5c310 pkanavos
239 81c5c310 pkanavos
	    private void OnCheckFinished(object sender, bool updaterequired)
240 049333d2 Panagiotis Kanavos
	    {
241 81c5c310 pkanavos
            
242 81c5c310 pkanavos
            Log.InfoFormat("Upgrade check finished. Need Upgrade: {0}", updaterequired);
243 81c5c310 pkanavos
            if (_manualUpgradeCheck)
244 81c5c310 pkanavos
            {
245 81c5c310 pkanavos
                _manualUpgradeCheck = false;
246 81c5c310 pkanavos
                if (!updaterequired)
247 81c5c310 pkanavos
                    //Sparkle raises events on a background thread
248 81c5c310 pkanavos
                    Execute.OnUIThread(()=>
249 dcca46c3 pkanavos
                        ShowBalloonFor(new Notification{Title="Pithos+ is up to date",Message="You have the latest Pithos+ version. No update is required"}));
250 81c5c310 pkanavos
            }
251 81c5c310 pkanavos
	    }
252 81c5c310 pkanavos
253 81c5c310 pkanavos
	    private void OnUpgradeDetected(object sender, UpdateDetectedEventArgs e)
254 81c5c310 pkanavos
	    {            
255 049333d2 Panagiotis Kanavos
	        Log.InfoFormat("Update detected {0}",e.LatestVersion);
256 049333d2 Panagiotis Kanavos
	    }
257 42800be8 Panagiotis Kanavos
258 049333d2 Panagiotis Kanavos
        public void CheckForUpgrade()
259 049333d2 Panagiotis Kanavos
        {
260 81c5c310 pkanavos
            ShowBalloonFor(new Notification{Title="Checking for upgrades",Message="Contacting the server to retrieve the latest Pithos+ version."});
261 049333d2 Panagiotis Kanavos
            _sparkle.StopLoop();
262 81c5c310 pkanavos
            _sparkle.updateDetected -= OnUpgradeDetected;
263 81c5c310 pkanavos
            _sparkle.checkLoopFinished -= OnCheckFinished;
264 049333d2 Panagiotis Kanavos
            _sparkle.Dispose();
265 81c5c310 pkanavos
266 81c5c310 pkanavos
            _manualUpgradeCheck = true;
267 81c5c310 pkanavos
            InitializeSparkle();
268 049333d2 Panagiotis Kanavos
            _sparkle.StartLoop(true,true,Settings.UpdateCheckInterval);
269 049333d2 Panagiotis Kanavos
        }
270 34bdb91d Panagiotis Kanavos
271 81c5c310 pkanavos
        private void InitializeSparkle()
272 81c5c310 pkanavos
        {
273 81c5c310 pkanavos
            _sparkle = new Sparkle(Settings.UpdateUrl);
274 81c5c310 pkanavos
            _sparkle.updateDetected += OnUpgradeDetected;
275 81c5c310 pkanavos
            _sparkle.checkLoopFinished += OnCheckFinished;
276 81c5c310 pkanavos
            _sparkle.ShowDiagnosticWindow = Settings.UpdateDiagnostics;
277 81c5c310 pkanavos
        }
278 81c5c310 pkanavos
279 049333d2 Panagiotis Kanavos
	    private async void StartMonitoring()
280 4ec636f6 Panagiotis Kanavos
		{
281 4ec636f6 Panagiotis Kanavos
			try
282 4ec636f6 Panagiotis Kanavos
			{
283 ebc37b0d pkanavos
                if (Settings.IgnoreCertificateErrors)
284 ebc37b0d pkanavos
                {
285 ebc37b0d pkanavos
                    ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;
286 ebc37b0d pkanavos
                }
287 ebc37b0d pkanavos
                    
288 4ec636f6 Panagiotis Kanavos
				var accounts = Settings.Accounts.Select(MonitorAccount);
289 4ec636f6 Panagiotis Kanavos
				await TaskEx.WhenAll(accounts);
290 4ec636f6 Panagiotis Kanavos
				_statusService = StatusService.Start();
291 692ec33b Panagiotis Kanavos
292 4ec636f6 Panagiotis Kanavos
			}
293 4ec636f6 Panagiotis Kanavos
			catch (AggregateException exc)
294 4ec636f6 Panagiotis Kanavos
			{
295 4ec636f6 Panagiotis Kanavos
				exc.Handle(e =>
296 4ec636f6 Panagiotis Kanavos
				{
297 4ec636f6 Panagiotis Kanavos
					Log.Error("Error while starting monitoring", e);
298 4ec636f6 Panagiotis Kanavos
					return true;
299 4ec636f6 Panagiotis Kanavos
				});
300 4ec636f6 Panagiotis Kanavos
				throw;
301 4ec636f6 Panagiotis Kanavos
			}
302 4ec636f6 Panagiotis Kanavos
		}
303 4ec636f6 Panagiotis Kanavos
304 4ec636f6 Panagiotis Kanavos
		protected override void OnDeactivate(bool close)
305 4ec636f6 Panagiotis Kanavos
		{
306 4ec636f6 Panagiotis Kanavos
			base.OnDeactivate(close);
307 4ec636f6 Panagiotis Kanavos
			if (close)
308 4ec636f6 Panagiotis Kanavos
			{
309 4ec636f6 Panagiotis Kanavos
				StatusService.Stop(_statusService);
310 4ec636f6 Panagiotis Kanavos
				_statusService = null;
311 4ec636f6 Panagiotis Kanavos
			}
312 4ec636f6 Panagiotis Kanavos
		}
313 4ec636f6 Panagiotis Kanavos
314 4ec636f6 Panagiotis Kanavos
		public Task MonitorAccount(AccountSettings account)
315 4ec636f6 Panagiotis Kanavos
		{
316 4ec636f6 Panagiotis Kanavos
			return Task.Factory.StartNew(() =>
317 4ec636f6 Panagiotis Kanavos
			{                                                
318 4f6d51d4 Panagiotis Kanavos
				PithosMonitor monitor;
319 4ec636f6 Panagiotis Kanavos
				var accountName = account.AccountName;
320 4ec636f6 Panagiotis Kanavos
321 6a7b8909 pkanavos
			    MigrateFolders(account);
322 6a7b8909 pkanavos
323 43dd02a8 pkanavos
			    Selectives.SetIsSelectiveEnabled(account.AccountKey, account.SelectiveSyncEnabled);
324 43dd02a8 pkanavos
325 ebc37b0d pkanavos
				if (Monitors.TryGetValue(account.AccountKey, out monitor))
326 4ec636f6 Panagiotis Kanavos
				{
327 4ec636f6 Panagiotis Kanavos
					//If the account is active
328 c636df1f Panagiotis Kanavos
                    if (account.IsActive)
329 c636df1f Panagiotis Kanavos
                    {
330 c636df1f Panagiotis Kanavos
                        //The Api Key may have changed throuth the Preferences dialog
331 c636df1f Panagiotis Kanavos
                        monitor.ApiKey = account.ApiKey;
332 c636df1f Panagiotis Kanavos
						Debug.Assert(monitor.StatusNotification == this,"An existing monitor should already have a StatusNotification service object");
333 c636df1f Panagiotis Kanavos
                        monitor.RootPath = account.RootPath;
334 c636df1f Panagiotis Kanavos
                        //Start the monitor. It's OK to start an already started monitor,
335 c636df1f Panagiotis Kanavos
                        //it will just ignore the call                        
336 c636df1f Panagiotis Kanavos
                        StartMonitor(monitor).Wait();
337 c636df1f Panagiotis Kanavos
                    }
338 c636df1f Panagiotis Kanavos
                    else
339 c636df1f Panagiotis Kanavos
                    {
340 c636df1f Panagiotis Kanavos
                        //If the account is inactive
341 c636df1f Panagiotis Kanavos
                        //Stop and remove the monitor
342 ebc37b0d pkanavos
                        RemoveMonitor(account.ServerUrl,accountName);
343 c636df1f Panagiotis Kanavos
                    }
344 4ec636f6 Panagiotis Kanavos
					return;
345 4ec636f6 Panagiotis Kanavos
				}
346 4ec636f6 Panagiotis Kanavos
347 255f5f86 Panagiotis Kanavos
				
348 4ec636f6 Panagiotis Kanavos
				//Create a new monitor/ Can't use MEF here, it would return a single instance for all monitors
349 4ec636f6 Panagiotis Kanavos
				monitor = new PithosMonitor
350 4ec636f6 Panagiotis Kanavos
							  {
351 4ec636f6 Panagiotis Kanavos
								  UserName = accountName,
352 4ec636f6 Panagiotis Kanavos
								  ApiKey = account.ApiKey,                                  
353 4ec636f6 Panagiotis Kanavos
								  StatusNotification = this,
354 4ec636f6 Panagiotis Kanavos
								  RootPath = account.RootPath
355 4ec636f6 Panagiotis Kanavos
							  };
356 4ec636f6 Panagiotis Kanavos
				//PithosMonitor uses MEF so we need to resolve it
357 4ec636f6 Panagiotis Kanavos
				IoC.BuildUp(monitor);
358 4ec636f6 Panagiotis Kanavos
359 255f5f86 Panagiotis Kanavos
				monitor.AuthenticationUrl = account.ServerUrl;
360 4ec636f6 Panagiotis Kanavos
361 ebc37b0d pkanavos
				Monitors[account.AccountKey] = monitor;
362 4ec636f6 Panagiotis Kanavos
363 4ec636f6 Panagiotis Kanavos
				if (account.IsActive)
364 4ec636f6 Panagiotis Kanavos
				{
365 4ec636f6 Panagiotis Kanavos
					//Don't start a monitor if it doesn't have an account and ApiKey
366 4ec636f6 Panagiotis Kanavos
					if (String.IsNullOrWhiteSpace(monitor.UserName) ||
367 4ec636f6 Panagiotis Kanavos
						String.IsNullOrWhiteSpace(monitor.ApiKey))
368 4ec636f6 Panagiotis Kanavos
						return;
369 4ec636f6 Panagiotis Kanavos
					StartMonitor(monitor);
370 4ec636f6 Panagiotis Kanavos
				}
371 4ec636f6 Panagiotis Kanavos
			});
372 4ec636f6 Panagiotis Kanavos
		}
373 4ec636f6 Panagiotis Kanavos
374 6a7b8909 pkanavos
	    private void MigrateFolders(AccountSettings account)
375 6a7b8909 pkanavos
	    {
376 6a7b8909 pkanavos
	        var oldOthersFolder=Path.Combine(account.RootPath, FolderConstants.OldOthersFolder);
377 6a7b8909 pkanavos
	        var newOthersFolder = Path.Combine(account.RootPath, FolderConstants.OthersFolder);
378 6a7b8909 pkanavos
	        var oldFolder = new DirectoryInfo(oldOthersFolder);
379 6a7b8909 pkanavos
	        var newFolder = new DirectoryInfo(newOthersFolder);
380 6a7b8909 pkanavos
381 6a7b8909 pkanavos
            if (oldFolder.Exists && !newFolder.Exists)
382 6a7b8909 pkanavos
            {
383 6a7b8909 pkanavos
                oldFolder.MoveTo(newOthersFolder);
384 6a7b8909 pkanavos
            }
385 6a7b8909 pkanavos
	    }
386 6a7b8909 pkanavos
387 4ec636f6 Panagiotis Kanavos
388 6a7b8909 pkanavos
	    protected override void OnViewLoaded(object view)
389 4ec636f6 Panagiotis Kanavos
		{
390 4ec636f6 Panagiotis Kanavos
			UpdateStatus();
391 4ec636f6 Panagiotis Kanavos
			var window = (Window)view;            
392 4ec636f6 Panagiotis Kanavos
			TaskEx.Delay(1000).ContinueWith(t => Execute.OnUIThread(window.Hide));
393 4ec636f6 Panagiotis Kanavos
			base.OnViewLoaded(view);
394 4ec636f6 Panagiotis Kanavos
		}
395 4ec636f6 Panagiotis Kanavos
396 4ec636f6 Panagiotis Kanavos
397 4ec636f6 Panagiotis Kanavos
		#region Status Properties
398 4ec636f6 Panagiotis Kanavos
399 4ec636f6 Panagiotis Kanavos
		private string _statusMessage;
400 4ec636f6 Panagiotis Kanavos
		public string StatusMessage
401 4ec636f6 Panagiotis Kanavos
		{
402 4ec636f6 Panagiotis Kanavos
			get { return _statusMessage; }
403 4ec636f6 Panagiotis Kanavos
			set
404 4ec636f6 Panagiotis Kanavos
			{
405 4ec636f6 Panagiotis Kanavos
				_statusMessage = value;
406 4ec636f6 Panagiotis Kanavos
				NotifyOfPropertyChange(() => StatusMessage);
407 6b0de454 Panagiotis Kanavos
                NotifyOfPropertyChange(() => TooltipMessage);
408 4ec636f6 Panagiotis Kanavos
			}
409 4ec636f6 Panagiotis Kanavos
		}
410 4ec636f6 Panagiotis Kanavos
411 6b0de454 Panagiotis Kanavos
        public string VersionMessage { get; set; }
412 6b0de454 Panagiotis Kanavos
413 6b0de454 Panagiotis Kanavos
	    public string TooltipMessage
414 6b0de454 Panagiotis Kanavos
	    {
415 6b0de454 Panagiotis Kanavos
	        get
416 6b0de454 Panagiotis Kanavos
	        {
417 6b0de454 Panagiotis Kanavos
	            return String.Format("{0}\r\n{1}",VersionMessage,StatusMessage);
418 6b0de454 Panagiotis Kanavos
	        }
419 6b0de454 Panagiotis Kanavos
	    }
420 6b0de454 Panagiotis Kanavos
421 4759a79c George Pantazis
        public string TooltipMiniStatus
422 4759a79c George Pantazis
        {
423 4759a79c George Pantazis
            get
424 4759a79c George Pantazis
            {
425 4759a79c George Pantazis
                return String.Format("{0}\r\n{1}", "Status Window", "Enable / Dissable the stuatus window");
426 4759a79c George Pantazis
            }
427 4759a79c George Pantazis
        }
428 4759a79c George Pantazis
429 c3f2e9dc George Pantazis
        public string ToggleStatusWindowMessage
430 c3f2e9dc George Pantazis
        {
431 c3f2e9dc George Pantazis
            get
432 c3f2e9dc George Pantazis
            {
433 c3f2e9dc George Pantazis
                return String.Format("{0}" + Environment.NewLine + "{1} Toggle Mini Status");
434 c3f2e9dc George Pantazis
            }
435 c3f2e9dc George Pantazis
        }
436 c3f2e9dc George Pantazis
437 6b0de454 Panagiotis Kanavos
	    private readonly ObservableConcurrentCollection<AccountInfo> _accounts = new ObservableConcurrentCollection<AccountInfo>();
438 4ec636f6 Panagiotis Kanavos
		public ObservableConcurrentCollection<AccountInfo> Accounts
439 4ec636f6 Panagiotis Kanavos
		{
440 4ec636f6 Panagiotis Kanavos
			get { return _accounts; }
441 4ec636f6 Panagiotis Kanavos
		}
442 4ec636f6 Panagiotis Kanavos
443 4ec636f6 Panagiotis Kanavos
		public bool HasAccounts
444 4ec636f6 Panagiotis Kanavos
		{
445 4ec636f6 Panagiotis Kanavos
			get { return _accounts.Count > 0; }
446 4ec636f6 Panagiotis Kanavos
		}
447 4ec636f6 Panagiotis Kanavos
448 4ec636f6 Panagiotis Kanavos
449 4ec636f6 Panagiotis Kanavos
		public string OpenFolderCaption
450 4ec636f6 Panagiotis Kanavos
		{
451 4ec636f6 Panagiotis Kanavos
			get
452 4ec636f6 Panagiotis Kanavos
			{
453 4ec636f6 Panagiotis Kanavos
				return (_accounts.Count == 0)
454 4ec636f6 Panagiotis Kanavos
						? "No Accounts Defined"
455 4ec636f6 Panagiotis Kanavos
						: "Open Pithos Folder";
456 4ec636f6 Panagiotis Kanavos
			}
457 4ec636f6 Panagiotis Kanavos
		}
458 4ec636f6 Panagiotis Kanavos
459 4ec636f6 Panagiotis Kanavos
		private string _pauseSyncCaption="Pause Synching";
460 4ec636f6 Panagiotis Kanavos
		public string PauseSyncCaption
461 4ec636f6 Panagiotis Kanavos
		{
462 4ec636f6 Panagiotis Kanavos
			get { return _pauseSyncCaption; }
463 4ec636f6 Panagiotis Kanavos
			set
464 4ec636f6 Panagiotis Kanavos
			{
465 4ec636f6 Panagiotis Kanavos
				_pauseSyncCaption = value;
466 4ec636f6 Panagiotis Kanavos
				NotifyOfPropertyChange(() => PauseSyncCaption);
467 4ec636f6 Panagiotis Kanavos
			}
468 4ec636f6 Panagiotis Kanavos
		}
469 4ec636f6 Panagiotis Kanavos
470 4ec636f6 Panagiotis Kanavos
		private readonly ObservableConcurrentCollection<FileEntry> _recentFiles = new ObservableConcurrentCollection<FileEntry>();
471 4ec636f6 Panagiotis Kanavos
		public ObservableConcurrentCollection<FileEntry> RecentFiles
472 4ec636f6 Panagiotis Kanavos
		{
473 4ec636f6 Panagiotis Kanavos
			get { return _recentFiles; }
474 4ec636f6 Panagiotis Kanavos
		}
475 4ec636f6 Panagiotis Kanavos
476 4ec636f6 Panagiotis Kanavos
477 4ec636f6 Panagiotis Kanavos
		private string _statusIcon="../Images/Pithos.ico";
478 4ec636f6 Panagiotis Kanavos
		public string StatusIcon
479 4ec636f6 Panagiotis Kanavos
		{
480 4ec636f6 Panagiotis Kanavos
			get { return _statusIcon; }
481 4ec636f6 Panagiotis Kanavos
			set
482 4ec636f6 Panagiotis Kanavos
			{
483 255f5f86 Panagiotis Kanavos
				//TODO: Ensure all status icons use the Pithos logo
484 4f6d51d4 Panagiotis Kanavos
				_statusIcon = value;
485 4ec636f6 Panagiotis Kanavos
				NotifyOfPropertyChange(() => StatusIcon);
486 4ec636f6 Panagiotis Kanavos
			}
487 4ec636f6 Panagiotis Kanavos
		}
488 4ec636f6 Panagiotis Kanavos
489 4ec636f6 Panagiotis Kanavos
		#endregion
490 4ec636f6 Panagiotis Kanavos
491 4ec636f6 Panagiotis Kanavos
		#region Commands
492 4ec636f6 Panagiotis Kanavos
493 2341c603 pkanavos
        public void CancelCurrentOperation()
494 2341c603 pkanavos
        {
495 2341c603 pkanavos
            _networkAgent.CancelCurrentOperation();
496 2341c603 pkanavos
        }
497 2341c603 pkanavos
498 f2d88248 Panagiotis Kanavos
        public void ShowPreferences()
499 f2d88248 Panagiotis Kanavos
        {
500 f2d88248 Panagiotis Kanavos
            ShowPreferences(null);
501 f2d88248 Panagiotis Kanavos
        }
502 f2d88248 Panagiotis Kanavos
503 f2d88248 Panagiotis Kanavos
		public void ShowPreferences(string currentTab)
504 4ec636f6 Panagiotis Kanavos
		{
505 1e26eceb Panagiotis Kanavos
			//Settings.Reload();
506 ee950288 pkanavos
            
507 f2d88248 Panagiotis Kanavos
		    var preferences = new PreferencesViewModel(_windowManager, _events, this, Settings,currentTab);
508 f2d88248 Panagiotis Kanavos
		    _windowManager.ShowDialog(preferences);
509 4ec636f6 Panagiotis Kanavos
			
510 4ec636f6 Panagiotis Kanavos
		}
511 4ec636f6 Panagiotis Kanavos
512 4ec636f6 Panagiotis Kanavos
		public void AboutPithos()
513 4ec636f6 Panagiotis Kanavos
		{
514 6b0de454 Panagiotis Kanavos
			var about = IoC.Get<AboutViewModel>();
515 6b0de454 Panagiotis Kanavos
		    about.LatestVersion=_sparkle.LatestVersion;
516 4ec636f6 Panagiotis Kanavos
			_windowManager.ShowWindow(about);
517 4ec636f6 Panagiotis Kanavos
		}
518 4ec636f6 Panagiotis Kanavos
519 4ec636f6 Panagiotis Kanavos
		public void SendFeedback()
520 4ec636f6 Panagiotis Kanavos
		{
521 4ec636f6 Panagiotis Kanavos
			var feedBack =  IoC.Get<FeedbackViewModel>();
522 4ec636f6 Panagiotis Kanavos
			_windowManager.ShowWindow(feedBack);
523 4ec636f6 Panagiotis Kanavos
		}
524 4ec636f6 Panagiotis Kanavos
525 4ec636f6 Panagiotis Kanavos
		//public PithosCommand OpenPithosFolderCommand { get; private set; }
526 4ec636f6 Panagiotis Kanavos
527 4ec636f6 Panagiotis Kanavos
		public void OpenPithosFolder()
528 4ec636f6 Panagiotis Kanavos
		{
529 4ec636f6 Panagiotis Kanavos
			var account = Settings.Accounts.FirstOrDefault(acc => acc.IsActive);
530 4ec636f6 Panagiotis Kanavos
			if (account == null)
531 4ec636f6 Panagiotis Kanavos
				return;
532 4ec636f6 Panagiotis Kanavos
			Process.Start(account.RootPath);
533 4ec636f6 Panagiotis Kanavos
		}
534 4ec636f6 Panagiotis Kanavos
535 4ec636f6 Panagiotis Kanavos
		public void OpenPithosFolder(AccountInfo account)
536 4ec636f6 Panagiotis Kanavos
		{
537 4ec636f6 Panagiotis Kanavos
			Process.Start(account.AccountPath);
538 4ec636f6 Panagiotis Kanavos
		}
539 4ec636f6 Panagiotis Kanavos
540 4ec636f6 Panagiotis Kanavos
		
541 7ce172f6 George Pantazis
542 4ec636f6 Panagiotis Kanavos
		public void GoToSite()
543 4ec636f6 Panagiotis Kanavos
		{            
544 7ce172f6 George Pantazis
			var site = Properties.Settings.Default.ProductionServer;
545 4ec636f6 Panagiotis Kanavos
			Process.Start(site);            
546 4ec636f6 Panagiotis Kanavos
		}
547 7ce172f6 George Pantazis
548 6aa29f4f Panagiotis Kanavos
549 4ec636f6 Panagiotis Kanavos
		public void GoToSite(AccountInfo account)
550 4ec636f6 Panagiotis Kanavos
		{
551 9d2c0fc0 Panagiotis Kanavos
		    var uri = account.SiteUri.Replace("http://","https://");            
552 9d2c0fc0 Panagiotis Kanavos
		    Process.Start(uri);
553 4ec636f6 Panagiotis Kanavos
		}
554 4ec636f6 Panagiotis Kanavos
555 72eeda84 Panagiotis Kanavos
	    private bool _statusVisible;
556 72eeda84 Panagiotis Kanavos
557 72eeda84 Panagiotis Kanavos
	    public string MiniStatusCaption
558 72eeda84 Panagiotis Kanavos
	    {
559 72eeda84 Panagiotis Kanavos
	        get
560 72eeda84 Panagiotis Kanavos
	        {
561 72eeda84 Panagiotis Kanavos
	            return  _statusVisible ? "Hide Status Window" : "Show Status Window";
562 72eeda84 Panagiotis Kanavos
	        }
563 72eeda84 Panagiotis Kanavos
	    }
564 72eeda84 Panagiotis Kanavos
565 f4a72cb8 pkanavos
	    public bool HasConflicts
566 f4a72cb8 pkanavos
	    {
567 f4a72cb8 pkanavos
            get { return true; }
568 f4a72cb8 pkanavos
	    }
569 f4a72cb8 pkanavos
        public void ShowConflicts()
570 f4a72cb8 pkanavos
        {
571 bc27bb7e Panagiotis Kanavos
            _windowManager.ShowWindow(IoC.Get<ConflictsViewModel>());            
572 f4a72cb8 pkanavos
        }
573 f4a72cb8 pkanavos
574 9d2c0fc0 Panagiotis Kanavos
	    /// <summary>
575 7f5882da Panagiotis Kanavos
        /// Open an explorer window to the target path's directory
576 7f5882da Panagiotis Kanavos
        /// and select the file
577 7f5882da Panagiotis Kanavos
        /// </summary>
578 7f5882da Panagiotis Kanavos
        /// <param name="entry"></param>
579 7f5882da Panagiotis Kanavos
        public void GoToFile(FileEntry entry)
580 7f5882da Panagiotis Kanavos
        {
581 7f5882da Panagiotis Kanavos
            var fullPath = entry.FullPath;
582 7f5882da Panagiotis Kanavos
            if (!File.Exists(fullPath) && !Directory.Exists(fullPath))
583 7f5882da Panagiotis Kanavos
                return;
584 7f5882da Panagiotis Kanavos
            Process.Start("explorer.exe","/select, " + fullPath);
585 7f5882da Panagiotis Kanavos
        }
586 7f5882da Panagiotis Kanavos
587 db8a9589 Panagiotis Kanavos
        public void OpenLogPath()
588 db8a9589 Panagiotis Kanavos
        {
589 adfa4645 Panagiotis Kanavos
            var pithosDataPath = PithosSettings.PithosDataPath;
590 db8a9589 Panagiotis Kanavos
591 db8a9589 Panagiotis Kanavos
            Process.Start(pithosDataPath);
592 db8a9589 Panagiotis Kanavos
        }
593 db8a9589 Panagiotis Kanavos
        
594 db8a9589 Panagiotis Kanavos
        public void ShowFileProperties()
595 4ec636f6 Panagiotis Kanavos
		{
596 4ec636f6 Panagiotis Kanavos
			var account = Settings.Accounts.First(acc => acc.IsActive);            
597 4ec636f6 Panagiotis Kanavos
			var dir = new DirectoryInfo(account.RootPath + @"\pithos");
598 4ec636f6 Panagiotis Kanavos
			var files=dir.GetFiles();
599 4ec636f6 Panagiotis Kanavos
			var r=new Random();
600 4ec636f6 Panagiotis Kanavos
			var idx=r.Next(0, files.Length);
601 4ec636f6 Panagiotis Kanavos
			ShowFileProperties(files[idx].FullName);            
602 4ec636f6 Panagiotis Kanavos
		}
603 4ec636f6 Panagiotis Kanavos
604 4ec636f6 Panagiotis Kanavos
		public void ShowFileProperties(string filePath)
605 4ec636f6 Panagiotis Kanavos
		{
606 4ec636f6 Panagiotis Kanavos
			if (String.IsNullOrWhiteSpace(filePath))
607 4ec636f6 Panagiotis Kanavos
				throw new ArgumentNullException("filePath");
608 4f6d51d4 Panagiotis Kanavos
			if (!File.Exists(filePath) && !Directory.Exists(filePath))
609 4ec636f6 Panagiotis Kanavos
				throw new ArgumentException(String.Format("Non existent file {0}",filePath),"filePath");
610 4ec636f6 Panagiotis Kanavos
			Contract.EndContractBlock();
611 4ec636f6 Panagiotis Kanavos
612 4ec636f6 Panagiotis Kanavos
			var pair=(from monitor in  Monitors
613 4ec636f6 Panagiotis Kanavos
							   where filePath.StartsWith(monitor.Value.RootPath, StringComparison.InvariantCultureIgnoreCase)
614 4ec636f6 Panagiotis Kanavos
								   select monitor).FirstOrDefault();
615 255f5f86 Panagiotis Kanavos
			var accountMonitor = pair.Value;
616 4ec636f6 Panagiotis Kanavos
617 4ec636f6 Panagiotis Kanavos
			if (accountMonitor == null)
618 4ec636f6 Panagiotis Kanavos
				return;
619 4ec636f6 Panagiotis Kanavos
620 4ec636f6 Panagiotis Kanavos
			var infoTask=Task.Factory.StartNew(()=>accountMonitor.GetObjectInfo(filePath));
621 4ec636f6 Panagiotis Kanavos
622 4ec636f6 Panagiotis Kanavos
			
623 4ec636f6 Panagiotis Kanavos
624 4ec636f6 Panagiotis Kanavos
			var fileProperties = new FilePropertiesViewModel(this, infoTask,filePath);
625 4ec636f6 Panagiotis Kanavos
			_windowManager.ShowWindow(fileProperties);
626 4ec636f6 Panagiotis Kanavos
		} 
627 4ec636f6 Panagiotis Kanavos
		
628 4ec636f6 Panagiotis Kanavos
		public void ShowContainerProperties()
629 4ec636f6 Panagiotis Kanavos
		{
630 4ec636f6 Panagiotis Kanavos
			var account = Settings.Accounts.First(acc => acc.IsActive);            
631 4ec636f6 Panagiotis Kanavos
			var dir = new DirectoryInfo(account.RootPath);
632 4ec636f6 Panagiotis Kanavos
			var fullName = (from folder in dir.EnumerateDirectories()
633 4ec636f6 Panagiotis Kanavos
							where (folder.Attributes & FileAttributes.Hidden) == 0
634 4ec636f6 Panagiotis Kanavos
							select folder.FullName).First();
635 4ec636f6 Panagiotis Kanavos
			ShowContainerProperties(fullName);            
636 4ec636f6 Panagiotis Kanavos
		}
637 4ec636f6 Panagiotis Kanavos
638 4ec636f6 Panagiotis Kanavos
		public void ShowContainerProperties(string filePath)
639 4ec636f6 Panagiotis Kanavos
		{
640 4ec636f6 Panagiotis Kanavos
			if (String.IsNullOrWhiteSpace(filePath))
641 4ec636f6 Panagiotis Kanavos
				throw new ArgumentNullException("filePath");
642 4ec636f6 Panagiotis Kanavos
			if (!Directory.Exists(filePath))
643 4ec636f6 Panagiotis Kanavos
				throw new ArgumentException(String.Format("Non existent file {0}",filePath),"filePath");
644 4ec636f6 Panagiotis Kanavos
			Contract.EndContractBlock();
645 4ec636f6 Panagiotis Kanavos
646 4ec636f6 Panagiotis Kanavos
			var pair=(from monitor in  Monitors
647 4ec636f6 Panagiotis Kanavos
							   where filePath.StartsWith(monitor.Value.RootPath, StringComparison.InvariantCultureIgnoreCase)
648 4ec636f6 Panagiotis Kanavos
								   select monitor).FirstOrDefault();
649 255f5f86 Panagiotis Kanavos
			var accountMonitor = pair.Value;            
650 4ec636f6 Panagiotis Kanavos
			var info = accountMonitor.GetContainerInfo(filePath);
651 4ec636f6 Panagiotis Kanavos
652 4ec636f6 Panagiotis Kanavos
			
653 4ec636f6 Panagiotis Kanavos
654 4ec636f6 Panagiotis Kanavos
			var containerProperties = new ContainerPropertiesViewModel(this, info,filePath);
655 4ec636f6 Panagiotis Kanavos
			_windowManager.ShowWindow(containerProperties);
656 4ec636f6 Panagiotis Kanavos
		}
657 4ec636f6 Panagiotis Kanavos
658 255f5f86 Panagiotis Kanavos
		public void SynchNow()
659 255f5f86 Panagiotis Kanavos
		{
660 31c97141 Panagiotis Kanavos
			_pollAgent.SynchNow();
661 255f5f86 Panagiotis Kanavos
		}
662 133f83c2 Panagiotis Kanavos
663 4ec636f6 Panagiotis Kanavos
		public ObjectInfo RefreshObjectInfo(ObjectInfo currentInfo)
664 4ec636f6 Panagiotis Kanavos
		{
665 4ec636f6 Panagiotis Kanavos
			if (currentInfo==null)
666 4ec636f6 Panagiotis Kanavos
				throw new ArgumentNullException("currentInfo");
667 ebc37b0d pkanavos
			Contract.EndContractBlock();		    
668 ebc37b0d pkanavos
            var monitor = Monitors[currentInfo.AccountKey];
669 4ec636f6 Panagiotis Kanavos
			var newInfo=monitor.CloudClient.GetObjectInfo(currentInfo.Account, currentInfo.Container, currentInfo.Name);
670 4ec636f6 Panagiotis Kanavos
			return newInfo;
671 4ec636f6 Panagiotis Kanavos
		}
672 4ec636f6 Panagiotis Kanavos
673 4ec636f6 Panagiotis Kanavos
		public ContainerInfo RefreshContainerInfo(ContainerInfo container)
674 4ec636f6 Panagiotis Kanavos
		{
675 4ec636f6 Panagiotis Kanavos
			if (container == null)
676 4ec636f6 Panagiotis Kanavos
				throw new ArgumentNullException("container");
677 4ec636f6 Panagiotis Kanavos
			Contract.EndContractBlock();
678 4ec636f6 Panagiotis Kanavos
679 ebc37b0d pkanavos
			var monitor = Monitors[container.AccountKey];
680 4ec636f6 Panagiotis Kanavos
			var newInfo = monitor.CloudClient.GetContainerInfo(container.Account, container.Name);
681 4ec636f6 Panagiotis Kanavos
			return newInfo;
682 4ec636f6 Panagiotis Kanavos
		}
683 4ec636f6 Panagiotis Kanavos
684 2341c603 pkanavos
	    private bool _isPaused;
685 2341c603 pkanavos
	    public bool IsPaused
686 2341c603 pkanavos
	    {
687 2341c603 pkanavos
	        get { return _isPaused; }
688 2341c603 pkanavos
	        set
689 2341c603 pkanavos
	        {
690 2341c603 pkanavos
	            _isPaused = value;
691 2341c603 pkanavos
                PauseSyncCaption = IsPaused ? "Resume syncing" : "Pause syncing";
692 2341c603 pkanavos
                var iconKey = IsPaused ? "TraySyncPaused" : "TrayInSynch";
693 2341c603 pkanavos
                StatusIcon = String.Format(@"../Images/{0}.ico", iconKey);
694 2341c603 pkanavos
695 2341c603 pkanavos
                NotifyOfPropertyChange(() => IsPaused);
696 2341c603 pkanavos
	        }
697 2341c603 pkanavos
	    }
698 4ec636f6 Panagiotis Kanavos
699 2341c603 pkanavos
	    public void ToggleSynching()
700 4ec636f6 Panagiotis Kanavos
		{
701 2341c603 pkanavos
			IsPaused=!IsPaused;
702 2341c603 pkanavos
			foreach (var monitor in Monitors.Values)
703 4ec636f6 Panagiotis Kanavos
			{
704 2341c603 pkanavos
			    monitor.Pause = IsPaused ;
705 4ec636f6 Panagiotis Kanavos
			}
706 2341c603 pkanavos
            _pollAgent.Pause = IsPaused;
707 2341c603 pkanavos
            _networkAgent.Pause = IsPaused;
708 2341c603 pkanavos
709 4ec636f6 Panagiotis Kanavos
710 4ec636f6 Panagiotis Kanavos
		}
711 4ec636f6 Panagiotis Kanavos
712 d78d765c pkanavos
        public void ExitPithos()
713 d78d765c pkanavos
        {
714 d78d765c pkanavos
            try
715 d78d765c pkanavos
            {
716 4ec636f6 Panagiotis Kanavos
717 d78d765c pkanavos
                foreach (var monitor in Monitors.Select(pair => pair.Value))
718 d78d765c pkanavos
                {
719 d78d765c pkanavos
                    monitor.Stop();
720 d78d765c pkanavos
                }
721 d78d765c pkanavos
722 d78d765c pkanavos
                var view = GetView() as Window;
723 d78d765c pkanavos
                if (view != null)
724 d78d765c pkanavos
                    view.Close();
725 d78d765c pkanavos
            }
726 d78d765c pkanavos
            catch (Exception exc)
727 d78d765c pkanavos
            {
728 8dcf435d Panagiotis Kanavos
                Log.Info("Exception while exiting", exc);                
729 8dcf435d Panagiotis Kanavos
            }
730 8dcf435d Panagiotis Kanavos
            finally
731 8dcf435d Panagiotis Kanavos
            {
732 d78d765c pkanavos
                Application.Current.Shutdown();
733 d78d765c pkanavos
            }
734 d78d765c pkanavos
        }
735 d78d765c pkanavos
736 d78d765c pkanavos
	    #endregion
737 4ec636f6 Panagiotis Kanavos
738 4ec636f6 Panagiotis Kanavos
739 4f6d51d4 Panagiotis Kanavos
		private readonly Dictionary<PithosStatus, StatusInfo> _iconNames = new List<StatusInfo>
740 4ec636f6 Panagiotis Kanavos
			{
741 4ec636f6 Panagiotis Kanavos
				new StatusInfo(PithosStatus.InSynch, "All files up to date", "TrayInSynch"),
742 174bbb6e Panagiotis Kanavos
				new StatusInfo(PithosStatus.PollSyncing, "Polling Files", "TraySynching"),
743 174bbb6e Panagiotis Kanavos
                new StatusInfo(PithosStatus.LocalSyncing, "Syncing Files", "TraySynching"),
744 4ec636f6 Panagiotis Kanavos
				new StatusInfo(PithosStatus.SyncPaused, "Sync Paused", "TraySyncPaused")
745 4ec636f6 Panagiotis Kanavos
			}.ToDictionary(s => s.Status);
746 4ec636f6 Panagiotis Kanavos
747 4ec636f6 Panagiotis Kanavos
		readonly IWindowManager _windowManager;
748 255f5f86 Panagiotis Kanavos
		
749 174bbb6e Panagiotis Kanavos
        //private int _syncCount=0;
750 174bbb6e Panagiotis Kanavos
751 174bbb6e Panagiotis Kanavos
752 174bbb6e Panagiotis Kanavos
        private PithosStatus _pithosStatus = PithosStatus.Disconnected;
753 174bbb6e Panagiotis Kanavos
754 174bbb6e Panagiotis Kanavos
        public void SetPithosStatus(PithosStatus status)
755 174bbb6e Panagiotis Kanavos
        {
756 174bbb6e Panagiotis Kanavos
            if (_pithosStatus == PithosStatus.LocalSyncing && status == PithosStatus.PollComplete)
757 174bbb6e Panagiotis Kanavos
                return;
758 174bbb6e Panagiotis Kanavos
            if (_pithosStatus == PithosStatus.PollSyncing && status == PithosStatus.LocalComplete)
759 174bbb6e Panagiotis Kanavos
                return;
760 174bbb6e Panagiotis Kanavos
            if (status == PithosStatus.LocalComplete || status == PithosStatus.PollComplete)
761 174bbb6e Panagiotis Kanavos
                _pithosStatus = PithosStatus.InSynch;
762 174bbb6e Panagiotis Kanavos
            else
763 174bbb6e Panagiotis Kanavos
                _pithosStatus = status;
764 174bbb6e Panagiotis Kanavos
            UpdateStatus();
765 174bbb6e Panagiotis Kanavos
        }
766 174bbb6e Panagiotis Kanavos
767 174bbb6e Panagiotis Kanavos
        public void SetPithosStatus(PithosStatus status,string message)
768 174bbb6e Panagiotis Kanavos
        {
769 174bbb6e Panagiotis Kanavos
            StatusMessage = message;
770 174bbb6e Panagiotis Kanavos
            SetPithosStatus(status);
771 174bbb6e Panagiotis Kanavos
        }
772 174bbb6e Panagiotis Kanavos
773 f4a72cb8 pkanavos
	  /*  public Notifier GetNotifier(Notification startNotification, Notification endNotification)
774 f4a72cb8 pkanavos
	    {
775 f4a72cb8 pkanavos
	        return new Notifier(this, startNotification, endNotification);
776 f4a72cb8 pkanavos
	    }*/
777 174bbb6e Panagiotis Kanavos
778 f4a72cb8 pkanavos
	    public Notifier GetNotifier(string startMessage, string endMessage, params object[] args)
779 f4a72cb8 pkanavos
	    {
780 f4a72cb8 pkanavos
	        return new Notifier(this, 
781 f4a72cb8 pkanavos
                new StatusNotification(String.Format(startMessage,args)), 
782 f4a72cb8 pkanavos
                new StatusNotification(String.Format(endMessage,args)));
783 f4a72cb8 pkanavos
	    }
784 c53aa229 Panagiotis Kanavos
785 f4a72cb8 pkanavos
786 f4a72cb8 pkanavos
	    ///<summary>
787 cf761c0d Panagiotis Kanavos
		/// Updates the visual status indicators of the application depending on status changes, e.g. icon, stat		
788 cf761c0d Panagiotis Kanavos
		///</summary>
789 4ec636f6 Panagiotis Kanavos
		public void UpdateStatus()
790 4ec636f6 Panagiotis Kanavos
		{
791 4ec636f6 Panagiotis Kanavos
792 174bbb6e Panagiotis Kanavos
			if (_iconNames.ContainsKey(_pithosStatus))
793 4ec636f6 Panagiotis Kanavos
			{
794 174bbb6e Panagiotis Kanavos
				var info = _iconNames[_pithosStatus];
795 4ec636f6 Panagiotis Kanavos
				StatusIcon = String.Format(@"../Images/{0}.ico", info.IconName);
796 4ec636f6 Panagiotis Kanavos
			}
797 174bbb6e Panagiotis Kanavos
798 174bbb6e Panagiotis Kanavos
            if (_pithosStatus == PithosStatus.InSynch)
799 174bbb6e Panagiotis Kanavos
                StatusMessage = "All files up to date";
800 4ec636f6 Panagiotis Kanavos
		}
801 4ec636f6 Panagiotis Kanavos
802 4ec636f6 Panagiotis Kanavos
803 4ec636f6 Panagiotis Kanavos
	   
804 4ec636f6 Panagiotis Kanavos
		private Task StartMonitor(PithosMonitor monitor,int retries=0)
805 4ec636f6 Panagiotis Kanavos
		{
806 4ec636f6 Panagiotis Kanavos
			return Task.Factory.StartNew(() =>
807 4ec636f6 Panagiotis Kanavos
			{
808 4ec636f6 Panagiotis Kanavos
				using (log4net.ThreadContext.Stacks["Monitor"].Push("Start"))
809 4ec636f6 Panagiotis Kanavos
				{
810 4ec636f6 Panagiotis Kanavos
					try
811 4ec636f6 Panagiotis Kanavos
					{
812 4ec636f6 Panagiotis Kanavos
						Log.InfoFormat("Start Monitoring {0}", monitor.UserName);
813 4ec636f6 Panagiotis Kanavos
814 4ec636f6 Panagiotis Kanavos
						monitor.Start();
815 4ec636f6 Panagiotis Kanavos
					}
816 4ec636f6 Panagiotis Kanavos
					catch (WebException exc)
817 4ec636f6 Panagiotis Kanavos
					{
818 4ec636f6 Panagiotis Kanavos
						if (AbandonRetry(monitor, retries))
819 4ec636f6 Panagiotis Kanavos
							return;
820 4ec636f6 Panagiotis Kanavos
821 255f5f86 Panagiotis Kanavos
						HttpStatusCode statusCode =HttpStatusCode.OK;
822 255f5f86 Panagiotis Kanavos
						var response = exc.Response as HttpWebResponse;
823 255f5f86 Panagiotis Kanavos
						if(response!=null)
824 255f5f86 Panagiotis Kanavos
							statusCode = response.StatusCode;
825 255f5f86 Panagiotis Kanavos
826 255f5f86 Panagiotis Kanavos
						switch (statusCode)
827 255f5f86 Panagiotis Kanavos
						{
828 255f5f86 Panagiotis Kanavos
							case HttpStatusCode.Unauthorized:
829 255f5f86 Panagiotis Kanavos
								var message = String.Format("API Key Expired for {0}. Starting Renewal",
830 255f5f86 Panagiotis Kanavos
															monitor.UserName);
831 255f5f86 Panagiotis Kanavos
								Log.Error(message, exc);
832 97d149c1 pkanavos
                                var account = Settings.Accounts.Find(acc => acc.AccountKey == new Uri(new Uri(monitor.AuthenticationUrl), monitor.UserName));                                
833 1e26eceb Panagiotis Kanavos
						        account.IsExpired = true;
834 1e26eceb Panagiotis Kanavos
                                Notify(new ExpirationNotification(account));
835 1e26eceb Panagiotis Kanavos
								//TryAuthorize(monitor.UserName, retries).Wait();
836 255f5f86 Panagiotis Kanavos
								break;
837 255f5f86 Panagiotis Kanavos
							case HttpStatusCode.ProxyAuthenticationRequired:
838 255f5f86 Panagiotis Kanavos
								TryAuthenticateProxy(monitor,retries);
839 255f5f86 Panagiotis Kanavos
								break;
840 255f5f86 Panagiotis Kanavos
							default:
841 255f5f86 Panagiotis Kanavos
								TryLater(monitor, exc, retries);
842 255f5f86 Panagiotis Kanavos
								break;
843 255f5f86 Panagiotis Kanavos
						}
844 4ec636f6 Panagiotis Kanavos
					}
845 4ec636f6 Panagiotis Kanavos
					catch (Exception exc)
846 4ec636f6 Panagiotis Kanavos
					{
847 4ec636f6 Panagiotis Kanavos
						if (AbandonRetry(monitor, retries)) 
848 4ec636f6 Panagiotis Kanavos
							return;
849 4ec636f6 Panagiotis Kanavos
850 4ec636f6 Panagiotis Kanavos
						TryLater(monitor,exc,retries);
851 4ec636f6 Panagiotis Kanavos
					}
852 4ec636f6 Panagiotis Kanavos
				}
853 4ec636f6 Panagiotis Kanavos
			});
854 4ec636f6 Panagiotis Kanavos
		}
855 4ec636f6 Panagiotis Kanavos
856 255f5f86 Panagiotis Kanavos
		private void TryAuthenticateProxy(PithosMonitor monitor,int retries)
857 255f5f86 Panagiotis Kanavos
		{
858 255f5f86 Panagiotis Kanavos
			Execute.OnUIThread(() =>
859 255f5f86 Panagiotis Kanavos
								   {                                       
860 255f5f86 Panagiotis Kanavos
									   var proxyAccount = IoC.Get<ProxyAccountViewModel>();
861 7f5882da Panagiotis Kanavos
										proxyAccount.Settings = Settings;
862 255f5f86 Panagiotis Kanavos
									   if (true != _windowManager.ShowDialog(proxyAccount)) 
863 255f5f86 Panagiotis Kanavos
										   return;
864 255f5f86 Panagiotis Kanavos
									   StartMonitor(monitor, retries);
865 255f5f86 Panagiotis Kanavos
									   NotifyOfPropertyChange(() => Accounts);
866 255f5f86 Panagiotis Kanavos
								   });
867 255f5f86 Panagiotis Kanavos
		}
868 65282d58 Panagiotis Kanavos
869 255f5f86 Panagiotis Kanavos
		private bool AbandonRetry(PithosMonitor monitor, int retries)
870 4ec636f6 Panagiotis Kanavos
		{
871 4ec636f6 Panagiotis Kanavos
			if (retries > 1)
872 4ec636f6 Panagiotis Kanavos
			{
873 4ec636f6 Panagiotis Kanavos
				var message = String.Format("Monitoring of account {0} has failed too many times. Will not retry",
874 4ec636f6 Panagiotis Kanavos
											monitor.UserName);
875 4ec636f6 Panagiotis Kanavos
				_events.Publish(new Notification
876 4ec636f6 Panagiotis Kanavos
									{Title = "Account monitoring failed", Message = message, Level = TraceLevel.Error});
877 4ec636f6 Panagiotis Kanavos
				return true;
878 4ec636f6 Panagiotis Kanavos
			}
879 4ec636f6 Panagiotis Kanavos
			return false;
880 4ec636f6 Panagiotis Kanavos
		}
881 4ec636f6 Panagiotis Kanavos
882 4ec636f6 Panagiotis Kanavos
883 7f5882da Panagiotis Kanavos
	    private void TryLater(PithosMonitor monitor, Exception exc,int retries)
884 4ec636f6 Panagiotis Kanavos
		{
885 4ec636f6 Panagiotis Kanavos
			var message = String.Format("An exception occured. Can't start monitoring\nWill retry in 10 seconds");
886 4ec636f6 Panagiotis Kanavos
			Task.Factory.StartNewDelayed(10000, () => StartMonitor(monitor,retries+1));
887 4ec636f6 Panagiotis Kanavos
			_events.Publish(new Notification
888 4ec636f6 Panagiotis Kanavos
								{Title = "Error", Message = message, Level = TraceLevel.Error});
889 4ec636f6 Panagiotis Kanavos
			Log.Error(message, exc);
890 4ec636f6 Panagiotis Kanavos
		}
891 4ec636f6 Panagiotis Kanavos
892 4ec636f6 Panagiotis Kanavos
893 4ec636f6 Panagiotis Kanavos
		public void NotifyChange(string status, TraceLevel level=TraceLevel.Info)
894 4ec636f6 Panagiotis Kanavos
		{
895 4f6d51d4 Panagiotis Kanavos
			StatusMessage = status;
896 4ec636f6 Panagiotis Kanavos
			
897 6b0de454 Panagiotis Kanavos
			_events.Publish(new Notification { Title = "Pithos+", Message = status, Level = level });
898 4ec636f6 Panagiotis Kanavos
		}
899 4ec636f6 Panagiotis Kanavos
900 4ec636f6 Panagiotis Kanavos
		public void NotifyChangedFile(string filePath)
901 4ec636f6 Panagiotis Kanavos
		{
902 7f5882da Panagiotis Kanavos
            if (RecentFiles.Any(e => e.FullPath == filePath))
903 7f5882da Panagiotis Kanavos
                return;
904 7f5882da Panagiotis Kanavos
            
905 4f6d51d4 Panagiotis Kanavos
			IProducerConsumerCollection<FileEntry> files=RecentFiles;
906 4ec636f6 Panagiotis Kanavos
			FileEntry popped;
907 4ec636f6 Panagiotis Kanavos
			while (files.Count > 5)
908 4ec636f6 Panagiotis Kanavos
				files.TryTake(out popped);
909 7f5882da Panagiotis Kanavos
            var entry = new FileEntry { FullPath = filePath };
910 4ec636f6 Panagiotis Kanavos
			files.TryAdd(entry);
911 4ec636f6 Panagiotis Kanavos
		}
912 4ec636f6 Panagiotis Kanavos
913 4ec636f6 Panagiotis Kanavos
		public void NotifyAccount(AccountInfo account)
914 4ec636f6 Panagiotis Kanavos
		{
915 4ec636f6 Panagiotis Kanavos
			if (account== null)
916 4ec636f6 Panagiotis Kanavos
				return;
917 4ec636f6 Panagiotis Kanavos
			//TODO: What happens to an existing account whose Token has changed?
918 4ec636f6 Panagiotis Kanavos
			account.SiteUri= String.Format("{0}/ui/?token={1}&user={2}",
919 eae84ae8 Panagiotis Kanavos
				account.SiteUri, Uri.EscapeDataString(account.Token),
920 255f5f86 Panagiotis Kanavos
				Uri.EscapeDataString(account.UserName));
921 4ec636f6 Panagiotis Kanavos
922 311d1cde Panagiotis Kanavos
			if (!Accounts.Any(item => item.UserName == account.UserName && item.SiteUri == account.SiteUri))
923 4ec636f6 Panagiotis Kanavos
				Accounts.TryAdd(account);
924 4ec636f6 Panagiotis Kanavos
925 4ec636f6 Panagiotis Kanavos
		}
926 4ec636f6 Panagiotis Kanavos
927 255f5f86 Panagiotis Kanavos
		public void NotifyConflicts(IEnumerable<FileSystemInfo> conflictFiles, string message)
928 255f5f86 Panagiotis Kanavos
		{
929 255f5f86 Panagiotis Kanavos
			if (conflictFiles == null)
930 255f5f86 Panagiotis Kanavos
				return;
931 7f5882da Panagiotis Kanavos
		    //Convert to list to avoid multiple iterations
932 7f5882da Panagiotis Kanavos
            var files = conflictFiles.ToList();
933 7f5882da Panagiotis Kanavos
			if (files.Count==0)
934 255f5f86 Panagiotis Kanavos
				return;
935 e5b65606 Panagiotis Kanavos
936 255f5f86 Panagiotis Kanavos
			UpdateStatus();
937 255f5f86 Panagiotis Kanavos
			//TODO: Create a more specific message. For now, just show a warning
938 7f5882da Panagiotis Kanavos
			NotifyForFiles(files,message,TraceLevel.Warning);
939 9c6d3193 Panagiotis Kanavos
940 255f5f86 Panagiotis Kanavos
		}
941 9c6d3193 Panagiotis Kanavos
942 255f5f86 Panagiotis Kanavos
		public void NotifyForFiles(IEnumerable<FileSystemInfo> files, string message,TraceLevel level=TraceLevel.Info)
943 255f5f86 Panagiotis Kanavos
		{
944 255f5f86 Panagiotis Kanavos
			if (files == null)
945 255f5f86 Panagiotis Kanavos
				return;
946 255f5f86 Panagiotis Kanavos
			if (!files.Any())
947 255f5f86 Panagiotis Kanavos
				return;
948 9c6d3193 Panagiotis Kanavos
949 255f5f86 Panagiotis Kanavos
			StatusMessage = message;
950 9c6d3193 Panagiotis Kanavos
951 6b0de454 Panagiotis Kanavos
			_events.Publish(new Notification { Title = "Pithos+", Message = message, Level = level});
952 255f5f86 Panagiotis Kanavos
		}
953 9c6d3193 Panagiotis Kanavos
954 255f5f86 Panagiotis Kanavos
		public void Notify(Notification notification)
955 255f5f86 Panagiotis Kanavos
		{
956 255f5f86 Panagiotis Kanavos
			_events.Publish(notification);
957 255f5f86 Panagiotis Kanavos
		}
958 e5b65606 Panagiotis Kanavos
959 4ec636f6 Panagiotis Kanavos
960 ebc37b0d pkanavos
		public void RemoveMonitor(string serverUrl,string accountName)
961 4ec636f6 Panagiotis Kanavos
		{
962 4ec636f6 Panagiotis Kanavos
			if (String.IsNullOrWhiteSpace(accountName))
963 4ec636f6 Panagiotis Kanavos
				return;
964 4ec636f6 Panagiotis Kanavos
965 ebc37b0d pkanavos
			var accountInfo=_accounts.FirstOrDefault(account => account.UserName == accountName && account.StorageUri.ToString().StartsWith(serverUrl));
966 8e89b160 Panagiotis Kanavos
            if (accountInfo != null)
967 8e89b160 Panagiotis Kanavos
            {
968 8e89b160 Panagiotis Kanavos
                _accounts.TryRemove(accountInfo);
969 8e89b160 Panagiotis Kanavos
                _pollAgent.RemoveAccount(accountInfo);
970 8e89b160 Panagiotis Kanavos
            }
971 4ec636f6 Panagiotis Kanavos
972 ebc37b0d pkanavos
            var accountKey = new Uri(new Uri(serverUrl),accountName);
973 8e89b160 Panagiotis Kanavos
		    PithosMonitor monitor;
974 ebc37b0d pkanavos
			if (Monitors.TryRemove(accountKey, out monitor))
975 4ec636f6 Panagiotis Kanavos
			{
976 4ec636f6 Panagiotis Kanavos
				monitor.Stop();
977 7f5882da Panagiotis Kanavos
                //TODO: Also remove any pending actions for this account
978 7f5882da Panagiotis Kanavos
                //from the network queue                
979 4ec636f6 Panagiotis Kanavos
			}
980 4ec636f6 Panagiotis Kanavos
		}
981 4ec636f6 Panagiotis Kanavos
982 4ec636f6 Panagiotis Kanavos
		public void RefreshOverlays()
983 4ec636f6 Panagiotis Kanavos
		{
984 4ec636f6 Panagiotis Kanavos
			foreach (var pair in Monitors)
985 4ec636f6 Panagiotis Kanavos
			{
986 4ec636f6 Panagiotis Kanavos
				var monitor = pair.Value;
987 4ec636f6 Panagiotis Kanavos
988 4ec636f6 Panagiotis Kanavos
				var path = monitor.RootPath;
989 4ec636f6 Panagiotis Kanavos
990 4ec636f6 Panagiotis Kanavos
				if (String.IsNullOrWhiteSpace(path))
991 4ec636f6 Panagiotis Kanavos
					continue;
992 4ec636f6 Panagiotis Kanavos
993 4ec636f6 Panagiotis Kanavos
				if (!Directory.Exists(path) && !File.Exists(path))
994 4ec636f6 Panagiotis Kanavos
					continue;
995 4ec636f6 Panagiotis Kanavos
996 4ec636f6 Panagiotis Kanavos
				IntPtr pathPointer = Marshal.StringToCoTaskMemAuto(path);
997 4ec636f6 Panagiotis Kanavos
998 4ec636f6 Panagiotis Kanavos
				try
999 4ec636f6 Panagiotis Kanavos
				{
1000 4ec636f6 Panagiotis Kanavos
					NativeMethods.SHChangeNotify(HChangeNotifyEventID.SHCNE_UPDATEITEM,
1001 4ec636f6 Panagiotis Kanavos
												 HChangeNotifyFlags.SHCNF_PATHW | HChangeNotifyFlags.SHCNF_FLUSHNOWAIT,
1002 4ec636f6 Panagiotis Kanavos
												 pathPointer, IntPtr.Zero);
1003 4ec636f6 Panagiotis Kanavos
				}
1004 4ec636f6 Panagiotis Kanavos
				finally
1005 4ec636f6 Panagiotis Kanavos
				{
1006 4ec636f6 Panagiotis Kanavos
					Marshal.FreeHGlobal(pathPointer);
1007 4ec636f6 Panagiotis Kanavos
				}
1008 4ec636f6 Panagiotis Kanavos
			}
1009 4ec636f6 Panagiotis Kanavos
		}
1010 4ec636f6 Panagiotis Kanavos
1011 4ec636f6 Panagiotis Kanavos
		#region Event Handlers
1012 4ec636f6 Panagiotis Kanavos
		
1013 4ec636f6 Panagiotis Kanavos
		public void Handle(SelectiveSynchChanges message)
1014 dd19241a pkanavos
		{
1015 dd19241a pkanavos
		    TaskEx.Run(() =>
1016 dd19241a pkanavos
		    {
1017 dd19241a pkanavos
		        PithosMonitor monitor;
1018 dd19241a pkanavos
		        if (Monitors.TryGetValue(message.Account.AccountKey, out monitor))
1019 dd19241a pkanavos
		        {
1020 43dd02a8 pkanavos
                    Selectives.SetIsSelectiveEnabled(message.Account.AccountKey, message.Enabled);
1021 dd19241a pkanavos
		            monitor.SetSelectivePaths(message.Uris, message.Added, message.Removed);
1022 dd19241a pkanavos
		        }
1023 026a6c5a Panagiotis Kanavos
1024 dd19241a pkanavos
		        var account = Accounts.FirstOrDefault(acc => acc.AccountKey == message.Account.AccountKey);
1025 dd19241a pkanavos
		        if (account != null)
1026 dd19241a pkanavos
		        {
1027 dd19241a pkanavos
		            this._pollAgent.SetSelectivePaths(account, message.Added, message.Removed);
1028 dd19241a pkanavos
		        }
1029 dd19241a pkanavos
		    });
1030 8f44fd3a pkanavos
1031 dd19241a pkanavos
		}
1032 4ec636f6 Panagiotis Kanavos
1033 4ec636f6 Panagiotis Kanavos
1034 7f5882da Panagiotis Kanavos
		private bool _pollStarted;
1035 049333d2 Panagiotis Kanavos
	    private Sparkle _sparkle;
1036 81c5c310 pkanavos
	    private bool _manualUpgradeCheck;
1037 eae84ae8 Panagiotis Kanavos
1038 049333d2 Panagiotis Kanavos
	    //SMELL: Doing so much work for notifications in the shell is wrong
1039 255f5f86 Panagiotis Kanavos
		//The notifications should be moved to their own view/viewmodel pair
1040 255f5f86 Panagiotis Kanavos
		//and different templates should be used for different message types
1041 255f5f86 Panagiotis Kanavos
		//This will also allow the addition of extra functionality, eg. actions
1042 255f5f86 Panagiotis Kanavos
		//
1043 4ec636f6 Panagiotis Kanavos
		public void Handle(Notification notification)
1044 4ec636f6 Panagiotis Kanavos
		{
1045 255f5f86 Panagiotis Kanavos
			UpdateStatus();
1046 e5b65606 Panagiotis Kanavos
1047 4ec636f6 Panagiotis Kanavos
			if (!Settings.ShowDesktopNotifications)
1048 4ec636f6 Panagiotis Kanavos
				return;
1049 eae84ae8 Panagiotis Kanavos
1050 255f5f86 Panagiotis Kanavos
			if (notification is PollNotification)
1051 255f5f86 Panagiotis Kanavos
			{
1052 255f5f86 Panagiotis Kanavos
				_pollStarted = true;
1053 255f5f86 Panagiotis Kanavos
				return;
1054 255f5f86 Panagiotis Kanavos
			}
1055 255f5f86 Panagiotis Kanavos
			if (notification is CloudNotification)
1056 255f5f86 Panagiotis Kanavos
			{
1057 255f5f86 Panagiotis Kanavos
				if (!_pollStarted) 
1058 255f5f86 Panagiotis Kanavos
					return;
1059 255f5f86 Panagiotis Kanavos
				_pollStarted= false;
1060 6b0de454 Panagiotis Kanavos
				notification.Title = "Pithos+";
1061 255f5f86 Panagiotis Kanavos
				notification.Message = "Start Synchronisation";
1062 255f5f86 Panagiotis Kanavos
			}
1063 255f5f86 Panagiotis Kanavos
1064 70e0b702 Panagiotis Kanavos
		    var deleteNotification = notification as CloudDeleteNotification;
1065 70e0b702 Panagiotis Kanavos
            if (deleteNotification != null)
1066 70e0b702 Panagiotis Kanavos
            {
1067 70e0b702 Panagiotis Kanavos
                StatusMessage = String.Format("Deleted {0}", deleteNotification.Data.Name);
1068 70e0b702 Panagiotis Kanavos
                return;
1069 70e0b702 Panagiotis Kanavos
            }
1070 70e0b702 Panagiotis Kanavos
1071 6bcdd8e2 Panagiotis Kanavos
		    var progress = notification as ProgressNotification;
1072 6b0de454 Panagiotis Kanavos
		    
1073 6b0de454 Panagiotis Kanavos
		    
1074 6b0de454 Panagiotis Kanavos
            if (progress != null)
1075 6bcdd8e2 Panagiotis Kanavos
		    {
1076 6b0de454 Panagiotis Kanavos
		        StatusMessage = String.Format("{0} {1:p2} of {2} - {3}",		                                      
1077 6bcdd8e2 Panagiotis Kanavos
                                              progress.Action,
1078 6bcdd8e2 Panagiotis Kanavos
		                                      progress.Block/(double)progress.TotalBlocks,
1079 6bcdd8e2 Panagiotis Kanavos
		                                      progress.FileSize.ToByteSize(),
1080 6bcdd8e2 Panagiotis Kanavos
		                                      progress.FileName);
1081 6bcdd8e2 Panagiotis Kanavos
		        return;
1082 6bcdd8e2 Panagiotis Kanavos
		    }
1083 6bcdd8e2 Panagiotis Kanavos
1084 174bbb6e Panagiotis Kanavos
		    var info = notification as StatusNotification;
1085 174bbb6e Panagiotis Kanavos
            if (info != null)
1086 174bbb6e Panagiotis Kanavos
            {
1087 6b0de454 Panagiotis Kanavos
                StatusMessage = info.Title;
1088 174bbb6e Panagiotis Kanavos
                return;
1089 174bbb6e Panagiotis Kanavos
            }
1090 255f5f86 Panagiotis Kanavos
			if (String.IsNullOrWhiteSpace(notification.Message) && String.IsNullOrWhiteSpace(notification.Title))
1091 255f5f86 Panagiotis Kanavos
				return;
1092 2dc6f765 Panagiotis Kanavos
1093 81c5c310 pkanavos
            if (notification.Level <= TraceLevel.Warning)
1094 81c5c310 pkanavos
			    ShowBalloonFor(notification);
1095 4ec636f6 Panagiotis Kanavos
		}
1096 174bbb6e Panagiotis Kanavos
1097 174bbb6e Panagiotis Kanavos
	    private void ShowBalloonFor(Notification notification)
1098 174bbb6e Panagiotis Kanavos
	    {
1099 174bbb6e Panagiotis Kanavos
            Contract.Requires(notification!=null);
1100 174bbb6e Panagiotis Kanavos
            
1101 174bbb6e Panagiotis Kanavos
            if (!Settings.ShowDesktopNotifications) 
1102 174bbb6e Panagiotis Kanavos
                return;
1103 174bbb6e Panagiotis Kanavos
            
1104 174bbb6e Panagiotis Kanavos
            BalloonIcon icon;
1105 174bbb6e Panagiotis Kanavos
	        switch (notification.Level)
1106 174bbb6e Panagiotis Kanavos
	        {
1107 81c5c310 pkanavos
                case TraceLevel.Verbose:
1108 174bbb6e Panagiotis Kanavos
	                return;
1109 81c5c310 pkanavos
	            case TraceLevel.Info:	            
1110 81c5c310 pkanavos
	                icon = BalloonIcon.Info;
1111 81c5c310 pkanavos
	                break;
1112 174bbb6e Panagiotis Kanavos
                case TraceLevel.Error:
1113 174bbb6e Panagiotis Kanavos
                    icon = BalloonIcon.Error;
1114 174bbb6e Panagiotis Kanavos
                    break;
1115 174bbb6e Panagiotis Kanavos
                case TraceLevel.Warning:
1116 174bbb6e Panagiotis Kanavos
	                icon = BalloonIcon.Warning;
1117 174bbb6e Panagiotis Kanavos
	                break;
1118 174bbb6e Panagiotis Kanavos
	            default:
1119 174bbb6e Panagiotis Kanavos
	                return;
1120 174bbb6e Panagiotis Kanavos
	        }
1121 174bbb6e Panagiotis Kanavos
1122 174bbb6e Panagiotis Kanavos
	        var tv = (ShellView) GetView();
1123 174bbb6e Panagiotis Kanavos
	        System.Action clickAction = null;
1124 174bbb6e Panagiotis Kanavos
	        if (notification is ExpirationNotification)
1125 174bbb6e Panagiotis Kanavos
	        {
1126 174bbb6e Panagiotis Kanavos
	            clickAction = () => ShowPreferences("AccountTab");
1127 174bbb6e Panagiotis Kanavos
	        }
1128 174bbb6e Panagiotis Kanavos
	        var balloon = new PithosBalloon
1129 174bbb6e Panagiotis Kanavos
	                          {
1130 174bbb6e Panagiotis Kanavos
	                              Title = notification.Title,
1131 174bbb6e Panagiotis Kanavos
	                              Message = notification.Message,
1132 174bbb6e Panagiotis Kanavos
	                              Icon = icon,
1133 174bbb6e Panagiotis Kanavos
	                              ClickAction = clickAction
1134 174bbb6e Panagiotis Kanavos
	                          };
1135 174bbb6e Panagiotis Kanavos
	        tv.TaskbarView.ShowCustomBalloon(balloon, PopupAnimation.Fade, 4000);
1136 174bbb6e Panagiotis Kanavos
	    }
1137 174bbb6e Panagiotis Kanavos
1138 174bbb6e Panagiotis Kanavos
	    #endregion
1139 4ec636f6 Panagiotis Kanavos
1140 4ec636f6 Panagiotis Kanavos
		public void Handle(ShowFilePropertiesEvent message)
1141 4ec636f6 Panagiotis Kanavos
		{
1142 4ec636f6 Panagiotis Kanavos
			if (message == null)
1143 4ec636f6 Panagiotis Kanavos
				throw new ArgumentNullException("message");
1144 4ec636f6 Panagiotis Kanavos
			if (String.IsNullOrWhiteSpace(message.FileName) )
1145 4ec636f6 Panagiotis Kanavos
				throw new ArgumentException("message");
1146 4ec636f6 Panagiotis Kanavos
			Contract.EndContractBlock();
1147 4ec636f6 Panagiotis Kanavos
1148 4ec636f6 Panagiotis Kanavos
			var fileName = message.FileName;
1149 255f5f86 Panagiotis Kanavos
			//TODO: Display file properties for non-container folders
1150 4ec636f6 Panagiotis Kanavos
			if (File.Exists(fileName))
1151 255f5f86 Panagiotis Kanavos
				//Retrieve the full name with exact casing. Pithos names are case sensitive				
1152 255f5f86 Panagiotis Kanavos
				ShowFileProperties(FileInfoExtensions.GetProperFilePathCapitalization(fileName));
1153 4ec636f6 Panagiotis Kanavos
			else if (Directory.Exists(fileName))
1154 255f5f86 Panagiotis Kanavos
				//Retrieve the full name with exact casing. Pithos names are case sensitive
1155 4f6d51d4 Panagiotis Kanavos
			{
1156 255f5f86 Panagiotis Kanavos
				var path = FileInfoExtensions.GetProperDirectoryCapitalization(fileName);
1157 255f5f86 Panagiotis Kanavos
				if (IsContainer(path))
1158 255f5f86 Panagiotis Kanavos
					ShowContainerProperties(path);
1159 255f5f86 Panagiotis Kanavos
				else
1160 255f5f86 Panagiotis Kanavos
					ShowFileProperties(path);
1161 4f6d51d4 Panagiotis Kanavos
			}
1162 4ec636f6 Panagiotis Kanavos
		}
1163 4f6d51d4 Panagiotis Kanavos
1164 255f5f86 Panagiotis Kanavos
		private bool IsContainer(string path)
1165 255f5f86 Panagiotis Kanavos
		{
1166 255f5f86 Panagiotis Kanavos
			var matchingFolders = from account in _accounts
1167 255f5f86 Panagiotis Kanavos
								  from rootFolder in Directory.GetDirectories(account.AccountPath)
1168 255f5f86 Panagiotis Kanavos
								  where rootFolder.Equals(path, StringComparison.InvariantCultureIgnoreCase)
1169 255f5f86 Panagiotis Kanavos
								  select rootFolder;
1170 255f5f86 Panagiotis Kanavos
			return matchingFolders.Any();
1171 255f5f86 Panagiotis Kanavos
		}
1172 255f5f86 Panagiotis Kanavos
1173 255f5f86 Panagiotis Kanavos
		public FileStatus GetFileStatus(string localFileName)
1174 255f5f86 Panagiotis Kanavos
		{
1175 255f5f86 Panagiotis Kanavos
			if (String.IsNullOrWhiteSpace(localFileName))
1176 255f5f86 Panagiotis Kanavos
				throw new ArgumentNullException("localFileName");
1177 255f5f86 Panagiotis Kanavos
			Contract.EndContractBlock();
1178 255f5f86 Panagiotis Kanavos
			
1179 255f5f86 Panagiotis Kanavos
			var statusKeeper = IoC.Get<IStatusKeeper>();
1180 255f5f86 Panagiotis Kanavos
			var status=statusKeeper.GetFileStatus(localFileName);
1181 255f5f86 Panagiotis Kanavos
			return status;
1182 255f5f86 Panagiotis Kanavos
		}
1183 fe62b7f4 Panagiotis Kanavos
1184 fe62b7f4 Panagiotis Kanavos
	    public void RemoveAccountFromDatabase(AccountSettings account)
1185 fe62b7f4 Panagiotis Kanavos
	    {
1186 fe62b7f4 Panagiotis Kanavos
            var statusKeeper = IoC.Get<IStatusKeeper>();
1187 fe62b7f4 Panagiotis Kanavos
            statusKeeper.ClearFolderStatus(account.RootPath);	        
1188 fe62b7f4 Panagiotis Kanavos
	    }
1189 4ec636f6 Panagiotis Kanavos
	}
1190 9bae55d1 Panagiotis Kanavos
}