diff --git a/Source/FileManager/BackgroundFileSystem.cs b/Source/FileManager/BackgroundFileSystem.cs
index 4dbf1f93..f44c2274 100644
--- a/Source/FileManager/BackgroundFileSystem.cs
+++ b/Source/FileManager/BackgroundFileSystem.cs
@@ -134,6 +134,7 @@ namespace FileManager
private void AddPath(string path)
{
+ if (!File.Exists(path)) return;
if (File.GetAttributes(path).HasFlag(FileAttributes.Directory))
AddUniqueFiles(FileUtility.SaferEnumerateFiles(path, SearchPattern, SearchOption));
else
diff --git a/Source/LibationWinForms/grid/ImageDisplay.Designer.cs b/Source/LibationWinForms/grid/ImageDisplay.Designer.cs
new file mode 100644
index 00000000..ec1dbdf0
--- /dev/null
+++ b/Source/LibationWinForms/grid/ImageDisplay.Designer.cs
@@ -0,0 +1,86 @@
+namespace LibationWinForms
+{
+ partial class ImageDisplay
+ {
+ ///
+ /// 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();
+ this.pictureBox1 = new System.Windows.Forms.PictureBox();
+ this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this.savePictureToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
+ this.contextMenuStrip1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // pictureBox1
+ //
+ this.pictureBox1.ContextMenuStrip = this.contextMenuStrip1;
+ this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.pictureBox1.Location = new System.Drawing.Point(0, 0);
+ this.pictureBox1.Name = "pictureBox1";
+ this.pictureBox1.Size = new System.Drawing.Size(522, 450);
+ this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+ this.pictureBox1.TabIndex = 0;
+ this.pictureBox1.TabStop = false;
+ //
+ // contextMenuStrip1
+ //
+ this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.savePictureToolStripMenuItem});
+ this.contextMenuStrip1.Name = "contextMenuStrip1";
+ this.contextMenuStrip1.Size = new System.Drawing.Size(139, 26);
+ //
+ // savePictureToolStripMenuItem
+ //
+ this.savePictureToolStripMenuItem.Name = "savePictureToolStripMenuItem";
+ this.savePictureToolStripMenuItem.Size = new System.Drawing.Size(138, 22);
+ this.savePictureToolStripMenuItem.Text = "Save Picture";
+ this.savePictureToolStripMenuItem.Click += new System.EventHandler(this.savePictureToolStripMenuItem_Click);
+ //
+ // ImageDisplay
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(522, 450);
+ this.Controls.Add(this.pictureBox1);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;
+ this.Name = "ImageDisplay";
+ this.Text = "ImageDisplay";
+ this.Shown += new System.EventHandler(this.ImageDisplay_Shown);
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
+ this.contextMenuStrip1.ResumeLayout(false);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ public System.Windows.Forms.PictureBox pictureBox1;
+ private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
+ private System.Windows.Forms.ToolStripMenuItem savePictureToolStripMenuItem;
+ }
+}
\ No newline at end of file
diff --git a/Source/LibationWinForms/grid/ImageDisplay.cs b/Source/LibationWinForms/grid/ImageDisplay.cs
new file mode 100644
index 00000000..09fa2481
--- /dev/null
+++ b/Source/LibationWinForms/grid/ImageDisplay.cs
@@ -0,0 +1,118 @@
+using FileLiberator;
+using LibationFileManager;
+using System;
+using System.Drawing;
+using System.IO;
+using System.Windows.Forms;
+
+namespace LibationWinForms
+{
+ public partial class ImageDisplay : Form
+ {
+ public string PictureFileName { get; set; }
+ public string BookSaveDirectory { get; set; }
+ public byte[] CoverPicture { get => _coverBytes; set => pictureBox1.Image = Dinah.Core.Drawing.ImageReader.ToImage(_coverBytes = value); }
+
+
+
+ private byte[] _coverBytes;
+
+ private bool detectedResizeDirection = false;
+ private bool resizingWidth = false;
+ private bool resizingHeight = false;
+
+ private int lastWidth;
+ private int lastHeight;
+ private int formExtraWidth;
+ private int formExtraHeight;
+
+ private double pictureAR = 1;
+
+ public ImageDisplay()
+ {
+ InitializeComponent();
+ lastWidth = Width;
+ lastHeight = Height;
+ }
+
+ protected override void OnResizeBegin(EventArgs e)
+ {
+ detectedResizeDirection = false;
+ base.OnResizeBegin(e);
+ }
+
+ protected override void OnResizeEnd(EventArgs e)
+ {
+ base.OnResize(e);
+ base.OnResizeEnd(e);
+ }
+
+ protected override void OnResize(EventArgs e)
+ {
+ if (WindowState != FormWindowState.Normal)
+ {
+ base.OnResize(e);
+ return;
+ }
+
+ int width = this.Width, height = this.Height;
+
+ if (!detectedResizeDirection)
+ {
+ resizingWidth = lastWidth != width;
+ resizingHeight = lastHeight != height;
+ detectedResizeDirection = true;
+ }
+
+ if (resizingWidth && !resizingHeight)
+ height = CalculateARHeight(width);
+ else
+ width = CalculateARWidth(height);
+
+ pictureBox1.Size = new Size(width - formExtraWidth, height - formExtraHeight);
+
+ lastWidth = width;
+ lastHeight = height;
+
+ SetBoundsCore(Location.X, Location.Y, width, height, BoundsSpecified.Width | BoundsSpecified.Height);
+ }
+
+ private int CalculateARHeight(int width)
+ {
+ return (int)((width - formExtraWidth) * pictureAR) + formExtraHeight;
+ }
+
+ private int CalculateARWidth(int height)
+ {
+ return (int)((height - formExtraHeight) * pictureAR) + formExtraWidth;
+ }
+
+ private void ImageDisplay_Shown(object sender, EventArgs e)
+ {
+ formExtraWidth = Width - pictureBox1.Width;
+ formExtraHeight = Height - pictureBox1.Height;
+ OnResize(e);
+ }
+
+ private void savePictureToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ SaveFileDialog saveFileDialog = new();
+ saveFileDialog.Filter = "jpeg|*.jpg";
+ saveFileDialog.InitialDirectory = Directory.Exists(BookSaveDirectory) ? BookSaveDirectory : Path.GetDirectoryName(BookSaveDirectory);
+ saveFileDialog.FileName = PictureFileName;
+
+ if (saveFileDialog.ShowDialog() != DialogResult.OK)
+ return;
+
+ try
+ {
+ File.WriteAllBytes(saveFileDialog.FileName, CoverPicture);
+ }
+ catch (Exception ex)
+ {
+ Serilog.Log.Logger.Error(ex.Message);
+ MessageBox.Show(this, $"An error was encountered while trying to save the picture\r\n\r\n{ex.Message}", "Sailed to save picture", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
+ }
+ }
+ }
+}
diff --git a/Source/LibationWinForms/grid/ImageDisplay.resx b/Source/LibationWinForms/grid/ImageDisplay.resx
new file mode 100644
index 00000000..2a349cc7
--- /dev/null
+++ b/Source/LibationWinForms/grid/ImageDisplay.resx
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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
+
+
+ 17, 17
+
+
\ No newline at end of file
diff --git a/Source/LibationWinForms/grid/ProductsGrid.cs b/Source/LibationWinForms/grid/ProductsGrid.cs
index 239288b6..3bcc2a7f 100644
--- a/Source/LibationWinForms/grid/ProductsGrid.cs
+++ b/Source/LibationWinForms/grid/ProductsGrid.cs
@@ -9,6 +9,7 @@ using Dinah.Core;
using Dinah.Core.DataBinding;
using Dinah.Core.Threading;
using Dinah.Core.Windows.Forms;
+using FileLiberator;
using LibationFileManager;
using LibationWinForms.Dialogs;
@@ -31,6 +32,8 @@ namespace LibationWinForms
public partial class ProductsGrid : UserControl
{
+
+ ImageDisplay imageDisplay;
public event EventHandler VisibleCountChanged;
// alias
@@ -62,14 +65,43 @@ namespace LibationWinForms
if (e.RowIndex < 0)
return;
- var clickedColumn = _dataGridView.Columns[e.ColumnIndex];
-
- if (clickedColumn == liberateGVColumn)
+ if (e.ColumnIndex == liberateGVColumn.Index)
await Liberate_Click(getGridEntry(e.RowIndex));
- else if (clickedColumn == tagAndDetailsGVColumn)
+ else if (e.ColumnIndex == tagAndDetailsGVColumn.Index)
Details_Click(getGridEntry(e.RowIndex));
- else if (clickedColumn == descriptionGVColumn)
+ else if (e.ColumnIndex == descriptionGVColumn.Index)
Description_Click(getGridEntry(e.RowIndex), _dataGridView.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, false));
+ else if (e.ColumnIndex == coverGVColumn.Index)
+ await Cover_Click(getGridEntry(e.RowIndex));
+ }
+
+ private async Task Cover_Click(GridEntry liveGridEntry)
+ {
+ var picDefinition = new PictureDefinition(liveGridEntry.LibraryBook.Book.PictureLarge, PictureSize.Native);
+ (_, byte[] initialImageBts) = PictureStorage.GetPicture(new PictureDefinition(liveGridEntry.LibraryBook.Book.PictureId, PictureSize._80x80));
+
+ var windowTitle = $"{liveGridEntry.Title} - Cover";
+
+ var picDlTask = Task.Run(() =>
+ {
+ return PictureStorage.GetPictureSynchronously(picDefinition);
+ });
+
+ if (imageDisplay is null || imageDisplay.IsDisposed || !imageDisplay.Visible)
+ {
+ imageDisplay = new ImageDisplay();
+ imageDisplay.RestoreSizeAndLocation(Configuration.Instance);
+ imageDisplay.FormClosed += (_, _) => imageDisplay.SaveSizeAndLocation(Configuration.Instance);
+ imageDisplay.Show(this);
+ }
+
+ imageDisplay.BookSaveDirectory = AudibleFileStorage.Audio.GetDestinationDirectory(liveGridEntry.LibraryBook);
+ imageDisplay.PictureFileName = System.IO.Path.GetFileName(AudibleFileStorage.Audio.GetBooksDirectoryFilename(liveGridEntry.LibraryBook, ".jpg"));
+ imageDisplay.Text = windowTitle;
+ imageDisplay.CoverPicture = initialImageBts;
+ imageDisplay.CoverPicture = await picDlTask;
+
+
}
private void Description_Click(GridEntry liveGridEntry, Rectangle cellDisplay)
@@ -81,13 +113,13 @@ namespace LibationWinForms
BorderThickness = 2,
};
- void CloseWindow (object o, EventArgs e)
+ void CloseWindow(object o, EventArgs e)
{
displayWindow.Close();
}
_dataGridView.Scroll += CloseWindow;
- displayWindow.FormClosed += (_,_) => _dataGridView.Scroll -= CloseWindow;
+ displayWindow.FormClosed += (_, _) => _dataGridView.Scroll -= CloseWindow;
displayWindow.Show(this);
}
@@ -166,40 +198,40 @@ namespace LibationWinForms
Filter();
}
- private void bindToGrid(List orderedBooks)
- {
- bindingList = new SortableBindingList(orderedBooks.Select(lb => toGridEntry(lb)));
- gridEntryBindingSource.DataSource = bindingList;
- }
+ private void bindToGrid(List orderedBooks)
+ {
+ bindingList = new SortableBindingList(orderedBooks.Select(lb => toGridEntry(lb)));
+ gridEntryBindingSource.DataSource = bindingList;
+ }
- private void updateGrid(List orderedBooks)
- {
- for (var i = orderedBooks.Count - 1; i >= 0; i--)
- {
- var libraryBook = orderedBooks[i];
- var existingItem = bindingList.FirstOrDefault(i => i.AudibleProductId == libraryBook.Book.AudibleProductId);
+ private void updateGrid(List orderedBooks)
+ {
+ for (var i = orderedBooks.Count - 1; i >= 0; i--)
+ {
+ var libraryBook = orderedBooks[i];
+ var existingItem = bindingList.FirstOrDefault(i => i.AudibleProductId == libraryBook.Book.AudibleProductId);
- // add new to top
- if (existingItem is null)
- bindingList.Insert(0, toGridEntry(libraryBook));
- // update existing
- else
- existingItem.UpdateLibraryBook(libraryBook);
- }
+ // add new to top
+ if (existingItem is null)
+ bindingList.Insert(0, toGridEntry(libraryBook));
+ // update existing
+ else
+ existingItem.UpdateLibraryBook(libraryBook);
+ }
- // remove deleted from grid. note: actual deletion from db must still occur via the RemoveBook feature. deleting from audible will not trigger this
- var oldIds = bindingList.Select(ge => ge.AudibleProductId).ToList();
- var newIds = orderedBooks.Select(lb => lb.Book.AudibleProductId).ToList();
- var remove = oldIds.Except(newIds).ToList();
- foreach (var id in remove)
- {
- var oldItem = bindingList.FirstOrDefault(ge => ge.AudibleProductId == id);
- if (oldItem is not null)
- bindingList.Remove(oldItem);
- }
- }
+ // remove deleted from grid. note: actual deletion from db must still occur via the RemoveBook feature. deleting from audible will not trigger this
+ var oldIds = bindingList.Select(ge => ge.AudibleProductId).ToList();
+ var newIds = orderedBooks.Select(lb => lb.Book.AudibleProductId).ToList();
+ var remove = oldIds.Except(newIds).ToList();
+ foreach (var id in remove)
+ {
+ var oldItem = bindingList.FirstOrDefault(ge => ge.AudibleProductId == id);
+ if (oldItem is not null)
+ bindingList.Remove(oldItem);
+ }
+ }
- private GridEntry toGridEntry(DataLayer.LibraryBook libraryBook)
+ private GridEntry toGridEntry(DataLayer.LibraryBook libraryBook)
{
var entry = new GridEntry(libraryBook);
entry.Committed += Filter;
@@ -207,11 +239,11 @@ namespace LibationWinForms
return entry;
}
- #endregion
+ #endregion
- #region Filter
+ #region Filter
- private string _filterSearchString;
+ private string _filterSearchString;
private void Filter(object _ = null, EventArgs __ = null) => Filter(_filterSearchString);
public void Filter(string searchString)
{
@@ -344,6 +376,8 @@ namespace LibationWinForms
{
if (e.ColumnIndex == descriptionGVColumn.Index)
e.ToolTipText = "Click to see full description";
+ else if (e.ColumnIndex == coverGVColumn.Index)
+ e.ToolTipText = "Click to see full size";
}
#endregion