From 70bb2a80634ef18c088fd3d59b5b10d2b9d4dcc1 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Thu, 16 Oct 2025 01:15:13 +0100 Subject: [PATCH] [TUI] Get image information. --- Aaru.Tui/Aaru.Tui.csproj | 2 + Aaru.Tui/Models/FileModel.cs | 1 + Aaru.Tui/Program.cs | 25 ++-- .../ViewModels/Windows/MainWindowViewModel.cs | 132 +++++++++++++++++- Aaru.Tui/Views/Windows/MainWindow.axaml | 19 ++- 5 files changed, 165 insertions(+), 14 deletions(-) diff --git a/Aaru.Tui/Aaru.Tui.csproj b/Aaru.Tui/Aaru.Tui.csproj index 99564c245..124b94f18 100644 --- a/Aaru.Tui/Aaru.Tui.csproj +++ b/Aaru.Tui/Aaru.Tui.csproj @@ -19,6 +19,8 @@ + + diff --git a/Aaru.Tui/Models/FileModel.cs b/Aaru.Tui/Models/FileModel.cs index 4e883da17..c07b86a90 100644 --- a/Aaru.Tui/Models/FileModel.cs +++ b/Aaru.Tui/Models/FileModel.cs @@ -9,4 +9,5 @@ public class FileModel public IBrush ForegroundBrush { get; set; } public bool IsDirectory { get; set; } public FileInfo? FileInfo { get; set; } + public string? Information { get; set; } } \ No newline at end of file diff --git a/Aaru.Tui/Program.cs b/Aaru.Tui/Program.cs index 8839ca0a7..76630e932 100644 --- a/Aaru.Tui/Program.cs +++ b/Aaru.Tui/Program.cs @@ -1,18 +1,19 @@ +using Aaru.Core; using Avalonia; using Consolonia; -namespace Aaru.Tui -{ - public static class Program - { - public static int Main(string[] args) - { - return BuildAvaloniaApp().StartWithConsoleLifetime(args); - } +namespace Aaru.Tui; - public static AppBuilder BuildAvaloniaApp() - { - return AppBuilder.Configure().UseConsolonia().UseAutoDetectedConsole().LogToException(); - } +public static class Program +{ + public static int Main(string[] args) + { + // There are too many places that depend on this being inited to be sure all are covered, so init it here. + PluginBase.Init(); + + return BuildAvaloniaApp().StartWithConsoleLifetime(args); } + + public static AppBuilder BuildAvaloniaApp() => + AppBuilder.Configure().UseConsolonia().UseAutoDetectedConsole().LogToException(); } \ No newline at end of file diff --git a/Aaru.Tui/ViewModels/Windows/MainWindowViewModel.cs b/Aaru.Tui/ViewModels/Windows/MainWindowViewModel.cs index 2dc115f72..4c595177c 100644 --- a/Aaru.Tui/ViewModels/Windows/MainWindowViewModel.cs +++ b/Aaru.Tui/ViewModels/Windows/MainWindowViewModel.cs @@ -1,6 +1,11 @@ using System.Collections.ObjectModel; using System.Reflection; +using System.Text; using System.Windows.Input; +using Aaru.CommonTypes; +using Aaru.CommonTypes.Enums; +using Aaru.CommonTypes.Interfaces; +using Aaru.Core; using Aaru.Helpers; using Aaru.Tui.Models; using Avalonia; @@ -8,6 +13,8 @@ using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Media; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; +using Humanizer; +using Humanizer.Bytes; using Color = Avalonia.Media.Color; namespace Aaru.Tui.ViewModels.Windows; @@ -51,6 +58,8 @@ public sealed partial class MainWindowViewModel : ViewModelBase OnPropertyChanged(nameof(SelectedFileLastWriteTime)); OnPropertyChanged(nameof(SelectedFileAttributes)); OnPropertyChanged(nameof(SelectedFileUnixMode)); + OnPropertyChanged(nameof(SelectedFileHasInformation)); + OnPropertyChanged(nameof(SelectedFileInformation)); } } @@ -63,6 +72,9 @@ public sealed partial class MainWindowViewModel : ViewModelBase public DateTime? SelectedFileLastWriteTime => SelectedFile?.FileInfo?.LastWriteTime; public string? SelectedFileAttributes => SelectedFile?.FileInfo?.Attributes.ToString(); public string? SelectedFileUnixMode => SelectedFile?.FileInfo?.UnixFileMode.ToString(); + public bool SelectedFileHasInformation => SelectedFile?.Information != null; + + public string? SelectedFileInformation => SelectedFile?.Information; void Exit() { @@ -129,7 +141,125 @@ public sealed partial class MainWindowViewModel : ViewModelBase void Worker() { - foreach(FileModel file in Files) file.FileInfo = new FileInfo(file.Path); + foreach(FileModel file in Files) + { + try + { + file.FileInfo = new FileInfo(file.Path); + + IFilter inputFilter = PluginRegister.Singleton.GetFilter(file.Path); + + if(inputFilter is null) continue; + + IBaseImage imageFormat = ImageFormat.Detect(inputFilter); + + if(imageFormat is null) continue; + + StringBuilder sb = new(); + + if(!string.IsNullOrWhiteSpace(imageFormat.Info.Version)) + sb.AppendLine($"Format: {imageFormat.Format} version {imageFormat.Info.Version}"); + else + sb.AppendLine($"Format: {imageFormat.Format}"); + + switch(string.IsNullOrWhiteSpace(imageFormat.Info.Application)) + { + case false when !string.IsNullOrWhiteSpace(imageFormat.Info.ApplicationVersion): + sb.AppendLine($"Was created with {imageFormat.Info.Application} version {imageFormat.Info.ApplicationVersion}"); + + break; + case false: + sb.AppendLine($"Was created with {imageFormat.Info.Application}"); + + break; + } + + sb.AppendLine($"Image without headers is {imageFormat.Info.ImageSize} bytes long"); + + sb.AppendLine($"Contains a media of {imageFormat.Info.Sectors} sectors with a maximum sector size of {imageFormat.Info.SectorSize} bytes (if all sectors are of the same size this would be [aqua]{ByteSize.FromBytes(imageFormat.Info.Sectors * imageFormat.Info.SectorSize).Humanize()})"); + + if(!string.IsNullOrWhiteSpace(imageFormat.Info.Creator)) + sb.AppendLine($"Created by: {imageFormat.Info.Creator}"); + + if(imageFormat.Info.CreationTime != DateTime.MinValue) + sb.AppendLine($"Created on {imageFormat.Info.CreationTime}"); + + if(imageFormat.Info.LastModificationTime != DateTime.MinValue) + sb.AppendLine($"Last modified on {imageFormat.Info.LastModificationTime}"); + + sb.AppendLine($"Contains a media of type {imageFormat.Info.MediaType} and XML type {imageFormat.Info.MetadataMediaType}"); + + sb.AppendLine(imageFormat.Info.HasPartitions ? "Has partitions" : "Doesn\'t have partitions"); + + sb.AppendLine(imageFormat.Info.HasSessions ? "Has sessions" : "Doesn\'t have sessions"); + + if(!string.IsNullOrWhiteSpace(imageFormat.Info.Comments)) + sb.AppendLine($"Comments: {imageFormat.Info.Comments}"); + + if(imageFormat.Info.MediaSequence != 0 && imageFormat.Info.LastMediaSequence != 0) + sb.AppendLine($"Media is number {imageFormat.Info.MediaSequence} on a set of {imageFormat.Info.LastMediaSequence} medias"); + + if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaTitle)) + sb.AppendLine($"Media title: {imageFormat.Info.MediaTitle}"); + + if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaManufacturer)) + sb.AppendLine($"Media manufacturer: {imageFormat.Info.MediaManufacturer}"); + + if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaModel)) + sb.AppendLine($"Media model: {imageFormat.Info.MediaModel}"); + + if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaSerialNumber)) + sb.AppendLine($"Media serial number: {imageFormat.Info.MediaSerialNumber}"); + + if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaBarcode)) + sb.AppendLine($"Media barcode: {imageFormat.Info.MediaBarcode}"); + + if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaPartNumber)) + sb.AppendLine($"Media part number: {imageFormat.Info.MediaPartNumber}"); + + if(!string.IsNullOrWhiteSpace(imageFormat.Info.DriveManufacturer)) + sb.AppendLine($"Drive manufacturer: {imageFormat.Info.DriveManufacturer}"); + + if(!string.IsNullOrWhiteSpace(imageFormat.Info.DriveModel)) + sb.AppendLine($"Drive model: {imageFormat.Info.DriveModel}"); + + if(!string.IsNullOrWhiteSpace(imageFormat.Info.DriveSerialNumber)) + sb.AppendLine($"Drive serial number: {imageFormat.Info.DriveSerialNumber}"); + + if(!string.IsNullOrWhiteSpace(imageFormat.Info.DriveFirmwareRevision)) + sb.AppendLine($"Drive firmware info: {imageFormat.Info.DriveFirmwareRevision}"); + + if(imageFormat.Info.Cylinders > 0 && + imageFormat.Info is { Heads: > 0, SectorsPerTrack: > 0 } && + imageFormat.Info.MetadataMediaType != MetadataMediaType.OpticalDisc && + imageFormat is not ITapeImage { IsTape: true }) + sb.AppendLine($"Media geometry: {imageFormat.Info.Cylinders} cylinders, {imageFormat.Info.Heads} heads, {imageFormat.Info.SectorsPerTrack} sectors per track"); + + if(imageFormat.Info.ReadableMediaTags is { Count: > 0 }) + { + sb.AppendLine($"Contains {imageFormat.Info.ReadableMediaTags.Count} readable media tags:"); + + foreach(MediaTagType tag in imageFormat.Info.ReadableMediaTags.Order()) sb.Append($"{tag} "); + + sb.AppendLine(); + } + + if(imageFormat.Info.ReadableSectorTags is { Count: > 0 }) + { + sb.AppendLine($"Contains {imageFormat.Info.ReadableSectorTags.Count} readable sector tags:"); + + foreach(SectorTagType tag in imageFormat.Info.ReadableSectorTags.Order()) sb.Append($"{tag} "); + + sb.AppendLine(); + } + + file.Information = sb.ToString(); + } + catch(Exception ex) + { + SentrySdk.CaptureException(ex); + } + } } void OpenSelectedFile() diff --git a/Aaru.Tui/Views/Windows/MainWindow.axaml b/Aaru.Tui/Views/Windows/MainWindow.axaml index ef909d605..8bf048daf 100644 --- a/Aaru.Tui/Views/Windows/MainWindow.axaml +++ b/Aaru.Tui/Views/Windows/MainWindow.axaml @@ -45,7 +45,7 @@ - @@ -136,6 +136,23 @@ + + + + + + + + + + +