-#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.Collections.Specialized;
-using System.IO;
-using System.Linq;
-using System.Text;
-using Caliburn.Micro;
-using Pithos.Client.WPF.Properties;
-using Pithos.Interfaces;
-using Pithos.Network;
-
-namespace Pithos.Client.WPF.SelectiveSynch
-{
- class SelectiveSynchViewModel:Screen
- {
- private IEventAggregator _events ;
-
- private string _rootPath;
- private string _cachePath;
- public string RootPath
- {
- get { return _rootPath; }
- set
- {
- _rootPath = value;
- _cachePath = Path.Combine(_rootPath, FolderConstants.CacheFolder);
- _pithosDirectory = new ObservableCollection<DirectoryRecord>{
- new DirectoryRecord(_cachePath) {Info = new DirectoryInfo(value)}};
- NotifyOfPropertyChange(() => RootPath);
- NotifyOfPropertyChange(()=>PithosDirectory);
- }
- }
-
- private string _title;
- public string Title
- {
- get { return _title; }
- set
- {
- _title = value;
- NotifyOfPropertyChange(() => Title);
- }
- }
-
- public AccountSettings Account { get; set; }
-
- private ObservableCollection<DirectoryRecord> _pithosDirectory;
- public ObservableCollection<DirectoryRecord> PithosDirectory
- {
- get { return _pithosDirectory; }
- }
-
- private ObservableCollection<DirectoryInfo> _checks;
- public ObservableCollection<DirectoryInfo> Checks
- {
- get { return _checks; }
- }
-
- public void GetChecks()
- {
- var root = PithosDirectory[0];
- _checks = new ObservableCollection<DirectoryInfo>(
- from record in root
- where record.IsChecked==true
- select record.Info);
- NotifyOfPropertyChange(() => Checks);
- }
-
- public SelectiveSynchViewModel(IEnumerable<string> folders, IEventAggregator events, AccountSettings account)
- {
- Account = account;
- AccountName = account.AccountName;
- Title = account.AccountName;
- RootPath = account.RootPath;
-
- SetInitialSelections(account);
- }
-
- private void SetInitialSelections(AccountSettings account)
- {
- var selections = account.SelectiveFolders;
- if (selections.Count == 0)
- return;
- var root = PithosDirectory[0];
- var selects= from record in root
- where selections.Contains(record.Info.FullName)
- select record;
- selects.Apply(record=>record.IsChecked=true);
- }
-
- protected string AccountName { get; set; }
-
- public void SaveChanges()
- {
- var selections = GetSelectedFolderNames();
-
- SaveSettings(selections);
- var root = PithosDirectory[0];
-
- var added= (from record in root
- where record.Added
- select record.Info.FullName.ToLower()).ToArray();
- var removed= (from record in root
- where record.Removed
- select record.Info.FullName.ToLower()).ToArray();
-
- _events.Publish(new SelectiveSynchChanges{Account=Account,Added=added,Removed=removed});
-
-
-
-
- TryClose(true);
- }
-
-
- private void SaveSettings(string[] selections)
- {
- Account.SelectiveFolders.Clear();
- Account.SelectiveFolders.AddRange(selections);
- Settings.Default.Save();
- }
-
- private string[] GetSelectedFolderNames()
- {
- var root = PithosDirectory[0];
- var selections = from record in root
- where record.IsChecked == true
- select record.Info.FullName;
- return selections.ToArray();
- }
-
- 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 readonly 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,bool forSelectiveActivation)\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
+ //IsEnabled = account.SelectiveSyncEnabled; \r
+ TaskEx.Run(()=>LoadRootNode(forSelectiveActivation));\r
+ }\r
+\r
+ private async void LoadRootNode(bool forSelectiveActivation)\r
+ { \r
+ //TODO: Check this\r
+ var client = new CloudFilesClient(AccountName,_apiKey){AuthenticationUrl=Account.ServerUrl,UsePithos=true};\r
+ await client.Authenticate().ConfigureAwait(false);\r
+ \r
+ //NEED to get the local folders here as well,\r
+ // and combine them with the cloud folders\r
+\r
+\r
+ var containerInfos = await client.ListContainers(AccountName).ConfigureAwait(false);\r
+ var dirs = from container in containerInfos \r
+ where container.Name.ToUnescapedString() != "trash"\r
+ select new DirectoryRecord\r
+ {\r
+ DisplayName = container.Name.ToUnescapedString(),\r
+ Uri=client.StorageUrl.Combine(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=client.StorageUrl.Combine("../"+ account.name),\r
+ Directories=(from container in client.ListContainers(account.name).Result\r
+ select new DirectoryRecord\r
+ {\r
+ DisplayName=container.Name.ToUnescapedString(),\r
+ Uri = client.StorageUrl.Combine("../" + 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 with me",\r
+ Directories=accountNodes.ToList()\r
+ };\r
+\r
+ \r
+ var rootItem = new DirectoryRecord\r
+ {\r
+ DisplayName = AccountName ,\r
+ Directories = ownFolders.ToList()\r
+ };\r
+\r
+ // Add Local Folders\r
+ //var localFolders = SelectiveExtensions.LocalFolders(AccountName, Account.RootPath,client.StorageUrl.AbsoluteUri);\r
+ //AppendToTree(localFolders, rootItem);\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,forSelectiveActivation);\r
+ \r
+ IsBusy = false;\r
+ }\r
+\r
+ private static void AppendToTree(IEnumerable<DirectoryRecord> localFolders, DirectoryRecord rootItem)\r
+ {\r
+ foreach (var folder in localFolders)\r
+ {\r
+ var items = from root in rootItem\r
+ from child in root\r
+ select child;\r
+ //If this folder is not included in the server folders\r
+ if (items.Any(dir => dir.Uri == folder.Uri)) \r
+ continue;\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 > 2; i--)\r
+ {\r
+ var parentUrl = String.Join("/", parts.Splice(0, i));\r
+ var parentUri = new Uri(parentUrl);\r
+\r
+ var parent = items.FirstOrDefault(dir => dir.Uri == parentUri);\r
+ if (parent != null)\r
+ {\r
+ parent.Directories.Add(folder);\r
+ break;\r
+ }\r
+ }\r
+ }\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,bool forSelectiveActivation)\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 = !forSelectiveActivation);\r
+\r
+ //If any of the root nodes has at least one selected child, set it to gray\r
+ SetRootNodeSelections(forSelectiveActivation);\r
+\r
+ //shouldBeChecked.Apply(record => record.IsChecked = true);\r
+\r
+\r
+\r
+ }\r
+\r
+ private void SetRootNodeSelections(bool forSelectiveActivation)\r
+ {\r
+ var selectedRoots = from DirectoryRecord rootRecord in RootNodes\r
+ from DirectoryRecord record in rootRecord\r
+ where record.IsChecked == true\r
+ select rootRecord;\r
+ selectedRoots.Apply(record => record.IsExplicitlyChecked = !forSelectiveActivation);\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{Enabled=true, Account=Account,Uris=uris,Added=added,Removed=removed});\r
+ \r
+\r
+ \r
+\r
+ TryClose(true);\r
+ }\r
+\r
+/*\r
+ private bool _isEnabled;\r
+ public bool IsEnabled\r
+ {\r
+ get { return _isEnabled; }\r
+ set\r
+ {\r
+ _isEnabled = value;\r
+ NotifyOfPropertyChange(()=>IsEnabled);\r
+ }\r
+ }\r
+*/\r
+\r
+ private void SaveSettings(IEnumerable<Uri> uris)\r
+ {\r
+ var selections = uris.Select(uri => uri.ToString()).ToArray();\r
+ //Account.SelectiveSyncEnabled = IsEnabled;\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