mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
359 lines
13 KiB
C#
359 lines
13 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Input;
|
|
using Aaru.CommonTypes;
|
|
using Aaru.CommonTypes.Enums;
|
|
using Aaru.CommonTypes.Interfaces;
|
|
using Aaru.Core;
|
|
using Aaru.Gui.Views.Windows;
|
|
using Aaru.Images;
|
|
using Aaru.Localization;
|
|
using Aaru.Logging;
|
|
using Avalonia.Platform.Storage;
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
|
using CommunityToolkit.Mvvm.Input;
|
|
using Humanizer;
|
|
using MsBox.Avalonia;
|
|
using MsBox.Avalonia.Base;
|
|
using MsBox.Avalonia.Enums;
|
|
using ImageInfo = Aaru.CommonTypes.Structs.ImageInfo;
|
|
|
|
namespace Aaru.Gui.ViewModels.Windows;
|
|
|
|
public sealed partial class ImageMetadataViewModel : ViewModelBase
|
|
{
|
|
readonly ImageMetadata _view;
|
|
[ObservableProperty]
|
|
string _comments;
|
|
[ObservableProperty]
|
|
bool _commentsNotSet = true;
|
|
[ObservableProperty]
|
|
string _creator;
|
|
[ObservableProperty]
|
|
bool _creatorNotSet = true;
|
|
[ObservableProperty]
|
|
string _driveFirmwareRevision;
|
|
[ObservableProperty]
|
|
bool _driveFirmwareRevisionNotSet = true;
|
|
[ObservableProperty]
|
|
string _driveManufacturer;
|
|
[ObservableProperty]
|
|
bool _driveManufacturerNotSet = true;
|
|
[ObservableProperty]
|
|
string _driveModel;
|
|
[ObservableProperty]
|
|
bool _driveModelNotSet = true;
|
|
[ObservableProperty]
|
|
string _driveSerialNumber;
|
|
[ObservableProperty]
|
|
bool _driveSerialNumberNotSet = true;
|
|
AaruFormat _imageFormat;
|
|
[ObservableProperty]
|
|
string _imagePath;
|
|
IFilter _inputFilter;
|
|
[ObservableProperty]
|
|
bool _isOpened;
|
|
[ObservableProperty]
|
|
int _mediaLastSequence;
|
|
[ObservableProperty]
|
|
string _mediaManufacturer;
|
|
[ObservableProperty]
|
|
bool _mediaManufacturerNotSet = true;
|
|
[ObservableProperty]
|
|
string _mediaModel;
|
|
[ObservableProperty]
|
|
bool _mediaModelNotSet = true;
|
|
[ObservableProperty]
|
|
string _mediaPartNumber;
|
|
[ObservableProperty]
|
|
bool _mediaPartNumberNotSet = true;
|
|
[ObservableProperty]
|
|
int _mediaSequence;
|
|
[ObservableProperty]
|
|
string _mediaSerialNumber;
|
|
[ObservableProperty]
|
|
bool _mediaSerialNumberNotSet = true;
|
|
[ObservableProperty]
|
|
string _mediaTitle;
|
|
[ObservableProperty]
|
|
bool _mediaTitleNotSet = true;
|
|
[ObservableProperty]
|
|
string _mediaType;
|
|
[ObservableProperty]
|
|
bool _sequenceNotSet = true;
|
|
[ObservableProperty]
|
|
string _size;
|
|
|
|
|
|
public ImageMetadataViewModel(ImageMetadata view)
|
|
{
|
|
_view = view;
|
|
OpenImageCommand = new AsyncRelayCommand(OpenImageAsync);
|
|
LoadMetadataCommand = new RelayCommand(LoadMetadata);
|
|
SaveMetadataCommand = new AsyncRelayCommand(SaveMetadataAsync);
|
|
CloseCommand = new RelayCommand(Close);
|
|
}
|
|
|
|
public ICommand OpenImageCommand { get; }
|
|
public ICommand LoadMetadataCommand { get; }
|
|
|
|
public ICommand SaveMetadataCommand { get; }
|
|
public ICommand CloseCommand { get; }
|
|
|
|
static FilePickerFileType AaruFormatFiles { get; } = new(UI.AaruFormat_files)
|
|
{
|
|
Patterns = new AaruFormat().KnownExtensions.Select(static s => $"*{s}").ToList(),
|
|
MimeTypes = ["application/octet-stream"]
|
|
};
|
|
|
|
void Close()
|
|
{
|
|
CloseImage();
|
|
|
|
_view.Close();
|
|
}
|
|
|
|
public void CloseImage()
|
|
{
|
|
if(!IsOpened) return;
|
|
|
|
_imageFormat.Close();
|
|
IsOpened = false;
|
|
}
|
|
|
|
async Task SaveMetadataAsync()
|
|
{
|
|
if(!IsOpened) return;
|
|
|
|
var info = new ImageInfo
|
|
{
|
|
MediaSequence = SequenceNotSet ? 0 : MediaSequence,
|
|
LastMediaSequence = SequenceNotSet ? 0 : MediaLastSequence,
|
|
Creator = CreatorNotSet ? null : Creator,
|
|
Comments = CommentsNotSet ? null : Comments,
|
|
MediaTitle = MediaTitleNotSet ? null : MediaTitle,
|
|
MediaManufacturer = MediaManufacturerNotSet ? null : MediaManufacturer,
|
|
MediaModel = MediaModelNotSet ? null : MediaModel,
|
|
MediaSerialNumber = MediaSerialNumberNotSet ? null : MediaSerialNumber,
|
|
MediaPartNumber = MediaPartNumberNotSet ? null : MediaPartNumber,
|
|
DriveManufacturer = DriveManufacturerNotSet ? null : DriveManufacturer,
|
|
DriveModel = DriveModelNotSet ? null : DriveModel,
|
|
DriveSerialNumber = DriveSerialNumberNotSet ? null : DriveSerialNumber,
|
|
DriveFirmwareRevision = DriveFirmwareRevisionNotSet ? null : DriveFirmwareRevision
|
|
};
|
|
|
|
ulong sectors = _imageFormat.Info.Sectors;
|
|
MediaType mediaType = _imageFormat.Info.MediaType;
|
|
uint negativeSectors = _imageFormat.Info.NegativeSectors;
|
|
uint overflowSectors = _imageFormat.Info.OverflowSectors;
|
|
uint sectorSize = _imageFormat.Info.SectorSize;
|
|
|
|
// We close the read-only context and reopen it in resume mode
|
|
_imageFormat.Close();
|
|
|
|
bool ret = _imageFormat.Create(ImagePath, mediaType, [], sectors, negativeSectors, overflowSectors, sectorSize);
|
|
|
|
IMsBox<ButtonResult> msbox;
|
|
|
|
if(!ret)
|
|
{
|
|
AaruLogging.Error(UI.Error_reopening_image_for_writing);
|
|
AaruLogging.Error(_imageFormat.ErrorMessage);
|
|
|
|
msbox = MessageBoxManager.GetMessageBoxStandard(UI.Title_Error,
|
|
UI.There_was_an_error_reopening_the_image_for_writing,
|
|
ButtonEnum.Ok,
|
|
Icon.Error);
|
|
|
|
await msbox.ShowAsync();
|
|
|
|
_view.Close();
|
|
|
|
return;
|
|
}
|
|
|
|
// Now we set the metadata
|
|
_imageFormat.SetImageInfo(info);
|
|
|
|
// We close the image
|
|
_imageFormat.Close();
|
|
|
|
// And we re-open it in read-only mode
|
|
ErrorNumber errno = _imageFormat.Open(_inputFilter);
|
|
|
|
if(errno != ErrorNumber.NoError)
|
|
{
|
|
AaruLogging.Error(UI.Error_reopening_image_in_read_only_mode_after_writing_metadata);
|
|
AaruLogging.Error(Aaru.Localization.Core.Error_0, errno);
|
|
|
|
msbox = MessageBoxManager.GetMessageBoxStandard(UI.Title_Error,
|
|
UI
|
|
.There_was_an_error_reopening_the_image_in_read_only_mode_after_writing_metadata,
|
|
ButtonEnum.Ok,
|
|
Icon.Error);
|
|
|
|
await msbox.ShowAsync();
|
|
|
|
_view.Close();
|
|
|
|
return;
|
|
}
|
|
|
|
msbox = MessageBoxManager.GetMessageBoxStandard(Aaru.Localization.Core.Success,
|
|
UI.Metadata_saved_successfully,
|
|
ButtonEnum.Ok,
|
|
Icon.Success);
|
|
|
|
await msbox.ShowAsync();
|
|
|
|
LoadMetadata();
|
|
}
|
|
|
|
void LoadMetadata()
|
|
{
|
|
if(!IsOpened) return;
|
|
|
|
MediaSequence = _imageFormat.Info.MediaSequence;
|
|
MediaLastSequence = _imageFormat.Info.LastMediaSequence;
|
|
Creator = _imageFormat.Info.Creator;
|
|
Comments = _imageFormat.Info.Comments;
|
|
MediaTitle = _imageFormat.Info.MediaTitle;
|
|
MediaManufacturer = _imageFormat.Info.MediaManufacturer;
|
|
MediaModel = _imageFormat.Info.MediaModel;
|
|
MediaSerialNumber = _imageFormat.Info.MediaSerialNumber;
|
|
MediaPartNumber = _imageFormat.Info.MediaPartNumber;
|
|
DriveManufacturer = _imageFormat.Info.DriveManufacturer;
|
|
DriveModel = _imageFormat.Info.DriveModel;
|
|
DriveSerialNumber = _imageFormat.Info.DriveSerialNumber;
|
|
DriveFirmwareRevision = _imageFormat.Info.DriveFirmwareRevision;
|
|
SequenceNotSet = MediaSequence == 0 || MediaLastSequence == 0;
|
|
CreatorNotSet = string.IsNullOrEmpty(Creator);
|
|
CommentsNotSet = string.IsNullOrEmpty(Comments);
|
|
MediaTitleNotSet = string.IsNullOrEmpty(MediaTitle);
|
|
MediaManufacturerNotSet = string.IsNullOrEmpty(MediaManufacturer);
|
|
MediaModelNotSet = string.IsNullOrEmpty(MediaModel);
|
|
MediaSerialNumberNotSet = string.IsNullOrEmpty(MediaSerialNumber);
|
|
MediaPartNumberNotSet = string.IsNullOrEmpty(MediaPartNumber);
|
|
DriveManufacturerNotSet = string.IsNullOrEmpty(DriveManufacturer);
|
|
DriveModelNotSet = string.IsNullOrEmpty(DriveModel);
|
|
DriveSerialNumberNotSet = string.IsNullOrEmpty(DriveSerialNumber);
|
|
DriveFirmwareRevisionNotSet = string.IsNullOrEmpty(DriveFirmwareRevision);
|
|
}
|
|
|
|
async Task OpenImageAsync()
|
|
{
|
|
IReadOnlyList<IStorageFile> result = await _view.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
|
|
{
|
|
Title = UI.Dialog_Choose_image_to_open,
|
|
AllowMultiple = false,
|
|
FileTypeFilter = [AaruFormatFiles]
|
|
});
|
|
|
|
// Exit if user did not select exactly one file
|
|
if(result.Count != 1) return;
|
|
|
|
// Get the appropriate filter plugin for the selected file
|
|
IFilter inputFilter = PluginRegister.Singleton.GetFilter(result[0].Path.LocalPath);
|
|
|
|
// Show error if no suitable filter plugin is found
|
|
if(inputFilter == null)
|
|
{
|
|
IMsBox<ButtonResult> msbox = MessageBoxManager.GetMessageBoxStandard(UI.Title_Error,
|
|
UI.Cannot_open_specified_file,
|
|
ButtonEnum.Ok,
|
|
Icon.Error);
|
|
|
|
await msbox.ShowAsync();
|
|
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
// Detect the image format of the selected file
|
|
if(ImageFormat.Detect(inputFilter) is not AaruFormat imageFormat)
|
|
{
|
|
IMsBox<ButtonResult> msbox = MessageBoxManager.GetMessageBoxStandard(UI.Title_Error,
|
|
UI.File_is_not_an_AaruFormat_image,
|
|
ButtonEnum.Ok,
|
|
Icon.Error);
|
|
|
|
await msbox.ShowAsync();
|
|
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
// Open the image file
|
|
ErrorNumber opened = imageFormat.Open(inputFilter);
|
|
|
|
if(opened != ErrorNumber.NoError)
|
|
{
|
|
IMsBox<ButtonResult> msbox = MessageBoxManager.GetMessageBoxStandard(UI.Title_Error,
|
|
string.Format(UI.Error_0_opening_image_format, opened),
|
|
ButtonEnum.Ok,
|
|
Icon.Error);
|
|
|
|
await msbox.ShowAsync();
|
|
|
|
AaruLogging.Error(UI.Unable_to_open_image_format);
|
|
AaruLogging.Error(UI.No_error_given);
|
|
|
|
return;
|
|
}
|
|
|
|
if(imageFormat.Info.Version.StartsWith("1.", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
IMsBox<ButtonResult> msbox = MessageBoxManager.GetMessageBoxStandard(UI.Title_Warning,
|
|
UI.AaruFormat_images_version_1_x_are_read_only,
|
|
ButtonEnum.Ok,
|
|
Icon.Warning);
|
|
|
|
await msbox.ShowAsync();
|
|
|
|
return;
|
|
}
|
|
|
|
ImagePath = $"[lime]{result[0].Path.LocalPath}[/]";
|
|
MediaType = $"[orange]{imageFormat.Info.MediaType.Humanize()}[/]";
|
|
|
|
Size =
|
|
$"[teal]{ByteSize.FromBytes(imageFormat.Info.Sectors * imageFormat.Info.SectorSize).Humanize()}[/]";
|
|
|
|
_inputFilter = inputFilter;
|
|
_imageFormat = imageFormat;
|
|
IsOpened = true;
|
|
|
|
LoadMetadata();
|
|
}
|
|
catch(Exception ex)
|
|
{
|
|
IMsBox<ButtonResult> msbox = MessageBoxManager.GetMessageBoxStandard(UI.Title_Error,
|
|
UI.Unable_to_open_image_format,
|
|
ButtonEnum.Ok,
|
|
Icon.Error);
|
|
|
|
await msbox.ShowAsync();
|
|
|
|
AaruLogging.Error(UI.Unable_to_open_image_format);
|
|
AaruLogging.Error(Aaru.Localization.Core.Error_0, ex.Message);
|
|
AaruLogging.Exception(ex, Aaru.Localization.Core.Error_0, ex.Message);
|
|
}
|
|
}
|
|
catch(Exception ex)
|
|
{
|
|
IMsBox<ButtonResult> msbox = MessageBoxManager.GetMessageBoxStandard(UI.Title_Error,
|
|
UI.Exception_reading_file,
|
|
ButtonEnum.Ok,
|
|
Icon.Error);
|
|
|
|
await msbox.ShowAsync();
|
|
|
|
AaruLogging.Error(string.Format(UI.Error_reading_file_0, ex.Message));
|
|
AaruLogging.Exception(ex, UI.Error_reading_file_0, ex.Message);
|
|
}
|
|
}
|
|
} |