diff --git a/Source/LibationAvalonia/Views/MainWindow.ProcessQueue.cs b/Source/LibationAvalonia/Views/MainWindow.ProcessQueue.cs index 77e8b626..b63a183b 100644 --- a/Source/LibationAvalonia/Views/MainWindow.ProcessQueue.cs +++ b/Source/LibationAvalonia/Views/MainWindow.ProcessQueue.cs @@ -1,7 +1,9 @@ using DataLayer; using Dinah.Core; using LibationFileManager; +using LibationUiBase.GridView; using System; +using System.Collections.Generic; using System.Linq; namespace LibationAvalonia.Views @@ -48,6 +50,22 @@ namespace LibationAvalonia.Views } } + public void ProductsDisplay_LiberateSeriesClicked(object sender, ISeriesEntry series) + { + try + { + SetQueueCollapseState(false); + + Serilog.Log.Logger.Information("Begin backing up all {series} episodes", series.LibraryBook); + + _viewModel.ProcessQueue.AddDownloadDecrypt(series.Children.Select(c => c.LibraryBook).UnLiberated()); + } + catch (Exception ex) + { + Serilog.Log.Logger.Error(ex, "An error occurred while backing up {series} episodes", series.LibraryBook); + } + } + public void ProductsDisplay_ConvertToMp3Clicked(object sender, LibraryBook libraryBook) { try diff --git a/Source/LibationAvalonia/Views/MainWindow.axaml b/Source/LibationAvalonia/Views/MainWindow.axaml index f6490cd1..d2feee33 100644 --- a/Source/LibationAvalonia/Views/MainWindow.axaml +++ b/Source/LibationAvalonia/Views/MainWindow.axaml @@ -195,6 +195,7 @@ Name="productsDisplay" DataContext="{Binding ProductsDisplay}" LiberateClicked="ProductsDisplay_LiberateClicked" + LiberateSeriesClicked="ProductsDisplay_LiberateSeriesClicked" ConvertToMp3Clicked="ProductsDisplay_ConvertToMp3Clicked" /> diff --git a/Source/LibationAvalonia/Views/ProductsDisplay.axaml.cs b/Source/LibationAvalonia/Views/ProductsDisplay.axaml.cs index 1461e6d7..1d107bf2 100644 --- a/Source/LibationAvalonia/Views/ProductsDisplay.axaml.cs +++ b/Source/LibationAvalonia/Views/ProductsDisplay.axaml.cs @@ -20,6 +20,7 @@ namespace LibationAvalonia.Views public partial class ProductsDisplay : UserControl { public event EventHandler LiberateClicked; + public event EventHandler LiberateSeriesClicked; public event EventHandler ConvertToMp3Clicked; private ProductsDisplayViewModel _viewModel => DataContext as ProductsDisplayViewModel; @@ -90,74 +91,131 @@ namespace LibationAvalonia.Views { var entry = args.GridEntry; + #region Liberate all Episodes + if (entry.Liberate.IsSeries) - return; + { + var liberateEpisodesMenuItem = new MenuItem() + { + Header = "_Liberate All Episodes", + IsEnabled = ((ISeriesEntry)entry).Children.Any(c => c.Liberate.BookStatus is LiberatedStatus.NotLiberated or LiberatedStatus.PartialDownload) + }; + + args.ContextMenuItems.Add(liberateEpisodesMenuItem); + + liberateEpisodesMenuItem.Click += (_, _) => LiberateSeriesClicked?.Invoke(this, ((ISeriesEntry)entry)); + } + + #endregion + #region Set Download status to Downloaded var setDownloadMenuItem = new MenuItem() { Header = "Set Download status to '_Downloaded'", - IsEnabled = entry.Book.UserDefinedItem.BookStatus != LiberatedStatus.Liberated + IsEnabled = entry.Book.UserDefinedItem.BookStatus != LiberatedStatus.Liberated || entry.Liberate.IsSeries }; - setDownloadMenuItem.Click += (_, __) => entry.Book.UpdateBookStatus(LiberatedStatus.Liberated); + + args.ContextMenuItems.Add(setDownloadMenuItem); + + if (entry.Liberate.IsSeries) + setDownloadMenuItem.Click += (_, __) => ((ISeriesEntry)entry).Children.Select(c => c.LibraryBook).UpdateBookStatus(LiberatedStatus.Liberated); + else + setDownloadMenuItem.Click += (_, __) => entry.Book.UpdateBookStatus(LiberatedStatus.Liberated); + + #endregion + #region Set Download status to Not Downloaded var setNotDownloadMenuItem = new MenuItem() { Header = "Set Download status to '_Not Downloaded'", - IsEnabled = entry.Book.UserDefinedItem.BookStatus != LiberatedStatus.NotLiberated + IsEnabled = entry.Book.UserDefinedItem.BookStatus != LiberatedStatus.NotLiberated || entry.Liberate.IsSeries }; - setNotDownloadMenuItem.Click += (_, __) => entry.Book.UpdateBookStatus(LiberatedStatus.NotLiberated); + + args.ContextMenuItems.Add(setNotDownloadMenuItem); + + if (entry.Liberate.IsSeries) + setNotDownloadMenuItem.Click += (_, __) => ((ISeriesEntry)entry).Children.Select(c => c.LibraryBook).UpdateBookStatus(LiberatedStatus.NotLiberated); + else + setNotDownloadMenuItem.Click += (_, __) => entry.Book.UpdateBookStatus(LiberatedStatus.NotLiberated); + + #endregion + #region Remove from library var removeMenuItem = new MenuItem() { Header = "_Remove from library" }; - removeMenuItem.Click += async (_, __) => await Task.Run(entry.LibraryBook.RemoveBook); - var locateFileMenuItem = new MenuItem() { Header = "_Locate file..." }; - locateFileMenuItem.Click += async (_, __) => + args.ContextMenuItems.Add(removeMenuItem); + + if (entry.Liberate.IsSeries) + removeMenuItem.Click += async (_, __) => await ((ISeriesEntry)entry).Children.Select(c => c.LibraryBook).RemoveBooksAsync(); + else + removeMenuItem.Click += async (_, __) => await Task.Run(entry.LibraryBook.RemoveBook); + + #endregion + + if (!entry.Liberate.IsSeries) { - try + #region Locate file + var locateFileMenuItem = new MenuItem() { Header = "_Locate file..." }; + + args.ContextMenuItems.Add(locateFileMenuItem); + + locateFileMenuItem.Click += async (_, __) => { - var openFileDialogOptions = new FilePickerOpenOptions + try { - Title = $"Locate the audio file for '{entry.Book.Title}'", - AllowMultiple = false, - SuggestedStartLocation = new Avalonia.Platform.Storage.FileIO.BclStorageFolder(Configuration.Instance.Books.PathWithoutPrefix), - FileTypeFilter = new FilePickerFileType[] + var openFileDialogOptions = new FilePickerOpenOptions { + Title = $"Locate the audio file for '{entry.Book.Title}'", + AllowMultiple = false, + SuggestedStartLocation = new Avalonia.Platform.Storage.FileIO.BclStorageFolder(Configuration.Instance.Books.PathWithoutPrefix), + FileTypeFilter = new FilePickerFileType[] + { new("All files (*.*)") { Patterns = new[] { "*" } }, - } - }; + } + }; - var selectedFiles = await this.GetParentWindow().StorageProvider.OpenFilePickerAsync(openFileDialogOptions); - var selectedFile = selectedFiles.SingleOrDefault(); + var selectedFiles = await this.GetParentWindow().StorageProvider.OpenFilePickerAsync(openFileDialogOptions); + var selectedFile = selectedFiles.SingleOrDefault(); - if (selectedFile?.TryGetUri(out var uri) is true) - FilePathCache.Insert(entry.AudibleProductId, uri.LocalPath); - } - catch (Exception ex) + if (selectedFile?.TryGetUri(out var uri) is true) + FilePathCache.Insert(entry.AudibleProductId, uri.LocalPath); + } + catch (Exception ex) + { + var msg = "Error saving book's location"; + await MessageBox.ShowAdminAlert(null, msg, msg, ex); + } + }; + + #endregion + #region Convert to Mp3 + var convertToMp3MenuItem = new MenuItem { - var msg = "Error saving book's location"; - await MessageBox.ShowAdminAlert(null, msg, msg, ex); - } - }; - var convertToMp3MenuItem = new MenuItem - { - Header = "_Convert to Mp3", - IsEnabled = entry.Book.UserDefinedItem.BookStatus is LiberatedStatus.Liberated - }; - convertToMp3MenuItem.Click += (_, _) => ConvertToMp3Clicked?.Invoke(this, entry.LibraryBook); + Header = "_Convert to Mp3", + IsEnabled = entry.Book.UserDefinedItem.BookStatus is LiberatedStatus.Liberated + }; + args.ContextMenuItems.Add(convertToMp3MenuItem); - var bookRecordMenuItem = new MenuItem { Header = "View _Bookmarks/Clips" }; - bookRecordMenuItem.Click += async (_, _) => await new BookRecordsDialog(entry.LibraryBook).ShowDialog(VisualRoot as Window); + convertToMp3MenuItem.Click += (_, _) => ConvertToMp3Clicked?.Invoke(this, entry.LibraryBook); - args.ContextMenuItems.AddRange(new Control[] + #endregion + } + + args.ContextMenuItems.Add(new Separator()); + + #region View Bookmarks/Clips + + if (!entry.Liberate.IsSeries) { - setDownloadMenuItem, - setNotDownloadMenuItem, - removeMenuItem, - locateFileMenuItem, - convertToMp3MenuItem, - new Separator(), - bookRecordMenuItem - }); + + var bookRecordMenuItem = new MenuItem { Header = "View _Bookmarks/Clips" }; + + args.ContextMenuItems.Add(bookRecordMenuItem); + + bookRecordMenuItem.Click += async (_, _) => await new BookRecordsDialog(entry.LibraryBook).ShowDialog(VisualRoot as Window); + } + + #endregion } else { diff --git a/Source/LibationUiBase/GridView/SeriesEntry[TStatus].cs b/Source/LibationUiBase/GridView/SeriesEntry[TStatus].cs index 37fd472e..f3ed63fc 100644 --- a/Source/LibationUiBase/GridView/SeriesEntry[TStatus].cs +++ b/Source/LibationUiBase/GridView/SeriesEntry[TStatus].cs @@ -62,7 +62,7 @@ namespace LibationUiBase.GridView } protected override string GetBookTags() => null; - protected override int GetLengthInMinutes() => Children.Sum(c => c.LibraryBook.Book.LengthInMinutes); - protected override DateTime GetPurchaseDate() => Children.Min(c => c.LibraryBook.DateAdded); + protected override int GetLengthInMinutes() => Children.Count == 0 ? 0 : Children.Sum(c => c.LibraryBook.Book.LengthInMinutes); + protected override DateTime GetPurchaseDate() => Children.Count == 0 ? default : Children.Min(c => c.LibraryBook.DateAdded); } } diff --git a/Source/LibationWinForms/Form1.Designer.cs b/Source/LibationWinForms/Form1.Designer.cs index ef404581..995bf2ed 100644 --- a/Source/LibationWinForms/Form1.Designer.cs +++ b/Source/LibationWinForms/Form1.Designer.cs @@ -528,6 +528,7 @@ this.productsDisplay.VisibleCountChanged += new System.EventHandler(this.productsDisplay_VisibleCountChanged); this.productsDisplay.RemovableCountChanged += new System.EventHandler(this.productsDisplay_RemovableCountChanged); this.productsDisplay.LiberateClicked += new System.EventHandler(this.ProductsDisplay_LiberateClicked); + this.productsDisplay.LiberateSeriesClicked += new System.EventHandler(this.ProductsDisplay_LiberateSeriesClicked); this.productsDisplay.ConvertToMp3Clicked += new System.EventHandler(this.ProductsDisplay_ConvertToMp3Clicked); this.productsDisplay.InitialLoaded += new System.EventHandler(this.productsDisplay_InitialLoaded); // diff --git a/Source/LibationWinForms/Form1.ProcessQueue.cs b/Source/LibationWinForms/Form1.ProcessQueue.cs index dfd7ac90..cf3b3863 100644 --- a/Source/LibationWinForms/Form1.ProcessQueue.cs +++ b/Source/LibationWinForms/Form1.ProcessQueue.cs @@ -1,8 +1,10 @@ using DataLayer; using Dinah.Core; using LibationFileManager; +using LibationUiBase.GridView; using LibationWinForms.ProcessQueue; using System; +using System.Collections.Generic; using System.Linq; using System.Windows.Forms; @@ -56,6 +58,22 @@ namespace LibationWinForms } } + private void ProductsDisplay_LiberateSeriesClicked(object sender, ISeriesEntry series) + { + try + { + SetQueueCollapseState(false); + + Serilog.Log.Logger.Information("Begin backing up all {series} episodes", series.LibraryBook); + + processBookQueue1.AddDownloadDecrypt(series.Children.Select(c => c.LibraryBook).UnLiberated()); + } + catch (Exception ex) + { + Serilog.Log.Logger.Error(ex, "An error occurred while backing up {series} episodes", series.LibraryBook); + } + } + private void ProductsDisplay_ConvertToMp3Clicked(object sender, LibraryBook libraryBook) { try diff --git a/Source/LibationWinForms/GridView/ProductsDisplay.Designer.cs b/Source/LibationWinForms/GridView/ProductsDisplay.Designer.cs index 1e32af52..879d2f62 100644 --- a/Source/LibationWinForms/GridView/ProductsDisplay.Designer.cs +++ b/Source/LibationWinForms/GridView/ProductsDisplay.Designer.cs @@ -28,35 +28,35 @@ /// private void InitializeComponent() { - this.productsGrid = new LibationWinForms.GridView.ProductsGrid(); - this.SuspendLayout(); + productsGrid = new ProductsGrid(); + SuspendLayout(); // // productsGrid // - this.productsGrid.AutoScroll = true; - this.productsGrid.Dock = System.Windows.Forms.DockStyle.Fill; - this.productsGrid.Location = new System.Drawing.Point(0, 0); - this.productsGrid.Name = "productsGrid"; - this.productsGrid.Size = new System.Drawing.Size(1510, 380); - this.productsGrid.TabIndex = 0; - this.productsGrid.VisibleCountChanged += new System.EventHandler(this.productsGrid_VisibleCountChanged); - this.productsGrid.LiberateClicked += new LibationWinForms.GridView.LibraryBookEntryClickedEventHandler(this.productsGrid_LiberateClicked); - this.productsGrid.ConvertToMp3Clicked += new LibationWinForms.GridView.LibraryBookEntryClickedEventHandler(this.productsGrid_ConvertToMp3Clicked); - 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.RemovableCountChanged += new System.EventHandler(this.productsGrid_RemovableCountChanged); + productsGrid.AutoScroll = true; + productsGrid.Dock = System.Windows.Forms.DockStyle.Fill; + productsGrid.Location = new System.Drawing.Point(0, 0); + productsGrid.Name = "productsGrid"; + productsGrid.Size = new System.Drawing.Size(1510, 380); + productsGrid.TabIndex = 0; + productsGrid.VisibleCountChanged += productsGrid_VisibleCountChanged; + productsGrid.LiberateClicked += productsGrid_LiberateClicked; + productsGrid.ConvertToMp3Clicked += productsGrid_ConvertToMp3Clicked; + productsGrid.CoverClicked += productsGrid_CoverClicked; + productsGrid.DetailsClicked += productsGrid_DetailsClicked; + productsGrid.DescriptionClicked += productsGrid_DescriptionClicked; + productsGrid.RemovableCountChanged += productsGrid_RemovableCountChanged; + productsGrid.LiberateContextMenuStripNeeded += productsGrid_CellContextMenuStripNeeded; // // ProductsDisplay // - this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.Controls.Add(this.productsGrid); - this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); - this.Name = "ProductsDisplay"; - this.Size = new System.Drawing.Size(1510, 380); - this.ResumeLayout(false); - + AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + Controls.Add(productsGrid); + Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + Name = "ProductsDisplay"; + Size = new System.Drawing.Size(1510, 380); + ResumeLayout(false); } #endregion diff --git a/Source/LibationWinForms/GridView/ProductsDisplay.cs b/Source/LibationWinForms/GridView/ProductsDisplay.cs index a0bbf00a..c4659d81 100644 --- a/Source/LibationWinForms/GridView/ProductsDisplay.cs +++ b/Source/LibationWinForms/GridView/ProductsDisplay.cs @@ -20,6 +20,7 @@ namespace LibationWinForms.GridView public event EventHandler VisibleCountChanged; public event EventHandler RemovableCountChanged; public event EventHandler LiberateClicked; + public event EventHandler LiberateSeriesClicked; public event EventHandler ConvertToMp3Clicked; public event EventHandler InitialLoaded; @@ -96,6 +97,132 @@ namespace LibationWinForms.GridView #endregion + #region Cell Context Menu + + private void productsGrid_CellContextMenuStripNeeded(IGridEntry entry, ContextMenuStrip ctxMenu) + { + #region Liberate all Episodes + + if (entry.Liberate.IsSeries) + { + var liberateEpisodesMenuItem = new ToolStripMenuItem() + { + Text = "&Liberate All Episodes", + Enabled = ((ISeriesEntry)entry).Children.Any(c => c.Liberate.BookStatus is LiberatedStatus.NotLiberated or LiberatedStatus.PartialDownload) + }; + + ctxMenu.Items.Add(liberateEpisodesMenuItem); + + liberateEpisodesMenuItem.Click += (_, _) => LiberateSeriesClicked?.Invoke(this, (ISeriesEntry)entry); + } + + #endregion + #region Set Download status to Downloaded + + var setDownloadMenuItem = new ToolStripMenuItem() + { + Text = "Set Download status to '&Downloaded'", + Enabled = entry.Book.UserDefinedItem.BookStatus != LiberatedStatus.Liberated || entry.Liberate.IsSeries + }; + + ctxMenu.Items.Add(setDownloadMenuItem); + + if (entry.Liberate.IsSeries) + setDownloadMenuItem.Click += (_, _) => ((ISeriesEntry)entry).Children.Select(c => c.LibraryBook).UpdateBookStatus(LiberatedStatus.Liberated); + else + setDownloadMenuItem.Click += (_, _) => entry.Book.UpdateBookStatus(LiberatedStatus.Liberated); + + #endregion + #region Set Download status to Not Downloaded + + var setNotDownloadMenuItem = new ToolStripMenuItem() + { + Text = "Set Download status to '&Not Downloaded'", + Enabled = entry.Book.UserDefinedItem.BookStatus != LiberatedStatus.NotLiberated || entry.Liberate.IsSeries + }; + + ctxMenu.Items.Add(setNotDownloadMenuItem); + + if (entry.Liberate.IsSeries) + setNotDownloadMenuItem.Click += (_, _) => ((ISeriesEntry)entry).Children.Select(c => c.LibraryBook).UpdateBookStatus(LiberatedStatus.NotLiberated); + else + setNotDownloadMenuItem.Click += (_, _) => entry.Book.UpdateBookStatus(LiberatedStatus.NotLiberated); + + #endregion + #region Remove from library + + var removeMenuItem = new ToolStripMenuItem() { Text = "&Remove from library" }; + + ctxMenu.Items.Add(removeMenuItem); + + if (entry.Liberate.IsSeries) + removeMenuItem.Click += async (_, _) => await ((ISeriesEntry)entry).Children.Select(c => c.LibraryBook).RemoveBooksAsync(); + else + removeMenuItem.Click += async (_, _) => await Task.Run(entry.LibraryBook.RemoveBook); + + #endregion + + if (!entry.Liberate.IsSeries) + { + #region Locate file + var locateFileMenuItem = new ToolStripMenuItem() { Text = "&Locate file..." }; + + ctxMenu.Items.Add(locateFileMenuItem); + + locateFileMenuItem.Click += (_, _) => + { + try + { + var openFileDialog = new OpenFileDialog + { + Title = $"Locate the audio file for '{entry.Book.Title}'", + Filter = "All files (*.*)|*.*", + FilterIndex = 1 + }; + if (openFileDialog.ShowDialog() == DialogResult.OK) + FilePathCache.Insert(entry.AudibleProductId, openFileDialog.FileName); + } + catch (Exception ex) + { + var msg = "Error saving book's location"; + MessageBoxLib.ShowAdminAlert(this, msg, msg, ex); + } + }; + + #endregion + #region Convert to Mp3 + + var convertToMp3MenuItem = new ToolStripMenuItem + { + Text = "&Convert to Mp3", + Enabled = entry.Book.UserDefinedItem.BookStatus is LiberatedStatus.Liberated + }; + + ctxMenu.Items.Add(convertToMp3MenuItem); + + convertToMp3MenuItem.Click += (_, e) => ConvertToMp3Clicked?.Invoke(this, entry.LibraryBook); + + #endregion + } + + ctxMenu.Items.Add(new ToolStripSeparator()); + + #region View Bookmarks/Clips + + if (!entry.Liberate.IsSeries) + { + var bookRecordMenuItem = new ToolStripMenuItem { Text = "View &Bookmarks/Clips" }; + + ctxMenu.Items.Add(bookRecordMenuItem); + + bookRecordMenuItem.Click += (_, _) => new BookRecordsDialog(entry.LibraryBook).ShowDialog(this); + } + + #endregion + } + + #endregion + #region Scan and Remove Books public void CloseRemoveBooksColumn() diff --git a/Source/LibationWinForms/GridView/ProductsGrid.Designer.cs b/Source/LibationWinForms/GridView/ProductsGrid.Designer.cs index 51b5d09b..3bc46638 100644 --- a/Source/LibationWinForms/GridView/ProductsGrid.Designer.cs +++ b/Source/LibationWinForms/GridView/ProductsGrid.Designer.cs @@ -99,7 +99,6 @@ namespace LibationWinForms.GridView 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.CellContextMenuStripNeeded += new System.Windows.Forms.DataGridViewCellContextMenuStripNeededEventHandler(this.gridEntryDataGridView_CellContextMenuStripNeeded); this.gridEntryDataGridView.CellToolTipTextNeeded += new System.Windows.Forms.DataGridViewCellToolTipTextNeededEventHandler(this.gridEntryDataGridView_CellToolTipTextNeeded); // // removeGVColumn diff --git a/Source/LibationWinForms/GridView/ProductsGrid.cs b/Source/LibationWinForms/GridView/ProductsGrid.cs index b7b8815f..0c09e8fc 100644 --- a/Source/LibationWinForms/GridView/ProductsGrid.cs +++ b/Source/LibationWinForms/GridView/ProductsGrid.cs @@ -1,15 +1,12 @@ -using ApplicationServices; -using DataLayer; +using DataLayer; using Dinah.Core.WindowsDesktop.Forms; using LibationFileManager; using LibationUiBase.GridView; -using LibationWinForms.Dialogs; using System; using System.Collections.Generic; using System.Data; using System.Drawing; using System.Linq; -using System.Threading.Tasks; using System.Windows.Forms; namespace LibationWinForms.GridView @@ -17,6 +14,7 @@ namespace LibationWinForms.GridView public delegate void GridEntryClickedEventHandler(IGridEntry liveGridEntry); public delegate void LibraryBookEntryClickedEventHandler(ILibraryBookEntry liveGridEntry); public delegate void GridEntryRectangleClickedEventHandler(IGridEntry liveGridEntry, Rectangle cellRectangle); + public delegate void ProductsGridCellContextMenuStripNeededEventHandler(IGridEntry liveGridEntry, ContextMenuStrip ctxMenu); public partial class ProductsGrid : UserControl { @@ -29,6 +27,7 @@ namespace LibationWinForms.GridView public event GridEntryRectangleClickedEventHandler DescriptionClicked; public new event EventHandler Scroll; public event EventHandler RemovableCountChanged; + public event ProductsGridCellContextMenuStripNeededEventHandler LiberateContextMenuStripNeeded; private GridEntryBindingList bindingList; internal IEnumerable GetVisibleBooks() @@ -43,9 +42,43 @@ namespace LibationWinForms.GridView InitializeComponent(); EnableDoubleBuffering(); gridEntryDataGridView.Scroll += (_, s) => Scroll?.Invoke(this, s); + gridEntryDataGridView.CellContextMenuStripNeeded += GridEntryDataGridView_CellContextMenuStripNeeded; removeGVColumn.Frozen = false; } + private void GridEntryDataGridView_CellContextMenuStripNeeded(object sender, DataGridViewCellContextMenuStripNeededEventArgs e) + { + // header + if (e.RowIndex < 0) + return; + + // cover + else if (e.ColumnIndex == coverGVColumn.Index) + return; + + e.ContextMenuStrip = new ContextMenuStrip(); + // any non-stop light + if (e.ColumnIndex != liberateGVColumn.Index) + { + e.ContextMenuStrip.Items.Add("Copy", null, (_, __) => + { + try + { + var dgv = (DataGridView)sender; + var text = dgv[e.ColumnIndex, e.RowIndex].FormattedValue.ToString(); + Clipboard.SetDataObject(text, false, 5, 150); + } + catch { } + }); + } + else + { + var entry = getGridEntry(e.RowIndex); + var name = gridEntryDataGridView.Columns[e.ColumnIndex].DataPropertyName; + LiberateContextMenuStripNeeded?.Invoke(entry, e.ContextMenuStrip); + } + } + private void EnableDoubleBuffering() { var propertyInfo = gridEntryDataGridView.GetType().GetProperty("DoubleBuffered", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); @@ -103,101 +136,6 @@ namespace LibationWinForms.GridView } } - private void gridEntryDataGridView_CellContextMenuStripNeeded(object sender, DataGridViewCellContextMenuStripNeededEventArgs e) - { - // header - if (e.RowIndex < 0) - return; - - // cover - if (e.ColumnIndex == coverGVColumn.Index) - return; - - // any non-stop light - if (e.ColumnIndex != liberateGVColumn.Index) - { - var copyContextMenu = new ContextMenuStrip(); - copyContextMenu.Items.Add("Copy", null, (_, __) => - { - try - { - var dgv = (DataGridView)sender; - var text = dgv[e.ColumnIndex, e.RowIndex].FormattedValue.ToString(); - Clipboard.SetDataObject(text, false, 5, 150); - } - catch { } - }); - - e.ContextMenuStrip = copyContextMenu; - return; - } - - // else: stop light - - var entry = getGridEntry(e.RowIndex); - if (entry.Liberate.IsSeries) - return; - - var setDownloadMenuItem = new ToolStripMenuItem() - { - Text = "Set Download status to '&Downloaded'", - Enabled = entry.Book.UserDefinedItem.BookStatus != LiberatedStatus.Liberated - }; - setDownloadMenuItem.Click += (_, __) => entry.Book.UpdateBookStatus(LiberatedStatus.Liberated); - - var setNotDownloadMenuItem = new ToolStripMenuItem() - { - Text = "Set Download status to '&Not Downloaded'", - Enabled = entry.Book.UserDefinedItem.BookStatus != LiberatedStatus.NotLiberated - }; - setNotDownloadMenuItem.Click += (_, __) => entry.Book.UpdateBookStatus(LiberatedStatus.NotLiberated); - - var removeMenuItem = new ToolStripMenuItem() { Text = "&Remove from library" }; - removeMenuItem.Click += async (_, __) => await Task.Run(entry.LibraryBook.RemoveBook); - - var locateFileMenuItem = new ToolStripMenuItem() { Text = "&Locate file..." }; - locateFileMenuItem.Click += (_, __) => - { - try - { - var openFileDialog = new OpenFileDialog - { - Title = $"Locate the audio file for '{entry.Book.Title}'", - Filter = "All files (*.*)|*.*", - FilterIndex = 1 - }; - if (openFileDialog.ShowDialog() == DialogResult.OK) - FilePathCache.Insert(entry.AudibleProductId, openFileDialog.FileName); - } - catch (Exception ex) - { - var msg = "Error saving book's location"; - MessageBoxLib.ShowAdminAlert(this, msg, msg, ex); - } - }; - - var convertToMp3MenuItem = new ToolStripMenuItem - { - Text = "&Convert to Mp3", - Enabled = entry.Book.UserDefinedItem.BookStatus is LiberatedStatus.Liberated - }; - convertToMp3MenuItem.Click += (_, e) => ConvertToMp3Clicked?.Invoke(entry as ILibraryBookEntry); - - var bookRecordMenuItem = new ToolStripMenuItem { Text = "View &Bookmarks/Clips" }; - bookRecordMenuItem.Click += (_, _) => new BookRecordsDialog(entry.LibraryBook).ShowDialog(this); - - var stopLightContextMenu = new ContextMenuStrip(); - stopLightContextMenu.Items.Add(setDownloadMenuItem); - stopLightContextMenu.Items.Add(setNotDownloadMenuItem); - stopLightContextMenu.Items.Add(removeMenuItem); - stopLightContextMenu.Items.Add(locateFileMenuItem); - stopLightContextMenu.Items.Add(convertToMp3MenuItem); - stopLightContextMenu.Items.Add(new ToolStripSeparator()); - stopLightContextMenu.Items.Add(bookRecordMenuItem); - - e.ContextMenuStrip = stopLightContextMenu; - } - private IGridEntry getGridEntry(int rowIndex) => gridEntryDataGridView.GetBoundItem(rowIndex); #endregion