mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
[GUI] Add block map to media scan.
This commit is contained in:
@@ -30,8 +30,10 @@
|
|||||||
// Copyright © 2011-2025 Natalia Portillo
|
// Copyright © 2011-2025 Natalia Portillo
|
||||||
// ****************************************************************************/
|
// ****************************************************************************/
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
@@ -40,7 +42,6 @@ using Aaru.Core.Devices.Scanning;
|
|||||||
using Aaru.Devices;
|
using Aaru.Devices;
|
||||||
using Aaru.Localization;
|
using Aaru.Localization;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Media;
|
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using CommunityToolkit.Mvvm.Input;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
@@ -56,17 +57,20 @@ namespace Aaru.Gui.ViewModels.Windows;
|
|||||||
|
|
||||||
public sealed partial class MediaScanViewModel : ViewModelBase
|
public sealed partial class MediaScanViewModel : ViewModelBase
|
||||||
{
|
{
|
||||||
readonly Device _device;
|
readonly Device _device;
|
||||||
readonly Window _view;
|
readonly string _devicePath;
|
||||||
|
readonly List<(ulong startingSector, double duration)> _pendingSectorData = new();
|
||||||
|
readonly object _pendingSectorDataLock = new();
|
||||||
|
readonly Window _view;
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
string _a;
|
string _a;
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
string _avgSpeed;
|
string _avgSpeed;
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
Color _axesColor;
|
|
||||||
[ObservableProperty]
|
|
||||||
string _b;
|
string _b;
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
|
ObservableCollection<(ulong startingSector, double duration)> _blockMapSectorData;
|
||||||
|
[ObservableProperty]
|
||||||
ulong _blocks;
|
ulong _blocks;
|
||||||
ulong _blocksToRead;
|
ulong _blocksToRead;
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
@@ -75,13 +79,10 @@ public sealed partial class MediaScanViewModel : ViewModelBase
|
|||||||
bool _closeVisible;
|
bool _closeVisible;
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
string _d;
|
string _d;
|
||||||
readonly string _devicePath;
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
string _e;
|
string _e;
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
string _f;
|
string _f;
|
||||||
[ObservableProperty]
|
|
||||||
Color _lineColor;
|
|
||||||
ScanResults _localResults;
|
ScanResults _localResults;
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
string _maxSpeed;
|
string _maxSpeed;
|
||||||
@@ -98,16 +99,6 @@ public sealed partial class MediaScanViewModel : ViewModelBase
|
|||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
bool _progress1Visible;
|
bool _progress1Visible;
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
string _progress2Indeterminate;
|
|
||||||
[ObservableProperty]
|
|
||||||
string _progress2MaxValue;
|
|
||||||
[ObservableProperty]
|
|
||||||
string _progress2Text;
|
|
||||||
[ObservableProperty]
|
|
||||||
string _progress2Value;
|
|
||||||
[ObservableProperty]
|
|
||||||
string _progress2Visible;
|
|
||||||
[ObservableProperty]
|
|
||||||
bool _progressIndeterminate;
|
bool _progressIndeterminate;
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
double _progressMaxValue;
|
double _progressMaxValue;
|
||||||
@@ -119,6 +110,8 @@ public sealed partial class MediaScanViewModel : ViewModelBase
|
|||||||
bool _progressVisible;
|
bool _progressVisible;
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
bool _resultsVisible;
|
bool _resultsVisible;
|
||||||
|
[ObservableProperty]
|
||||||
|
uint _scanBlockSize;
|
||||||
MediaScan _scanner;
|
MediaScan _scanner;
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
bool _startVisible;
|
bool _startVisible;
|
||||||
@@ -146,23 +139,8 @@ public sealed partial class MediaScanViewModel : ViewModelBase
|
|||||||
StopCommand = new RelayCommand(Stop);
|
StopCommand = new RelayCommand(Stop);
|
||||||
StartVisible = true;
|
StartVisible = true;
|
||||||
CloseVisible = true;
|
CloseVisible = true;
|
||||||
BlockMapList = [];
|
|
||||||
|
|
||||||
// ChartPoints = new ObservableCollection<DataPoint>();
|
|
||||||
StepsX = double.NaN;
|
|
||||||
StepsY = double.NaN;
|
|
||||||
AxesColor = Colors.Black;
|
|
||||||
LineColor = Colors.Yellow;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string SpeedLabel => UI.ButtonLabel_Stop;
|
|
||||||
public string KbsLabel => UI.Kb_s;
|
|
||||||
public string BlockLabel => UI.Title_Block;
|
|
||||||
|
|
||||||
public ObservableCollection<(ulong block, double duration)> BlockMapList { get; }
|
|
||||||
|
|
||||||
// public ObservableCollection<DataPoint> ChartPoints { get; }
|
|
||||||
|
|
||||||
public string Title { get; }
|
public string Title { get; }
|
||||||
|
|
||||||
public ICommand StartCommand { get; }
|
public ICommand StartCommand { get; }
|
||||||
@@ -181,7 +159,6 @@ public sealed partial class MediaScanViewModel : ViewModelBase
|
|||||||
ProgressVisible = true;
|
ProgressVisible = true;
|
||||||
ResultsVisible = true;
|
ResultsVisible = true;
|
||||||
|
|
||||||
// ChartPoints.Clear();
|
|
||||||
new Thread(DoWork).Start();
|
new Thread(DoWork).Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,8 +181,17 @@ public sealed partial class MediaScanViewModel : ViewModelBase
|
|||||||
|
|
||||||
ScanResults results = _scanner.Scan();
|
ScanResults results = _scanner.Scan();
|
||||||
|
|
||||||
|
// Flush any remaining pending sector data
|
||||||
await Dispatcher.UIThread.InvokeAsync(() =>
|
await Dispatcher.UIThread.InvokeAsync(() =>
|
||||||
{
|
{
|
||||||
|
lock(_pendingSectorDataLock)
|
||||||
|
{
|
||||||
|
foreach((ulong startingSector, double duration) item in _pendingSectorData)
|
||||||
|
BlockMapSectorData.Add(item);
|
||||||
|
|
||||||
|
_pendingSectorData.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
TotalTime = string.Format(Localization.Core.Took_a_total_of_0_1_processing_commands,
|
TotalTime = string.Format(Localization.Core.Took_a_total_of_0_1_processing_commands,
|
||||||
results.TotalTime.Seconds().Humanize(minUnit: TimeUnit.Second),
|
results.TotalTime.Seconds().Humanize(minUnit: TimeUnit.Second),
|
||||||
results.ProcessingTime.Seconds().Humanize(minUnit: TimeUnit.Second));
|
results.ProcessingTime.Seconds().Humanize(minUnit: TimeUnit.Second));
|
||||||
@@ -268,6 +254,9 @@ public sealed partial class MediaScanViewModel : ViewModelBase
|
|||||||
async void InitBlockMap(ulong blocks, ulong blockSize, ulong blocksToRead, ushort currentProfile) =>
|
async void InitBlockMap(ulong blocks, ulong blockSize, ulong blocksToRead, ushort currentProfile) =>
|
||||||
await Dispatcher.UIThread.InvokeAsync(() =>
|
await Dispatcher.UIThread.InvokeAsync(() =>
|
||||||
{
|
{
|
||||||
|
ScanBlockSize = (uint)blocksToRead;
|
||||||
|
BlockMapSectorData = [];
|
||||||
|
|
||||||
Blocks = blocks / blocksToRead;
|
Blocks = blocks / blocksToRead;
|
||||||
_blocksToRead = blocksToRead;
|
_blocksToRead = blocksToRead;
|
||||||
|
|
||||||
@@ -419,14 +408,12 @@ public sealed partial class MediaScanViewModel : ViewModelBase
|
|||||||
{
|
{
|
||||||
_localResults.Errored += _blocksToRead;
|
_localResults.Errored += _blocksToRead;
|
||||||
UnreadableSectors = string.Format(Localization.Core._0_sectors_could_not_be_read, _localResults.Errored);
|
UnreadableSectors = string.Format(Localization.Core._0_sectors_could_not_be_read, _localResults.Errored);
|
||||||
BlockMapList.Add((sector / _blocksToRead, double.NaN));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
[SuppressMessage("ReSharper", "AsyncVoidMethod")]
|
[SuppressMessage("ReSharper", "AsyncVoidMethod")]
|
||||||
async void OnScanTime(ulong sector, double duration) => await Dispatcher.UIThread.InvokeAsync(() =>
|
async void OnScanTime(ulong sector, double duration)
|
||||||
{
|
{
|
||||||
BlockMapList.Add((sector / _blocksToRead, duration));
|
// Update local results counters (thread-safe, no UI dispatch needed)
|
||||||
|
|
||||||
switch(duration)
|
switch(duration)
|
||||||
{
|
{
|
||||||
case < 3:
|
case < 3:
|
||||||
@@ -455,11 +442,55 @@ public sealed partial class MediaScanViewModel : ViewModelBase
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
A = string.Format(Localization.Core._0_sectors_took_less_than_3_ms, _localResults.A);
|
// Batch sector data updates
|
||||||
B = string.Format(Localization.Core._0_sectors_took_less_than_10_ms_but_more_than_3_ms, _localResults.B);
|
List<(ulong sector, double duration)> itemsToAdd = null;
|
||||||
C = string.Format(Localization.Core._0_sectors_took_less_than_50_ms_but_more_than_10_ms, _localResults.C);
|
|
||||||
D = string.Format(Localization.Core._0_sectors_took_less_than_150_ms_but_more_than_50_ms, _localResults.D);
|
lock(_pendingSectorDataLock)
|
||||||
E = string.Format(Localization.Core._0_sectors_took_less_than_500_ms_but_more_than_150_ms, _localResults.E);
|
{
|
||||||
F = string.Format(Localization.Core._0_sectors_took_more_than_500_ms, _localResults.F);
|
_pendingSectorData.Add((sector, duration));
|
||||||
});
|
|
||||||
|
// Only dispatch to UI thread every 50 items to reduce overhead
|
||||||
|
if(_pendingSectorData.Count >= 50)
|
||||||
|
{
|
||||||
|
itemsToAdd = _pendingSectorData.ToList();
|
||||||
|
_pendingSectorData.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dispatch outside the lock
|
||||||
|
if(itemsToAdd != null)
|
||||||
|
{
|
||||||
|
await Dispatcher.UIThread.InvokeAsync(() =>
|
||||||
|
{
|
||||||
|
foreach((ulong sector, double duration) item in itemsToAdd)
|
||||||
|
BlockMapSectorData.Add(item);
|
||||||
|
|
||||||
|
// Update text labels
|
||||||
|
A = string.Format(Localization.Core
|
||||||
|
._0_sectors_took_less_than_3_ms,
|
||||||
|
_localResults.A);
|
||||||
|
|
||||||
|
B = string.Format(Localization.Core
|
||||||
|
._0_sectors_took_less_than_10_ms_but_more_than_3_ms,
|
||||||
|
_localResults.B);
|
||||||
|
|
||||||
|
C = string.Format(Localization.Core
|
||||||
|
._0_sectors_took_less_than_50_ms_but_more_than_10_ms,
|
||||||
|
_localResults.C);
|
||||||
|
|
||||||
|
D = string.Format(Localization.Core
|
||||||
|
._0_sectors_took_less_than_150_ms_but_more_than_50_ms,
|
||||||
|
_localResults.D);
|
||||||
|
|
||||||
|
E = string.Format(Localization.Core
|
||||||
|
._0_sectors_took_less_than_500_ms_but_more_than_150_ms,
|
||||||
|
_localResults.E);
|
||||||
|
|
||||||
|
F = string.Format(Localization.Core
|
||||||
|
._0_sectors_took_more_than_500_ms,
|
||||||
|
_localResults.F);
|
||||||
|
},
|
||||||
|
DispatcherPriority.Background);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -83,7 +83,18 @@
|
|||||||
<TabItem.Header>
|
<TabItem.Header>
|
||||||
<TextBlock Text="{x:Static localization:UI.Title_Block_map}" />
|
<TextBlock Text="{x:Static localization:UI.Title_Block_map}" />
|
||||||
</TabItem.Header>
|
</TabItem.Header>
|
||||||
<!-- <controls:BlockMap Width="750" Height="400" Blocks="{Binding Blocks}" ItemsSource="{Binding BlockMapList}" /> -->
|
<Border Margin="8"
|
||||||
|
BorderThickness="1"
|
||||||
|
BorderBrush="LightGray"
|
||||||
|
CornerRadius="8">
|
||||||
|
<ScrollViewer HorizontalScrollBarVisibility="Disabled"
|
||||||
|
VerticalScrollBarVisibility="Auto">
|
||||||
|
<controls:BlockMap SectorData="{Binding BlockMapSectorData, Mode=OneWay}"
|
||||||
|
VerticalAlignment="Top"
|
||||||
|
ScanBlockSize="{Binding ScanBlockSize, Mode=OneWay}"
|
||||||
|
Margin="4" />
|
||||||
|
</ScrollViewer>
|
||||||
|
</Border>
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem>
|
<TabItem>
|
||||||
<TabItem.Header>
|
<TabItem.Header>
|
||||||
|
|||||||
Reference in New Issue
Block a user