diff --git a/TVRename/Forms/ListViewActionItemSorter.cs b/TVRename/Forms/ListViewActionItemSorter.cs
index 763617df..58bd7afe 100644
--- a/TVRename/Forms/ListViewActionItemSorter.cs
+++ b/TVRename/Forms/ListViewActionItemSorter.cs
@@ -1,6 +1,7 @@
using BrightIdeasSoftware;
using System.Collections;
using System.Collections.Generic;
+using System.Windows.Forms;
namespace TVRename;
@@ -48,6 +49,150 @@ public int Compare(OLVListItem? x, OLVListItem? y)
return xIsNull ? -1 : 1;
}
- return new ActionItemSorter().Compare(x1, y1);
+ return Polarity() * Sorter.Compare(x1, y1);
+ }
+
+ ///
+ /// Class constructor. Initializes various elements
+ ///
+ public ListViewActionItemSorter()
+ {
+ // Initialize the column to '0'
+ SortColumn = 0;
+
+ // Initialize the sort order to 'none'
+ Order = SortOrder.None;
+
+ // Initialize the CaseInsensitiveComparer object
+ Sorter = new DefaultActionItemSorter();
+ }
+
+ private int Polarity()
+ {
+ return Order switch
+ {
+ // Calculate correct return value based on object comparison
+ SortOrder.Ascending =>
+ // Ascending sort is selected, return normal result of compare operation
+ 1,
+ SortOrder.Descending =>
+ // Descending sort is selected, return negative result of compare operation
+ -1,
+ SortOrder.None =>
+ // Return '0' to indicate they are equal
+ 0,
+ _ => 0
+ };
+ }
+
+ ///
+ /// Gets or sets the number of the column to which to apply the sorting operation (Defaults to '0').
+ ///
+ public int SortColumn { set; get; }
+
+ ///
+ /// Gets or sets the order of sorting to apply (for example, 'Ascending' or 'Descending').
+ ///
+ public SortOrder Order { set; get; }
+
+ ///
+ /// Case insensitive comparer object
+ ///
+ public ActionItemSorter Sorter { get; set; }
+
+ public void ClickedOn(int col, ActionItemSorter sorter)
+ {
+ Sorter = sorter;
+
+ // Determine if clicked column is already the column that is being sorted.
+ if (col == SortColumn)
+ {
+ // Reverse the current sort direction for this column.
+ Order = Order == SortOrder.Ascending ? SortOrder.Descending : SortOrder.Ascending;
+ }
+ else
+ {
+ // Set the column number that is to be sorted; default to ascending.
+ SortColumn = col;
+ Order = SortOrder.Ascending;
+ }
+ }
+}
+
+internal class OlvActionGroupComparer : IComparer
+{
+ ///
+ /// Gets or sets the order of sorting to apply (for example, 'Ascending' or 'Descending').
+ ///
+ public SortOrder Order { set; get; }
+
+ ///
+ /// Case insensitive comparer object
+ ///
+ public ActionItemSorter Sorter { get; set; }
+
+ ///
+ /// Class constructor. Initializes various elements
+ ///
+ public OlvActionGroupComparer(ActionItemSorter sorter, SortOrder order)
+ {
+ // Initialize the sort order to 'none'
+ Order = order;
+
+ // Initialize the CaseInsensitiveComparer object
+ Sorter = sorter;
+ }
+
+ ///
+ /// Compare two rows
+ ///
+ /// row1
+ /// row2
+ /// An ordering indication: -1, 0, 1
+ public int Compare(object? x, object? y) => Compare(x as OLVListItem, y as OLVListItem);
+
+ ///
+ /// Compare two rows
+ ///
+ /// row1
+ /// row2
+ /// An ordering indication: -1, 0, 1
+ public int Compare(OLVListItem? x, OLVListItem? y)
+ {
+ Item? x1 = x?.RowObject as Item;
+ Item? y1 = y?.RowObject as Item;
+
+ // Handle nulls. Null values come last
+ bool xIsNull = x1 == null;
+ bool yIsNull = y1 == null;
+ if (xIsNull || yIsNull)
+ {
+ if (xIsNull && yIsNull)
+ {
+ return 0;
+ }
+
+ return xIsNull ? -1 : 1;
+ }
+
+ return Polarity() * Sorter.Compare(x1, y1);
+ }
+
+ private int Polarity()
+ {
+ return Order switch
+ {
+ // Calculate correct return value based on object comparison
+ SortOrder.Ascending =>
+ // Ascending sort is selected, return normal result of compare operation
+ 1,
+ SortOrder.Descending =>
+ // Descending sort is selected, return negative result of compare operation
+ -1,
+ SortOrder.None =>
+ // Return '0' to indicate they are equal
+ 0,
+ _ => 0
+ };
}
}
diff --git a/TVRename/Forms/SeasonGroupComparer.cs b/TVRename/Forms/SeasonGroupComparer.cs
new file mode 100644
index 00000000..42776cc7
--- /dev/null
+++ b/TVRename/Forms/SeasonGroupComparer.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows.Forms;
+using BrightIdeasSoftware;
+
+namespace TVRename.Forms;
+
+///
+/// This comparer sort list view specifically for sesaons so that they appear in the season order
+/// OLVGroups have a "SortValue" property,
+/// which is used if present. Otherwise, the titles of the groups will be compared.
+///
+public class SeasonGroupComparer : IComparer
+{
+ ///
+ /// Create a group comparer
+ ///
+ /// The ordering for column values
+ public SeasonGroupComparer(SortOrder order)
+ {
+ sortOrder = order;
+ }
+
+ ///
+ /// Compare the two groups. OLVGroups have a "SortValue" property,
+ /// which is used if present. Otherwise, the titles of the groups will be compared.
+ ///
+ /// group1
+ /// group2
+ /// An ordering indication: -1, 0, 1
+ public int Compare(OLVGroup? x, OLVGroup? y)
+ {
+ if (x is null || y is null)
+ {
+ return 0;
+ }
+
+ // If we can compare the sort values, do that.
+ // Otherwise do a case insensitive compare on the group header.
+ int result;
+ if (x.Items.Any() && y.Items.Any())
+ {
+ result = CompareValue(x).CompareTo(CompareValue(y));
+ }
+ else if (x.SortValue != null && y.SortValue != null)
+ {
+ result = x.SortValue.CompareTo(y.SortValue);
+ }
+ else
+ {
+ result = string.Compare(x.Header, y.Header, StringComparison.CurrentCultureIgnoreCase);
+ }
+
+ if (sortOrder == SortOrder.Descending)
+ {
+ return 0 - result;
+ }
+
+ return result;
+ }
+
+ private static int CompareValue(OLVGroup x) => ((Item)x.Items.First().RowObject).SeasonNumberAsInt ?? 0;
+
+ private readonly SortOrder sortOrder;
+}
diff --git a/TVRename/Forms/Tools/Recommendations/RecommendationView.cs b/TVRename/Forms/Tools/Recommendations/RecommendationView.cs
index 1f40a515..af6f1b8f 100644
--- a/TVRename/Forms/Tools/Recommendations/RecommendationView.cs
+++ b/TVRename/Forms/Tools/Recommendations/RecommendationView.cs
@@ -276,11 +276,11 @@ private void lvRecommendations_ItemSelectionChanged(object sender, ListViewItemS
}
if (rr.Movie != null)
{
- UI.SetHtmlBody(chrRecommendationPreview, rr.Movie.GetMovieHtmlOverview(rr));
+ chrRecommendationPreview.SetHtmlBody(rr.Movie.GetMovieHtmlOverview(rr));
}
else if (rr.Series != null)
{
- UI.SetHtmlBody(chrRecommendationPreview, rr.Series.GetShowHtmlOverview(rr));
+ chrRecommendationPreview.SetHtmlBody(rr.Series.GetShowHtmlOverview(rr));
}
}
private void this_FormClosing(object sender, FormClosingEventArgs e)
diff --git a/TVRename/Forms/Tools/YTSRecomendations/YtsRecommendationView.cs b/TVRename/Forms/Tools/YTSRecomendations/YtsRecommendationView.cs
index 8d3867e0..9a40119f 100644
--- a/TVRename/Forms/Tools/YTSRecomendations/YtsRecommendationView.cs
+++ b/TVRename/Forms/Tools/YTSRecomendations/YtsRecommendationView.cs
@@ -248,8 +248,7 @@ private void lvRecommendations_ItemSelectionChanged(object sender, ListViewItemS
{
if (e.Item is BrightIdeasSoftware.OLVListItem { RowObject: YtsRecommendationRow rr })
{
- UI.SetHtmlBody(chrRecommendationPreview,
- rr.Movie != null
+ chrRecommendationPreview.SetHtmlBody(rr.Movie != null
? rr.Movie.GetMovieHtmlOverview(false)
: rr.YtsMovie.GetMovieHtmlOverview());
}
diff --git a/TVRename/Forms/Tools/YTSRecomendations/YtsViewerView.cs b/TVRename/Forms/Tools/YTSRecomendations/YtsViewerView.cs
index fce4e0c6..536b8448 100644
--- a/TVRename/Forms/Tools/YTSRecomendations/YtsViewerView.cs
+++ b/TVRename/Forms/Tools/YTSRecomendations/YtsViewerView.cs
@@ -203,8 +203,7 @@ private void lvRecommendations_ItemSelectionChanged(object sender, ListViewItemS
object? rowObject = (e.Item as BrightIdeasSoftware.OLVListItem)?.RowObject;
if (rowObject is YtsViewerRow rr)
{
- UI.SetHtmlBody(chrRecommendationPreview,
- rr.Movie != null
+ chrRecommendationPreview.SetHtmlBody(rr.Movie != null
? rr.Movie.GetMovieHtmlOverview(false)
: rr.YtsMovie.GetMovieHtmlOverview());
}
diff --git a/TVRename/Forms/UI.Designer.cs b/TVRename/Forms/UI.Designer.cs
index b0160366..6b3c5bcf 100644
--- a/TVRename/Forms/UI.Designer.cs
+++ b/TVRename/Forms/UI.Designer.cs
@@ -1451,12 +1451,10 @@ public void InitializeComponent()
olvAction.UseFiltering = true;
olvAction.UseNotifyPropertyChanged = true;
olvAction.View = View.Details;
- olvAction.BeforeSorting += olvAction_BeforeSorting;
olvAction.BeforeCreatingGroups += olvAction_BeforeCreatingGroups;
olvAction.CanDrop += OlvAction_CanDrop;
olvAction.Dropped += OlvAction_Dropped;
olvAction.FormatRow += olv1_FormatRow;
- olvAction.ColumnClick += olvAction_ColumnClick;
olvAction.ItemChecked += lvAction_ItemChecked;
olvAction.SelectedIndexChanged += lvAction_SelectedIndexChanged;
olvAction.KeyDown += lvAction_KeyDown;
diff --git a/TVRename/Forms/UI.cs b/TVRename/Forms/UI.cs
index 3aae4d53..f214d8e3 100644
--- a/TVRename/Forms/UI.cs
+++ b/TVRename/Forms/UI.cs
@@ -75,8 +75,7 @@ public partial class UI : Form, IDialogParent
private MovieConfiguration? switchToWhenOpenMyMovies;
private readonly ListViewColumnSorter lvwScheduleColumnSorter;
- //private readonly ListViewColumnSorter lvwActionColumnSorter;
-
+
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private bool IsBusy => busy != 0;
@@ -125,7 +124,7 @@ public UI(TVDoc doc, TVRenameSplash splash, bool showUi)
lvwScheduleColumnSorter = new ListViewColumnSorter(new DateSorterWtw(3));
lvWhenToWatch.ListViewItemSorter = lvwScheduleColumnSorter;
- //lvwActionColumnSorter = new ListViewColumnSorter(new NumberAsTextSorter(1));
+ //lvwActionColumnSorter = new ListViewActionItemSorter();
if (mDoc.Args.Hide || !showUi)
{
@@ -300,6 +299,8 @@ private void ShowChild(Form childForm)
}
}
+ #region olvAction Methods
+
private void SetupObjectListForScanResults()
{
olvAction.SetObjects(mDoc.TheActionList);
@@ -312,6 +313,7 @@ private void SetupObjectListForScanResults()
olvDate.GroupKeyGetter = GroupDateKeyDelegate;
olvDate.GroupKeyToTitleConverter = GroupDateTitleDelegate;
+ olvDate.DataType = typeof(DateTime);
olvSeason.GroupKeyGetter = GroupSeasonKeyDelegate;
@@ -320,10 +322,140 @@ private void SetupObjectListForScanResults()
SimpleDropSink currActionDropSink = (SimpleDropSink)olvAction.DropSink;
currActionDropSink.FeedbackColor = Color.LightGray;
- olvDate.DataType = typeof(DateTime);
olvAction.SortGroupItemsByPrimaryColumn = false;
+
+ olvAction.CustomSorter = delegate(OLVColumn column, SortOrder order)
+ {
+ olvAction.ListViewItemSorter = new ColumnComparer(
+ MapToSortColumn(column), order);
+ };
+ olvAction.ShowSortIndicator();
+ }
+ private void olvAction_BeforeCreatingGroups(object sender, CreateGroupsEventArgs e)
+ {
+ e.Parameters.ItemComparer = new OlvActionGroupComparer(MapColumnToSorter(e.Parameters.PrimarySort), e.Parameters.PrimarySortOrder);
+
+ if (e.Parameters.PrimarySort == olvEpisode || e.Parameters.PrimarySort == olvSeason)
+ {
+ e.Parameters.GroupComparer = new SeasonGroupComparer(e.Parameters.GroupByOrder);
+ }
+ }
+
+ private ActionItemSorter MapColumnToSorter(OLVColumn column)
+ {
+ if (column == olvDate)
+ {
+ return new ActionItemDateSorter();
+ }
+ if (column == olvShowColumn)
+ {
+ return new ActionItemNameSorter();
+ }
+ if (column == olvEpisode)
+ {
+ return new ActionItemEpisodeSorter();
+ }
+ if (column == olvSeason)
+ {
+ return new ActionItemSeasonSorter();
+ }
+ if (column == olvErrors)
+ {
+ return new ActionItemErrorsSorter();
+ }
+ if (column == olvFolder)
+ {
+ return new ActionItemFolderSorter();
+ }
+ if (column == olvFilename)
+ {
+ return new ActionItemFilenameSorter();
+ }
+ if (column == olvSource)
+ {
+ return new ActionItemSourceSorter();
+ }
+ if (column == olvType)
+ {
+ return new DefaultActionItemSorter();
+ }
+
+ return new DefaultActionItemSorter();
+ }
+
+ private void DefaultOlvView()
+ {
+ olvAction.BeginUpdate();
+ olvAction.ShowGroups = true;
+ olvAction.AlwaysGroupByColumn = null;
+ olvAction.Sort(olvType, SortOrder.Ascending);
+ olvAction.BuildGroups(olvType, SortOrder.Ascending, olvShowColumn, SortOrder.Ascending, olvSeason, SortOrder.Ascending);
+ olvAction.ResetColumnFiltering();
+ olvAction.EndUpdate();
+ }
+
+ private void OlvAction_Dropped(object sender, OlvDropEventArgs e)
+ {
+ // Get a list of filenames being dragged
+ string[] files = (string[])((DataObject)e.DataObject).GetData(DataFormats.FileDrop, false);
+
+ // Establish item in list being dragged to, and exit if no item matched
+ // Check at least one file was being dragged, and that dragged-to item is a "Missing Item" item.
+ if (files.Length <= 0 || e.DropTargetItem.RowObject is not ItemMissing mi)
+ {
+ return;
+ }
+
+ // Only want the first file if multiple files were dragged across.
+ ManuallyAddFileForItem(mi, files[0]);
}
+ private void OlvAction_CanDrop(object sender, OlvDropEventArgs e)
+ {
+ if (e.DropSink?.DropTargetItem?.RowObject is not Item item)
+ {
+ e.Effect = DragDropEffects.None;
+ }
+ else
+ {
+ if (item is ItemMissing)
+ {
+ if (((DataObject)e.DataObject).GetDataPresent(DataFormats.FileDrop))
+ {
+ e.Effect = DragDropEffects.All;
+ }
+ else
+ {
+ e.Effect = DragDropEffects.None;
+ e.InfoMessage = "Can only drag files onto a missing episode";
+ }
+ }
+ else
+ {
+ e.Effect = DragDropEffects.None;
+ e.InfoMessage = "Can only drag onto a missing episode";
+ }
+ }
+ }
+
+ private OLVColumn MapToSortColumn(OLVColumn source)
+ {
+ if (source == olvDate)
+ {
+ return new OLVColumn("RawDate", "AirDate");
+ }
+ if (source == olvEpisode)
+ {
+ return new OLVColumn("RawEp", "EpisodeString");
+ }
+ if (source == olvSeason)
+ {
+ return new OLVColumn("RawSe", "SeasonNumberAsInt");
+ }
+
+ return source;
+ }
+
private static object GroupFolderTitleDelegate(object rowObject)
{
Item? ep = (Item?)rowObject;
@@ -525,12 +657,14 @@ private static string ConvertShowNameDelegate(object x)
private void olv1_FormatRow(object sender, FormatRowEventArgs e)
{
- if (e.Model is Action a && a.Outcome.Error)
+ if (e.Model is Action { Outcome.Error: true })
{
e.Item.BackColor = UiHelpers.WarningColor();
}
}
+ #endregion
+
private void ReceiveArgs(string[] args)
{
// Send command-line arguments to already running instance
@@ -575,17 +709,17 @@ private static void UpdateSplashStatus(TVRenameSplash splashScreen, string text,
private void ClearInfoWindows(string defaultText)
{
- SetHtmlBody(chrImages, ShowHtmlHelper.CreateOldPage(defaultText));
- SetHtmlBody(chrInformation, ShowHtmlHelper.CreateOldPage(defaultText));
- SetHtmlBody(chrSummary, ShowHtmlHelper.CreateOldPage(defaultText));
- SetHtmlBody(chrTvTrailer, ShowHtmlHelper.CreateOldPage(defaultText));
+ chrImages.SetSimpleHtmlBody(defaultText);
+ chrInformation.SetSimpleHtmlBody(defaultText);
+ chrSummary.SetSimpleHtmlBody(defaultText);
+ chrTvTrailer.SetSimpleHtmlBody(defaultText);
}
private void ClearMovieInfoWindows(string defaultText)
{
- SetHtmlBody(chrMovieImages, ShowHtmlHelper.CreateOldPage(defaultText));
- SetHtmlBody(chrMovieInformation, ShowHtmlHelper.CreateOldPage(defaultText));
- SetHtmlBody(chrMovieTrailer, ShowHtmlHelper.CreateOldPage(defaultText));
+ chrMovieImages.SetSimpleHtmlBody(defaultText);
+ chrMovieInformation.SetSimpleHtmlBody(defaultText);
+ chrMovieTrailer.SetSimpleHtmlBody(defaultText);
}
private void MoreBusy()
@@ -929,6 +1063,8 @@ private void flushCacheToolStripMenuItem_Click(object sender, EventArgs e)
}
}
+ #region Save and Load window size XML
+
private bool LoadWidths(XElement xml)
{
string? forwho = xml.Attribute("For")?.Value;
@@ -1132,6 +1268,8 @@ private void WriteColWidthsXml(string thingName, XmlWriter writer)
writer.WriteEndElement(); // ColumnWidths
}
+ #endregion
+
private void UI_FormClosing(object sender, FormClosingEventArgs e)
{
try
@@ -1316,10 +1454,10 @@ private void ShowQuickStartGuide()
{
try
{
- SetHtmlEmbed(chrInformation, QuickStartGuide());
- SetHtmlEmbed(chrImages, QuickStartGuide());
- SetHtmlEmbed(chrSummary, QuickStartGuide());
- SetHtmlEmbed(chrTvTrailer, QuickStartGuide());
+ chrInformation.SetHtmlEmbed(QuickStartGuide());
+ chrImages.SetHtmlEmbed(QuickStartGuide());
+ chrSummary.SetHtmlEmbed(QuickStartGuide());
+ chrTvTrailer.SetHtmlEmbed( QuickStartGuide());
}
catch (COMException ex)
{
@@ -1445,27 +1583,27 @@ private void FillEpGuideHtml(ShowConfiguration? si, int snum)
{
if (snum >= 0 && si.AppropriateSeasons().TryGetValue( snum, out ProcessedSeason? s))
{
- SetHtmlBody(chrInformation, ShowHtmlHelper.CreateOldPage(si.GetSeasonHtmlOverviewOffline(s)));
- SetHtmlBody(chrImages, ShowHtmlHelper.CreateOldPage(si.GetSeasonImagesHtmlOverview(s)));
+ chrInformation.SetSimpleHtmlBody(si.GetSeasonHtmlOverviewOffline(s));
+ chrImages.SetSimpleHtmlBody(si.GetSeasonImagesHtmlOverview(s));
}
else
{
// no epnum specified, just show an overview
- SetHtmlBody(chrInformation, ShowHtmlHelper.CreateOldPage(si.GetShowHtmlOverviewOffline()));
- SetHtmlBody(chrImages, ShowHtmlHelper.CreateOldPage(si.GetShowImagesHtmlOverview()));
+ chrInformation.SetSimpleHtmlBody(si.GetShowHtmlOverviewOffline());
+ chrImages.SetSimpleHtmlBody(si.GetShowImagesHtmlOverview());
}
- SetHtmlBody(chrSummary, ShowHtmlHelper.CreateOldPage("Not available offline"));
- SetHtmlBody(chrTvTrailer, ShowHtmlHelper.CreateOldPage("Not available offline"));
+ chrSummary.SetSimpleHtmlBody("Not available offline");
+ chrTvTrailer.SetSimpleHtmlBody("Not available offline");
return;
}
if (snum >= 0 && si.AppropriateSeasons().TryGetValue(snum, out ProcessedSeason? se))
{
- SetHtmlBody(chrImages, se.GetSeasonImagesOverview());
- SetHtmlBody(chrInformation, si.GetSeasonHtmlOverview(se, false));
- SetHtmlBody(chrSummary, si.GetSeasonSummaryHtmlOverview(se, false));
- UpdateTvTrailer(si);
+ chrImages.SetHtmlBody(se.GetSeasonImagesOverview());
+ chrInformation.SetHtmlBody(si.GetSeasonHtmlOverview(se, false));
+ chrSummary.SetHtmlBody(si.GetSeasonSummaryHtmlOverview(se, false));
+ chrTvTrailer.UpdateTvTrailer(si);
ResetRunBackGroundWorker(bwSeasonHTMLGenerator, se);
ResetRunBackGroundWorker(bwSeasonSummaryHTMLGenerator, se);
@@ -1473,10 +1611,10 @@ private void FillEpGuideHtml(ShowConfiguration? si, int snum)
else
{
// no epnum specified, just show an overview
- SetHtmlBody(chrImages, si.GetShowImagesOverview());
- SetHtmlBody(chrInformation, si.GetShowHtmlOverview(false));
- SetHtmlBody(chrSummary, si.GetShowSummaryHtmlOverview(false));
- UpdateTvTrailer(si);
+ chrImages.SetHtmlBody(si.GetShowImagesOverview());
+ chrInformation.SetHtmlBody(si.GetShowHtmlOverview(false));
+ chrSummary.SetHtmlBody(si.GetShowSummaryHtmlOverview(false));
+ chrTvTrailer.UpdateTvTrailer(si);
ResetRunBackGroundWorker(bwShowHTMLGenerator, si);
ResetRunBackGroundWorker(bwShowSummaryHTMLGenerator, si);
@@ -1497,70 +1635,6 @@ private static void ResetRunBackGroundWorker(BackgroundWorker worker, object s)
}
}
- private void UpdateTvTrailer(ShowConfiguration? si)
- {
- if (si?.CachedShow?.TrailerUrl?.HasValue() ?? false)
- {
- // ReSharper disable once AssignNullToNotNullAttribute
- SetHtmlEmbed(chrTvTrailer, ShowHtmlHelper.YoutubeTrailer(si.CachedShow!));
- }
- else
- {
- SetHtmlBody(chrTvTrailer, ShowHtmlHelper.CreateOldPage("Not available for this TV show"));
- }
- }
-
- private static void SetWeb(ChromiumWebBrowser web, System.Action a)
- {
- web.Visible = true;
- if (web.IsDisposed)
- {
- return;
- }
-
- if (!web.IsBrowserInitialized)
- {
- web.IsBrowserInitializedChanged += (_, _) =>
- {
- web.BeginInvoke((MethodInvoker)delegate { SetWeb(web, a); });
- };
- }
-
- try
- {
- a();
- }
- catch (COMException ex)
- {
- //Fail gracefully - no RHS episode guide is not too big of a problem.
- Logger.Warn(ex, "Could not update UI for the show/cachedSeries/movie information pane");
- }
- catch (Exception ex)
- {
- //Fail gracefully - no RHS episode guide is not too big of a problem.
- Logger.Error(ex);
- }
- web.Update();
- }
-
- public static void SetHtmlBody(ChromiumWebBrowser web, string body)
- {
- SetWeb(web,
- () =>
- {
- web.Load("data:text/html;base64," + Convert.ToBase64String(Encoding.UTF8.GetBytes(body)));
- });
- }
-
- private static void SetHtmlEmbed(ChromiumWebBrowser web, string? link)
- {
- SetWeb(web,
- () =>
- {
- web.Load(link ?? string.Empty);
- });
- }
-
public static void TvSourceFor(ProcessedEpisode? e)
{
if (e?.WebsiteUrl != null && e.WebsiteUrl.HasValue())
@@ -1683,8 +1757,7 @@ private ListViewItem GenerateLvi(DirFilesCache dfc, ProcessedEpisode pe)
private void lvWhenToWatch_ColumnClick(object sender, ColumnClickEventArgs e)
{
- int col = e.Column;
- SortSchedule(col);
+ SortSchedule(e.Column);
}
private void SortSchedule(int col)
@@ -3290,22 +3363,23 @@ private void FillMovieGuideHtml(MovieConfiguration? si)
if (TVSettings.Instance.OfflineMode || TVSettings.Instance.ShowBasicShowDetails)
{
- SetHtmlBody(chrMovieInformation, ShowHtmlHelper.CreateOldPage(si.GetMovieHtmlOverviewOffline()));
- SetHtmlBody(chrMovieImages, ShowHtmlHelper.CreateOldPage(si.GetMovieImagesHtmlOverview()));
- SetHtmlBody(chrMovieTrailer, ShowHtmlHelper.CreateOldPage("Not available offline"));
+ chrMovieInformation.SetSimpleHtmlBody(si.GetMovieHtmlOverviewOffline());
+ chrMovieImages.SetSimpleHtmlBody(si.GetMovieImagesHtmlOverview());
+ chrMovieTrailer.SetSimpleHtmlBody("Not available offline");
return;
}
- //SetHtmlBody(chrMovieImages, ShowHtmlHelper.CreateOldPage(si.GetMovieImagesHtmlOverview()));
- SetHtmlBody(chrMovieImages, si.GetMovieImagesOverview());
- SetHtmlBody(chrMovieInformation, si.GetMovieHtmlOverview(false));
+
+ chrMovieImages.SetHtmlBody(si.GetMovieImagesOverview());
+ chrMovieInformation.SetHtmlBody(si.GetMovieHtmlOverview(false));
+
if (si.CachedMovie?.TrailerUrl?.HasValue() ?? false)
{
// ReSharper disable once AssignNullToNotNullAttribute
- SetHtmlEmbed(chrMovieTrailer, ShowHtmlHelper.YoutubeTrailer(si.CachedMovie));
+ chrMovieTrailer.SetHtmlEmbed(ShowHtmlHelper.YoutubeTrailer(si.CachedMovie));
}
else
{
- SetHtmlBody(chrMovieTrailer, ShowHtmlHelper.CreateOldPage("Not available for this Movie"));
+ chrMovieTrailer.SetSimpleHtmlBody("Not available for this Movie");
}
ResetRunBackGroundWorker(bwMovieHTMLGenerator, si);
@@ -3682,7 +3756,7 @@ private void AskUserAboutShowProblems(bool unattended)
{
string message = mDoc.ShowProblems.Count() > 1
? $"Shows with Id {mDoc.ShowProblems.Select(exception => exception.Media.ToString()).ToCsv()} are not found on TVDB, TMDB and TVMaze. Please update them"
- : $"Show with {StringFor(mDoc.ShowProblems.First().ShowIdProvider)} Id {mDoc.ShowProblems.First().Media.IdFor(mDoc.ShowProblems.First().Media.Provider)} is not found on {StringFor(mDoc.ShowProblems.First().ErrorProvider)}. Please Update";
+ : $"Show with {mDoc.ShowProblems.First().ShowIdProvider.PrettyPrint()} Id {mDoc.ShowProblems.First().Media.IdFor(mDoc.ShowProblems.First().Media.Provider)} is not found on {(mDoc.ShowProblems.First().ErrorProvider.PrettyPrint())}. Please Update";
DialogResult result = MessageBox.Show(message, "Series/Show No Longer Found", MessageBoxButtons.OKCancel,
MessageBoxIcon.Error);
@@ -3714,7 +3788,7 @@ private void AskUserAboutShowProblems(bool unattended)
{
string message = mDoc.MovieProblems.Count() > 1
? $"Movies with Id {string.Join(",", mDoc.MovieProblems.Select(exception => exception.Media.ToString()))} are not found on TVDB, TMDB and TVMaze. Please update them"
- : $"Movie with {StringFor(mDoc.MovieProblems.First().ShowIdProvider)} Id {mDoc.MovieProblems.First().Media} is not found on {StringFor(mDoc.MovieProblems.First().ErrorProvider)}. Please Update";
+ : $"Movie with {(mDoc.MovieProblems.First().ShowIdProvider.PrettyPrint())} Id {mDoc.MovieProblems.First().Media} is not found on {(mDoc.MovieProblems.First().ErrorProvider.PrettyPrint())}. Please Update";
DialogResult result = MessageBox.Show(message, "Movie No Longer Found", MessageBoxButtons.OKCancel,
MessageBoxIcon.Error);
@@ -3743,18 +3817,6 @@ private void AskUserAboutShowProblems(bool unattended)
mDoc.ClearCacheUpdateProblems();
}
- private static string StringFor(TVDoc.ProviderType i)
- {
- return i switch
- {
- TVDoc.ProviderType.TVmaze => "TV Maze",
- TVDoc.ProviderType.TMDB => "TMDB",
- TVDoc.ProviderType.TheTVDB => "The TVDB",
- TVDoc.ProviderType.libraryDefault => throw new ArgumentOutOfRangeException(nameof(i), i, null),
- _ => throw new ArgumentOutOfRangeException(nameof(i), i, null)
- };
- }
-
private static object ActionImageGetter(object rowObject)
{
Item s = (Item)rowObject;
@@ -4618,7 +4680,7 @@ private void UpdateWeb(object sender, RunWorkerCompletedEventArgs e)
{
if (UiHasContextFor(result.Argument))
{
- SetHtmlBody(result.Web, result.Html);
+ result.Web.SetHtmlBody(result.Html);
}
}
}
@@ -4789,64 +4851,6 @@ private void BtnRevertView_Click(object sender, EventArgs e)
DefaultOlvView();
}
- private void DefaultOlvView()
- {
- olvAction.BeginUpdate();
- olvAction.ShowGroups = true;
- olvAction.AlwaysGroupByColumn = null;
- olvAction.CustomSorter = delegate { olvAction.ListViewItemSorter = new ListViewActionItemSorter(); };
- olvAction.Sort(olvType, SortOrder.Ascending);
- olvAction.BuildGroups(olvType, SortOrder.Ascending, olvShowColumn, SortOrder.Ascending, olvSeason, SortOrder.Ascending);
- //olvAction.Sort();
- //olvAction.BuildGroups(olvType,SortOrder.Ascending);//(olvType, SortOrder.Ascending,olvShowColumn,SortOrder.Ascending,olvSeason,SortOrder.Ascending);
- olvAction.ResetColumnFiltering();
- olvAction.EndUpdate();
- }
-
- private void OlvAction_Dropped(object sender, OlvDropEventArgs e)
- {
- // Get a list of filenames being dragged
- string[] files = (string[])((DataObject)e.DataObject).GetData(DataFormats.FileDrop, false);
-
- // Establish item in list being dragged to, and exit if no item matched
- // Check at least one file was being dragged, and that dragged-to item is a "Missing Item" item.
- if (files.Length <= 0 || e.DropTargetItem.RowObject is not ItemMissing mi)
- {
- return;
- }
-
- // Only want the first file if multiple files were dragged across.
- ManuallyAddFileForItem(mi, files[0]);
- }
-
- private void OlvAction_CanDrop(object sender, OlvDropEventArgs e)
- {
- if (e.DropSink?.DropTargetItem?.RowObject is not Item item)
- {
- e.Effect = DragDropEffects.None;
- }
- else
- {
- if (item is ItemMissing)
- {
- if (((DataObject)e.DataObject).GetDataPresent(DataFormats.FileDrop))
- {
- e.Effect = DragDropEffects.All;
- }
- else
- {
- e.Effect = DragDropEffects.None;
- e.InfoMessage = "Can only drag files onto a missing episode";
- }
- }
- else
- {
- e.Effect = DragDropEffects.None;
- e.InfoMessage = "Can only drag onto a missing episode";
- }
- }
- }
-
private void BwShowSummaryHTMLGenerator_DoWork(object sender, DoWorkEventArgs e)
{
Thread.CurrentThread.Name ??= "Show Summary HTML Creation Thread"; // Can only set it once
@@ -4975,42 +4979,6 @@ private void tsbScheduleJackettSearch_Click(object sender, EventArgs e)
}
}
- private void olvAction_BeforeCreatingGroups(object sender, CreateGroupsEventArgs e)
- {
- e.Parameters.ItemComparer = GetActionComparer(e.Parameters.GroupByColumn);
-
- if (e.Parameters.PrimarySort == olvDate)
- {
- e.Parameters.PrimarySort = new OLVColumn("RawDate",olvDate.AspectName);
- }
-
- if (e.Parameters.PrimarySort == olvEpisode)
- {
- e.Parameters.PrimarySort = new OLVColumn("RawEp", olvEpisode.AspectName);
- e.Parameters.GroupComparer = new SeasonGroupComparer(e.Parameters.GroupByOrder);
- }
-
- if (e.Parameters.PrimarySort == olvSeason || e.Parameters.PrimarySort.AspectName == "SeasonNumberAsInt")
- {
- e.Parameters.PrimarySort = new OLVColumn("RawSe", "SeasonNumberAsInt");
- e.Parameters.GroupComparer = new SeasonGroupComparer(e.Parameters.GroupByOrder);
- }
-
- e.Parameters.SecondarySort = new OLVColumn("key", "OrderKey");
- e.Parameters.SecondarySortOrder = SortOrder.Ascending;
- }
-
- private static IComparer GetActionComparer(OLVColumn column)
- {
- return column.Index switch
- {
- 1 => new NumberAsTextActionComparer(column.Index),
- 2 => new NumberAsTextActionComparer(column.Index),
- 3 => new DateActionComparer(column.Index),
- _ => new TextActionComparer(column.Index)
- };
- }
-
public void ShowFgDownloadProgress(CacheUpdater cu, CancellationTokenSource cts)
{
if (!IsDisposed)
@@ -5327,36 +5295,6 @@ private void PartialScan(PostScanActivity activity)
FocusOnScanResults();
}
- private void olvAction_ColumnClick(object sender, ColumnClickEventArgs e)
- {
- if (!olvAction.AllColumns[e.Column].Groupable && olvAction.AllColumns[e.Column].Sortable)
- {
- //TODO work out how to deal with this
- }
- }
-
- private void olvAction_BeforeSorting(object sender, BeforeSortingEventArgs e)
- {
- if (e.ColumnToSort == olvDate)
- {
- e.ColumnToSort = new OLVColumn("RawDate", "AirDate");
- }
-
- if (e.ColumnToSort == olvEpisode)
- {
- e.ColumnToSort = new OLVColumn("RawEp", "EpisodeString");
- }
-
- if (e.ColumnToSort == olvSeason)
- {
- e.ColumnToSort = new OLVColumn("RawSe", "SeasonNumberAsInt");
- }
-
- e.SecondaryColumnToSort = new OLVColumn("AbsoluteOrder", "OrderKey");
- e.SecondarySortOrder = SortOrder.Ascending;
- olvAction.ShowSortIndicator();
- }
-
private void tVDBUPdateCheckerLogToolStripMenuItem_Click(object sender, EventArgs e)
{
TvdbUpdateChecker form = new(mDoc);
@@ -5457,61 +5395,74 @@ private void removeShowsWithNoFoldersToolStripMenuItem_Click(object sender, Even
}
}
-///
-/// This comparer sort list view specifically for sesaons so that they appear in the season order
-/// OLVGroups have a "SortValue" property,
-/// which is used if present. Otherwise, the titles of the groups will be compared.
-///
-public class SeasonGroupComparer : IComparer
+public static class TvWebExtensions
{
- ///
- /// Create a group comparer
- ///
- /// The ordering for column values
- public SeasonGroupComparer(SortOrder order)
+ private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
+ public static void UpdateTvTrailer(this ChromiumWebBrowser web, ShowConfiguration? si)
{
- sortOrder = order;
+ if (si?.CachedShow?.TrailerUrl?.HasValue() ?? false)
+ {
+ // ReSharper disable once AssignNullToNotNullAttribute
+ SetHtmlEmbed(web, ShowHtmlHelper.YoutubeTrailer(si.CachedShow!));
+ }
+ else
+ {
+ SetHtmlBody(web, ShowHtmlHelper.CreateOldPage("Not available for this TV show"));
+ }
}
- ///
- /// Compare the two groups. OLVGroups have a "SortValue" property,
- /// which is used if present. Otherwise, the titles of the groups will be compared.
- ///
- /// group1
- /// group2
- /// An ordering indication: -1, 0, 1
- public int Compare(OLVGroup? x, OLVGroup? y)
+ private static void SetWeb(this ChromiumWebBrowser web, System.Action a)
{
- if (x is null || y is null)
+ web.Visible = true;
+ if (web.IsDisposed)
{
- return 0;
+ return;
}
- // If we can compare the sort values, do that.
- // Otherwise do a case insensitive compare on the group header.
- int result;
- if (x.Items.Any() && y.Items.Any())
+ if (!web.IsBrowserInitialized)
{
- result = CompareValue(x).CompareTo(CompareValue(y));
+ web.IsBrowserInitializedChanged += (_, _) =>
+ {
+ web.BeginInvoke((MethodInvoker)delegate { SetWeb(web, a); });
+ };
}
- else if (x.SortValue != null && y.SortValue != null)
+
+ try
{
- result = x.SortValue.CompareTo(y.SortValue);
+ a();
}
- else
+ catch (COMException ex)
{
- result = string.Compare(x.Header, y.Header, StringComparison.CurrentCultureIgnoreCase);
+ //Fail gracefully - no RHS episode guide is not too big of a problem.
+ Logger.Warn(ex, "Could not update UI for the show/cachedSeries/movie information pane");
}
-
- if (sortOrder == SortOrder.Descending)
+ catch (Exception ex)
{
- return 0 - result;
+ //Fail gracefully - no RHS episode guide is not too big of a problem.
+ Logger.Error(ex);
}
-
- return result;
+ web.Update();
}
- private static int CompareValue(OLVGroup x) => ((Item)x.Items.First().RowObject).SeasonNumberAsInt ?? 0;
+ public static void SetSimpleHtmlBody(this ChromiumWebBrowser web, string message)
+ {
+ web.SetHtmlBody(ShowHtmlHelper.CreateOldPage(message));
+ }
+ public static void SetHtmlBody(this ChromiumWebBrowser web, string body)
+ {
+ SetHtml(web,"data:text/html;base64," + Convert.ToBase64String(Encoding.UTF8.GetBytes(body)));
+ }
+ internal static void SetHtmlEmbed(this ChromiumWebBrowser web, string? link)
+ {
+ SetHtml(web,link ?? string.Empty);
+ }
- private readonly SortOrder sortOrder;
+ private static void SetHtml(this ChromiumWebBrowser web, string value)
+ {
+ SetWeb(web,
+ () =>
+ {
+ web.Load(value);
+ });
+ }
}
diff --git a/TVRename/ItemsAndActions/ActionItemSorter.cs b/TVRename/ItemsAndActions/ActionItemSorter.cs
index 80babfde..a0a93a74 100644
--- a/TVRename/ItemsAndActions/ActionItemSorter.cs
+++ b/TVRename/ItemsAndActions/ActionItemSorter.cs
@@ -10,10 +10,8 @@
namespace TVRename;
-public class ActionItemSorter : System.Collections.Generic.IComparer-
+public abstract class ActionItemSorter : System.Collections.Generic.IComparer
-
{
- #region IComparer
- Members
-
public int Compare(Item? x, Item? y)
{
if (x is null)
@@ -26,9 +24,18 @@ public int Compare(Item? x, Item? y)
return 1;
}
- return TypeNumber(x) == TypeNumber(y) ? x.CompareTo(y) : TypeNumber(x) - TypeNumber(y);
+ return CompareItems(x,y);
}
+ protected abstract int CompareItems(Item item, Item item1);
+}
+public class DefaultActionItemSorter:ActionItemSorter
+{
+ #region IComparer
- Members
+
+ protected override int CompareItems(Item x, Item y)
+ => TypeNumber(x) == TypeNumber(y) ? x.CompareTo(y) : TypeNumber(x) - TypeNumber(y);
+
#endregion IComparer
- Members
private static int TypeNumber(Item a)
@@ -62,3 +69,43 @@ private static int TypeNumber(Item a)
};
}
}
+
+public abstract class ActionItemStringSorter : ActionItemSorter
+{
+ protected override int CompareItems(Item x, Item y) => string.Compare(GetString(x),GetString(y),StringComparison.CurrentCultureIgnoreCase);
+
+ protected abstract string GetString(Item x);
+}
+
+public class ActionItemNameSorter : ActionItemStringSorter
+{
+ protected override string GetString(Item x) => x.SeriesName;
+}
+public class ActionItemDateSorter : ActionItemSorter
+{
+ protected override int CompareItems(Item x, Item y) => DateTime.Compare(x.AirDate ?? DateTime.MinValue,y.AirDate ?? DateTime.MinValue);
+}
+public class ActionItemFilenameSorter : ActionItemStringSorter
+{
+ protected override string GetString(Item x) => x.DestinationFile ?? string.Empty;
+}
+public class ActionItemFolderSorter : ActionItemStringSorter
+{
+ protected override string GetString(Item x) => x.DestinationFolder ?? string.Empty;
+}
+public class ActionItemSourceSorter : ActionItemStringSorter
+{
+ protected override string GetString(Item x) => x.SourceDetails;
+}
+public class ActionItemErrorsSorter : ActionItemStringSorter
+{
+ protected override string GetString(Item x) =>x.ErrorText ?? string.Empty;
+}
+public class ActionItemSeasonSorter : ActionItemSorter
+{
+ protected override int CompareItems(Item x, Item y) => x.SeasonNumberAsInt ?? 0 - y.SeasonNumberAsInt ?? 0;
+}
+public class ActionItemEpisodeSorter : ActionItemSorter
+{
+ protected override int CompareItems(Item x, Item y) => x.EpisodeNumber ?? 0 - y.EpisodeNumber ?? 0 ;
+}
diff --git a/TVRename/ScanActivity/Finders/FileFinder.cs b/TVRename/ScanActivity/Finders/FileFinder.cs
index b6f13e04..1882f126 100644
--- a/TVRename/ScanActivity/Finders/FileFinder.cs
+++ b/TVRename/ScanActivity/Finders/FileFinder.cs
@@ -513,7 +513,7 @@ protected static void ReorganiseToLeaveOriginals(ItemList newList)
// ideally do that move within same filesystem
// sort based on source file, and destination drive, putting last if destdrive == sourcedrive
- newList.Sort(new ActionItemSorter());
+ newList.Sort(new DefaultActionItemSorter());
// sort puts all the CopyMoveRenames together
// then set the last of each source file to be a move
diff --git a/TVRename/Sources/CacheHelper.cs b/TVRename/Sources/CacheHelper.cs
index a8b0ed97..6d68fad0 100644
--- a/TVRename/Sources/CacheHelper.cs
+++ b/TVRename/Sources/CacheHelper.cs
@@ -291,14 +291,12 @@ public static Dictionary GetMoviesDictMatching(this T c
{
cache.Search(hint, showErrorMsgBox, MediaConfiguration.MediaType.movie, preferredLocale);
- string showName = hint;
-
- if (string.IsNullOrEmpty(showName))
+ if (string.IsNullOrEmpty(hint))
{
return null;
}
- showName = showName.ToLower();
+ string showName = hint.ToLower();
List matchingShows = cache.GetMoviesDictMatching(showName).Values.ToList();
diff --git a/TVRename/TVRename/TVDoc.cs b/TVRename/TVRename/TVDoc.cs
index ba325143..b7bc311e 100644
--- a/TVRename/TVRename/TVDoc.cs
+++ b/TVRename/TVRename/TVDoc.cs
@@ -932,7 +932,7 @@ public void Scan(ScanSettings settings)
}
// sort Action list by type
- TheActionList.Sort(new ActionItemSorter()); // was new ActionSorter()
+ TheActionList.Sort(new DefaultActionItemSorter()); // was new ActionSorter()
Stats().FindAndOrganisesDone++;
diff --git a/TVRename/Utility/Sorters/NumberAsTextSorter.cs b/TVRename/Utility/Sorters/NumberAsTextSorter.cs
index b2a4a3ed..ab10de60 100644
--- a/TVRename/Utility/Sorters/NumberAsTextSorter.cs
+++ b/TVRename/Utility/Sorters/NumberAsTextSorter.cs
@@ -39,7 +39,7 @@ private int ParseAsInt(ListViewItem cellItem)
}
catch
{
- return 0;
+ return -1;
}
}
}