Statistics
| Branch: | Revision:

root / trunk / Pithos.Client.WPF / FileProperties / ContainerPropertiesViewModel.cs @ 2115e2a5

History | View | Annotate | Download (14.6 kB)

1
#region
2
/* -----------------------------------------------------------------------
3
 * <copyright file="ContainerPropertiesViewModel.cs" company="GRNet">
4
 * 
5
 * Copyright 2011-2012 GRNET S.A. All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or
8
 * without modification, are permitted provided that the following
9
 * conditions are met:
10
 *
11
 *   1. Redistributions of source code must retain the above
12
 *      copyright notice, this list of conditions and the following
13
 *      disclaimer.
14
 *
15
 *   2. Redistributions in binary form must reproduce the above
16
 *      copyright notice, this list of conditions and the following
17
 *      disclaimer in the documentation and/or other materials
18
 *      provided with the distribution.
19
 *
20
 *
21
 * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
22
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
25
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
 * POSSIBILITY OF SUCH DAMAGE.
33
 *
34
 * The views and conclusions contained in the software and
35
 * documentation are those of the authors and should not be
36
 * interpreted as representing official policies, either expressed
37
 * or implied, of GRNET S.A.
38
 * </copyright>
39
 * -----------------------------------------------------------------------
40
 */
41
#endregion
42
using System;
43
using System.Collections.Concurrent;
44
using System.Collections.Generic;
45
using System.Collections.ObjectModel;
46
using System.ComponentModel.Composition;
47
using System.Diagnostics.Contracts;
48
using System.IO;
49
using System.Linq;
50
using System.Net;
51
using System.Text;
52
using System.Threading.Tasks;
53
using System.Windows;
54
using Caliburn.Micro;
55
using Pithos.Network;
56

    
57
namespace Pithos.Client.WPF.FileProperties
58
{
59
    [Export(typeof(ContainerPropertiesViewModel))]
60
    public class ContainerPropertiesViewModel:Screen
61
    {
62
        private string _containerName;
63

    
64
        /// <summary>
65
        /// Name of the displayed container
66
        /// </summary>
67
        public string ContainerName
68
        {
69
            get { return _containerName; }
70
            set
71
            {
72
                _containerName = value;
73
                NotifyOfPropertyChange(()=>ContainerName);
74
            }
75
        }
76

    
77
        private string _title;
78
        /// <summary>
79
        /// Window title
80
        /// </summary>
81
        public string Title
82
        {
83
            get { return _title; }
84
            set
85
            {
86
                _title = value;
87
                NotifyOfPropertyChange(() => Title);
88
            }
89
        }
90

    
91
        private long _count;
92

    
93
        /// <summary>
94
        /// Count of files in the container
95
        /// </summary>
96
        public long Count
97
        {
98
            get { return _count; }
99
            set
100
            {
101
                _count = value;
102
                NotifyOfPropertyChange(() => Count);
103
            }
104
        }
105

    
106
        private DateTimeOffset? _modified;
107

    
108
        /// <summary>
109
        /// Date of last modification
110
        /// </summary>
111
        public DateTimeOffset? Modified
112
        {
113
            get { return _modified; }
114
            set
115
            {
116
                _modified = value;
117
                NotifyOfPropertyChange(() => Modified);
118
            }
119
        }
120

    
121
        private string _size;
122

    
123
        /// <summary>
124
        /// Total size of the container in bytes
125
        /// </summary>
126
        public string Size
127
        {
128
            get { return _size; }
129
            set
130
            {
131
                _size = value;
132
                NotifyOfPropertyChange(() => Size);
133
            }
134
        }
135

    
136
        private string _shortSize;
137

    
138
        /// <summary>
139
        /// Total size of the container formatted in KB,MB etc
140
        /// </summary>
141
        public string ShortSize
142
        {
143
            get { return _shortSize; }
144
            set
145
            {
146
                _shortSize = value;
147
                NotifyOfPropertyChange(() => ShortSize);
148
            }
149
        }
150

    
151
        private int _blockSize;
152

    
153
        /// <summary>
154
        /// Block size used by the container
155
        /// </summary>
156
        public int BlockSize
157
        {
158
            get { return _blockSize; }
159
            set
160
            {
161
                _blockSize = value;
162
                NotifyOfPropertyChange(() => BlockSize);
163
            }
164
        }
165

    
166
        private string _blockHash;
167

    
168
        /// <summary>
169
        /// Hash algorithm used to calculate block hashes
170
        /// </summary>
171
        public string BlockHash
172
        {
173
            get { return _blockHash; }
174
            set
175
            {
176
                _blockHash = value;
177
                NotifyOfPropertyChange(() => BlockHash);
178
            }
179
        }
180

    
181
        private ShellViewModel _shell;
182

    
183
        /// <summary>
184
        /// Reference to the parent Shell
185
        /// </summary>
186
        protected ShellViewModel Shell
187
        {
188
            get { return _shell; }
189
            set
190
            {
191
                _shell = value;
192
                NotifyOfPropertyChange(() => Shell);
193
            }
194
        }
195

    
196
        private ContainerInfo _container;
197
        /// <summary>
198
        /// The displayed ContainerInfo
199
        /// </summary>
200
        protected ContainerInfo Container
201
        {
202
            get { return _container; }
203
            set
204
            {
205
                _container = value;
206

    
207
                
208

    
209
                LoadFromDictionary(Tags, value.Tags);
210
                TagsChanged = false;
211
                //LoadFromDictionary(Policies, value.Policies);
212

    
213
                if (value.Policies.ContainsKey("Versioning"))
214
                {
215
                    Versioning version;
216
                    if (Enum.TryParse(value.Policies["Versioning"], out version))
217
                    {
218
                        SelectedVersion = version;
219
                    }
220
                }
221

    
222
                if (value.Policies.ContainsKey("Quota"))
223
                {
224
                    int quota;
225
                    if (int.TryParse(value.Policies["Quota"], out quota))
226
                    {
227
                        Quota=quota;
228
                    }
229
                }
230

    
231
                Title = String.Format("{0} Properties", _container.Name);
232
                Count = value.Count;
233
                ShortSize = value.Bytes.ToByteSize();
234
                Size = String.Format("{0} ({1:N0} bytes)", ShortSize, value.Bytes);
235
                Modified = value.Last_Modified;
236
                BlockSize = value.BlockSize;
237
                BlockHash = value.BlockHash;                
238
                ContainerName = Uri.UnescapeDataString(value.Name.ToString().Split('/').Last());                                                
239

    
240
                NotifyOfPropertyChange(() => Container);
241
                IsBusy = false;
242
            }
243
        }
244

    
245
        private int _quota;
246
        public int Quota
247
        {
248
            get { return _quota; }
249
            set
250
            {
251
                if (value < 0)
252
                    throw new ArgumentOutOfRangeException("Quota");
253

    
254
                _quota = value;                
255
                NotifyOfPropertyChange(() => Quota);
256
            }
257
        }
258

    
259

    
260

    
261
        private Versioning[] _versions={Versioning.manual,Versioning.auto,Versioning.none};
262
        public Versioning[] Versions
263
        {
264
            get { return _versions; }
265
        }
266

    
267

    
268
        private Versioning _selectedVersion;
269
        public Versioning SelectedVersion
270
        {
271
            get { return _selectedVersion; }
272
            set { 
273
                _selectedVersion = value;
274
                NotifyOfPropertyChange(()=>SelectedVersion);
275
            }
276
        }
277

    
278
        private void LoadFromDictionary(ICollection<MetaValue> collection,Dictionary<string,string> source  )
279
        {
280
            collection.Clear();
281
            var items = from item in source
282
                        select new MetaValue(item.Key, item.Value);
283
            
284
            items.Apply(collection.Add);
285
        }
286

    
287
        private MetaValue _currentTag;
288
        public MetaValue CurrentTag
289
        {
290
            get { return _currentTag; }
291
            set
292
            {
293
                _currentTag = (value == null) ? new MetaValue() : value.Clone();
294
                _currentTag.PropertyChanged += (o, e) => NotifyOfPropertyChange(() => CanAddTag);
295

    
296
                NotifyOfPropertyChange(() => CurrentTag);
297
                NotifyOfPropertyChange(() => CanAddTag);
298
            }
299
        }
300

    
301
        private readonly ObservableCollection<MetaValue> _tags;
302
        public ObservableCollection<MetaValue> Tags
303
        {
304
            get { return _tags; }
305
        }
306

    
307
        public bool CanAddTag
308
        {
309
            get { return !String.IsNullOrWhiteSpace(CurrentTag.Name); }
310
        }
311

    
312
        public void AddTag()
313
        {
314
            var existingTag = Tags.FirstOrDefault(tag => tag.Name == CurrentTag.Name);
315
            if (existingTag == null)
316
                Tags.Add(CurrentTag.Clone());
317
            else
318
            {
319
                existingTag.Value = CurrentTag.Value;
320
            }
321

    
322
            TagsChanged = true;
323
        }
324

    
325
       /* private readonly ObservableCollection<MetaValue> _policies;
326
        public ObservableCollection<MetaValue> Policies
327
        {
328
            get { return _policies; }
329
        }*/
330

    
331
        private bool _tagsChanged;
332
        public bool TagsChanged
333
        {
334
            get { return _tagsChanged; }
335
            private set
336
            {
337
                _tagsChanged = value;
338
                NotifyOfPropertyChange(()=>TagsChanged);
339
                NotifyOfPropertyChange(() => CanApplyChanges);
340
            }
341
        }
342

    
343
        //public bool PoliciesChanged { get; private set; }
344

    
345
        private bool _isBusy=true;
346
        public bool IsBusy
347
        {
348
            get { return _isBusy; }
349
            set
350
            {
351
                _isBusy = value;
352
                NotifyOfPropertyChange(()=>IsBusy);
353
            }
354
        }
355

    
356
        private string _busyMessage = "Loading Container Info ...";
357
        public string BusyMessage
358
        {
359
            get { return _busyMessage; }
360
            set
361
            {
362
                _busyMessage = value;
363
                NotifyOfPropertyChange(() => BusyMessage);
364
            }
365
        }
366

    
367

    
368
        public ContainerPropertiesViewModel(ShellViewModel shell, Task<ContainerInfo> container, string localFolderName)
369
        {
370
            if (shell==null)
371
                throw new ArgumentNullException("shell");
372
            if (container==null)
373
                throw new ArgumentNullException("container");
374
            if (String.IsNullOrWhiteSpace(localFolderName))
375
                throw new ArgumentNullException("localFolderName");
376
            Contract.EndContractBlock();
377
            
378
            _tags = new ObservableCollection<MetaValue>();
379
            _tags.CollectionChanged += (sender, evt) => { TagsChanged = true; };
380

    
381
            CurrentTag=new MetaValue();
382
            /*_policies = new ObservableCollection<MetaValue>();
383
            _policies.CollectionChanged += (sender, evt) => { PoliciesChanged = true; };
384
*/
385

    
386
            var name = Path.GetFileName(localFolderName);
387
            DisplayName = String.Format("{0} Container Properties", name);
388

    
389
            Shell = shell;
390
            ContainerName = localFolderName;
391
            container.ContinueWith(t =>{                
392
                if (t.IsFaulted)
393
                {
394
                    IsBusy = false;
395
                    Execute.OnUIThread(() => ShowError(t.Exception));
396
                    this.TryClose();
397

    
398
                }
399
                else
400
                    Execute.OnUIThread(()=>Container = t.Result);                                           
401
            });
402
        }
403

    
404
        private void ShowError(AggregateException exception)
405
        {
406
            MessageView view=null;
407
            if (exception.InnerException is RetryException)
408
                view=new MessageView(exception.InnerException as RetryException);
409
            else if (exception.InnerException is WebException)
410
                view = new MessageView(exception.InnerException as WebException);
411
            else
412
                view = new MessageView(exception.InnerException);
413
            view.ShowDialog();
414
        }
415

    
416
        public async Task Reload()
417
        {
418
            Container =await Shell.RefreshContainerInfo(Container);
419
        }
420

    
421
        public override void CanClose(Action<bool> callback)
422
        {
423
            base.CanClose(callback);
424
        }
425

    
426
        public async Task SaveChanges()
427
        {
428
            await DoSave();
429
            TryClose();
430
        }
431

    
432
        public void RejectChanges()
433
        {
434
            TryClose();
435
        }
436

    
437
        public async Task ApplyChanges()
438
        {
439
            await DoSave();
440
        }
441

    
442
        public bool CanApplyChanges
443
        {
444
            get { return TagsChanged; }
445
        }
446

    
447
        private async Task DoSave()
448
        {
449
            try
450
            {
451
                IsBusy = true;
452
                BusyMessage = "Updating Container Info ...";
453
                await TaskEx.Run(() =>{
454
                    if (TagsChanged)
455
                    {
456
                        Container.Tags = this.Tags.ToDictionary(tag => tag.Name, tag => tag.Value);
457
                        var monitor = Shell.Monitors[Container.AccountKey];
458
                        monitor.CloudClient.UpdateMetadata(Container);
459
                    }
460
                    /*
461
                        Container.Policies["Quota"] = Quota.ToString();
462
                        Container.Policies["Versioning"] = Enum.GetName(typeof (Versioning), SelectedVersion);
463

    
464
                        if (PoliciesChanged)
465
                        {
466
                            Container.Policies = this.Policies.ToDictionary(policy=> policy.Name, tag => tag.Value);
467
                        }
468
                    */
469
                }).ConfigureAwait(false);
470
            }
471
            finally
472
            {
473
                IsBusy = false;
474
                TagsChanged = false;                
475
            }
476
        }
477

    
478
    }
479

    
480
    
481
}