Refactoring and addressing comments
This commit is contained in:
parent
4a82541ffd
commit
d71cdecd35
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0-windows</TargetFramework>
|
<TargetFramework>net6.0-windows</TargetFramework>
|
||||||
<Version>7.7.0.14</Version>
|
<Version>7.7.1.1</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
26
Source/LibationWinForms/Form1.Designer.cs
generated
26
Source/LibationWinForms/Form1.Designer.cs
generated
@ -98,7 +98,7 @@
|
|||||||
// filterBtn
|
// filterBtn
|
||||||
//
|
//
|
||||||
this.filterBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
this.filterBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.filterBtn.Location = new System.Drawing.Point(748, 3);
|
this.filterBtn.Location = new System.Drawing.Point(916, 3);
|
||||||
this.filterBtn.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
this.filterBtn.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||||
this.filterBtn.Name = "filterBtn";
|
this.filterBtn.Name = "filterBtn";
|
||||||
this.filterBtn.Size = new System.Drawing.Size(88, 27);
|
this.filterBtn.Size = new System.Drawing.Size(88, 27);
|
||||||
@ -114,7 +114,7 @@
|
|||||||
this.filterSearchTb.Location = new System.Drawing.Point(196, 7);
|
this.filterSearchTb.Location = new System.Drawing.Point(196, 7);
|
||||||
this.filterSearchTb.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
this.filterSearchTb.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||||
this.filterSearchTb.Name = "filterSearchTb";
|
this.filterSearchTb.Name = "filterSearchTb";
|
||||||
this.filterSearchTb.Size = new System.Drawing.Size(544, 23);
|
this.filterSearchTb.Size = new System.Drawing.Size(712, 23);
|
||||||
this.filterSearchTb.TabIndex = 1;
|
this.filterSearchTb.TabIndex = 1;
|
||||||
this.filterSearchTb.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.filterSearchTb_KeyPress);
|
this.filterSearchTb.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.filterSearchTb_KeyPress);
|
||||||
//
|
//
|
||||||
@ -132,7 +132,7 @@
|
|||||||
this.menuStrip1.Location = new System.Drawing.Point(0, 0);
|
this.menuStrip1.Location = new System.Drawing.Point(0, 0);
|
||||||
this.menuStrip1.Name = "menuStrip1";
|
this.menuStrip1.Name = "menuStrip1";
|
||||||
this.menuStrip1.Padding = new System.Windows.Forms.Padding(7, 2, 0, 2);
|
this.menuStrip1.Padding = new System.Windows.Forms.Padding(7, 2, 0, 2);
|
||||||
this.menuStrip1.Size = new System.Drawing.Size(893, 24);
|
this.menuStrip1.Size = new System.Drawing.Size(1061, 24);
|
||||||
this.menuStrip1.TabIndex = 0;
|
this.menuStrip1.TabIndex = 0;
|
||||||
this.menuStrip1.Text = "menuStrip1";
|
this.menuStrip1.Text = "menuStrip1";
|
||||||
//
|
//
|
||||||
@ -396,7 +396,7 @@
|
|||||||
this.statusStrip1.Location = new System.Drawing.Point(0, 618);
|
this.statusStrip1.Location = new System.Drawing.Point(0, 618);
|
||||||
this.statusStrip1.Name = "statusStrip1";
|
this.statusStrip1.Name = "statusStrip1";
|
||||||
this.statusStrip1.Padding = new System.Windows.Forms.Padding(1, 0, 16, 0);
|
this.statusStrip1.Padding = new System.Windows.Forms.Padding(1, 0, 16, 0);
|
||||||
this.statusStrip1.Size = new System.Drawing.Size(893, 22);
|
this.statusStrip1.Size = new System.Drawing.Size(1061, 22);
|
||||||
this.statusStrip1.TabIndex = 6;
|
this.statusStrip1.TabIndex = 6;
|
||||||
this.statusStrip1.Text = "statusStrip1";
|
this.statusStrip1.Text = "statusStrip1";
|
||||||
//
|
//
|
||||||
@ -410,7 +410,7 @@
|
|||||||
// springLbl
|
// springLbl
|
||||||
//
|
//
|
||||||
this.springLbl.Name = "springLbl";
|
this.springLbl.Name = "springLbl";
|
||||||
this.springLbl.Size = new System.Drawing.Size(379, 17);
|
this.springLbl.Size = new System.Drawing.Size(547, 17);
|
||||||
this.springLbl.Spring = true;
|
this.springLbl.Spring = true;
|
||||||
//
|
//
|
||||||
// backupsCountsLbl
|
// backupsCountsLbl
|
||||||
@ -452,8 +452,8 @@
|
|||||||
// splitContainer1.Panel2
|
// splitContainer1.Panel2
|
||||||
//
|
//
|
||||||
this.splitContainer1.Panel2.Controls.Add(this.processBookQueue1);
|
this.splitContainer1.Panel2.Controls.Add(this.processBookQueue1);
|
||||||
this.splitContainer1.Size = new System.Drawing.Size(1231, 640);
|
this.splitContainer1.Size = new System.Drawing.Size(1463, 640);
|
||||||
this.splitContainer1.SplitterDistance = 893;
|
this.splitContainer1.SplitterDistance = 1061;
|
||||||
this.splitContainer1.SplitterWidth = 8;
|
this.splitContainer1.SplitterWidth = 8;
|
||||||
this.splitContainer1.TabIndex = 7;
|
this.splitContainer1.TabIndex = 7;
|
||||||
//
|
//
|
||||||
@ -470,7 +470,7 @@
|
|||||||
this.panel1.Location = new System.Drawing.Point(0, 24);
|
this.panel1.Location = new System.Drawing.Point(0, 24);
|
||||||
this.panel1.Margin = new System.Windows.Forms.Padding(0);
|
this.panel1.Margin = new System.Windows.Forms.Padding(0);
|
||||||
this.panel1.Name = "panel1";
|
this.panel1.Name = "panel1";
|
||||||
this.panel1.Size = new System.Drawing.Size(893, 594);
|
this.panel1.Size = new System.Drawing.Size(1061, 594);
|
||||||
this.panel1.TabIndex = 7;
|
this.panel1.TabIndex = 7;
|
||||||
//
|
//
|
||||||
// productsDisplay
|
// productsDisplay
|
||||||
@ -482,16 +482,16 @@
|
|||||||
this.productsDisplay.Location = new System.Drawing.Point(15, 36);
|
this.productsDisplay.Location = new System.Drawing.Point(15, 36);
|
||||||
this.productsDisplay.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
this.productsDisplay.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||||
this.productsDisplay.Name = "productsDisplay";
|
this.productsDisplay.Name = "productsDisplay";
|
||||||
this.productsDisplay.Size = new System.Drawing.Size(863, 555);
|
this.productsDisplay.Size = new System.Drawing.Size(1031, 555);
|
||||||
this.productsDisplay.TabIndex = 9;
|
this.productsDisplay.TabIndex = 9;
|
||||||
this.productsDisplay.LiberateClicked += new System.EventHandler<DataLayer.LibraryBook>(this.ProductsDisplay_LiberateClicked);
|
|
||||||
this.productsDisplay.VisibleCountChanged += new System.EventHandler<int>(this.productsDisplay_VisibleCountChanged);
|
this.productsDisplay.VisibleCountChanged += new System.EventHandler<int>(this.productsDisplay_VisibleCountChanged);
|
||||||
|
this.productsDisplay.LiberateClicked += new System.EventHandler<DataLayer.LibraryBook>(this.ProductsDisplay_LiberateClicked);
|
||||||
this.productsDisplay.InitialLoaded += new System.EventHandler(this.productsDisplay_InitialLoaded);
|
this.productsDisplay.InitialLoaded += new System.EventHandler(this.productsDisplay_InitialLoaded);
|
||||||
//
|
//
|
||||||
// toggleQueueHideBtn
|
// toggleQueueHideBtn
|
||||||
//
|
//
|
||||||
this.toggleQueueHideBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
this.toggleQueueHideBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.toggleQueueHideBtn.Location = new System.Drawing.Point(845, 3);
|
this.toggleQueueHideBtn.Location = new System.Drawing.Point(1013, 3);
|
||||||
this.toggleQueueHideBtn.Margin = new System.Windows.Forms.Padding(4, 3, 15, 3);
|
this.toggleQueueHideBtn.Margin = new System.Windows.Forms.Padding(4, 3, 15, 3);
|
||||||
this.toggleQueueHideBtn.Name = "toggleQueueHideBtn";
|
this.toggleQueueHideBtn.Name = "toggleQueueHideBtn";
|
||||||
this.toggleQueueHideBtn.Size = new System.Drawing.Size(33, 27);
|
this.toggleQueueHideBtn.Size = new System.Drawing.Size(33, 27);
|
||||||
@ -507,14 +507,14 @@
|
|||||||
this.processBookQueue1.Location = new System.Drawing.Point(0, 0);
|
this.processBookQueue1.Location = new System.Drawing.Point(0, 0);
|
||||||
this.processBookQueue1.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
this.processBookQueue1.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||||
this.processBookQueue1.Name = "processBookQueue1";
|
this.processBookQueue1.Name = "processBookQueue1";
|
||||||
this.processBookQueue1.Size = new System.Drawing.Size(330, 640);
|
this.processBookQueue1.Size = new System.Drawing.Size(394, 640);
|
||||||
this.processBookQueue1.TabIndex = 0;
|
this.processBookQueue1.TabIndex = 0;
|
||||||
//
|
//
|
||||||
// Form1
|
// Form1
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.ClientSize = new System.Drawing.Size(1231, 640);
|
this.ClientSize = new System.Drawing.Size(1463, 640);
|
||||||
this.Controls.Add(this.splitContainer1);
|
this.Controls.Add(this.splitContainer1);
|
||||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||||
this.MainMenuStrip = this.menuStrip1;
|
this.MainMenuStrip = this.menuStrip1;
|
||||||
|
|||||||
@ -57,12 +57,48 @@
|
|||||||
<resheader name="writer">
|
<resheader name="writer">
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
|
<metadata name="filterHelpBtn.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>True</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="filterBtn.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>True</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="filterSearchTb.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>True</value>
|
||||||
|
</metadata>
|
||||||
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
<value>17, 17</value>
|
<value>17, 17</value>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
<metadata name="menuStrip1.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>True</value>
|
||||||
|
</metadata>
|
||||||
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
<value>132, 17</value>
|
<value>132, 17</value>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
<metadata name="statusStrip1.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>True</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="addQuickFilterBtn.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>True</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="splitContainer1.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>True</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="panel1.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>True</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="productsDisplay.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>True</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="toggleQueueHideBtn.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>True</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="processBookQueue1.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>True</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="$this.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>True</value>
|
||||||
|
</metadata>
|
||||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
|
|||||||
@ -46,24 +46,31 @@ namespace LibationWinForms.ProcessQueue
|
|||||||
public ProcessQueueControl()
|
public ProcessQueueControl()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
Logger = LogMe.RegisterForm(this);
|
|
||||||
|
|
||||||
runningTimeLbl.Text = string.Empty;
|
|
||||||
popoutBtn.DisplayStyle = ToolStripItemDisplayStyle.Text;
|
popoutBtn.DisplayStyle = ToolStripItemDisplayStyle.Text;
|
||||||
popoutBtn.Name = "popoutBtn";
|
popoutBtn.Name = "popoutBtn";
|
||||||
popoutBtn.Text = "Pop Out";
|
popoutBtn.Text = "Pop Out";
|
||||||
popoutBtn.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
popoutBtn.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||||
popoutBtn.Alignment = ToolStripItemAlignment.Right;
|
popoutBtn.Alignment = ToolStripItemAlignment.Right;
|
||||||
popoutBtn.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
|
popoutBtn.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
|
||||||
|
|
||||||
statusStrip1.Items.Add(popoutBtn);
|
statusStrip1.Items.Add(popoutBtn);
|
||||||
|
|
||||||
|
Logger = LogMe.RegisterForm(this);
|
||||||
|
|
||||||
virtualFlowControl2.RequestData += VirtualFlowControl1_RequestData;
|
virtualFlowControl2.RequestData += VirtualFlowControl1_RequestData;
|
||||||
virtualFlowControl2.ButtonClicked += VirtualFlowControl2_ButtonClicked;
|
virtualFlowControl2.ButtonClicked += VirtualFlowControl2_ButtonClicked;
|
||||||
|
|
||||||
Queue.QueuededCountChanged += Queue_QueuededCountChanged;
|
Queue.QueuededCountChanged += Queue_QueuededCountChanged;
|
||||||
Queue.CompletedCountChanged += Queue_CompletedCountChanged;
|
Queue.CompletedCountChanged += Queue_CompletedCountChanged;
|
||||||
|
|
||||||
|
Load += ProcessQueueControl_Load;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessQueueControl_Load(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (DesignMode) return;
|
||||||
|
|
||||||
|
runningTimeLbl.Text = string.Empty;
|
||||||
QueuedCount = 0;
|
QueuedCount = 0;
|
||||||
ErrorCount = 0;
|
ErrorCount = 0;
|
||||||
CompletedCount = 0;
|
CompletedCount = 0;
|
||||||
|
|||||||
@ -114,9 +114,6 @@ namespace LibationWinForms.ProcessQueue
|
|||||||
BookControls.Add(control);
|
BookControls.Add(control);
|
||||||
panel1.Controls.Add(control);
|
panel1.Controls.Add(control);
|
||||||
|
|
||||||
if (DesignMode)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (int i = 1; i < NUM_ACTUAL_CONTROLS; i++)
|
for (int i = 1; i < NUM_ACTUAL_CONTROLS; i++)
|
||||||
{
|
{
|
||||||
control = InitControl(VirtualControlHeight * i);
|
control = InitControl(VirtualControlHeight * i);
|
||||||
|
|||||||
@ -5,37 +5,12 @@ using LibationFileManager;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace LibationWinForms
|
namespace LibationWinForms
|
||||||
{
|
{
|
||||||
public interface IHierarchical<T> where T : class
|
public abstract class GridEntry : AsyncNotifyPropertyChanged, IMemberComparable
|
||||||
{
|
|
||||||
T Parent { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LiberateButtonStatus : IComparable
|
|
||||||
{
|
|
||||||
public LiberatedStatus BookStatus;
|
|
||||||
public LiberatedStatus? PdfStatus;
|
|
||||||
public bool IsSeries;
|
|
||||||
public bool Expanded;
|
|
||||||
|
|
||||||
public int CompareTo(object obj)
|
|
||||||
{
|
|
||||||
if (obj is not LiberateButtonStatus second) return -1;
|
|
||||||
|
|
||||||
if (IsSeries && !second.IsSeries) return -1;
|
|
||||||
else if (!IsSeries && second.IsSeries) return 1;
|
|
||||||
else if (IsSeries && second.IsSeries) return 0;
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract class GridEntry : AsyncNotifyPropertyChanged, IMemberComparable, IHierarchical<GridEntry>
|
|
||||||
{
|
{
|
||||||
protected abstract Book Book { get; }
|
protected abstract Book Book { get; }
|
||||||
|
|
||||||
@ -50,12 +25,7 @@ namespace LibationWinForms
|
|||||||
NotifyPropertyChanged();
|
NotifyPropertyChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Browsable(false)]
|
|
||||||
public new bool InvokeRequired => base.InvokeRequired;
|
public new bool InvokeRequired => base.InvokeRequired;
|
||||||
[Browsable(false)]
|
|
||||||
public GridEntry Parent { get; set; }
|
|
||||||
[Browsable(false)]
|
|
||||||
public abstract DateTime DateAdded { get; }
|
public abstract DateTime DateAdded { get; }
|
||||||
public abstract string ProductRating { get; protected set; }
|
public abstract string ProductRating { get; protected set; }
|
||||||
public abstract string PurchaseDate { get; protected set; }
|
public abstract string PurchaseDate { get; protected set; }
|
||||||
@ -116,9 +86,16 @@ namespace LibationWinForms
|
|||||||
|
|
||||||
internal static class GridEntryExtensions
|
internal static class GridEntryExtensions
|
||||||
{
|
{
|
||||||
|
#nullable enable
|
||||||
public static IEnumerable<SeriesEntry> Series(this IEnumerable<GridEntry> gridEntries)
|
public static IEnumerable<SeriesEntry> Series(this IEnumerable<GridEntry> gridEntries)
|
||||||
=> gridEntries.Where(i => i is SeriesEntry).Cast<SeriesEntry>();
|
=> gridEntries.Where(i => i is SeriesEntry).Cast<SeriesEntry>();
|
||||||
public static IEnumerable<LibraryBookEntry> LibraryBooks(this IEnumerable<GridEntry> gridEntries)
|
public static IEnumerable<LibraryBookEntry> LibraryBooks(this IEnumerable<GridEntry> gridEntries)
|
||||||
=> gridEntries.Where(i => i is LibraryBookEntry).Cast<LibraryBookEntry>();
|
=> gridEntries.Where(i => i is LibraryBookEntry).Cast<LibraryBookEntry>();
|
||||||
|
public static LibraryBookEntry? FindBookByAsin(this IEnumerable<LibraryBookEntry> gridEntries, string audibleProductID)
|
||||||
|
=> gridEntries.FirstOrDefault(i => i.AudibleProductId == audibleProductID);
|
||||||
|
public static SeriesEntry? FindBookSeriesEntry(this IEnumerable<GridEntry> gridEntries, IEnumerable<SeriesBook> matchSeries)
|
||||||
|
=> gridEntries.Series().FirstOrDefault(i => matchSeries.Any(s => s.Series.Name == i.Series));
|
||||||
|
public static IEnumerable<SeriesEntry> EmptySeries(this IEnumerable<GridEntry> gridEntries)
|
||||||
|
=> gridEntries.Series().Where(i => i.Children.Count == 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,7 @@ using System.Linq;
|
|||||||
namespace LibationWinForms
|
namespace LibationWinForms
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Allows filtering of the underlying SortableBindingList<GridEntry>
|
* Allows filtering and sorting of the underlying BindingList<GridEntry>
|
||||||
* by implementing IBindingListView and using SearchEngineCommands
|
* by implementing IBindingListView and using SearchEngineCommands
|
||||||
*
|
*
|
||||||
* When filtering is applied, the filtered-out items are removed
|
* When filtering is applied, the filtered-out items are removed
|
||||||
@ -19,19 +19,34 @@ namespace LibationWinForms
|
|||||||
* Remove is overridden to ensure that removed items are removed from
|
* Remove is overridden to ensure that removed items are removed from
|
||||||
* the base list (visible items) as well as the FilterRemoved list.
|
* the base list (visible items) as well as the FilterRemoved list.
|
||||||
*/
|
*/
|
||||||
internal class FilterableSortableBindingList : SortableBindingList1<GridEntry>, IBindingListView
|
internal class GridEntryBindingList : BindingList<GridEntry>, IBindingListView
|
||||||
{
|
{
|
||||||
|
private bool isSorted;
|
||||||
|
private ListSortDirection listSortDirection;
|
||||||
|
private PropertyDescriptor propertyDescriptor;
|
||||||
|
|
||||||
|
public GridEntryBindingList() : base(new List<GridEntry>()) { }
|
||||||
|
public GridEntryBindingList(IEnumerable<GridEntry> enumeration) : base(new List<GridEntry>(enumeration)) { }
|
||||||
|
|
||||||
|
/// <returns>All items in the list, including those filtered out.</returns>
|
||||||
|
public List<GridEntry> AllItems() => Items.Concat(FilterRemoved).ToList();
|
||||||
|
|
||||||
|
protected MemberComparer<GridEntry> Comparer { get; } = new();
|
||||||
|
protected override bool SupportsSortingCore => true;
|
||||||
|
protected override bool SupportsSearchingCore => true;
|
||||||
|
protected override bool IsSortedCore => isSorted;
|
||||||
|
protected override PropertyDescriptor SortPropertyCore => propertyDescriptor;
|
||||||
|
protected override ListSortDirection SortDirectionCore => listSortDirection;
|
||||||
|
public bool SupportsFiltering => true;
|
||||||
|
public string Filter { get => FilterString; set => ApplyFilter(value); }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Items that were removed from the base list due to filtering
|
/// Items that were removed from the base list due to filtering
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly List<GridEntry> FilterRemoved = new();
|
private readonly List<GridEntry> FilterRemoved = new();
|
||||||
private string FilterString;
|
private string FilterString;
|
||||||
private LibationSearchEngine.SearchResultSet SearchResults;
|
private LibationSearchEngine.SearchResultSet SearchResults;
|
||||||
public FilterableSortableBindingList(IEnumerable<GridEntry> enumeration) : base(enumeration) { }
|
|
||||||
public FilterableSortableBindingList() : base(new List<GridEntry>()) { }
|
|
||||||
|
|
||||||
public bool SupportsFiltering => true;
|
|
||||||
public string Filter { get => FilterString; set => ApplyFilter(value); }
|
|
||||||
|
|
||||||
#region Unused - Advanced Filtering
|
#region Unused - Advanced Filtering
|
||||||
public bool SupportsAdvancedSorting => false;
|
public bool SupportsAdvancedSorting => false;
|
||||||
@ -49,9 +64,6 @@ namespace LibationWinForms
|
|||||||
base.Remove(entry);
|
base.Remove(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <returns>All items in the list, including those filtered out.</returns>
|
|
||||||
public List<GridEntry> AllItems() => Items.Concat(FilterRemoved).ToList();
|
|
||||||
|
|
||||||
private void ApplyFilter(string filterString)
|
private void ApplyFilter(string filterString)
|
||||||
{
|
{
|
||||||
if (filterString != FilterString)
|
if (filterString != FilterString)
|
||||||
@ -88,7 +100,7 @@ namespace LibationWinForms
|
|||||||
|
|
||||||
public void CollapseItem(SeriesEntry sEntry)
|
public void CollapseItem(SeriesEntry sEntry)
|
||||||
{
|
{
|
||||||
foreach (var episode in Items.Where(b => b.Parent == sEntry).Cast<LibraryBookEntry>().ToList())
|
foreach (var episode in Items.LibraryBooks().Where(b => b.Parent == sEntry).ToList())
|
||||||
{
|
{
|
||||||
FilterRemoved.Add(episode);
|
FilterRemoved.Add(episode);
|
||||||
base.Remove(episode);
|
base.Remove(episode);
|
||||||
@ -101,7 +113,7 @@ namespace LibationWinForms
|
|||||||
{
|
{
|
||||||
var sindex = Items.IndexOf(sEntry);
|
var sindex = Items.IndexOf(sEntry);
|
||||||
|
|
||||||
foreach (var episode in FilterRemoved.Where(b => b.Parent == sEntry).Cast<LibraryBookEntry>().ToList())
|
foreach (var episode in FilterRemoved.LibraryBooks().Where(b => b.Parent == sEntry).ToList())
|
||||||
{
|
{
|
||||||
if (SearchResults is null || SearchResults.Docs.Any(d => d.ProductId == episode.AudibleProductId))
|
if (SearchResults is null || SearchResults.Docs.Any(d => d.ProductId == episode.AudibleProductId))
|
||||||
{
|
{
|
||||||
@ -120,23 +132,19 @@ namespace LibationWinForms
|
|||||||
|
|
||||||
int visibleCount = Items.Count;
|
int visibleCount = Items.Count;
|
||||||
|
|
||||||
SuspendSorting = true;
|
|
||||||
|
|
||||||
foreach (var item in FilterRemoved.ToList())
|
foreach (var item in FilterRemoved.ToList())
|
||||||
{
|
{
|
||||||
if (item.Parent is null || item.Parent.Liberate.Expanded)
|
if (item is SeriesEntry || (item is LibraryBookEntry lbe && (lbe.Parent is null || lbe.Parent.Liberate.Expanded)))
|
||||||
{
|
{
|
||||||
FilterRemoved.Remove(item);
|
FilterRemoved.Remove(item);
|
||||||
base.InsertItem(visibleCount++, item);
|
base.InsertItem(visibleCount++, item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SuspendSorting = false;
|
|
||||||
|
|
||||||
if (IsSortedCore)
|
if (IsSortedCore)
|
||||||
Sort();
|
Sort();
|
||||||
else
|
else
|
||||||
//No user sort is applied, so do default sorting by PurchaseDate, descending
|
//No user sort is applied, so do default sorting by DateAdded, descending
|
||||||
{
|
{
|
||||||
Comparer.PropertyName = nameof(GridEntry.DateAdded);
|
Comparer.PropertyName = nameof(GridEntry.DateAdded);
|
||||||
Comparer.Direction = ListSortDirection.Descending;
|
Comparer.Direction = ListSortDirection.Descending;
|
||||||
@ -148,5 +156,64 @@ namespace LibationWinForms
|
|||||||
FilterString = null;
|
FilterString = null;
|
||||||
SearchResults = null;
|
SearchResults = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void ApplySortCore(PropertyDescriptor property, ListSortDirection direction)
|
||||||
|
{
|
||||||
|
Comparer.PropertyName = property.Name;
|
||||||
|
Comparer.Direction = direction;
|
||||||
|
|
||||||
|
Sort();
|
||||||
|
|
||||||
|
propertyDescriptor = property;
|
||||||
|
listSortDirection = direction;
|
||||||
|
isSorted = true;
|
||||||
|
|
||||||
|
OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void Sort()
|
||||||
|
{
|
||||||
|
var itemsList = (List<GridEntry>)Items;
|
||||||
|
|
||||||
|
var sortedItems = Items.OrderBy(ge => ge, Comparer).ToList();
|
||||||
|
|
||||||
|
var children = sortedItems.LibraryBooks().Where(i => i.Parent is not null).ToList();
|
||||||
|
|
||||||
|
itemsList.Clear();
|
||||||
|
|
||||||
|
//Only add parentless items at this stage. After these items are added in the
|
||||||
|
//correct sorting order, go back and add the children beneath their parents.
|
||||||
|
itemsList.AddRange(sortedItems.Except(children));
|
||||||
|
|
||||||
|
foreach (var parent in children.Select(c => c.Parent).Distinct())
|
||||||
|
{
|
||||||
|
var pIndex = itemsList.IndexOf(parent);
|
||||||
|
foreach (var c in children.Where(c => c.Parent == parent))
|
||||||
|
itemsList.Insert(++pIndex, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnListChanged(ListChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (isSorted && e.ListChangedType == ListChangedType.ItemChanged && e.PropertyDescriptor == SortPropertyCore)
|
||||||
|
{
|
||||||
|
var item = Items[e.NewIndex];
|
||||||
|
Sort();
|
||||||
|
var newIndex = Items.IndexOf(item);
|
||||||
|
|
||||||
|
base.OnListChanged(new ListChangedEventArgs(ListChangedType.ItemMoved, newIndex, e.NewIndex));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
base.OnListChanged(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void RemoveSortCore()
|
||||||
|
{
|
||||||
|
isSorted = false;
|
||||||
|
propertyDescriptor = base.SortPropertyCore;
|
||||||
|
listSortDirection = base.SortDirectionCore;
|
||||||
|
|
||||||
|
OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
28
Source/LibationWinForms/grid/LiberateButtonStatus.cs
Normal file
28
Source/LibationWinForms/grid/LiberateButtonStatus.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using DataLayer;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace LibationWinForms
|
||||||
|
{
|
||||||
|
public class LiberateButtonStatus : IComparable
|
||||||
|
{
|
||||||
|
public LiberatedStatus BookStatus { get; set; }
|
||||||
|
public LiberatedStatus? PdfStatus { get; set; }
|
||||||
|
public bool IsSeries { get; init; }
|
||||||
|
public bool Expanded { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the Liberate column's sorting behavior
|
||||||
|
/// </summary>
|
||||||
|
public int CompareTo(object obj)
|
||||||
|
{
|
||||||
|
if (obj is not LiberateButtonStatus second) return -1;
|
||||||
|
|
||||||
|
if (IsSeries && !second.IsSeries) return -1;
|
||||||
|
else if (!IsSeries && second.IsSeries) return 1;
|
||||||
|
else if (IsSeries && second.IsSeries) return 0;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,16 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Drawing;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using ApplicationServices;
|
using ApplicationServices;
|
||||||
using DataLayer;
|
using DataLayer;
|
||||||
using Dinah.Core.DataBinding;
|
|
||||||
using Dinah.Core;
|
using Dinah.Core;
|
||||||
using Dinah.Core.Drawing;
|
|
||||||
using LibationFileManager;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace LibationWinForms
|
namespace LibationWinForms
|
||||||
{
|
{
|
||||||
@ -30,7 +24,6 @@ namespace LibationWinForms
|
|||||||
public string LongDescription { get; private set; }
|
public string LongDescription { get; private set; }
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
// alias
|
|
||||||
protected override Book Book => LibraryBook.Book;
|
protected override Book Book => LibraryBook.Book;
|
||||||
#region Model properties exposed to the view
|
#region Model properties exposed to the view
|
||||||
|
|
||||||
@ -69,9 +62,9 @@ namespace LibationWinForms
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
public LibraryBookEntry(LibraryBook libraryBook) => setLibraryBook(libraryBook);
|
public LibraryBookEntry(LibraryBook libraryBook) => setLibraryBook(libraryBook);
|
||||||
|
|
||||||
|
public SeriesEntry Parent { get; init; }
|
||||||
public void UpdateLibraryBook(LibraryBook libraryBook)
|
public void UpdateLibraryBook(LibraryBook libraryBook)
|
||||||
{
|
{
|
||||||
if (AudibleProductId != libraryBook.Book.AudibleProductId)
|
if (AudibleProductId != libraryBook.Book.AudibleProductId)
|
||||||
|
|||||||
@ -47,10 +47,8 @@
|
|||||||
this.tagAndDetailsGVColumn = new LibationWinForms.EditTagsDataGridViewImageButtonColumn();
|
this.tagAndDetailsGVColumn = new LibationWinForms.EditTagsDataGridViewImageButtonColumn();
|
||||||
this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
|
this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||||
this.syncBindingSource = new LibationWinForms.SyncBindingSource(this.components);
|
this.syncBindingSource = new LibationWinForms.SyncBindingSource(this.components);
|
||||||
this.bindingSource = new System.Windows.Forms.BindingSource(this.components);
|
|
||||||
((System.ComponentModel.ISupportInitialize)(this.gridEntryDataGridView)).BeginInit();
|
((System.ComponentModel.ISupportInitialize)(this.gridEntryDataGridView)).BeginInit();
|
||||||
((System.ComponentModel.ISupportInitialize)(this.syncBindingSource)).BeginInit();
|
((System.ComponentModel.ISupportInitialize)(this.syncBindingSource)).BeginInit();
|
||||||
((System.ComponentModel.ISupportInitialize)(this.bindingSource)).BeginInit();
|
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// gridEntryDataGridView
|
// gridEntryDataGridView
|
||||||
@ -216,11 +214,7 @@
|
|||||||
//
|
//
|
||||||
// syncBindingSource
|
// syncBindingSource
|
||||||
//
|
//
|
||||||
this.syncBindingSource.DataSource = this.bindingSource;
|
this.syncBindingSource.DataSource = typeof(LibationWinForms.GridEntry);
|
||||||
//
|
|
||||||
// bindingSource
|
|
||||||
//
|
|
||||||
this.bindingSource.DataSource = typeof(LibationWinForms.GridEntry);
|
|
||||||
//
|
//
|
||||||
// ProductsGrid
|
// ProductsGrid
|
||||||
//
|
//
|
||||||
@ -233,7 +227,6 @@
|
|||||||
this.Load += new System.EventHandler(this.ProductsGrid_Load);
|
this.Load += new System.EventHandler(this.ProductsGrid_Load);
|
||||||
((System.ComponentModel.ISupportInitialize)(this.gridEntryDataGridView)).EndInit();
|
((System.ComponentModel.ISupportInitialize)(this.gridEntryDataGridView)).EndInit();
|
||||||
((System.ComponentModel.ISupportInitialize)(this.syncBindingSource)).EndInit();
|
((System.ComponentModel.ISupportInitialize)(this.syncBindingSource)).EndInit();
|
||||||
((System.ComponentModel.ISupportInitialize)(this.bindingSource)).EndInit();
|
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -257,6 +250,5 @@
|
|||||||
private System.Windows.Forms.DataGridViewTextBoxColumn miscGVColumn;
|
private System.Windows.Forms.DataGridViewTextBoxColumn miscGVColumn;
|
||||||
private EditTagsDataGridViewImageButtonColumn tagAndDetailsGVColumn;
|
private EditTagsDataGridViewImageButtonColumn tagAndDetailsGVColumn;
|
||||||
private SyncBindingSource syncBindingSource;
|
private SyncBindingSource syncBindingSource;
|
||||||
private System.Windows.Forms.BindingSource bindingSource;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,7 +23,7 @@ namespace LibationWinForms.grid
|
|||||||
public event LibraryBookEntryRectangleClickedEventHandler DescriptionClicked;
|
public event LibraryBookEntryRectangleClickedEventHandler DescriptionClicked;
|
||||||
public new event EventHandler<ScrollEventArgs> Scroll;
|
public new event EventHandler<ScrollEventArgs> Scroll;
|
||||||
|
|
||||||
private FilterableSortableBindingList bindingList;
|
private GridEntryBindingList bindingList;
|
||||||
internal IEnumerable<LibraryBookEntry> GetVisible()
|
internal IEnumerable<LibraryBookEntry> GetVisible()
|
||||||
=> bindingList
|
=> bindingList
|
||||||
.LibraryBooks();
|
.LibraryBooks();
|
||||||
@ -89,20 +89,15 @@ namespace LibationWinForms.grid
|
|||||||
|
|
||||||
var episodes = dbBooks.Where(b => b.Book.ContentType is ContentType.Episode).ToList();
|
var episodes = dbBooks.Where(b => b.Book.ContentType is ContentType.Episode).ToList();
|
||||||
|
|
||||||
var series = episodes.Select(lb => lb.Book.SeriesLink.First()).DistinctBy(s => s.Series).ToList();
|
foreach (var series in episodes.Select(lb => lb.Book.SeriesLink.First()).DistinctBy(s => s.Series))
|
||||||
|
|
||||||
foreach (var s in series)
|
|
||||||
{
|
{
|
||||||
var seriesEntry = new SeriesEntry();
|
var seriesEntry = new SeriesEntry(series, episodes.Where(lb => lb.Book.SeriesLink.First().Series == series.Book.SeriesLink.First().Series));
|
||||||
seriesEntry.Children = episodes.Where(lb => lb.Book.SeriesLink.First().Series == s.Book.SeriesLink.First().Series).Select(lb => new LibraryBookEntry(lb) { Parent = seriesEntry }).ToList();
|
|
||||||
|
|
||||||
seriesEntry.setSeriesBook(s);
|
|
||||||
|
|
||||||
geList.Add(seriesEntry);
|
geList.Add(seriesEntry);
|
||||||
geList.AddRange(seriesEntry.Children);
|
geList.AddRange(seriesEntry.Children);
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingList = new FilterableSortableBindingList(geList.OrderByDescending(e => e.DateAdded));
|
bindingList = new GridEntryBindingList(geList.OrderByDescending(e => e.DateAdded));
|
||||||
bindingList.CollapseAll();
|
bindingList.CollapseAll();
|
||||||
syncBindingSource.DataSource = bindingList;
|
syncBindingSource.DataSource = bindingList;
|
||||||
VisibleCountChanged?.Invoke(this, bindingList.LibraryBooks().Count());
|
VisibleCountChanged?.Invoke(this, bindingList.LibraryBooks().Count());
|
||||||
@ -116,39 +111,36 @@ namespace LibationWinForms.grid
|
|||||||
//Add absent books to grid, or update current books
|
//Add absent books to grid, or update current books
|
||||||
|
|
||||||
var allItmes = bindingList.AllItems().LibraryBooks();
|
var allItmes = bindingList.AllItems().LibraryBooks();
|
||||||
for (var i = dbBooks.Count - 1; i >= 0; i--)
|
foreach (var libraryBook in dbBooks)
|
||||||
{
|
{
|
||||||
var libraryBook = dbBooks[i];
|
var existingItem = allItmes.FindBookByAsin(libraryBook.Book.AudibleProductId);
|
||||||
var existingItem = allItmes.FirstOrDefault(i => i.AudibleProductId == libraryBook.Book.AudibleProductId);
|
|
||||||
|
|
||||||
// add new to top
|
// add new to top
|
||||||
if (existingItem is null)
|
if (existingItem is null)
|
||||||
{
|
{
|
||||||
var lb = new LibraryBookEntry(libraryBook);
|
|
||||||
|
|
||||||
if (libraryBook.Book.ContentType is ContentType.Episode)
|
if (libraryBook.Book.ContentType is ContentType.Episode)
|
||||||
{
|
{
|
||||||
|
LibraryBookEntry lbe;
|
||||||
//Find the series that libraryBook belongs to, if it exists
|
//Find the series that libraryBook belongs to, if it exists
|
||||||
var series = bindingList.AllItems().Series().FirstOrDefault(i => libraryBook.Book.SeriesLink.Any(s => s.Series.Name == i.Series));
|
var series = bindingList.AllItems().FindBookSeriesEntry(libraryBook.Book.SeriesLink);
|
||||||
|
|
||||||
if (series is null)
|
if (series is null)
|
||||||
{
|
{
|
||||||
//Series doesn't exist yet, so create and add it
|
//Series doesn't exist yet, so create and add it
|
||||||
var newSeries = new SeriesEntry { Children = new List<LibraryBookEntry> { lb } };
|
var newSeries = new SeriesEntry(libraryBook.Book.SeriesLink.First(), libraryBook);
|
||||||
newSeries.setSeriesBook(libraryBook.Book.SeriesLink.First());
|
lbe = newSeries.Children[0];
|
||||||
lb.Parent = newSeries;
|
|
||||||
newSeries.Liberate.Expanded = true;
|
newSeries.Liberate.Expanded = true;
|
||||||
bindingList.Insert(0, newSeries);
|
bindingList.Insert(0, newSeries);
|
||||||
series = newSeries;
|
series = newSeries;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lb.Parent = series;
|
lbe = new(libraryBook) { Parent = series };
|
||||||
series.Children.Add(lb);
|
series.Children.Add(lbe);
|
||||||
}
|
}
|
||||||
//Add episode beneath the parent
|
//Add episode beneath the parent
|
||||||
int seriesIndex = bindingList.IndexOf(series);
|
int seriesIndex = bindingList.IndexOf(series);
|
||||||
bindingList.Insert(seriesIndex + 1, lb);
|
bindingList.Insert(seriesIndex + 1, lbe);
|
||||||
|
|
||||||
if (series.Liberate.Expanded)
|
if (series.Liberate.Expanded)
|
||||||
bindingList.ExpandItem(series);
|
bindingList.ExpandItem(series);
|
||||||
@ -159,7 +151,7 @@ namespace LibationWinForms.grid
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
//Add the new product
|
//Add the new product
|
||||||
bindingList.Insert(0, lb);
|
bindingList.Insert(0, new LibraryBookEntry(libraryBook));
|
||||||
}
|
}
|
||||||
// update existing
|
// update existing
|
||||||
else
|
else
|
||||||
@ -168,6 +160,9 @@ namespace LibationWinForms.grid
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Re-filter after updating existing / adding new books to capture any changes
|
||||||
|
Filter(existingFilter);
|
||||||
|
|
||||||
// remove deleted from grid.
|
// remove deleted from grid.
|
||||||
// note: actual deletion from db must still occur via the RemoveBook feature. deleting from audible will not trigger this
|
// note: actual deletion from db must still occur via the RemoveBook feature. deleting from audible will not trigger this
|
||||||
var removedBooks =
|
var removedBooks =
|
||||||
@ -176,26 +171,23 @@ namespace LibationWinForms.grid
|
|||||||
.LibraryBooks()
|
.LibraryBooks()
|
||||||
.ExceptBy(dbBooks.Select(lb => lb.Book.AudibleProductId), ge => ge.AudibleProductId);
|
.ExceptBy(dbBooks.Select(lb => lb.Book.AudibleProductId), ge => ge.AudibleProductId);
|
||||||
|
|
||||||
|
//Remove books in series from their parents' Children list
|
||||||
foreach (var removed in removedBooks.Where(b => b.Parent is not null))
|
foreach (var removed in removedBooks.Where(b => b.Parent is not null))
|
||||||
{
|
{
|
||||||
var series = removed.Parent as SeriesEntry;
|
removed.Parent.Children.Remove(removed);
|
||||||
series.Children.Remove(removed);
|
removed.Parent.NotifyPropertyChanged();
|
||||||
series.NotifyPropertyChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Remove series that have no children
|
//Remove series that have no children
|
||||||
var removedSeries =
|
var removedSeries =
|
||||||
bindingList
|
bindingList
|
||||||
.AllItems()
|
.AllItems()
|
||||||
.Series()
|
.EmptySeries();
|
||||||
.Where(i => i.Children.Count == 0);
|
|
||||||
|
|
||||||
foreach (var removed in removedBooks.Cast<GridEntry>().Concat(removedSeries))
|
foreach (var removed in removedBooks.Cast<GridEntry>().Concat(removedSeries))
|
||||||
//no need to re-filter for removed books
|
//no need to re-filter for removed books
|
||||||
bindingList.Remove(removed);
|
bindingList.Remove(removed);
|
||||||
|
|
||||||
Filter(existingFilter);
|
|
||||||
|
|
||||||
VisibleCountChanged?.Invoke(this, bindingList.LibraryBooks().Count());
|
VisibleCountChanged?.Invoke(this, bindingList.LibraryBooks().Count());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,9 +6,9 @@ using System.Linq;
|
|||||||
|
|
||||||
namespace LibationWinForms
|
namespace LibationWinForms
|
||||||
{
|
{
|
||||||
internal class SeriesEntry : GridEntry
|
public class SeriesEntry : GridEntry
|
||||||
{
|
{
|
||||||
public List<LibraryBookEntry> Children { get; set; }
|
public List<LibraryBookEntry> Children { get; init; }
|
||||||
public override DateTime DateAdded => Children.Max(c => c.DateAdded);
|
public override DateTime DateAdded => Children.Max(c => c.DateAdded);
|
||||||
public override string ProductRating
|
public override string ProductRating
|
||||||
{
|
{
|
||||||
@ -55,7 +55,18 @@ namespace LibationWinForms
|
|||||||
|
|
||||||
private LiberateButtonStatus _liberate = new LiberateButtonStatus { IsSeries = true };
|
private LiberateButtonStatus _liberate = new LiberateButtonStatus { IsSeries = true };
|
||||||
|
|
||||||
public void setSeriesBook(SeriesBook seriesBook)
|
public SeriesEntry(SeriesBook seriesBook, IEnumerable<LibraryBook> children)
|
||||||
|
{
|
||||||
|
Children = children.Select(c=>new LibraryBookEntry(c) { Parent = this }).ToList();
|
||||||
|
SetSeriesBook(seriesBook);
|
||||||
|
}
|
||||||
|
public SeriesEntry(SeriesBook seriesBook, LibraryBook child)
|
||||||
|
{
|
||||||
|
Children = new() { new LibraryBookEntry(child) { Parent = this } };
|
||||||
|
SetSeriesBook(seriesBook);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetSeriesBook(SeriesBook seriesBook)
|
||||||
{
|
{
|
||||||
SeriesBook = seriesBook;
|
SeriesBook = seriesBook;
|
||||||
_memberValues = CreateMemberValueDictionary();
|
_memberValues = CreateMemberValueDictionary();
|
||||||
|
|||||||
@ -1,87 +0,0 @@
|
|||||||
using Dinah.Core.DataBinding;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace LibationWinForms
|
|
||||||
{
|
|
||||||
internal class SortableBindingList1<T> : BindingList<T> where T : class, IMemberComparable, IHierarchical<T>
|
|
||||||
{
|
|
||||||
private bool isSorted;
|
|
||||||
private ListSortDirection listSortDirection;
|
|
||||||
private PropertyDescriptor propertyDescriptor;
|
|
||||||
|
|
||||||
public SortableBindingList1() : base(new List<T>()) { }
|
|
||||||
public SortableBindingList1(IEnumerable<T> enumeration) : base(new List<T>(enumeration)) { }
|
|
||||||
|
|
||||||
protected bool SuspendSorting { get; set; }
|
|
||||||
protected MemberComparer<T> Comparer { get; } = new();
|
|
||||||
protected override bool SupportsSortingCore => true;
|
|
||||||
protected override bool SupportsSearchingCore => true;
|
|
||||||
protected override bool IsSortedCore => isSorted;
|
|
||||||
protected override PropertyDescriptor SortPropertyCore => propertyDescriptor;
|
|
||||||
protected override ListSortDirection SortDirectionCore => listSortDirection;
|
|
||||||
|
|
||||||
protected override void ApplySortCore(PropertyDescriptor property, ListSortDirection direction)
|
|
||||||
{
|
|
||||||
Comparer.PropertyName = property.Name;
|
|
||||||
Comparer.Direction = direction;
|
|
||||||
|
|
||||||
Sort();
|
|
||||||
|
|
||||||
propertyDescriptor = property;
|
|
||||||
listSortDirection = direction;
|
|
||||||
isSorted = true;
|
|
||||||
|
|
||||||
OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void Sort()
|
|
||||||
{
|
|
||||||
List<T> itemsList = (List<T>)Items;
|
|
||||||
|
|
||||||
var sortedItems = Items.OrderBy(ge => ge, Comparer).ToList();
|
|
||||||
|
|
||||||
var children = sortedItems.Where(i => i.Parent is not null).ToList();
|
|
||||||
|
|
||||||
itemsList.Clear();
|
|
||||||
|
|
||||||
//Only add parentless items at this stage. After these items are added in the
|
|
||||||
//correct sorting order, go back and add the children beneath their parents.
|
|
||||||
itemsList.AddRange(sortedItems.Except(children));
|
|
||||||
|
|
||||||
foreach (var parent in children.Select(c => c.Parent).Distinct())
|
|
||||||
{
|
|
||||||
var pIndex = itemsList.IndexOf(parent);
|
|
||||||
foreach (var c in children.Where(c=> c.Parent == parent))
|
|
||||||
itemsList.Insert(++pIndex, c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnListChanged(ListChangedEventArgs e)
|
|
||||||
{
|
|
||||||
if (isSorted && !SuspendSorting &&
|
|
||||||
((e.ListChangedType == ListChangedType.ItemChanged && e.PropertyDescriptor == SortPropertyCore) ||
|
|
||||||
e.ListChangedType == ListChangedType.ItemAdded))
|
|
||||||
{
|
|
||||||
var item = Items[e.NewIndex];
|
|
||||||
Sort();
|
|
||||||
var newIndex = Items.IndexOf(item);
|
|
||||||
|
|
||||||
base.OnListChanged(new ListChangedEventArgs(ListChangedType.ItemMoved, newIndex, e.NewIndex));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
base.OnListChanged(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void RemoveSortCore()
|
|
||||||
{
|
|
||||||
isSorted = false;
|
|
||||||
propertyDescriptor = base.SortPropertyCore;
|
|
||||||
listSortDirection = base.SortDirectionCore;
|
|
||||||
|
|
||||||
OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user