-#region
-/* -----------------------------------------------------------------------
- * <copyright file="SelectiveSynchViewModel.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;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Linq;
-using System.Threading.Tasks;
-using Caliburn.Micro;
-using Pithos.Client.WPF.Properties;
-using Pithos.Client.WPF.Utils;
-using Pithos.Core;
-using Pithos.Interfaces;
-
-namespace Pithos.Client.WPF.SelectiveSynch
-{
- class SelectiveSynchViewModel:Screen
- {
- private const string DirectoryType = "application/directory";
- private readonly IEventAggregator _events ;
-
-
- public AccountSettings Account { get; set; }
-
- private readonly ObservableCollection<DirectoryRecord> _rootNodes=new ObservableCollection<DirectoryRecord>();
- public ObservableCollection<DirectoryRecord> RootNodes
- {
- get { return _rootNodes; }
- }
-
- private ObservableCollection<ObjectInfo> _checks;
- private readonly PithosMonitor _monitor;
- private bool _isBusy=true;
-
- public ObservableCollection<ObjectInfo> Checks
- {
- get { return _checks; }
- }
-
- public void GetChecks()
- {
- var root = RootNodes[0];
- _checks = new ObservableCollection<ObjectInfo>(
- from DirectoryRecord record in root
- where record.IsChecked==true
- select record.ObjectInfo);
- NotifyOfPropertyChange(() => Checks);
- }
-
- public SelectiveSynchViewModel(PithosMonitor monitor, IEventAggregator events, AccountSettings account)
- {
- Account = account;
- AccountName = account.AccountName;
- DisplayName = String.Format("Selective folder synchronization for {0}",account.AccountName);
- _monitor = monitor;
- _events = events;
- TaskEx.Run(LoadRootNode);
- }
-
- private void LoadRootNode()
- {
- var client = _monitor.CloudClient;
-
- var dirs = from container in client.ListContainers(_monitor.UserName)
- select new DirectoryRecord
- {
- DisplayName = container.Name,
- Uri=new Uri(client.StorageUrl,String.Format(@"{0}/{1}",Account.AccountName, container.Name)),
- Directories = (from dir in client.ListObjects(_monitor.UserName, container.Name)
- where dir.Content_Type == DirectoryType
- select dir).ToTree()
- };
- var ownFolders = dirs.ToList();
-
- var accountNodes=from account in client.ListSharingAccounts()
- select new DirectoryRecord
- {
- DisplayName=account.name,
- Uri=new Uri(client.StorageUrl,"../"+ account.name),
- Directories=(from container in client.ListContainers(account.name)
- select new DirectoryRecord
- {
- DisplayName=container.Name,
- Uri = new Uri(client.StorageUrl, "../" + account.name + "/" + container.Name),
- Directories=(from folder in client.ListObjects(account.name,container.Name)
- where folder.Content_Type==DirectoryType
- select folder).ToTree()
- }).ToList()
- };
-
- var othersNode = new DirectoryRecord
- {
- DisplayName = "Others",
- Directories=accountNodes.ToList()
- };
-
-
- var rootItem = new DirectoryRecord
- {
- DisplayName = AccountName ,
- Directories = ownFolders.ToList()
- };
-
- Execute.OnUIThread(() =>
- {
- RootNodes.Add(rootItem);
- RootNodes.Add(othersNode);
- });
-
- SetInitialSelections(Account);
-
- IsBusy = false;
- }
-
- public bool IsBusy
- {
- get {
- return _isBusy;
- }
- set {
- _isBusy = value;
- NotifyOfPropertyChange(()=>IsBusy);
- }
- }
-
- private void SetInitialSelections(AccountSettings account)
- {
- var selections = account.SelectiveFolders;
-
- if (selections.Count == 0)
- return;
- //Initially, all nodes are checked
- //We need to *uncheck* the nodes that are not selected
-
- var selects = from DirectoryRecord rootRecord in RootNodes
- from DirectoryRecord record in rootRecord
- where record.Uri !=null && !selections.Contains(record.Uri.ToString())
- select record;
-
- selects.Apply(record=>record.IsChecked=false);
- }
-
- protected string AccountName { get; set; }
-
- public void SaveChanges()
- {
- var uris = (from DirectoryRecord root in RootNodes
- from DirectoryRecord record in root
- where record.IsChecked == true && record.Uri != null
- select record.Uri).ToArray();
-
- SaveSettings(uris);
-
- //RootNodes is an ObservableCollection, it can't be enumerated iterativelly
-
- var added = (from DirectoryRecord root in RootNodes
- from DirectoryRecord record in root
- where record.Added && record.Uri != null
- select record.Uri).ToArray();
- var removed = (from DirectoryRecord root in RootNodes
- from DirectoryRecord record in root
- where record.Removed && record.Uri != null
- select record.Uri).ToArray();
- //TODO: Include Uris for the containers as well
- _events.Publish(new SelectiveSynchChanges{Account=Account,Uris=uris,Added=added,Removed=removed});
-
-
-
-
- TryClose(true);
- }
-
-
- private void SaveSettings(IEnumerable<Uri> uris)
- {
- var selections = uris.Select(uri => uri.ToString()).ToArray();
-
- Account.SelectiveFolders.Clear();
- Account.SelectiveFolders.AddRange(selections);
- Settings.Default.Save();
- }
-
- public void RejectChanges()
- {
- TryClose(false);
- }
- }
-}
+#region\r
+/* -----------------------------------------------------------------------\r
+ * <copyright file="SelectiveSynchViewModel.cs" company="GRNet">\r
+ * \r
+ * Copyright 2011-2012 GRNET S.A. All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS\r
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR\r
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF\r
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED\r
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * The views and conclusions contained in the software and\r
+ * documentation are those of the authors and should not be\r
+ * interpreted as representing official policies, either expressed\r
+ * or implied, of GRNET S.A.\r
+ * </copyright>\r
+ * -----------------------------------------------------------------------\r
+ */\r
+#endregion\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Collections.ObjectModel;\r
+using System.Linq;\r
+using System.Threading.Tasks;\r
+using Caliburn.Micro;\r
+using Pithos.Client.WPF.Properties;\r
+using Pithos.Client.WPF.Utils;\r
+using Pithos.Core;\r
+using Pithos.Interfaces;\r
+using Pithos.Network;\r
+\r
+namespace Pithos.Client.WPF.SelectiveSynch\r
+{\r
+ class SelectiveSynchViewModel:Screen\r
+ { \r
+ private readonly IEventAggregator _events ;\r
+\r
+\r
+ public AccountSettings Account { get; set; }\r
+\r
+ private readonly ObservableCollection<DirectoryRecord> _rootNodes=new ObservableCollection<DirectoryRecord>();\r
+ public ObservableCollection<DirectoryRecord> RootNodes\r
+ {\r
+ get { return _rootNodes; }\r
+ }\r
+\r
+ private ObservableCollection<ObjectInfo> _checks;\r
+ //private readonly PithosMonitor _monitor;\r
+ private bool _isBusy=true;\r
+ private string _apiKey;\r
+\r
+ public ObservableCollection<ObjectInfo> Checks\r
+ {\r
+ get { return _checks; }\r
+ }\r
+\r
+ public void GetChecks()\r
+ {\r
+ var root = RootNodes[0]; \r
+ _checks = new ObservableCollection<ObjectInfo>(\r
+ from DirectoryRecord record in root\r
+ where record.IsChecked==true\r
+ select record.ObjectInfo);\r
+ NotifyOfPropertyChange(() => Checks);\r
+ }\r
+\r
+ public SelectiveSynchViewModel(/*PithosMonitor monitor,*/ IEventAggregator events, AccountSettings account, string apiKey)\r
+ {\r
+ Account = account;\r
+ AccountName = account.AccountName;\r
+ DisplayName = String.Format("Selective folder synchronization for {0}",account.AccountName);\r
+ //_monitor = monitor;\r
+ _events = events;\r
+ _apiKey = apiKey;\r
+ TaskEx.Run(LoadRootNode);\r
+ }\r
+\r
+ private void LoadRootNode()\r
+ { \r
+ //TODO: Check this\r
+ var client = new CloudFilesClient(AccountName,_apiKey){AuthenticationUrl=Account.ServerUrl,UsePithos=true};\r
+ client.Authenticate();\r
+ \r
+ //NEED to get the local folders here as well,\r
+ // and combine them with the cloud folders\r
+\r
+\r
+ var dirs = from container in client.ListContainers(AccountName) \r
+ where container.Name != "trash"\r
+ select new DirectoryRecord\r
+ {\r
+ DisplayName = container.Name,\r
+ Uri=new Uri(client.StorageUrl,String.Format(@"{0}/{1}",Account.AccountName, container.Name)),\r
+ Directories = (from dir in client.ListObjects(AccountName, container.Name) \r
+ select dir).ToTree()\r
+ };\r
+ var ownFolders = dirs.ToList();\r
+\r
+\r
+\r
+ var accountNodes=from account in client.ListSharingAccounts()\r
+ select new DirectoryRecord\r
+ {\r
+ DisplayName=account.name,\r
+ Uri=new Uri(client.StorageUrl,"../"+ account.name),\r
+ Directories=(from container in client.ListContainers(account.name)\r
+ select new DirectoryRecord\r
+ {\r
+ DisplayName=container.Name,\r
+ Uri = new Uri(client.StorageUrl, "../" + account.name + "/" + container.Name),\r
+ Directories=(from folder in client.ListObjects(account.name,container.Name) \r
+ select folder).ToTree()\r
+ }).ToList()\r
+ }; \r
+\r
+ var othersNode = new DirectoryRecord\r
+ {\r
+ DisplayName = "Shared to me",\r
+ Directories=accountNodes.ToList()\r
+ };\r
+\r
+ \r
+ var rootItem = new DirectoryRecord\r
+ {\r
+ DisplayName = AccountName ,\r
+ Directories = ownFolders.ToList()\r
+ };\r
+\r
+ var localFolders = SelectiveExtensions.LocalFolders(AccountName, Account.RootPath,client.StorageUrl.AbsoluteUri);\r
+\r
+ foreach (var folder in localFolders)\r
+ {\r
+ //If this folder is not included in the server folders\r
+ if (!rootItem.Directories.Any(dir => dir.Uri == folder.Uri))\r
+ {\r
+ //we need to add it\r
+ //Find the best parent\r
+\r
+ //One way to do this, is to break the the Uri to its parts\r
+ //and try to find a parent using progressively fewer parts\r
+ var parts = folder.Uri.AbsoluteUri.Split('/');\r
+ for (var i = parts.Length - 1; i > 0; i--)\r
+ {\r
+ var parentUrl = String.Join("/",parts.Splice(0, i));\r
+ var parentUri = new Uri(parentUrl);\r
+\r
+ var parent = rootItem.Directories.FirstOrDefault(dir => dir.Uri == parentUri);\r
+ if (parent != null)\r
+ {\r
+ parent.Directories.Add(folder);\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ \r
+ //For each local folder that doesn't exist in the server nodes \r
+ //find the best matching parent and add the folder below it.\r
+\r
+ Execute.OnUIThread(() =>\r
+ {\r
+ RootNodes.Add(rootItem);\r
+ RootNodes.Add(othersNode);\r
+ });\r
+\r
+ SetInitialSelections(Account);\r
+ \r
+ IsBusy = false;\r
+ }\r
+\r
+ public bool IsBusy\r
+ {\r
+ get {\r
+ return _isBusy;\r
+ }\r
+ set {\r
+ _isBusy = value;\r
+ NotifyOfPropertyChange(()=>IsBusy);\r
+ }\r
+ }\r
+\r
+ private void SetInitialSelections(AccountSettings account)\r
+ {\r
+ var selections = account.SelectiveFolders;\r
+\r
+\r
+ \r
+ //Initially, all nodes are checked\r
+ //We need to *uncheck* the nodes that are not selected\r
+\r
+ var allNodes = (from DirectoryRecord rootRecord in RootNodes\r
+ from DirectoryRecord record in rootRecord\r
+ select record).ToList();\r
+ //WARNING: Using IsChecked marks the item as REMOVED\r
+ allNodes.Apply(record => record.IsExplicitlyChecked = false);\r
+\r
+ if (selections.Count == 0)\r
+ {\r
+ // allNodes.Apply(record => record.IsChecked = false);\r
+ return;\r
+ } \r
+ \r
+ var selects = (from DirectoryRecord rootRecord in RootNodes\r
+ from DirectoryRecord record in rootRecord\r
+ where record.Uri !=null && selections.Contains(record.Uri.ToString())\r
+ select record).ToList();\r
+ //var shouldBeChecked = allNodes.Except(selects).ToList();\r
+ \r
+ //WARNING: Using IsChecked marks the item as ADDED\r
+ selects.Apply(record=>record.IsExplicitlyChecked=true);\r
+\r
+ //shouldBeChecked.Apply(record => record.IsChecked = true);\r
+ \r
+ \r
+\r
+ }\r
+\r
+ protected string AccountName { get; set; }\r
+\r
+ public void SaveChanges()\r
+ {\r
+ var uris = (from DirectoryRecord root in RootNodes\r
+ from DirectoryRecord record in root\r
+ where record.IsChecked == true && record.Uri != null\r
+ select record.Uri).ToArray(); \r
+\r
+ SaveSettings(uris);\r
+ \r
+ //RootNodes is an ObservableCollection, it can't be enumerated iterativelly\r
+\r
+ var added = (from DirectoryRecord root in RootNodes\r
+ from DirectoryRecord record in root\r
+ where record.Added && record.Uri != null\r
+ select record.Uri).ToArray();\r
+ var removed = (from DirectoryRecord root in RootNodes\r
+ from DirectoryRecord record in root\r
+ where record.Removed && record.Uri != null\r
+ select record.Uri).ToArray();\r
+ //TODO: Include Uris for the containers as well\r
+ _events.Publish(new SelectiveSynchChanges{Account=Account,Uris=uris,Added=added,Removed=removed});\r
+ \r
+\r
+ \r
+\r
+ TryClose(true);\r
+ }\r
+\r
+ \r
+ private void SaveSettings(IEnumerable<Uri> uris)\r
+ {\r
+ var selections = uris.Select(uri => uri.ToString()).ToArray();\r
+\r
+ Account.SelectiveFolders.Clear();\r
+ Account.SelectiveFolders.AddRange(selections);\r
+ Settings.Default.Save(); \r
+ } \r
+\r
+ public void RejectChanges()\r
+ {\r
+ TryClose(false);\r
+ }\r
+ }\r
+}\r