-#region
-/* -----------------------------------------------------------------------
- * <copyright file="PreferencesViewModel.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.Concurrent;
-using System.Collections.Generic;
-using System.Collections.Specialized;
-using System.ComponentModel.Composition;
-using System.Diagnostics;
-using System.IO;
-using System.Net;
-using System.Reflection;
-using System.Threading.Tasks;
-using System.Windows;
-using System.Windows.Forms;
-using Caliburn.Micro;
-using Pithos.Client.WPF.Configuration;
-using Pithos.Client.WPF.Properties;
-using Pithos.Client.WPF.SelectiveSynch;
-using Pithos.Client.WPF.Utils;
-using Pithos.Core;
-using Pithos.Interfaces;
-using System;
-using System.Linq;
-using Pithos.Network;
-using MessageBox = System.Windows.MessageBox;
-using Screen = Caliburn.Micro.Screen;
-
-namespace Pithos.Client.WPF.Preferences
-{
- /// <summary>
- /// The preferences screen displays user and account settings and updates the PithosMonitor
- /// classes when account settings change.
- /// </summary>
- /// <remarks>
- /// The class is a single ViewModel for all Preferences tabs. It can be broken in separate
- /// ViewModels, one for each tab.
- /// </remarks>
- [Export, PartCreationPolicy(CreationPolicy.Shared)]
- public class PreferencesViewModel : Screen
- {
- private readonly IEventAggregator _events;
-
- //Logging in the Pithos client is provided by log4net
- private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
-
- private PithosSettings _settings;
- public PithosSettings Settings
- {
- get { return _settings; }
- set
- {
- _settings = value;
- NotifyOfPropertyChange(()=>Settings);
- }
- }
-
- private ObservableConcurrentCollection<AccountViewModel> _accounts;
- public ObservableConcurrentCollection<AccountViewModel> Accounts
- {
- get { return _accounts; }
- set
- {
- _accounts = value;
- NotifyOfPropertyChange(()=>Accounts);
- }
- }
-
- public bool StartOnSystemStartup { get; set; }
-
- public ShellViewModel Shell { get; set; }
- //ShellExtensionController _extensionController=new ShellExtensionController();
-
- public PreferencesViewModel(IWindowManager windowManager, IEventAggregator events, ShellViewModel shell, PithosSettings settings, string currentTab)
- {
- // ReSharper disable DoNotCallOverridableMethodsInConstructor
- //Caliburn.Micro uses DisplayName for the view's title
- DisplayName = "Pithos+ Preferences";
- // ReSharper restore DoNotCallOverridableMethodsInConstructor
-
- _windowManager = windowManager;
- _events = events;
-
- Shell = shell;
-
- Settings=settings;
- Accounts = new ObservableConcurrentCollection<AccountViewModel>();
- if (settings.Accounts == null)
- {
- settings.Accounts=new AccountsCollection();
- settings.Save();
- }
- var accountVMs = from account in settings.Accounts
- select new AccountViewModel(account);
-
- Accounts.AddFromEnumerable(accountVMs);
-
- var startupPath = Environment.GetFolderPath(Environment.SpecialFolder.Startup);
- _shortcutPath = Path.Combine(startupPath, "Pithos.lnk");
-
-
- StartOnSystemStartup = File.Exists(_shortcutPath);
-
- SelectedTab = currentTab;
- }
-
- private string _selectedTab="General";
- public string SelectedTab
- {
- get { return _selectedTab; }
- set
- {
- _selectedTab = value??"General";
- NotifyOfPropertyChange(()=>SelectedTab);
- NotifyOfPropertyChange(() => AccountTabSelected);
- }
- }
-
-
- public bool AccountTabSelected
- {
- get { return _selectedTab == "AccountTab"; }
- }
- #region Preferences Properties
-
- private bool _noProxy;
- public bool NoProxy
- {
- get { return _noProxy; }
- set
- {
- _noProxy = value;
- NotifyOfPropertyChange(()=>NoProxy);
- }
- }
-
-
- private bool _defaultProxy;
-
- public bool DefaultProxy
- {
- get { return _defaultProxy; }
- set
- {
- _defaultProxy = value;
- NotifyOfPropertyChange(() => DefaultProxy);
- }
- }
-
-
- private bool _manualProxy;
-
- public bool ManualProxy
- {
- get { return _manualProxy; }
- set
- {
- _manualProxy = value;
- NotifyOfPropertyChange(() => ManualProxy);
- }
- }
- #endregion
-
-
- public int StartupDelay
- {
- get { return (int) Settings.StartupDelay.TotalMinutes; }
- set
- {
- if (value<0)
- throw new ArgumentOutOfRangeException("value",Resources.PreferencesViewModel_StartupDelay_Greater_or_equal_to_0);
- Settings.StartupDelay = TimeSpan.FromMinutes(value);
- NotifyOfPropertyChange(()=>StartupDelay);
- }
- }
-
- #region Commands
-
- public bool CanSelectiveSyncFolders
- {
- get { return CurrentAccount != null; }
- }
-
- public void SelectiveSyncFolders()
- {
- //var monitor = Shell.Monitors[CurrentAccount.AccountKey];
-
-
- var model = new SelectiveSynchViewModel(/*monitor,*/_events,CurrentAccount.Account,CurrentAccount.ApiKey);
- if (_windowManager.ShowDialog(model) == true)
- {
-
- }
- }
-
- /* private bool _networkTracing;
- public bool NetworkTracing
- {
- get { return _networkTracing; }
- set
- {
- _networkTracing = value;
-
- }
- }*/
-
- public void RefreshApiKey()
- {
- //_events.Publish(new Notification { Title = "Authorization failed", Message = "Your API Key has probably expired. You will be directed to a page where you can renew it", Level = TraceLevel.Error });
- if (CurrentAccount == null)
- return;
- try
- {
-
- var name = CurrentAccount.AccountName;
-
- var loginUri = new Uri(new Uri(CurrentAccount.ServerUrl), "login");
- var credentials = PithosAccount.RetrieveCredentials(loginUri.ToString(),name);
- if (credentials==null)
- return;
- //The server will return credentials for a different account, not just the current account
- //We need to find the correct account first
- var account = Accounts.First(act => act.AccountName == credentials.UserName && act.ServerUrl == CurrentAccount.ServerUrl);
- account.ApiKey = credentials.Password;
- account.IsExpired = false;
- Settings.Save();
- TaskEx.Delay(10000).ContinueWith(_ =>Shell.MonitorAccount(account.Account));
- NotifyOfPropertyChange(() => Accounts);
- }
- catch (AggregateException exc)
- {
- string message = String.Format("API Key retrieval failed");
- Log.Error(message, exc.InnerException);
- _events.Publish(new Notification { Title = "Authorization failed", Message = message, Level = TraceLevel.Error });
- }
- catch (Exception exc)
- {
- string message = String.Format("API Key retrieval failed");
- Log.Error(message, exc);
- _events.Publish(new Notification { Title = "Authorization failed", Message = message, Level = TraceLevel.Error });
- }
-
- }
-
-
- public void OpenLogPath()
- {
- Shell.OpenLogPath();
- }
-
- public void OpenLogConsole()
- {
- var logView=IoC.Get<LogConsole.LogConsoleViewModel>();
- _windowManager.ShowWindow(logView);
- }
-
- public void SaveChanges()
- {
- DoSave();
- TryClose(true);
- }
-
- public void RejectChanges()
- {
- Settings.Reload();
- TryClose(false);
- }
-
- public void ApplyChanges()
- {
- DoSave();
- }
-
- private void DoSave()
- {
- //SetStartupMode();
-
- //Ensure we save the settings changes first
- foreach (var account in _accountsToRemove)
- {
- Settings.Accounts.Remove(account);
- }
-
- foreach (var account in _accountsToAdd)
- {
- Settings.Accounts.Add(account);
- }
-
- Settings.Save();
-
-
- try
- {
- foreach (var account in _accountsToRemove)
- {
- Shell.RemoveMonitor(account.ServerUrl, account.AccountName);
- Shell.RemoveAccountFromDatabase(account);
- }
-
- foreach (var account in Settings.Accounts)
- {
- Shell.MonitorAccount(account);
- }
- }
- finally
- {
- _accountsToRemove.Clear();
- _accountsToAdd.Clear();
- }
-
- NotifyOfPropertyChange(()=>Settings);
-
- if (IgnoreCertificateErrors)
- ServicePointManager.ServerCertificateValidationCallback= (sender,certificate,chain,errors)=> true;
- else
- {
- ServicePointManager.ServerCertificateValidationCallback = null;
- }
- }
-
- /* public void ChangePithosFolder()
- {
- var browser = new FolderBrowserDialog();
- browser.SelectedPath = Settings.PithosPath;
- var result = browser.ShowDialog((IWin32Window)GetView());
- if (result == DialogResult.OK)
- {
- var newPath = browser.SelectedPath;
- var accountName = CurrentAccount.AccountName;
- var monitor = Shell.Monitors[accountName];
- monitor.Stop();
-
- Shell.Monitors.Remove(accountName);
-
- Directory.Move(Settings.PithosPath, newPath);
- Settings.PithosPath = newPath;
- Settings.Save();
-
- Shell.MonitorAccount(CurrentAccount);
-
- NotifyOfPropertyChange(() => Settings);
- }
- }
-*/
-
-
- readonly List<AccountSettings> _accountsToAdd=new List<AccountSettings>();
- public void AddAccount()
- {
- var wizard = new AddAccountViewModel();
- if (_windowManager.ShowDialog(wizard) == true)
- {
- string selectedPath = wizard.AccountPath;
- var initialRootPath = wizard.ShouldCreateOkeanosFolder?
- Path.Combine(selectedPath, "Okeanos")
- :selectedPath;
- var actualRootPath= initialRootPath;
- if (wizard.ShouldCreateOkeanosFolder)
- {
- int attempt = 1;
- while (Directory.Exists(actualRootPath) || File.Exists(actualRootPath))
- {
- actualRootPath = String.Format("{0} {1}", initialRootPath, attempt++);
- }
- }
-
-
-
- var account = Accounts.FirstOrDefault(act => act.AccountName == wizard.AccountName && act.ServerUrl == wizard.CurrentServer);
- if (account != null)
- {
- if (MessageBox.Show("The account you specified already exists. Do you want to update it?", "The account exists") == MessageBoxResult.Yes)
- {
- account.ApiKey = wizard.Token;
- account.IsExpired = false;
- CurrentAccount = account;
- }
- }
- else
- {
- var newAccount = new AccountSettings
- {
- AccountName = wizard.AccountName,
- ServerUrl = wizard.CurrentServer,
- ApiKey = wizard.Token,
- RootPath = actualRootPath,
- IsActive = wizard.IsAccountActive,
- };
-
-
- var client = new CloudFilesClient(newAccount.AccountName, newAccount.ApiKey)
- {
- AuthenticationUrl = newAccount.ServerUrl, UsePithos = true
- };
- client.Authenticate();
-
-
- var dirs = (from container in client.ListContainers(newAccount.AccountName)
- from dir in client.ListObjects(newAccount.AccountName, container.Name)
- where container.Name != "trash"
- select dir)
- .ToTree()
- .Select(d=>d.Uri.ToString())
- .ToArray();
-
- newAccount.SelectiveFolders.AddRange(dirs);
-
- //TODO:Add the "pithos" container as a default selection
-
- _accountsToAdd.Add(newAccount);
- var accountVm = new AccountViewModel(newAccount);
- (Accounts as IProducerConsumerCollection<AccountViewModel>).TryAdd(accountVm);
- CurrentAccount = accountVm;
- }
- NotifyOfPropertyChange(() => Accounts);
- NotifyOfPropertyChange(() => Settings);
- }
-
-
-
- }
-
-/*
- public void AddPithosAccount()
- {
- var credentials=PithosAccount.RetrieveCredentials(null);
- if (credentials == null)
- return;
- var account = Settings.Accounts.FirstOrDefault(act => act.AccountName == credentials.UserName);
- var accountVM = new AccountViewModel(account);
- if (account == null)
- {
- account=new AccountSettings{
- AccountName=credentials.UserName,
- ApiKey=credentials.Password
- };
- Settings.Accounts.Add(account);
- accountVM = new AccountViewModel(account);
- (Accounts as IProducerConsumerCollection<AccountViewModel>).TryAdd(accountVM);
- }
- else
- {
- account.ApiKey=credentials.Password;
- }
- //SelectedAccountIndex= Settings.Accounts.IndexOf(account);
- CurrentAccount = accountVM;
- NotifyOfPropertyChange(() => Accounts);
- NotifyOfPropertyChange(()=>Settings);
- }
-*/
-
-
- readonly List<AccountSettings> _accountsToRemove = new List<AccountSettings>();
- public void RemoveAccount()
- {
- Accounts.TryRemove(CurrentAccount);
- _accountsToRemove.Add(CurrentAccount.Account);
-
- CurrentAccount = null;
- NotifyOfPropertyChange(() => Accounts);
-
-
- //NotifyOfPropertyChange("Settings.Accounts");
- }
-
- public bool CanRemoveAccount
- {
- get { return (CurrentAccount != null); }
- }
-
- public bool CanClearAccountCache
- {
- get { return (CurrentAccount != null); }
- }
-
- public void ClearAccountCache()
- {
- if (MessageBoxResult.Yes == MessageBox.Show("You are about to delete all partially downloaded files from the account's cache.\n" +
- " You will have to download all partially downloaded data again\n" +
- "This change can not be undone\n\n" +
- "Do you wish to delete all partially downloaded data?", "Warning! Clearing account cache",
- MessageBoxButton.YesNo,MessageBoxImage.Question,MessageBoxResult.No))
- {
-
- var cachePath = Path.Combine(CurrentAccount.RootPath, FolderConstants.CacheFolder);
- var dir = new DirectoryInfo(cachePath);
- //The file may not exist if we just created the account
- if (!dir.Exists)
- return;
- dir.EnumerateFiles().Apply(file=>file.Delete());
- dir.EnumerateDirectories().Apply(folder => folder.Delete(true));
- }
- }
-
-
- public bool ExtensionsActivated
- {
- get { return Settings.ExtensionsActivated; }
- set
- {
- if (Settings.ExtensionsActivated == value)
- return;
-
- Settings.ExtensionsActivated = value;
-
-/*
- if (value)
- _extensionController.RegisterExtensions();
- else
- {
- _extensionController.UnregisterExtensions();
- }
-*/
- NotifyOfPropertyChange(() => ExtensionsActivated);
- }
- }
-
- public bool DebugLoggingEnabled
- {
- get { return Settings.DebugLoggingEnabled; }
- set {
- Settings.DebugLoggingEnabled = value;
- NotifyOfPropertyChange(()=>DebugLoggingEnabled);
- }
- }
-
- public bool IgnoreCertificateErrors
- {
- get { return Settings.IgnoreCertificateErrors; }
- set {
- Settings.IgnoreCertificateErrors = value;
- NotifyOfPropertyChange(() => IgnoreCertificateErrors);
- }
- }
-
- #endregion
-
- /* private int _selectedAccountIndex;
- public int SelectedAccountIndex
- {
- get { return _selectedAccountIndex; }
- set
- {
- //var accountCount=Settings.Accounts.Count;
- //if (accountCount == 0)
- // return;
- //if (0 <= value && value < accountCount)
- // _selectedAccountIndex = value;
- //else
- // _selectedAccountIndex = 0;
- _selectedAccountIndex = value;
- NotifyOfPropertyChange(() => CurrentAccount);
- NotifyOfPropertyChange(() => CanRemoveAccount);
- NotifyOfPropertyChange(()=>SelectedAccountIndex);
- }
- }*/
-
- private AccountViewModel _currentAccount;
- private readonly IWindowManager _windowManager;
- private readonly string _shortcutPath;
-
-
-
- public AccountViewModel CurrentAccount
- {
- get { return _currentAccount; }
- set
- {
- _currentAccount = value;
- NotifyOfPropertyChange(()=>CurrentAccount);
- NotifyOfPropertyChange(() => CanRemoveAccount);
- NotifyOfPropertyChange(() => CanSelectiveSyncFolders);
- NotifyOfPropertyChange(() => CanMoveAccountFolder);
- NotifyOfPropertyChange(() => CanClearAccountCache);
- }
- }
-
-/*
- public AccountSettings CurrentAccount
- {
- get {
- if (0 <= SelectedAccountIndex && SelectedAccountIndex < Settings.Accounts.Count)
- return Settings.Accounts[SelectedAccountIndex];
- return null;
- }
-
- }
-*/
-
-
- public bool CanMoveAccountFolder
- {
- get { return CurrentAccount != null; }
- }
-
- public void MoveAccountFolder()
- {
-
- using (var dlg = new FolderBrowserDialog())
- {
- var currentFolder = CurrentAccount.RootPath;
- dlg.SelectedPath = currentFolder;
- //Ask the user to select a folder
- //Note: We need a parent window here, which we retrieve with GetView
- var view = (Window)GetView();
- if (DialogResult.OK != dlg.ShowDialog(new Wpf32Window(view)))
- return;
-
- var newPath= dlg.SelectedPath;
- //Find the account's monitor and stop it
- PithosMonitor monitor;
- if (Shell.Monitors.TryGetValue(CurrentAccount.AccountKey, out monitor))
- {
- monitor.Stop();
-
-
- var oldPath = monitor.RootPath;
- //The old directory may not exist eg. if we create an account for the first time
- if (Directory.Exists(oldPath))
- {
- //If it does, do the move
-
- //Now Create all of the directories
- foreach (string dirPath in Directory.EnumerateDirectories(oldPath, "*",
- SearchOption.AllDirectories))
- Directory.CreateDirectory(dirPath.Replace(oldPath, newPath));
-
- //Copy all the files
- foreach (string newFilePath in Directory.EnumerateFiles(oldPath, "*.*",
- SearchOption.AllDirectories))
- File.Copy(newFilePath, newFilePath.Replace(oldPath, newPath));
-
- Log.InfoFormat("Deleting account folder {0}",oldPath);
- Directory.Delete(oldPath, true);
-
- //We also need to change the path of the existing file states
- monitor.MoveFileStates(oldPath, newPath);
- }
- }
- //Replace the old rootpath with the new
- CurrentAccount.RootPath = newPath;
- //TODO: This will save all settings changes. Too coarse grained, need to fix at a later date
- Settings.Save();
- //And start the monitor on the new RootPath
- if (monitor != null)
- {
- monitor.RootPath = newPath;
- if (CurrentAccount.IsActive)
- monitor.Start();
- }
- else
- Shell.MonitorAccount(CurrentAccount.Account);
- //Finally, notify that the Settings, CurrentAccount have changed
- NotifyOfPropertyChange(() => CurrentAccount);
- NotifyOfPropertyChange(() => Settings);
-
- }
- }
- }
-}
+#region\r
+/* -----------------------------------------------------------------------\r
+ * <copyright file="PreferencesViewModel.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
+\r
+\r
+using System.Collections.Concurrent;\r
+using System.Collections.Generic;\r
+using System.Collections.Specialized;\r
+using System.ComponentModel.Composition;\r
+using System.Diagnostics;\r
+using System.IO;\r
+using System.Net;\r
+using System.Reflection;\r
+using System.Threading.Tasks;\r
+using System.Windows;\r
+using System.Windows.Forms;\r
+using Caliburn.Micro;\r
+using Pithos.Client.WPF.Configuration;\r
+using Pithos.Client.WPF.Properties;\r
+using Pithos.Client.WPF.SelectiveSynch;\r
+using Pithos.Client.WPF.Utils;\r
+using Pithos.Core;\r
+using Pithos.Interfaces;\r
+using System;\r
+using System.Linq;\r
+using Pithos.Network;\r
+using MessageBox = System.Windows.MessageBox;\r
+using Screen = Caliburn.Micro.Screen;\r
+\r
+namespace Pithos.Client.WPF.Preferences\r
+{\r
+ /// <summary>\r
+ /// The preferences screen displays user and account settings and updates the PithosMonitor\r
+ /// classes when account settings change.\r
+ /// </summary>\r
+ /// <remarks>\r
+ /// The class is a single ViewModel for all Preferences tabs. It can be broken in separate\r
+ /// ViewModels, one for each tab.\r
+ /// </remarks>\r
+ [Export, PartCreationPolicy(CreationPolicy.Shared)]\r
+ public class PreferencesViewModel : Screen\r
+ {\r
+ private readonly IEventAggregator _events;\r
+\r
+ //Logging in the Pithos client is provided by log4net\r
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);\r
+\r
+ private PithosSettings _settings;\r
+ public PithosSettings Settings\r
+ {\r
+ get { return _settings; }\r
+ set\r
+ {\r
+ _settings = value;\r
+ NotifyOfPropertyChange(()=>Settings);\r
+ }\r
+ }\r
+\r
+ private ObservableConcurrentCollection<AccountViewModel> _accounts;\r
+ public ObservableConcurrentCollection<AccountViewModel> Accounts\r
+ {\r
+ get { return _accounts; }\r
+ set \r
+ { \r
+ _accounts = value;\r
+ NotifyOfPropertyChange(()=>Accounts);\r
+ }\r
+ }\r
+ \r
+ public bool StartOnSystemStartup { get; set; }\r
+\r
+ public ShellViewModel Shell { get; set; }\r
+ //ShellExtensionController _extensionController=new ShellExtensionController();\r
+\r
+ public PreferencesViewModel(IWindowManager windowManager, IEventAggregator events, ShellViewModel shell, PithosSettings settings, string currentTab)\r
+ {\r
+ // ReSharper disable DoNotCallOverridableMethodsInConstructor\r
+ //Caliburn.Micro uses DisplayName for the view's title\r
+ DisplayName = "Pithos+ Preferences";\r
+ // ReSharper restore DoNotCallOverridableMethodsInConstructor\r
+\r
+ _windowManager = windowManager;\r
+ _events = events;\r
+\r
+ Shell = shell;\r
+ \r
+ Settings=settings;\r
+ Accounts = new ObservableConcurrentCollection<AccountViewModel>();\r
+ if (settings.Accounts == null)\r
+ {\r
+ settings.Accounts=new AccountsCollection();\r
+ settings.Save();\r
+ }\r
+ var accountVMs = from account in settings.Accounts\r
+ select new AccountViewModel(account);\r
+\r
+ Accounts.AddFromEnumerable(accountVMs);\r
+ \r
+ var startupPath = Environment.GetFolderPath(Environment.SpecialFolder.Startup);\r
+ _shortcutPath = Path.Combine(startupPath, "Pithos.lnk");\r
+\r
+\r
+ StartOnSystemStartup = File.Exists(_shortcutPath);\r
+\r
+ SelectedTab = currentTab;\r
+ }\r
+\r
+ private string _selectedTab="General";\r
+ public string SelectedTab\r
+ {\r
+ get { return _selectedTab; }\r
+ set\r
+ {\r
+ _selectedTab = value??"General";\r
+ NotifyOfPropertyChange(()=>SelectedTab);\r
+ NotifyOfPropertyChange(() => AccountTabSelected);\r
+ }\r
+ }\r
+\r
+\r
+ public bool AccountTabSelected\r
+ {\r
+ get { return _selectedTab == "AccountTab"; }\r
+ }\r
+ #region Preferences Properties\r
+\r
+ private bool _noProxy;\r
+ public bool NoProxy\r
+ {\r
+ get { return _noProxy; }\r
+ set\r
+ {\r
+ _noProxy = value;\r
+ NotifyOfPropertyChange(()=>NoProxy);\r
+ }\r
+ }\r
+\r
+\r
+ private bool _defaultProxy;\r
+\r
+ public bool DefaultProxy\r
+ {\r
+ get { return _defaultProxy; }\r
+ set\r
+ {\r
+ _defaultProxy = value;\r
+ NotifyOfPropertyChange(() => DefaultProxy);\r
+ }\r
+ }\r
+\r
+\r
+ private bool _manualProxy;\r
+\r
+ public bool ManualProxy\r
+ {\r
+ get { return _manualProxy; }\r
+ set\r
+ {\r
+ _manualProxy = value;\r
+ NotifyOfPropertyChange(() => ManualProxy);\r
+ }\r
+ }\r
+ #endregion\r
+\r
+\r
+ public int StartupDelay\r
+ {\r
+ get { return (int) Settings.StartupDelay.TotalMinutes; }\r
+ set\r
+ {\r
+ if (value<0)\r
+ throw new ArgumentOutOfRangeException("value",Resources.PreferencesViewModel_StartupDelay_Greater_or_equal_to_0);\r
+ Settings.StartupDelay = TimeSpan.FromMinutes(value);\r
+ NotifyOfPropertyChange(()=>StartupDelay);\r
+ }\r
+ }\r
+ \r
+ #region Commands\r
+ \r
+ public bool CanSelectiveSyncFolders\r
+ {\r
+ get { return CurrentAccount != null; }\r
+ }\r
+\r
+ public void SelectiveSyncFolders()\r
+ {\r
+ //var monitor = Shell.Monitors[CurrentAccount.AccountKey];\r
+ \r
+\r
+ var model = new SelectiveSynchViewModel(/*monitor,*/_events,CurrentAccount.Account,CurrentAccount.ApiKey);\r
+ if (_windowManager.ShowDialog(model) == true)\r
+ {\r
+ \r
+ }\r
+ }\r
+\r
+ /* private bool _networkTracing;\r
+ public bool NetworkTracing\r
+ {\r
+ get { return _networkTracing; }\r
+ set\r
+ {\r
+ _networkTracing = value;\r
+ \r
+ }\r
+ }*/\r
+\r
+ public void RefreshApiKey()\r
+ {\r
+ //_events.Publish(new Notification { Title = "Authorization failed", Message = "Your API Key has probably expired. You will be directed to a page where you can renew it", Level = TraceLevel.Error });\r
+ if (CurrentAccount == null)\r
+ return;\r
+ try\r
+ {\r
+\r
+ var name = CurrentAccount.AccountName;\r
+\r
+ var loginUri = new Uri(new Uri(CurrentAccount.ServerUrl), "login");\r
+ var credentials = PithosAccount.RetrieveCredentials(loginUri.ToString(),name);\r
+ if (credentials==null)\r
+ return;\r
+ //The server will return credentials for a different account, not just the current account\r
+ //We need to find the correct account first\r
+ var account = Accounts.First(act => act.AccountName == credentials.UserName && act.ServerUrl == CurrentAccount.ServerUrl);\r
+ account.ApiKey = credentials.Password; \r
+ account.IsExpired = false;\r
+ Settings.Save();\r
+ TaskEx.Delay(10000).ContinueWith(_ =>Shell.MonitorAccount(account.Account));\r
+ NotifyOfPropertyChange(() => Accounts);\r
+ }\r
+ catch (AggregateException exc)\r
+ {\r
+ string message = String.Format("API Key retrieval failed");\r
+ Log.Error(message, exc.InnerException);\r
+ _events.Publish(new Notification { Title = "Authorization failed", Message = message, Level = TraceLevel.Error });\r
+ }\r
+ catch (Exception exc)\r
+ {\r
+ string message = String.Format("API Key retrieval failed");\r
+ Log.Error(message, exc);\r
+ _events.Publish(new Notification { Title = "Authorization failed", Message = message, Level = TraceLevel.Error });\r
+ }\r
+\r
+ }\r
+\r
+ \r
+ public void OpenLogPath()\r
+ {\r
+ Shell.OpenLogPath();\r
+ }\r
+\r
+ public void OpenLogConsole()\r
+ {\r
+ var logView=IoC.Get<LogConsole.LogConsoleViewModel>(); \r
+ _windowManager.ShowWindow(logView);\r
+ }\r
+\r
+ public void SaveChanges()\r
+ {\r
+ DoSave();\r
+ TryClose(true);\r
+ }\r
+\r
+ public void RejectChanges()\r
+ {\r
+ Settings.Reload();\r
+ TryClose(false);\r
+ }\r
+\r
+ public void ApplyChanges()\r
+ {\r
+ DoSave();\r
+ }\r
+\r
+ private void DoSave()\r
+ {\r
+ //SetStartupMode(); \r
+\r
+ //Ensure we save the settings changes first\r
+ foreach (var account in _accountsToRemove)\r
+ {\r
+ Settings.Accounts.Remove(account);\r
+ }\r
+\r
+ foreach (var account in _accountsToAdd)\r
+ {\r
+ Settings.Accounts.Add(account); \r
+ }\r
+\r
+ Settings.Save();\r
+\r
+\r
+ try\r
+ {\r
+ foreach (var account in _accountsToRemove)\r
+ {\r
+ Shell.RemoveMonitor(account.ServerUrl, account.AccountName);\r
+ Shell.RemoveAccountFromDatabase(account);\r
+ }\r
+\r
+ foreach (var account in Settings.Accounts)\r
+ {\r
+ Shell.MonitorAccount(account);\r
+ }\r
+ } \r
+ finally\r
+ {\r
+ _accountsToRemove.Clear();\r
+ _accountsToAdd.Clear();\r
+ }\r
+\r
+ NotifyOfPropertyChange(()=>Settings);\r
+\r
+ if (IgnoreCertificateErrors)\r
+ ServicePointManager.ServerCertificateValidationCallback= (sender,certificate,chain,errors)=> true;\r
+ else\r
+ {\r
+ ServicePointManager.ServerCertificateValidationCallback = null;\r
+ }\r
+ }\r
+\r
+ /* public void ChangePithosFolder()\r
+ {\r
+ var browser = new FolderBrowserDialog();\r
+ browser.SelectedPath = Settings.PithosPath;\r
+ var result = browser.ShowDialog((IWin32Window)GetView());\r
+ if (result == DialogResult.OK)\r
+ {\r
+ var newPath = browser.SelectedPath;\r
+ var accountName = CurrentAccount.AccountName;\r
+ var monitor = Shell.Monitors[accountName];\r
+ monitor.Stop();\r
+ \r
+ Shell.Monitors.Remove(accountName);\r
+\r
+ Directory.Move(Settings.PithosPath, newPath);\r
+ Settings.PithosPath = newPath;\r
+ Settings.Save();\r
+\r
+ Shell.MonitorAccount(CurrentAccount);\r
+\r
+ NotifyOfPropertyChange(() => Settings); \r
+ }\r
+ }\r
+*/\r
+\r
+\r
+ readonly List<AccountSettings> _accountsToAdd=new List<AccountSettings>();\r
+ public void AddAccount()\r
+ {\r
+ var wizard = new AddAccountViewModel();\r
+ if (_windowManager.ShowDialog(wizard) == true)\r
+ {\r
+ string selectedPath = wizard.AccountPath;\r
+ var initialRootPath = wizard.ShouldCreateOkeanosFolder?\r
+ Path.Combine(selectedPath, "Okeanos")\r
+ :selectedPath;\r
+ var actualRootPath= initialRootPath;\r
+ if (wizard.ShouldCreateOkeanosFolder)\r
+ {\r
+ int attempt = 1;\r
+ while (Directory.Exists(actualRootPath) || File.Exists(actualRootPath))\r
+ {\r
+ actualRootPath = String.Format("{0} {1}", initialRootPath, attempt++);\r
+ }\r
+ }\r
+\r
+\r
+\r
+ var account = Accounts.FirstOrDefault(act => act.AccountName == wizard.AccountName && act.ServerUrl == wizard.CurrentServer);\r
+ if (account != null)\r
+ {\r
+ if (MessageBox.Show("The account you specified already exists. Do you want to update it?", "The account exists") == MessageBoxResult.Yes)\r
+ {\r
+ account.ApiKey = wizard.Token;\r
+ account.IsExpired = false;\r
+ CurrentAccount = account;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ var newAccount = new AccountSettings\r
+ {\r
+ AccountName = wizard.AccountName,\r
+ ServerUrl = wizard.CurrentServer,\r
+ ApiKey = wizard.Token,\r
+ RootPath = actualRootPath,\r
+ IsActive = wizard.IsAccountActive,\r
+ };\r
+\r
+\r
+ var client = new CloudFilesClient(newAccount.AccountName, newAccount.ApiKey)\r
+ {\r
+ AuthenticationUrl = newAccount.ServerUrl, UsePithos = true\r
+ };\r
+ client.Authenticate();\r
+\r
+\r
+ var containers = client.ListContainers(newAccount.AccountName);\r
+ var containerUris = from container in containers\r
+ select String.Format(@"{0}/v1/{1}/{2}",\r
+ newAccount.ServerUrl, newAccount.AccountName, container.Name);\r
+ \r
+ newAccount.SelectiveFolders.AddRange(containerUris.ToArray());\r
+\r
+ var objectInfos = (from container in containers\r
+ from dir in client.ListObjects(newAccount.AccountName, container.Name)\r
+ where container.Name != "trash"\r
+ select dir).ToList();\r
+ var tree = objectInfos.ToTree();\r
+\r
+ var selected = (from root in tree \r
+ from child in root \r
+ select child.Uri.ToString()).ToArray();\r
+ newAccount.SelectiveFolders.AddRange(selected);\r
+\r
+ \r
+ //TODO:Add the "pithos" container as a default selection \r
+\r
+ _accountsToAdd.Add(newAccount);\r
+ var accountVm = new AccountViewModel(newAccount);\r
+ (Accounts as IProducerConsumerCollection<AccountViewModel>).TryAdd(accountVm);\r
+ CurrentAccount = accountVm;\r
+ }\r
+ NotifyOfPropertyChange(() => Accounts);\r
+ NotifyOfPropertyChange(() => Settings); \r
+ }\r
+\r
+\r
+ \r
+ }\r
+\r
+/*\r
+ public void AddPithosAccount()\r
+ {\r
+ var credentials=PithosAccount.RetrieveCredentials(null);\r
+ if (credentials == null)\r
+ return;\r
+ var account = Settings.Accounts.FirstOrDefault(act => act.AccountName == credentials.UserName);\r
+ var accountVM = new AccountViewModel(account);\r
+ if (account == null)\r
+ {\r
+ account=new AccountSettings{\r
+ AccountName=credentials.UserName,\r
+ ApiKey=credentials.Password\r
+ };\r
+ Settings.Accounts.Add(account);\r
+ accountVM = new AccountViewModel(account);\r
+ (Accounts as IProducerConsumerCollection<AccountViewModel>).TryAdd(accountVM);\r
+ }\r
+ else\r
+ {\r
+ account.ApiKey=credentials.Password;\r
+ }\r
+ //SelectedAccountIndex= Settings.Accounts.IndexOf(account);\r
+ CurrentAccount = accountVM;\r
+ NotifyOfPropertyChange(() => Accounts);\r
+ NotifyOfPropertyChange(()=>Settings); \r
+ }\r
+*/\r
+\r
+\r
+ readonly List<AccountSettings> _accountsToRemove = new List<AccountSettings>();\r
+ public void RemoveAccount()\r
+ {\r
+ Accounts.TryRemove(CurrentAccount);\r
+ _accountsToRemove.Add(CurrentAccount.Account);\r
+\r
+ CurrentAccount = null;\r
+ NotifyOfPropertyChange(() => Accounts);\r
+\r
+ \r
+ //NotifyOfPropertyChange("Settings.Accounts");\r
+ }\r
+\r
+ public bool CanRemoveAccount\r
+ {\r
+ get { return (CurrentAccount != null); }\r
+ }\r
+\r
+ public bool CanClearAccountCache\r
+ {\r
+ get { return (CurrentAccount != null); }\r
+ }\r
+\r
+ public void ClearAccountCache()\r
+ {\r
+ if (MessageBoxResult.Yes == MessageBox.Show("You are about to delete all partially downloaded files from the account's cache.\n" +\r
+ " You will have to download all partially downloaded data again\n" +\r
+ "This change can not be undone\n\n" +\r
+ "Do you wish to delete all partially downloaded data?", "Warning! Clearing account cache",\r
+ MessageBoxButton.YesNo,MessageBoxImage.Question,MessageBoxResult.No))\r
+ {\r
+\r
+ var cachePath = Path.Combine(CurrentAccount.RootPath, FolderConstants.CacheFolder);\r
+ var dir = new DirectoryInfo(cachePath);\r
+ //The file may not exist if we just created the account\r
+ if (!dir.Exists)\r
+ return;\r
+ dir.EnumerateFiles().Apply(file=>file.Delete());\r
+ dir.EnumerateDirectories().Apply(folder => folder.Delete(true));\r
+ }\r
+ }\r
+\r
+\r
+ public bool ExtensionsActivated\r
+ {\r
+ get { return Settings.ExtensionsActivated; }\r
+ set\r
+ {\r
+ if (Settings.ExtensionsActivated == value)\r
+ return;\r
+\r
+ Settings.ExtensionsActivated = value;\r
+\r
+/*\r
+ if (value)\r
+ _extensionController.RegisterExtensions();\r
+ else\r
+ {\r
+ _extensionController.UnregisterExtensions();\r
+ }\r
+*/\r
+ NotifyOfPropertyChange(() => ExtensionsActivated);\r
+ }\r
+ }\r
+\r
+ public bool DebugLoggingEnabled\r
+ {\r
+ get { return Settings.DebugLoggingEnabled; }\r
+ set { \r
+ Settings.DebugLoggingEnabled = value;\r
+ NotifyOfPropertyChange(()=>DebugLoggingEnabled);\r
+ }\r
+ }\r
+\r
+ public bool IgnoreCertificateErrors\r
+ {\r
+ get { return Settings.IgnoreCertificateErrors; }\r
+ set {\r
+ Settings.IgnoreCertificateErrors = value;\r
+ NotifyOfPropertyChange(() => IgnoreCertificateErrors);\r
+ }\r
+ }\r
+ \r
+ #endregion\r
+\r
+ /* private int _selectedAccountIndex;\r
+ public int SelectedAccountIndex\r
+ {\r
+ get { return _selectedAccountIndex; }\r
+ set\r
+ {\r
+ //var accountCount=Settings.Accounts.Count;\r
+ //if (accountCount == 0)\r
+ // return;\r
+ //if (0 <= value && value < accountCount)\r
+ // _selectedAccountIndex = value;\r
+ //else\r
+ // _selectedAccountIndex = 0;\r
+ _selectedAccountIndex = value;\r
+ NotifyOfPropertyChange(() => CurrentAccount);\r
+ NotifyOfPropertyChange(() => CanRemoveAccount);\r
+ NotifyOfPropertyChange(()=>SelectedAccountIndex);\r
+ }\r
+ }*/\r
+\r
+ private AccountViewModel _currentAccount;\r
+ private readonly IWindowManager _windowManager;\r
+ private readonly string _shortcutPath;\r
+\r
+\r
+ \r
+ public AccountViewModel CurrentAccount\r
+ {\r
+ get { return _currentAccount; }\r
+ set\r
+ {\r
+ _currentAccount = value;\r
+ NotifyOfPropertyChange(()=>CurrentAccount);\r
+ NotifyOfPropertyChange(() => CanRemoveAccount);\r
+ NotifyOfPropertyChange(() => CanSelectiveSyncFolders);\r
+ NotifyOfPropertyChange(() => CanMoveAccountFolder);\r
+ NotifyOfPropertyChange(() => CanClearAccountCache);\r
+ }\r
+ }\r
+\r
+/*\r
+ public AccountSettings CurrentAccount\r
+ {\r
+ get {\r
+ if (0 <= SelectedAccountIndex && SelectedAccountIndex < Settings.Accounts.Count) \r
+ return Settings.Accounts[SelectedAccountIndex];\r
+ return null;\r
+ }\r
+\r
+ }\r
+*/\r
+\r
+\r
+ public bool CanMoveAccountFolder\r
+ {\r
+ get { return CurrentAccount != null; }\r
+ }\r
+\r
+ public void MoveAccountFolder()\r
+ {\r
+\r
+ using (var dlg = new FolderBrowserDialog())\r
+ {\r
+ var currentFolder = CurrentAccount.RootPath;\r
+ dlg.SelectedPath = currentFolder;\r
+ //Ask the user to select a folder\r
+ //Note: We need a parent window here, which we retrieve with GetView \r
+ var view = (Window)GetView(); \r
+ if (DialogResult.OK != dlg.ShowDialog(new Wpf32Window(view)))\r
+ return; \r
+\r
+ var newPath= dlg.SelectedPath; \r
+ //Find the account's monitor and stop it\r
+ PithosMonitor monitor;\r
+ if (Shell.Monitors.TryGetValue(CurrentAccount.AccountKey, out monitor))\r
+ {\r
+ monitor.Stop();\r
+\r
+\r
+ var oldPath = monitor.RootPath;\r
+ //The old directory may not exist eg. if we create an account for the first time\r
+ if (Directory.Exists(oldPath))\r
+ {\r
+ //If it does, do the move\r
+\r
+ //Now Create all of the directories\r
+ foreach (string dirPath in Directory.EnumerateDirectories(oldPath, "*",\r
+ SearchOption.AllDirectories))\r
+ Directory.CreateDirectory(dirPath.Replace(oldPath, newPath));\r
+\r
+ //Copy all the files\r
+ foreach (string newFilePath in Directory.EnumerateFiles(oldPath, "*.*",\r
+ SearchOption.AllDirectories))\r
+ File.Copy(newFilePath, newFilePath.Replace(oldPath, newPath));\r
+\r
+ Log.InfoFormat("Deleting account folder {0}",oldPath);\r
+ Directory.Delete(oldPath, true);\r
+\r
+ //We also need to change the path of the existing file states\r
+ monitor.MoveFileStates(oldPath, newPath);\r
+ }\r
+ }\r
+ //Replace the old rootpath with the new\r
+ CurrentAccount.RootPath = newPath;\r
+ //TODO: This will save all settings changes. Too coarse grained, need to fix at a later date\r
+ Settings.Save(); \r
+ //And start the monitor on the new RootPath \r
+ if (monitor != null)\r
+ {\r
+ monitor.RootPath = newPath;\r
+ if (CurrentAccount.IsActive)\r
+ monitor.Start();\r
+ }\r
+ else\r
+ Shell.MonitorAccount(CurrentAccount.Account);\r
+ //Finally, notify that the Settings, CurrentAccount have changed\r
+ NotifyOfPropertyChange(() => CurrentAccount);\r
+ NotifyOfPropertyChange(() => Settings);\r
+\r
+ }\r
+ }\r
+ }\r
+}\r
-#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;
-using Pithos.Network;
-
-namespace Pithos.Client.WPF.SelectiveSynch
-{
- class SelectiveSynchViewModel:Screen
- {
- 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;
- private string _apiKey;
-
- 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, string apiKey)
- {
- Account = account;
- AccountName = account.AccountName;
- DisplayName = String.Format("Selective folder synchronization for {0}",account.AccountName);
- //_monitor = monitor;
- _events = events;
- _apiKey = apiKey;
- TaskEx.Run(LoadRootNode);
- }
-
- private void LoadRootNode()
- {
- //TODO: Check this
- var client = new CloudFilesClient(AccountName,_apiKey){AuthenticationUrl=Account.ServerUrl,UsePithos=true};
- client.Authenticate();
-
-
- var dirs = from container in client.ListContainers(AccountName)
- where container.Name != "trash"
- 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(AccountName, container.Name)
- 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)
- select folder).ToTree()
- }).ToList()
- };
-
- var othersNode = new DirectoryRecord
- {
- DisplayName = "Shared to me",
- 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;
-
-
-
- //Initially, all nodes are checked
- //We need to *uncheck* the nodes that are not selected
-
- var allNodes = (from DirectoryRecord rootRecord in RootNodes
- from DirectoryRecord record in rootRecord
- select record).ToList();
-
- allNodes.Apply(record => record.IsChecked = false);
-
- if (selections.Count == 0)
- {
- // allNodes.Apply(record => record.IsChecked = false);
- return;
- }
-
- var selects = (from DirectoryRecord rootRecord in RootNodes
- from DirectoryRecord record in rootRecord
- where record.Uri !=null && selections.Contains(record.Uri.ToString())
- select record).ToList();
- //var shouldBeChecked = allNodes.Except(selects).ToList();
-
- selects.Apply(record=>record.IsExplicitlyChecked=true);
-
- //shouldBeChecked.Apply(record => record.IsChecked = true);
-
-
-
- }
-
- 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
+\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
+ 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
+ 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