Show AbsentFromLastScan book status in grid

This commit is contained in:
MBucari 2023-03-07 19:36:15 -07:00
parent f6dcc0db1d
commit 3ebd4ce243
17 changed files with 61 additions and 23 deletions

View File

@ -467,6 +467,7 @@ namespace ApplicationServices
var results = libraryBooks var results = libraryBooks
.AsParallel() .AsParallel()
.Where(lb => !lb.AbsentFromLastScan)
.Select(lb => Liberated_Status(lb.Book)) .Select(lb => Liberated_Status(lb.Book))
.ToList(); .ToList();
var booksFullyBackedUp = results.Count(r => r == LiberatedStatus.Liberated); var booksFullyBackedUp = results.Count(r => r == LiberatedStatus.Liberated);

View File

@ -107,8 +107,9 @@ namespace DataLayer
=> bookList => bookList
.Where( .Where(
lb => lb =>
lb.Book.UserDefinedItem.BookStatus is LiberatedStatus.NotLiberated or LiberatedStatus.PartialDownload !lb.AbsentFromLastScan &&
|| lb.Book.UserDefinedItem.PdfStatus is LiberatedStatus.NotLiberated or LiberatedStatus.PartialDownload (lb.Book.UserDefinedItem.BookStatus is LiberatedStatus.NotLiberated or LiberatedStatus.PartialDownload
|| lb.Book.UserDefinedItem.PdfStatus is LiberatedStatus.NotLiberated or LiberatedStatus.PartialDownload)
); );
} }
} }

View File

@ -8,6 +8,8 @@
<SolidColorBrush x:Key="ProcessQueueBookCancelledBrush" Color="Khaki" /> <SolidColorBrush x:Key="ProcessQueueBookCancelledBrush" Color="Khaki" />
<SolidColorBrush x:Key="ProcessQueueBookDefaultBrush" Color="{StaticResource SystemAltHighColor}" /> <SolidColorBrush x:Key="ProcessQueueBookDefaultBrush" Color="{StaticResource SystemAltHighColor}" />
<SolidColorBrush x:Key="ProcessQueueBookBorderBrush" Color="Gray" /> <SolidColorBrush x:Key="ProcessQueueBookBorderBrush" Color="Gray" />
<SolidColorBrush x:Key="DisabledGrayBrush" Color="#60D3D3D3" />
</Styles.Resources> </Styles.Resources>
<Style Selector="TextBox[IsReadOnly=true]"> <Style Selector="TextBox[IsReadOnly=true]">
<Setter Property="Background" Value="LightGray" /> <Setter Property="Background" Value="LightGray" />

View File

@ -78,7 +78,6 @@ namespace LibationAvalonia.ViewModels
public abstract bool? Remove { get; set; } public abstract bool? Remove { get; set; }
public abstract LiberateButtonStatus Liberate { get; } public abstract LiberateButtonStatus Liberate { get; }
public abstract BookTags BookTags { get; } public abstract BookTags BookTags { get; }
public abstract bool IsSeries { get; }
public abstract bool IsEpisode { get; } public abstract bool IsEpisode { get; }
public abstract bool IsBook { get; } public abstract bool IsBook { get; }
public IBrush BackgroundBrush => IsEpisode ? App.SeriesEntryGridBackgroundBrush : Brushes.Transparent; public IBrush BackgroundBrush => IsEpisode ? App.SeriesEntryGridBackgroundBrush : Brushes.Transparent;

View File

@ -8,9 +8,10 @@ namespace LibationAvalonia.ViewModels
{ {
public class LiberateButtonStatus : ViewModelBase, IComparable public class LiberateButtonStatus : ViewModelBase, IComparable
{ {
public LiberateButtonStatus(bool isSeries) public LiberateButtonStatus(bool isSeries, bool isAbsent)
{ {
IsSeries = isSeries; IsSeries = isSeries;
IsAbsent = isAbsent;
} }
public LiberatedStatus BookStatus { get; set; } public LiberatedStatus BookStatus { get; set; }
public LiberatedStatus? PdfStatus { get; set; } public LiberatedStatus? PdfStatus { get; set; }
@ -26,7 +27,10 @@ namespace LibationAvalonia.ViewModels
this.RaisePropertyChanged(nameof(ToolTip)); this.RaisePropertyChanged(nameof(ToolTip));
} }
} }
private bool IsSeries { get; }
private bool IsAbsent { get; }
public bool IsSeries { get; }
public bool IsUnavailable => !IsSeries & IsAbsent & (BookStatus is not LiberatedStatus.Liberated || PdfStatus is not null and not LiberatedStatus.Liberated);
public Bitmap Image => GetLiberateIcon(); public Bitmap Image => GetLiberateIcon();
public string ToolTip => GetTooltip(); public string ToolTip => GetTooltip();
@ -40,6 +44,8 @@ namespace LibationAvalonia.ViewModels
if (IsSeries && !second.IsSeries) return -1; if (IsSeries && !second.IsSeries) return -1;
else if (!IsSeries && second.IsSeries) return 1; else if (!IsSeries && second.IsSeries) return 1;
else if (IsSeries && second.IsSeries) return 0; else if (IsSeries && second.IsSeries) return 0;
else if (IsUnavailable && !second.IsUnavailable) return 1;
else if (!IsUnavailable && second.IsUnavailable) return -1;
else if (BookStatus == LiberatedStatus.Liberated && second.BookStatus != LiberatedStatus.Liberated) return -1; else if (BookStatus == LiberatedStatus.Liberated && second.BookStatus != LiberatedStatus.Liberated) return -1;
else if (BookStatus != LiberatedStatus.Liberated && second.BookStatus == LiberatedStatus.Liberated) return 1; else if (BookStatus != LiberatedStatus.Liberated && second.BookStatus == LiberatedStatus.Liberated) return 1;
else return BookStatus.CompareTo(second.BookStatus); else return BookStatus.CompareTo(second.BookStatus);
@ -72,11 +78,15 @@ namespace LibationAvalonia.ViewModels
return GetFromResources($"liberate_{image_lib}{image_pdf}"); return GetFromResources($"liberate_{image_lib}{image_pdf}");
} }
private string GetTooltip() private string GetTooltip()
{ {
if (IsSeries) if (IsSeries)
return Expanded ? "Click to Collpase" : "Click to Expand"; return Expanded ? "Click to Collpase" : "Click to Expand";
if (IsUnavailable)
return "This book cannot be downloaded\nbecause it wasn't found during\nthe most recent library scan";
if (BookStatus == LiberatedStatus.Error) if (BookStatus == LiberatedStatus.Error)
return "Book downloaded ERROR"; return "Book downloaded ERROR";

View File

@ -44,13 +44,12 @@ namespace LibationAvalonia.ViewModels
_pdfStatus = LibraryCommands.Pdf_Status(LibraryBook.Book); _pdfStatus = LibraryCommands.Pdf_Status(LibraryBook.Book);
lastStatusUpdate = DateTime.Now; lastStatusUpdate = DateTime.Now;
} }
return new LiberateButtonStatus(IsSeries) { BookStatus = _bookStatus, PdfStatus = _pdfStatus }; return new LiberateButtonStatus(isSeries: false, LibraryBook.AbsentFromLastScan) { BookStatus = _bookStatus, PdfStatus = _pdfStatus };
} }
} }
public override BookTags BookTags => new() { Tags = string.Join("\r\n", Book.UserDefinedItem.TagsEnumerated) }; public override BookTags BookTags => new() { Tags = string.Join("\r\n", Book.UserDefinedItem.TagsEnumerated) };
public override bool IsSeries => false;
public override bool IsEpisode => Parent is not null; public override bool IsEpisode => Parent is not null;
public override bool IsBook => Parent is null; public override bool IsBook => Parent is null;
@ -93,6 +92,7 @@ namespace LibationAvalonia.ViewModels
SeriesIndex = Book.SeriesLink.FirstOrDefault()?.Index ?? 0; SeriesIndex = Book.SeriesLink.FirstOrDefault()?.Index ?? 0;
this.RaisePropertyChanged(nameof(MyRating)); this.RaisePropertyChanged(nameof(MyRating));
this.RaisePropertyChanged(nameof(Liberate));
UserDefinedItem.ItemChanged += UserDefinedItem_ItemChanged; UserDefinedItem.ItemChanged += UserDefinedItem_ItemChanged;
} }

View File

@ -46,7 +46,6 @@ namespace LibationAvalonia.ViewModels
public override LiberateButtonStatus Liberate { get; } public override LiberateButtonStatus Liberate { get; }
public override BookTags BookTags { get; } = new(); public override BookTags BookTags { get; } = new();
public override bool IsSeries => true;
public override bool IsEpisode => false; public override bool IsEpisode => false;
public override bool IsBook => false; public override bool IsBook => false;
@ -54,7 +53,7 @@ namespace LibationAvalonia.ViewModels
public SeriesEntry(LibraryBook parent, IEnumerable<LibraryBook> children) public SeriesEntry(LibraryBook parent, IEnumerable<LibraryBook> children)
{ {
Liberate = new LiberateButtonStatus(IsSeries); Liberate = new LiberateButtonStatus(isSeries: true, isAbsent: false);
SeriesIndex = -1; SeriesIndex = -1;
Children = children Children = children

View File

@ -157,6 +157,7 @@ namespace LibationAvalonia.Views
=> _viewModel.VisibleNotLiberated => _viewModel.VisibleNotLiberated
= _viewModel.ProductsDisplay = _viewModel.ProductsDisplay
.GetVisibleBookEntries() .GetVisibleBookEntries()
.Where(lb => !lb.AbsentFromLastScan)
.Count(lb => lb.Book.UserDefinedItem.BookStatus == LiberatedStatus.NotLiberated); .Count(lb => lb.Book.UserDefinedItem.BookStatus == LiberatedStatus.NotLiberated);
} }
} }

View File

@ -61,9 +61,13 @@
<controls:DataGridTemplateColumnExt CanUserSort="True" Width="75" Header="Liberate" SortMemberPath="Liberate" ClipboardContentBinding="{Binding Liberate.ToolTip}"> <controls:DataGridTemplateColumnExt CanUserSort="True" Width="75" Header="Liberate" SortMemberPath="Liberate" ClipboardContentBinding="{Binding Liberate.ToolTip}">
<DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellTemplate>
<DataTemplate> <DataTemplate>
<Button Opacity="{Binding Opacity}" Padding="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Click="LiberateButton_Click" ToolTip.Tip="{Binding Liberate.ToolTip}"> <Panel ToolTip.Tip="{Binding Liberate.ToolTip}">
<Image Source="{Binding Liberate.Image}" Stretch="None" /> <Button Opacity="{Binding Opacity}" Padding="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Click="LiberateButton_Click" IsVisible="{Binding !Liberate.IsUnavailable}">
</Button> <Image Source="{Binding Liberate.Image}" Stretch="None" />
</Button>
<Image Source="{Binding Liberate.Image}" Stretch="None" IsVisible="{Binding Liberate.IsUnavailable}"/>
<Panel Background="{StaticResource DisabledGrayBrush}" IsVisible="{Binding Liberate.IsUnavailable}" />
</Panel>
</DataTemplate> </DataTemplate>
</DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn.CellTemplate>
</controls:DataGridTemplateColumnExt> </controls:DataGridTemplateColumnExt>

View File

@ -34,7 +34,7 @@ namespace LibationAvalonia.Views
List<LibraryBook> sampleEntries = new() List<LibraryBook> sampleEntries = new()
{ {
//context.GetLibraryBook_Flat_NoTracking("B00DCD0OXU"), //context.GetLibraryBook_Flat_NoTracking("B00DCD0OXU"),
context.GetLibraryBook_Flat_NoTracking("B017V4IM1G"), context.GetLibraryBook_Flat_NoTracking("B002V8H7G4"),
context.GetLibraryBook_Flat_NoTracking("B017V4IWVG"), context.GetLibraryBook_Flat_NoTracking("B017V4IWVG"),
context.GetLibraryBook_Flat_NoTracking("B017V4JA2Q"), context.GetLibraryBook_Flat_NoTracking("B017V4JA2Q"),
context.GetLibraryBook_Flat_NoTracking("B017V4NUPO"), context.GetLibraryBook_Flat_NoTracking("B017V4NUPO"),
@ -84,7 +84,7 @@ namespace LibationAvalonia.Views
{ {
var entry = args.GridEntry; var entry = args.GridEntry;
if (entry.IsSeries) if (entry.Liberate.IsSeries)
return; return;
var setDownloadMenuItem = new MenuItem() var setDownloadMenuItem = new MenuItem()
@ -135,7 +135,7 @@ namespace LibationAvalonia.Views
var convertToMp3MenuItem = new MenuItem var convertToMp3MenuItem = new MenuItem
{ {
Header = "_Convert to Mp3", Header = "_Convert to Mp3",
IsEnabled = entry.Book.UserDefinedItem.BookStatus != LiberatedStatus.NotLiberated IsEnabled = entry.Book.UserDefinedItem.BookStatus is LiberatedStatus.Liberated
}; };
convertToMp3MenuItem.Click += (_, _) => ConvertToMp3Clicked?.Invoke(this, entry.LibraryBook); convertToMp3MenuItem.Click += (_, _) => ConvertToMp3Clicked?.Invoke(this, entry.LibraryBook);

View File

@ -27,7 +27,7 @@ namespace LibationWinForms
=> await Task.Run(setLiberatedVisibleMenuItem); => await Task.Run(setLiberatedVisibleMenuItem);
void setLiberatedVisibleMenuItem() void setLiberatedVisibleMenuItem()
{ {
var notLiberated = productsDisplay.GetVisible().Count(lb => lb.Book.UserDefinedItem.BookStatus == DataLayer.LiberatedStatus.NotLiberated); var notLiberated = productsDisplay.GetVisible().Count(lb => lb.Book.UserDefinedItem.BookStatus == LiberatedStatus.NotLiberated && !lb.AbsentFromLastScan);
this.UIThreadSync(() => this.UIThreadSync(() =>
{ {
if (notLiberated > 0) if (notLiberated > 0)

View File

@ -8,7 +8,15 @@ namespace LibationWinForms.GridView
public LiberatedStatus BookStatus { get; set; } public LiberatedStatus BookStatus { get; set; }
public LiberatedStatus? PdfStatus { get; set; } public LiberatedStatus? PdfStatus { get; set; }
public bool Expanded { get; set; } public bool Expanded { get; set; }
public bool IsSeries { get; init; } public bool IsSeries { get; }
private bool IsAbsent { get; }
public bool IsUnavailable => !IsSeries & IsAbsent & (BookStatus is not LiberatedStatus.Liberated || PdfStatus is not null and not LiberatedStatus.Liberated);
public LiberateButtonStatus(bool isSeries, bool isAbsent)
{
IsSeries = isSeries;
IsAbsent = isAbsent;
}
/// <summary> /// <summary>
/// Defines the Liberate column's sorting behavior /// Defines the Liberate column's sorting behavior
@ -20,6 +28,8 @@ namespace LibationWinForms.GridView
if (IsSeries && !second.IsSeries) return -1; if (IsSeries && !second.IsSeries) return -1;
else if (!IsSeries && second.IsSeries) return 1; else if (!IsSeries && second.IsSeries) return 1;
else if (IsSeries && second.IsSeries) return 0; else if (IsSeries && second.IsSeries) return 0;
else if (IsUnavailable && !second.IsUnavailable) return 1;
else if (!IsUnavailable && second.IsUnavailable) return -1;
else if (BookStatus == LiberatedStatus.Liberated && second.BookStatus != LiberatedStatus.Liberated) return -1; else if (BookStatus == LiberatedStatus.Liberated && second.BookStatus != LiberatedStatus.Liberated) return -1;
else if (BookStatus != LiberatedStatus.Liberated && second.BookStatus == LiberatedStatus.Liberated) return 1; else if (BookStatus != LiberatedStatus.Liberated && second.BookStatus == LiberatedStatus.Liberated) return 1;
else return BookStatus.CompareTo(second.BookStatus); else return BookStatus.CompareTo(second.BookStatus);

View File

@ -17,11 +17,14 @@ namespace LibationWinForms.GridView
internal class LiberateDataGridViewImageButtonCell : DataGridViewImageButtonCell internal class LiberateDataGridViewImageButtonCell : DataGridViewImageButtonCell
{ {
private static readonly Color SERIES_BG_COLOR = Color.FromArgb(230, 255, 230); private static readonly Color SERIES_BG_COLOR = Color.FromArgb(230, 255, 230);
private static readonly Brush DISABLED_GRAY = new SolidBrush(Color.FromArgb(0x60, Color.LightGray));
protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates elementState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts) protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates elementState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
{ {
if (value is LiberateButtonStatus status) if (value is LiberateButtonStatus status)
{ {
if (status.BookStatus is LiberatedStatus.Error)
if (status.BookStatus is LiberatedStatus.Error || status.IsUnavailable)
//Don't paint the button graphic
paintParts ^= DataGridViewPaintParts.ContentBackground | DataGridViewPaintParts.ContentForeground | DataGridViewPaintParts.SelectionBackground; paintParts ^= DataGridViewPaintParts.ContentBackground | DataGridViewPaintParts.ContentForeground | DataGridViewPaintParts.SelectionBackground;
if (rowIndex >= 0 && DataGridView.GetBoundItem<GridEntry>(rowIndex) is LibraryBookEntry lbEntry && lbEntry.Parent is not null) if (rowIndex >= 0 && DataGridView.GetBoundItem<GridEntry>(rowIndex) is LibraryBookEntry lbEntry && lbEntry.Parent is not null)
@ -41,7 +44,14 @@ namespace LibationWinForms.GridView
DrawButtonImage(graphics, buttonImage, cellBounds); DrawButtonImage(graphics, buttonImage, cellBounds);
ToolTipText = mouseoverText; if (status.IsUnavailable)
{
//Create the "disabled" look by painting a transparent gray box over the buttom image.
graphics.FillRectangle(DISABLED_GRAY, cellBounds);
ToolTipText = "This book cannot be downloaded\r\nbecause it wasn't found during\r\nthe most recent library scan";
}
else
ToolTipText = mouseoverText;
} }
} }
} }

View File

@ -52,7 +52,7 @@ namespace LibationWinForms.GridView
_pdfStatus = LibraryCommands.Pdf_Status(LibraryBook.Book); _pdfStatus = LibraryCommands.Pdf_Status(LibraryBook.Book);
lastStatusUpdate = DateTime.Now; lastStatusUpdate = DateTime.Now;
} }
return new LiberateButtonStatus { BookStatus = _bookStatus, PdfStatus = _pdfStatus, IsSeries = false }; return new LiberateButtonStatus(isSeries: false, LibraryBook.AbsentFromLastScan) { BookStatus = _bookStatus, PdfStatus = _pdfStatus };
} }
} }
public override string DisplayTags => string.Join("\r\n", Book.UserDefinedItem.TagsEnumerated); public override string DisplayTags => string.Join("\r\n", Book.UserDefinedItem.TagsEnumerated);

View File

@ -200,7 +200,8 @@ namespace LibationWinForms.GridView
private void productsGrid_LiberateClicked(LibraryBookEntry liveGridEntry) private void productsGrid_LiberateClicked(LibraryBookEntry liveGridEntry)
{ {
if (liveGridEntry.LibraryBook.Book.UserDefinedItem.BookStatus is not LiberatedStatus.Error) if (liveGridEntry.LibraryBook.Book.UserDefinedItem.BookStatus is not LiberatedStatus.Error
&& !liveGridEntry.Liberate.IsUnavailable)
LiberateClicked?.Invoke(this, liveGridEntry.LibraryBook); LiberateClicked?.Invoke(this, liveGridEntry.LibraryBook);
} }

View File

@ -180,7 +180,7 @@ namespace LibationWinForms.GridView
var convertToMp3MenuItem = new ToolStripMenuItem var convertToMp3MenuItem = new ToolStripMenuItem
{ {
Text = "&Convert to Mp3", Text = "&Convert to Mp3",
Enabled = entry.Book.UserDefinedItem.BookStatus != LiberatedStatus.NotLiberated Enabled = entry.Book.UserDefinedItem.BookStatus is LiberatedStatus.Liberated
}; };
convertToMp3MenuItem.Click += (_, e) => ConvertToMp3Clicked?.Invoke(entry as LibraryBookEntry); convertToMp3MenuItem.Click += (_, e) => ConvertToMp3Clicked?.Invoke(entry as LibraryBookEntry);

View File

@ -62,7 +62,7 @@ namespace LibationWinForms.GridView
private SeriesEntry(LibraryBook parent) private SeriesEntry(LibraryBook parent)
{ {
Liberate = new LiberateButtonStatus { IsSeries = true }; Liberate = new LiberateButtonStatus(isSeries: true, isAbsent: false);
SeriesIndex = -1; SeriesIndex = -1;
LibraryBook = parent; LibraryBook = parent;
LoadCover(); LoadCover();