mirror of
https://github.com/PredatH0r/ChanSort.git
synced 2026-05-07 21:07:13 +02:00
- unified handling for deleting channels (action based on file format support either mark-as-deleted, remove-from-file, append-at-end)
- added unit tests - internal code cleanup
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
@@ -10,7 +10,7 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>ChanSort.Api</RootNamespace>
|
||||
<AssemblyName>ChanSort.Api</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile>
|
||||
</TargetFrameworkProfile>
|
||||
@@ -23,6 +23,7 @@
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
@@ -31,6 +32,7 @@
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@@ -40,19 +42,23 @@
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
<OutputPath>..\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.IO.Compression.FileSystem" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Data" />
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace ChanSort.Api
|
||||
{
|
||||
/// <summary>
|
||||
/// Reads a reference list from a .csv file with the format
|
||||
/// [dummy1],ProgramNr,[dummy2],UID,ChannelName[,SignalSource,FavAndFlags]
|
||||
/// [obsolete],ProgramNr,[obsolete],UID,ChannelName[,SignalSource,FavAndFlags]
|
||||
/// </summary>
|
||||
public class CsvRefListSerializer : SerializerBase
|
||||
{
|
||||
@@ -31,17 +31,15 @@ namespace ChanSort.Api
|
||||
{
|
||||
this.Features.ChannelNameEdit = ChannelNameEditMode.All;
|
||||
this.Features.CanSkipChannels = true;
|
||||
this.Features.CanDeleteChannels = true;
|
||||
this.Features.DeleteMode = DeleteMode.FlagWithoutPrNr;
|
||||
this.Features.CanHaveGaps = true;
|
||||
this.Features.EncryptedFlagEdit = false;
|
||||
this.DataRoot.SortedFavorites = false;
|
||||
this.DataRoot.SupportedFavorites = Favorites.A | Favorites.B | Favorites.C | Favorites.D | Favorites.E;
|
||||
this.Features.SortedFavorites = false;
|
||||
this.Features.SupportedFavorites = Favorites.A | Favorites.B | Favorites.C | Favorites.D | Favorites.E | Favorites.F | Favorites.G | Favorites.H;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public override string DisplayName => "ChanSort .csv Reference List Loader";
|
||||
|
||||
#region Load()
|
||||
|
||||
public override void Load()
|
||||
@@ -211,6 +209,8 @@ namespace ChanSort.Api
|
||||
channel.Lock = false;
|
||||
channel.Skip = false;
|
||||
channel.Hidden = false;
|
||||
channel.IsDeleted = false;
|
||||
channel.Favorites = 0;
|
||||
|
||||
foreach (var c in flags)
|
||||
{
|
||||
@@ -251,6 +251,7 @@ namespace ChanSort.Api
|
||||
break;
|
||||
case 'D':
|
||||
channel.IsDeleted = true;
|
||||
channel.NewProgramNr = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -318,7 +319,7 @@ namespace ChanSort.Api
|
||||
}
|
||||
}
|
||||
|
||||
public static void Save(TextWriter stream, DataRoot dataRoot)
|
||||
public static void Save(TextWriter stream, DataRoot dataRoot, bool includeDeletedChannels = true)
|
||||
{
|
||||
foreach (var channelList in dataRoot.ChannelLists)
|
||||
{
|
||||
@@ -327,8 +328,9 @@ namespace ChanSort.Api
|
||||
|
||||
foreach (var channel in channelList.GetChannelsByNewOrder())
|
||||
{
|
||||
if (channel.NewProgramNr == -1)
|
||||
if (channel.NewProgramNr == -1 && !includeDeletedChannels)
|
||||
continue;
|
||||
|
||||
var line = string.Format("{0},{1},{2},{3},\"{4}\",{5},{6}",
|
||||
"", // past: channel.RecordIndex,
|
||||
channel.NewProgramNr,
|
||||
|
||||
@@ -353,28 +353,34 @@ namespace ChanSort.Api
|
||||
{
|
||||
if (list.IsMixedSourceFavoritesList)
|
||||
continue;
|
||||
|
||||
// sort the channels by assigned numbers, then unassigned by original order or alphabetically, then deleted channels
|
||||
var sortedChannels = list.Channels.OrderBy(ChanSortCriteria).ToList();
|
||||
int maxProgNr = 0;
|
||||
|
||||
foreach (var appChannel in sortedChannels)
|
||||
{
|
||||
if (appChannel.RecordIndex < 0)
|
||||
if (appChannel.IsProxy)
|
||||
continue;
|
||||
|
||||
if (appChannel.NewProgramNr == -1)
|
||||
{
|
||||
if (mode == UnsortedChannelMode.MarkDeleted)
|
||||
if (mode == UnsortedChannelMode.Delete)
|
||||
appChannel.IsDeleted = true;
|
||||
else
|
||||
else // append (hidden if possible)
|
||||
{
|
||||
appChannel.Hidden = true;
|
||||
appChannel.Skip = true;
|
||||
}
|
||||
}
|
||||
|
||||
int progNr = this.GetNewProgramNr(appChannel, ref maxProgNr);
|
||||
if (mode != UnsortedChannelMode.MarkDeleted || this.DataRoot.DeletedChannelsNeedNumbers)
|
||||
appChannel.NewProgramNr = progNr;
|
||||
// assign a valid number or 0 .... because -1 will never be a valid value for the TV
|
||||
appChannel.NewProgramNr = mode != UnsortedChannelMode.Delete || this.DataRoot.DeletedChannelsNeedNumbers ? ++maxProgNr : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (appChannel.NewProgramNr > maxProgNr)
|
||||
maxProgNr = appChannel.NewProgramNr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -384,13 +390,13 @@ namespace ChanSort.Api
|
||||
private string ChanSortCriteria(ChannelInfo channel)
|
||||
{
|
||||
// explicitly sorted
|
||||
var pos = channel.GetPosition(this.SubListIndex);
|
||||
var pos = channel.NewProgramNr;
|
||||
if (pos != -1)
|
||||
return pos.ToString("d5");
|
||||
|
||||
// eventually hide unsorted channels
|
||||
if (this.unsortedChannelMode == UnsortedChannelMode.MarkDeleted)
|
||||
return "Z";
|
||||
if (this.unsortedChannelMode == UnsortedChannelMode.Delete)
|
||||
return "Z" + channel.RecordIndex.ToString("d5");
|
||||
|
||||
// eventually append in old order
|
||||
if (this.unsortedChannelMode == UnsortedChannelMode.AppendInOrder)
|
||||
@@ -406,20 +412,6 @@ namespace ChanSort.Api
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetNewProgramNr()
|
||||
|
||||
private int GetNewProgramNr(ChannelInfo appChannel, ref int maxPrNr)
|
||||
{
|
||||
int prNr = appChannel.NewProgramNr;
|
||||
if (prNr > maxPrNr)
|
||||
maxPrNr = prNr;
|
||||
if (prNr == -1)
|
||||
prNr = ++maxPrNr;
|
||||
return prNr;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region SetFavorites()
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace ChanSort.Api
|
||||
{
|
||||
@@ -6,21 +9,34 @@ namespace ChanSort.Api
|
||||
{
|
||||
#region class SupportedFeatures
|
||||
|
||||
public enum DeleteMode
|
||||
{
|
||||
NotSupported = 0,
|
||||
Physically = 1,
|
||||
FlagWithoutPrNr = 2,
|
||||
FlagWithPrNr = 3
|
||||
}
|
||||
|
||||
public class SupportedFeatures
|
||||
{
|
||||
public ChannelNameEditMode ChannelNameEdit { get; set; }
|
||||
public bool CleanUpChannelData { get; set; }
|
||||
public bool DeviceSettings { get; set; }
|
||||
public bool CanDeleteChannels { get; set; }
|
||||
public bool CanSkipChannels { get; set; } = true;
|
||||
public bool CanHaveGaps { get; set; }
|
||||
public bool CanHaveGaps { get; set; } = true;
|
||||
public bool EncryptedFlagEdit { get; set; }
|
||||
public DeleteMode DeleteMode { get; set; } = DeleteMode.NotSupported;
|
||||
|
||||
|
||||
public Favorites SupportedFavorites { get; set; } = Favorites.A | Favorites.B | Favorites.C | Favorites.D;
|
||||
public bool SortedFavorites { get; set; }
|
||||
public bool MixedSourceFavorites { get; set; }
|
||||
public bool AllowGapsInFavNumbers { get; set; }
|
||||
|
||||
public bool CanDeleteChannelsWithFlag => this.DeleteMode == DeleteMode.FlagWithPrNr || this.DeleteMode == DeleteMode.FlagWithoutPrNr;
|
||||
public bool CanDeleteChannelsFromFile => this.DeleteMode == DeleteMode.Physically;
|
||||
public bool DeletedChannelsNeedNumbers => this.DeleteMode == DeleteMode.FlagWithPrNr;
|
||||
|
||||
public SupportedFeatures()
|
||||
{
|
||||
this.CanDeleteChannels = true;
|
||||
this.CanHaveGaps = true;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -28,17 +44,15 @@ namespace ChanSort.Api
|
||||
|
||||
public string FileName { get; set; }
|
||||
public DataRoot DataRoot { get; protected set; }
|
||||
public SupportedFeatures Features { get; private set; }
|
||||
public SupportedFeatures Features { get; } = new SupportedFeatures();
|
||||
|
||||
protected SerializerBase(string inputFile)
|
||||
{
|
||||
this.Features = new SupportedFeatures();
|
||||
this.FileName = inputFile;
|
||||
this.DataRoot = new DataRoot();
|
||||
this.defaultEncoding = Encoding.GetEncoding("iso-8859-9");
|
||||
this.DataRoot = new DataRoot(this);
|
||||
}
|
||||
|
||||
public abstract string DisplayName { get; }
|
||||
public abstract void Load();
|
||||
public abstract void Save(string tvOutputFile);
|
||||
|
||||
@@ -48,8 +62,7 @@ namespace ChanSort.Api
|
||||
set { this.defaultEncoding = value; }
|
||||
}
|
||||
|
||||
public virtual void EraseChannelData() { }
|
||||
|
||||
#region GetFileInformation()
|
||||
public virtual string GetFileInformation()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
@@ -85,9 +98,52 @@ namespace ChanSort.Api
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
#endregion
|
||||
|
||||
public virtual void ShowDeviceSettingsForm(object parentWindow) { }
|
||||
|
||||
public virtual string CleanUpChannelData() { return ""; }
|
||||
|
||||
|
||||
// common implementation helper methods
|
||||
|
||||
protected string UnzipFileToTempFolder()
|
||||
{
|
||||
var tempDir = this.FileName + ".tmp";
|
||||
|
||||
if (Directory.Exists(tempDir))
|
||||
Directory.Delete(tempDir, true);
|
||||
Directory.CreateDirectory(tempDir);
|
||||
ZipFile.ExtractToDirectory(this.FileName, tempDir);
|
||||
this.DeleteOnExit(tempDir);
|
||||
return tempDir;
|
||||
}
|
||||
|
||||
protected void ZipToOutputFile(string tvOutputFile)
|
||||
{
|
||||
var tempDir = this.FileName + ".tmp";
|
||||
File.Delete(tvOutputFile);
|
||||
ZipFile.CreateFromDirectory(tempDir, tvOutputFile);
|
||||
this.FileName = tvOutputFile;
|
||||
}
|
||||
|
||||
// TODO: replace this with a SerializerBase implementing IDisposable
|
||||
protected virtual void DeleteOnExit(string fileOrFolder)
|
||||
{
|
||||
Application.ApplicationExit += (sender, args) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(fileOrFolder))
|
||||
Directory.Delete(fileOrFolder, true);
|
||||
else if (File.Exists(fileOrFolder))
|
||||
File.Delete(fileOrFolder);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,11 +16,11 @@ namespace ChanSort.Api
|
||||
{
|
||||
this.Features.ChannelNameEdit = ChannelNameEditMode.All;
|
||||
this.Features.CanSkipChannels = false;
|
||||
this.Features.CanDeleteChannels = true;
|
||||
this.Features.DeleteMode = DeleteMode.Physically;
|
||||
this.Features.CanHaveGaps = true;
|
||||
this.Features.EncryptedFlagEdit = false;
|
||||
this.DataRoot.SortedFavorites = false;
|
||||
this.DataRoot.SupportedFavorites = 0;
|
||||
this.Features.SortedFavorites = false;
|
||||
this.Features.SupportedFavorites = 0;
|
||||
this.DataRoot.AddChannelList(this.allChannels);
|
||||
|
||||
allChannels.VisibleColumnFieldNames = new List<string>
|
||||
@@ -36,8 +36,6 @@ namespace ChanSort.Api
|
||||
|
||||
#endregion
|
||||
|
||||
public override string DisplayName => ".txt Reference List Loader";
|
||||
|
||||
#region Load()
|
||||
|
||||
public override void Load()
|
||||
|
||||
@@ -10,21 +10,31 @@ namespace ChanSort.Api
|
||||
private string uid;
|
||||
private string serviceTypeName;
|
||||
|
||||
/// <summary>
|
||||
/// List of channels that have the same UID as this channel and were not added to the channel list directly
|
||||
/// </summary>
|
||||
public readonly List<ChannelInfo> Duplicates = new List<ChannelInfo>();
|
||||
|
||||
public virtual bool IsDeleted { get; set; }
|
||||
public SignalSource SignalSource { get; set; }
|
||||
public string Source { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Index or ID of the data record
|
||||
/// </summary>
|
||||
public long RecordIndex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// logical record order (might be different from the index, like old LG TLL files with a linked list of record indices)
|
||||
/// </summary>
|
||||
public int RecordOrder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// original program number from the file, except for channels with IsDeleted==true, which will have the value -1
|
||||
/// </summary>
|
||||
public int OldProgramNr { get; set; }
|
||||
/// <summary>
|
||||
/// new program number or -1, if the channel isn't assigned a number or has IsDeleted==true
|
||||
/// </summary>
|
||||
public int NewProgramNr { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
public string ShortName { get; set; }
|
||||
public Favorites Favorites { get; set; }
|
||||
public bool Skip { get; set; }
|
||||
public bool Lock { get; set; }
|
||||
public bool Hidden { get; set; }
|
||||
@@ -39,23 +49,50 @@ namespace ChanSort.Api
|
||||
public int AudioPid { get; set; }
|
||||
public int OriginalNetworkId { get; set; }
|
||||
public int TransportStreamId { get; set; }
|
||||
public int Bouquet { get; set; }
|
||||
public string Provider { get; set; }
|
||||
public int SymbolRate { get; set; }
|
||||
public int ServiceType { get; set; }
|
||||
public string Debug { get; private set; }
|
||||
public string SatPosition { get; set; }
|
||||
public Transponder Transponder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Bitmask in which favorite lists the channel is included
|
||||
/// </summary>
|
||||
public Favorites Favorites { get; set; }
|
||||
/// <summary>
|
||||
/// current number of the channel in the various favorite lists (if individual sorting is supported)
|
||||
/// </summary>
|
||||
public List<int> FavIndex { get; }
|
||||
/// <summary>
|
||||
/// original number of the channel in the various favorite lists (if individual sorting is supported)
|
||||
/// </summary>
|
||||
public List<int> OldFavIndex { get; }
|
||||
|
||||
/// <summary>
|
||||
/// predefined LCN (logical channel number) assigned by TV firmware or cable/sat operator
|
||||
/// </summary>
|
||||
public int ProgramNrPreset { get; set; }
|
||||
|
||||
public bool IsNameModified { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A proxy channel is inserted into the current channel list when there was no match for a reference list channel
|
||||
/// </summary>
|
||||
public bool IsProxy => this.RecordIndex < 0;
|
||||
|
||||
/// <summary>
|
||||
/// arbitrary information that can be shown in a UI column to assist in analyzing a file format while coding a plugin
|
||||
/// </summary>
|
||||
public string Debug { get; private set; }
|
||||
|
||||
|
||||
|
||||
|
||||
#region ctor()
|
||||
protected ChannelInfo()
|
||||
{
|
||||
this.OldProgramNr = -1;
|
||||
this.NewProgramNr = -1;
|
||||
this.FavIndex = new List<int>(MAX_FAV_LISTS);
|
||||
this.OldFavIndex = new List<int>(MAX_FAV_LISTS);
|
||||
@@ -76,7 +113,6 @@ namespace ChanSort.Api
|
||||
this.SignalSource = source;
|
||||
this.RecordIndex = index;
|
||||
this.RecordOrder = (int)index;
|
||||
this.NewProgramNr = -1;
|
||||
this.OldProgramNr = oldProgNr;
|
||||
this.Name = name;
|
||||
this.Encrypted = null;
|
||||
@@ -99,6 +135,11 @@ namespace ChanSort.Api
|
||||
#endregion
|
||||
|
||||
#region Uid
|
||||
/// <summary>
|
||||
/// The Uid is the preferred way of matching channels between the current channel list and a reference list.
|
||||
/// The basic format of this string was taken from a command line tool "TllSort" for LG TVs but then expanded beyond that
|
||||
/// in order to support the various file formats and the data provided in those.
|
||||
/// </summary>
|
||||
public string Uid
|
||||
{
|
||||
get
|
||||
@@ -113,7 +154,7 @@ namespace ChanSort.Api
|
||||
this.uid = "S" + /*this.SatPosition + */ "-" + this.OriginalNetworkId + "-" + this.TransportStreamId + "-" + this.ServiceId;
|
||||
else if ((this.SignalSource & SignalSource.MaskAntennaCableSat) == SignalSource.Antenna || (this.SignalSource & SignalSource.MaskAntennaCableSat) == SignalSource.Cable)
|
||||
{
|
||||
// ChannelOrTransponder is needed for DVB-T where the same ONID+TSID+SID can be received from 2 different towers (on different frequencies)
|
||||
// ChannelOrTransponder is needed for DVB-T where the same ONID+TSID+SID can be received from 2 different radio transmitters, but on different frequencies/channels
|
||||
this.uid = "C-" + this.OriginalNetworkId + "-" + this.TransportStreamId + "-" + this.ServiceId + "-" + this.ChannelOrTransponder;
|
||||
}
|
||||
else
|
||||
@@ -177,23 +218,6 @@ namespace ChanSort.Api
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetFavString()
|
||||
public static string GetFavString(Favorites favorites)
|
||||
{
|
||||
string sep = "";
|
||||
string text = "";
|
||||
foreach (Favorites favMask in Enum.GetValues(typeof(Favorites)))
|
||||
{
|
||||
if ((favorites & favMask) != 0)
|
||||
{
|
||||
text += sep + favMask.ToString();
|
||||
sep = ",";
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ParseFavString()
|
||||
public static Favorites ParseFavString(string value)
|
||||
{
|
||||
@@ -246,12 +270,19 @@ namespace ChanSort.Api
|
||||
#endregion
|
||||
|
||||
#region UpdateRawData()
|
||||
/// <summary>
|
||||
/// called during the saving procedure to update the external channel list data with the changes made by the user
|
||||
/// </summary>
|
||||
public virtual void UpdateRawData()
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ChangeEncoding()
|
||||
/// <summary>
|
||||
/// for file formats that allow characters in local code pages, this method should re-parse the raw data bytes for the given encoding
|
||||
/// </summary>
|
||||
/// <param name="encoding"></param>
|
||||
public virtual void ChangeEncoding(System.Text.Encoding encoding)
|
||||
{
|
||||
}
|
||||
@@ -259,16 +290,25 @@ namespace ChanSort.Api
|
||||
|
||||
#region GetPosition(), SetPosition(), ChangePosition()
|
||||
|
||||
/// <summary>
|
||||
/// Gets the new channel number in the main channel list (index=0) or the various favorite lists (1-x)
|
||||
/// </summary>
|
||||
public int GetPosition(int subListIndex)
|
||||
{
|
||||
return subListIndex == 0 ? this.NewProgramNr : this.FavIndex[subListIndex - 1];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the original channel number in the main channel list (index=0) or the various favorite lists (1-x)
|
||||
/// </summary>
|
||||
public int GetOldPosition(int subListIndex)
|
||||
{
|
||||
return subListIndex == 0 ? this.OldProgramNr : this.OldFavIndex[subListIndex - 1];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the new channel number in the main channel list (index=0) or the various favorite lists (1-x)
|
||||
/// </summary>
|
||||
public void SetPosition(int subListIndex, int newPos)
|
||||
{
|
||||
if (subListIndex == 0)
|
||||
@@ -284,6 +324,9 @@ namespace ChanSort.Api
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the original channel number in the main channel list (index=0) or the various favorite lists (1-x)
|
||||
/// </summary>
|
||||
public void SetOldPosition(int subListIndex, int oldPos)
|
||||
{
|
||||
if (subListIndex == 0)
|
||||
@@ -292,6 +335,9 @@ namespace ChanSort.Api
|
||||
this.OldFavIndex[subListIndex - 1] = oldPos;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal helper method to adjust the main or favorite program number by a delta value
|
||||
/// </summary>
|
||||
internal void ChangePosition(int subListIndex, int delta)
|
||||
{
|
||||
if (subListIndex == 0)
|
||||
|
||||
@@ -1,41 +1,37 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
|
||||
namespace ChanSort.Api
|
||||
{
|
||||
public class DataRoot
|
||||
{
|
||||
private readonly IDictionary<int, Satellite> satellites = new Dictionary<int, Satellite>();
|
||||
private readonly IDictionary<int, Transponder> transponder = new Dictionary<int, Transponder>();
|
||||
private readonly IDictionary<int, LnbConfig> lnbConfig = new Dictionary<int, LnbConfig>();
|
||||
private readonly IList<ChannelList> channelLists = new List<ChannelList>();
|
||||
private readonly StringBuilder warnings = new StringBuilder();
|
||||
private readonly SerializerBase loader;
|
||||
|
||||
public StringBuilder Warnings { get { return this.warnings; } }
|
||||
public IDictionary<int, Satellite> Satellites { get { return this.satellites; } }
|
||||
public IDictionary<int, Transponder> Transponder { get { return this.transponder; } }
|
||||
public IDictionary<int, LnbConfig> LnbConfig { get { return this.lnbConfig; } }
|
||||
public IEnumerable<ChannelList> ChannelLists { get { return this.channelLists; } }
|
||||
public bool IsEmpty { get { return this.channelLists.Count == 0; } }
|
||||
public StringBuilder Warnings { get; } = new StringBuilder();
|
||||
public IDictionary<int, Satellite> Satellites { get; } = new Dictionary<int, Satellite>();
|
||||
public IDictionary<int, Transponder> Transponder { get; } = new Dictionary<int, Transponder>();
|
||||
public IDictionary<int, LnbConfig> LnbConfig { get; } = new Dictionary<int, LnbConfig>();
|
||||
public IEnumerable<ChannelList> ChannelLists => this.channelLists;
|
||||
public bool IsEmpty => this.channelLists.Count == 0;
|
||||
public bool NeedsSaving { get; set; }
|
||||
public Favorites SupportedFavorites { get; set; }
|
||||
public bool SortedFavorites { get; set; }
|
||||
public bool MixedSourceFavorites { get; set; }
|
||||
public bool AllowGapsInFavNumbers { get; set; }
|
||||
public bool ShowDeletedChannels { get; set; }
|
||||
|
||||
public bool DeletedChannelsNeedNumbers { get; set; }
|
||||
|
||||
public DataRoot()
|
||||
public Favorites SupportedFavorites => this.loader.Features.SupportedFavorites;
|
||||
public bool SortedFavorites => this.loader.Features.SortedFavorites;
|
||||
public bool MixedSourceFavorites => this.loader.Features.MixedSourceFavorites;
|
||||
public bool AllowGapsInFavNumbers => this.loader.Features.AllowGapsInFavNumbers;
|
||||
public bool DeletedChannelsNeedNumbers => this.loader.Features.DeletedChannelsNeedNumbers;
|
||||
|
||||
public DataRoot(SerializerBase loader)
|
||||
{
|
||||
this.SupportedFavorites = Favorites.A | Favorites.B | Favorites.C | Favorites.D;
|
||||
this.loader = loader;
|
||||
}
|
||||
|
||||
#region AddSatellite()
|
||||
public virtual void AddSatellite(Satellite satellite)
|
||||
{
|
||||
this.satellites.Add(satellite.Id, satellite);
|
||||
this.Satellites.Add(satellite.Id, satellite);
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -43,21 +39,21 @@ namespace ChanSort.Api
|
||||
public virtual void AddTransponder(Satellite sat, Transponder trans)
|
||||
{
|
||||
trans.Satellite = sat;
|
||||
if (this.transponder.ContainsKey(trans.Id))
|
||||
if (this.Transponder.ContainsKey(trans.Id))
|
||||
{
|
||||
this.warnings.AppendFormat("Duplicate transponder data record for satellite #{0} with id {1}\r\n", sat?.Id, trans.Id);
|
||||
this.Warnings.AppendFormat("Duplicate transponder data record for satellite #{0} with id {1}\r\n", sat?.Id, trans.Id);
|
||||
return;
|
||||
}
|
||||
if (sat != null)
|
||||
sat.Transponder.Add(trans.Id, trans);
|
||||
this.transponder.Add(trans.Id, trans);
|
||||
this.Transponder.Add(trans.Id, trans);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AddLnbConfig()
|
||||
public void AddLnbConfig(LnbConfig lnb)
|
||||
{
|
||||
this.lnbConfig.Add(lnb.Id, lnb);
|
||||
this.LnbConfig.Add(lnb.Id, lnb);
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -65,7 +61,7 @@ namespace ChanSort.Api
|
||||
public virtual void AddChannelList(ChannelList list)
|
||||
{
|
||||
this.channelLists.Add(list);
|
||||
this.MixedSourceFavorites |= list.IsMixedSourceFavoritesList;
|
||||
this.loader.Features.MixedSourceFavorites |= list.IsMixedSourceFavoritesList;
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -74,7 +70,7 @@ namespace ChanSort.Api
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
warnings.AppendFormat("No list found to add channel '{0}'\r\n", channel);
|
||||
this.Warnings.AppendFormat("No list found to add channel '{0}'\r\n", channel);
|
||||
return;
|
||||
}
|
||||
string warning = list.AddChannel(channel);
|
||||
@@ -105,6 +101,26 @@ namespace ChanSort.Api
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ValidateAfterLoad()
|
||||
public virtual void ValidateAfterLoad()
|
||||
{
|
||||
foreach (var list in this.ChannelLists)
|
||||
{
|
||||
if (list.IsMixedSourceFavoritesList)
|
||||
continue;
|
||||
|
||||
// make sure that deleted channels have OldProgramNr = -1
|
||||
foreach (var chan in list.Channels)
|
||||
{
|
||||
if (chan.IsDeleted)
|
||||
chan.OldProgramNr = -1;
|
||||
else if (chan.OldProgramNr < 0) // old versions of ChanSort saved -1 and without setting IsDeleted
|
||||
chan.IsDeleted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ApplyCurrentProgramNumbers()
|
||||
public void ApplyCurrentProgramNumbers()
|
||||
{
|
||||
@@ -120,35 +136,37 @@ namespace ChanSort.Api
|
||||
foreach (var channel in list.Channels)
|
||||
{
|
||||
for (int i = 0; i <= c; i++)
|
||||
channel.SetPosition(i, channel.IsDeleted && !this.DeletedChannelsNeedNumbers ? -1 : channel.GetOldPosition(i));
|
||||
channel.SetPosition(i, channel.GetOldPosition(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SetPrNrForDeletedChannels()
|
||||
public void SetPrNrForDeletedChannels()
|
||||
#region ValidateAfterSave()
|
||||
public virtual void ValidateAfterSave()
|
||||
{
|
||||
if (this.DeletedChannelsNeedNumbers)
|
||||
return;
|
||||
|
||||
// make sure that deleted channels have OldProgramNr = -1
|
||||
// set old numbers to match the new numbers
|
||||
// also make sure that deleted channels are either removed from the list or assigned the -1 prNr, depending on the loader's DeleteMode
|
||||
foreach (var list in this.ChannelLists)
|
||||
{
|
||||
if (list.IsMixedSourceFavoritesList)
|
||||
continue;
|
||||
foreach (var chan in list.Channels)
|
||||
for (int i = 0; i < list.Channels.Count; i++)
|
||||
{
|
||||
var chan = list.Channels[i];
|
||||
if (chan.IsDeleted)
|
||||
{
|
||||
chan.NewProgramNr = -1;
|
||||
chan.OldProgramNr = -1;
|
||||
if (this.loader.Features.DeleteMode == SerializerBase.DeleteMode.Physically)
|
||||
list.Channels.RemoveAt(i--);
|
||||
else
|
||||
chan.NewProgramNr = -1;
|
||||
}
|
||||
else if (chan.OldProgramNr == -1) // old versions of ChanSort saved -1 and without setting IsDeleted
|
||||
chan.IsDeleted = true;
|
||||
|
||||
chan.OldProgramNr = chan.NewProgramNr;
|
||||
chan.OldFavIndex.Clear();
|
||||
chan.OldFavIndex.AddRange(chan.FavIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace ChanSort.Api
|
||||
{
|
||||
AppendInOrder=0,
|
||||
AppendAlphabetically=1,
|
||||
MarkDeleted=2
|
||||
Delete=2
|
||||
}
|
||||
|
||||
[Flags]
|
||||
|
||||
2
source/ChanSort.Api/Resources.Designer.cs
generated
2
source/ChanSort.Api/Resources.Designer.cs
generated
@@ -19,7 +19,7 @@ namespace ChanSort.Api {
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
Reference in New Issue
Block a user