diff --git a/Aaru.Gui/Aaru.Gui.csproj b/Aaru.Gui/Aaru.Gui.csproj
index da60d32a0..ac3fac63f 100644
--- a/Aaru.Gui/Aaru.Gui.csproj
+++ b/Aaru.Gui/Aaru.Gui.csproj
@@ -313,6 +313,10 @@
+
+ PublicResXFileCodeGenerator
+ GUI.Designer.cs
+
@@ -410,6 +414,11 @@
ViewSector.xaml
+
+ True
+ True
+ GUI.resx
+
diff --git a/Aaru.Gui/Localization/GUI.Designer.cs b/Aaru.Gui/Localization/GUI.Designer.cs
new file mode 100644
index 000000000..693eeeb62
--- /dev/null
+++ b/Aaru.Gui/Localization/GUI.Designer.cs
@@ -0,0 +1,654 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Aaru.Gui.Localization {
+ using System;
+
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ public class GUI {
+
+ private static System.Resources.ResourceManager resourceMan;
+
+ private static System.Globalization.CultureInfo resourceCulture;
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal GUI() {
+ }
+
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ public static System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.Equals(null, resourceMan)) {
+ System.Resources.ResourceManager temp = new System.Resources.ResourceManager("Aaru.Gui.Localization.GUI", typeof(GUI).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ public static System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ public static string Button_Save {
+ get {
+ return ResourceManager.GetString("Button.Save", resourceCulture);
+ }
+ }
+
+ public static string Button_Cancel {
+ get {
+ return ResourceManager.GetString("Button.Cancel", resourceCulture);
+ }
+ }
+
+ public static string Header_Basic_Information {
+ get {
+ return ResourceManager.GetString("Header.Basic_Information", resourceCulture);
+ }
+ }
+
+ public static string Header_General_Information {
+ get {
+ return ResourceManager.GetString("Header.General_Information", resourceCulture);
+ }
+ }
+
+ public static string Label_Name {
+ get {
+ return ResourceManager.GetString("Label.Name", resourceCulture);
+ }
+ }
+
+ public static string Watermark_Enter_name {
+ get {
+ return ResourceManager.GetString("Watermark.Enter_name", resourceCulture);
+ }
+ }
+
+ public static string Label_Version {
+ get {
+ return ResourceManager.GetString("Label.Version", resourceCulture);
+ }
+ }
+
+ public static string Watermark_Enter_version {
+ get {
+ return ResourceManager.GetString("Watermark.Enter_version", resourceCulture);
+ }
+ }
+
+ public static string Label_Release_type {
+ get {
+ return ResourceManager.GetString("Label.Release_type", resourceCulture);
+ }
+ }
+
+ public static string Placeholder_Select_release_type {
+ get {
+ return ResourceManager.GetString("Placeholder.Select_release_type", resourceCulture);
+ }
+ }
+
+ public static string Label_Release_Date {
+ get {
+ return ResourceManager.GetString("Label.Release_Date", resourceCulture);
+ }
+ }
+
+ public static string Label_Part_Number {
+ get {
+ return ResourceManager.GetString("Label.Part_Number", resourceCulture);
+ }
+ }
+
+ public static string Watermark_Enter_part_number {
+ get {
+ return ResourceManager.GetString("Watermark.Enter_part_number", resourceCulture);
+ }
+ }
+
+ public static string Label_Serial_Number {
+ get {
+ return ResourceManager.GetString("Label.Serial_Number", resourceCulture);
+ }
+ }
+
+ public static string Watermark_Enter_serial_number {
+ get {
+ return ResourceManager.GetString("Watermark.Enter_serial_number", resourceCulture);
+ }
+ }
+
+ public static string Header_People_and_Organizations {
+ get {
+ return ResourceManager.GetString("Header.People_and_Organizations", resourceCulture);
+ }
+ }
+
+ public static string Header_Developers {
+ get {
+ return ResourceManager.GetString("Header.Developers", resourceCulture);
+ }
+ }
+
+ public static string Button_Add_Developer {
+ get {
+ return ResourceManager.GetString("Button.Add_Developer", resourceCulture);
+ }
+ }
+
+ public static string Button_Remove {
+ get {
+ return ResourceManager.GetString("Button.Remove", resourceCulture);
+ }
+ }
+
+ public static string Watermark_Enter_developer_name {
+ get {
+ return ResourceManager.GetString("Watermark.Enter_developer_name", resourceCulture);
+ }
+ }
+
+ public static string Header_Publishers {
+ get {
+ return ResourceManager.GetString("Header.Publishers", resourceCulture);
+ }
+ }
+
+ public static string Button_Add_Publisher {
+ get {
+ return ResourceManager.GetString("Button.Add_Publisher", resourceCulture);
+ }
+ }
+
+ public static string Watermark_Enter_publisher_name {
+ get {
+ return ResourceManager.GetString("Watermark.Enter_publisher_name", resourceCulture);
+ }
+ }
+
+ public static string Header_Authors {
+ get {
+ return ResourceManager.GetString("Header.Authors", resourceCulture);
+ }
+ }
+
+ public static string Button_Add_Author {
+ get {
+ return ResourceManager.GetString("Button.Add_Author", resourceCulture);
+ }
+ }
+
+ public static string Watermark_Enter_author_name {
+ get {
+ return ResourceManager.GetString("Watermark.Enter_author_name", resourceCulture);
+ }
+ }
+
+ public static string Header_Performers {
+ get {
+ return ResourceManager.GetString("Header.Performers", resourceCulture);
+ }
+ }
+
+ public static string Button_Add_Performer {
+ get {
+ return ResourceManager.GetString("Button.Add_Performer", resourceCulture);
+ }
+ }
+
+ public static string Watermark_Enter_performer_name {
+ get {
+ return ResourceManager.GetString("Watermark.Enter_performer_name", resourceCulture);
+ }
+ }
+
+ public static string Header_Classification {
+ get {
+ return ResourceManager.GetString("Header.Classification", resourceCulture);
+ }
+ }
+
+ public static string Header_Keywords {
+ get {
+ return ResourceManager.GetString("Header.Keywords", resourceCulture);
+ }
+ }
+
+ public static string Button_Add_Keyword {
+ get {
+ return ResourceManager.GetString("Button.Add_Keyword", resourceCulture);
+ }
+ }
+
+ public static string Watermark_Enter_keyword {
+ get {
+ return ResourceManager.GetString("Watermark.Enter_keyword", resourceCulture);
+ }
+ }
+
+ public static string Header_Categories {
+ get {
+ return ResourceManager.GetString("Header.Categories", resourceCulture);
+ }
+ }
+
+ public static string Button_Add_Category {
+ get {
+ return ResourceManager.GetString("Button.Add_Category", resourceCulture);
+ }
+ }
+
+ public static string Watermark_Enter_category {
+ get {
+ return ResourceManager.GetString("Watermark.Enter_category", resourceCulture);
+ }
+ }
+
+ public static string Header_Subcategories {
+ get {
+ return ResourceManager.GetString("Header.Subcategories", resourceCulture);
+ }
+ }
+
+ public static string Button_Add_Subcategory {
+ get {
+ return ResourceManager.GetString("Button.Add_Subcategory", resourceCulture);
+ }
+ }
+
+ public static string Watermark_Enter_subcategory {
+ get {
+ return ResourceManager.GetString("Watermark.Enter_subcategory", resourceCulture);
+ }
+ }
+
+ public static string Header_Systems {
+ get {
+ return ResourceManager.GetString("Header.Systems", resourceCulture);
+ }
+ }
+
+ public static string Button_Add_System {
+ get {
+ return ResourceManager.GetString("Button.Add_System", resourceCulture);
+ }
+ }
+
+ public static string Watermark_Enter_system {
+ get {
+ return ResourceManager.GetString("Watermark.Enter_system", resourceCulture);
+ }
+ }
+
+ public static string Header_Technical_Details {
+ get {
+ return ResourceManager.GetString("Header.Technical_Details", resourceCulture);
+ }
+ }
+
+ public static string Header_Languages {
+ get {
+ return ResourceManager.GetString("Header.Languages", resourceCulture);
+ }
+ }
+
+ public static string Button_Add {
+ get {
+ return ResourceManager.GetString("Button.Add", resourceCulture);
+ }
+ }
+
+ public static string Placeholder_Select_language_to_add {
+ get {
+ return ResourceManager.GetString("Placeholder.Select_language_to_add", resourceCulture);
+ }
+ }
+
+ public static string Header_Architectures {
+ get {
+ return ResourceManager.GetString("Header.Architectures", resourceCulture);
+ }
+ }
+
+ public static string Placeholder_Select_architecture_to_add {
+ get {
+ return ResourceManager.GetString("Placeholder.Select_architecture_to_add", resourceCulture);
+ }
+ }
+
+ public static string Header_Required_Operating_Systems {
+ get {
+ return ResourceManager.GetString("Header.Required_Operating_Systems", resourceCulture);
+ }
+ }
+
+ public static string Button_Add_Operating_System {
+ get {
+ return ResourceManager.GetString("Button.Add_Operating_System", resourceCulture);
+ }
+ }
+
+ public static string Label_OS_Name {
+ get {
+ return ResourceManager.GetString("Label.OS_Name", resourceCulture);
+ }
+ }
+
+ public static string Watermark_Enter_OS_name {
+ get {
+ return ResourceManager.GetString("Watermark.Enter_OS_name", resourceCulture);
+ }
+ }
+
+ public static string Header_Barcodes {
+ get {
+ return ResourceManager.GetString("Header.Barcodes", resourceCulture);
+ }
+ }
+
+ public static string Button_Add_Barcode {
+ get {
+ return ResourceManager.GetString("Button.Add_Barcode", resourceCulture);
+ }
+ }
+
+ public static string Button_Remove_Barcode {
+ get {
+ return ResourceManager.GetString("Button.Remove_Barcode", resourceCulture);
+ }
+ }
+
+ public static string Label_Barcode_Type {
+ get {
+ return ResourceManager.GetString("Label.Barcode_Type", resourceCulture);
+ }
+ }
+
+ public static string Label_Value {
+ get {
+ return ResourceManager.GetString("Label.Value", resourceCulture);
+ }
+ }
+
+ public static string Watermark_Enter_barcode_value {
+ get {
+ return ResourceManager.GetString("Watermark.Enter_barcode_value", resourceCulture);
+ }
+ }
+
+ public static string Header_Publications {
+ get {
+ return ResourceManager.GetString("Header.Publications", resourceCulture);
+ }
+ }
+
+ public static string Header_Magazines {
+ get {
+ return ResourceManager.GetString("Header.Magazines", resourceCulture);
+ }
+ }
+
+ public static string Button_Add_Magazine {
+ get {
+ return ResourceManager.GetString("Button.Add_Magazine", resourceCulture);
+ }
+ }
+
+ public static string Label_Editorial {
+ get {
+ return ResourceManager.GetString("Label.Editorial", resourceCulture);
+ }
+ }
+
+ public static string Label_Number {
+ get {
+ return ResourceManager.GetString("Label.Number", resourceCulture);
+ }
+ }
+
+ public static string Label_Pages {
+ get {
+ return ResourceManager.GetString("Label.Pages", resourceCulture);
+ }
+ }
+
+ public static string Header_Books {
+ get {
+ return ResourceManager.GetString("Header.Books", resourceCulture);
+ }
+ }
+
+ public static string Button_Add_Book {
+ get {
+ return ResourceManager.GetString("Button.Add_Book", resourceCulture);
+ }
+ }
+
+ public static string Label_Author {
+ get {
+ return ResourceManager.GetString("Label.Author", resourceCulture);
+ }
+ }
+
+ public static string Header_User_Manuals {
+ get {
+ return ResourceManager.GetString("Header.User_Manuals", resourceCulture);
+ }
+ }
+
+ public static string Button_Add_User_Manual {
+ get {
+ return ResourceManager.GetString("Button.Add_User_Manual", resourceCulture);
+ }
+ }
+
+ public static string Label_Page_Size {
+ get {
+ return ResourceManager.GetString("Label.Page_Size", resourceCulture);
+ }
+ }
+
+ public static string Header_Media {
+ get {
+ return ResourceManager.GetString("Header.Media", resourceCulture);
+ }
+ }
+
+ public static string Header_Optical_Discs {
+ get {
+ return ResourceManager.GetString("Header.Optical_Discs", resourceCulture);
+ }
+ }
+
+ public static string Button_Add_Optical_Disc {
+ get {
+ return ResourceManager.GetString("Button.Add_Optical_Disc", resourceCulture);
+ }
+ }
+
+ public static string Label_Disc_Type {
+ get {
+ return ResourceManager.GetString("Label.Disc_Type", resourceCulture);
+ }
+ }
+
+ public static string Label_Disc_SubType {
+ get {
+ return ResourceManager.GetString("Label.Disc_SubType", resourceCulture);
+ }
+ }
+
+ public static string Header_Block_Media {
+ get {
+ return ResourceManager.GetString("Header.Block_Media", resourceCulture);
+ }
+ }
+
+ public static string Button_Add_Block_Media {
+ get {
+ return ResourceManager.GetString("Button.Add_Block_Media", resourceCulture);
+ }
+ }
+
+ public static string Label_Manufacturer {
+ get {
+ return ResourceManager.GetString("Label.Manufacturer", resourceCulture);
+ }
+ }
+
+ public static string Label_Serial {
+ get {
+ return ResourceManager.GetString("Label.Serial", resourceCulture);
+ }
+ }
+
+ public static string Label_Model {
+ get {
+ return ResourceManager.GetString("Label.Model", resourceCulture);
+ }
+ }
+
+ public static string Label_Firmware {
+ get {
+ return ResourceManager.GetString("Label.Firmware", resourceCulture);
+ }
+ }
+
+ public static string Header_Linear_Media {
+ get {
+ return ResourceManager.GetString("Header.Linear_Media", resourceCulture);
+ }
+ }
+
+ public static string Button_Add_Linear_Media {
+ get {
+ return ResourceManager.GetString("Button.Add_Linear_Media", resourceCulture);
+ }
+ }
+
+ public static string Header_Audio_Media {
+ get {
+ return ResourceManager.GetString("Header.Audio_Media", resourceCulture);
+ }
+ }
+
+ public static string Button_Add_Audio_Media {
+ get {
+ return ResourceManager.GetString("Button.Add_Audio_Media", resourceCulture);
+ }
+ }
+
+ public static string Header_Hardware {
+ get {
+ return ResourceManager.GetString("Header.Hardware", resourceCulture);
+ }
+ }
+
+ public static string Header_PCI_Cards {
+ get {
+ return ResourceManager.GetString("Header.PCI_Cards", resourceCulture);
+ }
+ }
+
+ public static string Button_Add_PCI_Card {
+ get {
+ return ResourceManager.GetString("Button.Add_PCI_Card", resourceCulture);
+ }
+ }
+
+ public static string Label_Vendor_ID {
+ get {
+ return ResourceManager.GetString("Label.Vendor_ID", resourceCulture);
+ }
+ }
+
+ public static string Label_Device_ID {
+ get {
+ return ResourceManager.GetString("Label.Device_ID", resourceCulture);
+ }
+ }
+
+ public static string Header_Advertisements {
+ get {
+ return ResourceManager.GetString("Header.Advertisements", resourceCulture);
+ }
+ }
+
+ public static string Button_Add_Advertisement {
+ get {
+ return ResourceManager.GetString("Button.Add_Advertisement", resourceCulture);
+ }
+ }
+
+ public static string Label_Product {
+ get {
+ return ResourceManager.GetString("Label.Product", resourceCulture);
+ }
+ }
+
+ public static string Title_Create_Metadata {
+ get {
+ return ResourceManager.GetString("Title.Create_Metadata", resourceCulture);
+ }
+ }
+
+ public static string Title_Edit_Metadata {
+ get {
+ return ResourceManager.GetString("Title.Edit_Metadata", resourceCulture);
+ }
+ }
+
+ public static string Error_Loading_metadata {
+ get {
+ return ResourceManager.GetString("Error.Loading_metadata", resourceCulture);
+ }
+ }
+
+ public static string Dialog_Save_Metadata_File {
+ get {
+ return ResourceManager.GetString("Dialog.Save_Metadata_File", resourceCulture);
+ }
+ }
+
+ public static string FileType_JSON {
+ get {
+ return ResourceManager.GetString("FileType.JSON", resourceCulture);
+ }
+ }
+
+ public static string Title_Success {
+ get {
+ return ResourceManager.GetString("Title.Success", resourceCulture);
+ }
+ }
+
+ public static string Message_Metadata_saved_successfully {
+ get {
+ return ResourceManager.GetString("Message.Metadata_saved_successfully", resourceCulture);
+ }
+ }
+
+ public static string Error_Saving_metadata {
+ get {
+ return ResourceManager.GetString("Error.Saving_metadata", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/Aaru.Gui/Localization/GUI.es.resx b/Aaru.Gui/Localization/GUI.es.resx
new file mode 100644
index 000000000..6a88515fa
--- /dev/null
+++ b/Aaru.Gui/Localization/GUI.es.resx
@@ -0,0 +1,332 @@
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 1.3
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
+ PublicKeyToken=b77a5c561934e089
+
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
+ PublicKeyToken=b77a5c561934e089
+
+
+
+ Guardar
+
+
+ Cancelar
+
+
+ Información Básica
+
+
+ Información General
+
+
+ Nombre:
+
+
+ Introducir nombre...
+
+
+ Versión:
+
+
+ Introducir versión...
+
+
+ Tipo de Lanzamiento:
+
+
+ Seleccionar tipo de lanzamiento...
+
+
+ Fecha de Lanzamiento:
+
+
+ Número de Pieza:
+
+
+ Introducir número de pieza...
+
+
+ Número de Serie:
+
+
+ Introducir número de serie...
+
+
+ Personas y Organizaciones
+
+
+ Desarrolladores
+
+
+ + Agregar Desarrollador
+
+
+ Eliminar
+
+
+ Introducir nombre del desarrollador...
+
+
+ Editores
+
+
+ + Agregar Editor
+
+
+ Introducir nombre del editor...
+
+
+ Autores
+
+
+ + Agregar Autor
+
+
+ Introducir nombre del autor...
+
+
+ Intérpretes
+
+
+ + Agregar Intérprete
+
+
+ Introducir nombre del intérprete...
+
+
+ Clasificación
+
+
+ Palabras Clave
+
+
+ + Agregar Palabra Clave
+
+
+ Introducir palabra clave...
+
+
+ Categorías
+
+
+ + Agregar Categoría
+
+
+ Introducir categoría...
+
+
+ Subcategorías
+
+
+ + Agregar Subcategoría
+
+
+ Introducir subcategoría...
+
+
+ Sistemas
+
+
+ + Agregar Sistema
+
+
+ Introducir sistema...
+
+
+ Detalles Técnicos
+
+
+ Idiomas
+
+
+ Agregar
+
+
+ Seleccionar idioma para agregar...
+
+
+ Arquitecturas
+
+
+ Seleccionar arquitectura para agregar...
+
+
+ Sistemas Operativos Requeridos
+
+
+ + Agregar Sistema Operativo
+
+
+ Nombre del SO:
+
+
+ Introducir nombre del SO...
+
+
+ Códigos de Barras
+
+
+ + Agregar Código de Barras
+
+
+ Eliminar Código de Barras
+
+
+ Tipo de Código de Barras:
+
+
+ Valor:
+
+
+ Introducir valor del código de barras...
+
+
+ Publicaciones
+
+
+ Revistas
+
+
+ + Agregar Revista
+
+
+ Editorial:
+
+
+ Número:
+
+
+ Páginas:
+
+
+ Libros
+
+
+ + Agregar Libro
+
+
+ Autor:
+
+
+ Manuales de Usuario
+
+
+ + Agregar Manual de Usuario
+
+
+ Tamaño de Página:
+
+
+ Medios
+
+
+ Discos Ópticos
+
+
+ + Agregar Disco Óptico
+
+
+ Tipo de Disco:
+
+
+ Subtipo de Disco:
+
+
+ Medios de Bloques
+
+
+ + Agregar Medio de Bloques
+
+
+ Fabricante:
+
+
+ Serie:
+
+
+ Modelo:
+
+
+ Firmware:
+
+
+ Medios Lineales
+
+
+ + Agregar Medio Lineal
+
+
+ Medios de Audio
+
+
+ + Agregar Medio de Audio
+
+
+ Hardware
+
+
+ Tarjetas PCI
+
+
+ + Agregar Tarjeta PCI
+
+
+ ID de Proveedor:
+
+
+ ID de Dispositivo:
+
+
+ Anuncios
+
+
+ + Agregar Anuncio
+
+
+ Producto:
+
+
+ Crear Metadatos
+
+
+ Editar Metadatos
+
+
+ Error al cargar metadatos: {0}
+
+
+ Guardar Archivo de Metadatos
+
+
+ JSON
+
+
+ Éxito
+
+
+ Metadatos guardados correctamente
+
+
+ Error al guardar metadatos: {0}
+
+
+
diff --git a/Aaru.Gui/Localization/GUI.resx b/Aaru.Gui/Localization/GUI.resx
new file mode 100644
index 000000000..6695673b4
--- /dev/null
+++ b/Aaru.Gui/Localization/GUI.resx
@@ -0,0 +1,331 @@
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 1.3
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
+ PublicKeyToken=b77a5c561934e089
+
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
+ PublicKeyToken=b77a5c561934e089
+
+
+
+ Save
+
+
+ Cancel
+
+
+ Basic Information
+
+
+ General Information
+
+
+ Name:
+
+
+ Enter name...
+
+
+ Version:
+
+
+ Enter version...
+
+
+ Release Type:
+
+
+ Select release type...
+
+
+ Release Date:
+
+
+ Part Number:
+
+
+ Enter part number...
+
+
+ Serial Number:
+
+
+ Enter serial number...
+
+
+ People & Organizations
+
+
+ Developers
+
+
+ + Add Developer
+
+
+ Remove
+
+
+ Enter developer name...
+
+
+ Publishers
+
+
+ + Add Publisher
+
+
+ Enter publisher name...
+
+
+ Authors
+
+
+ + Add Author
+
+
+ Enter author name...
+
+
+ Performers
+
+
+ + Add Performer
+
+
+ Enter performer name...
+
+
+ Classification
+
+
+ Keywords
+
+
+ + Add Keyword
+
+
+ Enter keyword...
+
+
+ Categories
+
+
+ + Add Category
+
+
+ Enter category...
+
+
+ Subcategories
+
+
+ + Add Subcategory
+
+
+ Enter subcategory...
+
+
+ Systems
+
+
+ + Add System
+
+
+ Enter system...
+
+
+ Technical Details
+
+
+ Languages
+
+
+ Add
+
+
+ Select language to add...
+
+
+ Architectures
+
+
+ Select architecture to add...
+
+
+ Required Operating Systems
+
+
+ + Add Operating System
+
+
+ OS Name:
+
+
+ Enter OS name...
+
+
+ Barcodes
+
+
+ + Add Barcode
+
+
+ Remove Barcode
+
+
+ Barcode Type:
+
+
+ Value:
+
+
+ Enter barcode value...
+
+
+ Publications
+
+
+ Magazines
+
+
+ + Add Magazine
+
+
+ Editorial:
+
+
+ Number:
+
+
+ Pages:
+
+
+ Books
+
+
+ + Add Book
+
+
+ Author:
+
+
+ User Manuals
+
+
+ + Add User Manual
+
+
+ Page Size:
+
+
+ Media
+
+
+ Optical Discs
+
+
+ + Add Optical Disc
+
+
+ Disc Type:
+
+
+ Disc SubType:
+
+
+ Block Media
+
+
+ + Add Block Media
+
+
+ Manufacturer:
+
+
+ Serial:
+
+
+ Model:
+
+
+ Firmware:
+
+
+ Linear Media
+
+
+ + Add Linear Media
+
+
+ Audio Media
+
+
+ + Add Audio Media
+
+
+ Hardware
+
+
+ PCI Cards
+
+
+ + Add PCI Card
+
+
+ Vendor ID:
+
+
+ Device ID:
+
+
+ Advertisements
+
+
+ + Add Advertisement
+
+
+ Product:
+
+
+ Create Metadata
+
+
+ Edit Metadata
+
+
+ Error loading metadata: {0}
+
+
+ Save Metadata File
+
+
+ JSON
+
+
+ Success
+
+
+ Metadata saved successfully
+
+
+ Error saving metadata: {0}
+
+
\ No newline at end of file
diff --git a/Aaru.Gui/ViewModels/Dialogs/ConsoleViewModel.cs b/Aaru.Gui/ViewModels/Dialogs/ConsoleViewModel.cs
index af9c82b95..8d4826326 100644
--- a/Aaru.Gui/ViewModels/Dialogs/ConsoleViewModel.cs
+++ b/Aaru.Gui/ViewModels/Dialogs/ConsoleViewModel.cs
@@ -98,7 +98,7 @@ public sealed class ConsoleViewModel : ViewModelBase
typeof(AssemblyInformationalVersionAttribute)) as
AssemblyInformationalVersionAttribute;
- await logSw.WriteLineAsync(Localization.Core.System_information);
+ await logSw.WriteLineAsync(Aaru.Localization.Core.System_information);
await
logSw.WriteLineAsync($"{DetectOS.GetPlatformName(platId, platVer)} {platVer} ({(Environment.Is64BitOperatingSystem ? 64 : 32)}-bit)");
@@ -107,15 +107,15 @@ public sealed class ConsoleViewModel : ViewModelBase
await logSw.WriteLineAsync();
- await logSw.WriteLineAsync(Localization.Core.Program_information);
+ await logSw.WriteLineAsync(Aaru.Localization.Core.Program_information);
await logSw.WriteLineAsync($"Aaru {assemblyVersion?.InformationalVersion}");
- await logSw.WriteLineAsync(string.Format(Localization.Core.Running_in_0_bit,
+ await logSw.WriteLineAsync(string.Format(Aaru.Localization.Core.Running_in_0_bit,
Environment.Is64BitProcess ? 64 : 32));
#if DEBUG
- await logSw.WriteLineAsync(Localization.Core.DEBUG_version);
+ await logSw.WriteLineAsync(Aaru.Localization.Core.DEBUG_version);
#endif
- await logSw.WriteLineAsync(string.Format(Localization.Core.Command_line_0, Environment.CommandLine));
+ await logSw.WriteLineAsync(string.Format(Aaru.Localization.Core.Command_line_0, Environment.CommandLine));
await logSw.WriteLineAsync();
await logSw.WriteLineAsync(UI.Console_with_ornament);
diff --git a/Aaru.Gui/ViewModels/Panels/FileSystemViewModel.cs b/Aaru.Gui/ViewModels/Panels/FileSystemViewModel.cs
index 5a99c16ea..591cff6bf 100644
--- a/Aaru.Gui/ViewModels/Panels/FileSystemViewModel.cs
+++ b/Aaru.Gui/ViewModels/Panels/FileSystemViewModel.cs
@@ -37,51 +37,52 @@ namespace Aaru.Gui.ViewModels.Panels;
public sealed class FileSystemViewModel([NotNull] FileSystem metadata, string information)
{
- public string TypeText { get; } = string.Format(Localization.Core.Filesystem_type_0, metadata.Type);
- public string VolumeNameText { get; } = string.Format(Localization.Core.Volume_name_0, metadata.VolumeName);
- public string SerialNumberText { get; } = string.Format(Localization.Core.Volume_serial_0, metadata.VolumeSerial);
+ public string TypeText { get; } = string.Format(Aaru.Localization.Core.Filesystem_type_0, metadata.Type);
+ public string VolumeNameText { get; } = string.Format(Aaru.Localization.Core.Volume_name_0, metadata.VolumeName);
+ public string SerialNumberText { get; } =
+ string.Format(Aaru.Localization.Core.Volume_serial_0, metadata.VolumeSerial);
public string ApplicationIdentifierText { get; } =
- string.Format(Localization.Core.Application_identifier_0, metadata.ApplicationIdentifier);
+ string.Format(Aaru.Localization.Core.Application_identifier_0, metadata.ApplicationIdentifier);
public string SystemIdentifierText { get; } =
- string.Format(Localization.Core.System_identifier_0, metadata.SystemIdentifier);
+ string.Format(Aaru.Localization.Core.System_identifier_0, metadata.SystemIdentifier);
public string VolumeSetIdentifierText { get; } =
- string.Format(Localization.Core.Volume_set_identifier_0, metadata.VolumeSetIdentifier);
+ string.Format(Aaru.Localization.Core.Volume_set_identifier_0, metadata.VolumeSetIdentifier);
public string DataPreparerIdentifierText { get; } =
- string.Format(Localization.Core.Data_preparer_identifier_0, metadata.DataPreparerIdentifier);
+ string.Format(Aaru.Localization.Core.Data_preparer_identifier_0, metadata.DataPreparerIdentifier);
public string PublisherIdentifierText { get; } =
- string.Format(Localization.Core.Publisher_identifier_0, metadata.PublisherIdentifier);
+ string.Format(Aaru.Localization.Core.Publisher_identifier_0, metadata.PublisherIdentifier);
public string CreationDateText { get; } =
- string.Format(Localization.Core.Volume_created_on_0, metadata.CreationDate);
+ string.Format(Aaru.Localization.Core.Volume_created_on_0, metadata.CreationDate);
public string EffectiveDateText { get; } =
- string.Format(Localization.Core.Volume_effective_from_0, metadata.EffectiveDate);
+ string.Format(Aaru.Localization.Core.Volume_effective_from_0, metadata.EffectiveDate);
public string ModificationDateText { get; } =
- string.Format(Localization.Core.Volume_last_modified_on_0, metadata.ModificationDate);
+ string.Format(Aaru.Localization.Core.Volume_last_modified_on_0, metadata.ModificationDate);
public string ExpirationDateText { get; } =
- string.Format(Localization.Core.Volume_expired_on_0, metadata.ExpirationDate);
+ string.Format(Aaru.Localization.Core.Volume_expired_on_0, metadata.ExpirationDate);
public string BackupDateText { get; } =
- string.Format(Localization.Core.Volume_last_backed_up_on_0, metadata.BackupDate);
+ string.Format(Aaru.Localization.Core.Volume_last_backed_up_on_0, metadata.BackupDate);
public string ClustersText { get; } =
- string.Format(Localization.Core.Volume_has_0_clusters_of_1_bytes_each_total_of_2_bytes,
+ string.Format(Aaru.Localization.Core.Volume_has_0_clusters_of_1_bytes_each_total_of_2_bytes,
metadata.Clusters,
metadata.ClusterSize,
metadata.Clusters * metadata.ClusterSize);
- public string FreeClustersText { get; } = string.Format(Localization.Core.Volume_has_0_clusters_free_1,
+ public string FreeClustersText { get; } = string.Format(Aaru.Localization.Core.Volume_has_0_clusters_free_1,
metadata.FreeClusters,
metadata.FreeClusters / metadata.Clusters);
- public string FilesText { get; } = string.Format(Localization.Core.Volume_contains_0_files, metadata.Files);
+ public string FilesText { get; } = string.Format(Aaru.Localization.Core.Volume_contains_0_files, metadata.Files);
public bool BootableChecked { get; } = metadata.Bootable;
public bool DirtyChecked { get; } = metadata.Dirty;
public string InformationText { get; } = information;
diff --git a/Aaru.Gui/ViewModels/Panels/ImageInfoViewModel.cs b/Aaru.Gui/ViewModels/Panels/ImageInfoViewModel.cs
index 66613d7df..e7c7746b3 100644
--- a/Aaru.Gui/ViewModels/Panels/ImageInfoViewModel.cs
+++ b/Aaru.Gui/ViewModels/Panels/ImageInfoViewModel.cs
@@ -123,109 +123,113 @@ public sealed class ImageInfoViewModel : ViewModelBase
ImageIdentifiedText = string.Format(UI.Image_format_identified_by_0_1, imageFormat.Name, imageFormat.Id);
ImageFormatText = !string.IsNullOrWhiteSpace(imageFormat.Info.Version)
- ? string.Format(Localization.Core.Format_0_version_1_WithMarkup,
+ ? string.Format(Aaru.Localization.Core.Format_0_version_1_WithMarkup,
imageFormat.Format,
imageFormat.Info.Version)
- : string.Format(Localization.Core.Format_0_WithMarkup, imageFormat.Format);
+ : string.Format(Aaru.Localization.Core.Format_0_WithMarkup, imageFormat.Format);
- ImageSizeText = string.Format(Localization.Core.Image_without_headers_is_0_bytes_long,
+ ImageSizeText = string.Format(Aaru.Localization.Core.Image_without_headers_is_0_bytes_long,
imageFormat.Info.ImageSize);
SectorsText =
- string.Format(Localization.Core.Contains_a_media_of_0_sectors_with_a_maximum_sector_size_of_1_bytes_etc,
+ string.Format(Aaru.Localization.Core
+ .Contains_a_media_of_0_sectors_with_a_maximum_sector_size_of_1_bytes_etc,
imageFormat.Info.Sectors,
imageFormat.Info.SectorSize,
ByteSize.FromBytes(imageFormat.Info.Sectors * imageFormat.Info.SectorSize).Humanize());
- MediaTypeText = string.Format(Localization.Core.Contains_a_media_of_type_0_and_XML_type_1_WithMarkup,
+ MediaTypeText = string.Format(Aaru.Localization.Core.Contains_a_media_of_type_0_and_XML_type_1_WithMarkup,
imageFormat.Info.MediaType.Humanize(),
imageFormat.Info.MetadataMediaType);
HasPartitionsText = imageFormat.Info.HasPartitions
- ? Localization.Core.Has_partitions
- : Localization.Core.Doesnt_have_partitions;
+ ? Aaru.Localization.Core.Has_partitions
+ : Aaru.Localization.Core.Doesnt_have_partitions;
HasSessionsText = imageFormat.Info.HasSessions
- ? Localization.Core.Has_sessions
- : Localization.Core.Doesnt_have_sessions;
+ ? Aaru.Localization.Core.Has_sessions
+ : Aaru.Localization.Core.Doesnt_have_sessions;
if(!string.IsNullOrWhiteSpace(imageFormat.Info.Application))
{
ApplicationText = !string.IsNullOrWhiteSpace(imageFormat.Info.ApplicationVersion)
- ? string.Format(Localization.Core.Was_created_with_0_version_1_WithMarkup,
+ ? string.Format(Aaru.Localization.Core.Was_created_with_0_version_1_WithMarkup,
imageFormat.Info.Application,
imageFormat.Info.ApplicationVersion)
- : string.Format(Localization.Core.Was_created_with_0_WithMarkup,
+ : string.Format(Aaru.Localization.Core.Was_created_with_0_WithMarkup,
imageFormat.Info.Application);
}
if(!string.IsNullOrWhiteSpace(imageFormat.Info.Creator))
- CreatorText = string.Format(Localization.Core.Created_by_0_WithMarkup, imageFormat.Info.Creator);
+ CreatorText = string.Format(Aaru.Localization.Core.Created_by_0_WithMarkup, imageFormat.Info.Creator);
if(imageFormat.Info.CreationTime != DateTime.MinValue)
- CreationTimeText = string.Format(Localization.Core.Created_on_0, imageFormat.Info.CreationTime);
+ CreationTimeText = string.Format(Aaru.Localization.Core.Created_on_0, imageFormat.Info.CreationTime);
if(imageFormat.Info.LastModificationTime != DateTime.MinValue)
{
LastModificationTimeText =
- string.Format(Localization.Core.Last_modified_on_0, imageFormat.Info.LastModificationTime);
+ string.Format(Aaru.Localization.Core.Last_modified_on_0, imageFormat.Info.LastModificationTime);
}
if(imageFormat.Info.MediaSequence != 0 && imageFormat.Info.LastMediaSequence != 0)
{
- MediaSequenceText = string.Format(Localization.Core.Media_is_number_0_on_a_set_of_1_medias,
+ MediaSequenceText = string.Format(Aaru.Localization.Core.Media_is_number_0_on_a_set_of_1_medias,
imageFormat.Info.MediaSequence,
imageFormat.Info.LastMediaSequence);
}
if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaTitle))
- MediaTitleText = string.Format(Localization.Core.Media_title_0_WithMarkup, imageFormat.Info.MediaTitle);
+ MediaTitleText =
+ string.Format(Aaru.Localization.Core.Media_title_0_WithMarkup, imageFormat.Info.MediaTitle);
if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaManufacturer))
{
- MediaManufacturerText = string.Format(Localization.Core.Media_manufacturer_0_WithMarkup,
+ MediaManufacturerText = string.Format(Aaru.Localization.Core.Media_manufacturer_0_WithMarkup,
imageFormat.Info.MediaManufacturer);
}
if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaModel))
- MediaModelText = string.Format(Localization.Core.Media_model_0_WithMarkup, imageFormat.Info.MediaModel);
+ MediaModelText =
+ string.Format(Aaru.Localization.Core.Media_model_0_WithMarkup, imageFormat.Info.MediaModel);
if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaSerialNumber))
{
- MediaSerialNumberText = string.Format(Localization.Core.Media_serial_number_0_WithMarkup,
+ MediaSerialNumberText = string.Format(Aaru.Localization.Core.Media_serial_number_0_WithMarkup,
imageFormat.Info.MediaSerialNumber);
}
if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaBarcode))
{
- MediaBarcodeText =
- string.Format(Localization.Core.Media_barcode_0_WithMarkup, imageFormat.Info.MediaBarcode);
+ MediaBarcodeText = string.Format(Aaru.Localization.Core.Media_barcode_0_WithMarkup,
+ imageFormat.Info.MediaBarcode);
}
if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaPartNumber))
{
- MediaPartNumberText = string.Format(Localization.Core.Media_part_number_0_WithMarkup,
+ MediaPartNumberText = string.Format(Aaru.Localization.Core.Media_part_number_0_WithMarkup,
imageFormat.Info.MediaPartNumber);
}
if(!string.IsNullOrWhiteSpace(imageFormat.Info.DriveManufacturer))
{
- DriveManufacturerText = string.Format(Localization.Core.Drive_manufacturer_0_WithMarkup,
+ DriveManufacturerText = string.Format(Aaru.Localization.Core.Drive_manufacturer_0_WithMarkup,
imageFormat.Info.DriveManufacturer);
}
if(!string.IsNullOrWhiteSpace(imageFormat.Info.DriveModel))
- DriveModelText = string.Format(Localization.Core.Drive_model_0_WithMarkup, imageFormat.Info.DriveModel);
+ DriveModelText =
+ string.Format(Aaru.Localization.Core.Drive_model_0_WithMarkup, imageFormat.Info.DriveModel);
if(!string.IsNullOrWhiteSpace(imageFormat.Info.DriveSerialNumber))
{
- DriveSerialNumberText = string.Format(Localization.Core.Drive_serial_number_0_WithMarkup,
+ DriveSerialNumberText = string.Format(Aaru.Localization.Core.Drive_serial_number_0_WithMarkup,
imageFormat.Info.DriveSerialNumber);
}
if(!string.IsNullOrWhiteSpace(imageFormat.Info.DriveFirmwareRevision))
{
- DriveFirmwareRevisionText = string.Format(Localization.Core.Drive_firmware_info_0_WithMarkup,
+ DriveFirmwareRevisionText = string.Format(Aaru.Localization.Core.Drive_firmware_info_0_WithMarkup,
imageFormat.Info.DriveFirmwareRevision);
}
@@ -241,9 +245,8 @@ public sealed class ImageInfoViewModel : ViewModelBase
}
if(imageFormat.Info.ReadableMediaTags is { Count: > 0 })
- {
- foreach(MediaTagType tag in imageFormat.Info.ReadableMediaTags.Order()) MediaTagsList.Add(tag.Humanize());
- }
+ foreach(MediaTagType tag in imageFormat.Info.ReadableMediaTags.Order())
+ MediaTagsList.Add(tag.Humanize());
if(imageFormat.Info.ReadableSectorTags is { Count: > 0 })
{
@@ -762,8 +765,9 @@ public sealed class ImageInfoViewModel : ViewModelBase
try
{
if(opticalMediaImage.Sessions is { Count: > 0 })
- foreach(Session session in opticalMediaImage.Sessions)
- Sessions.Add(session);
+ {
+ foreach(Session session in opticalMediaImage.Sessions) Sessions.Add(session);
+ }
}
catch(Exception ex)
{
@@ -773,8 +777,9 @@ public sealed class ImageInfoViewModel : ViewModelBase
try
{
if(opticalMediaImage.Tracks is { Count: > 0 })
- foreach(Track track in opticalMediaImage.Tracks)
- Tracks.Add(track);
+ {
+ foreach(Track track in opticalMediaImage.Tracks) Tracks.Add(track);
+ }
}
catch(Exception ex)
{
diff --git a/Aaru.Gui/ViewModels/Panels/PartitionViewModel.cs b/Aaru.Gui/ViewModels/Panels/PartitionViewModel.cs
index 35c6b9924..19481fa56 100644
--- a/Aaru.Gui/ViewModels/Panels/PartitionViewModel.cs
+++ b/Aaru.Gui/ViewModels/Panels/PartitionViewModel.cs
@@ -36,16 +36,17 @@ namespace Aaru.Gui.ViewModels.Panels;
public sealed class PartitionViewModel(Partition partition)
{
- public string NameText { get; } = string.Format(Localization.Core.Partition_name_0, partition.Name);
- public string TypeText { get; } = string.Format(Localization.Core.Partition_type_0, partition.Type);
+ public string NameText { get; } = string.Format(Aaru.Localization.Core.Partition_name_0, partition.Name);
+ public string TypeText { get; } = string.Format(Aaru.Localization.Core.Partition_type_0, partition.Type);
- public string StartText { get; } =
- string.Format(Localization.Core.Partition_start_sector_0_byte_1, partition.Start, partition.Offset);
+ public string StartText { get; } = string.Format(Aaru.Localization.Core.Partition_start_sector_0_byte_1,
+ partition.Start,
+ partition.Offset);
- public string LengthText { get; } = string.Format(Localization.Core.Partition_length_0_sectors_1_bytes,
+ public string LengthText { get; } = string.Format(Aaru.Localization.Core.Partition_length_0_sectors_1_bytes,
partition.Length,
partition.Size);
- public string DescriptionLabelText { get; } = Localization.Core.Title_Partition_description;
+ public string DescriptionLabelText { get; } = Aaru.Localization.Core.Title_Partition_description;
public string DescriptionText { get; } = partition.Description;
}
\ No newline at end of file
diff --git a/Aaru.Gui/ViewModels/Tabs/AtaInfoViewModel.cs b/Aaru.Gui/ViewModels/Tabs/AtaInfoViewModel.cs
index 4a9e77e80..23d805f21 100644
--- a/Aaru.Gui/ViewModels/Tabs/AtaInfoViewModel.cs
+++ b/Aaru.Gui/ViewModels/Tabs/AtaInfoViewModel.cs
@@ -70,12 +70,12 @@ public sealed class AtaInfoViewModel : ViewModelBase
{
AtaMcptText = (ataMcptError.Value.DeviceHead & 0x7) switch
{
- 0 => Localization.Core.Device_reports_incorrect_media_card_type,
- 1 => Localization.Core.Device_contains_SD_card,
- 2 => Localization.Core.Device_contains_MMC,
- 3 => Localization.Core.Device_contains_SDIO_card,
- 4 => Localization.Core.Device_contains_SM_card,
- _ => string.Format(Localization.Core.Device_contains_unknown_media_card_type_0,
+ 0 => Aaru.Localization.Core.Device_reports_incorrect_media_card_type,
+ 1 => Aaru.Localization.Core.Device_contains_SD_card,
+ 2 => Aaru.Localization.Core.Device_contains_MMC,
+ 3 => Aaru.Localization.Core.Device_contains_SDIO_card,
+ 4 => Aaru.Localization.Core.Device_contains_SM_card,
+ _ => string.Format(Aaru.Localization.Core.Device_contains_unknown_media_card_type_0,
ataMcptError.Value.DeviceHead & 0x07)
};
@@ -83,7 +83,7 @@ public sealed class AtaInfoViewModel : ViewModelBase
var specificData = (ushort)(ataMcptError.Value.CylinderHigh * 0x100 + ataMcptError.Value.CylinderLow);
- AtaMcptSpecificDataText = string.Format(Localization.Core.Card_specific_data_0, specificData);
+ AtaMcptSpecificDataText = string.Format(Aaru.Localization.Core.Card_specific_data_0, specificData);
}
AtaIdentifyText = Identify.Prettify(_ata);
diff --git a/Aaru.Gui/ViewModels/Tabs/PcmciaInfoViewModel.cs b/Aaru.Gui/ViewModels/Tabs/PcmciaInfoViewModel.cs
index b1c5588dd..7391521c9 100644
--- a/Aaru.Gui/ViewModels/Tabs/PcmciaInfoViewModel.cs
+++ b/Aaru.Gui/ViewModels/Tabs/PcmciaInfoViewModel.cs
@@ -135,8 +135,10 @@ public sealed partial class PcmciaInfoViewModel : ViewModelBase
break;
default:
- tupleCode = $"0x{(byte)tuple.Code:X2}";
- tupleDescription = string.Format(Localization.Core.Found_unknown_tuple_ID_0, (byte)tuple.Code);
+ tupleCode = $"0x{(byte)tuple.Code:X2}";
+
+ tupleDescription =
+ string.Format(Aaru.Localization.Core.Found_unknown_tuple_ID_0, (byte)tuple.Code);
break;
}
diff --git a/Aaru.Gui/ViewModels/Tabs/ScsiInfoViewModel.cs b/Aaru.Gui/ViewModels/Tabs/ScsiInfoViewModel.cs
index 1ca8ac068..44f232488 100644
--- a/Aaru.Gui/ViewModels/Tabs/ScsiInfoViewModel.cs
+++ b/Aaru.Gui/ViewModels/Tabs/ScsiInfoViewModel.cs
@@ -370,7 +370,7 @@ public sealed partial class ScsiInfoViewModel : ViewModelBase
case 0x30:
{
if(Modes.IsAppleModePage_30(page.PageResponse))
- decodedText = Localization.Core.Drive_identifies_as_Apple_OEM_drive;
+ decodedText = Aaru.Localization.Core.Drive_identifies_as_Apple_OEM_drive;
else
goto default;
@@ -608,7 +608,9 @@ public sealed partial class ScsiInfoViewModel : ViewModelBase
evpdPageTitle = string.Format(UI.Page_0_h, page.Key);
evpdDecodedPage = UI.Undecoded;
- AaruLogging.Debug(MODULE_NAME, Localization.Core.Found_undecoded_SCSI_VPD_page_0, page.Key);
+ AaruLogging.Debug(MODULE_NAME,
+ Aaru.Localization.Core.Found_undecoded_SCSI_VPD_page_0,
+ page.Key);
break;
}
@@ -627,16 +629,18 @@ public sealed partial class ScsiInfoViewModel : ViewModelBase
Features.SeparatedFeatures ftr = Features.Separate(_configuration);
- AaruLogging.Debug(MODULE_NAME, Localization.Core.GET_CONFIGURATION_length_is_0, ftr.DataLength);
+ AaruLogging.Debug(MODULE_NAME, Aaru.Localization.Core.GET_CONFIGURATION_length_is_0, ftr.DataLength);
- AaruLogging.Debug(MODULE_NAME, Localization.Core.GET_CONFIGURATION_current_profile_is_0, ftr.CurrentProfile);
+ AaruLogging.Debug(MODULE_NAME,
+ Aaru.Localization.Core.GET_CONFIGURATION_current_profile_is_0,
+ ftr.CurrentProfile);
if(ftr.Descriptors != null)
{
foreach(Features.FeatureDescriptor desc in ftr.Descriptors)
{
- var featureNumber = string.Format(Localization.Core.Feature_0, desc.Code);
- AaruLogging.Debug(MODULE_NAME, Localization.Core.Feature_0, desc.Code);
+ var featureNumber = string.Format(Aaru.Localization.Core.Feature_0, desc.Code);
+ AaruLogging.Debug(MODULE_NAME, Aaru.Localization.Core.Feature_0, desc.Code);
string featureDescription = desc.Code switch
{
@@ -709,7 +713,7 @@ public sealed partial class ScsiInfoViewModel : ViewModelBase
}
}
else
- AaruLogging.Debug(MODULE_NAME, Localization.Core.GET_CONFIGURATION_returned_no_feature_descriptors);
+ AaruLogging.Debug(MODULE_NAME, Aaru.Localization.Core.GET_CONFIGURATION_returned_no_feature_descriptors);
}
public byte[] InquiryData { get; }
diff --git a/Aaru.Gui/ViewModels/Tabs/XboxInfoViewModel.cs b/Aaru.Gui/ViewModels/Tabs/XboxInfoViewModel.cs
index 836cf1352..baacf0dc5 100644
--- a/Aaru.Gui/ViewModels/Tabs/XboxInfoViewModel.cs
+++ b/Aaru.Gui/ViewModels/Tabs/XboxInfoViewModel.cs
@@ -58,11 +58,11 @@ public sealed class XboxInfoViewModel
if(xgdInfo != null)
{
XboxInformationVisible = true;
- XboxL0VideoText = string.Format(Localization.Core._0_sectors, xgdInfo.L0Video);
- XboxL1VideoText = string.Format(Localization.Core._0_sectors, xgdInfo.L1Video);
- XboxMiddleZoneText = string.Format(Localization.Core._0_sectors, xgdInfo.MiddleZone);
- XboxGameSizeText = string.Format(Localization.Core._0_sectors, xgdInfo.GameSize);
- XboxTotalSizeText = string.Format(Localization.Core._0_sectors, xgdInfo.TotalSize);
+ XboxL0VideoText = string.Format(Aaru.Localization.Core._0_sectors, xgdInfo.L0Video);
+ XboxL1VideoText = string.Format(Aaru.Localization.Core._0_sectors, xgdInfo.L1Video);
+ XboxMiddleZoneText = string.Format(Aaru.Localization.Core._0_sectors, xgdInfo.MiddleZone);
+ XboxGameSizeText = string.Format(Aaru.Localization.Core._0_sectors, xgdInfo.GameSize);
+ XboxTotalSizeText = string.Format(Aaru.Localization.Core._0_sectors, xgdInfo.TotalSize);
XboxRealBreakText = xgdInfo.LayerBreak.ToString();
}
diff --git a/Aaru.Gui/ViewModels/Windows/DeviceViewModel.cs b/Aaru.Gui/ViewModels/Windows/DeviceViewModel.cs
index 8cd6a81b3..7ddbcccbb 100644
--- a/Aaru.Gui/ViewModels/Windows/DeviceViewModel.cs
+++ b/Aaru.Gui/ViewModels/Windows/DeviceViewModel.cs
@@ -586,8 +586,8 @@ public partial class DeviceViewModel : ViewModelBase
if(devInfo.PlextorFeatures.SilentModeEnabled)
{
PlextorSilentModeAccessTime = devInfo.PlextorFeatures.AccessTimeLimit == 2
- ? Localization.Core.Access_time_is_slow
- : Localization.Core.Access_time_is_fast;
+ ? Aaru.Localization.Core.Access_time_is_slow
+ : Aaru.Localization.Core.Access_time_is_fast;
PlextorSilentModeCdReadSpeedLimit =
devInfo.PlextorFeatures.CdReadSpeedLimit > 0
@@ -669,24 +669,25 @@ public partial class DeviceViewModel : ViewModelBase
if(blockLimits.Value.minBlockLen == blockLimits.Value.maxBlockLen)
{
- MinBlockSize = string.Format(Localization.Core.Device_block_size_is_fixed_at_0_bytes,
+ MinBlockSize = string.Format(Aaru.Localization.Core.Device_block_size_is_fixed_at_0_bytes,
blockLimits.Value.minBlockLen);
}
else
{
MaxBlockSize = blockLimits.Value.maxBlockLen > 0
- ? string.Format(Localization.Core.Device_maximum_block_size_is_0_bytes,
+ ? string.Format(Aaru.Localization.Core
+ .Device_maximum_block_size_is_0_bytes,
blockLimits.Value.maxBlockLen)
- : Localization.Core.Device_does_not_specify_a_maximum_block_size;
+ : Aaru.Localization.Core.Device_does_not_specify_a_maximum_block_size;
- MinBlockSize = string.Format(Localization.Core.Device_minimum_block_size_is_0_bytes,
+ MinBlockSize = string.Format(Aaru.Localization.Core.Device_minimum_block_size_is_0_bytes,
blockLimits.Value.minBlockLen);
if(blockLimits.Value.granularity > 0)
{
BlockSizeGranularity =
- string.Format(Localization.Core
- .Device_needs_a_block_size_granularity_of_pow_0_1_bytes,
+ string.Format(Aaru.Localization.Core
+ .Device_needs_a_block_size_granularity_of_pow_0_1_bytes,
blockLimits.Value.granularity,
Math.Pow(2, blockLimits.Value.granularity));
}
@@ -773,8 +774,8 @@ public partial class DeviceViewModel : ViewModelBase
Dispatcher.UIThread.Invoke(() =>
{
MediaSize =
- string.Format(Localization.Core
- .Media_has_0_blocks_of_1_bytes_each_for_a_total_of_2,
+ string.Format(Aaru.Localization.Core
+ .Media_has_0_blocks_of_1_bytes_each_for_a_total_of_2,
mediaInfo.Blocks,
mediaInfo.BlockSize,
ByteSize.FromBytes(mediaInfo.Blocks *
@@ -991,7 +992,7 @@ public partial class DeviceViewModel : ViewModelBase
case CommonTypes.MediaType.GDR or CommonTypes.MediaType.GDROM:
await MessageBoxManager
.GetMessageBoxStandard(UI.Title_Error,
- Localization.Core.GD_ROM_dump_support_is_not_yet_implemented,
+ Aaru.Localization.Core.GD_ROM_dump_support_is_not_yet_implemented,
ButtonEnum.Ok,
Icon.Error)
.ShowWindowDialogAsync(_window);
@@ -1001,8 +1002,8 @@ public partial class DeviceViewModel : ViewModelBase
when _mediaInfo.DeviceInfo.ScsiInquiry?.KreonPresent != true:
await MessageBoxManager
.GetMessageBoxStandard(UI.Title_Error,
- Localization.Core
- .Dumping_Xbox_Game_Discs_requires_a_drive_with_Kreon_firmware,
+ Aaru.Localization.Core
+ .Dumping_Xbox_Game_Discs_requires_a_drive_with_Kreon_firmware,
ButtonEnum.Ok,
Icon.Error)
.ShowWindowDialogAsync(_window);
@@ -1026,7 +1027,7 @@ public partial class DeviceViewModel : ViewModelBase
case CommonTypes.MediaType.GDROM:
await MessageBoxManager
.GetMessageBoxStandard(UI.Title_Error,
- Localization.Core.GD_ROM_scan_support_is_not_yet_implemented,
+ Aaru.Localization.Core.GD_ROM_scan_support_is_not_yet_implemented,
ButtonEnum.Ok,
Icon.Error)
.ShowWindowDialogAsync(_window);
@@ -1038,8 +1039,8 @@ public partial class DeviceViewModel : ViewModelBase
case CommonTypes.MediaType.XGD2:
case CommonTypes.MediaType.XGD3:
await MessageBoxManager.GetMessageBoxStandard(UI.Title_Error,
- Localization.Core
- .Scanning_Xbox_discs_is_not_yet_supported,
+ Aaru.Localization.Core
+ .Scanning_Xbox_discs_is_not_yet_supported,
ButtonEnum.Ok,
Icon.Error)
.ShowWindowDialogAsync(_window);
diff --git a/Aaru.Gui/ViewModels/Windows/ImageChecksumViewModel.cs b/Aaru.Gui/ViewModels/Windows/ImageChecksumViewModel.cs
index 31ba1df8b..00da4f498 100644
--- a/Aaru.Gui/ViewModels/Windows/ImageChecksumViewModel.cs
+++ b/Aaru.Gui/ViewModels/Windows/ImageChecksumViewModel.cs
@@ -307,7 +307,7 @@ public sealed partial class ImageChecksumViewModel : ViewModelBase
if(errno != ErrorNumber.NoError)
{
- AaruLogging.Error(string.Format(Localization.Core.Error_0_reading_sector_1, errno, i));
+ AaruLogging.Error(string.Format(Aaru.Localization.Core.Error_0_reading_sector_1, errno, i));
_cancel = true;
@@ -356,7 +356,7 @@ public sealed partial class ImageChecksumViewModel : ViewModelBase
if(errno != ErrorNumber.NoError)
{
- AaruLogging.Error(string.Format(Localization.Core.Error_0_reading_sector_1,
+ AaruLogging.Error(string.Format(Aaru.Localization.Core.Error_0_reading_sector_1,
errno,
doneSectors));
@@ -389,7 +389,7 @@ public sealed partial class ImageChecksumViewModel : ViewModelBase
if(errno != ErrorNumber.NoError)
{
- AaruLogging.Error(string.Format(Localization.Core.Error_0_reading_sector_1,
+ AaruLogging.Error(string.Format(Aaru.Localization.Core.Error_0_reading_sector_1,
errno,
doneSectors));
@@ -455,7 +455,7 @@ public sealed partial class ImageChecksumViewModel : ViewModelBase
if(errno != ErrorNumber.NoError)
{
- AaruLogging.Error(string.Format(Localization.Core.Error_0_reading_sector_1, errno, i));
+ AaruLogging.Error(string.Format(Aaru.Localization.Core.Error_0_reading_sector_1, errno, i));
_cancel = true;
@@ -483,9 +483,9 @@ public sealed partial class ImageChecksumViewModel : ViewModelBase
}
catch(Exception ex)
{
- AaruLogging.Debug(Localization.Core.Could_not_get_tracks_because_0, ex.Message);
+ AaruLogging.Debug(Aaru.Localization.Core.Could_not_get_tracks_because_0, ex.Message);
AaruLogging.WriteLine("Unable to get separate tracks, not checksumming them");
- AaruLogging.Exception(ex, Localization.Core.Could_not_get_tracks_because_0, ex.Message);
+ AaruLogging.Exception(ex, Aaru.Localization.Core.Could_not_get_tracks_because_0, ex.Message);
}
}
else
@@ -518,7 +518,7 @@ public sealed partial class ImageChecksumViewModel : ViewModelBase
if(errno != ErrorNumber.NoError)
{
- AaruLogging.Error(string.Format(Localization.Core.Error_0_reading_sector_1,
+ AaruLogging.Error(string.Format(Aaru.Localization.Core.Error_0_reading_sector_1,
errno,
doneSectors));
@@ -550,7 +550,7 @@ public sealed partial class ImageChecksumViewModel : ViewModelBase
if(errno != ErrorNumber.NoError)
{
- AaruLogging.Error(string.Format(Localization.Core.Error_0_reading_sector_1,
+ AaruLogging.Error(string.Format(Aaru.Localization.Core.Error_0_reading_sector_1,
errno,
doneSectors));
diff --git a/Aaru.Gui/ViewModels/Windows/ImageMetadataViewModel.cs b/Aaru.Gui/ViewModels/Windows/ImageMetadataViewModel.cs
index 2443824ea..157bec55e 100644
--- a/Aaru.Gui/ViewModels/Windows/ImageMetadataViewModel.cs
+++ b/Aaru.Gui/ViewModels/Windows/ImageMetadataViewModel.cs
@@ -186,7 +186,7 @@ public sealed partial class ImageMetadataViewModel : ViewModelBase
if(errno != ErrorNumber.NoError)
{
AaruLogging.Error(UI.Error_reopening_image_in_read_only_mode_after_writing_metadata);
- AaruLogging.Error(Localization.Core.Error_0, errno);
+ AaruLogging.Error(Aaru.Localization.Core.Error_0, errno);
msbox = MessageBoxManager.GetMessageBoxStandard(UI.Title_Error,
UI
@@ -201,7 +201,7 @@ public sealed partial class ImageMetadataViewModel : ViewModelBase
return;
}
- msbox = MessageBoxManager.GetMessageBoxStandard(Localization.Core.Success,
+ msbox = MessageBoxManager.GetMessageBoxStandard(Aaru.Localization.Core.Success,
UI.Metadata_saved_successfully,
ButtonEnum.Ok,
Icon.Success);
@@ -339,8 +339,8 @@ public sealed partial class ImageMetadataViewModel : ViewModelBase
await msbox.ShowAsync();
AaruLogging.Error(UI.Unable_to_open_image_format);
- AaruLogging.Error(Localization.Core.Error_0, ex.Message);
- AaruLogging.Exception(ex, Localization.Core.Error_0, ex.Message);
+ AaruLogging.Error(Aaru.Localization.Core.Error_0, ex.Message);
+ AaruLogging.Exception(ex, Aaru.Localization.Core.Error_0, ex.Message);
}
}
catch(Exception ex)
diff --git a/Aaru.Gui/ViewModels/Windows/ImageSidecarViewModel.cs b/Aaru.Gui/ViewModels/Windows/ImageSidecarViewModel.cs
index 00015b65b..990146172 100644
--- a/Aaru.Gui/ViewModels/Windows/ImageSidecarViewModel.cs
+++ b/Aaru.Gui/ViewModels/Windows/ImageSidecarViewModel.cs
@@ -153,7 +153,7 @@ public sealed partial class ImageSidecarViewModel : ViewModelBase
_sidecarClass.EndProgressEvent2 += EndProgress2;
Metadata sidecar = _sidecarClass.Create();
- AaruLogging.WriteLine(Localization.Core.Writing_metadata_sidecar);
+ AaruLogging.WriteLine(Aaru.Localization.Core.Writing_metadata_sidecar);
var jsonFs = new FileStream(DestinationText, FileMode.Create);
@@ -217,7 +217,7 @@ public sealed partial class ImageSidecarViewModel : ViewModelBase
void Stop()
{
- ProgressText = Localization.Core.Aborting;
+ ProgressText = Aaru.Localization.Core.Aborting;
StopEnabled = false;
_sidecarClass.Abort();
}
diff --git a/Aaru.Gui/ViewModels/Windows/MainWindowViewModel.cs b/Aaru.Gui/ViewModels/Windows/MainWindowViewModel.cs
index 6ed3d44b0..949c45dee 100644
--- a/Aaru.Gui/ViewModels/Windows/MainWindowViewModel.cs
+++ b/Aaru.Gui/ViewModels/Windows/MainWindowViewModel.cs
@@ -119,6 +119,8 @@ public partial class MainWindowViewModel : ViewModelBase
ConnectToRemoteCommand = new AsyncRelayCommand(ConnectToRemoteAsync);
OpenDeviceCommand = new RelayCommand(OpenDevice);
ImageMetadataCommand = new AsyncRelayCommand(ImageMetadataAsync);
+ CreateMetadataCommand = new AsyncRelayCommand(CreateMetadataAsync);
+ EditMetadataCommand = new AsyncRelayCommand(EditMetadataAsync);
_genericHddIcon =
new Bitmap(AssetLoader.Open(new Uri("avares://Aaru.Gui/Assets/Icons/oxygen/32x32/drive-harddisk.png")));
@@ -174,6 +176,8 @@ public partial class MainWindowViewModel : ViewModelBase
public ICommand ConnectToRemoteCommand { get; }
public ICommand OpenDeviceCommand { get; }
public ICommand ImageMetadataCommand { get; }
+ public ICommand CreateMetadataCommand { get; }
+ public ICommand EditMetadataCommand { get; }
public bool NativeMenuSupported
{
@@ -239,6 +243,43 @@ public partial class MainWindowViewModel : ViewModelBase
return dialog.ShowDialog(_view);
}
+ async Task CreateMetadataAsync()
+ {
+ var dialog = new MetadataEditor();
+ await dialog.ShowDialog(_view);
+ }
+
+ async Task EditMetadataAsync()
+ {
+ var lifetime = Application.Current?.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime;
+ Window mainWindow = lifetime?.MainWindow;
+
+ if(mainWindow == null) return;
+
+ IReadOnlyList files =
+ await mainWindow.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
+ {
+ Title = "Open Metadata File",
+ AllowMultiple = false,
+ FileTypeFilter = new[]
+ {
+ new FilePickerFileType("JSON")
+ {
+ Patterns = new[]
+ {
+ "*.json"
+ }
+ }
+ }
+ });
+
+ if(files.Count == 0) return;
+
+ string filePath = files[0].Path.LocalPath;
+ var dialog = new MetadataEditor(filePath);
+ await dialog.ShowDialog(_view);
+ }
+
void OpenDevice()
{
var deviceListWindow = new DeviceList();
@@ -533,7 +574,7 @@ public partial class MainWindowViewModel : ViewModelBase
{
var wholePart = new Partition
{
- Name = Localization.Core.Whole_device,
+ Name = Aaru.Localization.Core.Whole_device,
Length = imageFormat.Info.Sectors,
Size = imageFormat.Info.Sectors * imageFormat.Info.SectorSize
};
@@ -619,8 +660,8 @@ public partial class MainWindowViewModel : ViewModelBase
await msbox.ShowAsync();
AaruLogging.Error(UI.Unable_to_open_image_format);
- AaruLogging.Error(Localization.Core.Error_0, ex.Message);
- AaruLogging.Exception(ex, Localization.Core.Error_0, ex.Message);
+ AaruLogging.Error(Aaru.Localization.Core.Error_0, ex.Message);
+ AaruLogging.Exception(ex, Aaru.Localization.Core.Error_0, ex.Message);
}
}
catch(Exception ex)
diff --git a/Aaru.Gui/ViewModels/Windows/MediaScanViewModel.cs b/Aaru.Gui/ViewModels/Windows/MediaScanViewModel.cs
index 078a39ec0..302313c30 100644
--- a/Aaru.Gui/ViewModels/Windows/MediaScanViewModel.cs
+++ b/Aaru.Gui/ViewModels/Windows/MediaScanViewModel.cs
@@ -203,27 +203,27 @@ public sealed partial class MediaScanViewModel : ViewModelBase
_pendingSectorData.Clear();
}
- TotalTime = string.Format(Localization.Core.Took_a_total_of_0_1_processing_commands,
+ TotalTime = string.Format(Aaru.Localization.Core.Took_a_total_of_0_1_processing_commands,
results.TotalTime.Seconds().Humanize(minUnit: TimeUnit.Second),
results.ProcessingTime.Seconds().Humanize(minUnit: TimeUnit.Second));
- AvgSpeed = string.Format(Localization.Core.Average_speed_0,
+ AvgSpeed = string.Format(Aaru.Localization.Core.Average_speed_0,
ByteSize.FromMegabytes(results.AvgSpeed).Per(1.Seconds()).Humanize());
- MaxSpeed = string.Format(Localization.Core.Fastest_speed_burst_0,
+ MaxSpeed = string.Format(Aaru.Localization.Core.Fastest_speed_burst_0,
ByteSize.FromMegabytes(results.MaxSpeed).Per(1.Seconds()).Humanize());
- MinSpeed = string.Format(Localization.Core.Slowest_speed_burst_0,
+ MinSpeed = string.Format(Aaru.Localization.Core.Slowest_speed_burst_0,
ByteSize.FromMegabytes(results.MinSpeed).Per(1.Seconds()).Humanize());
- A = string.Format(Localization.Core._0_sectors_took_less_than_3_ms, results.A);
- B = string.Format(Localization.Core._0_sectors_took_less_than_10_ms_but_more_than_3_ms, results.B);
- C = string.Format(Localization.Core._0_sectors_took_less_than_50_ms_but_more_than_10_ms, results.C);
- D = string.Format(Localization.Core._0_sectors_took_less_than_150_ms_but_more_than_50_ms, results.D);
- E = string.Format(Localization.Core._0_sectors_took_less_than_500_ms_but_more_than_150_ms, results.E);
- F = string.Format(Localization.Core._0_sectors_took_more_than_500_ms, results.F);
+ A = string.Format(Aaru.Localization.Core._0_sectors_took_less_than_3_ms, results.A);
+ B = string.Format(Aaru.Localization.Core._0_sectors_took_less_than_10_ms_but_more_than_3_ms, results.B);
+ C = string.Format(Aaru.Localization.Core._0_sectors_took_less_than_50_ms_but_more_than_10_ms, results.C);
+ D = string.Format(Aaru.Localization.Core._0_sectors_took_less_than_150_ms_but_more_than_50_ms, results.D);
+ E = string.Format(Aaru.Localization.Core._0_sectors_took_less_than_500_ms_but_more_than_150_ms, results.E);
+ F = string.Format(Aaru.Localization.Core._0_sectors_took_more_than_500_ms, results.F);
- UnreadableSectors = string.Format(Localization.Core._0_sectors_could_not_be_read,
+ UnreadableSectors = string.Format(Aaru.Localization.Core._0_sectors_could_not_be_read,
results.UnreadableSectors?.Count ?? 0);
});
@@ -364,7 +364,7 @@ public sealed partial class MediaScanViewModel : ViewModelBase
async void OnScanUnreadable(ulong sector) => await Dispatcher.UIThread.InvokeAsync(() =>
{
_localResults.Errored += _blocksToRead;
- UnreadableSectors = string.Format(Localization.Core._0_sectors_could_not_be_read, _localResults.Errored);
+ UnreadableSectors = string.Format(Aaru.Localization.Core._0_sectors_could_not_be_read, _localResults.Errored);
});
async void OnScanTime(ulong sector, double duration)
@@ -422,28 +422,28 @@ public sealed partial class MediaScanViewModel : ViewModelBase
BlockMapSectorData.Add(item);
// Update text labels
- A = string.Format(Localization.Core
- ._0_sectors_took_less_than_3_ms,
+ A = string.Format(Aaru.Localization.Core
+ ._0_sectors_took_less_than_3_ms,
_localResults.A);
- B = string.Format(Localization.Core
- ._0_sectors_took_less_than_10_ms_but_more_than_3_ms,
+ B = string.Format(Aaru.Localization.Core
+ ._0_sectors_took_less_than_10_ms_but_more_than_3_ms,
_localResults.B);
- C = string.Format(Localization.Core
- ._0_sectors_took_less_than_50_ms_but_more_than_10_ms,
+ C = string.Format(Aaru.Localization.Core
+ ._0_sectors_took_less_than_50_ms_but_more_than_10_ms,
_localResults.C);
- D = string.Format(Localization.Core
- ._0_sectors_took_less_than_150_ms_but_more_than_50_ms,
+ D = string.Format(Aaru.Localization.Core
+ ._0_sectors_took_less_than_150_ms_but_more_than_50_ms,
_localResults.D);
- E = string.Format(Localization.Core
- ._0_sectors_took_less_than_500_ms_but_more_than_150_ms,
+ E = string.Format(Aaru.Localization.Core
+ ._0_sectors_took_less_than_500_ms_but_more_than_150_ms,
_localResults.E);
- F = string.Format(Localization.Core
- ._0_sectors_took_more_than_500_ms,
+ F = string.Format(Aaru.Localization.Core
+ ._0_sectors_took_more_than_500_ms,
_localResults.F);
},
DispatcherPriority.Background);
diff --git a/Aaru.Gui/ViewModels/Windows/MetadataEditorViewModel.cs b/Aaru.Gui/ViewModels/Windows/MetadataEditorViewModel.cs
new file mode 100644
index 000000000..35b809da7
--- /dev/null
+++ b/Aaru.Gui/ViewModels/Windows/MetadataEditorViewModel.cs
@@ -0,0 +1,870 @@
+// /***************************************************************************
+// Aaru Data Preservation Suite
+// ----------------------------------------------------------------------------
+//
+// Filename : MetadataEditorViewModel.cs
+// Author(s) : Natalia Portillo
+//
+// Component : GUI view models.
+//
+// --[ Description ] ----------------------------------------------------------
+//
+// Metadata editor window view model.
+//
+// --[ 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 .
+//
+// ----------------------------------------------------------------------------
+// Copyright © 2011-2025 Natalia Portillo
+// ****************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text.Json;
+using System.Threading.Tasks;
+using Aaru.CommonTypes.AaruMetadata;
+using Aaru.Gui.Localization;
+using Aaru.Localization;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Platform.Storage;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using JetBrains.Annotations;
+using MsBox.Avalonia;
+using MsBox.Avalonia.Enums;
+using Sentry;
+using File = System.IO.File;
+
+namespace Aaru.Gui.ViewModels.Windows;
+
+public sealed partial class MetadataEditorViewModel : ViewModelBase
+{
+ readonly Window _view;
+
+ [ObservableProperty]
+ ObservableCollection _advertisements = [];
+
+ [ObservableProperty]
+ ObservableCollection _architectures = [];
+
+ [ObservableProperty]
+ ObservableCollection _audioMedias = [];
+
+ [ObservableProperty]
+ ObservableCollection _authors = [];
+
+ // Complex object lists
+ [ObservableProperty]
+ ObservableCollection _barcodes = [];
+
+ [ObservableProperty]
+ ObservableCollection _blockMedias = [];
+
+ [ObservableProperty]
+ ObservableCollection _books = [];
+
+ [ObservableProperty]
+ ObservableCollection _categories = [];
+
+ // String lists
+ [ObservableProperty]
+ ObservableCollection _developers = [];
+
+ [ObservableProperty]
+ string _filePath;
+
+ [ObservableProperty]
+ ObservableCollection _keywords = [];
+
+ // Enum lists
+ [ObservableProperty]
+ ObservableCollection _languages = [];
+
+ [ObservableProperty]
+ ObservableCollection _linearMedias = [];
+
+ [ObservableProperty]
+ ObservableCollection _magazines = [];
+
+ // Basic metadata fields
+ [ObservableProperty]
+ string _name;
+
+ [ObservableProperty]
+ ObservableCollection _opticalDiscs = [];
+
+ [ObservableProperty]
+ string _partNumber;
+
+ [ObservableProperty]
+ ObservableCollection _pciCards = [];
+
+ [ObservableProperty]
+ ObservableCollection _performers = [];
+
+ [ObservableProperty]
+ ObservableCollection _publishers = [];
+
+ [ObservableProperty]
+ DateTime? _releaseDate;
+
+ [ObservableProperty]
+ ObservableCollection _requiredOperatingSystems = [];
+
+ [ObservableProperty]
+ ReleaseType? _selectedReleaseType;
+
+ [ObservableProperty]
+ string _serialNumber;
+
+ [ObservableProperty]
+ ObservableCollection _subcategories = [];
+
+ [ObservableProperty]
+ ObservableCollection _systems = [];
+
+ [ObservableProperty]
+ string _title;
+
+ [ObservableProperty]
+ ObservableCollection _userManuals = [];
+
+ [ObservableProperty]
+ string _version;
+
+ public MetadataEditorViewModel(Window view, [CanBeNull] string existingFilePath = null)
+ {
+ _view = view;
+ _title = existingFilePath == null ? GUI.Title_Create_Metadata : GUI.Title_Edit_Metadata;
+ _filePath = existingFilePath;
+
+ if(!string.IsNullOrEmpty(existingFilePath) && File.Exists(existingFilePath)) LoadMetadata(existingFilePath);
+ }
+
+ // Available enum values for ComboBoxes
+ [NotNull]
+ public IEnumerable AvailableReleaseTypes => Enum.GetValues();
+ [NotNull]
+ public IEnumerable AvailableLanguages => Enum.GetValues();
+ [NotNull]
+ public IEnumerable AvailableArchitectures => Enum.GetValues();
+ [NotNull]
+ public IEnumerable AvailableBarcodeTypes => Enum.GetValues();
+
+ void LoadMetadata([NotNull] string path)
+ {
+ try
+ {
+ string json = File.ReadAllText(path);
+ MetadataJson metadataJson = JsonSerializer.Deserialize(json, MetadataJsonContext.Default.MetadataJson);
+
+ if(metadataJson?.AaruMetadata == null) return;
+
+ Metadata metadata = metadataJson.AaruMetadata;
+
+ // Basic fields
+ Name = metadata.Name;
+ Version = metadata.Version;
+ SelectedReleaseType = metadata.Release;
+ ReleaseDate = metadata.ReleaseDate;
+ PartNumber = metadata.PartNumber;
+ SerialNumber = metadata.SerialNumber;
+
+ // String lists
+ LoadStringList(metadata.Developers, Developers);
+ LoadStringList(metadata.Publishers, Publishers);
+ LoadStringList(metadata.Authors, Authors);
+ LoadStringList(metadata.Performers, Performers);
+ LoadStringList(metadata.Keywords, Keywords);
+ LoadStringList(metadata.Categories, Categories);
+ LoadStringList(metadata.Subcategories, Subcategories);
+ LoadStringList(metadata.Systems, Systems);
+
+ // Enum lists
+ LoadEnumList(metadata.Languages, Languages);
+ LoadEnumList(metadata.Architectures, Architectures);
+
+ // Complex objects
+ if(metadata.Barcodes != null)
+ {
+ foreach(Barcode barcode in metadata.Barcodes) Barcodes.Add(new BarcodeViewModel(barcode));
+ }
+
+ if(metadata.Magazines != null)
+ {
+ foreach(Magazine magazine in metadata.Magazines) Magazines.Add(new MagazineViewModel(magazine));
+ }
+
+ if(metadata.Books != null)
+ {
+ foreach(Book book in metadata.Books) Books.Add(new BookViewModel(book));
+ }
+
+ if(metadata.RequiredOperatingSystems != null)
+ {
+ foreach(RequiredOperatingSystem os in metadata.RequiredOperatingSystems)
+ RequiredOperatingSystems.Add(new RequiredOperatingSystemViewModel(os));
+ }
+
+ if(metadata.UserManuals != null)
+ {
+ foreach(UserManual manual in metadata.UserManuals) UserManuals.Add(new UserManualViewModel(manual));
+ }
+
+ if(metadata.OpticalDiscs != null)
+ {
+ foreach(OpticalDisc disc in metadata.OpticalDiscs) OpticalDiscs.Add(new OpticalDiscViewModel(disc));
+ }
+
+ if(metadata.Advertisements != null)
+ {
+ foreach(Advertisement ad in metadata.Advertisements) Advertisements.Add(new AdvertisementViewModel(ad));
+ }
+
+ if(metadata.LinearMedias != null)
+ {
+ foreach(LinearMedia media in metadata.LinearMedias) LinearMedias.Add(new LinearMediaViewModel(media));
+ }
+
+ if(metadata.PciCards != null)
+ {
+ foreach(Pci pci in metadata.PciCards) PciCards.Add(new PciViewModel(pci));
+ }
+
+ if(metadata.BlockMedias != null)
+ {
+ foreach(BlockMedia media in metadata.BlockMedias) BlockMedias.Add(new BlockMediaViewModel(media));
+ }
+
+ if(metadata.AudioMedias != null)
+ {
+ foreach(AudioMedia media in metadata.AudioMedias) AudioMedias.Add(new AudioMediaViewModel(media));
+ }
+ }
+ catch(Exception ex)
+ {
+ _ = MessageBoxManager.GetMessageBoxStandard(UI.Title_Error,
+ string.Format(GUI.Error_Loading_metadata, ex.Message),
+ ButtonEnum.Ok,
+ Icon.Error)
+ .ShowAsync();
+ }
+ }
+
+ static void LoadStringList([CanBeNull] List source, ObservableCollection target)
+ {
+ if(source == null) return;
+
+ target.Clear();
+ foreach(string item in source) target.Add(item);
+ }
+
+ static void LoadEnumList([CanBeNull] List source, ObservableCollection target) where T : struct, Enum
+ {
+ if(source == null) return;
+
+ target.Clear();
+ foreach(T item in source) target.Add(item);
+ }
+
+ [RelayCommand]
+ async Task SaveAsync()
+ {
+ try
+ {
+ var metadata = new Metadata
+ {
+ Name = Name,
+ Version = Version,
+ Release = SelectedReleaseType,
+ ReleaseDate = ReleaseDate,
+ PartNumber = PartNumber,
+ SerialNumber = SerialNumber,
+ Developers = Developers.Any() ? [..Developers] : null,
+ Publishers = Publishers.Any() ? [..Publishers] : null,
+ Authors = Authors.Any() ? [..Authors] : null,
+ Performers = Performers.Any() ? [..Performers] : null,
+ Keywords = Keywords.Any() ? [..Keywords] : null,
+ Categories = Categories.Any() ? [..Categories] : null,
+ Subcategories = Subcategories.Any() ? [..Subcategories] : null,
+ Systems = Systems.Any() ? [..Systems] : null,
+ Languages = Languages.Any() ? [..Languages] : null,
+ Architectures = Architectures.Any() ? [..Architectures] : null,
+ Barcodes = Barcodes.Any() ? [..Barcodes.Select(static b => b.ToModel())] : null,
+ Magazines = Magazines.Any() ? [..Magazines.Select(static m => m.ToModel())] : null,
+ Books = Books.Any() ? [..Books.Select(static b => b.ToModel())] : null,
+ RequiredOperatingSystems =
+ RequiredOperatingSystems.Any()
+ ? [..RequiredOperatingSystems.Select(static os => os.ToModel())]
+ : null,
+ UserManuals = UserManuals.Any() ? [..UserManuals.Select(static um => um.ToModel())] : null,
+ OpticalDiscs =
+ OpticalDiscs.Any() ? [..OpticalDiscs.Select(static od => od.ToModel())] : null,
+ Advertisements =
+ Advertisements.Any() ? [..Advertisements.Select(static a => a.ToModel())] : null,
+ LinearMedias =
+ LinearMedias.Any() ? [..LinearMedias.Select(static lm => lm.ToModel())] : null,
+ PciCards = PciCards.Any() ? [..PciCards.Select(static p => p.ToModel())] : null,
+ BlockMedias = BlockMedias.Any() ? [..BlockMedias.Select(static bm => bm.ToModel())] : null,
+ AudioMedias = AudioMedias.Any() ? [..AudioMedias.Select(static am => am.ToModel())] : null
+ };
+
+ var metadataJson = new MetadataJson
+ {
+ AaruMetadata = metadata
+ };
+
+ string savePath = FilePath;
+
+ if(string.IsNullOrEmpty(savePath))
+ {
+ var lifetime = Application.Current?.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime;
+ Window mainWindow = lifetime?.MainWindow;
+
+ if(mainWindow == null) return;
+
+ IStorageFile file = await mainWindow.StorageProvider.SaveFilePickerAsync(new FilePickerSaveOptions
+ {
+ Title = GUI.Dialog_Save_Metadata_File,
+ FileTypeChoices =
+ [
+ new FilePickerFileType(GUI.FileType_JSON)
+ {
+ Patterns =
+ [
+ "*.json"
+ ]
+ }
+ ],
+ DefaultExtension = "json"
+ });
+
+ if(file == null) return;
+
+ savePath = file.Path.LocalPath;
+ FilePath = savePath;
+ }
+
+ string json = JsonSerializer.Serialize(metadataJson, MetadataJsonContext.Default.MetadataJson);
+ await File.WriteAllTextAsync(savePath, json);
+
+ await MessageBoxManager.GetMessageBoxStandard(GUI.Title_Success,
+ GUI.Message_Metadata_saved_successfully,
+ ButtonEnum.Ok,
+ Icon.Success)
+ .ShowAsync();
+
+ _view.Close();
+ }
+ catch(Exception ex)
+ {
+ SentrySdk.CaptureException(ex);
+
+ await MessageBoxManager.GetMessageBoxStandard(UI.Title_Error,
+ string.Format(GUI.Error_Saving_metadata, ex.Message),
+ ButtonEnum.Ok,
+ Icon.Error)
+ .ShowAsync();
+ }
+ }
+
+ [RelayCommand]
+ void Cancel()
+ {
+ _view.Close();
+ }
+
+ // Commands for adding items to simple string lists
+ [RelayCommand]
+ void AddDeveloper() => Developers.Add(string.Empty);
+
+ [RelayCommand]
+ void RemoveDeveloper(string item) => Developers.Remove(item);
+
+ [RelayCommand]
+ void AddPublisher() => Publishers.Add(string.Empty);
+
+ [RelayCommand]
+ void RemovePublisher(string item) => Publishers.Remove(item);
+
+ [RelayCommand]
+ void AddAuthor() => Authors.Add(string.Empty);
+
+ [RelayCommand]
+ void RemoveAuthor(string item) => Authors.Remove(item);
+
+ [RelayCommand]
+ void AddPerformer() => Performers.Add(string.Empty);
+
+ [RelayCommand]
+ void RemovePerformer(string item) => Performers.Remove(item);
+
+ [RelayCommand]
+ void AddKeyword() => Keywords.Add(string.Empty);
+
+ [RelayCommand]
+ void RemoveKeyword(string item) => Keywords.Remove(item);
+
+ [RelayCommand]
+ void AddCategory() => Categories.Add(string.Empty);
+
+ [RelayCommand]
+ void RemoveCategory(string item) => Categories.Remove(item);
+
+ [RelayCommand]
+ void AddSubcategory() => Subcategories.Add(string.Empty);
+
+ [RelayCommand]
+ void RemoveSubcategory(string item) => Subcategories.Remove(item);
+
+ [RelayCommand]
+ void AddSystem() => Systems.Add(string.Empty);
+
+ [RelayCommand]
+ void RemoveSystem(string item) => Systems.Remove(item);
+
+ // Commands for adding items to enum lists
+ [RelayCommand]
+ void AddLanguage(Language language)
+ {
+ if(!Languages.Contains(language)) Languages.Add(language);
+ }
+
+ [RelayCommand]
+ void RemoveLanguage(Language language) => Languages.Remove(language);
+
+ [RelayCommand]
+ void AddArchitecture(Architecture architecture)
+ {
+ if(!Architectures.Contains(architecture)) Architectures.Add(architecture);
+ }
+
+ [RelayCommand]
+ void RemoveArchitecture(Architecture architecture) => Architectures.Remove(architecture);
+
+ // Commands for complex objects
+ [RelayCommand]
+ void AddBarcode() => Barcodes.Add(new BarcodeViewModel());
+
+ [RelayCommand]
+ void RemoveBarcode(BarcodeViewModel item) => Barcodes.Remove(item);
+
+ [RelayCommand]
+ void AddMagazine() => Magazines.Add(new MagazineViewModel());
+
+ [RelayCommand]
+ void RemoveMagazine(MagazineViewModel item) => Magazines.Remove(item);
+
+ [RelayCommand]
+ void AddBook() => Books.Add(new BookViewModel());
+
+ [RelayCommand]
+ void RemoveBook(BookViewModel item) => Books.Remove(item);
+
+ [RelayCommand]
+ void AddRequiredOperatingSystem() => RequiredOperatingSystems.Add(new RequiredOperatingSystemViewModel());
+
+ [RelayCommand]
+ void RemoveRequiredOperatingSystem(RequiredOperatingSystemViewModel item) => RequiredOperatingSystems.Remove(item);
+
+ [RelayCommand]
+ void AddUserManual() => UserManuals.Add(new UserManualViewModel());
+
+ [RelayCommand]
+ void RemoveUserManual(UserManualViewModel item) => UserManuals.Remove(item);
+
+ [RelayCommand]
+ void AddOpticalDisc() => OpticalDiscs.Add(new OpticalDiscViewModel());
+
+ [RelayCommand]
+ void RemoveOpticalDisc(OpticalDiscViewModel item) => OpticalDiscs.Remove(item);
+
+ [RelayCommand]
+ void AddAdvertisement() => Advertisements.Add(new AdvertisementViewModel());
+
+ [RelayCommand]
+ void RemoveAdvertisement(AdvertisementViewModel item) => Advertisements.Remove(item);
+
+ [RelayCommand]
+ void AddLinearMedia() => LinearMedias.Add(new LinearMediaViewModel());
+
+ [RelayCommand]
+ void RemoveLinearMedia(LinearMediaViewModel item) => LinearMedias.Remove(item);
+
+ [RelayCommand]
+ void AddPciCard() => PciCards.Add(new PciViewModel());
+
+ [RelayCommand]
+ void RemovePciCard(PciViewModel item) => PciCards.Remove(item);
+
+ [RelayCommand]
+ void AddBlockMedia() => BlockMedias.Add(new BlockMediaViewModel());
+
+ [RelayCommand]
+ void RemoveBlockMedia(BlockMediaViewModel item) => BlockMedias.Remove(item);
+
+ [RelayCommand]
+ void AddAudioMedia() => AudioMedias.Add(new AudioMediaViewModel());
+
+ [RelayCommand]
+ void RemoveAudioMedia(AudioMediaViewModel item) => AudioMedias.Remove(item);
+}
+
+// Helper ViewModels for complex objects
+public sealed partial class BarcodeViewModel : ObservableObject
+{
+ [ObservableProperty]
+ BarcodeType _type;
+
+ [ObservableProperty]
+ string _value;
+
+ public BarcodeViewModel() {}
+
+ public BarcodeViewModel([NotNull] Barcode barcode)
+ {
+ Type = barcode.Type;
+ Value = barcode.Value;
+ }
+
+ [NotNull]
+ public Barcode ToModel() => new()
+ {
+ Type = Type,
+ Value = Value
+ };
+}
+
+public sealed partial class MagazineViewModel : ObservableObject
+{
+ [ObservableProperty]
+ string _editorial;
+ [ObservableProperty]
+ string _name;
+
+ [ObservableProperty]
+ uint? _number;
+
+ [ObservableProperty]
+ uint? _pages;
+
+ [ObservableProperty]
+ string _pageSize;
+
+ [ObservableProperty]
+ DateTime? _publicationDate;
+
+ public MagazineViewModel() {}
+
+ public MagazineViewModel([NotNull] Magazine magazine)
+ {
+ Name = magazine.Name;
+ Editorial = magazine.Editorial;
+ PublicationDate = magazine.PublicationDate;
+ Number = magazine.Number;
+ Pages = magazine.Pages;
+ PageSize = magazine.PageSize;
+ }
+
+ [NotNull]
+ public Magazine ToModel() => new()
+ {
+ Name = Name,
+ Editorial = Editorial,
+ PublicationDate = PublicationDate,
+ Number = Number,
+ Pages = Pages,
+ PageSize = PageSize
+ };
+}
+
+public sealed partial class BookViewModel : ObservableObject
+{
+ [ObservableProperty]
+ string _author;
+
+ [ObservableProperty]
+ string _editorial;
+ [ObservableProperty]
+ string _name;
+
+ [ObservableProperty]
+ uint? _pages;
+
+ [ObservableProperty]
+ string _pageSize;
+
+ [ObservableProperty]
+ DateTime? _publicationDate;
+
+ public BookViewModel() {}
+
+ public BookViewModel([NotNull] Book book)
+ {
+ Name = book.Name;
+ Editorial = book.Editorial;
+ Author = book.Author;
+ PublicationDate = book.PublicationDate;
+ Pages = book.Pages;
+ PageSize = book.PageSize;
+ }
+
+ [NotNull]
+ public Book ToModel() => new()
+ {
+ Name = Name,
+ Editorial = Editorial,
+ Author = Author,
+ PublicationDate = PublicationDate,
+ Pages = Pages,
+ PageSize = PageSize
+ };
+}
+
+public sealed partial class RequiredOperatingSystemViewModel : ObservableObject
+{
+ [ObservableProperty]
+ string _name;
+
+ [ObservableProperty]
+ ObservableCollection _versions = [];
+
+ public RequiredOperatingSystemViewModel() {}
+
+ public RequiredOperatingSystemViewModel([NotNull] RequiredOperatingSystem os)
+ {
+ Name = os.Name;
+
+ if(os.Versions == null) return;
+
+ foreach(string version in os.Versions) Versions.Add(version);
+ }
+
+ [NotNull]
+ public RequiredOperatingSystem ToModel() => new()
+ {
+ Name = Name,
+ Versions = Versions.Any() ? [..Versions] : null
+ };
+}
+
+public sealed partial class UserManualViewModel : ObservableObject
+{
+ [ObservableProperty]
+ uint _pages;
+
+ [ObservableProperty]
+ string _pageSize;
+
+ public UserManualViewModel() {}
+
+ public UserManualViewModel([NotNull] UserManual manual)
+ {
+ Pages = manual.Pages;
+ PageSize = manual.PageSize;
+ }
+
+ [NotNull]
+ public UserManual ToModel() => new()
+ {
+ Pages = Pages,
+ PageSize = PageSize
+ };
+}
+
+// Simplified ViewModels for complex media types (can be expanded as needed)
+public sealed partial class OpticalDiscViewModel : ObservableObject
+{
+ [ObservableProperty]
+ string _discSubType;
+
+ [ObservableProperty]
+ string _discType;
+ [ObservableProperty]
+ string _partNumber;
+
+ [ObservableProperty]
+ string _serialNumber;
+
+ public OpticalDiscViewModel() {}
+
+ public OpticalDiscViewModel([NotNull] OpticalDisc disc)
+ {
+ PartNumber = disc.PartNumber;
+ SerialNumber = disc.SerialNumber;
+ DiscType = disc.DiscType;
+ DiscSubType = disc.DiscSubType;
+ }
+
+ [NotNull]
+ public OpticalDisc ToModel() => new()
+ {
+ PartNumber = PartNumber,
+ SerialNumber = SerialNumber,
+ DiscType = DiscType,
+ DiscSubType = DiscSubType
+ };
+}
+
+public sealed partial class AdvertisementViewModel : ObservableObject
+{
+ [ObservableProperty]
+ string _manufacturer;
+
+ [ObservableProperty]
+ string _product;
+
+ public AdvertisementViewModel() {}
+
+ public AdvertisementViewModel([NotNull] Advertisement ad)
+ {
+ Manufacturer = ad.Manufacturer;
+ Product = ad.Product;
+ }
+
+ [NotNull]
+ public Advertisement ToModel() => new()
+ {
+ Manufacturer = Manufacturer,
+ Product = Product
+ };
+}
+
+public sealed partial class LinearMediaViewModel : ObservableObject
+{
+ [ObservableProperty]
+ string _manufacturer;
+
+ [ObservableProperty]
+ string _model;
+ [ObservableProperty]
+ string _partNumber;
+
+ [ObservableProperty]
+ string _serialNumber;
+
+ public LinearMediaViewModel() {}
+
+ public LinearMediaViewModel([NotNull] LinearMedia media)
+ {
+ PartNumber = media.PartNumber;
+ SerialNumber = media.SerialNumber;
+ Manufacturer = media.Manufacturer;
+ Model = media.Model;
+ }
+
+ [NotNull]
+ public LinearMedia ToModel() => new()
+ {
+ PartNumber = PartNumber,
+ SerialNumber = SerialNumber,
+ Manufacturer = Manufacturer,
+ Model = Model
+ };
+}
+
+public sealed partial class PciViewModel : ObservableObject
+{
+ [ObservableProperty]
+ ushort _deviceID;
+ [ObservableProperty]
+ ushort _vendorID;
+
+ public PciViewModel() {}
+
+ public PciViewModel([NotNull] Pci pci)
+ {
+ VendorID = pci.VendorID;
+ DeviceID = pci.DeviceID;
+ }
+
+ [NotNull]
+ public Pci ToModel() => new()
+ {
+ VendorID = VendorID,
+ DeviceID = DeviceID
+ };
+}
+
+public sealed partial class BlockMediaViewModel : ObservableObject
+{
+ [ObservableProperty]
+ string _firmware;
+ [ObservableProperty]
+ string _manufacturer;
+
+ [ObservableProperty]
+ string _model;
+
+ [ObservableProperty]
+ string _serial;
+
+ public BlockMediaViewModel() {}
+
+ public BlockMediaViewModel([NotNull] BlockMedia media)
+ {
+ Manufacturer = media.Manufacturer;
+ Model = media.Model;
+ Serial = media.Serial;
+ Firmware = media.Firmware;
+ }
+
+ [NotNull]
+ public BlockMedia ToModel() => new()
+ {
+ Manufacturer = Manufacturer,
+ Model = Model,
+ Serial = Serial,
+ Firmware = Firmware
+ };
+}
+
+public sealed partial class AudioMediaViewModel : ObservableObject
+{
+ [ObservableProperty]
+ string _manufacturer;
+
+ [ObservableProperty]
+ string _model;
+
+ [ObservableProperty]
+ string _partNumber;
+
+ [ObservableProperty]
+ string _serialNumber;
+
+ public AudioMediaViewModel() {}
+
+ public AudioMediaViewModel([NotNull] AudioMedia media)
+ {
+ Manufacturer = media.Manufacturer;
+ Model = media.Model;
+ PartNumber = media.PartNumber;
+ SerialNumber = media.SerialNumber;
+ }
+
+ [NotNull]
+ public AudioMedia ToModel() => new()
+ {
+ Manufacturer = Manufacturer,
+ Model = Model,
+ PartNumber = PartNumber,
+ SerialNumber = SerialNumber
+ };
+}
\ No newline at end of file
diff --git a/Aaru.Gui/Views/Windows/MainWindow.axaml b/Aaru.Gui/Views/Windows/MainWindow.axaml
index cc2a4f3db..a78501e96 100644
--- a/Aaru.Gui/Views/Windows/MainWindow.axaml
+++ b/Aaru.Gui/Views/Windows/MainWindow.axaml
@@ -58,6 +58,11 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Aaru.Gui/Views/Windows/MetadataEditor.axaml.cs b/Aaru.Gui/Views/Windows/MetadataEditor.axaml.cs
new file mode 100644
index 000000000..b0aa197b9
--- /dev/null
+++ b/Aaru.Gui/Views/Windows/MetadataEditor.axaml.cs
@@ -0,0 +1,51 @@
+// /***************************************************************************
+// Aaru Data Preservation Suite
+// ----------------------------------------------------------------------------
+//
+// Filename : MetadataEditor.axaml.cs
+// Author(s) : Natalia Portillo
+//
+// Component : GUI windows.
+//
+// --[ Description ] ----------------------------------------------------------
+//
+// Metadata editor 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 .
+//
+// ----------------------------------------------------------------------------
+// Copyright © 2011-2025 Natalia Portillo
+// ****************************************************************************/
+
+using Aaru.Gui.ViewModels.Windows;
+using Avalonia.Controls;
+
+namespace Aaru.Gui.Views.Windows;
+
+public partial class MetadataEditor : Window
+{
+ public MetadataEditor()
+ {
+ InitializeComponent();
+ DataContext = new MetadataEditorViewModel(this);
+ }
+
+ public MetadataEditor(string existingFilePath)
+ {
+ InitializeComponent();
+ DataContext = new MetadataEditorViewModel(this, existingFilePath);
+ }
+}
\ No newline at end of file