Changes for directories
[pithos-ms-client] / trunk / Pithos.Client.WPF / FileProperties / FilePropertiesViewModel.cs
1 // -----------------------------------------------------------------------
2 // <copyright file="FilePropertiesViewModel.cs" company="GRNet">
3 // Copyright 2011 GRNET S.A. All rights reserved.
4 // 
5 // Redistribution and use in source and binary forms, with or
6 // without modification, are permitted provided that the following
7 // conditions are met:
8 // 
9 //   1. Redistributions of source code must retain the above
10 //      copyright notice, this list of conditions and the following
11 //      disclaimer.
12 // 
13 //   2. Redistributions in binary form must reproduce the above
14 //      copyright notice, this list of conditions and the following
15 //      disclaimer in the documentation and/or other materials
16 //      provided with the distribution.
17 // 
18 // THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
19 // OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
22 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
25 // USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 // AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 // POSSIBILITY OF SUCH DAMAGE.
30 // 
31 // The views and conclusions contained in the software and
32 // documentation are those of the authors and should not be
33 // interpreted as representing official policies, either expressed
34 // or implied, of GRNET S.A.
35 // </copyright>
36 // -----------------------------------------------------------------------
37
38 using System.Collections;
39 using System.Collections.Concurrent;
40 using System.Collections.ObjectModel;
41 using System.Collections.Specialized;
42 using System.ComponentModel.Composition;
43 using System.Diagnostics;
44 using System.Diagnostics.Contracts;
45 using System.Drawing;
46 using System.IO;
47 using System.Net;
48 using System.Threading.Tasks;
49 using System.Windows;
50 using System.Windows.Interop;
51 using System.Windows.Media.Imaging;
52 using Caliburn.Micro;
53 using Pithos.Client.WPF.FileProperties;
54 using Pithos.Client.WPF.Properties;
55 using Pithos.Interfaces;
56 using Pithos.Network;
57
58 namespace Pithos.Client.WPF
59 {
60     using System;
61     using System.Collections.Generic;
62     using System.Linq;
63     using System.Text;
64
65     /// <summary>
66     /// TODO: Update summary.
67     /// </summary>
68     [Export(typeof(FilePropertiesViewModel))]
69     public class FilePropertiesViewModel : Screen
70     {
71         private string _title;
72         public string Title
73         {
74             get { return _title; }
75             set
76             {
77                 _title = value;
78                 NotifyOfPropertyChange(()=>Title);
79             }
80         }
81
82
83         private bool _isPublic;
84         public bool IsPublic
85         {
86             get { return _isPublic; }
87             set
88             {
89                 _isPublic = value;
90                 NotifyOfPropertyChange(()=>IsPublic);
91             }
92         }
93
94         private string _contentDisposition;
95         public string ContentDisposition
96         {
97             get { return _contentDisposition; }
98             set
99             {
100                 _contentDisposition = value;
101                 NotifyOfPropertyChange(() => ContentDisposition);
102             }
103         }
104
105         private string _contentEncoding;
106         public string ContentEncoding
107         {
108             get { return _contentEncoding; }
109             set
110             {
111                 _contentEncoding = value;
112                 NotifyOfPropertyChange(() => ContentEncoding);
113             }
114         }
115
116
117         private string _manifest;
118         public string Manifest
119         {
120             get { return _manifest; }
121             set
122             {
123                 _manifest = value;
124                 NotifyOfPropertyChange(() => Manifest);
125             }
126         }
127
128         private string _kind;
129         public string Kind
130         {
131             get { return _kind; }
132             set
133             {
134                 _kind = value;
135                 NotifyOfPropertyChange(() => Kind);
136             }
137         }
138
139         private string _size;
140         public string Size
141         {
142             get { return _size; }
143             set
144             {
145                 _size = value;
146                 NotifyOfPropertyChange(() => Size);
147             }
148         }
149
150         private string _shortSize;
151         public string ShortSize
152         {
153             get { return _shortSize; }
154             set
155             {
156                 _shortSize = value;
157                 NotifyOfPropertyChange(() => ShortSize);
158             }
159         }
160
161         private string _where;
162         public string Where
163         {
164             get { return _where; }
165             set
166             {
167                 _where = value;
168                 NotifyOfPropertyChange(() => Where);
169             }
170         }
171
172         private DateTime _modified;
173         public DateTime Modified
174         {
175             get { return _modified; }
176             set
177             {
178                 _modified = value;
179                 NotifyOfPropertyChange(() => Modified);
180             }
181         }
182
183         private string _modifiedBy;
184         public string ModifiedBy
185         {
186             get { return _modifiedBy; }
187             set
188             {
189                 _modifiedBy = value;
190                 NotifyOfPropertyChange(() => ModifiedBy);
191             }
192         }
193
194         private long _version;
195         public long Version
196         {
197             get { return _version; }
198             set
199             {
200                 _version = value;
201                 NotifyOfPropertyChange(() => Version);
202             }
203         }
204
205         private string _localFileName;
206         protected string LocalFileName
207         {
208             get { return _localFileName; }
209             set
210             {
211                 _localFileName = value;
212                 NotifyOfPropertyChange(() => LocalFileName);
213             }
214         }
215
216         private BitmapSource _fileIcon;
217         public BitmapSource FileIcon
218         {
219             get { return _fileIcon; }
220             set
221             {
222                 _fileIcon = value;
223                 NotifyOfPropertyChange(() => FileIcon);
224             }
225         }
226
227         private string _publicUrl;
228         public string PublicUrl
229         {
230             get { return _publicUrl; }
231             set
232             {
233                 _publicUrl = value;
234                 NotifyOfPropertyChange(() => PublicUrl);
235             }
236         }
237
238         private string _fileName;
239         public string FileName
240         {
241             get { return _fileName; }
242             set
243             {
244                 _fileName = value;
245                 NotifyOfPropertyChange(() => FileName);
246             }
247         }
248
249         private string _container;
250         public string Container
251         {
252             get { return _container; }
253             set
254             {
255                 _container = value;
256                 NotifyOfPropertyChange(() => Container);
257             }
258         }
259
260         public bool TagsChanged { get; private set; }
261         public bool PermissionsChanged { get; private set; }
262
263         private bool _isBusy = true;
264         public bool IsBusy
265         {
266             get { return _isBusy; }
267             set
268             {
269                 _isBusy = value;
270                 NotifyOfPropertyChange(() => IsBusy);
271             }
272         }
273
274
275         public FilePropertiesViewModel(ShellViewModel shell,Task<ObjectInfo> pithosFile,string localFileName)
276         {
277             if (shell==null)
278                 throw new ArgumentNullException("shell");
279             if (pithosFile==null)
280                 throw new ArgumentNullException("pithosFile");
281             if (String.IsNullOrWhiteSpace(localFileName))
282                 throw new ArgumentNullException("localFileName");
283             Contract.EndContractBlock();
284
285
286             _tags = new ObservableCollection<MetaValue>();
287             _tags.CollectionChanged += (sender, evt) => { TagsChanged = true; };
288             _permissions = new ObservableCollection<Permission>();
289             _permissions.CollectionChanged += (sender, evt) => { PermissionsChanged = true; };
290             
291             Shell = shell;
292             LocalFileName = localFileName;
293             pithosFile.ContinueWith(t =>
294             {
295                 if (t.IsFaulted)
296                 {
297                     IsBusy = false;
298                     Execute.OnUIThread(()=>ShowError(t.Exception));
299                     this.TryClose();
300
301                 }
302                 else
303                     Execute.OnUIThread(() => PithosFile = t.Result);
304             });                        
305         }
306
307         private void ShowError(AggregateException exception)
308         {
309             MessageView view = null;
310             if (exception.InnerException is RetryException)
311                 view = new MessageView(exception.InnerException as RetryException);
312             else if (exception.InnerException is WebException)
313                 view = new MessageView(exception.InnerException as WebException);
314             else
315                 view = new MessageView(exception.InnerException);
316             view.ShowDialog();
317         }
318
319
320         protected ShellViewModel Shell { get; set; }
321
322         private ObjectInfo _pithosFile;
323         public ObjectInfo PithosFile
324         {
325             get { return _pithosFile; }
326             set
327             {
328                 _pithosFile = value;
329                 
330                 Permissions.Clear();
331                 Tags.Clear();
332
333                 var perms=from permission in value.Permissions
334                             select new Permission(permission.Key, permission.Value);
335                 perms.Apply(perm=>Permissions.Add(perm));
336                 
337                 var tags=from tag in value.Tags
338                              select new MetaValue(tag.Key, tag.Value);
339                 tags.Apply(tag=>Tags.Add(tag));
340
341                 Title = String.Format("{0} Properties", value.Name);
342                 Kind=value.Content_Type;
343                 ShortSize = value.Bytes.ToByteSize();
344                 Size = String.Format("{0} ({1:N0} bytes)", ShortSize, value.Bytes);
345                 Where = Uri.UnescapeDataString(value.Name);
346                 FileName = Uri.UnescapeDataString(value.Name.Split('/').Last());
347                 Container = value.Container;
348                 Modified = value.Last_Modified;
349                 ModifiedBy = value.ModifiedBy;
350                 Version = value.Version??0;
351
352                 ContentDisposition = value.ContendDisposition;
353                 ContentEncoding = value.ContentEncoding;
354                 Manifest = value.Manifest;
355                 IsPublic = value.IsPublic;
356                 if (IsPublic)
357                     PublicUrl = String.Format("{0}/v1{1}", Shell.Accounts.First(account=>account.UserName==PithosFile.Account).SiteUri,value.PublicUrl);
358
359                 if (Directory.Exists(LocalFileName))
360                 {
361                     FileIcon= new BitmapImage(new Uri("../Images/Folder.ico",UriKind.Relative));
362                 }
363                 else if (File.Exists(LocalFileName))
364                 {
365                     using (var icon = Icon.ExtractAssociatedIcon(LocalFileName))
366                     {
367                         FileIcon = Imaging.CreateBitmapSourceFromHIcon(icon.Handle, Int32Rect.Empty,
368                                                                        BitmapSizeOptions.FromEmptyOptions());
369                     }
370                 }
371                 NotifyOfPropertyChange(()=>PithosFile);
372                 IsBusy = false;
373             }
374         }
375
376
377         private readonly ObservableCollection<MetaValue> _tags ;
378         public ObservableCollection<MetaValue> Tags
379         {
380             get { return _tags;}
381         }
382
383         private readonly ObservableCollection<Permission> _permissions ;
384         
385
386         public ObservableCollection<Permission> Permissions
387         {
388             get { return _permissions; }
389         }
390
391         public void Reload()
392         {
393             PithosFile=Shell.RefreshObjectInfo(PithosFile);
394         }
395
396         public override void CanClose(Action<bool> callback)
397         {
398             base.CanClose(callback);
399         }
400
401         public void SaveChanges()
402         {
403             DoSave();
404             TryClose();
405         }
406
407         public void RejectChanges()
408         {
409             TryClose();
410         }
411
412         public void ApplyChanges()
413         {
414             DoSave();
415         }
416
417         private void DoSave()
418         {
419             if (TagsChanged)
420             {
421                 PithosFile.Tags = this.Tags.ToDictionary(tag => tag.Name, tag => tag.Value);
422             }
423             
424             if (PermissionsChanged)
425             {
426                 PithosFile.Permissions = this.Permissions.ToDictionary(perm => perm.UserName, perm => perm.Value);
427             }
428
429             PithosFile.ContendDisposition = ContentDisposition;
430             PithosFile.ContentEncoding = ContentEncoding;
431             PithosFile.Manifest = Manifest;
432             PithosFile.IsPublic = IsPublic;
433
434             var monitor = Shell.Monitors[PithosFile.Account];
435             monitor.CloudClient.UpdateMetadata(PithosFile);
436
437
438             TagsChanged = false;
439             PermissionsChanged = false;
440         }
441
442
443     }
444 }