Add scan and remove books tomain view, remove separate dialog.
This commit is contained in:
parent
7bcabdda38
commit
52193933b2
17 changed files with 289 additions and 485 deletions
|
|
@ -12,6 +12,12 @@ using System.Linq;
|
|||
|
||||
namespace LibationWinForms.GridView
|
||||
{
|
||||
public enum RemoveStatus
|
||||
{
|
||||
NotRemoved,
|
||||
Removed,
|
||||
SomeRemoved
|
||||
}
|
||||
/// <summary>The View Model base for the DataGridView</summary>
|
||||
public abstract class GridEntry : AsyncNotifyPropertyChanged, IMemberComparable
|
||||
{
|
||||
|
|
@ -24,6 +30,9 @@ namespace LibationWinForms.GridView
|
|||
|
||||
#region Model properties exposed to the view
|
||||
|
||||
protected RemoveStatus _remove = RemoveStatus.NotRemoved;
|
||||
public abstract RemoveStatus Remove { get; set; }
|
||||
|
||||
public abstract LiberateButtonStatus Liberate { get; }
|
||||
public Image Cover
|
||||
{
|
||||
|
|
|
|||
|
|
@ -20,6 +20,20 @@ namespace LibationWinForms.GridView
|
|||
private LiberatedStatus _bookStatus;
|
||||
private LiberatedStatus? _pdfStatus;
|
||||
|
||||
public override RemoveStatus Remove
|
||||
{
|
||||
get
|
||||
{
|
||||
return _remove;
|
||||
}
|
||||
set
|
||||
{
|
||||
_remove = value is RemoveStatus.SomeRemoved ? RemoveStatus.NotRemoved : value;
|
||||
Parent?.ChildRemoveUpdate();
|
||||
NotifyPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public override LiberateButtonStatus Liberate
|
||||
{
|
||||
get
|
||||
|
|
|
|||
|
|
@ -39,11 +39,12 @@
|
|||
this.productsGrid.Name = "productsGrid";
|
||||
this.productsGrid.Size = new System.Drawing.Size(1510, 380);
|
||||
this.productsGrid.TabIndex = 0;
|
||||
this.productsGrid.VisibleCountChanged += new System.EventHandler<int>(this.productsGrid_VisibleCountChanged);
|
||||
this.productsGrid.LiberateClicked += new LibationWinForms.GridView.LibraryBookEntryClickedEventHandler(this.productsGrid_LiberateClicked);
|
||||
this.productsGrid.CoverClicked += new LibationWinForms.GridView.GridEntryClickedEventHandler(this.productsGrid_CoverClicked);
|
||||
this.productsGrid.DetailsClicked += new LibationWinForms.GridView.LibraryBookEntryClickedEventHandler(this.productsGrid_DetailsClicked);
|
||||
this.productsGrid.DescriptionClicked += new LibationWinForms.GridView.GridEntryRectangleClickedEventHandler(this.productsGrid_DescriptionClicked);
|
||||
this.productsGrid.VisibleCountChanged += new System.EventHandler<int>(this.productsGrid_VisibleCountChanged);
|
||||
this.productsGrid.RemovableCountChanged += new LibationWinForms.GridView.GridEntryClickedEventHandler(this.productsGrid_RemovableCountChanged);
|
||||
//
|
||||
// ProductsDisplay
|
||||
//
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using ApplicationServices;
|
||||
using AudibleUtilities;
|
||||
using DataLayer;
|
||||
using FileLiberator;
|
||||
using LibationFileManager;
|
||||
|
|
@ -16,6 +17,7 @@ namespace LibationWinForms.GridView
|
|||
{
|
||||
/// <summary>Number of visible rows has changed</summary>
|
||||
public event EventHandler<int> VisibleCountChanged;
|
||||
public event EventHandler<int> RemovableCountChanged;
|
||||
public event EventHandler<LibraryBook> LiberateClicked;
|
||||
public event EventHandler InitialLoaded;
|
||||
|
||||
|
|
@ -82,6 +84,61 @@ namespace LibationWinForms.GridView
|
|||
|
||||
#region UI display functions
|
||||
|
||||
public void CloseRemoveBooksColumn()
|
||||
=> productsGrid.RemoveColumnVisible = false;
|
||||
|
||||
public async void RemoveCheckedBooksAsync()
|
||||
{
|
||||
var selectedBooks = productsGrid.GetAllBookEntries().Where(lbe => lbe.Remove is RemoveStatus.Removed).ToList();
|
||||
|
||||
if (selectedBooks.Count == 0)
|
||||
return;
|
||||
|
||||
var libraryBooks = selectedBooks.Select(rge => rge.LibraryBook).ToList();
|
||||
var result = MessageBoxLib.ShowConfirmationDialog(
|
||||
libraryBooks,
|
||||
$"Are you sure you want to remove {selectedBooks.Count} books from Libation's library?",
|
||||
"Remove books from Libation?");
|
||||
|
||||
if (result != DialogResult.Yes)
|
||||
return;
|
||||
|
||||
productsGrid.RemoveBooks(selectedBooks);
|
||||
var idsToRemove = libraryBooks.Select(lb => lb.Book.AudibleProductId).ToList();
|
||||
var removeLibraryBooks = await LibraryCommands.RemoveBooksAsync(idsToRemove);
|
||||
}
|
||||
|
||||
public async Task ScanAndRemoveBooksAsync(params Account[] accounts)
|
||||
{
|
||||
RemovableCountChanged?.Invoke(this, 0);
|
||||
productsGrid.RemoveColumnVisible = true;
|
||||
|
||||
try
|
||||
{
|
||||
if (accounts is null || accounts.Length == 0)
|
||||
return;
|
||||
|
||||
var allBooks = productsGrid.GetAllBookEntries();
|
||||
var lib = allBooks.Select(lbe => lbe.LibraryBook);
|
||||
var removedBooks = await LibraryCommands.FindInactiveBooks(Login.WinformLoginChoiceEager.ApiExtendedFunc, lib, accounts);
|
||||
|
||||
var removable = allBooks.Where(lbe => removedBooks.Any(rb => rb.Book.AudibleProductId == lbe.AudibleProductId)).ToList();
|
||||
|
||||
foreach (var r in removable)
|
||||
r.Remove = RemoveStatus.Removed;
|
||||
|
||||
productsGrid_RemovableCountChanged(null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBoxLib.ShowAdminAlert(
|
||||
this,
|
||||
"Error scanning library. You may still manually select books to remove from Libation's library.",
|
||||
"Error scanning library",
|
||||
ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void Display()
|
||||
{
|
||||
try
|
||||
|
|
@ -125,5 +182,10 @@ namespace LibationWinForms.GridView
|
|||
{
|
||||
LiberateClicked?.Invoke(this, liveGridEntry.LibraryBook);
|
||||
}
|
||||
|
||||
private void productsGrid_RemovableCountChanged(GridEntry liveGridEntry)
|
||||
{
|
||||
RemovableCountChanged?.Invoke(this, productsGrid.GetAllBookEntries().Count(lbe => lbe.Remove is RemoveStatus.Removed));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,8 +29,9 @@
|
|||
private void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
this.gridEntryDataGridView = new System.Windows.Forms.DataGridView();
|
||||
this.removeGVColumn = new System.Windows.Forms.DataGridViewCheckBoxColumn();
|
||||
this.liberateGVColumn = new LibationWinForms.GridView.LiberateDataGridViewImageButtonColumn();
|
||||
this.coverGVColumn = new System.Windows.Forms.DataGridViewImageColumn();
|
||||
this.titleGVColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
|
|
@ -60,41 +61,56 @@
|
|||
this.gridEntryDataGridView.AutoGenerateColumns = false;
|
||||
this.gridEntryDataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
|
||||
this.gridEntryDataGridView.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
|
||||
this.liberateGVColumn,
|
||||
this.coverGVColumn,
|
||||
this.titleGVColumn,
|
||||
this.authorsGVColumn,
|
||||
this.narratorsGVColumn,
|
||||
this.lengthGVColumn,
|
||||
this.seriesGVColumn,
|
||||
this.descriptionGVColumn,
|
||||
this.categoryGVColumn,
|
||||
this.productRatingGVColumn,
|
||||
this.purchaseDateGVColumn,
|
||||
this.myRatingGVColumn,
|
||||
this.miscGVColumn,
|
||||
this.tagAndDetailsGVColumn});
|
||||
this.removeGVColumn,
|
||||
this.liberateGVColumn,
|
||||
this.coverGVColumn,
|
||||
this.titleGVColumn,
|
||||
this.authorsGVColumn,
|
||||
this.narratorsGVColumn,
|
||||
this.lengthGVColumn,
|
||||
this.seriesGVColumn,
|
||||
this.descriptionGVColumn,
|
||||
this.categoryGVColumn,
|
||||
this.productRatingGVColumn,
|
||||
this.purchaseDateGVColumn,
|
||||
this.myRatingGVColumn,
|
||||
this.miscGVColumn,
|
||||
this.tagAndDetailsGVColumn});
|
||||
this.gridEntryDataGridView.ContextMenuStrip = this.contextMenuStrip1;
|
||||
this.gridEntryDataGridView.DataSource = this.syncBindingSource;
|
||||
dataGridViewCellStyle2.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
|
||||
dataGridViewCellStyle2.BackColor = System.Drawing.SystemColors.Window;
|
||||
dataGridViewCellStyle2.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
|
||||
dataGridViewCellStyle2.ForeColor = System.Drawing.SystemColors.ControlText;
|
||||
dataGridViewCellStyle2.SelectionBackColor = System.Drawing.SystemColors.Highlight;
|
||||
dataGridViewCellStyle2.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
|
||||
dataGridViewCellStyle2.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
|
||||
this.gridEntryDataGridView.DefaultCellStyle = dataGridViewCellStyle2;
|
||||
dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
|
||||
dataGridViewCellStyle1.BackColor = System.Drawing.SystemColors.Window;
|
||||
dataGridViewCellStyle1.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
|
||||
dataGridViewCellStyle1.ForeColor = System.Drawing.SystemColors.ControlText;
|
||||
dataGridViewCellStyle1.SelectionBackColor = System.Drawing.SystemColors.Highlight;
|
||||
dataGridViewCellStyle1.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
|
||||
dataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
|
||||
this.gridEntryDataGridView.DefaultCellStyle = dataGridViewCellStyle1;
|
||||
this.gridEntryDataGridView.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.gridEntryDataGridView.Location = new System.Drawing.Point(0, 0);
|
||||
this.gridEntryDataGridView.Name = "gridEntryDataGridView";
|
||||
this.gridEntryDataGridView.ReadOnly = true;
|
||||
this.gridEntryDataGridView.RowHeadersVisible = false;
|
||||
this.gridEntryDataGridView.RowTemplate.Height = 82;
|
||||
this.gridEntryDataGridView.Size = new System.Drawing.Size(1510, 380);
|
||||
this.gridEntryDataGridView.Size = new System.Drawing.Size(1570, 380);
|
||||
this.gridEntryDataGridView.TabIndex = 0;
|
||||
this.gridEntryDataGridView.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.DataGridView_CellContentClick);
|
||||
this.gridEntryDataGridView.CellToolTipTextNeeded += new System.Windows.Forms.DataGridViewCellToolTipTextNeededEventHandler(this.gridEntryDataGridView_CellToolTipTextNeeded);
|
||||
//
|
||||
// removeGVColumn
|
||||
//
|
||||
this.removeGVColumn.DataPropertyName = "Remove";
|
||||
this.removeGVColumn.FalseValue = "";
|
||||
this.removeGVColumn.Frozen = true;
|
||||
this.removeGVColumn.HeaderText = "Remove";
|
||||
this.removeGVColumn.IndeterminateValue = "";
|
||||
this.removeGVColumn.MinimumWidth = 60;
|
||||
this.removeGVColumn.Name = "removeGVColumn";
|
||||
this.removeGVColumn.Resizable = System.Windows.Forms.DataGridViewTriState.False;
|
||||
this.removeGVColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Automatic;
|
||||
this.removeGVColumn.ThreeState = true;
|
||||
this.removeGVColumn.TrueValue = "";
|
||||
this.removeGVColumn.Width = 60;
|
||||
//
|
||||
// liberateGVColumn
|
||||
//
|
||||
this.liberateGVColumn.DataPropertyName = "Liberate";
|
||||
|
|
@ -223,7 +239,7 @@
|
|||
this.AutoScroll = true;
|
||||
this.Controls.Add(this.gridEntryDataGridView);
|
||||
this.Name = "ProductsGrid";
|
||||
this.Size = new System.Drawing.Size(1510, 380);
|
||||
this.Size = new System.Drawing.Size(1570, 380);
|
||||
this.Load += new System.EventHandler(this.ProductsGrid_Load);
|
||||
((System.ComponentModel.ISupportInitialize)(this.gridEntryDataGridView)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.syncBindingSource)).EndInit();
|
||||
|
|
@ -235,6 +251,8 @@
|
|||
#endregion
|
||||
private System.Windows.Forms.DataGridView gridEntryDataGridView;
|
||||
private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
|
||||
private SyncBindingSource syncBindingSource;
|
||||
private System.Windows.Forms.DataGridViewCheckBoxColumn removeGVColumn;
|
||||
private LiberateDataGridViewImageButtonColumn liberateGVColumn;
|
||||
private System.Windows.Forms.DataGridViewImageColumn coverGVColumn;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn titleGVColumn;
|
||||
|
|
@ -249,6 +267,5 @@
|
|||
private System.Windows.Forms.DataGridViewTextBoxColumn myRatingGVColumn;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn miscGVColumn;
|
||||
private EditTagsDataGridViewImageButtonColumn tagAndDetailsGVColumn;
|
||||
private SyncBindingSource syncBindingSource;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,12 +23,15 @@ namespace LibationWinForms.GridView
|
|||
public event LibraryBookEntryClickedEventHandler DetailsClicked;
|
||||
public event GridEntryRectangleClickedEventHandler DescriptionClicked;
|
||||
public new event EventHandler<ScrollEventArgs> Scroll;
|
||||
public event GridEntryClickedEventHandler RemovableCountChanged;
|
||||
|
||||
private GridEntryBindingList bindingList;
|
||||
internal IEnumerable<LibraryBook> GetVisibleBooks()
|
||||
=> bindingList
|
||||
.BookEntries()
|
||||
.Select(lbe => lbe.LibraryBook);
|
||||
internal IEnumerable<LibraryBookEntry> GetAllBookEntries()
|
||||
=> bindingList.AllItems().BookEntries();
|
||||
|
||||
public ProductsGrid()
|
||||
{
|
||||
|
|
@ -81,6 +84,12 @@ namespace LibationWinForms.GridView
|
|||
else if (e.ColumnIndex == coverGVColumn.Index)
|
||||
CoverClicked?.Invoke(sEntry);
|
||||
}
|
||||
|
||||
if (e.ColumnIndex == removeGVColumn.Index)
|
||||
{
|
||||
gridEntryDataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit);
|
||||
RemovableCountChanged?.Invoke(entry);
|
||||
}
|
||||
}
|
||||
|
||||
private GridEntry getGridEntry(int rowIndex) => gridEntryDataGridView.GetBoundItem<GridEntry>(rowIndex);
|
||||
|
|
@ -89,6 +98,20 @@ namespace LibationWinForms.GridView
|
|||
|
||||
#region UI display functions
|
||||
|
||||
internal bool RemoveColumnVisible
|
||||
{
|
||||
get => removeGVColumn.Visible;
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
foreach (var book in bindingList.AllItems())
|
||||
book.Remove = RemoveStatus.NotRemoved;
|
||||
}
|
||||
removeGVColumn.Visible = value;
|
||||
}
|
||||
}
|
||||
|
||||
internal void BindToGrid(List<LibraryBook> dbBooks)
|
||||
{
|
||||
var geList = dbBooks.Where(lb => lb.Book.IsProduct()).Select(b => new LibraryBookEntry(b)).Cast<GridEntry>().ToList();
|
||||
|
|
@ -153,6 +176,11 @@ namespace LibationWinForms.GridView
|
|||
.BookEntries()
|
||||
.ExceptBy(dbBooks.Select(lb => lb.Book.AudibleProductId), ge => ge.AudibleProductId);
|
||||
|
||||
RemoveBooks(removedBooks);
|
||||
}
|
||||
|
||||
public void RemoveBooks(IEnumerable<LibraryBookEntry> removedBooks)
|
||||
{
|
||||
//Remove books in series from their parents' Children list
|
||||
foreach (var removed in removedBooks.Where(b => b.Parent is not null))
|
||||
{
|
||||
|
|
@ -312,6 +340,14 @@ namespace LibationWinForms.GridView
|
|||
|
||||
column.DisplayIndex = displayIndices.GetValueOrDefault(itemName, column.Index);
|
||||
}
|
||||
|
||||
//Remove column is always first;
|
||||
removeGVColumn.DisplayIndex = 0;
|
||||
removeGVColumn.Visible = false;
|
||||
removeGVColumn.ValueType = typeof(RemoveStatus);
|
||||
removeGVColumn.FalseValue = RemoveStatus.NotRemoved;
|
||||
removeGVColumn.TrueValue = RemoveStatus.Removed;
|
||||
removeGVColumn.IndeterminateValue = RemoveStatus.SomeRemoved;
|
||||
}
|
||||
|
||||
private void HideMenuItem_Click(object sender, EventArgs e)
|
||||
|
|
|
|||
|
|
@ -57,16 +57,13 @@
|
|||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="removeGVColumn.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>171, 17</value>
|
||||
</metadata>
|
||||
<metadata name="syncBindingSource.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<metadata name="bindingSource.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>326, 17</value>
|
||||
</metadata>
|
||||
<metadata name="bindingSource.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>326, 17</value>
|
||||
</metadata>
|
||||
</root>
|
||||
|
|
@ -13,7 +13,43 @@ namespace LibationWinForms.GridView
|
|||
[Browsable(false)] public List<LibraryBookEntry> Children { get; }
|
||||
[Browsable(false)] public override DateTime DateAdded => Children.Max(c => c.DateAdded);
|
||||
|
||||
private bool suspendCounting = false;
|
||||
public void ChildRemoveUpdate()
|
||||
{
|
||||
if (suspendCounting) return;
|
||||
|
||||
var removeCount = Children.Count(c => c.Remove is RemoveStatus.Removed);
|
||||
|
||||
if (removeCount == 0)
|
||||
_remove = RemoveStatus.NotRemoved;
|
||||
else if (removeCount == Children.Count)
|
||||
_remove = RemoveStatus.Removed;
|
||||
else
|
||||
_remove = RemoveStatus.SomeRemoved;
|
||||
NotifyPropertyChanged(nameof(Remove));
|
||||
}
|
||||
|
||||
#region Model properties exposed to the view
|
||||
public override RemoveStatus Remove
|
||||
{
|
||||
get
|
||||
{
|
||||
return _remove;
|
||||
}
|
||||
set
|
||||
{
|
||||
_remove = value is RemoveStatus.SomeRemoved ? RemoveStatus.NotRemoved : value;
|
||||
|
||||
suspendCounting = true;
|
||||
|
||||
foreach (var item in Children)
|
||||
item.Remove = value;
|
||||
|
||||
suspendCounting = false;
|
||||
|
||||
NotifyPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public override LiberateButtonStatus Liberate { get; }
|
||||
public override string DisplayTags { get; } = string.Empty;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue