mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
[GUI] Add opening image to new main window.
This commit is contained in:
@@ -33,6 +33,7 @@
|
|||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using Aaru.CommonTypes.Interfaces;
|
using Aaru.CommonTypes.Interfaces;
|
||||||
using Aaru.Gui.ViewModels.Panels;
|
using Aaru.Gui.ViewModels.Panels;
|
||||||
|
using Avalonia.Media.Imaging;
|
||||||
|
|
||||||
namespace Aaru.Gui.Models;
|
namespace Aaru.Gui.Models;
|
||||||
|
|
||||||
@@ -45,4 +46,5 @@ public sealed class FileSystemModel : RootModel
|
|||||||
public IReadOnlyFilesystem ReadOnlyFilesystem { get; set; }
|
public IReadOnlyFilesystem ReadOnlyFilesystem { get; set; }
|
||||||
public FileSystemViewModel ViewModel { get; set; }
|
public FileSystemViewModel ViewModel { get; set; }
|
||||||
public ObservableCollection<SubdirectoryModel> Roots { get; set; }
|
public ObservableCollection<SubdirectoryModel> Roots { get; set; }
|
||||||
|
public Bitmap Icon { get; set; }
|
||||||
}
|
}
|
||||||
@@ -37,7 +37,7 @@ using Avalonia.Media.Imaging;
|
|||||||
|
|
||||||
namespace Aaru.Gui.Models;
|
namespace Aaru.Gui.Models;
|
||||||
|
|
||||||
public sealed class ImageModel
|
public sealed class ImageModel : RootModel
|
||||||
{
|
{
|
||||||
public ImageModel() => PartitionSchemesOrFileSystems = [];
|
public ImageModel() => PartitionSchemesOrFileSystems = [];
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
|
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using Aaru.CommonTypes.Interfaces;
|
using Aaru.CommonTypes.Interfaces;
|
||||||
|
using Avalonia.Media.Imaging;
|
||||||
|
|
||||||
namespace Aaru.Gui.Models;
|
namespace Aaru.Gui.Models;
|
||||||
|
|
||||||
@@ -44,4 +45,5 @@ public sealed class SubdirectoryModel
|
|||||||
public ObservableCollection<SubdirectoryModel> Subdirectories { get; set; }
|
public ObservableCollection<SubdirectoryModel> Subdirectories { get; set; }
|
||||||
public IReadOnlyFilesystem Plugin { get; set; }
|
public IReadOnlyFilesystem Plugin { get; set; }
|
||||||
public bool Listed { get; set; }
|
public bool Listed { get; set; }
|
||||||
|
public Bitmap Icon { get; set; }
|
||||||
}
|
}
|
||||||
@@ -1,26 +1,48 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
|
using Aaru.CommonTypes;
|
||||||
|
using Aaru.CommonTypes.AaruMetadata;
|
||||||
|
using Aaru.CommonTypes.Enums;
|
||||||
|
using Aaru.CommonTypes.Interfaces;
|
||||||
using Aaru.CommonTypes.Interop;
|
using Aaru.CommonTypes.Interop;
|
||||||
|
using Aaru.Core;
|
||||||
using Aaru.Database;
|
using Aaru.Database;
|
||||||
using Aaru.Gui.Models;
|
using Aaru.Gui.Models;
|
||||||
using Aaru.Gui.ViewModels.Dialogs;
|
using Aaru.Gui.ViewModels.Dialogs;
|
||||||
|
using Aaru.Gui.ViewModels.Panels;
|
||||||
using Aaru.Gui.Views.Dialogs;
|
using Aaru.Gui.Views.Dialogs;
|
||||||
using Aaru.Localization;
|
using Aaru.Localization;
|
||||||
|
using Aaru.Logging;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.ApplicationLifetimes;
|
using Avalonia.Controls.ApplicationLifetimes;
|
||||||
|
using Avalonia.Media.Imaging;
|
||||||
|
using Avalonia.Platform;
|
||||||
|
using Avalonia.Platform.Storage;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using CommunityToolkit.Mvvm.Input;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
using MsBox.Avalonia;
|
using MsBox.Avalonia;
|
||||||
|
using MsBox.Avalonia.Base;
|
||||||
|
using MsBox.Avalonia.Enums;
|
||||||
|
using Spectre.Console;
|
||||||
using Console = Aaru.Gui.Views.Dialogs.Console;
|
using Console = Aaru.Gui.Views.Dialogs.Console;
|
||||||
|
using Partition = Aaru.CommonTypes.Partition;
|
||||||
using PlatformID = Aaru.CommonTypes.Interop.PlatformID;
|
using PlatformID = Aaru.CommonTypes.Interop.PlatformID;
|
||||||
|
|
||||||
namespace Aaru.Gui.ViewModels.Windows;
|
namespace Aaru.Gui.ViewModels.Windows;
|
||||||
|
|
||||||
public partial class MainWindowViewModel : ViewModelBase
|
public partial class MainWindowViewModel : ViewModelBase
|
||||||
{
|
{
|
||||||
|
const string MODULE_NAME = "Main Window ViewModel";
|
||||||
|
readonly Bitmap _genericFolderIcon;
|
||||||
|
readonly Bitmap _genericHddIcon;
|
||||||
|
readonly Bitmap _genericOpticalIcon;
|
||||||
|
readonly Bitmap _genericTapeIcon;
|
||||||
readonly Window _view;
|
readonly Window _view;
|
||||||
Console _console;
|
Console _console;
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
@@ -28,6 +50,8 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
bool _devicesSupported;
|
bool _devicesSupported;
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
|
string _title;
|
||||||
|
[ObservableProperty]
|
||||||
ObservableCollection<RootModel> _treeRoot;
|
ObservableCollection<RootModel> _treeRoot;
|
||||||
object _treeViewSelectedItem;
|
object _treeViewSelectedItem;
|
||||||
|
|
||||||
@@ -43,6 +67,19 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
ConsoleCommand = new RelayCommand(Console);
|
ConsoleCommand = new RelayCommand(Console);
|
||||||
OpenCommand = new AsyncRelayCommand(OpenAsync);
|
OpenCommand = new AsyncRelayCommand(OpenAsync);
|
||||||
|
|
||||||
|
_genericHddIcon =
|
||||||
|
new Bitmap(AssetLoader.Open(new Uri("avares://Aaru.Gui/Assets/Icons/oxygen/32x32/drive-harddisk.png")));
|
||||||
|
|
||||||
|
_genericOpticalIcon =
|
||||||
|
new Bitmap(AssetLoader.Open(new Uri("avares://Aaru.Gui/Assets/Icons/oxygen/32x32/drive-optical.png")));
|
||||||
|
|
||||||
|
_genericTapeIcon =
|
||||||
|
new Bitmap(AssetLoader.Open(new Uri("avares://Aaru.Gui/Assets/Icons/oxygen/32x32/media-tape.png")));
|
||||||
|
|
||||||
|
_genericFolderIcon =
|
||||||
|
new Bitmap(AssetLoader.Open(new Uri("avares://Aaru.Gui/Assets/Icons/oxygen/32x32/inode-directory.png")));
|
||||||
|
|
||||||
|
|
||||||
switch(DetectOS.GetRealPlatformID())
|
switch(DetectOS.GetRealPlatformID())
|
||||||
{
|
{
|
||||||
case PlatformID.Win32NT:
|
case PlatformID.Win32NT:
|
||||||
@@ -62,6 +99,7 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
];
|
];
|
||||||
|
|
||||||
_view = view;
|
_view = view;
|
||||||
|
Title = "Aaru";
|
||||||
}
|
}
|
||||||
|
|
||||||
public ICommand OpenCommand { get; }
|
public ICommand OpenCommand { get; }
|
||||||
@@ -90,10 +128,308 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
set => SetProperty(ref _treeViewSelectedItem, value);
|
set => SetProperty(ref _treeViewSelectedItem, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Task OpenAsync() =>
|
async Task OpenAsync()
|
||||||
|
{
|
||||||
|
// Open file picker dialog to allow user to select an image file
|
||||||
|
// TODO: Extensions
|
||||||
|
IReadOnlyList<IStorageFile> result = await _view.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
|
||||||
|
{
|
||||||
|
Title = UI.Dialog_Choose_image_to_open,
|
||||||
|
AllowMultiple = false,
|
||||||
|
FileTypeFilter = [FilePickerFileTypes.All]
|
||||||
|
});
|
||||||
|
|
||||||
// TODO
|
// Exit if user did not select exactly one file
|
||||||
null;
|
if(result.Count != 1) return;
|
||||||
|
|
||||||
|
// Get the appropriate filter plugin for the selected file
|
||||||
|
IFilter inputFilter = PluginRegister.Singleton.GetFilter(result[0].Path.LocalPath);
|
||||||
|
|
||||||
|
// Show error if no suitable filter plugin is found
|
||||||
|
if(inputFilter == null)
|
||||||
|
{
|
||||||
|
IMsBox<ButtonResult> msbox = MessageBoxManager.GetMessageBoxStandard(UI.Title_Error,
|
||||||
|
UI.Cannot_open_specified_file,
|
||||||
|
ButtonEnum.Ok,
|
||||||
|
Icon.Error);
|
||||||
|
|
||||||
|
await msbox.ShowAsync();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Detect the image format of the selected file
|
||||||
|
if(ImageFormat.Detect(inputFilter) is not IMediaImage imageFormat)
|
||||||
|
{
|
||||||
|
IMsBox<ButtonResult> msbox = MessageBoxManager.GetMessageBoxStandard(UI.Title_Error,
|
||||||
|
UI.Image_format_not_identified,
|
||||||
|
ButtonEnum.Ok,
|
||||||
|
Icon.Error);
|
||||||
|
|
||||||
|
await msbox.ShowAsync();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AaruLogging.WriteLine(UI.Image_format_identified_by_0_1, Markup.Escape(imageFormat.Name), imageFormat.Id);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Open the image file
|
||||||
|
ErrorNumber opened = imageFormat.Open(inputFilter);
|
||||||
|
|
||||||
|
if(opened != ErrorNumber.NoError)
|
||||||
|
{
|
||||||
|
IMsBox<ButtonResult> msbox = MessageBoxManager.GetMessageBoxStandard(UI.Title_Error,
|
||||||
|
string.Format(UI.Error_0_opening_image_format, opened),
|
||||||
|
ButtonEnum.Ok,
|
||||||
|
Icon.Error);
|
||||||
|
|
||||||
|
await msbox.ShowAsync();
|
||||||
|
|
||||||
|
AaruLogging.Error(UI.Unable_to_open_image_format);
|
||||||
|
AaruLogging.Error(UI.No_error_given);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create image model with appropriate icon based on media type
|
||||||
|
var mediaResource = new Uri($"avares://Aaru.Gui/Assets/Logos/Media/{imageFormat.Info.MediaType}.png");
|
||||||
|
|
||||||
|
var imageModel = new ImageModel
|
||||||
|
{
|
||||||
|
Path = result[0].Path.LocalPath,
|
||||||
|
Icon = AssetLoader.Exists(mediaResource)
|
||||||
|
? new Bitmap(AssetLoader.Open(mediaResource))
|
||||||
|
: imageFormat.Info.MetadataMediaType == MetadataMediaType.BlockMedia
|
||||||
|
? _genericHddIcon
|
||||||
|
: imageFormat.Info.MetadataMediaType == MetadataMediaType.OpticalDisc
|
||||||
|
? _genericOpticalIcon
|
||||||
|
: _genericFolderIcon,
|
||||||
|
FileName = Path.GetFileName(result[0].Path.LocalPath),
|
||||||
|
Image = imageFormat,
|
||||||
|
ViewModel = new ImageInfoViewModel(result[0].Path.LocalPath, inputFilter, imageFormat, _view),
|
||||||
|
Filter = inputFilter
|
||||||
|
};
|
||||||
|
|
||||||
|
// Extract all partitions from the image
|
||||||
|
List<Partition> partitions = Core.Partitions.GetAll(imageFormat);
|
||||||
|
Core.Partitions.AddSchemesToStats(partitions);
|
||||||
|
|
||||||
|
var checkRaw = false;
|
||||||
|
List<string> idPlugins;
|
||||||
|
PluginRegister plugins = PluginRegister.Singleton;
|
||||||
|
|
||||||
|
// Process partitions or raw device if no partitions found
|
||||||
|
if(partitions.Count == 0)
|
||||||
|
{
|
||||||
|
AaruLogging.Debug(MODULE_NAME, UI.No_partitions_found);
|
||||||
|
|
||||||
|
checkRaw = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AaruLogging.WriteLine(UI._0_partitions_found, partitions.Count);
|
||||||
|
|
||||||
|
// Group partitions by scheme and process each one
|
||||||
|
foreach(string scheme in partitions.Select(static p => p.Scheme).Distinct().Order())
|
||||||
|
{
|
||||||
|
// TODO: Add icons to partition schemes
|
||||||
|
var schemeModel = new PartitionSchemeModel
|
||||||
|
{
|
||||||
|
Name = scheme
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach(Partition partition in partitions.Where(p => p.Scheme == scheme)
|
||||||
|
.OrderBy(static p => p.Start))
|
||||||
|
{
|
||||||
|
var partitionModel = new PartitionModel
|
||||||
|
{
|
||||||
|
// TODO: Add icons to partition types
|
||||||
|
Name = $"{partition.Name} ({partition.Type})",
|
||||||
|
Partition = partition,
|
||||||
|
ViewModel = new PartitionViewModel(partition)
|
||||||
|
};
|
||||||
|
|
||||||
|
AaruLogging.WriteLine(UI.Identifying_filesystems_on_partition);
|
||||||
|
|
||||||
|
// Identify all filesystems on this partition
|
||||||
|
Core.Filesystems.Identify(imageFormat, out idPlugins, partition);
|
||||||
|
|
||||||
|
if(idPlugins.Count == 0)
|
||||||
|
AaruLogging.WriteLine(UI.Filesystem_not_identified);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AaruLogging.WriteLine(string.Format(UI.Identified_by_0_plugins, idPlugins.Count));
|
||||||
|
|
||||||
|
// Mount and create models for each identified filesystem
|
||||||
|
foreach(string pluginName in idPlugins)
|
||||||
|
{
|
||||||
|
if(!plugins.Filesystems.TryGetValue(pluginName, out IFilesystem fs)) continue;
|
||||||
|
if(fs is null) continue;
|
||||||
|
|
||||||
|
fs.GetInformation(imageFormat,
|
||||||
|
partition,
|
||||||
|
null,
|
||||||
|
out string information,
|
||||||
|
out FileSystem fsMetadata);
|
||||||
|
|
||||||
|
var rofs = fs as IReadOnlyFilesystem;
|
||||||
|
|
||||||
|
if(rofs != null)
|
||||||
|
{
|
||||||
|
ErrorNumber error = rofs.Mount(imageFormat, partition, null, [], null);
|
||||||
|
|
||||||
|
if(error != ErrorNumber.NoError) rofs = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var filesystemModel = new FileSystemModel
|
||||||
|
{
|
||||||
|
VolumeName = rofs?.Metadata.VolumeName is null
|
||||||
|
? fsMetadata.VolumeName is null
|
||||||
|
? fsMetadata.Type
|
||||||
|
: $"{fsMetadata.VolumeName} ({fsMetadata.Type})"
|
||||||
|
: $"{rofs.Metadata.VolumeName} ({rofs.Metadata.Type})",
|
||||||
|
Filesystem = fs,
|
||||||
|
ReadOnlyFilesystem = rofs,
|
||||||
|
ViewModel = new FileSystemViewModel(rofs?.Metadata ?? fsMetadata, information)
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: Trap expanding item
|
||||||
|
if(rofs != null)
|
||||||
|
{
|
||||||
|
filesystemModel.Roots.Add(new SubdirectoryModel
|
||||||
|
{
|
||||||
|
Name = "/",
|
||||||
|
Path = "",
|
||||||
|
Plugin = rofs
|
||||||
|
});
|
||||||
|
|
||||||
|
Statistics.AddCommand("ls");
|
||||||
|
}
|
||||||
|
|
||||||
|
Statistics.AddFilesystem(rofs?.Metadata.Type ?? fsMetadata.Type);
|
||||||
|
partitionModel.FileSystems.Add(filesystemModel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
schemeModel.Partitions.Add(partitionModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
imageModel.PartitionSchemesOrFileSystems.Add(schemeModel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no partitions were found, check the raw device
|
||||||
|
if(checkRaw)
|
||||||
|
{
|
||||||
|
var wholePart = new Partition
|
||||||
|
{
|
||||||
|
Name = Localization.Core.Whole_device,
|
||||||
|
Length = imageFormat.Info.Sectors,
|
||||||
|
Size = imageFormat.Info.Sectors * imageFormat.Info.SectorSize
|
||||||
|
};
|
||||||
|
|
||||||
|
Core.Filesystems.Identify(imageFormat, out idPlugins, wholePart);
|
||||||
|
|
||||||
|
if(idPlugins.Count == 0)
|
||||||
|
AaruLogging.WriteLine(UI.Filesystem_not_identified);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AaruLogging.WriteLine(string.Format(UI.Identified_by_0_plugins, idPlugins.Count));
|
||||||
|
|
||||||
|
// Mount and create models for each identified filesystem on raw device
|
||||||
|
foreach(string pluginName in idPlugins)
|
||||||
|
{
|
||||||
|
if(!plugins.Filesystems.TryGetValue(pluginName, out IFilesystem fs)) continue;
|
||||||
|
if(fs is null) continue;
|
||||||
|
|
||||||
|
fs.GetInformation(imageFormat,
|
||||||
|
wholePart,
|
||||||
|
null,
|
||||||
|
out string information,
|
||||||
|
out FileSystem fsMetadata);
|
||||||
|
|
||||||
|
var rofs = fs as IReadOnlyFilesystem;
|
||||||
|
|
||||||
|
if(rofs != null)
|
||||||
|
{
|
||||||
|
ErrorNumber error = rofs.Mount(imageFormat, wholePart, null, [], null);
|
||||||
|
|
||||||
|
if(error != ErrorNumber.NoError) rofs = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var filesystemModel = new FileSystemModel
|
||||||
|
{
|
||||||
|
VolumeName = rofs?.Metadata.VolumeName is null
|
||||||
|
? fsMetadata.VolumeName is null
|
||||||
|
? fsMetadata.Type
|
||||||
|
: $"{fsMetadata.VolumeName} ({fsMetadata.Type})"
|
||||||
|
: $"{rofs.Metadata.VolumeName} ({rofs.Metadata.Type})",
|
||||||
|
Filesystem = fs,
|
||||||
|
ReadOnlyFilesystem = rofs,
|
||||||
|
ViewModel = new FileSystemViewModel(rofs?.Metadata ?? fsMetadata, information)
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: Trap expanding item
|
||||||
|
if(rofs != null)
|
||||||
|
{
|
||||||
|
filesystemModel.Roots.Add(new SubdirectoryModel
|
||||||
|
{
|
||||||
|
Name = "/",
|
||||||
|
Path = "",
|
||||||
|
Plugin = rofs
|
||||||
|
});
|
||||||
|
|
||||||
|
Statistics.AddCommand("ls");
|
||||||
|
}
|
||||||
|
|
||||||
|
Statistics.AddFilesystem(rofs?.Metadata.Type ?? fsMetadata.Type);
|
||||||
|
imageModel.PartitionSchemesOrFileSystems.Add(filesystemModel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update statistics and populate the tree view with the opened image
|
||||||
|
Statistics.AddMediaFormat(imageFormat.Format);
|
||||||
|
Statistics.AddMedia(imageFormat.Info.MediaType, false);
|
||||||
|
Statistics.AddFilter(inputFilter.Name);
|
||||||
|
|
||||||
|
TreeRoot.Clear();
|
||||||
|
TreeRoot.Add(imageModel);
|
||||||
|
Title = $"Aaru - {imageModel.FileName}";
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
IMsBox<ButtonResult> msbox = MessageBoxManager.GetMessageBoxStandard(UI.Title_Error,
|
||||||
|
UI.Unable_to_open_image_format,
|
||||||
|
ButtonEnum.Ok,
|
||||||
|
Icon.Error);
|
||||||
|
|
||||||
|
await msbox.ShowAsync();
|
||||||
|
|
||||||
|
AaruLogging.Error(UI.Unable_to_open_image_format);
|
||||||
|
AaruLogging.Error(Localization.Core.Error_0, ex.Message);
|
||||||
|
AaruLogging.Exception(ex, Localization.Core.Error_0, ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
IMsBox<ButtonResult> msbox = MessageBoxManager.GetMessageBoxStandard(UI.Title_Error,
|
||||||
|
UI.Exception_reading_file,
|
||||||
|
ButtonEnum.Ok,
|
||||||
|
Icon.Error);
|
||||||
|
|
||||||
|
await msbox.ShowAsync();
|
||||||
|
|
||||||
|
AaruLogging.Error(string.Format(UI.Error_reading_file_0, ex.Message));
|
||||||
|
AaruLogging.Exception(ex, UI.Error_reading_file_0, ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
Statistics.AddCommand("image-info");
|
||||||
|
}
|
||||||
|
|
||||||
Task AboutAsync()
|
Task AboutAsync()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
d:DesignHeight="450"
|
d:DesignHeight="450"
|
||||||
x:Class="Aaru.Gui.Views.Windows.MainWindow"
|
x:Class="Aaru.Gui.Views.Windows.MainWindow"
|
||||||
Icon="/Assets/aaru-logo.png"
|
Icon="/Assets/aaru-logo.png"
|
||||||
Title="Aaru">
|
Title="{Binding Title, Mode=OneWay}">
|
||||||
<Design.DataContext>
|
<Design.DataContext>
|
||||||
<windows:MainWindowViewModel />
|
<windows:MainWindowViewModel />
|
||||||
</Design.DataContext>
|
</Design.DataContext>
|
||||||
@@ -50,13 +50,78 @@
|
|||||||
Command="{Binding AboutCommand, Mode=OneWay}" />
|
Command="{Binding AboutCommand, Mode=OneWay}" />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</Menu>
|
</Menu>
|
||||||
<Grid ColumnDefinitions="*,5,6*">
|
<Grid ColumnDefinitions="*,5,4*">
|
||||||
<TreeView ItemsSource="{Binding TreeRoot, Mode=OneWay}"
|
<TreeView ItemsSource="{Binding TreeRoot, Mode=OneWay}"
|
||||||
SelectedItem="{Binding TreeViewSelectedItem, Mode=OneWay}"
|
SelectedItem="{Binding TreeViewSelectedItem, Mode=OneWay}"
|
||||||
|
Background="#111111"
|
||||||
BorderBrush="LightGray"
|
BorderBrush="LightGray"
|
||||||
BorderThickness="1"
|
BorderThickness="1"
|
||||||
CornerRadius="4">
|
CornerRadius="4">
|
||||||
<TreeView.DataTemplates>
|
<TreeView.DataTemplates>
|
||||||
|
<TreeDataTemplate DataType="models:ImageModel"
|
||||||
|
ItemsSource="{Binding PartitionSchemesOrFileSystems, Mode=OneWay}">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<StackPanel.ContextMenu>
|
||||||
|
<ContextMenu
|
||||||
|
DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType=Window}, Mode=OneWay}">
|
||||||
|
<MenuItem Command="{Binding CalculateEntropyCommand, Mode=OneWay}"
|
||||||
|
Header="{x:Static localization:UI.ButtonLabel_Calculate_entropy}" />
|
||||||
|
<MenuItem Command="{Binding VerifyImageCommand, Mode=OneWay}"
|
||||||
|
Header="{x:Static localization:UI.ButtonLabel_Verify}" />
|
||||||
|
<MenuItem Command="{Binding ChecksumImageCommand, Mode=OneWay}"
|
||||||
|
Header="{x:Static localization:UI.ButtonLabel_Checksum}" />
|
||||||
|
<MenuItem Command="{Binding ConvertImageCommand, Mode=OneWay}"
|
||||||
|
Header="{x:Static localization:UI.ButtonLabel_Convert_to}" />
|
||||||
|
<MenuItem Command="{Binding CreateSidecarCommand, Mode=OneWay}"
|
||||||
|
Header="{x:Static localization:UI.ButtonLabel_Create_Aaru_Metadata_sidecar}" />
|
||||||
|
<MenuItem Command="{Binding ViewImageSectorsCommand, Mode=OneWay}"
|
||||||
|
Header="{x:Static localization:UI.ButtonLabel_View_sectors}" />
|
||||||
|
<MenuItem Command="{Binding DecodeImageMediaTagsCommand, Mode=OneWay}"
|
||||||
|
Header="{x:Static localization:UI.ButtonLabel_Decode_media_tags}" />
|
||||||
|
</ContextMenu>
|
||||||
|
</StackPanel.ContextMenu>
|
||||||
|
<Image Width="24"
|
||||||
|
Height="24"
|
||||||
|
Source="{Binding Icon, Mode=OneWay}" />
|
||||||
|
<TextBlock Text="{Binding FileName, Mode=OneWay}" />
|
||||||
|
</StackPanel>
|
||||||
|
</TreeDataTemplate>
|
||||||
|
<TreeDataTemplate DataType="models:PartitionSchemeModel"
|
||||||
|
ItemsSource="{Binding Partitions, Mode=OneWay}">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<Image Width="24"
|
||||||
|
Height="24"
|
||||||
|
Source="{Binding Icon, Mode=OneWay}" />
|
||||||
|
<TextBlock Text="{Binding Name, Mode=OneWay}" />
|
||||||
|
</StackPanel>
|
||||||
|
</TreeDataTemplate>
|
||||||
|
<TreeDataTemplate DataType="models:PartitionModel"
|
||||||
|
ItemsSource="{Binding FileSystems, Mode=OneWay}">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<Image Width="24"
|
||||||
|
Height="24"
|
||||||
|
Source="{Binding Icon, Mode=OneWay}" />
|
||||||
|
<TextBlock Text="{Binding Name, Mode=OneWay}" />
|
||||||
|
</StackPanel>
|
||||||
|
</TreeDataTemplate>
|
||||||
|
<TreeDataTemplate DataType="models:FileSystemModel"
|
||||||
|
ItemsSource="{Binding Roots, Mode=OneWay}">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<Image Width="24"
|
||||||
|
Height="24"
|
||||||
|
Source="{Binding Icon, Mode=OneWay}" />
|
||||||
|
<TextBlock Text="{Binding VolumeName, Mode=OneWay}" />
|
||||||
|
</StackPanel>
|
||||||
|
</TreeDataTemplate>
|
||||||
|
<TreeDataTemplate DataType="models:SubdirectoryModel"
|
||||||
|
ItemsSource="{Binding Subdirectories, Mode=OneWay}">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<Image Width="24"
|
||||||
|
Height="24"
|
||||||
|
Source="{Binding Icon, Mode=OneWay}" />
|
||||||
|
<TextBlock Text="{Binding Name, Mode=OneWay}" />
|
||||||
|
</StackPanel>
|
||||||
|
</TreeDataTemplate>
|
||||||
<DataTemplate DataType="models:RootModel">
|
<DataTemplate DataType="models:RootModel">
|
||||||
<TextBlock Text="{Binding Name, Mode=OneWay}" />
|
<TextBlock Text="{Binding Name, Mode=OneWay}" />
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|||||||
Reference in New Issue
Block a user