Files
Aaru/Aaru.Gui/ViewModels/Windows/MainWindowViewModel.cs

901 lines
36 KiB
C#
Raw Normal View History

2020-04-17 21:45:50 +01:00
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : MainWindowViewModel.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : GUI view models.
//
// --[ Description ] ----------------------------------------------------------
//
// View model and code for the main window.
//
// --[ License ] --------------------------------------------------------------
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General public License for more details.
//
// You should have received a copy of the GNU General public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
2022-12-03 16:07:10 +00:00
// Copyright © 2011-2023 Natalia Portillo
2020-04-17 21:45:50 +01:00
// ****************************************************************************/
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
2020-04-11 04:35:38 +01:00
using System.Linq;
using System.Reactive;
using System.Threading.Tasks;
using Aaru.CommonTypes;
using Aaru.CommonTypes.Enums;
using Aaru.CommonTypes.Interfaces;
2020-04-11 04:35:38 +01:00
using Aaru.CommonTypes.Interop;
using Aaru.CommonTypes.Structs.Devices.SCSI;
using Aaru.Console;
using Aaru.Core;
using Aaru.Core.Media.Info;
using Aaru.Database;
using Aaru.Devices;
2020-04-11 04:35:38 +01:00
using Aaru.Gui.Models;
2020-04-16 20:40:25 +01:00
using Aaru.Gui.ViewModels.Dialogs;
using Aaru.Gui.ViewModels.Panels;
using Aaru.Gui.Views.Dialogs;
using Aaru.Gui.Views.Panels;
using Aaru.Gui.Views.Windows;
using Aaru.Localization;
2020-04-09 18:18:56 +01:00
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Media.Imaging;
using Avalonia.Platform;
2020-07-22 13:20:25 +01:00
using JetBrains.Annotations;
2023-09-26 01:29:07 +01:00
using MsBox.Avalonia;
using MsBox.Avalonia.Enums;
2020-04-10 01:10:55 +01:00
using ReactiveUI;
using DeviceInfo = Aaru.Core.Devices.Info.DeviceInfo;
2020-04-16 21:29:40 +01:00
using ImageInfo = Aaru.Gui.Views.Panels.ImageInfo;
using Partition = Aaru.Gui.Views.Panels.Partition;
using PlatformID = Aaru.CommonTypes.Interop.PlatformID;
2020-04-09 18:18:56 +01:00
namespace Aaru.Gui.ViewModels.Windows;
2022-03-06 13:29:38 +00:00
public sealed class MainWindowViewModel : ViewModelBase
2020-04-09 02:26:04 +01:00
{
2023-10-03 23:27:57 +01:00
const string MODULE_NAME = "Main Window ViewModel";
readonly DevicesRootModel _devicesRoot;
readonly Bitmap _ejectIcon;
readonly Bitmap _genericFolderIcon;
readonly Bitmap _genericHddIcon;
readonly Bitmap _genericOpticalIcon;
readonly Bitmap _genericTapeIcon;
readonly ImagesRootModel _imagesRoot;
readonly Bitmap _removableIcon;
readonly Bitmap _sdIcon;
readonly Bitmap _usbIcon;
readonly MainWindow _view;
Views.Dialogs.Console _console;
object _contentPanel;
bool _devicesSupported;
object _treeViewSelectedItem;
2022-03-06 13:29:38 +00:00
public MainWindowViewModel(MainWindow view)
2020-04-09 02:26:04 +01:00
{
2022-03-06 13:29:38 +00:00
AboutCommand = ReactiveCommand.Create(ExecuteAboutCommand);
EncodingsCommand = ReactiveCommand.Create(ExecuteEncodingsCommand);
PluginsCommand = ReactiveCommand.Create(ExecutePluginsCommand);
StatisticsCommand = ReactiveCommand.Create(ExecuteStatisticsCommand);
ExitCommand = ReactiveCommand.Create(ExecuteExitCommand);
SettingsCommand = ReactiveCommand.Create(ExecuteSettingsCommand);
ConsoleCommand = ReactiveCommand.Create(ExecuteConsoleCommand);
OpenCommand = ReactiveCommand.Create(ExecuteOpenCommand);
CalculateEntropyCommand = ReactiveCommand.Create(ExecuteCalculateEntropyCommand);
VerifyImageCommand = ReactiveCommand.Create(ExecuteVerifyImageCommand);
ChecksumImageCommand = ReactiveCommand.Create(ExecuteChecksumImageCommand);
ConvertImageCommand = ReactiveCommand.Create(ExecuteConvertImageCommand);
CreateSidecarCommand = ReactiveCommand.Create(ExecuteCreateSidecarCommand);
ViewImageSectorsCommand = ReactiveCommand.Create(ExecuteViewImageSectorsCommand);
DecodeImageMediaTagsCommand = ReactiveCommand.Create(ExecuteDecodeImageMediaTagsCommand);
RefreshDevicesCommand = ReactiveCommand.Create(ExecuteRefreshDevicesCommand);
_view = view;
TreeRoot = new ObservableCollection<RootModel>();
ContentPanel = Greeting;
_imagesRoot = new ImagesRootModel
{
Name = UI.Title_Images
2022-03-06 13:29:38 +00:00
};
2022-03-06 13:29:38 +00:00
TreeRoot.Add(_imagesRoot);
2022-03-06 13:29:38 +00:00
switch(DetectOS.GetRealPlatformID())
{
case PlatformID.Win32NT:
case PlatformID.Linux:
case PlatformID.FreeBSD:
_devicesRoot = new DevicesRootModel
{
Name = UI.Title_Devices
2022-03-06 13:29:38 +00:00
};
2022-03-06 13:29:38 +00:00
TreeRoot.Add(_devicesRoot);
DevicesSupported = true;
2022-03-06 13:29:38 +00:00
break;
}
2022-03-06 13:29:38 +00:00
_genericHddIcon =
2023-09-25 22:58:48 +01:00
new Bitmap(AssetLoader.Open(new Uri("avares://Aaru.Gui/Assets/Icons/oxygen/32x32/drive-harddisk.png")));
2022-03-06 13:29:38 +00:00
_genericOpticalIcon =
2023-09-25 22:58:48 +01:00
new Bitmap(AssetLoader.Open(new Uri("avares://Aaru.Gui/Assets/Icons/oxygen/32x32/drive-optical.png")));
2022-03-06 13:29:38 +00:00
_genericTapeIcon =
2023-09-25 22:58:48 +01:00
new Bitmap(AssetLoader.Open(new Uri("avares://Aaru.Gui/Assets/Icons/oxygen/32x32/media-tape.png")));
2022-03-06 13:29:38 +00:00
_genericFolderIcon =
2023-09-25 22:58:48 +01:00
new Bitmap(AssetLoader.Open(new Uri("avares://Aaru.Gui/Assets/Icons/oxygen/32x32/inode-directory.png")));
2022-03-06 13:29:38 +00:00
_usbIcon =
new Bitmap(AssetLoader.
Open(new Uri("avares://Aaru.Gui/Assets/Icons/oxygen/32x32/drive-removable-media-usb.png")));
2022-03-06 13:29:38 +00:00
_removableIcon =
new Bitmap(AssetLoader.
Open(new Uri("avares://Aaru.Gui/Assets/Icons/oxygen/32x32/drive-removable-media.png")));
2022-03-06 13:29:38 +00:00
_sdIcon =
2023-09-25 22:58:48 +01:00
new Bitmap(AssetLoader.Open(new Uri("avares://Aaru.Gui/Assets/Icons/oxygen/32x32/media-flash-sd-mmc.png")));
2023-10-03 23:27:57 +01:00
_ejectIcon =
new Bitmap(AssetLoader.Open(new Uri("avares://Aaru.Gui/Assets/Icons/oxygen/32x32/media-eject.png")));
2022-03-06 13:29:38 +00:00
}
public string FileLabel => UI.Menu_File;
public string OpenLabel => UI.Menu_Open;
public string SettingsLabel => UI.Menu_Settings;
public string ExitLabel => UI.Menu_Exit;
public string DevicesLabel => UI.Menu_Devices;
public string RefreshDevicesLabel => UI.Menu_Refresh;
public string WindowLabel => UI.Menu_Window;
public string ConsoleLabel => UI.Menu_Console;
public string HelpLabel => UI.Menu_Help;
public string EncodingsLabel => UI.Menu_Encodings;
public string PluginsLabel => UI.Menu_Plugins;
public string StatisticsLabel => UI.Menu_Statistics;
public string AboutLabel => UI.Menu_About;
public string RefreshDevicesFullLabel => UI.Menu_Refresh_devices;
public string CloseAllImagesLabel => UI.Menu_Close_all_images;
public string CalculateEntropyLabel => UI.ButtonLabel_Calculate_entropy;
public string VerifyImageLabel => UI.ButtonLabel_Verify;
public string ChecksumImageLabel => UI.ButtonLabel_Checksum;
public string CreateSidecarLabel => UI.ButtonLabel_Create_Aaru_Metadata_sidecar;
public string ViewImageSectorsLabel => UI.ButtonLabel_View_sectors;
public string DecodeImageMediaTagsLabel => UI.ButtonLabel_Decode_media_tags;
2022-03-06 13:29:38 +00:00
public bool DevicesSupported
{
get => _devicesSupported;
set => this.RaiseAndSetIfChanged(ref _devicesSupported, value);
}
public bool NativeMenuSupported
{
get
{
Window mainWindow = (Application.Current?.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime)?.
MainWindow;
return mainWindow is not null && NativeMenu.GetIsNativeMenuExported(mainWindow);
}
}
2022-03-06 13:29:38 +00:00
[NotNull]
public string Greeting => UI.Welcome_to_Aaru;
2023-10-03 23:27:57 +01:00
2022-03-06 13:29:38 +00:00
public ObservableCollection<RootModel> TreeRoot { get; }
public ReactiveCommand<Unit, Unit> AboutCommand { get; }
public ReactiveCommand<Unit, Unit> ConsoleCommand { get; }
public ReactiveCommand<Unit, Unit> EncodingsCommand { get; }
public ReactiveCommand<Unit, Unit> PluginsCommand { get; }
public ReactiveCommand<Unit, Unit> StatisticsCommand { get; }
public ReactiveCommand<Unit, Unit> ExitCommand { get; }
public ReactiveCommand<Unit, Task> SettingsCommand { get; }
public ReactiveCommand<Unit, Task> OpenCommand { get; }
2022-03-06 13:29:38 +00:00
public ReactiveCommand<Unit, Unit> CalculateEntropyCommand { get; }
public ReactiveCommand<Unit, Unit> VerifyImageCommand { get; }
public ReactiveCommand<Unit, Unit> ChecksumImageCommand { get; }
public ReactiveCommand<Unit, Unit> ConvertImageCommand { get; }
public ReactiveCommand<Unit, Unit> CreateSidecarCommand { get; }
public ReactiveCommand<Unit, Unit> ViewImageSectorsCommand { get; }
public ReactiveCommand<Unit, Unit> DecodeImageMediaTagsCommand { get; }
public ReactiveCommand<Unit, Unit> RefreshDevicesCommand { get; }
public object ContentPanel
{
get => _contentPanel;
set => this.RaiseAndSetIfChanged(ref _contentPanel, value);
}
2022-03-06 13:29:38 +00:00
public object TreeViewSelectedItem
{
get => _treeViewSelectedItem;
set
{
2022-03-06 13:29:38 +00:00
if(value == _treeViewSelectedItem)
return;
2022-03-06 13:29:38 +00:00
this.RaiseAndSetIfChanged(ref _treeViewSelectedItem, value);
2022-03-06 13:29:38 +00:00
ContentPanel = null;
2022-03-06 13:29:38 +00:00
switch(value)
{
case ImageModel imageModel:
ContentPanel = new ImageInfo
{
DataContext = imageModel.ViewModel
};
2022-03-06 13:29:38 +00:00
break;
case PartitionModel partitionModel:
ContentPanel = new Partition
{
DataContext = partitionModel.ViewModel
};
2022-03-06 13:29:38 +00:00
break;
case FileSystemModel fileSystemModel:
ContentPanel = new FileSystem
{
DataContext = fileSystemModel.ViewModel
};
2022-03-06 13:29:38 +00:00
break;
case SubdirectoryModel subdirectoryModel:
ContentPanel = new Subdirectory
{
DataContext = new SubdirectoryViewModel(subdirectoryModel, _view)
};
2022-03-06 13:29:38 +00:00
break;
case DeviceModel deviceModel:
{
if(deviceModel.ViewModel is null)
{
var dev = Device.Create(deviceModel.Path, out ErrorNumber devErrno);
switch(dev)
{
case null:
ContentPanel = string.Format(UI.Error_0_opening_device, devErrno);
return;
case Devices.Remote.Device remoteDev:
Statistics.AddRemote(remoteDev.RemoteApplication, remoteDev.RemoteVersion,
remoteDev.RemoteOperatingSystem,
remoteDev.RemoteOperatingSystemVersion,
remoteDev.RemoteArchitecture);
break;
}
if(dev.Error)
{
ContentPanel = string.Format(UI.Error_0_opening_device, dev.LastError);
2022-03-06 13:29:38 +00:00
return;
}
var devInfo = new DeviceInfo(dev);
deviceModel.ViewModel = new DeviceInfoViewModel(devInfo, _view);
if(!dev.IsRemovable)
2023-10-03 23:27:57 +01:00
{
deviceModel.Media.Add(new MediaModel
{
NonRemovable = true,
Name = UI.Non_removable_device_commands_not_yet_implemented
});
2023-10-03 23:27:57 +01:00
}
else
{
// TODO: Removable non-SCSI?
var scsiInfo = new ScsiInfo(dev);
if(!scsiInfo.MediaInserted)
2023-10-03 23:27:57 +01:00
{
2022-03-06 13:29:38 +00:00
deviceModel.Media.Add(new MediaModel
{
NoMediaInserted = true,
Icon = _ejectIcon,
Name = UI.No_media_inserted
2022-03-06 13:29:38 +00:00
});
2023-10-03 23:27:57 +01:00
}
2022-03-06 13:29:38 +00:00
else
{
var mediaResource =
new Uri($"avares://Aaru.Gui/Assets/Logos/Media/{scsiInfo.MediaType}.png");
deviceModel.Media.Add(new MediaModel
{
DevicePath = deviceModel.Path,
2023-10-03 23:27:57 +01:00
Icon = AssetLoader.Exists(mediaResource)
? new Bitmap(AssetLoader.Open(mediaResource))
: null,
Name = $"{scsiInfo.MediaType}",
ViewModel = new MediaInfoViewModel(scsiInfo, deviceModel.Path, _view)
});
}
}
dev.Close();
}
2022-03-06 13:29:38 +00:00
ContentPanel = new Views.Panels.DeviceInfo
{
2022-03-06 13:29:38 +00:00
DataContext = deviceModel.ViewModel
};
2022-03-06 13:29:38 +00:00
break;
}
case MediaModel { NonRemovable: true }:
ContentPanel = UI.Non_removable_device_commands_not_yet_implemented;
2022-03-06 13:29:38 +00:00
break;
case MediaModel { NoMediaInserted: true }:
ContentPanel = UI.No_media_inserted;
2022-03-06 13:29:38 +00:00
break;
case MediaModel mediaModel:
{
if(mediaModel.ViewModel != null)
2023-10-03 23:27:57 +01:00
{
2022-03-06 13:29:38 +00:00
ContentPanel = new MediaInfo
{
DataContext = mediaModel.ViewModel
};
2023-10-03 23:27:57 +01:00
}
2022-03-06 13:29:38 +00:00
break;
}
}
}
2022-03-06 13:29:38 +00:00
}
2020-04-14 19:27:07 +01:00
2022-03-06 13:29:38 +00:00
void ExecuteCalculateEntropyCommand()
{
2022-11-14 01:20:28 +00:00
if(TreeViewSelectedItem is not ImageModel imageModel)
2022-03-06 13:29:38 +00:00
return;
2020-04-14 19:27:07 +01:00
2022-03-06 13:29:38 +00:00
var imageEntropyWindow = new ImageEntropy();
imageEntropyWindow.DataContext = new ImageEntropyViewModel(imageModel.Image, imageEntropyWindow);
2020-04-14 19:27:07 +01:00
2022-03-16 00:31:33 +00:00
imageEntropyWindow.Closed += (_, _) => imageEntropyWindow = null;
2020-04-14 19:27:07 +01:00
2022-03-06 13:29:38 +00:00
imageEntropyWindow.Show();
}
2020-04-14 19:27:07 +01:00
2022-03-06 13:29:38 +00:00
void ExecuteVerifyImageCommand()
{
2022-11-14 01:20:28 +00:00
if(TreeViewSelectedItem is not ImageModel imageModel)
2022-03-06 13:29:38 +00:00
return;
2020-04-14 19:27:07 +01:00
2022-03-06 13:29:38 +00:00
var imageVerifyWindow = new ImageVerify();
imageVerifyWindow.DataContext = new ImageVerifyViewModel(imageModel.Image, imageVerifyWindow);
2020-04-14 19:27:07 +01:00
2022-03-16 00:31:33 +00:00
imageVerifyWindow.Closed += (_, _) => imageVerifyWindow = null;
2020-04-14 19:27:07 +01:00
2022-03-06 13:29:38 +00:00
imageVerifyWindow.Show();
}
2020-04-14 19:27:07 +01:00
2022-03-06 13:29:38 +00:00
void ExecuteChecksumImageCommand()
{
2022-11-14 01:20:28 +00:00
if(TreeViewSelectedItem is not ImageModel imageModel)
2022-03-06 13:29:38 +00:00
return;
2020-04-14 19:27:07 +01:00
2022-03-06 13:29:38 +00:00
var imageChecksumWindow = new ImageChecksum();
imageChecksumWindow.DataContext = new ImageChecksumViewModel(imageModel.Image, imageChecksumWindow);
2020-04-14 19:27:07 +01:00
2022-03-16 00:31:33 +00:00
imageChecksumWindow.Closed += (_, _) => imageChecksumWindow = null;
2020-04-14 19:27:07 +01:00
2022-03-06 13:29:38 +00:00
imageChecksumWindow.Show();
}
2020-04-14 19:27:07 +01:00
2022-03-06 13:29:38 +00:00
void ExecuteConvertImageCommand()
{
2022-11-14 01:20:28 +00:00
if(TreeViewSelectedItem is not ImageModel imageModel)
2022-03-06 13:29:38 +00:00
return;
2020-04-14 19:27:07 +01:00
2022-03-06 13:29:38 +00:00
var imageConvertWindow = new ImageConvert();
2022-03-06 13:29:38 +00:00
imageConvertWindow.DataContext =
new ImageConvertViewModel(imageModel.Image, imageModel.Path, imageConvertWindow);
2020-04-14 19:27:07 +01:00
2022-03-16 00:31:33 +00:00
imageConvertWindow.Closed += (_, _) => imageConvertWindow = null;
2020-04-14 19:27:07 +01:00
2022-03-06 13:29:38 +00:00
imageConvertWindow.Show();
}
2020-04-14 19:27:07 +01:00
2022-03-06 13:29:38 +00:00
void ExecuteCreateSidecarCommand()
{
2022-11-14 01:20:28 +00:00
if(TreeViewSelectedItem is not ImageModel imageModel)
2022-03-06 13:29:38 +00:00
return;
2020-04-14 19:27:07 +01:00
2022-03-06 13:29:38 +00:00
var imageSidecarWindow = new ImageSidecar();
2020-04-14 19:27:07 +01:00
2022-03-06 13:29:38 +00:00
// TODO: Pass thru chosen default encoding
imageSidecarWindow.DataContext =
new ImageSidecarViewModel(imageModel.Image, imageModel.Path, imageModel.Filter.Id, null,
imageSidecarWindow);
2020-04-14 19:27:07 +01:00
2022-03-06 13:29:38 +00:00
imageSidecarWindow.Show();
}
void ExecuteViewImageSectorsCommand()
{
2022-11-14 01:20:28 +00:00
if(TreeViewSelectedItem is not ImageModel imageModel)
2022-03-06 13:29:38 +00:00
return;
2020-04-14 19:27:07 +01:00
2022-03-06 13:29:38 +00:00
new ViewSector
2020-04-14 19:27:07 +01:00
{
2022-03-06 13:29:38 +00:00
DataContext = new ViewSectorViewModel(imageModel.Image)
}.Show();
}
2020-04-14 19:27:07 +01:00
2022-03-06 13:29:38 +00:00
void ExecuteDecodeImageMediaTagsCommand()
{
2022-11-14 01:20:28 +00:00
if(TreeViewSelectedItem is not ImageModel imageModel)
2022-03-06 13:29:38 +00:00
return;
2020-04-14 19:27:07 +01:00
2022-03-06 13:29:38 +00:00
new DecodeMediaTags
2020-04-14 19:27:07 +01:00
{
2022-03-06 13:29:38 +00:00
DataContext = new DecodeMediaTagsViewModel(imageModel.Image)
}.Show();
}
2020-04-14 19:27:07 +01:00
2022-03-06 13:29:38 +00:00
internal void ExecuteAboutCommand()
{
var dialog = new About();
dialog.DataContext = new AboutViewModel(dialog);
dialog.ShowDialog(_view);
}
2020-04-10 01:10:55 +01:00
2022-03-06 13:29:38 +00:00
void ExecuteEncodingsCommand()
{
var dialog = new Encodings();
dialog.DataContext = new EncodingsViewModel(dialog);
dialog.ShowDialog(_view);
}
2022-03-06 13:29:38 +00:00
void ExecutePluginsCommand()
{
var dialog = new PluginsDialog();
dialog.DataContext = new PluginsViewModel(dialog);
dialog.ShowDialog(_view);
}
2022-03-06 13:29:38 +00:00
void ExecuteStatisticsCommand()
{
using var ctx = AaruContext.Create(Settings.Settings.LocalDbPath);
2022-03-06 13:29:38 +00:00
if(!ctx.Commands.Any() &&
!ctx.Filesystems.Any() &&
!ctx.Filters.Any() &&
!ctx.MediaFormats.Any() &&
!ctx.Medias.Any() &&
!ctx.Partitions.Any() &&
!ctx.SeenDevices.Any())
{
2023-09-26 01:29:07 +01:00
MessageBoxManager.GetMessageBoxStandard(UI.Title_Warning, UI.There_are_no_statistics).
ShowWindowDialogAsync(_view);
2022-03-06 13:29:38 +00:00
return;
}
2022-03-06 13:29:38 +00:00
var dialog = new StatisticsDialog();
dialog.DataContext = new StatisticsViewModel(dialog);
dialog.ShowDialog(_view);
}
internal async Task ExecuteSettingsCommand()
2022-03-06 13:29:38 +00:00
{
var dialog = new SettingsDialog();
dialog.DataContext = new SettingsViewModel(dialog, false);
await dialog.ShowDialog(_view);
}
2022-03-06 13:29:38 +00:00
internal void ExecuteExitCommand() =>
2022-03-17 00:46:26 +00:00
(Application.Current?.ApplicationLifetime as ClassicDesktopStyleApplicationLifetime)?.Shutdown();
2020-04-10 19:11:19 +01:00
2022-03-06 13:29:38 +00:00
void ExecuteConsoleCommand()
{
if(_console is null)
{
_console = new Views.Dialogs.Console();
2022-03-06 13:29:38 +00:00
_console.DataContext = new ConsoleViewModel(_console);
}
2022-03-06 13:29:38 +00:00
_console.Show();
}
async Task ExecuteOpenCommand()
2022-03-06 13:29:38 +00:00
{
// TODO: Extensions
var dlgOpenImage = new OpenFileDialog
{
Title = UI.Dialog_Choose_image_to_open,
2022-03-06 13:29:38 +00:00
AllowMultiple = false
};
2022-03-06 13:29:38 +00:00
string[] result = await dlgOpenImage.ShowAsync(_view);
2022-03-06 13:29:38 +00:00
if(result?.Length != 1)
return;
IFilter inputFilter = PluginRegister.Singleton.GetFilter(result[0]);
2022-03-06 13:29:38 +00:00
if(inputFilter == null)
{
2023-09-26 01:29:07 +01:00
MessageBoxManager.GetMessageBoxStandard(UI.Title_Error, UI.Cannot_open_specified_file, ButtonEnum.Ok,
2023-10-03 23:27:57 +01:00
Icon.Error);
2022-03-06 13:29:38 +00:00
return;
}
2022-03-06 13:29:38 +00:00
try
{
2022-11-14 01:49:10 +00:00
if(ImageFormat.Detect(inputFilter) is not IMediaImage imageFormat)
{
MessageBoxManager.GetMessageBoxStandard(UI.Title_Error, UI.Image_format_not_identified, ButtonEnum.Ok,
Icon.Error);
return;
}
AaruConsole.WriteLine(UI.Image_format_identified_by_0_1, imageFormat.Name, imageFormat.Id);
2022-03-06 13:29:38 +00:00
try
{
2022-03-06 13:29:38 +00:00
ErrorNumber opened = imageFormat.Open(inputFilter);
2022-03-06 13:29:38 +00:00
if(opened != ErrorNumber.NoError)
{
2023-09-26 01:29:07 +01:00
MessageBoxManager.GetMessageBoxStandard(UI.Title_Error,
string.Format(UI.Error_0_opening_image_format, opened),
ButtonEnum.Ok, Icon.Error);
AaruConsole.ErrorWriteLine(UI.Unable_to_open_image_format);
AaruConsole.ErrorWriteLine(UI.No_error_given);
2022-03-06 13:29:38 +00:00
return;
}
2022-03-07 07:36:44 +00:00
var mediaResource = new Uri($"avares://Aaru.Gui/Assets/Logos/Media/{imageFormat.Info.MediaType}.png");
2022-03-06 13:29:38 +00:00
var imageModel = new ImageModel
{
2022-03-06 13:29:38 +00:00
Path = result[0],
2023-09-25 22:58:48 +01:00
Icon = AssetLoader.Exists(mediaResource)
? new Bitmap(AssetLoader.Open(mediaResource))
:
imageFormat.Info.MetadataMediaType == MetadataMediaType.BlockMedia
2022-03-06 13:29:38 +00:00
? _genericHddIcon
:
imageFormat.Info.MetadataMediaType == MetadataMediaType.OpticalDisc
?
_genericOpticalIcon
2022-03-06 13:29:38 +00:00
: _genericFolderIcon,
FileName = Path.GetFileName(result[0]),
Image = imageFormat,
ViewModel = new ImageInfoViewModel(result[0], inputFilter, imageFormat, _view),
Filter = inputFilter
};
List<CommonTypes.Partition> partitions = Core.Partitions.GetAll(imageFormat);
Core.Partitions.AddSchemesToStats(partitions);
2022-03-06 13:29:38 +00:00
var checkRaw = false;
List<string> idPlugins;
Type pluginType;
PluginRegister plugins = PluginRegister.Singleton;
2022-03-06 13:29:38 +00:00
if(partitions.Count == 0)
{
AaruConsole.DebugWriteLine(MODULE_NAME, UI.No_partitions_found);
2022-03-06 13:29:38 +00:00
checkRaw = true;
}
else
{
AaruConsole.WriteLine(UI._0_partitions_found, partitions.Count);
2022-03-06 13:29:38 +00:00
foreach(string scheme in partitions.Select(p => p.Scheme).Distinct().OrderBy(s => s))
{
2022-03-06 13:29:38 +00:00
// TODO: Add icons to partition schemes
var schemeModel = new PartitionSchemeModel
{
Name = scheme
};
2022-03-06 13:29:38 +00:00
foreach(CommonTypes.Partition partition in partitions.Where(p => p.Scheme == scheme).
OrderBy(p => p.Start))
{
2022-03-06 13:29:38 +00:00
var partitionModel = new PartitionModel
{
2022-03-06 13:29:38 +00:00
// TODO: Add icons to partition types
Name = $"{partition.Name} ({partition.Type})",
Partition = partition,
ViewModel = new PartitionViewModel(partition)
};
AaruConsole.WriteLine(UI.Identifying_filesystems_on_partition);
2022-03-06 13:29:38 +00:00
Core.Filesystems.Identify(imageFormat, out idPlugins, partition);
2022-03-06 13:29:38 +00:00
if(idPlugins.Count == 0)
AaruConsole.WriteLine(UI.Filesystem_not_identified);
2022-03-06 13:29:38 +00:00
else
{
AaruConsole.WriteLine(string.Format(UI.Identified_by_0_plugins, idPlugins.Count));
2022-03-06 13:29:38 +00:00
foreach(string pluginName in idPlugins)
2023-10-03 23:27:57 +01:00
{
if(!plugins.Filesystems.TryGetValue(pluginName, out pluginType))
continue;
if(Activator.CreateInstance(pluginType) is not IFilesystem fs)
continue;
fs.GetInformation(imageFormat, partition, null, out string information,
out CommonTypes.AaruMetadata.FileSystem fsMetadata);
2022-12-17 14:56:37 +00:00
var rofs = fs as IReadOnlyFilesystem;
if(rofs != null)
{
ErrorNumber error = rofs.Mount(imageFormat, partition, null,
new Dictionary<string, string>(), null);
if(error != ErrorNumber.NoError)
rofs = null;
}
var filesystemModel = new FileSystemModel
{
VolumeName = rofs?.Metadata.VolumeName is null
? fsMetadata.VolumeName is null
? $"{fsMetadata.Type}"
: $"{fsMetadata.VolumeName} ({fsMetadata.Type})"
: $"{rofs.Metadata.VolumeName} ({rofs.Metadata.Type})",
Filesystem = fs,
ReadOnlyFilesystem = rofs,
ViewModel = new FileSystemViewModel(rofs?.Metadata ?? fsMetadata, information)
};
// TODO: Trap expanding item
if(rofs != null)
{
filesystemModel.Roots.Add(new SubdirectoryModel
2022-03-06 13:29:38 +00:00
{
Name = "/",
Path = "",
Plugin = rofs
});
Statistics.AddCommand("ls");
2022-03-06 13:29:38 +00:00
}
Statistics.AddFilesystem(rofs?.Metadata.Type ?? fsMetadata.Type);
partitionModel.FileSystems.Add(filesystemModel);
2023-10-03 23:27:57 +01:00
}
}
2022-03-06 13:29:38 +00:00
schemeModel.Partitions.Add(partitionModel);
}
2022-03-06 13:29:38 +00:00
imageModel.PartitionSchemesOrFileSystems.Add(schemeModel);
}
2022-03-06 13:29:38 +00:00
}
2022-03-06 13:29:38 +00:00
if(checkRaw)
{
var wholePart = new CommonTypes.Partition
{
Name = Localization.Core.Whole_device,
2022-03-06 13:29:38 +00:00
Length = imageFormat.Info.Sectors,
Size = imageFormat.Info.Sectors * imageFormat.Info.SectorSize
};
Core.Filesystems.Identify(imageFormat, out idPlugins, wholePart);
2022-03-06 13:29:38 +00:00
if(idPlugins.Count == 0)
AaruConsole.WriteLine(UI.Filesystem_not_identified);
2022-03-06 13:29:38 +00:00
else
{
AaruConsole.WriteLine(string.Format(UI.Identified_by_0_plugins, idPlugins.Count));
2022-03-06 13:29:38 +00:00
foreach(string pluginName in idPlugins)
2023-10-03 23:27:57 +01:00
{
if(!plugins.Filesystems.TryGetValue(pluginName, out pluginType))
continue;
if(Activator.CreateInstance(pluginType) is not IFilesystem fs)
continue;
2022-12-17 14:56:37 +00:00
fs.GetInformation(imageFormat, wholePart, null, out string information,
out CommonTypes.AaruMetadata.FileSystem fsMetadata);
var rofs = fs as IReadOnlyFilesystem;
if(rofs != null)
{
ErrorNumber error = rofs.Mount(imageFormat, wholePart, null,
new Dictionary<string, string>(), null);
if(error != ErrorNumber.NoError)
rofs = null;
}
var filesystemModel = new FileSystemModel
{
VolumeName = rofs?.Metadata.VolumeName is null
? fsMetadata.VolumeName is null
? $"{fsMetadata.Type}"
: $"{fsMetadata.VolumeName} ({fsMetadata.Type})"
: $"{rofs.Metadata.VolumeName} ({rofs.Metadata.Type})",
Filesystem = fs,
ReadOnlyFilesystem = rofs,
ViewModel = new FileSystemViewModel(rofs?.Metadata ?? fsMetadata, information)
};
// TODO: Trap expanding item
if(rofs != null)
{
filesystemModel.Roots.Add(new SubdirectoryModel
{
Name = "/",
Path = "",
Plugin = rofs
});
Statistics.AddCommand("ls");
2022-03-06 13:29:38 +00:00
}
Statistics.AddFilesystem(rofs?.Metadata.Type ?? fsMetadata.Type);
imageModel.PartitionSchemesOrFileSystems.Add(filesystemModel);
2023-10-03 23:27:57 +01:00
}
2022-03-06 13:29:38 +00:00
}
}
2022-03-06 13:29:38 +00:00
Statistics.AddMediaFormat(imageFormat.Format);
Statistics.AddMedia(imageFormat.Info.MediaType, false);
Statistics.AddFilter(inputFilter.Name);
_imagesRoot.Images.Add(imageModel);
}
catch(Exception ex)
{
MessageBoxManager.GetMessageBoxStandard(UI.Title_Error, UI.Unable_to_open_image_format, ButtonEnum.Ok,
Icon.Error);
AaruConsole.ErrorWriteLine(UI.Unable_to_open_image_format);
AaruConsole.ErrorWriteLine(Localization.Core.Error_0, ex.Message);
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Core.Stack_trace_0, ex.StackTrace);
}
2022-03-06 13:29:38 +00:00
}
catch(Exception ex)
{
2023-09-26 01:29:07 +01:00
MessageBoxManager.GetMessageBoxStandard(UI.Title_Error, UI.Exception_reading_file, ButtonEnum.Ok,
2023-10-03 23:27:57 +01:00
Icon.Error);
AaruConsole.ErrorWriteLine(string.Format(UI.Error_reading_file_0, ex.Message));
AaruConsole.DebugWriteLine(MODULE_NAME, ex.StackTrace);
}
2022-03-06 13:29:38 +00:00
Statistics.AddCommand("image-info");
}
internal void LoadComplete() => RefreshDevices();
void ExecuteRefreshDevicesCommand() => RefreshDevices();
2022-03-06 13:29:38 +00:00
void RefreshDevices()
{
if(!DevicesSupported)
return;
2022-03-06 13:29:38 +00:00
try
{
AaruConsole.WriteLine(UI.Refreshing_devices);
2022-03-06 13:29:38 +00:00
_devicesRoot.Devices.Clear();
foreach(Devices.DeviceInfo device in Device.ListDevices().
Where(d => d.Supported).
OrderBy(d => d.Vendor).
2022-03-07 07:36:44 +00:00
ThenBy(d => d.Model))
{
AaruConsole.DebugWriteLine(MODULE_NAME,
UI.Found_supported_device_model_0_by_manufacturer_1_on_bus_2_and_path_3,
2022-03-06 13:29:38 +00:00
device.Model, device.Vendor, device.Bus, device.Path);
2022-03-06 13:29:38 +00:00
var deviceModel = new DeviceModel
{
2022-03-06 13:29:38 +00:00
Icon = _genericHddIcon,
Name = $"{device.Vendor} {device.Model} ({device.Bus})",
Path = device.Path
};
var dev = Device.Create(device.Path, out _);
if(dev != null)
{
if(dev is Devices.Remote.Device remoteDev)
2023-10-03 23:27:57 +01:00
{
Statistics.AddRemote(remoteDev.RemoteApplication, remoteDev.RemoteVersion,
remoteDev.RemoteOperatingSystem, remoteDev.RemoteOperatingSystemVersion,
remoteDev.RemoteArchitecture);
2023-10-03 23:27:57 +01:00
}
2022-03-06 13:29:38 +00:00
switch(dev.Type)
{
case DeviceType.ATAPI:
case DeviceType.SCSI:
switch(dev.ScsiType)
{
case PeripheralDeviceTypes.DirectAccess:
case PeripheralDeviceTypes.SCSIZonedBlockDevice:
case PeripheralDeviceTypes.SimplifiedDevice:
2023-10-03 23:27:57 +01:00
deviceModel.Icon = dev.IsRemovable
? dev.IsUsb ? _usbIcon : _removableIcon
: _genericHddIcon;
2022-03-06 13:29:38 +00:00
break;
case PeripheralDeviceTypes.SequentialAccess:
deviceModel.Icon = _genericTapeIcon;
break;
case PeripheralDeviceTypes.OpticalDevice:
case PeripheralDeviceTypes.WriteOnceDevice:
case PeripheralDeviceTypes.OCRWDevice:
deviceModel.Icon = _removableIcon;
break;
case PeripheralDeviceTypes.MultiMediaDevice:
deviceModel.Icon = _genericOpticalIcon;
break;
}
2022-03-06 13:29:38 +00:00
break;
case DeviceType.SecureDigital:
case DeviceType.MMC:
deviceModel.Icon = _sdIcon;
2022-03-06 13:29:38 +00:00
break;
case DeviceType.NVMe:
deviceModel.Icon = null;
2022-03-06 13:29:38 +00:00
break;
}
2022-03-06 13:29:38 +00:00
dev.Close();
}
2022-03-06 13:29:38 +00:00
_devicesRoot.Devices.Add(deviceModel);
}
2022-03-06 13:29:38 +00:00
}
catch(InvalidOperationException ex)
{
AaruConsole.ErrorWriteLine(ex.Message);
}
2020-04-09 02:26:04 +01:00
}
2020-04-09 04:18:29 +01:00
}