diff --git a/LibationWinForms/Dialogs/RemoveBooksDialog.Designer.cs b/LibationWinForms/Dialogs/RemoveBooksDialog.Designer.cs new file mode 100644 index 00000000..d4484ce3 --- /dev/null +++ b/LibationWinForms/Dialogs/RemoveBooksDialog.Designer.cs @@ -0,0 +1,188 @@ + +namespace LibationWinForms.Dialogs +{ + partial class RemoveBooksDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle(); + this.dataGridView1 = new System.Windows.Forms.DataGridView(); + this.gridEntryBindingSource = new System.Windows.Forms.BindingSource(this.components); + this.btnRemoveBooks = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.removeDataGridViewCheckBoxColumn = new System.Windows.Forms.DataGridViewCheckBoxColumn(); + this.coverDataGridViewImageColumn = new System.Windows.Forms.DataGridViewImageColumn(); + this.titleDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.authorsDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.miscDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.DatePurchased = new System.Windows.Forms.DataGridViewTextBoxColumn(); + ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridEntryBindingSource)).BeginInit(); + this.SuspendLayout(); + // + // dataGridView1 + // + this.dataGridView1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.dataGridView1.AutoGenerateColumns = false; + this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this.dataGridView1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { + this.removeDataGridViewCheckBoxColumn, + this.coverDataGridViewImageColumn, + this.titleDataGridViewTextBoxColumn, + this.authorsDataGridViewTextBoxColumn, + this.miscDataGridViewTextBoxColumn, + this.DatePurchased}); + this.dataGridView1.DataSource = this.gridEntryBindingSource; + 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.dataGridView1.DefaultCellStyle = dataGridViewCellStyle1; + this.dataGridView1.Location = new System.Drawing.Point(0, 0); + this.dataGridView1.Name = "dataGridView1"; + this.dataGridView1.RowHeadersVisible = false; + this.dataGridView1.RowTemplate.Height = 82; + this.dataGridView1.Size = new System.Drawing.Size(800, 409); + this.dataGridView1.TabIndex = 0; + // + // gridEntryBindingSource + // + this.gridEntryBindingSource.AllowNew = false; + this.gridEntryBindingSource.DataSource = typeof(LibationWinForms.Dialogs.RemovableGridEntry); + // + // btnRemoveBooks + // + this.btnRemoveBooks.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.btnRemoveBooks.Location = new System.Drawing.Point(570, 419); + this.btnRemoveBooks.Name = "btnRemoveBooks"; + this.btnRemoveBooks.Size = new System.Drawing.Size(218, 23); + this.btnRemoveBooks.TabIndex = 1; + this.btnRemoveBooks.Text = "Remove Selected Books from Libation"; + this.btnRemoveBooks.UseVisualStyleBackColor = true; + this.btnRemoveBooks.Click += new System.EventHandler(this.btnRemoveBooks_Click); + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(12, 423); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(169, 15); + this.label1.TabIndex = 2; + this.label1.Text = "{0} books selected for removal."; + // + // removeDataGridViewCheckBoxColumn + // + this.removeDataGridViewCheckBoxColumn.DataPropertyName = "Remove"; + this.removeDataGridViewCheckBoxColumn.FalseValue = "False"; + this.removeDataGridViewCheckBoxColumn.Frozen = true; + this.removeDataGridViewCheckBoxColumn.HeaderText = "Remove"; + this.removeDataGridViewCheckBoxColumn.MinimumWidth = 60; + this.removeDataGridViewCheckBoxColumn.Name = "removeDataGridViewCheckBoxColumn"; + this.removeDataGridViewCheckBoxColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Automatic; + this.removeDataGridViewCheckBoxColumn.TrueValue = "True"; + this.removeDataGridViewCheckBoxColumn.Width = 60; + // + // coverDataGridViewImageColumn + // + this.coverDataGridViewImageColumn.DataPropertyName = "Cover"; + this.coverDataGridViewImageColumn.HeaderText = "Cover"; + this.coverDataGridViewImageColumn.MinimumWidth = 80; + this.coverDataGridViewImageColumn.Name = "coverDataGridViewImageColumn"; + this.coverDataGridViewImageColumn.ReadOnly = true; + this.coverDataGridViewImageColumn.Resizable = System.Windows.Forms.DataGridViewTriState.False; + this.coverDataGridViewImageColumn.Width = 80; + // + // titleDataGridViewTextBoxColumn + // + this.titleDataGridViewTextBoxColumn.DataPropertyName = "Title"; + this.titleDataGridViewTextBoxColumn.HeaderText = "Title"; + this.titleDataGridViewTextBoxColumn.Name = "titleDataGridViewTextBoxColumn"; + this.titleDataGridViewTextBoxColumn.ReadOnly = true; + this.titleDataGridViewTextBoxColumn.Width = 200; + // + // authorsDataGridViewTextBoxColumn + // + this.authorsDataGridViewTextBoxColumn.DataPropertyName = "Authors"; + this.authorsDataGridViewTextBoxColumn.HeaderText = "Authors"; + this.authorsDataGridViewTextBoxColumn.Name = "authorsDataGridViewTextBoxColumn"; + this.authorsDataGridViewTextBoxColumn.ReadOnly = true; + // + // miscDataGridViewTextBoxColumn + // + this.miscDataGridViewTextBoxColumn.DataPropertyName = "Misc"; + this.miscDataGridViewTextBoxColumn.HeaderText = "Misc"; + this.miscDataGridViewTextBoxColumn.Name = "miscDataGridViewTextBoxColumn"; + this.miscDataGridViewTextBoxColumn.ReadOnly = true; + this.miscDataGridViewTextBoxColumn.Width = 150; + // + // DatePurchased + // + this.DatePurchased.DataPropertyName = "DatePurchased"; + this.DatePurchased.HeaderText = "Date Purchased"; + this.DatePurchased.Name = "DatePurchased"; + this.DatePurchased.ReadOnly = true; + this.DatePurchased.Width = 120; + // + // RemoveBooksDialog + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(800, 450); + this.Controls.Add(this.label1); + this.Controls.Add(this.btnRemoveBooks); + this.Controls.Add(this.dataGridView1); + this.Name = "RemoveBooksDialog"; + this.Text = "RemoveBooksDialog"; + this.Shown += new System.EventHandler(this.RemoveBooksDialog_Shown); + ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridEntryBindingSource)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.DataGridView dataGridView1; + private System.Windows.Forms.BindingSource gridEntryBindingSource; + private System.Windows.Forms.Button btnRemoveBooks; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.DataGridViewCheckBoxColumn removeDataGridViewCheckBoxColumn; + private System.Windows.Forms.DataGridViewImageColumn coverDataGridViewImageColumn; + private System.Windows.Forms.DataGridViewTextBoxColumn titleDataGridViewTextBoxColumn; + private System.Windows.Forms.DataGridViewTextBoxColumn authorsDataGridViewTextBoxColumn; + private System.Windows.Forms.DataGridViewTextBoxColumn miscDataGridViewTextBoxColumn; + private System.Windows.Forms.DataGridViewTextBoxColumn DatePurchased; + } +} \ No newline at end of file diff --git a/LibationWinForms/Dialogs/RemoveBooksDialog.cs b/LibationWinForms/Dialogs/RemoveBooksDialog.cs new file mode 100644 index 00000000..273176cb --- /dev/null +++ b/LibationWinForms/Dialogs/RemoveBooksDialog.cs @@ -0,0 +1,217 @@ +using ApplicationServices; +using DataLayer; +using InternalUtilities; +using LibationWinForms.Login; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Windows.Forms; +using Dinah.Core.DataBinding; +using System.Runtime.CompilerServices; +using Dinah.Core.Drawing; +using System.Collections; + +namespace LibationWinForms.Dialogs +{ + public partial class RemoveBooksDialog : Form + { + public bool BooksRemoved { get; private set; } + + private Account[] _accounts { get; } + private List _libraryBooks; + private SortableBindingList _removableGridEntries; + private string _labelFormat; + private int SelectedCount => SelectedEntries?.Count() ?? 0; + private IEnumerable SelectedEntries => _removableGridEntries?.Where(b => b.Remove); + + public RemoveBooksDialog(params Account[] accounts) + { + _libraryBooks = DbContexts.GetContext().GetLibrary_Flat_NoTracking(); + _accounts = accounts; + InitializeComponent(); + _labelFormat = label1.Text; + + dataGridView1.CellContentClick += (s, e) => dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit); + dataGridView1.CellValueChanged += DataGridView1_CellValueChanged; + dataGridView1.BindingContextChanged += (s, e) => UpdateSelection(); + + var orderedGridEntries = _libraryBooks + .Select(lb => new RemovableGridEntry(new GridEntry(lb))) + .OrderByDescending(ge => ge.GridEntry.Purchase_Date) + .ToList(); + + _removableGridEntries = orderedGridEntries.ToSortableBindingList(); + gridEntryBindingSource.DataSource = _removableGridEntries; + + dataGridView1.Enabled = false; + } + + private void DataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e) + { + if (e.ColumnIndex == 0) + { + UpdateSelection(); + } + } + + private async void RemoveBooksDialog_Shown(object sender, EventArgs e) + { + if (_accounts == null || _accounts.Length == 0) + return; + try + { + var rmovedBooks = await LibraryCommands.FindInactiveBooks((account) => new WinformResponder(account), _libraryBooks, _accounts); + + var removable = _removableGridEntries.Where(rge => rmovedBooks.Count(rb => rb.Book.AudibleProductId == rge.GridEntry.AudibleProductId) == 1); + + if (removable.Count() == 0) + return; + + foreach (var r in removable) + r.Remove = true; + + UpdateSelection(); + } + catch (Exception ex) + { + MessageBoxAlertAdmin.Show( + "Error scanning library. You may still manually select books to remove from Libation's library.", + "Error scanning library", + ex); + } + finally + { + dataGridView1.Enabled = true; + } + } + + private void btnRemoveBooks_Click(object sender, EventArgs e) + { + var selected = SelectedEntries.ToList(); + + if (selected.Count == 0) return; + + string titles = string.Join("\r\n", selected.Select(rge => "-" + rge.Title)); + + var result = MessageBox.Show( + this, + $"Are you sure you want to remove the following {selected.Count} books from Libation's library?\r\n\r\n{titles}", + "Remove books from Libation?", + MessageBoxButtons.YesNo, + MessageBoxIcon.Question, + MessageBoxDefaultButton.Button1); + + if (result == DialogResult.Yes) + { + using var context = DbContexts.GetContext(); + + var libBooks = context.GetLibrary_Flat_NoTracking(); + + var removeLibraryBooks = libBooks.Where(lb => selected.Count(rge => rge.GridEntry.AudibleProductId == lb.Book.AudibleProductId) == 1).ToArray(); + context.Library.RemoveRange(removeLibraryBooks); + context.SaveChanges(); + BooksRemoved = true; + + foreach (var rEntry in selected) + _removableGridEntries.Remove(rEntry); + + UpdateSelection(); + } + } + private void UpdateSelection() + { + dataGridView1.Sort(dataGridView1.Columns[0], ListSortDirection.Descending); + var selectedCount = SelectedCount; + label1.Text = string.Format(_labelFormat, selectedCount); + btnRemoveBooks.Enabled = selectedCount > 0; + } + } + class CompareBool : IComparer + { + public int Compare(object x, object y) + { + var rge1 = x as RemovableGridEntry; + var rge2 = y as RemovableGridEntry; + + return rge1.Remove.CompareTo(rge2.Remove); + } + } + + + internal class RemovableGridEntry : INotifyPropertyChanged + { + public event PropertyChangedEventHandler PropertyChanged; + public GridEntry GridEntry { get; } + + public bool Remove + { + get + { + return _remove; + } + set + { + if (_remove != value) + { + _remove = value; + NotifyPropertyChanged(); + } + } + } + public Image Cover + { + get + { + return _cover; + } + set + { + _cover = value; + NotifyPropertyChanged(); + } + } + public string Title => GetDisplayValue(nameof(GridEntry.Title), GridEntry.Title); + public string Authors => GetDisplayValue(nameof(GridEntry.Authors), GridEntry.Authors); + public string Misc => GetDisplayValue(nameof(GridEntry.Misc), GridEntry.Misc); + public string DatePurchased => GetDisplayValue(nameof(GridEntry.Purchase_Date), GridEntry.Purchase_Date); + + private bool _remove = false; + private Image _cover; + + public RemovableGridEntry(GridEntry gridEntry) + { + GridEntry = gridEntry; + + var picDef = new FileManager.PictureDefinition(GridEntry.GetBook().PictureId, FileManager.PictureSize._80x80); + (bool isDefault, byte[] picture) = FileManager.PictureStorage.GetPicture(picDef); + + if (isDefault) + FileManager.PictureStorage.PictureCached += PictureStorage_PictureCached; + + _cover = ImageReader.ToImage(picture); + } + + private void PictureStorage_PictureCached(object sender, string pictureId) + { + if (pictureId == GridEntry.GetBook().PictureId) + { + Cover = WindowsDesktopUtilities.WinAudibleImageServer.GetImage(pictureId, FileManager.PictureSize._80x80); + FileManager.PictureStorage.PictureCached -= PictureStorage_PictureCached; + } + } + + private string GetDisplayValue(string propertyName, string defaultValue) + { + if (GridEntry.TryDisplayValue(propertyName, out string value)) + return value; + return defaultValue; + } + + private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") => + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + + } +} diff --git a/LibationWinForms/Dialogs/RemoveBooksDialog.resx b/LibationWinForms/Dialogs/RemoveBooksDialog.resx new file mode 100644 index 00000000..303f91a6 --- /dev/null +++ b/LibationWinForms/Dialogs/RemoveBooksDialog.resx @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + + 17, 17 + + \ No newline at end of file diff --git a/LibationWinForms/Properties/DataSources/LibationWinForm.RemovableGridEntry.datasource b/LibationWinForms/Properties/DataSources/LibationWinForm.RemovableGridEntry.datasource new file mode 100644 index 00000000..da01a0bf --- /dev/null +++ b/LibationWinForms/Properties/DataSources/LibationWinForm.RemovableGridEntry.datasource @@ -0,0 +1,10 @@ + + + + LibationWinForms.Dialogs.RemovableGridEntry, LibationWinForms, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + \ No newline at end of file