batch book status updates

bug fixes, esp. threading
This commit is contained in:
Robert McRackan 2021-09-23 14:33:04 -04:00
parent 613c97524a
commit 14e14ba9bd
7 changed files with 64 additions and 19 deletions

View File

@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net5.0</TargetFramework>
<Version>6.0.5.1</Version> <Version>6.0.6.1</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -106,6 +106,11 @@ namespace DataLayer
#endregion #endregion
#region LiberatedStatuses #region LiberatedStatuses
/// <summary>
/// Occurs when <see cref="Tags"/>, <see cref="BookStatus"/>, or <see cref="PdfStatus"/> values change.
/// This signals the change of the in-memory value; it does not ensure that the new value has been persisted.
/// </summary>
public static event EventHandler<string> ItemChanged;
private LiberatedStatus _bookStatus; private LiberatedStatus _bookStatus;
private LiberatedStatus? _pdfStatus; private LiberatedStatus? _pdfStatus;
@ -132,13 +137,41 @@ namespace DataLayer
ItemChanged?.Invoke(this, nameof(PdfStatus)); ItemChanged?.Invoke(this, nameof(PdfStatus));
} }
} }
}
#endregion
#region batch changes
public static event EventHandler<string> Batch_ItemChanged;
public void BatchMode_UpdateBookStatus(LiberatedStatus value)
{
if (_bookStatus != value)
{
_bookStatus = value;
batchFlag = true;
}
}
// don't overwrite current with null. Therefore input is "LiberatedStatus" not "LiberatedStatus?"
public void BatchMode_UpdatePdfStatus(LiberatedStatus value)
{
if (_pdfStatus != value)
{
_pdfStatus = value;
batchFlag = true;
}
}
private static bool batchFlag = false;
public static void BatchMode_Finalize()
{
if (batchFlag)
Batch_ItemChanged?.Invoke(null, null);
batchFlag = false;
} }
#endregion #endregion
/// <summary>
/// Occurs when <see cref="Tags"/>, <see cref="BookStatus"/>, or <see cref="PdfStatus"/> values change.
/// This signals the change of the in-memory value; it does not ensure that the new value has been persisted.
/// </summary>
public static event EventHandler<string> ItemChanged;
public override string ToString() => $"{Book} {Rating} {Tags}"; public override string ToString() => $"{Book} {Rating} {Tags}";
} }
} }

View File

@ -315,7 +315,7 @@ namespace LibationSearchEngine
var docs = searcher.Search(query, 1); var docs = searcher.Search(query, 1);
var scoreDoc = docs.ScoreDocs.SingleOrDefault(); var scoreDoc = docs.ScoreDocs.SingleOrDefault();
if (scoreDoc == null) if (scoreDoc == null)
throw new Exception("document not found"); return;
var document = searcher.Doc(scoreDoc.Doc); var document = searcher.Doc(scoreDoc.Doc);

View File

@ -34,6 +34,8 @@ namespace LibationWinForms
this.FormClosing += (_, _) => this.SaveSizeAndLocation(Configuration.Instance); this.FormClosing += (_, _) => this.SaveSizeAndLocation(Configuration.Instance);
LibraryCommands.LibrarySizeChanged += reloadGridAndUpdateBottomNumbers; LibraryCommands.LibrarySizeChanged += reloadGridAndUpdateBottomNumbers;
LibraryCommands.BookUserDefinedItemCommitted += setBackupCounts; LibraryCommands.BookUserDefinedItemCommitted += setBackupCounts;
// used by async migrations to update ui when complete
DataLayer.UserDefinedItem.Batch_ItemChanged += reloadGridAndUpdateBottomNumbers;
var format = System.Drawing.Imaging.ImageFormat.Jpeg; var format = System.Drawing.Imaging.ImageFormat.Jpeg;
PictureStorage.SetDefaultImage(PictureSize._80x80, Properties.Resources.default_cover_80x80.ToBytes(format)); PictureStorage.SetDefaultImage(PictureSize._80x80, Properties.Resources.default_cover_80x80.ToBytes(format));

View File

@ -27,17 +27,16 @@ namespace LibationWinForms
#endregion #endregion
public event EventHandler Committed;
private Book Book => LibraryBook.Book; private Book Book => LibraryBook.Book;
private Image _cover; private Image _cover;
private Action Refilter { get; }
public GridEntry(LibraryBook libraryBook, Action refilterOnChanged = null) public GridEntry(LibraryBook libraryBook)
{ {
LibraryBook = libraryBook; LibraryBook = libraryBook;
Refilter = refilterOnChanged;
_memberValues = CreateMemberValueDictionary(); _memberValues = CreateMemberValueDictionary();
//Get cover art. If it's default, subscribe to PictureCached //Get cover art. If it's default, subscribe to PictureCached
{ {
(bool isDefault, byte[] picture) = FileManager.PictureStorage.GetPicture(new FileManager.PictureDefinition(Book.PictureId, FileManager.PictureSize._80x80)); (bool isDefault, byte[] picture) = FileManager.PictureStorage.GetPicture(new FileManager.PictureDefinition(Book.PictureId, FileManager.PictureSize._80x80));
@ -142,7 +141,7 @@ namespace LibationWinForms
Book.UserDefinedItem.BookStatus = displayStatus; Book.UserDefinedItem.BookStatus = displayStatus;
Refilter?.Invoke(); Committed?.Invoke(this, null);
} }
#endregion #endregion

View File

@ -3,9 +3,9 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
using ApplicationServices; using ApplicationServices;
using DataLayer;
using Dinah.Core; using Dinah.Core;
using Dinah.Core.DataBinding; using Dinah.Core.DataBinding;
using Dinah.Core.Threading;
using Dinah.Core.Windows.Forms; using Dinah.Core.Windows.Forms;
using LibationWinForms.Dialogs; using LibationWinForms.Dialogs;
@ -130,7 +130,12 @@ namespace LibationWinForms
} }
var orderedGridEntries = lib var orderedGridEntries = lib
.Select(lb => new GridEntry(lb, Filter)).ToList() .Select(lb =>
{
var entry = new GridEntry(lb);
entry.Committed += (_, __) => Filter();
return entry;
}).ToList()
// default load order // default load order
.OrderByDescending(ge => (DateTime)ge.GetMemberValue(nameof(ge.PurchaseDate))) .OrderByDescending(ge => (DateTime)ge.GetMemberValue(nameof(ge.PurchaseDate)))
//// more advanced example: sort by author, then series, then title //// more advanced example: sort by author, then series, then title
@ -166,8 +171,11 @@ namespace LibationWinForms
var bindingContext = BindingContext[_dataGridView.DataSource]; var bindingContext = BindingContext[_dataGridView.DataSource];
bindingContext.SuspendBinding(); bindingContext.SuspendBinding();
{ {
for (var r = _dataGridView.RowCount - 1; r >= 0; r--) this.UIThreadSync(() =>
_dataGridView.Rows[r].Visible = productIds.Contains(getGridEntry(r).AudibleProductId); {
for (var r = _dataGridView.RowCount - 1; r >= 0; r--)
_dataGridView.Rows[r].Visible = productIds.Contains(getGridEntry(r).AudibleProductId);
});
} }
//Causes repainting of the DataGridView //Causes repainting of the DataGridView

View File

@ -259,22 +259,25 @@ namespace LibationWinForms
// assign these strings and enums/ints unconditionally. EFCore will only update if changed // assign these strings and enums/ints unconditionally. EFCore will only update if changed
if (fileType == FileType.PDF) if (fileType == FileType.PDF)
book.UserDefinedItem.PdfStatus = LiberatedStatus.Liberated; book.UserDefinedItem.BatchMode_UpdatePdfStatus(LiberatedStatus.Liberated);
if (fileType == FileType.Audio) if (fileType == FileType.Audio)
{ {
var lhack = libhackFiles.FirstOrDefault(f => f.ContainsInsensitive(asin)); var lhack = libhackFiles.FirstOrDefault(f => f.ContainsInsensitive(asin));
if (lhack is null) if (lhack is null)
book.UserDefinedItem.BookStatus = LiberatedStatus.Liberated; book.UserDefinedItem.BatchMode_UpdateBookStatus(LiberatedStatus.Liberated);
else else
{ {
book.UserDefinedItem.BookStatus = LiberatedStatus.Error; book.UserDefinedItem.BatchMode_UpdateBookStatus(LiberatedStatus.Error);
libhackFilesToDelete.Add(lhack); libhackFilesToDelete.Add(lhack);
} }
} }
} }
// in order: save to db, full reindex from db, refresh ui
context.SaveChanges(); context.SaveChanges();
ApplicationServices.SearchEngineCommands.FullReIndex();
UserDefinedItem.BatchMode_Finalize();
// only do this after save changes // only do this after save changes
foreach (var libhackFile in libhackFilesToDelete) foreach (var libhackFile in libhackFilesToDelete)