using Microsoft.Win32; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Data; using Tango.BL; using Tango.BL.Builders; using Tango.BL.Calibration; using Tango.BL.Entities; using Tango.Core.Commands; using Tango.MachineStudio.Common; using Tango.MachineStudio.Common.Notifications; using Tango.MachineStudio.RML.Contracts; using Tango.MachineStudio.RML.Models; using Tango.MachineStudio.RML.Views; using Tango.PMR.ColorLab; using System.Data.Entity; using Tango.Core.ExtensionMethods; using Tango.MachineStudio.Common.Authentication; using Tango.BL.ActionLogs; using Tango.BL.DTO; using Tango.BL.Enumerations; using Google.Protobuf; using Tango.ColorConversion; using Tango.CSV; using Tango.Core; namespace Tango.MachineStudio.RML.ViewModels { public class MainViewVM : StudioViewModel { private INotificationProvider _notification; private IAuthenticationProvider _authentication; private IActionLogManager _actionLogManager; private RmlDTO _rmlBeforeSave; private ObservablesContext _active_context; #region Properties private List _rmls; public List Rmls { get { return _rmls; } set { _rmls = value; RaisePropertyChangedAuto(); } } private ObservableCollection _materials; public ObservableCollection Materials { get { return _materials; } set { _materials = value; RaisePropertyChangedAuto(); } } private ObservableCollection _purposes; public ObservableCollection Purposes { get { return _purposes; } set { _purposes = value; RaisePropertyChangedAuto(); } } private ObservableCollection _conditions; public ObservableCollection Conditions { get { return _conditions; } set { _conditions = value; RaisePropertyChangedAuto(); } } private ObservableCollection _linearMassDensityUnits; public ObservableCollection LinearMassDensityUnits { get { return _linearMassDensityUnits; } set { _linearMassDensityUnits = value; RaisePropertyChangedAuto(); } } private ObservableCollection _fiberShapes; public ObservableCollection FiberShapes { get { return _fiberShapes; } set { _fiberShapes = value; RaisePropertyChangedAuto(); } } private ObservableCollection _fiberSynths; public ObservableCollection FiberSynths { get { return _fiberSynths; } set { _fiberSynths = value; RaisePropertyChangedAuto(); } } private ObservableCollection _spoolTypes; public ObservableCollection SpoolTypes { get { return _spoolTypes; } set { _spoolTypes = value; RaisePropertyChangedAuto(); } } private ObservableCollection _btsrApplicationTypes; public ObservableCollection BtsrApplicationTypes { get { return _btsrApplicationTypes; } set { _btsrApplicationTypes = value; RaisePropertyChangedAuto(); } } private ObservableCollection _btsrYarnTypes; public ObservableCollection BtsrYarnTypes { get { return _btsrYarnTypes; } set { _btsrYarnTypes = value; RaisePropertyChangedAuto(); } } private RmlModel _selectedRML; public RmlModel SelectedRML { get { return _selectedRML; } set { _selectedRML = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); } } private Rml _activeRML; public Rml ActiveRML { get { return _activeRML; } set { _activeRML = value; RaisePropertyChangedAuto(); } } private CalibrationDataViewVM _calibrationDataViewVM; public CalibrationDataViewVM CalibrationDataViewVM { get { return _calibrationDataViewVM; } set { _calibrationDataViewVM = value; RaisePropertyChangedAuto(); } } private ObservableCollection _liquidTypesRmls; public ObservableCollection LiquidTypesRmls { get { return _liquidTypesRmls; } set { _liquidTypesRmls = value; RaisePropertyChangedAuto(); } } private ProcessParametersTablesGroup _activeProcessParametersGroup; public ProcessParametersTablesGroup ActiveProcessParametersGroup { get { return _activeProcessParametersGroup; } set { _activeProcessParametersGroup = value; RaisePropertyChangedAuto(); } } private ICollectionView _activeProcessParametersTableView; public ICollectionView ActiveProcessParametersTableView { get { return _activeProcessParametersTableView; } set { _activeProcessParametersTableView = value; RaisePropertyChangedAuto(); } } private ObservableCollection _ccts; public ObservableCollection CCTS { get { return _ccts; } set { _ccts = value; RaisePropertyChangedAuto(); } } private DataFileModel _selectedCCT; public DataFileModel SelectedCCT { get { return _selectedCCT; } set { _selectedCCT = value; RaisePropertyChangedAuto(); OnSelectedCCTChanged(); InvalidateRelayCommands(); } } private ObservableCollection _gbds; public ObservableCollection GBDS { get { return _gbds; } set { _gbds = value; RaisePropertyChangedAuto(); } } private DataFileModel _selectedGBD; public DataFileModel SelectedGBD { get { return _selectedGBD; } set { _selectedGBD = value; RaisePropertyChangedAuto(); OnSelectedGBDChanged(); InvalidateRelayCommands(); } } private ObservableCollection _lubs; public ObservableCollection LUBS { get { return _lubs; } set { _lubs = value; RaisePropertyChangedAuto(); } } private DataFileModel _selectedLUB; public DataFileModel SelectedLUB { get { return _selectedLUB; } set { _selectedLUB = value; RaisePropertyChangedAuto(); OnSelectedLUBChanged(); InvalidateRelayCommands(); } } private ColorConversionViewVM _colorConversionViewVM; public ColorConversionViewVM ColorConversionViewVM { get { return _colorConversionViewVM; } set { _colorConversionViewVM = value; RaisePropertyChangedAuto(); } } private RmlsSpool _selectedSpool; public RmlsSpool SelectedSpool { get { return _selectedSpool; } set { _selectedSpool = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); } } private ColorCalibrationViewVM _colorCalibrationVM; public ColorCalibrationViewVM ColorCalibrationVM { get { return _colorCalibrationVM; } set { _colorCalibrationVM = value; RaisePropertyChangedAuto(); } } private List _manufacturers; public List Manufacturers { get { return _manufacturers; } set { _manufacturers = value; RaisePropertyChangedAuto(); } } private String _RMLFilter; /// /// Gets or sets the job filter. /// public String RMLFilter { get { return _RMLFilter; } set { _RMLFilter = value; RaisePropertyChangedAuto(); OnRMLFilterChanged(); } } private bool _loadingRmls; public bool LoadingRmls { get { return _loadingRmls; } set { _loadingRmls = value; RaisePropertyChangedAuto(); } } #endregion #region Commands /// /// Gets or sets the manage RML command. /// public RelayCommand ManageRmlCommand { get; set; } /// /// Gets or sets the add RML command. /// public RelayCommand AddRmlCommand { get; set; } /// /// Gets or sets the remove RML command. /// public RelayCommand RemoveRmlCommand { get; set; } public RelayCommand ImportForwardDataCommand { get; set; } public RelayCommand ExportForwardDataCommand { get; set; } public RelayCommand ImportGBDCommand { get; set; } public RelayCommand ExportGBDCommand { get; set; } public RelayCommand ImportLUBCommand { get; set; } public RelayCommand ExportLUBCommand { get; set; } public RelayCommand AddProcessParametersTableCommand { get; set; } public RelayCommand RemoveProcessParametersTableCommand { get; set; } public RelayCommand AddLiquidFactorCommand { get; set; } public RelayCommand RemoveLiquidFactorCommand { get; set; } public RelayCommand CreateCalibrationDataExcelTemplateCommand { get; set; } /// /// Gets or sets the back to RMLS command. /// public RelayCommand BackToRmlsCommand { get; set; } public RelayCommand SaveCommand { get; set; } public RelayCommand CloneRmlCommand { get; set; } public RelayCommand ExportRMLFileCommand { get; set; } public RelayCommand ImportRMLFileCommand { get; set; } /// /// Gets or sets the add spool command. /// public RelayCommand AddSpoolCommand { get; set; } /// /// Gets or sets the remove spool command. /// public RelayCommand RemoveSpoolCommand { get; set; } public RelayCommand BatchConversionCommand { get; set; } public RelayCommand ActivatedInSitesCommand { get; set; } #endregion public MainViewVM(INotificationProvider notificationProvider, IAuthenticationProvider authentication, IActionLogManager actionLogManager) { _notification = notificationProvider; _authentication = authentication; _actionLogManager = actionLogManager; ManageRmlCommand = new RelayCommand(() => LoadActiveRML(SelectedRML.Guid), () => SelectedRML != null); RemoveRmlCommand = new RelayCommand(RemoveSelectedRml, () => SelectedRML != null); CloneRmlCommand = new RelayCommand(CloneSelectedRml, () => SelectedRML != null); AddRmlCommand = new RelayCommand(AddNewRml); BackToRmlsCommand = new RelayCommand(BackToRmls, () => IsFree); AddProcessParametersTableCommand = new RelayCommand(AddProcessParametersTable, () => IsFree); RemoveProcessParametersTableCommand = new RelayCommand(RemoveProcessParametersTable, () => IsFree); AddLiquidFactorCommand = new RelayCommand(AddLiquidFactor, () => IsFree); RemoveLiquidFactorCommand = new RelayCommand(RemoveLiquidFactor, () => IsFree); CreateCalibrationDataExcelTemplateCommand = new RelayCommand(CreateCalibrationDataExcelTemplate); SaveCommand = new RelayCommand(Save, () => IsFree); ActivatedInSitesCommand = new RelayCommand(ActivatedInSitesDialog, () => SelectedRML != null); ImportForwardDataCommand = new RelayCommand(ImportCCTData, () => ActiveRML != null && IsFree); ExportForwardDataCommand = new RelayCommand(ExportCCTData, () => ActiveRML != null && SelectedCCT != null && IsFree); ImportGBDCommand = new RelayCommand(ImportGBDData, () => ActiveRML != null && IsFree); ExportGBDCommand = new RelayCommand(ExportGBDData, () => ActiveRML != null && SelectedGBD != null && IsFree); ImportLUBCommand = new RelayCommand(ImportLUBData, () => ActiveRML != null && IsFree); ExportLUBCommand = new RelayCommand(ExportLUBData, () => ActiveRML != null && SelectedLUB != null && IsFree); ExportRMLFileCommand = new RelayCommand(ExportRmlFile, () => SelectedRML != null && IsFree); ImportRMLFileCommand = new RelayCommand(ImportRmlFile, () => IsFree); AddSpoolCommand = new RelayCommand(AddNewSpool); RemoveSpoolCommand = new RelayCommand(RemoveSpool, () => SelectedSpool != null); BatchConversionCommand = new RelayCommand(BatchConversion); } public override void OnApplicationReady() { } private async Task LoadRmls() { try { LoadingRmls = true; var filter = RMLFilter.ToStringOrEmpty().ToLower(); using (ObservablesContext db = ObservablesContext.CreateDefault()) { var rmls = await db.Rmls.Where(x => x.Name.ToLower().Contains(filter) || x.DisplayName.ToLower().Contains(filter)) .Include(x => x.Cct.FileName) .Include(x => x.LiquidTypesRmls) .Include(x => x.LiquidTypesRmls.Select(y => y.LiquidType)) .Include(x => x.BtsrApplicationType.Name) .Include(x => x.BtsrYarnType.Name) .Include(x => x.ProcessParametersTablesGroups) .Select(x => new { x.Name, x.Guid, x.DisplayName, x.Cct.FileName, x.ColorConversionVersion, x.UseColorLibGradients, x.UseLightInks, x.HeadType, x.LastUpdated, x.MachineType, BtsrApplicationType = x.BtsrApplicationType != null ? x.BtsrApplicationType.Name : String.Empty, BtsrYarnType = x.BtsrYarnType != null ? x.BtsrYarnType.Name : String.Empty, //LiquidTypesRmls = x.LiquidTypesRmls, //LiquidTypes = x.LiquidTypesRmls.Select(y => y.LiquidType), ProcessParametersTables = x.ProcessParametersTablesGroups }).ToListAsync(); List models = new List(); //var tables = ActiveRML.GetActiveProcessGroup().ProcessParametersTables; foreach (var rml in rmls.OrderBy(x => x.Name).ToList()) { ProcessParametersTable tableZone1 = null; ProcessParametersTable tableZone2 = null; if (rml.ProcessParametersTables != null) { var activeTablesGroup = rml.ProcessParametersTables.Where(x => x.Active).FirstOrDefault(); if (activeTablesGroup != null) { try { var tables = await db.ProcessParametersTables.Where(x => x.ProcessParametersTablesGroupGuid == activeTablesGroup.Guid).OrderBy(x => x.TableIndex).ToListAsync(); if (tables.Count > 0) { tableZone1 = tables[0]; } if (tables.Count > 1) { tableZone2 = tables[1]; } } catch (Exception ex) { LogManager.Log($"Error loading ProcessParametersTables {ex.Message}"); } }; } RmlModel model = new RmlModel(); model.Guid = rml.Guid; model.Name = rml.Name; model.LastUpdated = rml.LastUpdated; model.DisplayName = rml.DisplayName; model.CCT = rml.FileName + " v" + rml.ColorConversionVersion; model.UseGradients = rml.UseColorLibGradients; model.UseLightInks = rml.UseLightInks; model.HeadType = (HeadTypes)rml.HeadType; model.Btsr = (String.IsNullOrEmpty(rml.BtsrApplicationType) ? "N/A" : rml.BtsrApplicationType) + ", " + (String.IsNullOrEmpty(rml.BtsrYarnType) ? "N/A" : rml.BtsrYarnType); model.MachineType = (MachineTypes?)rml.MachineType; if (tableZone1 != null) { model.Zone1InkUptake = String.Format($"{tableZone1.MinInkUptake}-{tableZone1.MaxInkUptake}"); model.DyeingSpeed = tableZone1.DyeingSpeed.ToString(); } if (tableZone2 != null) { model.DyeingSpeed += String.Format($"-{tableZone2.DyeingSpeed}"); model.Zone2InkUptake = tableZone2 == null ? "-" : String.Format($"{tableZone2.MinInkUptake}-{tableZone2.MaxInkUptake}"); } //model.LiquidTypes = rml.LiquidTypes.OrderBy(x => x.Code).Select(x => x.Color).ToList(); //model.LiquidTypesR = rml.LiquidTypesRmls.OrderBy(x => x.LiquidType.Code).ToList().Select((n) => new RmlModel.LiquidTypeColorValue(){ Color = n.LiquidType.Color, LiquidTypeValue = n.MaxNlPerCm }).ToList(); models.Add(model); } Rmls = models; } } catch (Exception ex) { LogManager.Log(ex, "Error filtering rmls on RML module."); } finally { LoadingRmls = false; } } private async void LoadActiveRML(String guid) { using (_notification.PushTaskItem("Loading RML...")) { try { IsFree = false; if (_active_context != null) { _active_context.Dispose(); } _active_context = ObservablesContext.CreateDefault(); CCTS = _active_context.Ccts .Select(x => new DataFileModel() { Guid = x.Guid, FileName = x.FileName, }).ToObservableCollection(); CCTS.Where(x => String.IsNullOrWhiteSpace(x.FileName)).ToList().ForEach(x => x.FileName = x.Guid); GBDS = _active_context.Gbds .Select(x => new DataFileModel() { Guid = x.Guid, FileName = x.FileName, }).ToObservableCollection(); LUBS = _active_context.Lubs .Select(x => new DataFileModel() { Guid = x.Guid, FileName = x.FileName, }).ToObservableCollection(); LoadRmlProperties(); ActiveRML = await new RmlBuilder(_active_context) .Set(guid) .WithActiveParametersGroup() .WithLiquidFactors() .WithCCT() .WithGbdAndLub() .WithSpools() .BuildAsync(); InvalidateRelayCommands(); if (ActiveRML.ProcessParametersTablesGroups.ToList().Count == 0) { if (!_notification.ShowQuestion("Could not find any process group for the selected RML. Would you like to create one?")) { _notification.ShowError("Cannot load an RML with no process group."); IsFree = true; return; } else { ProcessParametersTablesGroup group = new ProcessParametersTablesGroup(); group.Name = "Active Group"; group.Active = true; group.ProcessParametersTables.Add(new ProcessParametersTable() { Name = "Process Table 1", }); group.Rml = ActiveRML; _active_context.ProcessParametersTablesGroups.Add(group); _active_context.ProcessParametersTables.Add(group.ProcessParametersTables[0]); await _active_context.SaveChangesAsync(); LoadActiveRML(ActiveRML.Guid); return; } } if (!String.IsNullOrEmpty(ActiveRML.Manufacturer) && false == Manufacturers.Any(x => x == ActiveRML.Manufacturer)) { _active_context.YarnManufacturers.Add(new YarnManufacturer() { Name = ActiveRML.Manufacturer }); await _active_context.SaveChangesAsync(); Manufacturers.Add(ActiveRML.Manufacturer); } ActiveProcessParametersGroup = ActiveRML.ProcessParametersTablesGroups.ToList().FirstOrDefault(); var tables= ActiveRML.ProcessParametersTablesGroups.ToList(); var zone1 = tables[0].ProcessParametersTables; /* * */ ActiveProcessParametersTableView = CollectionViewSource.GetDefaultView(ActiveProcessParametersGroup.ProcessParametersTables); ActiveProcessParametersTableView.SortDescriptions.Add(new SortDescription(nameof(ProcessParametersTable.TableIndex), ListSortDirection.Ascending)); CalibrationDataViewVM = new CalibrationDataViewVM(_notification); LiquidTypesRmls = ActiveRML.LiquidTypesRmls; foreach (var liquidTypeRml in LiquidTypesRmls) { CalibrationDataVM catVM = new CalibrationDataVM(liquidTypeRml.LiquidType); if (liquidTypeRml.DefaultCatData != null) { catVM.CalibrationPoints = liquidTypeRml.GetCalibrationData().CalibrationPoints.Select(x => new CalibrationDataPointVM(x.X, x.Y)).ToObservableCollection(); } CalibrationDataViewVM.LiquidsCalibrationData.Add(catVM); } ColorConversionViewVM = new ColorConversionViewVM(_notification) { RML = ActiveRML, CCT = SelectedCCT, GBD = SelectedGBD, LUB = SelectedLUB, LiquidsCalibrationData = CalibrationDataViewVM.LiquidsCalibrationData, LiquidTypesRmls = LiquidTypesRmls, }; if (ActiveRML.Cct != null) { _selectedCCT = CCTS.SingleOrDefault(x => x.Guid == ActiveRML.Cct.Guid); await OnSelectedCCTChanged(); RaisePropertyChanged(nameof(SelectedCCT)); } if (ActiveRML.Gbd != null) { _selectedGBD = GBDS.SingleOrDefault(x => x.Guid == ActiveRML.Gbd.Guid); await OnSelectedGBDChanged(); RaisePropertyChanged(nameof(SelectedGBD)); } if (ActiveRML.Lub != null) { _selectedLUB = LUBS.SingleOrDefault(x => x.Guid == ActiveRML.Lub.Guid); await OnSelectedLUBChanged(); RaisePropertyChanged(nameof(SelectedLUB)); } ColorCalibrationVM = new ColorCalibrationViewVM(_notification) { RML = ActiveRML, LiquidTypes = LiquidTypesRmls.Where(x => x.LiquidType.HasPigment).ToList().Select(y => y.LiquidType).ToList(), }; _rmlBeforeSave = RmlDTO.FromObservable(ActiveRML); View.NavigateTo(RmlNavigationView.RmlView); InvalidateRelayCommands(); IsFree = true; } catch (Exception ex) { LogManager.Log($"Error loading RML '{ActiveRML.Name}'..."); _notification.ShowError($"Error loading the selected thread.\n{ex.FlattenMessage()}"); } finally { IsFree = true; } } } private async Task OnSelectedCCTChanged() { if (ColorConversionViewVM != null && SelectedCCT != null && !SelectedCCT.IsNew) { using (_notification.PushTaskItem("Loading CCT data...")) { IsFree = false; var cct = await _active_context.Ccts.SingleOrDefaultAsync(x => x.Guid == SelectedCCT.Guid); if (cct != null) { SelectedCCT.Data = cct.Data; ColorConversionViewVM.CCT = SelectedCCT; } IsFree = true; } } } private async Task OnSelectedGBDChanged() { if (ColorConversionViewVM != null && SelectedGBD != null && !SelectedGBD.IsNew) { using (_notification.PushTaskItem("Loading GBD data...")) { IsFree = false; var gbd = await _active_context.Gbds.SingleOrDefaultAsync(x => x.Guid == SelectedGBD.Guid); if (gbd != null) { SelectedGBD.Data = gbd.Data; ColorConversionViewVM.GBD = SelectedGBD; } IsFree = true; } } } private async Task OnSelectedLUBChanged() { if (ColorConversionViewVM != null && SelectedLUB != null && !SelectedLUB.IsNew) { using (_notification.PushTaskItem("Loading LUB data...")) { IsFree = false; var lub = await _active_context.Lubs.SingleOrDefaultAsync(x => x.Guid == SelectedLUB.Guid); if (lub != null) { SelectedLUB.Data = lub.Data; ColorConversionViewVM.LUB = SelectedLUB; } IsFree = true; } } } private void LoadRmlProperties() { Materials = _active_context.MediaMaterials.ToObservableCollection(); Purposes = _active_context.MediaPurposes.ToObservableCollection(); Conditions = _active_context.MediaConditions.ToObservableCollection(); LinearMassDensityUnits = _active_context.LinearMassDensityUnits.ToObservableCollection(); FiberShapes = _active_context.FiberShapes.ToObservableCollection(); FiberSynths = _active_context.FiberSynths.ToObservableCollection(); SpoolTypes = _active_context.SpoolTypes.ToObservableCollection(); BtsrApplicationTypes = _active_context.BtsrApplicationTypes.ToObservableCollection(); BtsrYarnTypes = _active_context.BtsrYarnTypes.ToObservableCollection(); Manufacturers = _active_context.YarnManufacturers.Select(x => x.Name).ToList(); } private async void AddNewRml() { var name = _notification.ShowTextInput("Please enter RML name", "Name"); if (!String.IsNullOrWhiteSpace(name)) { using (ObservablesContext db = ObservablesContext.CreateDefault()) { if (await db.Rmls.AnyAsync(x => x.Name == name)) { _notification.ShowError("The specified RML name already exists. Please select a different name."); return; } } using (_notification.PushTaskItem("Creating new RML...")) { IsFree = false; if (_active_context != null) { _active_context.Dispose(); } _active_context = ObservablesContext.CreateDefault(); LoadRmlProperties(); Rml rml = new Rml(); rml.Name = name; rml.DisplayName = name; rml.QualificationDate = DateTime.UtcNow; rml.Manufacturer = "Twine"; rml.DefaultLiquidFactor = 140; using (ObservablesContext db = ObservablesContext.CreateDefault()) { int count = db.Rmls.Count(); if (count > 0) { rml.Code = (await db.Rmls.MaxAsync(x => x.Code)) + 1; } else { rml.Code = 1; } } rml.MediaMaterial = Materials.FirstOrDefault(); rml.MediaPurpose = Purposes.FirstOrDefault(); rml.MediaCondition = Conditions.FirstOrDefault(); rml.LinearMassDensityUnit = LinearMassDensityUnits.FirstOrDefault(); rml.FiberShape = FiberShapes.FirstOrDefault(); rml.FiberSynth = FiberSynths.FirstOrDefault(); ProcessParametersTablesGroup group = new ProcessParametersTablesGroup(); group.Name = "Active Group"; group.Active = true; group.ProcessParametersTables.Add(new ProcessParametersTable() { Name = "Process Table 1", }); group.Rml = rml; _active_context.ProcessParametersTablesGroups.Add(group); _active_context.ProcessParametersTables.Add(group.ProcessParametersTables[0]); _active_context.Rmls.Add(rml); await _active_context.SaveChangesAsync(); _actionLogManager.InsertLog(BL.Enumerations.ActionLogType.RmlCreated, _authentication.CurrentUser, rml.Name, rml, "Rml created using Machine Studio."); LoadActiveRML(rml.Guid); IsFree = true; } } } private async void RemoveSelectedRml() { if (_notification.ShowQuestion("Removing the selected thread will result in the loss of all related process parameters and default calibration data. Are you sure you want to delete the selected RML?")) { using (_notification.PushTaskItem("Removing RML...")) { try { using (ObservablesContext db = ObservablesContext.CreateDefault()) { IsFree = false; var selectedRml = await db.Rmls.FirstAsync(x => x.Guid == SelectedRML.Guid); var rml_jobs = await db.Jobs.Where(x => x.RmlGuid == SelectedRML.Guid).Include(x => x.Machine).OrderBy(x => x.Machine.SerialNumber).ToListAsync(); if (rml_jobs.Count > 0) { var vm = new RmlDeleteDialogViewVM(SelectedRML, Rmls.ToList(), rml_jobs.ToList()); _notification.ShowModalDialog(vm, (x) => { }, () => { }); if (!vm.DialogResult) { return; } //Perform actions... foreach (var jobAction in vm.JobsActions) { if (jobAction.Action == RmlDeleteDialogViewVM.RmlDeleteJobAction.Delete) { _actionLogManager.InsertLog(BL.Enumerations.ActionLogType.JobDeleted, _authentication.CurrentUser.Guid, jobAction.Job.Name, jobAction.Job.Guid, $"Job deleted due to RML '{SelectedRML.Name}' being removed."); await jobAction.Job.DeleteCascadeAsync(db); } else if (jobAction.Action == RmlDeleteDialogViewVM.RmlDeleteJobAction.Change) { var job = await db.Jobs.SingleOrDefaultAsync(x => x.Guid == jobAction.Job.Guid); job.RmlGuid = jobAction.TargetRml.Guid; _actionLogManager.InsertLog(BL.Enumerations.ActionLogType.JobSaved, _authentication.CurrentUser.Guid, jobAction.Job.Name, jobAction.Job.Guid, $"Job RML changed to '{jobAction.TargetRml.Name}' due to RML '{SelectedRML.Name}' being removed."); } } } await db.SaveChangesAsync(); await selectedRml.DeleteCascadeAsync(db); _actionLogManager.InsertLog(BL.Enumerations.ActionLogType.RmlDeleted, _authentication.CurrentUser, selectedRml.Name, selectedRml, "RML deleted from Machine Studio."); await LoadRmls(); } } catch (Exception ex) { LogManager.Log(ex, $"Error removing selected RML {SelectedRML?.Name}."); _notification.ShowError($"An error occurred while trying to remove the selected RML.\n{ex.FlattenMessage()}"); await LoadRmls(); } finally { IsFree = true; } } } } private async void CloneSelectedRml() { String name = _notification.ShowTextInput("Enter thread name", "thread name"); if (!String.IsNullOrWhiteSpace(name)) { using (_notification.PushTaskItem("Cloning thread...")) { try { IsFree = false; using (var context = ObservablesContext.CreateDefault()) { if (await context.Rmls.AnyAsync(x => x.Name == name)) { _notification.ShowError("The specified RML name already exists. Please select a different name."); IsFree = true; return; } var rml = await new RmlBuilder(context).Set(SelectedRML.Guid).WithActiveParametersGroup().WithLiquidFactors().WithSpools().BuildAsync(); Rml cloned = new Rml(); rml.MapPropertiesTo(cloned, MappingFlags.NoReferenceTypes); cloned.Code = (await context.Rmls.MaxAsync(x => x.Code)) + 1; cloned.Guid = Guid.NewGuid().ToString(); cloned.ID = 0; cloned.Name = name; cloned.DisplayName = name; cloned.RmlQualificationLevel = RmlQualifications.Provisional; cloned.QualificationDate = DateTime.UtcNow; ProcessParametersTablesGroup group = new ProcessParametersTablesGroup(); group.Name = rml.GetActiveProcessGroup().Name; group.Active = true; foreach (var p in rml.GetActiveProcessGroup().ProcessParametersTables) { var pc = new ProcessParametersTable(); p.MapPrimitivesTo(pc); pc.Name = p.Name; group.ProcessParametersTables.Add(pc); } cloned.ProcessParametersTablesGroups.Add(group); foreach (var liquidFactor in rml.LiquidTypesRmls) { LiquidTypesRml l = new LiquidTypesRml(); l.DefaultCatData = liquidFactor.DefaultCatData; l.LiquidType = liquidFactor.LiquidType; l.MaxNlPerCm = liquidFactor.MaxNlPerCm; cloned.LiquidTypesRmls.Add(l); } foreach (var spool in rml.RmlsSpools) { RmlsSpool s = new RmlsSpool(); spool.MapPropertiesTo(s, MappingFlags.ValueTypesOnly); s.RmlGuid = cloned.Guid; s.SpoolTypeGuid = spool.SpoolTypeGuid; cloned.RmlsSpools.Add(s); } context.Rmls.Add(cloned); await context.SaveChangesAsync(); _actionLogManager.InsertLog(BL.Enumerations.ActionLogType.RmlCreated, _authentication.CurrentUser, cloned.Name, cloned, "RML cloned from Machine Studio."); } await LoadRmls(); } catch (Exception ex) { LogManager.Log(ex, "Error cloning thread."); _notification.ShowError($"An error occurred while trying to clone the selected thread\n{ex.Message}"); } finally { IsFree = true; } } } } private void AddProcessParametersTable() { var name = _notification.ShowTextInput("Enter table name", "Name"); if (!String.IsNullOrWhiteSpace(name)) { _active_context.ProcessParametersTables.Add(new ProcessParametersTable() { ProcessParametersTablesGroup = ActiveProcessParametersGroup, Name = name, TableIndex = ActiveProcessParametersGroup.ProcessParametersTables.Max(x => x.TableIndex) + 1, }); } } public void OnProcessParametersTableDropped(ProcessParametersTable dragged, ProcessParametersTable dropped) { if (dragged.TableIndex > dropped.TableIndex) { dragged.TableIndex = dropped.TableIndex - 1; } else { dragged.TableIndex = dropped.TableIndex + 1; } int index = 0; foreach (var table in ActiveProcessParametersGroup.ProcessParametersTables.OrderBy(x => x.TableIndex)) { table.TableIndex = index++; } ActiveProcessParametersTableView.Refresh(); } private async void OnRMLFilterChanged() { await LoadRmls(); } private void RemoveLiquidFactor(LiquidTypesRml liquidFactor) { if (_notification.ShowQuestion("Removing this liquid factor will remove the liquid type association with the RML and will drop the calibration data. Are you sure?")) { var catVM = CalibrationDataViewVM.LiquidsCalibrationData.SingleOrDefault(x => x.LiquidType == liquidFactor.LiquidType); CalibrationDataViewVM.LiquidsCalibrationData.Remove(catVM); _active_context.LiquidTypesRmls.Remove(liquidFactor); } } private void AddLiquidFactor() { AddLiquidFactorViewVM vm = new AddLiquidFactorViewVM(_active_context); _notification.ShowModalDialog(vm, (_) => { if (LiquidTypesRmls.ToList().Exists(x => x.LiquidType == vm.SelectedLiquidType)) { _notification.ShowError("The selected liquid type is already associated with this RML."); return; } LiquidTypesRml liquidFactor = new LiquidTypesRml() { LiquidType = vm.SelectedLiquidType, Rml = ActiveRML, }; _active_context.LiquidTypesRmls.Add(liquidFactor); CalibrationDataVM catVM = new CalibrationDataVM(liquidFactor.LiquidType); CalibrationDataViewVM.LiquidsCalibrationData.Add(catVM); }, () => { }); } private void RemoveProcessParametersTable(ProcessParametersTable processParametersTable) { if (ActiveProcessParametersGroup.ProcessParametersTables.Count == 1) { _notification.ShowError("The process group must contain at least one table."); return; } if (_notification.ShowQuestion("Are you sure you want to remove this process parameters table?")) { _active_context.ProcessParametersTables.Remove(processParametersTable); } } private void CreateCalibrationDataExcelTemplate() { SaveFileDialog dlg = new SaveFileDialog(); try { dlg.Title = $"Create excel template file"; dlg.Filter = "Excel Files|*.xlsx"; dlg.DefaultExt = ".xlsx"; dlg.FileName = "Calibration File Template"; if (dlg.ShowDialog().Value) { CalibrationHelper.CreateCalibrationDataExcelTemplate(dlg.FileName); } } catch (Exception ex) { LogManager.Log(ex, "Error generating excel calibration template file " + dlg.FileName); _notification.ShowError("An error occurred while trying to generate the calibration file."); } } private async void Save() { IsFree = false; try { using (_notification.PushTaskItem("Saving RML...")) { foreach (var calDataVM in CalibrationDataViewVM.LiquidsCalibrationData) { var liquidTypeRml = LiquidTypesRmls.SingleOrDefault(x => x.LiquidType == calDataVM.LiquidType); CalibrationData calData = new CalibrationData(); calData.LiquidType = (PMR.ColorLab.LiquidType)liquidTypeRml.LiquidType.Code; calData.CalibrationPoints.AddRange(calDataVM.CalibrationPoints.Select(x => new CalibrationPoint() { X = x.X, Y = x.Y })); liquidTypeRml.PutCalibrationData(calData); } ActiveRML.LastUpdated = DateTime.UtcNow; if (_rmlBeforeSave.QualificationLevel != ActiveRML.QualificationLevel) { ActiveRML.QualificationDate = DateTime.UtcNow; } if (SelectedCCT != null) { if (SelectedCCT.IsNew) { Cct cct = new Cct(); cct.Guid = SelectedCCT.Guid; cct.FileName = SelectedCCT.FileName; cct.Data = SelectedCCT.Data; ActiveRML.Cct = cct; SelectedCCT.IsNew = false; } else { ActiveRML.CctGuid = SelectedCCT.Guid; } } if (SelectedGBD != null) { if (SelectedGBD.IsNew) { Gbd gbd = new Gbd(); gbd.Guid = SelectedGBD.Guid; gbd.FileName = SelectedGBD.FileName; gbd.Data = SelectedGBD.Data; ActiveRML.Gbd = gbd; SelectedGBD.IsNew = false; } else { ActiveRML.GbdGuid = SelectedGBD.Guid; } } if (SelectedLUB != null) { if (SelectedLUB.IsNew) { Lub lub = new Lub(); lub.Guid = SelectedLUB.Guid; lub.FileName = SelectedLUB.FileName; lub.Data = SelectedLUB.Data; ActiveRML.Lub = lub; SelectedLUB.IsNew = false; } else { ActiveRML.LubGuid = SelectedLUB.Guid; } } var rmlAfter = RmlDTO.FromObservable(ActiveRML); await _active_context.SaveChangesAsync(); _actionLogManager.InsertLog(BL.Enumerations.ActionLogType.RmlSaved, _authentication.CurrentUser, _rmlBeforeSave.Name, _rmlBeforeSave, rmlAfter, "RML saved using Machine Studio."); _rmlBeforeSave = rmlAfter; LoadActiveRML(ActiveRML.Guid); } } catch (Exception ex) { LogManager.Log(ex, $"Error saving RML {ActiveRML.Name}"); _notification.ShowError($"An error occurred while trying to save the current RML.\n{ex.FlattenMessage()}"); } finally { IsFree = true; } } private async void ActivatedInSitesDialog() { if(SelectedRML == null) return; try { using (ObservablesContext db = ObservablesContext.CreateDefault()) { IsFree = false; var selSites = await db.SitesRmls.OrderBy(x => x.ID).Where(y => y.RmlGuid == SelectedRML.Guid).Include(x=>x.Site).Select(x => x.Site.Name).ToListAsync(); var vm = new RmlActiveSitesDialogVM(selSites, SelectedRML.Name); _notification.ShowModalDialog(vm, (x) => { }, () => { }); if (!vm.DialogResult) { return; } } } catch (Exception ex) { LogManager.Log(ex, $"Error display Activated In Sites selected RML {SelectedRML?.Name}."); } finally { IsFree = true; } } private async void BackToRmls() { View.NavigateTo(RmlNavigationView.RmlsView); await LoadRmls(); } #region Batch Conversion private void BatchConversion() { OpenFileDialog dlg = new OpenFileDialog(); dlg.Title = "Select CSV file with LAB data"; dlg.Filter = "CSV Files|*.csv"; if (!dlg.ShowDialogCenter()) { return; } String fileName = dlg.FileName; try { ConversionInput input = new ConversionInput(); input.ColorSpace = PMR.ColorLab.ColorSpace.Lab; input.ForwardData = ByteString.CopyFrom(SelectedCCT.Data); input.InputCoordinates = new InputCoordinates(); input.ThreadL = ActiveRML.WhitePointL; input.ThreadA = ActiveRML.WhitePointA; input.ThreadB = ActiveRML.WhitePointB; input.UseLightInks = ActiveRML.UseLightInks; input.VMax = ActiveRML.VMax; if (SelectedGBD != null) { input.GbdData = ByteString.CopyFrom(SelectedGBD.Data); } if (SelectedLUB != null) { input.LubData = ByteString.CopyFrom(SelectedLUB.Data); } input.UseLubricantTransform = ActiveRML.UseLubricantTransform; //Validate calibration data foreach (var vm in CalibrationDataViewVM.LiquidsCalibrationData.Where(x => x.LiquidType.HasPigment)) { if (vm.CalibrationPoints.Count == 0) { InvokeUI(() => { _notification.ShowError($"No calibration data for liquid '{vm.LiquidType.Name}'. Could not convert source color."); }); return; } else if (!(vm.CalibrationPoints.First().X == 0 && vm.CalibrationPoints.First().Y == 0 && vm.CalibrationPoints.Last().X >= 100 && vm.CalibrationPoints.Last().Y >= 100)) { InvokeUI(() => { _notification.ShowError($"Invalid calibration data for liquid '{vm.LiquidType.Name}'. Could not convert source color."); }); return; } } foreach (var vm in CalibrationDataViewVM.LiquidsCalibrationData) { InputLiquid inputLiquid = new InputLiquid(); CalibrationData calData = new CalibrationData(); calData.LiquidType = (PMR.ColorLab.LiquidType)vm.LiquidType.Code; calData.CalibrationPoints.AddRange(vm.CalibrationPoints.Select(x => new CalibrationPoint() { X = x.X, Y = x.Y })); inputLiquid.CalibrationData = calData; inputLiquid.LiquidType = (PMR.ColorLab.LiquidType)vm.LiquidType.Code; inputLiquid.MaxNanoliterPerCentimeter = LiquidTypesRmls.SingleOrDefault(x => x.LiquidType.Code == vm.LiquidType.Code).MaxNlPerCm; input.InputCoordinates.InputLiquids.Add(inputLiquid); } foreach (var process in ActiveRML.GetActiveProcessGroup().ProcessParametersTables) { input.ProcessRanges.Add(new ProcessRange() { MinInkUptake = process.MinInkUptake, MaxInkUptake = process.MaxInkUptake, }); } input.GenerateHive = false; IColorConverter converter = new DefaultColorConverter(); List labList = CsvFile.Read(new CsvSource(fileName)).ToList(); List resultsList = new List(); using (_notification.PushTaskItem("Converting...")) { foreach (var lab in labList) { input.InputCoordinates.L = lab.L; input.InputCoordinates.A = lab.A; input.InputCoordinates.B = lab.B; input.ColorSpace = PMR.ColorLab.ColorSpace.Lab; var output = converter.Convert(input, ActiveRML.ColorConversionVersion); BatchConversionCsvModelOut result = new BatchConversionCsvModelOut(); result.Index = lab.Index; result.L = lab.L; result.A = lab.A; result.B = lab.B; result.SuggestionL = output.CreateSingleSuggestion().Coordinates.L; result.SuggestionA = output.CreateSingleSuggestion().Coordinates.A; result.SuggestionB = output.CreateSingleSuggestion().Coordinates.B; var cyanVolume = output.CreateSingleSuggestion().Coordinates.OutputLiquids.FirstOrDefault(x => x.LiquidType == PMR.ColorLab.LiquidType.Cyan); if (cyanVolume != null) { result.Cyan = cyanVolume.Volume; } var magentaVolume = output.CreateSingleSuggestion().Coordinates.OutputLiquids.FirstOrDefault(x => x.LiquidType == PMR.ColorLab.LiquidType.Magenta); if (magentaVolume != null) { result.Magenta = magentaVolume.Volume; } var yellowVolume = output.CreateSingleSuggestion().Coordinates.OutputLiquids.FirstOrDefault(x => x.LiquidType == PMR.ColorLab.LiquidType.Yellow); if (yellowVolume != null) { result.Yellow = yellowVolume.Volume; } var blackVolume = output.CreateSingleSuggestion().Coordinates.OutputLiquids.FirstOrDefault(x => x.LiquidType == PMR.ColorLab.LiquidType.Black); if (blackVolume != null) { result.Black = blackVolume.Volume; } var lightCyanVolume = output.CreateSingleSuggestion().Coordinates.OutputLiquids.FirstOrDefault(x => x.LiquidType == PMR.ColorLab.LiquidType.LightCyan); if (lightCyanVolume != null) { result.LightCyan = lightCyanVolume.Volume; } var lightMagentaVolume = output.CreateSingleSuggestion().Coordinates.OutputLiquids.FirstOrDefault(x => x.LiquidType == PMR.ColorLab.LiquidType.LightMagenta); if (lightMagentaVolume != null) { result.LightMagenta = lightMagentaVolume.Volume; } var lightYellowVolume = output.CreateSingleSuggestion().Coordinates.OutputLiquids.FirstOrDefault(x => x.LiquidType == PMR.ColorLab.LiquidType.LightYellow); if (lightYellowVolume != null) { result.LightYellow = lightYellowVolume.Volume; } foreach (var item in input.InputCoordinates.InputLiquids) { switch (item.LiquidType) { case PMR.ColorLab.LiquidType.Cyan: item.Volume = result.Cyan; break; case PMR.ColorLab.LiquidType.Magenta: item.Volume = result.Magenta; break; case PMR.ColorLab.LiquidType.Yellow: item.Volume = result.Yellow; break; case PMR.ColorLab.LiquidType.Black: item.Volume = result.Black; break; case PMR.ColorLab.LiquidType.Transparent: break; case PMR.ColorLab.LiquidType.Lubricant: break; case PMR.ColorLab.LiquidType.Cleaner: break; case PMR.ColorLab.LiquidType.LightCyan: item.Volume = result.LightCyan; break; case PMR.ColorLab.LiquidType.LightMagenta: item.Volume = result.LightMagenta; break; case PMR.ColorLab.LiquidType.LightYellow: item.Volume = result.LightYellow; break; default: break; } } result.OutOfGamut = output.OutOfGamut; input.ColorSpace = PMR.ColorLab.ColorSpace.Volume; output = converter.Convert(input, ActiveRML.ColorConversionVersion); result.OutputL = output.CreateSingleSuggestion().Coordinates.L; result.OutputA = output.CreateSingleSuggestion().Coordinates.A; result.OutputB = output.CreateSingleSuggestion().Coordinates.B; result.SuggestionDeltaE = BatchConversionCsvModelOut.MirtaDeltaE(result.L, result.A, result.B, result.SuggestionL, result.SuggestionA, result.SuggestionB); result.OutputDeltaE = BatchConversionCsvModelOut.MirtaDeltaE(result.L, result.A, result.B, result.OutputL, result.OutputA, result.OutputB); resultsList.Add(result); } } SaveFileDialog dlgOut = new SaveFileDialog(); dlgOut.Title = "Select results CSV file"; dlgOut.Filter = "CSV Files|*.csv"; dlgOut.FileName = Path.GetFileNameWithoutExtension(fileName) + " - Results"; dlgOut.DefaultExt = ".csv"; if (!dlgOut.ShowDialogCenter()) { return; } using (CsvFile outFile = new CsvFile(new CsvDestination(dlgOut.FileName))) { foreach (var result in resultsList) { outFile.Append(result); } } } catch (Exception ex) { _notification.ShowError($"Error converting the selected file. Please check all data is valid.\n{ex.FlattenMessage()}"); } _notification.ShowInfo("Batch Conversion Completed."); } #endregion #region Import / Export Color Conversion Data private void ImportCCTData() { String file = GetDataFileOpen("Select color adjustment file", "Color Conversion Table|*.cct"); if (file != null) { if (CCTS.ToList().Exists(x => x.FileName == Path.GetFileName(file))) { _notification.ShowError("The selected CCT file already exists on the database. Please select the CCT file from the dropdown box."); return; } DataFileModel cctModel = new DataFileModel(); cctModel.Guid = Guid.NewGuid().ToString(); cctModel.IsNew = true; cctModel.FileName = Path.GetFileName(file); cctModel.Data = File.ReadAllBytes(file); CCTS.Insert(0, cctModel); SelectedCCT = cctModel; ColorConversionViewVM.CCT = SelectedCCT; } } private void ExportCCTData() { if (SelectedCCT != null) { String file = GetDataFileSave("Select color adjustment file", "Color Conversion Table|*.cct", ActiveRML.Cct.FileName); if (file != null) { using (_notification.PushTaskItem("Exporting CCT file...")) { try { IsFree = false; if (SelectedCCT.IsNew) { File.WriteAllBytes(file, SelectedCCT.Data); } else { var cct = _active_context.Ccts.SingleOrDefault(x => x.Guid == SelectedCCT.Guid); if (cct != null) { File.WriteAllBytes(file, cct.Data); } } } catch (Exception ex) { LogManager.Log(ex, "Error exporting CCT file."); _notification.ShowError($"An error occurred while trying to export the CCT file.\n{ex.Message}"); } finally { IsFree = true; } } } } } private void ExportLUBData() { if (SelectedLUB != null) { String file = GetDataFileSave("Select lubrication transformation file", "Lubrication Transformation File|*.lub", ActiveRML.Lub.FileName); if (file != null) { using (_notification.PushTaskItem("Exporting LUB file...")) { try { IsFree = false; if (SelectedLUB.IsNew) { File.WriteAllBytes(file, SelectedLUB.Data); } else { var lub = _active_context.Lubs.SingleOrDefault(x => x.Guid == SelectedLUB.Guid); if (lub != null) { File.WriteAllBytes(file, lub.Data); } } } catch (Exception ex) { LogManager.Log(ex, "Error exporting LUB file."); _notification.ShowError($"An error occurred while trying to export the LUB file.\n{ex.Message}"); } finally { IsFree = true; } } } } } private void ImportLUBData() { String file = GetDataFileOpen("Select lubrication transformation file", "Lubrication Transformation File|*.lub"); if (file != null) { if (LUBS.ToList().Exists(x => x.FileName == Path.GetFileName(file))) { _notification.ShowError("The selected LUB file already exists on the database. Please select the LUB file from the dropdown box."); return; } DataFileModel lubModel = new DataFileModel(); lubModel.Guid = Guid.NewGuid().ToString(); lubModel.IsNew = true; lubModel.FileName = Path.GetFileName(file); lubModel.Data = File.ReadAllBytes(file); LUBS.Insert(0, lubModel); SelectedLUB = lubModel; ColorConversionViewVM.LUB = SelectedLUB; } } private void ExportGBDData() { if (SelectedGBD != null) { String file = GetDataFileSave("Select gamut boundary descriptor file", "Gamut Boundary Descriptor File|*.gbd", ActiveRML.Gbd.FileName); if (file != null) { using (_notification.PushTaskItem("Exporting GBD file...")) { try { IsFree = false; if (SelectedGBD.IsNew) { File.WriteAllBytes(file, SelectedGBD.Data); } else { var gbd = _active_context.Gbds.SingleOrDefault(x => x.Guid == SelectedGBD.Guid); if (gbd != null) { File.WriteAllBytes(file, gbd.Data); } } } catch (Exception ex) { LogManager.Log(ex, "Error exporting GBD file."); _notification.ShowError($"An error occurred while trying to export the GBD file.\n{ex.Message}"); } finally { IsFree = true; } } } } } private void ImportGBDData() { String file = GetDataFileOpen("Select gamut boundary description file", "Gamut Boundary Description File|*.gbd"); if (file != null) { if (GBDS.ToList().Exists(x => x.FileName == Path.GetFileName(file))) { _notification.ShowError("The selected GBD file already exists on the database. Please select the GBD file from the dropdown box."); return; } DataFileModel gbdModel = new DataFileModel(); gbdModel.Guid = Guid.NewGuid().ToString(); gbdModel.IsNew = true; gbdModel.FileName = Path.GetFileName(file); gbdModel.Data = File.ReadAllBytes(file); GBDS.Insert(0, gbdModel); SelectedGBD = gbdModel; ColorConversionViewVM.GBD = SelectedGBD; } } private String GetDataFileOpen(String title, String filter) { OpenFileDialog dlg = new OpenFileDialog(); dlg.Title = title; dlg.Filter = filter; if (dlg.ShowDialogCenter()) { return dlg.FileName; } return null; } private String GetDataFileSave(String title, String filter, String fileName) { SaveFileDialog dlg = new SaveFileDialog(); dlg.Title = title; dlg.Filter = filter; dlg.FileName = fileName; dlg.DefaultExt = ".cct"; if (dlg.ShowDialogCenter()) { return dlg.FileName; } return null; } #endregion #region RML Import / Export private async void ImportRmlFile() { OpenFileDialog dlg = new OpenFileDialog(); dlg.Title = "Import Thread Files"; dlg.Filter = "Twine Thread Files|*.rml"; dlg.Multiselect = true; if (dlg.ShowDialog().Value) { using (_notification.PushTaskItem($"Importing thread files...")) { try { IsFree = false; LogManager.Log($"Importing thread files..."); using (ObservablesContext db = ObservablesContext.CreateDefault()) { foreach (var file in dlg.FileNames) { var json = File.ReadAllText(file); var rmlFile = await Rml.FromRmlFile(db, json); db.Rmls.Add(rmlFile); if (rmlFile.RmlsExtensions != null && rmlFile.RmlsExtensions.Count > 0) { db.RmlsExtensions.Add(rmlFile.RmlsExtensions.FirstOrDefault()); } _actionLogManager.InsertLog(BL.Enumerations.ActionLogType.RmlImported, _authentication.CurrentUser, rmlFile.Name, rmlFile, "RML imported from Machine Studio."); } await db.SaveChangesAsync(); } IsFree = true; _notification.ShowInfo($"Threads imported successfully."); LoadRmls(); } catch (Exception ex) { LogManager.Log(ex, "Error importing thread file."); _notification.ShowError($"An error occurred while trying to import the selected thread file.\n{ex.FlattenMessage()}"); } finally { IsFree = true; } } } } private async void ExportRmlFile() { SaveFileDialog dlg = new SaveFileDialog(); dlg.Title = "Export Thread File"; dlg.Filter = "Twine Thread Files|*.rml"; dlg.DefaultExt = ".rml"; dlg.FileName = SelectedRML.Name; if (dlg.ShowDialog().Value) { using (_notification.PushTaskItem($"Exporting Thread '{SelectedRML.Name}'...")) { try { LogManager.Log($"Exporting Thread file {SelectedRML.Name}"); using (ObservablesContext db = ObservablesContext.CreateDefault()) { var rml = await db.Rmls.FirstAsync(x => x.Guid == SelectedRML.Guid); var rmlJsonFile = await rml.ToRmlFile(db); File.WriteAllText(dlg.FileName, rmlJsonFile); } } catch (Exception ex) { LogManager.Log(ex, "Error exporting Thread file."); _notification.ShowError($"An error occurred while trying to export thread '{SelectedRML.Name}'.\n{ex.FlattenMessage()}"); } } } } #endregion #region Spools private void AddNewSpool() { _active_context.RmlsSpools.Add(new RmlsSpool() { Rml = ActiveRML, }); } private void RemoveSpool() { if (SelectedSpool != null) { _active_context.RmlsSpools.Remove(SelectedSpool); ActiveRML.RmlsSpools.Remove(SelectedSpool); } } #endregion } }