Fix incorrect check in Selective Sync that prevented folder changes to propagate...
[pithos-ms-client] / trunk / Pithos.Client.WPF / FileProperties / FilePropertiesViewModel.cs
index 8ea08fe..fb75da7 100644 (file)
-// -----------------------------------------------------------------------
-// <copyright file="FilePropertiesViewModel.cs" company="Microsoft">
-// TODO: Update copyright text.
-// </copyright>
-// -----------------------------------------------------------------------
+#region
+/* -----------------------------------------------------------------------
+ * <copyright file="FilePropertiesViewModel.cs" company="GRNet">
+ * 
+ * Copyright 2011-2012 GRNET S.A. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials
+ *      provided with the distribution.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and
+ * documentation are those of the authors and should not be
+ * interpreted as representing official policies, either expressed
+ * or implied, of GRNET S.A.
+ * </copyright>
+ * -----------------------------------------------------------------------
+ */
+#endregion
 
+using System.Collections.ObjectModel;
 using System.ComponentModel.Composition;
+using System.Diagnostics.Contracts;
+using System.Drawing;
+using System.IO;
+using System.Net;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Interop;
+using System.Windows.Media.Imaging;
 using Caliburn.Micro;
+using Pithos.Client.WPF.FileProperties;
+using Pithos.Core;
+using Pithos.Interfaces;
+using Pithos.Network;
 
 namespace Pithos.Client.WPF
 {
     using System;
-    using System.Collections.Generic;
     using System.Linq;
-    using System.Text;
 
     /// <summary>
     /// TODO: Update summary.
     /// </summary>
     [Export(typeof(FilePropertiesViewModel))]
-    public class FilePropertiesViewModel : Screen, IShell
+    public class FilePropertiesViewModel : Screen
     {
-        public FilePropertiesViewModel()
+        private string _title;
+        public string Title
         {
+            get { return _title; }
+            set
+            {
+                _title = value;
+                NotifyOfPropertyChange(()=>Title);
+            }
+        }
+
+
+        private bool _isPublic;
+        public bool IsPublic
+        {
+            get { return _isPublic; }
+            set
+            {
+                _isPublic = value;
+                NotifyOfPropertyChange(()=>IsPublic);
+            }
+        }
+
+        private string _contentDisposition;
+        public string ContentDisposition
+        {
+            get { return _contentDisposition; }
+            set
+            {
+                _contentDisposition = value;
+                NotifyOfPropertyChange(() => ContentDisposition);
+            }
+        }
+
+        private string _contentEncoding;
+        public string ContentEncoding
+        {
+            get { return _contentEncoding; }
+            set
+            {
+                _contentEncoding = value;
+                NotifyOfPropertyChange(() => ContentEncoding);
+            }
+        }
+
+
+        private string _manifest;
+        public string Manifest
+        {
+            get { return _manifest; }
+            set
+            {
+                _manifest = value;
+                NotifyOfPropertyChange(() => Manifest);
+            }
+        }
+
+        private string _kind;
+        public string Kind
+        {
+            get { return _kind; }
+            set
+            {
+                _kind = value;
+                NotifyOfPropertyChange(() => Kind);
+            }
+        }
+
+        private string _size;
+        public string Size
+        {
+            get { return _size; }
+            set
+            {
+                _size = value;
+                NotifyOfPropertyChange(() => Size);
+            }
+        }
+
+        private string _shortSize;
+        public string ShortSize
+        {
+            get { return _shortSize; }
+            set
+            {
+                _shortSize = value;
+                NotifyOfPropertyChange(() => ShortSize);
+            }
+        }
+
+        private string _where;
+        public string Where
+        {
+            get { return _where; }
+            set
+            {
+                _where = value;
+                NotifyOfPropertyChange(() => Where);
+            }
+        }
+
+        private DateTime _modified;
+        public DateTime Modified
+        {
+            get { return _modified; }
+            set
+            {
+                _modified = value;
+                NotifyOfPropertyChange(() => Modified);
+            }
+        }
+
+        private string _modifiedBy;
+        public string ModifiedBy
+        {
+            get { return _modifiedBy; }
+            set
+            {
+                _modifiedBy = value;
+                NotifyOfPropertyChange(() => ModifiedBy);
+            }
+        }
+
+        private long _version;
+        public long Version
+        {
+            get { return _version; }
+            set
+            {
+                _version = value;
+                NotifyOfPropertyChange(() => Version);
+            }
+        }
+
+        private string _localFileName;
+        protected string LocalFileName
+        {
+            get { return _localFileName; }
+            set
+            {
+                _localFileName = value;
+                NotifyOfPropertyChange(() => LocalFileName);
+            }
+        }
+
+        private BitmapSource _fileIcon;
+        public BitmapSource FileIcon
+        {
+            get { return _fileIcon; }
+            set
+            {
+                _fileIcon = value;
+                NotifyOfPropertyChange(() => FileIcon);
+            }
+        }
+
+        private string _publicUrl;
+        public string PublicUrl
+        {
+            get { return _publicUrl; }
+            set
+            {
+                _publicUrl = value;
+                NotifyOfPropertyChange(() => PublicUrl);
+            }
+        }
+
+        private string _fileName;
+        public string FileName
+        {
+            get { return _fileName; }
+            set
+            {
+                _fileName = value;
+                NotifyOfPropertyChange(() => FileName);
+            }
+        }
+
+        private string _container;
+        public string Container
+        {
+            get { return _container; }
+            set
+            {
+                _container = value;
+                NotifyOfPropertyChange(() => Container);
+            }
+        }
+
+        private string _synchStatus;
+        public string SynchStatus
+        {
+            get { return _synchStatus; }
+            set
+            {
+                _synchStatus = value;
+                NotifyOfPropertyChange(()=>SynchStatus);
+            }
+        }
+        
+        private Permission _currentPermission;
+        public Permission CurrentPermission
+        {
+            get { return _currentPermission; }
+            set
+            {                
+                _currentPermission = (value==null)?new Permission() : value.Clone();
+                _currentPermission.PropertyChanged += (o, e) => NotifyOfPropertyChange(() => CanAddPermission);
+
+                NotifyOfPropertyChange(()=>CurrentPermission);
+                NotifyOfPropertyChange(() => CanAddPermission);
+            }
+        }
+
+        public bool CanAddPermission
+        {
+            get { return !String.IsNullOrWhiteSpace(CurrentPermission.UserName); }
+        }
+
+        public void AddPermission()
+        {
+            var existingPermission = Permissions.FirstOrDefault(perm => perm.UserName == CurrentPermission.UserName);
+            if (existingPermission==null)
+                Permissions.Add(CurrentPermission.Clone());
+            else
+            {
+                existingPermission.Read = CurrentPermission.Read;
+            }
+        }
+
+        public bool CanAddTag
+        {
+            get { return !String.IsNullOrWhiteSpace(CurrentTag.Name); }
+        }
+
+        public void AddTag()
+        {
+            var existingTag = Tags.FirstOrDefault(tag => tag.Name == CurrentTag.Name);           
+            if (existingTag == null)
+                Tags.Add(CurrentTag.Clone());
+            else
+            {
+                existingTag.Value = CurrentTag.Value;
+            }
+        }
+
+
+        public bool TagsChanged { get; private set; }
+        public bool PermissionsChanged { get; private set; }
+
+        private bool _isBusy = true;
+        public bool IsBusy
+        {
+            get { return _isBusy; }
+            set
+            {
+                _isBusy = value;
+                NotifyOfPropertyChange(() => IsBusy);
+            }
+        }
+
+
+        public FilePropertiesViewModel(ShellViewModel shell,Task<ObjectInfo> pithosFile,string localFileName)
+        {
+            if (shell==null)
+                throw new ArgumentNullException("shell");
+            if (pithosFile==null)
+                throw new ArgumentNullException("pithosFile");
+            if (String.IsNullOrWhiteSpace(localFileName))
+                throw new ArgumentNullException("localFileName");
+            Contract.EndContractBlock();
+
+
+            _tags = new ObservableCollection<MetaValue>();
+            _tags.CollectionChanged += (sender, evt) => { TagsChanged = true; };
+            _permissions = new ObservableCollection<Permission>();
+            _permissions.CollectionChanged += (sender, evt) => { PermissionsChanged = true; };
+            
+
+            CurrentPermission=new Permission();
+            CurrentTag=new MetaValue();
+
+
+            Shell = shell;
+            LocalFileName = localFileName;
+
+            var name=Path.GetFileName(localFileName);
+            DisplayName = String.Format("{0} File Properties", name);
+
+            pithosFile.ContinueWith(t =>
+            {
+                if (t.IsFaulted)
+                {
+                    IsBusy = false;
+                    Execute.OnUIThread(()=>ShowError(t.Exception));
+                    this.TryClose();
+
+                }
+                else
+                    Execute.OnUIThread(() => PithosFile = t.Result);
+            });       
+                 
+        }
+
+        private void ShowError(AggregateException exception)
+        {
+            MessageView view;
+            if (exception.InnerException is RetryException)
+                view = new MessageView(exception.InnerException as RetryException);
+            else if (exception.InnerException is WebException)
+                view = new MessageView(exception.InnerException as WebException);
+            else
+                view = new MessageView(exception.InnerException);
+            view.ShowDialog();
+        }
+
+
+        protected ShellViewModel Shell { get; set; }
+
+        private ObjectInfo _pithosFile;
+        public ObjectInfo PithosFile
+        {
+            get { return _pithosFile; }
+            set
+            {
+                _pithosFile = value;
+                
+                Permissions.Clear();
+                Tags.Clear();
+
+                var perms=from permission in value.Permissions
+                            select new Permission(permission.Key, permission.Value);
+                perms.Apply(perm=>Permissions.Add(perm));
+                
+                var tags=from tag in value.Tags
+                             select new MetaValue(tag.Key, tag.Value);
+                tags.Apply(tag=>Tags.Add(tag));
+
+                Title = String.Format("{0} Properties", value.Name);
+                Kind=value.Content_Type;
+                ShortSize = value.Bytes.ToByteSize();
+                Size = String.Format("{0} ({1:N0} bytes)", ShortSize, value.Bytes);
+                Where = Uri.UnescapeDataString(value.Name);
+                FileName = Uri.UnescapeDataString(value.Name.Split('/').Last());
+                Container = value.Container;
+                Modified = value.Last_Modified;
+                ModifiedBy = value.ModifiedBy;
+                Version = value.Version??0;
+
+                ContentDisposition = value.ContendDisposition;
+                ContentEncoding = value.ContentEncoding;
+                Manifest = value.Manifest;
+                IsPublic = value.IsPublic;
+                if (IsPublic)
+                    PublicUrl = String.Format("{0}/v1{1}", Shell.Accounts.First(account=>account.UserName==PithosFile.Account).SiteUri,value.PublicUrl);
+
+                if (Directory.Exists(LocalFileName))
+                {
+                    FileIcon= new BitmapImage(new Uri("../Images/Folder.ico",UriKind.Relative));
+                }
+                else if (File.Exists(LocalFileName))
+                {
+                    using (var icon = Icon.ExtractAssociatedIcon(LocalFileName))
+                    {
+                        FileIcon = Imaging.CreateBitmapSourceFromHIcon(icon.Handle, Int32Rect.Empty,
+                                                                       BitmapSizeOptions.FromEmptyOptions());
+                    }
+                }
+
+                var status=Shell.GetFileStatus(LocalFileName);
+                SynchStatus = Enum.GetName(typeof (FileStatus), status);
+
+
+                NotifyOfPropertyChange(()=>PithosFile);
+                IsBusy = false;
+            }
+        }
+
+        private MetaValue _currentTag;
+        public MetaValue CurrentTag
+        {
+            get { return _currentTag; }
+            set
+            {
+                _currentTag = (value==null)?new MetaValue() : value.Clone();
+                _currentTag.PropertyChanged += (o, e) => NotifyOfPropertyChange(() => CanAddTag);
+
+                NotifyOfPropertyChange(()=>CurrentTag);
+                NotifyOfPropertyChange(() => CanAddTag);
+            }
+        }
+
+        private readonly ObservableCollection<MetaValue> _tags ;
+        public ObservableCollection<MetaValue> Tags
+        {
+            get { return _tags;}
+        }
+
+        private readonly ObservableCollection<Permission> _permissions ;
+        
+
+        public ObservableCollection<Permission> Permissions
+        {
+            get { return _permissions; }
+        }
+
+        public void Reload()
+        {
+            PithosFile=Shell.RefreshObjectInfo(PithosFile);
+        }
+
+        public override void CanClose(Action<bool> callback)
+        {
+            base.CanClose(callback);
+        }
+
+        public void SaveChanges()
+        {
+            DoSave();
+            TryClose();
+        }
+
+        public void RejectChanges()
+        {
+            TryClose();
+        }
+
+        public void ApplyChanges()
+        {
+            DoSave();
+        }
+
+        private void DoSave()
+        {
+            if (TagsChanged)
+            {
+                PithosFile.Tags = this.Tags.ToDictionary(tag => tag.Name, tag => tag.Value);
+            }
+            
+            if (PermissionsChanged)
+            {
+                PithosFile.Permissions = this.Permissions.ToDictionary(perm => perm.UserName, perm => 
+                    (perm.Value.Trim()));
+            }
+
+            PithosFile.ContendDisposition = ContentDisposition;
+            PithosFile.ContentEncoding = ContentEncoding;
+            PithosFile.Manifest = Manifest;
+            PithosFile.IsPublic = IsPublic;
             
+            var monitor = Shell.Monitors[PithosFile.AccountKey];
+            monitor.CloudClient.UpdateMetadata(PithosFile);
+
+
+            TagsChanged = false;
+            PermissionsChanged = false;
         }
+
+
     }
 }