mirror of
https://github.com/aaru-dps/Aaru.git
synced 2026-07-08 18:16:24 +00:00
[GUI] Add archive information and subdirectory panels with data models
This commit is contained in:
@@ -38,6 +38,7 @@ using System.Collections.Generic;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using Aaru.CommonTypes.Enums;
|
using Aaru.CommonTypes.Enums;
|
||||||
using Aaru.CommonTypes.Structs;
|
using Aaru.CommonTypes.Structs;
|
||||||
|
using Aaru.Localization;
|
||||||
|
|
||||||
namespace Aaru.CommonTypes.Interfaces;
|
namespace Aaru.CommonTypes.Interfaces;
|
||||||
|
|
||||||
@@ -46,28 +47,35 @@ namespace Aaru.CommonTypes.Interfaces;
|
|||||||
public enum ArchiveSupportedFeature : uint
|
public enum ArchiveSupportedFeature : uint
|
||||||
{
|
{
|
||||||
/// <summary>The archive supports filenames for its entries. If this flag is not set, files can only be accessed by number.</summary>
|
/// <summary>The archive supports filenames for its entries. If this flag is not set, files can only be accessed by number.</summary>
|
||||||
|
[LocalizedDescription(nameof(UI.Archive_supports_filenames))]
|
||||||
SupportsFilenames = 1 << 0,
|
SupportsFilenames = 1 << 0,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The archive supports compression. If this flag is not set, compressed and uncompressed lengths are always the
|
/// The archive supports compression. If this flag is not set, compressed and uncompressed lengths are always the
|
||||||
/// same.
|
/// same.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[LocalizedDescription(nameof(UI.Archive_supports_compression))]
|
||||||
SupportsCompression = 1 << 1,
|
SupportsCompression = 1 << 1,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The archive supports subdirectories. If this flag is not set, all filenames are guaranteed to not contain any
|
/// The archive supports subdirectories. If this flag is not set, all filenames are guaranteed to not contain any
|
||||||
/// "/" character.
|
/// "/" character.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[LocalizedDescription(nameof(UI.Archive_supports_subdirectories))]
|
||||||
SupportsSubdirectories = 1 << 2,
|
SupportsSubdirectories = 1 << 2,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The archive supports explicit entries for directories (like Zip, for example). If this flag is not set,
|
/// The archive supports explicit entries for directories (like Zip, for example). If this flag is not set,
|
||||||
/// directories are implicit by the relative name of the files.
|
/// directories are implicit by the relative name of the files.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[LocalizedDescription(nameof(UI.Archive_has_explicit_directories))]
|
||||||
HasExplicitDirectories = 1 << 3,
|
HasExplicitDirectories = 1 << 3,
|
||||||
/// <summary>The archive stores a timestamp with each entry if this flag is set.</summary>
|
/// <summary>The archive stores a timestamp with each entry if this flag is set.</summary>
|
||||||
|
[LocalizedDescription(nameof(UI.Archive_has_entry_timestamp))]
|
||||||
HasEntryTimestamp = 1 << 4,
|
HasEntryTimestamp = 1 << 4,
|
||||||
/// <summary>If this flag is set, individual files or the whole archive might be encrypted or password-protected.</summary>
|
/// <summary>If this flag is set, individual files or the whole archive might be encrypted or password-protected.</summary>
|
||||||
|
[LocalizedDescription(nameof(UI.Archive_supports_protection))]
|
||||||
SupportsProtection = 1 << 5, // TODO: not implemented yet
|
SupportsProtection = 1 << 5, // TODO: not implemented yet
|
||||||
|
|
||||||
/// <summary>If this flag is set, the archive supports returning extended attributes (Xattrs) for each entry.</summary>
|
/// <summary>If this flag is set, the archive supports returning extended attributes (Xattrs) for each entry.</summary>
|
||||||
|
[LocalizedDescription(nameof(UI.Archive_supports_xattrs))]
|
||||||
SupportsXAttrs = 1 << 6
|
SupportsXAttrs = 1 << 6
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
75
Aaru.Gui/Models/ArchiveFileModel.cs
Normal file
75
Aaru.Gui/Models/ArchiveFileModel.cs
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
// /***************************************************************************
|
||||||
|
// Aaru Data Preservation Suite
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Filename : ArchiveFileModel.cs
|
||||||
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||||
|
//
|
||||||
|
// Component : GUI data models.
|
||||||
|
//
|
||||||
|
// --[ Description ] ----------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Contains information about a file entry inside an archive.
|
||||||
|
//
|
||||||
|
// --[ 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-2026 Natalia Portillo
|
||||||
|
// ****************************************************************************/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Aaru.CommonTypes.Structs;
|
||||||
|
using Avalonia.Media;
|
||||||
|
|
||||||
|
namespace Aaru.Gui.Models;
|
||||||
|
|
||||||
|
public sealed class ArchiveFileModel
|
||||||
|
{
|
||||||
|
public int EntryNumber { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public string Size => $"{Stat?.Length ?? 0}";
|
||||||
|
|
||||||
|
public string CreationTime =>
|
||||||
|
Stat is null || Stat.CreationTime == default(DateTime) ? "" : $"{Stat.CreationTime:G}";
|
||||||
|
|
||||||
|
public string LastAccessTime => Stat is null || Stat.AccessTime == default(DateTime) ? "" : $"{Stat.AccessTime:G}";
|
||||||
|
|
||||||
|
public string ChangedTime => Stat is null || Stat.StatusChangeTime == default(DateTime)
|
||||||
|
? ""
|
||||||
|
: $"{Stat.StatusChangeTime:G}";
|
||||||
|
|
||||||
|
public string LastBackupTime => Stat is null || Stat.BackupTime == default(DateTime) ? "" : $"{Stat.BackupTime:G}";
|
||||||
|
|
||||||
|
public string LastWriteTime => Stat is null || Stat.LastWriteTime == default(DateTime)
|
||||||
|
? ""
|
||||||
|
: $"{Stat.LastWriteTime:G}";
|
||||||
|
|
||||||
|
public string Attributes => Stat is null ? "" : $"{Stat.Attributes}";
|
||||||
|
|
||||||
|
public string Gid => Stat is null ? "" : $"{Stat.GID}";
|
||||||
|
|
||||||
|
public string Uid => Stat is null ? "" : $"{Stat.UID}";
|
||||||
|
|
||||||
|
public string Inode => Stat is null ? "" : $"{Stat.Inode}";
|
||||||
|
|
||||||
|
public string Links => Stat is null ? "" : $"{Stat.Links}";
|
||||||
|
|
||||||
|
public string Mode => Stat is null ? "" : $"{Stat.Mode}";
|
||||||
|
|
||||||
|
public FileEntryInfo Stat { get; set; }
|
||||||
|
public IBrush Color { get; set; }
|
||||||
|
}
|
||||||
49
Aaru.Gui/Models/ArchiveModel.cs
Normal file
49
Aaru.Gui/Models/ArchiveModel.cs
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
// /***************************************************************************
|
||||||
|
// Aaru Data Preservation Suite
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Filename : ArchiveModel.cs
|
||||||
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||||
|
//
|
||||||
|
// Component : GUI data models.
|
||||||
|
//
|
||||||
|
// --[ Description ] ----------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Contains information about an opened archive.
|
||||||
|
//
|
||||||
|
// --[ 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-2026 Natalia Portillo
|
||||||
|
// ****************************************************************************/
|
||||||
|
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using Aaru.CommonTypes.Interfaces;
|
||||||
|
using Aaru.Gui.ViewModels.Panels;
|
||||||
|
using Avalonia.Media;
|
||||||
|
|
||||||
|
namespace Aaru.Gui.Models;
|
||||||
|
|
||||||
|
public sealed class ArchiveModel : RootModel
|
||||||
|
{
|
||||||
|
public string Path { get; set; }
|
||||||
|
public string FileName { get; set; }
|
||||||
|
public IImage Icon { get; set; }
|
||||||
|
public IArchive Archive { get; set; }
|
||||||
|
public IFilter Filter { get; set; }
|
||||||
|
public ArchiveInfoViewModel ViewModel { get; set; }
|
||||||
|
public ObservableCollection<ArchiveSubdirectoryModel> Roots { get; set; } = [];
|
||||||
|
}
|
||||||
47
Aaru.Gui/Models/ArchiveSubdirectoryModel.cs
Normal file
47
Aaru.Gui/Models/ArchiveSubdirectoryModel.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
// /***************************************************************************
|
||||||
|
// Aaru Data Preservation Suite
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Filename : ArchiveSubdirectoryModel.cs
|
||||||
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||||
|
//
|
||||||
|
// Component : GUI data models.
|
||||||
|
//
|
||||||
|
// --[ Description ] ----------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Contains information about a virtual subdirectory inside an archive.
|
||||||
|
//
|
||||||
|
// --[ 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-2026 Natalia Portillo
|
||||||
|
// ****************************************************************************/
|
||||||
|
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using Aaru.CommonTypes.Interfaces;
|
||||||
|
using Avalonia.Media.Imaging;
|
||||||
|
|
||||||
|
namespace Aaru.Gui.Models;
|
||||||
|
|
||||||
|
public sealed class ArchiveSubdirectoryModel
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Path { get; set; }
|
||||||
|
public IArchive Archive { get; set; }
|
||||||
|
public ObservableCollection<ArchiveSubdirectoryModel> Subdirectories { get; set; } = [];
|
||||||
|
public ObservableCollection<ArchiveFileModel> Entries { get; set; } = [];
|
||||||
|
public Bitmap Icon { get; set; }
|
||||||
|
}
|
||||||
61
Aaru.Gui/ViewModels/Panels/ArchiveInfoViewModel.cs
Normal file
61
Aaru.Gui/ViewModels/Panels/ArchiveInfoViewModel.cs
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
// /***************************************************************************
|
||||||
|
// Aaru Data Preservation Suite
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Filename : ArchiveInfoViewModel.cs
|
||||||
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||||
|
//
|
||||||
|
// Component : GUI view models.
|
||||||
|
//
|
||||||
|
// --[ Description ] ----------------------------------------------------------
|
||||||
|
//
|
||||||
|
// View model and code for the opened archive information panel.
|
||||||
|
//
|
||||||
|
// --[ 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-2026 Natalia Portillo
|
||||||
|
// ****************************************************************************/
|
||||||
|
|
||||||
|
using Aaru.CommonTypes.Interfaces;
|
||||||
|
using Aaru.Localization;
|
||||||
|
using Humanizer;
|
||||||
|
|
||||||
|
namespace Aaru.Gui.ViewModels.Panels;
|
||||||
|
|
||||||
|
public sealed class ArchiveInfoViewModel
|
||||||
|
{
|
||||||
|
public ArchiveInfoViewModel(string path, IFilter filter, IArchive archive)
|
||||||
|
{
|
||||||
|
ArchivePathText = string.Format($"[blue]{path}[/]");
|
||||||
|
FilterText = string.Format(UI.Filter_0, filter.Name);
|
||||||
|
PluginText = string.Format(UI.Archive_plugin_0, archive.Name);
|
||||||
|
PluginIdText = string.Format(UI.Archive_plugin_id_0, archive.Id);
|
||||||
|
NumberOfEntriesText = string.Format(UI.Archive_number_of_entries_0, archive.NumberOfEntries);
|
||||||
|
FeaturesText = string.Format(UI.Archive_features_0, archive.ArchiveFeatures.Humanize());
|
||||||
|
|
||||||
|
archive.GetInformation(filter, null, out string information);
|
||||||
|
InformationText = information ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ArchivePathText { get; }
|
||||||
|
public string FilterText { get; }
|
||||||
|
public string PluginText { get; }
|
||||||
|
public string PluginIdText { get; }
|
||||||
|
public string NumberOfEntriesText { get; }
|
||||||
|
public string FeaturesText { get; }
|
||||||
|
public string InformationText { get; }
|
||||||
|
}
|
||||||
310
Aaru.Gui/ViewModels/Panels/ArchiveSubdirectoryViewModel.cs
Normal file
310
Aaru.Gui/ViewModels/Panels/ArchiveSubdirectoryViewModel.cs
Normal file
@@ -0,0 +1,310 @@
|
|||||||
|
// /***************************************************************************
|
||||||
|
// Aaru Data Preservation Suite
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Filename : ArchiveSubdirectoryViewModel.cs
|
||||||
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||||
|
//
|
||||||
|
// Component : GUI view models.
|
||||||
|
//
|
||||||
|
// --[ Description ] ----------------------------------------------------------
|
||||||
|
//
|
||||||
|
// View model and code for the archive subdirectory contents panel.
|
||||||
|
//
|
||||||
|
// --[ 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-2026 Natalia Portillo
|
||||||
|
// ****************************************************************************/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using Aaru.CommonTypes.Enums;
|
||||||
|
using Aaru.CommonTypes.Interfaces;
|
||||||
|
using Aaru.CommonTypes.Interop;
|
||||||
|
using Aaru.Core;
|
||||||
|
using Aaru.Gui.Models;
|
||||||
|
using Aaru.Helpers;
|
||||||
|
using Aaru.Localization;
|
||||||
|
using Aaru.Logging;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Media;
|
||||||
|
using Avalonia.Platform.Storage;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
using MsBox.Avalonia;
|
||||||
|
using MsBox.Avalonia.Enums;
|
||||||
|
using Sentry;
|
||||||
|
|
||||||
|
namespace Aaru.Gui.ViewModels.Panels;
|
||||||
|
|
||||||
|
public sealed class ArchiveSubdirectoryViewModel
|
||||||
|
{
|
||||||
|
const string MODULE_NAME = "Archive Subdirectory ViewModel";
|
||||||
|
readonly ArchiveSubdirectoryModel _model;
|
||||||
|
readonly Window _view;
|
||||||
|
|
||||||
|
public ArchiveSubdirectoryViewModel(ArchiveSubdirectoryModel model, Window view)
|
||||||
|
{
|
||||||
|
Entries = [];
|
||||||
|
SelectedEntries = [];
|
||||||
|
ExtractFilesCommand = new AsyncRelayCommand(ExtractFiles);
|
||||||
|
_model = model;
|
||||||
|
_view = view;
|
||||||
|
|
||||||
|
foreach(ArchiveFileModel entry in model.Entries)
|
||||||
|
{
|
||||||
|
entry.Color =
|
||||||
|
new SolidColorBrush(Color.Parse(DirColorsParser.Instance.ExtensionColors
|
||||||
|
.TryGetValue(Path.GetExtension(entry.Name),
|
||||||
|
out string hex)
|
||||||
|
? hex
|
||||||
|
: DirColorsParser.Instance.NormalColor));
|
||||||
|
|
||||||
|
Entries.Add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObservableCollection<ArchiveFileModel> Entries { get; }
|
||||||
|
public List<ArchiveFileModel> SelectedEntries { get; }
|
||||||
|
public ICommand ExtractFilesCommand { get; }
|
||||||
|
|
||||||
|
async Task ExtractFiles()
|
||||||
|
{
|
||||||
|
if(SelectedEntries.Count == 0) return;
|
||||||
|
|
||||||
|
IReadOnlyList<IStorageFolder> result =
|
||||||
|
await _view.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
|
||||||
|
{
|
||||||
|
Title = UI.Dialog_Choose_destination_folder,
|
||||||
|
AllowMultiple = false
|
||||||
|
});
|
||||||
|
|
||||||
|
if(result.Count != 1) return;
|
||||||
|
|
||||||
|
Statistics.AddCommand("extract-files");
|
||||||
|
|
||||||
|
string folder = result[0].Path.AbsolutePath;
|
||||||
|
|
||||||
|
foreach(ArchiveFileModel file in SelectedEntries)
|
||||||
|
{
|
||||||
|
string filename = file.Name;
|
||||||
|
|
||||||
|
ButtonResult mboxResult;
|
||||||
|
|
||||||
|
if(DetectOS.IsWindows)
|
||||||
|
{
|
||||||
|
if(filename.Contains('<') ||
|
||||||
|
filename.Contains('>') ||
|
||||||
|
filename.Contains(':') ||
|
||||||
|
filename.Contains('\\') ||
|
||||||
|
filename.Contains('/') ||
|
||||||
|
filename.Contains('|') ||
|
||||||
|
filename.Contains('?') ||
|
||||||
|
filename.Contains('*') ||
|
||||||
|
filename.Any(static c => c < 32) ||
|
||||||
|
filename.Equals("CON", StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
|
filename.Equals("PRN", StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
|
filename.Equals("AUX", StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
|
filename.Equals("COM1", StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
|
filename.Equals("COM2", StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
|
filename.Equals("COM3", StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
|
filename.Equals("COM4", StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
|
filename.Equals("COM5", StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
|
filename.Equals("COM6", StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
|
filename.Equals("COM7", StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
|
filename.Equals("COM8", StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
|
filename.Equals("COM9", StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
|
filename.Equals("LPT1", StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
|
filename.Equals("LPT2", StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
|
filename.Equals("LPT3", StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
|
filename.Equals("LPT4", StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
|
filename.Equals("LPT5", StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
|
filename.Equals("LPT6", StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
|
filename.Equals("LPT7", StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
|
filename.Equals("LPT8", StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
|
filename.Equals("LPT9", StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
|
filename[^1] == '.' ||
|
||||||
|
filename[^1] == ' ')
|
||||||
|
{
|
||||||
|
char[] chars;
|
||||||
|
|
||||||
|
if(filename[^1] == '.' || filename[^1] == ' ')
|
||||||
|
chars = new char[filename.Length - 1];
|
||||||
|
else
|
||||||
|
chars = new char[filename.Length];
|
||||||
|
|
||||||
|
for(var ci = 0; ci < chars.Length; ci++)
|
||||||
|
{
|
||||||
|
chars[ci] = filename[ci] switch
|
||||||
|
{
|
||||||
|
'<'
|
||||||
|
or '>'
|
||||||
|
or ':'
|
||||||
|
or '\\'
|
||||||
|
or '/'
|
||||||
|
or '|'
|
||||||
|
or '?'
|
||||||
|
or '*'
|
||||||
|
or >= '\u0000' and <= '\u001F' => '_',
|
||||||
|
_ => filename[ci]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if(filename.StartsWith("CON", StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
|
filename.StartsWith("PRN", StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
|
filename.StartsWith("AUX", StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
|
filename.StartsWith("COM", StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
|
filename.StartsWith("LPT", StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
chars[0] = '_';
|
||||||
|
chars[1] = '_';
|
||||||
|
chars[2] = '_';
|
||||||
|
}
|
||||||
|
|
||||||
|
string corrected = new(chars);
|
||||||
|
|
||||||
|
mboxResult = await MessageBoxManager.GetMessageBoxStandard(UI.Unsupported_filename,
|
||||||
|
string
|
||||||
|
.Format(UI
|
||||||
|
.Filename_0_not_supported_want_to_rename_to_1,
|
||||||
|
filename,
|
||||||
|
corrected),
|
||||||
|
ButtonEnum.YesNoCancel,
|
||||||
|
Icon.Warning)
|
||||||
|
.ShowWindowDialogAsync(_view);
|
||||||
|
|
||||||
|
switch(mboxResult)
|
||||||
|
{
|
||||||
|
case ButtonResult.Cancel:
|
||||||
|
return;
|
||||||
|
case ButtonResult.No:
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
filename = corrected;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string outputPath = Path.Combine(folder, filename);
|
||||||
|
|
||||||
|
if(File.Exists(outputPath))
|
||||||
|
{
|
||||||
|
mboxResult = await MessageBoxManager.GetMessageBoxStandard(UI.Existing_file,
|
||||||
|
string
|
||||||
|
.Format(UI.File_named_0_exists_overwrite_Q,
|
||||||
|
filename),
|
||||||
|
ButtonEnum.YesNoCancel,
|
||||||
|
Icon.Warning)
|
||||||
|
.ShowWindowDialogAsync(_view);
|
||||||
|
|
||||||
|
switch(mboxResult)
|
||||||
|
{
|
||||||
|
case ButtonResult.Cancel:
|
||||||
|
return;
|
||||||
|
case ButtonResult.No:
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File.Delete(outputPath);
|
||||||
|
}
|
||||||
|
catch(IOException)
|
||||||
|
{
|
||||||
|
mboxResult = await MessageBoxManager.GetMessageBoxStandard(UI.Cannot_delete,
|
||||||
|
UI.Could_note_delete_existe_file_continue_Q,
|
||||||
|
ButtonEnum.YesNo,
|
||||||
|
Icon.Error)
|
||||||
|
.ShowWindowDialogAsync(_view);
|
||||||
|
|
||||||
|
if(mboxResult == ButtonResult.No) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ErrorNumber error = _model.Archive.GetEntry(file.EntryNumber, out IFilter entryFilter);
|
||||||
|
|
||||||
|
if(error != ErrorNumber.NoError || entryFilter is null)
|
||||||
|
{
|
||||||
|
AaruLogging.Debug(MODULE_NAME, string.Format(UI.Skipped_non_regular_archive_entry_0, file.Name));
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
using(Stream inStream = entryFilter.GetDataForkStream())
|
||||||
|
{
|
||||||
|
await using(var fs = new FileStream(outputPath,
|
||||||
|
FileMode.CreateNew,
|
||||||
|
FileAccess.ReadWrite,
|
||||||
|
FileShare.None))
|
||||||
|
{
|
||||||
|
await inStream.CopyToAsync(fs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var fi = new FileInfo(outputPath);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if(file.Stat?.CreationTimeUtc is not null) fi.CreationTimeUtc = file.Stat.CreationTimeUtc.Value;
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
SentrySdk.CaptureException(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if(file.Stat?.LastWriteTimeUtc is not null) fi.LastWriteTimeUtc = file.Stat.LastWriteTimeUtc.Value;
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
SentrySdk.CaptureException(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if(file.Stat?.AccessTimeUtc is not null) fi.LastAccessTimeUtc = file.Stat.AccessTimeUtc.Value;
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
SentrySdk.CaptureException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(IOException)
|
||||||
|
{
|
||||||
|
mboxResult = await MessageBoxManager.GetMessageBoxStandard(UI.Cannot_create_file,
|
||||||
|
UI
|
||||||
|
.Could_not_create_destination_file_continue_Q,
|
||||||
|
ButtonEnum.YesNo,
|
||||||
|
Icon.Error)
|
||||||
|
.ShowWindowDialogAsync(_view);
|
||||||
|
|
||||||
|
if(mboxResult == ButtonResult.No) return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -41,6 +41,7 @@ using Aaru.CommonTypes;
|
|||||||
using Aaru.CommonTypes.Enums;
|
using Aaru.CommonTypes.Enums;
|
||||||
using Aaru.CommonTypes.Interfaces;
|
using Aaru.CommonTypes.Interfaces;
|
||||||
using Aaru.CommonTypes.Interop;
|
using Aaru.CommonTypes.Interop;
|
||||||
|
using Aaru.CommonTypes.Structs;
|
||||||
using Aaru.Core;
|
using Aaru.Core;
|
||||||
using Aaru.Database;
|
using Aaru.Database;
|
||||||
using Aaru.Gui.Models;
|
using Aaru.Gui.Models;
|
||||||
@@ -67,6 +68,7 @@ using MsBox.Avalonia.Dto;
|
|||||||
using MsBox.Avalonia.Enums;
|
using MsBox.Avalonia.Enums;
|
||||||
using MsBox.Avalonia.Models;
|
using MsBox.Avalonia.Models;
|
||||||
using Spectre.Console;
|
using Spectre.Console;
|
||||||
|
using ArchiveInfo = Aaru.Gui.Views.Panels.ArchiveInfo;
|
||||||
using Console = Aaru.Gui.Views.Dialogs.Console;
|
using Console = Aaru.Gui.Views.Dialogs.Console;
|
||||||
using FileSystem = Aaru.CommonTypes.AaruMetadata.FileSystem;
|
using FileSystem = Aaru.CommonTypes.AaruMetadata.FileSystem;
|
||||||
using ImageInfo = Aaru.Gui.Views.Panels.ImageInfo;
|
using ImageInfo = Aaru.Gui.Views.Panels.ImageInfo;
|
||||||
@@ -83,6 +85,9 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
readonly SvgImage _genericOpticalIcon;
|
readonly SvgImage _genericOpticalIcon;
|
||||||
readonly SvgImage _genericTapeIcon;
|
readonly SvgImage _genericTapeIcon;
|
||||||
readonly Window _view;
|
readonly Window _view;
|
||||||
|
ArchiveModel _archive;
|
||||||
|
[ObservableProperty]
|
||||||
|
bool _archiveLoaded;
|
||||||
Console _console;
|
Console _console;
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
[CanBeNull]
|
[CanBeNull]
|
||||||
@@ -107,13 +112,13 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
SettingsCommand = new AsyncRelayCommand(SettingsAsync);
|
SettingsCommand = new AsyncRelayCommand(SettingsAsync);
|
||||||
ConsoleCommand = new RelayCommand(Console);
|
ConsoleCommand = new RelayCommand(Console);
|
||||||
OpenCommand = new AsyncRelayCommand(OpenAsync);
|
OpenCommand = new AsyncRelayCommand(OpenAsync);
|
||||||
CalculateEntropyCommand = new RelayCommand(CalculateEntropy);
|
CalculateEntropyCommand = new RelayCommand(CalculateEntropy, () => ImageLoaded);
|
||||||
VerifyImageCommand = new RelayCommand(VerifyImage);
|
VerifyImageCommand = new RelayCommand(VerifyImage, () => ImageLoaded);
|
||||||
ChecksumImageCommand = new RelayCommand(ChecksumImage);
|
ChecksumImageCommand = new RelayCommand(ChecksumImage, () => ImageLoaded);
|
||||||
ConvertImageCommand = new RelayCommand(ConvertImage);
|
ConvertImageCommand = new RelayCommand(ConvertImage, () => ImageLoaded);
|
||||||
CreateSidecarCommand = new RelayCommand(CreateSidecar);
|
CreateSidecarCommand = new RelayCommand(CreateSidecar, () => ImageLoaded);
|
||||||
ViewImageSectorsCommand = new RelayCommand(ViewImageSectors);
|
ViewImageSectorsCommand = new RelayCommand(ViewImageSectors, () => ImageLoaded);
|
||||||
DecodeImageMediaTagsCommand = new RelayCommand(DecodeImageMediaTags);
|
DecodeImageMediaTagsCommand = new RelayCommand(DecodeImageMediaTags, () => ImageLoaded);
|
||||||
OpenMhddLogCommand = new AsyncRelayCommand(OpenMhddLogAsync);
|
OpenMhddLogCommand = new AsyncRelayCommand(OpenMhddLogAsync);
|
||||||
OpenIbgLogCommand = new AsyncRelayCommand(OpenIbgLogAsync);
|
OpenIbgLogCommand = new AsyncRelayCommand(OpenIbgLogAsync);
|
||||||
ConnectToRemoteCommand = new AsyncRelayCommand(ConnectToRemoteAsync);
|
ConnectToRemoteCommand = new AsyncRelayCommand(ConnectToRemoteAsync);
|
||||||
@@ -240,6 +245,20 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
DataContext = new SubdirectoryViewModel(subdirectoryModel, _view)
|
DataContext = new SubdirectoryViewModel(subdirectoryModel, _view)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
break;
|
||||||
|
case ArchiveModel archiveModel:
|
||||||
|
ContentPanel = new ArchiveInfo
|
||||||
|
{
|
||||||
|
DataContext = archiveModel.ViewModel
|
||||||
|
};
|
||||||
|
|
||||||
|
break;
|
||||||
|
case ArchiveSubdirectoryModel archiveSubdirectoryModel:
|
||||||
|
ContentPanel = new ArchiveSubdirectory
|
||||||
|
{
|
||||||
|
DataContext = new ArchiveSubdirectoryViewModel(archiveSubdirectoryModel, _view)
|
||||||
|
};
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -388,7 +407,7 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
// TODO: Extensions
|
// TODO: Extensions
|
||||||
IReadOnlyList<IStorageFile> result = await _view.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
|
IReadOnlyList<IStorageFile> result = await _view.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
|
||||||
{
|
{
|
||||||
Title = UI.Dialog_Choose_image_to_open,
|
Title = UI.Dialog_Choose_file_to_open,
|
||||||
AllowMultiple = false,
|
AllowMultiple = false,
|
||||||
FileTypeFilter = [FilePickerFileTypes.All]
|
FileTypeFilter = [FilePickerFileTypes.All]
|
||||||
});
|
});
|
||||||
@@ -416,6 +435,11 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
{
|
{
|
||||||
// Detect the image format of the selected file
|
// Detect the image format of the selected file
|
||||||
if(ImageFormat.Detect(inputFilter) is not IMediaImage imageFormat)
|
if(ImageFormat.Detect(inputFilter) is not IMediaImage imageFormat)
|
||||||
|
{
|
||||||
|
// Try archive format as fallback
|
||||||
|
IArchive archiveFormat = ArchiveFormat.Detect(inputFilter);
|
||||||
|
|
||||||
|
if(archiveFormat is null)
|
||||||
{
|
{
|
||||||
IMsBox<ButtonResult> msbox = MessageBoxManager.GetMessageBoxStandard(UI.Title_Error,
|
IMsBox<ButtonResult> msbox = MessageBoxManager.GetMessageBoxStandard(UI.Title_Error,
|
||||||
UI.Image_format_not_identified,
|
UI.Image_format_not_identified,
|
||||||
@@ -427,6 +451,11 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await OpenArchiveAsync(archiveFormat, inputFilter, result[0].Path.LocalPath);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
AaruLogging.WriteLine(UI.Image_format_identified_by_0_1, Markup.Escape(imageFormat.Name), imageFormat.Id);
|
AaruLogging.WriteLine(UI.Image_format_identified_by_0_1, Markup.Escape(imageFormat.Name), imageFormat.Id);
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -666,6 +695,11 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
Statistics.AddMedia(imageFormat.Info.MediaType, false);
|
Statistics.AddMedia(imageFormat.Info.MediaType, false);
|
||||||
Statistics.AddFilter(inputFilter.Name);
|
Statistics.AddFilter(inputFilter.Name);
|
||||||
|
|
||||||
|
// Close any previously opened archive before replacing the tree
|
||||||
|
_archive?.Archive?.Close();
|
||||||
|
_archive = null;
|
||||||
|
ArchiveLoaded = false;
|
||||||
|
|
||||||
TreeRoot.Clear();
|
TreeRoot.Clear();
|
||||||
TreeRoot.Add(imageModel);
|
TreeRoot.Add(imageModel);
|
||||||
Title = $"Aaru - {imageModel.FileName}";
|
Title = $"Aaru - {imageModel.FileName}";
|
||||||
@@ -702,6 +736,144 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
Statistics.AddCommand("image-info");
|
Statistics.AddCommand("image-info");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async Task OpenArchiveAsync(IArchive archiveFormat, IFilter inputFilter, string path)
|
||||||
|
{
|
||||||
|
AaruLogging.WriteLine(UI.Archive_format_identified_by_0_1, Markup.Escape(archiveFormat.Name), archiveFormat.Id);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ErrorNumber opened = archiveFormat.Open(inputFilter, null);
|
||||||
|
|
||||||
|
if(opened != ErrorNumber.NoError)
|
||||||
|
{
|
||||||
|
IMsBox<ButtonResult> msbox = MessageBoxManager.GetMessageBoxStandard(UI.Title_Error,
|
||||||
|
string.Format(UI.Error_0_opening_archive_format, opened),
|
||||||
|
ButtonEnum.Ok,
|
||||||
|
Icon.Error);
|
||||||
|
|
||||||
|
await msbox.ShowAsync();
|
||||||
|
|
||||||
|
AaruLogging.Error(UI.Unable_to_open_archive_format);
|
||||||
|
AaruLogging.Error(UI.No_error_given);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var archiveModel = new ArchiveModel
|
||||||
|
{
|
||||||
|
Path = path,
|
||||||
|
FileName = Path.GetFileName(path),
|
||||||
|
Icon = _genericFolderIcon,
|
||||||
|
Archive = archiveFormat,
|
||||||
|
Filter = inputFilter,
|
||||||
|
ViewModel = new ArchiveInfoViewModel(path, inputFilter, archiveFormat)
|
||||||
|
};
|
||||||
|
|
||||||
|
var rootDir = new ArchiveSubdirectoryModel
|
||||||
|
{
|
||||||
|
Name = "/",
|
||||||
|
Path = "",
|
||||||
|
Archive = archiveFormat
|
||||||
|
};
|
||||||
|
|
||||||
|
bool supportsSubdirs =
|
||||||
|
archiveFormat.ArchiveFeatures.HasFlag(ArchiveSupportedFeature.SupportsSubdirectories);
|
||||||
|
|
||||||
|
for(var entryNumber = 0; entryNumber < archiveFormat.NumberOfEntries; entryNumber++)
|
||||||
|
{
|
||||||
|
ErrorNumber nameErr = archiveFormat.GetFilename(entryNumber, out string entryName);
|
||||||
|
|
||||||
|
if(nameErr != ErrorNumber.NoError || string.IsNullOrEmpty(entryName)) continue;
|
||||||
|
|
||||||
|
archiveFormat.Stat(entryNumber, out FileEntryInfo stat);
|
||||||
|
|
||||||
|
if(!supportsSubdirs || !entryName.Contains('/'))
|
||||||
|
{
|
||||||
|
rootDir.Entries.Add(new ArchiveFileModel
|
||||||
|
{
|
||||||
|
EntryNumber = entryNumber,
|
||||||
|
Name = entryName,
|
||||||
|
Stat = stat
|
||||||
|
});
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
string[] parts = entryName.Split('/');
|
||||||
|
ArchiveSubdirectoryModel current = rootDir;
|
||||||
|
|
||||||
|
for(var i = 0; i < parts.Length - 1; i++)
|
||||||
|
{
|
||||||
|
string part = parts[i];
|
||||||
|
|
||||||
|
if(string.IsNullOrEmpty(part)) continue;
|
||||||
|
|
||||||
|
ArchiveSubdirectoryModel child = current.Subdirectories.FirstOrDefault(s => s.Name == part);
|
||||||
|
|
||||||
|
if(child == null)
|
||||||
|
{
|
||||||
|
child = new ArchiveSubdirectoryModel
|
||||||
|
{
|
||||||
|
Name = part,
|
||||||
|
Path = string.Join('/', parts, 0, i + 1),
|
||||||
|
Archive = archiveFormat
|
||||||
|
};
|
||||||
|
|
||||||
|
current.Subdirectories.Add(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
current = child;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the entry itself is a directory (trailing slash) skip adding as a file
|
||||||
|
string leaf = parts[^1];
|
||||||
|
|
||||||
|
if(string.IsNullOrEmpty(leaf))
|
||||||
|
{
|
||||||
|
// Entry represents a directory; ensure it's present as subdirectory
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
current.Entries.Add(new ArchiveFileModel
|
||||||
|
{
|
||||||
|
EntryNumber = entryNumber,
|
||||||
|
Name = leaf,
|
||||||
|
Stat = stat
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
archiveModel.Roots.Add(rootDir);
|
||||||
|
|
||||||
|
Statistics.AddFilter(inputFilter.Name);
|
||||||
|
|
||||||
|
// Close any previously opened archive before replacing the tree
|
||||||
|
_archive?.Archive?.Close();
|
||||||
|
|
||||||
|
TreeRoot.Clear();
|
||||||
|
TreeRoot.Add(archiveModel);
|
||||||
|
Title = $"Aaru - {archiveModel.FileName}";
|
||||||
|
_image = null;
|
||||||
|
ImageLoaded = false;
|
||||||
|
_archive = archiveModel;
|
||||||
|
ArchiveLoaded = true;
|
||||||
|
|
||||||
|
Statistics.AddCommand("archive-info");
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
IMsBox<ButtonResult> msbox = MessageBoxManager.GetMessageBoxStandard(UI.Title_Error,
|
||||||
|
UI.Unable_to_open_archive_format,
|
||||||
|
ButtonEnum.Ok,
|
||||||
|
Icon.Error);
|
||||||
|
|
||||||
|
await msbox.ShowAsync();
|
||||||
|
|
||||||
|
AaruLogging.Error(UI.Unable_to_open_archive_format);
|
||||||
|
AaruLogging.Error(Aaru.Localization.Core.Error_0, ex.Message);
|
||||||
|
AaruLogging.Exception(ex, Aaru.Localization.Core.Error_0, ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Task AboutAsync()
|
Task AboutAsync()
|
||||||
{
|
{
|
||||||
var dialog = new About();
|
var dialog = new About();
|
||||||
@@ -757,8 +929,24 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
return dialog.ShowDialog(_view);
|
return dialog.ShowDialog(_view);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Exit() =>
|
internal void Exit()
|
||||||
|
{
|
||||||
|
_archive?.Archive?.Close();
|
||||||
|
_archive = null;
|
||||||
|
|
||||||
(Application.Current?.ApplicationLifetime as ClassicDesktopStyleApplicationLifetime)?.Shutdown();
|
(Application.Current?.ApplicationLifetime as ClassicDesktopStyleApplicationLifetime)?.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
partial void OnImageLoadedChanged(bool value)
|
||||||
|
{
|
||||||
|
(CalculateEntropyCommand as IRelayCommand)?.NotifyCanExecuteChanged();
|
||||||
|
(VerifyImageCommand as IRelayCommand)?.NotifyCanExecuteChanged();
|
||||||
|
(ChecksumImageCommand as IRelayCommand)?.NotifyCanExecuteChanged();
|
||||||
|
(ConvertImageCommand as IRelayCommand)?.NotifyCanExecuteChanged();
|
||||||
|
(CreateSidecarCommand as IRelayCommand)?.NotifyCanExecuteChanged();
|
||||||
|
(ViewImageSectorsCommand as IRelayCommand)?.NotifyCanExecuteChanged();
|
||||||
|
(DecodeImageMediaTagsCommand as IRelayCommand)?.NotifyCanExecuteChanged();
|
||||||
|
}
|
||||||
|
|
||||||
void Console()
|
void Console()
|
||||||
{
|
{
|
||||||
|
|||||||
82
Aaru.Gui/Views/Panels/ArchiveInfo.xaml
Normal file
82
Aaru.Gui/Views/Panels/ArchiveInfo.xaml
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
<!--
|
||||||
|
// /***************************************************************************
|
||||||
|
// Aaru Data Preservation Suite
|
||||||
|
// ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
|
||||||
|
//
|
||||||
|
// Filename : ArchiveInfo.xaml
|
||||||
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||||
|
//
|
||||||
|
// Component : GUI panel.
|
||||||
|
//
|
||||||
|
// ‐‐[ Description ] ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
|
||||||
|
//
|
||||||
|
// Archive information panel.
|
||||||
|
//
|
||||||
|
// ‐‐[ 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-2026 Natalia Portillo
|
||||||
|
// ****************************************************************************/
|
||||||
|
-->
|
||||||
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:panels="clr-namespace:Aaru.Gui.ViewModels.Panels"
|
||||||
|
xmlns:localization="clr-namespace:Aaru.Localization;assembly=Aaru.Localization"
|
||||||
|
xmlns:controls="clr-namespace:Aaru.Gui.Controls"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignWidth="800"
|
||||||
|
d:DesignHeight="450"
|
||||||
|
x:DataType="panels:ArchiveInfoViewModel"
|
||||||
|
x:Class="Aaru.Gui.Views.Panels.ArchiveInfo">
|
||||||
|
<Grid RowDefinitions="Auto,*"
|
||||||
|
Margin="12"
|
||||||
|
RowSpacing="8">
|
||||||
|
<StackPanel Grid.Row="0"
|
||||||
|
Spacing="8">
|
||||||
|
<controls:SpectreTextBlock FontWeight="Bold"
|
||||||
|
Text="{x:Static localization:UI.Title_Archive_information}" />
|
||||||
|
<controls:SpectreTextBlock Text="{Binding ArchivePathText, Mode=OneWay}"
|
||||||
|
TextWrapping="Wrap" />
|
||||||
|
<controls:SpectreTextBlock Text="{Binding FilterText, Mode=OneWay}"
|
||||||
|
TextWrapping="Wrap" />
|
||||||
|
<controls:SpectreTextBlock Text="{Binding PluginText, Mode=OneWay}"
|
||||||
|
TextWrapping="Wrap" />
|
||||||
|
<controls:SpectreTextBlock Text="{Binding PluginIdText, Mode=OneWay}"
|
||||||
|
TextWrapping="Wrap" />
|
||||||
|
<controls:SpectreTextBlock Text="{Binding NumberOfEntriesText, Mode=OneWay}"
|
||||||
|
TextWrapping="Wrap" />
|
||||||
|
<controls:SpectreTextBlock Text="{Binding FeaturesText, Mode=OneWay}"
|
||||||
|
TextWrapping="Wrap" />
|
||||||
|
</StackPanel>
|
||||||
|
<Border Grid.Row="1"
|
||||||
|
BorderThickness="1"
|
||||||
|
BorderBrush="{DynamicResource SystemControlForegroundBaseMediumLowBrush}"
|
||||||
|
CornerRadius="8"
|
||||||
|
IsVisible="{Binding !!InformationText, Mode=OneWay}">
|
||||||
|
<StackPanel Spacing="8"
|
||||||
|
Margin="12">
|
||||||
|
<controls:SpectreTextBlock FontWeight="Bold"
|
||||||
|
Text="{x:Static localization:UI.Title_Details}" />
|
||||||
|
<ScrollViewer>
|
||||||
|
<controls:SpectreTextBlock Text="{Binding InformationText, Mode=OneWay}"
|
||||||
|
TextWrapping="Wrap" />
|
||||||
|
</ScrollViewer>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
||||||
43
Aaru.Gui/Views/Panels/ArchiveInfo.xaml.cs
Normal file
43
Aaru.Gui/Views/Panels/ArchiveInfo.xaml.cs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
// /***************************************************************************
|
||||||
|
// Aaru Data Preservation Suite
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Filename : ArchiveInfo.xaml.cs
|
||||||
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||||
|
//
|
||||||
|
// Component : GUI panels.
|
||||||
|
//
|
||||||
|
// --[ Description ] ----------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Archive information panel.
|
||||||
|
//
|
||||||
|
// --[ 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-2026 Natalia Portillo
|
||||||
|
// ****************************************************************************/
|
||||||
|
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Markup.Xaml;
|
||||||
|
|
||||||
|
namespace Aaru.Gui.Views.Panels;
|
||||||
|
|
||||||
|
public sealed class ArchiveInfo : UserControl
|
||||||
|
{
|
||||||
|
public ArchiveInfo() => InitializeComponent();
|
||||||
|
|
||||||
|
void InitializeComponent() => AvaloniaXamlLoader.Load(this);
|
||||||
|
}
|
||||||
108
Aaru.Gui/Views/Panels/ArchiveSubdirectory.xaml
Normal file
108
Aaru.Gui/Views/Panels/ArchiveSubdirectory.xaml
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
<!--
|
||||||
|
// /***************************************************************************
|
||||||
|
// Aaru Data Preservation Suite
|
||||||
|
// ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
|
||||||
|
//
|
||||||
|
// Filename : ArchiveSubdirectory.xaml
|
||||||
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||||
|
//
|
||||||
|
// Component : GUI panel.
|
||||||
|
//
|
||||||
|
// ‐‐[ Description ] ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
|
||||||
|
//
|
||||||
|
// Archive subdirectory contents panel.
|
||||||
|
//
|
||||||
|
// ‐‐[ 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-2026 Natalia Portillo
|
||||||
|
// ****************************************************************************/
|
||||||
|
-->
|
||||||
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:panels="clr-namespace:Aaru.Gui.ViewModels.Panels"
|
||||||
|
xmlns:localization="clr-namespace:Aaru.Localization;assembly=Aaru.Localization"
|
||||||
|
xmlns:controls="clr-namespace:Aaru.Gui.Controls"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignWidth="800"
|
||||||
|
d:DesignHeight="450"
|
||||||
|
x:DataType="panels:ArchiveSubdirectoryViewModel"
|
||||||
|
x:Class="Aaru.Gui.Views.Panels.ArchiveSubdirectory">
|
||||||
|
<DataGrid Margin="12"
|
||||||
|
ItemsSource="{Binding Entries, Mode=OneWay}"
|
||||||
|
IsReadOnly="True"
|
||||||
|
SelectionMode="Extended">
|
||||||
|
<DataGrid.Styles>
|
||||||
|
<Style Selector="DataGridRow">
|
||||||
|
<Setter Property="Foreground"
|
||||||
|
Value="{ReflectionBinding Color, Mode=OneWay}" />
|
||||||
|
</Style>
|
||||||
|
</DataGrid.Styles>
|
||||||
|
<DataGrid.ContextMenu>
|
||||||
|
<ContextMenu>
|
||||||
|
<Button Command="{Binding ExtractFilesCommand, Mode=OneWay}">
|
||||||
|
<TextBlock Text="{x:Static localization:UI.ButtonLabel_Extract_to}" />
|
||||||
|
</Button>
|
||||||
|
</ContextMenu>
|
||||||
|
</DataGrid.ContextMenu>
|
||||||
|
<DataGrid.Columns>
|
||||||
|
<DataGridTextColumn Binding="{Binding Name, Mode=OneWay}"
|
||||||
|
Width="Auto"
|
||||||
|
IsReadOnly="True">
|
||||||
|
<DataGridTextColumn.Header>
|
||||||
|
<controls:SpectreTextBlock Text="{x:Static localization:UI.Title_Name}" />
|
||||||
|
</DataGridTextColumn.Header>
|
||||||
|
</DataGridTextColumn>
|
||||||
|
<DataGridTextColumn Binding="{Binding Size, Mode=OneWay}"
|
||||||
|
Width="Auto"
|
||||||
|
IsReadOnly="True">
|
||||||
|
<DataGridTextColumn.Header>
|
||||||
|
<controls:SpectreTextBlock Text="{x:Static localization:UI.Title_Length}" />
|
||||||
|
</DataGridTextColumn.Header>
|
||||||
|
</DataGridTextColumn>
|
||||||
|
<DataGridTextColumn Binding="{Binding CreationTime, Mode=OneWay}"
|
||||||
|
Width="Auto"
|
||||||
|
IsReadOnly="True">
|
||||||
|
<DataGridTextColumn.Header>
|
||||||
|
<controls:SpectreTextBlock Text="{x:Static localization:UI.Title_Creation}" />
|
||||||
|
</DataGridTextColumn.Header>
|
||||||
|
</DataGridTextColumn>
|
||||||
|
<DataGridTextColumn Binding="{Binding LastAccessTime, Mode=OneWay}"
|
||||||
|
Width="Auto"
|
||||||
|
IsReadOnly="True">
|
||||||
|
<DataGridTextColumn.Header>
|
||||||
|
<controls:SpectreTextBlock Text="{x:Static localization:UI.Title_Last_access}" />
|
||||||
|
</DataGridTextColumn.Header>
|
||||||
|
</DataGridTextColumn>
|
||||||
|
<DataGridTextColumn Binding="{Binding LastWriteTime, Mode=OneWay}"
|
||||||
|
Width="Auto"
|
||||||
|
IsReadOnly="True">
|
||||||
|
<DataGridTextColumn.Header>
|
||||||
|
<controls:SpectreTextBlock Text="{x:Static localization:UI.Title_Last_write}" />
|
||||||
|
</DataGridTextColumn.Header>
|
||||||
|
</DataGridTextColumn>
|
||||||
|
<DataGridTextColumn Binding="{Binding Attributes, Mode=OneWay}"
|
||||||
|
Width="Auto"
|
||||||
|
IsReadOnly="True">
|
||||||
|
<DataGridTextColumn.Header>
|
||||||
|
<controls:SpectreTextBlock Text="{x:Static localization:UI.Title_Attributes}" />
|
||||||
|
</DataGridTextColumn.Header>
|
||||||
|
</DataGridTextColumn>
|
||||||
|
</DataGrid.Columns>
|
||||||
|
</DataGrid>
|
||||||
|
</UserControl>
|
||||||
43
Aaru.Gui/Views/Panels/ArchiveSubdirectory.xaml.cs
Normal file
43
Aaru.Gui/Views/Panels/ArchiveSubdirectory.xaml.cs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
// /***************************************************************************
|
||||||
|
// Aaru Data Preservation Suite
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Filename : ArchiveSubdirectory.xaml.cs
|
||||||
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||||
|
//
|
||||||
|
// Component : GUI panels.
|
||||||
|
//
|
||||||
|
// --[ Description ] ----------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Archive subdirectory contents panel.
|
||||||
|
//
|
||||||
|
// --[ 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-2026 Natalia Portillo
|
||||||
|
// ****************************************************************************/
|
||||||
|
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Markup.Xaml;
|
||||||
|
|
||||||
|
namespace Aaru.Gui.Views.Panels;
|
||||||
|
|
||||||
|
public sealed class ArchiveSubdirectory : UserControl
|
||||||
|
{
|
||||||
|
public ArchiveSubdirectory() => InitializeComponent();
|
||||||
|
|
||||||
|
void InitializeComponent() => AvaloniaXamlLoader.Load(this);
|
||||||
|
}
|
||||||
@@ -325,6 +325,28 @@
|
|||||||
VerticalAlignment="Center" />
|
VerticalAlignment="Center" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</TreeDataTemplate>
|
</TreeDataTemplate>
|
||||||
|
<TreeDataTemplate DataType="models:ArchiveModel"
|
||||||
|
ItemsSource="{Binding Roots, Mode=OneWay}">
|
||||||
|
<StackPanel Orientation="Horizontal"
|
||||||
|
Spacing="4">
|
||||||
|
<Image Width="24"
|
||||||
|
Height="24"
|
||||||
|
Source="{Binding Icon, Mode=OneWay}" />
|
||||||
|
<TextBlock Text="{Binding FileName, Mode=OneWay}"
|
||||||
|
VerticalAlignment="Center" />
|
||||||
|
</StackPanel>
|
||||||
|
</TreeDataTemplate>
|
||||||
|
<TreeDataTemplate DataType="models:ArchiveSubdirectoryModel"
|
||||||
|
ItemsSource="{Binding Subdirectories, Mode=OneWay}">
|
||||||
|
<StackPanel Orientation="Horizontal"
|
||||||
|
Spacing="4">
|
||||||
|
<Svg Width="24"
|
||||||
|
Height="24"
|
||||||
|
Path="/Assets/Icons/oxygen/inode-directory.svg" />
|
||||||
|
<TextBlock Text="{Binding Name, Mode=OneWay}"
|
||||||
|
VerticalAlignment="Center" />
|
||||||
|
</StackPanel>
|
||||||
|
</TreeDataTemplate>
|
||||||
<DataTemplate DataType="models:RootModel">
|
<DataTemplate DataType="models:RootModel">
|
||||||
<TextBlock Text="{Binding Name, Mode=OneWay}" />
|
<TextBlock Text="{Binding Name, Mode=OneWay}" />
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|||||||
90
Aaru.Localization/UI.Designer.cs
generated
90
Aaru.Localization/UI.Designer.cs
generated
@@ -11255,5 +11255,95 @@ namespace Aaru.Localization {
|
|||||||
return ResourceManager.GetString("Maximum_error_recovery_is_100", resourceCulture);
|
return ResourceManager.GetString("Maximum_error_recovery_is_100", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string Dialog_Choose_file_to_open {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Dialog_Choose_file_to_open", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Error_0_opening_archive_format {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Error_0_opening_archive_format", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Title_Archive_information {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Title_Archive_information", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Archive_plugin_0 {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Archive_plugin_0", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Archive_plugin_id_0 {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Archive_plugin_id_0", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Archive_number_of_entries_0 {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Archive_number_of_entries_0", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Archive_features_0 {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Archive_features_0", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Skipped_non_regular_archive_entry_0 {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Skipped_non_regular_archive_entry_0", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Archive_supports_filenames {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Archive_supports_filenames", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Archive_supports_compression {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Archive_supports_compression", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Archive_supports_subdirectories {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Archive_supports_subdirectories", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Archive_has_explicit_directories {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Archive_has_explicit_directories", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Archive_has_entry_timestamp {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Archive_has_entry_timestamp", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Archive_supports_protection {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Archive_supports_protection", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Archive_supports_xattrs {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Archive_supports_xattrs", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5623,4 +5623,49 @@ Probadores:
|
|||||||
<data name="Maximum_error_recovery_is_100" xml:space="preserve">
|
<data name="Maximum_error_recovery_is_100" xml:space="preserve">
|
||||||
<value>La recuperación de errores máxima es 100%</value>
|
<value>La recuperación de errores máxima es 100%</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Dialog_Choose_file_to_open" xml:space="preserve">
|
||||||
|
<value>Elegir archivo a abrir</value>
|
||||||
|
</data>
|
||||||
|
<data name="Error_0_opening_archive_format" xml:space="preserve">
|
||||||
|
<value>Error {0} al abrir el formato de archivo.</value>
|
||||||
|
</data>
|
||||||
|
<data name="Title_Archive_information" xml:space="preserve">
|
||||||
|
<value>[bold][slateblue1]Información del archivo[/][/]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Archive_plugin_0" xml:space="preserve">
|
||||||
|
<value>[slateblue1]Plugin:[/] [red]{0}[/]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Archive_plugin_id_0" xml:space="preserve">
|
||||||
|
<value>[slateblue1]ID del plugin:[/] [purple]{0}[/]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Archive_number_of_entries_0" xml:space="preserve">
|
||||||
|
<value>[slateblue1]Número de entradas:[/] [aqua]{0}[/]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Archive_features_0" xml:space="preserve">
|
||||||
|
<value>[slateblue1]Características:[/] [orange3]{0}[/]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Skipped_non_regular_archive_entry_0" xml:space="preserve">
|
||||||
|
<value>Se omitió la entrada de archivo no regular {0}.</value>
|
||||||
|
</data>
|
||||||
|
<data name="Archive_supports_filenames" xml:space="preserve">
|
||||||
|
<value>Soporta nombres de archivos</value>
|
||||||
|
</data>
|
||||||
|
<data name="Archive_supports_compression" xml:space="preserve">
|
||||||
|
<value>Soporta compresión</value>
|
||||||
|
</data>
|
||||||
|
<data name="Archive_supports_subdirectories" xml:space="preserve">
|
||||||
|
<value>Soporta subdirectorios</value>
|
||||||
|
</data>
|
||||||
|
<data name="Archive_has_explicit_directories" xml:space="preserve">
|
||||||
|
<value>Tiene subdirectories explícitos</value>
|
||||||
|
</data>
|
||||||
|
<data name="Archive_has_entry_timestamp" xml:space="preserve">
|
||||||
|
<value>Tiene marcas de tiempo</value>
|
||||||
|
</data>
|
||||||
|
<data name="Archive_supports_protection" xml:space="preserve">
|
||||||
|
<value>Soporta protección</value>
|
||||||
|
</data>
|
||||||
|
<data name="Archive_supports_xattrs" xml:space="preserve">
|
||||||
|
<value>Soporta atributos extendidos</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -5707,4 +5707,49 @@ Do you want to continue?</value>
|
|||||||
<data name="Maximum_error_recovery_is_100" xml:space="preserve">
|
<data name="Maximum_error_recovery_is_100" xml:space="preserve">
|
||||||
<value>Maximum error recovery is 100%</value>
|
<value>Maximum error recovery is 100%</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Dialog_Choose_file_to_open" xml:space="preserve">
|
||||||
|
<value>Choose file to open</value>
|
||||||
|
</data>
|
||||||
|
<data name="Error_0_opening_archive_format" xml:space="preserve">
|
||||||
|
<value>Error {0} opening archive format.</value>
|
||||||
|
</data>
|
||||||
|
<data name="Title_Archive_information" xml:space="preserve">
|
||||||
|
<value>[bold][slateblue1]Archive information[/][/]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Archive_plugin_0" xml:space="preserve">
|
||||||
|
<value>[slateblue1]Plugin:[/] [red]{0}[/]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Archive_plugin_id_0" xml:space="preserve">
|
||||||
|
<value>[slateblue1]Plugin ID:[/] [purple]{0}[/]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Archive_number_of_entries_0" xml:space="preserve">
|
||||||
|
<value>[slateblue1]Number of entries:[/] [aqua]{0}[/]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Archive_features_0" xml:space="preserve">
|
||||||
|
<value>[slateblue1]Features:[/] [orange3]{0}[/]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Skipped_non_regular_archive_entry_0" xml:space="preserve">
|
||||||
|
<value>Skipped non-regular archive entry {0}.</value>
|
||||||
|
</data>
|
||||||
|
<data name="Archive_supports_filenames" xml:space="preserve">
|
||||||
|
<value>Supports filenames</value>
|
||||||
|
</data>
|
||||||
|
<data name="Archive_supports_compression" xml:space="preserve">
|
||||||
|
<value>Supports compression</value>
|
||||||
|
</data>
|
||||||
|
<data name="Archive_supports_subdirectories" xml:space="preserve">
|
||||||
|
<value>Supports subdirectories</value>
|
||||||
|
</data>
|
||||||
|
<data name="Archive_has_explicit_directories" xml:space="preserve">
|
||||||
|
<value>Has explicit subdirectories</value>
|
||||||
|
</data>
|
||||||
|
<data name="Archive_has_entry_timestamp" xml:space="preserve">
|
||||||
|
<value>Has entry timestamp</value>
|
||||||
|
</data>
|
||||||
|
<data name="Archive_supports_protection" xml:space="preserve">
|
||||||
|
<value>Supports protection</value>
|
||||||
|
</data>
|
||||||
|
<data name="Archive_supports_xattrs" xml:space="preserve">
|
||||||
|
<value>Supports extended attributes</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
Reference in New Issue
Block a user