mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 11:14:25 +00:00
862 lines
26 KiB
C#
862 lines
26 KiB
C#
// /***************************************************************************
|
|
// Aaru Data Preservation Suite
|
|
// ----------------------------------------------------------------------------
|
|
//
|
|
// Filename : MetadataEditorViewModel.cs
|
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
|
//
|
|
// 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 <http://www.gnu.org/licenses/>.
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
// 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.Helpers;
|
|
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<AdvertisementViewModel> _advertisements = [];
|
|
|
|
[ObservableProperty]
|
|
ObservableCollection<Architecture> _architectures = [];
|
|
|
|
[ObservableProperty]
|
|
ObservableCollection<AudioMediaViewModel> _audioMedias = [];
|
|
|
|
[ObservableProperty]
|
|
ObservableCollection<string> _authors = [];
|
|
|
|
// Complex object lists
|
|
[ObservableProperty]
|
|
ObservableCollection<BarcodeViewModel> _barcodes = [];
|
|
|
|
[ObservableProperty]
|
|
ObservableCollection<BlockMediaViewModel> _blockMedias = [];
|
|
|
|
[ObservableProperty]
|
|
ObservableCollection<BookViewModel> _books = [];
|
|
|
|
[ObservableProperty]
|
|
ObservableCollection<string> _categories = [];
|
|
|
|
// String lists
|
|
[ObservableProperty]
|
|
ObservableCollection<string> _developers = [];
|
|
|
|
[ObservableProperty]
|
|
string _filePath;
|
|
|
|
[ObservableProperty]
|
|
ObservableCollection<string> _keywords = [];
|
|
|
|
// Enum lists
|
|
[ObservableProperty]
|
|
ObservableCollection<Language> _languages = [];
|
|
|
|
[ObservableProperty]
|
|
ObservableCollection<LinearMediaViewModel> _linearMedias = [];
|
|
|
|
[ObservableProperty]
|
|
ObservableCollection<MagazineViewModel> _magazines = [];
|
|
|
|
// Basic metadata fields
|
|
[ObservableProperty]
|
|
string _name;
|
|
|
|
[ObservableProperty]
|
|
ObservableCollection<OpticalDiscViewModel> _opticalDiscs = [];
|
|
|
|
[ObservableProperty]
|
|
string _partNumber;
|
|
|
|
[ObservableProperty]
|
|
ObservableCollection<PciViewModel> _pciCards = [];
|
|
|
|
[ObservableProperty]
|
|
ObservableCollection<string> _performers = [];
|
|
|
|
[ObservableProperty]
|
|
ObservableCollection<string> _publishers = [];
|
|
|
|
[ObservableProperty]
|
|
DateTime? _releaseDate;
|
|
|
|
[ObservableProperty]
|
|
ObservableCollection<RequiredOperatingSystemViewModel> _requiredOperatingSystems = [];
|
|
|
|
[ObservableProperty]
|
|
LocalizedEnumValue<ReleaseType> _selectedReleaseType;
|
|
|
|
[ObservableProperty]
|
|
string _serialNumber;
|
|
|
|
[ObservableProperty]
|
|
ObservableCollection<string> _subcategories = [];
|
|
|
|
[ObservableProperty]
|
|
ObservableCollection<string> _systems = [];
|
|
|
|
[ObservableProperty]
|
|
string _title;
|
|
|
|
[ObservableProperty]
|
|
ObservableCollection<UserManualViewModel> _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<LocalizedEnumValue<ReleaseType>> AvailableReleaseTypes =>
|
|
LocalizedEnumHelper.GetLocalizedValues<ReleaseType>();
|
|
[NotNull]
|
|
public IEnumerable<Language> AvailableLanguages => Enum.GetValues<Language>();
|
|
[NotNull]
|
|
public IEnumerable<Architecture> AvailableArchitectures => Enum.GetValues<Architecture>();
|
|
[NotNull]
|
|
public IEnumerable<BarcodeType> AvailableBarcodeTypes => Enum.GetValues<BarcodeType>();
|
|
|
|
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.HasValue
|
|
? new LocalizedEnumValue<ReleaseType>(metadata.Release.Value)
|
|
: null;
|
|
|
|
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<string> source, ObservableCollection<string> target)
|
|
{
|
|
if(source == null) return;
|
|
|
|
target.Clear();
|
|
foreach(string item in source) target.Add(item);
|
|
}
|
|
|
|
static void LoadEnumList<T>([CanBeNull] List<T> source, ObservableCollection<T> 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?.Value,
|
|
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<string> _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
|
|
};
|
|
} |