livia-test/Livia/ViewModels/SelectReportModuleWindowViewModel.cs
2025-03-28 14:31:53 +08:00

227 lines
8.4 KiB
C#

using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Windows;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
using Livia.Models;
using Livia.Models.Data;
using Livia.Properties;
using Livia.Utility;
using Livia.ViewModels.Utility;
using Livia.Views.Utility;
using Microsoft.Extensions.Logging;
namespace Livia.ViewModels;
public class ReportModuleItemViewModel : ObservableObject, ISelectableItem
{
public bool IsChecked { get => _isChecked; set => SetProperty(ref _isChecked, value); }
public string Name { get; }
public object Value { get; }
private bool _isChecked = true;
public ReportModuleItemViewModel(string name, object value, bool isChecked = true)
{
Name = name;
Value = value;
IsChecked = isChecked;
}
}
public class ReportModuleExpanderViewModel : ObservableObject
{
public string Name { get; }
public string Type { get; }
public bool Visible => ModuleItemCollection.Items.Count > 0;
public SelectableObservableCollection<ReportModuleItemViewModel> ModuleItemCollection { get; } = new();
public ReportModuleExpanderViewModel(string name, string type, IEnumerable<ReportModuleItemViewModel> list)
{
Name = name;
Type = type;
ModuleItemCollection.AddRange(list);
}
}
public class SelectReportModuleWindowViewModel : ObservableObject, IDisposable, IRecipient<LogoutMessage>, IRecipient<IdleTimerTickMessage>
{
public event EventHandler? OnRequestClose;
public static string DefaultReportName => Application.Current.TryFindResource("DefaultReportName") as string ?? "Report1";
public bool Processing { get => _processing; private set => SetProperty(ref _processing, value); }
public bool ReportModuleAal { get => _reportModuleAal; set => SetProperty(ref _reportModuleAal, value); }
public bool ShowRoiLocation { get => _showRoiLocation; set => SetProperty(ref _showRoiLocation, value); }
public string ReportName { get => _reportName; set => SetProperty(ref _reportName, value); }
public string Language { get => _language; set => SetProperty(ref _language, value); }
public ObservableCollection<ReportModuleExpanderViewModel> ModuleGroups { get; } = [];
public IPatientInfoManager PatientInfoManager { get; }
private readonly IDataBlockLoader _dataBlockLoader;
private readonly IServerHandler _serverHandler;
private readonly IWarningSystem _warningSystem;
private readonly ILogger _logger;
private readonly CancellationTokenSource _cancellationTokenSource = new();
private bool _processing;
private bool _reportModuleAal = true;
private bool _showRoiLocation = true;
private string _reportName;
private string _language;
public SelectReportModuleWindowViewModel(ILiviaControlViewModel liviaControlViewModel, IServerHandler serverHandler, IWarningSystem warningSystem, IPatientInfoManager patientInfoManager, ILogger logger, IDataBlockLoader blockLoader)
{
_serverHandler = serverHandler;
_warningSystem = warningSystem;
PatientInfoManager = patientInfoManager;
_logger = logger;
_dataBlockLoader = blockLoader;
_reportName = DefaultReportName;
List<ReportModuleExpanderViewModel> viewModels = liviaControlViewModel.GenerateReportModuleGroups();
foreach (ReportModuleExpanderViewModel reportModuleExpanderViewModel in viewModels)
{
ModuleGroups.Add(reportModuleExpanderViewModel);
}
_language = Settings.Default.Language;
WeakReferenceMessenger.Default.RegisterAll(this);
}
private SelectReportModuleJson GenerateJson(bool overrideSameName)
{
ReportModules reportModules = new()
{
BrainRoi = true,
ShowRoiLocation = ShowRoiLocation,
ReportModuleAal = Settings.Default.ShowReportModuleAalCheckbox && ReportModuleAal,
RegionalPerfusion = [],
ParamColorImg = [],
Cbf = [],
Att = [],
Acbv = [],
AnteriorAspects = [],
PosteriorAspects = [],
RestrictedDiffusion = []
};
//TODO::is this good approach?
foreach (ReportModuleExpanderViewModel viewModel in ModuleGroups)
{
List<object> selectedItems = (from reportModuleItemViewModel in viewModel.ModuleItemCollection.Items where reportModuleItemViewModel.IsChecked select reportModuleItemViewModel.Value).ToList();
switch (viewModel.Type)
{
case "regional_perfusion":
reportModules.RegionalPerfusion.AddRange(selectedItems);
break;
case "param_color_img":
reportModules.ParamColorImg.AddRange(selectedItems);
break;
case "cbf":
reportModules.Cbf.AddRange(selectedItems);
break;
case "att":
reportModules.Att.AddRange(selectedItems);
break;
case "acbv":
reportModules.Acbv.AddRange(selectedItems);
break;
case "anterior_aspects":
reportModules.AnteriorAspects.AddRange(selectedItems);
break;
case "posterior_aspects":
reportModules.PosteriorAspects.AddRange(selectedItems);
break;
case "restricted_diffusion":
reportModules.RestrictedDiffusion.AddRange(selectedItems);
break;
default:
_logger.LogError("Unknown Report Module type {type}", viewModel.Type);
break;
}
}
SelectReportModuleJson json = new()
{
Anonymous = PatientInfoManager.AnonymousMode,
Key = _dataBlockLoader.CurrentDisplayingDataBlock?.Key ?? "",
Language = LiviaUtility.GetLanguageOnlyString(Language),
Title = ReportName,
Override = overrideSameName,
DisplayModules = reportModules
};
return json;
}
public bool CheckReportNameValid()
{
if (ReportName.Length is not (0 or > 20) && ReportName.IndexOfAny(Path.GetInvalidFileNameChars()) == -1)
return true;
_warningSystem.ShowDialog(WarningWindowKind.Warning, true, "ReportNameWarning");
return false;
}
public async Task<bool> SelectReportModule(string fileName)
{
Processing = true;
bool overrideSameName = !Settings.Default.ShowSelectReportModuleDialog;
while (true)
{
(bool success, string messageIndex) = await _serverHandler.SelectReportModule(fileName, GenerateJson(overrideSameName), _cancellationTokenSource.Token).ConfigureAwait(false);
if (success)
{
_warningSystem.ShowDialog(WarningWindowKind.Info, true, messageIndex);
if (!Settings.Default.OpenReportOnFinish)
return true;
try
{
Process.Start("explorer.exe", fileName);
}
catch (Exception e)
{
_logger.LogError(e, "Error opening {path}", fileName);
}
}
else if (messageIndex == "ServerError10035")
{
bool confirm = _warningSystem.ShowDialog(WarningWindowKind.Confirmation, true, messageIndex) ?? false;
if (confirm)
{
overrideSameName = true;
continue;
}
}
else if (_cancellationTokenSource.Token.IsCancellationRequested)
{
_logger.LogInformation("SelectReportModule canceled");
}
else
{
_warningSystem.ShowDialog(WarningWindowKind.Warning, false, messageIndex);
}
Processing = false;
return success;
}
}
public void Receive(LogoutMessage message)
{
//TODO::not sure if it is safe
if (!Processing)
OnRequestClose?.Invoke(this, EventArgs.Empty);
}
public void Receive(IdleTimerTickMessage message)
{
if (Processing)
message.IdleTimer.ResetTimer();
}
public void Dispose()
{
WeakReferenceMessenger.Default.UnregisterAll(this);
}
}