aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels
diff options
context:
space:
mode:
authorAvi Levkovich <avi@twine-s.com>2018-02-26 16:30:42 +0200
committerAvi Levkovich <avi@twine-s.com>2018-02-26 16:30:42 +0200
commit5942bb7a13e5ad26c720a1b95ae4ea766eeeda25 (patch)
tree2a855ce1065c875e615f5b040f984cb3fb84e518 /Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels
parent4c052df707280abd208b03aa88cf904e0eb6b9bf (diff)
parent6549d8672a93893599e921d9f1938af7dcabb8bf (diff)
downloadTango-5942bb7a13e5ad26c720a1b95ae4ea766eeeda25.tar.gz
Tango-5942bb7a13e5ad26c720a1b95ae4ea766eeeda25.zip
MERGE!
Diffstat (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels')
-rw-r--r--Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoadingViewVM.cs9
-rw-r--r--Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MainViewVM.cs153
-rw-r--r--Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/ModuleWindowVM.cs30
-rw-r--r--Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/UpdateViewVM.cs305
4 files changed, 496 insertions, 1 deletions
diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoadingViewVM.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoadingViewVM.cs
index 55a54e8aa..9acf26afd 100644
--- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoadingViewVM.cs
+++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoadingViewVM.cs
@@ -6,9 +6,11 @@ using System.Threading;
using System.Threading.Tasks;
using Tango.Core.Helpers;
using Tango.Integration.Observables;
+using Tango.Logging;
using Tango.MachineStudio.Common.Modules;
using Tango.MachineStudio.Common.Navigation;
using Tango.MachineStudio.Common.Notifications;
+using Tango.MachineStudio.Common.StudioApplication;
using Tango.SharedUI;
namespace Tango.MachineStudio.UI.ViewModels
@@ -23,14 +25,17 @@ namespace Tango.MachineStudio.UI.ViewModels
private INavigationManager _navigationManager;
private IStudioModuleLoader _studioModuleLoader;
+ public IStudioApplicationManager ApplicationManager { get; set; }
+
/// <summary>
/// Initializes a new instance of the <see cref="LoadingViewVM"/> class.
/// </summary>
/// <param name="navigationManager">The navigation manager.</param>
/// <param name="studioModuleLoader">The studio module loader.</param>
/// <param name="notificationProvider">The notification provider.</param>
- public LoadingViewVM(INavigationManager navigationManager, IStudioModuleLoader studioModuleLoader, INotificationProvider notificationProvider)
+ public LoadingViewVM(IStudioApplicationManager applicationManager, INavigationManager navigationManager, IStudioModuleLoader studioModuleLoader, INotificationProvider notificationProvider)
{
+ ApplicationManager = applicationManager;
_navigationManager = navigationManager;
_studioModuleLoader = studioModuleLoader;
_notificationProvider = notificationProvider;
@@ -55,6 +60,8 @@ namespace Tango.MachineStudio.UI.ViewModels
}
catch (Exception ex)
{
+ LogManager.Log(ex);
+
InvokeUINow(() =>
{
if (_notificationProvider.ShowQuestion("An error occurred while trying to connect to Twine database." + Environment.NewLine + "Would you like to try again?"))
diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MainViewVM.cs
index 679ba5ff3..fb2cd5c82 100644
--- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MainViewVM.cs
+++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MainViewVM.cs
@@ -6,7 +6,11 @@ using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
+using System.Threading;
using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
using Tango.Core.Commands;
using Tango.Integration.Services;
using Tango.Logging;
@@ -16,10 +20,14 @@ using Tango.MachineStudio.Common.Modules;
using Tango.MachineStudio.Common.Navigation;
using Tango.MachineStudio.Common.Notifications;
using Tango.MachineStudio.Common.StudioApplication;
+using Tango.MachineStudio.Common.Update;
+using Tango.MachineStudio.UI.StudioApplication;
using Tango.MachineStudio.UI.SupervisingController;
using Tango.MachineStudio.UI.Views;
+using Tango.MachineStudio.UI.Windows;
using Tango.PMR.Stubs;
using Tango.SharedUI;
+using Tango.SharedUI.Helpers;
using Tango.Transport.Adapters;
namespace Tango.MachineStudio.UI.ViewModels
@@ -33,6 +41,7 @@ namespace Tango.MachineStudio.UI.ViewModels
private IStudioModule _currentModule;
private INavigationManager _navigation;
private bool _isDisconnecting;
+ private Thread _updateCheckThread;
/// <summary>
/// Gets or sets the current loaded module.
@@ -69,6 +78,11 @@ namespace Tango.MachineStudio.UI.ViewModels
public RelayCommand<IStudioModule> StartModuleCommand { get; set; }
/// <summary>
+ /// Gets or sets the open module in window command.
+ /// </summary>
+ public RelayCommand<IStudioModule> OpenModuleInWindowCommand { get; set; }
+
+ /// <summary>
/// Gets or sets the home command.
/// </summary>
public RelayCommand HomeCommand { get; set; }
@@ -88,6 +102,16 @@ namespace Tango.MachineStudio.UI.ViewModels
/// </summary>
public RelayCommand SignoutCommand { get; set; }
+ /// <summary>
+ /// Gets or sets the exit command.
+ /// </summary>
+ public RelayCommand ExitCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the update center command.
+ /// </summary>
+ public RelayCommand UpdateCenterCommand { get; set; }
+
private IAuthenticationProvider _authenticationProvider;
/// <summary>
/// Gets or sets the authentication provider.
@@ -128,6 +152,38 @@ namespace Tango.MachineStudio.UI.ViewModels
set { _applicationManager = value; RaisePropertyChangedAuto(); }
}
+ private bool _isUpdateAvailable;
+ /// <summary>
+ /// Gets or sets a value indicating whether a new version update is available.
+ /// </summary>
+ public bool IsUpdateAvailable
+ {
+ get { return _isUpdateAvailable; }
+ set { _isUpdateAvailable = value; RaisePropertyChangedAuto(); }
+ }
+
+ private String _latestVersion;
+ /// <summary>
+ /// Gets or sets the latest version.
+ /// </summary>
+ public String LatestVersion
+ {
+ get { return _latestVersion; }
+ set { _latestVersion = value; RaisePropertyChangedAuto(); }
+ }
+
+
+ private bool _disableCheckForUpdates;
+ /// <summary>
+ /// Gets or sets a value indicating whether [disable check for updates].
+ /// </summary>
+ public bool DisableCheckForUpdates
+ {
+ get { return _disableCheckForUpdates; }
+ set { _disableCheckForUpdates = value; RaisePropertyChangedAuto(); }
+ }
+
+
/// <summary>
/// Initializes a new instance of the <see cref="MainViewVM"/> class.
/// </summary>
@@ -157,6 +213,46 @@ namespace Tango.MachineStudio.UI.ViewModels
ConnectCommand = new RelayCommand(ConnectToMachine);
SignoutCommand = new RelayCommand(SignOut);
DisconnectCommand = new RelayCommand(DisconnectFromMachine, (x) => ApplicationManager.IsMachineConnected && !_isDisconnecting);
+ OpenModuleInWindowCommand = new RelayCommand<IStudioModule>(OpenModuleInWindow);
+ ExitCommand = new RelayCommand(ExitApplication);
+ UpdateCenterCommand = new RelayCommand(NavigateToUpdateCenter);
+
+ _updateCheckThread = new Thread(UpdateCheckThreadMethod);
+ _updateCheckThread.IsBackground = true;
+ _updateCheckThread.Start();
+ }
+
+ private void UpdateCheckThreadMethod()
+ {
+ while (!DisableCheckForUpdates)
+ {
+ Thread.Sleep(TimeSpan.FromMinutes(1));
+
+ try
+ {
+ if (_authenticationProvider.CurrentUser != null)
+ {
+ var service = UpdateServiceHelper.GetUpdateServiceChannel();
+ var client = service.CreateChannel();
+
+ CheckForUpdatesResponse response = client.CheckForUpdates(new CheckForUpdatesRequest()
+ {
+ Email = _authenticationProvider.CurrentUser.Email,
+ Password = _authenticationProvider.CurrentUser.Password,
+ Version = _applicationManager.Version,
+ });
+
+ IsUpdateAvailable = response.IsUpdateAvailable;
+ LatestVersion = response.Version;
+ }
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error in version update periodic check...");
+ }
+
+ Thread.Sleep(TimeSpan.FromMinutes(4));
+ }
}
/// <summary>
@@ -302,5 +398,62 @@ namespace Tango.MachineStudio.UI.ViewModels
{
base.OnViewAttached();
}
+
+ /// <summary>
+ /// Opens the module in a new window.
+ /// </summary>
+ /// <param name="module">The module.</param>
+ private void OpenModuleInWindow(IStudioModule module)
+ {
+ if (module == null) return;
+
+ try
+ {
+ StartModule(null);
+
+ module.InNewWindow = true;
+
+ var parent = (MainView.Self as MainView).TransitionControl.Controls.SingleOrDefault(x => x.Tag.ToString() == module.Name).Content as Grid;
+
+ var view = parent.Children[0] as FrameworkElement;
+ parent.Children.Remove(view);
+
+ ModuleWindowVM vm = new ModuleWindowVM(module, parent);
+ ModuleWindow window = new ModuleWindow(this, vm, view);
+
+ window.Closing += (x, y) =>
+ {
+ window.grid.Children.Remove(view);
+ parent.Children.Add(view);
+ module.InNewWindow = false;
+ };
+
+ window.Owner = MainWindow.Instance;
+ window.Show();
+
+ (_applicationManager as DefaultStudioApplicationManager).RegisterOpenedWindow(window);
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error popping out module " + module.Name);
+ _notificationProvider.ShowError("Error popping out module " + module.Name);
+ }
+ }
+
+ /// <summary>
+ /// Navigates to update center.
+ /// </summary>
+ private void NavigateToUpdateCenter()
+ {
+ _navigation.NavigateTo(NavigationView.UpdateView);
+ }
+
+ /// <summary>
+ /// Exits the application.
+ /// </summary>
+ private void ExitApplication()
+ {
+ _applicationManager.ShutDown();
+ }
}
}
diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/ModuleWindowVM.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/ModuleWindowVM.cs
new file mode 100644
index 000000000..a5b737b59
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/ModuleWindowVM.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Controls;
+using Tango.MachineStudio.Common;
+using Tango.SharedUI;
+
+namespace Tango.MachineStudio.UI.ViewModels
+{
+ public class ModuleWindowVM : ViewModel
+ {
+ private IStudioModule _module;
+
+ public IStudioModule Module
+ {
+ get { return _module; }
+ set { _module = value; RaisePropertyChangedAuto(); }
+ }
+
+ public Grid Parent { get; set; }
+
+ public ModuleWindowVM(IStudioModule module, Grid parent)
+ {
+ Parent = parent;
+ Module = module;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/UpdateViewVM.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/UpdateViewVM.cs
new file mode 100644
index 000000000..6be4ba4ca
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/UpdateViewVM.cs
@@ -0,0 +1,305 @@
+using FluentFTP;
+using Ionic.Zip;
+using Microsoft.Practices.ServiceLocation;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.ServiceModel;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Tango.Core.Commands;
+using Tango.Core.Helpers;
+using Tango.Logging;
+using Tango.MachineStudio.Common.Authentication;
+using Tango.MachineStudio.Common.Navigation;
+using Tango.MachineStudio.Common.Notifications;
+using Tango.MachineStudio.Common.StudioApplication;
+using Tango.MachineStudio.Common.Update;
+using Tango.SharedUI;
+
+namespace Tango.MachineStudio.UI.ViewModels
+{
+ public enum UpdateStatus
+ {
+ None,
+ CheckingForUpdate,
+ UpToDate,
+ UpdateAvailable,
+ Downloading,
+ Updating,
+ UpdateCompleted,
+ Error,
+ }
+
+ public class UpdateViewVM : ViewModel
+ {
+ private String _appPath = AppDomain.CurrentDomain.BaseDirectory;
+
+ private INotificationProvider _notification;
+ private INavigationManager _navigation;
+ private IStudioApplicationManager _application;
+ private IAuthenticationProvider _authentication;
+ private CheckForUpdatesResponse _updateInfo;
+ private String _newPackageTempFolder;
+
+ private UpdateStatus _status;
+ public UpdateStatus Status
+ {
+ get { return _status; }
+ set { _status = value; RaisePropertyChangedAuto(); }
+ }
+
+ private String _latestVersion;
+ public String LatestVersion
+ {
+ get { return _latestVersion; }
+ set { _latestVersion = value; RaisePropertyChangedAuto(); }
+ }
+
+ private double _downloadProgress;
+
+ public double DownloadProgress
+ {
+ get { return _downloadProgress; }
+ set { _downloadProgress = value; RaisePropertyChangedAuto(); }
+ }
+
+ private double _updateProgress;
+
+ public double UpdateProgress
+ {
+ get { return _updateProgress; }
+ set { _updateProgress = value; RaisePropertyChangedAuto(); }
+ }
+
+ private String _currentUpdateFile;
+
+ public String CurrentUpdateFile
+ {
+ get { return _currentUpdateFile; }
+ set { _currentUpdateFile = value; RaisePropertyChanged(nameof(CurrentUpdateFile)); }
+ }
+
+ public RelayCommand UpdateCommand { get; set; }
+
+ public RelayCommand BackCommand { get; set; }
+
+ public RelayCommand RestartCommand { get; set; }
+
+ public RelayCommand TryAgainCommand { get; set; }
+
+ public UpdateViewVM(INotificationProvider notification, IAuthenticationProvider authentication, INavigationManager navigation, IStudioApplicationManager application)
+ {
+ _notification = notification;
+ _navigation = navigation;
+ _application = application;
+ _authentication = authentication;
+
+ LatestVersion = "1.0.0.2";
+ Status = UpdateStatus.CheckingForUpdate;
+ UpdateCommand = new RelayCommand(StartUpdate, () => Status == UpdateStatus.UpdateAvailable);
+ BackCommand = new RelayCommand(BackToApplication, () => Status != UpdateStatus.Updating);
+ RestartCommand = new RelayCommand(RestartApplication, () => Status == UpdateStatus.UpdateCompleted);
+ TryAgainCommand = new RelayCommand(TryAgain, () => Status == UpdateStatus.Error);
+ }
+
+ public void OnNavigatedInto()
+ {
+ CheckForUpdates();
+ }
+
+ private void CheckForUpdates()
+ {
+ Status = UpdateStatus.CheckingForUpdate;
+
+ ChannelFactory<IMachineStudioUpdateService> service = null;
+
+ Task.Factory.StartNew(() =>
+ {
+ try
+ {
+ Thread.Sleep(2000);
+
+ service = UpdateServiceHelper.GetUpdateServiceChannel();
+ var client = service.CreateChannel();
+
+ CheckForUpdatesResponse response = client.CheckForUpdates(new CheckForUpdatesRequest()
+ {
+ Email = _authentication.CurrentUser.Email,
+ Password = _authentication.CurrentUser.Password,
+ Version = _application.Version,
+ });
+
+ if (response.IsUpdateAvailable)
+ {
+ _updateInfo = response;
+ Status = UpdateStatus.UpdateAvailable;
+ LatestVersion = response.Version;
+ }
+ else
+ {
+ Status = UpdateStatus.UpToDate;
+ }
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error while checking for version update!");
+ Status = UpdateStatus.Error;
+ }
+ finally
+ {
+ if (service != null)
+ {
+ service.Close();
+ }
+ }
+ });
+ }
+
+ private void BackToApplication()
+ {
+ if (Status == UpdateStatus.Downloading)
+ {
+ if (!_notification.ShowQuestion("This will abort all update operations. Are you sure?"))
+ {
+ return;
+ }
+ }
+
+ _navigation.NavigateTo(NavigationView.MainView);
+ Status = UpdateStatus.None;
+ }
+
+ private void StartUpdate()
+ {
+ DownloadProgress = 0;
+ UpdateProgress = 0;
+
+ Status = UpdateStatus.Downloading;
+
+ Task.Factory.StartNew(() =>
+ {
+ var tempFile = PathHelper.GetTempFilePath() + ".zip";
+
+ try
+ {
+ LogManager.Log("Creating temporary file " + tempFile);
+
+ int fileSize = 0;
+
+ using (FileStreamWrapper fs = new FileStreamWrapper(tempFile, FileMode.Create, (current) =>
+ {
+ InvokeUINow(() =>
+ {
+ Thread.Sleep(10);
+ DownloadProgress = ((double)current / (double)fileSize) * 100d;
+ });
+ }))
+ {
+ using (FtpClient ftp = new FtpClient(_updateInfo.FtpHost, _updateInfo.UserName, _updateInfo.Password))
+ {
+ LogManager.Log("Connecting to FTP site: " + _updateInfo.FtpHost);
+ ftp.ConnectAsync().Wait();
+ LogManager.Log("Retrieving download size...");
+ fileSize = (int)ftp.GetFileSize(_updateInfo.FilePath);
+ LogManager.Log("Download size: " + fileSize + " bytes.");
+ LogManager.Log("Starting download...");
+ ftp.DownloadAsync(fs, _updateInfo.FilePath).Wait();
+ }
+ }
+
+
+ Status = UpdateStatus.Updating;
+
+ _newPackageTempFolder = PathHelper.GetTempFolderPath();
+
+ using (ZipFile zip = ZipFile.Read(tempFile))
+ {
+ int currentEntry = 0;
+
+ zip.ExtractProgress += (x, args) =>
+ {
+ if (args.EventType == ZipProgressEventType.Extracting_AfterExtractEntry)
+ {
+ LogManager.Log("Extracting " + Path.GetFileName(args.CurrentEntry.FileName));
+ UpdateProgress = ((double)(currentEntry++) / (double)zip.Entries.Count) * 100d;
+ }
+ };
+
+ foreach (ZipEntry entry in zip)
+ {
+ Thread.Sleep(10);
+
+ string newPath = Path.Combine(_newPackageTempFolder, entry.FileName);
+
+ try
+ {
+ if (entry.IsDirectory)
+ {
+ Directory.CreateDirectory(newPath);
+ }
+ else
+ {
+ CurrentUpdateFile = Path.GetFileName(entry.FileName);
+ entry.Extract(_newPackageTempFolder, ExtractExistingFileAction.OverwriteSilently);
+ }
+ }
+ catch
+ {
+ LogManager.Log("Could not extract file " + entry.FileName);
+ }
+ }
+ }
+
+ ServiceLocator.Current.GetInstance<MainViewVM>().DisableCheckForUpdates = true;
+ Status = UpdateStatus.UpdateCompleted;
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error while extracting update package.");
+ Status = UpdateStatus.Error;
+ }
+ finally
+ {
+ PathHelper.TryDeleteFile(tempFile);
+ }
+ });
+ }
+
+ private void TryAgain()
+ {
+ CheckForUpdates();
+ }
+
+ private void RestartApplication()
+ {
+ try
+ {
+ Process p = new Process();
+ p.StartInfo.FileName = _appPath + "\\Tango.MachineStudio.Updater.exe";
+ p.StartInfo.UseShellExecute = true;
+ p.StartInfo.Arguments = _newPackageTempFolder;
+ p.Start();
+ }
+ catch (Exception ex)
+ {
+ if (ex.Message == "The operation was canceled by the user")
+ {
+ _notification.ShowWarning("It seems like you refused to invoke our update utility. This prevents Machine Studio from completing the update process!");
+ return;
+ }
+ }
+ Environment.Exit(0);
+ }
+
+ protected override void RaisePropertyChangedAuto([CallerMemberName] string caller = null)
+ {
+ base.RaisePropertyChangedAuto(caller);
+ InvalidateRelayCommands();
+ }
+ }
+}