diff --git a/Source/DataLayer/EfClasses/Rating.cs b/Source/DataLayer/EfClasses/Rating.cs index 761633be..18b0cd05 100644 --- a/Source/DataLayer/EfClasses/Rating.cs +++ b/Source/DataLayer/EfClasses/Rating.cs @@ -12,7 +12,7 @@ namespace DataLayer public float StoryRating { get; private set; } private Rating() { } - internal Rating(float overallRating, float performanceRating, float storyRating) + public Rating(float overallRating, float performanceRating, float storyRating) { OverallRating = overallRating; PerformanceRating = performanceRating; diff --git a/Source/LibationWinForms/Dialogs/RemoveBooksDialog.Designer.cs b/Source/LibationWinForms/Dialogs/RemoveBooksDialog.Designer.cs index 61974264..7240b8f3 100644 --- a/Source/LibationWinForms/Dialogs/RemoveBooksDialog.Designer.cs +++ b/Source/LibationWinForms/Dialogs/RemoveBooksDialog.Designer.cs @@ -38,7 +38,7 @@ namespace LibationWinForms.Dialogs this.authorsDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); this.miscDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); this.purchaseDateGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.gridEntryBindingSource = new LibationWinForms.SyncBindingSource(this.components); + this.gridEntryBindingSource = new LibationWinForms.GridView.SyncBindingSource(this.components); this.btnRemoveBooks = new System.Windows.Forms.Button(); this.label1 = new System.Windows.Forms.Label(); ((System.ComponentModel.ISupportInitialize)(this._dataGridView)).BeginInit(); @@ -176,7 +176,7 @@ namespace LibationWinForms.Dialogs #endregion private System.Windows.Forms.DataGridView _dataGridView; - private LibationWinForms.SyncBindingSource gridEntryBindingSource; + private LibationWinForms.GridView.SyncBindingSource gridEntryBindingSource; private System.Windows.Forms.Button btnRemoveBooks; private System.Windows.Forms.Label label1; private System.Windows.Forms.DataGridViewCheckBoxColumn removeDataGridViewCheckBoxColumn; diff --git a/Source/LibationWinForms/Dialogs/RemoveBooksDialog.cs b/Source/LibationWinForms/Dialogs/RemoveBooksDialog.cs index ecd56188..558095f0 100644 --- a/Source/LibationWinForms/Dialogs/RemoveBooksDialog.cs +++ b/Source/LibationWinForms/Dialogs/RemoveBooksDialog.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Data; @@ -121,10 +120,8 @@ namespace LibationWinForms.Dialogs } } - internal class RemovableGridEntry : GridEntry + internal class RemovableGridEntry : GridView.LibraryBookEntry { - private static readonly IComparer BoolComparer = new ObjectComparer(); - private bool _remove = false; public RemovableGridEntry(LibraryBook libraryBook) : base(libraryBook) { } @@ -147,12 +144,5 @@ namespace LibationWinForms.Dialogs return Remove; return base.GetMemberValue(memberName); } - - public override IComparer GetMemberComparer(Type memberType) - { - if (memberType == typeof(bool)) - return BoolComparer; - return base.GetMemberComparer(memberType); - } } } diff --git a/Source/LibationWinForms/Form1.Designer.cs b/Source/LibationWinForms/Form1.Designer.cs index 1f554c16..f4abad4f 100644 --- a/Source/LibationWinForms/Form1.Designer.cs +++ b/Source/LibationWinForms/Form1.Designer.cs @@ -28,111 +28,100 @@ /// private void InitializeComponent() { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1)); - this.gridPanel = new System.Windows.Forms.Panel(); - this.filterHelpBtn = new System.Windows.Forms.Button(); - this.filterBtn = new System.Windows.Forms.Button(); - this.filterSearchTb = new System.Windows.Forms.TextBox(); - this.menuStrip1 = new System.Windows.Forms.MenuStrip(); - this.importToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.autoScanLibraryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.noAccountsYetAddAccountToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.scanLibraryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.scanLibraryOfAllAccountsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.scanLibraryOfSomeAccountsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.removeLibraryBooksToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.removeAllAccountsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.removeSomeAccountsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.liberateToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.beginBookBackupsToolStripMenuItem = new LibationWinForms.FormattableToolStripMenuItem(); - this.beginPdfBackupsToolStripMenuItem = new LibationWinForms.FormattableToolStripMenuItem(); - this.convertAllM4bToMp3ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.liberateVisible2ToolStripMenuItem = new LibationWinForms.FormattableToolStripMenuItem(); - this.exportToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.exportLibraryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.quickFiltersToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.firstFilterIsDefaultToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.editQuickFiltersToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); - this.scanningToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.visibleBooksToolStripMenuItem = new LibationWinForms.FormattableToolStripMenuItem(); - this.liberateVisibleToolStripMenuItem = new LibationWinForms.FormattableToolStripMenuItem(); - this.replaceTagsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.setDownloadedToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.removeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.settingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.accountsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.basicSettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); - this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.statusStrip1 = new System.Windows.Forms.StatusStrip(); - this.visibleCountLbl = new LibationWinForms.FormattableToolStripStatusLabel(); - this.springLbl = new System.Windows.Forms.ToolStripStatusLabel(); - this.backupsCountsLbl = new System.Windows.Forms.ToolStripStatusLabel(); - this.pdfsCountsLbl = new LibationWinForms.FormattableToolStripStatusLabel(); - this.addQuickFilterBtn = new System.Windows.Forms.Button(); - this.splitContainer1 = new System.Windows.Forms.SplitContainer(); - this.panel1 = new System.Windows.Forms.Panel(); - this.toggleQueueHideBtn = new System.Windows.Forms.Button(); - this.processBookQueue1 = new LibationWinForms.ProcessQueue.ProcessQueueControl(); - this.menuStrip1.SuspendLayout(); - this.statusStrip1.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); - this.splitContainer1.Panel1.SuspendLayout(); - this.splitContainer1.Panel2.SuspendLayout(); - this.splitContainer1.SuspendLayout(); - this.panel1.SuspendLayout(); - this.SuspendLayout(); - // - // gridPanel - // - this.gridPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1)); + this.filterHelpBtn = new System.Windows.Forms.Button(); + this.filterBtn = new System.Windows.Forms.Button(); + this.filterSearchTb = new System.Windows.Forms.TextBox(); + this.menuStrip1 = new System.Windows.Forms.MenuStrip(); + this.importToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.autoScanLibraryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.noAccountsYetAddAccountToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.scanLibraryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.scanLibraryOfAllAccountsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.scanLibraryOfSomeAccountsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.removeLibraryBooksToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.removeAllAccountsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.removeSomeAccountsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.liberateToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.beginBookBackupsToolStripMenuItem = new LibationWinForms.FormattableToolStripMenuItem(); + this.beginPdfBackupsToolStripMenuItem = new LibationWinForms.FormattableToolStripMenuItem(); + this.convertAllM4bToMp3ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.liberateVisible2ToolStripMenuItem = new LibationWinForms.FormattableToolStripMenuItem(); + this.exportToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.exportLibraryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.quickFiltersToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.firstFilterIsDefaultToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.editQuickFiltersToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.scanningToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.visibleBooksToolStripMenuItem = new LibationWinForms.FormattableToolStripMenuItem(); + this.liberateVisibleToolStripMenuItem = new LibationWinForms.FormattableToolStripMenuItem(); + this.replaceTagsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.setDownloadedToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.removeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.settingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.accountsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.basicSettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.statusStrip1 = new System.Windows.Forms.StatusStrip(); + this.visibleCountLbl = new LibationWinForms.FormattableToolStripStatusLabel(); + this.springLbl = new System.Windows.Forms.ToolStripStatusLabel(); + this.backupsCountsLbl = new System.Windows.Forms.ToolStripStatusLabel(); + this.pdfsCountsLbl = new LibationWinForms.FormattableToolStripStatusLabel(); + this.addQuickFilterBtn = new System.Windows.Forms.Button(); + this.splitContainer1 = new System.Windows.Forms.SplitContainer(); + this.panel1 = new System.Windows.Forms.Panel(); + this.productsDisplay = new LibationWinForms.GridView.ProductsDisplay(); + this.toggleQueueHideBtn = new System.Windows.Forms.Button(); + this.processBookQueue1 = new LibationWinForms.ProcessQueue.ProcessQueueControl(); + this.menuStrip1.SuspendLayout(); + this.statusStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); + this.splitContainer1.Panel1.SuspendLayout(); + this.splitContainer1.Panel2.SuspendLayout(); + this.splitContainer1.SuspendLayout(); + this.panel1.SuspendLayout(); + this.SuspendLayout(); + // + // filterHelpBtn + // + this.filterHelpBtn.Location = new System.Drawing.Point(15, 3); + this.filterHelpBtn.Margin = new System.Windows.Forms.Padding(15, 3, 4, 3); + this.filterHelpBtn.Name = "filterHelpBtn"; + this.filterHelpBtn.Size = new System.Drawing.Size(26, 27); + this.filterHelpBtn.TabIndex = 3; + this.filterHelpBtn.Text = "?"; + this.filterHelpBtn.UseVisualStyleBackColor = true; + this.filterHelpBtn.Click += new System.EventHandler(this.filterHelpBtn_Click); + // + // filterBtn + // + this.filterBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.filterBtn.Location = new System.Drawing.Point(916, 3); + this.filterBtn.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.filterBtn.Name = "filterBtn"; + this.filterBtn.Size = new System.Drawing.Size(88, 27); + this.filterBtn.TabIndex = 2; + this.filterBtn.Text = "Filter"; + this.filterBtn.UseVisualStyleBackColor = true; + this.filterBtn.Click += new System.EventHandler(this.filterBtn_Click); + // + // filterSearchTb + // + this.filterSearchTb.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.gridPanel.Location = new System.Drawing.Point(15, 33); - this.gridPanel.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); - this.gridPanel.Name = "gridPanel"; - this.gridPanel.Size = new System.Drawing.Size(864, 558); - this.gridPanel.TabIndex = 5; - // - // filterHelpBtn - // - this.filterHelpBtn.Location = new System.Drawing.Point(15, 3); - this.filterHelpBtn.Margin = new System.Windows.Forms.Padding(15, 3, 4, 3); - this.filterHelpBtn.Name = "filterHelpBtn"; - this.filterHelpBtn.Size = new System.Drawing.Size(26, 27); - this.filterHelpBtn.TabIndex = 3; - this.filterHelpBtn.Text = "?"; - this.filterHelpBtn.UseVisualStyleBackColor = true; - this.filterHelpBtn.Click += new System.EventHandler(this.filterHelpBtn_Click); - // - // filterBtn - // - 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.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); - this.filterBtn.Name = "filterBtn"; - this.filterBtn.Size = new System.Drawing.Size(88, 27); - this.filterBtn.TabIndex = 2; - this.filterBtn.Text = "Filter"; - this.filterBtn.UseVisualStyleBackColor = true; - this.filterBtn.Click += new System.EventHandler(this.filterBtn_Click); - // - // filterSearchTb - // - this.filterSearchTb.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.filterSearchTb.Location = new System.Drawing.Point(196, 7); - this.filterSearchTb.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); - this.filterSearchTb.Name = "filterSearchTb"; - this.filterSearchTb.Size = new System.Drawing.Size(544, 23); - this.filterSearchTb.TabIndex = 1; - this.filterSearchTb.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.filterSearchTb_KeyPress); - // - // menuStrip1 - // - this.menuStrip1.ImageScalingSize = new System.Drawing.Size(40, 40); - this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.filterSearchTb.Location = new System.Drawing.Point(196, 7); + this.filterSearchTb.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.filterSearchTb.Name = "filterSearchTb"; + this.filterSearchTb.Size = new System.Drawing.Size(712, 23); + this.filterSearchTb.TabIndex = 1; + this.filterSearchTb.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.filterSearchTb_KeyPress); + // + // menuStrip1 + // + this.menuStrip1.ImageScalingSize = new System.Drawing.Size(40, 40); + this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.importToolStripMenuItem, this.liberateToolStripMenuItem, this.exportToolStripMenuItem, @@ -140,402 +129,415 @@ this.scanningToolStripMenuItem, this.visibleBooksToolStripMenuItem, this.settingsToolStripMenuItem}); - this.menuStrip1.Location = new System.Drawing.Point(0, 0); - this.menuStrip1.Name = "menuStrip1"; - this.menuStrip1.Padding = new System.Windows.Forms.Padding(7, 2, 0, 2); - this.menuStrip1.Size = new System.Drawing.Size(893, 24); - this.menuStrip1.TabIndex = 0; - this.menuStrip1.Text = "menuStrip1"; - // - // importToolStripMenuItem - // - this.importToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.menuStrip1.Location = new System.Drawing.Point(0, 0); + this.menuStrip1.Name = "menuStrip1"; + this.menuStrip1.Padding = new System.Windows.Forms.Padding(7, 2, 0, 2); + this.menuStrip1.Size = new System.Drawing.Size(1061, 24); + this.menuStrip1.TabIndex = 0; + this.menuStrip1.Text = "menuStrip1"; + // + // importToolStripMenuItem + // + this.importToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.autoScanLibraryToolStripMenuItem, this.noAccountsYetAddAccountToolStripMenuItem, this.scanLibraryToolStripMenuItem, this.scanLibraryOfAllAccountsToolStripMenuItem, this.scanLibraryOfSomeAccountsToolStripMenuItem, this.removeLibraryBooksToolStripMenuItem}); - this.importToolStripMenuItem.Name = "importToolStripMenuItem"; - this.importToolStripMenuItem.Size = new System.Drawing.Size(55, 20); - this.importToolStripMenuItem.Text = "&Import"; - // - // autoScanLibraryToolStripMenuItem - // - this.autoScanLibraryToolStripMenuItem.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None; - this.autoScanLibraryToolStripMenuItem.Name = "autoScanLibraryToolStripMenuItem"; - this.autoScanLibraryToolStripMenuItem.Size = new System.Drawing.Size(247, 22); - this.autoScanLibraryToolStripMenuItem.Text = "A&uto Scan Library"; - this.autoScanLibraryToolStripMenuItem.Click += new System.EventHandler(this.autoScanLibraryToolStripMenuItem_Click); - // - // noAccountsYetAddAccountToolStripMenuItem - // - this.noAccountsYetAddAccountToolStripMenuItem.Name = "noAccountsYetAddAccountToolStripMenuItem"; - this.noAccountsYetAddAccountToolStripMenuItem.Size = new System.Drawing.Size(247, 22); - this.noAccountsYetAddAccountToolStripMenuItem.Text = "No accounts yet. A&dd Account..."; - this.noAccountsYetAddAccountToolStripMenuItem.Click += new System.EventHandler(this.noAccountsYetAddAccountToolStripMenuItem_Click); - // - // scanLibraryToolStripMenuItem - // - this.scanLibraryToolStripMenuItem.Name = "scanLibraryToolStripMenuItem"; - this.scanLibraryToolStripMenuItem.Size = new System.Drawing.Size(247, 22); - this.scanLibraryToolStripMenuItem.Text = "Scan &Library"; - this.scanLibraryToolStripMenuItem.Click += new System.EventHandler(this.scanLibraryToolStripMenuItem_Click); - // - // scanLibraryOfAllAccountsToolStripMenuItem - // - this.scanLibraryOfAllAccountsToolStripMenuItem.Name = "scanLibraryOfAllAccountsToolStripMenuItem"; - this.scanLibraryOfAllAccountsToolStripMenuItem.Size = new System.Drawing.Size(247, 22); - this.scanLibraryOfAllAccountsToolStripMenuItem.Text = "Scan Library of &All Accounts"; - this.scanLibraryOfAllAccountsToolStripMenuItem.Click += new System.EventHandler(this.scanLibraryOfAllAccountsToolStripMenuItem_Click); - // - // scanLibraryOfSomeAccountsToolStripMenuItem - // - this.scanLibraryOfSomeAccountsToolStripMenuItem.Name = "scanLibraryOfSomeAccountsToolStripMenuItem"; - this.scanLibraryOfSomeAccountsToolStripMenuItem.Size = new System.Drawing.Size(247, 22); - this.scanLibraryOfSomeAccountsToolStripMenuItem.Text = "Scan Library of &Some Accounts..."; - this.scanLibraryOfSomeAccountsToolStripMenuItem.Click += new System.EventHandler(this.scanLibraryOfSomeAccountsToolStripMenuItem_Click); - // - // removeLibraryBooksToolStripMenuItem - // - this.removeLibraryBooksToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.importToolStripMenuItem.Name = "importToolStripMenuItem"; + this.importToolStripMenuItem.Size = new System.Drawing.Size(55, 20); + this.importToolStripMenuItem.Text = "&Import"; + // + // autoScanLibraryToolStripMenuItem + // + this.autoScanLibraryToolStripMenuItem.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None; + this.autoScanLibraryToolStripMenuItem.Name = "autoScanLibraryToolStripMenuItem"; + this.autoScanLibraryToolStripMenuItem.Size = new System.Drawing.Size(247, 22); + this.autoScanLibraryToolStripMenuItem.Text = "A&uto Scan Library"; + this.autoScanLibraryToolStripMenuItem.Click += new System.EventHandler(this.autoScanLibraryToolStripMenuItem_Click); + // + // noAccountsYetAddAccountToolStripMenuItem + // + this.noAccountsYetAddAccountToolStripMenuItem.Name = "noAccountsYetAddAccountToolStripMenuItem"; + this.noAccountsYetAddAccountToolStripMenuItem.Size = new System.Drawing.Size(247, 22); + this.noAccountsYetAddAccountToolStripMenuItem.Text = "No accounts yet. A&dd Account..."; + this.noAccountsYetAddAccountToolStripMenuItem.Click += new System.EventHandler(this.noAccountsYetAddAccountToolStripMenuItem_Click); + // + // scanLibraryToolStripMenuItem + // + this.scanLibraryToolStripMenuItem.Name = "scanLibraryToolStripMenuItem"; + this.scanLibraryToolStripMenuItem.Size = new System.Drawing.Size(247, 22); + this.scanLibraryToolStripMenuItem.Text = "Scan &Library"; + this.scanLibraryToolStripMenuItem.Click += new System.EventHandler(this.scanLibraryToolStripMenuItem_Click); + // + // scanLibraryOfAllAccountsToolStripMenuItem + // + this.scanLibraryOfAllAccountsToolStripMenuItem.Name = "scanLibraryOfAllAccountsToolStripMenuItem"; + this.scanLibraryOfAllAccountsToolStripMenuItem.Size = new System.Drawing.Size(247, 22); + this.scanLibraryOfAllAccountsToolStripMenuItem.Text = "Scan Library of &All Accounts"; + this.scanLibraryOfAllAccountsToolStripMenuItem.Click += new System.EventHandler(this.scanLibraryOfAllAccountsToolStripMenuItem_Click); + // + // scanLibraryOfSomeAccountsToolStripMenuItem + // + this.scanLibraryOfSomeAccountsToolStripMenuItem.Name = "scanLibraryOfSomeAccountsToolStripMenuItem"; + this.scanLibraryOfSomeAccountsToolStripMenuItem.Size = new System.Drawing.Size(247, 22); + this.scanLibraryOfSomeAccountsToolStripMenuItem.Text = "Scan Library of &Some Accounts..."; + this.scanLibraryOfSomeAccountsToolStripMenuItem.Click += new System.EventHandler(this.scanLibraryOfSomeAccountsToolStripMenuItem_Click); + // + // removeLibraryBooksToolStripMenuItem + // + this.removeLibraryBooksToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.removeAllAccountsToolStripMenuItem, this.removeSomeAccountsToolStripMenuItem}); - this.removeLibraryBooksToolStripMenuItem.Name = "removeLibraryBooksToolStripMenuItem"; - this.removeLibraryBooksToolStripMenuItem.Size = new System.Drawing.Size(247, 22); - this.removeLibraryBooksToolStripMenuItem.Text = "Remove Library Books"; - this.removeLibraryBooksToolStripMenuItem.Click += new System.EventHandler(this.removeLibraryBooksToolStripMenuItem_Click); - // - // removeAllAccountsToolStripMenuItem - // - this.removeAllAccountsToolStripMenuItem.Name = "removeAllAccountsToolStripMenuItem"; - this.removeAllAccountsToolStripMenuItem.Size = new System.Drawing.Size(157, 22); - this.removeAllAccountsToolStripMenuItem.Text = "All Accounts"; - this.removeAllAccountsToolStripMenuItem.Click += new System.EventHandler(this.removeAllAccountsToolStripMenuItem_Click); - // - // removeSomeAccountsToolStripMenuItem - // - this.removeSomeAccountsToolStripMenuItem.Name = "removeSomeAccountsToolStripMenuItem"; - this.removeSomeAccountsToolStripMenuItem.Size = new System.Drawing.Size(157, 22); - this.removeSomeAccountsToolStripMenuItem.Text = "Some Accounts"; - this.removeSomeAccountsToolStripMenuItem.Click += new System.EventHandler(this.removeSomeAccountsToolStripMenuItem_Click); - // - // liberateToolStripMenuItem - // - this.liberateToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.removeLibraryBooksToolStripMenuItem.Name = "removeLibraryBooksToolStripMenuItem"; + this.removeLibraryBooksToolStripMenuItem.Size = new System.Drawing.Size(247, 22); + this.removeLibraryBooksToolStripMenuItem.Text = "Remove Library Books"; + this.removeLibraryBooksToolStripMenuItem.Click += new System.EventHandler(this.removeLibraryBooksToolStripMenuItem_Click); + // + // removeAllAccountsToolStripMenuItem + // + this.removeAllAccountsToolStripMenuItem.Name = "removeAllAccountsToolStripMenuItem"; + this.removeAllAccountsToolStripMenuItem.Size = new System.Drawing.Size(157, 22); + this.removeAllAccountsToolStripMenuItem.Text = "All Accounts"; + this.removeAllAccountsToolStripMenuItem.Click += new System.EventHandler(this.removeAllAccountsToolStripMenuItem_Click); + // + // removeSomeAccountsToolStripMenuItem + // + this.removeSomeAccountsToolStripMenuItem.Name = "removeSomeAccountsToolStripMenuItem"; + this.removeSomeAccountsToolStripMenuItem.Size = new System.Drawing.Size(157, 22); + this.removeSomeAccountsToolStripMenuItem.Text = "Some Accounts"; + this.removeSomeAccountsToolStripMenuItem.Click += new System.EventHandler(this.removeSomeAccountsToolStripMenuItem_Click); + // + // liberateToolStripMenuItem + // + this.liberateToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.beginBookBackupsToolStripMenuItem, this.beginPdfBackupsToolStripMenuItem, this.convertAllM4bToMp3ToolStripMenuItem, this.liberateVisible2ToolStripMenuItem}); - this.liberateToolStripMenuItem.Name = "liberateToolStripMenuItem"; - this.liberateToolStripMenuItem.Size = new System.Drawing.Size(61, 20); - this.liberateToolStripMenuItem.Text = "&Liberate"; - // - // beginBookBackupsToolStripMenuItem - // - this.beginBookBackupsToolStripMenuItem.FormatText = "Begin &Book and PDF Backups: {0}"; - this.beginBookBackupsToolStripMenuItem.Name = "beginBookBackupsToolStripMenuItem"; - this.beginBookBackupsToolStripMenuItem.Size = new System.Drawing.Size(293, 22); - this.beginBookBackupsToolStripMenuItem.Text = "Begin &Book and PDF Backups: {0}"; - this.beginBookBackupsToolStripMenuItem.Click += new System.EventHandler(this.beginBookBackupsToolStripMenuItem_Click); - // - // beginPdfBackupsToolStripMenuItem - // - this.beginPdfBackupsToolStripMenuItem.FormatText = "Begin &PDF Only Backups: {0}"; - this.beginPdfBackupsToolStripMenuItem.Name = "beginPdfBackupsToolStripMenuItem"; - this.beginPdfBackupsToolStripMenuItem.Size = new System.Drawing.Size(293, 22); - this.beginPdfBackupsToolStripMenuItem.Text = "Begin &PDF Only Backups: {0}"; - this.beginPdfBackupsToolStripMenuItem.Click += new System.EventHandler(this.beginPdfBackupsToolStripMenuItem_Click); - // - // convertAllM4bToMp3ToolStripMenuItem - // - this.convertAllM4bToMp3ToolStripMenuItem.Name = "convertAllM4bToMp3ToolStripMenuItem"; - this.convertAllM4bToMp3ToolStripMenuItem.Size = new System.Drawing.Size(293, 22); - this.convertAllM4bToMp3ToolStripMenuItem.Text = "Convert all &M4b to Mp3 [Long-running]..."; - this.convertAllM4bToMp3ToolStripMenuItem.Click += new System.EventHandler(this.convertAllM4bToMp3ToolStripMenuItem_Click); - // - // liberateVisible2ToolStripMenuItem - // - this.liberateVisible2ToolStripMenuItem.FormatText = "Liberate &Visible Books: {0}"; - this.liberateVisible2ToolStripMenuItem.Name = "liberateVisible2ToolStripMenuItem"; - this.liberateVisible2ToolStripMenuItem.Size = new System.Drawing.Size(293, 22); - this.liberateVisible2ToolStripMenuItem.Text = "Liberate &Visible Books: {0}"; - this.liberateVisible2ToolStripMenuItem.Click += new System.EventHandler(this.liberateVisible); - // - // exportToolStripMenuItem - // - this.exportToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.liberateToolStripMenuItem.Name = "liberateToolStripMenuItem"; + this.liberateToolStripMenuItem.Size = new System.Drawing.Size(61, 20); + this.liberateToolStripMenuItem.Text = "&Liberate"; + // + // beginBookBackupsToolStripMenuItem + // + this.beginBookBackupsToolStripMenuItem.FormatText = "Begin &Book and PDF Backups: {0}"; + this.beginBookBackupsToolStripMenuItem.Name = "beginBookBackupsToolStripMenuItem"; + this.beginBookBackupsToolStripMenuItem.Size = new System.Drawing.Size(293, 22); + this.beginBookBackupsToolStripMenuItem.Text = "Begin &Book and PDF Backups: {0}"; + this.beginBookBackupsToolStripMenuItem.Click += new System.EventHandler(this.beginBookBackupsToolStripMenuItem_Click); + // + // beginPdfBackupsToolStripMenuItem + // + this.beginPdfBackupsToolStripMenuItem.FormatText = "Begin &PDF Only Backups: {0}"; + this.beginPdfBackupsToolStripMenuItem.Name = "beginPdfBackupsToolStripMenuItem"; + this.beginPdfBackupsToolStripMenuItem.Size = new System.Drawing.Size(293, 22); + this.beginPdfBackupsToolStripMenuItem.Text = "Begin &PDF Only Backups: {0}"; + this.beginPdfBackupsToolStripMenuItem.Click += new System.EventHandler(this.beginPdfBackupsToolStripMenuItem_Click); + // + // convertAllM4bToMp3ToolStripMenuItem + // + this.convertAllM4bToMp3ToolStripMenuItem.Name = "convertAllM4bToMp3ToolStripMenuItem"; + this.convertAllM4bToMp3ToolStripMenuItem.Size = new System.Drawing.Size(293, 22); + this.convertAllM4bToMp3ToolStripMenuItem.Text = "Convert all &M4b to Mp3 [Long-running]..."; + this.convertAllM4bToMp3ToolStripMenuItem.Click += new System.EventHandler(this.convertAllM4bToMp3ToolStripMenuItem_Click); + // + // liberateVisible2ToolStripMenuItem + // + this.liberateVisible2ToolStripMenuItem.FormatText = "Liberate &Visible Books: {0}"; + this.liberateVisible2ToolStripMenuItem.Name = "liberateVisible2ToolStripMenuItem"; + this.liberateVisible2ToolStripMenuItem.Size = new System.Drawing.Size(293, 22); + this.liberateVisible2ToolStripMenuItem.Text = "Liberate &Visible Books: {0}"; + this.liberateVisible2ToolStripMenuItem.Click += new System.EventHandler(this.liberateVisible); + // + // exportToolStripMenuItem + // + this.exportToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.exportLibraryToolStripMenuItem}); - this.exportToolStripMenuItem.Name = "exportToolStripMenuItem"; - this.exportToolStripMenuItem.Size = new System.Drawing.Size(53, 20); - this.exportToolStripMenuItem.Text = "E&xport"; - // - // exportLibraryToolStripMenuItem - // - this.exportLibraryToolStripMenuItem.Name = "exportLibraryToolStripMenuItem"; - this.exportLibraryToolStripMenuItem.Size = new System.Drawing.Size(156, 22); - this.exportLibraryToolStripMenuItem.Text = "E&xport Library..."; - this.exportLibraryToolStripMenuItem.Click += new System.EventHandler(this.exportLibraryToolStripMenuItem_Click); - // - // quickFiltersToolStripMenuItem - // - this.quickFiltersToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.exportToolStripMenuItem.Name = "exportToolStripMenuItem"; + this.exportToolStripMenuItem.Size = new System.Drawing.Size(53, 20); + this.exportToolStripMenuItem.Text = "E&xport"; + // + // exportLibraryToolStripMenuItem + // + this.exportLibraryToolStripMenuItem.Name = "exportLibraryToolStripMenuItem"; + this.exportLibraryToolStripMenuItem.Size = new System.Drawing.Size(156, 22); + this.exportLibraryToolStripMenuItem.Text = "E&xport Library..."; + this.exportLibraryToolStripMenuItem.Click += new System.EventHandler(this.exportLibraryToolStripMenuItem_Click); + // + // quickFiltersToolStripMenuItem + // + this.quickFiltersToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.firstFilterIsDefaultToolStripMenuItem, this.editQuickFiltersToolStripMenuItem, this.toolStripSeparator1}); - this.quickFiltersToolStripMenuItem.Name = "quickFiltersToolStripMenuItem"; - this.quickFiltersToolStripMenuItem.Size = new System.Drawing.Size(84, 20); - this.quickFiltersToolStripMenuItem.Text = "Quick &Filters"; - // - // firstFilterIsDefaultToolStripMenuItem - // - this.firstFilterIsDefaultToolStripMenuItem.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None; - this.firstFilterIsDefaultToolStripMenuItem.Name = "firstFilterIsDefaultToolStripMenuItem"; - this.firstFilterIsDefaultToolStripMenuItem.Size = new System.Drawing.Size(256, 22); - this.firstFilterIsDefaultToolStripMenuItem.Text = "Start Libation with 1st filter &Default"; - this.firstFilterIsDefaultToolStripMenuItem.Click += new System.EventHandler(this.firstFilterIsDefaultToolStripMenuItem_Click); - // - // editQuickFiltersToolStripMenuItem - // - this.editQuickFiltersToolStripMenuItem.Name = "editQuickFiltersToolStripMenuItem"; - this.editQuickFiltersToolStripMenuItem.Size = new System.Drawing.Size(256, 22); - this.editQuickFiltersToolStripMenuItem.Text = "&Edit quick filters..."; - this.editQuickFiltersToolStripMenuItem.Click += new System.EventHandler(this.editQuickFiltersToolStripMenuItem_Click); - // - // toolStripSeparator1 - // - this.toolStripSeparator1.Name = "toolStripSeparator1"; - this.toolStripSeparator1.Size = new System.Drawing.Size(253, 6); - // - // scanningToolStripMenuItem - // - this.scanningToolStripMenuItem.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right; - this.scanningToolStripMenuItem.Enabled = false; - this.scanningToolStripMenuItem.Image = global::LibationWinForms.Properties.Resources.import_16x16; - this.scanningToolStripMenuItem.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None; - this.scanningToolStripMenuItem.Name = "scanningToolStripMenuItem"; - this.scanningToolStripMenuItem.Size = new System.Drawing.Size(93, 20); - this.scanningToolStripMenuItem.Text = "Scanning..."; - this.scanningToolStripMenuItem.Visible = false; - // - // visibleBooksToolStripMenuItem - // - this.visibleBooksToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.quickFiltersToolStripMenuItem.Name = "quickFiltersToolStripMenuItem"; + this.quickFiltersToolStripMenuItem.Size = new System.Drawing.Size(84, 20); + this.quickFiltersToolStripMenuItem.Text = "Quick &Filters"; + // + // firstFilterIsDefaultToolStripMenuItem + // + this.firstFilterIsDefaultToolStripMenuItem.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None; + this.firstFilterIsDefaultToolStripMenuItem.Name = "firstFilterIsDefaultToolStripMenuItem"; + this.firstFilterIsDefaultToolStripMenuItem.Size = new System.Drawing.Size(256, 22); + this.firstFilterIsDefaultToolStripMenuItem.Text = "Start Libation with 1st filter &Default"; + this.firstFilterIsDefaultToolStripMenuItem.Click += new System.EventHandler(this.firstFilterIsDefaultToolStripMenuItem_Click); + // + // editQuickFiltersToolStripMenuItem + // + this.editQuickFiltersToolStripMenuItem.Name = "editQuickFiltersToolStripMenuItem"; + this.editQuickFiltersToolStripMenuItem.Size = new System.Drawing.Size(256, 22); + this.editQuickFiltersToolStripMenuItem.Text = "&Edit quick filters..."; + this.editQuickFiltersToolStripMenuItem.Click += new System.EventHandler(this.editQuickFiltersToolStripMenuItem_Click); + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(253, 6); + // + // scanningToolStripMenuItem + // + this.scanningToolStripMenuItem.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right; + this.scanningToolStripMenuItem.Enabled = false; + this.scanningToolStripMenuItem.Image = global::LibationWinForms.Properties.Resources.import_16x16; + this.scanningToolStripMenuItem.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None; + this.scanningToolStripMenuItem.Name = "scanningToolStripMenuItem"; + this.scanningToolStripMenuItem.Size = new System.Drawing.Size(93, 20); + this.scanningToolStripMenuItem.Text = "Scanning..."; + this.scanningToolStripMenuItem.Visible = false; + // + // visibleBooksToolStripMenuItem + // + this.visibleBooksToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.liberateVisibleToolStripMenuItem, this.replaceTagsToolStripMenuItem, this.setDownloadedToolStripMenuItem, this.removeToolStripMenuItem}); - this.visibleBooksToolStripMenuItem.FormatText = "&Visible Books: {0}"; - this.visibleBooksToolStripMenuItem.Name = "visibleBooksToolStripMenuItem"; - this.visibleBooksToolStripMenuItem.Size = new System.Drawing.Size(108, 20); - this.visibleBooksToolStripMenuItem.Text = "&Visible Books: {0}"; - // - // liberateVisibleToolStripMenuItem - // - this.liberateVisibleToolStripMenuItem.FormatText = "&Liberate: {0}"; - this.liberateVisibleToolStripMenuItem.Name = "liberateVisibleToolStripMenuItem"; - this.liberateVisibleToolStripMenuItem.Size = new System.Drawing.Size(209, 22); - this.liberateVisibleToolStripMenuItem.Text = "&Liberate: {0}"; - this.liberateVisibleToolStripMenuItem.Click += new System.EventHandler(this.liberateVisible); - // - // replaceTagsToolStripMenuItem - // - this.replaceTagsToolStripMenuItem.Name = "replaceTagsToolStripMenuItem"; - this.replaceTagsToolStripMenuItem.Size = new System.Drawing.Size(209, 22); - this.replaceTagsToolStripMenuItem.Text = "Replace &Tags..."; - this.replaceTagsToolStripMenuItem.Click += new System.EventHandler(this.replaceTagsToolStripMenuItem_Click); - // - // setDownloadedToolStripMenuItem - // - this.setDownloadedToolStripMenuItem.Name = "setDownloadedToolStripMenuItem"; - this.setDownloadedToolStripMenuItem.Size = new System.Drawing.Size(209, 22); - this.setDownloadedToolStripMenuItem.Text = "Set \'&Downloaded\' status..."; - this.setDownloadedToolStripMenuItem.Click += new System.EventHandler(this.setDownloadedToolStripMenuItem_Click); - // - // removeToolStripMenuItem - // - this.removeToolStripMenuItem.Name = "removeToolStripMenuItem"; - this.removeToolStripMenuItem.Size = new System.Drawing.Size(209, 22); - this.removeToolStripMenuItem.Text = "&Remove from library..."; - this.removeToolStripMenuItem.Click += new System.EventHandler(this.removeToolStripMenuItem_Click); - // - // settingsToolStripMenuItem - // - this.settingsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.visibleBooksToolStripMenuItem.FormatText = "&Visible Books: {0}"; + this.visibleBooksToolStripMenuItem.Name = "visibleBooksToolStripMenuItem"; + this.visibleBooksToolStripMenuItem.Size = new System.Drawing.Size(108, 20); + this.visibleBooksToolStripMenuItem.Text = "&Visible Books: {0}"; + // + // liberateVisibleToolStripMenuItem + // + this.liberateVisibleToolStripMenuItem.FormatText = "&Liberate: {0}"; + this.liberateVisibleToolStripMenuItem.Name = "liberateVisibleToolStripMenuItem"; + this.liberateVisibleToolStripMenuItem.Size = new System.Drawing.Size(209, 22); + this.liberateVisibleToolStripMenuItem.Text = "&Liberate: {0}"; + this.liberateVisibleToolStripMenuItem.Click += new System.EventHandler(this.liberateVisible); + // + // replaceTagsToolStripMenuItem + // + this.replaceTagsToolStripMenuItem.Name = "replaceTagsToolStripMenuItem"; + this.replaceTagsToolStripMenuItem.Size = new System.Drawing.Size(209, 22); + this.replaceTagsToolStripMenuItem.Text = "Replace &Tags..."; + this.replaceTagsToolStripMenuItem.Click += new System.EventHandler(this.replaceTagsToolStripMenuItem_Click); + // + // setDownloadedToolStripMenuItem + // + this.setDownloadedToolStripMenuItem.Name = "setDownloadedToolStripMenuItem"; + this.setDownloadedToolStripMenuItem.Size = new System.Drawing.Size(209, 22); + this.setDownloadedToolStripMenuItem.Text = "Set \'&Downloaded\' status..."; + this.setDownloadedToolStripMenuItem.Click += new System.EventHandler(this.setDownloadedToolStripMenuItem_Click); + // + // removeToolStripMenuItem + // + this.removeToolStripMenuItem.Name = "removeToolStripMenuItem"; + this.removeToolStripMenuItem.Size = new System.Drawing.Size(209, 22); + this.removeToolStripMenuItem.Text = "&Remove from library..."; + this.removeToolStripMenuItem.Click += new System.EventHandler(this.removeToolStripMenuItem_Click); + // + // settingsToolStripMenuItem + // + this.settingsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.accountsToolStripMenuItem, this.basicSettingsToolStripMenuItem, this.toolStripSeparator2, this.aboutToolStripMenuItem}); - this.settingsToolStripMenuItem.Name = "settingsToolStripMenuItem"; - this.settingsToolStripMenuItem.Size = new System.Drawing.Size(61, 20); - this.settingsToolStripMenuItem.Text = "&Settings"; - // - // accountsToolStripMenuItem - // - this.accountsToolStripMenuItem.Name = "accountsToolStripMenuItem"; - this.accountsToolStripMenuItem.Size = new System.Drawing.Size(133, 22); - this.accountsToolStripMenuItem.Text = "&Accounts..."; - this.accountsToolStripMenuItem.Click += new System.EventHandler(this.accountsToolStripMenuItem_Click); - // - // basicSettingsToolStripMenuItem - // - this.basicSettingsToolStripMenuItem.Name = "basicSettingsToolStripMenuItem"; - this.basicSettingsToolStripMenuItem.Size = new System.Drawing.Size(133, 22); - this.basicSettingsToolStripMenuItem.Text = "&Settings..."; - this.basicSettingsToolStripMenuItem.Click += new System.EventHandler(this.basicSettingsToolStripMenuItem_Click); - // - // toolStripSeparator2 - // - this.toolStripSeparator2.Name = "toolStripSeparator2"; - this.toolStripSeparator2.Size = new System.Drawing.Size(130, 6); - // - // aboutToolStripMenuItem - // - this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem"; - this.aboutToolStripMenuItem.Size = new System.Drawing.Size(133, 22); - this.aboutToolStripMenuItem.Text = "A&bout..."; - this.aboutToolStripMenuItem.Click += new System.EventHandler(this.aboutToolStripMenuItem_Click); - // - // statusStrip1 - // - this.statusStrip1.ImageScalingSize = new System.Drawing.Size(40, 40); - this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.settingsToolStripMenuItem.Name = "settingsToolStripMenuItem"; + this.settingsToolStripMenuItem.Size = new System.Drawing.Size(61, 20); + this.settingsToolStripMenuItem.Text = "&Settings"; + // + // accountsToolStripMenuItem + // + this.accountsToolStripMenuItem.Name = "accountsToolStripMenuItem"; + this.accountsToolStripMenuItem.Size = new System.Drawing.Size(133, 22); + this.accountsToolStripMenuItem.Text = "&Accounts..."; + this.accountsToolStripMenuItem.Click += new System.EventHandler(this.accountsToolStripMenuItem_Click); + // + // basicSettingsToolStripMenuItem + // + this.basicSettingsToolStripMenuItem.Name = "basicSettingsToolStripMenuItem"; + this.basicSettingsToolStripMenuItem.Size = new System.Drawing.Size(133, 22); + this.basicSettingsToolStripMenuItem.Text = "&Settings..."; + this.basicSettingsToolStripMenuItem.Click += new System.EventHandler(this.basicSettingsToolStripMenuItem_Click); + // + // toolStripSeparator2 + // + this.toolStripSeparator2.Name = "toolStripSeparator2"; + this.toolStripSeparator2.Size = new System.Drawing.Size(130, 6); + // + // aboutToolStripMenuItem + // + this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem"; + this.aboutToolStripMenuItem.Size = new System.Drawing.Size(133, 22); + this.aboutToolStripMenuItem.Text = "A&bout..."; + this.aboutToolStripMenuItem.Click += new System.EventHandler(this.aboutToolStripMenuItem_Click); + // + // statusStrip1 + // + this.statusStrip1.ImageScalingSize = new System.Drawing.Size(40, 40); + this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.visibleCountLbl, this.springLbl, this.backupsCountsLbl, this.pdfsCountsLbl}); - this.statusStrip1.Location = new System.Drawing.Point(0, 618); - this.statusStrip1.Name = "statusStrip1"; - this.statusStrip1.Padding = new System.Windows.Forms.Padding(1, 0, 16, 0); - this.statusStrip1.Size = new System.Drawing.Size(893, 22); - this.statusStrip1.TabIndex = 6; - this.statusStrip1.Text = "statusStrip1"; - // - // visibleCountLbl - // - this.visibleCountLbl.FormatText = "Visible: {0}"; - this.visibleCountLbl.Name = "visibleCountLbl"; - this.visibleCountLbl.Size = new System.Drawing.Size(61, 17); - this.visibleCountLbl.Text = "Visible: {0}"; - // - // springLbl - // - this.springLbl.Name = "springLbl"; - this.springLbl.Size = new System.Drawing.Size(379, 17); - this.springLbl.Spring = true; - // - // backupsCountsLbl - // - this.backupsCountsLbl.Name = "backupsCountsLbl"; - this.backupsCountsLbl.Size = new System.Drawing.Size(218, 17); - this.backupsCountsLbl.Text = "[Calculating backed up book quantities]"; - // - // pdfsCountsLbl - // - this.pdfsCountsLbl.FormatText = "| PDFs: NOT d/l\'ed: {0} Downloaded: {1}"; - this.pdfsCountsLbl.Name = "pdfsCountsLbl"; - this.pdfsCountsLbl.Size = new System.Drawing.Size(218, 17); - this.pdfsCountsLbl.Text = "| PDFs: NOT d/l\'ed: {0} Downloaded: {1}"; - // - // addQuickFilterBtn - // - this.addQuickFilterBtn.Location = new System.Drawing.Point(50, 3); - this.addQuickFilterBtn.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); - this.addQuickFilterBtn.Name = "addQuickFilterBtn"; - this.addQuickFilterBtn.Size = new System.Drawing.Size(137, 27); - this.addQuickFilterBtn.TabIndex = 4; - this.addQuickFilterBtn.Text = "Add To Quick Filters"; - this.addQuickFilterBtn.UseVisualStyleBackColor = true; - this.addQuickFilterBtn.Click += new System.EventHandler(this.addQuickFilterBtn_Click); - // - // splitContainer1 - // - this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; - this.splitContainer1.Location = new System.Drawing.Point(0, 0); - this.splitContainer1.Name = "splitContainer1"; - // - // splitContainer1.Panel1 - // - this.splitContainer1.Panel1.Controls.Add(this.panel1); - this.splitContainer1.Panel1.Controls.Add(this.menuStrip1); - this.splitContainer1.Panel1.Controls.Add(this.statusStrip1); - // - // splitContainer1.Panel2 - // - this.splitContainer1.Panel2.Controls.Add(this.processBookQueue1); - this.splitContainer1.Size = new System.Drawing.Size(1231, 640); - this.splitContainer1.SplitterDistance = 893; - this.splitContainer1.SplitterWidth = 8; - this.splitContainer1.TabIndex = 7; - // - // panel1 - // - this.panel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.panel1.Controls.Add(this.toggleQueueHideBtn); - this.panel1.Controls.Add(this.gridPanel); - this.panel1.Controls.Add(this.addQuickFilterBtn); - this.panel1.Controls.Add(this.filterHelpBtn); - this.panel1.Controls.Add(this.filterSearchTb); - this.panel1.Controls.Add(this.filterBtn); - this.panel1.Dock = System.Windows.Forms.DockStyle.Fill; - this.panel1.Location = new System.Drawing.Point(0, 24); - this.panel1.Margin = new System.Windows.Forms.Padding(0); - this.panel1.Name = "panel1"; - this.panel1.Size = new System.Drawing.Size(893, 594); - this.panel1.TabIndex = 7; - // - // toggleQueueHideBtn - // - 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.Margin = new System.Windows.Forms.Padding(4, 3, 15, 3); - this.toggleQueueHideBtn.Name = "toggleQueueHideBtn"; - this.toggleQueueHideBtn.Size = new System.Drawing.Size(33, 27); - this.toggleQueueHideBtn.TabIndex = 8; - this.toggleQueueHideBtn.Text = "❱❱❱"; - this.toggleQueueHideBtn.UseVisualStyleBackColor = true; - this.toggleQueueHideBtn.Click += new System.EventHandler(this.ToggleQueueHideBtn_Click); - // - // processBookQueue1 - // - this.processBookQueue1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.processBookQueue1.Dock = System.Windows.Forms.DockStyle.Fill; - this.processBookQueue1.Location = new System.Drawing.Point(0, 0); - this.processBookQueue1.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); - this.processBookQueue1.Name = "processBookQueue1"; - this.processBookQueue1.Size = new System.Drawing.Size(330, 640); - this.processBookQueue1.TabIndex = 0; - // - // Form1 - // - this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(1231, 640); - this.Controls.Add(this.splitContainer1); - this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); - this.MainMenuStrip = this.menuStrip1; - this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); - this.Name = "Form1"; - this.Text = "Libation: Liberate your Library"; - this.Load += new System.EventHandler(this.Form1_Load); - this.menuStrip1.ResumeLayout(false); - this.menuStrip1.PerformLayout(); - this.statusStrip1.ResumeLayout(false); - this.statusStrip1.PerformLayout(); - this.splitContainer1.Panel1.ResumeLayout(false); - this.splitContainer1.Panel1.PerformLayout(); - this.splitContainer1.Panel2.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); - this.splitContainer1.ResumeLayout(false); - this.panel1.ResumeLayout(false); - this.panel1.PerformLayout(); - this.ResumeLayout(false); + this.statusStrip1.Location = new System.Drawing.Point(0, 618); + this.statusStrip1.Name = "statusStrip1"; + this.statusStrip1.Padding = new System.Windows.Forms.Padding(1, 0, 16, 0); + this.statusStrip1.Size = new System.Drawing.Size(1061, 22); + this.statusStrip1.TabIndex = 6; + this.statusStrip1.Text = "statusStrip1"; + // + // visibleCountLbl + // + this.visibleCountLbl.FormatText = "Visible: {0}"; + this.visibleCountLbl.Name = "visibleCountLbl"; + this.visibleCountLbl.Size = new System.Drawing.Size(61, 17); + this.visibleCountLbl.Text = "Visible: {0}"; + // + // springLbl + // + this.springLbl.Name = "springLbl"; + this.springLbl.Size = new System.Drawing.Size(547, 17); + this.springLbl.Spring = true; + // + // backupsCountsLbl + // + this.backupsCountsLbl.Name = "backupsCountsLbl"; + this.backupsCountsLbl.Size = new System.Drawing.Size(218, 17); + this.backupsCountsLbl.Text = "[Calculating backed up book quantities]"; + // + // pdfsCountsLbl + // + this.pdfsCountsLbl.FormatText = "| PDFs: NOT d/l\'ed: {0} Downloaded: {1}"; + this.pdfsCountsLbl.Name = "pdfsCountsLbl"; + this.pdfsCountsLbl.Size = new System.Drawing.Size(218, 17); + this.pdfsCountsLbl.Text = "| PDFs: NOT d/l\'ed: {0} Downloaded: {1}"; + // + // addQuickFilterBtn + // + this.addQuickFilterBtn.Location = new System.Drawing.Point(50, 3); + this.addQuickFilterBtn.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.addQuickFilterBtn.Name = "addQuickFilterBtn"; + this.addQuickFilterBtn.Size = new System.Drawing.Size(137, 27); + this.addQuickFilterBtn.TabIndex = 4; + this.addQuickFilterBtn.Text = "Add To Quick Filters"; + this.addQuickFilterBtn.UseVisualStyleBackColor = true; + this.addQuickFilterBtn.Click += new System.EventHandler(this.addQuickFilterBtn_Click); + // + // splitContainer1 + // + this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer1.Location = new System.Drawing.Point(0, 0); + this.splitContainer1.Name = "splitContainer1"; + // + // splitContainer1.Panel1 + // + this.splitContainer1.Panel1.Controls.Add(this.panel1); + this.splitContainer1.Panel1.Controls.Add(this.menuStrip1); + this.splitContainer1.Panel1.Controls.Add(this.statusStrip1); + // + // splitContainer1.Panel2 + // + this.splitContainer1.Panel2.Controls.Add(this.processBookQueue1); + this.splitContainer1.Size = new System.Drawing.Size(1463, 640); + this.splitContainer1.SplitterDistance = 1061; + this.splitContainer1.SplitterWidth = 8; + this.splitContainer1.TabIndex = 7; + // + // panel1 + // + this.panel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.panel1.Controls.Add(this.productsDisplay); + this.panel1.Controls.Add(this.toggleQueueHideBtn); + this.panel1.Controls.Add(this.addQuickFilterBtn); + this.panel1.Controls.Add(this.filterHelpBtn); + this.panel1.Controls.Add(this.filterSearchTb); + this.panel1.Controls.Add(this.filterBtn); + this.panel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.panel1.Location = new System.Drawing.Point(0, 24); + this.panel1.Margin = new System.Windows.Forms.Padding(0); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(1061, 594); + this.panel1.TabIndex = 7; + // + // productsDisplay + // + this.productsDisplay.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.productsDisplay.AutoScroll = true; + this.productsDisplay.Location = new System.Drawing.Point(15, 36); + this.productsDisplay.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.productsDisplay.Name = "productsDisplay"; + this.productsDisplay.Size = new System.Drawing.Size(1031, 555); + this.productsDisplay.TabIndex = 9; + this.productsDisplay.VisibleCountChanged += new System.EventHandler(this.productsDisplay_VisibleCountChanged); + this.productsDisplay.LiberateClicked += new System.EventHandler(this.ProductsDisplay_LiberateClicked); + this.productsDisplay.InitialLoaded += new System.EventHandler(this.productsDisplay_InitialLoaded); + // + // toggleQueueHideBtn + // + this.toggleQueueHideBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.toggleQueueHideBtn.Location = new System.Drawing.Point(1013, 3); + this.toggleQueueHideBtn.Margin = new System.Windows.Forms.Padding(4, 3, 15, 3); + this.toggleQueueHideBtn.Name = "toggleQueueHideBtn"; + this.toggleQueueHideBtn.Size = new System.Drawing.Size(33, 27); + this.toggleQueueHideBtn.TabIndex = 8; + this.toggleQueueHideBtn.Text = "❱❱❱"; + this.toggleQueueHideBtn.UseVisualStyleBackColor = true; + this.toggleQueueHideBtn.Click += new System.EventHandler(this.ToggleQueueHideBtn_Click); + // + // processBookQueue1 + // + this.processBookQueue1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.processBookQueue1.Dock = System.Windows.Forms.DockStyle.Fill; + this.processBookQueue1.Location = new System.Drawing.Point(0, 0); + this.processBookQueue1.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); + this.processBookQueue1.Name = "processBookQueue1"; + this.processBookQueue1.Size = new System.Drawing.Size(394, 640); + this.processBookQueue1.TabIndex = 0; + // + // Form1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(1463, 640); + this.Controls.Add(this.splitContainer1); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MainMenuStrip = this.menuStrip1; + this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.Name = "Form1"; + this.Text = "Libation: Liberate your Library"; + this.Load += new System.EventHandler(this.Form1_Load); + this.menuStrip1.ResumeLayout(false); + this.menuStrip1.PerformLayout(); + this.statusStrip1.ResumeLayout(false); + this.statusStrip1.PerformLayout(); + this.splitContainer1.Panel1.ResumeLayout(false); + this.splitContainer1.Panel1.PerformLayout(); + this.splitContainer1.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); + this.splitContainer1.ResumeLayout(false); + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); + this.ResumeLayout(false); } #endregion - - private System.Windows.Forms.Panel gridPanel; private System.Windows.Forms.MenuStrip menuStrip1; private System.Windows.Forms.ToolStripMenuItem importToolStripMenuItem; private System.Windows.Forms.StatusStrip statusStrip1; @@ -581,5 +583,6 @@ private LibationWinForms.ProcessQueue.ProcessQueueControl processBookQueue1; private System.Windows.Forms.Panel panel1; private System.Windows.Forms.Button toggleQueueHideBtn; + private LibationWinForms.GridView.ProductsDisplay productsDisplay; } } diff --git a/Source/LibationWinForms/Form1.Filter.cs b/Source/LibationWinForms/Form1.Filter.cs index 03e89f9d..2a175e74 100644 --- a/Source/LibationWinForms/Form1.Filter.cs +++ b/Source/LibationWinForms/Form1.Filter.cs @@ -30,7 +30,7 @@ namespace LibationWinForms try { - productsGrid.Filter(filterString); + productsDisplay.Filter(filterString); lastGoodFilter = filterString; } catch (Exception ex) diff --git a/Source/LibationWinForms/Form1.PictureStorage.cs b/Source/LibationWinForms/Form1.PictureStorage.cs index 2a6efd09..c400eaf6 100644 --- a/Source/LibationWinForms/Form1.PictureStorage.cs +++ b/Source/LibationWinForms/Form1.PictureStorage.cs @@ -12,6 +12,7 @@ namespace LibationWinForms PictureStorage.SetDefaultImage(PictureSize._80x80, Properties.Resources.default_cover_80x80.ToBytes(format)); PictureStorage.SetDefaultImage(PictureSize._300x300, Properties.Resources.default_cover_300x300.ToBytes(format)); PictureStorage.SetDefaultImage(PictureSize._500x500, Properties.Resources.default_cover_500x500.ToBytes(format)); + PictureStorage.SetDefaultImage(PictureSize.Native, Properties.Resources.default_cover_500x500.ToBytes(format)); } } } diff --git a/Source/LibationWinForms/Form1.ProcessQueue.cs b/Source/LibationWinForms/Form1.ProcessQueue.cs index 74d30406..8a8178f2 100644 --- a/Source/LibationWinForms/Form1.ProcessQueue.cs +++ b/Source/LibationWinForms/Form1.ProcessQueue.cs @@ -14,14 +14,13 @@ namespace LibationWinForms int WidthChange = 0; private void Configure_ProcessQueue() { - productsGrid.LiberateClicked += ProductsGrid_LiberateClicked; processBookQueue1.popoutBtn.Click += ProcessBookQueue1_PopOut; var coppalseState = Configuration.Instance.GetNonString(nameof(splitContainer1.Panel2Collapsed)); WidthChange = splitContainer1.Panel2.Width + splitContainer1.SplitterWidth; SetQueueCollapseState(coppalseState); } - private void ProductsGrid_LiberateClicked(object sender, LibraryBook e) + private void ProductsDisplay_LiberateClicked(object sender, LibraryBook e) { if (e.Book.UserDefinedItem.BookStatus != LiberatedStatus.Liberated) { diff --git a/Source/LibationWinForms/Form1.QuickFilters.cs b/Source/LibationWinForms/Form1.QuickFilters.cs index 8804f083..3908290b 100644 --- a/Source/LibationWinForms/Form1.QuickFilters.cs +++ b/Source/LibationWinForms/Form1.QuickFilters.cs @@ -14,12 +14,6 @@ namespace LibationWinForms Load += updateFiltersMenu; QuickFilters.UseDefaultChanged += updateFirstFilterIsDefaultToolStripMenuItem; QuickFilters.Updated += updateFiltersMenu; - - productsGrid.InitialLoaded += (_, __) => - { - if (QuickFilters.UseDefault) - performFilter(QuickFilters.Filters.FirstOrDefault()); - }; } private object quickFilterTag { get; } = new(); @@ -56,5 +50,11 @@ namespace LibationWinForms private void addQuickFilterBtn_Click(object sender, EventArgs e) => QuickFilters.Add(this.filterSearchTb.Text); private void editQuickFiltersToolStripMenuItem_Click(object sender, EventArgs e) => new EditQuickFilters().ShowDialog(); + + private void productsDisplay_InitialLoaded(object sender, EventArgs e) + { + if (QuickFilters.UseDefault) + performFilter(QuickFilters.Filters.FirstOrDefault()); + } } } diff --git a/Source/LibationWinForms/Form1.VisibleBooks.cs b/Source/LibationWinForms/Form1.VisibleBooks.cs index 65dfecca..a17effa7 100644 --- a/Source/LibationWinForms/Form1.VisibleBooks.cs +++ b/Source/LibationWinForms/Form1.VisibleBooks.cs @@ -17,28 +17,16 @@ namespace LibationWinForms liberateVisibleToolStripMenuItem.Format(0); liberateVisible2ToolStripMenuItem.Format(0); - // bottom-left visible count - productsGrid.VisibleCountChanged += (_, qty) => visibleCountLbl.Format(qty); - // top menu strip visibleBooksToolStripMenuItem.Format(0); - productsGrid.VisibleCountChanged += (_, qty) => { - visibleBooksToolStripMenuItem.Format(qty); - visibleBooksToolStripMenuItem.Enabled = qty > 0; - var notLiberatedCount = productsGrid.GetVisible().Count(lb => lb.Book.UserDefinedItem.BookStatus == DataLayer.LiberatedStatus.NotLiberated); - }; - - productsGrid.VisibleCountChanged += setLiberatedVisibleMenuItemAsync; LibraryCommands.BookUserDefinedItemCommitted += setLiberatedVisibleMenuItemAsync; } - private async void setLiberatedVisibleMenuItemAsync(object _, int __) - => await Task.Run(setLiberatedVisibleMenuItem); private async void setLiberatedVisibleMenuItemAsync(object _, EventArgs __) => await Task.Run(setLiberatedVisibleMenuItem); void setLiberatedVisibleMenuItem() { - var notLiberated = productsGrid.GetVisible().Count(lb => lb.Book.UserDefinedItem.BookStatus == DataLayer.LiberatedStatus.NotLiberated); + var notLiberated = productsDisplay.GetVisible().Count(lb => lb.Book.UserDefinedItem.BookStatus == DataLayer.LiberatedStatus.NotLiberated); this.UIThreadSync(() => { if (notLiberated > 0) @@ -63,7 +51,7 @@ namespace LibationWinForms private async void liberateVisible(object sender, EventArgs e) { SetQueueCollapseState(false); - await Task.Run(() => processBookQueue1.AddDownloadDecrypt(productsGrid.GetVisible())); + await Task.Run(() => processBookQueue1.AddDownloadDecrypt(productsDisplay.GetVisible())); } private void replaceTagsToolStripMenuItem_Click(object sender, EventArgs e) @@ -73,7 +61,7 @@ namespace LibationWinForms if (result != DialogResult.OK) return; - var visibleLibraryBooks = productsGrid.GetVisible(); + var visibleLibraryBooks = productsDisplay.GetVisible(); var confirmationResult = MessageBoxLib.ShowConfirmationDialog( visibleLibraryBooks, @@ -95,7 +83,7 @@ namespace LibationWinForms if (result != DialogResult.OK) return; - var visibleLibraryBooks = productsGrid.GetVisible(); + var visibleLibraryBooks = productsDisplay.GetVisible(); var confirmationResult = MessageBoxLib.ShowConfirmationDialog( visibleLibraryBooks, @@ -112,7 +100,7 @@ namespace LibationWinForms private async void removeToolStripMenuItem_Click(object sender, EventArgs e) { - var visibleLibraryBooks = productsGrid.GetVisible(); + var visibleLibraryBooks = productsDisplay.GetVisible(); var confirmationResult = MessageBoxLib.ShowConfirmationDialog( visibleLibraryBooks, @@ -125,5 +113,20 @@ namespace LibationWinForms var visibleIds = visibleLibraryBooks.Select(lb => lb.Book.AudibleProductId).ToList(); await LibraryCommands.RemoveBooksAsync(visibleIds); } + + private async void productsDisplay_VisibleCountChanged(object sender, int qty) + { + // bottom-left visible count + visibleCountLbl.Format(qty); + + // top menu strip + visibleBooksToolStripMenuItem.Format(qty); + visibleBooksToolStripMenuItem.Enabled = qty > 0; + + //Not used for anything? + var notLiberatedCount = productsDisplay.GetVisible().Count(lb => lb.Book.UserDefinedItem.BookStatus == DataLayer.LiberatedStatus.NotLiberated); + + await Task.Run(setLiberatedVisibleMenuItem); + } } } diff --git a/Source/LibationWinForms/Form1.cs b/Source/LibationWinForms/Form1.cs index 04150167..43151f73 100644 --- a/Source/LibationWinForms/Form1.cs +++ b/Source/LibationWinForms/Form1.cs @@ -12,24 +12,10 @@ namespace LibationWinForms { public partial class Form1 : Form { - private ProductsGrid productsGrid { get; } - public Form1() { InitializeComponent(); - if (this.DesignMode) - return; - - { - // I'd actually like these lines to be handled in the designer, but I'm currently getting this error when I try: - // Failed to create component 'ProductsGrid'. The error message follows: - // 'Microsoft.DotNet.DesignTools.Client.DesignToolsServerException: Object reference not set to an instance of an object. - // Since the designer's choking on it, I'm keeping it below the DesignMode check to be safe - productsGrid = new ProductsGrid { Dock = DockStyle.Fill }; - gridPanel.Controls.Add(productsGrid); - } - // Pre-requisite: // Before calling anything else, including subscribing to events, ensure database exists. If we wait and let it happen lazily, race conditions and errors are likely during new installs using var _ = DbContexts.GetContext(); @@ -67,8 +53,8 @@ namespace LibationWinForms // Configure_Grid(); // since it's just this, can keep here. If it needs more, then give grid it's own 'partial class Form1' { - this.Load += (_, __) => productsGrid.Display(); - LibraryCommands.LibrarySizeChanged += (_, __) => this.UIThreadAsync(() => productsGrid.Display()); + this.Load += (_, __) => productsDisplay.Display(); + LibraryCommands.LibrarySizeChanged += (_, __) => this.UIThreadAsync(() => productsDisplay.Display()); } } diff --git a/Source/LibationWinForms/Form1.resx b/Source/LibationWinForms/Form1.resx index 64da6d15..2505fa27 100644 --- a/Source/LibationWinForms/Form1.resx +++ b/Source/LibationWinForms/Form1.resx @@ -57,12 +57,48 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + True + + + True + + + True + 17, 17 + + True + 132, 17 + + True + + + True + + + True + + + True + + + True + + + True + + + True + + + True + diff --git a/Source/LibationWinForms/grid/AsyncNotifyPropertyChanged.cs b/Source/LibationWinForms/GridView/AsyncNotifyPropertyChanged.cs similarity index 94% rename from Source/LibationWinForms/grid/AsyncNotifyPropertyChanged.cs rename to Source/LibationWinForms/GridView/AsyncNotifyPropertyChanged.cs index cce5e5b9..e4532cfe 100644 --- a/Source/LibationWinForms/grid/AsyncNotifyPropertyChanged.cs +++ b/Source/LibationWinForms/GridView/AsyncNotifyPropertyChanged.cs @@ -2,7 +2,7 @@ using System.ComponentModel; using System.Runtime.CompilerServices; -namespace LibationWinForms +namespace LibationWinForms.GridView { public abstract class AsyncNotifyPropertyChanged : SynchronizeInvoker, INotifyPropertyChanged { diff --git a/Source/LibationWinForms/grid/DataGridViewImageButtonCell.cs b/Source/LibationWinForms/GridView/DataGridViewImageButtonCell.cs similarity index 92% rename from Source/LibationWinForms/grid/DataGridViewImageButtonCell.cs rename to Source/LibationWinForms/GridView/DataGridViewImageButtonCell.cs index f4f25afd..d53b02ed 100644 --- a/Source/LibationWinForms/grid/DataGridViewImageButtonCell.cs +++ b/Source/LibationWinForms/GridView/DataGridViewImageButtonCell.cs @@ -1,7 +1,7 @@ using System.Drawing; using System.Windows.Forms; -namespace LibationWinForms +namespace LibationWinForms.GridView { public class DataGridViewImageButtonCell : DataGridViewButtonCell { diff --git a/Source/LibationWinForms/grid/DescriptionDisplay.Designer.cs b/Source/LibationWinForms/GridView/DescriptionDisplay.Designer.cs similarity index 98% rename from Source/LibationWinForms/grid/DescriptionDisplay.Designer.cs rename to Source/LibationWinForms/GridView/DescriptionDisplay.Designer.cs index 96012e50..be8d9496 100644 --- a/Source/LibationWinForms/grid/DescriptionDisplay.Designer.cs +++ b/Source/LibationWinForms/GridView/DescriptionDisplay.Designer.cs @@ -1,4 +1,4 @@ -namespace LibationWinForms +namespace LibationWinForms.GridView { partial class DescriptionDisplay { diff --git a/Source/LibationWinForms/grid/DescriptionDisplay.cs b/Source/LibationWinForms/GridView/DescriptionDisplay.cs similarity index 92% rename from Source/LibationWinForms/grid/DescriptionDisplay.cs rename to Source/LibationWinForms/GridView/DescriptionDisplay.cs index 3f95a92e..d3aefd52 100644 --- a/Source/LibationWinForms/grid/DescriptionDisplay.cs +++ b/Source/LibationWinForms/GridView/DescriptionDisplay.cs @@ -1,17 +1,15 @@ using System; -using System.ComponentModel; using System.Drawing; -using System.Linq; using System.Runtime.InteropServices; using System.Windows.Forms; -namespace LibationWinForms +namespace LibationWinForms.GridView { public partial class DescriptionDisplay : Form { private int borderThickness = 5; - public int BorderThickness + public int BorderThickness { get => borderThickness; set diff --git a/Source/LibationWinForms/grid/DescriptionDisplay.resx b/Source/LibationWinForms/GridView/DescriptionDisplay.resx similarity index 100% rename from Source/LibationWinForms/grid/DescriptionDisplay.resx rename to Source/LibationWinForms/GridView/DescriptionDisplay.resx diff --git a/Source/LibationWinForms/grid/EditTagsDataGridViewImageButtonColumn.cs b/Source/LibationWinForms/GridView/EditTagsDataGridViewImageButtonColumn.cs similarity index 79% rename from Source/LibationWinForms/grid/EditTagsDataGridViewImageButtonColumn.cs rename to Source/LibationWinForms/GridView/EditTagsDataGridViewImageButtonColumn.cs index 1349325a..065afdbb 100644 --- a/Source/LibationWinForms/grid/EditTagsDataGridViewImageButtonColumn.cs +++ b/Source/LibationWinForms/GridView/EditTagsDataGridViewImageButtonColumn.cs @@ -1,7 +1,8 @@ -using System.Drawing; +using Dinah.Core.Windows.Forms; +using System.Drawing; using System.Windows.Forms; -namespace LibationWinForms +namespace LibationWinForms.GridView { public class EditTagsDataGridViewImageButtonColumn : DataGridViewButtonColumn { @@ -18,6 +19,12 @@ namespace LibationWinForms protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates elementState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts) { + if (rowIndex >= 0 && DataGridView.GetBoundItem(rowIndex) is SeriesEntry) + { + base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, null, null, null, cellStyle, advancedBorderStyle, DataGridViewPaintParts.Background | DataGridViewPaintParts.Border); + return; + } + var tagsString = (string)value; var foreColor = tagsString?.Contains("hidden") == true ? HiddenForeColor : DataGridView.DefaultCellStyle.ForeColor; diff --git a/Source/LibationWinForms/GridView/GridEntry.cs b/Source/LibationWinForms/GridView/GridEntry.cs new file mode 100644 index 00000000..6d7e9cd8 --- /dev/null +++ b/Source/LibationWinForms/GridView/GridEntry.cs @@ -0,0 +1,113 @@ +using DataLayer; +using Dinah.Core.DataBinding; +using Dinah.Core.Drawing; +using LibationFileManager; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; + +namespace LibationWinForms.GridView +{ + public abstract class GridEntry : AsyncNotifyPropertyChanged, IMemberComparable + { + protected abstract Book Book { get; } + + private Image _cover; + #region Model properties exposed to the view + public Image Cover + { + get => _cover; + protected set + { + _cover = value; + NotifyPropertyChanged(); + } + } + public new bool InvokeRequired => base.InvokeRequired; + public abstract DateTime DateAdded { get; } + public abstract float SeriesIndex { get; } + public abstract string ProductRating { get; protected set; } + public abstract string PurchaseDate { get; protected set; } + public abstract string MyRating { get; protected set; } + public abstract string Series { get; protected set; } + public abstract string Title { get; protected set; } + public abstract string Length { get; protected set; } + public abstract string Authors { get; protected set; } + public abstract string Narrators { get; protected set; } + public abstract string Category { get; protected set; } + public abstract string Misc { get; protected set; } + public abstract string Description { get; protected set; } + public abstract string DisplayTags { get; } + public abstract LiberateButtonStatus Liberate { get; } + #endregion + + #region Sorting + + public GridEntry() => _memberValues = CreateMemberValueDictionary(); + private Dictionary> _memberValues { get; set; } + protected abstract Dictionary> CreateMemberValueDictionary(); + + // These methods are implementation of Dinah.Core.DataBinding.IMemberComparable + // Used by GridEntryBindingList for all sorting + public virtual object GetMemberValue(string memberName) => _memberValues[memberName](); + public IComparer GetMemberComparer(Type memberType) => _memberTypeComparers[memberType]; + + #endregion + + protected void LoadCover() + { + // Get cover art. If it's default, subscribe to PictureCached + { + (bool isDefault, byte[] picture) = PictureStorage.GetPicture(new PictureDefinition(Book.PictureId, PictureSize._80x80)); + + if (isDefault) + PictureStorage.PictureCached += PictureStorage_PictureCached; + + // Mutable property. Set the field so PropertyChanged isn't fired. + _cover = ImageReader.ToImage(picture); + } + } + + private void PictureStorage_PictureCached(object sender, PictureCachedEventArgs e) + { + if (e.Definition.PictureId == Book.PictureId) + { + Cover = ImageReader.ToImage(e.Picture); + PictureStorage.PictureCached -= PictureStorage_PictureCached; + } + } + + // Instantiate comparers for every exposed member object type. + private static readonly Dictionary _memberTypeComparers = new() + { + { typeof(string), new ObjectComparer() }, + { typeof(int), new ObjectComparer() }, + { typeof(float), new ObjectComparer() }, + { typeof(bool), new ObjectComparer() }, + { typeof(DateTime), new ObjectComparer() }, + { typeof(LiberateButtonStatus), new ObjectComparer() }, + }; + + ~GridEntry() + { + PictureStorage.PictureCached -= PictureStorage_PictureCached; + } + } + + internal static class GridEntryExtensions + { +#nullable enable + public static IEnumerable Series(this IEnumerable gridEntries) + => gridEntries.Where(i => i is SeriesEntry).Cast(); + public static IEnumerable LibraryBooks(this IEnumerable gridEntries) + => gridEntries.Where(i => i is LibraryBookEntry).Cast(); + public static LibraryBookEntry? FindBookByAsin(this IEnumerable gridEntries, string audibleProductID) + => gridEntries.FirstOrDefault(i => i.AudibleProductId == audibleProductID); + public static SeriesEntry? FindBookSeriesEntry(this IEnumerable gridEntries, IEnumerable matchSeries) + => gridEntries.Series().FirstOrDefault(i => matchSeries.Any(s => s.Series.Name == i.Series)); + public static IEnumerable EmptySeries(this IEnumerable gridEntries) + => gridEntries.Series().Where(i => i.Children.Count == 0); + } +} diff --git a/Source/LibationWinForms/GridView/GridEntryBindingList.cs b/Source/LibationWinForms/GridView/GridEntryBindingList.cs new file mode 100644 index 00000000..b5ee0f8f --- /dev/null +++ b/Source/LibationWinForms/GridView/GridEntryBindingList.cs @@ -0,0 +1,231 @@ +using ApplicationServices; +using Dinah.Core.DataBinding; +using LibationSearchEngine; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; + +namespace LibationWinForms.GridView +{ + /* + * Allows filtering and sorting of the underlying BindingList + * by implementing IBindingListView and using SearchEngineCommands + * + * When filtering is applied, the filtered-out items are removed + * from the base list and added to the private FilterRemoved list. + * When filtering is removed, items in the FilterRemoved list are + * added back to the base list. + * + * Remove is overridden to ensure that removed items are removed from + * the base list (visible items) as well as the FilterRemoved list. + */ + internal class GridEntryBindingList : BindingList, IBindingListView + { + public GridEntryBindingList() : base(new List()) { } + public GridEntryBindingList(IEnumerable enumeration) : base(new List(enumeration)) { } + + /// All items in the list, including those filtered out. + public List AllItems() => Items.Concat(FilterRemoved).ToList(); + public bool SupportsFiltering => true; + public string Filter { get => FilterString; set => ApplyFilter(value); } + + protected MemberComparer 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; + + /// Items that were removed from the base list due to filtering + private readonly List FilterRemoved = new(); + private string FilterString; + private SearchResultSet SearchResults; + private bool isSorted; + private ListSortDirection listSortDirection; + private PropertyDescriptor propertyDescriptor; + + + #region Unused - Advanced Filtering + public bool SupportsAdvancedSorting => false; + + //This ApplySort overload is only called if SupportsAdvancedSorting is true. + //Otherwise BindingList.ApplySort() is used + public void ApplySort(ListSortDescriptionCollection sorts) => throw new NotImplementedException(); + + public ListSortDescriptionCollection SortDescriptions => throw new NotImplementedException(); + #endregion + + public new void Remove(GridEntry entry) + { + FilterRemoved.Remove(entry); + base.Remove(entry); + } + + private void ApplyFilter(string filterString) + { + if (filterString != FilterString) + RemoveFilter(); + + FilterString = filterString; + SearchResults = SearchEngineCommands.Search(filterString); + + var booksFilteredIn = Items.LibraryBooks().Join(SearchResults.Docs, lbe => lbe.AudibleProductId, d => d.ProductId, (lbe, d) => (GridEntry)lbe); + + //Find all series containing children that match the search criteria + var seriesFilteredIn = Items.Series().Where(s => s.Children.Join(SearchResults.Docs, lbe => lbe.AudibleProductId, d => d.ProductId, (lbe, d) => lbe).Any()); + + var filteredOut = Items.Except(booksFilteredIn.Concat(seriesFilteredIn)).ToList(); + + foreach (var item in filteredOut) + { + FilterRemoved.Add(item); + base.Remove(item); + } + } + + public void CollapseAll() + { + foreach (var series in Items.Series().ToList()) + CollapseItem(series); + } + + public void ExpandAll() + { + foreach (var series in Items.Series().ToList()) + ExpandItem(series); + } + + public void CollapseItem(SeriesEntry sEntry) + { + foreach (var episode in Items.LibraryBooks().Where(b => b.Parent == sEntry).ToList()) + { + FilterRemoved.Add(episode); + base.Remove(episode); + } + + sEntry.Liberate.Expanded = false; + } + + public void ExpandItem(SeriesEntry sEntry) + { + var sindex = Items.IndexOf(sEntry); + + foreach (var episode in FilterRemoved.LibraryBooks().Where(b => b.Parent == sEntry).ToList()) + { + if (SearchResults is null || SearchResults.Docs.Any(d => d.ProductId == episode.AudibleProductId)) + { + FilterRemoved.Remove(episode); + InsertItem(++sindex, episode); + } + } + sEntry.Liberate.Expanded = true; + } + + public void RemoveFilter() + { + if (FilterString is null) return; + + int visibleCount = Items.Count; + + foreach (var item in FilterRemoved.ToList()) + { + if (item is SeriesEntry || (item is LibraryBookEntry lbe && (lbe.Parent is null || lbe.Parent.Liberate.Expanded))) + { + FilterRemoved.Remove(item); + InsertItem(visibleCount++, item); + } + } + + if (IsSortedCore) + Sort(); + else + //No user sort is applied, so do default sorting by DateAdded, descending + { + Comparer.PropertyName = nameof(GridEntry.DateAdded); + Comparer.Direction = ListSortDirection.Descending; + Sort(); + } + + OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1)); + + FilterString = 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)Items; + + var children = itemsList.LibraryBooks().Where(i => i.Parent is not null).ToList(); + + var sortedItems = itemsList.Except(children).OrderBy(ge => ge, Comparer).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); + + foreach (var parent in children.Select(c => c.Parent).Distinct()) + { + var pIndex = itemsList.IndexOf(parent); + + //children should always be sorted by series index. + foreach (var c in children.Where(c => c.Parent == parent).OrderBy(c => c.SeriesIndex)) + itemsList.Insert(++pIndex, c); + } + } + + protected override void OnListChanged(ListChangedEventArgs e) + { + if (e.ListChangedType == ListChangedType.ItemChanged) + { + if (Items[e.NewIndex] is LibraryBookEntry lbItem) + { + SearchResults = SearchEngineCommands.Search(FilterString); + if (!SearchResults.Docs.Any(d => d.ProductId == lbItem.AudibleProductId)) + { + FilterRemoved.Add(lbItem); + base.Remove(lbItem); + return; + } + } + + if (isSorted && e.PropertyDescriptor == SortPropertyCore) + { + var item = Items[e.NewIndex]; + Sort(); + var newIndex = Items.IndexOf(item); + + base.OnListChanged(new ListChangedEventArgs(ListChangedType.ItemMoved, newIndex, e.NewIndex)); + return; + } + } + base.OnListChanged(e); + } + + protected override void RemoveSortCore() + { + isSorted = false; + propertyDescriptor = base.SortPropertyCore; + listSortDirection = base.SortDirectionCore; + + OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1)); + } + } +} diff --git a/Source/LibationWinForms/grid/ImageDisplay.Designer.cs b/Source/LibationWinForms/GridView/ImageDisplay.Designer.cs similarity index 98% rename from Source/LibationWinForms/grid/ImageDisplay.Designer.cs rename to Source/LibationWinForms/GridView/ImageDisplay.Designer.cs index ec1dbdf0..a1ca5caa 100644 --- a/Source/LibationWinForms/grid/ImageDisplay.Designer.cs +++ b/Source/LibationWinForms/GridView/ImageDisplay.Designer.cs @@ -1,4 +1,4 @@ -namespace LibationWinForms +namespace LibationWinForms.GridView { partial class ImageDisplay { diff --git a/Source/LibationWinForms/grid/ImageDisplay.cs b/Source/LibationWinForms/GridView/ImageDisplay.cs similarity index 97% rename from Source/LibationWinForms/grid/ImageDisplay.cs rename to Source/LibationWinForms/GridView/ImageDisplay.cs index 53f75987..831b8ec9 100644 --- a/Source/LibationWinForms/grid/ImageDisplay.cs +++ b/Source/LibationWinForms/GridView/ImageDisplay.cs @@ -1,11 +1,9 @@ -using FileLiberator; -using LibationFileManager; -using System; +using System; using System.Drawing; using System.IO; using System.Windows.Forms; -namespace LibationWinForms +namespace LibationWinForms.GridView { public partial class ImageDisplay : Form { diff --git a/Source/LibationWinForms/grid/ImageDisplay.resx b/Source/LibationWinForms/GridView/ImageDisplay.resx similarity index 100% rename from Source/LibationWinForms/grid/ImageDisplay.resx rename to Source/LibationWinForms/GridView/ImageDisplay.resx diff --git a/Source/LibationWinForms/GridView/LiberateButtonStatus.cs b/Source/LibationWinForms/GridView/LiberateButtonStatus.cs new file mode 100644 index 00000000..21c207d0 --- /dev/null +++ b/Source/LibationWinForms/GridView/LiberateButtonStatus.cs @@ -0,0 +1,28 @@ +using DataLayer; +using System; + +namespace LibationWinForms.GridView +{ + public class LiberateButtonStatus : IComparable + { + public LiberatedStatus BookStatus { get; set; } + public LiberatedStatus? PdfStatus { get; set; } + public bool Expanded { get; set; } + public bool IsSeries { get; init; } + + /// + /// Defines the Liberate column's sorting behavior + /// + 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); + } + } +} diff --git a/Source/LibationWinForms/grid/LiberateDataGridViewImageButtonColumn.cs b/Source/LibationWinForms/GridView/LiberateDataGridViewImageButtonColumn.cs similarity index 69% rename from Source/LibationWinForms/grid/LiberateDataGridViewImageButtonColumn.cs rename to Source/LibationWinForms/GridView/LiberateDataGridViewImageButtonColumn.cs index e5ab82b8..62c56538 100644 --- a/Source/LibationWinForms/grid/LiberateDataGridViewImageButtonColumn.cs +++ b/Source/LibationWinForms/GridView/LiberateDataGridViewImageButtonColumn.cs @@ -1,10 +1,10 @@ -using System; +using DataLayer; +using Dinah.Core.Windows.Forms; +using System; using System.Drawing; using System.Windows.Forms; -using System.Linq; -using DataLayer; -namespace LibationWinForms +namespace LibationWinForms.GridView { public class LiberateDataGridViewImageButtonColumn : DataGridViewButtonColumn { @@ -16,19 +16,35 @@ namespace LibationWinForms internal class LiberateDataGridViewImageButtonCell : DataGridViewImageButtonCell { + private static readonly Color SERIES_BG_COLOR = Color.FromArgb(230, 255, 230); protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates elementState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts) { base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, null, null, null, cellStyle, advancedBorderStyle, paintParts); - if (value is (LiberatedStatus, LiberatedStatus) or (LiberatedStatus, null)) + if (value is LiberateButtonStatus status) { - var (bookState, pdfState) = ((LiberatedStatus bookState, LiberatedStatus? pdfState))value; + if (rowIndex >= 0 && DataGridView.GetBoundItem(rowIndex) is LibraryBookEntry lbEntry && lbEntry.Parent is not null) + { + DataGridView.Rows[rowIndex].DefaultCellStyle.BackColor = SERIES_BG_COLOR; + } - (string mouseoverText, Bitmap buttonImage) = GetLiberateDisplay(bookState, pdfState); + if (status.IsSeries) + { + var imageName = status.Expanded ? "minus" : "plus"; - DrawButtonImage(graphics, buttonImage, cellBounds); + var bmp = (Bitmap)Properties.Resources.ResourceManager.GetObject(imageName); + DrawButtonImage(graphics, bmp, cellBounds); - ToolTipText = mouseoverText; + ToolTipText = status.Expanded ? "Click to Collpase" : "Click to Expand"; + } + else + { + (string mouseoverText, Bitmap buttonImage) = GetLiberateDisplay(status.BookStatus, status.PdfStatus); + + DrawButtonImage(graphics, buttonImage, cellBounds); + + ToolTipText = mouseoverText; + } } } diff --git a/Source/LibationWinForms/grid/GridEntry.cs b/Source/LibationWinForms/GridView/LibraryBookEntry.cs similarity index 64% rename from Source/LibationWinForms/grid/GridEntry.cs rename to Source/LibationWinForms/GridView/LibraryBookEntry.cs index 3e02dc93..6a312ea1 100644 --- a/Source/LibationWinForms/grid/GridEntry.cs +++ b/Source/LibationWinForms/GridView/LibraryBookEntry.cs @@ -1,23 +1,17 @@ -using System; -using System.Collections; +using ApplicationServices; +using DataLayer; +using Dinah.Core; +using System; using System.Collections.Generic; using System.ComponentModel; -using System.Drawing; using System.Linq; -using ApplicationServices; -using DataLayer; -using Dinah.Core.DataBinding; -using Dinah.Core; -using Dinah.Core.Drawing; -using LibationFileManager; -using System.Threading.Tasks; -namespace LibationWinForms +namespace LibationWinForms.GridView { /// /// The View Model for a LibraryBook /// - internal class GridEntry : AsyncNotifyPropertyChanged, IMemberComparable + public class LibraryBookEntry : GridEntry { #region implementation properties NOT exposed to the view // hide from public fields from Data Source GUI with [Browsable(false)] @@ -30,37 +24,30 @@ namespace LibationWinForms public string LongDescription { get; private set; } #endregion + protected override Book Book => LibraryBook.Book; #region Model properties exposed to the view - private Image _cover; private DateTime lastStatusUpdate = default; private LiberatedStatus _bookStatus; private LiberatedStatus? _pdfStatus; - public Image Cover - { - get => _cover; - private set - { - _cover = value; - NotifyPropertyChanged(); - } - } - public string ProductRating { get; private set; } - public string PurchaseDate { get; private set; } - public string MyRating { get; private set; } - public string Series { get; private set; } - public string Title { get; private set; } - public string Length { get; private set; } - public string Authors { get; private set; } - public string Narrators { get; private set; } - public string Category { get; private set; } - public string Misc { get; private set; } - public string Description { get; private set; } - public string DisplayTags => string.Join("\r\n", Book.UserDefinedItem.TagsEnumerated); + public override DateTime DateAdded => LibraryBook.DateAdded; + public override float SeriesIndex => Book.SeriesLink.FirstOrDefault()?.Index ?? 0; + public override string ProductRating { get; protected set; } + public override string PurchaseDate { get; protected set; } + public override string MyRating { get; protected set; } + public override string Series { get; protected set; } + public override string Title { get; protected set; } + public override string Length { get; protected set; } + public override string Authors { get; protected set; } + public override string Narrators { get; protected set; } + public override string Category { get; protected set; } + public override string Misc { get; protected set; } + public override string Description { get; protected set; } + public override string DisplayTags => string.Join("\r\n", Book.UserDefinedItem.TagsEnumerated); // these 2 values being in 1 field is the trick behind getting the liberated+pdf 'stoplight' icon to draw. See: LiberateDataGridViewImageButtonCell.Paint - public (LiberatedStatus BookStatus, LiberatedStatus? PdfStatus) Liberate + public override LiberateButtonStatus Liberate { get { @@ -71,16 +58,14 @@ namespace LibationWinForms _pdfStatus = LibraryCommands.Pdf_Status(LibraryBook.Book); lastStatusUpdate = DateTime.Now; } - return (_bookStatus, _pdfStatus); + return new LiberateButtonStatus { BookStatus = _bookStatus, PdfStatus = _pdfStatus, IsSeries = false }; } } #endregion - // alias - private Book Book => LibraryBook.Book; - - public GridEntry(LibraryBook libraryBook) => setLibraryBook(libraryBook); + public LibraryBookEntry(LibraryBook libraryBook) => setLibraryBook(libraryBook); + public SeriesEntry Parent { get; init; } public void UpdateLibraryBook(LibraryBook libraryBook) { if (AudibleProductId != libraryBook.Book.AudibleProductId) @@ -93,19 +78,9 @@ namespace LibationWinForms private void setLibraryBook(LibraryBook libraryBook) { - LibraryBook = libraryBook; - _memberValues = CreateMemberValueDictionary(); + LibraryBook = libraryBook; - // Get cover art. If it's default, subscribe to PictureCached - { - (bool isDefault, byte[] picture) = PictureStorage.GetPicture(new PictureDefinition(Book.PictureId, PictureSize._80x80)); - - if (isDefault) - PictureStorage.PictureCached += PictureStorage_PictureCached; - - // Mutable property. Set the field so PropertyChanged isn't fired. - _cover = ImageReader.ToImage(picture); - } + LoadCover(); // Immutable properties { @@ -126,14 +101,6 @@ namespace LibationWinForms UserDefinedItem.ItemChanged += UserDefinedItem_ItemChanged; } - private void PictureStorage_PictureCached(object sender, PictureCachedEventArgs e) - { - if (e.Definition.PictureId == Book.PictureId) - { - Cover = ImageReader.ToImage(e.Picture); - PictureStorage.PictureCached -= PictureStorage_PictureCached; - } - } #region detect changes to the model, update the view, and save to database. @@ -152,16 +119,19 @@ namespace LibationWinForms { case nameof(udi.Tags): Book.UserDefinedItem.Tags = udi.Tags; + SearchEngineCommands.UpdateBookTags(Book); NotifyPropertyChanged(nameof(DisplayTags)); break; case nameof(udi.BookStatus): Book.UserDefinedItem.BookStatus = udi.BookStatus; _bookStatus = udi.BookStatus; + SearchEngineCommands.UpdateLiberatedStatus(Book); NotifyPropertyChanged(nameof(Liberate)); break; case nameof(udi.PdfStatus): Book.UserDefinedItem.PdfStatus = udi.PdfStatus; _pdfStatus = udi.PdfStatus; + SearchEngineCommands.UpdateLiberatedStatus(Book); NotifyPropertyChanged(nameof(Liberate)); break; } @@ -190,17 +160,9 @@ namespace LibationWinForms #endregion #region Data Sorting - // These methods are implementation of Dinah.Core.DataBinding.IMemberComparable - // Used by Dinah.Core.DataBinding.SortableBindingList for all sorting - public virtual object GetMemberValue(string memberName) => _memberValues[memberName](); - public virtual IComparer GetMemberComparer(Type memberType) => _memberTypeComparers[memberType]; - private Dictionary> _memberValues { get; set; } - - /// - /// Create getters for all member object values by name - /// - private Dictionary> CreateMemberValueDictionary() => new() + /// Create getters for all member object values by name + protected override Dictionary> CreateMemberValueDictionary() => new() { { nameof(Title), () => Book.TitleSortable() }, { nameof(Series), () => Book.SeriesSortable() }, @@ -214,25 +176,17 @@ namespace LibationWinForms { nameof(Category), () => Category }, { nameof(Misc), () => Misc }, { nameof(DisplayTags), () => DisplayTags }, - { nameof(Liberate), () => Liberate.BookStatus } + { nameof(Liberate), () => Liberate }, + { nameof(DateAdded), () => DateAdded }, }; - // Instantiate comparers for every exposed member object type. - private static readonly Dictionary _memberTypeComparers = new() - { - { typeof(string), new ObjectComparer() }, - { typeof(int), new ObjectComparer() }, - { typeof(float), new ObjectComparer() }, - { typeof(DateTime), new ObjectComparer() }, - { typeof(LiberatedStatus), new ObjectComparer() }, - }; #endregion #region Static library display functions /// - /// This information should not change during lifetime, so call only once. + /// This information should not change during lifetime, so call only once. /// private static string GetDescriptionDisplay(Book book) { @@ -250,7 +204,7 @@ namespace LibationWinForms } /// - /// This information should not change during lifetime, so call only once. + /// This information should not change during lifetime, so call only once. /// Maximum of 5 text rows will fit in 80-pixel row height. /// private static string GetMiscDisplay(LibraryBook libraryBook) @@ -280,10 +234,9 @@ namespace LibationWinForms #endregion - ~GridEntry() + ~LibraryBookEntry() { UserDefinedItem.ItemChanged -= UserDefinedItem_ItemChanged; - PictureStorage.PictureCached -= PictureStorage_PictureCached; } } } diff --git a/Source/LibationWinForms/GridView/ProductsDisplay.Designer.cs b/Source/LibationWinForms/GridView/ProductsDisplay.Designer.cs new file mode 100644 index 00000000..c4b1a543 --- /dev/null +++ b/Source/LibationWinForms/GridView/ProductsDisplay.Designer.cs @@ -0,0 +1,64 @@ +namespace LibationWinForms.GridView +{ + partial class ProductsDisplay + { + /// + /// 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 Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.productsGrid = new LibationWinForms.GridView.ProductsGrid(); + this.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.LiberateClicked += new LibationWinForms.GridView.ProductsGrid.LibraryBookEntryClickedEventHandler(this.productsGrid_LiberateClicked); + this.productsGrid.CoverClicked += new LibationWinForms.GridView.ProductsGrid.LibraryBookEntryClickedEventHandler(this.productsGrid_CoverClicked); + this.productsGrid.DetailsClicked += new LibationWinForms.GridView.ProductsGrid.LibraryBookEntryClickedEventHandler(this.productsGrid_DetailsClicked); + this.productsGrid.DescriptionClicked += new LibationWinForms.GridView.ProductsGrid.LibraryBookEntryRectangleClickedEventHandler(this.productsGrid_DescriptionClicked); + this.productsGrid.VisibleCountChanged += new System.EventHandler(this.productsGrid_VisibleCountChanged); + // + // 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); + + } + + #endregion + + private GridView.ProductsGrid productsGrid; + } +} diff --git a/Source/LibationWinForms/GridView/ProductsDisplay.cs b/Source/LibationWinForms/GridView/ProductsDisplay.cs new file mode 100644 index 00000000..7e1b2d8a --- /dev/null +++ b/Source/LibationWinForms/GridView/ProductsDisplay.cs @@ -0,0 +1,123 @@ +using ApplicationServices; +using DataLayer; +using FileLiberator; +using LibationFileManager; +using LibationWinForms.Dialogs; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace LibationWinForms.GridView +{ + public partial class ProductsDisplay : UserControl + { + /// Number of visible rows has changed + public event EventHandler VisibleCountChanged; + public event EventHandler LiberateClicked; + public event EventHandler InitialLoaded; + + private bool hasBeenDisplayed; + + public ProductsDisplay() + { + InitializeComponent(); + } + + #region Button controls + + private ImageDisplay imageDisplay; + private async void productsGrid_CoverClicked(LibraryBookEntry liveGridEntry) + { + var picDefinition = new PictureDefinition(liveGridEntry.LibraryBook.Book.PictureLarge ?? liveGridEntry.LibraryBook.Book.PictureId, PictureSize.Native); + var picDlTask = Task.Run(() => PictureStorage.GetPictureSynchronously(picDefinition)); + + (_, byte[] initialImageBts) = PictureStorage.GetPicture(new PictureDefinition(liveGridEntry.LibraryBook.Book.PictureId, PictureSize._80x80)); + var windowTitle = $"{liveGridEntry.Title} - Cover"; + + 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 productsGrid_DescriptionClicked(LibraryBookEntry liveGridEntry, Rectangle cellRectangle) + { + var displayWindow = new DescriptionDisplay + { + SpawnLocation = PointToScreen(cellRectangle.Location + new Size(cellRectangle.Width, 0)), + DescriptionText = liveGridEntry.LongDescription, + BorderThickness = 2, + }; + + void CloseWindow(object o, EventArgs e) + { + displayWindow.Close(); + } + + productsGrid.Scroll += CloseWindow; + displayWindow.FormClosed += (_, _) => productsGrid.Scroll -= CloseWindow; + displayWindow.Show(this); + } + + private void productsGrid_DetailsClicked(LibraryBookEntry liveGridEntry) + { + var bookDetailsForm = new BookDetailsDialog(liveGridEntry.LibraryBook); + if (bookDetailsForm.ShowDialog() == DialogResult.OK) + liveGridEntry.Commit(bookDetailsForm.NewTags, bookDetailsForm.BookLiberatedStatus, bookDetailsForm.PdfLiberatedStatus); + } + + #endregion + + #region UI display functions + + public void Display() + { + // don't return early if lib size == 0. this will not update correctly if all books are removed + var lib = DbContexts.GetLibrary_Flat_NoTracking(); + + if (!hasBeenDisplayed) + { + // bind + productsGrid.BindToGrid(lib); + hasBeenDisplayed = true; + InitialLoaded?.Invoke(this, new()); + } + else + productsGrid.UpdateGrid(lib); + + } + + #endregion + + #region Filter + + public void Filter(string searchString) + => productsGrid.Filter(searchString); + + #endregion + + internal List GetVisible() => productsGrid.GetVisible().Select(v => v.LibraryBook).ToList(); + + private void productsGrid_VisibleCountChanged(object sender, int count) + { + VisibleCountChanged?.Invoke(this, count); + } + + private void productsGrid_LiberateClicked(LibraryBookEntry liveGridEntry) + { + LiberateClicked?.Invoke(this, liveGridEntry.LibraryBook); + } + } +} diff --git a/Source/LibationWinForms/GridView/ProductsDisplay.resx b/Source/LibationWinForms/GridView/ProductsDisplay.resx new file mode 100644 index 00000000..be5db7af --- /dev/null +++ b/Source/LibationWinForms/GridView/ProductsDisplay.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 + + + 81 + + \ No newline at end of file diff --git a/Source/LibationWinForms/grid/ProductsGrid.Designer.cs b/Source/LibationWinForms/GridView/ProductsGrid.Designer.cs similarity index 81% rename from Source/LibationWinForms/grid/ProductsGrid.Designer.cs rename to Source/LibationWinForms/GridView/ProductsGrid.Designer.cs index b3eaecd5..b380ff95 100644 --- a/Source/LibationWinForms/grid/ProductsGrid.Designer.cs +++ b/Source/LibationWinForms/GridView/ProductsGrid.Designer.cs @@ -1,4 +1,4 @@ -namespace LibationWinForms +namespace LibationWinForms.GridView { partial class ProductsGrid { @@ -29,10 +29,9 @@ private void InitializeComponent() { this.components = new System.ComponentModel.Container(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle(); - this.gridEntryBindingSource = new LibationWinForms.SyncBindingSource(this.components); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle(); this.gridEntryDataGridView = new System.Windows.Forms.DataGridView(); - this.liberateGVColumn = new LibationWinForms.LiberateDataGridViewImageButtonColumn(); + this.liberateGVColumn = new LibationWinForms.GridView.LiberateDataGridViewImageButtonColumn(); this.coverGVColumn = new System.Windows.Forms.DataGridViewImageColumn(); this.titleGVColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); this.authorsGVColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); @@ -45,16 +44,13 @@ this.purchaseDateGVColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); this.myRatingGVColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); this.miscGVColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.tagAndDetailsGVColumn = new LibationWinForms.EditTagsDataGridViewImageButtonColumn(); + this.tagAndDetailsGVColumn = new LibationWinForms.GridView.EditTagsDataGridViewImageButtonColumn(); this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); - ((System.ComponentModel.ISupportInitialize)(this.gridEntryBindingSource)).BeginInit(); + this.syncBindingSource = new LibationWinForms.GridView.SyncBindingSource(this.components); ((System.ComponentModel.ISupportInitialize)(this.gridEntryDataGridView)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.syncBindingSource)).BeginInit(); this.SuspendLayout(); // - // gridEntryBindingSource - // - this.gridEntryBindingSource.DataSource = typeof(LibationWinForms.GridEntry); - // // gridEntryDataGridView // this.gridEntryDataGridView.AllowUserToAddRows = false; @@ -64,42 +60,40 @@ this.gridEntryDataGridView.AutoGenerateColumns = false; this.gridEntryDataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; this.gridEntryDataGridView.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { - this.liberateGVColumn, - this.coverGVColumn, - this.titleGVColumn, - this.authorsGVColumn, - this.narratorsGVColumn, - this.lengthGVColumn, - this.seriesGVColumn, - this.descriptionGVColumn, - this.categoryGVColumn, - this.productRatingGVColumn, - this.purchaseDateGVColumn, - this.myRatingGVColumn, - this.miscGVColumn, - this.tagAndDetailsGVColumn}); + this.liberateGVColumn, + this.coverGVColumn, + this.titleGVColumn, + this.authorsGVColumn, + this.narratorsGVColumn, + this.lengthGVColumn, + this.seriesGVColumn, + this.descriptionGVColumn, + this.categoryGVColumn, + this.productRatingGVColumn, + this.purchaseDateGVColumn, + this.myRatingGVColumn, + this.miscGVColumn, + this.tagAndDetailsGVColumn}); this.gridEntryDataGridView.ContextMenuStrip = this.contextMenuStrip1; - this.gridEntryDataGridView.DataSource = this.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.gridEntryDataGridView.DefaultCellStyle = dataGridViewCellStyle1; + this.gridEntryDataGridView.DataSource = this.syncBindingSource; + dataGridViewCellStyle2.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; + dataGridViewCellStyle2.BackColor = System.Drawing.SystemColors.Window; + dataGridViewCellStyle2.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + dataGridViewCellStyle2.ForeColor = System.Drawing.SystemColors.ControlText; + dataGridViewCellStyle2.SelectionBackColor = System.Drawing.SystemColors.Highlight; + dataGridViewCellStyle2.SelectionForeColor = System.Drawing.SystemColors.HighlightText; + dataGridViewCellStyle2.WrapMode = System.Windows.Forms.DataGridViewTriState.True; + this.gridEntryDataGridView.DefaultCellStyle = dataGridViewCellStyle2; this.gridEntryDataGridView.Dock = System.Windows.Forms.DockStyle.Fill; this.gridEntryDataGridView.Location = new System.Drawing.Point(0, 0); - this.gridEntryDataGridView.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.gridEntryDataGridView.Name = "gridEntryDataGridView"; this.gridEntryDataGridView.ReadOnly = true; this.gridEntryDataGridView.RowHeadersVisible = false; this.gridEntryDataGridView.RowTemplate.Height = 82; this.gridEntryDataGridView.Size = new System.Drawing.Size(1510, 380); this.gridEntryDataGridView.TabIndex = 0; + this.gridEntryDataGridView.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.DataGridView_CellContentClick); this.gridEntryDataGridView.CellToolTipTextNeeded += new System.Windows.Forms.DataGridViewCellToolTipTextNeededEventHandler(this.gridEntryDataGridView_CellToolTipTextNeeded); - this.gridEntryDataGridView.ColumnDisplayIndexChanged += new System.Windows.Forms.DataGridViewColumnEventHandler(this.gridEntryDataGridView_ColumnDisplayIndexChanged); - this.gridEntryDataGridView.ColumnWidthChanged += new System.Windows.Forms.DataGridViewColumnEventHandler(this.gridEntryDataGridView_ColumnWidthChanged); // // liberateGVColumn // @@ -218,23 +212,27 @@ this.contextMenuStrip1.Name = "contextMenuStrip1"; this.contextMenuStrip1.Size = new System.Drawing.Size(61, 4); // + // syncBindingSource + // + this.syncBindingSource.DataSource = typeof(LibationWinForms.GridView.GridEntry); + // // ProductsGrid // this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoScroll = true; this.Controls.Add(this.gridEntryDataGridView); - this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.Name = "ProductsGrid"; this.Size = new System.Drawing.Size(1510, 380); - ((System.ComponentModel.ISupportInitialize)(this.gridEntryBindingSource)).EndInit(); + this.Load += new System.EventHandler(this.ProductsGrid_Load); ((System.ComponentModel.ISupportInitialize)(this.gridEntryDataGridView)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.syncBindingSource)).EndInit(); this.ResumeLayout(false); } - #endregion - private LibationWinForms.SyncBindingSource gridEntryBindingSource; + #endregion private System.Windows.Forms.DataGridView gridEntryDataGridView; private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; private LiberateDataGridViewImageButtonColumn liberateGVColumn; @@ -251,5 +249,6 @@ private System.Windows.Forms.DataGridViewTextBoxColumn myRatingGVColumn; private System.Windows.Forms.DataGridViewTextBoxColumn miscGVColumn; private EditTagsDataGridViewImageButtonColumn tagAndDetailsGVColumn; + private SyncBindingSource syncBindingSource; } } diff --git a/Source/LibationWinForms/GridView/ProductsGrid.cs b/Source/LibationWinForms/GridView/ProductsGrid.cs new file mode 100644 index 00000000..a715eb8e --- /dev/null +++ b/Source/LibationWinForms/GridView/ProductsGrid.cs @@ -0,0 +1,319 @@ +using DataLayer; +using Dinah.Core.Windows.Forms; +using LibationFileManager; +using System; +using System.Collections.Generic; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Windows.Forms; + +namespace LibationWinForms.GridView +{ + public partial class ProductsGrid : UserControl + { + public delegate void LibraryBookEntryClickedEventHandler(LibraryBookEntry liveGridEntry); + public delegate void LibraryBookEntryRectangleClickedEventHandler(LibraryBookEntry liveGridEntry, Rectangle cellRectangle); + + /// Number of visible rows has changed + public event EventHandler VisibleCountChanged; + public event LibraryBookEntryClickedEventHandler LiberateClicked; + public event LibraryBookEntryClickedEventHandler CoverClicked; + public event LibraryBookEntryClickedEventHandler DetailsClicked; + public event LibraryBookEntryRectangleClickedEventHandler DescriptionClicked; + public new event EventHandler Scroll; + + private GridEntryBindingList bindingList; + internal IEnumerable GetVisible() + => bindingList + .LibraryBooks(); + + public ProductsGrid() + { + InitializeComponent(); + EnableDoubleBuffering(); + gridEntryDataGridView.Scroll += (_, s) => Scroll?.Invoke(this, s); + } + + private void EnableDoubleBuffering() + { + var propertyInfo = gridEntryDataGridView.GetType().GetProperty("DoubleBuffered", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); + + propertyInfo.SetValue(gridEntryDataGridView, true, null); + } + + #region Button controls + private void DataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e) + { + // handle grid button click: https://stackoverflow.com/a/13687844 + if (e.RowIndex < 0) + return; + + var entry = getGridEntry(e.RowIndex); + if (entry is LibraryBookEntry lbEntry) + { + if (e.ColumnIndex == liberateGVColumn.Index) + LiberateClicked?.Invoke(lbEntry); + else if (e.ColumnIndex == tagAndDetailsGVColumn.Index) + DetailsClicked?.Invoke(lbEntry); + else if (e.ColumnIndex == descriptionGVColumn.Index) + DescriptionClicked?.Invoke(lbEntry, gridEntryDataGridView.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, false)); + else if (e.ColumnIndex == coverGVColumn.Index) + CoverClicked?.Invoke(lbEntry); + } + else if (entry is SeriesEntry sEntry && e.ColumnIndex == liberateGVColumn.Index) + { + if (sEntry.Liberate.Expanded) + bindingList.CollapseItem(sEntry); + else + bindingList.ExpandItem(sEntry); + + sEntry.NotifyPropertyChanged(nameof(sEntry.Liberate)); + + VisibleCountChanged?.Invoke(this, bindingList.LibraryBooks().Count()); + } + } + + private GridEntry getGridEntry(int rowIndex) => gridEntryDataGridView.GetBoundItem(rowIndex); + + #endregion + + #region UI display functions + + internal void BindToGrid(List dbBooks) + { + var geList = dbBooks.Where(b => b.Book.ContentType is not ContentType.Episode).Select(b => new LibraryBookEntry(b)).Cast().ToList(); + + var episodes = dbBooks.Where(b => b.Book.ContentType is ContentType.Episode).ToList(); + + foreach (var series in episodes.Select(lb => lb.Book.SeriesLink.First()).DistinctBy(s => s.Series)) + { + var seriesEntry = new SeriesEntry(series, episodes.Where(lb => lb.Book.SeriesLink.First().Series == series.Book.SeriesLink.First().Series)); + + geList.Add(seriesEntry); + geList.AddRange(seriesEntry.Children); + } + + bindingList = new GridEntryBindingList(geList.OrderByDescending(e => e.DateAdded)); + bindingList.CollapseAll(); + syncBindingSource.DataSource = bindingList; + VisibleCountChanged?.Invoke(this, bindingList.LibraryBooks().Count()); + } + + internal void UpdateGrid(List dbBooks) + { + string existingFilter = syncBindingSource.Filter; + Filter(null); + + //Add absent books to grid, or update current books + + var allItmes = bindingList.AllItems().LibraryBooks(); + foreach (var libraryBook in dbBooks) + { + var existingItem = allItmes.FindBookByAsin(libraryBook.Book.AudibleProductId); + + // add new to top + if (existingItem is null) + { + if (libraryBook.Book.ContentType is ContentType.Episode) + { + LibraryBookEntry lbe; + //Find the series that libraryBook belongs to, if it exists + var series = bindingList.AllItems().FindBookSeriesEntry(libraryBook.Book.SeriesLink); + + if (series is null) + { + //Series doesn't exist yet, so create and add it + var newSeries = new SeriesEntry(libraryBook.Book.SeriesLink.First(), libraryBook); + lbe = newSeries.Children[0]; + newSeries.Liberate.Expanded = true; + bindingList.Insert(0, newSeries); + series = newSeries; + } + else + { + lbe = new(libraryBook) { Parent = series }; + series.Children.Add(lbe); + } + //Add episode beneath the parent + int seriesIndex = bindingList.IndexOf(series); + bindingList.Insert(seriesIndex + 1, lbe); + + if (series.Liberate.Expanded) + bindingList.ExpandItem(series); + else + bindingList.CollapseItem(series); + + series.NotifyPropertyChanged(); + } + else + //Add the new product + bindingList.Insert(0, new LibraryBookEntry(libraryBook)); + } + // update existing + else + { + existingItem.UpdateLibraryBook(libraryBook); + } + } + + //Re-filter after updating existing / adding new books to capture any changes + Filter(existingFilter); + + // remove deleted from grid. + // note: actual deletion from db must still occur via the RemoveBook feature. deleting from audible will not trigger this + var removedBooks = + bindingList + .AllItems() + .LibraryBooks() + .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)) + { + removed.Parent.Children.Remove(removed); + removed.Parent.NotifyPropertyChanged(); + } + + //Remove series that have no children + var removedSeries = + bindingList + .AllItems() + .EmptySeries(); + + foreach (var removed in removedBooks.Cast().Concat(removedSeries)) + //no need to re-filter for removed books + bindingList.Remove(removed); + + VisibleCountChanged?.Invoke(this, bindingList.LibraryBooks().Count()); + } + + #endregion + + #region Filter + + public void Filter(string searchString) + { + int visibleCount = bindingList.Count; + + if (string.IsNullOrEmpty(searchString)) + syncBindingSource.RemoveFilter(); + else + syncBindingSource.Filter = searchString; + + if (visibleCount != bindingList.Count) + VisibleCountChanged?.Invoke(this, bindingList.LibraryBooks().Count()); + + } + + #endregion + + #region Column Customizations + + private void ProductsGrid_Load(object sender, EventArgs e) + { + //https://stackoverflow.com/a/4498512/3335599 + if (System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime) return; + + gridEntryDataGridView.ColumnWidthChanged += gridEntryDataGridView_ColumnWidthChanged; + gridEntryDataGridView.ColumnDisplayIndexChanged += gridEntryDataGridView_ColumnDisplayIndexChanged; + + contextMenuStrip1.Items.Add(new ToolStripLabel("Show / Hide Columns")); + contextMenuStrip1.Items.Add(new ToolStripSeparator()); + + //Restore Grid Display Settings + var config = Configuration.Instance; + var gridColumnsVisibilities = config.GridColumnsVisibilities; + var gridColumnsWidths = config.GridColumnsWidths; + var displayIndices = config.GridColumnsDisplayIndices; + + var cmsKiller = new ContextMenuStrip(); + + foreach (DataGridViewColumn column in gridEntryDataGridView.Columns) + { + var itemName = column.DataPropertyName; + var visible = gridColumnsVisibilities.GetValueOrDefault(itemName, true); + + var menuItem = new ToolStripMenuItem() + { + Text = column.HeaderText, + Checked = visible, + Tag = itemName + }; + menuItem.Click += HideMenuItem_Click; + contextMenuStrip1.Items.Add(menuItem); + + column.Width = gridColumnsWidths.GetValueOrDefault(itemName, column.Width); + column.MinimumWidth = 10; + column.HeaderCell.ContextMenuStrip = contextMenuStrip1; + column.Visible = visible; + + //Setting a default ContextMenuStrip will allow the columns to handle the + //Show() event so it is not passed up to the _dataGridView.ContextMenuStrip. + //This allows the ContextMenuStrip to be shown if right-clicking in the gray + //background of _dataGridView but not shown if right-clicking inside cells. + column.ContextMenuStrip = cmsKiller; + } + + //We must set DisplayIndex properties in ascending order + foreach (var itemName in displayIndices.OrderBy(i => i.Value).Select(i => i.Key)) + { + var column = gridEntryDataGridView.Columns + .Cast() + .Single(c => c.DataPropertyName == itemName); + + column.DisplayIndex = displayIndices.GetValueOrDefault(itemName, column.Index); + } + } + + private void HideMenuItem_Click(object sender, EventArgs e) + { + var menuItem = sender as ToolStripMenuItem; + var propertyName = menuItem.Tag as string; + + var column = gridEntryDataGridView.Columns + .Cast() + .FirstOrDefault(c => c.DataPropertyName == propertyName); + + if (column != null) + { + var visible = menuItem.Checked; + menuItem.Checked = !visible; + column.Visible = !visible; + + var config = Configuration.Instance; + + var dictionary = config.GridColumnsVisibilities; + dictionary[propertyName] = column.Visible; + config.GridColumnsVisibilities = dictionary; + } + } + + private void gridEntryDataGridView_ColumnDisplayIndexChanged(object sender, DataGridViewColumnEventArgs e) + { + var config = Configuration.Instance; + + var dictionary = config.GridColumnsDisplayIndices; + dictionary[e.Column.DataPropertyName] = e.Column.DisplayIndex; + config.GridColumnsDisplayIndices = dictionary; + } + + private void gridEntryDataGridView_CellToolTipTextNeeded(object sender, DataGridViewCellToolTipTextNeededEventArgs e) + { + 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"; + } + + private void gridEntryDataGridView_ColumnWidthChanged(object sender, DataGridViewColumnEventArgs e) + { + var config = Configuration.Instance; + + var dictionary = config.GridColumnsWidths; + dictionary[e.Column.DataPropertyName] = e.Column.Width; + } + + #endregion + } +} diff --git a/Source/LibationWinForms/grid/ProductsGrid.resx b/Source/LibationWinForms/GridView/ProductsGrid.resx similarity index 83% rename from Source/LibationWinForms/grid/ProductsGrid.resx rename to Source/LibationWinForms/GridView/ProductsGrid.resx index 8a560af5..bc15cd01 100644 --- a/Source/LibationWinForms/grid/ProductsGrid.resx +++ b/Source/LibationWinForms/GridView/ProductsGrid.resx @@ -57,13 +57,16 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + + 171, 17 + + 17, 17 - - 197, 17 + + 326, 17 - - 81 + + 326, 17 \ No newline at end of file diff --git a/Source/LibationWinForms/GridView/SeriesEntry.cs b/Source/LibationWinForms/GridView/SeriesEntry.cs new file mode 100644 index 00000000..96d40f49 --- /dev/null +++ b/Source/LibationWinForms/GridView/SeriesEntry.cs @@ -0,0 +1,109 @@ +using DataLayer; +using Dinah.Core; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace LibationWinForms.GridView +{ + public class SeriesEntry : GridEntry + { + public List Children { get; init; } + public override DateTime DateAdded => Children.Max(c => c.DateAdded); + public override float SeriesIndex { get; } + public override string ProductRating + { + get + { + var productAverageRating = new Rating(Children.Average(c => c.LibraryBook.Book.Rating.OverallRating), Children.Average(c => c.LibraryBook.Book.Rating.PerformanceRating), Children.Average(c => c.LibraryBook.Book.Rating.StoryRating)); + return productAverageRating.ToStarString()?.DefaultIfNullOrWhiteSpace(""); + } + protected set => throw new NotImplementedException(); + } + public override string PurchaseDate { get; protected set; } + public override string MyRating + { + get + { + var myAverageRating = new Rating(Children.Average(c => c.LibraryBook.Book.UserDefinedItem.Rating.OverallRating), Children.Average(c => c.LibraryBook.Book.UserDefinedItem.Rating.PerformanceRating), Children.Average(c => c.LibraryBook.Book.UserDefinedItem.Rating.StoryRating)); + return myAverageRating.ToStarString()?.DefaultIfNullOrWhiteSpace(""); + } + protected set => throw new NotImplementedException(); + } + public override string Series { get; protected set; } + public override string Title { get; protected set; } + public override string Length + { + get + { + int bookLenMins = Children.Sum(c => c.LibraryBook.Book.LengthInMinutes); + return bookLenMins == 0 ? "" : $"{bookLenMins / 60} hr {bookLenMins % 60} min"; + } + protected set => throw new NotImplementedException(); + } + public override string Authors { get; protected set; } + public override string Narrators { get; protected set; } + public override string Category { get; protected set; } + public override string Misc { get; protected set; } = string.Empty; + public override string Description { get; protected set; } = string.Empty; + public override string DisplayTags { get; } = string.Empty; + + public override LiberateButtonStatus Liberate { get; } + + protected override Book Book => SeriesBook.Book; + + private SeriesBook SeriesBook { get; set; } + + private SeriesEntry(SeriesBook seriesBook) + { + Liberate = new LiberateButtonStatus { IsSeries = true }; + SeriesIndex = seriesBook.Index; + } + public SeriesEntry(SeriesBook seriesBook, IEnumerable children) : this(seriesBook) + { + Children = children.Select(c => new LibraryBookEntry(c) { Parent = this }).OrderBy(c => c.SeriesIndex).ToList(); + SetSeriesBook(seriesBook); + } + public SeriesEntry(SeriesBook seriesBook, LibraryBook child) : this(seriesBook) + { + Children = new() { new LibraryBookEntry(child) { Parent = this } }; + SetSeriesBook(seriesBook); + } + + private void SetSeriesBook(SeriesBook seriesBook) + { + SeriesBook = seriesBook; + LoadCover(); + + // Immutable properties + { + Title = SeriesBook.Series.Name; + Series = SeriesBook.Series.Name; + PurchaseDate = Children.Min(c => c.LibraryBook.DateAdded).ToString("d"); + Authors = Book.AuthorNames(); + Narrators = Book.NarratorNames(); + Category = string.Join(" > ", Book.CategoriesNames()); + } + } + + + /// Create getters for all member object values by name + protected override Dictionary> CreateMemberValueDictionary() => new() + { + { nameof(Title), () => Book.SeriesSortable() }, + { nameof(Series), () => Book.SeriesSortable() }, + { nameof(Length), () => Children.Sum(c => c.LibraryBook.Book.LengthInMinutes) }, + { nameof(MyRating), () => Children.Average(c => c.LibraryBook.Book.UserDefinedItem.Rating.FirstScore()) }, + { nameof(PurchaseDate), () => Children.Min(c => c.LibraryBook.DateAdded) }, + { nameof(ProductRating), () => Children.Average(c => c.LibraryBook.Book.Rating.FirstScore()) }, + { nameof(Authors), () => string.Empty }, + { nameof(Narrators), () => string.Empty }, + { nameof(Description), () => string.Empty }, + { nameof(Category), () => string.Empty }, + { nameof(Misc), () => string.Empty }, + { nameof(DisplayTags), () => string.Empty }, + { nameof(Liberate), () => Liberate }, + { nameof(DateAdded), () => DateAdded }, + }; + } +} diff --git a/Source/LibationWinForms/GridView/SyncBindingSource.cs b/Source/LibationWinForms/GridView/SyncBindingSource.cs new file mode 100644 index 00000000..970e110a --- /dev/null +++ b/Source/LibationWinForms/GridView/SyncBindingSource.cs @@ -0,0 +1,29 @@ +using System.ComponentModel; +using System.Threading; +using System.Windows.Forms; + +// https://stackoverflow.com/a/32886415 +namespace LibationWinForms.GridView +{ + public class SyncBindingSource : BindingSource + { + private SynchronizationContext syncContext { get; } + + public SyncBindingSource() : base() + => syncContext = SynchronizationContext.Current; + public SyncBindingSource(IContainer container) : base(container) + => syncContext = SynchronizationContext.Current; + public SyncBindingSource(object dataSource, string dataMember) : base(dataSource, dataMember) + => syncContext = SynchronizationContext.Current; + + public override bool SupportsFiltering => true; + + protected override void OnListChanged(ListChangedEventArgs e) + { + if (syncContext is not null) + syncContext.Send(_ => base.OnListChanged(e), null); + else + base.OnListChanged(e); + } + } +} diff --git a/Source/LibationWinForms/ProcessQueue/LogMe.cs b/Source/LibationWinForms/ProcessQueue/LogMe.cs index b6d61f69..06b84400 100644 --- a/Source/LibationWinForms/ProcessQueue/LogMe.cs +++ b/Source/LibationWinForms/ProcessQueue/LogMe.cs @@ -19,7 +19,7 @@ namespace LibationWinForms.ProcessQueue LogErrorString += (_, text) => Serilog.Log.Logger.Error(text); LogError += (_, tuple) => Serilog.Log.Logger.Error(tuple.Item1, tuple.Item2 ?? "Automated backup: error"); } - + private static ILogForm LogForm; public static LogMe RegisterForm(T form) where T : ILogForm { var logMe = new LogMe(); @@ -27,19 +27,31 @@ namespace LibationWinForms.ProcessQueue if (form is null) return logMe; - logMe.LogInfo += (_, text) => form?.WriteLine(text); + LogForm = form; - logMe.LogErrorString += (_, text) => form?.WriteLine(text); - - logMe.LogError += (_, tuple) => - { - form?.WriteLine(tuple.Item2 ?? "Automated backup: error"); - form?.WriteLine("ERROR: " + tuple.Item1.Message); - }; + logMe.LogInfo += LogMe_LogInfo; + logMe.LogErrorString += LogMe_LogErrorString; + logMe.LogError += LogMe_LogError; return logMe; } + private static async void LogMe_LogError(object sender, (Exception, string) tuple) + { + await Task.Run(() => LogForm?.WriteLine(tuple.Item2 ?? "Automated backup: error")); + await Task.Run(() => LogForm?.WriteLine("ERROR: " + tuple.Item1.Message)); + } + + private static async void LogMe_LogErrorString(object sender, string text) + { + await Task.Run(() => LogForm?.WriteLine(text)); + } + + private static async void LogMe_LogInfo(object sender, string text) + { + await Task.Run(() => LogForm?.WriteLine(text)); + } + public void Info(string text) => LogInfo?.Invoke(this, text); public void Error(string text) => LogErrorString?.Invoke(this, text); public void Error(Exception ex, string text = null) => LogError?.Invoke(this, (ex, text)); diff --git a/Source/LibationWinForms/ProcessQueue/ProcessBook.cs b/Source/LibationWinForms/ProcessQueue/ProcessBook.cs index f84db515..7c9778a5 100644 --- a/Source/LibationWinForms/ProcessQueue/ProcessBook.cs +++ b/Source/LibationWinForms/ProcessQueue/ProcessBook.cs @@ -131,7 +131,6 @@ namespace LibationWinForms.ProcessQueue { ProcessBookResult.Success => ProcessBookStatus.Completed, ProcessBookResult.Cancelled => ProcessBookStatus.Cancelled, - ProcessBookResult.FailedRetry => ProcessBookStatus.Queued, _ => ProcessBookStatus.Failed, }; } diff --git a/Source/LibationWinForms/ProcessQueue/ProcessBookControl.cs b/Source/LibationWinForms/ProcessQueue/ProcessBookControl.cs index 7eee6913..62062468 100644 --- a/Source/LibationWinForms/ProcessQueue/ProcessBookControl.cs +++ b/Source/LibationWinForms/ProcessQueue/ProcessBookControl.cs @@ -72,8 +72,8 @@ namespace LibationWinForms.ProcessQueue Status = ProcessBookStatus.Cancelled; break; case ProcessBookResult.FailedRetry: - statusText = "Queued"; - Status = ProcessBookStatus.Queued; + statusText = "Error, will retry later"; + Status = ProcessBookStatus.Failed; break; case ProcessBookResult.FailedSkip: statusText = "Error, Skippping"; diff --git a/Source/LibationWinForms/ProcessQueue/ProcessQueueControl.Designer.cs b/Source/LibationWinForms/ProcessQueue/ProcessQueueControl.Designer.cs index 3e99394f..f600fd5d 100644 --- a/Source/LibationWinForms/ProcessQueue/ProcessQueueControl.Designer.cs +++ b/Source/LibationWinForms/ProcessQueue/ProcessQueueControl.Designer.cs @@ -51,9 +51,9 @@ this.logEntryColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); this.panel4 = new System.Windows.Forms.Panel(); this.panel2 = new System.Windows.Forms.Panel(); + this.logCopyBtn = new System.Windows.Forms.Button(); this.clearLogBtn = new System.Windows.Forms.Button(); this.counterTimer = new System.Windows.Forms.Timer(this.components); - this.logCopyBtn = new System.Windows.Forms.Button(); this.statusStrip1.SuspendLayout(); this.tabControl1.SuspendLayout(); this.tabPage1.SuspendLayout(); @@ -264,10 +264,21 @@ this.panel2.Size = new System.Drawing.Size(390, 25); this.panel2.TabIndex = 1; // + // logCopyBtn + // + this.logCopyBtn.Dock = System.Windows.Forms.DockStyle.Left; + this.logCopyBtn.Location = new System.Drawing.Point(0, 0); + this.logCopyBtn.Name = "logCopyBtn"; + this.logCopyBtn.Size = new System.Drawing.Size(57, 23); + this.logCopyBtn.TabIndex = 1; + this.logCopyBtn.Text = "Copy"; + this.logCopyBtn.UseVisualStyleBackColor = true; + this.logCopyBtn.Click += new System.EventHandler(this.LogCopyBtn_Click); + // // clearLogBtn // - this.clearLogBtn.Dock = System.Windows.Forms.DockStyle.Left; - this.clearLogBtn.Location = new System.Drawing.Point(0, 0); + this.clearLogBtn.Dock = System.Windows.Forms.DockStyle.Right; + this.clearLogBtn.Location = new System.Drawing.Point(328, 0); this.clearLogBtn.Name = "clearLogBtn"; this.clearLogBtn.Size = new System.Drawing.Size(60, 23); this.clearLogBtn.TabIndex = 0; @@ -280,17 +291,6 @@ this.counterTimer.Interval = 950; this.counterTimer.Tick += new System.EventHandler(this.CounterTimer_Tick); // - // logCopyBtn - // - this.logCopyBtn.Dock = System.Windows.Forms.DockStyle.Right; - this.logCopyBtn.Location = new System.Drawing.Point(331, 0); - this.logCopyBtn.Name = "logCopyBtn"; - this.logCopyBtn.Size = new System.Drawing.Size(57, 23); - this.logCopyBtn.TabIndex = 1; - this.logCopyBtn.Text = "Copy"; - this.logCopyBtn.UseVisualStyleBackColor = true; - this.logCopyBtn.Click += new System.EventHandler(this.LogCopyBtn_Click); - // // ProcessQueueControl // this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); diff --git a/Source/LibationWinForms/ProcessQueue/ProcessQueueControl.cs b/Source/LibationWinForms/ProcessQueue/ProcessQueueControl.cs index 88c309a3..a55dc071 100644 --- a/Source/LibationWinForms/ProcessQueue/ProcessQueueControl.cs +++ b/Source/LibationWinForms/ProcessQueue/ProcessQueueControl.cs @@ -46,24 +46,31 @@ namespace LibationWinForms.ProcessQueue public ProcessQueueControl() { InitializeComponent(); - Logger = LogMe.RegisterForm(this); - runningTimeLbl.Text = string.Empty; popoutBtn.DisplayStyle = ToolStripItemDisplayStyle.Text; popoutBtn.Name = "popoutBtn"; popoutBtn.Text = "Pop Out"; popoutBtn.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; popoutBtn.Alignment = ToolStripItemAlignment.Right; popoutBtn.Anchor = AnchorStyles.Bottom | AnchorStyles.Right; - statusStrip1.Items.Add(popoutBtn); + Logger = LogMe.RegisterForm(this); + virtualFlowControl2.RequestData += VirtualFlowControl1_RequestData; virtualFlowControl2.ButtonClicked += VirtualFlowControl2_ButtonClicked; Queue.QueuededCountChanged += Queue_QueuededCountChanged; Queue.CompletedCountChanged += Queue_CompletedCountChanged; + Load += ProcessQueueControl_Load; + } + + private void ProcessQueueControl_Load(object sender, EventArgs e) + { + if (DesignMode) return; + + runningTimeLbl.Text = string.Empty; QueuedCount = 0; ErrorCount = 0; CompletedCount = 0; @@ -144,12 +151,15 @@ namespace LibationWinForms.ProcessQueue var result = await nextBook.ProcessOneAsync(); - if (result == ProcessBookResult.FailedRetry) - Queue.Enqueue(nextBook); - else if (result == ProcessBookResult.ValidationFail) + if (result == ProcessBookResult.ValidationFail) Queue.ClearCurrent(); else if (result == ProcessBookResult.FailedAbort) - return; + Queue.ClearQueue(); + else if (result == ProcessBookResult.FailedSkip) + { + nextBook.LibraryBook.Book.UserDefinedItem.BookStatus = DataLayer.LiberatedStatus.Error; + ApplicationServices.LibraryCommands.UpdateUserDefinedItem(nextBook.LibraryBook.Book); + } } Queue_CompletedCountChanged(this, 0); counterTimer.Stop(); @@ -162,14 +172,14 @@ namespace LibationWinForms.ProcessQueue if (IsDisposed) return; var timeStamp = DateTime.Now; - logDGV.Rows.Add(timeStamp, text.Trim()); + Invoke(() => logDGV.Rows.Add(timeStamp, text.Trim())); } #region Control event handlers private void Queue_CompletedCountChanged(object sender, int e) { - int errCount = Queue.Completed.Count(p => p.Result is ProcessBookResult.FailedAbort or ProcessBookResult.FailedSkip or ProcessBookResult.ValidationFail); + int errCount = Queue.Completed.Count(p => p.Result is ProcessBookResult.FailedAbort or ProcessBookResult.FailedSkip or ProcessBookResult.FailedRetry or ProcessBookResult.ValidationFail); int completeCount = Queue.Completed.Count(p => p.Result is ProcessBookResult.Success); ErrorCount = errCount; diff --git a/Source/LibationWinForms/ProcessQueue/VirtualFlowControl.Designer.cs b/Source/LibationWinForms/ProcessQueue/VirtualFlowControl.Designer.cs index 77f793fc..dfcedef8 100644 --- a/Source/LibationWinForms/ProcessQueue/VirtualFlowControl.Designer.cs +++ b/Source/LibationWinForms/ProcessQueue/VirtualFlowControl.Designer.cs @@ -29,6 +29,7 @@ private void InitializeComponent() { this.panel1 = new System.Windows.Forms.Panel(); + this.vScrollBar1 = new System.Windows.Forms.VScrollBar(); this.SuspendLayout(); // // panel1 @@ -39,12 +40,21 @@ this.panel1.BackColor = System.Drawing.SystemColors.ControlDark; this.panel1.Location = new System.Drawing.Point(0, 0); this.panel1.Name = "panel1"; - this.panel1.Size = new System.Drawing.Size(377, 505); + this.panel1.Size = new System.Drawing.Size(357, 505); this.panel1.TabIndex = 0; // + // vScrollBar1 + // + this.vScrollBar1.Dock = System.Windows.Forms.DockStyle.Right; + this.vScrollBar1.Location = new System.Drawing.Point(360, 0); + this.vScrollBar1.Name = "vScrollBar1"; + this.vScrollBar1.Size = new System.Drawing.Size(17, 505); + this.vScrollBar1.TabIndex = 0; + // // VirtualFlowControl // this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.Controls.Add(this.vScrollBar1); this.Controls.Add(this.panel1); this.Name = "VirtualFlowControl"; this.Size = new System.Drawing.Size(377, 505); @@ -55,5 +65,6 @@ #endregion private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.VScrollBar vScrollBar1; } } diff --git a/Source/LibationWinForms/ProcessQueue/VirtualFlowControl.cs b/Source/LibationWinForms/ProcessQueue/VirtualFlowControl.cs index d031d191..3c146703 100644 --- a/Source/LibationWinForms/ProcessQueue/VirtualFlowControl.cs +++ b/Source/LibationWinForms/ProcessQueue/VirtualFlowControl.cs @@ -75,7 +75,6 @@ namespace LibationWinForms.ProcessQueue /// private readonly int TopMargin; - private readonly VScrollBar vScrollBar1; private readonly List BookControls = new(); #endregion @@ -101,16 +100,6 @@ namespace LibationWinForms.ProcessQueue { InitializeComponent(); - vScrollBar1 = new VScrollBar - { - Minimum = 0, - Value = 0, - Dock = DockStyle.Right - }; - Controls.Add(vScrollBar1); - - vScrollBar1.Scroll += (_, s) => SetScrollPosition(s.NewValue); - panel1.Width -= vScrollBar1.Width + panel1.Margin.Right; panel1.Resize += (_, _) => { AdjustScrollBar(); @@ -125,9 +114,6 @@ namespace LibationWinForms.ProcessQueue BookControls.Add(control); panel1.Controls.Add(control); - if (DesignMode) - return; - for (int i = 1; i < NUM_ACTUAL_CONTROLS; i++) { control = InitControl(VirtualControlHeight * i); @@ -135,6 +121,7 @@ namespace LibationWinForms.ProcessQueue panel1.Controls.Add(control); } + vScrollBar1.Scroll += (_, s) => SetScrollPosition(s.NewValue); vScrollBar1.SmallChange = SmallScrollChange; panel1.Height += NUM_BLANK_SPACES_AT_BOTTOM * VirtualControlHeight; } @@ -227,6 +214,8 @@ namespace LibationWinForms.ProcessQueue /// private void SetScrollPosition(int value) { + if (!vScrollBar1.Enabled) return; + int newPos = (int)Math.Round((double)value / SmallScrollChange) * SmallScrollChange; if (vScrollBar1.Value != newPos) { diff --git a/Source/LibationWinForms/Properties/DataSources/LibationWinForm.GridEntry.datasource b/Source/LibationWinForms/Properties/DataSources/LibationWinForm.GridEntry.datasource index ce0d9a71..48143915 100644 --- a/Source/LibationWinForms/Properties/DataSources/LibationWinForm.GridEntry.datasource +++ b/Source/LibationWinForms/Properties/DataSources/LibationWinForm.GridEntry.datasource @@ -6,5 +6,5 @@ cause the file to be unrecognizable by the program. --> - LibationWinForms.GridEntry, LibationWinForms, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + LibationWinForms.GridView.GridEntry, LibationWinForms, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null \ No newline at end of file diff --git a/Source/LibationWinForms/Properties/Resources.Designer.cs b/Source/LibationWinForms/Properties/Resources.Designer.cs index 468d9e4d..f3e881e2 100644 --- a/Source/LibationWinForms/Properties/Resources.Designer.cs +++ b/Source/LibationWinForms/Properties/Resources.Designer.cs @@ -229,5 +229,25 @@ namespace LibationWinForms.Properties { return ((System.Drawing.Bitmap)(obj)); } } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap minus { + get { + object obj = ResourceManager.GetObject("minus", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap plus { + get { + object obj = ResourceManager.GetObject("plus", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } } } diff --git a/Source/LibationWinForms/Properties/Resources.resx b/Source/LibationWinForms/Properties/Resources.resx index 0a1ae67a..95b3b8a0 100644 --- a/Source/LibationWinForms/Properties/Resources.resx +++ b/Source/LibationWinForms/Properties/Resources.resx @@ -169,4 +169,10 @@ ..\Resources\liberate_yellow_pdf_yes.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\minus.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\plus.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/Source/LibationWinForms/Resources/minus.png b/Source/LibationWinForms/Resources/minus.png new file mode 100644 index 00000000..bfc2cf4a Binary files /dev/null and b/Source/LibationWinForms/Resources/minus.png differ diff --git a/Source/LibationWinForms/Resources/plus.png b/Source/LibationWinForms/Resources/plus.png new file mode 100644 index 00000000..1cae3d6b Binary files /dev/null and b/Source/LibationWinForms/Resources/plus.png differ diff --git a/Source/LibationWinForms/SyncBindingSource.cs b/Source/LibationWinForms/SyncBindingSource.cs deleted file mode 100644 index 42d38ad9..00000000 --- a/Source/LibationWinForms/SyncBindingSource.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.ComponentModel; -using System.Threading; -using System.Windows.Forms; - -// https://stackoverflow.com/a/32886415 -namespace LibationWinForms -{ - public class SyncBindingSource : BindingSource - { - private SynchronizationContext syncContext { get; } - - public SyncBindingSource() : base() - => syncContext = SynchronizationContext.Current; - public SyncBindingSource(IContainer container) : base(container) - => syncContext = SynchronizationContext.Current; - public SyncBindingSource(object dataSource, string dataMember) : base(dataSource, dataMember) - => syncContext = SynchronizationContext.Current; - - public override bool SupportsFiltering => true; - - protected override void OnListChanged(ListChangedEventArgs e) - { - if (syncContext is not null) - syncContext.Send(_ => base.OnListChanged(e), null); - else - base.OnListChanged(e); - } - } -} diff --git a/Source/LibationWinForms/grid/FilterableSortableBindingList.cs b/Source/LibationWinForms/grid/FilterableSortableBindingList.cs deleted file mode 100644 index 1e896e0b..00000000 --- a/Source/LibationWinForms/grid/FilterableSortableBindingList.cs +++ /dev/null @@ -1,94 +0,0 @@ -using ApplicationServices; -using Dinah.Core.DataBinding; -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; - -namespace LibationWinForms -{ - /* - * Allows filtering of the underlying SortableBindingList - * by implementing IBindingListView and using SearchEngineCommands - * - * When filtering is applied, the filtered-out items are removed - * from the base list and added to the private FilterRemoved list. - * When filtering is removed, items in the FilterRemoved list are - * added back to the base list. - * - * Remove is overridden to ensure that removed items are removed from - * the base list (visible items) as well as the FilterRemoved list. - */ - internal class FilterableSortableBindingList : SortableBindingList, IBindingListView - { - /// - /// Items that were removed from the base list due to filtering - /// - private readonly List FilterRemoved = new(); - private string FilterString; - public FilterableSortableBindingList(IEnumerable enumeration) : base(enumeration) { } - - public bool SupportsFiltering => true; - public string Filter { get => FilterString; set => ApplyFilter(value); } - - #region Unused - Advanced Filtering - public bool SupportsAdvancedSorting => false; - - //This ApplySort overload is only called if SupportsAdvancedSorting is true. - //Otherwise BindingList.ApplySort() is used - public void ApplySort(ListSortDescriptionCollection sorts) => throw new NotImplementedException(); - - public ListSortDescriptionCollection SortDescriptions => throw new NotImplementedException(); - #endregion - - public new void Remove(GridEntry entry) - { - FilterRemoved.Remove(entry); - base.Remove(entry); - } - - /// All items in the list, including those filtered out. - public List AllItems() => Items.Concat(FilterRemoved).ToList(); - - private void ApplyFilter(string filterString) - { - if (filterString != FilterString) - RemoveFilter(); - - FilterString = filterString; - - var searchResults = SearchEngineCommands.Search(filterString); - var filteredOut = Items.ExceptBy(searchResults.Docs.Select(d => d.ProductId), ge => ge.AudibleProductId); - - for (int i = Items.Count - 1; i >= 0; i--) - { - if (filteredOut.Contains(Items[i])) - { - FilterRemoved.Add(Items[i]); - Items.RemoveAt(i); - base.OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted, i)); - } - } - } - - public void RemoveFilter() - { - if (FilterString is null) return; - - int visibleCount = Items.Count; - for (int i = 0; i < FilterRemoved.Count; i++) - base.InsertItem(i + visibleCount, FilterRemoved[i]); - OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1)); - - FilterRemoved.Clear(); - - if (IsSortedCore) - Sort(); - else - //No user-defined sort is applied, so do default sorting by date added, descending - ((List)Items).Sort((i1, i2) => i2.LibraryBook.DateAdded.CompareTo(i1.LibraryBook.DateAdded)); - - FilterString = null; - } - } -} diff --git a/Source/LibationWinForms/grid/ProductsGrid.cs b/Source/LibationWinForms/grid/ProductsGrid.cs deleted file mode 100644 index 690cb00d..00000000 --- a/Source/LibationWinForms/grid/ProductsGrid.cs +++ /dev/null @@ -1,351 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Linq; -using System.Threading.Tasks; -using System.Windows.Forms; -using ApplicationServices; -using DataLayer; -using Dinah.Core.Windows.Forms; -using FileLiberator; -using LibationFileManager; -using LibationWinForms.Dialogs; - -namespace LibationWinForms -{ - - #region // legacy instructions to update data_grid_view - // INSTRUCTIONS TO UPDATE DATA_GRID_VIEW - // - delete current DataGridView - // - view > other windows > data sources - // - refresh - // OR - // - Add New Data Source - // Object. Next - // LibationWinForms - // AudibleDTO - // GridEntry - // - go to Design view - // - click on Data Sources > ProductItem. dropdown: DataGridView - // - drag/drop ProductItem on design surface - // - // as of august 2021 this does not work in vs2019 with .net5 projects - // VS has improved since then with .net6+ but I haven't checked again - #endregion - - - public partial class ProductsGrid : UserControl - { - public event EventHandler LiberateClicked; - /// Number of visible rows has changed - public event EventHandler VisibleCountChanged; - - // alias - private DataGridView _dataGridView => gridEntryDataGridView; - - public ProductsGrid() - { - InitializeComponent(); - - if (this.DesignMode) - return; - - EnableDoubleBuffering(); - - _dataGridView.CellContentClick += DataGridView_CellContentClick; - - this.Load += ProductsGrid_Load; - } - - private void EnableDoubleBuffering() - { - var propertyInfo = _dataGridView.GetType().GetProperty("DoubleBuffered", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); - - propertyInfo.SetValue(_dataGridView, true, null); - } - - #region Button controls - - private async void DataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e) - { - // handle grid button click: https://stackoverflow.com/a/13687844 - if (e.RowIndex < 0) - return; - - if (e.ColumnIndex == liberateGVColumn.Index) - Liberate_Click(getGridEntry(e.RowIndex)); - else if (e.ColumnIndex == tagAndDetailsGVColumn.Index) - Details_Click(getGridEntry(e.RowIndex)); - 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 ImageDisplay imageDisplay; - private async Task Cover_Click(GridEntry liveGridEntry) - { - var picDefinition = new PictureDefinition(liveGridEntry.LibraryBook.Book.PictureLarge ?? liveGridEntry.LibraryBook.Book.PictureId, PictureSize.Native); - var picDlTask = Task.Run(() => PictureStorage.GetPictureSynchronously(picDefinition)); - - (_, byte[] initialImageBts) = PictureStorage.GetPicture(new PictureDefinition(liveGridEntry.LibraryBook.Book.PictureId, PictureSize._80x80)); - var windowTitle = $"{liveGridEntry.Title} - Cover"; - - 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) - { - var displayWindow = new DescriptionDisplay - { - SpawnLocation = PointToScreen(cellDisplay.Location + new Size(cellDisplay.Width, 0)), - DescriptionText = liveGridEntry.LongDescription, - BorderThickness = 2, - }; - - void CloseWindow(object o, EventArgs e) - { - displayWindow.Close(); - } - - _dataGridView.Scroll += CloseWindow; - displayWindow.FormClosed += (_, _) => _dataGridView.Scroll -= CloseWindow; - displayWindow.Show(this); - } - - private void Liberate_Click(GridEntry liveGridEntry) - { - LiberateClicked?.Invoke(this, liveGridEntry.LibraryBook); - } - - private static void Details_Click(GridEntry liveGridEntry) - { - var bookDetailsForm = new BookDetailsDialog(liveGridEntry.LibraryBook); - if (bookDetailsForm.ShowDialog() == DialogResult.OK) - liveGridEntry.Commit(bookDetailsForm.NewTags, bookDetailsForm.BookLiberatedStatus, bookDetailsForm.PdfLiberatedStatus); - } - - #endregion - - #region UI display functions - - private FilterableSortableBindingList bindingList; - - private bool hasBeenDisplayed; - public event EventHandler InitialLoaded; - public void Display() - { - // don't return early if lib size == 0. this will not update correctly if all books are removed - var lib = DbContexts.GetLibrary_Flat_NoTracking(); - - if (!hasBeenDisplayed) - { - // bind - bindToGrid(lib); - hasBeenDisplayed = true; - InitialLoaded?.Invoke(this, new()); - VisibleCountChanged?.Invoke(this, bindingList.Count); - } - else - updateGrid(lib); - - } - - private void bindToGrid(List dbBooks) - { - bindingList = new FilterableSortableBindingList(dbBooks.OrderByDescending(lb => lb.DateAdded).Select(lb => new GridEntry(lb))); - gridEntryBindingSource.DataSource = bindingList; - } - - private void updateGrid(List dbBooks) - { - int visibleCount = bindingList.Count; - string existingFilter = gridEntryBindingSource.Filter; - - //Add absent books to grid, or update current books - - var allItmes = bindingList.AllItems(); - for (var i = dbBooks.Count - 1; i >= 0; i--) - { - var libraryBook = dbBooks[i]; - var existingItem = allItmes.FirstOrDefault(i => i.AudibleProductId == libraryBook.Book.AudibleProductId); - - // add new to top - if (existingItem is null) - bindingList.Insert(0, new GridEntry(libraryBook)); - // update existing - else - existingItem.UpdateLibraryBook(libraryBook); - } - - if (bindingList.Count != visibleCount) - { - //re-filter for newly added items - Filter(null); - Filter(existingFilter); - } - - // remove deleted from grid. - // note: actual deletion from db must still occur via the RemoveBook feature. deleting from audible will not trigger this - var removedBooks = - bindingList - .AllItems() - .ExceptBy(dbBooks.Select(lb => lb.Book.AudibleProductId), ge => ge.AudibleProductId) - .ToList(); - - foreach (var removed in removedBooks) - //no need to re-filter for removed books - bindingList.Remove(removed); - - if (bindingList.Count != visibleCount) - VisibleCountChanged?.Invoke(this, bindingList.Count); - } - - #endregion - - #region Filter - - public void Filter(string searchString) - { - int visibleCount = bindingList.Count; - - if (string.IsNullOrEmpty(searchString)) - gridEntryBindingSource.RemoveFilter(); - else - gridEntryBindingSource.Filter = searchString; - - if (visibleCount != bindingList.Count) - VisibleCountChanged?.Invoke(this, bindingList.Count); - } - - #endregion - - internal List GetVisible() - => bindingList - .Select(row => row.LibraryBook) - .ToList(); - - private GridEntry getGridEntry(int rowIndex) => _dataGridView.GetBoundItem(rowIndex); - - #region Column Customizations - - // to ensure this is only ever called once: Load instead of 'override OnVisibleChanged' - private void ProductsGrid_Load(object sender, EventArgs e) - { - if (this.DesignMode) - return; - - contextMenuStrip1.Items.Add(new ToolStripLabel("Show / Hide Columns")); - contextMenuStrip1.Items.Add(new ToolStripSeparator()); - - //Restore Grid Display Settings - var config = Configuration.Instance; - var gridColumnsVisibilities = config.GridColumnsVisibilities; - var gridColumnsWidths = config.GridColumnsWidths; - var displayIndices = config.GridColumnsDisplayIndices; - - var cmsKiller = new ContextMenuStrip(); - - foreach (DataGridViewColumn column in _dataGridView.Columns) - { - var itemName = column.DataPropertyName; - var visible = gridColumnsVisibilities.GetValueOrDefault(itemName, true); - - var menuItem = new ToolStripMenuItem() - { - Text = column.HeaderText, - Checked = visible, - Tag = itemName - }; - menuItem.Click += HideMenuItem_Click; - contextMenuStrip1.Items.Add(menuItem); - - column.Width = gridColumnsWidths.GetValueOrDefault(itemName, column.Width); - column.MinimumWidth = 10; - column.HeaderCell.ContextMenuStrip = contextMenuStrip1; - column.Visible = visible; - - //Setting a default ContextMenuStrip will allow the columns to handle the - //Show() event so it is not passed up to the _dataGridView.ContextMenuStrip. - //This allows the ContextMenuStrip to be shown if right-clicking in the gray - //background of _dataGridView but not shown if right-clicking inside cells. - column.ContextMenuStrip = cmsKiller; - } - - //We must set DisplayIndex properties in ascending order - foreach (var itemName in displayIndices.OrderBy(i => i.Value).Select(i => i.Key)) - { - var column = _dataGridView.Columns - .Cast() - .Single(c => c.DataPropertyName == itemName); - - column.DisplayIndex = displayIndices.GetValueOrDefault(itemName, column.Index); - } - - base.OnVisibleChanged(e); - } - - private void gridEntryDataGridView_ColumnDisplayIndexChanged(object sender, DataGridViewColumnEventArgs e) - { - var config = Configuration.Instance; - - var dictionary = config.GridColumnsDisplayIndices; - dictionary[e.Column.DataPropertyName] = e.Column.DisplayIndex; - config.GridColumnsDisplayIndices = dictionary; - } - - private void gridEntryDataGridView_ColumnWidthChanged(object sender, DataGridViewColumnEventArgs e) - { - var config = Configuration.Instance; - - var dictionary = config.GridColumnsWidths; - dictionary[e.Column.DataPropertyName] = e.Column.Width; - config.GridColumnsWidths = dictionary; - } - - private void HideMenuItem_Click(object sender, EventArgs e) - { - var menuItem = sender as ToolStripMenuItem; - var propertyName = menuItem.Tag as string; - - var column = _dataGridView.Columns - .Cast() - .FirstOrDefault(c => c.DataPropertyName == propertyName); - - if (column != null) - { - var visible = menuItem.Checked; - menuItem.Checked = !visible; - column.Visible = !visible; - - var config = Configuration.Instance; - - var dictionary = config.GridColumnsVisibilities; - dictionary[propertyName] = column.Visible; - config.GridColumnsVisibilities = dictionary; - } - } - - private void gridEntryDataGridView_CellToolTipTextNeeded(object sender, DataGridViewCellToolTipTextNeededEventArgs e) - { - 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 - } -}