Adding a new account now forces a logout to clear any stale Pithos cookies
[pithos-ms-client] / trunk / Pithos.Client.WPF / FileProperties / ConflictsViewModel.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Collections.ObjectModel;
4 using System.ComponentModel;
5 using System.ComponentModel.Composition;
6 using System.Diagnostics;
7 using System.IO;
8 using System.Linq;
9 using System.Text;
10 using Caliburn.Micro;
11 using Pithos.Client.WPF.Converters;
12 using Pithos.Client.WPF.Utils;
13 using Pithos.Core;
14 using Pithos.Interfaces;
15
16 namespace Pithos.Client.WPF.FileProperties
17 {
18     [TypeConverter(typeof(EnumTypeConverter))]
19     public enum ConflictAction
20     {
21         [Description("Defer Decision")]
22         Defer,
23         [Description("Keep Local")]
24         KeepLocal,
25         [Description("Keep Server")]
26         KeepServer,
27         [Description("Keep Both")]
28         KeepBoth,
29         [Description("Clear Record")]
30         ClearLocal
31     }
32
33     public class ConflictFile:PropertyChangedBase
34     {
35         private string _filePath;
36         public string FilePath
37         {
38             get { return _filePath; }
39             set
40             {
41                 _filePath = value;
42                 NotifyOfPropertyChange(()=>FilePath);
43             }
44         }
45
46         private string _reason;
47         public string Reason
48         {
49             get
50             {
51                 return _reason;
52             }
53             set
54             {
55                 _reason = value;
56                 NotifyOfPropertyChange(() => Reason);
57             }
58         }
59
60         private ConflictAction _action;
61         public ConflictAction Action
62         {
63             get { return _action; }
64             set
65             {
66                 _action = value;
67                 NotifyOfPropertyChange(()=>Action);
68             }
69         }
70
71         public DateTime LocalModified { get; set; }
72
73         public DateTime CloudModified { get; set; }
74
75         public void GoToFile()
76         {
77             if (!File.Exists(FilePath) && !Directory.Exists(FilePath))
78                 return;
79             Process.Start("explorer.exe", "/select, " + FilePath);
80         }
81     }
82     [Export(typeof(ConflictsViewModel))]
83     class ConflictsViewModel:Screen
84     {
85         [Import]
86         public IStatusKeeper StatusKeeper { get; set; }
87
88         [Import]
89         public IConflictResolver Resolver { get; set; }
90
91         private readonly ObservableCollection<ConflictFile> _conflicts;
92
93         public ObservableCollection<ConflictFile> Conflicts
94         {
95             get { return _conflicts; }
96         }
97
98         public bool HasConflicts
99         {
100             get { return Conflicts!=null && Conflicts.Count > 0; }
101         }
102
103         public bool HasNoConflicts
104         {
105             get { return !HasConflicts; }
106         }
107
108         public string[]  Actions
109         {
110             get { return new[] {"Keep Local", "Keep Server", "Keep Both"}; }
111         }
112
113         public ConflictsViewModel()
114         {
115                         this.DisplayName="Conflicts";
116             var fileStates = from state in FileState.Queryable
117                          where state.FileStatus == FileStatus.Conflict ||
118                                state.OverlayStatus == FileOverlayStatus.Conflict
119                          select state;
120             var conflicts = from state in fileStates
121                             let info=FileInfoExtensions.FromPath(state.FilePath)
122                             select new ConflictFile
123                                        {
124                                            FilePath = state.FilePath,
125                                            Reason=state.ConflictReason??state.FileStatus.Name() ,
126                                            LocalModified = info.LastWriteTime
127                                        };          
128             _conflicts = new ObservableCollection<ConflictFile>(conflicts.ToList());
129             
130         }
131
132         protected override void OnViewLoaded(object view)
133         {
134             base.OnViewLoaded(view);
135             StatusKeeper.CleanupOrphanStates();
136         }
137
138         /// <summary>
139         /// Open an explorer window to the target path's directory
140         /// and select the file
141         /// </summary>
142         /// <param name="entry"></param>
143         public void GoToFile(string fullPath)
144         {
145             if (!File.Exists(fullPath) && !Directory.Exists(fullPath))
146                 return;
147             Process.Start("explorer.exe", "/select, " + fullPath);
148         }
149
150         public void Apply()
151         {
152             var conflicts = from conflict in Conflicts
153                             where conflict.Action != ConflictAction.Defer
154                             select conflict;
155             Resolver.Resolve(conflicts);
156             
157             TryClose();
158         }
159
160         public void Cancel()
161         {
162             TryClose();
163         }
164
165         
166     }
167
168     internal interface IConflictResolver
169     {
170         void Resolve(IEnumerable<ConflictFile> conflicts);
171     }
172
173     [Export(typeof(IConflictResolver))]
174     public class DummyResolver:IConflictResolver
175     {
176         public void Resolve(IEnumerable<ConflictFile> conflicts)
177         {
178             
179         }
180     }
181 }